summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-format56
-rw-r--r--.github/workflows/build.yaml111
-rw-r--r--.github/workflows/monkey-test.yaml69
-rw-r--r--.github/workflows/static-analysis.yaml65
-rw-r--r--.gitignore15
-rw-r--r--Makefile611
-rw-r--r--Makefile.config.example16
-rw-r--r--Makefile.defaults60
-rw-r--r--Makefile.macros249
-rw-r--r--Makefile.tools118
-rw-r--r--README40
-rw-r--r--README.md27
-rw-r--r--content/Makefile18
-rw-r--r--content/content.c877
-rw-r--r--content/content.h408
-rw-r--r--content/content_factory.c5
-rw-r--r--content/content_factory.h5
-rw-r--r--content/content_protected.h453
-rw-r--r--content/fetch.c136
-rw-r--r--content/fetch.h102
-rw-r--r--content/fetchers/Makefile13
-rw-r--r--content/fetchers/about.c862
-rw-r--r--content/fetchers/about/Makefile20
-rw-r--r--content/fetchers/about/about.c758
-rw-r--r--content/fetchers/about/about.h (renamed from content/fetchers/about.h)9
-rw-r--r--content/fetchers/about/atestament.h35
-rw-r--r--content/fetchers/about/blank.c60
-rw-r--r--content/fetchers/about/blank.h35
-rw-r--r--content/fetchers/about/certificate.c1291
-rw-r--r--content/fetchers/about/certificate.h35
-rw-r--r--content/fetchers/about/chart.c630
-rw-r--r--content/fetchers/about/chart.h37
-rw-r--r--content/fetchers/about/choices.c93
-rw-r--r--content/fetchers/about/choices.h35
-rw-r--r--content/fetchers/about/config.c133
-rw-r--r--content/fetchers/about/config.h35
-rw-r--r--content/fetchers/about/imagecache.c188
-rw-r--r--content/fetchers/about/imagecache.h37
-rw-r--r--content/fetchers/about/nscolours.c81
-rw-r--r--content/fetchers/about/nscolours.h35
-rw-r--r--content/fetchers/about/private.h77
-rw-r--r--content/fetchers/about/query.c60
-rw-r--r--content/fetchers/about/query.h36
-rw-r--r--content/fetchers/about/query_auth.c246
-rw-r--r--content/fetchers/about/query_auth.h35
-rw-r--r--content/fetchers/about/query_fetcherror.c158
-rw-r--r--content/fetchers/about/query_fetcherror.h35
-rw-r--r--content/fetchers/about/query_privacy.c174
-rw-r--r--content/fetchers/about/query_privacy.h35
-rw-r--r--content/fetchers/about/query_timeout.c158
-rw-r--r--content/fetchers/about/query_timeout.h35
-rw-r--r--content/fetchers/about/testament.c129
-rw-r--r--content/fetchers/curl.c1259
-rw-r--r--content/fetchers/data.c132
-rw-r--r--content/fetchers/file/Makefile3
-rw-r--r--content/fetchers/file/dirlist.c (renamed from content/dirlist.c)45
-rw-r--r--content/fetchers/file/dirlist.h (renamed from content/dirlist.h)9
-rw-r--r--content/fetchers/file/file.c (renamed from content/fetchers/file.c)80
-rw-r--r--content/fetchers/file/file.h (renamed from content/fetchers/file.h)0
-rw-r--r--content/fetchers/resource.c77
-rw-r--r--content/fs_backing_store.c680
-rw-r--r--content/handlers/Makefile11
-rw-r--r--content/handlers/css/Makefile2
-rw-r--r--content/handlers/css/css.c43
-rw-r--r--content/handlers/css/css.h1
-rw-r--r--content/handlers/css/dump.c37
-rw-r--r--content/handlers/css/hints.c240
-rw-r--r--content/handlers/css/select.c158
-rw-r--r--content/handlers/css/select.h5
-rw-r--r--content/handlers/css/utils.c255
-rw-r--r--content/handlers/css/utils.h76
-rw-r--r--content/handlers/html/Makefile25
-rw-r--r--content/handlers/html/box.h457
-rw-r--r--content/handlers/html/box_construct.c1450
-rw-r--r--content/handlers/html/box_construct.h113
-rw-r--r--content/handlers/html/box_inspect.c898
-rw-r--r--content/handlers/html/box_inspect.h155
-rw-r--r--content/handlers/html/box_manipulate.c352
-rw-r--r--content/handlers/html/box_manipulate.h106
-rw-r--r--content/handlers/html/box_normalise.c (renamed from render/box_normalise.c)986
-rw-r--r--content/handlers/html/box_normalise.h66
-rw-r--r--content/handlers/html/box_special.c1935
-rw-r--r--content/handlers/html/box_special.h (renamed from render/table.h)27
-rw-r--r--content/handlers/html/box_textarea.c (renamed from render/box_textarea.c)109
-rw-r--r--content/handlers/html/box_textarea.h (renamed from render/box_textarea.h)21
-rw-r--r--content/handlers/html/css.c (renamed from render/html_css.c)99
-rw-r--r--content/handlers/html/css.h109
-rw-r--r--content/handlers/html/css_fetcher.c (renamed from render/html_css_fetcher.c)53
-rw-r--r--content/handlers/html/dom_event.c789
-rw-r--r--content/handlers/html/dom_event.h43
-rw-r--r--content/handlers/html/font.c (renamed from render/font.c)24
-rw-r--r--content/handlers/html/font.h (renamed from render/font.h)17
-rw-r--r--content/handlers/html/form.c2361
-rw-r--r--content/handlers/html/form_internal.h (renamed from render/form_internal.h)159
-rw-r--r--content/handlers/html/forms.c (renamed from render/html_forms.c)29
-rw-r--r--content/handlers/html/html.c (renamed from render/html.c)1313
-rw-r--r--content/handlers/html/html.h (renamed from render/html.h)96
-rw-r--r--content/handlers/html/html_save.h46
-rw-r--r--content/handlers/html/imagemap.c (renamed from render/imagemap.c)32
-rw-r--r--content/handlers/html/imagemap.h (renamed from render/imagemap.h)9
-rw-r--r--content/handlers/html/interaction.c1816
-rw-r--r--content/handlers/html/interaction.h125
-rw-r--r--content/handlers/html/layout.c (renamed from render/layout.c)1556
-rw-r--r--content/handlers/html/layout.h (renamed from render/layout.h)6
-rw-r--r--content/handlers/html/layout_flex.c1117
-rw-r--r--content/handlers/html/layout_internal.h738
-rw-r--r--content/handlers/html/object.c (renamed from render/html_object.c)242
-rw-r--r--content/handlers/html/object.h86
-rw-r--r--content/handlers/html/private.h (renamed from render/html_internal.h)255
-rw-r--r--content/handlers/html/redraw.c (renamed from render/html_redraw.c)234
-rw-r--r--content/handlers/html/redraw_border.c (renamed from render/html_redraw_border.c)15
-rw-r--r--content/handlers/html/script.c (renamed from render/html_script.c)188
-rw-r--r--content/handlers/html/table.c (renamed from render/table.c)1256
-rw-r--r--content/handlers/html/table.h56
-rw-r--r--content/handlers/html/textselection.c547
-rw-r--r--content/handlers/html/textselection.h43
-rw-r--r--content/handlers/image/Makefile7
-rw-r--r--content/handlers/image/bmp.c46
-rw-r--r--content/handlers/image/bmp.h13
-rw-r--r--content/handlers/image/gif.c412
-rw-r--r--content/handlers/image/ico.c88
-rw-r--r--content/handlers/image/image.c17
-rw-r--r--content/handlers/image/image_cache.c37
-rw-r--r--content/handlers/image/image_cache.h6
-rw-r--r--content/handlers/image/jpeg.c208
-rw-r--r--content/handlers/image/jpegxl.c340
-rw-r--r--content/handlers/image/jpegxl.h (renamed from frontends/atari/login.h)12
-rw-r--r--content/handlers/image/nssprite.c47
-rw-r--r--content/handlers/image/png.c74
-rw-r--r--content/handlers/image/rsvg.c77
-rw-r--r--content/handlers/image/rsvg246.c280
-rw-r--r--content/handlers/image/svg.c34
-rw-r--r--content/handlers/image/webp.c260
-rw-r--r--content/handlers/image/webp.h (renamed from frontends/atari/verify_ssl.h)13
-rw-r--r--content/handlers/javascript/content.c7
-rw-r--r--content/handlers/javascript/duktape/CSSRule.bnd22
-rw-r--r--content/handlers/javascript/duktape/CSSStyleSheet.bnd22
-rw-r--r--content/handlers/javascript/duktape/CanvasRenderingContext2D.bnd603
-rw-r--r--content/handlers/javascript/duktape/Console.bnd52
-rw-r--r--content/handlers/javascript/duktape/DOMImplementation.bnd120
-rw-r--r--content/handlers/javascript/duktape/DOMSettableTokenList.bnd44
-rw-r--r--content/handlers/javascript/duktape/DOMTokenList.bnd163
-rw-r--r--content/handlers/javascript/duktape/Document.bnd144
-rw-r--r--content/handlers/javascript/duktape/Element.bnd196
-rw-r--r--content/handlers/javascript/duktape/Event.bnd41
-rw-r--r--content/handlers/javascript/duktape/HTMLBodyElement.bnd33
-rw-r--r--content/handlers/javascript/duktape/HTMLCanvasElement.bnd47
-rw-r--r--content/handlers/javascript/duktape/HTMLFrameSetElement.bnd34
-rw-r--r--content/handlers/javascript/duktape/ImageData.bnd44
-rw-r--r--content/handlers/javascript/duktape/KeyboardEvent.bnd142
-rw-r--r--content/handlers/javascript/duktape/Makefile31
-rw-r--r--content/handlers/javascript/duktape/NamedNodeMap.bnd74
-rw-r--r--content/handlers/javascript/duktape/Node.bnd12
-rw-r--r--content/handlers/javascript/duktape/Window.bnd611
-rw-r--r--content/handlers/javascript/duktape/duk_config.h252
-rw-r--r--content/handlers/javascript/duktape/duk_custom.h2
-rw-r--r--content/handlers/javascript/duktape/dukky.c606
-rw-r--r--content/handlers/javascript/duktape/dukky.h18
-rw-r--r--content/handlers/javascript/duktape/duktape.c44466
-rw-r--r--content/handlers/javascript/duktape/duktape.h145
-rw-r--r--content/handlers/javascript/duktape/generics.js129
-rw-r--r--content/handlers/javascript/duktape/netsurf.bnd16
-rw-r--r--content/handlers/javascript/duktape/polyfill.js103
-rw-r--r--content/handlers/javascript/js.h128
-rw-r--r--content/handlers/javascript/none/none.c30
-rw-r--r--content/handlers/text/Makefile3
-rw-r--r--content/handlers/text/textplain.c (renamed from render/textplain.c)928
-rw-r--r--content/handlers/text/textplain.h37
-rw-r--r--content/hlcache.c87
-rw-r--r--content/hlcache.h5
-rw-r--r--content/llcache.c1024
-rw-r--r--content/llcache.h163
-rw-r--r--content/mimesniff.c13
-rw-r--r--content/textsearch.c740
-rw-r--r--content/textsearch.h101
-rw-r--r--content/urldb.c8
-rw-r--r--content/urldb.h21
-rw-r--r--desktop/Makefile7
-rw-r--r--desktop/bitmap.c338
-rw-r--r--desktop/bitmap.h147
-rw-r--r--desktop/browser.c3352
-rw-r--r--desktop/browser_history.c95
-rw-r--r--desktop/browser_private.h88
-rw-r--r--desktop/browser_window.c4813
-rw-r--r--desktop/cookie_manager.c43
-rw-r--r--desktop/cookie_manager.h9
-rw-r--r--desktop/cw_helper.c92
-rw-r--r--desktop/cw_helper.h45
-rw-r--r--desktop/download.c20
-rw-r--r--desktop/download.h2
-rw-r--r--desktop/font_haru.c2
-rw-r--r--desktop/frames.c342
-rw-r--r--desktop/frames.h38
-rw-r--r--desktop/global_history.c22
-rw-r--r--desktop/gui_factory.c119
-rw-r--r--desktop/hotlist.c59
-rw-r--r--desktop/knockout.c4
-rw-r--r--desktop/local_history.c258
-rw-r--r--desktop/local_history.h7
-rw-r--r--desktop/local_history_private.h38
-rw-r--r--desktop/netsurf.c80
-rw-r--r--desktop/options.h29
-rw-r--r--desktop/page-info.c836
-rw-r--r--desktop/page-info.h151
-rw-r--r--desktop/plot_style.c14
-rw-r--r--desktop/print.c40
-rw-r--r--desktop/save_complete.c428
-rw-r--r--desktop/save_complete.h14
-rw-r--r--desktop/save_pdf.c16
-rw-r--r--desktop/save_text.c4
-rw-r--r--desktop/scrollbar.c25
-rw-r--r--desktop/scrollbar.h1
-rw-r--r--desktop/search.c14
-rw-r--r--desktop/search.h10
-rw-r--r--desktop/searchweb.c52
-rw-r--r--desktop/searchweb.h13
-rw-r--r--desktop/selection.c1069
-rw-r--r--desktop/selection.h204
-rw-r--r--desktop/sslcert_viewer.c572
-rw-r--r--desktop/sslcert_viewer.h135
-rw-r--r--desktop/textarea.c111
-rw-r--r--desktop/textinput.c13
-rw-r--r--desktop/treeview.c501
-rw-r--r--desktop/treeview.h11
-rw-r--r--desktop/version.c6
-rw-r--r--docs/Doxyfile398
-rw-r--r--docs/PACKAGING-GTK22
-rw-r--r--docs/UnimplementedJavascript.md1549
-rw-r--r--docs/UnimplementedJavascript.txt1798
-rw-r--r--docs/building-GTK.md313
-rw-r--r--docs/core-window-interface.md2
-rw-r--r--docs/development.md123
-rw-r--r--docs/env.sh173
-rwxr-xr-xdocs/gource.sh4
-rw-r--r--docs/implementing-new-frontend.md413
-rw-r--r--docs/integration-testing.md542
-rw-r--r--docs/jsbinding.md313
-rw-r--r--docs/logging.md10
-rw-r--r--docs/mainpage.md95
-rw-r--r--docs/netsurf-fb.115
-rw-r--r--docs/netsurf-gtk.110
-rw-r--r--docs/netsurf-options.md2
-rw-r--r--docs/project.md17
-rw-r--r--docs/quick-start.md62
-rw-r--r--docs/source-object-backing-store.md120
-rw-r--r--docs/unit-testing.md (renamed from docs/unit-testing)199
-rw-r--r--docs/user-interface.md61
-rw-r--r--docs/using-framebuffer.md58
-rw-r--r--docs/using-monkey.md128
-rw-r--r--frontends/Makefile.hts122
-rw-r--r--frontends/amiga/Makefile19
-rw-r--r--frontends/amiga/Makefile.defaults17
-rw-r--r--frontends/amiga/Makefile.tools21
-rw-r--r--frontends/amiga/arexx.c120
-rw-r--r--frontends/amiga/bitmap.c103
-rwxr-xr-xfrontends/amiga/bitmap.h16
-rw-r--r--frontends/amiga/clipboard.c66
-rw-r--r--frontends/amiga/cookies.c12
-rw-r--r--frontends/amiga/cookies.h2
-rw-r--r--frontends/amiga/corewindow.c63
-rw-r--r--frontends/amiga/ctxmenu.c84
-rw-r--r--frontends/amiga/ctxmenu.h7
-rw-r--r--frontends/amiga/dist/Rexx/YT_download_page.nsrx21
-rw-r--r--frontends/amiga/dist/Rexx/YT_open.nsrx21
-rw-r--r--frontends/amiga/dist/Rexx/YT_play.nsrx19
-rw-r--r--frontends/amiga/download.c64
-rw-r--r--frontends/amiga/drag.c61
-rw-r--r--frontends/amiga/drag.h3
-rw-r--r--frontends/amiga/dt_anim.c25
-rw-r--r--frontends/amiga/dt_picture.c22
-rw-r--r--frontends/amiga/dt_sound.c19
-rw-r--r--frontends/amiga/file.c37
-rw-r--r--frontends/amiga/font.c2
-rw-r--r--frontends/amiga/font_bullet.c24
-rw-r--r--frontends/amiga/font_diskfont.c18
-rw-r--r--frontends/amiga/font_scan.c2
-rw-r--r--frontends/amiga/gui.c1370
-rw-r--r--frontends/amiga/gui.h328
-rw-r--r--frontends/amiga/gui_menu.c201
-rw-r--r--frontends/amiga/gui_menu.h11
-rwxr-xr-xfrontends/amiga/gui_options.c109
-rw-r--r--frontends/amiga/history.c10
-rw-r--r--frontends/amiga/history_local.c27
-rw-r--r--frontends/amiga/history_local.h4
-rw-r--r--frontends/amiga/hotlist.c10
-rw-r--r--frontends/amiga/icon.c29
-rw-r--r--frontends/amiga/iff_dr2d.c25
-rwxr-xr-xfrontends/amiga/launch.c2
-rw-r--r--frontends/amiga/libs.c39
-rw-r--r--frontends/amiga/libs.h1
-rwxr-xr-xfrontends/amiga/login.c244
-rw-r--r--frontends/amiga/menu.c3
-rwxr-xr-xfrontends/amiga/misc.c14
-rw-r--r--frontends/amiga/options.h19
-rw-r--r--frontends/amiga/os3support.c7
-rw-r--r--frontends/amiga/os3support.h13
-rw-r--r--frontends/amiga/pageinfo.c283
-rw-r--r--frontends/amiga/pageinfo.h (renamed from frontends/gtk/login.h)18
-rw-r--r--frontends/amiga/pkg/SearchEngines2
-rwxr-xr-xfrontends/amiga/pkg/netsurf.readme4
-rw-r--r--frontends/amiga/pkg/netsurf_os3.readme10
-rw-r--r--frontends/amiga/plotters.c85
-rw-r--r--frontends/amiga/plugin_hack.c15
-rw-r--r--frontends/amiga/print.c67
-rwxr-xr-xfrontends/amiga/resources/Themes/AISS/Theme5
-rwxr-xr-xfrontends/amiga/resources/Themes/Default/Theme5
-rw-r--r--frontends/amiga/rtg.c3
-rw-r--r--frontends/amiga/schedule.c34
-rwxr-xr-xfrontends/amiga/search.c165
-rwxr-xr-xfrontends/amiga/search.h2
-rw-r--r--frontends/amiga/selectmenu.c12
-rw-r--r--frontends/amiga/sslcert.c375
-rwxr-xr-xfrontends/amiga/stringview/stringview.c4
-rwxr-xr-xfrontends/amiga/stringview/stringview.h4
-rw-r--r--frontends/amiga/theme.c63
-rw-r--r--frontends/amiga/theme.h2
-rwxr-xr-xfrontends/amiga/utf8.c70
-rw-r--r--frontends/amiga/version.c2
-rw-r--r--frontends/atari/Makefile47
-rw-r--r--frontends/atari/Makefile.tools19
-rw-r--r--frontends/atari/bitmap.c96
-rw-r--r--frontends/atari/bitmap.h4
-rw-r--r--frontends/atari/certview.c293
-rw-r--r--frontends/atari/certview.h51
-rw-r--r--frontends/atari/ctxmenu.c6
-rw-r--r--frontends/atari/deskmenu.c10
-rw-r--r--frontends/atari/encoding.h2
-rw-r--r--frontends/atari/file.c12
-rw-r--r--frontends/atari/file.h2
-rw-r--r--frontends/atari/font.h2
-rw-r--r--frontends/atari/gui.c104
-rw-r--r--frontends/atari/gui.h1
-rw-r--r--frontends/atari/login.c67
-rw-r--r--frontends/atari/plot/font_freetype.c3
-rw-r--r--frontends/atari/plot/font_internal.c1
-rw-r--r--frontends/atari/plot/font_vdi.c14
-rw-r--r--frontends/atari/plot/plot.c8
-rwxr-xr-xfrontends/atari/res/netsurf.rsh3
-rwxr-xr-xfrontends/atari/res/netsurf.rsm3
-rw-r--r--frontends/atari/rootwin.c2
-rw-r--r--frontends/atari/search.h2
-rw-r--r--frontends/atari/settings.c29
-rw-r--r--frontends/atari/toolbar.c4
-rw-r--r--frontends/atari/treeview.c34
-rw-r--r--frontends/atari/verify_ssl.c273
-rw-r--r--frontends/beos/Makefile66
-rw-r--r--frontends/beos/Makefile.tools14
-rw-r--r--frontends/beos/bitmap.cpp76
-rw-r--r--frontends/beos/font.cpp2
-rw-r--r--frontends/beos/gui.cpp49
-rw-r--r--frontends/beos/gui.h7
-rw-r--r--frontends/beos/login.cpp31
-rw-r--r--frontends/beos/options.h5
-rw-r--r--frontends/beos/plotters.cpp8
l---------frontends/beos/res/en/maps.html1
l---------frontends/beos/res/maps.html1
-rw-r--r--frontends/beos/window.cpp216
-rw-r--r--frontends/beos/window.h2
-rw-r--r--frontends/framebuffer/Makefile105
-rw-r--r--frontends/framebuffer/Makefile.defaults4
-rw-r--r--frontends/framebuffer/Makefile.tools15
-rw-r--r--frontends/framebuffer/bitmap.c69
-rw-r--r--frontends/framebuffer/corewindow.c32
-rw-r--r--frontends/framebuffer/fbtk/event.c2
-rw-r--r--frontends/framebuffer/fbtk/text.c2
-rw-r--r--frontends/framebuffer/fetch.h2
-rw-r--r--frontends/framebuffer/findfile.c109
-rw-r--r--frontends/framebuffer/findfile.h2
-rw-r--r--frontends/framebuffer/font_freetype.c4
-rw-r--r--frontends/framebuffer/font_internal.c15
-rw-r--r--frontends/framebuffer/framebuffer.c8
-rw-r--r--frontends/framebuffer/gui.c156
-rw-r--r--frontends/framebuffer/local_history.c1
l---------frontends/framebuffer/res/Messages1
l---------frontends/framebuffer/res/de/welcome.html1
l---------frontends/framebuffer/res/en/credits.html1
l---------frontends/framebuffer/res/en/licence.html1
l---------frontends/framebuffer/res/en/welcome.html1
-rw-r--r--frontends/framebuffer/res/fonts/glyph_data95
l---------frontends/framebuffer/res/it/credits.html1
l---------frontends/framebuffer/res/it/licence.html1
l---------frontends/framebuffer/res/ja/welcome.html1
l---------frontends/framebuffer/res/maps.html1
l---------frontends/framebuffer/res/nl/credits.html1
l---------frontends/framebuffer/res/nl/licence.html1
l---------frontends/framebuffer/res/nl/welcome.html1
-rw-r--r--frontends/gtk/Makefile49
-rw-r--r--frontends/gtk/Makefile.tools16
-rw-r--r--frontends/gtk/bitmap.c278
-rw-r--r--frontends/gtk/bitmap.h2
-rw-r--r--frontends/gtk/compat.c55
-rw-r--r--frontends/gtk/compat.h47
-rw-r--r--frontends/gtk/completion.c55
-rw-r--r--frontends/gtk/completion.h9
-rw-r--r--frontends/gtk/cookies.c7
-rw-r--r--frontends/gtk/cookies.h2
-rw-r--r--frontends/gtk/corewindow.c116
-rw-r--r--frontends/gtk/download.c856
-rw-r--r--frontends/gtk/download.h27
-rw-r--r--frontends/gtk/fetch.c11
-rw-r--r--frontends/gtk/fetch.h2
-rw-r--r--frontends/gtk/gdk.c5
-rw-r--r--frontends/gtk/global_history.c6
-rw-r--r--frontends/gtk/gui.c1333
-rw-r--r--frontends/gtk/gui.h3
-rw-r--r--frontends/gtk/hotlist.c2
-rw-r--r--frontends/gtk/layout_pango.c2
-rw-r--r--frontends/gtk/local_history.c37
-rw-r--r--frontends/gtk/local_history.h5
-rw-r--r--frontends/gtk/login.c232
-rw-r--r--frontends/gtk/menu.c231
-rw-r--r--frontends/gtk/menu.h240
-rw-r--r--frontends/gtk/misc.c192
-rw-r--r--frontends/gtk/misc.h (renamed from frontends/windows/filetype.h)8
-rw-r--r--frontends/gtk/options.h15
-rw-r--r--frontends/gtk/page_info.c258
-rw-r--r--frontends/gtk/page_info.h (renamed from frontends/gtk/ssl_cert.h)29
-rw-r--r--frontends/gtk/plotters.c37
-rw-r--r--frontends/gtk/preferences.c41
-rw-r--r--frontends/gtk/print.c32
l---------frontends/gtk/res/en/maps.html1
l---------frontends/gtk/res/fr/credits.html1
l---------frontends/gtk/res/fr/licence.html1
l---------frontends/gtk/res/fr/welcome.html1
-rw-r--r--frontends/gtk/res/gtk2/cookies.ui (renamed from frontends/gtk/res/cookies.gtk2.ui)0
-rw-r--r--frontends/gtk/res/gtk2/downloads.ui (renamed from frontends/gtk/res/downloads.gtk2.ui)0
-rw-r--r--frontends/gtk/res/gtk2/globalhistory.ui (renamed from frontends/gtk/res/globalhistory.gtk2.ui)0
-rw-r--r--frontends/gtk/res/gtk2/hotlist.ui (renamed from frontends/gtk/res/hotlist.gtk2.ui)0
-rw-r--r--frontends/gtk/res/gtk2/localhistory.ui (renamed from frontends/gtk/res/localhistory.gtk2.ui)1
-rw-r--r--frontends/gtk/res/gtk2/netsurf.ui90
-rw-r--r--frontends/gtk/res/gtk2/options.ui (renamed from frontends/gtk/res/options.gtk2.ui)83
-rw-r--r--frontends/gtk/res/gtk2/pageinfo.ui16
-rw-r--r--frontends/gtk/res/gtk2/password.ui (renamed from frontends/gtk/res/password.gtk2.ui)0
-rw-r--r--frontends/gtk/res/gtk2/tabcontents.ui229
-rw-r--r--frontends/gtk/res/gtk2/toolbar.ui120
-rw-r--r--frontends/gtk/res/gtk2/viewdata.ui (renamed from frontends/gtk/res/viewdata.gtk2.ui)0
-rw-r--r--frontends/gtk/res/gtk2/warning.ui (renamed from frontends/gtk/res/warning.gtk2.ui)0
-rw-r--r--frontends/gtk/res/gtk3/cookies.ui (renamed from frontends/gtk/res/cookies.gtk3.ui)2
-rw-r--r--frontends/gtk/res/gtk3/downloads.ui (renamed from frontends/gtk/res/downloads.gtk3.ui)0
-rw-r--r--frontends/gtk/res/gtk3/globalhistory.ui (renamed from frontends/gtk/res/globalhistory.gtk3.ui)2
-rw-r--r--frontends/gtk/res/gtk3/hotlist.ui (renamed from frontends/gtk/res/hotlist.gtk3.ui)2
-rw-r--r--frontends/gtk/res/gtk3/localhistory.ui (renamed from frontends/gtk/res/localhistory.gtk3.ui)3
-rw-r--r--frontends/gtk/res/gtk3/netsurf.ui61
-rw-r--r--frontends/gtk/res/gtk3/options.ui (renamed from frontends/gtk/res/options.gtk3.ui)216
-rw-r--r--frontends/gtk/res/gtk3/pageinfo.ui22
-rw-r--r--frontends/gtk/res/gtk3/password.ui (renamed from frontends/gtk/res/password.gtk3.ui)0
-rw-r--r--frontends/gtk/res/gtk3/tabcontents.ui229
-rw-r--r--frontends/gtk/res/gtk3/toolbar.ui126
-rw-r--r--frontends/gtk/res/gtk3/viewdata.ui (renamed from frontends/gtk/res/viewdata.gtk3.ui)0
-rw-r--r--frontends/gtk/res/gtk3/warning.ui (renamed from frontends/gtk/res/warning.gtk3.ui)0
-rw-r--r--frontends/gtk/res/login.gtk2.ui223
-rw-r--r--frontends/gtk/res/login.gtk3.ui223
l---------frontends/gtk/res/maps.html1
-rw-r--r--frontends/gtk/res/messages.gresource.xml1
-rw-r--r--frontends/gtk/res/netsurf.gresource.xml48
-rw-r--r--frontends/gtk/res/netsurf.gtk2.ui212
-rw-r--r--frontends/gtk/res/netsurf.gtk3.ui207
-rw-r--r--frontends/gtk/res/ssl.gtk2.ui202
-rw-r--r--frontends/gtk/res/ssl.gtk3.ui181
-rw-r--r--frontends/gtk/res/tabcontents.gtk2.ui92
-rw-r--r--frontends/gtk/res/tabcontents.gtk3.ui92
-rw-r--r--frontends/gtk/res/toolbar.gtk2.ui172
-rw-r--r--frontends/gtk/res/toolbar.gtk3.ui137
-rw-r--r--frontends/gtk/res/ui.gresource.xml18
l---------frontends/gtk/res/zh_CN/credits.html1
l---------frontends/gtk/res/zh_CN/licence.html1
l---------frontends/gtk/res/zh_CN/welcome.html1
-rw-r--r--frontends/gtk/resources.c24
-rw-r--r--frontends/gtk/scaffolding.c2873
-rw-r--r--frontends/gtk/scaffolding.h176
-rw-r--r--frontends/gtk/schedule.c52
-rw-r--r--frontends/gtk/search.c418
-rw-r--r--frontends/gtk/search.h49
-rw-r--r--frontends/gtk/selection.c1
-rw-r--r--frontends/gtk/selection.h2
-rw-r--r--frontends/gtk/ssl_cert.c259
-rw-r--r--frontends/gtk/tabs.c379
-rw-r--r--frontends/gtk/tabs.h48
-rw-r--r--frontends/gtk/throbber.c48
-rw-r--r--frontends/gtk/throbber.h33
-rw-r--r--frontends/gtk/toolbar.c4564
-rw-r--r--frontends/gtk/toolbar.h184
-rw-r--r--frontends/gtk/toolbar_items.h159
-rw-r--r--frontends/gtk/viewsource.c15
-rw-r--r--frontends/gtk/window.c715
-rw-r--r--frontends/gtk/window.h110
-rw-r--r--frontends/monkey/401login.c212
-rw-r--r--frontends/monkey/401login.h38
-rw-r--r--frontends/monkey/Makefile36
-rw-r--r--frontends/monkey/Makefile.defaults1
-rw-r--r--frontends/monkey/Makefile.tools15
-rw-r--r--frontends/monkey/bitmap.c48
-rw-r--r--frontends/monkey/browser.c406
-rw-r--r--frontends/monkey/cert.c59
-rw-r--r--frontends/monkey/dispatch.c13
-rw-r--r--frontends/monkey/dispatch.h2
-rw-r--r--frontends/monkey/download.c16
-rw-r--r--frontends/monkey/farmer.py363
-rw-r--r--frontends/monkey/fetch.h2
-rw-r--r--frontends/monkey/filetype.c9
-rw-r--r--frontends/monkey/layout.c10
-rw-r--r--frontends/monkey/main.c128
-rw-r--r--frontends/monkey/options.h6
-rw-r--r--frontends/monkey/output.c53
-rw-r--r--frontends/monkey/output.h (renamed from frontends/monkey/cert.h)21
-rw-r--r--frontends/monkey/plot.c42
-rw-r--r--frontends/monkey/schedule.c10
-rw-r--r--frontends/riscos/401login.c235
-rw-r--r--frontends/riscos/Makefile71
-rw-r--r--frontends/riscos/Makefile.tools100
-rw-r--r--frontends/riscos/appdir/!Boot,feb4
-rw-r--r--frontends/riscos/appdir/Resources/Aletheia,ffdbin15237 -> 17159 bytes
-rw-r--r--frontends/riscos/appdir/Resources/SearchEngines43
-rw-r--r--frontends/riscos/appdir/Resources/en/!Help8
l---------frontends/riscos/appdir/Resources/en/maps.html,faf1
-rw-r--r--frontends/riscos/appdir/Resources/nl/!Help8
-rw-r--r--frontends/riscos/bitmap.c84
-rw-r--r--frontends/riscos/bitmap.h13
-rw-r--r--frontends/riscos/buffer.c2
-rw-r--r--frontends/riscos/buffer.h2
-rw-r--r--frontends/riscos/configure/con_content.c14
-rw-r--r--frontends/riscos/configure/con_image.c31
-rw-r--r--frontends/riscos/content-handlers/artworks.c57
-rw-r--r--frontends/riscos/content-handlers/awrender.s82
-rw-r--r--frontends/riscos/content-handlers/draw.c13
-rw-r--r--frontends/riscos/content-handlers/sprite.c15
-rw-r--r--frontends/riscos/cookies.c15
-rw-r--r--frontends/riscos/cookies.h2
-rw-r--r--frontends/riscos/corewindow.c119
-rw-r--r--frontends/riscos/dialog.c67
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/!Boot,feb2
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/!Help6
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/!Run,feb2
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Acorn/Latin1,ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Acorn/Latin1)bin256 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/CentEuro,ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/CentEuro)bin256 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Cyrillic,ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Cyrillic)bin256 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Roman,ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Roman)bin256 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Ukrainian,ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Ukrainian)bin256 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/BigFive,ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/BigFive)bin29516 -> 29516 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C0/40[ISO646],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C0/40[ISO646])bin64 -> 64 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C1/43[IS6429],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C1/43[IS6429])bin64 -> 64 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/40[646old],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/40[646old])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/41[646-GB],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/41[646-GB])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/42[646IRV],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/42[646IRV])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/43[FinSwe],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/43[FinSwe])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/47[646-SE],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/47[646-SE])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/48[646-SE],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/48[646-SE])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/49[JS201K],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/49[JS201K])0
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4A[JS201R],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4A[JS201R])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4B[646-DE],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4B[646-DE])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4C[646-PT],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4C[646-PT])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/54[GB1988],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/54[GB1988])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/56[Teltxt],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/56[Teltxt])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/59[646-IT],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/59[646-IT])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/5A[646-ES],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/5A[646-ES])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/60[646-NO],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/60[646-NO])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/66[646-FR],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/66[646-FR])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/69[646-HU],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/69[646-HU])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6B[Arabic],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6B[Arabic])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6C[IS6937],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6C[IS6937])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/7A[SerbCr],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/7A[SerbCr])bin188 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/40[JS6226],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/40[JS6226])bin17672 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/41[GB2312],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/41[GB2312])bin17672 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/42[JIS208],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/42[JIS208])bin17672 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/43[KS1001],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/43[KS1001])bin17672 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/44[JIS212],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/44[JIS212])bin17672 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/47[CNS1],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/47[CNS1])bin17672 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/48[CNS2],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/48[CNS2])bin17672 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/49[CNS3],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/49[CNS3])bin17672 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4A[CNS4],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4A[CNS4])bin17672 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4B[CNS5],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4B[CNS5])bin17672 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4C[CNS6],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4C[CNS6])bin17672 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4D[CNS7],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4D[CNS7])0
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/41[Lat1],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/41[Lat1])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/42[Lat2],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/42[Lat2])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/43[Lat3],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/43[Lat3])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/44[Lat4],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/44[Lat4])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/46[Greek],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/46[Greek])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/47[Arabic],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/47[Arabic])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/48[Hebrew],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/48[Hebrew])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4C[Cyrill],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4C[Cyrill])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4D[Lat5],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4D[Lat5])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/50[LatSup],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/50[LatSup])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/52[IS6937],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/52[IS6937])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/54[Thai],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/54[Thai])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/56[Lat6],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/56[Lat6])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/58[L6Sami],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/58[L6Sami])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/59[Lat7],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/59[Lat7])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5C[Welsh],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5C[Welsh])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5D[Sami],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5D[Sami])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5E[Hebrew],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5E[Hebrew])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5F[Lat8],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5F[Lat8])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/62[Lat9],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/62[Lat9])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/66[Lat10],ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/66[Lat10])bin192 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/KOI8-R,ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/KOI8-R)bin256 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1250,ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1250)bin256 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1251,ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1251)bin256 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1252,ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1252)bin256 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1253,ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1253)bin256 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1254,ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1254)bin256 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1256,ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1256)bin256 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP866,ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP866)bin256 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP874,ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP874)bin256 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP932,ffd (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP932)bin996 -> 996 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Files/CharNames14016
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/!Sprites,ff9 (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites,ff9)bin5780 -> 5780 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/!Sprites11,ff9 (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites11,ff9)bin11132 -> 11132 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/!Sprites22,ff9 (renamed from frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites22,ff9)bin7324 -> 7324 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/Morris4/!Sprites,ff9bin0 -> 996 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/Morris4/!Sprites22,ff9bin0 -> 1892 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/Ursula/!Sprites,ff9bin0 -> 1684 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/Ursula/!Sprites22,ff9bin0 -> 3268 bytes
-rw-r--r--frontends/riscos/distribution/!System/310/Modules/Network/URI,ffabin9188 -> 7120 bytes
-rw-r--r--[-rwxr-xr-x]frontends/riscos/distribution/!System/310/Modules/SharedULib,ffabin3116 -> 3192 bytes
-rw-r--r--frontends/riscos/distribution/!System/400/Modules/ARMEABISupport,ffabin0 -> 26504 bytes
-rw-r--r--frontends/riscos/distribution/3rdParty/ARMEABISupport/Copyright20
-rw-r--r--frontends/riscos/distribution/3rdParty/ARMEABISupport/Origin,b281
-rw-r--r--frontends/riscos/distribution/3rdParty/AcornURI/!ReadMe34
-rw-r--r--frontends/riscos/distribution/3rdParty/AcornURI/Apache-2.0202
-rw-r--r--frontends/riscos/distribution/3rdParty/AcornURI/Copying526
-rw-r--r--frontends/riscos/distribution/3rdParty/AcornURI/Origin,b281
-rw-r--r--frontends/riscos/distribution/3rdParty/Cache/Copyright20
-rw-r--r--frontends/riscos/distribution/3rdParty/Cache/Origin,b281
-rw-r--r--frontends/riscos/distribution/3rdParty/CryptRand/Origin,b281
-rw-r--r--frontends/riscos/distribution/3rdParty/Iconv/COPYING140
-rw-r--r--frontends/riscos/distribution/3rdParty/Iconv/Origin,b281
-rw-r--r--frontends/riscos/distribution/3rdParty/Iconv/ReadMe21
-rw-r--r--frontends/riscos/distribution/3rdParty/Iconv/licenses/Apache-2.0202
-rw-r--r--frontends/riscos/distribution/3rdParty/Iconv/licenses/LGPL-2481
-rw-r--r--frontends/riscos/distribution/3rdParty/SharedULib/Copyright15
-rw-r--r--frontends/riscos/distribution/3rdParty/SharedULib/Origin,b281
-rw-r--r--frontends/riscos/distribution/3rdParty/Tinct/Origin,b281
-rw-r--r--frontends/riscos/distribution/3rdParty/Unicode/Apache-2.0202
-rw-r--r--frontends/riscos/distribution/3rdParty/Unicode/Copyright66
-rw-r--r--frontends/riscos/distribution/3rdParty/Unicode/Origin,b281
-rw-r--r--frontends/riscos/distribution/LeesMij14
-rw-r--r--frontends/riscos/distribution/ReadMe23
-rw-r--r--frontends/riscos/download.c19
-rw-r--r--frontends/riscos/filetype.c2
-rw-r--r--frontends/riscos/filetype.h3
-rw-r--r--frontends/riscos/font.c2
-rw-r--r--frontends/riscos/font.h2
-rw-r--r--frontends/riscos/global_history.c14
-rw-r--r--frontends/riscos/gui.c128
-rw-r--r--frontends/riscos/gui.h13
-rw-r--r--frontends/riscos/gui/button_bar.c3
-rw-r--r--frontends/riscos/gui/throbber.c4
-rw-r--r--frontends/riscos/gui/url_bar.c1356
-rw-r--r--frontends/riscos/gui/url_bar.h15
-rw-r--r--frontends/riscos/hotlist.c10
-rw-r--r--frontends/riscos/iconbar.c4
-rw-r--r--frontends/riscos/image.c230
-rw-r--r--frontends/riscos/local_history.c22
-rw-r--r--frontends/riscos/options.h26
-rw-r--r--frontends/riscos/pageinfo.c325
-rw-r--r--frontends/riscos/pageinfo.h48
-rw-r--r--frontends/riscos/plotters.c58
-rw-r--r--frontends/riscos/print.c7
-rw-r--r--frontends/riscos/save.c20
-rw-r--r--frontends/riscos/save_draw.c9
-rw-r--r--frontends/riscos/scripts/Run13
-rw-r--r--frontends/riscos/sslcert.c415
-rw-r--r--frontends/riscos/sslcert.h47
-rw-r--r--frontends/riscos/templates/de450
-rw-r--r--frontends/riscos/templates/en449
-rw-r--r--frontends/riscos/templates/fr456
-rw-r--r--frontends/riscos/templates/nl453
-rw-r--r--frontends/riscos/textarea.c3
-rw-r--r--frontends/riscos/textselection.c3
-rw-r--r--frontends/riscos/textselection.h2
-rw-r--r--frontends/riscos/theme_install.c63
-rw-r--r--frontends/riscos/tinct.h13
-rw-r--r--frontends/riscos/toolbar.c40
-rw-r--r--frontends/riscos/toolbar.h10
-rw-r--r--frontends/riscos/ucstables.c219
-rw-r--r--frontends/riscos/ucstables.h2
-rw-r--r--frontends/riscos/wimputils.h26
-rw-r--r--frontends/riscos/window.c543
-rw-r--r--frontends/riscos/window.h11
-rw-r--r--frontends/windows/Makefile21
-rw-r--r--frontends/windows/Makefile.defaults4
-rw-r--r--frontends/windows/Makefile.tools19
-rw-r--r--frontends/windows/about.c4
-rw-r--r--frontends/windows/about.h6
-rw-r--r--frontends/windows/bitmap.c65
-rw-r--r--frontends/windows/bitmap.h4
-rw-r--r--frontends/windows/clipboard.c131
-rw-r--r--[-rwxr-xr-x]frontends/windows/clipboard.h (renamed from frontends/amiga/login.h)16
-rw-r--r--frontends/windows/cookies.c8
-rw-r--r--frontends/windows/cookies.h2
-rw-r--r--frontends/windows/corewindow.c28
-rw-r--r--frontends/windows/download.c3
-rw-r--r--frontends/windows/drawable.c197
-rw-r--r--frontends/windows/fetch.c (renamed from frontends/windows/filetype.c)69
-rw-r--r--frontends/windows/fetch.h (renamed from frontends/amiga/sslcert.h)34
-rw-r--r--frontends/windows/file.h2
-rw-r--r--frontends/windows/font.c222
-rw-r--r--frontends/windows/font.h4
-rw-r--r--frontends/windows/gui.c153
-rw-r--r--frontends/windows/gui.h42
-rw-r--r--frontends/windows/local_history.c1
-rw-r--r--frontends/windows/main.c207
-rw-r--r--frontends/windows/plot.c10
-rw-r--r--frontends/windows/pointers.c1
-rw-r--r--frontends/windows/prefs.c33
l---------frontends/windows/res/icons/arrow-l.png1
l---------frontends/windows/res/icons/content.png1
l---------frontends/windows/res/icons/directory.png1
l---------frontends/windows/res/icons/directory2.png1
l---------frontends/windows/res/icons/hotlist-add.png1
l---------frontends/windows/res/icons/hotlist-rmv.png1
l---------frontends/windows/res/icons/search.png1
-rw-r--r--frontends/windows/res/installer.nsi8
-rw-r--r--frontends/windows/res/page-info-insecure.bmpbin0 -> 890 bytes
-rw-r--r--frontends/windows/res/page-info-internal.bmpbin0 -> 890 bytes
-rw-r--r--frontends/windows/res/page-info-local.bmpbin0 -> 890 bytes
-rw-r--r--frontends/windows/res/page-info-secure.bmpbin0 -> 890 bytes
-rw-r--r--frontends/windows/res/page-info-warning.bmpbin0 -> 890 bytes
-rw-r--r--frontends/windows/res/resource.rc558
-rw-r--r--frontends/windows/resourceid.h45
-rw-r--r--frontends/windows/ssl_cert.c471
-rw-r--r--frontends/windows/ssl_cert.h51
-rw-r--r--frontends/windows/windbg.h11
-rw-r--r--frontends/windows/window.c560
-rw-r--r--frontends/windows/window.h9
-rw-r--r--include/netsurf/bitmap.h154
-rw-r--r--include/netsurf/browser.h42
-rw-r--r--include/netsurf/browser_window.h214
-rw-r--r--include/netsurf/console.h68
-rw-r--r--include/netsurf/content.h2
-rw-r--r--include/netsurf/content_type.h119
-rw-r--r--include/netsurf/core_window.h31
-rw-r--r--include/netsurf/fetch.h25
-rw-r--r--include/netsurf/inttypes.h9
-rw-r--r--include/netsurf/keypress.h2
-rw-r--r--include/netsurf/misc.h74
-rw-r--r--include/netsurf/plot_style.h119
-rw-r--r--include/netsurf/plotters.h72
-rw-r--r--include/netsurf/ssl_certs.h145
-rw-r--r--include/netsurf/url_db.h21
-rw-r--r--include/netsurf/window.h145
-rw-r--r--render/Makefile10
-rw-r--r--render/box.c1242
-rw-r--r--render/box.h368
-rw-r--r--render/box_construct.c3137
-rw-r--r--render/form.c1895
-rw-r--r--render/html_interaction.c1434
-rw-r--r--render/search.c656
-rw-r--r--render/search.h81
-rw-r--r--render/textplain.h139
-rw-r--r--resources/FatMessages7134
-rw-r--r--resources/SearchEngines37
-rw-r--r--resources/ca-bundle3296
-rw-r--r--resources/de/welcome.html40
-rw-r--r--resources/default.css4
-rw-r--r--resources/en/credits.html31
-rw-r--r--resources/en/licence.html98
-rw-r--r--resources/en/maps.html85
-rw-r--r--resources/en/welcome.html42
-rw-r--r--resources/fr/credits.html98
-rw-r--r--resources/fr/licence.html1876
-rw-r--r--resources/fr/welcome.html64
-rw-r--r--resources/icons/16x16/actions/page-info-insecure.pngbin0 -> 527 bytes
-rw-r--r--resources/icons/16x16/actions/page-info-internal.pngbin0 -> 799 bytes
-rw-r--r--resources/icons/16x16/actions/page-info-local.pngbin0 -> 456 bytes
-rw-r--r--resources/icons/16x16/actions/page-info-secure.pngbin0 -> 330 bytes
-rw-r--r--resources/icons/16x16/actions/page-info-warning.pngbin0 -> 552 bytes
-rw-r--r--resources/icons/24x24/actions/page-info-insecure.pngbin0 -> 767 bytes
-rw-r--r--resources/icons/24x24/actions/page-info-internal.pngbin0 -> 1226 bytes
-rw-r--r--resources/icons/24x24/actions/page-info-local.pngbin0 -> 672 bytes
-rw-r--r--resources/icons/24x24/actions/page-info-secure.pngbin0 -> 428 bytes
-rw-r--r--resources/icons/24x24/actions/page-info-warning.pngbin0 -> 781 bytes
-rw-r--r--resources/icons/48x48/actions/page-info-insecure.pngbin0 -> 1504 bytes
-rw-r--r--resources/icons/48x48/actions/page-info-internal.pngbin0 -> 2783 bytes
-rw-r--r--resources/icons/48x48/actions/page-info-local.pngbin0 -> 1278 bytes
-rw-r--r--resources/icons/48x48/actions/page-info-secure.pngbin0 -> 682 bytes
-rw-r--r--resources/icons/48x48/actions/page-info-warning.pngbin0 -> 1437 bytes
-rw-r--r--resources/icons/local-history.png (renamed from frontends/gtk/res/arrow_down_8x32.png)bin206 -> 206 bytes
-rw-r--r--resources/icons/page-info-insecure.svg80
-rw-r--r--resources/icons/page-info-internal.svg172
-rw-r--r--resources/icons/page-info-local.svg73
-rw-r--r--resources/icons/page-info-secure.svg69
-rw-r--r--resources/icons/page-info-warning.svg93
-rw-r--r--resources/icons/show-cookie.pngbin0 -> 303 bytes
-rw-r--r--resources/internal.css284
-rw-r--r--resources/it/credits.html17
-rw-r--r--resources/it/licence.html86
-rw-r--r--resources/it/welcome.html40
-rw-r--r--resources/ja/welcome.html40
-rw-r--r--resources/nl/credits.html17
-rw-r--r--resources/nl/licence.html98
-rw-r--r--resources/nl/welcome.html46
-rw-r--r--resources/zh_CN/credits.html98
-rw-r--r--resources/zh_CN/licence.html1869
-rw-r--r--resources/zh_CN/welcome.html65
-rw-r--r--test/.gitignore1
-rw-r--r--test/Makefile26
-rw-r--r--test/assert.c19
-rw-r--r--test/corestrings.c12
-rw-r--r--test/data/Choices5
-rw-r--r--test/data/Choices-all13
-rw-r--r--test/data/urldb-out8
-rw-r--r--test/hashmap.c571
-rw-r--r--test/js/class-list.html29
-rw-r--r--test/js/event-onclick-insert.html18
-rw-r--r--test/js/index.html3
-rw-r--r--test/js/inserted-script-async.js1
-rw-r--r--test/js/inserted-script-defer.js1
-rw-r--r--test/js/inserted-script.html39
-rw-r--r--test/js/inserted-script.js1
-rw-r--r--test/js/life.html175
-rw-r--r--test/js/mandelbrot.html31
-rw-r--r--test/js/settimeout.html17
-rw-r--r--test/js/sleepy-async.html13
-rw-r--r--test/messages.c3
-rwxr-xr-xtest/monkey-see-monkey-do143
-rw-r--r--test/monkey-tests/401login.yaml38
-rw-r--r--test/monkey-tests/cache-test.yaml35
-rw-r--r--test/monkey-tests/inserted-script.yaml28
-rw-r--r--test/monkey-tests/quit-mid-fetch.yaml22
-rw-r--r--test/monkey-tests/resource-scheme.yaml34
-rw-r--r--test/monkey-tests/simultanious-fetches.yaml35
-rw-r--r--test/monkey-tests/sslcert.yaml33
-rw-r--r--test/monkey-tests/start-stop-no-js.yaml7
-rw-r--r--test/monkey-tests/start-stop.yaml6
-rw-r--r--test/monkey-tests/state-test.yaml69
-rwxr-xr-xtest/monkey_driver.py670
-rw-r--r--test/monkeyfarmer.py661
-rw-r--r--test/nsoption.c10
-rw-r--r--test/nsurl.c26
-rw-r--r--test/utils.c33
-rw-r--r--tools/DerivedJoiningType.txt (renamed from utils/DerivedJoiningType.txt)246
-rw-r--r--tools/Makefile75
-rw-r--r--tools/convert_font.c (renamed from frontends/framebuffer/convert_font.c)16
-rw-r--r--tools/convert_image.c (renamed from frontends/framebuffer/convert_image.c)0
-rwxr-xr-xtools/coverity-build.sh (renamed from utils/coverity-build.sh)4
-rw-r--r--tools/fetch-transifex.pl (renamed from utils/fetch-transifex.pl)0
-rwxr-xr-xtools/git-date.sh (renamed from utils/git-date.sh)0
-rw-r--r--tools/git-testament.pl (renamed from utils/git-testament.pl)0
-rw-r--r--tools/idna-derived-props-gen.pl182
-rw-r--r--tools/idna-tables-properties.csv2838
-rw-r--r--tools/import-messages.pl (renamed from utils/import-messages.pl)6
-rwxr-xr-xtools/jenkins-build.sh (renamed from utils/jenkins-build.sh)83
-rw-r--r--tools/linktrace-to-depfile.pl19
-rwxr-xr-xtools/memanalyze.pl (renamed from utils/memanalyze.pl)0
-rw-r--r--tools/split-messages.c557
-rw-r--r--tools/split-messages.pl (renamed from utils/split-messages.pl)6
-rwxr-xr-xtools/test-netsurf (renamed from utils/test-netsurf)0
-rw-r--r--tools/valgrind.supp (renamed from utils/valgrind.supp)0
-rw-r--r--tools/xxd.c135
-rw-r--r--utils/Makefile3
-rw-r--r--utils/config.h84
-rw-r--r--utils/corestringlist.h29
-rw-r--r--utils/dirent.h4
-rw-r--r--utils/errors.h4
-rw-r--r--utils/file.c86
-rw-r--r--utils/file.h13
-rw-r--r--utils/filename.c92
-rw-r--r--utils/filepath.c76
-rw-r--r--utils/filepath.h14
-rw-r--r--utils/hashmap.c255
-rw-r--r--utils/hashmap.h197
-rw-r--r--utils/hashtable.c6
-rw-r--r--utils/http.h1
-rw-r--r--utils/http/Makefile2
-rw-r--r--utils/http/cache-control.c353
-rw-r--r--utils/http/cache-control.h77
-rw-r--r--utils/idna-derived-props-gen.pl96
-rw-r--r--utils/idna-tables-5.2.0-properties.csv2322
-rw-r--r--utils/idna.c444
-rw-r--r--utils/idna.h9
-rw-r--r--utils/idna_props.h1242
-rw-r--r--utils/inet.h11
-rw-r--r--utils/libdom.c123
-rw-r--r--utils/libdom.h23
-rw-r--r--utils/log.c18
-rw-r--r--utils/log.h3
-rw-r--r--utils/messages.c177
-rw-r--r--utils/messages.h25
-rw-r--r--utils/nscolour.c282
-rw-r--r--utils/nscolour.h81
-rw-r--r--utils/nsoption.c141
-rw-r--r--utils/nsurl.h50
-rw-r--r--utils/nsurl/nsurl.c125
-rw-r--r--utils/nsurl/parse.c88
-rw-r--r--utils/nsurl/private.h75
-rw-r--r--utils/regex.h63
-rw-r--r--utils/ring.h33
-rw-r--r--utils/ssl_certs.c356
-rw-r--r--utils/string.h2
-rw-r--r--utils/sys_time.h24
-rw-r--r--utils/time.c2
-rw-r--r--utils/useragent.c25
-rw-r--r--utils/useragent.h7
-rw-r--r--utils/utf8.c206
-rw-r--r--utils/utils.c134
-rw-r--r--utils/utils.h27
897 files changed, 127971 insertions, 70441 deletions
diff --git a/.clang-format b/.clang-format
index 3cee69bd9..75df82a95 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,43 +1,51 @@
---
Language: Cpp
-# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
-AlignEscapedNewlinesLeft: false
+AlignEscapedNewlines: Right
AlignOperands: true
-AlignTrailingComments: true
-AllowAllParametersOfDeclarationOnNextLine: true
+AlignTrailingComments: false
+AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
-AlwaysBreakAfterDefinitionReturnType: None
-AlwaysBreakAfterReturnType: All
+AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
-AlwaysBreakTemplateDeclarations: false
+AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
- AfterClass: false
+ AfterClass: true
AfterControlStatement: false
- AfterEnum: true
- AfterFunction: false
- AfterNamespace: false
+ AfterEnum: false
+ AfterFunction: true
+ AfterNamespace: true
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
+ AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
+ SplitEmptyFunction: true
+ SplitEmptyRecord: true
+ SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Linux
+BreakBeforeInheritanceComma: false
+BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeColon
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: false
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
+CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
@@ -45,7 +53,12 @@ Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
-ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
+FixNamespaceComments: true
+ForEachMacros:
+ - foreach
+ - Q_FOREACH
+ - BOOST_FOREACH
+IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^(<.*/)'
Priority: 3
@@ -57,29 +70,42 @@ IncludeCategories:
Priority: 5
- Regex: '.*'
Priority: 6
+IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
+IndentPPDirectives: None
IndentWidth: 8
IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
-MaxEmptyLinesToKeep: 1
+MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
+ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
-PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakAssignment: 100
+PenaltyBreakBeforeFirstCallParameter: 50
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
+PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
-PenaltyReturnTypeOnItsOwnLine: 60
+PenaltyReturnTypeOnItsOwnLine: 19
PointerAlignment: Right
ReflowComments: true
SortIncludes: false
+SortUsingDeclarations: true
SpaceAfterCStyleCast: false
+SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
+SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
new file mode 100644
index 000000000..eb92cdda1
--- /dev/null
+++ b/.github/workflows/build.yaml
@@ -0,0 +1,111 @@
+name: "Linux Build"
+
+on: [push]
+
+jobs:
+ linux:
+ name: '${{ matrix.os }}: ${{ matrix.compiler.vendor }}'
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os:
+ - ubuntu-22.04
+ - ubuntu-20.04
+ compiler:
+ # The NetSurf build system can't find LLVM AR (it looks for it
+ # in /usr/lib instead of /usr/bin:
+ # `make: /usr/lib/llvm-ar: No such file or directory`).
+ # So we need to make it explicit for llvm.
+ - { vendor: gnu, CC: gcc }
+ - { vendor: llvm, CC: clang, AR: llvm-ar }
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 1
+
+ - name: apt-get install packages
+ run: sudo apt-get update -qq &&
+ sudo apt-get install --no-install-recommends -y
+ bison
+ build-essential
+ ccache
+ check
+ clang
+ flex
+ git
+ gperf
+ libcurl4-openssl-dev
+ libgtk-3-dev
+ libhtml-parser-perl
+ libjpeg-dev
+ libpng-dev
+ librsvg2-dev
+ llvm
+ pkg-config
+ wbritish # Needed for `/usr/share/dict/words`, used by test
+
+ - name: ccache
+ uses: hendrikmuhs/ccache-action@v1.2
+ with:
+ key: ${{ github.job }}-${{ matrix.os }}-${{ matrix.compiler.vendor }}
+ max-size: 128M
+
+ - name: Build and install project libs
+ env:
+ CC: ${{ matrix.compiler.CC }}
+ CXX: ${{ matrix.compiler.CXX }}
+ run: |
+ export TARGET_WORKSPACE="$(pwd)/projects"
+ source docs/env.sh
+ ns-clone -d -s
+ ns-make-tools install
+ ns-make-libs install
+
+ - name: Disable -Werror
+ # We can remove this step if we ever move to GitHub properly.
+ run: |
+ find . -type f -name Makefile | xargs sed -i 's/-Werror//'
+
+ - name: Unit Tests
+ # Fails when built with clang:
+ # test/corestrings.c:58:F:corestrings:corestrings_test:486:
+ # Assertion 'ires == NSERROR_NOMEM' failed: ires == 0, NSERROR_NOMEM == 2
+ # Looks like `malloc_limit()` not working.
+ if: ${{ matrix.compiler.vendor != 'llvm' }}
+ env:
+ CC: ${{ matrix.compiler.CC }}
+ CXX: ${{ matrix.compiler.CXX }}
+ run: |
+ export TARGET_WORKSPACE="$(pwd)/projects"
+ source docs/env.sh
+ make test
+
+ - name: Build NetSurf GTK
+ env:
+ CC: ${{ matrix.compiler.CC }}
+ CXX: ${{ matrix.compiler.CXX }}
+ run: |
+ export TARGET_WORKSPACE="$(pwd)/projects"
+ source docs/env.sh
+ make -j"$(nproc)" TARGET=gtk
+
+ - name: Build NetSurf Monkey
+ env:
+ CC: ${{ matrix.compiler.CC }}
+ CXX: ${{ matrix.compiler.CXX }}
+ run: |
+ export TARGET_WORKSPACE="$(pwd)/projects"
+ source docs/env.sh
+ make -j"$(nproc)" TARGET=monkey
+
+ - name: Build NetSurf Framebuffer
+ env:
+ CC: ${{ matrix.compiler.CC }}
+ CXX: ${{ matrix.compiler.CXX }}
+ run: |
+ export TARGET_WORKSPACE="$(pwd)/projects"
+ source docs/env.sh
+ make -j"$(nproc)" TARGET=framebuffer
diff --git a/.github/workflows/monkey-test.yaml b/.github/workflows/monkey-test.yaml
new file mode 100644
index 000000000..e95c9796f
--- /dev/null
+++ b/.github/workflows/monkey-test.yaml
@@ -0,0 +1,69 @@
+name: "Monkey Test"
+
+on: [pull_request]
+
+jobs:
+ test:
+ name: '${{ matrix.test }}'
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ test:
+ - short-internet
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 1
+
+ - name: apt-get install packages
+ run: sudo apt-get update -qq &&
+ sudo apt-get install --no-install-recommends -y
+ bison
+ build-essential
+ ccache
+ check
+ clang
+ flex
+ git
+ gperf
+ libcurl4-openssl-dev
+ libgtk-3-dev
+ libhtml-parser-perl
+ libjpeg-dev
+ libpng-dev
+ librsvg2-dev
+ llvm
+ pkg-config
+ wbritish # Needed for `/usr/share/dict/words`, used by test
+
+ - name: ccache
+ uses: hendrikmuhs/ccache-action@v1.2
+ with:
+ key: ${{ github.job }}
+ max-size: 128M
+
+ - name: Build and install project libs
+ run: |
+ export TARGET_WORKSPACE="$(pwd)/projects"
+ source docs/env.sh
+ ns-clone -d -s
+ ns-make-tools install
+ ns-make-libs install
+
+ - name: Disable -Werror
+ # We can remove this step if we ever move to GitHub properly.
+ run: |
+ find . -type f -name Makefile | xargs sed -i 's/-Werror//'
+
+ - name: Build NetSurf Monkey
+ run: |
+ export TARGET_WORKSPACE="$(pwd)/projects"
+ source docs/env.sh
+ make -j"$(nproc)" TARGET=monkey
+
+ - name: Run Monkey Test
+ run: |
+ LC_ALL=C.UTF-8 test/monkey-see-monkey-do -v -d ${{ matrix.test }}
diff --git a/.github/workflows/static-analysis.yaml b/.github/workflows/static-analysis.yaml
new file mode 100644
index 000000000..8604761fe
--- /dev/null
+++ b/.github/workflows/static-analysis.yaml
@@ -0,0 +1,65 @@
+name: "Static Analysis"
+
+on: [push]
+
+jobs:
+ codeql:
+ name: codeql
+ runs-on: ubuntu-22.04
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: ['cpp']
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v2
+ with:
+ fetch-depth: 1
+
+ - name: apt-get install packages
+ run: sudo apt-get update -qq &&
+ sudo apt-get install --no-install-recommends -y
+ bison
+ build-essential
+ ccache
+ flex
+ git
+ gperf
+ libcurl4-openssl-dev
+ libgtk-3-dev
+ libhtml-parser-perl
+ libjpeg-dev
+ libpng-dev
+ librsvg2-dev
+ pkg-config
+
+ - name: ccache
+ uses: hendrikmuhs/ccache-action@v1.2
+ with:
+ key: ${{ github.job }}
+ max-size: 128M
+
+ - name: Build and install project libs
+ run: |
+ export TARGET_WORKSPACE="$(pwd)/projects"
+ source docs/env.sh
+ ns-clone -d -s
+ ns-make-tools install
+ ns-make-libs install
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v2
+ with:
+ languages: ${{ matrix.language }}
+
+ - name: Build NetSurf
+ run: |
+ export TARGET_WORKSPACE="$(pwd)/projects"
+ source docs/env.sh
+ make -j"$(nproc)"
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v2
diff --git a/.gitignore b/.gitignore
index bb10ba503..054455b32 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,18 +6,11 @@ frontends/riscos/appdir/Resources/en/Templates,fec
frontends/riscos/appdir/Resources/fr/Templates,fec
frontends/riscos/appdir/Resources/de/Templates,fec
frontends/riscos/appdir/Resources/nl/Templates,fec
-resources/en/Messages
-resources/fr/Messages
-resources/de/Messages
-resources/nl/Messages
-resources/it/Messages
-frontends/gtk/res/en/Messages
-frontends/gtk/res/fr/Messages
-frontends/gtk/res/de/Messages
-frontends/gtk/res/nl/Messages
-frontends/gtk/res/it/Messages
+resources/*/Messages
+frontends/*/res/*/Messages
codedocs
-nsgtk
+nsgtk2
+nsgtk3
nsfb
nsmonkey
nsdebug
diff --git a/Makefile b/Makefile
index 52f55d52a..18665ed3d 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,7 @@
#
# Copyright 2007 Daniel Silverstone <dsilvers@netsurf-browser.org>
# Copyright 2008 Rob Kendrick <rjek@netsurf-browser.org>
+# Copyright 2024 Vincent Sanders <vince@netsurf-browser.org>
#
# Trivially, invoke as:
# make
@@ -12,8 +13,7 @@
#
# Look at Makefile.config for configuration options.
#
-# Tested on unix platforms (building for GTK and cross-compiling for RO) and
-# on RO (building for RO).
+# Best results obtained building on unix platforms cross compiling for others
#
# To clean, invoke as above, with the 'clean' target
#
@@ -26,100 +26,8 @@
all: all-program
-# Determine host type
-# NOTE: HOST determination on RISC OS could fail because of missing bug fixes
-# in UnixLib which only got addressed in UnixLib 5 / GCCSDK 4.
-# When you don't have 'uname' available, you will see:
-# File 'uname' not found
-# When you do and using a 'uname' compiled with a buggy UnixLib, you
-# will see the following printed on screen:
-# RISC OS
-# In both cases HOST make variable is empty and we recover from that by
-# assuming we're building on RISC OS.
-# In case you don't see anything printed (including the warning), you
-# have an up-to-date RISC OS build system. ;-)
-HOST := $(shell uname -s)
-
-# Sanitise host
-# TODO: Ideally, we want the equivalent of s/[^A-Za-z0-9]/_/g here
-HOST := $(subst .,_,$(subst -,_,$(subst /,_,$(HOST))))
-
-ifeq ($(HOST),)
- HOST := riscos
- $(warning Build platform determination failed but that's a known problem for RISC OS so we're assuming a native RISC OS build.)
-else
- ifeq ($(HOST),RISC OS)
- # Fixup uname -s returning "RISC OS"
- HOST := riscos
- endif
-endif
-ifeq ($(HOST),riscos)
- # Build happening on RO platform, default target is RO backend
- ifeq ($(TARGET),)
- TARGET := riscos
- endif
-endif
-
-ifeq ($(HOST),BeOS)
- HOST := beos
-endif
-ifeq ($(HOST),Haiku)
- # Haiku implements the BeOS API
- HOST := beos
-endif
-ifeq ($(HOST),beos)
- # Build happening on BeOS platform, default target is BeOS backend
- ifeq ($(TARGET),)
- TARGET := beos
- endif
- ifeq ($(TARGET),haiku)
- override TARGET := beos
- endif
-endif
-
-ifeq ($(HOST),AmigaOS)
- HOST := amiga
- ifeq ($(TARGET),)
- TARGET := amiga
- endif
-endif
-
-ifeq ($(HOST),FreeMiNT)
- HOST := mint
-endif
-ifeq ($(HOST),mint)
- ifeq ($(TARGET),)
- TARGET := atari
- endif
-endif
-
-ifeq ($(findstring MINGW,$(HOST)),MINGW)
- # MSYS' uname reports the likes of "MINGW32_NT-6.0"
- HOST := windows
-endif
-ifeq ($(HOST),windows)
- ifeq ($(TARGET),)
- TARGET := windows
- endif
-endif
+# default values for base variables
-# Default target is GTK backend
-ifeq ($(TARGET),)
- TARGET := gtk
-endif
-
-# valid values for the TARGET
-VLDTARGET := riscos gtk gtk3 beos amiga amigaos3 framebuffer windows atari monkey
-
-# Check for valid TARGET
-ifeq ($(filter $(VLDTARGET),$(TARGET)),)
- $(error Unknown TARGET "$(TARGET)", Must be one of $(VLDTARGET))
-endif
-
-# ensure empty values for base variables
-
-# Sub target for build
-SUBTARGET=
# Resources executable target depends upon
RESOURCES=
# Messages executable target depends on
@@ -128,17 +36,10 @@ MESSAGES:=
# The filter applied to the fat (full) messages to generate split messages
MESSAGES_FILTER=any
# The languages in the fat messages to convert
-MESSAGES_LANGUAGES=de en fr it nl
+MESSAGES_LANGUAGES=de en fr it nl zh_CN
# The target directory for the split messages
MESSAGES_TARGET=resources
-# Defaults for tools
-PERL=perl
-MKDIR=mkdir
-TOUCH=touch
-STRIP?=strip
-SPLIT_MESSAGES=$(PERL) utils/split-messages.pl
-
# build verbosity
ifeq ($(V),1)
Q:=
@@ -147,190 +48,11 @@ else
endif
VQ=@
-# Override this only if the host compiler is called something different
-HOST_CC := gcc
-
-ifeq ($(TARGET),riscos)
- ifeq ($(HOST),riscos)
- # Build for RO on RO
- GCCSDK_INSTALL_ENV := <NSLibs$$Dir>
- CCRES := ccres
- TPLEXT :=
- MAKERUN := makerun
- SQUEEZE := squeeze
- RUNEXT :=
- CC := gcc
- CXX := g++
- EXEEXT :=
- PKG_CONFIG :=
- else
- # Cross-build for RO (either using GCCSDK 3.4.6 - AOF,
- # either using GCCSDK 4 - ELF)
- ifeq ($(origin GCCSDK_INSTALL_ENV),undefined)
- ifneq ($(realpath /opt/netsurf/arm-unknown-riscos/env),)
- GCCSDK_INSTALL_ENV := /opt/netsurf/arm-unknown-riscos/env
- else
- GCCSDK_INSTALL_ENV := /home/riscos/env
- endif
- endif
-
- ifeq ($(origin GCCSDK_INSTALL_CROSSBIN),undefined)
- ifneq ($(realpath /opt/netsurf/arm-unknown-riscos/cross/bin),)
- GCCSDK_INSTALL_CROSSBIN := /opt/netsurf/arm-unknown-riscos/cross/bin
- else
- GCCSDK_INSTALL_CROSSBIN := /home/riscos/cross/bin
- endif
- endif
-
- CCRES := $(GCCSDK_INSTALL_CROSSBIN)/ccres
- TPLEXT := ,fec
- MAKERUN := $(GCCSDK_INSTALL_CROSSBIN)/makerun
- SQUEEZE := $(GCCSDK_INSTALL_CROSSBIN)/squeeze
- RUNEXT := ,feb
- CC := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc)
- ifneq (,$(findstring arm-unknown-riscos-gcc,$(CC)))
- SUBTARGET := -elf
- EXEEXT := ,e1f
- ELF2AIF := $(GCCSDK_INSTALL_CROSSBIN)/elf2aif
- else
- SUBTARGET := -aof
- EXEEXT := ,ff8
- endif
- CXX := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++)
- PKG_CONFIG := $(GCCSDK_INSTALL_ENV)/ro-pkg-config
- endif
-else
- ifeq ($(TARGET),beos)
- # Building for BeOS/Haiku
- #ifeq ($(HOST),beos)
- # Build for BeOS on BeOS
- GCCSDK_INSTALL_ENV := /boot/develop
- CC := gcc
- CXX := g++
- EXEEXT :=
- PKG_CONFIG := pkg-config
- #endif
- else
- ifeq ($(TARGET),windows)
- ifneq ($(HOST),windows)
- # Set Mingw defaults
- GCCSDK_INSTALL_ENV ?= /opt/netsurf/i686-w64-mingw32/env
- GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/i686-w64-mingw32/cross/bin
-
- CC := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc)
- WINDRES := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*windres)
-
- PKG_CONFIG := PKG_CONFIG_LIBDIR="$(GCCSDK_INSTALL_ENV)/lib/pkgconfig" pkg-config
- else
- # Building on Windows
- CC := gcc
- PKG_CONFIG :=
- endif
- else
- ifeq ($(findstring amiga,$(TARGET)),amiga)
- ifeq ($(findstring amiga,$(HOST)),amiga)
- PKG_CONFIG := pkg-config
- else
- ifeq ($(TARGET),amigaos3)
- GCCSDK_INSTALL_ENV ?= /opt/netsurf/m68k-unknown-amigaos/env
- GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/m68k-unknown-amigaos/cross/bin
-
- SUBTARGET = os3
- else
- GCCSDK_INSTALL_ENV ?= /opt/netsurf/ppc-amigaos/env
- GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/ppc-amigaos/cross/bin
- endif
-
- override TARGET := amiga
-
- CC := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc)
-
- PKG_CONFIG := PKG_CONFIG_LIBDIR="$(GCCSDK_INSTALL_ENV)/lib/pkgconfig" pkg-config
- endif
- else
- ifeq ($(TARGET),atari)
- ifeq ($(HOST),atari)
- PKG_CONFIG := pkg-config
- else
- ifeq ($(HOST),mint)
- PKG_CONFIG := pkg-config
- else
- GCCSDK_INSTALL_ENV ?= /opt/netsurf/m68k-atari-mint/env
- GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/m68k-atari-mint/cross/bin
-
- CC := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc)
-
- PKG_CONFIG := PKG_CONFIG_LIBDIR="$(GCCSDK_INSTALL_ENV)/lib/pkgconfig" pkg-config
- endif
- endif
- else
- ifeq ($(TARGET),monkey)
- ifeq ($(origin GCCSDK_INSTALL_ENV),undefined)
- PKG_CONFIG := pkg-config
- else
- PKG_CONFIG := PKG_CONFIG_LIBDIR="$(GCCSDK_INSTALL_ENV)/lib/pkgconfig" pkg-config
- endif
-
- ifneq ($(origin GCCSDK_INSTALL_CROSSBIN),undefined)
- CC := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc)
- CXX := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++)
- endif
- else
- ifeq ($(TARGET),framebuffer)
- ifeq ($(origin GCCSDK_INSTALL_ENV),undefined)
- PKG_CONFIG := pkg-config
- else
- PKG_CONFIG := PKG_CONFIG_LIBDIR="$(GCCSDK_INSTALL_ENV)/lib/pkgconfig" pkg-config
- endif
-
- ifneq ($(origin GCCSDK_INSTALL_CROSSBIN),undefined)
- CC := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc)
- CXX := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++)
- endif
-
- else
- # All native targets
-
- # use native package config
- PKG_CONFIG := pkg-config
-
- # gtk target processing
- ifeq ($(TARGET),gtk3)
- override TARGET := gtk
- override NETSURF_GTK_MAJOR := 3
- SUBTARGET = $(NETSURF_GTK_MAJOR)
- else
- ifeq ($(TARGET),gtk)
- ifeq ($(origin NETSURF_GTK_MAJOR),undefined)
- override NETSURF_GTK_MAJOR := 2
- else
- ifneq ($(NETSURF_GTK_MAJOR),2)
- SUBTARGET = $(NETSURF_GTK_MAJOR)
- endif
- endif
- endif
- endif
- endif
- endif
- endif
- endif
- endif
- endif
-endif
+# compute HOST, TARGET and SUBTARGET
+include frontends/Makefile.hts
-# compiler versioning to adjust warning flags
-CC_VERSION := $(shell $(CC) -dumpversion)
-CC_MAJOR := $(word 1,$(subst ., ,$(CC_VERSION)))
-CC_MINOR := $(word 2,$(subst ., ,$(CC_VERSION)))
-define cc_ver_ge
-$(shell expr $(CC_MAJOR) \>= $(1) \& $(CC_MINOR) \>= $(2))
-endef
-
-# CCACHE
-ifeq ($(origin CCACHE),undefined)
- CCACHE=$(word 1,$(shell ccache -V 2>/dev/null))
-endif
-CC := $(CCACHE) $(CC)
+# tools used in builds
+include Makefile.tools
# Target paths
OBJROOT = build/$(HOST)-$(TARGET)$(SUBTARGET)
@@ -341,142 +63,18 @@ TOOLROOT := $(OBJROOT)/tools
CFLAGS_ENV := $(CFLAGS)
CXXFLAGS_ENV := $(CXXFLAGS)
-# A macro that conditionaly adds flags to the build when a feature is enabled.
-#
-# 1: Feature name (ie, NETSURF_USE_BMP -> BMP)
-# 2: Parameters to add to CFLAGS
-# 3: Parameters to add to LDFLAGS
-# 4: Human-readable name for the feature
-define feature_enabled
- ifeq ($$(NETSURF_USE_$(1)),YES)
- CFLAGS += $(2)
- CXXFLAGS += $(2)
- LDFLAGS += $(3)
- ifneq ($(MAKECMDGOALS),clean)
- $$(info M.CONFIG: $(4) enabled (NETSURF_USE_$(1) := YES))
- endif
- else ifeq ($$(NETSURF_USE_$(1)),NO)
- ifneq ($(MAKECMDGOALS),clean)
- $$(info M.CONFIG: $(4) disabled (NETSURF_USE_$(1) := NO))
- endif
- else
- $$(info M.CONFIG: $(4) error (NETSURF_USE_$(1) := $$(NETSURF_USE_$(1))))
- $$(error NETSURF_USE_$(1) must be YES or NO)
- endif
-endef
-
-# A macro that conditionaly adds flags to the build with a uniform display.
-#
-# 1: Feature name (ie, NETSURF_USE_BMP -> BMP)
-# 2: Human-readable name for the feature
-# 3: Parameters to add to CFLAGS when enabled
-# 4: Parameters to add to LDFLAGS when enabled
-# 5: Parameters to add to CFLAGS when disabled
-# 6: Parameters to add to LDFLAGS when disabled
-define feature_switch
- ifeq ($$(NETSURF_USE_$(1)),YES)
- CFLAGS += $(3)
- CXXFLAGS += $(3)
- LDFLAGS += $(4)
- ifneq ($(MAKECMDGOALS),clean)
- $$(info M.CONFIG: $(2) enabled (NETSURF_USE_$(1) := YES))
- endif
- else ifeq ($$(NETSURF_USE_$(1)),NO)
- CFLAGS += $(5)
- CXXFLAGS += $(5)
- LDFLAGS += $(6)
- ifneq ($(MAKECMDGOALS),clean)
- $$(info M.CONFIG: $(2) disabled (NETSURF_USE_$(1) := NO))
- endif
- else
- $$(info M.CONFIG: $(4) error (NETSURF_USE_$(1) := $$(NETSURF_USE_$(1))))
- $$(error NETSURF_USE_$(1) must be YES or NO)
- endif
-endef
-
-# Extend flags with appropriate values from pkg-config for enabled features
-#
-# 1: pkg-config required modules for feature
-# 2: Human-readable name for the feature
-define pkg_config_find_and_add
- ifeq ($$(PKG_CONFIG),)
- $$(error pkg-config is required to auto-detect feature availability)
- endif
-
- PKG_CONFIG_$(1)_EXISTS := $$(shell $$(PKG_CONFIG) --exists $(1) && echo yes)
-
- ifeq ($$(PKG_CONFIG_$(1)_EXISTS),yes)
- CFLAGS += $$(shell $$(PKG_CONFIG) --cflags $(1))
- CXXFLAGS += $$(shell $$(PKG_CONFIG) --cflags $(1))
- LDFLAGS += $$(shell $$(PKG_CONFIG) --libs $(1))
- ifneq ($(MAKECMDGOALS),clean)
- $$(info PKG.CNFG: $(2) ($(1)) enabled)
- endif
- else
- ifneq ($(MAKECMDGOALS),clean)
- $$(info PKG.CNFG: $(2) ($(1)) failed)
- $$(error Unable to find library for: $(2) ($(1)))
- endif
- endif
-endef
-
-# Extend flags with appropriate values from pkg-config for enabled features
-#
-# 1: Feature name (ie, NETSURF_USE_RSVG -> RSVG)
-# 2: pkg-config required modules for feature
-# 3: Human-readable name for the feature
-define pkg_config_find_and_add_enabled
- ifeq ($$(PKG_CONFIG),)
- $$(error pkg-config is required to auto-detect feature availability)
- endif
-
- NETSURF_FEATURE_$(1)_AVAILABLE := $$(shell $$(PKG_CONFIG) --exists $(2) && echo yes)
-
- ifeq ($$(NETSURF_USE_$(1)),YES)
- ifeq ($$(NETSURF_FEATURE_$(1)_AVAILABLE),yes)
- CFLAGS += $$(shell $$(PKG_CONFIG) --cflags $(2)) $$(NETSURF_FEATURE_$(1)_CFLAGS)
- CXXFLAGS += $$(shell $$(PKG_CONFIG) --cflags $(2)) $$(NETSURF_FEATURE_$(1)_CFLAGS)
- LDFLAGS += $$(shell $$(PKG_CONFIG) --libs $(2)) $$(NETSURF_FEATURE_$(1)_LDFLAGS)
- ifneq ($(MAKECMDGOALS),clean)
- $$(info M.CONFIG: $(3) ($(2)) enabled (NETSURF_USE_$(1) := YES))
- endif
- else
- ifneq ($(MAKECMDGOALS),clean)
- $$(info M.CONFIG: $(3) ($(2)) failed (NETSURF_USE_$(1) := YES))
- $$(error Unable to find library for: $(3) ($(2)))
- endif
- endif
- else ifeq ($$(NETSURF_USE_$(1)),AUTO)
- ifeq ($$(NETSURF_FEATURE_$(1)_AVAILABLE),yes)
- CFLAGS += $$(shell $$(PKG_CONFIG) --cflags $(2)) $$(NETSURF_FEATURE_$(1)_CFLAGS)
- CXXFLAGS += $$(shell $$(PKG_CONFIG) --cflags $(2)) $$(NETSURF_FEATURE_$(1)_CFLAGS)
- LDFLAGS += $$(shell $$(PKG_CONFIG) --libs $(2)) $$(NETSURF_FEATURE_$(1)_LDFLAGS)
- ifneq ($(MAKECMDGOALS),clean)
- $$(info M.CONFIG: $(3) ($(2)) auto-enabled (NETSURF_USE_$(1) := AUTO))
- NETSURF_USE_$(1) := YES
- endif
- else
- ifneq ($(MAKECMDGOALS),clean)
- $$(info M.CONFIG: $(3) ($(2)) auto-disabled (NETSURF_USE_$(1) := AUTO))
- NETSURF_USE_$(1) := NO
- endif
- endif
- else ifeq ($$(NETSURF_USE_$(1)),NO)
- ifneq ($(MAKECMDGOALS),clean)
- $$(info M.CONFIG: $(3) ($(2)) disabled (NETSURF_USE_$(1) := NO))
- endif
- else
- ifneq ($(MAKECMDGOALS),clean)
- $$(info M.CONFIG: $(3) ($(2)) error (NETSURF_USE_$(1) := $$(NETSURF_USE_$(1))))
- $$(error NETSURF_USE_$(1) must be YES, NO, or AUTO)
- endif
- endif
-endef
+# library and feature building macros
+include Makefile.macros
# ----------------------------------------------------------------------------
# General flag setup
# ----------------------------------------------------------------------------
+# host compiler flags
+BUILD_CFLAGS = -g -W -Wall -Wundef -Wpointer-arith -Wcast-align \
+ -Wwrite-strings -Wmissing-declarations -Wuninitialized \
+ -Wno-unused-parameter
+
# Set up the warning flags here so that they can be overridden in the
# Makefile.config
COMMON_WARNFLAGS = -W -Wall -Wundef -Wpointer-arith -Wcast-align \
@@ -491,6 +89,16 @@ ifeq ($(call cc_ver_ge,4,6),1)
COMMON_WARNFLAGS += -Wno-unused-but-set-variable
endif
+ifeq ($(TOOLCHAIN),gcc)
+ # Implicit fallthrough warnings
+ ifeq ($(call cc_ver_ge,7,1),1)
+ COMMON_WARNFLAGS += -Wimplicit-fallthrough=5
+ endif
+else
+ # non gcc has different warning syntax
+ COMMON_WARNFLAGS += -Wimplicit-fallthrough
+endif
+
# deal with chaging warning flags for different platforms
ifeq ($(HOST),OpenBSD)
# OpenBSD headers are not compatible with redundant declaration warning
@@ -521,7 +129,6 @@ $(eval $(call feature_switch,DUKTAPE,Javascript (Duktape),,,,,))
$(eval $(call pkg_config_find_and_add,libcss,CSS))
$(eval $(call pkg_config_find_and_add,libdom,DOM))
$(eval $(call pkg_config_find_and_add,libnsutils,nsutils))
-$(eval $(call pkg_config_find_and_add,libutf8proc,utf8proc))
# Common libraries without pkg-config support
LDFLAGS += -lz
@@ -529,15 +136,10 @@ LDFLAGS += -lz
# Optional libraries with pkgconfig
# define additional CFLAGS and LDFLAGS requirements for pkg-configed libs
-NETSURF_FEATURE_PNG_CFLAGS := -DWITH_PNG
-NETSURF_FEATURE_BMP_CFLAGS := -DWITH_BMP
-NETSURF_FEATURE_GIF_CFLAGS := -DWITH_GIF
-NETSURF_FEATURE_CURL_CFLAGS := -DWITH_CURL
+# We only need to define the ones where the feature name doesn't exactly
+# match the WITH_FEATURE flag
NETSURF_FEATURE_NSSVG_CFLAGS := -DWITH_NS_SVG
-NETSURF_FEATURE_OPENSSL_CFLAGS := -DWITH_OPENSSL
NETSURF_FEATURE_ROSPRITE_CFLAGS := -DWITH_NSSPRITE
-NETSURF_FEATURE_NSPSL_CFLAGS := -DWITH_NSPSL
-NETSURF_FEATURE_NSLOG_CFLAGS := -DWITH_NSLOG
# libcurl and openssl ordering matters as if libcurl requires ssl it
# needs to come first in link order to ensure its symbols can be
@@ -552,6 +154,9 @@ else
endif
$(eval $(call pkg_config_find_and_add_enabled,OPENSSL,openssl,OpenSSL))
+$(eval $(call pkg_config_find_and_add_enabled,UTF8PROC,libutf8proc,utf8))
+$(eval $(call pkg_config_find_and_add_enabled,JPEGXL,libjxl,JPEGXL))
+$(eval $(call pkg_config_find_and_add_enabled,WEBP,libwebp,WEBP))
$(eval $(call pkg_config_find_and_add_enabled,PNG,libpng,PNG))
$(eval $(call pkg_config_find_and_add_enabled,BMP,libnsbmp,BMP))
$(eval $(call pkg_config_find_and_add_enabled,GIF,libnsgif,GIF))
@@ -575,6 +180,25 @@ CXXFLAGS += -DNETSURF_HOMEPAGE=\"$(NETSURF_HOMEPAGE)\"
CFLAGS += -DNETSURF_LOG_LEVEL=$(NETSURF_LOG_LEVEL)
CXXFLAGS += -DNETSURF_LOG_LEVEL=$(NETSURF_LOG_LEVEL)
+# If we're building the sanitize goal, override things
+ifneq ($(filter-out sanitize,$(MAKECMDGOALS)),$(MAKECMDGOALS))
+override NETSURF_USE_SANITIZER := YES
+override NETSURF_RECOVER_SANITIZERS := NO
+endif
+
+# If we're going to use the sanitizer set it up
+ifeq ($(NETSURF_USE_SANITIZER),YES)
+SAN_FLAGS := -fsanitize=address -fsanitize=undefined
+ifeq ($(NETSURF_RECOVER_SANITIZERS),NO)
+SAN_FLAGS += -fno-sanitize-recover
+endif
+else
+SAN_FLAGS :=
+endif
+CFLAGS += $(SAN_FLAGS)
+CXXFLAGS += $(SAN_FLAGS)
+LDFLAGS += $(SAN_FLAGS)
+
# and the logging filter
CFLAGS += -DNETSURF_BUILTIN_LOG_FILTER=\"$(NETSURF_BUILTIN_LOG_FILTER)\"
CXXFLAGS += -DNETSURF_BUILTIN_LOG_FILTER=\"$(NETSURF_BUILTIN_LOG_FILTER)\"
@@ -582,6 +206,17 @@ CXXFLAGS += -DNETSURF_BUILTIN_LOG_FILTER=\"$(NETSURF_BUILTIN_LOG_FILTER)\"
CFLAGS += -DNETSURF_BUILTIN_VERBOSE_FILTER=\"$(NETSURF_BUILTIN_VERBOSE_FILTER)\"
CXXFLAGS += -DNETSURF_BUILTIN_VERBOSE_FILTER=\"$(NETSURF_BUILTIN_VERBOSE_FILTER)\"
+# Determine if the C compiler supports statement expressions
+# This is needed to permit certain optimisations in our library headers
+ifneq ($(shell $(CC) -dM -E - < /dev/null | grep __GNUC__),)
+CFLAGS += -DSTMTEXPR=1
+CXXFLAGS += -DSTMTEXPR=1
+endif
+
+# We trace during link so that we can determine if a libary changes under us in
+# order to re-link. This *may* be gcc specific, so may need tweaks in future.
+LDFLAGS += -Wl,--trace
+
# ----------------------------------------------------------------------------
# General make rules
# ----------------------------------------------------------------------------
@@ -611,15 +246,18 @@ POSTEXES :=
include frontends/Makefile
# ----------------------------------------------------------------------------
+# Build tools setup
+# ----------------------------------------------------------------------------
+
+include tools/Makefile
+
+# ----------------------------------------------------------------------------
# General source file setup
# ----------------------------------------------------------------------------
# Content sources
include content/Makefile
-# render sources
-include render/Makefile
-
# utility sources
include utils/Makefile
@@ -636,7 +274,6 @@ include desktop/Makefile
S_COMMON := \
$(S_CONTENT) \
$(S_FETCHERS) \
- $(S_RENDER) \
$(S_UTILS) \
$(S_HTTP) \
$(S_NSURL) \
@@ -648,20 +285,6 @@ S_COMMON := \
# Message targets
# ----------------------------------------------------------------------------
-# Message splitting rule generation macro
-# 1 = Language
-define split_messages
-
-$$(MESSAGES_TARGET)/$(1)/Messages: resources/FatMessages
- $$(VQ)echo "MSGSPLIT: Language: $(1) Filter: $$(MESSAGES_FILTER)"
- $$(Q)$$(MKDIR) -p $$(MESSAGES_TARGET)/$(1)
- $$(Q)$$(RM) $$@
- $$(Q)$$(SPLIT_MESSAGES) -l $(1) -p $$(MESSAGES_FILTER) -f messages -o $$@ -z $$<
-
-CLEAN_MESSAGES += $$(MESSAGES_TARGET)/$(1)/Messages
-MESSAGES += $$(MESSAGES_TARGET)/$(1)/Messages
-
-endef
# generate the message file rules
$(eval $(foreach LANG,$(MESSAGES_LANGUAGES), \
@@ -689,15 +312,23 @@ OBJECTS := $(sort $(addprefix $(OBJROOT)/,$(subst /,_,$(patsubst %.c,%.o,$(patsu
# Include directory flags
IFLAGS = $(addprefix -I,$(INCLUDE_DIRS))
-$(EXETARGET): $(OBJECTS) $(RESOURCES) $(MESSAGES)
+$(EXETARGET): $(OBJECTS) $(RESOURCES) $(MESSAGES) tools/linktrace-to-depfile.pl
$(VQ)echo " LINK: $(EXETARGET)"
-ifneq ($(TARGET)$(SUBTARGET),riscos-elf)
- $(Q)$(CC) -o $(EXETARGET) $(OBJECTS) $(LDFLAGS)
+ifneq ($(TARGET),riscos)
+ $(Q)$(CC) -o $(EXETARGET) $(OBJECTS) $(LDFLAGS) > $(DEPROOT)/link-raw.d
else
- $(Q)$(CXX) -o $(EXETARGET:,ff8=,e1f) $(OBJECTS) $(LDFLAGS)
+ @# RISC OS targets are a bit special: we need to convert ELF -> AIF
+ ifeq ($(SUBTARGET),-aof)
+ $(Q)$(CC) -o $(EXETARGET) $(OBJECTS) $(LDFLAGS) > $(DEPROOT)/link-raw.d
+ else
+ $(Q)$(CXX) -o $(EXETARGET:,ff8=,e1f) $(OBJECTS) $(LDFLAGS) > $(DEPROOT)/link-raw.d
$(Q)$(ELF2AIF) $(EXETARGET:,ff8=,e1f) $(EXETARGET)
$(Q)$(RM) $(EXETARGET:,ff8=,e1f)
+ endif
endif
+ $(VQ)echo "LINKDEPS: $(EXETARGET)"
+ $(Q)echo -n "$(EXETARGET) $(DEPROOT)/link.d: " > $(DEPROOT)/link.d
+ $(Q)$(PERL) tools/linktrace-to-depfile.pl < $(DEPROOT)/link-raw.d >> $(DEPROOT)/link.d
ifeq ($(NETSURF_STRIP_BINARY),YES)
$(VQ)echo " STRIP: $(EXETARGET)"
$(Q)$(STRIP) $(EXETARGET)
@@ -709,21 +340,16 @@ ifeq ($(TARGET),beos)
$(Q)$(BEOS_SETVER) $(EXETARGET) \
-app $(VERSION_MAJ) $(VERSION_MIN) 0 d 0 \
-short "NetSurf $(VERSION_FULL)" \
- -long "NetSurf $(VERSION_FULL) © 2003 - 2016 The NetSurf Developers"
+ -long "NetSurf $(VERSION_FULL) © 2003 - 2021 The NetSurf Developers"
$(VQ)echo " MIMESET: $(EXETARGET)"
$(Q)$(BEOS_MIMESET) $(EXETARGET)
endif
-
clean-target:
$(VQ)echo " CLEAN: $(EXETARGET)"
$(Q)$(RM) $(EXETARGET)
CLEANS += clean-target
-clean-testament:
- $(VQ)echo " CLEAN: testament.h"
- $(Q)$(RM) $(OBJROOT)/testament.h
-CLEANS += clean-testament
clean-builddir:
$(VQ)echo " CLEAN: $(OBJROOT)"
@@ -731,89 +357,13 @@ clean-builddir:
CLEANS += clean-builddir
-.PHONY: all-program testament
-
-testament $(OBJROOT)/testament.h:
- $(Q)$(PERL) utils/git-testament.pl $(CURDIR) $(OBJROOT)/testament.h
+.PHONY: all-program
all-program: $(EXETARGET) $(POSTEXES)
.SUFFIXES:
DEPFILES :=
-# Now some macros which build the make system
-
-# 1 = Source file
-# 2 = dep filename, no prefix
-# 3 = obj filename, no prefix
-define dependency_generate_c
-DEPFILES += $(2)
-
-endef
-
-# 1 = Source file
-# 2 = dep filename, no prefix
-# 3 = obj filename, no prefix
-define dependency_generate_s
-DEPFILES += $(2)
-
-endef
-
-# 1 = Source file
-# 2 = obj filename, no prefix
-# 3 = dep filename, no prefix
-ifeq ($(CC_MAJOR),2)
-# simpler deps tracking for gcc2...
-define compile_target_c
-$$(OBJROOT)/$(2): $(1) $$(OBJROOT)/created $$(DEPROOT)/created
- $$(VQ)echo " DEP: $(1)"
- $$(Q)$$(RM) $$(DEPROOT)/$(3)
- $$(Q)$$(CC) $$(IFLAGS) $$(CFLAGS) -MM \
- $(1) | sed 's,^.*:,$$(DEPROOT)/$(3) $$(OBJROOT)/$(2):,' \
- > $$(DEPROOT)/$(3)
- $$(VQ)echo " COMPILE: $(1)"
- $$(Q)$$(RM) $$(OBJROOT)/$(2)
- $$(Q)$$(CC) $$(COMMON_WARNFLAGS) $$(CWARNFLAGS) $$(IFLAGS) $$(CFLAGS) $(CFLAGS_ENV) -o $$(OBJROOT)/$(2) -c $(1)
-
-endef
-else
-define compile_target_c
-$$(OBJROOT)/$(2): $(1) $$(OBJROOT)/created $$(DEPROOT)/created
- $$(VQ)echo " COMPILE: $(1)"
- $$(Q)$$(RM) $$(DEPROOT)/$(3)
- $$(Q)$$(RM) $$(OBJROOT)/$(2)
- $$(Q)$$(CC) $$(COMMON_WARNFLAGS) $$(CWARNFLAGS) $$(IFLAGS) $$(CFLAGS) $(CFLAGS_ENV) \
- -MMD -MT '$$(DEPROOT)/$(3) $$(OBJROOT)/$(2)' \
- -MF $$(DEPROOT)/$(3) -o $$(OBJROOT)/$(2) -c $(1)
-
-endef
-endif
-
-define compile_target_cpp
-$$(OBJROOT)/$(2): $(1) $$(OBJROOT)/created $$(DEPROOT)/created
- $$(VQ)echo " DEP: $(1)"
- $$(Q)$$(RM) $$(DEPROOT)/$(3)
- $$(Q)$$(CC) $$(IFLAGS) $$(CXXFLAGS) $$(COMMON_WARNFLAGS) $$(CXXWARNFLAGS) -MM \
- $(1) | sed 's,^.*:,$$(DEPROOT)/$(3) $$(OBJROOT)/$(2):,' \
- > $$(DEPROOT)/$(3)
- $$(VQ)echo " COMPILE: $(1)"
- $$(Q)$$(RM) $$(OBJROOT)/$(2)
- $$(Q)$$(CXX) $$(COMMON_WARNFLAGS) $$(CXXWARNFLAGS) $$(IFLAGS) $$(CXXFLAGS) $(CXXFLAGS_ENV) -o $$(OBJROOT)/$(2) -c $(1)
-
-endef
-
-# 1 = Source file
-# 2 = obj filename, no prefix
-# 3 = dep filename, no prefix
-define compile_target_s
-$$(OBJROOT)/$(2): $(1) $$(OBJROOT)/created $$(DEPROOT)/created
- $$(VQ)echo "ASSEMBLE: $(1)"
- $$(Q)$$(RM) $$(DEPROOT)/$(3)
- $$(Q)$$(RM) $$(OBJROOT)/$(2)
- $$(Q)$$(CC) $$(ASFLAGS) -MMD -MT '$$(DEPROOT)/$(3) $$(OBJROOT)/$(2)' \
- -MF $$(DEPROOT)/$(3) -o $$(OBJROOT)/$(2) -c $(1)
-
-endef
# Rules to construct dep lines for each object...
$(eval $(foreach SOURCE,$(filter %.c,$(SOURCES)), \
@@ -833,6 +383,7 @@ $(eval $(foreach SOURCE,$(filter %.m,$(SOURCES)), \
ifeq ($(filter $(MAKECMDGOALS),clean test coverage),)
-include $(sort $(addprefix $(DEPROOT)/,$(DEPFILES)))
+-include $(DEPROOT)/link.d
endif
# And rules to build the objects themselves...
diff --git a/Makefile.config.example b/Makefile.config.example
index aeddc1071..988fd0ac8 100644
--- a/Makefile.config.example
+++ b/Makefile.config.example
@@ -33,3 +33,19 @@
### To change flags to javascript binding generator
# GBFLAGS:=-g
+
+### To enable ASAN and UBSAN support in builds regardless of target
+# override NETSURF_USE_SANITIZER := YES
+
+### If you're using the sanitizers and you want it to stop on failure...
+# override NETSURF_RECOVER_SANITIZERS := NO
+
+### To change the compiled in log level, alter this.
+# Valid options are: DEEPDEBUG, DEBUG, VERBOSE, INFO, WARNING, ERROR, CRITICAL
+# override NETSURF_LOG_LEVEL := DEBUG
+
+### To change the compiled in default log, change this
+# override NETSURF_BUILTIN_LOG_FILTER := "(level:WARNING || cat:jserrors)"
+
+### To change the compiled in *verbose* log, change this
+# override NETSURF_BUILTIN_VERBOSE_FILTER := "(level:VERBOSE || cat:jserrors)"
diff --git a/Makefile.defaults b/Makefile.defaults
index 1f9ce5fdf..bbff68814 100644
--- a/Makefile.defaults
+++ b/Makefile.defaults
@@ -32,33 +32,41 @@
# ----------------------------------------------------------------------------
# Enable NetSurf's use of libcurl for fetching over http(s)
-# Valid options: YES, NO (highly recommended)
+# Valid options: YES, NO, AUTO (highly recommended)
NETSURF_USE_CURL := YES
-# Enable NetSurf's use of openssl for fetching over https
-# Valid options: YES, NO
-NETSURF_USE_OPENSSL := YES
+# Enable NetSurf's use of openssl for processing certificates
+# Valid options: YES, NO, AUTO
+NETSURF_USE_OPENSSL := AUTO
# Enable NetSurf's use of libnsbmp for displaying BMPs and ICOs
-# Valid options: YES, NO
-NETSURF_USE_BMP := YES
+# Valid options: YES, NO, AUTO
+NETSURF_USE_BMP := AUTO
# Enable NetSurf's use of libnsgif for displaying GIFs
-# Valid options: YES, NO (highly recommended)
-NETSURF_USE_GIF := YES
+# Valid options: YES, NO, AUTO (highly recommended)
+NETSURF_USE_GIF := AUTO
# Enable NetSurf's use of libjpeg for displaying JPEGs
# Valid options: YES, NO (highly recommended)
NETSURF_USE_JPEG := YES
+# Enable NetSurf's use of libjxl for displaying JPEGXLs
+# Valid options: YES, NO, AUTO (highly recommended)
+NETSURF_USE_JPEGXL := AUTO
+
# Enable NetSurf's use of libpng for displaying PNGs.
-# Valid options: YES, NO (highly recommended)
-NETSURF_USE_PNG := YES
+# Valid options: YES, NO, AUTO (highly recommended)
+NETSURF_USE_PNG := AUTO
# Enable NetSurf's use of gstreamer for displaying videos
# Valid options: YES, NO
NETSURF_USE_VIDEO := NO
+# Enable NetSurf's use of libwebp for displaying WEBPs.
+# Valid options: YES, NO, AUTO
+NETSURF_USE_WEBP := AUTO
+
# Enable NetSurf's use of duktape for javascript
# Valid options: YES, NO
NETSURF_USE_DUKTAPE := YES
@@ -78,21 +86,30 @@ NETSURF_USE_NSPSL := AUTO
NETSURF_USE_NSLOG := AUTO
# The minimum logging level *compiled* into netsurf
# Valid options are: DEEPDEBUG, DEBUG, VERBOSE, INFO, WARNING, ERROR, CRITICAL
-NETSURF_LOG_LEVEL := INFO
+NETSURF_LOG_LEVEL := VERBOSE
# The log filter set during log initialisation before options are available
-NETSURF_BUILTIN_LOG_FILTER := level:WARNING
+NETSURF_BUILTIN_LOG_FILTER := "(level:WARNING || cat:jserrors)"
# The log filter set during log initialisation before options are available
# if the logging level is set to verbose
-NETSURF_BUILTIN_VERBOSE_FILTER := level:VERBOSE
+NETSURF_BUILTIN_VERBOSE_FILTER := "(level:VERBOSE || cat:jserrors)"
+
+# Force using glibc internal iconv implementation instead of external libiconv
+# Valid options: YES, NO
+NETSURF_USE_LIBICONV_PLUG := YES
+
+# Enable use of utf8proc for international domain name processing
+# Valid options: YES, NO, AUTO (highly recommended)
+NETSURF_USE_UTF8PROC := YES
# Enable stripping the NetSurf binary
# Valid options: YES, NO
NETSURF_STRIP_BINARY := NO
-# Template used for constructing the User Agent: string. The first two
-# replacements are major/minor version, next is OS.
-# Please don't be tempted to mention Mozilla here! Let's let that lie die.
-NETSURF_UA_FORMAT_STRING := "NetSurf/%d.%d (%s)"
+# Template used for constructing the User Agent: string. The first
+# replacement is OS, the next two are major/minor version.
+# Note that the "Mozilla/5.0" prefix is a requirement to enable modern
+# web standards on many websites. It should not be removed or modified.
+NETSURF_UA_FORMAT_STRING := "Mozilla/5.0 (%s) NetSurf/%d.%d"
# Default home page, if one is not defined by the user. Note that this
# option does not apply to the RISC OS version, as it has its own local
@@ -100,15 +117,16 @@ NETSURF_UA_FORMAT_STRING := "NetSurf/%d.%d (%s)"
# riscos/gui.c
NETSURF_HOMEPAGE := "about:welcome"
-# Force using glibc internal iconv implementation instead of external libiconv
-# Valid options: YES, NO
-NETSURF_USE_LIBICONV_PLUG := YES
-
# Enable building the source object cache filesystem based backing store.
# implementation.
# Valid options: YES, NO
NETSURF_FS_BACKING_STORE := NO
+# Enable the ASAN and UBSAN flags regardless of targets
+NETSURF_USE_SANITIZERS := NO
+# But recover after sanitizer failure
+NETSURF_RECOVER_SANITIZERS := YES
+
# Initial CFLAGS. Optimisation level etc. tend to be target specific.
CFLAGS :=
diff --git a/Makefile.macros b/Makefile.macros
new file mode 100644
index 000000000..9421acfa2
--- /dev/null
+++ b/Makefile.macros
@@ -0,0 +1,249 @@
+# -*- mode: makefile-gmake -*-
+##
+## Netsurf library and feature macros
+##
+
+# A macro that conditionaly adds flags to the build when a feature is enabled.
+#
+# 1: Feature name (ie, NETSURF_USE_BMP -> BMP)
+# 2: Parameters to add to CFLAGS
+# 3: Parameters to add to LDFLAGS
+# 4: Human-readable name for the feature
+define feature_enabled
+ ifeq ($$(NETSURF_USE_$(1)),YES)
+ CFLAGS += $(2)
+ CXXFLAGS += $(2)
+ LDFLAGS += $(3)
+ ifneq ($(MAKECMDGOALS),clean)
+ $$(info M.CONFIG: $(4) enabled (NETSURF_USE_$(1) := YES))
+ endif
+ else ifeq ($$(NETSURF_USE_$(1)),NO)
+ ifneq ($(MAKECMDGOALS),clean)
+ $$(info M.CONFIG: $(4) disabled (NETSURF_USE_$(1) := NO))
+ endif
+ else
+ $$(info M.CONFIG: $(4) error (NETSURF_USE_$(1) := $$(NETSURF_USE_$(1))))
+ $$(error NETSURF_USE_$(1) must be YES or NO)
+ endif
+endef
+
+
+# A macro that conditionaly adds flags to the build with a uniform display.
+#
+# 1: Feature name (ie, NETSURF_USE_BMP -> BMP)
+# 2: Human-readable name for the feature
+# 3: Parameters to add to CFLAGS when enabled
+# 4: Parameters to add to LDFLAGS when enabled
+# 5: Parameters to add to CFLAGS when disabled
+# 6: Parameters to add to LDFLAGS when disabled
+define feature_switch
+ ifeq ($$(NETSURF_USE_$(1)),YES)
+ CFLAGS += $(3)
+ CXXFLAGS += $(3)
+ LDFLAGS += $(4)
+ ifneq ($(MAKECMDGOALS),clean)
+ $$(info M.CONFIG: $(2) enabled (NETSURF_USE_$(1) := YES))
+ endif
+ else ifeq ($$(NETSURF_USE_$(1)),NO)
+ CFLAGS += $(5)
+ CXXFLAGS += $(5)
+ LDFLAGS += $(6)
+ ifneq ($(MAKECMDGOALS),clean)
+ $$(info M.CONFIG: $(2) disabled (NETSURF_USE_$(1) := NO))
+ endif
+ else
+ $$(info M.CONFIG: $(4) error (NETSURF_USE_$(1) := $$(NETSURF_USE_$(1))))
+ $$(error NETSURF_USE_$(1) must be YES or NO)
+ endif
+endef
+
+
+# Extend flags with appropriate values from pkg-config for enabled features
+#
+# 1: pkg-config required modules for feature
+# 2: Human-readable name for the feature
+define pkg_config_find_and_add
+ ifeq ($$(PKG_CONFIG),)
+ $$(error pkg-config is required to auto-detect feature availability)
+ endif
+
+ PKG_CONFIG_$(1)_EXISTS := $$(shell $$(PKG_CONFIG) --exists $(1) && echo yes)
+
+ ifeq ($$(PKG_CONFIG_$(1)_EXISTS),yes)
+ CFLAGS += $$(shell $$(PKG_CONFIG) --cflags $(1))
+ CXXFLAGS += $$(shell $$(PKG_CONFIG) --cflags $(1))
+ LDFLAGS += $$(shell $$(PKG_CONFIG) --libs $(1))
+ ifneq ($(MAKECMDGOALS),clean)
+ $$(info PKG.CNFG: $(2) ($(1)) enabled)
+ endif
+ else
+ ifneq ($(MAKECMDGOALS),clean)
+ $$(info PKG.CNFG: $(2) ($(1)) failed)
+ $$(error Unable to find library for: $(2) ($(1)))
+ endif
+ endif
+endef
+
+
+# Extend flags with appropriate values from pkg-config for enabled features
+#
+# 1: Feature name (ie, NETSURF_USE_RSVG -> RSVG)
+# 2: pkg-config required modules for feature
+# 3: Human-readable name for the feature
+define pkg_config_find_and_add_enabled
+ ifeq ($$(PKG_CONFIG),)
+ $$(error pkg-config is required to auto-detect feature availability)
+ endif
+
+ NETSURF_FEATURE_$(1)_AVAILABLE := $$(shell $$(PKG_CONFIG) --exists $(2) && echo yes)
+ NETSURF_FEATURE_$(1)_CFLAGS ?= -DWITH_$(1)
+
+ ifeq ($$(NETSURF_USE_$(1)),YES)
+ ifeq ($$(NETSURF_FEATURE_$(1)_AVAILABLE),yes)
+ CFLAGS += $$(shell $$(PKG_CONFIG) --cflags $(2)) $$(NETSURF_FEATURE_$(1)_CFLAGS)
+ CXXFLAGS += $$(shell $$(PKG_CONFIG) --cflags $(2)) $$(NETSURF_FEATURE_$(1)_CFLAGS)
+ LDFLAGS += $$(shell $$(PKG_CONFIG) --libs $(2)) $$(NETSURF_FEATURE_$(1)_LDFLAGS)
+ ifneq ($(MAKECMDGOALS),clean)
+ $$(info M.CONFIG: $(3) ($(2)) enabled (NETSURF_USE_$(1) := YES))
+ endif
+ else
+ ifneq ($(MAKECMDGOALS),clean)
+ $$(info M.CONFIG: $(3) ($(2)) failed (NETSURF_USE_$(1) := YES))
+ $$(error Unable to find library for: $(3) ($(2)))
+ endif
+ endif
+ else ifeq ($$(NETSURF_USE_$(1)),AUTO)
+ ifeq ($$(NETSURF_FEATURE_$(1)_AVAILABLE),yes)
+ CFLAGS += $$(shell $$(PKG_CONFIG) --cflags $(2)) $$(NETSURF_FEATURE_$(1)_CFLAGS)
+ CXXFLAGS += $$(shell $$(PKG_CONFIG) --cflags $(2)) $$(NETSURF_FEATURE_$(1)_CFLAGS)
+ LDFLAGS += $$(shell $$(PKG_CONFIG) --libs $(2)) $$(NETSURF_FEATURE_$(1)_LDFLAGS)
+ ifneq ($(MAKECMDGOALS),clean)
+ $$(info M.CONFIG: $(3) ($(2)) auto-enabled (NETSURF_USE_$(1) := AUTO))
+ NETSURF_USE_$(1) := YES
+ endif
+ else
+ ifneq ($(MAKECMDGOALS),clean)
+ $$(info M.CONFIG: $(3) ($(2)) auto-disabled (NETSURF_USE_$(1) := AUTO))
+ NETSURF_USE_$(1) := NO
+ endif
+ endif
+ else ifeq ($$(NETSURF_USE_$(1)),NO)
+ ifneq ($(MAKECMDGOALS),clean)
+ $$(info M.CONFIG: $(3) ($(2)) disabled (NETSURF_USE_$(1) := NO))
+ endif
+ else
+ ifneq ($(MAKECMDGOALS),clean)
+ $$(info M.CONFIG: $(3) ($(2)) error (NETSURF_USE_$(1) := $$(NETSURF_USE_$(1))))
+ $$(error NETSURF_USE_$(1) must be YES, NO, or AUTO)
+ endif
+ endif
+endef
+
+
+# Message splitting rule generation macro
+#
+# 1 = Language
+define split_messages
+
+$$(MESSAGES_TARGET)/$(1)/Messages: resources/FatMessages $$(TOOLROOT)/split-messages
+ $$(VQ)echo "MSGSPLIT: Language: $(1) Filter: $$(MESSAGES_FILTER)"
+ $$(Q)$$(MKDIR) -p $$(MESSAGES_TARGET)/$(1)
+ $$(Q)$$(RM) $$@
+ $$(Q)$$(TOOLROOT)/split-messages -l $(1) -p $$(MESSAGES_FILTER) -f messages -o $$@ -z $$<
+
+CLEAN_MESSAGES += $$(MESSAGES_TARGET)/$(1)/Messages
+MESSAGES += $$(MESSAGES_TARGET)/$(1)/Messages
+
+endef
+
+
+# Now some macros which build the make system
+
+# Extend dependancy files for c source files
+#
+# 1 = Source file
+# 2 = dep filename, no prefix
+# 3 = obj filename, no prefix
+define dependency_generate_c
+DEPFILES += $(2)
+
+endef
+
+
+# Extend dependancy files for s source files
+#
+# 1 = Source file
+# 2 = dep filename, no prefix
+# 3 = obj filename, no prefix
+define dependency_generate_s
+DEPFILES += $(2)
+
+endef
+
+
+# Rule generator to compile c files
+#
+# 1 = Source file
+# 2 = obj filename, no prefix
+# 3 = dep filename, no prefix
+ifeq ($(CC_MAJOR),2)
+# simpler deps tracking for gcc2...
+define compile_target_c
+$$(OBJROOT)/$(2): $(1) $$(OBJROOT)/created $$(DEPROOT)/created
+ $$(VQ)echo " DEP: $(1)"
+ $$(Q)$$(RM) $$(DEPROOT)/$(3)
+ $$(Q)$$(CC) $$(IFLAGS) $$(CFLAGS) -MM \
+ $(1) | sed 's,^.*:,$$(DEPROOT)/$(3) $$(OBJROOT)/$(2):,' \
+ > $$(DEPROOT)/$(3)
+ $$(VQ)echo " COMPILE: $(1)"
+ $$(Q)$$(RM) $$(OBJROOT)/$(2)
+ $$(Q)$$(CC) $$(COMMON_WARNFLAGS) $$(CWARNFLAGS) $$(IFLAGS) $$(CFLAGS) $(CFLAGS_ENV) -o $$(OBJROOT)/$(2) -c $(1)
+
+endef
+else
+define compile_target_c
+$$(OBJROOT)/$(2): $(1) $$(OBJROOT)/created $$(DEPROOT)/created
+ $$(VQ)echo " COMPILE: $(1)"
+ $$(Q)$$(RM) $$(DEPROOT)/$(3)
+ $$(Q)$$(RM) $$(OBJROOT)/$(2)
+ $$(Q)$$(CC) $$(COMMON_WARNFLAGS) $$(CWARNFLAGS) $$(IFLAGS) $$(CFLAGS) $(CFLAGS_ENV) \
+ -MMD -MP -MT '$$(DEPROOT)/$(3) $$(OBJROOT)/$(2)' \
+ -MF $$(DEPROOT)/$(3) -o $$(OBJROOT)/$(2) -c $(1)
+
+endef
+endif
+
+
+# Rule generator to compile cpp files
+#
+# 1 = Source file
+# 2 = obj filename, no prefix
+# 3 = dep filename, no prefix
+define compile_target_cpp
+$$(OBJROOT)/$(2): $(1) $$(OBJROOT)/created $$(DEPROOT)/created
+ $$(VQ)echo " DEP: $(1)"
+ $$(Q)$$(RM) $$(DEPROOT)/$(3)
+ $$(Q)$$(CC) $$(IFLAGS) $$(CXXFLAGS) $$(COMMON_WARNFLAGS) $$(CXXWARNFLAGS) -MM \
+ $(1) | sed 's,^.*:,$$(DEPROOT)/$(3) $$(OBJROOT)/$(2):,' \
+ > $$(DEPROOT)/$(3)
+ $$(VQ)echo " COMPILE: $(1)"
+ $$(Q)$$(RM) $$(OBJROOT)/$(2)
+ $$(Q)$$(CXX) $$(COMMON_WARNFLAGS) $$(CXXWARNFLAGS) $$(IFLAGS) $$(CXXFLAGS) $(CXXFLAGS_ENV) -o $$(OBJROOT)/$(2) -c $(1)
+
+endef
+
+
+# Rule generator to compile s files
+#
+# 1 = Source file
+# 2 = obj filename, no prefix
+# 3 = dep filename, no prefix
+define compile_target_s
+$$(OBJROOT)/$(2): $(1) $$(OBJROOT)/created $$(DEPROOT)/created
+ $$(VQ)echo "ASSEMBLE: $(1)"
+ $$(Q)$$(RM) $$(DEPROOT)/$(3)
+ $$(Q)$$(RM) $$(OBJROOT)/$(2)
+ $$(Q)$$(CC) $$(ASFLAGS) -MMD -MT '$$(DEPROOT)/$(3) $$(OBJROOT)/$(2)' \
+ -MF $$(DEPROOT)/$(3) -o $$(OBJROOT)/$(2) -c $(1)
+
+endef
diff --git a/Makefile.tools b/Makefile.tools
new file mode 100644
index 000000000..3226d13b0
--- /dev/null
+++ b/Makefile.tools
@@ -0,0 +1,118 @@
+# -*- mode: makefile-gmake -*-
+##
+## Setup tools to build project including compiler
+##
+
+# Expected inputs:
+#
+# HOST
+# TARGET
+# SUBTARGET
+#
+# output:
+# variables:
+# CC
+# BUILD_CC
+# CCACHE
+# TOOLCHAIN
+# PERL
+# MKDIR
+# TOUCH
+# STRIP
+# INSTALL
+# CC_VERSION
+# CC_MAJOR
+# CC_MINOR
+#
+# macros:
+# cc_ver_ge
+
+# Defaults for tools
+PERL=perl
+MKDIR=mkdir
+TOUCH=touch
+STRIP?=strip
+INSTALL?=install
+# Override this only if the host compiler is called something different
+BUILD_CC := cc
+
+# target specific tool overrides
+include frontends/$(TARGET)/Makefile.tools
+
+# CCACHE
+ifeq ($(origin CCACHE),undefined)
+ CCACHE=$(word 1,$(shell ccache -V 2>/dev/null))
+endif
+CC := $(CCACHE) $(CC)
+
+###############################################################################
+# Auto-detect the toolchain
+###############################################################################
+
+# Check for GCC first, as that's most likely
+# TODO: Using shell redirection like this probably hurts portability
+CC_SPECS := $(shell $(CC) -dumpspecs 2>&1)
+ifeq ($(findstring libgcc,$(CC_SPECS)),libgcc)
+ # Looks like GCC
+ TOOLCHAIN := gcc
+else
+ # Not GCC, so enquire further
+ ccvsn := $(shell $(CC) --version 2>&1)
+ ifeq ($(ccvsn),)
+ # Version string is blank
+ ifeq ($(BUILD),arm-unknown-riscos)
+ # For some reason we never see the output of SCL apps, so might be
+ # Norcroft. However it might also be a GCC linked against a buggy
+ # UnixLib.
+ # TODO: Something more useful than blindly assuming GCC.
+ ccvsn := GCC
+ # ccvsn := Norcroft
+ endif
+ endif
+
+ ifeq ($(findstring lcc:,$(ccvsn)),lcc:)
+ # MCST LCC pretends to be gcc
+ TOOLCHAIN := gcc
+ endif
+
+ # "Norcroft ..."
+ ifeq ($(word 1,$(ccvsn)),Norcroft)
+ TOOLCHAIN := norcroft
+ endif
+ # "GCC ..."
+ ifeq ($(word 1,$(ccvsn)),GCC)
+ TOOLCHAIN := gcc
+ endif
+ # "clang ..."
+ ifeq ($(word 1,$(ccvsn)),clang)
+ TOOLCHAIN := clang
+ endif
+ ifeq ($(word 2,$(ccvsn)),clang)
+ # Some newer clangs have distributor as first word
+ # (ie, Debian, Apple, etc)
+ TOOLCHAIN := clang
+ endif
+ ifeq ($(word 2,$(ccvsn)),LLVM)
+ # Apple version is "Apple LLVM" to be differntly awkward
+ TOOLCHAIN := clang
+ endif
+ ifeq ($(word 1,$(ccvsn)),Open64)
+ TOOLCHAIN := open64
+ endif
+endif
+
+ifeq ($(TOOLCHAIN),)
+ $(error Unable to detect toolchain)
+endif
+
+
+###############################################################################
+# Compiler Versioning (to adjust warning flags)
+###############################################################################
+
+CC_VERSION := $(shell $(CC) -dumpfullversion -dumpversion)
+CC_MAJOR := $(word 1,$(subst ., ,$(CC_VERSION)))
+CC_MINOR := $(word 2,$(subst ., ,$(CC_VERSION)))
+define cc_ver_ge
+$(shell expr $(CC_MAJOR) \> $(1) \| \( $(CC_MAJOR) = $(1) \& $(CC_MINOR) \>= $(2) \) )
+endef
diff --git a/README b/README
deleted file mode 100644
index f983b9e27..000000000
--- a/README
+++ /dev/null
@@ -1,40 +0,0 @@
---------------------------------------------------------------------------------
- NetSurf README
---------------------------------------------------------------------------------
-
- This document should help point you at various useful bits of information.
-
-
- Building NetSurf
-==================
-
- Read the QUICK-START document in the Docs/ directory for instructions.
-
-
- Creating a new port
-=====================
-
- Look at the existing front ends for example implementations. The framebuffer
- front end is simplest and most self-contained. Also, you can contact the
- developers for help:
-
- http://www.netsurf-browser.org/contact/
-
- Check out the developer documentation sources listed below too.
-
-
- Further documentation
-=======================
-
- The Developer section of the web site has loads of info to get you started:
-
- http://www.netsurf-browser.org/developers/
-
- General documentation on how NetSurf's code works can be found on the
- development wiki:
-
- http://wiki.netsurf-browser.org/Documentation/
-
- The code style guide is here:
-
- http://www.netsurf-browser.org/developers/StyleGuide.pdf
diff --git a/README.md b/README.md
new file mode 100644
index 000000000..8f3843042
--- /dev/null
+++ b/README.md
@@ -0,0 +1,27 @@
+NetSurf
+=======
+
+This document should help point you at various useful bits of information.
+
+
+Building NetSurf
+----------------
+
+Read the [Quick Start](docs/quick-start.md) document for instructions.
+
+
+Creating a new port
+-------------------
+
+Look at the existing front ends for example implementations.
+The framebuffer front end is simplest and most self-contained.
+Also, you can [contact the developers](https://www.netsurf-browser.org/contact/)
+for help.
+
+
+Further documentation
+---------------------
+
+* [Developer documentation](https://www.netsurf-browser.org/developers/)
+* [Developer wiki](https://wiki.netsurf-browser.org/Documentation/)
+* [Code style guide](https://www.netsurf-browser.org/developers/StyleGuide.pdf)
diff --git a/content/Makefile b/content/Makefile
index b4353ba95..188d0f46e 100644
--- a/content/Makefile
+++ b/content/Makefile
@@ -1,7 +1,15 @@
# Content sources
-S_CONTENT := content.c content_factory.c dirlist.c fetch.c hlcache.c \
- llcache.c mimesniff.c urldb.c no_backing_store.c
+S_CONTENT := \
+ content.c \
+ content_factory.c \
+ fetch.c \
+ hlcache.c \
+ llcache.c \
+ mimesniff.c \
+ textsearch.c \
+ urldb.c \
+ no_backing_store.c
# Make filesystem backing store available
ifeq ($(NETSURF_FS_BACKING_STORE),YES)
@@ -9,10 +17,12 @@ ifeq ($(NETSURF_FS_BACKING_STORE),YES)
endif
-# Content fetchers sources
+# Content fetcher sources
include content/fetchers/Makefile
-# Content handlers
+S_FETCHERS := $(addprefix content/,$(S_FETCHERS))
+
+# Content handler sources
include content/handlers/Makefile
S_CONTENT := $(addprefix content/,$(S_CONTENT))
diff --git a/content/content.c b/content/content.c
index 9a240417d..ae4718f54 100644
--- a/content/content.c
+++ b/content/content.c
@@ -23,20 +23,23 @@
#include <stdint.h>
#include <stdlib.h>
+#include <string.h>
#include <nsutils/time.h>
#include "netsurf/inttypes.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/corestrings.h"
#include "netsurf/browser_window.h"
#include "netsurf/bitmap.h"
#include "netsurf/content.h"
#include "desktop/knockout.h"
-#include "desktop/gui_internal.h"
#include "content/content_protected.h"
+#include "content/textsearch.h"
#include "content/content_debug.h"
#include "content/hlcache.h"
+#include "content/urldb.h"
#define URL_FMT_SPC "%.140s"
@@ -47,84 +50,48 @@ const char * const content_status_name[] = {
"ERROR"
};
-static nserror content_llcache_callback(llcache_handle *llcache,
- const llcache_event *event, void *pw);
-static void content_convert(struct content *c);
-
/**
- * Initialise a new content structure.
+ * All data has arrived, convert for display.
*
- * \param c Content to initialise
- * \param handler Content handler
- * \param imime_type MIME type of content
- * \param params HTTP parameters
- * \param llcache Source data handle
- * \param fallback_charset Fallback charset
- * \param quirks Quirkiness of content
- * \return NSERROR_OK on success, appropriate error otherwise
+ * Calls the convert function for the content.
+ *
+ * - If the conversion succeeds, but there is still some processing required
+ * (eg. loading images), the content gets status CONTENT_STATUS_READY, and a
+ * CONTENT_MSG_READY is sent to all users.
+ * - If the conversion succeeds and is complete, the content gets status
+ * CONTENT_STATUS_DONE, and CONTENT_MSG_READY then CONTENT_MSG_DONE are sent.
+ * - If the conversion fails, CONTENT_MSG_ERROR is sent. The content will soon
+ * be destroyed and must no longer be used.
*/
-
-nserror content__init(struct content *c, const content_handler *handler,
- lwc_string *imime_type, const struct http_parameter *params,
- llcache_handle *llcache, const char *fallback_charset,
- bool quirks)
+static void content_convert(struct content *c)
{
- struct content_user *user_sentinel;
- nserror error;
-
- NSLOG(netsurf, INFO, "url "URL_FMT_SPC" -> %p",
- nsurl_access(llcache_handle_get_url(llcache)), c);
-
- user_sentinel = calloc(1, sizeof(struct content_user));
- if (user_sentinel == NULL) {
- return NSERROR_NOMEM;
- }
+ assert(c);
+ assert(c->status == CONTENT_STATUS_LOADING ||
+ c->status == CONTENT_STATUS_ERROR);
- if (fallback_charset != NULL) {
- c->fallback_charset = strdup(fallback_charset);
- if (c->fallback_charset == NULL) {
- free(user_sentinel);
- return NSERROR_NOMEM;
- }
- }
+ if (c->status != CONTENT_STATUS_LOADING)
+ return;
- c->llcache = llcache;
- c->mime_type = lwc_string_ref(imime_type);
- c->handler = handler;
- c->status = CONTENT_STATUS_LOADING;
- c->width = 0;
- c->height = 0;
- c->available_width = 0;
- c->quirks = quirks;
- c->refresh = 0;
- nsu_getmonotonic_ms(&c->time);
- c->size = 0;
- c->title = NULL;
- c->active = 0;
- user_sentinel->callback = NULL;
- user_sentinel->pw = NULL;
- user_sentinel->next = NULL;
- c->user_list = user_sentinel;
- c->sub_status[0] = 0;
- c->locked = false;
- c->total_size = 0;
- c->http_code = 0;
- c->error_count = 0;
+ if (c->locked == true)
+ return;
- content_set_status(c, messages_get("Loading"));
+ NSLOG(netsurf, INFO, "content "URL_FMT_SPC" (%p)",
+ nsurl_access_log(llcache_handle_get_url(c->llcache)), c);
- /* Finally, claim low-level cache events */
- error = llcache_handle_change_callback(llcache,
- content_llcache_callback, c);
- if (error != NSERROR_OK) {
- lwc_string_unref(c->mime_type);
- return error;
+ if (c->handler->data_complete != NULL) {
+ c->locked = true;
+ if (c->handler->data_complete(c) == false) {
+ content_set_error(c);
+ }
+ /* Conversion to the READY state will unlock the content */
+ } else {
+ content_set_ready(c);
+ content_set_done(c);
}
-
- return NSERROR_OK;
}
+
/**
* Handler for low-level cache events
*
@@ -133,22 +100,26 @@ nserror content__init(struct content *c, const content_handler *handler,
* \param pw Pointer to our context
* \return NSERROR_OK on success, appropriate error otherwise
*/
-nserror content_llcache_callback(llcache_handle *llcache,
- const llcache_event *event, void *pw)
+static nserror
+content_llcache_callback(llcache_handle *llcache,
+ const llcache_event *event, void *pw)
{
struct content *c = pw;
union content_msg_data msg_data;
nserror error = NSERROR_OK;
switch (event->type) {
+ case LLCACHE_EVENT_GOT_CERTS:
+ /* Will never happen: handled in hlcache */
+ break;
case LLCACHE_EVENT_HAD_HEADERS:
/* Will never happen: handled in hlcache */
break;
case LLCACHE_EVENT_HAD_DATA:
if (c->handler->process_data != NULL) {
- if (c->handler->process_data(c,
- (const char *) event->data.data.buf,
- event->data.data.len) == false) {
+ if (c->handler->process_data(c,
+ (const char *) event->data.data.buf,
+ event->data.data.len) == false) {
llcache_handle_abort(c->llcache);
c->status = CONTENT_STATUS_ERROR;
/** \todo It's not clear what error this is */
@@ -157,26 +128,27 @@ nserror content_llcache_callback(llcache_handle *llcache,
}
break;
case LLCACHE_EVENT_DONE:
- {
- size_t source_size;
+ {
+ size_t source_size;
- (void) llcache_handle_get_source_data(llcache, &source_size);
+ (void) llcache_handle_get_source_data(llcache, &source_size);
- content_set_status(c, messages_get("Processing"));
- msg_data.explicit_status_text = NULL;
- content_broadcast(c, CONTENT_MSG_STATUS, &msg_data);
+ content_set_status(c, messages_get("Processing"));
+ msg_data.explicit_status_text = NULL;
+ content_broadcast(c, CONTENT_MSG_STATUS, &msg_data);
- content_convert(c);
- }
+ content_convert(c);
+ }
break;
case LLCACHE_EVENT_ERROR:
/** \todo Error page? */
c->status = CONTENT_STATUS_ERROR;
- msg_data.error = event->data.msg;
+ msg_data.errordata.errorcode = event->data.error.code;
+ msg_data.errordata.errormsg = event->data.error.msg;
content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
break;
case LLCACHE_EVENT_PROGRESS:
- content_set_status(c, event->data.msg);
+ content_set_status(c, event->data.progress_msg);
msg_data.explicit_status_text = NULL;
content_broadcast(c, CONTENT_MSG_STATUS, &msg_data);
break;
@@ -190,111 +162,129 @@ nserror content_llcache_callback(llcache_handle *llcache,
return error;
}
+
/**
- * Get whether a content can reformat
+ * update content status message
*
- * \param h content to check
- * \return whether the content can reformat
+ * \param c the content to update.
*/
-bool content_can_reformat(hlcache_handle *h)
-{
- struct content *c = hlcache_handle_get_content(h);
-
- if (c == NULL)
- return false;
-
- return (c->handler->reformat != NULL);
-}
-
-
static void content_update_status(struct content *c)
{
if (c->status == CONTENT_STATUS_LOADING ||
- c->status == CONTENT_STATUS_READY) {
+ c->status == CONTENT_STATUS_READY) {
/* Not done yet */
snprintf(c->status_message, sizeof (c->status_message),
- "%s%s%s", messages_get("Fetching"),
- c->sub_status[0] != '\0' ? ", " : " ",
- c->sub_status);
+ "%s%s%s", messages_get("Fetching"),
+ c->sub_status[0] != '\0' ? ", " : " ",
+ c->sub_status);
} else {
snprintf(c->status_message, sizeof (c->status_message),
- "%s (%.1fs)", messages_get("Done"),
- (float) c->time / 1000);
+ "%s (%.1fs)", messages_get("Done"),
+ (float) c->time / 1000);
}
}
-/**
- * Updates content with new status.
- *
- * The textual status contained in the content is updated with given string.
- *
- * \param c The content to set status in.
- * \param status_message new textual status
- */
-
-void content_set_status(struct content *c, const char *status_message)
+/* exported interface documented in content/protected.h */
+nserror
+content__init(struct content *c,
+ const content_handler *handler,
+ lwc_string *imime_type,
+ const struct http_parameter *params,
+ llcache_handle *llcache,
+ const char *fallback_charset,
+ bool quirks)
{
- size_t len = strlen(status_message);
+ struct content_user *user_sentinel;
+ nserror error;
- if (len >= sizeof(c->sub_status)) {
- len = sizeof(c->sub_status) - 1;
+ NSLOG(netsurf, INFO, "url "URL_FMT_SPC" -> %p",
+ nsurl_access_log(llcache_handle_get_url(llcache)), c);
+
+ user_sentinel = calloc(1, sizeof(struct content_user));
+ if (user_sentinel == NULL) {
+ return NSERROR_NOMEM;
}
- memcpy(c->sub_status, status_message, len);
- c->sub_status[len] = '\0';
- content_update_status(c);
-}
+ if (fallback_charset != NULL) {
+ c->fallback_charset = strdup(fallback_charset);
+ if (c->fallback_charset == NULL) {
+ free(user_sentinel);
+ return NSERROR_NOMEM;
+ }
+ }
+
+ c->llcache = llcache;
+ c->mime_type = lwc_string_ref(imime_type);
+ c->handler = handler;
+ c->status = CONTENT_STATUS_LOADING;
+ c->width = 0;
+ c->height = 0;
+ c->available_width = 0;
+ c->available_height = 0;
+ c->quirks = quirks;
+ c->refresh = 0;
+ nsu_getmonotonic_ms(&c->time);
+ c->size = 0;
+ c->title = NULL;
+ c->active = 0;
+ user_sentinel->callback = NULL;
+ user_sentinel->pw = NULL;
+ user_sentinel->next = NULL;
+ c->user_list = user_sentinel;
+ c->sub_status[0] = 0;
+ c->locked = false;
+ c->total_size = 0;
+ c->http_code = 0;
+ c->textsearch.string = NULL;
+ c->textsearch.context = NULL;
-/**
- * All data has arrived, convert for display.
- *
- * Calls the convert function for the content.
- *
- * - If the conversion succeeds, but there is still some processing required
- * (eg. loading images), the content gets status CONTENT_STATUS_READY, and a
- * CONTENT_MSG_READY is sent to all users.
- * - If the conversion succeeds and is complete, the content gets status
- * CONTENT_STATUS_DONE, and CONTENT_MSG_READY then CONTENT_MSG_DONE are sent.
- * - If the conversion fails, CONTENT_MSG_ERROR is sent. The content will soon
- * be destroyed and must no longer be used.
- */
+ content_set_status(c, messages_get("Loading"));
-void content_convert(struct content *c)
+ /* Finally, claim low-level cache events */
+ error = llcache_handle_change_callback(llcache,
+ content_llcache_callback, c);
+ if (error != NSERROR_OK) {
+ lwc_string_unref(c->mime_type);
+ return error;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in content/content.h */
+bool content_can_reformat(hlcache_handle *h)
{
- assert(c);
- assert(c->status == CONTENT_STATUS_LOADING ||
- c->status == CONTENT_STATUS_ERROR);
+ struct content *c = hlcache_handle_get_content(h);
- if (c->status != CONTENT_STATUS_LOADING)
- return;
+ if (c == NULL)
+ return false;
- if (c->locked == true)
- return;
-
- NSLOG(netsurf, INFO, "content "URL_FMT_SPC" (%p)",
- nsurl_access(llcache_handle_get_url(c->llcache)), c);
+ return (c->handler->reformat != NULL);
+}
- if (c->handler->data_complete != NULL) {
- c->locked = true;
- if (c->handler->data_complete(c) == false) {
- content_set_error(c);
- }
- /* Conversion to the READY state will unlock the content */
- } else {
- content_set_ready(c);
- content_set_done(c);
+
+/* exported interface documented in content/protected.h */
+void content_set_status(struct content *c, const char *status_message)
+{
+ size_t len = strlen(status_message);
+
+ if (len >= sizeof(c->sub_status)) {
+ len = sizeof(c->sub_status) - 1;
}
+ memcpy(c->sub_status, status_message, len);
+ c->sub_status[len] = '\0';
+
+ content_update_status(c);
}
-/**
- * Put a content in status CONTENT_STATUS_READY and unlock the content.
- */
+/* exported interface documented in content/protected.h */
void content_set_ready(struct content *c)
{
- /* The content must be locked at this point, as it can only
+ /* The content must be locked at this point, as it can only
* become READY after conversion. */
assert(c->locked);
c->locked = false;
@@ -304,10 +294,8 @@ void content_set_ready(struct content *c)
content_broadcast(c, CONTENT_MSG_READY, NULL);
}
-/**
- * Put a content in status CONTENT_STATUS_DONE.
- */
+/* exported interface documented in content/protected.h */
void content_set_done(struct content *c)
{
uint64_t now_ms;
@@ -320,41 +308,36 @@ void content_set_done(struct content *c)
content_broadcast(c, CONTENT_MSG_DONE, NULL);
}
-/**
- * Put a content in status CONTENT_STATUS_ERROR and unlock the content.
- *
- * \note We expect the caller to broadcast an error report if needed.
- */
+/* exported interface documented in content/protected.h */
void content_set_error(struct content *c)
{
c->locked = false;
c->status = CONTENT_STATUS_ERROR;
}
-/**
- * Reformat to new size.
- *
- * Calls the reformat function for the content.
- */
+/* exported interface documented in content/content.h */
void content_reformat(hlcache_handle *h, bool background,
- int width, int height)
+ int width, int height)
{
content__reformat(hlcache_handle_get_content(h), background,
- width, height);
+ width, height);
}
-void content__reformat(struct content *c, bool background,
- int width, int height)
+
+/* exported interface documented in content/protected.h */
+void
+content__reformat(struct content *c, bool background, int width, int height)
{
union content_msg_data data;
assert(c != 0);
assert(c->status == CONTENT_STATUS_READY ||
- c->status == CONTENT_STATUS_DONE);
+ c->status == CONTENT_STATUS_DONE);
assert(c->locked == false);
c->available_width = width;
+ c->available_height = height;
if (c->handler->reformat != NULL) {
c->locked = true;
@@ -367,19 +350,14 @@ void content__reformat(struct content *c, bool background,
}
-/**
- * Destroy and free a content.
- *
- * Calls the destroy function for the content, and frees the structure.
- */
-
+/* exported interface documented in content/content.h */
void content_destroy(struct content *c)
{
struct content_rfc5988_link *link;
assert(c);
NSLOG(netsurf, INFO, "content %p %s", c,
- nsurl_access(llcache_handle_get_url(c->llcache)));
+ nsurl_access_log(llcache_handle_get_url(c->llcache)));
assert(c->locked == false);
if (c->handler->destroy != NULL)
@@ -415,18 +393,12 @@ void content_destroy(struct content *c)
}
-/**
- * Handle mouse movements in a content window.
- *
- * \param h Content handle
- * \param bw browser window
- * \param mouse state of mouse buttons and modifier keys
- * \param x coordinate of mouse
- * \param y coordinate of mouse
- */
-
-void content_mouse_track(hlcache_handle *h, struct browser_window *bw,
- browser_mouse_state mouse, int x, int y)
+/* exported interface documented in content/content.h */
+void
+content_mouse_track(hlcache_handle *h,
+ struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y)
{
struct content *c = hlcache_handle_get_content(h);
assert(c != NULL);
@@ -444,24 +416,12 @@ void content_mouse_track(hlcache_handle *h, struct browser_window *bw,
}
-/**
- * Handle mouse clicks and movements in a content window.
- *
- * \param h Content handle
- * \param bw browser window
- * \param mouse state of mouse buttons and modifier keys
- * \param x coordinate of mouse
- * \param y coordinate of mouse
- *
- * This function handles both hovering and clicking. It is important that the
- * code path is identical (except that hovering doesn't carry out the action),
- * so that the status bar reflects exactly what will happen. Having separate
- * code paths opens the possibility that an attacker will make the status bar
- * show some harmless action where clicking will be harmful.
- */
-
-void content_mouse_action(hlcache_handle *h, struct browser_window *bw,
- browser_mouse_state mouse, int x, int y)
+/* exported interface documented in content/content.h */
+void
+content_mouse_action(hlcache_handle *h,
+ struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y)
{
struct content *c = hlcache_handle_get_content(h);
assert(c != NULL);
@@ -473,14 +433,7 @@ void content_mouse_action(hlcache_handle *h, struct browser_window *bw,
}
-/**
- * Handle keypresses.
- *
- * \param h Content handle
- * \param key The UCS4 character codepoint
- * \return true if key handled, false otherwise
- */
-
+/* exported interface documented in content/content.h */
bool content_keypress(struct hlcache_handle *h, uint32_t key)
{
struct content *c = hlcache_handle_get_content(h);
@@ -493,34 +446,18 @@ bool content_keypress(struct hlcache_handle *h, uint32_t key)
}
-/**
- * Request a redraw of an area of a content
- *
- * \param h high-level cache handle
- * \param x x co-ord of left edge
- * \param y y co-ord of top edge
- * \param width Width of rectangle
- * \param height Height of rectangle
- */
+/* exported interface documented in content/content.h */
void content_request_redraw(struct hlcache_handle *h,
- int x, int y, int width, int height)
+ int x, int y, int width, int height)
{
content__request_redraw(hlcache_handle_get_content(h),
- x, y, width, height);
+ x, y, width, height);
}
-/**
- * Request a redraw of an area of a content
- *
- * \param c Content
- * \param x x co-ord of left edge
- * \param y y co-ord of top edge
- * \param width Width of rectangle
- * \param height Height of rectangle
- */
+/* exported interface, documented in content/protected.h */
void content__request_redraw(struct content *c,
- int x, int y, int width, int height)
+ int x, int y, int width, int height)
{
union content_msg_data data;
@@ -532,21 +469,96 @@ void content__request_redraw(struct content *c,
data.redraw.width = width;
data.redraw.height = height;
- data.redraw.full_redraw = true;
+ content_broadcast(c, CONTENT_MSG_REDRAW, &data);
+}
- data.redraw.object = c;
- data.redraw.object_x = 0;
- data.redraw.object_y = 0;
- data.redraw.object_width = c->width;
- data.redraw.object_height = c->height;
- content_broadcast(c, CONTENT_MSG_REDRAW, &data);
+/* exported interface, documented in content/content.h */
+bool content_exec(struct hlcache_handle *h, const char *src, size_t srclen)
+{
+ struct content *c = hlcache_handle_get_content(h);
+
+ assert(c != NULL);
+
+ if (c->locked) {
+ /* Not safe to do stuff */
+ NSLOG(netsurf, DEEPDEBUG, "Unable to exec, content locked");
+ return false;
+ }
+
+ if (c->handler->exec == NULL) {
+ /* Can't exec something on this content */
+ NSLOG(netsurf, DEEPDEBUG, "Unable to exec, no exec function");
+ return false;
+ }
+
+ return c->handler->exec(c, src, srclen);
}
/* exported interface, documented in content/content.h */
-bool content_redraw(hlcache_handle *h, struct content_redraw_data *data,
- const struct rect *clip, const struct redraw_context *ctx)
+bool content_saw_insecure_objects(struct hlcache_handle *h)
+{
+ struct content *c = hlcache_handle_get_content(h);
+ struct nsurl *url = hlcache_handle_get_url(h);
+ lwc_string *scheme = nsurl_get_component(url, NSURL_SCHEME);
+ bool match;
+
+ /* Is this an internal scheme? If so, we trust here and stop */
+ if ((lwc_string_isequal(scheme, corestring_lwc_about,
+ &match) == lwc_error_ok &&
+ (match == true)) ||
+ (lwc_string_isequal(scheme, corestring_lwc_data,
+ &match) == lwc_error_ok &&
+ (match == true)) ||
+ (lwc_string_isequal(scheme, corestring_lwc_resource,
+ &match) == lwc_error_ok &&
+ (match == true)) ||
+ /* Our internal x-ns-css scheme is secure */
+ (lwc_string_isequal(scheme, corestring_lwc_x_ns_css,
+ &match) == lwc_error_ok &&
+ (match == true)) ||
+ /* We also treat file: as "not insecure" here */
+ (lwc_string_isequal(scheme, corestring_lwc_file,
+ &match) == lwc_error_ok &&
+ (match == true))) {
+ /* No insecurity to find */
+ lwc_string_unref(scheme);
+ return false;
+ }
+
+ /* Okay, not internal, am *I* secure? */
+ if ((lwc_string_isequal(scheme, corestring_lwc_https,
+ &match) == lwc_error_ok)
+ && (match == false)) {
+ /* I did see something insecure -- ME! */
+ lwc_string_unref(scheme);
+ return true;
+ }
+
+ lwc_string_unref(scheme);
+ /* I am supposed to be secure, but was I overridden */
+ if (urldb_get_cert_permissions(url)) {
+ /* I was https:// but I was overridden, that's no good */
+ return true;
+ }
+
+ /* Otherwise try and chain through the handler */
+ if (c != NULL && c->handler->saw_insecure_objects != NULL) {
+ return c->handler->saw_insecure_objects(c);
+ }
+
+ /* If we can't see insecure objects, we can't see them */
+ return false;
+}
+
+
+/* exported interface, documented in content/content.h */
+bool
+content_redraw(hlcache_handle *h,
+ struct content_redraw_data *data,
+ const struct rect *clip,
+ const struct redraw_context *ctx)
{
struct content *c = hlcache_handle_get_content(h);
@@ -567,8 +579,10 @@ bool content_redraw(hlcache_handle *h, struct content_redraw_data *data,
/* exported interface, documented in content/content.h */
-bool content_scaled_redraw(struct hlcache_handle *h,
- int width, int height, const struct redraw_context *ctx)
+bool
+content_scaled_redraw(struct hlcache_handle *h,
+ int width, int height,
+ const struct redraw_context *ctx)
{
struct content *c = hlcache_handle_get_content(h);
struct redraw_context new_ctx = *ctx;
@@ -634,32 +648,22 @@ bool content_scaled_redraw(struct hlcache_handle *h,
return plot_ok;
}
-/**
- * Register a user for callbacks.
- *
- * \param c the content to register
- * \param callback the callback function
- * \param pw callback private data
- * \return true on success, false otherwise on memory exhaustion
- *
- * The callback will be called when content_broadcast() is
- * called with the content.
- */
-bool content_add_user(
- struct content *c,
- void (*callback)(
- struct content *c,
- content_msg msg,
- const union content_msg_data *data,
- void *pw),
- void *pw)
+/* exported interface documented in content/content.h */
+bool
+content_add_user(struct content *c,
+ void (*callback)(
+ struct content *c,
+ content_msg msg,
+ const union content_msg_data *data,
+ void *pw),
+ void *pw)
{
struct content_user *user;
NSLOG(netsurf, INFO, "content "URL_FMT_SPC" (%p), user %p %p",
- nsurl_access(llcache_handle_get_url(c->llcache)), c, callback,
- pw);
+ nsurl_access_log(llcache_handle_get_url(c->llcache)),
+ c, callback, pw);
user = malloc(sizeof(struct content_user));
if (!user)
return false;
@@ -675,31 +679,25 @@ bool content_add_user(
}
-/**
- * Remove a callback user.
- *
- * The callback function and pw must be identical to those passed to
- * content_add_user().
- */
-
-void content_remove_user(
- struct content *c,
- void (*callback)(
- struct content *c,
- content_msg msg,
- const union content_msg_data *data,
- void *pw),
- void *pw)
+/* exported interface documented in content/content.h */
+void
+content_remove_user(struct content *c,
+ void (*callback)(
+ struct content *c,
+ content_msg msg,
+ const union content_msg_data *data,
+ void *pw),
+ void *pw)
{
struct content_user *user, *next;
NSLOG(netsurf, INFO, "content "URL_FMT_SPC" (%p), user %p %p",
- nsurl_access(llcache_handle_get_url(c->llcache)), c, callback,
- pw);
+ nsurl_access_log(llcache_handle_get_url(c->llcache)),
+ c, callback, pw);
/* user_list starts with a sentinel */
for (user = c->user_list; user->next != 0 &&
- !(user->next->callback == callback &&
- user->next->pw == pw); user = user->next)
+ !(user->next->callback == callback &&
+ user->next->pw == pw); user = user->next)
;
if (user->next == 0) {
NSLOG(netsurf, INFO, "user not found in list");
@@ -715,17 +713,15 @@ void content_remove_user(
free(next);
}
-/**
- * Count users for the content.
- */
+/* exported interface documented in content/content.h */
uint32_t content_count_users(struct content *c)
{
struct content_user *user;
uint32_t counter = 0;
assert(c != NULL);
-
+
for (user = c->user_list; user != NULL; user = user->next)
counter += 1;
@@ -734,13 +730,8 @@ uint32_t content_count_users(struct content *c)
return counter - 1; /* Subtract 1 for the sentinel */
}
-/**
- * Determine if quirks mode matches
- *
- * \param c Content to consider
- * \param quirks Quirks mode to match
- * \return True if quirks match, false otherwise
- */
+
+/* exported interface documented in content/content.h */
bool content_matches_quirks(struct content *c, bool quirks)
{
if (c->handler->matches_quirks == NULL)
@@ -749,23 +740,17 @@ bool content_matches_quirks(struct content *c, bool quirks)
return c->handler->matches_quirks(c, quirks);
}
-/**
- * Determine if a content is shareable
- *
- * \param c Content to consider
- * \return True if content is shareable, false otherwise
- */
+
+/* exported interface documented in content/content.h */
bool content_is_shareable(struct content *c)
{
return c->handler->no_share == false;
}
-/**
- * Send a message to all users.
- */
+/* exported interface documented in content/protected.h */
void content_broadcast(struct content *c, content_msg msg,
- const union content_msg_data *data)
+ const union content_msg_data *data)
{
struct content_user *user, *next;
assert(c);
@@ -778,72 +763,87 @@ void content_broadcast(struct content *c, content_msg msg,
}
}
+
/* exported interface documented in content_protected.h */
-void content_broadcast_errorcode(struct content *c, nserror errorcode)
+void
+content_broadcast_error(struct content *c, nserror errorcode, const char *msg)
{
struct content_user *user, *next;
union content_msg_data data;
assert(c);
- data.errorcode = errorcode;
+ data.errordata.errorcode = errorcode;
+ data.errordata.errormsg = msg;
for (user = c->user_list->next; user != 0; user = next) {
next = user->next; /* user may be destroyed during callback */
if (user->callback != 0) {
- user->callback(c, CONTENT_MSG_ERRORCODE,
- &data, user->pw);
+ user->callback(c, CONTENT_MSG_ERROR,
+ &data, user->pw);
}
}
}
-/**
- * A window containing the content has been opened.
- *
- * \param h handle to content that has been opened
- * \param bw browser window containing the content
- * \param page content of type CONTENT_HTML containing h, or 0 if not an
- * object within a page
- * \param params object parameters, or 0 if not an object
- *
- * Calls the open function for the content.
- */
-
-void content_open(hlcache_handle *h, struct browser_window *bw,
- struct content *page, struct object_params *params)
+/* exported interface, documented in content/content.h */
+nserror
+content_open(hlcache_handle *h,
+ struct browser_window *bw,
+ struct content *page,
+ struct object_params *params)
{
- struct content *c = hlcache_handle_get_content(h);
+ struct content *c;
+ nserror res;
+
+ c = hlcache_handle_get_content(h);
assert(c != 0);
NSLOG(netsurf, INFO, "content %p %s", c,
- nsurl_access(llcache_handle_get_url(c->llcache)));
- if (c->handler->open != NULL)
- c->handler->open(c, bw, page, params);
+ nsurl_access_log(llcache_handle_get_url(c->llcache)));
+ if (c->handler->open != NULL) {
+ res = c->handler->open(c, bw, page, params);
+ } else {
+ res = NSERROR_OK;
+ }
+ return res;
}
-/**
- * The window containing the content has been closed.
- *
- * Calls the close function for the content.
- */
-
-void content_close(hlcache_handle *h)
+/* exported interface, documented in content/content.h */
+nserror content_close(hlcache_handle *h)
{
- struct content *c = hlcache_handle_get_content(h);
- assert(c != 0);
+ struct content *c;
+ nserror res;
+
+ c = hlcache_handle_get_content(h);
+ if (c == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if ((c->status != CONTENT_STATUS_READY) &&
+ (c->status != CONTENT_STATUS_DONE)) {
+ /* status is not read or done so nothing to do */
+ return NSERROR_INVALID;
+ }
+
NSLOG(netsurf, INFO, "content %p %s", c,
- nsurl_access(llcache_handle_get_url(c->llcache)));
- if (c->handler->close != NULL)
- c->handler->close(c);
-}
+ nsurl_access_log(llcache_handle_get_url(c->llcache)));
+ if (c->textsearch.context != NULL) {
+ content_textsearch_destroy(c->textsearch.context);
+ c->textsearch.context = NULL;
+ }
+
+ if (c->handler->close != NULL) {
+ res = c->handler->close(c);
+ } else {
+ res = NSERROR_OK;
+ }
+ return res;
+}
-/**
- * Tell a content that any selection it has, or one of its objects has, must be
- * cleared.
- */
+/* exported interface, documented in content/content.h */
void content_clear_selection(hlcache_handle *h)
{
struct content *c = hlcache_handle_get_content(h);
@@ -854,11 +854,7 @@ void content_clear_selection(hlcache_handle *h)
}
-/**
- * Get a text selection from a content. Ownership is passed to the caller,
- * who must free() it.
- */
-
+/* exported interface, documented in content/content.h */
char * content_get_selection(hlcache_handle *h)
{
struct content *c = hlcache_handle_get_content(h);
@@ -870,9 +866,12 @@ char * content_get_selection(hlcache_handle *h)
return NULL;
}
+
/* exported interface documented in content/content.h */
-nserror content_get_contextual_content(struct hlcache_handle *h,
- int x, int y, struct browser_window_features *data)
+nserror
+content_get_contextual_content(struct hlcache_handle *h,
+ int x, int y,
+ struct browser_window_features *data)
{
struct content *c = hlcache_handle_get_content(h);
assert(c != 0);
@@ -886,8 +885,11 @@ nserror content_get_contextual_content(struct hlcache_handle *h,
}
-bool content_scroll_at_point(struct hlcache_handle *h,
- int x, int y, int scrx, int scry)
+/* exported interface, documented in content/content.h */
+bool
+content_scroll_at_point(struct hlcache_handle *h,
+ int x, int y,
+ int scrx, int scry)
{
struct content *c = hlcache_handle_get_content(h);
assert(c != 0);
@@ -899,8 +901,11 @@ bool content_scroll_at_point(struct hlcache_handle *h,
}
-bool content_drop_file_at_point(struct hlcache_handle *h,
- int x, int y, char *file)
+/* exported interface, documented in content/content.h */
+bool
+content_drop_file_at_point(struct hlcache_handle *h,
+ int x, int y,
+ char *file)
{
struct content *c = hlcache_handle_get_content(h);
assert(c != 0);
@@ -912,30 +917,9 @@ bool content_drop_file_at_point(struct hlcache_handle *h,
}
-void content_search(struct hlcache_handle *h, void *context,
- search_flags_t flags, const char *string)
-{
- struct content *c = hlcache_handle_get_content(h);
- assert(c != 0);
-
- if (c->handler->search != NULL) {
- c->handler->search(c, context, flags, string);
- }
-}
-
-
-void content_search_clear(struct hlcache_handle *h)
-{
- struct content *c = hlcache_handle_get_content(h);
- assert(c != 0);
-
- if (c->handler->search_clear != NULL) {
- c->handler->search_clear(c);
- }
-}
-
/* exported interface documented in content/content.h */
-nserror content_debug_dump(struct hlcache_handle *h, FILE *f, enum content_debug op)
+nserror
+content_debug_dump(struct hlcache_handle *h, FILE *f, enum content_debug op)
{
struct content *c = hlcache_handle_get_content(h);
assert(c != 0);
@@ -947,6 +931,7 @@ nserror content_debug_dump(struct hlcache_handle *h, FILE *f, enum content_debug
return c->handler->debug_dump(c, f, op);
}
+
/* exported interface documented in content/content.h */
nserror content_debug(struct hlcache_handle *h, enum content_debug op)
{
@@ -964,12 +949,6 @@ nserror content_debug(struct hlcache_handle *h, enum content_debug op)
}
-void content_add_error(struct content *c, const char *token,
- unsigned int line)
-{
-}
-
-
/* exported interface documented in content/content.h */
struct content_rfc5988_link *
content_find_rfc5988_link(hlcache_handle *h, lwc_string *rel)
@@ -980,7 +959,7 @@ content_find_rfc5988_link(hlcache_handle *h, lwc_string *rel)
while (link != NULL) {
if (lwc_string_caseless_isequal(link->rel, rel,
- &rel_match) == lwc_error_ok && rel_match) {
+ &rel_match) == lwc_error_ok && rel_match) {
break;
}
link = link->next;
@@ -988,8 +967,10 @@ content_find_rfc5988_link(hlcache_handle *h, lwc_string *rel)
return link;
}
+
+/* exported interface documented in content/protected.h */
struct content_rfc5988_link *
-content__free_rfc5988_link(struct content_rfc5988_link *link)
+content__free_rfc5988_link(struct content_rfc5988_link *link)
{
struct content_rfc5988_link *next;
@@ -1014,10 +995,13 @@ content__free_rfc5988_link(struct content_rfc5988_link *link)
return next;
}
-bool content__add_rfc5988_link(struct content *c,
- const struct content_rfc5988_link *link)
+
+/* exported interface documented in content/protected.h */
+bool
+content__add_rfc5988_link(struct content *c,
+ const struct content_rfc5988_link *link)
{
- struct content_rfc5988_link *newlink;
+ struct content_rfc5988_link *newlink;
union content_msg_data msg_data;
/* a link relation must be present for it to be a link */
@@ -1032,7 +1016,7 @@ bool content__add_rfc5988_link(struct content *c,
newlink = calloc(1, sizeof(struct content_rfc5988_link));
if (newlink == NULL) {
- return false;
+ return false;
}
/* copy values */
@@ -1063,7 +1047,6 @@ bool content__add_rfc5988_link(struct content *c,
}
-
/* exported interface documented in content/content.h */
nsurl *content_get_url(struct content *c)
{
@@ -1092,6 +1075,7 @@ lwc_string *content_get_mime_type(hlcache_handle *h)
return content__get_mime_type(hlcache_handle_get_content(h));
}
+
/* exported interface documented in content/content_protected.h */
lwc_string *content__get_mime_type(struct content *c)
{
@@ -1124,6 +1108,7 @@ const char *content_get_title(hlcache_handle *h)
return content__get_title(hlcache_handle_get_content(h));
}
+
/* exported interface documented in content/content_protected.h */
const char *content__get_title(struct content *c)
{
@@ -1131,7 +1116,7 @@ const char *content__get_title(struct content *c)
return NULL;
return c->title != NULL ? c->title :
- nsurl_access(llcache_handle_get_url(c->llcache));
+ nsurl_access(llcache_handle_get_url(c->llcache));
}
@@ -1141,6 +1126,7 @@ content_status content_get_status(hlcache_handle *h)
return content__get_status(hlcache_handle_get_content(h));
}
+
/* exported interface documented in content/content_protected.h */
content_status content__get_status(struct content *c)
{
@@ -1157,6 +1143,7 @@ const char *content_get_status_message(hlcache_handle *h)
return content__get_status_message(hlcache_handle_get_content(h));
}
+
/* exported interface documented in content/content_protected.h */
const char *content__get_status_message(struct content *c)
{
@@ -1173,6 +1160,7 @@ int content_get_width(hlcache_handle *h)
return content__get_width(hlcache_handle_get_content(h));
}
+
/* exported interface documented in content/content_protected.h */
int content__get_width(struct content *c)
{
@@ -1189,6 +1177,7 @@ int content_get_height(hlcache_handle *h)
return content__get_height(hlcache_handle_get_content(h));
}
+
/* exported interface documented in content/content_protected.h */
int content__get_height(struct content *c)
{
@@ -1205,6 +1194,7 @@ int content_get_available_width(hlcache_handle *h)
return content__get_available_width(hlcache_handle_get_content(h));
}
+
/* exported interface documented in content/content_protected.h */
int content__get_available_width(struct content *c)
{
@@ -1216,35 +1206,32 @@ int content__get_available_width(struct content *c)
/* exported interface documented in content/content.h */
-const char *content_get_source_data(hlcache_handle *h, unsigned long *size)
+const uint8_t *content_get_source_data(hlcache_handle *h, size_t *size)
{
return content__get_source_data(hlcache_handle_get_content(h), size);
}
+
/* exported interface documented in content/content_protected.h */
-const char *content__get_source_data(struct content *c, unsigned long *size)
+const uint8_t *content__get_source_data(struct content *c, size_t *size)
{
- const uint8_t *data;
- size_t len;
-
assert(size != NULL);
+ /** \todo check if the content check should be an assert */
if (c == NULL)
return NULL;
- data = llcache_handle_get_source_data(c->llcache, &len);
-
- *size = (unsigned long) len;
-
- return (const char *) data;
+ return llcache_handle_get_source_data(c->llcache, size);
}
+
/* exported interface documented in content/content.h */
void content_invalidate_reuse_data(hlcache_handle *h)
{
content__invalidate_reuse_data(hlcache_handle_get_content(h));
}
+
/* exported interface documented in content/content_protected.h */
void content__invalidate_reuse_data(struct content *c)
{
@@ -1255,12 +1242,14 @@ void content__invalidate_reuse_data(struct content *c)
llcache_handle_invalidate_cache_data(c->llcache);
}
+
/* exported interface documented in content/content.h */
nsurl *content_get_refresh_url(hlcache_handle *h)
{
return content__get_refresh_url(hlcache_handle_get_content(h));
}
+
/* exported interface documented in content/content_protected.h */
nsurl *content__get_refresh_url(struct content *c)
{
@@ -1283,9 +1272,9 @@ struct bitmap *content__get_bitmap(struct content *c)
{
struct bitmap *bitmap = NULL;
- if ((c != NULL) &&
- (c->handler != NULL) &&
- (c->handler->type != NULL) &&
+ if ((c != NULL) &&
+ (c->handler != NULL) &&
+ (c->handler->type != NULL) &&
(c->handler->type() == CONTENT_IMAGE) &&
(c->handler->get_internal != NULL) ) {
bitmap = c->handler->get_internal(c, NULL);
@@ -1305,21 +1294,13 @@ bool content_get_opaque(hlcache_handle *h)
/* exported interface documented in content/content_protected.h */
bool content__get_opaque(struct content *c)
{
- bool opaque = false;
-
- if ((c != NULL) &&
- (c->handler != NULL) &&
- (c->handler->type != NULL) &&
- (c->handler->type() == CONTENT_IMAGE) &&
- (c->handler->get_internal != NULL) ) {
- struct bitmap *bitmap = NULL;
- bitmap = c->handler->get_internal(c, NULL);
- if (bitmap != NULL) {
- opaque = guit->bitmap->get_opaque(bitmap);
- }
+ if ((c != NULL) &&
+ (c->handler != NULL) &&
+ (c->handler->is_opaque != NULL)) {
+ return c->handler->is_opaque(c);
}
- return opaque;
+ return false;
}
@@ -1336,14 +1317,16 @@ bool content_get_quirks(hlcache_handle *h)
/* exported interface documented in content/content.h */
-const char *content_get_encoding(hlcache_handle *h, enum content_encoding_type op)
+const char *
+content_get_encoding(hlcache_handle *h, enum content_encoding_type op)
{
return content__get_encoding(hlcache_handle_get_content(h), op);
}
/* exported interface documented in content/content_protected.h */
-const char *content__get_encoding(struct content *c, enum content_encoding_type op)
+const char *
+content__get_encoding(struct content *c, enum content_encoding_type op)
{
const char *encoding = NULL;
@@ -1370,12 +1353,8 @@ bool content__is_locked(struct content *c)
return c->locked;
}
-/**
- * Retrieve the low-level cache handle for a content
- *
- * \param c Content to retrieve from
- * \return Low-level cache handle
- */
+
+/* exported interface documented in content/content.h */
const llcache_handle *content_get_llcache_handle(struct content *c)
{
if (c == NULL)
@@ -1384,12 +1363,8 @@ const llcache_handle *content_get_llcache_handle(struct content *c)
return c->llcache;
}
-/**
- * Clone a content object in its current state.
- *
- * \param c Content to clone
- * \return Clone of \a c
- */
+
+/* exported interface documented in content/protected.h */
struct content *content_clone(struct content *c)
{
struct content *nc;
@@ -1402,13 +1377,8 @@ struct content *content_clone(struct content *c)
return nc;
};
-/**
- * Clone a content's data members
- *
- * \param c Content to clone
- * \param nc Content to populate
- * \return NSERROR_OK on success, appropriate error otherwise
- */
+
+/* exported interface documented in content/protected.h */
nserror content__clone(const struct content *c, struct content *nc)
{
nserror error;
@@ -1469,24 +1439,19 @@ nserror content__clone(const struct content *c, struct content *nc)
nc->locked = c->locked;
nc->total_size = c->total_size;
nc->http_code = c->http_code;
-
+
return NSERROR_OK;
}
-/**
- * Abort a content object
- *
- * \param c The content object to abort
- * \return NSERROR_OK on success, otherwise appropriate error
- */
+
+/* exported interface documented in content/content.h */
nserror content_abort(struct content *c)
{
NSLOG(netsurf, INFO, "Aborting %p", c);
-
+
if (c->handler->stop != NULL)
c->handler->stop(c);
-
+
/* And for now, abort our llcache object */
return llcache_handle_abort(c->llcache);
}
-
diff --git a/content/content.h b/content/content.h
index e555df269..1bae813b2 100644
--- a/content/content.h
+++ b/content/content.h
@@ -24,15 +24,14 @@
* The content functions manipulate struct contents, which correspond to URLs.
*/
-#ifndef _NETSURF_CONTENT_CONTENT_H_
-#define _NETSURF_CONTENT_CONTENT_H_
+#ifndef NETSURF_CONTENT_CONTENT_H_
+#define NETSURF_CONTENT_CONTENT_H_
#include <libwapcaplet/libwapcaplet.h>
-#include "utils/errors.h"
-#include "content/content_factory.h"
-#include "desktop/search.h" /* search flags enum */
+#include "netsurf/content_type.h"
#include "netsurf/mouse.h" /* mouse state enums */
+#include "netsurf/console.h" /* console state and flags enums */
struct browser_window;
struct browser_window_features;
@@ -42,43 +41,7 @@ struct hlcache_handle;
struct object_params;
struct rect;
struct redraw_context;
-
-/** Status of a content */
-typedef enum {
- CONTENT_STATUS_LOADING, /**< Content is being fetched or
- converted and is not safe to display. */
- CONTENT_STATUS_READY, /**< Some parts of content still being
- loaded, but can be displayed. */
- CONTENT_STATUS_DONE, /**< All finished. */
- CONTENT_STATUS_ERROR /**< Error occurred, content will be
- destroyed imminently. */
-} content_status;
-
-/** Used in callbacks to indicate what has occurred. */
-typedef enum {
- CONTENT_MSG_LOADING, /**< fetching or converting */
- CONTENT_MSG_READY, /**< may be displayed */
- CONTENT_MSG_DONE, /**< finished */
- CONTENT_MSG_ERROR, /**< error occurred */
- CONTENT_MSG_ERRORCODE, /**< error occurred return nserror */
- CONTENT_MSG_REDIRECT, /**< fetch url redirect occured */
- CONTENT_MSG_STATUS, /**< new status string */
- CONTENT_MSG_REFORMAT, /**< content_reformat done */
- CONTENT_MSG_REDRAW, /**< needs redraw (eg. new animation frame) */
- CONTENT_MSG_REFRESH, /**< wants refresh */
- CONTENT_MSG_DOWNLOAD, /**< download, not for display */
- CONTENT_MSG_LINK, /**< RFC5988 link */
- CONTENT_MSG_GETCTX, /**< Javascript context */
- CONTENT_MSG_SCROLL, /**< Request to scroll content */
- CONTENT_MSG_DRAGSAVE, /**< Allow drag saving of content */
- CONTENT_MSG_SAVELINK, /**< Allow URL to be saved */
- CONTENT_MSG_POINTER, /**< Wants a specific mouse pointer set */
- CONTENT_MSG_SELECTION, /**< A selection made or cleared */
- CONTENT_MSG_CARET, /**< Caret movement / hiding */
- CONTENT_MSG_DRAG, /**< A drag started or ended */
- CONTENT_MSG_SELECTMENU,/**< Create a select menu */
- CONTENT_MSG_GADGETCLICK/**< A gadget has been clicked on (mainly for file) */
-} content_msg;
+struct cert_chain;
/** RFC5988 metadata link */
@@ -95,51 +58,115 @@ struct content_rfc5988_link {
/** Extra data for some content_msg messages. */
union content_msg_data {
- /** CONTENT_MSG_ERROR - Error message */
- const char *error;
- /** CONTENT_MSG_ERRORCODE - Error code */
- nserror errorcode;
- /** CONTENT_MSG_REDIRECT - Redirect info */
+ /**
+ * CONTENT_MSG_LOG - Information for logging
+ */
+ struct {
+ /** The source of the logging */
+ browser_window_console_source src;
+ /** The message to log */
+ const char *msg;
+ /** The length of that message */
+ size_t msglen;
+ /** The flags of the logging */
+ browser_window_console_flags flags;
+ } log;
+
+ /**
+ * CONTENT_MSG_SSL_CERTS - The certificate chain from the
+ * underlying fetch
+ */
+ const struct cert_chain *chain;
+
+ /**
+ * CONTENT_MSG_ERROR - Error from content or underlying fetch
+ */
+ struct {
+ /**
+ * The error code to convey meaning
+ */
+ nserror errorcode;
+ /**
+ * The message. if NSERROR_UNKNOWN then this is the direct
+ * message, otherwise is some kind of metadata (e.g. a
+ * message name or somesuch) but always a null terminated
+ * string.
+ */
+ const char *errormsg;
+ } errordata;
+
+ /**
+ * CONTENT_MSG_REDIRECT - Redirect info
+ */
struct {
struct nsurl *from; /**< Redirect origin */
struct nsurl *to; /**< Redirect target */
} redirect; /**< Fetch URL redirect occured */
- /** CONTENT_MSG_REDRAW - Area of content which needs redrawing */
+
+ /**
+ * CONTENT_MSG_REDRAW - Area of content which needs redrawing
+ */
struct {
int x, y, width, height;
- /** Redraw the area fully. If false, object must be set,
- * and only the object will be redrawn. */
- bool full_redraw;
- /** Object to redraw if full_redraw is false. */
- struct content *object;
- /** Coordinates to plot object at. */
- int object_x, object_y;
- /** Dimensions to plot object with. */
- int object_width, object_height;
} redraw;
- /** CONTENT_MSG_REFRESH - Minimum delay */
+
+ /**
+ * CONTENT_MSG_REFRESH - Minimum delay
+ */
int delay;
- /** CONTENT_MSG_REFORMAT - Reformat should not cause a redraw */
+
+ /**
+ * CONTENT_MSG_REFORMAT - Reformat should not cause a redraw
+ */
bool background;
- /** CONTENT_MSG_STATUS - Status message update. If NULL, the content's
- * internal status text has been updated, and listener should use
- * content_get_status_message() */
+
+ /**
+ * CONTENT_MSG_STATUS - Status message update. If NULL, the
+ * content's internal status text has been updated, and
+ * listener should use content_get_status_message()
+ */
const char *explicit_status_text;
- /** CONTENT_MSG_DOWNLOAD - Low-level cache handle */
+
+ /**
+ * CONTENT_MSG_DOWNLOAD - Low-level cache handle
+ */
struct llcache_handle *download;
- /** CONTENT_MSG_RFC5988_LINK - rfc5988 link data */
+
+ /**
+ * CONTENT_MSG_RFC5988_LINK - rfc5988 link data
+ */
struct content_rfc5988_link *rfc5988_link;
- /** CONTENT_MSG_GETCTX - Javascript context */
- struct jscontext **jscontext;
- /** CONTENT_MSG_SCROLL - Part of content to scroll to show */
+
+ /**
+ * CONTENT_MSG_GETTHREAD - Javascript context (thread)
+ */
+ struct jsthread **jsthread;
+
+ /**
+ * CONTENT_MSG_GETDIMS - Get the viewport dimensions
+ */
struct {
- /** if true, scroll to show area given by (x0, y0) and (x1,y1).
- * if false, scroll point (x0, y0) to top left of viewport */
+ /** \todo Consider getting screen_width, screen_height too. */
+ unsigned *viewport_width;
+ unsigned *viewport_height;
+ } getdims;
+
+ /**
+ * CONTENT_MSG_SCROLL - Part of content to scroll to show
+ */
+ struct {
+ /*
+ * if true, scroll to show area given by (x0, y0) and (x1,y1).
+ * if false, scroll point (x0, y0) to top left of viewport
+ */
bool area;
int x0, y0;
int x1, y1;
} scroll;
- /** CONTENT_MSG_DRAGSAVE - Drag save a content */
+
+ /**
+ * CONTENT_MSG_DRAGSAVE - Drag save a content
+ */
struct {
enum {
CONTENT_SAVE_ORIG,
@@ -150,19 +177,31 @@ union content_msg_data {
/** if NULL, save the content generating the message */
struct hlcache_handle *content;
} dragsave;
- /** CONTENT_MSG_SAVELINK - Save a URL */
+
+ /**
+ * CONTENT_MSG_SAVELINK - Save a URL
+ */
struct {
struct nsurl *url;
const char *title;
} savelink;
- /** CONTENT_MSG_POINTER - Mouse pointer to set */
+
+ /**
+ * CONTENT_MSG_POINTER - Mouse pointer to set
+ */
browser_pointer_shape pointer;
- /** CONTENT_MSG_SELECTION - Selection made or cleared */
+
+ /**
+ * CONTENT_MSG_SELECTION - Selection made or cleared
+ */
struct {
bool selection; /**< false for selection cleared */
bool read_only;
} selection;
- /** CONTENT_MSG_CARET - set caret position or, hide caret */
+
+ /**
+ * CONTENT_MSG_CARET - set caret position or, hide caret
+ */
struct {
enum {
CONTENT_CARET_SET_POS,
@@ -176,7 +215,10 @@ union content_msg_data {
const struct rect *clip; /**< Carret clip rect */
} pos; /**< With CONTENT_CARET_SET_POS */
} caret;
- /** CONTENT_MSG_DRAG - Drag start or end */
+
+ /**
+ * CONTENT_MSG_DRAG - Drag start or end
+ */
struct {
enum {
CONTENT_DRAG_NONE,
@@ -185,90 +227,166 @@ union content_msg_data {
} type;
const struct rect *rect;
} drag;
- /** CONTENT_MSG_SELECTMENU - Create select menu at pointer */
+
+ /**
+ * CONTENT_MSG_SELECTMENU - Create select menu at pointer
+ */
struct {
struct form_control *gadget;
} select_menu;
- /** CONTENT_MSG_GADGETCLICK - User clicked on a form gadget */
+
+ /**
+ * CONTENT_MSG_GADGETCLICK - User clicked on a form gadget
+ */
struct {
struct form_control *gadget;
} gadget_click;
-};
-
-/* The following are for hlcache */
-void content_destroy(struct content *c);
-
-
-bool content_add_user(
- struct content *h,
- void (*callback)(
- struct content *c,
- content_msg msg,
- const union content_msg_data *data,
- void *pw),
- void *pw);
-
-
-void content_remove_user(
- struct content *c,
- void (*callback)(
- struct content *c,
- content_msg msg,
- const union content_msg_data *data,
- void *pw),
- void *pw);
-
-
-uint32_t content_count_users(struct content *c);
-
-
-bool content_matches_quirks(struct content *c, bool quirks);
-
-
-bool content_is_shareable(struct content *c);
+ /**
+ * CONTENT_MSG_TEXTSEARCH - Free text search action
+ */
+ struct {
+ /**
+ * The type of text search operation
+ */
+ enum {
+ /**
+ * Free text search find operation has started or finished
+ */
+ CONTENT_TEXTSEARCH_FIND,
+ /**
+ * Free text search match state has changed
+ */
+ CONTENT_TEXTSEARCH_MATCH,
+ /**
+ * Free text search back available state changed
+ */
+ CONTENT_TEXTSEARCH_BACK,
+ /**
+ * Free text search forward available state changed
+ */
+ CONTENT_TEXTSEARCH_FORWARD,
+ /**
+ * add a search query string to the recent searches
+ */
+ CONTENT_TEXTSEARCH_RECENT
+ } type;
+ /**
+ * context passed to browser_window_search()
+ */
+ void *ctx;
+ /**
+ * state for operation
+ */
+ bool state;
+ /**
+ * search string
+ */
+ const char *string;
+ } textsearch;
-/* only used by cocoa apple image handling and for getting nsurl of content */
-const struct llcache_handle *content_get_llcache_handle(struct content *c);
+};
/**
- * Retrieve URL associated with content
+ * Get whether a content can reformat
*
- * \param c Content to retrieve URL from
- * \return Pointer to URL, or NULL if not found.
+ * \param h content to check
+ * \return whether the content can reformat
*/
-struct nsurl *content_get_url(struct content *c);
-
-struct content *content_clone(struct content *c);
-
-nserror content_abort(struct content *c);
-
-/* Client functions */
bool content_can_reformat(struct hlcache_handle *h);
+/**
+ * Reformat to new size.
+ *
+ * Calls the reformat function for the content.
+ */
void content_reformat(struct hlcache_handle *h, bool background,
int width, int height);
+/**
+ * Request a redraw of an area of a content
+ *
+ * \param h high-level cache handle
+ * \param x x co-ord of left edge
+ * \param y y co-ord of top edge
+ * \param width Width of rectangle
+ * \param height Height of rectangle
+ */
void content_request_redraw(struct hlcache_handle *h,
int x, int y, int width, int height);
+/**
+ * Handle mouse movements in a content window.
+ *
+ * \param h Content handle
+ * \param bw browser window
+ * \param mouse state of mouse buttons and modifier keys
+ * \param x coordinate of mouse
+ * \param y coordinate of mouse
+ */
void content_mouse_track(struct hlcache_handle *h, struct browser_window *bw,
browser_mouse_state mouse, int x, int y);
+/**
+ * Handle mouse clicks and movements in a content window.
+ *
+ * \param h Content handle
+ * \param bw browser window
+ * \param mouse state of mouse buttons and modifier keys
+ * \param x coordinate of mouse
+ * \param y coordinate of mouse
+ *
+ * This function handles both hovering and clicking. It is important that the
+ * code path is identical (except that hovering doesn't carry out the action),
+ * so that the status bar reflects exactly what will happen. Having separate
+ * code paths opens the possibility that an attacker will make the status bar
+ * show some harmless action where clicking will be harmful.
+ */
void content_mouse_action(struct hlcache_handle *h, struct browser_window *bw,
browser_mouse_state mouse, int x, int y);
+/**
+ * Handle keypresses.
+ *
+ * \param h Content handle
+ * \param key The UCS4 character codepoint
+ * \return true if key handled, false otherwise
+ */
bool content_keypress(struct hlcache_handle *h, uint32_t key);
-void content_open(struct hlcache_handle *h, struct browser_window *bw,
+/**
+ * A window containing the content has been opened.
+ *
+ * \param h handle to content that has been opened
+ * \param bw browser window containing the content
+ * \param page content of type CONTENT_HTML containing h, or NULL if not an
+ * object within a page
+ * \param params object parameters, or NULL if not an object
+ *
+ * Calls the open function for the content.
+ */
+nserror content_open(struct hlcache_handle *h, struct browser_window *bw,
struct content *page, struct object_params *params);
-void content_close(struct hlcache_handle *h);
+/**
+ * The window containing the content has been closed.
+ *
+ * Calls the close function for the content.
+ */
+nserror content_close(struct hlcache_handle *h);
+/**
+ * Tell a content that any selection it has, or one of its objects
+ * has, must be cleared.
+ */
void content_clear_selection(struct hlcache_handle *h);
+/**
+ * Get a text selection from a content. Ownership is passed to the caller,
+ * who must free() it.
+ */
char * content_get_selection(struct hlcache_handle *h);
/**
@@ -282,17 +400,26 @@ char * content_get_selection(struct hlcache_handle *h);
nserror content_get_contextual_content(struct hlcache_handle *h,
int x, int y, struct browser_window_features *data);
+/**
+ * scroll content at coordnate
+ *
+ * \param[in] h Handle to content to examine.
+ * \param[in] x The x coordinate to examine.
+ * \param[in] y The y coordinate to examine.
+ */
bool content_scroll_at_point(struct hlcache_handle *h,
int x, int y, int scrx, int scry);
+/**
+ * Drag and drop a file at coordinate
+ *
+ * \param[in] h Handle to content to examine.
+ * \param[in] x The x coordinate to examine.
+ * \param[in] y The y coordinate to examine.
+ */
bool content_drop_file_at_point(struct hlcache_handle *h,
int x, int y, char *file);
-void content_search(struct hlcache_handle *h, void *context,
- search_flags_t flags, const char *string);
-
-void content_search_clear(struct hlcache_handle *h);
-
/**
* Control debug con a content.
@@ -387,6 +514,29 @@ bool content_get_quirks(struct hlcache_handle *h);
bool content_is_locked(struct hlcache_handle *h);
+/**
+ * Execute some JavaScript code inside a content object.
+ *
+ * Runs the passed in JavaScript code in the content object's context.
+ *
+ * \param h The handle to the content
+ * \param src The JavaScript source code
+ * \param srclen The length of the source code
+ * \return Whether the JS function was successfully injected into the content
+ */
+bool content_exec(struct hlcache_handle *h, const char *src, size_t srclen);
+/**
+ * Determine if the content referred to any insecure objects.
+ *
+ * Query the content to determine if any of its referred objects were loaded
+ * in a manner not considered secure. For a content to be recursively
+ * secure it must only load over https and must not have certificate overrides
+ * in place.
+ *
+ * \param h The handle to the content
+ * \return Whether the content referred to any insecure objects
+ */
+bool content_saw_insecure_objects(struct hlcache_handle *h);
#endif
diff --git a/content/content_factory.c b/content/content_factory.c
index 935354a5d..44fc333c8 100644
--- a/content/content_factory.c
+++ b/content/content_factory.c
@@ -16,8 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Content factory (implementation)
+/**
+ * \file
+ * Content factory implementation
*/
#include <assert.h>
diff --git a/content/content_factory.h b/content/content_factory.h
index 9beeb193c..354a1789f 100644
--- a/content/content_factory.h
+++ b/content/content_factory.h
@@ -46,13 +46,12 @@ nserror HNAME##_init(void) \
struct content;
struct llcache_handle;
-
-typedef struct content_handler content_handler;
+struct content_handler;
void content_factory_fini(void);
nserror content_factory_register_handler(const char *mime_type,
- const content_handler *handler);
+ const struct content_handler *handler);
struct content *content_factory_create_content(struct llcache_handle *llcache,
const char *fallback_charset, bool quirks,
diff --git a/content/content_protected.h b/content/content_protected.h
index 21b73a662..fd0924d64 100644
--- a/content/content_protected.h
+++ b/content/content_protected.h
@@ -17,24 +17,45 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Content handling (interface).
+/**
+ * \file
+ * Protected interface to Content handling.
*
* The content functions manipulate struct contents, which correspond to URLs.
*/
-#ifndef _NETSURF_CONTENT_CONTENT_PROTECTED_H_
-#define _NETSURF_CONTENT_CONTENT_PROTECTED_H_
+#ifndef NETSURF_CONTENT_CONTENT_PROTECTED_H_
+#define NETSURF_CONTENT_CONTENT_PROTECTED_H_
#include <stdio.h>
+#include <libwapcaplet/libwapcaplet.h>
-#include "utils/nsurl.h"
#include "netsurf/content_type.h"
-#include "content/content.h"
+#include "netsurf/mouse.h" /* mouse state enums */
+struct nsurl;
struct content_redraw_data;
+union content_msg_data;
struct http_parameter;
+struct llcache_handle;
+struct object_params;
+struct content;
+struct redraw_context;
+struct rect;
+struct browser_window;
+struct browser_window_features;
+struct textsearch_context;
+struct box;
+struct selection;
+struct selection_string;
+
+typedef struct content_handler content_handler;
+/**
+ * Content operation function table
+ *
+ * function table implementing a content type.
+ */
struct content_handler {
void (*fini)(void);
@@ -45,23 +66,23 @@ struct content_handler {
const char *fallback_charset, bool quirks,
struct content **c);
- bool (*process_data)(struct content *c,
+ bool (*process_data)(struct content *c,
const char *data, unsigned int size);
bool (*data_complete)(struct content *c);
void (*reformat)(struct content *c, int width, int height);
void (*destroy)(struct content *c);
void (*stop)(struct content *c);
- void (*mouse_track)(struct content *c, struct browser_window *bw,
+ nserror (*mouse_track)(struct content *c, struct browser_window *bw,
browser_mouse_state mouse, int x, int y);
- void (*mouse_action)(struct content *c, struct browser_window *bw,
+ nserror (*mouse_action)(struct content *c, struct browser_window *bw,
browser_mouse_state mouse, int x, int y);
bool (*keypress)(struct content *c, uint32_t key);
bool (*redraw)(struct content *c, struct content_redraw_data *data,
const struct rect *clip,
const struct redraw_context *ctx);
- void (*open)(struct content *c, struct browser_window *bw,
+ nserror (*open)(struct content *c, struct browser_window *bw,
struct content *page, struct object_params *params);
- void (*close)(struct content *c);
+ nserror (*close)(struct content *c);
void (*clear_selection)(struct content *c);
char * (*get_selection)(struct content *c);
nserror (*get_contextual_content)(struct content *c, int x, int y,
@@ -70,9 +91,6 @@ struct content_handler {
int scrx, int scry);
bool (*drop_file_at_point)(struct content *c, int x, int y,
char *file);
- void (*search)(struct content *c, void *context, search_flags_t flags,
- const char *string);
- void (*search_clear)(struct content *c);
nserror (*debug_dump)(struct content *c, FILE *f, enum content_debug op);
nserror (*debug)(struct content *c, enum content_debug op);
nserror (*clone)(const struct content *old, struct content **newc);
@@ -81,15 +99,69 @@ struct content_handler {
content_type (*type)(void);
void (*add_user)(struct content *c);
void (*remove_user)(struct content *c);
+ bool (*exec)(struct content *c, const char *src, size_t srclen);
+ bool (*saw_insecure_objects)(struct content *c);
+
+ /**
+ * content specific free text search find
+ */
+ nserror (*textsearch_find)(struct content *c, struct textsearch_context *context, const char *pattern, int p_len, bool case_sens);
+
+ /**
+ * get bounds of free text search match
+ */
+ nserror (*textsearch_bounds)(struct content *c, unsigned start_idx, unsigned end_idx, struct box *start_ptr, struct box *end_ptr, struct rect *bounds_out);
+
+ /**
+ * redraw an area of selected text
+ *
+ * The defined text selection will cause an area of the
+ * content to be marked as invalid and hence redrawn.
+ *
+ * \param c The content being redrawn
+ * \param start_idx The start index of the text region to be redrawn
+ * \param end_idx The end index of teh text region to be redrawn
+ * \return NSERROR_OK on success else error code
+ */
+ nserror (*textselection_redraw)(struct content *c, unsigned start_idx, unsigned end_idx);
+
+ /**
+ * copy selected text into selection string possibly with formatting
+ */
+ nserror (*textselection_copy)(struct content *c, unsigned start_idx, unsigned end_idx, struct selection_string *selstr);
+
+ /**
+ * get maximum index of text section.
+ *
+ * \param[in] c The content to measure
+ * \param[out] end_idx pointer to value to recive result
+ * \return NSERROR_OK and \a end_idx updated else error code
+ */
+ nserror (*textselection_get_end)(struct content *c, unsigned *end_idx);
- /** handler dependant content sensitive internal data interface. */
- void * (*get_internal)(const struct content *c, void *context);
+ /**
+ * handler dependant content sensitive internal data interface.
+ */
+ void *(*get_internal)(const struct content *c, void *context);
+
+ /**
+ * are the content contents opaque.
+ *
+ * Determine if this content would obscure (not mix with) any background
+ *
+ * \param c The content to check
+ */
+ bool (*is_opaque)(struct content *c);
- /** There must be one content per user for this type. */
+ /**
+ * There must be one content per user for this type.
+ */
bool no_share;
};
-/** Linked list of users of a content. */
+/**
+ * Linked list of users of a content.
+ */
struct content_user
{
void (*callback)(
@@ -102,92 +174,233 @@ struct content_user
struct content_user *next;
};
-/** Corresponds to a single URL. */
+/**
+ * Content which corresponds to a single URL.
+ */
struct content {
- struct llcache_handle *llcache; /**< Low-level cache object */
+ /**
+ * Low-level cache object
+ */
+ struct llcache_handle *llcache;
- lwc_string *mime_type; /**< Original MIME type of data */
+ /**
+ * Original MIME type of data
+ */
+ lwc_string *mime_type;
- const struct content_handler *handler; /**< Handler for content */
+ /**
+ * Handler for content
+ */
+ const struct content_handler *handler;
- content_status status; /**< Current status. */
+ /**
+ * Current status.
+ */
+ content_status status;
- int width, height; /**< Dimensions, if applicable. */
- int available_width; /**< Available width (eg window width). */
+ /**
+ * Width dimension, if applicable.
+ */
+ int width;
+ /**
+ * Height dimension, if applicable.
+ */
+ int height;
+ /**
+ * Viewport width.
+ */
+ int available_width;
+ /**
+ * Viewport height.
+ */
+ int available_height;
- bool quirks; /**< Content is in quirks mode */
- char *fallback_charset; /**< Fallback charset, or NULL */
+ /**
+ * Content is in quirks mode
+ */
+ bool quirks;
+ /**
+ * Fallback charset, or NULL
+ */
+ char *fallback_charset;
- nsurl *refresh; /**< URL for refresh request */
+ /**
+ * URL for refresh request
+ */
+ struct nsurl *refresh;
- struct content_rfc5988_link *links; /**< list of metadata links */
+ /**
+ * list of metadata links
+ */
+ struct content_rfc5988_link *links;
- /** Creation timestamp when LOADING or READY.
- * Total time in ms when DONE.
+ /**
+ * Creation timestamp when LOADING or READY. Total time in ms
+ * when DONE.
*/
uint64_t time;
- uint64_t reformat_time; /**< Earliest time to attempt a period
- * reflow while fetching a page's objects.
- */
-
- unsigned int size; /**< Estimated size of all data
- associated with this content */
- char *title; /**< Title for browser window. */
- unsigned int active; /**< Number of child fetches or
- conversions currently in progress. */
- struct content_user *user_list; /**< List of users. */
- char status_message[120]; /**< Full text for status bar. */
- char sub_status[80]; /**< Status of content. */
- /** Content is being processed: data structures may be inconsistent
- * and content must not be redrawn or modified. */
+ /**
+ * Earliest time to attempt a period reflow while fetching a
+ * page's objects.
+ */
+ uint64_t reformat_time;
+
+ /**
+ * Estimated size of all data associated with this content
+ */
+ unsigned int size;
+ /**
+ * Title for browser window.
+ */
+ char *title;
+ /**
+ * Number of child fetches or conversions currently in progress.
+ */
+ unsigned int active;
+ /**
+ * List of users.
+ */
+ struct content_user *user_list;
+ /**
+ * Full text for status bar.
+ */
+ char status_message[120];
+ /**
+ * Status of content.
+ */
+ char sub_status[80];
+ /**
+ * Content is being processed: data structures may be
+ * inconsistent and content must not be redrawn or modified.
+ */
bool locked;
- unsigned long total_size; /**< Total data size, 0 if unknown. */
- long http_code; /**< HTTP status code, 0 if not HTTP. */
+ /**
+ * Total data size, 0 if unknown.
+ */
+ unsigned long total_size;
+ /**
+ * HTTP status code, 0 if not HTTP.
+ */
+ long http_code;
- /** Array of first n rendering errors or warnings. */
+ /**
+ * Free text search state
+ */
struct {
- const char *token;
- unsigned int line; /**< Line no, 0 if not applicable. */
- } error_list[40];
- unsigned int error_count; /**< Number of valid error entries. */
+ char *string;
+ struct textsearch_context *context;
+ } textsearch;
};
extern const char * const content_type_name[];
extern const char * const content_status_name[];
+
+/**
+ * Initialise a new base content structure.
+ *
+ * \param c Content to initialise
+ * \param handler Content handler
+ * \param imime_type MIME type of content
+ * \param params HTTP parameters
+ * \param llcache Source data handle
+ * \param fallback_charset Fallback charset
+ * \param quirks Quirkiness of content
+ * \return NSERROR_OK on success, appropriate error otherwise
+ */
nserror content__init(struct content *c, const struct content_handler *handler,
lwc_string *imime_type, const struct http_parameter *params,
struct llcache_handle *llcache, const char *fallback_charset,
bool quirks);
+
+/**
+ * Clone a content's data members
+ *
+ * \param c Content to clone
+ * \param nc Content to populate
+ * \return NSERROR_OK on success, appropriate error otherwise
+ */
nserror content__clone(const struct content *c, struct content *nc);
+/**
+ * Put a content in status CONTENT_STATUS_READY and unlock the content.
+ */
void content_set_ready(struct content *c);
+
+/**
+ * Put a content in status CONTENT_STATUS_DONE.
+ */
void content_set_done(struct content *c);
+
+/**
+ * Put a content in status CONTENT_STATUS_ERROR and unlock the content.
+ *
+ * \note We expect the caller to broadcast an error report if needed.
+ */
void content_set_error(struct content *c);
+/**
+ * Updates content with new status.
+ *
+ * The textual status contained in the content is updated with given string.
+ *
+ * \param c The content to set status in.
+ * \param status_message new textual status
+ */
void content_set_status(struct content *c, const char *status_message);
-void content_broadcast(struct content *c, content_msg msg,
- const union content_msg_data *data);
+
+/**
+ * Send a message to all users.
+ */
+void content_broadcast(struct content *c, content_msg msg, const union content_msg_data *data);
+
/**
- * Send an errorcode message to all users.
+ * Send an error message to all users.
+ *
+ * \param c The content whose users should be informed of an error
+ * \param errorcode The nserror code to send
+ * \param msg The error message to send alongside
*/
-void content_broadcast_errorcode(struct content *c, nserror errorcode);
+void content_broadcast_error(struct content *c, nserror errorcode, const char *msg);
-void content_add_error(struct content *c, const char *token,
- unsigned int line);
+/**
+ * associate a metadata link with a content.
+ *
+ * \param c content to add link to
+ * \param link The rfc5988 link to add
+ */
+bool content__add_rfc5988_link(struct content *c, const struct content_rfc5988_link *link);
-bool content__add_rfc5988_link(struct content *c,
- const struct content_rfc5988_link *link);
-struct content_rfc5988_link *content__free_rfc5988_link(
- struct content_rfc5988_link *link);
+/**
+ * free a rfc5988 link
+ *
+ * \param link The link to free
+ * \return The next link in the chain
+ */
+struct content_rfc5988_link *content__free_rfc5988_link(struct content_rfc5988_link *link);
-void content__reformat(struct content *c, bool background,
- int width, int height);
-void content__request_redraw(struct content *c,
- int x, int y, int width, int height);
+/**
+ * cause a content to be reformatted.
+ *
+ * \param c content to be reformatted
+ * \param background perform reformat in background
+ * \param width The available width to reformat content in
+ * \param height The available height to reformat content in
+ */
+void content__reformat(struct content *c, bool background, int width, int height);
+/**
+ * Request a redraw of an area of a content
+ *
+ * \param c Content
+ * \param x x co-ord of left edge
+ * \param y y co-ord of top edge
+ * \param width Width of rectangle
+ * \param height Height of rectangle
+ */
+void content__request_redraw(struct content *c, int x, int y, int width, int height);
/**
* Retrieve mime-type of content
@@ -253,7 +466,7 @@ int content__get_available_width(struct content *c);
* \param size Pointer to location to receive byte size of source.
* \return Pointer to source data.
*/
-const char *content__get_source_data(struct content *c, unsigned long *size);
+const uint8_t *content__get_source_data(struct content *c, size_t *size);
/**
* Invalidate content reuse data.
@@ -272,7 +485,7 @@ void content__invalidate_reuse_data(struct content *c);
* \param c Content to retrieve refresh URL from
* \return Pointer to URL or NULL if none
*/
-nsurl *content__get_refresh_url(struct content *c);
+struct nsurl *content__get_refresh_url(struct content *c);
/**
* Retrieve the bitmap contained in an image content
@@ -308,4 +521,108 @@ const char *content__get_encoding(struct content *c, enum content_encoding_type
*/
bool content__is_locked(struct content *c);
+/**
+ * Destroy and free a content.
+ *
+ * Calls the destroy function for the content, and frees the structure.
+ */
+void content_destroy(struct content *c);
+
+/**
+ * Register a user for callbacks.
+ *
+ * \param c the content to register
+ * \param callback the user callback function
+ * \param pw callback private data
+ * \return true on success, false otherwise on memory exhaustion
+ *
+ * The callback will be called when content_broadcast() is
+ * called with the content.
+ */
+bool content_add_user(struct content *h,
+ void (*callback)(
+ struct content *c,
+ content_msg msg,
+ const union content_msg_data *data,
+ void *pw),
+ void *pw);
+
+/**
+ * Remove a callback user.
+ *
+ * The callback function and pw must be identical to those passed to
+ * content_add_user().
+ *
+ * \param c Content to remove user from
+ * \param callback passed when added
+ * \param ctx Context passed when added
+ */
+void content_remove_user(struct content *c,
+ void (*callback)(
+ struct content *c,
+ content_msg msg,
+ const union content_msg_data *data,
+ void *pw),
+ void *ctx);
+
+
+/**
+ * Count users for the content.
+ *
+ * \param c Content to consider
+ */
+uint32_t content_count_users(struct content *c);
+
+
+/**
+ * Determine if quirks mode matches
+ *
+ * \param c Content to consider
+ * \param quirks Quirks mode to match
+ * \return True if quirks match, false otherwise
+ */
+bool content_matches_quirks(struct content *c, bool quirks);
+
+/**
+ * Determine if a content is shareable
+ *
+ * \param c Content to consider
+ * \return True if content is shareable, false otherwise
+ */
+bool content_is_shareable(struct content *c);
+
+/**
+ * Retrieve the low-level cache handle for a content
+ *
+ * \note only used by hlcache
+ *
+ * \param c Content to retrieve from
+ * \return Low-level cache handle
+ */
+const struct llcache_handle *content_get_llcache_handle(struct content *c);
+
+/**
+ * Retrieve URL associated with content
+ *
+ * \param c Content to retrieve URL from
+ * \return Pointer to URL, or NULL if not found.
+ */
+struct nsurl *content_get_url(struct content *c);
+
+/**
+ * Clone a content object in its current state.
+ *
+ * \param c Content to clone
+ * \return Clone of \a c
+ */
+struct content *content_clone(struct content *c);
+
+/**
+ * Abort a content object
+ *
+ * \param c The content object to abort
+ * \return NSERROR_OK on success, otherwise appropriate error
+ */
+nserror content_abort(struct content *c);
+
#endif
diff --git a/content/fetch.c b/content/fetch.c
index 766502941..1fcc3f996 100644
--- a/content/fetch.c
+++ b/content/fetch.c
@@ -53,10 +53,10 @@
#include "content/fetch.h"
#include "content/fetchers.h"
#include "content/fetchers/resource.h"
-#include "content/fetchers/about.h"
+#include "content/fetchers/about/about.h"
#include "content/fetchers/curl.h"
#include "content/fetchers/data.h"
-#include "content/fetchers/file.h"
+#include "content/fetchers/file/file.h"
#include "javascript/fetcher.h"
#include "content/urldb.h"
@@ -90,7 +90,6 @@ struct fetch {
fetch_callback callback;/**< Callback function. */
nsurl *url; /**< URL. */
nsurl *referer; /**< Referer URL. */
- bool send_referer; /**< Valid to send the referer */
bool verifiable; /**< Transaction is verifiable */
void *p; /**< Private data for callback. */
lwc_string *host; /**< Host part of URL, interned */
@@ -98,6 +97,7 @@ struct fetch {
int fetcherd; /**< Fetcher descriptor for this fetch */
void *fetcher_handle; /**< The handle for the fetcher. */
bool fetch_is_active; /**< This fetch is active. */
+ fetch_msg_type last_msg;/**< The last message sent for this fetch */
struct fetch *r_prev; /**< Previous active fetch in ::fetch_ring. */
struct fetch *r_next; /**< Next active fetch in ::fetch_ring. */
};
@@ -460,9 +460,8 @@ fetch_start(nsurl *url,
{
struct fetch *fetch;
lwc_string *scheme;
- bool match;
- fetch = malloc(sizeof (*fetch));
+ fetch = calloc(1, sizeof (*fetch));
if (fetch == NULL) {
return NSERROR_NOMEM;
}
@@ -473,8 +472,8 @@ fetch_start(nsurl *url,
/* try and obtain a fetcher for this scheme */
fetch->fetcherd = get_fetcher_for_scheme(scheme);
+ lwc_string_unref(scheme);
if (fetch->fetcherd == -1) {
- lwc_string_unref(scheme);
free(fetch);
return NSERROR_NO_FETCH_HANDLER;
}
@@ -486,58 +485,12 @@ fetch_start(nsurl *url,
fetch->url = nsurl_ref(url);
fetch->verifiable = verifiable;
fetch->p = p;
- fetch->http_code = 0;
- fetch->r_prev = NULL;
- fetch->r_next = NULL;
- fetch->referer = NULL;
- fetch->send_referer = false;
- fetch->fetcher_handle = NULL;
- fetch->fetch_is_active = false;
fetch->host = nsurl_get_component(url, NSURL_HOST);
if (referer != NULL) {
- lwc_string *ref_scheme;
fetch->referer = nsurl_ref(referer);
-
- ref_scheme = nsurl_get_component(referer, NSURL_SCHEME);
- /* Not a problem if referer has no scheme */
-
- /* Determine whether to send the Referer header */
- if (nsoption_bool(send_referer) && ref_scheme != NULL) {
- /* User permits us to send the header
- * Only send it if:
- * 1) The fetch and referer schemes match
- * or 2) The fetch is https and the referer is http
- *
- * This ensures that referer information is only sent
- * across schemes in the special case of an https
- * request from a page served over http. The inverse
- * (https -> http) should not send the referer (15.1.3)
- */
- bool match1;
- bool match2;
- if (lwc_string_isequal(scheme, ref_scheme,
- &match) != lwc_error_ok) {
- match = false;
- }
- if (lwc_string_isequal(scheme, corestring_lwc_https,
- &match1) != lwc_error_ok) {
- match1 = false;
- }
- if (lwc_string_isequal(ref_scheme, corestring_lwc_http,
- &match2) != lwc_error_ok) {
- match2= false;
- }
- if (match == true || (match1 == true && match2 == true))
- fetch->send_referer = true;
- }
- if (ref_scheme != NULL)
- lwc_string_unref(ref_scheme);
}
- /* these aren't needed past here */
- lwc_string_unref(scheme);
-
/* try and set up the fetch */
fetch->fetcher_handle = fetchers[fetch->fetcherd].ops.setup(fetch, url,
only_2xx, downgrade_tls,
@@ -584,6 +537,7 @@ fetch_start(nsurl *url,
void fetch_abort(struct fetch *f)
{
assert(f);
+ f->last_msg = FETCH__INTERNAL_ABORTED;
NSLOG(fetch, DEBUG,
"fetch %p, fetcher %p, url '%s'", f, f->fetcher_handle,
nsurl_access(f->url));
@@ -593,6 +547,20 @@ void fetch_abort(struct fetch *f)
/* exported interface documented in content/fetch.h */
void fetch_free(struct fetch *f)
{
+ if (f->last_msg < FETCH_MIN_FINISHED_MSG) {
+ /* We didn't finish, so tell our user that an error occurred */
+ fetch_msg msg;
+
+ msg.type = FETCH_ERROR;
+ msg.data.error = "FetchFailedToFinish";
+
+ NSLOG(fetch, CRITICAL,
+ "During the fetch of %s, the fetcher did not finish.",
+ nsurl_access(f->url));
+
+ fetch_send_callback(&msg, f);
+ }
+
NSLOG(fetch, DEBUG,
"Freeing fetch %p, fetcher %p",
f,
@@ -712,6 +680,23 @@ fetch_multipart_data_clone(const struct fetch_multipart_data *list)
return result;
}
+
+/* exported interface documented in content/fetch.h */
+const char *
+fetch_multipart_data_find(const struct fetch_multipart_data *list,
+ const char *name)
+{
+ while (list != NULL) {
+ if (strcmp(list->name, name) == 0) {
+ return list->value;
+ }
+ list = list->next;
+ }
+
+ return NULL;
+}
+
+
/* exported interface documented in content/fetch.h */
void fetch_multipart_data_destroy(struct fetch_multipart_data *list)
{
@@ -730,10 +715,50 @@ void fetch_multipart_data_destroy(struct fetch_multipart_data *list)
}
}
+
+/* exported interface documented in content/fetch.h */
+nserror
+fetch_multipart_data_new_kv(struct fetch_multipart_data **list,
+ const char *name,
+ const char *value)
+{
+ struct fetch_multipart_data *newdata;
+
+ assert(list);
+
+ newdata = calloc(sizeof(*newdata), 1);
+
+ if (newdata == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ newdata->name = strdup(name);
+ if (newdata->name == NULL) {
+ free(newdata);
+ return NSERROR_NOMEM;
+ }
+
+ newdata->value = strdup(value);
+ if (newdata->value == NULL) {
+ free(newdata->name);
+ free(newdata);
+ return NSERROR_NOMEM;
+ }
+
+ newdata->next = *list;
+ *list = newdata;
+
+ return NSERROR_OK;
+}
+
+
/* exported interface documented in content/fetch.h */
void
fetch_send_callback(const fetch_msg *msg, struct fetch *fetch)
{
+ /* Bump the last_msg to the greatest seen msg */
+ if (msg->type > fetch->last_msg)
+ fetch->last_msg = msg->type;
fetch->callback(msg, fetch->p);
}
@@ -773,13 +798,6 @@ void fetch_set_http_code(struct fetch *fetch, long http_code)
fetch->http_code = http_code;
}
-/* exported interface documented in content/fetch.h */
-const char *fetch_get_referer_to_send(struct fetch *fetch)
-{
- if (fetch->send_referer)
- return nsurl_access(fetch->referer);
- return NULL;
-}
/* exported interface documented in content/fetch.h */
void fetch_set_cookie(struct fetch *fetch, const char *data)
diff --git a/content/fetch.h b/content/fetch.h
index 5521778ea..e7180d0c3 100644
--- a/content/fetch.h
+++ b/content/fetch.h
@@ -28,15 +28,21 @@
#include "utils/config.h"
#include "utils/nsurl.h"
#include "utils/inet.h"
+#include "netsurf/ssl_certs.h"
struct content;
struct fetch;
struct ssl_cert_info;
+/**
+ * Fetcher message types
+ */
typedef enum {
FETCH_PROGRESS,
+ FETCH_CERTS,
FETCH_HEADER,
FETCH_DATA,
+ /* Anything after here is a completed fetch of some kind. */
FETCH_FINISHED,
FETCH_TIMEDOUT,
FETCH_ERROR,
@@ -47,6 +53,22 @@ typedef enum {
FETCH_SSL_ERR
} fetch_msg_type;
+/** Minimum finished message type.
+ *
+ * If a fetch does not progress this far, it's an error and the fetch machinery
+ * will send FETCH_ERROR to the llcache on fetch_free()
+ */
+#define FETCH_MIN_FINISHED_MSG FETCH_FINISHED
+
+/**
+ * This message is actually an internal message used to indicate
+ * that a fetch was aborted. Do not send this, nor expect it.
+ */
+#define FETCH__INTERNAL_ABORTED FETCH_ERROR
+
+/**
+ * Fetcher message data
+ */
typedef struct fetch_msg {
fetch_msg_type type;
@@ -67,34 +89,47 @@ typedef struct fetch_msg {
const char *realm;
} auth;
- struct {
- const struct ssl_cert_info *certs;
- size_t num_certs;
- } cert_err;
+ const struct cert_chain *chain;
} data;
} fetch_msg;
-/** Fetch POST multipart data */
+/**
+ * Fetcher post data types
+ */
+typedef enum {
+ FETCH_POSTDATA_NONE,
+ FETCH_POSTDATA_URLENC,
+ FETCH_POSTDATA_MULTIPART,
+} fetch_postdata_type;
+
+
+/**
+ * Fetch POST multipart data
+ */
struct fetch_multipart_data {
- bool file; /**< Item is a file */
- char *name; /**< Name of item */
- char *value; /**< Item value */
- char *rawfile; /**< Raw filename if file is true */
+ struct fetch_multipart_data *next; /**< Next in linked list */
- struct fetch_multipart_data *next; /**< Next in linked list */
+ char *name; /**< Name of item */
+ char *value; /**< Item value */
+
+ char *rawfile; /**< Raw filename if file is true */
+ bool file; /**< Item is a file */
};
-struct ssl_cert_info {
- long version; /**< Certificate version */
- char not_before[32]; /**< Valid from date */
- char not_after[32]; /**< Valid to date */
- int sig_type; /**< Signature type */
- long serial; /**< Serial number */
- char issuer[256]; /**< Issuer details */
- char subject[256]; /**< Subject details */
- int cert_type; /**< Certificate type */
+/**
+ * fetch POST data
+ */
+struct fetch_postdata {
+ fetch_postdata_type type;
+ union {
+ /** Url encoded POST string if type is FETCH_POSTDATA_URLENC */
+ char *urlenc;
+ /** Multipart post data if type is FETCH_POSTDATA_MULTIPART */
+ struct fetch_multipart_data *multipart;
+ } data;
};
+
typedef void (*fetch_callback)(const fetch_msg *msg, void *p);
/**
@@ -175,6 +210,30 @@ void fetch_multipart_data_destroy(struct fetch_multipart_data *list);
struct fetch_multipart_data *fetch_multipart_data_clone(const struct fetch_multipart_data *list);
/**
+ * Find an entry in a fetch_multipart_data
+ *
+ * \param list Pointer to the multipart list
+ * \param name The name to look for in the list
+ * \return The value found, or NULL if not present
+ */
+const char *fetch_multipart_data_find(const struct fetch_multipart_data *list,
+ const char *name);
+
+/**
+ * Create an entry for a fetch_multipart_data
+ *
+ * If an entry exists of the same name, it will *NOT* be overwritten
+ *
+ * \param list Pointer to the pointer to the current multipart list
+ * \param name The name of the entry to create
+ * \param value The value of the entry to create
+ * \return The result of the attempt
+ */
+nserror fetch_multipart_data_new_kv(struct fetch_multipart_data **list,
+ const char *name,
+ const char *value);
+
+/**
* send message to fetch
*/
void fetch_send_callback(const fetch_msg *msg, struct fetch *fetch);
@@ -195,11 +254,6 @@ void fetch_free(struct fetch *f);
void fetch_set_http_code(struct fetch *fetch, long http_code);
/**
- * get the referer from the fetch
- */
-const char *fetch_get_referer_to_send(struct fetch *fetch);
-
-/**
* set cookie data on a fetch
*/
void fetch_set_cookie(struct fetch *fetch, const char *data);
diff --git a/content/fetchers/Makefile b/content/fetchers/Makefile
index 9c8479320..8f6e5211f 100644
--- a/content/fetchers/Makefile
+++ b/content/fetchers/Makefile
@@ -1,10 +1,15 @@
# Content fetchers sources
-S_FETCHERS_YES := data.c file.c about.c resource.c
+S_FETCHERS_YES := data.c resource.c
S_FETCHERS_NO :=
S_FETCHERS_$(NETSURF_USE_CURL) += curl.c
-S_FETCHERS := $(addprefix content/fetchers/,$(S_FETCHERS_YES))
+S_FETCHERS := $(addprefix fetchers/,$(S_FETCHERS_YES))
-# The following files depend on the testament
-content/fetchers/about.c: testament $(OBJROOT)/testament.h
+# about fetcher
+include content/fetchers/about/Makefile
+S_FETCHERS += $(addprefix fetchers/about/,$(S_FETCHER_ABOUT))
+
+# file fetcher
+include content/fetchers/file/Makefile
+S_FETCHERS += $(addprefix fetchers/file/,$(S_FETCHER_FILE))
diff --git a/content/fetchers/about.c b/content/fetchers/about.c
deleted file mode 100644
index 4d14020b0..000000000
--- a/content/fetchers/about.c
+++ /dev/null
@@ -1,862 +0,0 @@
-/*
- * Copyright 2011 Vincent Sanders <vince@netsurf-browser.org>
- *
- * This file is part of NetSurf.
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- *
- * URL handling for the "about" scheme.
- *
- * Based on the data fetcher by Rob Kendrick
- * This fetcher provides a simple scheme for the user to access
- * information from the browser from a known, fixed URL.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-#include "testament.h"
-#include "utils/corestrings.h"
-#include "utils/nsoption.h"
-#include "utils/utils.h"
-#include "utils/ring.h"
-
-#include "content/fetch.h"
-#include "content/fetchers.h"
-#include "content/fetchers/about.h"
-#include "image/image_cache.h"
-
-
-struct fetch_about_context;
-
-typedef bool (*fetch_about_handler)(struct fetch_about_context *);
-
-/** Context for an about fetch */
-struct fetch_about_context {
- struct fetch_about_context *r_next, *r_prev;
-
- struct fetch *fetchh; /**< Handle for this fetch */
-
- bool aborted; /**< Flag indicating fetch has been aborted */
- bool locked; /**< Flag indicating entry is already entered */
-
- nsurl *url; /**< The full url the fetch refers to */
-
- fetch_about_handler handler;
-};
-
-static struct fetch_about_context *ring = NULL;
-
-/** issue fetch callbacks with locking */
-static inline bool fetch_about_send_callback(const fetch_msg *msg,
- struct fetch_about_context *ctx)
-{
- ctx->locked = true;
- fetch_send_callback(msg, ctx->fetchh);
- ctx->locked = false;
-
- return ctx->aborted;
-}
-
-static bool fetch_about_send_header(struct fetch_about_context *ctx,
- const char *fmt, ...)
-{
- char header[64];
- fetch_msg msg;
- va_list ap;
-
- va_start(ap, fmt);
-
- vsnprintf(header, sizeof header, fmt, ap);
-
- va_end(ap);
-
- msg.type = FETCH_HEADER;
- msg.data.header_or_data.buf = (const uint8_t *) header;
- msg.data.header_or_data.len = strlen(header);
-
- fetch_about_send_callback(&msg, ctx);
-
- return ctx->aborted;
-}
-
-
-
-
-static bool fetch_about_blank_handler(struct fetch_about_context *ctx)
-{
- fetch_msg msg;
- const char buffer[2] = { ' ', '\0' };
-
- /* content is going to return ok */
- fetch_set_http_code(ctx->fetchh, 200);
-
- /* content type */
- if (fetch_about_send_header(ctx, "Content-Type: text/html"))
- goto fetch_about_blank_handler_aborted;
-
- msg.type = FETCH_DATA;
- msg.data.header_or_data.buf = (const uint8_t *) buffer;
- msg.data.header_or_data.len = strlen(buffer);
-
- if (fetch_about_send_callback(&msg, ctx))
- goto fetch_about_blank_handler_aborted;
-
- msg.type = FETCH_FINISHED;
-
- fetch_about_send_callback(&msg, ctx);
-
- return true;
-
-fetch_about_blank_handler_aborted:
- return false;
-}
-
-
-static bool fetch_about_credits_handler(struct fetch_about_context *ctx)
-{
- fetch_msg msg;
-
- /* content is going to return redirect */
- fetch_set_http_code(ctx->fetchh, 302);
-
- msg.type = FETCH_REDIRECT;
- msg.data.redirect = "resource:credits.html";
-
- fetch_about_send_callback(&msg, ctx);
-
- return true;
-}
-
-
-static bool fetch_about_licence_handler(struct fetch_about_context *ctx)
-{
- fetch_msg msg;
-
- /* content is going to return redirect */
- fetch_set_http_code(ctx->fetchh, 302);
-
- msg.type = FETCH_REDIRECT;
- msg.data.redirect = "resource:licence.html";
-
- fetch_about_send_callback(&msg, ctx);
-
- return true;
-}
-
-/**
- * Handler to generate about:cache page.
- *
- * Shows details of current image cache.
- *
- * \param ctx The fetcher context.
- * \return true if handled false if aborted.
- */
-static bool fetch_about_imagecache_handler(struct fetch_about_context *ctx)
-{
- fetch_msg msg;
- char buffer[2048]; /* output buffer */
- int code = 200;
- int slen;
- unsigned int cent_loop = 0;
- int res = 0;
-
- /* content is going to return ok */
- fetch_set_http_code(ctx->fetchh, code);
-
- /* content type */
- if (fetch_about_send_header(ctx, "Content-Type: text/html"))
- goto fetch_about_imagecache_handler_aborted;
-
- msg.type = FETCH_DATA;
- msg.data.header_or_data.buf = (const uint8_t *) buffer;
-
- /* page head */
- slen = snprintf(buffer, sizeof buffer,
- "<html>\n<head>\n"
- "<title>NetSurf Browser Image Cache Status</title>\n"
- "<link rel=\"stylesheet\" type=\"text/css\" "
- "href=\"resource:internal.css\">\n"
- "</head>\n"
- "<body id =\"cachelist\">\n"
- "<p class=\"banner\">"
- "<a href=\"http://www.netsurf-browser.org/\">"
- "<img src=\"resource:netsurf.png\" alt=\"NetSurf\"></a>"
- "</p>\n"
- "<h1>NetSurf Browser Image Cache Status</h1>\n" );
- msg.data.header_or_data.len = slen;
- if (fetch_about_send_callback(&msg, ctx))
- goto fetch_about_imagecache_handler_aborted;
-
- /* image cache summary */
- slen = image_cache_snsummaryf(buffer, sizeof(buffer),
- "<p>Configured limit of %a hysteresis of %b</p>\n"
- "<p>Total bitmap size in use %c (in %d)</p>\n"
- "<p>Age %es</p>\n"
- "<p>Peak size %f (in %g)</p>\n"
- "<p>Peak image count %h (size %i)</p>\n"
- "<p>Cache total/hit/miss/fail (counts) %j/%k/%l/%m "
- "(%pj%%/%pk%%/%pl%%/%pm%%)</p>\n"
- "<p>Cache total/hit/miss/fail (size) %n/%o/%q/%r "
- "(%pn%%/%po%%/%pq%%/%pr%%)</p>\n"
- "<p>Total images never rendered: %s "
- "(includes %t that were converted)</p>\n"
- "<p>Total number of excessive conversions: %u "
- "(from %v images converted more than once)"
- "</p>\n"
- "<p>Bitmap of size %w had most (%x) conversions</p>\n"
- "<h2>Current image cache contents</h2>\n");
- if (slen >= (int) (sizeof(buffer)))
- goto fetch_about_imagecache_handler_aborted; /* overflow */
-
- msg.data.header_or_data.len = slen;
- if (fetch_about_send_callback(&msg, ctx))
- goto fetch_about_imagecache_handler_aborted;
-
-
- /* image cache entry table */
- slen = snprintf(buffer, sizeof buffer,
- "<p class=\"imagecachelist\">\n"
- "<strong>"
- "<span>Entry</span>"
- "<span>Content Key</span>"
- "<span>Redraw Count</span>"
- "<span>Conversion Count</span>"
- "<span>Last Redraw</span>"
- "<span>Bitmap Age</span>"
- "<span>Bitmap Size</span>"
- "<span>Source</span>"
- "</strong>\n");
- do {
- res = image_cache_snentryf(buffer + slen, sizeof buffer - slen,
- cent_loop,
- "<a href=\"%U\">"
- "<span>%e</span>"
- "<span>%k</span>"
- "<span>%r</span>"
- "<span>%c</span>"
- "<span>%a</span>"
- "<span>%g</span>"
- "<span>%s</span>"
- "<span>%o</span>"
- "</a>\n");
- if (res <= 0)
- break; /* last option */
-
- if (res >= (int) (sizeof buffer - slen)) {
- /* last entry would not fit in buffer, submit buffer */
- msg.data.header_or_data.len = slen;
- if (fetch_about_send_callback(&msg, ctx))
- goto fetch_about_imagecache_handler_aborted;
- slen = 0;
- } else {
- /* normal addition */
- slen += res;
- cent_loop++;
- }
- } while (res > 0);
-
- slen += snprintf(buffer + slen, sizeof buffer - slen,
- "</p>\n</body>\n</html>\n");
-
- msg.data.header_or_data.len = slen;
- if (fetch_about_send_callback(&msg, ctx))
- goto fetch_about_imagecache_handler_aborted;
-
- msg.type = FETCH_FINISHED;
- fetch_about_send_callback(&msg, ctx);
-
- return true;
-
-fetch_about_imagecache_handler_aborted:
- return false;
-}
-
-/** Handler to generate about:config page */
-static bool fetch_about_config_handler(struct fetch_about_context *ctx)
-{
- fetch_msg msg;
- char buffer[1024];
- int code = 200;
- int slen;
- unsigned int opt_loop = 0;
- int res = 0;
-
- /* content is going to return ok */
- fetch_set_http_code(ctx->fetchh, code);
-
- /* content type */
- if (fetch_about_send_header(ctx, "Content-Type: text/html"))
- goto fetch_about_config_handler_aborted;
-
- msg.type = FETCH_DATA;
- msg.data.header_or_data.buf = (const uint8_t *) buffer;
-
- slen = snprintf(buffer, sizeof buffer,
- "<html>\n<head>\n"
- "<title>NetSurf Browser Config</title>\n"
- "<link rel=\"stylesheet\" type=\"text/css\" "
- "href=\"resource:internal.css\">\n"
- "</head>\n"
- "<body id =\"configlist\">\n"
- "<p class=\"banner\">"
- "<a href=\"http://www.netsurf-browser.org/\">"
- "<img src=\"resource:netsurf.png\" alt=\"NetSurf\"></a>"
- "</p>\n"
- "<h1>NetSurf Browser Config</h1>\n"
- "<table class=\"config\">\n"
- "<tr><th>Option</th><th>Type</th><th>Provenance</th><th>Setting</th></tr>\n");
-
- do {
- res = nsoption_snoptionf(buffer + slen,
- sizeof buffer - slen,
- opt_loop,
- "<tr><th>%k</th><td>%t</td><td>%p</td><td>%V</td></tr>\n");
- if (res <= 0)
- break; /* last option */
-
- if (res >= (int) (sizeof buffer - slen)) {
- /* last entry would not fit in buffer, submit buffer */
- msg.data.header_or_data.len = slen;
- if (fetch_about_send_callback(&msg, ctx))
- goto fetch_about_config_handler_aborted;
- slen = 0;
- } else {
- /* normal addition */
- slen += res;
- opt_loop++;
- }
- } while (res > 0);
-
- slen += snprintf(buffer + slen, sizeof buffer - slen,
- "</table>\n</body>\n</html>\n");
-
- msg.data.header_or_data.len = slen;
- if (fetch_about_send_callback(&msg, ctx))
- goto fetch_about_config_handler_aborted;
-
- msg.type = FETCH_FINISHED;
- fetch_about_send_callback(&msg, ctx);
-
- return true;
-
-fetch_about_config_handler_aborted:
- return false;
-}
-
-
-/** Generate the text of a Choices file which represents the current
- * in use options.
- */
-static bool fetch_about_choices_handler(struct fetch_about_context *ctx)
-{
- fetch_msg msg;
- char buffer[1024];
- int code = 200;
- int slen;
- unsigned int opt_loop = 0;
- int res = 0;
-
- /* content is going to return ok */
- fetch_set_http_code(ctx->fetchh, code);
-
- /* content type */
- if (fetch_about_send_header(ctx, "Content-Type: text/plain"))
- goto fetch_about_choices_handler_aborted;
-
- msg.type = FETCH_DATA;
- msg.data.header_or_data.buf = (const uint8_t *) buffer;
-
- slen = snprintf(buffer, sizeof buffer,
- "# Automatically generated current NetSurf browser Choices\n");
-
- do {
- res = nsoption_snoptionf(buffer + slen,
- sizeof buffer - slen,
- opt_loop,
- "%k:%v\n");
- if (res <= 0)
- break; /* last option */
-
- if (res >= (int) (sizeof buffer - slen)) {
- /* last entry would not fit in buffer, submit buffer */
- msg.data.header_or_data.len = slen;
- if (fetch_about_send_callback(&msg, ctx))
- goto fetch_about_choices_handler_aborted;
- slen = 0;
- } else {
- /* normal addition */
- slen += res;
- opt_loop++;
- }
- } while (res > 0);
-
- msg.data.header_or_data.len = slen;
- if (fetch_about_send_callback(&msg, ctx))
- goto fetch_about_choices_handler_aborted;
-
- msg.type = FETCH_FINISHED;
- fetch_about_send_callback(&msg, ctx);
-
- return true;
-
-fetch_about_choices_handler_aborted:
- return false;
-}
-
-/** Generate the text of an svn testament which represents the current
- * build-tree status
- */
-typedef struct { const char *leaf; const char *modtype; } modification_t;
-static bool fetch_about_testament_handler(struct fetch_about_context *ctx)
-{
- static modification_t modifications[] = WT_MODIFICATIONS;
- fetch_msg msg;
- char buffer[1024];
- int code = 200;
- int slen;
- int i;
-
-
- /* content is going to return ok */
- fetch_set_http_code(ctx->fetchh, code);
-
- /* content type */
- if (fetch_about_send_header(ctx, "Content-Type: text/plain"))
- goto fetch_about_testament_handler_aborted;
-
- msg.type = FETCH_DATA;
- msg.data.header_or_data.buf = (const uint8_t *) buffer;
-
- slen = snprintf(buffer, sizeof buffer,
- "# Automatically generated by NetSurf build system\n\n");
-
- msg.data.header_or_data.len = slen;
- if (fetch_about_send_callback(&msg, ctx))
- goto fetch_about_testament_handler_aborted;
-
- slen = snprintf(buffer, sizeof buffer,
-#if defined(WT_BRANCHISTRUNK) || defined(WT_BRANCHISMASTER)
- "# This is a *DEVELOPMENT* build from the main line.\n\n"
-#elif defined(WT_BRANCHISTAG) && (WT_MODIFIED == 0)
- "# This is a tagged build of NetSurf\n"
-#ifdef WT_TAGIS
- "# The tag used was '" WT_TAGIS "'\n\n"
-#else
- "\n"
-#endif
-#elif defined(WT_NO_SVN) || defined(WT_NO_GIT)
- "# This NetSurf was built outside of our revision "
- "control environment.\n"
- "# This testament is therefore not very useful.\n\n"
-#else
- "# This NetSurf was built from a branch (" WT_BRANCHPATH ").\n\n"
-#endif
-#if defined(CI_BUILD)
- "# This build carries the CI build number '" CI_BUILD "'\n\n"
-#endif
- );
-
- msg.data.header_or_data.len = slen;
- if (fetch_about_send_callback(&msg, ctx))
- goto fetch_about_testament_handler_aborted;
-
-
- slen = snprintf(buffer, sizeof buffer,
- "Built by %s (%s) from %s at revision %s on %s\n\n",
- GECOS, USERNAME, WT_BRANCHPATH, WT_REVID, WT_COMPILEDATE);
-
- msg.data.header_or_data.len = slen;
- if (fetch_about_send_callback(&msg, ctx))
- goto fetch_about_testament_handler_aborted;
-
- slen = snprintf(buffer, sizeof buffer,
- "Built on %s in %s\n\n",
- WT_HOSTNAME, WT_ROOT);
-
- msg.data.header_or_data.len = slen;
- if (fetch_about_send_callback(&msg, ctx))
- goto fetch_about_testament_handler_aborted;
-
- if (WT_MODIFIED > 0) {
- slen = snprintf(buffer, sizeof buffer,
- "Working tree has %d modification%s\n\n",
- WT_MODIFIED, WT_MODIFIED == 1 ? "" : "s");
- } else {
- slen = snprintf(buffer, sizeof buffer,
- "Working tree is not modified.\n");
- }
-
- msg.data.header_or_data.len = slen;
- if (fetch_about_send_callback(&msg, ctx))
- goto fetch_about_testament_handler_aborted;
-
- for (i = 0; i < WT_MODIFIED; ++i) {
- slen = snprintf(buffer, sizeof buffer,
- " %s %s\n",
- modifications[i].modtype,
- modifications[i].leaf);
- msg.data.header_or_data.len = slen;
- if (fetch_about_send_callback(&msg, ctx))
- goto fetch_about_testament_handler_aborted;
-
- }
-
- msg.type = FETCH_FINISHED;
- fetch_about_send_callback(&msg, ctx);
-
- return true;
-
-fetch_about_testament_handler_aborted:
- return false;
-}
-
-static bool fetch_about_logo_handler(struct fetch_about_context *ctx)
-{
- fetch_msg msg;
-
- /* content is going to return redirect */
- fetch_set_http_code(ctx->fetchh, 302);
-
- msg.type = FETCH_REDIRECT;
- msg.data.redirect = "resource:netsurf.png";
-
- fetch_about_send_callback(&msg, ctx);
-
- return true;
-}
-
-static bool fetch_about_welcome_handler(struct fetch_about_context *ctx)
-{
- fetch_msg msg;
-
- /* content is going to return redirect */
- fetch_set_http_code(ctx->fetchh, 302);
-
- msg.type = FETCH_REDIRECT;
- msg.data.redirect = "resource:welcome.html";
-
- fetch_about_send_callback(&msg, ctx);
-
- return true;
-}
-
-static bool fetch_about_maps_handler(struct fetch_about_context *ctx)
-{
- fetch_msg msg;
-
- /* content is going to return redirect */
- fetch_set_http_code(ctx->fetchh, 302);
-
- msg.type = FETCH_REDIRECT;
- msg.data.redirect = "resource:maps.html";
-
- fetch_about_send_callback(&msg, ctx);
-
- return true;
-}
-
-/* Forward declaration because this handler requires the handler table. */
-static bool fetch_about_about_handler(struct fetch_about_context *ctx);
-
-struct about_handlers {
- const char *name; /**< name to match in url */
- int name_len;
- lwc_string *lname; /**< Interned name */
- fetch_about_handler handler; /* handler for the url */
- bool hidden; /* Flag indicating if entry should show in listing */
-};
-
-/** List of about paths and their handlers */
-struct about_handlers about_handler_list[] = {
- { "credits", SLEN("credits"), NULL,
- fetch_about_credits_handler, false },
- { "licence", SLEN("licence"), NULL,
- fetch_about_licence_handler, false },
- { "license", SLEN("license"), NULL,
- fetch_about_licence_handler, true },
- { "welcome", SLEN("welcome"), NULL,
- fetch_about_welcome_handler, false },
- { "maps", SLEN("maps"), NULL,
- fetch_about_maps_handler, false },
- { "config", SLEN("config"), NULL,
- fetch_about_config_handler, false },
- { "Choices", SLEN("Choices"), NULL,
- fetch_about_choices_handler, false },
- { "testament", SLEN("testament"), NULL,
- fetch_about_testament_handler, false },
- { "about", SLEN("about"), NULL,
- fetch_about_about_handler, true },
- { "logo", SLEN("logo"), NULL,
- fetch_about_logo_handler, true },
- /* details about the image cache */
- { "imagecache", SLEN("imagecache"), NULL,
- fetch_about_imagecache_handler, true },
- /* The default blank page */
- { "blank", SLEN("blank"), NULL,
- fetch_about_blank_handler, true }
-};
-
-#define about_handler_list_len (sizeof(about_handler_list) / \
- sizeof(struct about_handlers))
-
-/**
- * List all the valid about: paths available
- *
- * \param ctx The fetch context.
- * \return true for sucess or false to generate an error.
- */
-static bool fetch_about_about_handler(struct fetch_about_context *ctx)
-{
- fetch_msg msg;
- char buffer[1024];
- int code = 200;
- int slen;
- unsigned int abt_loop = 0;
- int res = 0;
-
- /* content is going to return ok */
- fetch_set_http_code(ctx->fetchh, code);
-
- /* content type */
- if (fetch_about_send_header(ctx, "Content-Type: text/html"))
- goto fetch_about_config_handler_aborted;
-
- msg.type = FETCH_DATA;
- msg.data.header_or_data.buf = (const uint8_t *) buffer;
-
- slen = snprintf(buffer, sizeof buffer,
- "<html>\n<head>\n"
- "<title>NetSurf List of About pages</title>\n"
- "<link rel=\"stylesheet\" type=\"text/css\" "
- "href=\"resource:internal.css\">\n"
- "</head>\n"
- "<body id =\"aboutlist\">\n"
- "<p class=\"banner\">"
- "<a href=\"http://www.netsurf-browser.org/\">"
- "<img src=\"resource:netsurf.png\" alt=\"NetSurf\"></a>"
- "</p>\n"
- "<h1>NetSurf List of About pages</h1>\n"
- "<ul>\n");
-
- for (abt_loop = 0; abt_loop < about_handler_list_len; abt_loop++) {
-
- /* Skip over hidden entries */
- if (about_handler_list[abt_loop].hidden)
- continue;
-
- res = snprintf(buffer + slen, sizeof buffer - slen,
- "<li><a href=\"about:%s\">about:%s</a></li>\n",
- about_handler_list[abt_loop].name,
- about_handler_list[abt_loop].name);
- if (res <= 0)
- break; /* last option */
-
- if (res >= (int)(sizeof buffer - slen)) {
- /* last entry would not fit in buffer, submit buffer */
- msg.data.header_or_data.len = slen;
- if (fetch_about_send_callback(&msg, ctx))
- goto fetch_about_config_handler_aborted;
- slen = 0;
- } else {
- /* normal addition */
- slen += res;
- }
- }
-
- slen += snprintf(buffer + slen, sizeof buffer - slen,
- "</ul>\n</body>\n</html>\n");
-
- msg.data.header_or_data.len = slen;
- if (fetch_about_send_callback(&msg, ctx))
- goto fetch_about_config_handler_aborted;
-
- msg.type = FETCH_FINISHED;
- fetch_about_send_callback(&msg, ctx);
-
- return true;
-
-fetch_about_config_handler_aborted:
- return false;
-}
-
-
-/** callback to initialise the about fetcher. */
-static bool fetch_about_initialise(lwc_string *scheme)
-{
- unsigned int abt_loop = 0;
- lwc_error error;
-
- for (abt_loop = 0; abt_loop < about_handler_list_len; abt_loop++) {
- error = lwc_intern_string(about_handler_list[abt_loop].name,
- about_handler_list[abt_loop].name_len,
- &about_handler_list[abt_loop].lname);
- if (error != lwc_error_ok) {
- while (abt_loop-- != 0) {
- lwc_string_unref(about_handler_list[abt_loop].lname);
- }
- return false;
- }
- }
-
- return true;
-}
-
-/** callback to finalise the about fetcher. */
-static void fetch_about_finalise(lwc_string *scheme)
-{
- unsigned int abt_loop = 0;
- for (abt_loop = 0; abt_loop < about_handler_list_len; abt_loop++) {
- lwc_string_unref(about_handler_list[abt_loop].lname);
- }
-}
-
-static bool fetch_about_can_fetch(const nsurl *url)
-{
- return true;
-}
-
-/** callback to set up a about fetch context. */
-static void *
-fetch_about_setup(struct fetch *fetchh,
- nsurl *url,
- bool only_2xx,
- bool downgrade_tls,
- const char *post_urlenc,
- const struct fetch_multipart_data *post_multipart,
- const char **headers)
-{
- struct fetch_about_context *ctx;
- unsigned int handler_loop;
- lwc_string *path;
- bool match;
-
- ctx = calloc(1, sizeof(*ctx));
- if (ctx == NULL)
- return NULL;
-
- path = nsurl_get_component(url, NSURL_PATH);
-
- for (handler_loop = 0;
- handler_loop < about_handler_list_len;
- handler_loop++) {
- ctx->handler = about_handler_list[handler_loop].handler;
- if (lwc_string_isequal(path,
- about_handler_list[handler_loop].lname,
- &match) == lwc_error_ok && match) {
- break;
- }
- }
-
- if (path != NULL)
- lwc_string_unref(path);
-
- ctx->fetchh = fetchh;
- ctx->url = nsurl_ref(url);
-
- RING_INSERT(ring, ctx);
-
- return ctx;
-}
-
-/** callback to free a about fetch */
-static void fetch_about_free(void *ctx)
-{
- struct fetch_about_context *c = ctx;
- nsurl_unref(c->url);
- RING_REMOVE(ring, c);
- free(ctx);
-}
-
-/** callback to start a about fetch */
-static bool fetch_about_start(void *ctx)
-{
- return true;
-}
-
-/** callback to abort a about fetch */
-static void fetch_about_abort(void *ctx)
-{
- struct fetch_about_context *c = ctx;
-
- /* To avoid the poll loop having to deal with the fetch context
- * disappearing from under it, we simply flag the abort here.
- * The poll loop itself will perform the appropriate cleanup.
- */
- c->aborted = true;
-}
-
-
-/** callback to poll for additional about fetch contents */
-static void fetch_about_poll(lwc_string *scheme)
-{
- struct fetch_about_context *c, *next;
-
- if (ring == NULL) return;
-
- /* Iterate over ring, processing each pending fetch */
- c = ring;
- do {
- /* Ignore fetches that have been flagged as locked.
- * This allows safe re-entrant calls to this function.
- * Re-entrancy can occur if, as a result of a callback,
- * the interested party causes fetch_poll() to be called
- * again.
- */
- if (c->locked == true) {
- next = c->r_next;
- continue;
- }
-
- /* Only process non-aborted fetches */
- if (c->aborted == false) {
- /* about fetches can be processed in one go */
- c->handler(c);
- }
-
- /* Compute next fetch item at the last possible moment
- * as processing this item may have added to the ring
- */
- next = c->r_next;
-
- fetch_remove_from_queues(c->fetchh);
- fetch_free(c->fetchh);
-
- /* Advance to next ring entry, exiting if we've reached
- * the start of the ring or the ring has become empty
- */
- } while ( (c = next) != ring && ring != NULL);
-}
-
-nserror fetch_about_register(void)
-{
- lwc_string *scheme = lwc_string_ref(corestring_lwc_about);
- const struct fetcher_operation_table fetcher_ops = {
- .initialise = fetch_about_initialise,
- .acceptable = fetch_about_can_fetch,
- .setup = fetch_about_setup,
- .start = fetch_about_start,
- .abort = fetch_about_abort,
- .free = fetch_about_free,
- .poll = fetch_about_poll,
- .finalise = fetch_about_finalise
- };
-
- return fetcher_add(scheme, &fetcher_ops);
-}
diff --git a/content/fetchers/about/Makefile b/content/fetchers/about/Makefile
new file mode 100644
index 000000000..4f12a0626
--- /dev/null
+++ b/content/fetchers/about/Makefile
@@ -0,0 +1,20 @@
+# about fetcher sources
+
+S_FETCHER_ABOUT := \
+ about.c \
+ blank.c \
+ certificate.c \
+ chart.c \
+ choices.c \
+ config.c \
+ imagecache.c \
+ nscolours.c \
+ query.c \
+ query_auth.c \
+ query_fetcherror.c \
+ query_privacy.c \
+ query_timeout.c \
+ testament.c
+
+# The following files depend on the testament
+content/fetchers/about/testament.c: testament $(OBJROOT)/testament.h
diff --git a/content/fetchers/about/about.c b/content/fetchers/about/about.c
new file mode 100644
index 000000000..651894249
--- /dev/null
+++ b/content/fetchers/about/about.c
@@ -0,0 +1,758 @@
+/*
+ * Copyright 2011 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ *
+ * URL handling for the "about" scheme.
+ *
+ * Based on the data fetcher by Rob Kendrick
+ * This fetcher provides a simple scheme for the user to access
+ * information from the browser from a known, fixed URL.
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "netsurf/inttypes.h"
+
+#include "utils/errors.h"
+#include "utils/nsurl.h"
+#include "utils/corestrings.h"
+#include "utils/utils.h"
+#include "utils/ring.h"
+
+#include "content/fetch.h"
+#include "content/fetchers.h"
+
+#include "private.h"
+#include "about.h"
+#include "blank.h"
+#include "certificate.h"
+#include "config.h"
+#include "chart.h"
+#include "choices.h"
+#include "imagecache.h"
+#include "nscolours.h"
+#include "query.h"
+#include "query_auth.h"
+#include "query_fetcherror.h"
+#include "query_privacy.h"
+#include "query_timeout.h"
+#include "atestament.h"
+
+typedef bool (*fetch_about_handler)(struct fetch_about_context *);
+
+/**
+ * Context for an about fetch
+ */
+struct fetch_about_context {
+ struct fetch_about_context *r_next, *r_prev;
+
+ struct fetch *fetchh; /**< Handle for this fetch */
+
+ bool aborted; /**< Flag indicating fetch has been aborted */
+ bool locked; /**< Flag indicating entry is already entered */
+
+ nsurl *url; /**< The full url the fetch refers to */
+
+ const struct fetch_multipart_data *multipart; /**< post data */
+
+ fetch_about_handler handler;
+};
+
+static struct fetch_about_context *ring = NULL;
+
+/**
+ * handler info for about scheme
+ */
+struct about_handlers {
+ const char *name; /**< name to match in url */
+ int name_len;
+ lwc_string *lname; /**< Interned name */
+ fetch_about_handler handler; /**< handler for the url */
+ bool hidden; /**< If entry should be hidden in listing */
+};
+
+
+
+/**
+ * issue fetch callbacks with locking
+ */
+static bool
+fetch_about_send_callback(const fetch_msg *msg, struct fetch_about_context *ctx)
+{
+ ctx->locked = true;
+ fetch_send_callback(msg, ctx->fetchh);
+ ctx->locked = false;
+
+ return ctx->aborted;
+}
+
+/* exported interface documented in about/private.h */
+bool
+fetch_about_send_finished(struct fetch_about_context *ctx)
+{
+ fetch_msg msg;
+ msg.type = FETCH_FINISHED;
+ return fetch_about_send_callback(&msg, ctx);
+}
+
+/* exported interface documented in about/private.h */
+bool fetch_about_set_http_code(struct fetch_about_context *ctx, long code)
+{
+ fetch_set_http_code(ctx->fetchh, code);
+
+ return ctx->aborted;
+}
+
+/* exported interface documented in about/private.h */
+bool
+fetch_about_send_header(struct fetch_about_context *ctx, const char *fmt, ...)
+{
+ char header[64];
+ fetch_msg msg;
+ va_list ap;
+
+ va_start(ap, fmt);
+
+ vsnprintf(header, sizeof header, fmt, ap);
+
+ va_end(ap);
+
+ msg.type = FETCH_HEADER;
+ msg.data.header_or_data.buf = (const uint8_t *) header;
+ msg.data.header_or_data.len = strlen(header);
+
+ return fetch_about_send_callback(&msg, ctx);
+}
+
+/* exported interface documented in about/private.h */
+nserror
+fetch_about_senddata(struct fetch_about_context *ctx, const uint8_t *data, size_t data_len)
+{
+ fetch_msg msg;
+
+ msg.type = FETCH_DATA;
+ msg.data.header_or_data.buf = data;
+ msg.data.header_or_data.len = data_len;
+
+ if (fetch_about_send_callback(&msg, ctx)) {
+ return NSERROR_INVALID;
+ }
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in about/private.h */
+nserror
+fetch_about_ssenddataf(struct fetch_about_context *ctx, const char *fmt, ...)
+{
+ char buffer[1024];
+ char *dbuff;
+ fetch_msg msg;
+ va_list ap;
+ int slen;
+
+ va_start(ap, fmt);
+
+ slen = vsnprintf(buffer, sizeof(buffer), fmt, ap);
+
+ va_end(ap);
+
+ if (slen < (int)sizeof(buffer)) {
+ msg.type = FETCH_DATA;
+ msg.data.header_or_data.buf = (const uint8_t *) buffer;
+ msg.data.header_or_data.len = slen;
+
+ if (fetch_about_send_callback(&msg, ctx)) {
+ return NSERROR_INVALID;
+ }
+
+ return NSERROR_OK;
+ }
+
+ dbuff = malloc(slen + 1);
+ if (dbuff == NULL) {
+ return NSERROR_NOSPACE;
+ }
+
+ va_start(ap, fmt);
+
+ slen = vsnprintf(dbuff, slen + 1, fmt, ap);
+
+ va_end(ap);
+
+ msg.type = FETCH_DATA;
+ msg.data.header_or_data.buf = (const uint8_t *)dbuff;
+ msg.data.header_or_data.len = slen;
+
+ if (fetch_about_send_callback(&msg, ctx)) {
+ free(dbuff);
+ return NSERROR_INVALID;
+ }
+
+ free(dbuff);
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in about/private.h */
+nsurl *fetch_about_get_url(struct fetch_about_context *ctx)
+{
+ return ctx->url;
+}
+
+
+/* exported interface documented in about/private.h */
+const struct fetch_multipart_data *
+fetch_about_get_multipart(struct fetch_about_context *ctx)
+{
+ return ctx->multipart;
+}
+
+
+/* exported interface documented in about/private.h */
+bool fetch_about_srverror(struct fetch_about_context *ctx)
+{
+ nserror res;
+
+ fetch_set_http_code(ctx->fetchh, 500);
+
+ /* content type */
+ if (fetch_about_send_header(ctx, "Content-Type: text/plain"))
+ return false;
+
+ res = fetch_about_ssenddataf(ctx, "Server error 500");
+ if (res != NSERROR_OK) {
+ return false;
+ }
+
+ fetch_about_send_finished(ctx);
+
+ return true;
+}
+
+
+/**
+ * Handler to generate about scheme credits page.
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+static bool fetch_about_credits_handler(struct fetch_about_context *ctx)
+{
+ fetch_msg msg;
+
+ /* content is going to return redirect */
+ fetch_set_http_code(ctx->fetchh, 302);
+
+ msg.type = FETCH_REDIRECT;
+ msg.data.redirect = "resource:credits.html";
+
+ fetch_about_send_callback(&msg, ctx);
+
+ return true;
+}
+
+
+/**
+ * Handler to generate about scheme licence page.
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+static bool fetch_about_licence_handler(struct fetch_about_context *ctx)
+{
+ fetch_msg msg;
+
+ /* content is going to return redirect */
+ fetch_set_http_code(ctx->fetchh, 302);
+
+ msg.type = FETCH_REDIRECT;
+ msg.data.redirect = "resource:licence.html";
+
+ fetch_about_send_callback(&msg, ctx);
+
+ return true;
+}
+
+
+/**
+ * Handler to generate about scheme logo page
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+static bool fetch_about_logo_handler(struct fetch_about_context *ctx)
+{
+ fetch_msg msg;
+
+ /* content is going to return redirect */
+ fetch_set_http_code(ctx->fetchh, 302);
+
+ msg.type = FETCH_REDIRECT;
+ msg.data.redirect = "resource:netsurf.png";
+
+ fetch_about_send_callback(&msg, ctx);
+
+ return true;
+}
+
+
+/**
+ * Handler to generate about scheme welcome page
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+static bool fetch_about_welcome_handler(struct fetch_about_context *ctx)
+{
+ fetch_msg msg;
+
+ /* content is going to return redirect */
+ fetch_set_http_code(ctx->fetchh, 302);
+
+ msg.type = FETCH_REDIRECT;
+ msg.data.redirect = "resource:welcome.html";
+
+ fetch_about_send_callback(&msg, ctx);
+
+ return true;
+}
+
+
+/* Forward declaration because this handler requires the handler table. */
+static bool fetch_about_about_handler(struct fetch_about_context *ctx);
+
+/**
+ * List of about paths and their handlers
+ */
+struct about_handlers about_handler_list[] = {
+ {
+ "credits",
+ SLEN("credits"),
+ NULL,
+ fetch_about_credits_handler,
+ false
+ },
+ {
+ "licence",
+ SLEN("licence"),
+ NULL,
+ fetch_about_licence_handler,
+ false
+ },
+ {
+ "license",
+ SLEN("license"),
+ NULL,
+ fetch_about_licence_handler,
+ true
+ },
+ {
+ "welcome",
+ SLEN("welcome"),
+ NULL,
+ fetch_about_welcome_handler,
+ false
+ },
+ {
+ "config",
+ SLEN("config"),
+ NULL,
+ fetch_about_config_handler,
+ false
+ },
+ {
+ "Choices",
+ SLEN("Choices"),
+ NULL,
+ fetch_about_choices_handler,
+ false
+ },
+ {
+ "testament",
+ SLEN("testament"),
+ NULL,
+ fetch_about_testament_handler,
+ false
+ },
+ {
+ "about",
+ SLEN("about"),
+ NULL,
+ fetch_about_about_handler,
+ true
+ },
+ {
+ "nscolours.css",
+ SLEN("nscolours.css"),
+ NULL,
+ fetch_about_nscolours_handler,
+ true
+ },
+ {
+ "logo",
+ SLEN("logo"),
+ NULL,
+ fetch_about_logo_handler,
+ true
+ },
+ {
+ /* details about the image cache */
+ "imagecache",
+ SLEN("imagecache"),
+ NULL,
+ fetch_about_imagecache_handler,
+ true
+ },
+ {
+ /* The default blank page */
+ "blank",
+ SLEN("blank"),
+ NULL,
+ fetch_about_blank_handler,
+ true
+ },
+ {
+ /* details about a certificate */
+ "certificate",
+ SLEN("certificate"),
+ NULL,
+ fetch_about_certificate_handler,
+ true
+ },
+ {
+ /* chart generator */
+ "chart",
+ SLEN("chart"),
+ NULL,
+ fetch_about_chart_handler,
+ true
+ },
+ {
+ "query/auth",
+ SLEN("query/auth"),
+ NULL,
+ fetch_about_query_auth_handler,
+ true
+ },
+ {
+ "query/ssl",
+ SLEN("query/ssl"),
+ NULL,
+ fetch_about_query_privacy_handler,
+ true
+ },
+ {
+ "query/timeout",
+ SLEN("query/timeout"),
+ NULL,
+ fetch_about_query_timeout_handler,
+ true
+ },
+ {
+ "query/fetcherror",
+ SLEN("query/fetcherror"),
+ NULL,
+ fetch_about_query_fetcherror_handler,
+ true
+ }
+};
+
+#define about_handler_list_len \
+ (sizeof(about_handler_list) / sizeof(struct about_handlers))
+
+/**
+ * List all the valid about: paths available
+ *
+ * \param ctx The fetch context.
+ * \return true for sucess or false to generate an error.
+ */
+static bool fetch_about_about_handler(struct fetch_about_context *ctx)
+{
+ nserror res;
+ unsigned int abt_loop = 0;
+
+ /* content is going to return ok */
+ fetch_set_http_code(ctx->fetchh, 200);
+
+ /* content type */
+ if (fetch_about_send_header(ctx, "Content-Type: text/html"))
+ goto fetch_about_config_handler_aborted;
+
+ res = fetch_about_ssenddataf(ctx,
+ "<html>\n<head>\n"
+ "<title>List of NetSurf pages</title>\n"
+ "<link rel=\"stylesheet\" type=\"text/css\" "
+ "href=\"resource:internal.css\">\n"
+ "</head>\n"
+ "<body class=\"ns-even-bg ns-even-fg ns-border\">\n"
+ "<h1 class =\"ns-border\">List of NetSurf pages</h1>\n"
+ "<ul>\n");
+ if (res != NSERROR_OK) {
+ goto fetch_about_config_handler_aborted;
+ }
+
+ for (abt_loop = 0; abt_loop < about_handler_list_len; abt_loop++) {
+
+ /* Skip over hidden entries */
+ if (about_handler_list[abt_loop].hidden)
+ continue;
+
+ res = fetch_about_ssenddataf(ctx,
+ "<li><a href=\"about:%s\">about:%s</a></li>\n",
+ about_handler_list[abt_loop].name,
+ about_handler_list[abt_loop].name);
+ if (res != NSERROR_OK) {
+ goto fetch_about_config_handler_aborted;
+ }
+ }
+
+ res = fetch_about_ssenddataf(ctx, "</ul>\n</body>\n</html>\n");
+ if (res != NSERROR_OK) {
+ goto fetch_about_config_handler_aborted;
+ }
+
+ fetch_about_send_finished(ctx);
+
+ return true;
+
+fetch_about_config_handler_aborted:
+ return false;
+}
+
+static bool
+fetch_about_404_handler(struct fetch_about_context *ctx)
+{
+ nserror res;
+
+ /* content is going to return 404 */
+ fetch_set_http_code(ctx->fetchh, 404);
+
+ /* content type */
+ if (fetch_about_send_header(ctx, "Content-Type: text/plain; charset=utf-8")) {
+ return false;
+ }
+
+ res = fetch_about_ssenddataf(ctx, "Unknown page: %s", nsurl_access(ctx->url));
+ if (res != NSERROR_OK) {
+ return false;
+ }
+
+ fetch_about_send_finished(ctx);
+
+ return true;
+}
+
+/**
+ * callback to initialise the about scheme fetcher.
+ */
+static bool fetch_about_initialise(lwc_string *scheme)
+{
+ unsigned int abt_loop = 0;
+ lwc_error error;
+
+ for (abt_loop = 0; abt_loop < about_handler_list_len; abt_loop++) {
+ error = lwc_intern_string(about_handler_list[abt_loop].name,
+ about_handler_list[abt_loop].name_len,
+ &about_handler_list[abt_loop].lname);
+ if (error != lwc_error_ok) {
+ while (abt_loop-- != 0) {
+ lwc_string_unref(about_handler_list[abt_loop].lname);
+ }
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+/**
+ * callback to finalise the about scheme fetcher.
+ */
+static void fetch_about_finalise(lwc_string *scheme)
+{
+ unsigned int abt_loop = 0;
+ for (abt_loop = 0; abt_loop < about_handler_list_len; abt_loop++) {
+ lwc_string_unref(about_handler_list[abt_loop].lname);
+ }
+}
+
+
+static bool fetch_about_can_fetch(const nsurl *url)
+{
+ return true;
+}
+
+
+/**
+ * callback to set up a about scheme fetch.
+ *
+ * \param post_urlenc post data in urlenc format, owned by the llcache object
+ * hence valid the entire lifetime of the fetch.
+ * \param post_multipart post data in multipart format, owned by the llcache
+ * object hence valid the entire lifetime of the fetch.
+ */
+static void *
+fetch_about_setup(struct fetch *fetchh,
+ nsurl *url,
+ bool only_2xx,
+ bool downgrade_tls,
+ const char *post_urlenc,
+ const struct fetch_multipart_data *post_multipart,
+ const char **headers)
+{
+ struct fetch_about_context *ctx;
+ unsigned int handler_loop;
+ lwc_string *path;
+ bool match;
+
+ ctx = calloc(1, sizeof(*ctx));
+ if (ctx == NULL)
+ return NULL;
+
+ path = nsurl_get_component(url, NSURL_PATH);
+
+ for (handler_loop = 0;
+ handler_loop < about_handler_list_len;
+ handler_loop++) {
+ if (lwc_string_isequal(path,
+ about_handler_list[handler_loop].lname,
+ &match) == lwc_error_ok && match) {
+ ctx->handler = about_handler_list[handler_loop].handler;
+ break;
+ }
+ }
+
+ if (path != NULL)
+ lwc_string_unref(path);
+
+ ctx->fetchh = fetchh;
+ ctx->url = nsurl_ref(url);
+ ctx->multipart = post_multipart;
+
+ RING_INSERT(ring, ctx);
+
+ return ctx;
+}
+
+
+/**
+ * callback to free a about scheme fetch
+ */
+static void fetch_about_free(void *ctx)
+{
+ struct fetch_about_context *c = ctx;
+ nsurl_unref(c->url);
+ free(ctx);
+}
+
+
+/**
+ * callback to start an about scheme fetch
+ */
+static bool fetch_about_start(void *ctx)
+{
+ return true;
+}
+
+
+/**
+ * callback to abort a about fetch
+ */
+static void fetch_about_abort(void *ctx)
+{
+ struct fetch_about_context *c = ctx;
+
+ /* To avoid the poll loop having to deal with the fetch context
+ * disappearing from under it, we simply flag the abort here.
+ * The poll loop itself will perform the appropriate cleanup.
+ */
+ c->aborted = true;
+}
+
+
+/**
+ * callback to poll for additional about fetch contents
+ */
+static void fetch_about_poll(lwc_string *scheme)
+{
+ struct fetch_about_context *c, *save_ring = NULL;
+
+ /* Iterate over ring, processing each pending fetch */
+ while (ring != NULL) {
+ /* Take the first entry from the ring */
+ c = ring;
+ RING_REMOVE(ring, c);
+
+ /* Ignore fetches that have been flagged as locked.
+ * This allows safe re-entrant calls to this function.
+ * Re-entrancy can occur if, as a result of a callback,
+ * the interested party causes fetch_poll() to be called
+ * again.
+ */
+ if (c->locked == true) {
+ RING_INSERT(save_ring, c);
+ continue;
+ }
+
+ /* Only process non-aborted fetches */
+ if (c->aborted == false) {
+ /* about fetches can be processed in one go */
+ if (c->handler == NULL) {
+ fetch_about_404_handler(c);
+ } else {
+ c->handler(c);
+ }
+ }
+
+ /* And now finish */
+ fetch_remove_from_queues(c->fetchh);
+ fetch_free(c->fetchh);
+ }
+
+ /* Finally, if we saved any fetches which were locked, put them back
+ * into the ring for next time
+ */
+ ring = save_ring;
+}
+
+
+nserror fetch_about_register(void)
+{
+ lwc_string *scheme = lwc_string_ref(corestring_lwc_about);
+ const struct fetcher_operation_table fetcher_ops = {
+ .initialise = fetch_about_initialise,
+ .acceptable = fetch_about_can_fetch,
+ .setup = fetch_about_setup,
+ .start = fetch_about_start,
+ .abort = fetch_about_abort,
+ .free = fetch_about_free,
+ .poll = fetch_about_poll,
+ .finalise = fetch_about_finalise
+ };
+
+ return fetcher_add(scheme, &fetcher_ops);
+}
diff --git a/content/fetchers/about.h b/content/fetchers/about/about.h
index 944f84a59..bf6379709 100644
--- a/content/fetchers/about.h
+++ b/content/fetchers/about/about.h
@@ -16,12 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * about: URL method handler
+/**
+ * \file
+ * about scheme URL method handler
*/
-#ifndef NETSURF_CONTENT_FETCHERS_FETCH_ABOUT_H
-#define NETSURF_CONTENT_FETCHERS_FETCH_ABOUT_H
+#ifndef NETSURF_CONTENT_FETCHERS_ABOUT_ABOUT_H
+#define NETSURF_CONTENT_FETCHERS_ABOUT_ABOUT_H
/**
* Register about scheme handler.
diff --git a/content/fetchers/about/atestament.h b/content/fetchers/about/atestament.h
new file mode 100644
index 000000000..1851e8f3c
--- /dev/null
+++ b/content/fetchers/about/atestament.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * about scheme testament handler interface
+ */
+
+#ifndef NETSURF_CONTENT_FETCHERS_ABOUT_TESTAMENT_H
+#define NETSURF_CONTENT_FETCHERS_ABOUT_TESTAMENT_H
+
+/**
+ * Handler to generate about scheme testament page.
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_testament_handler(struct fetch_about_context *ctx);
+
+#endif
diff --git a/content/fetchers/about/blank.c b/content/fetchers/about/blank.c
new file mode 100644
index 000000000..8ad774512
--- /dev/null
+++ b/content/fetchers/about/blank.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * content generator for the about scheme blank page
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "netsurf/types.h"
+#include "utils/errors.h"
+
+#include "private.h"
+#include "blank.h"
+
+/**
+ * Handler to generate about scheme cache page.
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_blank_handler(struct fetch_about_context *ctx)
+{
+ const char buffer[2] = { ' ', '\0' };
+
+ /* content is going to return ok */
+ fetch_about_set_http_code(ctx, 200);
+
+ /* content type */
+ if (fetch_about_send_header(ctx, "Content-Type: text/html"))
+ goto fetch_about_blank_handler_aborted;
+
+ if (fetch_about_senddata(ctx, (const uint8_t *) buffer, strlen(buffer)) != NSERROR_OK)
+ goto fetch_about_blank_handler_aborted;
+
+ fetch_about_send_finished(ctx);
+
+ return true;
+
+fetch_about_blank_handler_aborted:
+ return false;
+}
diff --git a/content/fetchers/about/blank.h b/content/fetchers/about/blank.h
new file mode 100644
index 000000000..09dcc1f6a
--- /dev/null
+++ b/content/fetchers/about/blank.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * about scheme blank handler interface
+ */
+
+#ifndef NETSURF_CONTENT_FETCHERS_ABOUT_BLANK_H
+#define NETSURF_CONTENT_FETCHERS_ABOUT_BLANK_H
+
+/**
+ * Handler to generate about scheme blank page.
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_blank_handler(struct fetch_about_context *ctx);
+
+#endif
diff --git a/content/fetchers/about/certificate.c b/content/fetchers/about/certificate.c
new file mode 100644
index 000000000..6f634d22a
--- /dev/null
+++ b/content/fetchers/about/certificate.c
@@ -0,0 +1,1291 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * content generator for the about scheme certificate page
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "utils/errors.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "netsurf/inttypes.h"
+#include "netsurf/ssl_certs.h"
+
+#include "private.h"
+#include "certificate.h"
+
+/**
+ * certificate name parameters
+ */
+struct ns_cert_name {
+ char *common_name;
+ char *organisation;
+ char *organisation_unit;
+ char *locality;
+ char *province;
+ char *country;
+};
+
+/**
+ * Certificate public key parameters
+ */
+struct ns_cert_pkey {
+ char *algor;
+ int size;
+ char *modulus;
+ char *exponent;
+ char *curve;
+ char *public;
+};
+
+/**
+ * Certificate subject alternative name
+ */
+struct ns_cert_san {
+ struct ns_cert_san *next;
+ char *name;
+};
+
+/**
+ * certificate information for certificate chain
+ */
+struct ns_cert_info {
+ struct ns_cert_name subject_name; /**< Subject details */
+ struct ns_cert_name issuer_name; /**< Issuer details */
+ struct ns_cert_pkey public_key; /**< public key details */
+ long version; /**< Certificate version */
+ char *not_before; /**< Valid from date */
+ char *not_after; /**< Valid to date */
+ int sig_type; /**< Signature type */
+ char *sig_algor; /**< Signature Algorithm */
+ char *serialnum; /**< Serial number */
+ char *sha1fingerprint; /**< fingerprint shar1 encoded */
+ char *sha256fingerprint; /**< fingerprint shar256 encoded */
+ struct ns_cert_san *san; /**< subject alternative names */
+ ssl_cert_err err; /**< Whatever is wrong with this certificate */
+};
+
+/**
+ * free all resources associated with a certificate information structure
+ */
+static nserror free_ns_cert_info(struct ns_cert_info *cinfo)
+{
+ struct ns_cert_san *san;
+
+ free(cinfo->subject_name.common_name);
+ free(cinfo->subject_name.organisation);
+ free(cinfo->subject_name.organisation_unit);
+ free(cinfo->subject_name.locality);
+ free(cinfo->subject_name.province);
+ free(cinfo->subject_name.country);
+ free(cinfo->issuer_name.common_name);
+ free(cinfo->issuer_name.organisation);
+ free(cinfo->issuer_name.organisation_unit);
+ free(cinfo->issuer_name.locality);
+ free(cinfo->issuer_name.province);
+ free(cinfo->issuer_name.country);
+ free(cinfo->public_key.algor);
+ free(cinfo->public_key.modulus);
+ free(cinfo->public_key.exponent);
+ free(cinfo->public_key.curve);
+ free(cinfo->public_key.public);
+ free(cinfo->not_before);
+ free(cinfo->not_after);
+ free(cinfo->sig_algor);
+ free(cinfo->serialnum);
+
+ /* free san list avoiding use after free */
+ san = cinfo->san;
+ while (san != NULL) {
+ struct ns_cert_san *next;
+ next = san->next;
+ free(san);
+ san = next;
+ }
+
+ free(cinfo);
+
+ return NSERROR_OK;
+}
+
+#ifdef WITH_OPENSSL
+
+#include <openssl/ssl.h>
+#include <openssl/x509v3.h>
+
+#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
+/* OpenSSL 1.1.1 or LibreSSL */
+
+# if defined(LIBRESSL_VERSION_NUMBER)
+ /* LibreSSL */
+# if (LIBRESSL_VERSION_NUMBER < 0x3050000fL)
+ /* LibreSSL <3.5.0 */
+
+# if (LIBRESSL_VERSION_NUMBER < 0x2070000fL)
+ /* LibreSSL <2.7.0 */
+static int ns_X509_get_signature_nid(X509 *cert)
+{
+ return OBJ_obj2nid(cert->cert_info->key->algor->algorithm);
+}
+
+static const unsigned char *ns_ASN1_STRING_get0_data(ASN1_STRING *asn1str)
+{
+ return (const unsigned char *)ASN1_STRING_data(asn1str);
+}
+# else
+# define ns_X509_get_signature_nid X509_get_signature_nid
+# define ns_ASN1_STRING_get0_data ASN1_STRING_get0_data
+# endif
+
+static const BIGNUM *ns_RSA_get0_n(const RSA *d)
+{
+ return d->n;
+}
+
+static const BIGNUM *ns_RSA_get0_e(const RSA *d)
+{
+ return d->e;
+}
+# else
+ /* LibreSSL >= 3.5.0 */
+# define ns_X509_get_signature_nid X509_get_signature_nid
+# define ns_ASN1_STRING_get0_data ASN1_STRING_get0_data
+# define ns_RSA_get0_n RSA_get0_n
+# define ns_RSA_get0_e RSA_get0_e
+# endif
+# else
+ /* OpenSSL 1.1.1 */
+# define ns_X509_get_signature_nid X509_get_signature_nid
+# define ns_ASN1_STRING_get0_data ASN1_STRING_get0_data
+# define ns_RSA_get0_n RSA_get0_n
+# define ns_RSA_get0_e RSA_get0_e
+# endif
+
+static int ns_EVP_PKEY_get_bn_param(const EVP_PKEY *pkey,
+ const char *key_name, BIGNUM **bn) {
+ RSA *rsa;
+ BIGNUM *result = NULL;
+
+ /* Check parameters: only support allocation-form *bn */
+ if (pkey == NULL || key_name == NULL || bn == NULL || *bn != NULL)
+ return 0;
+
+ /* Only support RSA keys */
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA)
+ return 0;
+
+ rsa = EVP_PKEY_get1_RSA((EVP_PKEY *) pkey);
+ if (rsa == NULL)
+ return 0;
+
+ if (strcmp(key_name, "n") == 0) {
+ const BIGNUM *n = ns_RSA_get0_n(rsa);
+ if (n != NULL)
+ result = BN_dup(n);
+ } else if (strcmp(key_name, "e") == 0) {
+ const BIGNUM *e = ns_RSA_get0_e(rsa);
+ if (e != NULL)
+ result = BN_dup(e);
+ }
+
+ RSA_free(rsa);
+
+ *bn = result;
+
+ return (result != NULL) ? 1 : 0;
+}
+
+static int ns_EVP_PKEY_get_utf8_string_param(const EVP_PKEY *pkey,
+ const char *key_name, char *str, size_t max_len,
+ size_t *out_len)
+{
+ const EC_GROUP *ecgroup;
+ const char *group;
+ EC_KEY *ec;
+ int ret = 0;
+
+ if (pkey == NULL || key_name == NULL)
+ return 0;
+
+ /* Only support EC keys */
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC)
+ return 0;
+
+ /* Only support fetching the group */
+ if (strcmp(key_name, "group") != 0)
+ return 0;
+
+ ec = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) pkey);
+
+ ecgroup = EC_KEY_get0_group(ec);
+ if (ecgroup == NULL) {
+ group = "";
+ } else {
+ group = OBJ_nid2ln(EC_GROUP_get_curve_name(ecgroup));
+ }
+
+ if (str != NULL && max_len > strlen(group)) {
+ strcpy(str, group);
+ str[strlen(group)] = '\0';
+ ret = 1;
+ }
+ if (out_len != NULL)
+ *out_len = strlen(group);
+
+ EC_KEY_free(ec);
+
+ return ret;
+}
+
+static int ns_EVP_PKEY_get_octet_string_param(const EVP_PKEY *pkey,
+ const char *key_name, unsigned char *buf, size_t max_len,
+ size_t *out_len)
+{
+ const EC_GROUP *ecgroup;
+ const EC_POINT *ecpoint;
+ size_t len;
+ BN_CTX *bnctx;
+ EC_KEY *ec;
+ int ret = 0;
+
+ if (pkey == NULL || key_name == NULL)
+ return 0;
+
+ /* Only support EC keys */
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC)
+ return 0;
+
+ if (strcmp(key_name, "encoded-pub-key") != 0)
+ return 0;
+
+ ec = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) pkey);
+ if (ec == NULL)
+ return 0;
+
+ ecgroup = EC_KEY_get0_group(ec);
+ if (ecgroup != NULL) {
+ ecpoint = EC_KEY_get0_public_key(ec);
+ if (ecpoint != NULL) {
+ bnctx = BN_CTX_new();
+ len = EC_POINT_point2oct(ecgroup,
+ ecpoint,
+ POINT_CONVERSION_UNCOMPRESSED,
+ NULL,
+ 0,
+ bnctx);
+ if (len != 0 && len <= max_len) {
+ if (EC_POINT_point2oct(ecgroup,
+ ecpoint,
+ POINT_CONVERSION_UNCOMPRESSED,
+ buf,
+ len,
+ bnctx) == len)
+ ret = 1;
+ }
+ if (out_len != NULL)
+ *out_len = len;
+ BN_CTX_free(bnctx);
+ }
+ }
+
+ EC_KEY_free(ec);
+
+ return ret;
+}
+#else
+/* OpenSSL 3.x and later */
+#define ns_X509_get_signature_nid X509_get_signature_nid
+#define ns_ASN1_STRING_get0_data ASN1_STRING_get0_data
+#define ns_RSA_get0_n RSA_get0_n
+#define ns_RSA_get0_e RSA_get0_e
+#define ns_EVP_PKEY_get_bn_param EVP_PKEY_get_bn_param
+#define ns_EVP_PKEY_get_octet_string_param EVP_PKEY_get_octet_string_param
+#define ns_EVP_PKEY_get_utf8_string_param EVP_PKEY_get_utf8_string_param
+#endif
+
+/**
+ * extract certificate name information
+ *
+ * \param xname The X509 name to convert. The reference is borrowed so is not freeed
+ * \param iname The info structure to recive the extracted parameters.
+ * \return NSERROR_OK on success else error code
+ */
+static nserror
+xname_to_info(X509_NAME *xname, struct ns_cert_name *iname)
+{
+ int entryidx;
+ int entrycnt;
+ X509_NAME_ENTRY *entry; /* current name entry */
+ ASN1_STRING *value;
+ const unsigned char *value_str;
+ ASN1_OBJECT *name;
+ int name_nid;
+ char **field;
+
+ entrycnt = X509_NAME_entry_count(xname);
+
+ for (entryidx = 0; entryidx < entrycnt; entryidx++) {
+ entry = X509_NAME_get_entry(xname, entryidx);
+ name = X509_NAME_ENTRY_get_object(entry);
+ name_nid = OBJ_obj2nid(name);
+ value = X509_NAME_ENTRY_get_data(entry);
+ value_str = ns_ASN1_STRING_get0_data(value);
+ switch (name_nid) {
+ case NID_commonName:
+ field = &iname->common_name;
+ break;
+ case NID_countryName:
+ field = &iname->country;
+ break;
+ case NID_localityName:
+ field = &iname->locality;
+ break;
+ case NID_stateOrProvinceName:
+ field = &iname->province;
+ break;
+ case NID_organizationName:
+ field = &iname->organisation;
+ break;
+ case NID_organizationalUnitName:
+ field = &iname->organisation_unit;
+ break;
+ default :
+ field = NULL;
+ break;
+ }
+ if (field != NULL) {
+ *field = strdup((const char *)value_str);
+ NSLOG(netsurf, DEEPDEBUG,
+ "NID:%d value: %s", name_nid, *field);
+ } else {
+ NSLOG(netsurf, DEEPDEBUG, "NID:%d", name_nid);
+ }
+ }
+
+ /*
+ * ensure the common name is set to something, this being
+ * missing means the certificate is broken but this should be
+ * robust in the face of bad data
+ */
+ if (iname->common_name == NULL) {
+ iname->common_name = strdup("Unknown");
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * duplicate a hex formatted string inserting the colons
+ *
+ * \todo only uses html entity as separator because netsurfs line breaking
+ * fails otherwise.
+ */
+static char *hexdup(const char *hex)
+{
+ int hexlen;
+ char *dst;
+ char *out;
+ int cn = 0;
+
+ hexlen = strlen(hex);
+ /* allow space fox XXYY to XX&#58;YY&#58; */
+ dst = malloc(((hexlen * 7) + 6) / 2);
+
+ if (dst != NULL) {
+ for (out = dst; *hex != 0; hex++) {
+ if (cn == 2) {
+ cn = 0;
+ *out++ = '&';
+ *out++ = '#';
+ *out++ = '5';
+ *out++ = '8';
+ *out++ = ';';
+ }
+ *out++ = *hex;
+ cn++;
+ }
+ *out = 0;
+ }
+ return dst;
+}
+
+
+/**
+ * create a hex formatted string inserting the colons from binary data
+ *
+ * \todo only uses html entity as separator because netsurfs line breaking
+ * fails otherwise.
+ */
+static char *bindup(unsigned char *bin, unsigned int binlen)
+{
+ char *dst;
+ char *out;
+ unsigned int idx;
+ const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ /* allow space fox XY to expand to XX&#58;YY&#58; */
+ dst = malloc(binlen * 7);
+
+ if (dst != NULL) {
+ out = dst;
+ for (idx = 0; idx < binlen; idx++) {
+ *out++ = hex[(bin[idx] & 0xf0) >> 4];
+ *out++ = hex[bin[idx] & 0xf];
+
+ *out++ = '&';
+ *out++ = '#';
+ *out++ = '5';
+ *out++ = '8';
+ *out++ = ';';
+ }
+ out -= 5;
+ *out = 0;
+ }
+ return dst;
+}
+
+
+/**
+ * extract RSA key information to info structure
+ *
+ * \param pkey The RSA key to examine.
+ * \param ikey The public key info structure to fill
+ * \rerun NSERROR_OK on success else error code.
+ */
+static nserror
+rsa_to_info(EVP_PKEY *pkey, struct ns_cert_pkey *ikey)
+{
+ BIGNUM *n = NULL, *e = NULL;
+ char *tmp;
+
+ if (ns_EVP_PKEY_get_bn_param(pkey, "n", &n) != 1) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if (ns_EVP_PKEY_get_bn_param(pkey, "e", &e) != 1) {
+ BN_free(n);
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ ikey->algor = strdup("RSA");
+
+ ikey->size = EVP_PKEY_bits(pkey);
+
+ tmp = BN_bn2hex(n);
+ if (tmp != NULL) {
+ ikey->modulus = hexdup(tmp);
+ OPENSSL_free(tmp);
+ }
+
+ tmp = BN_bn2dec(e);
+ if (tmp != NULL) {
+ ikey->exponent = strdup(tmp);
+ OPENSSL_free(tmp);
+ }
+
+ BN_free(e);
+ BN_free(n);
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * extract DSA key information to info structure
+ *
+ * \param pkey The DSA key to examine.
+ * \param ikey The public key info structure to fill
+ * \rerun NSERROR_OK on success else error code.
+ */
+static nserror
+dsa_to_info(EVP_PKEY *pkey, struct ns_cert_pkey *ikey)
+{
+ ikey->algor = strdup("DSA");
+
+ ikey->size = EVP_PKEY_bits(pkey);
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * extract DH key information to info structure
+ *
+ * \param pkey The DH key to examine.
+ * \param ikey The public key info structure to fill
+ * \rerun NSERROR_OK on success else error code.
+ */
+static nserror
+dh_to_info(EVP_PKEY *pkey, struct ns_cert_pkey *ikey)
+{
+ ikey->algor = strdup("Diffie Hellman");
+
+ ikey->size = EVP_PKEY_bits(pkey);
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * extract EC key information to info structure
+ *
+ * \param pkey The EC key to examine.
+ * \param ikey The public key info structure to fill
+ * \rerun NSERROR_OK on success else error code.
+ */
+static nserror
+ec_to_info(EVP_PKEY *pkey, struct ns_cert_pkey *ikey)
+{
+ size_t len;
+
+ ikey->algor = strdup("Elliptic Curve");
+
+ ikey->size = EVP_PKEY_bits(pkey);
+
+ len = 0;
+ ns_EVP_PKEY_get_utf8_string_param(pkey, "group", NULL, 0, &len);
+ if (len != 0) {
+ ikey->curve = malloc(len + 1);
+ if (ikey->curve != NULL) {
+ if (ns_EVP_PKEY_get_utf8_string_param(pkey, "group",
+ ikey->curve, len + 1, NULL) == 0) {
+ free(ikey->curve);
+ ikey->curve = NULL;
+ }
+ }
+ }
+
+ len = 0;
+ ns_EVP_PKEY_get_octet_string_param(pkey, "encoded-pub-key",
+ NULL, 0, &len);
+ if (len != 0) {
+ unsigned char *point = malloc(len);
+ if (point != NULL) {
+ if (ns_EVP_PKEY_get_octet_string_param(pkey,
+ "encoded-pub-key", point, len,
+ NULL) == 1) {
+ ikey->public = bindup(point, len);
+ }
+ free(point);
+ }
+ }
+
+ return NSERROR_OK;
+}
+
+/**
+ * extract public key information to info structure
+ *
+ * \param pkey the public key to examine. The reference is dropped on return
+ * \param ikey The public key info structure to fill
+ * \rerun NSERROR_OK on success else error code.
+ */
+static nserror
+pkey_to_info(EVP_PKEY *pkey, struct ns_cert_pkey *ikey)
+{
+ nserror res;
+
+ if (pkey == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ switch (EVP_PKEY_base_id(pkey)) {
+ case EVP_PKEY_RSA:
+ res = rsa_to_info(pkey, ikey);
+ break;
+
+ case EVP_PKEY_DSA:
+ res = dsa_to_info(pkey, ikey);
+ break;
+
+ case EVP_PKEY_DH:
+ res = dh_to_info(pkey, ikey);
+ break;
+
+ case EVP_PKEY_EC:
+ res = ec_to_info(pkey, ikey);
+ break;
+
+ default:
+ res = NSERROR_NOT_IMPLEMENTED;
+ break;
+ }
+
+ EVP_PKEY_free(pkey);
+
+ return res;
+}
+
+static nserror san_to_info(X509 *cert, struct ns_cert_san **prev_next)
+{
+ int idx;
+ int san_names_nb = -1;
+ const GENERAL_NAME *current_name;
+ const unsigned char *dns_name;
+ struct ns_cert_san *isan;
+
+ STACK_OF(GENERAL_NAME) *san_names = NULL;
+
+ san_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
+ if (san_names == NULL) {
+ return NSERROR_OK;
+ }
+
+ san_names_nb = sk_GENERAL_NAME_num(san_names);
+
+ /* Check each name within the extension */
+ for (idx = 0; idx < san_names_nb; idx++) {
+ current_name = sk_GENERAL_NAME_value(san_names, idx);
+
+ if (current_name->type == GEN_DNS) {
+ /* extract DNS name into info structure */
+ dns_name = ns_ASN1_STRING_get0_data(current_name->d.dNSName);
+
+ isan = malloc(sizeof(struct ns_cert_san));
+ if (isan != NULL) {
+ isan->name = strdup((const char *)dns_name);
+ isan->next = NULL;
+ *prev_next = isan;
+ prev_next = &isan->next;
+ }
+ }
+ }
+
+ /* AmiSSL can't cope with the "correct" mechanism of freeing
+ * the GENERAL_NAME stack, which is:
+ * sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free);
+ * So instead we do this open-coded loop which does the same:
+ */
+ for (idx = 0; idx < san_names_nb; idx++) {
+ GENERAL_NAME *entry = sk_GENERAL_NAME_pop(san_names);
+ GENERAL_NAME_free(entry);
+ }
+ sk_GENERAL_NAME_free(san_names);
+
+ return NSERROR_OK;
+}
+
+static nserror
+der_to_certinfo(const uint8_t *der,
+ size_t der_length,
+ struct ns_cert_info *info)
+{
+ BIO *mem;
+ BUF_MEM *buf;
+ const ASN1_INTEGER *asn1_num;
+ BIGNUM *bignum;
+ X509 *cert; /**< Pointer to certificate */
+
+ if (der == NULL) {
+ return NSERROR_OK;
+ }
+
+ cert = d2i_X509(NULL, &der, der_length);
+ if (cert == NULL) {
+ return NSERROR_INVALID;
+ }
+
+ /*
+ * get certificate version
+ *
+ * \note this is defined by standards (X.509 et al) to be one
+ * less than the certificate version.
+ */
+ info->version = X509_get_version(cert) + 1;
+
+ /* not before date */
+ mem = BIO_new(BIO_s_mem());
+ ASN1_TIME_print(mem, X509_get_notBefore(cert));
+ BIO_get_mem_ptr(mem, &buf);
+ (void) BIO_set_close(mem, BIO_NOCLOSE);
+ BIO_free(mem);
+ info->not_before = calloc(1, buf->length + 1);
+ if (info->not_before != NULL) {
+ memcpy(info->not_before, buf->data, (unsigned)buf->length);
+ }
+ BUF_MEM_free(buf);
+
+ /* not after date */
+ mem = BIO_new(BIO_s_mem());
+ ASN1_TIME_print(mem,
+ X509_get_notAfter(cert));
+ BIO_get_mem_ptr(mem, &buf);
+ (void) BIO_set_close(mem, BIO_NOCLOSE);
+ BIO_free(mem);
+ info->not_after = calloc(1, buf->length + 1);
+ if (info->not_after != NULL) {
+ memcpy(info->not_after, buf->data, (unsigned)buf->length);
+ }
+ BUF_MEM_free(buf);
+
+ /* signature type */
+ info->sig_type = X509_get_signature_type(cert);
+
+ /* signature algorithm */
+ int pkey_nid = ns_X509_get_signature_nid(cert);
+ if (pkey_nid != NID_undef) {
+ const char* sslbuf = OBJ_nid2ln(pkey_nid);
+ if (sslbuf != NULL) {
+ info->sig_algor = strdup(sslbuf);
+ }
+ }
+
+ /* serial number */
+ asn1_num = X509_get_serialNumber(cert);
+ if (asn1_num != NULL) {
+ bignum = ASN1_INTEGER_to_BN(asn1_num, NULL);
+ if (bignum != NULL) {
+ char *tmp = BN_bn2hex(bignum);
+ if (tmp != NULL) {
+ info->serialnum = hexdup(tmp);
+ OPENSSL_free(tmp);
+ }
+ BN_free(bignum);
+ bignum = NULL;
+ }
+ }
+
+ /* fingerprints */
+ const EVP_MD *digest;
+ unsigned int dig_len;
+ unsigned char *buff;
+ int rc;
+
+ digest = EVP_sha1();
+ buff = malloc(EVP_MD_size(digest));
+ if (buff != NULL) {
+ rc = X509_digest(cert, digest, buff, &dig_len);
+ if ((rc == 1) && (dig_len == (unsigned int)EVP_MD_size(digest))) {
+ info->sha1fingerprint = bindup(buff, dig_len);
+ }
+ free(buff);
+ }
+
+ digest = EVP_sha256();
+ buff = malloc(EVP_MD_size(digest));
+ if (buff != NULL) {
+ rc = X509_digest(cert, digest, buff, &dig_len);
+ if ((rc == 1) && (dig_len == (unsigned int)EVP_MD_size(digest))) {
+ info->sha256fingerprint = bindup(buff, dig_len);
+ }
+ free(buff);
+ }
+
+ /* subject alternative names */
+ san_to_info(cert, &info->san);
+
+ /* issuer name */
+ xname_to_info(X509_get_issuer_name(cert), &info->issuer_name);
+
+ /* subject */
+ xname_to_info(X509_get_subject_name(cert), &info->subject_name);
+
+ /* public key */
+ pkey_to_info(X509_get_pubkey(cert), &info->public_key);
+
+ X509_free(cert);
+
+ return NSERROR_OK;
+}
+
+/* copy certificate data */
+static nserror
+convert_chain_to_cert_info(const struct cert_chain *chain,
+ struct ns_cert_info **cert_info_out)
+{
+ struct ns_cert_info *certs;
+ size_t depth;
+ nserror res;
+
+ certs = calloc(chain->depth, sizeof(struct ns_cert_info));
+ if (certs == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ for (depth = 0; depth < chain->depth;depth++) {
+ res = der_to_certinfo(chain->certs[depth].der,
+ chain->certs[depth].der_length,
+ certs + depth);
+ if (res != NSERROR_OK) {
+ free(certs);
+ return res;
+ }
+ certs[depth].err = chain->certs[depth].err;
+ }
+
+ *cert_info_out = certs;
+ return NSERROR_OK;
+}
+
+#else
+static nserror
+convert_chain_to_cert_info(const struct cert_chain *chain,
+ struct ns_cert_info **cert_info_out)
+{
+ return NSERROR_NOT_IMPLEMENTED;
+}
+#endif
+
+
+static nserror
+format_certificate_name(struct fetch_about_context *ctx,
+ struct ns_cert_name *cert_name)
+{
+ nserror res;
+ res = fetch_about_ssenddataf(ctx,
+ "<tr><th>Common Name</th><td>%s</td></tr>\n",
+ cert_name->common_name);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ if (cert_name->organisation != NULL) {
+ res = fetch_about_ssenddataf(ctx,
+ "<tr><th>Organisation</th><td>%s</td></tr>\n",
+ cert_name->organisation);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ if (cert_name->organisation_unit != NULL) {
+ res = fetch_about_ssenddataf(ctx,
+ "<tr><th>Organisation Unit</th><td>%s</td></tr>\n",
+ cert_name->organisation_unit);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ if (cert_name->locality != NULL) {
+ res = fetch_about_ssenddataf(ctx,
+ "<tr><th>Locality</th><td>%s</td></tr>\n",
+ cert_name->locality);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ if (cert_name->province != NULL) {
+ res = fetch_about_ssenddataf(ctx,
+ "<tr><th>Privince</th><td>%s</td></tr>\n",
+ cert_name->province);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ if (cert_name->country != NULL) {
+ res = fetch_about_ssenddataf(ctx,
+ "<tr><th>Country</th><td>%s</td></tr>\n",
+ cert_name->country);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ return res;
+}
+
+/**
+ * output formatted certificate subject alternate names
+ */
+static nserror
+format_certificate_san(struct fetch_about_context *ctx,
+ struct ns_cert_san *san)
+{
+ nserror res;
+
+ if (san == NULL) {
+ return NSERROR_OK;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "<table class=\"info\">\n"
+ "<tr><th>Alternative Names</th><td><hr></td></tr>\n");
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ while (san != NULL) {
+ res = fetch_about_ssenddataf(ctx,
+ "<tr><th>DNS Name</th><td>%s</td></tr>\n",
+ san->name);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ san = san->next;
+ }
+
+ res = fetch_about_ssenddataf(ctx, "</table>\n");
+
+ return res;
+
+}
+
+
+static nserror
+format_certificate_public_key(struct fetch_about_context *ctx,
+ struct ns_cert_pkey *public_key)
+{
+ nserror res;
+
+ if (public_key->algor == NULL) {
+ /* skip the table if no algorithm name */
+ return NSERROR_OK;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "<table class=\"info\">\n"
+ "<tr><th>Public Key</th><td><hr></td></tr>\n"
+ "<tr><th>Algorithm</th><td>%s</td></tr>\n"
+ "<tr><th>Key Size</th><td>%d</td></tr>\n",
+ public_key->algor,
+ public_key->size);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+
+ if (public_key->exponent != NULL) {
+ res = fetch_about_ssenddataf(ctx,
+ "<tr><th>Exponent</th><td>%s</td></tr>\n",
+ public_key->exponent);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ if (public_key->modulus != NULL) {
+ res = fetch_about_ssenddataf(ctx,
+ "<tr><th>Modulus</th><td class=\"data\">%s</td></tr>\n",
+ public_key->modulus);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ if (public_key->curve != NULL) {
+ res = fetch_about_ssenddataf(ctx,
+ "<tr><th>Curve</th><td>%s</td></tr>\n",
+ public_key->curve);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ if (public_key->public != NULL) {
+ res = fetch_about_ssenddataf(ctx,
+ "<tr><th>Public Value</th><td>%s</td></tr>\n",
+ public_key->public);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ res = fetch_about_ssenddataf(ctx, "</table>\n");
+
+ return res;
+}
+
+static nserror
+format_certificate_fingerprint(struct fetch_about_context *ctx,
+ struct ns_cert_info *cert_info)
+{
+ nserror res;
+
+ if ((cert_info->sha1fingerprint == NULL) &&
+ (cert_info->sha256fingerprint == NULL)) {
+ /* skip the table if no fingerprints */
+ return NSERROR_OK;
+ }
+
+
+ res = fetch_about_ssenddataf(ctx,
+ "<table class=\"info\">\n"
+ "<tr><th>Fingerprints</th><td><hr></td></tr>\n");
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ if (cert_info->sha256fingerprint != NULL) {
+ res = fetch_about_ssenddataf(ctx,
+ "<tr><th>SHA-256</th><td class=\"data\">%s</td></tr>\n",
+ cert_info->sha256fingerprint);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ if (cert_info->sha1fingerprint != NULL) {
+ res = fetch_about_ssenddataf(ctx,
+ "<tr><th>SHA-1</th><td class=\"data\">%s</td></tr>\n",
+ cert_info->sha1fingerprint);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ res = fetch_about_ssenddataf(ctx, "</table>\n");
+
+ return res;
+}
+
+static nserror
+format_certificate(struct fetch_about_context *ctx,
+ struct ns_cert_info *cert_info,
+ size_t depth)
+{
+ nserror res;
+
+ res = fetch_about_ssenddataf(ctx,
+ "<h2 id=\"%"PRIsizet"\" class=\"ns-border\">%s</h2>\n",
+ depth, cert_info->subject_name.common_name);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ if (cert_info->err != SSL_CERT_ERR_OK) {
+ res = fetch_about_ssenddataf(ctx,
+ "<table class=\"info\">\n"
+ "<tr class=\"ns-even-fg-bad\">"
+ "<th>Fault</th>"
+ "<td>%s</td>"
+ "</tr>"
+ "</table>\n",
+ messages_get_sslcode(cert_info->err));
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "<table class=\"info\">\n"
+ "<tr><th>Issued To</th><td><hr></td></tr>\n");
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = format_certificate_name(ctx, &cert_info->subject_name);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "</table>\n");
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "<table class=\"info\">\n"
+ "<tr><th>Issued By</th><td><hr></td></tr>\n");
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = format_certificate_name(ctx, &cert_info->issuer_name);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "</table>\n");
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "<table class=\"info\">\n"
+ "<tr><th>Validity</th><td><hr></td></tr>\n"
+ "<tr><th>Valid From</th><td>%s</td></tr>\n"
+ "<tr><th>Valid Until</th><td>%s</td></tr>\n"
+ "</table>\n",
+ cert_info->not_before,
+ cert_info->not_after);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = format_certificate_san(ctx, cert_info->san);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = format_certificate_public_key(ctx, &cert_info->public_key);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "<table class=\"info\">\n"
+ "<tr><th>Miscellaneous</th><td><hr></td></tr>\n");
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ if (cert_info->serialnum != NULL) {
+ res = fetch_about_ssenddataf(ctx,
+ "<tr><th>Serial Number</th><td>%s</td></tr>\n",
+ cert_info->serialnum);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ if (cert_info->sig_algor != NULL) {
+ res = fetch_about_ssenddataf(ctx,
+ "<tr><th>Signature Algorithm</th>"
+ "<td>%s</td></tr>\n",
+ cert_info->sig_algor);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "<tr><th>Version</th><td>%ld</td></tr>\n"
+ "</table>\n",
+ cert_info->version);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = format_certificate_fingerprint(ctx, cert_info);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ return res;
+}
+
+/**
+ * Handler to generate about:certificate page.
+ *
+ * Shows details of a certificate chain
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_certificate_handler(struct fetch_about_context *ctx)
+{
+ int code = 200;
+ nserror res;
+ struct cert_chain *chain = NULL;
+
+ /* content is going to return ok */
+ fetch_about_set_http_code(ctx, code);
+
+ /* content type */
+ if (fetch_about_send_header(ctx, "Content-Type: text/html"))
+ goto fetch_about_certificate_handler_aborted;
+
+ /* page head */
+ res = fetch_about_ssenddataf(ctx,
+ "<html>\n<head>\n"
+ "<title>NetSurf Browser Certificate Viewer</title>\n"
+ "<link rel=\"stylesheet\" type=\"text/css\" "
+ "href=\"resource:internal.css\">\n"
+ "</head>\n"
+ "<body id=\"certificate\" class=\"ns-even-bg ns-even-fg ns-border\">\n"
+ "<h1 class=\"ns-border\">Certificate</h1>\n");
+ if (res != NSERROR_OK) {
+ goto fetch_about_certificate_handler_aborted;
+ }
+
+ res = cert_chain_from_query(fetch_about_get_url(ctx), &chain);
+ if (res != NSERROR_OK) {
+ res = fetch_about_ssenddataf(ctx, "<p>Could not process that</p>\n");
+ if (res != NSERROR_OK) {
+ goto fetch_about_certificate_handler_aborted;
+ }
+ } else {
+ struct ns_cert_info *cert_info;
+ res = convert_chain_to_cert_info(chain, &cert_info);
+ if (res == NSERROR_OK) {
+ size_t depth;
+ res = fetch_about_ssenddataf(ctx, "<ul>\n");
+ if (res != NSERROR_OK) {
+ free_ns_cert_info(cert_info);
+ goto fetch_about_certificate_handler_aborted;
+ }
+
+ for (depth = 0; depth < chain->depth; depth++) {
+ res = fetch_about_ssenddataf(ctx, "<li><a href=\"#%"PRIsizet"\">%s</a></li>\n",
+ depth, (cert_info + depth)
+ ->subject_name
+ .common_name);
+ if (res != NSERROR_OK) {
+ free_ns_cert_info(cert_info);
+ goto fetch_about_certificate_handler_aborted;
+ }
+
+ }
+
+ res = fetch_about_ssenddataf(ctx, "</ul>\n");
+ if (res != NSERROR_OK) {
+ free_ns_cert_info(cert_info);
+ goto fetch_about_certificate_handler_aborted;
+ }
+
+ for (depth = 0; depth < chain->depth; depth++) {
+ res = format_certificate(ctx, cert_info + depth,
+ depth);
+ if (res != NSERROR_OK) {
+ free_ns_cert_info(cert_info);
+ goto fetch_about_certificate_handler_aborted;
+ }
+
+ }
+ free_ns_cert_info(cert_info);
+
+ } else {
+ res = fetch_about_ssenddataf(ctx,
+ "<p>Invalid certificate data</p>\n");
+ if (res != NSERROR_OK) {
+ goto fetch_about_certificate_handler_aborted;
+ }
+ }
+ }
+
+
+ /* page footer */
+ res = fetch_about_ssenddataf(ctx, "</body>\n</html>\n");
+ if (res != NSERROR_OK) {
+ goto fetch_about_certificate_handler_aborted;
+ }
+
+ fetch_about_send_finished(ctx);
+
+ cert_chain_free(chain);
+
+ return true;
+
+fetch_about_certificate_handler_aborted:
+ cert_chain_free(chain);
+ return false;
+}
diff --git a/content/fetchers/about/certificate.h b/content/fetchers/about/certificate.h
new file mode 100644
index 000000000..80ac06853
--- /dev/null
+++ b/content/fetchers/about/certificate.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * about scheme certificate handler interface
+ */
+
+#ifndef NETSURF_CONTENT_FETCHERS_ABOUT_CERTIFICATE_H
+#define NETSURF_CONTENT_FETCHERS_ABOUT_CERTIFICATE_H
+
+/**
+ * Handler to generate about scheme certificate page.
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_certificate_handler(struct fetch_about_context *ctx);
+
+#endif
diff --git a/content/fetchers/about/chart.c b/content/fetchers/about/chart.c
new file mode 100644
index 000000000..c030c12b4
--- /dev/null
+++ b/content/fetchers/about/chart.c
@@ -0,0 +1,630 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * content generator for the about scheme chart page
+ *
+ * A chart consists of the figure area in which a chart a title and a
+ * key are placed.
+ *
+ *
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <stdio.h>
+
+#include "utils/config.h"
+#include "netsurf/inttypes.h"
+#include "utils/config.h"
+#include "utils/utils.h"
+#include "utils/errors.h"
+#include "utils/nsurl.h"
+
+#include "private.h"
+#include "chart.h"
+
+/** minimum figure dimension */
+#define FIGURE_MIN_WIDTH 150
+#define FIGURE_MIN_HEIGHT 100
+
+enum chart_type {
+ CHART_TYPE_UNKNOWN,
+ CHART_TYPE_PIE,
+};
+
+/* type of chart key */
+enum key_type {
+ CHART_KEY_UNSET,
+ CHART_KEY_NONE,
+ CHART_KEY_LEFT,
+ CHART_KEY_RIGHT,
+ CHART_KEY_TOP,
+ CHART_KEY_BOT,
+ CHART_KEY_END
+};
+
+
+struct chart_label {
+ char *title; /* label title */
+ unsigned int colour; /* colour */
+};
+
+struct chart_series {
+ unsigned int len; /* number of values in the series */
+ float *value; /* array of values */
+};
+
+#define MAX_SERIES 4
+
+struct chart_data {
+ unsigned int series_len;
+ struct chart_series series[MAX_SERIES];
+
+ unsigned int label_len; /* number of labels */
+ struct chart_label *label;
+
+};
+
+/**
+ * parameters for a chart figure
+ */
+struct chart_param {
+ enum chart_type type;
+ enum key_type key; /* what type of key to use */
+ unsigned int width; /* width of figure */
+ unsigned int height; /* height of figure */
+ char *title; /* title */
+ struct {
+ unsigned int x;
+ unsigned int y;
+ unsigned int width;
+ unsigned int height;
+ } area; /* chart area within figure */
+ struct chart_data data;
+};
+
+#define DEF_COLOUR_NUM 8
+/** default colour series */
+static unsigned int colour_series[DEF_COLOUR_NUM] =
+ {
+ 0x00ff00, /* green */
+ 0x0000ff, /* blue */
+ 0xff0000, /* red */
+ 0xffff00, /* yellow */
+ 0x00ffff, /* cyan */
+ 0xff00ff, /* pink */
+ 0x777777, /* grey */
+ 0x000000, /* black */
+ };
+
+
+/* ensures there are labels present for every value */
+static nserror ensure_label_count(struct chart_param *chart, unsigned int count)
+{
+ unsigned int lidx;
+ int deltac;
+ struct chart_label *nlabels;
+
+ deltac = count - chart->data.label_len;
+ if (deltac <= 0) {
+ /* there are enough labels */
+ return NSERROR_OK;
+ }
+
+ nlabels = realloc(chart->data.label,
+ count * sizeof(struct chart_label));
+ if (nlabels == NULL) {
+ return NSERROR_NOMEM;
+ }
+ chart->data.label = nlabels;
+
+ for (lidx = chart->data.label_len; lidx < count; lidx++) {
+ chart->data.label[lidx].title = calloc(1, 20);
+ snprintf(chart->data.label[lidx].title, 19, "item %d", lidx + 1);
+ chart->data.label[lidx].colour = colour_series[lidx % DEF_COLOUR_NUM];
+ }
+
+ chart->data.label_len = count;
+
+ return NSERROR_OK;
+}
+
+/**
+ * extract values for a series
+ */
+static nserror
+extract_series_values(struct chart_param *chart,
+ unsigned int series_num,
+ const char *valstr,
+ size_t valstrlen)
+{
+ nserror res;
+ unsigned int valcur;
+ size_t valstart;/* value start in valstr */
+ size_t vallen; /* value end in valstr */
+ struct chart_series *series;
+
+ series = chart->data.series + series_num;
+
+ /* ensure we do not leak any data in this series */
+ if (series->value != NULL) {
+ free(series->value);
+ }
+
+ /* count how many values present */
+ for (series->len = 1, valstart=0; valstart < valstrlen; valstart++) {
+ if (valstr[valstart] == ',') {
+ series->len++;
+ }
+ }
+
+ /* allocate storage for values */
+ series->value = calloc(series->len, sizeof(float));
+ if (series->value == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ /* extract values from query string */
+ for (valcur = 0, vallen = 0, valstart = 0;
+ (valstart < valstrlen) && (valcur < series->len);
+ valstart += vallen, valcur++) {
+ /* get query section length */
+ vallen = 0;
+ while (((valstart + vallen) < valstrlen) &&
+ (valstr[valstart + vallen] != ',')) {
+ vallen++;
+ }
+
+ series->value[valcur] = strtof(valstr + valstart, NULL);
+ vallen++; /* account for , separator */
+ }
+
+ res = ensure_label_count(chart, series->len);
+
+ return res;
+}
+
+
+/**
+ * extract values for next series
+ */
+static nserror
+extract_next_series_values(struct chart_param *chart,
+ const char *valstr,
+ size_t valstrlen)
+{
+ nserror res;
+
+ if (chart->data.series_len >= MAX_SERIES) {
+ return NSERROR_NOSPACE;
+ }
+
+ res = extract_series_values(chart,
+ chart->data.series_len,
+ valstr,
+ valstrlen);
+ if (res == NSERROR_OK) {
+ chart->data.series_len++;
+ }
+
+ return res;
+}
+
+
+/**
+ * extract label title
+ */
+static nserror
+extract_series_labels(struct chart_param *chart,
+ const char *valstr,
+ size_t valstrlen)
+{
+ nserror res;
+ unsigned int valcount; /* count of values in valstr */
+ unsigned int valcur;
+ size_t valstart;/* value start in valstr */
+ size_t vallen; /* value end in valstr */
+
+ for (valcount = 1, valstart=0; valstart < valstrlen; valstart++) {
+ if (valstr[valstart] == ',') {
+ valcount++;
+ }
+ }
+
+ res = ensure_label_count(chart, valcount);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+
+ for (valcur = 0, vallen = 0, valstart = 0;
+ (valstart < valstrlen) && (valcur < chart->data.label_len);
+ valstart += vallen, valcur++) {
+ /* get query section length */
+ vallen = 0;
+ while (((valstart + vallen) < valstrlen) &&
+ (valstr[valstart + vallen] != ',')) {
+ vallen++;
+ }
+
+ chart->data.label[valcur].title = strndup(valstr + valstart, vallen);
+ vallen++; /* account for , separator */
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * extract labels colour
+ */
+static nserror
+extract_series_colours(struct chart_param *chart,
+ const char *valstr,
+ size_t valstrlen)
+{
+ return NSERROR_OK;
+}
+
+/**
+ * process a part of a query
+ */
+static nserror
+process_query_section(const char *str, size_t len, struct chart_param *chart)
+{
+ nserror res = NSERROR_OK;
+
+ if ((len > 6) &&
+ (strncmp(str, "width=", 6) == 0)) {
+ /* figure width */
+ chart->width = strtoul(str + 6, NULL, 10);
+ } else if ((len > 7) &&
+ (strncmp(str, "height=", 7) == 0)) {
+ /* figure height */
+ chart->height = strtoul(str + 7, NULL, 10);
+ } else if ((len > 8) &&
+ (strncmp(str, "cawidth=", 8) == 0)) {
+ /* chart area width */
+ chart->area.width = strtoul(str + 8, NULL, 10);
+ } else if ((len > 9) &&
+ (strncmp(str, "caheight=", 9) == 0)) {
+ /* chart area height */
+ chart->area.height = strtoul(str + 9, NULL, 10);
+ } else if ((len > 4) &&
+ (strncmp(str, "key=", 4) == 0)) {
+ /* figure has key */
+ chart->key = strtoul(str + 4, NULL, 10);
+ } else if ((len > 6) &&
+ (strncmp(str, "title=", 6) == 0)) {
+ chart->title = strndup(str + 6, len - 6);
+ } else if ((len > 5) &&
+ (strncmp(str, "type=", 5) == 0)) {
+ if (strncmp(str + 5, "pie", len - 5) == 0) {
+ chart->type = CHART_TYPE_PIE;
+ } else {
+ chart->type = CHART_TYPE_UNKNOWN;
+ }
+ } else if ((len > 7) &&
+ (strncmp(str, "values=", 7) == 0)) {
+ res = extract_next_series_values(chart, str + 7, len - 7);
+ } else if ((len > 7) &&
+ (strncmp(str, "labels=", 7) == 0)) {
+ res = extract_series_labels(chart, str + 7, len - 7);
+ } else if ((len > 8) &&
+ (strncmp(str, "colours=", 8) == 0)) {
+ res = extract_series_colours(chart, str + 8, len - 8);
+ }
+
+ return res;
+}
+
+
+
+static nserror
+chart_from_query(struct nsurl *url, struct chart_param *chart)
+{
+ nserror res;
+ char *querystr;
+ size_t querylen;
+ size_t kvstart;/* key value start */
+ size_t kvlen; /* key value end */
+
+ res = nsurl_get(url, NSURL_QUERY, &querystr, &querylen);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ for (kvlen = 0, kvstart = 0; kvstart < querylen; kvstart += kvlen) {
+ /* get query section length */
+ kvlen = 0;
+ while (((kvstart + kvlen) < querylen) &&
+ (querystr[kvstart + kvlen] != '&')) {
+ kvlen++;
+ }
+
+ res = process_query_section(querystr + kvstart, kvlen, chart);
+ if (res != NSERROR_OK) {
+ break;
+ }
+ kvlen++; /* account for & separator */
+ }
+ free(querystr);
+
+ /* sanity check dimensions */
+ if (chart->width < FIGURE_MIN_WIDTH) {
+ /* bad width - check height */
+ if (chart->height < FIGURE_MIN_HEIGHT) {
+ /* both bad set to defaults */
+ chart->width = FIGURE_MIN_WIDTH;
+ chart->height = FIGURE_MIN_HEIGHT;
+ } else {
+ /* base width on valid height */
+ chart->width = (chart->height * 3) / 2;
+ }
+ } else {
+ /* good width check height */
+ if (chart->height < FIGURE_MIN_HEIGHT) {
+ /* base height on valid width */
+ chart->height = (chart->width * 2) / 3;
+ }
+ }
+
+ /* ensure legend type correct */
+ if ((chart->key == CHART_KEY_UNSET) ||
+ (chart->key >= CHART_KEY_END )) {
+ /* default to putting key on right */
+ chart->key = CHART_KEY_RIGHT;
+ }
+
+ return NSERROR_OK;
+}
+
+
+static nserror
+output_pie_legend(struct fetch_about_context *ctx, struct chart_param *chart)
+{
+ nserror res;
+ unsigned int lblidx;
+ unsigned int legend_width;
+ unsigned int legend_height;
+ unsigned int vertical_spacing;
+
+ switch (chart->key) {
+
+ case CHART_KEY_NONE:
+ break;
+ case CHART_KEY_RIGHT:
+ legend_width = chart->width - chart->area.width - chart->area.x;
+ legend_width -= 10; /* margin */
+ legend_height = chart->height;
+ vertical_spacing = legend_height / (chart->data.label_len + 1);
+
+ for(lblidx = 0; lblidx < chart->data.label_len ; lblidx++) {
+ res = fetch_about_ssenddataf(ctx,
+ "<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" fill=\"#%06x\" />",
+ chart->width - legend_width,
+ (vertical_spacing * lblidx) + (vertical_spacing/2),
+ vertical_spacing * 2 / 3,
+ vertical_spacing * 2 / 3,
+ chart->data.label[lblidx].colour);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ res = fetch_about_ssenddataf(ctx,
+ "<text x=\"%d\" y=\"%d\" fill=\"#%06x\" >%s</text>",
+ chart->width - legend_width + vertical_spacing,
+ vertical_spacing * (lblidx+1),
+ chart->data.label[lblidx].colour,
+ chart->data.label[lblidx].title);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return NSERROR_OK;
+}
+
+static float
+compute_series_total(struct chart_param *chart, unsigned int series)
+{
+ float total;
+ unsigned int curdata;
+
+ for (total = 0, curdata = 0;
+ curdata < chart->data.series[series].len;
+ curdata++) {
+ total += chart->data.series[series].value[curdata];
+ }
+ return total;
+}
+
+/**
+ * render the data as a pie chart svg
+ */
+static bool
+pie_chart(struct fetch_about_context *ctx, struct chart_param *chart)
+{
+ nserror res;
+ float ra; /* pie a radius */
+ float rb; /* pie b radius */
+ float series_total;
+ unsigned int curdata; /* current data point index */
+ float last_x, last_y;
+ float end_x, end_y;
+ float start;
+ float extent;
+ bool large;
+ float circle_centre_x, circle_centre_y;
+
+ /* ensure there is data to render */
+ if ((chart->data.series_len < 1) || (chart->data.series[0].len < 2)) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* get the first series total value */
+ series_total = compute_series_total(chart, 0);
+ if (series_total == 0) {
+ /* dividing by zero is embarasing */
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /*
+ * need to ensure the chart area is setup correctly
+ *
+ * this is left to each chart type as different charts
+ * have differnt requirements
+ */
+ if ((chart->area.width == 0) || (chart->area.height == 0)) {
+ /*
+ * pie chart defaults to square of smaller of figure
+ * width and height
+ */
+ if (chart->width > chart->height) {
+ chart->area.width = chart->area.height = (chart->height - chart->area.x);
+ } else {
+ chart->area.width = chart->area.height = (chart->width - chart->area.y);
+ }
+ }
+
+ /* content is going to return ok */
+ fetch_about_set_http_code(ctx, 200);
+
+ /* content type */
+ if (fetch_about_send_header(ctx,
+ "Content-Type: image/svg; charset=utf-8")) {
+ goto aborted;
+ }
+
+ /* get the pie charts elipse radii */
+ ra = chart->area.width / 2;
+ rb = chart->area.height / 2;
+
+ /* get the offset to the circle centre */
+ circle_centre_x = chart->area.x + ra;
+ circle_centre_y = chart->area.y + rb;
+
+
+ /* svg header */
+ res = fetch_about_ssenddataf(ctx,
+ "<svg width=\"%u\" height=\"%u\" "
+ "xmlns=\"http://www.w3.org/2000/svg\">\n",
+ chart->width, chart->height);
+ if (res != NSERROR_OK) {
+ goto aborted;
+ }
+
+ /* generate the legend */
+ res = output_pie_legend(ctx, chart);
+ if (res != NSERROR_OK) {
+ goto aborted;
+ }
+
+ /* plot the arcs */
+ start = -M_PI_2;
+ last_x = (ra * cos(start));
+ last_y = (rb * sin(start));
+
+ /* iterate over each data point creating a slice o pie */
+ for (curdata=0; curdata < chart->data.series[0].len; curdata++) {
+ extent = ((chart->data.series[0].value[curdata] / series_total) * 2 * M_PI);
+ end_x = (ra * cos(start + extent));
+ end_y = (rb * sin(start + extent));
+
+ if (extent > M_PI) {
+ large = true;
+ } else {
+ large = false;
+ }
+
+ res = fetch_about_ssenddataf(
+ ctx,
+ "<path d=\"M %g %g\n"
+ "A %g %g 0 %d 1 %g %g\n"
+ "L %g %g Z\" fill=\"#%06x\" />\n",
+ circle_centre_x + last_x,
+ circle_centre_y + last_y,
+ ra, rb, large?1:0,
+ circle_centre_x + end_x,
+ circle_centre_y + end_y,
+ circle_centre_x,
+ circle_centre_y,
+ chart->data.label[curdata].colour);
+ if (res != NSERROR_OK) {
+ goto aborted;
+ }
+ last_x = end_x;
+ last_y = end_y;
+ start +=extent;
+ }
+
+ res = fetch_about_ssenddataf(ctx, "</svg>\n");
+ if (res != NSERROR_OK) {
+ goto aborted;
+ }
+
+ fetch_about_send_finished(ctx);
+
+ return true;
+
+ aborted:
+
+ return false;
+
+}
+
+/**
+ * Handler to generate about scheme chart page.
+ *
+ * generates an svg chart
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_chart_handler(struct fetch_about_context *ctx)
+{
+ nserror res;
+ struct chart_param chart;
+ memset(&chart, 0, sizeof(struct chart_param));
+
+ res = chart_from_query(fetch_about_get_url(ctx), &chart);
+ if (res != NSERROR_OK) {
+ goto aborted;
+ }
+
+ switch (chart.type) {
+ case CHART_TYPE_PIE:
+ return pie_chart(ctx, &chart);
+
+
+ default:
+ break;
+ }
+
+aborted:
+
+ return false;
+
+}
diff --git a/content/fetchers/about/chart.h b/content/fetchers/about/chart.h
new file mode 100644
index 000000000..4eb7e7898
--- /dev/null
+++ b/content/fetchers/about/chart.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * about scheme chart handler interface
+ */
+
+#ifndef NETSURF_CONTENT_FETCHERS_ABOUT_CHART_H
+#define NETSURF_CONTENT_FETCHERS_ABOUT_CHART_H
+
+/**
+ * Handler to generate about scheme chart page.
+ *
+ * generates an svg chart
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_chart_handler(struct fetch_about_context *ctx);
+
+#endif
diff --git a/content/fetchers/about/choices.c b/content/fetchers/about/choices.c
new file mode 100644
index 000000000..a95502e6e
--- /dev/null
+++ b/content/fetchers/about/choices.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * content generator for the about scheme blank page
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include "netsurf/types.h"
+#include "utils/errors.h"
+#include "utils/nsoption.h"
+
+#include "private.h"
+#include "choices.h"
+
+/**
+ * Generate the text of a Choices file which represents the current
+ * in use options.
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_choices_handler(struct fetch_about_context *ctx)
+{
+ char buffer[1024];
+ int code = 200;
+ int slen;
+ unsigned int opt_loop = 0;
+ int res = 0;
+
+ /* content is going to return ok */
+ fetch_about_set_http_code(ctx, code);
+
+ /* content type */
+ if (fetch_about_send_header(ctx, "Content-Type: text/plain"))
+ goto fetch_about_choices_handler_aborted;
+
+ slen = snprintf(buffer, sizeof buffer,
+ "# Automatically generated current NetSurf browser Choices\n");
+
+ do {
+ res = nsoption_snoptionf(buffer + slen,
+ sizeof buffer - slen,
+ opt_loop,
+ "%k:%v\n");
+ if (res <= 0)
+ break; /* last option */
+
+ if (res >= (int) (sizeof buffer - slen)) {
+ /* last entry would not fit in buffer, submit buffer */
+ res = fetch_about_senddata(ctx, (const uint8_t *)buffer, slen);
+ if (res != NSERROR_OK) {
+ goto fetch_about_choices_handler_aborted;
+ }
+ slen = 0;
+ } else {
+ /* normal addition */
+ slen += res;
+ opt_loop++;
+ }
+ } while (res > 0);
+
+ res = fetch_about_senddata(ctx, (const uint8_t *)buffer, slen);
+ if (res != NSERROR_OK) {
+ goto fetch_about_choices_handler_aborted;
+ }
+
+ fetch_about_send_finished(ctx);
+
+ return true;
+
+fetch_about_choices_handler_aborted:
+ return false;
+}
diff --git a/content/fetchers/about/choices.h b/content/fetchers/about/choices.h
new file mode 100644
index 000000000..0548f5b9c
--- /dev/null
+++ b/content/fetchers/about/choices.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * about scheme choices handler interface
+ */
+
+#ifndef NETSURF_CONTENT_FETCHERS_ABOUT_CHOICES_H
+#define NETSURF_CONTENT_FETCHERS_ABOUT_CHOICES_H
+
+/**
+ * Handler to generate about scheme choices page.
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_choices_handler(struct fetch_about_context *ctx);
+
+#endif
diff --git a/content/fetchers/about/config.c b/content/fetchers/about/config.c
new file mode 100644
index 000000000..a18af956f
--- /dev/null
+++ b/content/fetchers/about/config.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * content generator for the about scheme blank page
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "netsurf/types.h"
+#include "utils/errors.h"
+#include "utils/nsoption.h"
+
+#include "private.h"
+#include "config.h"
+
+/**
+ * Handler to generate about scheme config page
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_config_handler(struct fetch_about_context *ctx)
+{
+ char buffer[1024];
+ int slen = 0;
+ unsigned int opt_loop = 0;
+ int elen = 0; /* entry length */
+ nserror res;
+ bool even = false;
+
+ /* content is going to return ok */
+ fetch_about_set_http_code(ctx, 200);
+
+ /* content type */
+ if (fetch_about_send_header(ctx, "Content-Type: text/html")) {
+ goto fetch_about_config_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "<html>\n<head>\n"
+ "<title>NetSurf Browser Config</title>\n"
+ "<link rel=\"stylesheet\" type=\"text/css\" "
+ "href=\"resource:internal.css\">\n"
+ "</head>\n"
+ "<body "
+ "id =\"configlist\" "
+ "class=\"ns-even-bg ns-even-fg ns-border\" "
+ "style=\"overflow: hidden;\">\n"
+ "<h1 class=\"ns-border\">NetSurf Browser Config</h1>\n"
+ "<table class=\"config\">\n"
+ "<tr><th>Option</th>"
+ "<th>Type</th>"
+ "<th>Provenance</th>"
+ "<th>Setting</th></tr>\n");
+ if (res != NSERROR_OK) {
+ goto fetch_about_config_handler_aborted;
+ }
+
+
+ do {
+ if (even) {
+ elen = nsoption_snoptionf(buffer + slen,
+ sizeof buffer - slen,
+ opt_loop,
+ "<tr class=\"ns-even-bg\">"
+ "<th class=\"ns-border\">%k</th>"
+ "<td class=\"ns-border\">%t</td>"
+ "<td class=\"ns-border\">%p</td>"
+ "<td class=\"ns-border\">%V</td>"
+ "</tr>\n");
+ } else {
+ elen = nsoption_snoptionf(buffer + slen,
+ sizeof buffer - slen,
+ opt_loop,
+ "<tr class=\"ns-odd-bg\">"
+ "<th class=\"ns-border\">%k</th>"
+ "<td class=\"ns-border\">%t</td>"
+ "<td class=\"ns-border\">%p</td>"
+ "<td class=\"ns-border\">%V</td>"
+ "</tr>\n");
+ }
+ if (elen <= 0)
+ break; /* last option */
+
+ if (elen >= (int) (sizeof buffer - slen)) {
+ /* last entry would not fit in buffer, submit buffer */
+ res = fetch_about_senddata(ctx, (const uint8_t *)buffer, slen);
+ if (res != NSERROR_OK) {
+ goto fetch_about_config_handler_aborted;
+ }
+ slen = 0;
+ } else {
+ /* normal addition */
+ slen += elen;
+ opt_loop++;
+ even = !even;
+ }
+ } while (elen > 0);
+
+ slen += snprintf(buffer + slen, sizeof buffer - slen,
+ "</table>\n</body>\n</html>\n");
+
+ res = fetch_about_senddata(ctx, (const uint8_t *)buffer, slen);
+ if (res != NSERROR_OK) {
+ goto fetch_about_config_handler_aborted;
+ }
+
+ fetch_about_send_finished(ctx);
+
+ return true;
+
+fetch_about_config_handler_aborted:
+ return false;
+}
diff --git a/content/fetchers/about/config.h b/content/fetchers/about/config.h
new file mode 100644
index 000000000..efef23971
--- /dev/null
+++ b/content/fetchers/about/config.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * about scheme config handler interface
+ */
+
+#ifndef NETSURF_CONTENT_FETCHERS_ABOUT_CONFIG_H
+#define NETSURF_CONTENT_FETCHERS_ABOUT_CONFIG_H
+
+/**
+ * Handler to generate about scheme config page.
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_config_handler(struct fetch_about_context *ctx);
+
+#endif
diff --git a/content/fetchers/about/imagecache.c b/content/fetchers/about/imagecache.c
new file mode 100644
index 000000000..23d3ef41c
--- /dev/null
+++ b/content/fetchers/about/imagecache.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * content generator for the about scheme imagecache page
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+
+#include "netsurf/types.h"
+
+#include "image/image_cache.h"
+
+#include "private.h"
+#include "imagecache.h"
+
+/* exported interface documented in about/imagecache.h */
+bool fetch_about_imagecache_handler(struct fetch_about_context *ctx)
+{
+ char buffer[2048]; /* output buffer */
+ int code = 200;
+ int slen;
+ unsigned int cent_loop = 0;
+ int elen = 0; /* entry length */
+ nserror res;
+ bool even = false;
+
+ /* content is going to return ok */
+ fetch_about_set_http_code(ctx, code);
+
+ /* content type */
+ if (fetch_about_send_header(ctx, "Content-Type: text/html"))
+ goto fetch_about_imagecache_handler_aborted;
+
+ /* page head */
+ res = fetch_about_ssenddataf(ctx,
+ "<html>\n<head>\n"
+ "<title>Image Cache Status</title>\n"
+ "<link rel=\"stylesheet\" type=\"text/css\" "
+ "href=\"resource:internal.css\">\n"
+ "</head>\n"
+ "<body id =\"cachelist\" class=\"ns-even-bg ns-even-fg ns-border\">\n"
+ "<h1 class=\"ns-border\">Image Cache Status</h1>\n");
+ if (res != NSERROR_OK) {
+ goto fetch_about_imagecache_handler_aborted;
+ }
+
+ /* image cache summary */
+ slen = image_cache_snsummaryf(buffer, sizeof(buffer),
+ "<p>Configured limit of %a hysteresis of %b</p>\n"
+ "<p>Total bitmap size in use %c (in %d)</p>\n"
+ "<p>Age %es</p>\n"
+ "<p>Peak size %f (in %g)</p>\n"
+ "<p>Peak image count %h (size %i)</p>\n"
+ "<p>Cache total/hit/miss/fail (counts) %j/%k/%l/%m "
+ "(%pj%%/%pk%%/%pl%%/%pm%%)"
+ "<img width=200 height=100 src=\"about:chart?type=pie&width=200&height=100&labels=hit,miss,fail&values=%k,%l,%m\" />"
+ "</p>\n");
+ if (slen >= (int) (sizeof(buffer))) {
+ goto fetch_about_imagecache_handler_aborted; /* overflow */
+ }
+
+ res = fetch_about_senddata(ctx, (const uint8_t *)buffer, slen);
+ if (res != NSERROR_OK) {
+ goto fetch_about_imagecache_handler_aborted;
+ }
+
+ /* image cache summary */
+ slen = image_cache_snsummaryf(buffer, sizeof(buffer),
+ "<p>Cache total/hit/miss/fail (size) %n/%o/%q/%r "
+ "(%pn%%/%po%%/%pq%%/%pr%%)"
+ "<img width=200 height=100 src=\"about:chart?type=pie&width=200&height=100&labels=hit,miss,fail&values=%o,%q,%r\" /></p>\n"
+ "<p>Total images never rendered: %s "
+ "(includes %t that were converted)</p>\n"
+ "<p>Total number of excessive conversions: %u "
+ "(from %v images converted more than once)"
+ "</p>\n"
+ "<p>Bitmap of size %w had most (%x) conversions</p>\n"
+ "<h2 class=\"ns-border\">Current contents</h2>\n");
+ if (slen >= (int) (sizeof(buffer))) {
+ goto fetch_about_imagecache_handler_aborted; /* overflow */
+ }
+
+ res = fetch_about_senddata(ctx, (const uint8_t *)buffer, slen);
+ if (res != NSERROR_OK) {
+ goto fetch_about_imagecache_handler_aborted;
+ }
+
+ /* image cache entry table */
+ res = fetch_about_ssenddataf(ctx, "<p class=\"imagecachelist\">\n"
+ "<strong>"
+ "<span>Entry</span>"
+ "<span>Content Key</span>"
+ "<span>Redraw Count</span>"
+ "<span>Conversion Count</span>"
+ "<span>Last Redraw</span>"
+ "<span>Bitmap Age</span>"
+ "<span>Bitmap Size</span>"
+ "<span>Source</span>"
+ "</strong>\n");
+ if (res != NSERROR_OK) {
+ goto fetch_about_imagecache_handler_aborted;
+ }
+
+ slen = 0;
+ do {
+ if (even) {
+ elen = image_cache_snentryf(buffer + slen,
+ sizeof buffer - slen,
+ cent_loop,
+ "<a href=\"%U\">"
+ "<span class=\"ns-border\">%e</span>"
+ "<span class=\"ns-border\">%k</span>"
+ "<span class=\"ns-border\">%r</span>"
+ "<span class=\"ns-border\">%c</span>"
+ "<span class=\"ns-border\">%a</span>"
+ "<span class=\"ns-border\">%g</span>"
+ "<span class=\"ns-border\">%s</span>"
+ "<span class=\"ns-border\">%o</span>"
+ "</a>\n");
+ } else {
+ elen = image_cache_snentryf(buffer + slen,
+ sizeof buffer - slen,
+ cent_loop,
+ "<a class=\"ns-odd-bg\" href=\"%U\">"
+ "<span class=\"ns-border\">%e</span>"
+ "<span class=\"ns-border\">%k</span>"
+ "<span class=\"ns-border\">%r</span>"
+ "<span class=\"ns-border\">%c</span>"
+ "<span class=\"ns-border\">%a</span>"
+ "<span class=\"ns-border\">%g</span>"
+ "<span class=\"ns-border\">%s</span>"
+ "<span class=\"ns-border\">%o</span>"
+ "</a>\n");
+ }
+ if (elen <= 0)
+ break; /* last option */
+
+ if (elen >= (int) (sizeof buffer - slen)) {
+ /* last entry would not fit in buffer, submit buffer */
+ res = fetch_about_senddata(ctx,
+ (const uint8_t *)buffer,
+ slen);
+ if (res != NSERROR_OK) {
+ goto fetch_about_imagecache_handler_aborted;
+ }
+
+ slen = 0;
+ } else {
+ /* normal addition */
+ slen += elen;
+ cent_loop++;
+ even = !even;
+ }
+ } while (elen > 0);
+
+ slen += snprintf(buffer + slen, sizeof buffer - slen,
+ "</p>\n</body>\n</html>\n");
+
+ res = fetch_about_senddata(ctx, (const uint8_t *)buffer, slen);
+ if (res != NSERROR_OK) {
+ goto fetch_about_imagecache_handler_aborted;
+ }
+
+ fetch_about_send_finished(ctx);
+
+ return true;
+
+fetch_about_imagecache_handler_aborted:
+ return false;
+}
diff --git a/content/fetchers/about/imagecache.h b/content/fetchers/about/imagecache.h
new file mode 100644
index 000000000..d1419cea7
--- /dev/null
+++ b/content/fetchers/about/imagecache.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * about scheme imagecache handler interface
+ */
+
+#ifndef NETSURF_CONTENT_FETCHERS_ABOUT_IMAGECACHE_H
+#define NETSURF_CONTENT_FETCHERS_ABOUT_IMAGECACHE_H
+
+/**
+ * Handler to generate about scheme imagecache page.
+ *
+ * Shows details of current image cache.
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_imagecache_handler(struct fetch_about_context *ctx);
+
+#endif
diff --git a/content/fetchers/about/nscolours.c b/content/fetchers/about/nscolours.c
new file mode 100644
index 000000000..bd7a5ed7a
--- /dev/null
+++ b/content/fetchers/about/nscolours.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * content generator for the about scheme query privacy page
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "netsurf/plot_style.h"
+
+#include "utils/errors.h"
+#include "utils/nscolour.h"
+
+#include "private.h"
+#include "nscolours.h"
+
+/**
+ * Handler to generate the nscolours stylesheet
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_nscolours_handler(struct fetch_about_context *ctx)
+{
+ nserror res;
+ const char *stylesheet;
+
+ /* content is going to return ok */
+ fetch_about_set_http_code(ctx, 200);
+
+ /* content type */
+ if (fetch_about_send_header(ctx, "Content-Type: text/css; charset=utf-8")) {
+ goto aborted;
+ }
+
+ res = nscolour_get_stylesheet(&stylesheet);
+ if (res != NSERROR_OK) {
+ goto aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "html {\n"
+ "\tbackground-color: #%06x;\n"
+ "}\n"
+ "%s",
+ colour_rb_swap(nscolours[NSCOLOUR_WIN_ODD_BG]),
+ stylesheet);
+ if (res != NSERROR_OK) {
+ goto aborted;
+ }
+
+ fetch_about_send_finished(ctx);
+
+ return true;
+
+aborted:
+
+ return false;
+}
diff --git a/content/fetchers/about/nscolours.h b/content/fetchers/about/nscolours.h
new file mode 100644
index 000000000..a602e4d99
--- /dev/null
+++ b/content/fetchers/about/nscolours.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * about scheme nscolours handler interface
+ */
+
+#ifndef NETSURF_CONTENT_FETCHERS_ABOUT_NSCOLOURS_H
+#define NETSURF_CONTENT_FETCHERS_ABOUT_NSCOLOURS_H
+
+/**
+ * Handler to generate the nscolours stylesheet
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_nscolours_handler(struct fetch_about_context *ctx);
+
+#endif
diff --git a/content/fetchers/about/private.h b/content/fetchers/about/private.h
new file mode 100644
index 000000000..fcf9b1987
--- /dev/null
+++ b/content/fetchers/about/private.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Private interfaces for the about scheme fetcher.
+ */
+
+#ifndef NETSURF_CONTENT_FETCHERS_ABOUT_PRIVATE_H
+#define NETSURF_CONTENT_FETCHERS_ABOUT_PRIVATE_H
+
+struct fetch_about_context;
+struct fetch_multipart_data;
+
+/**
+ * set http response code on about response
+ */
+bool fetch_about_set_http_code(struct fetch_about_context *ctx, long code);
+
+/**
+ * Send a header on the about response
+ *
+ * \param ctx The about fetch context
+ * \param fmt The format specifier of the header
+ * \return true if the fetch has been aborted else false
+ */
+bool fetch_about_send_header(struct fetch_about_context *ctx, const char *fmt, ...);
+
+/**
+ * send data on the about response
+ */
+nserror fetch_about_senddata(struct fetch_about_context *ctx, const uint8_t *data, size_t data_len);
+
+/**
+ * send formatted data on the about response
+ */
+nserror fetch_about_ssenddataf(struct fetch_about_context *ctx, const char *fmt, ...);
+
+/**
+ * complete the about fetch response
+ */
+bool fetch_about_send_finished(struct fetch_about_context *ctx);
+
+/**
+ * Generate a 500 server error respnse
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_srverror(struct fetch_about_context *ctx);
+
+/**
+ * get the fetch url
+ */
+struct nsurl *fetch_about_get_url(struct fetch_about_context *ctx);
+
+/**
+ * get multipart fetch data
+ */
+const struct fetch_multipart_data *fetch_about_get_multipart(struct fetch_about_context *ctx);
+
+#endif
diff --git a/content/fetchers/about/query.c b/content/fetchers/about/query.c
new file mode 100644
index 000000000..7c4e9f442
--- /dev/null
+++ b/content/fetchers/about/query.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * content generator for the about scheme query privacy page
+ */
+
+#include <stdlib.h>
+
+#include "utils/errors.h"
+#include "utils/nsurl.h"
+#include "utils/messages.h"
+
+#include "query.h"
+
+/* exported interface documented in about/query.h */
+nserror
+get_query_description(struct nsurl *url,
+ const char *key,
+ char **out_str)
+{
+ nserror res;
+ char *url_s;
+ size_t url_l;
+ char *str = NULL;
+
+ /* get the host in question */
+ res = nsurl_get(url, NSURL_HOST, &url_s, &url_l);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* obtain the description with the url substituted */
+ str = messages_get_buff(key, url_s);
+ if (str == NULL) {
+ res = NSERROR_NOMEM;
+ } else {
+ *out_str = str;
+ }
+
+ free(url_s);
+
+ return res;
+}
diff --git a/content/fetchers/about/query.h b/content/fetchers/about/query.h
new file mode 100644
index 000000000..889a9ecdd
--- /dev/null
+++ b/content/fetchers/about/query.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * about scheme query handlers support interface
+ */
+
+#ifndef NETSURF_CONTENT_FETCHERS_ABOUT_QUERY_H
+#define NETSURF_CONTENT_FETCHERS_ABOUT_QUERY_H
+
+/**
+ * generate a generic query description
+ *
+ * \param url The site url
+ * \param key message key
+ * \param out_str pointer to buffer with output
+ */
+nserror get_query_description(struct nsurl *url, const char *key, char **out_str);
+
+#endif
diff --git a/content/fetchers/about/query_auth.c b/content/fetchers/about/query_auth.c
new file mode 100644
index 000000000..1ed2e80ee
--- /dev/null
+++ b/content/fetchers/about/query_auth.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * content generator for the about scheme query privacy page
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "utils/errors.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "content/fetch.h"
+
+#include "private.h"
+#include "query_auth.h"
+
+
+/**
+ * generate the description of the login query
+ */
+static nserror
+get_authentication_description(struct nsurl *url,
+ const char *realm,
+ const char *username,
+ const char *password,
+ char **out_str)
+{
+ nserror res;
+ char *url_s;
+ size_t url_l;
+ char *str = NULL;
+ const char *key;
+
+ res = nsurl_get(url, NSURL_HOST, &url_s, &url_l);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ if ((*username == 0) && (*password == 0)) {
+ key = "LoginDescription";
+ } else {
+ key = "LoginAgain";
+ }
+
+ str = messages_get_buff(key, url_s, realm);
+ if (str != NULL) {
+ NSLOG(netsurf, INFO,
+ "key:%s url:%s realm:%s str:%s",
+ key, url_s, realm, str);
+ *out_str = str;
+ } else {
+ res = NSERROR_NOMEM;
+ }
+
+ free(url_s);
+
+ return res;
+}
+
+
+/**
+ * Handler to generate about scheme authentication query page
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_query_auth_handler(struct fetch_about_context *ctx)
+{
+ nserror res;
+ char *url_s;
+ size_t url_l;
+ const char *realm = "";
+ const char *username = "";
+ const char *password = "";
+ const char *title;
+ char *description = NULL;
+ struct nsurl *siteurl = NULL;
+ const struct fetch_multipart_data *curmd; /* mutipart data iterator */
+
+ /* extract parameters from multipart post data */
+ curmd = fetch_about_get_multipart(ctx);
+ while (curmd != NULL) {
+ if (strcmp(curmd->name, "siteurl") == 0) {
+ res = nsurl_create(curmd->value, &siteurl);
+ if (res != NSERROR_OK) {
+ return fetch_about_srverror(ctx);
+ }
+ } else if (strcmp(curmd->name, "realm") == 0) {
+ realm = curmd->value;
+ } else if (strcmp(curmd->name, "username") == 0) {
+ username = curmd->value;
+ } else if (strcmp(curmd->name, "password") == 0) {
+ password = curmd->value;
+ }
+ curmd = curmd->next;
+ }
+
+ if (siteurl == NULL) {
+ return fetch_about_srverror(ctx);
+ }
+
+ /* content is going to return ok */
+ fetch_about_set_http_code(ctx, 200);
+
+ /* content type */
+ if (fetch_about_send_header(ctx, "Content-Type: text/html; charset=utf-8")) {
+ goto fetch_about_query_auth_handler_aborted;
+ }
+
+ title = messages_get("LoginTitle");
+ res = fetch_about_ssenddataf(ctx,
+ "<html>\n<head>\n"
+ "<title>%s</title>\n"
+ "<link rel=\"stylesheet\" type=\"text/css\" "
+ "href=\"resource:internal.css\">\n"
+ "</head>\n"
+ "<body class=\"ns-even-bg ns-even-fg ns-border\" id =\"authentication\">\n"
+ "<h1 class=\"ns-border\">%s</h1>\n",
+ title, title);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_auth_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "<form method=\"post\""
+ " enctype=\"multipart/form-data\">");
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_auth_handler_aborted;
+ }
+
+ res = get_authentication_description(siteurl,
+ realm,
+ username,
+ password,
+ &description);
+ if (res == NSERROR_OK) {
+ res = fetch_about_ssenddataf(ctx, "<p>%s</p>", description);
+ free(description);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_auth_handler_aborted;
+ }
+ }
+
+ res = fetch_about_ssenddataf(ctx, "<table>");
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_auth_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "<tr>"
+ "<th><label for=\"name\">%s:</label></th>"
+ "<td><input type=\"text\" id=\"username\" "
+ "name=\"username\" value=\"%s\"></td>"
+ "</tr>",
+ messages_get("Username"), username);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_auth_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "<tr>"
+ "<th><label for=\"password\">%s:</label></th>"
+ "<td><input type=\"password\" id=\"password\" "
+ "name=\"password\" value=\"%s\"></td>"
+ "</tr>",
+ messages_get("Password"), password);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_auth_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx, "</table>");
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_auth_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "<div id=\"buttons\">"
+ "<input type=\"submit\" id=\"login\" name=\"login\" "
+ "value=\"%s\" class=\"default-action\">"
+ "<input type=\"submit\" id=\"cancel\" name=\"cancel\" "
+ "value=\"%s\">"
+ "</div>",
+ messages_get("Login"),
+ messages_get("Cancel"));
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_auth_handler_aborted;
+ }
+
+ res = nsurl_get(siteurl, NSURL_COMPLETE, &url_s, &url_l);
+ if (res != NSERROR_OK) {
+ url_s = strdup("");
+ }
+ res = fetch_about_ssenddataf(ctx,
+ "<input type=\"hidden\" name=\"siteurl\" value=\"%s\">",
+ url_s);
+ free(url_s);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_auth_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "<input type=\"hidden\" name=\"realm\" value=\"%s\">",
+ realm);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_auth_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx, "</form></body>\n</html>\n");
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_auth_handler_aborted;
+ }
+
+ fetch_about_send_finished(ctx);
+
+ nsurl_unref(siteurl);
+
+ return true;
+
+fetch_about_query_auth_handler_aborted:
+
+ nsurl_unref(siteurl);
+
+ return false;
+}
diff --git a/content/fetchers/about/query_auth.h b/content/fetchers/about/query_auth.h
new file mode 100644
index 000000000..1c7f658e1
--- /dev/null
+++ b/content/fetchers/about/query_auth.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * about scheme query auth handler interface
+ */
+
+#ifndef NETSURF_CONTENT_FETCHERS_ABOUT_QUERY_AUTH_H
+#define NETSURF_CONTENT_FETCHERS_ABOUT_QUERY_AUTH_H
+
+/**
+ * Handler to generate about scheme query auth page.
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_query_auth_handler(struct fetch_about_context *ctx);
+
+#endif
diff --git a/content/fetchers/about/query_fetcherror.c b/content/fetchers/about/query_fetcherror.c
new file mode 100644
index 000000000..010a597e4
--- /dev/null
+++ b/content/fetchers/about/query_fetcherror.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * content generator for the about scheme query privacy page
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "utils/errors.h"
+#include "utils/messages.h"
+#include "content/fetch.h"
+
+#include "private.h"
+#include "query.h"
+#include "query_fetcherror.h"
+
+/**
+ * Handler to generate about scheme fetch error query page
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_query_fetcherror_handler(struct fetch_about_context *ctx)
+{
+ nserror res;
+ char *url_s;
+ size_t url_l;
+ const char *reason = "";
+ const char *title;
+ struct nsurl *siteurl = NULL;
+ char *description = NULL;
+ const struct fetch_multipart_data *curmd; /* mutipart data iterator */
+
+ /* extract parameters from multipart post data */
+ curmd = fetch_about_get_multipart(ctx);
+ while (curmd != NULL) {
+ if (strcmp(curmd->name, "siteurl") == 0) {
+ res = nsurl_create(curmd->value, &siteurl);
+ if (res != NSERROR_OK) {
+ return fetch_about_srverror(ctx);
+ }
+ } else if (strcmp(curmd->name, "reason") == 0) {
+ reason = curmd->value;
+ }
+ curmd = curmd->next;
+ }
+
+ if (siteurl == NULL) {
+ return fetch_about_srverror(ctx);
+ }
+
+ /* content is going to return ok */
+ fetch_about_set_http_code(ctx, 200);
+
+ /* content type */
+ if (fetch_about_send_header(ctx, "Content-Type: text/html; charset=utf-8")) {
+ goto fetch_about_query_fetcherror_handler_aborted;
+ }
+
+ title = messages_get("FetchErrorTitle");
+ res = fetch_about_ssenddataf(ctx,
+ "<html>\n<head>\n"
+ "<title>%s</title>\n"
+ "<link rel=\"stylesheet\" type=\"text/css\" "
+ "href=\"resource:internal.css\">\n"
+ "</head>\n"
+ "<body class=\"ns-even-bg ns-even-fg ns-border\" id =\"fetcherror\">\n"
+ "<h1 class=\"ns-border ns-odd-fg-bad\">%s</h1>\n",
+ title, title);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_fetcherror_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "<form method=\"post\""
+ " enctype=\"multipart/form-data\">");
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_fetcherror_handler_aborted;
+ }
+
+ res = get_query_description(siteurl,
+ "FetchErrorDescription",
+ &description);
+ if (res == NSERROR_OK) {
+ res = fetch_about_ssenddataf(ctx, "<div><p>%s</p></div>", description);
+ free(description);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_fetcherror_handler_aborted;
+ }
+ }
+ res = fetch_about_ssenddataf(ctx, "<div><p>%s</p></div>", reason);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_fetcherror_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "<div id=\"buttons\">"
+ "<input type=\"submit\" id=\"back\" name=\"back\" "
+ "value=\"%s\" class=\"default-action\">"
+ "<input type=\"submit\" id=\"retry\" name=\"retry\" "
+ "value=\"%s\">"
+ "</div>",
+ messages_get("Backtoprevious"),
+ messages_get("TryAgain"));
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_fetcherror_handler_aborted;
+ }
+
+ res = nsurl_get(siteurl, NSURL_COMPLETE, &url_s, &url_l);
+ if (res != NSERROR_OK) {
+ url_s = strdup("");
+ }
+ res = fetch_about_ssenddataf(ctx,
+ "<input type=\"hidden\" name=\"siteurl\" value=\"%s\">",
+ url_s);
+ free(url_s);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_fetcherror_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx, "</form></body>\n</html>\n");
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_fetcherror_handler_aborted;
+ }
+
+ fetch_about_send_finished(ctx);
+
+ nsurl_unref(siteurl);
+
+ return true;
+
+fetch_about_query_fetcherror_handler_aborted:
+ nsurl_unref(siteurl);
+
+ return false;
+}
diff --git a/content/fetchers/about/query_fetcherror.h b/content/fetchers/about/query_fetcherror.h
new file mode 100644
index 000000000..85d972f8e
--- /dev/null
+++ b/content/fetchers/about/query_fetcherror.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * about scheme query fetch error handler interface
+ */
+
+#ifndef NETSURF_CONTENT_FETCHERS_ABOUT_QUERY_FETCHERROR_H
+#define NETSURF_CONTENT_FETCHERS_ABOUT_QUERY_FETCHERROR_H
+
+/**
+ * Handler to generate about scheme fetch error query page
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_query_fetcherror_handler(struct fetch_about_context *ctx);
+
+#endif
diff --git a/content/fetchers/about/query_privacy.c b/content/fetchers/about/query_privacy.c
new file mode 100644
index 000000000..030672bab
--- /dev/null
+++ b/content/fetchers/about/query_privacy.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * content generator for the about scheme query privacy page
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "utils/errors.h"
+#include "utils/messages.h"
+#include "content/fetch.h"
+
+#include "private.h"
+#include "query.h"
+#include "query_privacy.h"
+
+/**
+ * Handler to generate about scheme privacy query page
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_query_privacy_handler(struct fetch_about_context *ctx)
+{
+ nserror res;
+ char *url_s;
+ size_t url_l;
+ const char *reason = "";
+ const char *title;
+ struct nsurl *siteurl = NULL;
+ char *description = NULL;
+ const char *chainurl = NULL;
+ const struct fetch_multipart_data *curmd; /* mutipart data iterator */
+
+ /* extract parameters from multipart post data */
+ curmd = fetch_about_get_multipart(ctx);
+ while (curmd != NULL) {
+ if (strcmp(curmd->name, "siteurl") == 0) {
+ res = nsurl_create(curmd->value, &siteurl);
+ if (res != NSERROR_OK) {
+ return fetch_about_srverror(ctx);
+ }
+ } else if (strcmp(curmd->name, "reason") == 0) {
+ reason = curmd->value;
+ } else if (strcmp(curmd->name, "chainurl") == 0) {
+ chainurl = curmd->value;
+ }
+ curmd = curmd->next;
+ }
+
+ if (siteurl == NULL) {
+ return fetch_about_srverror(ctx);
+ }
+
+ /* content is going to return ok */
+ fetch_about_set_http_code(ctx, 200);
+
+ /* content type */
+ if (fetch_about_send_header(ctx, "Content-Type: text/html; charset=utf-8")) {
+ goto fetch_about_query_ssl_handler_aborted;
+ }
+
+ title = messages_get("PrivacyTitle");
+ res = fetch_about_ssenddataf(ctx,
+ "<html>\n<head>\n"
+ "<title>%s</title>\n"
+ "<link rel=\"stylesheet\" type=\"text/css\" "
+ "href=\"resource:internal.css\">\n"
+ "</head>\n"
+ "<body class=\"ns-even-bg ns-even-fg ns-border\" id =\"privacy\">\n"
+ "<h1 class=\"ns-border ns-odd-fg-bad\">%s</h1>\n",
+ title, title);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_ssl_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "<form method=\"post\""
+ " enctype=\"multipart/form-data\">");
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_ssl_handler_aborted;
+ }
+
+ res = get_query_description(siteurl,
+ "PrivacyDescription",
+ &description);
+ if (res == NSERROR_OK) {
+ res = fetch_about_ssenddataf(ctx, "<div><p>%s</p></div>", description);
+ free(description);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_ssl_handler_aborted;
+ }
+ }
+
+ if (chainurl == NULL) {
+ res = fetch_about_ssenddataf(ctx,
+ "<div><p>%s</p></div>"
+ "<div><p>%s</p></div>",
+ reason,
+ messages_get("ViewCertificatesNotPossible"));
+ } else {
+ res = fetch_about_ssenddataf(ctx,
+ "<div><p>%s</p></div>"
+ "<div><p><a href=\"%s\" target=\"_blank\">%s</a></p></div>",
+ reason,
+ chainurl,
+ messages_get("ViewCertificates"));
+ }
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_ssl_handler_aborted;
+ }
+ res = fetch_about_ssenddataf(ctx,
+ "<div id=\"buttons\">"
+ "<input type=\"submit\" id=\"back\" name=\"back\" "
+ "value=\"%s\" class=\"default-action\">"
+ "<input type=\"submit\" id=\"proceed\" name=\"proceed\" "
+ "value=\"%s\">"
+ "</div>",
+ messages_get("Backtosafety"),
+ messages_get("Proceed"));
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_ssl_handler_aborted;
+ }
+
+ res = nsurl_get(siteurl, NSURL_COMPLETE, &url_s, &url_l);
+ if (res != NSERROR_OK) {
+ url_s = strdup("");
+ }
+ res = fetch_about_ssenddataf(ctx,
+ "<input type=\"hidden\" name=\"siteurl\" value=\"%s\">",
+ url_s);
+ free(url_s);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_ssl_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx, "</form></body>\n</html>\n");
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_ssl_handler_aborted;
+ }
+
+ fetch_about_send_finished(ctx);
+
+ nsurl_unref(siteurl);
+
+ return true;
+
+fetch_about_query_ssl_handler_aborted:
+ nsurl_unref(siteurl);
+
+ return false;
+}
diff --git a/content/fetchers/about/query_privacy.h b/content/fetchers/about/query_privacy.h
new file mode 100644
index 000000000..38ddbe889
--- /dev/null
+++ b/content/fetchers/about/query_privacy.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * about scheme query privacy handler interface
+ */
+
+#ifndef NETSURF_CONTENT_FETCHERS_ABOUT_QUERY_PRIVACY_H
+#define NETSURF_CONTENT_FETCHERS_ABOUT_QUERY_PRIVACY_H
+
+/**
+ * Handler to generate about scheme query privacy page.
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_query_privacy_handler(struct fetch_about_context *ctx);
+
+#endif
diff --git a/content/fetchers/about/query_timeout.c b/content/fetchers/about/query_timeout.c
new file mode 100644
index 000000000..5c014bc9b
--- /dev/null
+++ b/content/fetchers/about/query_timeout.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * content generator for the about scheme query timeout page
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "utils/errors.h"
+#include "utils/messages.h"
+#include "content/fetch.h"
+
+#include "private.h"
+#include "query.h"
+#include "query_timeout.h"
+
+/**
+ * Handler to generate about scheme timeout query page
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_query_timeout_handler(struct fetch_about_context *ctx)
+{
+ nserror res;
+ char *url_s;
+ size_t url_l;
+ const char *reason = "";
+ const char *title;
+ struct nsurl *siteurl = NULL;
+ char *description = NULL;
+ const struct fetch_multipart_data *curmd; /* mutipart data iterator */
+
+ /* extract parameters from multipart post data */
+ curmd = fetch_about_get_multipart(ctx);
+ while (curmd != NULL) {
+ if (strcmp(curmd->name, "siteurl") == 0) {
+ res = nsurl_create(curmd->value, &siteurl);
+ if (res != NSERROR_OK) {
+ return fetch_about_srverror(ctx);
+ }
+ } else if (strcmp(curmd->name, "reason") == 0) {
+ reason = curmd->value;
+ }
+ curmd = curmd->next;
+ }
+
+ if (siteurl == NULL) {
+ return fetch_about_srverror(ctx);
+ }
+
+ /* content is going to return ok */
+ fetch_about_set_http_code(ctx, 200);
+
+ /* content type */
+ if (fetch_about_send_header(ctx, "Content-Type: text/html; charset=utf-8")) {
+ goto fetch_about_query_timeout_handler_aborted;
+ }
+
+ title = messages_get("TimeoutTitle");
+ res = fetch_about_ssenddataf(ctx,
+ "<html>\n<head>\n"
+ "<title>%s</title>\n"
+ "<link rel=\"stylesheet\" type=\"text/css\" "
+ "href=\"resource:internal.css\">\n"
+ "</head>\n"
+ "<body class=\"ns-even-bg ns-even-fg ns-border\" id =\"timeout\">\n"
+ "<h1 class=\"ns-border ns-odd-fg-bad\">%s</h1>\n",
+ title, title);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_timeout_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "<form method=\"post\""
+ " enctype=\"multipart/form-data\">");
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_timeout_handler_aborted;
+ }
+
+ res = get_query_description(siteurl,
+ "TimeoutDescription",
+ &description);
+ if (res == NSERROR_OK) {
+ res = fetch_about_ssenddataf(ctx, "<div><p>%s</p></div>", description);
+ free(description);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_timeout_handler_aborted;
+ }
+ }
+ res = fetch_about_ssenddataf(ctx, "<div><p>%s</p></div>", reason);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_timeout_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "<div id=\"buttons\">"
+ "<input type=\"submit\" id=\"back\" name=\"back\" "
+ "value=\"%s\" class=\"default-action\">"
+ "<input type=\"submit\" id=\"retry\" name=\"retry\" "
+ "value=\"%s\">"
+ "</div>",
+ messages_get("Backtoprevious"),
+ messages_get("TryAgain"));
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_timeout_handler_aborted;
+ }
+
+ res = nsurl_get(siteurl, NSURL_COMPLETE, &url_s, &url_l);
+ if (res != NSERROR_OK) {
+ url_s = strdup("");
+ }
+ res = fetch_about_ssenddataf(ctx,
+ "<input type=\"hidden\" name=\"siteurl\" value=\"%s\">",
+ url_s);
+ free(url_s);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_timeout_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx, "</form></body>\n</html>\n");
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_timeout_handler_aborted;
+ }
+
+ fetch_about_send_finished(ctx);
+
+ nsurl_unref(siteurl);
+
+ return true;
+
+fetch_about_query_timeout_handler_aborted:
+ nsurl_unref(siteurl);
+
+ return false;
+}
diff --git a/content/fetchers/about/query_timeout.h b/content/fetchers/about/query_timeout.h
new file mode 100644
index 000000000..a64757f21
--- /dev/null
+++ b/content/fetchers/about/query_timeout.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * about scheme query timeout handler interface
+ */
+
+#ifndef NETSURF_CONTENT_FETCHERS_ABOUT_QUERY_TIMEOUT_H
+#define NETSURF_CONTENT_FETCHERS_ABOUT_QUERY_TIMEOUT_H
+
+/**
+ * Handler to generate about scheme timeout query page
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_query_timeout_handler(struct fetch_about_context *ctx);
+
+#endif
diff --git a/content/fetchers/about/testament.c b/content/fetchers/about/testament.c
new file mode 100644
index 000000000..ae992ec52
--- /dev/null
+++ b/content/fetchers/about/testament.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf.
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * content generator for the about scheme testament page
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#include "utils/errors.h"
+#include "netsurf/inttypes.h"
+#include "testament.h"
+
+#include "private.h"
+#include "atestament.h"
+
+typedef struct {
+ const char *leaf;
+ const char *modtype;
+} modification_t;
+
+/**
+ * Generate the text of an svn testament which represents the current
+ * build-tree status
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+bool fetch_about_testament_handler(struct fetch_about_context *ctx)
+{
+ nserror res;
+ static modification_t modifications[] = WT_MODIFICATIONS;
+ int modidx; /* midification index */
+
+ /* content is going to return ok */
+ fetch_about_set_http_code(ctx, 200);
+
+ /* content type */
+ if (fetch_about_send_header(ctx, "Content-Type: text/plain"))
+ goto fetch_about_testament_handler_aborted;
+
+ res = fetch_about_ssenddataf(ctx,
+ "# Automatically generated by NetSurf build system\n\n");
+ if (res != NSERROR_OK) {
+ goto fetch_about_testament_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+#if defined(WT_BRANCHISTRUNK) || defined(WT_BRANCHISMASTER)
+ "# This is a *DEVELOPMENT* build from the main line.\n\n"
+#elif defined(WT_BRANCHISTAG) && (WT_MODIFIED == 0)
+ "# This is a tagged build of NetSurf\n"
+#ifdef WT_TAGIS
+ "# The tag used was '" WT_TAGIS "'\n\n"
+#else
+ "\n"
+#endif
+#elif defined(WT_NO_SVN) || defined(WT_NO_GIT)
+ "# This NetSurf was built outside of our revision "
+ "control environment.\n"
+ "# This testament is therefore not very useful.\n\n"
+#else
+ "# This NetSurf was built from a branch (" WT_BRANCHPATH ").\n\n"
+#endif
+#if defined(CI_BUILD)
+ "# This build carries the CI build number '" CI_BUILD "'\n\n"
+#endif
+ );
+ if (res != NSERROR_OK) {
+ goto fetch_about_testament_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx,
+ "Built by %s (%s) from %s at revision %s on %s\n\n",
+ GECOS, USERNAME, WT_BRANCHPATH, WT_REVID, WT_COMPILEDATE);
+ if (res != NSERROR_OK) {
+ goto fetch_about_testament_handler_aborted;
+ }
+
+ res = fetch_about_ssenddataf(ctx, "Built on %s in %s\n\n", WT_HOSTNAME, WT_ROOT);
+ if (res != NSERROR_OK) {
+ goto fetch_about_testament_handler_aborted;
+ }
+
+ if (WT_MODIFIED > 0) {
+ res = fetch_about_ssenddataf(ctx,
+ "Working tree has %d modification%s\n\n",
+ WT_MODIFIED, WT_MODIFIED == 1 ? "" : "s");
+ } else {
+ res = fetch_about_ssenddataf(ctx, "Working tree is not modified.\n");
+ }
+ if (res != NSERROR_OK) {
+ goto fetch_about_testament_handler_aborted;
+ }
+
+ for (modidx = 0; modidx < WT_MODIFIED; ++modidx) {
+ res = fetch_about_ssenddataf(ctx,
+ " %s %s\n",
+ modifications[modidx].modtype,
+ modifications[modidx].leaf);
+ if (res != NSERROR_OK) {
+ goto fetch_about_testament_handler_aborted;
+ }
+ }
+
+ fetch_about_send_finished(ctx);
+
+ return true;
+
+fetch_about_testament_handler_aborted:
+ return false;
+}
diff --git a/content/fetchers/curl.c b/content/fetchers/curl.c
index bf9d88bc1..680e60456 100644
--- a/content/fetchers/curl.c
+++ b/content/fetchers/curl.c
@@ -1,7 +1,7 @@
/*
- * Copyright 2006 Daniel Silverstone <dsilvers@digital-scurf.org>
+ * Copyright 2006-2019 Daniel Silverstone <dsilvers@digital-scurf.org>
+ * Copyright 2010-2018 Vincent Sanders <vince@netsurf-browser.org>
* Copyright 2007 James Bursa <bursa@users.sourceforge.net>
- * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
*
* This file is part of NetSurf.
*
@@ -38,12 +38,12 @@
#include <strings.h>
#include <time.h>
#include <sys/stat.h>
-#include <openssl/ssl.h>
#include <libwapcaplet/libwapcaplet.h>
#include <nsutils/time.h>
#include "utils/corestrings.h"
+#include "utils/hashmap.h"
#include "utils/nsoption.h"
#include "utils/log.h"
#include "utils/messages.h"
@@ -61,26 +61,149 @@
#include "content/fetchers/curl.h"
#include "content/urldb.h"
-/** maximum number of progress notifications per second */
+/**
+ * maximum number of progress notifications per second
+ */
#define UPDATES_PER_SECOND 2
-/** maximum number of X509 certificates in chain for TLS connection */
-#define MAX_CERTS 10
+/**
+ * The ciphersuites the browser is prepared to use for TLS1.3
+ */
+#define CIPHER_SUITES \
+ "TLS_AES_256_GCM_SHA384:" \
+ "TLS_CHACHA20_POLY1305_SHA256:" \
+ "TLS_AES_128_GCM_SHA256"
-/* the ciphersuites we are willing to use */
+/**
+ * The ciphersuites the browser is prepared to use for TLS<1.3
+ */
#define CIPHER_LIST \
/* disable everything */ \
"-ALL:" \
- /* enable TLSv1.2 PFS suites */ \
- "EECDH+AES+TLSv1.2:EDH+AES+TLSv1.2:" \
- /* enable PFS AES GCM suites */ \
- "EECDH+AESGCM:EDH+AESGCM:" \
- /* Enable PFS AES CBC suites */ \
- "EECDH+AES:EDH+AES:" \
- /* Enable non-PFS fallback suite */ \
- "AES128-SHA:" \
- /* Remove any PFS suites using weak DSA key exchange */ \
- "-DSS"
+ /* enable TLSv1.2 ECDHE AES GCM suites */ \
+ "EECDH+AESGCM+TLSv1.2:" \
+ /* enable ECDHE CHACHA20/POLY1305 suites */ \
+ "EECDH+CHACHA20:" \
+ /* Sort above by strength */ \
+ "@STRENGTH:" \
+ /* enable ECDHE (auth=RSA, mac=SHA1) AES CBC suites */ \
+ "EECDH+aRSA+AES+SHA1"
+
+/**
+ * The legacy cipher suites the browser is prepared to use for TLS<1.3
+ */
+#define CIPHER_LIST_LEGACY \
+ /* as above */ \
+ CIPHER_LIST":" \
+ /* enable (non-PFS) RSA AES GCM suites */ \
+ "RSA+AESGCM:" \
+ /* enable (non-PFS) RSA (mac=SHA1) AES CBC suites */ \
+ "RSA+AES+SHA1"
+
+/* Open SSL compatability for certificate handling */
+#ifdef WITH_OPENSSL
+
+#include <openssl/ssl.h>
+#include <openssl/x509v3.h>
+
+#else /* WITH_OPENSSL */
+
+typedef char X509;
+
+static void X509_free(X509 *cert)
+{
+ free(cert);
+}
+
+#endif /* WITH_OPENSSL */
+
+/* SSL certificate chain cache */
+
+/* We're only interested in the hostname and port */
+static uint32_t
+curl_fetch_ssl_key_hash(void *key)
+{
+ nsurl *url = key;
+ lwc_string *hostname = nsurl_get_component(url, NSURL_HOST);
+ lwc_string *port = nsurl_get_component(url, NSURL_PORT);
+ uint32_t hash;
+
+ if (port == NULL)
+ port = lwc_string_ref(corestring_lwc_443);
+
+ hash = lwc_string_hash_value(hostname) ^ lwc_string_hash_value(port);
+
+ lwc_string_unref(hostname);
+ lwc_string_unref(port);
+
+ return hash;
+}
+
+/* We only compare the hostname and port */
+static bool
+curl_fetch_ssl_key_eq(void *key1, void *key2)
+{
+ nsurl *url1 = key1;
+ nsurl *url2 = key2;
+ lwc_string *hostname1 = nsurl_get_component(url1, NSURL_HOST);
+ lwc_string *hostname2 = nsurl_get_component(url2, NSURL_HOST);
+ lwc_string *port1 = nsurl_get_component(url1, NSURL_PORT);
+ lwc_string *port2 = nsurl_get_component(url2, NSURL_PORT);
+ bool iseq = false;
+
+ if (port1 == NULL)
+ port1 = lwc_string_ref(corestring_lwc_443);
+ if (port2 == NULL)
+ port2 = lwc_string_ref(corestring_lwc_443);
+
+ if (lwc_string_isequal(hostname1, hostname2, &iseq) != lwc_error_ok ||
+ iseq == false)
+ goto out;
+
+ iseq = false;
+ if (lwc_string_isequal(port1, port2, &iseq) != lwc_error_ok)
+ goto out;
+
+out:
+ lwc_string_unref(hostname1);
+ lwc_string_unref(hostname2);
+ lwc_string_unref(port1);
+ lwc_string_unref(port2);
+
+ return iseq;
+}
+
+static void *
+curl_fetch_ssl_value_alloc(void *key)
+{
+ struct cert_chain *out;
+
+ if (cert_chain_alloc(0, &out) != NSERROR_OK) {
+ return NULL;
+ }
+
+ return out;
+}
+
+static void
+curl_fetch_ssl_value_destroy(void *value)
+{
+ struct cert_chain *chain = value;
+ if (cert_chain_free(chain) != NSERROR_OK) {
+ NSLOG(netsurf, WARNING, "Problem freeing SSL certificate chain");
+ }
+}
+
+static hashmap_parameters_t curl_fetch_ssl_hashmap_parameters = {
+ .key_clone = (hashmap_key_clone_t)nsurl_ref,
+ .key_destroy = (hashmap_key_destroy_t)nsurl_unref,
+ .key_eq = curl_fetch_ssl_key_eq,
+ .key_hash = curl_fetch_ssl_key_hash,
+ .value_alloc = curl_fetch_ssl_value_alloc,
+ .value_destroy = curl_fetch_ssl_value_destroy,
+};
+
+static hashmap_t *curl_fetch_ssl_hashmap = NULL;
/** SSL certificate info */
struct cert_info {
@@ -88,15 +211,36 @@ struct cert_info {
long err; /**< OpenSSL error code */
};
+#if LIBCURL_VERSION_NUM >= 0x072000 /* 7.32.0 depricated CURLOPT_PROGRESSFUNCTION*/
+#define NSCURLOPT_PROGRESS_FUNCTION CURLOPT_XFERINFOFUNCTION
+#define NSCURLOPT_PROGRESS_DATA CURLOPT_XFERINFODATA
+#define NSCURL_PROGRESS_T curl_off_t
+#else
+#define NSCURLOPT_PROGRESS_FUNCTION CURLOPT_PROGRESSFUNCTION
+#define NSCURLOPT_PROGRESS_DATA CURLOPT_PROGRESSDATA
+#define NSCURL_PROGRESS_T double
+#endif
+
+#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 depricated curl_formadd */
+#define NSCURL_POSTDATA_T curl_mime
+#define NSCURL_POSTDATA_CURLOPT CURLOPT_MIMEPOST
+#define NSCURL_POSTDATA_FREE(x) curl_mime_free(x)
+#else
+#define NSCURL_POSTDATA_T struct curl_httppost
+#define NSCURL_POSTDATA_CURLOPT CURLOPT_HTTPPOST
+#define NSCURL_POSTDATA_FREE(x) curl_formfree(x)
+#endif
+
/** Information for a single fetch. */
struct curl_fetch_info {
struct fetch *fetch_handle; /**< The fetch handle we're parented by. */
CURL * curl_handle; /**< cURL handle if being fetched, or 0. */
+ bool sent_ssl_chain; /**< Have we tried to send the SSL chain */
bool had_headers; /**< Headers have been processed. */
bool abort; /**< Abort requested. */
bool stopped; /**< Download stopped on purpose. */
bool only_2xx; /**< Only HTTP 2xx responses acceptable. */
- bool downgrade_tls; /**< Downgrade to TLS <= 1.0 */
+ bool downgrade_tls; /**< Downgrade to TLS 1.2 */
nsurl *url; /**< URL of this fetch. */
lwc_string *host; /**< The hostname of this fetch. */
struct curl_slist *headers; /**< List of request headers. */
@@ -104,12 +248,14 @@ struct curl_fetch_info {
unsigned long content_length; /**< Response Content-Length, or 0. */
char *cookie_string; /**< Cookie string for this fetch */
char *realm; /**< HTTP Auth Realm */
- char *post_urlenc; /**< Url encoded POST string, or 0. */
+ struct fetch_postdata *postdata; /**< POST data */
+ NSCURL_POSTDATA_T *curl_postdata; /**< POST data in curl representation */
+
long http_code; /**< HTTP result code from cURL. */
- struct curl_httppost *post_multipart; /**< Multipart post data, or 0. */
+
uint64_t last_progress_update; /**< Time of last progress update */
int cert_depth; /**< deepest certificate in use */
- struct cert_info cert_data[MAX_CERTS]; /**< HTTPS certificate data */
+ struct cert_info cert_data[MAX_CERT_DEPTH]; /**< HTTPS certificate data */
};
/** curl handle cache entry */
@@ -142,28 +288,9 @@ static char fetch_error_buffer[CURL_ERROR_SIZE];
/** Proxy authentication details. */
static char fetch_proxy_userpwd[100];
+/** Interlock to prevent initiation during callbacks */
+static bool inside_curl = false;
-/* OpenSSL 1.0.x to 1.1.0 certificate reference counting changed
- * LibreSSL declares its OpenSSL version as 2.1 but only supports the old way
- */
-#if (defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x1010000fL))
-static int ns_X509_up_ref(X509 *cert)
-{
- cert->references++;
- return 1;
-}
-
-static void ns_X509_free(X509 *cert)
-{
- cert->references--;
- if (cert->references == 0) {
- X509_free(cert);
- }
-}
-#else
-#define ns_X509_up_ref X509_up_ref
-#define ns_X509_free X509_free
-#endif
/**
* Initialise a cURL fetcher.
@@ -203,6 +330,10 @@ static void fetch_curl_finalise(lwc_string *scheme)
"curl_multi_cleanup failed: ignoring");
curl_global_cleanup();
+
+ NSLOG(netsurf, DEBUG, "Cleaning up SSL cert chain hashmap");
+ hashmap_destroy(curl_fetch_ssl_hashmap);
+ curl_fetch_ssl_hashmap = NULL;
}
/* Free anything remaining in the cached curl handle ring */
@@ -228,85 +359,95 @@ static bool fetch_curl_can_fetch(const nsurl *url)
}
+
/**
- * Convert a list of struct ::fetch_multipart_data to a list of
- * struct curl_httppost for libcurl.
+ * allocate postdata
*/
-static struct curl_httppost *
-fetch_curl_post_convert(const struct fetch_multipart_data *control)
+static struct fetch_postdata *
+fetch_curl_alloc_postdata(const char *post_urlenc,
+ const struct fetch_multipart_data *post_multipart)
{
- struct curl_httppost *post = 0, *last = 0;
- CURLFORMcode code;
- nserror ret;
-
- for (; control; control = control->next) {
- if (control->file) {
- char *leafname = NULL;
- ret = guit->file->basename(control->value, &leafname, NULL);
- if (ret != NSERROR_OK) {
- continue;
+ struct fetch_postdata *postdata;
+ postdata = calloc(1, sizeof(struct fetch_postdata));
+ if (postdata != NULL) {
+
+ if (post_urlenc) {
+ postdata->type = FETCH_POSTDATA_URLENC;
+ postdata->data.urlenc = strdup(post_urlenc);
+ if (postdata->data.urlenc == NULL) {
+ free(postdata);
+ postdata = NULL;
}
-
- /* We have to special case filenames of "", so curl
- * a) actually attempts the fetch and
- * b) doesn't attempt to open the file ""
- */
- if (control->value[0] == '\0') {
- /* dummy buffer - needs to be static so
- * pointer's still valid when we go out
- * of scope (not that libcurl should be
- * attempting to access it, of course).
- */
- static char buf;
-
- code = curl_formadd(&post, &last,
- CURLFORM_COPYNAME, control->name,
- CURLFORM_BUFFER, control->value,
- /* needed, as basename("") == "." */
- CURLFORM_FILENAME, "",
- CURLFORM_BUFFERPTR, &buf,
- CURLFORM_BUFFERLENGTH, 0,
- CURLFORM_CONTENTTYPE,
- "application/octet-stream",
- CURLFORM_END);
- if (code != CURL_FORMADD_OK)
- NSLOG(netsurf, INFO,
- "curl_formadd: %d (%s)", code,
- control->name);
- } else {
- char *mimetype = guit->fetch->mimetype(control->value);
- code = curl_formadd(&post, &last,
- CURLFORM_COPYNAME, control->name,
- CURLFORM_FILE, control->rawfile,
- CURLFORM_FILENAME, leafname,
- CURLFORM_CONTENTTYPE,
- (mimetype != 0 ? mimetype : "text/plain"),
- CURLFORM_END);
- if (code != CURL_FORMADD_OK)
- NSLOG(netsurf, INFO,
- "curl_formadd: %d (%s=%s)",
- code,
- control->name,
- control->value);
- free(mimetype);
+ } else if (post_multipart) {
+ postdata->type = FETCH_POSTDATA_MULTIPART;
+ postdata->data.multipart = fetch_multipart_data_clone(post_multipart);
+ if (postdata->data.multipart == NULL) {
+ free(postdata);
+ postdata = NULL;
}
- free(leafname);
- }
- else {
- code = curl_formadd(&post, &last,
- CURLFORM_COPYNAME, control->name,
- CURLFORM_COPYCONTENTS, control->value,
- CURLFORM_END);
- if (code != CURL_FORMADD_OK)
- NSLOG(netsurf, INFO,
- "curl_formadd: %d (%s=%s)", code,
- control->name, control->value);
+ } else {
+ postdata->type = FETCH_POSTDATA_NONE;
}
}
+ return postdata;
+}
- return post;
+/**
+ * free postdata
+ */
+static void fetch_curl_free_postdata(struct fetch_postdata *postdata)
+{
+ if (postdata != NULL) {
+ switch (postdata->type) {
+ case FETCH_POSTDATA_NONE:
+ break;
+ case FETCH_POSTDATA_URLENC:
+ free(postdata->data.urlenc);
+ break;
+ case FETCH_POSTDATA_MULTIPART:
+ fetch_multipart_data_destroy(postdata->data.multipart);
+ break;
+ }
+
+ free(postdata);
+ }
}
+/**
+ *construct a new fetch structure
+ */
+static struct curl_fetch_info *fetch_alloc(void)
+{
+ struct curl_fetch_info *fetch;
+ fetch = malloc(sizeof (*fetch));
+ if (fetch == NULL)
+ return NULL;
+
+ fetch->curl_handle = NULL;
+ fetch->sent_ssl_chain = false;
+ fetch->had_headers = false;
+ fetch->abort = false;
+ fetch->stopped = false;
+ fetch->only_2xx = false;
+ fetch->downgrade_tls = false;
+ fetch->headers = NULL;
+ fetch->url = NULL;
+ fetch->host = NULL;
+ fetch->location = NULL;
+ fetch->content_length = 0;
+ fetch->http_code = 0;
+ fetch->cookie_string = NULL;
+ fetch->realm = NULL;
+ fetch->last_progress_update = 0;
+ fetch->postdata = NULL;
+ fetch->curl_postdata = NULL;
+
+ /* Clear certificate chain data */
+ memset(fetch->cert_data, 0, sizeof(fetch->cert_data));
+ fetch->cert_depth = -1;
+
+ return fetch;
+}
/**
* Start fetching data for the given URL.
@@ -342,45 +483,22 @@ fetch_curl_setup(struct fetch *parent_fetch,
struct curl_slist *slist;
int i;
- fetch = malloc(sizeof (*fetch));
+ fetch = fetch_alloc();
if (fetch == NULL)
- return 0;
-
- fetch->fetch_handle = parent_fetch;
+ return NULL;
NSLOG(netsurf, INFO, "fetch %p, url '%s'", fetch, nsurl_access(url));
- /* construct a new fetch structure */
- fetch->curl_handle = NULL;
- fetch->had_headers = false;
- fetch->abort = false;
- fetch->stopped = false;
fetch->only_2xx = only_2xx;
fetch->downgrade_tls = downgrade_tls;
- fetch->headers = NULL;
+ fetch->fetch_handle = parent_fetch;
fetch->url = nsurl_ref(url);
fetch->host = nsurl_get_component(url, NSURL_HOST);
- fetch->location = NULL;
- fetch->content_length = 0;
- fetch->http_code = 0;
- fetch->cookie_string = NULL;
- fetch->realm = NULL;
- fetch->post_urlenc = NULL;
- fetch->post_multipart = NULL;
- if (post_urlenc) {
- fetch->post_urlenc = strdup(post_urlenc);
- } else if (post_multipart) {
- fetch->post_multipart = fetch_curl_post_convert(post_multipart);
+ if (fetch->host == NULL) {
+ goto failed;
}
- fetch->last_progress_update = 0;
-
- /* TLS defaults */
- memset(fetch->cert_data, 0, sizeof(fetch->cert_data));
- fetch->cert_depth = -1;
-
- if ((fetch->host == NULL) ||
- (post_multipart != NULL && fetch->post_multipart == NULL) ||
- (post_urlenc != NULL && fetch->post_urlenc == NULL)) {
+ fetch->postdata = fetch_curl_alloc_postdata(post_urlenc, post_multipart);
+ if (fetch->postdata == NULL) {
goto failed;
}
@@ -433,15 +551,141 @@ failed:
lwc_string_unref(fetch->host);
nsurl_unref(fetch->url);
- free(fetch->post_urlenc);
- if (fetch->post_multipart)
- curl_formfree(fetch->post_multipart);
+ fetch_curl_free_postdata(fetch->postdata);
curl_slist_free_all(fetch->headers);
free(fetch);
return NULL;
}
+#ifdef WITH_OPENSSL
+
+/**
+ * Retrieve the ssl cert chain for the fetch, creating a blank one if needed
+ */
+static struct cert_chain *
+fetch_curl_get_cached_chain(struct curl_fetch_info *f)
+{
+ struct cert_chain *chain;
+
+ chain = hashmap_lookup(curl_fetch_ssl_hashmap, f->url);
+ if (chain == NULL) {
+ chain = hashmap_insert(curl_fetch_ssl_hashmap, f->url);
+ }
+
+ return chain;
+}
+
+/**
+ * Report the certificate information in the fetch to the users
+ */
+static void
+fetch_curl_store_certs_in_cache(struct curl_fetch_info *f)
+{
+ size_t depth;
+ BIO *mem;
+ BUF_MEM *buf[MAX_CERT_DEPTH];
+ struct cert_chain chain, *cached_chain;
+ struct cert_info *certs;
+
+ memset(&chain, 0, sizeof(chain));
+
+ certs = f->cert_data;
+ chain.depth = f->cert_depth + 1; /* 0 indexed certificate depth */
+
+ for (depth = 0; depth < chain.depth; depth++) {
+ if (certs[depth].cert == NULL) {
+ /* This certificate is missing, skip it */
+ chain.certs[depth].err = SSL_CERT_ERR_CERT_MISSING;
+ continue;
+ }
+
+ /* error code (if any) */
+ switch (certs[depth].err) {
+ case X509_V_OK:
+ chain.certs[depth].err = SSL_CERT_ERR_OK;
+ break;
+
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+ /* fallthrough */
+ case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
+ chain.certs[depth].err = SSL_CERT_ERR_BAD_ISSUER;
+ break;
+
+ case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
+ /* fallthrough */
+ case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
+ /* fallthrough */
+ case X509_V_ERR_CERT_SIGNATURE_FAILURE:
+ /* fallthrough */
+ case X509_V_ERR_CRL_SIGNATURE_FAILURE:
+ chain.certs[depth].err = SSL_CERT_ERR_BAD_SIG;
+ break;
+
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ /* fallthrough */
+ case X509_V_ERR_CRL_NOT_YET_VALID:
+ chain.certs[depth].err = SSL_CERT_ERR_TOO_YOUNG;
+ break;
+
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ /* fallthrough */
+ case X509_V_ERR_CRL_HAS_EXPIRED:
+ chain.certs[depth].err = SSL_CERT_ERR_TOO_OLD;
+ break;
+
+ case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+ chain.certs[depth].err = SSL_CERT_ERR_SELF_SIGNED;
+ break;
+
+ case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+ chain.certs[depth].err = SSL_CERT_ERR_CHAIN_SELF_SIGNED;
+ break;
+
+ case X509_V_ERR_CERT_REVOKED:
+ chain.certs[depth].err = SSL_CERT_ERR_REVOKED;
+ break;
+
+ case X509_V_ERR_HOSTNAME_MISMATCH:
+ chain.certs[depth].err = SSL_CERT_ERR_HOSTNAME_MISMATCH;
+ break;
+
+ default:
+ chain.certs[depth].err = SSL_CERT_ERR_UNKNOWN;
+ break;
+ }
+
+ /*
+ * get certificate in Distinguished Encoding Rules (DER) format.
+ */
+ mem = BIO_new(BIO_s_mem());
+ i2d_X509_bio(mem, certs[depth].cert);
+ BIO_get_mem_ptr(mem, &buf[depth]);
+ (void) BIO_set_close(mem, BIO_NOCLOSE);
+ BIO_free(mem);
+
+ chain.certs[depth].der = (uint8_t *)buf[depth]->data;
+ chain.certs[depth].der_length = buf[depth]->length;
+ }
+
+ /* Now dup that chain into the cache */
+ cached_chain = fetch_curl_get_cached_chain(f);
+ if (cert_chain_dup_into(&chain, cached_chain) != NSERROR_OK) {
+ /* Something went wrong storing the chain, give up */
+ hashmap_remove(curl_fetch_ssl_hashmap, f->url);
+ }
+
+ /* release the openssl memory buffer */
+ for (depth = 0; depth < chain.depth; depth++) {
+ if (chain.certs[depth].err == SSL_CERT_ERR_CERT_MISSING) {
+ continue;
+ }
+ if (buf[depth] != NULL) {
+ BUF_MEM_free(buf[depth]);
+ }
+ }
+}
+
/**
* OpenSSL Certificate verification callback
*
@@ -470,24 +714,24 @@ fetch_curl_verify_callback(int verify_ok, X509_STORE_CTX *x509_ctx)
depth = X509_STORE_CTX_get_error_depth(x509_ctx);
fetch = X509_STORE_CTX_get_app_data(x509_ctx);
- /* record the max depth */
- if (depth > fetch->cert_depth) {
- fetch->cert_depth = depth;
- }
-
/* certificate chain is excessively deep so fail verification */
- if (depth >= MAX_CERTS) {
+ if (depth >= MAX_CERT_DEPTH) {
X509_STORE_CTX_set_error(x509_ctx,
X509_V_ERR_CERT_CHAIN_TOO_LONG);
return 0;
}
+ /* record the max depth */
+ if (depth > fetch->cert_depth) {
+ fetch->cert_depth = depth;
+ }
+
/* save the certificate by incrementing the reference count and
* keeping a pointer.
*/
if (!fetch->cert_data[depth].cert) {
fetch->cert_data[depth].cert = X509_STORE_CTX_get_current_cert(x509_ctx);
- ns_X509_up_ref(fetch->cert_data[depth].cert);
+ X509_up_ref(fetch->cert_data[depth].cert);
fetch->cert_data[depth].err = X509_STORE_CTX_get_error(x509_ctx);
}
@@ -521,16 +765,30 @@ fetch_curl_verify_callback(int verify_ok, X509_STORE_CTX *x509_ctx)
*/
static int fetch_curl_cert_verify_callback(X509_STORE_CTX *x509_ctx, void *parm)
{
+ struct curl_fetch_info *f = (struct curl_fetch_info *) parm;
int ok;
+ X509_VERIFY_PARAM *vparam;
+
+ /* Configure the verification parameters to include hostname */
+ vparam = X509_STORE_CTX_get0_param(x509_ctx);
+ X509_VERIFY_PARAM_set_hostflags(vparam, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+
+ ok = X509_VERIFY_PARAM_set1_host(vparam,
+ lwc_string_data(f->host),
+ lwc_string_length(f->host));
/* Store fetch struct in context for verify callback */
- ok = X509_STORE_CTX_set_app_data(x509_ctx, parm);
+ if (ok) {
+ ok = X509_STORE_CTX_set_app_data(x509_ctx, parm);
+ }
/* verify the certificate chain using standard call */
if (ok) {
ok = X509_verify_cert(x509_ctx);
}
+ fetch_curl_store_certs_in_cache(f);
+
return ok;
}
@@ -548,7 +806,8 @@ fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx, void *parm)
{
struct curl_fetch_info *f = (struct curl_fetch_info *) parm;
SSL_CTX *sslctx = _sslctx;
- long options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
+ long options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
+ SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
/* set verify callback for each certificate in chain */
SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, fetch_curl_verify_callback);
@@ -559,19 +818,14 @@ fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx, void *parm)
parm);
if (f->downgrade_tls) {
- /* Disable TLS 1.1/1.2 if the server can't cope with them */
-#ifdef SSL_OP_NO_TLSv1_1
- options |= SSL_OP_NO_TLSv1_1;
-#endif
-#ifdef SSL_OP_NO_TLSv1_2
- options |= SSL_OP_NO_TLSv1_2;
+ /* Disable TLS 1.3 if the server can't cope with it */
+#ifdef SSL_OP_NO_TLSv1_3
+ options |= SSL_OP_NO_TLSv1_3;
#endif
#ifdef SSL_MODE_SEND_FALLBACK_SCSV
/* Ensure server rejects the connection if downgraded too far */
SSL_CTX_set_mode(sslctx, SSL_MODE_SEND_FALLBACK_SCSV);
#endif
- /* Disable TLS1.2 ciphersuites */
- SSL_CTX_set_cipher_list(sslctx, CIPHER_LIST ":-TLSv1.2");
}
SSL_CTX_set_options(sslctx, options);
@@ -584,6 +838,326 @@ fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx, void *parm)
}
+#endif /* WITH_OPENSSL */
+
+
+/**
+ * Report the certificate information in the fetch to the users
+ */
+static void
+fetch_curl_report_certs_upstream(struct curl_fetch_info *f)
+{
+ fetch_msg msg;
+ struct cert_chain *chain;
+
+ chain = hashmap_lookup(curl_fetch_ssl_hashmap, f->url);
+
+ if (chain != NULL) {
+ msg.type = FETCH_CERTS;
+ msg.data.chain = chain;
+
+ fetch_send_callback(&msg, f->fetch_handle);
+ }
+
+ f->sent_ssl_chain = true;
+}
+
+#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 depricated curl_formadd */
+
+/**
+ * curl mime data context
+ */
+struct curl_mime_ctx {
+ char *buffer;
+ curl_off_t size;
+ curl_off_t position;
+};
+
+static size_t mime_data_read_callback(char *buffer, size_t size, size_t nitems, void *arg)
+{
+ struct curl_mime_ctx *mctx = (struct curl_mime_ctx *) arg;
+ curl_off_t sz = mctx->size - mctx->position;
+
+ nitems *= size;
+ if(sz > (curl_off_t)nitems) {
+ sz = nitems;
+ }
+ if(sz) {
+ memcpy(buffer, mctx->buffer + mctx->position, sz);
+ }
+ mctx->position += sz;
+ return sz;
+}
+
+static int mime_data_seek_callback(void *arg, curl_off_t offset, int origin)
+{
+ struct curl_mime_ctx *mctx = (struct curl_mime_ctx *) arg;
+
+ switch(origin) {
+ case SEEK_END:
+ offset += mctx->size;
+ break;
+ case SEEK_CUR:
+ offset += mctx->position;
+ break;
+ }
+
+ if(offset < 0) {
+ return CURL_SEEKFUNC_FAIL;
+ }
+ mctx->position = offset;
+ return CURL_SEEKFUNC_OK;
+}
+
+static void mime_data_free_callback(void *arg)
+{
+ struct curl_mime_ctx *mctx = (struct curl_mime_ctx *) arg;
+ free(mctx);
+}
+
+/**
+ * Convert a POST data list to a libcurl curl_mime.
+ *
+ * \param chandle curl fetch handle.
+ * \param multipart limked list of struct ::fetch_multipart forming post data.
+ */
+static curl_mime *
+fetch_curl_postdata_convert(CURL *chandle,
+ const struct fetch_multipart_data *multipart)
+{
+ curl_mime *cmime;
+ curl_mimepart *part;
+ CURLcode code = CURLE_OK;
+ size_t value_len;
+
+ cmime = curl_mime_init(chandle);
+ if (cmime == NULL) {
+ NSLOG(netsurf, WARNING, "postdata conversion failed to curl mime context");
+ return NULL;
+ }
+
+ /* iterate post data */
+ for (; multipart != NULL; multipart = multipart->next) {
+ part = curl_mime_addpart(cmime);
+ if (part == NULL) {
+ goto convert_failed;
+ }
+
+ code = curl_mime_name(part, multipart->name);
+ if (code != CURLE_OK) {
+ goto convert_failed;
+ }
+
+ value_len = strlen(multipart->value);
+
+ if (multipart->file && value_len==0) {
+ /* file entries with no filename require special handling */
+ code=curl_mime_data(part, multipart->value, value_len);
+ if (code != CURLE_OK) {
+ goto convert_failed;
+ }
+
+ code = curl_mime_filename(part, "");
+ if (code != CURLE_OK) {
+ goto convert_failed;
+ }
+
+ code = curl_mime_type(part, "application/octet-stream");
+ if (code != CURLE_OK) {
+ goto convert_failed;
+ }
+
+ } else if(multipart->file) {
+ /* file entry */
+ nserror ret;
+ char *leafname = NULL;
+ char *mimetype = NULL;
+
+ code = curl_mime_filedata(part, multipart->rawfile);
+ if (code != CURLE_OK) {
+ goto convert_failed;
+ }
+
+ ret = guit->file->basename(multipart->value, &leafname, NULL);
+ if (ret != NSERROR_OK) {
+ goto convert_failed;
+ }
+ code = curl_mime_filename(part, leafname);
+ free(leafname);
+ if (code != CURLE_OK) {
+ goto convert_failed;
+ }
+
+ mimetype = guit->fetch->mimetype(multipart->value);
+ if (mimetype == NULL) {
+ mimetype=strdup("text/plain");
+ }
+ if (mimetype == NULL) {
+ goto convert_failed;
+ }
+ code = curl_mime_type(part, mimetype);
+ free(mimetype);
+ if (code != CURLE_OK) {
+ goto convert_failed;
+ }
+
+ } else {
+ /* make the curl mime reference the existing multipart
+ * data which requires use of a callback and context.
+ */
+ struct curl_mime_ctx *cb_ctx;
+ cb_ctx = malloc(sizeof(struct curl_mime_ctx));
+ if (cb_ctx == NULL) {
+ goto convert_failed;
+ }
+ cb_ctx->buffer = multipart->value;
+ cb_ctx->size = value_len;
+ cb_ctx->position = 0;
+ code = curl_mime_data_cb(part,
+ value_len,
+ mime_data_read_callback,
+ mime_data_seek_callback,
+ mime_data_free_callback,
+ cb_ctx);
+ if (code != CURLE_OK) {
+ free(cb_ctx);
+ goto convert_failed;
+ }
+ }
+ }
+
+ return cmime;
+
+convert_failed:
+ NSLOG(netsurf, WARNING, "postdata conversion failed with curl code: %d", code);
+ curl_mime_free(cmime);
+ return NULL;
+}
+
+#else /* LIBCURL_VERSION_NUM >= 0x073800 */
+
+/**
+ * Convert a list of struct ::fetch_multipart_data to a list of
+ * struct curl_httppost for libcurl.
+ */
+static struct curl_httppost *
+fetch_curl_postdata_convert(CURL *chandle,
+ const struct fetch_multipart_data *control)
+{
+ struct curl_httppost *post = NULL, *last = NULL;
+ CURLFORMcode code;
+ nserror ret;
+
+ for (; control; control = control->next) {
+ if (control->file) {
+ char *leafname = NULL;
+ ret = guit->file->basename(control->value, &leafname, NULL);
+ if (ret != NSERROR_OK) {
+ continue;
+ }
+
+ /* We have to special case filenames of "", so curl
+ * a) actually attempts the fetch and
+ * b) doesn't attempt to open the file ""
+ */
+ if (control->value[0] == '\0') {
+ /* dummy buffer - needs to be static so
+ * pointer's still valid when we go out
+ * of scope (not that libcurl should be
+ * attempting to access it, of course).
+ */
+ static char buf;
+
+ code = curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, control->name,
+ CURLFORM_BUFFER, control->value,
+ /* needed, as basename("") == "." */
+ CURLFORM_FILENAME, "",
+ CURLFORM_BUFFERPTR, &buf,
+ CURLFORM_BUFFERLENGTH, 0,
+ CURLFORM_CONTENTTYPE,
+ "application/octet-stream",
+ CURLFORM_END);
+ if (code != CURL_FORMADD_OK)
+ NSLOG(netsurf, INFO,
+ "curl_formadd: %d (%s)", code,
+ control->name);
+ } else {
+ char *mimetype = guit->fetch->mimetype(control->value);
+ code = curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, control->name,
+ CURLFORM_FILE, control->rawfile,
+ CURLFORM_FILENAME, leafname,
+ CURLFORM_CONTENTTYPE,
+ (mimetype != 0 ? mimetype : "text/plain"),
+ CURLFORM_END);
+ if (code != CURL_FORMADD_OK)
+ NSLOG(netsurf, INFO,
+ "curl_formadd: %d (%s=%s)",
+ code,
+ control->name,
+ control->value);
+ free(mimetype);
+ }
+ free(leafname);
+ } else {
+ code = curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, control->name,
+ CURLFORM_COPYCONTENTS, control->value,
+ CURLFORM_END);
+ if (code != CURL_FORMADD_OK)
+ NSLOG(netsurf, INFO,
+ "curl_formadd: %d (%s=%s)", code,
+ control->name, control->value);
+ }
+ }
+
+ return post;
+}
+
+#endif /* LIBCURL_VERSION_NUM >= 0x073800 */
+
+/**
+ * Setup multipart post data
+ */
+static CURLcode fetch_curl_set_postdata(struct curl_fetch_info *f)
+{
+ CURLcode code = CURLE_OK;
+
+#undef SETOPT
+#define SETOPT(option, value) { \
+ code = curl_easy_setopt(f->curl_handle, option, value); \
+ if (code != CURLE_OK) \
+ return code; \
+ }
+
+ switch (f->postdata->type) {
+ case FETCH_POSTDATA_NONE:
+ SETOPT(CURLOPT_POSTFIELDS, NULL);
+ SETOPT(NSCURL_POSTDATA_CURLOPT, NULL);
+ SETOPT(CURLOPT_HTTPGET, 1L);
+ break;
+
+ case FETCH_POSTDATA_URLENC:
+ SETOPT(NSCURL_POSTDATA_CURLOPT, NULL);
+ SETOPT(CURLOPT_HTTPGET, 0L);
+ SETOPT(CURLOPT_POSTFIELDS, f->postdata->data.urlenc);
+ break;
+
+ case FETCH_POSTDATA_MULTIPART:
+ SETOPT(CURLOPT_POSTFIELDS, NULL);
+ SETOPT(CURLOPT_HTTPGET, 0L);
+ if (f->curl_postdata == NULL) {
+ f->curl_postdata =
+ fetch_curl_postdata_convert(f->curl_handle,
+ f->postdata->data.multipart);
+ }
+ SETOPT(NSCURL_POSTDATA_CURLOPT, f->curl_postdata);
+ break;
+ }
+ return code;
+}
+
/**
* Set options specific for a fetch.
*
@@ -606,21 +1180,11 @@ static CURLcode fetch_curl_set_options(struct curl_fetch_info *f)
SETOPT(CURLOPT_PRIVATE, f);
SETOPT(CURLOPT_WRITEDATA, f);
SETOPT(CURLOPT_WRITEHEADER, f);
- SETOPT(CURLOPT_PROGRESSDATA, f);
- SETOPT(CURLOPT_REFERER, fetch_get_referer_to_send(f->fetch_handle));
+ SETOPT(NSCURLOPT_PROGRESS_DATA, f);
SETOPT(CURLOPT_HTTPHEADER, f->headers);
- if (f->post_urlenc) {
- SETOPT(CURLOPT_HTTPPOST, NULL);
- SETOPT(CURLOPT_HTTPGET, 0L);
- SETOPT(CURLOPT_POSTFIELDS, f->post_urlenc);
- } else if (f->post_multipart) {
- SETOPT(CURLOPT_POSTFIELDS, NULL);
- SETOPT(CURLOPT_HTTPGET, 0L);
- SETOPT(CURLOPT_HTTPPOST, f->post_multipart);
- } else {
- SETOPT(CURLOPT_POSTFIELDS, NULL);
- SETOPT(CURLOPT_HTTPPOST, NULL);
- SETOPT(CURLOPT_HTTPGET, 1L);
+ code = fetch_curl_set_postdata(f);
+ if (code != CURLE_OK) {
+ return code;
}
f->cookie_string = urldb_get_cookie(f->url, true);
@@ -631,7 +1195,7 @@ static CURLcode fetch_curl_set_options(struct curl_fetch_info *f)
}
if ((auth = urldb_get_auth_details(f->url, NULL)) != NULL) {
- SETOPT(CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+ SETOPT(CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
SETOPT(CURLOPT_USERPWD, auth);
} else {
SETOPT(CURLOPT_USERPWD, NULL);
@@ -667,6 +1231,12 @@ static CURLcode fetch_curl_set_options(struct curl_fetch_info *f)
SETOPT(CURLOPT_PROXY, NULL);
}
+
+ if (curl_with_openssl) {
+ SETOPT(CURLOPT_SSL_CIPHER_LIST,
+ f->downgrade_tls ? CIPHER_LIST_LEGACY : CIPHER_LIST);
+ }
+
/* Force-enable SSL session ID caching, as some distros are odd. */
SETOPT(CURLOPT_SSL_SESSIONID_CACHE, 1);
@@ -682,10 +1252,12 @@ static CURLcode fetch_curl_set_options(struct curl_fetch_info *f)
/* do verification */
SETOPT(CURLOPT_SSL_VERIFYPEER, 1L);
SETOPT(CURLOPT_SSL_VERIFYHOST, 2L);
+#ifdef WITH_OPENSSL
if (curl_with_openssl) {
SETOPT(CURLOPT_SSL_CTX_FUNCTION, fetch_curl_sslctxfun);
SETOPT(CURLOPT_SSL_CTX_DATA, f);
}
+#endif
}
return CURLE_OK;
@@ -710,6 +1282,9 @@ fetch_curl_initiate_fetch(struct curl_fetch_info *fetch, CURL *handle)
code = fetch_curl_set_options(fetch);
if (code != CURLE_OK) {
fetch->curl_handle = 0;
+ /* The handle maybe went bad, eat it */
+ NSLOG(netsurf, WARNING, "cURL handle maybe went bad, retry later");
+ curl_easy_cleanup(handle);
return false;
}
@@ -747,6 +1322,10 @@ static CURL *fetch_curl_get_handle(lwc_string *host)
static bool fetch_curl_start(void *vfetch)
{
struct curl_fetch_info *fetch = (struct curl_fetch_info*)vfetch;
+ if (inside_curl) {
+ NSLOG(netsurf, DEBUG, "Deferring fetch because we're inside cURL");
+ return false;
+ }
return fetch_curl_initiate_fetch(fetch,
fetch_curl_get_handle(fetch->host));
}
@@ -803,23 +1382,6 @@ static void fetch_curl_cache_handle(CURL *handle, lwc_string *host)
/**
- * Abort a fetch.
- */
-static void fetch_curl_abort(void *vf)
-{
- struct curl_fetch_info *f = (struct curl_fetch_info *)vf;
- assert(f);
- NSLOG(netsurf, INFO, "fetch %p, url '%s'", f, nsurl_access(f->url));
- if (f->curl_handle) {
- f->abort = true;
- } else {
- fetch_remove_from_queues(f->fetch_handle);
- fetch_free(f->fetch_handle);
- }
-}
-
-
-/**
* Clean up the provided fetch object and free it.
*
* Will prod the queue afterwards to allow pending requests to be initiated.
@@ -846,6 +1408,30 @@ static void fetch_curl_stop(struct curl_fetch_info *f)
/**
+ * Abort a fetch.
+ */
+static void fetch_curl_abort(void *vf)
+{
+ struct curl_fetch_info *f = (struct curl_fetch_info *)vf;
+ assert(f);
+ NSLOG(netsurf, INFO, "fetch %p, url '%s'", f, nsurl_access(f->url));
+ if (f->curl_handle) {
+ if (inside_curl) {
+ NSLOG(netsurf, DEBUG, "Deferring cleanup");
+ f->abort = true;
+ } else {
+ NSLOG(netsurf, DEBUG, "Immediate abort");
+ fetch_curl_stop(f);
+ fetch_free(f->fetch_handle);
+ }
+ } else {
+ fetch_remove_from_queues(f->fetch_handle);
+ fetch_free(f->fetch_handle);
+ }
+}
+
+
+/**
* Free a fetch structure and associated resources.
*/
static void fetch_curl_free(void *vf)
@@ -864,13 +1450,14 @@ static void fetch_curl_free(void *vf)
if (f->headers) {
curl_slist_free_all(f->headers);
}
- free(f->post_urlenc);
- if (f->post_multipart) {
- curl_formfree(f->post_multipart);
- }
+ fetch_curl_free_postdata(f->postdata);
+ NSCURL_POSTDATA_FREE(f->curl_postdata);
- for (i = 0; i < MAX_CERTS && f->cert_data[i].cert; i++) {
- ns_X509_free(f->cert_data[i].cert);
+ /* free certificate data */
+ for (i = 0; i < MAX_CERT_DEPTH; i++) {
+ if (f->cert_data[i].cert != NULL) {
+ X509_free(f->cert_data[i].cert);
+ }
}
free(f);
@@ -899,7 +1486,7 @@ static bool fetch_curl_process_headers(struct curl_fetch_info *f)
http_code = f->http_code;
NSLOG(netsurf, INFO, "HTTP status code %li", http_code);
- if (http_code == 304 && !f->post_urlenc && !f->post_multipart) {
+ if ((http_code == 304) && (f->postdata->type==FETCH_POSTDATA_NONE)) {
/* Not Modified && GET request */
msg.type = FETCH_NOTMODIFIED;
fetch_send_callback(&msg, f->fetch_handle);
@@ -938,114 +1525,6 @@ static bool fetch_curl_process_headers(struct curl_fetch_info *f)
return false;
}
-/**
- * setup callback to allow the user to examine certificates which have
- * failed to validate during fetch.
- */
-static void
-curl_start_cert_validate(struct curl_fetch_info *f,
- struct cert_info *certs)
-{
- int depth;
- BIO *mem;
- BUF_MEM *buf;
- struct ssl_cert_info ssl_certs[MAX_CERTS];
- fetch_msg msg;
-
- for (depth = 0; depth <= f->cert_depth; depth++) {
- assert(certs[depth].cert != NULL);
-
- /* get certificate version */
- ssl_certs[depth].version = X509_get_version(certs[depth].cert);
-
- /* not before date */
- mem = BIO_new(BIO_s_mem());
- ASN1_TIME_print(mem, X509_get_notBefore(certs[depth].cert));
- BIO_get_mem_ptr(mem, &buf);
- (void) BIO_set_close(mem, BIO_NOCLOSE);
- BIO_free(mem);
- memcpy(ssl_certs[depth].not_before,
- buf->data,
- min(sizeof(ssl_certs[depth].not_before) - 1,
- (unsigned)buf->length));
- ssl_certs[depth].not_before[min(sizeof(ssl_certs[depth].not_before) - 1,
- (unsigned)buf->length)] = 0;
- BUF_MEM_free(buf);
-
- /* not after date */
- mem = BIO_new(BIO_s_mem());
- ASN1_TIME_print(mem,
- X509_get_notAfter(certs[depth].cert));
- BIO_get_mem_ptr(mem, &buf);
- (void) BIO_set_close(mem, BIO_NOCLOSE);
- BIO_free(mem);
- memcpy(ssl_certs[depth].not_after,
- buf->data,
- min(sizeof(ssl_certs[depth].not_after) - 1,
- (unsigned)buf->length));
- ssl_certs[depth].not_after[min(sizeof(ssl_certs[depth].not_after) - 1,
- (unsigned)buf->length)] = 0;
- BUF_MEM_free(buf);
-
- /* signature type */
- ssl_certs[depth].sig_type =
- X509_get_signature_type(certs[depth].cert);
-
- /* serial number */
- ssl_certs[depth].serial =
- ASN1_INTEGER_get(
- X509_get_serialNumber(certs[depth].cert));
-
- /* issuer name */
- mem = BIO_new(BIO_s_mem());
- X509_NAME_print_ex(mem,
- X509_get_issuer_name(certs[depth].cert),
- 0, XN_FLAG_SEP_CPLUS_SPC |
- XN_FLAG_DN_REV | XN_FLAG_FN_NONE);
- BIO_get_mem_ptr(mem, &buf);
- (void) BIO_set_close(mem, BIO_NOCLOSE);
- BIO_free(mem);
- memcpy(ssl_certs[depth].issuer,
- buf->data,
- min(sizeof(ssl_certs[depth].issuer) - 1,
- (unsigned) buf->length));
- ssl_certs[depth].issuer[min(sizeof(ssl_certs[depth].issuer) - 1,
- (unsigned) buf->length)] = 0;
- BUF_MEM_free(buf);
-
- /* subject */
- mem = BIO_new(BIO_s_mem());
- X509_NAME_print_ex(mem,
- X509_get_subject_name(certs[depth].cert),
- 0,
- XN_FLAG_SEP_CPLUS_SPC |
- XN_FLAG_DN_REV |
- XN_FLAG_FN_NONE);
- BIO_get_mem_ptr(mem, &buf);
- (void) BIO_set_close(mem, BIO_NOCLOSE);
- BIO_free(mem);
- memcpy(ssl_certs[depth].subject,
- buf->data,
- min(sizeof(ssl_certs[depth].subject) - 1,
- (unsigned)buf->length));
- ssl_certs[depth].subject[min(sizeof(ssl_certs[depth].subject) - 1,
- (unsigned) buf->length)] = 0;
- BUF_MEM_free(buf);
-
- /* type of certificate */
- ssl_certs[depth].cert_type =
- X509_certificate_type(certs[depth].cert,
- X509_get_pubkey(certs[depth].cert));
-
- /* and clean up */
- ns_X509_free(certs[depth].cert);
- }
-
- msg.type = FETCH_CERT_ERR;
- msg.data.cert_err.certs = ssl_certs;
- msg.data.cert_err.num_certs = depth;
- fetch_send_callback(&msg, f->fetch_handle);
-}
/**
* Handle a completed fetch (CURLMSG_DONE from curl_multi_info_read()).
@@ -1062,7 +1541,6 @@ static void fetch_curl_done(CURL *curl_handle, CURLcode result)
struct curl_fetch_info *f;
char **_hideous_hack = (char **) (void *) &f;
CURLcode code;
- struct cert_info certs[MAX_CERTS];
/* find the structure associated with this fetch */
/* For some reason, cURL thinks CURLINFO_PRIVATE should be a string?! */
@@ -1106,13 +1584,11 @@ static void fetch_curl_done(CURL *curl_handle, CURLcode result)
*/
;
} else if (result == CURLE_SSL_PEER_CERTIFICATE ||
- result == CURLE_SSL_CACERT) {
- /* CURLE_SSL_PEER_CERTIFICATE renamed to
- * CURLE_PEER_FAILED_VERIFICATION
+ result == CURLE_SSL_CACERT) {
+ /* Some kind of failure has occurred. If we don't know
+ * what happened, we'll have reported unknown errors up
+ * to the user already via the certificate chain error fields.
*/
- memset(certs, 0, sizeof(certs));
- memcpy(certs, f->cert_data, sizeof(certs));
- memset(f->cert_data, 0, sizeof(f->cert_data));
cert = true;
} else {
NSLOG(netsurf, INFO, "Unknown cURL response code %d", result);
@@ -1121,6 +1597,10 @@ static void fetch_curl_done(CURL *curl_handle, CURLcode result)
fetch_curl_stop(f);
+ if (f->sent_ssl_chain == false) {
+ fetch_curl_report_certs_upstream(f);
+ }
+
if (abort_fetch) {
; /* fetch was aborted: no callback */
} else if (finished) {
@@ -1129,7 +1609,9 @@ static void fetch_curl_done(CURL *curl_handle, CURLcode result)
fetch_send_callback(&msg, f->fetch_handle);
} else if (cert) {
/* user needs to validate certificate with issue */
- curl_start_cert_validate(f, certs);
+ fetch_msg msg;
+ msg.type = FETCH_CERT_ERR;
+ fetch_send_callback(&msg, f->fetch_handle);
} else if (error) {
fetch_msg msg;
switch (result) {
@@ -1179,7 +1661,7 @@ static void fetch_curl_poll(lwc_string *scheme_ignored)
&exc_fd_set, &max_fd);
assert(codem == CURLM_OK);
- NSLOG(netsurf, INFO,
+ NSLOG(netsurf, DEEPDEBUG,
"Curl file descriptor states (maxfd=%i):", max_fd);
for (i = 0; i <= max_fd; i++) {
bool read = false;
@@ -1196,7 +1678,7 @@ static void fetch_curl_poll(lwc_string *scheme_ignored)
error = true;
}
if (read || write || error) {
- NSLOG(netsurf, INFO, " fd %i: %s %s %s", i,
+ NSLOG(netsurf, DEEPDEBUG, " fd %i: %s %s %s", i,
read ? "read" : " ",
write ? "write" : " ",
error ? "error" : " ");
@@ -1205,12 +1687,13 @@ static void fetch_curl_poll(lwc_string *scheme_ignored)
}
/* do any possible work on the current fetches */
+ inside_curl = true;
do {
codem = curl_multi_perform(fetch_curl_multi, &running);
if (codem != CURLM_OK && codem != CURLM_CALL_MULTI_PERFORM) {
- NSLOG(netsurf, INFO, "curl_multi_perform: %i %s",
+ NSLOG(netsurf, WARNING,
+ "curl_multi_perform: %i %s",
codem, curl_multi_strerror(codem));
- guit->misc->warning("MiscError", curl_multi_strerror(codem));
return;
}
} while (codem == CURLM_CALL_MULTI_PERFORM);
@@ -1228,6 +1711,7 @@ static void fetch_curl_poll(lwc_string *scheme_ignored)
}
curl_msg = curl_multi_info_read(fetch_curl_multi, &queue);
}
+ inside_curl = false;
}
@@ -1238,10 +1722,10 @@ static void fetch_curl_poll(lwc_string *scheme_ignored)
*/
static int
fetch_curl_progress(void *clientp,
- double dltotal,
- double dlnow,
- double ultotal,
- double ulnow)
+ NSCURL_PROGRESS_T dltotal,
+ NSCURL_PROGRESS_T dlnow,
+ NSCURL_PROGRESS_T ultotal,
+ NSCURL_PROGRESS_T ulnow)
{
static char fetch_progress_buffer[256]; /**< Progress buffer for cURL */
struct curl_fetch_info *f = (struct curl_fetch_info *) clientp;
@@ -1282,20 +1766,50 @@ fetch_curl_progress(void *clientp,
/**
- * Ignore everything given to it.
- *
- * Used to ignore cURL debug.
+ * Format curl debug for nslog
*/
-static int fetch_curl_ignore_debug(CURL *handle,
- curl_infotype type,
- char *data,
- size_t size,
- void *userptr)
+static int
+fetch_curl_debug(CURL *handle,
+ curl_infotype type,
+ char *data,
+ size_t size,
+ void *userptr)
{
+ static const char s_infotype[CURLINFO_END][3] = {
+ "* ", "< ", "> ", "{ ", "} ", "{ ", "} "
+ };
+ switch(type) {
+ case CURLINFO_TEXT:
+ case CURLINFO_HEADER_OUT:
+ case CURLINFO_HEADER_IN:
+ NSLOG(fetch, DEBUG, "%s%.*s", s_infotype[type], (int)size - 1, data);
+ break;
+
+ default:
+ break;
+ }
return 0;
}
+static curl_socket_t fetch_curl_socket_open(void *clientp,
+ curlsocktype purpose, struct curl_sockaddr *address)
+{
+ (void) clientp;
+ (void) purpose;
+
+ return (curl_socket_t) guit->fetch->socket_open(
+ address->family, address->socktype,
+ address->protocol);
+}
+
+static int fetch_curl_socket_close(void *clientp, curl_socket_t item)
+{
+ (void) clientp;
+
+ return guit->fetch->socket_close((int) item);
+}
+
/**
* Callback function for cURL.
*/
@@ -1359,6 +1873,10 @@ fetch_curl_header(char *data, size_t size, size_t nmemb, void *_f)
return 0;
}
+ if (f->sent_ssl_chain == false) {
+ fetch_curl_report_certs_upstream(f);
+ }
+
msg.type = FETCH_HEADER;
msg.data.header_or_data.buf = (const uint8_t *) data;
msg.data.header_or_data.len = size;
@@ -1462,6 +1980,18 @@ nserror fetch_curl_register(void)
.finalise = fetch_curl_finalise
};
+#if LIBCURL_VERSION_NUM >= 0x073800
+ /* version 7.56.0 can select which SSL backend to use */
+ CURLsslset setres;
+
+ setres = curl_global_sslset(CURLSSLBACKEND_OPENSSL, NULL, NULL);
+ if (setres == CURLSSLSET_OK) {
+ curl_with_openssl = true;
+ } else {
+ curl_with_openssl = false;
+ }
+#endif
+
NSLOG(netsurf, INFO, "curl_version %s", curl_version());
code = curl_global_init(CURL_GLOBAL_ALL);
@@ -1486,8 +2016,10 @@ nserror fetch_curl_register(void)
#undef SETOPT
#define SETOPT(option, value) \
mcode = curl_multi_setopt(fetch_curl_multi, option, value); \
- if (mcode != CURLM_OK) \
- goto curl_multi_setopt_failed;
+ if (mcode != CURLM_OK) { \
+ NSLOG(netsurf, ERROR, "attempting curl_multi_setopt(%s, ...)", #option); \
+ goto curl_multi_setopt_failed; \
+ }
SETOPT(CURLMOPT_MAXCONNECTS, maxconnects);
SETOPT(CURLMOPT_MAX_TOTAL_CONNECTIONS, maxconnects);
@@ -1507,21 +2039,25 @@ nserror fetch_curl_register(void)
#undef SETOPT
#define SETOPT(option, value) \
code = curl_easy_setopt(fetch_blank_curl, option, value); \
- if (code != CURLE_OK) \
- goto curl_easy_setopt_failed;
-
- if (verbose_log) {
- SETOPT(CURLOPT_VERBOSE, 1);
- } else {
- SETOPT(CURLOPT_VERBOSE, 0);
+ if (code != CURLE_OK) { \
+ NSLOG(netsurf, ERROR, "attempting curl_easy_setopt(%s, ...)", #option); \
+ goto curl_easy_setopt_failed; \
}
+
SETOPT(CURLOPT_ERRORBUFFER, fetch_error_buffer);
+ SETOPT(CURLOPT_DEBUGFUNCTION, fetch_curl_debug);
if (nsoption_bool(suppress_curl_debug)) {
- SETOPT(CURLOPT_DEBUGFUNCTION, fetch_curl_ignore_debug);
+ SETOPT(CURLOPT_VERBOSE, 0);
+ } else {
+ SETOPT(CURLOPT_VERBOSE, 1);
}
+
+ /* Currently we explode if curl uses HTTP2, so force 1.1. */
+ SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+
SETOPT(CURLOPT_WRITEFUNCTION, fetch_curl_data);
SETOPT(CURLOPT_HEADERFUNCTION, fetch_curl_header);
- SETOPT(CURLOPT_PROGRESSFUNCTION, fetch_curl_progress);
+ SETOPT(NSCURLOPT_PROGRESS_FUNCTION, fetch_curl_progress);
SETOPT(CURLOPT_NOPROGRESS, 0);
SETOPT(CURLOPT_USERAGENT, user_agent_string());
SETOPT(CURLOPT_ENCODING, "gzip");
@@ -1529,7 +2065,8 @@ nserror fetch_curl_register(void)
SETOPT(CURLOPT_LOW_SPEED_TIME, 180L);
SETOPT(CURLOPT_NOSIGNAL, 1L);
SETOPT(CURLOPT_CONNECTTIMEOUT, nsoption_uint(curl_fetch_timeout));
- SETOPT(CURLOPT_SSL_CIPHER_LIST, CIPHER_LIST);
+ SETOPT(CURLOPT_OPENSOCKETFUNCTION, fetch_curl_socket_open);
+ SETOPT(CURLOPT_CLOSESOCKETFUNCTION, fetch_curl_socket_close);
if (nsoption_charp(ca_bundle) &&
strcmp(nsoption_charp(ca_bundle), "")) {
@@ -1542,12 +2079,32 @@ nserror fetch_curl_register(void)
SETOPT(CURLOPT_CAPATH, nsoption_charp(ca_path));
}
- /* Detect whether the SSL CTX function API works */
- curl_with_openssl = true;
- code = curl_easy_setopt(fetch_blank_curl,
- CURLOPT_SSL_CTX_FUNCTION, NULL);
+#if LIBCURL_VERSION_NUM < 0x073800
+ /*
+ * before 7.56.0 Detect openssl from whether the SSL CTX
+ * function API works
+ */
+ code = curl_easy_setopt(fetch_blank_curl, CURLOPT_SSL_CTX_FUNCTION, NULL);
if (code != CURLE_OK) {
curl_with_openssl = false;
+ } else {
+ curl_with_openssl = true;
+ }
+#endif
+
+ if (curl_with_openssl) {
+ /* only set the cipher list with openssl otherwise the
+ * fetch fails with "Unknown cipher in list"
+ */
+#if LIBCURL_VERSION_NUM >= 0x073d00
+ /* Need libcurl 7.61.0 or later built against OpenSSL with
+ * TLS1.3 support */
+ code = curl_easy_setopt(fetch_blank_curl,
+ CURLOPT_TLS13_CIPHERS, CIPHER_SUITES);
+ if (code != CURLE_OK && code != CURLE_NOT_BUILT_IN)
+ goto curl_easy_setopt_failed;
+#endif
+ SETOPT(CURLOPT_SSL_CIPHER_LIST, CIPHER_LIST);
}
NSLOG(netsurf, INFO, "cURL %slinked against openssl",
@@ -1557,6 +2114,12 @@ nserror fetch_curl_register(void)
data = curl_version_info(CURLVERSION_NOW);
+ curl_fetch_ssl_hashmap = hashmap_create(&curl_fetch_ssl_hashmap_parameters);
+ if (curl_fetch_ssl_hashmap == NULL) {
+ NSLOG(netsurf, CRITICAL, "Unable to initialise SSL certificate hashmap");
+ return NSERROR_NOMEM;
+ }
+
for (i = 0; data->protocols[i]; i++) {
if (strcmp(data->protocols[i], "http") == 0) {
scheme = lwc_string_ref(corestring_lwc_http);
diff --git a/content/fetchers/data.c b/content/fetchers/data.c
index 5ba021fd3..c7de14c3d 100644
--- a/content/fetchers/data.c
+++ b/content/fetchers/data.c
@@ -23,6 +23,7 @@
#include <stdbool.h>
#include <string.h>
+#include <stdarg.h>
#include <stdlib.h>
#include <libwapcaplet/libwapcaplet.h>
#include <nsutils/base64.h>
@@ -41,7 +42,7 @@
struct fetch_data_context {
struct fetch *parent_fetch;
- char *url;
+ nsurl *url;
char *mimetype;
char *data;
size_t datalen;
@@ -74,6 +75,36 @@ static bool fetch_data_can_fetch(const nsurl *url)
return true;
}
+static void fetch_data_send_callback(const fetch_msg *msg,
+ struct fetch_data_context *c)
+{
+ c->locked = true;
+ fetch_send_callback(msg, c->parent_fetch);
+ c->locked = false;
+}
+
+static void fetch_data_send_header(struct fetch_data_context *ctx,
+ const char *fmt, ...)
+{
+ char header[64];
+ fetch_msg msg;
+ va_list ap;
+ int len;
+
+ va_start(ap, fmt);
+ len = vsnprintf(header, sizeof(header), fmt, ap);
+ va_end(ap);
+
+ if (len >= (int)sizeof(header) || len < 0) {
+ return;
+ }
+
+ msg.type = FETCH_HEADER;
+ msg.data.header_or_data.len = len;
+ msg.data.header_or_data.buf = (const uint8_t *)header;
+ fetch_data_send_callback(&msg, ctx);
+}
+
static void *fetch_data_setup(struct fetch *parent_fetch, nsurl *url,
bool only_2xx, bool downgrade_tls, const char *post_urlenc,
const struct fetch_multipart_data *post_multipart,
@@ -85,14 +116,7 @@ static void *fetch_data_setup(struct fetch *parent_fetch, nsurl *url,
return NULL;
ctx->parent_fetch = parent_fetch;
-
- /* TODO: keep as nsurl to avoid copy */
- ctx->url = malloc(nsurl_length(url) + 1);
- if (ctx->url == NULL) {
- free(ctx);
- return NULL;
- }
- memcpy(ctx->url, nsurl_access(url), nsurl_length(url) + 1);
+ ctx->url = nsurl_ref(url);
RING_INSERT(ring, ctx);
@@ -108,10 +132,9 @@ static void fetch_data_free(void *ctx)
{
struct fetch_data_context *c = ctx;
- free(c->url);
+ nsurl_unref(c->url);
free(c->data);
free(c->mimetype);
- RING_REMOVE(ring, c);
free(ctx);
}
@@ -126,20 +149,12 @@ static void fetch_data_abort(void *ctx)
c->aborted = true;
}
-static void fetch_data_send_callback(const fetch_msg *msg,
- struct fetch_data_context *c)
-{
- c->locked = true;
- fetch_send_callback(msg, c->parent_fetch);
- c->locked = false;
-}
-
static bool fetch_data_process(struct fetch_data_context *c)
{
nserror res;
fetch_msg msg;
- char *params;
- char *comma;
+ const char *params;
+ const char *comma;
char *unescaped;
size_t unescaped_len;
@@ -149,9 +164,9 @@ static bool fetch_data_process(struct fetch_data_context *c)
* data must still be there.
*/
- NSLOG(netsurf, INFO, "url: %.140s", c->url);
+ NSLOG(netsurf, DEEPDEBUG, "url: %.140s", nsurl_access(c->url));
- if (strlen(c->url) < 6) {
+ if (nsurl_length(c->url) < 6) {
/* 6 is the minimum possible length (data:,) */
msg.type = FETCH_ERROR;
msg.data.error = "Malformed data: URL";
@@ -160,7 +175,7 @@ static bool fetch_data_process(struct fetch_data_context *c)
}
/* skip the data: part */
- params = c->url + SLEN("data:");
+ params = nsurl_access(c->url) + SLEN("data:");
/* find the comma */
if ( (comma = strchr(params, ',')) == NULL) {
@@ -216,21 +231,12 @@ static bool fetch_data_process(struct fetch_data_context *c)
free(unescaped);
return false;
}
+ free(unescaped);
} else {
- c->data = malloc(unescaped_len);
- if (c->data == NULL) {
- msg.type = FETCH_ERROR;
- msg.data.error =
- "Unable to allocate memory for data: URL";
- fetch_data_send_callback(&msg, c);
- free(unescaped);
- return false;
- }
c->datalen = unescaped_len;
- memcpy(c->data, unescaped, unescaped_len);
+ c->data = unescaped;
}
- free(unescaped);
return true;
}
@@ -238,13 +244,14 @@ static bool fetch_data_process(struct fetch_data_context *c)
static void fetch_data_poll(lwc_string *scheme)
{
fetch_msg msg;
- struct fetch_data_context *c, *next;
-
- if (ring == NULL) return;
+ struct fetch_data_context *c, *save_ring = NULL;
/* Iterate over ring, processing each pending fetch */
- c = ring;
- do {
+ while (ring != NULL) {
+ /* Take the first entry from the ring */
+ c = ring;
+ RING_REMOVE(ring, c);
+
/* Ignore fetches that have been flagged as locked.
* This allows safe re-entrant calls to this function.
* Re-entrancy can occur if, as a result of a callback,
@@ -252,14 +259,12 @@ static void fetch_data_poll(lwc_string *scheme)
* again.
*/
if (c->locked == true) {
- next = c->r_next;
+ RING_INSERT(save_ring, c);
continue;
}
/* Only process non-aborted fetches */
if (c->aborted == false && fetch_data_process(c) == true) {
- char header[64];
-
fetch_set_http_code(c->parent_fetch, 200);
NSLOG(netsurf, INFO,
"setting data: MIME type to %s, length to %"PRIsizet,
@@ -269,22 +274,18 @@ static void fetch_data_poll(lwc_string *scheme)
* Therefore, we _must_ check for this after _every_
* call to fetch_data_send_callback().
*/
- snprintf(header, sizeof header, "Content-Type: %s",
+ fetch_data_send_header(c, "Content-Type: %s",
c->mimetype);
- msg.type = FETCH_HEADER;
- msg.data.header_or_data.buf = (const uint8_t *) header;
- msg.data.header_or_data.len = strlen(header);
- fetch_data_send_callback(&msg, c);
if (c->aborted == false) {
- snprintf(header, sizeof header,
- "Content-Length: %" PRIsizet,
- c->datalen);
- msg.type = FETCH_HEADER;
- msg.data.header_or_data.buf =
- (const uint8_t *) header;
- msg.data.header_or_data.len = strlen(header);
- fetch_data_send_callback(&msg, c);
+ fetch_data_send_header(c, "Content-Length: %"
+ PRIsizet, c->datalen);
+ }
+
+ if (c->aborted == false) {
+ /* Set max-age to 1 year. */
+ fetch_data_send_header(c, "Cache-Control: "
+ "max-age=31536000");
}
if (c->aborted == false) {
@@ -300,8 +301,8 @@ static void fetch_data_poll(lwc_string *scheme)
fetch_data_send_callback(&msg, c);
}
} else {
- NSLOG(netsurf, INFO, "Processing of %s failed!",
- c->url);
+ NSLOG(netsurf, INFO, "Processing of %.140s failed!",
+ nsurl_access(c->url));
/* Ensure that we're unlocked here. If we aren't,
* then fetch_data_process() is broken.
@@ -309,18 +310,15 @@ static void fetch_data_poll(lwc_string *scheme)
assert(c->locked == false);
}
- /* Compute next fetch item at the last possible moment as
- * processing this item may have added to the ring.
- */
- next = c->r_next;
-
+ /* And now finish */
fetch_remove_from_queues(c->parent_fetch);
fetch_free(c->parent_fetch);
+ }
- /* Advance to next ring entry, exiting if we've reached
- * the start of the ring or the ring has become empty
- */
- } while ( (c = next) != ring && ring != NULL);
+ /* Finally, if we saved any fetches which were locked, put them back
+ * into the ring for next time
+ */
+ ring = save_ring;
}
nserror fetch_data_register(void)
diff --git a/content/fetchers/file/Makefile b/content/fetchers/file/Makefile
new file mode 100644
index 000000000..c22400a56
--- /dev/null
+++ b/content/fetchers/file/Makefile
@@ -0,0 +1,3 @@
+# File fetcher sources
+
+S_FETCHER_FILE := dirlist.c file.c
diff --git a/content/dirlist.c b/content/fetchers/file/dirlist.c
index 1d7a67e1f..345dbd8f3 100644
--- a/content/dirlist.c
+++ b/content/fetchers/file/dirlist.c
@@ -27,8 +27,14 @@
#include "utils/nsurl.h"
#include "utils/messages.h"
+#include "utils/nscolour.h"
-#include "content/dirlist.h"
+#include "netsurf/inttypes.h"
+#include "netsurf/types.h"
+#include "netsurf/plot_style.h"
+
+#include "dirlist.h"
+#include "desktop/system_colour.h"
static int dirlist_filesize_calculate(unsigned long *bytesize);
static int dirlist_filesize_value(unsigned long bytesize);
@@ -136,18 +142,33 @@ bool dirlist_generate_hide_columns(int flags, char *buffer, int buffer_length)
bool dirlist_generate_title(const char *title, char *buffer, int buffer_length)
{
+ const char *stylesheet;
+ nserror err;
int error;
if (title == NULL)
title = "";
+ err = nscolour_get_stylesheet(&stylesheet);
+ if (err != NSERROR_OK) {
+ return false;
+ }
+
error = snprintf(buffer, buffer_length,
"</style>\n"
"<title>%s</title>\n"
+ "<style>\n"
+ "html {\n"
+ "\tbackground-color: #%06"PRIx32";\n"
+ "}\n"
+ "%s"
+ "</style>\n"
"</head>\n"
- "<body id=\"dirlist\">\n"
- "<h1>%s</h1>\n",
- title, title);
+ "<body id=\"dirlist\" class=\"ns-even-bg ns-even-fg ns-border\">\n"
+ "<h1 class=\"ns-border\">%s</h1>\n",
+ title,
+ colour_rb_swap(nscolours[NSCOLOUR_WIN_ODD_BG]),
+ stylesheet, title);
if (error < 0 || error >= buffer_length)
/* Error or buffer too small */
return false;
@@ -284,14 +305,14 @@ bool dirlist_generate_row(bool even, bool directory, nsurl *url, char *name,
error = snprintf(buffer, buffer_length,
"<a href=\"%s\" class=\"%s %s\">\n"
- "\t<span class=\"name\">%s</span>\n"
- "\t<span class=\"type\">%s</span>\n"
- "\t<span class=\"size\">%s</span>"
- "<span class=\"size\">%s</span>\n"
- "\t<span class=\"date\">%s</span>\n"
- "\t<span class=\"time\">%s</span>\n"
- "</a>\n",
- nsurl_access(url), even ? "even" : "odd",
+ "\t<span class=\"name ns-border\">%s</span>\n"
+ "\t<span class=\"type ns-border\">%s</span>\n"
+ "\t<span class=\"size ns-border\">%s</span>"
+ "<span class=\"size ns-border\">%s</span>\n"
+ "\t<span class=\"date ns-border\">%s</span>\n"
+ "\t<span class=\"time ns-border\">%s</span>\n"
+ "</a>\n", nsurl_access(url),
+ even ? "even ns-even-bg" : "odd ns-odd-bg",
directory ? "dir" : "file",
name, mimetype, size_string, unit, date, time);
if (error < 0 || error >= buffer_length)
diff --git a/content/dirlist.h b/content/fetchers/file/dirlist.h
index 5cdaf7532..3a0d48c1c 100644
--- a/content/dirlist.h
+++ b/content/fetchers/file/dirlist.h
@@ -16,14 +16,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Generate HTML content for displaying directory listings (interface).
+/**
+ * \file
+ * interface to generate HTML content for displaying directory listings.
*
* These functions should in general be called via the content interface.
*/
-#ifndef _NETSURF_CONTENT_DIRLIST_H_
-#define _NETSURF_CONTENT_DIRLIST_H_
+#ifndef NETSURF_CONTENT_DIRLIST_H_
+#define NETSURF_CONTENT_DIRLIST_H_
#include <stdbool.h>
diff --git a/content/fetchers/file.c b/content/fetchers/file/file.c
index 4fa1a2138..ff3a1b1f6 100644
--- a/content/fetchers/file.c
+++ b/content/fetchers/file/file.c
@@ -50,15 +50,17 @@
#include "utils/corestrings.h"
#include "utils/messages.h"
#include "utils/utils.h"
+#include "utils/log.h"
+#include "utils/time.h"
#include "utils/ring.h"
#include "utils/file.h"
#include "netsurf/fetch.h"
#include "desktop/gui_internal.h"
-#include "content/dirlist.h"
#include "content/fetch.h"
#include "content/fetchers.h"
-#include "content/fetchers/file.h"
+#include "dirlist.h"
+#include "file.h"
/* Maximum size of read buffer */
#define FETCH_FILE_MAX_BUF_SIZE (1024 * 1024)
@@ -97,19 +99,21 @@ static bool fetch_file_send_header(struct fetch_file_context *ctx,
fetch_msg msg;
char header[64];
va_list ap;
+ int len;
va_start(ap, fmt);
-
- vsnprintf(header, sizeof header, fmt, ap);
-
+ len = vsnprintf(header, sizeof header, fmt, ap);
va_end(ap);
+ if (len >= (int)sizeof(header) || len < 0) {
+ return false;
+ }
+
msg.type = FETCH_HEADER;
msg.data.header_or_data.buf = (const uint8_t *) header;
- msg.data.header_or_data.len = strlen(header);
- fetch_file_send_callback(&msg, ctx);
+ msg.data.header_or_data.len = len;
- return ctx->aborted;
+ return fetch_file_send_callback(&msg, ctx);
}
/** callback to initialise the file fetcher. */
@@ -156,18 +160,25 @@ fetch_file_setup(struct fetch *fetchh,
/* Scan request headers looking for If-None-Match */
for (i = 0; headers[i] != NULL; i++) {
- if (strncasecmp(headers[i], "If-None-Match:",
- SLEN("If-None-Match:")) == 0) {
- /* If-None-Match: "12345678" */
- const char *d = headers[i] + SLEN("If-None-Match:");
-
- /* Scan to first digit, if any */
- while (*d != '\0' && (*d < '0' || '9' < *d))
- d++;
-
- /* Convert to time_t */
- if (*d != '\0')
- ctx->file_etag = atoi(d);
+ if (strncasecmp(headers[i], "If-None-Match:",
+ SLEN("If-None-Match:")) != 0) {
+ continue;
+ }
+
+ /* If-None-Match: "12345678" */
+ const char *d = headers[i] + SLEN("If-None-Match:");
+
+ /* Scan to first digit, if any */
+ while (*d != '\0' && (*d < '0' || '9' < *d))
+ d++;
+
+ /* Convert to time_t */
+ if (*d != '\0') {
+ ret = nsc_snptimet(d, strlen(d), &ctx->file_etag);
+ if (ret != NSERROR_OK) {
+ NSLOG(fetch, WARNING,
+ "Bad If-None-Match value");
+ }
}
}
@@ -184,7 +195,6 @@ static void fetch_file_free(void *ctx)
struct fetch_file_context *c = ctx;
nsurl_unref(c->url);
free(c->path);
- RING_REMOVE(ring, c);
free(ctx);
}
@@ -780,13 +790,13 @@ static void fetch_file_process(struct fetch_file_context *ctx)
/** callback to poll for additional file fetch contents */
static void fetch_file_poll(lwc_string *scheme)
{
- struct fetch_file_context *c, *next;
+ struct fetch_file_context *c, *save_ring = NULL;
- if (ring == NULL) return;
+ while (ring != NULL) {
+ /* Take the first entry from the ring */
+ c = ring;
+ RING_REMOVE(ring, c);
- /* Iterate over ring, processing each pending fetch */
- c = ring;
- do {
/* Ignore fetches that have been flagged as locked.
* This allows safe re-entrant calls to this function.
* Re-entrancy can occur if, as a result of a callback,
@@ -794,7 +804,7 @@ static void fetch_file_poll(lwc_string *scheme)
* again.
*/
if (c->locked == true) {
- next = c->r_next;
+ RING_INSERT(save_ring, c);
continue;
}
@@ -804,18 +814,16 @@ static void fetch_file_poll(lwc_string *scheme)
fetch_file_process(c);
}
- /* Compute next fetch item at the last possible moment as
- * processing this item may have added to the ring.
- */
- next = c->r_next;
-
+ /* And now finish */
fetch_remove_from_queues(c->fetchh);
fetch_free(c->fetchh);
- /* Advance to next ring entry, exiting if we've reached
- * the start of the ring or the ring has become empty
- */
- } while ( (c = next) != ring && ring != NULL);
+ }
+
+ /* Finally, if we saved any fetches which were locked, put them back
+ * into the ring for next time
+ */
+ ring = save_ring;
}
nserror fetch_file_register(void)
diff --git a/content/fetchers/file.h b/content/fetchers/file/file.h
index 5a5cfe89b..5a5cfe89b 100644
--- a/content/fetchers/file.h
+++ b/content/fetchers/file/file.h
diff --git a/content/fetchers/resource.c b/content/fetchers/resource.c
index 78757733e..c8176f34b 100644
--- a/content/fetchers/resource.c
+++ b/content/fetchers/resource.c
@@ -33,6 +33,7 @@
#include "utils/nsurl.h"
#include "utils/corestrings.h"
#include "utils/log.h"
+#include "utils/time.h"
#include "utils/messages.h"
#include "utils/utils.h"
#include "utils/ring.h"
@@ -55,7 +56,6 @@ static const char *fetch_resource_paths[] = {
"credits.html",
"licence.html",
"welcome.html",
- "maps.html",
"favicon.ico",
"default.ico",
"netsurf.png",
@@ -97,7 +97,7 @@ struct fetch_resource_context {
fetch_resource_handler handler;
- int etag;
+ time_t etag;
};
static struct fetch_resource_context *ring = NULL;
@@ -121,19 +121,21 @@ static bool fetch_resource_send_header(struct fetch_resource_context *ctx,
fetch_msg msg;
char header[64];
va_list ap;
+ int len;
va_start(ap, fmt);
-
- vsnprintf(header, sizeof header, fmt, ap);
-
+ len = vsnprintf(header, sizeof header, fmt, ap);
va_end(ap);
+ if (len >= (int)sizeof(header) || len < 0) {
+ return false;
+ }
+
msg.type = FETCH_HEADER;
msg.data.header_or_data.buf = (const uint8_t *) header;
- msg.data.header_or_data.len = strlen(header);
- fetch_resource_send_callback(&msg, ctx);
+ msg.data.header_or_data.len = len;
- return ctx->aborted;
+ return fetch_resource_send_callback(&msg, ctx);
}
@@ -194,6 +196,11 @@ static bool fetch_resource_data_handler(struct fetch_resource_context *ctx)
goto fetch_resource_data_aborted;
}
+ /* create max-age of 1 year */
+ if (fetch_resource_send_header(ctx,
+ "Cache-Control: max-age=31536000")) {
+ goto fetch_resource_data_aborted;
+ }
msg.type = FETCH_DATA;
msg.data.header_or_data.buf = (const uint8_t *) ctx->entry->data;
@@ -328,6 +335,7 @@ fetch_resource_setup(struct fetch *fetchh,
{
struct fetch_resource_context *ctx;
lwc_string *path;
+ nserror ret;
uint32_t i;
ctx = calloc(1, sizeof(*ctx));
@@ -364,17 +372,24 @@ fetch_resource_setup(struct fetch *fetchh,
/* Scan request headers looking for If-None-Match */
for (i = 0; headers[i] != NULL; i++) {
if (strncasecmp(headers[i], "If-None-Match:",
- SLEN("If-None-Match:")) == 0) {
- /* If-None-Match: "12345678" */
- const char *d = headers[i] + SLEN("If-None-Match:");
+ SLEN("If-None-Match:")) != 0) {
+ continue;
+ }
+
+ /* If-None-Match: "12345678" */
+ const char *d = headers[i] + SLEN("If-None-Match:");
- /* Scan to first digit, if any */
- while (*d != '\0' && (*d < '0' || '9' < *d))
- d++;
+ /* Scan to first digit, if any */
+ while (*d != '\0' && (*d < '0' || '9' < *d))
+ d++;
- /* Convert to time_t */
- if (*d != '\0')
- ctx->etag = atoi(d);
+ /* Convert to time_t */
+ if (*d != '\0') {
+ ret = nsc_snptimet(d, strlen(d), &ctx->etag);
+ if (ret != NSERROR_OK) {
+ NSLOG(fetch, WARNING,
+ "Bad If-None-Match value");
+ }
}
}
@@ -391,7 +406,6 @@ static void fetch_resource_free(void *ctx)
struct fetch_resource_context *c = ctx;
if (c->url != NULL)
nsurl_unref(c->url);
- RING_REMOVE(ring, c);
free(ctx);
}
@@ -417,13 +431,13 @@ static void fetch_resource_abort(void *ctx)
/** callback to poll for additional resource fetch contents */
static void fetch_resource_poll(lwc_string *scheme)
{
- struct fetch_resource_context *c, *next;
+ struct fetch_resource_context *c, *save_ring = NULL;
- if (ring == NULL) return;
+ while (ring != NULL) {
+ /* Take the first entry from the ring */
+ c = ring;
+ RING_REMOVE(ring, c);
- /* Iterate over ring, processing each pending fetch */
- c = ring;
- do {
/* Ignore fetches that have been flagged as locked.
* This allows safe re-entrant calls to this function.
* Re-entrancy can occur if, as a result of a callback,
@@ -431,7 +445,7 @@ static void fetch_resource_poll(lwc_string *scheme)
* again.
*/
if (c->locked == true) {
- next = c->r_next;
+ RING_INSERT(save_ring, c);
continue;
}
@@ -441,18 +455,15 @@ static void fetch_resource_poll(lwc_string *scheme)
c->handler(c);
}
- /* Compute next fetch item at the last possible moment
- * as processing this item may have added to the ring
- */
- next = c->r_next;
-
+ /* And now finish */
fetch_remove_from_queues(c->fetchh);
fetch_free(c->fetchh);
+ }
- /* Advance to next ring entry, exiting if we've reached
- * the start of the ring or the ring has become empty
- */
- } while ( (c = next) != ring && ring != NULL);
+ /* Finally, if we saved any fetches which were locked, put them back
+ * into the ring for next time
+ */
+ ring = save_ring;
}
nserror fetch_resource_register(void)
diff --git a/content/fs_backing_store.c b/content/fs_backing_store.c
index 3736cc551..a145c6fe1 100644
--- a/content/fs_backing_store.c
+++ b/content/fs_backing_store.c
@@ -49,32 +49,21 @@
#include "utils/nsurl.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/hashmap.h"
#include "desktop/gui_internal.h"
#include "netsurf/misc.h"
#include "content/backing_store.h"
-/** Default number of bits of the ident to use in index hash */
-#define DEFAULT_IDENT_SIZE 20
-
-/** Default number of bits to use for an entry index. */
-#define DEFAULT_ENTRY_SIZE 16
-
/** Backing store file format version */
-#define CONTROL_VERSION 130
+#define CONTROL_VERSION 202
-/** Number of milliseconds after a update before control data maintenance is performed */
+/**
+ * Number of milliseconds after a update before control data
+ * maintenance is performed
+ */
#define CONTROL_MAINT_TIME 10000
-/** Get address from ident */
-#define BS_ADDRESS(ident, state) ((ident) & ((1 << state->ident_bits) - 1))
-
-/** Lookup store entry index from ident */
-#define BS_ENTRY_INDEX(ident, state) state->addrmap[(ident) & ((1 << state->ident_bits) - 1)]
-
-/** Get store entry from ident. */
-#define BS_ENTRY(ident, state) state->entries[state->addrmap[(ident) & ((1 << state->ident_bits) - 1)]]
-
/** Filename of serialised entries */
#define ENTRIES_FNAME "entries"
@@ -84,8 +73,8 @@
/** log2 block data address length (64k) */
#define BLOCK_ADDR_LEN 16
-/** log2 number of entries per block file(4k) */
-#define BLOCK_ENTRY_COUNT 12
+/** log2 number of entries per block file(1024) */
+#define BLOCK_ENTRY_COUNT 10
/** log2 number of data block files */
#define BLOCK_FILE_COUNT (BLOCK_ADDR_LEN - BLOCK_ENTRY_COUNT)
@@ -93,21 +82,13 @@
/** log2 size of data blocks (8k) */
#define BLOCK_DATA_SIZE 13
-/** log2 size of metadata blocks (1k) */
-#define BLOCK_META_SIZE 10
+/** log2 size of metadata blocks (8k) */
+#define BLOCK_META_SIZE 13
/** length in bytes of a block files use map */
#define BLOCK_USE_MAP_SIZE (1 << (BLOCK_ENTRY_COUNT - 3))
/**
- * The type used to store index values referring to store entries. Care
- * must be taken with this type as it is used to build address to
- * entry mapping so changing the size will have large impacts on
- * memory usage.
- */
-typedef uint16_t entry_index_t;
-
-/**
* The type used as a binary identifier for each entry derived from
* the URL. A larger identifier will have fewer collisions but
* requires proportionately more storage.
@@ -184,8 +165,8 @@ struct store_entry_element {
* @note Order is important to avoid excessive structure packing overhead.
*/
struct store_entry {
+ nsurl *url; /**< The URL for this entry */
int64_t last_used; /**< UNIX time the entry was last used */
- entry_ident_t ident; /**< entry identifier */
uint16_t use_count; /**< number of times this entry has been accessed */
uint8_t flags; /**< entry flags */
/** Entry element (data or meta) specific information */
@@ -219,29 +200,16 @@ struct store_state {
size_t limit; /**< The backing store upper bound target size */
size_t hysteresis; /**< The hysteresis around the target size */
- unsigned int ident_bits; /**< log2 number of bits to use for address. */
-
-
- /* cache entry management */
- struct store_entry *entries; /**< store entries. */
- unsigned int entry_bits; /**< log2 number of bits in entry index. */
- unsigned int last_entry; /**< index of last usable entry. */
+ /**
+ * The cache object hash
+ */
+ hashmap_t *entries;
/** flag indicating if the entries have been made persistent
* since they were last changed.
*/
bool entries_dirty;
- /**
- * URL identifier to entry index mapping.
- *
- * This is an open coded index on the entries URL field and
- * provides a computationally inexpensive way to go from the
- * URL to an entry.
- */
- entry_index_t *addrmap;
-
-
/** small block indexes */
struct block_file blocks[ENTRY_ELEM_COUNT][BLOCK_FILE_COUNT];
@@ -273,60 +241,44 @@ struct store_state {
*/
struct store_state *storestate;
-
-/**
- * Remove a backing store entry from the entry table.
+/* Entries hashmap parameters
*
- * This finds the store entry associated with the given key and
- * removes it from the table. The removed entry is returned but is
- * only valid until the next set_store_entry call.
- *
- * @param[in] state The store state to use.
- * @param[in, out] bse Pointer to the entry to be removed.
- * @return NSERROR_OK and \a bse updated on success or NSERROR_NOT_FOUND
- * if no entry corresponds to the URL.
+ * Our hashmap has nsurl keys and store_entry values
*/
-static nserror
-remove_store_entry(struct store_state *state, struct store_entry **bse)
-{
- entry_index_t sei; /* store entry index */
-
- /* sei is index to entry to be removed, we swap it to the end
- * of the table so there are no gaps and the returned entry is
- * held in storage with reasonable lifetime.
- */
-
- sei = BS_ENTRY_INDEX((*bse)->ident, state);
-
- /* remove entry from map */
- BS_ENTRY_INDEX((*bse)->ident, state) = 0;
-
- /* global allocation accounting */
- state->total_alloc -= state->entries[sei].elem[ENTRY_ELEM_DATA].size;
- state->total_alloc -= state->entries[sei].elem[ENTRY_ELEM_META].size;
-
- state->last_entry--;
-
- if (sei == state->last_entry) {
- /* the removed entry was the last one, how convenient */
- *bse = &state->entries[sei];
- } else {
- /* need to swap entries */
- struct store_entry tent;
-
- tent = state->entries[sei];
- state->entries[sei] = state->entries[state->last_entry];
- state->entries[state->last_entry] = tent;
- /* update map for moved entry */
- BS_ENTRY_INDEX(state->entries[sei].ident, state) = sei;
+static bool
+entries_hashmap_key_eq(void *key1, void *key2)
+{
+ return nsurl_compare((nsurl *)key1, (nsurl *)key2, NSURL_COMPLETE);
+}
- *bse = &state->entries[state->last_entry];
+static void *
+entries_hashmap_value_alloc(void *key)
+{
+ struct store_entry *ent = calloc(1, sizeof(struct store_entry));
+ if (ent != NULL) {
+ ent->url = nsurl_ref(key);
}
+ return ent;
+}
- return NSERROR_OK;
+static void
+entries_hashmap_value_destroy(void *value)
+{
+ struct store_entry *ent = value;
+ /** \todo Do we need to do any disk cleanup here? if so, meep! */
+ nsurl_unref(ent->url);
+ free(ent);
}
+static hashmap_parameters_t entries_hashmap_parameters = {
+ .key_clone = (hashmap_key_clone_t)nsurl_ref,
+ .key_destroy = (hashmap_key_destroy_t)nsurl_unref,
+ .key_hash = (hashmap_key_hash_t)nsurl_hash,
+ .key_eq = entries_hashmap_key_eq,
+ .value_alloc = entries_hashmap_value_alloc,
+ .value_destroy = entries_hashmap_value_destroy,
+};
/**
* Generate a filename for an object.
@@ -484,7 +436,7 @@ invalidate_element(struct store_state *state,
char *fname;
/* unlink the file from disc */
- fname = store_fname(state, bse->ident, elem_idx);
+ fname = store_fname(state, nsurl_hash(bse->url), elem_idx);
if (fname == NULL) {
return NSERROR_NOMEM;
}
@@ -492,6 +444,8 @@ invalidate_element(struct store_state *state,
free(fname);
}
+ state->total_alloc -= bse->elem[elem_idx].size;
+
return NSERROR_OK;
}
@@ -519,29 +473,27 @@ invalidate_entry(struct store_state *state, struct store_entry *bse)
* This entry cannot be immediately removed as it has
* associated allocation so wait for allocation release.
*/
- NSLOG(netsurf, INFO,
+ NSLOG(netsurf, DEBUG,
"invalidating entry with referenced allocation");
return NSERROR_OK;
}
- NSLOG(netsurf, INFO, "Removing entry for %p", bse);
-
- /* remove the entry from the index */
- ret = remove_store_entry(state, &bse);
- if (ret != NSERROR_OK) {
- return ret;
- }
+ NSLOG(netsurf, VERBOSE, "Removing entry for %s", nsurl_access(bse->url));
ret = invalidate_element(state, bse, ENTRY_ELEM_META);
if (ret != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Error invalidating metadata element");
+ NSLOG(netsurf, ERROR, "Error invalidating metadata element");
}
ret = invalidate_element(state, bse, ENTRY_ELEM_DATA);
if (ret != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Error invalidating data element");
+ NSLOG(netsurf, ERROR, "Error invalidating data element");
}
+ /* As our final act we remove bse from the cache */
+ hashmap_remove(state->entries, bse->url);
+ /* From now, bse is invalid memory */
+
return NSERROR_OK;
}
@@ -551,8 +503,8 @@ invalidate_entry(struct store_state *state, struct store_entry *bse)
*/
static int compar(const void *va, const void *vb)
{
- const struct store_entry *a = &BS_ENTRY(*(entry_ident_t *)va, storestate);
- const struct store_entry *b = &BS_ENTRY(*(entry_ident_t *)vb, storestate);
+ const struct store_entry *a = *(const struct store_entry **)va;
+ const struct store_entry *b = *(const struct store_entry **)vb;
/* consider the allocation flags - if an entry has an
* allocation it is considered more valuable as it cannot be
@@ -591,6 +543,22 @@ static int compar(const void *va, const void *vb)
return 0;
}
+typedef struct {
+ struct store_entry **elist;
+ size_t ent_count;
+} eviction_state_t;
+
+/**
+ * Iterator for gathering entries to compute eviction order
+ */
+static bool
+entry_eviction_iterator_cb(void *key, void *value, void *ctx)
+{
+ eviction_state_t *estate = ctx;
+ struct store_entry *ent = value;
+ estate->elist[estate->ent_count++] = ent;
+ return false;
+}
/**
* Evict entries from backing store as per configuration.
@@ -608,15 +576,14 @@ static int compar(const void *va, const void *vb)
*/
static nserror store_evict(struct store_state *state)
{
- entry_ident_t *elist; /* sorted list of entry identifiers */
- unsigned int ent;
- unsigned int ent_count;
- size_t removed; /* size of removed entries */
+ size_t ent = 0;
+ size_t removed = 0; /* size of removed entries */
nserror ret = NSERROR_OK;
+ size_t old_count;
+ eviction_state_t estate;
/* check if the cache has exceeded configured limit */
- if ((state->total_alloc < state->limit) &&
- (state->last_entry < (1U << state->entry_bits))) {
+ if (state->total_alloc < state->limit) {
/* cache within limits */
return NSERROR_OK;
}
@@ -627,24 +594,31 @@ static nserror store_evict(struct store_state *state)
state->hysteresis);
/* allocate storage for the list */
- elist = malloc(sizeof(entry_ident_t) * state->last_entry);
- if (elist == NULL) {
+ old_count = hashmap_count(state->entries);
+ estate.ent_count = 0;
+ estate.elist = malloc(sizeof(struct state_entry*) * old_count);
+ if (estate.elist == NULL) {
return NSERROR_NOMEM;
}
- /* sort the list avoiding entry 0 which is the empty sentinel */
- for (ent = 1; ent < state->last_entry; ent++) {
- elist[ent - 1] = state->entries[ent].ident;
+ if (hashmap_iterate(state->entries, entry_eviction_iterator_cb, &estate)) {
+ NSLOG(netsurf, WARNING, "Unexpected termination of eviction iterator");
+ free(estate.elist);
+ return NSERROR_UNKNOWN;
+ }
+
+ if (old_count != estate.ent_count) {
+ NSLOG(netsurf, WARNING, "Incorrect entry count after eviction iterator");
+ free(estate.elist);
+ return NSERROR_UNKNOWN;
}
- ent_count = ent - 1; /* important to keep this as the entry count will change when entries are removed */
- qsort(elist, ent_count, sizeof(entry_ident_t), compar);
+
+ qsort(estate.elist, estate.ent_count, sizeof(struct state_entry*), compar);
/* evict entries in listed order */
removed = 0;
- for (ent = 0; ent < ent_count; ent++) {
- struct store_entry *bse;
-
- bse = &BS_ENTRY(elist[ent], state);
+ for (ent = 0; ent < estate.ent_count; ent++) {
+ struct store_entry *bse = estate.elist[ent];
removed += bse->elem[ENTRY_ELEM_DATA].size;
removed += bse->elem[ENTRY_ELEM_META].size;
@@ -659,14 +633,55 @@ static nserror store_evict(struct store_state *state)
}
}
- free(elist);
+ free(estate.elist);
- NSLOG(netsurf, INFO, "removed %"PRIsizet" in %d entries", removed,
- ent);
+ NSLOG(netsurf, INFO,
+ "removed %"PRIsizet" in %"PRIsizet" entries, %"PRIu64" remaining in %"PRIsizet" entries",
+ removed, ent, state->total_alloc, old_count - ent);
return ret;
}
+/**
+ * Write a single store entry to disk
+ *
+ * To serialise a single store entry for now we write out a 32bit int
+ * which is the length of the url, then that many bytes of the url.
+ * Then we write out the full store entry struct as-is, which includes
+ * a useless nsurl pointer.
+ */
+static nserror
+write_entry(struct store_entry *ent, int fd)
+{
+ uint32_t len = strlen(nsurl_access(ent->url));
+ if (write(fd, &len, sizeof(len)) != sizeof(len))
+ return NSERROR_SAVE_FAILED;
+ if (write(fd, nsurl_access(ent->url), len) != (ssize_t)len)
+ return NSERROR_SAVE_FAILED;
+ if (write(fd, ent, sizeof(*ent)) != sizeof(*ent))
+ return NSERROR_SAVE_FAILED;
+
+ return NSERROR_OK;
+}
+
+typedef struct {
+ int fd;
+ size_t written;
+} write_entry_iteration_state;
+
+/**
+ * Callback for iterating the entries hashmap
+ */
+static bool
+write_entry_iterator(void *key, void *value, void *ctx)
+{
+ /* We ignore the key */
+ struct store_entry *ent = value;
+ write_entry_iteration_state *state = ctx;
+ state->written++;
+ /* We stop early if we fail to write this entry */
+ return write_entry(ent, state->fd) != NSERROR_OK;
+}
/**
* Write filesystem entries to file.
@@ -678,13 +693,13 @@ static nserror store_evict(struct store_state *state)
*/
static nserror write_entries(struct store_state *state)
{
- int fd;
char *tname = NULL; /* temporary file name for atomic replace */
char *fname = NULL; /* target filename */
- size_t entries_size;
- size_t written;
+ write_entry_iteration_state weistate;
nserror ret;
+ memset(&weistate, 0, sizeof(weistate));
+
if (state->entries_dirty == false) {
/* entries have not been updated since last write */
return NSERROR_OK;
@@ -695,25 +710,22 @@ static nserror write_entries(struct store_state *state)
return ret;
}
- fd = open(tname, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
- if (fd == -1) {
+ weistate.fd = open(tname, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
+ if (weistate.fd == -1) {
free(tname);
return NSERROR_SAVE_FAILED;
}
- entries_size = state->last_entry * sizeof(struct store_entry);
-
- written = (size_t)write(fd, state->entries, entries_size);
-
- close(fd);
-
- /* check all data was written */
- if (written != entries_size) {
+ if (hashmap_iterate(state->entries, write_entry_iterator, &weistate)) {
+ /* The iteration ended early, so we failed */
+ close(weistate.fd);
unlink(tname);
free(tname);
return NSERROR_SAVE_FAILED;
}
+ close(weistate.fd);
+
ret = netsurf_mkpath(&fname, NULL, 2, state->path, ENTRIES_FNAME);
if (ret != NSERROR_OK) {
unlink(tname);
@@ -730,6 +742,8 @@ static nserror write_entries(struct store_state *state)
return NSERROR_SAVE_FAILED;
}
+ NSLOG(netsurf, INFO, "Wrote out %"PRIsizet" entries", weistate.written);
+
return NSERROR_OK;
}
@@ -777,7 +791,7 @@ static nserror write_blocks(struct store_state *state)
&state->blocks[elem_idx][bfidx].use_map[0],
BLOCK_USE_MAP_SIZE);
if (wr != BLOCK_USE_MAP_SIZE) {
- NSLOG(netsurf, INFO,
+ NSLOG(netsurf, DEBUG,
"writing block file %d use index on file number %d failed",
elem_idx,
bfidx);
@@ -836,21 +850,21 @@ static nserror set_block_extents(struct store_state *state)
return NSERROR_OK;
}
- NSLOG(netsurf, INFO, "Starting");
+ NSLOG(netsurf, DEBUG, "Starting");
for (elem_idx = 0; elem_idx < ENTRY_ELEM_COUNT; elem_idx++) {
for (bfidx = 0; bfidx < BLOCK_FILE_COUNT; bfidx++) {
if (state->blocks[elem_idx][bfidx].fd != -1) {
/* ensure block file is correct extent */
ftr = ftruncate(state->blocks[elem_idx][bfidx].fd, 1U << (log2_block_size[elem_idx] + BLOCK_ENTRY_COUNT));
if (ftr == -1) {
- NSLOG(netsurf, INFO,
+ NSLOG(netsurf, ERROR,
"Truncate failed errno:%d",
errno);
}
}
}
}
- NSLOG(netsurf, INFO, "Complete");
+ NSLOG(netsurf, DEBUG, "Complete");
state->blocks_opened = false;
@@ -866,7 +880,7 @@ static nserror set_block_extents(struct store_state *state)
*
* \param s store state to maintain.
*/
-static void control_maintinance(void *s)
+static void control_maintenance(void *s)
{
struct store_state *state = s;
@@ -892,36 +906,22 @@ static void control_maintinance(void *s)
static nserror
get_store_entry(struct store_state *state, nsurl *url, struct store_entry **bse)
{
- entry_ident_t ident;
- unsigned int sei; /* store entry index */
-
- NSLOG(netsurf, INFO, "url:%s", nsurl_access(url));
+ struct store_entry *ent;
- /* use the url hash as the entry identifier */
- ident = nsurl_hash(url);
+ ent = hashmap_lookup(state->entries, url);
- sei = BS_ENTRY_INDEX(ident, state);
-
- if (sei == 0) {
- NSLOG(netsurf, INFO, "Failed to find ident 0x%x in index",
- ident);
- return NSERROR_NOT_FOUND;
- }
-
- if (state->entries[sei].ident != ident) {
- /* entry ident did not match */
- NSLOG(netsurf, INFO, "ident did not match entry");
+ if (ent == NULL) {
return NSERROR_NOT_FOUND;
}
- *bse = &state->entries[sei];
+ *bse = ent;
- state->entries[sei].last_used = time(NULL);
- state->entries[sei].use_count++;
+ ent->last_used = time(NULL);
+ ent->use_count++;
state->entries_dirty = true;
- guit->misc->schedule(CONTROL_MAINT_TIME, control_maintinance, state);
+ guit->misc->schedule(CONTROL_MAINT_TIME, control_maintenance, state);
return NSERROR_OK;
}
@@ -979,13 +979,11 @@ set_store_entry(struct store_state *state,
const size_t datalen,
struct store_entry **bse)
{
- entry_ident_t ident;
- entry_index_t sei; /* store entry index */
struct store_entry *se;
nserror ret;
struct store_entry_element *elem;
- NSLOG(netsurf, INFO, "url:%s", nsurl_access(url));
+ NSLOG(netsurf, DEBUG, "url:%s", nsurl_access(url));
/* evict entries as required and ensure there is at least one
* new entry available.
@@ -995,40 +993,12 @@ set_store_entry(struct store_state *state,
return ret;
}
- /* use the url hash as the entry identifier */
- ident = nsurl_hash(url);
-
- /* get the entry index from the ident */
- sei = BS_ENTRY_INDEX(ident, state);
- if (sei == 0) {
- /* allocating the next available entry */
- sei = state->last_entry;
- state->last_entry++;
- BS_ENTRY_INDEX(ident, state) = sei;
-
- /* the entry */
- se = &state->entries[sei];
-
- /* clear the new entry */
- memset(se, 0, sizeof(struct store_entry));
- } else {
- /* index found existing entry */
-
- /* the entry */
- se = &state->entries[sei];
-
- if (se->ident != ident) {
- /** @todo Is there a better heuristic than
- * first come, first served? Should we check
- * to see if the old entry is in use and if
- * not prefer the newly stored entry instead?
- */
- NSLOG(netsurf, INFO,
- "Entry index collision trying to replace %x with %x",
- se->ident,
- ident);
- return NSERROR_PERMISSION;
- }
+ se = hashmap_lookup(state->entries, url);
+ if (se == NULL) {
+ se = hashmap_insert(state->entries, url);
+ }
+ if (se == NULL) {
+ return NSERROR_NOMEM;
}
/* the entry element */
@@ -1039,13 +1009,12 @@ set_store_entry(struct store_state *state,
/* this entry cannot be removed as it has associated
* allocation.
*/
- NSLOG(netsurf, INFO,
+ NSLOG(netsurf, ERROR,
"attempt to overwrite entry with in use data");
return NSERROR_PERMISSION;
}
/* set the common entry data */
- se->ident = ident;
se->use_count = 1;
se->last_used = time(NULL);
@@ -1066,7 +1035,7 @@ set_store_entry(struct store_state *state,
/* ensure control maintenance scheduled. */
state->entries_dirty = true;
- guit->misc->schedule(CONTROL_MAINT_TIME, control_maintinance, state);
+ guit->misc->schedule(CONTROL_MAINT_TIME, control_maintenance, state);
*bse = se;
@@ -1099,7 +1068,7 @@ store_open(struct store_state *state,
fname = store_fname(state, ident, elem_idx);
if (fname == NULL) {
- NSLOG(netsurf, INFO, "filename error");
+ NSLOG(netsurf, ERROR, "filename error");
return -1;
}
@@ -1107,14 +1076,14 @@ store_open(struct store_state *state,
if (openflags & O_CREAT) {
ret = netsurf_mkdir_all(fname);
if (ret != NSERROR_OK) {
- NSLOG(netsurf, INFO,
+ NSLOG(netsurf, WARNING,
"file path \"%s\" could not be created", fname);
free(fname);
return -1;
}
}
- NSLOG(netsurf, INFO, "opening %s", fname);
+ NSLOG(netsurf, DEBUG, "opening %s", fname);
fd = open(fname, openflags, S_IRUSR | S_IWUSR);
free(fname);
@@ -1122,57 +1091,6 @@ store_open(struct store_state *state,
return fd;
}
-/**
- * Construct address ident to filesystem entry map
- *
- * To allow a filesystem entry to be found from it's identifier we
- * construct an mapping index. This is a hash map from the entries URL
- * (its unique key) to filesystem entry.
- *
- * As the entire entry list must be iterated over to construct the map
- * we also compute the total storage in use.
- *
- * @param state The backing store global state.
- * @return NSERROR_OK on success or NSERROR_NOMEM if the map storage
- * could not be allocated.
- */
-static nserror
-build_entrymap(struct store_state *state)
-{
- unsigned int eloop;
-
- NSLOG(netsurf, INFO, "Allocating %ld bytes for max of %d buckets",
- (1 << state->ident_bits) * sizeof(entry_index_t),
- 1 << state->ident_bits);
-
- state->addrmap = calloc(1 << state->ident_bits, sizeof(entry_index_t));
- if (state->addrmap == NULL) {
- return NSERROR_NOMEM;
- }
-
- state->total_alloc = 0;
-
- for (eloop = 1; eloop < state->last_entry; eloop++) {
-
- NSLOG(llcache, DEEPDEBUG,
- "entry:%d ident:0x%08x used:%d",
- eloop,
- BS_ADDRESS(state->entries[eloop].ident, state),
- state->entries[eloop].use_count);
-
- /* update the address map to point at the entry */
- BS_ENTRY_INDEX(state->entries[eloop].ident, state) = eloop;
-
- /* account for the storage space */
- state->total_alloc += state->entries[eloop].elem[ENTRY_ELEM_DATA].size;
- state->total_alloc += state->entries[eloop].elem[ENTRY_ELEM_META].size;
- /* ensure entry does not have any allocation state */
- state->entries[eloop].elem[ENTRY_ELEM_DATA].flags &= ~(ENTRY_ELEM_FLAG_HEAP | ENTRY_ELEM_FLAG_MMAP);
- state->entries[eloop].elem[ENTRY_ELEM_META].flags &= ~(ENTRY_ELEM_FLAG_HEAP | ENTRY_ELEM_FLAG_MMAP);
- }
-
- return NSERROR_OK;
-}
/**
* Unlink entries file
@@ -1206,46 +1124,84 @@ unlink_entries(struct store_state *state)
static nserror
read_entries(struct store_state *state)
{
- int fd;
- ssize_t rd;
- size_t entries_size;
char *fname = NULL;
+ char *url;
+ nsurl *nsurl;
nserror ret;
+ size_t read_entries = 0;
+ struct store_entry *ent;
+ int fd;
ret = netsurf_mkpath(&fname, NULL, 2, state->path, ENTRIES_FNAME);
if (ret != NSERROR_OK) {
return ret;
}
- entries_size = (1 << state->entry_bits) * sizeof(struct store_entry);
-
- NSLOG(netsurf, INFO,
- "Allocating %"PRIsizet" bytes for max of %d entries of %ld length elements %ld length",
- entries_size,
- 1 << state->entry_bits,
- sizeof(struct store_entry),
- sizeof(struct store_entry_element));
-
- state->entries = calloc(1, entries_size);
+ state->entries = hashmap_create(&entries_hashmap_parameters);
if (state->entries == NULL) {
free(fname);
return NSERROR_NOMEM;
}
fd = open(fname, O_RDWR);
- free(fname);
if (fd != -1) {
- rd = read(fd, state->entries, entries_size);
- close(fd);
- if (rd > 0) {
- state->last_entry = rd / sizeof(struct store_entry);
- NSLOG(netsurf, INFO, "Read %d entries",
- state->last_entry);
+ uint32_t urllen;
+ while (read(fd, &urllen, sizeof(urllen)) == sizeof(urllen)) {
+ url = calloc(1, urllen+1);
+ if (url == NULL) {
+ close(fd);
+ free(fname);
+ return NSERROR_NOMEM;
+ }
+ if (read(fd, url, urllen) != (ssize_t)urllen) {
+ free(url);
+ close(fd);
+ free(fname);
+ return NSERROR_INIT_FAILED;
+ }
+ ret = nsurl_create(url, &nsurl);
+ if (ret != NSERROR_OK) {
+ free(url);
+ close(fd);
+ free(fname);
+ return ret;
+ }
+ free(url);
+ /* We have to be careful here about nsurl refs */
+ ent = hashmap_insert(state->entries, nsurl);
+ if (ent == NULL) {
+ nsurl_unref(nsurl);
+ close(fd);
+ free(fname);
+ return NSERROR_NOMEM;
+ }
+ /* At this point, ent actually owns a ref of nsurl */
+ if (read(fd, ent, sizeof(*ent)) != sizeof(*ent)) {
+ /* The read failed, so reset the ptr */
+ ent->url = nsurl; /* It already had a ref */
+ nsurl_unref(nsurl);
+ close(fd);
+ free(fname);
+ return NSERROR_INIT_FAILED;
+ }
+ ent->url = nsurl; /* It already owns a ref */
+ nsurl_unref(nsurl);
+ NSLOG(netsurf, DEBUG, "Successfully read entry for %s", nsurl_access(ent->url));
+ read_entries++;
+ /* Note the size allocation */
+ state->total_alloc += ent->elem[ENTRY_ELEM_DATA].size;
+ state->total_alloc += ent->elem[ENTRY_ELEM_META].size;
+ /* And ensure we don't pretend to have this in memory yet */
+ ent->elem[ENTRY_ELEM_DATA].flags &= ~(ENTRY_ELEM_FLAG_HEAP | ENTRY_ELEM_FLAG_MMAP);
+ ent->elem[ENTRY_ELEM_META].flags &= ~(ENTRY_ELEM_FLAG_HEAP | ENTRY_ELEM_FLAG_MMAP);
+
}
- } else {
- /* could rebuild entries from fs */
- state->last_entry = 1;
+ close(fd);
}
+
+ NSLOG(netsurf, INFO, "Read %"PRIsizet" entries from cache", read_entries);
+
+ free(fname);
return NSERROR_OK;
}
@@ -1283,7 +1239,7 @@ read_blocks(struct store_state *state)
&state->blocks[elem_idx][bfidx].use_map[0],
BLOCK_USE_MAP_SIZE);
if (rd <= 0) {
- NSLOG(netsurf, INFO,
+ NSLOG(netsurf, ERROR,
"reading block file %d use index on file number %d failed",
elem_idx,
bfidx);
@@ -1382,9 +1338,6 @@ write_control(struct store_state *state)
}
fprintf(fcontrol, "%u%c", CONTROL_VERSION, 0);
- fprintf(fcontrol, "%u%c", state->entry_bits, 0);
- fprintf(fcontrol, "%u%c", state->ident_bits, 0);
- fprintf(fcontrol, "%u%c", state->last_entry, 0);
fclose(fcontrol);
@@ -1404,8 +1357,6 @@ read_control(struct store_state *state)
nserror ret;
FILE *fcontrol;
unsigned int ctrlversion;
- unsigned int addrbits;
- unsigned int entrybits;
char *fname = NULL;
ret = netsurf_mkpath(&fname, NULL, 2, state->path, "control");
@@ -1443,27 +1394,8 @@ read_control(struct store_state *state)
goto control_error;
}
- /* second line is log2 max number of entries */
- if (fscanf(fcontrol, "%u", &entrybits) != 1) {
- goto control_error;
- }
- if (fgetc(fcontrol) != 0) {
- goto control_error;
- }
-
- /* second line is log2 size of address hash */
- if (fscanf(fcontrol, "%u", &addrbits) != 1) {
- goto control_error;
- }
- if (fgetc(fcontrol) != 0) {
- goto control_error;
- }
-
fclose(fcontrol);
- state->entry_bits = entrybits;
- state->ident_bits = addrbits;
-
return NSERROR_OK;
control_error: /* problem with the control file */
@@ -1515,23 +1447,25 @@ initialise(const struct llcache_store_parameters *parameters)
newstate->limit = parameters->limit;
newstate->hysteresis = parameters->hysteresis;
- if (parameters->address_size == 0) {
- newstate->ident_bits = DEFAULT_IDENT_SIZE;
- } else {
- newstate->ident_bits = parameters->address_size;
- }
-
- if (parameters->entry_size == 0) {
- newstate->entry_bits = DEFAULT_ENTRY_SIZE;
- } else {
- newstate->entry_bits = parameters->entry_size;
- }
-
/* read store control and create new if required */
ret = read_control(newstate);
if (ret != NSERROR_OK) {
- NSLOG(netsurf, INFO, "read control failed %s",
- messages_get_errorcode(ret));
+ if (ret == NSERROR_NOT_FOUND) {
+ NSLOG(netsurf, INFO, "cache control file not found, making fresh");
+ } else {
+ NSLOG(netsurf, ERROR, "read control failed %s",
+ messages_get_errorcode(ret));
+ ret = netsurf_recursive_rm(newstate->path);
+ if (ret != NSERROR_OK) {
+ NSLOG(netsurf, WARNING, "Error `%s` while removing `%s`",
+ messages_get_errorcode(ret), newstate->path);
+ NSLOG(netsurf, WARNING, "Unable to clean up partial cache state.");
+ NSLOG(netsurf, WARNING, "Funky behaviour may ensue.");
+ } else {
+ NSLOG(netsurf, INFO, "Successfully removed old cache from `%s`",
+ newstate->path);
+ }
+ }
ret = write_control(newstate);
if (ret == NSERROR_OK) {
unlink_entries(newstate);
@@ -1545,13 +1479,6 @@ initialise(const struct llcache_store_parameters *parameters)
return ret;
}
- /* ensure the maximum number of entries can be represented in
- * the type available to store it.
- */
- if (newstate->entry_bits > (8 * sizeof(entry_index_t))) {
- newstate->entry_bits = (8 * sizeof(entry_index_t));
- }
-
/* read filesystem entries */
ret = read_entries(newstate);
if (ret != NSERROR_OK) {
@@ -1561,21 +1488,11 @@ initialise(const struct llcache_store_parameters *parameters)
return ret;
}
- /* build entry hash map */
- ret = build_entrymap(newstate);
- if (ret != NSERROR_OK) {
- /* that obviously went well */
- free(newstate->entries);
- free(newstate->path);
- free(newstate);
- return ret;
- }
-
+ /* read blocks */
ret = read_blocks(newstate);
if (ret != NSERROR_OK) {
/* oh dear */
- free(newstate->addrmap);
- free(newstate->entries);
+ hashmap_destroy(newstate->entries);
free(newstate->path);
free(newstate);
return ret;
@@ -1586,12 +1503,10 @@ initialise(const struct llcache_store_parameters *parameters)
NSLOG(netsurf, INFO, "FS backing store init successful");
NSLOG(netsurf, INFO,
- "path:%s limit:%"PRIsizet" hyst:%"PRIsizet" addr:%d entries:%d",
+ "path:%s limit:%"PRIsizet" hyst:%"PRIsizet,
newstate->path,
newstate->limit,
- newstate->hysteresis,
- newstate->ident_bits,
- newstate->entry_bits);
+ newstate->hysteresis);
NSLOG(netsurf, INFO, "Using %"PRIu64"/%"PRIsizet,
newstate->total_alloc, newstate->limit);
@@ -1614,7 +1529,7 @@ finalise(void)
unsigned int op_count;
if (storestate != NULL) {
- guit->misc->schedule(-1, control_maintinance, storestate);
+ guit->misc->schedule(-1, control_maintenance, storestate);
write_entries(storestate);
write_blocks(storestate);
@@ -1643,8 +1558,7 @@ finalise(void)
0);
}
- free(storestate->addrmap);
- free(storestate->entries);
+ hashmap_destroy(storestate->entries);
free(storestate->path);
free(storestate);
storestate = NULL;
@@ -1676,7 +1590,7 @@ static nserror store_write_block(struct store_state *state,
state->blocks[elem_idx][bf].fd = store_open(state, bf,
elem_idx + ENTRY_ELEM_COUNT, O_CREAT | O_RDWR);
if (state->blocks[elem_idx][bf].fd == -1) {
- NSLOG(netsurf, INFO, "Open failed errno %d", errno);
+ NSLOG(netsurf, ERROR, "Open failed errno %d", errno);
return NSERROR_SAVE_FAILED;
}
@@ -1687,24 +1601,24 @@ static nserror store_write_block(struct store_state *state,
offst = (unsigned int)bi << log2_block_size[elem_idx];
wr = nsu_pwrite(state->blocks[elem_idx][bf].fd,
- bse->elem[elem_idx].data,
- bse->elem[elem_idx].size,
- offst);
+ bse->elem[elem_idx].data,
+ bse->elem[elem_idx].size,
+ offst);
if (wr != (ssize_t)bse->elem[elem_idx].size) {
- NSLOG(netsurf, INFO,
- "Write failed %"PRIssizet" of %d bytes from %p at 0x%jx block %d errno %d",
+ NSLOG(netsurf, ERROR,
+ "Write failed %"PRIssizet" of %"PRId32" bytes from %p at %"PRIsizet" block %"PRIu16" errno %d",
wr,
bse->elem[elem_idx].size,
bse->elem[elem_idx].data,
- (uintmax_t)offst,
+ (size_t)offst,
bse->elem[elem_idx].block,
errno);
return NSERROR_SAVE_FAILED;
}
NSLOG(netsurf, INFO,
- "Wrote %"PRIssizet" bytes from %p at 0x%jx block %d", wr,
- bse->elem[elem_idx].data, (uintmax_t)offst,
+ "Wrote %"PRIssizet" bytes from %p at %"PRIsizet" block %d", wr,
+ bse->elem[elem_idx].data, (size_t)offst,
bse->elem[elem_idx].block);
return NSERROR_OK;
@@ -1726,10 +1640,10 @@ static nserror store_write_file(struct store_state *state,
int fd;
int err;
- fd = store_open(state, bse->ident, elem_idx, O_CREAT | O_WRONLY);
+ fd = store_open(state, nsurl_hash(bse->url), elem_idx, O_CREAT | O_WRONLY);
if (fd < 0) {
perror("");
- NSLOG(netsurf, INFO, "Open failed %d errno %d", fd, errno);
+ NSLOG(netsurf, ERROR, "Open failed %d errno %d", fd, errno);
return NSERROR_SAVE_FAILED;
}
@@ -1738,8 +1652,8 @@ static nserror store_write_file(struct store_state *state,
close(fd);
if (wr != (ssize_t)bse->elem[elem_idx].size) {
- NSLOG(netsurf, INFO,
- "Write failed %"PRIssizet" of %d bytes from %p errno %d",
+ NSLOG(netsurf, ERROR,
+ "Write failed %"PRIssizet" of %"PRId32" bytes from %p errno %d",
wr,
bse->elem[elem_idx].size,
bse->elem[elem_idx].data,
@@ -1749,7 +1663,7 @@ static nserror store_write_file(struct store_state *state,
return NSERROR_SAVE_FAILED;
}
- NSLOG(netsurf, INFO, "Wrote %"PRIssizet" bytes from %p", wr,
+ NSLOG(netsurf, VERBOSE, "Wrote %"PRIssizet" bytes from %p", wr,
bse->elem[elem_idx].data);
return NSERROR_OK;
@@ -1791,7 +1705,7 @@ store(nsurl *url,
/* set the store entry up */
ret = set_store_entry(storestate, url, elem_idx, data, datalen, &bse);
if (ret != NSERROR_OK) {
- NSLOG(netsurf, INFO, "store entry setting failed");
+ NSLOG(netsurf, ERROR, "store entry setting failed");
return ret;
}
@@ -1814,7 +1728,7 @@ static nserror entry_release_alloc(struct store_entry_element *elem)
if ((elem->flags & ENTRY_ELEM_FLAG_HEAP) != 0) {
elem->ref--;
if (elem->ref == 0) {
- NSLOG(netsurf, INFO, "freeing %p", elem->data);
+ NSLOG(netsurf, DEEPDEBUG, "freeing %p", elem->data);
free(elem->data);
elem->flags &= ~ENTRY_ELEM_FLAG_HEAP;
}
@@ -1846,7 +1760,7 @@ static nserror store_read_block(struct store_state *state,
state->blocks[elem_idx][bf].fd = store_open(state, bf,
elem_idx + ENTRY_ELEM_COUNT, O_CREAT | O_RDWR);
if (state->blocks[elem_idx][bf].fd == -1) {
- NSLOG(netsurf, INFO, "Open failed errno %d", errno);
+ NSLOG(netsurf, ERROR, "Open failed errno %d", errno);
return NSERROR_SAVE_FAILED;
}
@@ -1857,24 +1771,24 @@ static nserror store_read_block(struct store_state *state,
offst = (unsigned int)bi << log2_block_size[elem_idx];
rd = nsu_pread(state->blocks[elem_idx][bf].fd,
- bse->elem[elem_idx].data,
- bse->elem[elem_idx].size,
- offst);
+ bse->elem[elem_idx].data,
+ bse->elem[elem_idx].size,
+ offst);
if (rd != (ssize_t)bse->elem[elem_idx].size) {
- NSLOG(netsurf, INFO,
- "Failed reading %"PRIssizet" of %d bytes into %p from 0x%jx block %d errno %d",
+ NSLOG(netsurf, ERROR,
+ "Failed reading %"PRIssizet" of %"PRId32" bytes into %p from %"PRIsizet" block %"PRIu16" errno %d",
rd,
bse->elem[elem_idx].size,
bse->elem[elem_idx].data,
- (uintmax_t)offst,
+ (size_t)offst,
bse->elem[elem_idx].block,
errno);
return NSERROR_SAVE_FAILED;
}
- NSLOG(netsurf, INFO,
- "Read %"PRIssizet" bytes into %p from 0x%jx block %d", rd,
- bse->elem[elem_idx].data, (uintmax_t)offst,
+ NSLOG(netsurf, DEEPDEBUG,
+ "Read %"PRIssizet" bytes into %p from %"PRIsizet" block %d", rd,
+ bse->elem[elem_idx].data, (size_t)offst,
bse->elem[elem_idx].block);
return NSERROR_OK;
@@ -1898,9 +1812,9 @@ static nserror store_read_file(struct store_state *state,
size_t tot = 0; /* total size */
/* separate file in backing store */
- fd = store_open(storestate, bse->ident, elem_idx, O_RDONLY);
+ fd = store_open(storestate, nsurl_hash(bse->url), elem_idx, O_RDONLY);
if (fd < 0) {
- NSLOG(netsurf, INFO, "Open failed %d errno %d", fd, errno);
+ NSLOG(netsurf, ERROR, "Open failed %d errno %d", fd, errno);
/** @todo should this invalidate the entry? */
return NSERROR_NOT_FOUND;
}
@@ -1910,7 +1824,7 @@ static nserror store_read_file(struct store_state *state,
bse->elem[elem_idx].data + tot,
bse->elem[elem_idx].size - tot);
if (rd <= 0) {
- NSLOG(netsurf, INFO,
+ NSLOG(netsurf, ERROR,
"read error returned %"PRIssizet" errno %d",
rd,
errno);
@@ -1922,7 +1836,7 @@ static nserror store_read_file(struct store_state *state,
close(fd);
- NSLOG(netsurf, INFO, "Read %"PRIsizet" bytes into %p", tot,
+ NSLOG(netsurf, DEEPDEBUG, "Read %"PRIsizet" bytes into %p", tot,
bse->elem[elem_idx].data);
return ret;
@@ -1956,13 +1870,13 @@ fetch(nsurl *url,
/* fetch store entry */
ret = get_store_entry(storestate, url, &bse);
if (ret != NSERROR_OK) {
- NSLOG(netsurf, INFO, "entry not found");
+ NSLOG(netsurf, DEBUG, "Entry for %s not found", nsurl_access(url));
storestate->miss_count++;
return ret;
}
storestate->hit_count++;
- NSLOG(netsurf, INFO, "retrieving cache data for url:%s",
+ NSLOG(netsurf, DEBUG, "retrieving cache data for url:%s",
nsurl_access(url));
/* calculate the entry element index */
@@ -1978,7 +1892,7 @@ fetch(nsurl *url,
/* use the existing allocation and bump the ref count. */
elem->ref++;
- NSLOG(netsurf, INFO,
+ NSLOG(netsurf, DEEPDEBUG,
"Using existing entry (%p) allocation %p refs:%d", bse,
elem->data, elem->ref);
@@ -1986,11 +1900,11 @@ fetch(nsurl *url,
/* allocate from the heap */
elem->data = malloc(elem->size);
if (elem->data == NULL) {
- NSLOG(netsurf, INFO,
+ NSLOG(netsurf, ERROR,
"Failed to create new heap allocation");
return NSERROR_NOMEM;
}
- NSLOG(netsurf, INFO, "Created new heap allocation %p",
+ NSLOG(netsurf, DEEPDEBUG, "Created new heap allocation %p",
elem->data);
/* mark the entry as having a valid heap allocation */
@@ -2040,7 +1954,7 @@ static nserror release(nsurl *url, enum backing_store_flags bsflags)
ret = get_store_entry(storestate, url, &bse);
if (ret != NSERROR_OK) {
- NSLOG(netsurf, INFO, "entry not found");
+ NSLOG(netsurf, WARNING, "entry not found");
return ret;
}
diff --git a/content/handlers/Makefile b/content/handlers/Makefile
index 2f2da3aed..ea9d0c84d 100644
--- a/content/handlers/Makefile
+++ b/content/handlers/Makefile
@@ -13,4 +13,15 @@ include content/handlers/javascript/Makefile
S_CONTENT += $(addprefix handlers/javascript/,$(S_JAVASCRIPT))
+# HTML content handler sources
+include content/handlers/html/Makefile
+
+S_CONTENT += $(addprefix handlers/html/,$(S_HTML))
+
+# Text content handler sources
+include content/handlers/text/Makefile
+
+S_CONTENT += $(addprefix handlers/text/,$(S_TEXT))
+
+# extend the include search path
INCLUDE_DIRS += content/handlers
diff --git a/content/handlers/css/Makefile b/content/handlers/css/Makefile
index bbfc8d7b4..d5cf16647 100644
--- a/content/handlers/css/Makefile
+++ b/content/handlers/css/Makefile
@@ -1,4 +1,4 @@
# CSS sources
-S_CSS := css.c dump.c internal.c hints.c select.c utils.c
+S_CSS := css.c dump.c internal.c hints.c select.c
diff --git a/content/handlers/css/css.c b/content/handlers/css/css.c
index 93efd6a1b..f9197ddfe 100644
--- a/content/handlers/css/css.c
+++ b/content/handlers/css/css.c
@@ -16,19 +16,22 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <string.h>
#include <assert.h>
#include <libwapcaplet/libwapcaplet.h>
#include <dom/dom.h>
-#include "content/content_protected.h"
-#include "content/fetch.h"
-#include "content/hlcache.h"
-#include "desktop/system_colour.h"
+#include "utils/errors.h"
#include "utils/corestrings.h"
#include "utils/utils.h"
#include "utils/http.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "content/content_protected.h"
+#include "content/content_factory.h"
+#include "content/fetch.h"
+#include "content/hlcache.h"
+#include "desktop/system_colour.h"
#include "css/css.h"
#include "css/hints.h"
@@ -37,6 +40,9 @@
/* Define to trace import fetches */
#undef NSCSS_IMPORT_TRACE
+/** Screen DPI in fixed point units: defaults to 90, which RISC OS uses */
+css_fixed nscss_screen_dpi = F_90;
+
struct content_css_data;
/**
@@ -80,8 +86,6 @@ typedef struct {
* imports array */
} nscss_import_ctx;
-static bool nscss_process_data(struct content *c, const char *data,
- unsigned int size);
static bool nscss_convert(struct content *c);
static void nscss_destroy(struct content *c);
static nserror nscss_clone(const struct content *old, struct content **newc);
@@ -98,7 +102,7 @@ static void nscss_destroy_css_data(struct content_css_data *c);
static void nscss_content_done(struct content_css_data *css, void *pw);
static css_error nscss_handle_import(void *pw, css_stylesheet *parent,
- lwc_string *url, uint64_t media);
+ lwc_string *url);
static nserror nscss_import(hlcache_handle *handle,
const hlcache_event *event, void *pw);
static css_error nscss_import_complete(nscss_import_ctx *ctx);
@@ -170,7 +174,7 @@ nscss_create(const content_handler *handler,
xnsbase, charset, result->base.quirks,
nscss_content_done, result);
if (error != NSERROR_OK) {
- content_broadcast_errorcode(&result->base, NSERROR_NOMEM);
+ content_broadcast_error(&result->base, NSERROR_NOMEM, NULL);
if (charset_value != NULL)
lwc_string_unref(charset_value);
free(result);
@@ -245,14 +249,15 @@ static nserror nscss_create_css_data(struct content_css_data *c,
* \param size Number of bytes to process
* \return true on success, false on failure
*/
-bool nscss_process_data(struct content *c, const char *data, unsigned int size)
+static bool
+nscss_process_data(struct content *c, const char *data, unsigned int size)
{
nscss_content *css = (nscss_content *) c;
css_error error;
error = nscss_process_css_data(&css->data, data, size);
if (error != CSS_OK && error != CSS_NEEDDATA) {
- content_broadcast_errorcode(c, NSERROR_CSS);
+ content_broadcast_error(c, NSERROR_CSS, NULL);
}
return (error == CSS_OK || error == CSS_NEEDDATA);
@@ -286,7 +291,7 @@ bool nscss_convert(struct content *c)
error = nscss_convert_css_data(&css->data);
if (error != CSS_OK) {
- content_broadcast_errorcode(c, NSERROR_CSS);
+ content_broadcast_error(c, NSERROR_CSS, NULL);
return false;
}
@@ -374,8 +379,8 @@ nserror nscss_clone(const struct content *old, struct content **newc)
{
const nscss_content *old_css = (const nscss_content *) old;
nscss_content *new_css;
- const char *data;
- unsigned long size;
+ const uint8_t *data;
+ size_t size;
nserror error;
new_css = calloc(1, sizeof(nscss_content));
@@ -402,7 +407,9 @@ nserror nscss_clone(const struct content *old, struct content **newc)
data = content__get_source_data(&new_css->base, &size);
if (size > 0) {
- if (nscss_process_data(&new_css->base, data, size) == false) {
+ if (nscss_process_data(&new_css->base,
+ (char *)data,
+ (unsigned int)size) == false) {
content_destroy(&new_css->base);
return NSERROR_CLONE_FAILED;
}
@@ -479,7 +486,7 @@ void nscss_content_done(struct content_css_data *css, void *pw)
/* Retrieve the size of this sheet */
error = css_stylesheet_size(css->sheet, &size);
if (error != CSS_OK) {
- content_broadcast_errorcode(c, NSERROR_CSS);
+ content_broadcast_error(c, NSERROR_CSS, NULL);
content_set_error(c);
return;
}
@@ -512,11 +519,10 @@ void nscss_content_done(struct content_css_data *css, void *pw)
* \param pw CSS object requesting the import
* \param parent Stylesheet requesting the import
* \param url URL of the imported sheet
- * \param media Applicable media for the imported sheet
* \return CSS_OK on success, appropriate error otherwise
*/
css_error nscss_handle_import(void *pw, css_stylesheet *parent,
- lwc_string *url, uint64_t media)
+ lwc_string *url)
{
content_type accept = CONTENT_CSS;
struct content_css_data *c = pw;
@@ -562,7 +568,6 @@ css_error nscss_handle_import(void *pw, css_stylesheet *parent,
}
/* Create content */
- c->imports[c->import_count].media = media;
/** \todo Why aren't we getting a relative url part, to join? */
nerror = nsurl_create(lwc_string_data(url), &ns_url);
@@ -635,7 +640,6 @@ nserror nscss_import(hlcache_handle *handle,
error = nscss_import_complete(ctx);
break;
- case CONTENT_MSG_ERRORCODE:
case CONTENT_MSG_ERROR:
hlcache_handle_release(handle);
ctx->css->imports[ctx->index].c = NULL;
@@ -643,7 +647,6 @@ nserror nscss_import(hlcache_handle *handle,
error = nscss_import_complete(ctx);
/* Already released handle */
break;
-
default:
break;
}
diff --git a/content/handlers/css/css.h b/content/handlers/css/css.h
index 4b38829f0..5e2b64a38 100644
--- a/content/handlers/css/css.h
+++ b/content/handlers/css/css.h
@@ -32,7 +32,6 @@ struct hlcache_handle;
*/
struct nscss_import {
struct hlcache_handle *c; /**< Content containing sheet */
- uint64_t media; /**< Media types that sheet applies to */
};
/**
diff --git a/content/handlers/css/dump.c b/content/handlers/css/dump.c
index b12e1d9e8..950a6f8cc 100644
--- a/content/handlers/css/dump.c
+++ b/content/handlers/css/dump.c
@@ -19,6 +19,8 @@
#include <stdio.h>
#include <libcss/libcss.h>
+#include "netsurf/inttypes.h"
+
#include "css/dump.h"
#include "css/utils.h"
@@ -36,7 +38,7 @@ static void dump_css_fixed(FILE *stream, css_fixed f)
uint32_t fracpart = ((NSCSS_ABS(f) & 0x3ff) * 1000 + 500) / (1 << 10);
#undef NSCSS_ABS
- fprintf(stream, "%s%d.%03d", f < 0 ? "-" : "", uintpart, fracpart);
+ fprintf(stream, "%s%"PRIu32".%03"PRIu32, f < 0 ? "-" : "", uintpart, fracpart);
}
/**
@@ -48,7 +50,7 @@ static void dump_css_fixed(FILE *stream, css_fixed f)
static void dump_css_number(FILE *stream, css_fixed val)
{
if (INTTOFIX(FIXTOINT(val)) == val)
- fprintf(stream, "%d", FIXTOINT(val));
+ fprintf(stream, "%"PRId32, FIXTOINT(val));
else
dump_css_fixed(stream, val);
}
@@ -113,24 +115,15 @@ static void dump_css_unit(FILE *stream, css_fixed val, css_unit unit)
case CSS_UNIT_KHZ:
fprintf(stream, "kHz");
break;
- case CSS_UNIT_CAP:
- fprintf(stream, "cap");
- break;
case CSS_UNIT_CH:
fprintf(stream, "ch");
break;
- case CSS_UNIT_IC:
- fprintf(stream, "ic");
- break;
case CSS_UNIT_REM:
fprintf(stream, "rem");
break;
case CSS_UNIT_LH:
fprintf(stream, "lh");
break;
- case CSS_UNIT_RLH:
- fprintf(stream, "rlh");
- break;
case CSS_UNIT_VH:
fprintf(stream, "vh");
break;
@@ -190,7 +183,7 @@ void nscss_dump_computed_style(FILE *stream, const css_computed_style *style)
val = css_computed_background_color(style, &color);
switch (val) {
case CSS_BACKGROUND_COLOR_COLOR:
- fprintf(stream, "background-color: #%08x ", color);
+ fprintf(stream, "background-color: #%08"PRIx32" ", color);
break;
default:
break;
@@ -264,7 +257,7 @@ void nscss_dump_computed_style(FILE *stream, const css_computed_style *style)
val = css_computed_border_top_color(style, &color);
switch (val) {
case CSS_BORDER_COLOR_COLOR:
- fprintf(stream, "border-top-color: #%08x ", color);
+ fprintf(stream, "border-top-color: #%08"PRIx32" ", color);
break;
default:
break;
@@ -274,7 +267,7 @@ void nscss_dump_computed_style(FILE *stream, const css_computed_style *style)
val = css_computed_border_right_color(style, &color);
switch (val) {
case CSS_BORDER_COLOR_COLOR:
- fprintf(stream, "border-right-color: #%08x ", color);
+ fprintf(stream, "border-right-color: #%08"PRIx32" ", color);
break;
default:
break;
@@ -284,7 +277,7 @@ void nscss_dump_computed_style(FILE *stream, const css_computed_style *style)
val = css_computed_border_bottom_color(style, &color);
switch (val) {
case CSS_BORDER_COLOR_COLOR:
- fprintf(stream, "border-bottom-color: #%08x ", color);
+ fprintf(stream, "border-bottom-color: #%08"PRIx32" ", color);
break;
default:
break;
@@ -294,7 +287,7 @@ void nscss_dump_computed_style(FILE *stream, const css_computed_style *style)
val = css_computed_border_left_color(style, &color);
switch (val) {
case CSS_BORDER_COLOR_COLOR:
- fprintf(stream, "border-left-color: #%08x ", color);
+ fprintf(stream, "border-left-color: #%08"PRIx32" ", color);
break;
default:
break;
@@ -619,7 +612,7 @@ void nscss_dump_computed_style(FILE *stream, const css_computed_style *style)
/* color */
val = css_computed_color(style, &color);
if (val == CSS_COLOR_COLOR) {
- fprintf(stream, "color: #%08x ", color);
+ fprintf(stream, "color: #%08"PRIx32" ", color);
}
/* content */
@@ -873,6 +866,12 @@ void nscss_dump_computed_style(FILE *stream, const css_computed_style *style)
case CSS_DISPLAY_NONE:
fprintf(stream, "display: none ");
break;
+ case CSS_DISPLAY_FLEX:
+ fprintf(stream, "display: flex ");
+ break;
+ case CSS_DISPLAY_INLINE_FLEX:
+ fprintf(stream, "display: inline-flex ");
+ break;
default:
break;
}
@@ -1356,7 +1355,7 @@ void nscss_dump_computed_style(FILE *stream, const css_computed_style *style)
fprintf(stream, "outline-color: invert ");
break;
case CSS_OUTLINE_COLOR_COLOR:
- fprintf(stream, "outline-color: #%08x ", color);
+ fprintf(stream, "outline-color: #%08"PRIx32" ", color);
break;
default:
break;
@@ -1823,7 +1822,7 @@ void nscss_dump_computed_style(FILE *stream, const css_computed_style *style)
fprintf(stream, "z-index: auto ");
break;
case CSS_Z_INDEX_SET:
- fprintf(stream, "z-index: %d ", zindex);
+ fprintf(stream, "z-index: %"PRId32" ", zindex);
break;
default:
break;
diff --git a/content/handlers/css/hints.c b/content/handlers/css/hints.c
index 3a15f8e08..0f246a64c 100644
--- a/content/handlers/css/hints.c
+++ b/content/handlers/css/hints.c
@@ -607,12 +607,12 @@ static void css_hint_clean(void)
hint_ctx.len = 0;
}
-static inline struct css_hint * css_hint_advance(struct css_hint *hint)
+static inline void css_hint_advance(struct css_hint **hint)
{
hint_ctx.len++;
assert(hint_ctx.len < MAX_HINTS_PER_ELEMENT);
- return ++hint;
+ (*hint)++;
}
static void css_hint_get_hints(struct css_hint **hints, uint32_t *nhints)
@@ -671,7 +671,7 @@ static void css_hint_table_cell_border_padding(
hint_prop++) {
hint->prop = hint_prop;
hint->status = CSS_BORDER_STYLE_INSET;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
for (hint_prop = CSS_PROP_BORDER_TOP_WIDTH;
@@ -681,7 +681,7 @@ static void css_hint_table_cell_border_padding(
hint->data.length.value = INTTOFIX(1);
hint->data.length.unit = CSS_UNIT_PX;
hint->status = CSS_BORDER_WIDTH_WIDTH;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
}
dom_string_unref(attr);
@@ -704,7 +704,7 @@ static void css_hint_table_cell_border_padding(
hint->prop = hint_prop;
hint->data.color = hint_color;
hint->status = CSS_BORDER_COLOR_COLOR;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
}
dom_string_unref(attr);
@@ -729,7 +729,7 @@ static void css_hint_table_cell_border_padding(
hint->data.length.value = hint_length.value;
hint->data.length.unit = hint_length.unit;
hint->status = CSS_PADDING_SET;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
}
dom_string_unref(attr);
@@ -754,25 +754,25 @@ static void css_hint_vertical_align_table_cells(
corestring_lwc_top)) {
hint->prop = CSS_PROP_VERTICAL_ALIGN;
hint->status = CSS_VERTICAL_ALIGN_TOP;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
} else if (dom_string_caseless_lwc_isequal(attr,
corestring_lwc_middle)) {
hint->prop = CSS_PROP_VERTICAL_ALIGN;
hint->status = CSS_VERTICAL_ALIGN_MIDDLE;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
} else if (dom_string_caseless_lwc_isequal(attr,
corestring_lwc_bottom)) {
hint->prop = CSS_PROP_VERTICAL_ALIGN;
hint->status = CSS_VERTICAL_ALIGN_BOTTOM;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
} else if (dom_string_caseless_lwc_isequal(attr,
corestring_lwc_baseline)) {
hint->prop = CSS_PROP_VERTICAL_ALIGN;
hint->status = CSS_VERTICAL_ALIGN_BASELINE;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(attr);
}
@@ -794,7 +794,7 @@ static void css_hint_vertical_align_replaced(
corestring_lwc_top)) {
hint->prop = CSS_PROP_VERTICAL_ALIGN;
hint->status = CSS_VERTICAL_ALIGN_TOP;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
} else if (dom_string_caseless_lwc_isequal(attr,
corestring_lwc_bottom) ||
@@ -802,13 +802,13 @@ static void css_hint_vertical_align_replaced(
corestring_lwc_baseline)) {
hint->prop = CSS_PROP_VERTICAL_ALIGN;
hint->status = CSS_VERTICAL_ALIGN_BASELINE;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
} else if (dom_string_caseless_lwc_isequal(attr,
corestring_lwc_texttop)) {
hint->prop = CSS_PROP_VERTICAL_ALIGN;
hint->status = CSS_VERTICAL_ALIGN_TEXT_TOP;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
} else if (dom_string_caseless_lwc_isequal(attr,
corestring_lwc_absmiddle) ||
@@ -816,7 +816,7 @@ static void css_hint_vertical_align_replaced(
corestring_lwc_abscenter)) {
hint->prop = CSS_PROP_VERTICAL_ALIGN;
hint->status = CSS_VERTICAL_ALIGN_MIDDLE;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(attr);
}
@@ -837,25 +837,25 @@ static void css_hint_text_align_normal(
corestring_lwc_left)) {
hint->prop = CSS_PROP_TEXT_ALIGN;
hint->status = CSS_TEXT_ALIGN_LEFT;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
} else if (dom_string_caseless_lwc_isequal(align,
corestring_lwc_center)) {
hint->prop = CSS_PROP_TEXT_ALIGN;
hint->status = CSS_TEXT_ALIGN_CENTER;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
} else if (dom_string_caseless_lwc_isequal(align,
corestring_lwc_right)) {
hint->prop = CSS_PROP_TEXT_ALIGN;
hint->status = CSS_TEXT_ALIGN_RIGHT;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
} else if (dom_string_caseless_lwc_isequal(align,
corestring_lwc_justify)) {
hint->prop = CSS_PROP_TEXT_ALIGN;
hint->status = CSS_TEXT_ALIGN_JUSTIFY;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(align);
}
@@ -869,7 +869,7 @@ static void css_hint_text_align_center(
hint->prop = CSS_PROP_TEXT_ALIGN;
hint->status = CSS_TEXT_ALIGN_LIBCSS_CENTER;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
static void css_hint_margin_left_right_align_center(
@@ -895,11 +895,11 @@ static void css_hint_margin_left_right_align_center(
corestring_lwc_absmiddle)) {
hint->prop = CSS_PROP_MARGIN_LEFT;
hint->status = CSS_MARGIN_AUTO;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
hint->prop = CSS_PROP_MARGIN_RIGHT;
hint->status = CSS_MARGIN_AUTO;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(attr);
}
@@ -921,25 +921,25 @@ static void css_hint_text_align_special(
corestring_lwc_center)) {
hint->prop = CSS_PROP_TEXT_ALIGN;
hint->status = CSS_TEXT_ALIGN_LIBCSS_CENTER;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
} else if (dom_string_caseless_lwc_isequal(align,
corestring_lwc_left)) {
hint->prop = CSS_PROP_TEXT_ALIGN;
hint->status = CSS_TEXT_ALIGN_LIBCSS_LEFT;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
} else if (dom_string_caseless_lwc_isequal(align,
corestring_lwc_right)) {
hint->prop = CSS_PROP_TEXT_ALIGN;
hint->status = CSS_TEXT_ALIGN_LIBCSS_RIGHT;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
} else if (dom_string_caseless_lwc_isequal(align,
corestring_lwc_justify)) {
hint->prop = CSS_PROP_TEXT_ALIGN;
hint->status = CSS_TEXT_ALIGN_JUSTIFY;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(align);
}
@@ -953,7 +953,7 @@ static void css_hint_text_align_table_special(
hint->prop = CSS_PROP_TEXT_ALIGN;
hint->status = CSS_TEXT_ALIGN_INHERIT_IF_NON_MAGIC;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
static void css_hint_margin_hspace_vspace(
@@ -977,13 +977,13 @@ static void css_hint_margin_hspace_vspace(
hint->data.length.value = hint_length.value;
hint->data.length.unit = hint_length.unit;
hint->status = CSS_MARGIN_SET;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
hint->prop = CSS_PROP_MARGIN_BOTTOM;
hint->data.length.value = hint_length.value;
hint->data.length.unit = hint_length.unit;
hint->status = CSS_MARGIN_SET;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(attr);
}
@@ -1001,13 +1001,13 @@ static void css_hint_margin_hspace_vspace(
hint->data.length.value = hint_length.value;
hint->data.length.unit = hint_length.unit;
hint->status = CSS_MARGIN_SET;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
hint->prop = CSS_PROP_MARGIN_RIGHT;
hint->data.length.value = hint_length.value;
hint->data.length.unit = hint_length.unit;
hint->status = CSS_MARGIN_SET;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(attr);
}
@@ -1032,33 +1032,33 @@ static void css_hint_margin_left_right_hr(
hint->data.length.value = 0;
hint->data.length.unit = CSS_UNIT_PX;
hint->status = CSS_MARGIN_SET;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
hint->prop = CSS_PROP_MARGIN_RIGHT;
hint->status = CSS_MARGIN_AUTO;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
} else if (dom_string_caseless_lwc_isequal(attr,
corestring_lwc_center)) {
hint->prop = CSS_PROP_MARGIN_LEFT;
hint->status = CSS_MARGIN_AUTO;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
hint->prop = CSS_PROP_MARGIN_RIGHT;
hint->status = CSS_MARGIN_AUTO;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
} else if (dom_string_caseless_lwc_isequal(attr,
corestring_lwc_right)) {
hint->prop = CSS_PROP_MARGIN_LEFT;
hint->status = CSS_MARGIN_AUTO;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
hint->prop = CSS_PROP_MARGIN_RIGHT;
hint->data.length.value = 0;
hint->data.length.unit = CSS_UNIT_PX;
hint->status = CSS_MARGIN_SET;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(attr);
}
@@ -1083,7 +1083,7 @@ static void css_hint_table_spacing_border(
hint_prop++) {
hint->prop = hint_prop;
hint->status = CSS_BORDER_STYLE_OUTSET;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
if (parse_dimension(
@@ -1098,7 +1098,7 @@ static void css_hint_table_spacing_border(
hint->data.length.value = hint_length.value;
hint->data.length.unit = hint_length.unit;
hint->status = CSS_BORDER_WIDTH_WIDTH;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
}
dom_string_unref(attr);
@@ -1121,7 +1121,7 @@ static void css_hint_table_spacing_border(
hint->prop = hint_prop;
hint->data.color = hint_color;
hint->status = CSS_BORDER_COLOR_COLOR;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
}
dom_string_unref(attr);
@@ -1138,7 +1138,7 @@ static void css_hint_table_spacing_border(
hint->prop = CSS_PROP_BORDER_SPACING;
hint->data.position.v = hint->data.position.h;
hint->status = CSS_BORDER_SPACING_SET;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(attr);
}
@@ -1162,7 +1162,7 @@ static void css_hint_height(
&hint->data.length.unit)) {
hint->prop = CSS_PROP_HEIGHT;
hint->status = CSS_HEIGHT_SET;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(attr);
}
@@ -1186,7 +1186,7 @@ static void css_hint_width(
&hint->data.length.unit)) {
hint->prop = CSS_PROP_WIDTH;
hint->status = CSS_WIDTH_SET;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(attr);
}
@@ -1211,7 +1211,7 @@ static void css_hint_height_width_textarea(
hint->prop = CSS_PROP_HEIGHT;
hint->data.length.unit = CSS_UNIT_EM;
hint->status = CSS_HEIGHT_SET;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(attr);
}
@@ -1227,12 +1227,74 @@ static void css_hint_height_width_textarea(
hint->prop = CSS_PROP_WIDTH;
hint->data.length.unit = CSS_UNIT_EX;
hint->status = CSS_WIDTH_SET;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(attr);
}
}
+static void css_hint_height_width_canvas(
+ nscss_select_ctx *ctx,
+ dom_node *node)
+{
+ struct css_hint *hint = &hint_ctx.hints[hint_ctx.len];
+ dom_string *attr = NULL;
+ dom_exception err;
+ bool set_dim = false;
+
+ err = dom_element_get_attribute(node,
+ corestring_dom_height, &attr);
+
+ if (err == DOM_NO_ERR && attr != NULL) {
+ if (parse_dimension(
+ (const char *)dom_string_data(attr), true,
+ &hint->data.length.value,
+ &hint->data.length.unit)) {
+ hint->prop = CSS_PROP_HEIGHT;
+ hint->data.length.unit = CSS_UNIT_PX;
+ hint->status = CSS_HEIGHT_SET;
+ css_hint_advance(&hint);
+ set_dim = true;
+ }
+ dom_string_unref(attr);
+ }
+ if (set_dim == false) {
+ /* canvas defaults to 150px tall */
+ hint->prop = CSS_PROP_HEIGHT;
+ hint->data.length.unit = CSS_UNIT_PX;
+ hint->data.length.value = INTTOFIX(150);
+ hint->status = CSS_HEIGHT_SET;
+ css_hint_advance(&hint);
+ } else {
+ set_dim = false;
+ }
+
+ err = dom_element_get_attribute(node,
+ corestring_dom_width, &attr);
+
+ if (err == DOM_NO_ERR && attr != NULL) {
+ if (parse_dimension(
+ (const char *)dom_string_data(attr), true,
+ &hint->data.length.value,
+ &hint->data.length.unit)) {
+ hint->prop = CSS_PROP_WIDTH;
+ hint->data.length.unit = CSS_UNIT_PX;
+ hint->status = CSS_WIDTH_SET;
+ css_hint_advance(&hint);
+ set_dim = true;
+ }
+ dom_string_unref(attr);
+ }
+ if (set_dim == false) {
+ /* canvas defaults to 300px wide */
+ hint->prop = CSS_PROP_WIDTH;
+ hint->data.length.unit = CSS_UNIT_PX;
+ hint->data.length.value = INTTOFIX(300);
+ hint->status = CSS_WIDTH_SET;
+ css_hint_advance(&hint);
+ }
+}
+
static void css_hint_width_input(
nscss_select_ctx *ctx,
dom_node *node)
@@ -1276,7 +1338,7 @@ static void css_hint_width_input(
if (attr2 != NULL) {
dom_string_unref(attr2);
}
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
}
dom_string_unref(attr);
@@ -1329,7 +1391,7 @@ static void css_hint_anchor_color(
&hint->data.color)) {
hint->prop = CSS_PROP_COLOR;
hint->status = CSS_COLOR_COLOR;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(color);
}
@@ -1351,7 +1413,7 @@ static void css_hint_body_color(
&hint->data.color)) {
hint->prop = CSS_PROP_COLOR;
hint->status = CSS_COLOR_COLOR;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(color);
}
@@ -1373,7 +1435,7 @@ static void css_hint_color(
&hint->data.color)) {
hint->prop = CSS_PROP_COLOR;
hint->status = CSS_COLOR_COLOR;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(color);
}
@@ -1395,7 +1457,7 @@ static void css_hint_font_size(
&hint->data.length.value,
&hint->data.length.unit)) {
hint->prop = CSS_PROP_FONT_SIZE;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(size);
}
@@ -1415,13 +1477,13 @@ static void css_hint_float(
corestring_lwc_left)) {
hint->prop = CSS_PROP_FLOAT;
hint->status = CSS_FLOAT_LEFT;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
} else if (dom_string_caseless_lwc_isequal(align,
corestring_lwc_right)) {
hint->prop = CSS_PROP_FLOAT;
hint->status = CSS_FLOAT_RIGHT;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(align);
}
@@ -1441,7 +1503,7 @@ static void css_hint_caption_side(
corestring_lwc_bottom)) {
hint->prop = CSS_PROP_CAPTION_SIDE;
hint->status = CSS_CAPTION_SIDE_BOTTOM;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(align);
}
@@ -1463,7 +1525,7 @@ static void css_hint_bg_color(
&hint->data.color)) {
hint->prop = CSS_PROP_BACKGROUND_COLOR;
hint->status = CSS_BACKGROUND_COLOR_COLOR;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
dom_string_unref(bgcolor);
}
@@ -1495,7 +1557,7 @@ static void css_hint_bg_image(
hint->prop = CSS_PROP_BACKGROUND_IMAGE;
hint->data.string = iurl;
hint->status = CSS_BACKGROUND_IMAGE_IMAGE;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
}
}
@@ -1513,18 +1575,68 @@ static void css_hint_white_space_nowrap(
if (err == DOM_NO_ERR && nowrap == true) {
hint->prop = CSS_PROP_WHITE_SPACE;
hint->status = CSS_WHITE_SPACE_NOWRAP;
- hint = css_hint_advance(hint);
+ css_hint_advance(&hint);
}
}
+static void css_hint_list(
+ nscss_select_ctx *ctx,
+ dom_node *node)
+{
+ struct css_hint *hint = &(hint_ctx.hints[hint_ctx.len]);
+ dom_exception err;
+ dom_string *attr;
-/* Exported function, documeted in css/hints.h */
+ err = dom_element_get_attribute(node, corestring_dom_type, &attr);
+ if (err == DOM_NO_ERR && attr != NULL) {
+ const char *attr_str = dom_string_data(attr);
+ size_t attr_len = dom_string_byte_length(attr);
+ enum css_list_style_type_e type = CSS_LIST_STYLE_TYPE_INHERIT;
+
+ if (attr_len == 1) {
+ switch (attr_str[0]) {
+ case 'a':
+ type = CSS_LIST_STYLE_TYPE_LOWER_ALPHA;
+ break;
+ case 'A':
+ type = CSS_LIST_STYLE_TYPE_UPPER_ALPHA;
+ break;
+ case 'i':
+ type = CSS_LIST_STYLE_TYPE_LOWER_ROMAN;
+ break;
+ case 'I':
+ type = CSS_LIST_STYLE_TYPE_UPPER_ROMAN;
+ break;
+ case '1':
+ type = CSS_LIST_STYLE_TYPE_DECIMAL;
+ break;
+ }
+ }
+
+ if (type != CSS_LIST_STYLE_TYPE_INHERIT) {
+ hint->prop = CSS_PROP_LIST_STYLE_TYPE;
+ hint->status = type;
+ css_hint_advance(&hint);
+ }
+
+ dom_string_unref(attr);
+ }
+}
+
+
+/* Exported function, documented in css/hints.h */
css_error node_presentational_hint(void *pw, void *node,
uint32_t *nhints, css_hint **hints)
{
dom_exception exc;
dom_html_element_type tag_type;
+ if (nsoption_bool(author_level_css) == false) {
+ *nhints = 0;
+ *hints = NULL;
+ return CSS_OK;
+ }
+
css_hint_clean();
exc = dom_html_element_get_tag_type(node, &tag_type);
@@ -1538,22 +1650,22 @@ css_error node_presentational_hint(void *pw, void *node,
css_hint_width(pw, node);
css_hint_table_cell_border_padding(pw, node);
css_hint_white_space_nowrap(pw, node);
- /* fallthrough */
+ fallthrough;
case DOM_HTML_ELEMENT_TYPE_TR:
css_hint_height(pw, node);
- /* fallthrough */
+ fallthrough;
case DOM_HTML_ELEMENT_TYPE_THEAD:
case DOM_HTML_ELEMENT_TYPE_TBODY:
case DOM_HTML_ELEMENT_TYPE_TFOOT:
css_hint_text_align_special(pw, node);
- /* fallthrough */
+ fallthrough;
case DOM_HTML_ELEMENT_TYPE_COL:
css_hint_vertical_align_table_cells(pw, node);
break;
case DOM_HTML_ELEMENT_TYPE_APPLET:
case DOM_HTML_ELEMENT_TYPE_IMG:
css_hint_margin_hspace_vspace(pw, node);
- /* fallthrough */
+ fallthrough;
case DOM_HTML_ELEMENT_TYPE_EMBED:
case DOM_HTML_ELEMENT_TYPE_IFRAME:
case DOM_HTML_ELEMENT_TYPE_OBJECT:
@@ -1576,7 +1688,7 @@ css_error node_presentational_hint(void *pw, void *node,
break;
case DOM_HTML_ELEMENT_TYPE_CAPTION:
css_hint_caption_side(pw, node);
- /* fallthrough */
+ fallthrough;
case DOM_HTML_ELEMENT_TYPE_DIV:
css_hint_text_align_special(pw, node);
break;
@@ -1606,6 +1718,12 @@ css_error node_presentational_hint(void *pw, void *node,
case DOM_HTML_ELEMENT_TYPE_BODY:
css_hint_body_color(pw, node);
break;
+ case DOM_HTML_ELEMENT_TYPE_CANVAS:
+ css_hint_height_width_canvas(pw, node);
+ break;
+ case DOM_HTML_ELEMENT_TYPE_OL:
+ css_hint_list(pw, node);
+ break;
default:
break;
}
diff --git a/content/handlers/css/select.c b/content/handlers/css/select.c
index ee79eb394..c77644b43 100644
--- a/content/handlers/css/select.c
+++ b/content/handlers/css/select.c
@@ -91,10 +91,6 @@ static css_error set_libcss_node_data(void *pw, void *node,
static css_error get_libcss_node_data(void *pw, void *node,
void **libcss_node_data);
-static css_error nscss_compute_font_size(void *pw, const css_hint *parent,
- css_hint *size);
-
-
/**
* Selection callback table for libcss
*/
@@ -135,9 +131,8 @@ static css_select_handler selection_handler = {
node_is_lang,
node_presentational_hint,
ua_default_for_property,
- nscss_compute_font_size,
set_libcss_node_data,
- get_libcss_node_data
+ get_libcss_node_data,
};
/**
@@ -250,12 +245,15 @@ static void nscss_dom_user_data_handler(dom_node_operation operation,
* \param ctx CSS selection context
* \param n Element to select for
* \param media Permitted media types
+ * \param unit_unit_len_ctx Unit length conversion context
* \param inline_style Inline style associated with element, or NULL
* \return Pointer to selection results (containing computed styles),
* or NULL on failure
*/
css_select_results *nscss_get_style(nscss_select_ctx *ctx, dom_node *n,
- uint64_t media, const css_stylesheet *inline_style)
+ const css_media *media,
+ const css_unit_ctx *unit_len_ctx,
+ const css_stylesheet *inline_style)
{
css_computed_style *composed;
css_select_results *styles;
@@ -263,7 +261,7 @@ css_select_results *nscss_get_style(nscss_select_ctx *ctx, dom_node *n,
css_error error;
/* Select style for node */
- error = css_select_style(ctx->ctx, n, media, inline_style,
+ error = css_select_style(ctx->ctx, n, unit_len_ctx, media, inline_style,
&selection_handler, ctx, &styles);
if (error != CSS_OK || styles == NULL) {
@@ -278,8 +276,7 @@ css_select_results *nscss_get_style(nscss_select_ctx *ctx, dom_node *n,
* element's style */
error = css_computed_style_compose(ctx->parent_style,
styles->styles[CSS_PSEUDO_ELEMENT_NONE],
- nscss_compute_font_size, ctx,
- &composed);
+ unit_len_ctx, &composed);
if (error != CSS_OK) {
css_select_results_destroy(styles);
return NULL;
@@ -310,8 +307,7 @@ css_select_results *nscss_get_style(nscss_select_ctx *ctx, dom_node *n,
error = css_computed_style_compose(
styles->styles[CSS_PSEUDO_ELEMENT_NONE],
styles->styles[pseudo_element],
- nscss_compute_font_size, ctx,
- &composed);
+ unit_len_ctx, &composed);
if (error != CSS_OK) {
/* TODO: perhaps this shouldn't be quite so
* catastrophic? */
@@ -330,11 +326,13 @@ css_select_results *nscss_get_style(nscss_select_ctx *ctx, dom_node *n,
/**
* Get a blank style
*
- * \param ctx CSS selection context
- * \param parent Parent style to cascade inherited properties from
+ * \param ctx CSS selection context
+ * \param unit_unit_len_ctx Unit length conversion context
+ * \param parent Parent style to cascade inherited properties from
* \return Pointer to blank style, or NULL on failure
*/
css_computed_style *nscss_get_blank_style(nscss_select_ctx *ctx,
+ const css_unit_ctx *unit_len_ctx,
const css_computed_style *parent)
{
css_computed_style *partial, *composed;
@@ -349,7 +347,7 @@ css_computed_style *nscss_get_blank_style(nscss_select_ctx *ctx,
/* TODO: Do we really need to compose? Initial style shouldn't
* have any inherited properties. */
error = css_computed_style_compose(parent, partial,
- nscss_compute_font_size, ctx, &composed);
+ unit_len_ctx, &composed);
css_computed_style_destroy(partial);
if (error != CSS_OK) {
css_computed_style_destroy(composed);
@@ -359,133 +357,6 @@ css_computed_style *nscss_get_blank_style(nscss_select_ctx *ctx,
return composed;
}
-/**
- * Font size computation callback for libcss
- *
- * \param pw Computation context
- * \param parent Parent font size (absolute)
- * \param size Font size to compute
- * \return CSS_OK on success
- *
- * \post \a size will be an absolute font size
- */
-css_error nscss_compute_font_size(void *pw, const css_hint *parent,
- css_hint *size)
-{
- /**
- * Table of font-size keyword scale factors
- *
- * These are multiplied by the configured default font size
- * to produce an absolute size for the relevant keyword
- */
- static const css_fixed factors[] = {
- FLTTOFIX(0.5625), /* xx-small */
- FLTTOFIX(0.6250), /* x-small */
- FLTTOFIX(0.8125), /* small */
- FLTTOFIX(1.0000), /* medium */
- FLTTOFIX(1.1250), /* large */
- FLTTOFIX(1.5000), /* x-large */
- FLTTOFIX(2.0000) /* xx-large */
- };
- css_hint_length parent_size;
-
- /* Grab parent size, defaulting to medium if none */
- if (parent == NULL) {
- parent_size.value = FDIV(FMUL(factors[CSS_FONT_SIZE_MEDIUM - 1],
- INTTOFIX(nsoption_int(font_size))),
- INTTOFIX(10));
- parent_size.unit = CSS_UNIT_PT;
- } else {
- assert(parent->status == CSS_FONT_SIZE_DIMENSION);
- assert(parent->data.length.unit != CSS_UNIT_EM);
- assert(parent->data.length.unit != CSS_UNIT_EX);
- assert(parent->data.length.unit != CSS_UNIT_PCT);
-
- parent_size = parent->data.length;
- }
-
- assert(size->status != CSS_FONT_SIZE_INHERIT);
-
- if (size->status < CSS_FONT_SIZE_LARGER) {
- /* Keyword -- simple */
- size->data.length.value = FDIV(FMUL(factors[size->status - 1],
- INTTOFIX(nsoption_int(font_size))), F_10);
- size->data.length.unit = CSS_UNIT_PT;
- } else if (size->status == CSS_FONT_SIZE_LARGER) {
- /** \todo Step within table, if appropriate */
- size->data.length.value =
- FMUL(parent_size.value, FLTTOFIX(1.2));
- size->data.length.unit = parent_size.unit;
- } else if (size->status == CSS_FONT_SIZE_SMALLER) {
- /** \todo Step within table, if appropriate */
- size->data.length.value =
- FDIV(parent_size.value, FLTTOFIX(1.2));
- size->data.length.unit = parent_size.unit;
- } else if (size->data.length.unit == CSS_UNIT_EM ||
- size->data.length.unit == CSS_UNIT_EX ||
- size->data.length.unit == CSS_UNIT_CAP ||
- size->data.length.unit == CSS_UNIT_CH ||
- size->data.length.unit == CSS_UNIT_IC) {
- size->data.length.value =
- FMUL(size->data.length.value, parent_size.value);
-
- switch (size->data.length.unit) {
- case CSS_UNIT_EX:
- /* 1ex = 0.6em in NetSurf */
- size->data.length.value = FMUL(size->data.length.value,
- FLTTOFIX(0.6));
- break;
- case CSS_UNIT_CAP:
- /* Height of captals. 1cap = 0.9em in NetSurf. */
- size->data.length.value = FMUL(size->data.length.value,
- FLTTOFIX(0.9));
- break;
- case CSS_UNIT_CH:
- /* Width of '0'. 1ch = 0.4em in NetSurf. */
- size->data.length.value = FMUL(size->data.length.value,
- FLTTOFIX(0.4));
- break;
- case CSS_UNIT_IC:
- /* Width of U+6C43. 1ic = 1.1em in NetSurf. */
- size->data.length.value = FMUL(size->data.length.value,
- FLTTOFIX(1.1));
- break;
- default:
- /* No scaling required for EM. */
- break;
- }
-
- size->data.length.unit = parent_size.unit;
- } else if (size->data.length.unit == CSS_UNIT_PCT) {
- size->data.length.value = FDIV(FMUL(size->data.length.value,
- parent_size.value), INTTOFIX(100));
- size->data.length.unit = parent_size.unit;
- } else if (size->data.length.unit == CSS_UNIT_REM) {
- nscss_select_ctx *ctx = pw;
- if (parent == NULL) {
- size->data.length.value = parent_size.value;
- size->data.length.unit = parent_size.unit;
- } else {
- css_computed_font_size(ctx->root_style,
- &parent_size.value,
- &size->data.length.unit);
- size->data.length.value = FMUL(
- size->data.length.value,
- parent_size.value);
- }
- } else if (size->data.length.unit == CSS_UNIT_RLH) {
- /** TODO: Convert root element line-height to absolute value. */
- size->data.length.value = FMUL(size->data.length.value, FDIV(
- INTTOFIX(nsoption_int(font_size)),
- INTTOFIX(10)));
- size->data.length.unit = CSS_UNIT_PT;
- }
-
- size->status = CSS_FONT_SIZE_DIMENSION;
-
- return CSS_OK;
-}
-
/******************************************************************************
* Style selection callbacks *
******************************************************************************/
@@ -602,6 +473,7 @@ css_error named_ancestor_node(void *pw, void *node,
{
dom_element_named_ancestor_node(node, qname->name,
(struct dom_element **)ancestor);
+ dom_node_unref(*ancestor);
return CSS_OK;
}
@@ -622,6 +494,7 @@ css_error named_parent_node(void *pw, void *node,
{
dom_element_named_parent_node(node, qname->name,
(struct dom_element **)parent);
+ dom_node_unref(*parent);
return CSS_OK;
}
@@ -771,6 +644,7 @@ css_error named_generic_sibling_node(void *pw, void *node,
css_error parent_node(void *pw, void *node, void **parent)
{
dom_element_parent_node(node, (struct dom_element **)parent);
+ dom_node_unref(*parent);
return CSS_OK;
}
diff --git a/content/handlers/css/select.h b/content/handlers/css/select.h
index 9fa6d3a56..c17caadcb 100644
--- a/content/handlers/css/select.h
+++ b/content/handlers/css/select.h
@@ -45,9 +45,12 @@ css_stylesheet *nscss_create_inline_style(const uint8_t *data, size_t len,
const char *charset, const char *url, bool allow_quirks);
css_select_results *nscss_get_style(nscss_select_ctx *ctx, dom_node *n,
- uint64_t media, const css_stylesheet *inline_style);
+ const css_media *media,
+ const css_unit_ctx *unit_len_ctx,
+ const css_stylesheet *inline_style);
css_computed_style *nscss_get_blank_style(nscss_select_ctx *ctx,
+ const css_unit_ctx *unit_len_ctx,
const css_computed_style *parent);
diff --git a/content/handlers/css/utils.c b/content/handlers/css/utils.c
deleted file mode 100644
index 8fe157bd2..000000000
--- a/content/handlers/css/utils.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright 2004 James Bursa <james@netsurf-browser.org>
- * Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <assert.h>
-
-#include "utils/nsoption.h"
-#include "utils/log.h"
-
-#include "css/utils.h"
-
-/** Screen DPI in fixed point units: defaults to 90, which RISC OS uses */
-css_fixed nscss_screen_dpi = F_90;
-
-
-/**
- * Map viewport-relative length units to either vh or vw.
- *
- * Non-viewport-relative units are unchanged.
- *
- * \param[in] ctx Length conversion context.
- * \param[in] unit Unit to map.
- * \return the mapped unit.
- */
-static inline css_unit css_utils__fudge_viewport_units(
- const nscss_len_ctx *ctx,
- css_unit unit)
-{
- switch (unit) {
- case CSS_UNIT_VI:
- assert(ctx->root_style != NULL);
- if (css_computed_writing_mode(ctx->root_style) ==
- CSS_WRITING_MODE_HORIZONTAL_TB) {
- unit = CSS_UNIT_VW;
- } else {
- unit = CSS_UNIT_VH;
- }
- break;
- case CSS_UNIT_VB:
- assert(ctx->root_style != NULL);
- if (css_computed_writing_mode(ctx->root_style) ==
- CSS_WRITING_MODE_HORIZONTAL_TB) {
- unit = CSS_UNIT_VH;
- } else {
- unit = CSS_UNIT_VW;
- }
- break;
- case CSS_UNIT_VMIN:
- if (ctx->vh < ctx->vw) {
- unit = CSS_UNIT_VH;
- } else {
- unit = CSS_UNIT_VW;
- }
- break;
- case CSS_UNIT_VMAX:
- if (ctx->vh > ctx->vw) {
- unit = CSS_UNIT_VH;
- } else {
- unit = CSS_UNIT_VW;
- }
- break;
- default: break;
- }
-
- return unit;
-}
-
-/* exported interface documented in content/handlers/css/utils.h */
-css_fixed nscss_len2pt(
- const nscss_len_ctx *ctx,
- css_fixed length,
- css_unit unit)
-{
- /* Length must not be relative */
- assert(unit != CSS_UNIT_EM &&
- unit != CSS_UNIT_EX &&
- unit != CSS_UNIT_CAP &&
- unit != CSS_UNIT_CH &&
- unit != CSS_UNIT_IC &&
- unit != CSS_UNIT_REM &&
- unit != CSS_UNIT_RLH);
-
- unit = css_utils__fudge_viewport_units(ctx, unit);
-
- switch (unit) {
- /* We assume the screen and any other output has the same dpi */
- /* 1in = DPIpx => 1px = (72/DPI)pt */
- case CSS_UNIT_PX: return FDIV(FMUL(length, F_72), nscss_screen_dpi);
- /* 1in = 72pt */
- case CSS_UNIT_IN: return FMUL(length, F_72);
- /* 1in = 2.54cm => 1cm = (72/2.54)pt */
- case CSS_UNIT_CM: return FMUL(length,
- FDIV(F_72, FLTTOFIX(2.54)));
- /* 1in = 25.4mm => 1mm = (72/25.4)pt */
- case CSS_UNIT_MM: return FMUL(length,
- FDIV(F_72, FLTTOFIX(25.4)));
- /* 1in = 101.6q => 1mm = (72/101.6)pt */
- case CSS_UNIT_Q: return FMUL(length,
- FDIV(F_72, FLTTOFIX(101.6)));
- case CSS_UNIT_PT: return length;
- /* 1pc = 12pt */
- case CSS_UNIT_PC: return FMUL(length, INTTOFIX(12));
- case CSS_UNIT_VH: return FDIV(FMUL(FDIV((length * ctx->vh), F_100),
- F_72), nscss_screen_dpi);
- case CSS_UNIT_VW: return FDIV(FMUL(FDIV((length * ctx->vw), F_100),
- F_72), nscss_screen_dpi);
- default: break;
- }
-
- return 0;
-}
-
-/* exported interface documented in content/handlers/css/utils.h */
-css_fixed nscss_len2px(
- const nscss_len_ctx *ctx,
- css_fixed length,
- css_unit unit,
- const css_computed_style *style)
-{
- /* We assume the screen and any other output has the same dpi */
- css_fixed px_per_unit;
-
- unit = css_utils__fudge_viewport_units(ctx, unit);
-
- switch (unit) {
- case CSS_UNIT_EM:
- case CSS_UNIT_EX:
- case CSS_UNIT_CAP:
- case CSS_UNIT_CH:
- case CSS_UNIT_IC:
- {
- css_fixed font_size = 0;
- css_unit font_unit = CSS_UNIT_PT;
-
- assert(style != NULL);
-
- css_computed_font_size(style, &font_size, &font_unit);
-
- /* Convert to points */
- font_size = nscss_len2pt(ctx, font_size, font_unit);
-
- /* Clamp to configured minimum */
- if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) {
- font_size = FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10);
- }
-
- /* Convert to pixels (manually, to maximise precision)
- * 1in = 72pt => 1pt = (DPI/72)px */
- px_per_unit = FDIV(FMUL(font_size, nscss_screen_dpi), F_72);
-
- /* Scale non-em units to em. We have fixed ratios. */
- switch (unit) {
- case CSS_UNIT_EX:
- px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.6));
- break;
- case CSS_UNIT_CAP:
- px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.9));
- break;
- case CSS_UNIT_CH:
- px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.4));
- break;
- case CSS_UNIT_IC:
- px_per_unit = FMUL(px_per_unit, FLTTOFIX(1.1));
- break;
- default: break;
- }
- }
- break;
- case CSS_UNIT_PX:
- px_per_unit = F_1;
- break;
- /* 1in = DPIpx */
- case CSS_UNIT_IN:
- px_per_unit = nscss_screen_dpi;
- break;
- /* 1in = 2.54cm => 1cm = (DPI/2.54)px */
- case CSS_UNIT_CM:
- px_per_unit = FDIV(nscss_screen_dpi, FLTTOFIX(2.54));
- break;
- /* 1in = 25.4mm => 1mm = (DPI/25.4)px */
- case CSS_UNIT_MM:
- px_per_unit = FDIV(nscss_screen_dpi, FLTTOFIX(25.4));
- break;
- /* 1in = 101.6q => 1q = (DPI/101.6)px */
- case CSS_UNIT_Q:
- px_per_unit = FDIV(nscss_screen_dpi, FLTTOFIX(101.6));
- break;
- /* 1in = 72pt => 1pt = (DPI/72)px */
- case CSS_UNIT_PT:
- px_per_unit = FDIV(nscss_screen_dpi, F_72);
- break;
- /* 1pc = 12pt => 1in = 6pc => 1pc = (DPI/6)px */
- case CSS_UNIT_PC:
- px_per_unit = FDIV(nscss_screen_dpi, INTTOFIX(6));
- break;
- case CSS_UNIT_REM:
- {
- css_fixed font_size = 0;
- css_unit font_unit = CSS_UNIT_PT;
-
- assert(ctx->root_style != NULL);
-
- css_computed_font_size(ctx->root_style,
- &font_size, &font_unit);
-
- /* Convert to points */
- font_size = nscss_len2pt(ctx, font_size, font_unit);
-
- /* Clamp to configured minimum */
- if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) {
- font_size = FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10);
- }
-
- /* Convert to pixels (manually, to maximise precision)
- * 1in = 72pt => 1pt = (DPI/72)px */
- px_per_unit = FDIV(FMUL(font_size, nscss_screen_dpi), F_72);
- break;
- }
- /* 1rlh = <user_font_size>pt => 1rlh = (DPI/user_font_size)px */
- case CSS_UNIT_RLH:
- px_per_unit = FDIV(nscss_screen_dpi, FDIV(
- INTTOFIX(nsoption_int(font_size)),
- INTTOFIX(10)));
- break;
- case CSS_UNIT_VH:
- return TRUNCATEFIX((FDIV((length * ctx->vh), F_100) + F_0_5));
- case CSS_UNIT_VW:
- return TRUNCATEFIX((FDIV((length * ctx->vw), F_100) + F_0_5));
- default:
- px_per_unit = 0;
- break;
- }
-
- /* Ensure we round px_per_unit to the nearest whole number of pixels:
- * the use of FIXTOINT() below will truncate. */
- px_per_unit += F_0_5;
-
- /* Calculate total number of pixels */
- return FMUL(length, TRUNCATEFIX(px_per_unit));
-}
diff --git a/content/handlers/css/utils.h b/content/handlers/css/utils.h
index c8f4c82f4..ee241e2cc 100644
--- a/content/handlers/css/utils.h
+++ b/content/handlers/css/utils.h
@@ -27,93 +27,51 @@
extern css_fixed nscss_screen_dpi;
/**
- * Length conversion context data.
- */
-typedef struct nscss_len_ctx {
- /**
- * Viewport width in px.
- * Only used if unit is vh, vw, vi, vb, vmin, or vmax.
- */
- int vw;
- /**
- * Viewport height in px.
- * Only used if unit is vh, vw, vi, vb, vmin, or vmax.
- */
- int vh;
- /**
- * Computed style for the document root element.
- * May be NULL if unit is not rem, or rlh.
- */
- const css_computed_style *root_style;
-} nscss_len_ctx;
-
-/**
- * Convert an absolute CSS length to points.
- *
- * \param[in] ctx Length conversion context.
- * \param[in] length Absolute CSS length.
- * \param[in] unit Unit of the length.
- * \return length in points
- */
-css_fixed nscss_len2pt(
- const nscss_len_ctx *ctx,
- css_fixed length,
- css_unit unit);
-
-/**
- * Convert a CSS length to pixels.
- *
- * \param[in] ctx Length conversion context.
- * \param[in] length Length to convert.
- * \param[in] unit Corresponding unit.
- * \param[in] style Computed style applying to length.
- * May be NULL if unit is not em, ex, cap, ch, or ic.
- * \return length in pixels
- */
-css_fixed nscss_len2px(
- const nscss_len_ctx *ctx,
- css_fixed length,
- css_unit unit,
- const css_computed_style *style);
-
-
-/**
* Temporary helper wrappers for for libcss computed style getter, while
- * we don't support flexbox related property values.
+ * we don't support all values of display.
*/
-
static inline uint8_t ns_computed_display(
const css_computed_style *style, bool root)
{
uint8_t value = css_computed_display(style, root);
- if (value == CSS_DISPLAY_FLEX) {
+ switch (value) {
+ case CSS_DISPLAY_GRID:
return CSS_DISPLAY_BLOCK;
- } else if (value == CSS_DISPLAY_INLINE_FLEX) {
+ case CSS_DISPLAY_INLINE_GRID:
return CSS_DISPLAY_INLINE_BLOCK;
+
+ default:
+ break;
}
return value;
}
-
+/**
+ * Temporary helper wrappers for for libcss computed style getter, while
+ * we don't support all values of display.
+ */
static inline uint8_t ns_computed_display_static(
const css_computed_style *style)
{
uint8_t value = css_computed_display_static(style);
- if (value == CSS_DISPLAY_FLEX) {
+ switch (value) {
+ case CSS_DISPLAY_GRID:
return CSS_DISPLAY_BLOCK;
- } else if (value == CSS_DISPLAY_INLINE_FLEX) {
+ case CSS_DISPLAY_INLINE_GRID:
return CSS_DISPLAY_INLINE_BLOCK;
+
+ default:
+ break;
}
return value;
}
-
static inline uint8_t ns_computed_min_height(
const css_computed_style *style,
css_fixed *length, css_unit *unit)
diff --git a/content/handlers/html/Makefile b/content/handlers/html/Makefile
new file mode 100644
index 000000000..e41cc1d22
--- /dev/null
+++ b/content/handlers/html/Makefile
@@ -0,0 +1,25 @@
+# HTML content handler sources
+
+S_HTML := box_construct.c \
+ box_inspect.c \
+ box_manipulate.c \
+ box_normalise.c \
+ box_special.c \
+ box_textarea.c \
+ css.c \
+ css_fetcher.c \
+ dom_event.c \
+ font.c \
+ form.c \
+ forms.c \
+ html.c \
+ imagemap.c \
+ interaction.c \
+ layout.c \
+ layout_flex.c \
+ object.c \
+ redraw.c \
+ redraw_border.c \
+ script.c \
+ table.c \
+ textselection.c
diff --git a/content/handlers/html/box.h b/content/handlers/html/box.h
new file mode 100644
index 000000000..df2b99d87
--- /dev/null
+++ b/content/handlers/html/box.h
@@ -0,0 +1,457 @@
+/*
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Box interface.
+ *
+ */
+
+#ifndef NETSURF_HTML_BOX_H
+#define NETSURF_HTML_BOX_H
+
+#include <limits.h>
+#include <stdbool.h>
+#include <libcss/libcss.h>
+
+#include "content/handlers/css/utils.h"
+
+struct content;
+struct box;
+struct browser_window;
+struct html_content;
+struct nsurl;
+struct dom_node;
+struct dom_string;
+struct rect;
+
+#define UNKNOWN_WIDTH INT_MAX
+#define UNKNOWN_MAX_WIDTH INT_MAX
+
+
+typedef void (*box_construct_complete_cb)(struct html_content *c, bool success);
+
+
+/**
+ * Type of a struct box.
+ */
+typedef enum {
+ BOX_BLOCK,
+ BOX_INLINE_CONTAINER,
+ BOX_INLINE,
+ BOX_TABLE,
+ BOX_TABLE_ROW,
+ BOX_TABLE_CELL,
+ BOX_TABLE_ROW_GROUP,
+ BOX_FLOAT_LEFT,
+ BOX_FLOAT_RIGHT,
+ BOX_INLINE_BLOCK,
+ BOX_BR,
+ BOX_TEXT,
+ BOX_INLINE_END,
+ BOX_NONE,
+ BOX_FLEX,
+ BOX_INLINE_FLEX,
+} box_type;
+
+
+/**
+ * Flags for a struct box.
+ */
+typedef enum {
+ NEW_LINE = 1 << 0, /* first inline on a new line */
+ STYLE_OWNED = 1 << 1, /* style is owned by this box */
+ PRINTED = 1 << 2, /* box has already been printed */
+ PRE_STRIP = 1 << 3, /* PRE tag needing leading newline stripped */
+ CLONE = 1 << 4, /* continuation of previous box from wrapping */
+ MEASURED = 1 << 5, /* text box width has been measured */
+ HAS_HEIGHT = 1 << 6, /* box has height (perhaps due to children) */
+ MAKE_HEIGHT = 1 << 7, /* box causes its own height */
+ NEED_MIN = 1 << 8, /* minimum width is required for layout */
+ REPLACE_DIM = 1 << 9, /* replaced element has given dimensions */
+ IFRAME = 1 << 10, /* box contains an iframe */
+ CONVERT_CHILDREN = 1 << 11, /* wanted children converting */
+ IS_REPLACED = 1 << 12 /* box is a replaced element */
+} box_flags;
+
+
+/**
+ * Sides of a box
+ */
+enum box_side { TOP, RIGHT, BOTTOM, LEFT };
+
+
+/**
+ * Container for box border details
+ */
+struct box_border {
+ enum css_border_style_e style; /**< border-style */
+ css_color c; /**< border-color value */
+ int width; /**< border-width (pixels) */
+};
+
+
+/**
+ * Table column data.
+ */
+struct column {
+ /**
+ * Type of column.
+ */
+ enum {
+ COLUMN_WIDTH_UNKNOWN,
+ COLUMN_WIDTH_FIXED,
+ COLUMN_WIDTH_AUTO,
+ COLUMN_WIDTH_PERCENT,
+ COLUMN_WIDTH_RELATIVE
+ } type;
+
+ /**
+ * Preferred width of column. Pixels for FIXED, percentage for
+ * PERCENT, relative units for RELATIVE, unused for AUTO.
+ */
+ int width;
+
+ /**
+ * Minimum width of content.
+ */
+ int min;
+
+ /**
+ * Maximum width of content.
+ */
+ int max;
+
+ /**
+ * Whether all of column's cells are css positioned.
+ */
+ bool positioned;
+};
+
+
+/**
+ * Linked list of object element parameters.
+ */
+struct object_param {
+ char *name;
+ char *value;
+ char *type;
+ char *valuetype;
+ struct object_param *next;
+};
+
+
+/**
+ * Parameters for object element and similar elements.
+ */
+struct object_params {
+ struct nsurl *data;
+ char *type;
+ char *codetype;
+ struct nsurl *codebase;
+ struct nsurl *classid;
+ struct object_param *params;
+};
+
+
+/**
+ * Node in box tree. All dimensions are in pixels.
+ */
+struct box {
+ /**
+ * Type of box.
+ */
+ box_type type;
+
+ /**
+ * Box flags
+ */
+ box_flags flags;
+
+ /**
+ * DOM node that generated this box or NULL
+ */
+ struct dom_node *node;
+
+ /**
+ * Computed styles for elements and their pseudo elements.
+ * NULL on non-element boxes.
+ */
+ css_select_results *styles;
+
+ /**
+ * Style for this box. 0 for INLINE_CONTAINER and
+ * FLOAT_*. Pointer into a box's 'styles' select results,
+ * except for implied boxes, where it is a pointer to an
+ * owned computed style.
+ */
+ css_computed_style *style;
+
+ /**
+ * value of id attribute (or name for anchors)
+ */
+ lwc_string *id;
+
+
+ /**
+ * Next sibling box, or NULL.
+ */
+ struct box *next;
+
+ /**
+ * Previous sibling box, or NULL.
+ */
+ struct box *prev;
+
+ /**
+ * First child box, or NULL.
+ */
+ struct box *children;
+
+ /**
+ * Last child box, or NULL.
+ */
+ struct box *last;
+
+ /**
+ * Parent box, or NULL.
+ */
+ struct box *parent;
+
+ /**
+ * INLINE_END box corresponding to this INLINE box, or INLINE
+ * box corresponding to this INLINE_END box.
+ */
+ struct box *inline_end;
+
+
+ /**
+ * First float child box, or NULL. Float boxes are in the tree
+ * twice, in this list for the block box which defines the
+ * area for floats, and also in the standard tree given by
+ * children, next, prev, etc.
+ */
+ struct box *float_children;
+
+ /**
+ * Next sibling float box.
+ */
+ struct box *next_float;
+
+ /**
+ * If box is a float, points to box's containing block
+ */
+ struct box *float_container;
+
+ /**
+ * Level below which subsequent floats must be cleared. This
+ * is used only for boxes with float_children
+ */
+ int clear_level;
+
+ /**
+ * Level below which floats have been placed.
+ */
+ int cached_place_below_level;
+
+
+ /**
+ * Coordinate of left padding edge relative to parent box, or
+ * relative to ancestor that contains this box in
+ * float_children for FLOAT_.
+ */
+ int x;
+ /**
+ * Coordinate of top padding edge, relative as for x.
+ */
+ int y;
+
+ /**
+ * Width of content box (excluding padding etc.).
+ */
+ int width;
+ /**
+ * Height of content box (excluding padding etc.).
+ */
+ int height;
+
+ /* These four variables determine the maximum extent of a box's
+ * descendants. They are relative to the x,y coordinates of the box.
+ *
+ * Their use depends on the overflow CSS property:
+ *
+ * Overflow: Usage:
+ * visible The content of the box is displayed within these
+ * dimensions.
+ * hidden These are ignored. Content is plotted within the box
+ * dimensions.
+ * scroll These are used to determine the extent of the
+ * scrollable area.
+ * auto As "scroll".
+ */
+ int descendant_x0; /**< left edge of descendants */
+ int descendant_y0; /**< top edge of descendants */
+ int descendant_x1; /**< right edge of descendants */
+ int descendant_y1; /**< bottom edge of descendants */
+
+ /**
+ * Margin: TOP, RIGHT, BOTTOM, LEFT.
+ */
+ int margin[4];
+
+ /**
+ * Padding: TOP, RIGHT, BOTTOM, LEFT.
+ */
+ int padding[4];
+
+ /**
+ * Border: TOP, RIGHT, BOTTOM, LEFT.
+ */
+ struct box_border border[4];
+
+ /**
+ * Horizontal scroll.
+ */
+ struct scrollbar *scroll_x;
+
+ /**
+ * Vertical scroll.
+ */
+ struct scrollbar *scroll_y;
+
+ /**
+ * Width of box taking all line breaks (including margins
+ * etc). Must be non-negative.
+ */
+ int min_width;
+
+ /**
+ * Width that would be taken with no line breaks. Must be
+ * non-negative.
+ */
+ int max_width;
+
+
+ /**
+ * Text, or NULL if none. Unterminated.
+ */
+ char *text;
+
+ /**
+ * Length of text.
+ */
+ size_t length;
+
+ /**
+ * Width of space after current text (depends on font and size).
+ */
+ int space;
+
+ /**
+ * Byte offset within a textual representation of this content.
+ */
+ size_t byte_offset;
+
+
+ /**
+ * Link, or NULL.
+ */
+ struct nsurl *href;
+
+ /**
+ * Link target, or NULL.
+ */
+ const char *target;
+
+ /**
+ * Title, or NULL.
+ */
+ const char *title;
+
+
+ /**
+ * Number of columns for TABLE / TABLE_CELL.
+ */
+ unsigned int columns;
+
+ /**
+ * Number of rows for TABLE only.
+ */
+ unsigned int rows;
+
+ /**
+ * Start column for TABLE_CELL only.
+ */
+ unsigned int start_column;
+
+ /**
+ * Array of table column data for TABLE only.
+ */
+ struct column *col;
+
+ /**
+ * List item value.
+ */
+ int list_value;
+
+ /**
+ * List marker box if this is a list-item, or NULL.
+ */
+ struct box *list_marker;
+
+
+ /**
+ * Form control data, or NULL if not a form control.
+ */
+ struct form_control* gadget;
+
+
+ /**
+ * (Image)map to use with this object, or NULL if none
+ */
+ char *usemap;
+
+
+ /**
+ * Background image for this box, or NULL if none
+ */
+ struct hlcache_handle *background;
+
+
+ /**
+ * Object in this box (usually an image), or NULL if none.
+ */
+ struct hlcache_handle* object;
+
+ /**
+ * Parameters for the object, or NULL.
+ */
+ struct object_params *object_params;
+
+
+ /**
+ * Iframe's browser_window, or NULL if none
+ */
+ struct browser_window *iframe;
+
+};
+
+
+#endif
diff --git a/content/handlers/html/box_construct.c b/content/handlers/html/box_construct.c
new file mode 100644
index 000000000..8519c2b1d
--- /dev/null
+++ b/content/handlers/html/box_construct.c
@@ -0,0 +1,1450 @@
+/*
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
+ * Copyright 2005 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ * Copyright 2008 Michael Drake <tlsa@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of conversion from DOM tree to box tree.
+ */
+
+#include <string.h>
+#include <dom/dom.h>
+
+#include "utils/errors.h"
+#include "utils/nsoption.h"
+#include "utils/corestrings.h"
+#include "utils/talloc.h"
+#include "utils/string.h"
+#include "utils/ascii.h"
+#include "utils/nsurl.h"
+#include "netsurf/misc.h"
+#include "css/select.h"
+#include "desktop/gui_internal.h"
+
+#include "html/private.h"
+#include "html/object.h"
+#include "html/box.h"
+#include "html/box_manipulate.h"
+#include "html/box_construct.h"
+#include "html/box_special.h"
+#include "html/box_normalise.h"
+#include "html/form_internal.h"
+
+/**
+ * Context for box tree construction
+ */
+struct box_construct_ctx {
+ html_content *content; /**< Content we're constructing for */
+
+ dom_node *n; /**< Current node to process */
+
+ struct box *root_box; /**< Root box in the tree */
+
+ box_construct_complete_cb cb; /**< Callback to invoke on completion */
+
+ int *bctx; /**< talloc context */
+};
+
+/**
+ * Transient properties for construction of current node
+ */
+struct box_construct_props {
+ /** Style from which to inherit, or NULL if none */
+ const css_computed_style *parent_style;
+ /** Current link target, or NULL if none */
+ struct nsurl *href;
+ /** Current frame target, or NULL if none */
+ const char *target;
+ /** Current title attribute, or NULL if none */
+ const char *title;
+ /** Identity of the current block-level container */
+ struct box *containing_block;
+ /** Current container for inlines, or NULL if none
+ * \note If non-NULL, will be the last child of containing_block */
+ struct box *inline_container;
+ /** Whether the current node is the root of the DOM tree */
+ bool node_is_root;
+};
+
+static const content_type image_types = CONTENT_IMAGE;
+
+/* mapping from CSS display to box type
+ * this table must be in sync with libcss' css_display enum */
+static const box_type box_map[] = {
+ BOX_BLOCK, /* CSS_DISPLAY_INHERIT */
+ BOX_INLINE, /* CSS_DISPLAY_INLINE */
+ BOX_BLOCK, /* CSS_DISPLAY_BLOCK */
+ BOX_BLOCK, /* CSS_DISPLAY_LIST_ITEM */
+ BOX_INLINE, /* CSS_DISPLAY_RUN_IN */
+ BOX_INLINE_BLOCK, /* CSS_DISPLAY_INLINE_BLOCK */
+ BOX_TABLE, /* CSS_DISPLAY_TABLE */
+ BOX_TABLE, /* CSS_DISPLAY_INLINE_TABLE */
+ BOX_TABLE_ROW_GROUP, /* CSS_DISPLAY_TABLE_ROW_GROUP */
+ BOX_TABLE_ROW_GROUP, /* CSS_DISPLAY_TABLE_HEADER_GROUP */
+ BOX_TABLE_ROW_GROUP, /* CSS_DISPLAY_TABLE_FOOTER_GROUP */
+ BOX_TABLE_ROW, /* CSS_DISPLAY_TABLE_ROW */
+ BOX_NONE, /* CSS_DISPLAY_TABLE_COLUMN_GROUP */
+ BOX_NONE, /* CSS_DISPLAY_TABLE_COLUMN */
+ BOX_TABLE_CELL, /* CSS_DISPLAY_TABLE_CELL */
+ BOX_INLINE, /* CSS_DISPLAY_TABLE_CAPTION */
+ BOX_NONE, /* CSS_DISPLAY_NONE */
+ BOX_FLEX, /* CSS_DISPLAY_FLEX */
+ BOX_INLINE_FLEX, /* CSS_DISPLAY_INLINE_FLEX */
+ BOX_BLOCK, /* CSS_DISPLAY_GRID */
+ BOX_INLINE_BLOCK, /* CSS_DISPLAY_INLINE_GRID */
+};
+
+
+/**
+ * determine if a box is the root node
+ *
+ * \param n node to check
+ * \return true if node is root else false.
+ */
+static inline bool box_is_root(dom_node *n)
+{
+ dom_node *parent;
+ dom_node_type type;
+ dom_exception err;
+
+ err = dom_node_get_parent_node(n, &parent);
+ if (err != DOM_NO_ERR)
+ return false;
+
+ if (parent != NULL) {
+ err = dom_node_get_node_type(parent, &type);
+
+ dom_node_unref(parent);
+
+ if (err != DOM_NO_ERR)
+ return false;
+
+ if (type != DOM_DOCUMENT_NODE)
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Extract transient construction properties
+ *
+ * \param n Current DOM node to convert
+ * \param props Property object to populate
+ */
+static void
+box_extract_properties(dom_node *n, struct box_construct_props *props)
+{
+ memset(props, 0, sizeof(*props));
+
+ props->node_is_root = box_is_root(n);
+
+ /* Extract properties from containing DOM node */
+ if (props->node_is_root == false) {
+ dom_node *current_node = n;
+ dom_node *parent_node = NULL;
+ struct box *parent_box;
+ dom_exception err;
+
+ /* Find ancestor node containing parent box */
+ while (true) {
+ err = dom_node_get_parent_node(current_node,
+ &parent_node);
+ if (err != DOM_NO_ERR || parent_node == NULL)
+ break;
+
+ parent_box = box_for_node(parent_node);
+
+ if (parent_box != NULL) {
+ props->parent_style = parent_box->style;
+ props->href = parent_box->href;
+ props->target = parent_box->target;
+ props->title = parent_box->title;
+
+ dom_node_unref(parent_node);
+ break;
+ } else {
+ if (current_node != n)
+ dom_node_unref(current_node);
+ current_node = parent_node;
+ parent_node = NULL;
+ }
+ }
+
+ /* Find containing block (may be parent) */
+ while (true) {
+ struct box *b;
+
+ err = dom_node_get_parent_node(current_node,
+ &parent_node);
+ if (err != DOM_NO_ERR || parent_node == NULL) {
+ if (current_node != n)
+ dom_node_unref(current_node);
+ break;
+ }
+
+ if (current_node != n)
+ dom_node_unref(current_node);
+
+ b = box_for_node(parent_node);
+
+ /* Children of nodes that created an inline box
+ * will generate boxes which are attached as
+ * _siblings_ of the box generated for their
+ * parent node. Note, however, that we'll still
+ * use the parent node's styling as the parent
+ * style, above. */
+ if (b != NULL && b->type != BOX_INLINE &&
+ b->type != BOX_BR) {
+ props->containing_block = b;
+
+ dom_node_unref(parent_node);
+ break;
+ } else {
+ current_node = parent_node;
+ parent_node = NULL;
+ }
+ }
+ }
+
+ /* Compute current inline container, if any */
+ if (props->containing_block != NULL &&
+ props->containing_block->last != NULL &&
+ props->containing_block->last->type ==
+ BOX_INLINE_CONTAINER)
+ props->inline_container = props->containing_block->last;
+}
+
+
+/**
+ * Get the style for an element.
+ *
+ * \param c content of type CONTENT_HTML that is being processed
+ * \param parent_style style at this point in xml tree, or NULL for root
+ * \param root_style root node's style, or NULL for root
+ * \param n node in xml tree
+ * \return the new style, or NULL on memory exhaustion
+ */
+static css_select_results *
+box_get_style(html_content *c,
+ const css_computed_style *parent_style,
+ const css_computed_style *root_style,
+ dom_node *n)
+{
+ dom_string *s = NULL;
+ css_stylesheet *inline_style = NULL;
+ css_select_results *styles;
+ nscss_select_ctx ctx;
+
+ /* Firstly, construct inline stylesheet, if any */
+ if (nsoption_bool(author_level_css)) {
+ dom_exception err;
+ err = dom_element_get_attribute(n, corestring_dom_style, &s);
+ if (err != DOM_NO_ERR) {
+ return NULL;
+ }
+ }
+
+ if (s != NULL) {
+ inline_style = nscss_create_inline_style(
+ (const uint8_t *) dom_string_data(s),
+ dom_string_byte_length(s),
+ c->encoding,
+ nsurl_access(c->base_url),
+ c->quirks != DOM_DOCUMENT_QUIRKS_MODE_NONE);
+
+ dom_string_unref(s);
+
+ if (inline_style == NULL)
+ return NULL;
+ }
+
+ /* Populate selection context */
+ ctx.ctx = c->select_ctx;
+ ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
+ ctx.base_url = c->base_url;
+ ctx.universal = c->universal;
+ ctx.root_style = root_style;
+ ctx.parent_style = parent_style;
+
+ /* Select style for element */
+ styles = nscss_get_style(&ctx, n, &c->media, &c->unit_len_ctx,
+ inline_style);
+
+ /* No longer need inline style */
+ if (inline_style != NULL)
+ css_stylesheet_destroy(inline_style);
+
+ return styles;
+}
+
+
+/**
+ * Construct the box required for a generated element.
+ *
+ * \param n XML node of type XML_ELEMENT_NODE
+ * \param content Content of type CONTENT_HTML that is being processed
+ * \param box Box which may have generated content
+ * \param style Complete computed style for pseudo element, or NULL
+ *
+ * \todo This is currently incomplete. It just does enough to support
+ * the clearfix hack. (http://www.positioniseverything.net/easyclearing.html )
+ */
+static void
+box_construct_generate(dom_node *n,
+ html_content *content,
+ struct box *box,
+ const css_computed_style *style)
+{
+ struct box *gen = NULL;
+ enum css_display_e computed_display;
+ const css_computed_content_item *c_item;
+
+ /* Nothing to generate if the parent box is not a block */
+ if (box->type != BOX_BLOCK)
+ return;
+
+ /* To determine if an element has a pseudo element, we select
+ * for it and test to see if the returned style's content
+ * property is set to normal. */
+ if (style == NULL ||
+ css_computed_content(style, &c_item) ==
+ CSS_CONTENT_NORMAL) {
+ /* No pseudo element */
+ return;
+ }
+
+ /* create box for this element */
+ computed_display = ns_computed_display(style, box_is_root(n));
+ if (computed_display == CSS_DISPLAY_BLOCK ||
+ computed_display == CSS_DISPLAY_TABLE) {
+ /* currently only support block level boxes */
+
+ /** \todo Not wise to drop const from the computed style */
+ gen = box_create(NULL, (css_computed_style *) style,
+ false, NULL, NULL, NULL, NULL, content->bctx);
+ if (gen == NULL) {
+ return;
+ }
+
+ /* set box type from computed display */
+ gen->type = box_map[ns_computed_display(
+ style, box_is_root(n))];
+
+ box_add_child(box, gen);
+ }
+}
+
+
+/**
+ * Construct a list marker box
+ *
+ * \param box Box to attach marker to
+ * \param title Current title attribute
+ * \param ctx Box construction context
+ * \param parent Current block-level container
+ * \return true on success, false on memory exhaustion
+ */
+static bool
+box_construct_marker(struct box *box,
+ const char *title,
+ struct box_construct_ctx *ctx,
+ struct box *parent)
+{
+ lwc_string *image_uri;
+ struct box *marker;
+ enum css_list_style_type_e list_style_type;
+
+ marker = box_create(NULL, box->style, false, NULL, NULL, title,
+ NULL, ctx->bctx);
+ if (marker == false)
+ return false;
+
+ marker->type = BOX_BLOCK;
+
+ list_style_type = css_computed_list_style_type(box->style);
+
+ /** \todo marker content (list-style-type) */
+ switch (list_style_type) {
+ case CSS_LIST_STYLE_TYPE_DISC:
+ /* 2022 BULLET */
+ marker->text = (char *) "\342\200\242";
+ marker->length = 3;
+ break;
+
+ case CSS_LIST_STYLE_TYPE_CIRCLE:
+ /* 25CB WHITE CIRCLE */
+ marker->text = (char *) "\342\227\213";
+ marker->length = 3;
+ break;
+
+ case CSS_LIST_STYLE_TYPE_SQUARE:
+ /* 25AA BLACK SMALL SQUARE */
+ marker->text = (char *) "\342\226\252";
+ marker->length = 3;
+ break;
+
+ default:
+ /* Numerical list counters get handled in layout. */
+ /* Fall through. */
+ case CSS_LIST_STYLE_TYPE_NONE:
+ marker->text = NULL;
+ marker->length = 0;
+ break;
+ }
+
+ if (css_computed_list_style_image(box->style, &image_uri) == CSS_LIST_STYLE_IMAGE_URI &&
+ (image_uri != NULL) &&
+ (nsoption_bool(foreground_images) == true)) {
+ nsurl *url;
+ nserror error;
+
+ /* TODO: we get a url out of libcss as a lwc string, but
+ * earlier we already had it as a nsurl after we
+ * nsurl_joined it. Can this be improved?
+ * For now, just making another nsurl. */
+ error = nsurl_create(lwc_string_data(image_uri), &url);
+ if (error != NSERROR_OK)
+ return false;
+
+ if (html_fetch_object(ctx->content,
+ url,
+ marker,
+ image_types,
+ false) == false) {
+ nsurl_unref(url);
+ return false;
+ }
+ nsurl_unref(url);
+ }
+
+ box->list_marker = marker;
+ marker->parent = box;
+
+ return true;
+}
+
+static inline bool box__style_is_float(const struct box *box)
+{
+ return css_computed_float(box->style) == CSS_FLOAT_LEFT ||
+ css_computed_float(box->style) == CSS_FLOAT_RIGHT;
+}
+
+static inline bool box__is_flex(const struct box *box)
+{
+ return box->type == BOX_FLEX || box->type == BOX_INLINE_FLEX;
+}
+
+static inline bool box__containing_block_is_flex(
+ const struct box_construct_props *props)
+{
+ return props->containing_block != NULL &&
+ box__is_flex(props->containing_block);
+}
+
+/**
+ * Construct the box tree for an XML element.
+ *
+ * \param ctx Tree construction context
+ * \param convert_children Whether to convert children
+ * \return true on success, false on memory exhaustion
+ */
+static bool
+box_construct_element(struct box_construct_ctx *ctx, bool *convert_children)
+{
+ dom_string *title0, *s;
+ lwc_string *id = NULL;
+ enum css_display_e css_display;
+ struct box *box = NULL, *old_box;
+ css_select_results *styles = NULL;
+ lwc_string *bgimage_uri;
+ dom_exception err;
+ struct box_construct_props props;
+ const css_computed_style *root_style = NULL;
+
+ assert(ctx->n != NULL);
+
+ box_extract_properties(ctx->n, &props);
+
+ if (props.containing_block != NULL) {
+ /* In case the containing block is a pre block, we clear
+ * the PRE_STRIP flag since it is not used if we follow
+ * the pre with a tag */
+ props.containing_block->flags &= ~PRE_STRIP;
+ }
+
+ if (props.node_is_root == false) {
+ root_style = ctx->root_box->style;
+ }
+
+ styles = box_get_style(ctx->content, props.parent_style, root_style,
+ ctx->n);
+ if (styles == NULL)
+ return false;
+
+ /* Extract title attribute, if present */
+ err = dom_element_get_attribute(ctx->n, corestring_dom_title, &title0);
+ if (err != DOM_NO_ERR)
+ return false;
+
+ if (title0 != NULL) {
+ char *t = squash_whitespace(dom_string_data(title0));
+
+ dom_string_unref(title0);
+
+ if (t == NULL)
+ return false;
+
+ props.title = talloc_strdup(ctx->bctx, t);
+
+ free(t);
+
+ if (props.title == NULL)
+ return false;
+ }
+
+ /* Extract id attribute, if present */
+ err = dom_element_get_attribute(ctx->n, corestring_dom_id, &s);
+ if (err != DOM_NO_ERR)
+ return false;
+
+ if (s != NULL) {
+ err = dom_string_intern(s, &id);
+ if (err != DOM_NO_ERR)
+ id = NULL;
+
+ dom_string_unref(s);
+ }
+
+ box = box_create(styles, styles->styles[CSS_PSEUDO_ELEMENT_NONE], false,
+ props.href, props.target, props.title, id,
+ ctx->bctx);
+ if (box == NULL)
+ return false;
+
+ /* If this is the root box, add it to the context */
+ if (props.node_is_root)
+ ctx->root_box = box;
+
+ /* Deal with colspan/rowspan */
+ err = dom_element_get_attribute(ctx->n, corestring_dom_colspan, &s);
+ if (err != DOM_NO_ERR)
+ return false;
+
+ if (s != NULL) {
+ const char *val = dom_string_data(s);
+
+ if ('0' <= val[0] && val[0] <= '9')
+ box->columns = strtol(val, NULL, 10);
+
+ dom_string_unref(s);
+ }
+
+ err = dom_element_get_attribute(ctx->n, corestring_dom_rowspan, &s);
+ if (err != DOM_NO_ERR)
+ return false;
+
+ if (s != NULL) {
+ const char *val = dom_string_data(s);
+
+ if ('0' <= val[0] && val[0] <= '9')
+ box->rows = strtol(val, NULL, 10);
+
+ dom_string_unref(s);
+ }
+
+ css_display = ns_computed_display_static(box->style);
+
+ /* Set box type from computed display */
+ if ((css_computed_position(box->style) == CSS_POSITION_ABSOLUTE ||
+ css_computed_position(box->style) == CSS_POSITION_FIXED) &&
+ (css_display == CSS_DISPLAY_INLINE ||
+ css_display == CSS_DISPLAY_INLINE_BLOCK ||
+ css_display == CSS_DISPLAY_INLINE_TABLE ||
+ css_display == CSS_DISPLAY_INLINE_FLEX)) {
+ /* Special case for absolute positioning: make absolute inlines
+ * into inline block so that the boxes are constructed in an
+ * inline container as if they were not absolutely positioned.
+ * Layout expects and handles this. */
+ box->type = box_map[CSS_DISPLAY_INLINE_BLOCK];
+ } else if (props.node_is_root) {
+ /* Special case for root element: force it to BLOCK, or the
+ * rest of the layout will break. */
+ box->type = BOX_BLOCK;
+ } else {
+ /* Normal mapping */
+ box->type = box_map[ns_computed_display(box->style,
+ props.node_is_root)];
+
+ if (props.containing_block->type == BOX_FLEX ||
+ props.containing_block->type == BOX_INLINE_FLEX) {
+ /* Blockification */
+ switch (box->type) {
+ case BOX_INLINE_FLEX:
+ box->type = BOX_FLEX;
+ break;
+ case BOX_INLINE_BLOCK:
+ box->type = BOX_BLOCK;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (convert_special_elements(ctx->n,
+ ctx->content,
+ box,
+ convert_children) == false) {
+ return false;
+ }
+
+ /* Handle the :before pseudo element */
+ if (!(box->flags & IS_REPLACED)) {
+ box_construct_generate(ctx->n, ctx->content, box,
+ box->styles->styles[CSS_PSEUDO_ELEMENT_BEFORE]);
+ }
+
+ if (box->type == BOX_NONE || (ns_computed_display(box->style,
+ props.node_is_root) == CSS_DISPLAY_NONE &&
+ props.node_is_root == false)) {
+ css_select_results_destroy(styles);
+ box->styles = NULL;
+ box->style = NULL;
+
+ /* Invalidate associated gadget, if any */
+ if (box->gadget != NULL) {
+ box->gadget->box = NULL;
+ box->gadget = NULL;
+ }
+
+ /* Can't do this, because the lifetimes of boxes and gadgets
+ * are inextricably linked. Fortunately, talloc will save us
+ * (for now) */
+ /* box_free_box(box); */
+
+ *convert_children = false;
+
+ return true;
+ }
+
+ /* Attach DOM node to box */
+ err = dom_node_set_user_data(ctx->n,
+ corestring_dom___ns_key_box_node_data, box, NULL,
+ (void *) &old_box);
+ if (err != DOM_NO_ERR)
+ return false;
+
+ /* Attach box to DOM node */
+ box->node = dom_node_ref(ctx->n);
+
+ if (props.inline_container == NULL &&
+ (box->type == BOX_INLINE ||
+ box->type == BOX_BR ||
+ box->type == BOX_INLINE_BLOCK ||
+ box->type == BOX_INLINE_FLEX ||
+ (box__style_is_float(box) &&
+ !box__containing_block_is_flex(&props))) &&
+ props.node_is_root == false) {
+ /* Found an inline child of a block without a current container
+ * (i.e. this box is the first child of its parent, or was
+ * preceded by block-level siblings) */
+ assert(props.containing_block != NULL &&
+ "Box must have containing block.");
+
+ props.inline_container = box_create(NULL, NULL, false, NULL,
+ NULL, NULL, NULL, ctx->bctx);
+ if (props.inline_container == NULL)
+ return false;
+
+ props.inline_container->type = BOX_INLINE_CONTAINER;
+
+ box_add_child(props.containing_block, props.inline_container);
+ }
+
+ /* Kick off fetch for any background image */
+ if (css_computed_background_image(box->style, &bgimage_uri) ==
+ CSS_BACKGROUND_IMAGE_IMAGE && bgimage_uri != NULL &&
+ nsoption_bool(background_images) == true) {
+ nsurl *url;
+ nserror error;
+
+ /* TODO: we get a url out of libcss as a lwc string, but
+ * earlier we already had it as a nsurl after we
+ * nsurl_joined it. Can this be improved?
+ * For now, just making another nsurl. */
+ error = nsurl_create(lwc_string_data(bgimage_uri), &url);
+ if (error == NSERROR_OK) {
+ /* Fetch image if we got a valid URL */
+ if (html_fetch_object(ctx->content,
+ url,
+ box,
+ image_types,
+ true) == false) {
+ nsurl_unref(url);
+ return false;
+ }
+ nsurl_unref(url);
+ }
+ }
+
+ if (*convert_children)
+ box->flags |= CONVERT_CHILDREN;
+
+ if (box->type == BOX_INLINE || box->type == BOX_BR ||
+ box->type == BOX_INLINE_FLEX ||
+ box->type == BOX_INLINE_BLOCK) {
+ /* Inline container must exist, as we'll have
+ * created it above if it didn't */
+ assert(props.inline_container != NULL);
+
+ box_add_child(props.inline_container, box);
+ } else {
+ if (ns_computed_display(box->style, props.node_is_root) ==
+ CSS_DISPLAY_LIST_ITEM) {
+ /* List item: compute marker */
+ if (box_construct_marker(box, props.title, ctx,
+ props.containing_block) == false)
+ return false;
+ }
+
+ if (props.node_is_root == false &&
+ box__containing_block_is_flex(&props) == false &&
+ (css_computed_float(box->style) ==
+ CSS_FLOAT_LEFT ||
+ css_computed_float(box->style) ==
+ CSS_FLOAT_RIGHT)) {
+ /* Float: insert a float between the parent and box. */
+ struct box *flt = box_create(NULL, NULL, false,
+ props.href, props.target, props.title,
+ NULL, ctx->bctx);
+ if (flt == NULL)
+ return false;
+
+ if (css_computed_float(box->style) == CSS_FLOAT_LEFT)
+ flt->type = BOX_FLOAT_LEFT;
+ else
+ flt->type = BOX_FLOAT_RIGHT;
+
+ box_add_child(props.inline_container, flt);
+ box_add_child(flt, box);
+ } else {
+ /* Non-floated block-level box: add to containing block
+ * if there is one. If we're the root box, then there
+ * won't be. */
+ if (props.containing_block != NULL)
+ box_add_child(props.containing_block, box);
+ }
+ }
+
+ return true;
+}
+
+
+/**
+ * Complete construction of the box tree for an element.
+ *
+ * \param n DOM node to construct for
+ * \param content Containing document
+ *
+ * This will be called after all children of an element have been processed
+ */
+static void box_construct_element_after(dom_node *n, html_content *content)
+{
+ struct box_construct_props props;
+ struct box *box = box_for_node(n);
+
+ assert(box != NULL);
+
+ box_extract_properties(n, &props);
+
+ if (box->type == BOX_INLINE || box->type == BOX_BR) {
+ /* Insert INLINE_END into containing block */
+ struct box *inline_end;
+ bool has_children;
+ dom_exception err;
+
+ err = dom_node_has_child_nodes(n, &has_children);
+ if (err != DOM_NO_ERR)
+ return;
+
+ if (has_children == false ||
+ (box->flags & CONVERT_CHILDREN) == 0) {
+ /* No children, or didn't want children converted */
+ return;
+ }
+
+ if (props.inline_container == NULL) {
+ /* Create inline container if we don't have one */
+ props.inline_container = box_create(NULL, NULL, false,
+ NULL, NULL, NULL, NULL, content->bctx);
+ if (props.inline_container == NULL)
+ return;
+
+ props.inline_container->type = BOX_INLINE_CONTAINER;
+
+ box_add_child(props.containing_block,
+ props.inline_container);
+ }
+
+ inline_end = box_create(NULL, box->style, false,
+ box->href, box->target, box->title,
+ box->id == NULL ? NULL :
+ lwc_string_ref(box->id), content->bctx);
+ if (inline_end != NULL) {
+ inline_end->type = BOX_INLINE_END;
+
+ assert(props.inline_container != NULL);
+
+ box_add_child(props.inline_container, inline_end);
+
+ box->inline_end = inline_end;
+ inline_end->inline_end = box;
+ }
+ } else if (!(box->flags & IS_REPLACED)) {
+ /* Handle the :after pseudo element */
+ box_construct_generate(n, content, box,
+ box->styles->styles[CSS_PSEUDO_ELEMENT_AFTER]);
+ }
+}
+
+
+/**
+ * Find the next node in the DOM tree, completing element construction
+ * where appropriate.
+ *
+ * \param n Current node
+ * \param content Containing content
+ * \param convert_children Whether to consider children of \a n
+ * \return Next node to process, or NULL if complete
+ *
+ * \note \a n will be unreferenced
+ */
+static dom_node *
+next_node(dom_node *n, html_content *content, bool convert_children)
+{
+ dom_node *next = NULL;
+ bool has_children;
+ dom_exception err;
+
+ err = dom_node_has_child_nodes(n, &has_children);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(n);
+ return NULL;
+ }
+
+ if (convert_children && has_children) {
+ err = dom_node_get_first_child(n, &next);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(n);
+ return NULL;
+ }
+ dom_node_unref(n);
+ } else {
+ err = dom_node_get_next_sibling(n, &next);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(n);
+ return NULL;
+ }
+
+ if (next != NULL) {
+ if (box_for_node(n) != NULL)
+ box_construct_element_after(n, content);
+ dom_node_unref(n);
+ } else {
+ if (box_for_node(n) != NULL)
+ box_construct_element_after(n, content);
+
+ while (box_is_root(n) == false) {
+ dom_node *parent = NULL;
+ dom_node *parent_next = NULL;
+
+ err = dom_node_get_parent_node(n, &parent);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(n);
+ return NULL;
+ }
+
+ assert(parent != NULL);
+
+ err = dom_node_get_next_sibling(parent,
+ &parent_next);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(parent);
+ dom_node_unref(n);
+ return NULL;
+ }
+
+ if (parent_next != NULL) {
+ dom_node_unref(parent_next);
+ dom_node_unref(parent);
+ break;
+ }
+
+ dom_node_unref(n);
+ n = parent;
+ parent = NULL;
+
+ if (box_for_node(n) != NULL) {
+ box_construct_element_after(
+ n, content);
+ }
+ }
+
+ if (box_is_root(n) == false) {
+ dom_node *parent = NULL;
+
+ err = dom_node_get_parent_node(n, &parent);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(n);
+ return NULL;
+ }
+
+ assert(parent != NULL);
+
+ err = dom_node_get_next_sibling(parent, &next);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(parent);
+ dom_node_unref(n);
+ return NULL;
+ }
+
+ if (box_for_node(parent) != NULL) {
+ box_construct_element_after(parent,
+ content);
+ }
+
+ dom_node_unref(parent);
+ }
+
+ dom_node_unref(n);
+ }
+ }
+
+ return next;
+}
+
+
+/**
+ * Apply the CSS text-transform property to given text for its ASCII chars.
+ *
+ * \param s string to transform
+ * \param len length of s
+ * \param tt transform type
+ */
+static void
+box_text_transform(char *s, unsigned int len, enum css_text_transform_e tt)
+{
+ unsigned int i;
+ if (len == 0)
+ return;
+ switch (tt) {
+ case CSS_TEXT_TRANSFORM_UPPERCASE:
+ for (i = 0; i < len; ++i)
+ if ((unsigned char) s[i] < 0x80)
+ s[i] = ascii_to_upper(s[i]);
+ break;
+ case CSS_TEXT_TRANSFORM_LOWERCASE:
+ for (i = 0; i < len; ++i)
+ if ((unsigned char) s[i] < 0x80)
+ s[i] = ascii_to_lower(s[i]);
+ break;
+ case CSS_TEXT_TRANSFORM_CAPITALIZE:
+ if ((unsigned char) s[0] < 0x80)
+ s[0] = ascii_to_upper(s[0]);
+ for (i = 1; i < len; ++i)
+ if ((unsigned char) s[i] < 0x80 &&
+ ascii_is_space(s[i - 1]))
+ s[i] = ascii_to_upper(s[i]);
+ break;
+ default:
+ break;
+ }
+}
+
+
+/**
+ * Construct the box tree for an XML text node.
+ *
+ * \param ctx Tree construction context
+ * \return true on success, false on memory exhaustion
+ */
+static bool box_construct_text(struct box_construct_ctx *ctx)
+{
+ struct box_construct_props props;
+ struct box *box = NULL;
+ dom_string *content;
+ dom_exception err;
+
+ assert(ctx->n != NULL);
+
+ box_extract_properties(ctx->n, &props);
+
+ assert(props.containing_block != NULL);
+
+ err = dom_characterdata_get_data(ctx->n, &content);
+ if (err != DOM_NO_ERR || content == NULL)
+ return false;
+
+ if (css_computed_white_space(props.parent_style) ==
+ CSS_WHITE_SPACE_NORMAL ||
+ css_computed_white_space(props.parent_style) ==
+ CSS_WHITE_SPACE_NOWRAP) {
+ char *text;
+
+ text = squash_whitespace(dom_string_data(content));
+
+ dom_string_unref(content);
+
+ if (text == NULL)
+ return false;
+
+ /* if the text is just a space, combine it with the preceding
+ * text node, if any */
+ if (text[0] == ' ' && text[1] == 0) {
+ if (props.inline_container != NULL) {
+ assert(props.inline_container->last != NULL);
+
+ props.inline_container->last->space =
+ UNKNOWN_WIDTH;
+ }
+
+ free(text);
+
+ return true;
+ }
+
+ if (props.inline_container == NULL) {
+ /* Child of a block without a current container
+ * (i.e. this box is the first child of its parent, or
+ * was preceded by block-level siblings) */
+ props.inline_container = box_create(NULL, NULL, false,
+ NULL, NULL, NULL, NULL, ctx->bctx);
+ if (props.inline_container == NULL) {
+ free(text);
+ return false;
+ }
+
+ props.inline_container->type = BOX_INLINE_CONTAINER;
+
+ box_add_child(props.containing_block,
+ props.inline_container);
+ }
+
+ /** \todo Dropping const here is not clever */
+ box = box_create(NULL,
+ (css_computed_style *) props.parent_style,
+ false, props.href, props.target, props.title,
+ NULL, ctx->bctx);
+ if (box == NULL) {
+ free(text);
+ return false;
+ }
+
+ box->type = BOX_TEXT;
+
+ box->text = talloc_strdup(ctx->bctx, text);
+ free(text);
+ if (box->text == NULL)
+ return false;
+
+ box->length = strlen(box->text);
+
+ /* strip ending space char off */
+ if (box->length > 1 && box->text[box->length - 1] == ' ') {
+ box->space = UNKNOWN_WIDTH;
+ box->length--;
+ }
+
+ if (css_computed_text_transform(props.parent_style) !=
+ CSS_TEXT_TRANSFORM_NONE)
+ box_text_transform(box->text, box->length,
+ css_computed_text_transform(
+ props.parent_style));
+
+ box_add_child(props.inline_container, box);
+
+ if (box->text[0] == ' ') {
+ box->length--;
+
+ memmove(box->text, &box->text[1], box->length);
+
+ if (box->prev != NULL)
+ box->prev->space = UNKNOWN_WIDTH;
+ }
+ } else {
+ /* white-space: pre */
+ char *text;
+ size_t text_len = dom_string_byte_length(content);
+ size_t i;
+ char *current;
+ enum css_white_space_e white_space =
+ css_computed_white_space(props.parent_style);
+
+ /* note: pre-wrap/pre-line are unimplemented */
+ assert(white_space == CSS_WHITE_SPACE_PRE ||
+ white_space == CSS_WHITE_SPACE_PRE_LINE ||
+ white_space == CSS_WHITE_SPACE_PRE_WRAP);
+
+ text = malloc(text_len + 1);
+ dom_string_unref(content);
+
+ if (text == NULL)
+ return false;
+
+ memcpy(text, dom_string_data(content), text_len);
+ text[text_len] = '\0';
+
+ /* TODO: Handle tabs properly */
+ for (i = 0; i < text_len; i++)
+ if (text[i] == '\t')
+ text[i] = ' ';
+
+ if (css_computed_text_transform(props.parent_style) !=
+ CSS_TEXT_TRANSFORM_NONE)
+ box_text_transform(text, strlen(text),
+ css_computed_text_transform(
+ props.parent_style));
+
+ current = text;
+
+ /* swallow a single leading new line */
+ if (props.containing_block->flags & PRE_STRIP) {
+ switch (*current) {
+ case '\n':
+ current++;
+ break;
+ case '\r':
+ current++;
+ if (*current == '\n')
+ current++;
+ break;
+ }
+ props.containing_block->flags &= ~PRE_STRIP;
+ }
+
+ do {
+ size_t len = strcspn(current, "\r\n");
+
+ char old = current[len];
+
+ current[len] = 0;
+
+ if (props.inline_container == NULL) {
+ /* Child of a block without a current container
+ * (i.e. this box is the first child of its
+ * parent, or was preceded by block-level
+ * siblings) */
+ props.inline_container = box_create(NULL, NULL,
+ false, NULL, NULL, NULL, NULL,
+ ctx->bctx);
+ if (props.inline_container == NULL) {
+ free(text);
+ return false;
+ }
+
+ props.inline_container->type =
+ BOX_INLINE_CONTAINER;
+
+ box_add_child(props.containing_block,
+ props.inline_container);
+ }
+
+ /** \todo Dropping const isn't clever */
+ box = box_create(NULL,
+ (css_computed_style *) props.parent_style,
+ false, props.href, props.target, props.title,
+ NULL, ctx->bctx);
+ if (box == NULL) {
+ free(text);
+ return false;
+ }
+
+ box->type = BOX_TEXT;
+
+ box->text = talloc_strdup(ctx->bctx, current);
+ if (box->text == NULL) {
+ free(text);
+ return false;
+ }
+
+ box->length = strlen(box->text);
+
+ box_add_child(props.inline_container, box);
+
+ current[len] = old;
+
+ current += len;
+
+ if (current[0] != '\0') {
+ /* Linebreak: create new inline container */
+ props.inline_container = box_create(NULL, NULL,
+ false, NULL, NULL, NULL, NULL,
+ ctx->bctx);
+ if (props.inline_container == NULL) {
+ free(text);
+ return false;
+ }
+
+ props.inline_container->type =
+ BOX_INLINE_CONTAINER;
+
+ box_add_child(props.containing_block,
+ props.inline_container);
+
+ if (current[0] == '\r' && current[1] == '\n')
+ current += 2;
+ else
+ current++;
+ }
+ } while (*current);
+
+ free(text);
+ }
+
+ return true;
+}
+
+
+/**
+ * Convert an ELEMENT node to a box tree fragment,
+ * then schedule conversion of the next ELEMENT node
+ */
+static void convert_xml_to_box(struct box_construct_ctx *ctx)
+{
+ dom_node *next;
+ bool convert_children;
+ uint32_t num_processed = 0;
+ const uint32_t max_processed_before_yield = 10;
+
+ do {
+ convert_children = true;
+
+ assert(ctx->n != NULL);
+
+ if (box_construct_element(ctx, &convert_children) == false) {
+ ctx->cb(ctx->content, false);
+ dom_node_unref(ctx->n);
+ free(ctx);
+ return;
+ }
+
+ /* Find next element to process, converting text nodes as we go */
+ next = next_node(ctx->n, ctx->content, convert_children);
+ while (next != NULL) {
+ dom_node_type type;
+ dom_exception err;
+
+ err = dom_node_get_node_type(next, &type);
+ if (err != DOM_NO_ERR) {
+ ctx->cb(ctx->content, false);
+ dom_node_unref(next);
+ free(ctx);
+ return;
+ }
+
+ if (type == DOM_ELEMENT_NODE)
+ break;
+
+ if (type == DOM_TEXT_NODE) {
+ ctx->n = next;
+ if (box_construct_text(ctx) == false) {
+ ctx->cb(ctx->content, false);
+ dom_node_unref(ctx->n);
+ free(ctx);
+ return;
+ }
+ }
+
+ next = next_node(next, ctx->content, true);
+ }
+
+ ctx->n = next;
+
+ if (next == NULL) {
+ /* Conversion complete */
+ struct box root;
+
+ memset(&root, 0, sizeof(root));
+
+ root.type = BOX_BLOCK;
+ root.children = root.last = ctx->root_box;
+ root.children->parent = &root;
+
+ /** \todo Remove box_normalise_block */
+ if (box_normalise_block(&root, ctx->root_box,
+ ctx->content) == false) {
+ ctx->cb(ctx->content, false);
+ } else {
+ ctx->content->layout = root.children;
+ ctx->content->layout->parent = NULL;
+
+ ctx->cb(ctx->content, true);
+ }
+
+ assert(ctx->n == NULL);
+
+ free(ctx);
+ return;
+ }
+ } while (++num_processed < max_processed_before_yield);
+
+ /* More work to do: schedule a continuation */
+ guit->misc->schedule(0, (void *)convert_xml_to_box, ctx);
+}
+
+
+/* exported function documented in html/box_construct.h */
+nserror
+dom_to_box(dom_node *n,
+ html_content *c,
+ box_construct_complete_cb cb,
+ void **box_conversion_context)
+{
+ struct box_construct_ctx *ctx;
+
+ assert(box_conversion_context != NULL);
+
+ if (c->bctx == NULL) {
+ /* create a context allocation for this box tree */
+ c->bctx = talloc_zero(0, int);
+ if (c->bctx == NULL) {
+ return NSERROR_NOMEM;
+ }
+ }
+
+ ctx = malloc(sizeof(*ctx));
+ if (ctx == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ ctx->content = c;
+ ctx->n = dom_node_ref(n);
+ ctx->root_box = NULL;
+ ctx->cb = cb;
+ ctx->bctx = c->bctx;
+
+ *box_conversion_context = ctx;
+
+ return guit->misc->schedule(0, (void *)convert_xml_to_box, ctx);
+}
+
+
+/* exported function documented in html/box_construct.h */
+nserror cancel_dom_to_box(void *box_conversion_context)
+{
+ struct box_construct_ctx *ctx = box_conversion_context;
+ nserror err;
+
+ err = guit->misc->schedule(-1, (void *)convert_xml_to_box, ctx);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
+ dom_node_unref(ctx->n);
+ free(ctx);
+
+ return NSERROR_OK;
+}
+
+
+/* exported function documented in html/box_construct.h */
+struct box *box_for_node(dom_node *n)
+{
+ struct box *box = NULL;
+ dom_exception err;
+
+ err = dom_node_get_user_data(n, corestring_dom___ns_key_box_node_data,
+ (void *) &box);
+ if (err != DOM_NO_ERR)
+ return NULL;
+
+ return box;
+}
+
+/* exported function documented in html/box_construct.h */
+bool
+box_extract_link(const html_content *content,
+ const dom_string *dsrel,
+ nsurl *base,
+ nsurl **result)
+{
+ char *s, *s1, *apos0 = 0, *apos1 = 0, *quot0 = 0, *quot1 = 0;
+ unsigned int i, j, end;
+ nserror error;
+ const char *rel;
+
+ rel = dom_string_data(dsrel);
+
+ s1 = s = malloc(3 * strlen(rel) + 1);
+ if (!s)
+ return false;
+
+ /* copy to s, removing white space and control characters */
+ for (i = 0; rel[i] && ascii_is_space(rel[i]); i++)
+ ;
+ for (end = strlen(rel);
+ (end != i) && ascii_is_space(rel[end - 1]);
+ end--)
+ ;
+ for (j = 0; i != end; i++) {
+ if ((unsigned char) rel[i] < 0x20) {
+ ; /* skip control characters */
+ } else if (rel[i] == ' ') {
+ s[j++] = '%';
+ s[j++] = '2';
+ s[j++] = '0';
+ } else {
+ s[j++] = rel[i];
+ }
+ }
+ s[j] = 0;
+
+ if (content->enable_scripting == false) {
+ /* extract first quoted string out of "javascript:" link */
+ if (strncmp(s, "javascript:", 11) == 0) {
+ apos0 = strchr(s, '\'');
+ if (apos0)
+ apos1 = strchr(apos0 + 1, '\'');
+ quot0 = strchr(s, '"');
+ if (quot0)
+ quot1 = strchr(quot0 + 1, '"');
+ if (apos0 && apos1 &&
+ (!quot0 || !quot1 || apos0 < quot0)) {
+ *apos1 = 0;
+ s1 = apos0 + 1;
+ } else if (quot0 && quot1) {
+ *quot1 = 0;
+ s1 = quot0 + 1;
+ }
+ }
+ }
+
+ /* construct absolute URL */
+ error = nsurl_join(base, s1, result);
+ free(s);
+ if (error != NSERROR_OK) {
+ *result = NULL;
+ return false;
+ }
+
+ return true;
+}
diff --git a/content/handlers/html/box_construct.h b/content/handlers/html/box_construct.h
new file mode 100644
index 000000000..f4bd119b1
--- /dev/null
+++ b/content/handlers/html/box_construct.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * HTML Box tree construction interface.
+ *
+ * This stage of rendering converts a tree of dom_nodes (produced by libdom)
+ * to a tree of struct box. The box tree represents the structure of the
+ * document as given by the CSS display and float properties.
+ *
+ * For example, consider the following HTML:
+ * \code
+ * <h1>Example Heading</h1>
+ * <p>Example paragraph <em>with emphasised text</em> etc.</p> \endcode
+ *
+ * This would produce approximately the following box tree with default CSS
+ * rules:
+ * \code
+ * BOX_BLOCK (corresponds to h1)
+ * BOX_INLINE_CONTAINER
+ * BOX_INLINE "Example Heading"
+ * BOX_BLOCK (p)
+ * BOX_INLINE_CONTAINER
+ * BOX_INLINE "Example paragraph "
+ * BOX_INLINE "with emphasised text" (em)
+ * BOX_INLINE "etc." \endcode
+ *
+ * Note that the em has been collapsed into the INLINE_CONTAINER.
+ *
+ * If these CSS rules were applied:
+ * \code
+ * h1 { display: table-cell }
+ * p { display: table-cell }
+ * em { float: left; width: 5em } \endcode
+ *
+ * then the box tree would instead look like this:
+ * \code
+ * BOX_TABLE
+ * BOX_TABLE_ROW_GROUP
+ * BOX_TABLE_ROW
+ * BOX_TABLE_CELL (h1)
+ * BOX_INLINE_CONTAINER
+ * BOX_INLINE "Example Heading"
+ * BOX_TABLE_CELL (p)
+ * BOX_INLINE_CONTAINER
+ * BOX_INLINE "Example paragraph "
+ * BOX_FLOAT_LEFT (em)
+ * BOX_BLOCK
+ * BOX_INLINE_CONTAINER
+ * BOX_INLINE "with emphasised text"
+ * BOX_INLINE "etc." \endcode
+ *
+ * Here implied boxes have been added and a float is present.
+ */
+
+#ifndef NETSURF_HTML_BOX_CONSTRUCT_H
+#define NETSURF_HTML_BOX_CONSTRUCT_H
+
+/**
+ * Construct a box tree from a dom and html content
+ *
+ * \param n dom document
+ * \param c content of type CONTENT_HTML to construct box tree in
+ * \param cb callback to report conversion completion
+ * \param box_conversion_context pointer that recives the conversion context
+ * \return netsurf error code indicating status of call
+ */
+nserror dom_to_box(struct dom_node *n, struct html_content *c, box_construct_complete_cb cb, void **box_conversion_context);
+
+
+/**
+ * aborts any ongoing box construction
+ */
+nserror cancel_dom_to_box(void *box_conversion_context);
+
+
+/**
+ * Retrieve the box for a dom node, if there is one
+ *
+ * \param node The DOM node
+ * \return The box if there is one
+ */
+struct box *box_for_node(struct dom_node *node);
+
+/**
+ * Extract a URL from a relative link, handling junk like whitespace and
+ * attempting to read a real URL from "javascript:" links.
+ *
+ * \param content html content
+ * \param dsrel relative URL text taken from page
+ * \param base base for relative URLs
+ * \param result updated to target URL on heap, unchanged if extract failed
+ * \return true on success, false on memory exhaustion
+ */
+bool box_extract_link(const struct html_content *content, const struct dom_string *dsrel, struct nsurl *base, struct nsurl **result);
+
+#endif
diff --git a/content/handlers/html/box_inspect.c b/content/handlers/html/box_inspect.c
new file mode 100644
index 000000000..6591b6446
--- /dev/null
+++ b/content/handlers/html/box_inspect.c
@@ -0,0 +1,898 @@
+/*
+ * Copyright 2008 Michael Drake <tlsa@netsurf-browser.org>
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * implementation of box tree inspection.
+ */
+
+#include <stdio.h>
+#include <dom/dom.h>
+
+#include "utils/utils.h"
+#include "utils/nsurl.h"
+#include "utils/errors.h"
+#include "netsurf/types.h"
+#include "netsurf/content.h"
+#include "netsurf/mouse.h"
+#include "css/utils.h"
+#include "css/dump.h"
+#include "desktop/scrollbar.h"
+
+#include "html/private.h"
+#include "html/box.h"
+#include "html/box_inspect.h"
+
+/**
+ * Direction to move in a box-tree walk
+ */
+enum box_walk_dir {
+ BOX_WALK_CHILDREN,
+ BOX_WALK_PARENT,
+ BOX_WALK_NEXT_SIBLING,
+ BOX_WALK_FLOAT_CHILDREN,
+ BOX_WALK_NEXT_FLOAT_SIBLING,
+ BOX_WALK_FLOAT_CONTAINER
+};
+
+#define box_is_float(box) (box->type == BOX_FLOAT_LEFT || \
+ box->type == BOX_FLOAT_RIGHT)
+
+/**
+ * Determine if a point lies within a box.
+ *
+ * \param[in] unit_len_ctx CSS length conversion context to use.
+ * \param[in] box Box to consider
+ * \param[in] x Coordinate relative to box
+ * \param[in] y Coordinate relative to box
+ * \param[out] physically If function returning true, physically is set true
+ * iff point is within the box's physical dimensions and
+ * false if the point is not within the box's physical
+ * dimensions but is in the area defined by the box's
+ * descendants. If function returns false, physically
+ * is undefined.
+ * \return true if the point is within the box or a descendant box
+ *
+ * This is a helper function for box_at_point().
+ */
+static bool
+box_contains_point(const css_unit_ctx *unit_len_ctx,
+ const struct box *box,
+ int x,
+ int y,
+ bool *physically)
+{
+ css_computed_clip_rect css_rect;
+
+ if (box->style != NULL &&
+ css_computed_position(box->style) == CSS_POSITION_ABSOLUTE &&
+ css_computed_clip(box->style, &css_rect) == CSS_CLIP_RECT) {
+ /* We have an absolutly positioned box with a clip rect */
+ struct rect r = {
+ .x0 = box->border[LEFT].width,
+ .y0 = box->border[TOP].width,
+ .x1 = box->padding[LEFT] + box->width +
+ box->border[RIGHT].width +
+ box->padding[RIGHT],
+ .y1 = box->padding[TOP] + box->height +
+ box->border[BOTTOM].width +
+ box->padding[BOTTOM]
+ };
+ if (x >= r.x0 && x < r.x1 && y >= r.y0 && y < r.y1) {
+ *physically = true;
+ } else {
+ *physically = false;
+ }
+
+ /* Adjust rect to css clip region */
+ if (css_rect.left_auto == false) {
+ r.x0 += FIXTOINT(css_unit_len2device_px(
+ box->style,
+ unit_len_ctx,
+ css_rect.left,
+ css_rect.lunit));
+ }
+ if (css_rect.top_auto == false) {
+ r.y0 += FIXTOINT(css_unit_len2device_px(
+ box->style,
+ unit_len_ctx,
+ css_rect.top,
+ css_rect.tunit));
+ }
+ if (css_rect.right_auto == false) {
+ r.x1 = box->border[LEFT].width +
+ FIXTOINT(css_unit_len2device_px(
+ box->style,
+ unit_len_ctx,
+ css_rect.right,
+ css_rect.runit));
+ }
+ if (css_rect.bottom_auto == false) {
+ r.y1 = box->border[TOP].width +
+ FIXTOINT(css_unit_len2device_px(
+ box->style,
+ unit_len_ctx,
+ css_rect.bottom,
+ css_rect.bunit));
+ }
+
+ /* Test if point is in clipped box */
+ if (x >= r.x0 && x < r.x1 && y >= r.y0 && y < r.y1) {
+ /* inside clip area */
+ return true;
+ }
+
+ /* Not inside clip area */
+ return false;
+ }
+ if (x >= -box->border[LEFT].width &&
+ x < box->padding[LEFT] + box->width +
+ box->padding[RIGHT] + box->border[RIGHT].width &&
+ y >= -box->border[TOP].width &&
+ y < box->padding[TOP] + box->height +
+ box->padding[BOTTOM] + box->border[BOTTOM].width) {
+ *physically = true;
+ return true;
+ }
+ if (box->list_marker && box->list_marker->x - box->x <= x +
+ box->list_marker->border[LEFT].width &&
+ x < box->list_marker->x - box->x +
+ box->list_marker->padding[LEFT] +
+ box->list_marker->width +
+ box->list_marker->border[RIGHT].width +
+ box->list_marker->padding[RIGHT] &&
+ box->list_marker->y - box->y <= y +
+ box->list_marker->border[TOP].width &&
+ y < box->list_marker->y - box->y +
+ box->list_marker->padding[TOP] +
+ box->list_marker->height +
+ box->list_marker->border[BOTTOM].width +
+ box->list_marker->padding[BOTTOM]) {
+ *physically = true;
+ return true;
+ }
+ if ((box->style && css_computed_overflow_x(box->style) ==
+ CSS_OVERFLOW_VISIBLE) || !box->style) {
+ if (box->descendant_x0 <= x &&
+ x < box->descendant_x1) {
+ *physically = false;
+ return true;
+ }
+ }
+ if ((box->style && css_computed_overflow_y(box->style) ==
+ CSS_OVERFLOW_VISIBLE) || !box->style) {
+ if (box->descendant_y0 <= y &&
+ y < box->descendant_y1) {
+ *physically = false;
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/**
+ * Move from box to next box in given direction, adjusting for box coord change
+ *
+ * \param b box to move from from
+ * \param dir direction to move in
+ * \param x box's global x-coord, updated to position of next box
+ * \param y box's global y-coord, updated to position of next box
+ *
+ * If no box can be found in given direction, NULL is returned.
+ */
+static inline struct box *
+box_move_xy(struct box *b, enum box_walk_dir dir, int *x, int *y)
+{
+ struct box *rb = NULL;
+
+ switch (dir) {
+ case BOX_WALK_CHILDREN:
+ b = b->children;
+ if (b == NULL)
+ break;
+ *x += b->x;
+ *y += b->y;
+ if (!box_is_float(b)) {
+ rb = b;
+ break;
+ }
+ fallthrough;
+
+ case BOX_WALK_NEXT_SIBLING:
+ do {
+ *x -= b->x;
+ *y -= b->y;
+ b = b->next;
+ if (b == NULL)
+ break;
+ *x += b->x;
+ *y += b->y;
+ } while (box_is_float(b));
+ rb = b;
+ break;
+
+ case BOX_WALK_PARENT:
+ *x -= b->x;
+ *y -= b->y;
+ rb = b->parent;
+ break;
+
+ case BOX_WALK_FLOAT_CHILDREN:
+ b = b->float_children;
+ if (b == NULL)
+ break;
+ *x += b->x;
+ *y += b->y;
+ rb = b;
+ break;
+
+ case BOX_WALK_NEXT_FLOAT_SIBLING:
+ *x -= b->x;
+ *y -= b->y;
+ b = b->next_float;
+ if (b == NULL)
+ break;
+ *x += b->x;
+ *y += b->y;
+ rb = b;
+ break;
+
+ case BOX_WALK_FLOAT_CONTAINER:
+ *x -= b->x;
+ *y -= b->y;
+ rb = b->float_container;
+ break;
+
+ default:
+ assert(0 && "Bad box walk type.");
+ }
+
+ return rb;
+}
+
+
+/**
+ * Itterator for walking to next box in interaction order
+ *
+ * \param b box to find next box from
+ * \param x box's global x-coord, updated to position of next box
+ * \param y box's global y-coord, updated to position of next box
+ * \param skip_children whether to skip box's children
+ *
+ * This walks to a boxes float children before its children. When walking
+ * children, floating boxes are skipped.
+ */
+static inline struct box *
+box_next_xy(struct box *b, int *x, int *y, bool skip_children)
+{
+ struct box *n;
+ int tx, ty;
+
+ assert(b != NULL);
+
+ if (skip_children) {
+ /* Caller is not interested in any kind of children */
+ goto skip_children;
+ }
+
+ tx = *x; ty = *y;
+ n = box_move_xy(b, BOX_WALK_FLOAT_CHILDREN, &tx, &ty);
+ if (n) {
+ /* Next node is float child */
+ *x = tx;
+ *y = ty;
+ return n;
+ }
+ done_float_children:
+
+ tx = *x; ty = *y;
+ n = box_move_xy(b, BOX_WALK_CHILDREN, &tx, &ty);
+ if (n) {
+ /* Next node is child */
+ *x = tx;
+ *y = ty;
+ return n;
+ }
+
+ skip_children:
+ tx = *x; ty = *y;
+ n = box_move_xy(b, BOX_WALK_NEXT_FLOAT_SIBLING, &tx, &ty);
+ if (n) {
+ /* Go to next float sibling */
+ *x = tx;
+ *y = ty;
+ return n;
+ }
+
+ if (box_is_float(b)) {
+ /* Done floats, but the float container may have children,
+ * or siblings, or ansestors with siblings. Change to
+ * float container and move past handling its float children.
+ */
+ b = box_move_xy(b, BOX_WALK_FLOAT_CONTAINER, x, y);
+ goto done_float_children;
+ }
+
+ /* Go to next sibling, or nearest ancestor with next sibling. */
+ while (b) {
+ while (!b->next && b->parent) {
+ b = box_move_xy(b, BOX_WALK_PARENT, x, y);
+ if (box_is_float(b)) {
+ /* Go on to next float, if there is one */
+ goto skip_children;
+ }
+ }
+ if (!b->next) {
+ /* No more boxes */
+ return NULL;
+ }
+
+ tx = *x; ty = *y;
+ n = box_move_xy(b, BOX_WALK_NEXT_SIBLING, &tx, &ty);
+ if (n) {
+ /* Go to non-float (ancestor) sibling */
+ *x = tx;
+ *y = ty;
+ return n;
+
+ } else if (b->parent) {
+ b = box_move_xy(b, BOX_WALK_PARENT, x, y);
+ if (box_is_float(b)) {
+ /* Go on to next float, if there is one */
+ goto skip_children;
+ }
+
+ } else {
+ /* No more boxes */
+ return NULL;
+ }
+ }
+
+ assert(b != NULL);
+ return NULL;
+}
+
+
+/**
+ * Check whether box is nearer mouse coordinates than current nearest box
+ *
+ * \param box box to test
+ * \param bx position of box, in global document coordinates
+ * \param by position of box, in global document coordinates
+ * \param x mouse point, in global document coordinates
+ * \param y mouse point, in global document coordinates
+ * \param dir direction in which to search (-1 = above-left,
+ * +1 = below-right)
+ * \param nearest nearest text box found, or NULL if none
+ * updated if box is nearer than existing nearest
+ * \param tx position of text_box, in global document coordinates
+ * updated if box is nearer than existing nearest
+ * \param ty position of text_box, in global document coordinates
+ * updated if box is nearer than existing nearest
+ * \param nr_xd distance to nearest text box found
+ * updated if box is nearer than existing nearest
+ * \param nr_yd distance to nearest text box found
+ * updated if box is nearer than existing nearest
+ * \return true if mouse point is inside box
+ */
+static bool
+box_nearer_text_box(struct box *box,
+ int bx, int by,
+ int x, int y,
+ int dir,
+ struct box **nearest,
+ int *tx, int *ty,
+ int *nr_xd, int *nr_yd)
+{
+ int w = box->padding[LEFT] + box->width + box->padding[RIGHT];
+ int h = box->padding[TOP] + box->height + box->padding[BOTTOM];
+ int y1 = by + h;
+ int x1 = bx + w;
+ int yd = INT_MAX;
+ int xd = INT_MAX;
+
+ if (x >= bx && x1 > x && y >= by && y1 > y) {
+ *nearest = box;
+ *tx = bx;
+ *ty = by;
+ return true;
+ }
+
+ if (box->parent->list_marker != box) {
+ if (dir < 0) {
+ /* consider only those children (partly) above-left */
+ if (by <= y && bx < x) {
+ yd = y <= y1 ? 0 : y - y1;
+ xd = x <= x1 ? 0 : x - x1;
+ }
+ } else {
+ /* consider only those children (partly) below-right */
+ if (y1 > y && x1 > x) {
+ yd = y > by ? 0 : by - y;
+ xd = x > bx ? 0 : bx - x;
+ }
+ }
+
+ /* give y displacement precedence over x */
+ if (yd < *nr_yd || (yd == *nr_yd && xd <= *nr_xd)) {
+ *nr_yd = yd;
+ *nr_xd = xd;
+ *nearest = box;
+ *tx = bx;
+ *ty = by;
+ }
+ }
+ return false;
+}
+
+
+/**
+ * Pick the text box child of 'box' that is closest to and above-left
+ * (dir -ve) or below-right (dir +ve) of the point 'x,y'
+ *
+ * \param box parent box
+ * \param bx position of box, in global document coordinates
+ * \param by position of box, in global document coordinates
+ * \param fx position of float parent, in global document coordinates
+ * \param fy position of float parent, in global document coordinates
+ * \param x mouse point, in global document coordinates
+ * \param y mouse point, in global document coordinates
+ * \param dir direction in which to search (-1 = above-left,
+ * +1 = below-right)
+ * \param nearest nearest text box found, or NULL if none
+ * updated if a descendant of box is nearer than old nearest
+ * \param tx position of nearest, in global document coordinates
+ * updated if a descendant of box is nearer than old nearest
+ * \param ty position of nearest, in global document coordinates
+ * updated if a descendant of box is nearer than old nearest
+ * \param nr_xd distance to nearest text box found
+ * updated if a descendant of box is nearer than old nearest
+ * \param nr_yd distance to nearest text box found
+ * updated if a descendant of box is nearer than old nearest
+ * \return true if mouse point is inside text_box
+ */
+static bool
+box_nearest_text_box(struct box *box,
+ int bx, int by,
+ int fx, int fy,
+ int x, int y,
+ int dir,
+ struct box **nearest,
+ int *tx, int *ty,
+ int *nr_xd, int *nr_yd)
+{
+ struct box *child = box->children;
+ int c_bx, c_by;
+ int c_fx, c_fy;
+ bool in_box = false;
+
+ if (*nearest == NULL) {
+ *nr_xd = INT_MAX / 2; /* displacement of 'nearest so far' */
+ *nr_yd = INT_MAX / 2;
+ }
+ if (box->type == BOX_INLINE_CONTAINER) {
+ int bw = box->padding[LEFT] + box->width + box->padding[RIGHT];
+ int bh = box->padding[TOP] + box->height + box->padding[BOTTOM];
+ int b_y1 = by + bh;
+ int b_x1 = bx + bw;
+ if (x >= bx && b_x1 > x && y >= by && b_y1 > y) {
+ in_box = true;
+ }
+ }
+
+ while (child) {
+ if (child->type == BOX_FLOAT_LEFT ||
+ child->type == BOX_FLOAT_RIGHT) {
+ c_bx = fx + child->x -
+ scrollbar_get_offset(child->scroll_x);
+ c_by = fy + child->y -
+ scrollbar_get_offset(child->scroll_y);
+ } else {
+ c_bx = bx + child->x -
+ scrollbar_get_offset(child->scroll_x);
+ c_by = by + child->y -
+ scrollbar_get_offset(child->scroll_y);
+ }
+ if (child->float_children) {
+ c_fx = c_bx;
+ c_fy = c_by;
+ } else {
+ c_fx = fx;
+ c_fy = fy;
+ }
+ if (in_box && child->text && !child->object) {
+ if (box_nearer_text_box(child,
+ c_bx, c_by, x, y, dir, nearest,
+ tx, ty, nr_xd, nr_yd))
+ return true;
+ } else {
+ if (child->list_marker) {
+ if (box_nearer_text_box(
+ child->list_marker,
+ c_bx + child->list_marker->x,
+ c_by + child->list_marker->y,
+ x, y, dir, nearest,
+ tx, ty, nr_xd, nr_yd))
+ return true;
+ }
+ if (box_nearest_text_box(child, c_bx, c_by,
+ c_fx, c_fy,
+ x, y, dir, nearest, tx, ty,
+ nr_xd, nr_yd))
+ return true;
+ }
+ child = child->next;
+ }
+
+ return false;
+}
+
+
+/* Exported function documented in html/box.h */
+void box_coords(struct box *box, int *x, int *y)
+{
+ *x = box->x;
+ *y = box->y;
+ while (box->parent) {
+ if (box_is_float(box)) {
+ assert(box->float_container);
+ box = box->float_container;
+ } else {
+ box = box->parent;
+ }
+ *x += box->x - scrollbar_get_offset(box->scroll_x);
+ *y += box->y - scrollbar_get_offset(box->scroll_y);
+ }
+}
+
+
+/* Exported function documented in html/box.h */
+void box_bounds(struct box *box, struct rect *r)
+{
+ int width, height;
+
+ box_coords(box, &r->x0, &r->y0);
+
+ width = box->padding[LEFT] + box->width + box->padding[RIGHT];
+ height = box->padding[TOP] + box->height + box->padding[BOTTOM];
+
+ r->x1 = r->x0 + width;
+ r->y1 = r->y0 + height;
+}
+
+
+/* Exported function documented in html/box.h */
+struct box *
+box_at_point(const css_unit_ctx *unit_len_ctx,
+ struct box *box,
+ const int x, const int y,
+ int *box_x, int *box_y)
+{
+ bool skip_children;
+ bool physically;
+
+ assert(box);
+
+ skip_children = false;
+ while ((box = box_next_xy(box, box_x, box_y, skip_children))) {
+ if (box_contains_point(unit_len_ctx, box, x - *box_x, y - *box_y,
+ &physically)) {
+ *box_x -= scrollbar_get_offset(box->scroll_x);
+ *box_y -= scrollbar_get_offset(box->scroll_y);
+
+ if (physically)
+ return box;
+
+ skip_children = false;
+ } else {
+ skip_children = true;
+ }
+ }
+
+ return NULL;
+}
+
+
+/* Exported function documented in html/box.h */
+struct box *box_find_by_id(struct box *box, lwc_string *id)
+{
+ struct box *a, *b;
+ bool m;
+
+ if (box->id != NULL &&
+ lwc_string_isequal(id, box->id, &m) == lwc_error_ok &&
+ m == true) {
+ return box;
+ }
+
+ for (a = box->children; a; a = a->next) {
+ if ((b = box_find_by_id(a, id)) != NULL) {
+ return b;
+ }
+ }
+
+ return NULL;
+}
+
+
+/* Exported function documented in html/box.h */
+bool box_visible(struct box *box)
+{
+ /* visibility: hidden */
+ if (box->style &&
+ css_computed_visibility(box->style) == CSS_VISIBILITY_HIDDEN) {
+ return false;
+ }
+
+ return true;
+}
+
+
+/* Exported function documented in html/box.h */
+void box_dump(FILE *stream, struct box *box, unsigned int depth, bool style)
+{
+ unsigned int i;
+ struct box *c, *prev;
+
+ for (i = 0; i != depth; i++) {
+ fprintf(stream, " ");
+ }
+
+ fprintf(stream, "%p ", box);
+ fprintf(stream, "x%i y%i w%i h%i ",
+ box->x, box->y, box->width, box->height);
+ if (box->max_width != UNKNOWN_MAX_WIDTH) {
+ fprintf(stream, "min%i max%i ", box->min_width, box->max_width);
+ }
+ fprintf(stream, "desc(%i %i %i %i) ",
+ box->descendant_x0, box->descendant_y0,
+ box->descendant_x1, box->descendant_y1);
+
+ fprintf(stream, "m(%i %i %i %i) ",
+ box->margin[TOP], box->margin[LEFT],
+ box->margin[BOTTOM], box->margin[RIGHT]);
+
+ switch (box->type) {
+ case BOX_BLOCK:
+ fprintf(stream, "BLOCK ");
+ break;
+
+ case BOX_INLINE_CONTAINER:
+ fprintf(stream, "INLINE_CONTAINER ");
+ break;
+
+ case BOX_INLINE:
+ fprintf(stream, "INLINE ");
+ break;
+
+ case BOX_INLINE_END:
+ fprintf(stream, "INLINE_END ");
+ break;
+
+ case BOX_INLINE_BLOCK:
+ fprintf(stream, "INLINE_BLOCK ");
+ break;
+
+ case BOX_TABLE:
+ fprintf(stream, "TABLE [columns %i] ", box->columns);
+ break;
+
+ case BOX_TABLE_ROW:
+ fprintf(stream, "TABLE_ROW ");
+ break;
+
+ case BOX_TABLE_CELL:
+ fprintf(stream, "TABLE_CELL [columns %i, start %i, rows %i] ",
+ box->columns,
+ box->start_column,
+ box->rows);
+ break;
+
+ case BOX_TABLE_ROW_GROUP:
+ fprintf(stream, "TABLE_ROW_GROUP ");
+ break;
+
+ case BOX_FLOAT_LEFT:
+ fprintf(stream, "FLOAT_LEFT ");
+ break;
+
+ case BOX_FLOAT_RIGHT:
+ fprintf(stream, "FLOAT_RIGHT ");
+ break;
+
+ case BOX_BR:
+ fprintf(stream, "BR ");
+ break;
+
+ case BOX_TEXT:
+ fprintf(stream, "TEXT ");
+ break;
+
+ case BOX_FLEX:
+ fprintf(stream, "FLEX ");
+ break;
+
+ case BOX_INLINE_FLEX:
+ fprintf(stream, "INLINE_FLEX ");
+ break;
+
+ default:
+ fprintf(stream, "Unknown box type ");
+ }
+
+ if (box->text)
+ fprintf(stream, "%li '%.*s' ", (unsigned long) box->byte_offset,
+ (int) box->length, box->text);
+ if (box->space)
+ fprintf(stream, "space ");
+ if (box->object) {
+ fprintf(stream, "(object '%s') ",
+ nsurl_access(hlcache_handle_get_url(box->object)));
+ }
+ if (box->iframe) {
+ fprintf(stream, "(iframe) ");
+ }
+ if (box->gadget)
+ fprintf(stream, "(gadget) ");
+ if (style && box->style)
+ nscss_dump_computed_style(stream, box->style);
+ if (box->href)
+ fprintf(stream, " -> '%s'", nsurl_access(box->href));
+ if (box->target)
+ fprintf(stream, " |%s|", box->target);
+ if (box->title)
+ fprintf(stream, " [%s]", box->title);
+ if (box->id)
+ fprintf(stream, " ID:%s", lwc_string_data(box->id));
+ if (box->type == BOX_INLINE || box->type == BOX_INLINE_END)
+ fprintf(stream, " inline_end %p", box->inline_end);
+ if (box->float_children)
+ fprintf(stream, " float_children %p", box->float_children);
+ if (box->next_float)
+ fprintf(stream, " next_float %p", box->next_float);
+ if (box->float_container)
+ fprintf(stream, " float_container %p", box->float_container);
+ if (box->col) {
+ fprintf(stream, " (columns");
+ for (i = 0; i != box->columns; i++) {
+ fprintf(stream, " (%s %s %i %i %i)",
+ ((const char *[]) {
+ "UNKNOWN",
+ "FIXED",
+ "AUTO",
+ "PERCENT",
+ "RELATIVE"
+ })
+ [box->col[i].type],
+ ((const char *[]) {
+ "normal",
+ "positioned"})
+ [box->col[i].positioned],
+ box->col[i].width,
+ box->col[i].min, box->col[i].max);
+ }
+ fprintf(stream, ")");
+ }
+ if (box->node != NULL) {
+ dom_string *name;
+ if (dom_node_get_node_name(box->node, &name) == DOM_NO_ERR) {
+ fprintf(stream, " <%s>", dom_string_data(name));
+ dom_string_unref(name);
+ }
+ }
+ fprintf(stream, "\n");
+
+ if (box->list_marker) {
+ for (i = 0; i != depth; i++)
+ fprintf(stream, " ");
+ fprintf(stream, "list_marker:\n");
+ box_dump(stream, box->list_marker, depth + 1, style);
+ }
+
+ for (c = box->children; c && c->next; c = c->next)
+ ;
+ if (box->last != c)
+ fprintf(stream, "warning: box->last %p (should be %p) "
+ "(box %p)\n", box->last, c, box);
+ for (prev = 0, c = box->children; c; prev = c, c = c->next) {
+ if (c->parent != box)
+ fprintf(stream, "warning: box->parent %p (should be "
+ "%p) (box on next line)\n",
+ c->parent, box);
+ if (c->prev != prev)
+ fprintf(stream, "warning: box->prev %p (should be "
+ "%p) (box on next line)\n",
+ c->prev, prev);
+ box_dump(stream, c, depth + 1, style);
+ }
+}
+
+
+/* exported interface documented in html/box.h */
+bool box_vscrollbar_present(const struct box * const box)
+{
+ return box->padding[TOP] +
+ box->height +
+ box->padding[BOTTOM] +
+ box->border[BOTTOM].width < box->descendant_y1;
+}
+
+
+/* exported interface documented in html/box.h */
+bool box_hscrollbar_present(const struct box * const box)
+{
+ return box->padding[LEFT] +
+ box->width +
+ box->padding[RIGHT] +
+ box->border[RIGHT].width < box->descendant_x1;
+}
+
+
+/* Exported function documented in html/box.h */
+struct box *
+box_pick_text_box(struct html_content *html,
+ int x, int y,
+ int dir,
+ int *dx, int *dy)
+{
+ struct box *text_box = NULL;
+ struct box *box;
+ int nr_xd, nr_yd;
+ int bx, by;
+ int fx, fy;
+ int tx, ty;
+
+ if (html == NULL)
+ return NULL;
+
+ box = html->layout;
+ bx = box->margin[LEFT];
+ by = box->margin[TOP];
+ fx = bx;
+ fy = by;
+
+ if (!box_nearest_text_box(box, bx, by, fx, fy, x, y,
+ dir, &text_box, &tx, &ty, &nr_xd, &nr_yd)) {
+ if (text_box && text_box->text && !text_box->object) {
+ int w = (text_box->padding[LEFT] +
+ text_box->width +
+ text_box->padding[RIGHT]);
+ int h = (text_box->padding[TOP] +
+ text_box->height +
+ text_box->padding[BOTTOM]);
+ int x1, y1;
+
+ y1 = ty + h;
+ x1 = tx + w;
+
+ /* ensure point lies within the text box */
+ if (x < tx) x = tx;
+ if (y < ty) y = ty;
+ if (y > y1) y = y1;
+ if (x > x1) x = x1;
+ }
+ }
+
+ /* return coordinates relative to box */
+ *dx = x - tx;
+ *dy = y - ty;
+
+ return text_box;
+}
diff --git a/content/handlers/html/box_inspect.h b/content/handlers/html/box_inspect.h
new file mode 100644
index 000000000..a218326d8
--- /dev/null
+++ b/content/handlers/html/box_inspect.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * HTML Box tree inspection interface.
+ */
+
+#ifndef NETSURF_HTML_BOX_INSPECT_H
+#define NETSURF_HTML_BOX_INSPECT_H
+
+/**
+ * Find the absolute coordinates of a box.
+ *
+ * \param box the box to calculate coordinates of
+ * \param x updated to x coordinate
+ * \param y updated to y coordinate
+ */
+void box_coords(struct box *box, int *x, int *y);
+
+
+/**
+ * Find the bounds of a box.
+ *
+ * \param box the box to calculate bounds of
+ * \param r receives bounds
+ */
+void box_bounds(struct box *box, struct rect *r);
+
+
+/**
+ * Find the boxes at a point.
+ *
+ * \param unit_len_ctx CSS length conversion context for document.
+ * \param box box to search children of
+ * \param x point to find, in global document coordinates
+ * \param y point to find, in global document coordinates
+ * \param box_x position of box, in global document coordinates, updated
+ * to position of returned box, if any
+ * \param box_y position of box, in global document coordinates, updated
+ * to position of returned box, if any
+ * \return box at given point, or 0 if none found
+ *
+ * To find all the boxes in the hierarchy at a certain point, use code like
+ * this:
+ * \code
+ * struct box *box = top_of_document_to_search;
+ * int box_x = 0, box_y = 0;
+ *
+ * while ((box = box_at_point(unit_len_ctx, box, x, y, &box_x, &box_y))) {
+ * // process box
+ * }
+ * \endcode
+ */
+struct box *box_at_point(const css_unit_ctx *unit_len_ctx, struct box *box, const int x, const int y, int *box_x, int *box_y);
+
+
+/**
+ * Find a box based upon its id attribute.
+ *
+ * \param box box tree to search
+ * \param id id to look for
+ * \return the box or 0 if not found
+ */
+struct box *box_find_by_id(struct box *box, lwc_string *id);
+
+
+/**
+ * Determine if a box is visible when the tree is rendered.
+ *
+ * \param box box to check
+ * \return true iff the box is rendered
+ */
+bool box_visible(struct box *box);
+
+
+/**
+ * Print a box tree to a file.
+ */
+void box_dump(FILE *stream, struct box *box, unsigned int depth, bool style);
+
+
+/**
+ * Determine if a box has a vertical scrollbar.
+ *
+ * \param box scrolling box
+ * \return the box has a vertical scrollbar
+ */
+bool box_vscrollbar_present(const struct box *box);
+
+
+/**
+ * Determine if a box has a horizontal scrollbar.
+ *
+ * \param box scrolling box
+ * \return the box has a horizontal scrollbar
+ */
+bool box_hscrollbar_present(const struct box *box);
+
+
+/**
+ * Peform pick text on browser window contents to locate the box under
+ * the mouse pointer, or nearest in the given direction if the pointer is
+ * not over a text box.
+ *
+ * \param html an HTML content
+ * \param x coordinate of mouse
+ * \param y coordinate of mouse
+ * \param dir direction to search (-1 = above-left, +1 = below-right)
+ * \param dx receives x ordinate of mouse relative to text box
+ * \param dy receives y ordinate of mouse relative to text box
+ */
+struct box *box_pick_text_box(struct html_content *html, int x, int y, int dir, int *dx, int *dy);
+
+
+/**
+ * Check if layout box is a first child.
+ *
+ * \param[in] b Box to check.
+ * \return true iff box is first child.
+ */
+static inline bool box_is_first_child(struct box *b)
+{
+ return (b->parent == NULL || b == b->parent->children);
+}
+
+static inline unsigned box_count_children(const struct box *b)
+{
+ const struct box *c = b->children;
+ unsigned count = 0;
+
+ while (c != NULL) {
+ count++;
+ c = c->next;
+ }
+
+ return count;
+}
+
+#endif
diff --git a/content/handlers/html/box_manipulate.c b/content/handlers/html/box_manipulate.c
new file mode 100644
index 000000000..8073a7fd1
--- /dev/null
+++ b/content/handlers/html/box_manipulate.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright 2005-2007 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
+ * Copyright 2005 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2008 Michael Drake <tlsa@netsurf-browser.org>
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * implementation of box tree manipulation.
+ */
+
+
+#include "utils/errors.h"
+#include "utils/talloc.h"
+#include "utils/nsurl.h"
+#include "netsurf/types.h"
+#include "netsurf/mouse.h"
+#include "desktop/scrollbar.h"
+
+#include "html/private.h"
+#include "html/form_internal.h"
+#include "html/interaction.h"
+#include "html/box.h"
+#include "html/box_manipulate.h"
+
+
+/**
+ * Destructor for box nodes which own styles
+ *
+ * \param b The box being destroyed.
+ * \return 0 to allow talloc to continue destroying the tree.
+ */
+static int box_talloc_destructor(struct box *b)
+{
+ struct html_scrollbar_data *data;
+
+ if ((b->flags & STYLE_OWNED) && b->style != NULL) {
+ css_computed_style_destroy(b->style);
+ b->style = NULL;
+ }
+
+ if (b->styles != NULL) {
+ css_select_results_destroy(b->styles);
+ b->styles = NULL;
+ }
+
+ if (b->href != NULL)
+ nsurl_unref(b->href);
+
+ if (b->id != NULL) {
+ lwc_string_unref(b->id);
+ }
+
+ if (b->node != NULL) {
+ dom_node_unref(b->node);
+ }
+
+ if (b->scroll_x != NULL) {
+ data = scrollbar_get_data(b->scroll_x);
+ scrollbar_destroy(b->scroll_x);
+ free(data);
+ }
+
+ if (b->scroll_y != NULL) {
+ data = scrollbar_get_data(b->scroll_y);
+ scrollbar_destroy(b->scroll_y);
+ free(data);
+ }
+
+ return 0;
+}
+
+
+/* Exported function documented in html/box.h */
+struct box *
+box_create(css_select_results *styles,
+ css_computed_style *style,
+ bool style_owned,
+ nsurl *href,
+ const char *target,
+ const char *title,
+ lwc_string *id,
+ void *context)
+{
+ unsigned int i;
+ struct box *box;
+
+ box = talloc(context, struct box);
+ if (!box) {
+ return 0;
+ }
+
+ talloc_set_destructor(box, box_talloc_destructor);
+
+ box->type = BOX_INLINE;
+ box->flags = 0;
+ box->flags = style_owned ? (box->flags | STYLE_OWNED) : box->flags;
+ box->styles = styles;
+ box->style = style;
+ box->x = box->y = 0;
+ box->width = UNKNOWN_WIDTH;
+ box->height = 0;
+ box->descendant_x0 = box->descendant_y0 = 0;
+ box->descendant_x1 = box->descendant_y1 = 0;
+ for (i = 0; i != 4; i++)
+ box->margin[i] = box->padding[i] = box->border[i].width = 0;
+ box->scroll_x = box->scroll_y = NULL;
+ box->min_width = 0;
+ box->max_width = UNKNOWN_MAX_WIDTH;
+ box->byte_offset = 0;
+ box->text = NULL;
+ box->length = 0;
+ box->space = 0;
+ box->href = (href == NULL) ? NULL : nsurl_ref(href);
+ box->target = target;
+ box->title = title;
+ box->columns = 1;
+ box->rows = 1;
+ box->start_column = 0;
+ box->next = NULL;
+ box->prev = NULL;
+ box->children = NULL;
+ box->last = NULL;
+ box->parent = NULL;
+ box->inline_end = NULL;
+ box->float_children = NULL;
+ box->float_container = NULL;
+ box->next_float = NULL;
+ box->cached_place_below_level = 0;
+ box->list_value = 1;
+ box->list_marker = NULL;
+ box->col = NULL;
+ box->gadget = NULL;
+ box->usemap = NULL;
+ box->id = id;
+ box->background = NULL;
+ box->object = NULL;
+ box->object_params = NULL;
+ box->iframe = NULL;
+ box->node = NULL;
+
+ return box;
+}
+
+
+/* Exported function documented in html/box.h */
+void box_add_child(struct box *parent, struct box *child)
+{
+ assert(parent);
+ assert(child);
+
+ if (parent->children != 0) { /* has children already */
+ parent->last->next = child;
+ child->prev = parent->last;
+ } else { /* this is the first child */
+ parent->children = child;
+ child->prev = 0;
+ }
+
+ parent->last = child;
+ child->parent = parent;
+}
+
+
+/* Exported function documented in html/box.h */
+void box_insert_sibling(struct box *box, struct box *new_box)
+{
+ new_box->parent = box->parent;
+ new_box->prev = box;
+ new_box->next = box->next;
+ box->next = new_box;
+ if (new_box->next)
+ new_box->next->prev = new_box;
+ else if (new_box->parent)
+ new_box->parent->last = new_box;
+}
+
+
+/* Exported function documented in html/box.h */
+void box_unlink_and_free(struct box *box)
+{
+ struct box *parent = box->parent;
+ struct box *next = box->next;
+ struct box *prev = box->prev;
+
+ if (parent) {
+ if (parent->children == box)
+ parent->children = next;
+ if (parent->last == box)
+ parent->last = next ? next : prev;
+ }
+
+ if (prev)
+ prev->next = next;
+ if (next)
+ next->prev = prev;
+
+ box_free(box);
+}
+
+
+/* Exported function documented in html/box.h */
+void box_free(struct box *box)
+{
+ struct box *child, *next;
+
+ /* free children first */
+ for (child = box->children; child; child = next) {
+ next = child->next;
+ box_free(child);
+ }
+
+ /* last this box */
+ box_free_box(box);
+}
+
+
+/* Exported function documented in html/box.h */
+void box_free_box(struct box *box)
+{
+ if (!(box->flags & CLONE)) {
+ if (box->gadget)
+ form_free_control(box->gadget);
+ if (box->scroll_x != NULL)
+ scrollbar_destroy(box->scroll_x);
+ if (box->scroll_y != NULL)
+ scrollbar_destroy(box->scroll_y);
+ if (box->styles != NULL)
+ css_select_results_destroy(box->styles);
+ }
+
+ talloc_free(box);
+}
+
+
+/* exported interface documented in html/box.h */
+nserror
+box_handle_scrollbars(struct content *c,
+ struct box *box,
+ bool bottom,
+ bool right)
+{
+ struct html_scrollbar_data *data;
+ int visible_width, visible_height;
+ int full_width, full_height;
+ nserror res;
+
+ if (!bottom && box->scroll_x != NULL) {
+ data = scrollbar_get_data(box->scroll_x);
+ scrollbar_destroy(box->scroll_x);
+ free(data);
+ box->scroll_x = NULL;
+ }
+
+ if (!right && box->scroll_y != NULL) {
+ data = scrollbar_get_data(box->scroll_y);
+ scrollbar_destroy(box->scroll_y);
+ free(data);
+ box->scroll_y = NULL;
+ }
+
+ if (!bottom && !right) {
+ return NSERROR_OK;
+ }
+
+ visible_width = box->width + box->padding[RIGHT] + box->padding[LEFT];
+ visible_height = box->height + box->padding[TOP] + box->padding[BOTTOM];
+
+ full_width = ((box->descendant_x1 - box->border[RIGHT].width) >
+ visible_width) ?
+ box->descendant_x1 + box->padding[RIGHT] :
+ visible_width;
+ full_height = ((box->descendant_y1 - box->border[BOTTOM].width) >
+ visible_height) ?
+ box->descendant_y1 + box->padding[BOTTOM] :
+ visible_height;
+
+ if (right) {
+ if (box->scroll_y == NULL) {
+ data = malloc(sizeof(struct html_scrollbar_data));
+ if (data == NULL) {
+ return NSERROR_NOMEM;
+ }
+ data->c = c;
+ data->box = box;
+ res = scrollbar_create(false,
+ visible_height,
+ full_height,
+ visible_height,
+ data,
+ html_overflow_scroll_callback,
+ &(box->scroll_y));
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ } else {
+ scrollbar_set_extents(box->scroll_y,
+ visible_height,
+ visible_height,
+ full_height);
+ }
+ }
+ if (bottom) {
+ if (box->scroll_x == NULL) {
+ data = malloc(sizeof(struct html_scrollbar_data));
+ if (data == NULL) {
+ return NSERROR_OK;
+ }
+ data->c = c;
+ data->box = box;
+ res = scrollbar_create(true,
+ visible_width - (right ? SCROLLBAR_WIDTH : 0),
+ full_width,
+ visible_width,
+ data,
+ html_overflow_scroll_callback,
+ &box->scroll_x);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ } else {
+ scrollbar_set_extents(box->scroll_x,
+ visible_width -
+ (right ? SCROLLBAR_WIDTH : 0),
+ visible_width, full_width);
+ }
+ }
+
+ if (right && bottom) {
+ scrollbar_make_pair(box->scroll_x, box->scroll_y);
+ }
+
+ return NSERROR_OK;
+}
+
+
diff --git a/content/handlers/html/box_manipulate.h b/content/handlers/html/box_manipulate.h
new file mode 100644
index 000000000..43a66a7d9
--- /dev/null
+++ b/content/handlers/html/box_manipulate.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Box tree manipulation interface.
+ */
+
+#ifndef NETSURF_HTML_BOX_MANIPULATE_H
+#define NETSURF_HTML_BOX_MANIPULATE_H
+
+
+/**
+ * Create a box tree node.
+ *
+ * \param styles selection results for the box, or NULL
+ * \param style computed style for the box (not copied), or 0
+ * \param style_owned whether style is owned by this box
+ * \param href href for the box (copied), or 0
+ * \param target target for the box (not copied), or 0
+ * \param title title for the box (not copied), or 0
+ * \param id id for the box (not copied), or 0
+ * \param context context for allocations
+ * \return allocated and initialised box, or 0 on memory exhaustion
+ *
+ * styles is always owned by the box, if it is set.
+ * style is only owned by the box in the case of implied boxes.
+ */
+struct box * box_create(css_select_results *styles, css_computed_style *style, bool style_owned, struct nsurl *href, const char *target, const char *title, lwc_string *id, void *context);
+
+
+/**
+ * Add a child to a box tree node.
+ *
+ * \param parent box giving birth
+ * \param child box to link as last child of parent
+ */
+void box_add_child(struct box *parent, struct box *child);
+
+
+/**
+ * Insert a new box as a sibling to a box in a tree.
+ *
+ * \param box box already in tree
+ * \param new_box box to link into tree as next sibling
+ */
+void box_insert_sibling(struct box *box, struct box *new_box);
+
+
+/**
+ * Unlink a box from the box tree and then free it recursively.
+ *
+ * \param box box to unlink and free recursively.
+ */
+void box_unlink_and_free(struct box *box);
+
+
+/**
+ * Free a box tree recursively.
+ *
+ * \param box box to free recursively
+ *
+ * The box and all its children is freed.
+ */
+void box_free(struct box *box);
+
+
+/**
+ * Free the data in a single box structure.
+ *
+ * \param box box to free
+ */
+void box_free_box(struct box *box);
+
+
+/**
+ * Applies the given scroll setup to a box. This includes scroll
+ * creation/deletion as well as scroll dimension updates.
+ *
+ * \param c content in which the box is located
+ * \param box the box to handle the scrolls for
+ * \param bottom whether the horizontal scrollbar should be present
+ * \param right whether the vertical scrollbar should be present
+ * \return true on success false otherwise
+ */
+nserror box_handle_scrollbars(struct content *c, struct box *box,
+ bool bottom, bool right);
+
+
+#endif
diff --git a/render/box_normalise.c b/content/handlers/html/box_normalise.c
index 8da245754..8f25b031f 100644
--- a/render/box_normalise.c
+++ b/content/handlers/html/box_normalise.c
@@ -19,8 +19,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Box tree normalisation (implementation).
+/**
+ * \file
+ * Box tree normalisation implementation.
*/
#include <assert.h>
@@ -31,9 +32,11 @@
#include "utils/errors.h"
#include "css/select.h"
-#include "render/box.h"
-#include "render/html_internal.h"
-#include "render/table.h"
+#include "html/private.h"
+#include "html/table.h"
+#include "html/box.h"
+#include "html/box_manipulate.h"
+#include "html/box_normalise.h"
/* Define to enable box normalise debug */
#undef BOX_NORMALISE_DEBUG
@@ -65,282 +68,321 @@ struct columns {
};
-static bool box_normalise_table(
- struct box *table,
- const struct box *root,
- html_content *c);
-static bool box_normalise_table_spans(
- struct box *table,
- const struct box *root,
- struct span_info *spans,
- html_content *c);
-static bool box_normalise_table_row_group(
- struct box *row_group,
- const struct box *root,
- struct columns *col_info,
- html_content *c);
-static bool box_normalise_table_row(
- struct box *row,
- const struct box *root,
- struct columns *col_info,
- html_content *c);
-static bool calculate_table_row(struct columns *col_info,
- unsigned int col_span, unsigned int row_span,
- unsigned int *start_column, struct box *cell);
-static bool box_normalise_inline_container(
- struct box *cont,
- const struct box *root,
- html_content *c);
-
/**
- * Ensure the box tree is correctly nested by adding and removing nodes.
- *
- * \param block box of type BLOCK, INLINE_BLOCK, or TABLE_CELL
- * \param root root box of document
- * \param c content of boxes
- * \return true on success, false on memory exhaustion
+ * Compute the column index at which the current cell begins.
+ * Additionally, update the column record to reflect row spanning.
*
- * The tree is modified to satisfy the following:
- * \code
- * parent permitted child nodes
- * BLOCK, INLINE_BLOCK BLOCK, INLINE_CONTAINER, TABLE
- * INLINE_CONTAINER INLINE, INLINE_BLOCK, FLOAT_LEFT, FLOAT_RIGHT, BR, TEXT
- * INLINE, TEXT none
- * TABLE at least 1 TABLE_ROW_GROUP
- * TABLE_ROW_GROUP at least 1 TABLE_ROW
- * TABLE_ROW at least 1 TABLE_CELL
- * TABLE_CELL BLOCK, INLINE_CONTAINER, TABLE (same as BLOCK)
- * FLOAT_(LEFT|RIGHT) exactly 1 BLOCK or TABLE
- * \endcode
+ * \param col_info Column record
+ * \param col_span Number of columns that current cell spans
+ * \param row_span Number of rows that current cell spans
+ * \param start_column Pointer to location to receive column index
+ * \param cell Box for current table cell
+ * \return true on success, false on memory exhaustion
*/
+static bool
+calculate_table_row(struct columns *col_info,
+ unsigned int col_span,
+ unsigned int row_span,
+ unsigned int *start_column,
+ struct box *cell)
+{
+ unsigned int cell_start_col = col_info->current_column;
+ unsigned int cell_end_col;
+ unsigned int i;
+ struct span_info *spans;
+ struct box *rg = cell->parent->parent; /* Cell's row group */
-bool box_normalise_block(
- struct box *block,
- const struct box *root,
- html_content *c)
+ /* Skip columns with cells spanning from above */
+ /* TODO: Need to ignore cells spanning from above that belong to
+ * different row group. We don't have that info here. */
+ while (col_info->spans[cell_start_col].row_span != 0 &&
+ col_info->spans[cell_start_col].rg == rg) {
+ cell_start_col++;
+ }
+
+ /* Update current column with calculated start */
+ col_info->current_column = cell_start_col;
+
+ /* If this cell has a colspan of 0, then assume 1.
+ * No other browser supports colspan=0, anyway. */
+ if (col_span == 0)
+ col_span = 1;
+
+ cell_end_col = cell_start_col + col_span;
+
+ if (col_info->num_columns < cell_end_col) {
+ /* It appears that this row has more columns than
+ * the maximum recorded for the table so far.
+ * Allocate more span records. */
+ spans = realloc(col_info->spans,
+ sizeof *spans * (cell_end_col + 1));
+ if (spans == NULL)
+ return false;
+
+ col_info->spans = spans;
+ col_info->num_columns = cell_end_col;
+
+ /* Mark new final column as sentinel */
+ col_info->spans[cell_end_col].row_span = 0;
+ col_info->spans[cell_end_col].auto_row = false;
+ }
+
+ /* This cell may span multiple columns. If it also wants to span
+ * multiple rows, temporarily assume it spans 1 row only. This will
+ * be fixed up in box_normalise_table_spans() */
+ for (i = cell_start_col; i < cell_end_col; i++) {
+ col_info->spans[i].row_span = (row_span == 0) ? 1 : row_span;
+ col_info->spans[i].auto_row = (row_span == 0);
+ col_info->spans[i].rg = rg;
+ }
+
+ /* Update current column with calculated end. */
+ col_info->current_column = cell_end_col;
+
+ *start_column = cell_start_col;
+
+ return true;
+}
+
+
+static bool
+box_normalise_table_row(struct box *row,
+ const struct box *root,
+ struct columns *col_info,
+ html_content * c)
{
struct box *child;
struct box *next_child;
- struct box *table;
+ struct box *cell = NULL;
css_computed_style *style;
+ unsigned int i;
nscss_select_ctx ctx;
- assert(block != NULL);
- assert(root != NULL);
+ assert(row != NULL);
+ assert(row->type == BOX_TABLE_ROW);
ctx.root_style = root->style;
#ifdef BOX_NORMALISE_DEBUG
- NSLOG(netsurf, INFO, "block %p, block->type %u", block, block->type);
-#endif
-
- assert(block->type == BOX_BLOCK || block->type == BOX_INLINE_BLOCK ||
- block->type == BOX_TABLE_CELL);
-
- for (child = block->children; child != NULL; child = next_child) {
-#ifdef BOX_NORMALISE_DEBUG
- NSLOG(netsurf, INFO, "child %p, child->type = %d", child,
- child->type);
+ NSLOG(netsurf, INFO, "row %p", row);
#endif
- next_child = child->next; /* child may be destroyed */
+ for (child = row->children; child != NULL; child = next_child) {
+ next_child = child->next;
switch (child->type) {
- case BOX_BLOCK:
+ case BOX_TABLE_CELL:
/* ok */
if (box_normalise_block(child, root, c) == false)
return false;
+ cell = child;
break;
+ case BOX_FLEX:
+ case BOX_BLOCK:
case BOX_INLINE_CONTAINER:
- if (box_normalise_inline_container(child, root, c) == false)
- return false;
- break;
case BOX_TABLE:
- if (box_normalise_table(child, root, c) == false)
- return false;
- break;
- case BOX_INLINE:
- case BOX_INLINE_END:
- case BOX_INLINE_BLOCK:
- case BOX_FLOAT_LEFT:
- case BOX_FLOAT_RIGHT:
- case BOX_BR:
- case BOX_TEXT:
- /* should have been wrapped in inline
- container by convert_xml_to_box() */
- assert(0);
- break;
case BOX_TABLE_ROW_GROUP:
case BOX_TABLE_ROW:
- case BOX_TABLE_CELL:
- /* insert implied table */
- assert(block->style != NULL);
+ /* insert implied table cell */
+ assert(row->style != NULL);
ctx.ctx = c->select_ctx;
ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
- style = nscss_get_blank_style(&ctx, block->style);
+ style = nscss_get_blank_style(&ctx, &c->unit_len_ctx,
+ row->style);
if (style == NULL)
return false;
- table = box_create(NULL, style, true, block->href,
- block->target, NULL, NULL, c->bctx);
- if (table == NULL) {
+ cell = box_create(NULL, style, true, row->href,
+ row->target, NULL, NULL, c->bctx);
+ if (cell == NULL) {
css_computed_style_destroy(style);
return false;
}
- table->type = BOX_TABLE;
+ cell->type = BOX_TABLE_CELL;
if (child->prev == NULL)
- block->children = table;
+ row->children = cell;
else
- child->prev->next = table;
+ child->prev->next = cell;
- table->prev = child->prev;
+ cell->prev = child->prev;
while (child != NULL && (
+ child->type == BOX_FLEX ||
+ child->type == BOX_BLOCK ||
+ child->type == BOX_INLINE_CONTAINER ||
+ child->type == BOX_TABLE ||
child->type == BOX_TABLE_ROW_GROUP ||
- child->type == BOX_TABLE_ROW ||
- child->type == BOX_TABLE_CELL)) {
- box_add_child(table, child);
+ child->type == BOX_TABLE_ROW)) {
+ box_add_child(cell, child);
next_child = child->next;
child->next = NULL;
child = next_child;
}
- table->last->next = NULL;
- table->next = next_child = child;
- if (table->next != NULL)
- table->next->prev = table;
+ assert(cell->last != NULL);
+
+ cell->last->next = NULL;
+ cell->next = next_child = child;
+ if (cell->next != NULL)
+ cell->next->prev = cell;
else
- block->last = table;
- table->parent = block;
+ row->last = cell;
+ cell->parent = row;
- if (box_normalise_table(table, root, c) == false)
+ if (box_normalise_block(cell, root, c) == false)
return false;
break;
+ case BOX_INLINE:
+ case BOX_INLINE_END:
+ case BOX_INLINE_FLEX:
+ case BOX_INLINE_BLOCK:
+ case BOX_FLOAT_LEFT:
+ case BOX_FLOAT_RIGHT:
+ case BOX_BR:
+ case BOX_TEXT:
+ /* should have been wrapped in inline
+ container by convert_xml_to_box() */
+ assert(0);
+ break;
default:
assert(0);
}
+
+ if (calculate_table_row(col_info, cell->columns, cell->rows,
+ &cell->start_column, cell) == false)
+ return false;
}
+
+ /* Update row spanning details for all columns */
+ for (i = 0; i < col_info->num_columns; i++) {
+ if (col_info->spans[i].row_span != 0 &&
+ col_info->spans[i].auto_row == false) {
+ /* This cell spans rows, and is not an auto row.
+ * Reduce number of rows left to span */
+ col_info->spans[i].row_span--;
+ }
+ }
+
+ /* Reset current column for next row */
+ col_info->current_column = 0;
+
+ /* Increment row counter */
+ col_info->num_rows++;
+
+#ifdef BOX_NORMALISE_DEBUG
+ NSLOG(netsurf, INFO, "row %p done", row);
+#endif
+
return true;
}
-bool box_normalise_table(
- struct box *table,
- const struct box *root,
- html_content * c)
+static bool
+box_normalise_table_row_group(struct box *row_group,
+ const struct box *root,
+ struct columns *col_info,
+ html_content * c)
{
struct box *child;
struct box *next_child;
- struct box *row_group;
+ struct box *row;
css_computed_style *style;
- struct columns col_info;
nscss_select_ctx ctx;
+ unsigned int group_row_count = 0;
- assert(table != NULL);
- assert(table->type == BOX_TABLE);
+ assert(row_group != 0);
+ assert(row_group->type == BOX_TABLE_ROW_GROUP);
ctx.root_style = root->style;
#ifdef BOX_NORMALISE_DEBUG
- NSLOG(netsurf, INFO, "table %p", table);
+ NSLOG(netsurf, INFO, "row_group %p", row_group);
#endif
- col_info.num_columns = 1;
- col_info.current_column = 0;
- col_info.spans = malloc(2 * sizeof *col_info.spans);
- if (col_info.spans == NULL)
- return false;
-
- col_info.spans[0].row_span = col_info.spans[1].row_span = 0;
- col_info.spans[0].auto_row = false;
- col_info.spans[1].auto_row = false;
- col_info.num_rows = 0;
-
- for (child = table->children; child != NULL; child = next_child) {
+ for (child = row_group->children; child != NULL; child = next_child) {
next_child = child->next;
+
switch (child->type) {
- case BOX_TABLE_ROW_GROUP:
+ case BOX_TABLE_ROW:
/* ok */
- if (box_normalise_table_row_group(child, root,
- &col_info, c) == false) {
- free(col_info.spans);
+ group_row_count++;
+ if (box_normalise_table_row(child, root, col_info,
+ c) == false)
return false;
- }
break;
+ case BOX_FLEX:
case BOX_BLOCK:
case BOX_INLINE_CONTAINER:
case BOX_TABLE:
- case BOX_TABLE_ROW:
+ case BOX_TABLE_ROW_GROUP:
case BOX_TABLE_CELL:
- /* insert implied table row group */
- assert(table->style != NULL);
+ /* insert implied table row */
+ assert(row_group->style != NULL);
ctx.ctx = c->select_ctx;
ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
- style = nscss_get_blank_style(&ctx, table->style);
- if (style == NULL) {
- free(col_info.spans);
+ style = nscss_get_blank_style(&ctx, &c->unit_len_ctx,
+ row_group->style);
+ if (style == NULL)
return false;
- }
- row_group = box_create(NULL, style, true, table->href,
- table->target, NULL, NULL, c->bctx);
- if (row_group == NULL) {
+ row = box_create(NULL, style, true, row_group->href,
+ row_group->target, NULL, NULL, c->bctx);
+ if (row == NULL) {
css_computed_style_destroy(style);
- free(col_info.spans);
return false;
}
-
- row_group->type = BOX_TABLE_ROW_GROUP;
+ row->type = BOX_TABLE_ROW;
if (child->prev == NULL)
- table->children = row_group;
+ row_group->children = row;
else
- child->prev->next = row_group;
+ child->prev->next = row;
- row_group->prev = child->prev;
+ row->prev = child->prev;
while (child != NULL && (
+ child->type == BOX_FLEX ||
child->type == BOX_BLOCK ||
child->type == BOX_INLINE_CONTAINER ||
child->type == BOX_TABLE ||
- child->type == BOX_TABLE_ROW ||
+ child->type == BOX_TABLE_ROW_GROUP ||
child->type == BOX_TABLE_CELL)) {
- box_add_child(row_group, child);
+ box_add_child(row, child);
next_child = child->next;
child->next = NULL;
child = next_child;
}
- assert(row_group->last != NULL);
+ assert(row->last != NULL);
- row_group->last->next = NULL;
- row_group->next = next_child = child;
- if (row_group->next != NULL)
- row_group->next->prev = row_group;
+ row->last->next = NULL;
+ row->next = next_child = child;
+ if (row->next != NULL)
+ row->next->prev = row;
else
- table->last = row_group;
- row_group->parent = table;
+ row_group->last = row;
+ row->parent = row_group;
- if (box_normalise_table_row_group(row_group, root,
- &col_info, c) == false) {
- free(col_info.spans);
+ group_row_count++;
+ if (box_normalise_table_row(row, root, col_info,
+ c) == false)
return false;
- }
break;
case BOX_INLINE:
case BOX_INLINE_END:
+ case BOX_INLINE_FLEX:
case BOX_INLINE_BLOCK:
case BOX_FLOAT_LEFT:
case BOX_FLOAT_RIGHT:
@@ -351,48 +393,26 @@ bool box_normalise_table(
assert(0);
break;
default:
- fprintf(stderr, "%i\n", child->type);
assert(0);
}
}
- table->columns = col_info.num_columns;
- table->rows = col_info.num_rows;
-
- if (table->children == NULL) {
- struct box *row;
-
+ if (row_group->children == NULL) {
#ifdef BOX_NORMALISE_DEBUG
NSLOG(netsurf, INFO,
- "table->children == 0, creating implied row");
+ "row_group->children == 0, inserting implied row");
#endif
- assert(table->style != NULL);
+ assert(row_group->style != NULL);
ctx.ctx = c->select_ctx;
ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
- style = nscss_get_blank_style(&ctx, table->style);
+ style = nscss_get_blank_style(&ctx, &c->unit_len_ctx,
+ row_group->style);
if (style == NULL) {
- free(col_info.spans);
- return false;
- }
-
- row_group = box_create(NULL, style, true, table->href,
- table->target, NULL, NULL, c->bctx);
- if (row_group == NULL) {
- css_computed_style_destroy(style);
- free(col_info.spans);
- return false;
- }
- row_group->type = BOX_TABLE_ROW_GROUP;
-
- style = nscss_get_blank_style(&ctx, row_group->style);
- if (style == NULL) {
- box_free(row_group);
- free(col_info.spans);
return false;
}
@@ -400,8 +420,6 @@ bool box_normalise_table(
row_group->target, NULL, NULL, c->bctx);
if (row == NULL) {
css_computed_style_destroy(style);
- box_free(row_group);
- free(col_info.spans);
return false;
}
row->type = BOX_TABLE_ROW;
@@ -409,21 +427,16 @@ bool box_normalise_table(
row->parent = row_group;
row_group->children = row_group->last = row;
- row_group->parent = table;
- table->children = table->last = row_group;
-
- table->rows = 1;
- }
+ group_row_count = 1;
- if (box_normalise_table_spans(table, root, col_info.spans, c) == false) {
- free(col_info.spans);
- return false;
+ /* Keep table's row count in sync */
+ col_info->num_rows++;
}
- free(col_info.spans);
+ row_group->rows = group_row_count;
#ifdef BOX_NORMALISE_DEBUG
- NSLOG(netsurf, INFO, "table %p done", table);
+ NSLOG(netsurf, INFO, "row_group %p done", row_group);
#endif
return true;
@@ -440,12 +453,11 @@ bool box_normalise_table(
* \param c Content containing table
* \return True on success, false on memory exhaustion.
*/
-
-bool box_normalise_table_spans(
- struct box *table,
- const struct box *root,
- struct span_info *spans,
- html_content *c)
+static bool
+box_normalise_table_spans(struct box *table,
+ const struct box *root,
+ struct span_info *spans,
+ html_content *c)
{
struct box *table_row_group;
struct box *table_row;
@@ -460,7 +472,7 @@ bool box_normalise_table_spans(
/* Clear span data */
memset(spans, 0, table->columns * sizeof(struct span_info));
- /* Scan table, filling in width and height of table cells with
+ /* Scan table, filling in width and height of table cells with
* colspan = 0 and rowspan = 0. Also generate empty cells */
for (table_row_group = table->children;
table_row_group != NULL;
@@ -509,34 +521,35 @@ bool box_normalise_table_spans(
css_computed_style *style;
struct box *cell, *prev;
- /* If it's already zero, then we need
- * to generate an empty cell for the
- * gap in the row that spans as many
- * columns as remain blank.
+ /* If it's already zero, then we need
+ * to generate an empty cell for the
+ * gap in the row that spans as many
+ * columns as remain blank.
*/
assert(table_row->style != NULL);
/* Find width of gap */
while (col < table->columns &&
- spans[col].row_span ==
+ spans[col].row_span ==
0) {
col++;
}
ctx.ctx = c->select_ctx;
- ctx.quirks = (c->quirks ==
+ ctx.quirks = (c->quirks ==
DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
- style = nscss_get_blank_style(&ctx,
+ style = nscss_get_blank_style(&ctx,
+ &c->unit_len_ctx,
table_row->style);
if (style == NULL)
return false;
- cell = box_create(NULL, style, true,
- table_row->href,
- table_row->target,
+ cell = box_create(NULL, style, true,
+ table_row->href,
+ table_row->target,
NULL, NULL, c->bctx);
if (cell == NULL) {
css_computed_style_destroy(
@@ -553,8 +566,8 @@ bool box_normalise_table_spans(
for (prev = table_row->children;
prev != NULL;
prev = prev->next) {
- if (prev->start_column +
- prev->columns ==
+ if (prev->start_column +
+ prev->columns ==
start)
break;
if (prev->next == NULL)
@@ -569,7 +582,7 @@ bool box_normalise_table_spans(
else
table_row->last = cell;
- cell->next =
+ cell->next =
table_row->children;
table_row->children = cell;
} else {
@@ -600,101 +613,118 @@ bool box_normalise_table_spans(
}
-bool box_normalise_table_row_group(
- struct box *row_group,
- const struct box *root,
- struct columns *col_info,
- html_content * c)
+static bool
+box_normalise_table(struct box *table, const struct box *root, html_content * c)
{
struct box *child;
struct box *next_child;
- struct box *row;
+ struct box *row_group;
css_computed_style *style;
+ struct columns col_info;
nscss_select_ctx ctx;
- unsigned int group_row_count = 0;
- assert(row_group != 0);
- assert(row_group->type == BOX_TABLE_ROW_GROUP);
+ assert(table != NULL);
+ assert(table->type == BOX_TABLE);
ctx.root_style = root->style;
#ifdef BOX_NORMALISE_DEBUG
- NSLOG(netsurf, INFO, "row_group %p", row_group);
+ NSLOG(netsurf, INFO, "table %p", table);
#endif
- for (child = row_group->children; child != NULL; child = next_child) {
- next_child = child->next;
+ col_info.num_columns = 1;
+ col_info.current_column = 0;
+ col_info.spans = malloc(2 * sizeof *col_info.spans);
+ if (col_info.spans == NULL)
+ return false;
+
+ col_info.spans[0].row_span = col_info.spans[1].row_span = 0;
+ col_info.spans[0].auto_row = false;
+ col_info.spans[1].auto_row = false;
+ col_info.num_rows = 0;
+ for (child = table->children; child != NULL; child = next_child) {
+ next_child = child->next;
switch (child->type) {
- case BOX_TABLE_ROW:
+ case BOX_TABLE_ROW_GROUP:
/* ok */
- group_row_count++;
- if (box_normalise_table_row(child, root, col_info,
- c) == false)
+ if (box_normalise_table_row_group(child, root,
+ &col_info, c) == false) {
+ free(col_info.spans);
return false;
+ }
break;
+ case BOX_FLEX:
case BOX_BLOCK:
case BOX_INLINE_CONTAINER:
case BOX_TABLE:
- case BOX_TABLE_ROW_GROUP:
+ case BOX_TABLE_ROW:
case BOX_TABLE_CELL:
- /* insert implied table row */
- assert(row_group->style != NULL);
+ /* insert implied table row group */
+ assert(table->style != NULL);
ctx.ctx = c->select_ctx;
ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
- style = nscss_get_blank_style(&ctx, row_group->style);
- if (style == NULL)
+ style = nscss_get_blank_style(&ctx, &c->unit_len_ctx,
+ table->style);
+ if (style == NULL) {
+ free(col_info.spans);
return false;
+ }
- row = box_create(NULL, style, true, row_group->href,
- row_group->target, NULL, NULL, c->bctx);
- if (row == NULL) {
+ row_group = box_create(NULL, style, true, table->href,
+ table->target, NULL, NULL, c->bctx);
+ if (row_group == NULL) {
css_computed_style_destroy(style);
+ free(col_info.spans);
return false;
}
- row->type = BOX_TABLE_ROW;
+
+ row_group->type = BOX_TABLE_ROW_GROUP;
if (child->prev == NULL)
- row_group->children = row;
+ table->children = row_group;
else
- child->prev->next = row;
+ child->prev->next = row_group;
- row->prev = child->prev;
+ row_group->prev = child->prev;
while (child != NULL && (
+ child->type == BOX_FLEX ||
child->type == BOX_BLOCK ||
child->type == BOX_INLINE_CONTAINER ||
child->type == BOX_TABLE ||
- child->type == BOX_TABLE_ROW_GROUP ||
+ child->type == BOX_TABLE_ROW ||
child->type == BOX_TABLE_CELL)) {
- box_add_child(row, child);
+ box_add_child(row_group, child);
next_child = child->next;
child->next = NULL;
child = next_child;
}
- assert(row->last != NULL);
+ assert(row_group->last != NULL);
- row->last->next = NULL;
- row->next = next_child = child;
- if (row->next != NULL)
- row->next->prev = row;
+ row_group->last->next = NULL;
+ row_group->next = next_child = child;
+ if (row_group->next != NULL)
+ row_group->next->prev = row_group;
else
- row_group->last = row;
- row->parent = row_group;
+ table->last = row_group;
+ row_group->parent = table;
- group_row_count++;
- if (box_normalise_table_row(row, root, col_info,
- c) == false)
+ if (box_normalise_table_row_group(row_group, root,
+ &col_info, c) == false) {
+ free(col_info.spans);
return false;
+ }
break;
case BOX_INLINE:
case BOX_INLINE_END:
+ case BOX_INLINE_FLEX:
case BOX_INLINE_BLOCK:
case BOX_FLOAT_LEFT:
case BOX_FLOAT_RIGHT:
@@ -705,25 +735,50 @@ bool box_normalise_table_row_group(
assert(0);
break;
default:
+ fprintf(stderr, "%i\n", child->type);
assert(0);
}
}
- if (row_group->children == NULL) {
+ table->columns = col_info.num_columns;
+ table->rows = col_info.num_rows;
+
+ if (table->children == NULL) {
+ struct box *row;
+
#ifdef BOX_NORMALISE_DEBUG
NSLOG(netsurf, INFO,
- "row_group->children == 0, inserting implied row");
+ "table->children == 0, creating implied row");
#endif
- assert(row_group->style != NULL);
+ assert(table->style != NULL);
ctx.ctx = c->select_ctx;
ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
- style = nscss_get_blank_style(&ctx, row_group->style);
+ style = nscss_get_blank_style(&ctx, &c->unit_len_ctx,
+ table->style);
+ if (style == NULL) {
+ free(col_info.spans);
+ return false;
+ }
+
+ row_group = box_create(NULL, style, true, table->href,
+ table->target, NULL, NULL, c->bctx);
+ if (row_group == NULL) {
+ css_computed_style_destroy(style);
+ free(col_info.spans);
+ return false;
+ }
+ row_group->type = BOX_TABLE_ROW_GROUP;
+
+ style = nscss_get_blank_style(&ctx, &c->unit_len_ctx,
+ row_group->style);
if (style == NULL) {
+ box_free(row_group);
+ free(col_info.spans);
return false;
}
@@ -731,6 +786,8 @@ bool box_normalise_table_row_group(
row_group->target, NULL, NULL, c->bctx);
if (row == NULL) {
css_computed_style_destroy(style);
+ box_free(row_group);
+ free(col_info.spans);
return false;
}
row->type = BOX_TABLE_ROW;
@@ -738,114 +795,129 @@ bool box_normalise_table_row_group(
row->parent = row_group;
row_group->children = row_group->last = row;
- group_row_count = 1;
+ row_group->parent = table;
+ table->children = table->last = row_group;
- /* Keep table's row count in sync */
- col_info->num_rows++;
+ table->rows = 1;
}
- row_group->rows = group_row_count;
+ if (box_normalise_table_spans(table, root, col_info.spans, c) == false) {
+ free(col_info.spans);
+ return false;
+ }
+
+ free(col_info.spans);
#ifdef BOX_NORMALISE_DEBUG
- NSLOG(netsurf, INFO, "row_group %p done", row_group);
+ NSLOG(netsurf, INFO, "table %p done", table);
#endif
return true;
}
-
-bool box_normalise_table_row(
- struct box *row,
+static bool box_normalise_flex(
+ struct box *flex_container,
const struct box *root,
- struct columns *col_info,
- html_content * c)
+ html_content *c)
{
struct box *child;
struct box *next_child;
- struct box *cell = NULL;
+ struct box *implied_flex_item;
css_computed_style *style;
- unsigned int i;
nscss_select_ctx ctx;
- assert(row != NULL);
- assert(row->type == BOX_TABLE_ROW);
+ assert(flex_container != NULL);
+ assert(root != NULL);
ctx.root_style = root->style;
#ifdef BOX_NORMALISE_DEBUG
- NSLOG(netsurf, INFO, "row %p", row);
+ NSLOG(netsurf, INFO, "flex_container %p, flex_container->type %u",
+ flex_container, flex_container->type);
#endif
- for (child = row->children; child != NULL; child = next_child) {
- next_child = child->next;
+ assert(flex_container->type == BOX_FLEX ||
+ flex_container->type == BOX_INLINE_FLEX);
+
+ for (child = flex_container->children; child != NULL; child = next_child) {
+#ifdef BOX_NORMALISE_DEBUG
+ NSLOG(netsurf, INFO, "child %p, child->type = %d",
+ child, child->type);
+#endif
+
+ next_child = child->next; /* child may be destroyed */
switch (child->type) {
- case BOX_TABLE_CELL:
+ case BOX_FLEX:
/* ok */
- if (box_normalise_block(child, root, c) == false)
+ if (box_normalise_flex(child, root, c) == false)
return false;
- cell = child;
break;
case BOX_BLOCK:
+ /* ok */
+ if (box_normalise_block(child, root, c) == false)
+ return false;
+ break;
case BOX_INLINE_CONTAINER:
- case BOX_TABLE:
- case BOX_TABLE_ROW_GROUP:
- case BOX_TABLE_ROW:
- /* insert implied table cell */
- assert(row->style != NULL);
+ /* insert implied flex item */
+ assert(flex_container->style != NULL);
ctx.ctx = c->select_ctx;
ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
- style = nscss_get_blank_style(&ctx, row->style);
+ style = nscss_get_blank_style(&ctx, &c->unit_len_ctx,
+ flex_container->style);
if (style == NULL)
return false;
- cell = box_create(NULL, style, true, row->href,
- row->target, NULL, NULL, c->bctx);
- if (cell == NULL) {
+ implied_flex_item = box_create(NULL, style, true,
+ flex_container->href,
+ flex_container->target,
+ NULL, NULL, c->bctx);
+ if (implied_flex_item == NULL) {
css_computed_style_destroy(style);
return false;
}
- cell->type = BOX_TABLE_CELL;
+ implied_flex_item->type = BOX_BLOCK;
if (child->prev == NULL)
- row->children = cell;
+ flex_container->children = implied_flex_item;
else
- child->prev->next = cell;
+ child->prev->next = implied_flex_item;
- cell->prev = child->prev;
+ implied_flex_item->prev = child->prev;
- while (child != NULL && (
- child->type == BOX_BLOCK ||
- child->type == BOX_INLINE_CONTAINER ||
- child->type == BOX_TABLE ||
- child->type == BOX_TABLE_ROW_GROUP ||
- child->type == BOX_TABLE_ROW)) {
- box_add_child(cell, child);
+ while (child != NULL &&
+ child->type == BOX_INLINE_CONTAINER) {
+ box_add_child(implied_flex_item, child);
next_child = child->next;
child->next = NULL;
child = next_child;
}
- assert(cell->last != NULL);
-
- cell->last->next = NULL;
- cell->next = next_child = child;
- if (cell->next != NULL)
- cell->next->prev = cell;
+ implied_flex_item->last->next = NULL;
+ implied_flex_item->next = next_child = child;
+ if (implied_flex_item->next != NULL)
+ implied_flex_item->next->prev = implied_flex_item;
else
- row->last = cell;
- cell->parent = row;
+ flex_container->last = implied_flex_item;
+ implied_flex_item->parent = flex_container;
- if (box_normalise_block(cell, root, c) == false)
+ if (box_normalise_block(implied_flex_item,
+ root, c) == false)
+ return false;
+ break;
+
+ case BOX_TABLE:
+ if (box_normalise_table(child, root, c) == false)
return false;
break;
case BOX_INLINE:
case BOX_INLINE_END:
+ case BOX_INLINE_FLEX:
case BOX_INLINE_BLOCK:
case BOX_FLOAT_LEFT:
case BOX_FLOAT_RIGHT:
@@ -855,119 +927,74 @@ bool box_normalise_table_row(
container by convert_xml_to_box() */
assert(0);
break;
- default:
- assert(0);
- }
-
- if (calculate_table_row(col_info, cell->columns, cell->rows,
- &cell->start_column, cell) == false)
- return false;
- }
-
-
- /* Update row spanning details for all columns */
- for (i = 0; i < col_info->num_columns; i++) {
- if (col_info->spans[i].row_span != 0 &&
- col_info->spans[i].auto_row == false) {
- /* This cell spans rows, and is not an auto row.
- * Reduce number of rows left to span */
- col_info->spans[i].row_span--;
- }
- }
-
- /* Reset current column for next row */
- col_info->current_column = 0;
-
- /* Increment row counter */
- col_info->num_rows++;
-
-#ifdef BOX_NORMALISE_DEBUG
- NSLOG(netsurf, INFO, "row %p done", row);
-#endif
-
- return true;
-}
-
+ case BOX_TABLE_ROW_GROUP:
+ case BOX_TABLE_ROW:
+ case BOX_TABLE_CELL:
+ /* insert implied table */
+ assert(flex_container->style != NULL);
-/**
- * Compute the column index at which the current cell begins.
- * Additionally, update the column record to reflect row spanning.
- *
- * \param col_info Column record
- * \param col_span Number of columns that current cell spans
- * \param row_span Number of rows that current cell spans
- * \param start_column Pointer to location to receive column index
- * \param cell Box for current table cell
- * \return true on success, false on memory exhaustion
- */
+ ctx.ctx = c->select_ctx;
+ ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
+ ctx.base_url = c->base_url;
+ ctx.universal = c->universal;
-bool calculate_table_row(struct columns *col_info,
- unsigned int col_span, unsigned int row_span,
- unsigned int *start_column, struct box *cell)
-{
- unsigned int cell_start_col = col_info->current_column;
- unsigned int cell_end_col;
- unsigned int i;
- struct span_info *spans;
- struct box *rg = cell->parent->parent; /* Cell's row group */
+ style = nscss_get_blank_style(&ctx, &c->unit_len_ctx,
+ flex_container->style);
+ if (style == NULL)
+ return false;
- /* Skip columns with cells spanning from above */
- /* TODO: Need to ignore cells spanning from above that belong to
- * different row group. We don't have that info here. */
- while (col_info->spans[cell_start_col].row_span != 0 &&
- col_info->spans[cell_start_col].rg == rg) {
- cell_start_col++;
- }
+ implied_flex_item = box_create(NULL, style, true,
+ flex_container->href,
+ flex_container->target,
+ NULL, NULL, c->bctx);
+ if (implied_flex_item == NULL) {
+ css_computed_style_destroy(style);
+ return false;
+ }
+ implied_flex_item->type = BOX_TABLE;
- /* Update current column with calculated start */
- col_info->current_column = cell_start_col;
+ if (child->prev == NULL)
+ flex_container->children = implied_flex_item;
+ else
+ child->prev->next = implied_flex_item;
- /* If this cell has a colspan of 0, then assume 1.
- * No other browser supports colspan=0, anyway. */
- if (col_span == 0)
- col_span = 1;
-
- cell_end_col = cell_start_col + col_span;
+ implied_flex_item->prev = child->prev;
- if (col_info->num_columns < cell_end_col) {
- /* It appears that this row has more columns than
- * the maximum recorded for the table so far.
- * Allocate more span records. */
- spans = realloc(col_info->spans,
- sizeof *spans * (cell_end_col + 1));
- if (spans == NULL)
- return false;
+ while (child != NULL && (
+ child->type == BOX_TABLE_ROW_GROUP ||
+ child->type == BOX_TABLE_ROW ||
+ child->type == BOX_TABLE_CELL)) {
+ box_add_child(implied_flex_item, child);
- col_info->spans = spans;
- col_info->num_columns = cell_end_col;
+ next_child = child->next;
+ child->next = NULL;
+ child = next_child;
+ }
- /* Mark new final column as sentinel */
- col_info->spans[cell_end_col].row_span = 0;
- col_info->spans[cell_end_col].auto_row = false;
- }
+ implied_flex_item->last->next = NULL;
+ implied_flex_item->next = next_child = child;
+ if (implied_flex_item->next != NULL)
+ implied_flex_item->next->prev = implied_flex_item;
+ else
+ flex_container->last = implied_flex_item;
+ implied_flex_item->parent = flex_container;
- /* This cell may span multiple columns. If it also wants to span
- * multiple rows, temporarily assume it spans 1 row only. This will
- * be fixed up in box_normalise_table_spans() */
- for (i = cell_start_col; i < cell_end_col; i++) {
- col_info->spans[i].row_span = (row_span == 0) ? 1 : row_span;
- col_info->spans[i].auto_row = (row_span == 0);
- col_info->spans[i].rg = rg;
+ if (box_normalise_table(implied_flex_item,
+ root, c) == false)
+ return false;
+ break;
+ default:
+ assert(0);
+ }
}
- /* Update current column with calculated end. */
- col_info->current_column = cell_end_col;
-
- *start_column = cell_start_col;
-
return true;
}
-
-bool box_normalise_inline_container(
- struct box *cont,
- const struct box *root,
- html_content * c)
+static bool
+box_normalise_inline_container(struct box *cont,
+ const struct box *root,
+ html_content * c)
{
struct box *child;
struct box *next_child;
@@ -993,6 +1020,11 @@ bool box_normalise_inline_container(
if (box_normalise_block(child, root, c) == false)
return false;
break;
+ case BOX_INLINE_FLEX:
+ /* ok */
+ if (box_normalise_flex(child, root, c) == false)
+ return false;
+ break;
case BOX_FLOAT_LEFT:
case BOX_FLOAT_RIGHT:
/* ok */
@@ -1009,6 +1041,11 @@ bool box_normalise_inline_container(
c) == false)
return false;
break;
+ case BOX_FLEX:
+ if (box_normalise_flex(child->children, root,
+ c) == false)
+ return false;
+ break;
default:
assert(0);
}
@@ -1027,6 +1064,7 @@ bool box_normalise_inline_container(
box_free(child);
}
break;
+ case BOX_FLEX:
case BOX_BLOCK:
case BOX_INLINE_CONTAINER:
case BOX_TABLE:
@@ -1044,3 +1082,125 @@ bool box_normalise_inline_container(
return true;
}
+
+/* Exported function documented in html/box_normalise.h */
+bool
+box_normalise_block(struct box *block, const struct box *root, html_content *c)
+{
+ struct box *child;
+ struct box *next_child;
+ struct box *table;
+ css_computed_style *style;
+ nscss_select_ctx ctx;
+
+ assert(block != NULL);
+ assert(root != NULL);
+
+ ctx.root_style = root->style;
+
+#ifdef BOX_NORMALISE_DEBUG
+ NSLOG(netsurf, INFO, "block %p, block->type %u", block, block->type);
+#endif
+
+ assert(block->type == BOX_BLOCK || block->type == BOX_INLINE_BLOCK ||
+ block->type == BOX_TABLE_CELL);
+
+ for (child = block->children; child != NULL; child = next_child) {
+#ifdef BOX_NORMALISE_DEBUG
+ NSLOG(netsurf, INFO, "child %p, child->type = %d", child,
+ child->type);
+#endif
+
+ next_child = child->next; /* child may be destroyed */
+
+ switch (child->type) {
+ case BOX_FLEX:
+ /* ok */
+ if (box_normalise_flex(child, root, c) == false)
+ return false;
+ break;
+ case BOX_BLOCK:
+ /* ok */
+ if (box_normalise_block(child, root, c) == false)
+ return false;
+ break;
+ case BOX_INLINE_CONTAINER:
+ if (box_normalise_inline_container(child, root, c) == false)
+ return false;
+ break;
+ case BOX_TABLE:
+ if (box_normalise_table(child, root, c) == false)
+ return false;
+ break;
+ case BOX_INLINE:
+ case BOX_INLINE_END:
+ case BOX_INLINE_FLEX:
+ case BOX_INLINE_BLOCK:
+ case BOX_FLOAT_LEFT:
+ case BOX_FLOAT_RIGHT:
+ case BOX_BR:
+ case BOX_TEXT:
+ /* should have been wrapped in inline
+ container by convert_xml_to_box() */
+ assert(0);
+ break;
+ case BOX_TABLE_ROW_GROUP:
+ case BOX_TABLE_ROW:
+ case BOX_TABLE_CELL:
+ /* insert implied table */
+ assert(block->style != NULL);
+
+ ctx.ctx = c->select_ctx;
+ ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
+ ctx.base_url = c->base_url;
+ ctx.universal = c->universal;
+
+ style = nscss_get_blank_style(&ctx, &c->unit_len_ctx,
+ block->style);
+ if (style == NULL)
+ return false;
+
+ table = box_create(NULL, style, true, block->href,
+ block->target, NULL, NULL, c->bctx);
+ if (table == NULL) {
+ css_computed_style_destroy(style);
+ return false;
+ }
+ table->type = BOX_TABLE;
+
+ if (child->prev == NULL)
+ block->children = table;
+ else
+ child->prev->next = table;
+
+ table->prev = child->prev;
+
+ while (child != NULL && (
+ child->type == BOX_TABLE_ROW_GROUP ||
+ child->type == BOX_TABLE_ROW ||
+ child->type == BOX_TABLE_CELL)) {
+ box_add_child(table, child);
+
+ next_child = child->next;
+ child->next = NULL;
+ child = next_child;
+ }
+
+ table->last->next = NULL;
+ table->next = next_child = child;
+ if (table->next != NULL)
+ table->next->prev = table;
+ else
+ block->last = table;
+ table->parent = block;
+
+ if (box_normalise_table(table, root, c) == false)
+ return false;
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ return true;
+}
diff --git a/content/handlers/html/box_normalise.h b/content/handlers/html/box_normalise.h
new file mode 100644
index 000000000..377cd9019
--- /dev/null
+++ b/content/handlers/html/box_normalise.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * HTML Box tree normalise interface.
+ *
+ * A box tree is "normalized" if the following is satisfied:
+ * \code
+ * parent permitted child nodes
+ * BLOCK, INLINE_BLOCK BLOCK, INLINE_CONTAINER, TABLE
+ * INLINE_CONTAINER INLINE, INLINE_BLOCK, FLOAT_LEFT, FLOAT_RIGHT, BR, TEXT,
+ * INLINE_END
+ * INLINE none
+ * TABLE at least 1 TABLE_ROW_GROUP
+ * TABLE_ROW_GROUP at least 1 TABLE_ROW
+ * TABLE_ROW at least 1 TABLE_CELL
+ * TABLE_CELL BLOCK, INLINE_CONTAINER, TABLE (same as BLOCK)
+ * FLOAT_(LEFT|RIGHT) exactly 1 BLOCK or TABLE
+ * \endcode
+ *
+ */
+
+#ifndef NETSURF_HTML_BOX_NORMALISE_H
+#define NETSURF_HTML_BOX_NORMALISE_H
+
+/**
+ * Ensure the box tree is correctly nested by adding and removing nodes.
+ *
+ * \param block box of type BLOCK, INLINE_BLOCK, or TABLE_CELL
+ * \param root root box of document
+ * \param c content of boxes
+ * \return true on success, false on memory exhaustion
+ *
+ * The tree is modified to satisfy the following:
+ * \code
+ * parent permitted child nodes
+ * BLOCK, INLINE_BLOCK BLOCK, INLINE_CONTAINER, TABLE, FLEX
+ * FLEX, INLINE_FLEX BLOCK, INLINE_CONTAINER, TABLE, FLEX
+ * INLINE_CONTAINER INLINE, INLINE_BLOCK, FLOAT_LEFT, FLOAT_RIGHT, BR, TEXT, INLINE_FLEX
+ * INLINE, TEXT none
+ * TABLE at least 1 TABLE_ROW_GROUP
+ * TABLE_ROW_GROUP at least 1 TABLE_ROW
+ * TABLE_ROW at least 1 TABLE_CELL
+ * TABLE_CELL BLOCK, INLINE_CONTAINER, TABLE, FLEX (same as BLOCK)
+ * FLOAT_(LEFT|RIGHT) exactly 1 BLOCK, TABLE or FLEX
+ * \endcode
+ */
+bool box_normalise_block(struct box *block, const struct box *root, struct html_content *c);
+
+#endif
diff --git a/content/handlers/html/box_special.c b/content/handlers/html/box_special.c
new file mode 100644
index 000000000..db3c4126d
--- /dev/null
+++ b/content/handlers/html/box_special.c
@@ -0,0 +1,1935 @@
+/*
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
+ * Copyright 2005 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ * Copyright 2008 Michael Drake <tlsa@netsurf-browser.org>
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of special element handling conversion.
+ */
+
+#include <string.h>
+#include <stdbool.h>
+#include <dom/dom.h>
+
+#include "utils/nsoption.h"
+#include "utils/corestrings.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/talloc.h"
+#include "utils/string.h"
+#include "utils/ascii.h"
+#include "utils/nsurl.h"
+#include "netsurf/plot_style.h"
+#include "css/hints.h"
+#include "desktop/frame_types.h"
+#include "content/content_factory.h"
+
+#include "html/html.h"
+#include "html/private.h"
+#include "html/object.h"
+#include "html/box.h"
+#include "html/box_manipulate.h"
+#include "html/box_construct.h"
+#include "html/box_special.h"
+#include "html/box_textarea.h"
+#include "html/form_internal.h"
+
+
+static const content_type image_types = CONTENT_IMAGE;
+
+
+/**
+ * determine if a box is the root node
+ *
+ * \param n node to check
+ * \return true if node is root else false.
+ */
+static inline bool box_is_root(dom_node *n)
+{
+ dom_node *parent;
+ dom_node_type type;
+ dom_exception err;
+
+ err = dom_node_get_parent_node(n, &parent);
+ if (err != DOM_NO_ERR)
+ return false;
+
+ if (parent != NULL) {
+ err = dom_node_get_node_type(parent, &type);
+
+ dom_node_unref(parent);
+
+ if (err != DOM_NO_ERR)
+ return false;
+
+ if (type != DOM_DOCUMENT_NODE)
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ * Destructor for object_params, for &lt;object&gt; elements
+ *
+ * \param o The object params being destroyed.
+ * \return 0 to allow talloc to continue destroying the tree.
+ */
+static int box_object_talloc_destructor(struct object_params *o)
+{
+ if (o->codebase != NULL)
+ nsurl_unref(o->codebase);
+ if (o->classid != NULL)
+ nsurl_unref(o->classid);
+ if (o->data != NULL)
+ nsurl_unref(o->data);
+
+ return 0;
+}
+
+
+/**
+ * Parse a multi-length-list, as defined by HTML 4.01.
+ *
+ * \param ds dom string to parse
+ * \param count updated to number of entries
+ * \return array of struct box_multi_length, or 0 on memory exhaustion
+ */
+static struct frame_dimension *
+box_parse_multi_lengths(const dom_string *ds, unsigned int *count)
+{
+ char *end;
+ unsigned int i, n;
+ struct frame_dimension *length;
+ const char *s;
+
+ s = dom_string_data(ds);
+
+ for (i = 0, n = 1; s[i]; i++)
+ if (s[i] == ',')
+ n++;
+
+ length = calloc(n, sizeof(struct frame_dimension));
+ if (!length)
+ return NULL;
+
+ for (i = 0; i != n; i++) {
+ while (ascii_is_space(*s)) {
+ s++;
+ }
+ length[i].value = strtof(s, &end);
+ if (length[i].value <= 0) {
+ length[i].value = 1;
+ }
+ s = end;
+ switch (*s) {
+ case '%':
+ length[i].unit = FRAME_DIMENSION_PERCENT;
+ break;
+ case '*':
+ length[i].unit = FRAME_DIMENSION_RELATIVE;
+ break;
+ default:
+ length[i].unit = FRAME_DIMENSION_PIXELS;
+ break;
+ }
+ while (*s && *s != ',') {
+ s++;
+ }
+ if (*s == ',') {
+ s++;
+ }
+ }
+
+ *count = n;
+ return length;
+}
+
+
+/**
+ * Destructor for content_html_frames, for frame elements
+ *
+ * \param f The frame params being destroyed.
+ * \return 0 to allow talloc to continue destroying the tree.
+ */
+static int box_frames_talloc_destructor(struct content_html_frames *f)
+{
+ if (f->url != NULL) {
+ nsurl_unref(f->url);
+ f->url = NULL;
+ }
+
+ return 0;
+}
+
+
+/**
+ * create a frameset box tree
+ */
+static bool
+box_create_frameset(struct content_html_frames *f,
+ dom_node *n,
+ html_content *content)
+{
+ unsigned int row, col, index, i;
+ unsigned int rows = 1, cols = 1;
+ dom_string *s;
+ dom_exception err;
+ nsurl *url;
+ struct frame_dimension *row_height = 0, *col_width = 0;
+ dom_node *c, *next;
+ struct content_html_frames *frame;
+ bool default_border = true;
+ colour default_border_colour = 0x000000;
+
+ /* parse rows and columns */
+ err = dom_element_get_attribute(n, corestring_dom_rows, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ row_height = box_parse_multi_lengths(s, &rows);
+ dom_string_unref(s);
+ if (row_height == NULL)
+ return false;
+ } else {
+ row_height = calloc(1, sizeof(struct frame_dimension));
+ if (row_height == NULL)
+ return false;
+ row_height->value = 100;
+ row_height->unit = FRAME_DIMENSION_PERCENT;
+ }
+
+ err = dom_element_get_attribute(n, corestring_dom_cols, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ col_width = box_parse_multi_lengths(s, &cols);
+ dom_string_unref(s);
+ if (col_width == NULL) {
+ free(row_height);
+ return false;
+ }
+ } else {
+ col_width = calloc(1, sizeof(struct frame_dimension));
+ if (col_width == NULL) {
+ free(row_height);
+ return false;
+ }
+ col_width->value = 100;
+ col_width->unit = FRAME_DIMENSION_PERCENT;
+ }
+
+ /* common extension: border="0|1" to control all children */
+ err = dom_element_get_attribute(n, corestring_dom_border, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ if ((dom_string_data(s)[0] == '0') &&
+ (dom_string_data(s)[1] == '\0'))
+ default_border = false;
+ dom_string_unref(s);
+ }
+
+ /* common extension: frameborder="yes|no" to control all children */
+ err = dom_element_get_attribute(n, corestring_dom_frameborder, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ if (dom_string_caseless_lwc_isequal(s,
+ corestring_lwc_no) == 0)
+ default_border = false;
+ dom_string_unref(s);
+ }
+
+ /* common extension: bordercolor="#RRGGBB|<named colour>" to control
+ *all children */
+ err = dom_element_get_attribute(n, corestring_dom_bordercolor, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ css_color color;
+
+ if (nscss_parse_colour(dom_string_data(s), &color))
+ default_border_colour = nscss_color_to_ns(color);
+
+ dom_string_unref(s);
+ }
+
+ /* update frameset and create default children */
+ f->cols = cols;
+ f->rows = rows;
+ f->scrolling = BW_SCROLLING_NO;
+ f->children = talloc_array(content->bctx, struct content_html_frames,
+ (rows * cols));
+
+ talloc_set_destructor(f->children, box_frames_talloc_destructor);
+
+ for (row = 0; row < rows; row++) {
+ for (col = 0; col < cols; col++) {
+ index = (row * cols) + col;
+ frame = &f->children[index];
+ frame->cols = 0;
+ frame->rows = 0;
+ frame->width = col_width[col];
+ frame->height = row_height[row];
+ frame->margin_width = 0;
+ frame->margin_height = 0;
+ frame->name = NULL;
+ frame->url = NULL;
+ frame->no_resize = false;
+ frame->scrolling = BW_SCROLLING_AUTO;
+ frame->border = default_border;
+ frame->border_colour = default_border_colour;
+ frame->children = NULL;
+ }
+ }
+ free(col_width);
+ free(row_height);
+
+ /* create the frameset windows */
+ err = dom_node_get_first_child(n, &c);
+ if (err != DOM_NO_ERR)
+ return false;
+
+ for (row = 0; c != NULL && row < rows; row++) {
+ for (col = 0; c != NULL && col < cols; col++) {
+ while (c != NULL) {
+ dom_node_type type;
+ dom_string *name;
+
+ err = dom_node_get_node_type(c, &type);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(c);
+ return false;
+ }
+
+ err = dom_node_get_node_name(c, &name);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(c);
+ return false;
+ }
+
+ if (type != DOM_ELEMENT_NODE ||
+ (!dom_string_caseless_lwc_isequal(
+ name,
+ corestring_lwc_frame) &&
+ !dom_string_caseless_lwc_isequal(
+ name,
+ corestring_lwc_frameset
+ ))) {
+ err = dom_node_get_next_sibling(c,
+ &next);
+ if (err != DOM_NO_ERR) {
+ dom_string_unref(name);
+ dom_node_unref(c);
+ return false;
+ }
+
+ dom_string_unref(name);
+ dom_node_unref(c);
+ c = next;
+ } else {
+ /* Got a FRAME or FRAMESET element */
+ dom_string_unref(name);
+ break;
+ }
+ }
+
+ if (c == NULL)
+ break;
+
+ /* get current frame */
+ index = (row * cols) + col;
+ frame = &f->children[index];
+
+ /* nest framesets */
+ err = dom_node_get_node_name(c, &s);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(c);
+ return false;
+ }
+
+ if (dom_string_caseless_lwc_isequal(s,
+ corestring_lwc_frameset)) {
+ dom_string_unref(s);
+ frame->border = 0;
+ if (box_create_frameset(frame, c,
+ content) == false) {
+ dom_node_unref(c);
+ return false;
+ }
+
+ err = dom_node_get_next_sibling(c, &next);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(c);
+ return false;
+ }
+
+ dom_node_unref(c);
+ c = next;
+ continue;
+ }
+
+ dom_string_unref(s);
+
+ /* get frame URL (not required) */
+ url = NULL;
+ err = dom_element_get_attribute(c, corestring_dom_src, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ box_extract_link(content, s, content->base_url,
+ &url);
+ dom_string_unref(s);
+ }
+
+ /* copy url */
+ if (url != NULL) {
+ /* no self-references */
+ if (nsurl_compare(content->base_url, url,
+ NSURL_COMPLETE) == false)
+ frame->url = url;
+ url = NULL;
+ }
+
+ /* fill in specified values */
+ err = dom_element_get_attribute(c, corestring_dom_name, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ frame->name = talloc_strdup(content->bctx,
+ dom_string_data(s));
+ dom_string_unref(s);
+ }
+
+ if (dom_element_has_attribute(c, corestring_dom_noresize,
+ &frame->no_resize) != DOM_NO_ERR) {
+ /* If we can't read the attribute for some reason,
+ * assume we didn't have it.
+ */
+ frame->no_resize = false;
+ }
+
+ err = dom_element_get_attribute(c, corestring_dom_frameborder,
+ &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ i = atoi(dom_string_data(s));
+ frame->border = (i != 0);
+ dom_string_unref(s);
+ }
+
+ err = dom_element_get_attribute(c, corestring_dom_scrolling, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ if (dom_string_caseless_lwc_isequal(s,
+ corestring_lwc_yes))
+ frame->scrolling = BW_SCROLLING_YES;
+ else if (dom_string_caseless_lwc_isequal(s,
+ corestring_lwc_no))
+ frame->scrolling = BW_SCROLLING_NO;
+ dom_string_unref(s);
+ }
+
+ err = dom_element_get_attribute(c, corestring_dom_marginwidth,
+ &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ frame->margin_width = atoi(dom_string_data(s));
+ dom_string_unref(s);
+ }
+
+ err = dom_element_get_attribute(c, corestring_dom_marginheight,
+ &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ frame->margin_height = atoi(dom_string_data(s));
+ dom_string_unref(s);
+ }
+
+ err = dom_element_get_attribute(c, corestring_dom_bordercolor,
+ &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ css_color color;
+
+ if (nscss_parse_colour(dom_string_data(s),
+ &color))
+ frame->border_colour =
+ nscss_color_to_ns(color);
+
+ dom_string_unref(s);
+ }
+
+ /* advance */
+ err = dom_node_get_next_sibling(c, &next);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(c);
+ return false;
+ }
+
+ dom_node_unref(c);
+ c = next;
+ }
+ }
+
+ /* If the last child wasn't a frame, we still need to unref it */
+ if (c != NULL) {
+ dom_node_unref(c);
+ }
+
+ return true;
+}
+
+
+/**
+ * Destructor for content_html_iframe, for &lt;iframe&gt; elements
+ *
+ * \param f The iframe params being destroyed.
+ * \return 0 to allow talloc to continue destroying the tree.
+ */
+static int box_iframes_talloc_destructor(struct content_html_iframe *f)
+{
+ if (f->url != NULL) {
+ nsurl_unref(f->url);
+ f->url = NULL;
+ }
+
+ return 0;
+}
+
+
+/**
+ * Get the value of a dom node element's attribute.
+ *
+ * \param n dom element node
+ * \param attribute name of attribute
+ * \param context talloc context for result buffer
+ * \param value updated to value, if the attribute is present
+ * \return true on success, false if attribute present but memory exhausted
+ *
+ * \note returning true does not imply that the attribute was found. If the
+ * attribute was not found, *value will be unchanged.
+ */
+static bool
+box_get_attribute(dom_node *n,
+ const char *attribute,
+ void *context,
+ char **value)
+{
+ char *result;
+ dom_string *attr, *attr_name;
+ dom_exception err;
+
+ err = dom_string_create_interned((const uint8_t *) attribute,
+ strlen(attribute), &attr_name);
+ if (err != DOM_NO_ERR)
+ return false;
+
+ err = dom_element_get_attribute(n, attr_name, &attr);
+ if (err != DOM_NO_ERR) {
+ dom_string_unref(attr_name);
+ return false;
+ }
+
+ dom_string_unref(attr_name);
+
+ if (attr != NULL) {
+ result = talloc_strdup(context, dom_string_data(attr));
+
+ dom_string_unref(attr);
+
+ if (result == NULL)
+ return false;
+
+ *value = result;
+ }
+
+ return true;
+}
+
+
+/**
+ * Helper function for adding textarea widget to box.
+ *
+ * This is a load of hacks to ensure boxes replaced with textareas
+ * can be handled by the layout code.
+ */
+static bool
+box_input_text(html_content *html, struct box *box, struct dom_node *node)
+{
+ struct box *inline_container, *inline_box;
+ uint8_t display = css_computed_display_static(box->style);
+
+ switch (display) {
+ case CSS_DISPLAY_GRID:
+ case CSS_DISPLAY_FLEX:
+ case CSS_DISPLAY_BLOCK:
+ box->type = BOX_BLOCK;
+ break;
+ default:
+ box->type = BOX_INLINE_BLOCK;
+ break;
+ }
+
+ inline_container = box_create(NULL, 0, false, 0, 0, 0, 0, html->bctx);
+ if (!inline_container)
+ return false;
+ inline_container->type = BOX_INLINE_CONTAINER;
+ inline_box = box_create(NULL, box->style, false, 0, 0, box->title, 0,
+ html->bctx);
+ if (!inline_box)
+ return false;
+ inline_box->type = BOX_TEXT;
+ inline_box->text = talloc_strdup(html->bctx, "");
+
+ box_add_child(inline_container, inline_box);
+ box_add_child(box, inline_container);
+
+ return box_textarea_create_textarea(html, box, node);
+}
+
+
+/**
+ * Add an option to a form select control (helper function for box_select()).
+ *
+ * \param control select containing the &lt;option&gt;
+ * \param n xml element node for &lt;option&gt;
+ * \return true on success, false on memory exhaustion
+ */
+static bool box_select_add_option(struct form_control *control, dom_node *n)
+{
+ char *value = NULL;
+ char *text = NULL;
+ char *text_nowrap = NULL;
+ bool selected;
+ dom_string *content, *s;
+ dom_exception err;
+
+ err = dom_node_get_text_content(n, &content);
+ if (err != DOM_NO_ERR)
+ return false;
+
+ if (content != NULL) {
+ text = squash_whitespace(dom_string_data(content));
+ dom_string_unref(content);
+ } else {
+ text = strdup("");
+ }
+
+ if (text == NULL)
+ goto no_memory;
+
+ err = dom_element_get_attribute(n, corestring_dom_value, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ value = strdup(dom_string_data(s));
+ dom_string_unref(s);
+ } else {
+ value = strdup(text);
+ }
+
+ if (value == NULL)
+ goto no_memory;
+
+ if (dom_element_has_attribute(n, corestring_dom_selected, &selected) != DOM_NO_ERR) {
+ /* Assume not selected if we can't read the attribute presence */
+ selected = false;
+ }
+
+ /* replace spaces/TABs with hard spaces to prevent line wrapping */
+ text_nowrap = cnv_space2nbsp(text);
+ if (text_nowrap == NULL)
+ goto no_memory;
+
+ if (form_add_option(control, value, text_nowrap, selected, n) == false)
+ goto no_memory;
+
+ free(text);
+
+ return true;
+
+no_memory:
+ free(value);
+ free(text);
+ free(text_nowrap);
+ return false;
+}
+
+
+/**
+ * \name Special case element handlers
+ *
+ * These functions are called by box_construct_element() when an element is
+ * being converted, according to the entries in element_table.
+ *
+ * The parameters are the xmlNode, the content for the document, and a partly
+ * filled in box structure for the element.
+ *
+ * Return true on success, false on memory exhaustion. Set *convert_children
+ * to false if children of this element in the XML tree should be skipped (for
+ * example, if they have been processed in some special way already).
+ *
+ * Elements ordered as in the HTML 4.01 specification. Section numbers in
+ * brackets [] refer to the spec.
+ *
+ * \{
+ */
+
+/**
+ * special element handler for Anchor [12.2].
+ */
+static bool
+box_a(dom_node *n,
+ html_content *content,
+ struct box *box,
+ bool *convert_children)
+{
+ bool ok;
+ nsurl *url;
+ dom_string *s;
+ dom_exception err;
+
+ err = dom_element_get_attribute(n, corestring_dom_href, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ ok = box_extract_link(content, s, content->base_url, &url);
+ dom_string_unref(s);
+ if (!ok)
+ return false;
+ if (url) {
+ if (box->href != NULL)
+ nsurl_unref(box->href);
+ box->href = url;
+ }
+ }
+
+ /* name and id share the same namespace */
+ err = dom_element_get_attribute(n, corestring_dom_name, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ lwc_string *lwc_name;
+
+ err = dom_string_intern(s, &lwc_name);
+
+ dom_string_unref(s);
+
+ if (err == DOM_NO_ERR) {
+ /* name replaces existing id
+ * TODO: really? */
+ if (box->id != NULL)
+ lwc_string_unref(box->id);
+
+ box->id = lwc_name;
+ }
+ }
+
+ /* target frame [16.3] */
+ err = dom_element_get_attribute(n, corestring_dom_target, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ if (dom_string_caseless_lwc_isequal(s,
+ corestring_lwc__blank))
+ box->target = "_blank";
+ else if (dom_string_caseless_lwc_isequal(s,
+ corestring_lwc__top))
+ box->target = "_top";
+ else if (dom_string_caseless_lwc_isequal(s,
+ corestring_lwc__parent))
+ box->target = "_parent";
+ else if (dom_string_caseless_lwc_isequal(s,
+ corestring_lwc__self))
+ /* the default may have been overridden by a
+ * <base target=...>, so this is different to 0 */
+ box->target = "_self";
+ else {
+ /* 6.16 says that frame names must begin with [a-zA-Z]
+ * This doesn't match reality, so just take anything */
+ box->target = talloc_strdup(content->bctx,
+ dom_string_data(s));
+ if (!box->target) {
+ dom_string_unref(s);
+ return false;
+ }
+ }
+ dom_string_unref(s);
+ }
+
+ return true;
+}
+
+
+/**
+ * Document body special element handler [7.5.1].
+ */
+static bool
+box_body(dom_node *n,
+ html_content *content,
+ struct box *box,
+ bool *convert_children)
+{
+ css_color color;
+
+ css_computed_background_color(box->style, &color);
+ if (nscss_color_is_transparent(color)) {
+ content->background_colour = NS_TRANSPARENT;
+ } else {
+ content->background_colour = nscss_color_to_ns(color);
+ }
+
+ return true;
+}
+
+
+/**
+ * special element handler for forced line break [9.3.2].
+ */
+static bool
+box_br(dom_node *n,
+ html_content *content,
+ struct box *box,
+ bool *convert_children)
+{
+ box->type = BOX_BR;
+ return true;
+}
+
+
+/**
+ * special element handler for Push button [17.5].
+ */
+static bool
+box_button(dom_node *n,
+ html_content *content,
+ struct box *box,
+ bool *convert_children)
+{
+ struct form_control *gadget;
+
+ gadget = html_forms_get_control_for_node(content->forms, n);
+ if (!gadget)
+ return false;
+
+ gadget->html = content;
+ box->gadget = gadget;
+ box->flags |= IS_REPLACED;
+ gadget->box = box;
+
+ box->type = BOX_INLINE_BLOCK;
+
+ /* Just render the contents */
+
+ return true;
+}
+
+
+/**
+ * Canvas element
+ */
+static bool
+box_canvas(dom_node *n,
+ html_content *content,
+ struct box *box,
+ bool *convert_children)
+{
+ /* If scripting is not enabled display the contents of canvas */
+ if (!content->enable_scripting) {
+ return true;
+ }
+ *convert_children = false;
+
+ if (box->style && ns_computed_display(box->style,
+ box_is_root(n)) == CSS_DISPLAY_NONE)
+ return true;
+
+ /* This is replaced content */
+ box->flags |= IS_REPLACED | REPLACE_DIM;
+
+ return true;
+}
+
+
+/**
+ * Embedded object (not in any HTML specification:
+ * see http://wp.netscape.com/assist/net_sites/new_html3_prop.html )
+ */
+static bool
+box_embed(dom_node *n,
+ html_content *content,
+ struct box *box,
+ bool *convert_children)
+{
+ struct object_params *params;
+ struct object_param *param;
+ dom_namednodemap *attrs;
+ unsigned long idx;
+ uint32_t num_attrs;
+ dom_string *src;
+ dom_exception err;
+
+ if (box->style && ns_computed_display(box->style,
+ box_is_root(n)) == CSS_DISPLAY_NONE)
+ return true;
+
+ params = talloc(content->bctx, struct object_params);
+ if (params == NULL)
+ return false;
+
+ talloc_set_destructor(params, box_object_talloc_destructor);
+
+ params->data = NULL;
+ params->type = NULL;
+ params->codetype = NULL;
+ params->codebase = NULL;
+ params->classid = NULL;
+ params->params = NULL;
+
+ /* src is a URL */
+ err = dom_element_get_attribute(n, corestring_dom_src, &src);
+ if (err != DOM_NO_ERR || src == NULL)
+ return true;
+ if (box_extract_link(content, src, content->base_url,
+ &params->data) == false) {
+ dom_string_unref(src);
+ return false;
+ }
+
+ dom_string_unref(src);
+
+ if (params->data == NULL)
+ return true;
+
+ /* Don't include ourself */
+ if (nsurl_compare(content->base_url, params->data, NSURL_COMPLETE))
+ return true;
+
+ /* add attributes as parameters to linked list */
+ err = dom_node_get_attributes(n, &attrs);
+ if (err != DOM_NO_ERR)
+ return false;
+
+ err = dom_namednodemap_get_length(attrs, &num_attrs);
+ if (err != DOM_NO_ERR) {
+ dom_namednodemap_unref(attrs);
+ return false;
+ }
+
+ for (idx = 0; idx < num_attrs; idx++) {
+ dom_attr *attr;
+ dom_string *name, *value;
+
+ err = dom_namednodemap_item(attrs, idx, (void *) &attr);
+ if (err != DOM_NO_ERR) {
+ dom_namednodemap_unref(attrs);
+ return false;
+ }
+
+ err = dom_attr_get_name(attr, &name);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(attr);
+ dom_namednodemap_unref(attrs);
+ return false;
+ }
+
+ if (dom_string_caseless_lwc_isequal(name, corestring_lwc_src)) {
+ dom_node_unref(attr);
+ dom_string_unref(name);
+ continue;
+ }
+
+ err = dom_attr_get_value(attr, &value);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(attr);
+ dom_string_unref(name);
+ dom_namednodemap_unref(attrs);
+ return false;
+ }
+
+ param = talloc(content->bctx, struct object_param);
+ if (param == NULL) {
+ dom_node_unref(attr);
+ dom_string_unref(value);
+ dom_string_unref(name);
+ dom_namednodemap_unref(attrs);
+ return false;
+ }
+
+ param->name = talloc_strdup(content->bctx, dom_string_data(name));
+ param->value = talloc_strdup(content->bctx, dom_string_data(value));
+ param->type = NULL;
+ param->valuetype = talloc_strdup(content->bctx, "data");
+ param->next = NULL;
+
+ dom_string_unref(value);
+ dom_string_unref(name);
+ dom_node_unref(attr);
+
+ if (param->name == NULL || param->value == NULL ||
+ param->valuetype == NULL) {
+ dom_namednodemap_unref(attrs);
+ return false;
+ }
+
+ param->next = params->params;
+ params->params = param;
+ }
+
+ dom_namednodemap_unref(attrs);
+
+ box->object_params = params;
+
+ /* start fetch */
+ box->flags |= IS_REPLACED;
+ return html_fetch_object(content, params->data, box, CONTENT_ANY, false);
+}
+
+
+/**
+ * Window subdivision [16.2.1].
+ */
+static bool
+box_frameset(dom_node *n,
+ html_content *content,
+ struct box *box,
+ bool *convert_children)
+{
+ bool ok;
+
+ if (content->frameset) {
+ NSLOG(netsurf, INFO, "Error: multiple framesets in document.");
+ /* Don't convert children */
+ if (convert_children)
+ *convert_children = false;
+ /* And ignore this spurious frameset */
+ box->type = BOX_NONE;
+ return true;
+ }
+
+ content->frameset = talloc_zero(content->bctx,
+ struct content_html_frames);
+ if (!content->frameset) {
+ return false;
+ }
+
+ ok = box_create_frameset(content->frameset, n, content);
+ if (ok) {
+ box->type = BOX_NONE;
+ }
+
+ if (convert_children) {
+ *convert_children = false;
+ }
+ return ok;
+}
+
+
+/**
+ * Inline subwindow [16.5].
+ */
+static bool
+box_iframe(dom_node *n,
+ html_content *content,
+ struct box *box,
+ bool *convert_children)
+{
+ nsurl *url;
+ dom_string *s;
+ dom_exception err;
+ struct content_html_iframe *iframe;
+ int i;
+
+ if (box->style && ns_computed_display(box->style,
+ box_is_root(n)) == CSS_DISPLAY_NONE)
+ return true;
+
+ if (box->style &&
+ css_computed_visibility(box->style) == CSS_VISIBILITY_HIDDEN) {
+ /* Don't create iframe discriptors for invisible iframes
+ * TODO: handle hidden iframes at browser_window generation
+ * time instead? */
+ return true;
+ }
+
+ /* get frame URL */
+ err = dom_element_get_attribute(n, corestring_dom_src, &s);
+ if (err != DOM_NO_ERR || s == NULL)
+ return true;
+ if (box_extract_link(content, s, content->base_url, &url) == false) {
+ dom_string_unref(s);
+ return false;
+ }
+ dom_string_unref(s);
+ if (url == NULL)
+ return true;
+
+ /* don't include ourself */
+ if (nsurl_compare(content->base_url, url, NSURL_COMPLETE)) {
+ nsurl_unref(url);
+ return true;
+ }
+
+ /* create a new iframe */
+ iframe = talloc(content->bctx, struct content_html_iframe);
+ if (iframe == NULL) {
+ nsurl_unref(url);
+ return false;
+ }
+
+ talloc_set_destructor(iframe, box_iframes_talloc_destructor);
+
+ iframe->box = box;
+ iframe->margin_width = 0;
+ iframe->margin_height = 0;
+ iframe->name = NULL;
+ iframe->url = url;
+ iframe->scrolling = BW_SCROLLING_AUTO;
+ iframe->border = true;
+
+ /* Add this iframe to the linked list of iframes */
+ iframe->next = content->iframe;
+ content->iframe = iframe;
+
+ /* fill in specified values */
+ err = dom_element_get_attribute(n, corestring_dom_name, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ iframe->name = talloc_strdup(content->bctx, dom_string_data(s));
+ dom_string_unref(s);
+ }
+
+ err = dom_element_get_attribute(n, corestring_dom_frameborder, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ i = atoi(dom_string_data(s));
+ iframe->border = (i != 0);
+ dom_string_unref(s);
+ }
+
+ err = dom_element_get_attribute(n, corestring_dom_bordercolor, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ css_color color;
+
+ if (nscss_parse_colour(dom_string_data(s), &color))
+ iframe->border_colour = nscss_color_to_ns(color);
+
+ dom_string_unref(s);
+ }
+
+ err = dom_element_get_attribute(n, corestring_dom_scrolling, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ if (dom_string_caseless_lwc_isequal(s,
+ corestring_lwc_yes))
+ iframe->scrolling = BW_SCROLLING_YES;
+ else if (dom_string_caseless_lwc_isequal(s,
+ corestring_lwc_no))
+ iframe->scrolling = BW_SCROLLING_NO;
+ dom_string_unref(s);
+ }
+
+ err = dom_element_get_attribute(n, corestring_dom_marginwidth, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ iframe->margin_width = atoi(dom_string_data(s));
+ dom_string_unref(s);
+ }
+
+ err = dom_element_get_attribute(n, corestring_dom_marginheight, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ iframe->margin_height = atoi(dom_string_data(s));
+ dom_string_unref(s);
+ }
+
+ /* box */
+ assert(box->style);
+ box->flags |= IFRAME;
+ box->flags |= IS_REPLACED;
+
+ /* Showing iframe, so don't show alternate content */
+ if (convert_children)
+ *convert_children = false;
+ return true;
+}
+
+
+/**
+ * Embedded image [13.2].
+ */
+static bool
+box_image(dom_node *n,
+ html_content *content,
+ struct box *box,
+ bool *convert_children)
+{
+ bool ok;
+ dom_string *s;
+ dom_exception err;
+ nsurl *url;
+ enum css_width_e wtype;
+ enum css_height_e htype;
+ css_fixed value = 0;
+ css_unit wunit = CSS_UNIT_PX;
+ css_unit hunit = CSS_UNIT_PX;
+
+ if (box->style && ns_computed_display(box->style,
+ box_is_root(n)) == CSS_DISPLAY_NONE)
+ return true;
+
+ /* handle alt text */
+ err = dom_element_get_attribute(n, corestring_dom_alt, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ char *alt = squash_whitespace(dom_string_data(s));
+ dom_string_unref(s);
+ if (alt == NULL)
+ return false;
+ box->text = talloc_strdup(content->bctx, alt);
+ free(alt);
+ if (box->text == NULL)
+ return false;
+ box->length = strlen(box->text);
+ }
+
+ if (nsoption_bool(foreground_images) == false) {
+ return true;
+ }
+
+ /* imagemap associated with this image */
+ if (!box_get_attribute(n, "usemap", content->bctx, &box->usemap))
+ return false;
+ if (box->usemap && box->usemap[0] == '#')
+ box->usemap++;
+
+ /* get image URL */
+ err = dom_element_get_attribute(n, corestring_dom_src, &s);
+ if (err != DOM_NO_ERR || s == NULL)
+ return true;
+
+ if (box_extract_link(content, s, content->base_url, &url) == false) {
+ dom_string_unref(s);
+ return false;
+ }
+
+ dom_string_unref(s);
+
+ if (url == NULL)
+ return true;
+
+ /* start fetch */
+ box->flags |= IS_REPLACED;
+ ok = html_fetch_object(content, url, box, image_types, false);
+ nsurl_unref(url);
+
+ wtype = css_computed_width(box->style, &value, &wunit);
+ htype = css_computed_height(box->style, &value, &hunit);
+
+ if (wtype == CSS_WIDTH_SET &&
+ wunit != CSS_UNIT_PCT &&
+ htype == CSS_HEIGHT_SET &&
+ hunit != CSS_UNIT_PCT) {
+ /* We know the dimensions the image will be shown at
+ * before it's fetched. */
+ box->flags |= REPLACE_DIM;
+ }
+
+ return ok;
+}
+
+
+/**
+ * Form control [17.4].
+ */
+static bool
+box_input(dom_node *n,
+ html_content *content,
+ struct box *box,
+ bool *convert_children)
+{
+ struct form_control *gadget;
+ dom_string *type = NULL;
+ dom_exception err;
+ nsurl *url;
+ nserror error;
+
+ gadget = html_forms_get_control_for_node(content->forms, n);
+ if (gadget == NULL) {
+ return false;
+ }
+
+ box->gadget = gadget;
+ box->flags |= IS_REPLACED;
+ gadget->box = box;
+ gadget->html = content;
+
+ /* get entry type */
+ err = dom_element_get_attribute(n, corestring_dom_type, &type);
+ if ((err != DOM_NO_ERR) || (type == NULL)) {
+ /* no type so "text" is assumed */
+ if (box_input_text(content, box, n) == false) {
+ return false;
+ }
+ *convert_children = false;
+ return true;
+ }
+
+ if (dom_string_caseless_lwc_isequal(type, corestring_lwc_password)) {
+ if (box_input_text(content, box, n) == false)
+ goto no_memory;
+
+ } else if (dom_string_caseless_lwc_isequal(type, corestring_lwc_file)) {
+ box->type = BOX_INLINE_BLOCK;
+
+ } else if (dom_string_caseless_lwc_isequal(type,
+ corestring_lwc_hidden)) {
+ /* no box for hidden inputs */
+ box->type = BOX_NONE;
+
+ } else if ((dom_string_caseless_lwc_isequal(type,
+ corestring_lwc_checkbox) ||
+ dom_string_caseless_lwc_isequal(type,
+ corestring_lwc_radio))) {
+
+ } else if (dom_string_caseless_lwc_isequal(type,
+ corestring_lwc_submit) ||
+ dom_string_caseless_lwc_isequal(type,
+ corestring_lwc_reset) ||
+ dom_string_caseless_lwc_isequal(type,
+ corestring_lwc_button)) {
+ struct box *inline_container, *inline_box;
+
+ if (box_button(n, content, box, 0) == false)
+ goto no_memory;
+
+ inline_container = box_create(NULL, 0, false, 0, 0, 0, 0,
+ content->bctx);
+ if (inline_container == NULL)
+ goto no_memory;
+
+ inline_container->type = BOX_INLINE_CONTAINER;
+
+ inline_box = box_create(NULL, box->style, false, 0, 0,
+ box->title, 0, content->bctx);
+ if (inline_box == NULL)
+ goto no_memory;
+
+ inline_box->type = BOX_TEXT;
+
+ if (box->gadget->value != NULL)
+ inline_box->text = talloc_strdup(content->bctx,
+ box->gadget->value);
+ else if (box->gadget->type == GADGET_SUBMIT)
+ inline_box->text = talloc_strdup(content->bctx,
+ messages_get("Form_Submit"));
+ else if (box->gadget->type == GADGET_RESET)
+ inline_box->text = talloc_strdup(content->bctx,
+ messages_get("Form_Reset"));
+ else
+ inline_box->text = talloc_strdup(content->bctx,
+ "Button");
+
+ if (inline_box->text == NULL)
+ goto no_memory;
+
+ inline_box->length = strlen(inline_box->text);
+
+ box_add_child(inline_container, inline_box);
+
+ box_add_child(box, inline_container);
+
+ } else if (dom_string_caseless_lwc_isequal(type,
+ corestring_lwc_image)) {
+ gadget->type = GADGET_IMAGE;
+
+ if (box->style && ns_computed_display(box->style,
+ box_is_root(n)) != CSS_DISPLAY_NONE &&
+ nsoption_bool(foreground_images) == true) {
+ dom_string *s;
+
+ err = dom_element_get_attribute(n, corestring_dom_src, &s);
+ if (err == DOM_NO_ERR && s != NULL) {
+ error = nsurl_join(content->base_url,
+ dom_string_data(s), &url);
+ dom_string_unref(s);
+ if (error != NSERROR_OK)
+ goto no_memory;
+
+ /* if url is equivalent to the parent's url,
+ * we've got infinite inclusion. stop it here
+ */
+ if (nsurl_compare(url, content->base_url,
+ NSURL_COMPLETE) == false) {
+ if (!html_fetch_object(content,
+ url,
+ box,
+ image_types,
+ false)) {
+ nsurl_unref(url);
+ goto no_memory;
+ }
+ }
+ nsurl_unref(url);
+ }
+ }
+ } else {
+ /* unhandled type the default is "text" */
+ if (box_input_text(content, box, n) == false)
+ goto no_memory;
+ }
+
+ dom_string_unref(type);
+
+ *convert_children = false;
+
+ return true;
+
+no_memory:
+ dom_string_unref(type);
+
+ return false;
+}
+
+
+/**
+ * Noscript element
+ */
+static bool
+box_noscript(dom_node *n,
+ html_content *content,
+ struct box *box,
+ bool *convert_children)
+{
+ /* If scripting is enabled, do not display the contents of noscript */
+ if (content->enable_scripting) {
+ *convert_children = false;
+ }
+
+ return true;
+}
+
+
+/**
+ * Generic embedded object [13.3].
+ */
+static bool
+box_object(dom_node *n,
+ html_content *content,
+ struct box *box,
+ bool *convert_children)
+{
+ struct object_params *params;
+ struct object_param *param;
+ dom_string *codebase, *classid, *data;
+ dom_node *c;
+ dom_exception err;
+
+ if (box->style && ns_computed_display(box->style,
+ box_is_root(n)) == CSS_DISPLAY_NONE)
+ return true;
+
+ if (box_get_attribute(n, "usemap", content->bctx, &box->usemap) ==
+ false)
+ return false;
+ if (box->usemap && box->usemap[0] == '#')
+ box->usemap++;
+
+ params = talloc(content->bctx, struct object_params);
+ if (params == NULL)
+ return false;
+
+ talloc_set_destructor(params, box_object_talloc_destructor);
+
+ params->data = NULL;
+ params->type = NULL;
+ params->codetype = NULL;
+ params->codebase = NULL;
+ params->classid = NULL;
+ params->params = NULL;
+
+ /* codebase, classid, and data are URLs
+ * (codebase is the base for the other two) */
+ err = dom_element_get_attribute(n, corestring_dom_codebase, &codebase);
+ if (err == DOM_NO_ERR && codebase != NULL) {
+ if (box_extract_link(content, codebase, content->base_url,
+ &params->codebase) == false) {
+ dom_string_unref(codebase);
+ return false;
+ }
+ dom_string_unref(codebase);
+ }
+ if (params->codebase == NULL)
+ params->codebase = nsurl_ref(content->base_url);
+
+ err = dom_element_get_attribute(n, corestring_dom_classid, &classid);
+ if (err == DOM_NO_ERR && classid != NULL) {
+ if (box_extract_link(content, classid,
+ params->codebase, &params->classid) == false) {
+ dom_string_unref(classid);
+ return false;
+ }
+ dom_string_unref(classid);
+ }
+
+ err = dom_element_get_attribute(n, corestring_dom_data, &data);
+ if (err == DOM_NO_ERR && data != NULL) {
+ if (box_extract_link(content, data,
+ params->codebase, &params->data) == false) {
+ dom_string_unref(data);
+ return false;
+ }
+ dom_string_unref(data);
+ }
+
+ if (params->classid == NULL && params->data == NULL)
+ /* nothing to embed; ignore */
+ return true;
+
+ /* Don't include ourself */
+ if (params->classid != NULL && nsurl_compare(content->base_url,
+ params->classid, NSURL_COMPLETE))
+ return true;
+
+ if (params->data != NULL && nsurl_compare(content->base_url,
+ params->data, NSURL_COMPLETE))
+ return true;
+
+ /* codetype and type are MIME types */
+ if (box_get_attribute(n, "codetype", params,
+ &params->codetype) == false)
+ return false;
+ if (box_get_attribute(n, "type", params, &params->type) == false)
+ return false;
+
+ /* classid && !data => classid is used (consult codetype)
+ * (classid || !classid) && data => data is used (consult type)
+ * !classid && !data => invalid; ignored */
+
+ if (params->classid != NULL && params->data == NULL &&
+ params->codetype != NULL) {
+ lwc_string *icodetype;
+ lwc_error lerror;
+
+ lerror = lwc_intern_string(params->codetype,
+ strlen(params->codetype), &icodetype);
+ if (lerror != lwc_error_ok)
+ return false;
+
+ if (content_factory_type_from_mime_type(icodetype) ==
+ CONTENT_NONE) {
+ /* can't handle this MIME type */
+ lwc_string_unref(icodetype);
+ return true;
+ }
+
+ lwc_string_unref(icodetype);
+ }
+
+ if (params->data != NULL && params->type != NULL) {
+ lwc_string *itype;
+ lwc_error lerror;
+
+ lerror = lwc_intern_string(params->type, strlen(params->type),
+ &itype);
+ if (lerror != lwc_error_ok)
+ return false;
+
+ if (content_factory_type_from_mime_type(itype) ==
+ CONTENT_NONE) {
+ /* can't handle this MIME type */
+ lwc_string_unref(itype);
+ return true;
+ }
+
+ lwc_string_unref(itype);
+ }
+
+ /* add parameters to linked list */
+ err = dom_node_get_first_child(n, &c);
+ if (err != DOM_NO_ERR)
+ return false;
+
+ while (c != NULL) {
+ dom_node *next;
+ dom_node_type type;
+
+ err = dom_node_get_node_type(c, &type);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(c);
+ return false;
+ }
+
+ if (type == DOM_ELEMENT_NODE) {
+ dom_string *name;
+
+ err = dom_node_get_node_name(c, &name);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(c);
+ return false;
+ }
+
+ if (!dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_param)) {
+ /* The first non-param child is the start of
+ * the alt html. Therefore, we should break
+ * out of this loop. */
+ dom_string_unref(name);
+ dom_node_unref(c);
+ break;
+ }
+ dom_string_unref(name);
+
+ param = talloc(params, struct object_param);
+ if (param == NULL) {
+ dom_node_unref(c);
+ return false;
+ }
+ param->name = NULL;
+ param->value = NULL;
+ param->type = NULL;
+ param->valuetype = NULL;
+ param->next = NULL;
+
+ if (box_get_attribute(c, "name", param,
+ &param->name) == false) {
+ dom_node_unref(c);
+ return false;
+ }
+
+ if (box_get_attribute(c, "value", param,
+ &param->value) == false) {
+ dom_node_unref(c);
+ return false;
+ }
+
+ if (box_get_attribute(c, "type", param,
+ &param->type) == false) {
+ dom_node_unref(c);
+ return false;
+ }
+
+ if (box_get_attribute(c, "valuetype", param,
+ &param->valuetype) == false) {
+ dom_node_unref(c);
+ return false;
+ }
+
+ if (param->valuetype == NULL) {
+ param->valuetype = talloc_strdup(param, "data");
+ if (param->valuetype == NULL) {
+ dom_node_unref(c);
+ return false;
+ }
+ }
+
+ param->next = params->params;
+ params->params = param;
+ }
+
+ err = dom_node_get_next_sibling(c, &next);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(c);
+ return false;
+ }
+
+ dom_node_unref(c);
+ c = next;
+ }
+
+ box->object_params = params;
+
+ /* start fetch (MIME type is ok or not specified) */
+ box->flags |= IS_REPLACED;
+ if (!html_fetch_object(content,
+ params->data ? params->data : params->classid,
+ box,
+ CONTENT_ANY,
+ false))
+ return false;
+
+ *convert_children = false;
+ return true;
+}
+
+
+/**
+ * Preformatted text [9.3.4].
+ */
+static bool
+box_pre(dom_node *n,
+ html_content *content,
+ struct box *box,
+ bool *convert_children)
+{
+ box->flags |= PRE_STRIP;
+ return true;
+}
+
+
+/**
+ * Option selector [17.6].
+ */
+static bool
+box_select(dom_node *n,
+ html_content *content,
+ struct box *box,
+ bool *convert_children)
+{
+ struct box *inline_container;
+ struct box *inline_box;
+ struct form_control *gadget;
+ dom_node *c, *c2;
+ dom_node *next, *next2;
+ dom_exception err;
+
+ gadget = html_forms_get_control_for_node(content->forms, n);
+ if (gadget == NULL)
+ return false;
+
+ gadget->html = content;
+ err = dom_node_get_first_child(n, &c);
+ if (err != DOM_NO_ERR) {
+ form_free_control(gadget);
+ return false;
+ }
+
+ while (c != NULL) {
+ dom_string *name;
+
+ err = dom_node_get_node_name(c, &name);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(c);
+ form_free_control(gadget);
+ return false;
+ }
+
+ if (dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_option)) {
+ dom_string_unref(name);
+
+ if (box_select_add_option(gadget, c) == false) {
+ dom_node_unref(c);
+ form_free_control(gadget);
+ return false;
+ }
+ } else if (dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_optgroup)) {
+ dom_string_unref(name);
+
+ err = dom_node_get_first_child(c, &c2);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(c);
+ form_free_control(gadget);
+ return false;
+ }
+
+ while (c2 != NULL) {
+ dom_string *c2_name;
+
+ err = dom_node_get_node_name(c2, &c2_name);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(c2);
+ dom_node_unref(c);
+ form_free_control(gadget);
+ return false;
+ }
+
+ if (dom_string_caseless_lwc_isequal(c2_name,
+ corestring_lwc_option)) {
+ dom_string_unref(c2_name);
+
+ if (box_select_add_option(gadget,
+ c2) == false) {
+ dom_node_unref(c2);
+ dom_node_unref(c);
+ form_free_control(gadget);
+ return false;
+ }
+ } else {
+ dom_string_unref(c2_name);
+ }
+
+ err = dom_node_get_next_sibling(c2, &next2);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(c2);
+ dom_node_unref(c);
+ form_free_control(gadget);
+ return false;
+ }
+
+ dom_node_unref(c2);
+ c2 = next2;
+ }
+ } else {
+ dom_string_unref(name);
+ }
+
+ err = dom_node_get_next_sibling(c, &next);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(c);
+ form_free_control(gadget);
+ return false;
+ }
+
+ dom_node_unref(c);
+ c = next;
+ }
+
+ if (gadget->data.select.num_items == 0) {
+ /* no options: ignore entire select */
+ form_free_control(gadget);
+ return true;
+ }
+
+ box->type = BOX_INLINE_BLOCK;
+ box->gadget = gadget;
+ box->flags |= IS_REPLACED;
+ gadget->box = box;
+
+ inline_container = box_create(NULL, 0, false, 0, 0, 0, 0, content->bctx);
+ if (inline_container == NULL)
+ goto no_memory;
+ inline_container->type = BOX_INLINE_CONTAINER;
+ inline_box = box_create(NULL, box->style, false, 0, 0, box->title, 0,
+ content->bctx);
+ if (inline_box == NULL)
+ goto no_memory;
+ inline_box->type = BOX_TEXT;
+ box_add_child(inline_container, inline_box);
+ box_add_child(box, inline_container);
+
+ if (gadget->data.select.multiple == false &&
+ gadget->data.select.num_selected == 0) {
+ gadget->data.select.current = gadget->data.select.items;
+ gadget->data.select.current->initial_selected =
+ gadget->data.select.current->selected = true;
+ gadget->data.select.num_selected = 1;
+ dom_html_option_element_set_selected(
+ gadget->data.select.current->node, true);
+ }
+
+ if (gadget->data.select.num_selected == 0)
+ inline_box->text = talloc_strdup(content->bctx,
+ messages_get("Form_None"));
+ else if (gadget->data.select.num_selected == 1)
+ inline_box->text = talloc_strdup(content->bctx,
+ gadget->data.select.current->text);
+ else
+ inline_box->text = talloc_strdup(content->bctx,
+ messages_get("Form_Many"));
+ if (inline_box->text == NULL)
+ goto no_memory;
+
+ inline_box->length = strlen(inline_box->text);
+
+ *convert_children = false;
+ return true;
+
+no_memory:
+ return false;
+}
+
+
+/**
+ * Multi-line text field [17.7].
+ */
+static bool box_textarea(dom_node *n,
+ html_content *content,
+ struct box *box,
+ bool *convert_children)
+{
+ /* Get the form_control for the DOM node */
+ box->gadget = html_forms_get_control_for_node(content->forms, n);
+ if (box->gadget == NULL)
+ return false;
+
+ box->flags |= IS_REPLACED;
+ box->gadget->html = content;
+ box->gadget->box = box;
+
+ if (!box_input_text(content, box, n))
+ return false;
+
+ *convert_children = false;
+ return true;
+}
+
+
+/**
+ * \}
+ */
+
+
+/* exported interface documented in html/box_special.h */
+bool
+convert_special_elements(dom_node *node,
+ html_content *content,
+ struct box *box,
+ bool *convert_children)
+{
+ dom_exception exc;
+ dom_html_element_type tag_type;
+ bool res;
+
+ exc = dom_html_element_get_tag_type(node, &tag_type);
+ if (exc != DOM_NO_ERR) {
+ tag_type = DOM_HTML_ELEMENT_TYPE__UNKNOWN;
+ }
+
+ switch (tag_type) {
+ case DOM_HTML_ELEMENT_TYPE_A:
+ res = box_a(node, content, box, convert_children);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_BODY:
+ res = box_body(node, content, box, convert_children);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_BR:
+ res = box_br(node, content, box, convert_children);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_BUTTON:
+ res = box_button(node, content, box, convert_children);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_CANVAS:
+ res = box_canvas(node, content, box, convert_children);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_EMBED:
+ res = box_embed(node, content, box, convert_children);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_FRAMESET:
+ res = box_frameset(node, content, box, convert_children);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_IFRAME:
+ res = box_iframe(node, content, box, convert_children);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_IMG:
+ res = box_image(node, content, box, convert_children);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_INPUT:
+ res = box_input(node, content, box, convert_children);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_NOSCRIPT:
+ res = box_noscript(node, content, box, convert_children);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_OBJECT:
+ res = box_object(node, content, box, convert_children);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_PRE:
+ res = box_pre(node, content, box, convert_children);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_SELECT:
+ res = box_select(node, content, box, convert_children);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_TEXTAREA:
+ res = box_textarea(node, content, box, convert_children);
+ break;
+
+ default:
+ res = true;
+ }
+
+ return res;
+}
diff --git a/render/table.h b/content/handlers/html/box_special.h
index 2eeffe699..973ab976a 100644
--- a/render/table.h
+++ b/content/handlers/html/box_special.h
@@ -1,6 +1,5 @@
/*
- * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
- * Copyright 2005 Richard Wilson <info@tinct.net>
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -17,22 +16,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Table processing and layout (interface).
+/**
+ * \file
+ * HTML Box tree construction special element conversion interface.
*/
-#ifndef _NETSURF_RENDER_TABLE_H_
-#define _NETSURF_RENDER_TABLE_H_
+#ifndef NETSURF_HTML_BOX_SPECIAL_H
+#define NETSURF_HTML_BOX_SPECIAL_H
-#include <stdbool.h>
-struct box;
-
-bool table_calculate_column_types(
- const nscss_len_ctx *len_ctx,
- struct box *table);
-void table_used_border_for_cell(
- const nscss_len_ctx *len_ctx,
- struct box *cell);
+/**
+ * call an elements special conversion handler
+ *
+ * \return true if box construction should continue else false on error.
+ */
+bool convert_special_elements(dom_node *node, html_content *content, struct box *box, bool *convert_children);
#endif
diff --git a/render/box_textarea.c b/content/handlers/html/box_textarea.c
index a60984235..d08660030 100644
--- a/render/box_textarea.c
+++ b/content/handlers/html/box_textarea.c
@@ -16,89 +16,111 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Box tree treeview box replacement (implementation).
*/
+#include <string.h>
#include <dom/dom.h>
#include "utils/config.h"
#include "utils/log.h"
+#include "utils/messages.h"
#include "netsurf/keypress.h"
+#include "netsurf/misc.h"
#include "desktop/textarea.h"
-#include "render/box_textarea.h"
-#include "render/font.h"
-#include "render/form_internal.h"
+#include "html/private.h"
+#include "html/interaction.h"
+#include "html/box.h"
+#include "html/box_inspect.h"
+#include "html/box_textarea.h"
+#include "html/font.h"
+#include "html/form_internal.h"
-bool box_textarea_keypress(html_content *html, struct box *box, uint32_t key)
+nserror box_textarea_keypress(html_content *html, struct box *box, uint32_t key)
{
struct form_control *gadget = box->gadget;
struct textarea *ta = gadget->data.text.ta;
struct form* form = box->gadget->form;
- struct content *c = (struct content *) html;
+ struct content *c = (struct content *)html;
+ nserror res = NSERROR_OK;
assert(ta != NULL);
- if (gadget->type != GADGET_TEXTAREA) {
- switch (key) {
- case NS_KEY_NL:
- case NS_KEY_CR:
- if (form)
- form_submit(content_get_url(c), html->bw,
- form, 0);
- return true;
+ if (gadget->type == GADGET_TEXTAREA) {
+ if (textarea_keypress(ta, key)) {
+ return NSERROR_OK;
+ } else {
+ return NSERROR_INVALID;
+ }
+ }
+
+ /* non textarea input */
+ switch (key) {
+ case NS_KEY_NL:
+ case NS_KEY_CR:
+ if (form) {
+ res = form_submit(content_get_url(c),
+ html->bw,
+ form,
+ NULL);
+ }
+ break;
- case NS_KEY_TAB:
+ case NS_KEY_TAB:
{
struct form_control *next_input;
/* Find next text entry field that is actually
* displayed (i.e. has an associated box) */
for (next_input = gadget->next;
- next_input &&
- ((next_input->type != GADGET_TEXTBOX &&
- next_input->type != GADGET_TEXTAREA &&
- next_input->type != GADGET_PASSWORD) ||
- !next_input->box);
- next_input = next_input->next)
+ next_input &&
+ ((next_input->type != GADGET_TEXTBOX &&
+ next_input->type != GADGET_TEXTAREA &&
+ next_input->type != GADGET_PASSWORD) ||
+ !next_input->box);
+ next_input = next_input->next)
;
- if (!next_input)
- return true;
- textarea_set_caret(ta, -1);
- textarea_set_caret(next_input->data.text.ta, 0);
+ if (next_input != NULL) {
+ textarea_set_caret(ta, -1);
+ textarea_set_caret(next_input->data.text.ta, 0);
+ }
}
- return true;
+ break;
- case NS_KEY_SHIFT_TAB:
+ case NS_KEY_SHIFT_TAB:
{
struct form_control *prev_input;
/* Find previous text entry field that is actually
* displayed (i.e. has an associated box) */
for (prev_input = gadget->prev;
- prev_input &&
- ((prev_input->type != GADGET_TEXTBOX &&
- prev_input->type != GADGET_TEXTAREA &&
- prev_input->type != GADGET_PASSWORD) ||
- !prev_input->box);
- prev_input = prev_input->prev)
+ prev_input &&
+ ((prev_input->type != GADGET_TEXTBOX &&
+ prev_input->type != GADGET_TEXTAREA &&
+ prev_input->type != GADGET_PASSWORD) ||
+ !prev_input->box);
+ prev_input = prev_input->prev)
;
- if (!prev_input)
- return true;
- textarea_set_caret(ta, -1);
- textarea_set_caret(prev_input->data.text.ta, 0);
+ if (prev_input != NULL) {
+ textarea_set_caret(ta, -1);
+ textarea_set_caret(prev_input->data.text.ta, 0);
+ }
}
- return true;
+ break;
- default:
- /* Pass to textarea widget */
- break;
+ default:
+ /* Pass to textarea widget */
+ if (!textarea_keypress(ta, key)) {
+ res = NSERROR_INVALID;
}
+ break;
}
- return textarea_keypress(ta, key);
+ return res;
}
@@ -241,7 +263,7 @@ bool box_textarea_create_textarea(html_content *html,
textarea_flags ta_flags;
plot_font_style_t fstyle = {
.family = PLOT_FONT_FAMILY_SANS_SERIF,
- .size = 10 * FONT_SIZE_SCALE,
+ .size = 10 * PLOT_STYLE_SCALE,
.weight = 400,
.flags = FONTF_NONE,
.background = 0,
@@ -347,4 +369,3 @@ bool box_textarea_create_textarea(html_content *html,
return true;
}
-
diff --git a/render/box_textarea.h b/content/handlers/html/box_textarea.h
index a7a377076..219ef2301 100644
--- a/render/box_textarea.h
+++ b/content/handlers/html/box_textarea.h
@@ -16,20 +16,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Box tree treeview box replacement (interface).
*/
-
-
-#ifndef _NETSURF_RENDER_BOX_TEXTAREA_H_
-#define _NETSURF_RENDER_BOX_TEXTAREA_H_
-
-
-#include "render/box.h"
-#include "render/html_internal.h"
+#ifndef NETSURF_HTML_BOX_TEXTAREA_H
+#define NETSURF_HTML_BOX_TEXTAREA_H
struct dom_node;
+struct html_content;
+struct box;
/**
* Create textarea widget for a form element
@@ -38,7 +35,7 @@ struct dom_node;
* \param box box with gadget to be given textarea widget
* \param node DOM node for form element
*/
-bool box_textarea_create_textarea(html_content *html,
+bool box_textarea_create_textarea(struct html_content *html,
struct box *box, struct dom_node *node);
@@ -48,8 +45,8 @@ bool box_textarea_create_textarea(html_content *html,
* \param html html content object
* \param box box with textarea widget
* \param key keypress
- * \return true iff keypress handled
+ * \return NSERROR_OK iff keypress handled
*/
-bool box_textarea_keypress(html_content *html, struct box *box, uint32_t key);
+nserror box_textarea_keypress(struct html_content *html, struct box *box, uint32_t key);
#endif
diff --git a/render/html_css.c b/content/handlers/html/css.c
index 45bc16f56..0bc38844f 100644
--- a/render/html_css.c
+++ b/content/handlers/html/css.c
@@ -16,10 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Processing for html content css operations.
*/
+#include "utils/config.h"
+
#include <assert.h>
#include <ctype.h>
#include <stdint.h>
@@ -29,21 +32,26 @@
#include "utils/nsoption.h"
#include "utils/corestrings.h"
-#include "utils/config.h"
#include "utils/log.h"
+#include "netsurf/inttypes.h"
#include "netsurf/misc.h"
#include "netsurf/content.h"
#include "content/hlcache.h"
#include "css/css.h"
#include "desktop/gui_internal.h"
-#include "render/html_internal.h"
+#include "html/html.h"
+#include "html/private.h"
+#include "html/css.h"
static nsurl *html_default_stylesheet_url;
static nsurl *html_adblock_stylesheet_url;
static nsurl *html_quirks_stylesheet_url;
static nsurl *html_user_stylesheet_url;
+/**
+ * Convert css error to netsurf error.
+ */
static nserror css_error_to_nserror(css_error error)
{
switch (error) {
@@ -77,10 +85,10 @@ static nserror css_error_to_nserror(css_error error)
return NSERROR_CSS;
}
+
/**
* Callback for fetchcache() for stylesheets.
*/
-
static nserror
html_convert_css_callback(hlcache_handle *css,
const hlcache_event *event,
@@ -112,15 +120,12 @@ html_convert_css_callback(hlcache_handle *css,
case CONTENT_MSG_ERROR:
NSLOG(netsurf, INFO, "stylesheet %s failed: %s",
nsurl_access(hlcache_handle_get_url(css)),
- event->data.error);
- /* fall through */
+ event->data.errordata.errormsg);
- case CONTENT_MSG_ERRORCODE:
hlcache_handle_release(css);
s->sheet = NULL;
parent->base.active--;
NSLOG(netsurf, INFO, "%d fetches active", parent->base.active);
- content_add_error(&parent->base, "?", 0);
break;
case CONTENT_MSG_POINTER:
@@ -138,6 +143,7 @@ html_convert_css_callback(hlcache_handle *css,
return NSERROR_OK;
}
+
static nserror
html_stylesheet_from_domnode(html_content *c,
dom_node *node,
@@ -168,7 +174,7 @@ html_stylesheet_from_domnode(html_content *c,
dom_string_unref(style);
- snprintf(urlbuf, sizeof(urlbuf), "x-ns-css:%u", key);
+ snprintf(urlbuf, sizeof(urlbuf), "x-ns-css:%"PRIu32"", key);
error = nsurl_create(urlbuf, &url);
if (error != NSERROR_OK) {
@@ -192,6 +198,7 @@ html_stylesheet_from_domnode(html_content *c,
return NSERROR_OK;
}
+
/**
* Process an inline stylesheet in the document.
*
@@ -199,7 +206,6 @@ html_stylesheet_from_domnode(html_content *c,
* \param style xml node of style element
* \return true on success, false if an error occurred
*/
-
static struct html_stylesheet *
html_create_style_element(html_content *c, dom_node *style)
{
@@ -236,7 +242,7 @@ html_create_style_element(html_content *c, dom_node *style)
(c->stylesheet_count + 1));
if (stylesheets == NULL) {
- content_broadcast_errorcode(&c->base, NSERROR_NOMEM);
+ content_broadcast_error(&c->base, NSERROR_NOMEM, NULL);
return false;
}
@@ -251,8 +257,9 @@ html_create_style_element(html_content *c, dom_node *style)
return c->stylesheets + (c->stylesheet_count - 1);
}
-static bool html_css_process_modified_style(html_content *c,
- struct html_stylesheet *s)
+
+static bool
+html_css_process_modified_style(html_content *c, struct html_stylesheet *s)
{
hlcache_handle *sheet = NULL;
nserror error;
@@ -260,7 +267,7 @@ static bool html_css_process_modified_style(html_content *c,
error = html_stylesheet_from_domnode(c, s->node, &sheet);
if (error != NSERROR_OK) {
NSLOG(netsurf, INFO, "Failed to update sheet");
- content_broadcast_errorcode(&c->base, error);
+ content_broadcast_error(&c->base, error, NULL);
return false;
}
@@ -288,6 +295,10 @@ static bool html_css_process_modified_style(html_content *c,
return true;
}
+
+/**
+ * process a stylesheet that has been modified.
+ */
static void html_css_process_modified_styles(void *pw)
{
html_content *c = pw;
@@ -307,6 +318,8 @@ static void html_css_process_modified_styles(void *pw)
}
}
+
+/* exported function documented in html/css.h */
bool html_css_update_style(html_content *c, dom_node *style)
{
unsigned int i;
@@ -334,6 +347,8 @@ bool html_css_update_style(html_content *c, dom_node *style)
return true;
}
+
+/* exported function documented in html/css.h */
bool html_css_process_style(html_content *c, dom_node *node)
{
unsigned int i;
@@ -365,6 +380,8 @@ bool html_css_process_style(html_content *c, dom_node *node)
return true;
}
+
+/* exported function documented in html/css.h */
bool html_css_process_link(html_content *htmlc, dom_node *node)
{
dom_string *rel, *type_attr, *media, *href;
@@ -379,16 +396,20 @@ bool html_css_process_link(html_content *htmlc, dom_node *node)
if (exc != DOM_NO_ERR || rel == NULL)
return true;
- if (strcasestr(dom_string_data(rel), "stylesheet") == 0) {
+ if (strcasestr(dom_string_data(rel), "stylesheet") == NULL) {
dom_string_unref(rel);
return true;
- } else if (strcasestr(dom_string_data(rel), "alternate") != 0) {
+ } else if (strcasestr(dom_string_data(rel), "alternate") != NULL) {
/* Ignore alternate stylesheets */
dom_string_unref(rel);
return true;
}
dom_string_unref(rel);
+ if (nsoption_bool(author_level_css) == false) {
+ return true;
+ }
+
/* type='text/css' or not present */
exc = dom_element_get_attribute(node, corestring_dom_type, &type_attr);
if (exc == DOM_NO_ERR && type_attr != NULL) {
@@ -468,11 +489,12 @@ bool html_css_process_link(html_content *htmlc, dom_node *node)
return true;
no_memory:
- content_broadcast_errorcode(&htmlc->base, ns_error);
+ content_broadcast_error(&htmlc->base, ns_error, NULL);
return false;
}
-/* exported interface documented in render/html.h */
+
+/* exported interface documented in html/html.h */
struct html_stylesheet *html_get_stylesheets(hlcache_handle *h, unsigned int *n)
{
html_content *c = (html_content *) hlcache_handle_get_content(h);
@@ -486,7 +508,26 @@ struct html_stylesheet *html_get_stylesheets(hlcache_handle *h, unsigned int *n)
}
-/* exported interface documented in render/html_internal.h */
+/* exported function documented in html/css.h */
+bool html_css_saw_insecure_stylesheets(html_content *html)
+{
+ struct html_stylesheet *s;
+ unsigned int i;
+
+ for (i = 0, s = html->stylesheets; i < html->stylesheet_count;
+ i++, s++) {
+ if (s->sheet != NULL) {
+ if (content_saw_insecure_objects(s->sheet)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+/* exported function documented in html/css.h */
nserror html_css_free_stylesheets(html_content *html)
{
unsigned int i;
@@ -506,7 +547,8 @@ nserror html_css_free_stylesheets(html_content *html)
return NSERROR_OK;
}
-/* exported interface documented in render/html_internal.h */
+
+/* exported function documented in html/css.h */
nserror html_css_quirks_stylesheets(html_content *c)
{
nserror ns_error = NSERROR_OK;
@@ -534,7 +576,8 @@ nserror html_css_quirks_stylesheets(html_content *c)
return ns_error;
}
-/* exported interface documented in render/html_internal.h */
+
+/* exported function documented in html/css.h */
nserror html_css_new_stylesheets(html_content *c)
{
nserror ns_error;
@@ -604,6 +647,8 @@ nserror html_css_new_stylesheets(html_content *c)
return ns_error;
}
+
+/* exported function documented in html/css.h */
nserror
html_css_new_selection_context(html_content *c, css_select_ctx **ret_select_ctx)
{
@@ -629,6 +674,9 @@ html_css_new_selection_context(html_content *c, css_select_ctx **ret_select_ctx)
css_origin origin = CSS_ORIGIN_AUTHOR;
/* Filter out stylesheets for non-screen media. */
+ /* TODO: We should probably pass the sheet in anyway, and let
+ * libcss handle the filtering.
+ */
if (hsheet->unused) {
continue;
}
@@ -644,10 +692,13 @@ html_css_new_selection_context(html_content *c, css_select_ctx **ret_select_ctx)
}
if (sheet != NULL) {
+ /* TODO: Pass the sheet's full media query, instead of
+ * "screen".
+ */
css_ret = css_select_ctx_append_sheet(select_ctx,
sheet,
origin,
- CSS_MEDIA_SCREEN);
+ "screen");
if (css_ret != CSS_OK) {
css_select_ctx_destroy(select_ctx);
return css_error_to_nserror(css_ret);
@@ -660,6 +711,8 @@ html_css_new_selection_context(html_content *c, css_select_ctx **ret_select_ctx)
return NSERROR_OK;
}
+
+/* exported function documented in html/css.h */
nserror html_css_init(void)
{
nserror error;
@@ -689,6 +742,8 @@ nserror html_css_init(void)
return error;
}
+
+/* exported function documented in html/css.h */
void html_css_fini(void)
{
if (html_user_stylesheet_url != NULL) {
diff --git a/content/handlers/html/css.h b/content/handlers/html/css.h
new file mode 100644
index 000000000..35f6a61e9
--- /dev/null
+++ b/content/handlers/html/css.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * HTML content handler CSS interface.
+ */
+
+#ifndef NETSURF_HTML_CSS_H
+#define NETSURF_HTML_CSS_H
+
+/**
+ * Initialise html content css handling.
+ *
+ * \return NSERROR_OK on success else error code
+ */
+nserror html_css_init(void);
+
+/**
+ * Finalise html content css handling.
+ */
+void html_css_fini(void);
+
+/**
+ * create a new css selection context for an html content.
+ *
+ * \param c The html content to create css selction on.
+ * \param select_ctx A pointer to receive the new context.
+ * \return NSERROR_OK on success and \a select_ctx updated else error code
+ */
+nserror html_css_new_selection_context(struct html_content *c, css_select_ctx **select_ctx);
+
+/**
+ * Initialise core stylesheets for a content
+ *
+ * \param c content structure to update
+ * \return NSERROR_OK on success or error code
+ */
+nserror html_css_new_stylesheets(struct html_content *c);
+
+/**
+ * Initialise quirk stylesheets for a content
+ *
+ * \param c content structure to update
+ * \return NSERROR_OK on success or error code
+ */
+nserror html_css_quirks_stylesheets(struct html_content *c);
+
+/**
+ * Free all css stylesheets associated with an HTML content.
+ *
+ * \param html The HTML content to free stylesheets from.
+ * \return NSERROR_OK on success or error code.
+ */
+nserror html_css_free_stylesheets(struct html_content *html);
+
+/**
+ * determine if any of the stylesheets were loaded insecurely
+ *
+ * \param htmlc The HTML content to check.
+ * \return true if there were insecurely loadd stylesheets else false.
+ */
+bool html_css_saw_insecure_stylesheets(struct html_content *htmlc);
+
+/**
+ * process a css stylesheet dom LINK node
+ *
+ * \param htmlc The HTML content.
+ * \param node the DOM link node to process.
+ * \return true on success else false.
+ */
+bool html_css_process_link(struct html_content *htmlc, dom_node *node);
+
+/**
+ * process a css style dom node
+ *
+ * \param htmlc The HTML content.
+ * \param node the DOM node to process.
+ * \return true on success else false.
+ */
+bool html_css_process_style(struct html_content *htmlc, dom_node *node);
+
+/**
+ * process a css style dom node update
+ *
+ * \param htmlc The HTML content.
+ * \param node the DOM node to process.
+ * \return true on success else false.
+ */
+bool html_css_update_style(struct html_content *htmlc, dom_node *node);
+
+
+
+#endif
diff --git a/render/html_css_fetcher.c b/content/handlers/html/css_fetcher.c
index 0f8809a42..4e0f672e9 100644
--- a/render/html_css_fetcher.c
+++ b/content/handlers/html/css_fetcher.c
@@ -17,6 +17,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+/**
+ * \file
+ * HTML fetcher for CSS objects
+ */
+
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
@@ -26,6 +31,7 @@
#include "netsurf/inttypes.h"
#include "utils/config.h"
+#include "utils/corestrings.h"
#include "utils/log.h"
#include "utils/ring.h"
#include "utils/nsurl.h"
@@ -33,7 +39,7 @@
#include "content/fetch.h"
#include "content/fetchers.h"
-#include "render/html_internal.h"
+#include "html/private.h"
typedef struct html_css_fetcher_item {
uint32_t key;
@@ -51,7 +57,7 @@ typedef struct html_css_fetcher_context {
bool aborted;
bool locked;
-
+
struct html_css_fetcher_context *r_next, *r_prev;
} html_css_fetcher_context;
@@ -86,7 +92,7 @@ static void *html_css_fetcher_setup(struct fetch *parent_fetch, nsurl *url,
lwc_string *path;
uint32_t key;
html_css_fetcher_item *item, *found = NULL;
-
+
/* format of a x-ns-css URL is:
* x-ns-url:<key>
* Where key is an unsigned 32bit integer
@@ -131,7 +137,7 @@ static void *html_css_fetcher_setup(struct fetch *parent_fetch, nsurl *url,
ctx->item = found;
RING_INSERT(ring, ctx);
-
+
return ctx;
}
@@ -160,14 +166,14 @@ static void html_css_fetcher_abort(void *ctx)
html_css_fetcher_context *c = ctx;
/* To avoid the poll loop having to deal with the fetch context
- * disappearing from under it, we simply flag the abort here.
+ * disappearing from under it, we simply flag the abort here.
* The poll loop itself will perform the appropriate cleanup.
*/
c->aborted = true;
}
-static void html_css_fetcher_send_callback(const fetch_msg *msg,
- html_css_fetcher_context *c)
+static void html_css_fetcher_send_callback(const fetch_msg *msg,
+ html_css_fetcher_context *c)
{
c->locked = true;
fetch_send_callback(msg, c->parent_fetch);
@@ -178,16 +184,16 @@ static void html_css_fetcher_poll(lwc_string *scheme)
{
fetch_msg msg;
html_css_fetcher_context *c, *next;
-
+
if (ring == NULL) return;
-
+
/* Iterate over ring, processing each pending fetch */
c = ring;
do {
/* Ignore fetches that have been flagged as locked.
* This allows safe re-entrant calls to this function.
* Re-entrancy can occur if, as a result of a callback,
- * the interested party causes fetch_poll() to be called
+ * the interested party causes fetch_poll() to be called
* again.
*/
if (c->locked == true) {
@@ -213,26 +219,26 @@ static void html_css_fetcher_poll(lwc_string *scheme)
msg.type = FETCH_HEADER;
msg.data.header_or_data.buf = (const uint8_t *) header;
msg.data.header_or_data.len = strlen(header);
- html_css_fetcher_send_callback(&msg, c);
+ html_css_fetcher_send_callback(&msg, c);
if (c->aborted == false) {
- snprintf(header, sizeof header,
+ snprintf(header, sizeof header,
"Content-Length: %"PRIsizet,
dom_string_byte_length(c->item->data));
msg.type = FETCH_HEADER;
- msg.data.header_or_data.buf =
+ msg.data.header_or_data.buf =
(const uint8_t *) header;
msg.data.header_or_data.len = strlen(header);
html_css_fetcher_send_callback(&msg, c);
}
if (c->aborted == false) {
- snprintf(header, sizeof header,
+ snprintf(header, sizeof header,
"X-NS-Base: %.*s",
(int) nsurl_length(c->item->base_url),
nsurl_access(c->item->base_url));
msg.type = FETCH_HEADER;
- msg.data.header_or_data.buf =
+ msg.data.header_or_data.buf =
(const uint8_t *) header;
msg.data.header_or_data.len = strlen(header);
html_css_fetcher_send_callback(&msg, c);
@@ -240,8 +246,8 @@ static void html_css_fetcher_poll(lwc_string *scheme)
if (c->aborted == false) {
msg.type = FETCH_DATA;
- msg.data.header_or_data.buf =
- (const uint8_t *)
+ msg.data.header_or_data.buf =
+ (const uint8_t *)
dom_string_data(c->item->data);
msg.data.header_or_data.len =
dom_string_byte_length(c->item->data);
@@ -256,7 +262,7 @@ static void html_css_fetcher_poll(lwc_string *scheme)
NSLOG(netsurf, INFO, "Processing of %s failed!",
nsurl_access(c->url));
- /* Ensure that we're unlocked here. If we aren't,
+ /* Ensure that we're unlocked here. If we aren't,
* then html_css_fetcher_process() is broken.
*/
assert(c->locked == false);
@@ -279,7 +285,6 @@ static void html_css_fetcher_poll(lwc_string *scheme)
/* exported interface documented in html_internal.h */
nserror html_css_fetcher_register(void)
{
- lwc_string *scheme;
const struct fetcher_operation_table html_css_fetcher_ops = {
.initialise = html_css_fetcher_initialise,
.acceptable = html_css_fetcher_can_fetch,
@@ -291,13 +296,8 @@ nserror html_css_fetcher_register(void)
.finalise = html_css_fetcher_finalise
};
- if (lwc_intern_string("x-ns-css", SLEN("x-ns-css"),
- &scheme) != lwc_error_ok) {
- NSLOG(netsurf, INFO, "could not intern \"x-ns-css\".");
- return NSERROR_INIT_FAILED;
- }
-
- return fetcher_add(scheme, &html_css_fetcher_ops);
+ return fetcher_add(lwc_string_ref(corestring_lwc_x_ns_css),
+ &html_css_fetcher_ops);
}
/* exported interface documented in html_internal.h */
@@ -318,4 +318,3 @@ html_css_fetcher_add_item(dom_string *data, nsurl *base_url, uint32_t *key)
return NSERROR_OK;
}
-
diff --git a/content/handlers/html/dom_event.c b/content/handlers/html/dom_event.c
new file mode 100644
index 000000000..d42882515
--- /dev/null
+++ b/content/handlers/html/dom_event.c
@@ -0,0 +1,789 @@
+/*
+ * Copyright 2010 Michael Drake <tlsa@netsurf-browser.org>
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of HTML content DOM event handling.
+ */
+
+#include <string.h>
+
+#include "utils/config.h"
+#include "utils/utils.h"
+#include "utils/corestrings.h"
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "utils/ascii.h"
+#include "utils/string.h"
+#include "utils/nsurl.h"
+#include "content/content.h"
+#include "javascript/js.h"
+
+#include "netsurf/bitmap.h"
+
+#include "html/private.h"
+#include "html/object.h"
+#include "html/css.h"
+#include "html/box.h"
+#include "html/box_construct.h"
+#include "html/form_internal.h"
+#include "html/dom_event.h"
+
+
+/**
+ * process a base element being inserted into the DOM
+ *
+ * \param htmlc The html content containing the DOM
+ * \param node The DOM node being inserted
+ * \return NSERROR_OK on success else appropriate error code
+ */
+static bool html_process_inserted_base(html_content *htmlc, dom_node *node)
+{
+ dom_exception exc; /* returned by libdom functions */
+ dom_string *atr_string;
+
+ /* get href attribute if present */
+ exc = dom_element_get_attribute(node, corestring_dom_href, &atr_string);
+ if ((exc == DOM_NO_ERR) && (atr_string != NULL)) {
+ nsurl *url;
+ nserror error;
+
+ /* get url from string */
+ error = nsurl_create(dom_string_data(atr_string), &url);
+ dom_string_unref(atr_string);
+ if (error == NSERROR_OK) {
+ if (htmlc->base_url != NULL) {
+ nsurl_unref(htmlc->base_url);
+ }
+ htmlc->base_url = url;
+ }
+ }
+
+
+ /* get target attribute if present and not already set */
+ if (htmlc->base_target != NULL) {
+ return true;
+ }
+
+ exc = dom_element_get_attribute(node,
+ corestring_dom_target,
+ &atr_string);
+ if ((exc == DOM_NO_ERR) && (atr_string != NULL)) {
+ /* Validation rules from the HTML5 spec for the base element:
+ * The target must be one of _blank, _self, _parent, or
+ * _top or any identifier which does not begin with an
+ * underscore
+ */
+ if (*dom_string_data(atr_string) != '_' ||
+ dom_string_caseless_lwc_isequal(atr_string,
+ corestring_lwc__blank) ||
+ dom_string_caseless_lwc_isequal(atr_string,
+ corestring_lwc__self) ||
+ dom_string_caseless_lwc_isequal(atr_string,
+ corestring_lwc__parent) ||
+ dom_string_caseless_lwc_isequal(atr_string,
+ corestring_lwc__top)) {
+ htmlc->base_target = strdup(dom_string_data(atr_string));
+ }
+ dom_string_unref(atr_string);
+ }
+
+ return true;
+}
+
+
+
+/**
+ * Process img element being inserted into the DOM.
+ *
+ * \param htmlc The html content containing the DOM
+ * \param node The DOM node being inserted
+ * \return NSERROR_OK on success else appropriate error code
+ */
+static bool html_process_inserted_img(html_content *htmlc, dom_node *node)
+{
+ dom_string *src;
+ nsurl *url;
+ nserror err;
+ dom_exception exc;
+ bool success;
+
+ /* Do nothing if foreground images are disabled */
+ if (nsoption_bool(foreground_images) == false) {
+ return true;
+ }
+
+ exc = dom_element_get_attribute(node, corestring_dom_src, &src);
+ if (exc != DOM_NO_ERR || src == NULL) {
+ return true;
+ }
+
+ err = nsurl_join(htmlc->base_url, dom_string_data(src), &url);
+ if (err != NSERROR_OK) {
+ dom_string_unref(src);
+ return false;
+ }
+ dom_string_unref(src);
+
+ /* Speculatively fetch the image */
+ success = html_fetch_object(htmlc, url, NULL, CONTENT_IMAGE, false);
+ nsurl_unref(url);
+
+ return success;
+}
+
+
+/**
+ * process a LINK element being inserted into the DOM
+ *
+ * \note only the http-equiv attribute for refresh is currently considered
+ *
+ * \param htmlc The html content containing the DOM
+ * \param n The DOM node being inserted
+ * \return NSERROR_OK on success else appropriate error code
+ */
+static bool html_process_inserted_link(html_content *c, dom_node *node)
+{
+ struct content_rfc5988_link link; /* the link added to the content */
+ dom_exception exc; /* returned by libdom functions */
+ dom_string *atr_string;
+ nserror error;
+
+ /* Handle stylesheet loading */
+ html_css_process_link(c, (dom_node *)node);
+
+ /* try Generic link handling */
+
+ memset(&link, 0, sizeof(struct content_rfc5988_link));
+
+ /* check that the relation exists - w3c spec says must be present */
+ exc = dom_element_get_attribute(node, corestring_dom_rel, &atr_string);
+ if ((exc != DOM_NO_ERR) || (atr_string == NULL)) {
+ return false;
+ }
+ /* get a lwc string containing the link relation */
+ exc = dom_string_intern(atr_string, &link.rel);
+ dom_string_unref(atr_string);
+ if (exc != DOM_NO_ERR) {
+ return false;
+ }
+
+ /* check that the href exists - w3c spec says must be present */
+ exc = dom_element_get_attribute(node, corestring_dom_href, &atr_string);
+ if ((exc != DOM_NO_ERR) || (atr_string == NULL)) {
+ lwc_string_unref(link.rel);
+ return false;
+ }
+
+ /* get nsurl */
+ error = nsurl_join(c->base_url, dom_string_data(atr_string),
+ &link.href);
+ dom_string_unref(atr_string);
+ if (error != NSERROR_OK) {
+ lwc_string_unref(link.rel);
+ return false;
+ }
+
+ /* look for optional properties -- we don't care if internment fails */
+
+ exc = dom_element_get_attribute(node,
+ corestring_dom_hreflang, &atr_string);
+ if ((exc == DOM_NO_ERR) && (atr_string != NULL)) {
+ /* get a lwc string containing the href lang */
+ (void)dom_string_intern(atr_string, &link.hreflang);
+ dom_string_unref(atr_string);
+ }
+
+ exc = dom_element_get_attribute(node,
+ corestring_dom_type, &atr_string);
+ if ((exc == DOM_NO_ERR) && (atr_string != NULL)) {
+ /* get a lwc string containing the type */
+ (void)dom_string_intern(atr_string, &link.type);
+ dom_string_unref(atr_string);
+ }
+
+ exc = dom_element_get_attribute(node,
+ corestring_dom_media, &atr_string);
+ if ((exc == DOM_NO_ERR) && (atr_string != NULL)) {
+ /* get a lwc string containing the media */
+ (void)dom_string_intern(atr_string, &link.media);
+ dom_string_unref(atr_string);
+ }
+
+ exc = dom_element_get_attribute(node,
+ corestring_dom_sizes, &atr_string);
+ if ((exc == DOM_NO_ERR) && (atr_string != NULL)) {
+ /* get a lwc string containing the sizes */
+ (void)dom_string_intern(atr_string, &link.sizes);
+ dom_string_unref(atr_string);
+ }
+
+ /* add to content */
+ content__add_rfc5988_link(&c->base, &link);
+
+ if (link.sizes != NULL)
+ lwc_string_unref(link.sizes);
+ if (link.media != NULL)
+ lwc_string_unref(link.media);
+ if (link.type != NULL)
+ lwc_string_unref(link.type);
+ if (link.hreflang != NULL)
+ lwc_string_unref(link.hreflang);
+
+ nsurl_unref(link.href);
+ lwc_string_unref(link.rel);
+
+ return true;
+}
+
+
+/* handler for a SCRIPT which has been added to a tree */
+static void
+dom_SCRIPT_showed_up(html_content *htmlc, dom_html_script_element *script)
+{
+ dom_exception exc;
+ dom_html_script_element_flags flags;
+ dom_hubbub_error res;
+ bool within;
+
+ if (!htmlc->enable_scripting) {
+ NSLOG(netsurf, INFO, "Encountered a script, but scripting is off, ignoring");
+ return;
+ }
+
+ NSLOG(netsurf, DEEPDEBUG, "Encountered a script, node %p showed up", script);
+
+ exc = dom_html_script_element_get_flags(script, &flags);
+ if (exc != DOM_NO_ERR) {
+ NSLOG(netsurf, DEEPDEBUG, "Unable to retrieve flags, giving up");
+ return;
+ }
+
+ if (flags & DOM_HTML_SCRIPT_ELEMENT_FLAG_PARSER_INSERTED) {
+ NSLOG(netsurf, DEBUG, "Script was parser inserted, skipping");
+ return;
+ }
+
+ exc = dom_node_contains(htmlc->document, script, &within);
+ if (exc != DOM_NO_ERR) {
+ NSLOG(netsurf, DEBUG, "Unable to determine if script was within document, ignoring");
+ return;
+ }
+
+ if (!within) {
+ NSLOG(netsurf, DEBUG, "Script was not within the document, ignoring for now");
+ return;
+ }
+
+ res = html_process_script(htmlc, (dom_node *) script);
+ if (res == DOM_HUBBUB_OK) {
+ NSLOG(netsurf, DEEPDEBUG, "Inserted script has finished running");
+ } else {
+ if (res == (DOM_HUBBUB_HUBBUB_ERR | HUBBUB_PAUSED)) {
+ NSLOG(netsurf, DEEPDEBUG, "Inserted script has launced asynchronously");
+ } else {
+ NSLOG(netsurf, DEEPDEBUG, "Failure starting script");
+ }
+ }
+}
+
+
+/**
+ * process a META element being inserted into the DOM
+ *
+ * \note only the http-equiv attribute for refresh is currently considered
+ *
+ * \param htmlc The html content containing the DOM
+ * \param n The DOM node being inserted
+ * \return NSERROR_OK on success else appropriate error code
+ */
+static nserror html_process_inserted_meta(html_content *c, dom_node *n)
+{
+ union content_msg_data msg_data;
+ const char *url, *end, *refresh = NULL;
+ char *new_url;
+ char quote = '\0';
+ dom_string *equiv, *content;
+ dom_exception exc;
+ nsurl *nsurl;
+ nserror error = NSERROR_OK;
+
+ if (c->refresh) {
+ /* refresh already delt with */
+ return NSERROR_OK;
+ }
+
+ exc = dom_element_get_attribute(n, corestring_dom_http_equiv, &equiv);
+ if (exc != DOM_NO_ERR) {
+ return NSERROR_DOM;
+ }
+
+ if (equiv == NULL) {
+ return NSERROR_OK;
+ }
+
+ if (!dom_string_caseless_lwc_isequal(equiv, corestring_lwc_refresh)) {
+ dom_string_unref(equiv);
+ return NSERROR_OK;
+ }
+
+ dom_string_unref(equiv);
+
+ exc = dom_element_get_attribute(n, corestring_dom_content, &content);
+ if (exc != DOM_NO_ERR) {
+ return NSERROR_DOM;
+ }
+
+ if (content == NULL) {
+ return NSERROR_OK;
+ }
+
+ end = dom_string_data(content) + dom_string_byte_length(content);
+
+ /* content := *LWS intpart fracpart? *LWS [';' *LWS *1url *LWS]
+ * intpart := 1*DIGIT
+ * fracpart := 1*('.' | DIGIT)
+ * url := "url" *LWS '=' *LWS (url-nq | url-sq | url-dq)
+ * url-nq := *urlchar
+ * url-sq := "'" *(urlchar | '"') "'"
+ * url-dq := '"' *(urlchar | "'") '"'
+ * urlchar := [#x9#x21#x23-#x26#x28-#x7E] | nonascii
+ * nonascii := [#x80-#xD7FF#xE000-#xFFFD#x10000-#x10FFFF]
+ */
+
+ url = dom_string_data(content);
+
+ /* *LWS */
+ while (url < end && ascii_is_space(*url)) {
+ url++;
+ }
+
+ /* intpart */
+ if (url == end || (*url < '0' || '9' < *url)) {
+ /* Empty content, or invalid timeval */
+ dom_string_unref(content);
+ return NSERROR_OK;
+ }
+
+ msg_data.delay = (int) strtol(url, &new_url, 10);
+ /* a very small delay and self-referencing URL can cause a loop
+ * that grinds machines to a halt. To prevent this we set a
+ * minimum refresh delay of 1s. */
+ if (msg_data.delay < 1) {
+ msg_data.delay = 1;
+ }
+
+ url = new_url;
+
+ /* fracpart? (ignored, as delay is integer only) */
+ while (url < end && (('0' <= *url && *url <= '9') ||
+ *url == '.')) {
+ url++;
+ }
+
+ /* *LWS */
+ while (url < end && ascii_is_space(*url)) {
+ url++;
+ }
+
+ /* ';' */
+ if (url < end && *url == ';')
+ url++;
+
+ /* *LWS */
+ while (url < end && ascii_is_space(*url)) {
+ url++;
+ }
+
+ if (url == end) {
+ /* Just delay specified, so refresh current page */
+ dom_string_unref(content);
+
+ c->base.refresh = nsurl_ref(content_get_url(&c->base));
+
+ content_broadcast(&c->base, CONTENT_MSG_REFRESH, &msg_data);
+
+ return NSERROR_OK;
+ }
+
+ /* "url" */
+ if (url <= end - 3) {
+ if (strncasecmp(url, "url", 3) == 0) {
+ url += 3;
+ } else {
+ /* Unexpected input, ignore this header */
+ dom_string_unref(content);
+ return NSERROR_OK;
+ }
+ } else {
+ /* Insufficient input, ignore this header */
+ dom_string_unref(content);
+ return NSERROR_OK;
+ }
+
+ /* *LWS */
+ while (url < end && ascii_is_space(*url)) {
+ url++;
+ }
+
+ /* '=' */
+ if (url < end) {
+ if (*url == '=') {
+ url++;
+ } else {
+ /* Unexpected input, ignore this header */
+ dom_string_unref(content);
+ return NSERROR_OK;
+ }
+ } else {
+ /* Insufficient input, ignore this header */
+ dom_string_unref(content);
+ return NSERROR_OK;
+ }
+
+ /* *LWS */
+ while (url < end && ascii_is_space(*url)) {
+ url++;
+ }
+
+ /* '"' or "'" */
+ if (url < end && (*url == '"' || *url == '\'')) {
+ quote = *url;
+ url++;
+ }
+
+ /* Start of URL */
+ refresh = url;
+
+ if (quote != 0) {
+ /* url-sq | url-dq */
+ while (url < end && *url != quote)
+ url++;
+ } else {
+ /* url-nq */
+ while (url < end && !ascii_is_space(*url))
+ url++;
+ }
+
+ /* '"' or "'" or *LWS (we don't care) */
+ if (url > refresh) {
+ /* There's a URL */
+ new_url = strndup(refresh, url - refresh);
+ if (new_url == NULL) {
+ dom_string_unref(content);
+ return NSERROR_NOMEM;
+ }
+
+ error = nsurl_join(c->base_url, new_url, &nsurl);
+ if (error == NSERROR_OK) {
+ /* broadcast valid refresh url */
+
+ c->base.refresh = nsurl;
+
+ content_broadcast(&c->base,
+ CONTENT_MSG_REFRESH,
+ &msg_data);
+ c->refresh = true;
+ }
+
+ free(new_url);
+
+ }
+
+ dom_string_unref(content);
+
+ return error;
+}
+
+
+/**
+ * Process title element being inserted into the DOM.
+ *
+ * https://html.spec.whatwg.org/multipage/semantics.html#the-title-element
+ *
+ * \param htmlc The html content containing the DOM
+ * \param node The DOM node being inserted
+ * \return NSERROR_OK on success else appropriate error code
+ */
+static nserror html_process_inserted_title(html_content *htmlc, dom_node *node)
+{
+ if (htmlc->title == NULL) {
+ /* only the first title is considered */
+ htmlc->title = dom_node_ref(node);
+ }
+ return NSERROR_OK;
+}
+
+
+/** process title node */
+static bool html_process_title(html_content *c, dom_node *node)
+{
+ dom_exception exc; /* returned by libdom functions */
+ dom_string *title;
+ char *title_str;
+ bool success;
+
+ exc = dom_node_get_text_content(node, &title);
+ if ((exc != DOM_NO_ERR) || (title == NULL)) {
+ return false;
+ }
+
+ title_str = squash_whitespace(dom_string_data(title));
+ dom_string_unref(title);
+
+ if (title_str == NULL) {
+ return false;
+ }
+
+ success = content__set_title(&c->base, title_str);
+
+ free(title_str);
+
+ return success;
+}
+
+
+/**
+ * Deal with input elements being modified by resyncing their gadget
+ * if they have one.
+ */
+static void html_texty_element_update(html_content *htmlc, dom_node *node)
+{
+ struct box *box = box_for_node(node);
+ if (box == NULL) {
+ return; /* No Box (yet?) so no gadget to update */
+ }
+ if (box->gadget == NULL) {
+ return; /* No gadget yet (under construction perhaps?) */
+ }
+ form_gadget_sync_with_dom(box->gadget);
+ /* And schedule a redraw for the box */
+ html__redraw_a_box(htmlc, box);
+}
+
+
+/**
+ * callback for DOMNodeInserted end type
+ */
+static void
+dom_default_action_DOMNodeInserted_cb(struct dom_event *evt, void *pw)
+{
+ dom_event_target *node;
+ dom_node_type type;
+ dom_exception exc;
+ html_content *htmlc = pw;
+
+ exc = dom_event_get_target(evt, &node);
+ if ((exc != DOM_NO_ERR) || (node == NULL)) {
+ /* failed to obtain the event target node */
+ return;
+ }
+
+ exc = dom_node_get_node_type(node, &type);
+ if ((exc == DOM_NO_ERR) && (type == DOM_ELEMENT_NODE)) {
+ /* an element node has been inserted */
+ dom_html_element_type tag_type;
+
+ exc = dom_html_element_get_tag_type(node, &tag_type);
+ if (exc != DOM_NO_ERR) {
+ tag_type = DOM_HTML_ELEMENT_TYPE__UNKNOWN;
+ }
+
+ switch (tag_type) {
+ case DOM_HTML_ELEMENT_TYPE_BASE:
+ html_process_inserted_base(htmlc, (dom_node *)node);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_IMG:
+ html_process_inserted_img(htmlc, (dom_node *)node);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_LINK:
+ html_process_inserted_link(htmlc, (dom_node *)node);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_META:
+ html_process_inserted_meta(htmlc, (dom_node *)node);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_STYLE:
+ if (nsoption_bool(author_level_css)) {
+ html_css_process_style(htmlc, (dom_node *)node);
+ }
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_SCRIPT:
+ dom_SCRIPT_showed_up(htmlc,
+ (dom_html_script_element *)node);
+ break;
+
+ case DOM_HTML_ELEMENT_TYPE_TITLE:
+ html_process_inserted_title(htmlc, (dom_node *)node);
+ break;
+
+ default:
+ break;
+ }
+
+ if (htmlc->enable_scripting) {
+ /* ensure javascript context is available */
+ if (htmlc->jsthread == NULL) {
+ union content_msg_data msg_data;
+
+ msg_data.jsthread = &htmlc->jsthread;
+ content_broadcast(&htmlc->base,
+ CONTENT_MSG_GETTHREAD,
+ &msg_data);
+ NSLOG(netsurf, INFO,
+ "javascript context: %p (htmlc: %p)",
+ htmlc->jsthread,
+ htmlc);
+ }
+ if (htmlc->jsthread != NULL) {
+ js_handle_new_element(htmlc->jsthread,
+ (dom_element *) node);
+ }
+ }
+ }
+ dom_node_unref(node);
+}
+
+
+/**
+ * callback for DOMNodeInsertedIntoDocument end type
+ */
+static void
+dom_default_action_DOMNodeInsertedIntoDocument_cb(struct dom_event *evt,
+ void *pw)
+{
+ html_content *htmlc = pw;
+ dom_event_target *node;
+ dom_node_type type;
+ dom_exception exc;
+
+ exc = dom_event_get_target(evt, &node);
+ if ((exc == DOM_NO_ERR) && (node != NULL)) {
+ exc = dom_node_get_node_type(node, &type);
+ if ((exc == DOM_NO_ERR) && (type == DOM_ELEMENT_NODE)) {
+ /* an element node has been modified */
+ dom_html_element_type tag_type;
+
+ exc = dom_html_element_get_tag_type(node, &tag_type);
+ if (exc != DOM_NO_ERR) {
+ tag_type = DOM_HTML_ELEMENT_TYPE__UNKNOWN;
+ }
+
+ switch (tag_type) {
+ case DOM_HTML_ELEMENT_TYPE_SCRIPT:
+ dom_SCRIPT_showed_up(htmlc, (dom_html_script_element *) node);
+ fallthrough;
+ default:
+ break;
+ }
+ }
+ dom_node_unref(node);
+ }
+}
+
+
+/**
+ * callback for DOMSubtreeModified end type
+ */
+static void
+dom_default_action_DOMSubtreeModified_cb(struct dom_event *evt, void *pw)
+{
+ dom_event_target *node;
+ dom_node_type type;
+ dom_exception exc;
+ html_content *htmlc = pw;
+
+ exc = dom_event_get_target(evt, &node);
+ if ((exc == DOM_NO_ERR) && (node != NULL)) {
+ if (htmlc->title == (dom_node *)node) {
+ /* Node is our title node */
+ html_process_title(htmlc, (dom_node *)node);
+ dom_node_unref(node);
+ return;
+ }
+
+ exc = dom_node_get_node_type(node, &type);
+ if ((exc == DOM_NO_ERR) && (type == DOM_ELEMENT_NODE)) {
+ /* an element node has been modified */
+ dom_html_element_type tag_type;
+
+ exc = dom_html_element_get_tag_type(node, &tag_type);
+ if (exc != DOM_NO_ERR) {
+ tag_type = DOM_HTML_ELEMENT_TYPE__UNKNOWN;
+ }
+
+ switch (tag_type) {
+ case DOM_HTML_ELEMENT_TYPE_STYLE:
+ if (nsoption_bool(author_level_css)) {
+ html_css_update_style(htmlc,
+ (dom_node *)node);
+ }
+ break;
+ case DOM_HTML_ELEMENT_TYPE_TEXTAREA:
+ case DOM_HTML_ELEMENT_TYPE_INPUT:
+ html_texty_element_update(htmlc, (dom_node *)node);
+ fallthrough;
+ default:
+ break;
+ }
+ }
+ dom_node_unref(node);
+ }
+}
+
+
+/**
+ * callback for default action finished
+ */
+static void
+dom_default_action_finished_cb(struct dom_event *evt, void *pw)
+{
+ html_content *htmlc = pw;
+
+ if (htmlc->jsthread != NULL)
+ js_event_cleanup(htmlc->jsthread, evt);
+}
+
+
+/* exported interface documented in html/dom_event.c */
+dom_default_action_callback
+html_dom_event_fetcher(dom_string *type,
+ dom_default_action_phase phase,
+ void **pw)
+{
+ NSLOG(netsurf, DEEPDEBUG,
+ "phase:%d type:%s", phase, dom_string_data(type));
+
+ if (phase == DOM_DEFAULT_ACTION_END) {
+ if (dom_string_isequal(type, corestring_dom_DOMNodeInserted)) {
+ return dom_default_action_DOMNodeInserted_cb;
+ } else if (dom_string_isequal(type, corestring_dom_DOMNodeInsertedIntoDocument)) {
+ return dom_default_action_DOMNodeInsertedIntoDocument_cb;
+ } else if (dom_string_isequal(type, corestring_dom_DOMSubtreeModified)) {
+ return dom_default_action_DOMSubtreeModified_cb;
+ }
+ } else if (phase == DOM_DEFAULT_ACTION_FINISHED) {
+ return dom_default_action_finished_cb;
+ }
+ return NULL;
+}
diff --git a/content/handlers/html/dom_event.h b/content/handlers/html/dom_event.h
new file mode 100644
index 000000000..dec828df7
--- /dev/null
+++ b/content/handlers/html/dom_event.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * HTML content DOM event handling interface
+ */
+
+#ifndef NETSURF_HTML_DOM_EVENT_H
+#define NETSURF_HTML_DOM_EVENT_H
+
+/**
+ * html content DOM action callback function selector
+ *
+ * selects a callback function for libdom to call based on the type and phase.
+ * dom_default_action_phase from events/document_event.h
+ *
+ * The principle events are:
+ * DOMSubtreeModified
+ * DOMAttrModified
+ * DOMNodeInserted
+ * DOMNodeInsertedIntoDocument
+ *
+ * @return callback function pointer or NULL for none
+ */
+dom_default_action_callback html_dom_event_fetcher(dom_string *type, dom_default_action_phase phase, void **pw);
+
+#endif
diff --git a/render/font.c b/content/handlers/html/font.c
index a769b476f..4a64759d7 100644
--- a/render/font.c
+++ b/content/handlers/html/font.c
@@ -19,23 +19,23 @@
/**
* \file
*
- * Renderer internal font handling implementation.
+ * HTML internal font handling implementation.
*/
#include "utils/nsoption.h"
#include "netsurf/plot_style.h"
#include "css/utils.h"
-#include "render/font.h"
+#include "html/font.h"
/**
* Map a generic CSS font family to a generic plot font family
*
- * \param css Generic CSS font family
+ * \param css Generic CSS font family
* \return Plot font family
*/
-static plot_font_generic_family_t plot_font_generic_family(
- enum css_font_family_e css)
+static plot_font_generic_family_t
+plot_font_generic_family(enum css_font_family_e css)
{
plot_font_generic_family_t plot;
@@ -131,9 +131,9 @@ static plot_font_flags_t plot_font_flags(enum css_font_style_e style,
}
-/* exported function documented in render/font.h */
+/* exported function documented in html/font.h */
void font_plot_style_from_css(
- const nscss_len_ctx *len_ctx,
+ const css_unit_ctx *unit_len_ctx,
const css_computed_style *css,
plot_font_style_t *fstyle)
{
@@ -144,14 +144,16 @@ void font_plot_style_from_css(
fstyle->family = plot_font_generic_family(
css_computed_font_family(css, &families));
+ fstyle->families = families;
css_computed_font_size(css, &length, &unit);
- fstyle->size = FIXTOINT(FMUL(nscss_len2pt(len_ctx, length, unit),
- INTTOFIX(FONT_SIZE_SCALE)));
+ fstyle->size = FIXTOINT(FMUL(css_unit_font_size_len2pt(css,
+ unit_len_ctx, length, unit),
+ INTTOFIX(PLOT_STYLE_SCALE)));
/* Clamp font size to configured minimum */
- if (fstyle->size < (nsoption_int(font_min_size) * FONT_SIZE_SCALE) / 10)
- fstyle->size = (nsoption_int(font_min_size) * FONT_SIZE_SCALE) / 10;
+ if (fstyle->size < (nsoption_int(font_min_size) * PLOT_STYLE_SCALE) / 10)
+ fstyle->size = (nsoption_int(font_min_size) * PLOT_STYLE_SCALE) / 10;
fstyle->weight = plot_font_weight(css_computed_font_weight(css));
fstyle->flags = plot_font_flags(css_computed_font_style(css),
diff --git a/render/font.h b/content/handlers/html/font.h
index 52f5a62c2..26f5bf289 100644
--- a/render/font.h
+++ b/content/handlers/html/font.h
@@ -16,29 +16,28 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- *
+/**
+ * \file
* Internal font handling interfaces.
*
* These functions provide font related services. They all work on
* UTF-8 strings with lengths given.
*/
-#ifndef _NETSURF_RENDER_FONT_H_
-#define _NETSURF_RENDER_FONT_H_
+#ifndef NETSURF_HTML_FONT_H
+#define NETSURF_HTML_FONT_H
struct plot_font_style;
/**
* Populate a font style using data from a computed CSS style
*
- * \param len_ctx Length conversion context
+ * \param unit_len_ctx Length conversion context
* \param css Computed style to consider
* \param fstyle Font style to populate
*/
-void font_plot_style_from_css(
- const nscss_len_ctx *len_ctx,
- const css_computed_style *css,
- struct plot_font_style *fstyle);
+void font_plot_style_from_css(const css_unit_ctx *unit_len_ctx,
+ const css_computed_style *css,
+ struct plot_font_style *fstyle);
#endif
diff --git a/content/handlers/html/form.c b/content/handlers/html/form.c
new file mode 100644
index 000000000..9b6768a56
--- /dev/null
+++ b/content/handlers/html/form.c
@@ -0,0 +1,2361 @@
+/*
+ * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
+ * Copyright 2004 John Tytgat <joty@netsurf-browser.org>
+ * Copyright 2005-9 John-Mark Bell <jmb@netsurf-browser.org>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
+ * Copyright 2010 Michael Drake <tlsa@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Form handling functions (implementation).
+ */
+
+#include <assert.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <dom/dom.h>
+
+#include "utils/corestrings.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/talloc.h"
+#include "utils/url.h"
+#include "utils/utf8.h"
+#include "utils/ascii.h"
+#include "netsurf/browser_window.h"
+#include "netsurf/inttypes.h"
+#include "netsurf/mouse.h"
+#include "netsurf/plotters.h"
+#include "netsurf/misc.h"
+#include "content/fetch.h"
+#include "content/hlcache.h"
+#include "css/utils.h"
+#include "desktop/knockout.h"
+#include "desktop/scrollbar.h"
+#include "desktop/textarea.h"
+
+#include "html/html.h"
+#include "html/private.h"
+#include "html/layout.h"
+#include "html/box.h"
+#include "html/box_inspect.h"
+#include "html/font.h"
+#include "html/form_internal.h"
+
+#define MAX_SELECT_HEIGHT 210
+#define SELECT_LINE_SPACING 0.2
+#define SELECT_BORDER_WIDTH 1
+#define SELECT_SELECTED_COLOUR 0xDB9370
+
+struct form_select_menu {
+ int line_height;
+ int width, height;
+ struct scrollbar *scrollbar;
+ int f_size;
+ bool scroll_capture;
+ select_menu_redraw_callback callback;
+ void *client_data;
+ struct content *c;
+};
+
+static plot_style_t plot_style_fill_selected = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+ .fill_colour = SELECT_SELECTED_COLOUR,
+};
+
+static plot_font_style_t plot_fstyle_entry = {
+ .family = PLOT_FONT_FAMILY_SANS_SERIF,
+ .weight = 400,
+ .flags = FONTF_NONE,
+ .background = 0xffffff,
+ .foreground = 0x000000,
+};
+
+
+/**
+ * Convert a string from UTF-8 to the specified charset
+ * As a final fallback, this will attempt to convert to ISO-8859-1.
+ *
+ * \todo Return charset used?
+ *
+ * \param item String to convert
+ * \param len Length of string to convert
+ * \param charset Destination charset
+ * \param fallback Fallback charset (may be NULL),
+ * used iff converting to charset fails
+ * \return Pointer to converted string (on heap, caller frees), or NULL
+ */
+static char *
+form_encode_item(const char *item,
+ uint32_t len,
+ const char *charset,
+ const char *fallback)
+{
+ nserror err;
+ char *ret = NULL;
+ char cset[256];
+
+ if (!item || !charset)
+ return NULL;
+
+ snprintf(cset, sizeof cset, "%s//TRANSLIT", charset);
+
+ err = utf8_to_enc(item, cset, 0, &ret);
+ if (err == NSERROR_BAD_ENCODING) {
+ /* charset not understood, try without transliteration */
+ snprintf(cset, sizeof cset, "%s", charset);
+ err = utf8_to_enc(item, cset, len, &ret);
+
+ if (err == NSERROR_BAD_ENCODING) {
+ /* nope, try fallback charset (if any) */
+ if (fallback) {
+ snprintf(cset, sizeof cset,
+ "%s//TRANSLIT", fallback);
+ err = utf8_to_enc(item, cset, 0, &ret);
+
+ if (err == NSERROR_BAD_ENCODING) {
+ /* and without transliteration */
+ snprintf(cset, sizeof cset,
+ "%s", fallback);
+ err = utf8_to_enc(item, cset, 0, &ret);
+ }
+ }
+
+ if (err == NSERROR_BAD_ENCODING) {
+ /* that also failed, use 8859-1 */
+ err = utf8_to_enc(item, "ISO-8859-1//TRANSLIT",
+ 0, &ret);
+ if (err == NSERROR_BAD_ENCODING) {
+ /* and without transliteration */
+ err = utf8_to_enc(item, "ISO-8859-1",
+ 0, &ret);
+ }
+ }
+ }
+ }
+ if (err == NSERROR_NOMEM) {
+ return NULL;
+ }
+
+ return ret;
+}
+
+
+/**
+ * string allocation size for numeric values in multipart data
+ */
+#define FETCH_DATA_INT_VALUE_SIZE 20
+
+
+/**
+ * append split key name and integer value to a multipart data list
+ *
+ * \param name key name
+ * \param ksfx key name suffix
+ * \param value The value to encode
+ * \param fetch_data_next_ptr The multipart data list to append to.
+ */
+static nserror
+fetch_data_list_add_sname(const char *name,
+ const char *ksfx,
+ int value,
+ struct fetch_multipart_data ***fetch_data_next_ptr)
+{
+ struct fetch_multipart_data *fetch_data;
+ int keysize;
+
+ fetch_data = calloc(1, sizeof(*fetch_data));
+ if (fetch_data == NULL) {
+ NSLOG(netsurf, INFO, "failed allocation for fetch data");
+ return NSERROR_NOMEM;
+ }
+
+ /* key name */
+ keysize = snprintf(fetch_data->name, 0, "%s%s", name, ksfx);
+ fetch_data->name = malloc(keysize + 1); /* allow for null */
+ if (fetch_data->name == NULL) {
+ free(fetch_data);
+ NSLOG(netsurf, INFO,
+ "keyname allocation failure for %s%s", name, ksfx);
+ return NSERROR_NOMEM;
+ }
+ snprintf(fetch_data->name, keysize + 1, "%s%s", name, ksfx);
+
+ /* value */
+ fetch_data->value = malloc(FETCH_DATA_INT_VALUE_SIZE);
+ if (fetch_data->value == NULL) {
+ free(fetch_data->name);
+ free(fetch_data);
+ NSLOG(netsurf, INFO, "value allocation failure");
+ return NSERROR_NOMEM;
+ }
+ snprintf(fetch_data->value, FETCH_DATA_INT_VALUE_SIZE, "%d", value);
+
+ /* link into list */
+ **fetch_data_next_ptr = fetch_data;
+ *fetch_data_next_ptr = &fetch_data->next;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * append DOM string name/value pair to a multipart data list
+ *
+ * \param name key name
+ * \param value the value to associate with the key
+ * \param rawfile the raw file value to associate with the key.
+ * \param form_charset The form character set
+ * \param docu_charset The document character set for fallback
+ * \param fetch_data_next_ptr The multipart data list being constructed.
+ * \return NSERROR_OK on success or appropriate error code.
+ */
+static nserror
+fetch_data_list_add(dom_string *name,
+ dom_string *value,
+ const char *rawfile,
+ const char *form_charset,
+ const char *docu_charset,
+ struct fetch_multipart_data ***fetch_data_next_ptr)
+{
+ struct fetch_multipart_data *fetch_data;
+
+ assert(name != NULL);
+
+ fetch_data = calloc(1, sizeof(*fetch_data));
+ if (fetch_data == NULL) {
+ NSLOG(netsurf, INFO, "failed allocation for fetch data");
+ return NSERROR_NOMEM;
+ }
+
+ fetch_data->name = form_encode_item(dom_string_data(name),
+ dom_string_byte_length(name),
+ form_charset,
+ docu_charset);
+ if (fetch_data->name == NULL) {
+ NSLOG(netsurf, INFO, "Could not encode name for fetch data");
+ free(fetch_data);
+ return NSERROR_NOMEM;
+ }
+
+ if (value == NULL) {
+ fetch_data->value = strdup("");
+ } else {
+ fetch_data->value = form_encode_item(dom_string_data(value),
+ dom_string_byte_length(value),
+ form_charset,
+ docu_charset);
+ }
+ if (fetch_data->value == NULL) {
+ NSLOG(netsurf, INFO, "Could not encode value for fetch data");
+ free(fetch_data->name);
+ free(fetch_data);
+ return NSERROR_NOMEM;
+ }
+
+ /* deal with raw file name */
+ if (rawfile != NULL) {
+ fetch_data->file = true;
+ fetch_data->rawfile = strdup(rawfile);
+ if (fetch_data->rawfile == NULL) {
+ NSLOG(netsurf, INFO,
+ "Could not encode rawfile value for fetch data");
+ free(fetch_data->value);
+ free(fetch_data->name);
+ free(fetch_data);
+ return NSERROR_NOMEM;
+ }
+ }
+
+ /* link into list */
+ **fetch_data_next_ptr = fetch_data;
+ *fetch_data_next_ptr = &fetch_data->next;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * process form HTMLTextAreaElement into multipart data.
+ *
+ * \param text_area_element The form select DOM element to convert.
+ * \param form_charset The form character set
+ * \param doc_charset The document character set for fallback
+ * \param fetch_data_next_ptr The multipart data list being constructed.
+ * \return NSERROR_OK on success or appropriate error code.
+ */
+static nserror
+form_dom_to_data_textarea(dom_html_text_area_element *text_area_element,
+ const char *form_charset,
+ const char *doc_charset,
+ struct fetch_multipart_data ***fetch_data_next_ptr)
+{
+ dom_exception exp; /* the result from DOM operations */
+ bool element_disabled;
+ dom_string *inputname;
+ dom_string *inputvalue;
+ nserror res;
+
+ /* check if element is disabled */
+ exp = dom_html_text_area_element_get_disabled(text_area_element,
+ &element_disabled);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO,
+ "Could not get text area disabled property. exp %d", exp);
+ return NSERROR_DOM;
+ }
+
+ if (element_disabled) {
+ /* allow enumeration to continue after disabled element */
+ return NSERROR_OK;
+ }
+
+ /* obtain name property */
+ exp = dom_html_text_area_element_get_name(text_area_element,
+ &inputname);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO,
+ "Could not get text area name property. exp %d", exp);
+ return NSERROR_DOM;
+ }
+
+ if (inputname == NULL) {
+ /* allow enumeration to continue after element with no name */
+ return NSERROR_OK;
+ }
+
+ /* obtain text area value */
+ exp = dom_html_text_area_element_get_value(text_area_element,
+ &inputvalue);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO,
+ "Could not get text area content. exp %d", exp);
+ dom_string_unref(inputname);
+ return NSERROR_DOM;
+ }
+
+ /* add key/value pair to fetch data list */
+ res = fetch_data_list_add(inputname,
+ inputvalue,
+ NULL,
+ form_charset,
+ doc_charset,
+ fetch_data_next_ptr);
+
+ dom_string_unref(inputvalue);
+ dom_string_unref(inputname);
+
+ return res;
+}
+
+
+static nserror
+form_dom_to_data_select_option(dom_html_option_element *option_element,
+ dom_string *keyname,
+ const char *form_charset,
+ const char *docu_charset,
+ struct fetch_multipart_data ***fetch_data_next_ptr)
+{
+ nserror res;
+ dom_exception exp; /* the result from DOM operations */
+ dom_string *value;
+ bool selected;
+
+ exp = dom_html_option_element_get_selected(option_element, &selected);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO, "Could not get option selected property");
+ return NSERROR_DOM;
+ }
+
+ if (!selected) {
+ /* unselected options do not add fetch data entries */
+ return NSERROR_OK;
+ }
+
+ exp = dom_html_option_element_get_value(option_element, &value);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO, "Could not get option value");
+ return NSERROR_DOM;
+ }
+
+ /* add key/value pair to fetch data list */
+ res = fetch_data_list_add(keyname,
+ value,
+ NULL,
+ form_charset,
+ docu_charset,
+ fetch_data_next_ptr);
+
+ dom_string_unref(value);
+
+ return res;
+}
+
+
+/**
+ * process form HTMLSelectElement into multipart data.
+ *
+ * \param select_element The form select DOM element to convert.
+ * \param form_charset The form character set
+ * \param doc_charset The document character set for fallback
+ * \param fetch_data_next_ptr The multipart data list being constructed.
+ * \return NSERROR_OK on success or appropriate error code.
+ */
+static nserror
+form_dom_to_data_select(dom_html_select_element *select_element,
+ const char *form_charset,
+ const char *doc_charset,
+ struct fetch_multipart_data ***fetch_data_next_ptr)
+{
+ nserror res = NSERROR_OK;
+ dom_exception exp; /* the result from DOM operations */
+ bool element_disabled;
+ dom_string *inputname;
+ dom_html_options_collection *options = NULL;
+ uint32_t options_count;
+ uint32_t option_index;
+ dom_node *option_element = NULL;
+
+ /* check if element is disabled */
+ exp = dom_html_select_element_get_disabled(select_element,
+ &element_disabled);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO,
+ "Could not get select disabled property. exp %d", exp);
+ return NSERROR_DOM;
+ }
+
+ if (element_disabled) {
+ /* allow enumeration to continue after disabled element */
+ return NSERROR_OK;
+ }
+
+ /* obtain name property */
+ exp = dom_html_select_element_get_name(select_element, &inputname);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO,
+ "Could not get select name property. exp %d", exp);
+ return NSERROR_DOM;
+ }
+
+ if (inputname == NULL) {
+ /* allow enumeration to continue after element with no name */
+ return NSERROR_OK;
+ }
+
+ /* get options collection */
+ exp = dom_html_select_element_get_options(select_element, &options);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO,
+ "Could not get select options collection");
+ dom_string_unref(inputname);
+ return NSERROR_DOM;
+ }
+
+ /* get options collection length */
+ exp = dom_html_options_collection_get_length(options, &options_count);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO,
+ "Could not get select options collection length");
+ dom_html_options_collection_unref(options);
+ dom_string_unref(inputname);
+ return NSERROR_DOM;
+ }
+
+ /* iterate over options collection */
+ for (option_index = 0; option_index < options_count; ++option_index) {
+ exp = dom_html_options_collection_item(options,
+ option_index,
+ &option_element);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO,
+ "Could not get options item %"PRId32, option_index);
+ res = NSERROR_DOM;
+ } else {
+ res = form_dom_to_data_select_option(
+ (dom_html_option_element *)option_element,
+ inputname,
+ form_charset,
+ doc_charset,
+ fetch_data_next_ptr);
+
+ dom_node_unref(option_element);
+ }
+
+ if (res != NSERROR_OK) {
+ break;
+ }
+ }
+
+ dom_html_options_collection_unref(options);
+ dom_string_unref(inputname);
+
+ return res;
+}
+
+
+static nserror
+form_dom_to_data_input_submit(dom_html_input_element *input_element,
+ dom_string *inputname,
+ const char *charset,
+ const char *document_charset,
+ dom_html_element **submit_button,
+ struct fetch_multipart_data ***fetch_data_next_ptr)
+{
+ dom_exception exp; /* the result from DOM operations */
+ dom_string *inputvalue;
+ nserror res;
+
+ if (*submit_button == NULL) {
+ /* caller specified no button so use this one */
+ *submit_button = (dom_html_element *)input_element;
+ } else if (*submit_button != (dom_html_element *)input_element) {
+ return NSERROR_OK;
+ }
+
+ /* matched button used to submit form */
+ exp = dom_html_input_element_get_value(input_element, &inputvalue);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO, "Could not get submit button value");
+ return NSERROR_DOM;
+ }
+
+ /* add key/value pair to fetch data list */
+ res = fetch_data_list_add(inputname,
+ inputvalue,
+ NULL,
+ charset,
+ document_charset,
+ fetch_data_next_ptr);
+
+ dom_string_unref(inputvalue);
+
+ return res;
+}
+
+
+static nserror
+form_dom_to_data_input_image(dom_html_input_element *input_element,
+ dom_string *inputname,
+ const char *charset,
+ const char *document_charset,
+ dom_html_element **submit_button,
+ struct fetch_multipart_data ***fetch_data_next_ptr)
+{
+ nserror res;
+ dom_exception exp; /* the result from DOM operations */
+ struct image_input_coords *coords;
+ char *basename;
+
+ /* Only use an image input if it was the thing which activated us */
+ if (*submit_button != (dom_html_element *)input_element) {
+ return NSERROR_OK;
+ }
+
+ exp = dom_node_get_user_data((dom_node *)input_element,
+ corestring_dom___ns_key_image_coords_node_data,
+ &coords);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO, "Could not get image XY data");
+ return NSERROR_DOM;
+ }
+
+ if (coords == NULL) {
+ NSLOG(netsurf, INFO, "No XY data on the image input");
+ return NSERROR_DOM;
+ }
+
+ /* encode input name once */
+ basename = form_encode_item(dom_string_data(inputname),
+ dom_string_byte_length(inputname),
+ charset,
+ document_charset);
+ if (basename == NULL) {
+ NSLOG(netsurf, INFO, "Could not encode basename");
+ return NSERROR_NOMEM;
+ }
+
+ res = fetch_data_list_add_sname(basename, ".x",
+ coords->x,
+ fetch_data_next_ptr);
+
+ if (res == NSERROR_OK) {
+ res = fetch_data_list_add_sname(basename, ".y",
+ coords->y,
+ fetch_data_next_ptr);
+ }
+
+ free(basename);
+
+ return res;
+}
+
+
+static nserror
+form_dom_to_data_input_checkbox(dom_html_input_element *input_element,
+ dom_string *inputname,
+ const char *charset,
+ const char *document_charset,
+ struct fetch_multipart_data ***fetch_data_next_ptr)
+{
+ nserror res;
+ dom_exception exp; /* the result from DOM operations */
+ bool checked;
+ dom_string *inputvalue;
+
+ exp = dom_html_input_element_get_checked(input_element, &checked);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO,
+ "Could not get input element checked");
+ return NSERROR_DOM;
+ }
+
+ if (!checked) {
+ /* unchecked items do not generate a data entry */
+ return NSERROR_OK;
+ }
+
+ exp = dom_html_input_element_get_value(input_element, &inputvalue);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO,
+ "Could not get input element value");
+ return NSERROR_DOM;
+ }
+
+ /* ensure a default value */
+ if (inputvalue == NULL) {
+ inputvalue = dom_string_ref(corestring_dom_on);
+ }
+
+ /* add key/value pair to fetch data list */
+ res = fetch_data_list_add(inputname,
+ inputvalue,
+ NULL,
+ charset,
+ document_charset,
+ fetch_data_next_ptr);
+
+ dom_string_unref(inputvalue);
+
+ return res;
+}
+
+
+static nserror
+form_dom_to_data_input_file(dom_html_input_element *input_element,
+ dom_string *inputname,
+ const char *charset,
+ const char *document_charset,
+ struct fetch_multipart_data ***fetch_data_next_ptr)
+{
+ nserror res;
+ dom_exception exp; /* the result from DOM operations */
+ dom_string *inputvalue;
+ const char *rawfile = NULL;
+
+ exp = dom_html_input_element_get_value(input_element, &inputvalue);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO, "Could not get file value");
+ return NSERROR_DOM;
+ }
+
+ exp = dom_node_get_user_data((dom_node *)input_element,
+ corestring_dom___ns_key_file_name_node_data,
+ &rawfile);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO, "Could not get file rawname");
+ return NSERROR_DOM;
+ }
+
+ if (rawfile == NULL) {
+ rawfile = "";
+ }
+
+ /* add key/value pair to fetch data list */
+ res = fetch_data_list_add(inputname,
+ inputvalue,
+ rawfile,
+ charset,
+ document_charset,
+ fetch_data_next_ptr);
+
+ dom_string_unref(inputvalue);
+
+ return res;
+}
+
+
+static nserror
+form_dom_to_data_input_text(dom_html_input_element *input_element,
+ dom_string *inputname,
+ const char *charset,
+ const char *document_charset,
+ struct fetch_multipart_data ***fetch_data_next_ptr)
+{
+ nserror res;
+ dom_exception exp; /* the result from DOM operations */
+ dom_string *inputvalue;
+
+ exp = dom_html_input_element_get_value(input_element, &inputvalue);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO, "Could not get input value");
+ return NSERROR_DOM;
+ }
+
+ /* add key/value pair to fetch data list */
+ res = fetch_data_list_add(inputname,
+ inputvalue,
+ NULL,
+ charset,
+ document_charset,
+ fetch_data_next_ptr);
+
+ dom_string_unref(inputvalue);
+
+ return res;
+}
+
+
+/**
+ * process form input element into multipart data.
+ *
+ * \param input_element The form input DOM element to convert.
+ * \param charset The form character set
+ * \param document_charset The document character set for fallback
+ * \param submit_button The DOM element of the button submitting the form
+ * \param had_submit A boolean value indicating if the submit button
+ * has already been processed in the form element enumeration.
+ * \param fetch_data_next_ptr The multipart data list being constructed.
+ * \return NSERROR_OK on success or appropriate error code.
+ */
+static nserror
+form_dom_to_data_input(dom_html_input_element *input_element,
+ const char *charset,
+ const char *document_charset,
+ dom_html_element **submit_button,
+ struct fetch_multipart_data ***fetch_data_next_ptr)
+{
+ dom_exception exp; /* the result from DOM operations */
+ bool element_disabled;
+ dom_string *inputname;
+ dom_string *inputtype;
+ nserror res;
+
+ /* check if element is disabled */
+ exp = dom_html_input_element_get_disabled(input_element,
+ &element_disabled);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO,
+ "Could not get input disabled property. exp %d", exp);
+ return NSERROR_DOM;
+ }
+
+ if (element_disabled) {
+ /* disabled element requires no more processing */
+ return NSERROR_OK;
+ }
+
+ /* obtain name property */
+ exp = dom_html_input_element_get_name(input_element, &inputname);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO,
+ "Could not get input name property. exp %d", exp);
+ return NSERROR_DOM;
+ }
+
+ if (inputname == NULL) {
+ /* element with no name is not converted */
+ return NSERROR_OK;
+ }
+
+ /* get input type */
+ exp = dom_html_input_element_get_type(input_element, &inputtype);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO, "Could not get input element type");
+ dom_string_unref(inputname);
+ return NSERROR_DOM;
+ }
+
+ /* process according to input element type */
+ if (dom_string_caseless_isequal(inputtype, corestring_dom_submit)) {
+
+ res = form_dom_to_data_input_submit(input_element,
+ inputname,
+ charset,
+ document_charset,
+ submit_button,
+ fetch_data_next_ptr);
+
+ } else if (dom_string_caseless_isequal(inputtype,
+ corestring_dom_image)) {
+
+ res = form_dom_to_data_input_image(input_element,
+ inputname,
+ charset,
+ document_charset,
+ submit_button,
+ fetch_data_next_ptr);
+
+ } else if (dom_string_caseless_isequal(inputtype,
+ corestring_dom_radio) ||
+ dom_string_caseless_isequal(inputtype,
+ corestring_dom_checkbox)) {
+
+ res = form_dom_to_data_input_checkbox(input_element,
+ inputname,
+ charset,
+ document_charset,
+ fetch_data_next_ptr);
+
+ } else if (dom_string_caseless_isequal(inputtype,
+ corestring_dom_file)) {
+
+ res = form_dom_to_data_input_file(input_element,
+ inputname,
+ charset,
+ document_charset,
+ fetch_data_next_ptr);
+
+ } else if (dom_string_caseless_isequal(inputtype,
+ corestring_dom_reset) ||
+ dom_string_caseless_isequal(inputtype,
+ corestring_dom_button)) {
+ /* Skip these */
+ NSLOG(netsurf, INFO, "Skipping RESET and BUTTON");
+ res = NSERROR_OK;
+
+ } else {
+ /* Everything else is treated as text values */
+ res = form_dom_to_data_input_text(input_element,
+ inputname,
+ charset,
+ document_charset,
+ fetch_data_next_ptr);
+
+ }
+
+ dom_string_unref(inputtype);
+ dom_string_unref(inputname);
+
+ return res;
+}
+
+
+/**
+ * process form HTMLButtonElement into multipart data.
+ *
+ * https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element
+ *
+ * \param button_element The form button DOM element to convert.
+ * \param form_charset The form character set
+ * \param doc_charset The document character set for fallback
+ * \param submit_button The DOM element of the button submitting the form
+ * \param fetch_data_next_ptr The multipart data list being constructed.
+ * \return NSERROR_OK on success or appropriate error code.
+ */
+static nserror
+form_dom_to_data_button(dom_html_button_element *button_element,
+ const char *form_charset,
+ const char *doc_charset,
+ dom_html_element **submit_button,
+ struct fetch_multipart_data ***fetch_data_next_ptr)
+{
+ dom_exception exp; /* the result from DOM operations */
+ bool element_disabled;
+ dom_string *inputname;
+ dom_string *inputvalue;
+ dom_string *inputtype;
+ nserror res = NSERROR_OK;
+
+ /* check if element is disabled */
+ exp = dom_html_button_element_get_disabled(button_element,
+ &element_disabled);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO,
+ "Unable to get disabled property. exp %d", exp);
+ return NSERROR_DOM;
+ }
+
+ if (element_disabled) {
+ /* allow enumeration to continue after disabled element */
+ return NSERROR_OK;
+ }
+
+ /* get the type attribute */
+ exp = dom_html_button_element_get_type(button_element, &inputtype);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO, "Could not get button element type");
+ return NSERROR_DOM;
+ }
+
+ /* If the type attribute is "reset" or "button" the element is
+ * barred from constraint validation. Specification says
+ * default and invalid values result in submit which will
+ * be considered.
+ */
+ if (dom_string_caseless_isequal(inputtype, corestring_dom_reset)) {
+ /* multipart data entry not required for reset type */
+ dom_string_unref(inputtype);
+ return NSERROR_OK;
+ }
+ if (dom_string_caseless_isequal(inputtype, corestring_dom_button)) {
+ /* multipart data entry not required for button type */
+ dom_string_unref(inputtype);
+ return NSERROR_OK;
+ }
+ dom_string_unref(inputtype);
+
+ /* only submision button generates an element */
+ if (*submit_button == NULL) {
+ /* no submission button selected yet so use this one */
+ *submit_button = (dom_html_element *)button_element;
+ }
+ if (*submit_button != (dom_html_element *)button_element) {
+ return NSERROR_OK;
+ }
+
+ /* obtain name property */
+ exp = dom_html_button_element_get_name(button_element, &inputname);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO,
+ "Could not get button name property. exp %d", exp);
+ return NSERROR_DOM;
+ }
+
+ if (inputname == NULL) {
+ /* allow enumeration to continue after element with no name */
+ return NSERROR_OK;
+ }
+
+ /* get button value and add to fetch data list */
+ exp = dom_html_button_element_get_value(button_element, &inputvalue);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO, "Could not get submit button value");
+ res = NSERROR_DOM;
+ } else {
+ res = fetch_data_list_add(inputname,
+ inputvalue,
+ NULL,
+ form_charset,
+ doc_charset,
+ fetch_data_next_ptr);
+
+ dom_string_unref(inputvalue);
+ }
+
+ dom_string_unref(inputname);
+
+ return res;
+}
+
+
+/**
+ * Find an acceptable character set encoding with which to submit the form
+ *
+ * \param form The form
+ * \return Pointer to charset name (on heap, caller should free) or NULL
+ */
+static char *form_acceptable_charset(struct form *form)
+{
+ char *temp, *c;
+
+ if (!form->accept_charsets) {
+ /* no accept-charsets attribute for this form */
+ if (form->document_charset) {
+ /* document charset present, so use it */
+ return strdup(form->document_charset);
+ } else {
+ /* no document charset, so default to 8859-1 */
+ return strdup("ISO-8859-1");
+ }
+ }
+
+ /* make temporary copy of accept-charsets attribute */
+ temp = strdup(form->accept_charsets);
+ if (!temp)
+ return NULL;
+
+ /* make it upper case */
+ for (c = temp; *c; c++) {
+ *c = ascii_to_upper(*c);
+ }
+
+ /* is UTF-8 specified? */
+ c = strstr(temp, "UTF-8");
+ if (c) {
+ free(temp);
+ return strdup("UTF-8");
+ }
+
+ /* dispense with temporary copy */
+ free(temp);
+
+ /* according to RFC2070, the accept-charsets attribute of the
+ * form element contains a space and/or comma separated list */
+ c = form->accept_charsets;
+
+ /** \todo an improvement would be to choose an encoding
+ * acceptable to the server which covers as much of the input
+ * values as possible. Additionally, we need to handle the
+ * case where none of the acceptable encodings cover all the
+ * textual input values. For now, we just extract the first
+ * element of the charset list
+ */
+ while (*c && !ascii_is_space(*c)) {
+ if (*c == ',')
+ break;
+ c++;
+ }
+
+ return strndup(form->accept_charsets, c - form->accept_charsets);
+}
+
+
+/**
+ * Construct multipart data list from 'successful' controls via the DOM.
+ *
+ * All text strings in the successful controls list will be in the charset most
+ * appropriate for submission. Therefore, no utf8_to_* processing should be
+ * performed upon them.
+ *
+ * \todo The chosen charset needs to be made available such that it can be
+ * included in the submission request (e.g. in the fetch's Content-Type header)
+ *
+ * See HTML 4.01 section 17.13.2.
+ *
+ * \note care is taken to abort even if the error is recoverable as it
+ * is not desirable to submit incomplete form data.
+ *
+ * \param[in] form form to search for successful controls
+ * \param[in] submit_button control used to submit the form, if any
+ * \param[out] fetch_data_out updated to point to linked list of
+ * fetch_multipart_data, NULL if no controls
+ * \return NSERROR_OK on success or appropriate error code
+ */
+static nserror
+form_dom_to_data(struct form *form,
+ struct form_control *submit_control,
+ struct fetch_multipart_data **fetch_data_out)
+{
+ nserror res = NSERROR_OK;
+ char *charset; /* form characterset */
+ dom_exception exp; /* the result from DOM operations */
+ dom_html_collection *elements = NULL; /* the dom form elements */
+ uint32_t element_count; /* the number of elements in the DOM form */
+ uint32_t element_idx; /* the index of thr enumerated element */
+ dom_node *element = NULL; /* the DOM form element */
+ dom_string *nodename = NULL; /* the DOM node name of the element */
+ struct fetch_multipart_data *fetch_data = NULL; /* fetch data list */
+ struct fetch_multipart_data **fetch_data_next = &fetch_data;
+ dom_html_element *submit_button;
+
+ /* obtain the submit_button DOM node from the control */
+ if (submit_control != NULL) {
+ submit_button = submit_control->node;
+ } else {
+ submit_button = NULL;
+ }
+
+ /** \todo Replace this call with something DOMish */
+ charset = form_acceptable_charset(form);
+ if (charset == NULL) {
+ NSLOG(netsurf, INFO, "failed to find charset");
+ return NSERROR_NOMEM;
+ }
+
+ /* obtain the form elements and count */
+ exp = dom_html_form_element_get_elements(form->node, &elements);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO, "Could not get form elements");
+ free(charset);
+ return NSERROR_DOM;
+ }
+
+ exp = dom_html_collection_get_length(elements, &element_count);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO, "Could not get form element count");
+ res = NSERROR_DOM;
+ goto form_dom_to_data_error;
+ }
+
+ for (element_idx = 0; element_idx < element_count; element_idx++) {
+ /* obtain a form element */
+ exp = dom_html_collection_item(elements, element_idx, &element);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO,
+ "retrieving form element %"PRIu32" failed with %d",
+ element_idx, exp);
+ res = NSERROR_DOM;
+ goto form_dom_to_data_error;
+ }
+
+ /* node name from element */
+ exp = dom_node_get_node_name(element, &nodename);
+ if (exp != DOM_NO_ERR) {
+ NSLOG(netsurf, INFO,
+ "getting element node name %"PRIu32" failed with %d",
+ element_idx, exp);
+ dom_node_unref(element);
+ res = NSERROR_DOM;
+ goto form_dom_to_data_error;
+ }
+
+ if (dom_string_isequal(nodename, corestring_dom_TEXTAREA)) {
+ /* Form element is HTMLTextAreaElement */
+ res = form_dom_to_data_textarea(
+ (dom_html_text_area_element *)element,
+ charset,
+ form->document_charset,
+ &fetch_data_next);
+
+ } else if (dom_string_isequal(nodename, corestring_dom_SELECT)) {
+ /* Form element is HTMLSelectElement */
+ res = form_dom_to_data_select(
+ (dom_html_select_element *)element,
+ charset,
+ form->document_charset,
+ &fetch_data_next);
+
+ } else if (dom_string_isequal(nodename, corestring_dom_INPUT)) {
+ /* Form element is HTMLInputElement */
+ res = form_dom_to_data_input(
+ (dom_html_input_element *)element,
+ charset,
+ form->document_charset,
+ &submit_button,
+ &fetch_data_next);
+
+ } else if (dom_string_isequal(nodename, corestring_dom_BUTTON)) {
+ /* Form element is HTMLButtonElement */
+ res = form_dom_to_data_button(
+ (dom_html_button_element *)element,
+ charset,
+ form->document_charset,
+ &submit_button,
+ &fetch_data_next);
+
+ } else {
+ /* Form element is not handled */
+ NSLOG(netsurf, INFO,
+ "Unhandled element type: %*s",
+ (int)dom_string_byte_length(nodename),
+ dom_string_data(nodename));
+ res = NSERROR_DOM;
+
+ }
+
+ dom_string_unref(nodename);
+ dom_node_unref(element);
+
+ /* abort form element enumeration on error */
+ if (res != NSERROR_OK) {
+ goto form_dom_to_data_error;
+ }
+ }
+
+ *fetch_data_out = fetch_data;
+ dom_html_collection_unref(elements);
+ free(charset);
+
+ return NSERROR_OK;
+
+form_dom_to_data_error:
+ fetch_multipart_data_destroy(fetch_data);
+ dom_html_collection_unref(elements);
+ free(charset);
+
+ return res;
+}
+
+/**
+ * Encode controls using application/x-www-form-urlencoded.
+ *
+ * \param[in] form form to which successful controls relate
+ * \param[in] control linked list of fetch_multipart_data
+ * \param[out] encoded_out URL-encoded form data
+ * \return NSERROR_OK on success and \a encoded_out updated else appropriate error code
+ */
+static nserror
+form_url_encode(struct form *form,
+ struct fetch_multipart_data *control,
+ char **encoded_out)
+{
+ char *name, *value;
+ char *s, *s2;
+ unsigned int len, len1, len_init;
+ nserror res;
+
+ s = malloc(1);
+
+ if (s == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ s[0] = '\0';
+ len_init = len = 0;
+
+ for (; control; control = control->next) {
+ res = url_escape(control->name, true, NULL, &name);
+ if (res != NSERROR_OK) {
+ free(s);
+ return res;
+ }
+
+ res = url_escape(control->value, true, NULL, &value);
+ if (res != NSERROR_OK) {
+ free(name);
+ free(s);
+ return res;
+ }
+
+ /* resize string to allow for new key/value pair,
+ * equals, amphersand and terminator
+ */
+ len1 = len + strlen(name) + strlen(value) + 2;
+ s2 = realloc(s, len1 + 1);
+ if (s2 == NULL) {
+ free(value);
+ free(name);
+ free(s);
+ return NSERROR_NOMEM;
+ }
+ s = s2;
+
+ snprintf(s + len, (len1 + 1) - len, "%s=%s&", name, value);
+ len = len1;
+ free(name);
+ free(value);
+ }
+
+ if (len > len_init) {
+ /* Replace trailing '&' */
+ s[len - 1] = '\0';
+ }
+
+ *encoded_out = s;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Callback for the select menus scroll
+ */
+static void
+form_select_menu_scroll_callback(void *client_data,
+ struct scrollbar_msg_data *scrollbar_data)
+{
+ struct form_control *control = client_data;
+ struct form_select_menu *menu = control->data.select.menu;
+ html_content *html = (html_content *)menu->c;
+
+ switch (scrollbar_data->msg) {
+ case SCROLLBAR_MSG_MOVED:
+ menu->callback(menu->client_data,
+ 0, 0,
+ menu->width,
+ menu->height);
+ break;
+ case SCROLLBAR_MSG_SCROLL_START:
+ {
+ struct rect rect = {
+ .x0 = scrollbar_data->x0,
+ .y0 = scrollbar_data->y0,
+ .x1 = scrollbar_data->x1,
+ .y1 = scrollbar_data->y1
+ };
+
+ browser_window_set_drag_type(html->bw,
+ DRAGGING_CONTENT_SCROLLBAR, &rect);
+
+ menu->scroll_capture = true;
+ }
+ break;
+ case SCROLLBAR_MSG_SCROLL_FINISHED:
+ menu->scroll_capture = false;
+
+ browser_window_set_drag_type(html->bw,
+ DRAGGING_NONE, NULL);
+ break;
+ default:
+ break;
+ }
+}
+
+
+/**
+ * Process a selection from a form select menu.
+ *
+ * \param html The html content handle for the form
+ * \param control form control with menu
+ * \param item index of item selected from the menu
+ * \return NSERROR_OK or appropriate error code.
+ */
+static nserror
+form__select_process_selection(html_content *html,
+ struct form_control *control,
+ int item)
+{
+ struct box *inline_box;
+ struct form_option *o;
+ int count;
+ nserror ret = NSERROR_OK;
+
+ assert(control != NULL);
+ assert(html != NULL);
+
+ /**
+ * \todo Even though the form code is effectively part of the html
+ * content handler, poking around inside contents is not good
+ */
+
+ inline_box = control->box->children->children;
+
+ for (count = 0, o = control->data.select.items;
+ o != NULL;
+ count++, o = o->next) {
+ if (!control->data.select.multiple && o->selected) {
+ o->selected = false;
+ dom_html_option_element_set_selected(o->node, false);
+ }
+
+ if (count == item) {
+ if (control->data.select.multiple) {
+ if (o->selected) {
+ o->selected = false;
+ dom_html_option_element_set_selected(
+ o->node, false);
+ control->data.select.num_selected--;
+ } else {
+ o->selected = true;
+ dom_html_option_element_set_selected(
+ o->node, true);
+ control->data.select.num_selected++;
+ }
+ } else {
+ dom_html_option_element_set_selected(
+ o->node, true);
+ o->selected = true;
+ }
+ }
+
+ if (o->selected) {
+ control->data.select.current = o;
+ }
+ }
+
+ talloc_free(inline_box->text);
+ inline_box->text = 0;
+
+ if (control->data.select.num_selected == 0) {
+ inline_box->text = talloc_strdup(html->bctx,
+ messages_get("Form_None"));
+ } else if (control->data.select.num_selected == 1) {
+ inline_box->text = talloc_strdup(html->bctx,
+ control->data.select.current->text);
+ } else {
+ inline_box->text = talloc_strdup(html->bctx,
+ messages_get("Form_Many"));
+ }
+
+ if (!inline_box->text) {
+ ret = NSERROR_NOMEM;
+ inline_box->length = 0;
+ } else {
+ inline_box->length = strlen(inline_box->text);
+ }
+ inline_box->width = control->box->width;
+
+ html__redraw_a_box(html, control->box);
+
+ return ret;
+}
+
+
+/**
+ * Handle a click on the area of the currently opened select menu.
+ *
+ * \param control the select menu which received the click
+ * \param x X coordinate of click
+ * \param y Y coordinate of click
+ */
+static void form_select_menu_clicked(struct form_control *control, int x, int y)
+{
+ struct form_select_menu *menu = control->data.select.menu;
+ struct form_option *option;
+ html_content *html = (html_content *)menu->c;
+ int line_height, line_height_with_spacing;
+ int item_bottom_y;
+ int scroll, i;
+
+ scroll = scrollbar_get_offset(menu->scrollbar);
+
+ line_height = menu->line_height;
+ line_height_with_spacing = line_height +
+ line_height * SELECT_LINE_SPACING;
+
+ option = control->data.select.items;
+ item_bottom_y = line_height_with_spacing;
+ i = 0;
+ while (option && item_bottom_y < scroll + y) {
+ item_bottom_y += line_height_with_spacing;
+ option = option->next;
+ i++;
+ }
+
+ if (option != NULL) {
+ form__select_process_selection(html, control, i);
+ }
+
+ menu->callback(menu->client_data, 0, 0, menu->width, menu->height);
+}
+
+
+/* exported interface documented in html/form_internal.h */
+void form_add_control(struct form *form, struct form_control *control)
+{
+ if (form == NULL) {
+ return;
+ }
+
+ control->form = form;
+
+ if (form->controls != NULL) {
+ assert(form->last_control);
+
+ form->last_control->next = control;
+ control->prev = form->last_control;
+ control->next = NULL;
+ form->last_control = control;
+ } else {
+ form->controls = form->last_control = control;
+ }
+}
+
+
+/* exported interface documented in html/form_internal.h */
+void form_free_control(struct form_control *control)
+{
+ struct form_control *c;
+ assert(control != NULL);
+
+ NSLOG(netsurf, INFO, "Control:%p name:%p value:%p initial:%p",
+ control, control->name, control->value, control->initial_value);
+ free(control->name);
+ free(control->value);
+ free(control->initial_value);
+ if (control->last_synced_value != NULL) {
+ free(control->last_synced_value);
+ }
+
+ if (control->type == GADGET_SELECT) {
+ struct form_option *option, *next;
+
+ for (option = control->data.select.items; option;
+ option = next) {
+ next = option->next;
+ NSLOG(netsurf, INFO,
+ "select option:%p text:%p value:%p", option,
+ option->text, option->value);
+ free(option->text);
+ free(option->value);
+ free(option);
+ }
+ if (control->data.select.menu != NULL) {
+ form_free_select_menu(control);
+ }
+ }
+
+ if (control->type == GADGET_TEXTAREA ||
+ control->type == GADGET_TEXTBOX ||
+ control->type == GADGET_PASSWORD) {
+
+ if (control->data.text.initial != NULL) {
+ dom_string_unref(control->data.text.initial);
+ }
+
+ if (control->data.text.ta != NULL) {
+ textarea_destroy(control->data.text.ta);
+ }
+ }
+
+ /* unlink the control from the form */
+ if (control->form != NULL) {
+ for (c = control->form->controls; c != NULL; c = c->next) {
+ if (c->next == control) {
+ c->next = control->next;
+ if (control->form->last_control == control)
+ control->form->last_control = c;
+ break;
+ }
+ if (c == control) {
+ /* can only happen if control was first control */
+ control->form->controls = control->next;
+ if (control->form->last_control == control)
+ control->form->controls =
+ control->form->last_control = NULL;
+ break;
+ }
+ }
+ }
+
+ if (control->node_value != NULL) {
+ dom_string_unref(control->node_value);
+ }
+
+ free(control);
+}
+
+
+/* exported interface documented in html/form_internal.h */
+bool form_add_option(struct form_control *control, char *value, char *text,
+ bool selected, void *node)
+{
+ struct form_option *option;
+
+ assert(control);
+ assert(control->type == GADGET_SELECT);
+
+ option = calloc(1, sizeof *option);
+ if (!option)
+ return false;
+
+ option->value = value;
+ option->text = text;
+
+ /* add to linked list */
+ if (control->data.select.items == 0)
+ control->data.select.items = option;
+ else
+ control->data.select.last_item->next = option;
+ control->data.select.last_item = option;
+
+ /* set selected */
+ if (selected && (control->data.select.num_selected == 0 ||
+ control->data.select.multiple)) {
+ option->selected = option->initial_selected = true;
+ control->data.select.num_selected++;
+ control->data.select.current = option;
+ }
+
+ control->data.select.num_items++;
+
+ option->node = node;
+
+ return true;
+}
+
+
+/* exported interface documented in html/form_internal.h */
+nserror
+form_open_select_menu(void *client_data,
+ struct form_control *control,
+ select_menu_redraw_callback callback,
+ struct content *c)
+{
+ int line_height_with_spacing;
+ struct box *box;
+ plot_font_style_t fstyle;
+ int total_height;
+ struct form_select_menu *menu;
+ html_content *html = (html_content *)c;
+ nserror res;
+
+ /* if the menu is opened for the first time */
+ if (control->data.select.menu == NULL) {
+
+ menu = calloc(1, sizeof (struct form_select_menu));
+ if (menu == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ control->data.select.menu = menu;
+
+ box = control->box;
+
+ menu->width = box->width +
+ box->border[RIGHT].width + box->padding[RIGHT] +
+ box->border[LEFT].width + box->padding[LEFT];
+
+ font_plot_style_from_css(&html->unit_len_ctx,
+ control->box->style, &fstyle);
+ menu->f_size = fstyle.size;
+
+ menu->line_height = FIXTOINT(FDIV((FMUL(FLTTOFIX(1.2),
+ FMUL(html->unit_len_ctx.device_dpi,
+ INTTOFIX(fstyle.size / PLOT_STYLE_SCALE)))),
+ F_72));
+
+ line_height_with_spacing = menu->line_height +
+ menu->line_height *
+ SELECT_LINE_SPACING;
+
+ total_height = control->data.select.num_items *
+ line_height_with_spacing;
+ menu->height = total_height;
+
+ if (menu->height > MAX_SELECT_HEIGHT) {
+ menu->height = MAX_SELECT_HEIGHT;
+ }
+
+ menu->client_data = client_data;
+ menu->callback = callback;
+ res = scrollbar_create(false,
+ menu->height,
+ total_height,
+ menu->height,
+ control,
+ form_select_menu_scroll_callback,
+ &(menu->scrollbar));
+ if (res != NSERROR_OK) {
+ control->data.select.menu = NULL;
+ free(menu);
+ return res;
+ }
+ menu->c = c;
+ } else {
+ menu = control->data.select.menu;
+ }
+
+ menu->callback(client_data, 0, 0, menu->width, menu->height);
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in html/form_internal.h */
+void form_free_select_menu(struct form_control *control)
+{
+ if (control->data.select.menu->scrollbar != NULL)
+ scrollbar_destroy(control->data.select.menu->scrollbar);
+ free(control->data.select.menu);
+ control->data.select.menu = NULL;
+}
+
+
+/* exported interface documented in html/form_internal.h */
+bool
+form_redraw_select_menu(struct form_control *control,
+ int x, int y,
+ float scale,
+ const struct rect *clip,
+ const struct redraw_context *ctx)
+{
+ struct box *box;
+ struct form_select_menu *menu = control->data.select.menu;
+ struct form_option *option;
+ int line_height, line_height_with_spacing;
+ int width, height;
+ int x0, y0, x1, scrollbar_x, y1, y2, y3;
+ int item_y;
+ int text_pos_offset, text_x;
+ int scrollbar_width = SCROLLBAR_WIDTH;
+ int i;
+ int scroll;
+ int x_cp, y_cp;
+ struct rect r;
+ struct rect rect;
+ nserror res;
+
+ box = control->box;
+
+ x_cp = x;
+ y_cp = y;
+ width = menu->width;
+ height = menu->height;
+ line_height = menu->line_height;
+
+ line_height_with_spacing = line_height +
+ line_height * SELECT_LINE_SPACING;
+ scroll = scrollbar_get_offset(menu->scrollbar);
+
+ if (scale != 1.0) {
+ x *= scale;
+ y *= scale;
+ width *= scale;
+ height *= scale;
+ scrollbar_width *= scale;
+
+ i = scroll / line_height_with_spacing;
+ scroll -= i * line_height_with_spacing;
+ line_height *= scale;
+ line_height_with_spacing *= scale;
+ scroll *= scale;
+ scroll += i * line_height_with_spacing;
+ }
+
+
+ x0 = x;
+ y0 = y;
+ x1 = x + width - 1;
+ y1 = y + height - 1;
+ scrollbar_x = x1 - scrollbar_width;
+
+ r.x0 = x0;
+ r.y0 = y0;
+ r.x1 = x1 + 1;
+ r.y1 = y1 + 1;
+ res = ctx->plot->clip(ctx, &r);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+
+ rect.x0 = x0;
+ rect.y0 = y0;
+ rect.x1 = x1;
+ rect.y1 = y1;
+ res = ctx->plot->rectangle(ctx, plot_style_stroke_darkwbasec, &rect);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+
+ x0 = x0 + SELECT_BORDER_WIDTH;
+ y0 = y0 + SELECT_BORDER_WIDTH;
+ x1 = x1 - SELECT_BORDER_WIDTH;
+ y1 = y1 - SELECT_BORDER_WIDTH;
+ height = height - 2 * SELECT_BORDER_WIDTH;
+
+ r.x0 = x0;
+ r.y0 = y0;
+ r.x1 = x1 + 1;
+ r.y1 = y1 + 1;
+ res = ctx->plot->clip(ctx, &r);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+
+ res = ctx->plot->rectangle(ctx, plot_style_fill_lightwbasec, &r);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+
+ option = control->data.select.items;
+ item_y = line_height_with_spacing;
+
+ while (item_y < scroll) {
+ option = option->next;
+ item_y += line_height_with_spacing;
+ }
+ item_y -= line_height_with_spacing;
+ text_pos_offset = y - scroll +
+ (int) (line_height * (0.75 + SELECT_LINE_SPACING));
+ text_x = x + (box->border[LEFT].width + box->padding[LEFT]) * scale;
+
+ plot_fstyle_entry.size = menu->f_size;
+
+ while (option && item_y - scroll < height) {
+
+ if (option->selected) {
+ y2 = y + item_y - scroll;
+ y3 = y + item_y + line_height_with_spacing - scroll;
+
+ rect.x0 = x0;
+ rect.y0 = y0 > y2 ? y0 : y2;
+ rect.x1 = scrollbar_x + 1;
+ rect.y1 = y3 < y1 + 1 ? y3 : y1 + 1;
+ res = ctx->plot->rectangle(ctx, &plot_style_fill_selected, &rect);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+ }
+
+ y2 = text_pos_offset + item_y;
+ res = ctx->plot->text(ctx,
+ &plot_fstyle_entry,
+ text_x, y2,
+ option->text, strlen(option->text));
+ if (res != NSERROR_OK) {
+ return false;
+ }
+
+ item_y += line_height_with_spacing;
+ option = option->next;
+ }
+
+ res = scrollbar_redraw(menu->scrollbar,
+ x_cp + menu->width - SCROLLBAR_WIDTH,
+ y_cp,
+ clip, scale, ctx);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+
+ return true;
+}
+
+
+/* private interface described in html/form_internal.h */
+bool
+form_clip_inside_select_menu(struct form_control *control,
+ float scale,
+ const struct rect *clip)
+{
+ struct form_select_menu *menu = control->data.select.menu;
+ int width, height;
+
+
+ width = menu->width;
+ height = menu->height;
+
+ if (scale != 1.0) {
+ width *= scale;
+ height *= scale;
+ }
+
+ if (clip->x0 >= 0 &&
+ clip->x1 <= width &&
+ clip->y0 >= 0 &&
+ clip->y1 <= height)
+ return true;
+
+ return false;
+}
+
+
+/* exported interface documented in netsurf/form.h */
+nserror form_select_process_selection(struct form_control *control, int item)
+{
+ assert(control != NULL);
+
+ return form__select_process_selection(control->html, control, item);
+}
+
+
+/* exported interface documented in netsurf/form.h */
+struct form_option *
+form_select_get_option(struct form_control *control, int item)
+{
+ struct form_option *opt;
+
+ opt = control->data.select.items;
+ while ((opt != NULL) && (item > 0)) {
+ opt = opt->next;
+ item--;
+ }
+ return opt;
+}
+
+
+/* exported interface documented in netsurf/form.h */
+char *form_control_get_name(struct form_control *control)
+{
+ return control->name;
+}
+
+
+/* exported interface documented in netsurf/form.h */
+nserror form_control_bounding_rect(struct form_control *control, struct rect *r)
+{
+ box_bounds( control->box, r );
+ return NSERROR_OK;
+}
+
+
+/* private interface described in html/form_internal.h */
+const char *
+form_select_mouse_action(struct form_control *control,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ struct form_select_menu *menu = control->data.select.menu;
+ int x0, y0, x1, y1, scrollbar_x;
+ const char *status = NULL;
+ bool multiple = control->data.select.multiple;
+
+ x0 = 0;
+ y0 = 0;
+ x1 = menu->width;
+ y1 = menu->height;
+ scrollbar_x = x1 - SCROLLBAR_WIDTH;
+
+ if (menu->scroll_capture ||
+ (x > scrollbar_x && x < x1 && y > y0 && y < y1)) {
+ /* The scroll is currently capturing all events or the mouse
+ * event is taking place on the scrollbar widget area
+ */
+ x -= scrollbar_x;
+ return scrollbar_mouse_status_to_message(
+ scrollbar_mouse_action(menu->scrollbar,
+ mouse, x, y));
+ }
+
+
+ if (x > x0 && x < scrollbar_x && y > y0 && y < y1) {
+ /* over option area */
+
+ if (mouse & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2))
+ /* button 1 or 2 click */
+ form_select_menu_clicked(control, x, y);
+
+ if (!(mouse & BROWSER_MOUSE_CLICK_1 && !multiple))
+ /* anything but a button 1 click over a single select
+ menu */
+ status = messages_get(control->data.select.multiple ?
+ "SelectMClick" : "SelectClick");
+
+ } else if (!(mouse & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2)))
+ /* if not a button 1 or 2 click*/
+ status = messages_get("SelectClose");
+
+ return status;
+}
+
+
+/* private interface described in html/form_internal.h */
+void
+form_select_mouse_drag_end(struct form_control *control,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ int x0, y0, x1, y1;
+ int box_x, box_y;
+ struct box *box;
+ struct form_select_menu *menu = control->data.select.menu;
+
+ box = control->box;
+
+ /* Get global coords of scrollbar */
+ box_coords(box, &box_x, &box_y);
+ box_x -= box->border[LEFT].width;
+ box_y += box->height + box->border[BOTTOM].width +
+ box->padding[BOTTOM] + box->padding[TOP];
+
+ /* Get drag end coords relative to scrollbar */
+ x = x - box_x;
+ y = y - box_y;
+
+ if (menu->scroll_capture) {
+ x -= menu->width - SCROLLBAR_WIDTH;
+ scrollbar_mouse_drag_end(menu->scrollbar, mouse, x, y);
+ return;
+ }
+
+ x0 = 0;
+ y0 = 0;
+ x1 = menu->width;
+ y1 = menu->height;
+
+
+ if (x > x0 && x < x1 - SCROLLBAR_WIDTH && y > y0 && y < y1) {
+ /* handle drag end above the option area like a regular click */
+ form_select_menu_clicked(control, x, y);
+ }
+}
+
+
+/* private interface described in html/form_internal.h */
+void form_select_get_dimensions(struct form_control *control,
+ int *width, int *height)
+{
+ *width = control->data.select.menu->width;
+ *height = control->data.select.menu->height;
+}
+
+
+/* private interface described in html/form_internal.h */
+void form_select_menu_callback(void *client_data,
+ int x, int y, int width, int height)
+{
+ html_content *html = client_data;
+ int menu_x, menu_y;
+ struct box *box;
+
+ box = html->visible_select_menu->box;
+ box_coords(box, &menu_x, &menu_y);
+
+ menu_x -= box->border[LEFT].width;
+ menu_y += box->height + box->border[BOTTOM].width +
+ box->padding[BOTTOM] +
+ box->padding[TOP];
+ content__request_redraw((struct content *)html, menu_x + x, menu_y + y,
+ width, height);
+}
+
+
+/* private interface described in html/form_internal.h */
+void form_radio_set(struct form_control *radio)
+{
+ struct form_control *control;
+
+ assert(radio);
+ if (!radio->form)
+ return;
+
+ if (radio->selected)
+ return;
+
+ /* Clear selected state for other controls in
+ * the same radio button group */
+ for (control = radio->form->controls;
+ control != NULL;
+ control = control->next) {
+ /* Only interested in radio inputs */
+ if (control->type != GADGET_RADIO)
+ continue;
+
+ /* Ignore ourself */
+ if (control == radio)
+ continue;
+
+ /* Ignore inputs where:
+ * a) this or the other control have no name attribute
+ * b) this or the other control have an empty name attribute
+ * c) the control names do not match
+ */
+ if ((control->name == NULL) ||
+ (radio->name == NULL) ||
+ (control->name[0] == '\0') ||
+ (radio->name[0] == '\0') ||
+ strcmp(control->name, radio->name) != 0)
+ continue;
+
+ /* Other control is in the same radio button group: clear its
+ * selected state */
+ if (control->selected) {
+ control->selected = false;
+ dom_html_input_element_set_checked(control->node, false);
+ html__redraw_a_box(radio->html, control->box);
+ }
+ }
+
+ radio->selected = true;
+ dom_html_input_element_set_checked(radio->node, true);
+ html__redraw_a_box(radio->html, radio->box);
+}
+
+
+/* private interface described in html/form_internal.h */
+nserror
+form_submit(nsurl *page_url,
+ struct browser_window *target,
+ struct form *form,
+ struct form_control *submit_button)
+{
+ nserror res;
+ char *data = NULL; /* encoded form data */
+ struct fetch_multipart_data *success = NULL; /* gcc is incapable of correctly reasoning about use and generates "maybe used uninitialised" warnings */
+ nsurl *action_url;
+ nsurl *query_url;
+
+ assert(form != NULL);
+
+ /* obtain list of controls from DOM */
+ res = form_dom_to_data(form, submit_button, &success);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* Decompose action */
+ res = nsurl_create(form->action, &action_url);
+ if (res != NSERROR_OK) {
+ fetch_multipart_data_destroy(success);
+ return res;
+ }
+
+ switch (form->method) {
+ case method_GET:
+ res = form_url_encode(form, success, &data);
+ if (res == NSERROR_OK) {
+ /* Replace query segment */
+ res = nsurl_replace_query(action_url, data, &query_url);
+ if (res == NSERROR_OK) {
+ res = browser_window_navigate(target,
+ query_url,
+ page_url,
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+
+ nsurl_unref(query_url);
+ }
+ free(data);
+ }
+ break;
+
+ case method_POST_URLENC:
+ res = form_url_encode(form, success, &data);
+ if (res == NSERROR_OK) {
+ res = browser_window_navigate(target,
+ action_url,
+ page_url,
+ BW_NAVIGATE_HISTORY,
+ data,
+ NULL,
+ NULL);
+ free(data);
+ }
+ break;
+
+ case method_POST_MULTIPART:
+ res = browser_window_navigate(target,
+ action_url,
+ page_url,
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ success,
+ NULL);
+
+ break;
+ }
+
+ nsurl_unref(action_url);
+ fetch_multipart_data_destroy(success);
+
+ return res;
+}
+
+
+/* exported interface documented in html/form_internal.h */
+void form_gadget_update_value(struct form_control *control, char *value)
+{
+ switch (control->type) {
+ case GADGET_HIDDEN:
+ case GADGET_TEXTBOX:
+ case GADGET_TEXTAREA:
+ case GADGET_PASSWORD:
+ case GADGET_FILE:
+ if (control->value != NULL) {
+ free(control->value);
+ }
+ control->value = value;
+ if (control->node != NULL) {
+ dom_exception err;
+ dom_string *str;
+ err = dom_string_create((uint8_t *)value,
+ strlen(value), &str);
+ if (err == DOM_NO_ERR) {
+ if (control->type == GADGET_TEXTAREA)
+ err = dom_html_text_area_element_set_value(
+ (dom_html_text_area_element *)(control->node),
+ str);
+ else
+ err = dom_html_input_element_set_value(
+ (dom_html_input_element *)(control->node),
+ str);
+ dom_string_unref(str);
+ }
+ }
+ break;
+ default:
+ /* Do nothing */
+ break;
+ }
+
+ /* Finally, sync this with the DOM */
+ form_gadget_sync_with_dom(control);
+}
+
+
+/* Exported API, see html/form_internal.h */
+void
+form_gadget_sync_with_dom(struct form_control *control)
+{
+ dom_exception exc;
+ dom_string *value = NULL;
+ bool changed_dom = false;
+
+ if (control->syncing ||
+ (control->type != GADGET_TEXTBOX &&
+ control->type != GADGET_PASSWORD &&
+ control->type != GADGET_HIDDEN &&
+ control->type != GADGET_TEXTAREA)) {
+ /* Not a control we support, or the control is already
+ * mid-sync so we don't want to disrupt that
+ */
+ return;
+ }
+
+ control->syncing = true;
+
+ /* If we've changed value, sync that toward the DOM */
+ if ((control->last_synced_value == NULL &&
+ control->value != NULL &&
+ control->value[0] != '\0') ||
+ (control->last_synced_value != NULL &&
+ control->value != NULL &&
+ strcmp(control->value, control->last_synced_value) != 0)) {
+ char *dup = strdup(control->value);
+ if (dup == NULL) {
+ goto out;
+ }
+ if (control->last_synced_value != NULL) {
+ free(control->last_synced_value);
+ }
+ control->last_synced_value = dup;
+ exc = dom_string_create((uint8_t *)(control->value),
+ strlen(control->value), &value);
+ if (exc != DOM_NO_ERR) {
+ goto out;
+ }
+ if (control->node_value != NULL) {
+ dom_string_unref(control->node_value);
+ }
+ control->node_value = value;
+ value = NULL;
+ if (control->type == GADGET_TEXTAREA) {
+ exc = dom_html_text_area_element_set_value(control->node, control->node_value);
+ } else {
+ exc = dom_html_input_element_set_value(control->node, control->node_value);
+ }
+ if (exc != DOM_NO_ERR) {
+ goto out;
+ }
+ changed_dom = true;
+ }
+
+ /* Now check if the DOM has changed since our last go */
+ if (control->type == GADGET_TEXTAREA) {
+ exc = dom_html_text_area_element_get_value(control->node, &value);
+ } else {
+ exc = dom_html_input_element_get_value(control->node, &value);
+ }
+
+ if (exc != DOM_NO_ERR) {
+ /* Nothing much we can do here */
+ goto out;
+ }
+
+ if (!dom_string_isequal(control->node_value, value)) {
+ /* The DOM has changed */
+ if (!changed_dom) {
+ /* And it wasn't us */
+ char *value_s = strndup(
+ dom_string_data(value),
+ dom_string_byte_length(value));
+ char *dup = NULL;
+ if (value_s == NULL) {
+ goto out;
+ }
+ dup = strdup(value_s);
+ if (dup == NULL) {
+ free(value_s);
+ goto out;
+ }
+ free(control->value);
+ control->value = value_s;
+ free(control->last_synced_value);
+ control->last_synced_value = dup;
+ if (control->type != GADGET_HIDDEN &&
+ control->data.text.ta != NULL) {
+ textarea_set_text(control->data.text.ta,
+ value_s);
+ }
+ }
+ control->node_value = value;
+ value = NULL;
+ }
+
+out:
+ if (value != NULL)
+ dom_string_unref(value);
+ control->syncing = false;
+}
+
+
+/* exported interface documented in html/form_internal.h */
+struct form *
+form_new(void *node,
+ const char *action,
+ const char *target,
+ form_method method,
+ const char *charset,
+ const char *doc_charset)
+{
+ struct form *form;
+
+ form = calloc(1, sizeof *form);
+ if (!form)
+ return NULL;
+
+ form->action = strdup(action != NULL ? action : "");
+ if (form->action == NULL) {
+ free(form);
+ return NULL;
+ }
+
+ form->target = target != NULL ? strdup(target) : NULL;
+ if (target != NULL && form->target == NULL) {
+ free(form->action);
+ free(form);
+ return NULL;
+ }
+
+ form->method = method;
+
+ form->accept_charsets = charset != NULL ? strdup(charset) : NULL;
+ if (charset != NULL && form->accept_charsets == NULL) {
+ free(form->target);
+ free(form->action);
+ free(form);
+ return NULL;
+ }
+
+ form->document_charset = doc_charset != NULL ? strdup(doc_charset)
+ : NULL;
+ if (doc_charset && form->document_charset == NULL) {
+ free(form->accept_charsets);
+ free(form->target);
+ free(form->action);
+ free(form);
+ return NULL;
+ }
+
+ form->node = node;
+
+ return form;
+}
+
+
+/* exported interface documented in html/form_internal.h */
+void form_free(struct form *form)
+{
+ struct form_control *c, *d;
+
+ for (c = form->controls; c != NULL; c = d) {
+ d = c->next;
+
+ form_free_control(c);
+ }
+
+ free(form->action);
+ free(form->target);
+ free(form->accept_charsets);
+ free(form->document_charset);
+
+ free(form);
+}
+
+
+/* exported interface documented in html/form_internal.h */
+struct form_control *form_new_control(void *node, form_control_type type)
+{
+ struct form_control *control;
+
+ control = calloc(1, sizeof *control);
+ if (control == NULL)
+ return NULL;
+
+ control->node = node;
+ control->type = type;
+
+ return control;
+}
diff --git a/render/form_internal.h b/content/handlers/html/form_internal.h
index 0ffb6b46c..292a5df44 100644
--- a/render/form_internal.h
+++ b/content/handlers/html/form_internal.h
@@ -18,11 +18,11 @@
/**
* \file
- * Interface to form handling functions internal to render.
+ * Interface to form handling functions internal to HTML content handler.
*/
-#ifndef _NETSURF_RENDER_FORM_INTERNAL_H_
-#define _NETSURF_RENDER_FORM_INTERNAL_H_
+#ifndef NETSURF_HTML_FORM_INTERNAL_H
+#define NETSURF_HTML_FORM_INTERNAL_H
#include <stdbool.h>
@@ -72,6 +72,8 @@ struct image_input_coords {
/** Form control. */
struct form_control {
void *node; /**< Corresponding DOM node */
+ struct dom_string *node_value; /**< The last value sync'd with the DOM */
+ bool syncing; /**< Set if a DOM sync is in-progress */
struct html_content *html; /**< HTML content containing control */
form_control_type type; /**< Type of control */
@@ -81,6 +83,7 @@ struct form_control {
char *name; /**< Control name */
char *value; /**< Current value of control */
char *initial_value; /**< Initial value of control */
+ char *last_synced_value; /**< The last value sync'd to the DOM */
bool disabled; /**< Whether control is disabled */
struct box *box; /**< Box for control */
@@ -177,6 +180,7 @@ struct form *form_new(void *node, const char *action, const char *target,
*/
void form_free(struct form *form);
+
/**
* Create a struct form_control.
*
@@ -186,54 +190,51 @@ void form_free(struct form *form);
*/
struct form_control *form_new_control(void *node, form_control_type type);
-void form_add_control(struct form *form, struct form_control *control);
-void form_free_control(struct form_control *control);
-bool form_add_option(struct form_control *control, char *value, char *text,
- bool selected, void *node);
-bool form_successful_controls(struct form *form,
- struct form_control *submit_button,
- struct fetch_multipart_data **successful_controls);
/**
- * Identify 'successful' controls via the DOM.
+ * Add a control to the list of controls in a form.
*
- * All text strings in the successful controls list will be in the charset most
- * appropriate for submission. Therefore, no utf8_to_* processing should be
- * performed upon them.
- *
- * \todo The chosen charset needs to be made available such that it can be
- * included in the submission request (e.g. in the fetch's Content-Type header)
+ * \param form The form to add the control to
+ * \param control The control to add
+ */
+void form_add_control(struct form *form, struct form_control *control);
+
+
+/**
+ * Free a struct form_control.
*
- * See HTML 4.01 section 17.13.2.
+ * \param control structure to free
+ */
+void form_free_control(struct form_control *control);
+
+
+/**
+ * Add an option to a form select control.
*
- * \param[in] form form to search for successful controls
- * \param[in] submit_button control used to submit the form, if any
- * \param[out] successful_controls updated to point to linked list of
- * fetch_multipart_data, 0 if no controls
+ * \param control form control of type GADGET_SELECT
+ * \param value value of option, used directly (not copied)
+ * \param text text for option, used directly (not copied)
+ * \param selected this option is selected
+ * \param node the DOM node this option is associated with
* \return true on success, false on memory exhaustion
*/
-bool form_successful_controls_dom(struct form *form,
- struct form_control *submit_button,
- struct fetch_multipart_data **successful_controls);
+bool form_add_option(struct form_control *control, char *value, char *text,
+ bool selected, void *node);
/**
* Open a select menu for a select form control, creating it if necessary.
*
- * \param client_data data passed to the redraw callback
- * \param control The select form control for which the menu is being opened
- * \param redraw_callback The callback to redraw the select menu.
- * \param c The content the select menu is opening for.
- * \return false on memory exhaustion, true otherwise
+ * \param client_data data passed to the redraw callback
+ * \param control The select form control for which the menu is being opened
+ * \param redraw_callback The callback to redraw the select menu.
+ * \param c The content the select menu is opening for.
+ * \return NSERROR_OK on sucess else error code.
*/
-bool form_open_select_menu(void *client_data,
+nserror form_open_select_menu(void *client_data,
struct form_control *control,
select_menu_redraw_callback redraw_callback,
- struct content *c);
-
-
-void form_select_menu_callback(void *client_data,
- int x, int y, int width, int height);
+ struct content *c);
/**
@@ -260,18 +261,100 @@ bool form_redraw_select_menu(struct form_control *control, int x, int y,
float scale, const struct rect *clip,
const struct redraw_context *ctx);
+
+/**
+ * Check whether a clipping rectangle is completely contained in the
+ * select menu.
+ *
+ * \param control the select menu to check the clipping rectangle for
+ * \param scale the current browser window scale
+ * \param clip the clipping rectangle
+ * \return true if inside false otherwise
+ */
bool form_clip_inside_select_menu(struct form_control *control, float scale,
const struct rect *clip);
+
+
+/**
+ * Handle mouse action for the currently opened select menu.
+ *
+ * \param control the select menu which received the mouse action
+ * \param mouse current mouse state
+ * \param x X coordinate of click
+ * \param y Y coordinate of click
+ * \return text for the browser status bar or NULL if the menu has to be closed
+ */
const char *form_select_mouse_action(struct form_control *control,
enum browser_mouse_state mouse, int x, int y);
+
+
+/**
+ * Handle mouse drag end for the currently opened select menu.
+ *
+ * \param control the select menu which received the mouse drag end
+ * \param mouse current mouse state
+ * \param x X coordinate of drag end
+ * \param y Y coordinate of drag end
+ */
void form_select_mouse_drag_end(struct form_control *control,
enum browser_mouse_state mouse, int x, int y);
+
+
+/**
+ * Get the dimensions of a select menu.
+ *
+ * \param control the select menu to get the dimensions of
+ * \param width gets updated to menu width
+ * \param height gets updated to menu height
+ */
void form_select_get_dimensions(struct form_control *control,
int *width, int *height);
-void form_submit(struct nsurl *page_url, struct browser_window *target,
- struct form *form, struct form_control *submit_button);
+
+
+/**
+ * Callback for the core select menu.
+ */
+void form_select_menu_callback(void *client_data,
+ int x, int y, int width, int height);
+
+
+/**
+ * Set a radio form control and clear the others in the group.
+ *
+ * \param radio form control of type GADGET_RADIO
+ */
void form_radio_set(struct form_control *radio);
+/**
+ * navigate browser window based on form submission.
+ *
+ * \param page_url content url
+ * \param target The browsing context in which the navigation will occour.
+ * \param form The form to submit.
+ * \param submit_button The control used to submit the form.
+ */
+nserror form_submit(struct nsurl *page_url, struct browser_window *target,
+ struct form *form, struct form_control *submit_button);
+
+
+/**
+ * Update gadget value.
+ */
void form_gadget_update_value(struct form_control *control, char *value);
+
+/**
+ * Synchronise this gadget with its associated DOM node.
+ *
+ * If the DOM has changed and the gadget has not, the DOM's new value is
+ * imported into the gadget. If the gadget's value has changed and the DOM's
+ * has not, the gadget's value is pushed into the DOM.
+ * If both have changed, the gadget's value wins.
+ *
+ * \param control The form gadget to synchronise
+ *
+ * \note Currently this will only synchronise input gadgets (text/password)
+ */
+void form_gadget_sync_with_dom(struct form_control *control);
+
#endif
diff --git a/render/html_forms.c b/content/handlers/html/forms.c
index 39bc690d9..4669154e9 100644
--- a/render/html_forms.c
+++ b/content/handlers/html/forms.c
@@ -16,14 +16,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+/**
+ * \file
+ * HTML form handling implementation
+ */
+
+#include <string.h>
+
#include "utils/config.h"
#include "utils/corestrings.h"
#include "utils/log.h"
-#include "render/form_internal.h"
-#include "render/html_internal.h"
+#include "html/form_internal.h"
+#include "html/private.h"
-/**
+/**
* process form element from dom
*/
static struct form *
@@ -386,7 +393,18 @@ parse_input_element(struct form *forms, dom_html_input_element *input)
control = NULL;
goto out;
}
+
+ control->last_synced_value = strdup(control->value);
+ if (control->last_synced_value == NULL) {
+ form_free_control(control);
+ control = NULL;
+ goto out;
+ }
+
+ control->node_value = dom_string_ref(ds_value);
}
+ /* Force the gadget and DOM to be in sync */
+ form_gadget_sync_with_dom(control);
}
if (form != NULL && control != NULL)
@@ -523,8 +541,8 @@ invent_fake_gadget(dom_node *node)
}
/* documented in html_internal.h */
-struct form_control *html_forms_get_control_for_node(struct form *forms,
- dom_node *node)
+struct form_control *
+html_forms_get_control_for_node(struct form *forms, dom_node *node)
{
struct form *f;
struct form_control *ctl = NULL;
@@ -572,4 +590,3 @@ struct form_control *html_forms_get_control_for_node(struct form *forms,
return ctl;
}
-
diff --git a/render/html.c b/content/handlers/html/html.c
index b7d7aa313..82f5f1388 100644
--- a/render/html.c
+++ b/content/handlers/html/html.c
@@ -19,7 +19,7 @@
/**
* \file
- * Content for text/html (implementation).
+ * Implementation of HTML content handling.
*/
#include <assert.h>
@@ -44,9 +44,12 @@
#include "netsurf/content.h"
#include "netsurf/browser_window.h"
#include "netsurf/utf8.h"
+#include "netsurf/keypress.h"
#include "netsurf/layout.h"
#include "netsurf/misc.h"
#include "content/hlcache.h"
+#include "content/content_factory.h"
+#include "content/textsearch.h"
#include "desktop/selection.h"
#include "desktop/scrollbar.h"
#include "desktop/textarea.h"
@@ -54,12 +57,20 @@
#include "javascript/js.h"
#include "desktop/gui_internal.h"
-#include "render/box.h"
-#include "render/form_internal.h"
-#include "render/html_internal.h"
-#include "render/imagemap.h"
-#include "render/layout.h"
-#include "render/search.h"
+#include "html/html.h"
+#include "html/private.h"
+#include "html/dom_event.h"
+#include "html/css.h"
+#include "html/object.h"
+#include "html/html_save.h"
+#include "html/interaction.h"
+#include "html/box.h"
+#include "html/box_construct.h"
+#include "html/box_inspect.h"
+#include "html/form_internal.h"
+#include "html/imagemap.h"
+#include "html/layout.h"
+#include "html/textselection.h"
#define CHUNK 4096
@@ -74,9 +85,31 @@ static const char *html_types[] = {
"text/html"
};
+/**
+ * Fire an event at the DOM
+ *
+ * Helper that swallows DOM errors.
+ *
+ * \param[in] event the event to fire at the DOM
+ * \param[in] target the event target
+ * \return true on success
+ */
+static bool fire_dom_event(dom_event *event, dom_node *target)
+{
+ dom_exception exc;
+ bool result;
+
+ exc = dom_event_target_dispatch_event(target, event, &result);
+ if (exc != DOM_NO_ERR) {
+ return false;
+ }
+
+ return result;
+}
+
/* Exported interface, see html_internal.h */
-bool fire_dom_event(dom_string *type, dom_node *target,
- bool bubbles, bool cancelable)
+bool fire_generic_dom_event(dom_string *type, dom_node *target,
+ bool bubbles, bool cancelable)
{
dom_exception exc;
dom_event *evt;
@@ -90,11 +123,86 @@ bool fire_dom_event(dom_string *type, dom_node *target,
return false;
}
NSLOG(netsurf, INFO, "Dispatching '%*s' against %p",
- dom_string_length(type), dom_string_data(type), target);
- exc = dom_event_target_dispatch_event(target, evt, &result);
+ (int)dom_string_length(type), dom_string_data(type), target);
+ result = fire_dom_event(evt, target);
+ dom_event_unref(evt);
+ return result;
+}
+
+/* Exported interface, see html_internal.h */
+bool fire_dom_keyboard_event(dom_string *type, dom_node *target,
+ bool bubbles, bool cancelable, uint32_t key)
+{
+ bool is_special = key <= 0x001F || (0x007F <= key && key <= 0x009F);
+ dom_string *dom_key = NULL;
+ dom_keyboard_event *evt;
+ dom_exception exc;
+ bool result;
+
+ if (is_special) {
+ switch (key) {
+ case NS_KEY_ESCAPE:
+ dom_key = dom_string_ref(corestring_dom_Escape);
+ break;
+ case NS_KEY_LEFT:
+ dom_key = dom_string_ref(corestring_dom_ArrowLeft);
+ break;
+ case NS_KEY_RIGHT:
+ dom_key = dom_string_ref(corestring_dom_ArrowRight);
+ break;
+ case NS_KEY_UP:
+ dom_key = dom_string_ref(corestring_dom_ArrowUp);
+ break;
+ case NS_KEY_DOWN:
+ dom_key = dom_string_ref(corestring_dom_ArrowDown);
+ break;
+ case NS_KEY_PAGE_UP:
+ dom_key = dom_string_ref(corestring_dom_PageUp);
+ break;
+ case NS_KEY_PAGE_DOWN:
+ dom_key = dom_string_ref(corestring_dom_PageDown);
+ break;
+ case NS_KEY_TEXT_START:
+ dom_key = dom_string_ref(corestring_dom_Home);
+ break;
+ case NS_KEY_TEXT_END:
+ dom_key = dom_string_ref(corestring_dom_End);
+ break;
+ default:
+ dom_key = NULL;
+ break;
+ }
+ } else {
+ char utf8[6];
+ size_t length = utf8_from_ucs4(key, utf8);
+ utf8[length] = '\0';
+
+ exc = dom_string_create((const uint8_t *)utf8, strlen(utf8),
+ &dom_key);
+ if (exc != DOM_NO_ERR) {
+ return exc;
+ }
+ }
+
+ exc = dom_keyboard_event_create(&evt);
if (exc != DOM_NO_ERR) {
- result = false;
+ dom_string_unref(dom_key);
+ return false;
}
+
+ exc = dom_keyboard_event_init(evt, type, bubbles, cancelable, NULL,
+ dom_key, NULL, DOM_KEY_LOCATION_STANDARD, false,
+ false, false, false, false, false);
+ dom_string_unref(dom_key);
+ if (exc != DOM_NO_ERR) {
+ dom_event_unref(evt);
+ return false;
+ }
+
+ NSLOG(netsurf, INFO, "Dispatching '%*s' against %p",
+ (int)dom_string_length(type), dom_string_data(type), target);
+
+ result = fire_dom_event((dom_event *) evt, target);
dom_event_unref(evt);
return result;
}
@@ -111,16 +219,18 @@ static void html_box_convert_done(html_content *c, bool success)
dom_exception exc; /* returned by libdom functions */
dom_node *html;
- NSLOG(netsurf, INFO, "Done XML to box (%p)", c);
+ NSLOG(netsurf, INFO, "DOM to box conversion complete (content %p)", c);
+
+ c->box_conversion_context = NULL;
/* Clean up and report error if unsuccessful or aborted */
if ((success == false) || (c->aborted)) {
html_object_free_objects(c);
if (success == false) {
- content_broadcast_errorcode(&c->base, NSERROR_BOX_CONVERT);
+ content_broadcast_error(&c->base, NSERROR_BOX_CONVERT, NULL);
} else {
- content_broadcast_errorcode(&c->base, NSERROR_STOPPED);
+ content_broadcast_error(&c->base, NSERROR_STOPPED, NULL);
}
content_set_error(&c->base);
@@ -139,10 +249,10 @@ static void html_box_convert_done(html_content *c, bool success)
exc = dom_document_get_document_element(c->document, (void *) &html);
if ((exc != DOM_NO_ERR) || (html == NULL)) {
/** @todo should this call html_object_free_objects(c);
- * like the other error paths
+ * like the other error paths
*/
NSLOG(netsurf, INFO, "error retrieving html element from dom");
- content_broadcast_errorcode(&c->base, NSERROR_DOM);
+ content_broadcast_error(&c->base, NSERROR_DOM, NULL);
content_set_error(&c->base);
return;
}
@@ -152,7 +262,7 @@ static void html_box_convert_done(html_content *c, bool success)
if (err != NSERROR_OK) {
NSLOG(netsurf, INFO, "imagemap extraction failed");
html_object_free_objects(c);
- content_broadcast_errorcode(&c->base, err);
+ content_broadcast_error(&c->base, err, NULL);
content_set_error(&c->base);
dom_node_unref(html);
return;
@@ -165,410 +275,69 @@ static void html_box_convert_done(html_content *c, bool success)
content_set_ready(&c->base);
- if (c->base.active == 0) {
- content_set_done(&c->base);
- }
+ html_proceed_to_done(c);
dom_node_unref(html);
}
-
-/** process link node */
-static bool html_process_link(html_content *c, dom_node *node)
-{
- struct content_rfc5988_link link; /* the link added to the content */
- dom_exception exc; /* returned by libdom functions */
- dom_string *atr_string;
- nserror error;
-
- memset(&link, 0, sizeof(struct content_rfc5988_link));
-
- /* check that the relation exists - w3c spec says must be present */
- exc = dom_element_get_attribute(node, corestring_dom_rel, &atr_string);
- if ((exc != DOM_NO_ERR) || (atr_string == NULL)) {
- return false;
- }
- /* get a lwc string containing the link relation */
- exc = dom_string_intern(atr_string, &link.rel);
- dom_string_unref(atr_string);
- if (exc != DOM_NO_ERR) {
- return false;
- }
-
- /* check that the href exists - w3c spec says must be present */
- exc = dom_element_get_attribute(node, corestring_dom_href, &atr_string);
- if ((exc != DOM_NO_ERR) || (atr_string == NULL)) {
- lwc_string_unref(link.rel);
- return false;
- }
-
- /* get nsurl */
- error = nsurl_join(c->base_url, dom_string_data(atr_string),
- &link.href);
- dom_string_unref(atr_string);
- if (error != NSERROR_OK) {
- lwc_string_unref(link.rel);
- return false;
- }
-
- /* look for optional properties -- we don't care if internment fails */
-
- exc = dom_element_get_attribute(node,
- corestring_dom_hreflang, &atr_string);
- if ((exc == DOM_NO_ERR) && (atr_string != NULL)) {
- /* get a lwc string containing the href lang */
- exc = dom_string_intern(atr_string, &link.hreflang);
- dom_string_unref(atr_string);
- }
-
- exc = dom_element_get_attribute(node,
- corestring_dom_type, &atr_string);
- if ((exc == DOM_NO_ERR) && (atr_string != NULL)) {
- /* get a lwc string containing the type */
- exc = dom_string_intern(atr_string, &link.type);
- dom_string_unref(atr_string);
- }
-
- exc = dom_element_get_attribute(node,
- corestring_dom_media, &atr_string);
- if ((exc == DOM_NO_ERR) && (atr_string != NULL)) {
- /* get a lwc string containing the media */
- exc = dom_string_intern(atr_string, &link.media);
- dom_string_unref(atr_string);
- }
-
- exc = dom_element_get_attribute(node,
- corestring_dom_sizes, &atr_string);
- if ((exc == DOM_NO_ERR) && (atr_string != NULL)) {
- /* get a lwc string containing the sizes */
- exc = dom_string_intern(atr_string, &link.sizes);
- dom_string_unref(atr_string);
- }
-
- /* add to content */
- content__add_rfc5988_link(&c->base, &link);
-
- if (link.sizes != NULL)
- lwc_string_unref(link.sizes);
- if (link.media != NULL)
- lwc_string_unref(link.media);
- if (link.type != NULL)
- lwc_string_unref(link.type);
- if (link.hreflang != NULL)
- lwc_string_unref(link.hreflang);
-
- nsurl_unref(link.href);
- lwc_string_unref(link.rel);
-
- return true;
-}
-
-/** process title node */
-static bool html_process_title(html_content *c, dom_node *node)
+/* Documented in html_internal.h */
+nserror
+html_proceed_to_done(html_content *html)
{
- dom_exception exc; /* returned by libdom functions */
- dom_string *title;
- char *title_str;
- bool success;
-
- exc = dom_node_get_text_content(node, &title);
- if ((exc != DOM_NO_ERR) || (title == NULL)) {
- return false;
- }
-
- title_str = squash_whitespace(dom_string_data(title));
- dom_string_unref(title);
-
- if (title_str == NULL) {
- return false;
- }
-
- success = content__set_title(&c->base, title_str);
-
- free(title_str);
-
- return success;
-}
-
-static bool html_process_base(html_content *c, dom_node *node)
-{
- dom_exception exc; /* returned by libdom functions */
- dom_string *atr_string;
-
- /* get href attribute if present */
- exc = dom_element_get_attribute(node,
- corestring_dom_href, &atr_string);
- if ((exc == DOM_NO_ERR) && (atr_string != NULL)) {
- nsurl *url;
- nserror error;
-
- /* get url from string */
- error = nsurl_create(dom_string_data(atr_string), &url);
- dom_string_unref(atr_string);
- if (error == NSERROR_OK) {
- if (c->base_url != NULL)
- nsurl_unref(c->base_url);
- c->base_url = url;
- }
- }
-
-
- /* get target attribute if present and not already set */
- if (c->base_target != NULL) {
- return true;
- }
-
- exc = dom_element_get_attribute(node,
- corestring_dom_target, &atr_string);
- if ((exc == DOM_NO_ERR) && (atr_string != NULL)) {
- /* Validation rules from the HTML5 spec for the base element:
- * The target must be one of _blank, _self, _parent, or
- * _top or any identifier which does not begin with an
- * underscore
- */
- if (*dom_string_data(atr_string) != '_' ||
- dom_string_caseless_lwc_isequal(atr_string,
- corestring_lwc__blank) ||
- dom_string_caseless_lwc_isequal(atr_string,
- corestring_lwc__self) ||
- dom_string_caseless_lwc_isequal(atr_string,
- corestring_lwc__parent) ||
- dom_string_caseless_lwc_isequal(atr_string,
- corestring_lwc__top)) {
- c->base_target = strdup(dom_string_data(atr_string));
- }
- dom_string_unref(atr_string);
- }
-
- return true;
-}
-
-static nserror html_meta_refresh_process_element(html_content *c, dom_node *n)
-{
- union content_msg_data msg_data;
- const char *url, *end, *refresh = NULL;
- char *new_url;
- char quote = '\0';
- dom_string *equiv, *content;
- dom_exception exc;
- nsurl *nsurl;
- nserror error = NSERROR_OK;
-
- exc = dom_element_get_attribute(n, corestring_dom_http_equiv, &equiv);
- if (exc != DOM_NO_ERR) {
- return NSERROR_DOM;
- }
-
- if (equiv == NULL) {
- return NSERROR_OK;
- }
-
- if (!dom_string_caseless_lwc_isequal(equiv, corestring_lwc_refresh)) {
- dom_string_unref(equiv);
- return NSERROR_OK;
- }
-
- dom_string_unref(equiv);
-
- exc = dom_element_get_attribute(n, corestring_dom_content, &content);
- if (exc != DOM_NO_ERR) {
- return NSERROR_DOM;
- }
-
- if (content == NULL) {
- return NSERROR_OK;
- }
-
- end = dom_string_data(content) + dom_string_byte_length(content);
-
- /* content := *LWS intpart fracpart? *LWS [';' *LWS *1url *LWS]
- * intpart := 1*DIGIT
- * fracpart := 1*('.' | DIGIT)
- * url := "url" *LWS '=' *LWS (url-nq | url-sq | url-dq)
- * url-nq := *urlchar
- * url-sq := "'" *(urlchar | '"') "'"
- * url-dq := '"' *(urlchar | "'") '"'
- * urlchar := [#x9#x21#x23-#x26#x28-#x7E] | nonascii
- * nonascii := [#x80-#xD7FF#xE000-#xFFFD#x10000-#x10FFFF]
- */
-
- url = dom_string_data(content);
-
- /* *LWS */
- while (url < end && ascii_is_space(*url)) {
- url++;
- }
-
- /* intpart */
- if (url == end || (*url < '0' || '9' < *url)) {
- /* Empty content, or invalid timeval */
- dom_string_unref(content);
- return NSERROR_OK;
- }
-
- msg_data.delay = (int) strtol(url, &new_url, 10);
- /* a very small delay and self-referencing URL can cause a loop
- * that grinds machines to a halt. To prevent this we set a
- * minimum refresh delay of 1s. */
- if (msg_data.delay < 1) {
- msg_data.delay = 1;
- }
-
- url = new_url;
-
- /* fracpart? (ignored, as delay is integer only) */
- while (url < end && (('0' <= *url && *url <= '9') ||
- *url == '.')) {
- url++;
- }
-
- /* *LWS */
- while (url < end && ascii_is_space(*url)) {
- url++;
- }
-
- /* ';' */
- if (url < end && *url == ';')
- url++;
-
- /* *LWS */
- while (url < end && ascii_is_space(*url)) {
- url++;
- }
-
- if (url == end) {
- /* Just delay specified, so refresh current page */
- dom_string_unref(content);
-
- c->base.refresh = nsurl_ref(
- content_get_url(&c->base));
-
- content_broadcast(&c->base, CONTENT_MSG_REFRESH, &msg_data);
-
- return NSERROR_OK;
- }
-
- /* "url" */
- if (url <= end - 3) {
- if (strncasecmp(url, "url", 3) == 0) {
- url += 3;
- } else {
- /* Unexpected input, ignore this header */
- dom_string_unref(content);
- return NSERROR_OK;
- }
- } else {
- /* Insufficient input, ignore this header */
- dom_string_unref(content);
- return NSERROR_OK;
- }
-
- /* *LWS */
- while (url < end && ascii_is_space(*url)) {
- url++;
- }
-
- /* '=' */
- if (url < end) {
- if (*url == '=') {
- url++;
- } else {
- /* Unexpected input, ignore this header */
- dom_string_unref(content);
+ switch (content__get_status(&html->base)) {
+ case CONTENT_STATUS_READY:
+ if (html->base.active == 0) {
+ content_set_done(&html->base);
return NSERROR_OK;
}
- } else {
- /* Insufficient input, ignore this header */
- dom_string_unref(content);
+ break;
+ case CONTENT_STATUS_DONE:
+ /* fallthrough */
+ case CONTENT_STATUS_LOADING:
return NSERROR_OK;
+ default:
+ NSLOG(netsurf, ERROR, "Content status unexpectedly not LOADING/READY/DONE");
+ break;
}
-
- /* *LWS */
- while (url < end && ascii_is_space(*url)) {
- url++;
- }
-
- /* '"' or "'" */
- if (url < end && (*url == '"' || *url == '\'')) {
- quote = *url;
- url++;
- }
-
- /* Start of URL */
- refresh = url;
-
- if (quote != 0) {
- /* url-sq | url-dq */
- while (url < end && *url != quote)
- url++;
- } else {
- /* url-nq */
- while (url < end && !ascii_is_space(*url))
- url++;
- }
-
- /* '"' or "'" or *LWS (we don't care) */
- if (url > refresh) {
- /* There's a URL */
- new_url = strndup(refresh, url - refresh);
- if (new_url == NULL) {
- dom_string_unref(content);
- return NSERROR_NOMEM;
- }
-
- error = nsurl_join(c->base_url, new_url, &nsurl);
- if (error == NSERROR_OK) {
- /* broadcast valid refresh url */
-
- c->base.refresh = nsurl;
-
- content_broadcast(&c->base, CONTENT_MSG_REFRESH,
- &msg_data);
- c->refresh = true;
- }
-
- free(new_url);
-
- }
-
- dom_string_unref(content);
-
- return error;
+ return NSERROR_UNKNOWN;
}
-static bool html_process_img(html_content *c, dom_node *node)
-{
- dom_string *src;
- nsurl *url;
- nserror err;
- dom_exception exc;
- bool success;
- /* Do nothing if foreground images are disabled */
- if (nsoption_bool(foreground_images) == false) {
- return true;
- }
-
- exc = dom_element_get_attribute(node, corestring_dom_src, &src);
- if (exc != DOM_NO_ERR || src == NULL) {
- return true;
- }
-
- err = nsurl_join(c->base_url, dom_string_data(src), &url);
- if (err != NSERROR_OK) {
- dom_string_unref(src);
- return false;
- }
- dom_string_unref(src);
-
- /* Speculatively fetch the image */
- success = html_fetch_object(c, url, NULL, CONTENT_IMAGE, 0, 0, false);
- nsurl_unref(url);
-
- return success;
+static void html_get_dimensions(html_content *htmlc)
+{
+ css_fixed device_dpi = nscss_screen_dpi;
+ unsigned f_size;
+ unsigned f_min;
+ unsigned w;
+ unsigned h;
+ union content_msg_data msg_data = {
+ .getdims = {
+ .viewport_width = &w,
+ .viewport_height = &h,
+ },
+ };
+
+ content_broadcast(&htmlc->base, CONTENT_MSG_GETDIMS, &msg_data);
+
+
+ w = css_unit_device2css_px(INTTOFIX(w), device_dpi);
+ h = css_unit_device2css_px(INTTOFIX(h), device_dpi);
+
+ htmlc->media.width = w;
+ htmlc->media.height = h;
+ htmlc->unit_len_ctx.viewport_width = w;
+ htmlc->unit_len_ctx.viewport_height = h;
+ htmlc->unit_len_ctx.device_dpi = device_dpi;
+
+ /** \todo Change nsoption font sizes to px. */
+ f_size = FDIV(FMUL(F_96, FDIV(INTTOFIX(nsoption_int(font_size)), F_10)), F_72);
+ f_min = FDIV(FMUL(F_96, FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)), F_72);
+
+ htmlc->unit_len_ctx.font_size_default = f_size;
+ htmlc->unit_len_ctx.font_size_minimum = f_min;
}
-/* exported function documented in render/html_internal.h */
+/* exported function documented in html/html_internal.h */
void html_finish_conversion(html_content *htmlc)
{
union content_msg_data msg_data;
@@ -578,15 +347,31 @@ void html_finish_conversion(html_content *htmlc)
/* Bail out if we've been aborted */
if (htmlc->aborted) {
- content_broadcast_errorcode(&htmlc->base, NSERROR_STOPPED);
+ content_broadcast_error(&htmlc->base, NSERROR_STOPPED, NULL);
content_set_error(&htmlc->base);
return;
}
+ /* If we already have a selection context, then we have already
+ * "finished" conversion. We can get here twice if e.g. some JS
+ * adds a new stylesheet, and the stylesheet gets added after
+ * the HTML content is initially finished.
+ *
+ * If we didn't do this, the HTML content would try to rebuild the
+ * box tree for the html content when this new stylesheet is ready.
+ * NetSurf has no concept of dynamically changing documents, so this
+ * would break badly.
+ */
+ if (htmlc->select_ctx != NULL) {
+ NSLOG(netsurf, INFO,
+ "Ignoring style change: NS layout is static.");
+ return;
+ }
+
/* create new css selection context */
error = html_css_new_selection_context(htmlc, &htmlc->select_ctx);
if (error != NSERROR_OK) {
- content_broadcast_errorcode(&htmlc->base, error);
+ content_broadcast_error(&htmlc->base, error, NULL);
content_set_error(&htmlc->base);
return;
}
@@ -596,8 +381,8 @@ void html_finish_conversion(html_content *htmlc)
* object, but with its target set to the Document object (and
* the currentTarget set to the Window object)
*/
- if (htmlc->jscontext != NULL) {
- js_fire_event(htmlc->jscontext, "load", htmlc->document, NULL);
+ if (htmlc->jsthread != NULL) {
+ js_fire_event(htmlc->jsthread, "load", htmlc->document, NULL);
}
/* convert dom tree to box tree */
@@ -609,17 +394,19 @@ void html_finish_conversion(html_content *htmlc)
exc = dom_document_get_document_element(htmlc->document, (void *) &html);
if ((exc != DOM_NO_ERR) || (html == NULL)) {
NSLOG(netsurf, INFO, "error retrieving html element from dom");
- content_broadcast_errorcode(&htmlc->base, NSERROR_DOM);
+ content_broadcast_error(&htmlc->base, NSERROR_DOM, NULL);
content_set_error(&htmlc->base);
return;
}
- error = dom_to_box(html, htmlc, html_box_convert_done);
+ html_get_dimensions(htmlc);
+
+ error = dom_to_box(html, htmlc, html_box_convert_done, &htmlc->box_conversion_context);
if (error != NSERROR_OK) {
NSLOG(netsurf, INFO, "box conversion failed");
dom_node_unref(html);
html_object_free_objects(htmlc);
- content_broadcast_errorcode(&htmlc->base, error);
+ content_broadcast_error(&htmlc->base, error, NULL);
content_set_error(&htmlc->base);
return;
}
@@ -627,161 +414,6 @@ void html_finish_conversion(html_content *htmlc)
dom_node_unref(html);
}
-/* callback for DOMNodeInserted end type */
-static void
-dom_default_action_DOMNodeInserted_cb(struct dom_event *evt, void *pw)
-{
- dom_event_target *node;
- dom_node_type type;
- dom_exception exc;
- html_content *htmlc = pw;
-
- exc = dom_event_get_target(evt, &node);
- if ((exc == DOM_NO_ERR) && (node != NULL)) {
- exc = dom_node_get_node_type(node, &type);
- if ((exc == DOM_NO_ERR) && (type == DOM_ELEMENT_NODE)) {
- /* an element node has been inserted */
- dom_html_element_type tag_type;
-
- exc = dom_html_element_get_tag_type(node, &tag_type);
- if (exc != DOM_NO_ERR) {
- tag_type = DOM_HTML_ELEMENT_TYPE__UNKNOWN;
- }
-
- switch (tag_type) {
- case DOM_HTML_ELEMENT_TYPE_LINK:
- /* Handle stylesheet loading */
- html_css_process_link(htmlc, (dom_node *)node);
- /* Generic link handling */
- html_process_link(htmlc, (dom_node *)node);
- break;
- case DOM_HTML_ELEMENT_TYPE_META:
- if (htmlc->refresh)
- break;
- html_meta_refresh_process_element(htmlc,
- (dom_node *)node);
- break;
- case DOM_HTML_ELEMENT_TYPE_TITLE:
- if (htmlc->title != NULL)
- break;
- htmlc->title = dom_node_ref(node);
- break;
- case DOM_HTML_ELEMENT_TYPE_BASE:
- html_process_base(htmlc, (dom_node *)node);
- break;
- case DOM_HTML_ELEMENT_TYPE_IMG:
- html_process_img(htmlc, (dom_node *) node);
- break;
- case DOM_HTML_ELEMENT_TYPE_STYLE:
- html_css_process_style(htmlc, (dom_node *) node);
- break;
- default:
- break;
- }
- if (htmlc->enable_scripting) {
- /* ensure javascript context is available */
- if (htmlc->jscontext == NULL) {
- union content_msg_data msg_data;
-
- msg_data.jscontext = &htmlc->jscontext;
- content_broadcast(&htmlc->base,
- CONTENT_MSG_GETCTX,
- &msg_data);
- NSLOG(netsurf, INFO,
- "javascript context: %p (htmlc: %p)",
- htmlc->jscontext,
- htmlc);
- }
- if (htmlc->jscontext != NULL) {
- js_handle_new_element(htmlc->jscontext,
- (dom_element *) node);
- }
- }
- }
- dom_node_unref(node);
- }
-}
-
-/* callback for DOMNodeInserted end type */
-static void
-dom_default_action_DOMSubtreeModified_cb(struct dom_event *evt, void *pw)
-{
- dom_event_target *node;
- dom_node_type type;
- dom_exception exc;
- html_content *htmlc = pw;
-
- exc = dom_event_get_target(evt, &node);
- if ((exc == DOM_NO_ERR) && (node != NULL)) {
- if (htmlc->title == (dom_node *)node) {
- /* Node is our title node */
- html_process_title(htmlc, (dom_node *)node);
- dom_node_unref(node);
- return;
- }
-
- exc = dom_node_get_node_type(node, &type);
- if ((exc == DOM_NO_ERR) && (type == DOM_ELEMENT_NODE)) {
- /* an element node has been modified */
- dom_html_element_type tag_type;
-
- exc = dom_html_element_get_tag_type(node, &tag_type);
- if (exc != DOM_NO_ERR) {
- tag_type = DOM_HTML_ELEMENT_TYPE__UNKNOWN;
- }
-
- switch (tag_type) {
- case DOM_HTML_ELEMENT_TYPE_STYLE:
- html_css_update_style(htmlc, (dom_node *)node);
- break;
- default:
- break;
- }
- }
- dom_node_unref(node);
- }
-}
-
-static void
-dom_default_action_finished_cb(struct dom_event *evt, void *pw)
-{
- html_content *htmlc = pw;
-
- if (htmlc->jscontext != NULL)
- js_event_cleanup(htmlc->jscontext, evt);
-}
-
-/* callback function selector
- *
- * selects a callback function for libdom to call based on the type and phase.
- * dom_default_action_phase from events/document_event.h
- *
- * The principle events are:
- * DOMSubtreeModified
- * DOMAttrModified
- * DOMNodeInserted
- * DOMNodeInsertedIntoDocument
- *
- * @return callback function pointer or NULL for none
- */
-static dom_default_action_callback
-dom_event_fetcher(dom_string *type,
- dom_default_action_phase phase,
- void **pw)
-{
- NSLOG(netsurf, DEEPDEBUG, "type:%s", dom_string_data(type));
-
- if (phase == DOM_DEFAULT_ACTION_END) {
- if (dom_string_isequal(type, corestring_dom_DOMNodeInserted)) {
- return dom_default_action_DOMNodeInserted_cb;
- } else if (dom_string_isequal(type, corestring_dom_DOMSubtreeModified)) {
- return dom_default_action_DOMSubtreeModified_cb;
- }
- } else if (phase == DOM_DEFAULT_ACTION_FINISHED) {
- return dom_default_action_finished_cb;
- }
- return NULL;
-}
static void
html_document_user_data_handler(dom_node_operation operation,
@@ -826,9 +458,12 @@ html_create_html_data(html_content *c, const http_parameter *params)
dom_hubbub_error error;
dom_exception err;
void *old_node_data;
+ const char *prefer_color_mode = (nsoption_bool(prefer_dark_mode)) ?
+ "dark" : "light";
c->parser = NULL;
c->parse_completed = false;
+ c->conversion_begun = false;
c->document = NULL;
c->quirks = DOM_DOCUMENT_QUIRKS_MODE_NONE;
c->encoding = NULL;
@@ -844,6 +479,7 @@ html_create_html_data(html_content *c, const http_parameter *params)
c->stylesheet_count = 0;
c->stylesheets = NULL;
c->select_ctx = NULL;
+ c->media.type = CSS_MEDIA_SCREEN;
c->universal = NULL;
c->num_objects = 0;
c->object_list = NULL;
@@ -860,11 +496,9 @@ html_create_html_data(html_content *c, const http_parameter *params)
c->selection_owner.none = true;
c->focus_type = HTML_FOCUS_SELF;
c->focus_owner.self = true;
- c->search = NULL;
- c->search_string = NULL;
c->scripts_count = 0;
c->scripts = NULL;
- c->jscontext = NULL;
+ c->jsthread = NULL;
c->enable_scripting = nsoption_bool(enable_javascript);
c->base.active = 1; /* The html content itself is active */
@@ -873,7 +507,14 @@ html_create_html_data(html_content *c, const http_parameter *params)
return NSERROR_NOMEM;
}
- selection_prepare(&c->sel, (struct content *)c, true);
+ if (lwc_intern_string(prefer_color_mode, strlen(prefer_color_mode),
+ &c->media.prefers_color_scheme) != lwc_error_ok) {
+ lwc_string_unref(c->universal);
+ c->universal = NULL;
+ return NSERROR_NOMEM;
+ }
+
+ c->sel = selection_create((struct content *)c);
nerror = http_parameter_list_find_item(params, corestring_lwc_charset, &charset);
if (nerror == NSERROR_OK) {
@@ -884,6 +525,8 @@ html_create_html_data(html_content *c, const http_parameter *params)
if (c->encoding == NULL) {
lwc_string_unref(c->universal);
c->universal = NULL;
+ lwc_string_unref(c->media.prefers_color_scheme);
+ c->media.prefers_color_scheme = NULL;
return NSERROR_NOMEM;
}
@@ -897,7 +540,7 @@ html_create_html_data(html_content *c, const http_parameter *params)
parse_params.msg = NULL;
parse_params.script = html_process_script;
parse_params.ctx = c;
- parse_params.daf = dom_event_fetcher;
+ parse_params.daf = html_dom_event_fetcher;
error = dom_hubbub_parser_create(&parse_params,
&c->parser,
@@ -920,6 +563,8 @@ html_create_html_data(html_content *c, const http_parameter *params)
lwc_string_unref(c->universal);
c->universal = NULL;
+ lwc_string_unref(c->media.prefers_color_scheme);
+ c->media.prefers_color_scheme = NULL;
return libdom_hubbub_error_to_nserror(error);
}
@@ -930,11 +575,14 @@ html_create_html_data(html_content *c, const http_parameter *params)
(void *) &old_node_data);
if (err != DOM_NO_ERR) {
dom_hubbub_parser_destroy(c->parser);
+ c->parser = NULL;
nsurl_unref(c->base_url);
c->base_url = NULL;
lwc_string_unref(c->universal);
c->universal = NULL;
+ lwc_string_unref(c->media.prefers_color_scheme);
+ c->media.prefers_color_scheme = NULL;
NSLOG(netsurf, INFO, "Unable to set user data.");
return NSERROR_DOM;
@@ -978,14 +626,14 @@ html_create(const content_handler *handler,
error = html_create_html_data(html, params);
if (error != NSERROR_OK) {
- content_broadcast_errorcode(&html->base, error);
+ content_broadcast_error(&html->base, error, NULL);
free(html);
return error;
}
error = html_css_new_stylesheets(html);
if (error != NSERROR_OK) {
- content_broadcast_errorcode(&html->base, error);
+ content_broadcast_error(&html->base, error, NULL);
free(html);
return error;
}
@@ -998,19 +646,19 @@ html_create(const content_handler *handler,
static nserror
-html_process_encoding_change(struct content *c,
- const char *data,
+html_process_encoding_change(struct content *c,
+ const char *data,
unsigned int size)
{
html_content *html = (html_content *) c;
dom_hubbub_parser_params parse_params;
dom_hubbub_error error;
const char *encoding;
- const char *source_data;
- unsigned long source_size;
+ const uint8_t *source_data;
+ size_t source_size;
/* Retrieve new encoding */
- encoding = dom_hubbub_parser_get_encoding(html->parser,
+ encoding = dom_hubbub_parser_get_encoding(html->parser,
&html->encoding_source);
if (encoding == NULL) {
return NSERROR_NOMEM;
@@ -1040,7 +688,7 @@ html_process_encoding_change(struct content *c,
parse_params.msg = NULL;
parse_params.script = html_process_script;
parse_params.ctx = html;
- parse_params.daf = dom_event_fetcher;
+ parse_params.daf = html_dom_event_fetcher;
/* Create new binding, using the new encoding */
error = dom_hubbub_parser_create(&parse_params,
@@ -1070,10 +718,10 @@ html_process_encoding_change(struct content *c,
/* Reprocess all the data. This is safe because
* the encoding is now specified at parser start which means
- * it cannot be changed again.
+ * it cannot be changed again.
*/
- error = dom_hubbub_parser_parse_chunk(html->parser,
- (const uint8_t *)source_data,
+ error = dom_hubbub_parser_parse_chunk(html->parser,
+ source_data,
source_size);
return libdom_hubbub_error_to_nserror(error);
@@ -1091,8 +739,8 @@ html_process_data(struct content *c, const char *data, unsigned int size)
dom_hubbub_error dom_ret;
nserror err = NSERROR_OK; /* assume its all going to be ok */
- dom_ret = dom_hubbub_parser_parse_chunk(html->parser,
- (const uint8_t *) data,
+ dom_ret = dom_hubbub_parser_parse_chunk(html->parser,
+ (const uint8_t *) data,
size);
err = libdom_hubbub_error_to_nserror(dom_ret);
@@ -1104,11 +752,11 @@ html_process_data(struct content *c, const char *data, unsigned int size)
/* broadcast the error if necessary */
if (err != NSERROR_OK) {
- content_broadcast_errorcode(c, err);
+ content_broadcast_error(c, err, NULL);
return false;
}
- return true;
+ return true;
}
@@ -1167,14 +815,17 @@ bool html_can_begin_conversion(html_content *htmlc)
{
unsigned int i;
+ /* Cannot begin conversion if we're still fetching stuff */
if (htmlc->base.active != 0)
return false;
for (i = 0; i != htmlc->stylesheet_count; i++) {
+ /* Cannot begin conversion if the stylesheets are modified */
if (htmlc->stylesheets[i].modified)
return false;
}
+ /* All is good, begin */
return true;
}
@@ -1188,14 +839,14 @@ html_begin_conversion(html_content *htmlc)
dom_string *node_name = NULL;
dom_hubbub_error error;
- /* The act of completing the parse can result in additional data
- * being flushed through the parser. This may result in new style or
- * script nodes, upon which the conversion depends. Thus, once we
- * have completed the parse, we must check again to see if we can
- * begin the conversion. If we can't, we must stop and wait for the
+ /* The act of completing the parse can result in additional data
+ * being flushed through the parser. This may result in new style or
+ * script nodes, upon which the conversion depends. Thus, once we
+ * have completed the parse, we must check again to see if we can
+ * begin the conversion. If we can't, we must stop and wait for the
* new styles/scripts to be processed. Once they have been processed,
- * we will be called again to begin the conversion for real. Thus,
- * we must also ensure that we don't attempt to complete the parse
+ * we will be called again to begin the conversion for real. Thus,
+ * we must also ensure that we don't attempt to complete the parse
* multiple times, so store a flag to indicate that parsing is
* complete to avoid repeating the completion pointlessly.
*/
@@ -1203,11 +854,19 @@ html_begin_conversion(html_content *htmlc)
NSLOG(netsurf, INFO, "Completing parse (%p)", htmlc);
/* complete parsing */
error = dom_hubbub_parser_completed(htmlc->parser);
+ if (error == DOM_HUBBUB_HUBBUB_ERR_PAUSED && htmlc->base.active > 0) {
+ /* The act of completing the parse failed because we've
+ * encountered a sync script which needs to run
+ */
+ NSLOG(netsurf, INFO, "Completing parse brought synchronous JS to light, cannot complete yet");
+ return true;
+ }
if (error != DOM_HUBBUB_OK) {
NSLOG(netsurf, INFO, "Parsing failed");
-
- content_broadcast_errorcode(&htmlc->base,
- libdom_hubbub_error_to_nserror(error));
+
+ content_broadcast_error(&htmlc->base,
+ libdom_hubbub_error_to_nserror(error),
+ NULL);
return false;
}
@@ -1225,12 +884,15 @@ html_begin_conversion(html_content *htmlc)
NSLOG(netsurf, INFO, "Conversion aborted (%p) (active: %u)",
htmlc, htmlc->base.active);
content_set_error(&htmlc->base);
- content_broadcast_errorcode(&htmlc->base, NSERROR_STOPPED);
+ content_broadcast_error(&htmlc->base, NSERROR_STOPPED, NULL);
return false;
}
- /* complete script execution */
- html_script_exec(htmlc);
+ /* Conversion begins proper at this point */
+ htmlc->conversion_begun = true;
+
+ /* complete script execution, including deferred scripts */
+ html_script_exec(htmlc, true);
/* fire a simple event that bubbles named DOMContentLoaded at
* the Document.
@@ -1243,15 +905,17 @@ html_begin_conversion(html_content *htmlc)
encoding = dom_hubbub_parser_get_encoding(htmlc->parser,
&htmlc->encoding_source);
if (encoding == NULL) {
- content_broadcast_errorcode(&htmlc->base,
- NSERROR_NOMEM);
+ content_broadcast_error(&htmlc->base,
+ NSERROR_NOMEM,
+ NULL);
return false;
}
htmlc->encoding = strdup(encoding);
if (htmlc->encoding == NULL) {
- content_broadcast_errorcode(&htmlc->base,
- NSERROR_NOMEM);
+ content_broadcast_error(&htmlc->base,
+ NSERROR_NOMEM,
+ NULL);
return false;
}
}
@@ -1260,7 +924,7 @@ html_begin_conversion(html_content *htmlc)
exc = dom_document_get_document_element(htmlc->document, (void *) &html);
if ((exc != DOM_NO_ERR) || (html == NULL)) {
NSLOG(netsurf, INFO, "error retrieving html element from dom");
- content_broadcast_errorcode(&htmlc->base, NSERROR_DOM);
+ content_broadcast_error(&htmlc->base, NSERROR_DOM, NULL);
return false;
}
@@ -1268,9 +932,9 @@ html_begin_conversion(html_content *htmlc)
if ((exc != DOM_NO_ERR) ||
(node_name == NULL) ||
(!dom_string_caseless_lwc_isequal(node_name,
- corestring_lwc_html))) {
+ corestring_lwc_html))) {
NSLOG(netsurf, INFO, "root element not html");
- content_broadcast_errorcode(&htmlc->base, NSERROR_DOM);
+ content_broadcast_error(&htmlc->base, NSERROR_DOM, NULL);
dom_node_unref(html);
return false;
}
@@ -1287,16 +951,16 @@ html_begin_conversion(html_content *htmlc)
/* HTML5 4.10.22.3 step 9 */
nsurl *doc_addr = content_get_url(&htmlc->base);
ns_error = nsurl_join(htmlc->base_url,
- nsurl_access(doc_addr),
+ nsurl_access(doc_addr),
&action);
} else {
- ns_error = nsurl_join(htmlc->base_url,
- f->action,
+ ns_error = nsurl_join(htmlc->base_url,
+ f->action,
&action);
}
if (ns_error != NSERROR_OK) {
- content_broadcast_errorcode(&htmlc->base, ns_error);
+ content_broadcast_error(&htmlc->base, ns_error, NULL);
dom_node_unref(html);
return false;
@@ -1306,8 +970,9 @@ html_begin_conversion(html_content *htmlc)
f->action = strdup(nsurl_access(action));
nsurl_unref(action);
if (f->action == NULL) {
- content_broadcast_errorcode(&htmlc->base,
- NSERROR_NOMEM);
+ content_broadcast_error(&htmlc->base,
+ NSERROR_NOMEM,
+ NULL);
dom_node_unref(html);
return false;
@@ -1317,8 +982,9 @@ html_begin_conversion(html_content *htmlc)
if (f->document_charset == NULL) {
f->document_charset = strdup(htmlc->encoding);
if (f->document_charset == NULL) {
- content_broadcast_errorcode(&htmlc->base,
- NSERROR_NOMEM);
+ content_broadcast_error(&htmlc->base,
+ NSERROR_NOMEM,
+ NULL);
dom_node_unref(html);
return false;
}
@@ -1346,24 +1012,22 @@ static void html_stop(struct content *c)
{
html_content *htmlc = (html_content *) c;
- /* invalidate the html content reference to the javascript context
- * as it is about to become invalid and must not be used any
- * more.
- */
- html_script_invalidate_ctx(htmlc);
-
switch (c->status) {
case CONTENT_STATUS_LOADING:
/* Still loading; simply flag that we've been aborted
* html_convert/html_finish_conversion will do the rest */
htmlc->aborted = true;
+ if (htmlc->jsthread != NULL) {
+ /* Close the JS thread to cancel out any callbacks */
+ js_closethread(htmlc->jsthread);
+ }
break;
case CONTENT_STATUS_READY:
html_object_abort_objects(htmlc);
/* If there are no further active fetches and we're still
- * in the READY state, transition to the DONE state. */
+ * in the READY state, transition to the DONE state. */
if (c->status == CONTENT_STATUS_READY && c->active == 0) {
content_set_done(c);
}
@@ -1398,9 +1062,11 @@ static void html_reformat(struct content *c, int width, int height)
htmlc->reflowing = true;
- htmlc->len_ctx.vw = width;
- htmlc->len_ctx.vh = height;
- htmlc->len_ctx.root_style = htmlc->layout->style;
+ htmlc->unit_len_ctx.viewport_width = css_unit_device2css_px(
+ INTTOFIX(width), htmlc->unit_len_ctx.device_dpi);
+ htmlc->unit_len_ctx.viewport_height = css_unit_device2css_px(
+ INTTOFIX(height), htmlc->unit_len_ctx.device_dpi);
+ htmlc->unit_len_ctx.root_style = htmlc->layout->style;
layout_document(htmlc, width, height);
layout = htmlc->layout;
@@ -1419,14 +1085,15 @@ static void html_reformat(struct content *c, int width, int height)
if (c->height < layout->y + layout->descendant_y1)
c->height = layout->y + layout->descendant_y1;
- selection_reinit(&htmlc->sel, htmlc->layout);
+ selection_reinit(htmlc->sel);
htmlc->reflowing = false;
+ htmlc->had_initial_layout = true;
/* calculate next reflow time at three times what it took to reflow */
nsu_getmonotonic_ms(&ms_after);
- ms_interval = (ms_before - ms_after) * 3;
+ ms_interval = (ms_after - ms_before) * 3;
if (ms_interval < (nsoption_uint(min_reflow_period) * 10)) {
ms_interval = nsoption_uint(min_reflow_period) * 10;
}
@@ -1493,8 +1160,8 @@ static void html_destroy_frameset(struct content_html_frames *frameset)
nsurl_unref(frameset->children[i].url);
frameset->children[i].url = NULL;
}
- if (frameset->children[i].children)
- html_destroy_frameset(&frameset->children[i]);
+ if (frameset->children[i].children)
+ html_destroy_frameset(&frameset->children[i]);
}
talloc_free(frameset->children);
frameset->children = NULL;
@@ -1522,7 +1189,7 @@ static void html_free_layout(html_content *htmlc)
{
if (htmlc->bctx != NULL) {
/* freeing talloc context should let the entire box
- * set be destroyed
+ * set be destroyed
*/
talloc_free(htmlc->bctx);
}
@@ -1539,6 +1206,15 @@ static void html_destroy(struct content *c)
NSLOG(netsurf, INFO, "content %p", c);
+ /* If we're still converting a layout, cancel it */
+ if (html->box_conversion_context != NULL) {
+ if (cancel_dom_to_box(html->box_conversion_context) != NSERROR_OK) {
+ NSLOG(netsurf, CRITICAL, "WARNING, Unable to cancel conversion context, browser may crash");
+ }
+ }
+
+ selection_destroy(html->sel);
+
/* Destroy forms */
for (f = html->forms; f != NULL; f = g) {
g = f->prev;
@@ -1554,6 +1230,14 @@ static void html_destroy(struct content *c)
if (html->base_url)
nsurl_unref(html->base_url);
+ /* At this point we can be moderately confident the JS is offline
+ * so we destroy the JS thread.
+ */
+ if (html->jsthread != NULL) {
+ js_destroythread(html->jsthread);
+ html->jsthread = NULL;
+ }
+
if (html->parser != NULL) {
dom_hubbub_parser_destroy(html->parser);
html->parser = NULL;
@@ -1577,8 +1261,8 @@ static void html_destroy(struct content *c)
/* Free base target */
if (html->base_target != NULL) {
- free(html->base_target);
- html->base_target = NULL;
+ free(html->base_target);
+ html->base_target = NULL;
}
/* Free frameset */
@@ -1605,6 +1289,11 @@ static void html_destroy(struct content *c)
html->universal = NULL;
}
+ if (html->media.prefers_color_scheme != NULL) {
+ lwc_string_unref(html->media.prefers_color_scheme);
+ html->media.prefers_color_scheme = NULL;
+ }
+
/* Free stylesheets */
html_css_free_stylesheets(html);
@@ -1636,7 +1325,7 @@ static nserror html_clone(const struct content *old, struct content **newc)
* Handle a window containing a CONTENT_HTML being opened.
*/
-static void
+static nserror
html_open(struct content *c,
struct browser_window *bw,
struct content *page,
@@ -1651,11 +1340,13 @@ html_open(struct content *c,
html->drag_owner.no_owner = true;
/* text selection */
- selection_init(&html->sel, html->layout, &html->len_ctx);
+ selection_init(html->sel);
html->selection_type = HTML_SELECTION_NONE;
html->selection_owner.none = true;
html_object_open_objects(html, bw);
+
+ return NSERROR_OK;
}
@@ -1663,27 +1354,25 @@ html_open(struct content *c,
* Handle a window containing a CONTENT_HTML being closed.
*/
-static void html_close(struct content *c)
+static nserror html_close(struct content *c)
{
html_content *htmlc = (html_content *) c;
+ nserror ret = NSERROR_OK;
- selection_clear(&htmlc->sel, false);
-
- if (htmlc->search != NULL) {
- search_destroy_context(htmlc->search);
- }
+ selection_clear(htmlc->sel, false);
/* clear the html content reference to the browser window */
htmlc->bw = NULL;
- /* invalidate the html content reference to the javascript context
- * as it is about to become invalid and must not be used any
- * more.
- */
- html_script_invalidate_ctx(htmlc);
-
/* remove all object references from the html content */
html_object_close_objects(htmlc);
+
+ if (htmlc->jsthread != NULL) {
+ /* Close, but do not destroy (yet) the JS thread */
+ ret = js_closethread(htmlc->jsthread);
+ }
+
+ return ret;
}
@@ -1706,7 +1395,7 @@ static void html_clear_selection(struct content *c)
break;
case HTML_SELECTION_SELF:
assert(html->selection_owner.none == false);
- selection_clear(&html->sel, true);
+ selection_clear(html->sel, true);
break;
case HTML_SELECTION_CONTENT:
content_clear_selection(html->selection_owner.content->object);
@@ -1735,7 +1424,7 @@ static char *html_get_selection(struct content *c)
gadget->data.text.ta);
case HTML_SELECTION_SELF:
assert(html->selection_owner.none == false);
- return selection_get_copy(&html->sel);
+ return selection_get_copy(html->sel);
case HTML_SELECTION_CONTENT:
return content_get_selection(
html->selection_owner.content->object);
@@ -1772,7 +1461,7 @@ html_get_contextual_content(struct content *c, int x, int y,
struct box *next;
int box_x = 0, box_y = 0;
- while ((next = box_at_point(&html->len_ctx, box, x, y,
+ while ((next = box_at_point(&html->unit_len_ctx, box, x, y,
&box_x, &box_y)) != NULL) {
box = next;
@@ -1783,8 +1472,11 @@ html_get_contextual_content(struct content *c, int x, int y,
}
if (box->iframe) {
+ float scale = browser_window_get_scale(box->iframe);
browser_window_get_features(box->iframe,
- x - box_x, y - box_y, data);
+ (x - box_x) * scale,
+ (y - box_y) * scale,
+ data);
}
if (box->object)
@@ -1850,7 +1542,7 @@ html_scroll_at_point(struct content *c, int x, int y, int scrx, int scry)
/* TODO: invert order; visit deepest box first */
- while ((next = box_at_point(&html->len_ctx, box, x, y,
+ while ((next = box_at_point(&html->unit_len_ctx, box, x, y,
&box_x, &box_y)) != NULL) {
box = next;
@@ -1859,9 +1551,15 @@ html_scroll_at_point(struct content *c, int x, int y, int scrx, int scry)
continue;
/* Pass into iframe */
- if (box->iframe && browser_window_scroll_at_point(box->iframe,
- x - box_x, y - box_y, scrx, scry) == true)
- return true;
+ if (box->iframe) {
+ float scale = browser_window_get_scale(box->iframe);
+
+ if (browser_window_scroll_at_point(box->iframe,
+ (x - box_x) * scale,
+ (y - box_y) * scale,
+ scrx, scry) == true)
+ return true;
+ }
/* Pass into textarea widget */
if (box->gadget && (box->gadget->type == GADGET_TEXTAREA ||
@@ -1947,9 +1645,9 @@ static void html__set_file_gadget_filename(struct content *c,
NSLOG(netsurf, INFO,
"utf8 to local encoding conversion failed");
/* Load was for us - just no memory */
- return;
+ return;
}
-
+
form_gadget_update_value(gadget, utf8_fn);
/* corestring_dom___ns_key_file_name_node_data */
@@ -1962,7 +1660,7 @@ static void html__set_file_gadget_filename(struct content *c,
}
/* Redraw box. */
- html__redraw_a_box(html, file_box);
+ html__redraw_a_box(html, file_box);
}
void html_set_file_gadget_filename(struct hlcache_handle *hl,
@@ -1993,19 +1691,25 @@ static bool html_drop_file_at_point(struct content *c, int x, int y, char *file)
int box_x = 0, box_y = 0;
/* Scan box tree for boxes that can handle drop */
- while ((next = box_at_point(&html->len_ctx, box, x, y,
+ while ((next = box_at_point(&html->unit_len_ctx, box, x, y,
&box_x, &box_y)) != NULL) {
box = next;
- if (box->style && css_computed_visibility(box->style) ==
- CSS_VISIBILITY_HIDDEN)
+ if (box->style &&
+ css_computed_visibility(box->style) == CSS_VISIBILITY_HIDDEN)
continue;
- if (box->iframe)
- return browser_window_drop_file_at_point(box->iframe,
- x - box_x, y - box_y, file);
+ if (box->iframe) {
+ float scale = browser_window_get_scale(box->iframe);
+ return browser_window_drop_file_at_point(
+ box->iframe,
+ (x - box_x) * scale,
+ (y - box_y) * scale,
+ file);
+ }
- if (box->object && content_drop_file_at_point(box->object,
+ if (box->object &&
+ content_drop_file_at_point(box->object,
x - box_x, y - box_y, file) == true)
return true;
@@ -2097,10 +1801,11 @@ static bool html_drop_file_at_point(struct content *c, int x, int y, char *file)
ret = guit->utf8->local_to_utf8(buffer, file_len, &utf8_buff);
if (ret != NSERROR_OK) {
/* bad encoding shouldn't happen */
+ NSLOG(netsurf, ERROR,
+ "local to utf8 encoding failed (%s)",
+ messages_get_errorcode(ret));
assert(ret != NSERROR_BAD_ENCODING);
- NSLOG(netsurf, INFO, "local to utf8 encoding failed");
free(buffer);
- guit->misc->warning("NoMemory", NULL);
return true;
}
@@ -2260,7 +1965,8 @@ dom_document *html_get_document(hlcache_handle *h)
* \param h HTML content to retrieve tree from
* \return Pointer to box tree
*
- * \todo This API must die, as must all use of the box tree outside render/
+ * \todo This API must die, as must all use of the box tree outside of
+ * HTML content handler
*/
struct box *html_get_box_tree(hlcache_handle *h)
{
@@ -2381,6 +2087,119 @@ bool html_get_id_offset(hlcache_handle *h, lwc_string *frag_id, int *x, int *y)
return false;
}
+bool html_exec(struct content *c, const char *src, size_t srclen)
+{
+ html_content *htmlc = (html_content *)c;
+ bool result = false;
+ dom_exception err;
+ dom_html_body_element *body_node;
+ dom_string *dom_src;
+ dom_text *text_node;
+ dom_node *spare_node;
+ dom_html_script_element *script_node;
+
+ if (htmlc->document == NULL) {
+ NSLOG(netsurf, DEEPDEBUG, "Unable to exec, no document");
+ goto out_no_string;
+ }
+
+ err = dom_string_create((const uint8_t *)src, srclen, &dom_src);
+ if (err != DOM_NO_ERR) {
+ NSLOG(netsurf, DEEPDEBUG, "Unable to exec, could not create string");
+ goto out_no_string;
+ }
+
+ err = dom_html_document_get_body(htmlc->document, &body_node);
+ if (err != DOM_NO_ERR) {
+ NSLOG(netsurf, DEEPDEBUG, "Unable to retrieve body element");
+ goto out_no_body;
+ }
+
+ err = dom_document_create_text_node(htmlc->document, dom_src, &text_node);
+ if (err != DOM_NO_ERR) {
+ NSLOG(netsurf, DEEPDEBUG, "Unable to exec, could not create text node");
+ goto out_no_text_node;
+ }
+
+ err = dom_document_create_element(htmlc->document, corestring_dom_SCRIPT, &script_node);
+ if (err != DOM_NO_ERR) {
+ NSLOG(netsurf, DEEPDEBUG, "Unable to exec, could not create script node");
+ goto out_no_script_node;
+ }
+
+ err = dom_node_append_child(script_node, text_node, &spare_node);
+ if (err != DOM_NO_ERR) {
+ NSLOG(netsurf, DEEPDEBUG, "Unable to exec, could not insert code node into script node");
+ goto out_unparented;
+ }
+ dom_node_unref(spare_node); /* We do not need the spare ref at all */
+
+ err = dom_node_append_child(body_node, script_node, &spare_node);
+ if (err != DOM_NO_ERR) {
+ NSLOG(netsurf, DEEPDEBUG, "Unable to exec, could not insert script node into document body");
+ goto out_unparented;
+ }
+ dom_node_unref(spare_node); /* Again no need for the spare ref */
+
+ /* We successfully inserted the node into the DOM */
+
+ result = true;
+
+ /* Now we unwind, starting by removing the script from wherever it
+ * ended up parented
+ */
+
+ err = dom_node_get_parent_node(script_node, &spare_node);
+ if (err == DOM_NO_ERR && spare_node != NULL) {
+ dom_node *second_spare;
+ err = dom_node_remove_child(spare_node, script_node, &second_spare);
+ if (err == DOM_NO_ERR) {
+ dom_node_unref(second_spare);
+ }
+ dom_node_unref(spare_node);
+ }
+
+out_unparented:
+ dom_node_unref(script_node);
+out_no_script_node:
+ dom_node_unref(text_node);
+out_no_text_node:
+ dom_node_unref(body_node);
+out_no_body:
+ dom_string_unref(dom_src);
+out_no_string:
+ return result;
+}
+
+/* See \ref content_saw_insecure_objects */
+static bool
+html_saw_insecure_objects(struct content *c)
+{
+ html_content *htmlc = (html_content *)c;
+ struct content_html_object *obj = htmlc->object_list;
+
+ /* Check through the object list */
+ while (obj != NULL) {
+ if (obj->content != NULL) {
+ if (content_saw_insecure_objects(obj->content))
+ return true;
+ }
+ obj = obj->next;
+ }
+
+ /* Now check the script list */
+ if (html_saw_insecure_scripts(htmlc)) {
+ return true;
+ }
+
+ /* Now check stylesheets */
+ if (html_css_saw_insecure_stylesheets(htmlc)) {
+ return true;
+ }
+
+ return false;
+}
+
/**
* Compute the type of a content
*
@@ -2397,6 +2216,133 @@ static void html_fini(void)
html_css_fini();
}
+/**
+ * Finds all occurrences of a given string in an html box
+ *
+ * \param pattern the string pattern to search for
+ * \param p_len pattern length
+ * \param cur pointer to the current box
+ * \param case_sens whether to perform a case sensitive search
+ * \param context The search context to add the entry to.
+ * \return true on success, false on memory allocation failure
+ */
+static nserror
+find_occurrences_html_box(const char *pattern,
+ int p_len,
+ struct box *cur,
+ bool case_sens,
+ struct textsearch_context *context)
+{
+ struct box *a;
+ nserror res = NSERROR_OK;
+
+ /* ignore this box, if there's no visible text */
+ if (!cur->object && cur->text) {
+ const char *text = cur->text;
+ unsigned length = cur->length;
+
+ while (length > 0) {
+ unsigned match_length;
+ unsigned match_offset;
+ const char *new_text;
+ const char *pos;
+
+ pos = content_textsearch_find_pattern(text,
+ length,
+ pattern,
+ p_len,
+ case_sens,
+ &match_length);
+ if (!pos)
+ break;
+
+ /* found string in box => add to list */
+ match_offset = pos - cur->text;
+
+ res = content_textsearch_add_match(context,
+ cur->byte_offset + match_offset,
+ cur->byte_offset + match_offset + match_length,
+ cur,
+ cur);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ new_text = pos + match_length;
+ length -= (new_text - text);
+ text = new_text;
+ }
+ }
+
+ /* and recurse */
+ for (a = cur->children; a; a = a->next) {
+ res = find_occurrences_html_box(pattern,
+ p_len,
+ a,
+ case_sens,
+ context);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ return res;
+}
+
+/**
+ * Finds all occurrences of a given string in the html box tree
+ *
+ * \param pattern the string pattern to search for
+ * \param p_len pattern length
+ * \param c The content to search
+ * \param csens whether to perform a case sensitive search
+ * \param context The search context to add the entry to.
+ * \return true on success, false on memory allocation failure
+ */
+static nserror
+html_textsearch_find(struct content *c,
+ struct textsearch_context *context,
+ const char *pattern,
+ int p_len,
+ bool csens)
+{
+ html_content *html = (html_content *)c;
+
+ if (html->layout == NULL) {
+ return NSERROR_INVALID;
+ }
+
+ return find_occurrences_html_box(pattern,
+ p_len,
+ html->layout,
+ csens,
+ context);
+}
+
+
+static nserror
+html_textsearch_bounds(struct content *c,
+ unsigned start_idx,
+ unsigned end_idx,
+ struct box *start_box,
+ struct box *end_box,
+ struct rect *bounds)
+{
+ /* get box position and jump to it */
+ box_coords(start_box, &bounds->x0, &bounds->y0);
+ /* \todo: move x0 in by correct idx */
+ box_coords(end_box, &bounds->x1, &bounds->y1);
+ /* \todo: move x1 in by correct idx */
+ bounds->x1 += end_box->width;
+ bounds->y1 += end_box->height;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * HTML content handler function table
+ */
static const content_handler html_content_handler = {
.fini = html_fini,
.create = html_create,
@@ -2416,16 +2362,23 @@ static const content_handler html_content_handler = {
.get_contextual_content = html_get_contextual_content,
.scroll_at_point = html_scroll_at_point,
.drop_file_at_point = html_drop_file_at_point,
- .search = html_search,
- .search_clear = html_search_clear,
.debug_dump = html_debug_dump,
.debug = html_debug,
.clone = html_clone,
.get_encoding = html_encoding,
.type = html_content_type,
+ .exec = html_exec,
+ .saw_insecure_objects = html_saw_insecure_objects,
+ .textsearch_find = html_textsearch_find,
+ .textsearch_bounds = html_textsearch_bounds,
+ .textselection_redraw = html_textselection_redraw,
+ .textselection_copy = html_textselection_copy,
+ .textselection_get_end = html_textselection_get_end,
.no_share = true,
};
+
+/* exported function documented in html/html.h */
nserror html_init(void)
{
uint32_t i;
@@ -2449,19 +2402,3 @@ error:
return error;
}
-
-/**
- * Get the browser window containing an HTML content
- *
- * \param c HTML content
- * \return the browser window
- */
-struct browser_window *html_get_browser_window(struct content *c)
-{
- html_content *html = (html_content *) c;
-
- assert(c != NULL);
- assert(c->handler == &html_content_handler);
-
- return html->bw;
-}
diff --git a/render/html.h b/content/handlers/html/html.h
index 30219a3bd..8d1c77992 100644
--- a/render/html.h
+++ b/content/handlers/html/html.h
@@ -16,20 +16,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Content for text/html (interface).
+/**
+ * \file
+ * Interface to text/html content handler.
*
* These functions should in general be called via the content interface.
*/
-#ifndef _NETSURF_RENDER_HTML_H_
-#define _NETSURF_RENDER_HTML_H_
+#ifndef NETSURF_HTML_HTML_H
+#define NETSURF_HTML_HTML_H
#include <stdbool.h>
-#include <dom/dom.h>
-#include <dom/bindings/hubbub/parser.h>
-
#include "netsurf/types.h"
#include "netsurf/content_type.h"
#include "netsurf/browser_window.h"
@@ -64,6 +62,7 @@ struct html_stylesheet {
bool unused;
};
+
/**
* Container for scripts used by an HTML document
*/
@@ -88,7 +87,9 @@ struct html_script {
};
-/** An object (img, object, etc. tag) in a CONTENT_HTML document. */
+/**
+ * An object (img, object, etc. tag) in a CONTENT_HTML document.
+ */
struct content_html_object {
struct content *parent; /**< Parent document */
struct content_html_object *next; /**< Next in chain */
@@ -100,12 +101,10 @@ struct content_html_object {
bool background; /**< This object is a background image. */
};
-struct html_scrollbar_data {
- struct content *c;
- struct box *box;
-};
-/** Frame tree (frameset or frame tag) */
+/**
+ * Frame tree (frameset or frame tag)
+ */
struct content_html_frames {
int cols; /** number of columns in frameset */
int rows; /** number of rows in frameset */
@@ -126,9 +125,11 @@ struct content_html_frames {
struct content_html_frames *children; /** [cols * rows] children */
};
-/** Inline frame list (iframe tag) */
+/**
+ * Inline frame list (iframe tag)
+ */
struct content_html_iframe {
- struct box *box;
+ struct box *box;
int margin_width; /** frame margin width */
int margin_height; /** frame margin height */
@@ -140,7 +141,7 @@ struct content_html_iframe {
bool border; /** frame has a border */
colour border_colour; /** frame border colour */
- struct content_html_iframe *next;
+ struct content_html_iframe *next;
};
/* entries in stylesheet_content */
@@ -150,32 +151,46 @@ struct content_html_iframe {
#define STYLESHEET_USER 3 /* user stylesheet */
#define STYLESHEET_START 4 /* start of document stylesheets */
+/**
+ * initialise content handler
+ *
+ * \return NSERROR_OK on success otherwise appropriate error code
+ */
nserror html_init(void);
+/**
+ * redraw a specific box
+ *
+ * used by core browser
+ */
void html_redraw_a_box(struct hlcache_handle *h, struct box *box);
-void html_overflow_scroll_drag_end(struct scrollbar *scrollbar,
- browser_mouse_state mouse, int x, int y);
-
-bool text_redraw(const char *utf8_text, size_t utf8_len,
- size_t offset, int space,
- const struct plot_font_style *fstyle,
- int x, int y,
- const struct rect *clip,
- int height,
- float scale,
- bool excluded,
- struct content *c,
- const struct selection *sel,
- struct search_context *search,
- const struct redraw_context *ctx);
-
-dom_document *html_get_document(struct hlcache_handle *h);
-struct box *html_get_box_tree(struct hlcache_handle *h);
+/**
+ * obtain html frame content from handle
+ *
+ * used by core browser
+ */
struct content_html_frames *html_get_frameset(struct hlcache_handle *h);
+
+/**
+ * obtain html iframe content from handle
+ *
+ * used by core browser
+ */
struct content_html_iframe *html_get_iframe(struct hlcache_handle *h);
-struct nsurl *html_get_base_url(struct hlcache_handle *h);
+
+/**
+ * obtain html base target from handle
+ *
+ * used by core browser
+ */
const char *html_get_base_target(struct hlcache_handle *h);
+
+/**
+ * set filename on a file gadget
+ *
+ * used by core browser
+ */
void html_set_file_gadget_filename(struct hlcache_handle *hl,
struct form_control *gadget, const char *fn);
@@ -189,8 +204,19 @@ void html_set_file_gadget_filename(struct hlcache_handle *hl,
struct html_stylesheet *html_get_stylesheets(struct hlcache_handle *h,
unsigned int *n);
+/**
+ * Retrieve objects used by HTML document
+ *
+ * \param h Content to retrieve objects from
+ * \param n Pointer to location to receive number of objects
+ * \return Pointer to array of objects
+ */
struct content_html_object *html_get_objects(struct hlcache_handle *h,
unsigned int *n);
+
+/**
+ * get the offset within the docuemnt of a fragment id
+ */
bool html_get_id_offset(struct hlcache_handle *h, lwc_string *frag_id,
int *x, int *y);
diff --git a/content/handlers/html/html_save.h b/content/handlers/html/html_save.h
new file mode 100644
index 000000000..c173922d5
--- /dev/null
+++ b/content/handlers/html/html_save.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2018 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Interface to HTML content handler to save documents.
+ *
+ * \todo Investigate altering this API as it is only used for
+ * exporting the html content to disc.
+ */
+
+#ifndef NETSURF_HTML_HTML_SAVE_H
+#define NETSURF_HTML_HTML_SAVE_H
+
+/**
+ * get the dom document of a html content from a handle
+ */
+dom_document *html_get_document(struct hlcache_handle *h);
+
+
+/**
+ * get the render box tree of a html content from a handle
+ */
+struct box *html_get_box_tree(struct hlcache_handle *h);
+
+/**
+ * get the base url of an html content from a handle
+ */
+struct nsurl *html_get_base_url(struct hlcache_handle *h);
+
+#endif
diff --git a/render/imagemap.c b/content/handlers/html/imagemap.c
index 0d3b42a1b..f23be2353 100644
--- a/render/imagemap.c
+++ b/content/handlers/html/imagemap.c
@@ -16,8 +16,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/*
- * Much of this shamelessly copied from utils/messages.c
+/**
+ * \file
+ * Implementation of HTML image maps
+ *
+ * \todo should this should use the general hashmap instead of its own
*/
#include <assert.h>
@@ -32,9 +35,10 @@
#include "content/content_protected.h"
#include "content/hlcache.h"
-#include "render/box.h"
-#include "render/html_internal.h"
-#include "render/imagemap.h"
+#include "html/box.h"
+#include "html/box_construct.h"
+#include "html/private.h"
+#include "html/imagemap.h"
#define HASH_SIZE 31 /* fixed size hash table */
@@ -296,8 +300,11 @@ void imagemap_dump(html_content *c)
* \return false on memory exhaustion, true otherwise
*/
static bool
-imagemap_addtolist(const struct html_content *c, dom_node *n, nsurl *base_url,
- struct mapentry **entry, dom_string *tagtype)
+imagemap_addtolist(const struct html_content *c,
+ dom_node *n,
+ nsurl *base_url,
+ struct mapentry **entry,
+ dom_string *tagtype)
{
dom_exception exc;
dom_string *href = NULL, *target = NULL, *shape = NULL;
@@ -370,13 +377,16 @@ imagemap_addtolist(const struct html_content *c, dom_node *n, nsurl *base_url,
}
if (target != NULL) {
- /* Copy target into the map */
+ /* Copy target dom string into the map data */
new_map->target = malloc(dom_string_byte_length(target) + 1);
if (new_map->target == NULL)
goto bad_out;
- /* Safe, but relies on dom_strings being NULL terminated */
- /* \todo Do this better */
- strcpy(new_map->target, dom_string_data(target));
+
+ memcpy(new_map->target,
+ dom_string_data(target),
+ dom_string_byte_length(target));
+
+ new_map->target[dom_string_byte_length(target)] = 0;
}
if (new_map->type != IMAGEMAP_DEFAULT) {
diff --git a/render/imagemap.h b/content/handlers/html/imagemap.h
index 3ae6819da..8e189a072 100644
--- a/render/imagemap.h
+++ b/content/handlers/html/imagemap.h
@@ -16,8 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_RENDER_IMAGEMAP_H_
-#define _NETSURF_RENDER_IMAGEMAP_H_
+/**
+ * \file
+ * Interface to HTML imagemap
+ */
+
+#ifndef NETSURF_HTML_IMAGEMAP_H
+#define NETSURF_HTML_IMAGEMAP_H
#include <dom/dom.h>
diff --git a/content/handlers/html/interaction.c b/content/handlers/html/interaction.c
new file mode 100644
index 000000000..0a843e026
--- /dev/null
+++ b/content/handlers/html/interaction.c
@@ -0,0 +1,1816 @@
+/*
+ * Copyright 2006 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2006 Richard Wilson <info@tinct.net>
+ * Copyright 2008 Michael Drake <tlsa@netsurf-browser.org>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * implementation of user interaction with a CONTENT_HTML.
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <dom/dom.h>
+
+#include "utils/corestrings.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "utils/log.h"
+#include "utils/nsoption.h"
+#include "netsurf/content.h"
+#include "netsurf/browser_window.h"
+#include "netsurf/mouse.h"
+#include "netsurf/misc.h"
+#include "netsurf/layout.h"
+#include "netsurf/keypress.h"
+#include "content/hlcache.h"
+#include "content/textsearch.h"
+#include "desktop/frames.h"
+#include "desktop/scrollbar.h"
+#include "desktop/selection.h"
+#include "desktop/textarea.h"
+#include "javascript/js.h"
+#include "desktop/gui_internal.h"
+
+#include "html/box.h"
+#include "html/box_textarea.h"
+#include "html/box_inspect.h"
+#include "html/font.h"
+#include "html/form_internal.h"
+#include "html/private.h"
+#include "html/imagemap.h"
+#include "html/interaction.h"
+
+/**
+ * Get pointer shape for given box
+ *
+ * \param box box in question
+ * \param imagemap whether an imagemap applies to the box
+ */
+
+static browser_pointer_shape get_pointer_shape(struct box *box, bool imagemap)
+{
+ browser_pointer_shape pointer;
+ css_computed_style *style;
+ enum css_cursor_e cursor;
+ lwc_string **cursor_uris;
+
+ if (box->type == BOX_FLOAT_LEFT || box->type == BOX_FLOAT_RIGHT)
+ style = box->children->style;
+ else
+ style = box->style;
+
+ if (style == NULL)
+ return BROWSER_POINTER_DEFAULT;
+
+ cursor = css_computed_cursor(style, &cursor_uris);
+
+ switch (cursor) {
+ case CSS_CURSOR_AUTO:
+ if (box->href || (box->gadget &&
+ (box->gadget->type == GADGET_IMAGE ||
+ box->gadget->type == GADGET_SUBMIT)) ||
+ imagemap) {
+ /* link */
+ pointer = BROWSER_POINTER_POINT;
+ } else if (box->gadget &&
+ (box->gadget->type == GADGET_TEXTBOX ||
+ box->gadget->type == GADGET_PASSWORD ||
+ box->gadget->type == GADGET_TEXTAREA)) {
+ /* text input */
+ pointer = BROWSER_POINTER_CARET;
+ } else {
+ /* html content doesn't mind */
+ pointer = BROWSER_POINTER_AUTO;
+ }
+ break;
+ case CSS_CURSOR_CROSSHAIR:
+ pointer = BROWSER_POINTER_CROSS;
+ break;
+ case CSS_CURSOR_POINTER:
+ pointer = BROWSER_POINTER_POINT;
+ break;
+ case CSS_CURSOR_MOVE:
+ pointer = BROWSER_POINTER_MOVE;
+ break;
+ case CSS_CURSOR_E_RESIZE:
+ pointer = BROWSER_POINTER_RIGHT;
+ break;
+ case CSS_CURSOR_W_RESIZE:
+ pointer = BROWSER_POINTER_LEFT;
+ break;
+ case CSS_CURSOR_N_RESIZE:
+ pointer = BROWSER_POINTER_UP;
+ break;
+ case CSS_CURSOR_S_RESIZE:
+ pointer = BROWSER_POINTER_DOWN;
+ break;
+ case CSS_CURSOR_NE_RESIZE:
+ pointer = BROWSER_POINTER_RU;
+ break;
+ case CSS_CURSOR_SW_RESIZE:
+ pointer = BROWSER_POINTER_LD;
+ break;
+ case CSS_CURSOR_SE_RESIZE:
+ pointer = BROWSER_POINTER_RD;
+ break;
+ case CSS_CURSOR_NW_RESIZE:
+ pointer = BROWSER_POINTER_LU;
+ break;
+ case CSS_CURSOR_TEXT:
+ pointer = BROWSER_POINTER_CARET;
+ break;
+ case CSS_CURSOR_WAIT:
+ pointer = BROWSER_POINTER_WAIT;
+ break;
+ case CSS_CURSOR_PROGRESS:
+ pointer = BROWSER_POINTER_PROGRESS;
+ break;
+ case CSS_CURSOR_HELP:
+ pointer = BROWSER_POINTER_HELP;
+ break;
+ default:
+ pointer = BROWSER_POINTER_DEFAULT;
+ break;
+ }
+
+ return pointer;
+}
+
+
+/**
+ * Start drag scrolling the contents of a box
+ *
+ * \param box the box to be scrolled
+ * \param x x ordinate of initial mouse position
+ * \param y y ordinate
+ */
+
+static void html_box_drag_start(struct box *box, int x, int y)
+{
+ int box_x, box_y;
+ int scroll_mouse_x, scroll_mouse_y;
+
+ box_coords(box, &box_x, &box_y);
+
+ if (box->scroll_x != NULL) {
+ scroll_mouse_x = x - box_x ;
+ scroll_mouse_y = y - (box_y + box->padding[TOP] +
+ box->height + box->padding[BOTTOM] -
+ SCROLLBAR_WIDTH);
+ scrollbar_start_content_drag(box->scroll_x,
+ scroll_mouse_x, scroll_mouse_y);
+ } else if (box->scroll_y != NULL) {
+ scroll_mouse_x = x - (box_x + box->padding[LEFT] +
+ box->width + box->padding[RIGHT] -
+ SCROLLBAR_WIDTH);
+ scroll_mouse_y = y - box_y;
+
+ scrollbar_start_content_drag(box->scroll_y,
+ scroll_mouse_x, scroll_mouse_y);
+ }
+}
+
+
+/**
+ * End overflow scroll scrollbar drags
+ *
+ * \param html html content
+ * \param mouse state of mouse buttons and modifier keys
+ * \param x coordinate of mouse
+ * \param y coordinate of mouse
+ * \param dir Direction of drag
+ */
+static size_t html_selection_drag_end(struct html_content *html,
+ browser_mouse_state mouse, int x, int y, int dir)
+{
+ int pixel_offset;
+ struct box *box;
+ int dx, dy;
+ size_t idx = 0;
+
+ box = box_pick_text_box(html, x, y, dir, &dx, &dy);
+ if (box) {
+ plot_font_style_t fstyle;
+
+ font_plot_style_from_css(&html->unit_len_ctx, box->style, &fstyle);
+
+ guit->layout->position(&fstyle, box->text, box->length,
+ dx, &idx, &pixel_offset);
+
+ idx += box->byte_offset;
+ }
+
+ return idx;
+}
+
+
+/**
+ * Helper for file gadgets to store their filename.
+ *
+ * Stores the filename unencoded on the dom node associated with the
+ * gadget.
+ *
+ * \todo Get rid of this crap eventually
+ *
+ * \param operation DOM operation
+ * \param key DOM node key being considerd
+ * \param _data The data assocated with the key
+ * \param src The source DOM node.
+ * \param dst The destination DOM node.
+ */
+static void
+html__image_coords_dom_user_data_handler(dom_node_operation operation,
+ dom_string *key,
+ void *_data,
+ struct dom_node *src,
+ struct dom_node *dst)
+{
+ struct image_input_coords *oldcoords, *coords = _data, *newcoords;
+
+ if (!dom_string_isequal(corestring_dom___ns_key_image_coords_node_data,
+ key) || coords == NULL) {
+ return;
+ }
+
+ switch (operation) {
+ case DOM_NODE_CLONED:
+ newcoords = calloc(1, sizeof(*newcoords));
+ if (newcoords != NULL) {
+ *newcoords = *coords;
+ if (dom_node_set_user_data(dst,
+ corestring_dom___ns_key_image_coords_node_data,
+ newcoords,
+ html__image_coords_dom_user_data_handler,
+ &oldcoords) == DOM_NO_ERR) {
+ free(oldcoords);
+ }
+ }
+ break;
+
+ case DOM_NODE_DELETED:
+ free(coords);
+ break;
+
+ case DOM_NODE_RENAMED:
+ case DOM_NODE_IMPORTED:
+ case DOM_NODE_ADOPTED:
+ break;
+
+ default:
+ NSLOG(netsurf, INFO, "User data operation not handled.");
+ assert(0);
+ }
+}
+
+
+/**
+ * End overflow scroll scrollbar drags
+ *
+ * \param scrollbar scrollbar widget
+ * \param mouse state of mouse buttons and modifier keys
+ * \param x coordinate of mouse
+ * \param y coordinate of mouse
+ */
+static void
+html_overflow_scroll_drag_end(struct scrollbar *scrollbar,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ int scroll_mouse_x, scroll_mouse_y, box_x, box_y;
+ struct html_scrollbar_data *data = scrollbar_get_data(scrollbar);
+ struct box *box;
+
+ box = data->box;
+ box_coords(box, &box_x, &box_y);
+
+ if (scrollbar_is_horizontal(scrollbar)) {
+ scroll_mouse_x = x - box_x;
+ scroll_mouse_y = y - (box_y + box->padding[TOP] +
+ box->height + box->padding[BOTTOM] -
+ SCROLLBAR_WIDTH);
+ scrollbar_mouse_drag_end(scrollbar, mouse,
+ scroll_mouse_x, scroll_mouse_y);
+ } else {
+ scroll_mouse_x = x - (box_x + box->padding[LEFT] +
+ box->width + box->padding[RIGHT] -
+ SCROLLBAR_WIDTH);
+ scroll_mouse_y = y - box_y;
+ scrollbar_mouse_drag_end(scrollbar, mouse,
+ scroll_mouse_x, scroll_mouse_y);
+ }
+}
+
+
+/**
+ * handle html mouse action when select menu is open
+ *
+ */
+static nserror
+mouse_action_select_menu(html_content *html,
+ struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ struct box *box;
+ int box_x = 0;
+ int box_y = 0;
+ const char *status;
+ int width, height;
+ struct hlcache_handle *bw_content;
+ browser_drag_type bw_drag_type;
+
+ assert(html->visible_select_menu != NULL);
+
+ bw_drag_type = browser_window_get_drag_type(bw);
+ if (bw_drag_type != DRAGGING_NONE && !mouse) {
+ /* drag end: select menu */
+ form_select_mouse_drag_end(html->visible_select_menu, mouse, x, y);
+ }
+
+ box = html->visible_select_menu->box;
+ box_coords(box, &box_x, &box_y);
+
+ box_x -= box->border[LEFT].width;
+ box_y += box->height + box->border[BOTTOM].width +
+ box->padding[BOTTOM] + box->padding[TOP];
+
+ status = form_select_mouse_action(html->visible_select_menu,
+ mouse,
+ x - box_x,
+ y - box_y);
+ if (status != NULL) {
+ /* set status if menu still open */
+ union content_msg_data msg_data;
+ msg_data.explicit_status_text = status;
+ content_broadcast((struct content *)html,
+ CONTENT_MSG_STATUS,
+ &msg_data);
+ return NSERROR_OK;
+ }
+
+ /* close menu and redraw where it was */
+ form_select_get_dimensions(html->visible_select_menu, &width, &height);
+
+ html->visible_select_menu = NULL;
+
+ bw_content = browser_window_get_content(bw);
+ content_request_redraw(bw_content,
+ box_x,
+ box_y,
+ width,
+ height);
+ return NSERROR_OK;
+}
+
+
+/**
+ * handle html mouse action when a selection drag is being performed
+ *
+ */
+static nserror
+mouse_action_drag_selection(html_content *html,
+ struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ struct box *box;
+ int dir = -1;
+ int dx, dy;
+ size_t idx;
+ union html_drag_owner drag_owner;
+ int pixel_offset;
+ plot_font_style_t fstyle;
+
+ if (!mouse) {
+ /* End of selection drag */
+ if (selection_dragging_start(html->sel)) {
+ dir = 1;
+ }
+
+ idx = html_selection_drag_end(html, mouse, x, y, dir);
+
+ if (idx != 0) {
+ selection_track(html->sel, mouse, idx);
+ }
+
+ drag_owner.no_owner = true;
+ html_set_drag_type(html, HTML_DRAG_NONE, drag_owner, NULL);
+
+ return NSERROR_OK;
+ }
+
+ if (selection_dragging_start(html->sel)) {
+ dir = 1;
+ }
+
+ box = box_pick_text_box(html, x, y, dir, &dx, &dy);
+ if (box != NULL) {
+ font_plot_style_from_css(&html->unit_len_ctx, box->style, &fstyle);
+
+ guit->layout->position(&fstyle,
+ box->text,
+ box->length,
+ dx,
+ &idx,
+ &pixel_offset);
+
+ selection_track(html->sel, mouse, box->byte_offset + idx);
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * handle html mouse action when a scrollbar drag is being performed
+ *
+ */
+static nserror
+mouse_action_drag_scrollbar(html_content *html,
+ struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ struct scrollbar *scr;
+ struct html_scrollbar_data *data;
+ struct box *box;
+ int box_x = 0;
+ int box_y = 0;
+ const char *status;
+ int scroll_mouse_x = 0, scroll_mouse_y = 0;
+ scrollbar_mouse_status scrollbar_status;
+
+ scr = html->drag_owner.scrollbar;
+
+ if (!mouse) {
+ /* drag end: scrollbar */
+ html_overflow_scroll_drag_end(scr, mouse, x, y);
+ }
+
+ data = scrollbar_get_data(scr);
+
+ box = data->box;
+
+ box_coords(box, &box_x, &box_y);
+
+ if (scrollbar_is_horizontal(scr)) {
+ scroll_mouse_x = x - box_x ;
+ scroll_mouse_y = y - (box_y + box->padding[TOP] +
+ box->height + box->padding[BOTTOM] -
+ SCROLLBAR_WIDTH);
+ scrollbar_status = scrollbar_mouse_action(scr,
+ mouse,
+ scroll_mouse_x,
+ scroll_mouse_y);
+ } else {
+ scroll_mouse_x = x - (box_x + box->padding[LEFT] +
+ box->width + box->padding[RIGHT] -
+ SCROLLBAR_WIDTH);
+ scroll_mouse_y = y - box_y;
+
+ scrollbar_status = scrollbar_mouse_action(scr,
+ mouse,
+ scroll_mouse_x,
+ scroll_mouse_y);
+ }
+ status = scrollbar_mouse_status_to_message(scrollbar_status);
+
+ if (status != NULL) {
+ union content_msg_data msg_data;
+
+ msg_data.explicit_status_text = status;
+ content_broadcast((struct content *)html,
+ CONTENT_MSG_STATUS,
+ &msg_data);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * handle mouse actions while dragging in a text area
+ */
+static nserror
+mouse_action_drag_textarea(html_content *html,
+ struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ struct box *box;
+ int box_x = 0;
+ int box_y = 0;
+
+ box = html->drag_owner.textarea;
+
+ assert(box->gadget != NULL);
+ assert(box->gadget->type == GADGET_TEXTAREA ||
+ box->gadget->type == GADGET_PASSWORD ||
+ box->gadget->type == GADGET_TEXTBOX);
+
+ box_coords(box, &box_x, &box_y);
+ textarea_mouse_action(box->gadget->data.text.ta,
+ mouse,
+ x - box_x,
+ y - box_y);
+
+ /* TODO: Set appropriate statusbar message */
+ return NSERROR_OK;
+}
+
+
+/**
+ * handle mouse actions while dragging in a content
+ */
+static nserror
+mouse_action_drag_content(html_content *html,
+ struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ struct box *box;
+ int box_x = 0;
+ int box_y = 0;
+
+ box = html->drag_owner.content;
+ assert(box->object != NULL);
+
+ box_coords(box, &box_x, &box_y);
+ content_mouse_track(box->object,
+ bw, mouse,
+ x - box_x,
+ y - box_y);
+ return NSERROR_OK;
+}
+
+
+/**
+ * local structure containing all the mouse action state information
+ */
+struct mouse_action_state {
+ struct {
+ const char *status; /**< status text */
+ browser_pointer_shape pointer; /**< pointer shape */
+ enum {
+ ACTION_NONE,
+ ACTION_NOSEND, /**< do not send status and pointer message */
+ ACTION_SUBMIT,
+ ACTION_GO,
+ ACTION_JS,
+ } action;
+ } result;
+
+ /** dom node */
+ struct dom_node *node;
+
+ /** html object */
+ struct {
+ struct box *box;
+ int pos_x;
+ int pos_y;
+ } html_object;
+
+ /** non html object */
+ hlcache_handle *object;
+
+ /** iframe */
+ struct browser_window *iframe;
+
+ /** link either from href or imagemap */
+ struct {
+ struct box *box;
+ nsurl *url;
+ const char *target;
+ bool is_imagemap;
+ } link;
+
+ /** gadget */
+ struct {
+ struct form_control *control;
+ struct box *box;
+ int box_x;
+ int box_y;
+ const char *target;
+ } gadget;
+
+ /** title */
+ const char *title;
+
+ /** candidate box for drag operation */
+ struct box *drag_candidate;
+
+ /** scrollbar */
+ struct {
+ struct scrollbar *bar;
+ int mouse_x;
+ int mouse_y;
+ } scroll;
+
+ /** text in box */
+ struct {
+ struct box *box;
+ int box_x;
+ } text;
+};
+
+
+/**
+ * iterate the box tree for deepest node at coordinates
+ *
+ * extracts mouse action node information by descending through
+ * visible boxes setting more specific values for:
+ *
+ * box - deepest box at point
+ * html_object_box - html object
+ * html_object_pos_x - html object
+ * html_object_pos_y - html object
+ * object - non html object
+ * iframe - iframe
+ * url - href or imagemap
+ * target - href or imagemap or gadget
+ * url_box - href or imagemap
+ * imagemap - imagemap
+ * gadget - gadget
+ * gadget_box - gadget
+ * gadget_box_x - gadget
+ * gadget_box_y - gadget
+ * title - title
+ * pointer
+ *
+ * drag_candidate - first box with scroll
+ * padding_left - box with scroll
+ * padding_right
+ * padding_top
+ * padding_bottom
+ * scrollbar - inside padding box stops decent
+ * scroll_mouse_x - inside padding box stops decent
+ * scroll_mouse_y - inside padding box stops decent
+ *
+ * text_box - text box
+ * text_box_x - text_box
+ */
+static nserror
+get_mouse_action_node(html_content *html,
+ int x, int y,
+ struct mouse_action_state *man)
+{
+ struct box *box;
+ int box_x = 0;
+ int box_y = 0;
+
+ /* initialise the mouse action state data */
+ memset(man, 0, sizeof(struct mouse_action_state));
+ man->node = html->layout->node; /* Default dom node to the <HTML> */
+ man->result.pointer = BROWSER_POINTER_DEFAULT;
+
+ /* search the box tree for a link, imagemap, form control, or
+ * box with scrollbars
+ */
+ box = html->layout;
+
+ /* Consider the margins of the html page now */
+ box_x = box->margin[LEFT];
+ box_y = box->margin[TOP];
+
+ do {
+ /* skip hidden boxes */
+ if ((box->style != NULL) &&
+ (css_computed_visibility(box->style) ==
+ CSS_VISIBILITY_HIDDEN)) {
+ goto next_box;
+ }
+
+ if (box->node != NULL) {
+ man->node = box->node;
+ }
+
+ if (box->object) {
+ if (content_get_type(box->object) == CONTENT_HTML) {
+ man->html_object.box = box;
+ man->html_object.pos_x = box_x;
+ man->html_object.pos_y = box_y;
+ } else {
+ man->object = box->object;
+ }
+ }
+
+ if (box->iframe) {
+ man->iframe = box->iframe;
+ }
+
+ if (box->href) {
+ man->link.url = box->href;
+ man->link.target = box->target;
+ man->link.box = box;
+ man->link.is_imagemap = false;
+ }
+
+ if (box->usemap) {
+ man->link.url = imagemap_get(html,
+ box->usemap,
+ box_x,
+ box_y,
+ x, y,
+ &man->link.target);
+ man->link.box = box;
+ man->link.is_imagemap = true;
+ }
+
+ if (box->gadget) {
+ man->gadget.control = box->gadget;
+ man->gadget.box = box;
+ man->gadget.box_x = box_x;
+ man->gadget.box_y = box_y;
+ if (box->gadget->form) {
+ man->gadget.target = box->gadget->form->target;
+ }
+ }
+
+ if (box->title) {
+ man->title = box->title;
+ }
+
+ man->result.pointer = get_pointer_shape(box, false);
+
+ if ((box->scroll_x != NULL) ||
+ (box->scroll_y != NULL)) {
+ int padding_left;
+ int padding_right;
+ int padding_top;
+ int padding_bottom;
+
+ if (man->drag_candidate == NULL) {
+ man->drag_candidate = box;
+ }
+
+ padding_left = box_x +
+ scrollbar_get_offset(box->scroll_x);
+ padding_right = padding_left + box->padding[LEFT] +
+ box->width + box->padding[RIGHT];
+ padding_top = box_y +
+ scrollbar_get_offset(box->scroll_y);
+ padding_bottom = padding_top + box->padding[TOP] +
+ box->height + box->padding[BOTTOM];
+
+ if ((x > padding_left) &&
+ (x < padding_right) &&
+ (y > padding_top) &&
+ (y < padding_bottom)) {
+ /* mouse inside padding box */
+
+ if ((box->scroll_y != NULL) &&
+ (x > (padding_right - SCROLLBAR_WIDTH))) {
+ /* mouse above vertical box scroll */
+
+ man->scroll.bar = box->scroll_y;
+ man->scroll.mouse_x = x - (padding_right - SCROLLBAR_WIDTH);
+ man->scroll.mouse_y = y - padding_top;
+ break;
+
+ } else if ((box->scroll_x != NULL) &&
+ (y > (padding_bottom -
+ SCROLLBAR_WIDTH))) {
+ /* mouse above horizontal box scroll */
+
+ man->scroll.bar = box->scroll_x;
+ man->scroll.mouse_x = x - padding_left;
+ man->scroll.mouse_y = y - (padding_bottom - SCROLLBAR_WIDTH);
+ break;
+ }
+ }
+ }
+
+ if (box->text && !box->object) {
+ man->text.box = box;
+ man->text.box_x = box_x;
+ }
+
+ next_box:
+ /* iterate to next box */
+ box = box_at_point(&html->unit_len_ctx, box, x, y, &box_x, &box_y);
+ } while (box != NULL);
+
+ /* use of box_x, box_y, or content below this point is probably a
+ * mistake; they will refer to the last box returned by box_at_point */
+
+ assert(man->node != NULL);
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * process mouse activity on a form gadget
+ */
+static nserror
+gadget_mouse_action(html_content *html,
+ browser_mouse_state mouse,
+ int x, int y,
+ struct mouse_action_state *mas)
+{
+ struct content *c = (struct content *)html;
+ textarea_mouse_status ta_status;
+ union content_msg_data msg_data;
+ nserror res;
+ bool click;
+ click = mouse & (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2 |
+ BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2 |
+ BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2);
+
+ switch (mas->gadget.control->type) {
+ case GADGET_SELECT:
+ mas->result.status = messages_get("FormSelect");
+ mas->result.pointer = BROWSER_POINTER_MENU;
+ if (mouse & BROWSER_MOUSE_CLICK_1 &&
+ nsoption_bool(core_select_menu)) {
+ html->visible_select_menu = mas->gadget.control;
+ res = form_open_select_menu(c,
+ mas->gadget.control,
+ form_select_menu_callback,
+ c);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, ERROR, "%s",
+ messages_get_errorcode(res));
+ html->visible_select_menu = NULL;
+ }
+ mas->result.pointer = BROWSER_POINTER_DEFAULT;
+ } else if (mouse & BROWSER_MOUSE_CLICK_1) {
+ msg_data.select_menu.gadget = mas->gadget.control;
+ content_broadcast(c,
+ CONTENT_MSG_SELECTMENU,
+ &msg_data);
+ }
+ break;
+
+ case GADGET_CHECKBOX:
+ mas->result.status = messages_get("FormCheckbox");
+ if (mouse & BROWSER_MOUSE_CLICK_1) {
+ mas->gadget.control->selected = !mas->gadget.control->selected;
+ dom_html_input_element_set_checked(
+ (dom_html_input_element *)(mas->gadget.control->node),
+ mas->gadget.control->selected);
+ html__redraw_a_box(html, mas->gadget.box);
+ }
+ break;
+
+ case GADGET_RADIO:
+ mas->result.status = messages_get("FormRadio");
+ if (mouse & BROWSER_MOUSE_CLICK_1) {
+ form_radio_set(mas->gadget.control);
+ }
+ break;
+
+ case GADGET_IMAGE:
+ /* This falls through to SUBMIT */
+ if (mouse & BROWSER_MOUSE_CLICK_1) {
+ struct image_input_coords *coords, *oldcoords;
+ /** \todo Find a way to not ignore errors */
+ coords = calloc(1, sizeof(*coords));
+ if (coords == NULL) {
+ return NSERROR_OK;
+ }
+ coords->x = x - mas->gadget.box_x;
+ coords->y = y - mas->gadget.box_y;
+ if (dom_node_set_user_data(
+ mas->gadget.control->node,
+ corestring_dom___ns_key_image_coords_node_data,
+ coords,
+ html__image_coords_dom_user_data_handler,
+ &oldcoords) != DOM_NO_ERR) {
+ return NSERROR_OK;
+ }
+ free(oldcoords);
+ }
+ fallthrough;
+
+ case GADGET_SUBMIT:
+ if (mas->gadget.control->form) {
+ static char status_buffer[200];
+
+ snprintf(status_buffer,
+ sizeof status_buffer,
+ messages_get("FormSubmit"),
+ mas->gadget.control->form->action);
+ mas->result.status = status_buffer;
+ mas->result.pointer = get_pointer_shape(mas->gadget.box,
+ false);
+ if (mouse & (BROWSER_MOUSE_CLICK_1 |
+ BROWSER_MOUSE_CLICK_2)) {
+ mas->result.action = ACTION_SUBMIT;
+ }
+ } else {
+ mas->result.status = messages_get("FormBadSubmit");
+ }
+ break;
+
+ case GADGET_TEXTBOX:
+ case GADGET_PASSWORD:
+ case GADGET_TEXTAREA:
+ if (mas->gadget.control->type == GADGET_TEXTAREA) {
+ mas->result.status = messages_get("FormTextarea");
+ } else {
+ mas->result.status = messages_get("FormTextbox");
+ }
+
+ if (click &&
+ (html->selection_type != HTML_SELECTION_TEXTAREA ||
+ html->selection_owner.textarea != mas->gadget.box)) {
+ union html_selection_owner sel_owner;
+ sel_owner.none = true;
+ html_set_selection(html,
+ HTML_SELECTION_NONE,
+ sel_owner,
+ true);
+ }
+
+ ta_status = textarea_mouse_action(mas->gadget.control->data.text.ta,
+ mouse,
+ x - mas->gadget.box_x,
+ y - mas->gadget.box_y);
+
+ if (ta_status & TEXTAREA_MOUSE_EDITOR) {
+ mas->result.pointer = get_pointer_shape(mas->gadget.box, false);
+ } else {
+ mas->result.pointer = BROWSER_POINTER_DEFAULT;
+ mas->result.status = scrollbar_mouse_status_to_message(ta_status >> 3);
+ }
+ break;
+
+ case GADGET_HIDDEN:
+ /* not possible: no box generated */
+ break;
+
+ case GADGET_RESET:
+ mas->result.status = messages_get("FormReset");
+ break;
+
+ case GADGET_FILE:
+ mas->result.status = messages_get("FormFile");
+ if (mouse & BROWSER_MOUSE_CLICK_1) {
+ msg_data.gadget_click.gadget = mas->gadget.control;
+ content_broadcast(c,
+ CONTENT_MSG_GADGETCLICK,
+ &msg_data);
+ }
+ break;
+
+ case GADGET_BUTTON:
+ /* This gadget cannot be activated */
+ mas->result.status = messages_get("FormButton");
+ break;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * process mouse activity on an iframe
+ */
+static nserror
+iframe_mouse_action(struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y,
+ struct mouse_action_state *mas)
+{
+ int pos_x, pos_y;
+ float scale;
+
+ scale = browser_window_get_scale(bw);
+
+ browser_window_get_position(mas->iframe, false, &pos_x, &pos_y);
+
+ if (mouse & BROWSER_MOUSE_CLICK_1 ||
+ mouse & BROWSER_MOUSE_CLICK_2) {
+ browser_window_mouse_click(mas->iframe,
+ mouse,
+ (x * scale) - pos_x,
+ (y * scale) - pos_y);
+ } else {
+ browser_window_mouse_track(mas->iframe,
+ mouse,
+ (x * scale) - pos_x,
+ (y * scale) - pos_y);
+ }
+ mas->result.action = ACTION_NOSEND;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * process mouse activity on an html object
+ */
+static nserror
+html_object_mouse_action(html_content *html,
+ struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y,
+ struct mouse_action_state *mas)
+{
+ bool click;
+ click = mouse & (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2 |
+ BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2 |
+ BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2);
+
+ if (click &&
+ (html->selection_type != HTML_SELECTION_CONTENT ||
+ html->selection_owner.content != mas->html_object.box)) {
+ union html_selection_owner sel_owner;
+ sel_owner.none = true;
+ html_set_selection(html, HTML_SELECTION_NONE, sel_owner, true);
+ }
+
+ if (mouse & BROWSER_MOUSE_CLICK_1 ||
+ mouse & BROWSER_MOUSE_CLICK_2) {
+ content_mouse_action(mas->html_object.box->object,
+ bw,
+ mouse,
+ x - mas->html_object.pos_x,
+ y - mas->html_object.pos_y);
+ } else {
+ content_mouse_track(mas->html_object.box->object,
+ bw,
+ mouse,
+ x - mas->html_object.pos_x,
+ y - mas->html_object.pos_y);
+ }
+
+ mas->result.action = ACTION_NOSEND;
+ return NSERROR_OK;
+}
+
+
+/**
+ * determine if a url has a javascript scheme
+ *
+ * \param urm The url to check.
+ * \return true if the url is a javascript scheme else false
+ */
+static bool is_javascript_navigate_url(nsurl *url)
+{
+ bool is_js = false;
+ lwc_string *scheme;
+
+ scheme = nsurl_get_component(url, NSURL_SCHEME);
+ if (scheme != NULL) {
+ if (scheme == corestring_lwc_javascript) {
+ is_js = true;
+ }
+ lwc_string_unref(scheme);
+ }
+ return is_js;
+}
+
+
+/**
+ * process mouse activity on a link
+ */
+static nserror
+link_mouse_action(html_content *html,
+ struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y,
+ struct mouse_action_state *mas)
+{
+ nserror res;
+ char *url_s = NULL;
+ size_t url_l = 0;
+ static char status_buffer[200];
+ union content_msg_data msg_data;
+
+ if (nsoption_bool(display_decoded_idn) == true) {
+ res = nsurl_get_utf8(mas->link.url, &url_s, &url_l);
+ if (res != NSERROR_OK) {
+ /* Unable to obtain a decoded IDN. This is not
+ * a fatal error. Ensure the string pointer
+ * is NULL so we use the encoded version.
+ */
+ url_s = NULL;
+ }
+ }
+
+ if (mas->title) {
+ snprintf(status_buffer,
+ sizeof status_buffer,
+ "%s: %s",
+ url_s ? url_s : nsurl_access(mas->link.url),
+ mas->title);
+ } else {
+ snprintf(status_buffer,
+ sizeof status_buffer,
+ "%s",
+ url_s ? url_s : nsurl_access(mas->link.url));
+ }
+
+ if (url_s != NULL) {
+ free(url_s);
+ }
+
+ mas->result.status = status_buffer;
+
+ mas->result.pointer = get_pointer_shape(mas->link.box,
+ mas->link.is_imagemap);
+
+ if (mouse & BROWSER_MOUSE_CLICK_1 &&
+ mouse & BROWSER_MOUSE_MOD_1) {
+ /* force download of link */
+ browser_window_navigate(bw,
+ mas->link.url,
+ content_get_url((struct content *)html),
+ BW_NAVIGATE_DOWNLOAD,
+ NULL,
+ NULL,
+ NULL);
+
+ } else if (mouse & BROWSER_MOUSE_CLICK_2 &&
+ mouse & BROWSER_MOUSE_MOD_1) {
+ msg_data.savelink.url = mas->link.url;
+ msg_data.savelink.title = mas->title;
+ content_broadcast((struct content *)html,
+ CONTENT_MSG_SAVELINK,
+ &msg_data);
+
+ } else if (mouse & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2)) {
+ if (is_javascript_navigate_url(mas->link.url)) {
+ mas->result.action = ACTION_JS;
+ } else {
+ mas->result.action = ACTION_GO;
+ }
+ }
+
+ return NSERROR_OK;
+}
+
+
+
+/**
+ * process mouse activity if it is not anything else
+ */
+static nserror
+default_mouse_action(html_content *html,
+ struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y,
+ struct mouse_action_state *mas)
+{
+ struct content *c = (struct content *)html;
+ bool done = false;
+
+ /* frame resizing */
+ if (browser_window_frame_resize_start(bw, mouse, x, y, &mas->result.pointer)) {
+ if (mouse & (BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2)) {
+ mas->result.status = messages_get("FrameDrag");
+ }
+ done = true;
+ }
+
+ /* if clicking in the main page, remove the selection from any
+ * text areas */
+ if (!done) {
+ union html_selection_owner sel_owner;
+ bool click;
+ click = mouse & (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2 |
+ BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2 |
+ BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2);
+
+ if (click && html->focus_type != HTML_FOCUS_SELF) {
+ union html_focus_owner fo;
+ fo.self = true;
+ html_set_focus(html, HTML_FOCUS_SELF, fo,
+ true, 0, 0, 0, NULL);
+ }
+ if (click && html->selection_type != HTML_SELECTION_SELF) {
+ sel_owner.none = true;
+ html_set_selection(html, HTML_SELECTION_NONE,
+ sel_owner, true);
+ }
+
+ if (mas->text.box) {
+ int pixel_offset;
+ size_t idx;
+ plot_font_style_t fstyle;
+
+ font_plot_style_from_css(&html->unit_len_ctx,
+ mas->text.box->style,
+ &fstyle);
+
+ guit->layout->position(&fstyle,
+ mas->text.box->text,
+ mas->text.box->length,
+ x - mas->text.box_x,
+ &idx,
+ &pixel_offset);
+
+ if (selection_click(html->sel,
+ html->bw,
+ mouse,
+ mas->text.box->byte_offset + idx)) {
+ /* key presses must be directed at the
+ * main browser window, paste text
+ * operations ignored */
+ html_drag_type drag_type;
+ union html_drag_owner drag_owner;
+
+ if (selection_dragging(html->sel)) {
+ drag_type = HTML_DRAG_SELECTION;
+ drag_owner.no_owner = true;
+ html_set_drag_type(html,
+ drag_type,
+ drag_owner,
+ NULL);
+ mas->result.status = messages_get("Selecting");
+ }
+
+ done = true;
+ }
+
+ } else if (mouse & BROWSER_MOUSE_PRESS_1) {
+ sel_owner.none = true;
+ selection_clear(html->sel, true);
+ }
+
+ if (selection_active(html->sel)) {
+ sel_owner.none = false;
+ html_set_selection(html,
+ HTML_SELECTION_SELF,
+ sel_owner,
+ true);
+ } else if (click &&
+ html->selection_type != HTML_SELECTION_NONE) {
+ sel_owner.none = true;
+ html_set_selection(html,
+ HTML_SELECTION_NONE,
+ sel_owner,
+ true);
+ }
+ }
+
+ if (!done) {
+ union content_msg_data msg_data;
+ if (mas->title) {
+ mas->result.status = mas->title;
+ }
+
+ if (mouse & BROWSER_MOUSE_DRAG_1) {
+ if (mouse & BROWSER_MOUSE_MOD_2) {
+ msg_data.dragsave.type = CONTENT_SAVE_COMPLETE;
+ msg_data.dragsave.content = NULL;
+ content_broadcast(c,
+ CONTENT_MSG_DRAGSAVE,
+ &msg_data);
+ } else {
+ if (mas->drag_candidate == NULL) {
+ browser_window_page_drag_start(bw,
+ x, y);
+ } else {
+ html_box_drag_start(mas->drag_candidate,
+ x, y);
+ }
+ mas->result.pointer = BROWSER_POINTER_MOVE;
+ }
+ } else if (mouse & BROWSER_MOUSE_DRAG_2) {
+ if (mouse & BROWSER_MOUSE_MOD_2) {
+ msg_data.dragsave.type = CONTENT_SAVE_SOURCE;
+ msg_data.dragsave.content = NULL;
+ content_broadcast(c,
+ CONTENT_MSG_DRAGSAVE,
+ &msg_data);
+ } else {
+ if (mas->drag_candidate == NULL) {
+ browser_window_page_drag_start(bw,
+ x, y);
+ } else {
+ html_box_drag_start(mas->drag_candidate,
+ x, y);
+ }
+ mas->result.pointer = BROWSER_POINTER_MOVE;
+ }
+ }
+ }
+
+ if (mouse && mouse < BROWSER_MOUSE_MOD_1) {
+ /* ensure key presses still act on the browser window */
+ union html_focus_owner fo;
+ fo.self = true;
+ html_set_focus(html, HTML_FOCUS_SELF, fo, true, 0, 0, 0, NULL);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * handle non dragging mouse actions
+ */
+static nserror
+mouse_action_drag_none(html_content *html,
+ struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ nserror res;
+ struct content *c = (struct content *)html;
+ union content_msg_data msg_data;
+ lwc_string *path;
+
+ /**
+ * computed state
+ *
+ * not on heap to avoid allocation or stack because it is large
+ */
+ static struct mouse_action_state mas;
+
+ res = get_mouse_action_node(html, x, y, &mas);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ if (mas.scroll.bar) {
+ mas.result.status = scrollbar_mouse_status_to_message(
+ scrollbar_mouse_action(mas.scroll.bar,
+ mouse,
+ mas.scroll.mouse_x,
+ mas.scroll.mouse_y));
+ mas.result.pointer = BROWSER_POINTER_DEFAULT;
+
+ } else if (mas.gadget.control) {
+ res = gadget_mouse_action(html, mouse, x, y, &mas);
+
+ } else if ((mas.object != NULL) && (mouse & BROWSER_MOUSE_MOD_2)) {
+
+ if (mouse & BROWSER_MOUSE_DRAG_2) {
+ msg_data.dragsave.type = CONTENT_SAVE_NATIVE;
+ msg_data.dragsave.content = mas.object;
+ content_broadcast(c, CONTENT_MSG_DRAGSAVE, &msg_data);
+
+ } else if (mouse & BROWSER_MOUSE_DRAG_1) {
+ msg_data.dragsave.type = CONTENT_SAVE_ORIG;
+ msg_data.dragsave.content = mas.object;
+ content_broadcast(c, CONTENT_MSG_DRAGSAVE, &msg_data);
+ }
+
+ /* \todo should have a drag-saving object msg */
+
+ } else if (mas.iframe != NULL) {
+ res = iframe_mouse_action(bw, mouse, x, y, &mas);
+
+ } else if (mas.html_object.box != NULL) {
+ res = html_object_mouse_action(html, bw, mouse, x, y, &mas);
+
+ } else if (mas.link.url != NULL) {
+ res = link_mouse_action(html, bw, mouse, x, y, &mas);
+
+ } else {
+ res = default_mouse_action(html, bw, mouse, x, y, &mas);
+
+ }
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* send status and pointer message */
+ if (mas.result.action != ACTION_NOSEND) {
+ msg_data.explicit_status_text = mas.result.status;
+ content_broadcast(c, CONTENT_MSG_STATUS, &msg_data);
+
+ msg_data.pointer = mas.result.pointer;
+ content_broadcast(c, CONTENT_MSG_POINTER, &msg_data);
+ }
+
+ /* fire dom click event */
+ if (mouse & BROWSER_MOUSE_CLICK_1) {
+ fire_generic_dom_event(corestring_dom_click, mas.node, true, true);
+ }
+
+ /* deferred actions that can cause this browser_window to be destroyed
+ * and must therefore be done after set_status/pointer
+ */
+ switch (mas.result.action) {
+ case ACTION_SUBMIT:
+ res = form_submit(content_get_url(c),
+ browser_window_find_target(bw,
+ mas.gadget.target,
+ mouse),
+ mas.gadget.control->form,
+ mas.gadget.control);
+ break;
+
+ case ACTION_GO:
+ res = browser_window_navigate(
+ browser_window_find_target(bw,
+ mas.link.target,
+ mouse),
+ mas.link.url,
+ content_get_url(c),
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+ break;
+
+ case ACTION_JS:
+ path = nsurl_get_component(mas.link.url, NSURL_PATH);
+ if (path != NULL) {
+ html_exec(c,
+ lwc_string_data(path),
+ lwc_string_length(path));
+ lwc_string_unref(path);
+ }
+ break;
+
+ case ACTION_NOSEND:
+ case ACTION_NONE:
+ res = NSERROR_OK;
+ break;
+ }
+
+ return res;
+}
+
+
+/* exported interface documented in html/interaction.h */
+nserror html_mouse_track(struct content *c,
+ struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ return html_mouse_action(c, bw, mouse, x, y);
+}
+
+
+/* exported interface documented in html/interaction.h */
+nserror
+html_mouse_action(struct content *c,
+ struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ html_content *html = (html_content *)c;
+ nserror res = NSERROR_OK;
+
+ /* handle open select menu */
+ if (html->visible_select_menu != NULL) {
+ return mouse_action_select_menu(html, bw, mouse, x, y);
+ }
+
+ /* handle content drag */
+ switch (html->drag_type) {
+ case HTML_DRAG_SELECTION:
+ res = mouse_action_drag_selection(html, bw, mouse, x, y);
+ break;
+
+ case HTML_DRAG_SCROLLBAR:
+ res = mouse_action_drag_scrollbar(html, bw, mouse, x, y);
+ break;
+
+ case HTML_DRAG_TEXTAREA_SELECTION:
+ case HTML_DRAG_TEXTAREA_SCROLLBAR:
+ res = mouse_action_drag_textarea(html, bw, mouse, x, y);
+ break;
+
+ case HTML_DRAG_CONTENT_SELECTION:
+ case HTML_DRAG_CONTENT_SCROLL:
+ res = mouse_action_drag_content(html, bw, mouse, x, y);
+ break;
+
+ case HTML_DRAG_NONE:
+ res = mouse_action_drag_none(html, bw, mouse, x, y);
+ break;
+
+ default:
+ /* Unknown content related drag type */
+ assert(0 && "Unknown content related drag type");
+ }
+
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, ERROR, "%s", messages_get_errorcode(res));
+ }
+
+ return res;
+}
+
+
+/**
+ * Handle keypresses.
+ *
+ * \param c content of type HTML
+ * \param key The UCS4 character codepoint
+ * \return true if key handled, false otherwise
+ */
+bool html_keypress(struct content *c, uint32_t key)
+{
+ html_content *html = (html_content *) c;
+ struct selection *sel = html->sel;
+
+ /** \todo
+ * At the moment, the front end interface for keypress only gives
+ * us a UCS4 key value. This doesn't doesn't have all the information
+ * we need to fill out the event properly. We don't get to know about
+ * modifier keys, and things like CTRL+C are passed in as
+ * \ref NS_KEY_COPY_SELECTION, a magic value outside the valid Unicode
+ * range.
+ *
+ * We need to:
+ *
+ * 1. Update the front end interface so that both press and release
+ * events reach the core.
+ * 2. Stop encoding the special keys like \ref NS_KEY_COPY_SELECTION as
+ * magic values in the front ends, so we just get the events, e.g.:
+ * 1. Press ctrl
+ * 2. Press c
+ * 3. Release c
+ * 4. Release ctrl
+ * 3. Pass all the new info to the DOM KeyboardEvent events.
+ * 4. If there is a focused element, fire the event at that, instead of
+ * `html->layout->node`.
+ * 5. Rebuild the \ref NS_KEY_COPY_SELECTION values from the info we
+ * now get given, and use that for the code below this
+ * \ref fire_dom_keyboard_event call.
+ * 6. Move the code after this \ref fire_dom_keyboard_event call into
+ * the default action handler for DOM events.
+ *
+ * This will mean that if the JavaScript event listener does
+ * `event.preventDefault()` then we won't handle the event when
+ * we're not supposed to.
+ */
+ if (html->layout != NULL && html->layout->node != NULL) {
+ fire_dom_keyboard_event(corestring_dom_keydown,
+ html->layout->node, true, true, key);
+ }
+
+ switch (html->focus_type) {
+ case HTML_FOCUS_CONTENT:
+ return content_keypress(html->focus_owner.content->object, key);
+
+ case HTML_FOCUS_TEXTAREA:
+ if (box_textarea_keypress(html, html->focus_owner.textarea, key) == NSERROR_OK) {
+ return true;
+ } else {
+ return false;
+ }
+
+ default:
+ /* Deal with it below */
+ break;
+ }
+
+ switch (key) {
+ case NS_KEY_COPY_SELECTION:
+ selection_copy_to_clipboard(sel);
+ return true;
+
+ case NS_KEY_CLEAR_SELECTION:
+ selection_clear(sel, true);
+ return true;
+
+ case NS_KEY_SELECT_ALL:
+ selection_select_all(sel);
+ return true;
+
+ case NS_KEY_ESCAPE:
+ /* if there's no selection, leave Escape for the caller */
+ return selection_clear(sel, true);
+ }
+
+ return false;
+}
+
+
+/**
+ * Callback for in-page scrollbars.
+ */
+void html_overflow_scroll_callback(void *client_data,
+ struct scrollbar_msg_data *scrollbar_data)
+{
+ struct html_scrollbar_data *data = client_data;
+ html_content *html = (html_content *)data->c;
+ struct box *box = data->box;
+ union content_msg_data msg_data;
+ html_drag_type drag_type;
+ union html_drag_owner drag_owner;
+
+ switch(scrollbar_data->msg) {
+ case SCROLLBAR_MSG_MOVED:
+
+ if (html->reflowing == true) {
+ /* Can't redraw during layout, and it will
+ * be redrawn after layout anyway. */
+ break;
+ }
+
+ html__redraw_a_box(html, box);
+ break;
+ case SCROLLBAR_MSG_SCROLL_START:
+ {
+ struct rect rect = {
+ .x0 = scrollbar_data->x0,
+ .y0 = scrollbar_data->y0,
+ .x1 = scrollbar_data->x1,
+ .y1 = scrollbar_data->y1
+ };
+ drag_type = HTML_DRAG_SCROLLBAR;
+ drag_owner.scrollbar = scrollbar_data->scrollbar;
+ html_set_drag_type(html, drag_type, drag_owner, &rect);
+ }
+ break;
+ case SCROLLBAR_MSG_SCROLL_FINISHED:
+ drag_type = HTML_DRAG_NONE;
+ drag_owner.no_owner = true;
+ html_set_drag_type(html, drag_type, drag_owner, NULL);
+
+ msg_data.pointer = BROWSER_POINTER_AUTO;
+ content_broadcast(data->c, CONTENT_MSG_POINTER, &msg_data);
+ break;
+ }
+}
+
+
+/* Documented in html_internal.h */
+void html_set_drag_type(html_content *html, html_drag_type drag_type,
+ union html_drag_owner drag_owner, const struct rect *rect)
+{
+ union content_msg_data msg_data;
+
+ assert(html != NULL);
+
+ html->drag_type = drag_type;
+ html->drag_owner = drag_owner;
+
+ switch (drag_type) {
+ case HTML_DRAG_NONE:
+ assert(drag_owner.no_owner == true);
+ msg_data.drag.type = CONTENT_DRAG_NONE;
+ break;
+
+ case HTML_DRAG_SCROLLBAR:
+ case HTML_DRAG_TEXTAREA_SCROLLBAR:
+ case HTML_DRAG_CONTENT_SCROLL:
+ msg_data.drag.type = CONTENT_DRAG_SCROLL;
+ break;
+
+ case HTML_DRAG_SELECTION:
+ assert(drag_owner.no_owner == true);
+ fallthrough;
+ case HTML_DRAG_TEXTAREA_SELECTION:
+ case HTML_DRAG_CONTENT_SELECTION:
+ msg_data.drag.type = CONTENT_DRAG_SELECTION;
+ break;
+ }
+ msg_data.drag.rect = rect;
+
+ /* Inform of the content's drag status change */
+ content_broadcast((struct content *)html, CONTENT_MSG_DRAG, &msg_data);
+}
+
+/* Documented in html_internal.h */
+void html_set_focus(html_content *html, html_focus_type focus_type,
+ union html_focus_owner focus_owner, bool hide_caret,
+ int x, int y, int height, const struct rect *clip)
+{
+ union content_msg_data msg_data;
+ int x_off = 0;
+ int y_off = 0;
+ struct rect cr;
+ bool textarea_lost_focus = html->focus_type == HTML_FOCUS_TEXTAREA &&
+ focus_type != HTML_FOCUS_TEXTAREA;
+
+ assert(html != NULL);
+
+ switch (focus_type) {
+ case HTML_FOCUS_SELF:
+ assert(focus_owner.self == true);
+ if (html->focus_type == HTML_FOCUS_SELF)
+ /* Don't need to tell anyone anything */
+ return;
+ break;
+
+ case HTML_FOCUS_CONTENT:
+ box_coords(focus_owner.content, &x_off, &y_off);
+ break;
+
+ case HTML_FOCUS_TEXTAREA:
+ box_coords(focus_owner.textarea, &x_off, &y_off);
+ break;
+ }
+
+ html->focus_type = focus_type;
+ html->focus_owner = focus_owner;
+
+ if (textarea_lost_focus) {
+ msg_data.caret.type = CONTENT_CARET_REMOVE;
+ } else if (focus_type != HTML_FOCUS_SELF && hide_caret) {
+ msg_data.caret.type = CONTENT_CARET_HIDE;
+ } else {
+ if (clip != NULL) {
+ cr = *clip;
+ cr.x0 += x_off;
+ cr.y0 += y_off;
+ cr.x1 += x_off;
+ cr.y1 += y_off;
+ }
+
+ msg_data.caret.type = CONTENT_CARET_SET_POS;
+ msg_data.caret.pos.x = x + x_off;
+ msg_data.caret.pos.y = y + y_off;
+ msg_data.caret.pos.height = height;
+ msg_data.caret.pos.clip = (clip == NULL) ? NULL : &cr;
+ }
+
+ /* Inform of the content's drag status change */
+ content_broadcast((struct content *)html, CONTENT_MSG_CARET, &msg_data);
+}
+
+/* Documented in html_internal.h */
+void html_set_selection(html_content *html, html_selection_type selection_type,
+ union html_selection_owner selection_owner, bool read_only)
+{
+ union content_msg_data msg_data;
+ struct box *box;
+ bool changed = false;
+ bool same_type = html->selection_type == selection_type;
+
+ assert(html != NULL);
+
+ if ((selection_type == HTML_SELECTION_NONE &&
+ html->selection_type != HTML_SELECTION_NONE) ||
+ (selection_type != HTML_SELECTION_NONE &&
+ html->selection_type == HTML_SELECTION_NONE))
+ /* Existance of selection has changed, and we'll need to
+ * inform our owner */
+ changed = true;
+
+ /* Clear any existing selection */
+ if (html->selection_type != HTML_SELECTION_NONE) {
+ switch (html->selection_type) {
+ case HTML_SELECTION_SELF:
+ if (same_type)
+ break;
+ selection_clear(html->sel, true);
+ break;
+ case HTML_SELECTION_TEXTAREA:
+ if (same_type && html->selection_owner.textarea ==
+ selection_owner.textarea)
+ break;
+ box = html->selection_owner.textarea;
+ textarea_clear_selection(box->gadget->data.text.ta);
+ break;
+ case HTML_SELECTION_CONTENT:
+ if (same_type && html->selection_owner.content ==
+ selection_owner.content)
+ break;
+ box = html->selection_owner.content;
+ content_clear_selection(box->object);
+ break;
+ default:
+ break;
+ }
+ }
+
+ html->selection_type = selection_type;
+ html->selection_owner = selection_owner;
+
+ if (!changed)
+ /* Don't need to report lack of change to owner */
+ return;
+
+ /* Prepare msg */
+ switch (selection_type) {
+ case HTML_SELECTION_NONE:
+ assert(selection_owner.none == true);
+ msg_data.selection.selection = false;
+ break;
+ case HTML_SELECTION_SELF:
+ assert(selection_owner.none == false);
+ fallthrough;
+ case HTML_SELECTION_TEXTAREA:
+ case HTML_SELECTION_CONTENT:
+ msg_data.selection.selection = true;
+ break;
+ default:
+ break;
+ }
+ msg_data.selection.read_only = read_only;
+
+ /* Inform of the content's selection status change */
+ content_broadcast((struct content *)html, CONTENT_MSG_SELECTION,
+ &msg_data);
+}
diff --git a/content/handlers/html/interaction.h b/content/handlers/html/interaction.h
new file mode 100644
index 000000000..f92e3adb0
--- /dev/null
+++ b/content/handlers/html/interaction.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * HTML content user interaction handling
+ */
+
+#ifndef NETSURF_HTML_INTERACTION_H
+#define NETSURF_HTML_INTERACTION_H
+
+#include "desktop/search.h" /* search flags enum */
+
+/**
+ * Context for scrollbar
+ */
+struct html_scrollbar_data {
+ struct content *c;
+ struct box *box;
+};
+
+/**
+ * Handle mouse tracking (including drags) in an HTML content window.
+ *
+ * \param c content of type html
+ * \param bw browser window
+ * \param mouse state of mouse buttons and modifier keys
+ * \param x coordinate of mouse
+ * \param y coordinate of mouse
+ */
+nserror html_mouse_track(struct content *c, struct browser_window *bw,
+ browser_mouse_state mouse, int x, int y);
+
+
+/**
+ * Handle mouse clicks and movements in an HTML content window.
+ *
+ * This function handles both hovering and clicking. It is important that the
+ * code path is identical (except that hovering doesn't carry out the action),
+ * so that the status bar reflects exactly what will happen. Having separate
+ * code paths opens the possibility that an attacker will make the status bar
+ * show some harmless action where clicking will be harmful.
+ *
+ * \param c content of type html
+ * \param bw browser window
+ * \param mouse state of mouse buttons and modifier keys
+ * \param x x coordinate of mouse
+ * \param y y coordinate of mouse
+ * \return NSERROR_OK or appropriate error code.
+ */
+nserror html_mouse_action(struct content *c, struct browser_window *bw,
+ browser_mouse_state mouse, int x, int y);
+
+
+bool html_keypress(struct content *c, uint32_t key);
+
+
+void html_overflow_scroll_callback(void *client_data,
+ struct scrollbar_msg_data *scrollbar_data);
+
+
+void html_search(struct content *c, void *context,
+ search_flags_t flags, const char *string);
+
+
+void html_search_clear(struct content *c);
+
+
+/**
+ * Set our drag status, and inform whatever owns the content
+ *
+ * \param html HTML content
+ * \param drag_type Type of drag
+ * \param drag_owner What owns the drag
+ * \param rect Pointer movement bounds
+ */
+void html_set_drag_type(html_content *html, html_drag_type drag_type,
+ union html_drag_owner drag_owner, const struct rect *rect);
+
+
+/**
+ * Set our selection status, and inform whatever owns the content
+ *
+ * \param html HTML content
+ * \param selection_type Type of selection
+ * \param selection_owner What owns the selection
+ * \param read_only True iff selection is read only
+ */
+void html_set_selection(html_content *html, html_selection_type selection_type,
+ union html_selection_owner selection_owner, bool read_only);
+
+
+/**
+ * Set our input focus, and inform whatever owns the content
+ *
+ * \param html HTML content
+ * \param focus_type Type of input focus
+ * \param focus_owner What owns the focus
+ * \param hide_caret True iff caret to be hidden
+ * \param x Carret x-coord rel to owner
+ * \param y Carret y-coord rel to owner
+ * \param height Carret height
+ * \param clip Carret clip rect
+ */
+void html_set_focus(html_content *html, html_focus_type focus_type,
+ union html_focus_owner focus_owner, bool hide_caret,
+ int x, int y, int height, const struct rect *clip);
+
+
+#endif
diff --git a/render/layout.c b/content/handlers/html/layout.c
index 121137adc..76ce24df5 100644
--- a/render/layout.c
+++ b/content/handlers/html/layout.c
@@ -47,38 +47,31 @@
#include "utils/talloc.h"
#include "utils/utils.h"
#include "utils/nsoption.h"
+#include "utils/corestrings.h"
+#include "utils/nsurl.h"
#include "netsurf/inttypes.h"
#include "netsurf/content.h"
#include "netsurf/browser_window.h"
#include "netsurf/layout.h"
+#include "content/content.h"
#include "content/content_protected.h"
#include "css/utils.h"
#include "desktop/scrollbar.h"
#include "desktop/textarea.h"
-#include "render/box.h"
-#include "render/font.h"
-#include "render/form_internal.h"
-#include "render/html_internal.h"
-#include "render/layout.h"
-#include "render/table.h"
-
-#define AUTO INT_MIN
-
-/* Fixed point percentage (a) of an integer (b), to an integer */
-#define FPCT_OF_INT_TOINT(a, b) (FIXTOINT(FDIV((a * b), F_100)))
-
-typedef uint8_t (*css_len_func)(
- const css_computed_style *style,
- css_fixed *length, css_unit *unit);
-typedef uint8_t (*css_border_style_func)(
- const css_computed_style *style);
-typedef uint8_t (*css_border_color_func)(
- const css_computed_style *style,
- css_color *color);
+#include "html/html.h"
+#include "html/html_save.h"
+#include "html/private.h"
+#include "html/box.h"
+#include "html/box_inspect.h"
+#include "html/font.h"
+#include "html/form_internal.h"
+#include "html/layout.h"
+#include "html/layout_internal.h"
+#include "html/table.h"
/** Array of per-side access functions for computed style margins. */
-static const css_len_func margin_funcs[4] = {
+const css_len_func margin_funcs[4] = {
[TOP] = css_computed_margin_top,
[RIGHT] = css_computed_margin_right,
[BOTTOM] = css_computed_margin_bottom,
@@ -86,7 +79,7 @@ static const css_len_func margin_funcs[4] = {
};
/** Array of per-side access functions for computed style paddings. */
-static const css_len_func padding_funcs[4] = {
+const css_len_func padding_funcs[4] = {
[TOP] = css_computed_padding_top,
[RIGHT] = css_computed_padding_right,
[BOTTOM] = css_computed_padding_bottom,
@@ -94,7 +87,7 @@ static const css_len_func padding_funcs[4] = {
};
/** Array of per-side access functions for computed style border_widths. */
-static const css_len_func border_width_funcs[4] = {
+const css_len_func border_width_funcs[4] = {
[TOP] = css_computed_border_top_width,
[RIGHT] = css_computed_border_right_width,
[BOTTOM] = css_computed_border_bottom_width,
@@ -102,7 +95,7 @@ static const css_len_func border_width_funcs[4] = {
};
/** Array of per-side access functions for computed style border styles. */
-static const css_border_style_func border_style_funcs[4] = {
+const css_border_style_func border_style_funcs[4] = {
[TOP] = css_computed_border_top_style,
[RIGHT] = css_computed_border_right_style,
[BOTTOM] = css_computed_border_bottom_style,
@@ -110,7 +103,7 @@ static const css_border_style_func border_style_funcs[4] = {
};
/** Array of per-side access functions for computed style border colors. */
-static const css_border_color_func border_color_funcs[4] = {
+const css_border_color_func border_color_funcs[4] = {
[TOP] = css_computed_border_top_color,
[RIGHT] = css_computed_border_right_color,
[BOTTOM] = css_computed_border_bottom_color,
@@ -118,16 +111,11 @@ static const css_border_color_func border_color_funcs[4] = {
};
/* forward declaration to break cycles */
-static bool layout_block_context(
- struct box *block,
- int viewport_height,
- html_content *content);
static void layout_minmax_block(
struct box *block,
const struct gui_layout_table *font_func,
const html_content *content);
-
/**
* Compute the size of replaced boxes with auto dimensions, according to
* content.
@@ -218,6 +206,11 @@ layout_get_object_dimensions(struct box *box,
int intrinsic_width = content_get_width(box->object);
int intrinsic_height = content_get_height(box->object);
+ if (min_width > 0 && min_width > *width)
+ *width = min_width;
+ if (max_width >= 0 && max_width < *width)
+ *width = max_width;
+
if (intrinsic_width != 0)
*height = (*width * intrinsic_height) /
intrinsic_width;
@@ -235,7 +228,7 @@ layout_get_object_dimensions(struct box *box,
* \return length of indent
*/
static int layout_text_indent(
- const nscss_len_ctx *len_ctx,
+ const css_unit_ctx *unit_len_ctx,
const css_computed_style *style, int width)
{
css_fixed value = 0;
@@ -246,73 +239,8 @@ static int layout_text_indent(
if (unit == CSS_UNIT_PCT) {
return FPCT_OF_INT_TOINT(value, width);
} else {
- return FIXTOINT(nscss_len2px(len_ctx, value, unit, style));
- }
-}
-
-
-/**
- * Determine width of margin, borders, and padding on one side of a box.
- *
- * \param len_ctx CSS length conversion context for document
- * \param style style to measure
- * \param side side of box to measure
- * \param margin whether margin width is required
- * \param border whether border width is required
- * \param padding whether padding width is required
- * \param fixed increased by sum of fixed margin, border, and padding
- * \param frac increased by sum of fractional margin and padding
- */
-static void
-calculate_mbp_width(const nscss_len_ctx *len_ctx,
- const css_computed_style *style,
- unsigned int side,
- bool margin,
- bool border,
- bool padding,
- int *fixed,
- float *frac)
-{
- css_fixed value = 0;
- css_unit unit = CSS_UNIT_PX;
-
- assert(style);
-
- /* margin */
- if (margin) {
- enum css_margin_e type;
-
- type = margin_funcs[side](style, &value, &unit);
- if (type == CSS_MARGIN_SET) {
- if (unit == CSS_UNIT_PCT) {
- *frac += FIXTOINT(FDIV(value, F_100));
- } else {
- *fixed += FIXTOINT(nscss_len2px(len_ctx,
- value, unit, style));
- }
- }
- }
-
- /* border */
- if (border) {
- if (border_style_funcs[side](style) !=
- CSS_BORDER_STYLE_NONE) {
- border_width_funcs[side](style, &value, &unit);
-
- *fixed += FIXTOINT(nscss_len2px(len_ctx,
- value, unit, style));
- }
- }
-
- /* padding */
- if (padding) {
- padding_funcs[side](style, &value, &unit);
- if (unit == CSS_UNIT_PCT) {
- *frac += FIXTOINT(FDIV(value, F_100));
- } else {
- *fixed += FIXTOINT(nscss_len2px(len_ctx,
- value, unit, style));
- }
+ return FIXTOINT(css_unit_len2device_px(style, unit_len_ctx,
+ value, unit));
}
}
@@ -345,8 +273,8 @@ static void layout_minmax_table(struct box *table,
if (table->max_width != UNKNOWN_MAX_WIDTH)
return;
- if (table_calculate_column_types(&content->len_ctx, table) == false) {
- NSLOG(netsurf, WARNING,
+ if (table_calculate_column_types(&content->unit_len_ctx, table) == false) {
+ NSLOG(netsurf, ERROR,
"Could not establish table column types.");
return;
}
@@ -368,8 +296,10 @@ static void layout_minmax_table(struct box *table,
css_computed_border_spacing(table->style, &h, &hu, &v, &vu);
- border_spacing_h = FIXTOINT(nscss_len2px(&content->len_ctx,
- h, hu, table->style));
+ border_spacing_h = FIXTOINT(css_unit_len2device_px(
+ table->style,
+ &content->unit_len_ctx,
+ h, hu));
}
/* 1st pass: consider cells with colspan 1 only */
@@ -474,8 +404,10 @@ static void layout_minmax_table(struct box *table,
/* fixed width takes priority, unless it is too narrow */
wtype = css_computed_width(table->style, &value, &unit);
if (wtype == CSS_WIDTH_SET && unit != CSS_UNIT_PCT) {
- int width = FIXTOINT(nscss_len2px(&content->len_ctx,
- value, unit, table->style));
+ int width = FIXTOINT(css_unit_len2device_px(
+ table->style,
+ &content->unit_len_ctx,
+ value, unit));
if (table_min < width)
table_min = width;
if (table_max < width)
@@ -483,10 +415,10 @@ static void layout_minmax_table(struct box *table,
}
/* add margins, border, padding to min, max widths */
- calculate_mbp_width(&content->len_ctx,
+ calculate_mbp_width(&content->unit_len_ctx,
table->style, LEFT, true, true, true,
&extra_fixed, &extra_frac);
- calculate_mbp_width(&content->len_ctx,
+ calculate_mbp_width(&content->unit_len_ctx,
table->style, RIGHT, true, true, true,
&extra_fixed, &extra_frac);
if (extra_fixed < 0)
@@ -570,11 +502,7 @@ layout_minmax_line(struct box *first,
css_fixed value = 0;
css_unit unit = CSS_UNIT_PX;
- assert(b->type == BOX_INLINE || b->type == BOX_INLINE_BLOCK ||
- b->type == BOX_FLOAT_LEFT ||
- b->type == BOX_FLOAT_RIGHT ||
- b->type == BOX_BR || b->type == BOX_TEXT ||
- b->type == BOX_INLINE_END);
+ assert(lh__box_is_inline_content(b));
NSLOG(layout, DEBUG, "%p: min %i, max %i", b, min, max);
@@ -583,13 +511,13 @@ layout_minmax_line(struct box *first,
break;
}
- if (b->type == BOX_FLOAT_LEFT || b->type == BOX_FLOAT_RIGHT) {
+ if (lh__box_is_float_box(b)) {
assert(b->children);
- if (b->children->type == BOX_BLOCK)
- layout_minmax_block(b->children, font_func,
+ if (b->children->type == BOX_TABLE)
+ layout_minmax_table(b->children, font_func,
content);
else
- layout_minmax_table(b->children, font_func,
+ layout_minmax_block(b->children, font_func,
content);
b->min_width = b->children->min_width;
b->max_width = b->children->max_width;
@@ -599,7 +527,7 @@ layout_minmax_line(struct box *first,
continue;
}
- if (b->type == BOX_INLINE_BLOCK) {
+ if (b->type == BOX_INLINE_BLOCK || b->type == BOX_INLINE_FLEX) {
layout_minmax_block(b, font_func, content);
if (min < b->min_width)
min = b->min_width;
@@ -611,17 +539,17 @@ layout_minmax_line(struct box *first,
}
assert(b->style);
- font_plot_style_from_css(&content->len_ctx, b->style, &fstyle);
+ font_plot_style_from_css(&content->unit_len_ctx, b->style, &fstyle);
if (b->type == BOX_INLINE && !b->object &&
!(b->flags & REPLACE_DIM) &&
!(b->flags & IFRAME)) {
fixed = frac = 0;
- calculate_mbp_width(&content->len_ctx,
+ calculate_mbp_width(&content->unit_len_ctx,
b->style, LEFT, true, true, true,
&fixed, &frac);
if (!b->inline_end)
- calculate_mbp_width(&content->len_ctx,
+ calculate_mbp_width(&content->unit_len_ctx,
b->style, RIGHT,
true, true, true,
&fixed, &frac);
@@ -631,7 +559,7 @@ layout_minmax_line(struct box *first,
/* \todo update min width, consider fractional extra */
} else if (b->type == BOX_INLINE_END) {
fixed = frac = 0;
- calculate_mbp_width(&content->len_ctx,
+ calculate_mbp_width(&content->unit_len_ctx,
b->inline_end->style, RIGHT,
true, true, true,
&fixed, &frac);
@@ -650,8 +578,7 @@ layout_minmax_line(struct box *first,
continue;
}
- if (!b->object && !(b->flags & IFRAME) && !b->gadget &&
- !(b->flags & REPLACE_DIM)) {
+ if (lh__box_is_replace(b) == false) {
/* inline non-replaced, 10.3.1 and 10.6.1 */
bool no_wrap_box;
if (!b->text)
@@ -749,16 +676,18 @@ layout_minmax_line(struct box *first,
if (unit == CSS_UNIT_PCT) {
width = AUTO;
} else {
- width = FIXTOINT(nscss_len2px(&content->len_ctx,
- value, unit, b->style));
+ width = FIXTOINT(css_unit_len2device_px(
+ b->style,
+ &content->unit_len_ctx,
+ value, unit));
if (bs == CSS_BOX_SIZING_BORDER_BOX) {
fixed = frac = 0;
- calculate_mbp_width(&content->len_ctx,
+ calculate_mbp_width(&content->unit_len_ctx,
block->style, LEFT,
false, true, true,
&fixed, &frac);
- calculate_mbp_width(&content->len_ctx,
+ calculate_mbp_width(&content->unit_len_ctx,
block->style, RIGHT,
false, true, true,
&fixed, &frac);
@@ -776,8 +705,10 @@ layout_minmax_line(struct box *first,
/* height */
htype = css_computed_height(b->style, &value, &unit);
if (htype == CSS_HEIGHT_SET) {
- height = FIXTOINT(nscss_len2px(&content->len_ctx,
- value, unit, b->style));
+ height = FIXTOINT(css_unit_len2device_px(
+ b->style,
+ &content->unit_len_ctx,
+ value, unit));
} else {
height = AUTO;
}
@@ -793,20 +724,20 @@ layout_minmax_line(struct box *first,
fixed = frac = 0;
if (bs == CSS_BOX_SIZING_BORDER_BOX) {
- calculate_mbp_width(&content->len_ctx,
+ calculate_mbp_width(&content->unit_len_ctx,
b->style, LEFT,
true, false, false,
&fixed, &frac);
- calculate_mbp_width(&content->len_ctx,
+ calculate_mbp_width(&content->unit_len_ctx,
b->style, RIGHT,
true, false, false,
&fixed, &frac);
} else {
- calculate_mbp_width(&content->len_ctx,
+ calculate_mbp_width(&content->unit_len_ctx,
b->style, LEFT,
true, true, true,
&fixed, &frac);
- calculate_mbp_width(&content->len_ctx,
+ calculate_mbp_width(&content->unit_len_ctx,
b->style, RIGHT,
true, true, true,
&fixed, &frac);
@@ -820,20 +751,20 @@ layout_minmax_line(struct box *first,
fixed = frac = 0;
if (bs == CSS_BOX_SIZING_BORDER_BOX) {
- calculate_mbp_width(&content->len_ctx,
+ calculate_mbp_width(&content->unit_len_ctx,
b->style, LEFT,
true, false, false,
&fixed, &frac);
- calculate_mbp_width(&content->len_ctx,
+ calculate_mbp_width(&content->unit_len_ctx,
b->style, RIGHT,
true, false, false,
&fixed, &frac);
} else {
- calculate_mbp_width(&content->len_ctx,
+ calculate_mbp_width(&content->unit_len_ctx,
b->style, LEFT,
true, true, true,
&fixed, &frac);
- calculate_mbp_width(&content->len_ctx,
+ calculate_mbp_width(&content->unit_len_ctx,
b->style, RIGHT,
true, true, true,
&fixed, &frac);
@@ -845,10 +776,10 @@ layout_minmax_line(struct box *first,
} else {
/* form control with no object */
if (width == AUTO)
- width = FIXTOINT(nscss_len2px(
- &content->len_ctx,
- INTTOFIX(1), CSS_UNIT_EM,
- b->style));
+ width = FIXTOINT(css_unit_len2device_px(
+ b->style,
+ &content->unit_len_ctx,
+ INTTOFIX(1), CSS_UNIT_EM));
}
if (min < width && !box_has_percentage_max_width(b))
@@ -862,7 +793,7 @@ layout_minmax_line(struct box *first,
if (first_line) {
/* todo: handle percentage values properly */
/* todo: handle text-indent interaction with floats */
- int text_indent = layout_text_indent(&content->len_ctx,
+ int text_indent = layout_text_indent(&content->unit_len_ctx,
first->parent->parent->style, 100);
min = (min + text_indent < 0) ? 0 : min + text_indent;
max = (max + text_indent < 0) ? 0 : max + text_indent;
@@ -929,7 +860,6 @@ layout_minmax_inline_container(struct box *inline_container,
inline_container->max_width);
}
-
/**
* Calculate minimum and maximum width of a block.
*
@@ -955,9 +885,13 @@ static void layout_minmax_block(
css_fixed height = 0;
css_unit hunit = CSS_UNIT_PX;
enum css_box_sizing_e bs = CSS_BOX_SIZING_CONTENT_BOX;
+ bool using_min_border_box = false;
+ bool using_max_border_box = false;
bool child_has_height = false;
assert(block->type == BOX_BLOCK ||
+ block->type == BOX_FLEX ||
+ block->type == BOX_INLINE_FLEX ||
block->type == BOX_INLINE_BLOCK ||
block->type == BOX_TABLE_CELL);
@@ -972,9 +906,9 @@ static void layout_minmax_block(
}
/* set whether the minimum width is of any interest for this box */
- if (((block->parent && (block->parent->type == BOX_FLOAT_LEFT ||
- block->parent->type == BOX_FLOAT_RIGHT)) ||
- block->type == BOX_INLINE_BLOCK) &&
+ if (((block->parent && lh__box_is_float_box(block->parent)) ||
+ block->type == BOX_INLINE_BLOCK ||
+ block->type == BOX_INLINE_FLEX) &&
wtype != CSS_WIDTH_SET) {
/* box shrinks to fit; need minimum width */
block->flags |= NEED_MIN;
@@ -985,6 +919,9 @@ static void layout_minmax_block(
wtype != CSS_WIDTH_SET) {
/* box inside shrink-to-fit context; need minimum width */
block->flags |= NEED_MIN;
+ } else if (block->parent && (block->parent->type == BOX_FLEX)) {
+ /* box is flex item */
+ block->flags |= NEED_MIN;
}
if (block->gadget && (block->gadget->type == GADGET_TEXTBOX ||
@@ -995,8 +932,8 @@ static void layout_minmax_block(
css_fixed size = INTTOFIX(10);
css_unit unit = CSS_UNIT_EM;
- min = max = FIXTOINT(nscss_len2px(&content->len_ctx,
- size, unit, block->style));
+ min = max = FIXTOINT(css_unit_len2device_px(block->style,
+ &content->unit_len_ctx, size, unit));
block->flags |= HAS_HEIGHT;
}
@@ -1009,8 +946,8 @@ static void layout_minmax_block(
/* form checkbox or radio button
* if width is AUTO, set it to 1em */
- min = max = FIXTOINT(nscss_len2px(&content->len_ctx,
- size, unit, block->style));
+ min = max = FIXTOINT(css_unit_len2device_px(block->style,
+ &content->unit_len_ctx, size, unit));
block->flags |= HAS_HEIGHT;
}
@@ -1034,6 +971,7 @@ static void layout_minmax_block(
/* recurse through children */
for (child = block->children; child; child = child->next) {
switch (child->type) {
+ case BOX_FLEX:
case BOX_BLOCK:
layout_minmax_block(child, font_func,
content);
@@ -1075,10 +1013,24 @@ static void layout_minmax_block(
continue;
}
- if (min < child->min_width)
- min = child->min_width;
- if (max < child->max_width)
- max = child->max_width;
+ if (lh__box_is_flex_container(block) &&
+ lh__flex_main_is_horizontal(block)) {
+ if (block->style != NULL &&
+ css_computed_flex_wrap(block->style) ==
+ CSS_FLEX_WRAP_NOWRAP) {
+ min += child->min_width;
+ } else {
+ if (min < child->min_width)
+ min = child->min_width;
+ }
+ max += child->max_width;
+
+ } else {
+ if (min < child->min_width)
+ min = child->min_width;
+ if (max < child->max_width)
+ max = child->max_width;
+ }
if (child_has_height)
block->flags |= HAS_HEIGHT;
@@ -1091,23 +1043,40 @@ static void layout_minmax_block(
}
/* fixed width takes priority */
- if (block->type != BOX_TABLE_CELL && wtype == CSS_WIDTH_SET &&
- wunit != CSS_UNIT_PCT) {
- min = max = FIXTOINT(nscss_len2px(&content->len_ctx,
- width, wunit, block->style));
- if (bs == CSS_BOX_SIZING_BORDER_BOX) {
- int border_box_fixed = 0;
- float border_box_frac = 0;
- calculate_mbp_width(&content->len_ctx,
- block->style, LEFT,
- false, true, true,
- &border_box_fixed, &border_box_frac);
- calculate_mbp_width(&content->len_ctx,
- block->style, RIGHT,
- false, true, true,
- &border_box_fixed, &border_box_frac);
- if (min < border_box_fixed) {
- min = max = border_box_fixed;
+ if (block->type != BOX_TABLE_CELL && !lh__box_is_flex_item(block)) {
+ bool border_box = bs == CSS_BOX_SIZING_BORDER_BOX;
+ enum css_max_width_e max_type;
+ enum css_min_width_e min_type;
+ css_unit unit = CSS_UNIT_PX;
+ css_fixed value = 0;
+
+ if (wtype == CSS_WIDTH_SET && wunit != CSS_UNIT_PCT) {
+ min = max = FIXTOINT(
+ css_unit_len2device_px(block->style,
+ &content->unit_len_ctx, width, wunit));
+ using_max_border_box = border_box;
+ using_min_border_box = border_box;
+ }
+
+ min_type = css_computed_min_width(block->style, &value, &unit);
+ if (min_type == CSS_MIN_WIDTH_SET && unit != CSS_UNIT_PCT) {
+ int val = FIXTOINT(css_unit_len2device_px(block->style,
+ &content->unit_len_ctx, value, unit));
+
+ if (min < val) {
+ min = val;
+ using_min_border_box = border_box;
+ }
+ }
+
+ max_type = css_computed_max_width(block->style, &value, &unit);
+ if (max_type == CSS_MAX_WIDTH_SET && unit != CSS_UNIT_PCT) {
+ int val = FIXTOINT(css_unit_len2device_px(block->style,
+ &content->unit_len_ctx, value, unit));
+
+ if (val >= 0 && max > val) {
+ max = val;
+ using_max_border_box = border_box;
}
}
}
@@ -1121,22 +1090,30 @@ static void layout_minmax_block(
/* add margins, border, padding to min, max widths */
/* Note: we don't know available width here so percentage margin
* and paddings are wrong. */
- if (bs == CSS_BOX_SIZING_BORDER_BOX && wtype == CSS_WIDTH_SET) {
- /* Border and padding included in width, so just get margin */
- calculate_mbp_width(&content->len_ctx,
- block->style, LEFT, true, false, false,
- &extra_fixed, &extra_frac);
- calculate_mbp_width(&content->len_ctx,
- block->style, RIGHT, true, false, false,
- &extra_fixed, &extra_frac);
- } else {
- calculate_mbp_width(&content->len_ctx,
- block->style, LEFT, true, true, true,
- &extra_fixed, &extra_frac);
- calculate_mbp_width(&content->len_ctx,
- block->style, RIGHT, true, true, true,
- &extra_fixed, &extra_frac);
+ calculate_mbp_width(&content->unit_len_ctx, block->style, LEFT,
+ false, true, true, &extra_fixed, &extra_frac);
+ calculate_mbp_width(&content->unit_len_ctx, block->style, RIGHT,
+ false, true, true, &extra_fixed, &extra_frac);
+
+ if (using_max_border_box) {
+ max -= extra_fixed;
+ max = max(max, 0);
+ }
+
+ if (using_min_border_box) {
+ min -= extra_fixed;
+ min = max(min, 0);
}
+
+ if (max < min) {
+ min = max;
+ }
+
+ calculate_mbp_width(&content->unit_len_ctx, block->style, LEFT,
+ true, false, false, &extra_fixed, &extra_frac);
+ calculate_mbp_width(&content->unit_len_ctx, block->style, RIGHT,
+ true, false, false, &extra_fixed, &extra_frac);
+
if (extra_fixed < 0)
extra_fixed = 0;
if (extra_frac < 0)
@@ -1155,375 +1132,15 @@ static void layout_minmax_block(
block->max_width = (max + extra_fixed) / (1.0 - extra_frac);
}
- assert(0 <= block->min_width && block->min_width <= block->max_width);
-}
-
-
-/**
- * Adjust a specified width or height for the box-sizing property.
- *
- * This turns the specified dimension into a content-box dimension.
- *
- * \param len_ctx Length conversion context
- * \param box gadget to adjust dimensions of
- * \param available_width width of containing block
- * \param setwidth set true if the dimension to be tweaked is a width,
- * else set false for a height
- * \param dimension current value for given width/height dimension.
- * updated to new value after consideration of
- * gadget properties.
- */
-static void layout_handle_box_sizing(
- const nscss_len_ctx *len_ctx,
- struct box *box,
- int available_width,
- bool setwidth,
- int *dimension)
-{
- enum css_box_sizing_e bs;
-
- assert(box && box->style);
-
- bs = css_computed_box_sizing(box->style);
-
- if (bs == CSS_BOX_SIZING_BORDER_BOX) {
- int orig = *dimension;
- int fixed = 0;
- float frac = 0;
-
- calculate_mbp_width(len_ctx, box->style,
- setwidth ? LEFT : TOP,
- false, true, true, &fixed, &frac);
- calculate_mbp_width(len_ctx, box->style,
- setwidth ? RIGHT : BOTTOM,
- false, true, true, &fixed, &frac);
- orig -= frac * available_width + fixed;
- *dimension = orig > 0 ? orig : 0;
- }
-}
-
-
-/**
- * Calculate width, height, and thickness of margins, paddings, and borders.
- *
- * \param len_ctx Length conversion context
- * \param available_width width of containing block
- * \param viewport_height height of viewport in pixels or -ve if unknown
- * \param box current box
- * \param style style giving width, height, margins, paddings,
- * and borders
- * \param width updated to width, may be NULL
- * \param height updated to height, may be NULL
- * \param max_width updated to max-width, may be NULL
- * \param min_width updated to min-width, may be NULL
- * \param max_height updated to max-height, may be NULL
- * \param min_height updated to min-height, may be NULL
- * \param margin filled with margins, may be NULL
- * \param padding filled with paddings, may be NULL
- * \param border filled with border widths, may be NULL
- */
-static void
-layout_find_dimensions(const nscss_len_ctx *len_ctx,
- int available_width,
- int viewport_height,
- struct box *box,
- const css_computed_style *style,
- int *width,
- int *height,
- int *max_width,
- int *min_width,
- int *max_height,
- int *min_height,
- int margin[4],
- int padding[4],
- struct box_border border[4])
-{
- struct box *containing_block = NULL;
- unsigned int i;
-
- if (width) {
- enum css_width_e wtype;
- css_fixed value = 0;
- css_unit unit = CSS_UNIT_PX;
-
- wtype = css_computed_width(style, &value, &unit);
-
- if (wtype == CSS_WIDTH_SET) {
- if (unit == CSS_UNIT_PCT) {
- *width = FPCT_OF_INT_TOINT(
- value, available_width);
- } else {
- *width = FIXTOINT(nscss_len2px(len_ctx,
- value, unit, style));
- }
- } else {
- *width = AUTO;
- }
-
- if (*width != AUTO) {
- layout_handle_box_sizing(len_ctx, box, available_width,
- true, width);
- }
- }
-
- if (height) {
- enum css_height_e htype;
- css_fixed value = 0;
- css_unit unit = CSS_UNIT_PX;
-
- htype = css_computed_height(style, &value, &unit);
-
- if (htype == CSS_HEIGHT_SET) {
- if (unit == CSS_UNIT_PCT) {
- enum css_height_e cbhtype;
-
- if (css_computed_position(box->style) ==
- CSS_POSITION_ABSOLUTE &&
- box->parent) {
- /* Box is absolutely positioned */
- assert(box->float_container);
- containing_block = box->float_container;
- } else if (box->float_container &&
- css_computed_position(box->style) !=
- CSS_POSITION_ABSOLUTE &&
- (css_computed_float(box->style) ==
- CSS_FLOAT_LEFT ||
- css_computed_float(box->style) ==
- CSS_FLOAT_RIGHT)) {
- /* Box is a float */
- assert(box->parent &&
- box->parent->parent &&
- box->parent->parent->parent);
-
- containing_block =
- box->parent->parent->parent;
- } else if (box->parent && box->parent->type !=
- BOX_INLINE_CONTAINER) {
- /* Box is a block level element */
- containing_block = box->parent;
- } else if (box->parent && box->parent->type ==
- BOX_INLINE_CONTAINER) {
- /* Box is an inline block */
- assert(box->parent->parent);
- containing_block = box->parent->parent;
- }
-
- if (containing_block) {
- css_fixed f = 0;
- css_unit u = CSS_UNIT_PX;
-
- cbhtype = css_computed_height(
- containing_block->style,
- &f, &u);
- }
-
- if (containing_block &&
- containing_block->height != AUTO &&
- (css_computed_position(box->style) ==
- CSS_POSITION_ABSOLUTE ||
- cbhtype == CSS_HEIGHT_SET)) {
- /* Box is absolutely positioned or its
- * containing block has a valid
- * specified height.
- * (CSS 2.1 Section 10.5) */
- *height = FPCT_OF_INT_TOINT(value,
- containing_block->height);
- } else if ((!box->parent ||
- !box->parent->parent) &&
- viewport_height >= 0) {
- /* If root element or it's child
- * (HTML or BODY) */
- *height = FPCT_OF_INT_TOINT(value,
- viewport_height);
- } else {
- /* precentage height not permissible
- * treat height as auto */
- *height = AUTO;
- }
- } else {
- *height = FIXTOINT(nscss_len2px(len_ctx,
- value, unit, style));
- }
- } else {
- *height = AUTO;
- }
-
- if (*height != AUTO) {
- layout_handle_box_sizing(len_ctx, box, available_width,
- false, height);
- }
- }
-
- if (max_width) {
- enum css_max_width_e type;
- css_fixed value = 0;
- css_unit unit = CSS_UNIT_PX;
-
- type = css_computed_max_width(style, &value, &unit);
-
- if (type == CSS_MAX_WIDTH_SET) {
- if (unit == CSS_UNIT_PCT) {
- *max_width = FPCT_OF_INT_TOINT(value,
- available_width);
- } else {
- *max_width = FIXTOINT(nscss_len2px(len_ctx,
- value, unit, style));
- }
- } else {
- /* Inadmissible */
- *max_width = -1;
- }
-
- if (*max_width != -1) {
- layout_handle_box_sizing(len_ctx, box, available_width,
- true, max_width);
- }
- }
-
- if (min_width) {
- enum css_min_width_e type;
- css_fixed value = 0;
- css_unit unit = CSS_UNIT_PX;
-
- type = ns_computed_min_width(style, &value, &unit);
-
- if (type == CSS_MIN_WIDTH_SET) {
- if (unit == CSS_UNIT_PCT) {
- *min_width = FPCT_OF_INT_TOINT(value,
- available_width);
- } else {
- *min_width = FIXTOINT(nscss_len2px(len_ctx,
- value, unit, style));
- }
- } else {
- /* Inadmissible */
- *min_width = 0;
- }
-
- if (*min_width != 0) {
- layout_handle_box_sizing(len_ctx, box, available_width,
- true, min_width);
- }
- }
-
- if (max_height) {
- enum css_max_height_e type;
- css_fixed value = 0;
- css_unit unit = CSS_UNIT_PX;
-
- type = css_computed_max_height(style, &value, &unit);
-
- if (type == CSS_MAX_HEIGHT_SET) {
- if (unit == CSS_UNIT_PCT) {
- /* TODO: handle percentage */
- *max_height = -1;
- } else {
- *max_height = FIXTOINT(nscss_len2px(len_ctx,
- value, unit, style));
- }
- } else {
- /* Inadmissible */
- *max_height = -1;
- }
- }
-
- if (min_height) {
- enum css_min_height_e type;
- css_fixed value = 0;
- css_unit unit = CSS_UNIT_PX;
-
- type = ns_computed_min_height(style, &value, &unit);
-
- if (type == CSS_MIN_HEIGHT_SET) {
- if (unit == CSS_UNIT_PCT) {
- /* TODO: handle percentage */
- *min_height = 0;
- } else {
- *min_height = FIXTOINT(nscss_len2px(len_ctx,
- value, unit, style));
- }
- } else {
- /* Inadmissible */
- *min_height = 0;
- }
- }
-
- for (i = 0; i != 4; i++) {
- if (margin) {
- enum css_margin_e type = CSS_MARGIN_AUTO;
- css_fixed value = 0;
- css_unit unit = CSS_UNIT_PX;
-
- type = margin_funcs[i](style, &value, &unit);
-
- if (type == CSS_MARGIN_SET) {
- if (unit == CSS_UNIT_PCT) {
- margin[i] = FPCT_OF_INT_TOINT(value,
- available_width);
- } else {
- margin[i] = FIXTOINT(nscss_len2px(
- len_ctx,
- value, unit, style));
- }
- } else {
- margin[i] = AUTO;
- }
- }
-
- if (padding) {
- css_fixed value = 0;
- css_unit unit = CSS_UNIT_PX;
-
- padding_funcs[i](style, &value, &unit);
-
- if (unit == CSS_UNIT_PCT) {
- padding[i] = FPCT_OF_INT_TOINT(value,
- available_width);
- } else {
- padding[i] = FIXTOINT(nscss_len2px(len_ctx,
- value, unit, style));
- }
- }
-
- /* Table cell borders are populated in table.c */
- if (border && box->type != BOX_TABLE_CELL) {
- enum css_border_style_e bstyle = CSS_BORDER_STYLE_NONE;
- css_color color = 0;
- css_fixed value = 0;
- css_unit unit = CSS_UNIT_PX;
-
- border_width_funcs[i](style, &value, &unit);
- bstyle = border_style_funcs[i](style);
- border_color_funcs[i](style, &color);
-
- border[i].style = bstyle;
- border[i].c = color;
-
- if (bstyle == CSS_BORDER_STYLE_HIDDEN ||
- bstyle == CSS_BORDER_STYLE_NONE)
- /* spec unclear: following Mozilla */
- border[i].width = 0;
- else
- border[i].width = FIXTOINT(nscss_len2px(len_ctx,
- value, unit, style));
-
- /* Special case for border-collapse: make all borders
- * on table/table-row-group/table-row zero width. */
- if (css_computed_border_collapse(style) ==
- CSS_BORDER_COLLAPSE_COLLAPSE &&
- (box->type == BOX_TABLE ||
- box->type == BOX_TABLE_ROW_GROUP ||
- box->type == BOX_TABLE_ROW))
- border[i].width = 0;
- }
- }
+ assert(0 <= block->min_width);
+ assert(block->min_width <= block->max_width);
}
/**
* Find next block that current margin collapses to.
*
- * \param len_ctx Length conversion context
+ * \param unit_len_ctx Length conversion context
* \param box box to start tree-order search from (top margin is included)
* \param block box responsible for current block fromatting context
* \param viewport_height height of viewport in px
@@ -1532,7 +1149,7 @@ layout_find_dimensions(const nscss_len_ctx *len_ctx,
* \return next box that current margin collapses to, or NULL if none.
*/
static struct box*
-layout_next_margin_block(const nscss_len_ctx *len_ctx,
+layout_next_margin_block(const css_unit_ctx *unit_len_ctx,
struct box *box,
struct box *block,
int viewport_height,
@@ -1552,7 +1169,7 @@ layout_next_margin_block(const nscss_len_ctx *len_ctx,
/* Get margins */
if (box->style) {
- layout_find_dimensions(len_ctx,
+ layout_find_dimensions(unit_len_ctx,
box->parent->width,
viewport_height, box,
box->style,
@@ -1576,7 +1193,7 @@ layout_next_margin_block(const nscss_len_ctx *len_ctx,
css_computed_overflow_y(box->style) !=
CSS_OVERFLOW_VISIBLE) ||
(box->type == BOX_INLINE_CONTAINER &&
- box != box->parent->children)) {
+ !box_is_first_child(box))) {
/* Collapse to this box; return it */
return box;
}
@@ -1627,7 +1244,7 @@ layout_next_margin_block(const nscss_len_ctx *len_ctx,
/* Get margins */
if (box->style) {
- layout_find_dimensions(len_ctx,
+ layout_find_dimensions(unit_len_ctx,
box->parent->width,
viewport_height, box,
box->style,
@@ -1864,7 +1481,7 @@ layout_solve_width(struct box *box,
* Compute dimensions of box, margins, paddings, and borders for a block-level
* element.
*
- * \param len_ctx Length conversion context
+ * \param unit_len_ctx Length conversion context
* \param available_width Max width available in pixels
* \param viewport_height Height of viewport in pixels or -ve if unknown
* \param lm min left margin required to avoid floats in px.
@@ -1877,7 +1494,7 @@ layout_solve_width(struct box *box,
* See CSS 2.1 10.3.3, 10.3.4, 10.6.2, and 10.6.3.
*/
static void
-layout_block_find_dimensions(const nscss_len_ctx *len_ctx,
+layout_block_find_dimensions(const css_unit_ctx *unit_len_ctx,
int available_width,
int viewport_height,
int lm,
@@ -1891,7 +1508,7 @@ layout_block_find_dimensions(const nscss_len_ctx *len_ctx,
struct box_border *border = box->border;
const css_computed_style *style = box->style;
- layout_find_dimensions(len_ctx, available_width, viewport_height, box,
+ layout_find_dimensions(unit_len_ctx, available_width, viewport_height, box,
style, &width, &height, &max_width, &min_width,
&max_height, &min_height, margin, padding, border);
@@ -1983,15 +1600,10 @@ static void layout_move_children(struct box *box, int x, int y)
}
-/**
- * Layout a table.
- *
- * \param table table to layout
- * \param available_width width of containing block
- * \param content memory pool for any new boxes
- * \return true on success, false on memory exhaustion
- */
-static bool layout_table(struct box *table, int available_width,
+/* Documented in layout_internal.h */
+bool layout_table(
+ struct box *table,
+ int available_width,
html_content *content)
{
unsigned int columns = table->columns; /* total columns */
@@ -2045,7 +1657,7 @@ static bool layout_table(struct box *table, int available_width,
memcpy(col, table->col, sizeof(col[0]) * columns);
/* find margins, paddings, and borders for table and cells */
- layout_find_dimensions(&content->len_ctx, available_width, -1, table,
+ layout_find_dimensions(&content->unit_len_ctx, available_width, -1, table,
style, 0, 0, 0, 0, 0, 0, table->margin, table->padding,
table->border);
for (row_group = table->children; row_group;
@@ -2057,8 +1669,8 @@ static bool layout_table(struct box *table, int available_width,
assert(c->style);
table_used_border_for_cell(
- &content->len_ctx, c);
- layout_find_dimensions(&content->len_ctx,
+ &content->unit_len_ctx, c);
+ layout_find_dimensions(&content->unit_len_ctx,
available_width, -1, c,
c->style, 0, 0, 0, 0, 0, 0,
0, c->padding, c->border);
@@ -2088,10 +1700,10 @@ static bool layout_table(struct box *table, int available_width,
css_computed_border_spacing(style, &h, &hu, &v, &vu);
- border_spacing_h = FIXTOINT(nscss_len2px(&content->len_ctx,
- h, hu, style));
- border_spacing_v = FIXTOINT(nscss_len2px(&content->len_ctx,
- v, vu, style));
+ border_spacing_h = FIXTOINT(css_unit_len2device_px(
+ style, &content->unit_len_ctx, h, hu));
+ border_spacing_v = FIXTOINT(css_unit_len2device_px(
+ style, &content->unit_len_ctx, v, vu));
}
/* find specified table width, or available width if auto-width */
@@ -2101,8 +1713,9 @@ static bool layout_table(struct box *table, int available_width,
table_width = FPCT_OF_INT_TOINT(value, available_width);
} else {
table_width =
- FIXTOINT(nscss_len2px(&content->len_ctx,
- value, unit, style));
+ FIXTOINT(css_unit_len2device_px(
+ style, &content->unit_len_ctx,
+ value, unit));
}
/* specified width includes border */
@@ -2180,15 +1793,16 @@ static bool layout_table(struct box *table, int available_width,
} else {
/* This is the minimum height for the table
* (see 17.5.3) */
- min_height = FIXTOINT(nscss_len2px(&content->len_ctx,
- value, unit, style));
+ min_height = FIXTOINT(css_unit_len2device_px(
+ style, &content->unit_len_ctx,
+ value, unit));
}
}
/* calculate width required by cells */
for (i = 0; i != columns; i++) {
- NSLOG(layout, DEBUG,
+ NSLOG(layout, DEBUG,
"table %p, column %u: type %s, width %i, min %i, max %i",
table,
i,
@@ -2225,7 +1839,7 @@ static bool layout_table(struct box *table, int available_width,
required_width += (columns + 1 - positioned_columns) *
border_spacing_h;
- NSLOG(layout, DEBUG,
+ NSLOG(layout, DEBUG,
"width %i, min %i, max %i, auto %i, required %i", table_width,
table->min_width, table->max_width, auto_width, required_width);
@@ -2371,9 +1985,10 @@ static bool layout_table(struct box *table, int available_width,
htype = css_computed_height(row->style, &value, &unit);
if (htype == CSS_HEIGHT_SET && unit != CSS_UNIT_PCT) {
- row_height = FIXTOINT(nscss_len2px(
- &content->len_ctx,
- value, unit, row->style));
+ row_height = FIXTOINT(css_unit_len2device_px(
+ row->style,
+ &content->unit_len_ctx,
+ value, unit));
}
for (c = row->children; c; c = c->next) {
assert(c->style);
@@ -2410,9 +2025,10 @@ static bool layout_table(struct box *table, int available_width,
/* some sites use height="1" or similar
* to attempt to make cells as small as
* possible, so treat it as a minimum */
- int h = FIXTOINT(nscss_len2px(
- &content->len_ctx,
- value, unit, c->style));
+ int h = FIXTOINT(css_unit_len2device_px(
+ c->style,
+ &content->unit_len_ctx,
+ value, unit));
if (c->height < h)
c->height = h;
}
@@ -2556,14 +2172,14 @@ static bool layout_table(struct box *table, int available_width,
/**
* Manimpulate box height according to CSS min-height and max-height properties
*
- * \param len_ctx CSS length conversion context for document.
+ * \param unit_len_ctx CSS length conversion context for document.
* \param box block to modify with any min-height or max-height
* \param container containing block for absolutely positioned elements, or
* NULL for non absolutely positioned elements.
* \return whether the height has been changed
*/
static bool layout_apply_minmax_height(
- const nscss_len_ctx *len_ctx,
+ const css_unit_ctx *unit_len_ctx,
struct box *box,
struct box *container)
{
@@ -2624,8 +2240,9 @@ static bool layout_apply_minmax_height(
}
}
} else {
- h = FIXTOINT(nscss_len2px(len_ctx,
- value, unit, box->style));
+ h = FIXTOINT(css_unit_len2device_px(
+ box->style, unit_len_ctx,
+ value, unit));
if (h < box->height) {
box->height = h;
updated = true;
@@ -2654,8 +2271,9 @@ static bool layout_apply_minmax_height(
}
}
} else {
- h = FIXTOINT(nscss_len2px(len_ctx,
- value, unit, box->style));
+ h = FIXTOINT(css_unit_len2device_px(
+ box->style, unit_len_ctx,
+ value, unit));
if (h > box->height) {
box->height = h;
updated = true;
@@ -2677,7 +2295,9 @@ static bool layout_block_object(struct box *block)
{
assert(block);
assert(block->type == BOX_BLOCK ||
+ block->type == BOX_FLEX ||
block->type == BOX_INLINE_BLOCK ||
+ block->type == BOX_INLINE_FLEX ||
block->type == BOX_TABLE ||
block->type == BOX_TABLE_CELL);
assert(block->object);
@@ -2685,7 +2305,7 @@ static bool layout_block_object(struct box *block)
NSLOG(layout, DEBUG, "block %p, object %p, width %i", block,
hlcache_handle_get_url(block->object), block->width);
- if (content_get_type(block->object) == CONTENT_HTML) {
+ if (content_can_reformat(block->object)) {
content_reformat(block->object, false, block->width, 1);
} else {
/* Non-HTML objects */
@@ -2823,7 +2443,7 @@ layout_text_box_split(html_content *content,
* Compute dimensions of box, margins, paddings, and borders for a floating
* element using shrink-to-fit. Also used for inline-blocks.
*
- * \param len_ctx CSS length conversion context for document.
+ * \param unit_len_ctx CSS length conversion context for document.
* \param available_width Max width available in pixels
* \param style Box's style
* \param box Box for which to find dimensions
@@ -2832,7 +2452,7 @@ layout_text_box_split(html_content *content,
*/
static void
layout_float_find_dimensions(
- const nscss_len_ctx *len_ctx,
+ const css_unit_ctx *unit_len_ctx,
int available_width,
const css_computed_style *style,
struct box *box)
@@ -2852,7 +2472,7 @@ layout_float_find_dimensions(
overflow_y == CSS_OVERFLOW_AUTO) ?
SCROLLBAR_WIDTH : 0;
- layout_find_dimensions(len_ctx, available_width, -1, box, style,
+ layout_find_dimensions(unit_len_ctx, available_width, -1, box, style,
&width, &height, &max_width, &min_width,
&max_height, &min_height, margin, padding, border);
@@ -2888,26 +2508,30 @@ layout_float_find_dimensions(
box->gadget->type == GADGET_FILE) {
if (width == AUTO) {
size = INTTOFIX(10);
- width = FIXTOINT(nscss_len2px(len_ctx,
- size, unit, box->style));
+ width = FIXTOINT(css_unit_len2device_px(
+ box->style, unit_len_ctx,
+ size, unit));
}
if (box->gadget->type == GADGET_FILE &&
height == AUTO) {
size = FLTTOFIX(1.5);
- height = FIXTOINT(nscss_len2px(len_ctx,
- size, unit, box->style));
+ height = FIXTOINT(css_unit_len2device_px(
+ box->style, unit_len_ctx,
+ size, unit));
}
}
if (box->gadget->type == GADGET_TEXTAREA) {
if (width == AUTO) {
size = INTTOFIX(10);
- width = FIXTOINT(nscss_len2px(len_ctx,
- size, unit, box->style));
+ width = FIXTOINT(css_unit_len2device_px(
+ box->style, unit_len_ctx,
+ size, unit));
}
if (height == AUTO) {
size = INTTOFIX(4);
- height = FIXTOINT(nscss_len2px(len_ctx,
- size, unit, box->style));
+ height = FIXTOINT(css_unit_len2device_px(
+ box->style, unit_len_ctx,
+ size, unit));
}
}
} else if (width == AUTO) {
@@ -2928,9 +2552,9 @@ layout_float_find_dimensions(
* mbp as was used in layout_minmax_block() */
int fixed = 0;
float frac = 0;
- calculate_mbp_width(len_ctx, box->style, LEFT,
+ calculate_mbp_width(unit_len_ctx, box->style, LEFT,
true, true, true, &fixed, &frac);
- calculate_mbp_width(len_ctx, box->style, RIGHT,
+ calculate_mbp_width(unit_len_ctx, box->style, RIGHT,
true, true, true, &fixed, &frac);
if (fixed < 0)
fixed = 0;
@@ -2967,12 +2591,20 @@ layout_float_find_dimensions(
*/
static bool layout_float(struct box *b, int width, html_content *content)
{
- assert(b->type == BOX_TABLE || b->type == BOX_BLOCK ||
- b->type == BOX_INLINE_BLOCK);
- layout_float_find_dimensions(&content->len_ctx, width, b->style, b);
- if (b->type == BOX_TABLE) {
- if (!layout_table(b, width, content))
- return false;
+ assert(b->type == BOX_TABLE ||
+ b->type == BOX_BLOCK ||
+ b->type == BOX_INLINE_BLOCK ||
+ b->type == BOX_FLEX ||
+ b->type == BOX_INLINE_FLEX);
+ layout_float_find_dimensions(&content->unit_len_ctx, width, b->style, b);
+ if (b->type == BOX_TABLE || b->type == BOX_INLINE_FLEX) {
+ if (b->type == BOX_TABLE) {
+ if (!layout_table(b, width, content))
+ return false;
+ } else {
+ if (!layout_flex(b, width, content))
+ return false;
+ }
if (b->margin[LEFT] == AUTO)
b->margin[LEFT] = 0;
if (b->margin[RIGHT] == AUTO)
@@ -2981,8 +2613,9 @@ static bool layout_float(struct box *b, int width, html_content *content)
b->margin[TOP] = 0;
if (b->margin[BOTTOM] == AUTO)
b->margin[BOTTOM] = 0;
- } else
+ } else {
return layout_block_context(b, -1, content);
+ }
return true;
}
@@ -3042,7 +2675,7 @@ place_float_below(struct box *c, int width, int cx, int y, struct box *cont)
* Calculate line height from a style.
*/
static int line_height(
- const nscss_len_ctx *len_ctx,
+ const css_unit_ctx *unit_len_ctx,
const css_computed_style *style)
{
enum css_line_height_e lhtype;
@@ -3061,16 +2694,16 @@ static int line_height(
if (lhtype == CSS_LINE_HEIGHT_NUMBER ||
lhunit == CSS_UNIT_PCT) {
- line_height = nscss_len2px(len_ctx,
- lhvalue, CSS_UNIT_EM, style);
+ line_height = css_unit_len2device_px(style, unit_len_ctx,
+ lhvalue, CSS_UNIT_EM);
if (lhtype != CSS_LINE_HEIGHT_NUMBER)
line_height = FDIV(line_height, F_100);
} else {
assert(lhunit != CSS_UNIT_PCT);
- line_height = nscss_len2px(len_ctx,
- lhvalue, lhunit, style);
+ line_height = css_unit_len2device_px(style, unit_len_ctx,
+ lhvalue, lhunit);
}
return FIXTOINT(line_height);
@@ -3124,7 +2757,7 @@ layout_line(struct box *first,
const struct gui_layout_table *font_func = content->font_func;
plot_font_style_t fstyle;
- NSLOG(layout, DEBUG,
+ NSLOG(layout, DEBUG,
"first %p, first->text '%.*s', width %i, y %i, cx %i, cy %i",
first,
(int)first->length,
@@ -3142,7 +2775,7 @@ layout_line(struct box *first,
x1 -= cx;
if (indent)
- x0 += layout_text_indent(&content->len_ctx,
+ x0 += layout_text_indent(&content->unit_len_ctx,
first->parent->parent->style, *width);
if (x1 < x0)
@@ -3152,7 +2785,7 @@ layout_line(struct box *first,
* this is the line-height if there are text children and also in the
* case of an initially empty text input */
if (has_text_children || first->parent->parent->gadget)
- used_height = height = line_height(&content->len_ctx,
+ used_height = height = line_height(&content->unit_len_ctx,
first->parent->parent->style);
else
/* inline containers with no text are usually for layout and
@@ -3169,20 +2802,14 @@ layout_line(struct box *first,
for (x = 0, b = first; x <= x1 - x0 && b != 0; b = b->next) {
int min_width, max_width, min_height, max_height;
- assert(b->type == BOX_INLINE || b->type == BOX_INLINE_BLOCK ||
- b->type == BOX_FLOAT_LEFT ||
- b->type == BOX_FLOAT_RIGHT ||
- b->type == BOX_BR || b->type == BOX_TEXT ||
- b->type == BOX_INLINE_END);
-
+ assert(lh__box_is_inline_content(b));
NSLOG(layout, DEBUG, "pass 1: b %p, x %i", b, x);
-
if (b->type == BOX_BR)
break;
- if (b->type == BOX_FLOAT_LEFT || b->type == BOX_FLOAT_RIGHT)
+ if (lh__box_is_float_box(b))
continue;
if (b->type == BOX_INLINE_BLOCK &&
(css_computed_position(b->style) ==
@@ -3192,11 +2819,12 @@ layout_line(struct box *first,
continue;
assert(b->style != NULL);
- font_plot_style_from_css(&content->len_ctx, b->style, &fstyle);
+ font_plot_style_from_css(&content->unit_len_ctx, b->style, &fstyle);
x += space_after;
- if (b->type == BOX_INLINE_BLOCK) {
+ if (b->type == BOX_INLINE_BLOCK ||
+ b->type == BOX_INLINE_FLEX) {
if (b->max_width != UNKNOWN_WIDTH)
if (!layout_float(b, *width, content))
return false;
@@ -3216,7 +2844,7 @@ layout_line(struct box *first,
if (b->type == BOX_INLINE) {
/* calculate borders, margins, and padding */
- layout_find_dimensions(&content->len_ctx,
+ layout_find_dimensions(&content->unit_len_ctx,
*width, -1, b, b->style, 0, 0, 0, 0,
0, 0, b->margin, b->padding, b->border);
for (i = 0; i != 4; i++)
@@ -3248,10 +2876,9 @@ layout_line(struct box *first,
continue;
}
- if (!b->object && !(b->flags & IFRAME) && !b->gadget &&
- !(b->flags & REPLACE_DIM)) {
+ if (lh__box_is_replace(b) == false) {
/* inline non-replaced, 10.3.1 and 10.6.1 */
- b->height = line_height(&content->len_ctx,
+ b->height = line_height(&content->unit_len_ctx,
b->style ? b->style :
b->parent->parent->style);
if (height < b->height)
@@ -3322,7 +2949,7 @@ layout_line(struct box *first,
/* inline replaced, 10.3.2 and 10.6.2 */
assert(b->style);
- layout_find_dimensions(&content->len_ctx,
+ layout_find_dimensions(&content->unit_len_ctx,
*width, -1, b, b->style,
&b->width, &b->height,
&max_width, &min_width,
@@ -3345,17 +2972,19 @@ layout_line(struct box *first,
} else {
/* form control with no object */
if (b->width == AUTO)
- b->width = FIXTOINT(nscss_len2px(
- &content->len_ctx, INTTOFIX(1),
- CSS_UNIT_EM, b->style));
+ b->width = FIXTOINT(css_unit_len2device_px(
+ b->style,
+ &content->unit_len_ctx, INTTOFIX(1),
+ CSS_UNIT_EM));
if (b->height == AUTO)
- b->height = FIXTOINT(nscss_len2px(
- &content->len_ctx, INTTOFIX(1),
- CSS_UNIT_EM, b->style));
+ b->height = FIXTOINT(css_unit_len2device_px(
+ b->style,
+ &content->unit_len_ctx, INTTOFIX(1),
+ CSS_UNIT_EM));
}
/* Reformat object to new box size */
- if (b->object && content_get_type(b->object) == CONTENT_HTML &&
+ if (b->object && content_can_reformat(b->object) &&
b->width !=
content_get_available_width(b->object)) {
css_fixed value = 0;
@@ -3384,7 +3013,7 @@ layout_line(struct box *first,
x1 -= cx;
if (indent)
- x0 += layout_text_indent(&content->len_ctx,
+ x0 += layout_text_indent(&content->unit_len_ctx,
first->parent->parent->style, *width);
if (x1 < x0)
@@ -3407,10 +3036,7 @@ layout_line(struct box *first,
CSS_POSITION_FIXED)) {
b->x = x + space_after;
- } else if (b->type == BOX_INLINE ||
- b->type == BOX_INLINE_BLOCK ||
- b->type == BOX_TEXT ||
- b->type == BOX_INLINE_END) {
+ } else if (lh__box_is_inline_flow(b)) {
assert(b->width != UNKNOWN_WIDTH);
x_previous = x;
@@ -3418,7 +3044,8 @@ layout_line(struct box *first,
b->x = x;
if ((b->type == BOX_INLINE && !b->inline_end) ||
- b->type == BOX_INLINE_BLOCK) {
+ b->type == BOX_INLINE_BLOCK ||
+ b->type == BOX_INLINE_FLEX) {
b->x += b->margin[LEFT] + b->border[LEFT].width;
x = b->x + b->padding[LEFT] + b->width +
b->padding[RIGHT] +
@@ -3443,7 +3070,7 @@ layout_line(struct box *first,
else if (b->text || b->type == BOX_INLINE_END) {
if (b->space == UNKNOWN_WIDTH) {
font_plot_style_from_css(
- &content->len_ctx,
+ &content->unit_len_ctx,
b->style, &fstyle);
/** \todo handle errors */
font_func->width(&fstyle, " ", 1,
@@ -3597,7 +3224,7 @@ layout_line(struct box *first,
!(split_box->flags & IFRAME) &&
!split_box->gadget && split_box->text) {
- font_plot_style_from_css(&content->len_ctx,
+ font_plot_style_from_css(&content->unit_len_ctx,
split_box->style, &fstyle);
/** \todo handle errors */
font_func->split(&fstyle,
@@ -3615,8 +3242,8 @@ layout_line(struct box *first,
NSLOG(layout, DEBUG,
- "splitting: split_box %p \"%.*s\", spilt %zu, w %i, "
- "left %p, right %p, inline_count %u",
+ "splitting: split_box %p \"%.*s\", spilt %"PRIsizet
+ ", w %i, left %p, right %p, inline_count %u",
split_box,
(int)split_box->length,
split_box->text,
@@ -3653,7 +3280,7 @@ layout_line(struct box *first,
used_height = 0;
if (left) {
- NSLOG(layout, DEBUG,
+ NSLOG(layout, DEBUG,
"cy %i, left->y %i, left->height %i",
cy,
left->y,
@@ -3687,7 +3314,8 @@ layout_line(struct box *first,
/* fit as many words as possible */
assert(split != 0);
- NSLOG(layout, DEBUG, "'%.*s' %i %zu %i",
+ NSLOG(layout, DEBUG,
+ "'%.*s' %i %"PRIsizet" %i",
(int)split_box->length, split_box->text,
x1 - x0, split, w);
@@ -3748,9 +3376,7 @@ layout_line(struct box *first,
d->y = *y;
continue;
} else if ((d->type == BOX_INLINE &&
- ((d->object || d->gadget) == false) &&
- !(d->flags & IFRAME) &&
- !(d->flags & REPLACE_DIM)) ||
+ lh__box_is_replace(d) == false) ||
d->type == BOX_BR ||
d->type == BOX_TEXT ||
d->type == BOX_INLINE_END) {
@@ -3848,7 +3474,7 @@ static bool layout_inline_container(struct box *inline_container, int width,
assert(inline_container->type == BOX_INLINE_CONTAINER);
- NSLOG(layout, DEBUG,
+ NSLOG(layout, DEBUG,
"inline_container %p, width %i, cont %p, cx %i, cy %i",
inline_container,
width,
@@ -3871,8 +3497,7 @@ static bool layout_inline_container(struct box *inline_container, int width,
whitespace == CSS_WHITE_SPACE_PRE_WRAP);
}
- if ((!c->object && !(c->flags & REPLACE_DIM) &&
- !(c->flags & IFRAME) &&
+ if ((lh__box_is_object(c) == false &&
c->text && (c->length || is_pre)) ||
c->type == BOX_BR)
has_text_children = true;
@@ -3902,21 +3527,11 @@ static bool layout_inline_container(struct box *inline_container, int width,
}
-/**
- * Layout a block formatting context.
- *
- * \param block BLOCK, INLINE_BLOCK, or TABLE_CELL to layout
- * \param viewport_height Height of viewport in pixels or -ve if unknown
- * \param content Memory pool for any new boxes
- * \return true on success, false on memory exhaustion
- *
- * This function carries out layout of a block and its children, as described
- * in CSS 2.1 9.4.1.
- */
-static bool
-layout_block_context(struct box *block,
- int viewport_height,
- html_content *content)
+/* Documented in layout_intertnal.h */
+bool layout_block_context(
+ struct box *block,
+ int viewport_height,
+ html_content *content)
{
struct box *box;
int cx, cy; /**< current coordinates */
@@ -3931,7 +3546,9 @@ layout_block_context(struct box *block,
assert(block->type == BOX_BLOCK ||
block->type == BOX_INLINE_BLOCK ||
- block->type == BOX_TABLE_CELL);
+ block->type == BOX_TABLE_CELL ||
+ block->type == BOX_FLEX ||
+ block->type == BOX_INLINE_FLEX);
assert(block->width != UNKNOWN_WIDTH);
assert(block->width != AUTO);
@@ -3960,9 +3577,10 @@ layout_block_context(struct box *block,
gadget_unit = CSS_UNIT_EM;
gadget_size = INTTOFIX(1);
if (block->height == AUTO)
- block->height = FIXTOINT(nscss_len2px(
- &content->len_ctx, gadget_size,
- gadget_unit, block->style));
+ block->height = FIXTOINT(css_unit_len2device_px(
+ block->style,
+ &content->unit_len_ctx,
+ gadget_size, gadget_unit));
}
box = block->children;
@@ -3999,7 +3617,9 @@ layout_block_context(struct box *block,
enum css_overflow_e overflow_x = CSS_OVERFLOW_VISIBLE;
enum css_overflow_e overflow_y = CSS_OVERFLOW_VISIBLE;
- assert(box->type == BOX_BLOCK || box->type == BOX_TABLE ||
+ assert(box->type == BOX_BLOCK ||
+ box->type == BOX_FLEX ||
+ box->type == BOX_TABLE ||
box->type == BOX_INLINE_CONTAINER);
/* Tables are laid out before being positioned, because the
@@ -4026,7 +3646,7 @@ layout_block_context(struct box *block,
* through to, find out. Update the pos/neg margin values. */
if (margin_collapse == NULL) {
margin_collapse = layout_next_margin_block(
- &content->len_ctx, box, block,
+ &content->unit_len_ctx, box, block,
viewport_height,
&max_pos_margin, &max_neg_margin);
/* We have a margin that has not yet been applied. */
@@ -4050,9 +3670,10 @@ layout_block_context(struct box *block,
* left and right margins to avoid any floats. */
lm = rm = 0;
- if (box->type == BOX_BLOCK || box->flags & IFRAME) {
- if (!box->object && !(box->flags & IFRAME) &&
- !(box->flags & REPLACE_DIM) &&
+ if (box->type == BOX_FLEX ||
+ box->type == BOX_BLOCK ||
+ box->flags & IFRAME) {
+ if (lh__box_is_object(box) == false &&
box->style &&
(overflow_x != CSS_OVERFLOW_VISIBLE ||
overflow_y != CSS_OVERFLOW_VISIBLE)) {
@@ -4077,7 +3698,7 @@ layout_block_context(struct box *block,
box->parent->padding[RIGHT] -
x1;
}
- layout_block_find_dimensions(&content->len_ctx,
+ layout_block_find_dimensions(&content->unit_len_ctx,
box->parent->width,
viewport_height, lm, rm, box);
if (box->type == BOX_BLOCK && !(box->flags & IFRAME)) {
@@ -4136,13 +3757,13 @@ layout_block_context(struct box *block,
}
/* Vertical margin */
- if (((box->type == BOX_BLOCK &&
- (box->flags & HAS_HEIGHT)) ||
- box->type == BOX_TABLE ||
- (box->type == BOX_INLINE_CONTAINER &&
- box != box->parent->children) ||
- margin_collapse == box) &&
- in_margin == true) {
+ if (((box->type == BOX_BLOCK && (box->flags & HAS_HEIGHT)) ||
+ box->type == BOX_FLEX ||
+ box->type == BOX_TABLE ||
+ (box->type == BOX_INLINE_CONTAINER &&
+ !box_is_first_child(box)) ||
+ margin_collapse == box) &&
+ in_margin == true) {
/* Margin goes above this box. */
cy += max_pos_margin - max_neg_margin;
box->y += max_pos_margin - max_neg_margin;
@@ -4162,11 +3783,19 @@ layout_block_context(struct box *block,
/* Unless the box has an overflow style of visible, the box
* establishes a new block context. */
- if (box->type == BOX_BLOCK && box->style &&
- (overflow_x != CSS_OVERFLOW_VISIBLE ||
- overflow_y != CSS_OVERFLOW_VISIBLE)) {
+ if (box->type == BOX_FLEX ||
+ (box->type == BOX_BLOCK && box->style &&
+ (overflow_x != CSS_OVERFLOW_VISIBLE ||
+ overflow_y != CSS_OVERFLOW_VISIBLE))) {
- layout_block_context(box, viewport_height, content);
+ if (box->type == BOX_FLEX) {
+ if (!layout_flex(box, box->width, content)) {
+ return false;
+ }
+ } else {
+ layout_block_context(box,
+ viewport_height, content);
+ }
cy += box->padding[TOP];
@@ -4187,7 +3816,8 @@ layout_block_context(struct box *block,
goto advance_to_next_box;
}
- NSLOG(layout, DEBUG, "box %p, cx %i, cy %i", box, cx, cy);
+ NSLOG(layout, DEBUG, "box %p, cx %i, cy %i, width %i",
+ box, cx, cy, box->width);
/* Layout (except tables). */
if (box->object) {
@@ -4319,7 +3949,7 @@ layout_block_context(struct box *block,
css_computed_position(box->style) !=
CSS_POSITION_ABSOLUTE &&
layout_apply_minmax_height(
- &content->len_ctx,
+ &content->unit_len_ctx,
box, NULL)) {
/* Height altered */
/* Set current cy */
@@ -4376,7 +4006,7 @@ layout_block_context(struct box *block,
if (block->style && css_computed_position(block->style) !=
CSS_POSITION_ABSOLUTE) {
/* Block is in normal flow */
- layout_apply_minmax_height(&content->len_ctx, block, NULL);
+ layout_apply_minmax_height(&content->unit_len_ctx, block, NULL);
}
if (block->gadget &&
@@ -4388,7 +4018,7 @@ layout_block_context(struct box *block,
block->padding[RIGHT];
int ta_height = block->padding[TOP] + block->height +
block->padding[BOTTOM];
- font_plot_style_from_css(&content->len_ctx,
+ font_plot_style_from_css(&content->unit_len_ctx,
block->style, &fstyle);
fstyle.background = NS_TRANSPARENT;
textarea_set_layout(block->gadget->data.text.ta,
@@ -4400,36 +4030,426 @@ layout_block_context(struct box *block,
return true;
}
+/**
+ * Get a dom node's element tag type.
+ *
+ * \param[in] node Node to get tag type of.
+ * \param[in] type Returns element tag type on success.
+ * \return true if on success, false otherwise.
+ */
+static bool
+layout__get_element_tag(
+ const dom_node *node,
+ dom_html_element_type *type)
+{
+ dom_html_element_type element_type;
+ dom_node_type node_type;
+ dom_exception exc;
+
+ exc = dom_node_get_node_type(node, &node_type);
+ if (exc != DOM_NO_ERR ||
+ node_type != DOM_ELEMENT_NODE) {
+ return false;
+ }
+
+ exc = dom_html_element_get_tag_type(node, &element_type);
+ if (exc != DOM_NO_ERR) {
+ return false;
+ }
+
+ *type = element_type;
+ return true;
+}
+
+
+/**
+ * Check a node's tag type.
+ *
+ * \param[in] node Node to check tag type of.
+ * \param[in] type Tag type to test for.
+ * \return true if if node has given type, false otherwise.
+ */
+static inline bool
+layout__check_element_type(
+ const dom_node *node,
+ dom_html_element_type type)
+{
+ dom_html_element_type element_type;
+
+ if (!layout__get_element_tag(node, &element_type)) {
+ return false;
+ }
+
+ return element_type == type;
+}
+
+
+/**
+ * Helper to get attribute value from a LI node.
+ *
+ * \param[in] li_node DOM node for the LI element;
+ * \param[out] value_out Returns the value on success.
+ * \return true if node has value, otherwise false.
+ */
+static bool
+layout__get_li_value(dom_node *li_node, dom_long *value_out)
+{
+ dom_exception exc;
+ dom_long value;
+ bool has_value;
+
+ /** \todo
+ * dom_html_li_element_get_value() is rubbish and we can't tell
+ * a lack of value attribute or invalid value from a perfectly
+ * valid '-1'.
+ *
+ * This helps for the common case of no value. However we should
+ * fix libdom to have some kind of sane interface to get numerical
+ * attributes.
+ */
+ exc = dom_element_has_attribute(li_node,
+ corestring_dom_value,
+ &has_value);
+ if (exc != DOM_NO_ERR || has_value == false) {
+ return false;
+ }
+
+ exc = dom_html_li_element_get_value(
+ (dom_html_li_element *)li_node,
+ &value);
+ if (exc != DOM_NO_ERR) {
+ return false;
+ }
+
+ *value_out = value;
+ return true;
+}
+
+
+/**
+ * Helper to get start attribute value from a OL node.
+ *
+ * \param[in] ol_node DOM node for the OL element;
+ * \param[out] start_out Returns the value on success.
+ * \return true if node has value, otherwise false.
+ */
+static bool
+layout__get_ol_start(dom_node *ol_node, dom_long *start_out)
+{
+ dom_exception exc;
+ dom_long start;
+ bool has_start;
+
+ /** \todo
+ * see layout__get_li_value().
+ */
+ exc = dom_element_has_attribute(ol_node,
+ corestring_dom_start,
+ &has_start);
+ if (exc != DOM_NO_ERR || has_start == false) {
+ return false;
+ }
+
+ exc = dom_html_olist_element_get_start(
+ (dom_html_olist_element *)ol_node,
+ &start);
+ if (exc != DOM_NO_ERR) {
+ return false;
+ }
+
+ *start_out = start;
+ return true;
+}
+
+
+/**
+ * Helper to get reversed attribute value from a OL node.
+ *
+ * \param[in] ol_node DOM node for the OL element;
+ * \return true if node has reversed, otherwise false.
+ */
+static bool
+layout__get_ol_reversed(dom_node *ol_node)
+{
+ dom_exception exc;
+ bool has_reversed;
+
+ exc = dom_element_has_attribute(ol_node,
+ corestring_dom_reversed,
+ &has_reversed);
+ if (exc != DOM_NO_ERR) {
+ return false;
+ }
+
+ return has_reversed;
+}
+
+
+/**
+ * Get the number of list items for a list owner.
+ *
+ * \param[in] list_owner DOM node to count list items for.
+ * \param[in] count_out Returns list item count on success.
+ * \return true on success, otherwise false.
+ */
+static bool
+layout__get_list_item_count(
+ dom_node *list_owner, dom_long *count_out)
+{
+ dom_html_element_type tag_type;
+ dom_exception exc;
+ dom_node *child;
+ int count;
+
+ if (list_owner == NULL) {
+ return false;
+ }
+
+ if (!layout__get_element_tag(list_owner, &tag_type)) {
+ return false;
+ }
+
+ if (tag_type != DOM_HTML_ELEMENT_TYPE_OL &&
+ tag_type != DOM_HTML_ELEMENT_TYPE_UL) {
+ return false;
+ }
+
+ exc = dom_node_get_first_child(list_owner, &child);
+ if (exc != DOM_NO_ERR) {
+ return false;
+ }
+
+ count = 0;
+ while (child != NULL) {
+ dom_node *temp_node;
+
+ if (layout__check_element_type(child,
+ DOM_HTML_ELEMENT_TYPE_LI)) {
+ struct box *child_box;
+ if (dom_node_get_user_data(child,
+ corestring_dom___ns_key_box_node_data,
+ &child_box) != DOM_NO_ERR) {
+ dom_node_unref(child);
+ return false;
+ }
+
+ if (child_box != NULL &&
+ child_box->list_marker != NULL) {
+ count++;
+ }
+ }
+
+ exc = dom_node_get_next_sibling(child, &temp_node);
+ dom_node_unref(child);
+ if (exc != DOM_NO_ERR) {
+ return false;
+ }
+
+ child = temp_node;
+ }
+
+ *count_out = count;
+ return true;
+}
+
+
+/**
+ * Handle list item counting, if this is a list owner box.
+ *
+ * \param[in] box Box to do list item counting for.
+ */
+static void
+layout__ordered_list_count(
+ struct box *box)
+{
+ dom_html_element_type tag_type;
+ dom_exception exc;
+ dom_node *child;
+ int step = 1;
+ dom_long next;
+
+ if (box->node == NULL) {
+ return;
+ }
+
+ if (!layout__get_element_tag(box->node, &tag_type)) {
+ return;
+ }
+
+ if (tag_type != DOM_HTML_ELEMENT_TYPE_OL &&
+ tag_type != DOM_HTML_ELEMENT_TYPE_UL) {
+ return;
+ }
+
+ next = 1;
+ if (tag_type == DOM_HTML_ELEMENT_TYPE_OL) {
+ bool have_start = layout__get_ol_start(box->node, &next);
+ bool have_reversed = layout__get_ol_reversed(box->node);
+
+ if (have_reversed) {
+ step = -1;
+ }
+
+ if (!have_start && have_reversed) {
+ layout__get_list_item_count(box->node, &next);
+ }
+ }
+
+ exc = dom_node_get_first_child(box->node, &child);
+ if (exc != DOM_NO_ERR) {
+ return;
+ }
+
+ while (child != NULL) {
+ dom_node *temp_node;
+
+ if (layout__check_element_type(child,
+ DOM_HTML_ELEMENT_TYPE_LI)) {
+ struct box *child_box;
+
+ if (dom_node_get_user_data(child,
+ corestring_dom___ns_key_box_node_data,
+ &child_box) != DOM_NO_ERR) {
+ dom_node_unref(child);
+ return;
+ }
+
+ if (child_box != NULL &&
+ child_box->list_marker != NULL) {
+ dom_long value;
+ struct box *marker = child_box->list_marker;
+ if (layout__get_li_value(child, &value)) {
+ marker->list_value = value;
+ next = marker->list_value;
+ } else {
+ marker->list_value = next;
+ }
+ next += step;
+ }
+ }
+
+ exc = dom_node_get_next_sibling(child, &temp_node);
+ dom_node_unref(child);
+ if (exc != DOM_NO_ERR) {
+ return;
+ }
+
+ child = temp_node;
+ }
+}
+
+/**
+ * Set up the marker text for a numerical list item.
+ *
+ * \param[in] content The HTML content.
+ * \param[in] box The list item's main box.
+ */
+static void
+layout__set_numerical_marker_text(
+ const html_content *content,
+ struct box *box)
+{
+ struct box *marker = box->list_marker;
+ size_t counter_len;
+ css_error css_res;
+ enum {
+ /**
+ * initial length of a list marker buffer
+ *
+ * enough for 9,999,999,999,999,999,999 in decimal
+ * or five characters for 4-byte UTF-8.
+ */
+ LIST_MARKER_SIZE = 20,
+ };
+
+ marker->text = talloc_array(content->bctx, char, LIST_MARKER_SIZE);
+ if (marker->text == NULL) {
+ return;
+ }
+
+ css_res = css_computed_format_list_style(box->style, marker->list_value,
+ marker->text, LIST_MARKER_SIZE, &counter_len);
+ if (css_res == CSS_OK) {
+ if (counter_len > LIST_MARKER_SIZE) {
+ /* Use computed size as marker did not fit in
+ * default allocation. */
+ marker->text = talloc_realloc(content->bctx,
+ marker->text,
+ char,
+ counter_len);
+ if (marker->text == NULL) {
+ return;
+ }
+ css_computed_format_list_style(box->style,
+ marker->list_value, marker->text,
+ counter_len, &counter_len);
+ }
+ marker->length = counter_len;
+ }
+}
+
+/**
+ * Find out if box's style represents a numerical list style type.
+ *
+ * \param[in] b Box with style to test.
+ * \return true if box has numerical list style type, false otherwise.
+ */
+static bool
+layout__list_item_is_numerical(
+ const struct box *b)
+{
+ enum css_list_style_type_e t = css_computed_list_style_type(b->style);
+
+ switch (t) {
+ case CSS_LIST_STYLE_TYPE_DISC: /* Fall through. */
+ case CSS_LIST_STYLE_TYPE_CIRCLE: /* Fall through. */
+ case CSS_LIST_STYLE_TYPE_SQUARE: /* Fall through. */
+ case CSS_LIST_STYLE_TYPE_NONE:
+ return false;
+
+ default:
+ return true;
+ }
+}
/**
* Layout list markers.
*/
static void
-layout_lists(struct box *box,
- const struct gui_layout_table *font_func,
- const nscss_len_ctx *len_ctx)
+layout_lists(const html_content *content, struct box *box)
{
struct box *child;
- struct box *marker;
- plot_font_style_t fstyle;
+
+ layout__ordered_list_count(box);
for (child = box->children; child; child = child->next) {
if (child->list_marker) {
- marker = child->list_marker;
+ struct box *marker = child->list_marker;
+
+ if (layout__list_item_is_numerical(child)) {
+ if (marker->text == NULL) {
+ layout__set_numerical_marker_text(
+ content, child);
+ }
+ }
if (marker->object) {
marker->width =
content_get_width(marker->object);
marker->x = -marker->width;
marker->height =
content_get_height(marker->object);
- marker->y = (line_height(len_ctx,
+ marker->y = (line_height(
+ &content->unit_len_ctx,
marker->style) -
marker->height) / 2;
} else if (marker->text) {
if (marker->width == UNKNOWN_WIDTH) {
- font_plot_style_from_css(len_ctx,
- marker->style, &fstyle);
- font_func->width(&fstyle,
+ plot_font_style_t fstyle;
+ font_plot_style_from_css(
+ &content->unit_len_ctx,
+ marker->style,
+ &fstyle);
+ content->font_func->width(&fstyle,
marker->text,
marker->length,
&marker->width);
@@ -4437,7 +4457,8 @@ layout_lists(struct box *box,
}
marker->x = -marker->width;
marker->y = 0;
- marker->height = line_height(len_ctx,
+ marker->height = line_height(
+ &content->unit_len_ctx,
marker->style);
} else {
marker->x = 0;
@@ -4448,7 +4469,7 @@ layout_lists(struct box *box,
/* Gap between marker and content */
marker->x -= 4;
}
- layout_lists(child, font_func, len_ctx);
+ layout_lists(content, child);
}
}
@@ -4457,7 +4478,7 @@ layout_lists(struct box *box,
* Compute box offsets for a relatively or absolutely positioned box with
* respect to a box.
*
- * \param len_ctx Length conversion context
+ * \param unit_len_ctx Length conversion context
* \param box box to compute offsets for
* \param containing_block box to compute percentages with respect to
* \param top updated to top offset, or AUTO
@@ -4468,7 +4489,7 @@ layout_lists(struct box *box,
* See CSS 2.1 9.3.2. containing_block must have width and height.
*/
static void
-layout_compute_offsets(const nscss_len_ctx *len_ctx,
+layout_compute_offsets(const css_unit_ctx *unit_len_ctx,
struct box *box,
struct box *containing_block,
int *top,
@@ -4480,9 +4501,9 @@ layout_compute_offsets(const nscss_len_ctx *len_ctx,
css_fixed value = 0;
css_unit unit = CSS_UNIT_PX;
- assert(containing_block->width != UNKNOWN_WIDTH &&
- containing_block->width != AUTO &&
- containing_block->height != AUTO);
+ assert(containing_block->width != UNKNOWN_WIDTH);
+ assert(containing_block->width != AUTO);
+ assert(containing_block->height != AUTO);
/* left */
type = css_computed_left(box->style, &value, &unit);
@@ -4491,8 +4512,9 @@ layout_compute_offsets(const nscss_len_ctx *len_ctx,
*left = FPCT_OF_INT_TOINT(value,
containing_block->width);
} else {
- *left = FIXTOINT(nscss_len2px(len_ctx,
- value, unit, box->style));
+ *left = FIXTOINT(css_unit_len2device_px(
+ box->style, unit_len_ctx,
+ value, unit));
}
} else {
*left = AUTO;
@@ -4505,8 +4527,9 @@ layout_compute_offsets(const nscss_len_ctx *len_ctx,
*right = FPCT_OF_INT_TOINT(value,
containing_block->width);
} else {
- *right = FIXTOINT(nscss_len2px(len_ctx,
- value, unit, box->style));
+ *right = FIXTOINT(css_unit_len2device_px(
+ box->style, unit_len_ctx,
+ value, unit));
}
} else {
*right = AUTO;
@@ -4519,8 +4542,9 @@ layout_compute_offsets(const nscss_len_ctx *len_ctx,
*top = FPCT_OF_INT_TOINT(value,
containing_block->height);
} else {
- *top = FIXTOINT(nscss_len2px(len_ctx,
- value, unit, box->style));
+ *top = FIXTOINT(css_unit_len2device_px(
+ box->style, unit_len_ctx,
+ value, unit));
}
} else {
*top = AUTO;
@@ -4533,8 +4557,9 @@ layout_compute_offsets(const nscss_len_ctx *len_ctx,
*bottom = FPCT_OF_INT_TOINT(value,
containing_block->height);
} else {
- *bottom = FIXTOINT(nscss_len2px(len_ctx,
- value, unit, box->style));
+ *bottom = FIXTOINT(css_unit_len2device_px(
+ box->style, unit_len_ctx,
+ value, unit));
}
} else {
*bottom = AUTO;
@@ -4568,7 +4593,9 @@ layout_absolute(struct box *box,
int space;
assert(box->type == BOX_BLOCK || box->type == BOX_TABLE ||
- box->type == BOX_INLINE_BLOCK);
+ box->type == BOX_INLINE_BLOCK ||
+ box->type == BOX_FLEX ||
+ box->type == BOX_INLINE_FLEX);
/* The static position is where the box would be if it was not
* absolutely positioned. The x and y are filled in by
@@ -4586,18 +4613,16 @@ layout_absolute(struct box *box,
containing_block->padding[RIGHT];
containing_block->height += containing_block->padding[TOP] +
containing_block->padding[BOTTOM];
- } else {
- /** \todo inline containers */
}
- layout_compute_offsets(&content->len_ctx, box, containing_block,
+ layout_compute_offsets(&content->unit_len_ctx, box, containing_block,
&top, &right, &bottom, &left);
/* Pass containing block into layout_find_dimensions via the float
* containing block box member. This is unused for absolutely positioned
* boxes because a box can't be floated and absolutely positioned. */
box->float_container = containing_block;
- layout_find_dimensions(&content->len_ctx, available_width, -1,
+ layout_find_dimensions(&content->unit_len_ctx, available_width, -1,
box, box->style, &width, &height,
&max_width, &min_width, 0, 0,
margin, padding, border);
@@ -4805,6 +4830,13 @@ layout_absolute(struct box *box,
box->float_container = NULL;
layout_solve_width(box, box->parent->width, box->width, 0, 0,
-1, -1);
+ } else if (box->type == BOX_FLEX || box->type == BOX_INLINE_FLEX) {
+ /* layout_table also expects the containing block to be
+ * stored in the float_container field */
+ box->float_container = containing_block;
+ if (!layout_flex(box, width, content))
+ return false;
+ box->float_container = NULL;
}
/* 10.6.4 */
@@ -4915,7 +4947,7 @@ layout_absolute(struct box *box,
/** \todo Inline ancestors */
}
box->height = height;
- layout_apply_minmax_height(&content->len_ctx, box, containing_block);
+ layout_apply_minmax_height(&content->unit_len_ctx, box, containing_block);
return true;
}
@@ -4941,7 +4973,9 @@ layout_position_absolute(struct box *box,
for (c = box->children; c; c = c->next) {
if ((c->type == BOX_BLOCK || c->type == BOX_TABLE ||
- c->type == BOX_INLINE_BLOCK) &&
+ c->type == BOX_INLINE_BLOCK ||
+ c->type == BOX_FLEX ||
+ c->type == BOX_INLINE_FLEX) &&
(css_computed_position(c->style) ==
CSS_POSITION_ABSOLUTE ||
css_computed_position(c->style) ==
@@ -4992,13 +5026,13 @@ layout_position_absolute(struct box *box,
/**
* Compute a box's relative offset as per CSS 2.1 9.4.3
*
- * \param len_ctx Length conversion context
+ * \param unit_len_ctx Length conversion context
* \param box Box to compute relative offsets for.
* \param x Receives relative offset in x.
* \param y Receives relative offset in y.
*/
static void layout_compute_relative_offset(
- const nscss_len_ctx *len_ctx,
+ const css_unit_ctx *unit_len_ctx,
struct box *box,
int *x,
int *y)
@@ -5018,7 +5052,7 @@ static void layout_compute_relative_offset(
containing_block = box->parent;
}
- layout_compute_offsets(len_ctx, box, containing_block,
+ layout_compute_offsets(unit_len_ctx, box, containing_block,
&top, &right, &bottom, &left);
if (left == AUTO && right == AUTO)
@@ -5066,7 +5100,7 @@ static void layout_compute_relative_offset(
/**
* Adjust positions of relatively positioned boxes.
*
- * \param len_ctx Length conversion context
+ * \param unit_len_ctx Length conversion context
* \param root box to adjust the position of
* \param fp box which forms the block formatting context for children of
* "root" which are floats
@@ -5079,7 +5113,7 @@ static void layout_compute_relative_offset(
*/
static void
layout_position_relative(
- const nscss_len_ctx *len_ctx,
+ const css_unit_ctx *unit_len_ctx,
struct box *root,
struct box *fp,
int fx,
@@ -5108,7 +5142,7 @@ layout_position_relative(
if (box->style && css_computed_position(box->style) ==
CSS_POSITION_RELATIVE)
layout_compute_relative_offset(
- len_ctx, box, &x, &y);
+ unit_len_ctx, box, &x, &y);
else
x = y = 0;
@@ -5144,7 +5178,7 @@ layout_position_relative(
}
/* recurse first */
- layout_position_relative(len_ctx, box, fn, fnx, fny);
+ layout_position_relative(unit_len_ctx, box, fn, fnx, fny);
/* Ignore things we're not interested in. */
if (!box->style || (box->style &&
@@ -5173,7 +5207,7 @@ layout_position_relative(
/**
* Find a box's bounding box relative to itself, i.e. the box's border edge box
*
- * \param len_ctx Length conversion context
+ * \param unit_len_ctx Length conversion context
* \param box box find bounding box of
* \param desc_x0 updated to left of box's bbox
* \param desc_y0 updated to top of box's bbox
@@ -5182,7 +5216,7 @@ layout_position_relative(
*/
static void
layout_get_box_bbox(
- const nscss_len_ctx *len_ctx,
+ const css_unit_ctx *unit_len_ctx,
struct box *box,
int *desc_x0, int *desc_y0,
int *desc_x1, int *desc_y1)
@@ -5205,8 +5239,8 @@ layout_get_box_bbox(
int text_height;
css_computed_font_size(box->style, &font_size, &font_unit);
- text_height = nscss_len2px(len_ctx, font_size, font_unit,
- box->style);
+ text_height = css_unit_len2device_px(box->style, unit_len_ctx,
+ font_size, font_unit);
text_height = FIXTOINT(text_height * 3 / 4);
*desc_y0 = (*desc_y0 < -text_height) ? *desc_y0 : -text_height;
}
@@ -5216,7 +5250,7 @@ layout_get_box_bbox(
/**
* Apply changes to box descendant_[xy][01] values due to given child.
*
- * \param len_ctx Length conversion context
+ * \param unit_len_ctx Length conversion context
* \param box box to update
* \param child a box, which may affect box's descendant bbox
* \param off_x offset to apply to child->x coord to treat as child of box
@@ -5224,7 +5258,7 @@ layout_get_box_bbox(
*/
static void
layout_update_descendant_bbox(
- const nscss_len_ctx *len_ctx,
+ const css_unit_ctx *unit_len_ctx,
struct box *box,
struct box *child,
int off_x,
@@ -5248,7 +5282,7 @@ layout_update_descendant_bbox(
}
/* Get child's border edge */
- layout_get_box_bbox(len_ctx, child,
+ layout_get_box_bbox(unit_len_ctx, child,
&child_desc_x0, &child_desc_y0,
&child_desc_x1, &child_desc_y1);
@@ -5286,11 +5320,11 @@ layout_update_descendant_bbox(
* Recursively calculate the descendant_[xy][01] values for a laid-out box tree
* and inform iframe browser windows of their size and position.
*
- * \param len_ctx Length conversion context
+ * \param unit_len_ctx Length conversion context
* \param box tree of boxes to update
*/
static void layout_calculate_descendant_bboxes(
- const nscss_len_ctx *len_ctx,
+ const css_unit_ctx *unit_len_ctx,
struct box *box)
{
struct box *child;
@@ -5300,7 +5334,7 @@ static void layout_calculate_descendant_bboxes(
/* assert((box->width >= 0) && (box->height >= 0)); */
/* Initialise box's descendant box to border edge box */
- layout_get_box_bbox(len_ctx, box,
+ layout_get_box_bbox(unit_len_ctx, box,
&box->descendant_x0, &box->descendant_y0,
&box->descendant_x1, &box->descendant_y1);
@@ -5334,7 +5368,7 @@ static void layout_calculate_descendant_bboxes(
child->type == BOX_FLOAT_RIGHT)
continue;
- layout_update_descendant_bbox(len_ctx, box, child,
+ layout_update_descendant_bbox(unit_len_ctx, box, child,
box->x, box->y);
if (child == box->inline_end)
@@ -5352,7 +5386,7 @@ static void layout_calculate_descendant_bboxes(
child->type == BOX_FLOAT_RIGHT)
continue;
- layout_calculate_descendant_bboxes(len_ctx, child);
+ layout_calculate_descendant_bboxes(unit_len_ctx, child);
if (box->style && css_computed_overflow_x(box->style) ==
CSS_OVERFLOW_HIDDEN &&
@@ -5360,37 +5394,41 @@ static void layout_calculate_descendant_bboxes(
CSS_OVERFLOW_HIDDEN)
continue;
- layout_update_descendant_bbox(len_ctx, box, child, 0, 0);
+ layout_update_descendant_bbox(unit_len_ctx, box, child, 0, 0);
}
for (child = box->float_children; child; child = child->next_float) {
assert(child->type == BOX_FLOAT_LEFT ||
child->type == BOX_FLOAT_RIGHT);
- layout_calculate_descendant_bboxes(len_ctx, child);
+ layout_calculate_descendant_bboxes(unit_len_ctx, child);
- layout_update_descendant_bbox(len_ctx, box, child, 0, 0);
+ layout_update_descendant_bbox(unit_len_ctx, box, child, 0, 0);
}
if (box->list_marker) {
child = box->list_marker;
- layout_calculate_descendant_bboxes(len_ctx, child);
+ layout_calculate_descendant_bboxes(unit_len_ctx, child);
- layout_update_descendant_bbox(len_ctx, box, child, 0, 0);
+ layout_update_descendant_bbox(unit_len_ctx, box, child, 0, 0);
}
}
-/* exported function documented in render/layout.h */
+/* exported function documented in html/layout.h */
bool layout_document(html_content *content, int width, int height)
{
bool ret;
struct box *doc = content->layout;
const struct gui_layout_table *font_func = content->font_func;
+ NSLOG(layout, DEBUG, "Doing layout to %ix%i of %s",
+ width, height, nsurl_access(content_get_url(
+ &content->base)));
+
layout_minmax_block(doc, font_func, content);
- layout_block_find_dimensions(&content->len_ctx,
+ layout_block_find_dimensions(&content->unit_len_ctx,
width, height, 0, 0, doc);
doc->x = doc->margin[LEFT] + doc->border[LEFT].width;
doc->y = doc->margin[TOP] + doc->border[TOP].width;
@@ -5422,11 +5460,11 @@ bool layout_document(html_content *content, int width, int height)
doc->children->margin[BOTTOM]);
}
- layout_lists(doc, font_func, &content->len_ctx);
+ layout_lists(content, doc);
layout_position_absolute(doc, doc, 0, 0, content);
- layout_position_relative(&content->len_ctx, doc, doc, 0, 0);
+ layout_position_relative(&content->unit_len_ctx, doc, doc, 0, 0);
- layout_calculate_descendant_bboxes(&content->len_ctx, doc);
+ layout_calculate_descendant_bboxes(&content->unit_len_ctx, doc);
return ret;
}
diff --git a/render/layout.h b/content/handlers/html/layout.h
index cd5ddd77f..0811e81de 100644
--- a/render/layout.h
+++ b/content/handlers/html/layout.h
@@ -18,15 +18,15 @@
/**
* \file
- * HTML layout (interface).
+ * interface to HTML layout.
*
* The main interface to the layout code is layout_document(), which takes a
* normalized box tree and assigns coordinates and dimensions to the boxes, and
* also adds boxes to the tree (eg. when formatting lines of text).
*/
-#ifndef _NETSURF_RENDER_LAYOUT_H_
-#define _NETSURF_RENDER_LAYOUT_H_
+#ifndef NETSURF_HTML_LAYOUT_H
+#define NETSURF_HTML_LAYOUT_H
struct box;
struct html_content;
diff --git a/content/handlers/html/layout_flex.c b/content/handlers/html/layout_flex.c
new file mode 100644
index 000000000..bde3c5bd1
--- /dev/null
+++ b/content/handlers/html/layout_flex.c
@@ -0,0 +1,1117 @@
+/*
+ * Copyright 2022 Michael Drake <tlsa@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * HTML layout implementation: display: flex.
+ *
+ * Layout is carried out in two stages:
+ *
+ * 1. + calculation of minimum / maximum box widths, and
+ * + determination of whether block level boxes will have >zero height
+ *
+ * 2. + layout (position and dimensions)
+ *
+ * In most cases the functions for the two stages are a corresponding pair
+ * layout_minmax_X() and layout_X().
+ */
+
+#include <string.h>
+
+#include "utils/log.h"
+#include "utils/utils.h"
+
+#include "html/box.h"
+#include "html/html.h"
+#include "html/private.h"
+#include "html/box_inspect.h"
+#include "html/layout_internal.h"
+
+/**
+ * Flex item data
+ */
+struct flex_item_data {
+ enum css_flex_basis_e basis;
+ css_fixed basis_length;
+ css_unit basis_unit;
+ struct box *box;
+
+ css_fixed shrink;
+ css_fixed grow;
+
+ int min_main;
+ int max_main;
+ int min_cross;
+ int max_cross;
+
+ int target_main_size;
+ int base_size;
+ int main_size;
+ size_t line;
+
+ bool freeze;
+ bool min_violation;
+ bool max_violation;
+};
+
+/**
+ * Flex line data
+ */
+struct flex_line_data {
+ int main_size;
+ int cross_size;
+
+ int used_main_size;
+ int main_auto_margin_count;
+
+ int pos;
+
+ size_t first;
+ size_t count;
+ size_t frozen;
+};
+
+/**
+ * Flex layout context
+ */
+struct flex_ctx {
+ html_content *content;
+ const struct box *flex;
+ const css_unit_ctx *unit_len_ctx;
+
+ int main_size;
+ int cross_size;
+
+ int available_main;
+ int available_cross;
+
+ bool horizontal;
+ bool main_reversed;
+ enum css_flex_wrap_e wrap;
+
+ struct flex_items {
+ size_t count;
+ struct flex_item_data *data;
+ } item;
+
+ struct flex_lines {
+ size_t count;
+ size_t alloc;
+ struct flex_line_data *data;
+ } line;
+};
+
+/**
+ * Destroy a flex layout context
+ *
+ * \param[in] ctx Flex layout context
+ */
+static void layout_flex_ctx__destroy(struct flex_ctx *ctx)
+{
+ if (ctx != NULL) {
+ free(ctx->item.data);
+ free(ctx->line.data);
+ free(ctx);
+ }
+}
+
+/**
+ * Create a flex layout context
+ *
+ * \param[in] content HTML content containing flex box
+ * \param[in] flex Box to create layout context for
+ * \return flex layout context or NULL on error
+ */
+static struct flex_ctx *layout_flex_ctx__create(
+ html_content *content,
+ const struct box *flex)
+{
+ struct flex_ctx *ctx;
+
+ ctx = calloc(1, sizeof(*ctx));
+ if (ctx == NULL) {
+ return NULL;
+ }
+ ctx->line.alloc = 1;
+
+ ctx->item.count = box_count_children(flex);
+ ctx->item.data = calloc(ctx->item.count, sizeof(*ctx->item.data));
+ if (ctx->item.data == NULL) {
+ layout_flex_ctx__destroy(ctx);
+ return NULL;
+ }
+
+ ctx->line.alloc = 1;
+ ctx->line.data = calloc(ctx->line.alloc, sizeof(*ctx->line.data));
+ if (ctx->line.data == NULL) {
+ layout_flex_ctx__destroy(ctx);
+ return NULL;
+ }
+
+ ctx->flex = flex;
+ ctx->content = content;
+ ctx->unit_len_ctx = &content->unit_len_ctx;
+
+ ctx->wrap = css_computed_flex_wrap(flex->style);
+ ctx->horizontal = lh__flex_main_is_horizontal(flex);
+ ctx->main_reversed = lh__flex_direction_reversed(flex);
+
+ return ctx;
+}
+
+/**
+ * Find box side representing the start of flex container in main direction.
+ *
+ * \param[in] ctx Flex layout context.
+ * \return the start side.
+ */
+static enum box_side layout_flex__main_start_side(
+ const struct flex_ctx *ctx)
+{
+ if (ctx->horizontal) {
+ return (ctx->main_reversed) ? RIGHT : LEFT;
+ } else {
+ return (ctx->main_reversed) ? BOTTOM : TOP;
+ }
+}
+
+/**
+ * Find box side representing the end of flex container in main direction.
+ *
+ * \param[in] ctx Flex layout context.
+ * \return the end side.
+ */
+static enum box_side layout_flex__main_end_side(
+ const struct flex_ctx *ctx)
+{
+ if (ctx->horizontal) {
+ return (ctx->main_reversed) ? LEFT : RIGHT;
+ } else {
+ return (ctx->main_reversed) ? TOP : BOTTOM;
+ }
+}
+
+/**
+ * Perform layout on a flex item
+ *
+ * \param[in] ctx Flex layout context
+ * \param[in] item Item to lay out
+ * \param[in] available_width Available width for item in pixels
+ * \return true on success false on failure
+ */
+static bool layout_flex_item(
+ const struct flex_ctx *ctx,
+ const struct flex_item_data *item,
+ int available_width)
+{
+ bool success;
+ struct box *b = item->box;
+
+ switch (b->type) {
+ case BOX_BLOCK:
+ success = layout_block_context(b, -1, ctx->content);
+ break;
+ case BOX_TABLE:
+ b->float_container = b->parent;
+ success = layout_table(b, available_width, ctx->content);
+ b->float_container = NULL;
+ break;
+ case BOX_FLEX:
+ b->float_container = b->parent;
+ success = layout_flex(b, available_width, ctx->content);
+ b->float_container = NULL;
+ break;
+ default:
+ assert(0 && "Bad flex item back type");
+ success = false;
+ break;
+ }
+
+ if (!success) {
+ NSLOG(flex, ERROR, "box %p: layout failed", b);
+ }
+
+ return success;
+}
+
+/**
+ * Calculate an item's base and target main sizes.
+ *
+ * \param[in] ctx Flex layout context
+ * \param[in] item Item to get sizes of
+ * \param[in] available_width Available width in pixels
+ * \return true on success false on failure
+ */
+static inline bool layout_flex__base_and_main_sizes(
+ const struct flex_ctx *ctx,
+ struct flex_item_data *item,
+ int available_width)
+{
+ struct box *b = item->box;
+ int content_min_width = b->min_width;
+ int content_max_width = b->max_width;
+ int delta_outer_main = lh__delta_outer_main(ctx->flex, b);
+
+ NSLOG(flex, DEEPDEBUG, "box %p: delta_outer_main: %i",
+ b, delta_outer_main);
+
+ if (item->basis == CSS_FLEX_BASIS_SET) {
+ if (item->basis_unit == CSS_UNIT_PCT) {
+ item->base_size = FPCT_OF_INT_TOINT(
+ item->basis_length,
+ available_width);
+ } else {
+ item->base_size = FIXTOINT(css_unit_len2device_px(
+ b->style, ctx->unit_len_ctx,
+ item->basis_length,
+ item->basis_unit));
+ }
+
+ } else if (item->basis == CSS_FLEX_BASIS_AUTO) {
+ item->base_size = ctx->horizontal ? b->width : b->height;
+ } else {
+ item->base_size = AUTO;
+ }
+
+ if (ctx->horizontal == false) {
+ if (b->width == AUTO) {
+ b->width = min(max(content_min_width, available_width),
+ content_max_width);
+ b->width -= lh__delta_outer_width(b);
+ }
+
+ if (!layout_flex_item(ctx, item, b->width)) {
+ return false;
+ }
+ }
+
+ if (item->base_size == AUTO) {
+ if (ctx->horizontal == false) {
+ item->base_size = b->height;
+ } else {
+ item->base_size = content_max_width - delta_outer_main;
+ }
+ }
+
+ item->base_size += delta_outer_main;
+
+ if (ctx->horizontal) {
+ item->base_size = min(item->base_size, available_width);
+ item->base_size = max(item->base_size, content_min_width);
+ }
+
+ item->target_main_size = item->base_size;
+ item->main_size = item->base_size;
+
+ if (item->max_main > 0 &&
+ item->main_size > item->max_main + delta_outer_main) {
+ item->main_size = item->max_main + delta_outer_main;
+ }
+
+ if (item->main_size < item->min_main + delta_outer_main) {
+ item->main_size = item->min_main + delta_outer_main;
+ }
+
+ NSLOG(flex, DEEPDEBUG, "flex-item box: %p: base_size: %i, main_size %i",
+ b, item->base_size, item->main_size);
+
+ return true;
+}
+
+/**
+ * Fill out all item's data in a flex container.
+ *
+ * \param[in] ctx Flex layout context
+ * \param[in] flex Flex box
+ * \param[in] available_width Available width in pixels
+ */
+static void layout_flex_ctx__populate_item_data(
+ const struct flex_ctx *ctx,
+ const struct box *flex,
+ int available_width)
+{
+ size_t i = 0;
+ bool horizontal = ctx->horizontal;
+
+ for (struct box *b = flex->children; b != NULL; b = b->next) {
+ struct flex_item_data *item = &ctx->item.data[i++];
+
+ b->float_container = b->parent;
+ layout_find_dimensions(ctx->unit_len_ctx, available_width, -1,
+ b, b->style, &b->width, &b->height,
+ horizontal ? &item->max_main : &item->max_cross,
+ horizontal ? &item->min_main : &item->min_cross,
+ horizontal ? &item->max_cross : &item->max_main,
+ horizontal ? &item->min_cross : &item->min_main,
+ b->margin, b->padding, b->border);
+ b->float_container = NULL;
+
+ NSLOG(flex, DEEPDEBUG, "flex-item box: %p: width: %i",
+ b, b->width);
+
+ item->box = b;
+ item->basis = css_computed_flex_basis(b->style,
+ &item->basis_length, &item->basis_unit);
+
+ css_computed_flex_shrink(b->style, &item->shrink);
+ css_computed_flex_grow(b->style, &item->grow);
+
+ layout_flex__base_and_main_sizes(ctx, item, available_width);
+ }
+}
+
+/**
+ * Ensure context's lines array has a free space
+ *
+ * \param[in] ctx Flex layout context
+ * \return true on success false on out of memory
+ */
+static bool layout_flex_ctx__ensure_line(struct flex_ctx *ctx)
+{
+ struct flex_line_data *temp;
+ size_t line_alloc = ctx->line.alloc * 2;
+
+ if (ctx->line.alloc > ctx->line.count) {
+ return true;
+ }
+
+ temp = realloc(ctx->line.data, sizeof(*ctx->line.data) * line_alloc);
+ if (temp == NULL) {
+ return false;
+ }
+ ctx->line.data = temp;
+
+ memset(ctx->line.data + ctx->line.alloc, 0,
+ sizeof(*ctx->line.data) * (line_alloc - ctx->line.alloc));
+ ctx->line.alloc = line_alloc;
+
+ return true;
+}
+
+/**
+ * Assigns flex items to the line and returns the line
+ *
+ * \param[in] ctx Flex layout context
+ * \param[in] item_index Index to first item to assign to this line
+ * \return Pointer to the new line, or NULL on error.
+ */
+static struct flex_line_data *layout_flex__build_line(struct flex_ctx *ctx,
+ size_t item_index)
+{
+ enum box_side start_side = layout_flex__main_start_side(ctx);
+ enum box_side end_side = layout_flex__main_end_side(ctx);
+ struct flex_line_data *line;
+ int used_main = 0;
+
+ if (!layout_flex_ctx__ensure_line(ctx)) {
+ return NULL;
+ }
+
+ line = &ctx->line.data[ctx->line.count];
+ line->first = item_index;
+
+ NSLOG(flex, DEEPDEBUG, "flex container %p: available main: %i",
+ ctx->flex, ctx->available_main);
+
+ while (item_index < ctx->item.count) {
+ struct flex_item_data *item = &ctx->item.data[item_index];
+ struct box *b = item->box;
+ int pos_main;
+
+ pos_main = ctx->horizontal ?
+ item->main_size :
+ b->height + lh__delta_outer_main(ctx->flex, b);
+
+ if (ctx->wrap == CSS_FLEX_WRAP_NOWRAP ||
+ pos_main + used_main <= ctx->available_main ||
+ lh__box_is_absolute(item->box) ||
+ ctx->available_main == AUTO ||
+ line->count == 0 ||
+ pos_main == 0) {
+ if (lh__box_is_absolute(item->box) == false) {
+ line->main_size += item->main_size;
+ used_main += pos_main;
+
+ if (b->margin[start_side] == AUTO) {
+ line->main_auto_margin_count++;
+ }
+ if (b->margin[end_side] == AUTO) {
+ line->main_auto_margin_count++;
+ }
+ }
+ item->line = ctx->line.count;
+ line->count++;
+ item_index++;
+ } else {
+ break;
+ }
+ }
+
+ if (line->count > 0) {
+ ctx->line.count++;
+ } else {
+ NSLOG(layout, ERROR, "Failed to fit any flex items");
+ }
+
+ return line;
+}
+
+/**
+ * Freeze an item on a line
+ *
+ * \param[in] line Line to containing item
+ * \param[in] item Item to freeze
+ */
+static inline void layout_flex__item_freeze(
+ struct flex_line_data *line,
+ struct flex_item_data *item)
+{
+ item->freeze = true;
+ line->frozen++;
+
+ if (!lh__box_is_absolute(item->box)){
+ line->used_main_size += item->target_main_size;
+ }
+
+ NSLOG(flex, DEEPDEBUG, "flex-item box: %p: "
+ "Frozen at target_main_size: %i",
+ item->box, item->target_main_size);
+}
+
+/**
+ * Calculate remaining free space and unfrozen item factor sum
+ *
+ * \param[in] ctx Flex layout context
+ * \param[in] line Line to calculate free space on
+ * \param[out] unfrozen_factor_sum Returns sum of unfrozen item's flex factors
+ * \param[in] initial_free_main Initial free space in main direction
+ * \param[in] available_main Available space in main direction
+ * \param[in] grow Whether to grow or shrink
+ * return remaining free space on line
+ */
+static inline int layout_flex__remaining_free_main(
+ struct flex_ctx *ctx,
+ struct flex_line_data *line,
+ css_fixed *unfrozen_factor_sum,
+ int initial_free_main,
+ int available_main,
+ bool grow)
+{
+ int remaining_free_main = available_main;
+ size_t item_count = line->first + line->count;
+
+ *unfrozen_factor_sum = 0;
+
+ for (size_t i = line->first; i < item_count; i++) {
+ struct flex_item_data *item = &ctx->item.data[i];
+
+ if (item->freeze) {
+ remaining_free_main -= item->target_main_size;
+ } else {
+ remaining_free_main -= item->base_size;
+
+ *unfrozen_factor_sum += grow ?
+ item->grow : item->shrink;
+ }
+ }
+
+ if (*unfrozen_factor_sum < F_1) {
+ int free_space = FIXTOINT(FMUL(INTTOFIX(initial_free_main),
+ *unfrozen_factor_sum));
+
+ if (free_space < remaining_free_main) {
+ remaining_free_main = free_space;
+ }
+ }
+
+ NSLOG(flex, DEEPDEBUG, "Remaining free space: %i",
+ remaining_free_main);
+
+ return remaining_free_main;
+}
+
+/**
+ * Clamp flex item target main size and get min/max violations
+ *
+ * \param[in] ctx Flex layout context
+ * \param[in] line Line to align items on
+ * return total violation in pixels
+ */
+static inline int layout_flex__get_min_max_violations(
+ struct flex_ctx *ctx,
+ struct flex_line_data *line)
+{
+
+ int total_violation = 0;
+ size_t item_count = line->first + line->count;
+
+ for (size_t i = line->first; i < item_count; i++) {
+ struct flex_item_data *item = &ctx->item.data[i];
+ int target_main_size = item->target_main_size;
+
+ NSLOG(flex, DEEPDEBUG, "item %p: target_main_size: %i",
+ item->box, target_main_size);
+
+ if (item->freeze) {
+ continue;
+ }
+
+ if (item->max_main > 0 &&
+ target_main_size > item->max_main) {
+ target_main_size = item->max_main;
+ item->max_violation = true;
+ NSLOG(flex, DEEPDEBUG, "Violation: max_main: %i",
+ item->max_main);
+ }
+
+ if (target_main_size < item->min_main) {
+ target_main_size = item->min_main;
+ item->min_violation = true;
+ NSLOG(flex, DEEPDEBUG, "Violation: min_main: %i",
+ item->min_main);
+ }
+
+ if (target_main_size < item->box->min_width) {
+ target_main_size = item->box->min_width;
+ item->min_violation = true;
+ NSLOG(flex, DEEPDEBUG, "Violation: box min_width: %i",
+ item->box->min_width);
+ }
+
+ if (target_main_size < 0) {
+ target_main_size = 0;
+ item->min_violation = true;
+ NSLOG(flex, DEEPDEBUG, "Violation: less than 0");
+ }
+
+ total_violation += target_main_size - item->target_main_size;
+ item->target_main_size = target_main_size;
+ }
+
+ NSLOG(flex, DEEPDEBUG, "Total violation: %i", total_violation);
+
+ return total_violation;
+}
+
+/**
+ * Distribute remaining free space proportional to the flex factors.
+ *
+ * Remaining free space may be negative.
+ *
+ * \param[in] ctx Flex layout context
+ * \param[in] line Line to distribute free space on
+ * \param[in] unfrozen_factor_sum Sum of unfrozen item's flex factors
+ * \param[in] remaining_free_main Remaining free space in main direction
+ * \param[in] grow Whether to grow or shrink
+ */
+static inline void layout_flex__distribute_free_main(
+ struct flex_ctx *ctx,
+ struct flex_line_data *line,
+ css_fixed unfrozen_factor_sum,
+ int remaining_free_main,
+ bool grow)
+{
+ size_t item_count = line->first + line->count;
+
+ if (grow) {
+ css_fixed remainder = 0;
+ for (size_t i = line->first; i < item_count; i++) {
+ struct flex_item_data *item = &ctx->item.data[i];
+ css_fixed result;
+ css_fixed ratio;
+
+ if (item->freeze) {
+ continue;
+ }
+
+ ratio = FDIV(item->grow, unfrozen_factor_sum);
+ result = FMUL(INTTOFIX(remaining_free_main), ratio) +
+ remainder;
+
+ item->target_main_size = item->base_size +
+ FIXTOINT(result);
+ remainder = FIXFRAC(result);
+ }
+ } else {
+ css_fixed scaled_shrink_factor_sum = 0;
+ css_fixed remainder = 0;
+
+ for (size_t i = line->first; i < item_count; i++) {
+ struct flex_item_data *item = &ctx->item.data[i];
+ css_fixed scaled_shrink_factor;
+
+ if (item->freeze) {
+ continue;
+ }
+
+ scaled_shrink_factor = FMUL(
+ item->shrink,
+ INTTOFIX(item->base_size));
+ scaled_shrink_factor_sum += scaled_shrink_factor;
+ }
+
+ for (size_t i = line->first; i < item_count; i++) {
+ struct flex_item_data *item = &ctx->item.data[i];
+ css_fixed scaled_shrink_factor;
+ css_fixed result;
+ css_fixed ratio;
+
+ if (item->freeze) {
+ continue;
+ } else if (scaled_shrink_factor_sum == 0) {
+ item->target_main_size = item->main_size;
+ layout_flex__item_freeze(line, item);
+ continue;
+ }
+
+ scaled_shrink_factor = FMUL(
+ item->shrink,
+ INTTOFIX(item->base_size));
+ ratio = FDIV(scaled_shrink_factor,
+ scaled_shrink_factor_sum);
+ result = FMUL(INTTOFIX(abs(remaining_free_main)),
+ ratio) + remainder;
+
+ item->target_main_size = item->base_size -
+ FIXTOINT(result);
+ remainder = FIXFRAC(result);
+ }
+ }
+}
+
+/**
+ * Resolve flexible item lengths along a line.
+ *
+ * See 9.7 of Tests CSS Flexible Box Layout Module Level 1.
+ *
+ * \param[in] ctx Flex layout context
+ * \param[in] line Line to resolve
+ * \return true on success, false on failure.
+ */
+static bool layout_flex__resolve_line(
+ struct flex_ctx *ctx,
+ struct flex_line_data *line)
+{
+ size_t item_count = line->first + line->count;
+ int available_main = ctx->available_main;
+ int initial_free_main;
+ bool grow;
+
+ if (available_main == AUTO) {
+ available_main = INT_MAX;
+ }
+
+ grow = (line->main_size < available_main);
+ initial_free_main = available_main;
+
+ NSLOG(flex, DEEPDEBUG, "box %p: line %zu: first: %zu, count: %zu",
+ ctx->flex, line - ctx->line.data,
+ line->first, line->count);
+ NSLOG(flex, DEEPDEBUG, "Line main_size: %i, available_main: %i",
+ line->main_size, available_main);
+
+ for (size_t i = line->first; i < item_count; i++) {
+ struct flex_item_data *item = &ctx->item.data[i];
+
+ /* 3. Size inflexible items */
+ if (grow) {
+ if (item->grow == 0 ||
+ item->base_size > item->main_size) {
+ item->target_main_size = item->main_size;
+ layout_flex__item_freeze(line, item);
+ }
+ } else {
+ if (item->shrink == 0 ||
+ item->base_size < item->main_size) {
+ item->target_main_size = item->main_size;
+ layout_flex__item_freeze(line, item);
+ }
+ }
+
+ /* 4. Calculate initial free space */
+ if (item->freeze) {
+ initial_free_main -= item->target_main_size;
+ } else {
+ initial_free_main -= item->base_size;
+ }
+ }
+
+ /* 5. Loop */
+ while (line->frozen < line->count) {
+ css_fixed unfrozen_factor_sum;
+ int remaining_free_main;
+ int total_violation;
+
+ NSLOG(flex, DEEPDEBUG, "flex-container: %p: Resolver pass",
+ ctx->flex);
+
+ /* b */
+ remaining_free_main = layout_flex__remaining_free_main(ctx,
+ line, &unfrozen_factor_sum, initial_free_main,
+ available_main, grow);
+
+ /* c */
+ if (remaining_free_main != 0) {
+ layout_flex__distribute_free_main(ctx,
+ line, unfrozen_factor_sum,
+ remaining_free_main, grow);
+ }
+
+ /* d */
+ total_violation = layout_flex__get_min_max_violations(
+ ctx, line);
+
+ /* e */
+ for (size_t i = line->first; i < item_count; i++) {
+ struct flex_item_data *item = &ctx->item.data[i];
+
+ if (item->freeze) {
+ continue;
+ }
+
+ if (total_violation == 0 ||
+ (total_violation > 0 && item->min_violation) ||
+ (total_violation < 0 && item->max_violation)) {
+ layout_flex__item_freeze(line, item);
+ }
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Position items along a line
+ *
+ * \param[in] ctx Flex layout context
+ * \param[in] line Line to resolve
+ * \return true on success, false on failure.
+ */
+static bool layout_flex__place_line_items_main(
+ struct flex_ctx *ctx,
+ struct flex_line_data *line)
+{
+ int main_pos = ctx->flex->padding[layout_flex__main_start_side(ctx)];
+ int post_multiplier = ctx->main_reversed ? 0 : 1;
+ int pre_multiplier = ctx->main_reversed ? -1 : 0;
+ size_t item_count = line->first + line->count;
+ int extra_remainder = 0;
+ int extra = 0;
+
+ if (ctx->main_reversed) {
+ main_pos = lh__box_size_main(ctx->horizontal, ctx->flex) -
+ main_pos;
+ }
+
+ if (ctx->available_main != AUTO &&
+ ctx->available_main != UNKNOWN_WIDTH &&
+ ctx->available_main > line->used_main_size) {
+ if (line->main_auto_margin_count > 0) {
+ extra = ctx->available_main - line->used_main_size;
+
+ extra_remainder = extra % line->main_auto_margin_count;
+ extra /= line->main_auto_margin_count;
+ }
+ }
+
+ for (size_t i = line->first; i < item_count; i++) {
+ enum box_side main_end = ctx->horizontal ? RIGHT : BOTTOM;
+ enum box_side main_start = ctx->horizontal ? LEFT : TOP;
+ struct flex_item_data *item = &ctx->item.data[i];
+ struct box *b = item->box;
+ int extra_total = 0;
+ int extra_post = 0;
+ int extra_pre = 0;
+ int box_size_main;
+ int *box_pos_main;
+
+ if (ctx->horizontal) {
+ b->width = item->target_main_size -
+ lh__delta_outer_width(b);
+
+ if (!layout_flex_item(ctx, item, b->width)) {
+ return false;
+ }
+ }
+
+ box_size_main = lh__box_size_main(ctx->horizontal, b);
+ box_pos_main = ctx->horizontal ? &b->x : &b->y;
+
+ if (!lh__box_is_absolute(b)) {
+ if (b->margin[main_start] == AUTO) {
+ extra_pre = extra + extra_remainder;
+ }
+ if (b->margin[main_end] == AUTO) {
+ extra_post = extra + extra_remainder;
+ }
+ extra_total = extra_pre + extra_post;
+
+ main_pos += pre_multiplier *
+ (extra_total + box_size_main +
+ lh__delta_outer_main(ctx->flex, b));
+ }
+
+ *box_pos_main = main_pos + lh__non_auto_margin(b, main_start) +
+ extra_pre + b->border[main_start].width;
+
+ if (!lh__box_is_absolute(b)) {
+ int cross_size;
+ int box_size_cross = lh__box_size_cross(
+ ctx->horizontal, b);
+
+ main_pos += post_multiplier *
+ (extra_total + box_size_main +
+ lh__delta_outer_main(ctx->flex, b));
+
+ cross_size = box_size_cross + lh__delta_outer_cross(
+ ctx->flex, b);
+ if (line->cross_size < cross_size) {
+ line->cross_size = cross_size;
+ }
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Collect items onto lines and place items along the lines
+ *
+ * \param[in] ctx Flex layout context
+ * \return true on success, false on failure.
+ */
+static bool layout_flex__collect_items_into_lines(
+ struct flex_ctx *ctx)
+{
+ size_t pos = 0;
+
+ while (pos < ctx->item.count) {
+ struct flex_line_data *line;
+
+ line = layout_flex__build_line(ctx, pos);
+ if (line == NULL) {
+ return false;
+ }
+
+ pos += line->count;
+
+ NSLOG(flex, DEEPDEBUG, "flex-container: %p: "
+ "fitted: %zu (total: %zu/%zu)",
+ ctx->flex, line->count,
+ pos, ctx->item.count);
+
+ if (!layout_flex__resolve_line(ctx, line)) {
+ return false;
+ }
+
+ if (!layout_flex__place_line_items_main(ctx, line)) {
+ return false;
+ }
+
+ ctx->cross_size += line->cross_size;
+ if (ctx->main_size < line->main_size) {
+ ctx->main_size = line->main_size;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Align items on a line.
+ *
+ * \param[in] ctx Flex layout context
+ * \param[in] line Line to align items on
+ * \param[in] extra Extra line width in pixels
+ */
+static void layout_flex__place_line_items_cross(struct flex_ctx *ctx,
+ struct flex_line_data *line, int extra)
+{
+ enum box_side cross_start = ctx->horizontal ? TOP : LEFT;
+ size_t item_count = line->first + line->count;
+
+ for (size_t i = line->first; i < item_count; i++) {
+ struct flex_item_data *item = &ctx->item.data[i];
+ struct box *b = item->box;
+ int cross_free_space;
+ int *box_size_cross;
+ int *box_pos_cross;
+
+ box_pos_cross = ctx->horizontal ? &b->y : &b->x;
+ box_size_cross = lh__box_size_cross_ptr(ctx->horizontal, b);
+
+ cross_free_space = line->cross_size + extra - *box_size_cross -
+ lh__delta_outer_cross(ctx->flex, b);
+
+ switch (lh__box_align_self(ctx->flex, b)) {
+ default:
+ case CSS_ALIGN_SELF_STRETCH:
+ if (lh__box_size_cross_is_auto(ctx->horizontal, b)) {
+ *box_size_cross += cross_free_space;
+
+ /* Relayout children for stretch. */
+ if (!layout_flex_item(ctx, item, b->width)) {
+ return;
+ }
+ }
+ fallthrough;
+ case CSS_ALIGN_SELF_FLEX_START:
+ *box_pos_cross = ctx->flex->padding[cross_start] +
+ line->pos +
+ lh__non_auto_margin(b, cross_start) +
+ b->border[cross_start].width;
+ break;
+
+ case CSS_ALIGN_SELF_FLEX_END:
+ *box_pos_cross = ctx->flex->padding[cross_start] +
+ line->pos + cross_free_space +
+ lh__non_auto_margin(b, cross_start) +
+ b->border[cross_start].width;
+ break;
+
+ case CSS_ALIGN_SELF_BASELINE:
+ case CSS_ALIGN_SELF_CENTER:
+ *box_pos_cross = ctx->flex->padding[cross_start] +
+ line->pos + cross_free_space / 2 +
+ lh__non_auto_margin(b, cross_start) +
+ b->border[cross_start].width;
+ break;
+ }
+ }
+}
+
+/**
+ * Place the lines and align the items on the line.
+ *
+ * \param[in] ctx Flex layout context
+ */
+static void layout_flex__place_lines(struct flex_ctx *ctx)
+{
+ bool reversed = ctx->wrap == CSS_FLEX_WRAP_WRAP_REVERSE;
+ int line_pos = reversed ? ctx->cross_size : 0;
+ int post_multiplier = reversed ? 0 : 1;
+ int pre_multiplier = reversed ? -1 : 0;
+ int extra_remainder = 0;
+ int extra = 0;
+
+ if (ctx->available_cross != AUTO &&
+ ctx->available_cross > ctx->cross_size &&
+ ctx->line.count > 0) {
+ extra = ctx->available_cross - ctx->cross_size;
+
+ extra_remainder = extra % ctx->line.count;
+ extra /= ctx->line.count;
+ }
+
+ for (size_t i = 0; i < ctx->line.count; i++) {
+ struct flex_line_data *line = &ctx->line.data[i];
+
+ line_pos += pre_multiplier * line->cross_size;
+ line->pos = line_pos;
+ line_pos += post_multiplier * line->cross_size +
+ extra + extra_remainder;
+
+ layout_flex__place_line_items_cross(ctx, line,
+ extra + extra_remainder);
+
+ if (extra_remainder > 0) {
+ extra_remainder--;
+ }
+ }
+}
+
+/**
+ * Layout a flex container.
+ *
+ * \param[in] flex table to layout
+ * \param[in] available_width width of containing block
+ * \param[in] content memory pool for any new boxes
+ * \return true on success, false on memory exhaustion
+ */
+bool layout_flex(struct box *flex, int available_width,
+ html_content *content)
+{
+ int max_height, min_height;
+ struct flex_ctx *ctx;
+ bool success = false;
+
+ ctx = layout_flex_ctx__create(content, flex);
+ if (ctx == NULL) {
+ return false;
+ }
+
+ NSLOG(flex, DEEPDEBUG, "box %p: %s, available_width %i, width: %i",
+ flex, ctx->horizontal ? "horizontal" : "vertical",
+ available_width, flex->width);
+
+ layout_find_dimensions(
+ ctx->unit_len_ctx, available_width, -1,
+ flex, flex->style, NULL, &flex->height,
+ NULL, NULL, &max_height, &min_height,
+ flex->margin, flex->padding, flex->border);
+
+ available_width = min(available_width, flex->width);
+
+ if (ctx->horizontal) {
+ ctx->available_main = available_width;
+ ctx->available_cross = ctx->flex->height;
+ } else {
+ ctx->available_main = ctx->flex->height;
+ ctx->available_cross = available_width;
+ }
+
+ NSLOG(flex, DEEPDEBUG, "box %p: available_main: %i",
+ flex, ctx->available_main);
+ NSLOG(flex, DEEPDEBUG, "box %p: available_cross: %i",
+ flex, ctx->available_cross);
+
+ layout_flex_ctx__populate_item_data(ctx, flex, available_width);
+
+ /* Place items onto lines. */
+ success = layout_flex__collect_items_into_lines(ctx);
+ if (!success) {
+ goto cleanup;
+ }
+
+ layout_flex__place_lines(ctx);
+
+ if (flex->height == AUTO) {
+ flex->height = ctx->horizontal ?
+ ctx->cross_size :
+ ctx->main_size;
+ }
+
+ if (flex->height != AUTO) {
+ if (max_height >= 0 && flex->height > max_height) {
+ flex->height = max_height;
+ }
+ if (min_height > 0 && flex->height < min_height) {
+ flex->height = min_height;
+ }
+ }
+
+ success = true;
+
+cleanup:
+ layout_flex_ctx__destroy(ctx);
+
+ NSLOG(flex, DEEPDEBUG, "box %p: %s: w: %i, h: %i", flex,
+ success ? "success" : "failure",
+ flex->width, flex->height);
+ return success;
+}
diff --git a/content/handlers/html/layout_internal.h b/content/handlers/html/layout_internal.h
new file mode 100644
index 000000000..d094462ec
--- /dev/null
+++ b/content/handlers/html/layout_internal.h
@@ -0,0 +1,738 @@
+/*
+ * Copyright 2003 James Bursa <bursa@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * HTML layout private interface.
+ */
+
+#ifndef NETSURF_HTML_LAYOUT_INTERNAL_H
+#define NETSURF_HTML_LAYOUT_INTERNAL_H
+
+#define AUTO INT_MIN
+
+/* Fixed point percentage (a) of an integer (b), to an integer */
+#define FPCT_OF_INT_TOINT(a, b) (FIXTOINT(FDIV((a * b), F_100)))
+
+/**
+ * Layout a block formatting context.
+ *
+ * \param block BLOCK, INLINE_BLOCK, or TABLE_CELL to layout
+ * \param viewport_height Height of viewport in pixels or -ve if unknown
+ * \param content Memory pool for any new boxes
+ * \return true on success, false on memory exhaustion
+ *
+ * This function carries out layout of a block and its children, as described
+ * in CSS 2.1 9.4.1.
+ */
+bool layout_block_context(
+ struct box *block,
+ int viewport_height,
+ html_content *content);
+
+/**
+ * Layout a table.
+ *
+ * \param table table to layout
+ * \param available_width width of containing block
+ * \param content memory pool for any new boxes
+ * \return true on success, false on memory exhaustion
+ */
+bool layout_table(
+ struct box *table,
+ int available_width,
+ html_content *content);
+
+/**
+ * Layout a flex container.
+ *
+ * \param[in] flex table to layout
+ * \param[in] available_width width of containing block
+ * \param[in] content memory pool for any new boxes
+ * \return true on success, false on memory exhaustion
+ */
+bool layout_flex(
+ struct box *flex,
+ int available_width,
+ html_content *content);
+
+typedef uint8_t (*css_len_func)(
+ const css_computed_style *style,
+ css_fixed *length, css_unit *unit);
+typedef uint8_t (*css_border_style_func)(
+ const css_computed_style *style);
+typedef uint8_t (*css_border_color_func)(
+ const css_computed_style *style,
+ css_color *color);
+
+/** Array of per-side access functions for computed style margins. */
+extern const css_len_func margin_funcs[4];
+
+/** Array of per-side access functions for computed style paddings. */
+extern const css_len_func padding_funcs[4];
+
+/** Array of per-side access functions for computed style border_widths. */
+extern const css_len_func border_width_funcs[4];
+
+/** Array of per-side access functions for computed style border styles. */
+extern const css_border_style_func border_style_funcs[4];
+
+/** Array of per-side access functions for computed style border colors. */
+extern const css_border_color_func border_color_funcs[4];
+
+/** Layout helper: Check whether box is a float. */
+static inline bool lh__box_is_float_box(const struct box *b)
+{
+ return b->type == BOX_FLOAT_LEFT ||
+ b->type == BOX_FLOAT_RIGHT;
+}
+
+/** Layout helper: Check whether box takes part in inline flow. */
+static inline bool lh__box_is_inline_flow(const struct box *b)
+{
+ return b->type == BOX_INLINE ||
+ b->type == BOX_INLINE_FLEX ||
+ b->type == BOX_INLINE_BLOCK ||
+ b->type == BOX_TEXT ||
+ b->type == BOX_INLINE_END;
+}
+
+/** Layout helper: Check whether box takes part in inline flow. */
+static inline bool lh__box_is_flex_container(const struct box *b)
+{
+ return b->type == BOX_FLEX ||
+ b->type == BOX_INLINE_FLEX;
+}
+
+/** Layout helper: Check whether box takes part in inline flow. */
+static inline bool lh__box_is_flex_item(const struct box *b)
+{
+ return (b->parent != NULL) && lh__box_is_flex_container(b->parent);
+}
+
+/** Layout helper: Check whether box is inline level. (Includes BR.) */
+static inline bool lh__box_is_inline_level(const struct box *b)
+{
+ return lh__box_is_inline_flow(b) ||
+ b->type == BOX_BR;
+}
+
+/** Layout helper: Check whether box is inline level. (Includes BR, floats.) */
+static inline bool lh__box_is_inline_content(const struct box *b)
+{
+ return lh__box_is_float_box(b) ||
+ lh__box_is_inline_level(b);
+}
+
+/** Layout helper: Check whether box is an object. */
+static inline bool lh__box_is_object(const struct box *b)
+{
+ return b->object ||
+ (b->flags & (IFRAME | REPLACE_DIM));
+}
+
+/** Layout helper: Check whether box is replaced. */
+static inline bool lh__box_is_replace(const struct box *b)
+{
+ return b->gadget ||
+ lh__box_is_object(b);
+}
+
+/** Layout helper: Check for CSS border on given side. */
+static inline bool lh__have_border(
+ enum box_side side,
+ const css_computed_style *style)
+{
+ return border_style_funcs[side](style) != CSS_BORDER_STYLE_NONE;
+}
+
+static inline bool lh__box_is_absolute(const struct box *b)
+{
+ return css_computed_position(b->style) == CSS_POSITION_ABSOLUTE ||
+ css_computed_position(b->style) == CSS_POSITION_FIXED;
+}
+
+static inline bool lh__flex_main_is_horizontal(const struct box *flex)
+{
+ const css_computed_style *style = flex->style;
+
+ assert(style != NULL);
+
+ switch (css_computed_flex_direction(style)) {
+ default: /* Fallthrough. */
+ case CSS_FLEX_DIRECTION_ROW: /* Fallthrough. */
+ case CSS_FLEX_DIRECTION_ROW_REVERSE:
+ return true;
+ case CSS_FLEX_DIRECTION_COLUMN: /* Fallthrough. */
+ case CSS_FLEX_DIRECTION_COLUMN_REVERSE:
+ return false;
+ }
+}
+
+static inline bool lh__flex_direction_reversed(const struct box *flex)
+{
+ switch (css_computed_flex_direction(flex->style)) {
+ default: /* Fallthrough. */
+ case CSS_FLEX_DIRECTION_ROW_REVERSE: /* Fallthrough. */
+ case CSS_FLEX_DIRECTION_COLUMN_REVERSE:
+ return true;
+ case CSS_FLEX_DIRECTION_ROW: /* Fallthrough. */
+ case CSS_FLEX_DIRECTION_COLUMN:
+ return false;
+ }
+}
+
+static inline int lh__non_auto_margin(const struct box *b, enum box_side side)
+{
+ return (b->margin[side] == AUTO) ? 0 : b->margin[side];
+}
+
+static inline int lh__delta_outer_height(const struct box *b)
+{
+ return b->padding[TOP] +
+ b->padding[BOTTOM] +
+ b->border[TOP].width +
+ b->border[BOTTOM].width +
+ lh__non_auto_margin(b, TOP) +
+ lh__non_auto_margin(b, BOTTOM);
+}
+
+static inline int lh__delta_outer_width(const struct box *b)
+{
+ return b->padding[LEFT] +
+ b->padding[RIGHT] +
+ b->border[LEFT].width +
+ b->border[RIGHT].width +
+ lh__non_auto_margin(b, LEFT) +
+ lh__non_auto_margin(b, RIGHT);
+}
+
+static inline int lh__delta_outer_main(
+ const struct box *flex,
+ const struct box *b)
+{
+ if (lh__flex_main_is_horizontal(flex)) {
+ return lh__delta_outer_width(b);
+ } else {
+ return lh__delta_outer_height(b);
+ }
+}
+
+static inline int lh__delta_outer_cross(
+ const struct box *flex,
+ const struct box *b)
+{
+ if (lh__flex_main_is_horizontal(flex) == false) {
+ return lh__delta_outer_width(b);
+ } else {
+ return lh__delta_outer_height(b);
+ }
+}
+
+static inline int *lh__box_size_main_ptr(
+ bool horizontal,
+ struct box *b)
+{
+ return horizontal ? &b->width : &b->height;
+}
+
+static inline int *lh__box_size_cross_ptr(
+ bool horizontal,
+ struct box *b)
+{
+ return horizontal ? &b->height : &b->width;
+}
+
+static inline int lh__box_size_main(
+ bool horizontal,
+ const struct box *b)
+{
+ return horizontal ? b->width : b->height;
+}
+
+static inline int lh__box_size_cross(
+ bool horizontal,
+ const struct box *b)
+{
+ return horizontal ? b->height : b->width;
+}
+
+static inline bool lh__box_size_cross_is_auto(
+ bool horizontal,
+ struct box *b)
+{
+ css_fixed length;
+ css_unit unit;
+
+ if (horizontal) {
+ return css_computed_height(b->style,
+ &length, &unit) == CSS_HEIGHT_AUTO;
+ } else {
+ return css_computed_width(b->style,
+ &length, &unit) == CSS_WIDTH_AUTO;
+ }
+}
+
+static inline enum css_align_self_e lh__box_align_self(
+ const struct box *flex,
+ const struct box *item)
+{
+ enum css_align_self_e align_self = css_computed_align_self(item->style);
+
+ if (align_self == CSS_ALIGN_SELF_AUTO) {
+ align_self = css_computed_align_items(flex->style);
+ }
+
+ return align_self;
+}
+
+/**
+ * Determine width of margin, borders, and padding on one side of a box.
+ *
+ * \param unit_len_ctx CSS length conversion context for document
+ * \param style style to measure
+ * \param side side of box to measure
+ * \param margin whether margin width is required
+ * \param border whether border width is required
+ * \param padding whether padding width is required
+ * \param fixed increased by sum of fixed margin, border, and padding
+ * \param frac increased by sum of fractional margin and padding
+ */
+static inline void calculate_mbp_width(
+ const css_unit_ctx *unit_len_ctx,
+ const css_computed_style *style,
+ unsigned int side,
+ bool margin,
+ bool border,
+ bool padding,
+ int *fixed,
+ float *frac)
+{
+ css_fixed value = 0;
+ css_unit unit = CSS_UNIT_PX;
+
+ assert(style);
+
+ /* margin */
+ if (margin) {
+ enum css_margin_e type;
+
+ type = margin_funcs[side](style, &value, &unit);
+ if (type == CSS_MARGIN_SET) {
+ if (unit == CSS_UNIT_PCT) {
+ *frac += FIXTOFLT(FDIV(value, F_100));
+ } else {
+ *fixed += FIXTOINT(css_unit_len2device_px(
+ style, unit_len_ctx,
+ value, unit));
+ }
+ }
+ }
+
+ /* border */
+ if (border) {
+ if (lh__have_border(side, style)) {
+ border_width_funcs[side](style, &value, &unit);
+
+ *fixed += FIXTOINT(css_unit_len2device_px(
+ style, unit_len_ctx,
+ value, unit));
+ }
+ }
+
+ /* padding */
+ if (padding) {
+ padding_funcs[side](style, &value, &unit);
+ if (unit == CSS_UNIT_PCT) {
+ *frac += FIXTOFLT(FDIV(value, F_100));
+ } else {
+ *fixed += FIXTOINT(css_unit_len2device_px(
+ style, unit_len_ctx,
+ value, unit));
+ }
+ }
+}
+
+/**
+ * Adjust a specified width or height for the box-sizing property.
+ *
+ * This turns the specified dimension into a content-box dimension.
+ *
+ * \param unit_len_ctx Length conversion context
+ * \param box gadget to adjust dimensions of
+ * \param available_width width of containing block
+ * \param setwidth set true if the dimension to be tweaked is a width,
+ * else set false for a height
+ * \param dimension current value for given width/height dimension.
+ * updated to new value after consideration of
+ * gadget properties.
+ */
+static inline void layout_handle_box_sizing(
+ const css_unit_ctx *unit_len_ctx,
+ const struct box *box,
+ int available_width,
+ bool setwidth,
+ int *dimension)
+{
+ enum css_box_sizing_e bs;
+
+ assert(box && box->style);
+
+ bs = css_computed_box_sizing(box->style);
+
+ if (bs == CSS_BOX_SIZING_BORDER_BOX) {
+ int orig = *dimension;
+ int fixed = 0;
+ float frac = 0;
+
+ calculate_mbp_width(unit_len_ctx, box->style,
+ setwidth ? LEFT : TOP,
+ false, true, true, &fixed, &frac);
+ calculate_mbp_width(unit_len_ctx, box->style,
+ setwidth ? RIGHT : BOTTOM,
+ false, true, true, &fixed, &frac);
+ orig -= frac * available_width + fixed;
+ *dimension = orig > 0 ? orig : 0;
+ }
+}
+
+/**
+ * Calculate width, height, and thickness of margins, paddings, and borders.
+ *
+ * \param unit_len_ctx Length conversion context
+ * \param available_width width of containing block
+ * \param viewport_height height of viewport in pixels or -ve if unknown
+ * \param box current box
+ * \param style style giving width, height, margins, paddings,
+ * and borders
+ * \param width updated to width, may be NULL
+ * \param height updated to height, may be NULL
+ * \param max_width updated to max-width, may be NULL
+ * \param min_width updated to min-width, may be NULL
+ * \param max_height updated to max-height, may be NULL
+ * \param min_height updated to min-height, may be NULL
+ * \param margin filled with margins, may be NULL
+ * \param padding filled with paddings, may be NULL
+ * \param border filled with border widths, may be NULL
+ */
+static inline void layout_find_dimensions(
+ const css_unit_ctx *unit_len_ctx,
+ int available_width,
+ int viewport_height,
+ const struct box *box,
+ const css_computed_style *style,
+ int *width,
+ int *height,
+ int *max_width,
+ int *min_width,
+ int *max_height,
+ int *min_height,
+ int margin[4],
+ int padding[4],
+ struct box_border border[4])
+{
+ struct box *containing_block = NULL;
+ unsigned int i;
+
+ if (width) {
+ enum css_width_e wtype;
+ css_fixed value = 0;
+ css_unit unit = CSS_UNIT_PX;
+
+ wtype = css_computed_width(style, &value, &unit);
+
+ if (wtype == CSS_WIDTH_SET) {
+ if (unit == CSS_UNIT_PCT) {
+ *width = FPCT_OF_INT_TOINT(
+ value, available_width);
+ } else {
+ *width = FIXTOINT(css_unit_len2device_px(
+ style, unit_len_ctx,
+ value, unit));
+ }
+ } else {
+ *width = AUTO;
+ }
+
+ if (*width != AUTO) {
+ layout_handle_box_sizing(unit_len_ctx, box,
+ available_width, true, width);
+ }
+ }
+
+ if (height) {
+ enum css_height_e htype;
+ css_fixed value = 0;
+ css_unit unit = CSS_UNIT_PX;
+
+ htype = css_computed_height(style, &value, &unit);
+
+ if (htype == CSS_HEIGHT_SET) {
+ if (unit == CSS_UNIT_PCT) {
+ enum css_height_e cbhtype;
+
+ if (css_computed_position(box->style) ==
+ CSS_POSITION_ABSOLUTE &&
+ box->parent) {
+ /* Box is absolutely positioned */
+ assert(box->float_container);
+ containing_block = box->float_container;
+ } else if (box->float_container &&
+ css_computed_position(box->style) !=
+ CSS_POSITION_ABSOLUTE &&
+ (css_computed_float(box->style) ==
+ CSS_FLOAT_LEFT ||
+ css_computed_float(box->style) ==
+ CSS_FLOAT_RIGHT)) {
+ /* Box is a float */
+ assert(box->parent &&
+ box->parent->parent &&
+ box->parent->parent->parent);
+
+ containing_block =
+ box->parent->parent->parent;
+ } else if (box->parent && box->parent->type !=
+ BOX_INLINE_CONTAINER) {
+ /* Box is a block level element */
+ containing_block = box->parent;
+ } else if (box->parent && box->parent->type ==
+ BOX_INLINE_CONTAINER) {
+ /* Box is an inline block */
+ assert(box->parent->parent);
+ containing_block = box->parent->parent;
+ }
+
+ if (containing_block) {
+ css_fixed f = 0;
+ css_unit u = CSS_UNIT_PX;
+
+ cbhtype = css_computed_height(
+ containing_block->style,
+ &f, &u);
+ }
+
+ if (containing_block &&
+ containing_block->height != AUTO &&
+ (css_computed_position(box->style) ==
+ CSS_POSITION_ABSOLUTE ||
+ cbhtype == CSS_HEIGHT_SET)) {
+ /* Box is absolutely positioned or its
+ * containing block has a valid
+ * specified height.
+ * (CSS 2.1 Section 10.5) */
+ *height = FPCT_OF_INT_TOINT(value,
+ containing_block->height);
+ } else if ((!box->parent ||
+ !box->parent->parent) &&
+ viewport_height >= 0) {
+ /* If root element or it's child
+ * (HTML or BODY) */
+ *height = FPCT_OF_INT_TOINT(value,
+ viewport_height);
+ } else {
+ /* precentage height not permissible
+ * treat height as auto */
+ *height = AUTO;
+ }
+ } else {
+ *height = FIXTOINT(css_unit_len2device_px(
+ style, unit_len_ctx,
+ value, unit));
+ }
+ } else {
+ *height = AUTO;
+ }
+
+ if (*height != AUTO) {
+ layout_handle_box_sizing(unit_len_ctx, box,
+ available_width, false, height);
+ }
+ }
+
+ if (max_width) {
+ enum css_max_width_e type;
+ css_fixed value = 0;
+ css_unit unit = CSS_UNIT_PX;
+
+ type = css_computed_max_width(style, &value, &unit);
+
+ if (type == CSS_MAX_WIDTH_SET) {
+ if (unit == CSS_UNIT_PCT) {
+ *max_width = FPCT_OF_INT_TOINT(value,
+ available_width);
+ } else {
+ *max_width = FIXTOINT(css_unit_len2device_px(
+ style, unit_len_ctx,
+ value, unit));
+ }
+ } else {
+ /* Inadmissible */
+ *max_width = -1;
+ }
+
+ if (*max_width != -1) {
+ layout_handle_box_sizing(unit_len_ctx, box,
+ available_width, true, max_width);
+ }
+ }
+
+ if (min_width) {
+ enum css_min_width_e type;
+ css_fixed value = 0;
+ css_unit unit = CSS_UNIT_PX;
+
+ type = ns_computed_min_width(style, &value, &unit);
+
+ if (type == CSS_MIN_WIDTH_SET) {
+ if (unit == CSS_UNIT_PCT) {
+ *min_width = FPCT_OF_INT_TOINT(value,
+ available_width);
+ } else {
+ *min_width = FIXTOINT(css_unit_len2device_px(
+ style, unit_len_ctx,
+ value, unit));
+ }
+ } else {
+ /* Inadmissible */
+ *min_width = 0;
+ }
+
+ if (*min_width != 0) {
+ layout_handle_box_sizing(unit_len_ctx, box,
+ available_width, true, min_width);
+ }
+ }
+
+ if (max_height) {
+ enum css_max_height_e type;
+ css_fixed value = 0;
+ css_unit unit = CSS_UNIT_PX;
+
+ type = css_computed_max_height(style, &value, &unit);
+
+ if (type == CSS_MAX_HEIGHT_SET) {
+ if (unit == CSS_UNIT_PCT) {
+ /* TODO: handle percentage */
+ *max_height = -1;
+ } else {
+ *max_height = FIXTOINT(css_unit_len2device_px(
+ style, unit_len_ctx,
+ value, unit));
+ }
+ } else {
+ /* Inadmissible */
+ *max_height = -1;
+ }
+ }
+
+ if (min_height) {
+ enum css_min_height_e type;
+ css_fixed value = 0;
+ css_unit unit = CSS_UNIT_PX;
+
+ type = ns_computed_min_height(style, &value, &unit);
+
+ if (type == CSS_MIN_HEIGHT_SET) {
+ if (unit == CSS_UNIT_PCT) {
+ /* TODO: handle percentage */
+ *min_height = 0;
+ } else {
+ *min_height = FIXTOINT(css_unit_len2device_px(
+ style, unit_len_ctx,
+ value, unit));
+ }
+ } else {
+ /* Inadmissible */
+ *min_height = 0;
+ }
+ }
+
+ for (i = 0; i != 4; i++) {
+ if (margin) {
+ enum css_margin_e type = CSS_MARGIN_AUTO;
+ css_fixed value = 0;
+ css_unit unit = CSS_UNIT_PX;
+
+ type = margin_funcs[i](style, &value, &unit);
+
+ if (type == CSS_MARGIN_SET) {
+ if (unit == CSS_UNIT_PCT) {
+ margin[i] = FPCT_OF_INT_TOINT(value,
+ available_width);
+ } else {
+ margin[i] = FIXTOINT(css_unit_len2device_px(
+ style, unit_len_ctx,
+ value, unit));
+ }
+ } else {
+ margin[i] = AUTO;
+ }
+ }
+
+ if (padding) {
+ css_fixed value = 0;
+ css_unit unit = CSS_UNIT_PX;
+
+ padding_funcs[i](style, &value, &unit);
+
+ if (unit == CSS_UNIT_PCT) {
+ padding[i] = FPCT_OF_INT_TOINT(value,
+ available_width);
+ } else {
+ padding[i] = FIXTOINT(css_unit_len2device_px(
+ style, unit_len_ctx,
+ value, unit));
+ }
+ }
+
+ /* Table cell borders are populated in table.c */
+ if (border && box->type != BOX_TABLE_CELL) {
+ enum css_border_style_e bstyle = CSS_BORDER_STYLE_NONE;
+ css_color color = 0;
+ css_fixed value = 0;
+ css_unit unit = CSS_UNIT_PX;
+
+ border_width_funcs[i](style, &value, &unit);
+ bstyle = border_style_funcs[i](style);
+ border_color_funcs[i](style, &color);
+
+ border[i].style = bstyle;
+ border[i].c = color;
+
+ if (bstyle == CSS_BORDER_STYLE_HIDDEN ||
+ bstyle == CSS_BORDER_STYLE_NONE)
+ /* spec unclear: following Mozilla */
+ border[i].width = 0;
+ else
+ border[i].width = FIXTOINT(css_unit_len2device_px(
+ style, unit_len_ctx,
+ value, unit));
+
+ /* Special case for border-collapse: make all borders
+ * on table/table-row-group/table-row zero width. */
+ if (css_computed_border_collapse(style) ==
+ CSS_BORDER_COLLAPSE_COLLAPSE &&
+ (box->type == BOX_TABLE ||
+ box->type == BOX_TABLE_ROW_GROUP ||
+ box->type == BOX_TABLE_ROW))
+ border[i].width = 0;
+ }
+ }
+}
+
+#endif
diff --git a/render/html_object.c b/content/handlers/html/object.c
index 74e4bf0f3..a1f020bf7 100644
--- a/render/html_object.c
+++ b/content/handlers/html/object.c
@@ -16,7 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Processing for html content object operations.
*/
@@ -39,8 +40,12 @@
#include "desktop/scrollbar.h"
#include "desktop/gui_internal.h"
-#include "render/box.h"
-#include "render/html_internal.h"
+#include "html/html.h"
+#include "html/private.h"
+#include "html/interaction.h"
+#include "html/box.h"
+#include "html/box_inspect.h"
+#include "html/object.h"
/* break reference loop */
static void html_object_refresh(void *p);
@@ -120,10 +125,35 @@ html_object_done(struct box *box,
}
}
+
/**
- * Callback for hlcache_handle_retrieve() for objects.
+ * Callback for hlcache_handle_retrieve() for objects with no box.
*/
+static nserror
+html_object_nobox_callback(hlcache_handle *object,
+ const hlcache_event *event,
+ void *pw)
+{
+ struct content_html_object *chobject = pw;
+
+ switch (event->type) {
+ case CONTENT_MSG_ERROR:
+ hlcache_handle_release(object);
+ chobject->content = NULL;
+ break;
+
+ default:
+ break;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Callback for hlcache_handle_retrieve() for objects with a box.
+ */
static nserror
html_object_callback(hlcache_handle *object,
const hlcache_event *event,
@@ -135,11 +165,6 @@ html_object_callback(hlcache_handle *object,
struct box *box;
box = o->box;
- if (box == NULL &&
- event->type != CONTENT_MSG_ERROR &&
- event->type != CONTENT_MSG_ERRORCODE) {
- return NSERROR_OK;
- }
switch (event->type) {
case CONTENT_MSG_LOADING:
@@ -164,7 +189,7 @@ html_object_callback(hlcache_handle *object,
c->base.status == CONTENT_STATUS_DONE)
content__reformat(&c->base, false,
c->base.available_width,
- c->base.height);
+ c->base.available_height);
}
break;
@@ -178,6 +203,10 @@ html_object_callback(hlcache_handle *object,
box->flags & REPLACE_DIM) {
union content_msg_data data;
+ if (c->had_initial_layout == false) {
+ break;
+ }
+
if (!box_visible(box))
break;
@@ -187,32 +216,31 @@ html_object_callback(hlcache_handle *object,
data.redraw.y = y + box->padding[TOP];
data.redraw.width = box->width;
data.redraw.height = box->height;
- data.redraw.full_redraw = true;
content_broadcast(&c->base, CONTENT_MSG_REDRAW, &data);
}
break;
- case CONTENT_MSG_ERRORCODE:
case CONTENT_MSG_ERROR:
hlcache_handle_release(object);
o->content = NULL;
- if (box != NULL) {
- c->base.active--;
- NSLOG(netsurf, INFO, "%d fetches active",
- c->base.active);
+ c->base.active--;
+ NSLOG(netsurf, INFO, "%d fetches active", c->base.active);
+
+ html_object_failed(box, c, o->background);
- content_add_error(&c->base, "?", 0);
- html_object_failed(box, c, o->background);
- }
break;
case CONTENT_MSG_REDRAW:
if (c->base.status != CONTENT_STATUS_LOADING) {
union content_msg_data data = event->data;
+ if (c->had_initial_layout == false) {
+ break;
+ }
+
if (!box_visible(box))
break;
@@ -237,18 +265,20 @@ html_object_callback(hlcache_handle *object,
if (hunit == CSS_UNIT_PCT) {
l = (width - w) * hpos / INTTOFIX(100);
} else {
- l = FIXTOINT(nscss_len2px(&c->len_ctx,
- hpos, hunit,
- box->style));
+ l = FIXTOINT(css_unit_len2device_px(
+ box->style,
+ &c->unit_len_ctx,
+ hpos, hunit));
}
h = content_get_height(box->background);
if (vunit == CSS_UNIT_PCT) {
t = (height - h) * vpos / INTTOFIX(100);
} else {
- t = FIXTOINT(nscss_len2px(&c->len_ctx,
- vpos, vunit,
- box->style));
+ t = FIXTOINT(css_unit_len2device_px(
+ box->style,
+ &c->unit_len_ctx,
+ vpos, vunit));
}
/* Redraw area depends on background-repeat */
@@ -282,53 +312,39 @@ html_object_callback(hlcache_handle *object,
break;
}
- data.redraw.object_width = box->width;
- data.redraw.object_height = box->height;
-
/* Add offset to box */
data.redraw.x += x;
data.redraw.y += y;
- data.redraw.object_x += x;
- data.redraw.object_y += y;
-
- content_broadcast(&c->base,
- CONTENT_MSG_REDRAW, &data);
- break;
} else {
/* Non-background case */
- if (hlcache_handle_get_content(object) ==
- event->data.redraw.object) {
-
- int w = content_get_width(object);
- int h = content_get_height(object);
-
- if (w != 0) {
- data.redraw.x =
- data.redraw.x *
+ int w = content_get_width(object);
+ int h = content_get_height(object);
+
+ if (w != 0 && box->width != w) {
+ /* Not showing image at intrinsic
+ * width; need to scale the redraw
+ * request area. */
+ data.redraw.x = data.redraw.x *
box->width / w;
- data.redraw.width =
+ data.redraw.width =
data.redraw.width *
box->width / w;
- }
+ }
- if (h != 0) {
- data.redraw.y =
- data.redraw.y *
+ if (h != 0 && box->height != w) {
+ /* Not showing image at intrinsic
+ * height; need to scale the redraw
+ * request area. */
+ data.redraw.y = data.redraw.y *
box->height / h;
- data.redraw.height =
+ data.redraw.height =
data.redraw.height *
box->height / h;
- }
-
- data.redraw.object_width = box->width;
- data.redraw.object_height = box->height;
}
data.redraw.x += x + box->padding[LEFT];
data.redraw.y += y + box->padding[TOP];
- data.redraw.object_x += x + box->padding[LEFT];
- data.redraw.object_y += y + box->padding[TOP];
}
content_broadcast(&c->base, CONTENT_MSG_REDRAW, &data);
@@ -348,8 +364,16 @@ html_object_callback(hlcache_handle *object,
/* Don't care about favicons that aren't on top level content */
break;
- case CONTENT_MSG_GETCTX:
- *(event->data.jscontext) = NULL;
+ case CONTENT_MSG_GETTHREAD:
+ /* Objects don't have JS threads */
+ *(event->data.jsthread) = NULL;
+ break;
+
+ case CONTENT_MSG_GETDIMS:
+ *(event->data.getdims.viewport_width) =
+ content__get_width(&c->base);
+ *(event->data.getdims.viewport_height) =
+ content__get_height(&c->base);
break;
case CONTENT_MSG_SCROLL:
@@ -450,45 +474,45 @@ html_object_callback(hlcache_handle *object,
}
if (c->base.status == CONTENT_STATUS_READY &&
- c->base.active == 0 &&
- (event->type == CONTENT_MSG_LOADING ||
- event->type == CONTENT_MSG_DONE ||
- event->type == CONTENT_MSG_ERROR ||
- event->type == CONTENT_MSG_ERRORCODE)) {
+ c->base.active == 0 &&
+ (event->type == CONTENT_MSG_LOADING ||
+ event->type == CONTENT_MSG_DONE ||
+ event->type == CONTENT_MSG_ERROR)) {
/* all objects have arrived */
content__reformat(&c->base, false, c->base.available_width,
- c->base.height);
+ c->base.available_height);
content_set_done(&c->base);
} else if (nsoption_bool(incremental_reflow) &&
- event->type == CONTENT_MSG_DONE &&
- box != NULL &&
- !(box->flags & REPLACE_DIM) &&
- (c->base.status == CONTENT_STATUS_READY ||
- c->base.status == CONTENT_STATUS_DONE)) {
- /* 1) the configuration option to reflow pages while
- * objects are fetched is set
- * 2) an object is newly fetched & converted,
- * 3) the box's dimensions need to change due to being replaced
- * 4) the object's parent HTML is ready for reformat,
- */
- uint64_t ms_now;
- nsu_getmonotonic_ms(&ms_now);
- if (ms_now > c->base.reformat_time) {
- /* The time since the previous reformat is
- * more than the configured minimum time
- * between reformats so reformat the page to
- * display newly fetched objects
- */
- content__reformat(&c->base,
- false,
- c->base.available_width,
- c->base.height);
- }
+ event->type == CONTENT_MSG_DONE &&
+ box != NULL &&
+ !(box->flags & REPLACE_DIM) &&
+ (c->base.status == CONTENT_STATUS_READY ||
+ c->base.status == CONTENT_STATUS_DONE)) {
+ /* 1) the configuration option to reflow pages while
+ * objects are fetched is set
+ * 2) an object is newly fetched & converted,
+ * 3) the box's dimensions need to change due to being replaced
+ * 4) the object's parent HTML is ready for reformat,
+ */
+ uint64_t ms_now;
+ nsu_getmonotonic_ms(&ms_now);
+ if (ms_now > c->base.reformat_time) {
+ /* The time since the previous reformat is
+ * more than the configured minimum time
+ * between reformats so reformat the page to
+ * display newly fetched objects
+ */
+ content__reformat(&c->base,
+ false,
+ c->base.available_width,
+ c->base.available_height);
+ }
}
return NSERROR_OK;
}
+
/**
* Start a fetch for an object required by a page, replacing an existing object.
*
@@ -496,7 +520,6 @@ html_object_callback(hlcache_handle *object,
* \param url URL of object to fetch (copied)
* \return true on success, false on memory exhaustion
*/
-
static bool html_replace_object(struct content_html_object *object, nsurl *url)
{
html_content *c;
@@ -549,7 +572,6 @@ static bool html_replace_object(struct content_html_object *object, nsurl *url)
/**
* schedule callback for object refresh
*/
-
static void html_object_refresh(void *p)
{
struct content_html_object *object = p;
@@ -571,6 +593,8 @@ static void html_object_refresh(void *p)
}
}
+
+/* exported interface documented in html/object.h */
nserror html_object_open_objects(html_content *html, struct browser_window *bw)
{
struct content_html_object *object, *next;
@@ -592,6 +616,8 @@ nserror html_object_open_objects(html_content *html, struct browser_window *bw)
return NSERROR_OK;
}
+
+/* exported interface documented in html/object.h */
nserror html_object_abort_objects(html_content *htmlc)
{
struct content_html_object *object;
@@ -632,6 +658,8 @@ nserror html_object_abort_objects(html_content *htmlc)
return NSERROR_OK;
}
+
+/* exported interface documented in html/object.h */
nserror html_object_close_objects(html_content *html)
{
struct content_html_object *object, *next;
@@ -654,6 +682,8 @@ nserror html_object_close_objects(html_content *html)
return NSERROR_OK;
}
+
+/* exported interface documented in html/object.h */
nserror html_object_free_objects(html_content *html)
{
while (html->object_list != NULL) {
@@ -675,14 +705,16 @@ nserror html_object_free_objects(html_content *html)
}
-
-/* exported interface documented in render/html_internal.h */
-bool html_fetch_object(html_content *c, nsurl *url, struct box *box,
- content_type permitted_types,
- int available_width, int available_height,
- bool background)
+/* exported interface documented in html/object.h */
+bool
+html_fetch_object(html_content *c,
+ nsurl *url,
+ struct box *box,
+ content_type permitted_types,
+ bool background)
{
struct content_html_object *object;
+ hlcache_handle_callback object_callback;
hlcache_child_context child;
nserror error;
@@ -698,6 +730,12 @@ bool html_fetch_object(html_content *c, nsurl *url, struct box *box,
return false;
}
+ if (box == NULL) {
+ object_callback = html_object_nobox_callback;
+ } else {
+ object_callback = html_object_callback;
+ }
+
object->parent = (struct content *) c;
object->next = NULL;
object->content = NULL;
@@ -706,11 +744,15 @@ bool html_fetch_object(html_content *c, nsurl *url, struct box *box,
object->background = background;
error = hlcache_handle_retrieve(url,
- HLCACHE_RETRIEVE_SNIFF_TYPE,
- content_get_url(&c->base), NULL,
- html_object_callback, object, &child,
- object->permitted_types, &object->content);
- if (error != NSERROR_OK) {
+ HLCACHE_RETRIEVE_SNIFF_TYPE,
+ content_get_url(&c->base),
+ NULL,
+ object_callback,
+ object,
+ &child,
+ object->permitted_types,
+ &object->content);
+ if (error != NSERROR_OK) {
free(object);
return error != NSERROR_NOMEM;
}
diff --git a/content/handlers/html/object.h b/content/handlers/html/object.h
new file mode 100644
index 000000000..67d770c9e
--- /dev/null
+++ b/content/handlers/html/object.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * HTML content object interface
+ */
+
+#ifndef NETSURF_HTML_OBJECT_H
+#define NETSURF_HTML_OBJECT_H
+
+struct html_content;
+struct browser_window;
+struct box;
+struct nsurl;
+
+/**
+ * Start a fetch for an object required by a page.
+ *
+ * The created content object is added to the HTML content which is
+ * updated as the fetch progresses. The box (if any) is updated when
+ * the object content becomes done.
+ *
+ * \param c content of type CONTENT_HTML
+ * \param url URL of object to fetch
+ * \param box box that will contain the object or NULL if none
+ * \param permitted_types bitmap of acceptable types
+ * \param background this is a background image
+ * \return true on success, false on memory exhaustion
+ */
+bool html_fetch_object(struct html_content *c, struct nsurl *url, struct box *box, content_type permitted_types, bool background);
+
+/**
+ * release memory of content objects associated with a HTML content
+ *
+ * The content objects contents should have been previously closed
+ * with html_object_close_objects().
+ *
+ * \param html The html content to release the objects from.
+ * \return NSERROR_OK on success else appropriate error code.
+ */
+nserror html_object_free_objects(struct html_content *html);
+
+/**
+ * close content of content objects associated with a HTML content
+ *
+ * \param html The html content to close the objects from.
+ * \return NSERROR_OK on success else appropriate error code.
+ */
+nserror html_object_close_objects(struct html_content *html);
+
+
+/**
+ * open content of content objects associated with a HTML content
+ *
+ * \param html The html content to open the objects from.
+ * \param bw Browser window handle to open contents with.
+ * \return NSERROR_OK on success else appropriate error code.
+ */
+nserror html_object_open_objects(struct html_content *html, struct browser_window *bw);
+
+
+/**
+ * abort any content objects that have not completed fetching.
+ *
+ * \param html The html content to abort the objects from.
+ * \return NSERROR_OK on success else appropriate error code.
+ */
+nserror html_object_abort_objects(struct html_content *html);
+
+#endif
diff --git a/render/html_internal.h b/content/handlers/html/private.h
index 66ecb2b36..56cd957d5 100644
--- a/render/html_internal.h
+++ b/content/handlers/html/private.h
@@ -18,20 +18,23 @@
/**
* \file
- * Content for text/html (private data).
+ * Private data for text/html content.
*/
-#ifndef NETSURF_RENDER_HTML_INTERNAL_H_
-#define NETSURF_RENDER_HTML_INTERNAL_H_
+#ifndef NETSURF_HTML_PRIVATE_H
+#define NETSURF_HTML_PRIVATE_H
-#include <libcss/libcss.h>
+#include <dom/bindings/hubbub/parser.h>
-#include "content/handlers/css/utils.h"
+#include "netsurf/types.h"
#include "content/content_protected.h"
-#include "desktop/selection.h"
-#include "render/html.h"
+#include "content/handlers/css/utils.h"
+
struct gui_layout_table;
+struct scrollbar_msg_data;
+struct content_redraw_data;
+struct selection;
typedef enum {
HTML_DRAG_NONE, /** No drag */
@@ -43,12 +46,15 @@ typedef enum {
HTML_DRAG_CONTENT_SCROLL /** Not own; drag in child content */
} html_drag_type;
+/**
+ * For drags we don't own
+ */
union html_drag_owner {
bool no_owner;
struct box *content;
struct scrollbar *scrollbar;
struct box *textarea;
-}; /**< For drags we don't own */
+};
typedef enum {
HTML_SELECTION_NONE, /** No selection */
@@ -56,29 +62,40 @@ typedef enum {
HTML_SELECTION_SELF, /** Selection in this html content */
HTML_SELECTION_CONTENT /** Selection in child content */
} html_selection_type;
+
+/**
+ * For getting at selections in this content or things in this content
+ */
union html_selection_owner {
bool none;
struct box *textarea;
struct box *content;
-}; /**< For getting at selections in this content or things in this content */
+};
typedef enum {
- HTML_FOCUS_SELF, /** Focus is our own */
- HTML_FOCUS_CONTENT, /** Focus belongs to child content */
- HTML_FOCUS_TEXTAREA /** Focus belongs to textarea */
+ HTML_FOCUS_SELF, /**< Focus is our own */
+ HTML_FOCUS_CONTENT, /**< Focus belongs to child content */
+ HTML_FOCUS_TEXTAREA /**< Focus belongs to textarea */
} html_focus_type;
+
+/**
+ * For directing input
+ */
union html_focus_owner {
bool self;
struct box *textarea;
struct box *content;
-}; /**< For directing input */
+};
-/** Data specific to CONTENT_HTML. */
+/**
+ * Data specific to CONTENT_HTML.
+ */
typedef struct html_content {
struct content base;
dom_hubbub_parser *parser; /**< Parser object handle */
bool parse_completed; /**< Whether the parse has been completed */
+ bool conversion_begun; /**< Whether or not the conversion has begun */
/** Document tree */
dom_document *document;
@@ -91,13 +108,10 @@ typedef struct html_content {
dom_hubbub_encoding_source encoding_source;
/** Base URL (may be a copy of content->url). */
- nsurl *base_url;
+ struct nsurl *base_url;
/** Base target */
char *base_target;
- /** CSS length conversion context for document. */
- nscss_len_ctx len_ctx;
-
/** Content has been aborted in the LOADING state */
bool aborted;
@@ -107,14 +121,21 @@ typedef struct html_content {
/** Whether a layout (reflow) is in progress */
bool reflowing;
+ /** Whether an initial layout has been done */
+ bool had_initial_layout;
+
/** Whether scripts are enabled for this content */
bool enable_scripting;
/* Title element node */
dom_node *title;
- /** A talloc context purely for the render box tree */
+ /** A talloc context purely for the render box tree */
int *bctx;
+ /** A context pointer for the box conversion, NULL if no conversion
+ * is in progress.
+ */
+ void *box_conversion_context;
/** Box tree, or NULL. */
struct box *layout;
/** Document background colour. */
@@ -127,8 +148,8 @@ typedef struct html_content {
unsigned int scripts_count;
/** Scripts */
struct html_script *scripts;
- /** javascript context */
- struct jscontext *jscontext;
+ /** javascript thread in use */
+ struct jsthread *jsthread;
/** Number of entries in stylesheet_content. */
unsigned int stylesheet_count;
@@ -136,6 +157,10 @@ typedef struct html_content {
struct html_stylesheet *stylesheets;
/**< Style selection context */
css_select_ctx *select_ctx;
+ /**< Style selection media specification */
+ css_media media;
+ /** CSS length conversion context for document. */
+ css_unit_ctx unit_len_ctx;
/**< Universal selector */
lwc_string *universal;
@@ -157,7 +182,7 @@ typedef struct html_content {
/** Inline frame information */
struct content_html_iframe *iframe;
- /** Content of type CONTENT_HTML containing this, or NULL if not an
+ /** Content of type CONTENT_HTML containing this, or NULL if not an
* object within a page. */
struct html_content *page;
@@ -177,64 +202,32 @@ typedef struct html_content {
union html_focus_owner focus_owner;
/** HTML content's own text selection object */
- struct selection sel;
+ struct selection *sel;
- /** Open core-handled form SELECT menu,
- * or NULL if none currently open. */
+ /**
+ * Open core-handled form SELECT menu, or NULL if none
+ * currently open.
+ */
struct form_control *visible_select_menu;
- /** Context for free text search, or NULL if none */
- struct search_context *search;
- /** Search string or NULL */
- char *search_string;
-
} html_content;
-/** Render padding and margin box outlines in html_redraw(). */
-extern bool html_redraw_debug;
-
-void html__redraw_a_box(html_content *html, struct box *box);
-
/**
- * Set our drag status, and inform whatever owns the content
- *
- * \param html HTML content
- * \param drag_type Type of drag
- * \param drag_owner What owns the drag
- * \param rect Pointer movement bounds
+ * Render padding and margin box outlines in html_redraw().
*/
-void html_set_drag_type(html_content *html, html_drag_type drag_type,
- union html_drag_owner drag_owner, const struct rect *rect);
+extern bool html_redraw_debug;
-/**
- * Set our selection status, and inform whatever owns the content
- *
- * \param html HTML content
- * \param selection_type Type of selection
- * \param selection_owner What owns the selection
- * \param read_only True iff selection is read only
- */
-void html_set_selection(html_content *html, html_selection_type selection_type,
- union html_selection_owner selection_owner, bool read_only);
+
+/* in html/html.c */
/**
- * Set our input focus, and inform whatever owns the content
+ * redraw a box
*
- * \param html HTML content
- * \param focus_type Type of input focus
- * \param focus_owner What owns the focus
- * \param hide_caret True iff caret to be hidden
- * \param x Carret x-coord rel to owner
- * \param y Carret y-coord rel to owner
- * \param height Carret height
- * \param clip Carret clip rect
+ * \param htmlc HTML content
+ * \param box The box to redraw.
*/
-void html_set_focus(html_content *html, html_focus_type focus_type,
- union html_focus_owner focus_owner, bool hide_caret,
- int x, int y, int height, const struct rect *clip);
-
+void html__redraw_a_box(html_content *htmlc, struct box *box);
-struct browser_window *html_get_browser_window(struct content *c);
/**
* Complete conversion of an HTML document
@@ -243,6 +236,7 @@ struct browser_window *html_get_browser_window(struct content *c);
*/
void html_finish_conversion(html_content *htmlc);
+
/**
* Test if an HTML content conversion can begin
*
@@ -251,6 +245,7 @@ void html_finish_conversion(html_content *htmlc);
*/
bool html_can_begin_conversion(html_content *htmlc);
+
/**
* Begin conversion of an HTML document
*
@@ -258,35 +253,13 @@ bool html_can_begin_conversion(html_content *htmlc);
*/
bool html_begin_conversion(html_content *htmlc);
-/* in render/html_redraw.c */
-bool html_redraw(struct content *c, struct content_redraw_data *data,
- const struct rect *clip, const struct redraw_context *ctx);
-/* in render/html_redraw_border.c */
-bool html_redraw_borders(struct box *box, int x_parent, int y_parent,
- int p_width, int p_height, const struct rect *clip, float scale,
- const struct redraw_context *ctx);
-
-bool html_redraw_inline_borders(struct box *box, struct rect b,
- const struct rect *clip, float scale, bool first, bool last,
- const struct redraw_context *ctx);
-
-/* in render/html_interaction.c */
-void html_mouse_track(struct content *c, struct browser_window *bw,
- browser_mouse_state mouse, int x, int y);
-void html_mouse_action(struct content *c, struct browser_window *bw,
- browser_mouse_state mouse, int x, int y);
-bool html_keypress(struct content *c, uint32_t key);
-void html_overflow_scroll_callback(void *client_data,
- struct scrollbar_msg_data *scrollbar_data);
-void html_search(struct content *c, void *context,
- search_flags_t flags, const char *string);
-void html_search_clear(struct content *c);
+/**
+ * execute some text as a script element
+ */
+bool html_exec(struct content *c, const char *src, size_t srclen);
-/* in render/html_script.c */
-dom_hubbub_error html_process_script(void *ctx, dom_node *node);
-
/**
* Attempt script execution for defer and async scripts
*
@@ -294,9 +267,11 @@ dom_hubbub_error html_process_script(void *ctx, dom_node *node);
* http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#the-script-element
*
* \param htmlc html content.
+ * \param allow_defer allow deferred execution, if not, only async scripts.
* \return NSERROR_OK error code.
*/
-nserror html_script_exec(html_content *htmlc);
+nserror html_script_exec(html_content *htmlc, bool allow_defer);
+
/**
* Free all script resources and references for a html content.
@@ -306,82 +281,70 @@ nserror html_script_exec(html_content *htmlc);
*/
nserror html_script_free(html_content *htmlc);
+
/**
- * Ensure the html content javascript context is invalidated.
- *
- * \param htmlc html content.
- * \return NSERROR_OK or error code.
+ * Check if any of the scripts loaded were insecure
*/
-nserror html_script_invalidate_ctx(html_content *htmlc);
+bool html_saw_insecure_scripts(html_content *htmlc);
-/* in render/html_forms.c */
-struct form *html_forms_get_forms(const char *docenc, dom_html_document *doc);
-struct form_control *html_forms_get_control_for_node(struct form *forms,
- dom_node *node);
-
-/* in render/html_css.c */
-nserror html_css_init(void);
-void html_css_fini(void);
/**
- * Initialise core stylesheets for a content
- *
- * \param c content structure to update
- * \return nserror
+ * Complete the HTML content state machine *iff* all scripts are finished
*/
-nserror html_css_new_stylesheets(html_content *c);
-nserror html_css_quirks_stylesheets(html_content *c);
-nserror html_css_free_stylesheets(html_content *html);
+nserror html_proceed_to_done(html_content *html);
+
+
+/* in html/redraw.c */
+bool html_redraw(struct content *c, struct content_redraw_data *data,
+ const struct rect *clip, const struct redraw_context *ctx);
+
+
+/* in html/redraw_border.c */
+bool html_redraw_borders(struct box *box, int x_parent, int y_parent,
+ int p_width, int p_height, const struct rect *clip, float scale,
+ const struct redraw_context *ctx);
+
-bool html_css_process_link(html_content *htmlc, dom_node *node);
-bool html_css_process_style(html_content *htmlc, dom_node *node);
-bool html_css_update_style(html_content *c, dom_node *style);
+bool html_redraw_inline_borders(struct box *box, struct rect b,
+ const struct rect *clip, float scale, bool first, bool last,
+ const struct redraw_context *ctx);
+
+
+/* in html/script.c */
+dom_hubbub_error html_process_script(void *ctx, dom_node *node);
+
+
+/* in html/forms.c */
+struct form *html_forms_get_forms(const char *docenc, dom_html_document *doc);
+struct form_control *html_forms_get_control_for_node(struct form *forms,
+ dom_node *node);
-nserror html_css_new_selection_context(html_content *c,
- css_select_ctx **ret_select_ctx);
-/* in render/html_css_fetcher.c */
+/* in html/css_fetcher.c */
/**
* Register the fetcher for the pseudo x-ns-css scheme.
*
* \return NSERROR_OK on successful registration or error code on failure.
*/
nserror html_css_fetcher_register(void);
-nserror html_css_fetcher_add_item(dom_string *data, nsurl *base_url,
+nserror html_css_fetcher_add_item(dom_string *data, struct nsurl *base_url,
uint32_t *key);
-/* in render/html_object.c */
-
-/**
- * Start a fetch for an object required by a page.
- *
- * \param c content of type CONTENT_HTML
- * \param url URL of object to fetch (copied)
- * \param box box that will contain the object
- * \param permitted_types bitmap of acceptable types
- * \param available_width estimate of width of object
- * \param available_height estimate of height of object
- * \param background this is a background image
- * \return true on success, false on memory exhaustion
- */
-bool html_fetch_object(html_content *c, nsurl *url, struct box *box,
- content_type permitted_types,
- int available_width, int available_height,
- bool background);
-
-nserror html_object_free_objects(html_content *html);
-nserror html_object_close_objects(html_content *html);
-nserror html_object_open_objects(html_content *html, struct browser_window *bw);
-nserror html_object_abort_objects(html_content *html);
/* Events */
/**
* Construct an event and fire it at the DOM
*
*/
-bool fire_dom_event(dom_string *type, dom_node *target,
+bool fire_generic_dom_event(dom_string *type, dom_node *target,
bool bubbles, bool cancelable);
+/**
+ * Construct a keyboard event and fire it at the DOM
+ */
+bool fire_dom_keyboard_event(dom_string *type, dom_node *target,
+ bool bubbles, bool cancelable, uint32_t key);
+
/* Useful dom_string pointers */
struct dom_string;
@@ -406,5 +369,3 @@ extern struct dom_string *html_dom_string_type;
extern struct dom_string *html_dom_string_src;
#endif
-
-
diff --git a/render/html_redraw.c b/content/handlers/html/redraw.c
index 9a97e5ec5..f770699bb 100644
--- a/render/html_redraw.c
+++ b/content/handlers/html/redraw.c
@@ -5,7 +5,7 @@
* Copyright 2005-2006 Adrian Lees <adrianl@users.sourceforge.net>
* Copyright 2006 Rob Kendrick <rjek@netsurf-browser.org>
* Copyright 2008 Michael Drake <tlsa@netsurf-browser.org>
- * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
+ * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -40,12 +40,15 @@
#include "utils/messages.h"
#include "utils/utils.h"
#include "utils/nsoption.h"
+#include "utils/corestrings.h"
#include "netsurf/content.h"
#include "netsurf/browser_window.h"
#include "netsurf/plotters.h"
#include "netsurf/bitmap.h"
#include "netsurf/layout.h"
+#include "content/content.h"
#include "content/content_protected.h"
+#include "content/textsearch.h"
#include "css/utils.h"
#include "desktop/selection.h"
#include "desktop/print.h"
@@ -53,12 +56,13 @@
#include "desktop/textarea.h"
#include "desktop/gui_internal.h"
-#include "render/box.h"
-#include "render/font.h"
-#include "render/form_internal.h"
-#include "render/html_internal.h"
-#include "render/layout.h"
-#include "render/search.h"
+#include "html/box.h"
+#include "html/box_inspect.h"
+#include "html/box_manipulate.h"
+#include "html/font.h"
+#include "html/form_internal.h"
+#include "html/private.h"
+#include "html/layout.h"
bool html_redraw_debug = false;
@@ -150,7 +154,7 @@ static struct box *html_redraw_find_bg_box(struct box *box)
* \return true iff successful and redraw should proceed
*/
-bool
+static bool
text_redraw(const char *utf8_text,
size_t utf8_len,
size_t offset,
@@ -164,7 +168,6 @@ text_redraw(const char *utf8_text,
bool excluded,
struct content *c,
const struct selection *sel,
- struct search_context *search,
const struct redraw_context *ctx)
{
bool highlighted = false;
@@ -181,18 +184,22 @@ text_redraw(const char *utf8_text,
unsigned end_idx;
/* first try the browser window's current selection */
- if (selection_defined(sel) && selection_highlighted(sel,
- offset, offset + len,
- &start_idx, &end_idx)) {
+ if (selection_highlighted(sel,
+ offset,
+ offset + len,
+ &start_idx,
+ &end_idx)) {
highlighted = true;
}
/* what about the current search operation, if any? */
- if (!highlighted && (search != NULL) &&
- search_term_highlighted(c,
- offset, offset + len,
- &start_idx, &end_idx,
- search)) {
+ if (!highlighted &&
+ (c->textsearch.context != NULL) &&
+ content_textsearch_ishighlighted(c->textsearch.context,
+ offset,
+ offset + len,
+ &start_idx,
+ &end_idx)) {
highlighted = true;
}
@@ -401,7 +408,7 @@ static bool html_redraw_checkbox(int x, int y, int width, int height,
return false;
}
- /* light line across bottom */
+ /* light line across bottom */
rect.x0 = x;
rect.y0 = y + height;
res = ctx->plot->line(ctx, plot_style_stroke_lightwbasec, &rect);
@@ -521,14 +528,14 @@ static bool html_redraw_radio(int x, int y, int width, int height,
* \param box box of input
* \param scale scale for redraw
* \param background_colour current background colour
- * \param len_ctx Length conversion context
+ * \param unit_len_ctx Length conversion context
* \param ctx current redraw context
* \return true if successful, false otherwise
*/
static bool html_redraw_file(int x, int y, int width, int height,
struct box *box, float scale, colour background_colour,
- const nscss_len_ctx *len_ctx,
+ const css_unit_ctx *unit_len_ctx,
const struct redraw_context *ctx)
{
int text_width;
@@ -537,7 +544,7 @@ static bool html_redraw_file(int x, int y, int width, int height,
plot_font_style_t fstyle;
nserror res;
- font_plot_style_from_css(len_ctx, box->style, &fstyle);
+ font_plot_style_from_css(unit_len_ctx, box->style, &fstyle);
fstyle.background = background_colour;
if (box->gadget->value) {
@@ -580,7 +587,7 @@ static bool html_redraw_file(int x, int y, int width, int height,
* \param clip current clip rectangle
* \param background_colour current background colour
* \param background box containing background details (usually \a box)
- * \param len_ctx Length conversion context
+ * \param unit_len_ctx Length conversion context
* \param ctx current redraw context
* \return true if successful, false otherwise
*/
@@ -588,7 +595,7 @@ static bool html_redraw_file(int x, int y, int width, int height,
static bool html_redraw_background(int x, int y, struct box *box, float scale,
const struct rect *clip, colour *background_colour,
struct box *background,
- const nscss_len_ctx *len_ctx,
+ const css_unit_ctx *unit_len_ctx,
const struct redraw_context *ctx)
{
bool repeat_x = false;
@@ -661,21 +668,23 @@ static bool html_redraw_background(int x, int y, struct box *box, float scale,
css_computed_background_position(background->style,
&hpos, &hunit, &vpos, &vunit);
if (hunit == CSS_UNIT_PCT) {
- x += (width -
+ x += (width -
content_get_width(background->background)) *
scale * FIXTOFLT(hpos) / 100.;
} else {
- x += (int) (FIXTOFLT(nscss_len2px(len_ctx, hpos, hunit,
- background->style)) * scale);
+ x += (int) (FIXTOFLT(css_unit_len2device_px(
+ background->style, unit_len_ctx,
+ hpos, hunit)) * scale);
}
if (vunit == CSS_UNIT_PCT) {
- y += (height -
+ y += (height -
content_get_height(background->background)) *
scale * FIXTOFLT(vpos) / 100.;
} else {
- y += (int) (FIXTOFLT(nscss_len2px(len_ctx, vpos, vunit,
- background->style)) * scale);
+ y += (int) (FIXTOFLT(css_unit_len2device_px(
+ background->style, unit_len_ctx,
+ vpos, vunit)) * scale);
}
}
@@ -724,10 +733,10 @@ static bool html_redraw_background(int x, int y, struct box *box, float scale,
/* if the background content is opaque there
* is no need to plot underneath it.
*/
- if ((r.x0 >= r.x1) ||
+ if ((r.x0 >= r.x1) ||
(r.y0 >= r.y1) ||
(nscss_color_is_transparent(bgcol) == false) ||
- ((clip_box->background != NULL) &&
+ ((clip_box->background != NULL) &&
content_get_opaque(clip_box->background)))
continue;
}
@@ -807,7 +816,7 @@ static bool html_redraw_background(int x, int y, struct box *box, float scale,
* \param first true if this is the first rectangle associated with the inline
* \param last true if this is the last rectangle associated with the inline
* \param background_colour updated to current background colour if plotted
- * \param len_ctx Length conversion context
+ * \param unit_len_ctx Length conversion context
* \param ctx current redraw context
* \return true if successful, false otherwise
*/
@@ -815,7 +824,7 @@ static bool html_redraw_background(int x, int y, struct box *box, float scale,
static bool html_redraw_inline_background(int x, int y, struct box *box,
float scale, const struct rect *clip, struct rect b,
bool first, bool last, colour *background_colour,
- const nscss_len_ctx *len_ctx,
+ const css_unit_ctx *unit_len_ctx,
const struct redraw_context *ctx)
{
struct rect r = *clip;
@@ -843,7 +852,7 @@ static bool html_redraw_inline_background(int x, int y, struct box *box,
case CSS_BACKGROUND_REPEAT_REPEAT:
repeat_x = repeat_y = true;
/* optimisation: only plot the colour if
- * bitmap is not opaque
+ * bitmap is not opaque
*/
plot_colour = !content_get_opaque(box->background);
break;
@@ -868,16 +877,17 @@ static bool html_redraw_inline_background(int x, int y, struct box *box,
&hpos, &hunit, &vpos, &vunit);
if (hunit == CSS_UNIT_PCT) {
x += (b.x1 - b.x0 -
- content_get_width(box->background) *
+ content_get_width(box->background) *
scale) * FIXTOFLT(hpos) / 100.;
- if (!repeat_x && ((hpos < 2 && !first) ||
+ if (!repeat_x && ((hpos < 2 && !first) ||
(hpos > 98 && !last))){
plot_content = false;
}
} else {
- x += (int) (FIXTOFLT(nscss_len2px(len_ctx, hpos, hunit,
- box->style)) * scale);
+ x += (int) (FIXTOFLT(css_unit_len2device_px(
+ box->style, unit_len_ctx,
+ hpos, hunit)) * scale);
}
if (vunit == CSS_UNIT_PCT) {
@@ -885,8 +895,9 @@ static bool html_redraw_inline_background(int x, int y, struct box *box,
content_get_height(box->background) *
scale) * FIXTOFLT(vpos) / 100.;
} else {
- y += (int) (FIXTOFLT(nscss_len2px(len_ctx, vpos, vunit,
- box->style)) * scale);
+ y += (int) (FIXTOFLT(css_unit_len2device_px(
+ box->style, unit_len_ctx,
+ vpos, vunit)) * scale);
}
}
@@ -1082,7 +1093,7 @@ static bool html_redraw_text_decoration(struct box *box,
if (!box->inline_end)
return true;
for (i = 0; i != NOF_ELEMENTS(decoration); i++)
- if (css_computed_text_decoration(box->style) &
+ if (css_computed_text_decoration(box->style) &
decoration[i])
if (!html_redraw_text_decoration_inline(box,
x_parent, y_parent, scale,
@@ -1090,7 +1101,7 @@ static bool html_redraw_text_decoration(struct box *box,
return false;
} else {
for (i = 0; i != NOF_ELEMENTS(decoration); i++)
- if (css_computed_text_decoration(box->style) &
+ if (css_computed_text_decoration(box->style) &
decoration[i])
if (!html_redraw_text_decoration_block(box,
x_parent + box->x,
@@ -1127,14 +1138,22 @@ static bool html_redraw_text_box(const html_content *html, struct box *box,
bool excluded = (box->object != NULL);
plot_font_style_t fstyle;
- font_plot_style_from_css(&html->len_ctx, box->style, &fstyle);
+ font_plot_style_from_css(&html->unit_len_ctx, box->style, &fstyle);
fstyle.background = current_background_color;
- if (!text_redraw(box->text, box->length, box->byte_offset,
- box->space, &fstyle, x, y,
- clip, box->height, scale, excluded,
- (struct content *)html, &html->sel,
- html->search, ctx))
+ if (!text_redraw(box->text,
+ box->length,
+ box->byte_offset,
+ box->space,
+ &fstyle,
+ x, y,
+ clip,
+ box->height,
+ scale,
+ excluded,
+ (struct content *)html,
+ html->sel,
+ ctx))
return false;
return true;
@@ -1224,10 +1243,12 @@ bool html_redraw_box(const html_content *html, struct box *box,
struct rect rect;
int x_scrolled, y_scrolled;
struct box *bg_box = NULL;
- bool has_x_scroll, has_y_scroll;
css_computed_clip_rect css_rect;
enum css_overflow_e overflow_x = CSS_OVERFLOW_VISIBLE;
enum css_overflow_e overflow_y = CSS_OVERFLOW_VISIBLE;
+ dom_exception exc;
+ dom_html_element_type tag_type;
+
if (html_redraw_printing && (box->flags & PRINTED))
return true;
@@ -1365,7 +1386,7 @@ bool html_redraw_box(const html_content *html, struct box *box,
}
/* if visibility is hidden render children only */
- if (box->style && css_computed_visibility(box->style) ==
+ if (box->style && css_computed_visibility(box->style) ==
CSS_VISIBILITY_HIDDEN) {
if ((ctx->plot->group_start) &&
(ctx->plot->group_start(ctx, "hidden box") != NSERROR_OK))
@@ -1388,28 +1409,24 @@ bool html_redraw_box(const html_content *html, struct box *box,
CSS_CLIP_RECT) {
/* We have an absolutly positioned box with a clip rect */
if (css_rect.left_auto == false)
- r.x0 = x - border_left + FIXTOINT(nscss_len2px(
- &html->len_ctx,
- css_rect.left, css_rect.lunit,
- box->style));
+ r.x0 = x - border_left + FIXTOINT(css_unit_len2device_px(
+ box->style, &html->unit_len_ctx,
+ css_rect.left, css_rect.lunit));
if (css_rect.top_auto == false)
- r.y0 = y - border_top + FIXTOINT(nscss_len2px(
- &html->len_ctx,
- css_rect.top, css_rect.tunit,
- box->style));
+ r.y0 = y - border_top + FIXTOINT(css_unit_len2device_px(
+ box->style, &html->unit_len_ctx,
+ css_rect.top, css_rect.tunit));
if (css_rect.right_auto == false)
- r.x1 = x - border_left + FIXTOINT(nscss_len2px(
- &html->len_ctx,
- css_rect.right, css_rect.runit,
- box->style));
+ r.x1 = x - border_left + FIXTOINT(css_unit_len2device_px(
+ box->style, &html->unit_len_ctx,
+ css_rect.right, css_rect.runit));
if (css_rect.bottom_auto == false)
- r.y1 = y - border_top + FIXTOINT(nscss_len2px(
- &html->len_ctx,
- css_rect.bottom, css_rect.bunit,
- box->style));
+ r.y1 = y - border_top + FIXTOINT(css_unit_len2device_px(
+ box->style, &html->unit_len_ctx,
+ css_rect.bottom, css_rect.bunit));
/* find intersection of clip rectangle and box */
if (r.x0 < clip->x0) r.x0 = clip->x0;
@@ -1498,7 +1515,7 @@ bool html_redraw_box(const html_content *html, struct box *box,
/* plot background */
if (!html_redraw_background(x, y, box, scale, &p,
&current_background_color, bg_box,
- &html->len_ctx, ctx))
+ &html->unit_len_ctx, ctx))
return false;
/* restore previous graphics window */
if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
@@ -1578,7 +1595,7 @@ bool html_redraw_box(const html_content *html, struct box *box,
x, y, box, scale, &p, b,
first, false,
&current_background_color,
- &html->len_ctx, ctx))
+ &html->unit_len_ctx, ctx))
return false;
/* restore previous graphics window */
if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
@@ -1611,7 +1628,7 @@ bool html_redraw_box(const html_content *html, struct box *box,
* the inline */
if (!html_redraw_inline_background(x, ib_y, box, scale, &p, b,
first, true, &current_background_color,
- &html->len_ctx, ctx))
+ &html->unit_len_ctx, ctx))
return false;
/* restore previous graphics window */
if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
@@ -1729,6 +1746,15 @@ bool html_redraw_box(const html_content *html, struct box *box,
return false;
}
+ if (box->node != NULL) {
+ exc = dom_html_element_get_tag_type(box->node, &tag_type);
+ if (exc != DOM_NO_ERR) {
+ tag_type = DOM_HTML_ELEMENT_TYPE__UNKNOWN;
+ }
+ } else {
+ tag_type = DOM_HTML_ELEMENT_TYPE__UNKNOWN;
+ }
+
if (box->object && width != 0 && height != 0) {
struct content_redraw_data obj_data;
@@ -1782,12 +1808,27 @@ bool html_redraw_box(const html_content *html, struct box *box,
obj, sizeof(obj) - 1) != NSERROR_OK)
return false;
}
-
+ } else if (tag_type == DOM_HTML_ELEMENT_TYPE_CANVAS &&
+ box->node != NULL &&
+ box->flags & REPLACE_DIM) {
+ /* Canvas to draw */
+ struct bitmap *bitmap = NULL;
+ exc = dom_node_get_user_data(box->node,
+ corestring_dom___ns_key_canvas_node_data,
+ &bitmap);
+ if (exc != DOM_NO_ERR) {
+ bitmap = NULL;
+ }
+ if (bitmap != NULL &&
+ ctx->plot->bitmap(ctx, bitmap, x + padding_left, y + padding_top,
+ width, height, current_background_color,
+ BITMAPF_NONE) != NSERROR_OK)
+ return false;
} else if (box->iframe) {
/* Offset is passed to browser window redraw unscaled */
browser_window_redraw(box->iframe,
- (x + padding_left) / scale,
- (y + padding_top) / scale, &r, ctx);
+ x + padding_left,
+ y + padding_top, &r, ctx);
} else if (box->gadget && box->gadget->type == GADGET_CHECKBOX) {
if (!html_redraw_checkbox(x + padding_left, y + padding_top,
@@ -1802,7 +1843,7 @@ bool html_redraw_box(const html_content *html, struct box *box,
} else if (box->gadget && box->gadget->type == GADGET_FILE) {
if (!html_redraw_file(x + padding_left, y + padding_top,
width, height, box, scale,
- current_background_color, &html->len_ctx, ctx))
+ current_background_color, &html->unit_len_ctx, ctx))
return false;
} else if (box->gadget &&
@@ -1841,25 +1882,34 @@ bool html_redraw_box(const html_content *html, struct box *box,
/* scrollbars */
if (((box->style && box->type != BOX_BR &&
- box->type != BOX_TABLE && box->type != BOX_INLINE &&
- (overflow_x == CSS_OVERFLOW_SCROLL ||
- overflow_x == CSS_OVERFLOW_AUTO ||
- overflow_y == CSS_OVERFLOW_SCROLL ||
- overflow_y == CSS_OVERFLOW_AUTO)) ||
- (box->object && content_get_type(box->object) ==
- CONTENT_HTML)) && box->parent != NULL) {
-
- has_x_scroll = box_hscrollbar_present(box);
- has_y_scroll = box_vscrollbar_present(box);
-
- if (!box_handle_scrollbars((struct content *)html,
- box, has_x_scroll, has_y_scroll))
+ box->type != BOX_TABLE && box->type != BOX_INLINE &&
+ (box->gadget == NULL || box->gadget->type != GADGET_TEXTAREA) &&
+ (overflow_x == CSS_OVERFLOW_SCROLL ||
+ overflow_x == CSS_OVERFLOW_AUTO ||
+ overflow_y == CSS_OVERFLOW_SCROLL ||
+ overflow_y == CSS_OVERFLOW_AUTO)) ||
+ (box->object && content_get_type(box->object) ==
+ CONTENT_HTML)) && box->parent != NULL) {
+ nserror res;
+ bool has_x_scroll = (overflow_x == CSS_OVERFLOW_SCROLL);
+ bool has_y_scroll = (overflow_y == CSS_OVERFLOW_SCROLL);
+
+ has_x_scroll |= (overflow_x == CSS_OVERFLOW_AUTO) &&
+ box_hscrollbar_present(box);
+ has_y_scroll |= (overflow_y == CSS_OVERFLOW_AUTO) &&
+ box_vscrollbar_present(box);
+
+ res = box_handle_scrollbars((struct content *)html,
+ box, has_x_scroll, has_y_scroll);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "%s", messages_get_errorcode(res));
return false;
-
+ }
+
if (box->scroll_x != NULL)
scrollbar_redraw(box->scroll_x,
x_parent + box->x,
- y_parent + box->y + box->padding[TOP] +
+ y_parent + box->y + box->padding[TOP] +
box->height + box->padding[BOTTOM] -
SCROLLBAR_WIDTH, clip, scale, ctx);
if (box->scroll_y != NULL)
@@ -1919,16 +1969,16 @@ bool html_redraw(struct content *c, struct content_redraw_data *data,
select_only = form_clip_inside_select_menu(control,
data->scale, clip);
}
-
+
if (!select_only) {
/* clear to background colour */
result = (ctx->plot->clip(ctx, clip) == NSERROR_OK);
-
+
if (html->background_colour != NS_TRANSPARENT)
pstyle_fill_bg.fill_colour = html->background_colour;
result &= (ctx->plot->rectangle(ctx, &pstyle_fill_bg, clip) == NSERROR_OK);
-
+
result &= html_redraw_box(html, box, data->x, data->y, clip,
data->scale, pstyle_fill_bg.fill_colour, ctx);
}
@@ -1937,7 +1987,7 @@ bool html_redraw(struct content *c, struct content_redraw_data *data,
int menu_x, menu_y;
box = html->visible_select_menu->box;
box_coords(box, &menu_x, &menu_y);
-
+
menu_x -= box->border[LEFT].width;
menu_y += box->height + box->border[BOTTOM].width +
box->padding[BOTTOM] + box->padding[TOP];
diff --git a/render/html_redraw_border.c b/content/handlers/html/redraw_border.c
index 07c503c41..3a1f6f308 100644
--- a/render/html_redraw_border.c
+++ b/content/handlers/html/redraw_border.c
@@ -25,12 +25,13 @@
#include <stdbool.h>
#include <stdlib.h>
+#include "utils/utils.h"
#include "utils/log.h"
#include "netsurf/plotters.h"
#include "netsurf/css.h"
-#include "render/box.h"
-#include "render/html_internal.h"
+#include "html/box.h"
+#include "html/private.h"
static plot_style_t plot_style_bdr = {
@@ -111,7 +112,7 @@ html_redraw_border_plot(const int side,
plot_style_bdr.stroke_type = PLOT_OP_TYPE_DASH;
plot_style_bdr.stroke_colour = c;
- plot_style_bdr.stroke_width = thickness;
+ plot_style_bdr.stroke_width = (thickness << PLOT_STYLE_RADIX);
plot_style_fillbdr.fill_colour = c;
plot_style_fillbdr_dark.fill_colour = darken_colour(c);
plot_style_fillbdr_light.fill_colour = lighten_colour(c);
@@ -121,7 +122,7 @@ html_redraw_border_plot(const int side,
switch (style) {
case CSS_BORDER_STYLE_DOTTED:
plot_style_bdr.stroke_type = PLOT_OP_TYPE_DOT;
- /* fall through */
+ fallthrough;
case CSS_BORDER_STYLE_DASHED:
rect.x0 = (p[0] + p[2]) / 2;
rect.y0 = (p[1] + p[3]) / 2;
@@ -131,7 +132,7 @@ html_redraw_border_plot(const int side,
break;
case CSS_BORDER_STYLE_SOLID:
- /* fall through to default */
+ /* solid is the default */
default:
if (rectangular || thickness == 1) {
@@ -190,7 +191,7 @@ html_redraw_border_plot(const int side,
case CSS_BORDER_STYLE_GROOVE:
light = 3 - light;
- /* fall through */
+ fallthrough;
case CSS_BORDER_STYLE_RIDGE:
/* choose correct colours for each part of the border line */
if (light <= 1) {
@@ -300,7 +301,7 @@ html_redraw_border_plot(const int side,
case CSS_BORDER_STYLE_INSET:
light = (light + 2) % 4;
- /* fall through */
+ fallthrough;
case CSS_BORDER_STYLE_OUTSET:
/* choose correct colours for each part of the border line */
switch (light) {
diff --git a/render/html_script.c b/content/handlers/html/script.c
index c73a4806d..554fc4f70 100644
--- a/render/html_script.c
+++ b/content/handlers/html/script.c
@@ -16,8 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Content for text/html scripts (implementation).
+/**
+ * \file
+ * implementation of content handling for text/html scripts.
*/
#include <assert.h>
@@ -35,12 +36,14 @@
#include "netsurf/content.h"
#include "javascript/js.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
#include "content/fetch.h"
#include "content/hlcache.h"
-#include "render/html_internal.h"
+#include "html/html.h"
+#include "html/private.h"
-typedef bool (script_handler_t)(struct jscontext *jscontext, const char *data, size_t size) ;
+typedef bool (script_handler_t)(struct jsthread *jsthread, const uint8_t *data, size_t size, const char *name);
static script_handler_t *select_script_handler(content_type ctype)
@@ -52,14 +55,15 @@ static script_handler_t *select_script_handler(content_type ctype)
}
-/* exported internal interface documented in render/html_internal.h */
-nserror html_script_exec(html_content *c)
+/* exported internal interface documented in html/html_internal.h */
+nserror html_script_exec(html_content *c, bool allow_defer)
{
unsigned int i;
struct html_script *s;
script_handler_t *script_handler;
+ bool have_run_something = false;
- if (c->jscontext == NULL) {
+ if (c->jsthread == NULL) {
return NSERROR_BAD_PARAMETER;
}
@@ -69,7 +73,7 @@ nserror html_script_exec(html_content *c)
}
if ((s->type == HTML_SCRIPT_ASYNC) ||
- (s->type == HTML_SCRIPT_DEFER)) {
+ (allow_defer && (s->type == HTML_SCRIPT_DEFER))) {
/* ensure script content is present */
if (s->data.handle == NULL)
continue;
@@ -88,11 +92,18 @@ nserror html_script_exec(html_content *c)
if (content_get_status(s->data.handle) ==
CONTENT_STATUS_DONE) {
/* external script is now available */
- const char *data;
- unsigned long size;
+ const uint8_t *data;
+ size_t size;
data = content_get_source_data(
s->data.handle, &size );
- script_handler(c->jscontext, data, size);
+ script_handler(c->jsthread, data, size,
+ nsurl_access(hlcache_handle_get_url(s->data.handle)));
+ have_run_something = true;
+ /* We have to re-acquire this here since the
+ * c->scripts array may have been reallocated
+ * as a result of executing this script.
+ */
+ s = &(c->scripts[i]);
s->already_started = true;
@@ -100,6 +111,10 @@ nserror html_script_exec(html_content *c)
}
}
+ if (have_run_something) {
+ return html_proceed_to_done(c);
+ }
+
return NSERROR_OK;
}
@@ -175,15 +190,12 @@ convert_script_async_cb(hlcache_handle *script,
case CONTENT_MSG_ERROR:
NSLOG(netsurf, INFO, "script %s failed: %s",
nsurl_access(hlcache_handle_get_url(script)),
- event->data.error);
- /* fall through */
+ event->data.errordata.errormsg);
- case CONTENT_MSG_ERRORCODE:
hlcache_handle_release(script);
s->data.handle = NULL;
parent->base.active--;
NSLOG(netsurf, INFO, "%d fetches active", parent->base.active);
- content_add_error(&parent->base, "?", 0);
break;
@@ -198,6 +210,13 @@ convert_script_async_cb(hlcache_handle *script,
html_begin_conversion(parent);
}
+ /* if we have already started converting though, then we can handle the
+ * scripts as they come in.
+ */
+ else if (parent->conversion_begun) {
+ return html_script_exec(parent, false);
+ }
+
return NSERROR_OK;
}
@@ -234,15 +253,12 @@ convert_script_defer_cb(hlcache_handle *script,
case CONTENT_MSG_ERROR:
NSLOG(netsurf, INFO, "script %s failed: %s",
nsurl_access(hlcache_handle_get_url(script)),
- event->data.error);
- /* fall through */
+ event->data.errordata.errormsg);
- case CONTENT_MSG_ERRORCODE:
hlcache_handle_release(script);
s->data.handle = NULL;
parent->base.active--;
NSLOG(netsurf, INFO, "%d fetches active", parent->base.active);
- content_add_error(&parent->base, "?", 0);
break;
@@ -273,6 +289,15 @@ convert_script_sync_cb(hlcache_handle *script,
struct html_script *s;
script_handler_t *script_handler;
dom_hubbub_error err;
+ unsigned int active_sync_scripts = 0;
+
+ /* Count sync scripts which have yet to complete (other than us) */
+ for (i = 0, s = parent->scripts; i != parent->scripts_count; i++, s++) {
+ if (s->type == HTML_SCRIPT_SYNC &&
+ s->data.handle != script && s->already_started == false) {
+ active_sync_scripts++;
+ }
+ }
/* Find script */
for (i = 0, s = parent->scripts; i != parent->scripts_count; i++, s++) {
@@ -293,18 +318,21 @@ convert_script_sync_cb(hlcache_handle *script,
/* attempt to execute script */
script_handler = select_script_handler(content_get_type(s->data.handle));
- if (script_handler != NULL && parent->jscontext != NULL) {
+ if (script_handler != NULL && parent->jsthread != NULL) {
/* script has a handler */
- const char *data;
- unsigned long size;
+ const uint8_t *data;
+ size_t size;
data = content_get_source_data(s->data.handle, &size );
- script_handler(parent->jscontext, data, size);
+ script_handler(parent->jsthread, data, size,
+ nsurl_access(hlcache_handle_get_url(s->data.handle)));
}
/* continue parse */
- err = dom_hubbub_parser_pause(parent->parser, false);
- if (err != DOM_HUBBUB_OK) {
- NSLOG(netsurf, INFO, "unpause returned 0x%x", err);
+ if (parent->parser != NULL && active_sync_scripts == 0) {
+ err = dom_hubbub_parser_pause(parent->parser, false);
+ if (err != DOM_HUBBUB_OK) {
+ NSLOG(netsurf, INFO, "unpause returned 0x%x", err);
+ }
}
break;
@@ -312,23 +340,22 @@ convert_script_sync_cb(hlcache_handle *script,
case CONTENT_MSG_ERROR:
NSLOG(netsurf, INFO, "script %s failed: %s",
nsurl_access(hlcache_handle_get_url(script)),
- event->data.error);
- /* fall through */
+ event->data.errordata.errormsg);
- case CONTENT_MSG_ERRORCODE:
hlcache_handle_release(script);
s->data.handle = NULL;
parent->base.active--;
NSLOG(netsurf, INFO, "%d fetches active", parent->base.active);
- content_add_error(&parent->base, "?", 0);
s->already_started = true;
/* continue parse */
- err = dom_hubbub_parser_pause(parent->parser, false);
- if (err != DOM_HUBBUB_OK) {
- NSLOG(netsurf, INFO, "unpause returned 0x%x", err);
+ if (parent->parser != NULL && active_sync_scripts == 0) {
+ err = dom_hubbub_parser_pause(parent->parser, false);
+ if (err != DOM_HUBBUB_OK) {
+ NSLOG(netsurf, INFO, "unpause returned 0x%x", err);
+ }
}
break;
@@ -370,7 +397,7 @@ exec_src_script(html_content *c,
/* src url */
ns_error = nsurl_join(c->base_url, dom_string_data(src), &joined);
if (ns_error != NSERROR_OK) {
- content_broadcast_errorcode(&c->base, NSERROR_NOMEM);
+ content_broadcast_error(&c->base, NSERROR_NOMEM, NULL);
return DOM_HUBBUB_NOMEM;
}
@@ -400,6 +427,12 @@ exec_src_script(html_content *c,
return DOM_HUBBUB_OK; /* dom error */
}
+ if (c->parse_completed) {
+ /* After parse completed, all scripts are essentially async */
+ async = true;
+ defer = false;
+ }
+
if (async) {
/* asyncronous script */
script_type = HTML_SCRIPT_ASYNC;
@@ -426,7 +459,7 @@ exec_src_script(html_content *c,
nscript = html_process_new_script(c, mimetype, script_type);
if (nscript == NULL) {
nsurl_unref(joined);
- content_broadcast_errorcode(&c->base, NSERROR_NOMEM);
+ content_broadcast_error(&c->base, NSERROR_NOMEM, NULL);
return DOM_HUBBUB_NOMEM;
}
@@ -462,6 +495,7 @@ exec_src_script(html_content *c,
switch (script_type) {
case HTML_SCRIPT_SYNC:
ret = DOM_HUBBUB_HUBBUB_ERR | HUBBUB_PAUSED;
+ break;
case HTML_SCRIPT_ASYNC:
break;
@@ -496,7 +530,7 @@ exec_inline_script(html_content *c, dom_node *node, dom_string *mimetype)
if (nscript == NULL) {
dom_string_unref(script);
- content_broadcast_errorcode(&c->base, NSERROR_NOMEM);
+ content_broadcast_error(&c->base, NSERROR_NOMEM, NULL);
return DOM_HUBBUB_NOMEM;
}
@@ -505,14 +539,19 @@ exec_inline_script(html_content *c, dom_node *node, dom_string *mimetype)
nscript->already_started = true;
/* ensure script handler for content type */
- dom_string_intern(mimetype, &lwcmimetype);
+ exc = dom_string_intern(mimetype, &lwcmimetype);
+ if (exc != DOM_NO_ERR) {
+ return DOM_HUBBUB_DOM;
+ }
+
script_handler = select_script_handler(content_factory_type_from_mime_type(lwcmimetype));
lwc_string_unref(lwcmimetype);
if (script_handler != NULL) {
- script_handler(c->jscontext,
- dom_string_data(script),
- dom_string_byte_length(script));
+ script_handler(c->jsthread,
+ (const uint8_t *)dom_string_data(script),
+ dom_string_byte_length(script),
+ "?inline script?");
}
return DOM_HUBBUB_OK;
}
@@ -535,13 +574,13 @@ html_process_script(void *ctx, dom_node *node)
/* We should only ever be here if scripting was enabled for this
* content so it's correct to make a javascript context if there
* isn't one already. */
- if (c->jscontext == NULL) {
+ if (c->jsthread == NULL) {
union content_msg_data msg_data;
- msg_data.jscontext = &c->jscontext;
- content_broadcast(&c->base, CONTENT_MSG_GETCTX, &msg_data);
- NSLOG(netsurf, INFO, "javascript context %p ", c->jscontext);
- if (c->jscontext == NULL) {
+ msg_data.jsthread = &c->jsthread;
+ content_broadcast(&c->base, CONTENT_MSG_GETTHREAD, &msg_data);
+ NSLOG(netsurf, INFO, "javascript context %p ", c->jsthread);
+ if (c->jsthread == NULL) {
/* no context and it could not be created, abort */
return DOM_HUBBUB_OK;
}
@@ -568,7 +607,32 @@ html_process_script(void *ctx, dom_node *node)
return err;
}
-/* exported internal interface documented in render/html_internal.h */
+/* exported internal interface documented in html/html_internal.h */
+bool html_saw_insecure_scripts(html_content *htmlc)
+{
+ struct html_script *s;
+ unsigned int i;
+
+ for (i = 0, s = htmlc->scripts; i != htmlc->scripts_count; i++, s++) {
+ if (s->type == HTML_SCRIPT_INLINE) {
+ /* Inline scripts are no less secure than their
+ * containing HTML content
+ */
+ continue;
+ }
+ if (s->data.handle == NULL) {
+ /* We've not begun loading this? */
+ continue;
+ }
+ if (content_saw_insecure_objects(s->data.handle)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* exported internal interface documented in html/html_internal.h */
nserror html_script_free(html_content *html)
{
unsigned int i;
@@ -578,26 +642,24 @@ nserror html_script_free(html_content *html)
dom_string_unref(html->scripts[i].mimetype);
}
- if ((html->scripts[i].type == HTML_SCRIPT_INLINE) &&
- (html->scripts[i].data.string != NULL)) {
-
- dom_string_unref(html->scripts[i].data.string);
-
- } else if ((html->scripts[i].type == HTML_SCRIPT_SYNC) &&
- (html->scripts[i].data.handle != NULL)) {
-
- hlcache_handle_release(html->scripts[i].data.handle);
-
+ switch (html->scripts[i].type) {
+ case HTML_SCRIPT_INLINE:
+ if (html->scripts[i].data.string != NULL) {
+ dom_string_unref(html->scripts[i].data.string);
+ }
+ break;
+ case HTML_SCRIPT_SYNC:
+ /* fallthrough */
+ case HTML_SCRIPT_ASYNC:
+ /* fallthrough */
+ case HTML_SCRIPT_DEFER:
+ if (html->scripts[i].data.handle != NULL) {
+ hlcache_handle_release(html->scripts[i].data.handle);
+ }
+ break;
}
}
free(html->scripts);
return NSERROR_OK;
}
-
-/* exported internal interface documented in render/html_internal.h */
-nserror html_script_invalidate_ctx(html_content *htmlc)
-{
- htmlc->jscontext = NULL;
- return NSERROR_OK;
-}
diff --git a/render/table.c b/content/handlers/html/table.c
index 08a2e805c..f8762e862 100644
--- a/render/table.c
+++ b/content/handlers/html/table.c
@@ -17,19 +17,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Table processing and layout (implementation).
+/**
+ * \file
+ * implementation of HTML table processing and layout.
*/
#include <assert.h>
#include <dom/dom.h>
#include "utils/log.h"
+#include "utils/utils.h"
#include "utils/talloc.h"
#include "css/utils.h"
-#include "render/box.h"
-#include "render/table.h"
+#include "html/box.h"
+#include "html/table.h"
/* Define to enable verbose table debug */
#undef TABLE_DEBUG
@@ -45,316 +47,344 @@ struct border {
css_unit unit; /**< border-width units */
};
-static void table_used_left_border_for_cell(
- const nscss_len_ctx *len_ctx,
- struct box *cell);
-static void table_used_top_border_for_cell(
- const nscss_len_ctx *len_ctx,
- struct box *cell);
-static void table_used_right_border_for_cell(
- const nscss_len_ctx *len_ctx,
- struct box *cell);
-static void table_used_bottom_border_for_cell(
- const nscss_len_ctx *len_ctx,
- struct box *cell);
-static bool table_border_is_more_eyecatching(
- const nscss_len_ctx *len_ctx,
- const struct border *a,
- box_type a_src,
- const struct border *b,
- box_type b_src);
-static void table_cell_top_process_table(
- const nscss_len_ctx *len_ctx,
- struct box *table,
- struct border *a,
- box_type *a_src);
-static bool table_cell_top_process_group(
- const nscss_len_ctx *len_ctx,
- struct box *cell,
- struct box *group,
- struct border *a,
- box_type *a_src);
-static bool table_cell_top_process_row(
- const nscss_len_ctx *len_ctx,
- struct box *cell,
- struct box *row,
- struct border *a,
- box_type *a_src);
-
/**
- * Determine the column width types for a table.
- *
- * \param len_ctx Length conversion context
- * \param table box of type BOX_TABLE
- * \return true on success, false on memory exhaustion
+ * Determine if a border style is more eyecatching than another
*
- * The table->col array is allocated and type and width are filled in for each
- * column.
+ * \param unit_len_ctx Length conversion context
+ * \param a Reference border style
+ * \param a_src Source of \a a
+ * \param b Candidate border style
+ * \param b_src Source of \a b
+ * \return True if \a b is more eyecatching than \a a
*/
-
-bool table_calculate_column_types(
- const nscss_len_ctx *len_ctx,
- struct box *table)
+static bool
+table_border_is_more_eyecatching(const css_unit_ctx *unit_len_ctx,
+ const struct border *a,
+ box_type a_src,
+ const struct border *b,
+ box_type b_src)
{
- unsigned int i, j;
- struct column *col;
- struct box *row_group, *row, *cell;
+ css_fixed awidth, bwidth;
+ int impact = 0;
- if (table->col)
- /* table->col already constructed, for example frameset table */
+ /* See CSS 2.1 $17.6.2.1 */
+
+ /* 1 + 2 -- hidden beats everything, none beats nothing */
+ if (a->style == CSS_BORDER_STYLE_HIDDEN ||
+ b->style == CSS_BORDER_STYLE_NONE)
+ return false;
+
+ if (b->style == CSS_BORDER_STYLE_HIDDEN ||
+ a->style == CSS_BORDER_STYLE_NONE)
return true;
- table->col = col = talloc_array(table, struct column, table->columns);
- if (!col)
+ /* 3a -- wider borders beat narrow ones */
+ /* The widths must be absolute, which will be the case
+ * if they've come from a computed style. */
+ assert(a->unit != CSS_UNIT_EM && a->unit != CSS_UNIT_EX);
+ assert(b->unit != CSS_UNIT_EM && b->unit != CSS_UNIT_EX);
+ awidth = css_unit_len2device_px(NULL, unit_len_ctx, a->width, a->unit);
+ bwidth = css_unit_len2device_px(NULL, unit_len_ctx, b->width, b->unit);
+
+ if (awidth < bwidth)
+ return true;
+ else if (bwidth < awidth)
return false;
- for (i = 0; i != table->columns; i++) {
- col[i].type = COLUMN_WIDTH_UNKNOWN;
- col[i].width = 0;
- col[i].positioned = true;
+ /* 3b -- sort by style */
+ switch (a->style) {
+ case CSS_BORDER_STYLE_DOUBLE: impact++; fallthrough;
+ case CSS_BORDER_STYLE_SOLID: impact++; fallthrough;
+ case CSS_BORDER_STYLE_DASHED: impact++; fallthrough;
+ case CSS_BORDER_STYLE_DOTTED: impact++; fallthrough;
+ case CSS_BORDER_STYLE_RIDGE: impact++; fallthrough;
+ case CSS_BORDER_STYLE_OUTSET: impact++; fallthrough;
+ case CSS_BORDER_STYLE_GROOVE: impact++; fallthrough;
+ case CSS_BORDER_STYLE_INSET: impact++; fallthrough;
+ default:
+ break;
}
- /* 1st pass: cells with colspan 1 only */
- for (row_group = table->children; row_group; row_group =row_group->next)
- for (row = row_group->children; row; row = row->next)
- for (cell = row->children; cell; cell = cell->next) {
- enum css_width_e type;
- css_fixed value = 0;
- css_unit unit = CSS_UNIT_PX;
+ switch (b->style) {
+ case CSS_BORDER_STYLE_DOUBLE: impact--; fallthrough;
+ case CSS_BORDER_STYLE_SOLID: impact--; fallthrough;
+ case CSS_BORDER_STYLE_DASHED: impact--; fallthrough;
+ case CSS_BORDER_STYLE_DOTTED: impact--; fallthrough;
+ case CSS_BORDER_STYLE_RIDGE: impact--; fallthrough;
+ case CSS_BORDER_STYLE_OUTSET: impact--; fallthrough;
+ case CSS_BORDER_STYLE_GROOVE: impact--; fallthrough;
+ case CSS_BORDER_STYLE_INSET: impact--; fallthrough;
+ default:
+ break;
+ }
- assert(cell->type == BOX_TABLE_CELL);
- assert(cell->style);
+ if (impact < 0)
+ return true;
+ else if (impact > 0)
+ return false;
- if (cell->columns != 1)
- continue;
- i = cell->start_column;
+ /* 4a -- sort by origin */
+ impact = 0;
- if (css_computed_position(cell->style) !=
- CSS_POSITION_ABSOLUTE &&
- css_computed_position(cell->style) !=
- CSS_POSITION_FIXED) {
- col[i].positioned = false;
- }
+ /** \todo COL/COL_GROUP */
+ switch (a_src) {
+ case BOX_TABLE_CELL: impact++; fallthrough;
+ case BOX_TABLE_ROW: impact++; fallthrough;
+ case BOX_TABLE_ROW_GROUP: impact++; fallthrough;
+ case BOX_TABLE: impact++; fallthrough;
+ default:
+ break;
+ }
- type = css_computed_width(cell->style, &value, &unit);
-
- /* fixed width takes priority over any other width type */
- if (col[i].type != COLUMN_WIDTH_FIXED &&
- type == CSS_WIDTH_SET && unit != CSS_UNIT_PCT) {
- col[i].type = COLUMN_WIDTH_FIXED;
- col[i].width = FIXTOINT(nscss_len2px(len_ctx,
- value, unit, cell->style));
- if (col[i].width < 0)
- col[i].width = 0;
- continue;
- }
+ /** \todo COL/COL_GROUP */
+ switch (b_src) {
+ case BOX_TABLE_CELL: impact--; fallthrough;
+ case BOX_TABLE_ROW: impact--; fallthrough;
+ case BOX_TABLE_ROW_GROUP: impact--; fallthrough;
+ case BOX_TABLE: impact--; fallthrough;
+ default:
+ break;
+ }
- if (col[i].type != COLUMN_WIDTH_UNKNOWN)
- continue;
+ if (impact < 0)
+ return true;
+ else if (impact > 0)
+ return false;
- if (type == CSS_WIDTH_SET && unit == CSS_UNIT_PCT) {
- col[i].type = COLUMN_WIDTH_PERCENT;
- col[i].width = FIXTOINT(value);
- if (col[i].width < 0)
- col[i].width = 0;
- } else if (type == CSS_WIDTH_AUTO) {
- col[i].type = COLUMN_WIDTH_AUTO;
- }
+ /* 4b -- furthest left (if direction: ltr) and towards top wins */
+ /** \todo Currently assumes b satisifies this */
+ return true;
+}
+
+
+/**
+ * Process a table
+ *
+ * \param unit_len_ctx Length conversion context
+ * \param table Table to process
+ * \param a Current border style for cell
+ * \param a_src Source of \a a
+ *
+ * \post \a a will be updated with most eyecatching style
+ * \post \a a_src will be updated also
+ */
+static void
+table_cell_top_process_table(const css_unit_ctx *unit_len_ctx,
+ struct box *table,
+ struct border *a,
+ box_type *a_src)
+{
+ struct border b;
+ box_type b_src;
+
+ /* Top border of table */
+ b.style = css_computed_border_top_style(table->style);
+ b.color = css_computed_border_top_color(table->style, &b.c);
+ css_computed_border_top_width(table->style, &b.width, &b.unit);
+ b.width = css_unit_len2device_px(table->style, unit_len_ctx,
+ b.width, b.unit);
+ b.unit = CSS_UNIT_PX;
+ b_src = BOX_TABLE;
+
+ if (table_border_is_more_eyecatching(unit_len_ctx, a, *a_src, &b, b_src)) {
+ *a = b;
+ *a_src = b_src;
}
+}
- /* 2nd pass: cells which span multiple columns */
- for (row_group = table->children; row_group; row_group =row_group->next)
- for (row = row_group->children; row; row = row->next)
- for (cell = row->children; cell; cell = cell->next) {
- unsigned int fixed_columns = 0, percent_columns = 0,
- auto_columns = 0, unknown_columns = 0;
- int fixed_width = 0, percent_width = 0;
- enum css_width_e type;
- css_fixed value = 0;
- css_unit unit = CSS_UNIT_PX;
- if (cell->columns == 1)
- continue;
- i = cell->start_column;
+/**
+ * Process a row
+ *
+ * \param unit_len_ctx Length conversion context
+ * \param cell Cell being considered
+ * \param row Row to process
+ * \param a Current border style for cell
+ * \param a_src Source of \a a
+ * \return true if row has cells, false otherwise
+ *
+ * \post \a a will be updated with most eyecatching style
+ * \post \a a_src will be updated also
+ */
+static bool
+table_cell_top_process_row(const css_unit_ctx *unit_len_ctx,
+ struct box *cell,
+ struct box *row,
+ struct border *a,
+ box_type *a_src)
+{
+ struct border b;
+ box_type b_src;
- for (j = i; j < i + cell->columns; j++) {
- col[j].positioned = false;
- }
-
- /* count column types in spanned cells */
- for (j = 0; j != cell->columns; j++) {
- if (col[i + j].type == COLUMN_WIDTH_FIXED) {
- fixed_width += col[i + j].width;
- fixed_columns++;
- } else if (col[i + j].type == COLUMN_WIDTH_PERCENT) {
- percent_width += col[i + j].width;
- percent_columns++;
- } else if (col[i + j].type == COLUMN_WIDTH_AUTO) {
- auto_columns++;
- } else {
- unknown_columns++;
- }
+ /* Bottom border of row */
+ b.style = css_computed_border_bottom_style(row->style);
+ b.color = css_computed_border_bottom_color(row->style, &b.c);
+ css_computed_border_bottom_width(row->style, &b.width, &b.unit);
+ b.width = css_unit_len2device_px(row->style, unit_len_ctx,
+ b.width, b.unit);
+ b.unit = CSS_UNIT_PX;
+ b_src = BOX_TABLE_ROW;
+
+ if (table_border_is_more_eyecatching(unit_len_ctx, a, *a_src, &b, b_src)) {
+ *a = b;
+ *a_src = b_src;
+ }
+
+ if (row->children == NULL) {
+ /* Row is empty, so consider its top border */
+ b.style = css_computed_border_top_style(row->style);
+ b.color = css_computed_border_top_color(row->style, &b.c);
+ css_computed_border_top_width(row->style, &b.width, &b.unit);
+ b.width = css_unit_len2device_px(row->style, unit_len_ctx,
+ b.width, b.unit);
+ b.unit = CSS_UNIT_PX;
+ b_src = BOX_TABLE_ROW;
+
+ if (table_border_is_more_eyecatching(unit_len_ctx,
+ a, *a_src, &b, b_src)) {
+ *a = b;
+ *a_src = b_src;
}
- if (!unknown_columns)
- continue;
-
- type = css_computed_width(cell->style, &value, &unit);
-
- /* if cell is fixed width, and all spanned columns are fixed
- * or unknown width, split extra width among unknown columns */
- if (type == CSS_WIDTH_SET && unit != CSS_UNIT_PCT &&
- fixed_columns + unknown_columns ==
- cell->columns) {
- int width = (FIXTOFLT(nscss_len2px(len_ctx, value, unit,
- cell->style)) - fixed_width) /
- unknown_columns;
- if (width < 0)
- width = 0;
- for (j = 0; j != cell->columns; j++) {
- if (col[i + j].type == COLUMN_WIDTH_UNKNOWN) {
- col[i + j].type = COLUMN_WIDTH_FIXED;
- col[i + j].width = width;
+ return false;
+ } else {
+ /* Process cells that are directly above the cell being
+ * considered. They may not be in this row, but in one of the
+ * rows above it in the case where rowspan > 1. */
+ struct box *c;
+ bool processed = false;
+
+ while (processed == false) {
+ for (c = row->children; c != NULL; c = c->next) {
+ /* Ignore cells to the left */
+ if (c->start_column + c->columns - 1 <
+ cell->start_column)
+ continue;
+ /* Ignore cells to the right */
+ if (c->start_column > cell->start_column +
+ cell->columns - 1)
+ continue;
+
+ /* Flag that we've processed a cell */
+ processed = true;
+
+ /* Consider bottom border */
+ b.style = css_computed_border_bottom_style(
+ c->style);
+ b.color = css_computed_border_bottom_color(
+ c->style, &b.c);
+ css_computed_border_bottom_width(c->style,
+ &b.width, &b.unit);
+ b.width = css_unit_len2device_px(
+ c->style, unit_len_ctx,
+ b.width, b.unit);
+ b.unit = CSS_UNIT_PX;
+ b_src = BOX_TABLE_CELL;
+
+ if (table_border_is_more_eyecatching(unit_len_ctx,
+ a,
+ *a_src,
+ &b,
+ b_src)) {
+ *a = b;
+ *a_src = b_src;
}
}
- }
- /* as above for percentage width */
- if (type == CSS_WIDTH_SET && unit == CSS_UNIT_PCT &&
- percent_columns + unknown_columns ==
- cell->columns) {
- int width = (FIXTOFLT(value) -
- percent_width) / unknown_columns;
- if (width < 0)
- width = 0;
- for (j = 0; j != cell->columns; j++) {
- if (col[i + j].type == COLUMN_WIDTH_UNKNOWN) {
- col[i + j].type = COLUMN_WIDTH_PERCENT;
- col[i + j].width = width;
- }
+ if (processed == false) {
+ /* There must be a preceding row */
+ assert(row->prev != NULL);
+
+ row = row->prev;
}
}
}
- /* use AUTO if no width type was specified */
- for (i = 0; i != table->columns; i++) {
- if (col[i].type == COLUMN_WIDTH_UNKNOWN)
- col[i].type = COLUMN_WIDTH_AUTO;
- }
-
-#ifdef TABLE_DEBUG
- for (i = 0; i != table->columns; i++)
- NSLOG(netsurf, INFO,
- "table %p, column %u: type %s, width %i", table, i, ((const char *[]){
- "UNKNOWN",
- "FIXED",
- "AUTO",
- "PERCENT",
- "RELATIVE",
- })[col[i].type], col[i].width);
-#endif
-
return true;
}
+
/**
- * Calculate used values of border-{trbl}-{style,color,width} for table cells.
+ * Process a group
*
- * \param len_ctx Length conversion context
- * \param cell Table cell to consider
+ * \param unit_len_ctx Length conversion context
+ * \param cell Cell being considered
+ * \param group Group to process
+ * \param a Current border style for cell
+ * \param a_src Source of \a a
+ * \return true if group has non-empty rows, false otherwise
*
- * \post \a cell's border array is populated
+ * \post \a a will be updated with most eyecatching style
+ * \post \a a_src will be updated also
*/
-void table_used_border_for_cell(
- const nscss_len_ctx *len_ctx,
- struct box *cell)
+static bool
+table_cell_top_process_group(const css_unit_ctx *unit_len_ctx,
+ struct box *cell,
+ struct box *group,
+ struct border *a,
+ box_type *a_src)
{
- int side;
-
- assert(cell->type == BOX_TABLE_CELL);
-
- if (css_computed_border_collapse(cell->style) ==
- CSS_BORDER_COLLAPSE_SEPARATE) {
- css_fixed width = 0;
- css_unit unit = CSS_UNIT_PX;
+ struct border b;
+ box_type b_src;
- /* Left border */
- cell->border[LEFT].style =
- css_computed_border_left_style(cell->style);
- css_computed_border_left_color(cell->style,
- &cell->border[LEFT].c);
- css_computed_border_left_width(cell->style, &width, &unit);
- cell->border[LEFT].width =
- FIXTOINT(nscss_len2px(len_ctx,
- width, unit, cell->style));
+ /* Bottom border of group */
+ b.style = css_computed_border_bottom_style(group->style);
+ b.color = css_computed_border_bottom_color(group->style, &b.c);
+ css_computed_border_bottom_width(group->style, &b.width, &b.unit);
+ b.width = css_unit_len2device_px(group->style, unit_len_ctx,
+ b.width, b.unit);
+ b.unit = CSS_UNIT_PX;
+ b_src = BOX_TABLE_ROW_GROUP;
- /* Top border */
- cell->border[TOP].style =
- css_computed_border_top_style(cell->style);
- css_computed_border_top_color(cell->style,
- &cell->border[TOP].c);
- css_computed_border_top_width(cell->style, &width, &unit);
- cell->border[TOP].width =
- FIXTOINT(nscss_len2px(len_ctx,
- width, unit, cell->style));
+ if (table_border_is_more_eyecatching(unit_len_ctx, a, *a_src, &b, b_src)) {
+ *a = b;
+ *a_src = b_src;
+ }
- /* Right border */
- cell->border[RIGHT].style =
- css_computed_border_right_style(cell->style);
- css_computed_border_right_color(cell->style,
- &cell->border[RIGHT].c);
- css_computed_border_right_width(cell->style, &width, &unit);
- cell->border[RIGHT].width =
- FIXTOINT(nscss_len2px(len_ctx,
- width, unit, cell->style));
+ if (group->last != NULL) {
+ /* Process rows in group, starting with last */
+ struct box *row = group->last;
- /* Bottom border */
- cell->border[BOTTOM].style =
- css_computed_border_bottom_style(cell->style);
- css_computed_border_bottom_color(cell->style,
- &cell->border[BOTTOM].c);
- css_computed_border_bottom_width(cell->style, &width, &unit);
- cell->border[BOTTOM].width =
- FIXTOINT(nscss_len2px(len_ctx,
- width, unit, cell->style));
+ while (table_cell_top_process_row(unit_len_ctx, cell, row,
+ a, a_src) == false) {
+ if (row->prev == NULL) {
+ return false;
+ } else {
+ row = row->prev;
+ }
+ }
} else {
- /* Left border */
- table_used_left_border_for_cell(len_ctx, cell);
-
- /* Top border */
- table_used_top_border_for_cell(len_ctx, cell);
+ /* Group is empty, so consider its top border */
+ b.style = css_computed_border_top_style(group->style);
+ b.color = css_computed_border_top_color(group->style, &b.c);
+ css_computed_border_top_width(group->style, &b.width, &b.unit);
+ b.width = css_unit_len2device_px(group->style, unit_len_ctx,
+ b.width, b.unit);
+ b.unit = CSS_UNIT_PX;
+ b_src = BOX_TABLE_ROW_GROUP;
- /* Right border */
- table_used_right_border_for_cell(len_ctx, cell);
+ if (table_border_is_more_eyecatching(unit_len_ctx,
+ a, *a_src, &b, b_src)) {
+ *a = b;
+ *a_src = b_src;
+ }
- /* Bottom border */
- table_used_bottom_border_for_cell(len_ctx, cell);
+ return false;
}
- /* Finally, ensure that any borders configured as
- * hidden or none have zero width. (c.f. layout_find_dimensions) */
- for (side = 0; side != 4; side++) {
- if (cell->border[side].style == CSS_BORDER_STYLE_HIDDEN ||
- cell->border[side].style ==
- CSS_BORDER_STYLE_NONE)
- cell->border[side].width = 0;
- }
+ return true;
}
-/******************************************************************************
- * Helpers for used border calculations *
- ******************************************************************************/
/**
* Calculate used values of border-left-{style,color,width}
*
- * \param len_ctx Length conversion context
+ * \param unit_len_ctx Length conversion context
* \param cell Table cell to consider
*/
-void table_used_left_border_for_cell(
- const nscss_len_ctx *len_ctx,
- struct box *cell)
+static void
+table_used_left_border_for_cell(const css_unit_ctx *unit_len_ctx, struct box *cell)
{
struct border a, b;
box_type a_src, b_src;
@@ -365,7 +395,8 @@ void table_used_left_border_for_cell(
a.style = css_computed_border_left_style(cell->style);
a.color = css_computed_border_left_color(cell->style, &a.c);
css_computed_border_left_width(cell->style, &a.width, &a.unit);
- a.width = nscss_len2px(len_ctx, a.width, a.unit, cell->style);
+ a.width = css_unit_len2device_px(cell->style, unit_len_ctx,
+ a.width, a.unit);
a.unit = CSS_UNIT_PX;
a_src = BOX_TABLE_CELL;
@@ -378,11 +409,11 @@ void table_used_left_border_for_cell(
/* Spanned from a previous row in current row group */
for (row = cell->parent; row != NULL; row = row->prev) {
- for (prev = row->children; prev != NULL;
- prev = prev->next) {
- if (prev->start_column +
- prev->columns ==
- cell->start_column)
+ for (prev = row->children; prev != NULL;
+ prev = prev->next) {
+ if (prev->start_column +
+ prev->columns ==
+ cell->start_column)
break;
}
@@ -398,12 +429,13 @@ void table_used_left_border_for_cell(
b.style = css_computed_border_right_style(prev->style);
b.color = css_computed_border_right_color(prev->style, &b.c);
css_computed_border_right_width(prev->style, &b.width, &b.unit);
- b.width = nscss_len2px(len_ctx, b.width, b.unit, prev->style);
+ b.width = css_unit_len2device_px(prev->style, unit_len_ctx,
+ b.width, b.unit);
b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_CELL;
- if (table_border_is_more_eyecatching(len_ctx,
- &a, a_src, &b, b_src)) {
+ if (table_border_is_more_eyecatching(unit_len_ctx,
+ &a, a_src, &b, b_src)) {
a = b;
a_src = b_src;
}
@@ -418,16 +450,17 @@ void table_used_left_border_for_cell(
/* Spanned rows -- consider their left border */
b.style = css_computed_border_left_style(row->style);
b.color = css_computed_border_left_color(
- row->style, &b.c);
+ row->style, &b.c);
css_computed_border_left_width(
- row->style, &b.width, &b.unit);
- b.width = nscss_len2px(len_ctx,
- b.width, b.unit, row->style);
+ row->style, &b.width, &b.unit);
+ b.width = css_unit_len2device_px(
+ row->style, unit_len_ctx,
+ b.width, b.unit);
b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW;
- if (table_border_is_more_eyecatching(len_ctx,
- &a, a_src, &b, b_src)) {
+ if (table_border_is_more_eyecatching(unit_len_ctx,
+ &a, a_src, &b, b_src)) {
a = b;
a_src = b_src;
}
@@ -441,12 +474,13 @@ void table_used_left_border_for_cell(
b.style = css_computed_border_left_style(group->style);
b.color = css_computed_border_left_color(group->style, &b.c);
css_computed_border_left_width(group->style, &b.width, &b.unit);
- b.width = nscss_len2px(len_ctx, b.width, b.unit, group->style);
+ b.width = css_unit_len2device_px(group->style, unit_len_ctx,
+ b.width, b.unit);
b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW_GROUP;
-
- if (table_border_is_more_eyecatching(len_ctx,
- &a, a_src, &b, b_src)) {
+
+ if (table_border_is_more_eyecatching(unit_len_ctx,
+ &a, a_src, &b, b_src)) {
a = b;
a_src = b_src;
}
@@ -455,12 +489,13 @@ void table_used_left_border_for_cell(
b.style = css_computed_border_left_style(table->style);
b.color = css_computed_border_left_color(table->style, &b.c);
css_computed_border_left_width(table->style, &b.width, &b.unit);
- b.width = nscss_len2px(len_ctx, b.width, b.unit, table->style);
+ b.width = css_unit_len2device_px(table->style, unit_len_ctx,
+ b.width, b.unit);
b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE;
-
- if (table_border_is_more_eyecatching(len_ctx,
- &a, a_src, &b, b_src)) {
+
+ if (table_border_is_more_eyecatching(unit_len_ctx,
+ &a, a_src, &b, b_src)) {
a = b;
a_src = b_src;
}
@@ -469,19 +504,19 @@ void table_used_left_border_for_cell(
/* a now contains the used left border for the cell */
cell->border[LEFT].style = a.style;
cell->border[LEFT].c = a.c;
- cell->border[LEFT].width = FIXTOINT(nscss_len2px(len_ctx,
- a.width, a.unit, cell->style));
+ cell->border[LEFT].width = FIXTOINT(css_unit_len2device_px(
+ cell->style, unit_len_ctx, a.width, a.unit));
}
+
/**
* Calculate used values of border-top-{style,color,width}
*
- * \param len_ctx Length conversion context
+ * \param unit_len_ctx Length conversion context
* \param cell Table cell to consider
*/
-void table_used_top_border_for_cell(
- const nscss_len_ctx *len_ctx,
- struct box *cell)
+static void
+table_used_top_border_for_cell(const css_unit_ctx *unit_len_ctx, struct box *cell)
{
struct border a, b;
box_type a_src, b_src;
@@ -492,7 +527,8 @@ void table_used_top_border_for_cell(
a.style = css_computed_border_top_style(cell->style);
css_computed_border_top_color(cell->style, &a.c);
css_computed_border_top_width(cell->style, &a.width, &a.unit);
- a.width = nscss_len2px(len_ctx, a.width, a.unit, cell->style);
+ a.width = css_unit_len2device_px(cell->style, unit_len_ctx,
+ a.width, a.unit);
a.unit = CSS_UNIT_PX;
a_src = BOX_TABLE_CELL;
@@ -500,19 +536,20 @@ void table_used_top_border_for_cell(
b.style = css_computed_border_top_style(row->style);
css_computed_border_top_color(row->style, &b.c);
css_computed_border_top_width(row->style, &b.width, &b.unit);
- b.width = nscss_len2px(len_ctx, b.width, b.unit, row->style);
+ b.width = css_unit_len2device_px(row->style, unit_len_ctx,
+ b.width, b.unit);
b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW;
- if (table_border_is_more_eyecatching(len_ctx, &a, a_src, &b, b_src)) {
+ if (table_border_is_more_eyecatching(unit_len_ctx, &a, a_src, &b, b_src)) {
a = b;
a_src = b_src;
}
if (row->prev != NULL) {
/* Consider row(s) above */
- while (table_cell_top_process_row(len_ctx, cell, row->prev,
- &a, &a_src) == false) {
+ while (table_cell_top_process_row(unit_len_ctx, cell, row->prev,
+ &a, &a_src) == false) {
if (row->prev->prev == NULL) {
/* Consider row group */
process_group = true;
@@ -532,30 +569,31 @@ void table_used_top_border_for_cell(
b.style = css_computed_border_top_style(group->style);
b.color = css_computed_border_top_color(group->style, &b.c);
css_computed_border_top_width(group->style, &b.width, &b.unit);
- b.width = nscss_len2px(len_ctx, b.width, b.unit, group->style);
+ b.width = css_unit_len2device_px(group->style, unit_len_ctx,
+ b.width, b.unit);
b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW_GROUP;
- if (table_border_is_more_eyecatching(len_ctx,
- &a, a_src, &b, b_src)) {
+ if (table_border_is_more_eyecatching(unit_len_ctx,
+ &a, a_src, &b, b_src)) {
a = b;
a_src = b_src;
}
if (group->prev == NULL) {
/* Top border of table */
- table_cell_top_process_table(len_ctx,
- group->parent, &a, &a_src);
+ table_cell_top_process_table(unit_len_ctx,
+ group->parent, &a, &a_src);
} else {
/* Process previous group(s) */
- while (table_cell_top_process_group(len_ctx,
- cell, group->prev,
- &a, &a_src) == false) {
+ while (table_cell_top_process_group(unit_len_ctx,
+ cell, group->prev,
+ &a, &a_src) == false) {
if (group->prev->prev == NULL) {
/* Top border of table */
- table_cell_top_process_table(len_ctx,
- group->parent,
- &a, &a_src);
+ table_cell_top_process_table(unit_len_ctx,
+ group->parent,
+ &a, &a_src);
break;
} else {
group = group->prev;
@@ -567,19 +605,18 @@ void table_used_top_border_for_cell(
/* a now contains the used top border for the cell */
cell->border[TOP].style = a.style;
cell->border[TOP].c = a.c;
- cell->border[TOP].width = FIXTOINT(nscss_len2px(len_ctx,
- a.width, a.unit, cell->style));
+ cell->border[TOP].width = FIXTOINT(css_unit_len2device_px(
+ cell->style, unit_len_ctx, a.width, a.unit));
}
/**
* Calculate used values of border-right-{style,color,width}
*
- * \param len_ctx Length conversion context
+ * \param unit_len_ctx Length conversion context
* \param cell Table cell to consider
*/
-void table_used_right_border_for_cell(
- const nscss_len_ctx *len_ctx,
- struct box *cell)
+static void
+table_used_right_border_for_cell(const css_unit_ctx *unit_len_ctx, struct box *cell)
{
struct border a, b;
box_type a_src, b_src;
@@ -590,12 +627,13 @@ void table_used_right_border_for_cell(
a.style = css_computed_border_right_style(cell->style);
css_computed_border_right_color(cell->style, &a.c);
css_computed_border_right_width(cell->style, &a.width, &a.unit);
- a.width = nscss_len2px(len_ctx, a.width, a.unit, cell->style);
+ a.width = css_unit_len2device_px(cell->style, unit_len_ctx,
+ a.width, a.unit);
a.unit = CSS_UNIT_PX;
a_src = BOX_TABLE_CELL;
- if (cell->next != NULL || cell->start_column + cell->columns !=
- cell->parent->parent->parent->columns) {
+ if (cell->next != NULL || cell->start_column + cell->columns !=
+ cell->parent->parent->parent->columns) {
/* Cell is not at right edge of table -- no right border */
a.style = CSS_BORDER_STYLE_NONE;
a.width = 0;
@@ -610,17 +648,20 @@ void table_used_right_border_for_cell(
while (rows-- > 0 && row != NULL) {
/* Spanned rows -- consider their right border */
b.style = css_computed_border_right_style(row->style);
- b.color = css_computed_border_right_color(
- row->style, &b.c);
- css_computed_border_right_width(
- row->style, &b.width, &b.unit);
- b.width = nscss_len2px(len_ctx,
- b.width, b.unit, row->style);
+ b.color = css_computed_border_right_color(row->style,
+ &b.c);
+ css_computed_border_right_width(row->style,
+ &b.width,
+ &b.unit);
+ b.width = css_unit_len2device_px(
+ row->style, unit_len_ctx,
+ b.width, b.unit);
b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW;
- if (table_border_is_more_eyecatching(len_ctx,
- &a, a_src, &b, b_src)) {
+ if (table_border_is_more_eyecatching(unit_len_ctx,
+ &a, a_src,
+ &b, b_src)) {
a = b;
a_src = b_src;
}
@@ -634,13 +675,14 @@ void table_used_right_border_for_cell(
b.style = css_computed_border_right_style(group->style);
b.color = css_computed_border_right_color(group->style, &b.c);
css_computed_border_right_width(group->style,
- &b.width, &b.unit);
- b.width = nscss_len2px(len_ctx, b.width, b.unit, group->style);
+ &b.width, &b.unit);
+ b.width = css_unit_len2device_px(group->style, unit_len_ctx,
+ b.width, b.unit);
b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW_GROUP;
-
- if (table_border_is_more_eyecatching(len_ctx,
- &a, a_src, &b, b_src)) {
+
+ if (table_border_is_more_eyecatching(unit_len_ctx,
+ &a, a_src, &b, b_src)) {
a = b;
a_src = b_src;
}
@@ -648,14 +690,16 @@ void table_used_right_border_for_cell(
/* The table itself -- consider its right border */
b.style = css_computed_border_right_style(table->style);
b.color = css_computed_border_right_color(table->style, &b.c);
- css_computed_border_right_width(table->style,
- &b.width, &b.unit);
- b.width = nscss_len2px(len_ctx, b.width, b.unit, table->style);
+ css_computed_border_right_width(table->style,
+ &b.width, &b.unit);
+ b.width = css_unit_len2device_px(table->style, unit_len_ctx,
+ b.width, b.unit);
b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE;
-
- if (table_border_is_more_eyecatching(len_ctx,
- &a, a_src, &b, b_src)) {
+
+ if (table_border_is_more_eyecatching(unit_len_ctx,
+ &a, a_src,
+ &b, b_src)) {
a = b;
a_src = b_src;
}
@@ -664,19 +708,20 @@ void table_used_right_border_for_cell(
/* a now contains the used right border for the cell */
cell->border[RIGHT].style = a.style;
cell->border[RIGHT].c = a.c;
- cell->border[RIGHT].width = FIXTOINT(nscss_len2px(len_ctx,
- a.width, a.unit, cell->style));
+ cell->border[RIGHT].width = FIXTOINT(css_unit_len2device_px(
+ cell->style, unit_len_ctx, a.width, a.unit));
}
+
/**
* Calculate used values of border-bottom-{style,color,width}
*
- * \param len_ctx Length conversion context
+ * \param unit_len_ctx Length conversion context
* \param cell Table cell to consider
*/
-void table_used_bottom_border_for_cell(
- const nscss_len_ctx *len_ctx,
- struct box *cell)
+static void
+table_used_bottom_border_for_cell(const css_unit_ctx *unit_len_ctx,
+ struct box *cell)
{
struct border a, b;
box_type a_src, b_src;
@@ -687,7 +732,8 @@ void table_used_bottom_border_for_cell(
a.style = css_computed_border_bottom_style(cell->style);
css_computed_border_bottom_color(cell->style, &a.c);
css_computed_border_bottom_width(cell->style, &a.width, &a.unit);
- a.width = nscss_len2px(len_ctx, a.width, a.unit, cell->style);
+ a.width = css_unit_len2device_px(cell->style, unit_len_ctx,
+ a.width, a.unit);
a.unit = CSS_UNIT_PX;
a_src = BOX_TABLE_CELL;
@@ -711,12 +757,13 @@ void table_used_bottom_border_for_cell(
b.style = css_computed_border_bottom_style(row->style);
b.color = css_computed_border_bottom_color(row->style, &b.c);
css_computed_border_bottom_width(row->style, &b.width, &b.unit);
- b.width = nscss_len2px(len_ctx, b.width, b.unit, row->style);
+ b.width = css_unit_len2device_px(row->style, unit_len_ctx,
+ b.width, b.unit);
b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW;
-
- if (table_border_is_more_eyecatching(len_ctx,
- &a, a_src, &b, b_src)) {
+
+ if (table_border_is_more_eyecatching(unit_len_ctx,
+ &a, a_src, &b, b_src)) {
a = b;
a_src = b_src;
}
@@ -724,14 +771,15 @@ void table_used_bottom_border_for_cell(
/* Row group -- consider its bottom border */
b.style = css_computed_border_bottom_style(group->style);
b.color = css_computed_border_bottom_color(group->style, &b.c);
- css_computed_border_bottom_width(group->style,
- &b.width, &b.unit);
- b.width = nscss_len2px(len_ctx, b.width, b.unit, group->style);
+ css_computed_border_bottom_width(group->style,
+ &b.width, &b.unit);
+ b.width = css_unit_len2device_px(group->style, unit_len_ctx,
+ b.width, b.unit);
b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW_GROUP;
-
- if (table_border_is_more_eyecatching(len_ctx,
- &a, a_src, &b, b_src)) {
+
+ if (table_border_is_more_eyecatching(unit_len_ctx,
+ &a, a_src, &b, b_src)) {
a = b;
a_src = b_src;
}
@@ -739,14 +787,15 @@ void table_used_bottom_border_for_cell(
/* The table itself -- consider its bottom border */
b.style = css_computed_border_bottom_style(table->style);
b.color = css_computed_border_bottom_color(table->style, &b.c);
- css_computed_border_bottom_width(table->style,
- &b.width, &b.unit);
- b.width = nscss_len2px(len_ctx, b.width, b.unit, table->style);
+ css_computed_border_bottom_width(table->style,
+ &b.width, &b.unit);
+ b.width = css_unit_len2device_px(table->style, unit_len_ctx,
+ b.width, b.unit);
b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE;
-
- if (table_border_is_more_eyecatching(len_ctx,
- &a, a_src, &b, b_src)) {
+
+ if (table_border_is_more_eyecatching(unit_len_ctx,
+ &a, a_src, &b, b_src)) {
a = b;
}
}
@@ -754,327 +803,262 @@ void table_used_bottom_border_for_cell(
/* a now contains the used bottom border for the cell */
cell->border[BOTTOM].style = a.style;
cell->border[BOTTOM].c = a.c;
- cell->border[BOTTOM].width = FIXTOINT(nscss_len2px(len_ctx,
- a.width, a.unit, cell->style));
+ cell->border[BOTTOM].width = FIXTOINT(css_unit_len2device_px(
+ cell->style, unit_len_ctx, a.width, a.unit));
}
-/**
- * Determine if a border style is more eyecatching than another
- *
- * \param len_ctx Length conversion context
- * \param a Reference border style
- * \param a_src Source of \a a
- * \param b Candidate border style
- * \param b_src Source of \a b
- * \return True if \a b is more eyecatching than \a a
- */
-bool table_border_is_more_eyecatching(
- const nscss_len_ctx *len_ctx,
- const struct border *a,
- box_type a_src,
- const struct border *b,
- box_type b_src)
-{
- css_fixed awidth, bwidth;
- int impact = 0;
-
- /* See CSS 2.1 $17.6.2.1 */
- /* 1 + 2 -- hidden beats everything, none beats nothing */
- if (a->style == CSS_BORDER_STYLE_HIDDEN ||
- b->style == CSS_BORDER_STYLE_NONE)
- return false;
+/* exported interface documented in html/table.h */
+bool
+table_calculate_column_types(const css_unit_ctx *unit_len_ctx, struct box *table)
+{
+ unsigned int i, j;
+ struct column *col;
+ struct box *row_group, *row, *cell;
- if (b->style == CSS_BORDER_STYLE_HIDDEN ||
- a->style == CSS_BORDER_STYLE_NONE)
+ if (table->col)
+ /* table->col already constructed, for example frameset table */
return true;
- /* 3a -- wider borders beat narrow ones */
- /* The widths must be absolute, which will be the case
- * if they've come from a computed style. */
- assert(a->unit != CSS_UNIT_EM && a->unit != CSS_UNIT_EX);
- assert(b->unit != CSS_UNIT_EM && b->unit != CSS_UNIT_EX);
- awidth = nscss_len2px(len_ctx, a->width, a->unit, NULL);
- bwidth = nscss_len2px(len_ctx, b->width, b->unit, NULL);
-
- if (awidth < bwidth)
- return true;
- else if (bwidth < awidth)
+ table->col = col = talloc_array(table, struct column, table->columns);
+ if (!col)
return false;
- /* 3b -- sort by style */
- switch (a->style) {
- case CSS_BORDER_STYLE_DOUBLE: impact++; /* Fall through */
- case CSS_BORDER_STYLE_SOLID: impact++; /* Fall through */
- case CSS_BORDER_STYLE_DASHED: impact++; /* Fall through */
- case CSS_BORDER_STYLE_DOTTED: impact++; /* Fall through */
- case CSS_BORDER_STYLE_RIDGE: impact++; /* Fall through */
- case CSS_BORDER_STYLE_OUTSET: impact++; /* Fall through */
- case CSS_BORDER_STYLE_GROOVE: impact++; /* Fall through */
- case CSS_BORDER_STYLE_INSET: impact++; /* Fall through */
- default:
- break;
- }
-
- switch (b->style) {
- case CSS_BORDER_STYLE_DOUBLE: impact--; /* Fall through */
- case CSS_BORDER_STYLE_SOLID: impact--; /* Fall through */
- case CSS_BORDER_STYLE_DASHED: impact--; /* Fall through */
- case CSS_BORDER_STYLE_DOTTED: impact--; /* Fall through */
- case CSS_BORDER_STYLE_RIDGE: impact--; /* Fall through */
- case CSS_BORDER_STYLE_OUTSET: impact--; /* Fall through */
- case CSS_BORDER_STYLE_GROOVE: impact--; /* Fall through */
- case CSS_BORDER_STYLE_INSET: impact--; /* Fall through */
- default:
- break;
+ for (i = 0; i != table->columns; i++) {
+ col[i].type = COLUMN_WIDTH_UNKNOWN;
+ col[i].width = 0;
+ col[i].positioned = true;
}
- if (impact < 0)
- return true;
- else if (impact > 0)
- return false;
-
- /* 4a -- sort by origin */
- impact = 0;
-
- /** \todo COL/COL_GROUP */
- switch (a_src) {
- case BOX_TABLE_CELL: impact++; /* Fall through */
- case BOX_TABLE_ROW: impact++; /* Fall through */
- case BOX_TABLE_ROW_GROUP: impact++; /* Fall through */
- case BOX_TABLE: impact++; /* Fall through */
- default:
- break;
- }
+ /* 1st pass: cells with colspan 1 only */
+ for (row_group = table->children; row_group; row_group =row_group->next)
+ for (row = row_group->children; row; row = row->next)
+ for (cell = row->children; cell; cell = cell->next) {
+ enum css_width_e type;
+ css_fixed value = 0;
+ css_unit unit = CSS_UNIT_PX;
- /** \todo COL/COL_GROUP */
- switch (b_src) {
- case BOX_TABLE_CELL: impact--; /* Fall through */
- case BOX_TABLE_ROW: impact--; /* Fall through */
- case BOX_TABLE_ROW_GROUP: impact--; /* Fall through */
- case BOX_TABLE: impact--; /* Fall through */
- default:
- break;
- }
+ assert(cell->type == BOX_TABLE_CELL);
+ assert(cell->style);
- if (impact < 0)
- return true;
- else if (impact > 0)
- return false;
+ if (cell->columns != 1)
+ continue;
+ i = cell->start_column;
- /* 4b -- furthest left (if direction: ltr) and towards top wins */
- /** \todo Currently assumes b satisifies this */
- return true;
-}
+ if (css_computed_position(cell->style) !=
+ CSS_POSITION_ABSOLUTE &&
+ css_computed_position(cell->style) !=
+ CSS_POSITION_FIXED) {
+ col[i].positioned = false;
+ }
-/******************************************************************************
- * Helpers for top border collapsing *
- ******************************************************************************/
+ type = css_computed_width(cell->style, &value, &unit);
+
+ /* fixed width takes priority over any other width type */
+ if (col[i].type != COLUMN_WIDTH_FIXED &&
+ type == CSS_WIDTH_SET && unit != CSS_UNIT_PCT) {
+ col[i].type = COLUMN_WIDTH_FIXED;
+ col[i].width = FIXTOINT(css_unit_len2device_px(
+ cell->style,
+ unit_len_ctx,
+ value, unit));
+ if (col[i].width < 0)
+ col[i].width = 0;
+ continue;
+ }
-/**
- * Process a table
- *
- * \param len_ctx Length conversion context
- * \param table Table to process
- * \param a Current border style for cell
- * \param a_src Source of \a a
- *
- * \post \a a will be updated with most eyecatching style
- * \post \a a_src will be updated also
- */
-void table_cell_top_process_table(
- const nscss_len_ctx *len_ctx,
- struct box *table,
- struct border *a,
- box_type *a_src)
-{
- struct border b;
- box_type b_src;
+ if (col[i].type != COLUMN_WIDTH_UNKNOWN)
+ continue;
- /* Top border of table */
- b.style = css_computed_border_top_style(table->style);
- b.color = css_computed_border_top_color(table->style, &b.c);
- css_computed_border_top_width(table->style, &b.width, &b.unit);
- b.width = nscss_len2px(len_ctx, b.width, b.unit, table->style);
- b.unit = CSS_UNIT_PX;
- b_src = BOX_TABLE;
+ if (type == CSS_WIDTH_SET && unit == CSS_UNIT_PCT) {
+ col[i].type = COLUMN_WIDTH_PERCENT;
+ col[i].width = FIXTOINT(value);
+ if (col[i].width < 0)
+ col[i].width = 0;
+ } else if (type == CSS_WIDTH_AUTO) {
+ col[i].type = COLUMN_WIDTH_AUTO;
+ }
+ }
- if (table_border_is_more_eyecatching(len_ctx, a, *a_src, &b, b_src)) {
- *a = b;
- *a_src = b_src;
- }
-}
+ /* 2nd pass: cells which span multiple columns */
+ for (row_group = table->children; row_group; row_group =row_group->next)
+ for (row = row_group->children; row; row = row->next)
+ for (cell = row->children; cell; cell = cell->next) {
+ unsigned int fixed_columns = 0,
+ percent_columns = 0,
+ auto_columns = 0,
+ unknown_columns = 0;
+ int fixed_width = 0, percent_width = 0;
+ enum css_width_e type;
+ css_fixed value = 0;
+ css_unit unit = CSS_UNIT_PX;
+
+ if (cell->columns == 1)
+ continue;
+ i = cell->start_column;
-/**
- * Process a group
- *
- * \param len_ctx Length conversion context
- * \param cell Cell being considered
- * \param group Group to process
- * \param a Current border style for cell
- * \param a_src Source of \a a
- * \return true if group has non-empty rows, false otherwise
- *
- * \post \a a will be updated with most eyecatching style
- * \post \a a_src will be updated also
- */
-bool table_cell_top_process_group(
- const nscss_len_ctx *len_ctx,
- struct box *cell,
- struct box *group,
- struct border *a,
- box_type *a_src)
-{
- struct border b;
- box_type b_src;
+ for (j = i; j < i + cell->columns; j++) {
+ col[j].positioned = false;
+ }
- /* Bottom border of group */
- b.style = css_computed_border_bottom_style(group->style);
- b.color = css_computed_border_bottom_color(group->style, &b.c);
- css_computed_border_bottom_width(group->style, &b.width, &b.unit);
- b.width = nscss_len2px(len_ctx, b.width, b.unit, group->style);
- b.unit = CSS_UNIT_PX;
- b_src = BOX_TABLE_ROW_GROUP;
+ /* count column types in spanned cells */
+ for (j = 0; j != cell->columns; j++) {
+ if (col[i + j].type == COLUMN_WIDTH_FIXED) {
+ fixed_width += col[i + j].width;
+ fixed_columns++;
+ } else if (col[i + j].type == COLUMN_WIDTH_PERCENT) {
+ percent_width += col[i + j].width;
+ percent_columns++;
+ } else if (col[i + j].type == COLUMN_WIDTH_AUTO) {
+ auto_columns++;
+ } else {
+ unknown_columns++;
+ }
+ }
- if (table_border_is_more_eyecatching(len_ctx, a, *a_src, &b, b_src)) {
- *a = b;
- *a_src = b_src;
- }
+ if (!unknown_columns)
+ continue;
- if (group->last != NULL) {
- /* Process rows in group, starting with last */
- struct box *row = group->last;
+ type = css_computed_width(cell->style, &value, &unit);
+
+ /* if cell is fixed width, and all spanned columns are fixed
+ * or unknown width, split extra width among unknown columns */
+ if (type == CSS_WIDTH_SET && unit != CSS_UNIT_PCT &&
+ fixed_columns + unknown_columns ==
+ cell->columns) {
+ int width = (FIXTOFLT(css_unit_len2device_px(
+ cell->style,
+ unit_len_ctx,
+ value, unit)) -
+ fixed_width) / unknown_columns;
+ if (width < 0)
+ width = 0;
+ for (j = 0; j != cell->columns; j++) {
+ if (col[i + j].type == COLUMN_WIDTH_UNKNOWN) {
+ col[i + j].type = COLUMN_WIDTH_FIXED;
+ col[i + j].width = width;
+ }
+ }
+ }
- while (table_cell_top_process_row(len_ctx, cell, row,
- a, a_src) == false) {
- if (row->prev == NULL) {
- return false;
- } else {
- row = row->prev;
+ /* as above for percentage width */
+ if (type == CSS_WIDTH_SET && unit == CSS_UNIT_PCT &&
+ percent_columns + unknown_columns ==
+ cell->columns) {
+ int width = (FIXTOFLT(value) -
+ percent_width) / unknown_columns;
+ if (width < 0)
+ width = 0;
+ for (j = 0; j != cell->columns; j++) {
+ if (col[i + j].type == COLUMN_WIDTH_UNKNOWN) {
+ col[i + j].type = COLUMN_WIDTH_PERCENT;
+ col[i + j].width = width;
+ }
+ }
+ }
}
- }
- } else {
- /* Group is empty, so consider its top border */
- b.style = css_computed_border_top_style(group->style);
- b.color = css_computed_border_top_color(group->style, &b.c);
- css_computed_border_top_width(group->style, &b.width, &b.unit);
- b.width = nscss_len2px(len_ctx, b.width, b.unit, group->style);
- b.unit = CSS_UNIT_PX;
- b_src = BOX_TABLE_ROW_GROUP;
-
- if (table_border_is_more_eyecatching(len_ctx,
- a, *a_src, &b, b_src)) {
- *a = b;
- *a_src = b_src;
- }
- return false;
+ /* use AUTO if no width type was specified */
+ for (i = 0; i != table->columns; i++) {
+ if (col[i].type == COLUMN_WIDTH_UNKNOWN)
+ col[i].type = COLUMN_WIDTH_AUTO;
}
+#ifdef TABLE_DEBUG
+ for (i = 0; i != table->columns; i++)
+ NSLOG(netsurf, INFO,
+ "table %p, column %u: type %s, width %i",
+ table,
+ i,
+ ((const char *[]){
+ "UNKNOWN",
+ "FIXED",
+ "AUTO",
+ "PERCENT",
+ "RELATIVE",
+ })[col[i].type],
+ col[i].width);
+#endif
+
return true;
}
-/**
- * Process a row
- *
- * \param len_ctx Length conversion context
- * \param cell Cell being considered
- * \param row Row to process
- * \param a Current border style for cell
- * \param a_src Source of \a a
- * \return true if row has cells, false otherwise
- *
- * \post \a a will be updated with most eyecatching style
- * \post \a a_src will be updated also
- */
-bool table_cell_top_process_row(
- const nscss_len_ctx *len_ctx,
- struct box *cell,
- struct box *row,
- struct border *a,
- box_type *a_src)
-{
- struct border b;
- box_type b_src;
- /* Bottom border of row */
- b.style = css_computed_border_bottom_style(row->style);
- b.color = css_computed_border_bottom_color(row->style, &b.c);
- css_computed_border_bottom_width(row->style, &b.width, &b.unit);
- b.width = nscss_len2px(len_ctx, b.width, b.unit, row->style);
- b.unit = CSS_UNIT_PX;
- b_src = BOX_TABLE_ROW;
-
- if (table_border_is_more_eyecatching(len_ctx, a, *a_src, &b, b_src)) {
- *a = b;
- *a_src = b_src;
- }
+/* exported interface documented in html/table.h */
+void table_used_border_for_cell(const css_unit_ctx *unit_len_ctx, struct box *cell)
+{
+ int side;
- if (row->children == NULL) {
- /* Row is empty, so consider its top border */
- b.style = css_computed_border_top_style(row->style);
- b.color = css_computed_border_top_color(row->style, &b.c);
- css_computed_border_top_width(row->style, &b.width, &b.unit);
- b.width = nscss_len2px(len_ctx, b.width, b.unit, row->style);
- b.unit = CSS_UNIT_PX;
- b_src = BOX_TABLE_ROW;
+ assert(cell->type == BOX_TABLE_CELL);
- if (table_border_is_more_eyecatching(len_ctx,
- a, *a_src, &b, b_src)) {
- *a = b;
- *a_src = b_src;
- }
+ if (css_computed_border_collapse(cell->style) ==
+ CSS_BORDER_COLLAPSE_SEPARATE) {
+ css_fixed width = 0;
+ css_unit unit = CSS_UNIT_PX;
- return false;
- } else {
- /* Process cells that are directly above the cell being
- * considered. They may not be in this row, but in one of the
- * rows above it in the case where rowspan > 1. */
- struct box *c;
- bool processed = false;
+ /* Left border */
+ cell->border[LEFT].style =
+ css_computed_border_left_style(cell->style);
+ css_computed_border_left_color(cell->style,
+ &cell->border[LEFT].c);
+ css_computed_border_left_width(cell->style, &width, &unit);
+ cell->border[LEFT].width =
+ FIXTOINT(css_unit_len2device_px(
+ cell->style, unit_len_ctx,
+ width, unit));
- while (processed == false) {
- for (c = row->children; c != NULL; c = c->next) {
- /* Ignore cells to the left */
- if (c->start_column + c->columns - 1 <
- cell->start_column)
- continue;
- /* Ignore cells to the right */
- if (c->start_column > cell->start_column +
- cell->columns - 1)
- continue;
+ /* Top border */
+ cell->border[TOP].style =
+ css_computed_border_top_style(cell->style);
+ css_computed_border_top_color(cell->style,
+ &cell->border[TOP].c);
+ css_computed_border_top_width(cell->style, &width, &unit);
+ cell->border[TOP].width =
+ FIXTOINT(css_unit_len2device_px(
+ cell->style, unit_len_ctx,
+ width, unit));
- /* Flag that we've processed a cell */
- processed = true;
+ /* Right border */
+ cell->border[RIGHT].style =
+ css_computed_border_right_style(cell->style);
+ css_computed_border_right_color(cell->style,
+ &cell->border[RIGHT].c);
+ css_computed_border_right_width(cell->style, &width, &unit);
+ cell->border[RIGHT].width =
+ FIXTOINT(css_unit_len2device_px(
+ cell->style, unit_len_ctx,
+ width, unit));
- /* Consider bottom border */
- b.style = css_computed_border_bottom_style(
- c->style);
- b.color = css_computed_border_bottom_color(
- c->style, &b.c);
- css_computed_border_bottom_width(c->style,
- &b.width, &b.unit);
- b.width = nscss_len2px(len_ctx,
- b.width, b.unit, c->style);
- b.unit = CSS_UNIT_PX;
- b_src = BOX_TABLE_CELL;
+ /* Bottom border */
+ cell->border[BOTTOM].style =
+ css_computed_border_bottom_style(cell->style);
+ css_computed_border_bottom_color(cell->style,
+ &cell->border[BOTTOM].c);
+ css_computed_border_bottom_width(cell->style, &width, &unit);
+ cell->border[BOTTOM].width =
+ FIXTOINT(css_unit_len2device_px(
+ cell->style, unit_len_ctx,
+ width, unit));
+ } else {
+ /* Left border */
+ table_used_left_border_for_cell(unit_len_ctx, cell);
- if (table_border_is_more_eyecatching(len_ctx,
- a, *a_src, &b, b_src)) {
- *a = b;
- *a_src = b_src;
- }
- }
+ /* Top border */
+ table_used_top_border_for_cell(unit_len_ctx, cell);
- if (processed == false) {
- /* There must be a preceding row */
- assert(row->prev != NULL);
+ /* Right border */
+ table_used_right_border_for_cell(unit_len_ctx, cell);
- row = row->prev;
- }
- }
+ /* Bottom border */
+ table_used_bottom_border_for_cell(unit_len_ctx, cell);
}
- return true;
+ /* Finally, ensure that any borders configured as
+ * hidden or none have zero width. (c.f. layout_find_dimensions) */
+ for (side = 0; side != 4; side++) {
+ if (cell->border[side].style == CSS_BORDER_STYLE_HIDDEN ||
+ cell->border[side].style ==
+ CSS_BORDER_STYLE_NONE)
+ cell->border[side].width = 0;
+ }
}
-
diff --git a/content/handlers/html/table.h b/content/handlers/html/table.h
new file mode 100644
index 000000000..557032b06
--- /dev/null
+++ b/content/handlers/html/table.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Interface to HTML table processing and layout.
+ */
+
+#ifndef NETSURF_HTML_TABLE_H
+#define NETSURF_HTML_TABLE_H
+
+#include <stdbool.h>
+
+struct box;
+
+
+/**
+ * Determine the column width types for a table.
+ *
+ * \param unit_len_ctx Length conversion context
+ * \param table box of type BOX_TABLE
+ * \return true on success, false on memory exhaustion
+ *
+ * The table->col array is allocated and type and width are filled in for each
+ * column.
+ */
+bool table_calculate_column_types(const css_unit_ctx *unit_len_ctx, struct box *table);
+
+
+/**
+ * Calculate used values of border-{trbl}-{style,color,width} for table cells.
+ *
+ * \param unit_len_ctx Length conversion context
+ * \param cell Table cell to consider
+ *
+ * \post \a cell's border array is populated
+ */
+void table_used_border_for_cell(const css_unit_ctx *unit_len_ctx, struct box *cell);
+
+#endif
diff --git a/content/handlers/html/textselection.c b/content/handlers/html/textselection.c
new file mode 100644
index 000000000..9b83e73ec
--- /dev/null
+++ b/content/handlers/html/textselection.c
@@ -0,0 +1,547 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * implementation of text selection for a HTML content.
+ */
+
+#include <stdlib.h>
+
+#include "utils/errors.h"
+#include "utils/utils.h"
+#include "netsurf/types.h"
+#include "netsurf/plot_style.h"
+#include "desktop/selection.h"
+#include "desktop/save_text.h"
+
+#include "html/private.h"
+#include "html/box.h"
+#include "html/box_inspect.h"
+#include "html/font.h"
+#include "html/textselection.h"
+
+#define SPACE_LEN(b) ((b->space == 0) ? 0 : 1)
+
+struct rdw_info {
+ bool inited;
+ struct rect r;
+};
+
+
+/**
+ * Tests whether a text box lies partially within the given range of
+ * byte offsets, returning the start and end indexes of the bytes
+ * that are enclosed.
+ *
+ * \param box box to be tested
+ * \param start_idx byte offset of start of range
+ * \param end_idx byte offset of end of range
+ * \param start_offset receives the start offset of the selected part
+ * \param end_offset receives the end offset of the selected part
+ * \return true iff the range encloses at least part of the box
+ */
+static bool
+selected_part(struct box *box,
+ unsigned start_idx,
+ unsigned end_idx,
+ unsigned *start_offset,
+ unsigned *end_offset)
+{
+ size_t box_length = box->length + SPACE_LEN(box);
+
+ if (box_length > 0) {
+ if ((box->byte_offset >= start_idx) &&
+ (box->byte_offset + box_length <= end_idx)) {
+
+ /* fully enclosed */
+ *start_offset = 0;
+ *end_offset = box_length;
+ return true;
+ } else if ((box->byte_offset + box_length > start_idx) &&
+ (box->byte_offset < end_idx)) {
+ /* partly enclosed */
+ int offset = 0;
+ int len;
+
+ if (box->byte_offset < start_idx) {
+ offset = start_idx - box->byte_offset;
+ }
+
+ len = box_length - offset;
+
+ if (box->byte_offset + box_length > end_idx) {
+ len = end_idx - (box->byte_offset + offset);
+ }
+
+ *start_offset = offset;
+ *end_offset = offset + len;
+
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/**
+ * Traverse the given box subtree adding the boxes inside the
+ * selection to the coordinate range.
+ *
+ * \param box box subtree
+ * \param start_idx start of range within textual representation (bytes)
+ * \param end_idx end of range
+ * \param rdwi redraw range to fill in
+ * \param do_marker whether deal enter any marker box
+ * \return NSERROR_OK on success else error code
+ */
+static nserror
+coords_from_range(struct box *box,
+ unsigned start_idx,
+ unsigned end_idx,
+ struct rdw_info *rdwi,
+ bool do_marker)
+{
+ struct box *child;
+ nserror res;
+
+ assert(box);
+
+ /* If selection starts inside marker */
+ if (box->parent &&
+ box->parent->list_marker == box &&
+ !do_marker) {
+ /* set box to main list element */
+ box = box->parent;
+ }
+
+ /* If box has a list marker */
+ if (box->list_marker) {
+ /* do the marker box before continuing with the rest of the
+ * list element */
+ res = coords_from_range(box->list_marker,
+ start_idx,
+ end_idx,
+ rdwi,
+ true);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ /* we can prune this subtree, it's after the selection */
+ if (box->byte_offset >= end_idx) {
+ return NSERROR_OK;
+ }
+
+ /* read before calling the handler in case it modifies the tree */
+ child = box->children;
+
+ if ((box->type != BOX_BR) &&
+ !((box->type == BOX_FLOAT_LEFT ||
+ box->type == BOX_FLOAT_RIGHT) &&
+ !box->text)) {
+ unsigned start_off;
+ unsigned end_off;
+
+ if (selected_part(box, start_idx, end_idx, &start_off, &end_off)) {
+ int width, height;
+ int x, y;
+
+ /**
+ * \todo it should be possible to reduce the redrawn
+ * area using the offsets
+ */
+ box_coords(box, &x, &y);
+
+ width = box->padding[LEFT] + box->width + box->padding[RIGHT];
+ height = box->padding[TOP] + box->height + box->padding[BOTTOM];
+
+ if ((box->type == BOX_TEXT) &&
+ (box->space != 0)) {
+ width += box->space;
+ }
+
+ if (rdwi->inited) {
+ if (x < rdwi->r.x0) {
+ rdwi->r.x0 = x;
+ }
+ if (y < rdwi->r.y0) {
+ rdwi->r.y0 = y;
+ }
+ if (x + width > rdwi->r.x1) {
+ rdwi->r.x1 = x + width;
+ }
+ if (y + height > rdwi->r.y1) {
+ rdwi->r.y1 = y + height;
+ }
+ } else {
+ rdwi->inited = true;
+ rdwi->r.x0 = x;
+ rdwi->r.y0 = y;
+ rdwi->r.x1 = x + width;
+ rdwi->r.y1 = y + height;
+ }
+ }
+ }
+
+ /* find the first child that could lie partially within the selection;
+ * this is important at the top-levels of the tree for pruning subtrees
+ * that lie entirely before the selection */
+
+ if (child) {
+ struct box *next = child->next;
+
+ while (next && next->byte_offset < start_idx) {
+ child = next;
+ next = child->next;
+ }
+
+ while (child) {
+ /* read before calling the handler in case it modifies
+ * the tree */
+ struct box *next = child->next;
+
+ res = coords_from_range(child,
+ start_idx,
+ end_idx,
+ rdwi,
+ false);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ child = next;
+ }
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Append the contents of a box to a selection along with style information
+ *
+ * \param text pointer to text being added, or NULL for newline
+ * \param length length of text to be appended (bytes)
+ * \param box pointer to text box, or NULL if from textplain
+ * \param unit_len_ctx Length conversion context
+ * \param handle selection string to append to
+ * \param whitespace_text whitespace to place before text for formatting
+ * may be NULL
+ * \param whitespace_length length of whitespace_text
+ * \return NSERROR_OK iff successful and traversal should continue else error code
+ */
+static nserror
+selection_copy_box(const char *text,
+ size_t length,
+ struct box *box,
+ const css_unit_ctx *unit_len_ctx,
+ struct selection_string *handle,
+ const char *whitespace_text,
+ size_t whitespace_length)
+{
+ bool add_space = false;
+ plot_font_style_t style;
+ plot_font_style_t *pstyle = NULL;
+
+ /* add any whitespace which precedes the text from this box */
+ if (whitespace_text != NULL &&
+ whitespace_length > 0) {
+ if (!selection_string_append(whitespace_text,
+ whitespace_length,
+ false,
+ pstyle,
+ handle)) {
+ return NSERROR_NOMEM;
+ }
+ }
+
+ if (box != NULL) {
+ /* HTML */
+ add_space = (box->space != 0);
+
+ if (box->style != NULL) {
+ /* Override default font style */
+ font_plot_style_from_css(unit_len_ctx, box->style, &style);
+ pstyle = &style;
+ } else {
+ /* If there's no style, there must be no text */
+ assert(box->text == NULL);
+ }
+ }
+
+ /* add the text from this box */
+ if (!selection_string_append(text, length, add_space, pstyle, handle)) {
+ return NSERROR_NOMEM;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Traverse the given box subtree, calling selection copy for all
+ * boxes that lie (partially) within the given range
+ *
+ * \param box box subtree
+ * \param unit_len_ctx Length conversion context.
+ * \param start_idx start of range within textual representation (bytes)
+ * \param end_idx end of range
+ * \param handler handler function to call
+ * \param handle handle to pass
+ * \param before type of whitespace to place before next encountered text
+ * \param first whether this is the first box with text
+ * \param do_marker whether deal enter any marker box
+ * \return NSERROR_OK on sucess else error code
+ */
+static nserror
+selection_copy(struct box *box,
+ const css_unit_ctx *unit_len_ctx,
+ unsigned start_idx,
+ unsigned end_idx,
+ struct selection_string *selstr,
+ save_text_whitespace *before,
+ bool *first,
+ bool do_marker)
+{
+ nserror res;
+ struct box *child;
+ const char *whitespace_text = "";
+ size_t whitespace_length = 0;
+
+ assert(box);
+
+ /* If selection starts inside marker */
+ if (box->parent &&
+ box->parent->list_marker == box &&
+ !do_marker) {
+ /* set box to main list element */
+ box = box->parent;
+ }
+
+ /* If box has a list marker */
+ if (box->list_marker) {
+ /* do the marker box before continuing with the rest of the
+ * list element */
+ res = selection_copy(box->list_marker,
+ unit_len_ctx,
+ start_idx,
+ end_idx,
+ selstr,
+ before,
+ first,
+ true);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ /* we can prune this subtree, it's after the selection */
+ if (box->byte_offset >= end_idx) {
+ return NSERROR_OK;
+ }
+
+ /* read before calling the handler in case it modifies the tree */
+ child = box->children;
+
+ /* If nicely formatted output of the selected text is required, work
+ * out what whitespace should be placed before the next bit of text */
+ if (before) {
+ save_text_solve_whitespace(box,
+ first,
+ before,
+ &whitespace_text,
+ &whitespace_length);
+ } else {
+ whitespace_text = NULL;
+ }
+
+ if ((box->type != BOX_BR) &&
+ !((box->type == BOX_FLOAT_LEFT ||
+ box->type == BOX_FLOAT_RIGHT) &&
+ !box->text)) {
+ unsigned start_off;
+ unsigned end_off;
+
+ if (selected_part(box, start_idx, end_idx, &start_off, &end_off)) {
+ res = selection_copy_box(box->text + start_off,
+ min(box->length, end_off) - start_off,
+ box,
+ unit_len_ctx,
+ selstr,
+ whitespace_text,
+ whitespace_length);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ if (before) {
+ *first = false;
+ *before = WHITESPACE_NONE;
+ }
+ }
+ }
+
+ /* find the first child that could lie partially within the selection;
+ * this is important at the top-levels of the tree for pruning subtrees
+ * that lie entirely before the selection */
+
+ if (child) {
+ struct box *next = child->next;
+
+ while (next && next->byte_offset < start_idx) {
+ child = next;
+ next = child->next;
+ }
+
+ while (child) {
+ /* read before calling the handler in case it modifies
+ * the tree */
+ struct box *next = child->next;
+
+ res = selection_copy(child,
+ unit_len_ctx,
+ start_idx,
+ end_idx,
+ selstr,
+ before,
+ first,
+ false);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ child = next;
+ }
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Label each text box in the given box subtree with its position
+ * in a textual representation of the content.
+ *
+ * \param box The box at root of subtree
+ * \param idx current position within textual representation
+ * \return updated position
+ */
+static unsigned selection_label_subtree(struct box *box, unsigned idx)
+{
+ struct box *child;
+
+ assert(box != NULL);
+
+ child = box->children;
+
+ box->byte_offset = idx;
+
+ if (box->text) {
+ idx += box->length + SPACE_LEN(box);
+ }
+
+ while (child) {
+ if (child->list_marker) {
+ idx = selection_label_subtree(child->list_marker, idx);
+ }
+
+ idx = selection_label_subtree(child, idx);
+ child = child->next;
+ }
+
+ return idx;
+}
+
+
+/* exported interface documented in html/textselection.h */
+nserror
+html_textselection_redraw(struct content *c,
+ unsigned start_idx,
+ unsigned end_idx)
+{
+ nserror res;
+ html_content *html = (html_content *)c;
+ struct rdw_info rdw;
+
+ if (html->layout == NULL) {
+ return NSERROR_INVALID;
+ }
+
+ rdw.inited = false;
+
+ res = coords_from_range(html->layout, start_idx, end_idx, &rdw, false);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ if (rdw.inited) {
+ content__request_redraw(c,
+ rdw.r.x0,
+ rdw.r.y0,
+ rdw.r.x1 - rdw.r.x0,
+ rdw.r.y1 - rdw.r.y0);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in html/textselection.h */
+nserror
+html_textselection_copy(struct content *c,
+ unsigned start_idx,
+ unsigned end_idx,
+ struct selection_string *selstr)
+{
+ html_content *html = (html_content *)c;
+ save_text_whitespace before = WHITESPACE_NONE;
+ bool first = true;
+
+ if (html->layout == NULL) {
+ return NSERROR_INVALID;
+ }
+
+ return selection_copy(html->layout,
+ &html->unit_len_ctx,
+ start_idx,
+ end_idx,
+ selstr,
+ &before,
+ &first,
+ false);
+}
+
+
+/* exported interface documented in html/textselection.h */
+nserror
+html_textselection_get_end(struct content *c, unsigned *end_idx)
+{
+ html_content *html = (html_content *)c;
+ unsigned root_idx;
+
+ if (html->layout == NULL) {
+ return NSERROR_INVALID;
+ }
+
+ root_idx = 0;
+
+ *end_idx = selection_label_subtree(html->layout, root_idx);
+
+ return NSERROR_OK;
+}
diff --git a/content/handlers/html/textselection.h b/content/handlers/html/textselection.h
new file mode 100644
index 000000000..46db045ef
--- /dev/null
+++ b/content/handlers/html/textselection.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * HTML text selection handling
+ */
+
+#ifndef NETSURF_HTML_TEXTSELECTION_H
+#define NETSURF_HTML_TEXTSELECTION_H
+
+struct content;
+struct selection;
+
+nserror html_textselection_redraw(struct content *c, unsigned start_idx, unsigned end_idx);
+
+nserror html_textselection_copy(struct content *c, unsigned start_idx, unsigned end_idx, struct selection_string *selstr);
+
+/**
+ * get maximum index of text section.
+ *
+ * \param[in] c The content to measure
+ * \param[out] end_idx pointer to value to recive result
+ * \return NSERROR_OK and \a end_idx updated else error code
+ */
+nserror html_textselection_get_end(struct content *c, unsigned *end_idx);
+
+#endif
diff --git a/content/handlers/image/Makefile b/content/handlers/image/Makefile
index 541cd2cf9..ac052b37a 100644
--- a/content/handlers/image/Makefile
+++ b/content/handlers/image/Makefile
@@ -3,13 +3,16 @@
# S_IMAGE are sources related to image management
S_IMAGE_YES := image.c image_cache.c
S_IMAGE_NO :=
-S_IMAGE_$(NETSURF_USE_BMP) += bmp.c ico.c
+S_IMAGE_$(NETSURF_USE_BMP) += bmp.c
S_IMAGE_$(NETSURF_USE_GIF) += gif.c
+S_IMAGE_$(NETSURF_USE_BMP) += ico.c
S_IMAGE_$(NETSURF_USE_JPEG) += jpeg.c
+S_IMAGE_$(NETSURF_USE_JPEGXL) += jpegxl.c
S_IMAGE_$(NETSURF_USE_ROSPRITE) += nssprite.c
S_IMAGE_$(NETSURF_USE_PNG) += png.c
S_IMAGE_$(NETSURF_USE_NSSVG) += svg.c
-S_IMAGE_$(NETSURF_USE_RSVG) += rsvg.c
+S_IMAGE_$(NETSURF_USE_RSVG) += rsvg$(RSVG_API).c
S_IMAGE_$(NETSURF_USE_VIDEO) += video.c
+S_IMAGE_$(NETSURF_USE_WEBP) += webp.c
S_IMAGE := $(S_IMAGE_YES)
diff --git a/content/handlers/image/bmp.c b/content/handlers/image/bmp.c
index 48a37fb24..3fec2cc75 100644
--- a/content/handlers/image/bmp.c
+++ b/content/handlers/image/bmp.c
@@ -33,7 +33,9 @@
#include "netsurf/content.h"
#include "content/llcache.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
#include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
#include "image/bmp.h"
@@ -56,12 +58,12 @@ typedef struct nsbmp_content {
*/
static void *nsbmp_bitmap_create(int width, int height, unsigned int bmp_state)
{
- unsigned int bitmap_state = BITMAP_NEW;
+ unsigned int bitmap_state = BITMAP_NONE;
/* set bitmap state based on bmp state */
bitmap_state |= (bmp_state & BMP_OPAQUE) ? BITMAP_OPAQUE : 0;
bitmap_state |= (bmp_state & BMP_CLEAR_MEMORY) ?
- BITMAP_CLEAR_MEMORY : 0;
+ BITMAP_CLEAR : 0;
/* return the created bitmap */
return guit->bitmap->create(width, height, bitmap_state);
@@ -73,12 +75,11 @@ static nserror nsbmp_create_bmp_data(nsbmp_content *bmp)
.bitmap_create = nsbmp_bitmap_create,
.bitmap_destroy = guit->bitmap->destroy,
.bitmap_get_buffer = guit->bitmap->get_buffer,
- .bitmap_get_bpp = guit->bitmap->get_bpp
};
bmp->bmp = calloc(sizeof(struct bmp_image), 1);
if (bmp->bmp == NULL) {
- content_broadcast_errorcode(&bmp->base, NSERROR_NOMEM);
+ content_broadcast_error(&bmp->base, NSERROR_NOMEM, NULL);
return NSERROR_NOMEM;
}
@@ -87,10 +88,14 @@ static nserror nsbmp_create_bmp_data(nsbmp_content *bmp)
return NSERROR_OK;
}
-static nserror nsbmp_create(const content_handler *handler,
- lwc_string *imime_type, const struct http_parameter *params,
- llcache_handle *llcache, const char *fallback_charset,
- bool quirks, struct content **c)
+static nserror
+nsbmp_create(const struct content_handler *handler,
+ lwc_string *imime_type,
+ const struct http_parameter *params,
+ llcache_handle *llcache,
+ const char *fallback_charset,
+ bool quirks,
+ struct content **c)
{
nsbmp_content *bmp;
nserror error;
@@ -122,8 +127,8 @@ static bool nsbmp_convert(struct content *c)
nsbmp_content *bmp = (nsbmp_content *) c;
bmp_result res;
uint32_t swidth;
- const char *data;
- unsigned long size;
+ const uint8_t *data;
+ size_t size;
char *title;
/* set the bmp data */
@@ -135,19 +140,18 @@ static bool nsbmp_convert(struct content *c)
case BMP_OK:
break;
case BMP_INSUFFICIENT_MEMORY:
- content_broadcast_errorcode(c, NSERROR_NOMEM);
+ content_broadcast_error(c, NSERROR_NOMEM, NULL);
return false;
case BMP_INSUFFICIENT_DATA:
case BMP_DATA_ERROR:
- content_broadcast_errorcode(c, NSERROR_BMP_ERROR);
+ content_broadcast_error(c, NSERROR_BMP_ERROR, NULL);
return false;
}
/* Store our content width and description */
c->width = bmp->bmp->width;
c->height = bmp->bmp->height;
- swidth = bmp->bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bmp->bitmap) *
- bmp->bmp->width;
+ swidth = sizeof(uint32_t) * bmp->bmp->width;
c->size += (swidth * bmp->bmp->height) + 16 + 44;
/* set title text */
@@ -186,6 +190,9 @@ static bool nsbmp_redraw(struct content *c, struct content_redraw_data *data,
return false;
}
+ bitmap_format_to_client(bmp->bitmap, &(bitmap_fmt_t) {
+ .layout = BITMAP_LAYOUT_R8G8B8A8,
+ });
guit->bitmap->modified(bmp->bitmap);
}
@@ -259,6 +266,16 @@ static content_type nsbmp_content_type(void)
return CONTENT_IMAGE;
}
+static bool nsbmp_content_is_opaque(struct content *c)
+{
+ nsbmp_content *bmp = (nsbmp_content *)c;
+
+ if (bmp->bitmap != NULL) {
+ return guit->bitmap->get_opaque(bmp->bitmap);
+ }
+
+ return false;
+}
static const content_handler nsbmp_content_handler = {
.create = nsbmp_create,
@@ -268,6 +285,7 @@ static const content_handler nsbmp_content_handler = {
.clone = nsbmp_clone,
.get_internal = nsbmp_get_internal,
.type = nsbmp_content_type,
+ .is_opaque = nsbmp_content_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/bmp.h b/content/handlers/image/bmp.h
index f3b398584..d3d7623ed 100644
--- a/content/handlers/image/bmp.h
+++ b/content/handlers/image/bmp.h
@@ -17,16 +17,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Content for image/bmp (interface).
+/**
+ * \file
+ * interface to image/bmp content handler initialisation.
*/
-#ifndef _NETSURF_IMAGE_BMP_H_
-#define _NETSURF_IMAGE_BMP_H_
-
-#include <libnsbmp.h>
-
-extern bmp_bitmap_callback_vt bmp_bitmap_callbacks; /** Only to be used by ICO code. */
+#ifndef NETSURF_IMAGE_BMP_H_
+#define NETSURF_IMAGE_BMP_H_
nserror nsbmp_init(void);
diff --git a/content/handlers/image/gif.c b/content/handlers/image/gif.c
index 253265caa..4671d1df5 100644
--- a/content/handlers/image/gif.c
+++ b/content/handlers/image/gif.c
@@ -34,8 +34,12 @@
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
-#include <libnsgif.h>
+#include <nsutils/assert.h>
+
+#include <nsgif.h>
+
+#include "utils/log.h"
#include "utils/utils.h"
#include "utils/messages.h"
#include "utils/nsoption.h"
@@ -43,19 +47,37 @@
#include "netsurf/bitmap.h"
#include "netsurf/content.h"
#include "content/llcache.h"
+#include "content/content.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
#include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
#include "image/image.h"
#include "image/gif.h"
-typedef struct nsgif_content {
+typedef struct gif_content {
struct content base;
- struct gif_animation *gif; /**< GIF animation data */
- int current_frame; /**< current frame to display [0...(max-1)] */
-} nsgif_content;
+ nsgif_t *gif; /**< GIF animation data */
+ uint32_t current_frame; /**< current frame to display [0...(max-1)] */
+} gif_content;
+static inline nserror gif__nsgif_error_to_ns(nsgif_error gif_res)
+{
+ nserror err;
+
+ switch (gif_res) {
+ case NSGIF_ERR_OOM:
+ err = NSERROR_NOMEM;
+ break;
+ default:
+ err = NSERROR_GIF_ERROR;
+ break;
+ }
+
+ return err;
+}
/**
* Callback for libnsgif; forwards the call to bitmap_create()
@@ -64,44 +86,60 @@ typedef struct nsgif_content {
* \param height width of image in pixels
* \return an opaque struct bitmap, or NULL on memory exhaustion
*/
-static void *nsgif_bitmap_create(int width, int height)
+static void *gif_bitmap_create(int width, int height)
{
- return guit->bitmap->create(width, height, BITMAP_NEW);
+ return guit->bitmap->create(width, height, BITMAP_NONE);
}
+/**
+ * Convert client bitmap format to a LibNSGIF format specifier.
+ */
+static nsgif_bitmap_fmt_t nsgif__get_bitmap_format(void)
+{
+ ns_static_assert((int)BITMAP_LAYOUT_R8G8B8A8 == (int)NSGIF_BITMAP_FMT_R8G8B8A8);
+ ns_static_assert((int)BITMAP_LAYOUT_B8G8R8A8 == (int)NSGIF_BITMAP_FMT_B8G8R8A8);
+ ns_static_assert((int)BITMAP_LAYOUT_A8R8G8B8 == (int)NSGIF_BITMAP_FMT_A8R8G8B8);
+ ns_static_assert((int)BITMAP_LAYOUT_A8B8G8R8 == (int)NSGIF_BITMAP_FMT_A8B8G8R8);
+ ns_static_assert((int)BITMAP_LAYOUT_RGBA8888 == (int)NSGIF_BITMAP_FMT_RGBA8888);
+ ns_static_assert((int)BITMAP_LAYOUT_BGRA8888 == (int)NSGIF_BITMAP_FMT_BGRA8888);
+ ns_static_assert((int)BITMAP_LAYOUT_ARGB8888 == (int)NSGIF_BITMAP_FMT_ARGB8888);
+ ns_static_assert((int)BITMAP_LAYOUT_ABGR8888 == (int)NSGIF_BITMAP_FMT_ABGR8888);
+
+ return (nsgif_bitmap_fmt_t)bitmap_fmt.layout;
+}
-static nserror nsgif_create_gif_data(nsgif_content *c)
+static nserror gif_create_gif_data(gif_content *c)
{
- gif_bitmap_callback_vt gif_bitmap_callbacks = {
- .bitmap_create = nsgif_bitmap_create,
- .bitmap_destroy = guit->bitmap->destroy,
- .bitmap_get_buffer = guit->bitmap->get_buffer,
- .bitmap_set_opaque = guit->bitmap->set_opaque,
- .bitmap_test_opaque = guit->bitmap->test_opaque,
- .bitmap_modified = guit->bitmap->modified
+ nsgif_error gif_res;
+ const nsgif_bitmap_cb_vt gif_bitmap_callbacks = {
+ .create = gif_bitmap_create,
+ .destroy = guit->bitmap->destroy,
+ .get_buffer = guit->bitmap->get_buffer,
+ .set_opaque = guit->bitmap->set_opaque,
+ .test_opaque = bitmap_test_opaque,
+ .modified = guit->bitmap->modified,
};
- /* Initialise our data structure */
- c->gif = calloc(sizeof(gif_animation), 1);
- if (c->gif == NULL) {
- content_broadcast_errorcode(&c->base, NSERROR_NOMEM);
- return NSERROR_NOMEM;
+ gif_res = nsgif_create(&gif_bitmap_callbacks,
+ nsgif__get_bitmap_format(), &c->gif);
+ if (gif_res != NSGIF_OK) {
+ nserror err = gif__nsgif_error_to_ns(gif_res);
+ content_broadcast_error(&c->base, err, NULL);
+ return err;
}
- gif_create(c->gif, &gif_bitmap_callbacks);
+
return NSERROR_OK;
}
-
-
-static nserror nsgif_create(const content_handler *handler,
- lwc_string *imime_type, const struct http_parameter *params,
+static nserror gif_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
llcache_handle *llcache, const char *fallback_charset,
bool quirks, struct content **c)
{
- nsgif_content *result;
+ gif_content *result;
nserror error;
- result = calloc(1, sizeof(nsgif_content));
+ result = calloc(1, sizeof(gif_content));
if (result == NULL)
return NSERROR_NOMEM;
@@ -112,7 +150,7 @@ static nserror nsgif_create(const content_handler *handler,
return error;
}
- error = nsgif_create_gif_data(result);
+ error = gif_create_gif_data(result);
if (error != NSERROR_OK) {
free(result);
return error;
@@ -124,157 +162,98 @@ static nserror nsgif_create(const content_handler *handler,
}
/**
+ * Scheduler callback. Performs any necessary animation.
+ *
+ * \param p The content to animate
+*/
+static void gif_animate_cb(void *p);
+
+/**
* Performs any necessary animation.
*
* \param p The content to animate
*/
-static void nsgif_animate(void *p)
+static nserror gif__animate(gif_content *gif, bool redraw)
{
- nsgif_content *gif = p;
- union content_msg_data data;
- int delay;
- int f;
-
- /* Advance by a frame, updating the loop count accordingly */
- gif->current_frame++;
- if (gif->current_frame == (int)gif->gif->frame_count_partial) {
- gif->current_frame = 0;
-
- /* A loop count of 0 has a special meaning of infinite */
- if (gif->gif->loop_count != 0) {
- gif->gif->loop_count--;
- if (gif->gif->loop_count == 0) {
- gif->current_frame =
- gif->gif->frame_count_partial - 1;
- gif->gif->loop_count = -1;
- }
- }
+ nsgif_error gif_res;
+ nsgif_rect_t rect;
+ uint32_t delay;
+ uint32_t f;
+
+ gif_res = nsgif_frame_prepare(gif->gif, &rect, &delay, &f);
+ if (gif_res != NSGIF_OK) {
+ return gif__nsgif_error_to_ns(gif_res);
}
+ gif->current_frame = f;
+
/* Continue animating if we should */
- if (gif->gif->loop_count >= 0) {
- delay = gif->gif->frames[gif->current_frame].frame_delay;
- if (delay < nsoption_int(minimum_gif_delay))
- delay = nsoption_int(minimum_gif_delay);
- guit->misc->schedule(delay * 10, nsgif_animate, gif);
+ if (nsoption_bool(animate_images) && delay != NSGIF_INFINITE) {
+ guit->misc->schedule(delay * 10, gif_animate_cb, gif);
}
- if ((!nsoption_bool(animate_images)) ||
- (!gif->gif->frames[gif->current_frame].display)) {
- return;
- }
+ if (redraw) {
+ union content_msg_data data;
- /* area within gif to redraw */
- f = gif->current_frame;
- data.redraw.x = gif->gif->frames[f].redraw_x;
- data.redraw.y = gif->gif->frames[f].redraw_y;
- data.redraw.width = gif->gif->frames[f].redraw_width;
- data.redraw.height = gif->gif->frames[f].redraw_height;
-
- /* redraw background (true) or plot on top (false) */
- if (gif->current_frame > 0) {
- data.redraw.full_redraw =
- gif->gif->frames[f - 1].redraw_required;
- /* previous frame needed clearing: expand the redraw area to
- * cover it */
- if (data.redraw.full_redraw) {
- if (data.redraw.x >
- (int)(gif->gif->frames[f - 1].redraw_x)) {
- data.redraw.width += data.redraw.x -
- gif->gif->frames[f - 1].redraw_x;
- data.redraw.x =
- gif->gif->frames[f - 1].redraw_x;
- }
- if (data.redraw.y >
- (int)(gif->gif->frames[f - 1].redraw_y)) {
- data.redraw.height += (data.redraw.y -
- gif->gif->frames[f - 1].redraw_y);
- data.redraw.y =
- gif->gif->frames[f - 1].redraw_y;
- }
- if ((int)(gif->gif->frames[f - 1].redraw_x +
- gif->gif->frames[f - 1].redraw_width) >
- (data.redraw.x + data.redraw.width))
- data.redraw.width =
- gif->gif->frames[f - 1].redraw_x -
- data.redraw.x +
- gif->gif->frames[f - 1].redraw_width;
- if ((int)(gif->gif->frames[f - 1].redraw_y +
- gif->gif->frames[f - 1].redraw_height) >
- (data.redraw.y + data.redraw.height))
- data.redraw.height =
- gif->gif->frames[f - 1].redraw_y -
- data.redraw.y +
- gif->gif->frames[f - 1].redraw_height;
- }
- } else {
- /* do advanced check */
- if ((data.redraw.x == 0) && (data.redraw.y == 0) &&
- (data.redraw.width == (int)(gif->gif->width)) &&
- (data.redraw.height == (int)(gif->gif->height))) {
- data.redraw.full_redraw = !gif->gif->frames[f].opaque;
- } else {
- data.redraw.full_redraw = true;
- data.redraw.x = 0;
- data.redraw.y = 0;
- data.redraw.width = gif->gif->width;
- data.redraw.height = gif->gif->height;
- }
+ /* area within gif to redraw */
+ data.redraw.x = rect.x0;
+ data.redraw.y = rect.y0;
+ data.redraw.width = rect.x1 - rect.x0;
+ data.redraw.height = rect.y1 - rect.y0;
+
+ content_broadcast(&gif->base, CONTENT_MSG_REDRAW, &data);
}
- /* other data */
- data.redraw.object = (struct content *) gif;
- data.redraw.object_x = 0;
- data.redraw.object_y = 0;
- data.redraw.object_width = gif->base.width;
- data.redraw.object_height = gif->base.height;
+ return NSERROR_OK;
+}
- content_broadcast(&gif->base, CONTENT_MSG_REDRAW, &data);
+static void gif_animate_cb(void *p)
+{
+ gif_content *gif = p;
+
+ gif__animate(gif, true);
}
-static bool nsgif_convert(struct content *c)
+static bool gif_convert(struct content *c)
{
- nsgif_content *gif = (nsgif_content *) c;
- int res;
- const char *data;
- unsigned long size;
+ gif_content *gif = (gif_content *) c;
+ const nsgif_info_t *gif_info;
+ const uint8_t *data;
+ nsgif_error gif_err;
+ nserror err;
+ size_t size;
char *title;
/* Get the animation */
data = content__get_source_data(c, &size);
/* Initialise the GIF */
- do {
- res = gif_initialise(gif->gif, size, (unsigned char *) data);
- if (res != GIF_OK && res != GIF_WORKING &&
- res != GIF_INSUFFICIENT_FRAME_DATA) {
- nserror error = NSERROR_UNKNOWN;
- switch (res) {
- case GIF_FRAME_DATA_ERROR:
- case GIF_INSUFFICIENT_DATA:
- case GIF_DATA_ERROR:
- error = NSERROR_GIF_ERROR;
- break;
- case GIF_INSUFFICIENT_MEMORY:
- error = NSERROR_NOMEM;
- break;
- }
- content_broadcast_errorcode(c, error);
- return false;
- }
- } while (res != GIF_OK && res != GIF_INSUFFICIENT_FRAME_DATA);
+ gif_err = nsgif_data_scan(gif->gif, size, data);
+ if (gif_err != NSGIF_OK) {
+ NSLOG(netsurf, INFO, "nsgif scan: %s", nsgif_strerror(gif_err));
+ /* Not fatal unless we have no frames. */
+ }
+
+ nsgif_data_complete(gif->gif);
+
+ gif_info = nsgif_get_info(gif->gif);
+ assert(gif_info != NULL);
/* Abort on bad GIFs */
- if ((gif->gif->frame_count_partial == 0) || (gif->gif->width == 0) ||
- (gif->gif->height == 0)) {
- content_broadcast_errorcode(c, NSERROR_GIF_ERROR);
+ if (gif_info->frame_count == 0) {
+ err = gif__nsgif_error_to_ns(gif_err);
+ content_broadcast_error(c, err, "GIF with no frames.");
+ return false;
+ } else if (gif_info->width == 0 || gif_info->height == 0) {
+ err = gif__nsgif_error_to_ns(gif_err);
+ content_broadcast_error(c, err, "Zero size image.");
return false;
}
/* Store our content width, height and calculate size */
- c->width = gif->gif->width;
- c->height = gif->gif->height;
- c->size += (gif->gif->width * gif->gif->height * 4) + 16 + 44;
+ c->width = gif_info->width;
+ c->height = gif_info->height;
+ c->size += (gif_info->width * gif_info->height * 4) + 16 + 44;
/* set title text */
title = messages_get_buff("GIFTitle",
@@ -285,12 +264,11 @@ static bool nsgif_convert(struct content *c)
free(title);
}
- /* Schedule the animation if we have one */
- gif->current_frame = 0;
- if (gif->gif->frame_count_partial > 1)
- guit->misc->schedule(gif->gif->frames[0].frame_delay * 10,
- nsgif_animate,
- c);
+ err = gif__animate(gif, false);
+ if (err != NSERROR_OK) {
+ content_broadcast_error(c, NSERROR_GIF_ERROR, NULL);
+ return false;
+ }
/* Exit as a success */
content_set_ready(c);
@@ -301,68 +279,51 @@ static bool nsgif_convert(struct content *c)
return true;
}
-
/**
* Updates the GIF bitmap to display the current frame
*
* \param gif The gif context to update.
- * \return GIF_OK on success else apropriate error code.
+ * \return NSGIF_OK on success else apropriate error code.
*/
-static gif_result nsgif_get_frame(nsgif_content *gif)
+static nsgif_error gif_get_frame(gif_content *gif,
+ nsgif_bitmap_t **bitmap)
{
- int previous_frame, current_frame, frame;
- gif_result res = GIF_OK;
-
- current_frame = gif->current_frame;
+ uint32_t current_frame = gif->current_frame;
if (!nsoption_bool(animate_images)) {
current_frame = 0;
}
- if (current_frame < gif->gif->decoded_frame) {
- previous_frame = 0;
- } else {
- previous_frame = gif->gif->decoded_frame + 1;
- }
-
- for (frame = previous_frame; frame <= current_frame; frame++) {
- res = gif_decode_frame(gif->gif, frame);
- }
-
- return res;
+ return nsgif_frame_decode(gif->gif, current_frame, bitmap);
}
-static bool nsgif_redraw(struct content *c, struct content_redraw_data *data,
+static bool gif_redraw(struct content *c, struct content_redraw_data *data,
const struct rect *clip, const struct redraw_context *ctx)
{
- nsgif_content *gif = (nsgif_content *) c;
+ gif_content *gif = (gif_content *) c;
+ nsgif_bitmap_t *bitmap;
- if (gif->current_frame != gif->gif->decoded_frame) {
- if (nsgif_get_frame(gif) != GIF_OK) {
- return false;
- }
+ if (gif_get_frame(gif, &bitmap) != NSGIF_OK) {
+ return false;
}
- return image_bitmap_plot(gif->gif->frame_image, data, clip, ctx);
+ return image_bitmap_plot(bitmap, data, clip, ctx);
}
-
-static void nsgif_destroy(struct content *c)
+static void gif_destroy(struct content *c)
{
- nsgif_content *gif = (nsgif_content *) c;
+ gif_content *gif = (gif_content *) c;
/* Free all the associated memory buffers */
- guit->misc->schedule(-1, nsgif_animate, c);
- gif_finalise(gif->gif);
- free(gif->gif);
+ guit->misc->schedule(-1, gif_animate_cb, c);
+ nsgif_destroy(gif->gif);
}
-
-static nserror nsgif_clone(const struct content *old, struct content **newc)
+static nserror gif_clone(const struct content *old, struct content **newc)
{
- nsgif_content *gif;
+ gif_content *gif;
nserror error;
- gif = calloc(1, sizeof(nsgif_content));
+ gif = calloc(1, sizeof(gif_content));
if (gif == NULL)
return NSERROR_NOMEM;
@@ -373,7 +334,7 @@ static nserror nsgif_clone(const struct content *old, struct content **newc)
}
/* Simply replay creation and conversion of content */
- error = nsgif_create_gif_data(gif);
+ error = gif_create_gif_data(gif);
if (error != NSERROR_OK) {
content_destroy(&gif->base);
return error;
@@ -381,7 +342,7 @@ static nserror nsgif_clone(const struct content *old, struct content **newc)
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (nsgif_convert(&gif->base) == false) {
+ if (gif_convert(&gif->base) == false) {
content_destroy(&gif->base);
return NSERROR_CLONE_FAILED;
}
@@ -392,9 +353,9 @@ static nserror nsgif_clone(const struct content *old, struct content **newc)
return NSERROR_OK;
}
-static void nsgif_add_user(struct content *c)
+static void gif_add_user(struct content *c)
{
- nsgif_content *gif = (nsgif_content *) c;
+ gif_content *gif = (gif_content *) c;
/* Ensure this content has already been converted.
* If it hasn't, the animation will start at the conversion phase instead. */
@@ -402,53 +363,66 @@ static void nsgif_add_user(struct content *c)
if (content_count_users(c) == 1) {
/* First user, and content already converted, so start the animation. */
- if (gif->gif->frame_count_partial > 1) {
- guit->misc->schedule(gif->gif->frames[0].frame_delay * 10,
- nsgif_animate, c);
+ if (nsgif_reset(gif->gif) == NSGIF_OK) {
+ gif__animate(gif, true);
}
}
}
-static void nsgif_remove_user(struct content *c)
+static void gif_remove_user(struct content *c)
{
if (content_count_users(c) == 1) {
/* Last user is about to be removed from this content, so stop the animation. */
- guit->misc->schedule(-1, nsgif_animate, c);
+ guit->misc->schedule(-1, gif_animate_cb, c);
}
}
-static void *nsgif_get_internal(const struct content *c, void *context)
+static nsgif_bitmap_t *gif_get_bitmap(
+ const struct content *c, void *context)
{
- nsgif_content *gif = (nsgif_content *) c;
+ gif_content *gif = (gif_content *) c;
+ nsgif_bitmap_t *bitmap;
- if (gif->current_frame != gif->gif->decoded_frame) {
- if (nsgif_get_frame(gif) != GIF_OK)
- return NULL;
+ if (gif_get_frame(gif, &bitmap) != NSGIF_OK) {
+ return NULL;
}
- return gif->gif->frame_image;
+ return bitmap;
}
-static content_type nsgif_content_type(void)
+static content_type gif_content_type(void)
{
return CONTENT_IMAGE;
}
-static const content_handler nsgif_content_handler = {
- .create = nsgif_create,
- .data_complete = nsgif_convert,
- .destroy = nsgif_destroy,
- .redraw = nsgif_redraw,
- .clone = nsgif_clone,
- .add_user = nsgif_add_user,
- .remove_user = nsgif_remove_user,
- .get_internal = nsgif_get_internal,
- .type = nsgif_content_type,
+static bool gif_content_is_opaque(struct content *c)
+{
+ gif_content *gif = (gif_content *) c;
+ nsgif_bitmap_t *bitmap;
+
+ if (gif_get_frame(gif, &bitmap) != NSGIF_OK) {
+ return false;
+ }
+
+ return guit->bitmap->get_opaque(bitmap);
+}
+
+static const content_handler gif_content_handler = {
+ .create = gif_create,
+ .data_complete = gif_convert,
+ .destroy = gif_destroy,
+ .redraw = gif_redraw,
+ .clone = gif_clone,
+ .add_user = gif_add_user,
+ .remove_user = gif_remove_user,
+ .get_internal = gif_get_bitmap,
+ .type = gif_content_type,
+ .is_opaque = gif_content_is_opaque,
.no_share = false,
};
-static const char *nsgif_types[] = {
+static const char *gif_types[] = {
"image/gif"
};
-CONTENT_FACTORY_REGISTER_TYPES(nsgif, nsgif_types, nsgif_content_handler);
+CONTENT_FACTORY_REGISTER_TYPES(nsgif, gif_types, gif_content_handler);
diff --git a/content/handlers/image/ico.c b/content/handlers/image/ico.c
index 85aab9f64..871da41a9 100644
--- a/content/handlers/image/ico.c
+++ b/content/handlers/image/ico.c
@@ -16,8 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Content for image/ico (implementation)
+/**
+ * \file
+ * implementation for image/ico content handler
*/
#include <stdbool.h>
@@ -31,7 +32,9 @@
#include "netsurf/content.h"
#include "content/llcache.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
#include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
#include "image/image.h"
#include "image/ico.h"
@@ -39,8 +42,7 @@
typedef struct nsico_content {
struct content base;
- struct ico_collection *ico; /** ICO collection data */
-
+ struct ico_collection *ico; /** ICO collection data */
} nsico_content;
/**
@@ -53,12 +55,12 @@ typedef struct nsico_content {
*/
static void *nsico_bitmap_create(int width, int height, unsigned int bmp_state)
{
- unsigned int bitmap_state = BITMAP_NEW;
+ unsigned int bitmap_state = BITMAP_NONE;
/* set bitmap state based on bmp state */
bitmap_state |= (bmp_state & BMP_OPAQUE) ? BITMAP_OPAQUE : 0;
bitmap_state |= (bmp_state & BMP_CLEAR_MEMORY) ?
- BITMAP_CLEAR_MEMORY : 0;
+ BITMAP_CLEAR : 0;
/* return the created bitmap */
return guit->bitmap->create(width, height, bitmap_state);
@@ -70,12 +72,11 @@ static nserror nsico_create_ico_data(nsico_content *c)
.bitmap_create = nsico_bitmap_create,
.bitmap_destroy = guit->bitmap->destroy,
.bitmap_get_buffer = guit->bitmap->get_buffer,
- .bitmap_get_bpp = guit->bitmap->get_bpp
};
c->ico = calloc(sizeof(ico_collection), 1);
if (c->ico == NULL) {
- content_broadcast_errorcode(&c->base, NSERROR_NOMEM);
+ content_broadcast_error(&c->base, NSERROR_NOMEM, NULL);
return NSERROR_NOMEM;
}
ico_collection_create(c->ico, &bmp_bitmap_callbacks);
@@ -83,7 +84,7 @@ static nserror nsico_create_ico_data(nsico_content *c)
}
-static nserror nsico_create(const content_handler *handler,
+static nserror nsico_create(const content_handler *handler,
lwc_string *imime_type, const struct http_parameter *params,
llcache_handle *llcache, const char *fallback_charset,
bool quirks, struct content **c)
@@ -120,8 +121,8 @@ static bool nsico_convert(struct content *c)
nsico_content *ico = (nsico_content *) c;
struct bmp_image *bmp;
bmp_result res;
- const char *data;
- unsigned long size;
+ const uint8_t *data;
+ size_t size;
char *title;
/* set the ico data */
@@ -134,11 +135,11 @@ static bool nsico_convert(struct content *c)
case BMP_OK:
break;
case BMP_INSUFFICIENT_MEMORY:
- content_broadcast_errorcode(c, NSERROR_NOMEM);
+ content_broadcast_error(c, NSERROR_NOMEM, NULL);
return false;
case BMP_INSUFFICIENT_DATA:
case BMP_DATA_ERROR:
- content_broadcast_errorcode(c, NSERROR_ICO_ERROR);
+ content_broadcast_error(c, NSERROR_ICO_ERROR, NULL);
return false;
}
@@ -172,6 +173,23 @@ static bool nsico_convert(struct content *c)
return true;
}
+static bool nsico__decode(struct bmp_image *ico)
+{
+ if (ico->decoded == false) {
+ NSLOG(netsurf, DEBUG, "Decoding ICO %p", ico);
+ if (bmp_decode(ico) != BMP_OK) {
+ return false;
+ }
+
+ bitmap_format_to_client(ico->bitmap, &(bitmap_fmt_t) {
+ .layout = BITMAP_LAYOUT_R8G8B8A8,
+ });
+ guit->bitmap->modified(ico->bitmap);
+
+ }
+
+ return true;
+}
static bool nsico_redraw(struct content *c, struct content_redraw_data *data,
const struct rect *clip, const struct redraw_context *ctx)
@@ -188,14 +206,8 @@ static bool nsico_redraw(struct content *c, struct content_redraw_data *data,
}
/* ensure its decided */
- if (bmp->decoded == false) {
- if (bmp_decode(bmp) != BMP_OK) {
- return false;
- } else {
- NSLOG(netsurf, INFO, "Decoding bitmap");
- guit->bitmap->modified(bmp->bitmap);
- }
-
+ if (!nsico__decode(bmp)) {
+ return false;
}
return image_bitmap_plot(bmp->bitmap, data, clip, ctx);
@@ -250,7 +262,7 @@ static void *nsico_get_internal(const struct content *c, void *context)
nsico_content *ico = (nsico_content *) c;
/* TODO: Pick best size for purpose.
* Currently assumes it's for a URL bar. */
- struct bmp_image *bmp;
+ struct bmp_image *bmp;
bmp = ico_find(ico->ico, 16, 16);
if (bmp == NULL) {
@@ -259,12 +271,8 @@ static void *nsico_get_internal(const struct content *c, void *context)
return NULL;
}
- if (bmp->decoded == false) {
- if (bmp_decode(bmp) != BMP_OK) {
- return NULL;
- } else {
- guit->bitmap->modified(bmp->bitmap);
- }
+ if (!nsico__decode(bmp)) {
+ return NULL;
}
return bmp->bitmap;
@@ -275,6 +283,29 @@ static content_type nsico_content_type(void)
return CONTENT_IMAGE;
}
+static bool nsico_is_opaque(struct content *c)
+{
+ nsico_content *ico = (nsico_content *) c;
+ struct bmp_image *bmp;
+
+ /**
+ * \todo Pick best size for purpose. Currently assumes
+ * it's for a URL bar.
+ */
+ bmp = ico_find(ico->ico, 16, 16);
+ if (bmp == NULL) {
+ /* return error */
+ NSLOG(netsurf, INFO, "Failed to select icon");
+ return false;
+ }
+
+ if (!nsico__decode(bmp)) {
+ return false;
+ }
+
+ return guit->bitmap->get_opaque(bmp->bitmap);
+}
+
static const content_handler nsico_content_handler = {
.create = nsico_create,
.data_complete = nsico_convert,
@@ -283,6 +314,7 @@ static const content_handler nsico_content_handler = {
.clone = nsico_clone,
.get_internal = nsico_get_internal,
.type = nsico_content_type,
+ .is_opaque = nsico_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/image.c b/content/handlers/image/image.c
index 675fdd691..2bd5f5f8d 100644
--- a/content/handlers/image/image.c
+++ b/content/handlers/image/image.c
@@ -26,15 +26,18 @@
#include "netsurf/bitmap.h"
#include "netsurf/content.h"
#include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
#include "image/bmp.h"
#include "image/gif.h"
#include "image/ico.h"
#include "image/jpeg.h"
+#include "image/jpegxl.h"
#include "image/nssprite.h"
#include "image/png.h"
#include "image/rsvg.h"
#include "image/svg.h"
+#include "image/webp.h"
#include "image/image.h"
/**
@@ -70,6 +73,12 @@ nserror image_init(void)
return error;
#endif
+#ifdef WITH_JPEGXL
+ error = nsjpegxl_init();
+ if (error != NSERROR_OK)
+ return error;
+#endif
+
#ifdef WITH_PNG
error = nspng_init();
if (error != NSERROR_OK)
@@ -94,6 +103,12 @@ nserror image_init(void)
return error;
#endif
+#ifdef WITH_WEBP
+ error = nswebp_init();
+ if (error != NSERROR_OK)
+ return error;
+#endif
+
return error;
}
@@ -117,7 +132,7 @@ bool image_bitmap_plot(struct bitmap *bitmap,
if (height == 1) {
/* optimise 1x1 bitmap plot */
pixel = guit->bitmap->get_buffer(bitmap);
- fill_style.fill_colour = pixel_to_colour(pixel);
+ fill_style.fill_colour = bitmap_pixel_to_colour(pixel);
if (guit->bitmap->get_opaque(bitmap) ||
((fill_style.fill_colour & 0xff000000) == 0xff000000)) {
diff --git a/content/handlers/image/image_cache.c b/content/handlers/image/image_cache.c
index a1de01da5..8f7ff89ff 100644
--- a/content/handlers/image/image_cache.c
+++ b/content/handlers/image/image_cache.c
@@ -438,6 +438,7 @@ image_cache_init(const struct image_cache_parameters *image_cache_parameters)
nserror image_cache_fini(void)
{
unsigned int op_count;
+ uint64_t op_size;
guit->misc->schedule(-1, image_cache__background_update, image_cache);
@@ -452,6 +453,10 @@ nserror image_cache_fini(void)
image_cache->miss_count +
image_cache->fail_count;
+ op_size = image_cache->hit_size +
+ image_cache->miss_size +
+ image_cache->fail_size;
+
NSLOG(netsurf, INFO, "Age %ds", image_cache->current_age / 1000);
NSLOG(netsurf, INFO, "Peak size %"PRIsizet" (in %d)",
image_cache->max_bitmap_size,
@@ -460,12 +465,7 @@ nserror image_cache_fini(void)
image_cache->max_bitmap_count,
image_cache->max_bitmap_count_size);
- if (op_count > 0) {
- uint64_t op_size;
-
- op_size = image_cache->hit_size +
- image_cache->miss_size +
- image_cache->fail_size;
+ if ((op_count > 0) && (op_size >0)) {
NSLOG(netsurf, INFO,
"Cache total/hit/miss/fail (counts) %d/%d/%d/%d (100%%/%d%%/%d%%/%d%%)",
@@ -528,7 +528,7 @@ nserror image_cache_add(struct content *content,
image_cache__link(centry);
centry->content = content;
- centry->bitmap_size = content->width * content->height * 4;
+ centry->bitmap_size = content->width * content->height * 4llu;
}
NSLOG(netsurf, INFO, "centry %p, content %p, bitmap %p", centry,
@@ -632,15 +632,15 @@ case chr : \
slen++;
break;
- FMTCHR('a', PRIssizet, params.limit);
- FMTCHR('b', PRIssizet, params.hysteresis);
- FMTCHR('c', PRIssizet, total_bitmap_size);
+ FMTCHR('a', PRIsizet, params.limit);
+ FMTCHR('b', PRIsizet, params.hysteresis);
+ FMTCHR('c', PRIsizet, total_bitmap_size);
FMTCHR('d', "d", bitmap_count);
FMTCHR('e', "u", current_age / 1000);
- FMTCHR('f', PRIssizet, max_bitmap_size);
+ FMTCHR('f', PRIsizet, max_bitmap_size);
FMTCHR('g', "d", max_bitmap_size_count);
FMTCHR('h', "d", max_bitmap_count);
- FMTCHR('i', PRIssizet, max_bitmap_count_size);
+ FMTCHR('i', PRIsizet, max_bitmap_count_size);
case 'j':
@@ -770,7 +770,7 @@ image_cache_snentryf(char *string,
if (centry->bitmap != NULL) {
slen += snprintf(string + slen,
size - slen,
- "%" PRIssizet,
+ "%" PRIsizet,
centry->bitmap_size);
} else {
slen += snprintf(string + slen,
@@ -859,6 +859,17 @@ void *image_cache_get_internal(const struct content *c, void *context)
}
/* exported interface documented in image_cache.h */
+bool image_cache_is_opaque(struct content *c)
+{
+ struct bitmap *bmp;
+ bmp = image_cache_get_bitmap(c);
+ if (bmp != NULL) {
+ return guit->bitmap->get_opaque(bmp);
+ }
+ return false;
+}
+
+/* exported interface documented in image_cache.h */
content_type image_cache_content_type(void)
{
return CONTENT_IMAGE;
diff --git a/content/handlers/image/image_cache.h b/content/handlers/image/image_cache.h
index d57a3a956..1c2d621a6 100644
--- a/content/handlers/image/image_cache.h
+++ b/content/handlers/image/image_cache.h
@@ -40,6 +40,7 @@
#include "utils/errors.h"
#include "netsurf/content_type.h"
+struct content;
struct content_redraw_data;
struct redraw_context;
@@ -170,7 +171,8 @@ int image_cache_snsummaryf(char *string, size_t size, const char *fmt);
/********* Image content handler generic cache callbacks ************/
-/** Generic content redraw callback
+/**
+ * Generic content redraw callback
*
* May be used by image content handlers as their redraw
* callback. Performs all neccissary cache lookups and conversions and
@@ -185,6 +187,8 @@ void image_cache_destroy(struct content *c);
void *image_cache_get_internal(const struct content *c, void *context);
+bool image_cache_is_opaque(struct content *c);
+
content_type image_cache_content_type(void);
#endif
diff --git a/content/handlers/image/jpeg.c b/content/handlers/image/jpeg.c
index 123a0bf70..93372f15a 100644
--- a/content/handlers/image/jpeg.c
+++ b/content/handlers/image/jpeg.c
@@ -17,8 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Content for image/jpeg (implementation).
+/**
+ * \file
+ * implementation of content handling for image/jpeg
*
* This implementation uses the IJG JPEG library.
*/
@@ -32,8 +33,11 @@
#include "utils/messages.h"
#include "netsurf/bitmap.h"
#include "content/llcache.h"
+#include "content/content.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
#include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
#include "image/image_cache.h"
@@ -46,13 +50,8 @@
*/
#define MIN_JPEG_SIZE 20
-#ifdef riscos
-/* We prefer the library to be configured with these options to save
- * copying data during decoding. */
-#if RGB_RED != 0 || RGB_GREEN != 1 || RGB_BLUE != 2 || RGB_PIXELSIZE != 4
-#warning JPEG library not optimally configured. Decoding will be slower.
-#endif
-/* but we don't care if we're not on RISC OS */
+#ifndef LIBJPEG_TURBO_VERSION
+#warning Using libjpeg (libjpeg-turbo is recommended)
#endif
static char nsjpeg_error_buffer[JMSG_LENGTH_MAX];
@@ -161,16 +160,107 @@ static void nsjpeg_error_exit(j_common_ptr cinfo)
longjmp(*setjmp_buffer, 1);
}
+/**
+ * Convert scan lines from CMYK to core client bitmap layout.
+ */
+static inline void nsjpeg__decode_cmyk(
+ struct jpeg_decompress_struct *cinfo,
+ uint8_t * volatile pixels,
+ size_t rowstride)
+{
+ int width = cinfo->output_width * 4;
+
+ do {
+ JSAMPROW scanlines[1] = {
+ [0] = (JSAMPROW)
+ (pixels + rowstride * cinfo->output_scanline),
+ };
+ jpeg_read_scanlines(cinfo, scanlines, 1);
+
+ for (int i = width - 4; 0 <= i; i -= 4) {
+ /* Trivial inverse CMYK -> RGBA */
+ const int c = scanlines[0][i + 0];
+ const int m = scanlines[0][i + 1];
+ const int y = scanlines[0][i + 2];
+ const int k = scanlines[0][i + 3];
+
+ const int ck = c * k;
+ const int mk = m * k;
+ const int yk = y * k;
+
+#define DIV255(x) ((x) + 1 + ((x) >> 8)) >> 8
+ scanlines[0][i + bitmap_layout.r] = DIV255(ck);
+ scanlines[0][i + bitmap_layout.g] = DIV255(mk);
+ scanlines[0][i + bitmap_layout.b] = DIV255(yk);
+ scanlines[0][i + bitmap_layout.a] = 0xff;
+#undef DIV255
+ }
+ } while (cinfo->output_scanline != cinfo->output_height);
+}
+
+/**
+ * Convert scan lines from CMYK to core client bitmap layout.
+ */
+static inline void nsjpeg__decode_rgb(
+ struct jpeg_decompress_struct *cinfo,
+ uint8_t * volatile pixels,
+ size_t rowstride)
+{
+#if RGB_RED != 0 || RGB_GREEN != 1 || RGB_BLUE != 2 || RGB_PIXELSIZE != 4
+ int width = cinfo->output_width;
+#endif
+
+ do {
+ JSAMPROW scanlines[1] = {
+ [0] = (JSAMPROW)
+ (pixels + rowstride * cinfo->output_scanline),
+ };
+ jpeg_read_scanlines(cinfo, scanlines, 1);
+
+#if RGB_RED != 0 || RGB_GREEN != 1 || RGB_BLUE != 2 || RGB_PIXELSIZE != 4
+ /* Missmatch between configured libjpeg pixel format and
+ * NetSurf pixel format. Convert to RGBA */
+ for (int i = width - 1; 0 <= i; i--) {
+ int r = scanlines[0][i * RGB_PIXELSIZE + RGB_RED];
+ int g = scanlines[0][i * RGB_PIXELSIZE + RGB_GREEN];
+ int b = scanlines[0][i * RGB_PIXELSIZE + RGB_BLUE];
+ scanlines[0][i * 4 + bitmap_layout.r] = r;
+ scanlines[0][i * 4 + bitmap_layout.g] = g;
+ scanlines[0][i * 4 + bitmap_layout.b] = b;
+ scanlines[0][i * 4 + bitmap_layout.a] = 0xff;
+ }
+#endif
+ } while (cinfo->output_scanline != cinfo->output_height);
+}
+
+/**
+ * Convert scan lines from CMYK to core client bitmap layout.
+ */
+static inline void nsjpeg__decode_client_fmt(
+ struct jpeg_decompress_struct *cinfo,
+ uint8_t * volatile pixels,
+ size_t rowstride)
+{
+ do {
+ JSAMPROW scanlines[1] = {
+ [0] = (JSAMPROW)
+ (pixels + rowstride * cinfo->output_scanline),
+ };
+ jpeg_read_scanlines(cinfo, scanlines, 1);
+ } while (cinfo->output_scanline != cinfo->output_height);
+}
+
+/**
+ * create a bitmap from jpeg content.
+ */
static struct bitmap *
jpeg_cache_convert(struct content *c)
{
- uint8_t *source_data; /* Jpeg source data */
- unsigned long source_size; /* length of Jpeg source data */
+ const uint8_t *source_data; /* Jpeg source data */
+ size_t source_size; /* length of Jpeg source data */
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
jmp_buf setjmp_buffer;
- unsigned int height;
- unsigned int width;
struct bitmap * volatile bitmap = NULL;
uint8_t * volatile pixels = NULL;
size_t rowstride;
@@ -184,7 +274,7 @@ jpeg_cache_convert(struct content *c)
nsjpeg_term_source };
/* obtain jpeg source data and perfom minimal sanity checks */
- source_data = (uint8_t *)content__get_source_data(c, &source_size);
+ source_data = content__get_source_data(c, &source_size);
if ((source_data == NULL) ||
(source_size < MIN_JPEG_SIZE)) {
@@ -215,21 +305,42 @@ jpeg_cache_convert(struct content *c)
/* set output processing parameters */
if (cinfo.jpeg_color_space == JCS_CMYK ||
- cinfo.jpeg_color_space == JCS_YCCK) {
+ cinfo.jpeg_color_space == JCS_YCCK) {
cinfo.out_color_space = JCS_CMYK;
} else {
+#ifdef JCS_ALPHA_EXTENSIONS
+ switch (bitmap_fmt.layout) {
+ case BITMAP_LAYOUT_R8G8B8A8:
+ cinfo.out_color_space = JCS_EXT_RGBA;
+ break;
+ case BITMAP_LAYOUT_B8G8R8A8:
+ cinfo.out_color_space = JCS_EXT_BGRA;
+ break;
+ case BITMAP_LAYOUT_A8R8G8B8:
+ cinfo.out_color_space = JCS_EXT_ARGB;
+ break;
+ case BITMAP_LAYOUT_A8B8G8R8:
+ cinfo.out_color_space = JCS_EXT_ABGR;
+ break;
+ default:
+ NSLOG(netsurf, ERROR, "Unexpected bitmap format: %u",
+ bitmap_fmt.layout);
+ jpeg_destroy_decompress(&cinfo);
+ return NULL;
+ }
+#else
cinfo.out_color_space = JCS_RGB;
+#endif
}
cinfo.dct_method = JDCT_ISLOW;
/* commence the decompression, output parameters now valid */
jpeg_start_decompress(&cinfo);
- width = cinfo.output_width;
- height = cinfo.output_height;
-
/* create opaque bitmap (jpegs cannot be transparent) */
- bitmap = guit->bitmap->create(width, height, BITMAP_NEW | BITMAP_OPAQUE);
+ bitmap = guit->bitmap->create(
+ cinfo.output_width,
+ cinfo.output_height, BITMAP_OPAQUE);
if (bitmap == NULL) {
/* empty bitmap could not be created */
jpeg_destroy_decompress(&cinfo);
@@ -246,50 +357,21 @@ jpeg_cache_convert(struct content *c)
/* Convert scanlines from jpeg into bitmap */
rowstride = guit->bitmap->get_rowstride(bitmap);
- do {
- JSAMPROW scanlines[1];
- scanlines[0] = (JSAMPROW) (pixels +
- rowstride * cinfo.output_scanline);
- jpeg_read_scanlines(&cinfo, scanlines, 1);
+ switch (cinfo.out_color_space) {
+ case JCS_CMYK:
+ nsjpeg__decode_cmyk(&cinfo, pixels, rowstride);
+ break;
- if (cinfo.out_color_space == JCS_CMYK) {
- int i;
- for (i = width - 1; 0 <= i; i--) {
- /* Trivial inverse CMYK -> RGBA */
- const int c = scanlines[0][i * 4 + 0];
- const int m = scanlines[0][i * 4 + 1];
- const int y = scanlines[0][i * 4 + 2];
- const int k = scanlines[0][i * 4 + 3];
+ case JCS_RGB:
+ nsjpeg__decode_rgb(&cinfo, pixels, rowstride);
+ break;
- const int ck = c * k;
- const int mk = m * k;
- const int yk = y * k;
+ default:
+ nsjpeg__decode_client_fmt(&cinfo, pixels, rowstride);
+ break;
+ }
-#define DIV255(x) ((x) + 1 + ((x) >> 8)) >> 8
- scanlines[0][i * 4 + 0] = DIV255(ck);
- scanlines[0][i * 4 + 1] = DIV255(mk);
- scanlines[0][i * 4 + 2] = DIV255(yk);
- scanlines[0][i * 4 + 3] = 0xff;
-#undef DIV255
- }
- } else {
-#if RGB_RED != 0 || RGB_GREEN != 1 || RGB_BLUE != 2 || RGB_PIXELSIZE != 4
- /* Missmatch between configured libjpeg pixel format and
- * NetSurf pixel format. Convert to RGBA */
- int i;
- for (i = width - 1; 0 <= i; i--) {
- int r = scanlines[0][i * RGB_PIXELSIZE + RGB_RED];
- int g = scanlines[0][i * RGB_PIXELSIZE + RGB_GREEN];
- int b = scanlines[0][i * RGB_PIXELSIZE + RGB_BLUE];
- scanlines[0][i * 4 + 0] = r;
- scanlines[0][i * 4 + 1] = g;
- scanlines[0][i * 4 + 2] = b;
- scanlines[0][i * 4 + 3] = 0xff;
- }
-#endif
- }
- } while (cinfo.output_scanline != cinfo.output_height);
guit->bitmap->modified(bitmap);
jpeg_finish_decompress(&cinfo);
@@ -311,8 +393,8 @@ static bool nsjpeg_convert(struct content *c)
nsjpeg_skip_input_data, jpeg_resync_to_restart,
nsjpeg_term_source };
union content_msg_data msg_data;
- const char *data;
- unsigned long size;
+ const uint8_t *data;
+ size_t size;
char *title;
/* check image header is valid and get width/height */
@@ -325,7 +407,8 @@ static bool nsjpeg_convert(struct content *c)
if (setjmp(setjmp_buffer)) {
jpeg_destroy_decompress(&cinfo);
- msg_data.error = nsjpeg_error_buffer;
+ msg_data.errordata.errorcode = NSERROR_UNKNOWN;
+ msg_data.errordata.errormsg = nsjpeg_error_buffer;
content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
return false;
}
@@ -407,6 +490,7 @@ static const content_handler nsjpeg_content_handler = {
.clone = nsjpeg_clone,
.get_internal = image_cache_get_internal,
.type = image_cache_content_type,
+ .is_opaque = image_cache_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/jpegxl.c b/content/handlers/image/jpegxl.c
new file mode 100644
index 000000000..01c704577
--- /dev/null
+++ b/content/handlers/image/jpegxl.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright 2023 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * implementation of content handling for image/jpegxl
+ *
+ * This implementation uses the JXL library.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <string.h>
+
+#include <jxl/decode.h>
+
+#include "utils/utils.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "netsurf/bitmap.h"
+#include "content/llcache.h"
+#include "content/content.h"
+#include "content/content_protected.h"
+#include "content/content_factory.h"
+#include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
+
+#include "image/image_cache.h"
+
+#include "image/jpegxl.h"
+
+
+/**
+ * output image format
+ */
+static const JxlPixelFormat jxl_output_format = {
+ .num_channels = 4,
+ .data_type = JXL_TYPE_UINT8,
+ .endianness = JXL_LITTLE_ENDIAN,
+ .align = 0,
+};
+
+/**
+ * Content create entry point.
+ */
+static nserror
+nsjpegxl_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ struct content *jpeg;
+ nserror error;
+
+ jpeg = calloc(1, sizeof(struct content));
+ if (jpeg == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(jpeg, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ free(jpeg);
+ return error;
+ }
+
+ *c = jpeg;
+
+ return NSERROR_OK;
+}
+
+/**
+ * create a bitmap from jpeg xl content.
+ */
+static struct bitmap *
+jpegxl_cache_convert(struct content *c)
+{
+ struct bitmap * bitmap = NULL;
+ JxlDecoder *jxldec;
+ JxlDecoderStatus decstatus;
+ JxlBasicInfo binfo;
+ const uint8_t *src_data;
+ size_t src_size;
+ uint8_t * output;
+ bitmap_fmt_t jxl_fmt = {
+ /** TODO: At the moment we have to set the layout to the only
+ * pixel layout that libjxl supports. It looks like they
+ * plan to add support for decoding to other layouts
+ * in the future, as shown by the TODO in the docs:
+ *
+ * https://libjxl.readthedocs.io/en/latest/api_common.html#_CPPv414JxlPixelFormat
+ */
+ .layout = BITMAP_LAYOUT_R8G8B8A8,
+ .pma = bitmap_fmt.pma,
+ };
+
+ jxldec = JxlDecoderCreate(NULL);
+ if (jxldec == NULL) {
+ NSLOG(netsurf, ERROR, "Unable to allocate decoder");
+ return NULL;
+ }
+
+ decstatus = JxlDecoderSetUnpremultiplyAlpha(jxldec, !bitmap_fmt.pma);
+ if (decstatus != JXL_DEC_SUCCESS) {
+ NSLOG(netsurf, ERROR, "unable to set premultiplied alpha status: %d",
+ decstatus);
+ JxlDecoderDestroy(jxldec);
+ return NULL;
+ }
+
+ decstatus= JxlDecoderSubscribeEvents(jxldec, JXL_DEC_FULL_IMAGE);
+ if (decstatus != JXL_DEC_SUCCESS) {
+ NSLOG(netsurf, ERROR, "Unable to subscribe");
+ return NULL;
+ }
+ src_data = content__get_source_data(c, &src_size);
+
+ decstatus = JxlDecoderSetInput(jxldec, src_data, src_size);
+ if (decstatus != JXL_DEC_SUCCESS) {
+ NSLOG(netsurf, ERROR, "unable to set input");
+ return NULL;
+ }
+
+ decstatus = JxlDecoderProcessInput(jxldec);
+ if (decstatus != JXL_DEC_NEED_IMAGE_OUT_BUFFER) {
+ NSLOG(netsurf, ERROR,
+ "expected status JXL_DEC_NEED_IMAGE_OUT_BUFFER(%d) got %d",
+ JXL_DEC_NEED_IMAGE_OUT_BUFFER,
+ decstatus);
+ JxlDecoderDestroy(jxldec);
+ return NULL;
+ }
+
+ decstatus = JxlDecoderGetBasicInfo(jxldec, &binfo);
+ if (decstatus != JXL_DEC_SUCCESS) {
+ NSLOG(netsurf, ERROR, "unable to get basic info status:%d",decstatus);
+ JxlDecoderDestroy(jxldec);
+ return NULL;
+ }
+
+ /* create bitmap with appropriate opacity */
+ if (binfo.alpha_bits > 0) {
+ bitmap = guit->bitmap->create(c->width, c->height, BITMAP_OPAQUE);
+ } else {
+ bitmap = guit->bitmap->create(c->width, c->height, BITMAP_NONE);
+ }
+ if (bitmap == NULL) {
+ /* empty bitmap could not be created */
+ JxlDecoderDestroy(jxldec);
+ return NULL;
+ }
+
+ /* ensure buffer was allocated */
+ output = guit->bitmap->get_buffer(bitmap);
+ if (output == NULL) {
+ /* bitmap with no buffer available */
+ guit->bitmap->destroy(bitmap);
+ JxlDecoderDestroy(jxldec);
+ return NULL;
+ }
+ decstatus = JxlDecoderSetImageOutBuffer(jxldec, &jxl_output_format, output, c->size);
+ if (decstatus != JXL_DEC_SUCCESS) {
+ NSLOG(netsurf, ERROR, "unable to set output buffer callback status:%d",decstatus);
+ guit->bitmap->destroy(bitmap);
+ JxlDecoderDestroy(jxldec);
+ return NULL;
+ }
+
+ decstatus = JxlDecoderProcessInput(jxldec);
+ if (decstatus != JXL_DEC_FULL_IMAGE) {
+ NSLOG(netsurf, ERROR, "did not get decode event");
+ guit->bitmap->destroy(bitmap);
+ JxlDecoderDestroy(jxldec);
+ return NULL;
+ }
+
+ JxlDecoderDestroy(jxldec);
+
+ bitmap_format_to_client(bitmap, &jxl_fmt);
+ guit->bitmap->modified(bitmap);
+
+ return bitmap;
+}
+
+/**
+ * report failiure
+ */
+static bool jxl_report_fail(struct content *c, JxlDecoderStatus decstatus, const char *msg)
+{
+ union content_msg_data msg_data;
+ NSLOG(netsurf, ERROR, "%s decoder status:%d", msg, decstatus);
+ msg_data.errordata.errorcode = NSERROR_UNKNOWN;
+ msg_data.errordata.errormsg = msg;
+ content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
+ return false;
+}
+
+/**
+ * Convert a CONTENT_JPEGXL for display.
+ */
+static bool nsjpegxl_convert(struct content *c)
+{
+ JxlDecoder *jxldec;
+ JxlSignature decsig;
+ JxlDecoderStatus decstatus = JXL_DEC_ERROR;
+ JxlBasicInfo binfo;
+ union content_msg_data msg_data;
+ const uint8_t *data;
+ size_t size;
+ char *title;
+ size_t image_size;
+
+ /* check image header is valid and get width/height */
+ data = content__get_source_data(c, &size);
+
+ decsig = JxlSignatureCheck(data,size);
+ if ((decsig != JXL_SIG_CODESTREAM) && (decsig != JXL_SIG_CONTAINER)) {
+ NSLOG(netsurf, ERROR, "signature failed");
+ msg_data.errordata.errorcode = NSERROR_UNKNOWN;
+ msg_data.errordata.errormsg = "Signature failed";
+ content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
+ return false;
+ }
+
+ jxldec = JxlDecoderCreate(NULL);
+ if (jxldec == NULL) {
+ return jxl_report_fail(c, decstatus, "Unable to allocate decoder");
+ }
+ decstatus= JxlDecoderSubscribeEvents(jxldec, JXL_DEC_BASIC_INFO);
+ if (decstatus != JXL_DEC_SUCCESS) {
+ return jxl_report_fail(c, decstatus, "Unable to subscribe");
+ }
+ decstatus = JxlDecoderSetInput(jxldec, data,size);
+ if (decstatus != JXL_DEC_SUCCESS) {
+ return jxl_report_fail(c, decstatus, "unable to set input");
+ }
+ decstatus = JxlDecoderProcessInput(jxldec);
+ if (decstatus != JXL_DEC_BASIC_INFO) {
+ return jxl_report_fail(c, decstatus, "did not get basic info event");
+ }
+ decstatus = JxlDecoderGetBasicInfo(jxldec, &binfo);
+ if (decstatus != JXL_DEC_SUCCESS) {
+ return jxl_report_fail(c, decstatus, "unable to get basic info");
+ }
+ decstatus = JxlDecoderImageOutBufferSize(jxldec, &jxl_output_format, &image_size);
+ if (decstatus != JXL_DEC_SUCCESS) {
+ return jxl_report_fail(c, decstatus, "unable get image size");
+ }
+
+ JxlDecoderDestroy(jxldec);
+
+ NSLOG(netsurf, INFO, "got basic info size:%ld x:%d y:%d", image_size, binfo.xsize, binfo.ysize);
+
+ c->width = binfo.xsize;
+ c->height = binfo.ysize;
+ c->size = image_size;
+
+ image_cache_add(c, NULL, jpegxl_cache_convert);
+
+ /* set title text */
+ title = messages_get_buff("JPEGXLTitle",
+ nsurl_access_leaf(llcache_handle_get_url(c->llcache)),
+ c->width, c->height);
+ if (title != NULL) {
+ content__set_title(c, title);
+ free(title);
+ }
+
+ content_set_ready(c);
+ content_set_done(c);
+ content_set_status(c, ""); /* Done: update status bar */
+
+ return true;
+}
+
+
+/**
+ * Clone content.
+ */
+static nserror nsjpegxl_clone(const struct content *old, struct content **newc)
+{
+ struct content *jpegxl_c;
+ nserror error;
+
+ jpegxl_c = calloc(1, sizeof(struct content));
+ if (jpegxl_c == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, jpegxl_c);
+ if (error != NSERROR_OK) {
+ content_destroy(jpegxl_c);
+ return error;
+ }
+
+ /* re-convert if the content is ready */
+ if ((old->status == CONTENT_STATUS_READY) ||
+ (old->status == CONTENT_STATUS_DONE)) {
+ if (nsjpegxl_convert(jpegxl_c) == false) {
+ content_destroy(jpegxl_c);
+ return NSERROR_CLONE_FAILED;
+ }
+ }
+
+ *newc = jpegxl_c;
+
+ return NSERROR_OK;
+}
+
+static const content_handler nsjpegxl_content_handler = {
+ .create = nsjpegxl_create,
+ .data_complete = nsjpegxl_convert,
+ .destroy = image_cache_destroy,
+ .redraw = image_cache_redraw,
+ .clone = nsjpegxl_clone,
+ .get_internal = image_cache_get_internal,
+ .type = image_cache_content_type,
+ .is_opaque = image_cache_is_opaque,
+ .no_share = false,
+};
+
+static const char *nsjpegxl_types[] = {
+ "image/jxl",
+};
+
+CONTENT_FACTORY_REGISTER_TYPES(nsjpegxl, nsjpegxl_types, nsjpegxl_content_handler);
diff --git a/frontends/atari/login.h b/content/handlers/image/jpegxl.h
index b61808c71..e37d9344e 100644
--- a/frontends/atari/login.h
+++ b/content/handlers/image/jpegxl.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2010 Ole Loots <ole@monochrom.net>
+ * Copyright 2023 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,11 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef NS_LOGIN_H_INCLUDED
-#define NS_LOGIN_H_INCLUDED
+/** \file
+ * Content for image/jpegxl (interface).
+ */
-#include "utils/nsurl.h"
+#ifndef _NETSURF_IMAGE_JPEGXL_H_
+#define _NETSURF_IMAGE_JPEGXL_H_
-bool login_form_do( nsurl * host, char * realm, char **cbpw );
+nserror nsjpegxl_init(void);
#endif
diff --git a/content/handlers/image/nssprite.c b/content/handlers/image/nssprite.c
index 269c24356..c18f49063 100644
--- a/content/handlers/image/nssprite.c
+++ b/content/handlers/image/nssprite.c
@@ -23,6 +23,8 @@
#include <stdbool.h>
#include <stdlib.h>
+#include <string.h>
+
#include <librosprite.h>
#include "utils/utils.h"
@@ -33,7 +35,9 @@
#include "netsurf/content.h"
#include "content/llcache.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
#include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
#include "image/nssprite.h"
@@ -98,8 +102,8 @@ static bool nssprite_convert(struct content *c)
struct rosprite_mem_context* ctx = NULL;
- const char *data;
- unsigned long size;
+ const uint8_t *data;
+ size_t size;
char *title;
data = content__get_source_data(c, &size);
@@ -115,31 +119,19 @@ static bool nssprite_convert(struct content *c)
struct rosprite* sprite = sprite_area->sprites[0];
- nssprite->bitmap = guit->bitmap->create(sprite->width, sprite->height, BITMAP_NEW);
+ nssprite->bitmap = guit->bitmap->create(sprite->width, sprite->height, BITMAP_NONE);
if (!nssprite->bitmap) {
- content_broadcast_errorcode(c, NSERROR_NOMEM);
+ content_broadcast_error(c, NSERROR_NOMEM, NULL);
return false;
}
- uint32_t* imagebuf = (uint32_t *)guit->bitmap->get_buffer(nssprite->bitmap);
+ uint32_t* imagebuf = (uint32_t *)(void *)guit->bitmap->get_buffer(nssprite->bitmap);
if (!imagebuf) {
- content_broadcast_errorcode(c, NSERROR_NOMEM);
+ content_broadcast_error(c, NSERROR_NOMEM, NULL);
return false;
}
unsigned char *spritebuf = (unsigned char *)sprite->image;
- /* reverse byte order of each word */
- for (uint32_t y = 0; y < sprite->height; y++) {
- for (uint32_t x = 0; x < sprite->width; x++) {
- int offset = 4 * (y * sprite->width + x);
-
- *imagebuf = (spritebuf[offset] << 24) |
- (spritebuf[offset + 1] << 16) |
- (spritebuf[offset + 2] << 8) |
- (spritebuf[offset + 3]);
-
- imagebuf++;
- }
- }
+ memcpy(imagebuf, spritebuf, sprite->width * sprite->height * 4);
c->width = sprite->width;
c->height = sprite->height;
@@ -153,6 +145,9 @@ static bool nssprite_convert(struct content *c)
free(title);
}
+ bitmap_format_to_client(nssprite->bitmap, &(bitmap_fmt_t) {
+ .layout = BITMAP_LAYOUT_A8B8G8R8,
+ });
guit->bitmap->modified(nssprite->bitmap);
content_set_ready(c);
@@ -165,7 +160,7 @@ ro_sprite_error:
if (ctx != NULL) {
rosprite_destroy_mem_context(ctx);
}
- content_broadcast_errorcode(c, NSERROR_SPRITE_ERROR);
+ content_broadcast_error(c, NSERROR_SPRITE_ERROR, NULL);
return false;
}
@@ -257,6 +252,17 @@ static content_type nssprite_content_type(void)
}
+static bool nssprite_content_is_opaque(struct content *c)
+{
+ nssprite_content *nssprite = (nssprite_content *) c;
+
+ if (nssprite->bitmap != NULL) {
+ return guit->bitmap->get_opaque(nssprite->bitmap);
+ }
+
+ return false;
+}
+
static const content_handler nssprite_content_handler = {
.create = nssprite_create,
.data_complete = nssprite_convert,
@@ -265,6 +271,7 @@ static const content_handler nssprite_content_handler = {
.clone = nssprite_clone,
.get_internal = nssprite_get_internal,
.type = nssprite_content_type,
+ .is_opaque = nssprite_content_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/png.c b/content/handlers/image/png.c
index 7a4ce3010..97a5795b3 100644
--- a/content/handlers/image/png.c
+++ b/content/handlers/image/png.c
@@ -19,6 +19,7 @@
*/
#include <stdbool.h>
+#include <string.h>
#include <stdlib.h>
#include <png.h>
@@ -29,7 +30,9 @@
#include "netsurf/bitmap.h"
#include "content/llcache.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
#include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
#include "image/image_cache.h"
#include "image/png.h"
@@ -116,8 +119,37 @@ static void nspng_setup_transforms(png_structp png_ptr, png_infop info_ptr)
png_set_gray_to_rgb(png_ptr);
}
+ switch (bitmap_fmt.layout) {
+ case BITMAP_LAYOUT_B8G8R8A8: /* Fall through. */
+ case BITMAP_LAYOUT_A8B8G8R8:
+ png_set_bgr(png_ptr);
+ break;
+ default:
+ /* RGB is the default. */
+ break;
+ }
+
if (!(color_type & PNG_COLOR_MASK_ALPHA)) {
- png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
+ switch (bitmap_fmt.layout) {
+ case BITMAP_LAYOUT_A8R8G8B8: /* Fall through. */
+ case BITMAP_LAYOUT_A8B8G8R8:
+ png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
+ break;
+
+ default:
+ png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
+ break;
+ }
+ } else {
+ switch (bitmap_fmt.layout) {
+ case BITMAP_LAYOUT_A8R8G8B8: /* Fall through. */
+ case BITMAP_LAYOUT_A8B8G8R8:
+ png_set_swap_alpha(png_ptr);
+ break;
+ default:
+ /* Alpha as final component is the default. */
+ break;
+ }
}
/* gamma correction - we use 2.2 as our screen gamma
@@ -161,14 +193,14 @@ static void info_callback(png_structp png_s, png_infop info)
}
/* Claim the required memory for the converted PNG */
- png_c->bitmap = guit->bitmap->create(width, height, BITMAP_NEW);
+ png_c->bitmap = guit->bitmap->create(width, height, BITMAP_NONE);
if (png_c->bitmap == NULL) {
/* Failed to create bitmap skip pre-conversion */
longjmp(png_jmpbuf(png_s), CBERR_NOPRE);
}
png_c->rowstride = guit->bitmap->get_rowstride(png_c->bitmap);
- png_c->bpp = guit->bitmap->get_bpp(png_c->bitmap);
+ png_c->bpp = sizeof(uint32_t);
nspng_setup_transforms(png_s, info);
@@ -242,7 +274,7 @@ static nserror nspng_create_png_data(nspng_content *png_c)
png_c->png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
if (png_c->png == NULL) {
- content_broadcast_errorcode(&png_c->base, NSERROR_NOMEM);
+ content_broadcast_error(&png_c->base, NSERROR_NOMEM, NULL);
return NSERROR_NOMEM;
}
@@ -252,7 +284,7 @@ static nserror nspng_create_png_data(nspng_content *png_c)
if (png_c->info == NULL) {
png_destroy_read_struct(&png_c->png, &png_c->info, 0);
- content_broadcast_errorcode(&png_c->base, NSERROR_NOMEM);
+ content_broadcast_error(&png_c->base, NSERROR_NOMEM, NULL);
return NSERROR_NOMEM;
}
@@ -262,7 +294,7 @@ static nserror nspng_create_png_data(nspng_content *png_c)
png_c->png = NULL;
png_c->info = NULL;
- content_broadcast_errorcode(&png_c->base, NSERROR_PNG_ERROR);
+ content_broadcast_error(&png_c->base, NSERROR_PNG_ERROR, NULL);
return NSERROR_NOMEM;
}
@@ -355,7 +387,7 @@ static bool nspng_process_data(struct content *c, const char *data,
png_c->png = NULL;
png_c->info = NULL;
- content_broadcast_errorcode(c, NSERROR_PNG_ERROR);
+ content_broadcast_error(c, NSERROR_PNG_ERROR, NULL);
ret = false;
@@ -367,8 +399,8 @@ static bool nspng_process_data(struct content *c, const char *data,
}
struct png_cache_read_data_s {
- const char *data;
- unsigned long size;
+ const uint8_t *data;
+ size_t size;
};
/** PNG library read fucntion to read data from a memory array
@@ -481,7 +513,7 @@ png_cache_convert(struct content *c)
height = png_get_image_height(png_ptr, info_ptr);
/* Claim the required memory for the converted PNG */
- bitmap = guit->bitmap->create(width, height, BITMAP_NEW);
+ bitmap = guit->bitmap->create(width, height, BITMAP_NONE);
if (bitmap == NULL) {
/* cleanup and bail */
goto png_cache_convert_error;
@@ -506,7 +538,13 @@ png_cache_convert_error:
}
if (bitmap != NULL) {
- guit->bitmap->modified((struct bitmap *)bitmap);
+ bool opaque = bitmap_test_opaque((void *)bitmap);
+ guit->bitmap->set_opaque((void *)bitmap, opaque);
+ bitmap_format_to_client((void *)bitmap, &(bitmap_fmt_t) {
+ .layout = bitmap_fmt.layout,
+ .pma = opaque ? bitmap_fmt.pma : false,
+ });
+ guit->bitmap->modified((void *)bitmap);
}
return (struct bitmap *)bitmap;
@@ -533,7 +571,12 @@ static bool nspng_convert(struct content *c)
}
if (png_c->bitmap != NULL) {
- guit->bitmap->set_opaque(png_c->bitmap, guit->bitmap->test_opaque(png_c->bitmap));
+ bool opaque = bitmap_test_opaque(png_c->bitmap);
+ guit->bitmap->set_opaque(png_c->bitmap, opaque);
+ bitmap_format_to_client(png_c->bitmap, &(bitmap_fmt_t) {
+ .layout = bitmap_fmt.layout,
+ .pma = opaque ? bitmap_fmt.pma : false,
+ });
guit->bitmap->modified(png_c->bitmap);
}
@@ -551,8 +594,8 @@ static nserror nspng_clone(const struct content *old_c, struct content **new_c)
{
nspng_content *clone_png_c;
nserror error;
- const char *data;
- unsigned long size;
+ const uint8_t *data;
+ size_t size;
clone_png_c = calloc(1, sizeof(nspng_content));
if (clone_png_c == NULL)
@@ -573,7 +616,7 @@ static nserror nspng_clone(const struct content *old_c, struct content **new_c)
data = content__get_source_data(&clone_png_c->base, &size);
if (size > 0) {
- if (nspng_process_data(&clone_png_c->base, data, size) == false) {
+ if (nspng_process_data(&clone_png_c->base, (const char *)data, size) == false) {
content_destroy(&clone_png_c->base);
return NSERROR_NOMEM;
}
@@ -601,6 +644,7 @@ static const content_handler nspng_content_handler = {
.redraw = image_cache_redraw,
.get_internal = image_cache_get_internal,
.type = image_cache_content_type,
+ .is_opaque = image_cache_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/rsvg.c b/content/handlers/image/rsvg.c
index 2ba1b49f5..24fc1a4e0 100644
--- a/content/handlers/image/rsvg.c
+++ b/content/handlers/image/rsvg.c
@@ -49,7 +49,9 @@
#include "netsurf/content.h"
#include "content/llcache.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
#include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
#include "image/rsvg.h"
@@ -71,7 +73,7 @@ static nserror rsvg_create_svg_data(rsvg_content *c)
if ((c->rsvgh = rsvg_handle_new()) == NULL) {
NSLOG(netsurf, INFO, "rsvg_handle_new() returned NULL.");
- content_broadcast_errorcode(&c->base, NSERROR_NOMEM);
+ content_broadcast_error(&c->base, NSERROR_NOMEM, NULL);
return NSERROR_NOMEM;
}
@@ -120,48 +122,13 @@ static bool rsvg_process_data(struct content *c, const char *data,
&err) == FALSE) {
NSLOG(netsurf, INFO,
"rsvg_handle_write returned an error: %s", err->message);
- content_broadcast_errorcode(c, NSERROR_SVG_ERROR);
+ content_broadcast_error(c, NSERROR_SVG_ERROR, NULL);
return false;
}
return true;
}
-/** Convert Cairo's ARGB output to NetSurf's favoured ABGR format. It converts
- * the data in-place.
- *
- * \param pixels Pixel data, in the form of ARGB. This will
- * be overwritten with new data in the form of ABGR.
- * \param width Width of the bitmap
- * \param height Height of the bitmap
- * \param rowstride Number of bytes to skip after each row (this
- * implementation requires this to be a multiple of 4.)
- */
-static inline void rsvg_argb_to_abgr(uint8_t *pixels,
- int width, int height, size_t rowstride)
-{
- uint8_t *p = pixels;
- int boff = 0, roff = 2;
-
- if (endian_host_is_le() == false) {
- boff = 1;
- roff = 3;
- }
-
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++) {
- /* Swap R and B */
- const uint8_t r = p[4*x+roff];
-
- p[4*x+roff] = p[4*x+boff];
-
- p[4*x+boff] = r;
- }
-
- p += rowstride;
- }
-}
-
static bool rsvg_convert(struct content *c)
{
rsvg_content *d = (rsvg_content *) c;
@@ -171,7 +138,7 @@ static bool rsvg_convert(struct content *c)
if (rsvg_handle_close(d->rsvgh, &err) == FALSE) {
NSLOG(netsurf, INFO,
"rsvg_handle_close returned an error: %s", err->message);
- content_broadcast_errorcode(c, NSERROR_SVG_ERROR);
+ content_broadcast_error(c, NSERROR_SVG_ERROR, NULL);
return false;
}
@@ -186,10 +153,10 @@ static bool rsvg_convert(struct content *c)
c->height = rsvgsize.height;
if ((d->bitmap = guit->bitmap->create(c->width, c->height,
- BITMAP_NEW)) == NULL) {
+ BITMAP_NONE)) == NULL) {
NSLOG(netsurf, INFO,
"Failed to create bitmap for rsvg render.");
- content_broadcast_errorcode(c, NSERROR_NOMEM);
+ content_broadcast_error(c, NSERROR_NOMEM, NULL);
return false;
}
@@ -200,22 +167,22 @@ static bool rsvg_convert(struct content *c)
guit->bitmap->get_rowstride(d->bitmap))) == NULL) {
NSLOG(netsurf, INFO,
"Failed to create Cairo image surface for rsvg render.");
- content_broadcast_errorcode(c, NSERROR_NOMEM);
+ content_broadcast_error(c, NSERROR_NOMEM, NULL);
return false;
}
if ((d->ct = cairo_create(d->cs)) == NULL) {
NSLOG(netsurf, INFO,
"Failed to create Cairo drawing context for rsvg render.");
- content_broadcast_errorcode(c, NSERROR_NOMEM);
+ content_broadcast_error(c, NSERROR_NOMEM, NULL);
return false;
}
rsvg_handle_render_cairo(d->rsvgh, d->ct);
- rsvg_argb_to_abgr(guit->bitmap->get_buffer(d->bitmap),
- c->width, c->height,
- guit->bitmap->get_rowstride(d->bitmap));
+ bitmap_format_to_client(d->bitmap, &(bitmap_fmt_t) {
+ .layout = BITMAP_LAYOUT_ARGB8888,
+ });
guit->bitmap->modified(d->bitmap);
content_set_ready(c);
content_set_done(c);
@@ -262,8 +229,8 @@ static nserror rsvg_clone(const struct content *old, struct content **newc)
{
rsvg_content *svg;
nserror error;
- const char *data;
- unsigned long size;
+ const uint8_t *data;
+ size_t size;
svg = calloc(1, sizeof(rsvg_content));
if (svg == NULL)
@@ -284,7 +251,7 @@ static nserror rsvg_clone(const struct content *old, struct content **newc)
data = content__get_source_data(&svg->base, &size);
if (size > 0) {
- if (rsvg_process_data(&svg->base, data, size) == false) {
+ if (rsvg_process_data(&svg->base, (const char *)data, size) == false) {
content_destroy(&svg->base);
return NSERROR_NOMEM;
}
@@ -315,6 +282,19 @@ static content_type rsvg_content_type(void)
return CONTENT_IMAGE;
}
+
+static bool rsvg_content_is_opaque(struct content *c)
+{
+ rsvg_content *d = (rsvg_content *) c;
+
+ if (d->bitmap != NULL) {
+ return guit->bitmap->get_opaque(d->bitmap);
+ }
+
+ return false;
+}
+
+
static const content_handler rsvg_content_handler = {
.create = rsvg_create,
.process_data = rsvg_process_data,
@@ -324,6 +304,7 @@ static const content_handler rsvg_content_handler = {
.clone = rsvg_clone,
.get_internal = rsvg_get_internal,
.type = rsvg_content_type,
+ .is_opaque = rsvg_content_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/rsvg246.c b/content/handlers/image/rsvg246.c
new file mode 100644
index 000000000..0e337132f
--- /dev/null
+++ b/content/handlers/image/rsvg246.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2022 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * implementation of content handler for image/svg using librsvg 2.46 API.
+ *
+ * SVG files are rendered to a NetSurf bitmap by creating a Cairo rendering
+ * surface (content_rsvg_data.cs) over the bitmap's data, creating a Cairo
+ * drawing context using that surface, and then passing that drawing context
+ * to librsvg which then uses Cairo calls to plot the graphic to the bitmap.
+ * We store this in content->bitmap, and then use the usual bitmap plotter
+ * function to render it for redraw requests.
+ */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <librsvg/rsvg.h>
+
+#include <nsutils/endian.h>
+
+#include "utils/log.h"
+#include "utils/utils.h"
+#include "utils/messages.h"
+#include "netsurf/plotters.h"
+#include "netsurf/bitmap.h"
+#include "netsurf/content.h"
+#include "content/llcache.h"
+#include "content/content_protected.h"
+#include "content/content_factory.h"
+#include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
+
+#include "image/image_cache.h"
+
+#include "image/rsvg.h"
+
+
+typedef struct rsvg_content {
+ struct content base;
+
+ RsvgHandle *rsvgh; /**< Context handle for RSVG renderer */
+} rsvg_content;
+
+
+static nserror
+rsvg_create(const content_handler *handler,
+ lwc_string *imime_type,
+ const struct http_parameter *params,
+ llcache_handle *llcache,
+ const char *fallback_charset,
+ bool quirks,
+ struct content **c)
+{
+ rsvg_content *svg;
+ nserror error;
+
+ svg = calloc(1, sizeof(rsvg_content));
+ if (svg == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&svg->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ free(svg);
+ return error;
+ }
+
+ *c = (struct content *)svg;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * create a bitmap from jpeg content for the image cache.
+ */
+static struct bitmap *
+rsvg_cache_convert(struct content *c)
+{
+ rsvg_content *svgc = (rsvg_content *)c;
+ struct bitmap *bitmap;
+ cairo_surface_t *cs;
+ cairo_t *cr;
+ RsvgRectangle viewport;
+ gboolean renderres;
+
+ if ((bitmap = guit->bitmap->create(c->width, c->height, BITMAP_NONE)) == NULL) {
+ NSLOG(netsurf, INFO, "Failed to create bitmap for rsvg render.");
+ return NULL;
+ }
+
+ if ((cs = cairo_image_surface_create_for_data(
+ (unsigned char *)guit->bitmap->get_buffer(bitmap),
+ CAIRO_FORMAT_ARGB32,
+ c->width, c->height,
+ guit->bitmap->get_rowstride(bitmap))) == NULL) {
+ NSLOG(netsurf, INFO, "Failed to create Cairo image surface for rsvg render.");
+ guit->bitmap->destroy(bitmap);
+ return NULL;
+ }
+ if ((cr = cairo_create(cs)) == NULL) {
+ NSLOG(netsurf, INFO,
+ "Failed to create Cairo drawing context for rsvg render.");
+ cairo_surface_destroy(cs);
+ guit->bitmap->destroy(bitmap);
+ return NULL;
+ }
+
+ viewport.x = 0;
+ viewport.y = 0;
+ viewport.width = c->width;
+ viewport.height = c->height;
+ renderres = rsvg_handle_render_document(svgc->rsvgh, cr, &viewport, NULL);
+ NSLOG(netsurf, DEBUG, "rsvg render:%d, width:%d, height %d", renderres, c->width, c->height);
+
+ bitmap_format_to_client(bitmap, &(bitmap_fmt_t) {
+ .layout = BITMAP_LAYOUT_ARGB8888,
+ });
+ guit->bitmap->modified(bitmap);
+
+ cairo_destroy(cr);
+ cairo_surface_destroy(cs);
+
+ return bitmap;
+}
+
+static void rsvg__get_demensions(const rsvg_content *svgc,
+ int *width, int *height)
+{
+#if LIBRSVG_MAJOR_VERSION >= 2 && LIBRSVG_MINOR_VERSION >= 52
+ gdouble rwidth;
+ gdouble rheight;
+ gboolean gotsize;
+
+ gotsize = rsvg_handle_get_intrinsic_size_in_pixels(svgc->rsvgh,
+ &rwidth,
+ &rheight);
+ if (gotsize == TRUE) {
+ *width = rwidth;
+ *height = rheight;
+ } else {
+ RsvgRectangle ink_rect;
+ RsvgRectangle logical_rect;
+ rsvg_handle_get_geometry_for_element(svgc->rsvgh,
+ NULL,
+ &ink_rect,
+ &logical_rect,
+ NULL);
+ *width = ink_rect.width;
+ *height = ink_rect.height;
+ }
+#else
+ RsvgDimensionData rsvgsize;
+
+ rsvg_handle_get_dimensions(svgc->rsvgh, &rsvgsize);
+ *width = rsvgsize.width;
+ *height = rsvgsize.height;
+#endif
+ NSLOG(netsurf, DEBUG, "rsvg width:%d height:%d.", *width, *height);
+}
+
+static bool rsvg_convert(struct content *c)
+{
+ rsvg_content *svgc = (rsvg_content *)c;
+ const uint8_t *data; /* content data */
+ size_t size; /* content data size */
+ GInputStream * istream;
+ GError *gerror = NULL;
+
+ /* check image header is valid and get width/height */
+
+ data = content__get_source_data(c, &size);
+
+ istream = g_memory_input_stream_new_from_data(data, size, NULL);
+ svgc->rsvgh = rsvg_handle_new_from_stream_sync(istream,
+ NULL,
+ RSVG_HANDLE_FLAGS_NONE,
+ NULL,
+ &gerror);
+ g_object_unref(istream);
+ if (svgc->rsvgh == NULL) {
+ NSLOG(netsurf, INFO, "Failed to create rsvg handle for content.");
+ return false;
+ }
+
+ rsvg__get_demensions(svgc, &c->width, &c->height);
+
+ c->size = c->width * c->height * 4;
+
+ image_cache_add(c, NULL, rsvg_cache_convert);
+
+ content_set_ready(c);
+ content_set_done(c);
+ content_set_status(c, ""); /* Done: update status bar */
+
+ return true;
+}
+
+
+static nserror rsvg_clone(const struct content *old, struct content **newc)
+{
+ rsvg_content *svg;
+ nserror error;
+
+ svg = calloc(1, sizeof(rsvg_content));
+ if (svg == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &svg->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&svg->base);
+ return error;
+ }
+
+ /* re-convert if the content is ready */
+ if ((old->status == CONTENT_STATUS_READY) ||
+ (old->status == CONTENT_STATUS_DONE)) {
+ if (rsvg_convert(&svg->base) == false) {
+ content_destroy(&svg->base);
+ return NSERROR_CLONE_FAILED;
+ }
+ }
+
+ *newc = (struct content *)svg;
+
+ return NSERROR_OK;
+}
+
+
+static void rsvg_destroy(struct content *c)
+{
+ rsvg_content *d = (rsvg_content *) c;
+
+ if (d->rsvgh != NULL) {
+ g_object_unref(d->rsvgh);
+ d->rsvgh = NULL;
+ }
+
+ return image_cache_destroy(c);
+}
+
+static const content_handler rsvg_content_handler = {
+ .create = rsvg_create,
+ .data_complete = rsvg_convert,
+ .destroy = rsvg_destroy,
+ .redraw = image_cache_redraw,
+ .clone = rsvg_clone,
+ .get_internal = image_cache_get_internal,
+ .type = image_cache_content_type,
+ .is_opaque = image_cache_is_opaque,
+ .no_share = false,
+};
+
+static const char *rsvg_types[] = {
+ "image/svg",
+ "image/svg+xml"
+};
+
+CONTENT_FACTORY_REGISTER_TYPES(nsrsvg, rsvg_types, rsvg_content_handler);
+
diff --git a/content/handlers/image/svg.c b/content/handlers/image/svg.c
index 2edc7bd08..895d799df 100644
--- a/content/handlers/image/svg.c
+++ b/content/handlers/image/svg.c
@@ -30,9 +30,11 @@
#include "utils/messages.h"
#include "utils/utils.h"
+#include "utils/nsurl.h"
#include "netsurf/plotters.h"
#include "netsurf/content.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
#include "image/svg.h"
@@ -59,7 +61,7 @@ static nserror svg_create_svg_data(svg_content *c)
return NSERROR_OK;
no_memory:
- content_broadcast_errorcode(&c->base, NSERROR_NOMEM);
+ content_broadcast_error(&c->base, NSERROR_NOMEM, NULL);
return NSERROR_NOMEM;
}
@@ -126,8 +128,8 @@ static bool svg_convert(struct content *c)
static void svg_reformat(struct content *c, int width, int height)
{
svg_content *svg = (svg_content *) c;
- const char *source_data;
- unsigned long source_size;
+ const uint8_t *source_data;
+ size_t source_size;
assert(svg->diagram);
@@ -135,9 +137,12 @@ static void svg_reformat(struct content *c, int width, int height)
if (width != svg->current_width || height != svg->current_height) {
source_data = content__get_source_data(c, &source_size);
- svgtiny_parse(svg->diagram, source_data, source_size,
- nsurl_access(content_get_url(c)),
- width, height);
+ svgtiny_parse(svg->diagram,
+ (const char *)source_data,
+ source_size,
+ nsurl_access(content_get_url(c)),
+ width,
+ height);
svg->current_width = width;
svg->current_height = height;
@@ -188,14 +193,15 @@ svg_redraw_internal(struct content *c,
for (i = 0; i != diagram->shape_count; i++) {
if (diagram->shape[i].path) {
+ pstyle.stroke_width = plot_style_int_to_fixed(
+ diagram->shape[i].stroke_width);
pstyle.stroke_colour = BGR(diagram->shape[i].stroke);
pstyle.fill_colour = BGR(diagram->shape[i].fill);
res = ctx->plot->path(ctx,
- &pstyle,
- diagram->shape[i].path,
- diagram->shape[i].path_length,
- diagram->shape[i].stroke_width,
- transform);
+ &pstyle,
+ diagram->shape[i].path,
+ diagram->shape[i].path_length,
+ transform);
if (res != NSERROR_OK) {
return false;
}
@@ -210,7 +216,7 @@ svg_redraw_internal(struct content *c,
fstyle.background = 0xffffff;
fstyle.foreground = 0x000000;
- fstyle.size = (8 * FONT_SIZE_SCALE) * scale;
+ fstyle.size = (8 * PLOT_STYLE_SCALE) * scale;
res = ctx->plot->text(ctx,
&fstyle,
@@ -221,7 +227,7 @@ svg_redraw_internal(struct content *c,
return false;
}
}
- }
+ }
#undef BGR
@@ -360,5 +366,3 @@ static const char *svg_types[] = {
CONTENT_FACTORY_REGISTER_TYPES(svg, svg_types, svg_content_handler);
-
-
diff --git a/content/handlers/image/webp.c b/content/handlers/image/webp.c
new file mode 100644
index 000000000..c04c0efd2
--- /dev/null
+++ b/content/handlers/image/webp.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2019 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * implementation of content handling for image/webp
+ *
+ * This implementation uses the google webp library.
+ * Image cache handling is performed by the generic NetSurf handler.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <setjmp.h>
+
+#include <webp/decode.h>
+
+#include "utils/utils.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "netsurf/bitmap.h"
+#include "content/llcache.h"
+#include "content/content_protected.h"
+#include "content/content_factory.h"
+#include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
+
+#include "image/image_cache.h"
+
+#include "webp.h"
+
+/**
+ * Content create entry point.
+ *
+ * create a content object for the webp
+ */
+static nserror
+webp_create(const content_handler *handler,
+ lwc_string *imime_type,
+ const struct http_parameter *params,
+ llcache_handle *llcache,
+ const char *fallback_charset,
+ bool quirks,
+ struct content **c)
+{
+ struct content *webp_c; /* webp content object */
+ nserror res;
+
+ webp_c = calloc(1, sizeof(struct content));
+ if (webp_c == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ res = content__init(webp_c,
+ handler,
+ imime_type,
+ params,
+ llcache,
+ fallback_charset,
+ quirks);
+ if (res != NSERROR_OK) {
+ free(webp_c);
+ return res;
+ }
+
+ *c = webp_c;
+
+ return NSERROR_OK;
+}
+
+/**
+ * create a bitmap from webp content.
+ */
+static struct bitmap *
+webp_cache_convert(struct content *c)
+{
+ const uint8_t *source_data; /* webp source data */
+ size_t source_size; /* length of webp source data */
+ VP8StatusCode webpres;
+ WebPBitstreamFeatures webpfeatures;
+ unsigned int bmap_flags;
+ uint8_t *pixels = NULL;
+ uint8_t *decoded;
+ size_t rowstride;
+ struct bitmap *bitmap = NULL;
+ bitmap_fmt_t webp_fmt = {
+ .layout = bitmap_fmt.layout,
+ };
+
+ source_data = content__get_source_data(c, &source_size);
+
+ webpres = WebPGetFeatures(source_data, source_size, &webpfeatures);
+
+ if (webpres != VP8_STATUS_OK) {
+ return NULL;
+ }
+
+ if (webpfeatures.has_alpha == 0) {
+ bmap_flags = BITMAP_OPAQUE;
+ /* Image has no alpha. Premultiplied alpha makes no difference.
+ * Optimisation: Avoid unnecessary conversion by copying format.
+ */
+ webp_fmt.pma = bitmap_fmt.pma;
+ } else {
+ bmap_flags = BITMAP_NONE;
+ }
+
+ /* create bitmap */
+ bitmap = guit->bitmap->create(webpfeatures.width,
+ webpfeatures.height,
+ bmap_flags);
+ if (bitmap == NULL) {
+ /* empty bitmap could not be created */
+ return NULL;
+ }
+
+ pixels = guit->bitmap->get_buffer(bitmap);
+ if (pixels == NULL) {
+ /* bitmap with no buffer available */
+ guit->bitmap->destroy(bitmap);
+ return NULL;
+ }
+
+ rowstride = guit->bitmap->get_rowstride(bitmap);
+
+ switch (webp_fmt.layout) {
+ default:
+ /* WebP has no ABGR function, fall back to default. */
+ webp_fmt.layout = BITMAP_LAYOUT_R8G8B8A8;
+ fallthrough;
+ case BITMAP_LAYOUT_R8G8B8A8:
+ decoded = WebPDecodeRGBAInto(source_data, source_size, pixels,
+ rowstride * webpfeatures.height, rowstride);
+ break;
+
+ case BITMAP_LAYOUT_B8G8R8A8:
+ decoded = WebPDecodeBGRAInto(source_data, source_size, pixels,
+ rowstride * webpfeatures.height, rowstride);
+ break;
+
+ case BITMAP_LAYOUT_A8R8G8B8:
+ decoded = WebPDecodeARGBInto(source_data, source_size, pixels,
+ rowstride * webpfeatures.height, rowstride);
+ break;
+ }
+ if (decoded == NULL) {
+ /* decode failed */
+ guit->bitmap->destroy(bitmap);
+ return NULL;
+ }
+
+ bitmap_format_to_client(bitmap, &webp_fmt);
+ guit->bitmap->modified(bitmap);
+
+ return bitmap;
+}
+
+/**
+ * Convert the webp source data content.
+ *
+ * This ensures there is valid webp source data in the content object
+ * and then adds it to the image cache ready to be converted on
+ * demand.
+ *
+ * \param c The webp content object
+ * \return true on successful processing of teh webp content else false
+ */
+static bool webp_convert(struct content *c)
+{
+ int res;
+ const uint8_t* data;
+ size_t data_size;
+ int width;
+ int height;
+
+ data = content__get_source_data(c, &data_size);
+
+ res = WebPGetInfo(data, data_size, &width, &height);
+ if (res == 0) {
+ NSLOG(netsurf, INFO, "WebPGetInfo failed:%p", c);
+ return false;
+ }
+
+ c->width = width;
+ c->height = height;
+ c->size = c->width * c->height * 4;
+
+ image_cache_add(c, NULL, webp_cache_convert);
+
+ content_set_ready(c);
+ content_set_done(c);
+
+ return true;
+}
+
+/**
+ * Clone content.
+ */
+static nserror webp_clone(const struct content *old, struct content **new_c)
+{
+ struct content *webp_c; /* cloned webp content */
+ nserror res;
+
+ webp_c = calloc(1, sizeof(struct content));
+ if (webp_c == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ res = content__clone(old, webp_c);
+ if (res != NSERROR_OK) {
+ content_destroy(webp_c);
+ return res;
+ }
+
+ /* re-convert if the content is ready */
+ if ((old->status == CONTENT_STATUS_READY) ||
+ (old->status == CONTENT_STATUS_DONE)) {
+ if (webp_convert(webp_c) == false) {
+ content_destroy(webp_c);
+ return NSERROR_CLONE_FAILED;
+ }
+ }
+
+ *new_c = webp_c;
+
+ return NSERROR_OK;
+}
+
+static const content_handler webp_content_handler = {
+ .create = webp_create,
+ .data_complete = webp_convert,
+ .destroy = image_cache_destroy,
+ .redraw = image_cache_redraw,
+ .clone = webp_clone,
+ .get_internal = image_cache_get_internal,
+ .type = image_cache_content_type,
+ .is_opaque = image_cache_is_opaque,
+ .no_share = false,
+};
+
+static const char *webp_types[] = {
+ "image/webp"
+};
+
+CONTENT_FACTORY_REGISTER_TYPES(nswebp, webp_types, webp_content_handler);
diff --git a/frontends/atari/verify_ssl.h b/content/handlers/image/webp.h
index b69bc9cfb..b219f2576 100644
--- a/frontends/atari/verify_ssl.h
+++ b/content/handlers/image/webp.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2010 Ole Loots <ole@monochrom.net>
+ * Copyright 2019 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,9 +16,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef NS_VERIFY_SSL_H_INCLUDED
-#define NS_VERIFY_SSL_H_INCLUDED
+/**
+ * \file
+ * Interface to image/webp content handlers
+ */
+
+#ifndef _NETSURF_IMAGE_WEBP_H_
+#define _NETSURF_IMAGE_WEBP_H_
-bool verify_ssl_form_do( const char * url, const struct ssl_cert_info * cert_infos_n , unsigned long num_certs );
+nserror nswebp_init(void);
#endif
diff --git a/content/handlers/javascript/content.c b/content/handlers/javascript/content.c
index ef5614094..9f37e126c 100644
--- a/content/handlers/javascript/content.c
+++ b/content/handlers/javascript/content.c
@@ -16,8 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Content for javascript (implementation)
+/**
+ * \file
+ * javascript content implementation
*/
#include <assert.h>
@@ -25,8 +26,10 @@
#include <stdbool.h>
#include <stdlib.h>
+#include "utils/errors.h"
#include "utils/config.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
#include "content/hlcache.h"
#include "utils/log.h"
#include "utils/messages.h"
diff --git a/content/handlers/javascript/duktape/CSSRule.bnd b/content/handlers/javascript/duktape/CSSRule.bnd
new file mode 100644
index 000000000..555023c85
--- /dev/null
+++ b/content/handlers/javascript/duktape/CSSRule.bnd
@@ -0,0 +1,22 @@
+/* CSS Rule binding for NetSurf using duktape and libcss/libdom
+ *
+ * Copyright 2022 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * Released under the terms of the MIT License,
+ * http://www.opensource.org/licenses/mit-license
+ */
+
+/* Note, for now this exists purely to block warnings, eventually
+ * rules will have to come from stylesheets etc.
+ */
+
+class CSSRule {
+ private bool unused;
+};
+
+init CSSRule()
+%{
+ priv->unused = true;
+%}
diff --git a/content/handlers/javascript/duktape/CSSStyleSheet.bnd b/content/handlers/javascript/duktape/CSSStyleSheet.bnd
new file mode 100644
index 000000000..9167b8afa
--- /dev/null
+++ b/content/handlers/javascript/duktape/CSSStyleSheet.bnd
@@ -0,0 +1,22 @@
+/* CSS Stylesheet binding for NetSurf using duktape and libcss/libdom
+ *
+ * Copyright 2022 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * Released under the terms of the MIT License,
+ * http://www.opensource.org/licenses/mit-license
+ */
+
+/* Note, for now this exists purely to block warnings, eventually
+ * stylesheets will have to come from documents etc.
+ */
+
+class CSSStyleSheet {
+ private bool unused;
+};
+
+init CSSStyleSheet()
+%{
+ priv->unused = true;
+%}
diff --git a/content/handlers/javascript/duktape/CanvasRenderingContext2D.bnd b/content/handlers/javascript/duktape/CanvasRenderingContext2D.bnd
new file mode 100644
index 000000000..2fe73f4e1
--- /dev/null
+++ b/content/handlers/javascript/duktape/CanvasRenderingContext2D.bnd
@@ -0,0 +1,603 @@
+/* HTML canvas element rendering context binding using duktape and libdom
+ *
+ * Copyright 2020 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * Released under the terms of the MIT License,
+ * http://www.opensource.org/licenses/mit-license
+ */
+
+class CanvasRenderingContext2D {
+ private struct dom_html_canvas_element *canvas;
+ private struct bitmap *bitmap;
+ private int width;
+ private int height;
+ private size_t stride;
+ private dom_event_listener *listener;
+ prologue %{
+/* prologue */
+#include "desktop/gui_internal.h"
+#include "desktop/gui_table.h"
+#include "netsurf/bitmap.h"
+#include "utils/corestrings.h"
+/* It's a smidge naughty of us to read
+ * this particular header, but we're needing
+ * to redraw the node we represent
+ */
+#include "content/handlers/html/private.h"
+
+static void redraw_node(dom_node *node)
+{
+ struct box *box = NULL;
+ html_content *htmlc = NULL;
+ dom_exception exc;
+ dom_document *doc;
+
+ exc = dom_node_get_user_data(node,
+ corestring_dom___ns_key_box_node_data,
+ &box);
+ if (exc != DOM_NO_ERR || box == NULL) {
+ return;
+ }
+
+ exc = dom_node_get_owner_document(node, &doc);
+ if (exc != DOM_NO_ERR || doc == NULL) {
+ return;
+ }
+
+ exc = dom_node_get_user_data(doc,
+ corestring_dom___ns_key_html_content_data,
+ &htmlc);
+ if (exc != DOM_NO_ERR || htmlc == NULL) {
+ dom_node_unref(doc);
+ return;
+ }
+
+ html__redraw_a_box(htmlc, box);
+
+ dom_node_unref(doc);
+}
+
+/**
+ * deal with events from the DOM for canvas node user data
+ *
+ * \param operation The DOM operation happening
+ * \param key The user data key
+ * \param data The user data (our bitmap)
+ * \param src The DOM node emitting the event (our <canvas>)
+ * \param dst The target DOM node if applicable
+ */
+static void
+canvas2d_user_data_handler(dom_node_operation operation,
+ dom_string *key,
+ void *data,
+ struct dom_node *src,
+ struct dom_node *dst)
+{
+ struct bitmap *newbitmap, *bitmap = (struct bitmap*)data, *oldbitmap = NULL;
+ int width, height;
+ size_t stride;
+
+ if (dom_string_isequal(key,corestring_dom___ns_key_canvas_node_data) == false || data == NULL) {
+ /* Not for us */
+ return;
+ }
+
+ switch (operation) {
+ case DOM_NODE_CLONED:
+ width = guit->bitmap->get_width(bitmap);
+ height = guit->bitmap->get_height(bitmap);
+ stride = guit->bitmap->get_rowstride(bitmap);
+ newbitmap = guit->bitmap->create(width, height,
+ BITMAP_NONE);
+ if (newbitmap != NULL) {
+ if (guit->bitmap->get_rowstride(newbitmap) == stride) {
+ // Compatible bitmap, bung the data over
+ memcpy(guit->bitmap->get_buffer(newbitmap),
+ guit->bitmap->get_buffer(bitmap),
+ stride * height);
+ guit->bitmap->modified(newbitmap);
+ }
+ }
+ if (dom_node_set_user_data(dst,
+ corestring_dom___ns_key_canvas_node_data,
+ newbitmap, canvas2d_user_data_handler,
+ &oldbitmap) == DOM_NO_ERR) {
+ if (oldbitmap != NULL)
+ guit->bitmap->destroy(oldbitmap);
+ }
+ break;
+
+ case DOM_NODE_RENAMED:
+ case DOM_NODE_IMPORTED:
+ case DOM_NODE_ADOPTED:
+ break;
+
+ case DOM_NODE_DELETED:
+ guit->bitmap->destroy(bitmap);
+ break;
+ default:
+ NSLOG(netsurf, INFO, "User data operation not handled.");
+ assert(0);
+ }
+}
+
+/**
+ * Give the canvas element an appropriately sized bitmap
+ *
+ * \param node The DOM node being inserted
+ * \param[out] bitmap_out The bitmap created
+ * \return NSERROR_OK on success else appropriate error code
+ */
+static nserror canvas2d_create_bitmap(dom_node *node, struct bitmap **bitmap_out)
+{
+ dom_exception exc;
+ dom_string *width_s = NULL, *height_s = NULL;
+ unsigned long width = 300, height = 150;
+ struct bitmap *bitmap, *oldbitmap = NULL;
+
+ exc = dom_element_get_attribute(node,
+ corestring_dom_width,
+ &width_s);
+ if (exc == DOM_NO_ERR && width_s != NULL) {
+ const char *ptr = (const char *)dom_string_data(width_s);
+ const char *endptr = ptr + dom_string_length(width_s);
+ char * ended;
+ unsigned long width_n = strtoul(ptr, &ended, 10);
+
+ if (ended == endptr || strcasecmp(ended, "px") == 0) {
+ /* parsed it all */
+ width = width_n;
+ }
+
+ dom_string_unref(width_s);
+ }
+
+ exc = dom_element_get_attribute(node,
+ corestring_dom_height,
+ &height_s);
+ if (exc == DOM_NO_ERR && height_s != NULL) {
+ const char *ptr = (const char *)dom_string_data(height_s);
+ const char *endptr = ptr + dom_string_length(height_s);
+ char * ended;
+ unsigned long height_n = strtoul(ptr, &ended, 10);
+
+ if (ended == endptr || strcasecmp(ended, "px") == 0) {
+ /* parsed it all */
+ height = height_n;
+ }
+
+ dom_string_unref(height_s);
+ }
+
+ bitmap = guit->bitmap->create(
+ (int)width, (int)height,
+ BITMAP_NONE);
+
+ if (bitmap == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ memset(guit->bitmap->get_buffer(bitmap),
+ 0, /* Transparent black */
+ height * guit->bitmap->get_rowstride(bitmap));
+ guit->bitmap->modified(bitmap);
+
+ exc = dom_node_set_user_data(node,
+ corestring_dom___ns_key_canvas_node_data,
+ bitmap,
+ canvas2d_user_data_handler,
+ &oldbitmap);
+
+ if (exc != DOM_NO_ERR) {
+ guit->bitmap->destroy(bitmap);
+ return NSERROR_DOM;
+ }
+
+ assert(oldbitmap == NULL);
+
+ if (bitmap_out != NULL)
+ *bitmap_out = bitmap;
+
+ return NSERROR_OK;
+}
+
+/**
+ * Handle subtree modified events for our canvas node
+ *
+ * If width or height has changed relative to our priv, then
+ * we need to recreate the bitmap and reset our cached width
+ * and height values in order to be safe. Plus redraw ourselves.
+ *
+ * \param evt The event which occurred
+ * \param pw The private pointer for our canvas object
+ */
+static void
+canvas2d__handle_dom_event(dom_event *evt, void *pw)
+{
+ canvas_rendering_context2d_private_t *priv = pw;
+ dom_ulong width;
+ dom_ulong height;
+ dom_exception exc;
+ struct bitmap *newbitmap, *oldbitmap = NULL;
+ size_t stride;
+ dom_event_flow_phase phase;
+
+ exc = dom_event_get_event_phase(evt, &phase);
+ assert(exc == DOM_NO_ERR);
+ /* If we're not being hit right now, we're not up for it */
+ if (phase != DOM_AT_TARGET) return;
+
+ /* Rather than being complex about things, let's just work out
+ * what the width and height are and hope nothing else matters
+ */
+
+ exc = dom_html_canvas_element_get_width(priv->canvas, &width);
+ if (exc != DOM_NO_ERR) return;
+ exc = dom_html_canvas_element_get_height(priv->canvas, &height);
+ if (exc != DOM_NO_ERR) return;
+
+ if ((int)height == priv->height && (int)width == priv->width) return;
+
+ /* Okay, we need to reallocate our bitmap and re-cache values */
+
+ newbitmap = guit->bitmap->create(width, height, BITMAP_NONE);
+ stride = guit->bitmap->get_rowstride(newbitmap);
+
+ if (newbitmap != NULL) {
+ memset(guit->bitmap->get_buffer(newbitmap),
+ 0,
+ stride * height);
+ guit->bitmap->modified(newbitmap);
+ }
+
+ if (dom_node_set_user_data(priv->canvas,
+ corestring_dom___ns_key_canvas_node_data,
+ newbitmap, canvas2d_user_data_handler,
+ &oldbitmap) == DOM_NO_ERR) {
+ if (oldbitmap != NULL)
+ guit->bitmap->destroy(oldbitmap);
+ } else {
+ guit->bitmap->destroy(newbitmap);
+ /* We'll stick with the old, odd though that might be */
+ return;
+ }
+
+ /* Cache the new values */
+ priv->width = (int)width;
+ priv->height = (int)height;
+ priv->stride = stride;
+ priv->bitmap = newbitmap;
+}
+
+typedef struct {
+ uint8_t *ptr;
+ size_t stride;
+ ssize_t width;
+ ssize_t height;
+} raw_bitmap;
+
+typedef struct {
+ raw_bitmap src;
+ raw_bitmap dst;
+ /* These are relative to the destination top/left */
+ ssize_t dst_x;
+ ssize_t dst_y;
+ /* These are relative to the source top/left */
+ ssize_t x1;
+ ssize_t y1;
+ /* And these are +1, so a 1x1 copy will have x2==x1+1 etc */
+ ssize_t x2;
+ ssize_t y2;
+} copy_operation;
+
+/**
+ * Copy from src to dst
+ *
+ * Note, this is destructive to its copy_operation input
+ *
+ * \param op The copy operation to perform
+ * \return Whether the destination bitmap was altered
+ */
+static bool
+canvas2d__copy_bitmap_to_bitmap(copy_operation *op)
+{
+ /* Constrain src rectangle to src bitmap size */
+ if (op->x1 < 0) op->x1 = 0;
+ if (op->y1 < 0) op->y1 = 0;
+ if (op->x2 > op->src.width) op->x2 = op->src.width;
+ if (op->y2 > op->src.height) op->y2 = op->src.height;
+ /* Offset the rectangle into dst coordinates */
+ op->x1 += op->dst_x;
+ op->x2 += op->dst_x;
+ op->y1 += op->dst_y;
+ op->y2 += op->dst_y;
+ /* Constrain dst rectangle to dst bitmap */
+ if (op->x1 < 0) op->x1 = 0;
+ if (op->y1 < 0) op->y1 = 0;
+ if (op->x2 > op->dst.width) op->x2 = op->dst.width;
+ if (op->y2 > op->dst.height) op->y2 = op->dst.height;
+ /* If we have nothing to copy, stop now */
+ if ((op->x2 - op->x1) < 1 ||
+ (op->y2 - op->y1) < 1)
+ return false;
+ /* Okay, stuff to copy, so let's begin */
+ op->src.ptr +=
+ (op->src.stride * (op->y1 - op->dst_y)) + /* move down y1 rows */
+ (op->x1 - op->dst_x) * 4; /* and across x1 pixels */
+ op->dst.ptr +=
+ (op->dst.stride * op->y1) + /* down down y1 rows */
+ (op->x1 * 4); /* and across x1 pixels */
+ for (ssize_t rowctr = op->y2 - op->y1; rowctr > 0; --rowctr) {
+ memcpy(op->dst.ptr, op->src.ptr, (op->x2 - op->x1) * 4);
+ op->src.ptr += op->src.stride;
+ op->dst.ptr += op->dst.stride;
+ }
+ return true;
+}
+
+/* prologue ends */
+%};
+};
+
+init CanvasRenderingContext2D(struct dom_html_canvas_element *canvas)
+%{
+ struct bitmap *bitmap;
+ dom_exception exc;
+
+ assert(canvas != NULL);
+
+ priv->canvas = canvas;
+ dom_node_ref(canvas);
+
+ exc = dom_event_listener_create(canvas2d__handle_dom_event,
+ priv,
+ &priv->listener);
+ assert(exc == DOM_NO_ERR);
+
+ exc = dom_event_target_add_event_listener(
+ canvas,
+ corestring_dom_DOMSubtreeModified,
+ priv->listener,
+ false);
+ assert(exc == DOM_NO_ERR);
+
+ exc = dom_node_get_user_data(canvas,
+ corestring_dom___ns_key_canvas_node_data,
+ &bitmap);
+ assert(exc == DOM_NO_ERR);
+
+ if (bitmap == NULL) {
+ if (canvas2d_create_bitmap((dom_node *)canvas,
+ &bitmap) != NSERROR_OK) {
+ priv->bitmap = NULL;
+ priv->width = -1;
+ priv->height = -1;
+ priv->stride = 0;
+ return;
+ }
+ }
+
+ assert(bitmap != NULL);
+
+ priv->bitmap = bitmap;
+ priv->width = guit->bitmap->get_width(bitmap);
+ priv->height = guit->bitmap->get_height(bitmap);
+ priv->stride = guit->bitmap->get_rowstride(bitmap);
+%}
+
+fini CanvasRenderingContext2D()
+%{
+ dom_exception exc;
+ exc = dom_event_target_remove_event_listener(
+ priv->canvas,
+ corestring_dom_DOMSubtreeModified,
+ priv->listener,
+ false);
+ assert(exc == DOM_NO_ERR);
+ dom_event_listener_unref(priv->listener);
+ dom_node_unref(priv->canvas);
+%}
+
+getter CanvasRenderingContext2D::canvas()
+%{
+ dukky_push_node(ctx, (dom_node *)priv->canvas);
+ return 1;
+%}
+
+getter CanvasRenderingContext2D::width()
+%{
+ dom_exception exc;
+ dom_ulong width;
+
+ exc = dom_html_canvas_element_get_width(priv->canvas, &width);
+ if (exc != DOM_NO_ERR) return 0;
+
+ duk_push_number(ctx, (duk_double_t)width);
+ return 1;
+%}
+
+setter CanvasRenderingContext2D::width()
+%{
+ dom_exception exc;
+ dom_ulong width = duk_get_uint(ctx, 0);
+
+ exc = dom_html_canvas_element_set_width(priv->canvas, width);
+ if (exc != DOM_NO_ERR) return 0;
+
+ return 1;
+%}
+
+getter CanvasRenderingContext2D::height()
+%{
+ dom_exception exc;
+ dom_ulong height;
+
+ exc = dom_html_canvas_element_get_height(priv->canvas, &height);
+ if (exc != DOM_NO_ERR) return 0;
+
+ duk_push_number(ctx, (duk_double_t)height);
+ return 1;
+%}
+
+setter CanvasRenderingContext2D::height()
+%{
+ dom_exception exc;
+ dom_ulong height = duk_get_uint(ctx, 0);
+
+ exc = dom_html_canvas_element_set_height(priv->canvas, height);
+ if (exc != DOM_NO_ERR) return 0;
+
+ return 1;
+%}
+
+method CanvasRenderingContext2D::createImageData()
+%{
+ /* Can be called either with width and height, or with a reference
+ * imagedata object
+ */
+ image_data_private_t *idpriv;
+ int width, height;
+
+ if (duk_get_top(ctx) == 2) {
+ width = duk_to_int(ctx, 0);
+ height = duk_to_int(ctx, 1);
+ } else if (dukky_instanceof(ctx, 0, PROTO_NAME(IMAGEDATA))) {
+ duk_get_prop_string(ctx, 0, dukky_magic_string_private);
+ idpriv = duk_get_pointer(ctx, -1);
+ width = idpriv->width;
+ height = idpriv->height;
+ duk_pop(ctx);
+ } else {
+ duk_push_null(ctx);
+ return 1;
+ }
+
+ duk_push_int(ctx, width);
+ duk_push_int(ctx, height);
+ if (dukky_create_object(ctx,
+ PROTO_NAME(IMAGEDATA),
+ 2) != DUK_EXEC_SUCCESS) {
+ return duk_error(ctx,
+ DUK_ERR_ERROR,
+ "Unable to create ImageData");
+ }
+ return 1;
+%}
+
+method CanvasRenderingContext2D::getImageData()
+%{
+ /* called with x, y, width, height */
+ int x = duk_get_int(ctx, 0);
+ int y = duk_get_int(ctx, 1);
+ int width = duk_get_int(ctx, 2);
+ int height = duk_get_int(ctx, 3);
+ image_data_private_t *idpriv;
+ copy_operation copyop;
+
+ if (priv->bitmap == NULL)
+ return duk_generic_error(ctx, "Canvas in bad state, sorry");
+
+ duk_push_int(ctx, width);
+ duk_push_int(ctx, height);
+ if (dukky_create_object(ctx,
+ PROTO_NAME(IMAGEDATA),
+ 2) != DUK_EXEC_SUCCESS) {
+ return duk_error(ctx,
+ DUK_ERR_ERROR,
+ "Unable to create ImageData");
+ }
+
+ /* ... imgdata */
+ duk_get_prop_string(ctx, -1, dukky_magic_string_private);
+ idpriv = duk_get_pointer(ctx, -1);
+ duk_pop(ctx);
+
+ /* We now have access to the imagedata private, so we need to copy
+ * the pixel range out of ourselves
+ */
+ copyop.src.ptr = guit->bitmap->get_buffer(priv->bitmap);
+ copyop.src.stride = priv->stride;
+ copyop.src.width = priv->width;
+ copyop.src.height = priv->height;
+
+ copyop.dst.ptr = idpriv->data;
+ copyop.dst.stride = idpriv->width * 4;
+ copyop.dst.width = idpriv->width;
+ copyop.dst.height = idpriv->height;
+
+ /* Copying to top/left of our new bitmap */
+ copyop.dst_x = 0;
+ copyop.dst_y = 0;
+
+ /* Copying from x,y for width,height */
+ copyop.x1 = x;
+ copyop.x2 = x + width;
+ copyop.y1 = y;
+ copyop.y2 = y + height;
+
+ /* We don't care if the copy operation wrote or not because
+ * we don't need to invalidate ImageData objects
+ */
+ (void)canvas2d__copy_bitmap_to_bitmap(&copyop);
+ return 1;
+%}
+
+method CanvasRenderingContext2D::putImageData()
+%{
+ /* imgdata, x, y[, clipx, clipy, clipw, cliph] */
+ /* If provided, the clip coordinates are within the input image data */
+ /* We pretend the image is placed at x,y within ourselves, and then we
+ * copy the clip rectangle (defaults to whole image)
+ */
+ image_data_private_t *idpriv;
+ copy_operation copyop;
+
+ if (!dukky_instanceof(ctx, 0, PROTO_NAME(IMAGEDATA))) {
+ return duk_generic_error(ctx, "Expected ImageData as first argument");
+ }
+
+ if (priv->bitmap == NULL)
+ return duk_generic_error(ctx, "Canvas in bad state, sorry");
+
+ duk_get_prop_string(ctx, 0, dukky_magic_string_private);
+ idpriv = duk_get_pointer(ctx, -1);
+ duk_pop(ctx);
+
+ /* Copying from the input ImageData object */
+ copyop.src.ptr = idpriv->data;
+ copyop.src.stride = idpriv->width * 4;
+ copyop.src.width = idpriv->width;
+ copyop.src.height = idpriv->height;
+
+ /* Copying to ourselves */
+ copyop.dst.ptr = guit->bitmap->get_buffer(priv->bitmap);
+ copyop.dst.stride = priv->stride;
+ copyop.dst.width = priv->width;
+ copyop.dst.height = priv->height;
+
+ /* X Y target coordinates */
+ copyop.dst_x = duk_to_int(ctx, 1);
+ copyop.dst_y = duk_to_int(ctx, 2);
+
+ if (duk_get_top(ctx) < 7) {
+ /* Clipping data not provided */
+ copyop.x1 = 0;
+ copyop.y1 = 0;
+ copyop.x2 = idpriv->width;
+ copyop.y2 = idpriv->height;
+ } else {
+ copyop.x1 = duk_to_int(ctx, 3);
+ copyop.y1 = duk_to_int(ctx, 4);
+ copyop.x2 = copyop.x1 + duk_to_int(ctx, 5);
+ copyop.y2 = copyop.y1 + duk_to_int(ctx, 6);
+ }
+
+ if (canvas2d__copy_bitmap_to_bitmap(&copyop)) {
+ guit->bitmap->modified(priv->bitmap);
+ redraw_node((dom_node *)(priv->canvas));
+ }
+
+ return 0;
+%}
diff --git a/content/handlers/javascript/duktape/Console.bnd b/content/handlers/javascript/duktape/Console.bnd
index c4c0c8399..89d13cfad 100644
--- a/content/handlers/javascript/duktape/Console.bnd
+++ b/content/handlers/javascript/duktape/Console.bnd
@@ -13,28 +13,50 @@ class Console {
private unsigned int group;
prologue %{
#include <nsutils/time.h>
+#include "netsurf/browser_window.h"
#define CONSOLE_TIMERS MAGIC(ConsoleTimers)
static void
-write_log_entry(duk_context *ctx, unsigned int group, char logtype)
+write_log_entry(duk_context *ctx, unsigned int group, browser_window_console_flags flags)
{
/* objs... */
+ dukky_push_generics(ctx, "consoleFormatter");
+ duk_insert(ctx, 0);
+ if (dukky_pcall(ctx, duk_get_top(ctx) - 1, false)) {
+ /* Failed to convert somehow, oh dear, you get to keep
+ * all the pieces.
+ */
+ duk_pop(ctx);
+ duk_push_string(ctx, "Oh dear, formatter went banananas");
+ }
+ /* str?objs?... */
for (int i = 0; i < duk_get_top(ctx); ++i) {
(void)duk_safe_to_string(ctx, i);
}
/* strs... */
- duk_push_sprintf(ctx, "%c: ", logtype);
- duk_insert(ctx, 0);
- /* pfx strs... */
for (unsigned int u = 0; u < group; ++u) {
duk_push_lstring(ctx, " ", 1);
duk_insert(ctx, 0);
}
- /* spcs... pfx strs... */
+ /* spcs... strs... */
duk_concat(ctx, duk_get_top(ctx));
/* str */
- NSLOG(netsurf, INFO, "%s", duk_safe_to_string(ctx, 0));
+
+ duk_push_global_object(ctx);
+ duk_get_prop_string(ctx, -1, PRIVATE_MAGIC);
+ window_private_t *priv_win = duk_get_pointer(ctx, -1);
+ duk_pop(ctx);
+
+ duk_size_t msglen;
+ const char *msg = duk_safe_to_lstring(ctx, 0, &msglen);
+
+ if (priv_win == NULL || priv_win->win == NULL || priv_win->closed_down == true ||
+ browser_window_console_log(priv_win->win, BW_CS_SCRIPT_CONSOLE,
+ msg, msglen,
+ flags) != NSERROR_OK) {
+ NSLOG(netsurf, DEBUG, "Unable to log: %s", duk_safe_to_string(ctx, 0));
+ }
}
%};
@@ -68,37 +90,37 @@ method Console::groupEnd ()
method Console::info()
%{
- write_log_entry(ctx, priv->group, 'I');
+ write_log_entry(ctx, priv->group, BW_CS_FLAG_LEVEL_INFO);
return 0;
%}
method Console::debug()
%{
- write_log_entry(ctx, priv->group, 'D');
+ write_log_entry(ctx, priv->group, BW_CS_FLAG_LEVEL_DEBUG);
return 0;
%}
method Console::error()
%{
- write_log_entry(ctx, priv->group, 'E');
+ write_log_entry(ctx, priv->group, BW_CS_FLAG_LEVEL_ERROR);
return 0;
%}
method Console::log()
%{
- write_log_entry(ctx, priv->group, 'L');
+ write_log_entry(ctx, priv->group, BW_CS_FLAG_LEVEL_LOG);
return 0;
%}
method Console::warn()
%{
- write_log_entry(ctx, priv->group, 'W');
+ write_log_entry(ctx, priv->group, BW_CS_FLAG_LEVEL_WARN);
return 0;
%}
method Console::dir()
%{
- write_log_entry(ctx, priv->group, 'd');
+ write_log_entry(ctx, priv->group, BW_CS_FLAG_LEVEL_INFO);
return 0;
%}
@@ -160,8 +182,8 @@ method Console::timeEnd()
duk_del_prop(ctx, 0);
duk_push_string(ctx, "Timer elapsed: ");
duk_insert(ctx, 0);
- duk_push_sprintf(ctx, "%lu ms", (duk_uint_t)(time_ms - old_time_ms));
- write_log_entry(ctx, priv->group, 'T');
+ duk_push_sprintf(ctx, "%u ms", (duk_uint_t)(time_ms - old_time_ms));
+ write_log_entry(ctx, priv->group, BW_CS_FLAG_LEVEL_INFO);
return 0;
%}
@@ -172,6 +194,6 @@ method Console::trace ()
duk_safe_to_string(ctx, -1);
duk_insert(ctx, 0);
duk_set_top(ctx, 1);
- write_log_entry(ctx, priv->group, 'S');
+ write_log_entry(ctx, priv->group, BW_CS_FLAG_LEVEL_INFO);
return 0;
%}
diff --git a/content/handlers/javascript/duktape/DOMImplementation.bnd b/content/handlers/javascript/duktape/DOMImplementation.bnd
new file mode 100644
index 000000000..05c481ddc
--- /dev/null
+++ b/content/handlers/javascript/duktape/DOMImplementation.bnd
@@ -0,0 +1,120 @@
+/* DOMImplementation binding for browser using duktape and libdom
+ *
+ * Copyright 2020 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * Released under the terms of the MIT License,
+ * http://www.opensource.org/licenses/mit-license
+ */
+
+prologue DOMImplementation ()
+%{
+#include "utils/corestrings.h"
+%}
+
+method DOMImplemention::hasFeature ()
+%{
+ /* Always return true */
+ duk_push_bool(ctx, true);
+ return 1;
+%}
+
+method DOMImplementation::createHTMLDocument ()
+%{
+ duk_size_t text_len;
+ const char *text = duk_safe_to_lstring(ctx, 0, &text_len);
+ struct dom_document *doc = NULL, *ret = NULL;
+ struct dom_document_type *doctype = NULL;
+ struct dom_html_element *html = NULL, *head = NULL, *title = NULL, *body = NULL;
+ struct dom_node *spare_ref = NULL;
+ dom_string *text_str = NULL;
+ dom_exception exc;
+
+ exc = dom_string_create((const uint8_t*)text, text_len, &text_str);
+ if (exc != DOM_NO_ERR) goto out;
+
+ exc = dom_implementation_create_document(
+ DOM_IMPLEMENTATION_HTML,
+ NULL, NULL,
+ NULL,
+ NULL, NULL,
+ &doc
+ );
+ if (exc != DOM_NO_ERR) goto out;
+
+ exc = dom_implementation_create_document_type(
+ "html", NULL, NULL, &doctype);
+ if (exc != DOM_NO_ERR) goto out;
+
+ exc = dom_node_append_child(doc, doctype, &spare_ref);
+ if (exc != DOM_NO_ERR) goto out;
+ if (spare_ref != NULL) { dom_node_unref(spare_ref); spare_ref = NULL; }
+
+ exc = dom_document_create_element_ns(doc, corestring_dom_html_namespace,
+ corestring_dom_HTML, &html);
+ if (exc != DOM_NO_ERR) goto out;
+
+ exc = dom_document_create_element_ns(doc, corestring_dom_html_namespace,
+ corestring_dom_HEAD, &head);
+ if (exc != DOM_NO_ERR) goto out;
+
+ exc = dom_document_create_element_ns(doc, corestring_dom_html_namespace,
+ corestring_dom_TITLE, &title);
+ if (exc != DOM_NO_ERR) goto out;
+
+ exc = dom_document_create_element_ns(doc, corestring_dom_html_namespace,
+ corestring_dom_BODY, &body);
+ if (exc != DOM_NO_ERR) goto out;
+
+ exc = dom_node_set_text_content(title, text_str);
+ if (exc != DOM_NO_ERR) goto out;
+
+ exc = dom_node_append_child(head, title, &spare_ref);
+ if (exc != DOM_NO_ERR) goto out;
+ if (spare_ref != NULL) { dom_node_unref(spare_ref); spare_ref = NULL; }
+
+ exc = dom_node_append_child(html, head, &spare_ref);
+ if (exc != DOM_NO_ERR) goto out;
+ if (spare_ref != NULL) { dom_node_unref(spare_ref); spare_ref = NULL; }
+
+ exc = dom_node_append_child(html, body, &spare_ref);
+ if (exc != DOM_NO_ERR) goto out;
+ if (spare_ref != NULL) { dom_node_unref(spare_ref); spare_ref = NULL; }
+
+ exc = dom_node_append_child(doc, html, &spare_ref);
+ if (exc != DOM_NO_ERR) goto out;
+ if (spare_ref != NULL) { dom_node_unref(spare_ref); spare_ref = NULL; }
+
+ ret = doc;
+ doc = NULL;
+
+out:
+ if (text_str != NULL) {
+ dom_string_unref(text_str);
+ }
+ if (doc != NULL) {
+ dom_node_unref(doc);
+ }
+ if (html != NULL) {
+ dom_node_unref(html);
+ }
+ if (head != NULL) {
+ dom_node_unref(head);
+ }
+ if (title != NULL) {
+ dom_node_unref(title);
+ }
+ if (body != NULL) {
+ dom_node_unref(body);
+ }
+ if (doctype != NULL) {
+ dom_node_unref(doctype);
+ }
+ if (ret != NULL) {
+ dukky_push_node(ctx, (struct dom_node *)ret);
+ dom_node_unref(ret);
+ return 1;
+ }
+ return 0; /* Coerced to undefined */
+%}
diff --git a/content/handlers/javascript/duktape/DOMSettableTokenList.bnd b/content/handlers/javascript/duktape/DOMSettableTokenList.bnd
new file mode 100644
index 000000000..ac5c7062a
--- /dev/null
+++ b/content/handlers/javascript/duktape/DOMSettableTokenList.bnd
@@ -0,0 +1,44 @@
+/* DOMTokenList binding for browser using duktape and libdom
+ *
+ * Copyright 2015 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * Released under the terms of the MIT License,
+ * http://www.opensource.org/licenses/mit-license
+ */
+
+class DOMSettableTokenList {
+};
+
+init DOMSettableTokenList(struct dom_tokenlist *tokens::tokens);
+
+getter DOMSettableTokenList::value()
+%{
+ dom_exception exc;
+ dom_string *value;
+
+ exc = dom_tokenlist_get_value(priv->parent.tokens, &value);
+ if (exc != DOM_NO_ERR) return 0; /* coerced to undefined */
+
+ duk_push_lstring(ctx, dom_string_data(value), dom_string_length(value));
+ dom_string_unref(value);
+
+ return 1;
+%}
+
+setter DOMSettableTokenList::value()
+%{
+ dom_exception exc;
+ dom_string *value;
+ duk_size_t slen;
+ const char *s = duk_require_lstring(ctx, 0, &slen);
+
+ exc = dom_string_create_interned((const uint8_t *)s, slen, &value);
+ if (exc != DOM_NO_ERR) return 0;
+
+ exc = dom_tokenlist_set_value(priv->parent.tokens, value);
+ dom_string_unref(value);
+
+ return 0;
+%} \ No newline at end of file
diff --git a/content/handlers/javascript/duktape/DOMTokenList.bnd b/content/handlers/javascript/duktape/DOMTokenList.bnd
new file mode 100644
index 000000000..928d9ef35
--- /dev/null
+++ b/content/handlers/javascript/duktape/DOMTokenList.bnd
@@ -0,0 +1,163 @@
+/* DOMTokenList binding for browser using duktape and libdom
+ *
+ * Copyright 2015 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * Released under the terms of the MIT License,
+ * http://www.opensource.org/licenses/mit-license
+ */
+
+class DOMTokenList {
+ private struct dom_tokenlist *tokens;
+};
+
+init DOMTokenList(struct dom_tokenlist *tokens)
+%{
+ priv->tokens = tokens;
+ dom_tokenlist_ref(tokens);
+%}
+
+fini DOMTokenList()
+%{
+ dom_tokenlist_unref(priv->tokens);
+%}
+
+getter DOMTokenList::length()
+%{
+ dom_exception err;
+ uint32_t len;
+
+ err = dom_tokenlist_get_length(priv->tokens, &len);
+
+ if (err != DOM_NO_ERR) return 0; /* coerced to undefined */
+
+ duk_push_uint(ctx, (duk_uint_t)len);
+
+ return 1;
+%}
+
+method DOMTokenList::item()
+%{
+ unsigned long i = duk_to_uint(ctx, 0);
+ dom_exception err;
+ dom_string *value;
+
+ err = dom_tokenlist_item(priv->tokens, i, &value);
+
+ if (err != DOM_NO_ERR) return 0; /* coerced to undefined */
+
+ if (value == NULL) {
+ duk_push_null(ctx);
+ return 1;
+ }
+
+ duk_push_lstring(ctx, dom_string_data(value), dom_string_length(value));
+ dom_string_unref(value);
+
+ return 1;
+%}
+
+method DOMTokenList::add()
+%{
+ dom_exception exc;
+ dom_string *value;
+ duk_size_t slen;
+ const char *s;
+ duk_idx_t spos;
+
+ for (spos = 0; spos < duk_get_top(ctx); ++spos) {
+ s = duk_safe_to_lstring(ctx, spos, &slen);
+
+ duk_safe_to_lstring(ctx, 0, &slen);
+
+ exc = dom_string_create_interned((const uint8_t *)s, slen, &value);
+ if (exc != DOM_NO_ERR) return 0;
+
+ exc = dom_tokenlist_add(priv->tokens, value);
+ dom_string_unref(value);
+ }
+
+ return 0;
+%}
+
+method DOMTokenList::remove()
+%{
+ dom_exception exc;
+ dom_string *value;
+ duk_size_t slen;
+ const char *s;
+ duk_idx_t spos;
+
+ for (spos = 0; spos < duk_get_top(ctx); ++spos) {
+ s = duk_safe_to_lstring(ctx, spos, &slen);
+
+ duk_safe_to_lstring(ctx, 0, &slen);
+
+ exc = dom_string_create_interned((const uint8_t *)s, slen, &value);
+ if (exc != DOM_NO_ERR) return 0;
+
+ exc = dom_tokenlist_remove(priv->tokens, value);
+ dom_string_unref(value);
+ }
+
+ return 0;
+%}
+
+method DOMTokenList::contains()
+%{
+ dom_exception exc;
+ dom_string *value;
+ duk_size_t slen;
+ const char *s = duk_safe_to_lstring(ctx, 0, &slen);
+ bool present = false;
+
+ exc = dom_string_create_interned((const uint8_t *)s, slen, &value);
+ if (exc != DOM_NO_ERR) return 0;
+
+ exc = dom_tokenlist_contains(priv->tokens, value, &present);
+ dom_string_unref(value);
+ if (exc != DOM_NO_ERR) return 0;
+
+ duk_push_boolean(ctx, present);
+
+ return 1;
+%}
+
+method DOMTokenList::toggle()
+%{
+ dom_exception exc;
+ dom_string *value;
+ duk_size_t slen;
+ const char *s = duk_require_lstring(ctx, 0, &slen);
+ bool toggle_set = duk_get_top(ctx) > 1;
+ bool toggle = duk_opt_boolean(ctx, 1, 0);
+ bool present;
+
+ exc = dom_string_create_interned((const uint8_t *)s, slen, &value);
+ if (exc != DOM_NO_ERR) return 0;
+
+ exc = dom_tokenlist_contains(priv->tokens, value, &present);
+ if (exc != DOM_NO_ERR) {
+ dom_string_unref(value);
+ return 0;
+ }
+
+ /* Decision matrix is based on present, toggle_set, and toggle */
+ if (toggle_set) {
+ if (toggle) {
+ exc = dom_tokenlist_add(priv->tokens, value);
+ } else {
+ exc = dom_tokenlist_remove(priv->tokens, value);
+ }
+ } else {
+ if (present) {
+ exc = dom_tokenlist_add(priv->tokens, value);
+ } else {
+ exc = dom_tokenlist_remove(priv->tokens, value);
+ }
+ }
+ dom_string_unref(value);
+
+ return 0;
+%} \ No newline at end of file
diff --git a/content/handlers/javascript/duktape/Document.bnd b/content/handlers/javascript/duktape/Document.bnd
index ece417d0d..2f9adc380 100644
--- a/content/handlers/javascript/duktape/Document.bnd
+++ b/content/handlers/javascript/duktape/Document.bnd
@@ -14,7 +14,7 @@ prologue Document()
#include "utils/libdom.h"
#include "utils/utils.h"
#include "content/hlcache.h"
-#include "render/html_internal.h"
+#include "html/private.h"
#include "content/urldb.h"
#define HANDLER_MAGIC MAGIC(HANDLER_MAP)
@@ -35,7 +35,7 @@ method Document::write()
}
duk_concat(ctx, duk_get_top(ctx));
text = duk_safe_to_lstring(ctx, 0, &text_len);
- JS_LOG("Writing %*s", (int)text_len, text);
+ NSLOG(netsurf, DEBUG, "Writing %*s", (int)text_len, text);
err = dom_node_get_user_data(priv->parent.node,
corestring_dom___ns_key_html_content_data,
@@ -70,7 +70,7 @@ method Document::writeln()
duk_concat(ctx, duk_get_top(ctx));
text = duk_safe_to_lstring(ctx, 0, &text_len);
- JS_LOG("Writeln %*s", (int)text_len, text);
+ NSLOG(netsurf, DEBUG, "Writeln %*s", (int)text_len, text);
err = dom_node_get_user_data(priv->parent.node,
corestring_dom___ns_key_html_content_data,
&htmlc);
@@ -147,6 +147,62 @@ method Document::createElement()
return 1;
%}
+method Document::createElementNS()
+%{
+ dom_node *newnode;
+ dom_exception err;
+ duk_size_t text_len;
+ duk_size_t ns_len;
+ const char *ns = duk_safe_to_lstring(ctx, 0, &ns_len);
+ const char *text = duk_safe_to_lstring(ctx, 0, &text_len);
+ dom_string *text_str;
+ dom_string *ns_str;
+
+ err = dom_string_create((const uint8_t*)ns, ns_len, &ns_str);
+ if (err != DOM_NO_ERR) return 0; /* coerced to undefined */
+
+ err = dom_string_create((const uint8_t*)text, text_len, &text_str);
+ if (err != DOM_NO_ERR) {
+ dom_string_unref(ns_str);
+ return 0; /* coerced to undefined */
+ }
+
+ err = dom_document_create_element_ns(priv->parent.node,
+ ns_str,
+ text_str,
+ &newnode);
+ if (err != DOM_NO_ERR) {
+ dom_string_unref(ns_str);
+ dom_string_unref(text_str);
+ return 0; /* coerced to undefined */
+ }
+
+ dom_string_unref(text_str);
+ dom_string_unref(ns_str);
+
+ dukky_push_node(ctx, newnode);
+
+ dom_node_unref(newnode);
+
+ return 1;
+%}
+
+method Document::createDocumentFragment()
+%{
+ struct dom_document_fragment *frag = NULL;
+ dom_exception err;
+
+ err = dom_document_create_document_fragment(priv->parent.node, &frag);
+
+ if (err != DOM_NO_ERR) return 0; /* coerced to undefined */
+
+ dukky_push_node(ctx, (dom_node *)frag);
+
+ dom_node_unref(frag); /* The pushed node holds the reference now */
+
+ return 1;
+%}
+
getter Document::head()
%{
struct dom_nodelist *nodes;
@@ -290,10 +346,18 @@ method Document::getElementsByTagName()
if (nodes == NULL) return 0; /* coerced to undefined */
+ dukky_push_generics(ctx, "makeListProxy");
+
duk_push_pointer(ctx, nodes);
dukky_create_object(ctx, PROTO_NAME(NODELIST), 1);
dom_nodelist_unref(nodes);
- return 1;
+
+ if (dukky_pcall(ctx, 1, false) != 0) {
+ NSLOG(dukky, DEBUG, "Unable to construct nodelist?");
+ return 0; /* coerced to undefined */
+ }
+
+ return 1; /* The Proxy(NodeList) wrapper */
%}
getter Document::cookie()
@@ -310,7 +374,39 @@ getter Document::cookie()
if (cookie_str != NULL) {
duk_push_string(ctx, cookie_str);
free(cookie_str);
- return 1;
+ } else {
+ duk_push_string(ctx, "");
+ }
+ return 1;
+ } else {
+ NSLOG(netsurf, INFO,
+ "error getting htmlc. parent node:%p htmlc:%p",
+ priv->parent.node, htmlc);
+ }
+ return 0;
+%}
+
+setter Document::cookie()
+%{
+ struct html_content *htmlc;
+ dom_exception err;
+
+ const char * cookie_str = duk_safe_to_string(ctx, 0);
+
+ err = dom_node_get_user_data(priv->parent.node,
+ corestring_dom___ns_key_html_content_data,
+ &htmlc);
+ if ((err == DOM_NO_ERR) && (htmlc != NULL)) {
+ /* At this point we need to get the given cookie string parsed
+ * and inserted into the urldb
+ */
+ bool ok = urldb_set_cookie(cookie_str, /* The cookie string to set */
+ /* The location to set the cookie for */
+ llcache_handle_get_url(htmlc->base.llcache),
+ NULL); /* The referer, which we trust */
+ if (!ok) {
+ NSLOG(netsurf, DEEPDEBUG, "unable to set cookie: %s", cookie_str);
+ /* However there's no useful way to signal that to JS */
}
} else {
NSLOG(netsurf, INFO,
@@ -320,6 +416,44 @@ getter Document::cookie()
return 0;
%}
+method Document::createEvent ()
+%{
+ /* Create a new event, mark it untrusted since it's new from JS */
+ dom_event *evt = NULL;
+ dom_exception exc;
+
+ exc = dom_event_create(&evt);
+ if (exc != DOM_NO_ERR) return 0;
+ exc = dom_event_set_is_trusted(evt, false);
+ if (exc != DOM_NO_ERR) { dom_event_unref(evt); return 0; }
+
+ dukky_push_event(ctx, evt);
+
+ dom_event_unref(evt);
+ return 1;
+%}
+
+getter Document::implementation ()
+%{
+ /* Create a new DOMImplementation instance */
+ duk_push_this(ctx);
+ duk_get_prop_string(ctx, -1, MAGIC(DOMImplementation));
+ if (duk_is_undefined(ctx, -1)) {
+ duk_pop(ctx);
+
+ if (dukky_create_object(ctx,
+ PROTO_NAME(DOMIMPLEMENTATION),
+ 0) != DUK_EXEC_SUCCESS) {
+ return duk_error(ctx,
+ DUK_ERR_ERROR,
+ "Unable to create dom implementation object");
+ }
+ duk_dup(ctx, -1);
+ duk_put_prop_string(ctx, -3, MAGIC(DOMImplementation));
+ }
+ return 1;
+%}
+
getter Document::onabort();
setter Document::onabort();
getter Document::onautocompleteerror();
diff --git a/content/handlers/javascript/duktape/Element.bnd b/content/handlers/javascript/duktape/Element.bnd
index f7e33545f..ff0686fd9 100644
--- a/content/handlers/javascript/duktape/Element.bnd
+++ b/content/handlers/javascript/duktape/Element.bnd
@@ -11,6 +11,7 @@
class Element {
prologue %{
#include <utils/corestrings.h>
+#include <dom/bindings/hubbub/parser.h>
%};
};
@@ -204,10 +205,18 @@ method Element::getElementsByTagName ()
tagname, &nlist);
dom_string_unref(tagname);
if (exc != DOM_NO_ERR) return 0;
+
+ dukky_push_generics(ctx, "makeListProxy");
+
duk_push_pointer(ctx, nlist);
dukky_create_object(ctx, PROTO_NAME(NODELIST), 1);
dom_nodelist_unref(nlist);
+ if (dukky_pcall(ctx, 1, false) != 0) {
+ NSLOG(dukky, DEBUG, "Unable to construct nodelist?");
+ return 0; /* coerced to undefined */
+ }
+
return 1;
%}
@@ -275,6 +284,9 @@ method Element::getAttribute()
const char *s = duk_safe_to_lstring(ctx, 0, &slen);
exc = dom_string_create((const uint8_t *)s, slen, &attr_name);
duk_pop(ctx);
+ if (exc != DOM_NO_ERR) {
+ return 0;
+ }
exc = dom_element_get_attribute(priv->parent.node,
attr_name, &attr_value);
@@ -328,6 +340,9 @@ method Element::hasAttribute()
const char *s = duk_safe_to_lstring(ctx, 0, &slen);
exc = dom_string_create((const uint8_t *)s, slen, &attr_name);
duk_pop(ctx);
+ if (exc != DOM_NO_ERR) {
+ return 0;
+ }
exc = dom_element_has_attribute(priv->parent.node,
attr_name, &res);
@@ -377,3 +392,184 @@ setter Element::className ()
return 0;
%}
+getter Element::classList ()
+%{
+ dom_exception exc;
+ dom_tokenlist *tokens;
+
+ duk_set_top(ctx, 0);
+ duk_push_this(ctx);
+ duk_get_prop_string(ctx, 0, MAGIC(classList));
+
+ if (duk_is_undefined(ctx, -1)) {
+ duk_pop(ctx);
+ exc = dom_tokenlist_create((dom_element *)priv->parent.node, corestring_dom_class, &tokens);
+ if (exc != DOM_NO_ERR) return 0; /* Coerced to undefined */
+
+ /* Create a settable tokenlist - While the IDL says this isn't settable, all browsers
+ * seem to make it settable, so we'll permit it too
+ */
+ duk_push_pointer(ctx, tokens);
+ if (dukky_create_object(ctx, PROTO_NAME(DOMSETTABLETOKENLIST), 1) != DUK_EXEC_SUCCESS) {
+ dom_tokenlist_unref(tokens);
+ NSLOG(dukky, DEBUG, "Unable to create DOMSettableTokenList object");
+ return 0; /* Coerced to undefined */
+ }
+ dom_tokenlist_unref(tokens);
+ duk_dup(ctx, -1);
+ duk_put_prop_string(ctx, 0, MAGIC(classList));
+ }
+
+ return 1;
+%}
+
+getter Element::innerHTML()
+%{
+ duk_push_lstring(ctx, "", 0);
+ return 1;
+%}
+
+setter Element::innerHTML()
+%{
+ duk_size_t size;
+ const char *s = duk_safe_to_lstring(ctx, 0, &size);
+ dom_hubbub_parser_params parse_params;
+ dom_hubbub_error error;
+ dom_hubbub_parser *parser = NULL;
+ struct dom_document *doc = NULL;
+ struct dom_document_fragment *fragment = NULL;
+ dom_exception exc;
+ struct dom_node *child = NULL, *html = NULL, *body = NULL;
+ struct dom_nodelist *bodies = NULL;
+
+ exc = dom_node_get_owner_document(priv->parent.node, &doc);
+ if (exc != DOM_NO_ERR) goto out;
+
+ parse_params.enc = "UTF-8";
+ parse_params.fix_enc = true;
+ parse_params.enable_script = false;
+ parse_params.msg = NULL;
+ parse_params.script = NULL;
+ parse_params.ctx = NULL;
+ parse_params.daf = NULL;
+
+ error = dom_hubbub_fragment_parser_create(&parse_params,
+ doc,
+ &parser,
+ &fragment);
+ if (error != DOM_HUBBUB_OK) {
+ NSLOG(netsurf, ERROR, "Unable to create fragment parser!");
+ goto out;
+ }
+
+ error = dom_hubbub_parser_parse_chunk(parser, (const uint8_t*)s, size);
+ if (error != DOM_HUBBUB_OK) {
+ NSLOG(netsurf, ERROR, "Unable to parse HTML chunk");
+ goto out;
+ }
+ error = dom_hubbub_parser_completed(parser);
+ if (error != DOM_HUBBUB_OK) {
+ NSLOG(netsurf, ERROR, "Unable to complete parser");
+ goto out;
+ }
+
+ /* Parse is finished, transfer contents of fragment into node */
+
+ /* 1. empty this node */
+ exc = dom_node_get_first_child(priv->parent.node, &child);
+ if (exc != DOM_NO_ERR) goto out;
+ while (child != NULL) {
+ struct dom_node *cref;
+ exc = dom_node_remove_child(priv->parent.node, child, &cref);
+ if (exc != DOM_NO_ERR) goto out;
+ dom_node_unref(child);
+ child = NULL;
+ dom_node_unref(cref);
+ exc = dom_node_get_first_child(priv->parent.node, &child);
+ if (exc != DOM_NO_ERR) goto out;
+ }
+
+ /* 2. the first child in the fragment will be an HTML element
+ * because that's how hubbub works, walk through that to the body
+ * element hubbub will have created, we want to migrate that element's
+ * children into ourself.
+ */
+ exc = dom_node_get_first_child(fragment, &html);
+ if (exc != DOM_NO_ERR) goto out;
+
+ /* We can then ask that HTML element to give us its body */
+ exc = dom_element_get_elements_by_tag_name(html, corestring_dom_BODY, &bodies);
+ if (exc != DOM_NO_ERR) goto out;
+
+ /* And now we can get the body which will be the zeroth body */
+ exc = dom_nodelist_item(bodies, 0, &body);
+ if (exc != DOM_NO_ERR) goto out;
+
+ /* 3. Migrate the children */
+ exc = dom_node_get_first_child(body, &child);
+ if (exc != DOM_NO_ERR) goto out;
+ while (child != NULL) {
+ struct dom_node *cref;
+ exc = dom_node_remove_child(body, child, &cref);
+ if (exc != DOM_NO_ERR) goto out;
+ dom_node_unref(cref);
+ exc = dom_node_append_child(priv->parent.node, child, &cref);
+ if (exc != DOM_NO_ERR) goto out;
+ dom_node_unref(cref);
+ dom_node_unref(child);
+ child = NULL;
+ exc = dom_node_get_first_child(body, &child);
+ if (exc != DOM_NO_ERR) goto out;
+ }
+out:
+ if (parser != NULL) {
+ dom_hubbub_parser_destroy(parser);
+ }
+ if (doc != NULL) {
+ dom_node_unref(doc);
+ }
+ if (fragment != NULL) {
+ dom_node_unref(fragment);
+ }
+ if (child != NULL) {
+ dom_node_unref(child);
+ }
+ if (html != NULL) {
+ dom_node_unref(html);
+ }
+ if (bodies != NULL) {
+ dom_nodelist_unref(bodies);
+ }
+ if (body != NULL) {
+ dom_node_unref(body);
+ }
+ return 0;
+%}
+
+getter Element::attributes()
+%{
+ dom_exception exc;
+ dom_namednodemap *nmap = NULL;
+ duk_set_top(ctx, 0);
+ duk_push_this(ctx);
+ duk_get_prop_string(ctx, 0, MAGIC(attributes));
+ if (duk_is_undefined(ctx, -1)) {
+ duk_pop(ctx);
+ exc = dom_node_get_attributes(priv->parent.node, &nmap);
+ if (exc != DOM_NO_ERR) return 0;
+ dukky_push_generics(ctx, "makeNodeMapProxy");
+ duk_push_pointer(ctx, nmap);
+ if (dukky_create_object(ctx, PROTO_NAME(NAMEDNODEMAP), 1) != DUK_EXEC_SUCCESS) {
+ dom_namednodemap_unref(nmap);
+ return 0;
+ }
+ dom_namednodemap_unref(nmap);
+ if (dukky_pcall(ctx, 1, false) != 0) {
+ NSLOG(dukky, DEBUG, "Unable to construct nodelist?");
+ return 0; /* coerced to undefined */
+ }
+ duk_dup(ctx, -1);
+ duk_put_prop_string(ctx, 0, MAGIC(attributes));
+ }
+ return 1;
+%}
diff --git a/content/handlers/javascript/duktape/Event.bnd b/content/handlers/javascript/duktape/Event.bnd
index a0bc3c3e7..2c24cfa73 100644
--- a/content/handlers/javascript/duktape/Event.bnd
+++ b/content/handlers/javascript/duktape/Event.bnd
@@ -54,6 +54,8 @@ getter Event::target ()
if (exc != DOM_NO_ERR) return 0;
dukky_push_node(ctx, et);
+
+ dom_node_unref(et);
return 1;
%}
@@ -67,6 +69,8 @@ getter Event::currentTarget ()
if (exc != DOM_NO_ERR) return 0;
dukky_push_node(ctx, et);
+
+ dom_node_unref(et);
return 1;
%}
@@ -148,3 +152,40 @@ getter Event::defaultPrevented ()
return 1;
%}
+getter Event::isTrusted ()
+%{
+ dom_exception exc;
+ bool ret;
+
+ exc = dom_event_get_is_trusted(priv->evt, &ret);
+ if (exc != DOM_NO_ERR) return 0;
+
+ duk_push_boolean(ctx, ret);
+ return 1;
+%}
+
+
+method Event::initEvent ()
+%{
+ dom_exception exc;
+ bool bubbles;
+ bool cancellable;
+
+ duk_size_t text_len;
+ const char *text = duk_safe_to_lstring(ctx, 0, &text_len);
+ dom_string *text_str;
+
+ exc = dom_string_create((const uint8_t*)text, text_len, &text_str);
+ if (exc != DOM_NO_ERR) return 0; /* coerced to undefined */
+
+ bubbles = duk_get_boolean(ctx, 1);
+ cancellable = duk_get_boolean(ctx, 2);
+
+ exc = dom_event_init(priv->evt, text_str, bubbles, cancellable);
+ dom_string_unref(text_str);
+ if (exc != DOM_NO_ERR) {
+ return 0;
+ }
+
+ return 0;
+%}
diff --git a/content/handlers/javascript/duktape/HTMLBodyElement.bnd b/content/handlers/javascript/duktape/HTMLBodyElement.bnd
index a283f897c..478739651 100644
--- a/content/handlers/javascript/duktape/HTMLBodyElement.bnd
+++ b/content/handlers/javascript/duktape/HTMLBodyElement.bnd
@@ -8,6 +8,13 @@
* http://www.opensource.org/licenses/mit-license
*/
+prologue HTMLBodyElement()
+%{
+#include "utils/corestrings.h"
+
+#define HANDLER_MAGIC MAGIC(HANDLER_MAP)
+%}
+
init HTMLBodyElement(struct dom_html_element *html_body_element::html_element);
getter HTMLBodyElement::aLink();
@@ -22,3 +29,29 @@ getter HTMLBodyElement::text();
setter HTMLBodyElement::text();
getter HTMLBodyElement::vLink();
setter HTMLBodyElement::vLink();
+getter HTMLBodyElement::onafterprint();
+setter HTMLBodyElement::onafterprint();
+getter HTMLBodyElement::onbeforeprint();
+setter HTMLBodyElement::onbeforeprint();
+getter HTMLBodyElement::onbeforeunload();
+setter HTMLBodyElement::onbeforeunload();
+getter HTMLBodyElement::onhashchange();
+setter HTMLBodyElement::onhashchange();
+getter HTMLBodyElement::onlanguagechange();
+setter HTMLBodyElement::onlanguagechange();
+getter HTMLBodyElement::onmessage();
+setter HTMLBodyElement::onmessage();
+getter HTMLBodyElement::onoffline();
+setter HTMLBodyElement::onoffline();
+getter HTMLBodyElement::ononline();
+setter HTMLBodyElement::ononline();
+getter HTMLBodyElement::onpagehide();
+setter HTMLBodyElement::onpagehide();
+getter HTMLBodyElement::onpageshow();
+setter HTMLBodyElement::onpageshow();
+getter HTMLBodyElement::onpopstate();
+setter HTMLBodyElement::onpopstate();
+getter HTMLBodyElement::onstorage();
+setter HTMLBodyElement::onstorage();
+getter HTMLBodyElement::onunload();
+setter HTMLBodyElement::onunload();
diff --git a/content/handlers/javascript/duktape/HTMLCanvasElement.bnd b/content/handlers/javascript/duktape/HTMLCanvasElement.bnd
new file mode 100644
index 000000000..da9f66dee
--- /dev/null
+++ b/content/handlers/javascript/duktape/HTMLCanvasElement.bnd
@@ -0,0 +1,47 @@
+/* HTML canvas element binding using duktape and libdom
+ *
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ * Copyright 2020 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * Released under the terms of the MIT License,
+ * http://www.opensource.org/licenses/mit-license
+ */
+
+init HTMLCanvasElement(struct dom_html_element *html_canvas_element::html_element);
+
+getter HTMLCanvasElement::width();
+setter HTMLCanvasElement::width();
+
+getter HTMLCanvasElement::height();
+setter HTMLCanvasElement::height();
+
+method HTMLCanvasElement::getContext()
+%{
+ /* modetype[, {options}] */
+ const char *modetype = duk_to_string(ctx, 0);
+ if (strcmp(modetype, "2d") != 0) {
+ duk_push_null(ctx);
+ return 1;
+ }
+
+ duk_push_this(ctx);
+ duk_get_prop_string(ctx, -1, MAGIC(Context2D));
+ if (duk_is_undefined(ctx, -1)) {
+ duk_pop(ctx);
+
+ duk_push_pointer(ctx, ((node_private_t*)priv)->node);
+ if (dukky_create_object(ctx,
+ PROTO_NAME(CANVASRENDERINGCONTEXT2D),
+ 1) != DUK_EXEC_SUCCESS) {
+ return duk_error(ctx,
+ DUK_ERR_ERROR,
+ "Unable to create CanvasRenderingContext2D");
+ }
+ duk_dup(ctx, -1);
+ duk_put_prop_string(ctx, -3, MAGIC(Context2D));
+ }
+ return 1;
+%}
+
diff --git a/content/handlers/javascript/duktape/HTMLFrameSetElement.bnd b/content/handlers/javascript/duktape/HTMLFrameSetElement.bnd
index cc66e93d8..e72c17749 100644
--- a/content/handlers/javascript/duktape/HTMLFrameSetElement.bnd
+++ b/content/handlers/javascript/duktape/HTMLFrameSetElement.bnd
@@ -8,6 +8,13 @@
* http://www.opensource.org/licenses/mit-license
*/
+prologue HTMLFrameSetElement()
+%{
+#include "utils/corestrings.h"
+
+#define HANDLER_MAGIC MAGIC(HANDLER_MAP)
+%}
+
init HTMLFrameSetElement(struct dom_html_element *html_frame_set_element::html_element);
getter HTMLFrameSetElement::cols();
@@ -15,3 +22,30 @@ setter HTMLFrameSetElement::cols();
getter HTMLFrameSetElement::rows();
setter HTMLFrameSetElement::rows();
+
+getter HTMLFrameSetElement::onafterprint();
+setter HTMLFrameSetElement::onafterprint();
+getter HTMLFrameSetElement::onbeforeprint();
+setter HTMLFrameSetElement::onbeforeprint();
+getter HTMLFrameSetElement::onbeforeunload();
+setter HTMLFrameSetElement::onbeforeunload();
+getter HTMLFrameSetElement::onhashchange();
+setter HTMLFrameSetElement::onhashchange();
+getter HTMLFrameSetElement::onlanguagechange();
+setter HTMLFrameSetElement::onlanguagechange();
+getter HTMLFrameSetElement::onmessage();
+setter HTMLFrameSetElement::onmessage();
+getter HTMLFrameSetElement::onoffline();
+setter HTMLFrameSetElement::onoffline();
+getter HTMLFrameSetElement::ononline();
+setter HTMLFrameSetElement::ononline();
+getter HTMLFrameSetElement::onpagehide();
+setter HTMLFrameSetElement::onpagehide();
+getter HTMLFrameSetElement::onpageshow();
+setter HTMLFrameSetElement::onpageshow();
+getter HTMLFrameSetElement::onpopstate();
+setter HTMLFrameSetElement::onpopstate();
+getter HTMLFrameSetElement::onstorage();
+setter HTMLFrameSetElement::onstorage();
+getter HTMLFrameSetElement::onunload();
+setter HTMLFrameSetElement::onunload();
diff --git a/content/handlers/javascript/duktape/ImageData.bnd b/content/handlers/javascript/duktape/ImageData.bnd
new file mode 100644
index 000000000..be28cbd77
--- /dev/null
+++ b/content/handlers/javascript/duktape/ImageData.bnd
@@ -0,0 +1,44 @@
+/* HTML canvas ImageData objects
+ *
+ * Copyright 2020 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * Released under the terms of the MIT License,
+ * http://www.opensource.org/licenses/mit-license
+ */
+
+class ImageData {
+ private int width;
+ private int height;
+ private uint8_t *data;
+};
+
+init ImageData(int width, int height)
+%{
+ priv->width = width;
+ priv->height = height;
+ priv->data = duk_push_buffer(ctx, width * height * 4, false);
+ duk_put_prop_string(ctx, 0, MAGIC(DATA));
+ duk_pop(ctx);
+%}
+
+getter ImageData::width()
+%{
+ duk_push_int(ctx, priv->width);
+ return 1;
+%}
+
+getter ImageData::height()
+%{
+ duk_push_int(ctx, priv->height);
+ return 1;
+%}
+
+getter ImageData::data()
+%{
+ duk_push_this(ctx);
+ duk_get_prop_string(ctx, -1, MAGIC(DATA));
+ duk_push_buffer_object(ctx, -1, 0, priv->width * priv->height * 4llu, DUK_BUFOBJ_UINT8CLAMPEDARRAY);
+ return 1;
+%}
diff --git a/content/handlers/javascript/duktape/KeyboardEvent.bnd b/content/handlers/javascript/duktape/KeyboardEvent.bnd
new file mode 100644
index 000000000..67c4564c9
--- /dev/null
+++ b/content/handlers/javascript/duktape/KeyboardEvent.bnd
@@ -0,0 +1,142 @@
+/* Binding for browser using duktape and libdom
+ *
+ * Copyright 2019 Michael Drake <tlsa@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * Released under the terms of the MIT License,
+ * http://www.opensource.org/licenses/mit-license
+ */
+
+init KeyboardEvent (struct dom_keyboard_event *evt::ui_event);
+
+getter KeyboardEvent::key ()
+%{
+ dom_exception err;
+ dom_string *key;
+
+ err = dom_keyboard_event_get_key(priv->parent.parent.evt, &key);
+ if (err != DOM_NO_ERR) {
+ return 0;
+ }
+
+ duk_push_lstring(ctx, dom_string_data(key), dom_string_length(key));
+ dom_string_unref(key);
+ return 1;
+%}
+
+getter KeyboardEvent::code ()
+%{
+ dom_exception err;
+ dom_string *code;
+
+ err = dom_keyboard_event_get_code(priv->parent.parent.evt, &code);
+ if (err != DOM_NO_ERR) {
+ return 0;
+ }
+
+ duk_push_lstring(ctx, dom_string_data(code), dom_string_length(code));
+ dom_string_unref(code);
+ return 1;
+%}
+
+getter KeyboardEvent::location ()
+%{
+ dom_exception err;
+ dom_key_location location;
+
+ err = dom_keyboard_event_get_location(priv->parent.parent.evt,
+ &location);
+ if (err != DOM_NO_ERR) {
+ return 0;
+ }
+
+ duk_push_uint(ctx, (duk_uint_t) location);
+ return 1;
+%}
+
+getter KeyboardEvent::ctrlKey ()
+%{
+ dom_exception err;
+ bool ctrl_key;
+
+ err = dom_keyboard_event_get_ctrl_key(priv->parent.parent.evt,
+ &ctrl_key);
+ if (err != DOM_NO_ERR) {
+ return 0;
+ }
+
+ duk_push_boolean(ctx, (duk_bool_t) ctrl_key);
+ return 1;
+%}
+
+getter KeyboardEvent::shiftKey ()
+%{
+ dom_exception err;
+ bool shift_key;
+
+ err = dom_keyboard_event_get_shift_key(priv->parent.parent.evt,
+ &shift_key);
+ if (err != DOM_NO_ERR) {
+ return 0;
+ }
+
+ duk_push_boolean(ctx, (duk_bool_t) shift_key);
+ return 1;
+%}
+
+getter KeyboardEvent::altKey ()
+%{
+ dom_exception err;
+ bool alt_key;
+
+ err = dom_keyboard_event_get_alt_key(priv->parent.parent.evt,
+ &alt_key);
+ if (err != DOM_NO_ERR) {
+ return 0;
+ }
+
+ duk_push_boolean(ctx, (duk_bool_t) alt_key);
+ return 1;
+%}
+
+getter KeyboardEvent::metaKey ()
+%{
+ dom_exception err;
+ bool meta_key;
+
+ err = dom_keyboard_event_get_meta_key(priv->parent.parent.evt,
+ &meta_key);
+ if (err != DOM_NO_ERR) {
+ return 0;
+ }
+
+ duk_push_boolean(ctx, (duk_bool_t) meta_key);
+ return 1;
+%}
+
+method KeyboardEvent::getModifierState ()
+%{
+ dom_string *modifier;
+ dom_exception err;
+ duk_size_t slen;
+ const char *s;
+ bool state;
+
+ s = duk_safe_to_lstring(ctx, 0, &slen);
+ err = dom_string_create((const uint8_t *)s, slen, &modifier);
+ duk_pop(ctx);
+ if (err != DOM_NO_ERR) {
+ return 0;
+ }
+
+ err = dom_keyboard_event_get_modifier_state(priv->parent.parent.evt,
+ modifier, &state);
+ dom_string_unref(modifier);
+ if (err != DOM_NO_ERR) {
+ return 0;
+ }
+
+ duk_push_boolean(ctx, (duk_bool_t) state);
+ return 1;
+%}
diff --git a/content/handlers/javascript/duktape/Makefile b/content/handlers/javascript/duktape/Makefile
index 2a5c2e742..638ca4458 100644
--- a/content/handlers/javascript/duktape/Makefile
+++ b/content/handlers/javascript/duktape/Makefile
@@ -4,10 +4,27 @@
# Included by javascript/Makefile
#
-content/handlers/javascript/duktape/dukky.c: $(OBJROOT)/duktape/binding.h
+content/handlers/javascript/duktape/dukky.c: \
+ $(OBJROOT)/duktape/binding.h \
+ $(OBJROOT)/duktape/generics.js.inc \
+ $(OBJROOT)/duktape/polyfill.js.inc
BINDINGS := $(wildcard content/handlers/javascript/duktape/*.bnd)
+# Generator for the C include representing the generics.js
+$(OBJROOT)/duktape/generics.js.inc: content/handlers/javascript/duktape/generics.js $(TOOLROOT)/xxd
+ $(Q)$(MKDIR) -p $(OBJROOT)/duktape
+ $(VQ)echo " XXD: $<"
+ $(Q)$(TOOLROOT)/xxd -i $< $@.tmp
+ $(Q)sed -e 's/content_handlers_javascript_duktape_generics_js/generics_js/' $@.tmp > $@
+
+# Generator for the C include representing the polyfill.js
+$(OBJROOT)/duktape/polyfill.js.inc: content/handlers/javascript/duktape/polyfill.js $(TOOLROOT)/xxd
+ $(Q)$(MKDIR) -p $(OBJROOT)/duktape
+ $(VQ)echo " XXD: $<"
+ $(Q)$(TOOLROOT)/xxd -i $< $@.tmp
+ $(Q)sed -e 's/content_handlers_javascript_duktape_polyfill_js/polyfill_js/' $@.tmp > $@
+
# ensure genbind generates debugging files
GBFLAGS+=-D
@@ -17,14 +34,18 @@ $(OBJROOT)/duktape/binding.h $(OBJROOT)/duktape/Makefile: content/handlers/javas
$(Q)nsgenbind $(GBFLAGS) -I content/handlers/javascript/WebIDL $< $(OBJROOT)/duktape
# create unimplemented report for doxygen
-Docs/UnimplementedJavascript.txt: content/handlers/javascript/duktape/netsurf.bnd $(BINDINGS)
+docs/UnimplementedJavascript.md: content/handlers/javascript/duktape/netsurf.bnd $(BINDINGS)
$(Q)$(MKDIR) -p $(OBJROOT)/duktape
- $(VQ)echo "/** \page unimplemented Unimplemented javascript bindings" > $@
+ $(VQ)echo "Unimplemented javascript bindings {#unimplemented}" > $@
+ $(VQ)echo "=================================" >> $@
+ $(VQ)echo "" >> $@
$(VQ)echo "This is a list of all the binding methods, getters and setters without an implementation in a binding." >> $@
$(VQ)echo "" >> $@
+ $(VQ)echo "Type | Unimplemented binding" >> $@
+ $(VQ)echo "---- | ---------------------" >> $@
$(VQ)echo " GENBIND: $<"
- $(Q)nsgenbind $(GBFLAGS) -Wunimplemented -I content/handlers/javascript/WebIDL $< $(OBJROOT)/duktape 2>&1 >/dev/null | grep "Unimplemented" | cut -d' ' -f4- | sort -k 2 | awk '{print $$0"\\n" }' >> $@
- $(VQ)echo "*/" >> $@
+ $(Q)nsgenbind $(GBFLAGS) -Wunimplemented -I content/handlers/javascript/WebIDL $< $(OBJROOT)/duktape 2>&1 >/dev/null | awk 'BEGIN{count=0} /.*Unimplemented.*/{count++; out=$$4" |"; for(i=5;i<=NF;i++){out=out" "$$i}; print out} END{print "\n",count,"unimplemented bindings"}' >> $@
+ $(VQ)echo "" >> $@
ifeq ($(filter $(MAKECMDGOALS),clean test coverage),)
-include $(OBJROOT)/duktape/Makefile
diff --git a/content/handlers/javascript/duktape/NamedNodeMap.bnd b/content/handlers/javascript/duktape/NamedNodeMap.bnd
new file mode 100644
index 000000000..c81993c92
--- /dev/null
+++ b/content/handlers/javascript/duktape/NamedNodeMap.bnd
@@ -0,0 +1,74 @@
+/* NamedNodeMap binding for browser using duktape and libdom
+ *
+ * Copyright 2020 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * Released under the terms of the MIT License,
+ * http://www.opensource.org/licenses/mit-license
+ */
+
+class NamedNodeMap {
+ private struct dom_namednodemap *map;
+};
+
+init NamedNodeMap(struct dom_namednodemap *map)
+%{
+ priv->map = map;
+ dom_namednodemap_ref(map);
+%}
+
+fini NamedNodeMap()
+%{
+ dom_namednodemap_unref(priv->map);
+%}
+
+getter NamedNodeMap::length()
+%{
+ dom_exception err;
+ uint32_t len;
+
+ err = dom_namednodemap_get_length(priv->map, &len);
+
+ if (err != DOM_NO_ERR) return 0; /* coerced to undefined */
+
+ duk_push_uint(ctx, (duk_uint_t)len);
+
+ return 1;
+%}
+
+method NamedNodeMap::item()
+%{
+ unsigned long i = duk_to_uint(ctx, 0);
+ dom_exception err;
+ dom_node *node;
+
+ err = dom_namednodemap_item(priv->map, i, &node);
+
+ if (err != DOM_NO_ERR) return 0; /* coerced to undefined */
+
+ dukky_push_node(ctx, node);
+ dom_node_unref(node);
+
+ return 1;
+%}
+
+method NamedNodeMap::getNamedItem()
+%{
+ duk_size_t size;
+ const char *s = duk_safe_to_lstring(ctx, 0, &size);
+ dom_exception exc;
+ dom_node *attr = NULL;
+ dom_string *name = NULL;
+
+ exc = dom_string_create((const uint8_t*)s, size, &name);
+ if (exc != DOM_NO_ERR) return 0; /* coerced to undefined */
+
+ exc = dom_namednodemap_get_named_item(priv->map, name, &attr);
+ dom_string_unref(name);
+ if (exc != DOM_NO_ERR) return 0; /* coerced to undefined */
+
+ dukky_push_node(ctx, attr);
+ dom_node_unref(attr);
+ return 1;
+%}
diff --git a/content/handlers/javascript/duktape/Node.bnd b/content/handlers/javascript/duktape/Node.bnd
index f14cfc177..8cd07944d 100644
--- a/content/handlers/javascript/duktape/Node.bnd
+++ b/content/handlers/javascript/duktape/Node.bnd
@@ -10,6 +10,9 @@
class Node {
private dom_node *node;
+ prologue %{
+
+%};
};
init Node(struct dom_node *node)
@@ -117,12 +120,17 @@ getter Node::childNodes()
duk_pop(ctx);
exc = dom_node_get_child_nodes(priv->node, &nlist);
if (exc != DOM_NO_ERR) return 0;
+ dukky_push_generics(ctx, "makeListProxy");
duk_push_pointer(ctx, nlist);
if (dukky_create_object(ctx, PROTO_NAME(NODELIST), 1) != DUK_EXEC_SUCCESS) {
dom_nodelist_unref(nlist);
return 0;
}
dom_nodelist_unref(nlist);
+ if (dukky_pcall(ctx, 1, false) != 0) {
+ NSLOG(dukky, DEBUG, "Unable to construct nodelist?");
+ return 0; /* coerced to undefined */
+ }
duk_dup(ctx, -1);
duk_put_prop_string(ctx, 0, MAGIC(childNodes));
}
@@ -213,7 +221,8 @@ setter Node::nodeValue()
if (exc != DOM_NO_ERR) return 0;
exc = dom_node_set_node_value(priv->node, content);
dom_string_unref(content);
- return 0;
+ if (exc != DOM_NO_ERR) return 0;
+ return 1;
%}
getter Node::textContent()
@@ -427,6 +436,7 @@ method Node::appendChild()
dom_exception err;
dom_node *spare;
+ NSLOG(dukky, DEEPDEBUG, "About to append %p to %p", other->node, priv->node);
err = dom_node_append_child(priv->node, other->node, &spare);
if (err != DOM_NO_ERR) return 0;
dukky_push_node(ctx, spare);
diff --git a/content/handlers/javascript/duktape/Window.bnd b/content/handlers/javascript/duktape/Window.bnd
index 3f680d47d..f7d143f6c 100644
--- a/content/handlers/javascript/duktape/Window.bnd
+++ b/content/handlers/javascript/duktape/Window.bnd
@@ -11,24 +11,295 @@
class Window {
private struct browser_window * win;
private struct html_content * htmlc;
+ private struct window_schedule_s * schedule_ring;
+ private bool closed_down;
prologue %{
+#include "utils/corestrings.h"
#include "utils/nsurl.h"
#include "netsurf/browser_window.h"
#include "content/hlcache.h"
-#include "render/html.h"
-#include "render/html_internal.h"
+#include "html/html.h"
+#include "html/private.h"
+#include "desktop/gui_internal.h"
+#include "netsurf/misc.h"
+#include "utils/ring.h"
+#include "netsurf/inttypes.h"
+
+#define WINDOW_CALLBACKS MAGIC(WindowCallbacks)
+#define HANDLER_MAGIC MAGIC(HANDLER_MAP)
+
+static size_t next_handle = 0;
+
+typedef struct window_schedule_s {
+ window_private_t *owner;
+ duk_context *ctx;
+ struct window_schedule_s *r_next;
+ struct window_schedule_s *r_prev;
+ size_t handle;
+ int repeat_timeout;
+ bool running;
+} window_schedule_t;
+
+static void window_remove_callback_bits(duk_context *ctx, size_t handle) {
+ /* stack is ... */
+ duk_push_global_object(ctx);
+ duk_get_prop_string(ctx, -1, WINDOW_CALLBACKS);
+ /* stack is ..., win, cbt */
+ duk_push_int(ctx, (duk_int_t)handle);
+ /* ..., win, cbt, handle */
+ duk_del_prop(ctx, -2);
+ /* ..., win, cbt */
+ duk_pop_2(ctx);
+ /* ... */
+}
+
+static void
+window_call_callback(duk_context *ctx, size_t handle, bool clear_entry)
+{
+ NSLOG(dukky, DEEPDEBUG, "ctx=%p, handle=%"PRIsizet, ctx, handle);
+ /* Stack is ... */
+ duk_push_global_object(ctx);
+ /* ..., win */
+ duk_get_prop_string(ctx, -1, WINDOW_CALLBACKS);
+ /* ..., win, cbt */
+ duk_push_int(ctx, (duk_int_t)handle);
+ /* ..., win, cbt, handle */
+ duk_get_prop(ctx, -2);
+ /* ..., win, cbt, cbo */
+ //dukky_log_stack_frame(ctx, "On entry to callback");
+ /* ..., win, cbt, cbo */
+ /* What we want to do is call cbo.func passing all of cbo.args */
+ duk_get_prop_string(ctx, -1, "func");
+ duk_get_prop_string(ctx, -2, "args");
+ /* ..., win, cbt, cbo, func, argarr */
+ duk_size_t arrlen = duk_get_length(ctx, -1);
+ for (duk_size_t i = 0; i < arrlen; ++i) {
+ duk_push_int(ctx, (duk_int_t)i);
+ duk_get_prop(ctx, -(2+i));
+ }
+ /* ..., win, cbt, cbo, func, argarr, args... */
+ duk_remove(ctx, -(arrlen+1));
+ /* ..., win, cbt, cbo, func, args... */
+ //dukky_log_stack_frame(ctx, "Just before call");
+ (void) dukky_pcall(ctx, arrlen, true);
+ /* ..., win, cbt, cbo, retval */
+ if (clear_entry) {
+ NSLOG(dukky, DEEPDEBUG, "Not recurring callback, removing from cbt");
+ duk_pop_n(ctx, 2);
+ /* ..., win, cbt */
+ duk_push_int(ctx, (duk_int_t)handle);
+ /* ..., win, cbt, handle */
+ duk_del_prop(ctx, -2);
+ /* ..., win, cbt */
+ duk_pop_n(ctx, 2);
+ } else {
+ duk_pop_n(ctx, 4);
+ }
+ /* ... */
+ //dukky_log_stack_frame(ctx, "On leaving callback");
+}
+
+
+static void
+window_schedule_callback(void *p)
+{
+ window_schedule_t *priv = (window_schedule_t *)p;
+
+ NSLOG(dukky, DEEPDEBUG,
+ "Entered window scheduler callback: %"PRIsizet, priv->handle);
+
+ priv->running = true;
+ window_call_callback(priv->ctx,
+ priv->handle,
+ priv->repeat_timeout == 0);
+ priv->running = false;
+
+ if (priv->repeat_timeout > 0) {
+ /* Reschedule */
+ NSLOG(dukky, DEEPDEBUG,
+ "Rescheduling repeating callback %"PRIsizet,
+ priv->handle);
+ guit->misc->schedule(priv->repeat_timeout,
+ window_schedule_callback,
+ priv);
+ } else {
+ NSLOG(dukky, DEEPDEBUG,
+ "Removing completed callback %"PRIsizet, priv->handle);
+ /* Remove this from the ring */
+ RING_REMOVE(priv->owner->schedule_ring, priv);
+ window_remove_callback_bits(priv->ctx, priv->handle);
+ free(priv);
+ }
+}
+
+static size_t
+window_alloc_new_callback(duk_context *ctx,
+ window_private_t *window,
+ bool repeating,
+ int timeout)
+{
+ size_t new_handle = next_handle++;
+ window_schedule_t *sched = calloc(sizeof *sched, 1);
+ if (sched == NULL) {
+ return new_handle;
+ }
+ sched->owner = window;
+ sched->ctx = ctx;
+ sched->handle = new_handle;
+ sched->repeat_timeout = repeating ? timeout : 0;
+ sched->running = false;
+
+ RING_INSERT(window->schedule_ring, sched);
+
+ /* Next, the duktape stack looks like: func, timeout, ...
+ * In order to proceed, we want to put into the WINDOW_CALLBACKS
+ * keyed by the handle, an object containing the call to make and
+ * the array of arguments to call the function with
+ */
+ duk_idx_t nargs = duk_get_top(ctx) - 2;
+ duk_push_global_object(ctx);
+ duk_get_prop_string(ctx, -1, WINDOW_CALLBACKS);
+ duk_push_int(ctx, (duk_int_t)new_handle);
+ duk_push_object(ctx);
+ /* stack is: func, timeout, ..., win, cbt, handle, cbo */
+
+ /* put the function into the cbo */
+ duk_dup(ctx, 0);
+ duk_put_prop_string(ctx, -2, "func");
+
+ /* Now the arguments */
+ duk_push_array(ctx);
+ for (duk_idx_t i = 0; i < nargs; ++i) {
+ duk_dup(ctx, 2 + i); /* Dup the arg */
+ duk_put_prop_index(ctx, -2, i); /* arr[i] = arg[i] */
+ }
+ duk_put_prop_string(ctx, -2, "args");
+ /* stack is: func, timeout, ..., win, cbt, handle, cbo */
+ duk_put_prop(ctx, -3);
+ /* stack is: func, timeout, ..., win, cbt */
+ duk_pop_2(ctx);
+ /* And we're back to func, timeout, ... */
+
+ guit->misc->schedule(timeout, window_schedule_callback, sched);
+ NSLOG(dukky, DEEPDEBUG, "Scheduled callback %"PRIsizet" for %d ms from now", new_handle, timeout);
+
+ return new_handle;
+}
+
+static void
+window_remove_callback_by_handle(duk_context *ctx,
+ window_private_t *window,
+ size_t handle)
+{
+ int res;
+
+ RING_ITERATE_START(window_schedule_t, window->schedule_ring, sched) {
+ if (sched->handle == handle) {
+ if (sched->running) {
+ NSLOG(dukky, DEEPDEBUG,
+ "Cancelling in-train callback %"PRIsizet,
+ sched->handle);
+ sched->repeat_timeout = 0;
+ } else {
+ NSLOG(dukky, DEEPDEBUG,
+ "Cancelled callback %"PRIsizet,
+ sched->handle);
+ res = guit->misc->schedule(-1,
+ window_schedule_callback,
+ sched);
+ assert(res == NSERROR_OK);
+ RING_REMOVE(window->schedule_ring, sched);
+ window_remove_callback_bits(ctx, sched->handle);
+ free(sched);
+ }
+ RING_ITERATE_STOP(window->schedule_ring, sched);
+ }
+ } RING_ITERATE_END(window->schedule_ring, sched);
+}
+
+/* This is the dodgy thread closedown method */
+static duk_ret_t dukky_window_closedown_thread(duk_context *ctx)
+{
+ window_private_t *priv = NULL;
+
+ duk_push_global_object(ctx);
+ duk_get_prop_string(ctx, -1, dukky_magic_string_private);
+ priv = duk_get_pointer(ctx, -1);
+ duk_pop_2(ctx);
+
+ if (priv == NULL) {
+ return 0;
+ }
+
+ priv->closed_down = true;
+
+ NSLOG(dukky, DEEPDEBUG, "Closing down thread");
+ while (priv->schedule_ring != NULL) {
+ window_schedule_t *to_remove = NULL;
+ // Find a schedule item to remove
+ RING_ITERATE_START(window_schedule_t, priv->schedule_ring, sched) {
+ if (sched->running == false) {
+ // This one is not running, we can remove it
+ to_remove = sched;
+ RING_ITERATE_STOP(window->schedule_ring, sched);
+ } else if (sched->repeat_timeout != 0) {
+ // This one is running and has yet to be
+ // cancelled, so prevent it rescheduling itself
+ NSLOG(dukky, DEEPDEBUG,
+ "Cancelling in-train callback %"PRIsizet,
+ sched->handle);
+ sched->repeat_timeout = 0;
+ }
+ } RING_ITERATE_END(priv->schedule_ring, sched);
+
+ if (to_remove == NULL) {
+ // We didn't find any non-running callbacks
+ // so let's log that and break out of the closedown
+ // loop so we can continue and hopefully close down
+ NSLOG(dukky, DEEPDEBUG,
+ "Leaving in-train callbacks to unwind");
+ break;
+ }
+
+ // Remove the handle we found, this will reduce the callback
+ // scheduler ring by one and perhaps leave it empty so we can
+ // finish the closedown.
+ window_remove_callback_by_handle(ctx,
+ priv,
+ to_remove->handle);
+ }
+
+ return 0;
+}
+
%};
};
init Window(struct browser_window *win, struct html_content *htmlc)
%{
+ /* It makes no sense if win or htmlc are NULL */
+ assert(win != NULL);
+ assert(htmlc != NULL);
/* element window */
priv->win = win;
priv->htmlc = htmlc;
- NSLOG(netsurf, INFO, "win=%p htmlc=%p", priv->win, priv->htmlc);
+ priv->schedule_ring = NULL;
+ priv->closed_down = false;
+ NSLOG(netsurf, DEEPDEBUG, "win=%p htmlc=%p", priv->win, priv->htmlc);
+
+ NSLOG(netsurf, DEEPDEBUG,
+ "URL is %s", nsurl_access(browser_window_access_url(priv->win)));
+ duk_push_object(ctx);
+ duk_put_prop_string(ctx, 0, WINDOW_CALLBACKS);
+%}
- NSLOG(netsurf, INFO,
- "URL is %s", nsurl_access(browser_window_get_url(priv->win)));
+fini Window()
+%{
+ NSLOG(dukky, DEEPDEBUG, "Shutting down Window %p", priv->win);
+ /* Cheaply iterate the schedule ring, cancelling any pending callbacks */
+ while (priv->schedule_ring != NULL) {
+ window_remove_callback_by_handle(ctx, priv, priv->schedule_ring->handle);
+ }
%}
prototype Window()
@@ -36,25 +307,112 @@ prototype Window()
#define EXPOSE(v) \
duk_get_global_string(ctx, #v); \
duk_put_prop_string(ctx, 0, #v)
- /* steal undefined */
+ /* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects */
+ /* ** Value properties */
+ EXPOSE(Infinity);
+ EXPOSE(NaN);
EXPOSE(undefined);
+ EXPOSE(null);
+ EXPOSE(globalThis);
+
+ /* ** Function properties */
EXPOSE(eval);
- EXPOSE(Object);
- EXPOSE(parseInt);
+ /* EXPOSE(uneval); */ /* Not standard, maybe not available */
+ EXPOSE(isFinite);
+ EXPOSE(isNaN);
EXPOSE(parseFloat);
- EXPOSE(Array);
+ EXPOSE(parseInt);
+ EXPOSE(decodeURI);
+ EXPOSE(decodeURIComponent);
+ EXPOSE(encodeURI);
+ EXPOSE(encodeURIComponent);
+ EXPOSE(escape);
+ EXPOSE(unescape);
+
+ /* ** Fundamental Objects */
+ EXPOSE(Object);
+ EXPOSE(Function);
+ EXPOSE(Boolean);
+ EXPOSE(Symbol);
+ EXPOSE(Error);
+ EXPOSE(EvalError);
+ EXPOSE(InternalError);
+ EXPOSE(RangeError);
+ EXPOSE(ReferenceError);
+ EXPOSE(SyntaxError);
+ EXPOSE(TypeError);
+ EXPOSE(URIError);
+
+ /* ** Numbers and Dates */
+ EXPOSE(Number);
+ EXPOSE(BigInt);
+ EXPOSE(Math);
EXPOSE(Date);
+
+ /* ** Text Processing */
+ EXPOSE(String);
EXPOSE(RegExp);
- EXPOSE(Math);
- EXPOSE(Function);
+
+ /* ** Indexed Collections */
+ EXPOSE(Array);
+ EXPOSE(Int8Array);
+ EXPOSE(Uint8Array);
+ EXPOSE(Uint8ClampedArray);
+ EXPOSE(Int16Array);
+ EXPOSE(Uint16Array);
+ EXPOSE(Int32Array);
+ EXPOSE(Uint32Array);
+ EXPOSE(Float32Array);
+ EXPOSE(Float64Array);
+ /* EXPOSE(BigInt64Array); */ /* Duktape lacks this - nonstandard API */
+ /* EXPOSE(BigUint64Array); */ /* Duktape lacks this - nonstandard API */
+
+ /* ** Keyed Collections */
+ /* EXPOSE(Map); */ /* Duktape lacks this - ES6 */
+ /* EXPOSE(Set); */ /* Duktape lacks this - ES6 */
+ /* EXPOSE(WeakMap); */ /* Duktape lacks this - ES6 */
+ /* EXPOSE(WeakSet); */ /* Duktape lacks this - ES6 */
+
+ /* Structured Data */
+ EXPOSE(ArrayBuffer);
+ /* EXPOSE(SharedArrayBuffer); */ /* Duktape lacks this - experimental API */
+ /* EXPOSE(Atomics); */ /* Duktape lacks this - experimental API */
+ EXPOSE(DataView);
+ EXPOSE(JSON);
+
+ /* ** Control abstraction properties */
+ /* EXPOSE(Promise); */ /* Probably ought to be one of ours? Also ES6 */
+ /* EXPOSE(Generator); */ /* Duktape and async? ES6 */
+ /* EXPOSE(GeneratorFunction); */ /* Duktape and async? ES6 */
+ /* EXPOSE(AsyncFunction); */ /* Duktape lacks this - experimental API */
+
+ /* Reflection */
+ EXPOSE(Reflect);
EXPOSE(Proxy);
- EXPOSE(String);
+
+ /* ** Internationalisation */
+ /* Duktape lacks Intl - Maybe polyfill it? */
+ /* There is suggestion that cdn.polyfill.io exists for it */
+
+ /* ** WebAssembly */
+ /* As yet, Duktape lacks WA */
#undef EXPOSE
+ /* Add s3kr1t method to close the JS thread (browsing context) */
+ duk_dup(ctx, 0);
+ duk_push_string(ctx, MAGIC(closedownThread));
+ duk_push_c_function(ctx, dukky_window_closedown_thread, DUK_VARARGS);
+ duk_def_prop(ctx, -3,
+ DUK_DEFPROP_HAVE_VALUE |
+ DUK_DEFPROP_HAVE_WRITABLE |
+ DUK_DEFPROP_HAVE_ENUMERABLE |
+ DUK_DEFPROP_ENUMERABLE |
+ DUK_DEFPROP_HAVE_CONFIGURABLE);
+ duk_pop(ctx);
%}
getter Window::document()
%{
- JS_LOG("priv=%p", priv);
+ NSLOG(netsurf, DEBUG, "priv=%p", priv);
dom_document *doc = priv->htmlc->document;
dukky_push_node(ctx, (struct dom_node *)doc);
return 1;
@@ -83,9 +441,11 @@ getter Window::console()
getter Window::location()
%{
+ /* obtain location object for this window (if it exists) */
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, MAGIC(Location));
if (duk_is_undefined(ctx, -1)) {
+ /* location object did not previously exist so create it */
duk_pop(ctx);
duk_push_pointer(ctx, llcache_handle_get_url(priv->htmlc->base.llcache));
@@ -137,8 +497,227 @@ setter Window::name()
method Window::alert()
%{
- duk_size_t msg_len;
- const char *msg = duk_safe_to_lstring(ctx, 0, &msg_len);
- NSLOG(netsurf, INFO, "JS ALERT: %*s", (int)msg_len, msg);
+ duk_idx_t dukky_argc = duk_get_top(ctx);
+ if (dukky_argc == 0) {
+ NSLOG(netsurf, INFO, "JS ALERT");
+ } else {
+ duk_size_t msg_len;
+ const char *msg;
+
+ if (!duk_is_string(ctx, 0)) {
+ duk_to_string(ctx, 0);
+ }
+ msg = duk_safe_to_lstring(ctx, 0, &msg_len);
+ NSLOG(netsurf, INFO, "JS ALERT: %*s", (int)msg_len, msg);
+ }
+ return 0;
+%}
+
+method Window::setTimeout()
+%{
+ duk_idx_t argc = duk_get_top(ctx);
+ duk_int_t timeout = 10;
+
+ if (priv->closed_down == true) {
+ return 0; /* coerced to undefined */
+ }
+
+ if (argc >= 2) {
+ timeout = duk_get_int(ctx, 1);
+ }
+ /* func, [timeout, args...] */
+ if (timeout < 10) { timeout = 10; }
+ size_t handle = window_alloc_new_callback(ctx, priv, false, (int)timeout);
+
+ duk_push_int(ctx, (duk_int_t)handle);
+ return 1;
+%}
+
+method Window::setInterval()
+%{
+ duk_idx_t argc = duk_get_top(ctx);
+ duk_int_t timeout = 10;
+
+ if (priv->closed_down == true) {
+ return 0; /* coerced to undefined */
+ }
+
+ if (argc >= 2) {
+ timeout = duk_get_int(ctx, 1);
+ }
+ /* func, [timeout, args...] */
+ if (timeout < 10) { timeout = 10; }
+ size_t handle = window_alloc_new_callback(ctx, priv, true, (int)timeout);
+
+ duk_push_int(ctx, (duk_int_t)handle);
+ return 1;
+%}
+
+method Window::clearTimeout()
+%{
+ duk_int_t handle = duk_get_int(ctx, 0);
+ window_remove_callback_by_handle(ctx, priv, (size_t) handle);
+
+ return 0;
+%}
+
+method Window::clearInterval()
+%{
+ duk_int_t handle = duk_get_int(ctx, 0);
+ window_remove_callback_by_handle(ctx, priv, (size_t) handle);
+
return 0;
%}
+
+getter Window::onabort();
+setter Window::onabort();
+getter Window::onafterprint();
+setter Window::onafterprint();
+getter Window::onautocompleteerror();
+setter Window::onautocompleteerror();
+getter Window::onautocomplete();
+setter Window::onautocomplete();
+getter Window::onbeforeprint();
+setter Window::onbeforeprint();
+getter Window::onbeforeunload();
+setter Window::onbeforeunload();
+getter Window::onblur();
+setter Window::onblur();
+getter Window::oncancel();
+setter Window::oncancel();
+getter Window::oncanplaythrough();
+setter Window::oncanplaythrough();
+getter Window::oncanplay();
+setter Window::oncanplay();
+getter Window::onchange();
+setter Window::onchange();
+getter Window::onclick();
+setter Window::onclick();
+getter Window::onclose();
+setter Window::onclose();
+getter Window::oncontextmenu();
+setter Window::oncontextmenu();
+getter Window::oncuechange();
+setter Window::oncuechange();
+getter Window::ondblclick();
+setter Window::ondblclick();
+getter Window::ondragend();
+setter Window::ondragend();
+getter Window::ondragenter();
+setter Window::ondragenter();
+getter Window::ondragexit();
+setter Window::ondragexit();
+getter Window::ondragleave();
+setter Window::ondragleave();
+getter Window::ondragover();
+setter Window::ondragover();
+getter Window::ondragstart();
+setter Window::ondragstart();
+getter Window::ondrag();
+setter Window::ondrag();
+getter Window::ondrop();
+setter Window::ondrop();
+getter Window::ondurationchange();
+setter Window::ondurationchange();
+getter Window::onemptied();
+setter Window::onemptied();
+getter Window::onended();
+setter Window::onended();
+getter Window::onerror();
+setter Window::onerror();
+getter Window::onfocus();
+setter Window::onfocus();
+getter Window::onhashchange();
+setter Window::onhashchange();
+getter Window::oninput();
+setter Window::oninput();
+getter Window::oninvalid();
+setter Window::oninvalid();
+getter Window::onkeydown();
+setter Window::onkeydown();
+getter Window::onkeypress();
+setter Window::onkeypress();
+getter Window::onkeyup();
+setter Window::onkeyup();
+getter Window::onlanguagechange();
+setter Window::onlanguagechange();
+getter Window::onloadeddata();
+setter Window::onloadeddata();
+getter Window::onloadedmetadata();
+setter Window::onloadedmetadata();
+getter Window::onloadstart();
+setter Window::onloadstart();
+getter Window::onload();
+setter Window::onload();
+getter Window::onmessage();
+setter Window::onmessage();
+getter Window::onmousedown();
+setter Window::onmousedown();
+getter Window::onmouseenter();
+setter Window::onmouseenter();
+getter Window::onmouseleave();
+setter Window::onmouseleave();
+getter Window::onmousemove();
+setter Window::onmousemove();
+getter Window::onmouseout();
+setter Window::onmouseout();
+getter Window::onmouseover();
+setter Window::onmouseover();
+getter Window::onmouseup();
+setter Window::onmouseup();
+getter Window::onoffline();
+setter Window::onoffline();
+getter Window::ononline();
+setter Window::ononline();
+getter Window::onpagehide();
+setter Window::onpagehide();
+getter Window::onpageshow();
+setter Window::onpageshow();
+getter Window::onpause();
+setter Window::onpause();
+getter Window::onplaying();
+setter Window::onplaying();
+getter Window::onplay();
+setter Window::onplay();
+getter Window::onpopstate();
+setter Window::onpopstate();
+getter Window::onprogress();
+setter Window::onprogress();
+getter Window::onratechange();
+setter Window::onratechange();
+getter Window::onreset();
+setter Window::onreset();
+getter Window::onresize();
+setter Window::onresize();
+getter Window::onscroll();
+setter Window::onscroll();
+getter Window::onseeked();
+setter Window::onseeked();
+getter Window::onseeking();
+setter Window::onseeking();
+getter Window::onselect();
+setter Window::onselect();
+getter Window::onshow();
+setter Window::onshow();
+getter Window::onsort();
+setter Window::onsort();
+getter Window::onstalled();
+setter Window::onstalled();
+getter Window::onstorage();
+setter Window::onstorage();
+getter Window::onsubmit();
+setter Window::onsubmit();
+getter Window::onsuspend();
+setter Window::onsuspend();
+getter Window::ontimeupdate();
+setter Window::ontimeupdate();
+getter Window::ontoggle();
+setter Window::ontoggle();
+getter Window::onunload();
+setter Window::onunload();
+getter Window::onvolumechange();
+setter Window::onvolumechange();
+getter Window::onwaiting();
+setter Window::onwaiting();
+getter Window::onwheel();
+setter Window::onwheel();
diff --git a/content/handlers/javascript/duktape/duk_config.h b/content/handlers/javascript/duktape/duk_config.h
index 379e9f647..cba3e0f00 100644
--- a/content/handlers/javascript/duktape/duk_config.h
+++ b/content/handlers/javascript/duktape/duk_config.h
@@ -18,6 +18,7 @@
* - QNX
* - TI-Nspire
* - Emscripten
+ * - Android
* - Linux
* - Solaris
* - AIX
@@ -39,6 +40,8 @@
* - PowerPC 64-bit
* - SPARC 32-bit
* - SPARC 64-bit
+ * - RISC-V 32-bit
+ * - RISC-V 64-bit
* - SuperH
* - Motorola 68k
* - Emscripten
@@ -170,6 +173,10 @@
#define DUK_F_BCC
#endif
+#if defined(ANDROID) || defined(__ANDROID__)
+#define DUK_F_ANDROID
+#endif
+
/* Linux */
#if defined(__linux) || defined(__linux__) || defined(linux)
#define DUK_F_LINUX
@@ -218,12 +225,6 @@
#define DUK_F_UNIX
#endif
-/* C++ */
-#undef DUK_F_CPP
-#if defined(__cplusplus)
-#define DUK_F_CPP
-#endif
-
/* Intel x86 (32-bit), x64 (64-bit) or x32 (64-bit but 32-bit pointers),
* define only one of DUK_F_X86, DUK_F_X64, DUK_F_X32.
* https://sites.google.com/site/x32abi/
@@ -252,9 +253,9 @@
#endif
/* ARM */
-#if defined(__arm__) || defined(__thumb__) || defined(_ARM) || defined(_M_ARM) || defined(__aarch64__)
+#if defined(__arm__) || defined(__thumb__) || defined(_ARM) || defined(_M_ARM) || defined(_M_ARM64) || defined(__aarch64__)
#define DUK_F_ARM
-#if defined(__LP64__) || defined(_LP64) || defined(__arm64) || defined(__arm64__) || defined(__aarch64__)
+#if defined(__LP64__) || defined(_LP64) || defined(__arm64) || defined(__arm64__) || defined(_M_ARM64) || defined(__aarch64__)
#define DUK_F_ARM64
#else
#define DUK_F_ARM32
@@ -286,6 +287,22 @@
#endif
#endif
+/* RISC-V, https://github.com/riscv/riscv-toolchain-conventions#cc-preprocessor-definitions */
+#if defined(__riscv)
+#define DUK_F_RISCV
+#if defined(__riscv_xlen)
+#if (__riscv_xlen == 32)
+#define DUK_F_RISCV32
+#elif (__riscv_xlen == 64)
+#define DUK_F_RISCV64
+#else
+#error __riscv_xlen has unsupported value (not 32 or 64)
+#endif
+#else
+#error __riscv defined without __riscv_xlen
+#endif
+#endif /* __riscv */
+
/* SuperH */
#if defined(__sh__) || \
defined(__sh1__) || defined(__SH1__) || \
@@ -301,6 +318,12 @@
#define DUK_F_CLANG
#endif
+/* C++ */
+#undef DUK_F_CPP
+#if defined(__cplusplus)
+#define DUK_F_CPP
+#endif
+
/* C99 or above */
#undef DUK_F_C99
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
@@ -356,10 +379,6 @@
#define DUK_F_VBCC
#endif
-#if defined(ANDROID) || defined(__ANDROID__)
-#define DUK_F_ANDROID
-#endif
-
/* Atari Mint */
#if defined(__MINT__)
#define DUK_F_MINT
@@ -665,6 +684,41 @@
#define DUK_USE_DATE_FMT_STRFTIME
#define DUK_USE_OS_STRING "emscripten"
+#elif defined(DUK_F_ANDROID)
+/* --- Android --- */
+#if defined(DUK_COMPILING_DUKTAPE)
+#if !defined(_POSIX_C_SOURCE)
+#define _POSIX_C_SOURCE 200809L
+#endif
+#if !defined(_GNU_SOURCE)
+#define _GNU_SOURCE /* e.g. getdate_r */
+#endif
+#if !defined(_XOPEN_SOURCE)
+#define _XOPEN_SOURCE /* e.g. strptime */
+#endif
+#endif /* DUK_COMPILING_DUKTAPE */
+
+#include <sys/types.h>
+#if defined(DUK_F_BCC)
+/* no endian.h or stdint.h */
+#else
+#include <endian.h>
+#include <stdint.h>
+#endif /* DUK_F_BCC */
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+
+#if 0 /* XXX: safe condition? */
+#define DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME
+#endif
+
+#define DUK_USE_OS_STRING "android"
#elif defined(DUK_F_LINUX)
/* --- Linux --- */
#if defined(DUK_COMPILING_DUKTAPE)
@@ -715,7 +769,7 @@
#define DUK_USE_BYTEORDER 3
#endif
#else /* DUK_F_OLD_SOLARIS */
-#include <ast/endian.h>
+#include <sys/param.h>
#endif /* DUK_F_OLD_SOLARIS */
#include <sys/param.h>
@@ -836,9 +890,7 @@
#include <stdint.h>
#endif
-#if defined(DUK_F_CPP)
-#include <exception> /* std::exception */
-#endif
+/* <exception> is only included if needed, based on DUK_USE_xxx flags. */
/*
* Architecture autodetection
@@ -850,7 +902,16 @@
#if !defined(DUK_USE_BYTEORDER)
#define DUK_USE_BYTEORDER 1
#endif
+
#define DUK_USE_PACKED_TVAL
+
+/* FreeBSD, -m32, and clang prior to 5.0 has union aliasing issues which
+ * break duk_tval copying. Disable packed duk_tval automatically.
+ */
+#if defined(DUK_F_FREEBSD) && defined(DUK_F_X86) && \
+ defined(__clang__) && defined(__clang_major__) && (__clang_major__ < 5)
+#undef DUK_USE_PACKED_TVAL
+#endif
#define DUK_F_PACKED_TVAL_PROVIDED
#elif defined(DUK_F_X64)
/* --- x64 --- */
@@ -903,9 +964,7 @@
#elif defined(DUK_F_PPC64)
/* --- PowerPC 64-bit --- */
#define DUK_USE_ARCH_STRING "ppc64"
-#if !defined(DUK_USE_BYTEORDER)
-#define DUK_USE_BYTEORDER 3
-#endif
+/* No forced byteorder (both little and big endian are possible). */
#undef DUK_USE_PACKED_TVAL
#define DUK_F_PACKED_TVAL_PROVIDED
#elif defined(DUK_F_SPARC32)
@@ -920,13 +979,22 @@
/* SPARC byte order varies so rely on autodetection. */
#undef DUK_USE_PACKED_TVAL
#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_RISCV32)
+/* --- RISC-V 32-bit --- */
+#define DUK_USE_ARCH_STRING "riscv32"
+#define DUK_USE_BYTEORDER 1
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_RISCV64)
+/* --- RISC-V 64-bit --- */
+#define DUK_USE_ARCH_STRING "riscv64"
+#define DUK_USE_BYTEORDER 1
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
#elif defined(DUK_F_SUPERH)
/* --- SuperH --- */
#define DUK_USE_ARCH_STRING "sh"
/* Byte order varies, rely on autodetection. */
-/* Based on 'make checkalign' there are no alignment requirements on
- * Linux SH4, but align by 4 is probably a good basic default.
- */
#define DUK_USE_PACKED_TVAL
#define DUK_F_PACKED_TVAL_PROVIDED
#elif defined(DUK_F_M68K)
@@ -1063,8 +1131,20 @@
#define DUK_USE_FLEX_ZEROSIZE
#endif
-#undef DUK_USE_GCC_PRAGMAS
+#define DUK_USE_CLANG_PRAGMAS
#define DUK_USE_PACK_CLANG_ATTR
+
+#if defined(__clang__) && defined(__has_builtin)
+#if __has_builtin(__builtin_bswap64)
+#define DUK_BSWAP64(x) ((duk_uint64_t) __builtin_bswap64((duk_uint64_t) (x)))
+#endif
+#if __has_builtin(__builtin_bswap32)
+#define DUK_BSWAP32(x) ((duk_uint32_t) __builtin_bswap32((duk_uint32_t) (x)))
+#endif
+#if __has_builtin(__builtin_bswap16)
+#define DUK_BSWAP16(x) ((duk_uint16_t) __builtin_bswap16((duk_uint16_t) (x)))
+#endif
+#endif
#elif defined(DUK_F_GCC)
/* --- GCC --- */
#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
@@ -1075,13 +1155,17 @@
#define DUK_VA_COPY(dest,src) __va_copy(dest,src)
#endif
-#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 20500L)
-/* since gcc-2.5 */
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 20500L) && (DUK_F_GCC_VERSION < 50000L)
+/* Since gcc-2.5.
+ *
+ * Disabled temporarily in GCC 5+ because of an unresolved noreturn-related
+ * issue: https://github.com/svaarala/duktape/issues/2155.
+ */
#define DUK_NORETURN(decl) decl __attribute__((noreturn))
#endif
#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500L)
-/* since gcc-4.5 */
+/* Since gcc-4.5. */
#define DUK_UNREACHABLE() do { __builtin_unreachable(); } while (0)
#endif
@@ -1187,6 +1271,7 @@
#define DUK_USE_FLEX_ZEROSIZE
#endif
+/* Since 4.6 one can '#pragma GCC diagnostic push/pop'. */
#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40600)
#define DUK_USE_GCC_PRAGMAS
#else
@@ -1194,6 +1279,16 @@
#endif
#define DUK_USE_PACK_GCC_ATTR
+
+/* Availability varies based on platform (between GCC 4.4 and 4.8), and there
+ * are apparently some bugs in GCC 4.x. Check for GCC 5.0 before enabling
+ * these to be safe.
+ */
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 50000L)
+#define DUK_BSWAP64(x) ((duk_uint64_t) __builtin_bswap64((duk_uint64_t) (x)))
+#define DUK_BSWAP32(x) ((duk_uint32_t) __builtin_bswap32((duk_uint32_t) (x)))
+#define DUK_BSWAP16(x) ((duk_uint16_t) __builtin_bswap16((duk_uint16_t) (x)))
+#endif
#elif defined(DUK_F_MSVC)
/* --- MSVC --- */
/* http://msdn.microsoft.com/en-us/library/aa235362(VS.60).aspx */
@@ -1954,8 +2049,8 @@ typedef duk_uint_fast16_t duk_small_uint_fast_t;
/* Boolean values are represented with the platform 'unsigned int'. */
typedef duk_small_uint_t duk_bool_t;
-#define DUK_BOOL_MIN DUK_SMALL_INT_MIN
-#define DUK_BOOL_MAX DUK_SMALL_INT_MAX
+#define DUK_BOOL_MIN DUK_SMALL_UINT_MIN
+#define DUK_BOOL_MAX DUK_SMALL_UINT_MAX
/* Index values must have at least 32-bit signed range. */
typedef duk_int_t duk_idx_t;
@@ -2489,15 +2584,18 @@ typedef struct duk_hthread duk_context;
*
* Assume unaligned accesses are not supported unless specifically allowed
* in the target platform. Some platforms may support unaligned accesses
- * but alignment to 4 or 8 may still be desirable.
+ * but alignment to 4 or 8 may still be desirable. Note that unaligned
+ * accesses (and even pointers) relative to natural alignment (regardless
+ * of target alignment) are technically undefined behavior and thus
+ * compiler/architecture specific.
*/
-/* If not provided, use safe default for alignment. */
+/* If not forced, use safe default for alignment. */
#if !defined(DUK_USE_ALIGN_BY)
#define DUK_USE_ALIGN_BY 8
#endif
-/* Compiler specific hackery needed to force struct size to match aligment,
+/* Compiler specific hackery needed to force struct size to match alignment,
* see e.g. duk_hbuffer.h.
*
* http://stackoverflow.com/questions/11130109/c-struct-size-alignment
@@ -2508,6 +2606,13 @@ typedef struct duk_hthread duk_context;
#define DUK_USE_PACK_DUMMY_MEMBER
#endif
+#if !defined(DUK_U64_CONSTANT)
+#define DUK_U64_CONSTANT(x) x##ULL
+#endif
+#if !defined(DUK_I64_CONSTANT)
+#define DUK_I64_CONSTANT(x) x##LL
+#endif
+
#if !defined(DUK_VA_COPY)
/* We need va_copy() which is defined in C99 / C++11, so an awkward
* replacement is needed for pre-C99 / pre-C++11 environments. This
@@ -2544,6 +2649,7 @@ typedef struct duk_hthread duk_context;
*/
#define DUK_CAUSE_SEGFAULT() do { *((volatile duk_uint32_t *) NULL) = (duk_uint32_t) 0xdeadbeefUL; } while (0)
#endif
+
#if !defined(DUK_UNREF)
/* Macro for suppressing warnings for potentially unreferenced variables.
* The variables can be actually unreferenced or unreferenced in some
@@ -2553,16 +2659,35 @@ typedef struct duk_hthread duk_context;
*/
#define DUK_UNREF(x) do { (void) (x); } while (0)
#endif
-#if !defined(DUK_NORETURN)
+
+/* Fillin for DUK_NORETURN; DUK_WO_NORETURN() is used to insert dummy
+ * dummy statements after noreturn calls to silence harmless compiler
+ * warnings, e.g.:
+ *
+ * DUK_ERROR_TYPE(thr, "aiee");
+ * DUK_WO_NORETURN(return 0;);
+ *
+ * Statements inside DUK_WO_NORETURN() must NEVER be actually reachable,
+ * and they're only included to satisfy the compiler.
+ */
+#if defined(DUK_NORETURN)
+#define DUK_WO_NORETURN(stmt) do { } while (0)
+#else
#define DUK_NORETURN(decl) decl
+#define DUK_WO_NORETURN(stmt) do { stmt } while (0)
#endif
-#if !defined(DUK_UNREACHABLE)
+
+#if defined(DUK_UNREACHABLE)
+#define DUK_WO_UNREACHABLE(stmt) do { } while (0)
+#else
/* Don't know how to declare unreachable point, so don't do it; this
* may cause some spurious compilation warnings (e.g. "variable used
* uninitialized").
*/
#define DUK_UNREACHABLE() do { } while (0)
+#define DUK_WO_UNREACHABLE(stmt) do { stmt } while (0)
#endif
+
#if !defined(DUK_LOSE_CONST)
/* Convert any input pointer into a "void *", losing a const qualifier.
* This is not fully portable because casting through duk_uintptr_t may
@@ -2641,17 +2766,30 @@ typedef struct duk_hthread duk_context;
#endif
#endif
+#if defined(DUK_F_HAVE_64BIT)
+#if !defined(DUK_BSWAP64)
+#define DUK_BSWAP64(x) \
+ ((((duk_uint64_t) (x)) >> 56U) | \
+ ((((duk_uint64_t) (x)) >> 40U) & DUK_U64_CONSTANT(0xff00)) | \
+ ((((duk_uint64_t) (x)) >> 24U) & DUK_U64_CONSTANT(0xff0000)) | \
+ ((((duk_uint64_t) (x)) >> 8U) & DUK_U64_CONSTANT(0xff000000)) | \
+ ((((duk_uint64_t) (x)) << 8U) & DUK_U64_CONSTANT(0xff00000000)) | \
+ ((((duk_uint64_t) (x)) << 24U) & DUK_U64_CONSTANT(0xff0000000000)) | \
+ ((((duk_uint64_t) (x)) << 40U) & DUK_U64_CONSTANT(0xff000000000000)) | \
+ (((duk_uint64_t) (x)) << 56U))
+#endif
+#endif
#if !defined(DUK_BSWAP32)
#define DUK_BSWAP32(x) \
- ((((duk_uint32_t) (x)) >> 24) | \
- ((((duk_uint32_t) (x)) >> 8) & 0xff00UL) | \
- ((((duk_uint32_t) (x)) << 8) & 0xff0000UL) | \
- (((duk_uint32_t) (x)) << 24))
+ ((((duk_uint32_t) (x)) >> 24U) | \
+ ((((duk_uint32_t) (x)) >> 8U) & 0xff00UL) | \
+ ((((duk_uint32_t) (x)) << 8U) & 0xff0000UL) | \
+ (((duk_uint32_t) (x)) << 24U))
#endif
#if !defined(DUK_BSWAP16)
#define DUK_BSWAP16(x) \
- ((duk_uint16_t) (x) >> 8) | \
- ((duk_uint16_t) (x) << 8)
+ ((duk_uint16_t) (x) >> 8U) | \
+ ((duk_uint16_t) (x) << 8U)
#endif
/* DUK_USE_VARIADIC_MACROS: required from compilers, so no fill-in. */
@@ -2674,13 +2812,6 @@ typedef struct duk_hthread duk_context;
#undef DUK_USE_GCC_PRAGMAS
#endif
-#if !defined(DUK_U64_CONSTANT)
-#define DUK_U64_CONSTANT(x) x##ULL
-#endif
-#if !defined(DUK_I64_CONSTANT)
-#define DUK_I64_CONSTANT(x) x##LL
-#endif
-
/* Workaround for GH-323: avoid inlining control when compiling from
* multiple sources, as it causes compiler portability trouble.
*/
@@ -2730,8 +2861,8 @@ typedef struct duk_hthread duk_context;
#if defined(DUK_F_PACKED_TVAL_POSSIBLE)
#define DUK_USE_PACKED_TVAL
#endif
-
#undef DUK_F_PACKED_TVAL_POSSIBLE
+
#endif /* DUK_F_PACKED_TVAL_PROVIDED */
/* Object property allocation layout has implications for memory and code
* footprint and generated code size/speed. The best layout also depends
@@ -2766,6 +2897,7 @@ typedef struct duk_hthread duk_context;
* Autogenerated defaults
*/
+#undef DUK_USE_ALLOW_UNDEFINED_BEHAVIOR
#define DUK_USE_ARRAY_BUILTIN
#define DUK_USE_ARRAY_FASTPATH
#define DUK_USE_ARRAY_PROP_FASTPATH
@@ -2774,6 +2906,7 @@ typedef struct duk_hthread duk_context;
#define DUK_USE_AUGMENT_ERROR_THROW
#define DUK_USE_AVOID_PLATFORM_FUNCPTRS
#define DUK_USE_BASE64_FASTPATH
+#define DUK_USE_BASE64_SUPPORT
#define DUK_USE_BOOLEAN_BUILTIN
#define DUK_USE_BUFFEROBJECT_SUPPORT
#undef DUK_USE_BUFLEN16
@@ -2781,7 +2914,10 @@ typedef struct duk_hthread duk_context;
#define DUK_USE_CACHE_ACTIVATION
#define DUK_USE_CACHE_CATCHER
#define DUK_USE_CALLSTACK_LIMIT 10000
-#define DUK_USE_COMMONJS_MODULES
+#define DUK_USE_CBOR_BUILTIN
+#define DUK_USE_CBOR_DEC_RECLIMIT 1000
+#define DUK_USE_CBOR_ENC_RECLIMIT 1000
+#define DUK_USE_CBOR_SUPPORT
#define DUK_USE_COMPILER_RECLIMIT 2500
#define DUK_USE_COROUTINE_SUPPORT
#undef DUK_USE_CPP_EXCEPTIONS
@@ -2845,13 +2981,15 @@ typedef struct duk_hthread duk_context;
#undef DUK_USE_GC_TORTURE
#undef DUK_USE_GET_MONOTONIC_TIME
#undef DUK_USE_GET_RANDOM_DOUBLE
-#undef DUK_USE_GLOBAL_BINDING
+#define DUK_USE_GLOBAL_BINDING
#define DUK_USE_GLOBAL_BUILTIN
#undef DUK_USE_HEAPPTR16
#undef DUK_USE_HEAPPTR_DEC16
#undef DUK_USE_HEAPPTR_ENC16
#define DUK_USE_HEX_FASTPATH
+#define DUK_USE_HEX_SUPPORT
#define DUK_USE_HOBJECT_ARRAY_ABANDON_LIMIT 2
+#define DUK_USE_HOBJECT_ARRAY_ABANDON_MINSIZE 257
#define DUK_USE_HOBJECT_ARRAY_FAST_RESIZE_LIMIT 9
#define DUK_USE_HOBJECT_ARRAY_MINGROW_ADD 16
#define DUK_USE_HOBJECT_ARRAY_MINGROW_DIVISOR 8
@@ -2881,11 +3019,11 @@ typedef struct duk_hthread duk_context;
#define DUK_USE_JX
#define DUK_USE_LEXER_SLIDING_WINDOW
#undef DUK_USE_LIGHTFUNC_BUILTINS
+#define DUK_USE_LITCACHE_SIZE 256
#define DUK_USE_MARK_AND_SWEEP_RECLIMIT 256
#define DUK_USE_MATH_BUILTIN
#define DUK_USE_NATIVE_CALL_RECLIMIT 1000
-#define DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER
-#define DUK_USE_NONSTD_ARRAY_MAP_TRAILER
+#undef DUK_USE_NATIVE_STACK_CHECK
#define DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
#undef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
#undef DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY
@@ -2936,12 +3074,11 @@ typedef struct duk_hthread duk_context;
#define DUK_USE_STRTAB_RESIZE_CHECK_MASK 255
#define DUK_USE_STRTAB_SHRINK_LIMIT 6
#undef DUK_USE_STRTAB_TORTURE
-#undef DUK_USE_SYMBOL_BUILTIN
+#define DUK_USE_SYMBOL_BUILTIN
#define DUK_USE_TAILCALL
#define DUK_USE_TARGET_INFO "unknown"
#define DUK_USE_TRACEBACKS
#define DUK_USE_TRACEBACK_DEPTH 10
-#define DUK_USE_USER_DECLARE() /* no user declarations */
#define DUK_USE_VALSTACK_GROW_SHIFT 2
#define DUK_USE_VALSTACK_LIMIT 1000000L
#define DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT 2
@@ -2967,6 +3104,15 @@ typedef struct duk_hthread duk_context;
/* __OVERRIDE_DEFINES__ */
/*
+ * Conditional includes
+ */
+
+#if defined(DUK_F_CPP) && defined(DUK_USE_CPP_EXCEPTIONS)
+#include <exception> /* std::exception */
+#include <stdexcept> /* std::runtime_error */
+#endif
+
+/*
* Date provider selection
*
* User may define DUK_USE_DATE_GET_NOW() etc directly, in which case we'll
diff --git a/content/handlers/javascript/duktape/duk_custom.h b/content/handlers/javascript/duktape/duk_custom.h
index 2ff931793..b373719a3 100644
--- a/content/handlers/javascript/duktape/duk_custom.h
+++ b/content/handlers/javascript/duktape/duk_custom.h
@@ -36,3 +36,5 @@
extern duk_bool_t dukky_check_timeout(void *udata);
#define DUK_USE_EXEC_TIMEOUT_CHECK dukky_check_timeout
+
+#include "netsurf/inttypes.h"
diff --git a/content/handlers/javascript/duktape/dukky.c b/content/handlers/javascript/duktape/dukky.c
index 8cfeb3985..a780b0067 100644
--- a/content/handlers/javascript/duktape/dukky.c
+++ b/content/handlers/javascript/duktape/dukky.c
@@ -19,7 +19,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Duktapeish implementation of javascript engine functions.
*/
@@ -37,6 +38,8 @@
#include "javascript/content.h"
#include "duktape/binding.h"
+#include "duktape/generics.js.inc"
+#include "duktape/polyfill.js.inc"
#include "duktape.h"
#include "dukky.h"
@@ -47,6 +50,30 @@
#define HANDLER_LISTENER_MAGIC MAGIC(HANDLER_LISTENER_MAP)
#define HANDLER_MAGIC MAGIC(HANDLER_MAP)
#define EVENT_LISTENER_JS_MAGIC MAGIC(EVENT_LISTENER_JS_MAP)
+#define GENERICS_MAGIC MAGIC(GENERICS_TABLE)
+#define THREAD_MAP MAGIC(THREAD_MAP)
+
+/**
+ * dukky javascript heap
+ */
+struct jsheap {
+ duk_context *ctx; /**< duktape base context */
+ duk_uarridx_t next_thread; /**< monotonic thread counter */
+ bool pending_destroy; /**< Whether this heap is pending destruction */
+ unsigned int live_threads; /**< number of live threads */
+ uint64_t exec_start_time;
+};
+
+/**
+ * dukky javascript thread
+ */
+struct jsthread {
+ bool pending_destroy; /**< Whether this thread is pending destruction */
+ unsigned int in_use; /**< The number of times this thread is in use */
+ jsheap *heap; /**< The heap this thread belongs to */
+ duk_context *ctx; /**< The duktape thread context */
+ duk_uarridx_t thread_idx; /**< The thread number */
+};
static duk_ret_t dukky_populate_object(duk_context *ctx, void *udata)
{
@@ -56,17 +83,20 @@ static duk_ret_t dukky_populate_object(duk_context *ctx, void *udata)
/* ... obj args protoname */
duk_get_global_string(ctx, PROTO_MAGIC);
/* .. obj args protoname prototab */
- duk_insert(ctx, -2);
- /* ... obj args prototab protoname */
+ duk_dup(ctx, -2);
+ /* ... obj args protoname prototab protoname */
duk_get_prop(ctx, -2);
- /* ... obj args prototab {proto/undefined} */
+ /* ... obj args protoname prototab {proto/undefined} */
if (duk_is_undefined(ctx, -1)) {
- NSLOG(netsurf, INFO,
- "RuhRoh, couldn't find a prototype, HTMLUnknownElement it is");
+ NSLOG(dukky, WARNING,
+ "Unable to find dukky prototype for `%s` - falling back to HTMLUnknownElement",
+ duk_get_string(ctx, -3) + 2 /* Skip the two unprintables */);
duk_pop(ctx);
duk_push_string(ctx, PROTO_NAME(HTMLUNKNOWNELEMENT));
duk_get_prop(ctx, -2);
}
+ /* ... obj args protoname prototab proto */
+ duk_remove(ctx, -3);
/* ... obj args prototab proto */
duk_dup(ctx, -1);
/* ... obj args prototab proto proto */
@@ -78,7 +108,7 @@ static duk_ret_t dukky_populate_object(duk_context *ctx, void *udata)
/* ... initfn obj[proto] args prototab proto */
duk_pop_2(ctx);
/* ... initfn obj[proto] args */
- NSLOG(netsurf, INFO, "Call the init function");
+ NSLOG(dukky, DEEPDEBUG, "Call the init function");
duk_call(ctx, nargs + 1);
return 1; /* The object */
}
@@ -86,7 +116,7 @@ static duk_ret_t dukky_populate_object(duk_context *ctx, void *udata)
duk_ret_t dukky_create_object(duk_context *ctx, const char *name, int args)
{
duk_ret_t ret;
- NSLOG(netsurf, INFO, "name=%s nargs=%d", name + 2, args);
+ NSLOG(dukky, DEEPDEBUG, "name=%s nargs=%d", name + 2, args);
/* ... args */
duk_push_object(ctx);
/* ... args obj */
@@ -107,7 +137,7 @@ duk_ret_t dukky_create_object(duk_context *ctx, const char *name, int args)
if ((ret = duk_safe_call(ctx, dukky_populate_object, NULL, args + 3, 1))
!= DUK_EXEC_SUCCESS)
return ret;
- NSLOG(netsurf, INFO, "created");
+ NSLOG(dukky, DEEPDEBUG, "created");
return DUK_EXEC_SUCCESS;
}
@@ -147,7 +177,7 @@ dukky_push_node_stacked(duk_context *ctx)
if (duk_safe_call(ctx, dukky_populate_object, NULL, 4, 1)
!= DUK_EXEC_SUCCESS) {
duk_set_top(ctx, top_at_fail);
- NSLOG(netsurf, INFO, "Boo and also hiss");
+ NSLOG(dukky, ERROR, "Failed to populate object prototype");
return false;
}
/* ... nodeptr klass nodes node */
@@ -163,6 +193,12 @@ dukky_push_node_stacked(duk_context *ctx)
/* ... node nodeptr klass nodes */
duk_pop_3(ctx);
/* ... node */
+ if (NSLOG_COMPILED_MIN_LEVEL <= NSLOG_LEVEL_DEEPDEBUG) {
+ duk_dup(ctx, -1);
+ const char * what = duk_safe_to_string(ctx, -1);
+ NSLOG(dukky, DEEPDEBUG, "Created: %s", what);
+ duk_pop(ctx);
+ }
return true;
}
@@ -205,7 +241,7 @@ static void dukky_html_element_class_from_tag_type(dom_html_element_type type,
SET_HTML_CLASS(LINK)
break;
case DOM_HTML_ELEMENT_TYPE_BUTTON:
- SET_HTML_CLASS(BUTTOM)
+ SET_HTML_CLASS(BUTTON)
break;
case DOM_HTML_ELEMENT_TYPE_INPUT:
SET_HTML_CLASS(INPUT)
@@ -344,9 +380,12 @@ static void dukky_html_element_class_from_tag_type(dom_html_element_type type,
case DOM_HTML_ELEMENT_TYPE_ISINDEX:
SET_HTML_CLASS(ISINDEX)
break;
+ case DOM_HTML_ELEMENT_TYPE_CANVAS:
+ SET_HTML_CLASS(CANVAS)
+ break;
case DOM_HTML_ELEMENT_TYPE__COUNT:
assert(type != DOM_HTML_ELEMENT_TYPE__COUNT);
- /* fallthrough */
+ fallthrough;
case DOM_HTML_ELEMENT_TYPE__UNKNOWN:
SET_HTML_CLASS(UNKNOWN)
break;
@@ -385,14 +424,14 @@ dukky_push_node_klass(duk_context *ctx, struct dom_node *node)
err = dom_node_get_namespace(node, &namespace);
if (err != DOM_NO_ERR) {
/* Feck it, element */
- NSLOG(netsurf, INFO,
+ NSLOG(dukky, ERROR,
"dom_node_get_namespace() failed");
duk_push_string(ctx, PROTO_NAME(ELEMENT));
break;
}
if (namespace == NULL) {
/* No namespace, -> element */
- NSLOG(netsurf, INFO, "no namespace");
+ NSLOG(dukky, DEBUG, "no namespace");
duk_push_string(ctx, PROTO_NAME(ELEMENT));
break;
}
@@ -442,7 +481,7 @@ dukky_push_node_klass(duk_context *ctx, struct dom_node *node)
duk_bool_t
dukky_push_node(duk_context *ctx, struct dom_node *node)
{
- JS_LOG("Pushing node %p", node);
+ NSLOG(dukky, DEEPDEBUG, "Pushing node %p", node);
/* First check if we can find the node */
/* ... */
duk_get_global_string(ctx, NODE_MAGIC);
@@ -457,7 +496,12 @@ dukky_push_node(duk_context *ctx, struct dom_node *node)
/* ... node nodes */
duk_pop(ctx);
/* ... node */
- JS_LOG("Found it memoised");
+ if (NSLOG_COMPILED_MIN_LEVEL <= NSLOG_LEVEL_DEEPDEBUG) {
+ duk_dup(ctx, -1);
+ const char * what = duk_safe_to_string(ctx, -1);
+ NSLOG(dukky, DEEPDEBUG, "Found it memoised: %s", what);
+ duk_pop(ctx);
+ }
return true;
}
/* ... nodes undefined */
@@ -522,22 +566,14 @@ static void *dukky_realloc_function(void *udata, void *ptr, duk_size_t size)
return realloc(ptr, size);
}
+
static void dukky_free_function(void *udata, void *ptr)
{
if (ptr != NULL)
free(ptr);
}
-
-/**************************************** js.h ******************************/
-struct jscontext {
- duk_context *ctx;
- duk_context *thread;
- uint64_t exec_start_time;
-};
-
-#define CTX (ctx->thread)
-
+/* exported interface documented in js.h */
void js_initialise(void)
{
/** TODO: Forces JS on for our testing, needs changing before a release
@@ -549,21 +585,22 @@ void js_initialise(void)
javascript_init();
}
+
+/* exported interface documented in js.h */
void js_finalise(void)
{
/* NADA for now */
}
-#define DUKKY_NEW_PROTOTYPE(klass, uklass, klass_name) \
- dukky_create_prototype(ctx, dukky_##klass##___proto, PROTO_NAME(uklass), klass_name)
-nserror js_newcontext(int timeout, jscallback *cb, void *cbctx,
- jscontext **jsctx)
+/* exported interface documented in js.h */
+nserror
+js_newheap(int timeout, jsheap **heap)
{
duk_context *ctx;
- jscontext *ret = calloc(1, sizeof(*ret));
- *jsctx = NULL;
- NSLOG(netsurf, INFO, "Creating new duktape javascript context");
+ jsheap *ret = calloc(1, sizeof(*ret));
+ *heap = NULL;
+ NSLOG(dukky, DEBUG, "Creating new duktape javascript heap");
if (ret == NULL) return NSERROR_NOMEM;
ctx = ret->ctx = duk_create_heap(
dukky_alloc_function,
@@ -579,28 +616,62 @@ nserror js_newcontext(int timeout, jscallback *cb, void *cbctx,
duk_put_global_string(ctx, PROTO_MAGIC);
/* Create prototypes here */
dukky_create_prototypes(ctx);
+ /* Now create the thread map */
+ duk_push_object(ctx);
+ duk_put_global_string(ctx, THREAD_MAP);
- *jsctx = ret;
+ *heap = ret;
return NSERROR_OK;
}
-void js_destroycontext(jscontext *ctx)
+
+static void dukky_destroyheap(jsheap *heap)
+{
+ assert(heap->pending_destroy == true);
+ assert(heap->live_threads == 0);
+ NSLOG(dukky, DEBUG, "Destroying duktape javascript context");
+ duk_destroy_heap(heap->ctx);
+ free(heap);
+}
+
+/* exported interface documented in js.h */
+void js_destroyheap(jsheap *heap)
{
- NSLOG(netsurf, INFO, "Destroying duktape javascript context");
- duk_destroy_heap(ctx->ctx);
- free(ctx);
+ heap->pending_destroy = true;
+ if (heap->live_threads == 0) {
+ dukky_destroyheap(heap);
+ }
}
-jsobject *js_newcompartment(jscontext *ctx, void *win_priv, void *doc_priv)
+/* Just for here, the CTX is in ret, not thread */
+#define CTX (ret->ctx)
+
+/* exported interface documented in js.h */
+nserror js_newthread(jsheap *heap, void *win_priv, void *doc_priv, jsthread **thread)
{
- assert(ctx != NULL);
- /* Pop any active thread off */
- NSLOG(netsurf, INFO,
- "Yay, new compartment, win_priv=%p, doc_priv=%p", win_priv,
- doc_priv);
- duk_set_top(ctx->ctx, 0);
- duk_push_thread(ctx->ctx);
- ctx->thread = duk_require_context(ctx->ctx, -1);
+ jsthread *ret;
+ assert(heap != NULL);
+ assert(heap->pending_destroy == false);
+
+ ret = calloc(1, sizeof (*ret));
+ if (ret == NULL) {
+ NSLOG(dukky, ERROR, "Unable to allocate new JS thread structure");
+ return NSERROR_NOMEM;
+ }
+
+ NSLOG(dukky, DEBUG,
+ "New javascript/duktape thread, win_priv=%p, doc_priv=%p",
+ win_priv, doc_priv);
+
+ /* create new thread */
+ duk_get_global_string(heap->ctx, THREAD_MAP); /* ... threads */
+ duk_push_thread(heap->ctx); /* ... threads thread */
+ ret->heap = heap;
+ ret->ctx = duk_require_context(heap->ctx, -1);
+ ret->thread_idx = heap->next_thread++;
+ duk_put_prop_index(heap->ctx, -2, ret->thread_idx);
+ heap->live_threads++;
+ duk_pop(heap->ctx); /* ... */
duk_push_int(CTX, 0);
duk_push_int(CTX, 1);
duk_push_int(CTX, 2);
@@ -624,19 +695,152 @@ jsobject *js_newcompartment(jscontext *ctx, void *win_priv, void *doc_priv)
duk_push_object(CTX);
duk_put_global_string(CTX, EVENT_MAGIC);
- return (jsobject *)ctx;
+ /* Now load the polyfills */
+ /* ... */
+ duk_push_string(CTX, "polyfill.js");
+ /* ..., polyfill.js */
+ if (duk_pcompile_lstring_filename(CTX, DUK_COMPILE_EVAL,
+ (const char *)polyfill_js, polyfill_js_len) != 0) {
+ NSLOG(dukky, CRITICAL, "%s", duk_safe_to_string(CTX, -1));
+ NSLOG(dukky, CRITICAL, "Unable to compile polyfill.js, thread aborted");
+ js_destroythread(ret);
+ return NSERROR_INIT_FAILED;
+ }
+ /* ..., (generics.js) */
+ if (dukky_pcall(CTX, 0, true) != 0) {
+ NSLOG(dukky, CRITICAL, "Unable to run polyfill.js, thread aborted");
+ js_destroythread(ret);
+ return NSERROR_INIT_FAILED;
+ }
+ /* ..., result */
+ duk_pop(CTX);
+ /* ... */
+
+ /* Now load the NetSurf table in */
+ /* ... */
+ duk_push_string(CTX, "generics.js");
+ /* ..., generics.js */
+ if (duk_pcompile_lstring_filename(CTX, DUK_COMPILE_EVAL,
+ (const char *)generics_js, generics_js_len) != 0) {
+ NSLOG(dukky, CRITICAL, "%s", duk_safe_to_string(CTX, -1));
+ NSLOG(dukky, CRITICAL, "Unable to compile generics.js, thread aborted");
+ js_destroythread(ret);
+ return NSERROR_INIT_FAILED;
+ }
+ /* ..., (generics.js) */
+ if (dukky_pcall(CTX, 0, true) != 0) {
+ NSLOG(dukky, CRITICAL, "Unable to run generics.js, thread aborted");
+ js_destroythread(ret);
+ return NSERROR_INIT_FAILED;
+ }
+ /* ..., result */
+ duk_pop(CTX);
+ /* ... */
+ duk_push_global_object(CTX);
+ /* ..., Win */
+ duk_get_prop_string(CTX, -1, "NetSurf");
+ /* ..., Win, NetSurf */
+ duk_put_global_string(CTX, GENERICS_MAGIC);
+ /* ..., Win */
+ duk_del_prop_string(CTX, -1, "NetSurf");
+ duk_pop(CTX);
+ /* ... */
+
+ dukky_log_stack_frame(CTX, "New thread created");
+ NSLOG(dukky, DEBUG, "New thread is %p in heap %p", thread, heap);
+ *thread = ret;
+
+ return NSERROR_OK;
}
-static duk_ret_t eval_top_string(duk_context *ctx, void *udata)
+/* Now switch to the long term CTX behaviour */
+#undef CTX
+#define CTX (thread->ctx)
+
+/* exported interface documented in js.h */
+nserror js_closethread(jsthread *thread)
{
- duk_eval(ctx);
- return 0;
+ /* We can always close down a thread, it might just confuse
+ * the code running, though we don't mind since we're in the
+ * process of destruction at this point
+ */
+ duk_int_t top = duk_get_top(CTX);
+
+ /* Closing down the extant thread */
+ NSLOG(dukky, DEBUG, "Closing down extant thread %p in heap %p", thread, thread->heap);
+ duk_get_global_string(CTX, MAGIC(closedownThread));
+ dukky_pcall(CTX, 0, true);
+
+ /* Restore whatever stack we had */
+ duk_set_top(CTX, top);
+
+ return NSERROR_OK;
+}
+
+/**
+ * Destroy a Duktape thread
+ */
+static void dukky_destroythread(jsthread *thread)
+{
+ jsheap *heap = thread->heap;
+
+ assert(thread->in_use == 0);
+ assert(thread->pending_destroy == true);
+
+ /* Closing down the extant thread */
+ NSLOG(dukky, DEBUG, "Closing down extant thread %p in heap %p", thread, heap);
+ duk_get_global_string(CTX, MAGIC(closedownThread));
+ dukky_pcall(CTX, 0, true);
+
+ /* Now delete the thread from the heap */
+ duk_get_global_string(heap->ctx, THREAD_MAP); /* ... threads */
+ duk_del_prop_index(heap->ctx, -1, thread->thread_idx);
+ duk_pop(heap->ctx); /* ... */
+
+ /* We can now free the thread object */
+ free(thread);
+
+ /* Finally give the heap a chance to clean up */
+ duk_gc(heap->ctx, 0);
+ duk_gc(heap->ctx, DUK_GC_COMPACT);
+ heap->live_threads--;
+
+ /* And if the heap should now go, blow it away */
+ if (heap->pending_destroy == true && heap->live_threads == 0) {
+ dukky_destroyheap(heap);
+ }
+}
+
+/* exported interface documented in js.h */
+void js_destroythread(jsthread *thread)
+{
+ thread->pending_destroy = true;
+ if (thread->in_use == 0) {
+ dukky_destroythread(thread);
+ }
+}
+
+static void dukky_enter_thread(jsthread *thread)
+{
+ assert(thread != NULL);
+ thread->in_use++;
+}
+
+static void dukky_leave_thread(jsthread *thread)
+{
+ assert(thread != NULL);
+ assert(thread->in_use > 0);
+
+ thread->in_use--;
+ if (thread->in_use == 0 && thread->pending_destroy == true) {
+ dukky_destroythread(thread);
+ }
}
duk_bool_t dukky_check_timeout(void *udata)
{
#define JS_EXEC_TIMEOUT_MS 10000 /* 10 seconds */
- jscontext *ctx = (jscontext *) udata;
+ jsheap *heap = (jsheap *) udata;
uint64_t now;
(void) nsu_getmonotonic_ms(&now);
@@ -645,41 +849,161 @@ duk_bool_t dukky_check_timeout(void *udata)
* so only test for execution timeout if we've recorded a
* start time.
*/
- return ctx->exec_start_time != 0 &&
- now > (ctx->exec_start_time + JS_EXEC_TIMEOUT_MS);
+ return heap->exec_start_time != 0 &&
+ now > (heap->exec_start_time + JS_EXEC_TIMEOUT_MS);
}
-bool js_exec(jscontext *ctx, const char *txt, size_t txtlen)
+static void dukky_dump_error(duk_context *ctx)
{
- assert(ctx);
- if (txt == NULL || txtlen == 0) return false;
- duk_set_top(CTX, 0);
- duk_push_lstring(CTX, txt, txtlen);
-
- (void) nsu_getmonotonic_ms(&ctx->exec_start_time);
- if (duk_safe_call(CTX, eval_top_string, NULL, 1, 1) == DUK_EXEC_ERROR) {
- duk_get_prop_string(CTX, 0, "name");
- duk_get_prop_string(CTX, 0, "message");
- duk_get_prop_string(CTX, 0, "fileName");
- duk_get_prop_string(CTX, 0, "lineNumber");
- duk_get_prop_string(CTX, 0, "stack");
- NSLOG(netsurf, INFO, "Uncaught error in JS: %s: %s",
- duk_safe_to_string(CTX, 1), duk_safe_to_string(CTX, 2));
- NSLOG(netsurf, INFO, " was at: %s line %s",
- duk_safe_to_string(CTX, 3), duk_safe_to_string(CTX, 4));
- NSLOG(netsurf, INFO, " Stack trace: %s",
- duk_safe_to_string(CTX, 5));
+ /* stack is ..., errobj */
+ duk_dup_top(ctx);
+ /* ..., errobj, errobj */
+ NSLOG(jserrors, WARNING, "Uncaught error in JS: %s", duk_safe_to_stacktrace(ctx, -1));
+ /* ..., errobj, errobj.stackstring */
+ duk_pop(ctx);
+ /* ..., errobj */
+}
+
+static void dukky_reset_start_time(duk_context *ctx)
+{
+ duk_memory_functions funcs;
+ jsheap *heap;
+ duk_get_memory_functions(ctx, &funcs);
+ heap = funcs.udata;
+ (void) nsu_getmonotonic_ms(&heap->exec_start_time);
+}
+
+duk_int_t dukky_pcall(duk_context *ctx, duk_size_t argc, bool reset_timeout)
+{
+ if (reset_timeout) {
+ dukky_reset_start_time(ctx);
+ }
+
+ duk_int_t ret = duk_pcall(ctx, argc);
+ if (ret) {
+ /* Something went wrong calling this... */
+ dukky_dump_error(ctx);
+ }
+
+ return ret;
+}
+
+
+void dukky_push_generics(duk_context *ctx, const char *generic)
+{
+ /* ... */
+ duk_get_global_string(ctx, GENERICS_MAGIC);
+ /* ..., generics */
+ duk_get_prop_string(ctx, -1, generic);
+ /* ..., generics, generic */
+ duk_remove(ctx, -2);
+ /* ..., generic */
+}
+
+static duk_int_t dukky_push_context_dump(duk_context *ctx, void *udata)
+{
+ duk_push_context_dump(ctx);
+ return 1;
+}
+
+void dukky_log_stack_frame(duk_context *ctx, const char * reason)
+{
+ if (duk_safe_call(ctx, dukky_push_context_dump, NULL, 0, 1) != 0) {
+ duk_pop(ctx);
+ duk_push_string(ctx, "[???]");
+ }
+ NSLOG(dukky, DEEPDEBUG, "%s, stack is: %s", reason, duk_safe_to_string(ctx, -1));
+ duk_pop(ctx);
+}
+
+
+/* exported interface documented in js.h */
+bool
+js_exec(jsthread *thread, const uint8_t *txt, size_t txtlen, const char *name)
+{
+ bool ret = false;
+ assert(thread);
+
+ if (txt == NULL || txtlen == 0) {
+ return false;
+ }
+
+ if (thread->pending_destroy) {
+ NSLOG(dukky, DEEPDEBUG, "Skipping exec call because thread is dead");
return false;
}
+
+ dukky_enter_thread(thread);
+
+ duk_set_top(CTX, 0);
+ NSLOG(dukky, DEEPDEBUG, "Running %"PRIsizet" bytes from %s", txtlen, name);
+ /* NSLOG(dukky, DEEPDEBUG, "\n%s\n", txt); */
+
+ dukky_reset_start_time(CTX);
+ if (name != NULL) {
+ duk_push_string(CTX, name);
+ } else {
+ duk_push_string(CTX, "?unknown source?");
+ }
+ if (duk_pcompile_lstring_filename(CTX,
+ DUK_COMPILE_EVAL,
+ (const char *)txt,
+ txtlen) != 0) {
+ NSLOG(dukky, DEBUG, "Failed to compile JavaScript input");
+ goto handle_error;
+ }
+
+ if (duk_pcall(CTX, 0/*nargs*/) == DUK_EXEC_ERROR) {
+ NSLOG(dukky, DEBUG, "Failed to execute JavaScript");
+ goto handle_error;
+ }
+
if (duk_get_top(CTX) == 0) duk_push_boolean(CTX, false);
- NSLOG(netsurf, INFO, "Returning %s",
+ NSLOG(dukky, DEEPDEBUG, "Returning %s",
duk_get_boolean(CTX, 0) ? "true" : "false");
- return duk_get_boolean(CTX, 0);
+ ret = duk_get_boolean(CTX, 0);
+ goto out;
+
+handle_error:
+ dukky_dump_error(CTX);
+out:
+ dukky_leave_thread(thread);
+ return ret;
+}
+
+static const char* dukky_event_proto(dom_event *evt)
+{
+ const char *ret = PROTO_NAME(EVENT);
+ dom_string *type = NULL;
+ dom_exception err;
+
+ err = dom_event_get_type(evt, &type);
+ if (err != DOM_NO_ERR) {
+ goto out;
+ }
+
+ if (dom_string_isequal(type, corestring_dom_keydown)) {
+ ret = PROTO_NAME(KEYBOARDEVENT);
+ goto out;
+ } else if (dom_string_isequal(type, corestring_dom_keyup)) {
+ ret = PROTO_NAME(KEYBOARDEVENT);
+ goto out;
+ } else if (dom_string_isequal(type, corestring_dom_keypress)) {
+ ret = PROTO_NAME(KEYBOARDEVENT);
+ goto out;
+ }
+
+out:
+ if (type != NULL) {
+ dom_string_unref(type);
+ }
+
+ return ret;
}
/*** New style event handling ***/
-static void dukky_push_event(duk_context *ctx, dom_event *evt)
+void dukky_push_event(duk_context *ctx, dom_event *evt)
{
/* ... */
duk_get_global_string(ctx, EVENT_MAGIC);
@@ -693,7 +1017,7 @@ static void dukky_push_event(duk_context *ctx, dom_event *evt)
duk_pop(ctx);
/* ... events */
duk_push_pointer(ctx, evt);
- if (dukky_create_object(ctx, PROTO_NAME(EVENT), 1) != DUK_EXEC_SUCCESS) {
+ if (dukky_create_object(ctx, dukky_event_proto(evt), 1) != DUK_EXEC_SUCCESS) {
/* ... events err */
duk_pop(ctx);
/* ... events */
@@ -721,9 +1045,18 @@ static void dukky_push_handler_code_(duk_context *ctx, dom_string *name,
dom_exception exc;
dom_node_type ntype;
- /* Currently safe since libdom has no event targets which are not
- * nodes. Reconsider this as and when we work out how to have
- * window do stuff
+ /* If et is NULL, then we're actually dealing with the Window object
+ * which has no default handlers and no way to assign handlers
+ * which aren't directly stored in the HANDLER_MAGIC
+ */
+ if (et == NULL) {
+ duk_push_lstring(ctx, "", 0);
+ return;
+ }
+
+ /* The rest of this assumes et is a proper event target and expands
+ * out from there based on the assumption that all valid event targets
+ * are nodes.
*/
exc = dom_node_get_node_type(et, &ntype);
if (exc != DOM_NO_ERR) {
@@ -788,7 +1121,7 @@ bool dukky_get_current_value_of_event_handler(duk_context *ctx,
/* ... node fullhandlersrc filename */
if (duk_pcompile(ctx, DUK_COMPILE_FUNCTION) != 0) {
/* ... node err */
- NSLOG(netsurf, INFO,
+ NSLOG(dukky, DEBUG,
"Unable to proceed with handler, could not compile");
duk_pop_2(ctx);
return false;
@@ -809,9 +1142,7 @@ bool dukky_get_current_value_of_event_handler(duk_context *ctx,
static void dukky_generic_event_handler(dom_event *evt, void *pw)
{
- duk_memory_functions funcs;
duk_context *ctx = (duk_context *)pw;
- jscontext *jsctx;
dom_string *name;
dom_exception exc;
dom_event_target *targ;
@@ -819,31 +1150,27 @@ static void dukky_generic_event_handler(dom_event *evt, void *pw)
duk_uarridx_t idx;
event_listener_flags flags;
- /* Retrieve the JS context from the Duktape context */
- duk_get_memory_functions(ctx, &funcs);
- jsctx = funcs.udata;
-
- NSLOG(netsurf, INFO, "WOOP WOOP, An event:");
+ NSLOG(dukky, DEBUG, "Handling an event in duktape interface...");
exc = dom_event_get_type(evt, &name);
if (exc != DOM_NO_ERR) {
- NSLOG(netsurf, INFO, "Unable to find the event name");
+ NSLOG(dukky, DEBUG, "Unable to find the event name");
return;
}
- NSLOG(netsurf, INFO, "Event's name is %*s", dom_string_length(name),
+ NSLOG(dukky, DEBUG, "Event's name is %*s", (int)dom_string_length(name),
dom_string_data(name));
exc = dom_event_get_event_phase(evt, &phase);
if (exc != DOM_NO_ERR) {
- NSLOG(netsurf, INFO, "Unable to get event phase");
+ NSLOG(dukky, WARNING, "Unable to get event phase");
return;
}
- NSLOG(netsurf, INFO, "Event phase is: %s (%d)",
+ NSLOG(dukky, DEBUG, "Event phase is: %s (%d)",
phase == DOM_CAPTURING_PHASE ? "capturing" : phase == DOM_AT_TARGET ? "at-target" : phase == DOM_BUBBLING_PHASE ? "bubbling" : "unknown",
(int)phase);
exc = dom_event_get_current_target(evt, &targ);
if (exc != DOM_NO_ERR) {
dom_string_unref(name);
- NSLOG(netsurf, INFO, "Unable to find the event target");
+ NSLOG(dukky, DEBUG, "Unable to find the event target");
return;
}
@@ -857,7 +1184,7 @@ static void dukky_generic_event_handler(dom_event *evt, void *pw)
if (dukky_push_node(ctx, (dom_node *)targ) == false) {
dom_string_unref(name);
dom_node_unref(targ);
- NSLOG(netsurf, INFO,
+ NSLOG(dukky, DEBUG,
"Unable to push JS node representation?!");
return;
}
@@ -870,15 +1197,15 @@ static void dukky_generic_event_handler(dom_event *evt, void *pw)
/* ... handler node */
dukky_push_event(ctx, evt);
/* ... handler node event */
- (void) nsu_getmonotonic_ms(&jsctx->exec_start_time);
+ dukky_reset_start_time(ctx);
if (duk_pcall_method(ctx, 1) != 0) {
/* Failed to run the method */
/* ... err */
- NSLOG(netsurf, INFO,
+ NSLOG(dukky, DEBUG,
"OH NOES! An error running a callback. Meh.");
exc = dom_event_stop_immediate_propagation(evt);
if (exc != DOM_NO_ERR)
- NSLOG(netsurf, INFO,
+ NSLOG(dukky, DEBUG,
"WORSE! could not stop propagation");
duk_get_prop_string(ctx, -1, "name");
duk_get_prop_string(ctx, -2, "message");
@@ -886,13 +1213,13 @@ static void dukky_generic_event_handler(dom_event *evt, void *pw)
duk_get_prop_string(ctx, -4, "lineNumber");
duk_get_prop_string(ctx, -5, "stack");
/* ... err name message fileName lineNumber stack */
- NSLOG(netsurf, INFO, "Uncaught error in JS: %s: %s",
+ NSLOG(dukky, DEBUG, "Uncaught error in JS: %s: %s",
duk_safe_to_string(ctx, -5),
duk_safe_to_string(ctx, -4));
- NSLOG(netsurf, INFO, " was at: %s line %s",
+ NSLOG(dukky, INFO, " was at: %s line %s",
duk_safe_to_string(ctx, -3),
duk_safe_to_string(ctx, -2));
- NSLOG(netsurf, INFO, " Stack trace: %s",
+ NSLOG(dukky, INFO, " Stack trace: %s",
duk_safe_to_string(ctx, -1));
duk_pop_n(ctx, 6);
@@ -969,15 +1296,15 @@ handle_extras:
/* ... copy handler callback node */
dukky_push_event(ctx, evt);
/* ... copy handler callback node event */
- (void) nsu_getmonotonic_ms(&jsctx->exec_start_time);
+ dukky_reset_start_time(ctx);
if (duk_pcall_method(ctx, 1) != 0) {
/* Failed to run the method */
/* ... copy handler err */
- NSLOG(netsurf, INFO,
+ NSLOG(dukky, DEBUG,
"OH NOES! An error running a callback. Meh.");
exc = dom_event_stop_immediate_propagation(evt);
if (exc != DOM_NO_ERR)
- NSLOG(netsurf, INFO,
+ NSLOG(dukky, DEBUG,
"WORSE! could not stop propagation");
duk_get_prop_string(ctx, -1, "name");
duk_get_prop_string(ctx, -2, "message");
@@ -985,14 +1312,14 @@ handle_extras:
duk_get_prop_string(ctx, -4, "lineNumber");
duk_get_prop_string(ctx, -5, "stack");
/* ... err name message fileName lineNumber stack */
- NSLOG(netsurf, INFO, "Uncaught error in JS: %s: %s",
+ NSLOG(dukky, DEBUG, "Uncaught error in JS: %s: %s",
duk_safe_to_string(ctx, -5),
duk_safe_to_string(ctx, -4));
- NSLOG(netsurf, INFO,
+ NSLOG(dukky, DEBUG,
" was at: %s line %s",
duk_safe_to_string(ctx, -3),
duk_safe_to_string(ctx, -2));
- NSLOG(netsurf, INFO, " Stack trace: %s",
+ NSLOG(dukky, DEBUG, " Stack trace: %s",
duk_safe_to_string(ctx, -1));
duk_pop_n(ctx, 7);
@@ -1023,8 +1350,14 @@ void dukky_register_event_listener_for(duk_context *ctx,
dom_exception exc;
/* ... */
- if (dukky_push_node(ctx, (struct dom_node *)ele) == false)
- return;
+ if (ele == NULL) {
+ /* A null element is the Window object */
+ duk_push_global_object(ctx);
+ } else {
+ /* Non null elements must be pushed as a node object */
+ if (dukky_push_node(ctx, (struct dom_node *)ele) == false)
+ return;
+ }
/* ... node */
duk_get_prop_string(ctx, -1, HANDLER_LISTENER_MAGIC);
/* ... node handlers */
@@ -1045,18 +1378,26 @@ void dukky_register_event_listener_for(duk_context *ctx,
/* ... node handlers */
duk_pop_2(ctx);
/* ... */
+ if (ele == NULL) {
+ /* Nothing more to do, Window doesn't register in the
+ * normal event listener flow
+ */
+ return;
+ }
+
+ /* Otherwise add an event listener to the element */
exc = dom_event_listener_create(dukky_generic_event_handler, ctx,
&listen);
if (exc != DOM_NO_ERR) return;
exc = dom_event_target_add_event_listener(
ele, name, listen, capture);
if (exc != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
+ NSLOG(dukky, DEBUG,
"Unable to register listener for %p.%*s", ele,
- dom_string_length(name), dom_string_data(name));
+ (int)dom_string_length(name), dom_string_data(name));
} else {
- NSLOG(netsurf, INFO, "have registered listener for %p.%*s",
- ele, dom_string_length(name), dom_string_data(name));
+ NSLOG(dukky, DEBUG, "have registered listener for %p.%*s",
+ ele, (int)dom_string_length(name), dom_string_data(name));
}
dom_event_listener_unref(listen);
}
@@ -1127,9 +1468,9 @@ void dukky_shuffle_array(duk_context *ctx, duk_uarridx_t idx)
}
-void js_handle_new_element(jscontext *ctx, struct dom_element *node)
+void js_handle_new_element(jsthread *thread, struct dom_element *node)
{
- assert(ctx);
+ assert(thread);
assert(node);
dom_namednodemap *map;
dom_exception exc;
@@ -1152,6 +1493,8 @@ void js_handle_new_element(jscontext *ctx, struct dom_element *node)
if (exc != DOM_NO_ERR) return;
if (map == NULL) return;
+ dukky_enter_thread(thread);
+
exc = dom_namednodemap_get_length(map, &siz);
if (exc != DOM_NO_ERR) goto out;
@@ -1201,11 +1544,14 @@ out:
dom_node_unref(attr);
dom_namednodemap_unref(map);
+
+ dukky_leave_thread(thread);
}
-void js_event_cleanup(jscontext *ctx, struct dom_event *evt)
+void js_event_cleanup(jsthread *thread, struct dom_event *evt)
{
- assert(ctx);
+ assert(thread);
+ dukky_enter_thread(thread);
/* ... */
duk_get_global_string(CTX, EVENT_MAGIC);
/* ... EVENT_MAP */
@@ -1215,15 +1561,16 @@ void js_event_cleanup(jscontext *ctx, struct dom_event *evt)
/* ... EVENT_MAP */
duk_pop(CTX);
/* ... */
+ dukky_leave_thread(thread);
}
-bool js_fire_event(jscontext *ctx, const char *type, struct dom_document *doc, struct dom_node *target)
+bool js_fire_event(jsthread *thread, const char *type, struct dom_document *doc, struct dom_node *target)
{
dom_exception exc;
dom_event *evt;
dom_event_target *body;
- NSLOG(netsurf, INFO, "Event: %s (doc=%p, target=%p)", type, doc,
+ NSLOG(dukky, DEBUG, "Event: %s (doc=%p, target=%p)", type, doc,
target);
/** @todo Make this more generic, this only handles load and only
@@ -1253,6 +1600,7 @@ bool js_fire_event(jscontext *ctx, const char *type, struct dom_document *doc, s
dom_event_unref(evt);
return true;
}
+ dukky_enter_thread(thread);
/* ... */
duk_get_global_string(CTX, HANDLER_MAGIC);
/* ... handlers */
@@ -1269,16 +1617,22 @@ bool js_fire_event(jscontext *ctx, const char *type, struct dom_document *doc, s
exc = dom_html_document_get_body(doc, &body);
if (exc != DOM_NO_ERR) {
dom_event_unref(evt);
+ dukky_leave_thread(thread);
return true;
}
dukky_push_node(CTX, (struct dom_node *)body);
/* ... handlers bodynode */
if (dukky_get_current_value_of_event_handler(
CTX, corestring_dom_load, body) == false) {
+ /* Unref the body, we don't need it any more */
+ dom_node_unref(body);
/* ... handlers */
duk_pop(CTX);
+ dukky_leave_thread(thread);
return true;
}
+ /* Unref the body, we don't need it any more */
+ dom_node_unref(body);
/* ... handlers handler bodynode */
duk_pop(CTX);
}
@@ -1291,11 +1645,11 @@ bool js_fire_event(jscontext *ctx, const char *type, struct dom_document *doc, s
/* ... handler Window */
dukky_push_event(CTX, evt);
/* ... handler Window event */
- (void) nsu_getmonotonic_ms(&ctx->exec_start_time);
+ dukky_reset_start_time(CTX);
if (duk_pcall_method(CTX, 1) != 0) {
/* Failed to run the handler */
/* ... err */
- NSLOG(netsurf, INFO,
+ NSLOG(dukky, DEBUG,
"OH NOES! An error running a handler. Meh.");
duk_get_prop_string(CTX, -1, "name");
duk_get_prop_string(CTX, -2, "message");
@@ -1303,25 +1657,27 @@ bool js_fire_event(jscontext *ctx, const char *type, struct dom_document *doc, s
duk_get_prop_string(CTX, -4, "lineNumber");
duk_get_prop_string(CTX, -5, "stack");
/* ... err name message fileName lineNumber stack */
- NSLOG(netsurf, INFO, "Uncaught error in JS: %s: %s",
+ NSLOG(dukky, DEBUG, "Uncaught error in JS: %s: %s",
duk_safe_to_string(CTX, -5),
duk_safe_to_string(CTX, -4));
- NSLOG(netsurf, INFO, " was at: %s line %s",
+ NSLOG(dukky, DEBUG, " was at: %s line %s",
duk_safe_to_string(CTX, -3),
duk_safe_to_string(CTX, -2));
- NSLOG(netsurf, INFO, " Stack trace: %s",
+ NSLOG(dukky, DEBUG, " Stack trace: %s",
duk_safe_to_string(CTX, -1));
duk_pop_n(CTX, 6);
/* ... */
- js_event_cleanup(ctx, evt);
+ js_event_cleanup(thread, evt);
dom_event_unref(evt);
+ dukky_leave_thread(thread);
return true;
}
/* ... result */
duk_pop(CTX);
/* ... */
- js_event_cleanup(ctx, evt);
+ js_event_cleanup(thread, evt);
dom_event_unref(evt);
+ dukky_leave_thread(thread);
return true;
}
diff --git a/content/handlers/javascript/duktape/dukky.h b/content/handlers/javascript/duktape/dukky.h
index 435e0c305..5a67951dc 100644
--- a/content/handlers/javascript/duktape/dukky.h
+++ b/content/handlers/javascript/duktape/dukky.h
@@ -25,14 +25,6 @@
#ifndef DUKKY_H
#define DUKKY_H
-#ifdef JS_DEBUG
-# define JS_LOG(format, args...) NSLOG(netsurf, INFO, format , ##args)
-#else
-# define JS_LOG(format, ...) ((void) 0)
-#endif
-
-#define LOG(format, args...) NSLOG(netsurf, INFO, format , ##args)
-
duk_ret_t dukky_create_object(duk_context *ctx, const char *name, int args);
duk_bool_t dukky_push_node_stacked(duk_context *ctx);
duk_bool_t dukky_push_node(duk_context *ctx, struct dom_node *node);
@@ -44,6 +36,7 @@ void dukky_register_event_listener_for(duk_context *ctx,
bool dukky_get_current_value_of_event_handler(duk_context *ctx,
dom_string *name,
dom_event_target *et);
+void dukky_push_event(duk_context *ctx, dom_event *evt);
bool dukky_event_target_push_listeners(duk_context *ctx, bool dont_create);
typedef enum {
@@ -55,4 +48,13 @@ typedef enum {
void dukky_shuffle_array(duk_context *ctx, duk_uarridx_t idx);
+/* pcall something, and if it errored, also dump the error to the log */
+duk_int_t dukky_pcall(duk_context *ctx, duk_size_t argc, bool reset_timeout);
+
+/* Push a generics function onto the stack */
+void dukky_push_generics(duk_context *ctx, const char *generic);
+
+/* Log the current stack frame if possible */
+void dukky_log_stack_frame(duk_context *ctx, const char * reason);
+
#endif
diff --git a/content/handlers/javascript/duktape/duktape.c b/content/handlers/javascript/duktape/duktape.c
index 52b9e1309..18b2e99f9 100644
--- a/content/handlers/javascript/duktape/duktape.c
+++ b/content/handlers/javascript/duktape/duktape.c
@@ -1,7 +1,7 @@
/* Omit from static analysis. */
#ifndef __clang_analyzer__
/*
- * Single source autogenerated distributable for Duktape 2.2.0.
+ * Single source autogenerated distributable for Duktape 2.7.0.
*
* Git commit external (external).
* Git branch external.
@@ -18,7 +18,7 @@
*
* (http://opensource.org/licenses/MIT)
*
-* Copyright (c) 2013-2017 by Duktape authors (see AUTHORS.rst)
+* Copyright (c) 2013-present by Duktape authors (see AUTHORS.rst)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -89,6 +89,30 @@
* * Steven Don (https://github.com/shdon)
* * Simon Stone (https://github.com/sstone1)
* * \J. McC. (https://github.com/jmhmccr)
+* * Jakub Nowakowski (https://github.com/jimvonmoon)
+* * Tommy Nguyen (https://github.com/tn0502)
+* * Fabrice Fontaine (https://github.com/ffontaine)
+* * Christopher Hiller (https://github.com/boneskull)
+* * Gonzalo Diethelm (https://github.com/gonzus)
+* * Michal Kasperek (https://github.com/michalkas)
+* * Andrew Janke (https://github.com/apjanke)
+* * Steve Fan (https://github.com/stevefan1999)
+* * Edward Betts (https://github.com/edwardbetts)
+* * Ozhan Duz (https://github.com/webfolderio)
+* * Akos Kiss (https://github.com/akosthekiss)
+* * TheBrokenRail (https://github.com/TheBrokenRail)
+* * Jesse Doyle (https://github.com/jessedoyle)
+* * Gero Kuehn (https://github.com/dc6jgk)
+* * James Swift (https://github.com/phraemer)
+* * Luis de Bethencourt (https://github.com/luisbg)
+* * Ian Whyman (https://github.com/v00d00)
+* * Rick Sayre (https://github.com/whorfin)
+* * Craig Leres (https://github.com/leres)
+* * Maurici Abad (https://github.com/mauriciabad)
+* * Nancy Li (https://github.com/NancyLi1013)
+* * William Parks (https://github.com/WilliamParks)
+* * Sam Hellawell (https://github.com/samhellawell)
+* * Vladislavs Sokurenko (https://github.com/sokurenko)
*
* Other contributions
* ===================
@@ -127,6 +151,10 @@
* * https://github.com/chris-y
* * Laurent Zubiaur (https://github.com/lzubiaur)
* * Neil Kolban (https://github.com/nkolban)
+* * Wilhelm Wanecek (https://github.com/wanecek)
+* * Andrew Janke (https://github.com/apjanke)
+* * Unamer (https://github.com/unamer)
+* * Karl Dahlke (eklhad@gmail.com)
*
* If you are accidentally missing from this list, send me an e-mail
* (``sami.vaarala@iki.fi``) and I'll fix the omission.
@@ -169,13 +197,6 @@
#include "duktape.h"
/*
- * User declarations, e.g. prototypes for user functions used by Duktape
- * macros.
- */
-
-DUK_USE_USER_DECLARE()
-
-/*
* Duktape includes (other than duk_features.h)
*
* The header files expect to be included in an order which satisfies header
@@ -213,13 +234,14 @@ DUK_USE_USER_DECLARE()
*
* A B C D E F G H Big endian (e.g. 68k) DUK_USE_DOUBLE_BE
* H G F E D C B A Little endian (e.g. x86) DUK_USE_DOUBLE_LE
- * D C B A H G F E Mixed/cross endian (e.g. ARM) DUK_USE_DOUBLE_ME
+ * D C B A H G F E Mixed endian (e.g. ARM FPA) DUK_USE_DOUBLE_ME
*
- * ARM is a special case: ARM double values are in mixed/cross endian
- * format while ARM duk_uint64_t values are in standard little endian
+ * Legacy ARM (FPA) is a special case: ARM double values are in mixed
+ * endian format while ARM duk_uint64_t values are in standard little endian
* format (H G F E D C B A). When a double is read as a duk_uint64_t
* from memory, the register will contain the (logical) value
* E F G H A B C D. This requires some special handling below.
+ * See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0056d/Bcfhgcgd.html.
*
* Indexes of various types (8-bit, 16-bit, 32-bit) in memory relative to
* the logical (big endian) order:
@@ -252,7 +274,7 @@ union duk_double_union {
duk_uint16_t us[4];
duk_uint8_t uc[8];
#if defined(DUK_USE_PACKED_TVAL)
- void *vp[2]; /* used by packed duk_tval, assumes sizeof(void *) == 4 */
+ void *vp[2]; /* used by packed duk_tval, assumes sizeof(void *) == 4 */
#endif
};
@@ -264,64 +286,64 @@ typedef union duk_double_union duk_double_union;
#if defined(DUK_USE_DOUBLE_LE)
#if defined(DUK_USE_64BIT_OPS)
-#define DUK_DBL_IDX_ULL0 0
-#endif
-#define DUK_DBL_IDX_UI0 1
-#define DUK_DBL_IDX_UI1 0
-#define DUK_DBL_IDX_US0 3
-#define DUK_DBL_IDX_US1 2
-#define DUK_DBL_IDX_US2 1
-#define DUK_DBL_IDX_US3 0
-#define DUK_DBL_IDX_UC0 7
-#define DUK_DBL_IDX_UC1 6
-#define DUK_DBL_IDX_UC2 5
-#define DUK_DBL_IDX_UC3 4
-#define DUK_DBL_IDX_UC4 3
-#define DUK_DBL_IDX_UC5 2
-#define DUK_DBL_IDX_UC6 1
-#define DUK_DBL_IDX_UC7 0
-#define DUK_DBL_IDX_VP0 DUK_DBL_IDX_UI0 /* packed tval */
-#define DUK_DBL_IDX_VP1 DUK_DBL_IDX_UI1 /* packed tval */
+#define DUK_DBL_IDX_ULL0 0
+#endif
+#define DUK_DBL_IDX_UI0 1
+#define DUK_DBL_IDX_UI1 0
+#define DUK_DBL_IDX_US0 3
+#define DUK_DBL_IDX_US1 2
+#define DUK_DBL_IDX_US2 1
+#define DUK_DBL_IDX_US3 0
+#define DUK_DBL_IDX_UC0 7
+#define DUK_DBL_IDX_UC1 6
+#define DUK_DBL_IDX_UC2 5
+#define DUK_DBL_IDX_UC3 4
+#define DUK_DBL_IDX_UC4 3
+#define DUK_DBL_IDX_UC5 2
+#define DUK_DBL_IDX_UC6 1
+#define DUK_DBL_IDX_UC7 0
+#define DUK_DBL_IDX_VP0 DUK_DBL_IDX_UI0 /* packed tval */
+#define DUK_DBL_IDX_VP1 DUK_DBL_IDX_UI1 /* packed tval */
#elif defined(DUK_USE_DOUBLE_BE)
#if defined(DUK_USE_64BIT_OPS)
-#define DUK_DBL_IDX_ULL0 0
-#endif
-#define DUK_DBL_IDX_UI0 0
-#define DUK_DBL_IDX_UI1 1
-#define DUK_DBL_IDX_US0 0
-#define DUK_DBL_IDX_US1 1
-#define DUK_DBL_IDX_US2 2
-#define DUK_DBL_IDX_US3 3
-#define DUK_DBL_IDX_UC0 0
-#define DUK_DBL_IDX_UC1 1
-#define DUK_DBL_IDX_UC2 2
-#define DUK_DBL_IDX_UC3 3
-#define DUK_DBL_IDX_UC4 4
-#define DUK_DBL_IDX_UC5 5
-#define DUK_DBL_IDX_UC6 6
-#define DUK_DBL_IDX_UC7 7
-#define DUK_DBL_IDX_VP0 DUK_DBL_IDX_UI0 /* packed tval */
-#define DUK_DBL_IDX_VP1 DUK_DBL_IDX_UI1 /* packed tval */
+#define DUK_DBL_IDX_ULL0 0
+#endif
+#define DUK_DBL_IDX_UI0 0
+#define DUK_DBL_IDX_UI1 1
+#define DUK_DBL_IDX_US0 0
+#define DUK_DBL_IDX_US1 1
+#define DUK_DBL_IDX_US2 2
+#define DUK_DBL_IDX_US3 3
+#define DUK_DBL_IDX_UC0 0
+#define DUK_DBL_IDX_UC1 1
+#define DUK_DBL_IDX_UC2 2
+#define DUK_DBL_IDX_UC3 3
+#define DUK_DBL_IDX_UC4 4
+#define DUK_DBL_IDX_UC5 5
+#define DUK_DBL_IDX_UC6 6
+#define DUK_DBL_IDX_UC7 7
+#define DUK_DBL_IDX_VP0 DUK_DBL_IDX_UI0 /* packed tval */
+#define DUK_DBL_IDX_VP1 DUK_DBL_IDX_UI1 /* packed tval */
#elif defined(DUK_USE_DOUBLE_ME)
#if defined(DUK_USE_64BIT_OPS)
-#define DUK_DBL_IDX_ULL0 0 /* not directly applicable, byte order differs from a double */
-#endif
-#define DUK_DBL_IDX_UI0 0
-#define DUK_DBL_IDX_UI1 1
-#define DUK_DBL_IDX_US0 1
-#define DUK_DBL_IDX_US1 0
-#define DUK_DBL_IDX_US2 3
-#define DUK_DBL_IDX_US3 2
-#define DUK_DBL_IDX_UC0 3
-#define DUK_DBL_IDX_UC1 2
-#define DUK_DBL_IDX_UC2 1
-#define DUK_DBL_IDX_UC3 0
-#define DUK_DBL_IDX_UC4 7
-#define DUK_DBL_IDX_UC5 6
-#define DUK_DBL_IDX_UC6 5
-#define DUK_DBL_IDX_UC7 4
-#define DUK_DBL_IDX_VP0 DUK_DBL_IDX_UI0 /* packed tval */
-#define DUK_DBL_IDX_VP1 DUK_DBL_IDX_UI1 /* packed tval */
+#define DUK_DBL_IDX_ULL0 0 /* not directly applicable, byte order differs from a double */
+#endif
+#define DUK_DBL_IDX_UI0 0
+#define DUK_DBL_IDX_UI1 1
+#define DUK_DBL_IDX_US0 1
+#define DUK_DBL_IDX_US1 0
+#define DUK_DBL_IDX_US2 3
+#define DUK_DBL_IDX_US3 2
+#define DUK_DBL_IDX_UC0 3
+#define DUK_DBL_IDX_UC1 2
+#define DUK_DBL_IDX_UC2 1
+#define DUK_DBL_IDX_UC3 0
+#define DUK_DBL_IDX_UC4 7
+#define DUK_DBL_IDX_UC5 6
+#define DUK_DBL_IDX_UC6 5
+#define DUK_DBL_IDX_UC7 4
+#define DUK_DBL_IDX_VP0 DUK_DBL_IDX_UI0 /* packed tval */
+#define DUK_DBL_IDX_VP1 DUK_DBL_IDX_UI1 /* packed tval */
#else
#error internal error
#endif
@@ -331,57 +353,63 @@ typedef union duk_double_union duk_double_union;
* by duk_numconv.c and duk_tval.h.
*/
-#define DUK_DBLUNION_SET_DOUBLE(u,v) do { \
+#define DUK_DBLUNION_SET_DOUBLE(u, v) \
+ do { \
(u)->d = (v); \
} while (0)
-#define DUK_DBLUNION_SET_HIGH32(u,v) do { \
+#define DUK_DBLUNION_SET_HIGH32(u, v) \
+ do { \
(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) (v); \
} while (0)
#if defined(DUK_USE_64BIT_OPS)
#if defined(DUK_USE_DOUBLE_ME)
-#define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v) do { \
+#define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u, v) \
+ do { \
(u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \
} while (0)
#else
-#define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v) do { \
+#define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u, v) \
+ do { \
(u)->ull[DUK_DBL_IDX_ULL0] = ((duk_uint64_t) (v)) << 32; \
} while (0)
#endif
-#else /* DUK_USE_64BIT_OPS */
-#define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v) do { \
+#else /* DUK_USE_64BIT_OPS */
+#define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u, v) \
+ do { \
(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) (v); \
(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) 0; \
} while (0)
-#endif /* DUK_USE_64BIT_OPS */
+#endif /* DUK_USE_64BIT_OPS */
-#define DUK_DBLUNION_SET_LOW32(u,v) do { \
+#define DUK_DBLUNION_SET_LOW32(u, v) \
+ do { \
(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \
} while (0)
-#define DUK_DBLUNION_GET_DOUBLE(u) ((u)->d)
-#define DUK_DBLUNION_GET_HIGH32(u) ((u)->ui[DUK_DBL_IDX_UI0])
-#define DUK_DBLUNION_GET_LOW32(u) ((u)->ui[DUK_DBL_IDX_UI1])
+#define DUK_DBLUNION_GET_DOUBLE(u) ((u)->d)
+#define DUK_DBLUNION_GET_HIGH32(u) ((u)->ui[DUK_DBL_IDX_UI0])
+#define DUK_DBLUNION_GET_LOW32(u) ((u)->ui[DUK_DBL_IDX_UI1])
#if defined(DUK_USE_64BIT_OPS)
#if defined(DUK_USE_DOUBLE_ME)
-#define DUK_DBLUNION_SET_UINT64(u,v) do { \
+#define DUK_DBLUNION_SET_UINT64(u, v) \
+ do { \
(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) ((v) >> 32); \
(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \
} while (0)
-#define DUK_DBLUNION_GET_UINT64(u) \
- ((((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI0]) << 32) | \
- ((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI1]))
+#define DUK_DBLUNION_GET_UINT64(u) ((((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI0]) << 32) | ((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI1]))
#else
-#define DUK_DBLUNION_SET_UINT64(u,v) do { \
+#define DUK_DBLUNION_SET_UINT64(u, v) \
+ do { \
(u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \
} while (0)
-#define DUK_DBLUNION_GET_UINT64(u) ((u)->ull[DUK_DBL_IDX_ULL0])
+#define DUK_DBLUNION_GET_UINT64(u) ((u)->ull[DUK_DBL_IDX_ULL0])
#endif
-#define DUK_DBLUNION_SET_INT64(u,v) DUK_DBLUNION_SET_UINT64((u), (duk_uint64_t) (v))
-#define DUK_DBLUNION_GET_INT64(u) ((duk_int64_t) DUK_DBLUNION_GET_UINT64((u)))
-#endif /* DUK_USE_64BIT_OPS */
+#define DUK_DBLUNION_SET_INT64(u, v) DUK_DBLUNION_SET_UINT64((u), (duk_uint64_t) (v))
+#define DUK_DBLUNION_GET_INT64(u) ((duk_int64_t) DUK_DBLUNION_GET_UINT64((u)))
+#endif /* DUK_USE_64BIT_OPS */
/*
* Double NaN manipulation macros related to NaN normalization needed when
@@ -412,103 +440,87 @@ typedef union duk_double_union duk_double_union;
#if defined(DUK_USE_64BIT_OPS)
#if defined(DUK_USE_DOUBLE_ME)
/* Macros for 64-bit ops + mixed endian doubles. */
-#define DUK__DBLUNION_SET_NAN_FULL(u) do { \
+#define DUK__DBLUNION_SET_NAN_FULL(u) \
+ do { \
(u)->ull[DUK_DBL_IDX_ULL0] = DUK_U64_CONSTANT(0x000000007ff80000); \
} while (0)
#define DUK__DBLUNION_IS_NAN_FULL(u) \
((((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000)) && \
((((u)->ull[DUK_DBL_IDX_ULL0]) & DUK_U64_CONSTANT(0xffffffff000fffff)) != 0))
-#define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
- ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff80000))
+#define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff80000))
#define DUK__DBLUNION_IS_ANYINF(u) \
(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0xffffffff7fffffff)) == DUK_U64_CONSTANT(0x000000007ff00000))
-#define DUK__DBLUNION_IS_POSINF(u) \
- ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff00000))
-#define DUK__DBLUNION_IS_NEGINF(u) \
- ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x00000000fff00000))
+#define DUK__DBLUNION_IS_POSINF(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff00000))
+#define DUK__DBLUNION_IS_NEGINF(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x00000000fff00000))
#define DUK__DBLUNION_IS_ANYZERO(u) \
(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0xffffffff7fffffff)) == DUK_U64_CONSTANT(0x0000000000000000))
-#define DUK__DBLUNION_IS_POSZERO(u) \
- ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000))
-#define DUK__DBLUNION_IS_NEGZERO(u) \
- ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000080000000))
+#define DUK__DBLUNION_IS_POSZERO(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000))
+#define DUK__DBLUNION_IS_NEGZERO(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000080000000))
#else
/* Macros for 64-bit ops + big/little endian doubles. */
-#define DUK__DBLUNION_SET_NAN_FULL(u) do { \
+#define DUK__DBLUNION_SET_NAN_FULL(u) \
+ do { \
(u)->ull[DUK_DBL_IDX_ULL0] = DUK_U64_CONSTANT(0x7ff8000000000000); \
} while (0)
#define DUK__DBLUNION_IS_NAN_FULL(u) \
((((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000)) && \
((((u)->ull[DUK_DBL_IDX_ULL0]) & DUK_U64_CONSTANT(0x000fffffffffffff)) != 0))
-#define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
- ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff8000000000000))
+#define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff8000000000000))
#define DUK__DBLUNION_IS_ANYINF(u) \
(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7fffffffffffffff)) == DUK_U64_CONSTANT(0x7ff0000000000000))
-#define DUK__DBLUNION_IS_POSINF(u) \
- ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff0000000000000))
-#define DUK__DBLUNION_IS_NEGINF(u) \
- ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0xfff0000000000000))
+#define DUK__DBLUNION_IS_POSINF(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff0000000000000))
+#define DUK__DBLUNION_IS_NEGINF(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0xfff0000000000000))
#define DUK__DBLUNION_IS_ANYZERO(u) \
(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7fffffffffffffff)) == DUK_U64_CONSTANT(0x0000000000000000))
-#define DUK__DBLUNION_IS_POSZERO(u) \
- ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000))
-#define DUK__DBLUNION_IS_NEGZERO(u) \
- ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x8000000000000000))
+#define DUK__DBLUNION_IS_POSZERO(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000))
+#define DUK__DBLUNION_IS_NEGZERO(u) ((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x8000000000000000))
#endif
-#else /* DUK_USE_64BIT_OPS */
+#else /* DUK_USE_64BIT_OPS */
/* Macros for no 64-bit ops, any endianness. */
-#define DUK__DBLUNION_SET_NAN_FULL(u) do { \
+#define DUK__DBLUNION_SET_NAN_FULL(u) \
+ do { \
(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) 0x7ff80000UL; \
(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) 0x00000000UL; \
} while (0)
#define DUK__DBLUNION_IS_NAN_FULL(u) \
((((u)->ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL) && \
- (((u)->ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) != 0 || \
- (u)->ui[DUK_DBL_IDX_UI1] != 0))
+ (((u)->ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) != 0 || (u)->ui[DUK_DBL_IDX_UI1] != 0))
#define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
- (((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff80000UL) && \
- ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
+ (((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff80000UL) && ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
#define DUK__DBLUNION_IS_ANYINF(u) \
- ((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x7ff00000UL) && \
- ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
-#define DUK__DBLUNION_IS_POSINF(u) \
- (((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff00000UL) && \
- ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
-#define DUK__DBLUNION_IS_NEGINF(u) \
- (((u)->ui[DUK_DBL_IDX_UI0] == 0xfff00000UL) && \
- ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
+ ((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x7ff00000UL) && ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
+#define DUK__DBLUNION_IS_POSINF(u) (((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff00000UL) && ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
+#define DUK__DBLUNION_IS_NEGINF(u) (((u)->ui[DUK_DBL_IDX_UI0] == 0xfff00000UL) && ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
#define DUK__DBLUNION_IS_ANYZERO(u) \
- ((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x00000000UL) && \
- ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
-#define DUK__DBLUNION_IS_POSZERO(u) \
- (((u)->ui[DUK_DBL_IDX_UI0] == 0x00000000UL) && \
- ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
-#define DUK__DBLUNION_IS_NEGZERO(u) \
- (((u)->ui[DUK_DBL_IDX_UI0] == 0x80000000UL) && \
- ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
-#endif /* DUK_USE_64BIT_OPS */
-
-#define DUK__DBLUNION_SET_NAN_NOTFULL(u) do { \
+ ((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x00000000UL) && ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
+#define DUK__DBLUNION_IS_POSZERO(u) (((u)->ui[DUK_DBL_IDX_UI0] == 0x00000000UL) && ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
+#define DUK__DBLUNION_IS_NEGZERO(u) (((u)->ui[DUK_DBL_IDX_UI0] == 0x80000000UL) && ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
+#endif /* DUK_USE_64BIT_OPS */
+
+#define DUK__DBLUNION_SET_NAN_NOTFULL(u) \
+ do { \
(u)->us[DUK_DBL_IDX_US0] = 0x7ff8UL; \
} while (0)
#define DUK__DBLUNION_IS_NAN_NOTFULL(u) \
/* E == 0x7ff, topmost four bits of F != 0 => assume NaN */ \
- ((((u)->us[DUK_DBL_IDX_US0] & 0x7ff0UL) == 0x7ff0UL) && \
- (((u)->us[DUK_DBL_IDX_US0] & 0x000fUL) != 0x0000UL))
+ ((((u)->us[DUK_DBL_IDX_US0] & 0x7ff0UL) == 0x7ff0UL) && (((u)->us[DUK_DBL_IDX_US0] & 0x000fUL) != 0x0000UL))
#define DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL(u) \
/* E == 0x7ff, F == 8 => normalized NaN */ \
((u)->us[DUK_DBL_IDX_US0] == 0x7ff8UL)
-#define DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL(u) do { \
+#define DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL(u) \
+ do { \
if (DUK__DBLUNION_IS_NAN_FULL((u))) { \
DUK__DBLUNION_SET_NAN_FULL((u)); \
} \
} while (0)
-#define DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL(u) do { \
- if (DUK__DBLUNION_IS_NAN_NOTFULL((u))) { \
+#define DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL(u) \
+ do { \
+ /* Check must be full. */ \
+ if (DUK__DBLUNION_IS_NAN_FULL((u))) { \
DUK__DBLUNION_SET_NAN_NOTFULL((u)); \
} \
} while (0)
@@ -520,30 +532,30 @@ typedef union duk_double_union duk_double_union;
*/
#if defined(DUK_USE_PACKED_TVAL)
-#if defined(DUK_USE_FULL_TVAL)
-#define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u) DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL((u))
-#define DUK_DBLUNION_IS_NAN(u) DUK__DBLUNION_IS_NAN_FULL((u))
-#define DUK_DBLUNION_IS_NORMALIZED_NAN(u) DUK__DBLUNION_IS_NORMALIZED_NAN_FULL((u))
-#define DUK_DBLUNION_SET_NAN(d) DUK__DBLUNION_SET_NAN_FULL((d))
-#else
-#define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u) DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL((u))
-#define DUK_DBLUNION_IS_NAN(u) DUK__DBLUNION_IS_NAN_NOTFULL((u))
-#define DUK_DBLUNION_IS_NORMALIZED_NAN(u) DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL((u))
-#define DUK_DBLUNION_SET_NAN(d) DUK__DBLUNION_SET_NAN_NOTFULL((d))
+#define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u) DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL((u))
+#define DUK_DBLUNION_IS_NAN(u) DUK__DBLUNION_IS_NAN_FULL((u))
+#define DUK_DBLUNION_IS_NORMALIZED_NAN(u) DUK__DBLUNION_IS_NORMALIZED_NAN_FULL((u))
+#define DUK_DBLUNION_SET_NAN(d) DUK__DBLUNION_SET_NAN_FULL((d))
+#if 0
+#define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u) DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL((u))
+#define DUK_DBLUNION_IS_NAN(u) DUK__DBLUNION_IS_NAN_NOTFULL((u))
+#define DUK_DBLUNION_IS_NORMALIZED_NAN(u) DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL((u))
+#define DUK_DBLUNION_SET_NAN(d) DUK__DBLUNION_SET_NAN_NOTFULL((d))
#endif
#define DUK_DBLUNION_IS_NORMALIZED(u) \
- (!DUK_DBLUNION_IS_NAN((u)) || /* either not a NaN */ \
- DUK_DBLUNION_IS_NORMALIZED_NAN((u))) /* or is a normalized NaN */
-#else /* DUK_USE_PACKED_TVAL */
-#define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u) /* nop: no need to normalize */
-#define DUK_DBLUNION_IS_NAN(u) DUK__DBLUNION_IS_NAN_FULL((u)) /* (DUK_ISNAN((u)->d)) */
-#define DUK_DBLUNION_IS_NORMALIZED_NAN(u) DUK__DBLUNION_IS_NAN_FULL((u)) /* (DUK_ISNAN((u)->d)) */
-#define DUK_DBLUNION_IS_NORMALIZED(u) 1 /* all doubles are considered normalized */
-#define DUK_DBLUNION_SET_NAN(u) do { \
+ (!DUK_DBLUNION_IS_NAN((u)) || /* either not a NaN */ \
+ DUK_DBLUNION_IS_NORMALIZED_NAN((u))) /* or is a normalized NaN */
+#else /* DUK_USE_PACKED_TVAL */
+#define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u) /* nop: no need to normalize */
+#define DUK_DBLUNION_IS_NAN(u) DUK__DBLUNION_IS_NAN_FULL((u)) /* (DUK_ISNAN((u)->d)) */
+#define DUK_DBLUNION_IS_NORMALIZED_NAN(u) DUK__DBLUNION_IS_NAN_FULL((u)) /* (DUK_ISNAN((u)->d)) */
+#define DUK_DBLUNION_IS_NORMALIZED(u) 1 /* all doubles are considered normalized */
+#define DUK_DBLUNION_SET_NAN(u) \
+ do { \
/* in non-packed representation we don't care about which NaN is used */ \
(u)->d = DUK_DOUBLE_NAN; \
} while (0)
-#endif /* DUK_USE_PACKED_TVAL */
+#endif /* DUK_USE_PACKED_TVAL */
#define DUK_DBLUNION_IS_ANYINF(u) DUK__DBLUNION_IS_ANYINF((u))
#define DUK_DBLUNION_IS_POSINF(u) DUK__DBLUNION_IS_POSINF((u))
@@ -556,7 +568,8 @@ typedef union duk_double_union duk_double_union;
/* XXX: native 64-bit byteswaps when available */
/* 64-bit byteswap, same operation independent of target endianness. */
-#define DUK_DBLUNION_BSWAP64(u) do { \
+#define DUK_DBLUNION_BSWAP64(u) \
+ do { \
duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
duk__bswaptmp1 = (u)->ui[0]; \
duk__bswaptmp2 = (u)->ui[1]; \
@@ -570,7 +583,8 @@ typedef union duk_double_union duk_double_union;
* order. For a big endian target this is a no-op.
*/
#if defined(DUK_USE_DOUBLE_LE)
-#define DUK_DBLUNION_DOUBLE_HTON(u) do { \
+#define DUK_DBLUNION_DOUBLE_HTON(u) \
+ do { \
duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
duk__bswaptmp1 = (u)->ui[0]; \
duk__bswaptmp2 = (u)->ui[1]; \
@@ -580,7 +594,8 @@ typedef union duk_double_union duk_double_union;
(u)->ui[1] = duk__bswaptmp1; \
} while (0)
#elif defined(DUK_USE_DOUBLE_ME)
-#define DUK_DBLUNION_DOUBLE_HTON(u) do { \
+#define DUK_DBLUNION_DOUBLE_HTON(u) \
+ do { \
duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
duk__bswaptmp1 = (u)->ui[0]; \
duk__bswaptmp2 = (u)->ui[1]; \
@@ -590,7 +605,9 @@ typedef union duk_double_union duk_double_union;
(u)->ui[1] = duk__bswaptmp2; \
} while (0)
#elif defined(DUK_USE_DOUBLE_BE)
-#define DUK_DBLUNION_DOUBLE_HTON(u) do { } while (0)
+#define DUK_DBLUNION_DOUBLE_HTON(u) \
+ do { \
+ } while (0)
#else
#error internal error, double endianness insane
#endif
@@ -607,7 +624,47 @@ typedef union duk_double_union duk_double_union;
#define DUK_DBLUNION_GET_SIGNBIT(u) (((u)->ui[DUK_DBL_IDX_UI0] >> 31U))
#endif
-#endif /* DUK_DBLUNION_H_INCLUDED */
+#endif /* DUK_DBLUNION_H_INCLUDED */
+/* #include duk_fltunion.h */
+/*
+ * Union to access IEEE float memory representation.
+ */
+
+#if !defined(DUK_FLTUNION_H_INCLUDED)
+#define DUK_FLTUNION_H_INCLUDED
+
+/* #include duk_internal.h -> already included */
+
+union duk_float_union {
+ float f;
+ duk_uint32_t ui[1];
+ duk_uint16_t us[2];
+ duk_uint8_t uc[4];
+};
+
+typedef union duk_float_union duk_float_union;
+
+#if defined(DUK_USE_DOUBLE_LE) || defined(DUK_USE_DOUBLE_ME)
+#define DUK_FLT_IDX_UI0 0
+#define DUK_FLT_IDX_US0 1
+#define DUK_FLT_IDX_US1 0
+#define DUK_FLT_IDX_UC0 3
+#define DUK_FLT_IDX_UC1 2
+#define DUK_FLT_IDX_UC2 1
+#define DUK_FLT_IDX_UC3 0
+#elif defined(DUK_USE_DOUBLE_BE)
+#define DUK_FLT_IDX_UI0 0
+#define DUK_FLT_IDX_US0 0
+#define DUK_FLT_IDX_US1 1
+#define DUK_FLT_IDX_UC0 0
+#define DUK_FLT_IDX_UC1 1
+#define DUK_FLT_IDX_UC2 2
+#define DUK_FLT_IDX_UC3 3
+#else
+#error internal error
+#endif
+
+#endif /* DUK_FLTUNION_H_INCLUDED */
/* #include duk_replacements.h */
#if !defined(DUK_REPLACEMENTS_H_INCLUDED)
#define DUK_REPLACEMENTS_H_INCLUDED
@@ -619,7 +676,7 @@ DUK_INTERNAL_DECL double duk_computed_infinity;
#if defined(DUK_USE_COMPUTED_NAN)
DUK_INTERNAL_DECL double duk_computed_nan;
#endif
-#endif /* !DUK_SINGLE_FILE */
+#endif /* !DUK_SINGLE_FILE */
#if defined(DUK_USE_REPL_FPCLASSIFY)
DUK_INTERNAL_DECL int duk_repl_fpclassify(double x);
@@ -637,7 +694,7 @@ DUK_INTERNAL_DECL int duk_repl_isnan(double x);
DUK_INTERNAL_DECL int duk_repl_isinf(double x);
#endif
-#endif /* DUK_REPLACEMENTS_H_INCLUDED */
+#endif /* DUK_REPLACEMENTS_H_INCLUDED */
/* #include duk_jmpbuf.h */
/*
* Wrapper for jmp_buf.
@@ -654,7 +711,7 @@ DUK_INTERNAL_DECL int duk_repl_isinf(double x);
#if defined(DUK_USE_CPP_EXCEPTIONS)
struct duk_jmpbuf {
- duk_small_int_t dummy; /* unused */
+ duk_small_int_t dummy; /* unused */
};
#else
struct duk_jmpbuf {
@@ -662,26 +719,39 @@ struct duk_jmpbuf {
};
#endif
-#endif /* DUK_JMPBUF_H_INCLUDED */
+#endif /* DUK_JMPBUF_H_INCLUDED */
/* #include duk_exception.h */
/*
- * Exception for Duktape internal throws when C++ exceptions are used
+ * Exceptions for Duktape internal throws when C++ exceptions are used
* for long control transfers.
- *
- * Doesn't inherit from any exception base class to minimize the chance
- * that user code would accidentally catch this exception.
*/
#if !defined(DUK_EXCEPTION_H_INCLUDED)
#define DUK_EXCEPTION_H_INCLUDED
#if defined(DUK_USE_CPP_EXCEPTIONS)
+/* Internal exception used as a setjmp-longjmp replacement. User code should
+ * NEVER see or catch this exception, so it doesn't inherit from any base
+ * class which should minimize the chance of user code accidentally catching
+ * the exception.
+ */
class duk_internal_exception {
/* intentionally empty */
};
+
+/* Fatal error, thrown as a specific C++ exception with C++ exceptions
+ * enabled. It is unsafe to continue; doing so may cause crashes or memory
+ * leaks. This is intended to be either uncaught, or caught by user code
+ * aware of the "unsafe to continue" semantics.
+ */
+class duk_fatal_exception : public virtual std::runtime_error {
+ public:
+ duk_fatal_exception(const char *message) : std::runtime_error(message) {
+ }
+};
#endif
-#endif /* DUK_EXCEPTION_H_INCLUDED */
+#endif /* DUK_EXCEPTION_H_INCLUDED */
/* #include duk_forwdecl.h */
/*
* Forward declarations for all Duktape structures.
@@ -729,8 +799,9 @@ struct duk_breakpoint;
struct duk_activation;
struct duk_catcher;
-struct duk_strcache;
struct duk_ljstate;
+struct duk_strcache_entry;
+struct duk_litcache_entry;
struct duk_strtab_entry;
#if defined(DUK_USE_DEBUG)
@@ -789,8 +860,9 @@ typedef struct duk_breakpoint duk_breakpoint;
typedef struct duk_activation duk_activation;
typedef struct duk_catcher duk_catcher;
-typedef struct duk_strcache duk_strcache;
typedef struct duk_ljstate duk_ljstate;
+typedef struct duk_strcache_entry duk_strcache_entry;
+typedef struct duk_litcache_entry duk_litcache_entry;
typedef struct duk_strtab_entry duk_strtab_entry;
#if defined(DUK_USE_DEBUG)
@@ -814,7 +886,7 @@ typedef struct duk_compiler_ctx duk_compiler_ctx;
typedef struct duk_re_matcher_ctx duk_re_matcher_ctx;
typedef struct duk_re_compiler_ctx duk_re_compiler_ctx;
-#endif /* DUK_FORWDECL_H_INCLUDED */
+#endif /* DUK_FORWDECL_H_INCLUDED */
/* #include duk_tval.h */
/*
* Tagged type definition (duk_tval) and accessor macros.
@@ -859,30 +931,29 @@ typedef struct {
} duk_tval_unused;
/* tags */
-#define DUK_TAG_NORMALIZED_NAN 0x7ff8UL /* the NaN variant we use */
+#define DUK_TAG_NORMALIZED_NAN 0x7ff8UL /* the NaN variant we use */
/* avoid tag 0xfff0, no risk of confusion with negative infinity */
-#define DUK_TAG_MIN 0xfff1UL
+#define DUK_TAG_MIN 0xfff1UL
#if defined(DUK_USE_FASTINT)
-#define DUK_TAG_FASTINT 0xfff1UL /* embed: integer value */
+#define DUK_TAG_FASTINT 0xfff1UL /* embed: integer value */
#endif
-#define DUK_TAG_UNUSED 0xfff2UL /* marker; not actual tagged value */
-#define DUK_TAG_UNDEFINED 0xfff3UL /* embed: nothing */
-#define DUK_TAG_NULL 0xfff4UL /* embed: nothing */
-#define DUK_TAG_BOOLEAN 0xfff5UL /* embed: 0 or 1 (false or true) */
+#define DUK_TAG_UNUSED 0xfff2UL /* marker; not actual tagged value */
+#define DUK_TAG_UNDEFINED 0xfff3UL /* embed: nothing */
+#define DUK_TAG_NULL 0xfff4UL /* embed: nothing */
+#define DUK_TAG_BOOLEAN 0xfff5UL /* embed: 0 or 1 (false or true) */
/* DUK_TAG_NUMBER would logically go here, but it has multiple 'tags' */
-#define DUK_TAG_POINTER 0xfff6UL /* embed: void ptr */
-#define DUK_TAG_LIGHTFUNC 0xfff7UL /* embed: func ptr */
-#define DUK_TAG_STRING 0xfff8UL /* embed: duk_hstring ptr */
-#define DUK_TAG_OBJECT 0xfff9UL /* embed: duk_hobject ptr */
-#define DUK_TAG_BUFFER 0xfffaUL /* embed: duk_hbuffer ptr */
-#define DUK_TAG_MAX 0xfffaUL
+#define DUK_TAG_POINTER 0xfff6UL /* embed: void ptr */
+#define DUK_TAG_LIGHTFUNC 0xfff7UL /* embed: func ptr */
+#define DUK_TAG_STRING 0xfff8UL /* embed: duk_hstring ptr */
+#define DUK_TAG_OBJECT 0xfff9UL /* embed: duk_hobject ptr */
+#define DUK_TAG_BUFFER 0xfffaUL /* embed: duk_hbuffer ptr */
+#define DUK_TAG_MAX 0xfffaUL
/* for convenience */
-#define DUK_XTAG_BOOLEAN_FALSE 0xfff50000UL
-#define DUK_XTAG_BOOLEAN_TRUE 0xfff50001UL
+#define DUK_XTAG_BOOLEAN_FALSE 0xfff50000UL
+#define DUK_XTAG_BOOLEAN_TRUE 0xfff50001UL
-#define DUK_TVAL_IS_VALID_TAG(tv) \
- (DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)
+#define DUK_TVAL_IS_VALID_TAG(tv) (DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)
/* DUK_TVAL_UNUSED initializer for duk_tval_unused, works for any endianness. */
#define DUK_TVAL_UNUSED_INITIALIZER() \
@@ -891,116 +962,136 @@ typedef struct {
/* two casts to avoid gcc warning: "warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]" */
#if defined(DUK_USE_64BIT_OPS)
#if defined(DUK_USE_DOUBLE_ME)
-#define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag) do { \
+#define DUK__TVAL_SET_TAGGEDPOINTER(tv, h, tag) \
+ do { \
(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 16) | (((duk_uint64_t) (duk_uint32_t) (h)) << 32); \
} while (0)
#else
-#define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag) do { \
+#define DUK__TVAL_SET_TAGGEDPOINTER(tv, h, tag) \
+ do { \
(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 48) | ((duk_uint64_t) (duk_uint32_t) (h)); \
} while (0)
#endif
-#else /* DUK_USE_64BIT_OPS */
-#define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag) do { \
+#else /* DUK_USE_64BIT_OPS */
+#define DUK__TVAL_SET_TAGGEDPOINTER(tv, h, tag) \
+ do { \
duk_tval *duk__tv; \
duk__tv = (tv); \
duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) (tag)) << 16; \
duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (h); \
} while (0)
-#endif /* DUK_USE_64BIT_OPS */
+#endif /* DUK_USE_64BIT_OPS */
#if defined(DUK_USE_64BIT_OPS)
/* Double casting for pointer to avoid gcc warning (cast from pointer to integer of different size) */
#if defined(DUK_USE_DOUBLE_ME)
-#define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags) do { \
- (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 16) | \
- ((duk_uint64_t) (flags)) | \
+#define DUK__TVAL_SET_LIGHTFUNC(tv, fp, flags) \
+ do { \
+ (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint64_t) (flags)) | \
(((duk_uint64_t) (duk_uint32_t) (fp)) << 32); \
} while (0)
#else
-#define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags) do { \
- (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 48) | \
- (((duk_uint64_t) (flags)) << 32) | \
+#define DUK__TVAL_SET_LIGHTFUNC(tv, fp, flags) \
+ do { \
+ (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 48) | (((duk_uint64_t) (flags)) << 32) | \
((duk_uint64_t) (duk_uint32_t) (fp)); \
} while (0)
#endif
-#else /* DUK_USE_64BIT_OPS */
-#define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags) do { \
+#else /* DUK_USE_64BIT_OPS */
+#define DUK__TVAL_SET_LIGHTFUNC(tv, fp, flags) \
+ do { \
duk_tval *duk__tv; \
duk__tv = (tv); \
duk__tv->ui[DUK_DBL_IDX_UI0] = (((duk_uint32_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint32_t) (flags)); \
duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (fp); \
} while (0)
-#endif /* DUK_USE_64BIT_OPS */
+#endif /* DUK_USE_64BIT_OPS */
#if defined(DUK_USE_FASTINT)
/* Note: masking is done for 'i' to deal with negative numbers correctly */
#if defined(DUK_USE_DOUBLE_ME)
-#define DUK__TVAL_SET_I48(tv,i) do { \
+#define DUK__TVAL_SET_I48(tv, i) \
+ do { \
duk_tval *duk__tv; \
duk__tv = (tv); \
- duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16 | (((duk_uint32_t) ((i) >> 32)) & 0x0000ffffUL); \
+ duk__tv->ui[DUK_DBL_IDX_UI0] = \
+ ((duk_uint32_t) DUK_TAG_FASTINT) << 16 | (((duk_uint32_t) ((i) >> 32)) & 0x0000ffffUL); \
duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
} while (0)
-#define DUK__TVAL_SET_U32(tv,i) do { \
+#define DUK__TVAL_SET_U32(tv, i) \
+ do { \
duk_tval *duk__tv; \
duk__tv = (tv); \
duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16; \
duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
} while (0)
#else
-#define DUK__TVAL_SET_I48(tv,i) do { \
- (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (((duk_uint64_t) (i)) & DUK_U64_CONSTANT(0x0000ffffffffffff)); \
+#define DUK__TVAL_SET_I48(tv, i) \
+ do { \
+ (tv)->ull[DUK_DBL_IDX_ULL0] = \
+ (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (((duk_uint64_t) (i)) & DUK_U64_CONSTANT(0x0000ffffffffffff)); \
} while (0)
-#define DUK__TVAL_SET_U32(tv,i) do { \
+#define DUK__TVAL_SET_U32(tv, i) \
+ do { \
(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (duk_uint64_t) (i); \
} while (0)
#endif
/* This needs to go through a cast because sign extension is needed. */
-#define DUK__TVAL_SET_I32(tv,i) do { \
+#define DUK__TVAL_SET_I32(tv, i) \
+ do { \
duk_int64_t duk__tmp = (duk_int64_t) (i); \
DUK_TVAL_SET_I48((tv), duk__tmp); \
} while (0)
/* XXX: Clumsy sign extend and masking of 16 topmost bits. */
#if defined(DUK_USE_DOUBLE_ME)
-#define DUK__TVAL_GET_FASTINT(tv) (((duk_int64_t) ((((duk_uint64_t) (tv)->ui[DUK_DBL_IDX_UI0]) << 32) | ((duk_uint64_t) (tv)->ui[DUK_DBL_IDX_UI1]))) << 16 >> 16)
+#define DUK__TVAL_GET_FASTINT(tv) \
+ (((duk_int64_t) ((((duk_uint64_t) (tv)->ui[DUK_DBL_IDX_UI0]) << 32) | ((duk_uint64_t) (tv)->ui[DUK_DBL_IDX_UI1]))) \
+ << 16 >> \
+ 16)
#else
-#define DUK__TVAL_GET_FASTINT(tv) ((((duk_int64_t) (tv)->ull[DUK_DBL_IDX_ULL0]) << 16) >> 16)
+#define DUK__TVAL_GET_FASTINT(tv) ((((duk_int64_t) (tv)->ull[DUK_DBL_IDX_ULL0]) << 16) >> 16)
#endif
-#define DUK__TVAL_GET_FASTINT_U32(tv) ((tv)->ui[DUK_DBL_IDX_UI1])
-#define DUK__TVAL_GET_FASTINT_I32(tv) ((duk_int32_t) (tv)->ui[DUK_DBL_IDX_UI1])
-#endif /* DUK_USE_FASTINT */
+#define DUK__TVAL_GET_FASTINT_U32(tv) ((tv)->ui[DUK_DBL_IDX_UI1])
+#define DUK__TVAL_GET_FASTINT_I32(tv) ((duk_int32_t) (tv)->ui[DUK_DBL_IDX_UI1])
+#endif /* DUK_USE_FASTINT */
-#define DUK_TVAL_SET_UNDEFINED(tv) do { \
+#define DUK_TVAL_SET_UNDEFINED(tv) \
+ do { \
(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNDEFINED; \
} while (0)
-#define DUK_TVAL_SET_UNUSED(tv) do { \
+#define DUK_TVAL_SET_UNUSED(tv) \
+ do { \
(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNUSED; \
} while (0)
-#define DUK_TVAL_SET_NULL(tv) do { \
+#define DUK_TVAL_SET_NULL(tv) \
+ do { \
(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_NULL; \
} while (0)
-#define DUK_TVAL_SET_BOOLEAN(tv,val) DUK_DBLUNION_SET_HIGH32((tv), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val)))
+#define DUK_TVAL_SET_BOOLEAN(tv, val) \
+ DUK_DBLUNION_SET_HIGH32((tv), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val)))
-#define DUK_TVAL_SET_NAN(tv) DUK_DBLUNION_SET_NAN_FULL((tv))
+#define DUK_TVAL_SET_NAN(tv) DUK_DBLUNION_SET_NAN_FULL((tv))
/* Assumes that caller has normalized NaNs, otherwise trouble ahead. */
#if defined(DUK_USE_FASTINT)
-#define DUK_TVAL_SET_DOUBLE(tv,d) do { \
+#define DUK_TVAL_SET_DOUBLE(tv, d) \
+ do { \
duk_double_t duk__dblval; \
duk__dblval = (d); \
DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \
} while (0)
-#define DUK_TVAL_SET_I48(tv,i) DUK__TVAL_SET_I48((tv), (i))
-#define DUK_TVAL_SET_I32(tv,i) DUK__TVAL_SET_I32((tv), (i))
-#define DUK_TVAL_SET_U32(tv,i) DUK__TVAL_SET_U32((tv), (i))
-#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) duk_tval_set_number_chkfast_fast((tv), (d))
-#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) duk_tval_set_number_chkfast_slow((tv), (d))
-#define DUK_TVAL_SET_NUMBER(tv,d) DUK_TVAL_SET_DOUBLE((tv), (d))
-#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) do { \
+#define DUK_TVAL_SET_I48(tv, i) DUK__TVAL_SET_I48((tv), (i))
+#define DUK_TVAL_SET_I32(tv, i) DUK__TVAL_SET_I32((tv), (i))
+#define DUK_TVAL_SET_U32(tv, i) DUK__TVAL_SET_U32((tv), (i))
+#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv, d) duk_tval_set_number_chkfast_fast((tv), (d))
+#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, d) duk_tval_set_number_chkfast_slow((tv), (d))
+#define DUK_TVAL_SET_NUMBER(tv, d) DUK_TVAL_SET_DOUBLE((tv), (d))
+#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) \
+ do { \
duk_tval *duk__tv; \
duk_double_t duk__d; \
duk__tv = (tv); \
@@ -1009,7 +1100,8 @@ typedef struct {
DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
} \
} while (0)
-#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) do { \
+#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) \
+ do { \
duk_tval *duk__tv; \
duk_double_t duk__d; \
duk__tv = (tv); \
@@ -1018,89 +1110,98 @@ typedef struct {
DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
} \
} while (0)
-#else /* DUK_USE_FASTINT */
-#define DUK_TVAL_SET_DOUBLE(tv,d) do { \
+#else /* DUK_USE_FASTINT */
+#define DUK_TVAL_SET_DOUBLE(tv, d) \
+ do { \
duk_double_t duk__dblval; \
duk__dblval = (d); \
DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \
} while (0)
-#define DUK_TVAL_SET_I48(tv,i) DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i)) /* XXX: fast int-to-double */
-#define DUK_TVAL_SET_I32(tv,i) DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
-#define DUK_TVAL_SET_U32(tv,i) DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
-#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) DUK_TVAL_SET_DOUBLE((tv), (d))
-#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) DUK_TVAL_SET_DOUBLE((tv), (d))
-#define DUK_TVAL_SET_NUMBER(tv,d) DUK_TVAL_SET_DOUBLE((tv), (d))
-#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) do { } while (0)
-#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) do { } while (0)
-#endif /* DUK_USE_FASTINT */
-
-#define DUK_TVAL_SET_FASTINT(tv,i) DUK_TVAL_SET_I48((tv), (i)) /* alias */
-
-#define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags) DUK__TVAL_SET_LIGHTFUNC((tv), (fp), (flags))
-#define DUK_TVAL_SET_STRING(tv,h) DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_STRING)
-#define DUK_TVAL_SET_OBJECT(tv,h) DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_OBJECT)
-#define DUK_TVAL_SET_BUFFER(tv,h) DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_BUFFER)
-#define DUK_TVAL_SET_POINTER(tv,p) DUK__TVAL_SET_TAGGEDPOINTER((tv), (p), DUK_TAG_POINTER)
-
-#define DUK_TVAL_SET_TVAL(tv,x) do { *(tv) = *(x); } while (0)
+#define DUK_TVAL_SET_I48(tv, i) DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i)) /* XXX: fast int-to-double */
+#define DUK_TVAL_SET_I32(tv, i) DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
+#define DUK_TVAL_SET_U32(tv, i) DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
+#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv, d) DUK_TVAL_SET_DOUBLE((tv), (d))
+#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, d) DUK_TVAL_SET_DOUBLE((tv), (d))
+#define DUK_TVAL_SET_NUMBER(tv, d) DUK_TVAL_SET_DOUBLE((tv), (d))
+#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) \
+ do { \
+ } while (0)
+#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) \
+ do { \
+ } while (0)
+#endif /* DUK_USE_FASTINT */
+
+#define DUK_TVAL_SET_FASTINT(tv, i) DUK_TVAL_SET_I48((tv), (i)) /* alias */
+
+#define DUK_TVAL_SET_LIGHTFUNC(tv, fp, flags) DUK__TVAL_SET_LIGHTFUNC((tv), (fp), (flags))
+#define DUK_TVAL_SET_STRING(tv, h) DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_STRING)
+#define DUK_TVAL_SET_OBJECT(tv, h) DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_OBJECT)
+#define DUK_TVAL_SET_BUFFER(tv, h) DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_BUFFER)
+#define DUK_TVAL_SET_POINTER(tv, p) DUK__TVAL_SET_TAGGEDPOINTER((tv), (p), DUK_TAG_POINTER)
+
+#define DUK_TVAL_SET_TVAL(tv, x) \
+ do { \
+ *(tv) = *(x); \
+ } while (0)
/* getters */
-#define DUK_TVAL_GET_BOOLEAN(tv) ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US1])
+#define DUK_TVAL_GET_BOOLEAN(tv) ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US1])
#if defined(DUK_USE_FASTINT)
-#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->d)
-#define DUK_TVAL_GET_FASTINT(tv) DUK__TVAL_GET_FASTINT((tv))
-#define DUK_TVAL_GET_FASTINT_U32(tv) DUK__TVAL_GET_FASTINT_U32((tv))
-#define DUK_TVAL_GET_FASTINT_I32(tv) DUK__TVAL_GET_FASTINT_I32((tv))
-#define DUK_TVAL_GET_NUMBER(tv) duk_tval_get_number_packed((tv))
+#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->d)
+#define DUK_TVAL_GET_FASTINT(tv) DUK__TVAL_GET_FASTINT((tv))
+#define DUK_TVAL_GET_FASTINT_U32(tv) DUK__TVAL_GET_FASTINT_U32((tv))
+#define DUK_TVAL_GET_FASTINT_I32(tv) DUK__TVAL_GET_FASTINT_I32((tv))
+#define DUK_TVAL_GET_NUMBER(tv) duk_tval_get_number_packed((tv))
#else
-#define DUK_TVAL_GET_NUMBER(tv) ((tv)->d)
-#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->d)
+#define DUK_TVAL_GET_NUMBER(tv) ((tv)->d)
+#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->d)
#endif
-#define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags) do { \
+#define DUK_TVAL_GET_LIGHTFUNC(tv, out_fp, out_flags) \
+ do { \
(out_flags) = (tv)->ui[DUK_DBL_IDX_UI0] & 0xffffUL; \
(out_fp) = (duk_c_function) (tv)->ui[DUK_DBL_IDX_UI1]; \
} while (0)
-#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((duk_c_function) ((tv)->ui[DUK_DBL_IDX_UI1]))
-#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv) (((duk_small_uint_t) (tv)->ui[DUK_DBL_IDX_UI0]) & 0xffffUL)
-#define DUK_TVAL_GET_STRING(tv) ((duk_hstring *) (tv)->vp[DUK_DBL_IDX_VP1])
-#define DUK_TVAL_GET_OBJECT(tv) ((duk_hobject *) (tv)->vp[DUK_DBL_IDX_VP1])
-#define DUK_TVAL_GET_BUFFER(tv) ((duk_hbuffer *) (tv)->vp[DUK_DBL_IDX_VP1])
-#define DUK_TVAL_GET_POINTER(tv) ((void *) (tv)->vp[DUK_DBL_IDX_VP1])
-#define DUK_TVAL_GET_HEAPHDR(tv) ((duk_heaphdr *) (tv)->vp[DUK_DBL_IDX_VP1])
+#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((duk_c_function) ((tv)->ui[DUK_DBL_IDX_UI1]))
+#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv) (((duk_small_uint_t) (tv)->ui[DUK_DBL_IDX_UI0]) & 0xffffUL)
+#define DUK_TVAL_GET_STRING(tv) ((duk_hstring *) (tv)->vp[DUK_DBL_IDX_VP1])
+#define DUK_TVAL_GET_OBJECT(tv) ((duk_hobject *) (tv)->vp[DUK_DBL_IDX_VP1])
+#define DUK_TVAL_GET_BUFFER(tv) ((duk_hbuffer *) (tv)->vp[DUK_DBL_IDX_VP1])
+#define DUK_TVAL_GET_POINTER(tv) ((void *) (tv)->vp[DUK_DBL_IDX_VP1])
+#define DUK_TVAL_GET_HEAPHDR(tv) ((duk_heaphdr *) (tv)->vp[DUK_DBL_IDX_VP1])
/* decoding */
-#define DUK_TVAL_GET_TAG(tv) ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US0])
-
-#define DUK_TVAL_IS_UNDEFINED(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNDEFINED)
-#define DUK_TVAL_IS_UNUSED(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNUSED)
-#define DUK_TVAL_IS_NULL(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_NULL)
-#define DUK_TVAL_IS_BOOLEAN(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BOOLEAN)
-#define DUK_TVAL_IS_BOOLEAN_TRUE(tv) ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_TRUE)
-#define DUK_TVAL_IS_BOOLEAN_FALSE(tv) ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_FALSE)
-#define DUK_TVAL_IS_LIGHTFUNC(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_LIGHTFUNC)
-#define DUK_TVAL_IS_STRING(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_STRING)
-#define DUK_TVAL_IS_OBJECT(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_OBJECT)
-#define DUK_TVAL_IS_BUFFER(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BUFFER)
-#define DUK_TVAL_IS_POINTER(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_POINTER)
+#define DUK_TVAL_GET_TAG(tv) ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US0])
+
+#define DUK_TVAL_IS_UNDEFINED(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNDEFINED)
+#define DUK_TVAL_IS_UNUSED(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNUSED)
+#define DUK_TVAL_IS_NULL(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_NULL)
+#define DUK_TVAL_IS_BOOLEAN(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BOOLEAN)
+#define DUK_TVAL_IS_BOOLEAN_TRUE(tv) ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_TRUE)
+#define DUK_TVAL_IS_BOOLEAN_FALSE(tv) ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_FALSE)
+#define DUK_TVAL_IS_LIGHTFUNC(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_LIGHTFUNC)
+#define DUK_TVAL_IS_STRING(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_STRING)
+#define DUK_TVAL_IS_OBJECT(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_OBJECT)
+#define DUK_TVAL_IS_BUFFER(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BUFFER)
+#define DUK_TVAL_IS_POINTER(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_POINTER)
#if defined(DUK_USE_FASTINT)
/* 0xfff0 is -Infinity */
-#define DUK_TVAL_IS_DOUBLE(tv) (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
-#define DUK_TVAL_IS_FASTINT(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_FASTINT)
-#define DUK_TVAL_IS_NUMBER(tv) (DUK_TVAL_GET_TAG((tv)) <= 0xfff1UL)
+#define DUK_TVAL_IS_DOUBLE(tv) (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
+#define DUK_TVAL_IS_FASTINT(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_FASTINT)
+#define DUK_TVAL_IS_NUMBER(tv) (DUK_TVAL_GET_TAG((tv)) <= 0xfff1UL)
#else
-#define DUK_TVAL_IS_NUMBER(tv) (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
-#define DUK_TVAL_IS_DOUBLE(tv) DUK_TVAL_IS_NUMBER((tv))
+#define DUK_TVAL_IS_NUMBER(tv) (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
+#define DUK_TVAL_IS_DOUBLE(tv) DUK_TVAL_IS_NUMBER((tv))
#endif
/* This is performance critical because it appears in every DECREF. */
-#define DUK_TVAL_IS_HEAP_ALLOCATED(tv) (DUK_TVAL_GET_TAG((tv)) >= DUK_TAG_STRING)
+#define DUK_TVAL_IS_HEAP_ALLOCATED(tv) (DUK_TVAL_GET_TAG((tv)) >= DUK_TAG_STRING)
#if defined(DUK_USE_FASTINT)
DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_packed(duk_tval *tv);
#endif
-#else /* DUK_USE_PACKED_TVAL */
+#else /* DUK_USE_PACKED_TVAL */
/* ======================================================================== */
/*
@@ -1124,7 +1225,7 @@ struct duk_tval_struct {
duk_double_t d;
duk_small_int_t i;
#if defined(DUK_USE_FASTINT)
- duk_int64_t fi; /* if present, forces 16-byte duk_tval */
+ duk_int64_t fi; /* if present, forces 16-byte duk_tval */
#endif
void *voidptr;
duk_hstring *hstring;
@@ -1152,24 +1253,23 @@ typedef struct {
#define DUK_TVAL_UNUSED_INITIALIZER() \
{ DUK_TAG_UNUSED, 0, 0.0 }
-#define DUK_TAG_MIN 0
-#define DUK_TAG_NUMBER 0 /* DUK_TAG_NUMBER only defined for non-packed duk_tval */
+#define DUK_TAG_MIN 0
+#define DUK_TAG_NUMBER 0 /* DUK_TAG_NUMBER only defined for non-packed duk_tval */
#if defined(DUK_USE_FASTINT)
-#define DUK_TAG_FASTINT 1
-#endif
-#define DUK_TAG_UNDEFINED 2
-#define DUK_TAG_NULL 3
-#define DUK_TAG_BOOLEAN 4
-#define DUK_TAG_POINTER 5
-#define DUK_TAG_LIGHTFUNC 6
-#define DUK_TAG_UNUSED 7 /* marker; not actual tagged type */
-#define DUK_TAG_STRING 8 /* first heap allocated, match bit boundary */
-#define DUK_TAG_OBJECT 9
-#define DUK_TAG_BUFFER 10
-#define DUK_TAG_MAX 10
-
-#define DUK_TVAL_IS_VALID_TAG(tv) \
- (DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)
+#define DUK_TAG_FASTINT 1
+#endif
+#define DUK_TAG_UNDEFINED 2
+#define DUK_TAG_NULL 3
+#define DUK_TAG_BOOLEAN 4
+#define DUK_TAG_POINTER 5
+#define DUK_TAG_LIGHTFUNC 6
+#define DUK_TAG_UNUSED 7 /* marker; not actual tagged type */
+#define DUK_TAG_STRING 8 /* first heap allocated, match bit boundary */
+#define DUK_TAG_OBJECT 9
+#define DUK_TAG_BUFFER 10
+#define DUK_TAG_MAX 10
+
+#define DUK_TVAL_IS_VALID_TAG(tv) (DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)
/* DUK_TAG_NUMBER is intentionally first, as it is the default clause in code
* to support the 8-byte representation. Further, it is a non-heap-allocated
@@ -1178,25 +1278,29 @@ typedef struct {
*/
/* setters */
-#define DUK_TVAL_SET_UNDEFINED(tv) do { \
+#define DUK_TVAL_SET_UNDEFINED(tv) \
+ do { \
duk_tval *duk__tv; \
duk__tv = (tv); \
duk__tv->t = DUK_TAG_UNDEFINED; \
} while (0)
-#define DUK_TVAL_SET_UNUSED(tv) do { \
+#define DUK_TVAL_SET_UNUSED(tv) \
+ do { \
duk_tval *duk__tv; \
duk__tv = (tv); \
duk__tv->t = DUK_TAG_UNUSED; \
} while (0)
-#define DUK_TVAL_SET_NULL(tv) do { \
+#define DUK_TVAL_SET_NULL(tv) \
+ do { \
duk_tval *duk__tv; \
duk__tv = (tv); \
duk__tv->t = DUK_TAG_NULL; \
} while (0)
-#define DUK_TVAL_SET_BOOLEAN(tv,val) do { \
+#define DUK_TVAL_SET_BOOLEAN(tv, val) \
+ do { \
duk_tval *duk__tv; \
duk__tv = (tv); \
duk__tv->t = DUK_TAG_BOOLEAN; \
@@ -1204,7 +1308,8 @@ typedef struct {
} while (0)
#if defined(DUK_USE_FASTINT)
-#define DUK_TVAL_SET_DOUBLE(tv,val) do { \
+#define DUK_TVAL_SET_DOUBLE(tv, val) \
+ do { \
duk_tval *duk__tv; \
duk_double_t duk__dblval; \
duk__dblval = (val); \
@@ -1213,31 +1318,32 @@ typedef struct {
duk__tv->t = DUK_TAG_NUMBER; \
duk__tv->v.d = duk__dblval; \
} while (0)
-#define DUK_TVAL_SET_I48(tv,val) do { \
+#define DUK_TVAL_SET_I48(tv, val) \
+ do { \
duk_tval *duk__tv; \
duk__tv = (tv); \
duk__tv->t = DUK_TAG_FASTINT; \
duk__tv->v.fi = (val); \
} while (0)
-#define DUK_TVAL_SET_U32(tv,val) do { \
+#define DUK_TVAL_SET_U32(tv, val) \
+ do { \
duk_tval *duk__tv; \
duk__tv = (tv); \
duk__tv->t = DUK_TAG_FASTINT; \
duk__tv->v.fi = (duk_int64_t) (val); \
} while (0)
-#define DUK_TVAL_SET_I32(tv,val) do { \
+#define DUK_TVAL_SET_I32(tv, val) \
+ do { \
duk_tval *duk__tv; \
duk__tv = (tv); \
duk__tv->t = DUK_TAG_FASTINT; \
duk__tv->v.fi = (duk_int64_t) (val); \
} while (0)
-#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \
- duk_tval_set_number_chkfast_fast((tv), (d))
-#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \
- duk_tval_set_number_chkfast_slow((tv), (d))
-#define DUK_TVAL_SET_NUMBER(tv,val) \
- DUK_TVAL_SET_DOUBLE((tv), (val))
-#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) do { \
+#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv, d) duk_tval_set_number_chkfast_fast((tv), (d))
+#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, d) duk_tval_set_number_chkfast_slow((tv), (d))
+#define DUK_TVAL_SET_NUMBER(tv, val) DUK_TVAL_SET_DOUBLE((tv), (val))
+#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) \
+ do { \
duk_tval *duk__tv; \
duk_double_t duk__d; \
duk__tv = (tv); \
@@ -1246,7 +1352,8 @@ typedef struct {
DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
} \
} while (0)
-#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) do { \
+#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) \
+ do { \
duk_tval *duk__tv; \
duk_double_t duk__d; \
duk__tv = (tv); \
@@ -1255,16 +1362,13 @@ typedef struct {
DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
} \
} while (0)
-#else /* DUK_USE_FASTINT */
-#define DUK_TVAL_SET_DOUBLE(tv,d) \
- DUK_TVAL_SET_NUMBER((tv), (d))
-#define DUK_TVAL_SET_I48(tv,val) \
- DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val)) /* XXX: fast int-to-double */
-#define DUK_TVAL_SET_U32(tv,val) \
- DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
-#define DUK_TVAL_SET_I32(tv,val) \
- DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
-#define DUK_TVAL_SET_NUMBER(tv,val) do { \
+#else /* DUK_USE_FASTINT */
+#define DUK_TVAL_SET_DOUBLE(tv, d) DUK_TVAL_SET_NUMBER((tv), (d))
+#define DUK_TVAL_SET_I48(tv, val) DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val)) /* XXX: fast int-to-double */
+#define DUK_TVAL_SET_U32(tv, val) DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
+#define DUK_TVAL_SET_I32(tv, val) DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
+#define DUK_TVAL_SET_NUMBER(tv, val) \
+ do { \
duk_tval *duk__tv; \
duk_double_t duk__dblval; \
duk__dblval = (val); \
@@ -1273,25 +1377,28 @@ typedef struct {
duk__tv->t = DUK_TAG_NUMBER; \
duk__tv->v.d = duk__dblval; \
} while (0)
-#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \
- DUK_TVAL_SET_NUMBER((tv), (d))
-#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \
- DUK_TVAL_SET_NUMBER((tv), (d))
-#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) do { } while (0)
-#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) do { } while (0)
-#endif /* DUK_USE_FASTINT */
-
-#define DUK_TVAL_SET_FASTINT(tv,i) \
- DUK_TVAL_SET_I48((tv), (i)) /* alias */
-
-#define DUK_TVAL_SET_POINTER(tv,hptr) do { \
+#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv, d) DUK_TVAL_SET_NUMBER((tv), (d))
+#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, d) DUK_TVAL_SET_NUMBER((tv), (d))
+#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) \
+ do { \
+ } while (0)
+#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) \
+ do { \
+ } while (0)
+#endif /* DUK_USE_FASTINT */
+
+#define DUK_TVAL_SET_FASTINT(tv, i) DUK_TVAL_SET_I48((tv), (i)) /* alias */
+
+#define DUK_TVAL_SET_POINTER(tv, hptr) \
+ do { \
duk_tval *duk__tv; \
duk__tv = (tv); \
duk__tv->t = DUK_TAG_POINTER; \
duk__tv->v.voidptr = (hptr); \
} while (0)
-#define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags) do { \
+#define DUK_TVAL_SET_LIGHTFUNC(tv, fp, flags) \
+ do { \
duk_tval *duk__tv; \
duk__tv = (tv); \
duk__tv->t = DUK_TAG_LIGHTFUNC; \
@@ -1299,28 +1406,32 @@ typedef struct {
duk__tv->v.lightfunc = (duk_c_function) (fp); \
} while (0)
-#define DUK_TVAL_SET_STRING(tv,hptr) do { \
+#define DUK_TVAL_SET_STRING(tv, hptr) \
+ do { \
duk_tval *duk__tv; \
duk__tv = (tv); \
duk__tv->t = DUK_TAG_STRING; \
duk__tv->v.hstring = (hptr); \
} while (0)
-#define DUK_TVAL_SET_OBJECT(tv,hptr) do { \
+#define DUK_TVAL_SET_OBJECT(tv, hptr) \
+ do { \
duk_tval *duk__tv; \
duk__tv = (tv); \
duk__tv->t = DUK_TAG_OBJECT; \
duk__tv->v.hobject = (hptr); \
} while (0)
-#define DUK_TVAL_SET_BUFFER(tv,hptr) do { \
+#define DUK_TVAL_SET_BUFFER(tv, hptr) \
+ do { \
duk_tval *duk__tv; \
duk__tv = (tv); \
duk__tv->t = DUK_TAG_BUFFER; \
duk__tv->v.hbuffer = (hptr); \
} while (0)
-#define DUK_TVAL_SET_NAN(tv) do { \
+#define DUK_TVAL_SET_NAN(tv) \
+ do { \
/* in non-packed representation we don't care about which NaN is used */ \
duk_tval *duk__tv; \
duk__tv = (tv); \
@@ -1328,32 +1439,32 @@ typedef struct {
duk__tv->v.d = DUK_DOUBLE_NAN; \
} while (0)
-#define DUK_TVAL_SET_TVAL(tv,x) do { *(tv) = *(x); } while (0)
+#define DUK_TVAL_SET_TVAL(tv, x) \
+ do { \
+ *(tv) = *(x); \
+ } while (0)
/* getters */
-#define DUK_TVAL_GET_BOOLEAN(tv) ((duk_small_uint_t) (tv)->v.i)
+#define DUK_TVAL_GET_BOOLEAN(tv) ((duk_small_uint_t) (tv)->v.i)
#if defined(DUK_USE_FASTINT)
-#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->v.d)
-#define DUK_TVAL_GET_FASTINT(tv) ((tv)->v.fi)
-#define DUK_TVAL_GET_FASTINT_U32(tv) ((duk_uint32_t) ((tv)->v.fi))
-#define DUK_TVAL_GET_FASTINT_I32(tv) ((duk_int32_t) ((tv)->v.fi))
+#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->v.d)
+#define DUK_TVAL_GET_FASTINT(tv) ((tv)->v.fi)
+#define DUK_TVAL_GET_FASTINT_U32(tv) ((duk_uint32_t) ((tv)->v.fi))
+#define DUK_TVAL_GET_FASTINT_I32(tv) ((duk_int32_t) ((tv)->v.fi))
#if 0
-#define DUK_TVAL_GET_NUMBER(tv) (DUK_TVAL_IS_FASTINT((tv)) ? \
- (duk_double_t) DUK_TVAL_GET_FASTINT((tv)) : \
- DUK_TVAL_GET_DOUBLE((tv)))
-#define DUK_TVAL_GET_NUMBER(tv) duk_tval_get_number_unpacked((tv))
+#define DUK_TVAL_GET_NUMBER(tv) (DUK_TVAL_IS_FASTINT((tv)) ? (duk_double_t) DUK_TVAL_GET_FASTINT((tv)) : DUK_TVAL_GET_DOUBLE((tv)))
+#define DUK_TVAL_GET_NUMBER(tv) duk_tval_get_number_unpacked((tv))
#else
/* This seems reasonable overall. */
-#define DUK_TVAL_GET_NUMBER(tv) (DUK_TVAL_IS_FASTINT((tv)) ? \
- duk_tval_get_number_unpacked_fastint((tv)) : \
- DUK_TVAL_GET_DOUBLE((tv)))
+#define DUK_TVAL_GET_NUMBER(tv) (DUK_TVAL_IS_FASTINT((tv)) ? duk_tval_get_number_unpacked_fastint((tv)) : DUK_TVAL_GET_DOUBLE((tv)))
#endif
#else
-#define DUK_TVAL_GET_NUMBER(tv) ((tv)->v.d)
-#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->v.d)
-#endif /* DUK_USE_FASTINT */
-#define DUK_TVAL_GET_POINTER(tv) ((tv)->v.voidptr)
-#define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags) do { \
+#define DUK_TVAL_GET_NUMBER(tv) ((tv)->v.d)
+#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->v.d)
+#endif /* DUK_USE_FASTINT */
+#define DUK_TVAL_GET_POINTER(tv) ((tv)->v.voidptr)
+#define DUK_TVAL_GET_LIGHTFUNC(tv, out_fp, out_flags) \
+ do { \
(out_flags) = (duk_uint32_t) (tv)->v_extra; \
(out_fp) = (tv)->v.lightfunc; \
} while (0)
@@ -1373,19 +1484,18 @@ typedef struct {
#define DUK_TVAL_IS_BOOLEAN_TRUE(tv) (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i != 0))
#define DUK_TVAL_IS_BOOLEAN_FALSE(tv) (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i == 0))
#if defined(DUK_USE_FASTINT)
-#define DUK_TVAL_IS_DOUBLE(tv) ((tv)->t == DUK_TAG_NUMBER)
-#define DUK_TVAL_IS_FASTINT(tv) ((tv)->t == DUK_TAG_FASTINT)
-#define DUK_TVAL_IS_NUMBER(tv) ((tv)->t == DUK_TAG_NUMBER || \
- (tv)->t == DUK_TAG_FASTINT)
+#define DUK_TVAL_IS_DOUBLE(tv) ((tv)->t == DUK_TAG_NUMBER)
+#define DUK_TVAL_IS_FASTINT(tv) ((tv)->t == DUK_TAG_FASTINT)
+#define DUK_TVAL_IS_NUMBER(tv) ((tv)->t == DUK_TAG_NUMBER || (tv)->t == DUK_TAG_FASTINT)
#else
-#define DUK_TVAL_IS_NUMBER(tv) ((tv)->t == DUK_TAG_NUMBER)
-#define DUK_TVAL_IS_DOUBLE(tv) DUK_TVAL_IS_NUMBER((tv))
-#endif /* DUK_USE_FASTINT */
-#define DUK_TVAL_IS_POINTER(tv) ((tv)->t == DUK_TAG_POINTER)
-#define DUK_TVAL_IS_LIGHTFUNC(tv) ((tv)->t == DUK_TAG_LIGHTFUNC)
-#define DUK_TVAL_IS_STRING(tv) ((tv)->t == DUK_TAG_STRING)
-#define DUK_TVAL_IS_OBJECT(tv) ((tv)->t == DUK_TAG_OBJECT)
-#define DUK_TVAL_IS_BUFFER(tv) ((tv)->t == DUK_TAG_BUFFER)
+#define DUK_TVAL_IS_NUMBER(tv) ((tv)->t == DUK_TAG_NUMBER)
+#define DUK_TVAL_IS_DOUBLE(tv) DUK_TVAL_IS_NUMBER((tv))
+#endif /* DUK_USE_FASTINT */
+#define DUK_TVAL_IS_POINTER(tv) ((tv)->t == DUK_TAG_POINTER)
+#define DUK_TVAL_IS_LIGHTFUNC(tv) ((tv)->t == DUK_TAG_LIGHTFUNC)
+#define DUK_TVAL_IS_STRING(tv) ((tv)->t == DUK_TAG_STRING)
+#define DUK_TVAL_IS_OBJECT(tv) ((tv)->t == DUK_TAG_OBJECT)
+#define DUK_TVAL_IS_BUFFER(tv) ((tv)->t == DUK_TAG_BUFFER)
/* This is performance critical because it's needed for every DECREF.
* Take advantage of the fact that the first heap allocated tag is 8,
@@ -1393,61 +1503,68 @@ typedef struct {
* non-heap-allocated tags).
*/
#if 0
-#define DUK_TVAL_IS_HEAP_ALLOCATED(tv) ((tv)->t >= DUK_TAG_STRING)
+#define DUK_TVAL_IS_HEAP_ALLOCATED(tv) ((tv)->t >= DUK_TAG_STRING)
#endif
-#define DUK_TVAL_IS_HEAP_ALLOCATED(tv) ((tv)->t & 0x08)
+#define DUK_TVAL_IS_HEAP_ALLOCATED(tv) ((tv)->t & 0x08)
#if defined(DUK_USE_FASTINT)
#if 0
DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv);
#endif
-DUK_INTERNAL_DECL DUK_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv);
+DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv);
#endif
-#endif /* DUK_USE_PACKED_TVAL */
+#endif /* DUK_USE_PACKED_TVAL */
/*
* Convenience (independent of representation)
*/
-#define DUK_TVAL_SET_BOOLEAN_TRUE(tv) DUK_TVAL_SET_BOOLEAN((tv), 1)
-#define DUK_TVAL_SET_BOOLEAN_FALSE(tv) DUK_TVAL_SET_BOOLEAN((tv), 0)
+#define DUK_TVAL_SET_BOOLEAN_TRUE(tv) DUK_TVAL_SET_BOOLEAN((tv), 1)
+#define DUK_TVAL_SET_BOOLEAN_FALSE(tv) DUK_TVAL_SET_BOOLEAN((tv), 0)
-#define DUK_TVAL_STRING_IS_SYMBOL(tv) \
- DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING((tv)))
+#define DUK_TVAL_STRING_IS_SYMBOL(tv) DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING((tv)))
/* Lightfunc flags packing and unpacking. */
/* Sign extend: 0x0000##00 -> 0x##000000 -> sign extend to 0xssssss##.
* Avoid signed shifts due to portability limitations.
*/
-#define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags) \
- ((duk_int32_t) (duk_int8_t) (((duk_uint16_t) (lf_flags)) >> 8))
-#define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags) \
- (((lf_flags) >> 4) & 0x0fU)
-#define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags) \
- ((lf_flags) & 0x0fU)
-#define DUK_LFUNC_FLAGS_PACK(magic,length,nargs) \
- ((((duk_small_uint_t) (magic)) & 0xffU) << 8) | ((length) << 4) | (nargs)
-
-#define DUK_LFUNC_NARGS_VARARGS 0x0f /* varargs marker */
-#define DUK_LFUNC_NARGS_MIN 0x00
-#define DUK_LFUNC_NARGS_MAX 0x0e /* max, excl. varargs marker */
-#define DUK_LFUNC_LENGTH_MIN 0x00
-#define DUK_LFUNC_LENGTH_MAX 0x0f
-#define DUK_LFUNC_MAGIC_MIN (-0x80)
-#define DUK_LFUNC_MAGIC_MAX 0x7f
+#define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags) ((duk_int32_t) (duk_int8_t) (((duk_uint16_t) (lf_flags)) >> 8))
+#define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags) (((lf_flags) >> 4) & 0x0fU)
+#define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags) ((lf_flags) &0x0fU)
+#define DUK_LFUNC_FLAGS_PACK(magic, length, nargs) ((((duk_small_uint_t) (magic)) & 0xffU) << 8) | ((length) << 4) | (nargs)
+
+#define DUK_LFUNC_NARGS_VARARGS 0x0f /* varargs marker */
+#define DUK_LFUNC_NARGS_MIN 0x00
+#define DUK_LFUNC_NARGS_MAX 0x0e /* max, excl. varargs marker */
+#define DUK_LFUNC_LENGTH_MIN 0x00
+#define DUK_LFUNC_LENGTH_MAX 0x0f
+#define DUK_LFUNC_MAGIC_MIN (-0x80)
+#define DUK_LFUNC_MAGIC_MAX 0x7f
/* fastint constants etc */
#if defined(DUK_USE_FASTINT)
-#define DUK_FASTINT_MIN (DUK_I64_CONSTANT(-0x800000000000))
-#define DUK_FASTINT_MAX (DUK_I64_CONSTANT(0x7fffffffffff))
-#define DUK_FASTINT_BITS 48
+#define DUK_FASTINT_MIN (DUK_I64_CONSTANT(-0x800000000000))
+#define DUK_FASTINT_MAX (DUK_I64_CONSTANT(0x7fffffffffff))
+#define DUK_FASTINT_BITS 48
-DUK_INTERNAL_DECL DUK_INLINE void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x);
+DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x);
DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x);
#endif
-#endif /* DUK_TVAL_H_INCLUDED */
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_tval_assert_valid(duk_tval *tv);
+#define DUK_TVAL_ASSERT_VALID(tv) \
+ do { \
+ duk_tval_assert_valid((tv)); \
+ } while (0)
+#else
+#define DUK_TVAL_ASSERT_VALID(tv) \
+ do { \
+ } while (0)
+#endif
+
+#endif /* DUK_TVAL_H_INCLUDED */
/* #include duk_builtins.h */
/*
* Automatically generated by genbuiltins.py, do not edit!
@@ -1477,9 +1594,9 @@ DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double
#define DUK_STRIDX_UC_FUNCTION 5 /* 'Function' */
#define DUK_HEAP_STRING_UC_FUNCTION(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_FUNCTION)
#define DUK_HTHREAD_STRING_UC_FUNCTION(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_FUNCTION)
-#define DUK_STRIDX_ARRAY 6 /* 'Array' */
-#define DUK_HEAP_STRING_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY)
-#define DUK_HTHREAD_STRING_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY)
+#define DUK_STRIDX_UC_ARRAY 6 /* 'Array' */
+#define DUK_HEAP_STRING_UC_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARRAY)
+#define DUK_HTHREAD_STRING_UC_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARRAY)
#define DUK_STRIDX_UC_STRING 7 /* 'String' */
#define DUK_HEAP_STRING_UC_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_STRING)
#define DUK_HTHREAD_STRING_UC_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_STRING)
@@ -1489,9 +1606,9 @@ DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double
#define DUK_STRIDX_UC_NUMBER 9 /* 'Number' */
#define DUK_HEAP_STRING_UC_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NUMBER)
#define DUK_HTHREAD_STRING_UC_NUMBER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NUMBER)
-#define DUK_STRIDX_DATE 10 /* 'Date' */
-#define DUK_HEAP_STRING_DATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATE)
-#define DUK_HTHREAD_STRING_DATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATE)
+#define DUK_STRIDX_UC_DATE 10 /* 'Date' */
+#define DUK_HEAP_STRING_UC_DATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_DATE)
+#define DUK_HTHREAD_STRING_UC_DATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_DATE)
#define DUK_STRIDX_REG_EXP 11 /* 'RegExp' */
#define DUK_HEAP_STRING_REG_EXP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REG_EXP)
#define DUK_HTHREAD_STRING_REG_EXP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_REG_EXP)
@@ -1687,278 +1804,293 @@ DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double
#define DUK_STRIDX_OWN_KEYS 75 /* 'ownKeys' */
#define DUK_HEAP_STRING_OWN_KEYS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OWN_KEYS)
#define DUK_HTHREAD_STRING_OWN_KEYS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OWN_KEYS)
-#define DUK_STRIDX_SET_PROTOTYPE_OF 76 /* 'setPrototypeOf' */
+#define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE 76 /* '\x81Symbol.toPrimitive\xff' */
+#define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_TO_PRIMITIVE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)
+#define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_TO_PRIMITIVE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)
+#define DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE 77 /* '\x81Symbol.hasInstance\xff' */
+#define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_HAS_INSTANCE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)
+#define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_HAS_INSTANCE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)
+#define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG 78 /* '\x81Symbol.toStringTag\xff' */
+#define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_TO_STRING_TAG(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG)
+#define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_TO_STRING_TAG(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG)
+#define DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE 79 /* '\x81Symbol.isConcatSpreadable\xff' */
+#define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE)
+#define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE)
+#define DUK_STRIDX_SET_PROTOTYPE_OF 80 /* 'setPrototypeOf' */
#define DUK_HEAP_STRING_SET_PROTOTYPE_OF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_PROTOTYPE_OF)
#define DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_PROTOTYPE_OF)
-#define DUK_STRIDX___PROTO__ 77 /* '__proto__' */
+#define DUK_STRIDX___PROTO__ 81 /* '__proto__' */
#define DUK_HEAP_STRING___PROTO__(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX___PROTO__)
#define DUK_HTHREAD_STRING___PROTO__(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX___PROTO__)
-#define DUK_STRIDX_TO_STRING 78 /* 'toString' */
+#define DUK_STRIDX_TO_STRING 82 /* 'toString' */
#define DUK_HEAP_STRING_TO_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_STRING)
#define DUK_HTHREAD_STRING_TO_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_STRING)
-#define DUK_STRIDX_TO_JSON 79 /* 'toJSON' */
+#define DUK_STRIDX_TO_JSON 83 /* 'toJSON' */
#define DUK_HEAP_STRING_TO_JSON(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_JSON)
#define DUK_HTHREAD_STRING_TO_JSON(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_JSON)
-#define DUK_STRIDX_TYPE 80 /* 'type' */
+#define DUK_STRIDX_TYPE 84 /* 'type' */
#define DUK_HEAP_STRING_TYPE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE)
#define DUK_HTHREAD_STRING_TYPE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE)
-#define DUK_STRIDX_DATA 81 /* 'data' */
+#define DUK_STRIDX_DATA 85 /* 'data' */
#define DUK_HEAP_STRING_DATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA)
#define DUK_HTHREAD_STRING_DATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA)
-#define DUK_STRIDX_LENGTH 82 /* 'length' */
+#define DUK_STRIDX_LC_BUFFER 86 /* 'buffer' */
+#define DUK_HEAP_STRING_LC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER)
+#define DUK_HTHREAD_STRING_LC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER)
+#define DUK_STRIDX_LENGTH 87 /* 'length' */
#define DUK_HEAP_STRING_LENGTH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LENGTH)
#define DUK_HTHREAD_STRING_LENGTH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LENGTH)
-#define DUK_STRIDX_SET 83 /* 'set' */
+#define DUK_STRIDX_SET 88 /* 'set' */
#define DUK_HEAP_STRING_SET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET)
#define DUK_HTHREAD_STRING_SET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET)
-#define DUK_STRIDX_STACK 84 /* 'stack' */
+#define DUK_STRIDX_STACK 89 /* 'stack' */
#define DUK_HEAP_STRING_STACK(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STACK)
#define DUK_HTHREAD_STRING_STACK(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STACK)
-#define DUK_STRIDX_PC 85 /* 'pc' */
+#define DUK_STRIDX_PC 90 /* 'pc' */
#define DUK_HEAP_STRING_PC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PC)
#define DUK_HTHREAD_STRING_PC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PC)
-#define DUK_STRIDX_LINE_NUMBER 86 /* 'lineNumber' */
+#define DUK_STRIDX_LINE_NUMBER 91 /* 'lineNumber' */
#define DUK_HEAP_STRING_LINE_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER)
#define DUK_HTHREAD_STRING_LINE_NUMBER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER)
-#define DUK_STRIDX_INT_TRACEDATA 87 /* '\x82Tracedata' */
+#define DUK_STRIDX_INT_TRACEDATA 92 /* '\x82Tracedata' */
#define DUK_HEAP_STRING_INT_TRACEDATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA)
#define DUK_HTHREAD_STRING_INT_TRACEDATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA)
-#define DUK_STRIDX_NAME 88 /* 'name' */
+#define DUK_STRIDX_NAME 93 /* 'name' */
#define DUK_HEAP_STRING_NAME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAME)
#define DUK_HTHREAD_STRING_NAME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAME)
-#define DUK_STRIDX_FILE_NAME 89 /* 'fileName' */
+#define DUK_STRIDX_FILE_NAME 94 /* 'fileName' */
#define DUK_HEAP_STRING_FILE_NAME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME)
#define DUK_HTHREAD_STRING_FILE_NAME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILE_NAME)
-#define DUK_STRIDX_LC_POINTER 90 /* 'pointer' */
+#define DUK_STRIDX_LC_POINTER 95 /* 'pointer' */
#define DUK_HEAP_STRING_LC_POINTER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER)
#define DUK_HTHREAD_STRING_LC_POINTER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER)
-#define DUK_STRIDX_INT_TARGET 91 /* '\x82Target' */
+#define DUK_STRIDX_INT_TARGET 96 /* '\x82Target' */
#define DUK_HEAP_STRING_INT_TARGET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TARGET)
#define DUK_HTHREAD_STRING_INT_TARGET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TARGET)
-#define DUK_STRIDX_INT_NEXT 92 /* '\x82Next' */
+#define DUK_STRIDX_INT_NEXT 97 /* '\x82Next' */
#define DUK_HEAP_STRING_INT_NEXT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_NEXT)
#define DUK_HTHREAD_STRING_INT_NEXT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_NEXT)
-#define DUK_STRIDX_INT_BYTECODE 93 /* '\x82Bytecode' */
+#define DUK_STRIDX_INT_BYTECODE 98 /* '\x82Bytecode' */
#define DUK_HEAP_STRING_INT_BYTECODE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_BYTECODE)
#define DUK_HTHREAD_STRING_INT_BYTECODE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_BYTECODE)
-#define DUK_STRIDX_INT_FORMALS 94 /* '\x82Formals' */
+#define DUK_STRIDX_INT_FORMALS 99 /* '\x82Formals' */
#define DUK_HEAP_STRING_INT_FORMALS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FORMALS)
#define DUK_HTHREAD_STRING_INT_FORMALS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FORMALS)
-#define DUK_STRIDX_INT_VARMAP 95 /* '\x82Varmap' */
+#define DUK_STRIDX_INT_VARMAP 100 /* '\x82Varmap' */
#define DUK_HEAP_STRING_INT_VARMAP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARMAP)
#define DUK_HTHREAD_STRING_INT_VARMAP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARMAP)
-#define DUK_STRIDX_INT_SOURCE 96 /* '\x82Source' */
+#define DUK_STRIDX_INT_SOURCE 101 /* '\x82Source' */
#define DUK_HEAP_STRING_INT_SOURCE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_SOURCE)
#define DUK_HTHREAD_STRING_INT_SOURCE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_SOURCE)
-#define DUK_STRIDX_INT_PC2LINE 97 /* '\x82Pc2line' */
+#define DUK_STRIDX_INT_PC2LINE 102 /* '\x82Pc2line' */
#define DUK_HEAP_STRING_INT_PC2LINE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_PC2LINE)
#define DUK_HTHREAD_STRING_INT_PC2LINE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_PC2LINE)
-#define DUK_STRIDX_INT_MAP 98 /* '\x82Map' */
+#define DUK_STRIDX_INT_MAP 103 /* '\x82Map' */
#define DUK_HEAP_STRING_INT_MAP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_MAP)
#define DUK_HTHREAD_STRING_INT_MAP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_MAP)
-#define DUK_STRIDX_INT_VARENV 99 /* '\x82Varenv' */
+#define DUK_STRIDX_INT_VARENV 104 /* '\x82Varenv' */
#define DUK_HEAP_STRING_INT_VARENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARENV)
#define DUK_HTHREAD_STRING_INT_VARENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARENV)
-#define DUK_STRIDX_INT_FINALIZER 100 /* '\x82Finalizer' */
+#define DUK_STRIDX_INT_FINALIZER 105 /* '\x82Finalizer' */
#define DUK_HEAP_STRING_INT_FINALIZER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FINALIZER)
#define DUK_HTHREAD_STRING_INT_FINALIZER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FINALIZER)
-#define DUK_STRIDX_INT_VALUE 101 /* '\x82Value' */
+#define DUK_STRIDX_INT_VALUE 106 /* '\x82Value' */
#define DUK_HEAP_STRING_INT_VALUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VALUE)
#define DUK_HTHREAD_STRING_INT_VALUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE)
-#define DUK_STRIDX_COMPILE 102 /* 'compile' */
+#define DUK_STRIDX_COMPILE 107 /* 'compile' */
#define DUK_HEAP_STRING_COMPILE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPILE)
#define DUK_HTHREAD_STRING_COMPILE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPILE)
-#define DUK_STRIDX_INPUT 103 /* 'input' */
+#define DUK_STRIDX_INPUT 108 /* 'input' */
#define DUK_HEAP_STRING_INPUT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INPUT)
#define DUK_HTHREAD_STRING_INPUT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INPUT)
-#define DUK_STRIDX_ERR_CREATE 104 /* 'errCreate' */
+#define DUK_STRIDX_ERR_CREATE 109 /* 'errCreate' */
#define DUK_HEAP_STRING_ERR_CREATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_CREATE)
#define DUK_HTHREAD_STRING_ERR_CREATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_CREATE)
-#define DUK_STRIDX_ERR_THROW 105 /* 'errThrow' */
+#define DUK_STRIDX_ERR_THROW 110 /* 'errThrow' */
#define DUK_HEAP_STRING_ERR_THROW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_THROW)
#define DUK_HTHREAD_STRING_ERR_THROW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_THROW)
-#define DUK_STRIDX_ENV 106 /* 'env' */
+#define DUK_STRIDX_ENV 111 /* 'env' */
#define DUK_HEAP_STRING_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENV)
#define DUK_HTHREAD_STRING_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENV)
-#define DUK_STRIDX_HEX 107 /* 'hex' */
+#define DUK_STRIDX_HEX 112 /* 'hex' */
#define DUK_HEAP_STRING_HEX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HEX)
#define DUK_HTHREAD_STRING_HEX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HEX)
-#define DUK_STRIDX_BASE64 108 /* 'base64' */
+#define DUK_STRIDX_BASE64 113 /* 'base64' */
#define DUK_HEAP_STRING_BASE64(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BASE64)
#define DUK_HTHREAD_STRING_BASE64(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BASE64)
-#define DUK_STRIDX_JX 109 /* 'jx' */
+#define DUK_STRIDX_JX 114 /* 'jx' */
#define DUK_HEAP_STRING_JX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JX)
#define DUK_HTHREAD_STRING_JX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JX)
-#define DUK_STRIDX_JC 110 /* 'jc' */
+#define DUK_STRIDX_JC 115 /* 'jc' */
#define DUK_HEAP_STRING_JC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JC)
#define DUK_HTHREAD_STRING_JC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JC)
-#define DUK_STRIDX_JSON_EXT_UNDEFINED 111 /* '{"_undef":true}' */
+#define DUK_STRIDX_JSON_EXT_UNDEFINED 116 /* '{"_undef":true}' */
#define DUK_HEAP_STRING_JSON_EXT_UNDEFINED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_UNDEFINED)
#define DUK_HTHREAD_STRING_JSON_EXT_UNDEFINED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_UNDEFINED)
-#define DUK_STRIDX_JSON_EXT_NAN 112 /* '{"_nan":true}' */
+#define DUK_STRIDX_JSON_EXT_NAN 117 /* '{"_nan":true}' */
#define DUK_HEAP_STRING_JSON_EXT_NAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NAN)
#define DUK_HTHREAD_STRING_JSON_EXT_NAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NAN)
-#define DUK_STRIDX_JSON_EXT_POSINF 113 /* '{"_inf":true}' */
+#define DUK_STRIDX_JSON_EXT_POSINF 118 /* '{"_inf":true}' */
#define DUK_HEAP_STRING_JSON_EXT_POSINF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_POSINF)
#define DUK_HTHREAD_STRING_JSON_EXT_POSINF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_POSINF)
-#define DUK_STRIDX_JSON_EXT_NEGINF 114 /* '{"_ninf":true}' */
+#define DUK_STRIDX_JSON_EXT_NEGINF 119 /* '{"_ninf":true}' */
#define DUK_HEAP_STRING_JSON_EXT_NEGINF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NEGINF)
#define DUK_HTHREAD_STRING_JSON_EXT_NEGINF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NEGINF)
-#define DUK_STRIDX_JSON_EXT_FUNCTION1 115 /* '{"_func":true}' */
+#define DUK_STRIDX_JSON_EXT_FUNCTION1 120 /* '{"_func":true}' */
#define DUK_HEAP_STRING_JSON_EXT_FUNCTION1(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION1)
#define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION1(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION1)
-#define DUK_STRIDX_JSON_EXT_FUNCTION2 116 /* '{_func:true}' */
+#define DUK_STRIDX_JSON_EXT_FUNCTION2 121 /* '{_func:true}' */
#define DUK_HEAP_STRING_JSON_EXT_FUNCTION2(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION2)
#define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION2(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION2)
-#define DUK_STRIDX_BREAK 117 /* 'break' */
+#define DUK_STRIDX_BREAK 122 /* 'break' */
#define DUK_HEAP_STRING_BREAK(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BREAK)
#define DUK_HTHREAD_STRING_BREAK(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BREAK)
-#define DUK_STRIDX_CASE 118 /* 'case' */
+#define DUK_STRIDX_CASE 123 /* 'case' */
#define DUK_HEAP_STRING_CASE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CASE)
#define DUK_HTHREAD_STRING_CASE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CASE)
-#define DUK_STRIDX_CATCH 119 /* 'catch' */
+#define DUK_STRIDX_CATCH 124 /* 'catch' */
#define DUK_HEAP_STRING_CATCH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CATCH)
#define DUK_HTHREAD_STRING_CATCH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CATCH)
-#define DUK_STRIDX_CONTINUE 120 /* 'continue' */
+#define DUK_STRIDX_CONTINUE 125 /* 'continue' */
#define DUK_HEAP_STRING_CONTINUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONTINUE)
#define DUK_HTHREAD_STRING_CONTINUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONTINUE)
-#define DUK_STRIDX_DEBUGGER 121 /* 'debugger' */
+#define DUK_STRIDX_DEBUGGER 126 /* 'debugger' */
#define DUK_HEAP_STRING_DEBUGGER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEBUGGER)
#define DUK_HTHREAD_STRING_DEBUGGER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEBUGGER)
-#define DUK_STRIDX_DEFAULT 122 /* 'default' */
+#define DUK_STRIDX_DEFAULT 127 /* 'default' */
#define DUK_HEAP_STRING_DEFAULT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFAULT)
#define DUK_HTHREAD_STRING_DEFAULT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFAULT)
-#define DUK_STRIDX_DELETE 123 /* 'delete' */
+#define DUK_STRIDX_DELETE 128 /* 'delete' */
#define DUK_HEAP_STRING_DELETE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE)
#define DUK_HTHREAD_STRING_DELETE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE)
-#define DUK_STRIDX_DO 124 /* 'do' */
+#define DUK_STRIDX_DO 129 /* 'do' */
#define DUK_HEAP_STRING_DO(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DO)
#define DUK_HTHREAD_STRING_DO(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DO)
-#define DUK_STRIDX_ELSE 125 /* 'else' */
+#define DUK_STRIDX_ELSE 130 /* 'else' */
#define DUK_HEAP_STRING_ELSE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ELSE)
#define DUK_HTHREAD_STRING_ELSE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ELSE)
-#define DUK_STRIDX_FINALLY 126 /* 'finally' */
+#define DUK_STRIDX_FINALLY 131 /* 'finally' */
#define DUK_HEAP_STRING_FINALLY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FINALLY)
#define DUK_HTHREAD_STRING_FINALLY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FINALLY)
-#define DUK_STRIDX_FOR 127 /* 'for' */
+#define DUK_STRIDX_FOR 132 /* 'for' */
#define DUK_HEAP_STRING_FOR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FOR)
#define DUK_HTHREAD_STRING_FOR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FOR)
-#define DUK_STRIDX_LC_FUNCTION 128 /* 'function' */
+#define DUK_STRIDX_LC_FUNCTION 133 /* 'function' */
#define DUK_HEAP_STRING_LC_FUNCTION(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FUNCTION)
#define DUK_HTHREAD_STRING_LC_FUNCTION(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FUNCTION)
-#define DUK_STRIDX_IF 129 /* 'if' */
+#define DUK_STRIDX_IF 134 /* 'if' */
#define DUK_HEAP_STRING_IF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IF)
#define DUK_HTHREAD_STRING_IF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IF)
-#define DUK_STRIDX_IN 130 /* 'in' */
+#define DUK_STRIDX_IN 135 /* 'in' */
#define DUK_HEAP_STRING_IN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IN)
#define DUK_HTHREAD_STRING_IN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IN)
-#define DUK_STRIDX_INSTANCEOF 131 /* 'instanceof' */
+#define DUK_STRIDX_INSTANCEOF 136 /* 'instanceof' */
#define DUK_HEAP_STRING_INSTANCEOF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INSTANCEOF)
#define DUK_HTHREAD_STRING_INSTANCEOF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INSTANCEOF)
-#define DUK_STRIDX_NEW 132 /* 'new' */
+#define DUK_STRIDX_NEW 137 /* 'new' */
#define DUK_HEAP_STRING_NEW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEW)
#define DUK_HTHREAD_STRING_NEW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEW)
-#define DUK_STRIDX_RETURN 133 /* 'return' */
+#define DUK_STRIDX_RETURN 138 /* 'return' */
#define DUK_HEAP_STRING_RETURN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RETURN)
#define DUK_HTHREAD_STRING_RETURN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RETURN)
-#define DUK_STRIDX_SWITCH 134 /* 'switch' */
+#define DUK_STRIDX_SWITCH 139 /* 'switch' */
#define DUK_HEAP_STRING_SWITCH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SWITCH)
#define DUK_HTHREAD_STRING_SWITCH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SWITCH)
-#define DUK_STRIDX_THIS 135 /* 'this' */
+#define DUK_STRIDX_THIS 140 /* 'this' */
#define DUK_HEAP_STRING_THIS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THIS)
#define DUK_HTHREAD_STRING_THIS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THIS)
-#define DUK_STRIDX_THROW 136 /* 'throw' */
+#define DUK_STRIDX_THROW 141 /* 'throw' */
#define DUK_HEAP_STRING_THROW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THROW)
#define DUK_HTHREAD_STRING_THROW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW)
-#define DUK_STRIDX_TRY 137 /* 'try' */
+#define DUK_STRIDX_TRY 142 /* 'try' */
#define DUK_HEAP_STRING_TRY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRY)
#define DUK_HTHREAD_STRING_TRY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRY)
-#define DUK_STRIDX_TYPEOF 138 /* 'typeof' */
+#define DUK_STRIDX_TYPEOF 143 /* 'typeof' */
#define DUK_HEAP_STRING_TYPEOF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPEOF)
#define DUK_HTHREAD_STRING_TYPEOF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
-#define DUK_STRIDX_VAR 139 /* 'var' */
+#define DUK_STRIDX_VAR 144 /* 'var' */
#define DUK_HEAP_STRING_VAR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR)
#define DUK_HTHREAD_STRING_VAR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR)
-#define DUK_STRIDX_CONST 140 /* 'const' */
+#define DUK_STRIDX_CONST 145 /* 'const' */
#define DUK_HEAP_STRING_CONST(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
#define DUK_HTHREAD_STRING_CONST(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
-#define DUK_STRIDX_VOID 141 /* 'void' */
+#define DUK_STRIDX_VOID 146 /* 'void' */
#define DUK_HEAP_STRING_VOID(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID)
#define DUK_HTHREAD_STRING_VOID(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID)
-#define DUK_STRIDX_WHILE 142 /* 'while' */
+#define DUK_STRIDX_WHILE 147 /* 'while' */
#define DUK_HEAP_STRING_WHILE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
#define DUK_HTHREAD_STRING_WHILE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WHILE)
-#define DUK_STRIDX_WITH 143 /* 'with' */
+#define DUK_STRIDX_WITH 148 /* 'with' */
#define DUK_HEAP_STRING_WITH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WITH)
#define DUK_HTHREAD_STRING_WITH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
-#define DUK_STRIDX_CLASS 144 /* 'class' */
+#define DUK_STRIDX_CLASS 149 /* 'class' */
#define DUK_HEAP_STRING_CLASS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS)
#define DUK_HTHREAD_STRING_CLASS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS)
-#define DUK_STRIDX_ENUM 145 /* 'enum' */
+#define DUK_STRIDX_ENUM 150 /* 'enum' */
#define DUK_HEAP_STRING_ENUM(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM)
#define DUK_HTHREAD_STRING_ENUM(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM)
-#define DUK_STRIDX_EXPORT 146 /* 'export' */
+#define DUK_STRIDX_EXPORT 151 /* 'export' */
#define DUK_HEAP_STRING_EXPORT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
#define DUK_HTHREAD_STRING_EXPORT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORT)
-#define DUK_STRIDX_EXTENDS 147 /* 'extends' */
+#define DUK_STRIDX_EXTENDS 152 /* 'extends' */
#define DUK_HEAP_STRING_EXTENDS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXTENDS)
#define DUK_HTHREAD_STRING_EXTENDS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXTENDS)
-#define DUK_STRIDX_IMPORT 148 /* 'import' */
+#define DUK_STRIDX_IMPORT 153 /* 'import' */
#define DUK_HEAP_STRING_IMPORT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPORT)
#define DUK_HTHREAD_STRING_IMPORT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPORT)
-#define DUK_STRIDX_SUPER 149 /* 'super' */
+#define DUK_STRIDX_SUPER 154 /* 'super' */
#define DUK_HEAP_STRING_SUPER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUPER)
#define DUK_HTHREAD_STRING_SUPER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUPER)
-#define DUK_STRIDX_LC_NULL 150 /* 'null' */
+#define DUK_STRIDX_LC_NULL 155 /* 'null' */
#define DUK_HEAP_STRING_LC_NULL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NULL)
#define DUK_HTHREAD_STRING_LC_NULL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NULL)
-#define DUK_STRIDX_TRUE 151 /* 'true' */
+#define DUK_STRIDX_TRUE 156 /* 'true' */
#define DUK_HEAP_STRING_TRUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRUE)
#define DUK_HTHREAD_STRING_TRUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRUE)
-#define DUK_STRIDX_FALSE 152 /* 'false' */
+#define DUK_STRIDX_FALSE 157 /* 'false' */
#define DUK_HEAP_STRING_FALSE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FALSE)
#define DUK_HTHREAD_STRING_FALSE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FALSE)
-#define DUK_STRIDX_IMPLEMENTS 153 /* 'implements' */
+#define DUK_STRIDX_IMPLEMENTS 158 /* 'implements' */
#define DUK_HEAP_STRING_IMPLEMENTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPLEMENTS)
#define DUK_HTHREAD_STRING_IMPLEMENTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPLEMENTS)
-#define DUK_STRIDX_INTERFACE 154 /* 'interface' */
+#define DUK_STRIDX_INTERFACE 159 /* 'interface' */
#define DUK_HEAP_STRING_INTERFACE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INTERFACE)
#define DUK_HTHREAD_STRING_INTERFACE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INTERFACE)
-#define DUK_STRIDX_LET 155 /* 'let' */
+#define DUK_STRIDX_LET 160 /* 'let' */
#define DUK_HEAP_STRING_LET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LET)
#define DUK_HTHREAD_STRING_LET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LET)
-#define DUK_STRIDX_PACKAGE 156 /* 'package' */
+#define DUK_STRIDX_PACKAGE 161 /* 'package' */
#define DUK_HEAP_STRING_PACKAGE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PACKAGE)
#define DUK_HTHREAD_STRING_PACKAGE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PACKAGE)
-#define DUK_STRIDX_PRIVATE 157 /* 'private' */
+#define DUK_STRIDX_PRIVATE 162 /* 'private' */
#define DUK_HEAP_STRING_PRIVATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PRIVATE)
#define DUK_HTHREAD_STRING_PRIVATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PRIVATE)
-#define DUK_STRIDX_PROTECTED 158 /* 'protected' */
+#define DUK_STRIDX_PROTECTED 163 /* 'protected' */
#define DUK_HEAP_STRING_PROTECTED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTECTED)
#define DUK_HTHREAD_STRING_PROTECTED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTECTED)
-#define DUK_STRIDX_PUBLIC 159 /* 'public' */
+#define DUK_STRIDX_PUBLIC 164 /* 'public' */
#define DUK_HEAP_STRING_PUBLIC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PUBLIC)
#define DUK_HTHREAD_STRING_PUBLIC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PUBLIC)
-#define DUK_STRIDX_STATIC 160 /* 'static' */
+#define DUK_STRIDX_STATIC 165 /* 'static' */
#define DUK_HEAP_STRING_STATIC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STATIC)
#define DUK_HTHREAD_STRING_STATIC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STATIC)
-#define DUK_STRIDX_YIELD 161 /* 'yield' */
+#define DUK_STRIDX_YIELD 166 /* 'yield' */
#define DUK_HEAP_STRING_YIELD(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD)
#define DUK_HTHREAD_STRING_YIELD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD)
-#define DUK_HEAP_NUM_STRINGS 162
-#define DUK_STRIDX_START_RESERVED 117
-#define DUK_STRIDX_START_STRICT_RESERVED 153
-#define DUK_STRIDX_END_RESERVED 162 /* exclusive endpoint */
+#define DUK_HEAP_NUM_STRINGS 167
+#define DUK_STRIDX_START_RESERVED 122
+#define DUK_STRIDX_START_STRICT_RESERVED 158
+#define DUK_STRIDX_END_RESERVED 167 /* exclusive endpoint */
/* To convert a heap stridx to a token number, subtract
* DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
*/
#if !defined(DUK_SINGLE_FILE)
-DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[892];
+DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[972];
#endif /* !DUK_SINGLE_FILE */
-#define DUK_STRDATA_MAX_STRLEN 17
-#define DUK_STRDATA_DATA_LENGTH 892
+#define DUK_STRDATA_MAX_STRLEN 27
+#define DUK_STRDATA_DATA_LENGTH 972
#endif /* DUK_USE_ROM_STRINGS */
#if defined(DUK_USE_ROM_OBJECTS)
@@ -1975,9 +2107,12 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_constructor_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx);
@@ -1985,8 +2120,6 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_eval(duk_context *ctx);
-DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx);
-DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx);
@@ -2020,6 +2153,7 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_hasinstance(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_length(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_name(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx);
@@ -2058,6 +2192,7 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_cont
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_includes(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_number_check_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx);
@@ -2074,6 +2209,7 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_toprimitive(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_tostring(duk_context *ctx);
@@ -2114,6 +2250,9 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_delete_property(duk_context *c
DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_get(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_has(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_set(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_key_for(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_tostring_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_toprimitive(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx);
@@ -2134,13 +2273,15 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_cbor_encode(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_cbor_decode(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encode(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_performance_now(duk_context *ctx);
#if !defined(DUK_SINGLE_FILE)
-DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[176];
+DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[185];
#endif /* !DUK_SINGLE_FILE */
#define DUK_BIDX_GLOBAL 0
#define DUK_BIDX_GLOBAL_ENV 1
@@ -2195,22 +2336,22 @@ DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[176];
#define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE 50
#define DUK_NUM_BUILTINS 51
#define DUK_NUM_BIDX_BUILTINS 51
-#define DUK_NUM_ALL_BUILTINS 76
+#define DUK_NUM_ALL_BUILTINS 80
#if defined(DUK_USE_DOUBLE_LE)
#if !defined(DUK_SINGLE_FILE)
-DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3972];
+DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4281];
#endif /* !DUK_SINGLE_FILE */
-#define DUK_BUILTINS_DATA_LENGTH 3972
+#define DUK_BUILTINS_DATA_LENGTH 4281
#elif defined(DUK_USE_DOUBLE_BE)
#if !defined(DUK_SINGLE_FILE)
-DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3972];
+DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4281];
#endif /* !DUK_SINGLE_FILE */
-#define DUK_BUILTINS_DATA_LENGTH 3972
+#define DUK_BUILTINS_DATA_LENGTH 4281
#elif defined(DUK_USE_DOUBLE_ME)
#if !defined(DUK_SINGLE_FILE)
-DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3972];
+DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4281];
#endif /* !DUK_SINGLE_FILE */
-#define DUK_BUILTINS_DATA_LENGTH 3972
+#define DUK_BUILTINS_DATA_LENGTH 4281
#else
#error invalid endianness defines
#endif
@@ -2225,20 +2366,14 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3972];
#if !defined(DUK_UTIL_H_INCLUDED)
#define DUK_UTIL_H_INCLUDED
-#if defined(DUK_USE_GET_RANDOM_DOUBLE)
-#define DUK_UTIL_GET_RANDOM_DOUBLE(thr) DUK_USE_GET_RANDOM_DOUBLE((thr)->heap_udata)
-#else
-#define DUK_UTIL_GET_RANDOM_DOUBLE(thr) duk_util_tinyrandom_get_double(thr)
-#endif
-
/*
* Some useful constants
*/
-#define DUK_DOUBLE_2TO32 4294967296.0
-#define DUK_DOUBLE_2TO31 2147483648.0
-#define DUK_DOUBLE_LOG2E 1.4426950408889634
-#define DUK_DOUBLE_LOG10E 0.4342944819032518
+#define DUK_DOUBLE_2TO32 4294967296.0
+#define DUK_DOUBLE_2TO31 2147483648.0
+#define DUK_DOUBLE_LOG2E 1.4426950408889634
+#define DUK_DOUBLE_LOG10E 0.4342944819032518
/*
* Endian conversion
@@ -2287,40 +2422,51 @@ struct duk_bitencoder_ctx {
/*
* Raw write/read macros for big endian, unaligned basic values.
- * Caller ensures there's enough space. The macros update the pointer
- * argument automatically on resizes. The idiom seems a bit odd, but
- * leads to compact code.
+ * Caller ensures there's enough space. The INC macro variants
+ * update the pointer argument automatically.
*/
-#define DUK_RAW_WRITE_U8(ptr,val) do { \
- *(ptr)++ = (duk_uint8_t) (val); \
- } while (0)
-#define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be(&(ptr), (duk_uint16_t) (val))
-#define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be(&(ptr), (duk_uint32_t) (val))
-#define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be(&(ptr), (duk_double_t) (val))
-#define DUK_RAW_WRITE_XUTF8(ptr,val) do { \
- /* 'ptr' is evaluated both as LHS and RHS. */ \
- duk_uint8_t *duk__ptr; \
- duk_small_int_t duk__len; \
- duk__ptr = (duk_uint8_t *) (ptr); \
- duk__len = duk_unicode_encode_xutf8((duk_ucodepoint_t) (val), duk__ptr); \
- duk__ptr += duk__len; \
- (ptr) = duk__ptr; \
+#define DUK_RAW_WRITE_U8(ptr, val) \
+ do { \
+ *(ptr) = (duk_uint8_t) (val); \
} while (0)
-#define DUK_RAW_WRITE_CESU8(ptr,val) do { \
- /* 'ptr' is evaluated both as LHS and RHS. */ \
- duk_uint8_t *duk__ptr; \
- duk_small_int_t duk__len; \
- duk__ptr = (duk_uint8_t *) (ptr); \
- duk__len = duk_unicode_encode_cesu8((duk_ucodepoint_t) (val), duk__ptr); \
- duk__ptr += duk__len; \
- (ptr) = duk__ptr; \
+#define DUK_RAW_WRITE_U16_BE(ptr, val) duk_raw_write_u16_be((ptr), (duk_uint16_t) (val))
+#define DUK_RAW_WRITE_U32_BE(ptr, val) duk_raw_write_u32_be((ptr), (duk_uint32_t) (val))
+#define DUK_RAW_WRITE_FLOAT_BE(ptr, val) duk_raw_write_float_be((ptr), (duk_float_t) (val))
+#define DUK_RAW_WRITE_DOUBLE_BE(ptr, val) duk_raw_write_double_be((ptr), (duk_double_t) (val))
+#define DUK_RAW_WRITE_XUTF8(ptr, val) duk_raw_write_xutf8((ptr), (duk_ucodepoint_t) (val))
+
+#define DUK_RAW_WRITEINC_U8(ptr, val) \
+ do { \
+ *(ptr)++ = (duk_uint8_t) (val); \
} while (0)
+#define DUK_RAW_WRITEINC_U16_BE(ptr, val) duk_raw_writeinc_u16_be(&(ptr), (duk_uint16_t) (val))
+#define DUK_RAW_WRITEINC_U32_BE(ptr, val) duk_raw_writeinc_u32_be(&(ptr), (duk_uint32_t) (val))
+#define DUK_RAW_WRITEINC_FLOAT_BE(ptr, val) duk_raw_writeinc_float_be(&(ptr), (duk_float_t) (val))
+#define DUK_RAW_WRITEINC_DOUBLE_BE(ptr, val) duk_raw_writeinc_double_be(&(ptr), (duk_double_t) (val))
+#define DUK_RAW_WRITEINC_XUTF8(ptr, val) duk_raw_writeinc_xutf8(&(ptr), (duk_ucodepoint_t) (val))
+#define DUK_RAW_WRITEINC_CESU8(ptr, val) duk_raw_writeinc_cesu8(&(ptr), (duk_ucodepoint_t) (val))
-#define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)++))
-#define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be(&(ptr));
-#define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be(&(ptr));
-#define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be(&(ptr));
+#define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)))
+#define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be((ptr));
+#define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be((ptr));
+#define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be((ptr));
+
+#define DUK_RAW_READINC_U8(ptr) ((duk_uint8_t) (*(ptr)++))
+#define DUK_RAW_READINC_U16_BE(ptr) duk_raw_readinc_u16_be(&(ptr));
+#define DUK_RAW_READINC_U32_BE(ptr) duk_raw_readinc_u32_be(&(ptr));
+#define DUK_RAW_READINC_DOUBLE_BE(ptr) duk_raw_readinc_double_be(&(ptr));
+
+/*
+ * Double and float byte order operations.
+ */
+
+DUK_INTERNAL_DECL void duk_dblunion_host_to_little(duk_double_union *u);
+DUK_INTERNAL_DECL void duk_dblunion_little_to_host(duk_double_union *u);
+DUK_INTERNAL_DECL void duk_dblunion_host_to_big(duk_double_union *u);
+DUK_INTERNAL_DECL void duk_dblunion_big_to_host(duk_double_union *u);
+DUK_INTERNAL_DECL void duk_fltunion_host_to_big(duk_float_union *u);
+DUK_INTERNAL_DECL void duk_fltunion_big_to_host(duk_float_union *u);
/*
* Buffer writer (dynamic buffer only)
@@ -2355,79 +2501,82 @@ struct duk_bufwriter_ctx {
};
#if defined(DUK_USE_PREFER_SIZE)
-#define DUK_BW_SLACK_ADD 64
-#define DUK_BW_SLACK_SHIFT 4 /* 2^4 -> 1/16 = 6.25% slack */
+#define DUK_BW_SLACK_ADD 64
+#define DUK_BW_SLACK_SHIFT 4 /* 2^4 -> 1/16 = 6.25% slack */
#else
-#define DUK_BW_SLACK_ADD 64
-#define DUK_BW_SLACK_SHIFT 2 /* 2^2 -> 1/4 = 25% slack */
+#define DUK_BW_SLACK_ADD 64
+#define DUK_BW_SLACK_SHIFT 2 /* 2^2 -> 1/4 = 25% slack */
#endif
/* Initialization and finalization (compaction), converting to other types. */
-#define DUK_BW_INIT_PUSHBUF(thr,bw_ctx,sz) do { \
+#define DUK_BW_INIT_PUSHBUF(thr, bw_ctx, sz) \
+ do { \
duk_bw_init_pushbuf((thr), (bw_ctx), (sz)); \
} while (0)
-#define DUK_BW_INIT_WITHBUF(thr,bw_ctx,buf) do { \
+#define DUK_BW_INIT_WITHBUF(thr, bw_ctx, buf) \
+ do { \
duk_bw_init((thr), (bw_ctx), (buf)); \
} while (0)
-#define DUK_BW_COMPACT(thr,bw_ctx) do { \
+#define DUK_BW_COMPACT(thr, bw_ctx) \
+ do { \
/* Make underlying buffer compact to match DUK_BW_GET_SIZE(). */ \
duk_bw_compact((thr), (bw_ctx)); \
} while (0)
-#define DUK_BW_PUSH_AS_STRING(thr,bw_ctx) do { \
- duk_push_lstring((thr), \
- (const char *) (bw_ctx)->p_base, \
- (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
+#define DUK_BW_PUSH_AS_STRING(thr, bw_ctx) \
+ do { \
+ duk_push_lstring((thr), (const char *) (bw_ctx)->p_base, (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
} while (0)
+
/* Pointers may be NULL for a while when 'buf' size is zero and before any
* ENSURE calls have been made. Once an ENSURE has been made, the pointers
* are required to be non-NULL so that it's always valid to use memcpy() and
* memmove(), even for zero size.
*/
-#define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx) \
- DUK_ASSERT_EXPR((bw_ctx) != NULL && \
- (bw_ctx)->buf != NULL && \
- ((DUK_HBUFFER_DYNAMIC_GET_SIZE((bw_ctx)->buf) == 0) || \
- ((bw_ctx)->p != NULL && \
- (bw_ctx)->p_base != NULL && \
- (bw_ctx)->p_limit != NULL && \
- (bw_ctx)->p_limit >= (bw_ctx)->p_base && \
- (bw_ctx)->p >= (bw_ctx)->p_base && \
- (bw_ctx)->p <= (bw_ctx)->p_limit)))
-#define DUK_BW_ASSERT_VALID(thr,bw_ctx) do { \
- DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)); \
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_bw_assert_valid(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
+#define DUK_BW_ASSERT_VALID_EXPR(thr, bw_ctx) (duk_bw_assert_valid((thr), (bw_ctx)))
+#define DUK_BW_ASSERT_VALID(thr, bw_ctx) \
+ do { \
+ duk_bw_assert_valid((thr), (bw_ctx)); \
+ } while (0)
+#else
+#define DUK_BW_ASSERT_VALID_EXPR(thr, bw_ctx) DUK_ASSERT_EXPR(1)
+#define DUK_BW_ASSERT_VALID(thr, bw_ctx) \
+ do { \
} while (0)
+#endif
/* Working with the pointer and current size. */
-#define DUK_BW_GET_PTR(thr,bw_ctx) \
- ((bw_ctx)->p)
-#define DUK_BW_SET_PTR(thr,bw_ctx,ptr) do { \
+#define DUK_BW_GET_PTR(thr, bw_ctx) ((bw_ctx)->p)
+#define DUK_BW_SET_PTR(thr, bw_ctx, ptr) \
+ do { \
(bw_ctx)->p = (ptr); \
} while (0)
-#define DUK_BW_ADD_PTR(thr,bw_ctx,delta) do { \
+#define DUK_BW_ADD_PTR(thr, bw_ctx, delta) \
+ do { \
(bw_ctx)->p += (delta); \
} while (0)
-#define DUK_BW_GET_BASEPTR(thr,bw_ctx) \
- ((bw_ctx)->p_base)
-#define DUK_BW_GET_LIMITPTR(thr,bw_ctx) \
- ((bw_ctx)->p_limit)
-#define DUK_BW_GET_SIZE(thr,bw_ctx) \
- ((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base))
-#define DUK_BW_SET_SIZE(thr,bw_ctx,sz) do { \
+#define DUK_BW_GET_BASEPTR(thr, bw_ctx) ((bw_ctx)->p_base)
+#define DUK_BW_GET_LIMITPTR(thr, bw_ctx) ((bw_ctx)->p_limit)
+#define DUK_BW_GET_SIZE(thr, bw_ctx) ((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base))
+#define DUK_BW_SET_SIZE(thr, bw_ctx, sz) \
+ do { \
DUK_ASSERT((duk_size_t) (sz) <= (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
(bw_ctx)->p = (bw_ctx)->p_base + (sz); \
} while (0)
-#define DUK_BW_RESET_SIZE(thr,bw_ctx) do { \
+#define DUK_BW_RESET_SIZE(thr, bw_ctx) \
+ do { \
/* Reset to zero size, keep current limit. */ \
(bw_ctx)->p = (bw_ctx)->p_base; \
} while (0)
-#define DUK_BW_GET_BUFFER(thr,bw_ctx) \
- ((bw_ctx)->buf)
+#define DUK_BW_GET_BUFFER(thr, bw_ctx) ((bw_ctx)->buf)
/* Ensuring (reserving) space. */
-#define DUK_BW_ENSURE(thr,bw_ctx,sz) do { \
+#define DUK_BW_ENSURE(thr, bw_ctx, sz) \
+ do { \
duk_size_t duk__sz, duk__space; \
DUK_BW_ASSERT_VALID((thr), (bw_ctx)); \
duk__sz = (sz); \
@@ -2438,22 +2587,21 @@ struct duk_bufwriter_ctx {
} while (0)
/* NOTE: Multiple evaluation of 'ptr' in this macro. */
/* XXX: Rework to use an always-inline function? */
-#define DUK_BW_ENSURE_RAW(thr,bw_ctx,sz,ptr) \
- (((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? \
- (ptr) : \
- ((bw_ctx)->p = (ptr), duk_bw_resize((thr),(bw_ctx),(sz))))
-#define DUK_BW_ENSURE_GETPTR(thr,bw_ctx,sz) \
- DUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p)
-#define DUK_BW_ASSERT_SPACE_EXPR(thr,bw_ctx,sz) \
+#define DUK_BW_ENSURE_RAW(thr, bw_ctx, sz, ptr) \
+ (((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? (ptr) : ((bw_ctx)->p = (ptr), duk_bw_resize((thr), (bw_ctx), (sz))))
+#define DUK_BW_ENSURE_GETPTR(thr, bw_ctx, sz) DUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p)
+#define DUK_BW_ASSERT_SPACE_EXPR(thr, bw_ctx, sz) \
(DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)), \
DUK_ASSERT_EXPR((duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p) >= (duk_size_t) (sz)))
-#define DUK_BW_ASSERT_SPACE(thr,bw_ctx,sz) do { \
+#define DUK_BW_ASSERT_SPACE(thr, bw_ctx, sz) \
+ do { \
DUK_BW_ASSERT_SPACE_EXPR((thr), (bw_ctx), (sz)); \
} while (0)
/* Miscellaneous. */
-#define DUK_BW_SETPTR_AND_COMPACT(thr,bw_ctx,ptr) do { \
+#define DUK_BW_SETPTR_AND_COMPACT(thr, bw_ctx, ptr) \
+ do { \
(bw_ctx)->p = (ptr); \
duk_bw_compact((thr), (bw_ctx)); \
} while (0)
@@ -2464,11 +2612,13 @@ struct duk_bufwriter_ctx {
* explicit pointer load/stores get generated (e.g. gcc -Os).
*/
-#define DUK_BW_WRITE_RAW_U8(thr,bw_ctx,val) do { \
+#define DUK_BW_WRITE_RAW_U8(thr, bw_ctx, val) \
+ do { \
DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 1); \
*(bw_ctx)->p++ = (duk_uint8_t) (val); \
} while (0)
-#define DUK_BW_WRITE_RAW_U8_2(thr,bw_ctx,val1,val2) do { \
+#define DUK_BW_WRITE_RAW_U8_2(thr, bw_ctx, val1, val2) \
+ do { \
duk_uint8_t *duk__p; \
DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 2); \
duk__p = (bw_ctx)->p; \
@@ -2476,7 +2626,8 @@ struct duk_bufwriter_ctx {
*duk__p++ = (duk_uint8_t) (val2); \
(bw_ctx)->p = duk__p; \
} while (0)
-#define DUK_BW_WRITE_RAW_U8_3(thr,bw_ctx,val1,val2,val3) do { \
+#define DUK_BW_WRITE_RAW_U8_3(thr, bw_ctx, val1, val2, val3) \
+ do { \
duk_uint8_t *duk__p; \
DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 3); \
duk__p = (bw_ctx)->p; \
@@ -2485,7 +2636,8 @@ struct duk_bufwriter_ctx {
*duk__p++ = (duk_uint8_t) (val3); \
(bw_ctx)->p = duk__p; \
} while (0)
-#define DUK_BW_WRITE_RAW_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
+#define DUK_BW_WRITE_RAW_U8_4(thr, bw_ctx, val1, val2, val3, val4) \
+ do { \
duk_uint8_t *duk__p; \
DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 4); \
duk__p = (bw_ctx)->p; \
@@ -2495,7 +2647,8 @@ struct duk_bufwriter_ctx {
*duk__p++ = (duk_uint8_t) (val4); \
(bw_ctx)->p = duk__p; \
} while (0)
-#define DUK_BW_WRITE_RAW_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
+#define DUK_BW_WRITE_RAW_U8_5(thr, bw_ctx, val1, val2, val3, val4, val5) \
+ do { \
duk_uint8_t *duk__p; \
DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 5); \
duk__p = (bw_ctx)->p; \
@@ -2506,7 +2659,8 @@ struct duk_bufwriter_ctx {
*duk__p++ = (duk_uint8_t) (val5); \
(bw_ctx)->p = duk__p; \
} while (0)
-#define DUK_BW_WRITE_RAW_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
+#define DUK_BW_WRITE_RAW_U8_6(thr, bw_ctx, val1, val2, val3, val4, val5, val6) \
+ do { \
duk_uint8_t *duk__p; \
DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 6); \
duk__p = (bw_ctx)->p; \
@@ -2518,7 +2672,8 @@ struct duk_bufwriter_ctx {
*duk__p++ = (duk_uint8_t) (val6); \
(bw_ctx)->p = duk__p; \
} while (0)
-#define DUK_BW_WRITE_RAW_XUTF8(thr,bw_ctx,cp) do { \
+#define DUK_BW_WRITE_RAW_XUTF8(thr, bw_ctx, cp) \
+ do { \
duk_ucodepoint_t duk__cp; \
duk_small_int_t duk__enc_len; \
duk__cp = (duk_ucodepoint_t) (cp); \
@@ -2526,7 +2681,8 @@ struct duk_bufwriter_ctx {
duk__enc_len = duk_unicode_encode_xutf8(duk__cp, (bw_ctx)->p); \
(bw_ctx)->p += duk__enc_len; \
} while (0)
-#define DUK_BW_WRITE_RAW_CESU8(thr,bw_ctx,cp) do { \
+#define DUK_BW_WRITE_RAW_CESU8(thr, bw_ctx, cp) \
+ do { \
duk_ucodepoint_t duk__cp; \
duk_small_int_t duk__enc_len; \
duk__cp = (duk_ucodepoint_t) (cp); \
@@ -2535,164 +2691,191 @@ struct duk_bufwriter_ctx {
(bw_ctx)->p += duk__enc_len; \
} while (0)
/* XXX: add temporary duk__p pointer here too; sharing */
-#define DUK_BW_WRITE_RAW_BYTES(thr,bw_ctx,valptr,valsz) do { \
+/* XXX: avoid unsafe variants */
+#define DUK_BW_WRITE_RAW_BYTES(thr, bw_ctx, valptr, valsz) \
+ do { \
const void *duk__valptr; \
duk_size_t duk__valsz; \
duk__valptr = (const void *) (valptr); \
duk__valsz = (duk_size_t) (valsz); \
- DUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
+ duk_memcpy_unsafe((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
(bw_ctx)->p += duk__valsz; \
} while (0)
-#define DUK_BW_WRITE_RAW_CSTRING(thr,bw_ctx,val) do { \
+#define DUK_BW_WRITE_RAW_CSTRING(thr, bw_ctx, val) \
+ do { \
const duk_uint8_t *duk__val; \
duk_size_t duk__val_len; \
duk__val = (const duk_uint8_t *) (val); \
duk__val_len = DUK_STRLEN((const char *) duk__val); \
- DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
+ duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
(bw_ctx)->p += duk__val_len; \
} while (0)
-#define DUK_BW_WRITE_RAW_HSTRING(thr,bw_ctx,val) do { \
+#define DUK_BW_WRITE_RAW_HSTRING(thr, bw_ctx, val) \
+ do { \
duk_size_t duk__val_len; \
duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
- DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
+ duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
(bw_ctx)->p += duk__val_len; \
} while (0)
-#define DUK_BW_WRITE_RAW_HBUFFER(thr,bw_ctx,val) do { \
+#define DUK_BW_WRITE_RAW_HBUFFER(thr, bw_ctx, val) \
+ do { \
duk_size_t duk__val_len; \
duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
- DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
+ duk_memcpy_unsafe((void *) ((bw_ctx)->p), \
+ (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), \
+ duk__val_len); \
(bw_ctx)->p += duk__val_len; \
} while (0)
-#define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr,bw_ctx,val) do { \
+#define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr, bw_ctx, val) \
+ do { \
duk_size_t duk__val_len; \
duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
- DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
+ duk_memcpy_unsafe((void *) ((bw_ctx)->p), \
+ (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), \
+ duk__val_len); \
(bw_ctx)->p += duk__val_len; \
} while (0)
-#define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
+#define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr, bw_ctx, val) \
+ do { \
duk_size_t duk__val_len; \
duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
- DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
+ duk_memcpy_unsafe((void *) ((bw_ctx)->p), \
+ (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), \
+ duk__val_len); \
(bw_ctx)->p += duk__val_len; \
} while (0)
/* Append bytes from a slice already in the buffer. */
-#define DUK_BW_WRITE_RAW_SLICE(thr,bw,dst_off,dst_len) \
- duk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len))
+#define DUK_BW_WRITE_RAW_SLICE(thr, bw, dst_off, dst_len) duk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len))
/* Insert bytes in the middle of the buffer from an external buffer. */
-#define DUK_BW_INSERT_RAW_BYTES(thr,bw,dst_off,buf,len) \
- duk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len))
+#define DUK_BW_INSERT_RAW_BYTES(thr, bw, dst_off, buf, len) duk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len))
/* Insert bytes in the middle of the buffer from a slice already
* in the buffer. Source offset is interpreted "before" the operation.
*/
-#define DUK_BW_INSERT_RAW_SLICE(thr,bw,dst_off,src_off,len) \
- duk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len))
+#define DUK_BW_INSERT_RAW_SLICE(thr, bw, dst_off, src_off, len) duk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len))
/* Insert a reserved area somewhere in the buffer; caller fills it.
* Evaluates to a (duk_uint_t *) pointing to the start of the reserved
* area for convenience.
*/
-#define DUK_BW_INSERT_RAW_AREA(thr,bw,off,len) \
- duk_bw_insert_raw_area((thr), (bw), (off), (len))
+#define DUK_BW_INSERT_RAW_AREA(thr, bw, off, len) duk_bw_insert_raw_area((thr), (bw), (off), (len))
/* Remove a slice from inside buffer. */
-#define DUK_BW_REMOVE_RAW_SLICE(thr,bw,off,len) \
- duk_bw_remove_raw_slice((thr), (bw), (off), (len))
+#define DUK_BW_REMOVE_RAW_SLICE(thr, bw, off, len) duk_bw_remove_raw_slice((thr), (bw), (off), (len))
/* Safe write calls which will ensure space first. */
-#define DUK_BW_WRITE_ENSURE_U8(thr,bw_ctx,val) do { \
+#define DUK_BW_WRITE_ENSURE_U8(thr, bw_ctx, val) \
+ do { \
DUK_BW_ENSURE((thr), (bw_ctx), 1); \
DUK_BW_WRITE_RAW_U8((thr), (bw_ctx), (val)); \
} while (0)
-#define DUK_BW_WRITE_ENSURE_U8_2(thr,bw_ctx,val1,val2) do { \
+#define DUK_BW_WRITE_ENSURE_U8_2(thr, bw_ctx, val1, val2) \
+ do { \
DUK_BW_ENSURE((thr), (bw_ctx), 2); \
DUK_BW_WRITE_RAW_U8_2((thr), (bw_ctx), (val1), (val2)); \
} while (0)
-#define DUK_BW_WRITE_ENSURE_U8_3(thr,bw_ctx,val1,val2,val3) do { \
+#define DUK_BW_WRITE_ENSURE_U8_3(thr, bw_ctx, val1, val2, val3) \
+ do { \
DUK_BW_ENSURE((thr), (bw_ctx), 3); \
DUK_BW_WRITE_RAW_U8_3((thr), (bw_ctx), (val1), (val2), (val3)); \
} while (0)
-#define DUK_BW_WRITE_ENSURE_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
+#define DUK_BW_WRITE_ENSURE_U8_4(thr, bw_ctx, val1, val2, val3, val4) \
+ do { \
DUK_BW_ENSURE((thr), (bw_ctx), 4); \
DUK_BW_WRITE_RAW_U8_4((thr), (bw_ctx), (val1), (val2), (val3), (val4)); \
} while (0)
-#define DUK_BW_WRITE_ENSURE_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
+#define DUK_BW_WRITE_ENSURE_U8_5(thr, bw_ctx, val1, val2, val3, val4, val5) \
+ do { \
DUK_BW_ENSURE((thr), (bw_ctx), 5); \
DUK_BW_WRITE_RAW_U8_5((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5)); \
} while (0)
-#define DUK_BW_WRITE_ENSURE_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
+#define DUK_BW_WRITE_ENSURE_U8_6(thr, bw_ctx, val1, val2, val3, val4, val5, val6) \
+ do { \
DUK_BW_ENSURE((thr), (bw_ctx), 6); \
DUK_BW_WRITE_RAW_U8_6((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5), (val6)); \
} while (0)
-#define DUK_BW_WRITE_ENSURE_XUTF8(thr,bw_ctx,cp) do { \
+#define DUK_BW_WRITE_ENSURE_XUTF8(thr, bw_ctx, cp) \
+ do { \
DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_XUTF8_LENGTH); \
DUK_BW_WRITE_RAW_XUTF8((thr), (bw_ctx), (cp)); \
} while (0)
-#define DUK_BW_WRITE_ENSURE_CESU8(thr,bw_ctx,cp) do { \
+#define DUK_BW_WRITE_ENSURE_CESU8(thr, bw_ctx, cp) \
+ do { \
DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_CESU8_LENGTH); \
DUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \
} while (0)
/* XXX: add temporary duk__p pointer here too; sharing */
-#define DUK_BW_WRITE_ENSURE_BYTES(thr,bw_ctx,valptr,valsz) do { \
+/* XXX: avoid unsafe */
+#define DUK_BW_WRITE_ENSURE_BYTES(thr, bw_ctx, valptr, valsz) \
+ do { \
const void *duk__valptr; \
duk_size_t duk__valsz; \
duk__valptr = (const void *) (valptr); \
duk__valsz = (duk_size_t) (valsz); \
DUK_BW_ENSURE((thr), (bw_ctx), duk__valsz); \
- DUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
+ duk_memcpy_unsafe((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
(bw_ctx)->p += duk__valsz; \
} while (0)
-#define DUK_BW_WRITE_ENSURE_CSTRING(thr,bw_ctx,val) do { \
+#define DUK_BW_WRITE_ENSURE_CSTRING(thr, bw_ctx, val) \
+ do { \
const duk_uint8_t *duk__val; \
duk_size_t duk__val_len; \
duk__val = (const duk_uint8_t *) (val); \
duk__val_len = DUK_STRLEN((const char *) duk__val); \
DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
- DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
+ duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
(bw_ctx)->p += duk__val_len; \
} while (0)
-#define DUK_BW_WRITE_ENSURE_HSTRING(thr,bw_ctx,val) do { \
+#define DUK_BW_WRITE_ENSURE_HSTRING(thr, bw_ctx, val) \
+ do { \
duk_size_t duk__val_len; \
duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
- DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
+ duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
(bw_ctx)->p += duk__val_len; \
} while (0)
-#define DUK_BW_WRITE_ENSURE_HBUFFER(thr,bw_ctx,val) do { \
+#define DUK_BW_WRITE_ENSURE_HBUFFER(thr, bw_ctx, val) \
+ do { \
duk_size_t duk__val_len; \
duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
- DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
+ duk_memcpy_unsafe((void *) ((bw_ctx)->p), \
+ (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), \
+ duk__val_len); \
(bw_ctx)->p += duk__val_len; \
} while (0)
-#define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr,bw_ctx,val) do { \
+#define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr, bw_ctx, val) \
+ do { \
duk_size_t duk__val_len; \
duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
- DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
+ duk_memcpy_unsafe((void *) ((bw_ctx)->p), \
+ (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), \
+ duk__val_len); \
(bw_ctx)->p += duk__val_len; \
} while (0)
-#define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
+#define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr, bw_ctx, val) \
+ do { \
duk_size_t duk__val_len; \
duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
- DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
+ duk_memcpy_unsafe((void *) ((bw_ctx)->p), \
+ (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), \
+ duk__val_len); \
(bw_ctx)->p += duk__val_len; \
} while (0)
-#define DUK_BW_WRITE_ENSURE_SLICE(thr,bw,dst_off,dst_len) \
- duk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len))
-#define DUK_BW_INSERT_ENSURE_BYTES(thr,bw,dst_off,buf,len) \
- duk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len))
-#define DUK_BW_INSERT_ENSURE_SLICE(thr,bw,dst_off,src_off,len) \
+#define DUK_BW_WRITE_ENSURE_SLICE(thr, bw, dst_off, dst_len) duk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len))
+#define DUK_BW_INSERT_ENSURE_BYTES(thr, bw, dst_off, buf, len) duk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len))
+#define DUK_BW_INSERT_ENSURE_SLICE(thr, bw, dst_off, src_off, len) \
duk_bw_insert_ensure_slice((thr), (bw), (dst_off), (src_off), (len))
-#define DUK_BW_INSERT_ENSURE_AREA(thr,bw,off,len) \
+#define DUK_BW_INSERT_ENSURE_AREA(thr, bw, off, len) \
/* Evaluates to (duk_uint8_t *) pointing to start of area. */ \
duk_bw_insert_ensure_area((thr), (bw), (off), (len))
-#define DUK_BW_REMOVE_ENSURE_SLICE(thr,bw,off,len) \
+#define DUK_BW_REMOVE_ENSURE_SLICE(thr, bw, off, len) \
/* No difference between raw/ensure because the buffer shrinks. */ \
DUK_BW_REMOVE_RAW_SLICE((thr), (bw), (off), (len))
@@ -2708,17 +2891,13 @@ DUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256];
DUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256];
DUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256];
#endif
-#if defined(DUK_USE_BASE64_FASTPATH)
-DUK_INTERNAL_DECL const duk_uint8_t duk_base64_enctab[64];
-DUK_INTERNAL_DECL const duk_int8_t duk_base64_dectab[256];
-#endif
-#endif /* !DUK_SINGLE_FILE */
+#endif /* !DUK_SINGLE_FILE */
/* Note: assumes that duk_util_probe_steps size is 32 */
#if defined(DUK_USE_HOBJECT_HASH_PART)
#if !defined(DUK_SINGLE_FILE)
DUK_INTERNAL_DECL duk_uint8_t duk_util_probe_steps[32];
-#endif /* !DUK_SINGLE_FILE */
+#endif /* !DUK_SINGLE_FILE */
#endif
#if defined(DUK_USE_STRHASH_DENSE)
@@ -2746,26 +2925,191 @@ DUK_INTERNAL_DECL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx
DUK_INTERNAL_DECL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
DUK_INTERNAL_DECL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len);
DUK_INTERNAL_DECL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len);
-DUK_INTERNAL_DECL void duk_bw_insert_raw_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len);
-DUK_INTERNAL_DECL void duk_bw_insert_ensure_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len);
-DUK_INTERNAL_DECL void duk_bw_insert_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len);
-DUK_INTERNAL_DECL void duk_bw_insert_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len);
+DUK_INTERNAL_DECL void duk_bw_insert_raw_bytes(duk_hthread *thr,
+ duk_bufwriter_ctx *bw,
+ duk_size_t dst_off,
+ const duk_uint8_t *buf,
+ duk_size_t len);
+DUK_INTERNAL_DECL void duk_bw_insert_ensure_bytes(duk_hthread *thr,
+ duk_bufwriter_ctx *bw,
+ duk_size_t dst_off,
+ const duk_uint8_t *buf,
+ duk_size_t len);
+DUK_INTERNAL_DECL void duk_bw_insert_raw_slice(duk_hthread *thr,
+ duk_bufwriter_ctx *bw,
+ duk_size_t dst_off,
+ duk_size_t src_off,
+ duk_size_t len);
+DUK_INTERNAL_DECL void duk_bw_insert_ensure_slice(duk_hthread *thr,
+ duk_bufwriter_ctx *bw,
+ duk_size_t dst_off,
+ duk_size_t src_off,
+ duk_size_t len);
DUK_INTERNAL_DECL duk_uint8_t *duk_bw_insert_raw_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);
DUK_INTERNAL_DECL duk_uint8_t *duk_bw_insert_ensure_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);
DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);
/* No duk_bw_remove_ensure_slice(), functionality would be identical. */
-DUK_INTERNAL_DECL DUK_INLINE duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p);
-DUK_INTERNAL_DECL DUK_INLINE duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p);
-DUK_INTERNAL_DECL DUK_INLINE duk_double_t duk_raw_read_double_be(duk_uint8_t **p);
-DUK_INTERNAL_DECL DUK_INLINE void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val);
-DUK_INTERNAL_DECL DUK_INLINE void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val);
-DUK_INTERNAL_DECL DUK_INLINE void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val);
-
-#if defined(DUK_USE_DEBUGGER_SUPPORT) /* For now only needed by the debugger. */
+DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(const duk_uint8_t *p);
+DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(const duk_uint8_t *p);
+DUK_INTERNAL_DECL duk_float_t duk_raw_read_float_be(const duk_uint8_t *p);
+DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(const duk_uint8_t *p);
+DUK_INTERNAL_DECL duk_uint16_t duk_raw_readinc_u16_be(const duk_uint8_t **p);
+DUK_INTERNAL_DECL duk_uint32_t duk_raw_readinc_u32_be(const duk_uint8_t **p);
+DUK_INTERNAL_DECL duk_float_t duk_raw_readinc_float_be(const duk_uint8_t **p);
+DUK_INTERNAL_DECL duk_double_t duk_raw_readinc_double_be(const duk_uint8_t **p);
+DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t *p, duk_uint16_t val);
+DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t *p, duk_uint32_t val);
+DUK_INTERNAL_DECL void duk_raw_write_float_be(duk_uint8_t *p, duk_float_t val);
+DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t *p, duk_double_t val);
+DUK_INTERNAL_DECL duk_small_int_t duk_raw_write_xutf8(duk_uint8_t *p, duk_ucodepoint_t val);
+DUK_INTERNAL_DECL duk_small_int_t duk_raw_write_cesu8(duk_uint8_t *p, duk_ucodepoint_t val);
+DUK_INTERNAL_DECL void duk_raw_writeinc_u16_be(duk_uint8_t **p, duk_uint16_t val);
+DUK_INTERNAL_DECL void duk_raw_writeinc_u32_be(duk_uint8_t **p, duk_uint32_t val);
+DUK_INTERNAL_DECL void duk_raw_writeinc_float_be(duk_uint8_t **p, duk_float_t val);
+DUK_INTERNAL_DECL void duk_raw_writeinc_double_be(duk_uint8_t **p, duk_double_t val);
+DUK_INTERNAL_DECL void duk_raw_writeinc_xutf8(duk_uint8_t **p, duk_ucodepoint_t val);
+DUK_INTERNAL_DECL void duk_raw_writeinc_cesu8(duk_uint8_t **p, duk_ucodepoint_t val);
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT) /* For now only needed by the debugger. */
DUK_INTERNAL_DECL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len);
#endif
+DUK_INTERNAL_DECL duk_double_t duk_util_get_random_double(duk_hthread *thr);
+
+/* memcpy(), memmove() etc wrappers. The plain variants like duk_memcpy()
+ * assume C99+ and 'src' and 'dst' pointers must be non-NULL even when the
+ * operation size is zero. The unsafe variants like duk_memcpy_safe() deal
+ * with the zero size case explicitly, and allow NULL pointers in that case
+ * (which is undefined behavior in C99+). For the majority of actual targets
+ * a NULL pointer with a zero length is fine in practice. These wrappers are
+ * macros to force inlining; because there are hundreds of call sites, even a
+ * few extra bytes per call site adds up to ~1kB footprint.
+ */
+#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
+#define duk_memcpy(dst, src, len) \
+ do { \
+ void *duk__dst = (dst); \
+ const void *duk__src = (src); \
+ duk_size_t duk__len = (len); \
+ DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
+ DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
+ (void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
+ } while (0)
+#define duk_memcpy_unsafe(dst, src, len) duk_memcpy((dst), (src), (len))
+#define duk_memmove(dst, src, len) \
+ do { \
+ void *duk__dst = (dst); \
+ const void *duk__src = (src); \
+ duk_size_t duk__len = (len); \
+ DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
+ DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
+ (void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
+ } while (0)
+#define duk_memmove_unsafe(dst, src, len) duk_memmove((dst), (src), (len))
+#define duk_memset(dst, val, len) \
+ do { \
+ void *duk__dst = (dst); \
+ duk_small_int_t duk__val = (val); \
+ duk_size_t duk__len = (len); \
+ DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
+ (void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
+ } while (0)
+#define duk_memset_unsafe(dst, val, len) duk_memset((dst), (val), (len))
+#define duk_memzero(dst, len) \
+ do { \
+ void *duk__dst = (dst); \
+ duk_size_t duk__len = (len); \
+ DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
+ (void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
+ } while (0)
+#define duk_memzero_unsafe(dst, len) duk_memzero((dst), (len))
+#else /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
+#define duk_memcpy(dst, src, len) \
+ do { \
+ void *duk__dst = (dst); \
+ const void *duk__src = (src); \
+ duk_size_t duk__len = (len); \
+ DUK_ASSERT(duk__dst != NULL); \
+ DUK_ASSERT(duk__src != NULL); \
+ (void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
+ } while (0)
+#define duk_memcpy_unsafe(dst, src, len) \
+ do { \
+ void *duk__dst = (dst); \
+ const void *duk__src = (src); \
+ duk_size_t duk__len = (len); \
+ DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
+ DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
+ if (DUK_LIKELY(duk__len > 0U)) { \
+ DUK_ASSERT(duk__dst != NULL); \
+ DUK_ASSERT(duk__src != NULL); \
+ (void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
+ } \
+ } while (0)
+#define duk_memmove(dst, src, len) \
+ do { \
+ void *duk__dst = (dst); \
+ const void *duk__src = (src); \
+ duk_size_t duk__len = (len); \
+ DUK_ASSERT(duk__dst != NULL); \
+ DUK_ASSERT(duk__src != NULL); \
+ (void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
+ } while (0)
+#define duk_memmove_unsafe(dst, src, len) \
+ do { \
+ void *duk__dst = (dst); \
+ const void *duk__src = (src); \
+ duk_size_t duk__len = (len); \
+ DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
+ DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
+ if (DUK_LIKELY(duk__len > 0U)) { \
+ DUK_ASSERT(duk__dst != NULL); \
+ DUK_ASSERT(duk__src != NULL); \
+ (void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
+ } \
+ } while (0)
+#define duk_memset(dst, val, len) \
+ do { \
+ void *duk__dst = (dst); \
+ duk_small_int_t duk__val = (val); \
+ duk_size_t duk__len = (len); \
+ DUK_ASSERT(duk__dst != NULL); \
+ (void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
+ } while (0)
+#define duk_memset_unsafe(dst, val, len) \
+ do { \
+ void *duk__dst = (dst); \
+ duk_small_int_t duk__val = (val); \
+ duk_size_t duk__len = (len); \
+ DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
+ if (DUK_LIKELY(duk__len > 0U)) { \
+ DUK_ASSERT(duk__dst != NULL); \
+ (void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
+ } \
+ } while (0)
+#define duk_memzero(dst, len) \
+ do { \
+ void *duk__dst = (dst); \
+ duk_size_t duk__len = (len); \
+ DUK_ASSERT(duk__dst != NULL); \
+ (void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
+ } while (0)
+#define duk_memzero_unsafe(dst, len) \
+ do { \
+ void *duk__dst = (dst); \
+ duk_size_t duk__len = (len); \
+ DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
+ if (DUK_LIKELY(duk__len > 0U)) { \
+ DUK_ASSERT(duk__dst != NULL); \
+ (void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
+ } \
+ } while (0)
+#endif /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
+
+DUK_INTERNAL_DECL duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len);
+DUK_INTERNAL_DECL duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len);
+
DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival);
DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival);
DUK_INTERNAL_DECL duk_bool_t duk_double_is_anyinf(duk_double_t x);
@@ -2780,8 +3124,36 @@ DUK_INTERNAL_DECL duk_double_t duk_double_trunc_towards_zero(duk_double_t x);
DUK_INTERNAL_DECL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y);
DUK_INTERNAL_DECL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y);
DUK_INTERNAL_DECL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y);
+DUK_INTERNAL_DECL duk_bool_t duk_double_is_finite(duk_double_t x);
+DUK_INTERNAL_DECL duk_bool_t duk_double_is_integer(duk_double_t x);
+DUK_INTERNAL_DECL duk_bool_t duk_double_is_safe_integer(duk_double_t x);
+
+DUK_INTERNAL_DECL duk_double_t duk_double_div(duk_double_t x, duk_double_t y);
+DUK_INTERNAL_DECL duk_int_t duk_double_to_int_t(duk_double_t x);
+DUK_INTERNAL_DECL duk_uint_t duk_double_to_uint_t(duk_double_t x);
+DUK_INTERNAL_DECL duk_int32_t duk_double_to_int32_t(duk_double_t x);
+DUK_INTERNAL_DECL duk_uint32_t duk_double_to_uint32_t(duk_double_t x);
+DUK_INTERNAL_DECL duk_float_t duk_double_to_float_t(duk_double_t x);
+DUK_INTERNAL_DECL duk_bool_t duk_double_equals(duk_double_t x, duk_double_t y);
+DUK_INTERNAL_DECL duk_bool_t duk_float_equals(duk_float_t x, duk_float_t y);
+
+/*
+ * Miscellaneous
+ */
+
+/* Example: x = 0x10 = 0b00010000
+ * x - 1 = 0x0f = 0b00001111
+ * x & (x - 1) == 0
+ *
+ * x = 0x07 = 0b00000111
+ * x - 1 = 0x06 = 0b00000110
+ * x & (x - 1) != 0
+ *
+ * However, incorrectly true for x == 0 so check for that explicitly.
+ */
+#define DUK_IS_POWER_OF_TWO(x) ((x) != 0U && ((x) & ((x) -1U)) == 0U)
-#endif /* DUK_UTIL_H_INCLUDED */
+#endif /* DUK_UTIL_H_INCLUDED */
/* #include duk_strings.h */
/*
* Shared string macros.
@@ -2807,152 +3179,154 @@ DUK_INTERNAL_DECL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y);
#define DUK_ERRMSG_H_INCLUDED
/* Mostly API and built-in method related */
-#define DUK_STR_INTERNAL_ERROR "internal error"
-#define DUK_STR_UNSUPPORTED "unsupported"
-#define DUK_STR_INVALID_COUNT "invalid count"
-#define DUK_STR_INVALID_ARGS "invalid args"
-#define DUK_STR_INVALID_STATE "invalid state"
-#define DUK_STR_INVALID_INPUT "invalid input"
-#define DUK_STR_INVALID_LENGTH "invalid length"
-#define DUK_STR_NOT_CONSTRUCTABLE "not constructable"
-#define DUK_STR_CONSTRUCT_ONLY "constructor requires 'new'"
-#define DUK_STR_NOT_CALLABLE "not callable"
-#define DUK_STR_NOT_EXTENSIBLE "not extensible"
-#define DUK_STR_NOT_WRITABLE "not writable"
-#define DUK_STR_NOT_CONFIGURABLE "not configurable"
-#define DUK_STR_INVALID_CONTEXT "invalid context"
-#define DUK_STR_INVALID_INDEX "invalid args"
-#define DUK_STR_PUSH_BEYOND_ALLOC_STACK "cannot push beyond allocated stack"
-#define DUK_STR_NOT_UNDEFINED "unexpected type"
-#define DUK_STR_NOT_NULL "unexpected type"
-#define DUK_STR_NOT_BOOLEAN "unexpected type"
-#define DUK_STR_NOT_NUMBER "unexpected type"
-#define DUK_STR_NOT_STRING "unexpected type"
-#define DUK_STR_NOT_OBJECT "unexpected type"
-#define DUK_STR_NOT_POINTER "unexpected type"
-#define DUK_STR_NOT_BUFFER "not buffer" /* still in use with verbose messages */
-#define DUK_STR_UNEXPECTED_TYPE "unexpected type"
-#define DUK_STR_NOT_THREAD "unexpected type"
-#define DUK_STR_NOT_COMPFUNC "unexpected type"
-#define DUK_STR_NOT_NATFUNC "unexpected type"
-#define DUK_STR_NOT_C_FUNCTION "unexpected type"
-#define DUK_STR_NOT_FUNCTION "unexpected type"
-#define DUK_STR_NOT_REGEXP "unexpected type"
-#define DUK_STR_TOPRIMITIVE_FAILED "coercion to primitive failed"
-#define DUK_STR_NUMBER_OUTSIDE_RANGE "number outside range"
-#define DUK_STR_NOT_OBJECT_COERCIBLE "not object coercible"
-#define DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL "cannot number coerce Symbol"
-#define DUK_STR_CANNOT_STRING_COERCE_SYMBOL "cannot string coerce Symbol"
-#define DUK_STR_STRING_TOO_LONG "string too long"
-#define DUK_STR_BUFFER_TOO_LONG "buffer too long"
-#define DUK_STR_ALLOC_FAILED "alloc failed"
-#define DUK_STR_WRONG_BUFFER_TYPE "wrong buffer type"
-#define DUK_STR_BASE64_ENCODE_FAILED "base64 encode failed"
-#define DUK_STR_SOURCE_DECODE_FAILED "source decode failed"
-#define DUK_STR_UTF8_DECODE_FAILED "utf-8 decode failed"
-#define DUK_STR_BASE64_DECODE_FAILED "base64 decode failed"
-#define DUK_STR_HEX_DECODE_FAILED "hex decode failed"
-#define DUK_STR_INVALID_BYTECODE "invalid bytecode"
-#define DUK_STR_NO_SOURCECODE "no sourcecode"
-#define DUK_STR_RESULT_TOO_LONG "result too long"
-#define DUK_STR_INVALID_CFUNC_RC "invalid C function rc"
-#define DUK_STR_INVALID_INSTANCEOF_RVAL "invalid instanceof rval"
-#define DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO "instanceof rval has no .prototype"
+#define DUK_STR_INTERNAL_ERROR "internal error"
+#define DUK_STR_UNSUPPORTED "unsupported"
+#define DUK_STR_INVALID_COUNT "invalid count"
+#define DUK_STR_INVALID_ARGS "invalid args"
+#define DUK_STR_INVALID_STATE "invalid state"
+#define DUK_STR_INVALID_INPUT "invalid input"
+#define DUK_STR_INVALID_LENGTH "invalid length"
+#define DUK_STR_NOT_CONSTRUCTABLE "not constructable"
+#define DUK_STR_CONSTRUCT_ONLY "constructor requires 'new'"
+#define DUK_STR_NOT_CALLABLE "not callable"
+#define DUK_STR_NOT_EXTENSIBLE "not extensible"
+#define DUK_STR_NOT_WRITABLE "not writable"
+#define DUK_STR_NOT_CONFIGURABLE "not configurable"
+#define DUK_STR_INVALID_CONTEXT "invalid context"
+#define DUK_STR_INVALID_INDEX "invalid args"
+#define DUK_STR_PUSH_BEYOND_ALLOC_STACK "cannot push beyond allocated stack"
+#define DUK_STR_NOT_UNDEFINED "unexpected type"
+#define DUK_STR_NOT_NULL "unexpected type"
+#define DUK_STR_NOT_BOOLEAN "unexpected type"
+#define DUK_STR_NOT_NUMBER "unexpected type"
+#define DUK_STR_NOT_STRING "unexpected type"
+#define DUK_STR_NOT_OBJECT "unexpected type"
+#define DUK_STR_NOT_POINTER "unexpected type"
+#define DUK_STR_NOT_BUFFER "not buffer" /* still in use with verbose messages */
+#define DUK_STR_UNEXPECTED_TYPE "unexpected type"
+#define DUK_STR_NOT_THREAD "unexpected type"
+#define DUK_STR_NOT_COMPFUNC "unexpected type"
+#define DUK_STR_NOT_NATFUNC "unexpected type"
+#define DUK_STR_NOT_C_FUNCTION "unexpected type"
+#define DUK_STR_NOT_FUNCTION "unexpected type"
+#define DUK_STR_NOT_REGEXP "unexpected type"
+#define DUK_STR_TOPRIMITIVE_FAILED "coercion to primitive failed"
+#define DUK_STR_NUMBER_OUTSIDE_RANGE "number outside range"
+#define DUK_STR_NOT_OBJECT_COERCIBLE "not object coercible"
+#define DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL "cannot number coerce Symbol"
+#define DUK_STR_CANNOT_STRING_COERCE_SYMBOL "cannot string coerce Symbol"
+#define DUK_STR_STRING_TOO_LONG "string too long"
+#define DUK_STR_BUFFER_TOO_LONG "buffer too long"
+#define DUK_STR_ALLOC_FAILED "alloc failed"
+#define DUK_STR_WRONG_BUFFER_TYPE "wrong buffer type"
+#define DUK_STR_BASE64_ENCODE_FAILED "base64 encode failed"
+#define DUK_STR_SOURCE_DECODE_FAILED "source decode failed"
+#define DUK_STR_UTF8_DECODE_FAILED "utf-8 decode failed"
+#define DUK_STR_BASE64_DECODE_FAILED "base64 decode failed"
+#define DUK_STR_HEX_DECODE_FAILED "hex decode failed"
+#define DUK_STR_INVALID_BYTECODE "invalid bytecode"
+#define DUK_STR_NO_SOURCECODE "no sourcecode"
+#define DUK_STR_RESULT_TOO_LONG "result too long"
+#define DUK_STR_INVALID_CFUNC_RC "invalid C function rc"
+#define DUK_STR_INVALID_INSTANCEOF_RVAL "invalid instanceof rval"
+#define DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO "instanceof rval has no .prototype"
/* JSON */
-#define DUK_STR_FMT_PTR "%p"
-#define DUK_STR_FMT_INVALID_JSON "invalid json (at offset %ld)"
-#define DUK_STR_JSONDEC_RECLIMIT "json decode recursion limit"
-#define DUK_STR_JSONENC_RECLIMIT "json encode recursion limit"
-#define DUK_STR_CYCLIC_INPUT "cyclic input"
+#define DUK_STR_FMT_PTR "%p"
+#define DUK_STR_FMT_INVALID_JSON "invalid json (at offset %ld)"
+#define DUK_STR_CYCLIC_INPUT "cyclic input"
+
+/* Generic codec */
+#define DUK_STR_DEC_RECLIMIT "decode recursion limit"
+#define DUK_STR_ENC_RECLIMIT "encode recursion limit"
/* Object property access */
-#define DUK_STR_INVALID_BASE "invalid base value"
-#define DUK_STR_STRICT_CALLER_READ "cannot read strict 'caller'"
-#define DUK_STR_PROXY_REJECTED "proxy rejected"
-#define DUK_STR_INVALID_ARRAY_LENGTH "invalid array length"
-#define DUK_STR_SETTER_UNDEFINED "setter undefined"
-#define DUK_STR_INVALID_DESCRIPTOR "invalid descriptor"
+#define DUK_STR_INVALID_BASE "invalid base value"
+#define DUK_STR_STRICT_CALLER_READ "cannot read strict 'caller'"
+#define DUK_STR_PROXY_REJECTED "proxy rejected"
+#define DUK_STR_INVALID_ARRAY_LENGTH "invalid array length"
+#define DUK_STR_SETTER_UNDEFINED "setter undefined"
+#define DUK_STR_INVALID_DESCRIPTOR "invalid descriptor"
/* Proxy */
-#define DUK_STR_PROXY_REVOKED "proxy revoked"
-#define DUK_STR_INVALID_TRAP_RESULT "invalid trap result"
+#define DUK_STR_PROXY_REVOKED "proxy revoked"
+#define DUK_STR_INVALID_TRAP_RESULT "invalid trap result"
/* Variables */
/* Lexer */
-#define DUK_STR_INVALID_ESCAPE "invalid escape"
-#define DUK_STR_UNTERMINATED_STRING "unterminated string"
-#define DUK_STR_UNTERMINATED_COMMENT "unterminated comment"
-#define DUK_STR_UNTERMINATED_REGEXP "unterminated regexp"
-#define DUK_STR_TOKEN_LIMIT "token limit"
-#define DUK_STR_REGEXP_SUPPORT_DISABLED "regexp support disabled"
-#define DUK_STR_INVALID_NUMBER_LITERAL "invalid number literal"
-#define DUK_STR_INVALID_TOKEN "invalid token"
+#define DUK_STR_INVALID_ESCAPE "invalid escape"
+#define DUK_STR_UNTERMINATED_STRING "unterminated string"
+#define DUK_STR_UNTERMINATED_COMMENT "unterminated comment"
+#define DUK_STR_UNTERMINATED_REGEXP "unterminated regexp"
+#define DUK_STR_TOKEN_LIMIT "token limit"
+#define DUK_STR_REGEXP_SUPPORT_DISABLED "regexp support disabled"
+#define DUK_STR_INVALID_NUMBER_LITERAL "invalid number literal"
+#define DUK_STR_INVALID_TOKEN "invalid token"
/* Compiler */
-#define DUK_STR_PARSE_ERROR "parse error"
-#define DUK_STR_DUPLICATE_LABEL "duplicate label"
-#define DUK_STR_INVALID_LABEL "invalid label"
-#define DUK_STR_INVALID_ARRAY_LITERAL "invalid array literal"
-#define DUK_STR_INVALID_OBJECT_LITERAL "invalid object literal"
-#define DUK_STR_INVALID_VAR_DECLARATION "invalid variable declaration"
-#define DUK_STR_CANNOT_DELETE_IDENTIFIER "cannot delete identifier"
-#define DUK_STR_INVALID_EXPRESSION "invalid expression"
-#define DUK_STR_INVALID_LVALUE "invalid lvalue"
-#define DUK_STR_INVALID_NEWTARGET "invalid new.target"
-#define DUK_STR_EXPECTED_IDENTIFIER "expected identifier"
-#define DUK_STR_EMPTY_EXPR_NOT_ALLOWED "empty expression not allowed"
-#define DUK_STR_INVALID_FOR "invalid for statement"
-#define DUK_STR_INVALID_SWITCH "invalid switch statement"
-#define DUK_STR_INVALID_BREAK_CONT_LABEL "invalid break/continue label"
-#define DUK_STR_INVALID_RETURN "invalid return"
-#define DUK_STR_INVALID_TRY "invalid try"
-#define DUK_STR_INVALID_THROW "invalid throw"
-#define DUK_STR_WITH_IN_STRICT_MODE "with in strict mode"
-#define DUK_STR_FUNC_STMT_NOT_ALLOWED "function statement not allowed"
-#define DUK_STR_UNTERMINATED_STMT "unterminated statement"
-#define DUK_STR_INVALID_ARG_NAME "invalid argument name"
-#define DUK_STR_INVALID_FUNC_NAME "invalid function name"
-#define DUK_STR_INVALID_GETSET_NAME "invalid getter/setter name"
-#define DUK_STR_FUNC_NAME_REQUIRED "function name required"
+#define DUK_STR_PARSE_ERROR "parse error"
+#define DUK_STR_DUPLICATE_LABEL "duplicate label"
+#define DUK_STR_INVALID_LABEL "invalid label"
+#define DUK_STR_INVALID_ARRAY_LITERAL "invalid array literal"
+#define DUK_STR_INVALID_OBJECT_LITERAL "invalid object literal"
+#define DUK_STR_INVALID_VAR_DECLARATION "invalid variable declaration"
+#define DUK_STR_CANNOT_DELETE_IDENTIFIER "cannot delete identifier"
+#define DUK_STR_INVALID_EXPRESSION "invalid expression"
+#define DUK_STR_INVALID_LVALUE "invalid lvalue"
+#define DUK_STR_INVALID_NEWTARGET "invalid new.target"
+#define DUK_STR_EXPECTED_IDENTIFIER "expected identifier"
+#define DUK_STR_EMPTY_EXPR_NOT_ALLOWED "empty expression not allowed"
+#define DUK_STR_INVALID_FOR "invalid for statement"
+#define DUK_STR_INVALID_SWITCH "invalid switch statement"
+#define DUK_STR_INVALID_BREAK_CONT_LABEL "invalid break/continue label"
+#define DUK_STR_INVALID_RETURN "invalid return"
+#define DUK_STR_INVALID_TRY "invalid try"
+#define DUK_STR_INVALID_THROW "invalid throw"
+#define DUK_STR_WITH_IN_STRICT_MODE "with in strict mode"
+#define DUK_STR_FUNC_STMT_NOT_ALLOWED "function statement not allowed"
+#define DUK_STR_UNTERMINATED_STMT "unterminated statement"
+#define DUK_STR_INVALID_ARG_NAME "invalid argument name"
+#define DUK_STR_INVALID_FUNC_NAME "invalid function name"
+#define DUK_STR_INVALID_GETSET_NAME "invalid getter/setter name"
+#define DUK_STR_FUNC_NAME_REQUIRED "function name required"
/* RegExp */
-#define DUK_STR_INVALID_QUANTIFIER "invalid regexp quantifier"
-#define DUK_STR_INVALID_QUANTIFIER_NO_ATOM "quantifier without preceding atom"
-#define DUK_STR_INVALID_QUANTIFIER_VALUES "quantifier values invalid (qmin > qmax)"
-#define DUK_STR_QUANTIFIER_TOO_MANY_COPIES "quantifier requires too many atom copies"
-#define DUK_STR_UNEXPECTED_CLOSING_PAREN "unexpected closing parenthesis"
-#define DUK_STR_UNEXPECTED_END_OF_PATTERN "unexpected end of pattern"
-#define DUK_STR_UNEXPECTED_REGEXP_TOKEN "unexpected token in regexp"
-#define DUK_STR_INVALID_REGEXP_FLAGS "invalid regexp flags"
-#define DUK_STR_INVALID_REGEXP_ESCAPE "invalid regexp escape"
-#define DUK_STR_INVALID_BACKREFS "invalid backreference(s)"
-#define DUK_STR_INVALID_REGEXP_CHARACTER "invalid regexp character"
-#define DUK_STR_INVALID_REGEXP_GROUP "invalid regexp group"
-#define DUK_STR_UNTERMINATED_CHARCLASS "unterminated character class"
-#define DUK_STR_INVALID_RANGE "invalid range"
+#define DUK_STR_INVALID_QUANTIFIER "invalid regexp quantifier"
+#define DUK_STR_INVALID_QUANTIFIER_NO_ATOM "quantifier without preceding atom"
+#define DUK_STR_INVALID_QUANTIFIER_VALUES "quantifier values invalid (qmin > qmax)"
+#define DUK_STR_QUANTIFIER_TOO_MANY_COPIES "quantifier requires too many atom copies"
+#define DUK_STR_UNEXPECTED_CLOSING_PAREN "unexpected closing parenthesis"
+#define DUK_STR_UNEXPECTED_END_OF_PATTERN "unexpected end of pattern"
+#define DUK_STR_UNEXPECTED_REGEXP_TOKEN "unexpected token in regexp"
+#define DUK_STR_INVALID_REGEXP_FLAGS "invalid regexp flags"
+#define DUK_STR_INVALID_REGEXP_ESCAPE "invalid regexp escape"
+#define DUK_STR_INVALID_BACKREFS "invalid backreference(s)"
+#define DUK_STR_INVALID_REGEXP_CHARACTER "invalid regexp character"
+#define DUK_STR_INVALID_REGEXP_GROUP "invalid regexp group"
+#define DUK_STR_UNTERMINATED_CHARCLASS "unterminated character class"
+#define DUK_STR_INVALID_RANGE "invalid range"
/* Limits */
-#define DUK_STR_VALSTACK_LIMIT "valstack limit"
-#define DUK_STR_CALLSTACK_LIMIT "callstack limit"
-#define DUK_STR_PROTOTYPE_CHAIN_LIMIT "prototype chain limit"
-#define DUK_STR_BOUND_CHAIN_LIMIT "function call bound chain limit"
-#define DUK_STR_C_CALLSTACK_LIMIT "C call stack depth limit"
-#define DUK_STR_COMPILER_RECURSION_LIMIT "compiler recursion limit"
-#define DUK_STR_BYTECODE_LIMIT "bytecode limit"
-#define DUK_STR_REG_LIMIT "register limit"
-#define DUK_STR_TEMP_LIMIT "temp limit"
-#define DUK_STR_CONST_LIMIT "const limit"
-#define DUK_STR_FUNC_LIMIT "function limit"
-#define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT "regexp compiler recursion limit"
-#define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT "regexp executor recursion limit"
-#define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT "regexp step limit"
-
-#endif /* DUK_ERRMSG_H_INCLUDED */
+#define DUK_STR_VALSTACK_LIMIT "valstack limit"
+#define DUK_STR_CALLSTACK_LIMIT "callstack limit"
+#define DUK_STR_PROTOTYPE_CHAIN_LIMIT "prototype chain limit"
+#define DUK_STR_BOUND_CHAIN_LIMIT "function call bound chain limit"
+#define DUK_STR_NATIVE_STACK_LIMIT "C stack depth limit"
+#define DUK_STR_COMPILER_RECURSION_LIMIT "compiler recursion limit"
+#define DUK_STR_BYTECODE_LIMIT "bytecode limit"
+#define DUK_STR_REG_LIMIT "register limit"
+#define DUK_STR_TEMP_LIMIT "temp limit"
+#define DUK_STR_CONST_LIMIT "const limit"
+#define DUK_STR_FUNC_LIMIT "function limit"
+#define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT "regexp compiler recursion limit"
+#define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT "regexp executor recursion limit"
+#define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT "regexp step limit"
+
+#endif /* DUK_ERRMSG_H_INCLUDED */
/* #include duk_js_bytecode.h */
/*
- * Ecmascript bytecode
+ * ECMAScript bytecode
*/
#if !defined(DUK_JS_BYTECODE_H_INCLUDED)
@@ -3036,403 +3410,394 @@ DUK_INTERNAL_DECL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y);
typedef duk_uint32_t duk_instr_t;
-#define DUK_BC_SHIFT_OP 0
-#define DUK_BC_SHIFT_A 8
-#define DUK_BC_SHIFT_B 16
-#define DUK_BC_SHIFT_C 24
-#define DUK_BC_SHIFT_BC DUK_BC_SHIFT_B
-#define DUK_BC_SHIFT_ABC DUK_BC_SHIFT_A
-
-#define DUK_BC_UNSHIFTED_MASK_OP 0xffUL
-#define DUK_BC_UNSHIFTED_MASK_A 0xffUL
-#define DUK_BC_UNSHIFTED_MASK_B 0xffUL
-#define DUK_BC_UNSHIFTED_MASK_C 0xffUL
-#define DUK_BC_UNSHIFTED_MASK_BC 0xffffUL
-#define DUK_BC_UNSHIFTED_MASK_ABC 0xffffffUL
-
-#define DUK_BC_SHIFTED_MASK_OP (DUK_BC_UNSHIFTED_MASK_OP << DUK_BC_SHIFT_OP)
-#define DUK_BC_SHIFTED_MASK_A (DUK_BC_UNSHIFTED_MASK_A << DUK_BC_SHIFT_A)
-#define DUK_BC_SHIFTED_MASK_B (DUK_BC_UNSHIFTED_MASK_B << DUK_BC_SHIFT_B)
-#define DUK_BC_SHIFTED_MASK_C (DUK_BC_UNSHIFTED_MASK_C << DUK_BC_SHIFT_C)
-#define DUK_BC_SHIFTED_MASK_BC (DUK_BC_UNSHIFTED_MASK_BC << DUK_BC_SHIFT_BC)
-#define DUK_BC_SHIFTED_MASK_ABC (DUK_BC_UNSHIFTED_MASK_ABC << DUK_BC_SHIFT_ABC)
-
-#define DUK_DEC_OP(x) ((x) & 0xffUL)
-#define DUK_DEC_A(x) (((x) >> 8) & 0xffUL)
-#define DUK_DEC_B(x) (((x) >> 16) & 0xffUL)
-#define DUK_DEC_C(x) (((x) >> 24) & 0xffUL)
-#define DUK_DEC_BC(x) (((x) >> 16) & 0xffffUL)
-#define DUK_DEC_ABC(x) (((x) >> 8) & 0xffffffUL)
-
-#define DUK_ENC_OP(op) ((duk_instr_t) (op))
-#define DUK_ENC_OP_ABC(op,abc) ((duk_instr_t) ( \
- (((duk_instr_t) (abc)) << 8) | \
- ((duk_instr_t) (op)) \
- ))
-#define DUK_ENC_OP_A_BC(op,a,bc) ((duk_instr_t) ( \
- (((duk_instr_t) (bc)) << 16) | \
- (((duk_instr_t) (a)) << 8) | \
- ((duk_instr_t) (op)) \
- ))
-#define DUK_ENC_OP_A_B_C(op,a,b,c) ((duk_instr_t) ( \
- (((duk_instr_t) (c)) << 24) | \
- (((duk_instr_t) (b)) << 16) | \
- (((duk_instr_t) (a)) << 8) | \
- ((duk_instr_t) (op)) \
- ))
-#define DUK_ENC_OP_A_B(op,a,b) DUK_ENC_OP_A_B_C((op),(a),(b),0)
-#define DUK_ENC_OP_A(op,a) DUK_ENC_OP_A_B_C((op),(a),0,0)
-#define DUK_ENC_OP_BC(op,bc) DUK_ENC_OP_A_BC((op),0,(bc))
+#define DUK_BC_SHIFT_OP 0
+#define DUK_BC_SHIFT_A 8
+#define DUK_BC_SHIFT_B 16
+#define DUK_BC_SHIFT_C 24
+#define DUK_BC_SHIFT_BC DUK_BC_SHIFT_B
+#define DUK_BC_SHIFT_ABC DUK_BC_SHIFT_A
+
+#define DUK_BC_UNSHIFTED_MASK_OP 0xffUL
+#define DUK_BC_UNSHIFTED_MASK_A 0xffUL
+#define DUK_BC_UNSHIFTED_MASK_B 0xffUL
+#define DUK_BC_UNSHIFTED_MASK_C 0xffUL
+#define DUK_BC_UNSHIFTED_MASK_BC 0xffffUL
+#define DUK_BC_UNSHIFTED_MASK_ABC 0xffffffUL
+
+#define DUK_BC_SHIFTED_MASK_OP (DUK_BC_UNSHIFTED_MASK_OP << DUK_BC_SHIFT_OP)
+#define DUK_BC_SHIFTED_MASK_A (DUK_BC_UNSHIFTED_MASK_A << DUK_BC_SHIFT_A)
+#define DUK_BC_SHIFTED_MASK_B (DUK_BC_UNSHIFTED_MASK_B << DUK_BC_SHIFT_B)
+#define DUK_BC_SHIFTED_MASK_C (DUK_BC_UNSHIFTED_MASK_C << DUK_BC_SHIFT_C)
+#define DUK_BC_SHIFTED_MASK_BC (DUK_BC_UNSHIFTED_MASK_BC << DUK_BC_SHIFT_BC)
+#define DUK_BC_SHIFTED_MASK_ABC (DUK_BC_UNSHIFTED_MASK_ABC << DUK_BC_SHIFT_ABC)
+
+#define DUK_DEC_OP(x) ((x) &0xffUL)
+#define DUK_DEC_A(x) (((x) >> 8) & 0xffUL)
+#define DUK_DEC_B(x) (((x) >> 16) & 0xffUL)
+#define DUK_DEC_C(x) (((x) >> 24) & 0xffUL)
+#define DUK_DEC_BC(x) (((x) >> 16) & 0xffffUL)
+#define DUK_DEC_ABC(x) (((x) >> 8) & 0xffffffUL)
+
+#define DUK_ENC_OP(op) ((duk_instr_t) (op))
+#define DUK_ENC_OP_ABC(op, abc) ((duk_instr_t) ((((duk_instr_t) (abc)) << 8) | ((duk_instr_t) (op))))
+#define DUK_ENC_OP_A_BC(op, a, bc) \
+ ((duk_instr_t) ((((duk_instr_t) (bc)) << 16) | (((duk_instr_t) (a)) << 8) | ((duk_instr_t) (op))))
+#define DUK_ENC_OP_A_B_C(op, a, b, c) \
+ ((duk_instr_t) ((((duk_instr_t) (c)) << 24) | (((duk_instr_t) (b)) << 16) | (((duk_instr_t) (a)) << 8) | \
+ ((duk_instr_t) (op))))
+#define DUK_ENC_OP_A_B(op, a, b) DUK_ENC_OP_A_B_C((op), (a), (b), 0)
+#define DUK_ENC_OP_A(op, a) DUK_ENC_OP_A_B_C((op), (a), 0, 0)
+#define DUK_ENC_OP_BC(op, bc) DUK_ENC_OP_A_BC((op), 0, (bc))
/* Get opcode base value with B/C reg/const flags cleared. */
-#define DUK_BC_NOREGCONST_OP(op) ((op) & 0xfc)
+#define DUK_BC_NOREGCONST_OP(op) ((op) &0xfc)
/* Constants should be signed so that signed arithmetic involving them
* won't cause values to be coerced accidentally to unsigned.
*/
-#define DUK_BC_OP_MIN 0
-#define DUK_BC_OP_MAX 0xffL
-#define DUK_BC_A_MIN 0
-#define DUK_BC_A_MAX 0xffL
-#define DUK_BC_B_MIN 0
-#define DUK_BC_B_MAX 0xffL
-#define DUK_BC_C_MIN 0
-#define DUK_BC_C_MAX 0xffL
-#define DUK_BC_BC_MIN 0
-#define DUK_BC_BC_MAX 0xffffL
-#define DUK_BC_ABC_MIN 0
-#define DUK_BC_ABC_MAX 0xffffffL
+#define DUK_BC_OP_MIN 0
+#define DUK_BC_OP_MAX 0xffL
+#define DUK_BC_A_MIN 0
+#define DUK_BC_A_MAX 0xffL
+#define DUK_BC_B_MIN 0
+#define DUK_BC_B_MAX 0xffL
+#define DUK_BC_C_MIN 0
+#define DUK_BC_C_MAX 0xffL
+#define DUK_BC_BC_MIN 0
+#define DUK_BC_BC_MAX 0xffffL
+#define DUK_BC_ABC_MIN 0
+#define DUK_BC_ABC_MAX 0xffffffL
/* Masks for B/C reg/const indicator in opcode field. */
-#define DUK_BC_REGCONST_B (0x01UL)
-#define DUK_BC_REGCONST_C (0x02UL)
+#define DUK_BC_REGCONST_B (0x01UL)
+#define DUK_BC_REGCONST_C (0x02UL)
/* Misc. masks for opcode field. */
-#define DUK_BC_INCDECP_FLAG_DEC (0x04UL)
-#define DUK_BC_INCDECP_FLAG_POST (0x08UL)
+#define DUK_BC_INCDECP_FLAG_DEC (0x04UL)
+#define DUK_BC_INCDECP_FLAG_POST (0x08UL)
/* Opcodes. */
-#define DUK_OP_LDREG 0
-#define DUK_OP_STREG 1
-#define DUK_OP_JUMP 2
-#define DUK_OP_LDCONST 3
-#define DUK_OP_LDINT 4
-#define DUK_OP_LDINTX 5
-#define DUK_OP_LDTHIS 6
-#define DUK_OP_LDUNDEF 7
-#define DUK_OP_LDNULL 8
-#define DUK_OP_LDTRUE 9
-#define DUK_OP_LDFALSE 10
-#define DUK_OP_GETVAR 11
-#define DUK_OP_BNOT 12
-#define DUK_OP_LNOT 13
-#define DUK_OP_UNM 14
-#define DUK_OP_UNP 15
-#define DUK_OP_EQ 16
-#define DUK_OP_EQ_RR 16
-#define DUK_OP_EQ_CR 17
-#define DUK_OP_EQ_RC 18
-#define DUK_OP_EQ_CC 19
-#define DUK_OP_NEQ 20
-#define DUK_OP_NEQ_RR 20
-#define DUK_OP_NEQ_CR 21
-#define DUK_OP_NEQ_RC 22
-#define DUK_OP_NEQ_CC 23
-#define DUK_OP_SEQ 24
-#define DUK_OP_SEQ_RR 24
-#define DUK_OP_SEQ_CR 25
-#define DUK_OP_SEQ_RC 26
-#define DUK_OP_SEQ_CC 27
-#define DUK_OP_SNEQ 28
-#define DUK_OP_SNEQ_RR 28
-#define DUK_OP_SNEQ_CR 29
-#define DUK_OP_SNEQ_RC 30
-#define DUK_OP_SNEQ_CC 31
-#define DUK_OP_GT 32
-#define DUK_OP_GT_RR 32
-#define DUK_OP_GT_CR 33
-#define DUK_OP_GT_RC 34
-#define DUK_OP_GT_CC 35
-#define DUK_OP_GE 36
-#define DUK_OP_GE_RR 36
-#define DUK_OP_GE_CR 37
-#define DUK_OP_GE_RC 38
-#define DUK_OP_GE_CC 39
-#define DUK_OP_LT 40
-#define DUK_OP_LT_RR 40
-#define DUK_OP_LT_CR 41
-#define DUK_OP_LT_RC 42
-#define DUK_OP_LT_CC 43
-#define DUK_OP_LE 44
-#define DUK_OP_LE_RR 44
-#define DUK_OP_LE_CR 45
-#define DUK_OP_LE_RC 46
-#define DUK_OP_LE_CC 47
-#define DUK_OP_IFTRUE 48
-#define DUK_OP_IFTRUE_R 48
-#define DUK_OP_IFTRUE_C 49
-#define DUK_OP_IFFALSE 50
-#define DUK_OP_IFFALSE_R 50
-#define DUK_OP_IFFALSE_C 51
-#define DUK_OP_ADD 52
-#define DUK_OP_ADD_RR 52
-#define DUK_OP_ADD_CR 53
-#define DUK_OP_ADD_RC 54
-#define DUK_OP_ADD_CC 55
-#define DUK_OP_SUB 56
-#define DUK_OP_SUB_RR 56
-#define DUK_OP_SUB_CR 57
-#define DUK_OP_SUB_RC 58
-#define DUK_OP_SUB_CC 59
-#define DUK_OP_MUL 60
-#define DUK_OP_MUL_RR 60
-#define DUK_OP_MUL_CR 61
-#define DUK_OP_MUL_RC 62
-#define DUK_OP_MUL_CC 63
-#define DUK_OP_DIV 64
-#define DUK_OP_DIV_RR 64
-#define DUK_OP_DIV_CR 65
-#define DUK_OP_DIV_RC 66
-#define DUK_OP_DIV_CC 67
-#define DUK_OP_MOD 68
-#define DUK_OP_MOD_RR 68
-#define DUK_OP_MOD_CR 69
-#define DUK_OP_MOD_RC 70
-#define DUK_OP_MOD_CC 71
-#define DUK_OP_EXP 72
-#define DUK_OP_EXP_RR 72
-#define DUK_OP_EXP_CR 73
-#define DUK_OP_EXP_RC 74
-#define DUK_OP_EXP_CC 75
-#define DUK_OP_BAND 76
-#define DUK_OP_BAND_RR 76
-#define DUK_OP_BAND_CR 77
-#define DUK_OP_BAND_RC 78
-#define DUK_OP_BAND_CC 79
-#define DUK_OP_BOR 80
-#define DUK_OP_BOR_RR 80
-#define DUK_OP_BOR_CR 81
-#define DUK_OP_BOR_RC 82
-#define DUK_OP_BOR_CC 83
-#define DUK_OP_BXOR 84
-#define DUK_OP_BXOR_RR 84
-#define DUK_OP_BXOR_CR 85
-#define DUK_OP_BXOR_RC 86
-#define DUK_OP_BXOR_CC 87
-#define DUK_OP_BASL 88
-#define DUK_OP_BASL_RR 88
-#define DUK_OP_BASL_CR 89
-#define DUK_OP_BASL_RC 90
-#define DUK_OP_BASL_CC 91
-#define DUK_OP_BLSR 92
-#define DUK_OP_BLSR_RR 92
-#define DUK_OP_BLSR_CR 93
-#define DUK_OP_BLSR_RC 94
-#define DUK_OP_BLSR_CC 95
-#define DUK_OP_BASR 96
-#define DUK_OP_BASR_RR 96
-#define DUK_OP_BASR_CR 97
-#define DUK_OP_BASR_RC 98
-#define DUK_OP_BASR_CC 99
-#define DUK_OP_INSTOF 100
-#define DUK_OP_INSTOF_RR 100
-#define DUK_OP_INSTOF_CR 101
-#define DUK_OP_INSTOF_RC 102
-#define DUK_OP_INSTOF_CC 103
-#define DUK_OP_IN 104
-#define DUK_OP_IN_RR 104
-#define DUK_OP_IN_CR 105
-#define DUK_OP_IN_RC 106
-#define DUK_OP_IN_CC 107
-#define DUK_OP_GETPROP 108
-#define DUK_OP_GETPROP_RR 108
-#define DUK_OP_GETPROP_CR 109
-#define DUK_OP_GETPROP_RC 110
-#define DUK_OP_GETPROP_CC 111
-#define DUK_OP_PUTPROP 112
-#define DUK_OP_PUTPROP_RR 112
-#define DUK_OP_PUTPROP_CR 113
-#define DUK_OP_PUTPROP_RC 114
-#define DUK_OP_PUTPROP_CC 115
-#define DUK_OP_DELPROP 116
-#define DUK_OP_DELPROP_RR 116
-#define DUK_OP_DELPROP_CR_UNUSED 117 /* unused now */
-#define DUK_OP_DELPROP_RC 118
-#define DUK_OP_DELPROP_CC_UNUSED 119 /* unused now */
-#define DUK_OP_PREINCR 120 /* pre/post opcode values have constraints, */
-#define DUK_OP_PREDECR 121 /* see duk_js_executor.c and duk_js_compiler.c. */
-#define DUK_OP_POSTINCR 122
-#define DUK_OP_POSTDECR 123
-#define DUK_OP_PREINCV 124
-#define DUK_OP_PREDECV 125
-#define DUK_OP_POSTINCV 126
-#define DUK_OP_POSTDECV 127
-#define DUK_OP_PREINCP 128 /* pre/post inc/dec prop opcodes have constraints */
-#define DUK_OP_PREINCP_RR 128
-#define DUK_OP_PREINCP_CR 129
-#define DUK_OP_PREINCP_RC 130
-#define DUK_OP_PREINCP_CC 131
-#define DUK_OP_PREDECP 132
-#define DUK_OP_PREDECP_RR 132
-#define DUK_OP_PREDECP_CR 133
-#define DUK_OP_PREDECP_RC 134
-#define DUK_OP_PREDECP_CC 135
-#define DUK_OP_POSTINCP 136
-#define DUK_OP_POSTINCP_RR 136
-#define DUK_OP_POSTINCP_CR 137
-#define DUK_OP_POSTINCP_RC 138
-#define DUK_OP_POSTINCP_CC 139
-#define DUK_OP_POSTDECP 140
-#define DUK_OP_POSTDECP_RR 140
-#define DUK_OP_POSTDECP_CR 141
-#define DUK_OP_POSTDECP_RC 142
-#define DUK_OP_POSTDECP_CC 143
-#define DUK_OP_DECLVAR 144
-#define DUK_OP_DECLVAR_RR 144
-#define DUK_OP_DECLVAR_CR 145
-#define DUK_OP_DECLVAR_RC 146
-#define DUK_OP_DECLVAR_CC 147
-#define DUK_OP_REGEXP 148
-#define DUK_OP_REGEXP_RR 148
-#define DUK_OP_REGEXP_CR 149
-#define DUK_OP_REGEXP_RC 150
-#define DUK_OP_REGEXP_CC 151
-#define DUK_OP_CLOSURE 152
-#define DUK_OP_TYPEOF 153
-#define DUK_OP_TYPEOFID 154
-#define DUK_OP_PUTVAR 155
-#define DUK_OP_DELVAR 156
-#define DUK_OP_RETREG 157
-#define DUK_OP_RETUNDEF 158
-#define DUK_OP_RETCONST 159
-#define DUK_OP_RETCONSTN 160 /* return const without incref (e.g. number) */
-#define DUK_OP_LABEL 161
-#define DUK_OP_ENDLABEL 162
-#define DUK_OP_BREAK 163
-#define DUK_OP_CONTINUE 164
-#define DUK_OP_TRYCATCH 165
-#define DUK_OP_ENDTRY 166
-#define DUK_OP_ENDCATCH 167
-#define DUK_OP_ENDFIN 168
-#define DUK_OP_THROW 169
-#define DUK_OP_INVLHS 170
-#define DUK_OP_CSREG 171
-#define DUK_OP_CSVAR 172
-#define DUK_OP_CSVAR_RR 172
-#define DUK_OP_CSVAR_CR 173
-#define DUK_OP_CSVAR_RC 174
-#define DUK_OP_CSVAR_CC 175
-#define DUK_OP_CALL0 176 /* DUK_OP_CALL0 & 0x0F must be zero. */
-#define DUK_OP_CALL1 177
-#define DUK_OP_CALL2 178
-#define DUK_OP_CALL3 179
-#define DUK_OP_CALL4 180
-#define DUK_OP_CALL5 181
-#define DUK_OP_CALL6 182
-#define DUK_OP_CALL7 183
-#define DUK_OP_CALL8 184
-#define DUK_OP_CALL9 185
-#define DUK_OP_CALL10 186
-#define DUK_OP_CALL11 187
-#define DUK_OP_CALL12 188
-#define DUK_OP_CALL13 189
-#define DUK_OP_CALL14 190
-#define DUK_OP_CALL15 191
-#define DUK_OP_NEWOBJ 192
-#define DUK_OP_NEWARR 193
-#define DUK_OP_MPUTOBJ 194
-#define DUK_OP_MPUTOBJI 195
-#define DUK_OP_INITSET 196
-#define DUK_OP_INITGET 197
-#define DUK_OP_MPUTARR 198
-#define DUK_OP_MPUTARRI 199
-#define DUK_OP_SETALEN 200
-#define DUK_OP_INITENUM 201
-#define DUK_OP_NEXTENUM 202
-#define DUK_OP_NEWTARGET 203
-#define DUK_OP_DEBUGGER 204
-#define DUK_OP_NOP 205
-#define DUK_OP_INVALID 206
-#define DUK_OP_UNUSED207 207
-#define DUK_OP_GETPROPC 208
-#define DUK_OP_GETPROPC_RR 208
-#define DUK_OP_GETPROPC_CR 209
-#define DUK_OP_GETPROPC_RC 210
-#define DUK_OP_GETPROPC_CC 211
-#define DUK_OP_UNUSED212 212
-#define DUK_OP_UNUSED213 213
-#define DUK_OP_UNUSED214 214
-#define DUK_OP_UNUSED215 215
-#define DUK_OP_UNUSED216 216
-#define DUK_OP_UNUSED217 217
-#define DUK_OP_UNUSED218 218
-#define DUK_OP_UNUSED219 219
-#define DUK_OP_UNUSED220 220
-#define DUK_OP_UNUSED221 221
-#define DUK_OP_UNUSED222 222
-#define DUK_OP_UNUSED223 223
-#define DUK_OP_UNUSED224 224
-#define DUK_OP_UNUSED225 225
-#define DUK_OP_UNUSED226 226
-#define DUK_OP_UNUSED227 227
-#define DUK_OP_UNUSED228 228
-#define DUK_OP_UNUSED229 229
-#define DUK_OP_UNUSED230 230
-#define DUK_OP_UNUSED231 231
-#define DUK_OP_UNUSED232 232
-#define DUK_OP_UNUSED233 233
-#define DUK_OP_UNUSED234 234
-#define DUK_OP_UNUSED235 235
-#define DUK_OP_UNUSED236 236
-#define DUK_OP_UNUSED237 237
-#define DUK_OP_UNUSED238 238
-#define DUK_OP_UNUSED239 239
-#define DUK_OP_UNUSED240 240
-#define DUK_OP_UNUSED241 241
-#define DUK_OP_UNUSED242 242
-#define DUK_OP_UNUSED243 243
-#define DUK_OP_UNUSED244 244
-#define DUK_OP_UNUSED245 245
-#define DUK_OP_UNUSED246 246
-#define DUK_OP_UNUSED247 247
-#define DUK_OP_UNUSED248 248
-#define DUK_OP_UNUSED249 249
-#define DUK_OP_UNUSED250 250
-#define DUK_OP_UNUSED251 251
-#define DUK_OP_UNUSED252 252
-#define DUK_OP_UNUSED253 253
-#define DUK_OP_UNUSED254 254
-#define DUK_OP_UNUSED255 255
-#define DUK_OP_NONE 256 /* dummy value used as marker (doesn't fit in 8-bit field) */
+#define DUK_OP_LDREG 0
+#define DUK_OP_STREG 1
+#define DUK_OP_JUMP 2
+#define DUK_OP_LDCONST 3
+#define DUK_OP_LDINT 4
+#define DUK_OP_LDINTX 5
+#define DUK_OP_LDTHIS 6
+#define DUK_OP_LDUNDEF 7
+#define DUK_OP_LDNULL 8
+#define DUK_OP_LDTRUE 9
+#define DUK_OP_LDFALSE 10
+#define DUK_OP_GETVAR 11
+#define DUK_OP_BNOT 12
+#define DUK_OP_LNOT 13
+#define DUK_OP_UNM 14
+#define DUK_OP_UNP 15
+#define DUK_OP_EQ 16
+#define DUK_OP_EQ_RR 16
+#define DUK_OP_EQ_CR 17
+#define DUK_OP_EQ_RC 18
+#define DUK_OP_EQ_CC 19
+#define DUK_OP_NEQ 20
+#define DUK_OP_NEQ_RR 20
+#define DUK_OP_NEQ_CR 21
+#define DUK_OP_NEQ_RC 22
+#define DUK_OP_NEQ_CC 23
+#define DUK_OP_SEQ 24
+#define DUK_OP_SEQ_RR 24
+#define DUK_OP_SEQ_CR 25
+#define DUK_OP_SEQ_RC 26
+#define DUK_OP_SEQ_CC 27
+#define DUK_OP_SNEQ 28
+#define DUK_OP_SNEQ_RR 28
+#define DUK_OP_SNEQ_CR 29
+#define DUK_OP_SNEQ_RC 30
+#define DUK_OP_SNEQ_CC 31
+#define DUK_OP_GT 32
+#define DUK_OP_GT_RR 32
+#define DUK_OP_GT_CR 33
+#define DUK_OP_GT_RC 34
+#define DUK_OP_GT_CC 35
+#define DUK_OP_GE 36
+#define DUK_OP_GE_RR 36
+#define DUK_OP_GE_CR 37
+#define DUK_OP_GE_RC 38
+#define DUK_OP_GE_CC 39
+#define DUK_OP_LT 40
+#define DUK_OP_LT_RR 40
+#define DUK_OP_LT_CR 41
+#define DUK_OP_LT_RC 42
+#define DUK_OP_LT_CC 43
+#define DUK_OP_LE 44
+#define DUK_OP_LE_RR 44
+#define DUK_OP_LE_CR 45
+#define DUK_OP_LE_RC 46
+#define DUK_OP_LE_CC 47
+#define DUK_OP_IFTRUE 48
+#define DUK_OP_IFTRUE_R 48
+#define DUK_OP_IFTRUE_C 49
+#define DUK_OP_IFFALSE 50
+#define DUK_OP_IFFALSE_R 50
+#define DUK_OP_IFFALSE_C 51
+#define DUK_OP_ADD 52
+#define DUK_OP_ADD_RR 52
+#define DUK_OP_ADD_CR 53
+#define DUK_OP_ADD_RC 54
+#define DUK_OP_ADD_CC 55
+#define DUK_OP_SUB 56
+#define DUK_OP_SUB_RR 56
+#define DUK_OP_SUB_CR 57
+#define DUK_OP_SUB_RC 58
+#define DUK_OP_SUB_CC 59
+#define DUK_OP_MUL 60
+#define DUK_OP_MUL_RR 60
+#define DUK_OP_MUL_CR 61
+#define DUK_OP_MUL_RC 62
+#define DUK_OP_MUL_CC 63
+#define DUK_OP_DIV 64
+#define DUK_OP_DIV_RR 64
+#define DUK_OP_DIV_CR 65
+#define DUK_OP_DIV_RC 66
+#define DUK_OP_DIV_CC 67
+#define DUK_OP_MOD 68
+#define DUK_OP_MOD_RR 68
+#define DUK_OP_MOD_CR 69
+#define DUK_OP_MOD_RC 70
+#define DUK_OP_MOD_CC 71
+#define DUK_OP_EXP 72
+#define DUK_OP_EXP_RR 72
+#define DUK_OP_EXP_CR 73
+#define DUK_OP_EXP_RC 74
+#define DUK_OP_EXP_CC 75
+#define DUK_OP_BAND 76
+#define DUK_OP_BAND_RR 76
+#define DUK_OP_BAND_CR 77
+#define DUK_OP_BAND_RC 78
+#define DUK_OP_BAND_CC 79
+#define DUK_OP_BOR 80
+#define DUK_OP_BOR_RR 80
+#define DUK_OP_BOR_CR 81
+#define DUK_OP_BOR_RC 82
+#define DUK_OP_BOR_CC 83
+#define DUK_OP_BXOR 84
+#define DUK_OP_BXOR_RR 84
+#define DUK_OP_BXOR_CR 85
+#define DUK_OP_BXOR_RC 86
+#define DUK_OP_BXOR_CC 87
+#define DUK_OP_BASL 88
+#define DUK_OP_BASL_RR 88
+#define DUK_OP_BASL_CR 89
+#define DUK_OP_BASL_RC 90
+#define DUK_OP_BASL_CC 91
+#define DUK_OP_BLSR 92
+#define DUK_OP_BLSR_RR 92
+#define DUK_OP_BLSR_CR 93
+#define DUK_OP_BLSR_RC 94
+#define DUK_OP_BLSR_CC 95
+#define DUK_OP_BASR 96
+#define DUK_OP_BASR_RR 96
+#define DUK_OP_BASR_CR 97
+#define DUK_OP_BASR_RC 98
+#define DUK_OP_BASR_CC 99
+#define DUK_OP_INSTOF 100
+#define DUK_OP_INSTOF_RR 100
+#define DUK_OP_INSTOF_CR 101
+#define DUK_OP_INSTOF_RC 102
+#define DUK_OP_INSTOF_CC 103
+#define DUK_OP_IN 104
+#define DUK_OP_IN_RR 104
+#define DUK_OP_IN_CR 105
+#define DUK_OP_IN_RC 106
+#define DUK_OP_IN_CC 107
+#define DUK_OP_GETPROP 108
+#define DUK_OP_GETPROP_RR 108
+#define DUK_OP_GETPROP_CR 109
+#define DUK_OP_GETPROP_RC 110
+#define DUK_OP_GETPROP_CC 111
+#define DUK_OP_PUTPROP 112
+#define DUK_OP_PUTPROP_RR 112
+#define DUK_OP_PUTPROP_CR 113
+#define DUK_OP_PUTPROP_RC 114
+#define DUK_OP_PUTPROP_CC 115
+#define DUK_OP_DELPROP 116
+#define DUK_OP_DELPROP_RR 116
+#define DUK_OP_DELPROP_CR_UNUSED 117 /* unused now */
+#define DUK_OP_DELPROP_RC 118
+#define DUK_OP_DELPROP_CC_UNUSED 119 /* unused now */
+#define DUK_OP_PREINCR 120 /* pre/post opcode values have constraints, */
+#define DUK_OP_PREDECR 121 /* see duk_js_executor.c and duk_js_compiler.c. */
+#define DUK_OP_POSTINCR 122
+#define DUK_OP_POSTDECR 123
+#define DUK_OP_PREINCV 124
+#define DUK_OP_PREDECV 125
+#define DUK_OP_POSTINCV 126
+#define DUK_OP_POSTDECV 127
+#define DUK_OP_PREINCP 128 /* pre/post inc/dec prop opcodes have constraints */
+#define DUK_OP_PREINCP_RR 128
+#define DUK_OP_PREINCP_CR 129
+#define DUK_OP_PREINCP_RC 130
+#define DUK_OP_PREINCP_CC 131
+#define DUK_OP_PREDECP 132
+#define DUK_OP_PREDECP_RR 132
+#define DUK_OP_PREDECP_CR 133
+#define DUK_OP_PREDECP_RC 134
+#define DUK_OP_PREDECP_CC 135
+#define DUK_OP_POSTINCP 136
+#define DUK_OP_POSTINCP_RR 136
+#define DUK_OP_POSTINCP_CR 137
+#define DUK_OP_POSTINCP_RC 138
+#define DUK_OP_POSTINCP_CC 139
+#define DUK_OP_POSTDECP 140
+#define DUK_OP_POSTDECP_RR 140
+#define DUK_OP_POSTDECP_CR 141
+#define DUK_OP_POSTDECP_RC 142
+#define DUK_OP_POSTDECP_CC 143
+#define DUK_OP_DECLVAR 144
+#define DUK_OP_DECLVAR_RR 144
+#define DUK_OP_DECLVAR_CR 145
+#define DUK_OP_DECLVAR_RC 146
+#define DUK_OP_DECLVAR_CC 147
+#define DUK_OP_REGEXP 148
+#define DUK_OP_REGEXP_RR 148
+#define DUK_OP_REGEXP_CR 149
+#define DUK_OP_REGEXP_RC 150
+#define DUK_OP_REGEXP_CC 151
+#define DUK_OP_CLOSURE 152
+#define DUK_OP_TYPEOF 153
+#define DUK_OP_TYPEOFID 154
+#define DUK_OP_PUTVAR 155
+#define DUK_OP_DELVAR 156
+#define DUK_OP_RETREG 157
+#define DUK_OP_RETUNDEF 158
+#define DUK_OP_RETCONST 159
+#define DUK_OP_RETCONSTN 160 /* return const without incref (e.g. number) */
+#define DUK_OP_LABEL 161
+#define DUK_OP_ENDLABEL 162
+#define DUK_OP_BREAK 163
+#define DUK_OP_CONTINUE 164
+#define DUK_OP_TRYCATCH 165
+#define DUK_OP_ENDTRY 166
+#define DUK_OP_ENDCATCH 167
+#define DUK_OP_ENDFIN 168
+#define DUK_OP_THROW 169
+#define DUK_OP_INVLHS 170
+#define DUK_OP_CSREG 171
+#define DUK_OP_CSVAR 172
+#define DUK_OP_CSVAR_RR 172
+#define DUK_OP_CSVAR_CR 173
+#define DUK_OP_CSVAR_RC 174
+#define DUK_OP_CSVAR_CC 175
+#define DUK_OP_CALL0 176 /* DUK_OP_CALL0 & 0x0F must be zero. */
+#define DUK_OP_CALL1 177
+#define DUK_OP_CALL2 178
+#define DUK_OP_CALL3 179
+#define DUK_OP_CALL4 180
+#define DUK_OP_CALL5 181
+#define DUK_OP_CALL6 182
+#define DUK_OP_CALL7 183
+#define DUK_OP_CALL8 184
+#define DUK_OP_CALL9 185
+#define DUK_OP_CALL10 186
+#define DUK_OP_CALL11 187
+#define DUK_OP_CALL12 188
+#define DUK_OP_CALL13 189
+#define DUK_OP_CALL14 190
+#define DUK_OP_CALL15 191
+#define DUK_OP_NEWOBJ 192
+#define DUK_OP_NEWARR 193
+#define DUK_OP_MPUTOBJ 194
+#define DUK_OP_MPUTOBJI 195
+#define DUK_OP_INITSET 196
+#define DUK_OP_INITGET 197
+#define DUK_OP_MPUTARR 198
+#define DUK_OP_MPUTARRI 199
+#define DUK_OP_SETALEN 200
+#define DUK_OP_INITENUM 201
+#define DUK_OP_NEXTENUM 202
+#define DUK_OP_NEWTARGET 203
+#define DUK_OP_DEBUGGER 204
+#define DUK_OP_NOP 205
+#define DUK_OP_INVALID 206
+#define DUK_OP_UNUSED207 207
+#define DUK_OP_GETPROPC 208
+#define DUK_OP_GETPROPC_RR 208
+#define DUK_OP_GETPROPC_CR 209
+#define DUK_OP_GETPROPC_RC 210
+#define DUK_OP_GETPROPC_CC 211
+#define DUK_OP_UNUSED212 212
+#define DUK_OP_UNUSED213 213
+#define DUK_OP_UNUSED214 214
+#define DUK_OP_UNUSED215 215
+#define DUK_OP_UNUSED216 216
+#define DUK_OP_UNUSED217 217
+#define DUK_OP_UNUSED218 218
+#define DUK_OP_UNUSED219 219
+#define DUK_OP_UNUSED220 220
+#define DUK_OP_UNUSED221 221
+#define DUK_OP_UNUSED222 222
+#define DUK_OP_UNUSED223 223
+#define DUK_OP_UNUSED224 224
+#define DUK_OP_UNUSED225 225
+#define DUK_OP_UNUSED226 226
+#define DUK_OP_UNUSED227 227
+#define DUK_OP_UNUSED228 228
+#define DUK_OP_UNUSED229 229
+#define DUK_OP_UNUSED230 230
+#define DUK_OP_UNUSED231 231
+#define DUK_OP_UNUSED232 232
+#define DUK_OP_UNUSED233 233
+#define DUK_OP_UNUSED234 234
+#define DUK_OP_UNUSED235 235
+#define DUK_OP_UNUSED236 236
+#define DUK_OP_UNUSED237 237
+#define DUK_OP_UNUSED238 238
+#define DUK_OP_UNUSED239 239
+#define DUK_OP_UNUSED240 240
+#define DUK_OP_UNUSED241 241
+#define DUK_OP_UNUSED242 242
+#define DUK_OP_UNUSED243 243
+#define DUK_OP_UNUSED244 244
+#define DUK_OP_UNUSED245 245
+#define DUK_OP_UNUSED246 246
+#define DUK_OP_UNUSED247 247
+#define DUK_OP_UNUSED248 248
+#define DUK_OP_UNUSED249 249
+#define DUK_OP_UNUSED250 250
+#define DUK_OP_UNUSED251 251
+#define DUK_OP_UNUSED252 252
+#define DUK_OP_UNUSED253 253
+#define DUK_OP_UNUSED254 254
+#define DUK_OP_UNUSED255 255
+#define DUK_OP_NONE 256 /* dummy value used as marker (doesn't fit in 8-bit field) */
/* XXX: Allocate flags from opcode field? Would take 16 opcode slots
* but avoids shuffling in more cases. Maybe not worth it.
*/
/* DUK_OP_TRYCATCH flags in A. */
-#define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH (1U << 0)
-#define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY (1U << 1)
-#define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING (1U << 2)
-#define DUK_BC_TRYCATCH_FLAG_WITH_BINDING (1U << 3)
+#define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH (1U << 0)
+#define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY (1U << 1)
+#define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING (1U << 2)
+#define DUK_BC_TRYCATCH_FLAG_WITH_BINDING (1U << 3)
/* DUK_OP_DECLVAR flags in A; bottom bits are reserved for propdesc flags
* (DUK_PROPDESC_FLAG_XXX).
*/
-#define DUK_BC_DECLVAR_FLAG_FUNC_DECL (1U << 4) /* function declaration */
+#define DUK_BC_DECLVAR_FLAG_FUNC_DECL (1U << 4) /* function declaration */
/* DUK_OP_CALLn flags, part of opcode field. Three lowest bits must match
* DUK_CALL_FLAG_xxx directly.
*/
-#define DUK_BC_CALL_FLAG_TAILCALL (1U << 0)
-#define DUK_BC_CALL_FLAG_CONSTRUCT (1U << 1)
-#define DUK_BC_CALL_FLAG_CALLED_AS_EVAL (1U << 2)
-#define DUK_BC_CALL_FLAG_INDIRECT (1U << 3)
+#define DUK_BC_CALL_FLAG_TAILCALL (1U << 0)
+#define DUK_BC_CALL_FLAG_CONSTRUCT (1U << 1)
+#define DUK_BC_CALL_FLAG_CALLED_AS_EVAL (1U << 2)
+#define DUK_BC_CALL_FLAG_INDIRECT (1U << 3)
/* Misc constants and helper macros. */
-#define DUK_BC_LDINT_BIAS (1L << 15)
-#define DUK_BC_LDINTX_SHIFT 16
-#define DUK_BC_JUMP_BIAS (1L << 23)
+#define DUK_BC_LDINT_BIAS (1L << 15)
+#define DUK_BC_LDINTX_SHIFT 16
+#define DUK_BC_JUMP_BIAS (1L << 23)
-#endif /* DUK_JS_BYTECODE_H_INCLUDED */
+#endif /* DUK_JS_BYTECODE_H_INCLUDED */
/* #include duk_lexer.h */
/*
* Lexer defines.
@@ -3462,156 +3827,156 @@ typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepo
* in a continuous range and in a particular order. See genstrings.py.
*/
-#define DUK_LEXER_INITCTX(ctx) duk_lexer_initctx((ctx))
+#define DUK_LEXER_INITCTX(ctx) duk_lexer_initctx((ctx))
-#define DUK_LEXER_SETPOINT(ctx,pt) duk_lexer_setpoint((ctx), (pt))
+#define DUK_LEXER_SETPOINT(ctx, pt) duk_lexer_setpoint((ctx), (pt))
-#define DUK_LEXER_GETPOINT(ctx,pt) duk_lexer_getpoint((ctx), (pt))
+#define DUK_LEXER_GETPOINT(ctx, pt) duk_lexer_getpoint((ctx), (pt))
/* Currently 6 characters of lookup are actually needed (duk_lexer.c). */
-#define DUK_LEXER_WINDOW_SIZE 6
+#define DUK_LEXER_WINDOW_SIZE 6
#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
-#define DUK_LEXER_BUFFER_SIZE 64
+#define DUK_LEXER_BUFFER_SIZE 64
#endif
-#define DUK_TOK_MINVAL 0
+#define DUK_TOK_MINVAL 0
/* returned after EOF (infinite amount) */
-#define DUK_TOK_EOF 0
+#define DUK_TOK_EOF 0
/* identifier names (E5 Section 7.6) */
-#define DUK_TOK_IDENTIFIER 1
+#define DUK_TOK_IDENTIFIER 1
/* reserved words: keywords */
-#define DUK_TOK_START_RESERVED 2
-#define DUK_TOK_BREAK 2
-#define DUK_TOK_CASE 3
-#define DUK_TOK_CATCH 4
-#define DUK_TOK_CONTINUE 5
-#define DUK_TOK_DEBUGGER 6
-#define DUK_TOK_DEFAULT 7
-#define DUK_TOK_DELETE 8
-#define DUK_TOK_DO 9
-#define DUK_TOK_ELSE 10
-#define DUK_TOK_FINALLY 11
-#define DUK_TOK_FOR 12
-#define DUK_TOK_FUNCTION 13
-#define DUK_TOK_IF 14
-#define DUK_TOK_IN 15
-#define DUK_TOK_INSTANCEOF 16
-#define DUK_TOK_NEW 17
-#define DUK_TOK_RETURN 18
-#define DUK_TOK_SWITCH 19
-#define DUK_TOK_THIS 20
-#define DUK_TOK_THROW 21
-#define DUK_TOK_TRY 22
-#define DUK_TOK_TYPEOF 23
-#define DUK_TOK_VAR 24
-#define DUK_TOK_CONST 25
-#define DUK_TOK_VOID 26
-#define DUK_TOK_WHILE 27
-#define DUK_TOK_WITH 28
+#define DUK_TOK_START_RESERVED 2
+#define DUK_TOK_BREAK 2
+#define DUK_TOK_CASE 3
+#define DUK_TOK_CATCH 4
+#define DUK_TOK_CONTINUE 5
+#define DUK_TOK_DEBUGGER 6
+#define DUK_TOK_DEFAULT 7
+#define DUK_TOK_DELETE 8
+#define DUK_TOK_DO 9
+#define DUK_TOK_ELSE 10
+#define DUK_TOK_FINALLY 11
+#define DUK_TOK_FOR 12
+#define DUK_TOK_FUNCTION 13
+#define DUK_TOK_IF 14
+#define DUK_TOK_IN 15
+#define DUK_TOK_INSTANCEOF 16
+#define DUK_TOK_NEW 17
+#define DUK_TOK_RETURN 18
+#define DUK_TOK_SWITCH 19
+#define DUK_TOK_THIS 20
+#define DUK_TOK_THROW 21
+#define DUK_TOK_TRY 22
+#define DUK_TOK_TYPEOF 23
+#define DUK_TOK_VAR 24
+#define DUK_TOK_CONST 25
+#define DUK_TOK_VOID 26
+#define DUK_TOK_WHILE 27
+#define DUK_TOK_WITH 28
/* reserved words: future reserved words */
-#define DUK_TOK_CLASS 29
-#define DUK_TOK_ENUM 30
-#define DUK_TOK_EXPORT 31
-#define DUK_TOK_EXTENDS 32
-#define DUK_TOK_IMPORT 33
-#define DUK_TOK_SUPER 34
+#define DUK_TOK_CLASS 29
+#define DUK_TOK_ENUM 30
+#define DUK_TOK_EXPORT 31
+#define DUK_TOK_EXTENDS 32
+#define DUK_TOK_IMPORT 33
+#define DUK_TOK_SUPER 34
/* "null", "true", and "false" are always reserved words.
* Note that "get" and "set" are not!
*/
-#define DUK_TOK_NULL 35
-#define DUK_TOK_TRUE 36
-#define DUK_TOK_FALSE 37
+#define DUK_TOK_NULL 35
+#define DUK_TOK_TRUE 36
+#define DUK_TOK_FALSE 37
/* reserved words: additional future reserved words in strict mode */
-#define DUK_TOK_START_STRICT_RESERVED 38 /* inclusive */
-#define DUK_TOK_IMPLEMENTS 38
-#define DUK_TOK_INTERFACE 39
-#define DUK_TOK_LET 40
-#define DUK_TOK_PACKAGE 41
-#define DUK_TOK_PRIVATE 42
-#define DUK_TOK_PROTECTED 43
-#define DUK_TOK_PUBLIC 44
-#define DUK_TOK_STATIC 45
-#define DUK_TOK_YIELD 46
-
-#define DUK_TOK_END_RESERVED 47 /* exclusive */
+#define DUK_TOK_START_STRICT_RESERVED 38 /* inclusive */
+#define DUK_TOK_IMPLEMENTS 38
+#define DUK_TOK_INTERFACE 39
+#define DUK_TOK_LET 40
+#define DUK_TOK_PACKAGE 41
+#define DUK_TOK_PRIVATE 42
+#define DUK_TOK_PROTECTED 43
+#define DUK_TOK_PUBLIC 44
+#define DUK_TOK_STATIC 45
+#define DUK_TOK_YIELD 46
+
+#define DUK_TOK_END_RESERVED 47 /* exclusive */
/* "get" and "set" are tokens but NOT ReservedWords. They are currently
* parsed and identifiers and these defines are actually now unused.
*/
-#define DUK_TOK_GET 47
-#define DUK_TOK_SET 48
+#define DUK_TOK_GET 47
+#define DUK_TOK_SET 48
/* punctuators (unlike the spec, also includes "/" and "/=") */
-#define DUK_TOK_LCURLY 49
-#define DUK_TOK_RCURLY 50
-#define DUK_TOK_LBRACKET 51
-#define DUK_TOK_RBRACKET 52
-#define DUK_TOK_LPAREN 53
-#define DUK_TOK_RPAREN 54
-#define DUK_TOK_PERIOD 55
-#define DUK_TOK_SEMICOLON 56
-#define DUK_TOK_COMMA 57
-#define DUK_TOK_LT 58
-#define DUK_TOK_GT 59
-#define DUK_TOK_LE 60
-#define DUK_TOK_GE 61
-#define DUK_TOK_EQ 62
-#define DUK_TOK_NEQ 63
-#define DUK_TOK_SEQ 64
-#define DUK_TOK_SNEQ 65
-#define DUK_TOK_ADD 66
-#define DUK_TOK_SUB 67
-#define DUK_TOK_MUL 68
-#define DUK_TOK_DIV 69
-#define DUK_TOK_MOD 70
-#define DUK_TOK_EXP 71
-#define DUK_TOK_INCREMENT 72
-#define DUK_TOK_DECREMENT 73
-#define DUK_TOK_ALSHIFT 74 /* named "arithmetic" because result is signed */
-#define DUK_TOK_ARSHIFT 75
-#define DUK_TOK_RSHIFT 76
-#define DUK_TOK_BAND 77
-#define DUK_TOK_BOR 78
-#define DUK_TOK_BXOR 79
-#define DUK_TOK_LNOT 80
-#define DUK_TOK_BNOT 81
-#define DUK_TOK_LAND 82
-#define DUK_TOK_LOR 83
-#define DUK_TOK_QUESTION 84
-#define DUK_TOK_COLON 85
-#define DUK_TOK_EQUALSIGN 86
-#define DUK_TOK_ADD_EQ 87
-#define DUK_TOK_SUB_EQ 88
-#define DUK_TOK_MUL_EQ 89
-#define DUK_TOK_DIV_EQ 90
-#define DUK_TOK_MOD_EQ 91
-#define DUK_TOK_EXP_EQ 92
-#define DUK_TOK_ALSHIFT_EQ 93
-#define DUK_TOK_ARSHIFT_EQ 94
-#define DUK_TOK_RSHIFT_EQ 95
-#define DUK_TOK_BAND_EQ 96
-#define DUK_TOK_BOR_EQ 97
-#define DUK_TOK_BXOR_EQ 98
+#define DUK_TOK_LCURLY 49
+#define DUK_TOK_RCURLY 50
+#define DUK_TOK_LBRACKET 51
+#define DUK_TOK_RBRACKET 52
+#define DUK_TOK_LPAREN 53
+#define DUK_TOK_RPAREN 54
+#define DUK_TOK_PERIOD 55
+#define DUK_TOK_SEMICOLON 56
+#define DUK_TOK_COMMA 57
+#define DUK_TOK_LT 58
+#define DUK_TOK_GT 59
+#define DUK_TOK_LE 60
+#define DUK_TOK_GE 61
+#define DUK_TOK_EQ 62
+#define DUK_TOK_NEQ 63
+#define DUK_TOK_SEQ 64
+#define DUK_TOK_SNEQ 65
+#define DUK_TOK_ADD 66
+#define DUK_TOK_SUB 67
+#define DUK_TOK_MUL 68
+#define DUK_TOK_DIV 69
+#define DUK_TOK_MOD 70
+#define DUK_TOK_EXP 71
+#define DUK_TOK_INCREMENT 72
+#define DUK_TOK_DECREMENT 73
+#define DUK_TOK_ALSHIFT 74 /* named "arithmetic" because result is signed */
+#define DUK_TOK_ARSHIFT 75
+#define DUK_TOK_RSHIFT 76
+#define DUK_TOK_BAND 77
+#define DUK_TOK_BOR 78
+#define DUK_TOK_BXOR 79
+#define DUK_TOK_LNOT 80
+#define DUK_TOK_BNOT 81
+#define DUK_TOK_LAND 82
+#define DUK_TOK_LOR 83
+#define DUK_TOK_QUESTION 84
+#define DUK_TOK_COLON 85
+#define DUK_TOK_EQUALSIGN 86
+#define DUK_TOK_ADD_EQ 87
+#define DUK_TOK_SUB_EQ 88
+#define DUK_TOK_MUL_EQ 89
+#define DUK_TOK_DIV_EQ 90
+#define DUK_TOK_MOD_EQ 91
+#define DUK_TOK_EXP_EQ 92
+#define DUK_TOK_ALSHIFT_EQ 93
+#define DUK_TOK_ARSHIFT_EQ 94
+#define DUK_TOK_RSHIFT_EQ 95
+#define DUK_TOK_BAND_EQ 96
+#define DUK_TOK_BOR_EQ 97
+#define DUK_TOK_BXOR_EQ 98
/* literals (E5 Section 7.8), except null, true, false, which are treated
* like reserved words (above).
*/
-#define DUK_TOK_NUMBER 99
-#define DUK_TOK_STRING 100
-#define DUK_TOK_REGEXP 101
+#define DUK_TOK_NUMBER 99
+#define DUK_TOK_STRING 100
+#define DUK_TOK_REGEXP 101
-#define DUK_TOK_MAXVAL 101 /* inclusive */
+#define DUK_TOK_MAXVAL 101 /* inclusive */
-#define DUK_TOK_INVALID DUK_SMALL_UINT_MAX
+#define DUK_TOK_INVALID DUK_SMALL_UINT_MAX
/* Convert heap string index to a token (reserved words) */
-#define DUK_STRIDX_TO_TOK(x) ((x) - DUK_STRIDX_START_RESERVED + DUK_TOK_START_RESERVED)
+#define DUK_STRIDX_TO_TOK(x) ((x) -DUK_STRIDX_START_RESERVED + DUK_TOK_START_RESERVED)
/* Sanity check */
#if (DUK_TOK_MAXVAL > 255)
@@ -3756,57 +4121,57 @@ typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepo
#endif
/* Regexp tokens */
-#define DUK_RETOK_EOF 0
-#define DUK_RETOK_DISJUNCTION 1
-#define DUK_RETOK_QUANTIFIER 2
-#define DUK_RETOK_ASSERT_START 3
-#define DUK_RETOK_ASSERT_END 4
-#define DUK_RETOK_ASSERT_WORD_BOUNDARY 5
-#define DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY 6
-#define DUK_RETOK_ASSERT_START_POS_LOOKAHEAD 7
-#define DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD 8
-#define DUK_RETOK_ATOM_PERIOD 9
-#define DUK_RETOK_ATOM_CHAR 10
-#define DUK_RETOK_ATOM_DIGIT 11 /* assumptions in regexp compiler */
-#define DUK_RETOK_ATOM_NOT_DIGIT 12 /* -""- */
-#define DUK_RETOK_ATOM_WHITE 13 /* -""- */
-#define DUK_RETOK_ATOM_NOT_WHITE 14 /* -""- */
-#define DUK_RETOK_ATOM_WORD_CHAR 15 /* -""- */
-#define DUK_RETOK_ATOM_NOT_WORD_CHAR 16 /* -""- */
-#define DUK_RETOK_ATOM_BACKREFERENCE 17
-#define DUK_RETOK_ATOM_START_CAPTURE_GROUP 18
-#define DUK_RETOK_ATOM_START_NONCAPTURE_GROUP 19
-#define DUK_RETOK_ATOM_START_CHARCLASS 20
-#define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED 21
-#define DUK_RETOK_ATOM_END_GROUP 22
+#define DUK_RETOK_EOF 0
+#define DUK_RETOK_DISJUNCTION 1
+#define DUK_RETOK_QUANTIFIER 2
+#define DUK_RETOK_ASSERT_START 3
+#define DUK_RETOK_ASSERT_END 4
+#define DUK_RETOK_ASSERT_WORD_BOUNDARY 5
+#define DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY 6
+#define DUK_RETOK_ASSERT_START_POS_LOOKAHEAD 7
+#define DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD 8
+#define DUK_RETOK_ATOM_PERIOD 9
+#define DUK_RETOK_ATOM_CHAR 10
+#define DUK_RETOK_ATOM_DIGIT 11 /* assumptions in regexp compiler */
+#define DUK_RETOK_ATOM_NOT_DIGIT 12 /* -""- */
+#define DUK_RETOK_ATOM_WHITE 13 /* -""- */
+#define DUK_RETOK_ATOM_NOT_WHITE 14 /* -""- */
+#define DUK_RETOK_ATOM_WORD_CHAR 15 /* -""- */
+#define DUK_RETOK_ATOM_NOT_WORD_CHAR 16 /* -""- */
+#define DUK_RETOK_ATOM_BACKREFERENCE 17
+#define DUK_RETOK_ATOM_START_CAPTURE_GROUP 18
+#define DUK_RETOK_ATOM_START_NONCAPTURE_GROUP 19
+#define DUK_RETOK_ATOM_START_CHARCLASS 20
+#define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED 21
+#define DUK_RETOK_ATOM_END_GROUP 22
/* Constants for duk_lexer_ctx.buf. */
-#define DUK_LEXER_TEMP_BUF_LIMIT 256
+#define DUK_LEXER_TEMP_BUF_LIMIT 256
/* A token value. Can be memcpy()'d, but note that slot1/slot2 values are on the valstack.
* Some fields (like num, str1, str2) are only valid for specific token types and may have
* stale values otherwise.
*/
struct duk_token {
- duk_small_uint_t t; /* token type (with reserved word identification) */
- duk_small_uint_t t_nores; /* token type (with reserved words as DUK_TOK_IDENTIFER) */
- duk_double_t num; /* numeric value of token */
- duk_hstring *str1; /* string 1 of token (borrowed, stored to ctx->slot1_idx) */
- duk_hstring *str2; /* string 2 of token (borrowed, stored to ctx->slot2_idx) */
- duk_size_t start_offset; /* start byte offset of token in lexer input */
- duk_int_t start_line; /* start line of token (first char) */
- duk_int_t num_escapes; /* number of escapes and line continuations (for directive prologue) */
- duk_bool_t lineterm; /* token was preceded by a lineterm */
- duk_bool_t allow_auto_semi; /* token allows automatic semicolon insertion (eof or preceded by newline) */
+ duk_small_uint_t t; /* token type (with reserved word identification) */
+ duk_small_uint_t t_nores; /* token type (with reserved words as DUK_TOK_IDENTIFER) */
+ duk_double_t num; /* numeric value of token */
+ duk_hstring *str1; /* string 1 of token (borrowed, stored to ctx->slot1_idx) */
+ duk_hstring *str2; /* string 2 of token (borrowed, stored to ctx->slot2_idx) */
+ duk_size_t start_offset; /* start byte offset of token in lexer input */
+ duk_int_t start_line; /* start line of token (first char) */
+ duk_int_t num_escapes; /* number of escapes and line continuations (for directive prologue) */
+ duk_bool_t lineterm; /* token was preceded by a lineterm */
+ duk_bool_t allow_auto_semi; /* token allows automatic semicolon insertion (eof or preceded by newline) */
};
-#define DUK_RE_QUANTIFIER_INFINITE ((duk_uint32_t) 0xffffffffUL)
+#define DUK_RE_QUANTIFIER_INFINITE ((duk_uint32_t) 0xffffffffUL)
/* A regexp token value. */
struct duk_re_token {
- duk_small_uint_t t; /* token type */
+ duk_small_uint_t t; /* token type */
duk_small_uint_t greedy;
- duk_uint32_t num; /* numeric value (character, count) */
+ duk_uint32_t num; /* numeric value (character, count) */
duk_uint32_t qmin;
duk_uint32_t qmax;
};
@@ -3824,7 +4189,7 @@ struct duk_lexer_codepoint {
duk_int_t line;
};
-/* Lexer context. Same context is used for Ecmascript and Regexp parsing. */
+/* Lexer context. Same context is used for ECMAScript and Regexp parsing. */
struct duk_lexer_ctx {
#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
duk_lexer_codepoint *window; /* unicode code points, window[0] is always next, points to 'buffer' */
@@ -3833,23 +4198,23 @@ struct duk_lexer_ctx {
duk_lexer_codepoint window[DUK_LEXER_WINDOW_SIZE]; /* unicode code points, window[0] is always next */
#endif
- duk_hthread *thr; /* thread; minimizes argument passing */
+ duk_hthread *thr; /* thread; minimizes argument passing */
- const duk_uint8_t *input; /* input string (may be a user pointer) */
- duk_size_t input_length; /* input byte length */
- duk_size_t input_offset; /* input offset for window leading edge (not window[0]) */
- duk_int_t input_line; /* input linenumber at input_offset (not window[0]), init to 1 */
+ const duk_uint8_t *input; /* input string (may be a user pointer) */
+ duk_size_t input_length; /* input byte length */
+ duk_size_t input_offset; /* input offset for window leading edge (not window[0]) */
+ duk_int_t input_line; /* input linenumber at input_offset (not window[0]), init to 1 */
- duk_idx_t slot1_idx; /* valstack slot for 1st token value */
- duk_idx_t slot2_idx; /* valstack slot for 2nd token value */
- duk_idx_t buf_idx; /* valstack slot for temp buffer */
- duk_hbuffer_dynamic *buf; /* temp accumulation buffer */
- duk_bufwriter_ctx bw; /* bufwriter for temp accumulation */
+ duk_idx_t slot1_idx; /* valstack slot for 1st token value */
+ duk_idx_t slot2_idx; /* valstack slot for 2nd token value */
+ duk_idx_t buf_idx; /* valstack slot for temp buffer */
+ duk_hbuffer_dynamic *buf; /* temp accumulation buffer */
+ duk_bufwriter_ctx bw; /* bufwriter for temp accumulation */
- duk_int_t token_count; /* number of tokens parsed */
- duk_int_t token_limit; /* maximum token count before error (sanity backstop) */
+ duk_int_t token_count; /* number of tokens parsed */
+ duk_int_t token_limit; /* maximum token count before error (sanity backstop) */
- duk_small_uint_t flags; /* lexer flags, use compiler flag defines for now */
+ duk_small_uint_t flags; /* lexer flags, use compiler flag defines for now */
};
/*
@@ -3862,32 +4227,29 @@ DUK_INTERNAL_DECL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_poin
DUK_INTERNAL_DECL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);
DUK_INTERNAL_DECL
-void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
- duk_token *out_token,
- duk_bool_t strict_mode,
- duk_bool_t regexp_mode);
+void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx, duk_token *out_token, duk_bool_t strict_mode, duk_bool_t regexp_mode);
#if defined(DUK_USE_REGEXP_SUPPORT)
DUK_INTERNAL_DECL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token);
DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata);
-#endif /* DUK_USE_REGEXP_SUPPORT */
+#endif /* DUK_USE_REGEXP_SUPPORT */
-#endif /* DUK_LEXER_H_INCLUDED */
+#endif /* DUK_LEXER_H_INCLUDED */
/* #include duk_js_compiler.h */
/*
- * Ecmascript compiler.
+ * ECMAScript compiler.
*/
#if !defined(DUK_JS_COMPILER_H_INCLUDED)
#define DUK_JS_COMPILER_H_INCLUDED
-/* ecmascript compiler limits */
-#define DUK_COMPILER_TOKEN_LIMIT 100000000L /* 1e8: protects against deeply nested inner functions */
+/* ECMAScript compiler limits */
+#define DUK_COMPILER_TOKEN_LIMIT 100000000L /* 1e8: protects against deeply nested inner functions */
/* maximum loopcount for peephole optimization */
-#define DUK_COMPILER_PEEPHOLE_MAXITER 3
+#define DUK_COMPILER_PEEPHOLE_MAXITER 3
/* maximum bytecode length in instructions */
-#define DUK_COMPILER_MAX_BYTECODE_LENGTH (256L * 1024L * 1024L) /* 1 GB */
+#define DUK_COMPILER_MAX_BYTECODE_LENGTH (256L * 1024L * 1024L) /* 1 GB */
/*
* Compiler intermediate values
@@ -3897,21 +4259,21 @@ DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_
* either a left-hand-side or right-hand-side role (e.g. object property).
*/
-#define DUK_IVAL_NONE 0 /* no value */
-#define DUK_IVAL_PLAIN 1 /* register, constant, or value */
-#define DUK_IVAL_ARITH 2 /* binary arithmetic; DUK_OP_ADD, DUK_OP_EQ, other binary ops */
-#define DUK_IVAL_PROP 3 /* property access */
-#define DUK_IVAL_VAR 4 /* variable access */
+#define DUK_IVAL_NONE 0 /* no value */
+#define DUK_IVAL_PLAIN 1 /* register, constant, or value */
+#define DUK_IVAL_ARITH 2 /* binary arithmetic; DUK_OP_ADD, DUK_OP_EQ, other binary ops */
+#define DUK_IVAL_PROP 3 /* property access */
+#define DUK_IVAL_VAR 4 /* variable access */
-#define DUK_ISPEC_NONE 0 /* no value */
-#define DUK_ISPEC_VALUE 1 /* value resides in 'valstack_idx' */
-#define DUK_ISPEC_REGCONST 2 /* value resides in a register or constant */
+#define DUK_ISPEC_NONE 0 /* no value */
+#define DUK_ISPEC_VALUE 1 /* value resides in 'valstack_idx' */
+#define DUK_ISPEC_REGCONST 2 /* value resides in a register or constant */
/* Bit mask which indicates that a regconst is a constant instead of a register.
* Chosen so that when a regconst is cast to duk_int32_t, all consts are
* negative values.
*/
-#define DUK_REGCONST_CONST_MARKER DUK_INT32_MIN /* = -0x80000000 */
+#define DUK_REGCONST_CONST_MARKER DUK_INT32_MIN /* = -0x80000000 */
/* Type to represent a reg/const reference during compilation, with <0
* indicating a constant. Some call sites also use -1 to indicate 'none'.
@@ -3919,9 +4281,9 @@ DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_
typedef duk_int32_t duk_regconst_t;
typedef struct {
- duk_small_uint_t t; /* DUK_ISPEC_XXX */
+ duk_small_uint_t t; /* DUK_ISPEC_XXX */
duk_regconst_t regconst;
- duk_idx_t valstack_idx; /* always set; points to a reserved valstack slot */
+ duk_idx_t valstack_idx; /* always set; points to a reserved valstack slot */
} duk_ispec;
typedef struct {
@@ -3933,8 +4295,8 @@ typedef struct {
*/
/* XXX: can be optimized for smaller footprint esp. on 32-bit environments */
- duk_small_uint_t t; /* DUK_IVAL_XXX */
- duk_small_uint_t op; /* bytecode opcode for binary ops */
+ duk_small_uint_t t; /* DUK_IVAL_XXX */
+ duk_small_uint_t op; /* bytecode opcode for binary ops */
duk_ispec x1;
duk_ispec x2;
} duk_ivalue;
@@ -3956,22 +4318,22 @@ struct duk_compiler_instr {
* Compiler state
*/
-#define DUK_LABEL_FLAG_ALLOW_BREAK (1U << 0)
-#define DUK_LABEL_FLAG_ALLOW_CONTINUE (1U << 1)
+#define DUK_LABEL_FLAG_ALLOW_BREAK (1U << 0)
+#define DUK_LABEL_FLAG_ALLOW_CONTINUE (1U << 1)
-#define DUK_DECL_TYPE_VAR 0
-#define DUK_DECL_TYPE_FUNC 1
+#define DUK_DECL_TYPE_VAR 0
+#define DUK_DECL_TYPE_FUNC 1
/* XXX: optimize to 16 bytes */
typedef struct {
duk_small_uint_t flags;
- duk_int_t label_id; /* numeric label_id (-1 reserved as marker) */
- duk_hstring *h_label; /* borrowed label name */
- duk_int_t catch_depth; /* catch depth at point of definition */
- duk_int_t pc_label; /* pc of label statement:
- * pc+1: break jump site
- * pc+2: continue jump site
- */
+ duk_int_t label_id; /* numeric label_id (-1 reserved as marker) */
+ duk_hstring *h_label; /* borrowed label name */
+ duk_int_t catch_depth; /* catch depth at point of definition */
+ duk_int_t pc_label; /* pc of label statement:
+ * pc+1: break jump site
+ * pc+2: continue jump site
+ */
/* Fast jumps (which avoid longjmp) jump directly to the jump sites
* which are always known even while the iteration/switch statement
@@ -3987,22 +4349,22 @@ struct duk_compiler_func {
* platforms (e.g. if int is 32 bits and pointers are 64 bits).
*/
- duk_bufwriter_ctx bw_code; /* bufwriter for code */
+ duk_bufwriter_ctx bw_code; /* bufwriter for code */
- duk_hstring *h_name; /* function name (borrowed reference), ends up in _name */
+ duk_hstring *h_name; /* function name (borrowed reference), ends up in _name */
/* h_code: held in bw_code */
- duk_hobject *h_consts; /* array */
- duk_hobject *h_funcs; /* array of function templates: [func1, offset1, line1, func2, offset2, line2]
- * offset/line points to closing brace to allow skipping on pass 2
- */
- duk_hobject *h_decls; /* array of declarations: [ name1, val1, name2, val2, ... ]
- * valN = (typeN) | (fnum << 8), where fnum is inner func number (0 for vars)
- * record function and variable declarations in pass 1
- */
- duk_hobject *h_labelnames; /* array of active label names */
- duk_hbuffer_dynamic *h_labelinfos; /* C array of duk_labelinfo */
- duk_hobject *h_argnames; /* array of formal argument names (-> _Formals) */
- duk_hobject *h_varmap; /* variable map for pass 2 (identifier -> register number or null (unmapped)) */
+ duk_hobject *h_consts; /* array */
+ duk_hobject *h_funcs; /* array of function templates: [func1, offset1, line1, func2, offset2, line2]
+ * offset/line points to closing brace to allow skipping on pass 2
+ */
+ duk_hobject *h_decls; /* array of declarations: [ name1, val1, name2, val2, ... ]
+ * valN = (typeN) | (fnum << 8), where fnum is inner func number (0 for vars)
+ * record function and variable declarations in pass 1
+ */
+ duk_hobject *h_labelnames; /* array of active label names */
+ duk_hbuffer_dynamic *h_labelinfos; /* C array of duk_labelinfo */
+ duk_hobject *h_argnames; /* array of formal argument names (-> _Formals) */
+ duk_hobject *h_varmap; /* variable map for pass 2 (identifier -> register number or null (unmapped)) */
/* Value stack indices for tracking objects. */
/* code_idx: not needed */
@@ -4015,9 +4377,9 @@ struct duk_compiler_func {
duk_idx_t varmap_idx;
/* Temp reg handling. */
- duk_regconst_t temp_first; /* first register that is a temporary (below: variables) */
- duk_regconst_t temp_next; /* next temporary register to allocate */
- duk_regconst_t temp_max; /* highest value of temp_reg (temp_max - 1 is highest used reg) */
+ duk_regconst_t temp_first; /* first register that is a temporary (below: variables) */
+ duk_regconst_t temp_next; /* next temporary register to allocate */
+ duk_regconst_t temp_max; /* highest value of temp_reg (temp_max - 1 is highest used reg) */
/* Shuffle registers if large number of regs/consts. */
duk_regconst_t shuffle1;
@@ -4027,48 +4389,51 @@ struct duk_compiler_func {
/* Stats for current expression being parsed. */
duk_int_t nud_count;
duk_int_t led_count;
- duk_int_t paren_level; /* parenthesis count, 0 = top level */
- duk_bool_t expr_lhs; /* expression is left-hand-side compatible */
- duk_bool_t allow_in; /* current paren level allows 'in' token */
+ duk_int_t paren_level; /* parenthesis count, 0 = top level */
+ duk_bool_t expr_lhs; /* expression is left-hand-side compatible */
+ duk_bool_t allow_in; /* current paren level allows 'in' token */
/* Misc. */
- duk_int_t stmt_next; /* statement id allocation (running counter) */
- duk_int_t label_next; /* label id allocation (running counter) */
- duk_int_t catch_depth; /* catch stack depth */
- duk_int_t with_depth; /* with stack depth (affects identifier lookups) */
- duk_int_t fnum_next; /* inner function numbering */
- duk_int_t num_formals; /* number of formal arguments */
- duk_regconst_t reg_stmt_value; /* register for writing value of 'non-empty' statements (global or eval code), -1 is marker */
+ duk_int_t stmt_next; /* statement id allocation (running counter) */
+ duk_int_t label_next; /* label id allocation (running counter) */
+ duk_int_t catch_depth; /* catch stack depth */
+ duk_int_t with_depth; /* with stack depth (affects identifier lookups) */
+ duk_int_t fnum_next; /* inner function numbering */
+ duk_int_t num_formals; /* number of formal arguments */
+ duk_regconst_t
+ reg_stmt_value; /* register for writing value of 'non-empty' statements (global or eval code), -1 is marker */
#if defined(DUK_USE_DEBUGGER_SUPPORT)
- duk_int_t min_line; /* XXX: typing (duk_hcompfunc has duk_uint32_t) */
+ duk_int_t min_line; /* XXX: typing (duk_hcompfunc has duk_uint32_t) */
duk_int_t max_line;
#endif
/* Status booleans. */
- duk_uint8_t is_function; /* is an actual function (not global/eval code) */
- duk_uint8_t is_eval; /* is eval code */
- duk_uint8_t is_global; /* is global code */
- duk_uint8_t is_namebinding; /* needs a name binding */
- duk_uint8_t is_constructable; /* result is constructable */
- duk_uint8_t is_setget; /* is a setter/getter */
- duk_uint8_t is_strict; /* function is strict */
- duk_uint8_t is_notail; /* function must not be tail called */
- duk_uint8_t in_directive_prologue; /* parsing in "directive prologue", recognize directives */
- duk_uint8_t in_scanning; /* parsing in "scanning" phase (first pass) */
- duk_uint8_t may_direct_eval; /* function may call direct eval */
- duk_uint8_t id_access_arguments; /* function refers to 'arguments' identifier */
- duk_uint8_t id_access_slow; /* function makes one or more slow path accesses that won't match own static variables */
- duk_uint8_t id_access_slow_own; /* function makes one or more slow path accesses that may match own static variables */
- duk_uint8_t is_arguments_shadowed; /* argument/function declaration shadows 'arguments' */
- duk_uint8_t needs_shuffle; /* function needs shuffle registers */
- duk_uint8_t reject_regexp_in_adv; /* reject RegExp literal on next advance() call; needed for handling IdentifierName productions */
+ duk_uint8_t is_function; /* is an actual function (not global/eval code) */
+ duk_uint8_t is_eval; /* is eval code */
+ duk_uint8_t is_global; /* is global code */
+ duk_uint8_t is_namebinding; /* needs a name binding */
+ duk_uint8_t is_constructable; /* result is constructable */
+ duk_uint8_t is_setget; /* is a setter/getter */
+ duk_uint8_t is_strict; /* function is strict */
+ duk_uint8_t is_notail; /* function must not be tail called */
+ duk_uint8_t in_directive_prologue; /* parsing in "directive prologue", recognize directives */
+ duk_uint8_t in_scanning; /* parsing in "scanning" phase (first pass) */
+ duk_uint8_t may_direct_eval; /* function may call direct eval */
+ duk_uint8_t id_access_arguments; /* function refers to 'arguments' identifier */
+ duk_uint8_t id_access_slow; /* function makes one or more slow path accesses that won't match own static variables */
+ duk_uint8_t id_access_slow_own; /* function makes one or more slow path accesses that may match own static variables */
+ duk_uint8_t is_arguments_shadowed; /* argument/function declaration shadows 'arguments' */
+ duk_uint8_t needs_shuffle; /* function needs shuffle registers */
+ duk_uint8_t
+ reject_regexp_in_adv; /* reject RegExp literal on next advance() call; needed for handling IdentifierName productions */
+ duk_uint8_t allow_regexp_in_adv; /* allow RegExp literal on next advance() call */
};
struct duk_compiler_ctx {
duk_hthread *thr;
/* filename being compiled (ends up in functions' '_filename' property) */
- duk_hstring *h_filename; /* borrowed reference */
+ duk_hstring *h_filename; /* borrowed reference */
/* lexing (tokenization) state (contains two valstack slot indices) */
duk_lexer_ctx lex;
@@ -4076,10 +4441,10 @@ struct duk_compiler_ctx {
/* current and previous token for parsing */
duk_token prev_token;
duk_token curr_token;
- duk_idx_t tok11_idx; /* curr_token slot1 (matches 'lex' slot1_idx) */
- duk_idx_t tok12_idx; /* curr_token slot2 (matches 'lex' slot2_idx) */
- duk_idx_t tok21_idx; /* prev_token slot1 */
- duk_idx_t tok22_idx; /* prev_token slot2 */
+ duk_idx_t tok11_idx; /* curr_token slot1 (matches 'lex' slot1_idx) */
+ duk_idx_t tok12_idx; /* curr_token slot2 (matches 'lex' slot2_idx) */
+ duk_idx_t tok21_idx; /* prev_token slot1 */
+ duk_idx_t tok22_idx; /* prev_token slot2 */
/* recursion limit */
duk_int_t recursion_depth;
@@ -4096,9 +4461,12 @@ struct duk_compiler_ctx {
* Prototypes
*/
-DUK_INTERNAL_DECL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t src_length, duk_small_uint_t flags);
+DUK_INTERNAL_DECL void duk_js_compile(duk_hthread *thr,
+ const duk_uint8_t *src_buffer,
+ duk_size_t src_length,
+ duk_small_uint_t flags);
-#endif /* DUK_JS_COMPILER_H_INCLUDED */
+#endif /* DUK_JS_COMPILER_H_INCLUDED */
/* #include duk_regexp.h */
/*
* Regular expression structs, constants, and bytecode defines.
@@ -4108,39 +4476,39 @@ DUK_INTERNAL_DECL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_b
#define DUK_REGEXP_H_INCLUDED
/* maximum bytecode copies for {n,m} quantifiers */
-#define DUK_RE_MAX_ATOM_COPIES 1000
+#define DUK_RE_MAX_ATOM_COPIES 1000
/* regexp compilation limits */
-#define DUK_RE_COMPILE_TOKEN_LIMIT 100000000L /* 1e8 */
+#define DUK_RE_COMPILE_TOKEN_LIMIT 100000000L /* 1e8 */
/* regexp execution limits */
-#define DUK_RE_EXECUTE_STEPS_LIMIT 1000000000L /* 1e9 */
+#define DUK_RE_EXECUTE_STEPS_LIMIT 1000000000L /* 1e9 */
/* regexp opcodes */
-#define DUK_REOP_MATCH 1
-#define DUK_REOP_CHAR 2
-#define DUK_REOP_PERIOD 3
-#define DUK_REOP_RANGES 4
-#define DUK_REOP_INVRANGES 5
-#define DUK_REOP_JUMP 6
-#define DUK_REOP_SPLIT1 7
-#define DUK_REOP_SPLIT2 8
-#define DUK_REOP_SQMINIMAL 9
-#define DUK_REOP_SQGREEDY 10
-#define DUK_REOP_SAVE 11
-#define DUK_REOP_WIPERANGE 12
-#define DUK_REOP_LOOKPOS 13
-#define DUK_REOP_LOOKNEG 14
-#define DUK_REOP_BACKREFERENCE 15
-#define DUK_REOP_ASSERT_START 16
-#define DUK_REOP_ASSERT_END 17
-#define DUK_REOP_ASSERT_WORD_BOUNDARY 18
-#define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY 19
+#define DUK_REOP_MATCH 1
+#define DUK_REOP_CHAR 2
+#define DUK_REOP_PERIOD 3
+#define DUK_REOP_RANGES 4
+#define DUK_REOP_INVRANGES 5
+#define DUK_REOP_JUMP 6
+#define DUK_REOP_SPLIT1 7
+#define DUK_REOP_SPLIT2 8
+#define DUK_REOP_SQMINIMAL 9
+#define DUK_REOP_SQGREEDY 10
+#define DUK_REOP_SAVE 11
+#define DUK_REOP_WIPERANGE 12
+#define DUK_REOP_LOOKPOS 13
+#define DUK_REOP_LOOKNEG 14
+#define DUK_REOP_BACKREFERENCE 15
+#define DUK_REOP_ASSERT_START 16
+#define DUK_REOP_ASSERT_END 17
+#define DUK_REOP_ASSERT_WORD_BOUNDARY 18
+#define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY 19
/* flags */
-#define DUK_RE_FLAG_GLOBAL (1U << 0)
-#define DUK_RE_FLAG_IGNORE_CASE (1U << 1)
-#define DUK_RE_FLAG_MULTILINE (1U << 2)
+#define DUK_RE_FLAG_GLOBAL (1U << 0)
+#define DUK_RE_FLAG_IGNORE_CASE (1U << 1)
+#define DUK_RE_FLAG_MULTILINE (1U << 2)
struct duk_re_matcher_ctx {
duk_hthread *thr;
@@ -4150,7 +4518,7 @@ struct duk_re_matcher_ctx {
const duk_uint8_t *input_end;
const duk_uint8_t *bytecode;
const duk_uint8_t *bytecode_end;
- const duk_uint8_t **saved; /* allocated from valstack (fixed buffer) */
+ const duk_uint8_t **saved; /* allocated from valstack (fixed buffer) */
duk_uint32_t nsaved;
duk_uint32_t recursion_depth;
duk_uint32_t recursion_limit;
@@ -4165,11 +4533,11 @@ struct duk_re_compiler_ctx {
duk_lexer_ctx lex;
duk_re_token curr_token;
duk_bufwriter_ctx bw;
- duk_uint32_t captures; /* highest capture number emitted so far (used as: ++captures) */
+ duk_uint32_t captures; /* highest capture number emitted so far (used as: ++captures) */
duk_uint32_t highest_backref;
duk_uint32_t recursion_depth;
duk_uint32_t recursion_limit;
- duk_uint32_t nranges; /* internal temporary value, used for char classes */
+ duk_uint32_t nranges; /* internal temporary value, used for char classes */
};
/*
@@ -4180,10 +4548,10 @@ struct duk_re_compiler_ctx {
DUK_INTERNAL_DECL void duk_regexp_compile(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_regexp_create_instance(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_regexp_match(duk_hthread *thr);
-DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr); /* hacky helper for String.prototype.split() */
+DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr); /* hacky helper for String.prototype.split() */
#endif
-#endif /* DUK_REGEXP_H_INCLUDED */
+#endif /* DUK_REGEXP_H_INCLUDED */
/* #include duk_heaphdr.h */
/*
* Heap header definition and assorted macros, including ref counting.
@@ -4219,9 +4587,6 @@ DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr); /* hack
/* XXX: macro for shared header fields (avoids some padding issues) */
-#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
-#pragma pack(push, 8)
-#endif
struct duk_heaphdr {
duk_uint32_t h_flags;
@@ -4239,7 +4604,7 @@ struct duk_heaphdr {
#else
duk_size_t h_refcount;
#endif
-#endif /* DUK_USE_REFERENCE_COUNTING */
+#endif /* DUK_USE_REFERENCE_COUNTING */
#if defined(DUK_USE_HEAPPTR16)
duk_uint16_t h_next16;
@@ -4267,16 +4632,7 @@ struct duk_heaphdr {
#if defined(DUK_USE_HEAPPTR16)
duk_uint16_t h_extra16;
#endif
-}
-#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR)
-__attribute__ ((aligned (8)))
-#elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR)
-__attribute__ ((aligned (8)))
-#endif
-;
-#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
-#pragma pack(pop)
-#endif
+};
struct duk_heaphdr_string {
/* 16 bits would be enough for shared heaphdr flags and duk_hstring
@@ -4296,7 +4652,7 @@ struct duk_heaphdr_string {
#endif
#if defined(DUK_USE_REFCOUNT16)
duk_uint16_t h_refcount;
- duk_uint16_t h_strextra16; /* round out to 8 bytes */
+ duk_uint16_t h_strextra16; /* round out to 8 bytes */
#elif defined(DUK_USE_REFCOUNT32)
duk_uint32_t h_refcount;
#else
@@ -4304,160 +4660,169 @@ struct duk_heaphdr_string {
#endif
#else
duk_uint16_t h_strextra16;
-#endif /* DUK_USE_REFERENCE_COUNTING */
+#endif /* DUK_USE_REFERENCE_COUNTING */
duk_hstring *h_next;
/* No 'h_prev' pointer for strings. */
};
-#define DUK_HEAPHDR_FLAGS_TYPE_MASK 0x00000003UL
-#define DUK_HEAPHDR_FLAGS_FLAG_MASK (~DUK_HEAPHDR_FLAGS_TYPE_MASK)
+#define DUK_HEAPHDR_FLAGS_TYPE_MASK 0x00000003UL
+#define DUK_HEAPHDR_FLAGS_FLAG_MASK (~DUK_HEAPHDR_FLAGS_TYPE_MASK)
- /* 2 bits for heap type */
-#define DUK_HEAPHDR_FLAGS_HEAP_START 2 /* 5 heap flags */
-#define DUK_HEAPHDR_FLAGS_USER_START 7 /* 25 user flags */
+/* 2 bits for heap type */
+#define DUK_HEAPHDR_FLAGS_HEAP_START 2 /* 5 heap flags */
+#define DUK_HEAPHDR_FLAGS_USER_START 7 /* 25 user flags */
-#define DUK_HEAPHDR_HEAP_FLAG_NUMBER(n) (DUK_HEAPHDR_FLAGS_HEAP_START + (n))
-#define DUK_HEAPHDR_USER_FLAG_NUMBER(n) (DUK_HEAPHDR_FLAGS_USER_START + (n))
-#define DUK_HEAPHDR_HEAP_FLAG(n) (1UL << (DUK_HEAPHDR_FLAGS_HEAP_START + (n)))
-#define DUK_HEAPHDR_USER_FLAG(n) (1UL << (DUK_HEAPHDR_FLAGS_USER_START + (n)))
+#define DUK_HEAPHDR_HEAP_FLAG_NUMBER(n) (DUK_HEAPHDR_FLAGS_HEAP_START + (n))
+#define DUK_HEAPHDR_USER_FLAG_NUMBER(n) (DUK_HEAPHDR_FLAGS_USER_START + (n))
+#define DUK_HEAPHDR_HEAP_FLAG(n) (1UL << (DUK_HEAPHDR_FLAGS_HEAP_START + (n)))
+#define DUK_HEAPHDR_USER_FLAG(n) (1UL << (DUK_HEAPHDR_FLAGS_USER_START + (n)))
-#define DUK_HEAPHDR_FLAG_REACHABLE DUK_HEAPHDR_HEAP_FLAG(0) /* mark-and-sweep: reachable */
-#define DUK_HEAPHDR_FLAG_TEMPROOT DUK_HEAPHDR_HEAP_FLAG(1) /* mark-and-sweep: children not processed */
-#define DUK_HEAPHDR_FLAG_FINALIZABLE DUK_HEAPHDR_HEAP_FLAG(2) /* mark-and-sweep: finalizable (on current pass) */
-#define DUK_HEAPHDR_FLAG_FINALIZED DUK_HEAPHDR_HEAP_FLAG(3) /* mark-and-sweep: finalized (on previous pass) */
-#define DUK_HEAPHDR_FLAG_READONLY DUK_HEAPHDR_HEAP_FLAG(4) /* read-only object, in code section */
+#define DUK_HEAPHDR_FLAG_REACHABLE DUK_HEAPHDR_HEAP_FLAG(0) /* mark-and-sweep: reachable */
+#define DUK_HEAPHDR_FLAG_TEMPROOT DUK_HEAPHDR_HEAP_FLAG(1) /* mark-and-sweep: children not processed */
+#define DUK_HEAPHDR_FLAG_FINALIZABLE DUK_HEAPHDR_HEAP_FLAG(2) /* mark-and-sweep: finalizable (on current pass) */
+#define DUK_HEAPHDR_FLAG_FINALIZED DUK_HEAPHDR_HEAP_FLAG(3) /* mark-and-sweep: finalized (on previous pass) */
+#define DUK_HEAPHDR_FLAG_READONLY DUK_HEAPHDR_HEAP_FLAG(4) /* read-only object, in code section */
-#define DUK_HTYPE_MIN 0
-#define DUK_HTYPE_STRING 0
-#define DUK_HTYPE_OBJECT 1
-#define DUK_HTYPE_BUFFER 2
-#define DUK_HTYPE_MAX 2
+#define DUK_HTYPE_MIN 0
+#define DUK_HTYPE_STRING 0
+#define DUK_HTYPE_OBJECT 1
+#define DUK_HTYPE_BUFFER 2
+#define DUK_HTYPE_MAX 2
#if defined(DUK_USE_HEAPPTR16)
-#define DUK_HEAPHDR_GET_NEXT(heap,h) \
- ((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_next16))
-#define DUK_HEAPHDR_SET_NEXT(heap,h,val) do { \
+#define DUK_HEAPHDR_GET_NEXT(heap, h) ((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_next16))
+#define DUK_HEAPHDR_SET_NEXT(heap, h, val) \
+ do { \
(h)->h_next16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) val); \
} while (0)
#else
-#define DUK_HEAPHDR_GET_NEXT(heap,h) ((h)->h_next)
-#define DUK_HEAPHDR_SET_NEXT(heap,h,val) do { \
+#define DUK_HEAPHDR_GET_NEXT(heap, h) ((h)->h_next)
+#define DUK_HEAPHDR_SET_NEXT(heap, h, val) \
+ do { \
(h)->h_next = (val); \
} while (0)
#endif
#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
#if defined(DUK_USE_HEAPPTR16)
-#define DUK_HEAPHDR_GET_PREV(heap,h) \
- ((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_prev16))
-#define DUK_HEAPHDR_SET_PREV(heap,h,val) do { \
+#define DUK_HEAPHDR_GET_PREV(heap, h) ((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_prev16))
+#define DUK_HEAPHDR_SET_PREV(heap, h, val) \
+ do { \
(h)->h_prev16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (val)); \
} while (0)
#else
-#define DUK_HEAPHDR_GET_PREV(heap,h) ((h)->h_prev)
-#define DUK_HEAPHDR_SET_PREV(heap,h,val) do { \
+#define DUK_HEAPHDR_GET_PREV(heap, h) ((h)->h_prev)
+#define DUK_HEAPHDR_SET_PREV(heap, h, val) \
+ do { \
(h)->h_prev = (val); \
} while (0)
#endif
#endif
#if defined(DUK_USE_REFERENCE_COUNTING)
-#define DUK_HEAPHDR_GET_REFCOUNT(h) ((h)->h_refcount)
-#define DUK_HEAPHDR_SET_REFCOUNT(h,val) do { \
+#define DUK_HEAPHDR_GET_REFCOUNT(h) ((h)->h_refcount)
+#define DUK_HEAPHDR_SET_REFCOUNT(h, val) \
+ do { \
(h)->h_refcount = (val); \
- DUK_ASSERT((h)->h_refcount == (val)); /* No truncation. */ \
+ DUK_ASSERT((h)->h_refcount == (val)); /* No truncation. */ \
} while (0)
-#define DUK_HEAPHDR_PREINC_REFCOUNT(h) (++(h)->h_refcount) /* result: updated refcount */
-#define DUK_HEAPHDR_PREDEC_REFCOUNT(h) (--(h)->h_refcount) /* result: updated refcount */
+#define DUK_HEAPHDR_PREINC_REFCOUNT(h) (++(h)->h_refcount) /* result: updated refcount */
+#define DUK_HEAPHDR_PREDEC_REFCOUNT(h) (--(h)->h_refcount) /* result: updated refcount */
#else
/* refcount macros not defined without refcounting, caller must #if defined() now */
-#endif /* DUK_USE_REFERENCE_COUNTING */
+#endif /* DUK_USE_REFERENCE_COUNTING */
/*
* Note: type is treated as a field separate from flags, so some masking is
* involved in the macros below.
*/
-#define DUK_HEAPHDR_GET_FLAGS_RAW(h) ((h)->h_flags)
-#define DUK_HEAPHDR_SET_FLAGS_RAW(h,val) do { \
- (h)->h_flags = (val); } \
+#define DUK_HEAPHDR_GET_FLAGS_RAW(h) ((h)->h_flags)
+#define DUK_HEAPHDR_SET_FLAGS_RAW(h, val) \
+ do { \
+ (h)->h_flags = (val); \
+ } \
}
-#define DUK_HEAPHDR_GET_FLAGS(h) ((h)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK)
-#define DUK_HEAPHDR_SET_FLAGS(h,val) do { \
+#define DUK_HEAPHDR_GET_FLAGS(h) ((h)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK)
+#define DUK_HEAPHDR_SET_FLAGS(h, val) \
+ do { \
(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) | (val); \
} while (0)
-#define DUK_HEAPHDR_GET_TYPE(h) ((h)->h_flags & DUK_HEAPHDR_FLAGS_TYPE_MASK)
-#define DUK_HEAPHDR_SET_TYPE(h,val) do { \
+#define DUK_HEAPHDR_GET_TYPE(h) ((h)->h_flags & DUK_HEAPHDR_FLAGS_TYPE_MASK)
+#define DUK_HEAPHDR_SET_TYPE(h, val) \
+ do { \
(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_TYPE_MASK)) | (val); \
} while (0)
/* Comparison for type >= DUK_HTYPE_MIN skipped; because DUK_HTYPE_MIN is zero
* and the comparison is unsigned, it's always true and generates warnings.
*/
-#define DUK_HEAPHDR_HTYPE_VALID(h) ( \
- DUK_HEAPHDR_GET_TYPE((h)) <= DUK_HTYPE_MAX \
- )
+#define DUK_HEAPHDR_HTYPE_VALID(h) (DUK_HEAPHDR_GET_TYPE((h)) <= DUK_HTYPE_MAX)
-#define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h,tval,fval) do { \
- (h)->h_flags = ((tval) & DUK_HEAPHDR_FLAGS_TYPE_MASK) | \
- ((fval) & DUK_HEAPHDR_FLAGS_FLAG_MASK); \
+#define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h, tval, fval) \
+ do { \
+ (h)->h_flags = ((tval) &DUK_HEAPHDR_FLAGS_TYPE_MASK) | ((fval) &DUK_HEAPHDR_FLAGS_FLAG_MASK); \
} while (0)
-#define DUK_HEAPHDR_SET_FLAG_BITS(h,bits) do { \
+#define DUK_HEAPHDR_SET_FLAG_BITS(h, bits) \
+ do { \
DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
(h)->h_flags |= (bits); \
} while (0)
-#define DUK_HEAPHDR_CLEAR_FLAG_BITS(h,bits) do { \
+#define DUK_HEAPHDR_CLEAR_FLAG_BITS(h, bits) \
+ do { \
DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
(h)->h_flags &= ~((bits)); \
} while (0)
-#define DUK_HEAPHDR_CHECK_FLAG_BITS(h,bits) (((h)->h_flags & (bits)) != 0)
+#define DUK_HEAPHDR_CHECK_FLAG_BITS(h, bits) (((h)->h_flags & (bits)) != 0)
-#define DUK_HEAPHDR_SET_REACHABLE(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
-#define DUK_HEAPHDR_CLEAR_REACHABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
-#define DUK_HEAPHDR_HAS_REACHABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
+#define DUK_HEAPHDR_SET_REACHABLE(h) DUK_HEAPHDR_SET_FLAG_BITS((h), DUK_HEAPHDR_FLAG_REACHABLE)
+#define DUK_HEAPHDR_CLEAR_REACHABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h), DUK_HEAPHDR_FLAG_REACHABLE)
+#define DUK_HEAPHDR_HAS_REACHABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h), DUK_HEAPHDR_FLAG_REACHABLE)
-#define DUK_HEAPHDR_SET_TEMPROOT(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
-#define DUK_HEAPHDR_CLEAR_TEMPROOT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
-#define DUK_HEAPHDR_HAS_TEMPROOT(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
+#define DUK_HEAPHDR_SET_TEMPROOT(h) DUK_HEAPHDR_SET_FLAG_BITS((h), DUK_HEAPHDR_FLAG_TEMPROOT)
+#define DUK_HEAPHDR_CLEAR_TEMPROOT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h), DUK_HEAPHDR_FLAG_TEMPROOT)
+#define DUK_HEAPHDR_HAS_TEMPROOT(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h), DUK_HEAPHDR_FLAG_TEMPROOT)
-#define DUK_HEAPHDR_SET_FINALIZABLE(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
-#define DUK_HEAPHDR_CLEAR_FINALIZABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
-#define DUK_HEAPHDR_HAS_FINALIZABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
+#define DUK_HEAPHDR_SET_FINALIZABLE(h) DUK_HEAPHDR_SET_FLAG_BITS((h), DUK_HEAPHDR_FLAG_FINALIZABLE)
+#define DUK_HEAPHDR_CLEAR_FINALIZABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h), DUK_HEAPHDR_FLAG_FINALIZABLE)
+#define DUK_HEAPHDR_HAS_FINALIZABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h), DUK_HEAPHDR_FLAG_FINALIZABLE)
-#define DUK_HEAPHDR_SET_FINALIZED(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
-#define DUK_HEAPHDR_CLEAR_FINALIZED(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
-#define DUK_HEAPHDR_HAS_FINALIZED(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
+#define DUK_HEAPHDR_SET_FINALIZED(h) DUK_HEAPHDR_SET_FLAG_BITS((h), DUK_HEAPHDR_FLAG_FINALIZED)
+#define DUK_HEAPHDR_CLEAR_FINALIZED(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h), DUK_HEAPHDR_FLAG_FINALIZED)
+#define DUK_HEAPHDR_HAS_FINALIZED(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h), DUK_HEAPHDR_FLAG_FINALIZED)
-#define DUK_HEAPHDR_SET_READONLY(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
-#define DUK_HEAPHDR_CLEAR_READONLY(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
-#define DUK_HEAPHDR_HAS_READONLY(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
+#define DUK_HEAPHDR_SET_READONLY(h) DUK_HEAPHDR_SET_FLAG_BITS((h), DUK_HEAPHDR_FLAG_READONLY)
+#define DUK_HEAPHDR_CLEAR_READONLY(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h), DUK_HEAPHDR_FLAG_READONLY)
+#define DUK_HEAPHDR_HAS_READONLY(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h), DUK_HEAPHDR_FLAG_READONLY)
/* get or set a range of flags; m=first bit number, n=number of bits */
-#define DUK_HEAPHDR_GET_FLAG_RANGE(h,m,n) (((h)->h_flags >> (m)) & ((1UL << (n)) - 1UL))
+#define DUK_HEAPHDR_GET_FLAG_RANGE(h, m, n) (((h)->h_flags >> (m)) & ((1UL << (n)) - 1UL))
-#define DUK_HEAPHDR_SET_FLAG_RANGE(h,m,n,v) do { \
- (h)->h_flags = \
- ((h)->h_flags & (~(((1UL << (n)) - 1UL) << (m)))) \
- | ((v) << (m)); \
+#define DUK_HEAPHDR_SET_FLAG_RANGE(h, m, n, v) \
+ do { \
+ (h)->h_flags = ((h)->h_flags & (~(((1UL << (n)) - 1UL) << (m)))) | ((v) << (m)); \
} while (0)
/* init pointer fields to null */
#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
-#define DUK_HEAPHDR_INIT_NULLS(h) do { \
+#define DUK_HEAPHDR_INIT_NULLS(h) \
+ do { \
DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
DUK_HEAPHDR_SET_PREV((h), (void *) NULL); \
} while (0)
#else
-#define DUK_HEAPHDR_INIT_NULLS(h) do { \
+#define DUK_HEAPHDR_INIT_NULLS(h) \
+ do { \
DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
} while (0)
#endif
-#define DUK_HEAPHDR_STRING_INIT_NULLS(h) do { \
+#define DUK_HEAPHDR_STRING_INIT_NULLS(h) \
+ do { \
(h)->h_next = NULL; \
} while (0)
@@ -4482,26 +4847,28 @@ struct duk_heaphdr_string {
/* Check that prev/next links are consistent: if e.g. h->prev is != NULL,
* h->prev->next should point back to h.
*/
-#if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_ASSERTIONS)
-#define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do { \
- if ((h) != NULL) { \
- duk_heaphdr *h__prev, *h__next; \
- h__prev = DUK_HEAPHDR_GET_PREV((heap), (h)); \
- h__next = DUK_HEAPHDR_GET_NEXT((heap), (h)); \
- DUK_ASSERT(h__prev == NULL || (DUK_HEAPHDR_GET_NEXT((heap), h__prev) == (h))); \
- DUK_ASSERT(h__next == NULL || (DUK_HEAPHDR_GET_PREV((heap), h__next) == (h))); \
- } \
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_heaphdr_assert_valid_subclassed(duk_heaphdr *h);
+DUK_INTERNAL_DECL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h);
+DUK_INTERNAL_DECL void duk_heaphdr_assert_valid(duk_heaphdr *h);
+#define DUK_HEAPHDR_ASSERT_LINKS(heap, h) \
+ do { \
+ duk_heaphdr_assert_links((heap), (h)); \
+ } while (0)
+#define DUK_HEAPHDR_ASSERT_VALID(h) \
+ do { \
+ duk_heaphdr_assert_valid((h)); \
} while (0)
#else
-#define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do {} while (0)
-#endif
-
-#define DUK_ASSERT_HEAPHDR_VALID(h) do { \
- DUK_ASSERT((h) != NULL); \
- DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID((h))); \
+#define DUK_HEAPHDR_ASSERT_LINKS(heap, h) \
+ do { \
+ } while (0)
+#define DUK_HEAPHDR_ASSERT_VALID(h) \
+ do { \
} while (0)
+#endif
-#endif /* DUK_HEAPHDR_H_INCLUDED */
+#endif /* DUK_HEAPHDR_H_INCLUDED */
/* #include duk_refcount.h */
/*
* Reference counting helper macros. The macros take a thread argument
@@ -4522,19 +4889,20 @@ struct duk_heaphdr_string {
/* XXX: double evaluation for 'tv' argument. */
#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) \
(DUK_TVAL_IS_HEAP_ALLOCATED((tv)) && !DUK_HEAPHDR_HAS_READONLY(DUK_TVAL_GET_HEAPHDR((tv))))
-#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) (!DUK_HEAPHDR_HAS_READONLY((h)))
-#else /* DUK_USE_ROM_OBJECTS */
+#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) (!DUK_HEAPHDR_HAS_READONLY((h)))
+#else /* DUK_USE_ROM_OBJECTS */
/* Without ROM objects "needs refcount update" == is heap allocated. */
-#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) DUK_TVAL_IS_HEAP_ALLOCATED((tv))
-#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) 1
-#endif /* DUK_USE_ROM_OBJECTS */
+#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) DUK_TVAL_IS_HEAP_ALLOCATED((tv))
+#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) 1
+#endif /* DUK_USE_ROM_OBJECTS */
/* Fast variants, inline refcount operations except for refzero handling.
* Can be used explicitly when speed is always more important than size.
* For a good compiler and a single file build, these are basically the
* same as a forced inline.
*/
-#define DUK_TVAL_INCREF_FAST(thr,tv) do { \
+#define DUK_TVAL_INCREF_FAST(thr, tv) \
+ do { \
duk_tval *duk__tv = (tv); \
DUK_ASSERT(duk__tv != NULL); \
if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
@@ -4542,10 +4910,11 @@ struct duk_heaphdr_string {
DUK_ASSERT(duk__h != NULL); \
DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
- DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0); /* No wrapping. */ \
+ DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0); /* No wrapping. */ \
} \
} while (0)
-#define DUK_TVAL_DECREF_FAST(thr,tv) do { \
+#define DUK_TVAL_DECREF_FAST(thr, tv) \
+ do { \
duk_tval *duk__tv = (tv); \
DUK_ASSERT(duk__tv != NULL); \
if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
@@ -4558,7 +4927,8 @@ struct duk_heaphdr_string {
} \
} \
} while (0)
-#define DUK_TVAL_DECREF_NORZ_FAST(thr,tv) do { \
+#define DUK_TVAL_DECREF_NORZ_FAST(thr, tv) \
+ do { \
duk_tval *duk__tv = (tv); \
DUK_ASSERT(duk__tv != NULL); \
if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
@@ -4571,16 +4941,18 @@ struct duk_heaphdr_string {
} \
} \
} while (0)
-#define DUK_HEAPHDR_INCREF_FAST(thr,h) do { \
+#define DUK_HEAPHDR_INCREF_FAST(thr, h) \
+ do { \
duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
DUK_ASSERT(duk__h != NULL); \
DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
- DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0); /* No wrapping. */ \
+ DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0); /* No wrapping. */ \
} \
} while (0)
-#define DUK_HEAPHDR_DECREF_FAST_RAW(thr,h,rzcall,rzcast) do { \
+#define DUK_HEAPHDR_DECREF_FAST_RAW(thr, h, rzcall, rzcast) \
+ do { \
duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
DUK_ASSERT(duk__h != NULL); \
DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
@@ -4591,29 +4963,72 @@ struct duk_heaphdr_string {
} \
} \
} while (0)
-#define DUK_HEAPHDR_DECREF_FAST(thr,h) \
- DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *)
-#define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h) \
- DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *)
+#define DUK_HEAPHDR_DECREF_FAST(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_heaphdr_refzero, duk_heaphdr *)
+#define DUK_HEAPHDR_DECREF_NORZ_FAST(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_heaphdr_refzero_norz, duk_heaphdr *)
/* Slow variants, call to a helper to reduce code size.
* Can be used explicitly when size is always more important than speed.
*/
-#define DUK_TVAL_INCREF_SLOW(thr,tv) do { duk_tval_incref((tv)); } while (0)
-#define DUK_TVAL_DECREF_SLOW(thr,tv) do { duk_tval_decref((thr), (tv)); } while (0)
-#define DUK_TVAL_DECREF_NORZ_SLOW(thr,tv) do { duk_tval_decref_norz((thr), (tv)); } while (0)
-#define DUK_HEAPHDR_INCREF_SLOW(thr,h) do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
-#define DUK_HEAPHDR_DECREF_SLOW(thr,h) do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
-#define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h) do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
-#define DUK_HSTRING_INCREF_SLOW(thr,h) do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
-#define DUK_HSTRING_DECREF_SLOW(thr,h) do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
-#define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h) do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
-#define DUK_HBUFFER_INCREF_SLOW(thr,h) do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
-#define DUK_HBUFFER_DECREF_SLOW(thr,h) do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
-#define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h) do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
-#define DUK_HOBJECT_INCREF_SLOW(thr,h) do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
-#define DUK_HOBJECT_DECREF_SLOW(thr,h) do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
-#define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h) do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
+#define DUK_TVAL_INCREF_SLOW(thr, tv) \
+ do { \
+ duk_tval_incref((tv)); \
+ } while (0)
+#define DUK_TVAL_DECREF_SLOW(thr, tv) \
+ do { \
+ duk_tval_decref((thr), (tv)); \
+ } while (0)
+#define DUK_TVAL_DECREF_NORZ_SLOW(thr, tv) \
+ do { \
+ duk_tval_decref_norz((thr), (tv)); \
+ } while (0)
+#define DUK_HEAPHDR_INCREF_SLOW(thr, h) \
+ do { \
+ duk_heaphdr_incref((duk_heaphdr *) (h)); \
+ } while (0)
+#define DUK_HEAPHDR_DECREF_SLOW(thr, h) \
+ do { \
+ duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); \
+ } while (0)
+#define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr, h) \
+ do { \
+ duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); \
+ } while (0)
+#define DUK_HSTRING_INCREF_SLOW(thr, h) \
+ do { \
+ duk_heaphdr_incref((duk_heaphdr *) (h)); \
+ } while (0)
+#define DUK_HSTRING_DECREF_SLOW(thr, h) \
+ do { \
+ duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); \
+ } while (0)
+#define DUK_HSTRING_DECREF_NORZ_SLOW(thr, h) \
+ do { \
+ duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); \
+ } while (0)
+#define DUK_HBUFFER_INCREF_SLOW(thr, h) \
+ do { \
+ duk_heaphdr_incref((duk_heaphdr *) (h)); \
+ } while (0)
+#define DUK_HBUFFER_DECREF_SLOW(thr, h) \
+ do { \
+ duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); \
+ } while (0)
+#define DUK_HBUFFER_DECREF_NORZ_SLOW(thr, h) \
+ do { \
+ duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); \
+ } while (0)
+#define DUK_HOBJECT_INCREF_SLOW(thr, h) \
+ do { \
+ duk_heaphdr_incref((duk_heaphdr *) (h)); \
+ } while (0)
+#define DUK_HOBJECT_DECREF_SLOW(thr, h) \
+ do { \
+ duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); \
+ } while (0)
+#define DUK_HOBJECT_DECREF_NORZ_SLOW(thr, h) \
+ do { \
+ duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); \
+ } while (0)
/* Default variants. Selection depends on speed/size preference.
* Concretely: with gcc 4.8.1 -Os x64 the difference in final binary
@@ -4623,122 +5038,136 @@ struct duk_heaphdr_string {
/* XXX: It would be nice to specialize for specific duk_hobject subtypes
* but current refzero queue handling prevents that.
*/
-#define DUK_TVAL_INCREF(thr,tv) DUK_TVAL_INCREF_FAST((thr),(tv))
-#define DUK_TVAL_DECREF(thr,tv) DUK_TVAL_DECREF_FAST((thr),(tv))
-#define DUK_TVAL_DECREF_NORZ(thr,tv) DUK_TVAL_DECREF_NORZ_FAST((thr),(tv))
-#define DUK_HEAPHDR_INCREF(thr,h) DUK_HEAPHDR_INCREF_FAST((thr),(h))
-#define DUK_HEAPHDR_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *)
-#define DUK_HEAPHDR_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *)
-#define DUK_HSTRING_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
-#define DUK_HSTRING_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *)
-#define DUK_HSTRING_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *) /* no 'norz' variant */
-#define DUK_HOBJECT_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
-#define DUK_HOBJECT_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
-#define DUK_HOBJECT_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
-#define DUK_HBUFFER_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
-#define DUK_HBUFFER_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *)
-#define DUK_HBUFFER_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *) /* no 'norz' variant */
-#define DUK_HCOMPFUNC_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
-#define DUK_HCOMPFUNC_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
-#define DUK_HCOMPFUNC_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
-#define DUK_HNATFUNC_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
-#define DUK_HNATFUNC_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
-#define DUK_HNATFUNC_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
-#define DUK_HBUFOBJ_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
-#define DUK_HBUFOBJ_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
-#define DUK_HBUFOBJ_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
-#define DUK_HTHREAD_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
-#define DUK_HTHREAD_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
-#define DUK_HTHREAD_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
+#define DUK_TVAL_INCREF(thr, tv) DUK_TVAL_INCREF_FAST((thr), (tv))
+#define DUK_TVAL_DECREF(thr, tv) DUK_TVAL_DECREF_FAST((thr), (tv))
+#define DUK_TVAL_DECREF_NORZ(thr, tv) DUK_TVAL_DECREF_NORZ_FAST((thr), (tv))
+#define DUK_HEAPHDR_INCREF(thr, h) DUK_HEAPHDR_INCREF_FAST((thr), (h))
+#define DUK_HEAPHDR_DECREF(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_heaphdr_refzero, duk_heaphdr *)
+#define DUK_HEAPHDR_DECREF_NORZ(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_heaphdr_refzero_norz, duk_heaphdr *)
+#define DUK_HSTRING_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h))
+#define DUK_HSTRING_DECREF(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hstring_refzero, duk_hstring *)
+#define DUK_HSTRING_DECREF_NORZ(thr, h) \
+ DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hstring_refzero, duk_hstring *) /* no 'norz' variant */
+#define DUK_HOBJECT_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h))
+#define DUK_HOBJECT_DECREF(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero, duk_hobject *)
+#define DUK_HOBJECT_DECREF_NORZ(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero_norz, duk_hobject *)
+#define DUK_HBUFFER_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h))
+#define DUK_HBUFFER_DECREF(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hbuffer_refzero, duk_hbuffer *)
+#define DUK_HBUFFER_DECREF_NORZ(thr, h) \
+ DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hbuffer_refzero, duk_hbuffer *) /* no 'norz' variant */
+#define DUK_HCOMPFUNC_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) &(h)->obj)
+#define DUK_HCOMPFUNC_DECREF(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero, duk_hobject *)
+#define DUK_HCOMPFUNC_DECREF_NORZ(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero_norz, duk_hobject *)
+#define DUK_HNATFUNC_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) &(h)->obj)
+#define DUK_HNATFUNC_DECREF(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero, duk_hobject *)
+#define DUK_HNATFUNC_DECREF_NORZ(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero_norz, duk_hobject *)
+#define DUK_HBUFOBJ_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) &(h)->obj)
+#define DUK_HBUFOBJ_DECREF(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero, duk_hobject *)
+#define DUK_HBUFOBJ_DECREF_NORZ(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero_norz, duk_hobject *)
+#define DUK_HTHREAD_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) &(h)->obj)
+#define DUK_HTHREAD_DECREF(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero, duk_hobject *)
+#define DUK_HTHREAD_DECREF_NORZ(thr, h) DUK_HEAPHDR_DECREF_FAST_RAW((thr), (h), duk_hobject_refzero_norz, duk_hobject *)
#else
-#define DUK_TVAL_INCREF(thr,tv) DUK_TVAL_INCREF_SLOW((thr),(tv))
-#define DUK_TVAL_DECREF(thr,tv) DUK_TVAL_DECREF_SLOW((thr),(tv))
-#define DUK_TVAL_DECREF_NORZ(thr,tv) DUK_TVAL_DECREF_NORZ_SLOW((thr),(tv))
-#define DUK_HEAPHDR_INCREF(thr,h) DUK_HEAPHDR_INCREF_SLOW((thr),(h))
-#define DUK_HEAPHDR_DECREF(thr,h) DUK_HEAPHDR_DECREF_SLOW((thr),(h))
-#define DUK_HEAPHDR_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_NORZ_SLOW((thr),(h))
-#define DUK_HSTRING_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
-#define DUK_HSTRING_DECREF(thr,h) DUK_HSTRING_DECREF_SLOW((thr),(h))
-#define DUK_HSTRING_DECREF_NORZ(thr,h) DUK_HSTRING_DECREF_NORZ_SLOW((thr),(h))
-#define DUK_HOBJECT_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
-#define DUK_HOBJECT_DECREF(thr,h) DUK_HOBJECT_DECREF_SLOW((thr),(h))
-#define DUK_HOBJECT_DECREF_NORZ(thr,h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(h))
-#define DUK_HBUFFER_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
-#define DUK_HBUFFER_DECREF(thr,h) DUK_HBUFFER_DECREF_SLOW((thr),(h))
-#define DUK_HBUFFER_DECREF_NORZ(thr,h) DUK_HBUFFER_DECREF_NORZ_SLOW((thr),(h))
-#define DUK_HCOMPFUNC_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
-#define DUK_HCOMPFUNC_DECREF(thr,h) DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
-#define DUK_HCOMPFUNC_DECREF_NORZ(thr,h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
-#define DUK_HNATFUNC_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
-#define DUK_HNATFUNC_DECREF(thr,h) DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
-#define DUK_HNATFUNC_DECREF_NORZ(thr,h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
-#define DUK_HBUFOBJ_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
-#define DUK_HBUFOBJ_DECREF(thr,h) DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
-#define DUK_HBUFOB_DECREF_NORZ(thr,h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
-#define DUK_HTHREAD_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
-#define DUK_HTHREAD_DECREF(thr,h) DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
-#define DUK_HTHREAD_DECREF_NORZ(thr,h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
+#define DUK_TVAL_INCREF(thr, tv) DUK_TVAL_INCREF_SLOW((thr), (tv))
+#define DUK_TVAL_DECREF(thr, tv) DUK_TVAL_DECREF_SLOW((thr), (tv))
+#define DUK_TVAL_DECREF_NORZ(thr, tv) DUK_TVAL_DECREF_NORZ_SLOW((thr), (tv))
+#define DUK_HEAPHDR_INCREF(thr, h) DUK_HEAPHDR_INCREF_SLOW((thr), (h))
+#define DUK_HEAPHDR_DECREF(thr, h) DUK_HEAPHDR_DECREF_SLOW((thr), (h))
+#define DUK_HEAPHDR_DECREF_NORZ(thr, h) DUK_HEAPHDR_DECREF_NORZ_SLOW((thr), (h))
+#define DUK_HSTRING_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h))
+#define DUK_HSTRING_DECREF(thr, h) DUK_HSTRING_DECREF_SLOW((thr), (h))
+#define DUK_HSTRING_DECREF_NORZ(thr, h) DUK_HSTRING_DECREF_NORZ_SLOW((thr), (h))
+#define DUK_HOBJECT_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h))
+#define DUK_HOBJECT_DECREF(thr, h) DUK_HOBJECT_DECREF_SLOW((thr), (h))
+#define DUK_HOBJECT_DECREF_NORZ(thr, h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr), (h))
+#define DUK_HBUFFER_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h))
+#define DUK_HBUFFER_DECREF(thr, h) DUK_HBUFFER_DECREF_SLOW((thr), (h))
+#define DUK_HBUFFER_DECREF_NORZ(thr, h) DUK_HBUFFER_DECREF_NORZ_SLOW((thr), (h))
+#define DUK_HCOMPFUNC_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) &(h)->obj)
+#define DUK_HCOMPFUNC_DECREF(thr, h) DUK_HOBJECT_DECREF_SLOW((thr), (duk_hobject *) &(h)->obj)
+#define DUK_HCOMPFUNC_DECREF_NORZ(thr, h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr), (duk_hobject *) &(h)->obj)
+#define DUK_HNATFUNC_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) &(h)->obj)
+#define DUK_HNATFUNC_DECREF(thr, h) DUK_HOBJECT_DECREF_SLOW((thr), (duk_hobject *) &(h)->obj)
+#define DUK_HNATFUNC_DECREF_NORZ(thr, h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr), (duk_hobject *) &(h)->obj)
+#define DUK_HBUFOBJ_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) &(h)->obj)
+#define DUK_HBUFOBJ_DECREF(thr, h) DUK_HOBJECT_DECREF_SLOW((thr), (duk_hobject *) &(h)->obj)
+#define DUK_HBUFOB_DECREF_NORZ(thr, h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr), (duk_hobject *) &(h)->obj)
+#define DUK_HTHREAD_INCREF(thr, h) DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) &(h)->obj)
+#define DUK_HTHREAD_DECREF(thr, h) DUK_HOBJECT_DECREF_SLOW((thr), (duk_hobject *) &(h)->obj)
+#define DUK_HTHREAD_DECREF_NORZ(thr, h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr), (duk_hobject *) &(h)->obj)
#endif
/* Convenience for some situations; the above macros don't allow NULLs
* for performance reasons. Macros cover only actually needed cases.
*/
-#define DUK_HEAPHDR_INCREF_ALLOWNULL(thr,h) do { \
+#define DUK_HEAPHDR_INCREF_ALLOWNULL(thr, h) \
+ do { \
if ((h) != NULL) { \
DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h)); \
} \
} while (0)
-#define DUK_HEAPHDR_DECREF_ALLOWNULL(thr,h) do { \
+#define DUK_HEAPHDR_DECREF_ALLOWNULL(thr, h) \
+ do { \
if ((h) != NULL) { \
DUK_HEAPHDR_DECREF((thr), (duk_heaphdr *) (h)); \
} \
} while (0)
-#define DUK_HEAPHDR_DECREF_NORZ_ALLOWNULL(thr,h) do { \
+#define DUK_HEAPHDR_DECREF_NORZ_ALLOWNULL(thr, h) \
+ do { \
if ((h) != NULL) { \
DUK_HEAPHDR_DECREF_NORZ((thr), (duk_heaphdr *) (h)); \
} \
} while (0)
-#define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do { \
+#define DUK_HOBJECT_INCREF_ALLOWNULL(thr, h) \
+ do { \
if ((h) != NULL) { \
DUK_HOBJECT_INCREF((thr), (h)); \
} \
} while (0)
-#define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do { \
+#define DUK_HOBJECT_DECREF_ALLOWNULL(thr, h) \
+ do { \
if ((h) != NULL) { \
DUK_HOBJECT_DECREF((thr), (h)); \
} \
} while (0)
-#define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h) do { \
+#define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h) \
+ do { \
if ((h) != NULL) { \
DUK_HOBJECT_DECREF_NORZ((thr), (h)); \
} \
} while (0)
-#define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h) do { \
+#define DUK_HBUFFER_INCREF_ALLOWNULL(thr, h) \
+ do { \
if ((h) != NULL) { \
DUK_HBUFFER_INCREF((thr), (h)); \
} \
} while (0)
-#define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h) do { \
+#define DUK_HBUFFER_DECREF_ALLOWNULL(thr, h) \
+ do { \
if ((h) != NULL) { \
DUK_HBUFFER_DECREF((thr), (h)); \
} \
} while (0)
-#define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h) do { \
+#define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr, h) \
+ do { \
if ((h) != NULL) { \
DUK_HBUFFER_DECREF_NORZ((thr), (h)); \
} \
} while (0)
-#define DUK_HTHREAD_INCREF_ALLOWNULL(thr,h) do { \
+#define DUK_HTHREAD_INCREF_ALLOWNULL(thr, h) \
+ do { \
if ((h) != NULL) { \
DUK_HTHREAD_INCREF((thr), (h)); \
} \
} while (0)
-#define DUK_HTHREAD_DECREF_ALLOWNULL(thr,h) do { \
+#define DUK_HTHREAD_DECREF_ALLOWNULL(thr, h) \
+ do { \
if ((h) != NULL) { \
DUK_HTHREAD_DECREF((thr), (h)); \
} \
} while (0)
-#define DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr,h) do { \
+#define DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, h) \
+ do { \
if ((h) != NULL) { \
DUK_HTHREAD_DECREF_NORZ((thr), (h)); \
} \
@@ -4750,16 +5179,22 @@ struct duk_heaphdr_string {
* variant is performance critical.
*/
#if defined(DUK_USE_FINALIZER_SUPPORT)
-#define DUK_REFZERO_CHECK_FAST(thr) do { \
+#define DUK_REFZERO_CHECK_FAST(thr) \
+ do { \
duk_refzero_check_fast((thr)); \
} while (0)
-#define DUK_REFZERO_CHECK_SLOW(thr) do { \
+#define DUK_REFZERO_CHECK_SLOW(thr) \
+ do { \
duk_refzero_check_slow((thr)); \
} while (0)
-#else /* DUK_USE_FINALIZER_SUPPORT */
-#define DUK_REFZERO_CHECK_FAST(thr) do { } while (0)
-#define DUK_REFZERO_CHECK_SLOW(thr) do { } while (0)
-#endif /* DUK_USE_FINALIZER_SUPPORT */
+#else /* DUK_USE_FINALIZER_SUPPORT */
+#define DUK_REFZERO_CHECK_FAST(thr) \
+ do { \
+ } while (0)
+#define DUK_REFZERO_CHECK_SLOW(thr) \
+ do { \
+ } while (0)
+#endif /* DUK_USE_FINALIZER_SUPPORT */
/*
* Macros to set a duk_tval and update refcount of the target (decref the
@@ -4767,125 +5202,176 @@ struct duk_heaphdr_string {
* and footprint critical; any changes made should be measured for size/speed.
*/
-#define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
- duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr, tvptr_dst) \
+ do { \
+ duk_tval *tv__dst; \
+ duk_tval tv__tmp; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_UNDEFINED(tv__dst); \
- DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
+ DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
-#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0(thr,tvptr_dst) do { \
- duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0(thr, tvptr_dst) \
+ do { \
+ duk_tval *tv__dst; \
+ duk_tval tv__tmp; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_UNDEFINED(tv__dst); \
DUK_TVAL_DECREF_NORZ((thr), &tv__tmp); \
} while (0)
-#define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
- duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr, tvptr_dst) \
+ do { \
+ duk_tval *tv__dst; \
+ duk_tval tv__tmp; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_UNUSED(tv__dst); \
- DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
+ DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
-#define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
- duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr, tvptr_dst) \
+ do { \
+ duk_tval *tv__dst; \
+ duk_tval tv__tmp; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_NULL(tv__dst); \
- DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
+ DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
-#define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ duk_tval tv__tmp; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
- DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
+ DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
-#define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ duk_tval tv__tmp; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
- DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
+ DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
-#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ duk_tval tv__tmp; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
- DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
+ DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
-#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ duk_tval tv__tmp; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
- DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
+ DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
-#define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
- duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr, tvptr_dst) \
+ do { \
+ duk_tval *tv__dst; \
+ duk_tval tv__tmp; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_NAN(tv__dst); \
- DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
+ DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
#if defined(DUK_USE_FASTINT)
-#define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_I48_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ duk_tval tv__tmp; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_I48(tv__dst, (newval)); \
- DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
+ DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
-#define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_I32_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ duk_tval tv__tmp; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_I32(tv__dst, (newval)); \
- DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
+ DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
-#define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_U32_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ duk_tval tv__tmp; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_U32(tv__dst, (newval)); \
- DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
+ DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
#else
-#define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
+#define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr, tvptr_dst, newval) \
DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
-#endif /* DUK_USE_FASTINT */
+#endif /* DUK_USE_FASTINT */
-#define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
- duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr, tvptr_dst, lf_v, lf_fp, lf_flags) \
+ do { \
+ duk_tval *tv__dst; \
+ duk_tval tv__tmp; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
- DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
+ DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
-#define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ duk_tval tv__tmp; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_STRING(tv__dst, (newval)); \
DUK_HSTRING_INCREF((thr), (newval)); \
- DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
+ DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
-#define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ duk_tval tv__tmp; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
DUK_HOBJECT_INCREF((thr), (newval)); \
- DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
+ DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
-#define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ duk_tval tv__tmp; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
DUK_HBUFFER_INCREF((thr), (newval)); \
- DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
+ DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
-#define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ duk_tval tv__tmp; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
- DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
+ DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
/* DUK_TVAL_SET_TVAL_UPDREF() is used a lot in executor, property lookups,
@@ -4896,281 +5382,452 @@ struct duk_heaphdr_string {
*/
/* Original idiom used, minimal code size. */
-#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
- duk_tval *tv__dst, *tv__src; duk_tval tv__tmp; \
- tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
+#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr, tvptr_dst, tvptr_src) \
+ do { \
+ duk_tval *tv__dst, *tv__src; \
+ duk_tval tv__tmp; \
+ tv__dst = (tvptr_dst); \
+ tv__src = (tvptr_src); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
DUK_TVAL_INCREF((thr), tv__src); \
- DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
+ DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
/* Faster alternative: avoid making a temporary copy of tvptr_dst and use
* fast incref/decref macros.
*/
-#define DUK_TVAL_SET_TVAL_UPDREF_ALT1(thr,tvptr_dst,tvptr_src) do { \
- duk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \
- tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
+#define DUK_TVAL_SET_TVAL_UPDREF_ALT1(thr, tvptr_dst, tvptr_src) \
+ do { \
+ duk_tval *tv__dst, *tv__src; \
+ duk_heaphdr *h__obj; \
+ tv__dst = (tvptr_dst); \
+ tv__src = (tvptr_src); \
DUK_TVAL_INCREF_FAST((thr), tv__src); \
if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv__dst)) { \
h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \
DUK_ASSERT(h__obj != NULL); \
DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
- DUK_HEAPHDR_DECREF_FAST((thr), h__obj); /* side effects */ \
+ DUK_HEAPHDR_DECREF_FAST((thr), h__obj); /* side effects */ \
} else { \
DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
} \
} while (0)
/* XXX: no optimized variants yet */
-#define DUK_TVAL_SET_UNDEFINED_UPDREF DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
-#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0
-#define DUK_TVAL_SET_UNUSED_UPDREF DUK_TVAL_SET_UNUSED_UPDREF_ALT0
-#define DUK_TVAL_SET_NULL_UPDREF DUK_TVAL_SET_NULL_UPDREF_ALT0
-#define DUK_TVAL_SET_BOOLEAN_UPDREF DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
-#define DUK_TVAL_SET_NUMBER_UPDREF DUK_TVAL_SET_NUMBER_UPDREF_ALT0
-#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
-#define DUK_TVAL_SET_DOUBLE_UPDREF DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
-#define DUK_TVAL_SET_NAN_UPDREF DUK_TVAL_SET_NAN_UPDREF_ALT0
+#define DUK_TVAL_SET_UNDEFINED_UPDREF DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
+#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0
+#define DUK_TVAL_SET_UNUSED_UPDREF DUK_TVAL_SET_UNUSED_UPDREF_ALT0
+#define DUK_TVAL_SET_NULL_UPDREF DUK_TVAL_SET_NULL_UPDREF_ALT0
+#define DUK_TVAL_SET_BOOLEAN_UPDREF DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
+#define DUK_TVAL_SET_NUMBER_UPDREF DUK_TVAL_SET_NUMBER_UPDREF_ALT0
+#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
+#define DUK_TVAL_SET_DOUBLE_UPDREF DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
+#define DUK_TVAL_SET_NAN_UPDREF DUK_TVAL_SET_NAN_UPDREF_ALT0
#if defined(DUK_USE_FASTINT)
-#define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_I48_UPDREF_ALT0
-#define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_I32_UPDREF_ALT0
-#define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_U32_UPDREF_ALT0
+#define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_I48_UPDREF_ALT0
+#define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_I32_UPDREF_ALT0
+#define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_U32_UPDREF_ALT0
#else
-#define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF /* XXX: fast int-to-double */
-#define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
-#define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
-#endif /* DUK_USE_FASTINT */
-#define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_I48_UPDREF /* convenience */
-#define DUK_TVAL_SET_LIGHTFUNC_UPDREF DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
-#define DUK_TVAL_SET_STRING_UPDREF DUK_TVAL_SET_STRING_UPDREF_ALT0
-#define DUK_TVAL_SET_OBJECT_UPDREF DUK_TVAL_SET_OBJECT_UPDREF_ALT0
-#define DUK_TVAL_SET_BUFFER_UPDREF DUK_TVAL_SET_BUFFER_UPDREF_ALT0
-#define DUK_TVAL_SET_POINTER_UPDREF DUK_TVAL_SET_POINTER_UPDREF_ALT0
+#define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF /* XXX: fast int-to-double */
+#define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
+#define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
+#endif /* DUK_USE_FASTINT */
+#define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_I48_UPDREF /* convenience */
+#define DUK_TVAL_SET_LIGHTFUNC_UPDREF DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
+#define DUK_TVAL_SET_STRING_UPDREF DUK_TVAL_SET_STRING_UPDREF_ALT0
+#define DUK_TVAL_SET_OBJECT_UPDREF DUK_TVAL_SET_OBJECT_UPDREF_ALT0
+#define DUK_TVAL_SET_BUFFER_UPDREF DUK_TVAL_SET_BUFFER_UPDREF_ALT0
+#define DUK_TVAL_SET_POINTER_UPDREF DUK_TVAL_SET_POINTER_UPDREF_ALT0
#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
/* Optimized for speed. */
-#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT1
-#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT1
-#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
+#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT1
+#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT1
+#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
#else
/* Optimized for size. */
-#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT0
-#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT0
-#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
-#endif
-
-#else /* DUK_USE_REFERENCE_COUNTING */
-
-#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) 0
-#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) 0
-
-#define DUK_TVAL_INCREF_FAST(thr,v) do {} while (0) /* nop */
-#define DUK_TVAL_DECREF_FAST(thr,v) do {} while (0) /* nop */
-#define DUK_TVAL_DECREF_NORZ_FAST(thr,v) do {} while (0) /* nop */
-#define DUK_TVAL_INCREF_SLOW(thr,v) do {} while (0) /* nop */
-#define DUK_TVAL_DECREF_SLOW(thr,v) do {} while (0) /* nop */
-#define DUK_TVAL_DECREF_NORZ_SLOW(thr,v) do {} while (0) /* nop */
-#define DUK_TVAL_INCREF(thr,v) do {} while (0) /* nop */
-#define DUK_TVAL_DECREF(thr,v) do {} while (0) /* nop */
-#define DUK_TVAL_DECREF_NORZ(thr,v) do {} while (0) /* nop */
-#define DUK_HEAPHDR_INCREF_FAST(thr,h) do {} while (0) /* nop */
-#define DUK_HEAPHDR_DECREF_FAST(thr,h) do {} while (0) /* nop */
-#define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h) do {} while (0) /* nop */
-#define DUK_HEAPHDR_INCREF_SLOW(thr,h) do {} while (0) /* nop */
-#define DUK_HEAPHDR_DECREF_SLOW(thr,h) do {} while (0) /* nop */
-#define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h) do {} while (0) /* nop */
-#define DUK_HEAPHDR_INCREF(thr,h) do {} while (0) /* nop */
-#define DUK_HEAPHDR_DECREF(thr,h) do {} while (0) /* nop */
-#define DUK_HEAPHDR_DECREF_NORZ(thr,h) do {} while (0) /* nop */
-#define DUK_HSTRING_INCREF_FAST(thr,h) do {} while (0) /* nop */
-#define DUK_HSTRING_DECREF_FAST(thr,h) do {} while (0) /* nop */
-#define DUK_HSTRING_DECREF_NORZ_FAST(thr,h) do {} while (0) /* nop */
-#define DUK_HSTRING_INCREF_SLOW(thr,h) do {} while (0) /* nop */
-#define DUK_HSTRING_DECREF_SLOW(thr,h) do {} while (0) /* nop */
-#define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h) do {} while (0) /* nop */
-#define DUK_HSTRING_INCREF(thr,h) do {} while (0) /* nop */
-#define DUK_HSTRING_DECREF(thr,h) do {} while (0) /* nop */
-#define DUK_HSTRING_DECREF_NORZ(thr,h) do {} while (0) /* nop */
-#define DUK_HOBJECT_INCREF_FAST(thr,h) do {} while (0) /* nop */
-#define DUK_HOBJECT_DECREF_FAST(thr,h) do {} while (0) /* nop */
-#define DUK_HOBJECT_DECREF_NORZ_FAST(thr,h) do {} while (0) /* nop */
-#define DUK_HOBJECT_INCREF_SLOW(thr,h) do {} while (0) /* nop */
-#define DUK_HOBJECT_DECREF_SLOW(thr,h) do {} while (0) /* nop */
-#define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h) do {} while (0) /* nop */
-#define DUK_HOBJECT_INCREF(thr,h) do {} while (0) /* nop */
-#define DUK_HOBJECT_DECREF(thr,h) do {} while (0) /* nop */
-#define DUK_HOBJECT_DECREF_NORZ(thr,h) do {} while (0) /* nop */
-#define DUK_HBUFFER_INCREF_FAST(thr,h) do {} while (0) /* nop */
-#define DUK_HBUFFER_DECREF_FAST(thr,h) do {} while (0) /* nop */
-#define DUK_HBUFFER_DECREF_NORZ_FAST(thr,h) do {} while (0) /* nop */
-#define DUK_HBUFFER_INCREF_SLOW(thr,h) do {} while (0) /* nop */
-#define DUK_HBUFFER_DECREF_SLOW(thr,h) do {} while (0) /* nop */
-#define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h) do {} while (0) /* nop */
-#define DUK_HBUFFER_INCREF(thr,h) do {} while (0) /* nop */
-#define DUK_HBUFFER_DECREF(thr,h) do {} while (0) /* nop */
-#define DUK_HBUFFER_DECREF_NORZ(thr,h) do {} while (0) /* nop */
-
-#define DUK_HCOMPFUNC_INCREF(thr,h) do {} while (0) /* nop */
-#define DUK_HCOMPFUNC_DECREF(thr,h) do {} while (0) /* nop */
-#define DUK_HCOMPFUNC_DECREF_NORZ(thr,h) do {} while (0) /* nop */
-#define DUK_HNATFUNC_INCREF(thr,h) do {} while (0) /* nop */
-#define DUK_HNATFUNC_DECREF(thr,h) do {} while (0) /* nop */
-#define DUK_HNATFUNC_DECREF_NORZ(thr,h) do {} while (0) /* nop */
-#define DUK_HBUFOBJ_INCREF(thr,h) do {} while (0) /* nop */
-#define DUK_HBUFOBJ_DECREF(thr,h) do {} while (0) /* nop */
-#define DUK_HBUFOBJ_DECREF_NORZ(thr,h) do {} while (0) /* nop */
-#define DUK_HTHREAD_INCREF(thr,h) do {} while (0) /* nop */
-#define DUK_HTHREAD_DECREF(thr,h) do {} while (0) /* nop */
-#define DUK_HTHREAD_DECREF_NORZ(thr,h) do {} while (0) /* nop */
-#define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do {} while (0) /* nop */
-#define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do {} while (0) /* nop */
-#define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h) do {} while (0) /* nop */
-#define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h) do {} while (0) /* nop */
-#define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h) do {} while (0) /* nop */
-#define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h) do {} while (0) /* nop */
-
-#define DUK_REFZERO_CHECK_FAST(thr) do {} while (0) /* nop */
-#define DUK_REFZERO_CHECK_SLOW(thr) do {} while (0) /* nop */
-
-#define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
- duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT0
+#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT0
+#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
+#endif
+
+#else /* DUK_USE_REFERENCE_COUNTING */
+
+#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) 0
+#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) 0
+
+#define DUK_TVAL_INCREF_FAST(thr, v) \
+ do { \
+ } while (0) /* nop */
+#define DUK_TVAL_DECREF_FAST(thr, v) \
+ do { \
+ } while (0) /* nop */
+#define DUK_TVAL_DECREF_NORZ_FAST(thr, v) \
+ do { \
+ } while (0) /* nop */
+#define DUK_TVAL_INCREF_SLOW(thr, v) \
+ do { \
+ } while (0) /* nop */
+#define DUK_TVAL_DECREF_SLOW(thr, v) \
+ do { \
+ } while (0) /* nop */
+#define DUK_TVAL_DECREF_NORZ_SLOW(thr, v) \
+ do { \
+ } while (0) /* nop */
+#define DUK_TVAL_INCREF(thr, v) \
+ do { \
+ } while (0) /* nop */
+#define DUK_TVAL_DECREF(thr, v) \
+ do { \
+ } while (0) /* nop */
+#define DUK_TVAL_DECREF_NORZ(thr, v) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HEAPHDR_INCREF_FAST(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HEAPHDR_DECREF_FAST(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HEAPHDR_DECREF_NORZ_FAST(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HEAPHDR_INCREF_SLOW(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HEAPHDR_DECREF_SLOW(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HEAPHDR_INCREF(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HEAPHDR_DECREF(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HEAPHDR_DECREF_NORZ(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HSTRING_INCREF_FAST(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HSTRING_DECREF_FAST(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HSTRING_DECREF_NORZ_FAST(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HSTRING_INCREF_SLOW(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HSTRING_DECREF_SLOW(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HSTRING_DECREF_NORZ_SLOW(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HSTRING_INCREF(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HSTRING_DECREF(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HSTRING_DECREF_NORZ(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HOBJECT_INCREF_FAST(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HOBJECT_DECREF_FAST(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HOBJECT_DECREF_NORZ_FAST(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HOBJECT_INCREF_SLOW(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HOBJECT_DECREF_SLOW(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HOBJECT_DECREF_NORZ_SLOW(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HOBJECT_INCREF(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HOBJECT_DECREF(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HOBJECT_DECREF_NORZ(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HBUFFER_INCREF_FAST(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HBUFFER_DECREF_FAST(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HBUFFER_DECREF_NORZ_FAST(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HBUFFER_INCREF_SLOW(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HBUFFER_DECREF_SLOW(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HBUFFER_DECREF_NORZ_SLOW(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HBUFFER_INCREF(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HBUFFER_DECREF(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HBUFFER_DECREF_NORZ(thr, h) \
+ do { \
+ } while (0) /* nop */
+
+#define DUK_HCOMPFUNC_INCREF(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HCOMPFUNC_DECREF(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HCOMPFUNC_DECREF_NORZ(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HNATFUNC_INCREF(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HNATFUNC_DECREF(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HNATFUNC_DECREF_NORZ(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HBUFOBJ_INCREF(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HBUFOBJ_DECREF(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HBUFOBJ_DECREF_NORZ(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HTHREAD_INCREF(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HTHREAD_DECREF(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HTHREAD_DECREF_NORZ(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HOBJECT_INCREF_ALLOWNULL(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HOBJECT_DECREF_ALLOWNULL(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HBUFFER_INCREF_ALLOWNULL(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HBUFFER_DECREF_ALLOWNULL(thr, h) \
+ do { \
+ } while (0) /* nop */
+#define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr, h) \
+ do { \
+ } while (0) /* nop */
+
+#define DUK_REFZERO_CHECK_FAST(thr) \
+ do { \
+ } while (0) /* nop */
+#define DUK_REFZERO_CHECK_SLOW(thr) \
+ do { \
+ } while (0) /* nop */
+
+#define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr, tvptr_dst) \
+ do { \
+ duk_tval *tv__dst; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_UNDEFINED(tv__dst); \
DUK_UNREF((thr)); \
} while (0)
-#define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
- duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr, tvptr_dst) \
+ do { \
+ duk_tval *tv__dst; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_UNUSED(tv__dst); \
DUK_UNREF((thr)); \
} while (0)
-#define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
- duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr, tvptr_dst) \
+ do { \
+ duk_tval *tv__dst; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_NULL(tv__dst); \
DUK_UNREF((thr)); \
} while (0)
-#define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
DUK_UNREF((thr)); \
} while (0)
-#define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
DUK_UNREF((thr)); \
} while (0)
-#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
DUK_UNREF((thr)); \
} while (0)
-#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
DUK_UNREF((thr)); \
} while (0)
-#define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
- duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr, tvptr_dst) \
+ do { \
+ duk_tval *tv__dst; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_NAN(tv__dst); \
DUK_UNREF((thr)); \
} while (0)
#if defined(DUK_USE_FASTINT)
-#define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_I48_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_I48(tv__dst, (newval)); \
DUK_UNREF((thr)); \
} while (0)
-#define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_I32_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_I32(tv__dst, (newval)); \
DUK_UNREF((thr)); \
} while (0)
-#define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_U32_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_U32(tv__dst, (newval)); \
DUK_UNREF((thr)); \
} while (0)
#else
-#define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
+#define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr, tvptr_dst, newval) \
DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
-#endif /* DUK_USE_FASTINT */
+#endif /* DUK_USE_FASTINT */
-#define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
- duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr, tvptr_dst, lf_v, lf_fp, lf_flags) \
+ do { \
+ duk_tval *tv__dst; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
DUK_UNREF((thr)); \
} while (0)
-#define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_STRING(tv__dst, (newval)); \
DUK_UNREF((thr)); \
} while (0)
-#define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
DUK_UNREF((thr)); \
} while (0)
-#define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
DUK_UNREF((thr)); \
} while (0)
-#define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
- duk_tval *tv__dst; tv__dst = (tvptr_dst); \
+#define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr, tvptr_dst, newval) \
+ do { \
+ duk_tval *tv__dst; \
+ tv__dst = (tvptr_dst); \
DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
DUK_UNREF((thr)); \
} while (0)
-#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
+#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr, tvptr_dst, tvptr_src) \
+ do { \
duk_tval *tv__dst, *tv__src; \
- tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
+ tv__dst = (tvptr_dst); \
+ tv__src = (tvptr_src); \
DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
DUK_UNREF((thr)); \
} while (0)
-#define DUK_TVAL_SET_UNDEFINED_UPDREF DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
-#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
-#define DUK_TVAL_SET_UNUSED_UPDREF DUK_TVAL_SET_UNUSED_UPDREF_ALT0
-#define DUK_TVAL_SET_NULL_UPDREF DUK_TVAL_SET_NULL_UPDREF_ALT0
-#define DUK_TVAL_SET_BOOLEAN_UPDREF DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
-#define DUK_TVAL_SET_NUMBER_UPDREF DUK_TVAL_SET_NUMBER_UPDREF_ALT0
-#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
-#define DUK_TVAL_SET_DOUBLE_UPDREF DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
-#define DUK_TVAL_SET_NAN_UPDREF DUK_TVAL_SET_NAN_UPDREF_ALT0
+#define DUK_TVAL_SET_UNDEFINED_UPDREF DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
+#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
+#define DUK_TVAL_SET_UNUSED_UPDREF DUK_TVAL_SET_UNUSED_UPDREF_ALT0
+#define DUK_TVAL_SET_NULL_UPDREF DUK_TVAL_SET_NULL_UPDREF_ALT0
+#define DUK_TVAL_SET_BOOLEAN_UPDREF DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
+#define DUK_TVAL_SET_NUMBER_UPDREF DUK_TVAL_SET_NUMBER_UPDREF_ALT0
+#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
+#define DUK_TVAL_SET_DOUBLE_UPDREF DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
+#define DUK_TVAL_SET_NAN_UPDREF DUK_TVAL_SET_NAN_UPDREF_ALT0
#if defined(DUK_USE_FASTINT)
-#define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_I48_UPDREF_ALT0
-#define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_I32_UPDREF_ALT0
-#define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_U32_UPDREF_ALT0
+#define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_I48_UPDREF_ALT0
+#define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_I32_UPDREF_ALT0
+#define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_U32_UPDREF_ALT0
#else
-#define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF /* XXX: fast-int-to-double */
-#define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
-#define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
-#endif /* DUK_USE_FASTINT */
-#define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_I48_UPDREF /* convenience */
-#define DUK_TVAL_SET_LIGHTFUNC_UPDREF DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
-#define DUK_TVAL_SET_STRING_UPDREF DUK_TVAL_SET_STRING_UPDREF_ALT0
-#define DUK_TVAL_SET_OBJECT_UPDREF DUK_TVAL_SET_OBJECT_UPDREF_ALT0
-#define DUK_TVAL_SET_BUFFER_UPDREF DUK_TVAL_SET_BUFFER_UPDREF_ALT0
-#define DUK_TVAL_SET_POINTER_UPDREF DUK_TVAL_SET_POINTER_UPDREF_ALT0
+#define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF /* XXX: fast-int-to-double */
+#define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
+#define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
+#endif /* DUK_USE_FASTINT */
+#define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_I48_UPDREF /* convenience */
+#define DUK_TVAL_SET_LIGHTFUNC_UPDREF DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
+#define DUK_TVAL_SET_STRING_UPDREF DUK_TVAL_SET_STRING_UPDREF_ALT0
+#define DUK_TVAL_SET_OBJECT_UPDREF DUK_TVAL_SET_OBJECT_UPDREF_ALT0
+#define DUK_TVAL_SET_BUFFER_UPDREF DUK_TVAL_SET_BUFFER_UPDREF_ALT0
+#define DUK_TVAL_SET_POINTER_UPDREF DUK_TVAL_SET_POINTER_UPDREF_ALT0
-#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT0
-#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT0
-#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
+#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT0
+#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT0
+#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
-#endif /* DUK_USE_REFERENCE_COUNTING */
+#endif /* DUK_USE_REFERENCE_COUNTING */
/*
* Some convenience macros that don't have optimized implementations now.
*/
-#define DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr,tv_dst,tv_src) do { \
+#define DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr, tv_dst, tv_src) \
+ do { \
duk_hthread *duk__thr = (thr); \
duk_tval *duk__dst = (tv_dst); \
duk_tval *duk__src = (tv_src); \
@@ -5180,7 +5837,8 @@ struct duk_heaphdr_string {
DUK_TVAL_INCREF(thr, duk__dst); \
} while (0)
-#define DUK_TVAL_SET_U32_UPDREF_NORZ(thr,tv_dst,val) do { \
+#define DUK_TVAL_SET_U32_UPDREF_NORZ(thr, tv_dst, val) \
+ do { \
duk_hthread *duk__thr = (thr); \
duk_tval *duk__dst = (tv_dst); \
duk_uint32_t duk__val = (duk_uint32_t) (val); \
@@ -5196,11 +5854,11 @@ struct duk_heaphdr_string {
#if defined(DUK_USE_REFERENCE_COUNTING)
#if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_INTERNAL_DECL void duk_refzero_check_slow(duk_hthread *thr);
-DUK_INTERNAL_DECL DUK_INLINE void duk_refzero_check_fast(duk_hthread *thr);
+DUK_INTERNAL_DECL void duk_refzero_check_fast(duk_hthread *thr);
#endif
DUK_INTERNAL_DECL void duk_heaphdr_refcount_finalize_norz(duk_heap *heap, duk_heaphdr *hdr);
DUK_INTERNAL_DECL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject *h);
-#if 0 /* Not needed: fast path handles inline; slow path uses duk_heaphdr_decref() which is needed anyway. */
+#if 0 /* Not needed: fast path handles inline; slow path uses duk_heaphdr_decref() which is needed anyway. */
DUK_INTERNAL_DECL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h);
DUK_INTERNAL_DECL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h);
DUK_INTERNAL_DECL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h);
@@ -5211,8 +5869,8 @@ DUK_INTERNAL_DECL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h)
DUK_INTERNAL_DECL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h);
DUK_INTERNAL_DECL void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h);
#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
-DUK_INTERNAL_DECL void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h); /* no 'norz' variant */
-DUK_INTERNAL_DECL void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h); /* no 'norz' variant */
+DUK_INTERNAL_DECL void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h); /* no 'norz' variant */
+DUK_INTERNAL_DECL void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h); /* no 'norz' variant */
DUK_INTERNAL_DECL void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h);
DUK_INTERNAL_DECL void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h);
#else
@@ -5223,11 +5881,11 @@ DUK_INTERNAL_DECL void duk_heaphdr_incref(duk_heaphdr *h);
DUK_INTERNAL_DECL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h);
DUK_INTERNAL_DECL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h);
#endif
-#else /* DUK_USE_REFERENCE_COUNTING */
+#else /* DUK_USE_REFERENCE_COUNTING */
/* no refcounting */
-#endif /* DUK_USE_REFERENCE_COUNTING */
+#endif /* DUK_USE_REFERENCE_COUNTING */
-#endif /* DUK_REFCOUNT_H_INCLUDED */
+#endif /* DUK_REFCOUNT_H_INCLUDED */
/* #include duk_api_internal.h */
/*
* Internal API calls which have (stack and other) semantics similar
@@ -5237,22 +5895,42 @@ DUK_INTERNAL_DECL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h)
#if !defined(DUK_API_INTERNAL_H_INCLUDED)
#define DUK_API_INTERNAL_H_INCLUDED
-#define DUK_INTERNAL_SYMBOL(x) ("\x82" x)
+/* Inline macro helpers. */
+#if defined(DUK_USE_PREFER_SIZE)
+#define DUK_INLINE_PERF
+#define DUK_ALWAYS_INLINE_PERF
+#define DUK_NOINLINE_PERF
+#else
+#define DUK_INLINE_PERF DUK_INLINE
+#define DUK_ALWAYS_INLINE_PERF DUK_ALWAYS_INLINE
+#define DUK_NOINLINE_PERF DUK_NOINLINE
+#endif
+
+/* Inline macro helpers, for bytecode executor. */
+#if defined(DUK_USE_EXEC_PREFER_SIZE)
+#define DUK_EXEC_INLINE_PERF
+#define DUK_EXEC_ALWAYS_INLINE_PERF
+#define DUK_EXEC_NOINLINE_PERF
+#else
+#define DUK_EXEC_INLINE_PERF DUK_INLINE
+#define DUK_EXEC_ALWAYS_INLINE_PERF DUK_ALWAYS_INLINE
+#define DUK_EXEC_NOINLINE_PERF DUK_NOINLINE
+#endif
/* duk_push_sprintf constants */
-#define DUK_PUSH_SPRINTF_INITIAL_SIZE 256L
-#define DUK_PUSH_SPRINTF_SANITY_LIMIT (1L * 1024L * 1024L * 1024L)
+#define DUK_PUSH_SPRINTF_INITIAL_SIZE 256L
+#define DUK_PUSH_SPRINTF_SANITY_LIMIT (1L * 1024L * 1024L * 1024L)
/* Flag ORed to err_code to indicate __FILE__ / __LINE__ is not
* blamed as source of error for error fileName / lineNumber.
*/
-#define DUK_ERRCODE_FLAG_NOBLAME_FILELINE (1L << 24)
+#define DUK_ERRCODE_FLAG_NOBLAME_FILELINE (1L << 24)
/* Current convention is to use duk_size_t for value stack sizes and global indices,
* and duk_idx_t for local frame indices.
*/
-DUK_INTERNAL_DECL DUK_INLINE void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes);
-DUK_INTERNAL_DECL DUK_INLINE duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes);
+DUK_INTERNAL_DECL void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes);
+DUK_INTERNAL_DECL duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes);
DUK_INTERNAL_DECL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t snug);
DUK_INTERNAL_DECL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_size_t count);
@@ -5308,29 +5986,24 @@ DUK_INTERNAL_DECL duk_hstring *duk_push_uint_to_hstring(duk_hthread *thr, duk_ui
DUK_INTERNAL_DECL duk_tval *duk_get_borrowed_this_tval(duk_hthread *thr);
/* XXX: add fastint support? */
-#define duk_push_u64(thr,val) \
- duk_push_number((thr), (duk_double_t) (val))
-#define duk_push_i64(thr,val) \
- duk_push_number((thr), (duk_double_t) (val))
+#define duk_push_u64(thr, val) duk_push_number((thr), (duk_double_t) (val))
+#define duk_push_i64(thr, val) duk_push_number((thr), (duk_double_t) (val))
/* duk_push_(u)int() is guaranteed to support at least (un)signed 32-bit range */
-#define duk_push_u32(thr,val) \
- duk_push_uint((thr), (duk_uint_t) (val))
-#define duk_push_i32(thr,val) \
- duk_push_int((thr), (duk_int_t) (val))
+#define duk_push_u32(thr, val) duk_push_uint((thr), (duk_uint_t) (val))
+#define duk_push_i32(thr, val) duk_push_int((thr), (duk_int_t) (val))
/* sometimes stack and array indices need to go on the stack */
-#define duk_push_idx(thr,val) \
- duk_push_int((thr), (duk_int_t) (val))
-#define duk_push_uarridx(thr,val) \
- duk_push_uint((thr), (duk_uint_t) (val))
-#define duk_push_size_t(thr,val) \
- duk_push_uint((thr), (duk_uint_t) (val)) /* XXX: assumed to fit for now */
+#define duk_push_idx(thr, val) duk_push_int((thr), (duk_int_t) (val))
+#define duk_push_uarridx(thr, val) duk_push_uint((thr), (duk_uint_t) (val))
+#define duk_push_size_t(thr, val) duk_push_uint((thr), (duk_uint_t) (val)) /* XXX: assumed to fit for now */
DUK_INTERNAL_DECL duk_bool_t duk_is_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_bool_t duk_is_callable_tval(duk_hthread *thr, duk_tval *tv);
+DUK_INTERNAL_DECL duk_bool_t duk_is_bare_object(duk_hthread *thr, duk_idx_t idx);
+
DUK_INTERNAL_DECL duk_hstring *duk_get_hstring(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hstring *duk_get_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL const char *duk_get_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
@@ -5340,19 +6013,23 @@ DUK_INTERNAL_DECL duk_hthread *duk_get_hthread(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hcompfunc *duk_get_hcompfunc(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hnatfunc *duk_get_hnatfunc(duk_hthread *thr, duk_idx_t idx);
-DUK_INTERNAL_DECL void *duk_get_buffer_data_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_len, duk_bool_t throw_flag, duk_bool_t *out_isbuffer);
+DUK_INTERNAL_DECL void *duk_get_buffer_data_raw(duk_hthread *thr,
+ duk_idx_t idx,
+ duk_size_t *out_size,
+ void *def_ptr,
+ duk_size_t def_len,
+ duk_bool_t throw_flag,
+ duk_bool_t *out_isbuffer);
DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum);
DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_accept_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
-#define duk_require_hobject_promote_lfunc(thr,idx) \
- duk_require_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)
-#define duk_get_hobject_promote_lfunc(thr,idx) \
- duk_get_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)
+#define duk_require_hobject_promote_lfunc(thr, idx) duk_require_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)
+#define duk_get_hobject_promote_lfunc(thr, idx) duk_get_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)
-#if 0 /*unused*/
+#if 0 /*unused*/
DUK_INTERNAL_DECL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx);
#endif
@@ -5373,12 +6050,18 @@ DUK_INTERNAL_DECL duk_hobject *duk_to_hobject(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_double_t duk_to_number_m1(duk_hthread *thr);
DUK_INTERNAL_DECL duk_double_t duk_to_number_m2(duk_hthread *thr);
-#if defined(DUK_USE_DEBUGGER_SUPPORT) /* only needed by debugger for now */
+DUK_INTERNAL_DECL duk_bool_t duk_to_boolean_top_pop(duk_hthread *thr);
+
+#if defined(DUK_USE_DEBUGGER_SUPPORT) /* only needed by debugger for now */
DUK_INTERNAL_DECL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx);
#endif
-DUK_INTERNAL_DECL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv);
+DUK_INTERNAL_DECL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects);
-DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped_raw(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped); /* out_clamped=NULL, RangeError if outside range */
+DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped_raw(duk_hthread *thr,
+ duk_idx_t idx,
+ duk_int_t minval,
+ duk_int_t maxval,
+ duk_bool_t *out_clamped); /* out_clamped=NULL, RangeError if outside range */
DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval);
DUK_INTERNAL_DECL duk_int_t duk_to_int_check_range(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval);
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
@@ -5403,13 +6086,15 @@ DUK_INTERNAL_DECL void duk_push_hstring_stridx(duk_hthread *thr, duk_small_uint_
DUK_INTERNAL_DECL void duk_push_hstring_empty(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_push_hobject(duk_hthread *thr, duk_hobject *h);
DUK_INTERNAL_DECL void duk_push_hbuffer(duk_hthread *thr, duk_hbuffer *h);
-#define duk_push_hthread(thr,h) \
- duk_push_hobject((thr), (duk_hobject *) (h))
-#define duk_push_hnatfunc(thr,h) \
- duk_push_hobject((thr), (duk_hobject *) (h))
+#define duk_push_hthread(thr, h) duk_push_hobject((thr), (duk_hobject *) (h))
+#define duk_push_hnatfunc(thr, h) duk_push_hobject((thr), (duk_hobject *) (h))
DUK_INTERNAL_DECL void duk_push_hobject_bidx(duk_hthread *thr, duk_small_int_t builtin_idx);
-DUK_INTERNAL_DECL duk_hobject *duk_push_object_helper(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx);
-DUK_INTERNAL_DECL duk_hobject *duk_push_object_helper_proto(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_hobject *proto);
+DUK_INTERNAL_DECL duk_hobject *duk_push_object_helper(duk_hthread *thr,
+ duk_uint_t hobject_flags_and_class,
+ duk_small_int_t prototype_bidx);
+DUK_INTERNAL_DECL duk_hobject *duk_push_object_helper_proto(duk_hthread *thr,
+ duk_uint_t hobject_flags_and_class,
+ duk_hobject *proto);
DUK_INTERNAL_DECL duk_hcompfunc *duk_push_hcompfunc(duk_hthread *thr);
DUK_INTERNAL_DECL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_push_c_function_builtin(duk_hthread *thr, duk_c_function func, duk_int_t nargs);
@@ -5426,11 +6111,13 @@ DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *pt
DUK_INTERNAL_DECL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags);
DUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_hthread *thr, duk_tval *tv);
DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv);
-#if 0 /* not used yet */
+#if 0 /* not used yet */
DUK_INTERNAL_DECL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h);
#endif
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
-DUK_INTERNAL_DECL duk_hbufobj *duk_push_bufobj_raw(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx);
+DUK_INTERNAL_DECL duk_hbufobj *duk_push_bufobj_raw(duk_hthread *thr,
+ duk_uint_t hobject_flags_and_class,
+ duk_small_int_t prototype_bidx);
#endif
DUK_INTERNAL_DECL void *duk_push_fixed_buffer_nozero(duk_hthread *thr, duk_size_t len);
@@ -5447,72 +6134,88 @@ DUK_INTERNAL_DECL const char *duk_push_string_tval_readable_error(duk_hthread *t
* arguments and such call sites are also easiest to verify to be correct.
*/
-DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [] -> [val] */
+DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [] -> [val] */
DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
-#define duk_get_prop_stridx_short(thr,obj_idx,stridx) \
+#define duk_get_prop_stridx_short(thr, obj_idx, stridx) \
(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
duk_get_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
-DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_boolean(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_bool_t *out_has_prop); /* [] -> [] */
+DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_boolean(duk_hthread *thr,
+ duk_idx_t obj_idx,
+ duk_small_uint_t stridx,
+ duk_bool_t *out_has_prop); /* [] -> [] */
+
+DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop(duk_hthread *thr, duk_idx_t obj_idx);
+DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);
+DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
+#define duk_xget_owndataprop_stridx_short(thr, obj_idx, stridx) \
+ (DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
+ DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
+ duk_xget_owndataprop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
-DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [val] -> [] */
+DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [val] -> [] */
DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
-#define duk_put_prop_stridx_short(thr,obj_idx,stridx) \
+#define duk_put_prop_stridx_short(thr, obj_idx, stridx) \
(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
duk_put_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
-DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [] -> [] */
-#if 0 /* Too few call sites to be useful. */
+DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [] -> [] */
+#if 0 /* Too few call sites to be useful. */
DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
-#define duk_del_prop_stridx_short(thr,obj_idx,stridx) \
+#define duk_del_prop_stridx_short(thr, obj_idx, stridx) \
(DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \
DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \
duk_del_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
#endif
-#define duk_del_prop_stridx_short(thr,obj_idx,stridx) \
- duk_del_prop_stridx((thr), (obj_idx), (stridx))
+#define duk_del_prop_stridx_short(thr, obj_idx, stridx) duk_del_prop_stridx((thr), (obj_idx), (stridx))
-DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [] -> [] */
-#if 0 /* Too few call sites to be useful. */
+DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [] -> [] */
+#if 0 /* Too few call sites to be useful. */
DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
-#define duk_has_prop_stridx_short(thr,obj_idx,stridx) \
+#define duk_has_prop_stridx_short(thr, obj_idx, stridx) \
(DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \
DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \
duk_has_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
#endif
-#define duk_has_prop_stridx_short(thr,obj_idx,stridx) \
- duk_has_prop_stridx((thr), (obj_idx), (stridx))
+#define duk_has_prop_stridx_short(thr, obj_idx, stridx) duk_has_prop_stridx((thr), (obj_idx), (stridx))
-DUK_INTERNAL_DECL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags); /* [key val] -> [] */
+DUK_INTERNAL_DECL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags); /* [key val] -> [] */
-DUK_INTERNAL_DECL void duk_xdef_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx, duk_small_uint_t desc_flags); /* [val] -> [] */
+DUK_INTERNAL_DECL void duk_xdef_prop_index(duk_hthread *thr,
+ duk_idx_t obj_idx,
+ duk_uarridx_t arr_idx,
+ duk_small_uint_t desc_flags); /* [val] -> [] */
/* XXX: Because stridx and desc_flags have a limited range, this call could
* always pack stridx and desc_flags into a single argument.
*/
-DUK_INTERNAL_DECL void duk_xdef_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_uint_t desc_flags); /* [val] -> [] */
+DUK_INTERNAL_DECL void duk_xdef_prop_stridx(duk_hthread *thr,
+ duk_idx_t obj_idx,
+ duk_small_uint_t stridx,
+ duk_small_uint_t desc_flags); /* [val] -> [] */
DUK_INTERNAL_DECL void duk_xdef_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
-#define duk_xdef_prop_stridx_short(thr,obj_idx,stridx,desc_flags) \
+#define duk_xdef_prop_stridx_short(thr, obj_idx, stridx, desc_flags) \
(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x80L && (duk_int_t) (obj_idx) <= 0x7fL), \
DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
DUK_ASSERT_EXPR((duk_int_t) (desc_flags) >= 0 && (duk_int_t) (desc_flags) <= 0xffL), \
- duk_xdef_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 24) + (((duk_uint_t) (stridx)) << 8) + (duk_uint_t) (desc_flags)))
-
-#define duk_xdef_prop_wec(thr,obj_idx) \
- duk_xdef_prop((thr), (obj_idx), DUK_PROPDESC_FLAGS_WEC)
-#define duk_xdef_prop_index_wec(thr,obj_idx,arr_idx) \
- duk_xdef_prop_index((thr), (obj_idx), (arr_idx), DUK_PROPDESC_FLAGS_WEC)
-#define duk_xdef_prop_stridx_wec(thr,obj_idx,stridx) \
- duk_xdef_prop_stridx((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)
-#define duk_xdef_prop_stridx_short_wec(thr,obj_idx,stridx) \
+ duk_xdef_prop_stridx_short_raw((thr), \
+ (((duk_uint_t) (obj_idx)) << 24) + (((duk_uint_t) (stridx)) << 8) + \
+ (duk_uint_t) (desc_flags)))
+
+#define duk_xdef_prop_wec(thr, obj_idx) duk_xdef_prop((thr), (obj_idx), DUK_PROPDESC_FLAGS_WEC)
+#define duk_xdef_prop_index_wec(thr, obj_idx, arr_idx) duk_xdef_prop_index((thr), (obj_idx), (arr_idx), DUK_PROPDESC_FLAGS_WEC)
+#define duk_xdef_prop_stridx_wec(thr, obj_idx, stridx) duk_xdef_prop_stridx((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)
+#define duk_xdef_prop_stridx_short_wec(thr, obj_idx, stridx) \
duk_xdef_prop_stridx_short((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)
-#if 0 /*unused*/
+#if 0 /*unused*/
DUK_INTERNAL_DECL void duk_xdef_prop_stridx_builtin(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags); /* [] -> [] */
#endif
-DUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [] -> [] */
+DUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [] -> [] */
+
+DUK_INTERNAL_DECL duk_bool_t duk_get_method_stridx(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t stridx);
DUK_INTERNAL_DECL void duk_pack(duk_hthread *thr, duk_idx_t count);
DUK_INTERNAL_DECL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx);
@@ -5520,8 +6223,6 @@ DUK_INTERNAL_DECL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t id
DUK_INTERNAL_DECL void duk_unpack(duk_hthread *thr);
#endif
-DUK_INTERNAL_DECL void duk_require_constructor_call(duk_hthread *thr);
-DUK_INTERNAL_DECL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstring *h);
DUK_INTERNAL_DECL void duk_resolve_nonbound_function(duk_hthread *thr);
@@ -5550,33 +6251,35 @@ DUK_INTERNAL_DECL void duk_concat_2(duk_hthread *thr);
DUK_INTERNAL_DECL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags);
+#if defined(DUK_USE_SYMBOL_BUILTIN)
+DUK_INTERNAL_DECL void duk_to_primitive_ordinary(duk_hthread *thr, duk_idx_t idx, duk_int_t hint);
+#endif
+
+DUK_INTERNAL_DECL void duk_clear_prototype(duk_hthread *thr, duk_idx_t idx);
+
/* Raw internal valstack access macros: access is unsafe so call site
* must have a guarantee that the index is valid. When that is the case,
* using these macro results in faster and smaller code than duk_get_tval().
* Both 'ctx' and 'idx' are evaluted multiple times, but only for asserts.
*/
-#define DUK_ASSERT_VALID_NEGIDX(thr,idx) \
+#define DUK_ASSERT_VALID_NEGIDX(thr, idx) \
(DUK_ASSERT_EXPR((duk_int_t) (idx) < 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx))))
-#define DUK_ASSERT_VALID_POSIDX(thr,idx) \
+#define DUK_ASSERT_VALID_POSIDX(thr, idx) \
(DUK_ASSERT_EXPR((duk_int_t) (idx) >= 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx))))
-#define DUK_GET_TVAL_NEGIDX(thr,idx) \
- (DUK_ASSERT_VALID_NEGIDX((thr),(idx)), ((duk_hthread *) (thr))->valstack_top + (idx))
-#define DUK_GET_TVAL_POSIDX(thr,idx) \
- (DUK_ASSERT_VALID_POSIDX((thr),(idx)), ((duk_hthread *) (thr))->valstack_bottom + (idx))
-#define DUK_GET_HOBJECT_NEGIDX(thr,idx) \
- (DUK_ASSERT_VALID_NEGIDX((thr),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_top + (idx)))
-#define DUK_GET_HOBJECT_POSIDX(thr,idx) \
- (DUK_ASSERT_VALID_POSIDX((thr),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_bottom + (idx)))
-
-#define DUK_GET_THIS_TVAL_PTR(thr) \
- (DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \
- (thr)->valstack_bottom - 1)
+#define DUK_GET_TVAL_NEGIDX(thr, idx) (DUK_ASSERT_VALID_NEGIDX((thr), (idx)), ((duk_hthread *) (thr))->valstack_top + (idx))
+#define DUK_GET_TVAL_POSIDX(thr, idx) (DUK_ASSERT_VALID_POSIDX((thr), (idx)), ((duk_hthread *) (thr))->valstack_bottom + (idx))
+#define DUK_GET_HOBJECT_NEGIDX(thr, idx) \
+ (DUK_ASSERT_VALID_NEGIDX((thr), (idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_top + (idx)))
+#define DUK_GET_HOBJECT_POSIDX(thr, idx) \
+ (DUK_ASSERT_VALID_POSIDX((thr), (idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_bottom + (idx)))
+
+#define DUK_GET_THIS_TVAL_PTR(thr) (DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), (thr)->valstack_bottom - 1)
DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr);
DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr);
DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr);
-#endif /* DUK_API_INTERNAL_H_INCLUDED */
+#endif /* DUK_API_INTERNAL_H_INCLUDED */
/* #include duk_hstring.h */
/*
* Heap string representation.
@@ -5588,7 +6291,7 @@ DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr);
* strings used as internal property names and raw buffers converted to
* strings. In such cases the 'clen' field contains an inaccurate value.
*
- * Ecmascript requires support for 32-bit long strings. However, since each
+ * ECMAScript requires support for 32-bit long strings. However, since each
* 16-bit codepoint can take 3 bytes in CESU-8, this representation can only
* support about 1.4G codepoint long strings in extreme cases. This is not
* really a practical issue.
@@ -5607,147 +6310,168 @@ DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr);
*/
#if defined(DUK_USE_STRLEN16)
-#define DUK_HSTRING_MAX_BYTELEN (0x0000ffffUL)
+#define DUK_HSTRING_MAX_BYTELEN (0x0000ffffUL)
#else
-#define DUK_HSTRING_MAX_BYTELEN (0x7fffffffUL)
+#define DUK_HSTRING_MAX_BYTELEN (0x7fffffffUL)
#endif
-/* XXX: could add flags for "is valid CESU-8" (Ecmascript compatible strings),
+/* XXX: could add flags for "is valid CESU-8" (ECMAScript compatible strings),
* "is valid UTF-8", "is valid extended UTF-8" (internal strings are not,
* regexp bytecode is), and "contains non-BMP characters". These are not
* needed right now.
*/
-#define DUK_HSTRING_FLAG_ASCII DUK_HEAPHDR_USER_FLAG(0) /* string is ASCII, clen == blen */
-#define DUK_HSTRING_FLAG_ARRIDX DUK_HEAPHDR_USER_FLAG(1) /* string is a valid array index */
-#define DUK_HSTRING_FLAG_SYMBOL DUK_HEAPHDR_USER_FLAG(2) /* string is a symbol (invalid utf-8) */
-#define DUK_HSTRING_FLAG_HIDDEN DUK_HEAPHDR_USER_FLAG(3) /* string is a hidden symbol (implies symbol, Duktape 1.x internal string) */
-#define DUK_HSTRING_FLAG_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(4) /* string is a reserved word (non-strict) */
-#define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(5) /* string is a reserved word (strict) */
-#define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS DUK_HEAPHDR_USER_FLAG(6) /* string is 'eval' or 'arguments' */
-#define DUK_HSTRING_FLAG_EXTDATA DUK_HEAPHDR_USER_FLAG(7) /* string data is external (duk_hstring_external) */
-
-#define DUK_HSTRING_HAS_ASCII(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
-#define DUK_HSTRING_HAS_ARRIDX(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
-#define DUK_HSTRING_HAS_SYMBOL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
-#define DUK_HSTRING_HAS_HIDDEN(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
-#define DUK_HSTRING_HAS_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
-#define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
-#define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
-#define DUK_HSTRING_HAS_EXTDATA(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
-
-#define DUK_HSTRING_SET_ASCII(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
-#define DUK_HSTRING_SET_ARRIDX(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
-#define DUK_HSTRING_SET_SYMBOL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
-#define DUK_HSTRING_SET_HIDDEN(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
-#define DUK_HSTRING_SET_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
-#define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
-#define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
-#define DUK_HSTRING_SET_EXTDATA(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
-
-#define DUK_HSTRING_CLEAR_ASCII(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
-#define DUK_HSTRING_CLEAR_ARRIDX(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
-#define DUK_HSTRING_CLEAR_SYMBOL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
-#define DUK_HSTRING_CLEAR_HIDDEN(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
-#define DUK_HSTRING_CLEAR_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
-#define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
-#define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
-#define DUK_HSTRING_CLEAR_EXTDATA(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
-
-#if 0 /* Slightly smaller code without explicit flag, but explicit flag
- * is very useful when 'clen' is dropped.
- */
-#define DUK_HSTRING_IS_ASCII(x) (DUK_HSTRING_GET_BYTELEN((x)) == DUK_HSTRING_GET_CHARLEN((x)))
-#endif
-#define DUK_HSTRING_IS_ASCII(x) DUK_HSTRING_HAS_ASCII((x)) /* lazily set! */
-#define DUK_HSTRING_IS_EMPTY(x) (DUK_HSTRING_GET_BYTELEN((x)) == 0)
+/* With lowmem builds the high 16 bits of duk_heaphdr are used for other
+ * purposes, so this leaves 7 duk_heaphdr flags and 9 duk_hstring flags.
+ */
+#define DUK_HSTRING_FLAG_ASCII DUK_HEAPHDR_USER_FLAG(0) /* string is ASCII, clen == blen */
+#define DUK_HSTRING_FLAG_ARRIDX DUK_HEAPHDR_USER_FLAG(1) /* string is a valid array index */
+#define DUK_HSTRING_FLAG_SYMBOL DUK_HEAPHDR_USER_FLAG(2) /* string is a symbol (invalid utf-8) */
+#define DUK_HSTRING_FLAG_HIDDEN \
+ DUK_HEAPHDR_USER_FLAG(3) /* string is a hidden symbol (implies symbol, Duktape 1.x internal string) */
+#define DUK_HSTRING_FLAG_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(4) /* string is a reserved word (non-strict) */
+#define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(5) /* string is a reserved word (strict) */
+#define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS DUK_HEAPHDR_USER_FLAG(6) /* string is 'eval' or 'arguments' */
+#define DUK_HSTRING_FLAG_EXTDATA DUK_HEAPHDR_USER_FLAG(7) /* string data is external (duk_hstring_external) */
+#define DUK_HSTRING_FLAG_PINNED_LITERAL DUK_HEAPHDR_USER_FLAG(8) /* string is a literal, and pinned */
+
+#define DUK_HSTRING_HAS_ASCII(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
+#define DUK_HSTRING_HAS_ARRIDX(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
+#define DUK_HSTRING_HAS_SYMBOL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
+#define DUK_HSTRING_HAS_HIDDEN(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
+#define DUK_HSTRING_HAS_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
+#define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
+#define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
+#define DUK_HSTRING_HAS_EXTDATA(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
+#define DUK_HSTRING_HAS_PINNED_LITERAL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
+
+#define DUK_HSTRING_SET_ASCII(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
+#define DUK_HSTRING_SET_ARRIDX(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
+#define DUK_HSTRING_SET_SYMBOL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
+#define DUK_HSTRING_SET_HIDDEN(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
+#define DUK_HSTRING_SET_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
+#define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
+#define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
+#define DUK_HSTRING_SET_EXTDATA(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
+#define DUK_HSTRING_SET_PINNED_LITERAL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
+
+#define DUK_HSTRING_CLEAR_ASCII(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
+#define DUK_HSTRING_CLEAR_ARRIDX(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
+#define DUK_HSTRING_CLEAR_SYMBOL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
+#define DUK_HSTRING_CLEAR_HIDDEN(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
+#define DUK_HSTRING_CLEAR_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
+#define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
+#define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
+#define DUK_HSTRING_CLEAR_EXTDATA(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
+#define DUK_HSTRING_CLEAR_PINNED_LITERAL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
+
+#if 0 /* Slightly smaller code without explicit flag, but explicit flag \
+ * is very useful when 'clen' is dropped. \
+ */
+#define DUK_HSTRING_IS_ASCII(x) (DUK_HSTRING_GET_BYTELEN((x)) == DUK_HSTRING_GET_CHARLEN((x)))
+#endif
+#define DUK_HSTRING_IS_ASCII(x) DUK_HSTRING_HAS_ASCII((x)) /* lazily set! */
+#define DUK_HSTRING_IS_EMPTY(x) (DUK_HSTRING_GET_BYTELEN((x)) == 0)
#if defined(DUK_USE_STRHASH16)
-#define DUK_HSTRING_GET_HASH(x) ((x)->hdr.h_flags >> 16)
-#define DUK_HSTRING_SET_HASH(x,v) do { \
+#define DUK_HSTRING_GET_HASH(x) ((x)->hdr.h_flags >> 16)
+#define DUK_HSTRING_SET_HASH(x, v) \
+ do { \
(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | ((v) << 16); \
} while (0)
#else
-#define DUK_HSTRING_GET_HASH(x) ((x)->hash)
-#define DUK_HSTRING_SET_HASH(x,v) do { \
+#define DUK_HSTRING_GET_HASH(x) ((x)->hash)
+#define DUK_HSTRING_SET_HASH(x, v) \
+ do { \
(x)->hash = (v); \
} while (0)
#endif
#if defined(DUK_USE_STRLEN16)
-#define DUK_HSTRING_GET_BYTELEN(x) ((x)->hdr.h_strextra16)
-#define DUK_HSTRING_SET_BYTELEN(x,v) do { \
+#define DUK_HSTRING_GET_BYTELEN(x) ((x)->hdr.h_strextra16)
+#define DUK_HSTRING_SET_BYTELEN(x, v) \
+ do { \
(x)->hdr.h_strextra16 = (v); \
} while (0)
#if defined(DUK_USE_HSTRING_CLEN)
-#define DUK_HSTRING_GET_CHARLEN(x) duk_hstring_get_charlen((x))
-#define DUK_HSTRING_SET_CHARLEN(x,v) do { \
+#define DUK_HSTRING_GET_CHARLEN(x) duk_hstring_get_charlen((x))
+#define DUK_HSTRING_SET_CHARLEN(x, v) \
+ do { \
(x)->clen16 = (v); \
} while (0)
#else
-#define DUK_HSTRING_GET_CHARLEN(x) duk_hstring_get_charlen((x))
-#define DUK_HSTRING_SET_CHARLEN(x,v) do { \
- DUK_ASSERT(0); /* should never be called */ \
+#define DUK_HSTRING_GET_CHARLEN(x) duk_hstring_get_charlen((x))
+#define DUK_HSTRING_SET_CHARLEN(x, v) \
+ do { \
+ DUK_ASSERT(0); /* should never be called */ \
} while (0)
#endif
#else
-#define DUK_HSTRING_GET_BYTELEN(x) ((x)->blen)
-#define DUK_HSTRING_SET_BYTELEN(x,v) do { \
+#define DUK_HSTRING_GET_BYTELEN(x) ((x)->blen)
+#define DUK_HSTRING_SET_BYTELEN(x, v) \
+ do { \
(x)->blen = (v); \
} while (0)
-#define DUK_HSTRING_GET_CHARLEN(x) duk_hstring_get_charlen((x))
-#define DUK_HSTRING_SET_CHARLEN(x,v) do { \
+#define DUK_HSTRING_GET_CHARLEN(x) duk_hstring_get_charlen((x))
+#define DUK_HSTRING_SET_CHARLEN(x, v) \
+ do { \
(x)->clen = (v); \
} while (0)
#endif
#if defined(DUK_USE_HSTRING_EXTDATA)
-#define DUK_HSTRING_GET_EXTDATA(x) \
- ((x)->extdata)
+#define DUK_HSTRING_GET_EXTDATA(x) ((x)->extdata)
#define DUK_HSTRING_GET_DATA(x) \
- (DUK_HSTRING_HAS_EXTDATA((x)) ? \
- DUK_HSTRING_GET_EXTDATA((const duk_hstring_external *) (x)) : ((const duk_uint8_t *) ((x) + 1)))
+ (DUK_HSTRING_HAS_EXTDATA((x)) ? DUK_HSTRING_GET_EXTDATA((const duk_hstring_external *) (x)) : \
+ ((const duk_uint8_t *) ((x) + 1)))
#else
-#define DUK_HSTRING_GET_DATA(x) \
- ((const duk_uint8_t *) ((x) + 1))
+#define DUK_HSTRING_GET_DATA(x) ((const duk_uint8_t *) ((x) + 1))
#endif
-#define DUK_HSTRING_GET_DATA_END(x) \
- (DUK_HSTRING_GET_DATA((x)) + (x)->blen)
+#define DUK_HSTRING_GET_DATA_END(x) (DUK_HSTRING_GET_DATA((x)) + (x)->blen)
/* Marker value; in E5 2^32-1 is not a valid array index (2^32-2 is highest
* valid).
*/
-#define DUK_HSTRING_NO_ARRAY_INDEX (0xffffffffUL)
+#define DUK_HSTRING_NO_ARRAY_INDEX (0xffffffffUL)
#if defined(DUK_USE_HSTRING_ARRIDX)
-#define DUK_HSTRING_GET_ARRIDX_FAST(h) ((h)->arridx)
-#define DUK_HSTRING_GET_ARRIDX_SLOW(h) ((h)->arridx)
+#define DUK_HSTRING_GET_ARRIDX_FAST(h) ((h)->arridx)
+#define DUK_HSTRING_GET_ARRIDX_SLOW(h) ((h)->arridx)
#else
/* Get array index related to string (or return DUK_HSTRING_NO_ARRAY_INDEX);
* avoids helper call if string has no array index value.
*/
-#define DUK_HSTRING_GET_ARRIDX_FAST(h) \
+#define DUK_HSTRING_GET_ARRIDX_FAST(h) \
(DUK_HSTRING_HAS_ARRIDX((h)) ? duk_js_to_arrayindex_hstring_fast_known((h)) : DUK_HSTRING_NO_ARRAY_INDEX)
/* Slower but more compact variant. */
-#define DUK_HSTRING_GET_ARRIDX_SLOW(h) \
- (duk_js_to_arrayindex_hstring_fast((h)))
+#define DUK_HSTRING_GET_ARRIDX_SLOW(h) (duk_js_to_arrayindex_hstring_fast((h)))
#endif
/* XXX: these actually fit into duk_hstring */
-#define DUK_SYMBOL_TYPE_HIDDEN 0
-#define DUK_SYMBOL_TYPE_GLOBAL 1
-#define DUK_SYMBOL_TYPE_LOCAL 2
+#define DUK_SYMBOL_TYPE_HIDDEN 0
+#define DUK_SYMBOL_TYPE_GLOBAL 1
+#define DUK_SYMBOL_TYPE_LOCAL 2
#define DUK_SYMBOL_TYPE_WELLKNOWN 3
+/* Assertion for duk_hstring validity. */
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_hstring_assert_valid(duk_hstring *h);
+#define DUK_HSTRING_ASSERT_VALID(h) \
+ do { \
+ duk_hstring_assert_valid((h)); \
+ } while (0)
+#else
+#define DUK_HSTRING_ASSERT_VALID(h) \
+ do { \
+ } while (0)
+#endif
+
/*
* Misc
*/
-#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
-#pragma pack(push, 8)
-#endif
struct duk_hstring {
/* Smaller heaphdr than for other objects, because strings are held
* in string intern table which requires no link pointers. Much of
@@ -5792,16 +6516,7 @@ struct duk_hstring {
* for strings, but fields above should guarantee alignment-by-4
* (but not alignment-by-8).
*/
-}
-#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR)
-__attribute__ ((aligned (8)))
-#elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR)
-__attribute__ ((aligned (8)))
-#endif
-;
-#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
-#pragma pack(pop)
-#endif
+};
/* The external string struct is defined even when the feature is inactive. */
struct duk_hstring_external {
@@ -5820,24 +6535,27 @@ struct duk_hstring_external {
* Prototypes
*/
-DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos, duk_bool_t surrogate_aware);
+DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr,
+ duk_hstring *h,
+ duk_uint_t pos,
+ duk_bool_t surrogate_aware);
DUK_INTERNAL_DECL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const char *cstr);
DUK_INTERNAL_DECL duk_size_t duk_hstring_get_charlen(duk_hstring *h);
#if !defined(DUK_USE_HSTRING_LAZY_CLEN)
DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);
#endif
-#endif /* DUK_HSTRING_H_INCLUDED */
+#endif /* DUK_HSTRING_H_INCLUDED */
/* #include duk_hobject.h */
/*
* Heap object representation.
*
- * Heap objects are used for Ecmascript objects, arrays, and functions,
+ * Heap objects are used for ECMAScript objects, arrays, and functions,
* but also for internal control like declarative and object environment
* records. Compiled functions, native functions, and threads are also
* objects but with an extended C struct.
*
- * Objects provide the required Ecmascript semantics and exotic behaviors
+ * Objects provide the required ECMAScript semantics and exotic behaviors
* especially for property access.
*
* Properties are stored in three conceptual parts:
@@ -5870,36 +6588,40 @@ DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);
/* XXX: some flags are object subtype specific (e.g. common to all function
* subtypes, duk_harray, etc) and could be reused for different subtypes.
*/
-#define DUK_HOBJECT_FLAG_EXTENSIBLE DUK_HEAPHDR_USER_FLAG(0) /* object is extensible */
-#define DUK_HOBJECT_FLAG_CONSTRUCTABLE DUK_HEAPHDR_USER_FLAG(1) /* object is constructable */
-#define DUK_HOBJECT_FLAG_CALLABLE DUK_HEAPHDR_USER_FLAG(2) /* object is callable */
-#define DUK_HOBJECT_FLAG_BOUNDFUNC DUK_HEAPHDR_USER_FLAG(3) /* object established using Function.prototype.bind() */
-#define DUK_HOBJECT_FLAG_COMPFUNC DUK_HEAPHDR_USER_FLAG(4) /* object is a compiled function (duk_hcompfunc) */
-#define DUK_HOBJECT_FLAG_NATFUNC DUK_HEAPHDR_USER_FLAG(5) /* object is a native function (duk_hnatfunc) */
-#define DUK_HOBJECT_FLAG_BUFOBJ DUK_HEAPHDR_USER_FLAG(6) /* object is a buffer object (duk_hbufobj) (always exotic) */
-#define DUK_HOBJECT_FLAG_FASTREFS DUK_HEAPHDR_USER_FLAG(7) /* object has no fields needing DECREF/marking beyond base duk_hobject header */
-#define DUK_HOBJECT_FLAG_ARRAY_PART DUK_HEAPHDR_USER_FLAG(8) /* object has an array part (a_size may still be 0) */
-#define DUK_HOBJECT_FLAG_STRICT DUK_HEAPHDR_USER_FLAG(9) /* function: function object is strict */
-#define DUK_HOBJECT_FLAG_NOTAIL DUK_HEAPHDR_USER_FLAG(10) /* function: function must not be tail called */
-#define DUK_HOBJECT_FLAG_NEWENV DUK_HEAPHDR_USER_FLAG(11) /* function: create new environment when called (see duk_hcompfunc) */
-#define DUK_HOBJECT_FLAG_NAMEBINDING DUK_HEAPHDR_USER_FLAG(12) /* function: create binding for func name (function templates only, used for named function expressions) */
-#define DUK_HOBJECT_FLAG_CREATEARGS DUK_HEAPHDR_USER_FLAG(13) /* function: create an arguments object on function call */
-#define DUK_HOBJECT_FLAG_HAVE_FINALIZER DUK_HEAPHDR_USER_FLAG(14) /* object has a callable (own) finalizer property */
-#define DUK_HOBJECT_FLAG_EXOTIC_ARRAY DUK_HEAPHDR_USER_FLAG(15) /* 'Array' object, array length and index exotic behavior */
-#define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ DUK_HEAPHDR_USER_FLAG(16) /* 'String' object, array index exotic behavior */
-#define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS DUK_HEAPHDR_USER_FLAG(17) /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */
-#define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ DUK_HEAPHDR_USER_FLAG(18) /* 'Proxy' object */
-#define DUK_HOBJECT_FLAG_SPECIAL_CALL DUK_HEAPHDR_USER_FLAG(19) /* special casing in call behavior, for .call(), .apply(), etc. */
-
-#define DUK_HOBJECT_FLAG_CLASS_BASE DUK_HEAPHDR_USER_FLAG_NUMBER(20)
-#define DUK_HOBJECT_FLAG_CLASS_BITS 5
-
-#define DUK_HOBJECT_GET_CLASS_NUMBER(h) \
+#define DUK_HOBJECT_FLAG_EXTENSIBLE DUK_HEAPHDR_USER_FLAG(0) /* object is extensible */
+#define DUK_HOBJECT_FLAG_CONSTRUCTABLE DUK_HEAPHDR_USER_FLAG(1) /* object is constructable */
+#define DUK_HOBJECT_FLAG_CALLABLE DUK_HEAPHDR_USER_FLAG(2) /* object is callable */
+#define DUK_HOBJECT_FLAG_BOUNDFUNC DUK_HEAPHDR_USER_FLAG(3) /* object established using Function.prototype.bind() */
+#define DUK_HOBJECT_FLAG_COMPFUNC DUK_HEAPHDR_USER_FLAG(4) /* object is a compiled function (duk_hcompfunc) */
+#define DUK_HOBJECT_FLAG_NATFUNC DUK_HEAPHDR_USER_FLAG(5) /* object is a native function (duk_hnatfunc) */
+#define DUK_HOBJECT_FLAG_BUFOBJ DUK_HEAPHDR_USER_FLAG(6) /* object is a buffer object (duk_hbufobj) (always exotic) */
+#define DUK_HOBJECT_FLAG_FASTREFS \
+ DUK_HEAPHDR_USER_FLAG(7) /* object has no fields needing DECREF/marking beyond base duk_hobject header */
+#define DUK_HOBJECT_FLAG_ARRAY_PART DUK_HEAPHDR_USER_FLAG(8) /* object has an array part (a_size may still be 0) */
+#define DUK_HOBJECT_FLAG_STRICT DUK_HEAPHDR_USER_FLAG(9) /* function: function object is strict */
+#define DUK_HOBJECT_FLAG_NOTAIL DUK_HEAPHDR_USER_FLAG(10) /* function: function must not be tail called */
+#define DUK_HOBJECT_FLAG_NEWENV DUK_HEAPHDR_USER_FLAG(11) /* function: create new environment when called (see duk_hcompfunc) */
+#define DUK_HOBJECT_FLAG_NAMEBINDING \
+ DUK_HEAPHDR_USER_FLAG( \
+ 12) /* function: create binding for func name (function templates only, used for named function expressions) */
+#define DUK_HOBJECT_FLAG_CREATEARGS DUK_HEAPHDR_USER_FLAG(13) /* function: create an arguments object on function call */
+#define DUK_HOBJECT_FLAG_HAVE_FINALIZER DUK_HEAPHDR_USER_FLAG(14) /* object has a callable (own) finalizer property */
+#define DUK_HOBJECT_FLAG_EXOTIC_ARRAY DUK_HEAPHDR_USER_FLAG(15) /* 'Array' object, array length and index exotic behavior */
+#define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ DUK_HEAPHDR_USER_FLAG(16) /* 'String' object, array index exotic behavior */
+#define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS \
+ DUK_HEAPHDR_USER_FLAG(17) /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */
+#define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ DUK_HEAPHDR_USER_FLAG(18) /* 'Proxy' object */
+#define DUK_HOBJECT_FLAG_SPECIAL_CALL DUK_HEAPHDR_USER_FLAG(19) /* special casing in call behavior, for .call(), .apply(), etc. */
+
+#define DUK_HOBJECT_FLAG_CLASS_BASE DUK_HEAPHDR_USER_FLAG_NUMBER(20)
+#define DUK_HOBJECT_FLAG_CLASS_BITS 5
+
+#define DUK_HOBJECT_GET_CLASS_NUMBER(h) \
DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS)
-#define DUK_HOBJECT_SET_CLASS_NUMBER(h,v) \
+#define DUK_HOBJECT_SET_CLASS_NUMBER(h, v) \
DUK_HEAPHDR_SET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS, (v))
-#define DUK_HOBJECT_GET_CLASS_MASK(h) \
+#define DUK_HOBJECT_GET_CLASS_MASK(h) \
(1UL << DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS))
/* Macro for creating flag initializer from a class number.
@@ -5907,256 +6629,239 @@ DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);
* a signed integer to an unsigned one; the largest class values
* have the highest bit (bit 31) set which causes this.
*/
-#define DUK_HOBJECT_CLASS_AS_FLAGS(v) (((duk_uint_t) (v)) << DUK_HOBJECT_FLAG_CLASS_BASE)
+#define DUK_HOBJECT_CLASS_AS_FLAGS(v) (((duk_uint_t) (v)) << DUK_HOBJECT_FLAG_CLASS_BASE)
/* E5 Section 8.6.2 + custom classes */
-#define DUK_HOBJECT_CLASS_NONE 0
-#define DUK_HOBJECT_CLASS_OBJECT 1
-#define DUK_HOBJECT_CLASS_ARRAY 2
-#define DUK_HOBJECT_CLASS_FUNCTION 3
-#define DUK_HOBJECT_CLASS_ARGUMENTS 4
-#define DUK_HOBJECT_CLASS_BOOLEAN 5
-#define DUK_HOBJECT_CLASS_DATE 6
-#define DUK_HOBJECT_CLASS_ERROR 7
-#define DUK_HOBJECT_CLASS_JSON 8
-#define DUK_HOBJECT_CLASS_MATH 9
-#define DUK_HOBJECT_CLASS_NUMBER 10
-#define DUK_HOBJECT_CLASS_REGEXP 11
-#define DUK_HOBJECT_CLASS_STRING 12
-#define DUK_HOBJECT_CLASS_GLOBAL 13
-#define DUK_HOBJECT_CLASS_SYMBOL 14
-#define DUK_HOBJECT_CLASS_OBJENV 15 /* custom */
-#define DUK_HOBJECT_CLASS_DECENV 16 /* custom */
-#define DUK_HOBJECT_CLASS_POINTER 17 /* custom */
-#define DUK_HOBJECT_CLASS_THREAD 18 /* custom; implies DUK_HOBJECT_IS_THREAD */
-#define DUK_HOBJECT_CLASS_BUFOBJ_MIN 19
-#define DUK_HOBJECT_CLASS_ARRAYBUFFER 19 /* implies DUK_HOBJECT_IS_BUFOBJ */
-#define DUK_HOBJECT_CLASS_DATAVIEW 20
-#define DUK_HOBJECT_CLASS_INT8ARRAY 21
-#define DUK_HOBJECT_CLASS_UINT8ARRAY 22
-#define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY 23
-#define DUK_HOBJECT_CLASS_INT16ARRAY 24
-#define DUK_HOBJECT_CLASS_UINT16ARRAY 25
-#define DUK_HOBJECT_CLASS_INT32ARRAY 26
-#define DUK_HOBJECT_CLASS_UINT32ARRAY 27
-#define DUK_HOBJECT_CLASS_FLOAT32ARRAY 28
-#define DUK_HOBJECT_CLASS_FLOAT64ARRAY 29
-#define DUK_HOBJECT_CLASS_BUFOBJ_MAX 29
-#define DUK_HOBJECT_CLASS_MAX 29
+#define DUK_HOBJECT_CLASS_NONE 0
+#define DUK_HOBJECT_CLASS_OBJECT 1
+#define DUK_HOBJECT_CLASS_ARRAY 2
+#define DUK_HOBJECT_CLASS_FUNCTION 3
+#define DUK_HOBJECT_CLASS_ARGUMENTS 4
+#define DUK_HOBJECT_CLASS_BOOLEAN 5
+#define DUK_HOBJECT_CLASS_DATE 6
+#define DUK_HOBJECT_CLASS_ERROR 7
+#define DUK_HOBJECT_CLASS_JSON 8
+#define DUK_HOBJECT_CLASS_MATH 9
+#define DUK_HOBJECT_CLASS_NUMBER 10
+#define DUK_HOBJECT_CLASS_REGEXP 11
+#define DUK_HOBJECT_CLASS_STRING 12
+#define DUK_HOBJECT_CLASS_GLOBAL 13
+#define DUK_HOBJECT_CLASS_SYMBOL 14
+#define DUK_HOBJECT_CLASS_OBJENV 15 /* custom */
+#define DUK_HOBJECT_CLASS_DECENV 16 /* custom */
+#define DUK_HOBJECT_CLASS_POINTER 17 /* custom */
+#define DUK_HOBJECT_CLASS_THREAD 18 /* custom; implies DUK_HOBJECT_IS_THREAD */
+#define DUK_HOBJECT_CLASS_BUFOBJ_MIN 19
+#define DUK_HOBJECT_CLASS_ARRAYBUFFER 19 /* implies DUK_HOBJECT_IS_BUFOBJ */
+#define DUK_HOBJECT_CLASS_DATAVIEW 20
+#define DUK_HOBJECT_CLASS_INT8ARRAY 21
+#define DUK_HOBJECT_CLASS_UINT8ARRAY 22
+#define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY 23
+#define DUK_HOBJECT_CLASS_INT16ARRAY 24
+#define DUK_HOBJECT_CLASS_UINT16ARRAY 25
+#define DUK_HOBJECT_CLASS_INT32ARRAY 26
+#define DUK_HOBJECT_CLASS_UINT32ARRAY 27
+#define DUK_HOBJECT_CLASS_FLOAT32ARRAY 28
+#define DUK_HOBJECT_CLASS_FLOAT64ARRAY 29
+#define DUK_HOBJECT_CLASS_BUFOBJ_MAX 29
+#define DUK_HOBJECT_CLASS_MAX 29
/* Class masks. */
-#define DUK_HOBJECT_CMASK_ALL ((1UL << (DUK_HOBJECT_CLASS_MAX + 1)) - 1UL)
-#define DUK_HOBJECT_CMASK_NONE (1UL << DUK_HOBJECT_CLASS_NONE)
-#define DUK_HOBJECT_CMASK_ARGUMENTS (1UL << DUK_HOBJECT_CLASS_ARGUMENTS)
-#define DUK_HOBJECT_CMASK_ARRAY (1UL << DUK_HOBJECT_CLASS_ARRAY)
-#define DUK_HOBJECT_CMASK_BOOLEAN (1UL << DUK_HOBJECT_CLASS_BOOLEAN)
-#define DUK_HOBJECT_CMASK_DATE (1UL << DUK_HOBJECT_CLASS_DATE)
-#define DUK_HOBJECT_CMASK_ERROR (1UL << DUK_HOBJECT_CLASS_ERROR)
-#define DUK_HOBJECT_CMASK_FUNCTION (1UL << DUK_HOBJECT_CLASS_FUNCTION)
-#define DUK_HOBJECT_CMASK_JSON (1UL << DUK_HOBJECT_CLASS_JSON)
-#define DUK_HOBJECT_CMASK_MATH (1UL << DUK_HOBJECT_CLASS_MATH)
-#define DUK_HOBJECT_CMASK_NUMBER (1UL << DUK_HOBJECT_CLASS_NUMBER)
-#define DUK_HOBJECT_CMASK_OBJECT (1UL << DUK_HOBJECT_CLASS_OBJECT)
-#define DUK_HOBJECT_CMASK_REGEXP (1UL << DUK_HOBJECT_CLASS_REGEXP)
-#define DUK_HOBJECT_CMASK_STRING (1UL << DUK_HOBJECT_CLASS_STRING)
-#define DUK_HOBJECT_CMASK_GLOBAL (1UL << DUK_HOBJECT_CLASS_GLOBAL)
-#define DUK_HOBJECT_CMASK_SYMBOL (1UL << DUK_HOBJECT_CLASS_SYMBOL)
-#define DUK_HOBJECT_CMASK_OBJENV (1UL << DUK_HOBJECT_CLASS_OBJENV)
-#define DUK_HOBJECT_CMASK_DECENV (1UL << DUK_HOBJECT_CLASS_DECENV)
-#define DUK_HOBJECT_CMASK_POINTER (1UL << DUK_HOBJECT_CLASS_POINTER)
-#define DUK_HOBJECT_CMASK_ARRAYBUFFER (1UL << DUK_HOBJECT_CLASS_ARRAYBUFFER)
-#define DUK_HOBJECT_CMASK_DATAVIEW (1UL << DUK_HOBJECT_CLASS_DATAVIEW)
-#define DUK_HOBJECT_CMASK_INT8ARRAY (1UL << DUK_HOBJECT_CLASS_INT8ARRAY)
-#define DUK_HOBJECT_CMASK_UINT8ARRAY (1UL << DUK_HOBJECT_CLASS_UINT8ARRAY)
-#define DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY (1UL << DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY)
-#define DUK_HOBJECT_CMASK_INT16ARRAY (1UL << DUK_HOBJECT_CLASS_INT16ARRAY)
-#define DUK_HOBJECT_CMASK_UINT16ARRAY (1UL << DUK_HOBJECT_CLASS_UINT16ARRAY)
-#define DUK_HOBJECT_CMASK_INT32ARRAY (1UL << DUK_HOBJECT_CLASS_INT32ARRAY)
-#define DUK_HOBJECT_CMASK_UINT32ARRAY (1UL << DUK_HOBJECT_CLASS_UINT32ARRAY)
-#define DUK_HOBJECT_CMASK_FLOAT32ARRAY (1UL << DUK_HOBJECT_CLASS_FLOAT32ARRAY)
-#define DUK_HOBJECT_CMASK_FLOAT64ARRAY (1UL << DUK_HOBJECT_CLASS_FLOAT64ARRAY)
+#define DUK_HOBJECT_CMASK_ALL ((1UL << (DUK_HOBJECT_CLASS_MAX + 1)) - 1UL)
+#define DUK_HOBJECT_CMASK_NONE (1UL << DUK_HOBJECT_CLASS_NONE)
+#define DUK_HOBJECT_CMASK_ARGUMENTS (1UL << DUK_HOBJECT_CLASS_ARGUMENTS)
+#define DUK_HOBJECT_CMASK_ARRAY (1UL << DUK_HOBJECT_CLASS_ARRAY)
+#define DUK_HOBJECT_CMASK_BOOLEAN (1UL << DUK_HOBJECT_CLASS_BOOLEAN)
+#define DUK_HOBJECT_CMASK_DATE (1UL << DUK_HOBJECT_CLASS_DATE)
+#define DUK_HOBJECT_CMASK_ERROR (1UL << DUK_HOBJECT_CLASS_ERROR)
+#define DUK_HOBJECT_CMASK_FUNCTION (1UL << DUK_HOBJECT_CLASS_FUNCTION)
+#define DUK_HOBJECT_CMASK_JSON (1UL << DUK_HOBJECT_CLASS_JSON)
+#define DUK_HOBJECT_CMASK_MATH (1UL << DUK_HOBJECT_CLASS_MATH)
+#define DUK_HOBJECT_CMASK_NUMBER (1UL << DUK_HOBJECT_CLASS_NUMBER)
+#define DUK_HOBJECT_CMASK_OBJECT (1UL << DUK_HOBJECT_CLASS_OBJECT)
+#define DUK_HOBJECT_CMASK_REGEXP (1UL << DUK_HOBJECT_CLASS_REGEXP)
+#define DUK_HOBJECT_CMASK_STRING (1UL << DUK_HOBJECT_CLASS_STRING)
+#define DUK_HOBJECT_CMASK_GLOBAL (1UL << DUK_HOBJECT_CLASS_GLOBAL)
+#define DUK_HOBJECT_CMASK_SYMBOL (1UL << DUK_HOBJECT_CLASS_SYMBOL)
+#define DUK_HOBJECT_CMASK_OBJENV (1UL << DUK_HOBJECT_CLASS_OBJENV)
+#define DUK_HOBJECT_CMASK_DECENV (1UL << DUK_HOBJECT_CLASS_DECENV)
+#define DUK_HOBJECT_CMASK_POINTER (1UL << DUK_HOBJECT_CLASS_POINTER)
+#define DUK_HOBJECT_CMASK_ARRAYBUFFER (1UL << DUK_HOBJECT_CLASS_ARRAYBUFFER)
+#define DUK_HOBJECT_CMASK_DATAVIEW (1UL << DUK_HOBJECT_CLASS_DATAVIEW)
+#define DUK_HOBJECT_CMASK_INT8ARRAY (1UL << DUK_HOBJECT_CLASS_INT8ARRAY)
+#define DUK_HOBJECT_CMASK_UINT8ARRAY (1UL << DUK_HOBJECT_CLASS_UINT8ARRAY)
+#define DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY (1UL << DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY)
+#define DUK_HOBJECT_CMASK_INT16ARRAY (1UL << DUK_HOBJECT_CLASS_INT16ARRAY)
+#define DUK_HOBJECT_CMASK_UINT16ARRAY (1UL << DUK_HOBJECT_CLASS_UINT16ARRAY)
+#define DUK_HOBJECT_CMASK_INT32ARRAY (1UL << DUK_HOBJECT_CLASS_INT32ARRAY)
+#define DUK_HOBJECT_CMASK_UINT32ARRAY (1UL << DUK_HOBJECT_CLASS_UINT32ARRAY)
+#define DUK_HOBJECT_CMASK_FLOAT32ARRAY (1UL << DUK_HOBJECT_CLASS_FLOAT32ARRAY)
+#define DUK_HOBJECT_CMASK_FLOAT64ARRAY (1UL << DUK_HOBJECT_CLASS_FLOAT64ARRAY)
#define DUK_HOBJECT_CMASK_ALL_BUFOBJS \
- (DUK_HOBJECT_CMASK_ARRAYBUFFER | \
- DUK_HOBJECT_CMASK_DATAVIEW | \
- DUK_HOBJECT_CMASK_INT8ARRAY | \
- DUK_HOBJECT_CMASK_UINT8ARRAY | \
- DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY | \
- DUK_HOBJECT_CMASK_INT16ARRAY | \
- DUK_HOBJECT_CMASK_UINT16ARRAY | \
- DUK_HOBJECT_CMASK_INT32ARRAY | \
- DUK_HOBJECT_CMASK_UINT32ARRAY | \
- DUK_HOBJECT_CMASK_FLOAT32ARRAY | \
+ (DUK_HOBJECT_CMASK_ARRAYBUFFER | DUK_HOBJECT_CMASK_DATAVIEW | DUK_HOBJECT_CMASK_INT8ARRAY | DUK_HOBJECT_CMASK_UINT8ARRAY | \
+ DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY | DUK_HOBJECT_CMASK_INT16ARRAY | DUK_HOBJECT_CMASK_UINT16ARRAY | \
+ DUK_HOBJECT_CMASK_INT32ARRAY | DUK_HOBJECT_CMASK_UINT32ARRAY | DUK_HOBJECT_CMASK_FLOAT32ARRAY | \
DUK_HOBJECT_CMASK_FLOAT64ARRAY)
-#define DUK_HOBJECT_IS_OBJENV(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_OBJENV)
-#define DUK_HOBJECT_IS_DECENV(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DECENV)
-#define DUK_HOBJECT_IS_ENV(h) (DUK_HOBJECT_IS_OBJENV((h)) || DUK_HOBJECT_IS_DECENV((h)))
-#define DUK_HOBJECT_IS_ARRAY(h) DUK_HOBJECT_HAS_EXOTIC_ARRAY((h)) /* Rely on class Array <=> exotic Array */
-#define DUK_HOBJECT_IS_BOUNDFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
-#define DUK_HOBJECT_IS_COMPFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
-#define DUK_HOBJECT_IS_NATFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
+#define DUK_HOBJECT_IS_OBJENV(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_OBJENV)
+#define DUK_HOBJECT_IS_DECENV(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DECENV)
+#define DUK_HOBJECT_IS_ENV(h) (DUK_HOBJECT_IS_OBJENV((h)) || DUK_HOBJECT_IS_DECENV((h)))
+#define DUK_HOBJECT_IS_ARRAY(h) DUK_HOBJECT_HAS_EXOTIC_ARRAY((h)) /* Rely on class Array <=> exotic Array */
+#define DUK_HOBJECT_IS_BOUNDFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
+#define DUK_HOBJECT_IS_COMPFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
+#define DUK_HOBJECT_IS_NATFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
-#define DUK_HOBJECT_IS_BUFOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
+#define DUK_HOBJECT_IS_BUFOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
#else
-#define DUK_HOBJECT_IS_BUFOBJ(h) 0
+#define DUK_HOBJECT_IS_BUFOBJ(h) 0
#endif
-#define DUK_HOBJECT_IS_THREAD(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_THREAD)
+#define DUK_HOBJECT_IS_THREAD(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_THREAD)
#if defined(DUK_USE_ES6_PROXY)
-#define DUK_HOBJECT_IS_PROXY(h) DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((h))
+#define DUK_HOBJECT_IS_PROXY(h) DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((h))
#else
-#define DUK_HOBJECT_IS_PROXY(h) 0
+#define DUK_HOBJECT_IS_PROXY(h) 0
#endif
-#define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
- DUK_HOBJECT_FLAG_COMPFUNC | \
- DUK_HOBJECT_FLAG_NATFUNC)
+#define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h) \
+ DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC | DUK_HOBJECT_FLAG_NATFUNC)
-#define DUK_HOBJECT_IS_FUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
- DUK_HOBJECT_FLAG_BOUNDFUNC | \
- DUK_HOBJECT_FLAG_COMPFUNC | \
- DUK_HOBJECT_FLAG_NATFUNC)
+#define DUK_HOBJECT_IS_FUNCTION(h) \
+ DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC | DUK_HOBJECT_FLAG_COMPFUNC | DUK_HOBJECT_FLAG_NATFUNC)
-#define DUK_HOBJECT_IS_CALLABLE(h) DUK_HOBJECT_HAS_CALLABLE((h))
+#define DUK_HOBJECT_IS_CALLABLE(h) DUK_HOBJECT_HAS_CALLABLE((h))
/* Object has any exotic behavior(s). */
-#define DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
- DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS | \
- DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
- DUK_HOBJECT_FLAG_BUFOBJ | \
- DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
-#define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS)
+#define DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS \
+ (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS | DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
+ DUK_HOBJECT_FLAG_BUFOBJ | DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
+#define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS)
/* Object has any virtual properties (not counting Proxy behavior). */
-#define DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
- DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
- DUK_HOBJECT_FLAG_BUFOBJ)
-#define DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS)
-
-#define DUK_HOBJECT_HAS_EXTENSIBLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
-#define DUK_HOBJECT_HAS_CONSTRUCTABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
-#define DUK_HOBJECT_HAS_CALLABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
-#define DUK_HOBJECT_HAS_BOUNDFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
-#define DUK_HOBJECT_HAS_COMPFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
-#define DUK_HOBJECT_HAS_NATFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
+#define DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS \
+ (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | DUK_HOBJECT_FLAG_BUFOBJ)
+#define DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS)
+
+#define DUK_HOBJECT_HAS_EXTENSIBLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
+#define DUK_HOBJECT_HAS_CONSTRUCTABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
+#define DUK_HOBJECT_HAS_CALLABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
+#define DUK_HOBJECT_HAS_BOUNDFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
+#define DUK_HOBJECT_HAS_COMPFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
+#define DUK_HOBJECT_HAS_NATFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
-#define DUK_HOBJECT_HAS_BUFOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
+#define DUK_HOBJECT_HAS_BUFOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
#else
-#define DUK_HOBJECT_HAS_BUFOBJ(h) 0
-#endif
-#define DUK_HOBJECT_HAS_FASTREFS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
-#define DUK_HOBJECT_HAS_ARRAY_PART(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
-#define DUK_HOBJECT_HAS_STRICT(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
-#define DUK_HOBJECT_HAS_NOTAIL(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
-#define DUK_HOBJECT_HAS_NEWENV(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
-#define DUK_HOBJECT_HAS_NAMEBINDING(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
-#define DUK_HOBJECT_HAS_CREATEARGS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
-#define DUK_HOBJECT_HAS_HAVE_FINALIZER(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
-#define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
-#define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
-#define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
+#define DUK_HOBJECT_HAS_BUFOBJ(h) 0
+#endif
+#define DUK_HOBJECT_HAS_FASTREFS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
+#define DUK_HOBJECT_HAS_ARRAY_PART(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
+#define DUK_HOBJECT_HAS_STRICT(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
+#define DUK_HOBJECT_HAS_NOTAIL(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
+#define DUK_HOBJECT_HAS_NEWENV(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
+#define DUK_HOBJECT_HAS_NAMEBINDING(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
+#define DUK_HOBJECT_HAS_CREATEARGS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
+#define DUK_HOBJECT_HAS_HAVE_FINALIZER(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
+#define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
+#define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
+#define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
#if defined(DUK_USE_ES6_PROXY)
-#define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
+#define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
#else
-#define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h) 0
+#define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h) 0
#endif
-#define DUK_HOBJECT_HAS_SPECIAL_CALL(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
+#define DUK_HOBJECT_HAS_SPECIAL_CALL(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
-#define DUK_HOBJECT_SET_EXTENSIBLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
-#define DUK_HOBJECT_SET_CONSTRUCTABLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
-#define DUK_HOBJECT_SET_CALLABLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
-#define DUK_HOBJECT_SET_BOUNDFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
-#define DUK_HOBJECT_SET_COMPFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
-#define DUK_HOBJECT_SET_NATFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
+#define DUK_HOBJECT_SET_EXTENSIBLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
+#define DUK_HOBJECT_SET_CONSTRUCTABLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
+#define DUK_HOBJECT_SET_CALLABLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
+#define DUK_HOBJECT_SET_BOUNDFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
+#define DUK_HOBJECT_SET_COMPFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
+#define DUK_HOBJECT_SET_NATFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
-#define DUK_HOBJECT_SET_BUFOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
-#endif
-#define DUK_HOBJECT_SET_FASTREFS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
-#define DUK_HOBJECT_SET_ARRAY_PART(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
-#define DUK_HOBJECT_SET_STRICT(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
-#define DUK_HOBJECT_SET_NOTAIL(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
-#define DUK_HOBJECT_SET_NEWENV(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
-#define DUK_HOBJECT_SET_NAMEBINDING(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
-#define DUK_HOBJECT_SET_CREATEARGS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
-#define DUK_HOBJECT_SET_HAVE_FINALIZER(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
-#define DUK_HOBJECT_SET_EXOTIC_ARRAY(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
-#define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
-#define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
+#define DUK_HOBJECT_SET_BUFOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
+#endif
+#define DUK_HOBJECT_SET_FASTREFS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
+#define DUK_HOBJECT_SET_ARRAY_PART(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
+#define DUK_HOBJECT_SET_STRICT(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
+#define DUK_HOBJECT_SET_NOTAIL(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
+#define DUK_HOBJECT_SET_NEWENV(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
+#define DUK_HOBJECT_SET_NAMEBINDING(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
+#define DUK_HOBJECT_SET_CREATEARGS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
+#define DUK_HOBJECT_SET_HAVE_FINALIZER(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
+#define DUK_HOBJECT_SET_EXOTIC_ARRAY(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
+#define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
+#define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
#if defined(DUK_USE_ES6_PROXY)
-#define DUK_HOBJECT_SET_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
+#define DUK_HOBJECT_SET_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
#endif
-#define DUK_HOBJECT_SET_SPECIAL_CALL(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
+#define DUK_HOBJECT_SET_SPECIAL_CALL(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
-#define DUK_HOBJECT_CLEAR_EXTENSIBLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
-#define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
-#define DUK_HOBJECT_CLEAR_CALLABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
-#define DUK_HOBJECT_CLEAR_BOUNDFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
-#define DUK_HOBJECT_CLEAR_COMPFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
-#define DUK_HOBJECT_CLEAR_NATFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
+#define DUK_HOBJECT_CLEAR_EXTENSIBLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
+#define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
+#define DUK_HOBJECT_CLEAR_CALLABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
+#define DUK_HOBJECT_CLEAR_BOUNDFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
+#define DUK_HOBJECT_CLEAR_COMPFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
+#define DUK_HOBJECT_CLEAR_NATFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
-#define DUK_HOBJECT_CLEAR_BUFOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
-#endif
-#define DUK_HOBJECT_CLEAR_FASTREFS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
-#define DUK_HOBJECT_CLEAR_ARRAY_PART(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
-#define DUK_HOBJECT_CLEAR_STRICT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
-#define DUK_HOBJECT_CLEAR_NOTAIL(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
-#define DUK_HOBJECT_CLEAR_NEWENV(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
-#define DUK_HOBJECT_CLEAR_NAMEBINDING(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
-#define DUK_HOBJECT_CLEAR_CREATEARGS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
-#define DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
-#define DUK_HOBJECT_CLEAR_EXOTIC_ARRAY(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
-#define DUK_HOBJECT_CLEAR_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
-#define DUK_HOBJECT_CLEAR_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
+#define DUK_HOBJECT_CLEAR_BUFOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
+#endif
+#define DUK_HOBJECT_CLEAR_FASTREFS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
+#define DUK_HOBJECT_CLEAR_ARRAY_PART(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
+#define DUK_HOBJECT_CLEAR_STRICT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
+#define DUK_HOBJECT_CLEAR_NOTAIL(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
+#define DUK_HOBJECT_CLEAR_NEWENV(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
+#define DUK_HOBJECT_CLEAR_NAMEBINDING(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
+#define DUK_HOBJECT_CLEAR_CREATEARGS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
+#define DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
+#define DUK_HOBJECT_CLEAR_EXOTIC_ARRAY(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
+#define DUK_HOBJECT_CLEAR_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
+#define DUK_HOBJECT_CLEAR_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
#if defined(DUK_USE_ES6_PROXY)
-#define DUK_HOBJECT_CLEAR_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
+#define DUK_HOBJECT_CLEAR_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
#endif
-#define DUK_HOBJECT_CLEAR_SPECIAL_CALL(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
+#define DUK_HOBJECT_CLEAR_SPECIAL_CALL(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
/* Object can/cannot use FASTREFS, i.e. has no strong reference fields beyond
* duk_hobject base header. This is used just for asserts so doesn't need to
* be optimized.
*/
#define DUK_HOBJECT_PROHIBITS_FASTREFS(h) \
- (DUK_HOBJECT_IS_COMPFUNC((h)) || DUK_HOBJECT_IS_DECENV((h)) || DUK_HOBJECT_IS_OBJENV((h)) || \
- DUK_HOBJECT_IS_BUFOBJ((h)) || DUK_HOBJECT_IS_THREAD((h)) || DUK_HOBJECT_IS_PROXY((h)) || \
- DUK_HOBJECT_IS_BOUNDFUNC((h)))
+ (DUK_HOBJECT_IS_COMPFUNC((h)) || DUK_HOBJECT_IS_DECENV((h)) || DUK_HOBJECT_IS_OBJENV((h)) || DUK_HOBJECT_IS_BUFOBJ((h)) || \
+ DUK_HOBJECT_IS_THREAD((h)) || DUK_HOBJECT_IS_PROXY((h)) || DUK_HOBJECT_IS_BOUNDFUNC((h)))
#define DUK_HOBJECT_ALLOWS_FASTREFS(h) (!DUK_HOBJECT_PROHIBITS_FASTREFS((h)))
/* Flags used for property attributes in duk_propdesc and packed flags.
* Must fit into 8 bits.
*/
-#define DUK_PROPDESC_FLAG_WRITABLE (1U << 0) /* E5 Section 8.6.1 */
-#define DUK_PROPDESC_FLAG_ENUMERABLE (1U << 1) /* E5 Section 8.6.1 */
-#define DUK_PROPDESC_FLAG_CONFIGURABLE (1U << 2) /* E5 Section 8.6.1 */
-#define DUK_PROPDESC_FLAG_ACCESSOR (1U << 3) /* accessor */
-#define DUK_PROPDESC_FLAG_VIRTUAL (1U << 4) /* property is virtual: used in duk_propdesc, never stored
- * (used by e.g. buffer virtual properties)
- */
-#define DUK_PROPDESC_FLAGS_MASK (DUK_PROPDESC_FLAG_WRITABLE | \
- DUK_PROPDESC_FLAG_ENUMERABLE | \
- DUK_PROPDESC_FLAG_CONFIGURABLE | \
- DUK_PROPDESC_FLAG_ACCESSOR)
+#define DUK_PROPDESC_FLAG_WRITABLE (1U << 0) /* E5 Section 8.6.1 */
+#define DUK_PROPDESC_FLAG_ENUMERABLE (1U << 1) /* E5 Section 8.6.1 */
+#define DUK_PROPDESC_FLAG_CONFIGURABLE (1U << 2) /* E5 Section 8.6.1 */
+#define DUK_PROPDESC_FLAG_ACCESSOR (1U << 3) /* accessor */
+#define DUK_PROPDESC_FLAG_VIRTUAL \
+ (1U << 4) /* property is virtual: used in duk_propdesc, never stored \
+ * (used by e.g. buffer virtual properties) \
+ */
+#define DUK_PROPDESC_FLAGS_MASK \
+ (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE | DUK_PROPDESC_FLAG_ACCESSOR)
/* Additional flags which are passed in the same flags argument as property
* flags but are not stored in object properties.
*/
-#define DUK_PROPDESC_FLAG_NO_OVERWRITE (1U << 4) /* internal define property: skip write silently if exists */
+#define DUK_PROPDESC_FLAG_NO_OVERWRITE (1U << 4) /* internal define property: skip write silently if exists */
/* Convenience defines for property attributes. */
-#define DUK_PROPDESC_FLAGS_NONE 0
-#define DUK_PROPDESC_FLAGS_W (DUK_PROPDESC_FLAG_WRITABLE)
-#define DUK_PROPDESC_FLAGS_E (DUK_PROPDESC_FLAG_ENUMERABLE)
-#define DUK_PROPDESC_FLAGS_C (DUK_PROPDESC_FLAG_CONFIGURABLE)
-#define DUK_PROPDESC_FLAGS_WE (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE)
-#define DUK_PROPDESC_FLAGS_WC (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
-#define DUK_PROPDESC_FLAGS_EC (DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
-#define DUK_PROPDESC_FLAGS_WEC (DUK_PROPDESC_FLAG_WRITABLE | \
- DUK_PROPDESC_FLAG_ENUMERABLE | \
- DUK_PROPDESC_FLAG_CONFIGURABLE)
+#define DUK_PROPDESC_FLAGS_NONE 0
+#define DUK_PROPDESC_FLAGS_W (DUK_PROPDESC_FLAG_WRITABLE)
+#define DUK_PROPDESC_FLAGS_E (DUK_PROPDESC_FLAG_ENUMERABLE)
+#define DUK_PROPDESC_FLAGS_C (DUK_PROPDESC_FLAG_CONFIGURABLE)
+#define DUK_PROPDESC_FLAGS_WE (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE)
+#define DUK_PROPDESC_FLAGS_WC (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
+#define DUK_PROPDESC_FLAGS_EC (DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
+#define DUK_PROPDESC_FLAGS_WEC (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
/* Flags for duk_hobject_get_own_propdesc() and variants. */
-#define DUK_GETDESC_FLAG_PUSH_VALUE (1U << 0) /* push value to stack */
-#define DUK_GETDESC_FLAG_IGNORE_PROTOLOOP (1U << 1) /* don't throw for prototype loop */
+#define DUK_GETDESC_FLAG_PUSH_VALUE (1U << 0) /* push value to stack */
+#define DUK_GETDESC_FLAG_IGNORE_PROTOLOOP (1U << 1) /* don't throw for prototype loop */
/*
* Macro for object validity check
@@ -6164,78 +6869,58 @@ DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);
* Assert for currently guaranteed relations between flags, for instance.
*/
-#define DUK_ASSERT_HOBJECT_VALID(h) do { \
- DUK_ASSERT((h) != NULL); \
- DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE((h)) || \
- DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FUNCTION); \
- DUK_ASSERT(!DUK_HOBJECT_IS_BUFOBJ((h)) || \
- (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAYBUFFER || \
- DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DATAVIEW || \
- DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT8ARRAY || \
- DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8ARRAY || \
- DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY || \
- DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT16ARRAY || \
- DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT16ARRAY || \
- DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT32ARRAY || \
- DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT32ARRAY || \
- DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT32ARRAY || \
- DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT64ARRAY)); \
- /* Object is an Array <=> object has exotic array behavior */ \
- DUK_ASSERT((DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAY && DUK_HOBJECT_HAS_EXOTIC_ARRAY((h))) || \
- (DUK_HOBJECT_GET_CLASS_NUMBER((h)) != DUK_HOBJECT_CLASS_ARRAY && !DUK_HOBJECT_HAS_EXOTIC_ARRAY((h)))); \
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_hobject_assert_valid(duk_hobject *h);
+#define DUK_HOBJECT_ASSERT_VALID(h) \
+ do { \
+ duk_hobject_assert_valid((h)); \
} while (0)
+#else
+#define DUK_HOBJECT_ASSERT_VALID(h) \
+ do { \
+ } while (0)
+#endif
/*
* Macros to access the 'props' allocation.
*/
#if defined(DUK_USE_HEAPPTR16)
-#define DUK_HOBJECT_GET_PROPS(heap,h) \
- ((duk_uint8_t *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (h))->h_extra16))
-#define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
+#define DUK_HOBJECT_GET_PROPS(heap, h) ((duk_uint8_t *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (h))->h_extra16))
+#define DUK_HOBJECT_SET_PROPS(heap, h, x) \
+ do { \
((duk_heaphdr *) (h))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
} while (0)
#else
-#define DUK_HOBJECT_GET_PROPS(heap,h) \
- ((h)->props)
-#define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
+#define DUK_HOBJECT_GET_PROPS(heap, h) ((h)->props)
+#define DUK_HOBJECT_SET_PROPS(heap, h, x) \
+ do { \
(h)->props = (duk_uint8_t *) (x); \
} while (0)
#endif
#if defined(DUK_USE_HOBJECT_LAYOUT_1)
/* LAYOUT 1 */
-#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
- ((duk_hstring **) (void *) ( \
- DUK_HOBJECT_GET_PROPS((heap), (h)) \
- ))
-#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
- ((duk_propvalue *) (void *) ( \
- DUK_HOBJECT_GET_PROPS((heap), (h)) + \
- DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_hstring *) \
- ))
-#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
- ((duk_uint8_t *) (void *) ( \
- DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
- ))
-#define DUK_HOBJECT_A_GET_BASE(heap,h) \
- ((duk_tval *) (void *) ( \
- DUK_HOBJECT_GET_PROPS((heap), (h)) + \
- DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) \
- ))
-#define DUK_HOBJECT_H_GET_BASE(heap,h) \
- ((duk_uint32_t *) (void *) ( \
- DUK_HOBJECT_GET_PROPS((heap), (h)) + \
- DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
- DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
- ))
-#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
- ( \
- (n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
- (n_arr) * sizeof(duk_tval) + \
- (n_hash) * sizeof(duk_uint32_t) \
- )
-#define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash) do { \
+#define DUK_HOBJECT_E_GET_KEY_BASE(heap, h) ((duk_hstring **) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h))))
+#define DUK_HOBJECT_E_GET_VALUE_BASE(heap, h) \
+ ((duk_propvalue *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_hstring *)))
+#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap, h) \
+ ((duk_uint8_t *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + \
+ DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue))))
+#define DUK_HOBJECT_A_GET_BASE(heap, h) \
+ ((duk_tval *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + \
+ DUK_HOBJECT_GET_ESIZE((h)) * \
+ (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t))))
+#define DUK_HOBJECT_H_GET_BASE(heap, h) \
+ ((duk_uint32_t *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + \
+ DUK_HOBJECT_GET_ESIZE((h)) * \
+ (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
+ DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval)))
+#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent, n_arr, n_hash) \
+ ((n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + (n_arr) * sizeof(duk_tval) + \
+ (n_hash) * sizeof(duk_uint32_t))
+#define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base, set_e_k, set_e_pv, set_e_f, set_a, set_h, n_ent, n_arr, n_hash) \
+ do { \
(set_e_k) = (duk_hstring **) (void *) (p_base); \
(set_e_pv) = (duk_propvalue *) (void *) ((set_e_k) + (n_ent)); \
(set_e_f) = (duk_uint8_t *) (void *) ((set_e_pv) + (n_ent)); \
@@ -6253,85 +6938,57 @@ DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);
#else
#error invalid DUK_USE_ALIGN_BY
#endif
-#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
- ((duk_hstring **) (void *) ( \
- DUK_HOBJECT_GET_PROPS((heap), (h)) + \
- DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
- ))
-#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
- ((duk_propvalue *) (void *) ( \
- DUK_HOBJECT_GET_PROPS((heap), (h)) \
- ))
-#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
- ((duk_uint8_t *) (void *) ( \
- DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
- ))
-#define DUK_HOBJECT_A_GET_BASE(heap,h) \
- ((duk_tval *) (void *) ( \
- DUK_HOBJECT_GET_PROPS((heap), (h)) + \
- DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
- DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) \
- ))
-#define DUK_HOBJECT_H_GET_BASE(heap,h) \
- ((duk_uint32_t *) (void *) ( \
- DUK_HOBJECT_GET_PROPS((heap), (h)) + \
- DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
- DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) + \
- DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
- ))
-#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
- ( \
- (n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
- DUK_HOBJECT_E_FLAG_PADDING((n_ent)) + \
- (n_arr) * sizeof(duk_tval) + \
- (n_hash) * sizeof(duk_uint32_t) \
- )
-#define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash) do { \
+#define DUK_HOBJECT_E_GET_KEY_BASE(heap, h) \
+ ((duk_hstring **) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue)))
+#define DUK_HOBJECT_E_GET_VALUE_BASE(heap, h) ((duk_propvalue *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h))))
+#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap, h) \
+ ((duk_uint8_t *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + \
+ DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue))))
+#define DUK_HOBJECT_A_GET_BASE(heap, h) \
+ ((duk_tval *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + \
+ DUK_HOBJECT_GET_ESIZE((h)) * \
+ (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
+ DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h)))))
+#define DUK_HOBJECT_H_GET_BASE(heap, h) \
+ ((duk_uint32_t *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + \
+ DUK_HOBJECT_GET_ESIZE((h)) * \
+ (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
+ DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) + \
+ DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval)))
+#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent, n_arr, n_hash) \
+ ((n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + DUK_HOBJECT_E_FLAG_PADDING((n_ent)) + \
+ (n_arr) * sizeof(duk_tval) + (n_hash) * sizeof(duk_uint32_t))
+#define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base, set_e_k, set_e_pv, set_e_f, set_a, set_h, n_ent, n_arr, n_hash) \
+ do { \
(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
(set_e_k) = (duk_hstring **) (void *) ((set_e_pv) + (n_ent)); \
(set_e_f) = (duk_uint8_t *) (void *) ((set_e_k) + (n_ent)); \
- (set_a) = (duk_tval *) (void *) (((duk_uint8_t *) (set_e_f)) + \
- sizeof(duk_uint8_t) * (n_ent) + \
+ (set_a) = (duk_tval *) (void *) (((duk_uint8_t *) (set_e_f)) + sizeof(duk_uint8_t) * (n_ent) + \
DUK_HOBJECT_E_FLAG_PADDING((n_ent))); \
(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
} while (0)
#elif defined(DUK_USE_HOBJECT_LAYOUT_3)
/* LAYOUT 3 */
-#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
- ((duk_hstring **) (void *) ( \
- DUK_HOBJECT_GET_PROPS((heap), (h)) + \
- DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) + \
- DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
- ))
-#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
- ((duk_propvalue *) (void *) ( \
- DUK_HOBJECT_GET_PROPS((heap), (h)) \
- ))
-#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
- ((duk_uint8_t *) (void *) ( \
- DUK_HOBJECT_GET_PROPS((heap), (h)) + \
- DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
- DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) + \
- DUK_HOBJECT_GET_HSIZE((h)) * sizeof(duk_uint32_t) \
- ))
-#define DUK_HOBJECT_A_GET_BASE(heap,h) \
- ((duk_tval *) (void *) ( \
- DUK_HOBJECT_GET_PROPS((heap), (h)) + \
- DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
- ))
-#define DUK_HOBJECT_H_GET_BASE(heap,h) \
- ((duk_uint32_t *) (void *) ( \
- DUK_HOBJECT_GET_PROPS((heap), (h)) + \
- DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
- DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
- ))
-#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
- ( \
- (n_ent) * (sizeof(duk_propvalue) + sizeof(duk_hstring *) + sizeof(duk_uint8_t)) + \
- (n_arr) * sizeof(duk_tval) + \
- (n_hash) * sizeof(duk_uint32_t) \
- )
-#define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash) do { \
+#define DUK_HOBJECT_E_GET_KEY_BASE(heap, h) \
+ ((duk_hstring **) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) + \
+ DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval)))
+#define DUK_HOBJECT_E_GET_VALUE_BASE(heap, h) ((duk_propvalue *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h))))
+#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap, h) \
+ ((duk_uint8_t *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + \
+ DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
+ DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) + \
+ DUK_HOBJECT_GET_HSIZE((h)) * sizeof(duk_uint32_t)))
+#define DUK_HOBJECT_A_GET_BASE(heap, h) \
+ ((duk_tval *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue)))
+#define DUK_HOBJECT_H_GET_BASE(heap, h) \
+ ((duk_uint32_t *) (void *) (DUK_HOBJECT_GET_PROPS((heap), (h)) + \
+ DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
+ DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval)))
+#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent, n_arr, n_hash) \
+ ((n_ent) * (sizeof(duk_propvalue) + sizeof(duk_hstring *) + sizeof(duk_uint8_t)) + (n_arr) * sizeof(duk_tval) + \
+ (n_hash) * sizeof(duk_uint32_t))
+#define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base, set_e_k, set_e_pv, set_e_f, set_a, set_h, n_ent, n_arr, n_hash) \
+ do { \
(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
(set_a) = (duk_tval *) (void *) ((set_e_pv) + (n_ent)); \
(set_e_k) = (duk_hstring **) (void *) ((set_a) + (n_arr)); \
@@ -6340,85 +6997,99 @@ DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);
} while (0)
#else
#error invalid hobject layout defines
-#endif /* hobject property layout */
+#endif /* hobject property layout */
#define DUK_HOBJECT_P_ALLOC_SIZE(h) \
DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE((h)), DUK_HOBJECT_GET_ASIZE((h)), DUK_HOBJECT_GET_HSIZE((h)))
-#define DUK_HOBJECT_E_GET_KEY(heap,h,i) (DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
-#define DUK_HOBJECT_E_GET_KEY_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
-#define DUK_HOBJECT_E_GET_VALUE(heap,h,i) (DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
-#define DUK_HOBJECT_E_GET_VALUE_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
-#define DUK_HOBJECT_E_GET_VALUE_TVAL(heap,h,i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
-#define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
-#define DUK_HOBJECT_E_GET_VALUE_GETTER(heap,h,i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
-#define DUK_HOBJECT_E_GET_VALUE_GETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
-#define DUK_HOBJECT_E_GET_VALUE_SETTER(heap,h,i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
-#define DUK_HOBJECT_E_GET_VALUE_SETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
-#define DUK_HOBJECT_E_GET_FLAGS(heap,h,i) (DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
-#define DUK_HOBJECT_E_GET_FLAGS_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
-#define DUK_HOBJECT_A_GET_VALUE(heap,h,i) (DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
-#define DUK_HOBJECT_A_GET_VALUE_PTR(heap,h,i) (&DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
-#define DUK_HOBJECT_H_GET_INDEX(heap,h,i) (DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
-#define DUK_HOBJECT_H_GET_INDEX_PTR(heap,h,i) (&DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
-
-#define DUK_HOBJECT_E_SET_KEY(heap,h,i,k) do { \
+#define DUK_HOBJECT_E_GET_KEY(heap, h, i) (DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
+#define DUK_HOBJECT_E_GET_KEY_PTR(heap, h, i) (&DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
+#define DUK_HOBJECT_E_GET_VALUE(heap, h, i) (DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
+#define DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i) (&DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
+#define DUK_HOBJECT_E_GET_VALUE_TVAL(heap, h, i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
+#define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, h, i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
+#define DUK_HOBJECT_E_GET_VALUE_GETTER(heap, h, i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
+#define DUK_HOBJECT_E_GET_VALUE_GETTER_PTR(heap, h, i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
+#define DUK_HOBJECT_E_GET_VALUE_SETTER(heap, h, i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
+#define DUK_HOBJECT_E_GET_VALUE_SETTER_PTR(heap, h, i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
+#define DUK_HOBJECT_E_GET_FLAGS(heap, h, i) (DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
+#define DUK_HOBJECT_E_GET_FLAGS_PTR(heap, h, i) (&DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
+#define DUK_HOBJECT_A_GET_VALUE(heap, h, i) (DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
+#define DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i) (&DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
+#define DUK_HOBJECT_H_GET_INDEX(heap, h, i) (DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
+#define DUK_HOBJECT_H_GET_INDEX_PTR(heap, h, i) (&DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
+
+#define DUK_HOBJECT_E_SET_KEY(heap, h, i, k) \
+ do { \
DUK_HOBJECT_E_GET_KEY((heap), (h), (i)) = (k); \
} while (0)
-#define DUK_HOBJECT_E_SET_VALUE(heap,h,i,v) do { \
+#define DUK_HOBJECT_E_SET_VALUE(heap, h, i, v) \
+ do { \
DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)) = (v); \
} while (0)
-#define DUK_HOBJECT_E_SET_VALUE_TVAL(heap,h,i,v) do { \
+#define DUK_HOBJECT_E_SET_VALUE_TVAL(heap, h, i, v) \
+ do { \
DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v = (v); \
} while (0)
-#define DUK_HOBJECT_E_SET_VALUE_GETTER(heap,h,i,v) do { \
+#define DUK_HOBJECT_E_SET_VALUE_GETTER(heap, h, i, v) \
+ do { \
DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get = (v); \
} while (0)
-#define DUK_HOBJECT_E_SET_VALUE_SETTER(heap,h,i,v) do { \
+#define DUK_HOBJECT_E_SET_VALUE_SETTER(heap, h, i, v) \
+ do { \
DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set = (v); \
} while (0)
-#define DUK_HOBJECT_E_SET_FLAGS(heap,h,i,f) do { \
+#define DUK_HOBJECT_E_SET_FLAGS(heap, h, i, f) \
+ do { \
DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) = (duk_uint8_t) (f); \
} while (0)
-#define DUK_HOBJECT_A_SET_VALUE(heap,h,i,v) do { \
+#define DUK_HOBJECT_A_SET_VALUE(heap, h, i, v) \
+ do { \
DUK_HOBJECT_A_GET_VALUE((heap), (h), (i)) = (v); \
} while (0)
-#define DUK_HOBJECT_A_SET_VALUE_TVAL(heap,h,i,v) \
- DUK_HOBJECT_A_SET_VALUE((heap), (h), (i), (v)) /* alias for above */
-#define DUK_HOBJECT_H_SET_INDEX(heap,h,i,v) do { \
+#define DUK_HOBJECT_A_SET_VALUE_TVAL(heap, h, i, v) DUK_HOBJECT_A_SET_VALUE((heap), (h), (i), (v)) /* alias for above */
+#define DUK_HOBJECT_H_SET_INDEX(heap, h, i, v) \
+ do { \
DUK_HOBJECT_H_GET_INDEX((heap), (h), (i)) = (v); \
} while (0)
-#define DUK_HOBJECT_E_SET_FLAG_BITS(heap,h,i,mask) do { \
+#define DUK_HOBJECT_E_SET_FLAG_BITS(heap, h, i, mask) \
+ do { \
DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] |= (mask); \
} while (0)
-#define DUK_HOBJECT_E_CLEAR_FLAG_BITS(heap,h,i,mask) do { \
+#define DUK_HOBJECT_E_CLEAR_FLAG_BITS(heap, h, i, mask) \
+ do { \
DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] &= ~(mask); \
} while (0)
-#define DUK_HOBJECT_E_SLOT_IS_WRITABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_WRITABLE) != 0)
-#define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
-#define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
-#define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
+#define DUK_HOBJECT_E_SLOT_IS_WRITABLE(heap, h, i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_WRITABLE) != 0)
+#define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap, h, i) \
+ ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
+#define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap, h, i) \
+ ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
+#define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
-#define DUK_HOBJECT_E_SLOT_SET_WRITABLE(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
-#define DUK_HOBJECT_E_SLOT_SET_ENUMERABLE(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
-#define DUK_HOBJECT_E_SLOT_SET_CONFIGURABLE(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
-#define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
+#define DUK_HOBJECT_E_SLOT_SET_WRITABLE(heap, h, i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i), DUK_PROPDESC_FLAG_WRITABLE)
+#define DUK_HOBJECT_E_SLOT_SET_ENUMERABLE(heap, h, i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i), DUK_PROPDESC_FLAG_ENUMERABLE)
+#define DUK_HOBJECT_E_SLOT_SET_CONFIGURABLE(heap, h, i) \
+ DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i), DUK_PROPDESC_FLAG_CONFIGURABLE)
+#define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap, h, i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i), DUK_PROPDESC_FLAG_ACCESSOR)
-#define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
-#define DUK_HOBJECT_E_SLOT_CLEAR_ENUMERABLE(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
-#define DUK_HOBJECT_E_SLOT_CLEAR_CONFIGURABLE(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
-#define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
+#define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap, h, i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i), DUK_PROPDESC_FLAG_WRITABLE)
+#define DUK_HOBJECT_E_SLOT_CLEAR_ENUMERABLE(heap, h, i) \
+ DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i), DUK_PROPDESC_FLAG_ENUMERABLE)
+#define DUK_HOBJECT_E_SLOT_CLEAR_CONFIGURABLE(heap, h, i) \
+ DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i), DUK_PROPDESC_FLAG_CONFIGURABLE)
+#define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap, h, i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i), DUK_PROPDESC_FLAG_ACCESSOR)
-#define DUK_PROPDESC_IS_WRITABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_WRITABLE) != 0)
-#define DUK_PROPDESC_IS_ENUMERABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
-#define DUK_PROPDESC_IS_CONFIGURABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
-#define DUK_PROPDESC_IS_ACCESSOR(p) (((p)->flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
+#define DUK_PROPDESC_IS_WRITABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_WRITABLE) != 0)
+#define DUK_PROPDESC_IS_ENUMERABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
+#define DUK_PROPDESC_IS_CONFIGURABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
+#define DUK_PROPDESC_IS_ACCESSOR(p) (((p)->flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
-#define DUK_HOBJECT_HASHIDX_UNUSED 0xffffffffUL
-#define DUK_HOBJECT_HASHIDX_DELETED 0xfffffffeUL
+#define DUK_HOBJECT_HASHIDX_UNUSED 0xffffffffUL
+#define DUK_HOBJECT_HASHIDX_DELETED 0xfffffffeUL
/*
* Macros for accessing size fields
@@ -6426,33 +7097,63 @@ DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);
#if defined(DUK_USE_OBJSIZES16)
#define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size16)
-#define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size16 = (v); } while (0)
+#define DUK_HOBJECT_SET_ESIZE(h, v) \
+ do { \
+ (h)->e_size16 = (v); \
+ } while (0)
#define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next16)
-#define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next16 = (v); } while (0)
+#define DUK_HOBJECT_SET_ENEXT(h, v) \
+ do { \
+ (h)->e_next16 = (v); \
+ } while (0)
#define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next16++)
-#define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size16)
-#define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size16 = (v); } while (0)
+#define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size16)
+#define DUK_HOBJECT_SET_ASIZE(h, v) \
+ do { \
+ (h)->a_size16 = (v); \
+ } while (0)
#if defined(DUK_USE_HOBJECT_HASH_PART)
#define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size16)
-#define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size16 = (v); } while (0)
+#define DUK_HOBJECT_SET_HSIZE(h, v) \
+ do { \
+ (h)->h_size16 = (v); \
+ } while (0)
#else
#define DUK_HOBJECT_GET_HSIZE(h) 0
-#define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
+#define DUK_HOBJECT_SET_HSIZE(h, v) \
+ do { \
+ DUK_ASSERT((v) == 0); \
+ } while (0)
#endif
#else
#define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size)
-#define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size = (v); } while (0)
+#define DUK_HOBJECT_SET_ESIZE(h, v) \
+ do { \
+ (h)->e_size = (v); \
+ } while (0)
#define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next)
-#define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next = (v); } while (0)
+#define DUK_HOBJECT_SET_ENEXT(h, v) \
+ do { \
+ (h)->e_next = (v); \
+ } while (0)
#define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next++)
-#define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size)
-#define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size = (v); } while (0)
+#define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size)
+#define DUK_HOBJECT_SET_ASIZE(h, v) \
+ do { \
+ (h)->a_size = (v); \
+ } while (0)
#if defined(DUK_USE_HOBJECT_HASH_PART)
#define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size)
-#define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size = (v); } while (0)
+#define DUK_HOBJECT_SET_HSIZE(h, v) \
+ do { \
+ (h)->h_size = (v); \
+ } while (0)
#else
#define DUK_HOBJECT_GET_HSIZE(h) 0
-#define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
+#define DUK_HOBJECT_SET_HSIZE(h, v) \
+ do { \
+ DUK_ASSERT((v) == 0); \
+ } while (0)
#endif
#endif
@@ -6463,46 +7164,44 @@ DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);
/* Maximum prototype traversal depth. Sanity limit which handles e.g.
* prototype loops (even complex ones like 1->2->3->4->2->3->4->2->3->4).
*/
-#define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY 10000L
+#define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY 10000L
/*
- * Ecmascript [[Class]]
+ * ECMAScript [[Class]]
*/
/* range check not necessary because all 4-bit values are mapped */
-#define DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(n) duk_class_number_to_stridx[(n)]
+#define DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(n) duk_class_number_to_stridx[(n)]
-#define DUK_HOBJECT_GET_CLASS_STRING(heap,h) \
- DUK_HEAP_GET_STRING( \
- (heap), \
- DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(DUK_HOBJECT_GET_CLASS_NUMBER((h))) \
- )
+#define DUK_HOBJECT_GET_CLASS_STRING(heap, h) \
+ DUK_HEAP_GET_STRING((heap), DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(DUK_HOBJECT_GET_CLASS_NUMBER((h))))
/*
* Macros for property handling
*/
#if defined(DUK_USE_HEAPPTR16)
-#define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
- ((duk_hobject *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->prototype16))
-#define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
+#define DUK_HOBJECT_GET_PROTOTYPE(heap, h) ((duk_hobject *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->prototype16))
+#define DUK_HOBJECT_SET_PROTOTYPE(heap, h, x) \
+ do { \
(h)->prototype16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
} while (0)
#else
-#define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
- ((h)->prototype)
-#define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
+#define DUK_HOBJECT_GET_PROTOTYPE(heap, h) ((h)->prototype)
+#define DUK_HOBJECT_SET_PROTOTYPE(heap, h, x) \
+ do { \
(h)->prototype = (x); \
} while (0)
#endif
/* Set prototype, DECREF earlier value, INCREF new value (tolerating NULLs). */
-#define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr,h,p) duk_hobject_set_prototype_updref((thr), (h), (p))
+#define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, p) duk_hobject_set_prototype_updref((thr), (h), (p))
/* Set initial prototype, assume NULL previous prototype, INCREF new value,
* tolerate NULL.
*/
-#define DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr,h,proto) do { \
+#define DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, h, proto) \
+ do { \
duk_hthread *duk__thr = (thr); \
duk_hobject *duk__obj = (h); \
duk_hobject *duk__proto = (proto); \
@@ -6517,9 +7216,9 @@ DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);
*/
#if defined(DUK_USE_HEAPPTR16)
-#define DUK_HOBJECT_HAS_FINALIZER_FAST(heap,h) duk_hobject_has_finalizer_fast_raw((heap), (h))
+#define DUK_HOBJECT_HAS_FINALIZER_FAST(heap, h) duk_hobject_has_finalizer_fast_raw((heap), (h))
#else
-#define DUK_HOBJECT_HAS_FINALIZER_FAST(heap,h) duk_hobject_has_finalizer_fast_raw((h))
+#define DUK_HOBJECT_HAS_FINALIZER_FAST(heap, h) duk_hobject_has_finalizer_fast_raw((h))
#endif
/*
@@ -6533,18 +7232,18 @@ DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);
* so anything above 0x80000000 will cause trouble now.
*/
#if defined(DUK_USE_OBJSIZES16)
-#define DUK_HOBJECT_MAX_PROPERTIES 0x0000ffffUL
+#define DUK_HOBJECT_MAX_PROPERTIES 0x0000ffffUL
#else
-#define DUK_HOBJECT_MAX_PROPERTIES 0x3fffffffUL /* 2**30-1 ~= 1G properties */
+#define DUK_HOBJECT_MAX_PROPERTIES 0x3fffffffUL /* 2**30-1 ~= 1G properties */
#endif
/* internal align target for props allocation, must be 2*n for some n */
#if (DUK_USE_ALIGN_BY == 4)
-#define DUK_HOBJECT_ALIGN_TARGET 4
+#define DUK_HOBJECT_ALIGN_TARGET 4
#elif (DUK_USE_ALIGN_BY == 8)
-#define DUK_HOBJECT_ALIGN_TARGET 8
+#define DUK_HOBJECT_ALIGN_TARGET 8
#elif (DUK_USE_ALIGN_BY == 1)
-#define DUK_HOBJECT_ALIGN_TARGET 1
+#define DUK_HOBJECT_ALIGN_TARGET 1
#else
#error invalid DUK_USE_ALIGN_BY
#endif
@@ -6553,10 +7252,10 @@ DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);
* PC-to-line constants
*/
-#define DUK_PC2LINE_SKIP 64
+#define DUK_PC2LINE_SKIP 64
/* maximum length for a SKIP-1 diffstream: 35 bits per entry, rounded up to bytes */
-#define DUK_PC2LINE_MAX_DIFF_LENGTH (((DUK_PC2LINE_SKIP - 1) * 35 + 7) / 8)
+#define DUK_PC2LINE_MAX_DIFF_LENGTH (((DUK_PC2LINE_SKIP - 1) * 35 + 7) / 8)
/*
* Struct defs
@@ -6583,9 +7282,9 @@ struct duk_propdesc {
duk_hobject *set;
/* for updating (all are set to < 0 for virtual properties) */
- duk_int_t e_idx; /* prop index in 'entry part', < 0 if not there */
- duk_int_t h_idx; /* prop index in 'hash part', < 0 if not there */
- duk_int_t a_idx; /* prop index in 'array part', < 0 if not there */
+ duk_int_t e_idx; /* prop index in 'entry part', < 0 if not there */
+ duk_int_t h_idx; /* prop index in 'hash part', < 0 if not there */
+ duk_int_t a_idx; /* prop index in 'array part', < 0 if not there */
};
struct duk_hobject {
@@ -6680,11 +7379,11 @@ struct duk_hobject {
duk_uint16_t h_size16;
#endif
#else
- duk_uint32_t e_size; /* entry part size */
- duk_uint32_t e_next; /* index for next new key ([0,e_next[ are gc reachable) */
- duk_uint32_t a_size; /* array part size (entirely gc reachable) */
+ duk_uint32_t e_size; /* entry part size */
+ duk_uint32_t e_next; /* index for next new key ([0,e_next[ are gc reachable) */
+ duk_uint32_t a_size; /* array part size (entirely gc reachable) */
#if defined(DUK_USE_HOBJECT_HASH_PART)
- duk_uint32_t h_size; /* hash part size or 0 if unused */
+ duk_uint32_t h_size; /* hash part size or 0 if unused */
#endif
#endif
};
@@ -6695,7 +7394,7 @@ struct duk_hobject {
#if !defined(DUK_SINGLE_FILE)
DUK_INTERNAL_DECL duk_uint8_t duk_class_number_to_stridx[32];
-#endif /* !DUK_SINGLE_FILE */
+#endif /* !DUK_SINGLE_FILE */
/*
* Prototypes
@@ -6724,41 +7423,46 @@ DUK_INTERNAL_DECL void duk_hobject_realloc_props(duk_hthread *thr,
duk_uint32_t new_a_size,
duk_uint32_t new_h_size,
duk_bool_t abandon_array);
-DUK_INTERNAL_DECL void duk_hobject_resize_entrypart(duk_hthread *thr,
- duk_hobject *obj,
- duk_uint32_t new_e_size);
-#if 0 /*unused*/
+DUK_INTERNAL_DECL void duk_hobject_resize_entrypart(duk_hthread *thr, duk_hobject *obj, duk_uint32_t new_e_size);
+#if 0 /*unused*/
DUK_INTERNAL_DECL void duk_hobject_resize_arraypart(duk_hthread *thr,
duk_hobject *obj,
duk_uint32_t new_a_size);
#endif
/* low-level property functions */
-DUK_INTERNAL_DECL duk_bool_t duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx);
-DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key);
-DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint_t *out_attrs);
-DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i);
-DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_own_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags);
-
-/* XXX: when optimizing for guaranteed property slots, use a guaranteed
- * slot for internal value; this call can then access it directly.
- */
-#define duk_hobject_get_internal_value_tval_ptr(heap,obj) \
- duk_hobject_find_existing_entry_tval_ptr((heap), (obj), DUK_HEAP_STRING_INT_VALUE((heap)))
+DUK_INTERNAL_DECL duk_bool_t
+duk_hobject_find_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx);
+DUK_INTERNAL_DECL duk_tval *duk_hobject_find_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key);
+DUK_INTERNAL_DECL duk_tval *duk_hobject_find_entry_tval_ptr_stridx(duk_heap *heap, duk_hobject *obj, duk_small_uint_t stridx);
+DUK_INTERNAL_DECL duk_tval *duk_hobject_find_entry_tval_ptr_and_attrs(duk_heap *heap,
+ duk_hobject *obj,
+ duk_hstring *key,
+ duk_uint_t *out_attrs);
+DUK_INTERNAL_DECL duk_tval *duk_hobject_find_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i);
+DUK_INTERNAL_DECL duk_bool_t
+duk_hobject_get_own_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags);
/* core property functions */
DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
-DUK_INTERNAL_DECL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag);
+DUK_INTERNAL_DECL duk_bool_t
+duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag);
DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag);
DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
/* internal property functions */
-#define DUK_DELPROP_FLAG_THROW (1U << 0)
-#define DUK_DELPROP_FLAG_FORCE (1U << 1)
+#define DUK_DELPROP_FLAG_THROW (1U << 0)
+#define DUK_DELPROP_FLAG_FORCE (1U << 1)
DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key);
-DUK_INTERNAL_DECL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
-DUK_INTERNAL_DECL void duk_hobject_define_property_internal_arridx(duk_hthread *thr, duk_hobject *obj, duk_uarridx_t arr_idx, duk_small_uint_t flags);
+DUK_INTERNAL_DECL void duk_hobject_define_property_internal(duk_hthread *thr,
+ duk_hobject *obj,
+ duk_hstring *key,
+ duk_small_uint_t flags);
+DUK_INTERNAL_DECL void duk_hobject_define_property_internal_arridx(duk_hthread *thr,
+ duk_hobject *obj,
+ duk_uarridx_t arr_idx,
+ duk_small_uint_t flags);
DUK_INTERNAL_DECL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj);
#if defined(DUK_USE_HEAPPTR16)
DUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_heap *heap, duk_hobject *obj);
@@ -6789,8 +7493,10 @@ DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthr
DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_small_uint_t required_desc_flags);
/* internal properties */
-DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv);
+DUK_INTERNAL_DECL duk_tval *duk_hobject_get_internal_value_tval_ptr(duk_heap *heap, duk_hobject *obj);
DUK_INTERNAL_DECL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj);
+DUK_INTERNAL_DECL duk_harray *duk_hobject_get_formals(duk_hthread *thr, duk_hobject *obj);
+DUK_INTERNAL_DECL duk_hobject *duk_hobject_get_varmap(duk_hthread *thr, duk_hobject *obj);
/* hobject management functions */
DUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj);
@@ -6816,7 +7522,10 @@ DUK_INTERNAL_DECL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr,
#endif
/* misc */
-DUK_INTERNAL_DECL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p, duk_bool_t ignore_loop);
+DUK_INTERNAL_DECL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr,
+ duk_hobject *h,
+ duk_hobject *p,
+ duk_bool_t ignore_loop);
#if !defined(DUK_USE_OBJECT_BUILTIN)
/* These declarations are needed when related built-in is disabled and
@@ -6826,12 +7535,12 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_hthread *thr);
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_hthread *thr);
#endif
-#endif /* DUK_HOBJECT_H_INCLUDED */
+#endif /* DUK_HOBJECT_H_INCLUDED */
/* #include duk_hcompfunc.h */
/*
- * Heap compiled function (Ecmascript function) representation.
+ * Heap compiled function (ECMAScript function) representation.
*
- * There is a single data buffer containing the Ecmascript function's
+ * There is a single data buffer containing the ECMAScript function's
* bytecode, constants, and inner functions.
*/
@@ -6845,50 +7554,55 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_hthread *thr);
/* XXX: casts could be improved, especially for GET/SET DATA */
#if defined(DUK_USE_HEAPPTR16)
-#define DUK_HCOMPFUNC_GET_DATA(heap,h) \
- ((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16))
-#define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \
+#define DUK_HCOMPFUNC_GET_DATA(heap, h) ((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16))
+#define DUK_HCOMPFUNC_SET_DATA(heap, h, v) \
+ do { \
(h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
} while (0)
-#define DUK_HCOMPFUNC_GET_FUNCS(heap,h) \
- ((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16)))
-#define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v) do { \
+#define DUK_HCOMPFUNC_GET_FUNCS(heap, h) ((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16)))
+#define DUK_HCOMPFUNC_SET_FUNCS(heap, h, v) \
+ do { \
(h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
} while (0)
-#define DUK_HCOMPFUNC_GET_BYTECODE(heap,h) \
- ((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16)))
-#define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v) do { \
+#define DUK_HCOMPFUNC_GET_BYTECODE(heap, h) ((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16)))
+#define DUK_HCOMPFUNC_SET_BYTECODE(heap, h, v) \
+ do { \
(h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
} while (0)
-#define DUK_HCOMPFUNC_GET_LEXENV(heap,h) \
- ((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->lex_env16)))
-#define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v) do { \
+#define DUK_HCOMPFUNC_GET_LEXENV(heap, h) ((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->lex_env16)))
+#define DUK_HCOMPFUNC_SET_LEXENV(heap, h, v) \
+ do { \
(h)->lex_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
} while (0)
-#define DUK_HCOMPFUNC_GET_VARENV(heap,h) \
- ((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->var_env16)))
-#define DUK_HCOMPFUNC_SET_VARENV(heap,h,v) do { \
+#define DUK_HCOMPFUNC_GET_VARENV(heap, h) ((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->var_env16)))
+#define DUK_HCOMPFUNC_SET_VARENV(heap, h, v) \
+ do { \
(h)->var_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
} while (0)
#else
-#define DUK_HCOMPFUNC_GET_DATA(heap,h) ((duk_hbuffer_fixed *) (void *) (h)->data)
-#define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \
+#define DUK_HCOMPFUNC_GET_DATA(heap, h) ((duk_hbuffer_fixed *) (void *) (h)->data)
+#define DUK_HCOMPFUNC_SET_DATA(heap, h, v) \
+ do { \
(h)->data = (duk_hbuffer *) (v); \
} while (0)
-#define DUK_HCOMPFUNC_GET_FUNCS(heap,h) ((h)->funcs)
-#define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v) do { \
+#define DUK_HCOMPFUNC_GET_FUNCS(heap, h) ((h)->funcs)
+#define DUK_HCOMPFUNC_SET_FUNCS(heap, h, v) \
+ do { \
(h)->funcs = (v); \
} while (0)
-#define DUK_HCOMPFUNC_GET_BYTECODE(heap,h) ((h)->bytecode)
-#define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v) do { \
+#define DUK_HCOMPFUNC_GET_BYTECODE(heap, h) ((h)->bytecode)
+#define DUK_HCOMPFUNC_SET_BYTECODE(heap, h, v) \
+ do { \
(h)->bytecode = (v); \
} while (0)
-#define DUK_HCOMPFUNC_GET_LEXENV(heap,h) ((h)->lex_env)
-#define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v) do { \
+#define DUK_HCOMPFUNC_GET_LEXENV(heap, h) ((h)->lex_env)
+#define DUK_HCOMPFUNC_SET_LEXENV(heap, h, v) \
+ do { \
(h)->lex_env = (v); \
} while (0)
-#define DUK_HCOMPFUNC_GET_VARENV(heap,h) ((h)->var_env)
-#define DUK_HCOMPFUNC_SET_VARENV(heap,h,v) do { \
+#define DUK_HCOMPFUNC_GET_VARENV(heap, h) ((h)->var_env)
+#define DUK_HCOMPFUNC_SET_VARENV(heap, h, v) \
+ do { \
(h)->var_env = (v); \
} while (0)
#endif
@@ -6898,72 +7612,56 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_hthread *thr);
*/
/* Note: assumes 'data' is always a fixed buffer */
-#define DUK_HCOMPFUNC_GET_BUFFER_BASE(heap,h) \
- DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h)))
+#define DUK_HCOMPFUNC_GET_BUFFER_BASE(heap, h) DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h)))
-#define DUK_HCOMPFUNC_GET_CONSTS_BASE(heap,h) \
- ((duk_tval *) (void *) DUK_HCOMPFUNC_GET_BUFFER_BASE((heap), (h)))
+#define DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, h) ((duk_tval *) (void *) DUK_HCOMPFUNC_GET_BUFFER_BASE((heap), (h)))
-#define DUK_HCOMPFUNC_GET_FUNCS_BASE(heap,h) \
- DUK_HCOMPFUNC_GET_FUNCS((heap), (h))
+#define DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, h) DUK_HCOMPFUNC_GET_FUNCS((heap), (h))
-#define DUK_HCOMPFUNC_GET_CODE_BASE(heap,h) \
- DUK_HCOMPFUNC_GET_BYTECODE((heap), (h))
+#define DUK_HCOMPFUNC_GET_CODE_BASE(heap, h) DUK_HCOMPFUNC_GET_BYTECODE((heap), (h))
-#define DUK_HCOMPFUNC_GET_CONSTS_END(heap,h) \
- ((duk_tval *) (void *) DUK_HCOMPFUNC_GET_FUNCS((heap), (h)))
+#define DUK_HCOMPFUNC_GET_CONSTS_END(heap, h) ((duk_tval *) (void *) DUK_HCOMPFUNC_GET_FUNCS((heap), (h)))
-#define DUK_HCOMPFUNC_GET_FUNCS_END(heap,h) \
- ((duk_hobject **) (void *) DUK_HCOMPFUNC_GET_BYTECODE((heap), (h)))
+#define DUK_HCOMPFUNC_GET_FUNCS_END(heap, h) ((duk_hobject **) (void *) DUK_HCOMPFUNC_GET_BYTECODE((heap), (h)))
/* XXX: double evaluation of DUK_HCOMPFUNC_GET_DATA() */
-#define DUK_HCOMPFUNC_GET_CODE_END(heap,h) \
+#define DUK_HCOMPFUNC_GET_CODE_END(heap, h) \
((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h))) + \
- DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA((heap), h))))
-
-#define DUK_HCOMPFUNC_GET_CONSTS_SIZE(heap,h) \
- ( \
- (duk_size_t) \
- ( \
- ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_END((heap), (h))) - \
- ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_BASE((heap), (h))) \
- ) \
- )
-
-#define DUK_HCOMPFUNC_GET_FUNCS_SIZE(heap,h) \
- ( \
- (duk_size_t) \
- ( \
- ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_END((heap), (h))) - \
- ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_BASE((heap), (h))) \
- ) \
- )
-
-#define DUK_HCOMPFUNC_GET_CODE_SIZE(heap,h) \
- ( \
- (duk_size_t) \
- ( \
- ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_END((heap),(h))) - \
- ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_BASE((heap),(h))) \
- ) \
- )
-
-#define DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap,h) \
- ((duk_size_t) (DUK_HCOMPFUNC_GET_CONSTS_SIZE((heap), (h)) / sizeof(duk_tval)))
-
-#define DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap,h) \
- ((duk_size_t) (DUK_HCOMPFUNC_GET_FUNCS_SIZE((heap), (h)) / sizeof(duk_hobject *)))
-
-#define DUK_HCOMPFUNC_GET_CODE_COUNT(heap,h) \
- ((duk_size_t) (DUK_HCOMPFUNC_GET_CODE_SIZE((heap), (h)) / sizeof(duk_instr_t)))
+ DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA((heap), h))))
+
+#define DUK_HCOMPFUNC_GET_CONSTS_SIZE(heap, h) \
+ ((duk_size_t) (((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_END((heap), (h))) - \
+ ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_BASE((heap), (h)))))
+
+#define DUK_HCOMPFUNC_GET_FUNCS_SIZE(heap, h) \
+ ((duk_size_t) (((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_END((heap), (h))) - \
+ ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_BASE((heap), (h)))))
+
+#define DUK_HCOMPFUNC_GET_CODE_SIZE(heap, h) \
+ ((duk_size_t) (((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_END((heap), (h))) - \
+ ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_BASE((heap), (h)))))
+
+#define DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap, h) ((duk_size_t) (DUK_HCOMPFUNC_GET_CONSTS_SIZE((heap), (h)) / sizeof(duk_tval)))
+
+#define DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap, h) ((duk_size_t) (DUK_HCOMPFUNC_GET_FUNCS_SIZE((heap), (h)) / sizeof(duk_hobject *)))
+
+#define DUK_HCOMPFUNC_GET_CODE_COUNT(heap, h) ((duk_size_t) (DUK_HCOMPFUNC_GET_CODE_SIZE((heap), (h)) / sizeof(duk_instr_t)))
/*
* Validity assert
*/
-#define DUK_ASSERT_HCOMPFUNC_VALID(h) do { \
- DUK_ASSERT((h) != NULL); \
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_hcompfunc_assert_valid(duk_hcompfunc *h);
+#define DUK_HCOMPFUNC_ASSERT_VALID(h) \
+ do { \
+ duk_hcompfunc_assert_valid((h)); \
} while (0)
+#else
+#define DUK_HCOMPFUNC_ASSERT_VALID(h) \
+ do { \
+ } while (0)
+#endif
/*
* Main struct
@@ -7049,8 +7747,8 @@ struct duk_hcompfunc {
* at run time, except for debugging, so it is not maintained.
*/
- duk_uint16_t nregs; /* regs to allocate */
- duk_uint16_t nargs; /* number of arguments allocated to regs */
+ duk_uint16_t nregs; /* regs to allocate */
+ duk_uint16_t nargs; /* number of arguments allocated to regs */
/*
* Additional control information is placed into the object itself
@@ -7097,7 +7795,7 @@ struct duk_hcompfunc {
#endif
};
-#endif /* DUK_HCOMPFUNC_H_INCLUDED */
+#endif /* DUK_HCOMPFUNC_H_INCLUDED */
/* #include duk_hnatfunc.h */
/*
* Heap native function representation.
@@ -7106,8 +7804,20 @@ struct duk_hcompfunc {
#if !defined(DUK_HNATFUNC_H_INCLUDED)
#define DUK_HNATFUNC_H_INCLUDED
-#define DUK_HNATFUNC_NARGS_VARARGS ((duk_int16_t) -1)
-#define DUK_HNATFUNC_NARGS_MAX ((duk_int16_t) 0x7fff)
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_hnatfunc_assert_valid(duk_hnatfunc *h);
+#define DUK_HNATFUNC_ASSERT_VALID(h) \
+ do { \
+ duk_hnatfunc_assert_valid((h)); \
+ } while (0)
+#else
+#define DUK_HNATFUNC_ASSERT_VALID(h) \
+ do { \
+ } while (0)
+#endif
+
+#define DUK_HNATFUNC_NARGS_VARARGS ((duk_int16_t) -1)
+#define DUK_HNATFUNC_NARGS_MAX ((duk_int16_t) 0x7fff)
struct duk_hnatfunc {
/* shared object part */
@@ -7130,7 +7840,7 @@ struct duk_hnatfunc {
*/
};
-#endif /* DUK_HNATFUNC_H_INCLUDED */
+#endif /* DUK_HNATFUNC_H_INCLUDED */
/* #include duk_hboundfunc.h */
/*
* Bound function representation.
@@ -7144,15 +7854,17 @@ struct duk_hnatfunc {
*/
#define DUK_HBOUNDFUNC_MAX_ARGS 0x20000000UL
-#define DUK_ASSERT_HBOUNDFUNC_VALID(h) do { \
- DUK_ASSERT((h) != NULL); \
- DUK_ASSERT(DUK_HOBJECT_IS_BOUNDFUNC((duk_hobject *) (h))); \
- DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&(h)->target) || \
- (DUK_TVAL_IS_OBJECT(&(h)->target) && \
- DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(&(h)->target)))); \
- DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&(h)->this_binding)); \
- DUK_ASSERT((h)->nargs == 0 || (h)->args != NULL); \
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_hboundfunc_assert_valid(duk_hboundfunc *h);
+#define DUK_HBOUNDFUNC_ASSERT_VALID(h) \
+ do { \
+ duk_hboundfunc_assert_valid((h)); \
+ } while (0)
+#else
+#define DUK_HBOUNDFUNC_ASSERT_VALID(h) \
+ do { \
} while (0)
+#endif
struct duk_hboundfunc {
/* Shared object part. */
@@ -7167,11 +7879,11 @@ struct duk_hboundfunc {
duk_tval this_binding;
/* Arguments to prepend. */
- duk_tval *args; /* Separate allocation. */
+ duk_tval *args; /* Separate allocation. */
duk_idx_t nargs;
};
-#endif /* DUK_HBOUNDFUNC_H_INCLUDED */
+#endif /* DUK_HBOUNDFUNC_H_INCLUDED */
/* #include duk_hbufobj.h */
/*
* Heap Buffer object representation. Used for all Buffer variants.
@@ -7183,50 +7895,37 @@ struct duk_hboundfunc {
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
/* All element accessors are host endian now (driven by TypedArray spec). */
-#define DUK_HBUFOBJ_ELEM_UINT8 0
-#define DUK_HBUFOBJ_ELEM_UINT8CLAMPED 1
-#define DUK_HBUFOBJ_ELEM_INT8 2
-#define DUK_HBUFOBJ_ELEM_UINT16 3
-#define DUK_HBUFOBJ_ELEM_INT16 4
-#define DUK_HBUFOBJ_ELEM_UINT32 5
-#define DUK_HBUFOBJ_ELEM_INT32 6
-#define DUK_HBUFOBJ_ELEM_FLOAT32 7
-#define DUK_HBUFOBJ_ELEM_FLOAT64 8
-#define DUK_HBUFOBJ_ELEM_MAX 8
-
-#define DUK_ASSERT_HBUFOBJ_VALID(h) do { \
- DUK_ASSERT((h) != NULL); \
- DUK_ASSERT((h)->shift <= 3); \
- DUK_ASSERT((h)->elem_type <= DUK_HBUFOBJ_ELEM_MAX); \
- DUK_ASSERT(((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT8) || \
- ((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT8CLAMPED) || \
- ((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT8) || \
- ((h)->shift == 1 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT16) || \
- ((h)->shift == 1 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT16) || \
- ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT32) || \
- ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT32) || \
- ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_FLOAT32) || \
- ((h)->shift == 3 && (h)->elem_type == DUK_HBUFOBJ_ELEM_FLOAT64)); \
- DUK_ASSERT((h)->is_typedarray == 0 || (h)->is_typedarray == 1); \
- DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) (h))); \
- if ((h)->buf == NULL) { \
- DUK_ASSERT((h)->offset == 0); \
- DUK_ASSERT((h)->length == 0); \
- } else { \
- /* No assertions for offset or length; in particular, \
- * it's OK for length to be longer than underlying \
- * buffer. Just ensure they don't wrap when added. \
- */ \
- DUK_ASSERT((h)->offset + (h)->length >= (h)->offset); \
- } \
+#define DUK_HBUFOBJ_ELEM_UINT8 0
+#define DUK_HBUFOBJ_ELEM_UINT8CLAMPED 1
+#define DUK_HBUFOBJ_ELEM_INT8 2
+#define DUK_HBUFOBJ_ELEM_UINT16 3
+#define DUK_HBUFOBJ_ELEM_INT16 4
+#define DUK_HBUFOBJ_ELEM_UINT32 5
+#define DUK_HBUFOBJ_ELEM_INT32 6
+#define DUK_HBUFOBJ_ELEM_FLOAT32 7
+#define DUK_HBUFOBJ_ELEM_FLOAT64 8
+#define DUK_HBUFOBJ_ELEM_MAX 8
+
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_hbufobj_assert_valid(duk_hbufobj *h);
+#define DUK_HBUFOBJ_ASSERT_VALID(h) \
+ do { \
+ duk_hbufobj_assert_valid((h)); \
+ } while (0)
+#else
+#define DUK_HBUFOBJ_ASSERT_VALID(h) \
+ do { \
} while (0)
+#endif
/* Get the current data pointer (caller must ensure buf != NULL) as a
- * duk_uint8_t ptr.
+ * duk_uint8_t ptr. Note that the result may be NULL if the underlying
+ * buffer has zero size and is not a fixed buffer.
*/
-#define DUK_HBUFOBJ_GET_SLICE_BASE(heap,h) \
- (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
- (((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + (h)->offset))
+#define DUK_HBUFOBJ_GET_SLICE_BASE(heap, h) \
+ (DUK_ASSERT_EXPR((h) != NULL), \
+ DUK_ASSERT_EXPR((h)->buf != NULL), \
+ (((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + (h)->offset))
/* True if slice is full, i.e. offset is zero and length covers the entire
* buffer. This status may change independently of the duk_hbufobj if
@@ -7234,15 +7933,17 @@ struct duk_hboundfunc {
* being changed.
*/
#define DUK_HBUFOBJ_FULL_SLICE(h) \
- (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
- ((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf)))
+ (DUK_ASSERT_EXPR((h) != NULL), \
+ DUK_ASSERT_EXPR((h)->buf != NULL), \
+ ((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf)))
/* Validate that the whole slice [0,length[ is contained in the underlying
* buffer. Caller must ensure 'buf' != NULL.
*/
#define DUK_HBUFOBJ_VALID_SLICE(h) \
- (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
- ((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf)))
+ (DUK_ASSERT_EXPR((h) != NULL), \
+ DUK_ASSERT_EXPR((h)->buf != NULL), \
+ ((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf)))
/* Validate byte read/write for virtual 'offset', i.e. check that the
* offset, taking into account h->offset, is within the underlying
@@ -7251,13 +7952,11 @@ struct duk_hboundfunc {
* behavior (e.g. if an underlying dynamic buffer changes after being
* setup). Caller must ensure 'buf' != NULL.
*/
-#define DUK_HBUFOBJ_VALID_BYTEOFFSET_INCL(h,off) \
- (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
- ((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf)))
+#define DUK_HBUFOBJ_VALID_BYTEOFFSET_INCL(h, off) \
+ (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), ((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf)))
-#define DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h,off) \
- (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
- ((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf)))
+#define DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h, off) \
+ (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), ((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf)))
/* Clamp an input byte length (already assumed to be within the nominal
* duk_hbufobj 'length') to the current dynamic buffer limits to yield
@@ -7265,12 +7964,10 @@ struct duk_hboundfunc {
* be invalidated by any side effect because it may trigger a user
* callback that resizes the underlying buffer.
*/
-#define DUK_HBUFOBJ_CLAMP_BYTELENGTH(h,len) \
- (DUK_ASSERT_EXPR((h) != NULL), \
- duk_hbufobj_clamp_bytelength((h), (len)))
+#define DUK_HBUFOBJ_CLAMP_BYTELENGTH(h, len) (DUK_ASSERT_EXPR((h) != NULL), duk_hbufobj_clamp_bytelength((h), (len)))
/* Typed arrays have virtual indices, ArrayBuffer and DataView do not. */
-#define DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h) ((h)->is_typedarray)
+#define DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h) ((h)->is_typedarray)
struct duk_hbufobj {
/* Shared object part. */
@@ -7295,26 +7992,36 @@ struct duk_hbufobj {
* be dynamic and its pointer unstable.
*/
- duk_uint_t offset; /* byte offset to buf */
- duk_uint_t length; /* byte index limit for element access, exclusive */
- duk_uint8_t shift; /* element size shift:
- * 0 = u8/i8
- * 1 = u16/i16
- * 2 = u32/i32/float
- * 3 = double
- */
- duk_uint8_t elem_type; /* element type */
+ duk_uint_t offset; /* byte offset to buf */
+ duk_uint_t length; /* byte index limit for element access, exclusive */
+ duk_uint8_t shift; /* element size shift:
+ * 0 = u8/i8
+ * 1 = u16/i16
+ * 2 = u32/i32/float
+ * 3 = double
+ */
+ duk_uint8_t elem_type; /* element type */
duk_uint8_t is_typedarray;
};
DUK_INTERNAL_DECL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len);
DUK_INTERNAL_DECL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf);
-DUK_INTERNAL_DECL void duk_hbufobj_push_validated_read(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size);
-DUK_INTERNAL_DECL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size);
+DUK_INTERNAL_DECL void duk_hbufobj_push_validated_read(duk_hthread *thr,
+ duk_hbufobj *h_bufobj,
+ duk_uint8_t *p,
+ duk_small_uint_t elem_size);
+DUK_INTERNAL_DECL void duk_hbufobj_validated_write(duk_hthread *thr,
+ duk_hbufobj *h_bufobj,
+ duk_uint8_t *p,
+ duk_small_uint_t elem_size);
DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx);
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
-#endif /* DUK_HBUFOBJ_H_INCLUDED */
+#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
+
+/* nothing */
+
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_HBUFOBJ_H_INCLUDED */
/* #include duk_hthread.h */
/*
* Heap thread object representation.
@@ -7332,38 +8039,38 @@ DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx
*/
/* Initial valstack size, roughly 0.7kiB. */
-#define DUK_VALSTACK_INITIAL_SIZE 96U
+#define DUK_VALSTACK_INITIAL_SIZE 96U
/* Internal extra elements assumed on function entry, always added to
* user-defined 'extra' for e.g. the duk_check_stack() call.
*/
-#define DUK_VALSTACK_INTERNAL_EXTRA 32U
+#define DUK_VALSTACK_INTERNAL_EXTRA 32U
/* Number of elements guaranteed to be user accessible (in addition to call
* arguments) on Duktape/C function entry. This is the major public API
* commitment.
*/
-#define DUK_VALSTACK_API_ENTRY_MINIMUM DUK_API_ENTRY_STACK
+#define DUK_VALSTACK_API_ENTRY_MINIMUM DUK_API_ENTRY_STACK
/*
* Activation defines
*/
-#define DUK_ACT_FLAG_STRICT (1U << 0) /* function executes in strict mode */
-#define DUK_ACT_FLAG_TAILCALLED (1U << 1) /* activation has tail called one or more times */
-#define DUK_ACT_FLAG_CONSTRUCT (1U << 2) /* function executes as a constructor (called via "new") */
-#define DUK_ACT_FLAG_PREVENT_YIELD (1U << 3) /* activation prevents yield (native call or "new") */
-#define DUK_ACT_FLAG_DIRECT_EVAL (1U << 4) /* activation is a direct eval call */
-#define DUK_ACT_FLAG_CONSTRUCT_PROXY (1U << 5) /* activation is for Proxy 'construct' call, special return value handling */
-#define DUK_ACT_FLAG_BREAKPOINT_ACTIVE (1U << 6) /* activation has active breakpoint(s) */
+#define DUK_ACT_FLAG_STRICT (1U << 0) /* function executes in strict mode */
+#define DUK_ACT_FLAG_TAILCALLED (1U << 1) /* activation has tail called one or more times */
+#define DUK_ACT_FLAG_CONSTRUCT (1U << 2) /* function executes as a constructor (called via "new") */
+#define DUK_ACT_FLAG_PREVENT_YIELD (1U << 3) /* activation prevents yield (native call or "new") */
+#define DUK_ACT_FLAG_DIRECT_EVAL (1U << 4) /* activation is a direct eval call */
+#define DUK_ACT_FLAG_CONSTRUCT_PROXY (1U << 5) /* activation is for Proxy 'construct' call, special return value handling */
+#define DUK_ACT_FLAG_BREAKPOINT_ACTIVE (1U << 6) /* activation has active breakpoint(s) */
-#define DUK_ACT_GET_FUNC(act) ((act)->func)
+#define DUK_ACT_GET_FUNC(act) ((act)->func)
/*
* Flags for __FILE__ / __LINE__ registered into tracedata
*/
-#define DUK_TB_FLAG_NOBLAME_FILELINE (1U << 0) /* don't report __FILE__ / __LINE__ as fileName/lineNumber */
+#define DUK_TB_FLAG_NOBLAME_FILELINE (1U << 0) /* don't report __FILE__ / __LINE__ as fileName/lineNumber */
/*
* Catcher defines
@@ -7372,52 +8079,60 @@ DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx
/* XXX: remove catcher type entirely */
/* flags field: LLLLLLFT, L = label (24 bits), F = flags (4 bits), T = type (4 bits) */
-#define DUK_CAT_TYPE_MASK 0x0000000fUL
-#define DUK_CAT_TYPE_BITS 4
-#define DUK_CAT_LABEL_MASK 0xffffff00UL
-#define DUK_CAT_LABEL_BITS 24
-#define DUK_CAT_LABEL_SHIFT 8
-
-#define DUK_CAT_FLAG_CATCH_ENABLED (1U << 4) /* catch part will catch */
-#define DUK_CAT_FLAG_FINALLY_ENABLED (1U << 5) /* finally part will catch */
-#define DUK_CAT_FLAG_CATCH_BINDING_ENABLED (1U << 6) /* request to create catch binding */
-#define DUK_CAT_FLAG_LEXENV_ACTIVE (1U << 7) /* catch or with binding is currently active */
-
-#define DUK_CAT_TYPE_UNKNOWN 0
-#define DUK_CAT_TYPE_TCF 1
-#define DUK_CAT_TYPE_LABEL 2
-
-#define DUK_CAT_GET_TYPE(c) ((c)->flags & DUK_CAT_TYPE_MASK)
-#define DUK_CAT_GET_LABEL(c) (((c)->flags & DUK_CAT_LABEL_MASK) >> DUK_CAT_LABEL_SHIFT)
-
-#define DUK_CAT_HAS_CATCH_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_CATCH_ENABLED)
-#define DUK_CAT_HAS_FINALLY_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_FINALLY_ENABLED)
-#define DUK_CAT_HAS_CATCH_BINDING_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_CATCH_BINDING_ENABLED)
-#define DUK_CAT_HAS_LEXENV_ACTIVE(c) ((c)->flags & DUK_CAT_FLAG_LEXENV_ACTIVE)
-
-#define DUK_CAT_SET_CATCH_ENABLED(c) do { \
+#define DUK_CAT_TYPE_MASK 0x0000000fUL
+#define DUK_CAT_TYPE_BITS 4
+#define DUK_CAT_LABEL_MASK 0xffffff00UL
+#define DUK_CAT_LABEL_BITS 24
+#define DUK_CAT_LABEL_SHIFT 8
+
+#define DUK_CAT_FLAG_CATCH_ENABLED (1U << 4) /* catch part will catch */
+#define DUK_CAT_FLAG_FINALLY_ENABLED (1U << 5) /* finally part will catch */
+#define DUK_CAT_FLAG_CATCH_BINDING_ENABLED (1U << 6) /* request to create catch binding */
+#define DUK_CAT_FLAG_LEXENV_ACTIVE (1U << 7) /* catch or with binding is currently active */
+
+#define DUK_CAT_TYPE_UNKNOWN 0
+#define DUK_CAT_TYPE_TCF 1
+#define DUK_CAT_TYPE_LABEL 2
+
+#define DUK_CAT_GET_TYPE(c) ((c)->flags & DUK_CAT_TYPE_MASK)
+#define DUK_CAT_GET_LABEL(c) (((c)->flags & DUK_CAT_LABEL_MASK) >> DUK_CAT_LABEL_SHIFT)
+
+#define DUK_CAT_HAS_CATCH_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_CATCH_ENABLED)
+#define DUK_CAT_HAS_FINALLY_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_FINALLY_ENABLED)
+#define DUK_CAT_HAS_CATCH_BINDING_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_CATCH_BINDING_ENABLED)
+#define DUK_CAT_HAS_LEXENV_ACTIVE(c) ((c)->flags & DUK_CAT_FLAG_LEXENV_ACTIVE)
+
+#define DUK_CAT_SET_CATCH_ENABLED(c) \
+ do { \
(c)->flags |= DUK_CAT_FLAG_CATCH_ENABLED; \
} while (0)
-#define DUK_CAT_SET_FINALLY_ENABLED(c) do { \
+#define DUK_CAT_SET_FINALLY_ENABLED(c) \
+ do { \
(c)->flags |= DUK_CAT_FLAG_FINALLY_ENABLED; \
} while (0)
-#define DUK_CAT_SET_CATCH_BINDING_ENABLED(c) do { \
+#define DUK_CAT_SET_CATCH_BINDING_ENABLED(c) \
+ do { \
(c)->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
} while (0)
-#define DUK_CAT_SET_LEXENV_ACTIVE(c) do { \
+#define DUK_CAT_SET_LEXENV_ACTIVE(c) \
+ do { \
(c)->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE; \
} while (0)
-#define DUK_CAT_CLEAR_CATCH_ENABLED(c) do { \
+#define DUK_CAT_CLEAR_CATCH_ENABLED(c) \
+ do { \
(c)->flags &= ~DUK_CAT_FLAG_CATCH_ENABLED; \
} while (0)
-#define DUK_CAT_CLEAR_FINALLY_ENABLED(c) do { \
+#define DUK_CAT_CLEAR_FINALLY_ENABLED(c) \
+ do { \
(c)->flags &= ~DUK_CAT_FLAG_FINALLY_ENABLED; \
} while (0)
-#define DUK_CAT_CLEAR_CATCH_BINDING_ENABLED(c) do { \
+#define DUK_CAT_CLEAR_CATCH_BINDING_ENABLED(c) \
+ do { \
(c)->flags &= ~DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
} while (0)
-#define DUK_CAT_CLEAR_LEXENV_ACTIVE(c) do { \
+#define DUK_CAT_CLEAR_LEXENV_ACTIVE(c) \
+ do { \
(c)->flags &= ~DUK_CAT_FLAG_LEXENV_ACTIVE; \
} while (0)
@@ -7426,24 +8141,21 @@ DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx
*/
#if defined(DUK_USE_ROM_STRINGS)
-#define DUK_HTHREAD_GET_STRING(thr,idx) \
- ((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
-#else /* DUK_USE_ROM_STRINGS */
+#define DUK_HTHREAD_GET_STRING(thr, idx) ((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
+#else /* DUK_USE_ROM_STRINGS */
#if defined(DUK_USE_HEAPPTR16)
-#define DUK_HTHREAD_GET_STRING(thr,idx) \
- ((duk_hstring *) DUK_USE_HEAPPTR_DEC16((thr)->heap->heap_udata, (thr)->strs16[(idx)]))
+#define DUK_HTHREAD_GET_STRING(thr, idx) ((duk_hstring *) DUK_USE_HEAPPTR_DEC16((thr)->heap->heap_udata, (thr)->strs16[(idx)]))
#else
-#define DUK_HTHREAD_GET_STRING(thr,idx) \
- ((thr)->strs[(idx)])
+#define DUK_HTHREAD_GET_STRING(thr, idx) ((thr)->strs[(idx)])
#endif
-#endif /* DUK_USE_ROM_STRINGS */
+#endif /* DUK_USE_ROM_STRINGS */
/* values for the state field */
-#define DUK_HTHREAD_STATE_INACTIVE 1 /* thread not currently running */
-#define DUK_HTHREAD_STATE_RUNNING 2 /* thread currently running (only one at a time) */
-#define DUK_HTHREAD_STATE_RESUMED 3 /* thread resumed another thread (active but not running) */
-#define DUK_HTHREAD_STATE_YIELDED 4 /* thread has yielded */
-#define DUK_HTHREAD_STATE_TERMINATED 5 /* thread has terminated */
+#define DUK_HTHREAD_STATE_INACTIVE 1 /* thread not currently running */
+#define DUK_HTHREAD_STATE_RUNNING 2 /* thread currently running (only one at a time) */
+#define DUK_HTHREAD_STATE_RESUMED 3 /* thread resumed another thread (active but not running) */
+#define DUK_HTHREAD_STATE_YIELDED 4 /* thread has yielded */
+#define DUK_HTHREAD_STATE_TERMINATED 5 /* thread has terminated */
/* Executor interrupt default interval when nothing else requires a
* smaller value. The default interval must be small enough to allow
@@ -7451,7 +8163,7 @@ DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx
* impact on execution performance low.
*/
#if defined(DUK_USE_INTERRUPT_COUNTER)
-#define DUK_HTHREAD_INTCTR_DEFAULT (256L * 1024L)
+#define DUK_HTHREAD_INTCTR_DEFAULT (256L * 1024L)
#endif
/*
@@ -7462,37 +8174,35 @@ DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx
* diagnose behavior so it's worth checking even when the check is not 100%.
*/
+#if defined(DUK_USE_ASSERTIONS)
/* Assertions for internals. */
-#define DUK_ASSERT_HTHREAD_VALID(thr) do { \
- DUK_ASSERT((thr) != NULL); \
- DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) (thr)) == DUK_HTYPE_OBJECT); \
- DUK_ASSERT(DUK_HOBJECT_IS_THREAD((duk_hobject *) (thr))); \
- DUK_ASSERT((thr)->unused1 == 0); \
- DUK_ASSERT((thr)->unused2 == 0); \
+DUK_INTERNAL_DECL void duk_hthread_assert_valid(duk_hthread *thr);
+#define DUK_HTHREAD_ASSERT_VALID(thr) \
+ do { \
+ duk_hthread_assert_valid((thr)); \
} while (0)
/* Assertions for public API calls; a bit stronger. */
-#define DUK_ASSERT_CTX_VALID(thr) do { \
- DUK_ASSERT((thr) != NULL); \
- DUK_ASSERT_HTHREAD_VALID((thr)); \
- DUK_ASSERT((thr)->valstack != NULL); \
- DUK_ASSERT((thr)->valstack_bottom != NULL); \
- DUK_ASSERT((thr)->valstack_top != NULL); \
- DUK_ASSERT((thr)->valstack_end != NULL); \
- DUK_ASSERT((thr)->valstack_alloc_end != NULL); \
- DUK_ASSERT((thr)->valstack_alloc_end >= (thr)->valstack); \
- DUK_ASSERT((thr)->valstack_end >= (thr)->valstack); \
- DUK_ASSERT((thr)->valstack_top >= (thr)->valstack); \
- DUK_ASSERT((thr)->valstack_top >= (thr)->valstack_bottom); \
- DUK_ASSERT((thr)->valstack_end >= (thr)->valstack_top); \
- DUK_ASSERT((thr)->valstack_alloc_end >= (thr)->valstack_end); \
+DUK_INTERNAL_DECL void duk_ctx_assert_valid(duk_hthread *thr);
+#define DUK_CTX_ASSERT_VALID(thr) \
+ do { \
+ duk_ctx_assert_valid((thr)); \
} while (0)
+#else
+#define DUK_HTHREAD_ASSERT_VALID(thr) \
+ do { \
+ } while (0)
+#define DUK_CTX_ASSERT_VALID(thr) \
+ do { \
+ } while (0)
+#endif
/* Assertions for API call entry specifically. Checks 'ctx' but also may
* check internal state (e.g. not in a debugger transport callback).
*/
-#define DUK_ASSERT_API_ENTRY(thr) do { \
- DUK_ASSERT_CTX_VALID((thr)); \
+#define DUK_ASSERT_API_ENTRY(thr) \
+ do { \
+ DUK_CTX_ASSERT_VALID((thr)); \
DUK_ASSERT((thr)->heap != NULL); \
DUK_ASSERT((thr)->heap->dbg_calling_transport == 0); \
} while (0)
@@ -7501,11 +8211,9 @@ DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx
* Assertion helpers.
*/
-#define DUK_ASSERT_STRIDX_VALID(val) \
- DUK_ASSERT((duk_uint_t) (val) < DUK_HEAP_NUM_STRINGS)
+#define DUK_ASSERT_STRIDX_VALID(val) DUK_ASSERT((duk_uint_t) (val) < DUK_HEAP_NUM_STRINGS)
-#define DUK_ASSERT_BIDX_VALID(val) \
- DUK_ASSERT((duk_uint_t) (val) < DUK_NUM_BUILTINS)
+#define DUK_ASSERT_BIDX_VALID(val) DUK_ASSERT((duk_uint_t) (val) < DUK_NUM_BUILTINS)
/*
* Misc
@@ -7513,9 +8221,7 @@ DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx
/* Fast access to 'this' binding. Assumes there's a call in progress. */
#define DUK_HTHREAD_THIS_PTR(thr) \
- (DUK_ASSERT_EXPR((thr) != NULL), \
- DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \
- (thr)->valstack_bottom - 1)
+ (DUK_ASSERT_EXPR((thr) != NULL), DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), (thr)->valstack_bottom - 1)
/*
* Struct defines
@@ -7523,12 +8229,13 @@ DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx
/* Fields are ordered for alignment/packing. */
struct duk_activation {
- duk_tval tv_func; /* borrowed: full duk_tval for function being executed; for lightfuncs */
- duk_hobject *func; /* borrowed: function being executed; for bound function calls, this is the final, real function, NULL for lightfuncs */
+ duk_tval tv_func; /* borrowed: full duk_tval for function being executed; for lightfuncs */
+ duk_hobject *func; /* borrowed: function being executed; for bound function calls, this is the final, real function, NULL
+ for lightfuncs */
duk_activation *parent; /* previous (parent) activation (or NULL if none) */
- duk_hobject *var_env; /* current variable environment (may be NULL if delayed) */
- duk_hobject *lex_env; /* current lexical environment (may be NULL if delayed) */
- duk_catcher *cat; /* current catcher (or NULL) */
+ duk_hobject *var_env; /* current variable environment (may be NULL if delayed) */
+ duk_hobject *lex_env; /* current lexical environment (may be NULL if delayed) */
+ duk_catcher *cat; /* current catcher (or NULL) */
#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
/* Previous value of 'func' caller, restored when unwound. Only in use
@@ -7537,17 +8244,17 @@ struct duk_activation {
duk_hobject *prev_caller;
#endif
- duk_instr_t *curr_pc; /* next instruction to execute (points to 'func' bytecode, stable pointer), NULL for native calls */
+ duk_instr_t *curr_pc; /* next instruction to execute (points to 'func' bytecode, stable pointer), NULL for native calls */
/* bottom_byteoff and retval_byteoff are only used for book-keeping
- * of Ecmascript-initiated calls, to allow returning to an Ecmascript
+ * of ECMAScript-initiated calls, to allow returning to an ECMAScript
* function properly.
*/
/* Bottom of valstack for this activation, used to reset
* valstack_bottom on return; offset is absolute. There's
* no need to track 'top' because native call handling deals
- * with that using locals, and for Ecmascript returns 'nregs'
+ * with that using locals, and for ECMAScript returns 'nregs'
* indicates the necessary top.
*/
duk_size_t bottom_byteoff;
@@ -7584,12 +8291,12 @@ struct duk_activation {
};
struct duk_catcher {
- duk_catcher *parent; /* previous (parent) catcher (or NULL if none) */
- duk_hstring *h_varname; /* borrowed reference to catch variable name (or NULL if none) */
- /* (reference is valid as long activation exists) */
- duk_instr_t *pc_base; /* resume execution from pc_base or pc_base+1 (points to 'func' bytecode, stable pointer) */
- duk_size_t idx_base; /* idx_base and idx_base+1 get completion value and type */
- duk_uint32_t flags; /* type and control flags, label number */
+ duk_catcher *parent; /* previous (parent) catcher (or NULL if none) */
+ duk_hstring *h_varname; /* borrowed reference to catch variable name (or NULL if none) */
+ /* (reference is valid as long activation exists) */
+ duk_instr_t *pc_base; /* resume execution from pc_base or pc_base+1 (points to 'func' bytecode, stable pointer) */
+ duk_size_t idx_base; /* idx_base and idx_base+1 get completion value and type */
+ duk_uint32_t flags; /* type and control flags, label number */
/* XXX: could pack 'flags' and 'idx_base' to same value in practice,
* on 32-bit targets this would make duk_catcher 16 bytes.
*/
@@ -7647,21 +8354,21 @@ struct duk_hthread {
* yyy = arbitrary values, inside current frame
* uuu = outside active value stack, initialized to 'undefined'
*/
- duk_tval *valstack; /* start of valstack allocation */
- duk_tval *valstack_end; /* end of valstack reservation/guarantee (exclusive) */
- duk_tval *valstack_alloc_end; /* end of valstack allocation */
- duk_tval *valstack_bottom; /* bottom of current frame */
- duk_tval *valstack_top; /* top of current frame (exclusive) */
+ duk_tval *valstack; /* start of valstack allocation */
+ duk_tval *valstack_end; /* end of valstack reservation/guarantee (exclusive) */
+ duk_tval *valstack_alloc_end; /* end of valstack allocation */
+ duk_tval *valstack_bottom; /* bottom of current frame */
+ duk_tval *valstack_top; /* top of current frame (exclusive) */
/* Call stack, represented as a linked list starting from the current
* activation (or NULL if nothing is active).
*/
- duk_activation *callstack_curr; /* current activation (or NULL if none) */
- duk_size_t callstack_top; /* number of activation records in callstack (0 if none) */
- duk_size_t callstack_preventcount; /* number of activation records in callstack preventing a yield */
+ duk_activation *callstack_curr; /* current activation (or NULL if none) */
+ duk_size_t callstack_top; /* number of activation records in callstack (0 if none) */
+ duk_size_t callstack_preventcount; /* number of activation records in callstack preventing a yield */
/* Yield/resume book-keeping. */
- duk_hthread *resumer; /* who resumed us (if any) */
+ duk_hthread *resumer; /* who resumed us (if any) */
/* Current compiler state (if any), used for augmenting SyntaxErrors. */
duk_compiler_ctx *compile_ctx;
@@ -7674,8 +8381,8 @@ struct duk_hthread {
* important for the counter to be conveniently accessible for the
* bytecode executor inner loop for performance reasons.
*/
- duk_int_t interrupt_counter; /* countdown state */
- duk_int_t interrupt_init; /* start value for current countdown */
+ duk_int_t interrupt_counter; /* countdown state */
+ duk_int_t interrupt_init; /* start value for current countdown */
#endif
/* Builtin-objects; may or may not be shared with other threads,
@@ -7712,13 +8419,13 @@ DUK_INTERNAL_DECL void duk_hthread_create_builtin_objects(duk_hthread *thr);
DUK_INTERNAL_DECL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr);
DUK_INTERNAL_DECL void duk_hthread_terminate(duk_hthread *thr);
-DUK_INTERNAL_DECL DUK_INLINE duk_activation *duk_hthread_activation_alloc(duk_hthread *thr);
+DUK_INTERNAL_DECL duk_activation *duk_hthread_activation_alloc(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act);
DUK_INTERNAL_DECL void duk_hthread_activation_unwind_norz(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_hthread_activation_unwind_reuse_norz(duk_hthread *thr);
DUK_INTERNAL_DECL duk_activation *duk_hthread_get_activation_for_level(duk_hthread *thr, duk_int_t level);
-DUK_INTERNAL_DECL DUK_INLINE duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr);
+DUK_INTERNAL_DECL duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat);
DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activation *act);
DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk_activation *act);
@@ -7727,7 +8434,7 @@ DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr
DUK_INTERNAL_DECL void duk_hthread_valstack_torture_realloc(duk_hthread *thr);
#endif
-DUK_INTERNAL_DECL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud); /* indirect allocs */
+DUK_INTERNAL_DECL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud); /* indirect allocs */
#if defined(DUK_USE_DEBUGGER_SUPPORT)
DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act);
@@ -7736,7 +8443,7 @@ DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr
DUK_INTERNAL_DECL void duk_hthread_sync_currpc(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_hthread_sync_and_null_currpc(duk_hthread *thr);
-#endif /* DUK_HTHREAD_H_INCLUDED */
+#endif /* DUK_HTHREAD_H_INCLUDED */
/* #include duk_harray.h */
/*
* Array object representation, used for actual Array instances.
@@ -7749,16 +8456,28 @@ DUK_INTERNAL_DECL void duk_hthread_sync_and_null_currpc(duk_hthread *thr);
#if !defined(DUK_HARRAY_H_INCLUDED)
#define DUK_HARRAY_H_INCLUDED
-#define DUK_ASSERT_HARRAY_VALID(h) do { \
- DUK_ASSERT((h) != NULL); \
- DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) (h))); \
- DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY((duk_hobject *) (h))); \
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_harray_assert_valid(duk_harray *h);
+#define DUK_HARRAY_ASSERT_VALID(h) \
+ do { \
+ duk_harray_assert_valid((h)); \
+ } while (0)
+#else
+#define DUK_HARRAY_ASSERT_VALID(h) \
+ do { \
} while (0)
+#endif
-#define DUK_HARRAY_LENGTH_WRITABLE(h) (!(h)->length_nonwritable)
-#define DUK_HARRAY_LENGTH_NONWRITABLE(h) ((h)->length_nonwritable)
-#define DUK_HARRAY_SET_LENGTH_WRITABLE(h) do { (h)->length_nonwritable = 0; } while (0)
-#define DUK_HARRAY_SET_LENGTH_NONWRITABLE(h) do { (h)->length_nonwritable = 1; } while (0)
+#define DUK_HARRAY_LENGTH_WRITABLE(h) (!(h)->length_nonwritable)
+#define DUK_HARRAY_LENGTH_NONWRITABLE(h) ((h)->length_nonwritable)
+#define DUK_HARRAY_SET_LENGTH_WRITABLE(h) \
+ do { \
+ (h)->length_nonwritable = 0; \
+ } while (0)
+#define DUK_HARRAY_SET_LENGTH_NONWRITABLE(h) \
+ do { \
+ (h)->length_nonwritable = 1; \
+ } while (0)
struct duk_harray {
/* Shared object part. */
@@ -7784,7 +8503,7 @@ struct duk_harray {
duk_bool_t length_nonwritable;
};
-#endif /* DUK_HARRAY_H_INCLUDED */
+#endif /* DUK_HARRAY_H_INCLUDED */
/* #include duk_henv.h */
/*
* Environment object representation.
@@ -7793,18 +8512,25 @@ struct duk_harray {
#if !defined(DUK_HENV_H_INCLUDED)
#define DUK_HENV_H_INCLUDED
-#define DUK_ASSERT_HDECENV_VALID(h) do { \
- DUK_ASSERT((h) != NULL); \
- DUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) (h))); \
- DUK_ASSERT((h)->thread == NULL || (h)->varmap != NULL); \
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_hdecenv_assert_valid(duk_hdecenv *h);
+DUK_INTERNAL_DECL void duk_hobjenv_assert_valid(duk_hobjenv *h);
+#define DUK_HDECENV_ASSERT_VALID(h) \
+ do { \
+ duk_hdecenv_assert_valid((h)); \
} while (0)
-
-#define DUK_ASSERT_HOBJENV_VALID(h) do { \
- DUK_ASSERT((h) != NULL); \
- DUK_ASSERT(DUK_HOBJECT_IS_OBJENV((duk_hobject *) (h))); \
- DUK_ASSERT((h)->target != NULL); \
- DUK_ASSERT((h)->has_this == 0 || (h)->has_this == 1); \
+#define DUK_HOBJENV_ASSERT_VALID(h) \
+ do { \
+ duk_hobjenv_assert_valid((h)); \
} while (0)
+#else
+#define DUK_HDECENV_ASSERT_VALID(h) \
+ do { \
+ } while (0)
+#define DUK_HOBJENV_ASSERT_VALID(h) \
+ do { \
+ } while (0)
+#endif
struct duk_hdecenv {
/* Shared object part. */
@@ -7833,7 +8559,7 @@ struct duk_hobjenv {
duk_bool_t has_this;
};
-#endif /* DUK_HENV_H_INCLUDED */
+#endif /* DUK_HENV_H_INCLUDED */
/* #include duk_hbuffer.h */
/*
* Heap buffer representation.
@@ -7857,17 +8583,17 @@ struct duk_hobjenv {
* External buffer: DUK_HBUFFER_FLAG_DYNAMIC | DUK_HBUFFER_FLAG_EXTERNAL
*/
-#define DUK_HBUFFER_FLAG_DYNAMIC DUK_HEAPHDR_USER_FLAG(0) /* buffer is behind a pointer, dynamic or external */
-#define DUK_HBUFFER_FLAG_EXTERNAL DUK_HEAPHDR_USER_FLAG(1) /* buffer pointer is to an externally allocated buffer */
+#define DUK_HBUFFER_FLAG_DYNAMIC DUK_HEAPHDR_USER_FLAG(0) /* buffer is behind a pointer, dynamic or external */
+#define DUK_HBUFFER_FLAG_EXTERNAL DUK_HEAPHDR_USER_FLAG(1) /* buffer pointer is to an externally allocated buffer */
-#define DUK_HBUFFER_HAS_DYNAMIC(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
-#define DUK_HBUFFER_HAS_EXTERNAL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
+#define DUK_HBUFFER_HAS_DYNAMIC(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
+#define DUK_HBUFFER_HAS_EXTERNAL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
-#define DUK_HBUFFER_SET_DYNAMIC(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
-#define DUK_HBUFFER_SET_EXTERNAL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
+#define DUK_HBUFFER_SET_DYNAMIC(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
+#define DUK_HBUFFER_SET_EXTERNAL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
-#define DUK_HBUFFER_CLEAR_DYNAMIC(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
-#define DUK_HBUFFER_CLEAR_EXTERNAL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
+#define DUK_HBUFFER_CLEAR_DYNAMIC(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
+#define DUK_HBUFFER_CLEAR_EXTERNAL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
/*
* Misc defines
@@ -7880,12 +8606,12 @@ struct duk_hobjenv {
*/
#if defined(DUK_USE_BUFLEN16)
-#define DUK_HBUFFER_MAX_BYTELEN (0x0000ffffUL)
+#define DUK_HBUFFER_MAX_BYTELEN (0x0000ffffUL)
#else
/* Intentionally not 0x7fffffffUL; at least JSON code expects that
* 2*len + 2 fits in 32 bits.
*/
-#define DUK_HBUFFER_MAX_BYTELEN (0x7ffffffeUL)
+#define DUK_HBUFFER_MAX_BYTELEN (0x7ffffffeUL)
#endif
/*
@@ -7894,60 +8620,70 @@ struct duk_hobjenv {
#if defined(DUK_USE_BUFLEN16)
/* size stored in duk_heaphdr unused flag bits */
-#define DUK_HBUFFER_GET_SIZE(x) ((x)->hdr.h_flags >> 16)
-#define DUK_HBUFFER_SET_SIZE(x,v) do { \
+#define DUK_HBUFFER_GET_SIZE(x) ((x)->hdr.h_flags >> 16)
+#define DUK_HBUFFER_SET_SIZE(x, v) \
+ do { \
duk_size_t duk__v; \
duk__v = (v); \
DUK_ASSERT(duk__v <= 0xffffUL); \
(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | (((duk_uint32_t) duk__v) << 16); \
} while (0)
-#define DUK_HBUFFER_ADD_SIZE(x,dv) do { \
+#define DUK_HBUFFER_ADD_SIZE(x, dv) \
+ do { \
(x)->hdr.h_flags += ((dv) << 16); \
} while (0)
-#define DUK_HBUFFER_SUB_SIZE(x,dv) do { \
+#define DUK_HBUFFER_SUB_SIZE(x, dv) \
+ do { \
(x)->hdr.h_flags -= ((dv) << 16); \
} while (0)
#else
-#define DUK_HBUFFER_GET_SIZE(x) (((duk_hbuffer *) (x))->size)
-#define DUK_HBUFFER_SET_SIZE(x,v) do { \
+#define DUK_HBUFFER_GET_SIZE(x) (((duk_hbuffer *) (x))->size)
+#define DUK_HBUFFER_SET_SIZE(x, v) \
+ do { \
((duk_hbuffer *) (x))->size = (v); \
} while (0)
-#define DUK_HBUFFER_ADD_SIZE(x,dv) do { \
+#define DUK_HBUFFER_ADD_SIZE(x, dv) \
+ do { \
(x)->size += (dv); \
} while (0)
-#define DUK_HBUFFER_SUB_SIZE(x,dv) do { \
+#define DUK_HBUFFER_SUB_SIZE(x, dv) \
+ do { \
(x)->size -= (dv); \
} while (0)
#endif
-#define DUK_HBUFFER_FIXED_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
-#define DUK_HBUFFER_FIXED_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x))
+#define DUK_HBUFFER_FIXED_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
+#define DUK_HBUFFER_FIXED_SET_SIZE(x, v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x))
#define DUK_HBUFFER_DYNAMIC_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
-#define DUK_HBUFFER_DYNAMIC_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
-#define DUK_HBUFFER_DYNAMIC_ADD_SIZE(x,dv) DUK_HBUFFER_ADD_SIZE((duk_hbuffer *) (x), (dv))
-#define DUK_HBUFFER_DYNAMIC_SUB_SIZE(x,dv) DUK_HBUFFER_SUB_SIZE((duk_hbuffer *) (x), (dv))
+#define DUK_HBUFFER_DYNAMIC_SET_SIZE(x, v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
+#define DUK_HBUFFER_DYNAMIC_ADD_SIZE(x, dv) DUK_HBUFFER_ADD_SIZE((duk_hbuffer *) (x), (dv))
+#define DUK_HBUFFER_DYNAMIC_SUB_SIZE(x, dv) DUK_HBUFFER_SUB_SIZE((duk_hbuffer *) (x), (dv))
#define DUK_HBUFFER_EXTERNAL_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
-#define DUK_HBUFFER_EXTERNAL_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
+#define DUK_HBUFFER_EXTERNAL_SET_SIZE(x, v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
-#define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap,x) ((duk_uint8_t *) (((duk_hbuffer_fixed *) (x)) + 1))
+#define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap, x) ((duk_uint8_t *) (((duk_hbuffer_fixed *) (void *) (x)) + 1))
#if defined(DUK_USE_HEAPPTR16)
-#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) \
+#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, x) \
((void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (x))->h_extra16))
-#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v) do { \
+#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, x, v) \
+ do { \
((duk_heaphdr *) (x))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
} while (0)
-#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x) do { \
- ((duk_heaphdr *) (x))->h_extra16 = 0; /* assume 0 <=> NULL */ \
+#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap, x) \
+ do { \
+ ((duk_heaphdr *) (x))->h_extra16 = 0; /* assume 0 <=> NULL */ \
} while (0)
#else
-#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) ((x)->curr_alloc)
-#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v) do { \
+#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, x) ((x)->curr_alloc)
+#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, x, v) \
+ do { \
(x)->curr_alloc = (void *) (v); \
} while (0)
-#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x) do { \
+#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap, x) \
+ do { \
(x)->curr_alloc = (void *) NULL; \
} while (0)
#endif
@@ -7956,21 +8692,23 @@ struct duk_hobjenv {
* Duktape heap.
*/
#if defined(DUK_USE_HEAPPTR16)
-#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
- ((void *) (x)->curr_alloc)
-#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v) do { \
+#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap, x) ((void *) (x)->curr_alloc)
+#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap, x, v) \
+ do { \
(x)->curr_alloc = (void *) (v); \
} while (0)
-#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x) do { \
+#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap, x) \
+ do { \
(x)->curr_alloc = (void *) NULL; \
} while (0)
#else
-#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
- ((void *) (x)->curr_alloc)
-#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v) do { \
+#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap, x) ((void *) (x)->curr_alloc)
+#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap, x, v) \
+ do { \
(x)->curr_alloc = (void *) (v); \
} while (0)
-#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x) do { \
+#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap, x) \
+ do { \
(x)->curr_alloc = (void *) NULL; \
} while (0)
#endif
@@ -7979,24 +8717,31 @@ struct duk_hobjenv {
* size). May be NULL for zero size dynamic/external buffer.
*/
#if defined(DUK_USE_HEAPPTR16)
-#define DUK_HBUFFER_GET_DATA_PTR(heap,x) ( \
- DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
- ( \
- DUK_HBUFFER_HAS_EXTERNAL((x)) ? \
- DUK_HBUFFER_EXTERNAL_GET_DATA_PTR((heap), (duk_hbuffer_external *) (x)) : \
- DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) \
- ) : \
- DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \
- )
+#define DUK_HBUFFER_GET_DATA_PTR(heap, x) \
+ (DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
+ (DUK_HBUFFER_HAS_EXTERNAL((x)) ? DUK_HBUFFER_EXTERNAL_GET_DATA_PTR((heap), (duk_hbuffer_external *) (x)) : \
+ DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x))) : \
+ DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (void *) (x)))
#else
/* Without heap pointer compression duk_hbuffer_dynamic and duk_hbuffer_external
* have the same layout so checking for fixed vs. dynamic (or external) is enough.
*/
-#define DUK_HBUFFER_GET_DATA_PTR(heap,x) ( \
- DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
- DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) : \
- DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \
- )
+#define DUK_HBUFFER_GET_DATA_PTR(heap, x) \
+ (DUK_HBUFFER_HAS_DYNAMIC((x)) ? DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) : \
+ DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (void *) (x)))
+#endif
+
+/* Validity assert. */
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_hbuffer_assert_valid(duk_hbuffer *h);
+#define DUK_HBUFFER_ASSERT_VALID(h) \
+ do { \
+ duk_hbuffer_assert_valid((h)); \
+ } while (0)
+#else
+#define DUK_HBUFFER_ASSERT_VALID(h) \
+ do { \
+ } while (0)
#endif
/*
@@ -8069,7 +8814,10 @@ struct duk_hbuffer_fixed {
#if (DUK_USE_ALIGN_BY == 4)
duk_uint32_t dummy_for_align4;
#elif (DUK_USE_ALIGN_BY == 8)
- duk_double_t dummy_for_align8;
+ duk_double_t dummy_for_align8_1;
+#if defined(DUK_USE_64BIT_OPS)
+ duk_uint64_t dummy_for_align8_2;
+#endif
#elif (DUK_USE_ALIGN_BY == 1)
/* no extra padding */
#else
@@ -8091,9 +8839,9 @@ struct duk_hbuffer_fixed {
*/
}
#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR)
-__attribute__ ((aligned (8)))
+__attribute__((aligned(8)))
#elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR)
-__attribute__ ((aligned (8)))
+__attribute__((aligned(8)))
#endif
;
#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
@@ -8116,7 +8864,7 @@ struct duk_hbuffer_dynamic {
#if defined(DUK_USE_HEAPPTR16)
/* Stored in duk_heaphdr h_extra16. */
#else
- void *curr_alloc; /* may be NULL if alloc_size == 0 */
+ void *curr_alloc; /* may be NULL if alloc_size == 0 */
#endif
/*
@@ -8145,7 +8893,7 @@ struct duk_hbuffer_external {
/* Cannot be compressed as a heap pointer because may point to
* an arbitrary address.
*/
- void *curr_alloc; /* may be NULL if alloc_size == 0 */
+ void *curr_alloc; /* may be NULL if alloc_size == 0 */
};
/*
@@ -8153,13 +8901,13 @@ struct duk_hbuffer_external {
*/
DUK_INTERNAL_DECL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata);
-DUK_INTERNAL_DECL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud); /* indirect allocs */
+DUK_INTERNAL_DECL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud); /* indirect allocs */
/* dynamic buffer ops */
DUK_INTERNAL_DECL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size);
DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf);
-#endif /* DUK_HBUFFER_H_INCLUDED */
+#endif /* DUK_HBUFFER_H_INCLUDED */
/* #include duk_hproxy.h */
/*
* Proxy object representation.
@@ -8168,12 +8916,17 @@ DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *
#if !defined(DUK_HPROXY_H_INCLUDED)
#define DUK_HPROXY_H_INCLUDED
-#define DUK_ASSERT_HPROXY_VALID(h) do { \
- DUK_ASSERT((h) != NULL); \
- DUK_ASSERT((h)->target != NULL); \
- DUK_ASSERT((h)->handler != NULL); \
- DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((duk_hobject *) (h))); \
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_hproxy_assert_valid(duk_hproxy *h);
+#define DUK_HPROXY_ASSERT_VALID(h) \
+ do { \
+ duk_hproxy_assert_valid((h)); \
+ } while (0)
+#else
+#define DUK_HPROXY_ASSERT_VALID(h) \
+ do { \
} while (0)
+#endif
struct duk_hproxy {
/* Shared object part. */
@@ -8186,7 +8939,7 @@ struct duk_hproxy {
duk_hobject *handler;
};
-#endif /* DUK_HPROXY_H_INCLUDED */
+#endif /* DUK_HPROXY_H_INCLUDED */
/* #include duk_heap.h */
/*
* Heap structure.
@@ -8204,46 +8957,50 @@ struct duk_hproxy {
* Heap flags
*/
-#define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED (1U << 0) /* mark-and-sweep marking reached a recursion limit and must use multi-pass marking */
-#define DUK_HEAP_FLAG_INTERRUPT_RUNNING (1U << 1) /* executor interrupt running (used to avoid nested interrupts) */
-#define DUK_HEAP_FLAG_FINALIZER_NORESCUE (1U << 2) /* heap destruction ongoing, finalizer rescue no longer possible */
-#define DUK_HEAP_FLAG_DEBUGGER_PAUSED (1U << 3) /* debugger is paused: talk with debug client until step/resume */
+#define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED \
+ (1U << 0) /* mark-and-sweep marking reached a recursion limit and must use multi-pass marking */
+#define DUK_HEAP_FLAG_INTERRUPT_RUNNING (1U << 1) /* executor interrupt running (used to avoid nested interrupts) */
+#define DUK_HEAP_FLAG_FINALIZER_NORESCUE (1U << 2) /* heap destruction ongoing, finalizer rescue no longer possible */
+#define DUK_HEAP_FLAG_DEBUGGER_PAUSED (1U << 3) /* debugger is paused: talk with debug client until step/resume */
-#define DUK__HEAP_HAS_FLAGS(heap,bits) ((heap)->flags & (bits))
-#define DUK__HEAP_SET_FLAGS(heap,bits) do { \
+#define DUK__HEAP_HAS_FLAGS(heap, bits) ((heap)->flags & (bits))
+#define DUK__HEAP_SET_FLAGS(heap, bits) \
+ do { \
(heap)->flags |= (bits); \
} while (0)
-#define DUK__HEAP_CLEAR_FLAGS(heap,bits) do { \
+#define DUK__HEAP_CLEAR_FLAGS(heap, bits) \
+ do { \
(heap)->flags &= ~(bits); \
} while (0)
-#define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
-#define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
-#define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
-#define DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
+#define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
+#define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
+#define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
+#define DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
-#define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
-#define DUK_HEAP_SET_INTERRUPT_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
-#define DUK_HEAP_SET_FINALIZER_NORESCUE(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
-#define DUK_HEAP_SET_DEBUGGER_PAUSED(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
+#define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
+#define DUK_HEAP_SET_INTERRUPT_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
+#define DUK_HEAP_SET_FINALIZER_NORESCUE(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
+#define DUK_HEAP_SET_DEBUGGER_PAUSED(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
-#define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
-#define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
-#define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
-#define DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
+#define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) \
+ DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
+#define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
+#define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
+#define DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
/*
* Longjmp types, also double as identifying continuation type for a rethrow (in 'finally')
*/
-#define DUK_LJ_TYPE_UNKNOWN 0 /* unused */
-#define DUK_LJ_TYPE_THROW 1 /* value1 -> error object */
-#define DUK_LJ_TYPE_YIELD 2 /* value1 -> yield value, iserror -> error / normal */
-#define DUK_LJ_TYPE_RESUME 3 /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */
-#define DUK_LJ_TYPE_BREAK 4 /* value1 -> label number, pseudo-type to indicate a break continuation (for ENDFIN) */
-#define DUK_LJ_TYPE_CONTINUE 5 /* value1 -> label number, pseudo-type to indicate a continue continuation (for ENDFIN) */
-#define DUK_LJ_TYPE_RETURN 6 /* value1 -> return value, pseudo-type to indicate a return continuation (for ENDFIN) */
-#define DUK_LJ_TYPE_NORMAL 7 /* no value, pseudo-type to indicate a normal continuation (for ENDFIN) */
+#define DUK_LJ_TYPE_UNKNOWN 0 /* unused */
+#define DUK_LJ_TYPE_THROW 1 /* value1 -> error object */
+#define DUK_LJ_TYPE_YIELD 2 /* value1 -> yield value, iserror -> error / normal */
+#define DUK_LJ_TYPE_RESUME 3 /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */
+#define DUK_LJ_TYPE_BREAK 4 /* value1 -> label number, pseudo-type to indicate a break continuation (for ENDFIN) */
+#define DUK_LJ_TYPE_CONTINUE 5 /* value1 -> label number, pseudo-type to indicate a continue continuation (for ENDFIN) */
+#define DUK_LJ_TYPE_RETURN 6 /* value1 -> return value, pseudo-type to indicate a return continuation (for ENDFIN) */
+#define DUK_LJ_TYPE_NORMAL 7 /* no value, pseudo-type to indicate a normal continuation (for ENDFIN) */
/*
* Mark-and-sweep flags
@@ -8256,22 +9013,19 @@ struct duk_hproxy {
/* Emergency mark-and-sweep: try extra hard, even at the cost of
* performance.
*/
-#define DUK_MS_FLAG_EMERGENCY (1U << 0)
-
-/* Voluntary mark-and-sweep: triggered periodically. */
-#define DUK_MS_FLAG_VOLUNTARY (1U << 1)
+#define DUK_MS_FLAG_EMERGENCY (1U << 0)
/* Postpone rescue decisions for reachable objects with FINALIZED set.
* Used during finalize_list processing to avoid incorrect rescue
* decisions due to finalize_list being a reachability root.
*/
-#define DUK_MS_FLAG_POSTPONE_RESCUE (1U << 2)
+#define DUK_MS_FLAG_POSTPONE_RESCUE (1U << 1)
/* Don't compact objects; needed during object property table resize
* to prevent a recursive resize. It would suffice to protect only the
* current object being resized, but this is not yet implemented.
*/
-#define DUK_MS_FLAG_NO_OBJECT_COMPACTION (1U << 3)
+#define DUK_MS_FLAG_NO_OBJECT_COMPACTION (1U << 2)
/*
* Thread switching
@@ -8282,9 +9036,10 @@ struct duk_hproxy {
*/
#if defined(DUK_USE_INTERRUPT_COUNTER)
-#define DUK_HEAP_SWITCH_THREAD(heap,newthr) duk_heap_switch_thread((heap), (newthr))
+#define DUK_HEAP_SWITCH_THREAD(heap, newthr) duk_heap_switch_thread((heap), (newthr))
#else
-#define DUK_HEAP_SWITCH_THREAD(heap,newthr) do { \
+#define DUK_HEAP_SWITCH_THREAD(heap, newthr) \
+ do { \
(heap)->curr_thread = (newthr); \
} while (0)
#endif
@@ -8294,11 +9049,14 @@ struct duk_hproxy {
*/
#if defined(DUK_USE_DEBUG)
-#define DUK_STATS_INC(heap,fieldname) do { \
+#define DUK_STATS_INC(heap, fieldname) \
+ do { \
(heap)->fieldname += 1; \
} while (0)
#else
-#define DUK_STATS_INC(heap,fieldname) do {} while (0)
+#define DUK_STATS_INC(heap, fieldname) \
+ do { \
+ } while (0)
#endif
/*
@@ -8316,36 +9074,41 @@ struct duk_hproxy {
* only during init phases).
*/
#if defined(DUK_USE_REFERENCE_COUNTING)
-#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT 12800L /* 50x heap size */
-#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD 1024L
-#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP 256L
+#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT 12800L /* 50x heap size */
+#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD 1024L
+#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP 256L
#else
-#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT 256L /* 1x heap size */
-#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD 1024L
-#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP 256L
+#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT 256L /* 1x heap size */
+#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD 1024L
+#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP 256L
#endif
/* GC torture. */
#if defined(DUK_USE_GC_TORTURE)
-#define DUK_GC_TORTURE(heap) do { duk_heap_mark_and_sweep((heap), 0); } while (0)
+#define DUK_GC_TORTURE(heap) \
+ do { \
+ duk_heap_mark_and_sweep((heap), 0); \
+ } while (0)
#else
-#define DUK_GC_TORTURE(heap) do { } while (0)
+#define DUK_GC_TORTURE(heap) \
+ do { \
+ } while (0)
#endif
/* Stringcache is used for speeding up char-offset-to-byte-offset
* translations for non-ASCII strings.
*/
-#define DUK_HEAP_STRCACHE_SIZE 4
-#define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT 16 /* strings up to the this length are not cached */
+#define DUK_HEAP_STRCACHE_SIZE 4
+#define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT 16 /* strings up to the this length are not cached */
/* Some list management macros. */
-#define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr) duk_heap_insert_into_heap_allocated((heap), (hdr))
+#define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, hdr) duk_heap_insert_into_heap_allocated((heap), (hdr))
#if defined(DUK_USE_REFERENCE_COUNTING)
-#define DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap,hdr) duk_heap_remove_from_heap_allocated((heap), (hdr))
+#define DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap, hdr) duk_heap_remove_from_heap_allocated((heap), (hdr))
#endif
#if defined(DUK_USE_FINALIZER_SUPPORT)
-#define DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap,hdr) duk_heap_insert_into_finalize_list((heap), (hdr))
-#define DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap,hdr) duk_heap_remove_from_finalize_list((heap), (hdr))
+#define DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap, hdr) duk_heap_insert_into_finalize_list((heap), (hdr))
+#define DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap, hdr) duk_heap_remove_from_finalize_list((heap), (hdr))
#endif
/*
@@ -8354,30 +9117,24 @@ struct duk_hproxy {
/* heap string indices are autogenerated in duk_strings.h */
#if defined(DUK_USE_ROM_STRINGS)
-#define DUK_HEAP_GET_STRING(heap,idx) \
- ((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
-#else /* DUK_USE_ROM_STRINGS */
+#define DUK_HEAP_GET_STRING(heap, idx) ((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
+#else /* DUK_USE_ROM_STRINGS */
#if defined(DUK_USE_HEAPPTR16)
-#define DUK_HEAP_GET_STRING(heap,idx) \
- ((duk_hstring *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (heap)->strs16[(idx)]))
+#define DUK_HEAP_GET_STRING(heap, idx) ((duk_hstring *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (heap)->strs16[(idx)]))
#else
-#define DUK_HEAP_GET_STRING(heap,idx) \
- ((heap)->strs[(idx)])
+#define DUK_HEAP_GET_STRING(heap, idx) ((heap)->strs[(idx)])
#endif
-#endif /* DUK_USE_ROM_STRINGS */
+#endif /* DUK_USE_ROM_STRINGS */
/*
* Raw memory calls: relative to heap, but no GC interaction
*/
-#define DUK_ALLOC_RAW(heap,size) \
- ((heap)->alloc_func((heap)->heap_udata, (size)))
+#define DUK_ALLOC_RAW(heap, size) ((heap)->alloc_func((heap)->heap_udata, (size)))
-#define DUK_REALLOC_RAW(heap,ptr,newsize) \
- ((heap)->realloc_func((heap)->heap_udata, (void *) (ptr), (newsize)))
+#define DUK_REALLOC_RAW(heap, ptr, newsize) ((heap)->realloc_func((heap)->heap_udata, (void *) (ptr), (newsize)))
-#define DUK_FREE_RAW(heap,ptr) \
- ((heap)->free_func((heap)->heap_udata, (void *) (ptr)))
+#define DUK_FREE_RAW(heap, ptr) ((heap)->free_func((heap)->heap_udata, (void *) (ptr)))
/*
* Memory calls: relative to heap, GC interaction, but no error throwing.
@@ -8410,11 +9167,11 @@ struct duk_hproxy {
/* callback for indirect reallocs, request for current pointer */
typedef void *(*duk_mem_getptr)(duk_heap *heap, void *ud);
-#define DUK_ALLOC(heap,size) duk_heap_mem_alloc((heap), (size))
-#define DUK_ALLOC_ZEROED(heap,size) duk_heap_mem_alloc_zeroed((heap), (size))
-#define DUK_REALLOC(heap,ptr,newsize) duk_heap_mem_realloc((heap), (ptr), (newsize))
-#define DUK_REALLOC_INDIRECT(heap,cb,ud,newsize) duk_heap_mem_realloc_indirect((heap), (cb), (ud), (newsize))
-#define DUK_FREE(heap,ptr) duk_heap_mem_free((heap), (ptr))
+#define DUK_ALLOC(heap, size) duk_heap_mem_alloc((heap), (size))
+#define DUK_ALLOC_ZEROED(heap, size) duk_heap_mem_alloc_zeroed((heap), (size))
+#define DUK_REALLOC(heap, ptr, newsize) duk_heap_mem_realloc((heap), (ptr), (newsize))
+#define DUK_REALLOC_INDIRECT(heap, cb, ud, newsize) duk_heap_mem_realloc_indirect((heap), (cb), (ud), (newsize))
+#define DUK_FREE(heap, ptr) duk_heap_mem_free((heap), (ptr))
/*
* Checked allocation, relative to a thread
@@ -8423,24 +9180,26 @@ typedef void *(*duk_mem_getptr)(duk_heap *heap, void *ud);
* for convenience.
*/
-#define DUK_ALLOC_CHECKED(thr,size) duk_heap_mem_alloc_checked((thr), (size))
-#define DUK_ALLOC_CHECKED_ZEROED(thr,size) duk_heap_mem_alloc_checked_zeroed((thr), (size))
-#define DUK_FREE_CHECKED(thr,ptr) duk_heap_mem_free((thr)->heap, (ptr))
+#define DUK_ALLOC_CHECKED(thr, size) duk_heap_mem_alloc_checked((thr), (size))
+#define DUK_ALLOC_CHECKED_ZEROED(thr, size) duk_heap_mem_alloc_checked_zeroed((thr), (size))
+#define DUK_FREE_CHECKED(thr, ptr) duk_heap_mem_free((thr)->heap, (ptr))
/*
* Memory constants
*/
-#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT 10 /* Retry allocation after mark-and-sweep for this
- * many times. A single mark-and-sweep round is
- * not guaranteed to free all unreferenced memory
- * because of finalization (in fact, ANY number of
- * rounds is strictly not enough).
- */
+#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT \
+ 10 /* Retry allocation after mark-and-sweep for this \
+ * many times. A single mark-and-sweep round is \
+ * not guaranteed to free all unreferenced memory \
+ * because of finalization (in fact, ANY number of \
+ * rounds is strictly not enough). \
+ */
-#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT 3 /* Starting from this round, use emergency mode
- * for mark-and-sweep.
- */
+#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT \
+ 3 /* Starting from this round, use emergency mode \
+ * for mark-and-sweep. \
+ */
/*
* Debugger support
@@ -8449,26 +9208,26 @@ typedef void *(*duk_mem_getptr)(duk_heap *heap, void *ud);
/* Maximum number of breakpoints. Only breakpoints that are set are
* consulted so increasing this has no performance impact.
*/
-#define DUK_HEAP_MAX_BREAKPOINTS 16
+#define DUK_HEAP_MAX_BREAKPOINTS 16
/* Opcode interval for a Date-based status/peek rate limit check. Only
* relevant when debugger is attached. Requesting a timestamp may be a
* slow operation on some platforms so this shouldn't be too low. On the
* other hand a high value makes Duktape react to a pause request slowly.
*/
-#define DUK_HEAP_DBG_RATELIMIT_OPCODES 4000
+#define DUK_HEAP_DBG_RATELIMIT_OPCODES 4000
/* Milliseconds between status notify and transport peeks. */
-#define DUK_HEAP_DBG_RATELIMIT_MILLISECS 200
+#define DUK_HEAP_DBG_RATELIMIT_MILLISECS 200
/* Debugger pause flags. */
-#define DUK_PAUSE_FLAG_ONE_OPCODE (1U << 0) /* pause when a single opcode has been executed */
-#define DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE (1U << 1) /* one opcode pause actually active; artifact of current implementation */
-#define DUK_PAUSE_FLAG_LINE_CHANGE (1U << 2) /* pause when current line number changes */
-#define DUK_PAUSE_FLAG_FUNC_ENTRY (1U << 3) /* pause when entering a function */
-#define DUK_PAUSE_FLAG_FUNC_EXIT (1U << 4) /* pause when exiting current function */
-#define DUK_PAUSE_FLAG_CAUGHT_ERROR (1U << 5) /* pause when about to throw an error that is caught */
-#define DUK_PAUSE_FLAG_UNCAUGHT_ERROR (1U << 6) /* pause when about to throw an error that won't be caught */
+#define DUK_PAUSE_FLAG_ONE_OPCODE (1U << 0) /* pause when a single opcode has been executed */
+#define DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE (1U << 1) /* one opcode pause actually active; artifact of current implementation */
+#define DUK_PAUSE_FLAG_LINE_CHANGE (1U << 2) /* pause when current line number changes */
+#define DUK_PAUSE_FLAG_FUNC_ENTRY (1U << 3) /* pause when entering a function */
+#define DUK_PAUSE_FLAG_FUNC_EXIT (1U << 4) /* pause when exiting current function */
+#define DUK_PAUSE_FLAG_CAUGHT_ERROR (1U << 5) /* pause when about to throw an error that is caught */
+#define DUK_PAUSE_FLAG_UNCAUGHT_ERROR (1U << 6) /* pause when about to throw an error that won't be caught */
struct duk_breakpoint {
duk_hstring *filename;
@@ -8484,7 +9243,7 @@ struct duk_breakpoint {
* Thus, string caches are now at the heap level now.
*/
-struct duk_strcache {
+struct duk_strcache_entry {
duk_hstring *h;
duk_uint32_t bidx;
duk_uint32_t cidx;
@@ -8496,29 +9255,52 @@ struct duk_strcache {
*/
struct duk_ljstate {
- duk_jmpbuf *jmpbuf_ptr; /* current setjmp() catchpoint */
- duk_small_uint_t type; /* longjmp type */
- duk_bool_t iserror; /* isError flag for yield */
- duk_tval value1; /* 1st related value (type specific) */
- duk_tval value2; /* 2nd related value (type specific) */
+ duk_jmpbuf *jmpbuf_ptr; /* current setjmp() catchpoint */
+ duk_small_uint_t type; /* longjmp type */
+ duk_bool_t iserror; /* isError flag for yield */
+ duk_tval value1; /* 1st related value (type specific) */
+ duk_tval value2; /* 2nd related value (type specific) */
};
-#define DUK_ASSERT_LJSTATE_UNSET(heap) do { \
+#define DUK_ASSERT_LJSTATE_UNSET(heap) \
+ do { \
DUK_ASSERT(heap != NULL); \
DUK_ASSERT(heap->lj.type == DUK_LJ_TYPE_UNKNOWN); \
DUK_ASSERT(heap->lj.iserror == 0); \
DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&heap->lj.value1)); \
DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&heap->lj.value2)); \
} while (0)
-#define DUK_ASSERT_LJSTATE_SET(heap) do { \
+#define DUK_ASSERT_LJSTATE_SET(heap) \
+ do { \
DUK_ASSERT(heap != NULL); \
DUK_ASSERT(heap->lj.type != DUK_LJ_TYPE_UNKNOWN); \
} while (0)
/*
+ * Literal intern cache
+ */
+
+struct duk_litcache_entry {
+ const duk_uint8_t *addr;
+ duk_hstring *h;
+};
+
+/*
* Main heap structure
*/
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_heap_assert_valid(duk_heap *heap);
+#define DUK_HEAP_ASSERT_VALID(heap) \
+ do { \
+ duk_heap_assert_valid((heap)); \
+ } while (0)
+#else
+#define DUK_HEAP_ASSERT_VALID(heap) \
+ do { \
+ } while (0)
+#endif
+
struct duk_heap {
duk_small_uint_t flags;
@@ -8590,6 +9372,11 @@ struct duk_heap {
/* Mark-and-sweep running flag. Prevents re-entry, and also causes
* refzero events to be ignored (= objects won't be queued to refzero_list).
+ *
+ * 0: mark-and-sweep not running
+ * 1: mark-and-sweep is running
+ * 2: heap destruction active or debugger active, prevent mark-and-sweep
+ * and refzero processing (but mark-and-sweep not itself running)
*/
duk_uint_t ms_running;
@@ -8665,9 +9452,9 @@ struct duk_heap {
/* Random number state for duk_util_tinyrandom.c. */
#if !defined(DUK_USE_GET_RANDOM_DOUBLE)
#if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
- duk_uint32_t rnd_state; /* State for Shamir's three-op algorithm */
+ duk_uint32_t rnd_state; /* State for Shamir's three-op algorithm */
#else
- duk_uint64_t rnd_state[2]; /* State for xoroshiro128+ */
+ duk_uint64_t rnd_state[2]; /* State for xoroshiro128+ */
#endif
#endif
@@ -8690,8 +9477,8 @@ struct duk_heap {
/* Debugger state. */
#if defined(DUK_USE_DEBUGGER_SUPPORT)
/* Callbacks and udata; dbg_read_cb != NULL is used to indicate attached state. */
- duk_debug_read_function dbg_read_cb; /* required, NULL implies detached */
- duk_debug_write_function dbg_write_cb; /* required */
+ duk_debug_read_function dbg_read_cb; /* required, NULL implies detached */
+ duk_debug_write_function dbg_write_cb; /* required */
duk_debug_peek_function dbg_peek_cb;
duk_debug_read_flush_function dbg_read_flush_cb;
duk_debug_write_flush_function dbg_write_flush_cb;
@@ -8700,29 +9487,32 @@ struct duk_heap {
void *dbg_udata;
/* The following are only relevant when debugger is attached. */
- duk_bool_t dbg_processing; /* currently processing messages or breakpoints: don't enter message processing recursively (e.g. no breakpoints when processing debugger eval) */
- duk_bool_t dbg_state_dirty; /* resend state next time executor is about to run */
- duk_bool_t dbg_force_restart; /* force executor restart to recheck breakpoints; used to handle function returns (see GH-303) */
- duk_bool_t dbg_detaching; /* debugger detaching; used to avoid calling detach handler recursively */
- duk_small_uint_t dbg_pause_flags; /* flags for automatic pause behavior */
- duk_activation *dbg_pause_act; /* activation related to pause behavior (pause on line change, function entry/exit) */
- duk_uint32_t dbg_pause_startline; /* starting line number for line change related pause behavior */
- duk_breakpoint dbg_breakpoints[DUK_HEAP_MAX_BREAKPOINTS]; /* breakpoints: [0,breakpoint_count[ gc reachable */
+ duk_bool_t dbg_processing; /* currently processing messages or breakpoints: don't enter message processing recursively (e.g.
+ no breakpoints when processing debugger eval) */
+ duk_bool_t dbg_state_dirty; /* resend state next time executor is about to run */
+ duk_bool_t
+ dbg_force_restart; /* force executor restart to recheck breakpoints; used to handle function returns (see GH-303) */
+ duk_bool_t dbg_detaching; /* debugger detaching; used to avoid calling detach handler recursively */
+ duk_small_uint_t dbg_pause_flags; /* flags for automatic pause behavior */
+ duk_activation *dbg_pause_act; /* activation related to pause behavior (pause on line change, function entry/exit) */
+ duk_uint32_t dbg_pause_startline; /* starting line number for line change related pause behavior */
+ duk_breakpoint dbg_breakpoints[DUK_HEAP_MAX_BREAKPOINTS]; /* breakpoints: [0,breakpoint_count[ gc reachable */
duk_small_uint_t dbg_breakpoint_count;
- duk_breakpoint *dbg_breakpoints_active[DUK_HEAP_MAX_BREAKPOINTS + 1]; /* currently active breakpoints: NULL term, borrowed pointers */
+ duk_breakpoint
+ *dbg_breakpoints_active[DUK_HEAP_MAX_BREAKPOINTS + 1]; /* currently active breakpoints: NULL term, borrowed pointers */
/* XXX: make active breakpoints actual copies instead of pointers? */
/* These are for rate limiting Status notifications and transport peeking. */
- duk_uint_t dbg_exec_counter; /* cumulative opcode execution count (overflows are OK) */
- duk_uint_t dbg_last_counter; /* value of dbg_exec_counter when we last did a Date-based check */
- duk_double_t dbg_last_time; /* time when status/peek was last done (Date-based rate limit) */
+ duk_uint_t dbg_exec_counter; /* cumulative opcode execution count (overflows are OK) */
+ duk_uint_t dbg_last_counter; /* value of dbg_exec_counter when we last did a Date-based check */
+ duk_double_t dbg_last_time; /* time when status/peek was last done (Date-based rate limit) */
/* Used to support single-byte stream lookahead. */
duk_bool_t dbg_have_next_byte;
duk_uint8_t dbg_next_byte;
-#endif /* DUK_USE_DEBUGGER_SUPPORT */
+#endif /* DUK_USE_DEBUGGER_SUPPORT */
#if defined(DUK_USE_ASSERTIONS)
- duk_bool_t dbg_calling_transport; /* transport call in progress, calling into Duktape forbidden */
+ duk_bool_t dbg_calling_transport; /* transport call in progress, calling into Duktape forbidden */
#endif
/* String intern table (weak refs). */
@@ -8731,17 +9521,25 @@ struct duk_heap {
#else
duk_hstring **strtable;
#endif
- duk_uint32_t st_mask; /* mask for lookup, st_size - 1 */
- duk_uint32_t st_size; /* stringtable size */
+ duk_uint32_t st_mask; /* mask for lookup, st_size - 1 */
+ duk_uint32_t st_size; /* stringtable size */
#if (DUK_USE_STRTAB_MINSIZE != DUK_USE_STRTAB_MAXSIZE)
- duk_uint32_t st_count; /* string count for resize load factor checks */
+ duk_uint32_t st_count; /* string count for resize load factor checks */
#endif
- duk_bool_t st_resizing; /* string table is being resized; avoid recursive resize */
+ duk_bool_t st_resizing; /* string table is being resized; avoid recursive resize */
/* String access cache (codepoint offset -> byte offset) for fast string
* character looping; 'weak' reference which needs special handling in GC.
*/
- duk_strcache strcache[DUK_HEAP_STRCACHE_SIZE];
+ duk_strcache_entry strcache[DUK_HEAP_STRCACHE_SIZE];
+
+#if defined(DUK_USE_LITCACHE_SIZE)
+ /* Literal intern cache. When enabled, strings interned as literals
+ * (e.g. duk_push_literal()) will be pinned and cached for the lifetime
+ * of the heap.
+ */
+ duk_litcache_entry litcache[DUK_USE_LITCACHE_SIZE];
+#endif
/* Built-in strings. */
#if defined(DUK_USE_ROM_STRINGS)
@@ -8773,6 +9571,9 @@ struct duk_heap {
duk_int_t stats_strtab_resize_check;
duk_int_t stats_strtab_resize_grow;
duk_int_t stats_strtab_resize_shrink;
+ duk_int_t stats_strtab_litcache_hit;
+ duk_int_t stats_strtab_litcache_miss;
+ duk_int_t stats_strtab_litcache_pin;
duk_int_t stats_object_realloc_props;
duk_int_t stats_object_abandon_array;
duk_int_t stats_getownpropdesc_count;
@@ -8797,6 +9598,11 @@ struct duk_heap {
duk_int_t stats_putprop_proxy;
duk_int_t stats_getvar_all;
duk_int_t stats_putvar_all;
+ duk_int_t stats_envrec_delayedcreate;
+ duk_int_t stats_envrec_create;
+ duk_int_t stats_envrec_newenv;
+ duk_int_t stats_envrec_oldenv;
+ duk_int_t stats_envrec_pushclosure;
#endif
};
@@ -8833,6 +9639,11 @@ DUK_INTERNAL_DECL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_t
DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);
DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len);
+#if defined(DUK_USE_LITCACHE_SIZE)
+DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_literal_checked(duk_hthread *thr,
+ const duk_uint8_t *str,
+ duk_uint32_t blen);
+#endif
DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_u32(duk_heap *heap, duk_uint32_t val);
DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val);
#if defined(DUK_USE_REFERENCE_COUNTING)
@@ -8846,7 +9657,9 @@ DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap);
#endif
DUK_INTERNAL_DECL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h);
-DUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset);
+DUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr,
+ duk_hstring *h,
+ duk_uint_fast32_t char_offset);
#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
DUK_INTERNAL_DECL void *duk_default_alloc_function(void *udata, duk_size_t size);
@@ -8867,13 +9680,13 @@ DUK_INTERNAL_DECL void duk_heap_free_freelists(duk_heap *heap);
#if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_INTERNAL_DECL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj);
DUK_INTERNAL_DECL void duk_heap_process_finalize_list(duk_heap *heap);
-#endif /* DUK_USE_FINALIZER_SUPPORT */
+#endif /* DUK_USE_FINALIZER_SUPPORT */
DUK_INTERNAL_DECL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags);
DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len);
-#endif /* DUK_HEAP_H_INCLUDED */
+#endif /* DUK_HEAP_H_INCLUDED */
/* #include duk_debugger.h */
#if !defined(DUK_DEBUGGER_H_INCLUDED)
#define DUK_DEBUGGER_H_INCLUDED
@@ -8881,77 +9694,77 @@ DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uin
/* Debugger protocol version is defined in the public API header. */
/* Initial bytes for markers. */
-#define DUK_DBG_IB_EOM 0x00
-#define DUK_DBG_IB_REQUEST 0x01
-#define DUK_DBG_IB_REPLY 0x02
-#define DUK_DBG_IB_ERROR 0x03
-#define DUK_DBG_IB_NOTIFY 0x04
+#define DUK_DBG_IB_EOM 0x00
+#define DUK_DBG_IB_REQUEST 0x01
+#define DUK_DBG_IB_REPLY 0x02
+#define DUK_DBG_IB_ERROR 0x03
+#define DUK_DBG_IB_NOTIFY 0x04
/* Other initial bytes. */
-#define DUK_DBG_IB_INT4 0x10
-#define DUK_DBG_IB_STR4 0x11
-#define DUK_DBG_IB_STR2 0x12
-#define DUK_DBG_IB_BUF4 0x13
-#define DUK_DBG_IB_BUF2 0x14
-#define DUK_DBG_IB_UNUSED 0x15
-#define DUK_DBG_IB_UNDEFINED 0x16
-#define DUK_DBG_IB_NULL 0x17
-#define DUK_DBG_IB_TRUE 0x18
-#define DUK_DBG_IB_FALSE 0x19
-#define DUK_DBG_IB_NUMBER 0x1a
-#define DUK_DBG_IB_OBJECT 0x1b
-#define DUK_DBG_IB_POINTER 0x1c
-#define DUK_DBG_IB_LIGHTFUNC 0x1d
-#define DUK_DBG_IB_HEAPPTR 0x1e
+#define DUK_DBG_IB_INT4 0x10
+#define DUK_DBG_IB_STR4 0x11
+#define DUK_DBG_IB_STR2 0x12
+#define DUK_DBG_IB_BUF4 0x13
+#define DUK_DBG_IB_BUF2 0x14
+#define DUK_DBG_IB_UNUSED 0x15
+#define DUK_DBG_IB_UNDEFINED 0x16
+#define DUK_DBG_IB_NULL 0x17
+#define DUK_DBG_IB_TRUE 0x18
+#define DUK_DBG_IB_FALSE 0x19
+#define DUK_DBG_IB_NUMBER 0x1a
+#define DUK_DBG_IB_OBJECT 0x1b
+#define DUK_DBG_IB_POINTER 0x1c
+#define DUK_DBG_IB_LIGHTFUNC 0x1d
+#define DUK_DBG_IB_HEAPPTR 0x1e
/* The short string/integer initial bytes starting from 0x60 don't have
* defines now.
*/
/* Error codes. */
-#define DUK_DBG_ERR_UNKNOWN 0x00
-#define DUK_DBG_ERR_UNSUPPORTED 0x01
-#define DUK_DBG_ERR_TOOMANY 0x02
-#define DUK_DBG_ERR_NOTFOUND 0x03
-#define DUK_DBG_ERR_APPLICATION 0x04
+#define DUK_DBG_ERR_UNKNOWN 0x00
+#define DUK_DBG_ERR_UNSUPPORTED 0x01
+#define DUK_DBG_ERR_TOOMANY 0x02
+#define DUK_DBG_ERR_NOTFOUND 0x03
+#define DUK_DBG_ERR_APPLICATION 0x04
/* Commands and notifys initiated by Duktape. */
-#define DUK_DBG_CMD_STATUS 0x01
-#define DUK_DBG_CMD_UNUSED_2 0x02 /* Duktape 1.x: print notify */
-#define DUK_DBG_CMD_UNUSED_3 0x03 /* Duktape 1.x: alert notify */
-#define DUK_DBG_CMD_UNUSED_4 0x04 /* Duktape 1.x: log notify */
-#define DUK_DBG_CMD_THROW 0x05
-#define DUK_DBG_CMD_DETACHING 0x06
-#define DUK_DBG_CMD_APPNOTIFY 0x07
+#define DUK_DBG_CMD_STATUS 0x01
+#define DUK_DBG_CMD_UNUSED_2 0x02 /* Duktape 1.x: print notify */
+#define DUK_DBG_CMD_UNUSED_3 0x03 /* Duktape 1.x: alert notify */
+#define DUK_DBG_CMD_UNUSED_4 0x04 /* Duktape 1.x: log notify */
+#define DUK_DBG_CMD_THROW 0x05
+#define DUK_DBG_CMD_DETACHING 0x06
+#define DUK_DBG_CMD_APPNOTIFY 0x07
/* Commands initiated by debug client. */
-#define DUK_DBG_CMD_BASICINFO 0x10
-#define DUK_DBG_CMD_TRIGGERSTATUS 0x11
-#define DUK_DBG_CMD_PAUSE 0x12
-#define DUK_DBG_CMD_RESUME 0x13
-#define DUK_DBG_CMD_STEPINTO 0x14
-#define DUK_DBG_CMD_STEPOVER 0x15
-#define DUK_DBG_CMD_STEPOUT 0x16
-#define DUK_DBG_CMD_LISTBREAK 0x17
-#define DUK_DBG_CMD_ADDBREAK 0x18
-#define DUK_DBG_CMD_DELBREAK 0x19
-#define DUK_DBG_CMD_GETVAR 0x1a
-#define DUK_DBG_CMD_PUTVAR 0x1b
-#define DUK_DBG_CMD_GETCALLSTACK 0x1c
-#define DUK_DBG_CMD_GETLOCALS 0x1d
-#define DUK_DBG_CMD_EVAL 0x1e
-#define DUK_DBG_CMD_DETACH 0x1f
-#define DUK_DBG_CMD_DUMPHEAP 0x20
-#define DUK_DBG_CMD_GETBYTECODE 0x21
-#define DUK_DBG_CMD_APPREQUEST 0x22
-#define DUK_DBG_CMD_GETHEAPOBJINFO 0x23
-#define DUK_DBG_CMD_GETOBJPROPDESC 0x24
-#define DUK_DBG_CMD_GETOBJPROPDESCRANGE 0x25
+#define DUK_DBG_CMD_BASICINFO 0x10
+#define DUK_DBG_CMD_TRIGGERSTATUS 0x11
+#define DUK_DBG_CMD_PAUSE 0x12
+#define DUK_DBG_CMD_RESUME 0x13
+#define DUK_DBG_CMD_STEPINTO 0x14
+#define DUK_DBG_CMD_STEPOVER 0x15
+#define DUK_DBG_CMD_STEPOUT 0x16
+#define DUK_DBG_CMD_LISTBREAK 0x17
+#define DUK_DBG_CMD_ADDBREAK 0x18
+#define DUK_DBG_CMD_DELBREAK 0x19
+#define DUK_DBG_CMD_GETVAR 0x1a
+#define DUK_DBG_CMD_PUTVAR 0x1b
+#define DUK_DBG_CMD_GETCALLSTACK 0x1c
+#define DUK_DBG_CMD_GETLOCALS 0x1d
+#define DUK_DBG_CMD_EVAL 0x1e
+#define DUK_DBG_CMD_DETACH 0x1f
+#define DUK_DBG_CMD_DUMPHEAP 0x20
+#define DUK_DBG_CMD_GETBYTECODE 0x21
+#define DUK_DBG_CMD_APPREQUEST 0x22
+#define DUK_DBG_CMD_GETHEAPOBJINFO 0x23
+#define DUK_DBG_CMD_GETOBJPROPDESC 0x24
+#define DUK_DBG_CMD_GETOBJPROPDESCRANGE 0x25
/* The low 8 bits map directly to duk_hobject.h DUK_PROPDESC_FLAG_xxx.
* The remaining flags are specific to the debugger.
*/
-#define DUK_DBG_PROPFLAG_SYMBOL (1U << 8)
-#define DUK_DBG_PROPFLAG_HIDDEN (1U << 9)
+#define DUK_DBG_PROPFLAG_SYMBOL (1U << 8)
+#define DUK_DBG_PROPFLAG_HIDDEN (1U << 9)
#if defined(DUK_USE_DEBUGGER_SUPPORT)
DUK_INTERNAL_DECL void duk_debug_do_detach(duk_heap *heap);
@@ -8998,7 +9811,7 @@ DUK_INTERNAL_DECL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h)
#endif
DUK_INTERNAL_DECL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj);
DUK_INTERNAL_DECL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv);
-#if 0 /* unused */
+#if 0 /* unused */
DUK_INTERNAL_DECL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command);
#endif
DUK_INTERNAL_DECL void duk_debug_write_reply(duk_hthread *thr);
@@ -9023,9 +9836,9 @@ DUK_INTERNAL_DECL duk_bool_t duk_debug_is_paused(duk_heap *heap);
DUK_INTERNAL_DECL void duk_debug_set_paused(duk_heap *heap);
DUK_INTERNAL_DECL void duk_debug_clear_paused(duk_heap *heap);
DUK_INTERNAL_DECL void duk_debug_clear_pause_state(duk_heap *heap);
-#endif /* DUK_USE_DEBUGGER_SUPPORT */
+#endif /* DUK_USE_DEBUGGER_SUPPORT */
-#endif /* DUK_DEBUGGER_H_INCLUDED */
+#endif /* DUK_DEBUGGER_H_INCLUDED */
/* #include duk_debug.h */
/*
* Debugging macros, DUK_DPRINT() and its variants in particular.
@@ -9057,19 +9870,25 @@ DUK_INTERNAL_DECL void duk_debug_clear_pause_state(duk_heap *heap);
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
#define DUK_D(x) x
#else
-#define DUK_D(x) do { } while (0) /* omit */
+#define DUK_D(x) \
+ do { \
+ } while (0) /* omit */
#endif
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
#define DUK_DD(x) x
#else
-#define DUK_DD(x) do { } while (0) /* omit */
+#define DUK_DD(x) \
+ do { \
+ } while (0) /* omit */
#endif
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
#define DUK_DDD(x) x
#else
-#define DUK_DDD(x) do { } while (0) /* omit */
+#define DUK_DDD(x) \
+ do { \
+ } while (0) /* omit */
#endif
/*
@@ -9081,35 +9900,35 @@ DUK_INTERNAL_DECL void duk_debug_clear_pause_state(duk_heap *heap);
/* Note: combining __FILE__, __LINE__, and __func__ into fmt would be
* possible compile time, but waste some space with shared function names.
*/
-#define DUK__DEBUG_LOG(lev,...) duk_debug_log((duk_int_t) (lev), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, DUK_FUNC_MACRO, __VA_ARGS__);
+#define DUK__DEBUG_LOG(lev, ...) \
+ duk_debug_log((duk_int_t) (lev), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, DUK_FUNC_MACRO, __VA_ARGS__);
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
-#define DUK_DPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DEBUG, __VA_ARGS__)
+#define DUK_DPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DEBUG, __VA_ARGS__)
#else
#define DUK_DPRINT(...)
#endif
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
-#define DUK_DDPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DDEBUG, __VA_ARGS__)
+#define DUK_DDPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DDEBUG, __VA_ARGS__)
#else
#define DUK_DDPRINT(...)
#endif
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
-#define DUK_DDDPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DDDEBUG, __VA_ARGS__)
+#define DUK_DDDPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DDDEBUG, __VA_ARGS__)
#else
#define DUK_DDDPRINT(...)
#endif
-#else /* DUK_USE_VARIADIC_MACROS */
+#else /* DUK_USE_VARIADIC_MACROS */
-#define DUK__DEBUG_STASH(lev) \
+#define DUK__DEBUG_STASH(lev) \
(void) DUK_SNPRINTF(duk_debug_file_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FILE_MACRO), \
- (void) (duk_debug_file_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \
- (void) (duk_debug_line_stash = (duk_int_t) DUK_LINE_MACRO), \
- (void) DUK_SNPRINTF(duk_debug_func_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FUNC_MACRO), \
- (void) (duk_debug_func_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \
- (void) (duk_debug_level_stash = (lev))
+ (void) (duk_debug_file_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \
+ (void) (duk_debug_line_stash = (duk_int_t) DUK_LINE_MACRO), \
+ (void) DUK_SNPRINTF(duk_debug_func_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FUNC_MACRO), \
+ (void) (duk_debug_func_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), (void) (duk_debug_level_stash = (lev))
/* Without variadic macros resort to comma expression trickery to handle debug
* prints. This generates a lot of harmless warnings. These hacks are not
@@ -9118,34 +9937,40 @@ DUK_INTERNAL_DECL void duk_debug_clear_pause_state(duk_heap *heap);
*/
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
-#define DUK_DPRINT DUK__DEBUG_STASH(DUK_LEVEL_DEBUG), (void) duk_debug_log /* args go here in parens */
+#define DUK_DPRINT DUK__DEBUG_STASH(DUK_LEVEL_DEBUG), (void) duk_debug_log /* args go here in parens */
#else
-#define DUK_DPRINT 0 && /* args go here as a comma expression in parens */
+#define DUK_DPRINT 0 && /* args go here as a comma expression in parens */
#endif
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
-#define DUK_DDPRINT DUK__DEBUG_STASH(DUK_LEVEL_DDEBUG), (void) duk_debug_log /* args go here in parens */
+#define DUK_DDPRINT DUK__DEBUG_STASH(DUK_LEVEL_DDEBUG), (void) duk_debug_log /* args go here in parens */
#else
-#define DUK_DDPRINT 0 && /* args */
+#define DUK_DDPRINT 0 && /* args */
#endif
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
-#define DUK_DDDPRINT DUK__DEBUG_STASH(DUK_LEVEL_DDDEBUG), (void) duk_debug_log /* args go here in parens */
+#define DUK_DDDPRINT DUK__DEBUG_STASH(DUK_LEVEL_DDDEBUG), (void) duk_debug_log /* args go here in parens */
#else
-#define DUK_DDDPRINT 0 && /* args */
+#define DUK_DDDPRINT 0 && /* args */
#endif
-#endif /* DUK_USE_VARIADIC_MACROS */
+#endif /* DUK_USE_VARIADIC_MACROS */
-#else /* DUK_USE_DEBUG */
+#else /* DUK_USE_DEBUG */
/*
* Exposed debug macros: debugging disabled
*/
-#define DUK_D(x) do { } while (0) /* omit */
-#define DUK_DD(x) do { } while (0) /* omit */
-#define DUK_DDD(x) do { } while (0) /* omit */
+#define DUK_D(x) \
+ do { \
+ } while (0) /* omit */
+#define DUK_DD(x) \
+ do { \
+ } while (0) /* omit */
+#define DUK_DDD(x) \
+ do { \
+ } while (0) /* omit */
#if defined(DUK_USE_VARIADIC_MACROS)
@@ -9153,15 +9978,15 @@ DUK_INTERNAL_DECL void duk_debug_clear_pause_state(duk_heap *heap);
#define DUK_DDPRINT(...)
#define DUK_DDDPRINT(...)
-#else /* DUK_USE_VARIADIC_MACROS */
+#else /* DUK_USE_VARIADIC_MACROS */
-#define DUK_DPRINT 0 && /* args go here as a comma expression in parens */
-#define DUK_DDPRINT 0 && /* args */
-#define DUK_DDDPRINT 0 && /* args */
+#define DUK_DPRINT 0 && /* args go here as a comma expression in parens */
+#define DUK_DDPRINT 0 && /* args */
+#define DUK_DDDPRINT 0 && /* args */
-#endif /* DUK_USE_VARIADIC_MACROS */
+#endif /* DUK_USE_VARIADIC_MACROS */
-#endif /* DUK_USE_DEBUG */
+#endif /* DUK_USE_DEBUG */
/*
* Structs
@@ -9182,16 +10007,16 @@ struct duk_fixedbuffer {
#if defined(DUK_USE_DEBUG)
DUK_INTERNAL_DECL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap);
-#if 0 /*unused*/
+#if 0 /*unused*/
DUK_INTERNAL_DECL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...);
#endif
DUK_INTERNAL_DECL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size);
#if defined(DUK_USE_VARIADIC_MACROS)
DUK_INTERNAL_DECL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...);
-#else /* DUK_USE_VARIADIC_MACROS */
+#else /* DUK_USE_VARIADIC_MACROS */
/* parameter passing, not thread safe */
-#define DUK_DEBUG_STASH_SIZE 128
+#define DUK_DEBUG_STASH_SIZE 128
#if !defined(DUK_SINGLE_FILE)
DUK_INTERNAL_DECL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
DUK_INTERNAL_DECL duk_int_t duk_debug_line_stash;
@@ -9199,7 +10024,7 @@ DUK_INTERNAL_DECL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
DUK_INTERNAL_DECL duk_int_t duk_debug_level_stash;
#endif
DUK_INTERNAL_DECL void duk_debug_log(const char *fmt, ...);
-#endif /* DUK_USE_VARIADIC_MACROS */
+#endif /* DUK_USE_VARIADIC_MACROS */
DUK_INTERNAL_DECL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length);
DUK_INTERNAL_DECL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x);
@@ -9208,9 +10033,9 @@ DUK_INTERNAL_DECL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...)
DUK_INTERNAL_DECL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size);
DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
-#endif /* DUK_USE_DEBUG */
+#endif /* DUK_USE_DEBUG */
-#endif /* DUK_DEBUG_H_INCLUDED */
+#endif /* DUK_DEBUG_H_INCLUDED */
/* #include duk_error.h */
/*
* Error handling macros, assertion macro, error codes.
@@ -9234,8 +10059,8 @@ DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
* Error codes: defined in duktape.h
*
* Error codes are used as a shorthand to throw exceptions from inside
- * the implementation. The appropriate Ecmascript object is constructed
- * based on the code. Ecmascript code throws objects directly. The error
+ * the implementation. The appropriate ECMAScript object is constructed
+ * based on the code. ECMAScript code throws objects directly. The error
* codes are defined in the public API header because they are also used
* by calling code.
*/
@@ -9267,79 +10092,153 @@ DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
/* Because there are quite many call sites, pack error code (require at most
* 8-bit) into a single argument.
*/
-#define DUK_ERROR(thr,err,msg) do { \
- duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
- DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
+#define DUK_ERROR(thr, err, msg) \
+ do { \
+ duk_errcode_t duk__err = (err); \
+ duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
+ DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
+ DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
duk_err_handle_error((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
} while (0)
-#define DUK_ERROR_RAW(thr,file,line,err,msg) do { \
- duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
- DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
+#define DUK_ERROR_RAW(thr, file, line, err, msg) \
+ do { \
+ duk_errcode_t duk__err = (err); \
+ duk_int_t duk__line = (duk_int_t) (line); \
+ DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
+ DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
duk_err_handle_error((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
} while (0)
-#define DUK_ERROR_FMT1(thr,err,fmt,arg1) do { \
- duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
- DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
- duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
+#define DUK_ERROR_FMT1(thr, err, fmt, arg1) \
+ do { \
+ duk_errcode_t duk__err = (err); \
+ duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
+ DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
+ DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
+ duk_err_handle_error_fmt((thr), \
+ DUK_FILE_MACRO, \
+ (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), \
+ (fmt), \
+ (arg1)); \
} while (0)
-#define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) do { \
- duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
- DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
- duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
+#define DUK_ERROR_RAW_FMT1(thr, file, line, err, fmt, arg1) \
+ do { \
+ duk_errcode_t duk__err = (err); \
+ duk_int_t duk__line = (duk_int_t) (line); \
+ DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
+ DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
+ duk_err_handle_error_fmt((thr), \
+ (file), \
+ (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), \
+ (fmt), \
+ (arg1)); \
} while (0)
-#define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) do { \
- duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
- DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
- duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
+#define DUK_ERROR_FMT2(thr, err, fmt, arg1, arg2) \
+ do { \
+ duk_errcode_t duk__err = (err); \
+ duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
+ DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
+ DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
+ duk_err_handle_error_fmt((thr), \
+ DUK_FILE_MACRO, \
+ (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), \
+ (fmt), \
+ (arg1), \
+ (arg2)); \
} while (0)
-#define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) do { \
- duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
- DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
- duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
+#define DUK_ERROR_RAW_FMT2(thr, file, line, err, fmt, arg1, arg2) \
+ do { \
+ duk_errcode_t duk__err = (err); \
+ duk_int_t duk__line = (duk_int_t) (line); \
+ DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
+ DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
+ duk_err_handle_error_fmt((thr), \
+ (file), \
+ (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), \
+ (fmt), \
+ (arg1), \
+ (arg2)); \
} while (0)
-#define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) do { \
- duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
- DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
- duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
+#define DUK_ERROR_FMT3(thr, err, fmt, arg1, arg2, arg3) \
+ do { \
+ duk_errcode_t duk__err = (err); \
+ duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
+ DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
+ DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
+ duk_err_handle_error_fmt((thr), \
+ DUK_FILE_MACRO, \
+ (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), \
+ (fmt), \
+ (arg1), \
+ (arg2), \
+ (arg3)); \
} while (0)
-#define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) do { \
- duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
- DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
- duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
+#define DUK_ERROR_RAW_FMT3(thr, file, line, err, fmt, arg1, arg2, arg3) \
+ do { \
+ duk_errcode_t duk__err = (err); \
+ duk_int_t duk__line = (duk_int_t) (line); \
+ DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
+ DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
+ duk_err_handle_error_fmt((thr), \
+ (file), \
+ (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), \
+ (fmt), \
+ (arg1), \
+ (arg2), \
+ (arg3)); \
} while (0)
-#define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) do { \
- duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
- DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
- duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3), (arg4)); \
+#define DUK_ERROR_FMT4(thr, err, fmt, arg1, arg2, arg3, arg4) \
+ do { \
+ duk_errcode_t duk__err = (err); \
+ duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
+ DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
+ DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
+ duk_err_handle_error_fmt((thr), \
+ DUK_FILE_MACRO, \
+ (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), \
+ (fmt), \
+ (arg1), \
+ (arg2), \
+ (arg3), \
+ (arg4)); \
} while (0)
-#define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) do { \
- duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
- DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
- duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3), (arg4)); \
+#define DUK_ERROR_RAW_FMT4(thr, file, line, err, fmt, arg1, arg2, arg3, arg4) \
+ do { \
+ duk_errcode_t duk__err = (err); \
+ duk_int_t duk__line = (duk_int_t) (line); \
+ DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); \
+ DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
+ duk_err_handle_error_fmt((thr), \
+ (file), \
+ (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), \
+ (fmt), \
+ (arg1), \
+ (arg2), \
+ (arg3), \
+ (arg4)); \
} while (0)
-#else /* DUK_USE_VERBOSE_ERRORS */
+#else /* DUK_USE_VERBOSE_ERRORS */
-#define DUK_ERROR(thr,err,msg) duk_err_handle_error((thr), (err))
-#define DUK_ERROR_RAW(thr,file,line,err,msg) duk_err_handle_error((thr), (err))
+#define DUK_ERROR(thr, err, msg) duk_err_handle_error((thr), (err))
+#define DUK_ERROR_RAW(thr, file, line, err, msg) duk_err_handle_error((thr), (err))
-#define DUK_ERROR_FMT1(thr,err,fmt,arg1) DUK_ERROR((thr),(err),(fmt))
-#define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
+#define DUK_ERROR_FMT1(thr, err, fmt, arg1) DUK_ERROR((thr), (err), (fmt))
+#define DUK_ERROR_RAW_FMT1(thr, file, line, err, fmt, arg1) DUK_ERROR_RAW((thr), (file), (line), (err), (fmt))
-#define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) DUK_ERROR((thr),(err),(fmt))
-#define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
+#define DUK_ERROR_FMT2(thr, err, fmt, arg1, arg2) DUK_ERROR((thr), (err), (fmt))
+#define DUK_ERROR_RAW_FMT2(thr, file, line, err, fmt, arg1, arg2) DUK_ERROR_RAW((thr), (file), (line), (err), (fmt))
-#define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) DUK_ERROR((thr),(err),(fmt))
-#define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
+#define DUK_ERROR_FMT3(thr, err, fmt, arg1, arg2, arg3) DUK_ERROR((thr), (err), (fmt))
+#define DUK_ERROR_RAW_FMT3(thr, file, line, err, fmt, arg1, arg2, arg3) DUK_ERROR_RAW((thr), (file), (line), (err), (fmt))
-#define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR((thr),(err),(fmt))
-#define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
+#define DUK_ERROR_FMT4(thr, err, fmt, arg1, arg2, arg3, arg4) DUK_ERROR((thr), (err), (fmt))
+#define DUK_ERROR_RAW_FMT4(thr, file, line, err, fmt, arg1, arg2, arg3, arg4) DUK_ERROR_RAW((thr), (file), (line), (err), (fmt))
-#endif /* DUK_USE_VERBOSE_ERRORS */
+#endif /* DUK_USE_VERBOSE_ERRORS */
/*
* Fatal error without context
@@ -9347,8 +10246,7 @@ DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
* The macro is an expression to make it compatible with DUK_ASSERT_EXPR().
*/
-#define DUK_FATAL_WITHOUT_CONTEXT(msg) \
- duk_default_fatal_handler(NULL, (msg))
+#define DUK_FATAL_WITHOUT_CONTEXT(msg) duk_default_fatal_handler(NULL, (msg))
/*
* Error throwing helpers
@@ -9373,188 +10271,252 @@ DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
* vs. non-paranoid distinction affects only a few specific errors.
*/
#if defined(DUK_USE_PARANOID_ERRORS)
-#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
+#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, expectname, lowmemstr) \
+ do { \
duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \
} while (0)
-#else /* DUK_USE_PARANOID_ERRORS */
-#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
+#else /* DUK_USE_PARANOID_ERRORS */
+#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, expectname, lowmemstr) \
+ do { \
duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \
} while (0)
-#endif /* DUK_USE_PARANOID_ERRORS */
+#endif /* DUK_USE_PARANOID_ERRORS */
-#define DUK_ERROR_INTERNAL(thr) do { \
+#define DUK_ERROR_INTERNAL(thr) \
+ do { \
duk_err_error_internal((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
} while (0)
-#define DUK_DCERROR_INTERNAL(thr) do { \
+#define DUK_DCERROR_INTERNAL(thr) \
+ do { \
DUK_ERROR_INTERNAL((thr)); \
return 0; \
} while (0)
-#define DUK_ERROR_ALLOC_FAILED(thr) do { \
+#define DUK_ERROR_ALLOC_FAILED(thr) \
+ do { \
duk_err_error_alloc_failed((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
} while (0)
-#define DUK_ERROR_UNSUPPORTED(thr) do { \
+#define DUK_ERROR_UNSUPPORTED(thr) \
+ do { \
DUK_ERROR((thr), DUK_ERR_ERROR, DUK_STR_UNSUPPORTED); \
} while (0)
-#define DUK_ERROR_ERROR(thr,msg) do { \
+#define DUK_DCERROR_UNSUPPORTED(thr) \
+ do { \
+ DUK_ERROR_UNSUPPORTED((thr)); \
+ return 0; \
+ } while (0)
+#define DUK_ERROR_ERROR(thr, msg) \
+ do { \
duk_err_error((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
} while (0)
-#define DUK_ERROR_RANGE_INDEX(thr,idx) do { \
+#define DUK_ERROR_RANGE_INDEX(thr, idx) \
+ do { \
duk_err_range_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx)); \
} while (0)
-#define DUK_ERROR_RANGE_PUSH_BEYOND(thr) do { \
+#define DUK_ERROR_RANGE_PUSH_BEYOND(thr) \
+ do { \
duk_err_range_push_beyond((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
} while (0)
-#define DUK_ERROR_RANGE_INVALID_ARGS(thr) do { \
+#define DUK_ERROR_RANGE_INVALID_ARGS(thr) \
+ do { \
DUK_ERROR_RANGE((thr), DUK_STR_INVALID_ARGS); \
} while (0)
-#define DUK_DCERROR_RANGE_INVALID_ARGS(thr) do { \
+#define DUK_DCERROR_RANGE_INVALID_ARGS(thr) \
+ do { \
DUK_ERROR_RANGE_INVALID_ARGS((thr)); \
return 0; \
} while (0)
-#define DUK_ERROR_RANGE_INVALID_COUNT(thr) do { \
+#define DUK_ERROR_RANGE_INVALID_COUNT(thr) \
+ do { \
DUK_ERROR_RANGE((thr), DUK_STR_INVALID_COUNT); \
} while (0)
-#define DUK_DCERROR_RANGE_INVALID_COUNT(thr) do { \
+#define DUK_DCERROR_RANGE_INVALID_COUNT(thr) \
+ do { \
DUK_ERROR_RANGE_INVALID_COUNT((thr)); \
return 0; \
} while (0)
-#define DUK_ERROR_RANGE_INVALID_LENGTH(thr) do { \
+#define DUK_ERROR_RANGE_INVALID_LENGTH(thr) \
+ do { \
DUK_ERROR_RANGE((thr), DUK_STR_INVALID_LENGTH); \
} while (0)
-#define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) do { \
+#define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) \
+ do { \
DUK_ERROR_RANGE_INVALID_LENGTH((thr)); \
return 0; \
} while (0)
-#define DUK_ERROR_RANGE(thr,msg) do { \
+#define DUK_ERROR_RANGE(thr, msg) \
+ do { \
duk_err_range((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
} while (0)
-#define DUK_ERROR_EVAL(thr,msg) do { \
+#define DUK_ERROR_EVAL(thr, msg) \
+ do { \
DUK_ERROR((thr), DUK_ERR_EVAL_ERROR, (msg)); \
} while (0)
-#define DUK_ERROR_REFERENCE(thr,msg) do { \
+#define DUK_ERROR_REFERENCE(thr, msg) \
+ do { \
DUK_ERROR((thr), DUK_ERR_REFERENCE_ERROR, (msg)); \
} while (0)
-#define DUK_ERROR_SYNTAX(thr,msg) do { \
+#define DUK_ERROR_SYNTAX(thr, msg) \
+ do { \
DUK_ERROR((thr), DUK_ERR_SYNTAX_ERROR, (msg)); \
} while (0)
-#define DUK_ERROR_TYPE_INVALID_ARGS(thr) do { \
+#define DUK_ERROR_TYPE_INVALID_ARGS(thr) \
+ do { \
duk_err_type_invalid_args((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
} while (0)
-#define DUK_DCERROR_TYPE_INVALID_ARGS(thr) do { \
+#define DUK_DCERROR_TYPE_INVALID_ARGS(thr) \
+ do { \
DUK_ERROR_TYPE_INVALID_ARGS((thr)); \
return 0; \
} while (0)
-#define DUK_ERROR_TYPE_INVALID_STATE(thr) do { \
+#define DUK_ERROR_TYPE_INVALID_STATE(thr) \
+ do { \
duk_err_type_invalid_state((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
} while (0)
-#define DUK_DCERROR_TYPE_INVALID_STATE(thr) do { \
+#define DUK_DCERROR_TYPE_INVALID_STATE(thr) \
+ do { \
DUK_ERROR_TYPE_INVALID_STATE((thr)); \
return 0; \
} while (0)
-#define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
+#define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) \
+ do { \
duk_err_type_invalid_trap_result((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
} while (0)
-#define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
+#define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) \
+ do { \
DUK_ERROR_TYPE((thr), DUK_STR_INVALID_TRAP_RESULT); \
} while (0)
-#define DUK_ERROR_TYPE(thr,msg) do { \
+#define DUK_ERROR_TYPE(thr, msg) \
+ do { \
DUK_ERROR((thr), DUK_ERR_TYPE_ERROR, (msg)); \
} while (0)
-#define DUK_ERROR_URI(thr,msg) do { \
+#define DUK_ERROR_URI(thr, msg) \
+ do { \
DUK_ERROR((thr), DUK_ERR_URI_ERROR, (msg)); \
} while (0)
-#else /* DUK_USE_VERBOSE_ERRORS */
+#else /* DUK_USE_VERBOSE_ERRORS */
/* Non-verbose errors for low memory targets: no file, line, or message. */
-#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
+#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, expectname, lowmemstr) \
+ do { \
duk_err_type((thr)); \
} while (0)
-#define DUK_ERROR_INTERNAL(thr) do { \
+#define DUK_ERROR_INTERNAL(thr) \
+ do { \
duk_err_error((thr)); \
} while (0)
-#define DUK_DCERROR_INTERNAL(thr) do { \
+#define DUK_DCERROR_INTERNAL(thr) \
+ do { \
DUK_UNREF((thr)); \
return DUK_RET_ERROR; \
} while (0)
-#define DUK_ERROR_ALLOC_FAILED(thr) do { \
+#define DUK_ERROR_ALLOC_FAILED(thr) \
+ do { \
duk_err_error((thr)); \
} while (0)
-#define DUK_ERROR_UNSUPPORTED(thr) do { \
+#define DUK_ERROR_UNSUPPORTED(thr) \
+ do { \
duk_err_error((thr)); \
} while (0)
-#define DUK_ERROR_ERROR(thr,msg) do { \
+#define DUK_DCERROR_UNSUPPORTED(thr) \
+ do { \
+ DUK_UNREF((thr)); \
+ return DUK_RET_ERROR; \
+ } while (0)
+#define DUK_ERROR_ERROR(thr, msg) \
+ do { \
duk_err_error((thr)); \
} while (0)
-#define DUK_ERROR_RANGE_INDEX(thr,idx) do { \
+#define DUK_ERROR_RANGE_INDEX(thr, idx) \
+ do { \
duk_err_range((thr)); \
} while (0)
-#define DUK_ERROR_RANGE_PUSH_BEYOND(thr) do { \
+#define DUK_ERROR_RANGE_PUSH_BEYOND(thr) \
+ do { \
duk_err_range((thr)); \
} while (0)
-#define DUK_ERROR_RANGE_INVALID_ARGS(thr) do { \
+#define DUK_ERROR_RANGE_INVALID_ARGS(thr) \
+ do { \
duk_err_range((thr)); \
} while (0)
-#define DUK_DCERROR_RANGE_INVALID_ARGS(thr) do { \
+#define DUK_DCERROR_RANGE_INVALID_ARGS(thr) \
+ do { \
DUK_UNREF((thr)); \
return DUK_RET_RANGE_ERROR; \
} while (0)
-#define DUK_ERROR_RANGE_INVALID_COUNT(thr) do { \
+#define DUK_ERROR_RANGE_INVALID_COUNT(thr) \
+ do { \
duk_err_range((thr)); \
} while (0)
-#define DUK_DCERROR_RANGE_INVALID_COUNT(thr) do { \
+#define DUK_DCERROR_RANGE_INVALID_COUNT(thr) \
+ do { \
DUK_UNREF((thr)); \
return DUK_RET_RANGE_ERROR; \
} while (0)
-#define DUK_ERROR_RANGE_INVALID_LENGTH(thr) do { \
+#define DUK_ERROR_RANGE_INVALID_LENGTH(thr) \
+ do { \
duk_err_range((thr)); \
} while (0)
-#define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) do { \
+#define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) \
+ do { \
DUK_UNREF((thr)); \
return DUK_RET_RANGE_ERROR; \
} while (0)
-#define DUK_ERROR_RANGE(thr,msg) do { \
+#define DUK_ERROR_RANGE(thr, msg) \
+ do { \
duk_err_range((thr)); \
} while (0)
-#define DUK_ERROR_EVAL(thr,msg) do { \
+#define DUK_ERROR_EVAL(thr, msg) \
+ do { \
duk_err_eval((thr)); \
} while (0)
-#define DUK_ERROR_REFERENCE(thr,msg) do { \
+#define DUK_ERROR_REFERENCE(thr, msg) \
+ do { \
duk_err_reference((thr)); \
} while (0)
-#define DUK_ERROR_SYNTAX(thr,msg) do { \
+#define DUK_ERROR_SYNTAX(thr, msg) \
+ do { \
duk_err_syntax((thr)); \
} while (0)
-#define DUK_ERROR_TYPE_INVALID_ARGS(thr) do { \
+#define DUK_ERROR_TYPE_INVALID_ARGS(thr) \
+ do { \
duk_err_type((thr)); \
} while (0)
-#define DUK_DCERROR_TYPE_INVALID_ARGS(thr) do { \
+#define DUK_DCERROR_TYPE_INVALID_ARGS(thr) \
+ do { \
DUK_UNREF((thr)); \
return DUK_RET_TYPE_ERROR; \
} while (0)
-#define DUK_ERROR_TYPE_INVALID_STATE(thr) do { \
+#define DUK_ERROR_TYPE_INVALID_STATE(thr) \
+ do { \
duk_err_type((thr)); \
} while (0)
-#define DUK_DCERROR_TYPE_INVALID_STATE(thr) do { \
+#define DUK_DCERROR_TYPE_INVALID_STATE(thr) \
+ do { \
duk_err_type((thr)); \
} while (0)
-#define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
+#define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) \
+ do { \
duk_err_type((thr)); \
} while (0)
-#define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
+#define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) \
+ do { \
DUK_UNREF((thr)); \
return DUK_RET_TYPE_ERROR; \
} while (0)
-#define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
+#define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) \
+ do { \
duk_err_type((thr)); \
} while (0)
-#define DUK_ERROR_TYPE(thr,msg) do { \
+#define DUK_ERROR_TYPE(thr, msg) \
+ do { \
duk_err_type((thr)); \
} while (0)
-#define DUK_ERROR_URI(thr,msg) do { \
+#define DUK_ERROR_URI(thr, msg) \
+ do { \
duk_err_uri((thr)); \
} while (0)
-#endif /* DUK_USE_VERBOSE_ERRORS */
+#endif /* DUK_USE_VERBOSE_ERRORS */
/*
* Assert macro: failure causes a fatal error.
@@ -9572,63 +10534,72 @@ DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
* we don't care about assertion text size because they're not used in production
* builds.
*/
-#define DUK_ASSERT(x) do { \
- if (!(x)) { \
- DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x \
- " (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"); \
- } \
+#define DUK_ASSERT(x) \
+ do { \
+ if (!(x)) { \
+ DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x " (" DUK_FILE_MACRO \
+ ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"); \
+ } \
} while (0)
/* Assertion compatible inside a comma expression, evaluates to void. */
#define DUK_ASSERT_EXPR(x) \
- ((void) ((x) ? 0 : (DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x \
- " (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"), 0)))
+ ((void) ((x) ? 0 : \
+ (DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x " (" DUK_FILE_MACRO \
+ ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"), \
+ 0)))
-#else /* DUK_USE_ASSERTIONS */
+#else /* DUK_USE_ASSERTIONS */
-#define DUK_ASSERT(x) do { /* assertion omitted */ } while (0)
+#define DUK_ASSERT(x) \
+ do { /* assertion omitted */ \
+ } while (0)
-#define DUK_ASSERT_EXPR(x) ((void) 0)
+#define DUK_ASSERT_EXPR(x) ((void) 0)
-#endif /* DUK_USE_ASSERTIONS */
+#endif /* DUK_USE_ASSERTIONS */
/* this variant is used when an assert would generate a compile warning by
* being always true (e.g. >= 0 comparison for an unsigned value
*/
-#define DUK_ASSERT_DISABLE(x) do { /* assertion disabled */ } while (0)
+#define DUK_ASSERT_DISABLE(x) \
+ do { /* assertion disabled */ \
+ } while (0)
/*
* Assertion helpers
*/
#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
-#define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h) do { \
+#define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h) \
+ do { \
DUK_ASSERT((h) == NULL || DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) (h)) > 0); \
} while (0)
-#define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv) do { \
+#define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv) \
+ do { \
if ((tv) != NULL && DUK_TVAL_IS_HEAP_ALLOCATED((tv))) { \
DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(DUK_TVAL_GET_HEAPHDR((tv))) > 0); \
} \
} while (0)
#else
-#define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h) /* no refcount check */
-#define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv) /* no refcount check */
+#define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h) /* no refcount check */
+#define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv) /* no refcount check */
#endif
-#define DUK_ASSERT_TOP(ctx,n) DUK_ASSERT((duk_idx_t) duk_get_top((ctx)) == (duk_idx_t) (n))
+#define DUK_ASSERT_TOP(ctx, n) DUK_ASSERT((duk_idx_t) duk_get_top((ctx)) == (duk_idx_t) (n))
#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_PACKED_TVAL)
-#define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval) do { \
+#define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval) \
+ do { \
duk_double_union duk__assert_tmp_du; \
duk__assert_tmp_du.d = (dval); \
DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&duk__assert_tmp_du)); \
} while (0)
#else
-#define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval) /* nop */
+#define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval) /* nop */
#endif
-#define DUK_ASSERT_VS_SPACE(thr) \
- DUK_ASSERT(thr->valstack_top < thr->valstack_end)
+#define DUK_ASSERT_VS_SPACE(thr) DUK_ASSERT(thr->valstack_top < thr->valstack_end)
/*
* Helper to initialize a memory area (e.g. struct) with garbage when
@@ -9636,11 +10607,14 @@ DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
*/
#if defined(DUK_USE_ASSERTIONS)
-#define DUK_ASSERT_SET_GARBAGE(ptr,size) do { \
- DUK_MEMSET((void *) (ptr), 0x5a, size); \
+#define DUK_ASSERT_SET_GARBAGE(ptr, size) \
+ do { \
+ duk_memset_unsafe((void *) (ptr), 0x5a, size); \
} while (0)
#else
-#define DUK_ASSERT_SET_GARBAGE(ptr,size) do {} while (0)
+#define DUK_ASSERT_SET_GARBAGE(ptr, size) \
+ do { \
+ } while (0)
#endif
/*
@@ -9651,16 +10625,18 @@ DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
* or (b) Duktape calls which involve extending the valstack (e.g. getter call).
*/
-#define DUK_VALSTACK_ASSERT_EXTRA 5 /* this is added to checks to allow for Duktape
- * API calls in addition to function's own use
- */
+#define DUK_VALSTACK_ASSERT_EXTRA \
+ 5 /* this is added to checks to allow for Duktape \
+ * API calls in addition to function's own use \
+ */
#if defined(DUK_USE_ASSERTIONS)
-#define DUK_ASSERT_VALSTACK_SPACE(thr,n) do { \
+#define DUK_ASSERT_VALSTACK_SPACE(thr, n) \
+ do { \
DUK_ASSERT((thr) != NULL); \
DUK_ASSERT((thr)->valstack_end - (thr)->valstack_top >= (n) + DUK_VALSTACK_ASSERT_EXTRA); \
} while (0)
#else
-#define DUK_ASSERT_VALSTACK_SPACE(thr,n) /* no valstack space check */
+#define DUK_ASSERT_VALSTACK_SPACE(thr, n) /* no valstack space check */
#endif
/*
@@ -9668,25 +10644,35 @@ DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
*/
#if defined(DUK_USE_VERBOSE_ERRORS)
-DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg));
-DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error_fmt(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *fmt, ...));
-#else /* DUK_USE_VERBOSE_ERRORS */
+DUK_NORETURN(
+ DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg));
+DUK_NORETURN(DUK_INTERNAL_DECL void
+ duk_err_handle_error_fmt(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *fmt, ...));
+#else /* DUK_USE_VERBOSE_ERRORS */
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code));
-#endif /* DUK_USE_VERBOSE_ERRORS */
+#endif /* DUK_USE_VERBOSE_ERRORS */
#if defined(DUK_USE_VERBOSE_ERRORS)
-DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line));
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr,
+ duk_errcode_t code,
+ const char *msg,
+ const char *filename,
+ duk_int_t line));
#else
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code));
#endif
DUK_NORETURN(DUK_INTERNAL_DECL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc));
-#define DUK_AUGMENT_FLAG_NOBLAME_FILELINE (1U << 0) /* if set, don't blame C file/line for .fileName and .lineNumber */
-#define DUK_AUGMENT_FLAG_SKIP_ONE (1U << 1) /* if set, skip topmost activation in traceback construction */
+#define DUK_AUGMENT_FLAG_NOBLAME_FILELINE (1U << 0) /* if set, don't blame C file/line for .fileName and .lineNumber */
+#define DUK_AUGMENT_FLAG_SKIP_ONE (1U << 1) /* if set, skip topmost activation in traceback construction */
#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
-DUK_INTERNAL_DECL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *filename, duk_int_t line, duk_small_uint_t flags);
+DUK_INTERNAL_DECL void duk_err_augment_error_create(duk_hthread *thr,
+ duk_hthread *thr_callstack,
+ const char *filename,
+ duk_int_t line,
+ duk_small_uint_t flags);
#endif
#if defined(DUK_USE_AUGMENT_ERROR_THROW)
DUK_INTERNAL_DECL void duk_err_augment_error_throw(duk_hthread *thr);
@@ -9694,20 +10680,31 @@ DUK_INTERNAL_DECL void duk_err_augment_error_throw(duk_hthread *thr);
#if defined(DUK_USE_VERBOSE_ERRORS)
#if defined(DUK_USE_PARANOID_ERRORS)
-DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name));
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(duk_hthread *thr,
+ const char *filename,
+ duk_int_t linenumber,
+ duk_idx_t idx,
+ const char *expect_name));
#else
-DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name));
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(duk_hthread *thr,
+ const char *filename,
+ duk_int_t linenumber,
+ duk_idx_t idx,
+ const char *expect_name));
#endif
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber));
-DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
-DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx));
+DUK_NORETURN(
+ DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
+DUK_NORETURN(
+ DUK_INTERNAL_DECL void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber));
-DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
+DUK_NORETURN(
+ DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber));
-#else /* DUK_VERBOSE_ERRORS */
+#else /* DUK_VERBOSE_ERRORS */
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_eval(duk_hthread *thr));
@@ -9728,7 +10725,7 @@ DUK_INTERNAL_DECL void duk_err_check_debugger_integration(duk_hthread *thr);
DUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t err_code);
-#endif /* DUK_ERROR_H_INCLUDED */
+#endif /* DUK_ERROR_H_INCLUDED */
/* #include duk_unicode.h */
/*
* Unicode helpers
@@ -9741,10 +10738,10 @@ DUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, d
* UTF-8 / XUTF-8 / CESU-8 constants
*/
-#define DUK_UNICODE_MAX_XUTF8_LENGTH 7 /* up to 36 bit codepoints */
-#define DUK_UNICODE_MAX_XUTF8_BMP_LENGTH 3 /* all codepoints up to U+FFFF */
-#define DUK_UNICODE_MAX_CESU8_LENGTH 6 /* all codepoints up to U+10FFFF */
-#define DUK_UNICODE_MAX_CESU8_BMP_LENGTH 3 /* all codepoints up to U+FFFF */
+#define DUK_UNICODE_MAX_XUTF8_LENGTH 7 /* up to 36 bit codepoints */
+#define DUK_UNICODE_MAX_XUTF8_BMP_LENGTH 3 /* all codepoints up to U+FFFF */
+#define DUK_UNICODE_MAX_CESU8_LENGTH 6 /* all codepoints up to U+10FFFF */
+#define DUK_UNICODE_MAX_CESU8_BMP_LENGTH 3 /* all codepoints up to U+FFFF */
/*
* Useful Unicode codepoints
@@ -9753,9 +10750,11 @@ DUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, d
* in comparisons.
*/
-#define DUK_UNICODE_CP_ZWNJ 0x200cL /* zero-width non-joiner */
-#define DUK_UNICODE_CP_ZWJ 0x200dL /* zero-width joiner */
-#define DUK_UNICODE_CP_REPLACEMENT_CHARACTER 0xfffdL /* http://en.wikipedia.org/wiki/Replacement_character#Replacement_character */
+#define DUK_UNICODE_CP_ZWNJ 0x200cL /* zero-width non-joiner */
+#define DUK_UNICODE_CP_ZWJ 0x200dL /* zero-width joiner */
+#define DUK_UNICODE_CP_REPLACEMENT_CHARACTER \
+ 0xfffdL /* http://en.wikipedia.org/wiki/Replacement_character#Replacement_character \
+ */
/*
* ASCII character constants
@@ -9768,134 +10767,134 @@ DUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, d
* http://en.wikipedia.org/wiki/ASCII
*/
-#define DUK_ASC_NUL 0x00
-#define DUK_ASC_SOH 0x01
-#define DUK_ASC_STX 0x02
-#define DUK_ASC_ETX 0x03
-#define DUK_ASC_EOT 0x04
-#define DUK_ASC_ENQ 0x05
-#define DUK_ASC_ACK 0x06
-#define DUK_ASC_BEL 0x07
-#define DUK_ASC_BS 0x08
-#define DUK_ASC_HT 0x09
-#define DUK_ASC_LF 0x0a
-#define DUK_ASC_VT 0x0b
-#define DUK_ASC_FF 0x0c
-#define DUK_ASC_CR 0x0d
-#define DUK_ASC_SO 0x0e
-#define DUK_ASC_SI 0x0f
-#define DUK_ASC_DLE 0x10
-#define DUK_ASC_DC1 0x11
-#define DUK_ASC_DC2 0x12
-#define DUK_ASC_DC3 0x13
-#define DUK_ASC_DC4 0x14
-#define DUK_ASC_NAK 0x15
-#define DUK_ASC_SYN 0x16
-#define DUK_ASC_ETB 0x17
-#define DUK_ASC_CAN 0x18
-#define DUK_ASC_EM 0x19
-#define DUK_ASC_SUB 0x1a
-#define DUK_ASC_ESC 0x1b
-#define DUK_ASC_FS 0x1c
-#define DUK_ASC_GS 0x1d
-#define DUK_ASC_RS 0x1e
-#define DUK_ASC_US 0x1f
-#define DUK_ASC_SPACE 0x20
-#define DUK_ASC_EXCLAMATION 0x21
-#define DUK_ASC_DOUBLEQUOTE 0x22
-#define DUK_ASC_HASH 0x23
-#define DUK_ASC_DOLLAR 0x24
-#define DUK_ASC_PERCENT 0x25
-#define DUK_ASC_AMP 0x26
-#define DUK_ASC_SINGLEQUOTE 0x27
-#define DUK_ASC_LPAREN 0x28
-#define DUK_ASC_RPAREN 0x29
-#define DUK_ASC_STAR 0x2a
-#define DUK_ASC_PLUS 0x2b
-#define DUK_ASC_COMMA 0x2c
-#define DUK_ASC_MINUS 0x2d
-#define DUK_ASC_PERIOD 0x2e
-#define DUK_ASC_SLASH 0x2f
-#define DUK_ASC_0 0x30
-#define DUK_ASC_1 0x31
-#define DUK_ASC_2 0x32
-#define DUK_ASC_3 0x33
-#define DUK_ASC_4 0x34
-#define DUK_ASC_5 0x35
-#define DUK_ASC_6 0x36
-#define DUK_ASC_7 0x37
-#define DUK_ASC_8 0x38
-#define DUK_ASC_9 0x39
-#define DUK_ASC_COLON 0x3a
-#define DUK_ASC_SEMICOLON 0x3b
-#define DUK_ASC_LANGLE 0x3c
-#define DUK_ASC_EQUALS 0x3d
-#define DUK_ASC_RANGLE 0x3e
-#define DUK_ASC_QUESTION 0x3f
-#define DUK_ASC_ATSIGN 0x40
-#define DUK_ASC_UC_A 0x41
-#define DUK_ASC_UC_B 0x42
-#define DUK_ASC_UC_C 0x43
-#define DUK_ASC_UC_D 0x44
-#define DUK_ASC_UC_E 0x45
-#define DUK_ASC_UC_F 0x46
-#define DUK_ASC_UC_G 0x47
-#define DUK_ASC_UC_H 0x48
-#define DUK_ASC_UC_I 0x49
-#define DUK_ASC_UC_J 0x4a
-#define DUK_ASC_UC_K 0x4b
-#define DUK_ASC_UC_L 0x4c
-#define DUK_ASC_UC_M 0x4d
-#define DUK_ASC_UC_N 0x4e
-#define DUK_ASC_UC_O 0x4f
-#define DUK_ASC_UC_P 0x50
-#define DUK_ASC_UC_Q 0x51
-#define DUK_ASC_UC_R 0x52
-#define DUK_ASC_UC_S 0x53
-#define DUK_ASC_UC_T 0x54
-#define DUK_ASC_UC_U 0x55
-#define DUK_ASC_UC_V 0x56
-#define DUK_ASC_UC_W 0x57
-#define DUK_ASC_UC_X 0x58
-#define DUK_ASC_UC_Y 0x59
-#define DUK_ASC_UC_Z 0x5a
-#define DUK_ASC_LBRACKET 0x5b
-#define DUK_ASC_BACKSLASH 0x5c
-#define DUK_ASC_RBRACKET 0x5d
-#define DUK_ASC_CARET 0x5e
-#define DUK_ASC_UNDERSCORE 0x5f
-#define DUK_ASC_GRAVE 0x60
-#define DUK_ASC_LC_A 0x61
-#define DUK_ASC_LC_B 0x62
-#define DUK_ASC_LC_C 0x63
-#define DUK_ASC_LC_D 0x64
-#define DUK_ASC_LC_E 0x65
-#define DUK_ASC_LC_F 0x66
-#define DUK_ASC_LC_G 0x67
-#define DUK_ASC_LC_H 0x68
-#define DUK_ASC_LC_I 0x69
-#define DUK_ASC_LC_J 0x6a
-#define DUK_ASC_LC_K 0x6b
-#define DUK_ASC_LC_L 0x6c
-#define DUK_ASC_LC_M 0x6d
-#define DUK_ASC_LC_N 0x6e
-#define DUK_ASC_LC_O 0x6f
-#define DUK_ASC_LC_P 0x70
-#define DUK_ASC_LC_Q 0x71
-#define DUK_ASC_LC_R 0x72
-#define DUK_ASC_LC_S 0x73
-#define DUK_ASC_LC_T 0x74
-#define DUK_ASC_LC_U 0x75
-#define DUK_ASC_LC_V 0x76
-#define DUK_ASC_LC_W 0x77
-#define DUK_ASC_LC_X 0x78
-#define DUK_ASC_LC_Y 0x79
-#define DUK_ASC_LC_Z 0x7a
-#define DUK_ASC_LCURLY 0x7b
-#define DUK_ASC_PIPE 0x7c
-#define DUK_ASC_RCURLY 0x7d
-#define DUK_ASC_TILDE 0x7e
-#define DUK_ASC_DEL 0x7f
+#define DUK_ASC_NUL 0x00
+#define DUK_ASC_SOH 0x01
+#define DUK_ASC_STX 0x02
+#define DUK_ASC_ETX 0x03
+#define DUK_ASC_EOT 0x04
+#define DUK_ASC_ENQ 0x05
+#define DUK_ASC_ACK 0x06
+#define DUK_ASC_BEL 0x07
+#define DUK_ASC_BS 0x08
+#define DUK_ASC_HT 0x09
+#define DUK_ASC_LF 0x0a
+#define DUK_ASC_VT 0x0b
+#define DUK_ASC_FF 0x0c
+#define DUK_ASC_CR 0x0d
+#define DUK_ASC_SO 0x0e
+#define DUK_ASC_SI 0x0f
+#define DUK_ASC_DLE 0x10
+#define DUK_ASC_DC1 0x11
+#define DUK_ASC_DC2 0x12
+#define DUK_ASC_DC3 0x13
+#define DUK_ASC_DC4 0x14
+#define DUK_ASC_NAK 0x15
+#define DUK_ASC_SYN 0x16
+#define DUK_ASC_ETB 0x17
+#define DUK_ASC_CAN 0x18
+#define DUK_ASC_EM 0x19
+#define DUK_ASC_SUB 0x1a
+#define DUK_ASC_ESC 0x1b
+#define DUK_ASC_FS 0x1c
+#define DUK_ASC_GS 0x1d
+#define DUK_ASC_RS 0x1e
+#define DUK_ASC_US 0x1f
+#define DUK_ASC_SPACE 0x20
+#define DUK_ASC_EXCLAMATION 0x21
+#define DUK_ASC_DOUBLEQUOTE 0x22
+#define DUK_ASC_HASH 0x23
+#define DUK_ASC_DOLLAR 0x24
+#define DUK_ASC_PERCENT 0x25
+#define DUK_ASC_AMP 0x26
+#define DUK_ASC_SINGLEQUOTE 0x27
+#define DUK_ASC_LPAREN 0x28
+#define DUK_ASC_RPAREN 0x29
+#define DUK_ASC_STAR 0x2a
+#define DUK_ASC_PLUS 0x2b
+#define DUK_ASC_COMMA 0x2c
+#define DUK_ASC_MINUS 0x2d
+#define DUK_ASC_PERIOD 0x2e
+#define DUK_ASC_SLASH 0x2f
+#define DUK_ASC_0 0x30
+#define DUK_ASC_1 0x31
+#define DUK_ASC_2 0x32
+#define DUK_ASC_3 0x33
+#define DUK_ASC_4 0x34
+#define DUK_ASC_5 0x35
+#define DUK_ASC_6 0x36
+#define DUK_ASC_7 0x37
+#define DUK_ASC_8 0x38
+#define DUK_ASC_9 0x39
+#define DUK_ASC_COLON 0x3a
+#define DUK_ASC_SEMICOLON 0x3b
+#define DUK_ASC_LANGLE 0x3c
+#define DUK_ASC_EQUALS 0x3d
+#define DUK_ASC_RANGLE 0x3e
+#define DUK_ASC_QUESTION 0x3f
+#define DUK_ASC_ATSIGN 0x40
+#define DUK_ASC_UC_A 0x41
+#define DUK_ASC_UC_B 0x42
+#define DUK_ASC_UC_C 0x43
+#define DUK_ASC_UC_D 0x44
+#define DUK_ASC_UC_E 0x45
+#define DUK_ASC_UC_F 0x46
+#define DUK_ASC_UC_G 0x47
+#define DUK_ASC_UC_H 0x48
+#define DUK_ASC_UC_I 0x49
+#define DUK_ASC_UC_J 0x4a
+#define DUK_ASC_UC_K 0x4b
+#define DUK_ASC_UC_L 0x4c
+#define DUK_ASC_UC_M 0x4d
+#define DUK_ASC_UC_N 0x4e
+#define DUK_ASC_UC_O 0x4f
+#define DUK_ASC_UC_P 0x50
+#define DUK_ASC_UC_Q 0x51
+#define DUK_ASC_UC_R 0x52
+#define DUK_ASC_UC_S 0x53
+#define DUK_ASC_UC_T 0x54
+#define DUK_ASC_UC_U 0x55
+#define DUK_ASC_UC_V 0x56
+#define DUK_ASC_UC_W 0x57
+#define DUK_ASC_UC_X 0x58
+#define DUK_ASC_UC_Y 0x59
+#define DUK_ASC_UC_Z 0x5a
+#define DUK_ASC_LBRACKET 0x5b
+#define DUK_ASC_BACKSLASH 0x5c
+#define DUK_ASC_RBRACKET 0x5d
+#define DUK_ASC_CARET 0x5e
+#define DUK_ASC_UNDERSCORE 0x5f
+#define DUK_ASC_GRAVE 0x60
+#define DUK_ASC_LC_A 0x61
+#define DUK_ASC_LC_B 0x62
+#define DUK_ASC_LC_C 0x63
+#define DUK_ASC_LC_D 0x64
+#define DUK_ASC_LC_E 0x65
+#define DUK_ASC_LC_F 0x66
+#define DUK_ASC_LC_G 0x67
+#define DUK_ASC_LC_H 0x68
+#define DUK_ASC_LC_I 0x69
+#define DUK_ASC_LC_J 0x6a
+#define DUK_ASC_LC_K 0x6b
+#define DUK_ASC_LC_L 0x6c
+#define DUK_ASC_LC_M 0x6d
+#define DUK_ASC_LC_N 0x6e
+#define DUK_ASC_LC_O 0x6f
+#define DUK_ASC_LC_P 0x70
+#define DUK_ASC_LC_Q 0x71
+#define DUK_ASC_LC_R 0x72
+#define DUK_ASC_LC_S 0x73
+#define DUK_ASC_LC_T 0x74
+#define DUK_ASC_LC_U 0x75
+#define DUK_ASC_LC_V 0x76
+#define DUK_ASC_LC_W 0x77
+#define DUK_ASC_LC_X 0x78
+#define DUK_ASC_LC_Y 0x79
+#define DUK_ASC_LC_Z 0x7a
+#define DUK_ASC_LCURLY 0x7b
+#define DUK_ASC_PIPE 0x7c
+#define DUK_ASC_RCURLY 0x7d
+#define DUK_ASC_TILDE 0x7e
+#define DUK_ASC_DEL 0x7f
/*
* Miscellaneous
@@ -9904,7 +10903,7 @@ DUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, d
/* Uppercase A is 0x41, lowercase a is 0x61; OR 0x20 to convert uppercase
* to lowercase.
*/
-#define DUK_LOWERCASE_CHAR_ASCII(x) ((x) | 0x20)
+#define DUK_LOWERCASE_CHAR_ASCII(x) ((x) | 0x20)
/*
* Unicode tables
@@ -9915,7 +10914,7 @@ DUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, d
* Automatically generated by extract_chars.py, do not edit!
*/
-extern const duk_uint8_t duk_unicode_ids_noa[1036];
+extern const duk_uint8_t duk_unicode_ids_noa[1116];
#else
/*
* Automatically generated by extract_chars.py, do not edit!
@@ -9943,21 +10942,21 @@ extern const duk_uint8_t duk_unicode_ids_m_let_noabmp[24];
* Automatically generated by extract_chars.py, do not edit!
*/
-extern const duk_uint8_t duk_unicode_idp_m_ids_noa[530];
+extern const duk_uint8_t duk_unicode_idp_m_ids_noa[576];
#else
/*
* Automatically generated by extract_chars.py, do not edit!
*/
-extern const duk_uint8_t duk_unicode_idp_m_ids_noabmp[357];
+extern const duk_uint8_t duk_unicode_idp_m_ids_noabmp[358];
#endif
/*
* Automatically generated by extract_caseconv.py, do not edit!
*/
-extern const duk_uint8_t duk_unicode_caseconv_uc[1386];
-extern const duk_uint8_t duk_unicode_caseconv_lc[680];
+extern const duk_uint8_t duk_unicode_caseconv_uc[1411];
+extern const duk_uint8_t duk_unicode_caseconv_lc[706];
#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
/*
@@ -9992,7 +10991,7 @@ DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_digit[4];
DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_white[24];
DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10];
DUK_INTERNAL_DECL const duk_int8_t duk_is_idchar_tab[128];
-#endif /* !DUK_SINGLE_FILE */
+#endif /* !DUK_SINGLE_FILE */
/*
* Prototypes
@@ -10004,9 +11003,17 @@ DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t
#endif
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out);
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out);
-DUK_INTERNAL_DECL duk_small_int_t duk_unicode_decode_xutf8(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_ucodepoint_t *out_cp);
-DUK_INTERNAL_DECL duk_ucodepoint_t duk_unicode_decode_xutf8_checked(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end);
+DUK_INTERNAL_DECL duk_small_int_t duk_unicode_decode_xutf8(duk_hthread *thr,
+ const duk_uint8_t **ptr,
+ const duk_uint8_t *ptr_start,
+ const duk_uint8_t *ptr_end,
+ duk_ucodepoint_t *out_cp);
+DUK_INTERNAL_DECL duk_ucodepoint_t duk_unicode_decode_xutf8_checked(duk_hthread *thr,
+ const duk_uint8_t **ptr,
+ const duk_uint8_t *ptr_start,
+ const duk_uint8_t *ptr_end);
DUK_INTERNAL_DECL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen);
+DUK_INTERNAL_DECL duk_bool_t duk_unicode_is_utf8_compatible(const duk_uint8_t *buf, duk_size_t len);
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp);
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp);
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp);
@@ -10018,7 +11025,7 @@ DUK_INTERNAL_DECL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp);
#endif
-#endif /* DUK_UNICODE_H_INCLUDED */
+#endif /* DUK_UNICODE_H_INCLUDED */
/* #include duk_json.h */
/*
* Defines for JSON, especially duk_bi_json.c.
@@ -10028,28 +11035,28 @@ DUK_INTERNAL_DECL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp)
#define DUK_JSON_H_INCLUDED
/* Encoding/decoding flags */
-#define DUK_JSON_FLAG_ASCII_ONLY (1U << 0) /* escape any non-ASCII characters */
-#define DUK_JSON_FLAG_AVOID_KEY_QUOTES (1U << 1) /* avoid key quotes when key is an ASCII Identifier */
-#define DUK_JSON_FLAG_EXT_CUSTOM (1U << 2) /* extended types: custom encoding */
-#define DUK_JSON_FLAG_EXT_COMPATIBLE (1U << 3) /* extended types: compatible encoding */
+#define DUK_JSON_FLAG_ASCII_ONLY (1U << 0) /* escape any non-ASCII characters */
+#define DUK_JSON_FLAG_AVOID_KEY_QUOTES (1U << 1) /* avoid key quotes when key is an ASCII Identifier */
+#define DUK_JSON_FLAG_EXT_CUSTOM (1U << 2) /* extended types: custom encoding */
+#define DUK_JSON_FLAG_EXT_COMPATIBLE (1U << 3) /* extended types: compatible encoding */
/* How much stack to require on entry to object/array encode */
-#define DUK_JSON_ENC_REQSTACK 32
+#define DUK_JSON_ENC_REQSTACK 32
/* How much stack to require on entry to object/array decode */
-#define DUK_JSON_DEC_REQSTACK 32
+#define DUK_JSON_DEC_REQSTACK 32
/* How large a loop detection stack to use */
-#define DUK_JSON_ENC_LOOPARRAY 64
+#define DUK_JSON_ENC_LOOPARRAY 64
/* Encoding state. Heap object references are all borrowed. */
typedef struct {
duk_hthread *thr;
- duk_bufwriter_ctx bw; /* output bufwriter */
- duk_hobject *h_replacer; /* replacer function */
- duk_hstring *h_gap; /* gap (if empty string, NULL) */
- duk_idx_t idx_proplist; /* explicit PropertyList */
- duk_idx_t idx_loop; /* valstack index of loop detection object */
+ duk_bufwriter_ctx bw; /* output bufwriter */
+ duk_hobject *h_replacer; /* replacer function */
+ duk_hstring *h_gap; /* gap (if empty string, NULL) */
+ duk_idx_t idx_proplist; /* explicit PropertyList */
+ duk_idx_t idx_loop; /* valstack index of loop detection object */
duk_small_uint_t flags;
duk_small_uint_t flag_ascii_only;
duk_small_uint_t flag_avoid_key_quotes;
@@ -10060,7 +11067,7 @@ typedef struct {
#endif
duk_uint_t recursion_depth;
duk_uint_t recursion_limit;
- duk_uint_t mask_for_undefined; /* type bit mask: types which certainly produce 'undefined' */
+ duk_uint_t mask_for_undefined; /* type bit mask: types which certainly produce 'undefined' */
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
duk_small_uint_t stridx_custom_undefined;
duk_small_uint_t stridx_custom_nan;
@@ -10068,7 +11075,7 @@ typedef struct {
duk_small_uint_t stridx_custom_posinf;
duk_small_uint_t stridx_custom_function;
#endif
- duk_hobject *visiting[DUK_JSON_ENC_LOOPARRAY]; /* indexed by recursion_depth */
+ duk_hobject *visiting[DUK_JSON_ENC_LOOPARRAY]; /* indexed by recursion_depth */
} duk_json_enc_ctx;
typedef struct {
@@ -10087,31 +11094,32 @@ typedef struct {
duk_int_t recursion_limit;
} duk_json_dec_ctx;
-#endif /* DUK_JSON_H_INCLUDED */
+#endif /* DUK_JSON_H_INCLUDED */
/* #include duk_js.h */
/*
- * Ecmascript execution, support primitives.
+ * ECMAScript execution, support primitives.
*/
#if !defined(DUK_JS_H_INCLUDED)
#define DUK_JS_H_INCLUDED
/* Flags for call handling. Lowest flags must match bytecode DUK_BC_CALL_FLAG_xxx 1:1. */
-#define DUK_CALL_FLAG_TAILCALL (1U << 0) /* setup for a tail call */
-#define DUK_CALL_FLAG_CONSTRUCT (1U << 1) /* constructor call (i.e. called as 'new Foo()') */
-#define DUK_CALL_FLAG_CALLED_AS_EVAL (1U << 2) /* call was made using the identifier 'eval' */
-#define DUK_CALL_FLAG_ALLOW_ECMATOECMA (1U << 3) /* ecma-to-ecma call with executor reuse is possible */
-#define DUK_CALL_FLAG_DIRECT_EVAL (1U << 4) /* call is a direct eval call */
-#define DUK_CALL_FLAG_CONSTRUCT_PROXY (1U << 5) /* handled via 'construct' proxy trap, check return value invariant(s) */
-#define DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED (1U << 6) /* prototype of 'default instance' updated, temporary flag in call handling */
+#define DUK_CALL_FLAG_TAILCALL (1U << 0) /* setup for a tail call */
+#define DUK_CALL_FLAG_CONSTRUCT (1U << 1) /* constructor call (i.e. called as 'new Foo()') */
+#define DUK_CALL_FLAG_CALLED_AS_EVAL (1U << 2) /* call was made using the identifier 'eval' */
+#define DUK_CALL_FLAG_ALLOW_ECMATOECMA (1U << 3) /* ecma-to-ecma call with executor reuse is possible */
+#define DUK_CALL_FLAG_DIRECT_EVAL (1U << 4) /* call is a direct eval call */
+#define DUK_CALL_FLAG_CONSTRUCT_PROXY (1U << 5) /* handled via 'construct' proxy trap, check return value invariant(s) */
+#define DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED \
+ (1U << 6) /* prototype of 'default instance' updated, temporary flag in call handling */
/* Flags for duk_js_equals_helper(). */
-#define DUK_EQUALS_FLAG_SAMEVALUE (1U << 0) /* use SameValue instead of non-strict equality */
-#define DUK_EQUALS_FLAG_STRICT (1U << 1) /* use strict equality instead of non-strict equality */
+#define DUK_EQUALS_FLAG_SAMEVALUE (1U << 0) /* use SameValue instead of non-strict equality */
+#define DUK_EQUALS_FLAG_STRICT (1U << 1) /* use strict equality instead of non-strict equality */
/* Flags for duk_js_compare_helper(). */
-#define DUK_COMPARE_FLAG_NEGATE (1U << 0) /* negate result */
-#define DUK_COMPARE_FLAG_EVAL_LEFT_FIRST (1U << 1) /* eval left argument first */
+#define DUK_COMPARE_FLAG_NEGATE (1U << 0) /* negate result */
+#define DUK_COMPARE_FLAG_EVAL_LEFT_FIRST (1U << 1) /* eval left argument first */
/* conversions, coercions, comparison, etc */
DUK_INTERNAL_DECL duk_bool_t duk_js_toboolean(duk_tval *tv);
@@ -10127,59 +11135,79 @@ DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_hstring_fast_known(duk_hstr
DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h);
#endif
DUK_INTERNAL_DECL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags);
-DUK_INTERNAL_DECL duk_small_int_t duk_js_data_compare(const duk_uint8_t *buf1, const duk_uint8_t *buf2, duk_size_t len1, duk_size_t len2);
+DUK_INTERNAL_DECL duk_small_int_t duk_js_data_compare(const duk_uint8_t *buf1,
+ const duk_uint8_t *buf2,
+ duk_size_t len1,
+ duk_size_t len2);
DUK_INTERNAL_DECL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2);
-#if 0 /* unused */
+#if 0 /* unused */
DUK_INTERNAL_DECL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2);
#endif
DUK_INTERNAL_DECL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags);
DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
+#if defined(DUK_USE_SYMBOL_BUILTIN)
+DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof_ordinary(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
+#endif
DUK_INTERNAL_DECL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
DUK_INTERNAL_DECL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x);
+DUK_INTERNAL_DECL duk_bool_t duk_js_isarray_hobject(duk_hobject *h);
+DUK_INTERNAL_DECL duk_bool_t duk_js_isarray(duk_tval *tv);
/* arithmetic */
DUK_INTERNAL_DECL double duk_js_arith_pow(double x, double y);
DUK_INTERNAL_DECL double duk_js_arith_mod(double x, double y);
-#define duk_js_equals(thr,tv_x,tv_y) \
- duk_js_equals_helper((thr), (tv_x), (tv_y), 0)
-#define duk_js_strict_equals(tv_x,tv_y) \
- duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_STRICT)
-#define duk_js_samevalue(tv_x,tv_y) \
- duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_SAMEVALUE)
+#define duk_js_equals(thr, tv_x, tv_y) duk_js_equals_helper((thr), (tv_x), (tv_y), 0)
+#define duk_js_strict_equals(tv_x, tv_y) duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_STRICT)
+#define duk_js_samevalue(tv_x, tv_y) duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_SAMEVALUE)
/* E5 Sections 11.8.1, 11.8.5; x < y */
-#define duk_js_lessthan(thr,tv_x,tv_y) \
- duk_js_compare_helper((thr), (tv_x), (tv_Y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
+#define duk_js_lessthan(thr, tv_x, tv_y) duk_js_compare_helper((thr), (tv_x), (tv_Y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
/* E5 Sections 11.8.2, 11.8.5; x > y --> y < x */
-#define duk_js_greaterthan(thr,tv_x,tv_y) \
- duk_js_compare_helper((thr), (tv_y), (tv_x), 0)
+#define duk_js_greaterthan(thr, tv_x, tv_y) duk_js_compare_helper((thr), (tv_y), (tv_x), 0)
/* E5 Sections 11.8.3, 11.8.5; x <= y --> not (x > y) --> not (y < x) */
-#define duk_js_lessthanorequal(thr,tv_x,tv_y) \
- duk_js_compare_helper((thr), (tv_y), (tv_x), DUK_COMPARE_FLAG_NEGATE)
+#define duk_js_lessthanorequal(thr, tv_x, tv_y) duk_js_compare_helper((thr), (tv_y), (tv_x), DUK_COMPARE_FLAG_NEGATE)
/* E5 Sections 11.8.4, 11.8.5; x >= y --> not (x < y) */
-#define duk_js_greaterthanorequal(thr,tv_x,tv_y) \
+#define duk_js_greaterthanorequal(thr, tv_x, tv_y) \
duk_js_compare_helper((thr), (tv_x), (tv_y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
/* identifiers and environment handling */
-#if 0 /*unused*/
+#if 0 /*unused*/
DUK_INTERNAL duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
#endif
DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_bool_t throw_flag);
-DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_bool_t throw_flag);
-DUK_INTERNAL_DECL void duk_js_putvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_tval *val, duk_bool_t strict);
-DUK_INTERNAL_DECL void duk_js_putvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_bool_t strict);
-#if 0 /*unused*/
+DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_activation(duk_hthread *thr,
+ duk_activation *act,
+ duk_hstring *name,
+ duk_bool_t throw_flag);
+DUK_INTERNAL_DECL void duk_js_putvar_envrec(duk_hthread *thr,
+ duk_hobject *env,
+ duk_hstring *name,
+ duk_tval *val,
+ duk_bool_t strict);
+DUK_INTERNAL_DECL void duk_js_putvar_activation(duk_hthread *thr,
+ duk_activation *act,
+ duk_hstring *name,
+ duk_tval *val,
+ duk_bool_t strict);
+#if 0 /*unused*/
DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
#endif
DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name);
-DUK_INTERNAL_DECL duk_bool_t duk_js_declvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_small_uint_t prop_flags, duk_bool_t is_func_decl);
+DUK_INTERNAL_DECL duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
+ duk_activation *act,
+ duk_hstring *name,
+ duk_tval *val,
+ duk_small_uint_t prop_flags,
+ duk_bool_t is_func_decl);
DUK_INTERNAL_DECL void duk_js_init_activation_environment_records_delayed(duk_hthread *thr, duk_activation *act);
DUK_INTERNAL_DECL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env);
-DUK_INTERNAL_DECL duk_hobject *duk_create_activation_environment_record(duk_hthread *thr, duk_hobject *func, duk_size_t bottom_byteoff);
+DUK_INTERNAL_DECL duk_hobject *duk_create_activation_environment_record(duk_hthread *thr,
+ duk_hobject *func,
+ duk_size_t bottom_byteoff);
DUK_INTERNAL_DECL void duk_js_push_closure(duk_hthread *thr,
duk_hcompfunc *fun_temp,
duk_hobject *outer_var_env,
@@ -10187,22 +11215,24 @@ DUK_INTERNAL_DECL void duk_js_push_closure(duk_hthread *thr,
duk_bool_t add_auto_proto);
/* call handling */
+DUK_INTERNAL_DECL void duk_native_stack_check(duk_hthread *thr);
DUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected(duk_hthread *thr, duk_idx_t idx_func, duk_small_uint_t call_flags);
DUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags);
-DUK_INTERNAL_DECL duk_int_t duk_handle_safe_call(duk_hthread *thr, duk_safe_call_function func, void *udata, duk_idx_t num_stack_args, duk_idx_t num_stack_res);
+DUK_INTERNAL_DECL duk_int_t
+duk_handle_safe_call(duk_hthread *thr, duk_safe_call_function func, void *udata, duk_idx_t num_stack_args, duk_idx_t num_stack_res);
DUK_INTERNAL_DECL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uint_t proxy_invariant);
#if defined(DUK_USE_VERBOSE_ERRORS)
-DUK_INTERNAL_DECL void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_targ, duk_tval *tv_base, duk_tval *tv_key);
+DUK_INTERNAL_DECL void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_base, duk_tval *tv_key);
#endif
/* bytecode execution */
DUK_INTERNAL_DECL void duk_js_execute_bytecode(duk_hthread *exec_thr);
-#endif /* DUK_JS_H_INCLUDED */
+#endif /* DUK_JS_H_INCLUDED */
/* #include duk_numconv.h */
/*
* Number-to-string conversion. The semantics of these is very tightly
- * bound with the Ecmascript semantics required for call sites.
+ * bound with the ECMAScript semantics required for call sites.
*/
#if !defined(DUK_NUMCONV_H_INCLUDED)
@@ -10211,23 +11241,23 @@ DUK_INTERNAL_DECL void duk_js_execute_bytecode(duk_hthread *exec_thr);
/* Output a specified number of digits instead of using the shortest
* form. Used for toPrecision() and toFixed().
*/
-#define DUK_N2S_FLAG_FIXED_FORMAT (1U << 0)
+#define DUK_N2S_FLAG_FIXED_FORMAT (1U << 0)
/* Force exponential format. Used for toExponential(). */
-#define DUK_N2S_FLAG_FORCE_EXP (1U << 1)
+#define DUK_N2S_FLAG_FORCE_EXP (1U << 1)
/* If number would need zero padding (for whole number part), use
* exponential format instead. E.g. if input number is 12300, 3
* digits are generated ("123"), output "1.23e+4" instead of "12300".
* Used for toPrecision().
*/
-#define DUK_N2S_FLAG_NO_ZERO_PAD (1U << 2)
+#define DUK_N2S_FLAG_NO_ZERO_PAD (1U << 2)
/* Digit count indicates number of fractions (i.e. an absolute
* digit index instead of a relative one). Used together with
* DUK_N2S_FLAG_FIXED_FORMAT for toFixed().
*/
-#define DUK_N2S_FLAG_FRACTION_DIGITS (1U << 3)
+#define DUK_N2S_FLAG_FRACTION_DIGITS (1U << 3)
/*
* String-to-number conversion
@@ -10235,71 +11265,78 @@ DUK_INTERNAL_DECL void duk_js_execute_bytecode(duk_hthread *exec_thr);
/* Maximum exponent value when parsing numbers. This is not strictly
* compliant as there should be no upper limit, but as we parse the
- * exponent without a bigint, impose some limit.
+ * exponent without a bigint, impose some limit. The limit should be
+ * small enough that multiplying it (or limit-1 to be precise) won't
+ * overflow signed 32-bit integer range. Exponent is only parsed with
+ * radix 10, but with maximum radix (36) a safe limit is:
+ * (10000000*36).toString(16) -> '15752a00'
*/
-#define DUK_S2N_MAX_EXPONENT 1000000000
+#define DUK_S2N_MAX_EXPONENT 10000000L
/* Trim white space (= allow leading and trailing whitespace) */
-#define DUK_S2N_FLAG_TRIM_WHITE (1U << 0)
+#define DUK_S2N_FLAG_TRIM_WHITE (1U << 0)
/* Allow exponent */
-#define DUK_S2N_FLAG_ALLOW_EXP (1U << 1)
+#define DUK_S2N_FLAG_ALLOW_EXP (1U << 1)
/* Allow trailing garbage (e.g. treat "123foo" as "123) */
-#define DUK_S2N_FLAG_ALLOW_GARBAGE (1U << 2)
+#define DUK_S2N_FLAG_ALLOW_GARBAGE (1U << 2)
/* Allow leading plus sign */
-#define DUK_S2N_FLAG_ALLOW_PLUS (1U << 3)
+#define DUK_S2N_FLAG_ALLOW_PLUS (1U << 3)
/* Allow leading minus sign */
-#define DUK_S2N_FLAG_ALLOW_MINUS (1U << 4)
+#define DUK_S2N_FLAG_ALLOW_MINUS (1U << 4)
/* Allow 'Infinity' */
-#define DUK_S2N_FLAG_ALLOW_INF (1U << 5)
+#define DUK_S2N_FLAG_ALLOW_INF (1U << 5)
/* Allow fraction part */
-#define DUK_S2N_FLAG_ALLOW_FRAC (1U << 6)
+#define DUK_S2N_FLAG_ALLOW_FRAC (1U << 6)
/* Allow naked fraction (e.g. ".123") */
-#define DUK_S2N_FLAG_ALLOW_NAKED_FRAC (1U << 7)
+#define DUK_S2N_FLAG_ALLOW_NAKED_FRAC (1U << 7)
/* Allow empty fraction (e.g. "123.") */
-#define DUK_S2N_FLAG_ALLOW_EMPTY_FRAC (1U << 8)
+#define DUK_S2N_FLAG_ALLOW_EMPTY_FRAC (1U << 8)
/* Allow empty string to be interpreted as 0 */
-#define DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO (1U << 9)
+#define DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO (1U << 9)
/* Allow leading zeroes (e.g. "0123" -> "123") */
-#define DUK_S2N_FLAG_ALLOW_LEADING_ZERO (1U << 10)
+#define DUK_S2N_FLAG_ALLOW_LEADING_ZERO (1U << 10)
/* Allow automatic detection of hex base ("0x" or "0X" prefix),
* overrides radix argument and forces integer mode.
*/
-#define DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT (1U << 11)
+#define DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT (1U << 11)
/* Allow automatic detection of legacy octal base ("0n"),
* overrides radix argument and forces integer mode.
*/
-#define DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT (1U << 12)
+#define DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT (1U << 12)
/* Allow automatic detection of ES2015 octal base ("0o123"),
* overrides radix argument and forces integer mode.
*/
-#define DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT (1U << 13)
+#define DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT (1U << 13)
/* Allow automatic detection of ES2015 binary base ("0b10001"),
* overrides radix argument and forces integer mode.
*/
-#define DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT (1U << 14)
+#define DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT (1U << 14)
/*
* Prototypes
*/
-DUK_INTERNAL_DECL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags);
+DUK_INTERNAL_DECL void duk_numconv_stringify(duk_hthread *thr,
+ duk_small_int_t radix,
+ duk_small_int_t digits,
+ duk_small_uint_t flags);
DUK_INTERNAL_DECL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags);
-#endif /* DUK_NUMCONV_H_INCLUDED */
+#endif /* DUK_NUMCONV_H_INCLUDED */
/* #include duk_bi_protos.h */
/*
* Prototypes for built-in functions not automatically covered by the
@@ -10315,7 +11352,7 @@ DUK_INTERNAL_DECL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix
* 32
* Include additional space to be safe.
*/
-#define DUK_BI_DATE_ISO8601_BUFSIZE 40
+#define DUK_BI_DATE_ISO8601_BUFSIZE 40
/* Helpers exposed for internal use */
DUK_INTERNAL_DECL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t *dparts, duk_small_uint_t flags);
@@ -10353,7 +11390,10 @@ DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr,
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const char *str);
#endif
#if defined(DUK_USE_DATE_FMT_STRFTIME)
-DUK_INTERNAL_DECL duk_bool_t duk_bi_date_format_parts_strftime(duk_hthread *thr, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags);
+DUK_INTERNAL_DECL duk_bool_t duk_bi_date_format_parts_strftime(duk_hthread *thr,
+ duk_int_t *parts,
+ duk_int_t tzoffset,
+ duk_small_uint_t flags);
#endif
#if defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)
@@ -10364,10 +11404,7 @@ DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void);
#endif
DUK_INTERNAL_DECL
-void duk_bi_json_parse_helper(duk_hthread *thr,
- duk_idx_t idx_value,
- duk_idx_t idx_reviver,
- duk_small_uint_t flags);
+void duk_bi_json_parse_helper(duk_hthread *thr, duk_idx_t idx_value, duk_idx_t idx_reviver, duk_small_uint_t flags);
DUK_INTERNAL_DECL
void duk_bi_json_stringify_helper(duk_hthread *thr,
duk_idx_t idx_value,
@@ -10381,7 +11418,7 @@ DUK_INTERNAL_DECL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_hthread *thr)
DUK_INTERNAL_DECL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h_proxy_target, duk_uint_t flags);
#endif
-#endif /* DUK_BUILTIN_PROTOS_H_INCLUDED */
+#endif /* DUK_BUILTIN_PROTOS_H_INCLUDED */
/* #include duk_selftest.h */
/*
* Selftest code
@@ -10397,9 +11434,9 @@ DUK_INTERNAL_DECL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_fun
void *udata);
#endif
-#endif /* DUK_SELFTEST_H_INCLUDED */
+#endif /* DUK_SELFTEST_H_INCLUDED */
-#endif /* DUK_INTERNAL_H_INCLUDED */
+#endif /* DUK_INTERNAL_H_INCLUDED */
#if defined(DUK_USE_COMPUTED_NAN)
DUK_INTERNAL double duk_computed_nan;
@@ -10493,7 +11530,7 @@ DUK_INTERNAL int duk_repl_isinf(double x) {
#error debugging enabled (DUK_USE_DEBUG) but DUK_USE_DEBUG_WRITE not defined
#endif
-#define DUK__DEBUG_BUFSIZE DUK_USE_DEBUG_BUFSIZE
+#define DUK__DEBUG_BUFSIZE DUK_USE_DEBUG_BUFSIZE
#if defined(DUK_USE_VARIADIC_MACROS)
@@ -10508,7 +11545,7 @@ DUK_INTERNAL void duk_debug_log(duk_int_t level, const char *file, duk_int_t lin
va_start(ap, fmt);
- DUK_MEMZERO((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
+ duk_memzero((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
arg_level = (long) level;
@@ -10521,7 +11558,7 @@ DUK_INTERNAL void duk_debug_log(duk_int_t level, const char *file, duk_int_t lin
va_end(ap);
}
-#else /* DUK_USE_VARIADIC_MACROS */
+#else /* DUK_USE_VARIADIC_MACROS */
DUK_INTERNAL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
DUK_INTERNAL duk_int_t duk_debug_line_stash;
@@ -10539,7 +11576,7 @@ DUK_INTERNAL void duk_debug_log(const char *fmt, ...) {
va_start(ap, fmt);
- DUK_MEMZERO((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
+ duk_memzero((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
arg_level = (long) duk_debug_level_stash;
@@ -10552,15 +11589,15 @@ DUK_INTERNAL void duk_debug_log(const char *fmt, ...) {
va_end(ap);
}
-#endif /* DUK_USE_VARIADIC_MACROS */
+#endif /* DUK_USE_VARIADIC_MACROS */
-#else /* DUK_USE_DEBUG */
+#else /* DUK_USE_DEBUG */
/*
* Debugging disabled
*/
-#endif /* DUK_USE_DEBUG */
+#endif /* DUK_USE_DEBUG */
/* automatic undefs */
#undef DUK__DEBUG_BUFSIZE
@@ -10579,7 +11616,7 @@ DUK_INTERNAL void duk_debug_log(const char *fmt, ...) {
#if defined(DUK_USE_ROM_STRINGS)
#error ROM support not enabled, rerun configure.py with --rom-support
#else /* DUK_USE_ROM_STRINGS */
-DUK_INTERNAL const duk_uint8_t duk_strings_data[892] = {
+DUK_INTERNAL const duk_uint8_t duk_strings_data[972] = {
79,40,209,144,168,105,6,78,54,139,89,185,44,48,46,90,120,8,154,140,35,103,
35,113,193,73,5,52,112,180,104,166,135,52,188,4,98,12,27,146,156,80,211,31,
129,115,150,64,52,220,109,24,18,68,156,24,38,67,114,36,55,9,119,151,132,
@@ -10601,36 +11638,40 @@ DUK_INTERNAL const duk_uint8_t duk_strings_data[892] = {
249,110,128,126,88,95,133,109,237,237,237,151,235,127,46,249,119,203,190,
186,206,33,181,2,208,61,190,12,19,34,65,19,81,132,108,228,97,1,107,33,12,
32,45,100,137,64,247,175,9,19,155,41,198,130,155,134,69,146,100,227,226,
-231,146,51,192,204,73,140,224,145,221,102,241,68,196,157,34,79,143,139,166,
-233,225,228,227,138,157,173,167,197,211,118,214,210,38,238,74,113,67,76,
-105,187,169,147,154,73,225,228,32,193,48,25,100,105,166,113,200,147,44,166,
-1,40,79,18,150,134,147,141,163,2,72,171,115,147,136,4,65,130,96,35,64,194,
-32,168,89,56,208,48,135,123,144,217,146,39,220,228,193,19,18,101,220,227,
-73,121,167,115,129,196,200,39,12,136,220,225,93,22,1,114,62,231,42,8,176,
-15,62,231,36,234,68,68,70,231,30,45,37,161,164,38,231,24,7,159,115,149,4,
-72,218,171,115,133,67,64,180,100,145,54,231,42,5,208,135,19,152,244,44,133,
-67,95,73,164,145,143,5,18,2,100,65,35,30,76,241,117,134,70,212,103,37,204,
-16,72,154,218,130,77,196,145,63,127,123,106,141,25,11,189,243,169,198,132,
-251,235,119,247,182,154,6,239,124,234,113,161,62,250,221,253,237,164,52,
-187,223,58,156,104,79,190,187,127,123,105,168,105,119,190,117,56,208,159,
-125,118,254,246,209,104,209,111,124,234,113,161,62,250,205,253,162,209,162,
-249,212,227,66,125,244,161,137,0,162,8,18,33,68,9,136,232,19,155,52,54,132,
-64,200,26,24,196,137,198,66,130,139,153,134,69,146,100,16,220,66,46,68,57,
-80,208,45,120,25,93,20,22,141,20,208,230,137,5,18,26,164,54,83,3,68,71,20,
-109,37,141,18,78,145,105,165,100,76,71,36,206,137,22,103,139,172,57,199,6,
-158,30,71,20,117,4,74,39,54,83,37,92,129,150,199,66,200,75,34,103,40,150,9,
-72,132,109,24,98,93,238,140,206,75,204,141,28,140,134,61,209,153,101,71,
-146,36,109,22,178,78,52,33,74,5,200,138,67,30,178,48,141,156,146,134,204,
-145,40,4,65,172,147,59,192,37,0,196,59,226,138,130,100,75,226,233,144,83,
-32,204,250,5,104,17,165,48,77,2,46,16,69,140,
+231,146,51,192,204,73,140,224,145,221,102,241,68,196,169,248,30,75,12,11,
+151,242,233,187,143,138,24,137,162,164,255,253,63,3,201,97,129,114,254,92,
+112,75,136,108,166,6,136,159,255,167,224,121,44,48,46,95,203,166,238,74,
+113,67,77,201,128,223,255,223,224,121,44,48,46,95,203,145,46,9,205,16,39,
+201,62,36,0,192,21,147,255,238,145,39,199,197,211,116,240,242,113,197,78,
+214,211,226,233,187,107,105,19,119,37,56,161,166,52,221,212,201,205,36,240,
+242,16,96,152,12,26,20,164,137,150,70,154,103,28,137,50,202,96,18,132,241,
+41,104,105,56,218,48,36,138,183,57,56,128,68,24,38,2,52,12,34,10,133,147,
+141,3,8,119,185,13,153,34,125,206,76,17,49,38,93,206,52,151,154,119,56,28,
+76,130,112,200,141,206,21,209,96,23,35,238,114,160,139,0,243,238,114,78,
+164,68,68,110,113,226,210,90,26,66,110,113,128,121,247,57,80,68,141,170,
+183,56,84,52,11,70,73,19,110,114,160,93,8,113,57,143,66,200,84,53,244,154,
+73,24,240,81,32,38,68,18,49,228,207,23,88,100,109,70,114,92,193,4,137,173,
+168,36,220,73,19,247,247,182,168,209,144,187,223,58,156,104,79,190,183,127,
+123,105,160,110,247,206,167,26,19,239,173,223,222,218,67,75,189,243,169,
+198,132,251,235,183,247,182,154,134,151,123,231,83,141,9,247,215,111,239,
+109,22,141,22,247,206,167,26,19,239,172,223,218,45,26,47,157,78,52,39,223,
+74,24,144,10,32,129,34,20,64,152,142,129,57,179,67,104,68,12,129,161,140,
+72,156,100,40,40,185,152,100,89,38,65,13,196,34,228,67,149,13,2,215,129,
+149,209,65,104,209,77,14,104,144,81,33,170,67,101,48,52,68,113,70,210,88,
+209,36,233,22,154,86,68,196,114,76,232,145,102,120,186,195,156,112,105,225,
+228,113,71,80,68,162,115,101,50,85,200,25,108,116,44,132,178,38,114,137,96,
+148,136,70,209,134,37,222,232,204,228,188,200,209,200,200,99,221,25,150,84,
+121,34,70,209,107,36,227,66,20,160,92,136,164,49,235,35,8,217,201,40,108,
+201,18,128,68,26,201,51,188,2,80,12,67,190,40,168,38,68,190,46,153,5,50,12,
+207,160,86,129,26,83,4,208,34,225,4,88,192,
};
#endif /* DUK_USE_ROM_STRINGS */
#if defined(DUK_USE_ROM_OBJECTS)
#error ROM support not enabled, rerun configure.py with --rom-support
#else /* DUK_USE_ROM_OBJECTS */
-/* native functions: 176 */
-DUK_INTERNAL const duk_c_function duk_bi_native_functions[176] = {
+/* native functions: 185 */
+DUK_INTERNAL const duk_c_function duk_bi_native_functions[185] = {
NULL,
duk_bi_array_constructor,
duk_bi_array_constructor_is_array,
@@ -10656,6 +11697,8 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[176] = {
duk_bi_buffer_readfield,
duk_bi_buffer_slice_shared,
duk_bi_buffer_writefield,
+ duk_bi_cbor_decode,
+ duk_bi_cbor_encode,
duk_bi_dataview_constructor,
duk_bi_date_constructor,
duk_bi_date_constructor_now,
@@ -10666,6 +11709,7 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[176] = {
duk_bi_date_prototype_set_shared,
duk_bi_date_prototype_set_time,
duk_bi_date_prototype_to_json,
+ duk_bi_date_prototype_toprimitive,
duk_bi_date_prototype_tostring_shared,
duk_bi_date_prototype_value_of,
duk_bi_duktape_object_act,
@@ -10688,6 +11732,7 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[176] = {
duk_bi_function_prototype_apply,
duk_bi_function_prototype_bind,
duk_bi_function_prototype_call,
+ duk_bi_function_prototype_hasinstance,
duk_bi_function_prototype_to_string,
duk_bi_global_object_decode_uri,
duk_bi_global_object_decode_uri_component,
@@ -10723,6 +11768,7 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[176] = {
duk_bi_nodejs_buffer_tojson,
duk_bi_nodejs_buffer_tostring,
duk_bi_nodejs_buffer_write,
+ duk_bi_number_check_shared,
duk_bi_number_constructor,
duk_bi_number_prototype_to_exponential,
duk_bi_number_prototype_to_fixed,
@@ -10789,6 +11835,10 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[176] = {
duk_bi_string_prototype_substring,
duk_bi_string_prototype_to_string,
duk_bi_string_prototype_trim,
+ duk_bi_symbol_constructor_shared,
+ duk_bi_symbol_key_for,
+ duk_bi_symbol_toprimitive,
+ duk_bi_symbol_tostring_shared,
duk_bi_textdecoder_constructor,
duk_bi_textdecoder_prototype_decode,
duk_bi_textdecoder_prototype_shared_getter,
@@ -10809,556 +11859,604 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[176] = {
duk_bi_uint8array_plainof,
};
#if defined(DUK_USE_DOUBLE_LE)
-DUK_INTERNAL const duk_uint8_t duk_builtins_data[3972] = {
-144,148,105,223,160,68,52,228,62,12,104,200,165,132,52,167,194,138,105,242,
-252,57,28,211,57,18,64,52,238,62,44,138,111,171,241,164,19,87,125,30,33,
-167,16,145,159,8,211,136,9,225,42,5,240,145,139,163,163,8,211,136,10,228,
-64,211,19,132,140,93,29,56,70,156,64,119,34,66,146,36,104,137,194,70,46,
-142,172,35,78,32,47,146,195,102,11,240,145,139,163,175,8,211,136,9,228,240,
-242,112,145,139,163,179,8,211,136,8,237,34,130,118,49,116,118,225,26,48,0,
-1,80,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
-33,8,66,34,33,154,112,0,1,73,247,35,79,91,237,198,174,192,47,31,23,95,17,
-13,51,19,35,93,68,216,209,128,0,10,192,174,79,15,32,248,8,196,24,8,107,192,
-0,5,98,118,27,94,0,0,43,19,227,94,0,0,43,20,46,215,128,0,10,197,28,198,188,
-0,0,86,41,100,53,224,0,2,177,79,85,175,0,0,21,138,154,45,120,0,0,172,85,
-217,107,192,0,5,98,182,243,86,193,106,52,127,66,249,50,94,124,35,68,225,
-146,49,13,31,170,23,201,146,243,224,200,39,12,145,136,67,134,11,49,0,0,0,0,
-0,0,3,225,255,51,0,0,0,0,0,0,3,193,255,47,18,1,172,19,120,71,10,25,196,136,
-113,162,156,136,199,42,57,204,144,115,132,240,149,2,248,72,197,209,58,2,
-185,16,52,196,225,35,23,68,233,14,228,72,82,68,141,17,56,72,197,209,58,130,
-249,44,54,96,191,9,24,186,39,88,79,39,135,147,132,140,93,19,176,35,180,138,
-9,216,197,209,59,82,79,31,40,242,1,248,58,42,96,121,14,232,94,62,46,190,15,
-38,31,145,33,86,65,76,242,150,143,69,48,242,179,79,45,56,243,51,207,53,64,
-243,116,79,57,72,243,180,207,61,80,243,245,79,65,88,244,34,249,50,94,124,
-35,68,225,146,39,163,23,201,146,243,224,200,39,12,145,61,40,183,146,37,116,
-88,6,136,158,244,241,174,230,202,80,135,130,50,39,16,217,231,208,20,240,70,
-68,225,86,224,79,60,64,84,75,141,7,27,157,32,66,37,194,161,168,153,51,132,
-9,25,4,225,147,180,138,50,196,18,25,4,225,147,180,138,5,215,49,238,105,27,
-60,185,2,72,209,56,100,237,34,140,193,4,136,209,56,100,237,34,129,117,204,
-123,154,70,207,50,64,98,72,64,121,51,68,8,163,73,33,1,228,208,16,0,65,112,
-152,56,196,159,31,23,77,211,195,201,199,23,150,73,169,234,34,24,49,39,199,
-89,188,124,92,242,70,120,224,201,33,69,15,155,163,196,64,153,137,62,58,205,
-227,226,231,146,51,199,26,6,18,92,130,64,192,148,144,102,240,23,129,133,18,
-2,100,224,160,56,100,42,26,78,62,46,121,35,60,112,216,32,50,21,13,39,31,23,
-60,145,154,9,46,18,1,36,64,47,148,64,98,196,132,201,57,68,132,95,18,84,141,
-159,9,121,145,178,67,155,46,73,2,17,46,72,128,89,7,199,32,66,37,194,197,
-217,35,120,228,131,17,46,18,243,35,100,128,172,156,98,2,40,152,151,32,130,
-166,36,248,235,55,143,139,158,72,207,28,150,24,23,46,92,130,80,72,151,21,0,
-100,213,103,229,245,8,186,190,144,24,78,136,24,94,152,3,142,9,113,214,111,
-31,23,60,145,158,57,164,13,68,184,248,186,110,158,30,78,56,188,226,10,62,
-46,121,35,60,113,18,225,27,70,18,32,10,201,208,32,134,214,208,200,84,52,
-156,49,39,50,71,107,107,152,129,13,173,161,144,168,105,57,34,78,100,142,
-214,215,49,16,134,214,210,220,229,81,252,49,39,50,71,107,107,158,65,13,173,
-165,185,202,163,249,34,78,100,142,214,215,60,146,12,16,28,128,62,175,42,6,
-143,36,136,16,64,90,242,135,192,129,67,71,147,62,65,5,215,231,214,6,215,62,
-180,8,49,1,3,162,92,4,98,12,41,14,67,40,106,229,1,132,130,8,24,78,104,129,
-54,62,96,224,144,13,238,124,32,2,62,146,60,51,224,120,146,164,140,137,20,0,
-178,58,11,56,192,5,146,208,34,71,64,36,157,25,200,32,52,158,180,8,146,87,
-129,232,217,29,5,156,179,224,116,52,100,191,28,87,62,130,214,9,79,136,104,
-201,126,56,174,127,0,31,255,225,73,82,71,16,13,1,36,230,18,1,164,14,87,71,
-132,0,143,0,210,131,96,31,0,211,6,42,23,50,70,1,167,13,18,14,130,36,67,232,
-46,36,29,4,78,69,6,60,226,31,192,7,255,252,24,192,163,11,23,51,130,56,35,
-193,56,100,243,31,6,150,46,103,4,225,147,143,114,27,63,57,241,200,169,194,
-133,42,166,175,240,6,23,240,0,97,28,17,224,39,233,32,80,142,8,240,78,25,56,
-9,250,136,22,39,12,156,123,144,217,240,19,245,18,6,19,154,32,79,214,124,14,
-134,140,151,227,139,237,52,11,88,37,62,33,163,37,248,226,251,77,32,213,184,
-64,89,56,39,49,224,137,61,196,5,96,38,35,251,200,15,18,61,96,17,62,40,6,
-145,1,17,31,228,64,89,45,2,39,205,0,178,122,209,63,162,2,101,64,202,113,67,
-77,247,64,92,221,197,186,196,143,4,9,19,208,1,25,187,139,112,128,178,113,
-110,177,35,193,2,68,244,0,46,110,229,30,242,71,130,4,137,232,4,35,55,113,
-110,16,22,78,81,239,36,120,32,72,158,128,64,147,138,25,249,0,52,72,242,2,
-127,2,5,74,96,140,229,203,34,103,250,154,4,17,163,151,44,137,159,234,105,4,
-33,162,93,6,73,123,13,1,165,64,202,113,251,33,6,64,14,71,78,20,101,213,207,
-4,194,207,2,12,162,0,158,176,23,218,168,23,66,64,255,255,255,255,255,255,
-239,127,19,214,33,187,85,2,232,72,0,32,0,0,0,0,0,0,25,136,0,0,0,0,0,0,31,
-15,228,122,247,73,19,69,73,180,134,149,13,68,241,0,0,0,0,0,0,3,193,252,143,
-90,67,2,104,169,54,144,210,161,168,158,32,0,0,0,0,0,0,120,127,142,73,78,20,
-0,0,0,0,0,0,0,0,8,58,189,233,24,77,217,24,93,240,1,230,238,21,23,32,247,68,
-13,155,184,75,189,205,35,102,128,47,114,64,185,187,143,137,4,137,33,205,
-222,17,6,96,48,87,130,50,37,114,1,246,147,21,143,224,54,186,213,128,114,90,
-112,164,0,0,0,0,0,0,124,63,226,117,119,128,25,55,112,96,153,57,41,197,13,
-53,224,65,147,119,38,134,19,146,156,80,211,94,5,194,94,6,37,55,113,110,16,
-22,78,12,19,39,37,56,161,166,188,14,74,110,226,220,32,44,156,154,24,78,74,
-113,67,77,120,32,97,175,4,28,61,224,133,172,186,70,22,248,1,204,73,242,104,
-97,47,128,44,196,159,11,69,175,152,32,35,100,33,142,49,39,218,76,69,237,22,
-190,96,128,141,144,136,32,196,159,24,230,204,246,66,40,179,18,125,164,196,
-206,185,179,61,144,140,28,196,159,6,9,146,200,71,20,98,79,180,152,135,208,
-76,150,66,64,99,18,124,24,49,100,36,137,49,39,218,76,67,232,49,100,37,8,49,
-39,195,186,145,149,144,150,44,196,159,105,49,31,174,164,101,100,38,10,49,
-39,198,33,180,153,37,100,38,141,49,39,218,76,76,234,27,73,146,86,66,112,
-163,18,124,145,4,230,142,86,66,120,211,18,125,164,197,46,144,78,104,229,
-100,40,15,49,39,198,33,107,68,136,39,52,114,178,20,73,24,147,237,38,38,117,
-11,90,36,65,57,163,149,144,164,68,196,159,38,134,19,46,105,56,226,150,68,
-157,160,3,200,147,228,208,194,92,32,124,137,62,49,11,90,36,65,57,163,149,
-178,166,74,68,159,105,49,51,168,90,209,34,9,205,28,173,149,65,82,36,249,34,
-9,205,28,173,175,170,54,68,159,105,49,75,164,19,154,57,91,95,88,84,137,62,
-49,13,164,201,43,111,235,141,145,39,218,76,76,234,27,73,146,86,223,216,17,
-34,79,135,117,35,43,115,236,139,145,39,218,76,71,235,169,25,91,159,104,60,
-137,62,12,19,37,178,182,42,68,159,105,49,15,160,153,45,149,193,18,36,248,
-199,54,103,182,190,232,185,18,125,164,196,206,185,179,61,181,247,133,200,
-147,225,104,181,243,4,4,109,191,190,58,68,159,105,49,23,180,90,249,130,2,
-54,223,224,67,152,147,230,8,8,217,12,16,121,18,124,193,1,27,101,131,131,56,
-7,38,193,198,72,0,0,0,0,0,0,0,0,198,231,240,134,39,63,136,151,95,63,136,49,
-89,252,66,98,243,248,133,96,132,185,5,224,32,36,201,41,248,200,213,249,0,
-131,64,7,39,192,218,148,124,137,74,216,231,198,227,141,182,124,78,40,217,
-231,197,227,4,213,227,192,159,72,10,5,21,218,138,120,74,129,124,36,98,232,
-228,74,81,62,160,20,10,107,181,21,114,32,105,137,194,70,46,142,68,165,19,
-235,1,64,170,187,81,119,34,66,146,36,104,137,194,70,46,142,68,165,19,236,1,
-64,174,187,81,95,37,134,204,23,225,35,23,71,34,82,137,246,128,160,89,93,
-168,167,147,195,201,194,70,46,142,68,165,19,238,1,64,182,187,81,71,105,20,
-19,177,139,163,145,41,68,16,7,6,15,82,70,72,115,96,0,0,0,0,0,93,105,160,91,
-60,149,195,200,194,8,134,149,216,114,1,128,83,192,144,8,194,195,16,12,168,
-110,20,120,12,141,22,16,120,12,100,22,12,120,28,78,99,192,41,224,136,115,
-36,14,100,197,213,245,193,48,189,112,40,2,237,96,175,131,117,2,178,112,145,
-139,163,145,131,114,70,46,142,218,27,182,72,197,209,219,56,26,53,161,166,
-28,1,204,178,10,14,38,78,44,141,52,207,31,0,0,21,64,129,100,180,8,148,145,
-92,203,176,160,226,100,226,200,211,76,241,240,0,1,84,2,131,137,147,142,41,
-100,73,199,192,0,5,88,6,13,10,82,70,62,0,0,42,66,88,115,18,124,67,103,177,
-69,49,130,12,73,242,136,108,246,40,165,177,6,36,248,134,207,71,90,138,99,
-68,152,147,229,16,217,232,235,81,75,130,12,73,241,13,158,158,149,20,199,9,
-49,39,202,33,179,211,210,162,151,69,24,147,225,86,224,79,79,74,138,94,20,
-98,79,133,91,129,61,109,74,41,124,60,137,62,33,179,216,166,216,193,18,36,
-249,68,54,123,20,218,216,137,18,124,67,103,163,173,77,177,162,100,73,242,
-136,108,244,117,169,181,193,18,36,248,134,207,79,74,155,99,132,200,147,229,
-16,217,233,233,83,107,162,164,73,240,171,112,39,167,165,77,175,10,145,39,
-194,173,192,158,182,165,54,191,153,51,72,71,161,196,201,45,167,146,59,68,
-89,24,70,206,0,0,0,0,0,0,7,129,249,153,51,104,71,161,196,201,45,167,146,59,
-68,89,24,70,206,0,0,0,0,0,0,7,129,249,153,51,136,71,161,196,201,45,167,146,
-59,68,89,24,70,206,0,0,0,0,0,0,7,129,249,153,51,168,71,161,196,201,45,167,
-146,59,68,89,24,70,206,0,0,0,0,0,0,0,2,1,153,51,200,71,161,196,201,45,167,
-146,59,68,89,24,70,206,0,0,0,0,0,0,0,2,1,153,51,232,71,161,196,201,45,167,
-146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,153,52,8,71,161,196,201,45,167,
-146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,153,52,40,71,161,196,201,45,167,
-146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,153,52,72,71,161,196,201,45,167,
-146,59,68,89,24,70,206,0,0,0,0,0,0,1,2,1,135,52,102,32,76,72,1,246,136,235,
-103,177,69,1,17,32,7,196,54,123,20,82,88,200,144,3,237,17,214,207,71,91,
-171,37,20,65,145,32,7,218,35,173,158,142,183,66,74,41,16,92,72,1,241,13,
-158,142,183,86,74,41,48,92,72,1,241,13,158,142,183,66,74,41,80,100,72,1,
-246,136,235,103,167,165,213,146,138,40,200,144,3,237,17,214,207,79,75,161,
-37,20,138,46,36,0,248,134,207,79,75,171,37,20,154,46,36,0,248,134,207,79,
-75,161,37,20,170,46,36,0,248,85,184,19,234,201,69,24,92,72,1,240,171,112,
-39,208,146,138,70,25,18,0,124,27,168,21,147,171,37,20,113,145,32,7,193,186,
-129,89,58,18,81,72,226,162,64,15,180,71,91,62,172,148,90,0,168,144,3,237,
-17,214,207,161,37,22,144,38,36,0,248,134,207,171,37,22,160,38,36,0,248,134,
-207,161,37,22,176,42,209,68,201,218,35,173,158,197,54,4,218,40,153,56,134,
-207,98,155,75,27,104,162,100,237,17,214,207,71,91,171,37,54,65,182,138,38,
-78,209,29,108,244,117,186,18,83,104,131,45,20,76,156,67,103,163,173,213,
-146,155,76,25,104,162,100,226,27,61,29,110,132,148,218,160,219,69,19,39,
-104,142,182,122,122,93,89,41,178,141,180,81,50,118,136,235,103,167,165,208,
-146,155,69,25,104,162,100,226,27,61,61,46,172,148,218,104,203,69,19,39,16,
-217,233,233,116,36,166,213,70,90,40,153,56,85,184,19,234,201,77,152,101,
-162,137,147,133,91,129,62,132,148,218,48,219,69,19,39,6,234,5,100,234,201,
-77,156,109,162,137,147,131,117,2,178,116,36,166,209,197,218,40,153,59,68,
-117,179,234,201,78,32,11,180,81,50,118,136,235,103,208,146,156,72,21,104,
-162,100,226,27,62,172,148,226,128,171,69,19,39,16,217,244,36,167,22,53,123,
-102,53,155,80,2,21,11,94,201,128,196,133,0,185,80,32,56,156,199,130,36,160,
-72,16,78,126,54,48,5,146,208,34,82,72,1,109,20,76,155,120,28,34,1,225,32,
-52,171,138,69,133,95,130,160,4,234,219,163,161,0,89,86,214,238,197,172,9,0,
-31,86,221,40,29,231,63,95,200,69,220,199,225,122,183,27,72,144,63,160,138,
-217,81,197,125,207,195,117,110,54,142,129,32,7,114,147,10,189,229,237,159,
-130,235,209,0,96,181,17,83,236,132,37,0,63,101,8,207,71,107,74,6,105,219,
-251,52,245,7,49,248,94,202,17,158,148,12,211,183,246,105,234,15,99,242,159,
-129,228,176,192,185,127,46,155,185,41,197,13,55,38,3,127,255,20,138,160,
-192,25,106,8,8,1,58,90,130,64,128,146,27,168,37,8,9,129,186,130,96,160,152,
-27,165,171,64,32,131,25,234,10,64,65,17,11,212,19,133,18,243,167,165,163,
-32,24,157,45,65,64,6,75,191,80,80,66,149,110,116,117,5,8,41,240,247,79,72,
-188,8,134,81,122,84,1,173,198,212,20,48,139,113,180,181,5,36,42,220,109,29,
-13,65,74,6,192,95,76,188,6,196,55,78,188,6,247,91,86,136,26,32,104,220,205,
-72,1,98,234,52,122,130,136,18,72,51,117,68,3,146,27,168,40,161,37,8,207,80,
-81,129,204,13,212,20,112,179,141,26,45,65,75,112,20,43,193,25,19,66,128,
-153,78,40,105,144,92,104,152,131,124,27,253,128,0,10,116,3,68,146,163,9,
-128,0,10,102,3,138,145,137,27,60,0,0,82,129,7,2,4,16,7,2,70,143,178,203,
-164,237,35,14,25,10,134,147,143,139,158,72,207,28,54,77,47,109,13,55,113,
-120,96,196,159,29,102,241,241,115,201,25,227,131,36,133,20,62,110,143,17,
-16,113,137,62,62,46,155,167,135,147,142,47,44,151,79,221,64,98,37,194,94,
-100,108,144,21,147,140,73,168,228,19,17,124,73,82,54,124,37,230,70,201,14,
-108,185,36,155,14,243,243,83,212,69,131,132,4,12,137,114,168,37,166,145,7,
-10,4,28,200,14,12,40,56,153,56,178,52,211,60,124,0,0,85,0,160,226,100,227,
-138,89,18,113,240,0,1,86,1,131,66,148,145,143,128,0,10,144,93,134,0,0,43,
-80,17,42,4,17,136,49,73,19,49,134,16,143,67,137,146,91,79,36,118,136,178,
-48,141,156,0,0,0,0,0,0,15,3,243,49,135,16,143,67,137,146,91,79,36,118,136,
-178,48,141,156,0,0,0,0,0,0,15,3,245,20,5,173,194,227,214,4,55,0,0,21,196,7,
-122,192,134,241,197,192,0,5,121,25,140,64,132,122,28,76,146,218,121,35,180,
-69,145,132,108,224,0,0,0,0,0,0,120,31,153,140,72,132,122,28,76,146,218,121,
-35,180,69,145,132,108,224,0,0,0,0,0,0,0,32,25,140,80,132,122,28,76,146,218,
-121,35,180,69,145,132,108,224,0,0,0,0,0,0,0,32,25,140,88,132,122,28,76,146,
-218,121,35,180,69,145,132,108,224,0,0,0,0,0,0,8,32,25,140,96,132,122,28,76,
-146,218,121,35,180,69,145,132,108,224,0,0,0,0,0,0,8,32,25,140,104,132,122,
-28,76,146,218,121,35,180,69,145,132,108,224,0,0,0,0,0,0,8,32,25,140,112,
-132,122,28,76,146,218,121,35,180,69,145,132,108,224,0,0,0,0,0,0,16,32,16,
-113,225,0,48,156,209,2,122,244,5,34,92,35,68,225,161,166,218,16,33,18,224,
-104,82,146,59,50,5,7,19,39,22,70,154,103,215,32,28,78,99,193,18,80,70,131,
-165,1,205,34,8,35,68,225,161,166,239,255,4,12,70,137,195,39,248,73,7,78,3,
-154,102,16,70,137,195,67,77,223,248,1,74,9,129,125,255,130,9,65,154,232,
-147,161,115,59,255,5,64,195,32,156,50,126,197,14,2,3,107,173,213,0,
+DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = {
+144,148,105,226,32,68,52,228,254,12,104,202,37,132,52,167,194,138,105,245,
+124,57,28,211,57,18,64,52,239,126,44,138,111,175,241,164,19,87,145,30,33,
+167,22,145,159,8,211,139,9,225,42,5,240,145,139,163,163,8,211,139,10,228,
+64,211,19,132,140,93,29,56,70,156,88,119,34,66,146,36,104,137,194,70,46,
+142,172,35,78,44,47,146,195,102,11,240,145,139,163,175,8,211,139,9,228,240,
+242,112,145,139,163,179,8,211,139,8,237,34,130,118,49,116,118,225,26,48,0,
+1,98,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
+33,8,66,26,180,105,97,167,68,150,34,33,154,112,0,1,91,247,35,79,111,237,
+198,174,232,47,31,23,95,17,13,31,249,96,211,49,50,53,214,77,141,24,0,0,181,
+10,228,240,242,15,128,140,65,128,134,188,0,0,90,167,97,181,224,0,2,213,62,
+53,224,0,2,213,66,237,120,0,0,181,81,204,107,192,0,5,170,150,67,94,0,0,45,
+84,245,90,240,0,1,106,169,162,215,128,0,11,85,93,150,188,0,0,90,171,111,53,
+109,22,162,26,48,0,1,84,23,201,146,243,225,26,39,12,145,136,104,192,0,5,61,
+11,228,201,121,240,100,19,134,72,196,33,195,14,40,203,112,64,190,76,232,
+145,153,136,0,0,0,0,0,0,31,15,249,152,0,0,0,0,0,0,30,15,249,120,144,13,96,
+155,194,56,80,206,36,67,141,20,228,70,57,81,206,100,131,156,39,132,168,23,
+194,70,46,137,208,21,200,129,166,39,9,24,186,39,72,119,34,66,146,36,104,
+137,194,70,46,137,212,23,201,97,179,5,248,72,197,209,58,194,121,60,60,156,
+36,98,232,157,129,29,164,80,78,198,46,137,218,146,121,25,71,146,9,209,5,
+209,61,48,126,14,138,152,30,67,186,23,143,139,175,131,202,135,228,72,85,
+144,83,60,179,30,94,209,233,102,30,98,105,230,103,30,114,121,231,104,30,
+122,137,231,233,30,130,153,232,106,30,138,169,232,235,30,144,67,193,25,19,
+136,108,207,30,41,224,140,137,194,173,192,153,228,5,242,100,188,248,70,137,
+195,36,79,78,47,147,37,231,193,144,78,25,34,122,145,111,36,74,232,176,13,
+17,61,234,226,93,207,148,160,84,75,141,7,27,161,32,33,18,225,80,212,76,154,
+2,2,70,65,56,100,237,34,140,209,2,67,32,156,50,118,145,64,186,230,61,205,
+35,103,155,32,36,141,19,134,78,210,40,206,16,36,70,137,195,39,105,20,11,
+174,99,220,210,54,121,210,1,137,33,1,228,207,16,17,70,146,66,3,201,164,32,
+0,65,112,152,56,196,159,31,23,77,211,195,201,199,23,160,72,214,246,81,6,12,
+73,241,214,111,31,23,60,145,158,56,50,72,81,67,230,232,242,80,19,49,39,199,
+89,188,124,92,242,70,120,227,64,194,75,154,72,12,9,73,6,111,21,120,12,40,
+144,19,39,25,0,225,144,168,105,56,248,185,228,140,241,200,96,64,100,42,26,
+78,62,46,121,35,52,18,92,116,1,36,64,47,158,64,49,98,66,100,156,242,65,23,
+196,149,35,103,194,94,100,108,144,230,203,156,64,66,37,201,16,11,32,249,
+132,4,34,92,44,93,146,55,152,72,24,137,112,151,153,27,36,5,100,229,144,8,
+162,98,92,210,5,76,73,241,214,111,31,23,60,145,158,57,44,48,46,92,185,164,
+160,72,151,41,0,50,107,179,244,59,36,93,127,92,6,19,172,3,11,216,0,56,224,
+151,29,102,241,241,115,201,25,227,164,64,106,37,199,197,211,116,240,242,
+113,197,233,144,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,84,
+129,13,173,161,144,168,105,56,98,78,100,142,214,215,69,1,13,173,161,144,
+168,105,57,34,78,100,142,214,215,69,16,67,107,105,110,114,168,254,24,147,
+153,35,181,181,212,32,67,107,105,110,114,168,254,72,147,153,35,181,181,212,
+36,65,130,3,144,8,26,252,200,13,30,85,16,16,64,90,242,231,192,64,161,163,
+203,31,26,172,193,17,4,23,105,159,96,27,172,251,16,32,196,4,14,137,112,17,
+136,48,164,28,134,80,215,202,1,132,130,8,12,39,52,64,155,31,24,56,36,1,189,
+207,132,0,35,233,35,195,62,3,196,149,36,100,72,160,2,200,232,44,227,0,11,
+37,160,68,142,128,36,157,25,200,32,26,79,90,4,73,43,192,122,54,71,65,103,
+44,248,14,134,140,151,227,138,231,208,45,96,148,248,134,140,151,227,138,
+231,240,1,255,254,10,74,146,56,128,104,4,147,152,72,6,144,28,174,143,8,1,
+30,1,165,3,96,31,0,211,3,21,11,153,35,0,211,131,68,131,160,137,16,250,5,
+196,131,160,137,200,160,199,156,67,248,0,255,255,65,140,10,48,177,115,56,
+35,130,60,19,134,79,89,240,52,177,115,56,39,12,156,123,144,217,251,15,135,
+34,167,30,20,170,154,255,232,12,47,244,0,97,28,17,224,39,238,32,40,71,4,
+120,39,12,156,4,253,228,5,137,195,39,30,228,54,124,4,253,228,128,194,115,
+68,9,252,15,128,232,104,201,126,56,191,35,64,90,193,41,241,13,25,47,199,23,
+228,105,3,86,225,1,100,224,156,199,130,36,249,144,10,192,76,71,250,16,15,
+18,61,96,17,62,200,3,72,128,136,143,247,32,22,75,64,137,248,64,22,79,90,39,
+249,64,38,84,12,167,20,52,223,196,2,230,238,45,214,36,120,32,72,158,208,4,
+102,238,45,194,2,201,197,186,196,143,4,9,19,218,0,92,221,202,61,228,143,4,
+9,19,218,8,35,55,113,110,16,22,78,81,239,36,120,32,72,158,208,64,73,197,12,
+255,0,13,18,60,128,159,212,128,169,76,17,156,185,100,76,255,163,64,65,26,
+57,114,200,153,255,70,144,33,13,18,232,50,75,226,104,6,149,3,41,199,246,
+130,12,128,28,142,156,120,203,175,158,8,194,207,1,6,81,20,79,88,11,237,84,
+11,161,32,127,255,255,255,255,255,247,191,137,235,16,221,170,129,116,36,0,
+16,0,0,0,0,0,0,12,196,0,0,0,0,0,0,15,135,242,61,123,164,137,162,164,218,67,
+74,134,162,120,128,0,0,0,0,0,1,224,254,71,173,33,129,52,84,155,72,105,80,
+212,79,16,0,0,0,0,0,0,60,63,195,244,143,146,22,230,192,0,0,0,0,0,0,176,60,
+33,214,2,251,82,1,73,180,134,204,134,36,96,127,255,255,255,255,255,159,161,
+144,235,16,221,169,0,164,218,67,102,67,18,48,63,255,255,255,255,255,207,
+240,196,60,17,145,56,134,204,241,226,158,8,200,156,42,220,9,158,65,196,34,
+92,42,26,137,147,120,64,74,37,196,54,100,49,35,188,36,5,68,184,208,113,187,
+194,80,212,75,146,1,73,196,54,100,49,35,188,38,57,37,56,240,0,0,0,0,0,0,0,
+0,32,235,248,68,48,156,2,24,94,24,0,243,119,10,139,144,123,242,3,102,238,
+18,239,115,72,217,160,11,223,16,23,55,113,241,32,145,36,57,188,18,16,102,3,
+5,120,35,34,89,32,15,180,152,173,127,0,218,235,88,0,228,180,227,200,0,0,0,
+0,0,0,248,127,197,107,240,64,6,77,220,24,38,78,74,113,67,77,130,4,12,155,
+185,52,48,156,148,226,134,155,4,10,194,96,129,132,166,238,45,194,2,201,193,
+130,100,228,167,20,52,216,32,113,41,187,139,112,128,178,114,104,97,57,41,
+197,13,54,8,32,48,216,32,130,195,224,130,19,97,124,134,23,6,0,57,137,62,77,
+12,38,12,0,179,18,124,45,22,190,96,128,141,176,134,28,98,79,180,152,139,
+218,45,124,193,1,27,97,16,32,196,159,24,230,204,246,194,40,89,137,62,210,
+98,103,92,217,158,216,70,7,49,39,193,130,100,182,17,194,140,73,246,147,16,
+250,9,146,216,72,6,49,39,193,131,22,194,72,73,137,62,210,98,31,65,139,97,
+40,32,196,159,14,234,70,86,194,88,89,137,62,210,98,63,93,72,202,216,76,10,
+49,39,198,33,180,153,37,108,38,134,152,147,237,38,38,117,13,164,201,43,97,
+56,40,196,159,36,65,57,163,149,176,158,26,98,79,180,152,165,210,9,205,28,
+173,133,0,243,18,124,98,22,180,72,130,115,71,43,97,68,72,196,159,105,49,51,
+168,90,209,34,9,205,28,173,133,33,19,18,124,154,24,76,185,164,227,138,89,
+18,119,0,7,145,39,201,161,132,188,64,124,137,62,49,11,90,36,65,57,163,149,
+210,166,37,34,79,180,152,153,212,45,104,145,4,230,142,87,74,160,84,137,62,
+72,130,115,71,43,171,234,134,200,147,237,38,41,116,130,115,71,43,171,235,5,
+72,147,227,16,218,76,146,186,254,184,108,137,62,210,98,103,80,218,76,146,
+186,254,192,68,137,62,29,212,140,174,207,178,23,34,79,180,152,143,215,82,
+50,187,62,208,60,137,62,12,19,37,210,182,21,34,79,180,152,135,208,76,151,
+74,224,68,137,62,49,205,153,238,175,186,23,34,79,180,152,153,215,54,103,
+186,190,240,92,137,62,22,139,95,48,64,70,235,251,225,210,36,251,73,136,189,
+162,215,204,16,17,186,255,2,14,98,79,152,32,35,108,48,64,242,36,249,130,2,
+55,75,6,212,224,72,200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,
+48,98,115,249,201,117,243,249,195,21,159,206,38,47,63,156,86,8,75,144,94,
+82,1,38,73,79,208,67,95,233,1,6,128,14,79,129,186,40,249,18,149,182,207,
+144,200,155,188,248,204,105,184,207,142,199,137,175,201,0,159,72,10,5,21,
+221,10,120,74,129,124,36,98,232,228,74,81,62,160,20,10,107,186,21,114,32,
+105,137,194,70,46,142,68,165,19,235,1,64,170,187,161,119,34,66,146,36,104,
+137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35,
+23,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165,
+19,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,
+72,115,96,0,0,0,0,0,27,234,32,91,60,165,195,201,194,8,134,149,216,162,0,
+192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,
+195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,
+1,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,
+36,98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,
+0,83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,
+102,8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,
+20,28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179,
+216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,
+81,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,
+166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,
+20,188,20,98,79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,
+68,137,62,81,13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,
+159,40,134,207,71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,
+67,103,167,165,77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,
+173,192,158,182,165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,
+140,35,103,0,0,0,0,0,0,3,192,252,206,25,228,35,208,226,100,150,211,201,29,
+162,44,140,35,103,0,0,0,0,0,0,3,192,252,206,25,244,35,208,226,100,150,211,
+201,29,162,44,140,35,103,0,0,0,0,0,0,3,192,252,206,26,4,35,208,226,100,150,
+211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,1,0,206,26,20,35,208,226,100,
+150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,1,0,206,26,36,35,208,226,
+100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,52,35,208,
+226,100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,68,35,
+208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,84,
+35,208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,129,0,195,
+154,99,16,38,36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,
+25,18,0,125,162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,
+235,116,36,162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,
+196,54,122,58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,
+200,144,3,237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,
+213,146,138,77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,
+183,2,125,89,40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,
+221,64,172,157,89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,
+31,104,142,182,125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,
+18,0,124,67,103,213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,
+59,68,117,179,216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,
+39,104,142,182,122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,
+73,77,162,6,90,40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,
+61,29,110,132,148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,
+67,109,20,76,157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,
+167,165,213,146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,
+68,201,194,173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,
+193,182,138,38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,
+178,116,36,166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,
+157,162,58,217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,
+81,50,113,13,159,66,74,113,97,175,221,48,216,110,64,4,42,22,189,179,0,196,
+133,0,185,80,32,28,78,99,193,18,80,36,4,19,159,141,172,0,178,90,4,74,73,0,
+22,209,68,201,187,129,4,2,8,3,132,64,60,36,6,149,113,72,176,171,240,84,0,
+157,91,116,116,32,11,42,218,221,216,181,129,32,3,234,219,165,3,188,231,235,
+249,8,187,152,252,47,86,227,105,18,7,244,17,91,42,56,175,185,248,110,173,
+198,209,208,36,0,238,82,97,87,188,189,179,240,93,122,32,12,22,162,42,125,
+144,132,160,7,236,161,25,232,237,105,64,205,59,127,102,158,160,230,63,11,
+217,66,51,210,129,154,118,254,205,61,65,236,127,171,197,34,168,48,6,90,194,
+1,0,39,75,88,72,8,9,33,186,194,80,64,76,13,214,19,2,130,96,110,150,189,0,
+65,6,51,214,20,128,65,17,11,214,19,130,137,121,211,210,211,144,6,39,75,88,
+80,0,201,119,235,10,8,41,86,231,71,88,80,129,79,135,186,122,133,224,34,25,
+69,234,80,3,91,141,172,40,96,139,113,180,181,133,36,21,110,54,142,134,176,
+165,1,176,23,213,47,0,216,134,234,215,128,111,117,181,232,128,209,3,70,230,
+107,64,5,139,168,209,235,10,32,36,144,102,235,136,3,146,27,172,40,160,146,
+132,103,172,40,192,115,3,117,133,28,22,113,163,69,172,41,103,1,66,188,17,
+145,52,168,4,202,113,67,76,130,227,76,194,13,240,108,0,0,83,224,0,2,193,0,
+104,146,84,97,48,0,1,94,192,56,169,24,145,179,192,0,5,112,8,56,16,32,128,
+56,18,52,125,230,86,147,190,140,28,50,21,13,39,31,23,60,145,158,57,12,141,
+47,129,6,155,194,188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,
+15,155,163,201,68,14,49,39,199,197,211,116,240,242,113,197,232,18,180,254,
+36,3,17,46,18,243,35,100,128,172,156,178,70,163,154,76,34,248,146,164,108,
+248,75,204,141,146,28,217,115,137,27,95,27,241,173,236,162,160,224,200,2,
+206,9,113,13,148,192,209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,
+178,66,213,136,68,201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,
+38,232,255,252,92,221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,
+38,3,66,213,47,135,254,72,12,162,99,133,116,112,0,1,72,66,14,16,16,50,37,
+202,160,150,154,66,14,20,8,57,192,28,24,80,113,50,113,100,105,166,120,248,
+0,0,179,1,65,196,201,199,20,178,36,227,224,0,2,208,54,113,240,0,1,100,11,
+181,192,0,5,178,1,18,160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,
+121,35,180,69,145,132,108,224,0,0,0,0,0,0,120,31,153,188,56,132,122,28,76,
+146,218,121,35,180,69,145,132,108,224,0,0,0,0,0,0,120,31,168,160,45,110,23,
+30,176,33,184,0,0,183,32,29,235,2,27,199,23,0,0,23,4,51,120,129,8,244,56,
+153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,240,63,51,120,145,8,244,
+56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,120,161,8,
+244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,120,177,
+8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,120,
+193,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,
+120,209,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,
+51,120,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,32,
+64,32,227,194,0,97,57,162,4,246,104,5,34,92,35,68,225,161,166,220,16,16,
+137,112,52,41,73,29,185,1,65,196,201,197,145,166,153,246,72,3,137,204,120,
+34,74,8,199,1,67,17,162,112,201,84,128,97,144,78,25,42,16,131,169,1,205,66,
+8,35,68,225,161,166,239,128,0,10,192,64,196,104,156,50,96,0,2,172,73,240,
+117,96,57,170,97,4,104,156,52,52,221,240,0,1,82,1,74,9,129,125,240,0,1,82,
+32,148,25,174,137,58,23,51,190,0,0,42,69,64,195,32,156,50,96,0,2,160,81,
+238,2,3,107,173,218,3,192,
};
#elif defined(DUK_USE_DOUBLE_BE)
-DUK_INTERNAL const duk_uint8_t duk_builtins_data[3972] = {
-144,148,105,223,160,68,52,228,62,12,104,200,165,132,52,167,194,138,105,242,
-252,57,28,211,57,18,64,52,238,62,44,138,111,171,241,164,19,87,125,30,33,
-167,16,145,159,8,211,136,9,225,42,5,240,145,139,163,163,8,211,136,10,228,
-64,211,19,132,140,93,29,56,70,156,64,119,34,66,146,36,104,137,194,70,46,
-142,172,35,78,32,47,146,195,102,11,240,145,139,163,175,8,211,136,9,228,240,
-242,112,145,139,163,179,8,211,136,8,237,34,130,118,49,116,118,225,26,48,0,
-1,80,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
-33,8,66,34,33,154,112,0,1,73,247,35,79,91,237,198,174,192,47,31,23,95,17,
-13,51,19,35,93,68,216,209,128,0,10,192,174,79,15,32,248,8,196,24,8,107,192,
-0,5,98,118,27,94,0,0,43,19,227,94,0,0,43,20,46,215,128,0,10,197,28,198,188,
-0,0,86,41,100,53,224,0,2,177,79,85,175,0,0,21,138,154,45,120,0,0,172,85,
-217,107,192,0,5,98,182,243,86,193,106,52,127,66,249,50,94,124,35,68,225,
-146,49,13,31,170,23,201,146,243,224,200,39,12,145,136,67,134,11,49,1,255,
-224,0,0,0,0,0,3,51,1,255,192,0,0,0,0,0,3,47,18,1,172,19,120,71,10,25,196,
-136,113,162,156,136,199,42,57,204,144,115,132,240,149,2,248,72,197,209,58,
-2,185,16,52,196,225,35,23,68,233,14,228,72,82,68,141,17,56,72,197,209,58,
-130,249,44,54,96,191,9,24,186,39,88,79,39,135,147,132,140,93,19,176,35,180,
-138,9,216,197,209,59,82,79,31,40,242,1,248,58,42,96,121,14,232,94,62,46,
-190,15,38,31,145,33,86,65,76,242,150,143,69,48,242,179,79,45,56,243,51,207,
-53,64,243,116,79,57,72,243,180,207,61,80,243,245,79,65,88,244,34,249,50,94,
-124,35,68,225,146,39,163,23,201,146,243,224,200,39,12,145,61,40,183,146,37,
-116,88,6,136,158,244,241,174,230,202,80,135,130,50,39,16,217,231,208,20,
-240,70,68,225,86,224,79,60,64,84,75,141,7,27,157,32,66,37,194,161,168,153,
-51,132,9,25,4,225,147,180,138,50,196,18,25,4,225,147,180,138,5,215,49,238,
-105,27,60,185,2,72,209,56,100,237,34,140,193,4,136,209,56,100,237,34,129,
-117,204,123,154,70,207,50,64,98,72,64,121,51,68,8,163,73,33,1,228,208,16,0,
-65,112,152,56,196,159,31,23,77,211,195,201,199,23,150,73,169,234,34,24,49,
-39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,196,64,153,137,62,
-58,205,227,226,231,146,51,199,26,6,18,92,130,64,192,148,144,102,240,23,129,
-133,18,2,100,224,160,56,100,42,26,78,62,46,121,35,60,112,216,32,50,21,13,
-39,31,23,60,145,154,9,46,18,1,36,64,47,148,64,98,196,132,201,57,68,132,95,
-18,84,141,159,9,121,145,178,67,155,46,73,2,17,46,72,128,89,7,199,32,66,37,
-194,197,217,35,120,228,131,17,46,18,243,35,100,128,172,156,98,2,40,152,151,
-32,130,166,36,248,235,55,143,139,158,72,207,28,150,24,23,46,92,130,80,72,
-151,21,0,100,213,103,229,245,8,186,190,144,24,78,136,24,94,152,3,142,9,113,
-214,111,31,23,60,145,158,57,164,13,68,184,248,186,110,158,30,78,56,188,226,
-10,62,46,121,35,60,113,18,225,27,70,18,32,10,201,208,32,134,214,208,200,84,
-52,156,49,39,50,71,107,107,152,129,13,173,161,144,168,105,57,34,78,100,142,
-214,215,49,16,134,214,210,220,229,81,252,49,39,50,71,107,107,158,65,13,173,
-165,185,202,163,249,34,78,100,142,214,215,60,146,12,16,28,128,62,175,42,6,
-143,36,136,16,64,90,242,135,192,129,67,71,147,62,65,5,215,231,214,6,215,62,
-180,8,49,1,3,162,92,4,98,12,41,14,67,40,106,229,1,132,130,8,24,78,104,129,
-54,62,96,224,144,13,238,124,32,2,62,146,60,51,224,120,146,164,140,137,20,0,
-178,58,11,56,192,5,146,208,34,71,64,36,157,25,200,32,52,158,180,8,146,87,
-129,232,217,29,5,156,179,224,116,52,100,191,28,87,62,130,214,9,79,136,104,
-201,126,56,174,127,0,31,255,225,73,82,71,16,13,1,36,230,18,1,164,14,87,71,
-132,0,143,0,210,131,96,31,0,211,6,42,23,50,70,1,167,13,18,14,130,36,67,232,
-46,36,29,4,78,69,6,60,226,31,192,7,255,252,24,192,163,11,23,51,130,56,35,
-193,56,100,243,31,6,150,46,103,4,225,147,143,114,27,63,57,241,200,169,194,
-133,42,166,175,240,6,23,240,0,97,28,17,224,39,233,32,80,142,8,240,78,25,56,
-9,250,136,22,39,12,156,123,144,217,240,19,245,18,6,19,154,32,79,214,124,14,
-134,140,151,227,139,237,52,11,88,37,62,33,163,37,248,226,251,77,32,213,184,
-64,89,56,39,49,224,137,61,196,5,96,38,35,251,200,15,18,61,96,17,62,40,6,
-145,1,17,31,228,64,89,45,2,39,205,0,178,122,209,63,162,2,101,64,202,113,67,
-77,247,64,92,221,197,186,196,143,4,9,19,208,1,25,187,139,112,128,178,113,
-110,177,35,193,2,68,244,0,46,110,229,30,242,71,130,4,137,232,4,35,55,113,
-110,16,22,78,81,239,36,120,32,72,158,128,64,147,138,25,249,0,52,72,242,2,
-127,2,5,74,96,140,229,203,34,103,250,154,4,17,163,151,44,137,159,234,105,4,
-33,162,93,6,73,123,13,1,165,64,202,113,251,33,6,64,14,71,78,20,101,213,207,
-4,194,207,2,12,162,0,158,176,23,218,168,23,66,64,127,239,255,255,255,255,
-255,255,19,214,33,187,85,2,232,72,0,0,0,0,0,0,0,0,57,136,15,255,0,0,0,0,0,
-0,4,122,247,73,19,69,73,180,134,149,13,68,241,1,255,192,0,0,0,0,0,0,143,90,
-67,2,104,169,54,144,210,161,168,158,32,127,248,0,0,0,0,0,0,14,73,78,20,0,0,
-0,0,0,0,0,0,8,58,189,233,24,77,217,24,93,240,1,230,238,21,23,32,247,68,13,
-155,184,75,189,205,35,102,128,47,114,64,185,187,143,137,4,137,33,205,222,
-17,6,96,48,87,130,50,37,114,1,246,147,21,143,224,54,186,213,128,114,90,112,
-164,63,252,0,0,0,0,0,0,98,117,119,128,25,55,112,96,153,57,41,197,13,53,224,
-65,147,119,38,134,19,146,156,80,211,94,5,194,94,6,37,55,113,110,16,22,78,
-12,19,39,37,56,161,166,188,14,74,110,226,220,32,44,156,154,24,78,74,113,67,
-77,120,32,97,175,4,28,61,224,133,172,186,70,22,248,1,204,73,242,104,97,47,
-128,44,196,159,11,69,175,152,32,35,100,33,142,49,39,218,76,69,237,22,190,
-96,128,141,144,136,32,196,159,24,230,204,246,66,40,179,18,125,164,196,206,
-185,179,61,144,140,28,196,159,6,9,146,200,71,20,98,79,180,152,135,208,76,
-150,66,64,99,18,124,24,49,100,36,137,49,39,218,76,67,232,49,100,37,8,49,39,
-195,186,145,149,144,150,44,196,159,105,49,31,174,164,101,100,38,10,49,39,
-198,33,180,153,37,100,38,141,49,39,218,76,76,234,27,73,146,86,66,112,163,
-18,124,145,4,230,142,86,66,120,211,18,125,164,197,46,144,78,104,229,100,40,
-15,49,39,198,33,107,68,136,39,52,114,178,20,73,24,147,237,38,38,117,11,90,
-36,65,57,163,149,144,164,68,196,159,38,134,19,46,105,56,226,150,68,157,160,
-3,200,147,228,208,194,92,32,124,137,62,49,11,90,36,65,57,163,149,178,166,
-74,68,159,105,49,51,168,90,209,34,9,205,28,173,149,65,82,36,249,34,9,205,
-28,173,175,170,54,68,159,105,49,75,164,19,154,57,91,95,88,84,137,62,49,13,
-164,201,43,111,235,141,145,39,218,76,76,234,27,73,146,86,223,216,17,34,79,
-135,117,35,43,115,236,139,145,39,218,76,71,235,169,25,91,159,104,60,137,62,
-12,19,37,178,182,42,68,159,105,49,15,160,153,45,149,193,18,36,248,199,54,
-103,182,190,232,185,18,125,164,196,206,185,179,61,181,247,133,200,147,225,
-104,181,243,4,4,109,191,190,58,68,159,105,49,23,180,90,249,130,2,54,223,
-224,67,152,147,230,8,8,217,12,16,121,18,124,193,1,27,101,131,131,56,7,38,
-193,198,72,0,0,0,0,0,0,0,0,198,231,240,134,39,63,136,151,95,63,136,49,89,
-252,66,98,243,248,133,96,132,185,5,224,32,36,201,41,248,200,213,249,0,131,
-64,7,39,192,218,148,124,137,74,216,231,198,227,141,182,124,78,40,217,231,
-197,227,4,213,227,192,159,72,10,5,21,218,138,120,74,129,124,36,98,232,228,
-74,81,62,160,20,10,107,181,21,114,32,105,137,194,70,46,142,68,165,19,235,1,
-64,170,187,81,119,34,66,146,36,104,137,194,70,46,142,68,165,19,236,1,64,
-174,187,81,95,37,134,204,23,225,35,23,71,34,82,137,246,128,160,89,93,168,
-167,147,195,201,194,70,46,142,68,165,19,238,1,64,182,187,81,71,105,20,19,
-177,139,163,145,41,68,16,7,6,15,82,70,72,115,96,32,105,221,0,0,0,0,0,91,60,
-149,195,200,194,8,134,149,216,114,1,128,83,192,144,8,194,195,16,12,168,110,
-20,120,12,141,22,16,120,12,100,22,12,120,28,78,99,192,41,224,136,115,36,14,
-100,197,213,245,193,48,189,112,40,2,237,96,175,131,117,2,178,112,145,139,
-163,145,131,114,70,46,142,218,27,182,72,197,209,219,56,26,53,161,166,28,1,
-204,178,10,14,38,78,44,141,52,207,31,0,0,21,64,129,100,180,8,148,145,92,
-203,176,160,226,100,226,200,211,76,241,240,0,1,84,2,131,137,147,142,41,100,
-73,199,192,0,5,88,6,13,10,82,70,62,0,0,42,66,88,115,18,124,67,103,177,69,
-49,130,12,73,242,136,108,246,40,165,177,6,36,248,134,207,71,90,138,99,68,
-152,147,229,16,217,232,235,81,75,130,12,73,241,13,158,158,149,20,199,9,49,
-39,202,33,179,211,210,162,151,69,24,147,225,86,224,79,79,74,138,94,20,98,
-79,133,91,129,61,109,74,41,124,60,137,62,33,179,216,166,216,193,18,36,249,
-68,54,123,20,218,216,137,18,124,67,103,163,173,77,177,162,100,73,242,136,
-108,244,117,169,181,193,18,36,248,134,207,79,74,155,99,132,200,147,229,16,
-217,233,233,83,107,162,164,73,240,171,112,39,167,165,77,175,10,145,39,194,
-173,192,158,182,165,54,191,153,51,72,71,161,196,201,45,167,146,59,68,89,24,
-70,206,1,255,128,0,0,0,0,0,1,153,51,104,71,161,196,201,45,167,146,59,68,89,
-24,70,206,1,255,128,0,0,0,0,0,1,153,51,136,71,161,196,201,45,167,146,59,68,
-89,24,70,206,1,255,128,0,0,0,0,0,1,153,51,168,71,161,196,201,45,167,146,59,
-68,89,24,70,206,2,0,0,0,0,0,0,0,1,153,51,200,71,161,196,201,45,167,146,59,
-68,89,24,70,206,2,0,0,0,0,0,0,0,1,153,51,232,71,161,196,201,45,167,146,59,
-68,89,24,70,206,2,0,128,0,0,0,0,0,1,153,52,8,71,161,196,201,45,167,146,59,
-68,89,24,70,206,2,0,128,0,0,0,0,0,1,153,52,40,71,161,196,201,45,167,146,59,
-68,89,24,70,206,2,0,128,0,0,0,0,0,1,153,52,72,71,161,196,201,45,167,146,59,
-68,89,24,70,206,2,1,0,0,0,0,0,0,1,135,52,102,32,76,72,1,246,136,235,103,
-177,69,1,17,32,7,196,54,123,20,82,88,200,144,3,237,17,214,207,71,91,171,37,
-20,65,145,32,7,218,35,173,158,142,183,66,74,41,16,92,72,1,241,13,158,142,
-183,86,74,41,48,92,72,1,241,13,158,142,183,66,74,41,80,100,72,1,246,136,
-235,103,167,165,213,146,138,40,200,144,3,237,17,214,207,79,75,161,37,20,
-138,46,36,0,248,134,207,79,75,171,37,20,154,46,36,0,248,134,207,79,75,161,
-37,20,170,46,36,0,248,85,184,19,234,201,69,24,92,72,1,240,171,112,39,208,
-146,138,70,25,18,0,124,27,168,21,147,171,37,20,113,145,32,7,193,186,129,89,
-58,18,81,72,226,162,64,15,180,71,91,62,172,148,90,0,168,144,3,237,17,214,
-207,161,37,22,144,38,36,0,248,134,207,171,37,22,160,38,36,0,248,134,207,
-161,37,22,176,42,209,68,201,218,35,173,158,197,54,4,218,40,153,56,134,207,
-98,155,75,27,104,162,100,237,17,214,207,71,91,171,37,54,65,182,138,38,78,
-209,29,108,244,117,186,18,83,104,131,45,20,76,156,67,103,163,173,213,146,
-155,76,25,104,162,100,226,27,61,29,110,132,148,218,160,219,69,19,39,104,
-142,182,122,122,93,89,41,178,141,180,81,50,118,136,235,103,167,165,208,146,
-155,69,25,104,162,100,226,27,61,61,46,172,148,218,104,203,69,19,39,16,217,
-233,233,116,36,166,213,70,90,40,153,56,85,184,19,234,201,77,152,101,162,
-137,147,133,91,129,62,132,148,218,48,219,69,19,39,6,234,5,100,234,201,77,
-156,109,162,137,147,131,117,2,178,116,36,166,209,197,218,40,153,59,68,117,
-179,234,201,78,32,11,180,81,50,118,136,235,103,208,146,156,72,21,104,162,
-100,226,27,62,172,148,226,128,171,69,19,39,16,217,244,36,167,22,53,123,102,
-53,155,80,2,21,11,94,201,128,196,133,0,185,80,32,56,156,199,130,36,160,72,
-16,78,126,54,48,5,146,208,34,82,72,1,109,20,76,155,120,28,34,1,225,32,32,2,
-223,133,69,138,43,180,132,234,219,163,161,1,0,9,174,198,238,213,84,88,31,
-86,221,40,7,252,197,200,95,223,71,61,225,122,183,27,72,144,15,253,197,81,
-217,74,224,191,131,117,110,54,142,129,32,31,237,229,189,138,147,114,135,2,
-235,209,1,0,36,135,237,81,16,180,96,63,101,8,207,71,107,74,1,255,53,4,243,
-51,249,222,104,94,202,17,158,148,3,255,106,9,230,103,243,188,210,159,129,
-228,176,192,185,127,46,155,185,41,197,13,55,38,3,127,255,20,138,160,192,25,
-106,8,8,1,58,90,130,64,128,146,27,168,37,8,9,129,186,130,96,160,152,27,165,
-171,64,32,131,25,234,10,64,65,17,11,212,19,133,18,243,167,165,163,32,24,
-157,45,65,64,6,75,191,80,80,66,149,110,116,117,5,8,41,240,247,79,72,188,8,
-134,81,122,84,1,173,198,212,20,48,139,113,180,181,5,36,42,220,109,29,13,65,
-74,6,192,95,76,188,6,196,55,78,188,6,247,91,86,136,26,32,104,220,205,72,1,
-98,234,52,122,130,136,18,72,51,117,68,3,146,27,168,40,161,37,8,207,80,81,
-129,204,13,212,20,112,179,141,26,45,65,75,112,20,43,193,25,19,66,128,153,
-78,40,105,144,92,104,152,131,124,27,253,128,0,10,116,3,68,146,163,9,128,0,
-10,102,3,138,145,137,27,60,0,0,82,129,7,2,4,16,7,2,70,143,178,203,164,237,
-35,14,25,10,134,147,143,139,158,72,207,28,54,77,47,109,13,55,113,120,96,
-196,159,29,102,241,241,115,201,25,227,131,36,133,20,62,110,143,17,16,113,
-137,62,62,46,155,167,135,147,142,47,44,151,79,221,64,98,37,194,94,100,108,
-144,21,147,140,73,168,228,19,17,124,73,82,54,124,37,230,70,201,14,108,185,
-36,155,14,243,243,83,212,69,131,132,4,12,137,114,168,37,166,145,7,10,4,28,
-200,14,12,40,56,153,56,178,52,211,60,124,0,0,85,0,160,226,100,227,138,89,
-18,113,240,0,1,86,1,131,66,148,145,143,128,0,10,144,93,134,0,0,43,80,17,42,
-4,17,136,49,73,19,49,134,16,143,67,137,146,91,79,36,118,136,178,48,141,156,
-3,255,0,0,0,0,0,0,3,49,135,16,143,67,137,146,91,79,36,118,136,178,48,141,
-156,3,255,0,0,0,0,0,0,5,20,5,173,194,227,214,4,55,0,0,21,196,7,122,192,134,
-241,197,192,0,5,121,25,140,64,132,122,28,76,146,218,121,35,180,69,145,132,
-108,224,31,248,0,0,0,0,0,0,25,140,72,132,122,28,76,146,218,121,35,180,69,
-145,132,108,224,32,0,0,0,0,0,0,0,25,140,80,132,122,28,76,146,218,121,35,
-180,69,145,132,108,224,32,0,0,0,0,0,0,0,25,140,88,132,122,28,76,146,218,
-121,35,180,69,145,132,108,224,32,8,0,0,0,0,0,0,25,140,96,132,122,28,76,146,
-218,121,35,180,69,145,132,108,224,32,8,0,0,0,0,0,0,25,140,104,132,122,28,
-76,146,218,121,35,180,69,145,132,108,224,32,8,0,0,0,0,0,0,25,140,112,132,
-122,28,76,146,218,121,35,180,69,145,132,108,224,32,16,0,0,0,0,0,0,16,113,
-225,0,48,156,209,2,122,244,5,34,92,35,68,225,161,166,218,16,33,18,224,104,
-82,146,59,50,5,7,19,39,22,70,154,103,215,32,28,78,99,193,18,80,70,131,165,
-1,205,34,8,35,68,225,161,166,239,255,4,12,70,137,195,39,248,73,7,78,3,154,
-102,16,70,137,195,67,77,223,248,1,74,9,129,125,255,130,9,65,154,232,147,
-161,115,59,255,5,64,195,32,156,50,126,197,14,2,3,107,173,213,0,
+DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = {
+144,148,105,226,32,68,52,228,254,12,104,202,37,132,52,167,194,138,105,245,
+124,57,28,211,57,18,64,52,239,126,44,138,111,175,241,164,19,87,145,30,33,
+167,22,145,159,8,211,139,9,225,42,5,240,145,139,163,163,8,211,139,10,228,
+64,211,19,132,140,93,29,56,70,156,88,119,34,66,146,36,104,137,194,70,46,
+142,172,35,78,44,47,146,195,102,11,240,145,139,163,175,8,211,139,9,228,240,
+242,112,145,139,163,179,8,211,139,8,237,34,130,118,49,116,118,225,26,48,0,
+1,98,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
+33,8,66,26,180,105,97,167,68,150,34,33,154,112,0,1,91,247,35,79,111,237,
+198,174,232,47,31,23,95,17,13,31,249,96,211,49,50,53,214,77,141,24,0,0,181,
+10,228,240,242,15,128,140,65,128,134,188,0,0,90,167,97,181,224,0,2,213,62,
+53,224,0,2,213,66,237,120,0,0,181,81,204,107,192,0,5,170,150,67,94,0,0,45,
+84,245,90,240,0,1,106,169,162,215,128,0,11,85,93,150,188,0,0,90,171,111,53,
+109,22,162,26,48,0,1,84,23,201,146,243,225,26,39,12,145,136,104,192,0,5,61,
+11,228,201,121,240,100,19,134,72,196,33,195,14,40,203,112,64,190,76,232,
+145,153,136,15,255,0,0,0,0,0,0,25,152,15,254,0,0,0,0,0,0,25,120,144,13,96,
+155,194,56,80,206,36,67,141,20,228,70,57,81,206,100,131,156,39,132,168,23,
+194,70,46,137,208,21,200,129,166,39,9,24,186,39,72,119,34,66,146,36,104,
+137,194,70,46,137,212,23,201,97,179,5,248,72,197,209,58,194,121,60,60,156,
+36,98,232,157,129,29,164,80,78,198,46,137,218,146,121,25,71,146,9,209,5,
+209,61,48,126,14,138,152,30,67,186,23,143,139,175,131,202,135,228,72,85,
+144,83,60,179,30,94,209,233,102,30,98,105,230,103,30,114,121,231,104,30,
+122,137,231,233,30,130,153,232,106,30,138,169,232,235,30,144,67,193,25,19,
+136,108,207,30,41,224,140,137,194,173,192,153,228,5,242,100,188,248,70,137,
+195,36,79,78,47,147,37,231,193,144,78,25,34,122,145,111,36,74,232,176,13,
+17,61,234,226,93,207,148,160,84,75,141,7,27,161,32,33,18,225,80,212,76,154,
+2,2,70,65,56,100,237,34,140,209,2,67,32,156,50,118,145,64,186,230,61,205,
+35,103,155,32,36,141,19,134,78,210,40,206,16,36,70,137,195,39,105,20,11,
+174,99,220,210,54,121,210,1,137,33,1,228,207,16,17,70,146,66,3,201,164,32,
+0,65,112,152,56,196,159,31,23,77,211,195,201,199,23,160,72,214,246,81,6,12,
+73,241,214,111,31,23,60,145,158,56,50,72,81,67,230,232,242,80,19,49,39,199,
+89,188,124,92,242,70,120,227,64,194,75,154,72,12,9,73,6,111,21,120,12,40,
+144,19,39,25,0,225,144,168,105,56,248,185,228,140,241,200,96,64,100,42,26,
+78,62,46,121,35,52,18,92,116,1,36,64,47,158,64,49,98,66,100,156,242,65,23,
+196,149,35,103,194,94,100,108,144,230,203,156,64,66,37,201,16,11,32,249,
+132,4,34,92,44,93,146,55,152,72,24,137,112,151,153,27,36,5,100,229,144,8,
+162,98,92,210,5,76,73,241,214,111,31,23,60,145,158,57,44,48,46,92,185,164,
+160,72,151,41,0,50,107,179,244,59,36,93,127,92,6,19,172,3,11,216,0,56,224,
+151,29,102,241,241,115,201,25,227,164,64,106,37,199,197,211,116,240,242,
+113,197,233,144,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,84,
+129,13,173,161,144,168,105,56,98,78,100,142,214,215,69,1,13,173,161,144,
+168,105,57,34,78,100,142,214,215,69,16,67,107,105,110,114,168,254,24,147,
+153,35,181,181,212,32,67,107,105,110,114,168,254,72,147,153,35,181,181,212,
+36,65,130,3,144,8,26,252,200,13,30,85,16,16,64,90,242,231,192,64,161,163,
+203,31,26,172,193,17,4,23,105,159,96,27,172,251,16,32,196,4,14,137,112,17,
+136,48,164,28,134,80,215,202,1,132,130,8,12,39,52,64,155,31,24,56,36,1,189,
+207,132,0,35,233,35,195,62,3,196,149,36,100,72,160,2,200,232,44,227,0,11,
+37,160,68,142,128,36,157,25,200,32,26,79,90,4,73,43,192,122,54,71,65,103,
+44,248,14,134,140,151,227,138,231,208,45,96,148,248,134,140,151,227,138,
+231,240,1,255,254,10,74,146,56,128,104,4,147,152,72,6,144,28,174,143,8,1,
+30,1,165,3,96,31,0,211,3,21,11,153,35,0,211,131,68,131,160,137,16,250,5,
+196,131,160,137,200,160,199,156,67,248,0,255,255,65,140,10,48,177,115,56,
+35,130,60,19,134,79,89,240,52,177,115,56,39,12,156,123,144,217,251,15,135,
+34,167,30,20,170,154,255,232,12,47,244,0,97,28,17,224,39,238,32,40,71,4,
+120,39,12,156,4,253,228,5,137,195,39,30,228,54,124,4,253,228,128,194,115,
+68,9,252,15,128,232,104,201,126,56,191,35,64,90,193,41,241,13,25,47,199,23,
+228,105,3,86,225,1,100,224,156,199,130,36,249,144,10,192,76,71,250,16,15,
+18,61,96,17,62,200,3,72,128,136,143,247,32,22,75,64,137,248,64,22,79,90,39,
+249,64,38,84,12,167,20,52,223,196,2,230,238,45,214,36,120,32,72,158,208,4,
+102,238,45,194,2,201,197,186,196,143,4,9,19,218,0,92,221,202,61,228,143,4,
+9,19,218,8,35,55,113,110,16,22,78,81,239,36,120,32,72,158,208,64,73,197,12,
+255,0,13,18,60,128,159,212,128,169,76,17,156,185,100,76,255,163,64,65,26,
+57,114,200,153,255,70,144,33,13,18,232,50,75,226,104,6,149,3,41,199,246,
+130,12,128,28,142,156,120,203,175,158,8,194,207,1,6,81,20,79,88,11,237,84,
+11,161,32,63,247,255,255,255,255,255,255,137,235,16,221,170,129,116,36,0,0,
+0,0,0,0,0,0,28,196,7,255,128,0,0,0,0,0,2,61,123,164,137,162,164,218,67,74,
+134,162,120,128,255,224,0,0,0,0,0,0,71,173,33,129,52,84,155,72,105,80,212,
+79,16,63,252,0,0,0,0,0,0,3,244,143,146,22,230,192,60,176,0,0,0,0,0,0,33,
+214,2,251,82,1,73,180,134,204,134,36,96,33,159,255,255,255,255,255,255,144,
+235,16,221,169,0,164,218,67,102,67,18,48,48,207,255,255,255,255,255,255,
+196,60,17,145,56,134,204,241,226,158,8,200,156,42,220,9,158,65,196,34,92,
+42,26,137,147,120,64,74,37,196,54,100,49,35,188,36,5,68,184,208,113,187,
+194,80,212,75,146,1,73,196,54,100,49,35,188,38,57,37,56,240,0,0,0,0,0,0,0,
+0,32,235,248,68,48,156,2,24,94,24,0,243,119,10,139,144,123,242,3,102,238,
+18,239,115,72,217,160,11,223,16,23,55,113,241,32,145,36,57,188,18,16,102,3,
+5,120,35,34,89,32,15,180,152,173,127,0,218,235,88,0,228,180,227,200,127,
+248,0,0,0,0,0,0,197,107,240,64,6,77,220,24,38,78,74,113,67,77,130,4,12,155,
+185,52,48,156,148,226,134,155,4,10,194,96,129,132,166,238,45,194,2,201,193,
+130,100,228,167,20,52,216,32,113,41,187,139,112,128,178,114,104,97,57,41,
+197,13,54,8,32,48,216,32,130,195,224,130,19,97,124,134,23,6,0,57,137,62,77,
+12,38,12,0,179,18,124,45,22,190,96,128,141,176,134,28,98,79,180,152,139,
+218,45,124,193,1,27,97,16,32,196,159,24,230,204,246,194,40,89,137,62,210,
+98,103,92,217,158,216,70,7,49,39,193,130,100,182,17,194,140,73,246,147,16,
+250,9,146,216,72,6,49,39,193,131,22,194,72,73,137,62,210,98,31,65,139,97,
+40,32,196,159,14,234,70,86,194,88,89,137,62,210,98,63,93,72,202,216,76,10,
+49,39,198,33,180,153,37,108,38,134,152,147,237,38,38,117,13,164,201,43,97,
+56,40,196,159,36,65,57,163,149,176,158,26,98,79,180,152,165,210,9,205,28,
+173,133,0,243,18,124,98,22,180,72,130,115,71,43,97,68,72,196,159,105,49,51,
+168,90,209,34,9,205,28,173,133,33,19,18,124,154,24,76,185,164,227,138,89,
+18,119,0,7,145,39,201,161,132,188,64,124,137,62,49,11,90,36,65,57,163,149,
+210,166,37,34,79,180,152,153,212,45,104,145,4,230,142,87,74,160,84,137,62,
+72,130,115,71,43,171,234,134,200,147,237,38,41,116,130,115,71,43,171,235,5,
+72,147,227,16,218,76,146,186,254,184,108,137,62,210,98,103,80,218,76,146,
+186,254,192,68,137,62,29,212,140,174,207,178,23,34,79,180,152,143,215,82,
+50,187,62,208,60,137,62,12,19,37,210,182,21,34,79,180,152,135,208,76,151,
+74,224,68,137,62,49,205,153,238,175,186,23,34,79,180,152,153,215,54,103,
+186,190,240,92,137,62,22,139,95,48,64,70,235,251,225,210,36,251,73,136,189,
+162,215,204,16,17,186,255,2,14,98,79,152,32,35,108,48,64,242,36,249,130,2,
+55,75,6,212,224,72,200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,
+48,98,115,249,201,117,243,249,195,21,159,206,38,47,63,156,86,8,75,144,94,
+82,1,38,73,79,208,67,95,233,1,6,128,14,79,129,186,40,249,18,149,182,207,
+144,200,155,188,248,204,105,184,207,142,199,137,175,201,0,159,72,10,5,21,
+221,10,120,74,129,124,36,98,232,228,74,81,62,160,20,10,107,186,21,114,32,
+105,137,194,70,46,142,68,165,19,235,1,64,170,187,161,119,34,66,146,36,104,
+137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35,
+23,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165,
+19,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,
+72,115,96,32,106,27,128,0,0,0,0,91,60,165,195,201,194,8,134,149,216,162,0,
+192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,
+195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,
+1,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,
+36,98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,
+0,83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,
+102,8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,
+20,28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179,
+216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,
+81,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,
+166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,
+20,188,20,98,79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,
+68,137,62,81,13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,
+159,40,134,207,71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,
+67,103,167,165,77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,
+173,192,158,182,165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,
+140,35,103,0,255,192,0,0,0,0,0,0,206,25,228,35,208,226,100,150,211,201,29,
+162,44,140,35,103,0,255,192,0,0,0,0,0,0,206,25,244,35,208,226,100,150,211,
+201,29,162,44,140,35,103,0,255,192,0,0,0,0,0,0,206,26,4,35,208,226,100,150,
+211,201,29,162,44,140,35,103,1,0,0,0,0,0,0,0,0,206,26,20,35,208,226,100,
+150,211,201,29,162,44,140,35,103,1,0,0,0,0,0,0,0,0,206,26,36,35,208,226,
+100,150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,52,35,208,
+226,100,150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,68,35,
+208,226,100,150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,84,
+35,208,226,100,150,211,201,29,162,44,140,35,103,1,0,128,0,0,0,0,0,0,195,
+154,99,16,38,36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,
+25,18,0,125,162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,
+235,116,36,162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,
+196,54,122,58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,
+200,144,3,237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,
+213,146,138,77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,
+183,2,125,89,40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,
+221,64,172,157,89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,
+31,104,142,182,125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,
+18,0,124,67,103,213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,
+59,68,117,179,216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,
+39,104,142,182,122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,
+73,77,162,6,90,40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,
+61,29,110,132,148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,
+67,109,20,76,157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,
+167,165,213,146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,
+68,201,194,173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,
+193,182,138,38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,
+178,116,36,166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,
+157,162,58,217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,
+81,50,113,13,159,66,74,113,97,175,221,48,216,110,64,4,42,22,189,179,0,196,
+133,0,185,80,32,28,78,99,193,18,80,36,4,19,159,141,172,0,178,90,4,74,73,0,
+22,209,68,201,187,129,4,2,8,3,132,64,60,36,4,0,91,240,168,177,69,118,144,
+157,91,116,116,32,32,1,53,216,221,218,170,139,3,234,219,165,0,255,152,185,
+11,251,232,231,188,47,86,227,105,18,1,255,184,170,59,41,92,23,240,110,173,
+198,209,208,36,3,253,188,183,177,82,110,80,224,93,122,32,32,4,144,253,170,
+34,22,140,7,236,161,25,232,237,105,64,63,230,160,158,102,127,59,205,11,217,
+66,51,210,128,127,237,65,60,204,254,119,155,171,197,34,168,48,6,90,194,1,0,
+39,75,88,72,8,9,33,186,194,80,64,76,13,214,19,2,130,96,110,150,189,0,65,6,
+51,214,20,128,65,17,11,214,19,130,137,121,211,210,211,144,6,39,75,88,80,0,
+201,119,235,10,8,41,86,231,71,88,80,129,79,135,186,122,133,224,34,25,69,
+234,80,3,91,141,172,40,96,139,113,180,181,133,36,21,110,54,142,134,176,165,
+1,176,23,213,47,0,216,134,234,215,128,111,117,181,232,128,209,3,70,230,107,
+64,5,139,168,209,235,10,32,36,144,102,235,136,3,146,27,172,40,160,146,132,
+103,172,40,192,115,3,117,133,28,22,113,163,69,172,41,103,1,66,188,17,145,
+52,168,4,202,113,67,76,130,227,76,194,13,240,108,0,0,83,224,0,2,193,0,104,
+146,84,97,48,0,1,94,192,56,169,24,145,179,192,0,5,112,8,56,16,32,128,56,18,
+52,125,230,86,147,190,140,28,50,21,13,39,31,23,60,145,158,57,12,141,47,129,
+6,155,194,188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,
+163,201,68,14,49,39,199,197,211,116,240,242,113,197,232,18,180,254,36,3,17,
+46,18,243,35,100,128,172,156,178,70,163,154,76,34,248,146,164,108,248,75,
+204,141,146,28,217,115,137,27,95,27,241,173,236,162,160,224,200,2,206,9,
+113,13,148,192,209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,178,
+66,213,136,68,201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,38,
+232,255,252,92,221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,38,
+3,66,213,47,135,254,72,12,162,99,133,116,112,0,1,72,66,14,16,16,50,37,202,
+160,150,154,66,14,20,8,57,192,28,24,80,113,50,113,100,105,166,120,248,0,0,
+179,1,65,196,201,199,20,178,36,227,224,0,2,208,54,113,240,0,1,100,11,181,
+192,0,5,178,1,18,160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,121,
+35,180,69,145,132,108,224,31,248,0,0,0,0,0,0,25,188,56,132,122,28,76,146,
+218,121,35,180,69,145,132,108,224,31,248,0,0,0,0,0,0,40,160,45,110,23,30,
+176,33,184,0,0,183,32,29,235,2,27,199,23,0,0,23,4,51,120,129,8,244,56,153,
+37,180,242,71,104,139,35,8,217,192,63,240,0,0,0,0,0,0,51,120,145,8,244,56,
+153,37,180,242,71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,120,161,8,244,
+56,153,37,180,242,71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,120,177,8,
+244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,120,193,
+8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,120,
+209,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,
+120,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,32,0,0,0,0,0,0,
+32,227,194,0,97,57,162,4,246,104,5,34,92,35,68,225,161,166,220,16,16,137,
+112,52,41,73,29,185,1,65,196,201,197,145,166,153,246,72,3,137,204,120,34,
+74,8,199,1,67,17,162,112,201,84,128,97,144,78,25,42,16,131,169,1,205,66,8,
+35,68,225,161,166,239,128,0,10,192,64,196,104,156,50,96,0,2,172,73,240,117,
+96,57,170,97,4,104,156,52,52,221,240,0,1,82,1,74,9,129,125,240,0,1,82,32,
+148,25,174,137,58,23,51,190,0,0,42,69,64,195,32,156,50,96,0,2,160,81,238,2,
+3,107,173,218,3,192,
};
#elif defined(DUK_USE_DOUBLE_ME)
-DUK_INTERNAL const duk_uint8_t duk_builtins_data[3972] = {
-144,148,105,223,160,68,52,228,62,12,104,200,165,132,52,167,194,138,105,242,
-252,57,28,211,57,18,64,52,238,62,44,138,111,171,241,164,19,87,125,30,33,
-167,16,145,159,8,211,136,9,225,42,5,240,145,139,163,163,8,211,136,10,228,
-64,211,19,132,140,93,29,56,70,156,64,119,34,66,146,36,104,137,194,70,46,
-142,172,35,78,32,47,146,195,102,11,240,145,139,163,175,8,211,136,9,228,240,
-242,112,145,139,163,179,8,211,136,8,237,34,130,118,49,116,118,225,26,48,0,
-1,80,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
-33,8,66,34,33,154,112,0,1,73,247,35,79,91,237,198,174,192,47,31,23,95,17,
-13,51,19,35,93,68,216,209,128,0,10,192,174,79,15,32,248,8,196,24,8,107,192,
-0,5,98,118,27,94,0,0,43,19,227,94,0,0,43,20,46,215,128,0,10,197,28,198,188,
-0,0,86,41,100,53,224,0,2,177,79,85,175,0,0,21,138,154,45,120,0,0,172,85,
-217,107,192,0,5,98,182,243,86,193,106,52,127,66,249,50,94,124,35,68,225,
-146,49,13,31,170,23,201,146,243,224,200,39,12,145,136,67,134,11,49,0,0,3,
-225,252,0,0,0,3,51,0,0,3,193,252,0,0,0,3,47,18,1,172,19,120,71,10,25,196,
-136,113,162,156,136,199,42,57,204,144,115,132,240,149,2,248,72,197,209,58,
-2,185,16,52,196,225,35,23,68,233,14,228,72,82,68,141,17,56,72,197,209,58,
-130,249,44,54,96,191,9,24,186,39,88,79,39,135,147,132,140,93,19,176,35,180,
-138,9,216,197,209,59,82,79,31,40,242,1,248,58,42,96,121,14,232,94,62,46,
-190,15,38,31,145,33,86,65,76,242,150,143,69,48,242,179,79,45,56,243,51,207,
-53,64,243,116,79,57,72,243,180,207,61,80,243,245,79,65,88,244,34,249,50,94,
-124,35,68,225,146,39,163,23,201,146,243,224,200,39,12,145,61,40,183,146,37,
-116,88,6,136,158,244,241,174,230,202,80,135,130,50,39,16,217,231,208,20,
-240,70,68,225,86,224,79,60,64,84,75,141,7,27,157,32,66,37,194,161,168,153,
-51,132,9,25,4,225,147,180,138,50,196,18,25,4,225,147,180,138,5,215,49,238,
-105,27,60,185,2,72,209,56,100,237,34,140,193,4,136,209,56,100,237,34,129,
-117,204,123,154,70,207,50,64,98,72,64,121,51,68,8,163,73,33,1,228,208,16,0,
-65,112,152,56,196,159,31,23,77,211,195,201,199,23,150,73,169,234,34,24,49,
-39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,196,64,153,137,62,
-58,205,227,226,231,146,51,199,26,6,18,92,130,64,192,148,144,102,240,23,129,
-133,18,2,100,224,160,56,100,42,26,78,62,46,121,35,60,112,216,32,50,21,13,
-39,31,23,60,145,154,9,46,18,1,36,64,47,148,64,98,196,132,201,57,68,132,95,
-18,84,141,159,9,121,145,178,67,155,46,73,2,17,46,72,128,89,7,199,32,66,37,
-194,197,217,35,120,228,131,17,46,18,243,35,100,128,172,156,98,2,40,152,151,
-32,130,166,36,248,235,55,143,139,158,72,207,28,150,24,23,46,92,130,80,72,
-151,21,0,100,213,103,229,245,8,186,190,144,24,78,136,24,94,152,3,142,9,113,
-214,111,31,23,60,145,158,57,164,13,68,184,248,186,110,158,30,78,56,188,226,
-10,62,46,121,35,60,113,18,225,27,70,18,32,10,201,208,32,134,214,208,200,84,
-52,156,49,39,50,71,107,107,152,129,13,173,161,144,168,105,57,34,78,100,142,
-214,215,49,16,134,214,210,220,229,81,252,49,39,50,71,107,107,158,65,13,173,
-165,185,202,163,249,34,78,100,142,214,215,60,146,12,16,28,128,62,175,42,6,
-143,36,136,16,64,90,242,135,192,129,67,71,147,62,65,5,215,231,214,6,215,62,
-180,8,49,1,3,162,92,4,98,12,41,14,67,40,106,229,1,132,130,8,24,78,104,129,
-54,62,96,224,144,13,238,124,32,2,62,146,60,51,224,120,146,164,140,137,20,0,
-178,58,11,56,192,5,146,208,34,71,64,36,157,25,200,32,52,158,180,8,146,87,
-129,232,217,29,5,156,179,224,116,52,100,191,28,87,62,130,214,9,79,136,104,
-201,126,56,174,127,0,31,255,225,73,82,71,16,13,1,36,230,18,1,164,14,87,71,
-132,0,143,0,210,131,96,31,0,211,6,42,23,50,70,1,167,13,18,14,130,36,67,232,
-46,36,29,4,78,69,6,60,226,31,192,7,255,252,24,192,163,11,23,51,130,56,35,
-193,56,100,243,31,6,150,46,103,4,225,147,143,114,27,63,57,241,200,169,194,
-133,42,166,175,240,6,23,240,0,97,28,17,224,39,233,32,80,142,8,240,78,25,56,
-9,250,136,22,39,12,156,123,144,217,240,19,245,18,6,19,154,32,79,214,124,14,
-134,140,151,227,139,237,52,11,88,37,62,33,163,37,248,226,251,77,32,213,184,
-64,89,56,39,49,224,137,61,196,5,96,38,35,251,200,15,18,61,96,17,62,40,6,
-145,1,17,31,228,64,89,45,2,39,205,0,178,122,209,63,162,2,101,64,202,113,67,
-77,247,64,92,221,197,186,196,143,4,9,19,208,1,25,187,139,112,128,178,113,
-110,177,35,193,2,68,244,0,46,110,229,30,242,71,130,4,137,232,4,35,55,113,
-110,16,22,78,81,239,36,120,32,72,158,128,64,147,138,25,249,0,52,72,242,2,
-127,2,5,74,96,140,229,203,34,103,250,154,4,17,163,151,44,137,159,234,105,4,
-33,162,93,6,73,123,13,1,165,64,202,113,251,33,6,64,14,71,78,20,101,213,207,
-4,194,207,2,12,162,0,158,176,23,218,168,23,66,64,255,255,239,127,255,255,
-255,255,19,214,33,187,85,2,232,72,0,0,0,0,0,32,0,0,25,136,0,0,31,15,224,0,
-0,0,4,122,247,73,19,69,73,180,134,149,13,68,241,0,0,3,193,252,0,0,0,0,143,
-90,67,2,104,169,54,144,210,161,168,158,32,0,0,120,127,128,0,0,0,14,73,78,
-20,0,0,0,0,0,0,0,0,8,58,189,233,24,77,217,24,93,240,1,230,238,21,23,32,247,
-68,13,155,184,75,189,205,35,102,128,47,114,64,185,187,143,137,4,137,33,205,
-222,17,6,96,48,87,130,50,37,114,1,246,147,21,143,224,54,186,213,128,114,90,
-112,164,0,0,124,63,128,0,0,0,98,117,119,128,25,55,112,96,153,57,41,197,13,
-53,224,65,147,119,38,134,19,146,156,80,211,94,5,194,94,6,37,55,113,110,16,
-22,78,12,19,39,37,56,161,166,188,14,74,110,226,220,32,44,156,154,24,78,74,
-113,67,77,120,32,97,175,4,28,61,224,133,172,186,70,22,248,1,204,73,242,104,
-97,47,128,44,196,159,11,69,175,152,32,35,100,33,142,49,39,218,76,69,237,22,
-190,96,128,141,144,136,32,196,159,24,230,204,246,66,40,179,18,125,164,196,
-206,185,179,61,144,140,28,196,159,6,9,146,200,71,20,98,79,180,152,135,208,
-76,150,66,64,99,18,124,24,49,100,36,137,49,39,218,76,67,232,49,100,37,8,49,
-39,195,186,145,149,144,150,44,196,159,105,49,31,174,164,101,100,38,10,49,
-39,198,33,180,153,37,100,38,141,49,39,218,76,76,234,27,73,146,86,66,112,
-163,18,124,145,4,230,142,86,66,120,211,18,125,164,197,46,144,78,104,229,
-100,40,15,49,39,198,33,107,68,136,39,52,114,178,20,73,24,147,237,38,38,117,
-11,90,36,65,57,163,149,144,164,68,196,159,38,134,19,46,105,56,226,150,68,
-157,160,3,200,147,228,208,194,92,32,124,137,62,49,11,90,36,65,57,163,149,
-178,166,74,68,159,105,49,51,168,90,209,34,9,205,28,173,149,65,82,36,249,34,
-9,205,28,173,175,170,54,68,159,105,49,75,164,19,154,57,91,95,88,84,137,62,
-49,13,164,201,43,111,235,141,145,39,218,76,76,234,27,73,146,86,223,216,17,
-34,79,135,117,35,43,115,236,139,145,39,218,76,71,235,169,25,91,159,104,60,
-137,62,12,19,37,178,182,42,68,159,105,49,15,160,153,45,149,193,18,36,248,
-199,54,103,182,190,232,185,18,125,164,196,206,185,179,61,181,247,133,200,
-147,225,104,181,243,4,4,109,191,190,58,68,159,105,49,23,180,90,249,130,2,
-54,223,224,67,152,147,230,8,8,217,12,16,121,18,124,193,1,27,101,131,131,56,
-7,38,193,198,72,0,0,0,0,0,0,0,0,198,231,240,134,39,63,136,151,95,63,136,49,
-89,252,66,98,243,248,133,96,132,185,5,224,32,36,201,41,248,200,213,249,0,
-131,64,7,39,192,218,148,124,137,74,216,231,198,227,141,182,124,78,40,217,
-231,197,227,4,213,227,192,159,72,10,5,21,218,138,120,74,129,124,36,98,232,
-228,74,81,62,160,20,10,107,181,21,114,32,105,137,194,70,46,142,68,165,19,
-235,1,64,170,187,81,119,34,66,146,36,104,137,194,70,46,142,68,165,19,236,1,
-64,174,187,81,95,37,134,204,23,225,35,23,71,34,82,137,246,128,160,89,93,
-168,167,147,195,201,194,70,46,142,68,165,19,238,1,64,182,187,81,71,105,20,
-19,177,139,163,145,41,68,16,7,6,15,82,70,72,115,96,0,93,105,160,0,0,0,0,91,
-60,149,195,200,194,8,134,149,216,114,1,128,83,192,144,8,194,195,16,12,168,
-110,20,120,12,141,22,16,120,12,100,22,12,120,28,78,99,192,41,224,136,115,
-36,14,100,197,213,245,193,48,189,112,40,2,237,96,175,131,117,2,178,112,145,
-139,163,145,131,114,70,46,142,218,27,182,72,197,209,219,56,26,53,161,166,
-28,1,204,178,10,14,38,78,44,141,52,207,31,0,0,21,64,129,100,180,8,148,145,
-92,203,176,160,226,100,226,200,211,76,241,240,0,1,84,2,131,137,147,142,41,
-100,73,199,192,0,5,88,6,13,10,82,70,62,0,0,42,66,88,115,18,124,67,103,177,
-69,49,130,12,73,242,136,108,246,40,165,177,6,36,248,134,207,71,90,138,99,
-68,152,147,229,16,217,232,235,81,75,130,12,73,241,13,158,158,149,20,199,9,
-49,39,202,33,179,211,210,162,151,69,24,147,225,86,224,79,79,74,138,94,20,
-98,79,133,91,129,61,109,74,41,124,60,137,62,33,179,216,166,216,193,18,36,
-249,68,54,123,20,218,216,137,18,124,67,103,163,173,77,177,162,100,73,242,
-136,108,244,117,169,181,193,18,36,248,134,207,79,74,155,99,132,200,147,229,
-16,217,233,233,83,107,162,164,73,240,171,112,39,167,165,77,175,10,145,39,
-194,173,192,158,182,165,54,191,153,51,72,71,161,196,201,45,167,146,59,68,
-89,24,70,206,0,0,7,129,248,0,0,0,1,153,51,104,71,161,196,201,45,167,146,59,
-68,89,24,70,206,0,0,7,129,248,0,0,0,1,153,51,136,71,161,196,201,45,167,146,
-59,68,89,24,70,206,0,0,7,129,248,0,0,0,1,153,51,168,71,161,196,201,45,167,
-146,59,68,89,24,70,206,0,0,0,2,0,0,0,0,1,153,51,200,71,161,196,201,45,167,
-146,59,68,89,24,70,206,0,0,0,2,0,0,0,0,1,153,51,232,71,161,196,201,45,167,
-146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,153,52,8,71,161,196,201,45,167,
-146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,153,52,40,71,161,196,201,45,167,
-146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,153,52,72,71,161,196,201,45,167,
-146,59,68,89,24,70,206,0,0,1,2,0,0,0,0,1,135,52,102,32,76,72,1,246,136,235,
-103,177,69,1,17,32,7,196,54,123,20,82,88,200,144,3,237,17,214,207,71,91,
-171,37,20,65,145,32,7,218,35,173,158,142,183,66,74,41,16,92,72,1,241,13,
-158,142,183,86,74,41,48,92,72,1,241,13,158,142,183,66,74,41,80,100,72,1,
-246,136,235,103,167,165,213,146,138,40,200,144,3,237,17,214,207,79,75,161,
-37,20,138,46,36,0,248,134,207,79,75,171,37,20,154,46,36,0,248,134,207,79,
-75,161,37,20,170,46,36,0,248,85,184,19,234,201,69,24,92,72,1,240,171,112,
-39,208,146,138,70,25,18,0,124,27,168,21,147,171,37,20,113,145,32,7,193,186,
-129,89,58,18,81,72,226,162,64,15,180,71,91,62,172,148,90,0,168,144,3,237,
-17,214,207,161,37,22,144,38,36,0,248,134,207,171,37,22,160,38,36,0,248,134,
-207,161,37,22,176,42,209,68,201,218,35,173,158,197,54,4,218,40,153,56,134,
-207,98,155,75,27,104,162,100,237,17,214,207,71,91,171,37,54,65,182,138,38,
-78,209,29,108,244,117,186,18,83,104,131,45,20,76,156,67,103,163,173,213,
-146,155,76,25,104,162,100,226,27,61,29,110,132,148,218,160,219,69,19,39,
-104,142,182,122,122,93,89,41,178,141,180,81,50,118,136,235,103,167,165,208,
-146,155,69,25,104,162,100,226,27,61,61,46,172,148,218,104,203,69,19,39,16,
-217,233,233,116,36,166,213,70,90,40,153,56,85,184,19,234,201,77,152,101,
-162,137,147,133,91,129,62,132,148,218,48,219,69,19,39,6,234,5,100,234,201,
-77,156,109,162,137,147,131,117,2,178,116,36,166,209,197,218,40,153,59,68,
-117,179,234,201,78,32,11,180,81,50,118,136,235,103,208,146,156,72,21,104,
-162,100,226,27,62,172,148,226,128,171,69,19,39,16,217,244,36,167,22,53,123,
-102,53,155,80,2,21,11,94,201,128,196,133,0,185,80,32,56,156,199,130,36,160,
-72,16,78,126,54,48,5,146,208,34,82,72,1,109,20,76,155,120,28,34,1,225,32,5,
-95,130,160,52,171,138,69,132,234,219,163,161,2,197,172,9,0,89,86,214,236,
-31,86,221,40,8,69,220,199,253,231,63,95,193,122,183,27,72,144,17,197,125,
-207,255,160,138,217,67,117,110,54,142,129,32,61,229,237,159,135,114,147,10,
-130,235,209,3,236,132,37,0,96,181,17,80,63,101,8,207,71,107,74,4,245,7,49,
-254,105,219,251,48,94,202,17,158,148,9,234,15,99,252,211,183,246,98,159,
-129,228,176,192,185,127,46,155,185,41,197,13,55,38,3,127,255,20,138,160,
-192,25,106,8,8,1,58,90,130,64,128,146,27,168,37,8,9,129,186,130,96,160,152,
-27,165,171,64,32,131,25,234,10,64,65,17,11,212,19,133,18,243,167,165,163,
-32,24,157,45,65,64,6,75,191,80,80,66,149,110,116,117,5,8,41,240,247,79,72,
-188,8,134,81,122,84,1,173,198,212,20,48,139,113,180,181,5,36,42,220,109,29,
-13,65,74,6,192,95,76,188,6,196,55,78,188,6,247,91,86,136,26,32,104,220,205,
-72,1,98,234,52,122,130,136,18,72,51,117,68,3,146,27,168,40,161,37,8,207,80,
-81,129,204,13,212,20,112,179,141,26,45,65,75,112,20,43,193,25,19,66,128,
-153,78,40,105,144,92,104,152,131,124,27,253,128,0,10,116,3,68,146,163,9,
-128,0,10,102,3,138,145,137,27,60,0,0,82,129,7,2,4,16,7,2,70,143,178,203,
-164,237,35,14,25,10,134,147,143,139,158,72,207,28,54,77,47,109,13,55,113,
-120,96,196,159,29,102,241,241,115,201,25,227,131,36,133,20,62,110,143,17,
-16,113,137,62,62,46,155,167,135,147,142,47,44,151,79,221,64,98,37,194,94,
-100,108,144,21,147,140,73,168,228,19,17,124,73,82,54,124,37,230,70,201,14,
-108,185,36,155,14,243,243,83,212,69,131,132,4,12,137,114,168,37,166,145,7,
-10,4,28,200,14,12,40,56,153,56,178,52,211,60,124,0,0,85,0,160,226,100,227,
-138,89,18,113,240,0,1,86,1,131,66,148,145,143,128,0,10,144,93,134,0,0,43,
-80,17,42,4,17,136,49,73,19,49,134,16,143,67,137,146,91,79,36,118,136,178,
-48,141,156,0,0,15,3,240,0,0,0,3,49,135,16,143,67,137,146,91,79,36,118,136,
-178,48,141,156,0,0,15,3,240,0,0,0,5,20,5,173,194,227,214,4,55,0,0,21,196,7,
-122,192,134,241,197,192,0,5,121,25,140,64,132,122,28,76,146,218,121,35,180,
-69,145,132,108,224,0,0,120,31,128,0,0,0,25,140,72,132,122,28,76,146,218,
-121,35,180,69,145,132,108,224,0,0,0,32,0,0,0,0,25,140,80,132,122,28,76,146,
-218,121,35,180,69,145,132,108,224,0,0,0,32,0,0,0,0,25,140,88,132,122,28,76,
-146,218,121,35,180,69,145,132,108,224,0,0,8,32,0,0,0,0,25,140,96,132,122,
-28,76,146,218,121,35,180,69,145,132,108,224,0,0,8,32,0,0,0,0,25,140,104,
-132,122,28,76,146,218,121,35,180,69,145,132,108,224,0,0,8,32,0,0,0,0,25,
-140,112,132,122,28,76,146,218,121,35,180,69,145,132,108,224,0,0,16,32,0,0,
-0,0,16,113,225,0,48,156,209,2,122,244,5,34,92,35,68,225,161,166,218,16,33,
-18,224,104,82,146,59,50,5,7,19,39,22,70,154,103,215,32,28,78,99,193,18,80,
-70,131,165,1,205,34,8,35,68,225,161,166,239,255,4,12,70,137,195,39,248,73,
-7,78,3,154,102,16,70,137,195,67,77,223,248,1,74,9,129,125,255,130,9,65,154,
-232,147,161,115,59,255,5,64,195,32,156,50,126,197,14,2,3,107,173,213,0,
+DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = {
+144,148,105,226,32,68,52,228,254,12,104,202,37,132,52,167,194,138,105,245,
+124,57,28,211,57,18,64,52,239,126,44,138,111,175,241,164,19,87,145,30,33,
+167,22,145,159,8,211,139,9,225,42,5,240,145,139,163,163,8,211,139,10,228,
+64,211,19,132,140,93,29,56,70,156,88,119,34,66,146,36,104,137,194,70,46,
+142,172,35,78,44,47,146,195,102,11,240,145,139,163,175,8,211,139,9,228,240,
+242,112,145,139,163,179,8,211,139,8,237,34,130,118,49,116,118,225,26,48,0,
+1,98,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
+33,8,66,26,180,105,97,167,68,150,34,33,154,112,0,1,91,247,35,79,111,237,
+198,174,232,47,31,23,95,17,13,31,249,96,211,49,50,53,214,77,141,24,0,0,181,
+10,228,240,242,15,128,140,65,128,134,188,0,0,90,167,97,181,224,0,2,213,62,
+53,224,0,2,213,66,237,120,0,0,181,81,204,107,192,0,5,170,150,67,94,0,0,45,
+84,245,90,240,0,1,106,169,162,215,128,0,11,85,93,150,188,0,0,90,171,111,53,
+109,22,162,26,48,0,1,84,23,201,146,243,225,26,39,12,145,136,104,192,0,5,61,
+11,228,201,121,240,100,19,134,72,196,33,195,14,40,203,112,64,190,76,232,
+145,153,136,0,0,31,15,224,0,0,0,25,152,0,0,30,15,224,0,0,0,25,120,144,13,
+96,155,194,56,80,206,36,67,141,20,228,70,57,81,206,100,131,156,39,132,168,
+23,194,70,46,137,208,21,200,129,166,39,9,24,186,39,72,119,34,66,146,36,104,
+137,194,70,46,137,212,23,201,97,179,5,248,72,197,209,58,194,121,60,60,156,
+36,98,232,157,129,29,164,80,78,198,46,137,218,146,121,25,71,146,9,209,5,
+209,61,48,126,14,138,152,30,67,186,23,143,139,175,131,202,135,228,72,85,
+144,83,60,179,30,94,209,233,102,30,98,105,230,103,30,114,121,231,104,30,
+122,137,231,233,30,130,153,232,106,30,138,169,232,235,30,144,67,193,25,19,
+136,108,207,30,41,224,140,137,194,173,192,153,228,5,242,100,188,248,70,137,
+195,36,79,78,47,147,37,231,193,144,78,25,34,122,145,111,36,74,232,176,13,
+17,61,234,226,93,207,148,160,84,75,141,7,27,161,32,33,18,225,80,212,76,154,
+2,2,70,65,56,100,237,34,140,209,2,67,32,156,50,118,145,64,186,230,61,205,
+35,103,155,32,36,141,19,134,78,210,40,206,16,36,70,137,195,39,105,20,11,
+174,99,220,210,54,121,210,1,137,33,1,228,207,16,17,70,146,66,3,201,164,32,
+0,65,112,152,56,196,159,31,23,77,211,195,201,199,23,160,72,214,246,81,6,12,
+73,241,214,111,31,23,60,145,158,56,50,72,81,67,230,232,242,80,19,49,39,199,
+89,188,124,92,242,70,120,227,64,194,75,154,72,12,9,73,6,111,21,120,12,40,
+144,19,39,25,0,225,144,168,105,56,248,185,228,140,241,200,96,64,100,42,26,
+78,62,46,121,35,52,18,92,116,1,36,64,47,158,64,49,98,66,100,156,242,65,23,
+196,149,35,103,194,94,100,108,144,230,203,156,64,66,37,201,16,11,32,249,
+132,4,34,92,44,93,146,55,152,72,24,137,112,151,153,27,36,5,100,229,144,8,
+162,98,92,210,5,76,73,241,214,111,31,23,60,145,158,57,44,48,46,92,185,164,
+160,72,151,41,0,50,107,179,244,59,36,93,127,92,6,19,172,3,11,216,0,56,224,
+151,29,102,241,241,115,201,25,227,164,64,106,37,199,197,211,116,240,242,
+113,197,233,144,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,84,
+129,13,173,161,144,168,105,56,98,78,100,142,214,215,69,1,13,173,161,144,
+168,105,57,34,78,100,142,214,215,69,16,67,107,105,110,114,168,254,24,147,
+153,35,181,181,212,32,67,107,105,110,114,168,254,72,147,153,35,181,181,212,
+36,65,130,3,144,8,26,252,200,13,30,85,16,16,64,90,242,231,192,64,161,163,
+203,31,26,172,193,17,4,23,105,159,96,27,172,251,16,32,196,4,14,137,112,17,
+136,48,164,28,134,80,215,202,1,132,130,8,12,39,52,64,155,31,24,56,36,1,189,
+207,132,0,35,233,35,195,62,3,196,149,36,100,72,160,2,200,232,44,227,0,11,
+37,160,68,142,128,36,157,25,200,32,26,79,90,4,73,43,192,122,54,71,65,103,
+44,248,14,134,140,151,227,138,231,208,45,96,148,248,134,140,151,227,138,
+231,240,1,255,254,10,74,146,56,128,104,4,147,152,72,6,144,28,174,143,8,1,
+30,1,165,3,96,31,0,211,3,21,11,153,35,0,211,131,68,131,160,137,16,250,5,
+196,131,160,137,200,160,199,156,67,248,0,255,255,65,140,10,48,177,115,56,
+35,130,60,19,134,79,89,240,52,177,115,56,39,12,156,123,144,217,251,15,135,
+34,167,30,20,170,154,255,232,12,47,244,0,97,28,17,224,39,238,32,40,71,4,
+120,39,12,156,4,253,228,5,137,195,39,30,228,54,124,4,253,228,128,194,115,
+68,9,252,15,128,232,104,201,126,56,191,35,64,90,193,41,241,13,25,47,199,23,
+228,105,3,86,225,1,100,224,156,199,130,36,249,144,10,192,76,71,250,16,15,
+18,61,96,17,62,200,3,72,128,136,143,247,32,22,75,64,137,248,64,22,79,90,39,
+249,64,38,84,12,167,20,52,223,196,2,230,238,45,214,36,120,32,72,158,208,4,
+102,238,45,194,2,201,197,186,196,143,4,9,19,218,0,92,221,202,61,228,143,4,
+9,19,218,8,35,55,113,110,16,22,78,81,239,36,120,32,72,158,208,64,73,197,12,
+255,0,13,18,60,128,159,212,128,169,76,17,156,185,100,76,255,163,64,65,26,
+57,114,200,153,255,70,144,33,13,18,232,50,75,226,104,6,149,3,41,199,246,
+130,12,128,28,142,156,120,203,175,158,8,194,207,1,6,81,20,79,88,11,237,84,
+11,161,32,127,255,247,191,255,255,255,255,137,235,16,221,170,129,116,36,0,
+0,0,0,0,16,0,0,12,196,0,0,15,135,240,0,0,0,2,61,123,164,137,162,164,218,67,
+74,134,162,120,128,0,1,224,254,0,0,0,0,71,173,33,129,52,84,155,72,105,80,
+212,79,16,0,0,60,63,192,0,0,0,3,244,143,146,22,230,192,0,0,176,60,0,0,0,0,
+33,214,2,251,82,1,73,180,134,204,134,36,96,127,255,159,161,255,255,255,255,
+144,235,16,221,169,0,164,218,67,102,67,18,48,63,255,207,240,255,255,255,
+255,196,60,17,145,56,134,204,241,226,158,8,200,156,42,220,9,158,65,196,34,
+92,42,26,137,147,120,64,74,37,196,54,100,49,35,188,36,5,68,184,208,113,187,
+194,80,212,75,146,1,73,196,54,100,49,35,188,38,57,37,56,240,0,0,0,0,0,0,0,
+0,32,235,248,68,48,156,2,24,94,24,0,243,119,10,139,144,123,242,3,102,238,
+18,239,115,72,217,160,11,223,16,23,55,113,241,32,145,36,57,188,18,16,102,3,
+5,120,35,34,89,32,15,180,152,173,127,0,218,235,88,0,228,180,227,200,0,0,
+248,127,0,0,0,0,197,107,240,64,6,77,220,24,38,78,74,113,67,77,130,4,12,155,
+185,52,48,156,148,226,134,155,4,10,194,96,129,132,166,238,45,194,2,201,193,
+130,100,228,167,20,52,216,32,113,41,187,139,112,128,178,114,104,97,57,41,
+197,13,54,8,32,48,216,32,130,195,224,130,19,97,124,134,23,6,0,57,137,62,77,
+12,38,12,0,179,18,124,45,22,190,96,128,141,176,134,28,98,79,180,152,139,
+218,45,124,193,1,27,97,16,32,196,159,24,230,204,246,194,40,89,137,62,210,
+98,103,92,217,158,216,70,7,49,39,193,130,100,182,17,194,140,73,246,147,16,
+250,9,146,216,72,6,49,39,193,131,22,194,72,73,137,62,210,98,31,65,139,97,
+40,32,196,159,14,234,70,86,194,88,89,137,62,210,98,63,93,72,202,216,76,10,
+49,39,198,33,180,153,37,108,38,134,152,147,237,38,38,117,13,164,201,43,97,
+56,40,196,159,36,65,57,163,149,176,158,26,98,79,180,152,165,210,9,205,28,
+173,133,0,243,18,124,98,22,180,72,130,115,71,43,97,68,72,196,159,105,49,51,
+168,90,209,34,9,205,28,173,133,33,19,18,124,154,24,76,185,164,227,138,89,
+18,119,0,7,145,39,201,161,132,188,64,124,137,62,49,11,90,36,65,57,163,149,
+210,166,37,34,79,180,152,153,212,45,104,145,4,230,142,87,74,160,84,137,62,
+72,130,115,71,43,171,234,134,200,147,237,38,41,116,130,115,71,43,171,235,5,
+72,147,227,16,218,76,146,186,254,184,108,137,62,210,98,103,80,218,76,146,
+186,254,192,68,137,62,29,212,140,174,207,178,23,34,79,180,152,143,215,82,
+50,187,62,208,60,137,62,12,19,37,210,182,21,34,79,180,152,135,208,76,151,
+74,224,68,137,62,49,205,153,238,175,186,23,34,79,180,152,153,215,54,103,
+186,190,240,92,137,62,22,139,95,48,64,70,235,251,225,210,36,251,73,136,189,
+162,215,204,16,17,186,255,2,14,98,79,152,32,35,108,48,64,242,36,249,130,2,
+55,75,6,212,224,72,200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,
+48,98,115,249,201,117,243,249,195,21,159,206,38,47,63,156,86,8,75,144,94,
+82,1,38,73,79,208,67,95,233,1,6,128,14,79,129,186,40,249,18,149,182,207,
+144,200,155,188,248,204,105,184,207,142,199,137,175,201,0,159,72,10,5,21,
+221,10,120,74,129,124,36,98,232,228,74,81,62,160,20,10,107,186,21,114,32,
+105,137,194,70,46,142,68,165,19,235,1,64,170,187,161,119,34,66,146,36,104,
+137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35,
+23,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165,
+19,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,
+72,115,96,0,27,234,32,0,0,0,0,91,60,165,195,201,194,8,134,149,216,162,0,
+192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,
+195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,
+1,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,
+36,98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,
+0,83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,
+102,8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,
+20,28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179,
+216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,
+81,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,
+166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,
+20,188,20,98,79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,
+68,137,62,81,13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,
+159,40,134,207,71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,
+67,103,167,165,77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,
+173,192,158,182,165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,
+140,35,103,0,0,3,192,252,0,0,0,0,206,25,228,35,208,226,100,150,211,201,29,
+162,44,140,35,103,0,0,3,192,252,0,0,0,0,206,25,244,35,208,226,100,150,211,
+201,29,162,44,140,35,103,0,0,3,192,252,0,0,0,0,206,26,4,35,208,226,100,150,
+211,201,29,162,44,140,35,103,0,0,0,1,0,0,0,0,0,206,26,20,35,208,226,100,
+150,211,201,29,162,44,140,35,103,0,0,0,1,0,0,0,0,0,206,26,36,35,208,226,
+100,150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,52,35,208,
+226,100,150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,68,35,
+208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,84,
+35,208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,129,0,0,0,0,0,195,
+154,99,16,38,36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,
+25,18,0,125,162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,
+235,116,36,162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,
+196,54,122,58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,
+200,144,3,237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,
+213,146,138,77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,
+183,2,125,89,40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,
+221,64,172,157,89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,
+31,104,142,182,125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,
+18,0,124,67,103,213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,
+59,68,117,179,216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,
+39,104,142,182,122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,
+73,77,162,6,90,40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,
+61,29,110,132,148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,
+67,109,20,76,157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,
+167,165,213,146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,
+68,201,194,173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,
+193,182,138,38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,
+178,116,36,166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,
+157,162,58,217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,
+81,50,113,13,159,66,74,113,97,175,221,48,216,110,64,4,42,22,189,179,0,196,
+133,0,185,80,32,28,78,99,193,18,80,36,4,19,159,141,172,0,178,90,4,74,73,0,
+22,209,68,201,187,129,4,2,8,3,132,64,60,36,0,171,240,84,6,149,113,72,176,
+157,91,116,116,32,88,181,129,32,11,42,218,221,131,234,219,165,1,8,187,152,
+255,188,231,235,248,47,86,227,105,18,2,56,175,185,255,244,17,91,40,110,173,
+198,209,208,36,7,188,189,179,240,238,82,97,80,93,122,32,125,144,132,160,12,
+22,162,42,7,236,161,25,232,237,105,64,158,160,230,63,205,59,127,102,11,217,
+66,51,210,129,61,65,236,127,154,118,254,205,171,197,34,168,48,6,90,194,1,0,
+39,75,88,72,8,9,33,186,194,80,64,76,13,214,19,2,130,96,110,150,189,0,65,6,
+51,214,20,128,65,17,11,214,19,130,137,121,211,210,211,144,6,39,75,88,80,0,
+201,119,235,10,8,41,86,231,71,88,80,129,79,135,186,122,133,224,34,25,69,
+234,80,3,91,141,172,40,96,139,113,180,181,133,36,21,110,54,142,134,176,165,
+1,176,23,213,47,0,216,134,234,215,128,111,117,181,232,128,209,3,70,230,107,
+64,5,139,168,209,235,10,32,36,144,102,235,136,3,146,27,172,40,160,146,132,
+103,172,40,192,115,3,117,133,28,22,113,163,69,172,41,103,1,66,188,17,145,
+52,168,4,202,113,67,76,130,227,76,194,13,240,108,0,0,83,224,0,2,193,0,104,
+146,84,97,48,0,1,94,192,56,169,24,145,179,192,0,5,112,8,56,16,32,128,56,18,
+52,125,230,86,147,190,140,28,50,21,13,39,31,23,60,145,158,57,12,141,47,129,
+6,155,194,188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,
+163,201,68,14,49,39,199,197,211,116,240,242,113,197,232,18,180,254,36,3,17,
+46,18,243,35,100,128,172,156,178,70,163,154,76,34,248,146,164,108,248,75,
+204,141,146,28,217,115,137,27,95,27,241,173,236,162,160,224,200,2,206,9,
+113,13,148,192,209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,178,
+66,213,136,68,201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,38,
+232,255,252,92,221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,38,
+3,66,213,47,135,254,72,12,162,99,133,116,112,0,1,72,66,14,16,16,50,37,202,
+160,150,154,66,14,20,8,57,192,28,24,80,113,50,113,100,105,166,120,248,0,0,
+179,1,65,196,201,199,20,178,36,227,224,0,2,208,54,113,240,0,1,100,11,181,
+192,0,5,178,1,18,160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,121,
+35,180,69,145,132,108,224,0,0,120,31,128,0,0,0,25,188,56,132,122,28,76,146,
+218,121,35,180,69,145,132,108,224,0,0,120,31,128,0,0,0,40,160,45,110,23,30,
+176,33,184,0,0,183,32,29,235,2,27,199,23,0,0,23,4,51,120,129,8,244,56,153,
+37,180,242,71,104,139,35,8,217,192,0,0,240,63,0,0,0,0,51,120,145,8,244,56,
+153,37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,120,161,8,244,
+56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,120,177,8,
+244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,120,193,
+8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,120,
+209,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,
+120,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,32,64,0,0,0,0,
+32,227,194,0,97,57,162,4,246,104,5,34,92,35,68,225,161,166,220,16,16,137,
+112,52,41,73,29,185,1,65,196,201,197,145,166,153,246,72,3,137,204,120,34,
+74,8,199,1,67,17,162,112,201,84,128,97,144,78,25,42,16,131,169,1,205,66,8,
+35,68,225,161,166,239,128,0,10,192,64,196,104,156,50,96,0,2,172,73,240,117,
+96,57,170,97,4,104,156,52,52,221,240,0,1,82,1,74,9,129,125,240,0,1,82,32,
+148,25,174,137,58,23,51,190,0,0,42,69,64,195,32,156,50,96,0,2,160,81,238,2,
+3,107,173,218,3,192,
};
#else
#error invalid endianness defines
@@ -11373,31 +12471,43 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[3972] = {
/* #include duk_internal.h -> already included */
-#define DUK__ERRFMT_BUFSIZE 256 /* size for formatting buffers */
+#define DUK__ERRFMT_BUFSIZE 256 /* size for formatting buffers */
#if defined(DUK_USE_VERBOSE_ERRORS)
-DUK_INTERNAL DUK_COLD void duk_err_handle_error_fmt(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *fmt, ...) {
+DUK_INTERNAL DUK_COLD void duk_err_handle_error_fmt(duk_hthread *thr,
+ const char *filename,
+ duk_uint_t line_and_code,
+ const char *fmt,
+ ...) {
va_list ap;
char msg[DUK__ERRFMT_BUFSIZE];
va_start(ap, fmt);
(void) DUK_VSNPRINTF(msg, sizeof(msg), fmt, ap);
msg[sizeof(msg) - 1] = (char) 0;
- duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
- va_end(ap); /* dead code, but ensures portability (see Linux man page notes) */
+ duk_err_create_and_throw(thr,
+ (duk_errcode_t) (line_and_code >> 24),
+ msg,
+ filename,
+ (duk_int_t) (line_and_code & 0x00ffffffL));
+ va_end(ap); /* dead code, but ensures portability (see Linux man page notes) */
}
DUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg) {
- duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
+ duk_err_create_and_throw(thr,
+ (duk_errcode_t) (line_and_code >> 24),
+ msg,
+ filename,
+ (duk_int_t) (line_and_code & 0x00ffffffL));
}
-#else /* DUK_USE_VERBOSE_ERRORS */
+#else /* DUK_USE_VERBOSE_ERRORS */
DUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code) {
duk_err_create_and_throw(thr, code);
}
-#endif /* DUK_USE_VERBOSE_ERRORS */
+#endif /* DUK_USE_VERBOSE_ERRORS */
/*
* Error throwing helpers
@@ -11405,14 +12515,34 @@ DUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, duk_errcode_t
#if defined(DUK_USE_VERBOSE_ERRORS)
#if defined(DUK_USE_PARANOID_ERRORS)
-DUK_INTERNAL DUK_COLD void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name) {
- DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
- expect_name, duk_get_type_name(thr, idx), (long) idx);
+DUK_INTERNAL DUK_COLD void duk_err_require_type_index(duk_hthread *thr,
+ const char *filename,
+ duk_int_t linenumber,
+ duk_idx_t idx,
+ const char *expect_name) {
+ DUK_ERROR_RAW_FMT3(thr,
+ filename,
+ linenumber,
+ DUK_ERR_TYPE_ERROR,
+ "%s required, found %s (stack index %ld)",
+ expect_name,
+ duk_get_type_name(thr, idx),
+ (long) idx);
}
#else
-DUK_INTERNAL DUK_COLD void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name) {
- DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
- expect_name, duk_push_string_readable(thr, idx), (long) idx);
+DUK_INTERNAL DUK_COLD void duk_err_require_type_index(duk_hthread *thr,
+ const char *filename,
+ duk_int_t linenumber,
+ duk_idx_t idx,
+ const char *expect_name) {
+ DUK_ERROR_RAW_FMT3(thr,
+ filename,
+ linenumber,
+ DUK_ERR_TYPE_ERROR,
+ "%s required, found %s (stack index %ld)",
+ expect_name,
+ duk_push_string_readable(thr, idx),
+ (long) idx);
}
#endif
DUK_INTERNAL DUK_COLD void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
@@ -11482,10 +12612,18 @@ DUK_INTERNAL DUK_COLD void duk_default_fatal_handler(void *udata, const char *ms
DUK_UNREF(udata);
DUK_UNREF(msg);
+ msg = msg ? msg : "NULL";
+
#if defined(DUK_USE_FATAL_HANDLER)
/* duk_config.h provided a custom default fatal handler. */
- DUK_D(DUK_DPRINT("custom default fatal error handler called: %s", msg ? msg : "NULL"));
+ DUK_D(DUK_DPRINT("custom default fatal error handler called: %s", msg));
DUK_USE_FATAL_HANDLER(udata, msg);
+#elif defined(DUK_USE_CPP_EXCEPTIONS)
+ /* With C++ use a duk_fatal_exception which user code can catch in
+ * a natural way.
+ */
+ DUK_D(DUK_DPRINT("built-in default C++ fatal error handler called: %s", msg));
+ throw duk_fatal_exception(msg);
#else
/* Default behavior is to abort() on error. There's no printout
* which makes this awkward, so it's always recommended to use an
@@ -11502,7 +12640,7 @@ DUK_INTERNAL DUK_COLD void duk_default_fatal_handler(void *udata, const char *ms
* - http://duktape.org/api.html#taglist-protected
* ====================================================================
*/
- DUK_D(DUK_DPRINT("built-in default fatal error handler called: %s", msg ? msg : "NULL"));
+ DUK_D(DUK_DPRINT("built-in default fatal error handler called: %s", msg));
DUK_ABORT();
#endif
@@ -11531,14 +12669,14 @@ DUK_INTERNAL const duk_int8_t duk_is_idchar_tab[128] = {
* 1: IdentifierStart and IdentifierPart
* -1: IdentifierPart only
*/
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00...0x0f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10...0x1f */
- 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20...0x2f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, /* 0x30...0x3f */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40...0x4f */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50...0x5f */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60...0x6f */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 /* 0x70...0x7f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00...0x0f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10...0x1f */
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20...0x2f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, /* 0x30...0x3f */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40...0x4f */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50...0x5f */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60...0x6f */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 /* 0x70...0x7f */
};
#endif
@@ -11588,15 +12726,13 @@ DUK_INTERNAL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp) {
/* Encoded as surrogate pair, each encoding to 3 bytes for
* 6 bytes total. Codepoints above U+10FFFF encode as 6 bytes
* too, see duk_unicode_encode_cesu8().
- */
+ */
return 3 + 3;
}
}
-#endif /* DUK_USE_ASSERTIONS */
+#endif /* DUK_USE_ASSERTIONS */
-DUK_INTERNAL const duk_uint8_t duk_unicode_xutf8_markers[7] = {
- 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe
-};
+DUK_INTERNAL const duk_uint8_t duk_unicode_xutf8_markers[7] = { 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
/* Encode to extended UTF-8; 'out' must have space for at least
* DUK_UNICODE_MAX_XUTF8_LENGTH bytes. Allows encoding of any
@@ -11611,7 +12747,7 @@ DUK_INTERNAL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_u
len = duk_unicode_get_xutf8_length(cp);
DUK_ASSERT(len > 0);
- marker = duk_unicode_xutf8_markers[len - 1]; /* 64-bit OK because always >= 0 */
+ marker = duk_unicode_xutf8_markers[len - 1]; /* 64-bit OK because always >= 0 */
i = len;
DUK_ASSERT(i > 0);
@@ -11657,7 +12793,7 @@ DUK_INTERNAL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_u
/*
* Unicode codepoints above U+FFFF are encoded as surrogate
* pairs here. This ensures that all CESU-8 codepoints are
- * 16-bit values as expected in Ecmascript. The surrogate
+ * 16-bit values as expected in ECMAScript. The surrogate
* pairs always get a 3-byte encoding (each) in CESU-8.
* See: http://en.wikipedia.org/wiki/Surrogate_pair
*
@@ -11696,7 +12832,11 @@ DUK_INTERNAL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_u
}
/* Decode helper. Return zero on error. */
-DUK_INTERNAL duk_small_int_t duk_unicode_decode_xutf8(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_ucodepoint_t *out_cp) {
+DUK_INTERNAL duk_small_int_t duk_unicode_decode_xutf8(duk_hthread *thr,
+ const duk_uint8_t **ptr,
+ const duk_uint8_t *ptr_start,
+ const duk_uint8_t *ptr_end,
+ duk_ucodepoint_t *out_cp) {
const duk_uint8_t *p;
duk_uint32_t res;
duk_uint_fast8_t ch;
@@ -11758,7 +12898,7 @@ DUK_INTERNAL duk_small_int_t duk_unicode_decode_xutf8(duk_hthread *thr, const du
goto fail;
}
- DUK_ASSERT(p >= ptr_start); /* verified at beginning */
+ DUK_ASSERT(p >= ptr_start); /* verified at beginning */
if (p + n > ptr_end) {
/* check pointer at end */
goto fail;
@@ -11784,20 +12924,22 @@ DUK_INTERNAL duk_small_int_t duk_unicode_decode_xutf8(duk_hthread *thr, const du
*out_cp = res;
return 1;
- fail:
+fail:
return 0;
}
/* used by e.g. duk_regexp_executor.c, string built-ins */
-DUK_INTERNAL duk_ucodepoint_t duk_unicode_decode_xutf8_checked(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end) {
+DUK_INTERNAL duk_ucodepoint_t duk_unicode_decode_xutf8_checked(duk_hthread *thr,
+ const duk_uint8_t **ptr,
+ const duk_uint8_t *ptr_start,
+ const duk_uint8_t *ptr_end) {
duk_ucodepoint_t cp;
if (duk_unicode_decode_xutf8(thr, ptr, ptr_start, ptr_end, &cp)) {
return cp;
}
DUK_ERROR_INTERNAL(thr);
- DUK_UNREACHABLE();
- return 0;
+ DUK_WO_NORETURN(return 0;);
}
/* Compute (extended) utf-8 length without codepoint encoding validation,
@@ -11837,7 +12979,7 @@ DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *d
DUK_ASSERT(clen <= blen);
return clen;
}
-#else /* DUK_USE_PREFER_SIZE */
+#else /* DUK_USE_PREFER_SIZE */
/* This seems like a good overall approach. Fast path for ASCII in 4 byte
* blocks.
*/
@@ -11849,7 +12991,7 @@ DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *d
duk_size_t ncont;
duk_size_t clen;
- ncont = 0; /* number of continuation (non-initial) bytes in [0x80,0xbf] */
+ ncont = 0; /* number of continuation (non-initial) bytes in [0x80,0xbf] */
p = data;
p_end = data + blen;
if (blen < 16) {
@@ -11874,7 +13016,7 @@ DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *d
duk_uint32_t x;
x = *p32++;
if (DUK_LIKELY((x & 0x80808080UL) == 0)) {
- ; /* ASCII fast path */
+ ; /* ASCII fast path */
} else {
/* Flip highest bit of each byte which changes
* the bit pattern 10xxxxxx into 00xxxxxx which
@@ -11898,7 +13040,7 @@ DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *d
p = (const duk_uint8_t *) p32;
/* Fall through to handle the rest. */
- skip_fastpath:
+skip_fastpath:
while (p != p_end) {
duk_uint8_t x;
x = *p++;
@@ -11912,7 +13054,91 @@ DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *d
DUK_ASSERT(clen <= blen);
return clen;
}
-#endif /* DUK_USE_PREFER_SIZE */
+#endif /* DUK_USE_PREFER_SIZE */
+
+/* Check whether a string is UTF-8 compatible or not. */
+DUK_INTERNAL duk_bool_t duk_unicode_is_utf8_compatible(const duk_uint8_t *buf, duk_size_t len) {
+ duk_size_t i = 0;
+#if !defined(DUK_USE_PREFER_SIZE)
+ duk_size_t len_safe;
+#endif
+
+ /* Many practical strings are ASCII only, so use a fast path check
+ * to check chunks of bytes at once with minimal branch cost.
+ */
+#if !defined(DUK_USE_PREFER_SIZE)
+ len_safe = len & ~0x03UL;
+ for (; i < len_safe; i += 4) {
+ duk_uint8_t t = buf[i] | buf[i + 1] | buf[i + 2] | buf[i + 3];
+ if (DUK_UNLIKELY((t & 0x80U) != 0U)) {
+ /* At least one byte was outside 0x00-0x7f, break
+ * out to slow path (and remain there).
+ *
+ * XXX: We could also deal with the problem character
+ * and resume fast path later.
+ */
+ break;
+ }
+ }
+#endif
+
+ for (; i < len;) {
+ duk_uint8_t t;
+ duk_size_t left;
+ duk_size_t ncont;
+ duk_uint32_t cp;
+ duk_uint32_t mincp;
+
+ t = buf[i++];
+ if (DUK_LIKELY((t & 0x80U) == 0U)) {
+ /* Fast path, ASCII. */
+ continue;
+ }
+
+ /* Non-ASCII start byte, slow path.
+ *
+ * 10xx xxxx -> continuation byte
+ * 110x xxxx + 1*CONT -> [0x80, 0x7ff]
+ * 1110 xxxx + 2*CONT -> [0x800, 0xffff], must reject [0xd800,0xdfff]
+ * 1111 0xxx + 3*CONT -> [0x10000, 0x10ffff]
+ */
+ left = len - i;
+ if (t <= 0xdfU) { /* 1101 1111 = 0xdf */
+ if (t <= 0xbfU) { /* 1011 1111 = 0xbf */
+ return 0;
+ }
+ ncont = 1;
+ mincp = 0x80UL;
+ cp = t & 0x1fU;
+ } else if (t <= 0xefU) { /* 1110 1111 = 0xef */
+ ncont = 2;
+ mincp = 0x800UL;
+ cp = t & 0x0fU;
+ } else if (t <= 0xf7U) { /* 1111 0111 = 0xf7 */
+ ncont = 3;
+ mincp = 0x10000UL;
+ cp = t & 0x07U;
+ } else {
+ return 0;
+ }
+ if (left < ncont) {
+ return 0;
+ }
+ while (ncont > 0U) {
+ t = buf[i++];
+ if ((t & 0xc0U) != 0x80U) { /* 10xx xxxx */
+ return 0;
+ }
+ cp = (cp << 6) + (t & 0x3fU);
+ ncont--;
+ }
+ if (cp < mincp || cp > 0x10ffffUL || (cp >= 0xd800UL && cp <= 0xdfffUL)) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
/*
* Unicode range matcher
@@ -11946,7 +13172,7 @@ DUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_si
duk_bitdecoder_ctx bd_ctx;
duk_codepoint_t prev_re;
- DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
+ duk_memzero(&bd_ctx, sizeof(bd_ctx));
bd_ctx.data = (const duk_uint8_t *) unitab;
bd_ctx.length = (duk_size_t) unilen;
@@ -11966,7 +13192,9 @@ DUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_si
/* [r1,r2] is the range */
DUK_DDD(DUK_DDDPRINT("duk__uni_range_match: cp=%06lx range=[0x%06lx,0x%06lx]",
- (unsigned long) cp, (unsigned long) r1, (unsigned long) r2));
+ (unsigned long) cp,
+ (unsigned long) r1,
+ (unsigned long) r2));
if (cp >= r1 && cp <= r2) {
return 1;
}
@@ -12036,19 +13264,17 @@ DUK_INTERNAL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp) {
/* cp == -1 (EOF) never matches and causes return value 0 */
lo = (duk_uint_fast8_t) (cp & 0xff);
- hi = (duk_uint_fast32_t) (cp >> 8); /* does not fit into an uchar */
+ hi = (duk_uint_fast32_t) (cp >> 8); /* does not fit into an uchar */
if (hi == 0x0000UL) {
- if (lo == 0x09U || lo == 0x0bU || lo == 0x0cU ||
- lo == 0x20U || lo == 0xa0U) {
+ if (lo == 0x09U || lo == 0x0bU || lo == 0x0cU || lo == 0x20U || lo == 0xa0U) {
return 1;
}
} else if (hi == 0x0020UL) {
if (lo <= 0x0aU || lo == 0x2fU || lo == 0x5fU) {
return 1;
}
- } else if (cp == 0x1680L || cp == 0x180eL || cp == 0x3000L ||
- cp == 0xfeffL) {
+ } else if (cp == 0x1680L || cp == 0x180eL || cp == 0x3000L || cp == 0xfeffL) {
return 1;
}
@@ -12067,8 +13293,7 @@ DUK_INTERNAL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp)
* into a single line terminator. This must be handled by the caller.
*/
- if (cp == 0x000aL || cp == 0x000dL || cp == 0x2028L ||
- cp == 0x2029L) {
+ if (cp == 0x000aL || cp == 0x000dL || cp == 0x2028L || cp == 0x2029L) {
return 1;
}
@@ -12119,9 +13344,7 @@ DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp)
#if defined(DUK_USE_IDCHAR_FASTPATH)
return (cp >= 0) && (duk_is_idchar_tab[cp] > 0);
#else
- if ((cp >= 'a' && cp <= 'z') ||
- (cp >= 'A' && cp <= 'Z') ||
- cp == '_' || cp == '$') {
+ if ((cp >= 'a' && cp <= 'z') || (cp >= 'A' && cp <= 'Z') || cp == '_' || cp == '$') {
return 1;
}
return 0;
@@ -12131,17 +13354,13 @@ DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp)
/* Non-ASCII slow path (range-by-range linear comparison), very slow */
#if defined(DUK_USE_SOURCE_NONBMP)
- if (duk__uni_range_match(duk_unicode_ids_noa,
- (duk_size_t) sizeof(duk_unicode_ids_noa),
- (duk_codepoint_t) cp)) {
+ if (duk__uni_range_match(duk_unicode_ids_noa, (duk_size_t) sizeof(duk_unicode_ids_noa), (duk_codepoint_t) cp)) {
return 1;
}
return 0;
#else
if (cp < 0x10000L) {
- if (duk__uni_range_match(duk_unicode_ids_noabmp,
- sizeof(duk_unicode_ids_noabmp),
- (duk_codepoint_t) cp)) {
+ if (duk__uni_range_match(duk_unicode_ids_noabmp, sizeof(duk_unicode_ids_noabmp), (duk_codepoint_t) cp)) {
return 1;
}
return 0;
@@ -12208,10 +13427,7 @@ DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp)
#if defined(DUK_USE_IDCHAR_FASTPATH)
return (cp >= 0) && (duk_is_idchar_tab[cp] != 0);
#else
- if ((cp >= 'a' && cp <= 'z') ||
- (cp >= 'A' && cp <= 'Z') ||
- (cp >= '0' && cp <= '9') ||
- cp == '_' || cp == '$') {
+ if ((cp >= 'a' && cp <= 'z') || (cp >= 'A' && cp <= 'Z') || (cp >= '0' && cp <= '9') || cp == '_' || cp == '$') {
return 1;
}
return 0;
@@ -12221,20 +13437,14 @@ DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp)
/* Non-ASCII slow path (range-by-range linear comparison), very slow */
#if defined(DUK_USE_SOURCE_NONBMP)
- if (duk__uni_range_match(duk_unicode_ids_noa,
- sizeof(duk_unicode_ids_noa),
- (duk_codepoint_t) cp) ||
- duk__uni_range_match(duk_unicode_idp_m_ids_noa,
- sizeof(duk_unicode_idp_m_ids_noa),
- (duk_codepoint_t) cp)) {
+ if (duk__uni_range_match(duk_unicode_ids_noa, sizeof(duk_unicode_ids_noa), (duk_codepoint_t) cp) ||
+ duk__uni_range_match(duk_unicode_idp_m_ids_noa, sizeof(duk_unicode_idp_m_ids_noa), (duk_codepoint_t) cp)) {
return 1;
}
return 0;
#else
if (cp < 0x10000L) {
- if (duk__uni_range_match(duk_unicode_ids_noabmp,
- sizeof(duk_unicode_ids_noabmp),
- (duk_codepoint_t) cp) ||
+ if (duk__uni_range_match(duk_unicode_ids_noabmp, sizeof(duk_unicode_ids_noabmp), (duk_codepoint_t) cp) ||
duk__uni_range_match(duk_unicode_idp_m_ids_noabmp,
sizeof(duk_unicode_idp_m_ids_noabmp),
(duk_codepoint_t) cp)) {
@@ -12270,8 +13480,7 @@ DUK_INTERNAL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp) {
/* ASCII (and EOF) fast path -- quick accept and reject */
if (cp <= 0x7fL) {
- if ((cp >= 'a' && cp <= 'z') ||
- (cp >= 'A' && cp <= 'Z')) {
+ if ((cp >= 'a' && cp <= 'z') || (cp >= 'A' && cp <= 'Z')) {
return 1;
}
return 0;
@@ -12280,20 +13489,14 @@ DUK_INTERNAL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp) {
/* Non-ASCII slow path (range-by-range linear comparison), very slow */
#if defined(DUK_USE_SOURCE_NONBMP)
- if (duk__uni_range_match(duk_unicode_ids_noa,
- sizeof(duk_unicode_ids_noa),
- (duk_codepoint_t) cp) &&
- !duk__uni_range_match(duk_unicode_ids_m_let_noa,
- sizeof(duk_unicode_ids_m_let_noa),
- (duk_codepoint_t) cp)) {
+ if (duk__uni_range_match(duk_unicode_ids_noa, sizeof(duk_unicode_ids_noa), (duk_codepoint_t) cp) &&
+ !duk__uni_range_match(duk_unicode_ids_m_let_noa, sizeof(duk_unicode_ids_m_let_noa), (duk_codepoint_t) cp)) {
return 1;
}
return 0;
#else
if (cp < 0x10000L) {
- if (duk__uni_range_match(duk_unicode_ids_noabmp,
- sizeof(duk_unicode_ids_noabmp),
- (duk_codepoint_t) cp) &&
+ if (duk__uni_range_match(duk_unicode_ids_noabmp, sizeof(duk_unicode_ids_noabmp), (duk_codepoint_t) cp) &&
!duk__uni_range_match(duk_unicode_ids_m_let_noabmp,
sizeof(duk_unicode_ids_m_let_noabmp),
(duk_codepoint_t) cp)) {
@@ -12330,10 +13533,7 @@ DUK_INTERNAL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp) {
*/
DUK_LOCAL
-duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr,
- duk_bufwriter_ctx *bw,
- duk_codepoint_t cp,
- duk_bitdecoder_ctx *bd_ctx) {
+duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_codepoint_t cp, duk_bitdecoder_ctx *bd_ctx) {
duk_small_int_t skip = 0;
duk_small_int_t n;
duk_small_int_t t;
@@ -12363,10 +13563,13 @@ duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr,
start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
count = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
DUK_DDD(DUK_DDDPRINT("range: start_i=%ld, start_o=%ld, count=%ld, skip=%ld",
- (long) start_i, (long) start_o, (long) count, (long) skip));
+ (long) start_i,
+ (long) start_o,
+ (long) count,
+ (long) skip));
if (cp >= start_i) {
- tmp_cp = cp - start_i; /* always >= 0 */
+ tmp_cp = cp - start_i; /* always >= 0 */
if (tmp_cp < (duk_codepoint_t) count * (duk_codepoint_t) skip &&
(tmp_cp % (duk_codepoint_t) skip) == 0) {
DUK_DDD(DUK_DDDPRINT("range matches input codepoint"));
@@ -12418,7 +13621,7 @@ duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr,
DUK_DDD(DUK_DDDPRINT("no rule matches, output is same as input"));
/* fall through */
- single:
+single:
if (bw != NULL) {
DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
}
@@ -12480,9 +13683,9 @@ duk_codepoint_t duk__case_transform_helper(duk_hthread *thr,
* The rule is not locale/language specific so it is supported.
*/
- if (cp == 0x03a3L && /* U+03A3 = GREEK CAPITAL LETTER SIGMA */
- duk_unicode_is_letter(prev) && /* prev exists and is not a letter */
- !duk_unicode_is_letter(next)) { /* next does not exist or next is not a letter */
+ if (cp == 0x03a3L && /* U+03A3 = GREEK CAPITAL LETTER SIGMA */
+ duk_unicode_is_letter(prev) && /* prev exists and is not a letter */
+ !duk_unicode_is_letter(next)) { /* next does not exist or next is not a letter */
/* Capital sigma occurred at "end of word", lowercase to
* U+03C2 = GREEK SMALL LETTER FINAL SIGMA. Otherwise
* fall through and let the normal rules lowercase it to
@@ -12498,7 +13701,7 @@ duk_codepoint_t duk__case_transform_helper(duk_hthread *thr,
}
/* 1:1 or special conversions, but not locale/context specific: script generated rules */
- DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
+ duk_memzero(&bd_ctx, sizeof(bd_ctx));
if (uppercase) {
bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_uc;
bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_uc);
@@ -12508,13 +13711,13 @@ duk_codepoint_t duk__case_transform_helper(duk_hthread *thr,
}
return duk__slow_case_conversion(thr, bw, cp, &bd_ctx);
- singlechar:
+singlechar:
if (bw != NULL) {
DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
}
return cp;
- /* unused now, not needed until Turkish/Azeri */
+ /* unused now, not needed until Turkish/Azeri */
#if 0
nochar:
return -1;
@@ -12532,7 +13735,7 @@ DUK_INTERNAL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t u
const duk_uint8_t *p, *p_start, *p_end;
duk_codepoint_t prev, curr, next;
- h_input = duk_require_hstring(thr, -1); /* Accept symbols. */
+ h_input = duk_require_hstring(thr, -1); /* Accept symbols. */
DUK_ASSERT(h_input != NULL);
bw = &bw_alloc;
@@ -12544,7 +13747,8 @@ DUK_INTERNAL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t u
p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
p = p_start;
- prev = -1; DUK_UNREF(prev);
+ prev = -1;
+ DUK_UNREF(prev);
curr = -1;
next = -1;
for (;;) {
@@ -12569,17 +13773,12 @@ DUK_INTERNAL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t u
/* Ensure space for maximum multi-character result; estimate is overkill. */
DUK_BW_ENSURE(thr, bw, 8 * DUK_UNICODE_MAX_XUTF8_LENGTH);
- duk__case_transform_helper(thr,
- bw,
- (duk_codepoint_t) curr,
- prev,
- next,
- uppercase);
+ duk__case_transform_helper(thr, bw, (duk_codepoint_t) curr, prev, next, uppercase);
}
}
DUK_BW_COMPACT(thr, bw);
- (void) duk_buffer_to_string(thr, -1); /* Safe, output is encoded. */
+ (void) duk_buffer_to_string(thr, -1); /* Safe, output is encoded. */
/* invalidates h_buf pointer */
duk_remove_m2(thr);
}
@@ -12602,15 +13801,15 @@ DUK_INTERNAL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr,
return (duk_codepoint_t) duk_unicode_re_canon_lookup[cp];
}
return cp;
-#else /* DUK_USE_REGEXP_CANON_WORKAROUND */
+#else /* DUK_USE_REGEXP_CANON_WORKAROUND */
duk_codepoint_t y;
y = duk__case_transform_helper(thr,
- NULL, /* NULL is allowed, no output */
- cp, /* curr char */
- -1, /* prev char */
- -1, /* next char */
- 1); /* uppercase */
+ NULL, /* NULL is allowed, no output */
+ cp, /* curr char */
+ -1, /* prev char */
+ -1, /* next char */
+ 1); /* uppercase */
if ((y < 0) || (cp >= 0x80 && y < 0x80)) {
/* multiple codepoint conversion or non-ASCII mapped to ASCII
@@ -12620,7 +13819,7 @@ DUK_INTERNAL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr,
}
return y;
-#endif /* DUK_USE_REGEXP_CANON_WORKAROUND */
+#endif /* DUK_USE_REGEXP_CANON_WORKAROUND */
}
/*
@@ -12633,10 +13832,7 @@ DUK_INTERNAL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t x) {
* Note: the description in E5 Section 15.10.2.6 has a typo, it
* contains 'A' twice and lacks 'a'; the intent is [0-9a-zA-Z_].
*/
- if ((x >= '0' && x <= '9') ||
- (x >= 'a' && x <= 'z') ||
- (x >= 'A' && x <= 'Z') ||
- (x == '_')) {
+ if ((x >= '0' && x <= '9') || (x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z') || (x == '_')) {
return 1;
}
return 0;
@@ -12648,56 +13844,189 @@ DUK_INTERNAL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t x) {
/* exposed because lexer needs these too */
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_digit[2] = {
- (duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
+ (duk_uint16_t) 0x0030UL,
+ (duk_uint16_t) 0x0039UL,
};
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_white[22] = {
- (duk_uint16_t) 0x0009UL, (duk_uint16_t) 0x000DUL,
- (duk_uint16_t) 0x0020UL, (duk_uint16_t) 0x0020UL,
- (duk_uint16_t) 0x00A0UL, (duk_uint16_t) 0x00A0UL,
- (duk_uint16_t) 0x1680UL, (duk_uint16_t) 0x1680UL,
- (duk_uint16_t) 0x180EUL, (duk_uint16_t) 0x180EUL,
- (duk_uint16_t) 0x2000UL, (duk_uint16_t) 0x200AUL,
- (duk_uint16_t) 0x2028UL, (duk_uint16_t) 0x2029UL,
- (duk_uint16_t) 0x202FUL, (duk_uint16_t) 0x202FUL,
- (duk_uint16_t) 0x205FUL, (duk_uint16_t) 0x205FUL,
- (duk_uint16_t) 0x3000UL, (duk_uint16_t) 0x3000UL,
+ (duk_uint16_t) 0x0009UL, (duk_uint16_t) 0x000DUL, (duk_uint16_t) 0x0020UL, (duk_uint16_t) 0x0020UL, (duk_uint16_t) 0x00A0UL,
+ (duk_uint16_t) 0x00A0UL, (duk_uint16_t) 0x1680UL, (duk_uint16_t) 0x1680UL, (duk_uint16_t) 0x180EUL, (duk_uint16_t) 0x180EUL,
+ (duk_uint16_t) 0x2000UL, (duk_uint16_t) 0x200AUL, (duk_uint16_t) 0x2028UL, (duk_uint16_t) 0x2029UL, (duk_uint16_t) 0x202FUL,
+ (duk_uint16_t) 0x202FUL, (duk_uint16_t) 0x205FUL, (duk_uint16_t) 0x205FUL, (duk_uint16_t) 0x3000UL, (duk_uint16_t) 0x3000UL,
(duk_uint16_t) 0xFEFFUL, (duk_uint16_t) 0xFEFFUL,
};
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_wordchar[8] = {
- (duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
- (duk_uint16_t) 0x0041UL, (duk_uint16_t) 0x005AUL,
- (duk_uint16_t) 0x005FUL, (duk_uint16_t) 0x005FUL,
- (duk_uint16_t) 0x0061UL, (duk_uint16_t) 0x007AUL,
+ (duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL, (duk_uint16_t) 0x0041UL, (duk_uint16_t) 0x005AUL,
+ (duk_uint16_t) 0x005FUL, (duk_uint16_t) 0x005FUL, (duk_uint16_t) 0x0061UL, (duk_uint16_t) 0x007AUL,
};
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_digit[4] = {
- (duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
- (duk_uint16_t) 0x003AUL, (duk_uint16_t) 0xFFFFUL,
+ (duk_uint16_t) 0x0000UL,
+ (duk_uint16_t) 0x002FUL,
+ (duk_uint16_t) 0x003AUL,
+ (duk_uint16_t) 0xFFFFUL,
};
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_white[24] = {
- (duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x0008UL,
- (duk_uint16_t) 0x000EUL, (duk_uint16_t) 0x001FUL,
- (duk_uint16_t) 0x0021UL, (duk_uint16_t) 0x009FUL,
- (duk_uint16_t) 0x00A1UL, (duk_uint16_t) 0x167FUL,
- (duk_uint16_t) 0x1681UL, (duk_uint16_t) 0x180DUL,
- (duk_uint16_t) 0x180FUL, (duk_uint16_t) 0x1FFFUL,
- (duk_uint16_t) 0x200BUL, (duk_uint16_t) 0x2027UL,
- (duk_uint16_t) 0x202AUL, (duk_uint16_t) 0x202EUL,
- (duk_uint16_t) 0x2030UL, (duk_uint16_t) 0x205EUL,
- (duk_uint16_t) 0x2060UL, (duk_uint16_t) 0x2FFFUL,
- (duk_uint16_t) 0x3001UL, (duk_uint16_t) 0xFEFEUL,
- (duk_uint16_t) 0xFF00UL, (duk_uint16_t) 0xFFFFUL,
+ (duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x0008UL, (duk_uint16_t) 0x000EUL, (duk_uint16_t) 0x001FUL, (duk_uint16_t) 0x0021UL,
+ (duk_uint16_t) 0x009FUL, (duk_uint16_t) 0x00A1UL, (duk_uint16_t) 0x167FUL, (duk_uint16_t) 0x1681UL, (duk_uint16_t) 0x180DUL,
+ (duk_uint16_t) 0x180FUL, (duk_uint16_t) 0x1FFFUL, (duk_uint16_t) 0x200BUL, (duk_uint16_t) 0x2027UL, (duk_uint16_t) 0x202AUL,
+ (duk_uint16_t) 0x202EUL, (duk_uint16_t) 0x2030UL, (duk_uint16_t) 0x205EUL, (duk_uint16_t) 0x2060UL, (duk_uint16_t) 0x2FFFUL,
+ (duk_uint16_t) 0x3001UL, (duk_uint16_t) 0xFEFEUL, (duk_uint16_t) 0xFF00UL, (duk_uint16_t) 0xFFFFUL,
};
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = {
- (duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
- (duk_uint16_t) 0x003AUL, (duk_uint16_t) 0x0040UL,
- (duk_uint16_t) 0x005BUL, (duk_uint16_t) 0x005EUL,
- (duk_uint16_t) 0x0060UL, (duk_uint16_t) 0x0060UL,
- (duk_uint16_t) 0x007BUL, (duk_uint16_t) 0xFFFFUL,
+ (duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL, (duk_uint16_t) 0x003AUL, (duk_uint16_t) 0x0040UL, (duk_uint16_t) 0x005BUL,
+ (duk_uint16_t) 0x005EUL, (duk_uint16_t) 0x0060UL, (duk_uint16_t) 0x0060UL, (duk_uint16_t) 0x007BUL, (duk_uint16_t) 0xFFFFUL,
+};
+
+#endif /* DUK_USE_REGEXP_SUPPORT */
+/*
+ * Macro support functions for reading/writing raw data.
+ *
+ * These are done using memcpy to ensure they're valid even for unaligned
+ * reads/writes on platforms where alignment counts. On x86 at least gcc
+ * is able to compile these into a bswap+mov. "Always inline" is used to
+ * ensure these macros compile to minimal code.
+ */
+
+/* #include duk_internal.h -> already included */
+
+union duk__u16_union {
+ duk_uint8_t b[2];
+ duk_uint16_t x;
+};
+typedef union duk__u16_union duk__u16_union;
+
+union duk__u32_union {
+ duk_uint8_t b[4];
+ duk_uint32_t x;
};
+typedef union duk__u32_union duk__u32_union;
-#endif /* DUK_USE_REGEXP_SUPPORT */
+#if defined(DUK_USE_64BIT_OPS)
+union duk__u64_union {
+ duk_uint8_t b[8];
+ duk_uint64_t x;
+};
+typedef union duk__u64_union duk__u64_union;
+#endif
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(const duk_uint8_t *p) {
+ duk__u16_union u;
+ duk_memcpy((void *) u.b, (const void *) p, (size_t) 2);
+ u.x = DUK_NTOH16(u.x);
+ return u.x;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(const duk_uint8_t *p) {
+ duk__u32_union u;
+ duk_memcpy((void *) u.b, (const void *) p, (size_t) 4);
+ u.x = DUK_NTOH32(u.x);
+ return u.x;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_float_t duk_raw_read_float_be(const duk_uint8_t *p) {
+ duk_float_union fu;
+ duk_memcpy((void *) fu.uc, (const void *) p, (size_t) 4);
+ duk_fltunion_big_to_host(&fu);
+ return fu.f;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_read_double_be(const duk_uint8_t *p) {
+ duk_double_union du;
+ duk_memcpy((void *) du.uc, (const void *) p, (size_t) 8);
+ duk_dblunion_big_to_host(&du);
+ return du.d;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_readinc_u16_be(const duk_uint8_t **p) {
+ duk_uint16_t res = duk_raw_read_u16_be(*p);
+ *p += 2;
+ return res;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_readinc_u32_be(const duk_uint8_t **p) {
+ duk_uint32_t res = duk_raw_read_u32_be(*p);
+ *p += 4;
+ return res;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_float_t duk_raw_readinc_float_be(const duk_uint8_t **p) {
+ duk_float_t res = duk_raw_read_float_be(*p);
+ *p += 4;
+ return res;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_readinc_double_be(const duk_uint8_t **p) {
+ duk_double_t res = duk_raw_read_double_be(*p);
+ *p += 8;
+ return res;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t *p, duk_uint16_t val) {
+ duk__u16_union u;
+ u.x = DUK_HTON16(val);
+ duk_memcpy((void *) p, (const void *) u.b, (size_t) 2);
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t *p, duk_uint32_t val) {
+ duk__u32_union u;
+ u.x = DUK_HTON32(val);
+ duk_memcpy((void *) p, (const void *) u.b, (size_t) 4);
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_float_be(duk_uint8_t *p, duk_float_t val) {
+ duk_float_union fu;
+ fu.f = val;
+ duk_fltunion_host_to_big(&fu);
+ duk_memcpy((void *) p, (const void *) fu.uc, (size_t) 4);
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_double_be(duk_uint8_t *p, duk_double_t val) {
+ duk_double_union du;
+ du.d = val;
+ duk_dblunion_host_to_big(&du);
+ duk_memcpy((void *) p, (const void *) du.uc, (size_t) 8);
+}
+
+DUK_INTERNAL duk_small_int_t duk_raw_write_xutf8(duk_uint8_t *p, duk_ucodepoint_t val) {
+ duk_small_int_t len = duk_unicode_encode_xutf8(val, p);
+ return len;
+}
+
+DUK_INTERNAL duk_small_int_t duk_raw_write_cesu8(duk_uint8_t *p, duk_ucodepoint_t val) {
+ duk_small_int_t len = duk_unicode_encode_cesu8(val, p);
+ return len;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_u16_be(duk_uint8_t **p, duk_uint16_t val) {
+ duk_raw_write_u16_be(*p, val);
+ *p += 2;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_u32_be(duk_uint8_t **p, duk_uint32_t val) {
+ duk_raw_write_u32_be(*p, val);
+ *p += 4;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_float_be(duk_uint8_t **p, duk_float_t val) {
+ duk_raw_write_float_be(*p, val);
+ *p += 4;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_double_be(duk_uint8_t **p, duk_double_t val) {
+ duk_raw_write_double_be(*p, val);
+ *p += 8;
+}
+
+DUK_INTERNAL void duk_raw_writeinc_xutf8(duk_uint8_t **p, duk_ucodepoint_t val) {
+ duk_small_int_t len = duk_unicode_encode_xutf8(val, *p);
+ *p += len;
+}
+
+DUK_INTERNAL void duk_raw_writeinc_cesu8(duk_uint8_t **p, duk_ucodepoint_t val) {
+ duk_small_int_t len = duk_unicode_encode_cesu8(val, *p);
+ *p += len;
+}
/*
- * Misc util stuff
+ * Misc util stuff.
*/
/* #include duk_internal.h -> already included */
@@ -12708,23 +14037,17 @@ DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = {
*/
DUK_INTERNAL const duk_uint8_t duk_lc_digits[36] = {
- DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
- DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
- DUK_ASC_8, DUK_ASC_9, DUK_ASC_LC_A, DUK_ASC_LC_B,
- DUK_ASC_LC_C, DUK_ASC_LC_D, DUK_ASC_LC_E, DUK_ASC_LC_F,
- DUK_ASC_LC_G, DUK_ASC_LC_H, DUK_ASC_LC_I, DUK_ASC_LC_J,
- DUK_ASC_LC_K, DUK_ASC_LC_L, DUK_ASC_LC_M, DUK_ASC_LC_N,
- DUK_ASC_LC_O, DUK_ASC_LC_P, DUK_ASC_LC_Q, DUK_ASC_LC_R,
- DUK_ASC_LC_S, DUK_ASC_LC_T, DUK_ASC_LC_U, DUK_ASC_LC_V,
+ DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3, DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
+ DUK_ASC_8, DUK_ASC_9, DUK_ASC_LC_A, DUK_ASC_LC_B, DUK_ASC_LC_C, DUK_ASC_LC_D, DUK_ASC_LC_E, DUK_ASC_LC_F,
+ DUK_ASC_LC_G, DUK_ASC_LC_H, DUK_ASC_LC_I, DUK_ASC_LC_J, DUK_ASC_LC_K, DUK_ASC_LC_L, DUK_ASC_LC_M, DUK_ASC_LC_N,
+ DUK_ASC_LC_O, DUK_ASC_LC_P, DUK_ASC_LC_Q, DUK_ASC_LC_R, DUK_ASC_LC_S, DUK_ASC_LC_T, DUK_ASC_LC_U, DUK_ASC_LC_V,
DUK_ASC_LC_W, DUK_ASC_LC_X, DUK_ASC_LC_Y, DUK_ASC_LC_Z
};
-DUK_INTERNAL const duk_uint8_t duk_uc_nybbles[16] = {
- DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
- DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
- DUK_ASC_8, DUK_ASC_9, DUK_ASC_UC_A, DUK_ASC_UC_B,
- DUK_ASC_UC_C, DUK_ASC_UC_D, DUK_ASC_UC_E, DUK_ASC_UC_F
-};
+DUK_INTERNAL const duk_uint8_t duk_uc_nybbles[16] = { DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
+ DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
+ DUK_ASC_8, DUK_ASC_9, DUK_ASC_UC_A, DUK_ASC_UC_B,
+ DUK_ASC_UC_C, DUK_ASC_UC_D, DUK_ASC_UC_E, DUK_ASC_UC_F };
/*
* Table for hex decoding ASCII hex digits
@@ -12732,43 +14055,43 @@ DUK_INTERNAL const duk_uint8_t duk_uc_nybbles[16] = {
DUK_INTERNAL const duk_int8_t duk_hex_dectab[256] = {
/* -1 if invalid */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x20-0x2f */
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 0x30-0x3f */
- -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x40-0x4f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x50-0x5f */
- -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x60-0x6f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x70-0x7f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80-0x8f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90-0x9f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0-0xaf */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0-0xbf */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0-0xcf */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0-0xdf */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0-0xef */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0-0xff */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x20-0x2f */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 0x30-0x3f */
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x40-0x4f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x50-0x5f */
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x60-0x6f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x70-0x7f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80-0x8f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90-0x9f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0-0xaf */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0-0xbf */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0-0xcf */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0-0xdf */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0-0xef */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0-0xff */
};
#if defined(DUK_USE_HEX_FASTPATH)
/* Preshifted << 4. Must use 16-bit entry to allow negative value signaling. */
DUK_INTERNAL const duk_int16_t duk_hex_dectab_shift4[256] = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x20-0x2f */
- 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, -1, -1, -1, -1, -1, -1, /* 0x30-0x3f */
- -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x40-0x4f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x50-0x5f */
- -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x60-0x6f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x70-0x7f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80-0x8f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90-0x9f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0-0xaf */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0-0xbf */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0-0xcf */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0-0xdf */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0-0xef */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0-0xff */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x20-0x2f */
+ 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, -1, -1, -1, -1, -1, -1, /* 0x30-0x3f */
+ -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x40-0x4f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x50-0x5f */
+ -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x60-0x6f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x70-0x7f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80-0x8f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90-0x9f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0-0xaf */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0-0xbf */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0-0xcf */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0-0xdf */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0-0xef */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0-0xff */
};
#endif
@@ -12787,116 +14110,53 @@ DUK_INTERNAL const duk_int16_t duk_hex_dectab_shift4[256] = {
* print('0x' + t.encode('hex') + 'U')
* print('big endian'); genhextab(False)
* print('little endian'); genhextab(True)
-*/
+ */
DUK_INTERNAL const duk_uint16_t duk_hex_enctab[256] = {
#if defined(DUK_USE_INTEGER_BE)
- 0x3030U, 0x3031U, 0x3032U, 0x3033U, 0x3034U, 0x3035U, 0x3036U, 0x3037U,
- 0x3038U, 0x3039U, 0x3061U, 0x3062U, 0x3063U, 0x3064U, 0x3065U, 0x3066U,
- 0x3130U, 0x3131U, 0x3132U, 0x3133U, 0x3134U, 0x3135U, 0x3136U, 0x3137U,
- 0x3138U, 0x3139U, 0x3161U, 0x3162U, 0x3163U, 0x3164U, 0x3165U, 0x3166U,
- 0x3230U, 0x3231U, 0x3232U, 0x3233U, 0x3234U, 0x3235U, 0x3236U, 0x3237U,
- 0x3238U, 0x3239U, 0x3261U, 0x3262U, 0x3263U, 0x3264U, 0x3265U, 0x3266U,
- 0x3330U, 0x3331U, 0x3332U, 0x3333U, 0x3334U, 0x3335U, 0x3336U, 0x3337U,
- 0x3338U, 0x3339U, 0x3361U, 0x3362U, 0x3363U, 0x3364U, 0x3365U, 0x3366U,
- 0x3430U, 0x3431U, 0x3432U, 0x3433U, 0x3434U, 0x3435U, 0x3436U, 0x3437U,
- 0x3438U, 0x3439U, 0x3461U, 0x3462U, 0x3463U, 0x3464U, 0x3465U, 0x3466U,
- 0x3530U, 0x3531U, 0x3532U, 0x3533U, 0x3534U, 0x3535U, 0x3536U, 0x3537U,
- 0x3538U, 0x3539U, 0x3561U, 0x3562U, 0x3563U, 0x3564U, 0x3565U, 0x3566U,
- 0x3630U, 0x3631U, 0x3632U, 0x3633U, 0x3634U, 0x3635U, 0x3636U, 0x3637U,
- 0x3638U, 0x3639U, 0x3661U, 0x3662U, 0x3663U, 0x3664U, 0x3665U, 0x3666U,
- 0x3730U, 0x3731U, 0x3732U, 0x3733U, 0x3734U, 0x3735U, 0x3736U, 0x3737U,
- 0x3738U, 0x3739U, 0x3761U, 0x3762U, 0x3763U, 0x3764U, 0x3765U, 0x3766U,
- 0x3830U, 0x3831U, 0x3832U, 0x3833U, 0x3834U, 0x3835U, 0x3836U, 0x3837U,
- 0x3838U, 0x3839U, 0x3861U, 0x3862U, 0x3863U, 0x3864U, 0x3865U, 0x3866U,
- 0x3930U, 0x3931U, 0x3932U, 0x3933U, 0x3934U, 0x3935U, 0x3936U, 0x3937U,
- 0x3938U, 0x3939U, 0x3961U, 0x3962U, 0x3963U, 0x3964U, 0x3965U, 0x3966U,
- 0x6130U, 0x6131U, 0x6132U, 0x6133U, 0x6134U, 0x6135U, 0x6136U, 0x6137U,
- 0x6138U, 0x6139U, 0x6161U, 0x6162U, 0x6163U, 0x6164U, 0x6165U, 0x6166U,
- 0x6230U, 0x6231U, 0x6232U, 0x6233U, 0x6234U, 0x6235U, 0x6236U, 0x6237U,
- 0x6238U, 0x6239U, 0x6261U, 0x6262U, 0x6263U, 0x6264U, 0x6265U, 0x6266U,
- 0x6330U, 0x6331U, 0x6332U, 0x6333U, 0x6334U, 0x6335U, 0x6336U, 0x6337U,
- 0x6338U, 0x6339U, 0x6361U, 0x6362U, 0x6363U, 0x6364U, 0x6365U, 0x6366U,
- 0x6430U, 0x6431U, 0x6432U, 0x6433U, 0x6434U, 0x6435U, 0x6436U, 0x6437U,
- 0x6438U, 0x6439U, 0x6461U, 0x6462U, 0x6463U, 0x6464U, 0x6465U, 0x6466U,
- 0x6530U, 0x6531U, 0x6532U, 0x6533U, 0x6534U, 0x6535U, 0x6536U, 0x6537U,
- 0x6538U, 0x6539U, 0x6561U, 0x6562U, 0x6563U, 0x6564U, 0x6565U, 0x6566U,
- 0x6630U, 0x6631U, 0x6632U, 0x6633U, 0x6634U, 0x6635U, 0x6636U, 0x6637U,
- 0x6638U, 0x6639U, 0x6661U, 0x6662U, 0x6663U, 0x6664U, 0x6665U, 0x6666U
-#else /* DUK_USE_INTEGER_BE */
- 0x3030U, 0x3130U, 0x3230U, 0x3330U, 0x3430U, 0x3530U, 0x3630U, 0x3730U,
- 0x3830U, 0x3930U, 0x6130U, 0x6230U, 0x6330U, 0x6430U, 0x6530U, 0x6630U,
- 0x3031U, 0x3131U, 0x3231U, 0x3331U, 0x3431U, 0x3531U, 0x3631U, 0x3731U,
- 0x3831U, 0x3931U, 0x6131U, 0x6231U, 0x6331U, 0x6431U, 0x6531U, 0x6631U,
- 0x3032U, 0x3132U, 0x3232U, 0x3332U, 0x3432U, 0x3532U, 0x3632U, 0x3732U,
- 0x3832U, 0x3932U, 0x6132U, 0x6232U, 0x6332U, 0x6432U, 0x6532U, 0x6632U,
- 0x3033U, 0x3133U, 0x3233U, 0x3333U, 0x3433U, 0x3533U, 0x3633U, 0x3733U,
- 0x3833U, 0x3933U, 0x6133U, 0x6233U, 0x6333U, 0x6433U, 0x6533U, 0x6633U,
- 0x3034U, 0x3134U, 0x3234U, 0x3334U, 0x3434U, 0x3534U, 0x3634U, 0x3734U,
- 0x3834U, 0x3934U, 0x6134U, 0x6234U, 0x6334U, 0x6434U, 0x6534U, 0x6634U,
- 0x3035U, 0x3135U, 0x3235U, 0x3335U, 0x3435U, 0x3535U, 0x3635U, 0x3735U,
- 0x3835U, 0x3935U, 0x6135U, 0x6235U, 0x6335U, 0x6435U, 0x6535U, 0x6635U,
- 0x3036U, 0x3136U, 0x3236U, 0x3336U, 0x3436U, 0x3536U, 0x3636U, 0x3736U,
- 0x3836U, 0x3936U, 0x6136U, 0x6236U, 0x6336U, 0x6436U, 0x6536U, 0x6636U,
- 0x3037U, 0x3137U, 0x3237U, 0x3337U, 0x3437U, 0x3537U, 0x3637U, 0x3737U,
- 0x3837U, 0x3937U, 0x6137U, 0x6237U, 0x6337U, 0x6437U, 0x6537U, 0x6637U,
- 0x3038U, 0x3138U, 0x3238U, 0x3338U, 0x3438U, 0x3538U, 0x3638U, 0x3738U,
- 0x3838U, 0x3938U, 0x6138U, 0x6238U, 0x6338U, 0x6438U, 0x6538U, 0x6638U,
- 0x3039U, 0x3139U, 0x3239U, 0x3339U, 0x3439U, 0x3539U, 0x3639U, 0x3739U,
- 0x3839U, 0x3939U, 0x6139U, 0x6239U, 0x6339U, 0x6439U, 0x6539U, 0x6639U,
- 0x3061U, 0x3161U, 0x3261U, 0x3361U, 0x3461U, 0x3561U, 0x3661U, 0x3761U,
- 0x3861U, 0x3961U, 0x6161U, 0x6261U, 0x6361U, 0x6461U, 0x6561U, 0x6661U,
- 0x3062U, 0x3162U, 0x3262U, 0x3362U, 0x3462U, 0x3562U, 0x3662U, 0x3762U,
- 0x3862U, 0x3962U, 0x6162U, 0x6262U, 0x6362U, 0x6462U, 0x6562U, 0x6662U,
- 0x3063U, 0x3163U, 0x3263U, 0x3363U, 0x3463U, 0x3563U, 0x3663U, 0x3763U,
- 0x3863U, 0x3963U, 0x6163U, 0x6263U, 0x6363U, 0x6463U, 0x6563U, 0x6663U,
- 0x3064U, 0x3164U, 0x3264U, 0x3364U, 0x3464U, 0x3564U, 0x3664U, 0x3764U,
- 0x3864U, 0x3964U, 0x6164U, 0x6264U, 0x6364U, 0x6464U, 0x6564U, 0x6664U,
- 0x3065U, 0x3165U, 0x3265U, 0x3365U, 0x3465U, 0x3565U, 0x3665U, 0x3765U,
- 0x3865U, 0x3965U, 0x6165U, 0x6265U, 0x6365U, 0x6465U, 0x6565U, 0x6665U,
- 0x3066U, 0x3166U, 0x3266U, 0x3366U, 0x3466U, 0x3566U, 0x3666U, 0x3766U,
- 0x3866U, 0x3966U, 0x6166U, 0x6266U, 0x6366U, 0x6466U, 0x6566U, 0x6666U
-#endif /* DUK_USE_INTEGER_BE */
+ 0x3030U, 0x3031U, 0x3032U, 0x3033U, 0x3034U, 0x3035U, 0x3036U, 0x3037U, 0x3038U, 0x3039U, 0x3061U, 0x3062U, 0x3063U,
+ 0x3064U, 0x3065U, 0x3066U, 0x3130U, 0x3131U, 0x3132U, 0x3133U, 0x3134U, 0x3135U, 0x3136U, 0x3137U, 0x3138U, 0x3139U,
+ 0x3161U, 0x3162U, 0x3163U, 0x3164U, 0x3165U, 0x3166U, 0x3230U, 0x3231U, 0x3232U, 0x3233U, 0x3234U, 0x3235U, 0x3236U,
+ 0x3237U, 0x3238U, 0x3239U, 0x3261U, 0x3262U, 0x3263U, 0x3264U, 0x3265U, 0x3266U, 0x3330U, 0x3331U, 0x3332U, 0x3333U,
+ 0x3334U, 0x3335U, 0x3336U, 0x3337U, 0x3338U, 0x3339U, 0x3361U, 0x3362U, 0x3363U, 0x3364U, 0x3365U, 0x3366U, 0x3430U,
+ 0x3431U, 0x3432U, 0x3433U, 0x3434U, 0x3435U, 0x3436U, 0x3437U, 0x3438U, 0x3439U, 0x3461U, 0x3462U, 0x3463U, 0x3464U,
+ 0x3465U, 0x3466U, 0x3530U, 0x3531U, 0x3532U, 0x3533U, 0x3534U, 0x3535U, 0x3536U, 0x3537U, 0x3538U, 0x3539U, 0x3561U,
+ 0x3562U, 0x3563U, 0x3564U, 0x3565U, 0x3566U, 0x3630U, 0x3631U, 0x3632U, 0x3633U, 0x3634U, 0x3635U, 0x3636U, 0x3637U,
+ 0x3638U, 0x3639U, 0x3661U, 0x3662U, 0x3663U, 0x3664U, 0x3665U, 0x3666U, 0x3730U, 0x3731U, 0x3732U, 0x3733U, 0x3734U,
+ 0x3735U, 0x3736U, 0x3737U, 0x3738U, 0x3739U, 0x3761U, 0x3762U, 0x3763U, 0x3764U, 0x3765U, 0x3766U, 0x3830U, 0x3831U,
+ 0x3832U, 0x3833U, 0x3834U, 0x3835U, 0x3836U, 0x3837U, 0x3838U, 0x3839U, 0x3861U, 0x3862U, 0x3863U, 0x3864U, 0x3865U,
+ 0x3866U, 0x3930U, 0x3931U, 0x3932U, 0x3933U, 0x3934U, 0x3935U, 0x3936U, 0x3937U, 0x3938U, 0x3939U, 0x3961U, 0x3962U,
+ 0x3963U, 0x3964U, 0x3965U, 0x3966U, 0x6130U, 0x6131U, 0x6132U, 0x6133U, 0x6134U, 0x6135U, 0x6136U, 0x6137U, 0x6138U,
+ 0x6139U, 0x6161U, 0x6162U, 0x6163U, 0x6164U, 0x6165U, 0x6166U, 0x6230U, 0x6231U, 0x6232U, 0x6233U, 0x6234U, 0x6235U,
+ 0x6236U, 0x6237U, 0x6238U, 0x6239U, 0x6261U, 0x6262U, 0x6263U, 0x6264U, 0x6265U, 0x6266U, 0x6330U, 0x6331U, 0x6332U,
+ 0x6333U, 0x6334U, 0x6335U, 0x6336U, 0x6337U, 0x6338U, 0x6339U, 0x6361U, 0x6362U, 0x6363U, 0x6364U, 0x6365U, 0x6366U,
+ 0x6430U, 0x6431U, 0x6432U, 0x6433U, 0x6434U, 0x6435U, 0x6436U, 0x6437U, 0x6438U, 0x6439U, 0x6461U, 0x6462U, 0x6463U,
+ 0x6464U, 0x6465U, 0x6466U, 0x6530U, 0x6531U, 0x6532U, 0x6533U, 0x6534U, 0x6535U, 0x6536U, 0x6537U, 0x6538U, 0x6539U,
+ 0x6561U, 0x6562U, 0x6563U, 0x6564U, 0x6565U, 0x6566U, 0x6630U, 0x6631U, 0x6632U, 0x6633U, 0x6634U, 0x6635U, 0x6636U,
+ 0x6637U, 0x6638U, 0x6639U, 0x6661U, 0x6662U, 0x6663U, 0x6664U, 0x6665U, 0x6666U
+#else /* DUK_USE_INTEGER_BE */
+ 0x3030U, 0x3130U, 0x3230U, 0x3330U, 0x3430U, 0x3530U, 0x3630U, 0x3730U, 0x3830U, 0x3930U, 0x6130U, 0x6230U, 0x6330U,
+ 0x6430U, 0x6530U, 0x6630U, 0x3031U, 0x3131U, 0x3231U, 0x3331U, 0x3431U, 0x3531U, 0x3631U, 0x3731U, 0x3831U, 0x3931U,
+ 0x6131U, 0x6231U, 0x6331U, 0x6431U, 0x6531U, 0x6631U, 0x3032U, 0x3132U, 0x3232U, 0x3332U, 0x3432U, 0x3532U, 0x3632U,
+ 0x3732U, 0x3832U, 0x3932U, 0x6132U, 0x6232U, 0x6332U, 0x6432U, 0x6532U, 0x6632U, 0x3033U, 0x3133U, 0x3233U, 0x3333U,
+ 0x3433U, 0x3533U, 0x3633U, 0x3733U, 0x3833U, 0x3933U, 0x6133U, 0x6233U, 0x6333U, 0x6433U, 0x6533U, 0x6633U, 0x3034U,
+ 0x3134U, 0x3234U, 0x3334U, 0x3434U, 0x3534U, 0x3634U, 0x3734U, 0x3834U, 0x3934U, 0x6134U, 0x6234U, 0x6334U, 0x6434U,
+ 0x6534U, 0x6634U, 0x3035U, 0x3135U, 0x3235U, 0x3335U, 0x3435U, 0x3535U, 0x3635U, 0x3735U, 0x3835U, 0x3935U, 0x6135U,
+ 0x6235U, 0x6335U, 0x6435U, 0x6535U, 0x6635U, 0x3036U, 0x3136U, 0x3236U, 0x3336U, 0x3436U, 0x3536U, 0x3636U, 0x3736U,
+ 0x3836U, 0x3936U, 0x6136U, 0x6236U, 0x6336U, 0x6436U, 0x6536U, 0x6636U, 0x3037U, 0x3137U, 0x3237U, 0x3337U, 0x3437U,
+ 0x3537U, 0x3637U, 0x3737U, 0x3837U, 0x3937U, 0x6137U, 0x6237U, 0x6337U, 0x6437U, 0x6537U, 0x6637U, 0x3038U, 0x3138U,
+ 0x3238U, 0x3338U, 0x3438U, 0x3538U, 0x3638U, 0x3738U, 0x3838U, 0x3938U, 0x6138U, 0x6238U, 0x6338U, 0x6438U, 0x6538U,
+ 0x6638U, 0x3039U, 0x3139U, 0x3239U, 0x3339U, 0x3439U, 0x3539U, 0x3639U, 0x3739U, 0x3839U, 0x3939U, 0x6139U, 0x6239U,
+ 0x6339U, 0x6439U, 0x6539U, 0x6639U, 0x3061U, 0x3161U, 0x3261U, 0x3361U, 0x3461U, 0x3561U, 0x3661U, 0x3761U, 0x3861U,
+ 0x3961U, 0x6161U, 0x6261U, 0x6361U, 0x6461U, 0x6561U, 0x6661U, 0x3062U, 0x3162U, 0x3262U, 0x3362U, 0x3462U, 0x3562U,
+ 0x3662U, 0x3762U, 0x3862U, 0x3962U, 0x6162U, 0x6262U, 0x6362U, 0x6462U, 0x6562U, 0x6662U, 0x3063U, 0x3163U, 0x3263U,
+ 0x3363U, 0x3463U, 0x3563U, 0x3663U, 0x3763U, 0x3863U, 0x3963U, 0x6163U, 0x6263U, 0x6363U, 0x6463U, 0x6563U, 0x6663U,
+ 0x3064U, 0x3164U, 0x3264U, 0x3364U, 0x3464U, 0x3564U, 0x3664U, 0x3764U, 0x3864U, 0x3964U, 0x6164U, 0x6264U, 0x6364U,
+ 0x6464U, 0x6564U, 0x6664U, 0x3065U, 0x3165U, 0x3265U, 0x3365U, 0x3465U, 0x3565U, 0x3665U, 0x3765U, 0x3865U, 0x3965U,
+ 0x6165U, 0x6265U, 0x6365U, 0x6465U, 0x6565U, 0x6665U, 0x3066U, 0x3166U, 0x3266U, 0x3366U, 0x3466U, 0x3566U, 0x3666U,
+ 0x3766U, 0x3866U, 0x3966U, 0x6166U, 0x6266U, 0x6366U, 0x6466U, 0x6566U, 0x6666U
+#endif /* DUK_USE_INTEGER_BE */
};
-#endif /* DUK_USE_HEX_FASTPATH */
-
-/*
- * Table for base-64 encoding
- */
-
-#if defined(DUK_USE_BASE64_FASTPATH)
-DUK_INTERNAL const duk_uint8_t duk_base64_enctab[64] = {
- 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, /* A...P */
- 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, /* Q...f */
- 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, /* g...v */
- 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f /* w.../ */
-};
-#endif /* DUK_USE_BASE64_FASTPATH */
-
-/*
- * Table for base-64 decoding
- */
-
-#if defined(DUK_USE_BASE64_FASTPATH)
-DUK_INTERNAL const duk_int8_t duk_base64_dectab[256] = {
- /* -1 = error, -2 = allowed whitespace, -3 = padding ('='), 0...63 decoded bytes */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -1, -1, -2, -1, -1, /* 0x00...0x0f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10...0x1f */
- -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20...0x2f */
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -3, -1, -1, /* 0x30...0x3f */
- -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40...0x4f */
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50...0x5f */
- -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60...0x6f */
- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 0x70...0x7f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80...0x8f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90...0x9f */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0...0xaf */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0...0xbf */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0...0xcf */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0...0xdf */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0...0xef */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0...0xff */
-};
-#endif /* DUK_USE_BASE64_FASTPATH */
+#endif /* DUK_USE_HEX_FASTPATH */
/*
* Arbitrary byteswap for potentially unaligned values
@@ -12904,7 +14164,7 @@ DUK_INTERNAL const duk_int8_t duk_base64_dectab[256] = {
* Used to byteswap pointers e.g. in debugger code.
*/
-#if defined(DUK_USE_DEBUGGER_SUPPORT) /* For now only needed by the debugger. */
+#if defined(DUK_USE_DEBUGGER_SUPPORT) /* For now only needed by the debugger. */
DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) {
duk_uint8_t tmp;
duk_uint8_t *q = p + len - 1;
@@ -12920,189 +14180,18 @@ DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) {
#endif
/*
- * Miscellaneous coercion / clamping helpers.
- */
-
-/* Check whether a duk_double_t is a whole number in the 32-bit range (reject
- * negative zero), and if so, return a duk_int32_t.
- * For compiler use: don't allow negative zero as it will cause trouble with
- * LDINT+LDINTX, positive zero is OK.
- */
-DUK_INTERNAL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival) {
- duk_int32_t t;
-
- t = (duk_int32_t) x;
- if (!((duk_double_t) t == x)) {
- return 0;
- }
- if (t == 0) {
- duk_double_union du;
- du.d = x;
- if (DUK_DBLUNION_HAS_SIGNBIT(&du)) {
- return 0;
- }
- }
- *ival = t;
- return 1;
-}
-
-/* Check whether a duk_double_t is a whole number in the 32-bit range, and if
- * so, return a duk_int32_t.
- */
-DUK_INTERNAL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival) {
- duk_int32_t t;
-
- t = (duk_int32_t) x;
- if (!((duk_double_t) t == x)) {
- return 0;
- }
- *ival = t;
- return 1;
-}
-
-/*
- * IEEE double checks
+ * Random
*/
-DUK_INTERNAL duk_bool_t duk_double_is_anyinf(duk_double_t x) {
- duk_double_union du;
- du.d = x;
- return DUK_DBLUNION_IS_ANYINF(&du);
-}
-
-DUK_INTERNAL duk_bool_t duk_double_is_posinf(duk_double_t x) {
- duk_double_union du;
- du.d = x;
- return DUK_DBLUNION_IS_POSINF(&du);
-}
-
-DUK_INTERNAL duk_bool_t duk_double_is_neginf(duk_double_t x) {
- duk_double_union du;
- du.d = x;
- return DUK_DBLUNION_IS_NEGINF(&du);
-}
-
-DUK_INTERNAL duk_bool_t duk_double_is_nan(duk_double_t x) {
- duk_double_union du;
- du.d = x;
- /* Assumes we're dealing with a Duktape internal NaN which is
- * NaN normalized if duk_tval requires it.
- */
- DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
- return DUK_DBLUNION_IS_NAN(&du);
-}
-
-DUK_INTERNAL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x) {
- duk_double_union du;
- du.d = x;
- /* Assumes we're dealing with a Duktape internal NaN which is
- * NaN normalized if duk_tval requires it.
- */
- DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
- return DUK_DBLUNION_IS_NAN(&du) || DUK_DBLUNION_IS_ANYZERO(&du);
-}
-
-DUK_INTERNAL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x) {
- duk_double_union du;
- du.d = x;
- /* If exponent is 0x7FF the argument is either a NaN or an
- * infinity. We don't need to check any other fields.
- */
-#if defined(DUK_USE_64BIT_OPS)
-#if defined(DUK_USE_DOUBLE_ME)
- return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000);
-#else
- return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000);
-#endif
-#else
- return (du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL;
-#endif
-}
-
-DUK_INTERNAL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x) {
- duk_double_union du;
-#if defined(DUK_USE_64BIT_OPS)
- duk_uint64_t t;
-#else
- duk_uint32_t t;
-#endif
- du.d = x;
-#if defined(DUK_USE_64BIT_OPS)
-#if defined(DUK_USE_DOUBLE_ME)
- t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000);
- if (t == DUK_U64_CONSTANT(0x0000000000000000)) {
- t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x0000000080000000);
- return t == 0;
- }
- if (t == DUK_U64_CONSTANT(0x000000007ff00000)) {
- return 1;
- }
-#else
- t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000);
- if (t == DUK_U64_CONSTANT(0x0000000000000000)) {
- t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000);
- return t == 0;
- }
- if (t == DUK_U64_CONSTANT(0x7ff0000000000000)) {
- return 1;
- }
-#endif
+DUK_INTERNAL duk_double_t duk_util_get_random_double(duk_hthread *thr) {
+#if defined(DUK_USE_GET_RANDOM_DOUBLE)
+ return DUK_USE_GET_RANDOM_DOUBLE(thr->heap->heap_udata);
#else
- t = du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL;
- if (t == 0x00000000UL) {
- return DUK_DBLUNION_IS_ANYZERO(&du);
- }
- if (t == 0x7ff00000UL) {
- return 1;
- }
+ return duk_util_tinyrandom_get_double(thr);
#endif
- return 0;
-}
-
-DUK_INTERNAL duk_small_uint_t duk_double_signbit(duk_double_t x) {
- duk_double_union du;
- du.d = x;
- return (duk_small_uint_t) DUK_DBLUNION_GET_SIGNBIT(&du);
-}
-
-DUK_INTERNAL duk_double_t duk_double_trunc_towards_zero(duk_double_t x) {
- /* XXX: optimize */
- duk_small_uint_t s = duk_double_signbit(x);
- x = DUK_FLOOR(DUK_FABS(x)); /* truncate towards zero */
- if (s) {
- x = -x;
- }
- return x;
-}
-
-DUK_INTERNAL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y) {
- duk_double_union du1;
- duk_double_union du2;
- du1.d = x;
- du2.d = y;
-
- return (((du1.ui[DUK_DBL_IDX_UI0] ^ du2.ui[DUK_DBL_IDX_UI0]) & 0x80000000UL) == 0);
-}
-
-DUK_INTERNAL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y) {
- /* Doesn't replicate fmin() behavior exactly: for fmin() if one
- * argument is a NaN, the other argument should be returned.
- * Duktape doesn't rely on this behavior so the replacement can
- * be simplified.
- */
- return (x < y ? x : y);
-}
-
-DUK_INTERNAL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y) {
- /* Doesn't replicate fmax() behavior exactly: for fmax() if one
- * argument is a NaN, the other argument should be returned.
- * Duktape doesn't rely on this behavior so the replacement can
- * be simplified.
- */
- return (x > y ? x : y);
}
/*
- * Hobject Ecmascript [[Class]].
+ * Hobject ECMAScript [[Class]].
*/
/* #include duk_internal.h -> already included */
@@ -13110,13 +14199,13 @@ DUK_INTERNAL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y) {
#if (DUK_STRIDX_UC_ARGUMENTS > 255)
#error constant too large
#endif
-#if (DUK_STRIDX_ARRAY > 255)
+#if (DUK_STRIDX_UC_ARRAY > 255)
#error constant too large
#endif
#if (DUK_STRIDX_UC_BOOLEAN > 255)
#error constant too large
#endif
-#if (DUK_STRIDX_DATE > 255)
+#if (DUK_STRIDX_UC_DATE > 255)
#error constant too large
#endif
#if (DUK_STRIDX_UC_ERROR > 255)
@@ -13197,13 +14286,13 @@ DUK_INTERNAL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y) {
/* Note: assumes that these string indexes are 8-bit, genstrings.py must ensure that */
DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32] = {
- DUK_STRIDX_EMPTY_STRING, /* NONE, intentionally empty */
+ DUK_STRIDX_EMPTY_STRING, /* NONE, intentionally empty */
DUK_STRIDX_UC_OBJECT,
- DUK_STRIDX_ARRAY,
+ DUK_STRIDX_UC_ARRAY,
DUK_STRIDX_UC_FUNCTION,
DUK_STRIDX_UC_ARGUMENTS,
DUK_STRIDX_UC_BOOLEAN,
- DUK_STRIDX_DATE,
+ DUK_STRIDX_UC_DATE,
DUK_STRIDX_UC_ERROR,
DUK_STRIDX_JSON,
DUK_STRIDX_MATH,
@@ -13227,8 +14316,8 @@ DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32] = {
DUK_STRIDX_UINT32_ARRAY,
DUK_STRIDX_FLOAT32_ARRAY,
DUK_STRIDX_FLOAT64_ARRAY,
- DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */
- DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */
+ DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */
+ DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */
};
/*
* Default allocation functions.
@@ -13244,8 +14333,7 @@ DUK_INTERNAL void *duk_default_alloc_function(void *udata, duk_size_t size) {
void *res;
DUK_UNREF(udata);
res = DUK_ANSI_MALLOC(size);
- DUK_DDD(DUK_DDDPRINT("default alloc function: %lu -> %p",
- (unsigned long) size, (void *) res));
+ DUK_DDD(DUK_DDDPRINT("default alloc function: %lu -> %p", (unsigned long) size, (void *) res));
return res;
}
@@ -13253,8 +14341,7 @@ DUK_INTERNAL void *duk_default_realloc_function(void *udata, void *ptr, duk_size
void *res;
DUK_UNREF(udata);
res = DUK_ANSI_REALLOC(ptr, newsize);
- DUK_DDD(DUK_DDDPRINT("default realloc function: %p %lu -> %p",
- (void *) ptr, (unsigned long) newsize, (void *) res));
+ DUK_DDD(DUK_DDDPRINT("default realloc function: %p %lu -> %p", (void *) ptr, (unsigned long) newsize, (void *) res));
return res;
}
@@ -13263,7 +14350,7 @@ DUK_INTERNAL void duk_default_free_function(void *udata, void *ptr) {
DUK_UNREF(udata);
DUK_ANSI_FREE(ptr);
}
-#endif /* DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS */
+#endif /* DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS */
/*
* Buffer
*/
@@ -13280,9 +14367,10 @@ DUK_EXTERNAL void *duk_resize_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t
if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
+ DUK_WO_NORETURN(return NULL;);
}
- /* maximum size check is handled by callee */
+ /* Maximum size check is handled by callee. */
duk_hbuffer_resize(thr, h, new_size);
return DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
@@ -13300,6 +14388,7 @@ DUK_EXTERNAL void *duk_steal_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t
if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
+ DUK_WO_NORETURN(return NULL;);
}
/* Forget the previous allocation, setting size to 0 and alloc to
@@ -13328,6 +14417,7 @@ DUK_EXTERNAL void duk_config_buffer(duk_hthread *thr, duk_idx_t idx, void *ptr,
if (!DUK_HBUFFER_HAS_EXTERNAL(h)) {
DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
+ DUK_WO_NORETURN(return;);
}
DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h));
@@ -13350,33 +14440,33 @@ DUK_EXTERNAL void duk_config_buffer(duk_hthread *thr, duk_idx_t idx, void *ptr,
#if defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
-#define DUK__SER_MARKER 0xbf
-#define DUK__SER_STRING 0x00
-#define DUK__SER_NUMBER 0x01
+#define DUK__SER_MARKER 0xbf
+#define DUK__SER_STRING 0x00
+#define DUK__SER_NUMBER 0x01
#define DUK__BYTECODE_INITIAL_ALLOC 256
-#define DUK__NO_FORMALS 0xffffffffUL
+#define DUK__NO_FORMALS 0xffffffffUL
/*
* Dump/load helpers, xxx_raw() helpers do no buffer checks
*/
-DUK_LOCAL duk_uint8_t *duk__load_string_raw(duk_hthread *thr, duk_uint8_t *p) {
+DUK_LOCAL const duk_uint8_t *duk__load_string_raw(duk_hthread *thr, const duk_uint8_t *p) {
duk_uint32_t len;
- len = DUK_RAW_READ_U32_BE(p);
+ len = DUK_RAW_READINC_U32_BE(p);
duk_push_lstring(thr, (const char *) p, len);
p += len;
return p;
}
-DUK_LOCAL duk_uint8_t *duk__load_buffer_raw(duk_hthread *thr, duk_uint8_t *p) {
+DUK_LOCAL const duk_uint8_t *duk__load_buffer_raw(duk_hthread *thr, const duk_uint8_t *p) {
duk_uint32_t len;
duk_uint8_t *buf;
- len = DUK_RAW_READ_U32_BE(p);
+ len = DUK_RAW_READINC_U32_BE(p);
buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len);
DUK_ASSERT(buf != NULL);
- DUK_MEMCPY((void *) buf, (const void *) p, (size_t) len);
+ duk_memcpy((void *) buf, (const void *) p, (size_t) len);
p += len;
return p;
}
@@ -13388,12 +14478,10 @@ DUK_LOCAL duk_uint8_t *duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h) {
DUK_ASSERT(h != NULL);
len = DUK_HSTRING_GET_BYTELEN(h);
- DUK_ASSERT(len <= 0xffffffffUL); /* string limits */
+ DUK_ASSERT(len <= 0xffffffffUL); /* string limits */
tmp32 = (duk_uint32_t) len;
- DUK_RAW_WRITE_U32_BE(p, tmp32);
- DUK_MEMCPY((void *) p,
- (const void *) DUK_HSTRING_GET_DATA(h),
- len);
+ DUK_RAW_WRITEINC_U32_BE(p, tmp32);
+ duk_memcpy((void *) p, (const void *) DUK_HSTRING_GET_DATA(h), len);
p += len;
return p;
}
@@ -13407,21 +14495,24 @@ DUK_LOCAL duk_uint8_t *duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, d
DUK_UNREF(thr);
len = DUK_HBUFFER_GET_SIZE(h);
- DUK_ASSERT(len <= 0xffffffffUL); /* buffer limits */
+ DUK_ASSERT(len <= 0xffffffffUL); /* buffer limits */
tmp32 = (duk_uint32_t) len;
- DUK_RAW_WRITE_U32_BE(p, tmp32);
- DUK_MEMCPY((void *) p,
- (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),
- len);
+ DUK_RAW_WRITEINC_U32_BE(p, tmp32);
+ /* When len == 0, buffer data pointer may be NULL. */
+ duk_memcpy_unsafe((void *) p, (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h), len);
p += len;
return p;
}
-DUK_LOCAL duk_uint8_t *duk__dump_string_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx) {
+DUK_LOCAL duk_uint8_t *duk__dump_string_prop(duk_hthread *thr,
+ duk_uint8_t *p,
+ duk_bufwriter_ctx *bw_ctx,
+ duk_hobject *func,
+ duk_small_uint_t stridx) {
duk_hstring *h_str;
duk_tval *tv;
- tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
+ tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
if (tv != NULL && DUK_TVAL_IS_STRING(tv)) {
h_str = DUK_TVAL_GET_STRING(tv);
DUK_ASSERT(h_str != NULL);
@@ -13429,56 +14520,61 @@ DUK_LOCAL duk_uint8_t *duk__dump_string_prop(duk_hthread *thr, duk_uint8_t *p, d
h_str = DUK_HTHREAD_STRING_EMPTY_STRING(thr);
DUK_ASSERT(h_str != NULL);
}
- DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
+ DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(h_str), p);
p = duk__dump_hstring_raw(p, h_str);
return p;
}
-DUK_LOCAL duk_uint8_t *duk__dump_buffer_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx) {
+DUK_LOCAL duk_uint8_t *duk__dump_buffer_prop(duk_hthread *thr,
+ duk_uint8_t *p,
+ duk_bufwriter_ctx *bw_ctx,
+ duk_hobject *func,
+ duk_small_uint_t stridx) {
duk_tval *tv;
- tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
+ tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
if (tv != NULL && DUK_TVAL_IS_BUFFER(tv)) {
duk_hbuffer *h_buf;
h_buf = DUK_TVAL_GET_BUFFER(tv);
DUK_ASSERT(h_buf != NULL);
- DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
+ DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HBUFFER_GET_SIZE(h_buf), p);
p = duk__dump_hbuffer_raw(thr, p, h_buf);
} else {
p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
- DUK_RAW_WRITE_U32_BE(p, 0);
+ DUK_RAW_WRITEINC_U32_BE(p, 0);
}
return p;
}
-DUK_LOCAL duk_uint8_t *duk__dump_uint32_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx, duk_uint32_t def_value) {
+DUK_LOCAL duk_uint8_t *duk__dump_uint32_prop(duk_hthread *thr,
+ duk_uint8_t *p,
+ duk_bufwriter_ctx *bw_ctx,
+ duk_hobject *func,
+ duk_small_uint_t stridx,
+ duk_uint32_t def_value) {
duk_tval *tv;
duk_uint32_t val;
- tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
+ tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
if (tv != NULL && DUK_TVAL_IS_NUMBER(tv)) {
val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
} else {
val = def_value;
}
p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
- DUK_RAW_WRITE_U32_BE(p, val);
+ DUK_RAW_WRITEINC_U32_BE(p, val);
return p;
}
DUK_LOCAL duk_uint8_t *duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
- duk_tval *tv;
+ duk_hobject *h;
- tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
- if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
- duk_hobject *h;
+ h = duk_hobject_get_varmap(thr, (duk_hobject *) func);
+ if (h != NULL) {
duk_uint_fast32_t i;
- h = DUK_TVAL_GET_OBJECT(tv);
- DUK_ASSERT(h != NULL);
-
/* We know _Varmap only has own properties so walk property
* table directly. We also know _Varmap is dense and all
* values are numbers; assert for these. GC and finalizers
@@ -13490,36 +14586,36 @@ DUK_LOCAL duk_uint8_t *duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bu
duk_uint32_t val;
key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
- DUK_ASSERT(key != NULL); /* _Varmap is dense */
+ DUK_ASSERT(key != NULL); /* _Varmap is dense */
DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i));
tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i);
DUK_ASSERT(tv_val != NULL);
- DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_val)); /* known to be number; in fact an integer */
+ DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_val)); /* known to be number; in fact an integer */
#if defined(DUK_USE_FASTINT)
DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_val));
- DUK_ASSERT(DUK_TVAL_GET_FASTINT(tv_val) == (duk_int64_t) DUK_TVAL_GET_FASTINT_U32(tv_val)); /* known to be 32-bit */
+ DUK_ASSERT(DUK_TVAL_GET_FASTINT(tv_val) ==
+ (duk_int64_t) DUK_TVAL_GET_FASTINT_U32(tv_val)); /* known to be 32-bit */
val = DUK_TVAL_GET_FASTINT_U32(tv_val);
#else
val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv_val);
#endif
- DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
+ DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(key) + 4U, p);
p = duk__dump_hstring_raw(p, key);
- DUK_RAW_WRITE_U32_BE(p, val);
+ DUK_RAW_WRITEINC_U32_BE(p, val);
}
}
p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
- DUK_RAW_WRITE_U32_BE(p, 0); /* end of _Varmap */
+ DUK_RAW_WRITEINC_U32_BE(p, 0); /* end of _Varmap */
return p;
}
DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
- duk_tval *tv;
+ duk_harray *h;
- tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_FORMALS(thr));
- if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
- duk_harray *h;
+ h = duk_hobject_get_formals(thr, (duk_hobject *) func);
+ if (h != NULL) {
duk_uint32_t i;
/* Here we rely on _Formals being a dense array containing
@@ -13527,14 +14623,10 @@ DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_b
* tweaked by the application (which we don't support right
* now).
*/
- h = (duk_harray *) DUK_TVAL_GET_OBJECT(tv);
- DUK_ASSERT(h != NULL);
- DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) h));
- DUK_ASSERT(h->length <= DUK_HOBJECT_GET_ASIZE((duk_hobject *) h));
p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
- DUK_ASSERT(h->length != DUK__NO_FORMALS); /* limits */
- DUK_RAW_WRITE_U32_BE(p, h->length);
+ DUK_ASSERT(h->length != DUK__NO_FORMALS); /* limits */
+ DUK_RAW_WRITEINC_U32_BE(p, h->length);
for (i = 0; i < h->length; i++) {
duk_tval *tv_val;
@@ -13548,14 +14640,14 @@ DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_b
DUK_ASSERT(varname != NULL);
DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(varname) >= 1);
- DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
+ DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(varname), p);
p = duk__dump_hstring_raw(p, varname);
}
} else {
DUK_DD(DUK_DDPRINT("dumping function without _Formals, emit marker to indicate missing _Formals"));
p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
- DUK_RAW_WRITE_U32_BE(p, DUK__NO_FORMALS); /* marker: no formals */
+ DUK_RAW_WRITEINC_U32_BE(p, DUK__NO_FORMALS); /* marker: no formals */
}
return p;
}
@@ -13589,33 +14681,33 @@ static duk_uint8_t *duk__dump_func(duk_hthread *thr, duk_hcompfunc *func, duk_bu
(long) DUK_HCOMPFUNC_GET_CODE_SIZE(thr->heap, func),
(long) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func)));
- DUK_ASSERT(DUK_USE_ESBC_MAX_BYTES <= 0x7fffffffUL); /* ensures no overflow */
+ DUK_ASSERT(DUK_USE_ESBC_MAX_BYTES <= 0x7fffffffUL); /* ensures no overflow */
count_instr = (duk_uint32_t) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func);
p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 3U * 4U + 2U * 2U + 3U * 4U + count_instr * 4U, p);
/* Fixed header info. */
tmp32 = count_instr;
- DUK_RAW_WRITE_U32_BE(p, tmp32);
+ DUK_RAW_WRITEINC_U32_BE(p, tmp32);
tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func);
- DUK_RAW_WRITE_U32_BE(p, tmp32);
+ DUK_RAW_WRITEINC_U32_BE(p, tmp32);
tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func);
- DUK_RAW_WRITE_U32_BE(p, tmp32);
+ DUK_RAW_WRITEINC_U32_BE(p, tmp32);
tmp16 = func->nregs;
- DUK_RAW_WRITE_U16_BE(p, tmp16);
+ DUK_RAW_WRITEINC_U16_BE(p, tmp16);
tmp16 = func->nargs;
- DUK_RAW_WRITE_U16_BE(p, tmp16);
+ DUK_RAW_WRITEINC_U16_BE(p, tmp16);
#if defined(DUK_USE_DEBUGGER_SUPPORT)
tmp32 = func->start_line;
- DUK_RAW_WRITE_U32_BE(p, tmp32);
+ DUK_RAW_WRITEINC_U32_BE(p, tmp32);
tmp32 = func->end_line;
- DUK_RAW_WRITE_U32_BE(p, tmp32);
+ DUK_RAW_WRITEINC_U32_BE(p, tmp32);
#else
- DUK_RAW_WRITE_U32_BE(p, 0);
- DUK_RAW_WRITE_U32_BE(p, 0);
+ DUK_RAW_WRITEINC_U32_BE(p, 0);
+ DUK_RAW_WRITEINC_U32_BE(p, 0);
#endif
- tmp32 = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) func); /* masks flags, only duk_hobject flags */
- tmp32 &= ~(DUK_HOBJECT_FLAG_HAVE_FINALIZER); /* finalizer flag is lost */
- DUK_RAW_WRITE_U32_BE(p, tmp32);
+ tmp32 = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) func); /* masks flags, only duk_hobject flags */
+ tmp32 &= ~(DUK_HOBJECT_FLAG_HAVE_FINALIZER); /* finalizer flag is lost */
+ DUK_RAW_WRITEINC_U32_BE(p, tmp32);
/* Bytecode instructions: endian conversion needed unless
* platform is big endian.
@@ -13624,12 +14716,13 @@ static duk_uint8_t *duk__dump_func(duk_hthread *thr, duk_hcompfunc *func, duk_bu
ins_end = DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func);
DUK_ASSERT((duk_size_t) (ins_end - ins) == (duk_size_t) count_instr);
#if defined(DUK_USE_INTEGER_BE)
- DUK_MEMCPY((void *) p, (const void *) ins, (size_t) (ins_end - ins));
- p += (size_t) (ins_end - ins);
+ duk_memcpy_unsafe((void *) p, (const void *) ins, count_instr * sizeof(duk_instr_t));
+ p += count_instr * sizeof(duk_instr_t);
+ DUK_UNREF(ins_end);
#else
while (ins != ins_end) {
tmp32 = (duk_uint32_t) (*ins);
- DUK_RAW_WRITE_U32_BE(p, tmp32);
+ DUK_RAW_WRITEINC_U32_BE(p, tmp32);
ins++;
}
#endif
@@ -13639,14 +14732,13 @@ static duk_uint8_t *duk__dump_func(duk_hthread *thr, duk_hcompfunc *func, duk_bu
tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func);
while (tv != tv_end) {
/* constants are strings or numbers now */
- DUK_ASSERT(DUK_TVAL_IS_STRING(tv) ||
- DUK_TVAL_IS_NUMBER(tv));
+ DUK_ASSERT(DUK_TVAL_IS_STRING(tv) || DUK_TVAL_IS_NUMBER(tv));
if (DUK_TVAL_IS_STRING(tv)) {
h_str = DUK_TVAL_GET_STRING(tv);
DUK_ASSERT(h_str != NULL);
- DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
- p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 4U + DUK_HSTRING_GET_BYTELEN(h_str), p),
+ DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
+ p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 4U + DUK_HSTRING_GET_BYTELEN(h_str), p);
*p++ = DUK__SER_STRING;
p = duk__dump_hstring_raw(p, h_str);
} else {
@@ -13654,7 +14746,7 @@ static duk_uint8_t *duk__dump_func(duk_hthread *thr, duk_hcompfunc *func, duk_bu
p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 8U, p);
*p++ = DUK__SER_NUMBER;
d = DUK_TVAL_GET_NUMBER(tv);
- DUK_RAW_WRITE_DOUBLE_BE(p, d);
+ DUK_RAW_WRITEINC_DOUBLE_BE(p, d);
}
tv++;
}
@@ -13711,11 +14803,12 @@ static duk_uint8_t *duk__dump_func(duk_hthread *thr, duk_hcompfunc *func, duk_bu
* are validated (which is quite complex, especially for indirect opcodes).
*/
-#define DUK__ASSERT_LEFT(n) do { \
+#define DUK__ASSERT_LEFT(n) \
+ do { \
DUK_ASSERT((duk_size_t) (p_end - p) >= (duk_size_t) (n)); \
} while (0)
-static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t *p_end) {
+static const duk_uint8_t *duk__load_func(duk_hthread *thr, const duk_uint8_t *p, const duk_uint8_t *p_end) {
duk_hcompfunc *h_fun;
duk_hbuffer *h_data;
duk_size_t data_size;
@@ -13739,20 +14832,20 @@ static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t
DUK_ASSERT(thr != NULL);
- DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (void *) p, (void *) p_end));
+ DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (const void *) p, (const void *) p_end));
DUK__ASSERT_LEFT(3 * 4);
- count_instr = DUK_RAW_READ_U32_BE(p);
- count_const = DUK_RAW_READ_U32_BE(p);
- count_funcs = DUK_RAW_READ_U32_BE(p);
+ count_instr = DUK_RAW_READINC_U32_BE(p);
+ count_const = DUK_RAW_READINC_U32_BE(p);
+ count_funcs = DUK_RAW_READINC_U32_BE(p);
- data_size = sizeof(duk_tval) * count_const +
- sizeof(duk_hobject *) * count_funcs +
- sizeof(duk_instr_t) * count_instr;
+ data_size = sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs + sizeof(duk_instr_t) * count_instr;
DUK_DD(DUK_DDPRINT("instr=%ld, const=%ld, funcs=%ld, data_size=%ld",
- (long) count_instr, (long) count_const,
- (long) count_const, (long) data_size));
+ (long) count_instr,
+ (long) count_const,
+ (long) count_const,
+ (long) data_size));
/* Value stack is used to ensure reachability of constants and
* inner functions being loaded. Require enough space to handle
@@ -13772,18 +14865,18 @@ static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t
DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, h_fun) == NULL);
DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_fun) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
- h_fun->nregs = DUK_RAW_READ_U16_BE(p);
- h_fun->nargs = DUK_RAW_READ_U16_BE(p);
+ h_fun->nregs = DUK_RAW_READINC_U16_BE(p);
+ h_fun->nargs = DUK_RAW_READINC_U16_BE(p);
#if defined(DUK_USE_DEBUGGER_SUPPORT)
- h_fun->start_line = DUK_RAW_READ_U32_BE(p);
- h_fun->end_line = DUK_RAW_READ_U32_BE(p);
+ h_fun->start_line = DUK_RAW_READINC_U32_BE(p);
+ h_fun->end_line = DUK_RAW_READINC_U32_BE(p);
#else
- p += 8; /* skip line info */
+ p += 8; /* skip line info */
#endif
/* duk_hcompfunc flags; quite version specific */
- tmp32 = DUK_RAW_READ_U32_BE(p);
- DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32); /* masks flags to only change duk_hobject flags */
+ tmp32 = DUK_RAW_READINC_U32_BE(p);
+ DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32); /* masks flags to only change duk_hobject flags */
/* standard prototype (no need to set here, already set) */
DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_fun) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
@@ -13797,6 +14890,7 @@ static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t
DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&h_fun->obj));
DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&h_fun->obj));
DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(&h_fun->obj));
+ DUK_ASSERT(!DUK_HOBJECT_IS_PROXY(&h_fun->obj));
DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&h_fun->obj));
DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&h_fun->obj));
DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&h_fun->obj));
@@ -13810,14 +14904,12 @@ static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t
DUK__ASSERT_LEFT(count_instr * sizeof(duk_instr_t));
#if defined(DUK_USE_INTEGER_BE)
q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
- DUK_MEMCPY((void *) q,
- (const void *) p,
- sizeof(duk_instr_t) * count_instr);
+ duk_memcpy((void *) q, (const void *) p, sizeof(duk_instr_t) * count_instr);
p += sizeof(duk_instr_t) * count_instr;
#else
q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
for (n = count_instr; n > 0; n--) {
- *((duk_instr_t *) (void *) q) = DUK_RAW_READ_U32_BE(p);
+ *((duk_instr_t *) (void *) q) = DUK_RAW_READINC_U32_BE(p);
q += sizeof(duk_instr_t);
}
#endif
@@ -13825,7 +14917,7 @@ static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t
/* Load constants onto value stack but don't yet copy to buffer. */
for (n = count_const; n > 0; n--) {
DUK__ASSERT_LEFT(1);
- const_type = DUK_RAW_READ_U8(p);
+ const_type = DUK_RAW_READINC_U8(p);
switch (const_type) {
case DUK__SER_STRING: {
p = duk__load_string_raw(thr, p);
@@ -13838,7 +14930,7 @@ static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t
duk_tval tv_tmp;
duk_double_t val;
DUK__ASSERT_LEFT(8);
- val = DUK_RAW_READ_DOUBLE_BE(p);
+ val = DUK_RAW_READINC_DOUBLE_BE(p);
DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(&tv_tmp, val);
duk_push_tval(thr, &tv_tmp);
break;
@@ -13871,19 +14963,16 @@ static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t
DUK_HCOMPFUNC_SET_DATA(thr->heap, h_fun, h_data);
DUK_HBUFFER_INCREF(thr, h_data);
- tv1 = duk_get_tval(thr, idx_base + 2); /* may be NULL if no constants or inner funcs */
+ tv1 = duk_get_tval(thr, idx_base + 2); /* may be NULL if no constants or inner funcs */
DUK_ASSERT((count_const == 0 && count_funcs == 0) || tv1 != NULL);
q = fun_data;
- if (count_const > 0) {
- /* Explicit zero size check to avoid NULL 'tv1'. */
- DUK_MEMCPY((void *) q, (const void *) tv1, sizeof(duk_tval) * count_const);
- for (n = count_const; n > 0; n--) {
- DUK_TVAL_INCREF_FAST(thr, (duk_tval *) (void *) q); /* no side effects */
- q += sizeof(duk_tval);
- }
- tv1 += count_const;
+ duk_memcpy_unsafe((void *) q, (const void *) tv1, sizeof(duk_tval) * count_const);
+ for (n = count_const; n > 0; n--) {
+ DUK_TVAL_INCREF_FAST(thr, (duk_tval *) (void *) q); /* no side effects */
+ q += sizeof(duk_tval);
}
+ tv1 += count_const;
DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_fun, (duk_hobject **) (void *) q);
for (n = count_funcs; n > 0; n--) {
@@ -13908,12 +14997,12 @@ static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t
duk_set_top(thr, idx_base + 1);
/* Setup function properties. */
- tmp32 = DUK_RAW_READ_U32_BE(p);
+ tmp32 = DUK_RAW_READINC_U32_BE(p);
duk_push_u32(thr, tmp32);
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
#if defined(DUK_USE_FUNC_NAME_PROPERTY)
- p = duk__load_string_raw(thr, p); /* -> [ func funcname ] */
+ p = duk__load_string_raw(thr, p); /* -> [ func funcname ] */
func_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
DUK_ASSERT(func_env != NULL);
need_pop = 0;
@@ -13924,14 +15013,13 @@ static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t
*/
duk_hdecenv *new_env;
- new_env = duk_hdecenv_alloc(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
+ new_env =
+ duk_hdecenv_alloc(thr, DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
DUK_ASSERT(new_env != NULL);
- DUK_ASSERT(new_env->thread == NULL); /* Closed. */
+ DUK_ASSERT(new_env->thread == NULL); /* Closed. */
DUK_ASSERT(new_env->varmap == NULL);
DUK_ASSERT(new_env->regbase_byteoff == 0);
- DUK_ASSERT_HDECENV_VALID(new_env);
+ DUK_HDECENV_ASSERT_VALID(new_env);
DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, func_env);
DUK_HOBJECT_INCREF(thr, func_env);
@@ -13940,11 +15028,11 @@ static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t
duk_push_hobject(thr, (duk_hobject *) new_env);
- duk_dup_m2(thr); /* -> [ func funcname env funcname ] */
- duk_dup(thr, idx_base); /* -> [ func funcname env funcname func ] */
- duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE); /* -> [ func funcname env ] */
+ duk_dup_m2(thr); /* -> [ func funcname env funcname ] */
+ duk_dup(thr, idx_base); /* -> [ func funcname env funcname func ] */
+ duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE); /* -> [ func funcname env ] */
- need_pop = 1; /* Need to pop env, but -after- updating h_fun and increfs. */
+ need_pop = 1; /* Need to pop env, but -after- updating h_fun and increfs. */
}
DUK_ASSERT(func_env != NULL);
DUK_HCOMPFUNC_SET_LEXENV(thr->heap, h_fun, func_env);
@@ -13955,20 +15043,25 @@ static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t
duk_pop(thr);
}
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
-#endif /* DUK_USE_FUNC_NAME_PROPERTY */
+#endif /* DUK_USE_FUNC_NAME_PROPERTY */
#if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
p = duk__load_string_raw(thr, p);
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C);
-#endif /* DUK_USE_FUNC_FILENAME_PROPERTY */
+#endif /* DUK_USE_FUNC_FILENAME_PROPERTY */
if (DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_fun)) {
/* Restore empty external .prototype only for constructable
- * functions.
+ * functions. The prototype object should inherit from
+ * Object.prototype.
*/
duk_push_object(thr);
+ DUK_ASSERT(!duk_is_bare_object(thr, -1));
duk_dup_m2(thr);
- duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC); /* func.prototype.constructor = func */
+ duk_xdef_prop_stridx_short(thr,
+ -2,
+ DUK_STRIDX_CONSTRUCTOR,
+ DUK_PROPDESC_FLAGS_WC); /* func.prototype.constructor = func */
duk_compact_m1(thr);
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);
}
@@ -13976,9 +15069,9 @@ static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t
#if defined(DUK_USE_PC2LINE)
p = duk__load_buffer_raw(thr, p);
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_WC);
-#endif /* DUK_USE_PC2LINE */
+#endif /* DUK_USE_PC2LINE */
- duk_push_object(thr); /* _Varmap */
+ duk_push_bare_object(thr); /* _Varmap */
for (;;) {
/* XXX: awkward */
p = duk__load_string_raw(thr, p);
@@ -13986,7 +15079,7 @@ static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t
duk_pop(thr);
break;
}
- tmp32 = DUK_RAW_READ_U32_BE(p);
+ tmp32 = DUK_RAW_READINC_U32_BE(p);
duk_push_u32(thr, tmp32);
duk_put_prop(thr, -3);
}
@@ -13996,9 +15089,9 @@ static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t
/* _Formals may have been missing in the original function, which is
* handled using a marker length.
*/
- arr_limit = DUK_RAW_READ_U32_BE(p);
+ arr_limit = DUK_RAW_READINC_U32_BE(p);
if (arr_limit != DUK__NO_FORMALS) {
- duk_push_array(thr); /* _Formals */
+ duk_push_bare_array(thr); /* _Formals */
for (arr_idx = 0; arr_idx < arr_limit; arr_idx++) {
p = duk__load_string_raw(thr, p);
duk_put_prop_index(thr, -2, arr_idx);
@@ -14014,7 +15107,7 @@ static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t
DUK_ASSERT_TOP(thr, idx_base + 1);
return p;
- format_error:
+format_error:
return NULL;
}
@@ -14046,11 +15139,11 @@ DUK_EXTERNAL void duk_dump_function(duk_hthread *thr) {
DUK_DD(DUK_DDPRINT("serialized result: %!T", duk_get_tval(thr, -1)));
- duk_remove_m2(thr); /* [ ... func buf ] -> [ ... buf ] */
+ duk_remove_m2(thr); /* [ ... func buf ] -> [ ... buf ] */
}
DUK_EXTERNAL void duk_load_function(duk_hthread *thr) {
- duk_uint8_t *p_buf, *p, *p_end;
+ const duk_uint8_t *p_buf, *p, *p_end;
duk_size_t sz;
DUK_ASSERT_API_ENTRY(thr);
@@ -14079,26 +15172,29 @@ DUK_EXTERNAL void duk_load_function(duk_hthread *thr) {
goto format_error;
}
- duk_remove_m2(thr); /* [ ... buf func ] -> [ ... func ] */
+ duk_remove_m2(thr); /* [ ... buf func ] -> [ ... func ] */
return;
- format_error:
+format_error:
DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BYTECODE);
+ DUK_WO_NORETURN(return;);
}
-#else /* DUK_USE_BYTECODE_DUMP_SUPPORT */
+#else /* DUK_USE_BYTECODE_DUMP_SUPPORT */
DUK_EXTERNAL void duk_dump_function(duk_hthread *thr) {
DUK_ASSERT_API_ENTRY(thr);
DUK_ERROR_UNSUPPORTED(thr);
+ DUK_WO_NORETURN(return;);
}
DUK_EXTERNAL void duk_load_function(duk_hthread *thr) {
DUK_ASSERT_API_ENTRY(thr);
DUK_ERROR_UNSUPPORTED(thr);
+ DUK_WO_NORETURN(return;);
}
-#endif /* DUK_USE_BYTECODE_DUMP_SUPPORT */
+#endif /* DUK_USE_BYTECODE_DUMP_SUPPORT */
/* automatic undefs */
#undef DUK__ASSERT_LEFT
@@ -14160,9 +15256,9 @@ DUK_LOCAL duk_idx_t duk__call_get_idx_func(duk_hthread *thr, duk_idx_t nargs, du
DUK_ASSERT(other >= 0);
idx_func = duk_get_top(thr) - nargs - other;
- if (DUK_UNLIKELY((idx_func | nargs) < 0)) { /* idx_func < 0 || nargs < 0; OR sign bits */
+ if (DUK_UNLIKELY((idx_func | nargs) < 0)) { /* idx_func < 0 || nargs < 0; OR sign bits */
DUK_ERROR_TYPE_INVALID_ARGS(thr);
- /* unreachable */
+ DUK_WO_NORETURN(return 0;);
}
DUK_ASSERT(duk_is_valid_index(thr, idx_func));
return idx_func;
@@ -14190,34 +15286,34 @@ DUK_LOCAL duk_idx_t duk__call_get_idx_func_unvalidated(duk_hthread *thr, duk_idx
* May currently throw an error e.g. when getting the property.
*/
DUK_LOCAL void duk__call_prop_prep_stack(duk_hthread *thr, duk_idx_t normalized_obj_idx, duk_idx_t nargs) {
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
DUK_ASSERT(nargs >= 0);
DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_idx=%ld, nargs=%ld, stacktop=%ld",
- (long) normalized_obj_idx, (long) nargs, (long) duk_get_top(thr)));
+ (long) normalized_obj_idx,
+ (long) nargs,
+ (long) duk_get_top(thr)));
/* [... key arg1 ... argN] */
/* duplicate key */
- duk_dup(thr, -nargs - 1); /* Note: -nargs alone would fail for nargs == 0, this is OK */
+ duk_dup(thr, -nargs - 1); /* Note: -nargs alone would fail for nargs == 0, this is OK */
(void) duk_get_prop(thr, normalized_obj_idx);
DUK_DDD(DUK_DDDPRINT("func: %!T", (duk_tval *) duk_get_tval(thr, -1)));
#if defined(DUK_USE_VERBOSE_ERRORS)
if (DUK_UNLIKELY(!duk_is_callable(thr, -1))) {
- duk_tval *tv_targ;
duk_tval *tv_base;
duk_tval *tv_key;
- tv_targ = DUK_GET_TVAL_NEGIDX(thr, -1);
+ /* tv_targ is passed on stack top (at index -1). */
tv_base = DUK_GET_TVAL_POSIDX(thr, normalized_obj_idx);
tv_key = DUK_GET_TVAL_NEGIDX(thr, -nargs - 2);
- DUK_ASSERT(tv_targ >= thr->valstack_bottom && tv_targ < thr->valstack_top);
DUK_ASSERT(tv_base >= thr->valstack_bottom && tv_base < thr->valstack_top);
DUK_ASSERT(tv_key >= thr->valstack_bottom && tv_key < thr->valstack_top);
- duk_call_setup_propcall_error(thr, tv_targ, tv_base, tv_key);
+ duk_call_setup_propcall_error(thr, tv_base, tv_key);
}
#endif
@@ -14244,7 +15340,7 @@ DUK_EXTERNAL void duk_call(duk_hthread *thr, duk_idx_t nargs) {
duk_insert_undefined(thr, idx_func + 1);
- call_flags = 0; /* not protected, respect reclimit, not constructor */
+ call_flags = 0; /* not protected, respect reclimit, not constructor */
duk_handle_call_unprotected(thr, idx_func, call_flags);
}
@@ -14257,7 +15353,7 @@ DUK_EXTERNAL void duk_call_method(duk_hthread *thr, duk_idx_t nargs) {
idx_func = duk__call_get_idx_func(thr, nargs, 2);
DUK_ASSERT(duk_is_valid_index(thr, idx_func));
- call_flags = 0; /* not protected, respect reclimit, not constructor */
+ call_flags = 0; /* not protected, respect reclimit, not constructor */
duk_handle_call_unprotected(thr, idx_func, call_flags);
}
@@ -14271,9 +15367,10 @@ DUK_EXTERNAL void duk_call_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t n
DUK_ASSERT_API_ENTRY(thr);
- obj_idx = duk_require_normalize_index(thr, obj_idx); /* make absolute */
+ obj_idx = duk_require_normalize_index(thr, obj_idx); /* make absolute */
if (DUK_UNLIKELY(nargs < 0)) {
DUK_ERROR_TYPE_INVALID_ARGS(thr);
+ DUK_WO_NORETURN(return;);
}
duk__call_prop_prep_stack(thr, obj_idx, nargs);
@@ -14286,7 +15383,7 @@ DUK_LOCAL duk_ret_t duk__pcall_raw(duk_hthread *thr, void *udata) {
duk_idx_t idx_func;
duk_int_t ret;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
DUK_ASSERT(udata != NULL);
args = (duk__pcall_args *) udata;
@@ -14310,7 +15407,7 @@ DUK_EXTERNAL duk_int_t duk_pcall(duk_hthread *thr, duk_idx_t nargs) {
args.nargs = nargs;
if (DUK_UNLIKELY(nargs < 0)) {
DUK_ERROR_TYPE_INVALID_ARGS(thr);
- return DUK_EXEC_ERROR; /* unreachable */
+ DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
}
args.call_flags = 0;
@@ -14322,7 +15419,7 @@ DUK_LOCAL duk_ret_t duk__pcall_method_raw(duk_hthread *thr, void *udata) {
duk_idx_t idx_func;
duk_int_t ret;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
DUK_ASSERT(udata != NULL);
args = (duk__pcall_method_args *) udata;
@@ -14345,7 +15442,7 @@ DUK_INTERNAL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs,
args.nargs = nargs;
if (DUK_UNLIKELY(nargs < 0)) {
DUK_ERROR_TYPE_INVALID_ARGS(thr);
- return DUK_EXEC_ERROR; /* unreachable */
+ DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
}
args.call_flags = call_flags;
@@ -14363,12 +15460,12 @@ DUK_LOCAL duk_ret_t duk__pcall_prop_raw(duk_hthread *thr, void *udata) {
duk_idx_t obj_idx;
duk_int_t ret;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
DUK_ASSERT(udata != NULL);
args = (duk__pcall_prop_args *) udata;
- obj_idx = duk_require_normalize_index(thr, args->obj_idx); /* make absolute */
+ obj_idx = duk_require_normalize_index(thr, args->obj_idx); /* make absolute */
duk__call_prop_prep_stack(thr, obj_idx, args->nargs);
ret = duk_handle_call_unprotected_nargs(thr, args->nargs, args->call_flags);
@@ -14386,7 +15483,7 @@ DUK_EXTERNAL duk_int_t duk_pcall_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_i
args.nargs = nargs;
if (DUK_UNLIKELY(nargs < 0)) {
DUK_ERROR_TYPE_INVALID_ARGS(thr);
- return DUK_EXEC_ERROR; /* unreachable */
+ DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
}
args.call_flags = 0;
@@ -14406,30 +15503,30 @@ DUK_EXTERNAL duk_int_t duk_safe_call(duk_hthread *thr, duk_safe_call_function fu
*/
/* XXX: check for any reserve? */
- if (DUK_UNLIKELY((nargs | nrets) < 0 || /* nargs < 0 || nrets < 0; OR sign bits */
- thr->valstack_top < thr->valstack_bottom + nargs || /* nargs too large compared to top */
- thr->valstack_end + nargs < thr->valstack_top + nrets)) { /* nrets too large compared to reserve */
+ if (DUK_UNLIKELY((nargs | nrets) < 0 || /* nargs < 0 || nrets < 0; OR sign bits */
+ thr->valstack_top < thr->valstack_bottom + nargs || /* nargs too large compared to top */
+ thr->valstack_end + nargs < thr->valstack_top + nrets)) { /* nrets too large compared to reserve */
DUK_D(DUK_DPRINT("not enough stack reserve for safe call or invalid arguments: "
"nargs=%ld < 0 (?), nrets=%ld < 0 (?), top=%ld < bottom=%ld + nargs=%ld (?), "
"end=%ld + nargs=%ld < top=%ld + nrets=%ld (?)",
- (long) nargs,
- (long) nrets,
- (long) (thr->valstack_top - thr->valstack),
- (long) (thr->valstack_bottom - thr->valstack),
- (long) nargs,
- (long) (thr->valstack_end - thr->valstack),
- (long) nargs,
- (long) (thr->valstack_top - thr->valstack),
- (long) nrets));
+ (long) nargs,
+ (long) nrets,
+ (long) (thr->valstack_top - thr->valstack),
+ (long) (thr->valstack_bottom - thr->valstack),
+ (long) nargs,
+ (long) (thr->valstack_end - thr->valstack),
+ (long) nargs,
+ (long) (thr->valstack_top - thr->valstack),
+ (long) nrets));
DUK_ERROR_TYPE_INVALID_ARGS(thr);
- return DUK_EXEC_ERROR; /* unreachable */
+ DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
}
- rc = duk_handle_safe_call(thr, /* thread */
- func, /* func */
- udata, /* udata */
- nargs, /* num_stack_args */
- nrets); /* num_stack_res */
+ rc = duk_handle_safe_call(thr, /* thread */
+ func, /* func */
+ udata, /* udata */
+ nargs, /* num_stack_args */
+ nrets); /* num_stack_res */
return rc;
}
@@ -14442,7 +15539,7 @@ DUK_EXTERNAL void duk_new(duk_hthread *thr, duk_idx_t nargs) {
idx_func = duk__call_get_idx_func(thr, nargs, 1);
DUK_ASSERT(duk_is_valid_index(thr, idx_func));
- duk_push_object(thr); /* default instance; internal proto updated by call handling */
+ duk_push_object(thr); /* default instance; internal proto updated by call handling */
duk_insert(thr, idx_func + 1);
duk_handle_call_unprotected(thr, idx_func, DUK_CALL_FLAG_CONSTRUCT);
@@ -14470,7 +15567,7 @@ DUK_EXTERNAL duk_int_t duk_pnew(duk_hthread *thr, duk_idx_t nargs) {
if (DUK_UNLIKELY(nargs < 0)) {
DUK_ERROR_TYPE_INVALID_ARGS(thr);
- return DUK_EXEC_ERROR; /* unreachable */
+ DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
}
rc = duk_safe_call(thr, duk__pnew_helper, (void *) &nargs /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
@@ -14489,14 +15586,12 @@ DUK_EXTERNAL duk_bool_t duk_is_constructor_call(duk_hthread *thr) {
return 0;
}
-/* XXX: Make this obsolete by adding a function flag for rejecting a
- * non-constructor call automatically?
- */
-DUK_INTERNAL void duk_require_constructor_call(duk_hthread *thr) {
+DUK_EXTERNAL void duk_require_constructor_call(duk_hthread *thr) {
DUK_ASSERT_API_ENTRY(thr);
if (!duk_is_constructor_call(thr)) {
DUK_ERROR_TYPE(thr, DUK_STR_CONSTRUCT_ONLY);
+ DUK_WO_NORETURN(return;);
}
}
@@ -14507,7 +15602,7 @@ DUK_EXTERNAL duk_bool_t duk_is_strict_call(duk_hthread *thr) {
* because all Duktape/C functions are considered strict,
* and strict is also the default when nothing is running.
* However, Duktape may call this function internally when
- * the current activation is an Ecmascript function, so
+ * the current activation is an ECMAScript function, so
* this cannot be replaced by a 'return 1' without fixing
* the internal call sites.
*/
@@ -14572,9 +15667,9 @@ DUK_EXTERNAL duk_int_t duk_get_magic(duk_hthread *thr, duk_idx_t idx) {
}
/* fall through */
- type_error:
+type_error:
DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
- return 0;
+ DUK_WO_NORETURN(return 0;);
}
DUK_EXTERNAL void duk_set_magic(duk_hthread *thr, duk_idx_t idx, duk_int_t magic) {
@@ -14597,7 +15692,7 @@ DUK_EXTERNAL void duk_set_magic(duk_hthread *thr, duk_idx_t idx, duk_int_t magic
DUK_INTERNAL void duk_resolve_nonbound_function(duk_hthread *thr) {
duk_tval *tv;
- DUK_ASSERT_HTHREAD_VALID(thr);
+ DUK_HTHREAD_ASSERT_VALID(thr);
tv = DUK_GET_TVAL_NEGIDX(thr, -1);
if (DUK_TVAL_IS_OBJECT(tv)) {
@@ -14606,7 +15701,7 @@ DUK_INTERNAL void duk_resolve_nonbound_function(duk_hthread *thr) {
h = DUK_TVAL_GET_OBJECT(tv);
DUK_ASSERT(h != NULL);
if (DUK_HOBJECT_HAS_BOUNDFUNC(h)) {
- duk_push_tval(thr, &((duk_hboundfunc *) h)->target);
+ duk_push_tval(thr, &((duk_hboundfunc *) (void *) h)->target);
duk_replace(thr, -2);
#if 0
DUK_TVAL_SET_TVAL(tv, &((duk_hboundfunc *) h)->target);
@@ -14636,372 +15731,620 @@ DUK_INTERNAL void duk_resolve_nonbound_function(duk_hthread *thr) {
/* #include duk_internal.h -> already included */
+/*
+ * Misc helpers
+ */
+
/* Shared handling for encode/decode argument. Fast path handling for
* buffer and string values because they're the most common. In particular,
- * avoid creating a temporary string or buffer when possible.
+ * avoid creating a temporary string or buffer when possible. Return value
+ * is guaranteed to be non-NULL, even for zero length input.
*/
DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
- void *ptr;
+ const void *def_ptr = (const void *) out_len; /* Any non-NULL pointer will do. */
+ const void *ptr;
duk_bool_t isbuffer;
- DUK_ASSERT(duk_is_valid_index(thr, idx)); /* checked by caller */
+ DUK_ASSERT(out_len != NULL);
+ DUK_ASSERT(def_ptr != NULL);
+ DUK_ASSERT(duk_is_valid_index(thr, idx)); /* checked by caller */
- /* XXX: with def_ptr set to a stack related pointer, isbuffer could
- * be removed from the helper?
- */
- ptr = duk_get_buffer_data_raw(thr, idx, out_len, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, &isbuffer);
+ ptr = (const void *)
+ duk_get_buffer_data_raw(thr, idx, out_len, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, &isbuffer);
if (isbuffer) {
- DUK_ASSERT(*out_len == 0 || ptr != NULL);
- return (const duk_uint8_t *) ptr;
+ DUK_ASSERT(ptr != NULL || *out_len == 0U);
+ if (DUK_UNLIKELY(ptr == NULL)) {
+ ptr = def_ptr;
+ }
+ DUK_ASSERT(ptr != NULL);
+ } else {
+ /* For strings a non-NULL pointer is always guaranteed because
+ * at least a NUL will be present.
+ */
+ ptr = (const void *) duk_to_lstring(thr, idx, out_len);
+ DUK_ASSERT(ptr != NULL);
}
- return (const duk_uint8_t *) duk_to_lstring(thr, idx, out_len);
+ DUK_ASSERT(ptr != NULL);
+ return (const duk_uint8_t *) ptr;
}
+/*
+ * Base64
+ */
+
+#if defined(DUK_USE_BASE64_SUPPORT)
+/* Bytes emitted for number of padding characters in range [0,4]. */
+DUK_LOCAL const duk_int8_t duk__base64_decode_nequal_step[5] = {
+ 3, /* #### -> 24 bits, emit 3 bytes */
+ 2, /* ###= -> 18 bits, emit 2 bytes */
+ 1, /* ##== -> 12 bits, emit 1 byte */
+ -1, /* #=== -> 6 bits, error */
+ 0, /* ==== -> 0 bits, emit 0 bytes */
+};
+
#if defined(DUK_USE_BASE64_FASTPATH)
-DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
+DUK_LOCAL const duk_uint8_t duk__base64_enctab_fast[64] = {
+ 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, 0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, 0x50U, /* A...P */
+ 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U, 0x58U, 0x59U, 0x5aU, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, /* Q...f */
+ 0x67U, 0x68U, 0x69U, 0x6aU, 0x6bU, 0x6cU, 0x6dU, 0x6eU, 0x6fU, 0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, /* g...v */
+ 0x77U, 0x78U, 0x79U, 0x7aU, 0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U, 0x38U, 0x39U, 0x2bU, 0x2fU /* w.../ */
+};
+#endif /* DUK_USE_BASE64_FASTPATH */
+
+#if defined(DUK_USE_BASE64_FASTPATH)
+/* Decode table for one byte of input:
+ * -1 = allowed whitespace
+ * -2 = padding
+ * -3 = error
+ * 0...63 decoded bytes
+ */
+DUK_LOCAL const duk_int8_t duk__base64_dectab_fast[256] = {
+ -3, -3, -3, -3, -3, -3, -3, -3, -3, -1, -1, -3, -3, -1, -3, -3, /* 0x00...0x0f */
+ -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0x10...0x1f */
+ -1, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, 62, -3, -3, -3, 63, /* 0x20...0x2f */
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -3, -3, -3, -2, -3, -3, /* 0x30...0x3f */
+ -3, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40...0x4f */
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -3, -3, -3, -3, -3, /* 0x50...0x5f */
+ -3, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60...0x6f */
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -3, -3, -3, -3, -3, /* 0x70...0x7f */
+ -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0x80...0x8f */
+ -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0x90...0x9f */
+ -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0xa0...0xaf */
+ -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0xb0...0xbf */
+ -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0xc0...0xcf */
+ -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0xd0...0xdf */
+ -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, /* 0xe0...0xef */
+ -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3 /* 0xf0...0xff */
+};
+#endif /* DUK_USE_BASE64_FASTPATH */
+
+#if defined(DUK_USE_BASE64_FASTPATH)
+DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_3(const duk_uint8_t *src, duk_uint8_t *dst) {
duk_uint_t t;
- duk_size_t n_full, n_full3, n_final;
- const duk_uint8_t *src_end_fast;
-
- n_full = srclen / 3; /* full 3-byte -> 4-char conversions */
- n_full3 = n_full * 3;
- n_final = srclen - n_full3;
- DUK_ASSERT_DISABLE(n_final >= 0);
- DUK_ASSERT(n_final <= 2);
-
- src_end_fast = src + n_full3;
- while (DUK_UNLIKELY(src != src_end_fast)) {
- t = (duk_uint_t) (*src++);
- t = (t << 8) + (duk_uint_t) (*src++);
- t = (t << 8) + (duk_uint_t) (*src++);
-
- *dst++ = duk_base64_enctab[t >> 18];
- *dst++ = duk_base64_enctab[(t >> 12) & 0x3f];
- *dst++ = duk_base64_enctab[(t >> 6) & 0x3f];
- *dst++ = duk_base64_enctab[t & 0x3f];
-
-#if 0 /* Tested: not faster on x64 */
- /* aaaaaabb bbbbcccc ccdddddd */
- dst[0] = duk_base64_enctab[(src[0] >> 2) & 0x3f];
- dst[1] = duk_base64_enctab[((src[0] << 4) & 0x30) | ((src[1] >> 4) & 0x0f)];
- dst[2] = duk_base64_enctab[((src[1] << 2) & 0x3f) | ((src[2] >> 6) & 0x03)];
- dst[3] = duk_base64_enctab[src[2] & 0x3f];
- src += 3; dst += 4;
-#endif
- }
-
- switch (n_final) {
- /* case 0: nop */
- case 1: {
- /* XX== */
- t = (duk_uint_t) (*src++);
- *dst++ = duk_base64_enctab[t >> 2]; /* XXXXXX-- */
- *dst++ = duk_base64_enctab[(t << 4) & 0x3f]; /* ------XX */
- *dst++ = DUK_ASC_EQUALS;
- *dst++ = DUK_ASC_EQUALS;
- break;
- }
- case 2: {
- /* XXX= */
- t = (duk_uint_t) (*src++);
- t = (t << 8) + (duk_uint_t) (*src++);
- *dst++ = duk_base64_enctab[t >> 10]; /* XXXXXX-- -------- */
- *dst++ = duk_base64_enctab[(t >> 4) & 0x3f]; /* ------XX XXXX---- */
- *dst++ = duk_base64_enctab[(t << 2) & 0x3f]; /* -------- ----XXXX */
- *dst++ = DUK_ASC_EQUALS;
- break;
- }
+
+ t = (duk_uint_t) src[0];
+ t = (t << 8) + (duk_uint_t) src[1];
+ t = (t << 8) + (duk_uint_t) src[2];
+
+ dst[0] = duk__base64_enctab_fast[t >> 18];
+ dst[1] = duk__base64_enctab_fast[(t >> 12) & 0x3fU];
+ dst[2] = duk__base64_enctab_fast[(t >> 6) & 0x3fU];
+ dst[3] = duk__base64_enctab_fast[t & 0x3fU];
+
+#if 0
+ /* Tested: not faster on x64, most likely due to aliasing between
+ * output and input index computation.
+ */
+ /* aaaaaabb bbbbcccc ccdddddd */
+ dst[0] = duk__base64_enctab_fast[(src[0] >> 2) & 0x3fU];
+ dst[1] = duk__base64_enctab_fast[((src[0] << 4) & 0x30U) | ((src[1] >> 4) & 0x0fU)];
+ dst[2] = duk__base64_enctab_fast[((src[1] << 2) & 0x3fU) | ((src[2] >> 6) & 0x03U)];
+ dst[3] = duk__base64_enctab_fast[src[2] & 0x3fU];
+#endif
+}
+
+DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_2(const duk_uint8_t *src, duk_uint8_t *dst) {
+ duk_uint_t t;
+
+ t = (duk_uint_t) src[0];
+ t = (t << 8) + (duk_uint_t) src[1];
+ dst[0] = duk__base64_enctab_fast[t >> 10]; /* XXXXXX-- -------- */
+ dst[1] = duk__base64_enctab_fast[(t >> 4) & 0x3fU]; /* ------XX XXXX---- */
+ dst[2] = duk__base64_enctab_fast[(t << 2) & 0x3fU]; /* -------- ----XXXX */
+ dst[3] = DUK_ASC_EQUALS;
+}
+
+DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_1(const duk_uint8_t *src, duk_uint8_t *dst) {
+ duk_uint_t t;
+
+ t = (duk_uint_t) src[0];
+ dst[0] = duk__base64_enctab_fast[t >> 2]; /* XXXXXX-- */
+ dst[1] = duk__base64_enctab_fast[(t << 4) & 0x3fU]; /* ------XX */
+ dst[2] = DUK_ASC_EQUALS;
+ dst[3] = DUK_ASC_EQUALS;
+}
+
+DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
+ duk_size_t n;
+ const duk_uint8_t *p;
+ duk_uint8_t *q;
+
+ n = srclen;
+ p = src;
+ q = dst;
+
+ if (n >= 16U) {
+ /* Fast path, unrolled by 4, allows interleaving. Process
+ * 12-byte input chunks which encode to 16-char output chunks.
+ * Only enter when at least one block is emitted (avoids div+mul
+ * for short inputs too).
+ */
+ const duk_uint8_t *p_end_fast;
+
+ p_end_fast = p + ((n / 12U) * 12U);
+ DUK_ASSERT(p_end_fast >= p + 12);
+ do {
+ duk__base64_encode_fast_3(p, q);
+ duk__base64_encode_fast_3(p + 3, q + 4);
+ duk__base64_encode_fast_3(p + 6, q + 8);
+ duk__base64_encode_fast_3(p + 9, q + 12);
+ p += 12;
+ q += 16;
+ } while (DUK_LIKELY(p != p_end_fast));
+
+ DUK_ASSERT(src + srclen >= p);
+ n = (duk_size_t) (src + srclen - p);
+ DUK_ASSERT(n < 12U);
+ }
+
+ /* Remainder. */
+ while (n >= 3U) {
+ duk__base64_encode_fast_3(p, q);
+ p += 3;
+ q += 4;
+ n -= 3U;
+ }
+ DUK_ASSERT(n == 0U || n == 1U || n == 2U);
+ if (n == 1U) {
+ duk__base64_encode_fast_1(p, q);
+#if 0 /* Unnecessary. */
+ p += 1;
+ q += 4;
+ n -= 1U;
+#endif
+ } else if (n == 2U) {
+ duk__base64_encode_fast_2(p, q);
+#if 0 /* Unnecessary. */
+ p += 2;
+ q += 4;
+ n -= 2U;
+#endif
+ } else {
+ DUK_ASSERT(n == 0U); /* nothing to do */
+ ;
}
}
-#else /* DUK_USE_BASE64_FASTPATH */
+#else /* DUK_USE_BASE64_FASTPATH */
DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
- duk_small_uint_t i, snip;
- duk_uint_t t;
- duk_uint_fast8_t x, y;
- const duk_uint8_t *src_end;
+ duk_small_uint_t i, npad;
+ duk_uint_t t, x, y;
+ const duk_uint8_t *p;
+ const duk_uint8_t *p_end;
+ duk_uint8_t *q;
- src_end = src + srclen;
+ p = src;
+ p_end = src + srclen;
+ q = dst;
+ npad = 0U;
- while (src < src_end) {
- /* read 3 bytes into 't', padded by zero */
- snip = 4;
+ while (p < p_end) {
+ /* Read 3 bytes into 't', padded by zero. */
t = 0;
for (i = 0; i < 3; i++) {
t = t << 8;
- if (src >= src_end) {
- snip--;
+ if (p < p_end) {
+ t += (duk_uint_t) (*p++);
} else {
- t += (duk_uint_t) (*src++);
+ /* This only happens on the last loop and we're
+ * guaranteed to exit on the next loop.
+ */
+ npad++;
}
}
+ DUK_ASSERT(npad <= 2U);
- /*
- * Missing bytes snip base64 example
- * 0 4 XXXX
- * 1 3 XXX=
- * 2 2 XX==
+ /* Emit 4 encoded characters. If npad > 0, some of the
+ * chars will be incorrect (zero bits) but we fix up the
+ * padding after the loop. A straightforward 64-byte
+ * lookup would be faster and cleaner, but this is shorter.
*/
-
- DUK_ASSERT(snip >= 2 && snip <= 4);
-
for (i = 0; i < 4; i++) {
- x = (duk_uint_fast8_t) ((t >> 18) & 0x3f);
+ x = ((t >> 18) & 0x3fU);
t = t << 6;
- /* A straightforward 64-byte lookup would be faster
- * and cleaner, but this is shorter.
- */
- if (i >= snip) {
- y = '=';
- } else if (x <= 25) {
- y = x + 'A';
- } else if (x <= 51) {
- y = x - 26 + 'a';
- } else if (x <= 61) {
- y = x - 52 + '0';
- } else if (x == 62) {
- y = '+';
+ if (x <= 51U) {
+ if (x <= 25) {
+ y = x + DUK_ASC_UC_A;
+ } else {
+ y = x - 26 + DUK_ASC_LC_A;
+ }
} else {
- y = '/';
+ if (x <= 61U) {
+ y = x - 52 + DUK_ASC_0;
+ } else if (x == 62) {
+ y = DUK_ASC_PLUS;
+ } else {
+ DUK_ASSERT(x == 63);
+ y = DUK_ASC_SLASH;
+ }
}
- *dst++ = (duk_uint8_t) y;
+ *q++ = (duk_uint8_t) y;
}
}
+
+ /* Handle padding by rewriting 0-2 bogus characters at the end.
+ *
+ * Missing bytes npad base64 example
+ * 0 0 ####
+ * 1 1 ###=
+ * 2 2 ##==
+ */
+ DUK_ASSERT(npad <= 2U);
+ while (npad > 0U) {
+ *(q - npad) = DUK_ASC_EQUALS;
+ npad--;
+ }
}
-#endif /* DUK_USE_BASE64_FASTPATH */
+#endif /* DUK_USE_BASE64_FASTPATH */
#if defined(DUK_USE_BASE64_FASTPATH)
-DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst, duk_uint8_t **out_dst_final) {
+DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src,
+ duk_size_t srclen,
+ duk_uint8_t *dst,
+ duk_uint8_t **out_dst_final) {
duk_int_t x;
- duk_int_t t;
+ duk_uint_t t;
duk_small_uint_t n_equal;
- duk_small_uint_t n_chars;
- const duk_uint8_t *src_end;
- const duk_uint8_t *src_end_safe;
+ duk_int8_t step;
+ const duk_uint8_t *p;
+ const duk_uint8_t *p_end;
+ const duk_uint8_t *p_end_safe;
+ duk_uint8_t *q;
- src_end = src + srclen;
- src_end_safe = src_end - 4; /* if 'src < src_end_safe', safe to read 4 bytes */
+ DUK_ASSERT(src != NULL); /* Required by pointer arithmetic below, which fails for NULL. */
+
+ p = src;
+ p_end = src + srclen;
+ p_end_safe = p_end - 8; /* If 'src <= src_end_safe', safe to read 8 bytes. */
+ q = dst;
- /* Innermost fast path processes 4 valid base-64 characters at a time
- * but bails out on whitespace, padding chars ('=') and invalid chars.
- * Once the slow path segment has been processed, we return to the
- * inner fast path again. This handles e.g. base64 with newlines
- * reasonably well because the majority of a line is in the fast path.
+ /* Alternate between a fast path which processes clean groups with no
+ * padding or whitespace, and a slow path which processes one arbitrary
+ * group and then re-enters the fast path. This handles e.g. base64
+ * with newlines reasonably well because the majority of a line is in
+ * the fast path.
*/
for (;;) {
- /* Fast path, handle units with just actual encoding characters. */
-
- while (src <= src_end_safe) {
- /* The lookup byte is intentionally sign extended to (at least)
- * 32 bits and then ORed. This ensures that is at least 1 byte
- * is negative, the highest bit of 't' will be set at the end
- * and we don't need to check every byte.
+ /* Fast path, on each loop handle two 4-char input groups.
+ * If both are clean, emit 6 bytes and continue. If first
+ * is clean, emit 3 bytes and drop out; otherwise emit
+ * nothing and drop out. This approach could be extended to
+ * more groups per loop, but for inputs with e.g. periodic
+ * newlines (which are common) it might not be an improvement.
+ */
+ while (DUK_LIKELY(p <= p_end_safe)) {
+ duk_int_t t1, t2;
+
+ /* The lookup byte is intentionally sign extended to
+ * (at least) 32 bits and then ORed. This ensures
+ * that is at least 1 byte is negative, the highest
+ * bit of the accumulator will be set at the end and
+ * we don't need to check every byte.
+ *
+ * Read all input bytes first before writing output
+ * bytes to minimize aliasing.
*/
- DUK_DDD(DUK_DDDPRINT("fast loop: src=%p, src_end_safe=%p, src_end=%p",
- (const void *) src, (const void *) src_end_safe, (const void *) src_end));
-
- t = (duk_int_t) duk_base64_dectab[*src++];
- t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
- t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
- t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
-
- if (DUK_UNLIKELY(t < 0)) {
- DUK_DDD(DUK_DDDPRINT("fast loop unit was not clean, process one slow path unit"));
- src -= 4;
+ DUK_DDD(DUK_DDDPRINT("fast loop: p=%p, p_end_safe=%p, p_end=%p",
+ (const void *) p,
+ (const void *) p_end_safe,
+ (const void *) p_end));
+
+ t1 = (duk_int_t) duk__base64_dectab_fast[p[0]];
+ t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[1]];
+ t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[2]];
+ t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[3]];
+
+ t2 = (duk_int_t) duk__base64_dectab_fast[p[4]];
+ t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[5]];
+ t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[6]];
+ t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[7]];
+
+ q[0] = (duk_uint8_t) (((duk_uint_t) t1 >> 16) & 0xffU);
+ q[1] = (duk_uint8_t) (((duk_uint_t) t1 >> 8) & 0xffU);
+ q[2] = (duk_uint8_t) ((duk_uint_t) t1 & 0xffU);
+
+ q[3] = (duk_uint8_t) (((duk_uint_t) t2 >> 16) & 0xffU);
+ q[4] = (duk_uint8_t) (((duk_uint_t) t2 >> 8) & 0xffU);
+ q[5] = (duk_uint8_t) ((duk_uint_t) t2 & 0xffU);
+
+ /* Optimistic check using one branch. */
+ if (DUK_LIKELY((t1 | t2) >= 0)) {
+ p += 8;
+ q += 6;
+ } else if (t1 >= 0) {
+ DUK_DDD(
+ DUK_DDDPRINT("fast loop first group was clean, second was not, process one slow path group"));
+ DUK_ASSERT(t2 < 0);
+ p += 4;
+ q += 3;
+ break;
+ } else {
+ DUK_DDD(DUK_DDDPRINT(
+ "fast loop first group was not clean, second does not matter, process one slow path group"));
+ DUK_ASSERT(t1 < 0);
break;
}
+ } /* fast path */
- DUK_ASSERT(t <= 0xffffffL);
- DUK_ASSERT((t >> 24) == 0);
- *dst++ = (duk_uint8_t) (t >> 16);
- *dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
- *dst++ = (duk_uint8_t) (t & 0xff);
- }
-
- /* Handle one slow path unit (or finish if we're done). */
-
- n_equal = 0;
- n_chars = 0;
- t = 0;
+ /* Slow path step 1: try to scan a 4-character encoded group,
+ * end-of-input, or start-of-padding. We exit with:
+ * 1. n_chars == 4: full group, no padding, no end-of-input.
+ * 2. n_chars < 4: partial group (may also be 0), encountered
+ * padding or end of input.
+ *
+ * The accumulator is initialized to 1; this allows us to detect
+ * a full group by comparing >= 0x1000000 without an extra
+ * counter variable.
+ */
+ t = 1UL;
for (;;) {
- DUK_DDD(DUK_DDDPRINT("slow loop: src=%p, src_end=%p, n_chars=%ld, n_equal=%ld, t=%ld",
- (const void *) src, (const void *) src_end, (long) n_chars, (long) n_equal, (long) t));
-
- if (DUK_UNLIKELY(src >= src_end)) {
- goto done; /* two level break */
- }
-
- x = duk_base64_dectab[*src++];
- if (DUK_UNLIKELY(x < 0)) {
- if (x == -2) {
- continue; /* allowed ascii whitespace */
- } else if (x == -3) {
- n_equal++;
- t <<= 6;
+ DUK_DDD(DUK_DDDPRINT("slow loop: p=%p, p_end=%p, t=%lu",
+ (const void *) p,
+ (const void *) p_end,
+ (unsigned long) t));
+
+ if (DUK_LIKELY(p < p_end)) {
+ x = duk__base64_dectab_fast[*p++];
+ if (DUK_LIKELY(x >= 0)) {
+ DUK_ASSERT(x >= 0 && x <= 63);
+ t = (t << 6) + (duk_uint_t) x;
+ if (t >= 0x1000000UL) {
+ break;
+ }
+ } else if (x == -1) {
+ continue; /* allowed ascii whitespace */
+ } else if (x == -2) {
+ p--;
+ break; /* start of padding */
} else {
- DUK_ASSERT(x == -1);
+ DUK_ASSERT(x == -3);
goto decode_error;
}
} else {
- DUK_ASSERT(x >= 0 && x <= 63);
- if (n_equal > 0) {
- /* Don't allow actual chars after equal sign. */
- goto decode_error;
- }
- t = (t << 6) + x;
+ break; /* end of input */
}
+ } /* slow path step 1 */
- if (DUK_UNLIKELY(n_chars == 3)) {
- /* Emit 3 bytes and backtrack if there was padding. There's
- * always space for the whole 3 bytes so no check needed.
- */
- DUK_ASSERT(t <= 0xffffffL);
- DUK_ASSERT((t >> 24) == 0);
- *dst++ = (duk_uint8_t) (t >> 16);
- *dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
- *dst++ = (duk_uint8_t) (t & 0xff);
-
- if (DUK_UNLIKELY(n_equal > 0)) {
- DUK_ASSERT(n_equal <= 4);
-
- /* There may be whitespace between the equal signs. */
- if (n_equal == 1) {
- /* XXX= */
- dst -= 1;
- } else if (n_equal == 2) {
- /* XX== */
- dst -= 2;
- } else {
- goto decode_error; /* invalid padding */
- }
+ /* Complete the padding by simulating pad characters,
+ * regardless of actual input padding chars.
+ */
+ n_equal = 0;
+ while (t < 0x1000000UL) {
+ t = (t << 6) + 0U;
+ n_equal++;
+ }
- /* Continue parsing after padding, allows concatenated,
- * padded base64.
- */
- }
- break; /* back to fast loop */
+ /* Slow path step 2: deal with full/partial group, padding,
+ * etc. Note that for num chars in [0,3] we intentionally emit
+ * 3 bytes but don't step forward that much, buffer space is
+ * guaranteed in setup.
+ *
+ * num chars:
+ * 0 #### no output (= step 0)
+ * 1 #=== reject, 6 bits of data
+ * 2 ##== 12 bits of data, output 1 byte (= step 1)
+ * 3 ###= 18 bits of data, output 2 bytes (= step 2)
+ * 4 #### 24 bits of data, output 3 bytes (= step 3)
+ */
+ q[0] = (duk_uint8_t) ((t >> 16) & 0xffU);
+ q[1] = (duk_uint8_t) ((t >> 8) & 0xffU);
+ q[2] = (duk_uint8_t) (t & 0xffU);
+
+ DUK_ASSERT(n_equal <= 4);
+ step = duk__base64_decode_nequal_step[n_equal];
+ if (DUK_UNLIKELY(step < 0)) {
+ goto decode_error;
+ }
+ q += step;
+
+ /* Slow path step 3: read and ignore padding and whitespace
+ * until (a) next non-padding and non-whitespace character
+ * after which we resume the fast path, or (b) end of input.
+ * This allows us to accept missing, partial, full, and extra
+ * padding cases uniformly. We also support concatenated
+ * base-64 documents because we resume scanning afterwards.
+ *
+ * Note that to support concatenated documents well, the '='
+ * padding found inside the input must also allow for 'extra'
+ * padding. For example, 'Zm===' decodes to 'f' and has one
+ * extra padding char. So, 'Zm===Zm' should decode 'ff', even
+ * though the standard break-up would be 'Zm==' + '=Zm' which
+ * doesn't make sense.
+ *
+ * We also accept prepended padding like '==Zm9', because it
+ * is equivalent to an empty document with extra padding ('==')
+ * followed by a valid document.
+ */
+
+ for (;;) {
+ if (DUK_UNLIKELY(p >= p_end)) {
+ goto done;
+ }
+ x = duk__base64_dectab_fast[*p++];
+ if (x == -1 || x == -2) {
+ ; /* padding or whitespace, keep eating */
} else {
- n_chars++;
+ p--;
+ break; /* backtrack and go back to fast path, even for -1 */
}
- }
- }
- done:
- DUK_DDD(DUK_DDDPRINT("done; src=%p, src_end=%p, n_chars=%ld",
- (const void *) src, (const void *) src_end, (long) n_chars));
+ } /* slow path step 3 */
+ } /* outer fast+slow path loop */
- DUK_ASSERT(src == src_end);
+done:
+ DUK_DDD(DUK_DDDPRINT("done; p=%p, p_end=%p", (const void *) p, (const void *) p_end));
- if (n_chars != 0) {
- /* Here we'd have the option of decoding unpadded base64
- * (e.g. "xxxxyy" instead of "xxxxyy==". Currently not
- * accepted.
- */
- goto decode_error;
- }
+ DUK_ASSERT(p == p_end);
- *out_dst_final = dst;
+ *out_dst_final = q;
return 1;
- decode_error:
+decode_error:
return 0;
}
-#else /* DUK_USE_BASE64_FASTPATH */
-DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst, duk_uint8_t **out_dst_final) {
- duk_uint_t t;
- duk_uint_fast8_t x, y;
- duk_small_uint_t group_idx;
- duk_small_uint_t n_equal;
- const duk_uint8_t *src_end;
+#else /* DUK_USE_BASE64_FASTPATH */
+DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src,
+ duk_size_t srclen,
+ duk_uint8_t *dst,
+ duk_uint8_t **out_dst_final) {
+ duk_uint_t t, x;
+ duk_int_t y;
+ duk_int8_t step;
+ const duk_uint8_t *p;
+ const duk_uint8_t *p_end;
+ duk_uint8_t *q;
+ /* 0x09, 0x0a, or 0x0d */
+ duk_uint32_t mask_white = (1U << 9) | (1U << 10) | (1U << 13);
- src_end = src + srclen;
- t = 0;
- group_idx = 0;
- n_equal = 0;
-
- while (src < src_end) {
- x = *src++;
-
- if (x >= 'A' && x <= 'Z') {
- y = x - 'A' + 0;
- } else if (x >= 'a' && x <= 'z') {
- y = x - 'a' + 26;
- } else if (x >= '0' && x <= '9') {
- y = x - '0' + 52;
- } else if (x == '+') {
- y = 62;
- } else if (x == '/') {
- y = 63;
- } else if (x == '=') {
- /* We don't check the zero padding bytes here right now
- * (that they're actually zero). This seems to be common
- * behavior for base-64 decoders.
+ /* 't' tracks progress of the decoded group:
+ *
+ * t == 1 no valid chars yet
+ * t >= 0x40 1x6 = 6 bits shifted in
+ * t >= 0x1000 2x6 = 12 bits shifted in
+ * t >= 0x40000 3x6 = 18 bits shifted in
+ * t >= 0x1000000 4x6 = 24 bits shifted in
+ *
+ * By initializing t=1 there's no need for a separate counter for
+ * the number of characters found so far.
+ */
+ p = src;
+ p_end = src + srclen;
+ q = dst;
+ t = 1UL;
+
+ for (;;) {
+ duk_small_uint_t n_equal;
+
+ DUK_ASSERT(t >= 1U);
+ if (p >= p_end) {
+ /* End of input: if input exists, treat like
+ * start of padding, finish the block, then
+ * re-enter here to see we're done.
*/
+ if (t == 1U) {
+ break;
+ } else {
+ goto simulate_padding;
+ }
+ }
- n_equal++;
- t <<= 6; /* shift in zeroes */
- goto skip_add;
- } else if (x == 0x09 || x == 0x0a || x == 0x0d || x == 0x20) {
- /* allow basic ASCII whitespace */
- continue;
+ x = *p++;
+
+ if (x >= 0x41U) {
+ /* Valid: a-z and A-Z. */
+ DUK_ASSERT(x >= 0x41U && x <= 0xffU);
+ if (x >= 0x61U && x <= 0x7aU) {
+ y = (duk_int_t) x - 0x61 + 26;
+ } else if (x <= 0x5aU) {
+ y = (duk_int_t) x - 0x41;
+ } else {
+ goto decode_error;
+ }
+ } else if (x >= 0x30U) {
+ /* Valid: 0-9 and =. */
+ DUK_ASSERT(x >= 0x30U && x <= 0x40U);
+ if (x <= 0x39U) {
+ y = (duk_int_t) x - 0x30 + 52;
+ } else if (x == 0x3dU) {
+ /* Skip padding and whitespace unless we're in the
+ * middle of a block. Otherwise complete group by
+ * simulating shifting in the correct padding.
+ */
+ if (t == 1U) {
+ continue;
+ }
+ goto simulate_padding;
+ } else {
+ goto decode_error;
+ }
+ } else if (x >= 0x20U) {
+ /* Valid: +, /, and 0x20 whitespace. */
+ DUK_ASSERT(x >= 0x20U && x <= 0x2fU);
+ if (x == 0x2bU) {
+ y = 62;
+ } else if (x == 0x2fU) {
+ y = 63;
+ } else if (x == 0x20U) {
+ continue;
+ } else {
+ goto decode_error;
+ }
} else {
- goto decode_error;
+ /* Valid: whitespace. */
+ duk_uint32_t m;
+ DUK_ASSERT(x < 0x20U); /* 0x00 to 0x1f */
+ m = (1U << x);
+ if (mask_white & m) {
+ /* Allow basic ASCII whitespace. */
+ continue;
+ } else {
+ goto decode_error;
+ }
}
- if (n_equal > 0) {
- /* Don't allow mixed padding and actual chars. */
- goto decode_error;
+ DUK_ASSERT(y >= 0 && y <= 63);
+ t = (t << 6) + (duk_uint_t) y;
+ if (t < 0x1000000UL) {
+ continue;
}
- t = (t << 6) + y;
- skip_add:
-
- if (group_idx == 3) {
- /* output 3 bytes from 't' */
- *dst++ = (duk_uint8_t) ((t >> 16) & 0xff);
- *dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
- *dst++ = (duk_uint8_t) (t & 0xff);
-
- if (DUK_UNLIKELY(n_equal > 0)) {
- /* Backtrack. */
- DUK_ASSERT(n_equal <= 4);
- if (n_equal == 1) {
- dst -= 1;
- } else if (n_equal == 2) {
- dst -= 2;
- } else {
- goto decode_error; /* invalid padding */
- }
+ /* fall through; no padding will be added */
- /* Here we can choose either to end parsing and ignore
- * whatever follows, or to continue parsing in case
- * multiple (possibly padded) base64 strings have been
- * concatenated. Currently, keep on parsing.
- */
- n_equal = 0;
- }
+ simulate_padding:
+ n_equal = 0;
+ while (t < 0x1000000UL) {
+ t = (t << 6) + 0U;
+ n_equal++;
+ }
- t = 0;
- group_idx = 0;
- } else {
- group_idx++;
+ /* Output 3 bytes from 't' and advance as needed. */
+ q[0] = (duk_uint8_t) ((t >> 16) & 0xffU);
+ q[1] = (duk_uint8_t) ((t >> 8) & 0xffU);
+ q[2] = (duk_uint8_t) (t & 0xffU);
+
+ DUK_ASSERT(n_equal <= 4U);
+ step = duk__base64_decode_nequal_step[n_equal];
+ if (step < 0) {
+ goto decode_error;
}
- }
+ q += step;
- if (group_idx != 0) {
- /* Here we'd have the option of decoding unpadded base64
- * (e.g. "xxxxyy" instead of "xxxxyy==". Currently not
- * accepted.
+ /* Re-enter loop. The actual padding characters are skipped
+ * by the main loop. This handles cases like missing, partial,
+ * full, and extra padding, and allows parsing of concatenated
+ * documents (with extra padding) like: Zm===Zm. Also extra
+ * prepended padding is accepted: ===Zm9v.
*/
- goto decode_error;
+ t = 1U;
}
+ DUK_ASSERT(t == 1UL);
- *out_dst_final = dst;
+ *out_dst_final = q;
return 1;
- decode_error:
+decode_error:
return 0;
}
-#endif /* DUK_USE_BASE64_FASTPATH */
+#endif /* DUK_USE_BASE64_FASTPATH */
DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
const duk_uint8_t *src;
@@ -15012,15 +16355,12 @@ DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
- /* XXX: optimize for string inputs: no need to coerce to a buffer
- * which makes a copy of the input.
- */
-
idx = duk_require_normalize_index(thr, idx);
src = duk__prep_codec_arg(thr, idx, &srclen);
- /* Note: for srclen=0, src may be NULL */
+ DUK_ASSERT(src != NULL);
- /* Computation must not wrap; this limit works for 32-bit size_t:
+ /* Compute exact output length. Computation must not wrap; this
+ * limit works for 32-bit size_t:
* >>> srclen = 3221225469
* >>> '%x' % ((srclen + 2) / 3 * 4)
* 'fffffffc'
@@ -15028,18 +16368,18 @@ DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
if (srclen > 3221225469UL) {
goto type_error;
}
- dstlen = (srclen + 2) / 3 * 4;
+ dstlen = (srclen + 2U) / 3U * 4U;
dst = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, dstlen);
duk__base64_encode_helper((const duk_uint8_t *) src, srclen, dst);
- ret = duk_buffer_to_string(thr, -1); /* Safe, result is ASCII. */
+ ret = duk_buffer_to_string(thr, -1); /* Safe, result is ASCII. */
duk_replace(thr, idx);
return ret;
- type_error:
+type_error:
DUK_ERROR_TYPE(thr, DUK_STR_BASE64_ENCODE_FAILED);
- return NULL; /* never here */
+ DUK_WO_NORETURN(return NULL;);
}
DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) {
@@ -15048,31 +16388,25 @@ DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) {
duk_size_t dstlen;
duk_uint8_t *dst;
duk_uint8_t *dst_final;
- duk_bool_t retval;
DUK_ASSERT_API_ENTRY(thr);
- /* XXX: optimize for buffer inputs: no need to coerce to a string
- * which causes an unnecessary interning.
- */
-
idx = duk_require_normalize_index(thr, idx);
src = duk__prep_codec_arg(thr, idx, &srclen);
+ DUK_ASSERT(src != NULL);
- /* Computation must not wrap, only srclen + 3 is at risk of
- * wrapping because after that the number gets smaller.
- * This limit works for 32-bit size_t:
- * 0x100000000 - 3 - 1 = 4294967292
+ /* Round up and add safety margin. Avoid addition before division to
+ * avoid possibility of wrapping. Margin includes +3 for rounding up,
+ * and +3 for one extra group: the decoder may emit and then backtrack
+ * a full group (3 bytes) from zero-sized input for technical reasons.
+ * Similarly, 'xx' may ecause 1+3 = bytes to be emitted and then
+ * backtracked.
*/
- if (srclen > 4294967292UL) {
- goto type_error;
- }
- dstlen = (srclen + 3) / 4 * 3; /* upper limit, assuming no whitespace etc */
+ dstlen = (srclen / 4) * 3 + 6; /* upper limit, assuming no whitespace etc */
dst = (duk_uint8_t *) duk_push_dynamic_buffer(thr, dstlen);
/* Note: for dstlen=0, dst may be NULL */
- retval = duk__base64_decode_helper((const duk_uint8_t *) src, srclen, dst, &dst_final);
- if (!retval) {
+ if (!duk__base64_decode_helper((const duk_uint8_t *) src, srclen, dst, &dst_final)) {
goto type_error;
}
@@ -15081,10 +16415,29 @@ DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) {
duk_replace(thr, idx);
return;
- type_error:
+type_error:
DUK_ERROR_TYPE(thr, DUK_STR_BASE64_DECODE_FAILED);
+ DUK_WO_NORETURN(return;);
+}
+#else /* DUK_USE_BASE64_SUPPORT */
+DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
+ DUK_UNREF(idx);
+ DUK_ERROR_UNSUPPORTED(thr);
+ DUK_WO_NORETURN(return NULL;);
}
+DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) {
+ DUK_UNREF(idx);
+ DUK_ERROR_UNSUPPORTED(thr);
+ DUK_WO_NORETURN(return;);
+}
+#endif /* DUK_USE_BASE64_SUPPORT */
+
+/*
+ * Hex
+ */
+
+#if defined(DUK_USE_HEX_SUPPORT)
DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
const duk_uint8_t *inp;
duk_size_t len;
@@ -15100,14 +16453,14 @@ DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
idx = duk_require_normalize_index(thr, idx);
inp = duk__prep_codec_arg(thr, idx, &len);
- DUK_ASSERT(inp != NULL || len == 0);
+ DUK_ASSERT(inp != NULL);
/* Fixed buffer, no zeroing because we'll fill all the data. */
buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len * 2);
DUK_ASSERT(buf != NULL);
#if defined(DUK_USE_HEX_FASTPATH)
- DUK_ASSERT((((duk_size_t) buf) & 0x01U) == 0); /* pointer is aligned, guaranteed for fixed buffer */
+ DUK_ASSERT((((duk_size_t) buf) & 0x01U) == 0); /* pointer is aligned, guaranteed for fixed buffer */
p16 = (duk_uint16_t *) (void *) buf;
len_safe = len & ~0x03U;
for (i = 0; i < len_safe; i += 4) {
@@ -15120,14 +16473,14 @@ DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
for (; i < len; i++) {
*p16++ = duk_hex_enctab[inp[i]];
}
-#else /* DUK_USE_HEX_FASTPATH */
+#else /* DUK_USE_HEX_FASTPATH */
for (i = 0; i < len; i++) {
duk_small_uint_t t;
t = (duk_small_uint_t) inp[i];
- buf[i*2 + 0] = duk_lc_digits[t >> 4];
- buf[i*2 + 1] = duk_lc_digits[t & 0x0f];
+ buf[i * 2 + 0] = duk_lc_digits[t >> 4];
+ buf[i * 2 + 1] = duk_lc_digits[t & 0x0f];
}
-#endif /* DUK_USE_HEX_FASTPATH */
+#endif /* DUK_USE_HEX_FASTPATH */
/* XXX: Using a string return value forces a string intern which is
* not always necessary. As a rough performance measure, hex encode
@@ -15136,7 +16489,7 @@ DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
* caller coerce to string if necessary?
*/
- ret = duk_buffer_to_string(thr, -1); /* Safe, result is ASCII. */
+ ret = duk_buffer_to_string(thr, -1); /* Safe, result is ASCII. */
duk_replace(thr, idx);
return ret;
}
@@ -15157,7 +16510,7 @@ DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) {
idx = duk_require_normalize_index(thr, idx);
inp = duk__prep_codec_arg(thr, idx, &len);
- DUK_ASSERT(inp != NULL || len == 0);
+ DUK_ASSERT(inp != NULL);
if (len & 0x01) {
goto type_error;
@@ -15171,20 +16524,16 @@ DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) {
p = buf;
len_safe = len & ~0x07U;
for (i = 0; i < len_safe; i += 8) {
- t = ((duk_int_t) duk_hex_dectab_shift4[inp[i]]) |
- ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
+ t = ((duk_int_t) duk_hex_dectab_shift4[inp[i]]) | ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
chk = t;
p[0] = (duk_uint8_t) t;
- t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 2]]) |
- ((duk_int_t) duk_hex_dectab[inp[i + 3]]);
+ t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 2]]) | ((duk_int_t) duk_hex_dectab[inp[i + 3]]);
chk |= t;
p[1] = (duk_uint8_t) t;
- t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 4]]) |
- ((duk_int_t) duk_hex_dectab[inp[i + 5]]);
+ t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 4]]) | ((duk_int_t) duk_hex_dectab[inp[i + 5]]);
chk |= t;
p[2] = (duk_uint8_t) t;
- t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 6]]) |
- ((duk_int_t) duk_hex_dectab[inp[i + 7]]);
+ t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 6]]) | ((duk_int_t) duk_hex_dectab[inp[i + 7]]);
chk |= t;
p[3] = (duk_uint8_t) t;
p += 4;
@@ -15195,34 +16544,55 @@ DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) {
}
}
for (; i < len; i += 2) {
- t = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) |
- ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
+ /* First cast to duk_int_t to sign extend, second cast to
+ * duk_uint_t to avoid signed left shift, and final cast to
+ * duk_int_t result type.
+ */
+ t = (duk_int_t) ((((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i]]) << 4U) |
+ ((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i + 1]]));
if (DUK_UNLIKELY(t < 0)) {
goto type_error;
}
*p++ = (duk_uint8_t) t;
}
-#else /* DUK_USE_HEX_FASTPATH */
+#else /* DUK_USE_HEX_FASTPATH */
for (i = 0; i < len; i += 2) {
/* For invalid characters the value -1 gets extended to
* at least 16 bits. If either nybble is invalid, the
* resulting 't' will be < 0.
*/
- t = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) |
- ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
+ t = (duk_int_t) ((((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i]]) << 4U) |
+ ((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i + 1]]));
if (DUK_UNLIKELY(t < 0)) {
goto type_error;
}
buf[i >> 1] = (duk_uint8_t) t;
}
-#endif /* DUK_USE_HEX_FASTPATH */
+#endif /* DUK_USE_HEX_FASTPATH */
duk_replace(thr, idx);
return;
- type_error:
+type_error:
DUK_ERROR_TYPE(thr, DUK_STR_HEX_DECODE_FAILED);
+ DUK_WO_NORETURN(return;);
+}
+#else /* DUK_USE_HEX_SUPPORT */
+DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
+ DUK_UNREF(idx);
+ DUK_ERROR_UNSUPPORTED(thr);
+ DUK_WO_NORETURN(return NULL;);
+}
+DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) {
+ DUK_UNREF(idx);
+ DUK_ERROR_UNSUPPORTED(thr);
+ DUK_WO_NORETURN(return;);
}
+#endif /* DUK_USE_HEX_SUPPORT */
+
+/*
+ * JSON
+ */
#if defined(DUK_USE_JSON_SUPPORT)
DUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) {
@@ -15262,27 +16632,26 @@ DUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx) {
#endif
idx = duk_require_normalize_index(thr, idx);
- duk_bi_json_parse_helper(thr,
- idx /*idx_value*/,
- DUK_INVALID_INDEX /*idx_reviver*/,
- 0 /*flags*/);
+ duk_bi_json_parse_helper(thr, idx /*idx_value*/, DUK_INVALID_INDEX /*idx_reviver*/, 0 /*flags*/);
duk_replace(thr, idx);
DUK_ASSERT(duk_get_top(thr) == top_at_entry);
}
-#else /* DUK_USE_JSON_SUPPORT */
+#else /* DUK_USE_JSON_SUPPORT */
DUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
DUK_UNREF(idx);
DUK_ERROR_UNSUPPORTED(thr);
+ DUK_WO_NORETURN(return NULL;);
}
DUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
DUK_UNREF(idx);
DUK_ERROR_UNSUPPORTED(thr);
+ DUK_WO_NORETURN(return;);
}
-#endif /* DUK_USE_JSON_SUPPORT */
+#endif /* DUK_USE_JSON_SUPPORT */
/*
* Compilation and evaluation
*/
@@ -15291,7 +16660,7 @@ DUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx) {
typedef struct duk__compile_raw_args duk__compile_raw_args;
struct duk__compile_raw_args {
- duk_size_t src_length; /* should be first on 64-bit platforms */
+ duk_size_t src_length; /* should be first on 64-bit platforms */
const duk_uint8_t *src_buffer;
duk_uint_t flags;
};
@@ -15311,7 +16680,10 @@ DUK_EXTERNAL duk_int_t duk_eval_raw(duk_hthread *thr, const char *src_buffer, du
/* [ ... source? filename? ] (depends on flags) */
- rc = duk_compile_raw(thr, src_buffer, src_length, flags | DUK_COMPILE_EVAL); /* may be safe, or non-safe depending on flags */
+ rc = duk_compile_raw(thr,
+ src_buffer,
+ src_length,
+ flags | DUK_COMPILE_EVAL); /* may be safe, or non-safe depending on flags */
/* [ ... closure/error ] */
@@ -15320,7 +16692,7 @@ DUK_EXTERNAL duk_int_t duk_eval_raw(duk_hthread *thr, const char *src_buffer, du
goto got_rc;
}
- duk_push_global_object(thr); /* explicit 'this' binding, see GH-164 */
+ duk_push_global_object(thr); /* explicit 'this' binding, see GH-164 */
if (flags & DUK_COMPILE_SAFE) {
rc = duk_pcall_method(thr, 0);
@@ -15331,7 +16703,7 @@ DUK_EXTERNAL duk_int_t duk_eval_raw(duk_hthread *thr, const char *src_buffer, du
/* [ ... result/error ] */
- got_rc:
+got_rc:
if (flags & DUK_COMPILE_NORESULT) {
duk_pop(thr);
}
@@ -15345,7 +16717,7 @@ DUK_LOCAL duk_ret_t duk__do_compile(duk_hthread *thr, void *udata) {
duk_uint_t flags;
duk_hcompfunc *h_templ;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
DUK_ASSERT(udata != NULL);
/* Note: strictness is not inherited from the current Duktape/C
@@ -15371,9 +16743,10 @@ DUK_LOCAL duk_ret_t duk__do_compile(duk_hthread *thr, void *udata) {
duk_hstring *h_sourcecode;
h_sourcecode = duk_get_hstring(thr, -2);
- if ((flags & DUK_COMPILE_NOSOURCE) || /* args incorrect */
- (h_sourcecode == NULL)) { /* e.g. duk_push_string_file_raw() pushed undefined */
+ if ((flags & DUK_COMPILE_NOSOURCE) || /* args incorrect */
+ (h_sourcecode == NULL)) { /* e.g. duk_push_string_file_raw() pushed undefined */
DUK_ERROR_TYPE(thr, DUK_STR_NO_SOURCECODE);
+ DUK_WO_NORETURN(return 0;);
}
DUK_ASSERT(h_sourcecode != NULL);
comp_args->src_buffer = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode);
@@ -15401,11 +16774,11 @@ DUK_LOCAL duk_ret_t duk__do_compile(duk_hthread *thr, void *udata) {
h_templ = (duk_hcompfunc *) duk_known_hobject(thr, -1);
duk_js_push_closure(thr,
- h_templ,
- thr->builtins[DUK_BIDX_GLOBAL_ENV],
- thr->builtins[DUK_BIDX_GLOBAL_ENV],
- 1 /*add_auto_proto*/);
- duk_remove_m2(thr); /* -> [ ... closure ] */
+ h_templ,
+ thr->builtins[DUK_BIDX_GLOBAL_ENV],
+ thr->builtins[DUK_BIDX_GLOBAL_ENV],
+ 1 /*add_auto_proto*/);
+ duk_remove_m2(thr); /* -> [ ... closure ] */
/* [ ... closure ] */
@@ -15441,8 +16814,7 @@ DUK_EXTERNAL duk_int_t duk_compile_raw(duk_hthread *thr, const char *src_buffer,
* directly into flags.
*/
nargs = flags & 0x07;
- DUK_ASSERT(nargs == ((flags & DUK_COMPILE_NOSOURCE) ? 0 : 1) +
- ((flags & DUK_COMPILE_NOFILENAME) ? 0 : 1));
+ DUK_ASSERT(nargs == ((flags & DUK_COMPILE_NOSOURCE) ? 0 : 1) + ((flags & DUK_COMPILE_NOFILENAME) ? 0 : 1));
rc = duk_safe_call(thr, duk__do_compile, (void *) comp_args, nargs, nrets);
/* [ ... closure ] */
@@ -15472,7 +16844,7 @@ DUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) {
*/
top = duk_get_top(thr);
- duk_push_array(thr);
+ duk_push_bare_array(thr);
for (idx = 0; idx < top; idx++) {
duk_dup(thr, idx);
duk_put_prop_index(thr, -2, (duk_uarridx_t) idx);
@@ -15482,24 +16854,24 @@ DUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) {
* Perhaps values need to be coerced individually?
*/
duk_bi_json_stringify_helper(thr,
- duk_get_top_index(thr), /*idx_value*/
- DUK_INVALID_INDEX, /*idx_replacer*/
- DUK_INVALID_INDEX, /*idx_space*/
- DUK_JSON_FLAG_EXT_CUSTOM |
- DUK_JSON_FLAG_ASCII_ONLY |
- DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
+ duk_get_top_index(thr), /*idx_value*/
+ DUK_INVALID_INDEX, /*idx_replacer*/
+ DUK_INVALID_INDEX, /*idx_space*/
+ DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_ASCII_ONLY |
+ DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
duk_push_sprintf(thr, "ctx: top=%ld, stack=%s", (long) top, (const char *) duk_safe_to_string(thr, -1));
- duk_replace(thr, -3); /* [ ... arr jsonx(arr) res ] -> [ ... res jsonx(arr) ] */
+ duk_replace(thr, -3); /* [ ... arr jsonx(arr) res ] -> [ ... res jsonx(arr) ] */
duk_pop(thr);
DUK_ASSERT(duk_is_string(thr, -1));
}
-#else /* DUK_USE_JSON_SUPPORT */
+#else /* DUK_USE_JSON_SUPPORT */
DUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) {
DUK_ASSERT_API_ENTRY(thr);
DUK_ERROR_UNSUPPORTED(thr);
+ DUK_WO_NORETURN(return;);
}
-#endif /* DUK_USE_JSON_SUPPORT */
+#endif /* DUK_USE_JSON_SUPPORT */
#if defined(DUK_USE_DEBUGGER_SUPPORT)
@@ -15548,12 +16920,13 @@ DUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr,
heap->dbg_exec_counter = 0;
heap->dbg_last_counter = 0;
heap->dbg_last_time = 0.0;
- duk_debug_set_paused(heap); /* XXX: overlap with fields above */
+ duk_debug_set_paused(heap); /* XXX: overlap with fields above */
/* Send version identification and flush right afterwards. Note that
* we must write raw, unframed bytes here.
*/
- duk_push_sprintf(thr, "%ld %ld %s %s\n",
+ duk_push_sprintf(thr,
+ "%ld %ld %s %s\n",
(long) DUK_DEBUG_PROTOCOL_VERSION,
(long) DUK_VERSION,
(const char *) DUK_GIT_DESCRIBE,
@@ -15609,7 +16982,7 @@ DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues)
top = duk_get_top(thr);
if (top < nvalues) {
DUK_ERROR_RANGE(thr, "not enough stack values for notify");
- return ret; /* unreachable */
+ DUK_WO_NORETURN(return 0;);
}
if (duk_debug_is_attached(thr->heap)) {
duk_debug_write_notify(thr, DUK_DBG_CMD_APPNOTIFY);
@@ -15655,7 +17028,7 @@ DUK_EXTERNAL void duk_debugger_pause(duk_hthread *thr) {
}
}
-#else /* DUK_USE_DEBUGGER_SUPPORT */
+#else /* DUK_USE_DEBUGGER_SUPPORT */
DUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr,
duk_debug_read_function read_cb,
@@ -15676,11 +17049,13 @@ DUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr,
DUK_UNREF(detached_cb);
DUK_UNREF(udata);
DUK_ERROR_TYPE(thr, "no debugger support");
+ DUK_WO_NORETURN(return;);
}
DUK_EXTERNAL void duk_debugger_detach(duk_hthread *thr) {
DUK_ASSERT_API_ENTRY(thr);
DUK_ERROR_TYPE(thr, "no debugger support");
+ DUK_WO_NORETURN(return;);
}
DUK_EXTERNAL void duk_debugger_cooperate(duk_hthread *thr) {
@@ -15697,7 +17072,7 @@ DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues)
top = duk_get_top(thr);
if (top < nvalues) {
DUK_ERROR_RANGE_INVALID_COUNT(thr);
- return 0; /* unreachable */
+ DUK_WO_NORETURN(return 0;);
}
/* No debugger support, just pop values. */
@@ -15711,7 +17086,7 @@ DUK_EXTERNAL void duk_debugger_pause(duk_hthread *thr) {
DUK_UNREF(thr);
}
-#endif /* DUK_USE_DEBUGGER_SUPPORT */
+#endif /* DUK_USE_DEBUGGER_SUPPORT */
/*
* Heap creation and destruction
*/
@@ -15724,6 +17099,7 @@ struct duk_internal_thread_state {
duk_ljstate lj;
duk_bool_t creating_error;
duk_hthread *curr_thread;
+ duk_uint8_t thread_state;
duk_int_t call_recursion_depth;
};
@@ -15798,7 +17174,7 @@ DUK_EXTERNAL void duk_suspend(duk_hthread *thr, duk_thread_state *state) {
DUK_ASSERT_API_ENTRY(thr);
DUK_ASSERT(thr->heap != NULL);
- DUK_ASSERT(state != NULL); /* unvalidated */
+ DUK_ASSERT(state != NULL); /* unvalidated */
/* Currently not supported when called from within a finalizer.
* If that is done, the finalizer will remain running indefinitely,
@@ -15819,9 +17195,10 @@ DUK_EXTERNAL void duk_suspend(duk_hthread *thr, duk_thread_state *state) {
duk_push_tval(thr, &lj->value2);
/* XXX: creating_error == 0 is asserted above, so no need to store. */
- DUK_MEMCPY((void *) &snapshot->lj, (const void *) lj, sizeof(duk_ljstate));
+ duk_memcpy((void *) &snapshot->lj, (const void *) lj, sizeof(duk_ljstate));
snapshot->creating_error = heap->creating_error;
snapshot->curr_thread = heap->curr_thread;
+ snapshot->thread_state = thr->state;
snapshot->call_recursion_depth = heap->call_recursion_depth;
lj->jmpbuf_ptr = NULL;
@@ -15831,6 +17208,8 @@ DUK_EXTERNAL void duk_suspend(duk_hthread *thr, duk_thread_state *state) {
heap->creating_error = 0;
heap->curr_thread = NULL;
heap->call_recursion_depth = 0;
+
+ thr->state = DUK_HTHREAD_STATE_INACTIVE;
}
DUK_EXTERNAL void duk_resume(duk_hthread *thr, const duk_thread_state *state) {
@@ -15839,7 +17218,7 @@ DUK_EXTERNAL void duk_resume(duk_hthread *thr, const duk_thread_state *state) {
DUK_ASSERT_API_ENTRY(thr);
DUK_ASSERT(thr->heap != NULL);
- DUK_ASSERT(state != NULL); /* unvalidated */
+ DUK_ASSERT(state != NULL); /* unvalidated */
/* Shouldn't be necessary if duk_suspend() is called before
* duk_resume(), but assert in case API sequence is incorrect.
@@ -15847,9 +17226,11 @@ DUK_EXTERNAL void duk_resume(duk_hthread *thr, const duk_thread_state *state) {
DUK_ASSERT(thr->heap->pf_prevent_count == 0);
DUK_ASSERT(thr->heap->creating_error == 0);
+ thr->state = snapshot->thread_state;
+
heap = thr->heap;
- DUK_MEMCPY((void *) &heap->lj, (const void *) &snapshot->lj, sizeof(duk_ljstate));
+ duk_memcpy((void *) &heap->lj, (const void *) &snapshot->lj, sizeof(duk_ljstate));
heap->creating_error = snapshot->creating_error;
heap->curr_thread = snapshot->curr_thread;
heap->call_recursion_depth = snapshot->call_recursion_depth;
@@ -15879,7 +17260,7 @@ DUK_EXTERNAL void duk_set_global_object(duk_hthread *thr) {
DUK_UNREF(h_prev_glob);
thr->builtins[DUK_BIDX_GLOBAL] = h_glob;
DUK_HOBJECT_INCREF(thr, h_glob);
- DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_glob); /* side effects, in theory (referenced by global env) */
+ DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_glob); /* side effects, in theory (referenced by global env) */
/*
* Replace lexical environment for global scope
@@ -15890,9 +17271,7 @@ DUK_EXTERNAL void duk_set_global_object(duk_hthread *thr) {
* same (initial) built-ins.
*/
- h_env = duk_hobjenv_alloc(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
+ h_env = duk_hobjenv_alloc(thr, DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
DUK_ASSERT(h_env != NULL);
DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_env) == NULL);
@@ -15907,8 +17286,8 @@ DUK_EXTERNAL void duk_set_global_object(duk_hthread *thr) {
h_prev_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
thr->builtins[DUK_BIDX_GLOBAL_ENV] = (duk_hobject *) h_env;
DUK_HOBJECT_INCREF(thr, (duk_hobject *) h_env);
- DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_env); /* side effects */
- DUK_UNREF(h_env); /* without refcounts */
+ DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_env); /* side effects */
+ DUK_UNREF(h_env); /* without refcounts */
DUK_UNREF(h_prev_env);
/* [ ... new_glob ] */
@@ -15958,20 +17337,20 @@ DUK_LOCAL void duk__inspect_multiple_uint(duk_hthread *thr, const char *fmt, duk
* be security implications.
*/
-#define DUK__IDX_TYPE 0
-#define DUK__IDX_ITAG 1
-#define DUK__IDX_REFC 2
-#define DUK__IDX_HBYTES 3
-#define DUK__IDX_CLASS 4
-#define DUK__IDX_PBYTES 5
-#define DUK__IDX_ESIZE 6
-#define DUK__IDX_ENEXT 7
-#define DUK__IDX_ASIZE 8
-#define DUK__IDX_HSIZE 9
-#define DUK__IDX_BCBYTES 10
-#define DUK__IDX_DBYTES 11
-#define DUK__IDX_TSTATE 12
-#define DUK__IDX_VARIANT 13
+#define DUK__IDX_TYPE 0
+#define DUK__IDX_ITAG 1
+#define DUK__IDX_REFC 2
+#define DUK__IDX_HBYTES 3
+#define DUK__IDX_CLASS 4
+#define DUK__IDX_PBYTES 5
+#define DUK__IDX_ESIZE 6
+#define DUK__IDX_ENEXT 7
+#define DUK__IDX_ASIZE 8
+#define DUK__IDX_HSIZE 9
+#define DUK__IDX_BCBYTES 10
+#define DUK__IDX_DBYTES 11
+#define DUK__IDX_TSTATE 12
+#define DUK__IDX_VARIANT 13
DUK_EXTERNAL void duk_inspect_value(duk_hthread *thr, duk_idx_t idx) {
duk_tval *tv;
@@ -15985,8 +17364,8 @@ DUK_EXTERNAL void duk_inspect_value(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
/* Assume two's complement and set everything to -1. */
- DUK_MEMSET((void *) &vals, (int) 0xff, sizeof(vals));
- DUK_ASSERT(vals[DUK__IDX_TYPE] == -1); /* spot check one */
+ duk_memset((void *) &vals, (int) 0xff, sizeof(vals));
+ DUK_ASSERT(vals[DUK__IDX_TYPE] == -1); /* spot check one */
tv = duk_get_tval_or_unused(thr, idx);
h = (DUK_TVAL_IS_HEAP_ALLOCATED(tv) ? DUK_TVAL_GET_HEAPHDR(tv) : NULL);
@@ -15994,19 +17373,19 @@ DUK_EXTERNAL void duk_inspect_value(duk_hthread *thr, duk_idx_t idx) {
vals[DUK__IDX_TYPE] = duk_get_type_tval(tv);
vals[DUK__IDX_ITAG] = (duk_int_t) DUK_TVAL_GET_TAG(tv);
- duk_push_bare_object(thr); /* Invalidates 'tv'. */
+ duk_push_bare_object(thr); /* Invalidates 'tv'. */
tv = NULL;
if (h == NULL) {
goto finish;
}
duk_push_pointer(thr, (void *) h);
- duk_put_prop_string(thr, -2, "hptr");
+ duk_put_prop_literal(thr, -2, "hptr");
#if 0
/* Covers a lot of information, e.g. buffer and string variants. */
duk_push_uint(thr, (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
- duk_put_prop_string(thr, -2, "hflags");
+ duk_put_prop_literal(thr, -2, "hflags");
#endif
#if defined(DUK_USE_REFERENCE_COUNTING)
@@ -16051,7 +17430,7 @@ DUK_EXTERNAL void duk_inspect_value(duk_hthread *thr, duk_idx_t idx) {
}
vals[DUK__IDX_CLASS] = (duk_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
- vals[DUK__IDX_PBYTES] = (duk_int_t) DUK_HOBJECT_P_ALLOC_SIZE(h_obj),
+ vals[DUK__IDX_PBYTES] = (duk_int_t) DUK_HOBJECT_P_ALLOC_SIZE(h_obj);
vals[DUK__IDX_ESIZE] = (duk_int_t) DUK_HOBJECT_GET_ESIZE(h_obj);
vals[DUK__IDX_ENEXT] = (duk_int_t) DUK_HOBJECT_GET_ENEXT(h_obj);
vals[DUK__IDX_ASIZE] = (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj);
@@ -16076,30 +17455,56 @@ DUK_EXTERNAL void duk_inspect_value(duk_hthread *thr, duk_idx_t idx) {
if (DUK_HBUFFER_HAS_DYNAMIC(h_buf)) {
if (DUK_HBUFFER_HAS_EXTERNAL(h_buf)) {
- vals[DUK__IDX_VARIANT] = 2; /* buffer variant 2: external */
+ vals[DUK__IDX_VARIANT] = 2; /* buffer variant 2: external */
vals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_external));
} else {
/* When alloc_size == 0 the second allocation may not
* actually exist.
*/
- vals[DUK__IDX_VARIANT] = 1; /* buffer variant 1: dynamic */
+ vals[DUK__IDX_VARIANT] = 1; /* buffer variant 1: dynamic */
vals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_dynamic));
}
vals[DUK__IDX_DBYTES] = (duk_int_t) (DUK_HBUFFER_GET_SIZE(h_buf));
} else {
- DUK_ASSERT(vals[DUK__IDX_VARIANT] == 0); /* buffer variant 0: fixed */
+ DUK_ASSERT(vals[DUK__IDX_VARIANT] == 0); /* buffer variant 0: fixed */
vals[DUK__IDX_HBYTES] = (duk_int_t) (sizeof(duk_hbuffer_fixed) + DUK_HBUFFER_GET_SIZE(h_buf));
}
break;
}
}
- finish:
+finish:
duk__inspect_multiple_uint(thr,
- "type" "\x00" "itag" "\x00" "refc" "\x00" "hbytes" "\x00" "class" "\x00"
- "pbytes" "\x00" "esize" "\x00" "enext" "\x00" "asize" "\x00" "hsize" "\x00"
- "bcbytes" "\x00" "dbytes" "\x00" "tstate" "\x00" "variant" "\x00" "\x00",
- (duk_int_t *) &vals);
+ "type"
+ "\x00"
+ "itag"
+ "\x00"
+ "refc"
+ "\x00"
+ "hbytes"
+ "\x00"
+ "class"
+ "\x00"
+ "pbytes"
+ "\x00"
+ "esize"
+ "\x00"
+ "enext"
+ "\x00"
+ "asize"
+ "\x00"
+ "hsize"
+ "\x00"
+ "bcbytes"
+ "\x00"
+ "dbytes"
+ "\x00"
+ "tstate"
+ "\x00"
+ "variant"
+ "\x00"
+ "\x00",
+ (duk_int_t *) &vals);
}
DUK_EXTERNAL void duk_inspect_callstack_entry(duk_hthread *thr, duk_int_t level) {
@@ -16238,7 +17643,7 @@ DUK_EXTERNAL void duk_gc(duk_hthread *thr, duk_uint_t flags) {
DUK_ASSERT(heap != NULL);
DUK_D(DUK_DPRINT("mark-and-sweep requested by application"));
- DUK_ASSERT(DUK_GC_COMPACT == DUK_MS_FLAG_EMERGENCY); /* Compact flag is 1:1 with emergency flag which forces compaction. */
+ DUK_ASSERT(DUK_GC_COMPACT == DUK_MS_FLAG_EMERGENCY); /* Compact flag is 1:1 with emergency flag which forces compaction. */
ms_flags = (duk_small_uint_t) flags;
duk_heap_mark_and_sweep(heap, ms_flags);
}
@@ -16252,7 +17657,7 @@ DUK_EXTERNAL void duk_gc(duk_hthread *thr, duk_uint_t flags) {
* Property handling
*
* The API exposes only the most common property handling functions.
- * The caller can invoke Ecmascript built-ins for full control (e.g.
+ * The caller can invoke ECMAScript built-ins for full control (e.g.
* defineProperty, getOwnPropertyDescriptor).
*/
@@ -16274,9 +17679,9 @@ DUK_EXTERNAL duk_bool_t duk_get_prop(duk_hthread *thr, duk_idx_t obj_idx) {
DUK_ASSERT(rc == 0 || rc == 1);
/* a value is left on stack regardless of rc */
- duk_remove_m2(thr); /* remove key */
+ duk_remove_m2(thr); /* remove key */
DUK_ASSERT(duk_is_undefined(thr, -1) || rc == 1);
- return rc; /* 1 if property found, 0 otherwise */
+ return rc; /* 1 if property found, 0 otherwise */
}
DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
@@ -16284,7 +17689,7 @@ DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_hthread *thr, duk_idx_t obj_idx,
DUK_ASSERT(key != NULL);
obj_idx = duk_require_normalize_index(thr, obj_idx);
- duk_push_string(thr, key);
+ (void) duk_push_string(thr, key);
return duk_get_prop(thr, obj_idx);
}
@@ -16293,10 +17698,22 @@ DUK_EXTERNAL duk_bool_t duk_get_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx
DUK_ASSERT(key != NULL);
obj_idx = duk_require_normalize_index(thr, obj_idx);
- duk_push_lstring(thr, key, key_len);
+ (void) duk_push_lstring(thr, key, key_len);
return duk_get_prop(thr, obj_idx);
}
+#if !defined(DUK_USE_PREFER_SIZE)
+DUK_EXTERNAL duk_bool_t duk_get_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
+ DUK_ASSERT_API_ENTRY(thr);
+ DUK_ASSERT(key != NULL);
+ DUK_ASSERT(key[key_len] == (char) 0);
+
+ obj_idx = duk_require_normalize_index(thr, obj_idx);
+ (void) duk_push_literal_raw(thr, key, key_len);
+ return duk_get_prop(thr, obj_idx);
+}
+#endif
+
DUK_EXTERNAL duk_bool_t duk_get_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
DUK_ASSERT_API_ENTRY(thr);
@@ -16309,7 +17726,7 @@ DUK_EXTERNAL duk_bool_t duk_get_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx
DUK_ASSERT_API_ENTRY(thr);
obj_idx = duk_require_normalize_index(thr, obj_idx);
- duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */
+ (void) duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */
return duk_get_prop(thr, obj_idx);
}
@@ -16318,16 +17735,18 @@ DUK_INTERNAL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx,
DUK_ASSERT_STRIDX_VALID(stridx);
obj_idx = duk_require_normalize_index(thr, obj_idx);
- duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
+ (void) duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
return duk_get_prop(thr, obj_idx);
}
DUK_INTERNAL duk_bool_t duk_get_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
- return duk_get_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
- (duk_small_uint_t) (packed_args & 0xffffUL));
+ return duk_get_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16), (duk_small_uint_t) (packed_args & 0xffffUL));
}
-DUK_INTERNAL duk_bool_t duk_get_prop_stridx_boolean(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_bool_t *out_has_prop) {
+DUK_INTERNAL duk_bool_t duk_get_prop_stridx_boolean(duk_hthread *thr,
+ duk_idx_t obj_idx,
+ duk_small_uint_t stridx,
+ duk_bool_t *out_has_prop) {
duk_bool_t rc;
DUK_ASSERT_API_ENTRY(thr);
@@ -16337,10 +17756,59 @@ DUK_INTERNAL duk_bool_t duk_get_prop_stridx_boolean(duk_hthread *thr, duk_idx_t
if (out_has_prop) {
*out_has_prop = rc;
}
- rc = duk_to_boolean(thr, -1);
- DUK_ASSERT(rc == 0 || rc == 1);
- duk_pop(thr);
- return rc;
+ return duk_to_boolean_top_pop(thr);
+}
+
+/* This get variant is for internal use, it differs from standard
+ * duk_get_prop() in that:
+ * - Object argument must be an object (primitive values not supported).
+ * - Key argument must be a string (no coercion).
+ * - Only own properties are checked (no inheritance). Only "entry part"
+ * properties are checked (not array index properties).
+ * - Property must be a plain data property, not a getter.
+ * - Proxy traps are not triggered.
+ */
+DUK_INTERNAL duk_bool_t duk_xget_owndataprop(duk_hthread *thr, duk_idx_t obj_idx) {
+ duk_hobject *h_obj;
+ duk_hstring *h_key;
+ duk_tval *tv_val;
+
+ DUK_ASSERT_API_ENTRY(thr);
+
+ /* Note: copying tv_obj and tv_key to locals to shield against a valstack
+ * resize is not necessary for a property get right now.
+ */
+
+ h_obj = duk_get_hobject(thr, obj_idx);
+ if (h_obj == NULL) {
+ return 0;
+ }
+ h_key = duk_require_hstring(thr, -1);
+
+ tv_val = duk_hobject_find_entry_tval_ptr(thr->heap, h_obj, h_key);
+ if (tv_val == NULL) {
+ return 0;
+ }
+
+ duk_push_tval(thr, tv_val);
+ duk_remove_m2(thr); /* remove key */
+
+ return 1;
+}
+
+DUK_INTERNAL duk_bool_t duk_xget_owndataprop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
+ DUK_ASSERT_API_ENTRY(thr);
+ DUK_ASSERT_STRIDX_VALID(stridx);
+
+ obj_idx = duk_require_normalize_index(thr, obj_idx);
+ (void) duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
+ return duk_xget_owndataprop(thr, obj_idx);
+}
+
+DUK_INTERNAL duk_bool_t duk_xget_owndataprop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
+ return duk_xget_owndataprop_stridx(thr,
+ (duk_idx_t) (duk_int16_t) (packed_args >> 16),
+ (duk_small_uint_t) (packed_args & 0xffffUL));
}
DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t idx_key) {
@@ -16358,8 +17826,7 @@ DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_hthread *thr, duk_idx_t obj_idx, d
/* Key and value indices are either (-2, -1) or (-1, -2). Given idx_key,
* idx_val is always (idx_key ^ 0x01).
*/
- DUK_ASSERT((idx_key == -2 && (idx_key ^ 1) == -1) ||
- (idx_key == -1 && (idx_key ^ 1) == -2));
+ DUK_ASSERT((idx_key == -2 && (idx_key ^ 1) == -1) || (idx_key == -1 && (idx_key ^ 1) == -2));
/* XXX: Direct access; faster validation. */
tv_obj = duk_require_tval(thr, obj_idx);
tv_key = duk_require_tval(thr, idx_key);
@@ -16369,8 +17836,8 @@ DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_hthread *thr, duk_idx_t obj_idx, d
rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag);
DUK_ASSERT(rc == 0 || rc == 1);
- duk_pop_2(thr); /* remove key and value */
- return rc; /* 1 if property found, 0 otherwise */
+ duk_pop_2(thr); /* remove key and value */
+ return rc; /* 1 if property found, 0 otherwise */
}
DUK_EXTERNAL duk_bool_t duk_put_prop(duk_hthread *thr, duk_idx_t obj_idx) {
@@ -16400,6 +17867,18 @@ DUK_EXTERNAL duk_bool_t duk_put_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx
return duk__put_prop_shared(thr, obj_idx, -1);
}
+#if !defined(DUK_USE_PREFER_SIZE)
+DUK_EXTERNAL duk_bool_t duk_put_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
+ DUK_ASSERT_API_ENTRY(thr);
+ DUK_ASSERT(key != NULL);
+ DUK_ASSERT(key[key_len] == (char) 0);
+
+ obj_idx = duk_normalize_index(thr, obj_idx);
+ (void) duk_push_literal_raw(thr, key, key_len);
+ return duk__put_prop_shared(thr, obj_idx, -1);
+}
+#endif
+
DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
DUK_ASSERT_API_ENTRY(thr);
@@ -16412,11 +17891,10 @@ DUK_EXTERNAL duk_bool_t duk_put_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx
DUK_ASSERT_API_ENTRY(thr);
obj_idx = duk_require_normalize_index(thr, obj_idx);
- duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */
+ (void) duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */
return duk__put_prop_shared(thr, obj_idx, -1);
}
-
DUK_INTERNAL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
DUK_ASSERT_API_ENTRY(thr);
DUK_ASSERT_STRIDX_VALID(stridx);
@@ -16427,8 +17905,7 @@ DUK_INTERNAL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx,
}
DUK_INTERNAL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
- return duk_put_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
- (duk_small_uint_t) (packed_args & 0xffffUL));
+ return duk_put_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16), (duk_small_uint_t) (packed_args & 0xffffUL));
}
DUK_EXTERNAL duk_bool_t duk_del_prop(duk_hthread *thr, duk_idx_t obj_idx) {
@@ -16450,7 +17927,7 @@ DUK_EXTERNAL duk_bool_t duk_del_prop(duk_hthread *thr, duk_idx_t obj_idx) {
rc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag);
DUK_ASSERT(rc == 0 || rc == 1);
- duk_pop(thr); /* remove key */
+ duk_pop(thr); /* remove key */
return rc;
}
@@ -16459,7 +17936,7 @@ DUK_EXTERNAL duk_bool_t duk_del_prop_string(duk_hthread *thr, duk_idx_t obj_idx,
DUK_ASSERT(key != NULL);
obj_idx = duk_require_normalize_index(thr, obj_idx);
- duk_push_string(thr, key);
+ (void) duk_push_string(thr, key);
return duk_del_prop(thr, obj_idx);
}
@@ -16468,10 +17945,22 @@ DUK_EXTERNAL duk_bool_t duk_del_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx
DUK_ASSERT(key != NULL);
obj_idx = duk_require_normalize_index(thr, obj_idx);
- duk_push_lstring(thr, key, key_len);
+ (void) duk_push_lstring(thr, key, key_len);
return duk_del_prop(thr, obj_idx);
}
+#if !defined(DUK_USE_PREFER_SIZE)
+DUK_EXTERNAL duk_bool_t duk_del_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
+ DUK_ASSERT_API_ENTRY(thr);
+ DUK_ASSERT(key != NULL);
+ DUK_ASSERT(key[key_len] == (char) 0);
+
+ obj_idx = duk_require_normalize_index(thr, obj_idx);
+ (void) duk_push_literal_raw(thr, key, key_len);
+ return duk_del_prop(thr, obj_idx);
+}
+#endif
+
DUK_EXTERNAL duk_bool_t duk_del_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
DUK_ASSERT_API_ENTRY(thr);
@@ -16484,7 +17973,7 @@ DUK_EXTERNAL duk_bool_t duk_del_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx
DUK_ASSERT_API_ENTRY(thr);
obj_idx = duk_require_normalize_index(thr, obj_idx);
- duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */
+ (void) duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */
return duk_del_prop(thr, obj_idx);
}
@@ -16521,8 +18010,8 @@ DUK_EXTERNAL duk_bool_t duk_has_prop(duk_hthread *thr, duk_idx_t obj_idx) {
rc = duk_hobject_hasprop(thr, tv_obj, tv_key);
DUK_ASSERT(rc == 0 || rc == 1);
- duk_pop(thr); /* remove key */
- return rc; /* 1 if property found, 0 otherwise */
+ duk_pop(thr); /* remove key */
+ return rc; /* 1 if property found, 0 otherwise */
}
DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
@@ -16530,7 +18019,7 @@ DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_hthread *thr, duk_idx_t obj_idx,
DUK_ASSERT(key != NULL);
obj_idx = duk_require_normalize_index(thr, obj_idx);
- duk_push_string(thr, key);
+ (void) duk_push_string(thr, key);
return duk_has_prop(thr, obj_idx);
}
@@ -16539,10 +18028,22 @@ DUK_EXTERNAL duk_bool_t duk_has_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx
DUK_ASSERT(key != NULL);
obj_idx = duk_require_normalize_index(thr, obj_idx);
- duk_push_lstring(thr, key, key_len);
+ (void) duk_push_lstring(thr, key, key_len);
return duk_has_prop(thr, obj_idx);
}
+#if !defined(DUK_USE_PREFER_SIZE)
+DUK_EXTERNAL duk_bool_t duk_has_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
+ DUK_ASSERT_API_ENTRY(thr);
+ DUK_ASSERT(key != NULL);
+ DUK_ASSERT(key[key_len] == (char) 0);
+
+ obj_idx = duk_require_normalize_index(thr, obj_idx);
+ (void) duk_push_literal_raw(thr, key, key_len);
+ return duk_has_prop(thr, obj_idx);
+}
+#endif
+
DUK_EXTERNAL duk_bool_t duk_has_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
DUK_ASSERT_API_ENTRY(thr);
@@ -16555,7 +18056,7 @@ DUK_EXTERNAL duk_bool_t duk_has_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx
DUK_ASSERT_API_ENTRY(thr);
obj_idx = duk_require_normalize_index(thr, obj_idx);
- duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */
+ (void) duk_push_heapptr(thr, ptr); /* NULL -> 'undefined' */
return duk_has_prop(thr, obj_idx);
}
@@ -16594,7 +18095,7 @@ DUK_INTERNAL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_u
duk_hobject_define_property_internal(thr, obj, key, desc_flags);
- duk_pop(thr); /* pop key */
+ duk_pop(thr); /* pop key */
}
DUK_INTERNAL void duk_xdef_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx, duk_small_uint_t desc_flags) {
@@ -16627,12 +18128,13 @@ DUK_INTERNAL void duk_xdef_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_
}
DUK_INTERNAL void duk_xdef_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
- duk_xdef_prop_stridx(thr, (duk_idx_t) (duk_int8_t) (packed_args >> 24),
- (duk_small_uint_t) (packed_args >> 8) & 0xffffUL,
- (duk_small_uint_t) (packed_args & 0xffL));
+ duk_xdef_prop_stridx(thr,
+ (duk_idx_t) (duk_int8_t) (packed_args >> 24),
+ (duk_small_uint_t) (packed_args >> 8) & 0xffffUL,
+ (duk_small_uint_t) (packed_args & 0xffL));
}
-#if 0 /*unused*/
+#if 0 /*unused*/
DUK_INTERNAL void duk_xdef_prop_stridx_builtin(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags) {
duk_hobject *obj;
duk_hstring *key;
@@ -16664,15 +18166,15 @@ DUK_INTERNAL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_i
duk_push_hstring_stridx(thr, stridx);
duk_push_hobject_bidx(thr, DUK_BIDX_TYPE_ERROR_THROWER);
duk_dup_top(thr);
- duk_def_prop(thr, obj_idx, DUK_DEFPROP_HAVE_SETTER | DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_FORCE); /* attributes always 0 */
+ duk_def_prop(thr, obj_idx, DUK_DEFPROP_HAVE_SETTER | DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_FORCE); /* attributes always 0 */
}
/* Object.getOwnPropertyDescriptor() equivalent C binding. */
DUK_EXTERNAL void duk_get_prop_desc(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t flags) {
DUK_ASSERT_API_ENTRY(thr);
- DUK_UNREF(flags); /* no flags defined yet */
+ DUK_UNREF(flags); /* no flags defined yet */
- duk_hobject_object_get_own_property_descriptor(thr, obj_idx); /* [ ... key ] -> [ ... desc ] */
+ duk_hobject_object_get_own_property_descriptor(thr, obj_idx); /* [ ... key ] -> [ ... desc ] */
}
/* Object.defineProperty() equivalent C binding. */
@@ -16702,9 +18204,7 @@ DUK_EXTERNAL void duk_def_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t f
idx_base = duk_get_top_index(thr);
if (flags & DUK_DEFPROP_HAVE_SETTER) {
- duk_require_type_mask(thr, idx_base, DUK_TYPE_MASK_UNDEFINED |
- DUK_TYPE_MASK_OBJECT |
- DUK_TYPE_MASK_LIGHTFUNC);
+ duk_require_type_mask(thr, idx_base, DUK_TYPE_MASK_UNDEFINED | DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_LIGHTFUNC);
set = duk_get_hobject_promote_lfunc(thr, idx_base);
if (set != NULL && !DUK_HOBJECT_IS_CALLABLE(set)) {
goto fail_not_callable;
@@ -16714,9 +18214,7 @@ DUK_EXTERNAL void duk_def_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t f
set = NULL;
}
if (flags & DUK_DEFPROP_HAVE_GETTER) {
- duk_require_type_mask(thr, idx_base, DUK_TYPE_MASK_UNDEFINED |
- DUK_TYPE_MASK_OBJECT |
- DUK_TYPE_MASK_LIGHTFUNC);
+ duk_require_type_mask(thr, idx_base, DUK_TYPE_MASK_UNDEFINED | DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_LIGHTFUNC);
get = duk_get_hobject_promote_lfunc(thr, idx_base);
if (get != NULL && !DUK_HOBJECT_IS_CALLABLE(get)) {
goto fail_not_callable;
@@ -16736,14 +18234,7 @@ DUK_EXTERNAL void duk_def_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t f
duk_require_valid_index(thr, idx_base);
- duk_hobject_define_property_helper(thr,
- flags /*defprop_flags*/,
- obj,
- key,
- idx_value,
- get,
- set,
- 1 /*throw_flag*/);
+ duk_hobject_define_property_helper(thr, flags /*defprop_flags*/, obj, key, idx_value, get, set, 1 /*throw_flag*/);
/* Clean up stack */
@@ -16753,20 +18244,17 @@ DUK_EXTERNAL void duk_def_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t f
return;
- fail_invalid_desc:
+fail_invalid_desc:
DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
- return;
+ DUK_WO_NORETURN(return;);
- fail_not_callable:
+fail_not_callable:
DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
- return;
+ DUK_WO_NORETURN(return;);
}
/*
* Object related
- *
- * Note: seal() and freeze() are accessible through Ecmascript bindings,
- * and are not exposed through the API.
*/
DUK_EXTERNAL void duk_compact(duk_hthread *thr, duk_idx_t obj_idx) {
@@ -16794,7 +18282,7 @@ DUK_EXTERNAL void duk_enum(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t enum_
duk_dup(thr, obj_idx);
duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
- duk_hobject_enumerator_create(thr, enum_flags); /* [target] -> [enum] */
+ duk_hobject_enumerator_create(thr, enum_flags); /* [target] -> [enum] */
}
DUK_EXTERNAL duk_bool_t duk_next(duk_hthread *thr, duk_idx_t enum_index, duk_bool_t get_value) {
@@ -16855,8 +18343,9 @@ DUK_INTERNAL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_b
}
return;
- fail_cannot_freeze:
- DUK_ERROR_TYPE_INVALID_ARGS(thr); /* XXX: proper error message */
+fail_cannot_freeze:
+ DUK_ERROR_TYPE_INVALID_ARGS(thr); /* XXX: proper error message */
+ DUK_WO_NORETURN(return;);
}
DUK_EXTERNAL void duk_seal(duk_hthread *thr, duk_idx_t obj_idx) {
@@ -16900,8 +18389,8 @@ DUK_EXTERNAL void duk_put_number_list(duk_hthread *thr, duk_idx_t obj_idx, const
if (ent != NULL) {
while (ent->key != NULL) {
tv = thr->valstack_top++;
- DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv)); /* value stack init policy */
- DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, ent->value); /* no need for decref/incref */
+ DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv)); /* value stack init policy */
+ DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, ent->value); /* no need for decref/incref */
duk_put_prop_string(thr, obj_idx, ent->key);
ent++;
}
@@ -16940,6 +18429,37 @@ DUK_EXTERNAL duk_bool_t duk_get_global_lstring(duk_hthread *thr, const char *key
return ret;
}
+#if !defined(DUK_USE_PREFER_SIZE)
+DUK_EXTERNAL duk_bool_t duk_get_global_literal_raw(duk_hthread *thr, const char *key, duk_size_t key_len) {
+ duk_bool_t ret;
+
+ DUK_ASSERT_API_ENTRY(thr);
+ DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
+ DUK_ASSERT(key[key_len] == (char) 0);
+
+ /* XXX: direct implementation */
+
+ duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
+ ret = duk_get_prop_literal_raw(thr, -1, key, key_len);
+ duk_remove_m2(thr);
+ return ret;
+}
+#endif
+
+DUK_EXTERNAL duk_bool_t duk_get_global_heapptr(duk_hthread *thr, void *ptr) {
+ duk_bool_t ret;
+
+ DUK_ASSERT_API_ENTRY(thr);
+ DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
+
+ /* XXX: direct implementation */
+
+ duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
+ ret = duk_get_prop_heapptr(thr, -1, ptr);
+ duk_remove_m2(thr);
+ return ret;
+}
+
DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_hthread *thr, const char *key) {
duk_bool_t ret;
@@ -16950,7 +18470,7 @@ DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_hthread *thr, const char *key)
duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
duk_insert(thr, -2);
- ret = duk_put_prop_string(thr, -2, key); /* [ ... global val ] -> [ ... global ] */
+ ret = duk_put_prop_string(thr, -2, key); /* [ ... global val ] -> [ ... global ] */
duk_pop(thr);
return ret;
}
@@ -16965,12 +18485,62 @@ DUK_EXTERNAL duk_bool_t duk_put_global_lstring(duk_hthread *thr, const char *key
duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
duk_insert(thr, -2);
- ret = duk_put_prop_lstring(thr, -2, key, key_len); /* [ ... global val ] -> [ ... global ] */
+ ret = duk_put_prop_lstring(thr, -2, key, key_len); /* [ ... global val ] -> [ ... global ] */
+ duk_pop(thr);
+ return ret;
+}
+
+#if !defined(DUK_USE_PREFER_SIZE)
+DUK_EXTERNAL duk_bool_t duk_put_global_literal_raw(duk_hthread *thr, const char *key, duk_size_t key_len) {
+ duk_bool_t ret;
+
+ DUK_ASSERT_API_ENTRY(thr);
+ DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
+ DUK_ASSERT(key[key_len] == (char) 0);
+
+ /* XXX: direct implementation */
+
+ duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
+ duk_insert(thr, -2);
+ ret = duk_put_prop_literal_raw(thr, -2, key, key_len); /* [ ... global val ] -> [ ... global ] */
+ duk_pop(thr);
+ return ret;
+}
+#endif
+
+DUK_EXTERNAL duk_bool_t duk_put_global_heapptr(duk_hthread *thr, void *ptr) {
+ duk_bool_t ret;
+
+ DUK_ASSERT_API_ENTRY(thr);
+ DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
+
+ /* XXX: direct implementation */
+
+ duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
+ duk_insert(thr, -2);
+ ret = duk_put_prop_heapptr(thr, -2, ptr); /* [ ... global val ] -> [ ... global ] */
duk_pop(thr);
return ret;
}
/*
+ * ES2015 GetMethod()
+ */
+
+DUK_INTERNAL duk_bool_t duk_get_method_stridx(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t stridx) {
+ (void) duk_get_prop_stridx(thr, idx, stridx);
+ if (duk_is_null_or_undefined(thr, -1)) {
+ duk_pop_nodecref_unsafe(thr);
+ return 0;
+ }
+ if (!duk_is_callable(thr, -1)) {
+ DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
+ DUK_WO_NORETURN(return 0;);
+ }
+ return 1;
+}
+
+/*
* Object prototype
*/
@@ -17000,15 +18570,14 @@ DUK_EXTERNAL void duk_set_prototype(duk_hthread *thr, duk_idx_t idx) {
obj = duk_require_hobject(thr, idx);
DUK_ASSERT(obj != NULL);
- duk_require_type_mask(thr, -1, DUK_TYPE_MASK_UNDEFINED |
- DUK_TYPE_MASK_OBJECT);
+ duk_require_type_mask(thr, -1, DUK_TYPE_MASK_UNDEFINED | DUK_TYPE_MASK_OBJECT);
proto = duk_get_hobject(thr, -1);
/* proto can also be NULL here (allowed explicitly) */
#if defined(DUK_USE_ROM_OBJECTS)
if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
- DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE); /* XXX: "read only object"? */
- return;
+ DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE); /* XXX: "read only object"? */
+ DUK_WO_NORETURN(return;);
}
#endif
@@ -17017,6 +18586,37 @@ DUK_EXTERNAL void duk_set_prototype(duk_hthread *thr, duk_idx_t idx) {
duk_pop(thr);
}
+DUK_INTERNAL void duk_clear_prototype(duk_hthread *thr, duk_idx_t idx) {
+ duk_hobject *obj;
+
+ DUK_ASSERT_API_ENTRY(thr);
+
+ obj = duk_require_hobject(thr, idx);
+ DUK_ASSERT(obj != NULL);
+
+#if defined(DUK_USE_ROM_OBJECTS)
+ if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
+ DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE); /* XXX: "read only object"? */
+ DUK_WO_NORETURN(return;);
+ }
+#endif
+
+ DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, NULL);
+}
+
+DUK_INTERNAL duk_bool_t duk_is_bare_object(duk_hthread *thr, duk_idx_t idx) {
+ duk_hobject *obj;
+ duk_hobject *proto;
+
+ DUK_ASSERT_API_ENTRY(thr);
+
+ obj = duk_require_hobject(thr, idx);
+ DUK_ASSERT(obj != NULL);
+
+ proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);
+ return (proto == NULL);
+}
+
/*
* Object finalizer
*/
@@ -17030,6 +18630,10 @@ DUK_EXTERNAL void duk_set_prototype(duk_hthread *thr, duk_idx_t idx) {
DUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
+ /* This get intentionally walks the inheritance chain at present,
+ * which matches how the effective finalizer property is also
+ * looked up in GC.
+ */
duk_get_prop_stridx(thr, idx, DUK_STRIDX_INT_FINALIZER);
}
@@ -17039,8 +18643,14 @@ DUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
- h = duk_require_hobject(thr, idx); /* Get before 'put' so that 'idx' is correct. */
+ h = duk_require_hobject(thr, idx); /* Get before 'put' so that 'idx' is correct. */
callable = duk_is_callable(thr, -1);
+
+ /* At present finalizer is stored as a hidden Symbol, with normal
+ * inheritance and access control. As a result, finalizer cannot
+ * currently be set on a non-extensible (sealed or frozen) object.
+ * It might be useful to allow it.
+ */
duk_put_prop_stridx(thr, idx, DUK_STRIDX_INT_FINALIZER);
/* In addition to setting the finalizer property, keep a "have
@@ -17060,19 +18670,30 @@ DUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) {
DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h);
}
}
-#else /* DUK_USE_FINALIZER_SUPPORT */
+#else /* DUK_USE_FINALIZER_SUPPORT */
DUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
DUK_UNREF(idx);
DUK_ERROR_UNSUPPORTED(thr);
+ DUK_WO_NORETURN(return;);
}
DUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
DUK_UNREF(idx);
DUK_ERROR_UNSUPPORTED(thr);
+ DUK_WO_NORETURN(return;);
+}
+#endif /* DUK_USE_FINALIZER_SUPPORT */
+/*
+ * Random numbers
+ */
+
+/* #include duk_internal.h -> already included */
+
+DUK_EXTERNAL duk_double_t duk_random(duk_hthread *thr) {
+ return (duk_double_t) duk_util_get_random_double(thr);
}
-#endif /* DUK_USE_FINALIZER_SUPPORT */
/*
* API calls related to general value stack manipulation: resizing the value
* stack, pushing and popping values, type checking and reading values,
@@ -17091,7 +18712,8 @@ DUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) {
* Forward declarations
*/
-DUK_LOCAL_DECL duk_idx_t duk__push_c_function_raw(duk_hthread *thr, duk_c_function func, duk_idx_t nargs, duk_uint_t flags, duk_small_uint_t proto_bidx);
+DUK_LOCAL_DECL duk_idx_t
+duk__push_c_function_raw(duk_hthread *thr, duk_c_function func, duk_idx_t nargs, duk_uint_t flags, duk_small_uint_t proto_bidx);
/*
* Global state for working around missing variadic macros
@@ -17106,41 +18728,24 @@ DUK_EXTERNAL duk_int_t duk_api_global_line = 0;
* Misc helpers
*/
-DUK_LOCAL const char * const duk__symbol_type_strings[4] = {
- "hidden", "global", "local", "wellknown"
-};
+DUK_LOCAL const char * const duk__symbol_type_strings[4] = { "hidden", "global", "local", "wellknown" };
#if !defined(DUK_USE_PACKED_TVAL)
DUK_LOCAL const duk_uint_t duk__type_from_tag[] = {
- DUK_TYPE_NUMBER,
- DUK_TYPE_NUMBER, /* fastint */
- DUK_TYPE_UNDEFINED,
- DUK_TYPE_NULL,
- DUK_TYPE_BOOLEAN,
- DUK_TYPE_POINTER,
- DUK_TYPE_LIGHTFUNC,
- DUK_TYPE_NONE,
- DUK_TYPE_STRING,
- DUK_TYPE_OBJECT,
- DUK_TYPE_BUFFER,
+ DUK_TYPE_NUMBER, DUK_TYPE_NUMBER, /* fastint */
+ DUK_TYPE_UNDEFINED, DUK_TYPE_NULL, DUK_TYPE_BOOLEAN, DUK_TYPE_POINTER, DUK_TYPE_LIGHTFUNC,
+ DUK_TYPE_NONE, DUK_TYPE_STRING, DUK_TYPE_OBJECT, DUK_TYPE_BUFFER,
};
DUK_LOCAL const duk_uint_t duk__type_mask_from_tag[] = {
- DUK_TYPE_MASK_NUMBER,
- DUK_TYPE_MASK_NUMBER, /* fastint */
- DUK_TYPE_MASK_UNDEFINED,
- DUK_TYPE_MASK_NULL,
- DUK_TYPE_MASK_BOOLEAN,
- DUK_TYPE_MASK_POINTER,
- DUK_TYPE_MASK_LIGHTFUNC,
- DUK_TYPE_MASK_NONE,
- DUK_TYPE_MASK_STRING,
- DUK_TYPE_MASK_OBJECT,
- DUK_TYPE_MASK_BUFFER,
+ DUK_TYPE_MASK_NUMBER, DUK_TYPE_MASK_NUMBER, /* fastint */
+ DUK_TYPE_MASK_UNDEFINED, DUK_TYPE_MASK_NULL, DUK_TYPE_MASK_BOOLEAN, DUK_TYPE_MASK_POINTER, DUK_TYPE_MASK_LIGHTFUNC,
+ DUK_TYPE_MASK_NONE, DUK_TYPE_MASK_STRING, DUK_TYPE_MASK_OBJECT, DUK_TYPE_MASK_BUFFER,
};
-#endif /* !DUK_USE_PACKED_TVAL */
+#endif /* !DUK_USE_PACKED_TVAL */
/* Assert that there's room for one value. */
-#define DUK__ASSERT_SPACE() do { \
+#define DUK__ASSERT_SPACE() \
+ do { \
DUK_ASSERT(!(thr->valstack_top >= thr->valstack_end)); \
} while (0)
@@ -17149,7 +18754,8 @@ DUK_LOCAL const duk_uint_t duk__type_mask_from_tag[] = {
/* Faster but value stack overruns are memory unsafe. */
#define DUK__CHECK_SPACE() DUK__ASSERT_SPACE()
#else
-#define DUK__CHECK_SPACE() do { \
+#define DUK__CHECK_SPACE() \
+ do { \
if (DUK_UNLIKELY(thr->valstack_top >= thr->valstack_end)) { \
DUK_ERROR_RANGE_PUSH_BEYOND(thr); \
} \
@@ -17162,7 +18768,7 @@ DUK_LOCAL duk_small_uint_t duk__get_symbol_type(duk_hstring *h) {
DUK_ASSERT(h != NULL);
DUK_ASSERT(DUK_HSTRING_HAS_SYMBOL(h));
- DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h) >= 1); /* always true, symbol prefix */
+ DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h) >= 1); /* always true, symbol prefix */
data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
len = DUK_HSTRING_GET_BYTELEN(h);
@@ -17247,7 +18853,7 @@ DUK_LOCAL duk_int_t duk__api_coerce_d2i(duk_hthread *thr, duk_idx_t idx, duk_int
if (require) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
- /* not reachable */
+ DUK_WO_NORETURN(return 0;);
}
return def_value;
@@ -17298,7 +18904,7 @@ DUK_LOCAL duk_uint_t duk__api_coerce_d2ui(duk_hthread *thr, duk_idx_t idx, duk_u
if (require) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
- /* not reachable */
+ DUK_WO_NORETURN(return 0;);
}
return def_value;
@@ -17329,7 +18935,7 @@ DUK_EXTERNAL duk_idx_t duk_normalize_index(duk_hthread *thr, duk_idx_t idx) {
/* Assume value stack sizes (in elements) fits into duk_idx_t. */
DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
- DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
if (idx < 0) {
uidx = vs_size + (duk_uidx_t) idx;
@@ -17357,7 +18963,7 @@ DUK_EXTERNAL duk_idx_t duk_require_normalize_index(duk_hthread *thr, duk_idx_t i
DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
- DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
if (idx < 0) {
uidx = vs_size + (duk_uidx_t) idx;
@@ -17373,7 +18979,7 @@ DUK_EXTERNAL duk_idx_t duk_require_normalize_index(duk_hthread *thr, duk_idx_t i
return (duk_idx_t) uidx;
}
DUK_ERROR_RANGE_INDEX(thr, idx);
- return 0; /* unreachable */
+ DUK_WO_NORETURN(return 0;);
}
DUK_INTERNAL duk_tval *duk_get_tval(duk_hthread *thr, duk_idx_t idx) {
@@ -17385,7 +18991,7 @@ DUK_INTERNAL duk_tval *duk_get_tval(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
- DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
if (idx < 0) {
uidx = vs_size + (duk_uidx_t) idx;
@@ -17432,7 +19038,7 @@ DUK_INTERNAL duk_tval *duk_require_tval(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
- DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
/* Use unsigned arithmetic to optimize comparison. */
if (idx < 0) {
@@ -17449,7 +19055,7 @@ DUK_INTERNAL duk_tval *duk_require_tval(duk_hthread *thr, duk_idx_t idx) {
return thr->valstack_bottom + uidx;
}
DUK_ERROR_RANGE_INDEX(thr, idx);
- return NULL;
+ DUK_WO_NORETURN(return NULL;);
}
/* Non-critical. */
@@ -17467,7 +19073,7 @@ DUK_EXTERNAL void duk_require_valid_index(duk_hthread *thr, duk_idx_t idx) {
if (DUK_UNLIKELY(duk_normalize_index(thr, idx) < 0)) {
DUK_ERROR_RANGE_INDEX(thr, idx);
- return; /* unreachable */
+ DUK_WO_NORETURN(return;);
}
}
@@ -17492,6 +19098,7 @@ DUK_INTERNAL duk_idx_t duk_get_top_require_min(duk_hthread *thr, duk_idx_t min_t
ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
if (DUK_UNLIKELY(ret < min_top)) {
DUK_ERROR_TYPE_INVALID_ARGS(thr);
+ DUK_WO_NORETURN(return 0;);
}
return ret;
}
@@ -17536,7 +19143,7 @@ DUK_EXTERNAL void duk_set_top(duk_hthread *thr, duk_idx_t idx) {
#else
if (DUK_UNLIKELY(uidx > vs_limit)) {
DUK_ERROR_RANGE_INDEX(thr, idx);
- return; /* unreachable */
+ DUK_WO_NORETURN(return;);
}
#endif
DUK_ASSERT(uidx <= vs_limit);
@@ -17570,7 +19177,7 @@ DUK_EXTERNAL void duk_set_top(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT(count > 0);
tv = thr->valstack_top;
tv_end = tv - count;
- DUK_ASSERT(tv > tv_end); /* Because count > 0. */
+ DUK_ASSERT(tv > tv_end); /* Because count > 0. */
do {
tv--;
DUK_ASSERT(tv >= thr->valstack_bottom);
@@ -17578,7 +19185,7 @@ DUK_EXTERNAL void duk_set_top(duk_hthread *thr, duk_idx_t idx) {
} while (tv != tv_end);
thr->valstack_top = tv_end;
DUK_REFZERO_CHECK_FAST(thr);
-#else /* DUK_USE_REFERENCE_COUNTING */
+#else /* DUK_USE_REFERENCE_COUNTING */
duk_uidx_t count;
duk_tval *tv_end;
@@ -17591,7 +19198,7 @@ DUK_EXTERNAL void duk_set_top(duk_hthread *thr, duk_idx_t idx) {
DUK_TVAL_SET_UNDEFINED(tv);
} while (tv != tv_end);
thr->valstack_top = tv_end;
-#endif /* DUK_USE_REFERENCE_COUNTING */
+#endif /* DUK_USE_REFERENCE_COUNTING */
}
}
@@ -17602,7 +19209,7 @@ DUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {
duk_set_top(thr, idx);
}
-#else /* DUK_USE_PREFER_SIZE */
+#else /* DUK_USE_PREFER_SIZE */
DUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {
duk_uidx_t uidx;
duk_uidx_t vs_size;
@@ -17641,7 +19248,7 @@ DUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT(count > 0);
tv = thr->valstack_top;
tv_end = tv - count;
- DUK_ASSERT(tv > tv_end); /* Because count > 0. */
+ DUK_ASSERT(tv > tv_end); /* Because count > 0. */
do {
tv--;
DUK_ASSERT(tv >= thr->valstack_bottom);
@@ -17649,7 +19256,7 @@ DUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {
} while (tv != tv_end);
thr->valstack_top = tv_end;
DUK_REFZERO_CHECK_FAST(thr);
-#else /* DUK_USE_REFERENCE_COUNTING */
+#else /* DUK_USE_REFERENCE_COUNTING */
duk_uidx_t count;
duk_tval *tv_end;
@@ -17662,10 +19269,10 @@ DUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {
DUK_TVAL_SET_UNDEFINED(tv);
} while (tv != tv_end);
thr->valstack_top = tv_end;
-#endif /* DUK_USE_REFERENCE_COUNTING */
+#endif /* DUK_USE_REFERENCE_COUNTING */
}
}
-#endif /* DUK_USE_PREFER_SIZE */
+#endif /* DUK_USE_PREFER_SIZE */
/* Internal helper: set top to 'top', and set [idx_wipe_start,top[ to
* 'undefined' (doing nothing if idx_wipe_start == top). Indices are
@@ -17719,7 +19326,7 @@ DUK_EXTERNAL duk_idx_t duk_require_top_index(duk_hthread *thr) {
ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
if (DUK_UNLIKELY(ret < 0)) {
DUK_ERROR_RANGE_INDEX(thr, -1);
- return 0; /* unreachable */
+ DUK_WO_NORETURN(return 0;);
}
return ret;
}
@@ -17760,14 +19367,14 @@ DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__resize_valstack(duk_hthread *thr
duk_tval *tv_prev_alloc_end;
duk_tval *p;
- DUK_ASSERT_HTHREAD_VALID(thr);
+ DUK_HTHREAD_ASSERT_VALID(thr);
DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
- DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) <= new_size); /* can't resize below 'top' */
- DUK_ASSERT(new_size <= DUK_USE_VALSTACK_LIMIT); /* valstack limit caller has check, prevents wrapping */
- DUK_ASSERT(new_size <= DUK_SIZE_MAX / sizeof(duk_tval)); /* specific assert for wrapping */
+ DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) <= new_size); /* can't resize below 'top' */
+ DUK_ASSERT(new_size <= DUK_USE_VALSTACK_LIMIT); /* valstack limit caller has check, prevents wrapping */
+ DUK_ASSERT(new_size <= DUK_SIZE_MAX / sizeof(duk_tval)); /* specific assert for wrapping */
/* Pre-realloc pointer copies for asserts and debug logs. */
pre_valstack = thr->valstack;
@@ -17802,7 +19409,8 @@ DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__resize_valstack(duk_hthread *thr
*/
DUK_ASSERT(new_size != 0);
DUK_D(DUK_DPRINT("failed to resize valstack to %lu entries (%lu bytes)",
- (unsigned long) new_size, (unsigned long) new_alloc_size));
+ (unsigned long) new_size,
+ (unsigned long) new_alloc_size));
return 0;
}
@@ -17813,23 +19421,28 @@ DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__resize_valstack(duk_hthread *thr
#if defined(DUK_USE_DEBUG)
if (thr->valstack != pre_valstack) {
DUK_D(DUK_DPRINT("valstack base pointer changed during valstack resize: %p -> %p",
- (void *) pre_valstack, (void *) thr->valstack));
+ (void *) pre_valstack,
+ (void *) thr->valstack));
}
if (thr->valstack_bottom != pre_bottom) {
DUK_D(DUK_DPRINT("valstack bottom pointer changed during valstack resize: %p -> %p",
- (void *) pre_bottom, (void *) thr->valstack_bottom));
+ (void *) pre_bottom,
+ (void *) thr->valstack_bottom));
}
if (thr->valstack_top != pre_top) {
DUK_D(DUK_DPRINT("valstack top pointer changed during valstack resize: %p -> %p",
- (void *) pre_top, (void *) thr->valstack_top));
+ (void *) pre_top,
+ (void *) thr->valstack_top));
}
if (thr->valstack_end != pre_end) {
DUK_D(DUK_DPRINT("valstack end pointer changed during valstack resize: %p -> %p",
- (void *) pre_end, (void *) thr->valstack_end));
+ (void *) pre_end,
+ (void *) thr->valstack_end));
}
if (thr->valstack_alloc_end != pre_alloc_end) {
DUK_D(DUK_DPRINT("valstack alloc_end pointer changed during valstack resize: %p -> %p",
- (void *) pre_alloc_end, (void *) thr->valstack_alloc_end));
+ (void *) pre_alloc_end,
+ (void *) thr->valstack_alloc_end));
}
#endif
@@ -17868,12 +19481,22 @@ DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__resize_valstack(duk_hthread *thr
(unsigned long) new_size,
(unsigned long) ((duk_uint8_t *) pre_alloc_end - (duk_uint8_t *) pre_valstack),
(unsigned long) new_alloc_size,
- (void *) pre_valstack, (void *) thr->valstack,
- (void *) pre_bottom, (void *) thr->valstack_bottom, (long) (thr->valstack_bottom - thr->valstack),
- (void *) pre_top, (void *) thr->valstack_top, (long) (thr->valstack_top - thr->valstack),
- (void *) pre_end, (void *) thr->valstack_end, (long) (thr->valstack_end - thr->valstack),
- (void *) pre_alloc_end, (void *) thr->valstack_alloc_end, (long) (thr->valstack_alloc_end - thr->valstack),
- (void *) tv_prev_alloc_end, (long) (thr->valstack_alloc_end - tv_prev_alloc_end)));
+ (void *) pre_valstack,
+ (void *) thr->valstack,
+ (void *) pre_bottom,
+ (void *) thr->valstack_bottom,
+ (long) (thr->valstack_bottom - thr->valstack),
+ (void *) pre_top,
+ (void *) thr->valstack_top,
+ (long) (thr->valstack_top - thr->valstack),
+ (void *) pre_end,
+ (void *) thr->valstack_end,
+ (long) (thr->valstack_end - thr->valstack),
+ (void *) pre_alloc_end,
+ (void *) thr->valstack_alloc_end,
+ (long) (thr->valstack_alloc_end - thr->valstack),
+ (void *) tv_prev_alloc_end,
+ (long) (thr->valstack_alloc_end - tv_prev_alloc_end)));
/* If allocation grew, init any new slots to 'undefined'. */
p = tv_prev_alloc_end;
@@ -17900,7 +19523,7 @@ DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__valstack_grow(duk_hthread *thr,
duk_size_t new_size;
DUK_ASSERT(min_bytes / sizeof(duk_tval) * sizeof(duk_tval) == min_bytes);
- min_size = min_bytes / sizeof(duk_tval); /* from bytes to slots */
+ min_size = min_bytes / sizeof(duk_tval); /* from bytes to slots */
#if defined(DUK_USE_VALSTACK_GROW_SHIFT)
/* New size is minimum size plus a proportional slack, e.g. shift of
@@ -17920,6 +19543,7 @@ DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__valstack_grow(duk_hthread *thr,
*/
if (throw_on_error) {
DUK_ERROR_RANGE(thr, DUK_STR_VALSTACK_LIMIT);
+ DUK_WO_NORETURN(return 0;);
}
return 0;
}
@@ -17927,6 +19551,7 @@ DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__valstack_grow(duk_hthread *thr,
if (duk__resize_valstack(thr, new_size) == 0) {
if (throw_on_error) {
DUK_ERROR_ALLOC_FAILED(thr);
+ DUK_WO_NORETURN(return 0;);
}
return 0;
}
@@ -18015,17 +19640,18 @@ DUK_INTERNAL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t
#else
slack = 0;
#endif
- shrink_bytes = reserve_bytes +
- slack / sizeof(duk_tval) * sizeof(duk_tval); /* multiple of duk_tval */
+ shrink_bytes = reserve_bytes + slack / sizeof(duk_tval) * sizeof(duk_tval); /* multiple of duk_tval */
}
-#else /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */
+#else /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */
/* Always snug, useful in some low memory environments. */
DUK_UNREF(snug);
shrink_bytes = reserve_bytes;
-#endif /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */
+#endif /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */
DUK_D(DUK_DPRINT("valstack shrink check: alloc_bytes=%ld, reserve_bytes=%ld, shrink_bytes=%ld (unvalidated)",
- (long) alloc_bytes, (long) reserve_bytes, (long) shrink_bytes));
+ (long) alloc_bytes,
+ (long) reserve_bytes,
+ (long) shrink_bytes));
DUK_ASSERT(shrink_bytes >= reserve_bytes);
if (shrink_bytes >= alloc_bytes) {
/* Skip if shrink target is same as current one (or higher,
@@ -18172,7 +19798,7 @@ DUK_EXTERNAL void duk_dup(duk_hthread *thr, duk_idx_t from_idx) {
DUK_ASSERT(tv_from != NULL);
DUK_ASSERT(tv_to != NULL);
DUK_TVAL_SET_TVAL(tv_to, tv_from);
- DUK_TVAL_INCREF(thr, tv_to); /* no side effects */
+ DUK_TVAL_INCREF(thr, tv_to); /* no side effects */
}
DUK_EXTERNAL void duk_dup_top(duk_hthread *thr) {
@@ -18187,14 +19813,14 @@ DUK_EXTERNAL void duk_dup_top(duk_hthread *thr) {
if (DUK_UNLIKELY(thr->valstack_top - thr->valstack_bottom <= 0)) {
DUK_ERROR_RANGE_INDEX(thr, -1);
- return; /* unreachable */
+ DUK_WO_NORETURN(return;);
}
tv_from = thr->valstack_top - 1;
tv_to = thr->valstack_top++;
DUK_ASSERT(tv_from != NULL);
DUK_ASSERT(tv_to != NULL);
DUK_TVAL_SET_TVAL(tv_to, tv_from);
- DUK_TVAL_INCREF(thr, tv_to); /* no side effects */
+ DUK_TVAL_INCREF(thr, tv_to); /* no side effects */
#endif
}
@@ -18244,28 +19870,25 @@ DUK_EXTERNAL void duk_insert(duk_hthread *thr, duk_idx_t to_idx) {
* => [ ... | q | p | x | x ]
*/
- nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p)); /* Note: 'q' is top-1 */
+ nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));
DUK_DDD(DUK_DDDPRINT("duk_insert: to_idx=%ld, p=%p, q=%p, nbytes=%lu",
- (long) to_idx, (void *) p, (void *) q, (unsigned long) nbytes));
-
- /* No net refcount changes. */
+ (long) to_idx,
+ (void *) p,
+ (void *) q,
+ (unsigned long) nbytes));
- if (nbytes > 0) {
- DUK_TVAL_SET_TVAL(&tv_tmp, q);
- DUK_ASSERT(nbytes > 0);
- DUK_MEMMOVE((void *) (p + 1), (const void *) p, (size_t) nbytes);
- DUK_TVAL_SET_TVAL(p, &tv_tmp);
- } else {
- /* nop: insert top to top */
- DUK_ASSERT(nbytes == 0);
- DUK_ASSERT(p == q);
- }
+ /* No net refcount changes. No need to special case nbytes == 0
+ * (p == q).
+ */
+ DUK_TVAL_SET_TVAL(&tv_tmp, q);
+ duk_memmove((void *) (p + 1), (const void *) p, (size_t) nbytes);
+ DUK_TVAL_SET_TVAL(p, &tv_tmp);
}
DUK_INTERNAL void duk_insert_undefined(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
- DUK_ASSERT(idx >= 0); /* Doesn't support negative indices. */
+ DUK_ASSERT(idx >= 0); /* Doesn't support negative indices. */
duk_push_undefined(thr);
duk_insert(thr, idx);
@@ -18275,7 +19898,7 @@ DUK_INTERNAL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_id
duk_tval *tv, *tv_end;
DUK_ASSERT_API_ENTRY(thr);
- DUK_ASSERT(idx >= 0); /* Doesn't support negative indices or count. */
+ DUK_ASSERT(idx >= 0); /* Doesn't support negative indices or count. */
DUK_ASSERT(count >= 0);
tv = duk_reserve_gap(thr, idx, count);
@@ -18286,6 +19909,43 @@ DUK_INTERNAL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_id
}
}
+DUK_EXTERNAL void duk_pull(duk_hthread *thr, duk_idx_t from_idx) {
+ duk_tval *p;
+ duk_tval *q;
+ duk_tval tv_tmp;
+ duk_size_t nbytes;
+
+ DUK_ASSERT_API_ENTRY(thr);
+
+ /* nbytes
+ * <--------->
+ * [ ... | x | x | p | y | y | q ]
+ * => [ ... | x | x | y | y | q | p ]
+ */
+
+ p = duk_require_tval(thr, from_idx);
+ DUK_ASSERT(p != NULL);
+ q = duk_require_tval(thr, -1);
+ DUK_ASSERT(q != NULL);
+
+ DUK_ASSERT(q >= p);
+
+ nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));
+
+ DUK_DDD(DUK_DDDPRINT("duk_pull: from_idx=%ld, p=%p, q=%p, nbytes=%lu",
+ (long) from_idx,
+ (void *) p,
+ (void *) q,
+ (unsigned long) nbytes));
+
+ /* No net refcount changes. No need to special case nbytes == 0
+ * (p == q).
+ */
+ DUK_TVAL_SET_TVAL(&tv_tmp, p);
+ duk_memmove((void *) p, (const void *) (p + 1), (size_t) nbytes);
+ DUK_TVAL_SET_TVAL(q, &tv_tmp);
+}
+
DUK_EXTERNAL void duk_replace(duk_hthread *thr, duk_idx_t to_idx) {
duk_tval *tv1;
duk_tval *tv2;
@@ -18305,7 +19965,7 @@ DUK_EXTERNAL void duk_replace(duk_hthread *thr, duk_idx_t to_idx) {
DUK_TVAL_SET_TVAL(tv2, tv1);
DUK_TVAL_SET_UNDEFINED(tv1);
thr->valstack_top--;
- DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
+ DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
}
DUK_EXTERNAL void duk_copy(duk_hthread *thr, duk_idx_t from_idx, duk_idx_t to_idx) {
@@ -18320,7 +19980,7 @@ DUK_EXTERNAL void duk_copy(duk_hthread *thr, duk_idx_t from_idx, duk_idx_t to_id
DUK_ASSERT(tv2 != NULL);
/* For tv1 == tv2, this is a no-op (no explicit check needed). */
- DUK_TVAL_SET_TVAL_UPDREF(thr, tv2, tv1); /* side effects */
+ DUK_TVAL_SET_TVAL_UPDREF(thr, tv2, tv1); /* side effects */
}
DUK_EXTERNAL void duk_remove(duk_hthread *thr, duk_idx_t idx) {
@@ -18351,21 +20011,21 @@ DUK_EXTERNAL void duk_remove(duk_hthread *thr, duk_idx_t idx) {
DUK_TVAL_SET_TVAL(&tv_tmp, p);
#endif
- nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p)); /* Note: 'q' is top-1 */
- DUK_MEMMOVE((void *) p, (const void *) (p + 1), (size_t) nbytes); /* zero size not an issue: pointers are valid */
+ nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p)); /* Note: 'q' is top-1 */
+ duk_memmove((void *) p, (const void *) (p + 1), (size_t) nbytes);
DUK_TVAL_SET_UNDEFINED(q);
thr->valstack_top--;
#if defined(DUK_USE_REFERENCE_COUNTING)
- DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
+ DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
#endif
}
DUK_INTERNAL void duk_remove_unsafe(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
- duk_remove(thr, idx); /* XXX: no optimization for now */
+ duk_remove(thr, idx); /* XXX: no optimization for now */
}
DUK_INTERNAL void duk_remove_m2(duk_hthread *thr) {
@@ -18384,7 +20044,7 @@ DUK_INTERNAL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count)
while (count-- > 0) {
duk_remove(thr, idx);
}
-#else /* DUK_USE_PREFER_SIZE */
+#else /* DUK_USE_PREFER_SIZE */
duk_tval *tv_src;
duk_tval *tv_dst;
duk_tval *tv_newtop;
@@ -18405,7 +20065,7 @@ DUK_INTERNAL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count)
DUK_TVAL_DECREF_NORZ(thr, tv);
}
- DUK_MEMMOVE((void *) tv_dst, (const void *) tv_src, bytes);
+ duk_memmove((void *) tv_dst, (const void *) tv_src, bytes);
tv_newtop = thr->valstack_top - count;
for (tv = tv_newtop; tv < thr->valstack_top; tv++) {
@@ -18416,13 +20076,13 @@ DUK_INTERNAL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count)
/* When not preferring size, only NORZ macros are used; caller
* is expected to DUK_REFZERO_CHECK().
*/
-#endif /* DUK_USE_PREFER_SIZE */
+#endif /* DUK_USE_PREFER_SIZE */
}
DUK_INTERNAL void duk_remove_n_unsafe(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
DUK_ASSERT_API_ENTRY(thr);
- duk_remove_n(thr, idx, count); /* XXX: no optimization for now */
+ duk_remove_n(thr, idx, count); /* XXX: no optimization for now */
}
/*
@@ -18438,20 +20098,20 @@ DUK_EXTERNAL void duk_xcopymove_raw(duk_hthread *to_thr, duk_hthread *from_thr,
/* XXX: several pointer comparison issues here */
DUK_ASSERT_API_ENTRY(to_thr);
- DUK_ASSERT_CTX_VALID(to_thr);
- DUK_ASSERT_CTX_VALID(from_thr);
+ DUK_CTX_ASSERT_VALID(to_thr);
+ DUK_CTX_ASSERT_VALID(from_thr);
DUK_ASSERT(to_thr->heap == from_thr->heap);
if (DUK_UNLIKELY(to_thr == from_thr)) {
DUK_ERROR_TYPE(to_thr, DUK_STR_INVALID_CONTEXT);
- return;
+ DUK_WO_NORETURN(return;);
}
if (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) DUK_USE_VALSTACK_LIMIT)) {
/* Maximum value check ensures 'nbytes' won't wrap below.
* Also handles negative count.
*/
DUK_ERROR_RANGE_INVALID_COUNT(to_thr);
- return;
+ DUK_WO_NORETURN(return;);
}
DUK_ASSERT(count >= 0);
@@ -18462,17 +20122,19 @@ DUK_EXTERNAL void duk_xcopymove_raw(duk_hthread *to_thr, duk_hthread *from_thr,
DUK_ASSERT(to_thr->valstack_top <= to_thr->valstack_end);
if (DUK_UNLIKELY((duk_size_t) ((duk_uint8_t *) to_thr->valstack_end - (duk_uint8_t *) to_thr->valstack_top) < nbytes)) {
DUK_ERROR_RANGE_PUSH_BEYOND(to_thr);
+ DUK_WO_NORETURN(return;);
}
src = (void *) ((duk_uint8_t *) from_thr->valstack_top - nbytes);
if (DUK_UNLIKELY(src < (void *) from_thr->valstack_bottom)) {
DUK_ERROR_RANGE_INVALID_COUNT(to_thr);
+ DUK_WO_NORETURN(return;);
}
- /* copy values (no overlap even if to_thr == from_thr; that's not
- * allowed now anyway)
+ /* Copy values (no overlap even if to_thr == from_thr; that's not
+ * allowed now anyway).
*/
DUK_ASSERT(nbytes > 0);
- DUK_MEMCPY((void *) to_thr->valstack_top, (const void *) src, (size_t) nbytes);
+ duk_memcpy((void *) to_thr->valstack_top, (const void *) src, (size_t) nbytes);
p = to_thr->valstack_top;
to_thr->valstack_top = (duk_tval *) (void *) (((duk_uint8_t *) p) + nbytes);
@@ -18481,7 +20143,7 @@ DUK_EXTERNAL void duk_xcopymove_raw(duk_hthread *to_thr, duk_hthread *from_thr,
/* Incref copies, keep originals. */
q = to_thr->valstack_top;
while (p < q) {
- DUK_TVAL_INCREF(to_thr, p); /* no side effects */
+ DUK_TVAL_INCREF(to_thr, p); /* no side effects */
p++;
}
} else {
@@ -18521,7 +20183,7 @@ DUK_INTERNAL duk_tval *duk_reserve_gap(duk_hthread *thr, duk_idx_t idx_base, duk
tv_dst = (duk_tval *) (void *) ((duk_uint8_t *) tv_src + gap_bytes);
copy_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) tv_src);
thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_top + gap_bytes);
- DUK_MEMMOVE((void *) tv_dst, (const void *) tv_src, copy_bytes);
+ duk_memmove((void *) tv_dst, (const void *) tv_src, copy_bytes);
/* Values in the gap are left as garbage: caller must fill them in
* and INCREF them before any side effects.
@@ -18542,6 +20204,7 @@ DUK_EXTERNAL void duk_require_undefined(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT(tv != NULL);
if (DUK_UNLIKELY(!DUK_TVAL_IS_UNDEFINED(tv))) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "undefined", DUK_STR_NOT_UNDEFINED);
+ DUK_WO_NORETURN(return;);
}
}
@@ -18554,6 +20217,7 @@ DUK_EXTERNAL void duk_require_null(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT(tv != NULL);
if (DUK_UNLIKELY(!DUK_TVAL_IS_NULL(tv))) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "null", DUK_STR_NOT_NULL);
+ DUK_WO_NORETURN(return;);
}
}
@@ -18561,7 +20225,7 @@ DUK_LOCAL DUK_ALWAYS_INLINE duk_bool_t duk__get_boolean_raw(duk_hthread *thr, du
duk_bool_t ret;
duk_tval *tv;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
tv = duk_get_tval_or_unused(thr, idx);
DUK_ASSERT(tv != NULL);
@@ -18579,7 +20243,7 @@ DUK_LOCAL DUK_ALWAYS_INLINE duk_bool_t duk__get_boolean_raw(duk_hthread *thr, du
DUK_EXTERNAL duk_bool_t duk_get_boolean(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
- return duk__get_boolean_raw(thr, idx, 0); /* default: false */
+ return duk__get_boolean_raw(thr, idx, 0); /* default: false */
}
DUK_EXTERNAL duk_bool_t duk_get_boolean_default(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
@@ -18602,6 +20266,7 @@ DUK_EXTERNAL duk_bool_t duk_require_boolean(duk_hthread *thr, duk_idx_t idx) {
return ret;
} else {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "boolean", DUK_STR_NOT_BOOLEAN);
+ DUK_WO_NORETURN(return 0;);
}
}
@@ -18618,17 +20283,16 @@ DUK_LOCAL DUK_ALWAYS_INLINE duk_double_t duk__get_number_raw(duk_hthread *thr, d
duk_double_union ret;
duk_tval *tv;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
tv = duk_get_tval_or_unused(thr, idx);
DUK_ASSERT(tv != NULL);
#if defined(DUK_USE_FASTINT)
if (DUK_TVAL_IS_FASTINT(tv)) {
- ret.d = (duk_double_t) DUK_TVAL_GET_FASTINT(tv); /* XXX: cast trick */
- }
- else
+ ret.d = (duk_double_t) DUK_TVAL_GET_FASTINT(tv); /* XXX: cast trick */
+ } else
#endif
- if (DUK_TVAL_IS_DOUBLE(tv)) {
+ if (DUK_TVAL_IS_DOUBLE(tv)) {
/* When using packed duk_tval, number must be in NaN-normalized form
* for it to be a duk_tval, so no need to normalize. NOP for unpacked
* duk_tval.
@@ -18645,7 +20309,7 @@ DUK_LOCAL DUK_ALWAYS_INLINE duk_double_t duk__get_number_raw(duk_hthread *thr, d
DUK_EXTERNAL duk_double_t duk_get_number(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
- return duk__get_number_raw(thr, idx, DUK_DOUBLE_NAN); /* default: NaN */
+ return duk__get_number_raw(thr, idx, DUK_DOUBLE_NAN); /* default: NaN */
}
DUK_EXTERNAL duk_double_t duk_get_number_default(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
@@ -18663,6 +20327,7 @@ DUK_EXTERNAL duk_double_t duk_require_number(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT(tv != NULL);
if (DUK_UNLIKELY(!DUK_TVAL_IS_NUMBER(tv))) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
+ DUK_WO_NORETURN(return 0.0;);
}
ret.d = DUK_TVAL_GET_NUMBER(tv);
@@ -18800,7 +20465,11 @@ DUK_EXTERNAL const char *duk_get_string(duk_hthread *thr, duk_idx_t idx) {
}
}
-DUK_EXTERNAL const char *duk_opt_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len, const char *def_ptr, duk_size_t def_len) {
+DUK_EXTERNAL const char *duk_opt_lstring(duk_hthread *thr,
+ duk_idx_t idx,
+ duk_size_t *out_len,
+ const char *def_ptr,
+ duk_size_t def_len) {
DUK_ASSERT_API_ENTRY(thr);
if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
@@ -18821,7 +20490,11 @@ DUK_EXTERNAL const char *duk_opt_string(duk_hthread *thr, duk_idx_t idx, const c
return duk_require_string(thr, idx);
}
-DUK_EXTERNAL const char *duk_get_lstring_default(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len, const char *def_ptr, duk_size_t def_len) {
+DUK_EXTERNAL const char *duk_get_lstring_default(duk_hthread *thr,
+ duk_idx_t idx,
+ duk_size_t *out_len,
+ const char *def_ptr,
+ duk_size_t def_len) {
duk_hstring *h;
const char *ret;
duk_size_t len;
@@ -18894,6 +20567,7 @@ DUK_EXTERNAL void duk_require_object(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT(tv != NULL);
if (DUK_UNLIKELY(!DUK_TVAL_IS_OBJECT(tv))) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
+ DUK_WO_NORETURN(return;);
}
}
@@ -18901,7 +20575,7 @@ DUK_LOCAL void *duk__get_pointer_raw(duk_hthread *thr, duk_idx_t idx, void *def_
duk_tval *tv;
void *p;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
tv = duk_get_tval_or_unused(thr, idx);
DUK_ASSERT(tv != NULL);
@@ -18909,7 +20583,7 @@ DUK_LOCAL void *duk__get_pointer_raw(duk_hthread *thr, duk_idx_t idx, void *def_
return def_value;
}
- p = DUK_TVAL_GET_POINTER(tv); /* may be NULL */
+ p = DUK_TVAL_GET_POINTER(tv); /* may be NULL */
return p;
}
@@ -18945,12 +20619,13 @@ DUK_EXTERNAL void *duk_require_pointer(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT(tv != NULL);
if (DUK_UNLIKELY(!DUK_TVAL_IS_POINTER(tv))) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "pointer", DUK_STR_NOT_POINTER);
+ DUK_WO_NORETURN(return NULL;);
}
- p = DUK_TVAL_GET_POINTER(tv); /* may be NULL */
+ p = DUK_TVAL_GET_POINTER(tv); /* may be NULL */
return p;
}
-#if 0 /*unused*/
+#if 0 /*unused*/
DUK_INTERNAL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx) {
duk_tval *tv;
duk_heaphdr *h;
@@ -18969,13 +20644,18 @@ DUK_INTERNAL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx) {
}
#endif
-DUK_LOCAL void *duk__get_buffer_helper(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size, duk_bool_t throw_flag) {
+DUK_LOCAL void *duk__get_buffer_helper(duk_hthread *thr,
+ duk_idx_t idx,
+ duk_size_t *out_size,
+ void *def_ptr,
+ duk_size_t def_size,
+ duk_bool_t throw_flag) {
duk_hbuffer *h;
void *ret;
duk_size_t len;
duk_tval *tv;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
if (out_size != NULL) {
*out_size = 0;
@@ -18992,6 +20672,7 @@ DUK_LOCAL void *duk__get_buffer_helper(duk_hthread *thr, duk_idx_t idx, duk_size
} else {
if (throw_flag) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
+ DUK_WO_NORETURN(return NULL;);
}
len = def_size;
ret = def_ptr;
@@ -19021,7 +20702,11 @@ DUK_EXTERNAL void *duk_opt_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *o
return duk_require_buffer(thr, idx, out_size);
}
-DUK_EXTERNAL void *duk_get_buffer_default(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_len) {
+DUK_EXTERNAL void *duk_get_buffer_default(duk_hthread *thr,
+ duk_idx_t idx,
+ duk_size_t *out_size,
+ void *def_ptr,
+ duk_size_t def_len) {
DUK_ASSERT_API_ENTRY(thr);
return duk__get_buffer_helper(thr, idx, out_size, def_ptr, def_len, 0 /*throw_flag*/);
@@ -19038,7 +20723,13 @@ DUK_EXTERNAL void *duk_require_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_
* have a NULL data pointer when its size is zero, the optional 'out_isbuffer'
* argument allows caller to detect this reliably.
*/
-DUK_INTERNAL void *duk_get_buffer_data_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size, duk_bool_t throw_flag, duk_bool_t *out_isbuffer) {
+DUK_INTERNAL void *duk_get_buffer_data_raw(duk_hthread *thr,
+ duk_idx_t idx,
+ duk_size_t *out_size,
+ void *def_ptr,
+ duk_size_t def_size,
+ duk_bool_t throw_flag,
+ duk_bool_t *out_isbuffer) {
duk_tval *tv;
DUK_ASSERT_API_ENTRY(thr);
@@ -19062,7 +20753,7 @@ DUK_INTERNAL void *duk_get_buffer_data_raw(duk_hthread *thr, duk_idx_t idx, duk_
if (out_isbuffer != NULL) {
*out_isbuffer = 1;
}
- return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h); /* may be NULL (but only if size is 0) */
+ return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h); /* may be NULL (but only if size is 0) */
}
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
else if (DUK_TVAL_IS_OBJECT(tv)) {
@@ -19073,10 +20764,9 @@ DUK_INTERNAL void *duk_get_buffer_data_raw(duk_hthread *thr, duk_idx_t idx, duk_
* duk_hbufobj, get a validated buffer pointer/length.
*/
duk_hbufobj *h_bufobj = (duk_hbufobj *) h;
- DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+ DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
- if (h_bufobj->buf != NULL &&
- DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
+ if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
duk_uint8_t *p;
p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf);
@@ -19091,10 +20781,11 @@ DUK_INTERNAL void *duk_get_buffer_data_raw(duk_hthread *thr, duk_idx_t idx, duk_
/* if slice not fully valid, treat as error */
}
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
if (throw_flag) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
+ DUK_WO_NORETURN(return NULL;);
}
return def_ptr;
}
@@ -19104,7 +20795,11 @@ DUK_EXTERNAL void *duk_get_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size
return duk_get_buffer_data_raw(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, NULL);
}
-DUK_EXTERNAL void *duk_get_buffer_data_default(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size) {
+DUK_EXTERNAL void *duk_get_buffer_data_default(duk_hthread *thr,
+ duk_idx_t idx,
+ duk_size_t *out_size,
+ void *def_ptr,
+ duk_size_t def_size) {
DUK_ASSERT_API_ENTRY(thr);
return duk_get_buffer_data_raw(thr, idx, out_size, def_ptr, def_size, 0 /*throw_flag*/, NULL);
}
@@ -19135,7 +20830,7 @@ DUK_LOCAL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_hthread *thr, duk_idx_t i
duk_tval *tv;
duk_heaphdr *ret;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
tv = duk_get_tval_or_unused(thr, idx);
DUK_ASSERT(tv != NULL);
@@ -19144,9 +20839,8 @@ DUK_LOCAL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_hthread *thr, duk_idx_t i
}
ret = DUK_TVAL_GET_HEAPHDR(tv);
- DUK_ASSERT(ret != NULL); /* tagged null pointers should never occur */
+ DUK_ASSERT(ret != NULL); /* tagged null pointers should never occur */
return ret;
-
}
DUK_INTERNAL duk_hstring *duk_get_hstring(duk_hthread *thr, duk_idx_t idx) {
@@ -19174,6 +20868,7 @@ DUK_INTERNAL duk_hstring *duk_require_hstring(duk_hthread *thr, duk_idx_t idx) {
h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
if (DUK_UNLIKELY(h == NULL)) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "string", DUK_STR_NOT_STRING);
+ DUK_WO_NORETURN(return NULL;);
}
return h;
}
@@ -19186,6 +20881,7 @@ DUK_INTERNAL duk_hstring *duk_require_hstring_notsymbol(duk_hthread *thr, duk_id
h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
if (DUK_UNLIKELY(h == NULL || DUK_HSTRING_HAS_SYMBOL(h))) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "string", DUK_STR_NOT_STRING);
+ DUK_WO_NORETURN(return NULL;);
}
return h;
}
@@ -19203,6 +20899,7 @@ DUK_INTERNAL duk_hobject *duk_require_hobject(duk_hthread *thr, duk_idx_t idx) {
h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
if (DUK_UNLIKELY(h == NULL)) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
+ DUK_WO_NORETURN(return NULL;);
}
return h;
}
@@ -19220,6 +20917,7 @@ DUK_INTERNAL duk_hbuffer *duk_require_hbuffer(duk_hthread *thr, duk_idx_t idx) {
h = (duk_hbuffer *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_BUFFER);
if (DUK_UNLIKELY(h == NULL)) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
+ DUK_WO_NORETURN(return NULL;);
}
return h;
}
@@ -19244,6 +20942,7 @@ DUK_INTERNAL duk_hthread *duk_require_hthread(duk_hthread *thr, duk_idx_t idx) {
h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_THREAD(h)))) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "thread", DUK_STR_NOT_THREAD);
+ DUK_WO_NORETURN(return NULL;);
}
return (duk_hthread *) h;
}
@@ -19268,6 +20967,7 @@ DUK_INTERNAL duk_hcompfunc *duk_require_hcompfunc(duk_hthread *thr, duk_idx_t id
h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_COMPFUNC(h)))) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "compiledfunction", DUK_STR_NOT_COMPFUNC);
+ DUK_WO_NORETURN(return NULL;);
}
return (duk_hcompfunc *) h;
}
@@ -19292,6 +20992,7 @@ DUK_INTERNAL duk_hnatfunc *duk_require_hnatfunc(duk_hthread *thr, duk_idx_t idx)
h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_NATFUNC(h)))) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC);
+ DUK_WO_NORETURN(return NULL;);
}
return (duk_hnatfunc *) h;
}
@@ -19350,6 +21051,7 @@ DUK_EXTERNAL duk_c_function duk_require_c_function(duk_hthread *thr, duk_idx_t i
ret = duk_get_c_function(thr, idx);
if (DUK_UNLIKELY(!ret)) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC);
+ DUK_WO_NORETURN(return ret;);
}
return ret;
}
@@ -19358,10 +21060,11 @@ DUK_EXTERNAL void duk_require_function(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
if (DUK_UNLIKELY(!duk_is_function(thr, idx))) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "function", DUK_STR_NOT_FUNCTION);
+ DUK_WO_NORETURN(return;);
}
}
-DUK_INTERNAL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx) {
+DUK_EXTERNAL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx) {
duk_hobject *h;
DUK_ASSERT_API_ENTRY(thr);
@@ -19369,6 +21072,7 @@ DUK_INTERNAL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx) {
h = duk_require_hobject_accept_mask(thr, idx, DUK_TYPE_MASK_LIGHTFUNC);
if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_HAS_CONSTRUCTABLE(h))) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "constructable", DUK_STR_NOT_CONSTRUCTABLE);
+ DUK_WO_NORETURN(return;);
}
/* Lightfuncs (h == NULL) are constructable. */
}
@@ -19456,6 +21160,7 @@ DUK_EXTERNAL void *duk_require_heapptr(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT(tv != NULL);
if (DUK_UNLIKELY(!DUK_TVAL_IS_HEAP_ALLOCATED(tv))) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "heapobject", DUK_STR_UNEXPECTED_TYPE);
+ DUK_WO_NORETURN(return NULL;);
}
ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
@@ -19468,9 +21173,9 @@ DUK_LOCAL duk_hobject *duk__get_hobject_promote_mask_raw(duk_hthread *thr, duk_i
duk_uint_t val_mask;
duk_hobject *res;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
- res = duk_get_hobject(thr, idx); /* common case, not promoted */
+ res = duk_get_hobject(thr, idx); /* common case, not promoted */
if (DUK_LIKELY(res != NULL)) {
DUK_ASSERT(res != NULL);
return res;
@@ -19483,12 +21188,13 @@ DUK_LOCAL duk_hobject *duk__get_hobject_promote_mask_raw(duk_hthread *thr, duk_i
DUK_ASSERT(res != NULL);
return res;
} else {
- return NULL; /* accept without promoting */
+ return NULL; /* accept without promoting */
}
}
if (type_mask & DUK_TYPE_MASK_THROW) {
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
+ DUK_WO_NORETURN(return NULL;);
}
return NULL;
}
@@ -19525,7 +21231,7 @@ DUK_INTERNAL duk_hobject *duk_get_hobject_with_class(duk_hthread *thr, duk_idx_t
duk_hobject *h;
DUK_ASSERT_API_ENTRY(thr);
- DUK_ASSERT_DISABLE(classnum >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(classnum >= 0); /* unsigned */
DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
@@ -19539,7 +21245,7 @@ DUK_INTERNAL duk_hobject *duk_require_hobject_with_class(duk_hthread *thr, duk_i
duk_hobject *h;
DUK_ASSERT_API_ENTRY(thr);
- DUK_ASSERT_DISABLE(classnum >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(classnum >= 0); /* unsigned */
DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
@@ -19549,6 +21255,7 @@ DUK_INTERNAL duk_hobject *duk_require_hobject_with_class(duk_hthread *thr, duk_i
DUK_UNREF(h_class);
DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, (const char *) DUK_HSTRING_GET_DATA(h_class), DUK_STR_UNEXPECTED_TYPE);
+ DUK_WO_NORETURN(return NULL;);
}
return h;
}
@@ -19584,7 +21291,7 @@ DUK_EXTERNAL duk_size_t duk_get_length(duk_hthread *thr, duk_idx_t idx) {
duk_pop_unsafe(thr);
return ret;
}
-#else /* DUK_USE_PREFER_SIZE */
+#else /* DUK_USE_PREFER_SIZE */
case DUK_TAG_STRING: {
duk_hstring *h = DUK_TVAL_GET_STRING(tv);
DUK_ASSERT(h != NULL);
@@ -19610,7 +21317,7 @@ DUK_EXTERNAL duk_size_t duk_get_length(duk_hthread *thr, duk_idx_t idx) {
duk_pop_unsafe(thr);
return ret;
}
-#endif /* DUK_USE_PREFER_SIZE */
+#endif /* DUK_USE_PREFER_SIZE */
case DUK_TAG_OBJECT: {
duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
DUK_ASSERT(h != NULL);
@@ -19642,7 +21349,7 @@ DUK_LOCAL duk_heaphdr *duk__known_heaphdr(duk_hthread *thr, duk_idx_t idx) {
duk_tval *tv;
duk_heaphdr *h;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
if (idx < 0) {
tv = thr->valstack_top + idx;
} else {
@@ -19707,8 +21414,8 @@ DUK_LOCAL duk_bool_t duk__defaultvalue_coerce_attempt(duk_hthread *thr, duk_idx_
if (duk_get_prop_stridx(thr, idx, func_stridx)) {
/* [ ... func ] */
if (duk_is_callable(thr, -1)) {
- duk_dup(thr, idx); /* -> [ ... func this ] */
- duk_call_method(thr, 0); /* -> [ ... retval ] */
+ duk_dup(thr, idx); /* -> [ ... func this ] */
+ duk_call_method(thr, 0); /* -> [ ... retval ] */
if (duk_is_primitive(thr, -1)) {
duk_replace(thr, idx);
return 1;
@@ -19716,7 +21423,7 @@ DUK_LOCAL duk_bool_t duk__defaultvalue_coerce_attempt(duk_hthread *thr, duk_idx_
/* [ ... retval ]; popped below */
}
}
- duk_pop_unsafe(thr); /* [ ... func/retval ] -> [ ... ] */
+ duk_pop_unsafe(thr); /* [ ... func/retval ] -> [ ... ] */
return 0;
}
@@ -19727,7 +21434,7 @@ DUK_EXTERNAL void duk_to_undefined(duk_hthread *thr, duk_idx_t idx) {
tv = duk_require_tval(thr, idx);
DUK_ASSERT(tv != NULL);
- DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
+ DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
}
DUK_EXTERNAL void duk_to_null(duk_hthread *thr, duk_idx_t idx) {
@@ -19737,53 +21444,41 @@ DUK_EXTERNAL void duk_to_null(duk_hthread *thr, duk_idx_t idx) {
tv = duk_require_tval(thr, idx);
DUK_ASSERT(tv != NULL);
- DUK_TVAL_SET_NULL_UPDREF(thr, tv); /* side effects */
+ DUK_TVAL_SET_NULL_UPDREF(thr, tv); /* side effects */
}
/* E5 Section 9.1 */
-DUK_EXTERNAL void duk_to_primitive(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) {
- /* inline initializer for coercers[] is not allowed by old compilers like BCC */
+DUK_LOCAL const char * const duk__toprim_hint_strings[3] = { "default", "string", "number" };
+DUK_LOCAL void duk__to_primitive_helper(duk_hthread *thr, duk_idx_t idx, duk_int_t hint, duk_bool_t check_symbol) {
+ /* Inline initializer for coercers[] is not allowed by old compilers like BCC. */
duk_small_uint_t coercers[2];
- duk_small_uint_t class_number;
DUK_ASSERT_API_ENTRY(thr);
DUK_ASSERT(hint == DUK_HINT_NONE || hint == DUK_HINT_NUMBER || hint == DUK_HINT_STRING);
idx = duk_require_normalize_index(thr, idx);
- if (!duk_check_type_mask(thr, idx, DUK_TYPE_MASK_OBJECT |
- DUK_TYPE_MASK_LIGHTFUNC |
- DUK_TYPE_MASK_BUFFER)) {
- /* Any other values stay as is. */
- DUK_ASSERT(!duk_is_buffer(thr, idx)); /* duk_to_string() relies on this behavior */
+ /* If already primitive, return as is. */
+ if (!duk_check_type_mask(thr, idx, DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
+ DUK_ASSERT(!duk_is_buffer(thr, idx)); /* duk_to_string() relies on this behavior */
return;
}
- class_number = duk_get_class_number(thr, idx);
-
- /* XXX: Symbol objects normally coerce via the ES2015-revised ToPrimitive()
- * algorithm which consults value[@@toPrimitive] and avoids calling
- * .valueOf() and .toString(). Before that is implemented, special
- * case Symbol objects to behave as if they had the default @@toPrimitive
- * algorithm of E6 Section 19.4.3.4, i.e. return the plain symbol value
- * with no further side effects.
+ /* @@toPrimitive lookup. Also do for plain buffers and lightfuncs
+ * which mimic objects.
*/
-
- if (class_number == DUK_HOBJECT_CLASS_SYMBOL) {
- duk_hobject *h_obj;
- duk_hstring *h_str;
-
- /* XXX: pretty awkward, index based API for internal value access? */
- h_obj = duk_known_hobject(thr, idx);
- h_str = duk_hobject_get_internal_value_string(thr->heap, h_obj);
- if (h_str) {
- duk_push_hstring(thr, h_str);
- duk_replace(thr, idx);
- return;
+ if (check_symbol && duk_get_method_stridx(thr, idx, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)) {
+ DUK_ASSERT(hint >= 0 && (duk_size_t) hint < sizeof(duk__toprim_hint_strings) / sizeof(const char *));
+ duk_dup(thr, idx);
+ duk_push_string(thr, duk__toprim_hint_strings[hint]);
+ duk_call_method(thr, 1); /* [ ... method value hint ] -> [ ... res] */
+ if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
+ goto fail;
}
+ duk_replace(thr, idx);
+ return;
}
-
/* Objects are coerced based on E5 specification.
* Lightfuncs are coerced because they behave like
* objects even if they're internally a primitive
@@ -19791,35 +21486,59 @@ DUK_EXTERNAL void duk_to_primitive(duk_hthread *thr, duk_idx_t idx, duk_int_t hi
* like ArrayBuffer objects since Duktape 2.x.
*/
- coercers[0] = DUK_STRIDX_VALUE_OF;
- coercers[1] = DUK_STRIDX_TO_STRING;
-
+ /* Hint magic for Date is unnecessary in ES2015 because of
+ * Date.prototype[@@toPrimitive]. However, it is needed if
+ * symbol support is not enabled.
+ */
+#if defined(DUK_USE_SYMBOL_BUILTIN)
if (hint == DUK_HINT_NONE) {
+ hint = DUK_HINT_NUMBER;
+ }
+#else /* DUK_USE_SYMBOL_BUILTIN */
+ if (hint == DUK_HINT_NONE) {
+ duk_small_uint_t class_number;
+
+ class_number = duk_get_class_number(thr, idx);
if (class_number == DUK_HOBJECT_CLASS_DATE) {
hint = DUK_HINT_STRING;
} else {
hint = DUK_HINT_NUMBER;
}
}
+#endif /* DUK_USE_SYMBOL_BUILTIN */
+ coercers[0] = DUK_STRIDX_VALUE_OF;
+ coercers[1] = DUK_STRIDX_TO_STRING;
if (hint == DUK_HINT_STRING) {
coercers[0] = DUK_STRIDX_TO_STRING;
coercers[1] = DUK_STRIDX_VALUE_OF;
}
if (duk__defaultvalue_coerce_attempt(thr, idx, coercers[0])) {
- DUK_ASSERT(!duk_is_buffer(thr, idx)); /* duk_to_string() relies on this behavior */
+ DUK_ASSERT(!duk_is_buffer(thr, idx)); /* duk_to_string() relies on this behavior */
return;
}
if (duk__defaultvalue_coerce_attempt(thr, idx, coercers[1])) {
- DUK_ASSERT(!duk_is_buffer(thr, idx)); /* duk_to_string() relies on this behavior */
+ DUK_ASSERT(!duk_is_buffer(thr, idx)); /* duk_to_string() relies on this behavior */
return;
}
+fail:
DUK_ERROR_TYPE(thr, DUK_STR_TOPRIMITIVE_FAILED);
+ DUK_WO_NORETURN(return;);
+}
+
+DUK_EXTERNAL void duk_to_primitive(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) {
+ duk__to_primitive_helper(thr, idx, hint, 1 /*check_symbol*/);
}
+#if defined(DUK_USE_SYMBOL_BUILTIN)
+DUK_INTERNAL void duk_to_primitive_ordinary(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) {
+ duk__to_primitive_helper(thr, idx, hint, 0 /*check_symbol*/);
+}
+#endif
+
/* E5 Section 9.2 */
DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_hthread *thr, duk_idx_t idx) {
duk_tval *tv;
@@ -19836,7 +21555,23 @@ DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_hthread *thr, duk_idx_t idx) {
/* Note: no need to re-lookup tv, conversion is side effect free. */
DUK_ASSERT(tv != NULL);
- DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, val); /* side effects */
+ DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, val); /* side effects */
+ return val;
+}
+
+DUK_INTERNAL duk_bool_t duk_to_boolean_top_pop(duk_hthread *thr) {
+ duk_tval *tv;
+ duk_bool_t val;
+
+ DUK_ASSERT_API_ENTRY(thr);
+
+ tv = duk_require_tval(thr, -1);
+ DUK_ASSERT(tv != NULL);
+
+ val = duk_js_toboolean(tv);
+ DUK_ASSERT(val == 0 || val == 1);
+
+ duk_pop_unsafe(thr);
return val;
}
@@ -19852,11 +21587,11 @@ DUK_EXTERNAL duk_double_t duk_to_number(duk_hthread *thr, duk_idx_t idx) {
idx = duk_require_normalize_index(thr, idx);
tv = DUK_GET_TVAL_POSIDX(thr, idx);
DUK_ASSERT(tv != NULL);
- d = duk_js_tonumber(thr, tv); /* XXX: fastint coercion? now result will always be a non-fastint */
+ d = duk_js_tonumber(thr, tv); /* XXX: fastint coercion? now result will always be a non-fastint */
/* ToNumber() may have side effects so must relookup 'tv'. */
tv = DUK_GET_TVAL_POSIDX(thr, idx);
- DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d); /* side effects */
+ DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d); /* side effects */
return d;
}
@@ -19888,13 +21623,13 @@ DUK_INTERNAL duk_double_t duk_to_number_tval(duk_hthread *thr, duk_tval *tv) {
tv_dst = thr->valstack_top++;
DUK_TVAL_SET_TVAL(tv_dst, tv);
- DUK_TVAL_INCREF(thr, tv_dst); /* decref not necessary */
- res = duk_to_number_m1(thr); /* invalidates tv_dst */
+ DUK_TVAL_INCREF(thr, tv_dst); /* decref not necessary */
+ res = duk_to_number_m1(thr); /* invalidates tv_dst */
tv_dst = --thr->valstack_top;
DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_dst));
- DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv_dst)); /* plain number */
- DUK_TVAL_SET_UNDEFINED(tv_dst); /* valstack init policy */
+ DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv_dst)); /* plain number */
+ DUK_TVAL_SET_UNDEFINED(tv_dst); /* valstack init policy */
return res;
#endif
@@ -19910,7 +21645,7 @@ DUK_LOCAL duk_double_t duk__to_int_uint_helper(duk_hthread *thr, duk_idx_t idx,
duk_tval *tv;
duk_double_t d;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
tv = duk_require_tval(thr, idx);
DUK_ASSERT(tv != NULL);
@@ -19930,7 +21665,7 @@ DUK_LOCAL duk_double_t duk__to_int_uint_helper(duk_hthread *thr, duk_idx_t idx,
/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
tv = duk_require_tval(thr, idx);
- DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d); /* side effects */
+ DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d); /* side effects */
return d;
}
@@ -19964,7 +21699,7 @@ DUK_EXTERNAL duk_int32_t duk_to_int32(duk_hthread *thr, duk_idx_t idx) {
/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
tv = duk_require_tval(thr, idx);
- DUK_TVAL_SET_I32_UPDREF(thr, tv, ret); /* side effects */
+ DUK_TVAL_SET_I32_UPDREF(thr, tv, ret); /* side effects */
return ret;
}
@@ -19980,7 +21715,7 @@ DUK_EXTERNAL duk_uint32_t duk_to_uint32(duk_hthread *thr, duk_idx_t idx) {
/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
tv = duk_require_tval(thr, idx);
- DUK_TVAL_SET_U32_UPDREF(thr, tv, ret); /* side effects */
+ DUK_TVAL_SET_U32_UPDREF(thr, tv, ret); /* side effects */
return ret;
}
@@ -19996,7 +21731,7 @@ DUK_EXTERNAL duk_uint16_t duk_to_uint16(duk_hthread *thr, duk_idx_t idx) {
/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
tv = duk_require_tval(thr, idx);
- DUK_TVAL_SET_U32_UPDREF(thr, tv, ret); /* side effects */
+ DUK_TVAL_SET_U32_UPDREF(thr, tv, ret); /* side effects */
return ret;
}
@@ -20025,19 +21760,19 @@ DUK_INTERNAL duk_uint8_t duk_to_uint8clamped(duk_hthread *thr, duk_idx_t idx) {
}
t = d - DUK_FLOOR(d);
- if (t == 0.5) {
+ if (duk_double_equals(t, 0.5)) {
/* Exact halfway, round to even. */
ret = (duk_uint8_t) d;
- ret = (ret + 1) & 0xfe; /* Example: d=3.5, t=0.5 -> ret = (3 + 1) & 0xfe = 4 & 0xfe = 4
- * Example: d=4.5, t=0.5 -> ret = (4 + 1) & 0xfe = 5 & 0xfe = 4
- */
+ ret = (ret + 1) & 0xfe; /* Example: d=3.5, t=0.5 -> ret = (3 + 1) & 0xfe = 4 & 0xfe = 4
+ * Example: d=4.5, t=0.5 -> ret = (4 + 1) & 0xfe = 5 & 0xfe = 4
+ */
} else {
/* Not halfway, round to nearest. */
ret = (duk_uint8_t) (d + 0.5);
}
return ret;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
DUK_EXTERNAL const char *duk_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
DUK_ASSERT_API_ENTRY(thr);
@@ -20048,10 +21783,10 @@ DUK_EXTERNAL const char *duk_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_siz
}
DUK_LOCAL duk_ret_t duk__safe_to_string_raw(duk_hthread *thr, void *udata) {
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
DUK_UNREF(udata);
- duk_to_string(thr, -1);
+ (void) duk_to_string(thr, -1);
return 1;
}
@@ -20088,12 +21823,66 @@ DUK_EXTERNAL const char *duk_safe_to_lstring(duk_hthread *thr, duk_idx_t idx, du
return duk_get_lstring(thr, idx, out_len);
}
+DUK_EXTERNAL const char *duk_to_stacktrace(duk_hthread *thr, duk_idx_t idx) {
+ DUK_ASSERT_API_ENTRY(thr);
+ idx = duk_require_normalize_index(thr, idx);
+
+ /* The expected argument to the call is an Error object. The stack
+ * trace is extracted without an inheritance-based instanceof check
+ * so that one can also extract the stack trace of a foreign error
+ * created in another Realm. Accept only a string .stack property.
+ */
+ if (duk_is_object(thr, idx)) {
+ (void) duk_get_prop_string(thr, idx, "stack");
+ if (duk_is_string(thr, -1)) {
+ duk_replace(thr, idx);
+ } else {
+ duk_pop(thr);
+ }
+ }
+
+ return duk_to_string(thr, idx);
+}
+
+DUK_LOCAL duk_ret_t duk__safe_to_stacktrace_raw(duk_hthread *thr, void *udata) {
+ DUK_CTX_ASSERT_VALID(thr);
+ DUK_UNREF(udata);
+
+ (void) duk_to_stacktrace(thr, -1);
+
+ return 1;
+}
+
+DUK_EXTERNAL const char *duk_safe_to_stacktrace(duk_hthread *thr, duk_idx_t idx) {
+ duk_int_t rc;
+
+ DUK_ASSERT_API_ENTRY(thr);
+ idx = duk_require_normalize_index(thr, idx);
+
+ duk_dup(thr, idx);
+ rc = duk_safe_call(thr, duk__safe_to_stacktrace_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
+ if (rc != 0) {
+ /* Coercion failed. Try to coerce the coercion itself error
+ * to a stack trace once. If that also fails, return a fixed,
+ * preallocated 'Error' string to avoid potential infinite loop.
+ */
+ rc = duk_safe_call(thr, duk__safe_to_stacktrace_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
+ if (rc != 0) {
+ duk_pop_unsafe(thr);
+ duk_push_hstring_stridx(thr, DUK_STRIDX_UC_ERROR);
+ }
+ }
+ duk_replace(thr, idx);
+
+ return duk_get_string(thr, idx);
+}
+
DUK_INTERNAL duk_hstring *duk_to_property_key_hstring(duk_hthread *thr, duk_idx_t idx) {
duk_hstring *h;
DUK_ASSERT_API_ENTRY(thr);
- duk_to_primitive(thr, idx, DUK_HINT_STRING); /* needed for e.g. Symbol objects */
+ duk_to_primitive(thr, idx, DUK_HINT_STRING); /* needed for e.g. Symbol objects */
h = duk_get_hstring(thr, idx);
if (h == NULL) {
/* The "is string?" check may seem unnecessary, but as things
@@ -20107,7 +21896,7 @@ DUK_INTERNAL duk_hstring *duk_to_property_key_hstring(duk_hthread *thr, duk_idx_
return h;
}
-#if defined(DUK_USE_DEBUGGER_SUPPORT) /* only needed by debugger for now */
+#if defined(DUK_USE_DEBUGGER_SUPPORT) /* only needed by debugger for now */
DUK_INTERNAL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
@@ -20119,87 +21908,91 @@ DUK_INTERNAL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx) {
#endif
/* Push Object.prototype.toString() output for 'tv'. */
-DUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv) {
+DUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects) {
+ duk_hobject *h_obj;
+ duk_small_uint_t classnum;
duk_small_uint_t stridx;
- duk_hstring *h_strclass;
+ duk_tval tv_tmp;
DUK_ASSERT_API_ENTRY(thr);
+ DUK_ASSERT(tv != NULL);
+
+ /* Stabilize 'tv', duk_push_literal() may trigger side effects. */
+ DUK_TVAL_SET_TVAL(&tv_tmp, tv);
+ tv = &tv_tmp;
+
+ /* Conceptually for any non-undefined/null value we should do a
+ * ToObject() coercion and look up @@toStringTag (from the object
+ * prototype) to see if a custom result should be used, with the
+ * exception of Arrays which are handled specially first.
+ *
+ * We'd like to avoid the actual conversion, but even for primitive
+ * types the prototype may have @@toStringTag. What's worse, the
+ * @@toStringTag property may be a getter that must get the object
+ * coerced value (not the prototype) as its 'this' binding.
+ *
+ * For now, do an actual object coercion. This could be avoided by
+ * doing a side effect free lookup to see if a getter would be invoked.
+ * If not, the value can be read directly and the object coercion could
+ * be avoided. This may not be worth it in practice, because
+ * Object.prototype.toString() is usually not performance critical.
+ */
+
+ duk_push_literal(thr, "[object "); /* -> [ ... "[object" ] */
switch (DUK_TVAL_GET_TAG(tv)) {
- case DUK_TAG_UNUSED: /* Treat like 'undefined', shouldn't happen. */
+ case DUK_TAG_UNUSED: /* Treat like 'undefined', shouldn't happen. */
case DUK_TAG_UNDEFINED: {
- stridx = DUK_STRIDX_UC_UNDEFINED;
- break;
+ duk_push_hstring_stridx(thr, DUK_STRIDX_UC_UNDEFINED);
+ goto finish;
}
case DUK_TAG_NULL: {
- stridx = DUK_STRIDX_UC_NULL;
- break;
- }
- case DUK_TAG_BOOLEAN: {
- stridx = DUK_STRIDX_UC_BOOLEAN;
- break;
- }
- case DUK_TAG_POINTER: {
- stridx = DUK_STRIDX_UC_POINTER;
- break;
+ duk_push_hstring_stridx(thr, DUK_STRIDX_UC_NULL);
+ goto finish;
}
- case DUK_TAG_LIGHTFUNC: {
- stridx = DUK_STRIDX_UC_FUNCTION;
- break;
}
- case DUK_TAG_STRING: {
- duk_hstring *h;
- h = DUK_TVAL_GET_STRING(tv);
- DUK_ASSERT(h != NULL);
- if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
- stridx = DUK_STRIDX_UC_SYMBOL;
- } else {
- stridx = DUK_STRIDX_UC_STRING;
- }
- break;
- }
- case DUK_TAG_OBJECT: {
- duk_hobject *h;
- duk_small_uint_t classnum;
- h = DUK_TVAL_GET_OBJECT(tv);
- DUK_ASSERT(h != NULL);
- classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h);
- stridx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum);
+ duk_push_tval(thr, tv);
+ tv = NULL; /* Invalidated by ToObject(). */
+ h_obj = duk_to_hobject(thr, -1);
+ DUK_ASSERT(h_obj != NULL);
+ if (duk_js_isarray_hobject(h_obj)) {
+ stridx = DUK_STRIDX_UC_ARRAY;
+ } else {
+ /* [ ... "[object" obj ] */
- /* XXX: This is not entirely correct anymore; in ES2015 the
- * default lookup should use @@toStringTag to come up with
- * e.g. [object Symbol], [object Uint8Array], etc. See
- * ES2015 Section 19.1.3.6. The downside of implementing that
- * directly is that the @@toStringTag lookup may have side
- * effects, so all call sites must be checked for that.
- * Some may need a side-effect free lookup, e.g. avoiding
- * getters which are not typical.
+#if defined(DUK_USE_SYMBOL_BUILTIN)
+ /* XXX: better handling with avoid_side_effects == 1; lookup tval
+ * without Proxy or getter side effects, and use it in sanitized
+ * form if it's a string.
*/
- break;
- }
- case DUK_TAG_BUFFER: {
- stridx = DUK_STRIDX_UINT8_ARRAY;
- break;
- }
-#if defined(DUK_USE_FASTINT)
- case DUK_TAG_FASTINT:
- /* Fall through to generic number case. */
+ if (!avoid_side_effects) {
+ (void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG);
+ if (duk_is_string_notsymbol(thr, -1)) {
+ duk_remove_m2(thr);
+ goto finish;
+ }
+ duk_pop_unsafe(thr);
+ }
+#else
+ DUK_UNREF(avoid_side_effects);
#endif
- default: {
- DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv)); /* number (maybe fastint) */
- stridx = DUK_STRIDX_UC_NUMBER;
- break;
- }
+
+ classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
+ stridx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum);
}
- h_strclass = DUK_HTHREAD_GET_STRING(thr, stridx);
- DUK_ASSERT(h_strclass != NULL);
+ duk_pop_unsafe(thr);
+ duk_push_hstring_stridx(thr, stridx);
- duk_push_sprintf(thr, "[object %s]", (const char *) DUK_HSTRING_GET_DATA(h_strclass));
+finish:
+ /* [ ... "[object" tag ] */
+ duk_push_literal(thr, "]");
+ duk_concat(thr, 3); /* [ ... "[object" tag "]" ] -> [ ... res ] */
}
/* XXX: other variants like uint, u32 etc */
-DUK_INTERNAL duk_int_t duk_to_int_clamped_raw(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped) {
+DUK_INTERNAL duk_int_t
+duk_to_int_clamped_raw(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped) {
duk_tval *tv;
duk_tval tv_tmp;
duk_double_t d, dmin, dmax;
@@ -20210,7 +22003,7 @@ DUK_INTERNAL duk_int_t duk_to_int_clamped_raw(duk_hthread *thr, duk_idx_t idx, d
tv = duk_require_tval(thr, idx);
DUK_ASSERT(tv != NULL);
- d = duk_js_tointeger(thr, tv); /* E5 Section 9.4, ToInteger() */
+ d = duk_js_tointeger(thr, tv); /* E5 Section 9.4, ToInteger() */
dmin = (duk_double_t) minval;
dmax = (duk_double_t) maxval;
@@ -20226,12 +22019,12 @@ DUK_INTERNAL duk_int_t duk_to_int_clamped_raw(duk_hthread *thr, duk_idx_t idx, d
} else {
res = (duk_int_t) d;
}
- DUK_UNREF(d); /* SCANBUILD: with suitable dmin/dmax limits 'd' is unused */
+ DUK_UNREF(d); /* SCANBUILD: with suitable dmin/dmax limits 'd' is unused */
/* 'd' and 'res' agree here */
/* Relookup in case duk_js_tointeger() ends up e.g. coercing an object. */
tv = duk_get_tval(thr, idx);
- DUK_ASSERT(tv != NULL); /* not popped by side effect */
+ DUK_ASSERT(tv != NULL); /* not popped by side effect */
DUK_TVAL_SET_TVAL(&tv_tmp, tv);
#if defined(DUK_USE_FASTINT)
#if (DUK_INT_MAX <= 0x7fffffffL)
@@ -20245,9 +22038,9 @@ DUK_INTERNAL duk_int_t duk_to_int_clamped_raw(duk_hthread *thr, duk_idx_t idx, d
}
#endif
#else
- DUK_TVAL_SET_NUMBER(tv, d); /* no need to incref */
+ DUK_TVAL_SET_NUMBER(tv, d); /* no need to incref */
#endif
- DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
+ DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
if (out_clamped) {
*out_clamped = clamped;
@@ -20255,6 +22048,7 @@ DUK_INTERNAL duk_int_t duk_to_int_clamped_raw(duk_hthread *thr, duk_idx_t idx, d
/* coerced value is updated to value stack even when RangeError thrown */
if (clamped) {
DUK_ERROR_RANGE(thr, DUK_STR_NUMBER_OUTSIDE_RANGE);
+ DUK_WO_NORETURN(return 0;);
}
}
@@ -20271,7 +22065,7 @@ DUK_INTERNAL duk_int_t duk_to_int_clamped(duk_hthread *thr, duk_idx_t idx, duk_i
DUK_INTERNAL duk_int_t duk_to_int_check_range(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval) {
DUK_ASSERT_API_ENTRY(thr);
- return duk_to_int_clamped_raw(thr, idx, minval, maxval, NULL); /* out_clamped==NULL -> RangeError if outside range */
+ return duk_to_int_clamped_raw(thr, idx, minval, maxval, NULL); /* out_clamped==NULL -> RangeError if outside range */
}
DUK_EXTERNAL const char *duk_to_string(duk_hthread *thr, duk_idx_t idx) {
@@ -20312,12 +22106,14 @@ DUK_EXTERNAL const char *duk_to_string(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT(h != NULL);
if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
DUK_ERROR_TYPE(thr, DUK_STR_CANNOT_STRING_COERCE_SYMBOL);
+ DUK_WO_NORETURN(goto skip_replace;);
} else {
goto skip_replace;
}
#else
goto skip_replace;
#endif
+ break;
}
case DUK_TAG_BUFFER: /* Go through Uint8Array.prototype.toString() for coercion. */
case DUK_TAG_OBJECT: {
@@ -20328,9 +22124,9 @@ DUK_EXTERNAL const char *duk_to_string(duk_hthread *thr, duk_idx_t idx) {
* value, and duk_to_string() then causes a TypeError.
*/
duk_to_primitive(thr, idx, DUK_HINT_STRING);
- DUK_ASSERT(!duk_is_buffer(thr, idx)); /* ToPrimitive() must guarantee */
+ DUK_ASSERT(!duk_is_buffer(thr, idx)); /* ToPrimitive() must guarantee */
DUK_ASSERT(!duk_is_object(thr, idx));
- return duk_to_string(thr, idx); /* Note: recursive call */
+ return duk_to_string(thr, idx); /* Note: recursive call */
}
case DUK_TAG_POINTER: {
void *ptr = DUK_TVAL_GET_POINTER(tv);
@@ -20358,17 +22154,14 @@ DUK_EXTERNAL const char *duk_to_string(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
duk_push_tval(thr, tv);
- duk_numconv_stringify(thr,
- 10 /*radix*/,
- 0 /*precision:shortest*/,
- 0 /*force_exponential*/);
+ duk_numconv_stringify(thr, 10 /*radix*/, 0 /*precision:shortest*/, 0 /*force_exponential*/);
break;
}
}
duk_replace(thr, idx);
- skip_replace:
+skip_replace:
DUK_ASSERT(duk_is_string(thr, idx));
return duk_require_string(thr, idx);
}
@@ -20450,8 +22243,7 @@ DUK_EXTERNAL void *duk_to_buffer_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t
src_size = DUK_HBUFFER_GET_SIZE(h_buf);
tmp = (DUK_HBUFFER_HAS_DYNAMIC(h_buf) ? DUK_BUF_MODE_DYNAMIC : DUK_BUF_MODE_FIXED);
- if ((tmp == mode && !DUK_HBUFFER_HAS_EXTERNAL(h_buf)) ||
- mode == DUK_BUF_MODE_DONTCARE) {
+ if ((tmp == mode && !DUK_HBUFFER_HAS_EXTERNAL(h_buf)) || mode == DUK_BUF_MODE_DONTCARE) {
/* Note: src_data may be NULL if input is a zero-size
* dynamic buffer.
*/
@@ -20468,16 +22260,11 @@ DUK_EXTERNAL void *duk_to_buffer_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t
}
dst_data = (duk_uint8_t *) duk_push_buffer(thr, src_size, (mode == DUK_BUF_MODE_DYNAMIC) /*dynamic*/);
- if (DUK_LIKELY(src_size > 0)) {
- /* When src_size == 0, src_data may be NULL (if source
- * buffer is dynamic), and dst_data may be NULL (if
- * target buffer is dynamic). Avoid zero-size memcpy()
- * with an invalid pointer.
- */
- DUK_MEMCPY((void *) dst_data, (const void *) src_data, (size_t) src_size);
- }
+ /* dst_data may be NULL if size is zero. */
+ duk_memcpy_unsafe((void *) dst_data, (const void *) src_data, (size_t) src_size);
+
duk_replace(thr, idx);
- skip_copy:
+skip_copy:
if (out_size) {
*out_size = src_size;
@@ -20537,7 +22324,7 @@ DUK_EXTERNAL void *duk_to_pointer(duk_hthread *thr, duk_idx_t idx) {
DUK_LOCAL void duk__push_func_from_lightfunc(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags) {
duk_idx_t nargs;
- duk_uint_t flags = 0; /* shared flags for a subset of types */
+ duk_uint_t flags = 0; /* shared flags for a subset of types */
duk_small_uint_t lf_len;
duk_hnatfunc *nf;
@@ -20546,15 +22333,9 @@ DUK_LOCAL void duk__push_func_from_lightfunc(duk_hthread *thr, duk_c_function fu
nargs = (duk_idx_t) DUK_VARARGS;
}
- flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_CONSTRUCTABLE |
- DUK_HOBJECT_FLAG_CALLABLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_FLAG_NATFUNC |
- DUK_HOBJECT_FLAG_NEWENV |
- DUK_HOBJECT_FLAG_STRICT |
- DUK_HOBJECT_FLAG_NOTAIL |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
+ flags = DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_CONSTRUCTABLE | DUK_HOBJECT_FLAG_CALLABLE |
+ DUK_HOBJECT_FLAG_FASTREFS | DUK_HOBJECT_FLAG_NATFUNC | DUK_HOBJECT_FLAG_NEWENV | DUK_HOBJECT_FLAG_STRICT |
+ DUK_HOBJECT_FLAG_NOTAIL | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE);
lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
@@ -20575,7 +22356,7 @@ DUK_LOCAL void duk__push_func_from_lightfunc(duk_hthread *thr, duk_c_function fu
DUK_EXTERNAL void duk_to_object(duk_hthread *thr, duk_idx_t idx) {
duk_tval *tv;
- duk_uint_t flags = 0; /* shared flags for a subset of types */
+ duk_uint_t flags = 0; /* shared flags for a subset of types */
duk_small_int_t proto = 0;
DUK_ASSERT_API_ENTRY(thr);
@@ -20586,17 +22367,17 @@ DUK_EXTERNAL void duk_to_object(duk_hthread *thr, duk_idx_t idx) {
switch (DUK_TVAL_GET_TAG(tv)) {
#if !defined(DUK_USE_BUFFEROBJECT_SUPPORT)
- case DUK_TAG_BUFFER: /* With no bufferobject support, don't object coerce. */
+ case DUK_TAG_BUFFER: /* With no bufferobject support, don't object coerce. */
#endif
case DUK_TAG_UNDEFINED:
case DUK_TAG_NULL: {
DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);
+ DUK_WO_NORETURN(return;);
break;
}
case DUK_TAG_BOOLEAN: {
- flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BOOLEAN);
+ flags =
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BOOLEAN);
proto = DUK_BIDX_BOOLEAN_PROTOTYPE;
goto create_object;
}
@@ -20605,14 +22386,11 @@ DUK_EXTERNAL void duk_to_object(duk_hthread *thr, duk_idx_t idx) {
h = DUK_TVAL_GET_STRING(tv);
DUK_ASSERT(h != NULL);
if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
- flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
+ flags = DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS |
DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_SYMBOL);
proto = DUK_BIDX_SYMBOL_PROTOTYPE;
} else {
- flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
+ flags = DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS | DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
proto = DUK_BIDX_STRING_PROTOTYPE;
}
@@ -20638,11 +22416,10 @@ DUK_EXTERNAL void duk_to_object(duk_hthread *thr, duk_idx_t idx) {
duk_hbufobj_push_uint8array_from_plain(thr, h_buf);
goto replace_value;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
case DUK_TAG_POINTER: {
- flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER);
+ flags =
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER);
proto = DUK_BIDX_POINTER_PROTOTYPE;
goto create_object;
}
@@ -20669,9 +22446,8 @@ DUK_EXTERNAL void duk_to_object(duk_hthread *thr, duk_idx_t idx) {
default: {
DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
- flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_NUMBER);
+ flags =
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_NUMBER);
proto = DUK_BIDX_NUMBER_PROTOTYPE;
goto create_object;
}
@@ -20679,7 +22455,7 @@ DUK_EXTERNAL void duk_to_object(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT(duk_is_object(thr, idx));
return;
- create_object:
+create_object:
(void) duk_push_object_helper(thr, flags, proto);
/* Note: Boolean prototype's internal value property is not writable,
@@ -20692,7 +22468,7 @@ DUK_EXTERNAL void duk_to_object(duk_hthread *thr, duk_idx_t idx) {
duk_dup(thr, idx);
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
- replace_value:
+replace_value:
duk_replace(thr, idx);
DUK_ASSERT(duk_is_object(thr, idx));
}
@@ -20763,11 +22539,11 @@ DUK_INTERNAL duk_int_t duk_get_type_tval(duk_tval *tv) {
DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
return DUK_TYPE_NUMBER;
}
-#else /* DUK_USE_PACKED_TVAL */
+#else /* DUK_USE_PACKED_TVAL */
DUK_ASSERT(DUK_TVAL_IS_VALID_TAG(tv));
DUK_ASSERT(sizeof(duk__type_from_tag) / sizeof(duk_uint_t) == DUK_TAG_MAX - DUK_TAG_MIN + 1);
return (duk_int_t) duk__type_from_tag[DUK_TVAL_GET_TAG(tv) - DUK_TAG_MIN];
-#endif /* DUK_USE_PACKED_TVAL */
+#endif /* DUK_USE_PACKED_TVAL */
}
DUK_EXTERNAL duk_int_t duk_get_type(duk_hthread *thr, duk_idx_t idx) {
@@ -20782,18 +22558,8 @@ DUK_EXTERNAL duk_int_t duk_get_type(duk_hthread *thr, duk_idx_t idx) {
}
#if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
-DUK_LOCAL const char * const duk__type_names[] = {
- "none",
- "undefined",
- "null",
- "boolean",
- "number",
- "string",
- "object",
- "buffer",
- "pointer",
- "lightfunc"
-};
+DUK_LOCAL const char * const duk__type_names[] = { "none", "undefined", "null", "boolean", "number",
+ "string", "object", "buffer", "pointer", "lightfunc" };
DUK_INTERNAL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx) {
duk_int_t type_tag;
@@ -20806,7 +22572,7 @@ DUK_INTERNAL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx) {
return duk__type_names[type_tag];
}
-#endif /* DUK_USE_VERBOSE_ERRORS && DUK_USE_PARANOID_ERRORS */
+#endif /* DUK_USE_VERBOSE_ERRORS && DUK_USE_PARANOID_ERRORS */
DUK_INTERNAL duk_small_uint_t duk_get_class_number(duk_hthread *thr, duk_idx_t idx) {
duk_tval *tv;
@@ -20872,11 +22638,11 @@ DUK_INTERNAL duk_uint_t duk_get_type_mask_tval(duk_tval *tv) {
DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
return DUK_TYPE_MASK_NUMBER;
}
-#else /* DUK_USE_PACKED_TVAL */
+#else /* DUK_USE_PACKED_TVAL */
DUK_ASSERT(DUK_TVAL_IS_VALID_TAG(tv));
DUK_ASSERT(sizeof(duk__type_mask_from_tag) / sizeof(duk_uint_t) == DUK_TAG_MAX - DUK_TAG_MIN + 1);
return duk__type_mask_from_tag[DUK_TVAL_GET_TAG(tv) - DUK_TAG_MIN];
-#endif /* DUK_USE_PACKED_TVAL */
+#endif /* DUK_USE_PACKED_TVAL */
}
DUK_EXTERNAL duk_uint_t duk_get_type_mask(duk_hthread *thr, duk_idx_t idx) {
@@ -20898,7 +22664,7 @@ DUK_EXTERNAL duk_bool_t duk_check_type_mask(duk_hthread *thr, duk_idx_t idx, duk
}
if (mask & DUK_TYPE_MASK_THROW) {
DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
- DUK_UNREACHABLE();
+ DUK_WO_NORETURN(return 0;);
}
return 0;
}
@@ -20995,14 +22761,14 @@ DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_hthread *thr, duk_idx_t idx) {
}
return 0;
}
-#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
return duk_is_buffer(thr, idx);
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
DUK_EXTERNAL duk_bool_t duk_is_pointer(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
@@ -21028,14 +22794,15 @@ DUK_EXTERNAL duk_bool_t duk_is_symbol(duk_hthread *thr, duk_idx_t idx) {
return 0;
}
+/* IsArray(), returns true for Array instance or Proxy of Array instance. */
DUK_EXTERNAL duk_bool_t duk_is_array(duk_hthread *thr, duk_idx_t idx) {
- duk_hobject *obj;
+ duk_tval *tv;
DUK_ASSERT_API_ENTRY(thr);
- obj = duk_get_hobject(thr, idx);
- if (obj) {
- return (DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_ARRAY ? 1 : 0);
+ tv = duk_get_tval(thr, idx);
+ if (tv) {
+ return duk_js_isarray(tv);
}
return 0;
}
@@ -21095,23 +22862,17 @@ DUK_EXTERNAL duk_bool_t duk_is_constructable(duk_hthread *thr, duk_idx_t idx) {
DUK_EXTERNAL duk_bool_t duk_is_c_function(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
- return duk__obj_flag_any_default_false(thr,
- idx,
- DUK_HOBJECT_FLAG_NATFUNC);
+ return duk__obj_flag_any_default_false(thr, idx, DUK_HOBJECT_FLAG_NATFUNC);
}
DUK_EXTERNAL duk_bool_t duk_is_ecmascript_function(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
- return duk__obj_flag_any_default_false(thr,
- idx,
- DUK_HOBJECT_FLAG_COMPFUNC);
+ return duk__obj_flag_any_default_false(thr, idx, DUK_HOBJECT_FLAG_COMPFUNC);
}
DUK_EXTERNAL duk_bool_t duk_is_bound_function(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT_API_ENTRY(thr);
- return duk__obj_flag_any_default_false(thr,
- idx,
- DUK_HOBJECT_FLAG_BOUNDFUNC);
+ return duk__obj_flag_any_default_false(thr, idx, DUK_HOBJECT_FLAG_BOUNDFUNC);
}
DUK_EXTERNAL duk_bool_t duk_is_thread(duk_hthread *thr, duk_idx_t idx) {
@@ -21228,7 +22989,7 @@ DUK_INTERNAL void duk_push_tval(duk_hthread *thr, duk_tval *tv) {
DUK__CHECK_SPACE();
tv_slot = thr->valstack_top++;
DUK_TVAL_SET_TVAL(tv_slot, tv);
- DUK_TVAL_INCREF(thr, tv); /* no side effects */
+ DUK_TVAL_INCREF(thr, tv); /* no side effects */
}
DUK_EXTERNAL void duk_push_undefined(duk_hthread *thr) {
@@ -21258,7 +23019,7 @@ DUK_EXTERNAL void duk_push_boolean(duk_hthread *thr, duk_bool_t val) {
DUK_ASSERT_API_ENTRY(thr);
DUK__CHECK_SPACE();
- b = (val ? 1 : 0); /* ensure value is 1 or 0 (not other non-zero) */
+ b = (val ? 1 : 0); /* ensure value is 1 or 0 (not other non-zero) */
tv_slot = thr->valstack_top++;
DUK_TVAL_SET_BOOLEAN(tv_slot, b);
}
@@ -21311,7 +23072,7 @@ DUK_EXTERNAL void duk_push_int(duk_hthread *thr, duk_int_t val) {
DUK_TVAL_SET_NUMBER(tv_slot, d);
}
#endif
-#else /* DUK_USE_FASTINT */
+#else /* DUK_USE_FASTINT */
duk_tval *tv_slot;
duk_double_t d;
@@ -21320,7 +23081,7 @@ DUK_EXTERNAL void duk_push_int(duk_hthread *thr, duk_int_t val) {
d = (duk_double_t) val;
tv_slot = thr->valstack_top++;
DUK_TVAL_SET_NUMBER(tv_slot, d);
-#endif /* DUK_USE_FASTINT */
+#endif /* DUK_USE_FASTINT */
}
DUK_EXTERNAL void duk_push_uint(duk_hthread *thr, duk_uint_t val) {
@@ -21333,7 +23094,7 @@ DUK_EXTERNAL void duk_push_uint(duk_hthread *thr, duk_uint_t val) {
#if DUK_UINT_MAX <= 0xffffffffUL
DUK_TVAL_SET_U32(tv_slot, (duk_uint32_t) val);
#else
- if (val <= DUK_FASTINT_MAX) { /* val is unsigned so >= 0 */
+ if (val <= DUK_FASTINT_MAX) { /* val is unsigned so >= 0 */
/* XXX: take advantage of val being unsigned, no need to mask */
DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
} else {
@@ -21341,7 +23102,7 @@ DUK_EXTERNAL void duk_push_uint(duk_hthread *thr, duk_uint_t val) {
DUK_TVAL_SET_NUMBER(tv_slot, d);
}
#endif
-#else /* DUK_USE_FASTINT */
+#else /* DUK_USE_FASTINT */
duk_tval *tv_slot;
duk_double_t d;
@@ -21350,7 +23111,7 @@ DUK_EXTERNAL void duk_push_uint(duk_hthread *thr, duk_uint_t val) {
d = (duk_double_t) val;
tv_slot = thr->valstack_top++;
DUK_TVAL_SET_NUMBER(tv_slot, d);
-#endif /* DUK_USE_FASTINT */
+#endif /* DUK_USE_FASTINT */
}
DUK_EXTERNAL void duk_push_nan(duk_hthread *thr) {
@@ -21371,21 +23132,22 @@ DUK_EXTERNAL const char *duk_push_lstring(duk_hthread *thr, const char *str, duk
DUK_ASSERT_API_ENTRY(thr);
- /* check stack before interning (avoid hanging temp) */
+ /* Check stack before interning (avoid hanging temp). */
DUK__CHECK_SPACE();
/* NULL with zero length represents an empty string; NULL with higher
- * length is also now trated like an empty string although it is
+ * length is also now treated like an empty string although it is
* a bit dubious. This is unlike duk_push_string() which pushes a
* 'null' if the input string is a NULL.
*/
- if (!str) {
- len = 0;
+ if (DUK_UNLIKELY(str == NULL)) {
+ len = 0U;
}
- /* Check for maximum string length */
+ /* Check for maximum string length. */
if (DUK_UNLIKELY(len > DUK_HSTRING_MAX_BYTELEN)) {
DUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG);
+ DUK_WO_NORETURN(return NULL;);
}
h = duk_heap_strtable_intern_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
@@ -21393,7 +23155,7 @@ DUK_EXTERNAL const char *duk_push_lstring(duk_hthread *thr, const char *str, duk
tv_slot = thr->valstack_top++;
DUK_TVAL_SET_STRING(tv_slot, h);
- DUK_HSTRING_INCREF(thr, h); /* no side effects */
+ DUK_HSTRING_INCREF(thr, h); /* no side effects */
return (const char *) DUK_HSTRING_GET_DATA(h);
}
@@ -21409,6 +23171,42 @@ DUK_EXTERNAL const char *duk_push_string(duk_hthread *thr, const char *str) {
}
}
+#if !defined(DUK_USE_PREFER_SIZE)
+#if defined(DUK_USE_LITCACHE_SIZE)
+DUK_EXTERNAL const char *duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len) {
+ duk_hstring *h;
+ duk_tval *tv_slot;
+
+ DUK_ASSERT_API_ENTRY(thr);
+ DUK_ASSERT(str != NULL);
+ DUK_ASSERT(str[len] == (char) 0);
+
+ /* Check for maximum string length. */
+ if (DUK_UNLIKELY(len > DUK_HSTRING_MAX_BYTELEN)) {
+ DUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG);
+ DUK_WO_NORETURN(return NULL;);
+ }
+
+ h = duk_heap_strtable_intern_literal_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
+ DUK_ASSERT(h != NULL);
+
+ tv_slot = thr->valstack_top++;
+ DUK_TVAL_SET_STRING(tv_slot, h);
+ DUK_HSTRING_INCREF(thr, h); /* no side effects */
+
+ return (const char *) DUK_HSTRING_GET_DATA(h);
+}
+#else /* DUK_USE_LITCACHE_SIZE */
+DUK_EXTERNAL const char *duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len) {
+ DUK_ASSERT_API_ENTRY(thr);
+ DUK_ASSERT(str != NULL);
+ DUK_ASSERT(str[len] == (char) 0);
+
+ return duk_push_lstring(thr, str, len);
+}
+#endif /* DUK_USE_LITCACHE_SIZE */
+#endif /* !DUK_USE_PREFER_SIZE */
+
DUK_EXTERNAL void duk_push_pointer(duk_hthread *thr, void *val) {
duk_tval *tv_slot;
@@ -21435,7 +23233,7 @@ DUK_LOCAL void duk__push_this_helper(duk_hthread *thr, duk_small_uint_t check_ob
DUK__CHECK_SPACE();
- DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top)); /* because of valstack init policy */
+ DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top)); /* because of valstack init policy */
tv_slot = thr->valstack_top++;
if (DUK_UNLIKELY(thr->callstack_curr == NULL)) {
@@ -21449,8 +23247,7 @@ DUK_LOCAL void duk__push_this_helper(duk_hthread *thr, duk_small_uint_t check_ob
/* 'this' binding is just before current activation's bottom */
DUK_ASSERT(thr->valstack_bottom > thr->valstack);
tv = thr->valstack_bottom - 1;
- if (check_object_coercible &&
- (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv))) {
+ if (check_object_coercible && (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv))) {
/* XXX: better macro for DUK_TVAL_IS_UNDEFINED_OR_NULL(tv) */
goto type_error;
}
@@ -21460,8 +23257,9 @@ DUK_LOCAL void duk__push_this_helper(duk_hthread *thr, duk_small_uint_t check_ob
}
return;
- type_error:
+type_error:
DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);
+ DUK_WO_NORETURN(return;);
}
DUK_EXTERNAL void duk_push_this(duk_hthread *thr) {
@@ -21491,20 +23289,60 @@ DUK_INTERNAL duk_hstring *duk_push_this_coercible_to_string(duk_hthread *thr) {
DUK_ASSERT_API_ENTRY(thr);
duk__push_this_helper(thr, 1 /*check_object_coercible*/);
- return duk_to_hstring_m1(thr); /* This will reject all Symbol values; accepts Symbol objects. */
+ return duk_to_hstring_m1(thr); /* This will reject all Symbol values; accepts Symbol objects. */
}
DUK_INTERNAL duk_tval *duk_get_borrowed_this_tval(duk_hthread *thr) {
DUK_ASSERT_API_ENTRY(thr);
- DUK_ASSERT(thr->callstack_top > 0); /* caller required to know */
- DUK_ASSERT(thr->callstack_curr != NULL); /* caller required to know */
- DUK_ASSERT(thr->valstack_bottom > thr->valstack); /* consequence of above */
- DUK_ASSERT(thr->valstack_bottom - 1 >= thr->valstack); /* 'this' binding exists */
+ DUK_ASSERT(thr->callstack_top > 0); /* caller required to know */
+ DUK_ASSERT(thr->callstack_curr != NULL); /* caller required to know */
+ DUK_ASSERT(thr->valstack_bottom > thr->valstack); /* consequence of above */
+ DUK_ASSERT(thr->valstack_bottom - 1 >= thr->valstack); /* 'this' binding exists */
return thr->valstack_bottom - 1;
}
+DUK_EXTERNAL void duk_push_new_target(duk_hthread *thr) {
+ duk_activation *act;
+
+ DUK_ASSERT_API_ENTRY(thr);
+
+ /* https://www.ecma-international.org/ecma-262/6.0/#sec-meta-properties-runtime-semantics-evaluation
+ * https://www.ecma-international.org/ecma-262/6.0/#sec-getnewtarget
+ *
+ * No newTarget support now, so as a first approximation
+ * use the resolved (non-bound) target function.
+ *
+ * Check CONSTRUCT flag from current function, or if running
+ * direct eval, from a non-direct-eval parent (with possibly
+ * more than one nested direct eval). An alternative to this
+ * would be to store [[NewTarget]] as a hidden symbol of the
+ * lexical scope, and then just look up that variable.
+ *
+ * Calls from the application will either be for an empty
+ * call stack, or a Duktape/C function as the top activation.
+ */
+
+ act = thr->callstack_curr;
+ for (;;) {
+ if (act == NULL) {
+ break;
+ }
+
+ if (act->flags & DUK_ACT_FLAG_CONSTRUCT) {
+ duk_push_tval(thr, &act->tv_func);
+ return;
+ } else if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
+ act = act->parent;
+ } else {
+ break;
+ }
+ }
+
+ duk_push_undefined(thr);
+}
+
DUK_EXTERNAL void duk_push_current_function(duk_hthread *thr) {
duk_activation *act;
@@ -21536,12 +23374,15 @@ DUK_EXTERNAL void duk_push_global_object(duk_hthread *thr) {
/* XXX: size optimize */
DUK_LOCAL void duk__push_stash(duk_hthread *thr) {
- if (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE)) {
+ if (!duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE)) {
DUK_DDD(DUK_DDDPRINT("creating heap/global/thread stash on first use"));
duk_pop_unsafe(thr);
duk_push_bare_object(thr);
duk_dup_top(thr);
- duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_C); /* [ ... parent stash stash ] -> [ ... parent stash ] */
+ duk_xdef_prop_stridx_short(thr,
+ -3,
+ DUK_STRIDX_INT_VALUE,
+ DUK_PROPDESC_FLAGS_C); /* [ ... parent stash stash ] -> [ ... parent stash ] */
}
duk_remove_m2(thr);
}
@@ -21565,7 +23406,7 @@ DUK_EXTERNAL void duk_push_thread_stash(duk_hthread *thr, duk_hthread *target_th
DUK_ASSERT_API_ENTRY(thr);
if (DUK_UNLIKELY(target_thr == NULL)) {
DUK_ERROR_TYPE_INVALID_ARGS(thr);
- return; /* not reached */
+ DUK_WO_NORETURN(return;);
}
duk_push_hobject(thr, (duk_hobject *) target_thr);
duk__push_stash(thr);
@@ -21575,7 +23416,7 @@ DUK_EXTERNAL void duk_push_thread_stash(duk_hthread *thr, duk_hthread *target_th
DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_hthread *thr, void *buf, duk_size_t sz, const char *fmt, va_list ap) {
duk_int_t len;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
DUK_UNREF(thr);
/* NUL terminator handling doesn't matter here */
@@ -21594,7 +23435,7 @@ DUK_EXTERNAL const char *duk_push_vsprintf(duk_hthread *thr, const char *fmt, va
duk_size_t sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
duk_bool_t pushed_buf = 0;
void *buf;
- duk_int_t len; /* XXX: duk_ssize_t */
+ duk_int_t len; /* XXX: duk_ssize_t */
const char *res;
DUK_ASSERT_API_ENTRY(thr);
@@ -21608,7 +23449,7 @@ DUK_EXTERNAL const char *duk_push_vsprintf(duk_hthread *thr, const char *fmt, va
}
/* initial estimate based on format string */
- sz = DUK_STRLEN(fmt) + 16; /* format plus something to avoid just missing */
+ sz = DUK_STRLEN(fmt) + 16; /* format plus something to avoid just missing */
if (sz < DUK_PUSH_SPRINTF_INITIAL_SIZE) {
sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
}
@@ -21618,7 +23459,7 @@ DUK_EXTERNAL const char *duk_push_vsprintf(duk_hthread *thr, const char *fmt, va
* This works 99% of the time which is quite nice.
*/
for (;;) {
- va_list ap_copy; /* copied so that 'ap' can be reused */
+ va_list ap_copy; /* copied so that 'ap' can be reused */
if (sz <= sizeof(stack_buf)) {
buf = stack_buf;
@@ -21641,13 +23482,14 @@ DUK_EXTERNAL const char *duk_push_vsprintf(duk_hthread *thr, const char *fmt, va
sz = sz * 2;
if (DUK_UNLIKELY(sz >= DUK_PUSH_SPRINTF_SANITY_LIMIT)) {
DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
+ DUK_WO_NORETURN(return NULL;);
}
}
/* Cannot use duk_buffer_to_string() on the buffer because it is
* usually larger than 'len'; 'buf' is also usually a stack buffer.
*/
- res = duk_push_lstring(thr, (const char *) buf, (duk_size_t) len); /* [ buf? res ] */
+ res = duk_push_lstring(thr, (const char *) buf, (duk_size_t) len); /* [ buf? res ] */
if (pushed_buf) {
duk_remove_m2(thr);
}
@@ -21668,13 +23510,14 @@ DUK_EXTERNAL const char *duk_push_sprintf(duk_hthread *thr, const char *fmt, ...
return ret;
}
-DUK_INTERNAL duk_hobject *duk_push_object_helper(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
+DUK_INTERNAL duk_hobject *duk_push_object_helper(duk_hthread *thr,
+ duk_uint_t hobject_flags_and_class,
+ duk_small_int_t prototype_bidx) {
duk_tval *tv_slot;
duk_hobject *h;
DUK_ASSERT_API_ENTRY(thr);
- DUK_ASSERT(prototype_bidx == -1 ||
- (prototype_bidx >= 0 && prototype_bidx < DUK_NUM_BUILTINS));
+ DUK_ASSERT(prototype_bidx == -1 || (prototype_bidx >= 0 && prototype_bidx < DUK_NUM_BUILTINS));
DUK__CHECK_SPACE();
@@ -21685,7 +23528,7 @@ DUK_INTERNAL duk_hobject *duk_push_object_helper(duk_hthread *thr, duk_uint_t ho
tv_slot = thr->valstack_top;
DUK_TVAL_SET_OBJECT(tv_slot, h);
- DUK_HOBJECT_INCREF(thr, h); /* no side effects */
+ DUK_HOBJECT_INCREF(thr, h); /* no side effects */
thr->valstack_top++;
/* object is now reachable */
@@ -21715,9 +23558,8 @@ DUK_EXTERNAL duk_idx_t duk_push_object(duk_hthread *thr) {
DUK_ASSERT_API_ENTRY(thr);
(void) duk_push_object_helper(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
DUK_BIDX_OBJECT_PROTOTYPE);
return duk_get_top_index_unsafe(thr);
}
@@ -21730,11 +23572,8 @@ DUK_EXTERNAL duk_idx_t duk_push_array(duk_hthread *thr) {
DUK_ASSERT_API_ENTRY(thr);
- flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_FLAG_ARRAY_PART |
- DUK_HOBJECT_FLAG_EXOTIC_ARRAY |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAY);
+ flags = DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS | DUK_HOBJECT_FLAG_ARRAY_PART |
+ DUK_HOBJECT_FLAG_EXOTIC_ARRAY | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAY);
obj = duk_harray_alloc(thr, flags);
DUK_ASSERT(obj != NULL);
@@ -21743,11 +23582,35 @@ DUK_EXTERNAL duk_idx_t duk_push_array(duk_hthread *thr) {
tv_slot = thr->valstack_top;
DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
- DUK_HOBJECT_INCREF(thr, obj); /* XXX: could preallocate with refcount = 1 */
+ DUK_HOBJECT_INCREF(thr, obj); /* XXX: could preallocate with refcount = 1 */
ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
thr->valstack_top++;
- DUK_ASSERT(obj->length == 0); /* Array .length starts at zero. */
+ DUK_ASSERT(obj->length == 0); /* Array .length starts at zero. */
+ return ret;
+}
+
+DUK_EXTERNAL duk_idx_t duk_push_bare_array(duk_hthread *thr) {
+ duk_uint_t flags;
+ duk_harray *obj;
+ duk_idx_t ret;
+ duk_tval *tv_slot;
+
+ DUK_ASSERT_API_ENTRY(thr);
+
+ flags = DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS | DUK_HOBJECT_FLAG_ARRAY_PART |
+ DUK_HOBJECT_FLAG_EXOTIC_ARRAY | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAY);
+
+ obj = duk_harray_alloc(thr, flags);
+ DUK_ASSERT(obj != NULL);
+
+ tv_slot = thr->valstack_top;
+ DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
+ DUK_HOBJECT_INCREF(thr, obj); /* XXX: could preallocate with refcount = 1 */
+ ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
+ thr->valstack_top++;
+
+ DUK_ASSERT(obj->length == 0); /* Array .length starts at zero. */
return ret;
}
@@ -21774,12 +23637,7 @@ DUK_INTERNAL duk_harray *duk_push_harray_with_size(duk_hthread *thr, duk_uint32_
a = duk_push_harray(thr);
- duk_hobject_realloc_props(thr,
- (duk_hobject *) a,
- 0,
- size,
- 0,
- 0);
+ duk_hobject_realloc_props(thr, (duk_hobject *) a, 0, size, 0, 0);
a->length = size;
return a;
}
@@ -21803,9 +23661,7 @@ DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_hthread *thr, duk_uint_t flags) {
DUK__CHECK_SPACE();
- obj = duk_hthread_alloc(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
+ obj = duk_hthread_alloc(thr, DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
DUK_ASSERT(obj != NULL);
obj->state = DUK_HTHREAD_STATE_INACTIVE;
#if defined(DUK_USE_ROM_STRINGS)
@@ -21829,6 +23685,7 @@ DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_hthread *thr, duk_uint_t flags) {
/* important to do this *after* pushing, to make the thread reachable for gc */
if (DUK_UNLIKELY(!duk_hthread_init_stacks(thr->heap, obj))) {
DUK_ERROR_ALLOC_FAILED(thr);
+ DUK_WO_NORETURN(return 0;);
}
/* initialize built-ins - either by copying or creating new ones */
@@ -21844,8 +23701,7 @@ DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_hthread *thr, duk_uint_t flags) {
/* Initial stack size satisfies the stack slack constraints so there
* is no need to require stack here.
*/
- DUK_ASSERT(DUK_VALSTACK_INITIAL_SIZE >=
- DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
+ DUK_ASSERT(DUK_VALSTACK_INITIAL_SIZE >= DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
return ret;
}
@@ -21864,12 +23720,11 @@ DUK_INTERNAL duk_hcompfunc *duk_push_hcompfunc(duk_hthread *thr) {
*/
obj = duk_hcompfunc_alloc(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_CALLABLE |
- DUK_HOBJECT_FLAG_COMPFUNC |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_CALLABLE | DUK_HOBJECT_FLAG_COMPFUNC |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
if (DUK_UNLIKELY(obj == NULL)) {
DUK_ERROR_ALLOC_FAILED(thr);
+ DUK_WO_NORETURN(return NULL;);
}
DUK_DDD(DUK_DDDPRINT("created compiled function object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
@@ -21894,13 +23749,11 @@ DUK_INTERNAL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr) {
DUK__CHECK_SPACE();
obj = duk_hboundfunc_alloc(thr->heap,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_BOUNDFUNC |
- DUK_HOBJECT_FLAG_CONSTRUCTABLE |
- DUK_HOBJECT_FLAG_CALLABLE |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_BOUNDFUNC | DUK_HOBJECT_FLAG_CONSTRUCTABLE |
+ DUK_HOBJECT_FLAG_CALLABLE | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
if (!obj) {
DUK_ERROR_ALLOC_FAILED(thr);
+ DUK_WO_NORETURN(return NULL;);
}
tv_slot = thr->valstack_top++;
@@ -21915,13 +23768,14 @@ DUK_INTERNAL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr) {
return obj;
}
-DUK_LOCAL duk_idx_t duk__push_c_function_raw(duk_hthread *thr, duk_c_function func, duk_idx_t nargs, duk_uint_t flags, duk_small_uint_t proto_bidx) {
+DUK_LOCAL duk_idx_t
+duk__push_c_function_raw(duk_hthread *thr, duk_c_function func, duk_idx_t nargs, duk_uint_t flags, duk_small_uint_t proto_bidx) {
duk_hnatfunc *obj;
duk_idx_t ret;
duk_tval *tv_slot;
duk_int16_t func_nargs;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
DUK__CHECK_SPACE();
@@ -21943,7 +23797,8 @@ DUK_LOCAL duk_idx_t duk__push_c_function_raw(duk_hthread *thr, duk_c_function fu
obj->nargs = func_nargs;
DUK_DDD(DUK_DDDPRINT("created native function object with flags: 0x%08lx, nargs=%ld",
- (unsigned long) obj->obj.hdr.h_flags, (long) obj->nargs));
+ (unsigned long) obj->obj.hdr.h_flags,
+ (long) obj->nargs));
tv_slot = thr->valstack_top;
DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
@@ -21955,9 +23810,9 @@ DUK_LOCAL duk_idx_t duk__push_c_function_raw(duk_hthread *thr, duk_c_function fu
DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[proto_bidx]);
return ret;
- api_error:
+api_error:
DUK_ERROR_TYPE_INVALID_ARGS(thr);
- return 0; /* not reached */
+ DUK_WO_NORETURN(return 0;);
}
DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
@@ -21965,15 +23820,9 @@ DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_hthread *thr, duk_c_function func
DUK_ASSERT_API_ENTRY(thr);
- flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_CONSTRUCTABLE |
- DUK_HOBJECT_FLAG_CALLABLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_FLAG_NATFUNC |
- DUK_HOBJECT_FLAG_NEWENV |
- DUK_HOBJECT_FLAG_STRICT |
- DUK_HOBJECT_FLAG_NOTAIL |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
+ flags = DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_CONSTRUCTABLE | DUK_HOBJECT_FLAG_CALLABLE |
+ DUK_HOBJECT_FLAG_FASTREFS | DUK_HOBJECT_FLAG_NATFUNC | DUK_HOBJECT_FLAG_NEWENV | DUK_HOBJECT_FLAG_STRICT |
+ DUK_HOBJECT_FLAG_NOTAIL | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
/* Default prototype is a Duktape specific %NativeFunctionPrototype%
* which provides .length and .name getters.
@@ -21986,15 +23835,9 @@ DUK_INTERNAL void duk_push_c_function_builtin(duk_hthread *thr, duk_c_function f
DUK_ASSERT_API_ENTRY(thr);
- flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_CONSTRUCTABLE |
- DUK_HOBJECT_FLAG_CALLABLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_FLAG_NATFUNC |
- DUK_HOBJECT_FLAG_NEWENV |
- DUK_HOBJECT_FLAG_STRICT |
- DUK_HOBJECT_FLAG_NOTAIL |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
+ flags = DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_CONSTRUCTABLE | DUK_HOBJECT_FLAG_CALLABLE |
+ DUK_HOBJECT_FLAG_FASTREFS | DUK_HOBJECT_FLAG_NATFUNC | DUK_HOBJECT_FLAG_NEWENV | DUK_HOBJECT_FLAG_STRICT |
+ DUK_HOBJECT_FLAG_NOTAIL | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
/* Must use Function.prototype for standard built-in functions. */
(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_FUNCTION_PROTOTYPE);
@@ -22005,20 +23848,16 @@ DUK_INTERNAL void duk_push_c_function_builtin_noconstruct(duk_hthread *thr, duk_
DUK_ASSERT_API_ENTRY(thr);
- flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_CALLABLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_FLAG_NATFUNC |
- DUK_HOBJECT_FLAG_NEWENV |
- DUK_HOBJECT_FLAG_STRICT |
- DUK_HOBJECT_FLAG_NOTAIL |
+ flags = DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_CALLABLE | DUK_HOBJECT_FLAG_FASTREFS | DUK_HOBJECT_FLAG_NATFUNC |
+ DUK_HOBJECT_FLAG_NEWENV | DUK_HOBJECT_FLAG_STRICT | DUK_HOBJECT_FLAG_NOTAIL |
DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
/* Must use Function.prototype for standard built-in functions. */
(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_FUNCTION_PROTOTYPE);
}
-DUK_EXTERNAL duk_idx_t duk_push_c_lightfunc(duk_hthread *thr, duk_c_function func, duk_idx_t nargs, duk_idx_t length, duk_int_t magic) {
+DUK_EXTERNAL duk_idx_t
+duk_push_c_lightfunc(duk_hthread *thr, duk_c_function func, duk_idx_t nargs, duk_idx_t length, duk_int_t magic) {
duk_small_uint_t lf_flags;
duk_tval *tv_slot;
@@ -22047,13 +23886,15 @@ DUK_EXTERNAL duk_idx_t duk_push_c_lightfunc(duk_hthread *thr, duk_c_function fun
DUK_ASSERT(tv_slot >= thr->valstack_bottom);
return (duk_idx_t) (tv_slot - thr->valstack_bottom);
- api_error:
+api_error:
DUK_ERROR_TYPE_INVALID_ARGS(thr);
- return 0; /* not reached */
+ DUK_WO_NORETURN(return 0;);
}
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
-DUK_INTERNAL duk_hbufobj *duk_push_bufobj_raw(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
+DUK_INTERNAL duk_hbufobj *duk_push_bufobj_raw(duk_hthread *thr,
+ duk_uint_t hobject_flags_and_class,
+ duk_small_int_t prototype_bidx) {
duk_hbufobj *obj;
duk_tval *tv_slot;
@@ -22066,7 +23907,7 @@ DUK_INTERNAL duk_hbufobj *duk_push_bufobj_raw(duk_hthread *thr, duk_uint_t hobje
DUK_ASSERT(obj != NULL);
DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[prototype_bidx]);
- DUK_ASSERT_HBUFOBJ_VALID(obj);
+ DUK_HBUFOBJ_ASSERT_VALID(obj);
tv_slot = thr->valstack_top;
DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
@@ -22075,34 +23916,86 @@ DUK_INTERNAL duk_hbufobj *duk_push_bufobj_raw(duk_hthread *thr, duk_uint_t hobje
return obj;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/* XXX: There's quite a bit of overlap with buffer creation handling in
* duk_bi_buffer.c. Look for overlap and refactor.
*/
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
-#define DUK__PACK_ARGS(classnum,protobidx,elemtype,elemshift,istypedarray) \
+#define DUK__PACK_ARGS(classnum, protobidx, elemtype, elemshift, istypedarray) \
(((classnum) << 24) | ((protobidx) << 16) | ((elemtype) << 8) | ((elemshift) << 4) | (istypedarray))
static const duk_uint32_t duk__bufobj_flags_lookup[] = {
/* Node.js Buffers are Uint8Array instances which inherit from Buffer.prototype. */
- DUK__PACK_ARGS(DUK_HOBJECT_CLASS_ARRAYBUFFER, DUK_BIDX_ARRAYBUFFER_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT8, 0, 0), /* DUK_BUFOBJ_ARRAYBUFFER */
- DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY, DUK_BIDX_NODEJS_BUFFER_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT8, 0, 1), /* DUK_BUFOBJ_NODEJS_BUFFER */
- DUK__PACK_ARGS(DUK_HOBJECT_CLASS_DATAVIEW, DUK_BIDX_DATAVIEW_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT8, 0, 0), /* DUK_BUFOBJ_DATAVIEW */
- DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT8ARRAY, DUK_BIDX_INT8ARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_INT8, 0, 1), /* DUK_BUFOBJ_INT8ARRAY */
- DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY, DUK_BIDX_UINT8ARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT8, 0, 1), /* DUK_BUFOBJ_UINT8ARRAY */
- DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY, DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT8CLAMPED, 0, 1), /* DUK_BUFOBJ_UINT8CLAMPEDARRAY */
- DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT16ARRAY, DUK_BIDX_INT16ARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_INT16, 1, 1), /* DUK_BUFOBJ_INT16ARRAY */
- DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT16ARRAY, DUK_BIDX_UINT16ARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT16, 1, 1), /* DUK_BUFOBJ_UINT16ARRAY */
- DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT32ARRAY, DUK_BIDX_INT32ARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_INT32, 2, 1), /* DUK_BUFOBJ_INT32ARRAY */
- DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT32ARRAY, DUK_BIDX_UINT32ARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT32, 2, 1), /* DUK_BUFOBJ_UINT32ARRAY */
- DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT32ARRAY, DUK_BIDX_FLOAT32ARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_FLOAT32, 2, 1), /* DUK_BUFOBJ_FLOAT32ARRAY */
- DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT64ARRAY, DUK_BIDX_FLOAT64ARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_FLOAT64, 3, 1) /* DUK_BUFOBJ_FLOAT64ARRAY */
+ DUK__PACK_ARGS(DUK_HOBJECT_CLASS_ARRAYBUFFER,
+ DUK_BIDX_ARRAYBUFFER_PROTOTYPE,
+ DUK_HBUFOBJ_ELEM_UINT8,
+ 0,
+ 0), /* DUK_BUFOBJ_ARRAYBUFFER */
+ DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY,
+ DUK_BIDX_NODEJS_BUFFER_PROTOTYPE,
+ DUK_HBUFOBJ_ELEM_UINT8,
+ 0,
+ 1), /* DUK_BUFOBJ_NODEJS_BUFFER */
+ DUK__PACK_ARGS(DUK_HOBJECT_CLASS_DATAVIEW,
+ DUK_BIDX_DATAVIEW_PROTOTYPE,
+ DUK_HBUFOBJ_ELEM_UINT8,
+ 0,
+ 0), /* DUK_BUFOBJ_DATAVIEW */
+ DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT8ARRAY,
+ DUK_BIDX_INT8ARRAY_PROTOTYPE,
+ DUK_HBUFOBJ_ELEM_INT8,
+ 0,
+ 1), /* DUK_BUFOBJ_INT8ARRAY */
+ DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY,
+ DUK_BIDX_UINT8ARRAY_PROTOTYPE,
+ DUK_HBUFOBJ_ELEM_UINT8,
+ 0,
+ 1), /* DUK_BUFOBJ_UINT8ARRAY */
+ DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY,
+ DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
+ DUK_HBUFOBJ_ELEM_UINT8CLAMPED,
+ 0,
+ 1), /* DUK_BUFOBJ_UINT8CLAMPEDARRAY */
+ DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT16ARRAY,
+ DUK_BIDX_INT16ARRAY_PROTOTYPE,
+ DUK_HBUFOBJ_ELEM_INT16,
+ 1,
+ 1), /* DUK_BUFOBJ_INT16ARRAY */
+ DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT16ARRAY,
+ DUK_BIDX_UINT16ARRAY_PROTOTYPE,
+ DUK_HBUFOBJ_ELEM_UINT16,
+ 1,
+ 1), /* DUK_BUFOBJ_UINT16ARRAY */
+ DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT32ARRAY,
+ DUK_BIDX_INT32ARRAY_PROTOTYPE,
+ DUK_HBUFOBJ_ELEM_INT32,
+ 2,
+ 1), /* DUK_BUFOBJ_INT32ARRAY */
+ DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT32ARRAY,
+ DUK_BIDX_UINT32ARRAY_PROTOTYPE,
+ DUK_HBUFOBJ_ELEM_UINT32,
+ 2,
+ 1), /* DUK_BUFOBJ_UINT32ARRAY */
+ DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT32ARRAY,
+ DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
+ DUK_HBUFOBJ_ELEM_FLOAT32,
+ 2,
+ 1), /* DUK_BUFOBJ_FLOAT32ARRAY */
+ DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT64ARRAY,
+ DUK_BIDX_FLOAT64ARRAY_PROTOTYPE,
+ DUK_HBUFOBJ_ELEM_FLOAT64,
+ 3,
+ 1) /* DUK_BUFOBJ_FLOAT64ARRAY */
};
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
-DUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr, duk_idx_t idx_buffer, duk_size_t byte_offset, duk_size_t byte_length, duk_uint_t flags) {
+DUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr,
+ duk_idx_t idx_buffer,
+ duk_size_t byte_offset,
+ duk_size_t byte_length,
+ duk_uint_t flags) {
duk_hbufobj *h_bufobj;
duk_hbuffer *h_val;
duk_hobject *h_arraybuf;
@@ -22125,7 +24018,7 @@ DUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr, duk_idx_t idx_buffer,
}
}
- DUK_ASSERT_DISABLE(flags >= 0); /* flags is unsigned */
+ DUK_ASSERT_DISABLE(flags >= 0); /* flags is unsigned */
lookupidx = flags;
if (DUK_UNLIKELY(lookupidx >= sizeof(duk__bufobj_flags_lookup) / sizeof(duk_uint32_t))) {
goto arg_error;
@@ -22135,12 +24028,12 @@ DUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr, duk_idx_t idx_buffer,
protobidx = (tmp >> 16) & 0xff;
h_arraybuf = duk_get_hobject(thr, idx_buffer);
- if (h_arraybuf != NULL && /* argument is an object */
- flags != DUK_BUFOBJ_ARRAYBUFFER && /* creating a view */
- DUK_HOBJECT_GET_CLASS_NUMBER(h_arraybuf) == DUK_HOBJECT_CLASS_ARRAYBUFFER /* argument is ArrayBuffer */) {
+ if (h_arraybuf != NULL && /* argument is an object */
+ flags != DUK_BUFOBJ_ARRAYBUFFER && /* creating a view */
+ DUK_HOBJECT_GET_CLASS_NUMBER(h_arraybuf) == DUK_HOBJECT_CLASS_ARRAYBUFFER /* argument is ArrayBuffer */) {
duk_uint_t tmp_offset;
- DUK_ASSERT_HBUFOBJ_VALID((duk_hbufobj *) h_arraybuf);
+ DUK_HBUFOBJ_ASSERT_VALID((duk_hbufobj *) h_arraybuf);
h_val = ((duk_hbufobj *) h_arraybuf)->buf;
if (DUK_UNLIKELY(h_val == NULL)) {
goto arg_error;
@@ -22174,9 +24067,7 @@ DUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr, duk_idx_t idx_buffer,
DUK_ASSERT(h_val != NULL);
h_bufobj = duk_push_bufobj_raw(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_BUFOBJ |
- DUK_HOBJECT_CLASS_AS_FLAGS(classnum),
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_BUFOBJ | DUK_HOBJECT_CLASS_AS_FLAGS(classnum),
(duk_small_int_t) protobidx);
DUK_ASSERT(h_bufobj != NULL);
@@ -22189,7 +24080,7 @@ DUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr, duk_idx_t idx_buffer,
h_bufobj->shift = (tmp >> 4) & 0x0f;
h_bufobj->elem_type = (tmp >> 8) & 0xff;
h_bufobj->is_typedarray = tmp & 0x0f;
- DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+ DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
/* TypedArray views need an automatic ArrayBuffer which must be
* provided as .buffer property of the view. The ArrayBuffer is
@@ -22199,26 +24090,36 @@ DUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr, duk_idx_t idx_buffer,
*/
return;
- range_error:
+range_error:
DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS);
- return; /* not reached */
+ DUK_WO_NORETURN(return;);
- arg_error:
+arg_error:
DUK_ERROR_TYPE(thr, DUK_STR_INVALID_ARGS);
- return; /* not reached */
-}
-#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
-DUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr, duk_idx_t idx_buffer, duk_size_t byte_offset, duk_size_t byte_length, duk_uint_t flags) {
+ DUK_WO_NORETURN(return;);
+}
+#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
+DUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr,
+ duk_idx_t idx_buffer,
+ duk_size_t byte_offset,
+ duk_size_t byte_length,
+ duk_uint_t flags) {
DUK_ASSERT_API_ENTRY(thr);
DUK_UNREF(idx_buffer);
DUK_UNREF(byte_offset);
DUK_UNREF(byte_length);
DUK_UNREF(flags);
DUK_ERROR_UNSUPPORTED(thr);
+ DUK_WO_NORETURN(return;);
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
-DUK_EXTERNAL duk_idx_t duk_push_error_object_va_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) {
+DUK_EXTERNAL duk_idx_t duk_push_error_object_va_raw(duk_hthread *thr,
+ duk_errcode_t err_code,
+ const char *filename,
+ duk_int_t line,
+ const char *fmt,
+ va_list ap) {
duk_hobject *proto;
#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
duk_small_uint_t augment_flags;
@@ -22241,9 +24142,8 @@ DUK_EXTERNAL duk_idx_t duk_push_error_object_va_raw(duk_hthread *thr, duk_errcod
/* error gets its 'name' from the prototype */
proto = duk_error_prototype_from_code(thr, err_code);
(void) duk_push_object_helper_proto(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR),
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR),
proto);
/* ... and its 'message' from an instance property */
@@ -22252,7 +24152,7 @@ DUK_EXTERNAL duk_idx_t duk_push_error_object_va_raw(duk_hthread *thr, duk_errcod
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
} else {
/* If no explicit message given, put error code into message field
- * (as a number). This is not fully in keeping with the Ecmascript
+ * (as a number). This is not fully in keeping with the ECMAScript
* error model because messages are supposed to be strings (Error
* constructors use ToString() on their argument). However, it's
* probably more useful than having a separate 'code' property.
@@ -22266,13 +24166,14 @@ DUK_EXTERNAL duk_idx_t duk_push_error_object_va_raw(duk_hthread *thr, duk_errcod
/* Creation time error augmentation */
#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
/* filename may be NULL in which case file/line is not recorded */
- duk_err_augment_error_create(thr, thr, filename, line, augment_flags); /* may throw an error */
+ duk_err_augment_error_create(thr, thr, filename, line, augment_flags); /* may throw an error */
#endif
return duk_get_top_index_unsafe(thr);
}
-DUK_EXTERNAL duk_idx_t duk_push_error_object_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
+DUK_EXTERNAL duk_idx_t
+duk_push_error_object_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
va_list ap;
duk_idx_t ret;
@@ -22300,7 +24201,7 @@ DUK_EXTERNAL duk_idx_t duk_push_error_object_stash(duk_hthread *thr, duk_errcode
va_end(ap);
return ret;
}
-#endif /* DUK_USE_VARIADIC_MACROS */
+#endif /* DUK_USE_VARIADIC_MACROS */
DUK_EXTERNAL void *duk_push_buffer_raw(duk_hthread *thr, duk_size_t size, duk_small_uint_t flags) {
duk_tval *tv_slot;
@@ -22314,11 +24215,13 @@ DUK_EXTERNAL void *duk_push_buffer_raw(duk_hthread *thr, duk_size_t size, duk_sm
/* Check for maximum buffer length. */
if (DUK_UNLIKELY(size > DUK_HBUFFER_MAX_BYTELEN)) {
DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
+ DUK_WO_NORETURN(return NULL;);
}
h = duk_hbuffer_alloc(thr->heap, size, flags, &buf_data);
if (DUK_UNLIKELY(h == NULL)) {
DUK_ERROR_ALLOC_FAILED(thr);
+ DUK_WO_NORETURN(return NULL;);
}
tv_slot = thr->valstack_top;
@@ -22340,11 +24243,12 @@ DUK_INTERNAL void *duk_push_fixed_buffer_zero(duk_hthread *thr, duk_size_t len)
DUK_ASSERT_API_ENTRY(thr);
ptr = duk_push_buffer_raw(thr, len, 0);
+ DUK_ASSERT(ptr != NULL);
#if !defined(DUK_USE_ZERO_BUFFER_DATA)
/* ES2015 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
* is not set.
*/
- DUK_MEMZERO((void *) ptr, (size_t) len);
+ duk_memzero((void *) ptr, (size_t) len);
#endif
return ptr;
}
@@ -22400,13 +24304,10 @@ DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags)
/* CALLABLE and CONSTRUCTABLE flags are copied from the (initial)
* target, see ES2015 Sections 9.5.15 and 9.5.13.
*/
- flags = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h_target) &
- (DUK_HOBJECT_FLAG_CALLABLE | DUK_HOBJECT_FLAG_CONSTRUCTABLE);
- flags |= DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ;
+ flags = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h_target) & (DUK_HOBJECT_FLAG_CALLABLE | DUK_HOBJECT_FLAG_CONSTRUCTABLE);
+ flags |= DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ;
if (flags & DUK_HOBJECT_FLAG_CALLABLE) {
- flags |= DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION) |
- DUK_HOBJECT_FLAG_SPECIAL_CALL;
+ flags |= DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION) | DUK_HOBJECT_FLAG_SPECIAL_CALL;
} else {
flags |= DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT);
}
@@ -22423,7 +24324,7 @@ DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags)
h_proxy->target = h_target;
DUK_ASSERT(h_handler != NULL);
h_proxy->handler = h_handler;
- DUK_ASSERT_HPROXY_VALID(h_proxy);
+ DUK_HPROXY_ASSERT_VALID(h_proxy);
DUK_ASSERT(duk_get_hobject(thr, -2) == h_target);
DUK_ASSERT(duk_get_hobject(thr, -1) == h_handler);
@@ -22432,23 +24333,25 @@ DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags)
DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) h_proxy);
DUK_HOBJECT_INCREF(thr, (duk_hobject *) h_proxy);
tv_slot++;
- DUK_TVAL_SET_UNDEFINED(tv_slot); /* [ ... target handler ] -> [ ... proxy undefined ] */
- thr->valstack_top = tv_slot; /* -> [ ... proxy ] */
+ DUK_TVAL_SET_UNDEFINED(tv_slot); /* [ ... target handler ] -> [ ... proxy undefined ] */
+ thr->valstack_top = tv_slot; /* -> [ ... proxy ] */
DUK_DD(DUK_DDPRINT("created Proxy: %!iT", duk_get_tval(thr, -1)));
return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom - 1);
- fail_args:
+fail_args:
DUK_ERROR_TYPE_INVALID_ARGS(thr);
+ DUK_WO_NORETURN(return 0;);
}
-#else /* DUK_USE_ES6_PROXY */
+#else /* DUK_USE_ES6_PROXY */
DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags) {
DUK_ASSERT_API_ENTRY(thr);
DUK_UNREF(proxy_flags);
DUK_ERROR_UNSUPPORTED(thr);
+ DUK_WO_NORETURN(return 0;);
}
-#endif /* DUK_USE_ES6_PROXY */
+#endif /* DUK_USE_ES6_PROXY */
#if defined(DUK_USE_ASSERTIONS)
DUK_LOCAL void duk__validate_push_heapptr(duk_hthread *thr, void *ptr) {
@@ -22475,9 +24378,7 @@ DUK_LOCAL void duk__validate_push_heapptr(duk_hthread *thr, void *ptr) {
* the finalizer starts executing).
*/
#if defined(DUK_USE_FINALIZER_SUPPORT)
- for (curr = thr->heap->finalize_list;
- curr != NULL;
- curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
+ for (curr = thr->heap->finalize_list; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
/* FINALIZABLE is set for all objects on finalize_list
* except for an object being finalized right now. So
* can't assert here.
@@ -22489,18 +24390,18 @@ DUK_LOCAL void duk__validate_push_heapptr(duk_hthread *thr, void *ptr) {
if (curr == h) {
if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h)) {
/* Object is currently being finalized. */
- DUK_ASSERT(found == 0); /* Would indicate corrupted lists. */
+ DUK_ASSERT(found == 0); /* Would indicate corrupted lists. */
found = 1;
} else {
/* Not being finalized but on finalize_list,
* allowed since Duktape 2.1.
*/
- DUK_ASSERT(found == 0); /* Would indicate corrupted lists. */
+ DUK_ASSERT(found == 0); /* Would indicate corrupted lists. */
found = 1;
}
}
}
-#endif /* DUK_USE_FINALIZER_SUPPORT */
+#endif /* DUK_USE_FINALIZER_SUPPORT */
#if defined(DUK_USE_REFERENCE_COUNTING)
/* Because refzero_list is now processed to completion inline with
@@ -22526,7 +24427,7 @@ DUK_LOCAL void duk__validate_push_heapptr(duk_hthread *thr, void *ptr) {
#endif
while (str != NULL) {
if (str == (duk_hstring *) h) {
- DUK_ASSERT(found == 0); /* Would indicate corrupted lists. */
+ DUK_ASSERT(found == 0); /* Would indicate corrupted lists. */
found = 1;
break;
}
@@ -22535,18 +24436,16 @@ DUK_LOCAL void duk__validate_push_heapptr(duk_hthread *thr, void *ptr) {
}
DUK_ASSERT(found != 0);
} else {
- for (curr = thr->heap->heap_allocated;
- curr != NULL;
- curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
+ for (curr = thr->heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
if (curr == h) {
- DUK_ASSERT(found == 0); /* Would indicate corrupted lists. */
+ DUK_ASSERT(found == 0); /* Would indicate corrupted lists. */
found = 1;
}
}
DUK_ASSERT(found != 0);
}
}
-#endif /* DUK_USE_ASSERTIONS */
+#endif /* DUK_USE_ASSERTIONS */
DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_hthread *thr, void *ptr) {
duk_idx_t ret;
@@ -22575,7 +24474,7 @@ DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_hthread *thr, void *ptr) {
return ret;
}
- DUK_ASSERT_HEAPHDR_VALID((duk_heaphdr *) ptr);
+ DUK_HEAPHDR_ASSERT_VALID((duk_heaphdr *) ptr);
/* If the argument is on finalize_list it has technically been
* unreachable before duk_push_heapptr() but it's still safe to
@@ -22612,7 +24511,7 @@ DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_hthread *thr, void *ptr) {
* heap_allocated.
*/
#if defined(DUK_USE_REFERENCE_COUNTING)
- DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1); /* Preincremented on finalize_list insert. */
+ DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1); /* Preincremented on finalize_list insert. */
DUK_HEAPHDR_PREDEC_REFCOUNT(curr);
#endif
DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(thr->heap, curr);
@@ -22644,10 +24543,9 @@ DUK_EXTERNAL duk_idx_t duk_push_bare_object(duk_hthread *thr) {
DUK_ASSERT_API_ENTRY(thr);
(void) duk_push_object_helper(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
- -1); /* no prototype */
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
+ -1); /* no prototype */
return duk_get_top_index_unsafe(thr);
}
@@ -22710,7 +24608,7 @@ DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_n_unsafe_raw(duk_hthread *thr, duk_idx
duk_tval *tv_end;
#endif
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
DUK_ASSERT(count >= 0);
DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) count);
@@ -22744,7 +24642,7 @@ DUK_EXTERNAL void duk_pop_n(duk_hthread *thr, duk_idx_t count) {
if (DUK_UNLIKELY((duk_uidx_t) (thr->valstack_top - thr->valstack_bottom) < (duk_uidx_t) count)) {
DUK_ERROR_RANGE_INVALID_COUNT(thr);
- return;
+ DUK_WO_NORETURN(return;);
}
DUK_ASSERT(count >= 0);
@@ -22756,12 +24654,12 @@ DUK_INTERNAL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count) {
DUK_ASSERT_API_ENTRY(thr);
duk_pop_n(thr, count);
}
-#else /* DUK_USE_PREFER_SIZE */
+#else /* DUK_USE_PREFER_SIZE */
DUK_INTERNAL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count) {
DUK_ASSERT_API_ENTRY(thr);
duk__pop_n_unsafe_raw(thr, count);
}
-#endif /* DUK_USE_PREFER_SIZE */
+#endif /* DUK_USE_PREFER_SIZE */
/* Pop N elements without DECREF (in effect "stealing" any actual refcounts). */
#if defined(DUK_USE_REFERENCE_COUNTING)
@@ -22784,12 +24682,12 @@ DUK_INTERNAL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count) {
DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
}
-#else /* DUK_USE_REFERENCE_COUNTING */
+#else /* DUK_USE_REFERENCE_COUNTING */
DUK_INTERNAL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count) {
DUK_ASSERT_API_ENTRY(thr);
duk_pop_n_unsafe(thr, count);
}
-#endif /* DUK_USE_REFERENCE_COUNTING */
+#endif /* DUK_USE_REFERENCE_COUNTING */
/* Popping one element is called so often that when footprint is not an issue,
* compile a specialized function for it.
@@ -22807,11 +24705,11 @@ DUK_INTERNAL void duk_pop_nodecref_unsafe(duk_hthread *thr) {
DUK_ASSERT_API_ENTRY(thr);
duk_pop_n_nodecref_unsafe(thr, 1);
}
-#else /* DUK_USE_PREFER_SIZE */
+#else /* DUK_USE_PREFER_SIZE */
DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_unsafe_raw(duk_hthread *thr) {
duk_tval *tv;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);
@@ -22819,7 +24717,7 @@ DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_unsafe_raw(duk_hthread *thr) {
tv = --thr->valstack_top;
DUK_ASSERT(tv >= thr->valstack_bottom);
#if defined(DUK_USE_REFERENCE_COUNTING)
- DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
+ DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
#else
DUK_TVAL_SET_UNDEFINED(tv);
#endif
@@ -22832,6 +24730,7 @@ DUK_EXTERNAL void duk_pop(duk_hthread *thr) {
DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
DUK_ERROR_RANGE_INVALID_COUNT(thr);
+ DUK_WO_NORETURN(return;);
}
duk__pop_unsafe_raw(thr);
@@ -22854,14 +24753,14 @@ DUK_INTERNAL void duk_pop_nodecref_unsafe(duk_hthread *thr) {
DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
}
-#endif /* !DUK_USE_PREFER_SIZE */
+#endif /* !DUK_USE_PREFER_SIZE */
#if defined(DUK_USE_PREFER_SIZE)
DUK_INTERNAL void duk_pop_undefined(duk_hthread *thr) {
DUK_ASSERT_API_ENTRY(thr);
duk_pop_nodecref_unsafe(thr);
}
-#else /* DUK_USE_PREFER_SIZE */
+#else /* DUK_USE_PREFER_SIZE */
DUK_INTERNAL void duk_pop_undefined(duk_hthread *thr) {
DUK_ASSERT_API_ENTRY(thr);
DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
@@ -22873,7 +24772,7 @@ DUK_INTERNAL void duk_pop_undefined(duk_hthread *thr) {
DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
}
-#endif /* !DUK_USE_PREFER_SIZE */
+#endif /* !DUK_USE_PREFER_SIZE */
#if defined(DUK_USE_PREFER_SIZE)
DUK_EXTERNAL void duk_pop_2(duk_hthread *thr) {
@@ -22892,7 +24791,7 @@ DUK_INTERNAL void duk_pop_2_nodecref_unsafe(duk_hthread *thr) {
DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_2_unsafe_raw(duk_hthread *thr) {
duk_tval *tv;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 2);
@@ -22900,14 +24799,14 @@ DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_2_unsafe_raw(duk_hthread *thr) {
tv = --thr->valstack_top;
DUK_ASSERT(tv >= thr->valstack_bottom);
#if defined(DUK_USE_REFERENCE_COUNTING)
- DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
+ DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
#else
DUK_TVAL_SET_UNDEFINED(tv);
#endif
tv = --thr->valstack_top;
DUK_ASSERT(tv >= thr->valstack_bottom);
#if defined(DUK_USE_REFERENCE_COUNTING)
- DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
+ DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
#else
DUK_TVAL_SET_UNDEFINED(tv);
#endif
@@ -22920,6 +24819,7 @@ DUK_EXTERNAL void duk_pop_2(duk_hthread *thr) {
DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
if (DUK_UNLIKELY(thr->valstack_top - 2 < thr->valstack_bottom)) {
DUK_ERROR_RANGE_INVALID_COUNT(thr);
+ DUK_WO_NORETURN(return;);
}
duk__pop_2_unsafe_raw(thr);
@@ -22940,7 +24840,7 @@ DUK_INTERNAL void duk_pop_2_nodecref_unsafe(duk_hthread *thr) {
DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
}
-#endif /* !DUK_USE_PREFER_SIZE */
+#endif /* !DUK_USE_PREFER_SIZE */
DUK_EXTERNAL void duk_pop_3(duk_hthread *thr) {
DUK_ASSERT_API_ENTRY(thr);
@@ -22962,6 +24862,7 @@ DUK_INTERNAL void duk_pop_3_nodecref_unsafe(duk_hthread *thr) {
*/
/* XXX: pack index range? array index offset? */
+/* XXX: need ability to pack into a bare array? */
DUK_INTERNAL void duk_pack(duk_hthread *thr, duk_idx_t count) {
duk_tval *tv_src;
duk_tval *tv_dst;
@@ -22977,7 +24878,7 @@ DUK_INTERNAL void duk_pack(duk_hthread *thr, duk_idx_t count) {
if (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) top)) {
/* Also handles negative count. */
DUK_ERROR_RANGE_INVALID_COUNT(thr);
- return;
+ DUK_WO_NORETURN(return;);
}
DUK_ASSERT(count >= 0);
@@ -22986,23 +24887,23 @@ DUK_INTERNAL void duk_pack(duk_hthread *thr, duk_idx_t count) {
* multiplying with sizeof(duk_tval) won't wrap.
*/
DUK_ASSERT(count >= 0 && count <= (duk_idx_t) DUK_USE_VALSTACK_LIMIT);
- DUK_ASSERT((duk_size_t) count <= DUK_SIZE_MAX / sizeof(duk_tval)); /* no wrapping */
+ DUK_ASSERT((duk_size_t) count <= DUK_SIZE_MAX / sizeof(duk_tval)); /* no wrapping */
- tv_dst = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count); /* XXX: uninitialized would be OK */
+ tv_dst = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count); /* XXX: uninitialized would be OK */
DUK_ASSERT(count == 0 || tv_dst != NULL);
+ DUK_ASSERT(!duk_is_bare_object(thr, -1));
/* Copy value stack values directly to the array part without
* any refcount updates: net refcount changes are zero.
*/
-
tv_src = thr->valstack_top - count - 1;
- DUK_MEMCPY((void *) tv_dst, (const void *) tv_src, (size_t) count * sizeof(duk_tval));
+ duk_memcpy_unsafe((void *) tv_dst, (const void *) tv_src, (size_t) count * sizeof(duk_tval));
/* Overwrite result array to final value stack location and wipe
* the rest; no refcount operations needed.
*/
- tv_dst = tv_src; /* when count == 0, same as tv_src (OK) */
+ tv_dst = tv_src; /* when count == 0, same as tv_src (OK) */
tv_src = thr->valstack_top - 1;
DUK_TVAL_SET_TVAL(tv_dst, tv_src);
@@ -23032,9 +24933,8 @@ DUK_INTERNAL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT(h != NULL);
DUK_UNREF(h);
-#if defined(DUK_USE_ARRAY_FASTPATH) /* close enough */
- if (DUK_LIKELY(DUK_HOBJECT_IS_ARRAY(h) &&
- ((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h))) {
+#if defined(DUK_USE_ARRAY_FASTPATH) /* close enough */
+ if (DUK_LIKELY(DUK_HOBJECT_IS_ARRAY(h) && ((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h))) {
duk_harray *h_arr;
duk_tval *tv_src;
duk_tval *tv_dst;
@@ -23055,8 +24955,7 @@ DUK_INTERNAL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx) {
* XXX: alternatively, could prevent finalizers for the
* duration.
*/
- if (DUK_UNLIKELY(len != h_arr->length ||
- h_arr->length > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr))) {
+ if (DUK_UNLIKELY(len != h_arr->length || h_arr->length > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr))) {
goto skip_fast;
}
@@ -23075,7 +24974,7 @@ DUK_INTERNAL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx) {
* without an ancestor lookup (technically
* not compliant).
*/
- DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_dst)); /* valstack policy */
+ DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_dst)); /* valstack policy */
} else {
DUK_TVAL_SET_TVAL(tv_dst, tv_src);
DUK_TVAL_INCREF(thr, tv_dst);
@@ -23087,8 +24986,8 @@ DUK_INTERNAL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx) {
thr->valstack_top = tv_dst;
return (duk_idx_t) h_arr->length;
}
- skip_fast:
-#endif /* DUK_USE_ARRAY_FASTPATH */
+ skip_fast:
+#endif /* DUK_USE_ARRAY_FASTPATH */
/* Slow path: actual lookups. The initial 'length' lookup
* decides the output length, regardless of side effects that
@@ -23097,7 +24996,7 @@ DUK_INTERNAL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx) {
*/
idx = duk_normalize_index(thr, idx);
duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
- len = duk_to_uint32(thr, -1); /* ToUint32() coercion required */
+ len = duk_to_uint32(thr, -1); /* ToUint32() coercion required */
if (DUK_UNLIKELY(len >= 0x80000000UL)) {
goto fail_over_2g;
}
@@ -23114,17 +25013,24 @@ DUK_INTERNAL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx) {
}
DUK_ERROR_TYPE_INVALID_ARGS(thr);
- return 0;
+ DUK_WO_NORETURN(return 0;);
- fail_over_2g:
+fail_over_2g:
DUK_ERROR_RANGE_INVALID_LENGTH(thr);
- return 0;
+ DUK_WO_NORETURN(return 0;);
}
/*
* Error throwing
*/
+#if defined(DUK_USE_GCC_PRAGMAS)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn"
+#elif defined(DUK_USE_CLANG_PRAGMAS)
+#pragma clang diagnostic push
+#endif
+
DUK_EXTERNAL void duk_throw_raw(duk_hthread *thr) {
duk_tval *tv_val;
@@ -23135,6 +25041,7 @@ DUK_EXTERNAL void duk_throw_raw(duk_hthread *thr) {
if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
DUK_ERROR_TYPE_INVALID_ARGS(thr);
+ DUK_WO_NORETURN(return;);
}
/* Errors are augmented when they are created, not when they are
@@ -23193,14 +25100,25 @@ DUK_EXTERNAL void duk_fatal_raw(duk_hthread *thr, const char *err_msg) {
}
}
-DUK_EXTERNAL void duk_error_va_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) {
+DUK_EXTERNAL void duk_error_va_raw(duk_hthread *thr,
+ duk_errcode_t err_code,
+ const char *filename,
+ duk_int_t line,
+ const char *fmt,
+ va_list ap) {
DUK_ASSERT_API_ENTRY(thr);
duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
(void) duk_throw(thr);
+ DUK_WO_NORETURN(return;);
}
-DUK_EXTERNAL void duk_error_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
+DUK_EXTERNAL void duk_error_raw(duk_hthread *thr,
+ duk_errcode_t err_code,
+ const char *filename,
+ duk_int_t line,
+ const char *fmt,
+ ...) {
va_list ap;
DUK_ASSERT_API_ENTRY(thr);
@@ -23209,16 +25127,24 @@ DUK_EXTERNAL void duk_error_raw(duk_hthread *thr, duk_errcode_t err_code, const
duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
va_end(ap);
(void) duk_throw(thr);
+ DUK_WO_NORETURN(return;);
}
+#if defined(DUK_USE_GCC_PRAGMAS)
+#pragma GCC diagnostic pop
+#elif defined(DUK_USE_CLANG_PRAGMAS)
+#pragma clang diagnostic pop
+#endif
+
#if !defined(DUK_USE_VARIADIC_MACROS)
-DUK_NORETURN(DUK_LOCAL_DECL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, va_list ap));
+DUK_NORETURN(
+ DUK_LOCAL_DECL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, va_list ap));
DUK_LOCAL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, va_list ap) {
const char *filename;
duk_int_t line;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
filename = duk_api_global_filename;
line = duk_api_global_line;
@@ -23227,14 +25153,16 @@ DUK_LOCAL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_c
duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
(void) duk_throw(thr);
+ DUK_WO_NORETURN(return;);
}
-#define DUK__ERROR_STASH_SHARED(code) do { \
+#define DUK__ERROR_STASH_SHARED(code) \
+ do { \
va_list ap; \
va_start(ap, fmt); \
duk__throw_error_from_stash(thr, (code), fmt, ap); \
va_end(ap); \
- /* Never reached; if return 0 here, gcc/clang will complain. */ \
+ DUK_WO_NORETURN(return 0;); \
} while (0)
DUK_EXTERNAL duk_ret_t duk_error_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, ...) {
@@ -23269,7 +25197,7 @@ DUK_EXTERNAL duk_ret_t duk_uri_error_stash(duk_hthread *thr, const char *fmt, ..
DUK_ASSERT_API_ENTRY(thr);
DUK__ERROR_STASH_SHARED(DUK_ERR_URI_ERROR);
}
-#endif /* DUK_USE_VARIADIC_MACROS */
+#endif /* DUK_USE_VARIADIC_MACROS */
/*
* Comparison
@@ -23364,7 +25292,7 @@ DUK_INTERNAL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function f
DUK_ASSERT_API_ENTRY(thr);
- duk_push_sprintf(thr, "light_");
+ duk_push_literal(thr, "light_");
duk_push_string_funcptr(thr, (duk_uint8_t *) &func, sizeof(func));
duk_push_sprintf(thr, "_%04x", (unsigned int) lf_flags);
duk_concat(thr, 3);
@@ -23388,10 +25316,10 @@ DUK_INTERNAL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv) {
DUK_ASSERT_API_ENTRY(thr);
DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));
- DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags); /* read before 'tv' potentially invalidated */
- duk_push_string(thr, "function ");
+ DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags); /* read before 'tv' potentially invalidated */
+ duk_push_literal(thr, "function ");
duk_push_lightfunc_name_raw(thr, func, lf_flags);
- duk_push_string(thr, "() { [lightfunc code] }");
+ duk_push_literal(thr, "() { [lightfunc code] }");
duk_concat(thr, 3);
}
@@ -23409,7 +25337,7 @@ DUK_INTERNAL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, du
duk_small_uint_t t;
DUK_ASSERT_API_ENTRY(thr);
- DUK_ASSERT(sz <= 32); /* sanity limit for function pointer size */
+ DUK_ASSERT(sz <= 32); /* sanity limit for function pointer size */
p = buf;
#if defined(DUK_USE_INTEGER_LE)
@@ -23438,9 +25366,9 @@ DUK_INTERNAL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, du
*/
/* String limits for summary strings. */
-#define DUK__READABLE_SUMMARY_MAXCHARS 96 /* maximum supported by helper */
-#define DUK__READABLE_STRING_MAXCHARS 32 /* for strings/symbols */
-#define DUK__READABLE_ERRMSG_MAXCHARS 96 /* for error messages */
+#define DUK__READABLE_SUMMARY_MAXCHARS 96 /* maximum supported by helper */
+#define DUK__READABLE_STRING_MAXCHARS 32 /* for strings/symbols */
+#define DUK__READABLE_ERRMSG_MAXCHARS 96 /* for error messages */
/* String sanitizer which escapes ASCII control characters and a few other
* ASCII characters, passes Unicode as is, and replaces invalid UTF-8 with
@@ -23449,13 +25377,12 @@ DUK_INTERNAL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, du
*/
DUK_LOCAL void duk__push_hstring_readable_unicode(duk_hthread *thr, duk_hstring *h_input, duk_small_uint_t maxchars) {
const duk_uint8_t *p, *p_start, *p_end;
- duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH * DUK__READABLE_SUMMARY_MAXCHARS +
- 2 /*quotes*/ + 3 /*periods*/];
+ duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH * DUK__READABLE_SUMMARY_MAXCHARS + 2 /*quotes*/ + 3 /*periods*/];
duk_uint8_t *q;
duk_ucodepoint_t cp;
duk_small_uint_t nchars;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
DUK_ASSERT(h_input != NULL);
DUK_ASSERT(maxchars <= DUK__READABLE_SUMMARY_MAXCHARS);
@@ -23478,7 +25405,7 @@ DUK_LOCAL void duk__push_hstring_readable_unicode(duk_hthread *thr, duk_hstring
}
if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
if (cp < 0x20 || cp == 0x7f || cp == DUK_ASC_SINGLEQUOTE || cp == DUK_ASC_BACKSLASH) {
- DUK_ASSERT(DUK_UNICODE_MAX_XUTF8_LENGTH >= 4); /* estimate is valid */
+ DUK_ASSERT(DUK_UNICODE_MAX_XUTF8_LENGTH >= 4); /* estimate is valid */
DUK_ASSERT((cp >> 4) <= 0x0f);
*q++ = (duk_uint8_t) DUK_ASC_BACKSLASH;
*q++ = (duk_uint8_t) DUK_ASC_LC_X;
@@ -23488,7 +25415,7 @@ DUK_LOCAL void duk__push_hstring_readable_unicode(duk_hthread *thr, duk_hstring
q += duk_unicode_encode_xutf8(cp, q);
}
} else {
- p++; /* advance manually */
+ p++; /* advance manually */
*q++ = (duk_uint8_t) DUK_ASC_QUESTION;
}
nchars++;
@@ -23499,11 +25426,11 @@ DUK_LOCAL void duk__push_hstring_readable_unicode(duk_hthread *thr, duk_hstring
}
DUK_LOCAL const char *duk__push_string_tval_readable(duk_hthread *thr, duk_tval *tv, duk_bool_t error_aware) {
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
/* 'tv' may be NULL */
if (tv == NULL) {
- duk_push_string(thr, "none");
+ duk_push_literal(thr, "none");
} else {
switch (DUK_TVAL_GET_TAG(tv)) {
case DUK_TAG_STRING: {
@@ -23512,11 +25439,11 @@ DUK_LOCAL const char *duk__push_string_tval_readable(duk_hthread *thr, duk_tval
/* XXX: string summary produces question marks
* so this is not very ideal.
*/
- duk_push_string(thr, "[Symbol ");
+ duk_push_literal(thr, "[Symbol ");
duk_push_string(thr, duk__get_symbol_type_string(h));
- duk_push_string(thr, " ");
+ duk_push_literal(thr, " ");
duk__push_hstring_readable_unicode(thr, h, DUK__READABLE_STRING_MAXCHARS);
- duk_push_string(thr, "]");
+ duk_push_literal(thr, "]");
duk_concat(thr, 5);
break;
}
@@ -23527,8 +25454,10 @@ DUK_LOCAL const char *duk__push_string_tval_readable(duk_hthread *thr, duk_tval
duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
DUK_ASSERT(h != NULL);
- if (error_aware &&
- duk_hobject_prototype_chain_contains(thr, h, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
+ if (error_aware && duk_hobject_prototype_chain_contains(thr,
+ h,
+ thr->builtins[DUK_BIDX_ERROR_PROTOTYPE],
+ 1 /*ignore_loop*/)) {
/* Get error message in a side effect free way if
* possible; if not, summarize as a generic object.
* Error message currently gets quoted.
@@ -23537,16 +25466,18 @@ DUK_LOCAL const char *duk__push_string_tval_readable(duk_hthread *thr, duk_tval
* but traverse inheritance chain.
*/
duk_tval *tv_msg;
- tv_msg = duk_hobject_find_existing_entry_tval_ptr(thr->heap, h, DUK_HTHREAD_STRING_MESSAGE(thr));
+ tv_msg = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, h, DUK_STRIDX_MESSAGE);
if (tv_msg != NULL && DUK_TVAL_IS_STRING(tv_msg)) {
/* It's critical to avoid recursion so
* only summarize a string .message.
*/
- duk__push_hstring_readable_unicode(thr, DUK_TVAL_GET_STRING(tv_msg), DUK__READABLE_ERRMSG_MAXCHARS);
+ duk__push_hstring_readable_unicode(thr,
+ DUK_TVAL_GET_STRING(tv_msg),
+ DUK__READABLE_ERRMSG_MAXCHARS);
break;
}
}
- duk_push_class_string_tval(thr, tv);
+ duk_push_class_string_tval(thr, tv, 1 /*avoid_side_effects*/);
break;
}
case DUK_TAG_BUFFER: {
@@ -23601,7 +25532,7 @@ DUK_INTERNAL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstri
DUK_ASSERT_API_ENTRY(thr);
/* .toString() */
- duk_push_string(thr, "Symbol(");
+ duk_push_literal(thr, "Symbol(");
p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
p_end = p + DUK_HSTRING_GET_BYTELEN(h);
DUK_ASSERT(p[0] == 0xff || (p[0] & 0xc0) == 0x80);
@@ -23617,7 +25548,7 @@ DUK_INTERNAL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstri
}
}
duk_push_lstring(thr, (const char *) p, (duk_size_t) (q - p));
- duk_push_string(thr, ")");
+ duk_push_literal(thr, ")");
duk_concat(thr, 3);
}
@@ -23625,7 +25556,7 @@ DUK_INTERNAL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstri
* Functions
*/
-#if 0 /* not used yet */
+#if 0 /* not used yet */
DUK_INTERNAL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h) {
duk_c_function func;
@@ -23652,8 +25583,9 @@ DUK_INTERNAL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_
DUK_ASSERT_API_ENTRY(thr);
DUK_UNREF(thr);
- DUK_ASSERT(count * sizeof(duk_tval) >= count); /* no wrap */
- DUK_MEMCPY((void *) tv_dst, (const void *) tv_src, count * sizeof(duk_tval));
+ DUK_ASSERT(count * sizeof(duk_tval) >= count); /* no wrap */
+
+ duk_memcpy_unsafe((void *) tv_dst, (const void *) tv_src, count * sizeof(duk_tval));
tv = tv_dst;
while (count-- > 0) {
@@ -23684,12 +25616,12 @@ DUK_LOCAL void duk__concat_and_join_helper(duk_hthread *thr, duk_idx_t count_in,
duk_hstring *h;
duk_uint8_t *buf;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
if (DUK_UNLIKELY(count_in <= 0)) {
if (count_in < 0) {
DUK_ERROR_RANGE_INVALID_COUNT(thr);
- return;
+ DUK_WO_NORETURN(return;);
}
DUK_ASSERT(count_in == 0);
duk_push_hstring_empty(thr);
@@ -23723,15 +25655,14 @@ DUK_LOCAL void duk__concat_and_join_helper(duk_hthread *thr, duk_idx_t count_in,
/* Impose a string maximum length, need to handle overflow
* correctly.
*/
- if (new_len < len || /* wrapped */
+ if (new_len < len || /* wrapped */
new_len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN) {
goto error_overflow;
}
len = new_len;
}
- DUK_DDD(DUK_DDDPRINT("join/concat %lu strings, total length %lu bytes",
- (unsigned long) count, (unsigned long) len));
+ DUK_DDD(DUK_DDDPRINT("join/concat %lu strings, total length %lu bytes", (unsigned long) count, (unsigned long) len));
/* Use stack allocated buffer to ensure reachability in errors
* (e.g. intern error).
@@ -23744,12 +25675,12 @@ DUK_LOCAL void duk__concat_and_join_helper(duk_hthread *thr, duk_idx_t count_in,
idx = 0;
for (i = count; i >= 1; i--) {
if (is_join && i != count) {
- h = duk_require_hstring(thr, -((duk_idx_t) count) - 2); /* extra -1 for buffer */
- DUK_MEMCPY(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
+ h = duk_require_hstring(thr, -((duk_idx_t) count) - 2); /* extra -1 for buffer */
+ duk_memcpy(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
idx += DUK_HSTRING_GET_BYTELEN(h);
}
- h = duk_require_hstring(thr, -((duk_idx_t) i) - 1); /* extra -1 for buffer */
- DUK_MEMCPY(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
+ h = duk_require_hstring(thr, -((duk_idx_t) i) - 1); /* extra -1 for buffer */
+ duk_memcpy(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
idx += DUK_HSTRING_GET_BYTELEN(h);
}
@@ -23760,22 +25691,23 @@ DUK_LOCAL void duk__concat_and_join_helper(duk_hthread *thr, duk_idx_t count_in,
/* Get rid of the strings early to minimize memory use before intern. */
if (is_join) {
- duk_replace(thr, -((duk_idx_t) count) - 2); /* overwrite sep */
+ duk_replace(thr, -((duk_idx_t) count) - 2); /* overwrite sep */
duk_pop_n(thr, (duk_idx_t) count);
} else {
- duk_replace(thr, -((duk_idx_t) count) - 1); /* overwrite str1 */
+ duk_replace(thr, -((duk_idx_t) count) - 1); /* overwrite str1 */
duk_pop_n(thr, (duk_idx_t) (count - 1));
}
/* [ ... buf ] */
- (void) duk_buffer_to_string(thr, -1); /* Safe if inputs are safe. */
+ (void) duk_buffer_to_string(thr, -1); /* Safe if inputs are safe. */
/* [ ... res ] */
return;
- error_overflow:
+error_overflow:
DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
+ DUK_WO_NORETURN(return;);
}
DUK_EXTERNAL void duk_concat(duk_hthread *thr, duk_idx_t count) {
@@ -23789,7 +25721,7 @@ DUK_INTERNAL void duk_concat_2(duk_hthread *thr) {
DUK_ASSERT_API_ENTRY(thr);
duk_concat(thr, 2);
}
-#else /* DUK_USE_PREFER_SIZE */
+#else /* DUK_USE_PREFER_SIZE */
DUK_INTERNAL void duk_concat_2(duk_hthread *thr) {
duk_hstring *h1;
duk_hstring *h2;
@@ -23799,23 +25731,23 @@ DUK_INTERNAL void duk_concat_2(duk_hthread *thr) {
duk_size_t len;
DUK_ASSERT_API_ENTRY(thr);
- DUK_ASSERT(duk_get_top(thr) >= 2); /* Trusted caller. */
+ DUK_ASSERT(duk_get_top(thr) >= 2); /* Trusted caller. */
h1 = duk_to_hstring(thr, -2);
h2 = duk_to_hstring(thr, -1);
len1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
len2 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
len = len1 + len2;
- if (DUK_UNLIKELY(len < len1 || /* wrapped */
+ if (DUK_UNLIKELY(len < len1 || /* wrapped */
len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN)) {
goto error_overflow;
}
buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len);
DUK_ASSERT(buf != NULL);
- DUK_MEMCPY((void *) buf, (const void *) DUK_HSTRING_GET_DATA(h1), (size_t) len1);
- DUK_MEMCPY((void *) (buf + len1), (const void *) DUK_HSTRING_GET_DATA(h2), (size_t) len2);
- (void) duk_buffer_to_string(thr, -1); /* Safe if inputs are safe. */
+ duk_memcpy((void *) buf, (const void *) DUK_HSTRING_GET_DATA(h1), (size_t) len1);
+ duk_memcpy((void *) (buf + len1), (const void *) DUK_HSTRING_GET_DATA(h2), (size_t) len2);
+ (void) duk_buffer_to_string(thr, -1); /* Safe if inputs are safe. */
/* [ ... str1 str2 buf ] */
@@ -23823,10 +25755,11 @@ DUK_INTERNAL void duk_concat_2(duk_hthread *thr) {
duk_pop_unsafe(thr);
return;
- error_overflow:
+error_overflow:
DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
+ DUK_WO_NORETURN(return;);
}
-#endif /* DUK_USE_PREFER_SIZE */
+#endif /* DUK_USE_PREFER_SIZE */
DUK_EXTERNAL void duk_join(duk_hthread *thr, duk_idx_t count) {
DUK_ASSERT_API_ENTRY(thr);
@@ -23845,7 +25778,7 @@ DUK_EXTERNAL void duk_decode_string(duk_hthread *thr, duk_idx_t idx, duk_decode_
DUK_ASSERT_API_ENTRY(thr);
- h_input = duk_require_hstring(thr, idx); /* Accept symbols. */
+ h_input = duk_require_hstring(thr, idx); /* Accept symbols. */
DUK_ASSERT(h_input != NULL);
p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
@@ -23872,11 +25805,11 @@ DUK_EXTERNAL void duk_map_string(duk_hthread *thr, duk_idx_t idx, duk_map_char_f
idx = duk_normalize_index(thr, idx);
- h_input = duk_require_hstring(thr, idx); /* Accept symbols. */
+ h_input = duk_require_hstring(thr, idx); /* Accept symbols. */
DUK_ASSERT(h_input != NULL);
bw = &bw_alloc;
- DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input)); /* Reasonable output estimate. */
+ DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input)); /* Reasonable output estimate. */
p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
@@ -23897,7 +25830,7 @@ DUK_EXTERNAL void duk_map_string(duk_hthread *thr, duk_idx_t idx, duk_map_char_f
}
DUK_BW_COMPACT(thr, bw);
- (void) duk_buffer_to_string(thr, -1); /* Safe, extended UTF-8 encoded. */
+ (void) duk_buffer_to_string(thr, -1); /* Safe, extended UTF-8 encoded. */
duk_replace(thr, idx);
}
@@ -23910,7 +25843,7 @@ DUK_EXTERNAL void duk_substring(duk_hthread *thr, duk_idx_t idx, duk_size_t star
DUK_ASSERT_API_ENTRY(thr);
- idx = duk_require_normalize_index(thr, idx); /* Accept symbols. */
+ idx = duk_require_normalize_index(thr, idx); /* Accept symbols. */
h = duk_require_hstring(thr, idx);
DUK_ASSERT(h != NULL);
@@ -23935,7 +25868,7 @@ DUK_EXTERNAL void duk_substring(duk_hthread *thr, duk_idx_t idx, duk_size_t star
end_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) end_offset);
DUK_ASSERT(end_byte_offset >= start_byte_offset);
- DUK_ASSERT(end_byte_offset - start_byte_offset <= DUK_UINT32_MAX); /* Guaranteed by string limits. */
+ DUK_ASSERT(end_byte_offset - start_byte_offset <= DUK_UINT32_MAX); /* Guaranteed by string limits. */
/* No size check is necessary. */
res = duk_heap_strtable_intern_checked(thr,
@@ -23951,13 +25884,13 @@ DUK_EXTERNAL void duk_substring(duk_hthread *thr, duk_idx_t idx, duk_size_t star
*/
DUK_EXTERNAL void duk_trim(duk_hthread *thr, duk_idx_t idx) {
duk_hstring *h;
- const duk_uint8_t *p, *p_start, *p_end, *p_tmp1, *p_tmp2; /* pointers for scanning */
- const duk_uint8_t *q_start, *q_end; /* start (incl) and end (excl) of trimmed part */
+ const duk_uint8_t *p, *p_start, *p_end, *p_tmp1, *p_tmp2; /* pointers for scanning */
+ const duk_uint8_t *q_start, *q_end; /* start (incl) and end (excl) of trimmed part */
duk_codepoint_t cp;
DUK_ASSERT_API_ENTRY(thr);
- idx = duk_require_normalize_index(thr, idx); /* Accept symbols. */
+ idx = duk_require_normalize_index(thr, idx); /* Accept symbols. */
h = duk_require_hstring(thr, idx);
DUK_ASSERT(h != NULL);
@@ -23999,7 +25932,7 @@ DUK_EXTERNAL void duk_trim(duk_hthread *thr, duk_idx_t idx) {
}
q_end = p;
- scan_done:
+scan_done:
/* This may happen when forward and backward scanning disagree
* (possible for non-extended-UTF-8 strings).
*/
@@ -24012,8 +25945,10 @@ DUK_EXTERNAL void duk_trim(duk_hthread *thr, duk_idx_t idx) {
DUK_ASSERT(q_end >= q_start);
DUK_DDD(DUK_DDDPRINT("trim: p_start=%p, p_end=%p, q_start=%p, q_end=%p",
- (const void *) p_start, (const void *) p_end,
- (const void *) q_start, (const void *) q_end));
+ (const void *) p_start,
+ (const void *) p_end,
+ (const void *) q_start,
+ (const void *) q_end));
if (q_start == p_start && q_end == p_end) {
DUK_DDD(DUK_DDDPRINT("nothing was trimmed: avoid interning (hashing etc)"));
@@ -24034,15 +25969,15 @@ DUK_EXTERNAL duk_codepoint_t duk_char_code_at(duk_hthread *thr, duk_idx_t idx, d
* is handling of clamped offsets.
*/
- h = duk_require_hstring(thr, idx); /* Accept symbols. */
+ h = duk_require_hstring(thr, idx); /* Accept symbols. */
DUK_ASSERT(h != NULL);
- DUK_ASSERT_DISABLE(char_offset >= 0); /* Always true, arg is unsigned. */
+ DUK_ASSERT_DISABLE(char_offset >= 0); /* Always true, arg is unsigned. */
if (char_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
return 0;
}
- DUK_ASSERT(char_offset <= DUK_UINT_MAX); /* Guaranteed by string limits. */
+ DUK_ASSERT(char_offset <= DUK_UINT_MAX); /* Guaranteed by string limits. */
cp = duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) char_offset, 0 /*surrogate_aware*/);
return (duk_codepoint_t) cp;
}
@@ -24053,7 +25988,7 @@ DUK_EXTERNAL duk_codepoint_t duk_char_code_at(duk_hthread *thr, duk_idx_t idx, d
/* #include duk_internal.h -> already included */
DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr) {
- /* Ecmascript time, with millisecond fractions. Exposed via
+ /* ECMAScript time, with millisecond fractions. Exposed via
* duk_get_now() for example.
*/
DUK_UNREF(thr);
@@ -24061,7 +25996,7 @@ DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr) {
}
DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr) {
- /* Ecmascript time without millisecond fractions. Exposed via
+ /* ECMAScript time without millisecond fractions. Exposed via
* the Date built-in which doesn't allow fractions.
*/
DUK_UNREF(thr);
@@ -24085,7 +26020,7 @@ DUK_EXTERNAL duk_double_t duk_get_now(duk_hthread *thr) {
return duk_time_get_ecmascript_time(thr);
}
-#if 0 /* XXX: worth exposing? */
+#if 0 /* XXX: worth exposing? */
DUK_EXTERNAL duk_double_t duk_get_monotonic_time(duk_hthread *thr) {
DUK_ASSERT_API_ENTRY(thr);
DUK_UNREF(thr);
@@ -24100,11 +26035,11 @@ DUK_EXTERNAL void duk_time_to_components(duk_hthread *thr, duk_double_t timeval,
duk_uint_t flags;
DUK_ASSERT_API_ENTRY(thr);
- DUK_ASSERT(comp != NULL); /* XXX: or check? */
+ DUK_ASSERT(comp != NULL); /* XXX: or check? */
DUK_UNREF(thr);
/* Convert as one-based, but change month to zero-based to match the
- * Ecmascript Date built-in behavior 1:1.
+ * ECMAScript Date built-in behavior 1:1.
*/
flags = DUK_DATE_FLAG_ONEBASED | DUK_DATE_FLAG_NAN_TO_ZERO;
@@ -24129,7 +26064,7 @@ DUK_EXTERNAL duk_double_t duk_components_to_time(duk_hthread *thr, duk_time_comp
duk_uint_t flags;
DUK_ASSERT_API_ENTRY(thr);
- DUK_ASSERT(comp != NULL); /* XXX: or check? */
+ DUK_ASSERT(comp != NULL); /* XXX: or check? */
DUK_UNREF(thr);
/* Match Date constructor behavior (with UTC time). Month is given
@@ -24150,7 +26085,7 @@ DUK_EXTERNAL duk_double_t duk_components_to_time(duk_hthread *thr, duk_time_comp
dparts[DUK_DATE_IDX_MINUTE] = comp->minutes;
dparts[DUK_DATE_IDX_SECOND] = comp->seconds;
dparts[DUK_DATE_IDX_MILLISECOND] = comp->milliseconds;
- dparts[DUK_DATE_IDX_WEEKDAY] = 0; /* ignored */
+ dparts[DUK_DATE_IDX_WEEKDAY] = 0; /* ignored */
d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
@@ -24159,9 +26094,9 @@ DUK_EXTERNAL duk_double_t duk_components_to_time(duk_hthread *thr, duk_time_comp
/*
* Array built-ins
*
- * Most Array built-ins are intentionally generic in Ecmascript, and are
+ * Most Array built-ins are intentionally generic in ECMAScript, and are
* intended to work even when the 'this' binding is not an Array instance.
- * This Ecmascript feature is also used by much real world code. For this
+ * This ECMAScript feature is also used by much real world code. For this
* reason the implementations here don't assume exotic Array behavior or
* e.g. presence of a .length property. However, some algorithms have a
* fast path for duk_harray backed actual Array instances, enabled when
@@ -24201,7 +26136,7 @@ DUK_EXTERNAL duk_double_t duk_components_to_time(duk_hthread *thr, duk_time_comp
/* Perform an intermediate join when this many elements have been pushed
* on the value stack.
*/
-#define DUK__ARRAY_MID_JOIN_LIMIT 4096
+#define DUK__ARRAY_MID_JOIN_LIMIT 4096
#if defined(DUK_USE_ARRAY_BUILTIN)
@@ -24219,7 +26154,7 @@ DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32(duk_hthread *thr) {
/* XXX: push more directly? */
(void) duk_push_this_coercible_to_object(thr);
- DUK_ASSERT_HOBJECT_VALID(duk_get_hobject(thr, -1));
+ DUK_HOBJECT_ASSERT_VALID(duk_get_hobject(thr, -1));
duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_LENGTH);
len = duk_to_uint32(thr, -1);
@@ -24235,6 +26170,7 @@ DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32_limited(duk_hthread *thr) {
duk_uint32_t ret = duk__push_this_obj_len_u32(thr);
if (DUK_UNLIKELY(ret >= 0x80000000UL)) {
DUK_ERROR_RANGE_INVALID_LENGTH(thr);
+ DUK_WO_NORETURN(return 0U;);
}
return ret;
}
@@ -24251,7 +26187,7 @@ DUK_LOCAL duk_harray *duk__arraypart_fastpath_this(duk_hthread *thr) {
duk_hobject *h;
duk_uint_t flags_mask, flags_bits, flags_value;
- DUK_ASSERT(thr->valstack_bottom > thr->valstack); /* because call in progress */
+ DUK_ASSERT(thr->valstack_bottom > thr->valstack); /* because call in progress */
tv = DUK_GET_THIS_TVAL_PTR(thr);
/* Fast path requires that 'this' is a duk_harray. Read only arrays
@@ -24263,11 +26199,8 @@ DUK_LOCAL duk_harray *duk__arraypart_fastpath_this(duk_hthread *thr) {
}
h = DUK_TVAL_GET_OBJECT(tv);
DUK_ASSERT(h != NULL);
- flags_mask = DUK_HOBJECT_FLAG_ARRAY_PART | \
- DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
- DUK_HEAPHDR_FLAG_READONLY;
- flags_bits = DUK_HOBJECT_FLAG_ARRAY_PART | \
- DUK_HOBJECT_FLAG_EXOTIC_ARRAY;
+ flags_mask = DUK_HOBJECT_FLAG_ARRAY_PART | DUK_HOBJECT_FLAG_EXOTIC_ARRAY | DUK_HEAPHDR_FLAG_READONLY;
+ flags_bits = DUK_HOBJECT_FLAG_ARRAY_PART | DUK_HOBJECT_FLAG_EXOTIC_ARRAY;
flags_value = DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) h);
if ((flags_value & flags_mask) != flags_bits) {
DUK_DD(DUK_DDPRINT("reject array fast path: object flag check failed"));
@@ -24293,7 +26226,7 @@ DUK_LOCAL duk_harray *duk__arraypart_fastpath_this(duk_hthread *thr) {
DUK_DD(DUK_DDPRINT("array fast path allowed for: %!O", (duk_heaphdr *) h));
return (duk_harray *) h;
}
-#endif /* DUK_USE_ARRAY_FASTPATH */
+#endif /* DUK_USE_ARRAY_FASTPATH */
/*
* Constructor
@@ -24312,7 +26245,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_constructor(duk_hthread *thr) {
/* XXX: expensive check (also shared elsewhere - so add a shared internal API call?) */
d = duk_get_number(thr, 0);
len = duk_to_uint32(thr, 0);
- if (((duk_double_t) len) != d) {
+ if (!duk_double_equals((duk_double_t) len, d)) {
DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
}
@@ -24322,6 +26255,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_constructor(duk_hthread *thr) {
len_prealloc = len < 64 ? len : 64;
a = duk_push_harray_with_size(thr, len_prealloc);
DUK_ASSERT(a != NULL);
+ DUK_ASSERT(!duk_is_bare_object(thr, -1));
a->length = len;
return 1;
}
@@ -24335,10 +26269,8 @@ DUK_INTERNAL duk_ret_t duk_bi_array_constructor(duk_hthread *thr) {
*/
DUK_INTERNAL duk_ret_t duk_bi_array_constructor_is_array(duk_hthread *thr) {
- duk_hobject *h;
-
- h = duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_ARRAY);
- duk_push_boolean(thr, (h != NULL));
+ DUK_ASSERT_TOP(thr, 1);
+ duk_push_boolean(thr, duk_js_isarray(DUK_GET_TVAL_POSIDX(thr, 0)));
return 1;
}
@@ -24364,7 +26296,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_to_string(duk_hthread *thr) {
*/
DUK_DDD(DUK_DDDPRINT("this.join is not callable, fall back to (original) Object.toString"));
duk_set_top(thr, 0);
- return duk_bi_object_prototype_to_string(thr); /* has access to 'this' binding */
+ return duk_bi_object_prototype_to_string(thr); /* has access to 'this' binding */
}
/* [ ... this func ] */
@@ -24373,9 +26305,8 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_to_string(duk_hthread *thr) {
/* [ ... func this ] */
- DUK_DDD(DUK_DDDPRINT("calling: func=%!iT, this=%!iT",
- (duk_tval *) duk_get_tval(thr, -2),
- (duk_tval *) duk_get_tval(thr, -1)));
+ DUK_DDD(
+ DUK_DDDPRINT("calling: func=%!iT, this=%!iT", (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
duk_call_method(thr, 0);
return 1;
@@ -24387,11 +26318,17 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_to_string(duk_hthread *thr) {
DUK_INTERNAL duk_ret_t duk_bi_array_prototype_concat(duk_hthread *thr) {
duk_idx_t i, n;
- duk_uarridx_t idx, idx_last;
- duk_uarridx_t j, len;
+ duk_uint32_t j, idx, len;
duk_hobject *h;
+ duk_size_t tmp_len;
+
+ /* XXX: In ES2015 Array .length can be up to 2^53-1. The current
+ * implementation is limited to 2^32-1.
+ */
+
+ /* XXX: Fast path for array 'this' and array element. */
- /* XXX: the insert here is a bit expensive if there are a lot of items.
+ /* XXX: The insert here is a bit expensive if there are a lot of items.
* It could also be special cased in the outermost for loop quite easily
* (as the element is dup()'d anyway).
*/
@@ -24399,7 +26336,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_concat(duk_hthread *thr) {
(void) duk_push_this_coercible_to_object(thr);
duk_insert(thr, 0);
n = duk_get_top(thr);
- duk_push_array(thr); /* -> [ ToObject(this) item1 ... itemN arr ] */
+ duk_push_array(thr); /* -> [ ToObject(this) item1 ... itemN arr ] */
/* NOTE: The Array special behaviors are NOT invoked by duk_xdef_prop_index()
* (which differs from the official algorithm). If no error is thrown, this
@@ -24409,59 +26346,97 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_concat(duk_hthread *thr) {
*/
idx = 0;
- idx_last = 0;
for (i = 0; i < n; i++) {
+ duk_bool_t spreadable;
+ duk_bool_t need_has_check;
+
DUK_ASSERT_TOP(thr, n + 1);
/* [ ToObject(this) item1 ... itemN arr ] */
- duk_dup(thr, i);
- h = duk_get_hobject_with_class(thr, -1, DUK_HOBJECT_CLASS_ARRAY);
- if (!h) {
- duk_xdef_prop_index_wec(thr, -2, idx++);
- idx_last = idx;
+ h = duk_get_hobject(thr, i);
+
+ if (h == NULL) {
+ spreadable = 0;
+ } else {
+#if defined(DUK_USE_SYMBOL_BUILTIN)
+ duk_get_prop_stridx(thr, i, DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE);
+ if (duk_is_undefined(thr, -1)) {
+ spreadable = duk_js_isarray_hobject(h);
+ } else {
+ spreadable = duk_to_boolean(thr, -1);
+ }
+ duk_pop_nodecref_unsafe(thr);
+#else
+ spreadable = duk_js_isarray_hobject(h);
+#endif
+ }
+
+ if (!spreadable) {
+ duk_dup(thr, i);
+ duk_xdef_prop_index_wec(thr, -2, idx);
+ idx++;
+ if (DUK_UNLIKELY(idx == 0U)) {
+ /* Index after update is 0, and index written
+ * was 0xffffffffUL which is no longer a valid
+ * array index.
+ */
+ goto fail_wrap;
+ }
continue;
}
- /* [ ToObject(this) item1 ... itemN arr item(i) ] */
+ DUK_ASSERT(duk_is_object(thr, i));
+ need_has_check = (DUK_HOBJECT_IS_PROXY(h) != 0); /* Always 0 w/o Proxy support. */
- /* XXX: an array can have length higher than 32 bits; this is not handled
- * correctly now.
- */
- len = (duk_uarridx_t) duk_get_length(thr, -1);
+ /* [ ToObject(this) item1 ... itemN arr ] */
+
+ tmp_len = duk_get_length(thr, i);
+ len = (duk_uint32_t) tmp_len;
+ if (DUK_UNLIKELY(tmp_len != (duk_size_t) len)) {
+ goto fail_wrap;
+ }
+ if (DUK_UNLIKELY(idx + len < idx)) {
+ /* Result length must be at most 0xffffffffUL to be
+ * a valid 32-bit array index.
+ */
+ goto fail_wrap;
+ }
for (j = 0; j < len; j++) {
- if (duk_get_prop_index(thr, -1, j)) {
- /* [ ToObject(this) item1 ... itemN arr item(i) item(i)[j] ] */
- duk_xdef_prop_index_wec(thr, -3, idx++);
- idx_last = idx;
+ /* For a Proxy element, an explicit 'has' check is
+ * needed to allow the Proxy to present gaps.
+ */
+ if (need_has_check) {
+ if (duk_has_prop_index(thr, i, j)) {
+ duk_get_prop_index(thr, i, j);
+ duk_xdef_prop_index_wec(thr, -2, idx);
+ }
} else {
- idx++;
- duk_pop_undefined(thr);
-#if defined(DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER)
- /* According to E5.1 Section 15.4.4.4 nonexistent trailing
- * elements do not affect 'length' of the result. Test262
- * and other engines disagree, so update idx_last here too.
- */
- idx_last = idx;
-#else
- /* Strict standard behavior, ignore trailing elements for
- * result 'length'.
- */
-#endif
+ if (duk_get_prop_index(thr, i, j)) {
+ duk_xdef_prop_index_wec(thr, -2, idx);
+ } else {
+ duk_pop_undefined(thr);
+ }
}
+ idx++;
+ DUK_ASSERT(idx != 0U); /* Wrap check above. */
}
- duk_pop_unsafe(thr);
}
- /* The E5.1 Section 15.4.4.4 algorithm doesn't set the length explicitly
- * in the end, but because we're operating with an internal value which
- * is known to be an array, this should be equivalent.
+ /* ES5.1 has a specification "bug" in that nonexistent trailing
+ * elements don't affect the result .length. Test262 and other
+ * engines disagree, and the specification bug was fixed in ES2015
+ * (see NOTE 1 in https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.concat).
*/
- duk_push_uarridx(thr, idx_last);
+ duk_push_uarridx(thr, idx);
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
DUK_ASSERT_TOP(thr, n + 1);
return 1;
+
+fail_wrap:
+ DUK_ERROR_RANGE_INVALID_LENGTH(thr);
+ DUK_WO_NORETURN(return 0;);
}
/*
@@ -24505,8 +26480,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_join_shared(duk_hthread *thr) {
(unsigned long) len));
/* The extra (+4) is tight. */
- valstack_required = (duk_idx_t) ((len >= DUK__ARRAY_MID_JOIN_LIMIT ?
- DUK__ARRAY_MID_JOIN_LIMIT : len) + 4);
+ valstack_required = (duk_idx_t) ((len >= DUK__ARRAY_MID_JOIN_LIMIT ? DUK__ARRAY_MID_JOIN_LIMIT : len) + 4);
duk_require_stack(thr, valstack_required);
duk_dup_0(thr);
@@ -24517,14 +26491,13 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_join_shared(duk_hthread *thr) {
idx = 0;
for (;;) {
DUK_DDD(DUK_DDDPRINT("join idx=%ld", (long) idx));
- if (count >= DUK__ARRAY_MID_JOIN_LIMIT || /* intermediate join to avoid valstack overflow */
+ if (count >= DUK__ARRAY_MID_JOIN_LIMIT || /* intermediate join to avoid valstack overflow */
idx >= len) { /* end of loop (careful with len==0) */
/* [ sep ToObject(this) len sep str0 ... str(count-1) ] */
- DUK_DDD(DUK_DDDPRINT("mid/final join, count=%ld, idx=%ld, len=%ld",
- (long) count, (long) idx, (long) len));
- duk_join(thr, (duk_idx_t) count); /* -> [ sep ToObject(this) len str ] */
- duk_dup_0(thr); /* -> [ sep ToObject(this) len str sep ] */
- duk_insert(thr, -2); /* -> [ sep ToObject(this) len sep str ] */
+ DUK_DDD(DUK_DDDPRINT("mid/final join, count=%ld, idx=%ld, len=%ld", (long) count, (long) idx, (long) len));
+ duk_join(thr, (duk_idx_t) count); /* -> [ sep ToObject(this) len str ] */
+ duk_dup_0(thr); /* -> [ sep ToObject(this) len str sep ] */
+ duk_insert(thr, -2); /* -> [ sep ToObject(this) len sep str ] */
count = 1;
}
if (idx >= len) {
@@ -24540,7 +26513,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_join_shared(duk_hthread *thr) {
if (to_locale_string) {
duk_to_object(thr, -1);
duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_LOCALE_STRING);
- duk_insert(thr, -2); /* -> [ ... toLocaleString ToObject(val) ] */
+ duk_insert(thr, -2); /* -> [ ... toLocaleString ToObject(val) ] */
duk_call_method(thr, 0);
}
duk_to_string(thr, -1);
@@ -24598,7 +26571,7 @@ DUK_LOCAL duk_ret_t duk__array_pop_fastpath(duk_hthread *thr, duk_harray *h_arr)
return 1;
}
-#endif /* DUK_USE_ARRAY_FASTPATH */
+#endif /* DUK_USE_ARRAY_FASTPATH */
DUK_INTERNAL duk_ret_t duk_bi_array_prototype_pop(duk_hthread *thr) {
duk_uint32_t len;
@@ -24649,7 +26622,7 @@ DUK_LOCAL duk_ret_t duk__array_push_fastpath(duk_hthread *thr, duk_harray *h_arr
DUK_ASSERT((duk_uint32_t) n <= DUK_UINT32_MAX);
if (DUK_UNLIKELY(len + (duk_uint32_t) n < len)) {
DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
- DUK_DCERROR_RANGE_INVALID_LENGTH(thr); /* != 0 return value returned as is by caller */
+ DUK_DCERROR_RANGE_INVALID_LENGTH(thr); /* != 0 return value returned as is by caller */
}
if (len + (duk_uint32_t) n > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr)) {
/* Array part would need to be extended. Rely on slow path
@@ -24679,7 +26652,7 @@ DUK_LOCAL duk_ret_t duk__array_push_fastpath(duk_hthread *thr, duk_harray *h_arr
duk_push_uint(thr, (duk_uint_t) len);
return 1;
}
-#endif /* DUK_USE_ARRAY_FASTPATH */
+#endif /* DUK_USE_ARRAY_FASTPATH */
DUK_INTERNAL duk_ret_t duk_bi_array_prototype_push(duk_hthread *thr) {
/* Note: 'this' is not necessarily an Array object. The push()
@@ -24754,7 +26727,7 @@ DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_hthread *thr, duk_int_t id
duk_bool_t have1, have2;
duk_bool_t undef1, undef2;
duk_small_int_t ret;
- duk_idx_t idx_obj = 1; /* fixed offsets in valstack */
+ duk_idx_t idx_obj = 1; /* fixed offsets in valstack */
duk_idx_t idx_fn = 0;
duk_hstring *h1, *h2;
@@ -24775,7 +26748,8 @@ DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_hthread *thr, duk_int_t id
if (idx1 == idx2) {
DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld -> indices identical, quick exit",
- (long) idx1, (long) idx2));
+ (long) idx1,
+ (long) idx2));
return 0;
}
@@ -24783,8 +26757,12 @@ DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_hthread *thr, duk_int_t id
have2 = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) idx2);
DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld, have1=%ld, have2=%ld, val1=%!T, val2=%!T",
- (long) idx1, (long) idx2, (long) have1, (long) have2,
- (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
+ (long) idx1,
+ (long) idx2,
+ (long) have1,
+ (long) have2,
+ (duk_tval *) duk_get_tval(thr, -2),
+ (duk_tval *) duk_get_tval(thr, -1)));
if (have1) {
if (have2) {
@@ -24826,9 +26804,9 @@ DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_hthread *thr, duk_int_t id
duk_double_t d;
/* No need to check callable; duk_call() will do that. */
- duk_dup(thr, idx_fn); /* -> [ ... x y fn ] */
- duk_insert(thr, -3); /* -> [ ... fn x y ] */
- duk_call(thr, 2); /* -> [ ... res ] */
+ duk_dup(thr, idx_fn); /* -> [ ... x y fn ] */
+ duk_insert(thr, -3); /* -> [ ... fn x y ] */
+ duk_call(thr, 2); /* -> [ ... res ] */
/* ES5 is a bit vague about what to do if the return value is
* not a number. ES2015 provides a concrete description:
@@ -24860,10 +26838,10 @@ DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_hthread *thr, duk_int_t id
DUK_ASSERT(h1 != NULL);
DUK_ASSERT(h2 != NULL);
- ret = duk_js_string_compare(h1, h2); /* retval is directly usable */
+ ret = duk_js_string_compare(h1, h2); /* retval is directly usable */
goto pop_ret;
- pop_ret:
+pop_ret:
duk_pop_2_unsafe(thr);
DUK_DDD(DUK_DDDPRINT("-> result %ld", (long) ret));
return ret;
@@ -24871,7 +26849,7 @@ DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_hthread *thr, duk_int_t id
DUK_LOCAL void duk__array_sort_swap(duk_hthread *thr, duk_int_t l, duk_int_t r) {
duk_bool_t have_l, have_r;
- duk_idx_t idx_obj = 1; /* fixed offset in valstack */
+ duk_idx_t idx_obj = 1; /* fixed offset in valstack */
if (l == r) {
return;
@@ -24924,8 +26902,7 @@ DUK_LOCAL void duk__debuglog_qsort_state(duk_hthread *thr, duk_int_t lo, duk_int
*ptr++ = ']';
*ptr++ = '\0';
- DUK_DDD(DUK_DDDPRINT("%s (lo=%ld, hi=%ld, pivot=%ld)",
- (const char *) buf, (long) lo, (long) hi, (long) pivot));
+ DUK_DDD(DUK_DDDPRINT("%s (lo=%ld, hi=%ld, pivot=%ld)", (const char *) buf, (long) lo, (long) hi, (long) pivot));
}
#endif
@@ -24934,8 +26911,7 @@ DUK_LOCAL void duk__array_qsort(duk_hthread *thr, duk_int_t lo, duk_int_t hi) {
/* The lo/hi indices may be crossed and hi < 0 is possible at entry. */
- DUK_DDD(DUK_DDDPRINT("duk__array_qsort: lo=%ld, hi=%ld, obj=%!T",
- (long) lo, (long) hi, (duk_tval *) duk_get_tval(thr, 1)));
+ DUK_DDD(DUK_DDDPRINT("duk__array_qsort: lo=%ld, hi=%ld, obj=%!T", (long) lo, (long) hi, (duk_tval *) duk_get_tval(thr, 1)));
DUK_ASSERT_TOP(thr, 3);
@@ -24953,7 +26929,7 @@ DUK_LOCAL void duk__array_qsort(duk_hthread *thr, duk_int_t lo, duk_int_t hi) {
DUK_ASSERT(hi - lo + 1 >= 2);
/* randomized pivot selection */
- p = lo + (duk_int_t) (DUK_UTIL_GET_RANDOM_DOUBLE(thr) * (duk_double_t) (hi - lo + 1));
+ p = lo + (duk_int_t) (duk_util_get_random_double(thr) * (duk_double_t) (hi - lo + 1));
DUK_ASSERT(p >= lo && p <= hi);
DUK_DDD(DUK_DDDPRINT("lo=%ld, hi=%ld, chose pivot p=%ld", (long) lo, (long) hi, (long) p));
@@ -24967,23 +26943,21 @@ DUK_LOCAL void duk__array_qsort(duk_hthread *thr, duk_int_t lo, duk_int_t hi) {
for (;;) {
/* find elements to swap */
for (;;) {
- DUK_DDD(DUK_DDDPRINT("left scan: l=%ld, r=%ld, p=%ld",
- (long) l, (long) r, (long) p));
+ DUK_DDD(DUK_DDDPRINT("left scan: l=%ld, r=%ld, p=%ld", (long) l, (long) r, (long) p));
if (l >= hi) {
break;
}
- if (duk__array_sort_compare(thr, l, p) >= 0) { /* !(l < p) */
+ if (duk__array_sort_compare(thr, l, p) >= 0) { /* !(l < p) */
break;
}
l++;
}
for (;;) {
- DUK_DDD(DUK_DDDPRINT("right scan: l=%ld, r=%ld, p=%ld",
- (long) l, (long) r, (long) p));
+ DUK_DDD(DUK_DDDPRINT("right scan: l=%ld, r=%ld, p=%ld", (long) l, (long) r, (long) p));
if (r <= lo) {
break;
}
- if (duk__array_sort_compare(thr, p, r) >= 0) { /* !(p < r) */
+ if (duk__array_sort_compare(thr, p, r) >= 0) { /* !(p < r) */
break;
}
r--;
@@ -25001,7 +26975,7 @@ DUK_LOCAL void duk__array_qsort(duk_hthread *thr, duk_int_t lo, duk_int_t hi) {
l++;
r--;
}
- done:
+done:
/* Note that 'l' and 'r' may cross, i.e. r < l */
DUK_ASSERT(l >= lo && l <= hi);
DUK_ASSERT(r >= lo && r <= hi);
@@ -25045,7 +27019,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_sort(duk_hthread *thr) {
DUK_ASSERT_TOP(thr, 3);
duk_pop_nodecref_unsafe(thr);
- return 1; /* return ToObject(this) */
+ return 1; /* return ToObject(this) */
}
/*
@@ -25138,7 +27112,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_splice(duk_hthread *thr) {
for (i = 0; i < del_count; i++) {
if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (act_start + i))) {
- duk_xdef_prop_index_wec(thr, -2, (duk_uarridx_t) i); /* throw flag irrelevant (false in std alg) */
+ duk_xdef_prop_index_wec(thr, -2, (duk_uarridx_t) i); /* throw flag irrelevant (false in std alg) */
} else {
duk_pop_undefined(thr);
}
@@ -25208,7 +27182,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_splice(duk_hthread *thr) {
/* Step 15: insert itemCount elements into the hole made above */
for (i = 0; i < item_count; i++) {
- duk_dup(thr, i + 2); /* args start at index 2 */
+ duk_dup(thr, i + 2); /* args start at index 2 */
duk_put_prop_index(thr, -4, (duk_uarridx_t) (act_start + i));
}
@@ -25271,7 +27245,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reverse(duk_hthread *thr) {
}
DUK_ASSERT_TOP(thr, 2);
- duk_pop_unsafe(thr); /* -> [ ToObject(this) ] */
+ duk_pop_unsafe(thr); /* -> [ ToObject(this) ] */
return 1;
}
@@ -25421,26 +27395,32 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_unshift(duk_hthread *thr) {
if (duk_get_prop_index(thr, -2, (duk_uarridx_t) i)) {
/* fromPresent = true */
/* [ ... ToObject(this) ToUint32(length) val ] */
- duk_put_prop_index(thr, -3, (duk_uarridx_t) (i + (duk_uint32_t) nargs)); /* -> [ ... ToObject(this) ToUint32(length) ] */
+ duk_put_prop_index(
+ thr,
+ -3,
+ (duk_uarridx_t) (i + (duk_uint32_t) nargs)); /* -> [ ... ToObject(this) ToUint32(length) ] */
} else {
/* fromPresent = false */
/* [ ... ToObject(this) ToUint32(length) val ] */
duk_pop_undefined(thr);
- duk_del_prop_index(thr, -2, (duk_uarridx_t) (i + (duk_uint32_t) nargs)); /* -> [ ... ToObject(this) ToUint32(length) ] */
+ duk_del_prop_index(
+ thr,
+ -2,
+ (duk_uarridx_t) (i + (duk_uint32_t) nargs)); /* -> [ ... ToObject(this) ToUint32(length) ] */
}
DUK_ASSERT_TOP(thr, nargs + 2);
}
for (i = 0; i < (duk_uint32_t) nargs; i++) {
DUK_ASSERT_TOP(thr, nargs + 2);
- duk_dup(thr, (duk_idx_t) i); /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */
+ duk_dup(thr, (duk_idx_t) i); /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */
duk_put_prop_index(thr, -3, (duk_uarridx_t) i);
DUK_ASSERT_TOP(thr, nargs + 2);
}
DUK_ASSERT_TOP(thr, nargs + 2);
duk_push_u32(thr, len + (duk_uint32_t) nargs);
- duk_dup_top(thr); /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */
+ duk_dup_top(thr); /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */
duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);
return 1;
}
@@ -25453,7 +27433,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_hthread *thr) {
duk_idx_t nargs;
duk_int_t i, len;
duk_int_t from_idx;
- duk_small_int_t idx_step = duk_get_current_magic(thr); /* idx_step is +1 for indexOf, -1 for lastIndexOf */
+ duk_small_int_t idx_step = duk_get_current_magic(thr); /* idx_step is +1 for indexOf, -1 for lastIndexOf */
/* lastIndexOf() needs to be a vararg function because we must distinguish
* between an undefined fromIndex and a "not given" fromIndex; indexOf() is
@@ -25491,10 +27471,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_hthread *thr) {
* lastIndexOf: clamp fromIndex to [-len - 1, len - 1]
* (if clamped to -len-1 -> fromIndex becomes -1, terminates for-loop directly)
*/
- from_idx = duk_to_int_clamped(thr,
- 1,
- (idx_step > 0 ? -len : -len - 1),
- (idx_step > 0 ? len : len - 1));
+ from_idx = duk_to_int_clamped(thr, 1, (idx_step > 0 ? -len : -len - 1), (idx_step > 0 ? len : len - 1));
if (from_idx < 0) {
/* for lastIndexOf, result may be -1 (mark immediate termination) */
from_idx = len + from_idx;
@@ -25530,7 +27507,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_hthread *thr) {
duk_pop_unsafe(thr);
}
- not_found:
+not_found:
duk_push_int(thr, -1);
return 1;
}
@@ -25539,11 +27516,11 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_hthread *thr) {
* every(), some(), forEach(), map(), filter()
*/
-#define DUK__ITER_EVERY 0
-#define DUK__ITER_SOME 1
-#define DUK__ITER_FOREACH 2
-#define DUK__ITER_MAP 3
-#define DUK__ITER_FILTER 4
+#define DUK__ITER_EVERY 0
+#define DUK__ITER_SOME 1
+#define DUK__ITER_FOREACH 2
+#define DUK__ITER_MAP 3
+#define DUK__ITER_FILTER 4
/* XXX: This helper is a bit awkward because the handling for the different iteration
* callers is quite different. This now compiles to a bit less than 500 bytes, so with
@@ -25578,25 +27555,17 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_hthread *thr) {
* stack[4] = result array (or undefined)
*/
- k = 0; /* result index for filter() */
+ k = 0; /* result index for filter() */
for (i = 0; i < len; i++) {
DUK_ASSERT_TOP(thr, 5);
if (!duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
-#if defined(DUK_USE_NONSTD_ARRAY_MAP_TRAILER)
- /* Real world behavior for map(): trailing non-existent
- * elements don't invoke the user callback, but are still
- * counted towards result 'length'.
+ /* For 'map' trailing missing elements don't invoke the
+ * callback but count towards the result length.
*/
if (iter_type == DUK__ITER_MAP) {
res_length = i + 1;
}
-#else
- /* Standard behavior for map(): trailing non-existent
- * elements don't invoke the user callback and are not
- * counted towards result 'length'.
- */
-#endif
duk_pop_undefined(thr);
continue;
}
@@ -25610,7 +27579,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_hthread *thr) {
duk_dup_1(thr);
duk_dup_m3(thr);
duk_push_u32(thr, i);
- duk_dup_2(thr); /* [ ... val callback thisArg val i obj ] */
+ duk_dup_2(thr); /* [ ... val callback thisArg val i obj ] */
duk_call_method(thr, 3); /* -> [ ... val retval ] */
switch (iter_type) {
@@ -25633,13 +27602,13 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_hthread *thr) {
break;
case DUK__ITER_MAP:
duk_dup_top(thr);
- duk_xdef_prop_index_wec(thr, 4, (duk_uarridx_t) i); /* retval to result[i] */
+ duk_xdef_prop_index_wec(thr, 4, (duk_uarridx_t) i); /* retval to result[i] */
res_length = i + 1;
break;
case DUK__ITER_FILTER:
bval = duk_to_boolean(thr, -1);
if (bval) {
- duk_dup_m2(thr); /* orig value */
+ duk_dup_m2(thr); /* orig value */
duk_xdef_prop_index_wec(thr, 4, (duk_uarridx_t) k);
k++;
res_length = k;
@@ -25667,7 +27636,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_hthread *thr) {
case DUK__ITER_MAP:
case DUK__ITER_FILTER:
DUK_ASSERT_TOP(thr, 5);
- DUK_ASSERT(duk_is_array(thr, -1)); /* topmost element is the result array already */
+ DUK_ASSERT(duk_is_array(thr, -1)); /* topmost element is the result array already */
duk_push_u32(thr, res_length);
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
break;
@@ -25687,7 +27656,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_hthread *thr) {
duk_idx_t nargs;
duk_bool_t have_acc;
duk_uint32_t i, len;
- duk_small_int_t idx_step = duk_get_current_magic(thr); /* idx_step is +1 for reduce, -1 for reduceRight */
+ duk_small_int_t idx_step = duk_get_current_magic(thr); /* idx_step is +1 for reduce, -1 for reduceRight */
/* We're a varargs function because we need to detect whether
* initialValue was given or not.
@@ -25711,8 +27680,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_hthread *thr) {
duk_dup_1(thr);
have_acc = 1;
}
- DUK_DDD(DUK_DDDPRINT("have_acc=%ld, acc=%!T",
- (long) have_acc, (duk_tval *) duk_get_tval(thr, 3)));
+ DUK_DDD(DUK_DDDPRINT("have_acc=%ld, acc=%!T", (long) have_acc, (duk_tval *) duk_get_tval(thr, 3)));
/* For len == 0, i is initialized to len - 1 which underflows.
* The condition (i < len) will then exit the for-loop on the
@@ -25720,16 +27688,16 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_hthread *thr) {
* happens by i underflowing.
*/
- for (i = (idx_step >= 0 ? 0 : len - 1);
- i < len; /* i >= 0 would always be true */
+ for (i = (idx_step >= 0 ? 0 : len - 1); i < len; /* i >= 0 would always be true */
i += (duk_uint32_t) idx_step) {
DUK_DDD(DUK_DDDPRINT("i=%ld, len=%ld, have_acc=%ld, top=%ld, acc=%!T",
- (long) i, (long) len, (long) have_acc,
+ (long) i,
+ (long) len,
+ (long) have_acc,
(long) duk_get_top(thr),
(duk_tval *) duk_get_tval(thr, 4)));
- DUK_ASSERT((have_acc && duk_get_top(thr) == 5) ||
- (!have_acc && duk_get_top(thr) == 4));
+ DUK_ASSERT((have_acc && duk_get_top(thr) == 5) || (!have_acc && duk_get_top(thr) == 4));
if (!duk_has_prop_index(thr, 2, (duk_uarridx_t) i)) {
continue;
@@ -25748,8 +27716,10 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_hthread *thr) {
duk_push_u32(thr, i);
duk_dup_2(thr);
DUK_DDD(DUK_DDDPRINT("calling reduce function: func=%!T, prev=%!T, curr=%!T, idx=%!T, obj=%!T",
- (duk_tval *) duk_get_tval(thr, -5), (duk_tval *) duk_get_tval(thr, -4),
- (duk_tval *) duk_get_tval(thr, -3), (duk_tval *) duk_get_tval(thr, -2),
+ (duk_tval *) duk_get_tval(thr, -5),
+ (duk_tval *) duk_get_tval(thr, -4),
+ (duk_tval *) duk_get_tval(thr, -3),
+ (duk_tval *) duk_get_tval(thr, -2),
(duk_tval *) duk_get_tval(thr, -1)));
duk_call(thr, 4);
DUK_DDD(DUK_DDDPRINT("-> result: %!T", (duk_tval *) duk_get_tval(thr, -1)));
@@ -25766,7 +27736,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_hthread *thr) {
return 1;
}
-#endif /* DUK_USE_ARRAY_BUILTIN */
+#endif /* DUK_USE_ARRAY_BUILTIN */
/* automatic undefs */
#undef DUK__ARRAY_MID_JOIN_LIMIT
@@ -25807,7 +27777,7 @@ DUK_INTERNAL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_hthread *thr
DUK_ASSERT(h != NULL);
if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_BOOLEAN) {
- duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
+ duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
DUK_ASSERT(duk_is_boolean(thr, -1));
goto type_ok;
}
@@ -25816,7 +27786,7 @@ DUK_INTERNAL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_hthread *thr
DUK_DCERROR_TYPE_INVALID_ARGS(thr);
/* never here */
- type_ok:
+type_ok:
if (coerce_tostring) {
duk_to_string(thr, -1);
}
@@ -25836,14 +27806,14 @@ DUK_INTERNAL duk_ret_t duk_bi_boolean_constructor(duk_hthread *thr) {
DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_BOOLEAN);
- duk_dup_0(thr); /* -> [ val obj val ] */
- duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE); /* XXX: proper flags? */
- } /* unbalanced stack */
+ duk_dup_0(thr); /* -> [ val obj val ] */
+ duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE); /* XXX: proper flags? */
+ } /* unbalanced stack */
return 1;
}
-#endif /* DUK_USE_BOOLEAN_BUILTIN */
+#endif /* DUK_USE_BOOLEAN_BUILTIN */
/*
* ES2015 TypedArray and Node.js Buffer built-ins
*/
@@ -25859,57 +27829,38 @@ DUK_INTERNAL duk_ret_t duk_bi_boolean_constructor(duk_hthread *thr) {
* default internal prototype.
*/
static const duk_uint8_t duk__buffer_proto_from_classnum[] = {
- DUK_BIDX_ARRAYBUFFER_PROTOTYPE,
- DUK_BIDX_DATAVIEW_PROTOTYPE,
- DUK_BIDX_INT8ARRAY_PROTOTYPE,
- DUK_BIDX_UINT8ARRAY_PROTOTYPE,
- DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
- DUK_BIDX_INT16ARRAY_PROTOTYPE,
- DUK_BIDX_UINT16ARRAY_PROTOTYPE,
- DUK_BIDX_INT32ARRAY_PROTOTYPE,
- DUK_BIDX_UINT32ARRAY_PROTOTYPE,
- DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
- DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
+ DUK_BIDX_ARRAYBUFFER_PROTOTYPE, DUK_BIDX_DATAVIEW_PROTOTYPE, DUK_BIDX_INT8ARRAY_PROTOTYPE,
+ DUK_BIDX_UINT8ARRAY_PROTOTYPE, DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE, DUK_BIDX_INT16ARRAY_PROTOTYPE,
+ DUK_BIDX_UINT16ARRAY_PROTOTYPE, DUK_BIDX_INT32ARRAY_PROTOTYPE, DUK_BIDX_UINT32ARRAY_PROTOTYPE,
+ DUK_BIDX_FLOAT32ARRAY_PROTOTYPE, DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
};
/* Map DUK_HBUFOBJ_ELEM_xxx to duk_hobject class number.
* Sync with duk_hbufobj.h and duk_hobject.h.
*/
-static const duk_uint8_t duk__buffer_class_from_elemtype[9] = {
- DUK_HOBJECT_CLASS_UINT8ARRAY,
- DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY,
- DUK_HOBJECT_CLASS_INT8ARRAY,
- DUK_HOBJECT_CLASS_UINT16ARRAY,
- DUK_HOBJECT_CLASS_INT16ARRAY,
- DUK_HOBJECT_CLASS_UINT32ARRAY,
- DUK_HOBJECT_CLASS_INT32ARRAY,
- DUK_HOBJECT_CLASS_FLOAT32ARRAY,
- DUK_HOBJECT_CLASS_FLOAT64ARRAY
-};
+static const duk_uint8_t duk__buffer_class_from_elemtype[9] = { DUK_HOBJECT_CLASS_UINT8ARRAY, DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY,
+ DUK_HOBJECT_CLASS_INT8ARRAY, DUK_HOBJECT_CLASS_UINT16ARRAY,
+ DUK_HOBJECT_CLASS_INT16ARRAY, DUK_HOBJECT_CLASS_UINT32ARRAY,
+ DUK_HOBJECT_CLASS_INT32ARRAY, DUK_HOBJECT_CLASS_FLOAT32ARRAY,
+ DUK_HOBJECT_CLASS_FLOAT64ARRAY };
/* Map DUK_HBUFOBJ_ELEM_xxx to prototype object built-in index.
* Sync with duk_hbufobj.h.
*/
static const duk_uint8_t duk__buffer_proto_from_elemtype[9] = {
- DUK_BIDX_UINT8ARRAY_PROTOTYPE,
- DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
- DUK_BIDX_INT8ARRAY_PROTOTYPE,
- DUK_BIDX_UINT16ARRAY_PROTOTYPE,
- DUK_BIDX_INT16ARRAY_PROTOTYPE,
- DUK_BIDX_UINT32ARRAY_PROTOTYPE,
- DUK_BIDX_INT32ARRAY_PROTOTYPE,
- DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
- DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
+ DUK_BIDX_UINT8ARRAY_PROTOTYPE, DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE, DUK_BIDX_INT8ARRAY_PROTOTYPE,
+ DUK_BIDX_UINT16ARRAY_PROTOTYPE, DUK_BIDX_INT16ARRAY_PROTOTYPE, DUK_BIDX_UINT32ARRAY_PROTOTYPE,
+ DUK_BIDX_INT32ARRAY_PROTOTYPE, DUK_BIDX_FLOAT32ARRAY_PROTOTYPE, DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
};
/* Map DUK__FLD_xxx to byte size. */
static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6] = {
- 1, /* DUK__FLD_8BIT */
- 2, /* DUK__FLD_16BIT */
- 4, /* DUK__FLD_32BIT */
- 4, /* DUK__FLD_FLOAT */
- 8, /* DUK__FLD_DOUBLE */
- 0 /* DUK__FLD_VARINT; not relevant here */
+ 1, /* DUK__FLD_8BIT */
+ 2, /* DUK__FLD_16BIT */
+ 4, /* DUK__FLD_32BIT */
+ 4, /* DUK__FLD_FLOAT */
+ 8, /* DUK__FLD_DOUBLE */
+ 0 /* DUK__FLD_VARINT; not relevant here */
};
/* Bitfield for each DUK_HBUFOBJ_ELEM_xxx indicating which element types
@@ -25921,36 +27872,27 @@ static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6] = {
#if !defined(DUK_USE_PREFER_SIZE)
static duk_uint16_t duk__buffer_elemtype_copy_compatible[9] = {
/* xxx -> DUK_HBUFOBJ_ELEM_UINT8 */
- (1U << DUK_HBUFOBJ_ELEM_UINT8) |
- (1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) |
- (1U << DUK_HBUFOBJ_ELEM_INT8),
+ (1U << DUK_HBUFOBJ_ELEM_UINT8) | (1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) | (1U << DUK_HBUFOBJ_ELEM_INT8),
/* xxx -> DUK_HBUFOBJ_ELEM_UINT8CLAMPED
* Note: INT8 is -not- copy compatible, e.g. -1 would coerce to 0x00.
*/
- (1U << DUK_HBUFOBJ_ELEM_UINT8) |
- (1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED),
+ (1U << DUK_HBUFOBJ_ELEM_UINT8) | (1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED),
/* xxx -> DUK_HBUFOBJ_ELEM_INT8 */
- (1U << DUK_HBUFOBJ_ELEM_UINT8) |
- (1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) |
- (1U << DUK_HBUFOBJ_ELEM_INT8),
+ (1U << DUK_HBUFOBJ_ELEM_UINT8) | (1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) | (1U << DUK_HBUFOBJ_ELEM_INT8),
/* xxx -> DUK_HBUFOBJ_ELEM_UINT16 */
- (1U << DUK_HBUFOBJ_ELEM_UINT16) |
- (1U << DUK_HBUFOBJ_ELEM_INT16),
+ (1U << DUK_HBUFOBJ_ELEM_UINT16) | (1U << DUK_HBUFOBJ_ELEM_INT16),
/* xxx -> DUK_HBUFOBJ_ELEM_INT16 */
- (1U << DUK_HBUFOBJ_ELEM_UINT16) |
- (1U << DUK_HBUFOBJ_ELEM_INT16),
+ (1U << DUK_HBUFOBJ_ELEM_UINT16) | (1U << DUK_HBUFOBJ_ELEM_INT16),
/* xxx -> DUK_HBUFOBJ_ELEM_UINT32 */
- (1U << DUK_HBUFOBJ_ELEM_UINT32) |
- (1U << DUK_HBUFOBJ_ELEM_INT32),
+ (1U << DUK_HBUFOBJ_ELEM_UINT32) | (1U << DUK_HBUFOBJ_ELEM_INT32),
/* xxx -> DUK_HBUFOBJ_ELEM_INT32 */
- (1U << DUK_HBUFOBJ_ELEM_UINT32) |
- (1U << DUK_HBUFOBJ_ELEM_INT32),
+ (1U << DUK_HBUFOBJ_ELEM_UINT32) | (1U << DUK_HBUFOBJ_ELEM_INT32),
/* xxx -> DUK_HBUFOBJ_ELEM_FLOAT32 */
(1U << DUK_HBUFOBJ_ELEM_FLOAT32),
@@ -25958,7 +27900,7 @@ static duk_uint16_t duk__buffer_elemtype_copy_compatible[9] = {
/* xxx -> DUK_HBUFOBJ_ELEM_FLOAT64 */
(1U << DUK_HBUFOBJ_ELEM_FLOAT64)
};
-#endif /* !DUK_USE_PREFER_SIZE */
+#endif /* !DUK_USE_PREFER_SIZE */
DUK_LOCAL duk_hbufobj *duk__hbufobj_promote_this(duk_hthread *thr) {
duk_tval *tv_dst;
@@ -25967,7 +27909,7 @@ DUK_LOCAL duk_hbufobj *duk__hbufobj_promote_this(duk_hthread *thr) {
duk_push_this(thr);
DUK_ASSERT(duk_is_buffer(thr, -1));
res = (duk_hbufobj *) duk_to_hobject(thr, -1);
- DUK_ASSERT_HBUFOBJ_VALID(res);
+ DUK_HBUFOBJ_ASSERT_VALID(res);
DUK_DD(DUK_DDPRINT("promoted 'this' automatically to an ArrayBuffer: %!iT", duk_get_tval(thr, -1)));
tv_dst = duk_get_borrowed_this_tval(thr);
@@ -25977,8 +27919,8 @@ DUK_LOCAL duk_hbufobj *duk__hbufobj_promote_this(duk_hthread *thr) {
return res;
}
-#define DUK__BUFOBJ_FLAG_THROW (1 << 0)
-#define DUK__BUFOBJ_FLAG_PROMOTE (1 << 1)
+#define DUK__BUFOBJ_FLAG_THROW (1 << 0)
+#define DUK__BUFOBJ_FLAG_PROMOTE (1 << 1)
/* Shared helper. When DUK__BUFOBJ_FLAG_PROMOTE is given, the return value is
* always a duk_hbufobj *. Without the flag the return value can also be a
@@ -25997,7 +27939,7 @@ DUK_LOCAL duk_heaphdr *duk__getrequire_bufobj_this(duk_hthread *thr, duk_small_u
h_this = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
DUK_ASSERT(h_this != NULL);
if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_this)) {
- DUK_ASSERT_HBUFOBJ_VALID(h_this);
+ DUK_HBUFOBJ_ASSERT_VALID(h_this);
return (duk_heaphdr *) h_this;
}
} else if (DUK_TVAL_IS_BUFFER(tv)) {
@@ -26011,7 +27953,7 @@ DUK_LOCAL duk_heaphdr *duk__getrequire_bufobj_this(duk_hthread *thr, duk_small_u
/* XXX: make this conditional to a flag if call sites need it? */
h_this = duk__hbufobj_promote_this(thr);
DUK_ASSERT(h_this != NULL);
- DUK_ASSERT_HBUFOBJ_VALID(h_this);
+ DUK_HBUFOBJ_ASSERT_VALID(h_this);
return (duk_heaphdr *) h_this;
} else {
/* XXX: ugly, share return pointer for duk_hbuffer. */
@@ -26021,6 +27963,7 @@ DUK_LOCAL duk_heaphdr *duk__getrequire_bufobj_this(duk_hthread *thr, duk_small_u
if (flags & DUK__BUFOBJ_FLAG_THROW) {
DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);
+ DUK_WO_NORETURN(return NULL;);
}
return NULL;
}
@@ -26051,26 +27994,26 @@ DUK_LOCAL duk_hbufobj *duk__require_bufobj_value(duk_hthread *thr, duk_idx_t idx
h_obj = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
DUK_ASSERT(h_obj != NULL);
if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_obj)) {
- DUK_ASSERT_HBUFOBJ_VALID(h_obj);
+ DUK_HBUFOBJ_ASSERT_VALID(h_obj);
return h_obj;
}
} else if (DUK_TVAL_IS_BUFFER(tv)) {
h_obj = (duk_hbufobj *) duk_to_hobject(thr, idx);
DUK_ASSERT(h_obj != NULL);
- DUK_ASSERT_HBUFOBJ_VALID(h_obj);
+ DUK_HBUFOBJ_ASSERT_VALID(h_obj);
return h_obj;
}
DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);
- return NULL; /* not reachable */
+ DUK_WO_NORETURN(return NULL;);
}
DUK_LOCAL void duk__set_bufobj_buffer(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_hbuffer *h_val) {
DUK_ASSERT(thr != NULL);
DUK_ASSERT(h_bufobj != NULL);
- DUK_ASSERT(h_bufobj->buf == NULL); /* no need to decref */
+ DUK_ASSERT(h_bufobj->buf == NULL); /* no need to decref */
DUK_ASSERT(h_val != NULL);
- DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+ DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
DUK_UNREF(thr);
h_bufobj->buf = h_val;
@@ -26080,7 +28023,7 @@ DUK_LOCAL void duk__set_bufobj_buffer(duk_hthread *thr, duk_hbufobj *h_bufobj, d
DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFOBJ_ELEM_UINT8);
DUK_ASSERT(h_bufobj->is_typedarray == 0);
- DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+ DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
}
/* Shared offset/length coercion helper. */
@@ -26104,12 +28047,12 @@ DUK_LOCAL void duk__resolve_offset_opt_length(duk_hthread *thr,
if (offset > h_bufarg->length) {
goto fail_range;
}
- DUK_ASSERT_DISABLE(offset >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(offset >= 0); /* unsigned */
DUK_ASSERT(offset <= h_bufarg->length);
if (duk_is_undefined(thr, idx_length)) {
DUK_ASSERT(h_bufarg->length >= offset);
- length = h_bufarg->length - offset; /* >= 0 */
+ length = h_bufarg->length - offset; /* >= 0 */
} else {
length_signed = duk_to_int(thr, idx_length);
if (length_signed < 0) {
@@ -26128,15 +28071,16 @@ DUK_LOCAL void duk__resolve_offset_opt_length(duk_hthread *thr,
}
}
}
- DUK_ASSERT_DISABLE(length >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(length >= 0); /* unsigned */
DUK_ASSERT(offset + length <= h_bufarg->length);
*out_offset = offset;
*out_length = length;
return;
- fail_range:
+fail_range:
DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS);
+ DUK_WO_NORETURN(return;);
}
/* Shared lenient buffer length clamping helper. No negative indices, no
@@ -26192,7 +28136,7 @@ DUK_LOCAL void duk__clamp_startend_negidx_shifted(duk_hthread *thr,
DUK_ASSERT(out_start_offset != NULL);
DUK_ASSERT(out_end_offset != NULL);
- buffer_length >>= buffer_shift; /* as (full) elements */
+ buffer_length >>= buffer_shift; /* as (full) elements */
/* Resolve start/end offset as element indices first; arguments
* at idx_start/idx_end are element offsets. Working with element
@@ -26263,7 +28207,7 @@ DUK_INTERNAL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_h
DUK_ASSERT(h_bufobj != NULL);
duk__set_bufobj_buffer(thr, h_bufobj, h_buf);
h_bufobj->is_typedarray = 1;
- DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+ DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
h_arrbuf = duk_push_bufobj_raw(thr,
DUK_HOBJECT_FLAG_EXTENSIBLE |
@@ -26273,7 +28217,7 @@ DUK_INTERNAL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_h
DUK_ASSERT(h_arrbuf != NULL);
duk__set_bufobj_buffer(thr, h_arrbuf, h_buf);
DUK_ASSERT(h_arrbuf->is_typedarray == 0);
- DUK_ASSERT_HBUFOBJ_VALID(h_arrbuf);
+ DUK_HBUFOBJ_ASSERT_VALID(h_arrbuf);
DUK_ASSERT(h_bufobj->buf_prop == NULL);
h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
@@ -26284,10 +28228,14 @@ DUK_INTERNAL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_h
}
/* Indexed read helper for buffer objects, also called from outside this file. */
-DUK_INTERNAL void duk_hbufobj_push_validated_read(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
+DUK_INTERNAL void duk_hbufobj_push_validated_read(duk_hthread *thr,
+ duk_hbufobj *h_bufobj,
+ duk_uint8_t *p,
+ duk_small_uint_t elem_size) {
duk_double_union du;
- DUK_MEMCPY((void *) du.uc, (const void *) p, (size_t) elem_size);
+ DUK_ASSERT(elem_size > 0);
+ duk_memcpy((void *) du.uc, (const void *) p, (size_t) elem_size);
switch (h_bufobj->elem_type) {
case DUK_HBUFOBJ_ELEM_UINT8:
@@ -26355,7 +28303,11 @@ DUK_INTERNAL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_b
du.ui[0] = (duk_uint32_t) duk_to_int32(thr, -1);
break;
case DUK_HBUFOBJ_ELEM_FLOAT32:
- du.f[0] = (duk_float_t) duk_to_number_m1(thr);
+ /* A double-to-float cast is undefined behavior in C99 if
+ * the cast is out-of-range, so use a helper. Example:
+ * runtime error: value -1e+100 is outside the range of representable values of type 'float'
+ */
+ du.f[0] = duk_double_to_float_t(duk_to_number_m1(thr));
break;
case DUK_HBUFOBJ_ELEM_FLOAT64:
du.d = (duk_double_t) duk_to_number_m1(thr);
@@ -26364,7 +28316,8 @@ DUK_INTERNAL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_b
DUK_UNREACHABLE();
}
- DUK_MEMCPY((void *) p, (const void *) du.uc, (size_t) elem_size);
+ DUK_ASSERT(elem_size > 0);
+ duk_memcpy((void *) p, (const void *) du.uc, (size_t) elem_size);
}
/* Helper to create a fixed buffer from argument value at index 0.
@@ -26400,12 +28353,14 @@ DUK_LOCAL duk_hbuffer *duk__hbufobj_fixed_from_argvalue(duk_hthread *thr) {
h_bufobj = (duk_hbufobj *) h;
if (DUK_UNLIKELY(h_bufobj->buf == NULL)) {
DUK_ERROR_TYPE_INVALID_ARGS(thr);
+ DUK_WO_NORETURN(return NULL;);
}
if (DUK_UNLIKELY(h_bufobj->offset != 0 || h_bufobj->length != DUK_HBUFFER_GET_SIZE(h_bufobj->buf))) {
/* No support for ArrayBuffers with slice
* offset/length.
*/
DUK_ERROR_TYPE_INVALID_ARGS(thr);
+ DUK_WO_NORETURN(return NULL;);
}
duk_push_hbuffer(thr, h_bufobj->buf);
return h_bufobj->buf;
@@ -26421,19 +28376,20 @@ DUK_LOCAL duk_hbuffer *duk__hbufobj_fixed_from_argvalue(duk_hthread *thr) {
}
default:
DUK_ERROR_TYPE_INVALID_ARGS(thr);
+ DUK_WO_NORETURN(return NULL;);
}
- done:
+done:
DUK_ASSERT(duk_is_buffer(thr, -1));
return duk_known_hbuffer(thr, -1);
- slow_copy:
+slow_copy:
/* XXX: fast path for typed arrays and other buffer objects? */
(void) duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
len = duk_to_int_clamped(thr, -1, 0, DUK_INT_MAX);
duk_pop(thr);
- buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len); /* no zeroing, all indices get initialized */
+ buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len); /* no zeroing, all indices get initialized */
for (i = 0; i < len; i++) {
/* XXX: fast path for array or buffer arguments? */
duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
@@ -26442,7 +28398,7 @@ DUK_LOCAL duk_hbuffer *duk__hbufobj_fixed_from_argvalue(duk_hthread *thr) {
}
goto done;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* Node.js Buffer constructor
@@ -26459,11 +28415,7 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_hthread *thr) {
h_buf = duk__hbufobj_fixed_from_argvalue(thr);
DUK_ASSERT(h_buf != NULL);
- duk_push_buffer_object(thr,
- -1,
- 0,
- DUK_HBUFFER_FIXED_GET_SIZE((duk_hbuffer_fixed *) h_buf),
- DUK_BUFOBJ_UINT8ARRAY);
+ duk_push_buffer_object(thr, -1, 0, DUK_HBUFFER_FIXED_GET_SIZE((duk_hbuffer_fixed *) (void *) h_buf), DUK_BUFOBJ_UINT8ARRAY);
duk_push_hobject_bidx(thr, DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
duk_set_prototype(thr, -2);
@@ -26471,7 +28423,7 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_hthread *thr) {
return 1;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* ArrayBuffer, DataView, and TypedArray constructors
@@ -26483,7 +28435,7 @@ DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_hthread *thr) {
duk_hbuffer *h_val;
duk_int_t len;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
duk_require_constructor_call(thr);
@@ -26495,22 +28447,20 @@ DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_hthread *thr) {
h_val = (duk_hbuffer *) duk_known_hbuffer(thr, -1);
h_bufobj = duk_push_bufobj_raw(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_BUFOBJ |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_BUFOBJ |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
DUK_ASSERT(h_bufobj != NULL);
duk__set_bufobj_buffer(thr, h_bufobj, h_val);
- DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+ DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
return 1;
- fail_length:
+fail_length:
DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
-
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/* Format of magic, bits:
* 0...1: elem size shift (0-3)
@@ -26550,8 +28500,8 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
* element type.
*/
magic = (duk_small_uint_t) duk_get_current_magic(thr);
- shift = magic & 0x03U; /* bits 0...1: shift */
- elem_type = (magic >> 2) & 0x0fU; /* bits 2...5: type */
+ shift = magic & 0x03U; /* bits 0...1: shift */
+ elem_type = (magic >> 2) & 0x0fU; /* bits 2...5: type */
elem_size = 1U << shift;
align_mask = elem_size - 1;
DUK_ASSERT(elem_type < sizeof(duk__buffer_proto_from_elemtype) / sizeof(duk_uint8_t));
@@ -26562,8 +28512,12 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
DUK_DD(DUK_DDPRINT("typedarray constructor, magic=%d, shift=%d, elem_type=%d, "
"elem_size=%d, proto_bidx=%d, class_num=%d",
- (int) magic, (int) shift, (int) elem_type, (int) elem_size,
- (int) proto_bidx, (int) class_num));
+ (int) magic,
+ (int) shift,
+ (int) elem_type,
+ (int) elem_size,
+ (int) proto_bidx,
+ (int) class_num));
/* Argument variants. When the argument is an ArrayBuffer a view to
* the same buffer is created; otherwise a new ArrayBuffer is always
@@ -26577,7 +28531,7 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
duk_hbufobj_promote_plain(thr, 0);
tv = duk_get_tval(thr, 0);
- DUK_ASSERT(tv != NULL); /* arg count */
+ DUK_ASSERT(tv != NULL); /* arg count */
if (DUK_TVAL_IS_OBJECT(tv)) {
h_obj = DUK_TVAL_GET_OBJECT(tv);
DUK_ASSERT(h_obj != NULL);
@@ -26597,8 +28551,7 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
goto fail_arguments;
}
byte_offset = (duk_uint_t) byte_offset_signed;
- if (byte_offset > h_bufarg->length ||
- (byte_offset & align_mask) != 0) {
+ if (byte_offset > h_bufarg->length || (byte_offset & align_mask) != 0) {
/* Must be >= 0 and multiple of element size. */
goto fail_arguments;
}
@@ -26638,9 +28591,8 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
DUK_ASSERT((elem_length << shift) == byte_length);
h_bufobj = duk_push_bufobj_raw(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_BUFOBJ |
- DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_BUFOBJ |
+ DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
(duk_small_int_t) proto_bidx);
h_val = h_bufarg->buf;
if (h_val == NULL) {
@@ -26653,7 +28605,7 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
h_bufobj->shift = (duk_uint8_t) shift;
h_bufobj->elem_type = (duk_uint8_t) elem_type;
h_bufobj->is_typedarray = 1;
- DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+ DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
/* Set .buffer to the argument ArrayBuffer. */
DUK_ASSERT(h_bufobj->buf_prop == NULL);
@@ -26668,7 +28620,7 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
*/
h_bufarg = (duk_hbufobj *) h_obj;
- DUK_ASSERT_HBUFOBJ_VALID(h_bufarg);
+ DUK_HBUFOBJ_ASSERT_VALID(h_bufarg);
elem_length_signed = (duk_int_t) (h_bufarg->length >> h_bufarg->shift);
if (h_bufarg->buf == NULL) {
DUK_DCERROR_TYPE_INVALID_ARGS(thr);
@@ -26683,11 +28635,13 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
"src byte_length=%ld, src shift=%d, "
"src/dst elem_length=%ld; "
"dst shift=%d -> dst byte_length=%ld",
- (long) h_bufarg->length, (int) h_bufarg->shift,
- (long) elem_length_signed, (int) shift,
+ (long) h_bufarg->length,
+ (int) h_bufarg->shift,
+ (long) elem_length_signed,
+ (int) shift,
(long) (elem_length_signed << shift)));
- copy_mode = 2; /* default is explicit index read/write copy */
+ copy_mode = 2; /* default is explicit index read/write copy */
#if !defined(DUK_USE_PREFER_SIZE)
/* With a size optimized build copy_mode 2 is enough.
* Modes 0 and 1 are faster but conceptually the same.
@@ -26696,14 +28650,14 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
if ((duk__buffer_elemtype_copy_compatible[elem_type] & (1 << h_bufarg->elem_type)) != 0) {
DUK_DDD(DUK_DDDPRINT("source/target are copy compatible, memcpy"));
- DUK_ASSERT(shift == h_bufarg->shift); /* byte sizes will match */
+ DUK_ASSERT(shift == h_bufarg->shift); /* byte sizes will match */
copy_mode = 0;
} else {
DUK_DDD(DUK_DDDPRINT("source/target not copy compatible but valid, fast copy"));
copy_mode = 1;
}
}
-#endif /* !DUK_USE_PREFER_SIZE */
+#endif /* !DUK_USE_PREFER_SIZE */
} else {
/* Array or Array-like */
elem_length_signed = (duk_int_t) duk_get_length(thr, 0);
@@ -26728,8 +28682,7 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
goto fail_arguments;
}
- DUK_DDD(DUK_DDDPRINT("elem_length=%ld, byte_length=%ld",
- (long) elem_length, (long) byte_length));
+ DUK_DDD(DUK_DDDPRINT("elem_length=%ld, byte_length=%ld", (long) elem_length, (long) byte_length));
/* ArrayBuffer argument is handled specially above; the rest of the
* argument variants are handled by shared code below.
@@ -26744,11 +28697,10 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
h_val = duk_known_hbuffer(thr, -1);
DUK_ASSERT(h_val != NULL);
- h_bufobj = duk_push_bufobj_raw(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_BUFOBJ |
- DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
- (duk_small_int_t) proto_bidx);
+ h_bufobj =
+ duk_push_bufobj_raw(thr,
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_BUFOBJ | DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
+ (duk_small_int_t) proto_bidx);
h_bufobj->buf = h_val;
DUK_HBUFFER_INCREF(thr, h_val);
@@ -26757,7 +28709,7 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
h_bufobj->shift = (duk_uint8_t) shift;
h_bufobj->elem_type = (duk_uint8_t) elem_type;
h_bufobj->is_typedarray = 1;
- DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+ DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
/* Copy values, the copy method depends on the arguments.
*
@@ -26788,9 +28740,11 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
p_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
DUK_DDD(DUK_DDDPRINT("using memcpy: p_src=%p, p_dst=%p, byte_length=%ld",
- (void *) p_src, (void *) p_dst, (long) byte_length));
+ (void *) p_src,
+ (void *) p_dst,
+ (long) byte_length));
- DUK_MEMCPY((void *) p_dst, (const void *) p_src, (size_t) byte_length);
+ duk_memcpy_unsafe((void *) p_dst, (const void *) p_src, (size_t) byte_length);
break;
}
case 1: {
@@ -26818,13 +28772,18 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
DUK_DDD(DUK_DDDPRINT("using fast copy: p_src=%p, p_src_end=%p, p_dst=%p, "
"src_elem_size=%d, dst_elem_size=%d",
- (void *) p_src, (void *) p_src_end, (void *) p_dst,
- (int) src_elem_size, (int) dst_elem_size));
+ (void *) p_src,
+ (void *) p_src_end,
+ (void *) p_dst,
+ (int) src_elem_size,
+ (int) dst_elem_size));
while (p_src != p_src_end) {
DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
"p_src=%p, p_src_end=%p, p_dst=%p",
- (void *) p_src, (void *) p_src_end, (void *) p_dst));
+ (void *) p_src,
+ (void *) p_src_end,
+ (void *) p_dst));
/* A validated read() is always a number, so it's write coercion
* is always side effect free an won't invalidate pointers etc.
*/
@@ -26836,7 +28795,7 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
}
break;
}
-#endif /* !DUK_USE_PREFER_SIZE */
+#endif /* !DUK_USE_PREFER_SIZE */
case 2: {
/* Copy values by index reads and writes. Let virtual
* property handling take care of coercion.
@@ -26865,10 +28824,10 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
return 1;
- fail_arguments:
+fail_arguments:
DUK_DCERROR_RANGE_INVALID_ARGS(thr);
}
-#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
/* When bufferobject support is disabled, new Uint8Array() could still be
* supported to create a plain fixed buffer. Disabled for now.
*/
@@ -26895,8 +28854,8 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
fail_arguments:
DUK_DCERROR_RANGE_INVALID_ARGS(thr);
}
-#endif /* 0 */
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* 0 */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_dataview_constructor(duk_hthread *thr) {
@@ -26919,9 +28878,8 @@ DUK_INTERNAL duk_ret_t duk_bi_dataview_constructor(duk_hthread *thr) {
DUK_ASSERT(offset + length <= h_bufarg->length);
h_bufobj = duk_push_bufobj_raw(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_BUFOBJ |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATAVIEW),
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_BUFOBJ |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATAVIEW),
DUK_BIDX_DATAVIEW_PROTOTYPE);
h_val = h_bufarg->buf;
@@ -26941,10 +28899,10 @@ DUK_INTERNAL duk_ret_t duk_bi_dataview_constructor(duk_hthread *thr) {
DUK_ASSERT(h_bufarg != NULL);
DUK_HBUFOBJ_INCREF(thr, h_bufarg);
- DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+ DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
return 1;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* ArrayBuffer.isView()
@@ -26970,7 +28928,7 @@ DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_isview(duk_hthread *thr) {
duk_push_boolean(thr, ret);
return 1;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* Uint8Array.allocPlain()
@@ -26981,7 +28939,7 @@ DUK_INTERNAL duk_ret_t duk_bi_uint8array_allocplain(duk_hthread *thr) {
duk__hbufobj_fixed_from_argvalue(thr);
return 1;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* Uint8Array.plainOf()
@@ -27010,7 +28968,7 @@ DUK_INTERNAL duk_ret_t duk_bi_uint8array_plainof(duk_hthread *thr) {
}
return 1;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* Node.js Buffer: toString([encoding], [start], [end])
@@ -27026,10 +28984,10 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_hthread *thr) {
h_this = duk__get_bufobj_this(thr);
if (h_this == NULL) {
/* XXX: happens e.g. when evaluating: String(Buffer.prototype). */
- duk_push_string(thr, "[object Object]");
+ duk_push_literal(thr, "[object Object]");
return 1;
}
- DUK_ASSERT_HBUFOBJ_VALID(h_this);
+ DUK_HBUFOBJ_ASSERT_VALID(h_this);
/* Ignore encoding for now. */
@@ -27041,12 +28999,11 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_hthread *thr) {
&end_offset);
slice_length = (duk_size_t) (end_offset - start_offset);
- buf_slice = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, slice_length); /* all bytes initialized below */
+ buf_slice = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, slice_length); /* all bytes initialized below */
DUK_ASSERT(buf_slice != NULL);
/* Neutered or uncovered, TypeError. */
- if (h_this->buf == NULL ||
- !DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length)) {
+ if (h_this->buf == NULL || !DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length)) {
DUK_DCERROR_TYPE_INVALID_ARGS(thr);
}
@@ -27057,9 +29014,9 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_hthread *thr) {
*/
DUK_ASSERT(DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length));
- DUK_MEMCPY((void *) buf_slice,
- (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
- (size_t) slice_length);
+ duk_memcpy_unsafe((void *) buf_slice,
+ (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
+ (size_t) slice_length);
/* Use the equivalent of: new TextEncoder().encode(this) to convert the
* string. Result will be valid UTF-8; non-CESU-8 inputs are currently
@@ -27069,7 +29026,7 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_hthread *thr) {
duk_set_top(thr, 1);
return duk_textdecoder_decode_utf8_nodejs(thr);
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* Node.js Buffer.prototype: toJSON()
@@ -27099,18 +29056,19 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_hthread *thr) {
/* XXX: uninitialized would be OK */
DUK_ASSERT_DISABLE((duk_size_t) h_this->length <= (duk_size_t) DUK_UINT32_MAX);
- tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) h_this->length); /* XXX: needs revision with >4G buffers */
+ tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) h_this->length); /* XXX: needs revision with >4G buffers */
+ DUK_ASSERT(!duk_is_bare_object(thr, -1));
DUK_ASSERT(h_this->buf != NULL);
buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
for (i = 0, n = h_this->length; i < n; i++) {
- DUK_TVAL_SET_U32(tv + i, (duk_uint32_t) buf[i]); /* no need for decref or incref */
+ DUK_TVAL_SET_U32(tv + i, (duk_uint32_t) buf[i]); /* no need for decref or incref */
}
duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_DATA);
return 1;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* Node.js Buffer.prototype.equals()
@@ -27145,14 +29103,14 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_compare_shared(duk_hthread *thr) {
* matters is to be memory safe.
*/
- if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg1) &&
- DUK_HBUFOBJ_VALID_SLICE(h_bufarg2)) {
- comp_res = duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg1->buf) + h_bufarg1->offset,
- (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg2->buf) + h_bufarg2->offset,
- (duk_size_t) h_bufarg1->length,
- (duk_size_t) h_bufarg2->length);
+ if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg1) && DUK_HBUFOBJ_VALID_SLICE(h_bufarg2)) {
+ comp_res = duk_js_data_compare(
+ (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg1->buf) + h_bufarg1->offset,
+ (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg2->buf) + h_bufarg2->offset,
+ (duk_size_t) h_bufarg1->length,
+ (duk_size_t) h_bufarg2->length);
} else {
- comp_res = -1; /* either nonzero value is ok */
+ comp_res = -1; /* either nonzero value is ok */
}
if (magic & 0x01U) {
@@ -27165,7 +29123,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_compare_shared(duk_hthread *thr) {
return 1;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* Node.js Buffer.prototype.fill()
@@ -27210,7 +29168,10 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_hthread *thr) {
&fill_end);
DUK_DDD(DUK_DDDPRINT("fill: fill_value=%02x, fill_offset=%ld, fill_end=%ld, view length=%ld",
- (unsigned int) fill_value, (long) fill_offset, (long) fill_end, (long) h_this->length));
+ (unsigned int) fill_value,
+ (long) fill_offset,
+ (long) fill_end,
+ (long) h_this->length));
DUK_ASSERT(fill_end - fill_offset >= 0);
DUK_ASSERT(h_this->buf != NULL);
@@ -27221,7 +29182,7 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_hthread *thr) {
/* Handle single character fills as memset() even when
* the fill data comes from a one-char argument.
*/
- DUK_MEMSET((void *) p, (int) fill_str_ptr[0], (size_t) fill_length);
+ duk_memset_unsafe((void *) p, (int) fill_str_ptr[0], (size_t) fill_length);
} else if (fill_str_len > 1) {
duk_size_t i, n, t;
@@ -27239,7 +29200,7 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_hthread *thr) {
duk_push_this(thr);
return 1;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* Node.js Buffer.prototype.write(string, [offset], [length], [encoding])
@@ -27272,9 +29233,9 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_write(duk_hthread *thr) {
if (DUK_HBUFOBJ_VALID_SLICE(h_this)) {
/* Cannot overlap. */
- DUK_MEMCPY((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset),
- (const void *) str_data,
- (size_t) length);
+ duk_memcpy_unsafe((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset),
+ (const void *) str_data,
+ (size_t) length);
} else {
DUK_DDD(DUK_DDDPRINT("write() target buffer is not covered, silent ignore"));
}
@@ -27282,7 +29243,7 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_write(duk_hthread *thr) {
duk_push_uint(thr, length);
return 1;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* Node.js Buffer.prototype.copy()
@@ -27317,8 +29278,11 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_hthread *thr) {
DUK_DDD(DUK_DDDPRINT("checking copy args: target_start=%ld, target_length=%ld, "
"source_start=%ld, source_end=%ld, source_length=%ld",
- (long) target_start, (long) h_bufarg->length,
- (long) source_start, (long) source_end, (long) source_length));
+ (long) target_start,
+ (long) h_bufarg->length,
+ (long) source_start,
+ (long) source_end,
+ (long) source_length));
/* This behavior mostly mimics Node.js now. */
@@ -27329,9 +29293,9 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_hthread *thr) {
source_ustart = (duk_uint_t) source_start;
source_uend = (duk_uint_t) source_end;
target_ustart = (duk_uint_t) target_start;
- if (source_ustart >= source_uend || /* crossed offsets or zero size */
- source_ustart >= (duk_uint_t) source_length || /* source out-of-bounds (but positive) */
- target_ustart >= (duk_uint_t) target_length) { /* target out-of-bounds (but positive) */
+ if (source_ustart >= source_uend || /* crossed offsets or zero size */
+ source_ustart >= (duk_uint_t) source_length || /* source out-of-bounds (but positive) */
+ target_ustart >= (duk_uint_t) target_length) { /* target out-of-bounds (but positive) */
goto silent_ignore;
}
if (source_uend >= (duk_uint_t) source_length) {
@@ -27347,13 +29311,14 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_hthread *thr) {
* values in duk_int_t range. Adding them as duk_uint_t
* values is then guaranteed not to overflow.
*/
- DUK_ASSERT(target_ustart + copy_size >= target_ustart); /* no overflow */
- DUK_ASSERT(target_ustart + copy_size >= copy_size); /* no overflow */
+ DUK_ASSERT(target_ustart + copy_size >= target_ustart); /* no overflow */
+ DUK_ASSERT(target_ustart + copy_size >= copy_size); /* no overflow */
copy_size = (duk_uint_t) target_length - target_ustart;
}
DUK_DDD(DUK_DDDPRINT("making copy: target_ustart=%lu source_ustart=%lu copy_size=%lu",
- (unsigned long) target_ustart, (unsigned long) source_ustart,
+ (unsigned long) target_ustart,
+ (unsigned long) source_ustart,
(unsigned long) copy_size));
DUK_ASSERT(copy_size >= 1);
@@ -27363,32 +29328,32 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_hthread *thr) {
DUK_ASSERT(target_ustart + copy_size <= (duk_uint_t) target_length);
/* Ensure copy is covered by underlying buffers. */
- DUK_ASSERT(h_bufarg->buf != NULL); /* length check */
- DUK_ASSERT(h_this->buf != NULL); /* length check */
+ DUK_ASSERT(h_bufarg->buf != NULL); /* length check */
+ DUK_ASSERT(h_this->buf != NULL); /* length check */
if (DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufarg, target_ustart + copy_size) &&
DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, source_ustart + copy_size)) {
/* Must use memmove() because copy area may overlap (source and target
* buffer may be the same, or from different slices.
*/
- DUK_MEMMOVE((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart),
- (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + source_ustart),
- (size_t) copy_size);
+ duk_memmove_unsafe((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart),
+ (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + source_ustart),
+ (size_t) copy_size);
} else {
DUK_DDD(DUK_DDDPRINT("buffer copy not covered by underlying buffer(s), ignoring"));
}
- silent_ignore:
+silent_ignore:
/* Return value is like write(), number of bytes written.
* The return value matters because of code like:
* "off += buf.copy(...)".
- */
+ */
duk_push_uint(thr, copy_size);
return 1;
- fail_bounds:
+fail_bounds:
DUK_DCERROR_RANGE_INVALID_ARGS(thr);
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* TypedArray.prototype.set()
@@ -27437,7 +29402,7 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_hthread *thr) {
h_this = duk__require_bufobj_this(thr);
DUK_ASSERT(h_this != NULL);
- DUK_ASSERT_HBUFOBJ_VALID(h_this);
+ DUK_HBUFOBJ_ASSERT_VALID(h_this);
if (h_this->buf == NULL) {
DUK_DDD(DUK_DDDPRINT("source neutered, skip copy"));
@@ -27492,7 +29457,7 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_hthread *thr) {
duk_small_uint_t dst_elem_size;
h_bufarg = (duk_hbufobj *) h_obj;
- DUK_ASSERT_HBUFOBJ_VALID(h_bufarg);
+ DUK_HBUFOBJ_ASSERT_VALID(h_bufarg);
if (h_bufarg->buf == NULL) {
DUK_DDD(DUK_DDDPRINT("target neutered, skip copy"));
@@ -27500,16 +29465,15 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_hthread *thr) {
}
/* Nominal size check. */
- src_length = h_bufarg->length; /* bytes in source */
- dst_length_elems = (src_length >> h_bufarg->shift); /* elems in source and dest */
- dst_length = dst_length_elems << h_this->shift; /* bytes in dest */
+ src_length = h_bufarg->length; /* bytes in source */
+ dst_length_elems = (src_length >> h_bufarg->shift); /* elems in source and dest */
+ dst_length = dst_length_elems << h_this->shift; /* bytes in dest */
if ((dst_length >> h_this->shift) != dst_length_elems) {
/* Byte length would overflow. */
/* XXX: easier check with less code? */
goto fail_args;
}
- DUK_DDD(DUK_DDDPRINT("nominal size check: src_length=%ld, dst_length=%ld",
- (long) src_length, (long) dst_length));
+ DUK_DDD(DUK_DDDPRINT("nominal size check: src_length=%ld, dst_length=%ld", (long) src_length, (long) dst_length));
DUK_ASSERT(offset_bytes <= h_this->length);
if (dst_length > h_this->length - offset_bytes) {
/* Overflow not an issue because subtraction is used on the right
@@ -27530,8 +29494,7 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_hthread *thr) {
* cover the copy. No side effects are allowed after the check
* so that the validity status doesn't change.
*/
- if (!DUK_HBUFOBJ_VALID_SLICE(h_this) ||
- !DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
+ if (!DUK_HBUFOBJ_VALID_SLICE(h_this) || !DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
/* The condition could be more narrow and check for the
* copy area only, but there's no need for fine grained
* behavior when the underlying buffer is misconfigured.
@@ -27558,11 +29521,11 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_hthread *thr) {
DUK_ASSERT(src_length == dst_length);
DUK_DDD(DUK_DDDPRINT("fast path: able to use memmove() because views are compatible"));
- DUK_MEMMOVE((void *) p_dst_base, (const void *) p_src_base, (size_t) dst_length);
+ duk_memmove_unsafe((void *) p_dst_base, (const void *) p_src_base, (size_t) dst_length);
return 0;
}
DUK_DDD(DUK_DDDPRINT("fast path: views are not compatible with a byte copy, copy by item"));
-#endif /* !DUK_USE_PREFER_SIZE */
+#endif /* !DUK_USE_PREFER_SIZE */
/* We want to avoid making a copy to process set() but that's
* not always possible: the source and the target may overlap
@@ -27582,11 +29545,13 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_hthread *thr) {
DUK_DDD(DUK_DDDPRINT("overlap check: p_src_base=%p, src_length=%ld, "
"p_dst_base=%p, dst_length=%ld",
- (void *) p_src_base, (long) src_length,
- (void *) p_dst_base, (long) dst_length));
+ (void *) p_src_base,
+ (long) src_length,
+ (void *) p_dst_base,
+ (long) dst_length));
- if (p_src_base >= p_dst_base + dst_length || /* source starts after dest ends */
- p_src_base + src_length <= p_dst_base) { /* source ends before dest starts */
+ if (p_src_base >= p_dst_base + dst_length || /* source starts after dest ends */
+ p_src_base + src_length <= p_dst_base) { /* source ends before dest starts */
no_overlap = 1;
}
@@ -27601,16 +29566,18 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_hthread *thr) {
DUK_DDD(DUK_DDDPRINT("there is overlap, make a copy of the source"));
p_src_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_length);
DUK_ASSERT(p_src_copy != NULL);
- DUK_MEMCPY((void *) p_src_copy, (const void *) p_src_base, (size_t) src_length);
+ duk_memcpy_unsafe((void *) p_src_copy, (const void *) p_src_base, (size_t) src_length);
- p_src_base = p_src_copy; /* use p_src_base from now on */
+ p_src_base = p_src_copy; /* use p_src_base from now on */
}
/* Value stack intentionally mixed size here. */
DUK_DDD(DUK_DDDPRINT("after overlap check: p_src_base=%p, src_length=%ld, "
"p_dst_base=%p, dst_length=%ld, valstack top=%ld",
- (void *) p_src_base, (long) src_length,
- (void *) p_dst_base, (long) dst_length,
+ (void *) p_src_base,
+ (long) src_length,
+ (void *) p_dst_base,
+ (long) dst_length,
(long) duk_get_top(thr)));
/* Ready to make the copy. We must proceed element by element
@@ -27630,7 +29597,9 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_hthread *thr) {
while (p_src != p_src_end) {
DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
"p_src=%p, p_src_end=%p, p_dst=%p",
- (void *) p_src, (void *) p_src_end, (void *) p_dst));
+ (void *) p_src,
+ (void *) p_src_end,
+ (void *) p_dst));
/* A validated read() is always a number, so it's write coercion
* is always side effect free an won't invalidate pointers etc.
*/
@@ -27680,10 +29649,10 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_hthread *thr) {
return 0;
- fail_args:
+fail_args:
DUK_DCERROR_RANGE_INVALID_ARGS(thr);
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* Node.js Buffer.prototype.slice([start], [end])
@@ -27728,9 +29697,9 @@ DUK_LOCAL void duk__arraybuffer_plain_slice(duk_hthread *thr, duk_hbuffer *h_val
DUK_ASSERT(p_copy != NULL);
copy_length = slice_length;
- DUK_MEMCPY((void *) p_copy,
- (const void *) ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_val) + start_offset),
- copy_length);
+ duk_memcpy_unsafe((void *) p_copy,
+ (const void *) ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_val) + start_offset),
+ copy_length);
}
#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
@@ -27778,7 +29747,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_hthread *thr) {
/* fall through */
}
}
- tv = NULL; /* No longer valid nor needed. */
+ tv = NULL; /* No longer valid nor needed. */
h_this = duk__require_bufobj_this(thr);
@@ -27816,22 +29785,21 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_hthread *thr) {
* be an Uint8Array but inherit from Buffer.prototype.
*/
res_class_num = DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_this);
- DUK_ASSERT(res_class_num >= DUK_HOBJECT_CLASS_BUFOBJ_MIN); /* type check guarantees */
+ DUK_ASSERT(res_class_num >= DUK_HOBJECT_CLASS_BUFOBJ_MIN); /* type check guarantees */
DUK_ASSERT(res_class_num <= DUK_HOBJECT_CLASS_BUFOBJ_MAX);
res_proto_bidx = duk__buffer_proto_from_classnum[res_class_num - DUK_HOBJECT_CLASS_BUFOBJ_MIN];
if (magic & 0x04) {
res_proto_bidx = DUK_BIDX_NODEJS_BUFFER_PROTOTYPE;
}
- h_bufobj = duk_push_bufobj_raw(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_BUFOBJ |
- DUK_HOBJECT_CLASS_AS_FLAGS(res_class_num),
- res_proto_bidx);
+ h_bufobj =
+ duk_push_bufobj_raw(thr,
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_BUFOBJ | DUK_HOBJECT_CLASS_AS_FLAGS(res_class_num),
+ res_proto_bidx);
DUK_ASSERT(h_bufobj != NULL);
DUK_ASSERT(h_bufobj->length == 0);
- h_bufobj->shift = h_this->shift; /* inherit */
- h_bufobj->elem_type = h_this->elem_type; /* inherit */
+ h_bufobj->shift = h_this->shift; /* inherit */
+ h_bufobj->elem_type = h_this->elem_type; /* inherit */
h_bufobj->is_typedarray = magic & 0x01;
DUK_ASSERT(h_bufobj->is_typedarray == 0 || h_bufobj->is_typedarray == 1);
@@ -27845,16 +29813,18 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_hthread *thr) {
duk_uint8_t *p_copy;
duk_size_t copy_length;
- p_copy = (duk_uint8_t *) duk_push_fixed_buffer_zero(thr, (duk_size_t) slice_length); /* must be zeroed, not all bytes always copied */
+ p_copy = (duk_uint8_t *) duk_push_fixed_buffer_zero(
+ thr,
+ (duk_size_t) slice_length); /* must be zeroed, not all bytes always copied */
DUK_ASSERT(p_copy != NULL);
/* Copy slice, respecting underlying buffer limits; remainder
* is left as zero.
*/
copy_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, slice_length);
- DUK_MEMCPY((void *) p_copy,
- (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
- copy_length);
+ duk_memcpy_unsafe((void *) p_copy,
+ (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
+ copy_length);
h_val = duk_known_hbuffer(thr, -1);
@@ -27863,7 +29833,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_hthread *thr) {
h_bufobj->length = slice_length;
DUK_ASSERT(h_bufobj->offset == 0);
- duk_pop(thr); /* reachable so pop OK */
+ duk_pop(thr); /* reachable so pop OK */
} else {
h_bufobj->buf = h_val;
DUK_HBUFFER_INCREF(thr, h_val);
@@ -27876,15 +29846,15 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_hthread *thr) {
*/
DUK_ASSERT(h_bufobj->buf_prop == NULL);
- h_bufobj->buf_prop = h_this->buf_prop; /* may be NULL */
+ h_bufobj->buf_prop = h_this->buf_prop; /* may be NULL */
DUK_HOBJECT_INCREF_ALLOWNULL(thr, (duk_hobject *) h_bufobj->buf_prop);
}
/* unbalanced stack on purpose */
- DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+ DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
return 1;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* Node.js Buffer.isEncoding()
@@ -27897,11 +29867,11 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_hthread *thr) {
/* only accept lowercase 'utf8' now. */
encoding = duk_to_string(thr, 0);
- DUK_ASSERT(duk_is_string(thr, 0)); /* guaranteed by duk_to_string() */
+ DUK_ASSERT(duk_is_string(thr, 0)); /* guaranteed by duk_to_string() */
duk_push_boolean(thr, DUK_STRCMP(encoding, "utf8") == 0);
return 1;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* Node.js Buffer.isBuffer()
@@ -27913,7 +29883,7 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_hthread *thr) {
duk_hobject *h_proto;
duk_bool_t ret = 0;
- DUK_ASSERT(duk_get_top(thr) >= 1); /* nargs */
+ DUK_ASSERT(duk_get_top(thr) >= 1); /* nargs */
h = duk_get_hobject(thr, 0);
if (h != NULL) {
h_proto = thr->builtins[DUK_BIDX_NODEJS_BUFFER_PROTOTYPE];
@@ -27928,7 +29898,7 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_hthread *thr) {
duk_push_boolean(thr, ret);
return 1;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* Node.js Buffer.byteLength()
@@ -27959,7 +29929,7 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_hthread *thr) {
duk_push_size_t(thr, len);
return 1;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* Node.js Buffer.concat()
@@ -27990,13 +29960,13 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_hthread *thr) {
/* Neutered checks not necessary here: neutered buffers have
* zero 'length' so we'll effectively skip them.
*/
- DUK_ASSERT_TOP(thr, 2); /* [ array totalLength ] */
- duk_get_prop_index(thr, 0, (duk_uarridx_t) i); /* -> [ array totalLength buf ] */
+ DUK_ASSERT_TOP(thr, 2); /* [ array totalLength ] */
+ duk_get_prop_index(thr, 0, (duk_uarridx_t) i); /* -> [ array totalLength buf ] */
h_bufobj = duk__require_bufobj_value(thr, 2);
DUK_ASSERT(h_bufobj != NULL);
total_length += h_bufobj->length;
if (DUK_UNLIKELY(total_length < h_bufobj->length)) {
- DUK_DCERROR_RANGE_INVALID_ARGS(thr); /* Wrapped. */
+ DUK_DCERROR_RANGE_INVALID_ARGS(thr); /* Wrapped. */
}
duk_pop(thr);
}
@@ -28022,18 +29992,18 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_hthread *thr) {
}
h_bufres = duk_push_bufobj_raw(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_BUFOBJ |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_UINT8ARRAY),
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_BUFOBJ |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_UINT8ARRAY),
DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
DUK_ASSERT(h_bufres != NULL);
- p = (duk_uint8_t *) duk_push_fixed_buffer_zero(thr, total_length); /* must be zeroed, all bytes not necessarily written over */
+ p = (duk_uint8_t *) duk_push_fixed_buffer_zero(thr,
+ total_length); /* must be zeroed, all bytes not necessarily written over */
DUK_ASSERT(p != NULL);
space_left = (duk_size_t) total_length;
for (i = 0; i < n; i++) {
- DUK_ASSERT_TOP(thr, 4); /* [ array totalLength bufres buf ] */
+ DUK_ASSERT_TOP(thr, 4); /* [ array totalLength bufres buf ] */
duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
h_bufobj = duk__require_bufobj_value(thr, 4);
@@ -28044,11 +30014,8 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_hthread *thr) {
copy_size = space_left;
}
- if (h_bufobj->buf != NULL &&
- DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
- DUK_MEMCPY((void *) p,
- (const void *) DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj),
- copy_size);
+ if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
+ duk_memcpy_unsafe((void *) p, (const void *) DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj), copy_size);
} else {
/* Just skip, leaving zeroes in the result. */
;
@@ -28063,13 +30030,13 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_hthread *thr) {
duk__set_bufobj_buffer(thr, h_bufres, h_val);
h_bufres->is_typedarray = 1;
- DUK_ASSERT_HBUFOBJ_VALID(h_bufres);
+ DUK_HBUFOBJ_ASSERT_VALID(h_bufres);
- duk_pop(thr); /* pop plain buffer, now reachable through h_bufres */
+ duk_pop(thr); /* pop plain buffer, now reachable through h_bufres */
- return 1; /* return h_bufres */
+ return 1; /* return h_bufres */
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* Shared readfield and writefield methods
@@ -28085,24 +30052,24 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_hthread *thr) {
* 4: signed: 1=yes, 0=no
* 5: typedarray: 1=yes, 0=no
*/
-#define DUK__FLD_8BIT 0
-#define DUK__FLD_16BIT 1
-#define DUK__FLD_32BIT 2
-#define DUK__FLD_FLOAT 3
-#define DUK__FLD_DOUBLE 4
-#define DUK__FLD_VARINT 5
-#define DUK__FLD_BIGENDIAN (1 << 3)
-#define DUK__FLD_SIGNED (1 << 4)
-#define DUK__FLD_TYPEDARRAY (1 << 5)
+#define DUK__FLD_8BIT 0
+#define DUK__FLD_16BIT 1
+#define DUK__FLD_32BIT 2
+#define DUK__FLD_FLOAT 3
+#define DUK__FLD_DOUBLE 4
+#define DUK__FLD_VARINT 5
+#define DUK__FLD_BIGENDIAN (1 << 3)
+#define DUK__FLD_SIGNED (1 << 4)
+#define DUK__FLD_TYPEDARRAY (1 << 5)
/* XXX: split into separate functions for each field type? */
DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
- duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(thr);
- duk_small_int_t magic_ftype;
- duk_small_int_t magic_bigendian;
- duk_small_int_t magic_signed;
- duk_small_int_t magic_typedarray;
- duk_small_int_t endswap;
+ duk_small_uint_t magic = (duk_small_uint_t) duk_get_current_magic(thr);
+ duk_small_uint_t magic_ftype;
+ duk_small_uint_t magic_bigendian;
+ duk_small_uint_t magic_signed;
+ duk_small_uint_t magic_typedarray;
+ duk_small_uint_t endswap;
duk_hbufobj *h_this;
duk_bool_t no_assert;
duk_int_t offset_signed;
@@ -28112,12 +30079,12 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
duk_uint8_t *buf;
duk_double_union du;
- magic_ftype = magic & 0x0007;
- magic_bigendian = magic & 0x0008;
- magic_signed = magic & 0x0010;
- magic_typedarray = magic & 0x0020;
+ magic_ftype = magic & 0x0007U;
+ magic_bigendian = magic & 0x0008U;
+ magic_signed = magic & 0x0010U;
+ magic_typedarray = magic & 0x0020U;
- h_this = duk__require_bufobj_this(thr); /* XXX: very inefficient for plain buffers */
+ h_this = duk__require_bufobj_this(thr); /* XXX: very inefficient for plain buffers */
DUK_ASSERT(h_this != NULL);
buffer_length = h_this->length;
@@ -28129,9 +30096,9 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
if (magic_typedarray) {
no_assert = 0;
#if defined(DUK_USE_INTEGER_LE)
- endswap = !duk_to_boolean(thr, 1); /* 1=little endian */
+ endswap = !duk_to_boolean(thr, 1); /* 1=little endian */
#else
- endswap = duk_to_boolean(thr, 1); /* 1=little endian */
+ endswap = duk_to_boolean(thr, 1); /* 1=little endian */
#endif
} else {
no_assert = duk_to_boolean(thr, (magic_ftype == DUK__FLD_VARINT) ? 2 : 1);
@@ -28154,18 +30121,22 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
DUK_DDD(DUK_DDDPRINT("readfield, buffer_length=%ld, offset=%ld, no_assert=%d, "
"magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
- "endswap=%d",
- (long) buffer_length, (long) offset, (int) no_assert,
- (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
- (int) (magic_signed >> 4), (int) endswap));
+ "endswap=%u",
+ (long) buffer_length,
+ (long) offset,
+ (int) no_assert,
+ (unsigned int) magic,
+ (int) magic_ftype,
+ (int) (magic_bigendian >> 3),
+ (int) (magic_signed >> 4),
+ (int) endswap));
/* Update 'buffer_length' to be the effective, safe limit which
* takes into account the underlying buffer. This value will be
* potentially invalidated by any side effect.
*/
check_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);
- DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
- (long) buffer_length, (long) check_length));
+ DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld", (long) buffer_length, (long) check_length));
if (h_this->buf) {
buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
@@ -28198,7 +30169,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
if (offset + 2U > check_length) {
goto fail_bounds;
}
- DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 2);
+ duk_memcpy((void *) du.uc, (const void *) (buf + offset), 2);
tmp = du.us[0];
if (endswap) {
tmp = DUK_BSWAP16(tmp);
@@ -28215,7 +30186,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
if (offset + 4U > check_length) {
goto fail_bounds;
}
- DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4);
+ duk_memcpy((void *) du.uc, (const void *) (buf + offset), 4);
tmp = du.ui[0];
if (endswap) {
tmp = DUK_BSWAP32(tmp);
@@ -28232,7 +30203,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
if (offset + 4U > check_length) {
goto fail_bounds;
}
- DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4);
+ duk_memcpy((void *) du.uc, (const void *) (buf + offset), 4);
if (endswap) {
tmp = du.ui[0];
tmp = DUK_BSWAP32(tmp);
@@ -28245,7 +30216,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
if (offset + 8U > check_length) {
goto fail_bounds;
}
- DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 8);
+ duk_memcpy((void *) du.uc, (const void *) (buf + offset), 8);
if (endswap) {
DUK_DBLUNION_BSWAP64(&du);
}
@@ -28267,7 +30238,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
#endif
const duk_uint8_t *p;
- field_bytelen = duk_get_int(thr, 1); /* avoid side effects! */
+ field_bytelen = duk_get_int(thr, 1); /* avoid side effects! */
if (field_bytelen < 1 || field_bytelen > 6) {
goto fail_field_length;
}
@@ -28285,12 +30256,12 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
/* Gather in big endian */
i = 0;
i_step = 1;
- i_end = field_bytelen; /* one i_step over */
+ i_end = field_bytelen; /* one i_step over */
} else {
/* Gather in little endian */
i = field_bytelen - 1;
i_step = -1;
- i_end = -1; /* one i_step over */
+ i_end = -1; /* one i_step over */
}
#if defined(DUK_USE_64BIT_OPS)
@@ -28302,9 +30273,12 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
} while (i != i_end);
if (magic_signed) {
- /* Shift to sign extend. */
+ /* Shift to sign extend. Left shift must be unsigned
+ * to avoid undefined behavior; right shift must be
+ * signed to sign extend properly.
+ */
shift_tmp = (duk_small_uint_t) (64U - (duk_small_uint_t) field_bytelen * 8U);
- tmp = (tmp << shift_tmp) >> shift_tmp;
+ tmp = (duk_int64_t) ((duk_uint64_t) tmp << shift_tmp) >> shift_tmp;
}
duk_push_i64(thr, tmp);
@@ -28329,16 +30303,16 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
#endif
break;
}
- default: { /* should never happen but default here */
+ default: { /* should never happen but default here */
goto fail_bounds;
}
}
return 1;
- fail_neutered:
- fail_field_length:
- fail_bounds:
+fail_neutered:
+fail_field_length:
+fail_bounds:
if (no_assert) {
/* Node.js return value for noAssert out-of-bounds reads is
* usually (but not always) NaN. Return NaN consistently.
@@ -28348,17 +30322,17 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
}
DUK_DCERROR_RANGE_INVALID_ARGS(thr);
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
/* XXX: split into separate functions for each field type? */
DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
- duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(thr);
- duk_small_int_t magic_ftype;
- duk_small_int_t magic_bigendian;
- duk_small_int_t magic_signed;
- duk_small_int_t magic_typedarray;
- duk_small_int_t endswap;
+ duk_small_uint_t magic = (duk_small_uint_t) duk_get_current_magic(thr);
+ duk_small_uint_t magic_ftype;
+ duk_small_uint_t magic_bigendian;
+ duk_small_uint_t magic_signed;
+ duk_small_uint_t magic_typedarray;
+ duk_small_uint_t endswap;
duk_hbufobj *h_this;
duk_bool_t no_assert;
duk_int_t offset_signed;
@@ -28369,13 +30343,13 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
duk_double_union du;
duk_int_t nbytes = 0;
- magic_ftype = magic & 0x0007;
- magic_bigendian = magic & 0x0008;
- magic_signed = magic & 0x0010;
- magic_typedarray = magic & 0x0020;
+ magic_ftype = magic & 0x0007U;
+ magic_bigendian = magic & 0x0008U;
+ magic_signed = magic & 0x0010U;
+ magic_typedarray = magic & 0x0020U;
DUK_UNREF(magic_signed);
- h_this = duk__require_bufobj_this(thr); /* XXX: very inefficient for plain buffers */
+ h_this = duk__require_bufobj_this(thr); /* XXX: very inefficient for plain buffers */
DUK_ASSERT(h_this != NULL);
buffer_length = h_this->length;
@@ -28387,11 +30361,11 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
if (magic_typedarray) {
no_assert = 0;
#if defined(DUK_USE_INTEGER_LE)
- endswap = !duk_to_boolean(thr, 2); /* 1=little endian */
+ endswap = !duk_to_boolean(thr, 2); /* 1=little endian */
#else
- endswap = duk_to_boolean(thr, 2); /* 1=little endian */
+ endswap = duk_to_boolean(thr, 2); /* 1=little endian */
#endif
- duk_swap(thr, 0, 1); /* offset/value order different from Node.js */
+ duk_swap(thr, 0, 1); /* offset/value order different from Node.js */
} else {
no_assert = duk_to_boolean(thr, (magic_ftype == DUK__FLD_VARINT) ? 3 : 2);
#if defined(DUK_USE_INTEGER_LE)
@@ -28412,7 +30386,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
* (offset + nbytes) even when write fails due to invalid offset.
*/
if (magic_ftype != DUK__FLD_VARINT) {
- DUK_ASSERT(magic_ftype >= 0 && magic_ftype < (duk_small_int_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t)));
+ DUK_ASSERT(magic_ftype < (duk_small_uint_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t)));
nbytes = duk__buffer_nbytes_from_fldtype[magic_ftype];
} else {
nbytes = duk_get_int(thr, 2);
@@ -28429,10 +30403,16 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
DUK_DDD(DUK_DDDPRINT("writefield, value=%!T, buffer_length=%ld, offset=%ld, no_assert=%d, "
"magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
- "endswap=%d",
- duk_get_tval(thr, 0), (long) buffer_length, (long) offset, (int) no_assert,
- (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
- (int) (magic_signed >> 4), (int) endswap));
+ "endswap=%u",
+ duk_get_tval(thr, 0),
+ (long) buffer_length,
+ (long) offset,
+ (int) no_assert,
+ (unsigned int) magic,
+ (int) magic_ftype,
+ (int) (magic_bigendian >> 3),
+ (int) (magic_signed >> 4),
+ (int) endswap));
/* Coerce value to a number before computing check_length, so that
* the field type specific coercion below can't have side effects
@@ -28445,8 +30425,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
* potentially invalidated by any side effect.
*/
check_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);
- DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
- (long) buffer_length, (long) check_length));
+ DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld", (long) buffer_length, (long) check_length));
if (h_this->buf) {
buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
@@ -28480,7 +30459,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
}
du.us[0] = tmp;
/* sign doesn't matter when writing */
- DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 2);
+ duk_memcpy((void *) (buf + offset), (const void *) du.uc, 2);
break;
}
case DUK__FLD_32BIT: {
@@ -28494,7 +30473,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
}
du.ui[0] = tmp;
/* sign doesn't matter when writing */
- DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4);
+ duk_memcpy((void *) (buf + offset), (const void *) du.uc, 4);
break;
}
case DUK__FLD_FLOAT: {
@@ -28509,7 +30488,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
du.ui[0] = tmp;
}
/* sign doesn't matter when writing */
- DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4);
+ duk_memcpy((void *) (buf + offset), (const void *) du.uc, 4);
break;
}
case DUK__FLD_DOUBLE: {
@@ -28521,7 +30500,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
DUK_DBLUNION_BSWAP64(&du);
}
/* sign doesn't matter when writing */
- DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 8);
+ duk_memcpy((void *) (buf + offset), (const void *) du.uc, 8);
break;
}
case DUK__FLD_VARINT: {
@@ -28549,12 +30528,12 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
if (magic_bigendian) {
/* Write in big endian */
- i = field_bytelen; /* one i_step added at top of loop */
+ i = field_bytelen; /* one i_step added at top of loop */
i_step = -1;
i_end = 0;
} else {
/* Write in little endian */
- i = -1; /* one i_step added at top of loop */
+ i = -1; /* one i_step added at top of loop */
i_step = 1;
i_end = field_bytelen - 1;
}
@@ -28572,7 +30551,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
i += i_step;
DUK_ASSERT(i >= 0 && i < field_bytelen);
p[i] = (duk_uint8_t) (tmp & 0xff);
- tmp = tmp >> 8; /* unnecessary shift for last byte */
+ tmp = tmp >> 8; /* unnecessary shift for last byte */
} while (i != i_end);
#else
tmp = duk_to_number(thr, 0);
@@ -28582,12 +30561,12 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
tmp = DUK_FLOOR(tmp);
DUK_ASSERT(i >= 0 && i < field_bytelen);
p[i] = (duk_uint8_t) (DUK_FMOD(tmp, 256.0));
- tmp = tmp / 256.0; /* unnecessary div for last byte */
+ tmp = tmp / 256.0; /* unnecessary div for last byte */
} while (i != i_end);
#endif
break;
}
- default: { /* should never happen but default here */
+ default: { /* should never happen but default here */
goto fail_bounds;
}
}
@@ -28604,9 +30583,9 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
duk_push_uint(thr, offset + (duk_uint_t) nbytes);
return 1;
- fail_neutered:
- fail_field_length:
- fail_bounds:
+fail_neutered:
+fail_field_length:
+fail_bounds:
if (no_assert) {
/* Node.js return value for failed writes is offset + #bytes
* that would have been written.
@@ -28622,7 +30601,7 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
}
DUK_DCERROR_RANGE_INVALID_ARGS(thr);
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* Accessors for .buffer, .byteLength, .byteOffset
@@ -28633,15 +30612,14 @@ DUK_LOCAL duk_hbufobj *duk__autospawn_arraybuffer(duk_hthread *thr, duk_hbuffer
duk_hbufobj *h_res;
h_res = duk_push_bufobj_raw(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_BUFOBJ |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_BUFOBJ |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
DUK_ASSERT(h_res != NULL);
DUK_UNREF(h_res);
duk__set_bufobj_buffer(thr, h_res, h_buf);
- DUK_ASSERT_HBUFOBJ_VALID(h_res);
+ DUK_HBUFOBJ_ASSERT_VALID(h_res);
DUK_ASSERT(h_res->buf_prop == NULL);
return h_res;
}
@@ -28675,13 +30653,13 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_buffer_getter(duk_hthread *thr) {
* matches view[0].
*/
h_arrbuf->offset = 0;
- DUK_ASSERT(h_bufobj->offset + h_bufobj->length >= h_bufobj->offset); /* Wrap check on creation. */
+ DUK_ASSERT(h_bufobj->offset + h_bufobj->length >= h_bufobj->offset); /* Wrap check on creation. */
h_arrbuf->length = h_bufobj->offset + h_bufobj->length;
DUK_ASSERT(h_arrbuf->buf_prop == NULL);
DUK_ASSERT(h_bufobj->buf_prop == NULL);
h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
- DUK_HBUFOBJ_INCREF(thr, h_arrbuf); /* Now reachable and accounted for. */
+ DUK_HBUFOBJ_INCREF(thr, h_arrbuf); /* Now reachable and accounted for. */
}
/* Left on stack; pushed for the second time below (OK). */
@@ -28719,7 +30697,7 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_hthread *thr) {
duk_hbuffer *h_buf;
h_buf = (duk_hbuffer *) h_bufobj;
- DUK_ASSERT(DUK_HBUFFER_GET_SIZE(h_buf) <= DUK_UINT_MAX); /* Buffer limits. */
+ DUK_ASSERT(DUK_HBUFFER_GET_SIZE(h_buf) <= DUK_UINT_MAX); /* Buffer limits. */
duk_push_uint(thr, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
} else {
/* If neutered must return 0; length is zeroed during
@@ -28729,7 +30707,7 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_hthread *thr) {
}
return 1;
}
-#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
/* No .buffer getter without ArrayBuffer support. */
#if 0
DUK_INTERNAL duk_ret_t duk_bi_typedarray_buffer_getter(duk_hthread *thr) {
@@ -28751,7 +30729,7 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_hthread *thr) {
duk_push_uint(thr, DUK_HBUFFER_GET_SIZE(h_buf));
return 1;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/* automatic undefs */
#undef DUK__BUFOBJ_FLAG_PROMOTE
@@ -28766,6 +30744,1929 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_hthread *thr) {
#undef DUK__FLD_TYPEDARRAY
#undef DUK__FLD_VARINT
/*
+ * CBOR bindings.
+ *
+ * http://cbor.io/
+ * https://tools.ietf.org/html/rfc7049
+ */
+
+/* #include duk_internal.h -> already included */
+
+#if defined(DUK_USE_CBOR_SUPPORT)
+
+/* #define DUK_CBOR_STRESS */
+
+/* Default behavior for encoding strings: use CBOR text string if string
+ * is UTF-8 compatible, otherwise use CBOR byte string. These defines
+ * can be used to force either type for all strings. Using text strings
+ * for non-UTF-8 data is technically invalid CBOR.
+ */
+/* #define DUK_CBOR_TEXT_STRINGS */
+/* #define DUK_CBOR_BYTE_STRINGS */
+
+/* Misc. defines. */
+/* #define DUK_CBOR_PREFER_SIZE */
+/* #define DUK_CBOR_DOUBLE_AS_IS */
+/* #define DUK_CBOR_DECODE_FASTPATH */
+
+typedef struct {
+ duk_hthread *thr;
+ duk_uint8_t *ptr;
+ duk_uint8_t *buf;
+ duk_uint8_t *buf_end;
+ duk_size_t len;
+ duk_idx_t idx_buf;
+ duk_uint_t recursion_depth;
+ duk_uint_t recursion_limit;
+} duk_cbor_encode_context;
+
+typedef struct {
+ duk_hthread *thr;
+ const duk_uint8_t *buf;
+ duk_size_t off;
+ duk_size_t len;
+ duk_uint_t recursion_depth;
+ duk_uint_t recursion_limit;
+} duk_cbor_decode_context;
+
+DUK_LOCAL void duk__cbor_encode_value(duk_cbor_encode_context *enc_ctx);
+DUK_LOCAL void duk__cbor_decode_value(duk_cbor_decode_context *dec_ctx);
+
+/*
+ * Misc
+ */
+
+DUK_LOCAL duk_uint32_t duk__cbor_double_to_uint32(double d) {
+ /* Out of range casts are undefined behavior, so caller must avoid. */
+ DUK_ASSERT(d >= 0.0 && d <= 4294967295.0);
+ return (duk_uint32_t) d;
+}
+
+/*
+ * Encoding
+ */
+
+DUK_LOCAL void duk__cbor_encode_error(duk_cbor_encode_context *enc_ctx) {
+ (void) duk_type_error(enc_ctx->thr, "cbor encode error");
+}
+
+DUK_LOCAL void duk__cbor_encode_req_stack(duk_cbor_encode_context *enc_ctx) {
+ duk_require_stack(enc_ctx->thr, 4);
+}
+
+DUK_LOCAL void duk__cbor_encode_objarr_entry(duk_cbor_encode_context *enc_ctx) {
+ duk_hthread *thr = enc_ctx->thr;
+
+ /* Native stack check in object/array recursion. */
+ duk_native_stack_check(thr);
+
+ /* When working with deeply recursive structures, this is important
+ * to ensure there's no effective depth limit.
+ */
+ duk__cbor_encode_req_stack(enc_ctx);
+
+ DUK_ASSERT(enc_ctx->recursion_depth <= enc_ctx->recursion_limit);
+ if (enc_ctx->recursion_depth >= enc_ctx->recursion_limit) {
+ DUK_ERROR_RANGE(thr, DUK_STR_ENC_RECLIMIT);
+ DUK_WO_NORETURN(return;);
+ }
+ enc_ctx->recursion_depth++;
+}
+
+DUK_LOCAL void duk__cbor_encode_objarr_exit(duk_cbor_encode_context *enc_ctx) {
+ DUK_ASSERT(enc_ctx->recursion_depth > 0);
+ enc_ctx->recursion_depth--;
+}
+
+/* Check that a size_t is in uint32 range to avoid out-of-range casts. */
+DUK_LOCAL void duk__cbor_encode_sizet_uint32_check(duk_cbor_encode_context *enc_ctx, duk_size_t len) {
+ if (DUK_UNLIKELY(sizeof(duk_size_t) > sizeof(duk_uint32_t) && len > (duk_size_t) DUK_UINT32_MAX)) {
+ duk__cbor_encode_error(enc_ctx);
+ }
+}
+
+DUK_LOCAL DUK_NOINLINE void duk__cbor_encode_ensure_slowpath(duk_cbor_encode_context *enc_ctx, duk_size_t len) {
+ duk_size_t oldlen;
+ duk_size_t minlen;
+ duk_size_t newlen;
+ duk_uint8_t *p_new;
+ duk_size_t old_data_len;
+
+ DUK_ASSERT(enc_ctx->ptr >= enc_ctx->buf);
+ DUK_ASSERT(enc_ctx->buf_end >= enc_ctx->ptr);
+ DUK_ASSERT(enc_ctx->buf_end >= enc_ctx->buf);
+
+ /* Overflow check.
+ *
+ * Limit example: 0xffffffffUL / 2U = 0x7fffffffUL, we reject >= 0x80000000UL.
+ */
+ oldlen = enc_ctx->len;
+ minlen = oldlen + len;
+ if (DUK_UNLIKELY(oldlen > DUK_SIZE_MAX / 2U || minlen < oldlen)) {
+ duk__cbor_encode_error(enc_ctx);
+ }
+
+#if defined(DUK_CBOR_STRESS)
+ newlen = oldlen + 1U;
+#else
+ newlen = oldlen * 2U;
+#endif
+ DUK_ASSERT(newlen >= oldlen);
+
+ if (minlen > newlen) {
+ newlen = minlen;
+ }
+ DUK_ASSERT(newlen >= oldlen);
+ DUK_ASSERT(newlen >= minlen);
+ DUK_ASSERT(newlen > 0U);
+
+ DUK_DD(DUK_DDPRINT("cbor encode buffer resized to %ld", (long) newlen));
+
+ p_new = (duk_uint8_t *) duk_resize_buffer(enc_ctx->thr, enc_ctx->idx_buf, newlen);
+ DUK_ASSERT(p_new != NULL);
+ old_data_len = (duk_size_t) (enc_ctx->ptr - enc_ctx->buf);
+ enc_ctx->buf = p_new;
+ enc_ctx->buf_end = p_new + newlen;
+ enc_ctx->ptr = p_new + old_data_len;
+ enc_ctx->len = newlen;
+}
+
+DUK_LOCAL DUK_INLINE void duk__cbor_encode_ensure(duk_cbor_encode_context *enc_ctx, duk_size_t len) {
+ if (DUK_LIKELY((duk_size_t) (enc_ctx->buf_end - enc_ctx->ptr) >= len)) {
+ return;
+ }
+ duk__cbor_encode_ensure_slowpath(enc_ctx, len);
+}
+
+DUK_LOCAL duk_size_t duk__cbor_get_reserve(duk_cbor_encode_context *enc_ctx) {
+ DUK_ASSERT(enc_ctx->ptr >= enc_ctx->buf);
+ DUK_ASSERT(enc_ctx->ptr <= enc_ctx->buf_end);
+ return (duk_size_t) (enc_ctx->buf_end - enc_ctx->ptr);
+}
+
+DUK_LOCAL void duk__cbor_encode_uint32(duk_cbor_encode_context *enc_ctx, duk_uint32_t u, duk_uint8_t base) {
+ duk_uint8_t *p;
+
+ /* Caller must ensure space. */
+ DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 4);
+
+ p = enc_ctx->ptr;
+ if (DUK_LIKELY(u <= 23U)) {
+ *p++ = (duk_uint8_t) (base + (duk_uint8_t) u);
+ } else if (u <= 0xffUL) {
+ *p++ = base + 0x18U;
+ *p++ = (duk_uint8_t) u;
+ } else if (u <= 0xffffUL) {
+ *p++ = base + 0x19U;
+ DUK_RAW_WRITEINC_U16_BE(p, (duk_uint16_t) u);
+ } else {
+ *p++ = base + 0x1aU;
+ DUK_RAW_WRITEINC_U32_BE(p, u);
+ }
+ enc_ctx->ptr = p;
+}
+
+#if defined(DUK_CBOR_DOUBLE_AS_IS)
+DUK_LOCAL void duk__cbor_encode_double(duk_cbor_encode_context *enc_ctx, double d) {
+ duk_uint8_t *p;
+
+ /* Caller must ensure space. */
+ DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
+
+ p = enc_ctx->ptr;
+ *p++ = 0xfbU;
+ DUK_RAW_WRITEINC_DOUBLE_BE(p, d);
+ p += 8;
+ enc_ctx->ptr = p;
+}
+#else /* DUK_CBOR_DOUBLE_AS_IS */
+DUK_LOCAL void duk__cbor_encode_double_fp(duk_cbor_encode_context *enc_ctx, double d) {
+ duk_double_union u;
+ duk_uint16_t u16;
+ duk_int16_t expt;
+ duk_uint8_t *p;
+
+ DUK_ASSERT(DUK_FPCLASSIFY(d) != DUK_FP_ZERO);
+
+ /* Caller must ensure space. */
+ DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
+
+ /* Organize into little endian (no-op if platform is little endian). */
+ u.d = d;
+ duk_dblunion_host_to_little(&u);
+
+ /* Check if 'd' can represented as a normal half-float.
+ * Denormal half-floats could also be used, but that check
+ * isn't done now (denormal half-floats are decoded of course).
+ * So just check exponent range and that at most 10 significant
+ * bits (excluding implicit leading 1) are used in 'd'.
+ */
+ u16 = (((duk_uint16_t) u.uc[7]) << 8) | ((duk_uint16_t) u.uc[6]);
+ expt = (duk_int16_t) ((u16 & 0x7ff0U) >> 4) - 1023;
+
+ if (expt >= -14 && expt <= 15) {
+ /* Half-float normal exponents (excl. denormals).
+ *
+ * 7 6 5 4 3 2 1 0 (LE index)
+ * double: seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
+ * half: seeeee mmmm mmmmmm00 00000000 00000000 00000000 00000000 00000000
+ */
+ duk_bool_t use_half_float;
+
+ use_half_float =
+ (u.uc[0] == 0 && u.uc[1] == 0 && u.uc[2] == 0 && u.uc[3] == 0 && u.uc[4] == 0 && (u.uc[5] & 0x03U) == 0);
+
+ if (use_half_float) {
+ duk_uint32_t t;
+
+ expt += 15;
+ t = (duk_uint32_t) (u.uc[7] & 0x80U) << 8;
+ t += (duk_uint32_t) expt << 10;
+ t += ((duk_uint32_t) u.uc[6] & 0x0fU) << 6;
+ t += ((duk_uint32_t) u.uc[5]) >> 2;
+
+ /* seeeeemm mmmmmmmm */
+ p = enc_ctx->ptr;
+ *p++ = 0xf9U;
+ DUK_RAW_WRITEINC_U16_BE(p, (duk_uint16_t) t);
+ enc_ctx->ptr = p;
+ return;
+ }
+ }
+
+ /* Same check for plain float. Also no denormal support here. */
+ if (expt >= -126 && expt <= 127) {
+ /* Float normal exponents (excl. denormals).
+ *
+ * double: seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
+ * float: seeee eeeemmmm mmmmmmmm mmmmmmmm mmm00000 00000000 00000000 00000000
+ */
+ duk_bool_t use_float;
+ duk_float_t d_float;
+
+ /* We could do this explicit mantissa check, but doing
+ * a double-float-double cast is fine because we've
+ * already verified that the exponent is in range so
+ * that the narrower cast is not undefined behavior.
+ */
+#if 0
+ use_float =
+ (u.uc[0] == 0 && u.uc[1] == 0 && u.uc[2] == 0 && (u.uc[3] & 0xe0U) == 0);
+#endif
+ d_float = (duk_float_t) d;
+ use_float = duk_double_equals((duk_double_t) d_float, d);
+ if (use_float) {
+ p = enc_ctx->ptr;
+ *p++ = 0xfaU;
+ DUK_RAW_WRITEINC_FLOAT_BE(p, d_float);
+ enc_ctx->ptr = p;
+ return;
+ }
+ }
+
+ /* Special handling for NaN and Inf which we want to encode as
+ * half-floats. They share the same (maximum) exponent.
+ */
+ if (expt == 1024) {
+ DUK_ASSERT(DUK_ISNAN(d) || DUK_ISINF(d));
+ p = enc_ctx->ptr;
+ *p++ = 0xf9U;
+ if (DUK_ISNAN(d)) {
+ /* Shortest NaN encoding is using a half-float. Lose the
+ * exact NaN bits in the process. IEEE double would be
+ * 7ff8 0000 0000 0000, i.e. a quiet NaN in most architectures
+ * (https://en.wikipedia.org/wiki/NaN#Encoding). The
+ * equivalent half float is 7e00.
+ */
+ *p++ = 0x7eU;
+ } else {
+ /* Shortest +/- Infinity encoding is using a half-float. */
+ if (DUK_SIGNBIT(d)) {
+ *p++ = 0xfcU;
+ } else {
+ *p++ = 0x7cU;
+ }
+ }
+ *p++ = 0x00U;
+ enc_ctx->ptr = p;
+ return;
+ }
+
+ /* Cannot use half-float or float, encode as full IEEE double. */
+ p = enc_ctx->ptr;
+ *p++ = 0xfbU;
+ DUK_RAW_WRITEINC_DOUBLE_BE(p, d);
+ enc_ctx->ptr = p;
+}
+
+DUK_LOCAL void duk__cbor_encode_double(duk_cbor_encode_context *enc_ctx, double d) {
+ duk_uint8_t *p;
+ double d_floor;
+
+ /* Integers and floating point values of all types are conceptually
+ * equivalent in CBOR. Try to always choose the shortest encoding
+ * which is not always immediately obvious. For example, NaN and Inf
+ * can be most compactly represented as a half-float (assuming NaN
+ * bits are not preserved), and 0x1'0000'0000 as a single precision
+ * float. Shortest forms in preference order (prefer integer over
+ * float when equal length):
+ *
+ * uint 1 byte [0,23] (not -0)
+ * sint 1 byte [-24,-1]
+ * uint+1 2 bytes [24,255]
+ * sint+1 2 bytes [-256,-25]
+ * uint+2 3 bytes [256,65535]
+ * sint+2 3 bytes [-65536,-257]
+ * half-float 3 bytes -0, NaN, +/- Infinity, range [-65504,65504]
+ * uint+4 5 bytes [65536,4294967295]
+ * sint+4 5 bytes [-4294967296,-258]
+ * float 5 bytes range [-(1 - 2^(-24)) * 2^128, (1 - 2^(-24)) * 2^128]
+ * uint+8 9 bytes [4294967296,18446744073709551615]
+ * sint+8 9 bytes [-18446744073709551616,-4294967297]
+ * double 9 bytes
+ *
+ * For whole numbers (compatible with integers):
+ * - 1-byte or 2-byte uint/sint representation is preferred for
+ * [-256,255].
+ * - 3-byte uint/sint is preferred for [-65536,65535]. Half floats
+ * are never preferred because they have the same length.
+ * - 5-byte uint/sint is preferred for [-4294967296,4294967295].
+ * Single precision floats are never preferred, and half-floats
+ * don't reach above the 3-byte uint/sint range so they're never
+ * preferred.
+ * - So, for all integers up to signed/unsigned 32-bit range the
+ * preferred encoding is always an integer uint/sint.
+ * - For integers above 32 bits the situation is more complicated.
+ * Half-floats are never useful for them because of their limited
+ * range, but IEEE single precision floats (5 bytes encoded) can
+ * represent some integers between the 32-bit and 64-bit ranges
+ * which require 9 bytes as a uint/sint.
+ *
+ * For floating point values not compatible with integers, the
+ * preferred encoding is quite clear:
+ * - For +Inf/-Inf use half-float.
+ * - For NaN use a half-float, assuming NaN bits ("payload") is
+ * not worth preserving. Duktape doesn't in general guarantee
+ * preservation of the NaN payload so using a half-float seems
+ * consistent with that.
+ * - For remaining values, prefer the shortest form which doesn't
+ * lose any precision. For normal half-floats and single precision
+ * floats this is simple: just check exponent and mantissa bits
+ * using a fixed mask. For denormal half-floats and single
+ * precision floats the check is a bit more complicated: a normal
+ * IEEE double can sometimes be represented as a denormal
+ * half-float or single precision float.
+ *
+ * https://en.wikipedia.org/wiki/Half-precision_floating-point_format#IEEE_754_half-precision_binary_floating-point_format:_binary16
+ */
+
+ /* Caller must ensure space. */
+ DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
+
+ /* Most important path is integers. The floor() test will be true
+ * for Inf too (but not NaN).
+ */
+ d_floor = DUK_FLOOR(d); /* identity if d is +/- 0.0, NaN, or +/- Infinity */
+ if (DUK_LIKELY(duk_double_equals(d_floor, d) != 0)) {
+ DUK_ASSERT(!DUK_ISNAN(d)); /* NaN == NaN compares false. */
+ if (DUK_SIGNBIT(d)) {
+ if (d >= -4294967296.0) {
+ d = -1.0 - d;
+ if (d >= 0.0) {
+ DUK_ASSERT(d >= 0.0);
+ duk__cbor_encode_uint32(enc_ctx, duk__cbor_double_to_uint32(d), 0x20U);
+ return;
+ }
+
+ /* Input was negative zero, d == -1.0 < 0.0.
+ * Shortest -0 is using half-float.
+ */
+ p = enc_ctx->ptr;
+ *p++ = 0xf9U;
+ *p++ = 0x80U;
+ *p++ = 0x00U;
+ enc_ctx->ptr = p;
+ return;
+ }
+ } else {
+ if (d <= 4294967295.0) {
+ /* Positive zero needs no special handling. */
+ DUK_ASSERT(d >= 0.0);
+ duk__cbor_encode_uint32(enc_ctx, duk__cbor_double_to_uint32(d), 0x00U);
+ return;
+ }
+ }
+ }
+
+ /* 64-bit integers are not supported at present. So
+ * we also don't need to deal with choosing between a
+ * 64-bit uint/sint representation vs. IEEE double or
+ * float.
+ */
+
+ DUK_ASSERT(DUK_FPCLASSIFY(d) != DUK_FP_ZERO);
+ duk__cbor_encode_double_fp(enc_ctx, d);
+}
+#endif /* DUK_CBOR_DOUBLE_AS_IS */
+
+DUK_LOCAL void duk__cbor_encode_string_top(duk_cbor_encode_context *enc_ctx) {
+ const duk_uint8_t *str;
+ duk_size_t len;
+ duk_uint8_t *p;
+
+ /* CBOR differentiates between UTF-8 text strings and byte strings.
+ * Text strings MUST be valid UTF-8, so not all Duktape strings can
+ * be encoded as valid CBOR text strings. Possible behaviors:
+ *
+ * 1. Use text string when input is valid UTF-8, otherwise use
+ * byte string (maybe tagged to indicate it was an extended
+ * UTF-8 string).
+ * 2. Always use text strings, but sanitize input string so that
+ * invalid UTF-8 is replaced with U+FFFD for example. Combine
+ * surrogates whenever possible.
+ * 3. Always use byte strings. This is simple and produces valid
+ * CBOR, but isn't ideal for interoperability.
+ * 4. Always use text strings, even for invalid UTF-8 such as
+ * codepoints in the surrogate pair range. This is simple but
+ * produces technically invalid CBOR for non-UTF-8 strings which
+ * may affect interoperability.
+ *
+ * Current default is 1; can be changed with defines.
+ */
+
+ /* Caller must ensure space. */
+ DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
+
+ str = (const duk_uint8_t *) duk_require_lstring(enc_ctx->thr, -1, &len);
+ if (duk_is_symbol(enc_ctx->thr, -1)) {
+ /* Symbols, encode as an empty table for now. This matches
+ * the behavior of cbor-js.
+ *
+ * XXX: Maybe encode String() coercion with a tag?
+ * XXX: Option to keep enough information to recover
+ * Symbols when decoding (this is not always desirable).
+ */
+ p = enc_ctx->ptr;
+ *p++ = 0xa0U;
+ enc_ctx->ptr = p;
+ return;
+ }
+
+ duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
+#if defined(DUK_CBOR_TEXT_STRINGS)
+ duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x60U);
+#elif defined(DUK_CBOR_BYTE_STRINGS)
+ duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U);
+#else
+ duk__cbor_encode_uint32(enc_ctx,
+ (duk_uint32_t) len,
+ (DUK_LIKELY(duk_unicode_is_utf8_compatible(str, len) != 0) ? 0x60U : 0x40U));
+#endif
+ duk__cbor_encode_ensure(enc_ctx, len);
+ p = enc_ctx->ptr;
+ duk_memcpy((void *) p, (const void *) str, len);
+ p += len;
+ enc_ctx->ptr = p;
+}
+
+DUK_LOCAL void duk__cbor_encode_object(duk_cbor_encode_context *enc_ctx) {
+ duk_uint8_t *buf;
+ duk_size_t len;
+ duk_uint8_t *p;
+ duk_size_t i;
+ duk_size_t off_ib;
+ duk_uint32_t count;
+
+ /* Caller must ensure space. */
+ DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
+
+ duk__cbor_encode_objarr_entry(enc_ctx);
+
+ /* XXX: Support for specific built-ins like Date and RegExp. */
+ if (duk_is_array(enc_ctx->thr, -1)) {
+ /* Shortest encoding for arrays >= 256 in length is actually
+ * the indefinite length one (3 or more bytes vs. 2 bytes).
+ * We still use the definite length version because it is
+ * more decoding friendly.
+ */
+ len = duk_get_length(enc_ctx->thr, -1);
+ duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
+ duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x80U);
+ for (i = 0; i < len; i++) {
+ duk_get_prop_index(enc_ctx->thr, -1, (duk_uarridx_t) i);
+ duk__cbor_encode_value(enc_ctx);
+ }
+ } else if (duk_is_buffer_data(enc_ctx->thr, -1)) {
+ /* XXX: Tag buffer data?
+ * XXX: Encode typed arrays as integer arrays rather
+ * than buffer data as is?
+ */
+ buf = (duk_uint8_t *) duk_require_buffer_data(enc_ctx->thr, -1, &len);
+ duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
+ duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U);
+ duk__cbor_encode_ensure(enc_ctx, len);
+ p = enc_ctx->ptr;
+ duk_memcpy_unsafe((void *) p, (const void *) buf, len);
+ p += len;
+ enc_ctx->ptr = p;
+ } else {
+ /* We don't know the number of properties in advance
+ * but would still like to encode at least small
+ * objects without indefinite length. Emit an
+ * indefinite length byte initially, and if the final
+ * property count is small enough to also fit in one
+ * byte, backpatch it later. Otherwise keep the
+ * indefinite length. This works well up to 23
+ * properties which is practical and good enough.
+ */
+ off_ib = (duk_size_t) (enc_ctx->ptr - enc_ctx->buf); /* XXX: get_offset? */
+ count = 0U;
+ p = enc_ctx->ptr;
+ *p++ = 0xa0U + 0x1fU; /* indefinite length */
+ enc_ctx->ptr = p;
+ duk_enum(enc_ctx->thr, -1, DUK_ENUM_OWN_PROPERTIES_ONLY);
+ while (duk_next(enc_ctx->thr, -1, 1 /*get_value*/)) {
+ duk_insert(enc_ctx->thr, -2); /* [ ... key value ] -> [ ... value key ] */
+ duk__cbor_encode_value(enc_ctx);
+ duk__cbor_encode_value(enc_ctx);
+ count++;
+ if (count == 0U) {
+ duk__cbor_encode_error(enc_ctx);
+ }
+ }
+ duk_pop(enc_ctx->thr);
+ if (count <= 0x17U) {
+ DUK_ASSERT(off_ib < enc_ctx->len);
+ enc_ctx->buf[off_ib] = 0xa0U + (duk_uint8_t) count;
+ } else {
+ duk__cbor_encode_ensure(enc_ctx, 1);
+ p = enc_ctx->ptr;
+ *p++ = 0xffU; /* break */
+ enc_ctx->ptr = p;
+ }
+ }
+
+ duk__cbor_encode_objarr_exit(enc_ctx);
+}
+
+DUK_LOCAL void duk__cbor_encode_buffer(duk_cbor_encode_context *enc_ctx) {
+ duk_uint8_t *buf;
+ duk_size_t len;
+ duk_uint8_t *p;
+
+ /* Caller must ensure space. */
+ DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
+
+ /* Tag buffer data? */
+ buf = (duk_uint8_t *) duk_require_buffer(enc_ctx->thr, -1, &len);
+ duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
+ duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U);
+ duk__cbor_encode_ensure(enc_ctx, len);
+ p = enc_ctx->ptr;
+ duk_memcpy_unsafe((void *) p, (const void *) buf, len);
+ p += len;
+ enc_ctx->ptr = p;
+}
+
+DUK_LOCAL void duk__cbor_encode_pointer(duk_cbor_encode_context *enc_ctx) {
+ /* Pointers (void *) are challenging to encode. They can't
+ * be relied to be even 64-bit integer compatible (there are
+ * pointer models larger than that), nor can floats encode
+ * them. They could be encoded as strings (%p format) but
+ * that's not portable. They could be encoded as direct memory
+ * representations. Recovering pointers is non-portable in any
+ * case but it would be nice to be able to detect and recover
+ * compatible pointers.
+ *
+ * For now, encode as "(%p)" string, matching JX. There doesn't
+ * seem to be an appropriate tag, so pointers don't currently
+ * survive a CBOR encode/decode roundtrip intact.
+ */
+ const char *ptr;
+
+ ptr = duk_to_string(enc_ctx->thr, -1);
+ DUK_ASSERT(ptr != NULL);
+ duk_push_sprintf(enc_ctx->thr, "(%s)", ptr);
+ duk_remove(enc_ctx->thr, -2);
+ duk__cbor_encode_string_top(enc_ctx);
+}
+
+DUK_LOCAL void duk__cbor_encode_lightfunc(duk_cbor_encode_context *enc_ctx) {
+ duk_uint8_t *p;
+
+ /* Caller must ensure space. */
+ DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
+
+ /* For now encode as an empty object. */
+ p = enc_ctx->ptr;
+ *p++ = 0xa0U;
+ enc_ctx->ptr = p;
+}
+
+DUK_LOCAL void duk__cbor_encode_value(duk_cbor_encode_context *enc_ctx) {
+ duk_uint8_t *p;
+
+ /* Encode/decode cycle currently loses some type information.
+ * This can be improved by registering custom tags with IANA.
+ */
+
+ /* Reserve space for up to 64-bit types (1 initial byte + 8
+ * followup bytes). This allows encoding of integers, floats,
+ * string/buffer length fields, etc without separate checks
+ * in each code path.
+ */
+ duk__cbor_encode_ensure(enc_ctx, 1 + 8);
+
+ switch (duk_get_type(enc_ctx->thr, -1)) {
+ case DUK_TYPE_UNDEFINED: {
+ p = enc_ctx->ptr;
+ *p++ = 0xf7;
+ enc_ctx->ptr = p;
+ break;
+ }
+ case DUK_TYPE_NULL: {
+ p = enc_ctx->ptr;
+ *p++ = 0xf6;
+ enc_ctx->ptr = p;
+ break;
+ }
+ case DUK_TYPE_BOOLEAN: {
+ duk_uint8_t u8 = duk_get_boolean(enc_ctx->thr, -1) ? 0xf5U : 0xf4U;
+ p = enc_ctx->ptr;
+ *p++ = u8;
+ enc_ctx->ptr = p;
+ break;
+ }
+ case DUK_TYPE_NUMBER: {
+ duk__cbor_encode_double(enc_ctx, duk_get_number(enc_ctx->thr, -1));
+ break;
+ }
+ case DUK_TYPE_STRING: {
+ duk__cbor_encode_string_top(enc_ctx);
+ break;
+ }
+ case DUK_TYPE_OBJECT: {
+ duk__cbor_encode_object(enc_ctx);
+ break;
+ }
+ case DUK_TYPE_BUFFER: {
+ duk__cbor_encode_buffer(enc_ctx);
+ break;
+ }
+ case DUK_TYPE_POINTER: {
+ duk__cbor_encode_pointer(enc_ctx);
+ break;
+ }
+ case DUK_TYPE_LIGHTFUNC: {
+ duk__cbor_encode_lightfunc(enc_ctx);
+ break;
+ }
+ case DUK_TYPE_NONE:
+ default:
+ goto fail;
+ }
+
+ duk_pop(enc_ctx->thr);
+ return;
+
+fail:
+ duk__cbor_encode_error(enc_ctx);
+}
+
+/*
+ * Decoding
+ */
+
+DUK_LOCAL void duk__cbor_decode_error(duk_cbor_decode_context *dec_ctx) {
+ (void) duk_type_error(dec_ctx->thr, "cbor decode error");
+}
+
+DUK_LOCAL void duk__cbor_decode_req_stack(duk_cbor_decode_context *dec_ctx) {
+ duk_require_stack(dec_ctx->thr, 4);
+}
+
+DUK_LOCAL void duk__cbor_decode_objarr_entry(duk_cbor_decode_context *dec_ctx) {
+ duk_hthread *thr = dec_ctx->thr;
+
+ /* Native stack check in object/array recursion. */
+ duk_native_stack_check(thr);
+
+ duk__cbor_decode_req_stack(dec_ctx);
+
+ DUK_ASSERT(dec_ctx->recursion_depth <= dec_ctx->recursion_limit);
+ if (dec_ctx->recursion_depth >= dec_ctx->recursion_limit) {
+ DUK_ERROR_RANGE(thr, DUK_STR_DEC_RECLIMIT);
+ DUK_WO_NORETURN(return;);
+ }
+ dec_ctx->recursion_depth++;
+}
+
+DUK_LOCAL void duk__cbor_decode_objarr_exit(duk_cbor_decode_context *dec_ctx) {
+ DUK_ASSERT(dec_ctx->recursion_depth > 0);
+ dec_ctx->recursion_depth--;
+}
+
+DUK_LOCAL duk_uint8_t duk__cbor_decode_readbyte(duk_cbor_decode_context *dec_ctx) {
+ DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
+ if (DUK_UNLIKELY(dec_ctx->len - dec_ctx->off < 1U)) {
+ duk__cbor_decode_error(dec_ctx);
+ }
+ return dec_ctx->buf[dec_ctx->off++];
+}
+
+DUK_LOCAL duk_uint16_t duk__cbor_decode_read_u16(duk_cbor_decode_context *dec_ctx) {
+ duk_uint16_t res;
+
+ DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
+ if (DUK_UNLIKELY(dec_ctx->len - dec_ctx->off < 2U)) {
+ duk__cbor_decode_error(dec_ctx);
+ }
+ res = DUK_RAW_READ_U16_BE(dec_ctx->buf + dec_ctx->off);
+ dec_ctx->off += 2;
+ return res;
+}
+
+DUK_LOCAL duk_uint32_t duk__cbor_decode_read_u32(duk_cbor_decode_context *dec_ctx) {
+ duk_uint32_t res;
+
+ DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
+ if (DUK_UNLIKELY(dec_ctx->len - dec_ctx->off < 4U)) {
+ duk__cbor_decode_error(dec_ctx);
+ }
+ res = DUK_RAW_READ_U32_BE(dec_ctx->buf + dec_ctx->off);
+ dec_ctx->off += 4;
+ return res;
+}
+
+DUK_LOCAL duk_uint8_t duk__cbor_decode_peekbyte(duk_cbor_decode_context *dec_ctx) {
+ if (DUK_UNLIKELY(dec_ctx->off >= dec_ctx->len)) {
+ duk__cbor_decode_error(dec_ctx);
+ }
+ return dec_ctx->buf[dec_ctx->off];
+}
+
+DUK_LOCAL void duk__cbor_decode_rewind(duk_cbor_decode_context *dec_ctx, duk_size_t len) {
+ DUK_ASSERT(len <= dec_ctx->off); /* Caller must ensure. */
+ dec_ctx->off -= len;
+}
+
+#if 0
+DUK_LOCAL void duk__cbor_decode_ensure(duk_cbor_decode_context *dec_ctx, duk_size_t len) {
+ if (dec_ctx->off + len > dec_ctx->len) {
+ duk__cbor_decode_error(dec_ctx);
+ }
+}
+#endif
+
+DUK_LOCAL const duk_uint8_t *duk__cbor_decode_consume(duk_cbor_decode_context *dec_ctx, duk_size_t len) {
+ DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
+ if (DUK_LIKELY(dec_ctx->len - dec_ctx->off >= len)) {
+ const duk_uint8_t *res = dec_ctx->buf + dec_ctx->off;
+ dec_ctx->off += len;
+ return res;
+ }
+
+ duk__cbor_decode_error(dec_ctx); /* Not enough input. */
+ return NULL;
+}
+
+DUK_LOCAL int duk__cbor_decode_checkbreak(duk_cbor_decode_context *dec_ctx) {
+ if (duk__cbor_decode_peekbyte(dec_ctx) == 0xffU) {
+ DUK_ASSERT(dec_ctx->off < dec_ctx->len);
+ dec_ctx->off++;
+#if 0
+ (void) duk__cbor_decode_readbyte(dec_ctx);
+#endif
+ return 1;
+ }
+ return 0;
+}
+
+DUK_LOCAL void duk__cbor_decode_push_aival_int(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_bool_t negative) {
+ duk_uint8_t ai;
+ duk_uint32_t t, t1, t2;
+#if 0
+ duk_uint64_t t3;
+#endif
+ duk_double_t d1, d2;
+ duk_double_t d;
+
+ ai = ib & 0x1fU;
+ if (ai <= 0x17U) {
+ t = ai;
+ goto shared_exit;
+ }
+
+ switch (ai) {
+ case 0x18U: /* 1 byte */
+ t = (duk_uint32_t) duk__cbor_decode_readbyte(dec_ctx);
+ goto shared_exit;
+ case 0x19U: /* 2 byte */
+ t = (duk_uint32_t) duk__cbor_decode_read_u16(dec_ctx);
+ goto shared_exit;
+ case 0x1aU: /* 4 byte */
+ t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
+ goto shared_exit;
+ case 0x1bU: /* 8 byte */
+ /* For uint64 it's important to handle the -1.0 part before
+ * casting to double: otherwise the adjustment might be lost
+ * in the cast. Uses: -1.0 - d <=> -(d + 1.0).
+ */
+ t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
+ t2 = t;
+ t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
+ t1 = t;
+#if 0
+ t3 = (duk_uint64_t) t2 * DUK_U64_CONSTANT(0x100000000) + (duk_uint64_t) t1;
+ if (negative) {
+ if (t3 == DUK_UINT64_MAX) {
+ /* -(0xffff'ffff'ffff'ffffULL + 1) =
+ * -0x1'0000'0000'0000'0000
+ *
+ * >>> -0x10000000000000000
+ * -18446744073709551616L
+ */
+ return -18446744073709551616.0;
+ } else {
+ return -((duk_double_t) (t3 + DUK_U64_CONSTANT(1)));
+ }
+ } else {
+ return (duk_double_t) t3; /* XXX: cast helper */
+ }
+#endif
+#if 0
+ t3 = (duk_uint64_t) t2 * DUK_U64_CONSTANT(0x100000000) + (duk_uint64_t) t1;
+ if (negative) {
+ /* Simpler version: take advantage of the fact that
+ * 0xffff'ffff'ffff'ffff and 0x1'0000'0000'0000'0000
+ * both round to 0x1'0000'0000'0000'0000:
+ * > (0xffffffffffffffff).toString(16)
+ * '10000000000000000'
+ * > (0x10000000000000000).toString(16)
+ * '10000000000000000'
+ *
+ * For the DUK_UINT64_MAX case we just skip the +1
+ * increment to avoid wrapping; the result still
+ * comes out right for an IEEE double cast.
+ */
+ if (t3 != DUK_UINT64_MAX) {
+ t3++;
+ }
+ return -((duk_double_t) t3);
+ } else {
+ return (duk_double_t) t3; /* XXX: cast helper */
+ }
+#endif
+#if 1
+ /* Use two double parts, avoids dependency on 64-bit type.
+ * Avoid precision loss carefully, especially when dealing
+ * with the required +1 for negative values.
+ *
+ * No fastint check for this path at present.
+ */
+ d1 = (duk_double_t) t1; /* XXX: cast helpers */
+ d2 = (duk_double_t) t2 * 4294967296.0;
+ if (negative) {
+ d1 += 1.0;
+ }
+ d = d2 + d1;
+ if (negative) {
+ d = -d;
+ }
+#endif
+ /* XXX: a push and check for fastint API would be nice */
+ duk_push_number(dec_ctx->thr, d);
+ return;
+ }
+
+ duk__cbor_decode_error(dec_ctx);
+ return;
+
+shared_exit:
+ if (negative) {
+ /* XXX: a push and check for fastint API would be nice */
+ if ((duk_uint_t) t <= (duk_uint_t) - (DUK_INT_MIN + 1)) {
+ duk_push_int(dec_ctx->thr, -1 - ((duk_int_t) t));
+ } else {
+ duk_push_number(dec_ctx->thr, -1.0 - (duk_double_t) t);
+ }
+ } else {
+ duk_push_uint(dec_ctx->thr, (duk_uint_t) t);
+ }
+}
+
+DUK_LOCAL void duk__cbor_decode_skip_aival_int(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib) {
+ const duk_int8_t skips[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 8, -1, -1, -1, -1 };
+ duk_uint8_t ai;
+ duk_int8_t skip;
+
+ ai = ib & 0x1fU;
+ skip = skips[ai];
+ if (DUK_UNLIKELY(skip < 0)) {
+ duk__cbor_decode_error(dec_ctx);
+ }
+ duk__cbor_decode_consume(dec_ctx, (duk_size_t) skip);
+ return;
+}
+
+DUK_LOCAL duk_uint32_t duk__cbor_decode_aival_uint32(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib) {
+ duk_uint8_t ai;
+ duk_uint32_t t;
+
+ ai = ib & 0x1fU;
+ if (ai <= 0x17U) {
+ return (duk_uint32_t) ai;
+ }
+
+ switch (ai) {
+ case 0x18U: /* 1 byte */
+ t = (duk_uint32_t) duk__cbor_decode_readbyte(dec_ctx);
+ return t;
+ case 0x19U: /* 2 byte */
+ t = (duk_uint32_t) duk__cbor_decode_read_u16(dec_ctx);
+ return t;
+ case 0x1aU: /* 4 byte */
+ t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
+ return t;
+ case 0x1bU: /* 8 byte */
+ t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
+ if (t != 0U) {
+ break;
+ }
+ t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
+ return t;
+ }
+
+ duk__cbor_decode_error(dec_ctx);
+ return 0U;
+}
+
+DUK_LOCAL void duk__cbor_decode_buffer(duk_cbor_decode_context *dec_ctx, duk_uint8_t expected_base) {
+ duk_uint32_t len;
+ duk_uint8_t *buf;
+ const duk_uint8_t *inp;
+ duk_uint8_t ib;
+
+ ib = duk__cbor_decode_readbyte(dec_ctx);
+ if ((ib & 0xe0U) != expected_base) {
+ duk__cbor_decode_error(dec_ctx);
+ }
+ /* Indefinite format is rejected by the following on purpose. */
+ len = duk__cbor_decode_aival_uint32(dec_ctx, ib);
+ inp = duk__cbor_decode_consume(dec_ctx, len);
+ /* XXX: duk_push_fixed_buffer_with_data() would be a nice API addition. */
+ buf = (duk_uint8_t *) duk_push_fixed_buffer(dec_ctx->thr, (duk_size_t) len);
+ duk_memcpy((void *) buf, (const void *) inp, (size_t) len);
+}
+
+DUK_LOCAL void duk__cbor_decode_join_buffers(duk_cbor_decode_context *dec_ctx, duk_idx_t count) {
+ duk_size_t total_size = 0;
+ duk_idx_t top = duk_get_top(dec_ctx->thr);
+ duk_idx_t base = top - count; /* count is >= 1 */
+ duk_idx_t idx;
+ duk_uint8_t *p = NULL;
+
+ DUK_ASSERT(count >= 1);
+ DUK_ASSERT(top >= count);
+
+ for (;;) {
+ /* First round: compute total size.
+ * Second round: copy into place.
+ */
+ for (idx = base; idx < top; idx++) {
+ duk_uint8_t *buf_data;
+ duk_size_t buf_size;
+
+ buf_data = (duk_uint8_t *) duk_require_buffer(dec_ctx->thr, idx, &buf_size);
+ if (p != NULL) {
+ duk_memcpy_unsafe((void *) p, (const void *) buf_data, buf_size);
+ p += buf_size;
+ } else {
+ total_size += buf_size;
+ if (DUK_UNLIKELY(total_size < buf_size)) { /* Wrap check. */
+ duk__cbor_decode_error(dec_ctx);
+ }
+ }
+ }
+
+ if (p != NULL) {
+ break;
+ } else {
+ p = (duk_uint8_t *) duk_push_fixed_buffer(dec_ctx->thr, total_size);
+ DUK_ASSERT(p != NULL);
+ }
+ }
+
+ duk_replace(dec_ctx->thr, base);
+ duk_pop_n(dec_ctx->thr, count - 1);
+}
+
+DUK_LOCAL void duk__cbor_decode_and_join_strbuf(duk_cbor_decode_context *dec_ctx, duk_uint8_t expected_base) {
+ duk_idx_t count = 0;
+ for (;;) {
+ if (duk__cbor_decode_checkbreak(dec_ctx)) {
+ break;
+ }
+ duk_require_stack(dec_ctx->thr, 1);
+ duk__cbor_decode_buffer(dec_ctx, expected_base);
+ count++;
+ if (DUK_UNLIKELY(count <= 0)) { /* Wrap check. */
+ duk__cbor_decode_error(dec_ctx);
+ }
+ }
+ if (count == 0) {
+ (void) duk_push_fixed_buffer(dec_ctx->thr, 0);
+ } else if (count > 1) {
+ duk__cbor_decode_join_buffers(dec_ctx, count);
+ }
+}
+
+DUK_LOCAL duk_double_t duk__cbor_decode_half_float(duk_cbor_decode_context *dec_ctx) {
+ duk_double_union u;
+ const duk_uint8_t *inp;
+ duk_int_t expt;
+ duk_uint_t u16;
+ duk_uint_t tmp;
+ duk_double_t res;
+
+ inp = duk__cbor_decode_consume(dec_ctx, 2);
+ u16 = ((duk_uint_t) inp[0] << 8) + (duk_uint_t) inp[1];
+ expt = (duk_int_t) ((u16 >> 10) & 0x1fU) - 15;
+
+ /* Reconstruct IEEE double into little endian order first, then convert
+ * to host order.
+ */
+
+ duk_memzero((void *) &u, sizeof(u));
+
+ if (expt == -15) {
+ /* Zero or denormal; but note that half float
+ * denormals become double normals.
+ */
+ if ((u16 & 0x03ffU) == 0) {
+ u.uc[7] = inp[0] & 0x80U;
+ } else {
+ /* Create denormal by first creating a double that
+ * contains the denormal bits and a leading implicit
+ * 1-bit. Then subtract away the implicit 1-bit.
+ *
+ * 0.mmmmmmmmmm * 2^-14
+ * 1.mmmmmmmmmm 0.... * 2^-14
+ * -1.0000000000 0.... * 2^-14
+ *
+ * Double exponent: -14 + 1023 = 0x3f1
+ */
+ u.uc[7] = 0x3fU;
+ u.uc[6] = 0x10U + (duk_uint8_t) ((u16 >> 6) & 0x0fU);
+ u.uc[5] = (duk_uint8_t) ((u16 << 2) & 0xffU); /* Mask is really 0xfcU */
+
+ duk_dblunion_little_to_host(&u);
+ res = u.d - 0.00006103515625; /* 2^(-14) */
+ if (u16 & 0x8000U) {
+ res = -res;
+ }
+ return res;
+ }
+ } else if (expt == 16) {
+ /* +/- Inf or NaN. */
+ if ((u16 & 0x03ffU) == 0) {
+ u.uc[7] = (inp[0] & 0x80U) + 0x7fU;
+ u.uc[6] = 0xf0U;
+ } else {
+ /* Create a 'quiet NaN' with highest
+ * bit set (there are some platforms
+ * where the NaN payload convention is
+ * the opposite). Keep sign.
+ */
+ u.uc[7] = (inp[0] & 0x80U) + 0x7fU;
+ u.uc[6] = 0xf8U;
+ }
+ } else {
+ /* Normal. */
+ tmp = (inp[0] & 0x80U) ? 0x80000000UL : 0UL;
+ tmp += (duk_uint_t) (expt + 1023) << 20;
+ tmp += (duk_uint_t) (inp[0] & 0x03U) << 18;
+ tmp += (duk_uint_t) (inp[1] & 0xffU) << 10;
+ u.uc[7] = (tmp >> 24) & 0xffU;
+ u.uc[6] = (tmp >> 16) & 0xffU;
+ u.uc[5] = (tmp >> 8) & 0xffU;
+ u.uc[4] = (tmp >> 0) & 0xffU;
+ }
+
+ duk_dblunion_little_to_host(&u);
+ return u.d;
+}
+
+DUK_LOCAL void duk__cbor_decode_string(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) {
+ /* If the CBOR string data is not valid UTF-8 it is technically
+ * invalid CBOR. Possible behaviors at least:
+ *
+ * 1. Reject the input, i.e. throw TypeError.
+ *
+ * 2. Accept the input, but sanitize non-UTF-8 data into UTF-8
+ * using U+FFFD replacements. Also it might make sense to
+ * decode non-BMP codepoints into surrogates for better
+ * ECMAScript compatibility.
+ *
+ * 3. Accept the input as a Duktape string (which are not always
+ * valid UTF-8), but reject any input that would create a
+ * Symbol representation.
+ *
+ * Current behavior is 3.
+ */
+
+ if (ai == 0x1fU) {
+ duk_uint8_t *buf_data;
+ duk_size_t buf_size;
+
+ duk__cbor_decode_and_join_strbuf(dec_ctx, 0x60U);
+ buf_data = (duk_uint8_t *) duk_require_buffer(dec_ctx->thr, -1, &buf_size);
+ (void) duk_push_lstring(dec_ctx->thr, (const char *) buf_data, buf_size);
+ duk_remove(dec_ctx->thr, -2);
+ } else {
+ duk_uint32_t len;
+ const duk_uint8_t *inp;
+
+ len = duk__cbor_decode_aival_uint32(dec_ctx, ib);
+ inp = duk__cbor_decode_consume(dec_ctx, len);
+ (void) duk_push_lstring(dec_ctx->thr, (const char *) inp, (duk_size_t) len);
+ }
+ if (duk_is_symbol(dec_ctx->thr, -1)) {
+ /* Refuse to create Symbols when decoding. */
+ duk__cbor_decode_error(dec_ctx);
+ }
+
+ /* XXX: Here a Duktape API call to convert input -> utf-8 with
+ * replacements would be nice.
+ */
+}
+
+DUK_LOCAL duk_bool_t duk__cbor_decode_array(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) {
+ duk_uint32_t idx, len;
+
+ duk__cbor_decode_objarr_entry(dec_ctx);
+
+ /* Support arrays up to 0xfffffffeU in length. 0xffffffff is
+ * used as an indefinite length marker.
+ */
+ if (ai == 0x1fU) {
+ len = 0xffffffffUL;
+ } else {
+ len = duk__cbor_decode_aival_uint32(dec_ctx, ib);
+ if (len == 0xffffffffUL) {
+ goto failure;
+ }
+ }
+
+ /* XXX: use bare array? */
+ duk_push_array(dec_ctx->thr);
+ for (idx = 0U;;) {
+ if (len == 0xffffffffUL && duk__cbor_decode_checkbreak(dec_ctx)) {
+ break;
+ }
+ if (idx == len) {
+ if (ai == 0x1fU) {
+ goto failure;
+ }
+ break;
+ }
+ duk__cbor_decode_value(dec_ctx);
+ duk_put_prop_index(dec_ctx->thr, -2, (duk_uarridx_t) idx);
+ idx++;
+ if (idx == 0U) {
+ goto failure; /* wrapped */
+ }
+ }
+
+#if 0
+ success:
+#endif
+ duk__cbor_decode_objarr_exit(dec_ctx);
+ return 1;
+
+failure:
+ /* No need to unwind recursion checks, caller will throw. */
+ return 0;
+}
+
+DUK_LOCAL duk_bool_t duk__cbor_decode_map(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) {
+ duk_uint32_t count;
+
+ duk__cbor_decode_objarr_entry(dec_ctx);
+
+ if (ai == 0x1fU) {
+ count = 0xffffffffUL;
+ } else {
+ count = duk__cbor_decode_aival_uint32(dec_ctx, ib);
+ if (count == 0xffffffffUL) {
+ goto failure;
+ }
+ }
+
+ /* XXX: use bare object? */
+ duk_push_object(dec_ctx->thr);
+ for (;;) {
+ if (count == 0xffffffffUL) {
+ if (duk__cbor_decode_checkbreak(dec_ctx)) {
+ break;
+ }
+ } else {
+ if (count == 0UL) {
+ break;
+ }
+ count--;
+ }
+
+ /* Non-string keys are coerced to strings,
+ * possibly leading to overwriting previous
+ * keys. Last key of a certain coerced name
+ * wins. If key is an object, it will coerce
+ * to '[object Object]' which is consistent
+ * but potentially misleading. One alternative
+ * would be to skip non-string keys.
+ */
+ duk__cbor_decode_value(dec_ctx);
+ duk__cbor_decode_value(dec_ctx);
+ duk_put_prop(dec_ctx->thr, -3);
+ }
+
+#if 0
+ success:
+#endif
+ duk__cbor_decode_objarr_exit(dec_ctx);
+ return 1;
+
+failure:
+ /* No need to unwind recursion checks, caller will throw. */
+ return 0;
+}
+
+DUK_LOCAL duk_double_t duk__cbor_decode_float(duk_cbor_decode_context *dec_ctx) {
+ duk_float_union u;
+ const duk_uint8_t *inp;
+ inp = duk__cbor_decode_consume(dec_ctx, 4);
+ duk_memcpy((void *) u.uc, (const void *) inp, 4);
+ duk_fltunion_big_to_host(&u);
+ return (duk_double_t) u.f;
+}
+
+DUK_LOCAL duk_double_t duk__cbor_decode_double(duk_cbor_decode_context *dec_ctx) {
+ duk_double_union u;
+ const duk_uint8_t *inp;
+ inp = duk__cbor_decode_consume(dec_ctx, 8);
+ duk_memcpy((void *) u.uc, (const void *) inp, 8);
+ duk_dblunion_big_to_host(&u);
+ return u.d;
+}
+
+#if defined(DUK_CBOR_DECODE_FASTPATH)
+#define DUK__CBOR_AI (ib & 0x1fU)
+
+DUK_LOCAL void duk__cbor_decode_value(duk_cbor_decode_context *dec_ctx) {
+ duk_uint8_t ib;
+
+ /* Any paths potentially recursing back to duk__cbor_decode_value()
+ * must perform a Duktape value stack growth check. Avoid the check
+ * here for simple paths like primitive values.
+ */
+
+reread_initial_byte:
+ DUK_DDD(DUK_DDDPRINT("cbor decode off=%ld len=%ld", (long) dec_ctx->off, (long) dec_ctx->len));
+
+ ib = duk__cbor_decode_readbyte(dec_ctx);
+
+ /* Full initial byte switch, footprint cost over baseline is ~+1kB. */
+ /* XXX: Force full switch with no range check. */
+
+ switch (ib) {
+ case 0x00U:
+ case 0x01U:
+ case 0x02U:
+ case 0x03U:
+ case 0x04U:
+ case 0x05U:
+ case 0x06U:
+ case 0x07U:
+ case 0x08U:
+ case 0x09U:
+ case 0x0aU:
+ case 0x0bU:
+ case 0x0cU:
+ case 0x0dU:
+ case 0x0eU:
+ case 0x0fU:
+ case 0x10U:
+ case 0x11U:
+ case 0x12U:
+ case 0x13U:
+ case 0x14U:
+ case 0x15U:
+ case 0x16U:
+ case 0x17U:
+ duk_push_uint(dec_ctx->thr, ib);
+ break;
+ case 0x18U:
+ case 0x19U:
+ case 0x1aU:
+ case 0x1bU:
+ duk__cbor_decode_push_aival_int(dec_ctx, ib, 0 /*negative*/);
+ break;
+ case 0x1cU:
+ case 0x1dU:
+ case 0x1eU:
+ case 0x1fU:
+ goto format_error;
+ case 0x20U:
+ case 0x21U:
+ case 0x22U:
+ case 0x23U:
+ case 0x24U:
+ case 0x25U:
+ case 0x26U:
+ case 0x27U:
+ case 0x28U:
+ case 0x29U:
+ case 0x2aU:
+ case 0x2bU:
+ case 0x2cU:
+ case 0x2dU:
+ case 0x2eU:
+ case 0x2fU:
+ case 0x30U:
+ case 0x31U:
+ case 0x32U:
+ case 0x33U:
+ case 0x34U:
+ case 0x35U:
+ case 0x36U:
+ case 0x37U:
+ duk_push_int(dec_ctx->thr, -((duk_int_t) ((ib - 0x20U) + 1U)));
+ break;
+ case 0x38U:
+ case 0x39U:
+ case 0x3aU:
+ case 0x3bU:
+ duk__cbor_decode_push_aival_int(dec_ctx, ib, 1 /*negative*/);
+ break;
+ case 0x3cU:
+ case 0x3dU:
+ case 0x3eU:
+ case 0x3fU:
+ goto format_error;
+ case 0x40U:
+ case 0x41U:
+ case 0x42U:
+ case 0x43U:
+ case 0x44U:
+ case 0x45U:
+ case 0x46U:
+ case 0x47U:
+ case 0x48U:
+ case 0x49U:
+ case 0x4aU:
+ case 0x4bU:
+ case 0x4cU:
+ case 0x4dU:
+ case 0x4eU:
+ case 0x4fU:
+ case 0x50U:
+ case 0x51U:
+ case 0x52U:
+ case 0x53U:
+ case 0x54U:
+ case 0x55U:
+ case 0x56U:
+ case 0x57U:
+ /* XXX: Avoid rewind, we know the length already. */
+ DUK_ASSERT(dec_ctx->off > 0U);
+ dec_ctx->off--;
+ duk__cbor_decode_buffer(dec_ctx, 0x40U);
+ break;
+ case 0x58U:
+ case 0x59U:
+ case 0x5aU:
+ case 0x5bU:
+ /* XXX: Avoid rewind, decode length inline. */
+ DUK_ASSERT(dec_ctx->off > 0U);
+ dec_ctx->off--;
+ duk__cbor_decode_buffer(dec_ctx, 0x40U);
+ break;
+ case 0x5cU:
+ case 0x5dU:
+ case 0x5eU:
+ goto format_error;
+ case 0x5fU:
+ duk__cbor_decode_and_join_strbuf(dec_ctx, 0x40U);
+ break;
+ case 0x60U:
+ case 0x61U:
+ case 0x62U:
+ case 0x63U:
+ case 0x64U:
+ case 0x65U:
+ case 0x66U:
+ case 0x67U:
+ case 0x68U:
+ case 0x69U:
+ case 0x6aU:
+ case 0x6bU:
+ case 0x6cU:
+ case 0x6dU:
+ case 0x6eU:
+ case 0x6fU:
+ case 0x70U:
+ case 0x71U:
+ case 0x72U:
+ case 0x73U:
+ case 0x74U:
+ case 0x75U:
+ case 0x76U:
+ case 0x77U:
+ /* XXX: Avoid double decode of length. */
+ duk__cbor_decode_string(dec_ctx, ib, DUK__CBOR_AI);
+ break;
+ case 0x78U:
+ case 0x79U:
+ case 0x7aU:
+ case 0x7bU:
+ /* XXX: Avoid double decode of length. */
+ duk__cbor_decode_string(dec_ctx, ib, DUK__CBOR_AI);
+ break;
+ case 0x7cU:
+ case 0x7dU:
+ case 0x7eU:
+ goto format_error;
+ case 0x7fU:
+ duk__cbor_decode_string(dec_ctx, ib, DUK__CBOR_AI);
+ break;
+ case 0x80U:
+ case 0x81U:
+ case 0x82U:
+ case 0x83U:
+ case 0x84U:
+ case 0x85U:
+ case 0x86U:
+ case 0x87U:
+ case 0x88U:
+ case 0x89U:
+ case 0x8aU:
+ case 0x8bU:
+ case 0x8cU:
+ case 0x8dU:
+ case 0x8eU:
+ case 0x8fU:
+ case 0x90U:
+ case 0x91U:
+ case 0x92U:
+ case 0x93U:
+ case 0x94U:
+ case 0x95U:
+ case 0x96U:
+ case 0x97U:
+ if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
+ goto format_error;
+ }
+ break;
+ case 0x98U:
+ case 0x99U:
+ case 0x9aU:
+ case 0x9bU:
+ if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
+ goto format_error;
+ }
+ break;
+ case 0x9cU:
+ case 0x9dU:
+ case 0x9eU:
+ goto format_error;
+ case 0x9fU:
+ if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
+ goto format_error;
+ }
+ break;
+ case 0xa0U:
+ case 0xa1U:
+ case 0xa2U:
+ case 0xa3U:
+ case 0xa4U:
+ case 0xa5U:
+ case 0xa6U:
+ case 0xa7U:
+ case 0xa8U:
+ case 0xa9U:
+ case 0xaaU:
+ case 0xabU:
+ case 0xacU:
+ case 0xadU:
+ case 0xaeU:
+ case 0xafU:
+ case 0xb0U:
+ case 0xb1U:
+ case 0xb2U:
+ case 0xb3U:
+ case 0xb4U:
+ case 0xb5U:
+ case 0xb6U:
+ case 0xb7U:
+ if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
+ goto format_error;
+ }
+ break;
+ case 0xb8U:
+ case 0xb9U:
+ case 0xbaU:
+ case 0xbbU:
+ if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
+ goto format_error;
+ }
+ break;
+ case 0xbcU:
+ case 0xbdU:
+ case 0xbeU:
+ goto format_error;
+ case 0xbfU:
+ if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
+ goto format_error;
+ }
+ break;
+ case 0xc0U:
+ case 0xc1U:
+ case 0xc2U:
+ case 0xc3U:
+ case 0xc4U:
+ case 0xc5U:
+ case 0xc6U:
+ case 0xc7U:
+ case 0xc8U:
+ case 0xc9U:
+ case 0xcaU:
+ case 0xcbU:
+ case 0xccU:
+ case 0xcdU:
+ case 0xceU:
+ case 0xcfU:
+ case 0xd0U:
+ case 0xd1U:
+ case 0xd2U:
+ case 0xd3U:
+ case 0xd4U:
+ case 0xd5U:
+ case 0xd6U:
+ case 0xd7U:
+ /* Tag 0-23: drop. */
+ goto reread_initial_byte;
+ case 0xd8U:
+ case 0xd9U:
+ case 0xdaU:
+ case 0xdbU:
+ duk__cbor_decode_skip_aival_int(dec_ctx, ib);
+ goto reread_initial_byte;
+ case 0xdcU:
+ case 0xddU:
+ case 0xdeU:
+ case 0xdfU:
+ goto format_error;
+ case 0xe0U:
+ goto format_error;
+ case 0xe1U:
+ goto format_error;
+ case 0xe2U:
+ goto format_error;
+ case 0xe3U:
+ goto format_error;
+ case 0xe4U:
+ goto format_error;
+ case 0xe5U:
+ goto format_error;
+ case 0xe6U:
+ goto format_error;
+ case 0xe7U:
+ goto format_error;
+ case 0xe8U:
+ goto format_error;
+ case 0xe9U:
+ goto format_error;
+ case 0xeaU:
+ goto format_error;
+ case 0xebU:
+ goto format_error;
+ case 0xecU:
+ goto format_error;
+ case 0xedU:
+ goto format_error;
+ case 0xeeU:
+ goto format_error;
+ case 0xefU:
+ goto format_error;
+ case 0xf0U:
+ goto format_error;
+ case 0xf1U:
+ goto format_error;
+ case 0xf2U:
+ goto format_error;
+ case 0xf3U:
+ goto format_error;
+ case 0xf4U:
+ duk_push_false(dec_ctx->thr);
+ break;
+ case 0xf5U:
+ duk_push_true(dec_ctx->thr);
+ break;
+ case 0xf6U:
+ duk_push_null(dec_ctx->thr);
+ break;
+ case 0xf7U:
+ duk_push_undefined(dec_ctx->thr);
+ break;
+ case 0xf8U:
+ /* Simple value 32-255, nothing defined yet, so reject. */
+ goto format_error;
+ case 0xf9U: {
+ duk_double_t d;
+ d = duk__cbor_decode_half_float(dec_ctx);
+ duk_push_number(dec_ctx->thr, d);
+ break;
+ }
+ case 0xfaU: {
+ duk_double_t d;
+ d = duk__cbor_decode_float(dec_ctx);
+ duk_push_number(dec_ctx->thr, d);
+ break;
+ }
+ case 0xfbU: {
+ duk_double_t d;
+ d = duk__cbor_decode_double(dec_ctx);
+ duk_push_number(dec_ctx->thr, d);
+ break;
+ }
+ case 0xfcU:
+ case 0xfdU:
+ case 0xfeU:
+ case 0xffU:
+ goto format_error;
+ } /* end switch */
+
+ return;
+
+format_error:
+ duk__cbor_decode_error(dec_ctx);
+}
+#else /* DUK_CBOR_DECODE_FASTPATH */
+DUK_LOCAL void duk__cbor_decode_value(duk_cbor_decode_context *dec_ctx) {
+ duk_uint8_t ib, mt, ai;
+
+ /* Any paths potentially recursing back to duk__cbor_decode_value()
+ * must perform a Duktape value stack growth check. Avoid the check
+ * here for simple paths like primitive values.
+ */
+
+reread_initial_byte:
+ DUK_DDD(DUK_DDDPRINT("cbor decode off=%ld len=%ld", (long) dec_ctx->off, (long) dec_ctx->len));
+
+ ib = duk__cbor_decode_readbyte(dec_ctx);
+ mt = ib >> 5U;
+ ai = ib & 0x1fU;
+
+ /* Additional information in [24,27] = [0x18,0x1b] has relatively
+ * uniform handling for all major types: read 1/2/4/8 additional
+ * bytes. For major type 7 the 1-byte value is a 'simple type', and
+ * 2/4/8-byte values are floats. For other major types the 1/2/4/8
+ * byte values are integers. The lengths are uniform, but the typing
+ * is not.
+ */
+
+ switch (mt) {
+ case 0U: { /* unsigned integer */
+ duk__cbor_decode_push_aival_int(dec_ctx, ib, 0 /*negative*/);
+ break;
+ }
+ case 1U: { /* negative integer */
+ duk__cbor_decode_push_aival_int(dec_ctx, ib, 1 /*negative*/);
+ break;
+ }
+ case 2U: { /* byte string */
+ if (ai == 0x1fU) {
+ duk__cbor_decode_and_join_strbuf(dec_ctx, 0x40U);
+ } else {
+ duk__cbor_decode_rewind(dec_ctx, 1U);
+ duk__cbor_decode_buffer(dec_ctx, 0x40U);
+ }
+ break;
+ }
+ case 3U: { /* text string */
+ duk__cbor_decode_string(dec_ctx, ib, ai);
+ break;
+ }
+ case 4U: { /* array of data items */
+ if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, ai) == 0)) {
+ goto format_error;
+ }
+ break;
+ }
+ case 5U: { /* map of pairs of data items */
+ if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, ai) == 0)) {
+ goto format_error;
+ }
+ break;
+ }
+ case 6U: { /* semantic tagging */
+ /* Tags are ignored now, re-read initial byte. A tagged
+ * value may itself be tagged (an unlimited number of times)
+ * so keep on peeling away tags.
+ */
+ duk__cbor_decode_skip_aival_int(dec_ctx, ib);
+ goto reread_initial_byte;
+ }
+ case 7U: { /* floating point numbers, simple data types, break; other */
+ switch (ai) {
+ case 0x14U: {
+ duk_push_false(dec_ctx->thr);
+ break;
+ }
+ case 0x15U: {
+ duk_push_true(dec_ctx->thr);
+ break;
+ }
+ case 0x16U: {
+ duk_push_null(dec_ctx->thr);
+ break;
+ }
+ case 0x17U: {
+ duk_push_undefined(dec_ctx->thr);
+ break;
+ }
+ case 0x18U: { /* more simple values (1 byte) */
+ /* Simple value encoded in additional byte (none
+ * are defined so far). RFC 7049 states that the
+ * follow-up byte must be 32-255 to minimize
+ * confusion. So, a non-shortest encoding like
+ * f815 (= true, shortest encoding f5) must be
+ * rejected. cbor.me tester rejects f815, but
+ * e.g. Python CBOR binding decodes it as true.
+ */
+ goto format_error;
+ }
+ case 0x19U: { /* half-float (2 bytes) */
+ duk_double_t d;
+ d = duk__cbor_decode_half_float(dec_ctx);
+ duk_push_number(dec_ctx->thr, d);
+ break;
+ }
+ case 0x1aU: { /* float (4 bytes) */
+ duk_double_t d;
+ d = duk__cbor_decode_float(dec_ctx);
+ duk_push_number(dec_ctx->thr, d);
+ break;
+ }
+ case 0x1bU: { /* double (8 bytes) */
+ duk_double_t d;
+ d = duk__cbor_decode_double(dec_ctx);
+ duk_push_number(dec_ctx->thr, d);
+ break;
+ }
+ case 0xffU: /* unexpected break */
+ default: {
+ goto format_error;
+ }
+ } /* end switch */
+ break;
+ }
+ default: {
+ goto format_error; /* will never actually occur */
+ }
+ } /* end switch */
+
+ return;
+
+format_error:
+ duk__cbor_decode_error(dec_ctx);
+}
+#endif /* DUK_CBOR_DECODE_FASTPATH */
+
+DUK_LOCAL void duk__cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags) {
+ duk_cbor_encode_context enc_ctx;
+ duk_uint8_t *buf;
+
+ DUK_UNREF(encode_flags);
+
+ idx = duk_require_normalize_index(thr, idx);
+
+ enc_ctx.thr = thr;
+ enc_ctx.idx_buf = duk_get_top(thr);
+
+ enc_ctx.len = 64;
+ buf = (duk_uint8_t *) duk_push_dynamic_buffer(thr, enc_ctx.len);
+ enc_ctx.ptr = buf;
+ enc_ctx.buf = buf;
+ enc_ctx.buf_end = buf + enc_ctx.len;
+
+ enc_ctx.recursion_depth = 0;
+ enc_ctx.recursion_limit = DUK_USE_CBOR_ENC_RECLIMIT;
+
+ duk_dup(thr, idx);
+ duk__cbor_encode_req_stack(&enc_ctx);
+ duk__cbor_encode_value(&enc_ctx);
+ DUK_ASSERT(enc_ctx.recursion_depth == 0);
+ duk_resize_buffer(enc_ctx.thr, enc_ctx.idx_buf, (duk_size_t) (enc_ctx.ptr - enc_ctx.buf));
+ duk_replace(thr, idx);
+}
+
+DUK_LOCAL void duk__cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags) {
+ duk_cbor_decode_context dec_ctx;
+
+ DUK_UNREF(decode_flags);
+
+ /* Suppress compile warnings for functions only needed with e.g.
+ * asserts enabled.
+ */
+ DUK_UNREF(duk__cbor_get_reserve);
+
+ idx = duk_require_normalize_index(thr, idx);
+
+ dec_ctx.thr = thr;
+ dec_ctx.buf = (const duk_uint8_t *) duk_require_buffer_data(thr, idx, &dec_ctx.len);
+ dec_ctx.off = 0;
+ /* dec_ctx.len: set above */
+
+ dec_ctx.recursion_depth = 0;
+ dec_ctx.recursion_limit = DUK_USE_CBOR_DEC_RECLIMIT;
+
+ duk__cbor_decode_req_stack(&dec_ctx);
+ duk__cbor_decode_value(&dec_ctx);
+ DUK_ASSERT(dec_ctx.recursion_depth == 0);
+ if (dec_ctx.off != dec_ctx.len) {
+ (void) duk_type_error(thr, "trailing garbage");
+ }
+
+ duk_replace(thr, idx);
+}
+
+#else /* DUK_USE_CBOR_SUPPORT */
+
+DUK_LOCAL void duk__cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags) {
+ DUK_UNREF(idx);
+ DUK_UNREF(encode_flags);
+ DUK_ERROR_UNSUPPORTED(thr);
+}
+
+DUK_LOCAL void duk__cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags) {
+ DUK_UNREF(idx);
+ DUK_UNREF(decode_flags);
+ DUK_ERROR_UNSUPPORTED(thr);
+}
+
+#endif /* DUK_USE_CBOR_SUPPORT */
+
+/*
+ * Public APIs
+ */
+
+DUK_EXTERNAL void duk_cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags) {
+ DUK_ASSERT_API_ENTRY(thr);
+ duk__cbor_encode(thr, idx, encode_flags);
+}
+DUK_EXTERNAL void duk_cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags) {
+ DUK_ASSERT_API_ENTRY(thr);
+ duk__cbor_decode(thr, idx, decode_flags);
+}
+
+#if defined(DUK_USE_CBOR_BUILTIN)
+#if defined(DUK_USE_CBOR_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_cbor_encode(duk_hthread *thr) {
+ DUK_ASSERT_TOP(thr, 1);
+
+ duk__cbor_encode(thr, -1, 0 /*flags*/);
+
+ /* Produce an ArrayBuffer by first decoding into a plain buffer which
+ * mimics a Uint8Array and gettings its .buffer property.
+ */
+ /* XXX: shortcut */
+ (void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_LC_BUFFER);
+ return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_cbor_decode(duk_hthread *thr) {
+ DUK_ASSERT_TOP(thr, 1);
+
+ duk__cbor_decode(thr, -1, 0 /*flags*/);
+ return 1;
+}
+#else /* DUK_USE_CBOR_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_cbor_encode(duk_hthread *thr) {
+ DUK_ERROR_UNSUPPORTED(thr);
+ DUK_WO_NORETURN(return 0;);
+}
+DUK_INTERNAL duk_ret_t duk_bi_cbor_decode(duk_hthread *thr) {
+ DUK_ERROR_UNSUPPORTED(thr);
+ DUK_WO_NORETURN(return 0;);
+}
+#endif /* DUK_USE_CBOR_SUPPORT */
+#endif /* DUK_USE_CBOR_BUILTIN */
+
+/* automatic undefs */
+#undef DUK__CBOR_AI
+/*
* Date built-ins
*
* Unlike most built-ins, Date has some platform dependencies for getting
@@ -28796,30 +32697,49 @@ DUK_LOCAL_DECL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk
*/
/* Debug macro to print all parts and dparts (used manually because of debug level). */
-#define DUK__DPRINT_PARTS_AND_DPARTS(parts,dparts) do { \
+#define DUK__DPRINT_PARTS_AND_DPARTS(parts, dparts) \
+ do { \
DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld, dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
- (long) (parts)[0], (long) (parts)[1], \
- (long) (parts)[2], (long) (parts)[3], \
- (long) (parts)[4], (long) (parts)[5], \
- (long) (parts)[6], (long) (parts)[7], \
- (double) (dparts)[0], (double) (dparts)[1], \
- (double) (dparts)[2], (double) (dparts)[3], \
- (double) (dparts)[4], (double) (dparts)[5], \
- (double) (dparts)[6], (double) (dparts)[7])); \
+ (long) (parts)[0], \
+ (long) (parts)[1], \
+ (long) (parts)[2], \
+ (long) (parts)[3], \
+ (long) (parts)[4], \
+ (long) (parts)[5], \
+ (long) (parts)[6], \
+ (long) (parts)[7], \
+ (double) (dparts)[0], \
+ (double) (dparts)[1], \
+ (double) (dparts)[2], \
+ (double) (dparts)[3], \
+ (double) (dparts)[4], \
+ (double) (dparts)[5], \
+ (double) (dparts)[6], \
+ (double) (dparts)[7])); \
} while (0)
-#define DUK__DPRINT_PARTS(parts) do { \
+#define DUK__DPRINT_PARTS(parts) \
+ do { \
DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld", \
- (long) (parts)[0], (long) (parts)[1], \
- (long) (parts)[2], (long) (parts)[3], \
- (long) (parts)[4], (long) (parts)[5], \
- (long) (parts)[6], (long) (parts)[7])); \
+ (long) (parts)[0], \
+ (long) (parts)[1], \
+ (long) (parts)[2], \
+ (long) (parts)[3], \
+ (long) (parts)[4], \
+ (long) (parts)[5], \
+ (long) (parts)[6], \
+ (long) (parts)[7])); \
} while (0)
-#define DUK__DPRINT_DPARTS(dparts) do { \
+#define DUK__DPRINT_DPARTS(dparts) \
+ do { \
DUK_D(DUK_DPRINT("dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
- (double) (dparts)[0], (double) (dparts)[1], \
- (double) (dparts)[2], (double) (dparts)[3], \
- (double) (dparts)[4], (double) (dparts)[5], \
- (double) (dparts)[6], (double) (dparts)[7])); \
+ (double) (dparts)[0], \
+ (double) (dparts)[1], \
+ (double) (dparts)[2], \
+ (double) (dparts)[3], \
+ (double) (dparts)[4], \
+ (double) (dparts)[5], \
+ (double) (dparts)[6], \
+ (double) (dparts)[7])); \
} while (0)
/* Equivalent year for DST calculations outside [1970,2038[ range, see
@@ -28827,7 +32747,7 @@ DUK_LOCAL_DECL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk
* starts with the same weekday on Jan 1.
* https://bugzilla.mozilla.org/show_bug.cgi?id=351066
*/
-#define DUK__YEAR(x) ((duk_uint8_t) ((x) - 1970))
+#define DUK__YEAR(x) ((duk_uint8_t) ((x) -1970))
DUK_LOCAL duk_uint8_t duk__date_equivyear[14] = {
#if 1
/* This is based on V8 EquivalentYear() algorithm (see util/genequivyear.py):
@@ -28835,12 +32755,22 @@ DUK_LOCAL duk_uint8_t duk__date_equivyear[14] = {
*/
/* non-leap year: sunday, monday, ... */
- DUK__YEAR(2023), DUK__YEAR(2035), DUK__YEAR(2019), DUK__YEAR(2031),
- DUK__YEAR(2015), DUK__YEAR(2027), DUK__YEAR(2011),
+ DUK__YEAR(2023),
+ DUK__YEAR(2035),
+ DUK__YEAR(2019),
+ DUK__YEAR(2031),
+ DUK__YEAR(2015),
+ DUK__YEAR(2027),
+ DUK__YEAR(2011),
/* leap year: sunday, monday, ... */
- DUK__YEAR(2012), DUK__YEAR(2024), DUK__YEAR(2008), DUK__YEAR(2020),
- DUK__YEAR(2032), DUK__YEAR(2016), DUK__YEAR(2028)
+ DUK__YEAR(2012),
+ DUK__YEAR(2024),
+ DUK__YEAR(2008),
+ DUK__YEAR(2020),
+ DUK__YEAR(2032),
+ DUK__YEAR(2016),
+ DUK__YEAR(2028)
#endif
#if 0
@@ -28863,71 +32793,70 @@ DUK_LOCAL duk_uint8_t duk__date_equivyear[14] = {
*/
/* Parser part count. */
-#define DUK__NUM_ISO8601_PARSER_PARTS 9
+#define DUK__NUM_ISO8601_PARSER_PARTS 9
/* Parser part indices. */
-#define DUK__PI_YEAR 0
-#define DUK__PI_MONTH 1
-#define DUK__PI_DAY 2
-#define DUK__PI_HOUR 3
-#define DUK__PI_MINUTE 4
-#define DUK__PI_SECOND 5
-#define DUK__PI_MILLISECOND 6
-#define DUK__PI_TZHOUR 7
-#define DUK__PI_TZMINUTE 8
+#define DUK__PI_YEAR 0
+#define DUK__PI_MONTH 1
+#define DUK__PI_DAY 2
+#define DUK__PI_HOUR 3
+#define DUK__PI_MINUTE 4
+#define DUK__PI_SECOND 5
+#define DUK__PI_MILLISECOND 6
+#define DUK__PI_TZHOUR 7
+#define DUK__PI_TZMINUTE 8
/* Parser part masks. */
-#define DUK__PM_YEAR (1 << DUK__PI_YEAR)
-#define DUK__PM_MONTH (1 << DUK__PI_MONTH)
-#define DUK__PM_DAY (1 << DUK__PI_DAY)
-#define DUK__PM_HOUR (1 << DUK__PI_HOUR)
-#define DUK__PM_MINUTE (1 << DUK__PI_MINUTE)
-#define DUK__PM_SECOND (1 << DUK__PI_SECOND)
-#define DUK__PM_MILLISECOND (1 << DUK__PI_MILLISECOND)
-#define DUK__PM_TZHOUR (1 << DUK__PI_TZHOUR)
-#define DUK__PM_TZMINUTE (1 << DUK__PI_TZMINUTE)
+#define DUK__PM_YEAR (1 << DUK__PI_YEAR)
+#define DUK__PM_MONTH (1 << DUK__PI_MONTH)
+#define DUK__PM_DAY (1 << DUK__PI_DAY)
+#define DUK__PM_HOUR (1 << DUK__PI_HOUR)
+#define DUK__PM_MINUTE (1 << DUK__PI_MINUTE)
+#define DUK__PM_SECOND (1 << DUK__PI_SECOND)
+#define DUK__PM_MILLISECOND (1 << DUK__PI_MILLISECOND)
+#define DUK__PM_TZHOUR (1 << DUK__PI_TZHOUR)
+#define DUK__PM_TZMINUTE (1 << DUK__PI_TZMINUTE)
/* Parser separator indices. */
-#define DUK__SI_PLUS 0
-#define DUK__SI_MINUS 1
-#define DUK__SI_T 2
-#define DUK__SI_SPACE 3
-#define DUK__SI_COLON 4
-#define DUK__SI_PERIOD 5
-#define DUK__SI_Z 6
-#define DUK__SI_NUL 7
+#define DUK__SI_PLUS 0
+#define DUK__SI_MINUS 1
+#define DUK__SI_T 2
+#define DUK__SI_SPACE 3
+#define DUK__SI_COLON 4
+#define DUK__SI_PERIOD 5
+#define DUK__SI_Z 6
+#define DUK__SI_NUL 7
/* Parser separator masks. */
-#define DUK__SM_PLUS (1 << DUK__SI_PLUS)
-#define DUK__SM_MINUS (1 << DUK__SI_MINUS)
-#define DUK__SM_T (1 << DUK__SI_T)
-#define DUK__SM_SPACE (1 << DUK__SI_SPACE)
-#define DUK__SM_COLON (1 << DUK__SI_COLON)
-#define DUK__SM_PERIOD (1 << DUK__SI_PERIOD)
-#define DUK__SM_Z (1 << DUK__SI_Z)
-#define DUK__SM_NUL (1 << DUK__SI_NUL)
+#define DUK__SM_PLUS (1 << DUK__SI_PLUS)
+#define DUK__SM_MINUS (1 << DUK__SI_MINUS)
+#define DUK__SM_T (1 << DUK__SI_T)
+#define DUK__SM_SPACE (1 << DUK__SI_SPACE)
+#define DUK__SM_COLON (1 << DUK__SI_COLON)
+#define DUK__SM_PERIOD (1 << DUK__SI_PERIOD)
+#define DUK__SM_Z (1 << DUK__SI_Z)
+#define DUK__SM_NUL (1 << DUK__SI_NUL)
/* Rule control flags. */
-#define DUK__CF_NEG (1 << 0) /* continue matching, set neg_tzoffset flag */
-#define DUK__CF_ACCEPT (1 << 1) /* accept string */
-#define DUK__CF_ACCEPT_NUL (1 << 2) /* accept string if next char is NUL (otherwise reject) */
-
-#define DUK__PACK_RULE(partmask,sepmask,nextpart,flags) \
- ((duk_uint32_t) (partmask) + \
- (((duk_uint32_t) (sepmask)) << 9) + \
- (((duk_uint32_t) (nextpart)) << 17) + \
+#define DUK__CF_NEG (1 << 0) /* continue matching, set neg_tzoffset flag */
+#define DUK__CF_ACCEPT (1 << 1) /* accept string */
+#define DUK__CF_ACCEPT_NUL (1 << 2) /* accept string if next char is NUL (otherwise reject) */
+
+#define DUK__PACK_RULE(partmask, sepmask, nextpart, flags) \
+ ((duk_uint32_t) (partmask) + (((duk_uint32_t) (sepmask)) << 9) + (((duk_uint32_t) (nextpart)) << 17) + \
(((duk_uint32_t) (flags)) << 21))
-#define DUK__UNPACK_RULE(rule,var_nextidx,var_flags) do { \
+#define DUK__UNPACK_RULE(rule, var_nextidx, var_flags) \
+ do { \
(var_nextidx) = (duk_small_uint_t) (((rule) >> 17) & 0x0f); \
(var_flags) = (duk_small_uint_t) ((rule) >> 21); \
} while (0)
-#define DUK__RULE_MASK_PART_SEP 0x1ffffUL
+#define DUK__RULE_MASK_PART_SEP 0x1ffffUL
/* Matching separator index is used in the control table */
DUK_LOCAL const duk_uint8_t duk__parse_iso8601_seps[] = {
- DUK_ASC_PLUS /*0*/, DUK_ASC_MINUS /*1*/, DUK_ASC_UC_T /*2*/, DUK_ASC_SPACE /*3*/,
+ DUK_ASC_PLUS /*0*/, DUK_ASC_MINUS /*1*/, DUK_ASC_UC_T /*2*/, DUK_ASC_SPACE /*3*/,
DUK_ASC_COLON /*4*/, DUK_ASC_PERIOD /*5*/, DUK_ASC_UC_Z /*6*/, DUK_ASC_NUL /*7*/
};
@@ -28940,10 +32869,26 @@ DUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[] = {
DUK__PACK_RULE(DUK__PM_MINUTE, DUK__SM_COLON, DUK__PI_SECOND, 0),
DUK__PACK_RULE(DUK__PM_SECOND, DUK__SM_PERIOD, DUK__PI_MILLISECOND, 0),
DUK__PACK_RULE(DUK__PM_TZHOUR, DUK__SM_COLON, DUK__PI_TZMINUTE, 0),
- DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND, DUK__SM_PLUS, DUK__PI_TZHOUR, 0),
- DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND, DUK__SM_MINUS, DUK__PI_TZHOUR, DUK__CF_NEG),
- DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND, DUK__SM_Z, 0, DUK__CF_ACCEPT_NUL),
- DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND | DUK__PM_TZHOUR /*Note2*/ | DUK__PM_TZMINUTE, DUK__SM_NUL, 0, DUK__CF_ACCEPT)
+ DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND |
+ DUK__PM_MILLISECOND,
+ DUK__SM_PLUS,
+ DUK__PI_TZHOUR,
+ 0),
+ DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND |
+ DUK__PM_MILLISECOND,
+ DUK__SM_MINUS,
+ DUK__PI_TZHOUR,
+ DUK__CF_NEG),
+ DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND |
+ DUK__PM_MILLISECOND,
+ DUK__SM_Z,
+ 0,
+ DUK__CF_ACCEPT_NUL),
+ DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND |
+ DUK__PM_MILLISECOND | DUK__PM_TZHOUR /*Note2*/ | DUK__PM_TZMINUTE,
+ DUK__SM_NUL,
+ 0,
+ DUK__CF_ACCEPT)
/* Note1: the specification doesn't require matching a time form with
* just hours ("HH"), but we accept it here, e.g. "2012-01-02T12Z".
@@ -28967,8 +32912,8 @@ DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_hthread *thr, const ch
duk_small_uint_t i;
/* During parsing, month and day are one-based; set defaults here. */
- DUK_MEMZERO(parts, sizeof(parts));
- DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] == 0); /* don't care value, year is mandatory */
+ duk_memzero(parts, sizeof(parts));
+ DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] == 0); /* don't care value, year is mandatory */
parts[DUK_DATE_IDX_MONTH] = 1;
parts[DUK_DATE_IDX_DAY] = 1;
@@ -28985,7 +32930,8 @@ DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_hthread *thr, const ch
for (;;) {
ch = *p++;
DUK_DDD(DUK_DDDPRINT("parsing, part_idx=%ld, char=%ld ('%c')",
- (long) part_idx, (long) ch,
+ (long) part_idx,
+ (long) ch,
(int) ((ch >= 0x20 && ch <= 0x7e) ? ch : DUK_ASC_QUESTION)));
if (ch >= DUK_ASC_0 && ch <= DUK_ASC_9) {
@@ -29030,7 +32976,7 @@ DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_hthread *thr, const ch
}
sep_idx = i;
- match_val = (1UL << part_idx) + (1UL << (sep_idx + 9)); /* match against rule part/sep bits */
+ match_val = (1UL << part_idx) + (1UL << (sep_idx + 9)); /* match against rule part/sep bits */
for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t)); i++) {
duk_uint_fast32_t rule = duk__parse_iso8601_control[i];
@@ -29038,8 +32984,10 @@ DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_hthread *thr, const ch
duk_small_uint_t cflags;
DUK_DDD(DUK_DDDPRINT("part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, considering rule=0x%08lx",
- (long) part_idx, (long) sep_idx,
- (unsigned long) match_val, (unsigned long) rule));
+ (long) part_idx,
+ (long) sep_idx,
+ (unsigned long) match_val,
+ (unsigned long) rule));
if ((rule & match_val) != match_val) {
continue;
@@ -29049,9 +32997,12 @@ DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_hthread *thr, const ch
DUK_DDD(DUK_DDDPRINT("rule match -> part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, "
"rule=0x%08lx -> nextpart=%ld, cflags=0x%02lx",
- (long) part_idx, (long) sep_idx,
- (unsigned long) match_val, (unsigned long) rule,
- (long) nextpart, (unsigned long) cflags));
+ (long) part_idx,
+ (long) sep_idx,
+ (unsigned long) match_val,
+ (unsigned long) rule,
+ (long) nextpart,
+ (unsigned long) cflags));
if (cflags & DUK__CF_NEG) {
neg_tzoffset = 1;
@@ -29071,7 +33022,7 @@ DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_hthread *thr, const ch
part_idx = nextpart;
break;
- } /* rule match */
+ } /* rule match */
if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t))) {
DUK_DDD(DUK_DDDPRINT("no rule matches -> reject"));
@@ -29085,17 +33036,17 @@ DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_hthread *thr, const ch
DUK_DDD(DUK_DDDPRINT("NUL after rule matching (should not happen) -> reject"));
goto reject;
}
- } /* if-digit-else-ctrl */
- } /* char loop */
+ } /* if-digit-else-ctrl */
+ } /* char loop */
/* We should never exit the loop above. */
DUK_UNREACHABLE();
- reject:
+reject:
DUK_DDD(DUK_DDDPRINT("reject"));
return 0;
- accept:
+accept:
DUK_DDD(DUK_DDDPRINT("accept"));
/* Apply timezone offset to get the main parts in UTC */
@@ -29109,8 +33060,8 @@ DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_hthread *thr, const ch
parts[DUK__PI_HOUR] -= parts[DUK__PI_TZHOUR];
parts[DUK__PI_MINUTE] -= parts[DUK__PI_TZMINUTE];
}
- parts[DUK__PI_MONTH] -= 1; /* zero-based month */
- parts[DUK__PI_DAY] -= 1; /* zero-based day */
+ parts[DUK__PI_MONTH] -= 1; /* zero-based month */
+ parts[DUK__PI_DAY] -= 1; /* zero-based day */
/* Use double parts, they tolerate unnormalized time.
*
@@ -29187,24 +33138,22 @@ DUK_LOCAL duk_ret_t duk__parse_string(duk_hthread *thr, const char *str) {
* out for non-finite numbers etc.
*/
-DUK_LOCAL duk_uint8_t duk__days_in_month[12] = {
- (duk_uint8_t) 31, (duk_uint8_t) 28, (duk_uint8_t) 31, (duk_uint8_t) 30,
- (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 31,
- (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31
-};
+DUK_LOCAL duk_uint8_t duk__days_in_month[12] = { (duk_uint8_t) 31, (duk_uint8_t) 28, (duk_uint8_t) 31, (duk_uint8_t) 30,
+ (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 31,
+ (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31 };
/* Maximum iteration count for computing UTC-to-local time offset when
- * creating an Ecmascript time value from local parts.
+ * creating an ECMAScript time value from local parts.
*/
-#define DUK__LOCAL_TZOFFSET_MAXITER 4
+#define DUK__LOCAL_TZOFFSET_MAXITER 4
/* Because 'day since epoch' can be negative and is used to compute weekday
* using a modulo operation, add this multiple of 7 to avoid negative values
- * when year is below 1970 epoch. Ecmascript time values are restricted to
+ * when year is below 1970 epoch. ECMAScript time values are restricted to
* +/- 100 million days from epoch, so this adder fits nicely into 32 bits.
* Round to a multiple of 7 (= floor(100000000 / 7) * 7) and add margin.
*/
-#define DUK__WEEKDAY_MOD_ADDER (20000000 * 7) /* 0x08583b00 */
+#define DUK__WEEKDAY_MOD_ADDER (20000000 * 7) /* 0x08583b00 */
DUK_INTERNAL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year) {
if ((year % 4) != 0) {
@@ -29265,10 +33214,8 @@ DUK_LOCAL duk_int_t duk__day_from_year(duk_int_t year) {
/* Note: in integer arithmetic, (x / 4) is same as floor(x / 4) for non-negative
* values, but is incorrect for negative ones.
*/
- return 365 * (year - 1970)
- + duk__div_floor(year - 1969, 4)
- - duk__div_floor(year - 1901, 100)
- + duk__div_floor(year - 1601, 400);
+ return 365 * (year - 1970) + duk__div_floor(year - 1969, 4) - duk__div_floor(year - 1901, 100) +
+ duk__div_floor(year - 1601, 400);
}
/* Given a day number, determine year and day-within-year. */
@@ -29290,10 +33237,9 @@ DUK_LOCAL duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_w
diff_days = duk__day_from_year(year) - day;
DUK_DDD(DUK_DDDPRINT("year=%ld day=%ld, diff_days=%ld", (long) year, (long) day, (long) diff_days));
if (diff_days <= 0) {
- DUK_ASSERT(-diff_days < 366); /* fits into duk_small_int_t */
+ DUK_ASSERT(-diff_days < 366); /* fits into duk_small_int_t */
*out_day_within_year = -diff_days;
- DUK_DDD(DUK_DDDPRINT("--> year=%ld, day-within-year=%ld",
- (long) year, (long) *out_day_within_year));
+ DUK_DDD(DUK_DDDPRINT("--> year=%ld, day-within-year=%ld", (long) year, (long) *out_day_within_year));
DUK_ASSERT(*out_day_within_year >= 0);
DUK_ASSERT(*out_day_within_year < (duk_bi_date_is_leap_year(year) ? 366 : 365));
return year;
@@ -29302,7 +33248,7 @@ DUK_LOCAL duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_w
/* Note: this is very tricky; we must never 'overshoot' the
* correction downwards.
*/
- year -= 1 + (diff_days - 1) / 366; /* conservative */
+ year -= 1 + (diff_days - 1) / 366; /* conservative */
}
}
@@ -29375,7 +33321,7 @@ DUK_INTERNAL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts,
duk_double_t d1, d2;
duk_int_t t1, t2;
duk_int_t day_since_epoch;
- duk_int_t year; /* does not fit into 16 bits */
+ duk_int_t year; /* does not fit into 16 bits */
duk_small_int_t day_in_year;
duk_small_int_t month;
duk_small_int_t day;
@@ -29387,14 +33333,14 @@ DUK_INTERNAL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts,
duk_bool_t is_leap;
duk_small_int_t arridx;
- DUK_ASSERT(DUK_ISFINITE(d)); /* caller checks */
- d = DUK_FLOOR(d); /* remove fractions if present */
- DUK_ASSERT(DUK_FLOOR(d) == d);
+ DUK_ASSERT(DUK_ISFINITE(d)); /* caller checks */
+ d = DUK_FLOOR(d); /* remove fractions if present */
+ DUK_ASSERT(duk_double_equals(DUK_FLOOR(d), d));
- /* The timevalue must be in valid Ecmascript range, but since a local
+ /* The timevalue must be in valid ECMAScript range, but since a local
* time offset can be applied, we need to allow a +/- 24h leeway to
* the value. In other words, although the UTC time is within the
- * Ecmascript range, the local part values can be just outside of it.
+ * ECMAScript range, the local part values can be just outside of it.
*/
DUK_UNREF(duk_bi_date_timeval_in_leeway_range);
DUK_ASSERT(duk_bi_date_timeval_in_leeway_range(d));
@@ -29408,21 +33354,24 @@ DUK_INTERNAL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts,
d1 += (duk_double_t) DUK_DATE_MSEC_DAY;
}
d2 = DUK_FLOOR((double) (d / (duk_double_t) DUK_DATE_MSEC_DAY));
- DUK_ASSERT(d2 * ((duk_double_t) DUK_DATE_MSEC_DAY) + d1 == d);
+ DUK_ASSERT(duk_double_equals(d2 * ((duk_double_t) DUK_DATE_MSEC_DAY) + d1, d));
/* now expected to fit into a 32-bit integer */
t1 = (duk_int_t) d1;
t2 = (duk_int_t) d2;
day_since_epoch = t2;
- DUK_ASSERT((duk_double_t) t1 == d1);
- DUK_ASSERT((duk_double_t) t2 == d2);
+ DUK_ASSERT(duk_double_equals((duk_double_t) t1, d1));
+ DUK_ASSERT(duk_double_equals((duk_double_t) t2, d2));
/* t1 = milliseconds within day (fits 32 bit)
* t2 = day number from epoch (fits 32 bit, may be negative)
*/
- parts[DUK_DATE_IDX_MILLISECOND] = t1 % 1000; t1 /= 1000;
- parts[DUK_DATE_IDX_SECOND] = t1 % 60; t1 /= 60;
- parts[DUK_DATE_IDX_MINUTE] = t1 % 60; t1 /= 60;
+ parts[DUK_DATE_IDX_MILLISECOND] = t1 % 1000;
+ t1 /= 1000;
+ parts[DUK_DATE_IDX_SECOND] = t1 % 60;
+ t1 /= 60;
+ parts[DUK_DATE_IDX_MINUTE] = t1 % 60;
+ t1 /= 60;
parts[DUK_DATE_IDX_HOUR] = t1;
DUK_ASSERT(parts[DUK_DATE_IDX_MILLISECOND] >= 0 && parts[DUK_DATE_IDX_MILLISECOND] <= 999);
DUK_ASSERT(parts[DUK_DATE_IDX_SECOND] >= 0 && parts[DUK_DATE_IDX_SECOND] <= 59);
@@ -29430,17 +33379,21 @@ DUK_INTERNAL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts,
DUK_ASSERT(parts[DUK_DATE_IDX_HOUR] >= 0 && parts[DUK_DATE_IDX_HOUR] <= 23);
DUK_DDD(DUK_DDDPRINT("d=%lf, d1=%lf, d2=%lf, t1=%ld, t2=%ld, parts: hour=%ld min=%ld sec=%ld msec=%ld",
- (double) d, (double) d1, (double) d2, (long) t1, (long) t2,
+ (double) d,
+ (double) d1,
+ (double) d2,
+ (long) t1,
+ (long) t2,
(long) parts[DUK_DATE_IDX_HOUR],
(long) parts[DUK_DATE_IDX_MINUTE],
(long) parts[DUK_DATE_IDX_SECOND],
(long) parts[DUK_DATE_IDX_MILLISECOND]));
/* This assert depends on the input parts representing time inside
- * the Ecmascript range.
+ * the ECMAScript range.
*/
DUK_ASSERT(t2 + DUK__WEEKDAY_MOD_ADDER >= 0);
- parts[DUK_DATE_IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */
+ parts[DUK_DATE_IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */
DUK_ASSERT(parts[DUK_DATE_IDX_WEEKDAY] >= 0 && parts[DUK_DATE_IDX_WEEKDAY] <= 6);
year = duk__year_from_day(t2, &day_in_year);
@@ -29451,8 +33404,7 @@ DUK_INTERNAL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts,
if (month == 1 && is_leap) {
dim++;
}
- DUK_DDD(DUK_DDDPRINT("month=%ld, dim=%ld, day=%ld",
- (long) month, (long) dim, (long) day));
+ DUK_DDD(DUK_DDDPRINT("month=%ld, dim=%ld, day=%ld", (long) month, (long) dim, (long) day));
if (day < dim) {
break;
}
@@ -29477,9 +33429,9 @@ DUK_INTERNAL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts,
if ((flags & DUK_DATE_FLAG_EQUIVYEAR) && (year < 1971 || year > 2037)) {
DUK_ASSERT(is_leap == 0 || is_leap == 1);
- jan1_since_epoch = day_since_epoch - day_in_year; /* day number for Jan 1 since epoch */
+ jan1_since_epoch = day_since_epoch - day_in_year; /* day number for Jan 1 since epoch */
DUK_ASSERT(jan1_since_epoch + DUK__WEEKDAY_MOD_ADDER >= 0);
- jan1_weekday = (jan1_since_epoch + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */
+ jan1_weekday = (jan1_since_epoch + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */
DUK_ASSERT(jan1_weekday >= 0 && jan1_weekday <= 6);
arridx = jan1_weekday;
if (is_leap) {
@@ -29491,8 +33443,12 @@ DUK_INTERNAL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts,
year = equiv_year;
DUK_DDD(DUK_DDDPRINT("equiv year mapping, year=%ld, day_in_year=%ld, day_since_epoch=%ld, "
"jan1_since_epoch=%ld, jan1_weekday=%ld -> equiv year %ld",
- (long) year, (long) day_in_year, (long) day_since_epoch,
- (long) jan1_since_epoch, (long) jan1_weekday, (long) equiv_year));
+ (long) year,
+ (long) day_in_year,
+ (long) day_since_epoch,
+ (long) jan1_since_epoch,
+ (long) jan1_weekday,
+ (long) equiv_year));
}
parts[DUK_DATE_IDX_YEAR] = year;
@@ -29500,8 +33456,8 @@ DUK_INTERNAL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts,
parts[DUK_DATE_IDX_DAY] = day;
if (flags & DUK_DATE_FLAG_ONEBASED) {
- parts[DUK_DATE_IDX_MONTH]++; /* zero-based -> one-based */
- parts[DUK_DATE_IDX_DAY]++; /* -""- */
+ parts[DUK_DATE_IDX_MONTH]++; /* zero-based -> one-based */
+ parts[DUK_DATE_IDX_DAY]++; /* -""- */
}
if (dparts != NULL) {
@@ -29557,7 +33513,7 @@ DUK_INTERNAL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dpar
* computation happens with intermediate results coerced to
* double values (instead of using something more accurate).
* E.g. E5.1 Section 15.9.1.11 requires use of IEEE 754
- * rules (= Ecmascript '+' and '*' operators).
+ * rules (= ECMAScript '+' and '*' operators).
*
* Without 'volatile' even this approach fails on some platform
* and compiler combinations. For instance, gcc 4.8.1 on Ubuntu
@@ -29581,8 +33537,7 @@ DUK_INTERNAL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dpar
/* MakeDate */
d = tmp_day * ((duk_double_t) DUK_DATE_MSEC_DAY) + tmp_time;
- DUK_DDD(DUK_DDDPRINT("time=%lf day=%lf --> timeval=%lf",
- (double) tmp_time, (double) tmp_day, (double) d));
+ DUK_DDD(DUK_DDDPRINT("time=%lf day=%lf --> timeval=%lf", (double) tmp_time, (double) tmp_day, (double) d));
/* Optional UTC conversion. */
if (flags & DUK_DATE_FLAG_LOCALTIME) {
@@ -29612,16 +33567,22 @@ DUK_INTERNAL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dpar
/* Iteration solution */
tzoff = 0;
- tzoffprev1 = 999999999L; /* invalid value which never matches */
+ tzoffprev1 = 999999999L; /* invalid value which never matches */
for (i = 0; i < DUK__LOCAL_TZOFFSET_MAXITER; i++) {
tzoffprev2 = tzoffprev1;
tzoffprev1 = tzoff;
tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d - tzoff * 1000L);
DUK_DDD(DUK_DDDPRINT("tzoffset iteration, i=%d, tzoff=%ld, tzoffprev1=%ld tzoffprev2=%ld",
- (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
+ (int) i,
+ (long) tzoff,
+ (long) tzoffprev1,
+ (long) tzoffprev2));
if (tzoff == tzoffprev1) {
DUK_DDD(DUK_DDDPRINT("tzoffset iteration finished, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
- (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
+ (int) i,
+ (long) tzoff,
+ (long) tzoffprev1,
+ (long) tzoffprev2));
break;
} else if (tzoff == tzoffprev2) {
/* Two value cycle, see e.g. test-bi-date-tzoffset-basic-fi.js.
@@ -29629,8 +33590,12 @@ DUK_INTERNAL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dpar
* result which is independent of iteration count. Not sure if
* this is a generically correct solution.
*/
- DUK_DDD(DUK_DDDPRINT("tzoffset iteration two-value cycle, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
- (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
+ DUK_DDD(DUK_DDDPRINT(
+ "tzoffset iteration two-value cycle, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
+ (int) i,
+ (long) tzoff,
+ (long) tzoffprev1,
+ (long) tzoffprev2));
if (tzoffprev1 > tzoff) {
tzoff = tzoffprev1;
}
@@ -29661,12 +33626,13 @@ DUK_LOCAL duk_double_t duk__push_this_get_timeval_tzoffset(duk_hthread *thr, duk
duk_int_t tzoffset = 0;
duk_push_this(thr);
- h = duk_get_hobject(thr, -1); /* XXX: getter with class check, useful in built-ins */
+ h = duk_get_hobject(thr, -1); /* XXX: getter with class check, useful in built-ins */
if (h == NULL || DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_DATE) {
DUK_ERROR_TYPE(thr, "expected Date");
+ DUK_WO_NORETURN(return 0.0;);
}
- duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
+ duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
d = duk_to_number_m1(thr);
duk_pop(thr);
@@ -29676,6 +33642,7 @@ DUK_LOCAL duk_double_t duk__push_this_get_timeval_tzoffset(duk_hthread *thr, duk
}
if (flags & DUK_DATE_FLAG_NAN_TO_RANGE_ERROR) {
DUK_ERROR_RANGE(thr, "Invalid Date");
+ DUK_WO_NORETURN(return 0.0;);
}
}
/* if no NaN handling flag, may still be NaN here, but not Inf */
@@ -29685,7 +33652,7 @@ DUK_LOCAL duk_double_t duk__push_this_get_timeval_tzoffset(duk_hthread *thr, duk
/* Note: DST adjustment is determined using UTC time.
* If 'd' is NaN, tzoffset will be 0.
*/
- tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d); /* seconds */
+ tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d); /* seconds */
d += tzoffset * 1000L;
}
if (out_tzoffset) {
@@ -29710,18 +33677,22 @@ DUK_LOCAL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk_doub
/* [ ... this ] */
d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
- duk_push_number(thr, d); /* -> [ ... this timeval_new ] */
- duk_dup_top(thr); /* -> [ ... this timeval_new timeval_new ] */
- duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE);
+ duk_push_number(thr, d); /* -> [ ... this timeval_new ] */
+ duk_dup_top(thr); /* -> [ ... this timeval_new timeval_new ] */
+
+ /* Must force write because e.g. .setYear() must work even when
+ * the Date instance is frozen.
+ */
+ duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
- /* stack top: new time value, return 1 to allow tail calls */
+ /* Stack top: new time value, return 1 to allow tail calls. */
return 1;
}
/* 'out_buf' must be at least DUK_BI_DATE_ISO8601_BUFSIZE long. */
DUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags, duk_uint8_t *out_buf) {
- char yearstr[8]; /* "-123456\0" */
- char tzstr[8]; /* "+11:22\0" */
+ char yearstr[8]; /* "-123456\0" */
+ char tzstr[8]; /* "+11:22\0" */
char sep = (flags & DUK_DATE_FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE;
DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
@@ -29733,8 +33704,9 @@ DUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, d
*/
DUK_SNPRINTF(yearstr,
sizeof(yearstr),
- (parts[DUK_DATE_IDX_YEAR] >= 0 && parts[DUK_DATE_IDX_YEAR] <= 9999) ? "%04ld" :
- ((parts[DUK_DATE_IDX_YEAR] >= 0) ? "+%06ld" : "%07ld"),
+ (parts[DUK_DATE_IDX_YEAR] >= 0 && parts[DUK_DATE_IDX_YEAR] <= 9999) ?
+ "%04ld" :
+ ((parts[DUK_DATE_IDX_YEAR] >= 0) ? "+%06ld" : "%07ld"),
(long) parts[DUK_DATE_IDX_YEAR]);
yearstr[sizeof(yearstr) - 1] = (char) 0;
@@ -29755,8 +33727,9 @@ DUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, d
tmp = tmp / 60;
arg_hours = tmp / 60;
arg_minutes = tmp % 60;
- DUK_ASSERT(arg_hours <= 24); /* Even less is actually guaranteed for a valid tzoffset. */
- arg_hours = arg_hours & 0x3f; /* For [0,24] this is a no-op, but fixes GCC 7 warning, see https://github.com/svaarala/duktape/issues/1602. */
+ DUK_ASSERT(arg_hours <= 24); /* Even less is actually guaranteed for a valid tzoffset. */
+ arg_hours = arg_hours & 0x3f; /* For [0,24] this is a no-op, but fixes GCC 7 warning, see
+ https://github.com/svaarala/duktape/issues/1602. */
DUK_SNPRINTF(tzstr, sizeof(tzstr), fmt, (int) arg_hours, (int) arg_minutes);
tzstr[sizeof(tzstr) - 1] = (char) 0;
@@ -29769,18 +33742,31 @@ DUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, d
* is portable.
*/
if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
- DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d%c%02d:%02d:%02d.%03d%s",
- (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY], (int) sep,
- (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
- (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], (const char *) tzstr);
+ DUK_SPRINTF((char *) out_buf,
+ "%s-%02d-%02d%c%02d:%02d:%02d.%03d%s",
+ (const char *) yearstr,
+ (int) parts[DUK_DATE_IDX_MONTH],
+ (int) parts[DUK_DATE_IDX_DAY],
+ (int) sep,
+ (int) parts[DUK_DATE_IDX_HOUR],
+ (int) parts[DUK_DATE_IDX_MINUTE],
+ (int) parts[DUK_DATE_IDX_SECOND],
+ (int) parts[DUK_DATE_IDX_MILLISECOND],
+ (const char *) tzstr);
} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
- DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d",
- (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY]);
+ DUK_SPRINTF((char *) out_buf,
+ "%s-%02d-%02d",
+ (const char *) yearstr,
+ (int) parts[DUK_DATE_IDX_MONTH],
+ (int) parts[DUK_DATE_IDX_DAY]);
} else {
DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
- DUK_SPRINTF((char *) out_buf, "%02d:%02d:%02d.%03d%s",
- (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
- (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND],
+ DUK_SPRINTF((char *) out_buf,
+ "%02d:%02d:%02d.%03d%s",
+ (int) parts[DUK_DATE_IDX_HOUR],
+ (int) parts[DUK_DATE_IDX_MINUTE],
+ (int) parts[DUK_DATE_IDX_SECOND],
+ (int) parts[DUK_DATE_IDX_MILLISECOND],
(const char *) tzstr);
}
}
@@ -29792,11 +33778,11 @@ DUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, d
DUK_LOCAL duk_ret_t duk__to_string_helper(duk_hthread *thr, duk_small_uint_t flags) {
duk_double_t d;
duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
- duk_int_t tzoffset; /* seconds, doesn't fit into 16 bits */
+ duk_int_t tzoffset; /* seconds, doesn't fit into 16 bits */
duk_bool_t rc;
duk_uint8_t buf[DUK_BI_DATE_ISO8601_BUFSIZE];
- DUK_UNREF(rc); /* unreferenced with some options */
+ DUK_UNREF(rc); /* unreferenced with some options */
d = duk__push_this_get_timeval_tzoffset(thr, flags, &tzoffset);
if (DUK_ISNAN(d)) {
@@ -29848,9 +33834,9 @@ DUK_LOCAL duk_ret_t duk__to_string_helper(duk_hthread *thr, duk_small_uint_t fla
DUK_LOCAL duk_ret_t duk__get_part_helper(duk_hthread *thr, duk_small_uint_t flags_and_idx) {
duk_double_t d;
duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
- duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK_DATE_FLAG_VALUE_SHIFT); /* unpack args */
+ duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK_DATE_FLAG_VALUE_SHIFT); /* unpack args */
- DUK_ASSERT_DISABLE(idx_part >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(idx_part >= 0); /* unsigned */
DUK_ASSERT(idx_part < DUK_DATE_IDX_NUM_PARTS);
d = duk__push_this_get_timeval(thr, flags_and_idx);
@@ -29860,7 +33846,7 @@ DUK_LOCAL duk_ret_t duk__get_part_helper(duk_hthread *thr, duk_small_uint_t flag
}
DUK_ASSERT(DUK_ISFINITE(d));
- duk_bi_date_timeval_to_parts(d, parts, NULL, flags_and_idx); /* no need to mask idx portion */
+ duk_bi_date_timeval_to_parts(d, parts, NULL, flags_and_idx); /* no need to mask idx portion */
/* Setter APIs detect special year numbers (0...99) and apply a +1900
* only in certain cases. The legacy getYear() getter applies -1900
@@ -29882,7 +33868,7 @@ DUK_LOCAL duk_ret_t duk__set_part_helper(duk_hthread *thr, duk_small_uint_t flag
duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
duk_idx_t nargs;
- duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK_DATE_FLAG_VALUE_SHIFT); /* unpack args */
+ duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK_DATE_FLAG_VALUE_SHIFT); /* unpack args */
duk_small_uint_t idx_first, idx;
duk_small_uint_t i;
@@ -29929,7 +33915,7 @@ DUK_LOCAL duk_ret_t duk__set_part_helper(duk_hthread *thr, duk_small_uint_t flag
DUK_ASSERT(maxnargs >= 1 && maxnargs <= 3);
idx_first = DUK_DATE_IDX_DAY - (maxnargs - 1);
}
- DUK_ASSERT_DISABLE(idx_first >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(idx_first >= 0); /* unsigned */
DUK_ASSERT(idx_first < DUK_DATE_IDX_NUM_PARTS);
for (i = 0; i < maxnargs; i++) {
@@ -29938,7 +33924,7 @@ DUK_LOCAL duk_ret_t duk__set_part_helper(duk_hthread *thr, duk_small_uint_t flag
break;
}
idx = idx_first + i;
- DUK_ASSERT_DISABLE(idx >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(idx >= 0); /* unsigned */
DUK_ASSERT(idx < DUK_DATE_IDX_NUM_PARTS);
if (idx == DUK_DATE_IDX_YEAR && (flags_and_maxnargs & DUK_DATE_FLAG_YEAR_FIXUP)) {
@@ -29990,7 +33976,7 @@ DUK_LOCAL void duk__twodigit_year_fixup(duk_hthread *thr, duk_idx_t idx_val) {
}
duk_dup(thr, idx_val);
duk_to_int(thr, -1);
- d = duk_get_number(thr, -1); /* get as double to handle huge numbers correctly */
+ d = duk_get_number(thr, -1); /* get as double to handle huge numbers correctly */
if (d >= 0.0 && d <= 99.0) {
d += 1900.0;
duk_push_number(thr, d);
@@ -30038,10 +34024,14 @@ DUK_LOCAL void duk__set_parts_from_args(duk_hthread *thr, duk_double_t *dparts,
}
DUK_DDD(DUK_DDDPRINT("parts from args -> %lf %lf %lf %lf %lf %lf %lf %lf",
- (double) dparts[0], (double) dparts[1],
- (double) dparts[2], (double) dparts[3],
- (double) dparts[4], (double) dparts[5],
- (double) dparts[6], (double) dparts[7]));
+ (double) dparts[0],
+ (double) dparts[1],
+ (double) dparts[2],
+ (double) dparts[3],
+ (double) dparts[4],
+ (double) dparts[5],
+ (double) dparts[6],
+ (double) dparts[7]));
}
/*
@@ -30197,9 +34187,8 @@ DUK_INTERNAL duk_ret_t duk_bi_date_constructor(duk_hthread *thr) {
DUK_DDD(DUK_DDDPRINT("Date constructor, nargs=%ld, is_cons=%ld", (long) nargs, (long) is_cons));
(void) duk_push_object_helper(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATE),
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATE),
DUK_BIDX_DATE_PROTOTYPE);
/* Unlike most built-ins, the internal [[PrimitiveValue]] of a Date
@@ -30221,9 +34210,9 @@ DUK_INTERNAL duk_ret_t duk_bi_date_constructor(duk_hthread *thr) {
str = duk_get_string_notsymbol(thr, 0);
if (str) {
duk__parse_string(thr, str);
- duk_replace(thr, 0); /* may be NaN */
+ duk_replace(thr, 0); /* may be NaN */
}
- d = duk__timeclip(duk_to_number(thr, 0)); /* symbols fail here */
+ d = duk__timeclip(duk_to_number(thr, 0)); /* symbols fail here */
duk_push_number(thr, d);
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
return 1;
@@ -30233,8 +34222,8 @@ DUK_INTERNAL duk_ret_t duk_bi_date_constructor(duk_hthread *thr) {
/* Parts are in local time, convert when setting. */
- (void) duk__set_this_timeval_from_dparts(thr, dparts, DUK_DATE_FLAG_LOCALTIME /*flags*/); /* -> [ ... this timeval ] */
- duk_pop(thr); /* -> [ ... this ] */
+ (void) duk__set_this_timeval_from_dparts(thr, dparts, DUK_DATE_FLAG_LOCALTIME /*flags*/); /* -> [ ... this timeval ] */
+ duk_pop(thr); /* -> [ ... this ] */
return 1;
}
@@ -30265,7 +34254,7 @@ DUK_INTERNAL duk_ret_t duk_bi_date_constructor_now(duk_hthread *thr) {
duk_double_t d;
d = duk_time_get_ecmascript_time_nofrac(thr);
- DUK_ASSERT(duk__timeclip(d) == d); /* TimeClip() should never be necessary */
+ DUK_ASSERT(duk_double_equals(duk__timeclip(d), d)); /* TimeClip() should never be necessary */
duk_push_number(thr, d);
return 1;
}
@@ -30292,7 +34281,7 @@ DUK_INTERNAL duk_ret_t duk_bi_date_constructor_now(duk_hthread *thr) {
* Notes:
*
* - Date.prototype.toGMTString() and Date.prototype.toUTCString() are
- * required to be the same Ecmascript function object (!), so it is
+ * required to be the same ECMAScript function object (!), so it is
* omitted from here.
*
* - Date.prototype.toUTCString(): E5.1 specification does not require a
@@ -30314,7 +34303,7 @@ DUK_INTERNAL duk_ret_t duk_bi_date_prototype_value_of(duk_hthread *thr) {
* as their behavior is identical.
*/
- duk_double_t d = duk__push_this_get_timeval(thr, 0 /*flags*/); /* -> [ this ] */
+ duk_double_t d = duk__push_this_get_timeval(thr, 0 /*flags*/); /* -> [ this ] */
DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
duk_push_number(thr, d);
return 1;
@@ -30340,7 +34329,7 @@ DUK_INTERNAL duk_ret_t duk_bi_date_prototype_to_json(duk_hthread *thr) {
duk_pop(thr);
duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_ISO_STRING);
- duk_dup_m2(thr); /* -> [ O toIsoString O ] */
+ duk_dup_m2(thr); /* -> [ O toIsoString O ] */
duk_call_method(thr, 0);
return 1;
}
@@ -30483,12 +34472,50 @@ DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_time(duk_hthread *thr) {
d = duk__timeclip(duk_to_number(thr, 0));
duk_push_number(thr, d);
duk_dup_top(thr);
- duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE); /* -> [ timeval this timeval ] */
+ /* Must force write because .setTime() must work even when
+ * the Date instance is frozen.
+ */
+ duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
+ /* -> [ timeval this timeval ] */
return 1;
}
-#endif /* DUK_USE_DATE_BUILTIN */
+/*
+ * Misc.
+ */
+
+#if defined(DUK_USE_SYMBOL_BUILTIN)
+DUK_INTERNAL duk_ret_t duk_bi_date_prototype_toprimitive(duk_hthread *thr) {
+ duk_size_t hintlen;
+ const char *hintstr;
+ duk_int_t hint;
+
+ /* Invokes OrdinaryToPrimitive() with suitable hint. Note that the
+ * method is generic, and works on non-Date arguments too.
+ *
+ * https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype-@@toprimitive
+ */
+
+ duk_push_this(thr);
+ duk_require_object(thr, -1);
+ DUK_ASSERT_TOP(thr, 2);
+
+ hintstr = duk_require_lstring(thr, 0, &hintlen);
+ if ((hintlen == 6 && DUK_STRCMP(hintstr, "string") == 0) || (hintlen == 7 && DUK_STRCMP(hintstr, "default") == 0)) {
+ hint = DUK_HINT_STRING;
+ } else if (hintlen == 6 && DUK_STRCMP(hintstr, "number") == 0) {
+ hint = DUK_HINT_NUMBER;
+ } else {
+ DUK_DCERROR_TYPE_INVALID_ARGS(thr);
+ }
+
+ duk_to_primitive_ordinary(thr, -1, hint);
+ return 1;
+}
+#endif /* DUK_USE_SYMBOL_BUILTIN */
+
+#endif /* DUK_USE_DATE_BUILTIN */
/* automatic undefs */
#undef DUK__CF_ACCEPT
@@ -30551,11 +34578,11 @@ DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_time(duk_hthread *thr) {
/* Buffer sizes for some UNIX calls. Larger than strictly necessary
* to avoid Valgrind errors.
*/
-#define DUK__STRPTIME_BUF_SIZE 64
-#define DUK__STRFTIME_BUF_SIZE 64
+#define DUK__STRPTIME_BUF_SIZE 64
+#define DUK__STRFTIME_BUF_SIZE 64
#if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
-/* Get current Ecmascript time (= UNIX/Posix time, but in milliseconds). */
+/* Get current ECMAScript time (= UNIX/Posix time, but in milliseconds). */
DUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(void) {
struct timeval tv;
duk_double_t d;
@@ -30566,12 +34593,11 @@ DUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(void) {
}
/* As of Duktape 2.2.0 allow fractions. */
- d = ((duk_double_t) tv.tv_sec) * 1000.0 +
- ((duk_double_t) tv.tv_usec) / 1000.0;
+ d = ((duk_double_t) tv.tv_sec) * 1000.0 + ((duk_double_t) tv.tv_usec) / 1000.0;
return d;
}
-#endif /* DUK_USE_DATE_NOW_GETTIMEOFDAY */
+#endif /* DUK_USE_DATE_NOW_GETTIMEOFDAY */
#if defined(DUK_USE_DATE_NOW_TIME)
/* Not a very good provider: only full seconds are available. */
@@ -30585,7 +34611,7 @@ DUK_INTERNAL duk_double_t duk_bi_date_get_now_time(void) {
}
return ((duk_double_t) t) * 1000.0;
}
-#endif /* DUK_USE_DATE_NOW_TIME */
+#endif /* DUK_USE_DATE_NOW_TIME */
#if defined(DUK_USE_DATE_TZO_GMTIME) || defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S)
/* Get local time offset (in seconds) for a certain (UTC) instant 'd'. */
@@ -30603,7 +34629,7 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) {
return 0;
}
- /* If not within Ecmascript range, some integer time calculations
+ /* If not within ECMAScript range, some integer time calculations
* won't work correctly (and some asserts will fail), so bail out
* if so. This fixes test-bug-date-insane-setyear.js. There is
* a +/- 24h leeway in this range check to avoid a test262 corner
@@ -30654,10 +34680,10 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) {
* Since we rely on the platform APIs for conversions between local
* time and UTC, we can't guarantee the above. Rather, if the platform
* has historical DST rules they will be applied. This seems to be the
- * general preferred direction in Ecmascript standardization (or at least
+ * general preferred direction in ECMAScript standardization (or at least
* implementations) anyway, and even the equivalent year mapping should
* be disabled if the platform is known to handle DST properly for the
- * full Ecmascript range.
+ * full ECMAScript range.
*
* The following has useful discussion and links:
*
@@ -30668,11 +34694,11 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) {
DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= 1970 && parts[DUK_DATE_IDX_YEAR] <= 2038);
d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
- DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0); /* unsigned 31-bit range */
+ DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0); /* unsigned 31-bit range */
t = (time_t) (d / 1000.0);
DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t));
- DUK_MEMZERO((void *) tms, sizeof(struct tm) * 2);
+ duk_memzero((void *) tms, sizeof(struct tm) * 2);
#if defined(DUK_USE_DATE_TZO_GMTIME_R)
(void) gmtime_r(&t, &tms[0]);
@@ -30682,22 +34708,34 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) {
(void) localtime_s(&t, &tms[1]);
#elif defined(DUK_USE_DATE_TZO_GMTIME)
tm_ptr = gmtime(&t);
- DUK_MEMCPY((void *) &tms[0], tm_ptr, sizeof(struct tm));
+ duk_memcpy((void *) &tms[0], tm_ptr, sizeof(struct tm));
tm_ptr = localtime(&t);
- DUK_MEMCPY((void *) &tms[1], tm_ptr, sizeof(struct tm));
+ duk_memcpy((void *) &tms[1], tm_ptr, sizeof(struct tm));
#else
#error internal error
#endif
DUK_DDD(DUK_DDDPRINT("gmtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
"wday:%ld,yday:%ld,isdst:%ld}",
- (long) tms[0].tm_sec, (long) tms[0].tm_min, (long) tms[0].tm_hour,
- (long) tms[0].tm_mday, (long) tms[0].tm_mon, (long) tms[0].tm_year,
- (long) tms[0].tm_wday, (long) tms[0].tm_yday, (long) tms[0].tm_isdst));
+ (long) tms[0].tm_sec,
+ (long) tms[0].tm_min,
+ (long) tms[0].tm_hour,
+ (long) tms[0].tm_mday,
+ (long) tms[0].tm_mon,
+ (long) tms[0].tm_year,
+ (long) tms[0].tm_wday,
+ (long) tms[0].tm_yday,
+ (long) tms[0].tm_isdst));
DUK_DDD(DUK_DDDPRINT("localtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
"wday:%ld,yday:%ld,isdst:%ld}",
- (long) tms[1].tm_sec, (long) tms[1].tm_min, (long) tms[1].tm_hour,
- (long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year,
- (long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst));
+ (long) tms[1].tm_sec,
+ (long) tms[1].tm_min,
+ (long) tms[1].tm_hour,
+ (long) tms[1].tm_mday,
+ (long) tms[1].tm_mon,
+ (long) tms[1].tm_year,
+ (long) tms[1].tm_wday,
+ (long) tms[1].tm_yday,
+ (long) tms[1].tm_isdst));
/* tm_isdst is both an input and an output to mktime(), use 0 to
* avoid DST handling in mktime():
@@ -30706,8 +34744,8 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) {
*/
tms[0].tm_isdst = 0;
tms[1].tm_isdst = 0;
- t1 = mktime(&tms[0]); /* UTC */
- t2 = mktime(&tms[1]); /* local */
+ t1 = mktime(&tms[0]); /* UTC */
+ t2 = mktime(&tms[1]); /* local */
if (t1 == (time_t) -1 || t2 == (time_t) -1) {
/* This check used to be for (t < 0) but on some platforms
* time_t is unsigned and apparently the proper way to detect
@@ -30730,12 +34768,12 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) {
#endif
return (duk_int_t) difftime(t2, t1);
- mktime_error:
+mktime_error:
/* XXX: return something more useful, so that caller can throw? */
DUK_D(DUK_DPRINT("mktime() failed, d=%lf", (double) d));
return 0;
}
-#endif /* DUK_USE_DATE_TZO_GMTIME */
+#endif /* DUK_USE_DATE_TZO_GMTIME */
#if defined(DUK_USE_DATE_PRS_STRPTIME)
DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, const char *str) {
@@ -30745,20 +34783,26 @@ DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, cons
/* Copy to buffer with slack to avoid Valgrind gripes from strptime. */
DUK_ASSERT(str != NULL);
- DUK_MEMZERO(buf, sizeof(buf)); /* valgrind whine without this */
+ duk_memzero(buf, sizeof(buf)); /* valgrind whine without this */
DUK_SNPRINTF(buf, sizeof(buf), "%s", (const char *) str);
buf[sizeof(buf) - 1] = (char) 0;
DUK_DDD(DUK_DDDPRINT("parsing: '%s'", (const char *) buf));
- DUK_MEMZERO(&tm, sizeof(tm));
+ duk_memzero(&tm, sizeof(tm));
if (strptime((const char *) buf, "%c", &tm) != NULL) {
DUK_DDD(DUK_DDDPRINT("before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
"wday:%ld,yday:%ld,isdst:%ld}",
- (long) tm.tm_sec, (long) tm.tm_min, (long) tm.tm_hour,
- (long) tm.tm_mday, (long) tm.tm_mon, (long) tm.tm_year,
- (long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst));
- tm.tm_isdst = -1; /* negative: dst info not available */
+ (long) tm.tm_sec,
+ (long) tm.tm_min,
+ (long) tm.tm_hour,
+ (long) tm.tm_mday,
+ (long) tm.tm_mon,
+ (long) tm.tm_year,
+ (long) tm.tm_wday,
+ (long) tm.tm_yday,
+ (long) tm.tm_isdst));
+ tm.tm_isdst = -1; /* negative: dst info not available */
t = mktime(&tm);
DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
@@ -30770,7 +34814,7 @@ DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, cons
return 0;
}
-#endif /* DUK_USE_DATE_PRS_STRPTIME */
+#endif /* DUK_USE_DATE_PRS_STRPTIME */
#if defined(DUK_USE_DATE_PRS_GETDATE)
DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const char *str) {
@@ -30782,7 +34826,7 @@ DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const
* convenient for an embeddable interpreter.
*/
- DUK_MEMZERO(&tm, sizeof(struct tm));
+ duk_memzero(&tm, sizeof(struct tm));
rc = (duk_small_int_t) getdate_r(str, &tm);
DUK_DDD(DUK_DDDPRINT("getdate_r() -> %ld", (long) rc));
@@ -30797,44 +34841,46 @@ DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const
return 0;
}
-#endif /* DUK_USE_DATE_PRS_GETDATE */
+#endif /* DUK_USE_DATE_PRS_GETDATE */
#if defined(DUK_USE_DATE_FMT_STRFTIME)
-DUK_INTERNAL duk_bool_t duk_bi_date_format_parts_strftime(duk_hthread *thr, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags) {
+DUK_INTERNAL duk_bool_t duk_bi_date_format_parts_strftime(duk_hthread *thr,
+ duk_int_t *parts,
+ duk_int_t tzoffset,
+ duk_small_uint_t flags) {
char buf[DUK__STRFTIME_BUF_SIZE];
struct tm tm;
const char *fmt;
DUK_UNREF(tzoffset);
- /* If the platform doesn't support the entire Ecmascript range, we need
+ /* If the platform doesn't support the entire ECMAScript range, we need
* to return 0 so that the caller can fall back to the default formatter.
*
- * For now, assume that if time_t is 8 bytes or more, the whole Ecmascript
+ * For now, assume that if time_t is 8 bytes or more, the whole ECMAScript
* range is supported. For smaller time_t values (4 bytes in practice),
* assumes that the signed 32-bit range is supported.
*
* XXX: detect this more correctly per platform. The size of time_t is
* probably not an accurate guarantee of strftime() supporting or not
- * supporting a large time range (the full Ecmascript range).
+ * supporting a large time range (the full ECMAScript range).
*/
- if (sizeof(time_t) < 8 &&
- (parts[DUK_DATE_IDX_YEAR] < 1970 || parts[DUK_DATE_IDX_YEAR] > 2037)) {
+ if (sizeof(time_t) < 8 && (parts[DUK_DATE_IDX_YEAR] < 1970 || parts[DUK_DATE_IDX_YEAR] > 2037)) {
/* be paranoid for 32-bit time values (even avoiding negative ones) */
return 0;
}
- DUK_MEMZERO(&tm, sizeof(tm));
+ duk_memzero(&tm, sizeof(tm));
tm.tm_sec = parts[DUK_DATE_IDX_SECOND];
tm.tm_min = parts[DUK_DATE_IDX_MINUTE];
tm.tm_hour = parts[DUK_DATE_IDX_HOUR];
- tm.tm_mday = parts[DUK_DATE_IDX_DAY]; /* already one-based */
- tm.tm_mon = parts[DUK_DATE_IDX_MONTH] - 1; /* one-based -> zero-based */
+ tm.tm_mday = parts[DUK_DATE_IDX_DAY]; /* already one-based */
+ tm.tm_mon = parts[DUK_DATE_IDX_MONTH] - 1; /* one-based -> zero-based */
tm.tm_year = parts[DUK_DATE_IDX_YEAR] - 1900;
tm.tm_wday = parts[DUK_DATE_IDX_WEEKDAY];
tm.tm_isdst = 0;
- DUK_MEMZERO(buf, sizeof(buf));
+ duk_memzero(buf, sizeof(buf));
if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
fmt = "%c";
} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
@@ -30849,7 +34895,7 @@ DUK_INTERNAL duk_bool_t duk_bi_date_format_parts_strftime(duk_hthread *thr, duk_
duk_push_string(thr, buf);
return 1;
}
-#endif /* DUK_USE_DATE_FMT_STRFTIME */
+#endif /* DUK_USE_DATE_FMT_STRFTIME */
#if defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)
DUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_clock_gettime(void) {
@@ -30892,23 +34938,25 @@ DUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEG
}
}
+#if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
DUK_LOCAL void duk__convert_filetime_to_ularge(const FILETIME *ft, ULARGE_INTEGER *res) {
res->LowPart = ft->dwLowDateTime;
res->HighPart = ft->dwHighDateTime;
}
+#endif /* DUK_USE_DATE_NOW_WINDOWS_SUBMS */
DUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) {
- DUK_MEMZERO((void *) st, sizeof(*st));
+ duk_memzero((void *) st, sizeof(*st));
st->wYear = 1970;
st->wMonth = 1;
- st->wDayOfWeek = 4; /* not sure whether or not needed; Thursday */
+ st->wDayOfWeek = 4; /* not sure whether or not needed; Thursday */
st->wDay = 1;
DUK_ASSERT(st->wHour == 0);
DUK_ASSERT(st->wMinute == 0);
DUK_ASSERT(st->wSecond == 0);
DUK_ASSERT(st->wMilliseconds == 0);
}
-#endif /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */
+#endif /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */
#if defined(DUK_USE_DATE_NOW_WINDOWS)
DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows(void) {
@@ -30930,7 +34978,7 @@ DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows(void) {
*/
return (duk_double_t) ((LONGLONG) tmp1.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000.0;
}
-#endif /* DUK_USE_DATE_NOW_WINDOWS */
+#endif /* DUK_USE_DATE_NOW_WINDOWS */
#if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows_subms(void) {
@@ -30952,7 +35000,7 @@ DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows_subms(void) {
*/
return (duk_double_t) ((LONGLONG) tmp1.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000.0;
}
-#endif /* DUK_USE_DATE_NOW_WINDOWS */
+#endif /* DUK_USE_DATE_NOW_WINDOWS */
#if defined(DUK_USE_DATE_TZO_WINDOWS)
DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) {
@@ -30966,7 +35014,7 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) {
/* XXX: handling of timestamps outside Windows supported range.
* How does Windows deal with dates before 1600? Does windows
- * support all Ecmascript years (like -200000 and +200000)?
+ * support all ECMAScript years (like -200000 and +200000)?
* Should equivalent year mapping be used here too? If so, use
* a shared helper (currently integrated into timeval-to-parts).
*/
@@ -30977,12 +35025,15 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) {
duk__set_systime_jan1970(&st1);
duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
- tmp2.QuadPart = (ULONGLONG) (d * 10000.0); /* millisec -> 100ns units since jan 1, 1970 */
- tmp2.QuadPart += tmp1.QuadPart; /* input 'd' in Windows UTC, 100ns units */
+ tmp2.QuadPart = (ULONGLONG) (d * 10000.0); /* millisec -> 100ns units since jan 1, 1970 */
+ tmp2.QuadPart += tmp1.QuadPart; /* input 'd' in Windows UTC, 100ns units */
ft1.dwLowDateTime = tmp2.LowPart;
ft1.dwHighDateTime = tmp2.HighPart;
- FileTimeToSystemTime((const FILETIME *) &ft1, &st2);
+ if (FileTimeToSystemTime((const FILETIME *) &ft1, &st2) == 0) {
+ DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0"));
+ return 0;
+ }
if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) {
DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0"));
return 0;
@@ -30990,9 +35041,9 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) {
duk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3);
/* Positive if local time ahead of UTC. */
- return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / DUK_I64_CONSTANT(10000000)); /* seconds */
+ return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / DUK_I64_CONSTANT(10000000)); /* seconds */
}
-#endif /* DUK_USE_DATE_TZO_WINDOWS */
+#endif /* DUK_USE_DATE_TZO_WINDOWS */
#if defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST)
DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d) {
@@ -31017,22 +35068,29 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_
ft1.dwLowDateTime = tmp1.LowPart;
ft1.dwHighDateTime = tmp1.HighPart;
- FileTimeToLocalFileTime((const FILETIME *) &ft1, &ft2);
-
- FileTimeToSystemTime((const FILETIME *) &ft2, &st2);
+ if (FileTimeToLocalFileTime((const FILETIME *) &ft1, &ft2) == 0) {
+ DUK_D(DUK_DPRINT("FileTimeToLocalFileTime() failed, return tzoffset 0"));
+ return 0;
+ }
+ if (FileTimeToSystemTime((const FILETIME *) &ft2, &st2) == 0) {
+ DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0"));
+ return 0;
+ }
duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
- return (duk_int_t) (((LONGLONG) tmp2.QuadPart - (LONGLONG) tmp1.QuadPart) / DUK_I64_CONSTANT(10000000)); /* seconds */
+ return (duk_int_t) (((LONGLONG) tmp2.QuadPart - (LONGLONG) tmp1.QuadPart) / DUK_I64_CONSTANT(10000000)); /* seconds */
}
-#endif /* DUK_USE_DATE_TZO_WINDOWS_NO_DST */
+#endif /* DUK_USE_DATE_TZO_WINDOWS_NO_DST */
#if defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC)
DUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void) {
LARGE_INTEGER count, freq;
/* There are legacy issues with QueryPerformanceCounter():
- * - Potential jumps: https://support.microsoft.com/en-us/help/274323/performance-counter-value-may-unexpectedly-leap-forward
- * - Differences between cores (XP): https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx#qpc_support_in_windows_versions
+ * - Potential jumps:
+ * https://support.microsoft.com/en-us/help/274323/performance-counter-value-may-unexpectedly-leap-forward
+ * - Differences between cores (XP):
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx#qpc_support_in_windows_versions
*
* We avoid these by enabling QPC by default only for Vista or later.
*/
@@ -31049,13 +35107,13 @@ DUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void) {
return 0.0;
}
}
-#endif /* DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC */
+#endif /* DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC */
/*
* Duktape built-ins
*
* Size optimization note: it might seem that vararg multipurpose functions
* like fin(), enc(), and dec() are not very size optimal, but using a single
- * user-visible Ecmascript function saves a lot of run-time footprint; each
+ * user-visible ECMAScript function saves a lot of run-time footprint; each
* Function instance takes >100 bytes. Using a shared native helper and a
* 'magic' value won't save much if there are multiple Function instances
* anyway.
@@ -31112,7 +35170,7 @@ DUK_INTERNAL duk_ret_t duk_bi_duktape_object_fin(duk_hthread *thr) {
return 1;
}
}
-#endif /* DUK_USE_FINALIZER_SUPPORT */
+#endif /* DUK_USE_FINALIZER_SUPPORT */
DUK_INTERNAL duk_ret_t duk_bi_duktape_object_enc(duk_hthread *thr) {
duk_hstring *h_str;
@@ -31122,7 +35180,7 @@ DUK_INTERNAL duk_ret_t duk_bi_duktape_object_enc(duk_hthread *thr) {
* non-existent optional parameters.
*/
- h_str = duk_require_hstring(thr, 0); /* Could reject symbols, but no point: won't match comparisons. */
+ h_str = duk_require_hstring(thr, 0); /* Could reject symbols, but no point: won't match comparisons. */
duk_require_valid_index(thr, 1);
if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
@@ -31139,9 +35197,8 @@ DUK_INTERNAL duk_ret_t duk_bi_duktape_object_enc(duk_hthread *thr) {
1 /*idx_value*/,
2 /*idx_replacer*/,
3 /*idx_space*/,
- DUK_JSON_FLAG_EXT_CUSTOM |
- DUK_JSON_FLAG_ASCII_ONLY |
- DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
+ DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_ASCII_ONLY |
+ DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
#endif
#if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
@@ -31149,8 +35206,7 @@ DUK_INTERNAL duk_ret_t duk_bi_duktape_object_enc(duk_hthread *thr) {
1 /*idx_value*/,
2 /*idx_replacer*/,
3 /*idx_space*/,
- DUK_JSON_FLAG_EXT_COMPATIBLE |
- DUK_JSON_FLAG_ASCII_ONLY /*flags*/);
+ DUK_JSON_FLAG_EXT_COMPATIBLE | DUK_JSON_FLAG_ASCII_ONLY /*flags*/);
#endif
} else {
DUK_DCERROR_TYPE_INVALID_ARGS(thr);
@@ -31166,7 +35222,7 @@ DUK_INTERNAL duk_ret_t duk_bi_duktape_object_dec(duk_hthread *thr) {
* non-existent optional parameters.
*/
- h_str = duk_require_hstring(thr, 0); /* Could reject symbols, but no point: won't match comparisons */
+ h_str = duk_require_hstring(thr, 0); /* Could reject symbols, but no point: won't match comparisons */
duk_require_valid_index(thr, 1);
if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
@@ -31179,17 +35235,11 @@ DUK_INTERNAL duk_ret_t duk_bi_duktape_object_dec(duk_hthread *thr) {
DUK_ASSERT_TOP(thr, 2);
#if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
- duk_bi_json_parse_helper(thr,
- 1 /*idx_value*/,
- 2 /*idx_replacer*/,
- DUK_JSON_FLAG_EXT_CUSTOM /*flags*/);
+ duk_bi_json_parse_helper(thr, 1 /*idx_value*/, 2 /*idx_replacer*/, DUK_JSON_FLAG_EXT_CUSTOM /*flags*/);
#endif
#if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
- duk_bi_json_parse_helper(thr,
- 1 /*idx_value*/,
- 2 /*idx_replacer*/,
- DUK_JSON_FLAG_EXT_COMPATIBLE /*flags*/);
+ duk_bi_json_parse_helper(thr, 1 /*idx_value*/, 2 /*idx_replacer*/, DUK_JSON_FLAG_EXT_COMPATIBLE /*flags*/);
#endif
} else {
DUK_DCERROR_TYPE_INVALID_ARGS(thr);
@@ -31204,10 +35254,10 @@ DUK_INTERNAL duk_ret_t duk_bi_duktape_object_dec(duk_hthread *thr) {
DUK_INTERNAL duk_ret_t duk_bi_duktape_object_compact(duk_hthread *thr) {
DUK_ASSERT_TOP(thr, 1);
duk_compact(thr, 0);
- return 1; /* return the argument object */
+ return 1; /* return the argument object */
}
-#endif /* DUK_USE_DUKTAPE_BUILTIN */
+#endif /* DUK_USE_DUKTAPE_BUILTIN */
/*
* WHATWG Encoding API built-ins
*
@@ -31222,17 +35272,17 @@ DUK_INTERNAL duk_ret_t duk_bi_duktape_object_compact(duk_hthread *thr) {
*/
typedef struct {
- duk_uint8_t *out; /* where to write next byte(s) */
- duk_codepoint_t lead; /* lead surrogate */
+ duk_uint8_t *out; /* where to write next byte(s) */
+ duk_codepoint_t lead; /* lead surrogate */
} duk__encode_context;
typedef struct {
/* UTF-8 decoding state */
- duk_codepoint_t codepoint; /* built up incrementally */
- duk_uint8_t upper; /* max value of next byte (decode error otherwise) */
- duk_uint8_t lower; /* min value of next byte (ditto) */
- duk_uint8_t needed; /* how many more bytes we need */
- duk_uint8_t bom_handled; /* BOM seen or no longer expected */
+ duk_codepoint_t codepoint; /* built up incrementally */
+ duk_uint8_t upper; /* max value of next byte (decode error otherwise) */
+ duk_uint8_t lower; /* min value of next byte (ditto) */
+ duk_uint8_t needed; /* how many more bytes we need */
+ duk_uint8_t bom_handled; /* BOM seen or no longer expected */
/* Decoder configuration */
duk_uint8_t fatal;
@@ -31242,9 +35292,9 @@ typedef struct {
/* The signed duk_codepoint_t type is used to signal a decoded codepoint
* (>= 0) or various other states using negative values.
*/
-#define DUK__CP_CONTINUE (-1) /* continue to next byte, no completed codepoint */
-#define DUK__CP_ERROR (-2) /* decoding error */
-#define DUK__CP_RETRY (-3) /* decoding error; retry last byte */
+#define DUK__CP_CONTINUE (-1) /* continue to next byte, no completed codepoint */
+#define DUK__CP_ERROR (-2) /* decoding error */
+#define DUK__CP_RETRY (-3) /* decoding error; retry last byte */
/*
* Raw helpers for encoding/decoding
@@ -31331,7 +35381,7 @@ DUK_LOCAL duk_codepoint_t duk__utf8_decode_next(duk__decode_context *dec_ctx, du
} else {
/* got a codepoint */
duk_codepoint_t ret;
- DUK_ASSERT(dec_ctx->codepoint <= 0x10ffffL); /* Decoding rules guarantee. */
+ DUK_ASSERT(dec_ctx->codepoint <= 0x10ffffL); /* Decoding rules guarantee. */
ret = dec_ctx->codepoint;
dec_ctx->codepoint = 0x0000L;
dec_ctx->needed = 0;
@@ -31387,7 +35437,8 @@ DUK_LOCAL void duk__utf8_encode_char(void *udata, duk_codepoint_t codepoint) {
} else {
/* low surrogate */
if (enc_ctx->lead != 0x0000L) {
- codepoint = (duk_codepoint_t) (0x010000L + ((enc_ctx->lead - 0xd800L) << 10) + (codepoint - 0xdc00L));
+ codepoint =
+ (duk_codepoint_t) (0x010000L + ((enc_ctx->lead - 0xd800L) << 10) + (codepoint - 0xdc00L));
enc_ctx->lead = 0x0000L;
} else {
/* unpaired low surrogate */
@@ -31408,7 +35459,7 @@ DUK_LOCAL void duk__utf8_encode_char(void *udata, duk_codepoint_t codepoint) {
*/
enc_ctx->out += duk_unicode_encode_xutf8((duk_ucodepoint_t) codepoint, enc_ctx->out);
}
-#endif /* DUK_USE_ENCODING_BUILTINS */
+#endif /* DUK_USE_ENCODING_BUILTINS */
/* Shared helper for buffer-to-string using a TextDecoder() compatible UTF-8
* decoder.
@@ -31437,19 +35488,16 @@ DUK_LOCAL duk_ret_t duk__decode_helper(duk_hthread *thr, duk__decode_context *de
duk_push_fixed_buffer_nozero(thr, 0);
duk_replace(thr, 0);
}
- (void) duk_require_buffer_data(thr, 0, &len); /* Need 'len', avoid pointer. */
+ (void) duk_require_buffer_data(thr, 0, &len); /* Need 'len', avoid pointer. */
- if (duk_check_type_mask(thr, 1, DUK_TYPE_MASK_UNDEFINED |
- DUK_TYPE_MASK_NULL |
- DUK_TYPE_MASK_NONE)) {
+ if (duk_check_type_mask(thr, 1, DUK_TYPE_MASK_UNDEFINED | DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_NONE)) {
/* Use defaults, treat missing value like undefined. */
} else {
- duk_require_type_mask(thr, 1, DUK_TYPE_MASK_UNDEFINED |
- DUK_TYPE_MASK_NULL |
- DUK_TYPE_MASK_LIGHTFUNC |
- DUK_TYPE_MASK_BUFFER |
- DUK_TYPE_MASK_OBJECT);
- if (duk_get_prop_string(thr, 1, "stream")) {
+ duk_require_type_mask(thr,
+ 1,
+ DUK_TYPE_MASK_UNDEFINED | DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_LIGHTFUNC |
+ DUK_TYPE_MASK_BUFFER | DUK_TYPE_MASK_OBJECT);
+ if (duk_get_prop_literal(thr, 1, "stream")) {
stream = duk_to_boolean(thr, -1);
}
}
@@ -31464,8 +35512,10 @@ DUK_LOCAL duk_ret_t duk__decode_helper(duk_hthread *thr, duk__decode_context *de
*/
if (len >= (DUK_HBUFFER_MAX_BYTELEN / 3) - 3) {
DUK_ERROR_TYPE(thr, DUK_STR_RESULT_TOO_LONG);
+ DUK_WO_NORETURN(return 0;);
}
- output = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, 3 + (3 * len)); /* used parts will be always manually written over */
+ output =
+ (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, 3 + (3 * len)); /* used parts will be always manually written over */
input = (const duk_uint8_t *) duk_get_buffer_data(thr, 0, &len_tmp);
DUK_ASSERT(input != NULL || len == 0);
@@ -31497,7 +35547,7 @@ DUK_LOCAL duk_ret_t duk__decode_helper(duk_hthread *thr, duk__decode_context *de
/* Decoding error with or without retry. */
DUK_ASSERT(codepoint == DUK__CP_ERROR || codepoint == DUK__CP_RETRY);
if (codepoint == DUK__CP_RETRY) {
- --in; /* retry last byte */
+ --in; /* retry last byte */
}
/* replacement mode: replace with U+FFFD */
codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
@@ -31530,7 +35580,7 @@ DUK_LOCAL duk_ret_t duk__decode_helper(duk_hthread *thr, duk__decode_context *de
DUK_ASSERT(out <= output + (3 + (3 * len)));
}
}
- duk__utf8_decode_init(dec_ctx); /* Initialize decoding state for potential reuse. */
+ duk__utf8_decode_init(dec_ctx); /* Initialize decoding state for potential reuse. */
}
/* Output buffer is fixed and thus stable even if there had been
@@ -31539,9 +35589,9 @@ DUK_LOCAL duk_ret_t duk__decode_helper(duk_hthread *thr, duk__decode_context *de
duk_push_lstring(thr, (const char *) output, (duk_size_t) (out - output));
return 1;
- fail_type:
+fail_type:
DUK_ERROR_TYPE(thr, DUK_STR_UTF8_DECODE_FAILED);
- DUK_UNREACHABLE();
+ DUK_WO_NORETURN(return 0;);
}
/*
@@ -31559,7 +35609,7 @@ DUK_INTERNAL duk_ret_t duk_bi_textencoder_constructor(duk_hthread *thr) {
}
DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_hthread *thr) {
- duk_push_string(thr, "utf-8");
+ duk_push_literal(thr, "utf-8");
return 1;
}
@@ -31581,6 +35631,7 @@ DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encode(duk_hthread *thr) {
len = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_input);
if (len >= DUK_HBUFFER_MAX_BYTELEN / 3) {
DUK_ERROR_TYPE(thr, DUK_STR_RESULT_TOO_LONG);
+ DUK_WO_NORETURN(return 0;);
}
}
@@ -31597,17 +35648,17 @@ DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encode(duk_hthread *thr) {
output = (duk_uint8_t *) duk_push_dynamic_buffer(thr, 3 * len);
if (len > 0) {
- DUK_ASSERT(duk_is_string(thr, 0)); /* True if len > 0. */
+ DUK_ASSERT(duk_is_string(thr, 0)); /* True if len > 0. */
/* XXX: duk_decode_string() is used to process the input
- * string. For standard Ecmascript strings, represented
+ * string. For standard ECMAScript strings, represented
* internally as CESU-8, this is fine. However, behavior
* beyond CESU-8 is not very strict: codepoints using an
* extended form of UTF-8 are also accepted, and invalid
* codepoint sequences (which are allowed in Duktape strings)
* are not handled as well as they could (e.g. invalid
* continuation bytes may mask following codepoints).
- * This is how Ecmascript code would also see such strings.
+ * This is how ECMAScript code would also see such strings.
* Maybe replace duk_decode_string() with an explicit strict
* CESU-8 decoder here?
*/
@@ -31635,7 +35686,7 @@ DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encode(duk_hthread *thr) {
/* Standard WHATWG output is a Uint8Array. Here the Uint8Array will
* be backed by a dynamic buffer which differs from e.g. Uint8Arrays
- * created as 'new Uint8Array(N)'. Ecmascript code won't see the
+ * created as 'new Uint8Array(N)'. ECMAScript code won't see the
* difference but C code will. When bufferobjects are not supported,
* returns a plain dynamic buffer.
*/
@@ -31657,10 +35708,10 @@ DUK_INTERNAL duk_ret_t duk_bi_textdecoder_constructor(duk_hthread *thr) {
duk_to_string(thr, 0);
}
if (!duk_is_null_or_undefined(thr, 1)) {
- if (duk_get_prop_string(thr, 1, "fatal")) {
+ if (duk_get_prop_literal(thr, 1, "fatal")) {
fatal = duk_to_boolean(thr, -1);
}
- if (duk_get_prop_string(thr, 1, "ignoreBOM")) {
+ if (duk_get_prop_literal(thr, 1, "ignoreBOM")) {
ignore_bom = duk_to_boolean(thr, -1);
}
}
@@ -31673,9 +35724,9 @@ DUK_INTERNAL duk_ret_t duk_bi_textdecoder_constructor(duk_hthread *thr) {
dec_ctx = (duk__decode_context *) duk_push_fixed_buffer(thr, sizeof(duk__decode_context));
dec_ctx->fatal = (duk_uint8_t) fatal;
dec_ctx->ignore_bom = (duk_uint8_t) ignore_bom;
- duk__utf8_decode_init(dec_ctx); /* Initializes remaining fields. */
+ duk__utf8_decode_init(dec_ctx); /* Initializes remaining fields. */
- duk_put_prop_string(thr, -2, DUK_INTERNAL_SYMBOL("Context"));
+ duk_put_prop_literal(thr, -2, DUK_INTERNAL_SYMBOL("Context"));
return 0;
}
@@ -31683,7 +35734,7 @@ DUK_INTERNAL duk_ret_t duk_bi_textdecoder_constructor(duk_hthread *thr) {
DUK_LOCAL duk__decode_context *duk__get_textdecoder_context(duk_hthread *thr) {
duk__decode_context *dec_ctx;
duk_push_this(thr);
- duk_get_prop_string(thr, -1, DUK_INTERNAL_SYMBOL("Context"));
+ duk_get_prop_literal(thr, -1, DUK_INTERNAL_SYMBOL("Context"));
dec_ctx = (duk__decode_context *) duk_require_buffer(thr, -1, NULL);
DUK_ASSERT(dec_ctx != NULL);
return dec_ctx;
@@ -31700,7 +35751,7 @@ DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_hthread *t
/* Encoding is now fixed, so _Context lookup is only needed to
* validate the 'this' binding (TypeError if not TextDecoder-like).
*/
- duk_push_string(thr, "utf-8");
+ duk_push_literal(thr, "utf-8");
break;
case 1:
duk_push_boolean(thr, dec_ctx->fatal);
@@ -31719,7 +35770,7 @@ DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_hthread *thr) {
dec_ctx = duk__get_textdecoder_context(thr);
return duk__decode_helper(thr, dec_ctx);
}
-#endif /* DUK_USE_ENCODING_BUILTINS */
+#endif /* DUK_USE_ENCODING_BUILTINS */
/*
* Internal helper for Node.js Buffer
@@ -31733,8 +35784,8 @@ DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_hthread *thr) {
DUK_INTERNAL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_hthread *thr) {
duk__decode_context dec_ctx;
- dec_ctx.fatal = 0; /* use replacement chars */
- dec_ctx.ignore_bom = 1; /* ignore BOMs (matches Node.js Buffer .toString()) */
+ dec_ctx.fatal = 0; /* use replacement chars */
+ dec_ctx.ignore_bom = 1; /* ignore BOMs (matches Node.js Buffer .toString()) */
duk__utf8_decode_init(&dec_ctx);
return duk__decode_helper(thr, &dec_ctx);
@@ -31761,9 +35812,8 @@ DUK_INTERNAL duk_ret_t duk_bi_error_constructor_shared(duk_hthread *thr) {
duk_small_int_t bidx_prototype = duk_get_current_magic(thr);
/* same for both error and each subclass like TypeError */
- duk_uint_t flags_and_class = DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR);
+ duk_uint_t flags_and_class =
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR);
(void) duk_push_object_helper(thr, flags_and_class, bidx_prototype);
@@ -31772,7 +35822,7 @@ DUK_INTERNAL duk_ret_t duk_bi_error_constructor_shared(duk_hthread *thr) {
*/
if (!duk_is_undefined(thr, 0)) {
duk_to_string(thr, 0);
- duk_dup_0(thr); /* [ message error message ] */
+ duk_dup_0(thr); /* [ message error message ] */
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
}
@@ -31800,7 +35850,7 @@ DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_hthread *thr) {
duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME);
if (duk_is_undefined(thr, -1)) {
duk_pop(thr);
- duk_push_string(thr, "Error");
+ duk_push_literal(thr, "Error");
} else {
duk_to_string(thr, -1);
}
@@ -31830,8 +35880,8 @@ DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_hthread *thr) {
duk_pop(thr);
return 1;
}
- duk_push_string(thr, ": ");
- duk_insert(thr, -2); /* ... name ': ' message */
+ duk_push_literal(thr, ": ");
+ duk_insert(thr, -2); /* ... name ': ' message */
duk_concat(thr, 3);
return 1;
@@ -31854,15 +35904,15 @@ DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_hthread *thr) {
*/
/* constants arbitrary, chosen for small loads */
-#define DUK__OUTPUT_TYPE_TRACEBACK (-1)
-#define DUK__OUTPUT_TYPE_FILENAME 0
-#define DUK__OUTPUT_TYPE_LINENUMBER 1
+#define DUK__OUTPUT_TYPE_TRACEBACK (-1)
+#define DUK__OUTPUT_TYPE_FILENAME 0
+#define DUK__OUTPUT_TYPE_LINENUMBER 1
DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_hthread *thr, duk_small_int_t output_type) {
duk_idx_t idx_td;
- duk_small_int_t i; /* traceback depth fits into 16 bits */
- duk_small_int_t t; /* stack type fits into 16 bits */
- duk_small_int_t count_func = 0; /* traceback depth ensures fits into 16 bits */
+ duk_small_int_t i; /* traceback depth fits into 16 bits */
+ duk_small_int_t t; /* stack type fits into 16 bits */
+ duk_small_int_t count_func = 0; /* traceback depth ensures fits into 16 bits */
const char *str_tailcall = " tailcall";
const char *str_strict = " strict";
const char *str_construct = " construct";
@@ -31870,10 +35920,10 @@ DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_hthread *thr, duk_small_int_t o
const char *str_directeval = " directeval";
const char *str_empty = "";
- DUK_ASSERT_TOP(thr, 0); /* fixed arg count */
+ DUK_ASSERT_TOP(thr, 0); /* fixed arg count */
duk_push_this(thr);
- duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_TRACEDATA);
+ duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_TRACEDATA);
idx_td = duk_get_top_index(thr);
duk_push_hstring_stridx(thr, DUK_STRIDX_NEWLINE_4SPACE);
@@ -31885,7 +35935,7 @@ DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_hthread *thr, duk_small_int_t o
if (duk_check_type(thr, idx_td, DUK_TYPE_OBJECT)) {
/* Current tracedata contains 2 entries per callstack entry. */
- for (i = 0; ; i += 2) {
+ for (i = 0;; i += 2) {
duk_int_t pc;
duk_uint_t line;
duk_uint_t flags;
@@ -31899,13 +35949,13 @@ DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_hthread *thr, duk_small_int_t o
duk_get_prop_index(thr, idx_td, (duk_uarridx_t) i);
duk_get_prop_index(thr, idx_td, (duk_uarridx_t) (i + 1));
d = duk_to_number_m1(thr);
- pc = (duk_int_t) DUK_FMOD(d, DUK_DOUBLE_2TO32);
- flags = (duk_uint_t) DUK_FLOOR(d / DUK_DOUBLE_2TO32);
+ pc = duk_double_to_int_t(DUK_FMOD(d, DUK_DOUBLE_2TO32));
+ flags = duk_double_to_uint_t(DUK_FLOOR(d / DUK_DOUBLE_2TO32));
t = (duk_small_int_t) duk_get_type(thr, -2);
if (t == DUK_TYPE_OBJECT || t == DUK_TYPE_LIGHTFUNC) {
/*
- * Ecmascript/native function call or lightfunc call
+ * ECMAScript/native function call or lightfunc call
*/
count_func++;
@@ -31941,46 +35991,53 @@ DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_hthread *thr, duk_small_int_t o
/* XXX: Change 'anon' handling here too, to use empty string for anonymous functions? */
/* XXX: Could be improved by coercing to a readable duk_tval (especially string escaping) */
- h_name = duk_get_hstring_notsymbol(thr, -2); /* may be NULL */
+ h_name = duk_get_hstring_notsymbol(thr, -2); /* may be NULL */
funcname = (h_name == NULL || h_name == DUK_HTHREAD_STRING_EMPTY_STRING(thr)) ?
- "[anon]" : (const char *) DUK_HSTRING_GET_DATA(h_name);
+ "[anon]" :
+ (const char *) DUK_HSTRING_GET_DATA(h_name);
filename = duk_get_string_notsymbol(thr, -1);
filename = filename ? filename : "";
DUK_ASSERT(funcname != NULL);
DUK_ASSERT(filename != NULL);
- h_func = duk_get_hobject(thr, -4); /* NULL for lightfunc */
+ h_func = duk_get_hobject(thr, -4); /* NULL for lightfunc */
if (h_func == NULL) {
- duk_push_sprintf(thr, "at %s light%s%s%s%s%s",
- (const char *) funcname,
- (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
- (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
- (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
- (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
- (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
+ duk_push_sprintf(
+ thr,
+ "at %s light%s%s%s%s%s",
+ (const char *) funcname,
+ (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
+ (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
+ (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
+ (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
+ (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
} else if (DUK_HOBJECT_HAS_NATFUNC(h_func)) {
- duk_push_sprintf(thr, "at %s (%s) native%s%s%s%s%s",
- (const char *) funcname,
- (const char *) filename,
- (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
- (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
- (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
- (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
- (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
+ duk_push_sprintf(
+ thr,
+ "at %s (%s) native%s%s%s%s%s",
+ (const char *) funcname,
+ (const char *) filename,
+ (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
+ (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
+ (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
+ (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
+ (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
} else {
- duk_push_sprintf(thr, "at %s (%s:%lu)%s%s%s%s%s",
- (const char *) funcname,
- (const char *) filename,
- (unsigned long) line,
- (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
- (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
- (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
- (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
- (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
+ duk_push_sprintf(
+ thr,
+ "at %s (%s:%lu)%s%s%s%s%s",
+ (const char *) funcname,
+ (const char *) filename,
+ (unsigned long) line,
+ (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
+ (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
+ (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
+ (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
+ (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
}
- duk_replace(thr, -5); /* [ ... v1 v2 name filename str ] -> [ ... str v2 name filename ] */
- duk_pop_3(thr); /* -> [ ... str ] */
+ duk_replace(thr, -5); /* [ ... v1 v2 name filename str ] -> [ ... str v2 name filename ] */
+ duk_pop_3(thr); /* -> [ ... str ] */
} else if (t == DUK_TYPE_STRING) {
const char *str_file;
@@ -32011,10 +36068,12 @@ DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_hthread *thr, duk_small_int_t o
* safety issues.
*/
str_file = (const char *) duk_get_string(thr, -2);
- duk_push_sprintf(thr, "at [anon] (%s:%ld) internal",
- (const char *) (str_file ? str_file : "null"), (long) pc);
- duk_replace(thr, -3); /* [ ... v1 v2 str ] -> [ ... str v2 ] */
- duk_pop(thr); /* -> [ ... str ] */
+ duk_push_sprintf(thr,
+ "at [anon] (%s:%ld) internal",
+ (const char *) (str_file ? str_file : "null"),
+ (long) pc);
+ duk_replace(thr, -3); /* [ ... v1 v2 str ] -> [ ... str v2 ] */
+ duk_pop(thr); /* -> [ ... str ] */
} else {
/* unknown, ignore */
duk_pop_2(thr);
@@ -32061,7 +36120,7 @@ DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_hthread *thr
return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_LINENUMBER);
}
-#else /* DUK_USE_TRACEBACKS */
+#else /* DUK_USE_TRACEBACKS */
/*
* Traceback handling when tracebacks disabled.
@@ -32092,7 +36151,7 @@ DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_hthread *thr
return 0;
}
-#endif /* DUK_USE_TRACEBACKS */
+#endif /* DUK_USE_TRACEBACKS */
DUK_LOCAL duk_ret_t duk__error_setter_helper(duk_hthread *thr, duk_small_uint_t stridx_key) {
/* Attempt to write 'stack', 'fileName', 'lineNumber' works as if
@@ -32102,7 +36161,7 @@ DUK_LOCAL duk_ret_t duk__error_setter_helper(duk_hthread *thr, duk_small_uint_t
* See https://github.com/svaarala/duktape/issues/387.
*/
- DUK_ASSERT_TOP(thr, 1); /* fixed arg count: value */
+ DUK_ASSERT_TOP(thr, 1); /* fixed arg count: value */
duk_push_this(thr);
duk_push_hstring_stridx(thr, stridx_key);
@@ -32110,13 +36169,13 @@ DUK_LOCAL duk_ret_t duk__error_setter_helper(duk_hthread *thr, duk_small_uint_t
/* [ ... obj key value ] */
- DUK_DD(DUK_DDPRINT("error setter: %!T %!T %!T",
- duk_get_tval(thr, -3), duk_get_tval(thr, -2), duk_get_tval(thr, -1)));
+ DUK_DD(DUK_DDPRINT("error setter: %!T %!T %!T", duk_get_tval(thr, -3), duk_get_tval(thr, -2), duk_get_tval(thr, -1)));
- duk_def_prop(thr, -3, DUK_DEFPROP_HAVE_VALUE |
- DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE |
- DUK_DEFPROP_HAVE_ENUMERABLE | /*not enumerable*/
- DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE);
+ duk_def_prop(thr,
+ -3,
+ DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE |
+ DUK_DEFPROP_HAVE_ENUMERABLE | /*not enumerable*/
+ DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE);
return 0;
}
@@ -32163,7 +36222,7 @@ DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_hthread *thr) {
nargs = duk_get_top(thr);
for (i = 0; i < nargs; i++) {
- duk_to_string(thr, i); /* Rejects Symbols during coercion. */
+ duk_to_string(thr, i); /* Rejects Symbols during coercion. */
}
if (nargs == 0) {
@@ -32173,8 +36232,8 @@ DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_hthread *thr) {
/* XXX: cover this with the generic >1 case? */
duk_push_hstring_empty(thr);
} else {
- duk_insert(thr, 0); /* [ arg1 ... argN-1 body] -> [body arg1 ... argN-1] */
- duk_push_string(thr, ",");
+ duk_insert(thr, 0); /* [ arg1 ... argN-1 body] -> [body arg1 ... argN-1] */
+ duk_push_literal(thr, ",");
duk_insert(thr, 1);
duk_join(thr, nargs - 1);
}
@@ -32186,11 +36245,11 @@ DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_hthread *thr) {
/* XXX: this placeholder is not always correct, but use for now.
* It will fail in corner cases; see test-dev-func-cons-args.js.
*/
- duk_push_string(thr, "function(");
+ duk_push_literal(thr, "function(");
duk_dup_1(thr);
- duk_push_string(thr, "){");
+ duk_push_literal(thr, "){");
duk_dup_0(thr);
- duk_push_string(thr, "}");
+ duk_push_literal(thr, "\n}"); /* Newline is important to handle trailing // comment. */
duk_concat(thr, 5);
/* [ body formals source ] */
@@ -32200,15 +36259,15 @@ DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_hthread *thr) {
/* strictness is not inherited, intentional */
comp_flags = DUK_COMPILE_FUNCEXPR;
- duk_push_hstring_stridx(thr, DUK_STRIDX_COMPILE); /* XXX: copy from caller? */ /* XXX: ignored now */
- h_sourcecode = duk_require_hstring(thr, -2); /* no symbol check needed; -2 is concat'd code */
+ duk_push_hstring_stridx(thr, DUK_STRIDX_COMPILE); /* XXX: copy from caller? */ /* XXX: ignored now */
+ h_sourcecode = duk_require_hstring(thr, -2); /* no symbol check needed; -2 is concat'd code */
duk_js_compile(thr,
(const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode),
(duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode),
comp_flags);
/* Force .name to 'anonymous' (ES2015). */
- duk_push_string(thr, "anonymous");
+ duk_push_literal(thr, "anonymous");
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
func = (duk_hcompfunc *) duk_known_hobject(thr, -1);
@@ -32230,7 +36289,7 @@ DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_hthread *thr) {
return 1;
}
-#endif /* DUK_USE_FUNCTION_BUILTIN */
+#endif /* DUK_USE_FUNCTION_BUILTIN */
#if defined(DUK_USE_FUNCTION_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_function_prototype_to_string(duk_hthread *thr) {
@@ -32296,7 +36355,7 @@ DUK_INTERNAL duk_ret_t duk_bi_function_prototype_to_string(duk_hthread *thr) {
return 1;
- type_error:
+type_error:
DUK_DCERROR_TYPE_INVALID_ARGS(thr);
}
#endif
@@ -32338,7 +36397,7 @@ DUK_INTERNAL duk_ret_t duk_bi_reflect_construct(duk_hthread *thr) {
*/
DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) {
duk_hboundfunc *h_bound;
- duk_idx_t nargs; /* bound args, not counting 'this' binding */
+ duk_idx_t nargs; /* bound args, not counting 'this' binding */
duk_idx_t bound_nargs;
duk_int_t bound_len;
duk_tval *tv_prevbound;
@@ -32351,7 +36410,7 @@ DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) {
/* Vararg function, careful arg handling, e.g. thisArg may not
* be present.
*/
- nargs = duk_get_top(thr) - 1; /* actual args, not counting 'this' binding */
+ nargs = duk_get_top(thr) - 1; /* actual args, not counting 'this' binding */
if (nargs < 0) {
nargs++;
duk_push_undefined(thr);
@@ -32420,7 +36479,7 @@ DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) {
if (DUK_HOBJECT_HAS_BOUNDFUNC(h_target)) {
duk_hboundfunc *h_boundtarget;
- h_boundtarget = (duk_hboundfunc *) h_target;
+ h_boundtarget = (duk_hboundfunc *) (void *) h_target;
/* The final function should always be non-bound, unless
* there's a bug in the internals. Assert for it.
@@ -32446,7 +36505,7 @@ DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) {
DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) h_bound, bound_proto);
}
- DUK_TVAL_INCREF(thr, &h_bound->target); /* old values undefined, no decref needed */
+ DUK_TVAL_INCREF(thr, &h_bound->target); /* old values undefined, no decref needed */
DUK_TVAL_INCREF(thr, &h_bound->this_binding);
bound_nargs = n_prevbound + nargs;
@@ -32454,7 +36513,7 @@ DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) {
DUK_DCERROR_RANGE_INVALID_COUNT(thr);
}
tv_res = (duk_tval *) DUK_ALLOC_CHECKED(thr, ((duk_size_t) bound_nargs) * sizeof(duk_tval));
- DUK_ASSERT(tv_res != NULL);
+ DUK_ASSERT(tv_res != NULL || bound_nargs == 0);
DUK_ASSERT(h_bound->args == NULL);
DUK_ASSERT(h_bound->nargs == 0);
h_bound->args = tv_res;
@@ -32471,7 +36530,7 @@ DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) {
* For lightfuncs, simply read the virtual property.
*/
duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH);
- bound_len = duk_get_int(thr, -1); /* ES2015: no coercion */
+ bound_len = duk_get_int(thr, -1); /* ES2015: no coercion */
if (bound_len < nargs) {
bound_len = 0;
} else {
@@ -32485,8 +36544,8 @@ DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) {
tv_tmp = thr->valstack_top++;
DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_tmp));
DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv_tmp));
- DUK_TVAL_SET_U32(tv_tmp, (duk_uint32_t) bound_len); /* in-place update, fastint */
- duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C); /* attrs in E6 Section 9.2.4 */
+ DUK_TVAL_SET_U32(tv_tmp, (duk_uint32_t) bound_len); /* in-place update, fastint */
+ duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C); /* attrs in E6 Section 9.2.4 */
/* XXX: could these be virtual? */
/* Caller and arguments must use the same thrower, [[ThrowTypeError]]. */
@@ -32494,7 +36553,7 @@ DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) {
duk_xdef_prop_stridx_thrower(thr, -1, DUK_STRIDX_LC_ARGUMENTS);
/* Function name and fileName (non-standard). */
- duk_push_string(thr, "bound "); /* ES2015 19.2.3.2. */
+ duk_push_literal(thr, "bound "); /* ES2015 19.2.3.2. */
duk_get_prop_stridx(thr, -3, DUK_STRIDX_NAME);
if (!duk_is_string_notsymbol(thr, -1)) {
/* ES2015 has requirement to check that .name of target is a string
@@ -32515,7 +36574,7 @@ DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) {
return 1;
}
-#endif /* DUK_USE_FUNCTION_BUILTIN */
+#endif /* DUK_USE_FUNCTION_BUILTIN */
/* %NativeFunctionPrototype% .length getter. */
DUK_INTERNAL duk_ret_t duk_bi_native_function_length(duk_hthread *thr) {
@@ -32546,7 +36605,7 @@ DUK_INTERNAL duk_ret_t duk_bi_native_function_length(duk_hthread *thr) {
}
return 1;
- fail_type:
+fail_type:
DUK_DCERROR_TYPE_INVALID_ARGS(thr);
}
@@ -32575,9 +36634,20 @@ DUK_INTERNAL duk_ret_t duk_bi_native_function_name(duk_hthread *thr) {
}
return 1;
- fail_type:
+fail_type:
DUK_DCERROR_TYPE_INVALID_ARGS(thr);
}
+
+#if defined(DUK_USE_SYMBOL_BUILTIN)
+DUK_INTERNAL duk_ret_t duk_bi_function_prototype_hasinstance(duk_hthread *thr) {
+ /* This binding: RHS, stack index 0: LHS. */
+ duk_bool_t ret;
+
+ ret = duk_js_instanceof_ordinary(thr, DUK_GET_TVAL_POSIDX(thr, 0), DUK_GET_THIS_TVAL_PTR(thr));
+ duk_push_boolean(thr, ret);
+ return 1;
+}
+#endif /* DUK_USE_SYMBOL_BUILTIN */
/*
* Global object built-ins
*/
@@ -32596,73 +36666,71 @@ DUK_INTERNAL duk_ret_t duk_bi_native_function_name(duk_hthread *thr) {
/* Macros for creating and checking bitmasks for character encoding.
* Bit number is a bit counterintuitive, but minimizes code size.
*/
-#define DUK__MKBITS(a,b,c,d,e,f,g,h) ((duk_uint8_t) ( \
- ((a) << 0) | ((b) << 1) | ((c) << 2) | ((d) << 3) | \
- ((e) << 4) | ((f) << 5) | ((g) << 6) | ((h) << 7) \
- ))
-#define DUK__CHECK_BITMASK(table,cp) ((table)[(cp) >> 3] & (1 << ((cp) & 0x07)))
+#define DUK__MKBITS(a, b, c, d, e, f, g, h) \
+ ((duk_uint8_t) (((a) << 0) | ((b) << 1) | ((c) << 2) | ((d) << 3) | ((e) << 4) | ((f) << 5) | ((g) << 6) | ((h) << 7)))
+#define DUK__CHECK_BITMASK(table, cp) ((table)[(cp) >> 3] & (1 << ((cp) &0x07)))
/* E5.1 Section 15.1.3.3: uriReserved + uriUnescaped + '#' */
DUK_LOCAL const duk_uint8_t duk__encode_uriunescaped_table[16] = {
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
- DUK__MKBITS(0, 1, 0, 1, 1, 0, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x20-0x2f */
- DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 0, 1, 0, 1), /* 0x30-0x3f */
- DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */
- DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */
- DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */
- DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0), /* 0x70-0x7f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
+ DUK__MKBITS(0, 1, 0, 1, 1, 0, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x20-0x2f */
+ DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 0, 1, 0, 1), /* 0x30-0x3f */
+ DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */
+ DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */
+ DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */
+ DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0), /* 0x70-0x7f */
};
/* E5.1 Section 15.1.3.4: uriUnescaped */
DUK_LOCAL const duk_uint8_t duk__encode_uricomponent_unescaped_table[16] = {
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
- DUK__MKBITS(0, 1, 0, 0, 0, 0, 0, 1), DUK__MKBITS(1, 1, 1, 0, 0, 1, 1, 0), /* 0x20-0x2f */
- DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */
- DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */
- DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */
- DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */
- DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0), /* 0x70-0x7f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
+ DUK__MKBITS(0, 1, 0, 0, 0, 0, 0, 1), DUK__MKBITS(1, 1, 1, 0, 0, 1, 1, 0), /* 0x20-0x2f */
+ DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */
+ DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */
+ DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */
+ DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */
+ DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0), /* 0x70-0x7f */
};
/* E5.1 Section 15.1.3.1: uriReserved + '#' */
DUK_LOCAL const duk_uint8_t duk__decode_uri_reserved_table[16] = {
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
- DUK__MKBITS(0, 0, 0, 1, 1, 0, 1, 0), DUK__MKBITS(0, 0, 0, 1, 1, 0, 0, 1), /* 0x20-0x2f */
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 0, 1), /* 0x30-0x3f */
- DUK__MKBITS(1, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x40-0x4f */
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x50-0x5f */
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x60-0x6f */
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x70-0x7f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
+ DUK__MKBITS(0, 0, 0, 1, 1, 0, 1, 0), DUK__MKBITS(0, 0, 0, 1, 1, 0, 0, 1), /* 0x20-0x2f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 0, 1), /* 0x30-0x3f */
+ DUK__MKBITS(1, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x40-0x4f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x50-0x5f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x60-0x6f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x70-0x7f */
};
/* E5.1 Section 15.1.3.2: empty */
DUK_LOCAL const duk_uint8_t duk__decode_uri_component_reserved_table[16] = {
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x20-0x2f */
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x40-0x4f */
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x50-0x5f */
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x60-0x6f */
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x70-0x7f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x20-0x2f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x40-0x4f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x50-0x5f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x60-0x6f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x70-0x7f */
};
#if defined(DUK_USE_SECTION_B)
/* E5.1 Section B.2.2, step 7. */
DUK_LOCAL const duk_uint8_t duk__escape_unescaped_table[16] = {
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
- DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 1, 1), /* 0x20-0x2f */
- DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */
- DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */
- DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */
- DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */
- DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 0) /* 0x70-0x7f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
+ DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 1, 1), /* 0x20-0x2f */
+ DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */
+ DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */
+ DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */
+ DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */
+ DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 0) /* 0x70-0x7f */
};
-#endif /* DUK_USE_SECTION_B */
+#endif /* DUK_USE_SECTION_B */
typedef struct {
duk_hthread *thr;
@@ -32703,7 +36771,7 @@ DUK_LOCAL int duk__transform_helper(duk_hthread *thr, duk__transform_callback ca
tfm_ctx->h_str = duk_to_hstring(thr, 0);
DUK_ASSERT(tfm_ctx->h_str != NULL);
- DUK_BW_INIT_PUSHBUF(thr, &tfm_ctx->bw, DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str)); /* initial size guess */
+ DUK_BW_INIT_PUSHBUF(thr, &tfm_ctx->bw, DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str)); /* initial size guess */
tfm_ctx->p_start = DUK_HSTRING_GET_DATA(tfm_ctx->h_str);
tfm_ctx->p_end = tfm_ctx->p_start + DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str);
@@ -32716,7 +36784,7 @@ DUK_LOCAL int duk__transform_helper(duk_hthread *thr, duk__transform_callback ca
DUK_BW_COMPACT(thr, &tfm_ctx->bw);
- (void) duk_buffer_to_string(thr, -1); /* Safe if transform is safe. */
+ (void) duk_buffer_to_string(thr, -1); /* Safe if transform is safe. */
return 1;
}
@@ -32742,7 +36810,11 @@ DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ct
goto uri_error;
} else if (cp >= 0xd800L && cp <= 0xdbffL) {
/* Needs lookahead */
- if (duk_unicode_decode_xutf8(tfm_ctx->thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end, (duk_ucodepoint_t *) &cp2) == 0) {
+ if (duk_unicode_decode_xutf8(tfm_ctx->thr,
+ &tfm_ctx->p,
+ tfm_ctx->p_start,
+ tfm_ctx->p_end,
+ (duk_ucodepoint_t *) &cp2) == 0) {
goto uri_error;
}
if (!(cp2 >= 0xdc00L && cp2 <= 0xdfffL)) {
@@ -32773,20 +36845,21 @@ DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ct
&tfm_ctx->bw,
DUK_ASC_PERCENT,
(duk_uint8_t) duk_uc_nybbles[t >> 4],
- (duk_uint8_t) duk_uc_nybbles[t & 0x0f]);
+ (duk_uint8_t) duk_uc_nybbles[t & 0x0f]);
}
return;
- uri_error:
+uri_error:
DUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
+ DUK_WO_NORETURN(return;);
}
DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
const duk_uint8_t *reserved_table = (const duk_uint8_t *) udata;
duk_small_uint_t utf8_blen;
duk_codepoint_t min_cp;
- duk_small_int_t t; /* must be signed */
+ duk_small_int_t t; /* must be signed */
duk_small_uint_t i;
/* Maximum write size: XUTF8 path writes max DUK_UNICODE_MAX_XUTF8_LENGTH,
@@ -32794,12 +36867,12 @@ DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ct
*/
DUK_BW_ENSURE(tfm_ctx->thr,
&tfm_ctx->bw,
- (DUK_UNICODE_MAX_XUTF8_LENGTH >= 2 * DUK_UNICODE_MAX_CESU8_BMP_LENGTH ?
- DUK_UNICODE_MAX_XUTF8_LENGTH : DUK_UNICODE_MAX_CESU8_BMP_LENGTH));
+ (DUK_UNICODE_MAX_XUTF8_LENGTH >= 2 * DUK_UNICODE_MAX_CESU8_BMP_LENGTH ? DUK_UNICODE_MAX_XUTF8_LENGTH :
+ DUK_UNICODE_MAX_CESU8_BMP_LENGTH));
if (cp == (duk_codepoint_t) '%') {
const duk_uint8_t *p = tfm_ctx->p;
- duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p); /* bytes left */
+ duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p); /* bytes left */
DUK_DDD(DUK_DDDPRINT("percent encoding, left=%ld", (long) left));
@@ -32817,11 +36890,7 @@ DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ct
if (DUK__CHECK_BITMASK(reserved_table, t)) {
/* decode '%xx' to '%xx' if decoded char in reserved set */
DUK_ASSERT(tfm_ctx->p - 1 >= tfm_ctx->p_start);
- DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
- &tfm_ctx->bw,
- DUK_ASC_PERCENT,
- p[0],
- p[1]);
+ DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr, &tfm_ctx->bw, DUK_ASC_PERCENT, p[0], p[1]);
} else {
DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) t);
}
@@ -32872,7 +36941,10 @@ DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ct
/* p points to digit part ('%xy', p points to 'x') */
t = duk__decode_hex_escape(p, 2);
DUK_DDD(DUK_DDDPRINT("i=%ld utf8_blen=%ld cp=%ld t=0x%02lx",
- (long) i, (long) utf8_blen, (long) cp, (unsigned long) t));
+ (long) i,
+ (long) utf8_blen,
+ (long) cp,
+ (unsigned long) t));
if (t < 0) {
goto uri_error;
}
@@ -32882,7 +36954,7 @@ DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ct
cp = (cp << 6) + (t & 0x3f);
p += 3;
}
- p--; /* p overshoots */
+ p--; /* p overshoots */
tfm_ctx->p = p;
DUK_DDD(DUK_DDDPRINT("final cp=%ld, min_cp=%ld", (long) cp, (long) min_cp));
@@ -32916,8 +36988,9 @@ DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ct
}
return;
- uri_error:
+uri_error:
DUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
+ DUK_WO_NORETURN(return;);
}
#if defined(DUK_USE_SECTION_B)
@@ -32956,8 +37029,9 @@ DUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, c
return;
- esc_error:
+esc_error:
DUK_ERROR_TYPE(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
+ DUK_WO_NORETURN(return;);
}
DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
@@ -32967,14 +37041,12 @@ DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx,
if (cp == (duk_codepoint_t) '%') {
const duk_uint8_t *p = tfm_ctx->p;
- duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p); /* bytes left */
+ duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p); /* bytes left */
- if (left >= 5 && p[0] == 'u' &&
- ((t = duk__decode_hex_escape(p + 1, 4)) >= 0)) {
+ if (left >= 5 && p[0] == 'u' && ((t = duk__decode_hex_escape(p + 1, 4)) >= 0)) {
cp = (duk_codepoint_t) t;
tfm_ctx->p += 5;
- } else if (left >= 2 &&
- ((t = duk__decode_hex_escape(p, 2)) >= 0)) {
+ } else if (left >= 2 && ((t = duk__decode_hex_escape(p, 2)) >= 0)) {
cp = (duk_codepoint_t) t;
tfm_ctx->p += 2;
}
@@ -32982,7 +37054,7 @@ DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx,
DUK_BW_WRITE_ENSURE_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
}
-#endif /* DUK_USE_SECTION_B */
+#endif /* DUK_USE_SECTION_B */
/*
* Eval
@@ -32990,7 +37062,7 @@ DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx,
* Eval needs to handle both a "direct eval" and an "indirect eval".
* Direct eval handling needs access to the caller's activation so that its
* lexical environment can be accessed. A direct eval is only possible from
- * Ecmascript code; an indirect eval call is possible also from C code.
+ * ECMAScript code; an indirect eval call is possible also from C code.
* When an indirect eval call is made from C code, there may not be a
* calling activation at all which needs careful handling.
*/
@@ -33007,11 +37079,11 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_hthread *thr) {
duk_int_t level = -2;
duk_small_uint_t call_flags;
- DUK_ASSERT(duk_get_top(thr) == 1 || duk_get_top(thr) == 2); /* 2 when called by debugger */
- DUK_ASSERT(thr->callstack_top >= 1); /* at least this function exists */
+ DUK_ASSERT(duk_get_top(thr) == 1 || duk_get_top(thr) == 2); /* 2 when called by debugger */
+ DUK_ASSERT(thr->callstack_top >= 1); /* at least this function exists */
DUK_ASSERT(thr->callstack_curr != NULL);
DUK_ASSERT((thr->callstack_curr->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0 || /* indirect eval */
- (thr->callstack_top >= 2)); /* if direct eval, calling activation must exist */
+ (thr->callstack_top >= 2)); /* if direct eval, calling activation must exist */
/*
* callstack_top - 1 --> this function
@@ -33024,32 +37096,31 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_hthread *thr) {
h = duk_get_hstring_notsymbol(thr, 0);
if (!h) {
/* Symbol must be returned as is, like any non-string values. */
- return 1; /* return arg as-is */
+ return 1; /* return arg as-is */
}
#if defined(DUK_USE_DEBUGGER_SUPPORT)
/* NOTE: level is used only by the debugger and should never be present
- * for an Ecmascript eval().
+ * for an ECMAScript eval().
*/
- DUK_ASSERT(level == -2); /* by default, use caller's environment */
+ DUK_ASSERT(level == -2); /* by default, use caller's environment */
if (duk_get_top(thr) >= 2 && duk_is_number(thr, 1)) {
level = duk_get_int(thr, 1);
}
- DUK_ASSERT(level <= -2); /* This is guaranteed by debugger code. */
+ DUK_ASSERT(level <= -2); /* This is guaranteed by debugger code. */
#endif
/* [ source ] */
comp_flags = DUK_COMPILE_EVAL;
- act_eval = thr->callstack_curr; /* this function */
+ act_eval = thr->callstack_curr; /* this function */
DUK_ASSERT(act_eval != NULL);
act_caller = duk_hthread_get_activation_for_level(thr, level);
if (act_caller != NULL) {
/* Have a calling activation, check for direct eval (otherwise
* assume indirect eval.
*/
- if ((act_caller->flags & DUK_ACT_FLAG_STRICT) &&
- (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL)) {
+ if ((act_caller->flags & DUK_ACT_FLAG_STRICT) && (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL)) {
/* Only direct eval inherits strictness from calling code
* (E5.1 Section 10.1.1).
*/
@@ -33059,11 +37130,8 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_hthread *thr) {
DUK_ASSERT((act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0);
}
- duk_push_hstring_stridx(thr, DUK_STRIDX_INPUT); /* XXX: copy from caller? */
- duk_js_compile(thr,
- (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h),
- (duk_size_t) DUK_HSTRING_GET_BYTELEN(h),
- comp_flags);
+ duk_push_hstring_stridx(thr, DUK_STRIDX_INPUT); /* XXX: copy from caller? */
+ duk_js_compile(thr, (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h), (duk_size_t) DUK_HSTRING_GET_BYTELEN(h), comp_flags);
func = (duk_hcompfunc *) duk_known_hobject(thr, -1);
DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) func));
@@ -33096,9 +37164,9 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_hthread *thr) {
act_lex_env = act_caller->lex_env;
- new_env = duk_hdecenv_alloc(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
+ new_env =
+ duk_hdecenv_alloc(thr,
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
DUK_ASSERT(new_env != NULL);
duk_push_hobject(thr, (duk_hobject *) new_env);
@@ -33110,7 +37178,7 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_hthread *thr) {
outer_lex_env = (duk_hobject *) new_env;
outer_var_env = (duk_hobject *) new_env;
- duk_insert(thr, 0); /* stash to bottom of value stack to keep new_env reachable for duration of eval */
+ duk_insert(thr, 0); /* stash to bottom of value stack to keep new_env reachable for duration of eval */
/* compiler's responsibility */
DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));
@@ -33146,7 +37214,8 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_hthread *thr) {
duk_tval *tv;
DUK_ASSERT(thr->callstack_top >= 2);
DUK_ASSERT(act_caller != NULL);
- tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act_caller->bottom_byteoff - sizeof(duk_tval)); /* this is just beneath bottom */
+ tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act_caller->bottom_byteoff -
+ sizeof(duk_tval)); /* this is just beneath bottom */
DUK_ASSERT(tv >= thr->valstack);
duk_push_tval(thr, tv);
}
@@ -33185,19 +37254,15 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_int(duk_hthread *thr) {
duk_small_uint_t s2n_flags;
DUK_ASSERT_TOP(thr, 2);
- duk_to_string(thr, 0); /* Reject symbols. */
+ duk_to_string(thr, 0); /* Reject symbols. */
radix = duk_to_int32(thr, 1);
/* While parseInt() recognizes 0xdeadbeef, it doesn't recognize
* ES2015 0o123 or 0b10001.
*/
- s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
- DUK_S2N_FLAG_ALLOW_GARBAGE |
- DUK_S2N_FLAG_ALLOW_PLUS |
- DUK_S2N_FLAG_ALLOW_MINUS |
- DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
- DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
+ s2n_flags = DUK_S2N_FLAG_TRIM_WHITE | DUK_S2N_FLAG_ALLOW_GARBAGE | DUK_S2N_FLAG_ALLOW_PLUS | DUK_S2N_FLAG_ALLOW_MINUS |
+ DUK_S2N_FLAG_ALLOW_LEADING_ZERO | DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
/* Specification stripPrefix maps to DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT.
*
@@ -33221,35 +37286,28 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_int(duk_hthread *thr) {
duk_numconv_parse(thr, (duk_small_int_t) radix, s2n_flags);
return 1;
- ret_nan:
+ret_nan:
duk_push_nan(thr);
return 1;
}
-#endif /* DUK_USE_GLOBAL_BUILTIN */
+#endif /* DUK_USE_GLOBAL_BUILTIN */
#if defined(DUK_USE_GLOBAL_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_float(duk_hthread *thr) {
duk_small_uint_t s2n_flags;
DUK_ASSERT_TOP(thr, 1);
- duk_to_string(thr, 0); /* Reject symbols. */
+ duk_to_string(thr, 0); /* Reject symbols. */
/* XXX: check flags */
- s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
- DUK_S2N_FLAG_ALLOW_EXP |
- DUK_S2N_FLAG_ALLOW_GARBAGE |
- DUK_S2N_FLAG_ALLOW_PLUS |
- DUK_S2N_FLAG_ALLOW_MINUS |
- DUK_S2N_FLAG_ALLOW_INF |
- DUK_S2N_FLAG_ALLOW_FRAC |
- DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
- DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
- DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
+ s2n_flags = DUK_S2N_FLAG_TRIM_WHITE | DUK_S2N_FLAG_ALLOW_EXP | DUK_S2N_FLAG_ALLOW_GARBAGE | DUK_S2N_FLAG_ALLOW_PLUS |
+ DUK_S2N_FLAG_ALLOW_MINUS | DUK_S2N_FLAG_ALLOW_INF | DUK_S2N_FLAG_ALLOW_FRAC | DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
+ DUK_S2N_FLAG_ALLOW_EMPTY_FRAC | DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
return 1;
}
-#endif /* DUK_USE_GLOBAL_BUILTIN */
+#endif /* DUK_USE_GLOBAL_BUILTIN */
/*
* Number checkers
@@ -33261,7 +37319,7 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_is_nan(duk_hthread *thr) {
duk_push_boolean(thr, (duk_bool_t) DUK_ISNAN(d));
return 1;
}
-#endif /* DUK_USE_GLOBAL_BUILTIN */
+#endif /* DUK_USE_GLOBAL_BUILTIN */
#if defined(DUK_USE_GLOBAL_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_global_object_is_finite(duk_hthread *thr) {
@@ -33269,7 +37327,7 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_is_finite(duk_hthread *thr) {
duk_push_boolean(thr, (duk_bool_t) DUK_ISFINITE(d));
return 1;
}
-#endif /* DUK_USE_GLOBAL_BUILTIN */
+#endif /* DUK_USE_GLOBAL_BUILTIN */
/*
* URI handling
@@ -33281,7 +37339,9 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri(duk_hthread *thr) {
}
DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri_component(duk_hthread *thr) {
- return duk__transform_helper(thr, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_component_reserved_table);
+ return duk__transform_helper(thr,
+ duk__transform_callback_decode_uri,
+ (const void *) duk__decode_uri_component_reserved_table);
}
DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri(duk_hthread *thr) {
@@ -33289,7 +37349,9 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri(duk_hthread *thr) {
}
DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri_component(duk_hthread *thr) {
- return duk__transform_helper(thr, duk__transform_callback_encode_uri, (const void *) duk__encode_uricomponent_unescaped_table);
+ return duk__transform_helper(thr,
+ duk__transform_callback_encode_uri,
+ (const void *) duk__encode_uricomponent_unescaped_table);
}
#if defined(DUK_USE_SECTION_B)
@@ -33300,8 +37362,8 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_escape(duk_hthread *thr) {
DUK_INTERNAL duk_ret_t duk_bi_global_object_unescape(duk_hthread *thr) {
return duk__transform_helper(thr, duk__transform_callback_unescape, (const void *) NULL);
}
-#endif /* DUK_USE_SECTION_B */
-#endif /* DUK_USE_GLOBAL_BUILTIN */
+#endif /* DUK_USE_SECTION_B */
+#endif /* DUK_USE_GLOBAL_BUILTIN */
/* automatic undefs */
#undef DUK__CHECK_BITMASK
@@ -33330,34 +37392,34 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_unescape(duk_hthread *thr) {
* Local defines and forward declarations.
*/
-#define DUK__JSON_DECSTR_BUFSIZE 128
-#define DUK__JSON_DECSTR_CHUNKSIZE 64
-#define DUK__JSON_ENCSTR_CHUNKSIZE 64
+#define DUK__JSON_DECSTR_BUFSIZE 128
+#define DUK__JSON_DECSTR_CHUNKSIZE 64
+#define DUK__JSON_ENCSTR_CHUNKSIZE 64
#define DUK__JSON_STRINGIFY_BUFSIZE 128
-#define DUK__JSON_MAX_ESC_LEN 10 /* '\Udeadbeef' */
+#define DUK__JSON_MAX_ESC_LEN 10 /* '\Udeadbeef' */
-DUK_LOCAL_DECL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_syntax_error(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_eat_white(duk_json_dec_ctx *js_ctx);
#if defined(DUK_USE_JX)
-DUK_LOCAL_DECL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL duk_uint8_t duk__json_dec_peek(duk_json_dec_ctx *js_ctx);
#endif
-DUK_LOCAL_DECL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n);
-DUK_LOCAL_DECL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx);
-DUK_LOCAL_DECL void duk__dec_string(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL duk_uint8_t duk__json_dec_get(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL duk_uint8_t duk__json_dec_get_nonwhite(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL duk_uint_fast32_t duk__json_dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n);
+DUK_LOCAL_DECL void duk__json_dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx);
+DUK_LOCAL_DECL void duk__json_dec_string(duk_json_dec_ctx *js_ctx);
#if defined(DUK_USE_JX)
-DUK_LOCAL_DECL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__dec_pointer(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__dec_buffer(duk_json_dec_ctx *js_ctx);
-#endif
-DUK_LOCAL_DECL void duk__dec_number(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__dec_object(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__dec_array(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__dec_value(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_plain_string(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_pointer(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_buffer(duk_json_dec_ctx *js_ctx);
+#endif
+DUK_LOCAL_DECL void duk__json_dec_number(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_objarr_entry(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_objarr_exit(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_object(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_array(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_value(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_reviver_walk(duk_json_dec_ctx *js_ctx);
DUK_LOCAL_DECL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch);
DUK_LOCAL_DECL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2);
@@ -33368,29 +37430,29 @@ DUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p);
#endif
DUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx);
DUK_LOCAL_DECL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q);
-DUK_LOCAL_DECL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k);
-DUK_LOCAL_DECL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str);
-DUK_LOCAL_DECL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
-DUK_LOCAL_DECL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
-DUK_LOCAL_DECL void duk__enc_object(duk_json_enc_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__enc_array(duk_json_enc_ctx *js_ctx);
-DUK_LOCAL_DECL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder);
-DUK_LOCAL_DECL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv);
-DUK_LOCAL_DECL void duk__enc_double(duk_json_enc_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k);
+DUK_LOCAL_DECL void duk__json_enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str);
+DUK_LOCAL_DECL void duk__json_enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
+DUK_LOCAL_DECL void duk__json_enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
+DUK_LOCAL_DECL void duk__json_enc_object(duk_json_enc_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_enc_array(duk_json_enc_ctx *js_ctx);
+DUK_LOCAL_DECL duk_bool_t duk__json_enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder);
+DUK_LOCAL_DECL duk_bool_t duk__json_enc_allow_into_proplist(duk_tval *tv);
+DUK_LOCAL_DECL void duk__json_enc_double(duk_json_enc_ctx *js_ctx);
#if defined(DUK_USE_FASTINT)
-DUK_LOCAL_DECL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv);
+DUK_LOCAL_DECL void duk__json_enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv);
#endif
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
-DUK_LOCAL_DECL void duk__enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
-DUK_LOCAL_DECL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr);
+DUK_LOCAL_DECL void duk__json_enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
+DUK_LOCAL_DECL void duk__json_enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr);
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
-DUK_LOCAL_DECL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj);
+DUK_LOCAL_DECL void duk__json_enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj);
#endif
#endif
#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
-DUK_LOCAL_DECL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
+DUK_LOCAL_DECL void duk__json_enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
#endif
-DUK_LOCAL_DECL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth);
+DUK_LOCAL_DECL void duk__json_enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth);
/*
* Helper tables
@@ -33404,103 +37466,88 @@ DUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256] = {
* 0xa0 ... 0xff: backslash + one char
*/
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe2, 0xf4, 0xee, 0x80, 0xe6, 0xf2, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x20, 0x21, 0xa2, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
- 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0xdc, 0x5d, 0x5e, 0x5f,
- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x81,
- 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
- 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
- 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
- 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
- 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
- 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
- 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe2, 0xf4, 0xee, 0x80, 0xe6, 0xf2, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x20, 0x21, 0xa2, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
+ 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0xdc, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63,
+ 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81
};
-#else /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
-DUK_LOCAL const duk_uint8_t duk__json_quotestr_esc[14] = {
- DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
- DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
- DUK_ASC_LC_B, DUK_ASC_LC_T, DUK_ASC_LC_N, DUK_ASC_NUL,
- DUK_ASC_LC_F, DUK_ASC_LC_R
-};
-#endif /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
+#else /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
+DUK_LOCAL const duk_uint8_t duk__json_quotestr_esc[14] = { DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
+ DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_LC_B, DUK_ASC_LC_T,
+ DUK_ASC_LC_N, DUK_ASC_NUL, DUK_ASC_LC_F, DUK_ASC_LC_R };
+#endif /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
#if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
DUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256] = {
/* 0x00: slow path
* other: as is
*/
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x20, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
- 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x5d, 0x5e, 0x5f,
- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
- 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
- 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
- 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
- 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
+ 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63,
+ 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b,
+ 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
+ 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb,
+ 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
-#endif /* DUK_USE_JSON_DECSTRING_FASTPATH */
+#endif /* DUK_USE_JSON_DECSTRING_FASTPATH */
#if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
DUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256] = {
/* 0x00: finish (non-white)
* 0x01: continue
*/
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
-#endif /* DUK_USE_JSON_EATWHITE_FASTPATH */
+#endif /* DUK_USE_JSON_EATWHITE_FASTPATH */
#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256] = {
/* 0x00: finish (not part of number)
* 0x01: continue
*/
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
-#endif /* DUK_USE_JSON_DECNUMBER_FASTPATH */
+#endif /* DUK_USE_JSON_DECNUMBER_FASTPATH */
/*
* Parsing implementation.
@@ -33515,16 +37562,16 @@ DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256] = {
* CESU-8 encodings.
*/
-DUK_LOCAL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_syntax_error(duk_json_dec_ctx *js_ctx) {
/* Shared handler to minimize parser size. Cause will be
* hidden, unfortunately, but we'll have an offset which
* is often quite enough.
*/
- DUK_ERROR_FMT1(js_ctx->thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_FMT_INVALID_JSON,
- (long) (js_ctx->p - js_ctx->p_start));
+ DUK_ERROR_FMT1(js_ctx->thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_FMT_INVALID_JSON, (long) (js_ctx->p - js_ctx->p_start));
+ DUK_WO_NORETURN(return;);
}
-DUK_LOCAL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_eat_white(duk_json_dec_ctx *js_ctx) {
const duk_uint8_t *p;
duk_uint8_t t;
@@ -33537,42 +37584,42 @@ DUK_LOCAL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx) {
/* This fast path is pretty marginal in practice.
* XXX: candidate for removal.
*/
- DUK_ASSERT(duk__json_eatwhite_lookup[0x00] == 0x00); /* end-of-input breaks */
+ DUK_ASSERT(duk__json_eatwhite_lookup[0x00] == 0x00); /* end-of-input breaks */
if (duk__json_eatwhite_lookup[t] == 0) {
break;
}
-#else /* DUK_USE_JSON_EATWHITE_FASTPATH */
+#else /* DUK_USE_JSON_EATWHITE_FASTPATH */
if (!(t == 0x20 || t == 0x0a || t == 0x0d || t == 0x09)) {
/* NUL also comes here. Comparison order matters, 0x20
* is most common whitespace.
*/
break;
}
-#endif /* DUK_USE_JSON_EATWHITE_FASTPATH */
+#endif /* DUK_USE_JSON_EATWHITE_FASTPATH */
p++;
}
js_ctx->p = p;
}
#if defined(DUK_USE_JX)
-DUK_LOCAL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL duk_uint8_t duk__json_dec_peek(duk_json_dec_ctx *js_ctx) {
DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
return *js_ctx->p;
}
#endif
-DUK_LOCAL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL duk_uint8_t duk__json_dec_get(duk_json_dec_ctx *js_ctx) {
DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
return *js_ctx->p++;
}
-DUK_LOCAL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx) {
- duk__dec_eat_white(js_ctx);
- return duk__dec_get(js_ctx);
+DUK_LOCAL duk_uint8_t duk__json_dec_get_nonwhite(duk_json_dec_ctx *js_ctx) {
+ duk__json_dec_eat_white(js_ctx);
+ return duk__json_dec_get(js_ctx);
}
/* For JX, expressing the whole unsigned 32-bit range matters. */
-DUK_LOCAL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) {
+DUK_LOCAL duk_uint_fast32_t duk__json_dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) {
duk_small_uint_t i;
duk_uint_fast32_t res = 0;
duk_uint8_t x;
@@ -33581,9 +37628,8 @@ DUK_LOCAL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx,
for (i = 0; i < n; i++) {
/* XXX: share helper from lexer; duk_lexer.c / hexval(). */
- x = duk__dec_get(js_ctx);
- DUK_DDD(DUK_DDDPRINT("decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld",
- (long) i, (long) n, (long) res, (long) x));
+ x = duk__json_dec_get(js_ctx);
+ DUK_DDD(DUK_DDDPRINT("decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld", (long) i, (long) n, (long) res, (long) x));
/* x == 0x00 (EOF) causes syntax_error */
DUK_ASSERT(duk_hex_dectab[0] == -1);
@@ -33599,13 +37645,13 @@ DUK_LOCAL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx,
DUK_DDD(DUK_DDDPRINT("final hex decoded value: %ld", (long) res));
return res;
- syntax_error:
- duk__dec_syntax_error(js_ctx);
+syntax_error:
+ duk__json_dec_syntax_error(js_ctx);
DUK_UNREACHABLE();
return 0;
}
-DUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) {
+DUK_LOCAL void duk__json_dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) {
duk_hstring *h;
const duk_uint8_t *p;
duk_uint8_t x, y;
@@ -33620,14 +37666,14 @@ DUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t st
DUK_ASSERT(h != NULL);
p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h) + 1;
- DUK_ASSERT(*(js_ctx->p - 1) == *(p - 1)); /* first character has been matched */
+ DUK_ASSERT(*(js_ctx->p - 1) == *(p - 1)); /* first character has been matched */
for (;;) {
x = *p;
if (x == 0) {
break;
}
- y = duk__dec_get(js_ctx);
+ y = duk__json_dec_get(js_ctx);
if (x != y) {
/* Catches EOF of JSON input. */
goto syntax_error;
@@ -33637,61 +37683,74 @@ DUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t st
return;
- syntax_error:
- duk__dec_syntax_error(js_ctx);
+syntax_error:
+ duk__json_dec_syntax_error(js_ctx);
DUK_UNREACHABLE();
}
-DUK_LOCAL duk_small_int_t duk__dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p) {
+DUK_LOCAL duk_small_int_t duk__json_dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p) {
duk_uint_fast32_t cp;
/* EOF (-1) will be cast to an unsigned value first
* and then re-cast for the switch. In any case, it
* will match the default case (syntax error).
*/
- cp = (duk_uint_fast32_t) duk__dec_get(js_ctx);
+ cp = (duk_uint_fast32_t) duk__json_dec_get(js_ctx);
switch (cp) {
- case DUK_ASC_BACKSLASH: break;
- case DUK_ASC_DOUBLEQUOTE: break;
- case DUK_ASC_SLASH: break;
- case DUK_ASC_LC_T: cp = 0x09; break;
- case DUK_ASC_LC_N: cp = 0x0a; break;
- case DUK_ASC_LC_R: cp = 0x0d; break;
- case DUK_ASC_LC_F: cp = 0x0c; break;
- case DUK_ASC_LC_B: cp = 0x08; break;
+ case DUK_ASC_BACKSLASH:
+ break;
+ case DUK_ASC_DOUBLEQUOTE:
+ break;
+ case DUK_ASC_SLASH:
+ break;
+ case DUK_ASC_LC_T:
+ cp = 0x09;
+ break;
+ case DUK_ASC_LC_N:
+ cp = 0x0a;
+ break;
+ case DUK_ASC_LC_R:
+ cp = 0x0d;
+ break;
+ case DUK_ASC_LC_F:
+ cp = 0x0c;
+ break;
+ case DUK_ASC_LC_B:
+ cp = 0x08;
+ break;
case DUK_ASC_LC_U: {
- cp = duk__dec_decode_hex_escape(js_ctx, 4);
+ cp = duk__json_dec_decode_hex_escape(js_ctx, 4);
break;
}
#if defined(DUK_USE_JX)
case DUK_ASC_UC_U: {
if (js_ctx->flag_ext_custom) {
- cp = duk__dec_decode_hex_escape(js_ctx, 8);
+ cp = duk__json_dec_decode_hex_escape(js_ctx, 8);
} else {
- return 1; /* syntax error */
+ return 1; /* syntax error */
}
break;
}
case DUK_ASC_LC_X: {
if (js_ctx->flag_ext_custom) {
- cp = duk__dec_decode_hex_escape(js_ctx, 2);
+ cp = duk__json_dec_decode_hex_escape(js_ctx, 2);
} else {
- return 1; /* syntax error */
+ return 1; /* syntax error */
}
break;
}
-#endif /* DUK_USE_JX */
+#endif /* DUK_USE_JX */
default:
/* catches EOF (0x00) */
- return 1; /* syntax error */
+ return 1; /* syntax error */
}
- DUK_RAW_WRITE_XUTF8(*ext_p, cp);
+ DUK_RAW_WRITEINC_XUTF8(*ext_p, cp);
return 0;
}
-DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_string(duk_json_dec_ctx *js_ctx) {
duk_hthread *thr = js_ctx->thr;
duk_bufwriter_ctx bw_alloc;
duk_bufwriter_ctx *bw;
@@ -33725,7 +37784,7 @@ DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) {
/* Ensure space for 1:1 output plus one escape. */
q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, safe + DUK_UNICODE_MAX_XUTF8_LENGTH, q);
- p = js_ctx->p; /* temp copy, write back for next loop */
+ p = js_ctx->p; /* temp copy, write back for next loop */
for (;;) {
if (safe == 0) {
js_ctx->p = p;
@@ -33750,7 +37809,7 @@ DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) {
* quite slow but it's uncommon).
*/
js_ctx->p = p;
- if (duk__dec_string_escape(js_ctx, &q) != 0) {
+ if (duk__json_dec_string_escape(js_ctx, &q) != 0) {
goto syntax_error;
}
break;
@@ -33760,19 +37819,19 @@ DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) {
}
}
}
- found_quote:
-#else /* DUK_USE_JSON_DECSTRING_FASTPATH */
+found_quote:
+#else /* DUK_USE_JSON_DECSTRING_FASTPATH */
for (;;) {
duk_uint8_t x;
q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, DUK_UNICODE_MAX_XUTF8_LENGTH, q);
- x = duk__dec_get(js_ctx);
+ x = duk__json_dec_get(js_ctx);
if (x == DUK_ASC_DOUBLEQUOTE) {
break;
} else if (x == DUK_ASC_BACKSLASH) {
- if (duk__dec_string_escape(js_ctx, &q) != 0) {
+ if (duk__json_dec_string_escape(js_ctx, &q) != 0) {
goto syntax_error;
}
} else if (x < 0x20) {
@@ -33782,17 +37841,17 @@ DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) {
*q++ = (duk_uint8_t) x;
}
}
-#endif /* DUK_USE_JSON_DECSTRING_FASTPATH */
+#endif /* DUK_USE_JSON_DECSTRING_FASTPATH */
DUK_BW_SETPTR_AND_COMPACT(js_ctx->thr, bw, q);
- (void) duk_buffer_to_string(thr, -1); /* Safe if input string is safe. */
+ (void) duk_buffer_to_string(thr, -1); /* Safe if input string is safe. */
/* [ ... str ] */
return;
- syntax_error:
- duk__dec_syntax_error(js_ctx);
+syntax_error:
+ duk__json_dec_syntax_error(js_ctx);
DUK_UNREACHABLE();
}
@@ -33800,14 +37859,14 @@ DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) {
/* Decode a plain string consisting entirely of identifier characters.
* Used to parse plain keys (e.g. "foo: 123").
*/
-DUK_LOCAL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_plain_string(duk_json_dec_ctx *js_ctx) {
duk_hthread *thr = js_ctx->thr;
const duk_uint8_t *p;
duk_small_int_t x;
/* Caller has already eaten the first char so backtrack one byte. */
- js_ctx->p--; /* safe */
+ js_ctx->p--; /* safe */
p = js_ctx->p;
/* Here again we parse bytes, and non-ASCII UTF-8 will cause end of
@@ -33839,10 +37898,10 @@ DUK_LOCAL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx) {
/* [ ... str ] */
}
-#endif /* DUK_USE_JX */
+#endif /* DUK_USE_JX */
#if defined(DUK_USE_JX)
-DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_pointer(duk_json_dec_ctx *js_ctx) {
duk_hthread *thr = js_ctx->thr;
const duk_uint8_t *p;
duk_small_int_t x;
@@ -33882,20 +37941,20 @@ DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) {
voidptr = NULL;
(void) DUK_SSCANF((const char *) js_ctx->p, DUK_STR_FMT_PTR, &voidptr);
duk_push_pointer(thr, voidptr);
- js_ctx->p = p + 1; /* skip ')' */
+ js_ctx->p = p + 1; /* skip ')' */
/* [ ... ptr ] */
return;
- syntax_error:
- duk__dec_syntax_error(js_ctx);
+syntax_error:
+ duk__json_dec_syntax_error(js_ctx);
DUK_UNREACHABLE();
}
-#endif /* DUK_USE_JX */
+#endif /* DUK_USE_JX */
#if defined(DUK_USE_JX)
-DUK_LOCAL void duk__dec_buffer(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_buffer(duk_json_dec_ctx *js_ctx) {
duk_hthread *thr = js_ctx->thr;
const duk_uint8_t *p;
duk_uint8_t *buf;
@@ -33937,23 +37996,23 @@ DUK_LOCAL void duk__dec_buffer(duk_json_dec_ctx *js_ctx) {
src_len = (duk_size_t) (p - js_ctx->p);
buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_len);
DUK_ASSERT(buf != NULL);
- DUK_MEMCPY((void *) buf, (const void *) js_ctx->p, src_len);
+ duk_memcpy((void *) buf, (const void *) js_ctx->p, src_len);
duk_hex_decode(thr, -1);
- js_ctx->p = p + 1; /* skip '|' */
+ js_ctx->p = p + 1; /* skip '|' */
/* [ ... buf ] */
return;
- syntax_error:
- duk__dec_syntax_error(js_ctx);
+syntax_error:
+ duk__json_dec_syntax_error(js_ctx);
DUK_UNREACHABLE();
}
-#endif /* DUK_USE_JX */
+#endif /* DUK_USE_JX */
/* Parse a number, other than NaN or +/- Infinity */
-DUK_LOCAL void duk__dec_number(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_number(duk_json_dec_ctx *js_ctx) {
duk_hthread *thr = js_ctx->thr;
const duk_uint8_t *p_start;
const duk_uint8_t *p;
@@ -33973,66 +38032,67 @@ DUK_LOCAL void duk__dec_number(duk_json_dec_ctx *js_ctx) {
x = *p;
DUK_DDD(DUK_DDDPRINT("parse_number: p_start=%p, p=%p, p_end=%p, x=%ld",
- (const void *) p_start, (const void *) p,
- (const void *) js_ctx->p_end, (long) x));
+ (const void *) p_start,
+ (const void *) p,
+ (const void *) js_ctx->p_end,
+ (long) x));
#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
/* This fast path is pretty marginal in practice.
* XXX: candidate for removal.
*/
- DUK_ASSERT(duk__json_decnumber_lookup[0x00] == 0x00); /* end-of-input breaks */
+ DUK_ASSERT(duk__json_decnumber_lookup[0x00] == 0x00); /* end-of-input breaks */
if (duk__json_decnumber_lookup[x] == 0) {
break;
}
-#else /* DUK_USE_JSON_DECNUMBER_FASTPATH */
+#else /* DUK_USE_JSON_DECNUMBER_FASTPATH */
if (!((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
- (x == DUK_ASC_PERIOD || x == DUK_ASC_LC_E ||
- x == DUK_ASC_UC_E || x == DUK_ASC_MINUS || x == DUK_ASC_PLUS))) {
+ (x == DUK_ASC_PERIOD || x == DUK_ASC_LC_E || x == DUK_ASC_UC_E || x == DUK_ASC_MINUS || x == DUK_ASC_PLUS))) {
/* Plus sign must be accepted for positive exponents
* (e.g. '1.5e+2'). This clause catches NULs.
*/
break;
}
-#endif /* DUK_USE_JSON_DECNUMBER_FASTPATH */
- p++; /* safe, because matched (NUL causes a break) */
+#endif /* DUK_USE_JSON_DECNUMBER_FASTPATH */
+ p++; /* safe, because matched (NUL causes a break) */
}
js_ctx->p = p;
DUK_ASSERT(js_ctx->p > p_start);
duk_push_lstring(thr, (const char *) p_start, (duk_size_t) (p - p_start));
- s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
- DUK_S2N_FLAG_ALLOW_MINUS | /* but don't allow leading plus */
+ s2n_flags = DUK_S2N_FLAG_ALLOW_EXP | DUK_S2N_FLAG_ALLOW_MINUS | /* but don't allow leading plus */
DUK_S2N_FLAG_ALLOW_FRAC;
- DUK_DDD(DUK_DDDPRINT("parse_number: string before parsing: %!T",
- (duk_tval *) duk_get_tval(thr, -1)));
+ DUK_DDD(DUK_DDDPRINT("parse_number: string before parsing: %!T", (duk_tval *) duk_get_tval(thr, -1)));
duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
if (duk_is_nan(thr, -1)) {
- duk__dec_syntax_error(js_ctx);
+ duk__json_dec_syntax_error(js_ctx);
}
DUK_ASSERT(duk_is_number(thr, -1));
- DUK_DDD(DUK_DDDPRINT("parse_number: final number: %!T",
- (duk_tval *) duk_get_tval(thr, -1)));
+ DUK_DDD(DUK_DDDPRINT("parse_number: final number: %!T", (duk_tval *) duk_get_tval(thr, -1)));
/* [ ... num ] */
}
-DUK_LOCAL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_objarr_entry(duk_json_dec_ctx *js_ctx) {
duk_hthread *thr = js_ctx->thr;
duk_require_stack(thr, DUK_JSON_DEC_REQSTACK);
/* c recursion check */
- DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0); /* unsigned */
+ duk_native_stack_check(thr);
+
+ DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0); /* unsigned */
DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
- DUK_ERROR_RANGE(thr, DUK_STR_JSONDEC_RECLIMIT);
+ DUK_ERROR_RANGE(thr, DUK_STR_DEC_RECLIMIT);
+ DUK_WO_NORETURN(return;);
}
js_ctx->recursion_depth++;
}
-DUK_LOCAL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_objarr_exit(duk_json_dec_ctx *js_ctx) {
/* c recursion check */
DUK_ASSERT(js_ctx->recursion_depth > 0);
@@ -34040,14 +38100,14 @@ DUK_LOCAL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx) {
js_ctx->recursion_depth--;
}
-DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_object(duk_json_dec_ctx *js_ctx) {
duk_hthread *thr = js_ctx->thr;
- duk_int_t key_count; /* XXX: a "first" flag would suffice */
+ duk_int_t key_count; /* XXX: a "first" flag would suffice */
duk_uint8_t x;
DUK_DDD(DUK_DDDPRINT("parse_object"));
- duk__dec_objarr_entry(js_ctx);
+ duk__json_dec_objarr_entry(js_ctx);
duk_push_object(thr);
@@ -34055,17 +38115,18 @@ DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) {
key_count = 0;
for (;;) {
- x = duk__dec_get_nonwhite(js_ctx);
+ x = duk__json_dec_get_nonwhite(js_ctx);
DUK_DDD(DUK_DDDPRINT("parse_object: obj=%!T, x=%ld, key_count=%ld",
(duk_tval *) duk_get_tval(thr, -1),
- (long) x, (long) key_count));
+ (long) x,
+ (long) key_count));
/* handle comma and closing brace */
if (x == DUK_ASC_COMMA && key_count > 0) {
/* accept comma, expect new value */
- x = duk__dec_get_nonwhite(js_ctx);
+ x = duk__json_dec_get_nonwhite(js_ctx);
} else if (x == DUK_ASC_RCURLY) {
/* eat closing brace */
break;
@@ -34082,11 +38143,10 @@ DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) {
/* parse key and value */
if (x == DUK_ASC_DOUBLEQUOTE) {
- duk__dec_string(js_ctx);
+ duk__json_dec_string(js_ctx);
#if defined(DUK_USE_JX)
- } else if (js_ctx->flag_ext_custom &&
- duk_unicode_is_identifier_start((duk_codepoint_t) x)) {
- duk__dec_plain_string(js_ctx);
+ } else if (js_ctx->flag_ext_custom && duk_unicode_is_identifier_start((duk_codepoint_t) x)) {
+ duk__json_dec_plain_string(js_ctx);
#endif
} else {
goto syntax_error;
@@ -34094,12 +38154,12 @@ DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) {
/* [ ... obj key ] */
- x = duk__dec_get_nonwhite(js_ctx);
+ x = duk__json_dec_get_nonwhite(js_ctx);
if (x != DUK_ASC_COLON) {
goto syntax_error;
}
- duk__dec_value(js_ctx);
+ duk__json_dec_value(js_ctx);
/* [ ... obj key val ] */
@@ -34112,25 +38172,24 @@ DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) {
/* [ ... obj ] */
- DUK_DDD(DUK_DDDPRINT("parse_object: final object is %!T",
- (duk_tval *) duk_get_tval(thr, -1)));
+ DUK_DDD(DUK_DDDPRINT("parse_object: final object is %!T", (duk_tval *) duk_get_tval(thr, -1)));
- duk__dec_objarr_exit(js_ctx);
+ duk__json_dec_objarr_exit(js_ctx);
return;
- syntax_error:
- duk__dec_syntax_error(js_ctx);
+syntax_error:
+ duk__json_dec_syntax_error(js_ctx);
DUK_UNREACHABLE();
}
-DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_array(duk_json_dec_ctx *js_ctx) {
duk_hthread *thr = js_ctx->thr;
duk_uarridx_t arr_idx;
duk_uint8_t x;
DUK_DDD(DUK_DDDPRINT("parse_array"));
- duk__dec_objarr_entry(js_ctx);
+ duk__json_dec_objarr_entry(js_ctx);
duk_push_array(thr);
@@ -34138,11 +38197,12 @@ DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) {
arr_idx = 0;
for (;;) {
- x = duk__dec_get_nonwhite(js_ctx);
+ x = duk__json_dec_get_nonwhite(js_ctx);
DUK_DDD(DUK_DDDPRINT("parse_array: arr=%!T, x=%ld, arr_idx=%ld",
(duk_tval *) duk_get_tval(thr, -1),
- (long) x, (long) arr_idx));
+ (long) x,
+ (long) arr_idx));
/* handle comma and closing bracket */
@@ -34154,9 +38214,9 @@ DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) {
break;
} else if (arr_idx == 0) {
/* accept anything, expect first value (EOF will be
- * caught by duk__dec_value() below.
+ * caught by duk__json_dec_value() below.
*/
- js_ctx->p--; /* backtrack (safe) */
+ js_ctx->p--; /* backtrack (safe) */
} else {
/* catches EOF (NUL) and initial comma */
goto syntax_error;
@@ -34164,7 +38224,7 @@ DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) {
/* parse value */
- duk__dec_value(js_ctx);
+ duk__json_dec_value(js_ctx);
/* [ ... arr val ] */
@@ -34180,117 +38240,123 @@ DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) {
/* [ ... arr ] */
- DUK_DDD(DUK_DDDPRINT("parse_array: final array is %!T",
- (duk_tval *) duk_get_tval(thr, -1)));
+ DUK_DDD(DUK_DDDPRINT("parse_array: final array is %!T", (duk_tval *) duk_get_tval(thr, -1)));
- duk__dec_objarr_exit(js_ctx);
+ duk__json_dec_objarr_exit(js_ctx);
return;
- syntax_error:
- duk__dec_syntax_error(js_ctx);
+syntax_error:
+ duk__json_dec_syntax_error(js_ctx);
DUK_UNREACHABLE();
}
-DUK_LOCAL void duk__dec_value(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_value(duk_json_dec_ctx *js_ctx) {
duk_hthread *thr = js_ctx->thr;
duk_uint8_t x;
- x = duk__dec_get_nonwhite(js_ctx);
+ x = duk__json_dec_get_nonwhite(js_ctx);
DUK_DDD(DUK_DDDPRINT("parse_value: initial x=%ld", (long) x));
- /* Note: duk__dec_req_stridx() backtracks one char */
+ /* Note: duk__json_dec_req_stridx() backtracks one char */
if (x == DUK_ASC_DOUBLEQUOTE) {
- duk__dec_string(js_ctx);
+ duk__json_dec_string(js_ctx);
} else if ((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x == DUK_ASC_MINUS)) {
#if defined(DUK_USE_JX)
- if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__dec_peek(js_ctx) == DUK_ASC_UC_I) {
- duk__dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY); /* "-Infinity", '-' has been eaten */
+ if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__json_dec_peek(js_ctx) == DUK_ASC_UC_I) {
+ duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY); /* "-Infinity", '-' has been eaten */
duk_push_number(thr, -DUK_DOUBLE_INFINITY);
} else {
#else
- { /* unconditional block */
+ { /* unconditional block */
#endif
/* We already ate 'x', so backup one byte. */
- js_ctx->p--; /* safe */
- duk__dec_number(js_ctx);
+ js_ctx->p--; /* safe */
+ duk__json_dec_number(js_ctx);
}
} else if (x == DUK_ASC_LC_T) {
- duk__dec_req_stridx(js_ctx, DUK_STRIDX_TRUE);
+ duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_TRUE);
duk_push_true(thr);
} else if (x == DUK_ASC_LC_F) {
- duk__dec_req_stridx(js_ctx, DUK_STRIDX_FALSE);
+ duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_FALSE);
duk_push_false(thr);
} else if (x == DUK_ASC_LC_N) {
- duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_NULL);
+ duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_LC_NULL);
duk_push_null(thr);
#if defined(DUK_USE_JX)
} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LC_U) {
- duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_UNDEFINED);
+ duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_LC_UNDEFINED);
duk_push_undefined(thr);
} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_N) {
- duk__dec_req_stridx(js_ctx, DUK_STRIDX_NAN);
+ duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_NAN);
duk_push_nan(thr);
} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_I) {
- duk__dec_req_stridx(js_ctx, DUK_STRIDX_INFINITY);
+ duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_INFINITY);
duk_push_number(thr, DUK_DOUBLE_INFINITY);
} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LPAREN) {
- duk__dec_pointer(js_ctx);
+ duk__json_dec_pointer(js_ctx);
} else if (js_ctx->flag_ext_custom && x == DUK_ASC_PIPE) {
- duk__dec_buffer(js_ctx);
+ duk__json_dec_buffer(js_ctx);
#endif
} else if (x == DUK_ASC_LCURLY) {
- duk__dec_object(js_ctx);
+ duk__json_dec_object(js_ctx);
} else if (x == DUK_ASC_LBRACKET) {
- duk__dec_array(js_ctx);
+ duk__json_dec_array(js_ctx);
} else {
/* catches EOF (NUL) */
goto syntax_error;
}
- duk__dec_eat_white(js_ctx);
+ duk__json_dec_eat_white(js_ctx);
/* [ ... val ] */
return;
- syntax_error:
- duk__dec_syntax_error(js_ctx);
+syntax_error:
+ duk__json_dec_syntax_error(js_ctx);
DUK_UNREACHABLE();
}
-/* Recursive value reviver, implements the Walk() algorithm. No C recursion
- * check is done here because the initial parsing step will already ensure
- * there is a reasonable limit on C recursion depth and hence object depth.
+/* Recursive value reviver, implements the Walk() algorithm. The parsing
+ * step ensures there is a reasonable depth limit to the input. However,
+ * the reviver may create more depth by editing object or array entries, so
+ * we have both C recursion limit and native stack checks here.
*/
-DUK_LOCAL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
duk_hthread *thr = js_ctx->thr;
duk_hobject *h;
duk_uarridx_t i, arr_len;
+ duk__json_dec_objarr_entry(js_ctx);
+
DUK_DDD(DUK_DDDPRINT("walk: top=%ld, holder=%!T, name=%!T",
(long) duk_get_top(thr),
(duk_tval *) duk_get_tval(thr, -2),
(duk_tval *) duk_get_tval(thr, -1)));
duk_dup_top(thr);
- duk_get_prop(thr, -3); /* -> [ ... holder name val ] */
+ duk_get_prop(thr, -3); /* -> [ ... holder name val ] */
h = duk_get_hobject(thr, -1);
if (h != NULL) {
- if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
+ if (duk_js_isarray_hobject(h)) {
arr_len = (duk_uarridx_t) duk_get_length(thr, -1);
for (i = 0; i < arr_len; i++) {
/* [ ... holder name val ] */
DUK_DDD(DUK_DDDPRINT("walk: array, top=%ld, i=%ld, arr_len=%ld, holder=%!T, name=%!T, val=%!T",
- (long) duk_get_top(thr), (long) i, (long) arr_len,
- (duk_tval *) duk_get_tval(thr, -3), (duk_tval *) duk_get_tval(thr, -2),
+ (long) duk_get_top(thr),
+ (long) i,
+ (long) arr_len,
+ (duk_tval *) duk_get_tval(thr, -3),
+ (duk_tval *) duk_get_tval(thr, -2),
(duk_tval *) duk_get_tval(thr, -1)));
duk_dup_top(thr);
- (void) duk_push_uint_to_hstring(thr, (duk_uint_t) i); /* -> [ ... holder name val val ToString(i) ] */
- duk__dec_reviver_walk(js_ctx); /* -> [ ... holder name val new_elem ] */
+ (void) duk_push_uint_to_hstring(thr,
+ (duk_uint_t) i); /* -> [ ... holder name val val ToString(i) ] */
+ duk__json_dec_reviver_walk(js_ctx); /* -> [ ... holder name val new_elem ] */
if (duk_is_undefined(thr, -1)) {
duk_pop(thr);
@@ -34308,16 +38374,19 @@ DUK_LOCAL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
duk_enum(thr, -1, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);
while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
DUK_DDD(DUK_DDDPRINT("walk: object, top=%ld, holder=%!T, name=%!T, val=%!T, enum=%!iT, obj_key=%!T",
- (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -5),
- (duk_tval *) duk_get_tval(thr, -4), (duk_tval *) duk_get_tval(thr, -3),
- (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
+ (long) duk_get_top(thr),
+ (duk_tval *) duk_get_tval(thr, -5),
+ (duk_tval *) duk_get_tval(thr, -4),
+ (duk_tval *) duk_get_tval(thr, -3),
+ (duk_tval *) duk_get_tval(thr, -2),
+ (duk_tval *) duk_get_tval(thr, -1)));
/* [ ... holder name val enum obj_key ] */
duk_dup_m3(thr);
duk_dup_m2(thr);
/* [ ... holder name val enum obj_key val obj_key ] */
- duk__dec_reviver_walk(js_ctx);
+ duk__json_dec_reviver_walk(js_ctx);
/* [ ... holder name val enum obj_key new_elem ] */
if (duk_is_undefined(thr, -1)) {
@@ -34336,32 +38405,33 @@ DUK_LOCAL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
duk_put_prop(thr, -4);
}
}
- duk_pop(thr); /* pop enum */
+ duk_pop(thr); /* pop enum */
}
}
/* [ ... holder name val ] */
duk_dup(thr, js_ctx->idx_reviver);
- duk_insert(thr, -4); /* -> [ ... reviver holder name val ] */
- duk_call_method(thr, 2); /* -> [ ... res ] */
+ duk_insert(thr, -4); /* -> [ ... reviver holder name val ] */
+ duk_call_method(thr, 2); /* -> [ ... res ] */
- DUK_DDD(DUK_DDDPRINT("walk: top=%ld, result=%!T",
- (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -1)));
+ duk__json_dec_objarr_exit(js_ctx);
+
+ DUK_DDD(DUK_DDDPRINT("walk: top=%ld, result=%!T", (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -1)));
}
/*
* Stringify implementation.
*/
-#define DUK__EMIT_1(js_ctx,ch) duk__emit_1((js_ctx), (duk_uint_fast8_t) (ch))
-#define DUK__EMIT_2(js_ctx,ch1,ch2) duk__emit_2((js_ctx), (duk_uint_fast8_t) (ch1), (duk_uint_fast8_t) (ch2))
-#define DUK__EMIT_HSTR(js_ctx,h) duk__emit_hstring((js_ctx), (h))
+#define DUK__EMIT_1(js_ctx, ch) duk__emit_1((js_ctx), (duk_uint_fast8_t) (ch))
+#define DUK__EMIT_2(js_ctx, ch1, ch2) duk__emit_2((js_ctx), (duk_uint_fast8_t) (ch1), (duk_uint_fast8_t) (ch2))
+#define DUK__EMIT_HSTR(js_ctx, h) duk__emit_hstring((js_ctx), (h))
#if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
-#define DUK__EMIT_CSTR(js_ctx,p) duk__emit_cstring((js_ctx), (p))
+#define DUK__EMIT_CSTR(js_ctx, p) duk__emit_cstring((js_ctx), (p))
#endif
-#define DUK__EMIT_STRIDX(js_ctx,i) duk__emit_stridx((js_ctx), (i))
-#define DUK__UNEMIT_1(js_ctx) duk__unemit_1((js_ctx))
+#define DUK__EMIT_STRIDX(js_ctx, i) duk__emit_stridx((js_ctx), (i))
+#define DUK__UNEMIT_1(js_ctx) duk__unemit_1((js_ctx))
DUK_LOCAL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch) {
DUK_BW_WRITE_ENSURE_U8(js_ctx->thr, &js_ctx->bw, ch);
@@ -34396,10 +38466,8 @@ DUK_LOCAL void duk__unemit_1(duk_json_enc_ctx *js_ctx) {
DUK_BW_ADD_PTR(js_ctx->thr, &js_ctx->bw, -1);
}
-#define DUK__MKESC(nybbles,esc1,esc2) \
- (((duk_uint_fast32_t) (nybbles)) << 16) | \
- (((duk_uint_fast32_t) (esc1)) << 8) | \
- ((duk_uint_fast32_t) (esc2))
+#define DUK__MKESC(nybbles, esc1, esc2) \
+ (((duk_uint_fast32_t) (nybbles)) << 16) | (((duk_uint_fast32_t) (esc1)) << 8) | ((duk_uint_fast32_t) (esc2))
DUK_LOCAL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q) {
duk_uint_fast32_t tmp;
@@ -34424,7 +38492,7 @@ DUK_LOCAL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uin
}
} else
#endif
- if (DUK_LIKELY(cp < 0x10000UL)) {
+ if (DUK_LIKELY(cp < 0x10000UL)) {
tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);
} else {
#if defined(DUK_USE_JX)
@@ -34455,8 +38523,8 @@ DUK_LOCAL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uin
return q;
}
-DUK_LOCAL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) {
- const duk_int8_t *p, *p_start, *p_end; /* Note: intentionally signed. */
+DUK_LOCAL void duk__json_enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) {
+ const duk_int8_t *p, *p_start, *p_end; /* Note: intentionally signed. */
duk_size_t k_len;
duk_codepoint_t cp;
@@ -34497,8 +38565,8 @@ DUK_LOCAL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k)
return;
}
- quote_normally:
- duk__enc_quote_string(js_ctx, k);
+quote_normally:
+ duk__json_enc_quote_string(js_ctx, k);
}
/* The Quote(value) operation: quote a string.
@@ -34506,13 +38574,13 @@ DUK_LOCAL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k)
* Stack policy: [ ] -> [ ].
*/
-DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) {
+DUK_LOCAL void duk__json_enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) {
duk_hthread *thr = js_ctx->thr;
const duk_uint8_t *p, *p_start, *p_end, *p_now, *p_tmp;
duk_uint8_t *q;
- duk_ucodepoint_t cp; /* typed for duk_unicode_decode_xutf8() */
+ duk_ucodepoint_t cp; /* typed for duk_unicode_decode_xutf8() */
- DUK_DDD(DUK_DDDPRINT("duk__enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str));
+ DUK_DDD(DUK_DDDPRINT("duk__json_enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str));
DUK_ASSERT(h_str != NULL);
p_start = DUK_HSTRING_GET_DATA(h_str);
@@ -34529,8 +38597,7 @@ DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_st
duk_size_t left, now, space;
left = (duk_size_t) (p_end - p);
- now = (left > DUK__JSON_ENCSTR_CHUNKSIZE ?
- DUK__JSON_ENCSTR_CHUNKSIZE : left);
+ now = (left > DUK__JSON_ENCSTR_CHUNKSIZE ? DUK__JSON_ENCSTR_CHUNKSIZE : left);
/* Maximum expansion per input byte is 6:
* - invalid UTF-8 byte causes "\uXXXX" to be emitted (6/1 = 6).
@@ -34566,7 +38633,7 @@ DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_st
p--;
/* slow path is shared */
-#else /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
+#else /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
cp = *p;
if (DUK_LIKELY(cp <= 0x7f)) {
@@ -34597,16 +38664,16 @@ DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_st
}
} else {
/* slow path is shared */
-#endif /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
+#endif /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
/* slow path decode */
/* If XUTF-8 decoding fails, treat the offending byte as a codepoint directly
* and go forward one byte. This is of course very lossy, but allows some kind
* of output to be produced even for internal strings which don't conform to
- * XUTF-8. All standard Ecmascript strings are always CESU-8, so this behavior
- * does not violate the Ecmascript specification. The behavior is applied to
- * all modes, including Ecmascript standard JSON. Because the current XUTF-8
+ * XUTF-8. All standard ECMAScript strings are always CESU-8, so this behavior
+ * does not violate the ECMAScript specification. The behavior is applied to
+ * all modes, including ECMAScript standard JSON. Because the current XUTF-8
* decoding is not very strict, this behavior only really affects initial bytes
* and truncated codepoints.
*
@@ -34629,7 +38696,7 @@ DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_st
q = duk__emit_esc_auto_fast(js_ctx, cp, q);
} else {
/* as is */
- DUK_RAW_WRITE_XUTF8(q, cp);
+ DUK_RAW_WRITEINC_XUTF8(q, cp);
}
}
}
@@ -34643,7 +38710,7 @@ DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_st
/* Encode a double (checked by caller) from stack top. Stack top may be
* replaced by serialized string but is not popped (caller does that).
*/
-DUK_LOCAL void duk__enc_double(duk_json_enc_ctx *js_ctx) {
+DUK_LOCAL void duk__json_enc_double(duk_json_enc_ctx *js_ctx) {
duk_hthread *thr;
duk_tval *tv;
duk_double_t d;
@@ -34673,11 +38740,10 @@ DUK_LOCAL void duk__enc_double(duk_json_enc_ctx *js_ctx) {
/* Negative zero needs special handling in JX/JC because
* it would otherwise serialize to '0', not '-0'.
*/
- if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 &&
- (js_ctx->flag_ext_custom_or_compatible))) {
- duk_push_hstring_stridx(thr, DUK_STRIDX_MINUS_ZERO); /* '-0' */
+ if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 && (js_ctx->flag_ext_custom_or_compatible))) {
+ duk_push_hstring_stridx(thr, DUK_STRIDX_MINUS_ZERO); /* '-0' */
} else
-#endif /* DUK_USE_JX || DUK_USE_JC */
+#endif /* DUK_USE_JX || DUK_USE_JC */
{
n2s_flags = 0;
/* [ ... number ] -> [ ... string ] */
@@ -34689,8 +38755,7 @@ DUK_LOCAL void duk__enc_double(duk_json_enc_ctx *js_ctx) {
}
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
- if (!(js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
- DUK_JSON_FLAG_EXT_COMPATIBLE))) {
+ if (!(js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE))) {
stridx = DUK_STRIDX_LC_NULL;
} else if (c == DUK_FP_NAN) {
stridx = js_ctx->stridx_custom_nan;
@@ -34707,7 +38772,7 @@ DUK_LOCAL void duk__enc_double(duk_json_enc_ctx *js_ctx) {
#if defined(DUK_USE_FASTINT)
/* Encode a fastint from duk_tval ptr, no value stack effects. */
-DUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
+DUK_LOCAL void duk__json_enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
duk_int64_t v;
/* Fastint range is signed 48-bit so longest value is -2^47 = -140737488355328
@@ -34732,7 +38797,7 @@ DUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
#if defined(DUK_USE_HEX_FASTPATH)
-DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
+DUK_LOCAL duk_uint8_t *duk__json_enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
duk_uint8_t *q;
duk_uint16_t *q16;
duk_small_uint_t x;
@@ -34743,7 +38808,7 @@ DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size
/* Unlike in duk_hex_encode() 'dst' is not necessarily aligned by 2.
* For platforms where unaligned accesses are not allowed, shift 'dst'
- * ahead by 1 byte to get alignment and then DUK_MEMMOVE() the result
+ * ahead by 1 byte to get alignment and then duk_memmove() the result
* in place. The faster encoding loop makes up the difference.
* There's always space for one extra byte because a terminator always
* follows the hex data and that's been accounted for by the caller.
@@ -34776,7 +38841,7 @@ DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size
#if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
if (shift_dst) {
q--;
- DUK_MEMMOVE((void *) dst, (const void *) (dst + 1), 2 * len_safe);
+ duk_memmove((void *) dst, (const void *) (dst + 1), 2 * len_safe);
DUK_ASSERT(dst + 2 * len_safe == q);
}
#endif
@@ -34789,8 +38854,8 @@ DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size
return q;
}
-#else /* DUK_USE_HEX_FASTPATH */
-DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
+#else /* DUK_USE_HEX_FASTPATH */
+DUK_LOCAL duk_uint8_t *duk__json_enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
const duk_uint8_t *p;
const duk_uint8_t *p_end;
duk_uint8_t *q;
@@ -34807,16 +38872,16 @@ DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size
return q;
}
-#endif /* DUK_USE_HEX_FASTPATH */
+#endif /* DUK_USE_HEX_FASTPATH */
-DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) {
+DUK_LOCAL void duk__json_enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) {
duk_hthread *thr;
duk_uint8_t *q;
duk_size_t space;
thr = js_ctx->thr;
- DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); /* caller checks */
+ DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); /* caller checks */
DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
/* Buffer values are encoded in (lowercase) hex to make the
@@ -34832,7 +38897,7 @@ DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_d
/* Note: space must cater for both JX and JC. */
space = 9 + buf_len * 2 + 2;
DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7ffffffeUL);
- DUK_ASSERT((space - 2) / 2 >= buf_len); /* overflow not possible, buffer limits */
+ DUK_ASSERT((space - 2) / 2 >= buf_len); /* overflow not possible, buffer limits */
q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
@@ -34841,7 +38906,7 @@ DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_d
#if defined(DUK_USE_JX)
{
*q++ = DUK_ASC_PIPE;
- q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
+ q = duk__json_enc_buffer_data_hex(buf_data, buf_len, q);
*q++ = DUK_ASC_PIPE;
}
@@ -34852,9 +38917,9 @@ DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_d
#if defined(DUK_USE_JC)
{
DUK_ASSERT(js_ctx->flag_ext_compatible);
- DUK_MEMCPY((void *) q, (const void *) "{\"_buf\":\"", 9); /* len: 9 */
+ duk_memcpy((void *) q, (const void *) "{\"_buf\":\"", 9); /* len: 9 */
q += 9;
- q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
+ q = duk__json_enc_buffer_data_hex(buf_data, buf_len, q);
*q++ = DUK_ASC_DOUBLEQUOTE;
*q++ = DUK_ASC_RCURLY;
}
@@ -34863,15 +38928,15 @@ DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_d
DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
}
-DUK_LOCAL void duk__enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
- duk__enc_buffer_data(js_ctx,
- (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h),
- (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
+DUK_LOCAL void duk__json_enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
+ duk__json_enc_buffer_data(js_ctx,
+ (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h),
+ (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
}
-#endif /* DUK_USE_JX || DUK_USE_JC */
+#endif /* DUK_USE_JX || DUK_USE_JC */
#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
-DUK_LOCAL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
+DUK_LOCAL void duk__json_enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
duk_size_t i, n;
const duk_uint8_t *buf;
duk_uint8_t *q;
@@ -34895,7 +38960,7 @@ DUK_LOCAL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuff
buf = (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h);
if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
for (i = 0; i < n; i++) {
- duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth + 1);
+ duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth + 1);
q = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, 32);
q += DUK_SPRINTF((char *) q, "\"%lu\": %u,", (unsigned long) i, (unsigned int) buf[i]);
DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);
@@ -34908,24 +38973,24 @@ DUK_LOCAL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuff
}
DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);
}
- DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
+ DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
- duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
+ duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
}
DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
}
-#endif /* DUK_USE_JSON_STRINGIFY_FASTPATH */
+#endif /* DUK_USE_JSON_STRINGIFY_FASTPATH */
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
-DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {
- char buf[64]; /* XXX: how to figure correct size? */
+DUK_LOCAL void duk__json_enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {
+ char buf[64]; /* XXX: how to figure correct size? */
const char *fmt;
- DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); /* caller checks */
+ DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); /* caller checks */
DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
- DUK_MEMZERO(buf, sizeof(buf));
+ duk_memzero(buf, sizeof(buf));
/* The #if defined() clutter here needs to handle the three
* cases: (1) JX+JC, (2) JX only, (3) JC only.
@@ -34949,52 +39014,52 @@ DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {
#endif
/* When ptr == NULL, the format argument is unused. */
- DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr); /* must not truncate */
+ DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr); /* must not truncate */
DUK__EMIT_CSTR(js_ctx, buf);
}
-#endif /* DUK_USE_JX || DUK_USE_JC */
+#endif /* DUK_USE_JX || DUK_USE_JC */
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
-DUK_LOCAL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj) {
- DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+DUK_LOCAL void duk__json_enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj) {
+ DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
if (h_bufobj->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
} else {
/* Handle both full and partial slice (as long as covered). */
- duk__enc_buffer_data(js_ctx,
- (duk_uint8_t *) DUK_HBUFOBJ_GET_SLICE_BASE(js_ctx->thr->heap, h_bufobj),
- (duk_size_t) h_bufobj->length);
+ duk__json_enc_buffer_data(js_ctx,
+ (duk_uint8_t *) DUK_HBUFOBJ_GET_SLICE_BASE(js_ctx->thr->heap, h_bufobj),
+ (duk_size_t) h_bufobj->length);
}
}
-#endif /* DUK_USE_JX || DUK_USE_JC */
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_JX || DUK_USE_JC */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/* Indent helper. Calling code relies on js_ctx->recursion_depth also being
* directly related to indent depth.
*/
#if defined(DUK_USE_PREFER_SIZE)
-DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
+DUK_LOCAL void duk__json_enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
DUK_ASSERT(js_ctx->h_gap != NULL);
- DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0); /* caller guarantees */
+ DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0); /* caller guarantees */
DUK__EMIT_1(js_ctx, 0x0a);
while (depth-- > 0) {
DUK__EMIT_HSTR(js_ctx, js_ctx->h_gap);
}
}
-#else /* DUK_USE_PREFER_SIZE */
-DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
+#else /* DUK_USE_PREFER_SIZE */
+DUK_LOCAL void duk__json_enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
const duk_uint8_t *gap_data;
duk_size_t gap_len;
- duk_size_t avail_bytes; /* bytes of indent available for copying */
- duk_size_t need_bytes; /* bytes of indent still needed */
+ duk_size_t avail_bytes; /* bytes of indent available for copying */
+ duk_size_t need_bytes; /* bytes of indent still needed */
duk_uint8_t *p_start;
duk_uint8_t *p;
DUK_ASSERT(js_ctx->h_gap != NULL);
- DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0); /* caller guarantees */
+ DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0); /* caller guarantees */
DUK__EMIT_1(js_ctx, 0x0a);
if (DUK_UNLIKELY(depth == 0)) {
@@ -35015,43 +39080,44 @@ DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t dept
p = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, need_bytes);
p_start = p;
- DUK_MEMCPY((void *) p, (const void *) gap_data, (size_t) gap_len);
+ duk_memcpy((void *) p, (const void *) gap_data, (size_t) gap_len);
p += gap_len;
avail_bytes = gap_len;
DUK_ASSERT(need_bytes >= gap_len);
need_bytes -= gap_len;
while (need_bytes >= avail_bytes) {
- DUK_MEMCPY((void *) p, (const void *) p_start, (size_t) avail_bytes);
+ duk_memcpy((void *) p, (const void *) p_start, (size_t) avail_bytes);
p += avail_bytes;
need_bytes -= avail_bytes;
avail_bytes <<= 1;
}
- DUK_ASSERT(need_bytes < avail_bytes); /* need_bytes may be zero */
- DUK_MEMCPY((void *) p, (const void *) p_start, (size_t) need_bytes);
+ DUK_ASSERT(need_bytes < avail_bytes); /* need_bytes may be zero */
+ duk_memcpy((void *) p, (const void *) p_start, (size_t) need_bytes);
p += need_bytes;
/*avail_bytes += need_bytes*/
DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, p);
}
-#endif /* DUK_USE_PREFER_SIZE */
+#endif /* DUK_USE_PREFER_SIZE */
/* Shared entry handling for object/array serialization. */
-DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
+DUK_LOCAL void duk__json_enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
duk_hthread *thr = js_ctx->thr;
duk_hobject *h_target;
duk_uint_fast32_t i, n;
*entry_top = duk_get_top(thr);
+ duk_native_stack_check(thr);
duk_require_stack(thr, DUK_JSON_ENC_REQSTACK);
/* Loop check using a hybrid approach: a fixed-size visited[] array
* with overflow in a loop check object.
*/
- h_target = duk_known_hobject(thr, -1); /* object or array */
+ h_target = duk_known_hobject(thr, -1); /* object or array */
n = js_ctx->recursion_depth;
if (DUK_UNLIKELY(n > DUK_JSON_ENC_LOOPARRAY)) {
@@ -35061,35 +39127,39 @@ DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_
if (DUK_UNLIKELY(js_ctx->visiting[i] == h_target)) {
DUK_DD(DUK_DDPRINT("slow path loop detect"));
DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT);
+ DUK_WO_NORETURN(return;);
}
}
if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
js_ctx->visiting[js_ctx->recursion_depth] = h_target;
} else {
duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target);
- duk_dup_top(thr); /* -> [ ... voidp voidp ] */
+ duk_dup_top(thr); /* -> [ ... voidp voidp ] */
if (duk_has_prop(thr, js_ctx->idx_loop)) {
DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT);
+ DUK_WO_NORETURN(return;);
}
- duk_push_true(thr); /* -> [ ... voidp true ] */
- duk_put_prop(thr, js_ctx->idx_loop); /* -> [ ... ] */
+ duk_push_true(thr); /* -> [ ... voidp true ] */
+ duk_put_prop(thr, js_ctx->idx_loop); /* -> [ ... ] */
}
/* C recursion check. */
- DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0); /* unsigned */
DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
- DUK_ERROR_RANGE(thr, DUK_STR_JSONENC_RECLIMIT);
+ DUK_ERROR_RANGE(thr, DUK_STR_ENC_RECLIMIT);
+ DUK_WO_NORETURN(return;);
}
js_ctx->recursion_depth++;
DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
- (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));
+ (long) duk_get_top(thr),
+ (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));
}
/* Shared exit handling for object/array serialization. */
-DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
+DUK_LOCAL void duk__json_enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
duk_hthread *thr = js_ctx->thr;
duk_hobject *h_target;
@@ -35101,27 +39171,28 @@ DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_t
/* Loop check. */
- h_target = duk_known_hobject(thr, *entry_top - 1); /* original target at entry_top - 1 */
+ h_target = duk_known_hobject(thr, *entry_top - 1); /* original target at entry_top - 1 */
if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
/* Previous entry was inside visited[], nothing to do. */
} else {
duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target);
- duk_del_prop(thr, js_ctx->idx_loop); /* -> [ ... ] */
+ duk_del_prop(thr, js_ctx->idx_loop); /* -> [ ... ] */
}
/* Restore stack top after unbalanced code paths. */
duk_set_top(thr, *entry_top);
DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
- (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));
+ (long) duk_get_top(thr),
+ (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));
}
/* The JO(value) operation: encode object.
*
* Stack policy: [ object ] -> [ object ].
*/
-DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
+DUK_LOCAL void duk__json_enc_object(duk_json_enc_ctx *js_ctx) {
duk_hthread *thr = js_ctx->thr;
duk_hstring *h_key;
duk_idx_t entry_top;
@@ -35131,9 +39202,9 @@ DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
duk_uarridx_t arr_len, i;
duk_size_t prev_size;
- DUK_DDD(DUK_DDDPRINT("duk__enc_object: obj=%!T", (duk_tval *) duk_get_tval(thr, -1)));
+ DUK_DDD(DUK_DDDPRINT("duk__json_enc_object: obj=%!T", (duk_tval *) duk_get_tval(thr, -1)));
- duk__enc_objarr_entry(js_ctx, &entry_top);
+ duk__json_enc_objarr_entry(js_ctx, &entry_top);
idx_obj = entry_top - 1;
@@ -35142,13 +39213,14 @@ DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
} else {
/* XXX: would be nice to enumerate an object at specified index */
duk_dup(thr, idx_obj);
- (void) duk_hobject_get_enumerated_keys(thr, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/); /* [ ... target ] -> [ ... target keys ] */
+ (void) duk_hobject_get_enumerated_keys(
+ thr,
+ DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/); /* [ ... target ] -> [ ... target keys ] */
idx_keys = duk_require_normalize_index(thr, -1);
/* leave stack unbalanced on purpose */
}
- DUK_DDD(DUK_DDDPRINT("idx_keys=%ld, h_keys=%!T",
- (long) idx_keys, (duk_tval *) duk_get_tval(thr, idx_keys)));
+ DUK_DDD(DUK_DDDPRINT("idx_keys=%ld, h_keys=%!T", (long) idx_keys, (duk_tval *) duk_get_tval(thr, idx_keys)));
/* Steps 8-10 have been merged to avoid a "partial" variable. */
@@ -35163,7 +39235,7 @@ DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
arr_len = (duk_uarridx_t) duk_get_length(thr, idx_keys);
emitted = 0;
for (i = 0; i < arr_len; i++) {
- duk_get_prop_index(thr, idx_keys, i); /* -> [ ... key ] */
+ duk_get_prop_index(thr, idx_keys, i); /* -> [ ... key ] */
DUK_DDD(DUK_DDDPRINT("object property loop: holder=%!T, key=%!T",
(duk_tval *) duk_get_tval(thr, idx_obj),
@@ -35171,21 +39243,21 @@ DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
h_key = duk_known_hstring(thr, -1);
DUK_ASSERT(h_key != NULL);
- DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(h_key)); /* proplist filtering; enum options */
+ DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(h_key)); /* proplist filtering; enum options */
prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
- duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
- duk__enc_key_autoquote(js_ctx, h_key);
+ duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
+ duk__json_enc_key_autoquote(js_ctx, h_key);
DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
} else {
- duk__enc_key_autoquote(js_ctx, h_key);
+ duk__json_enc_key_autoquote(js_ctx, h_key);
DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
}
/* [ ... key ] */
- if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_obj) == 0)) {
+ if (DUK_UNLIKELY(duk__json_enc_value(js_ctx, idx_obj) == 0)) {
/* Value would yield 'undefined', so skip key altogether.
* Side effects have already happened.
*/
@@ -35200,15 +39272,15 @@ DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
if (emitted) {
DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
- DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
+ DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
DUK_ASSERT(js_ctx->recursion_depth >= 1);
- duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
+ duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
}
}
DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
- duk__enc_objarr_exit(js_ctx, &entry_top);
+ duk__json_enc_objarr_exit(js_ctx, &entry_top);
DUK_ASSERT_TOP(thr, entry_top);
}
@@ -35217,17 +39289,16 @@ DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
*
* Stack policy: [ array ] -> [ array ].
*/
-DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) {
+DUK_LOCAL void duk__json_enc_array(duk_json_enc_ctx *js_ctx) {
duk_hthread *thr = js_ctx->thr;
duk_idx_t entry_top;
duk_idx_t idx_arr;
duk_bool_t emitted;
duk_uarridx_t i, arr_len;
- DUK_DDD(DUK_DDDPRINT("duk__enc_array: array=%!T",
- (duk_tval *) duk_get_tval(thr, -1)));
+ DUK_DDD(DUK_DDDPRINT("duk__json_enc_array: array=%!T", (duk_tval *) duk_get_tval(thr, -1)));
- duk__enc_objarr_entry(js_ctx, &entry_top);
+ duk__json_enc_objarr_entry(js_ctx, &entry_top);
idx_arr = entry_top - 1;
@@ -35240,18 +39311,19 @@ DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) {
for (i = 0; i < arr_len; i++) {
DUK_DDD(DUK_DDDPRINT("array entry loop: array=%!T, index=%ld, arr_len=%ld",
(duk_tval *) duk_get_tval(thr, idx_arr),
- (long) i, (long) arr_len));
+ (long) i,
+ (long) arr_len));
if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
DUK_ASSERT(js_ctx->recursion_depth >= 1);
- duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
+ duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
}
- (void) duk_push_uint_to_hstring(thr, (duk_uint_t) i); /* -> [ ... key ] */
+ (void) duk_push_uint_to_hstring(thr, (duk_uint_t) i); /* -> [ ... key ] */
/* [ ... key ] */
- if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_arr) == 0)) {
+ if (DUK_UNLIKELY(duk__json_enc_value(js_ctx, idx_arr) == 0)) {
/* Value would normally be omitted, replace with 'null'. */
DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
} else {
@@ -35266,15 +39338,15 @@ DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) {
if (emitted) {
DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
- DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
+ DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
DUK_ASSERT(js_ctx->recursion_depth >= 1);
- duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
+ duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
}
}
DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
- duk__enc_objarr_exit(js_ctx, &entry_top);
+ duk__json_enc_objarr_exit(js_ctx, &entry_top);
DUK_ASSERT_TOP(thr, entry_top);
}
@@ -35283,22 +39355,23 @@ DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) {
*
* Stack policy: [ ... key ] -> [ ... ]
*/
-DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) {
+DUK_LOCAL duk_bool_t duk__json_enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) {
duk_hthread *thr = js_ctx->thr;
duk_tval *tv;
duk_tval *tv_holder;
duk_tval *tv_key;
duk_small_int_t c;
- DUK_DDD(DUK_DDDPRINT("duk__enc_value: idx_holder=%ld, holder=%!T, key=%!T",
- (long) idx_holder, (duk_tval *) duk_get_tval(thr, idx_holder),
+ DUK_DDD(DUK_DDDPRINT("duk__json_enc_value: idx_holder=%ld, holder=%!T, key=%!T",
+ (long) idx_holder,
+ (duk_tval *) duk_get_tval(thr, idx_holder),
(duk_tval *) duk_get_tval(thr, -1)));
tv_holder = DUK_GET_TVAL_POSIDX(thr, idx_holder);
DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_holder));
tv_key = DUK_GET_TVAL_NEGIDX(thr, -1);
DUK_ASSERT(DUK_TVAL_IS_STRING(tv_key));
- DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING(tv_key))); /* Caller responsible. */
+ DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING(tv_key))); /* Caller responsible. */
(void) duk_hobject_getprop(thr, tv_holder, tv_key);
/* -> [ ... key val ] */
@@ -35310,19 +39383,17 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold
* number won't invoke the .toJSON() method. However, lightfuncs and
* plain buffers mimic objects so we check for their .toJSON() method.
*/
- if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
- DUK_TYPE_MASK_LIGHTFUNC |
- DUK_TYPE_MASK_BUFFER)) {
+ if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_JSON);
- if (duk_is_callable(thr, -1)) { /* toJSON() can also be a lightfunc */
+ if (duk_is_callable(thr, -1)) { /* toJSON() can also be a lightfunc */
DUK_DDD(DUK_DDDPRINT("value is object, has callable toJSON() -> call it"));
/* XXX: duk_dup_unvalidated(thr, -2) etc. */
- duk_dup_m2(thr); /* -> [ ... key val toJSON val ] */
- duk_dup_m4(thr); /* -> [ ... key val toJSON val key ] */
- duk_call_method(thr, 1); /* -> [ ... key val val' ] */
- duk_remove_m2(thr); /* -> [ ... key val' ] */
+ duk_dup_m2(thr); /* -> [ ... key val toJSON val ] */
+ duk_dup_m4(thr); /* -> [ ... key val toJSON val key ] */
+ duk_call_method(thr, 1); /* -> [ ... key val val' ] */
+ duk_remove_m2(thr); /* -> [ ... key val' ] */
} else {
- duk_pop(thr); /* -> [ ... key val ] */
+ duk_pop(thr); /* -> [ ... key val ] */
}
}
@@ -35333,12 +39404,12 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold
if (js_ctx->h_replacer) {
/* XXX: Here a "slice copy" would be useful. */
DUK_DDD(DUK_DDDPRINT("replacer is set, call replacer"));
- duk_push_hobject(thr, js_ctx->h_replacer); /* -> [ ... key val replacer ] */
- duk_dup(thr, idx_holder); /* -> [ ... key val replacer holder ] */
- duk_dup_m4(thr); /* -> [ ... key val replacer holder key ] */
- duk_dup_m4(thr); /* -> [ ... key val replacer holder key val ] */
- duk_call_method(thr, 2); /* -> [ ... key val val' ] */
- duk_remove_m2(thr); /* -> [ ... key val' ] */
+ duk_push_hobject(thr, js_ctx->h_replacer); /* -> [ ... key val replacer ] */
+ duk_dup(thr, idx_holder); /* -> [ ... key val replacer holder ] */
+ duk_dup_m4(thr); /* -> [ ... key val replacer holder key ] */
+ duk_dup_m4(thr); /* -> [ ... key val replacer holder key val ] */
+ duk_call_method(thr, 2); /* -> [ ... key val val' ] */
+ duk_remove_m2(thr); /* -> [ ... key val' ] */
}
/* [ ... key val ] */
@@ -35354,18 +39425,17 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
- if (DUK_HOBJECT_IS_BUFOBJ(h) &&
- js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE)) {
+ if (DUK_HOBJECT_IS_BUFOBJ(h) && js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE)) {
/* With JX/JC a bufferobject gets serialized specially. */
duk_hbufobj *h_bufobj;
h_bufobj = (duk_hbufobj *) h;
- DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
- duk__enc_bufobj(js_ctx, h_bufobj);
+ DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
+ duk__json_enc_bufobj(js_ctx, h_bufobj);
goto pop2_emitted;
}
/* Otherwise bufferobjects get serialized as normal objects. */
-#endif /* JX || JC */
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* JX || JC */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
switch (c) {
case DUK_HOBJECT_CLASS_NUMBER: {
@@ -35390,7 +39460,7 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold
#endif
case DUK_HOBJECT_CLASS_BOOLEAN: {
DUK_DDD(DUK_DDDPRINT("value is a Boolean/Buffer/Pointer object -> get internal value"));
- duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
+ duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
duk_remove_m2(thr);
break;
}
@@ -35405,8 +39475,7 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold
DUK_ASSERT(h != NULL);
if (DUK_HOBJECT_IS_CALLABLE(h)) {
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
- if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
- DUK_JSON_FLAG_EXT_COMPATIBLE)) {
+ if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE)) {
/* We only get here when doing non-standard JSON encoding */
DUK_DDD(DUK_DDDPRINT("-> function allowed, serialize to custom format"));
DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);
@@ -35416,13 +39485,13 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold
DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
goto pop2_undef;
}
-#else /* DUK_USE_JX || DUK_USE_JC */
+#else /* DUK_USE_JX || DUK_USE_JC */
DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
goto pop2_undef;
-#endif /* DUK_USE_JX || DUK_USE_JC */
+#endif /* DUK_USE_JX || DUK_USE_JC */
}
}
- } /* end switch */
+ } /* end switch */
}
/* [ ... key val ] */
@@ -35449,24 +39518,23 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold
break;
}
case DUK_TAG_BOOLEAN: {
- DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
- DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
+ DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ? DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
break;
}
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
/* When JX/JC not in use, the type mask above will avoid this case if needed. */
case DUK_TAG_POINTER: {
- duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
+ duk__json_enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
break;
}
-#endif /* DUK_USE_JX || DUK_USE_JC */
+#endif /* DUK_USE_JX || DUK_USE_JC */
case DUK_TAG_STRING: {
duk_hstring *h = DUK_TVAL_GET_STRING(tv);
DUK_ASSERT(h != NULL);
if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
goto pop2_undef;
}
- duk__enc_quote_string(js_ctx, h);
+ duk__json_enc_quote_string(js_ctx, h);
break;
}
case DUK_TAG_OBJECT: {
@@ -35478,10 +39546,10 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold
*/
DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE(h));
- if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
- duk__enc_array(js_ctx);
+ if (duk_js_isarray_hobject(h)) {
+ duk__json_enc_array(js_ctx);
} else {
- duk__enc_object(js_ctx);
+ duk__json_enc_object(js_ctx);
}
break;
}
@@ -35494,7 +39562,7 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold
case DUK_TAG_BUFFER: {
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
if (js_ctx->flag_ext_custom_or_compatible) {
- duk__enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
+ duk__json_enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
break;
}
#endif
@@ -35503,7 +39571,7 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold
* to handle realloc side effects correctly.
*/
duk_to_object(thr, -1);
- duk__enc_object(js_ctx);
+ duk__json_enc_object(js_ctx);
break;
}
case DUK_TAG_LIGHTFUNC: {
@@ -35522,7 +39590,7 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold
/* Number serialization has a significant impact relative to
* other fast path code, so careful fast path for fastints.
*/
- duk__enc_fastint_tval(js_ctx, tv);
+ duk__json_enc_fastint_tval(js_ctx, tv);
break;
#endif
default: {
@@ -35532,24 +39600,24 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold
/* XXX: A fast path for usual integers would be useful when
* fastint support is not enabled.
*/
- duk__enc_double(js_ctx);
+ duk__json_enc_double(js_ctx);
break;
}
}
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
- pop2_emitted:
+pop2_emitted:
#endif
duk_pop_2(thr); /* [ ... key val ] -> [ ... ] */
- return 1; /* emitted */
+ return 1; /* emitted */
- pop2_undef:
- duk_pop_2(thr); /* [ ... key val ] -> [ ... ] */
- return 0; /* not emitted */
+pop2_undef:
+ duk_pop_2(thr); /* [ ... key val ] -> [ ... ] */
+ return 0; /* not emitted */
}
/* E5 Section 15.12.3, main algorithm, step 4.b.ii steps 1-4. */
-DUK_LOCAL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv) {
+DUK_LOCAL duk_bool_t duk__json_enc_allow_into_proplist(duk_tval *tv) {
duk_small_int_t c;
/* XXX: some kind of external internal type checker?
@@ -35621,8 +39689,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
break;
}
case DUK_TAG_BOOLEAN: {
- DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
- DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
+ DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ? DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
break;
}
case DUK_TAG_STRING: {
@@ -35632,15 +39699,14 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
goto emit_undefined;
}
- duk__enc_quote_string(js_ctx, h);
+ duk__json_enc_quote_string(js_ctx, h);
break;
}
case DUK_TAG_OBJECT: {
duk_hobject *obj;
duk_tval *tv_val;
duk_bool_t emitted = 0;
- duk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef,
- c_func, c_bufobj, c_object, c_abort;
+ duk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef, c_func, c_bufobj, c_object, c_abort;
/* For objects JSON.stringify() only looks for own, enumerable
* properties which is nice for the fast path here.
@@ -35667,23 +39733,25 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
obj = DUK_TVAL_GET_OBJECT(tv);
DUK_ASSERT(obj != NULL);
- DUK_ASSERT_HOBJECT_VALID(obj);
+ DUK_HOBJECT_ASSERT_VALID(obj);
/* Once recursion depth is increased, exit path must decrease
* it (though it's OK to abort the fast path).
*/
- DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0); /* unsigned */
DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
DUK_DD(DUK_DDPRINT("fast path recursion limit"));
- DUK_ERROR_RANGE(js_ctx->thr, DUK_STR_JSONDEC_RECLIMIT);
+ DUK_ERROR_RANGE(js_ctx->thr, DUK_STR_DEC_RECLIMIT);
+ DUK_WO_NORETURN(return 0;);
}
for (i = 0, n = (duk_uint_fast32_t) js_ctx->recursion_depth; i < n; i++) {
if (DUK_UNLIKELY(js_ctx->visiting[i] == obj)) {
DUK_DD(DUK_DDPRINT("fast path loop detect"));
DUK_ERROR_TYPE(js_ctx->thr, DUK_STR_CYCLIC_INPUT);
+ DUK_WO_NORETURN(return 0;);
}
}
@@ -35723,28 +39791,23 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
if (js_ctx->flag_ext_custom_or_compatible) {
c_all = DUK_HOBJECT_CMASK_ALL;
c_array = DUK_HOBJECT_CMASK_ARRAY;
- c_unbox = DUK_HOBJECT_CMASK_NUMBER |
- DUK_HOBJECT_CMASK_STRING |
- DUK_HOBJECT_CMASK_BOOLEAN |
- DUK_HOBJECT_CMASK_POINTER; /* Symbols are not unboxed. */
+ c_unbox = DUK_HOBJECT_CMASK_NUMBER | DUK_HOBJECT_CMASK_STRING | DUK_HOBJECT_CMASK_BOOLEAN |
+ DUK_HOBJECT_CMASK_POINTER; /* Symbols are not unboxed. */
c_func = DUK_HOBJECT_CMASK_FUNCTION;
c_bufobj = DUK_HOBJECT_CMASK_ALL_BUFOBJS;
c_undef = 0;
c_abort = 0;
c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);
- }
- else
+ } else
#endif
{
c_all = DUK_HOBJECT_CMASK_ALL;
c_array = DUK_HOBJECT_CMASK_ARRAY;
- c_unbox = DUK_HOBJECT_CMASK_NUMBER |
- DUK_HOBJECT_CMASK_STRING |
- DUK_HOBJECT_CMASK_BOOLEAN; /* Symbols are not unboxed. */
+ c_unbox = DUK_HOBJECT_CMASK_NUMBER | DUK_HOBJECT_CMASK_STRING |
+ DUK_HOBJECT_CMASK_BOOLEAN; /* Symbols are not unboxed. */
c_func = 0;
c_bufobj = 0;
- c_undef = DUK_HOBJECT_CMASK_FUNCTION |
- DUK_HOBJECT_CMASK_POINTER;
+ c_undef = DUK_HOBJECT_CMASK_FUNCTION | DUK_HOBJECT_CMASK_POINTER;
/* As the fast path doesn't currently properly support
* duk_hbufobj virtual properties, abort fast path if
* we encounter them in plain JSON mode.
@@ -35802,11 +39865,11 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
- duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
- duk__enc_key_autoquote(js_ctx, k);
+ duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
+ duk__json_enc_key_autoquote(js_ctx, k);
DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
} else {
- duk__enc_key_autoquote(js_ctx, k);
+ duk__json_enc_key_autoquote(js_ctx, k);
DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
}
@@ -35826,10 +39889,10 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
if (emitted) {
DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
- DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
+ DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
DUK_ASSERT(js_ctx->recursion_depth >= 1);
- duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
+ duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
}
}
DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
@@ -35857,7 +39920,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
duk_bool_t has_inherited;
if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
- duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
+ duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
}
if (DUK_LIKELY(i < asize)) {
@@ -35896,17 +39959,17 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
#endif
/* fall through */
- elem_done:
+ elem_done:
DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
emitted = 1;
}
if (emitted) {
DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
- DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
+ DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
DUK_ASSERT(js_ctx->recursion_depth >= 1);
- duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
+ duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
}
}
DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
@@ -35915,7 +39978,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
* automatic unboxing. Rely on internal value being
* sane (to avoid infinite recursion).
*/
- DUK_ASSERT((c_bit & DUK_HOBJECT_CMASK_SYMBOL) == 0); /* Symbols are not unboxed. */
+ DUK_ASSERT((c_bit & DUK_HOBJECT_CMASK_SYMBOL) == 0); /* Symbols are not unboxed. */
#if 1
/* The code below is incorrect if .toString() or .valueOf() have
@@ -35925,7 +39988,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
* Unimplemented for now, abort fast path for boxed values.
*/
goto abort_fastpath;
-#else /* disabled */
+#else /* disabled */
/* Disabled until fixed, see above. */
duk_tval *tv_internal;
@@ -35933,22 +39996,20 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
tv_internal = duk_hobject_get_internal_value_tval_ptr(js_ctx->thr->heap, obj);
DUK_ASSERT(tv_internal != NULL);
- DUK_ASSERT(DUK_TVAL_IS_STRING(tv_internal) ||
- DUK_TVAL_IS_NUMBER(tv_internal) ||
- DUK_TVAL_IS_BOOLEAN(tv_internal) ||
- DUK_TVAL_IS_POINTER(tv_internal));
+ DUK_ASSERT(DUK_TVAL_IS_STRING(tv_internal) || DUK_TVAL_IS_NUMBER(tv_internal) ||
+ DUK_TVAL_IS_BOOLEAN(tv_internal) || DUK_TVAL_IS_POINTER(tv_internal));
tv = tv_internal;
DUK_ASSERT(js_ctx->recursion_depth > 0);
- js_ctx->recursion_depth--; /* required to keep recursion depth correct */
+ js_ctx->recursion_depth--; /* required to keep recursion depth correct */
goto restart_match;
-#endif /* disabled */
+#endif /* disabled */
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
} else if (c_bit & c_func) {
DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
} else if (c_bit & c_bufobj) {
- duk__enc_bufobj(js_ctx, (duk_hbufobj *) obj);
+ duk__json_enc_bufobj(js_ctx, (duk_hbufobj *) obj);
#endif
#endif
} else if (c_bit & c_abort) {
@@ -35988,7 +40049,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
if (js_ctx->flag_ext_custom_or_compatible) {
- duk__enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
+ duk__json_enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
break;
}
#endif
@@ -35996,13 +40057,13 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
/* Plain buffers mimic Uint8Arrays, and have enumerable index
* properties.
*/
- duk__enc_buffer_json_fastpath(js_ctx, DUK_TVAL_GET_BUFFER(tv));
+ duk__json_enc_buffer_json_fastpath(js_ctx, DUK_TVAL_GET_BUFFER(tv));
break;
}
case DUK_TAG_POINTER: {
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
if (js_ctx->flag_ext_custom_or_compatible) {
- duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
+ duk__json_enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
break;
} else {
goto emit_undefined;
@@ -36024,7 +40085,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
/* Number serialization has a significant impact relative to
* other fast path code, so careful fast path for fastints.
*/
- duk__enc_fastint_tval(js_ctx, tv);
+ duk__json_enc_fastint_tval(js_ctx, tv);
break;
}
#endif
@@ -36037,7 +40098,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
/* XXX: Stack discipline is annoying, could be changed in numconv. */
duk_push_tval(js_ctx->thr, tv);
- duk__enc_double(js_ctx);
+ duk__json_enc_double(js_ctx);
duk_pop(js_ctx->thr);
#if 0
@@ -36055,16 +40116,16 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
#endif
}
}
- return 1; /* not undefined */
+ return 1; /* not undefined */
- emit_undefined:
- return 0; /* value was undefined/unsupported */
+emit_undefined:
+ return 0; /* value was undefined/unsupported */
- abort_fastpath:
+abort_fastpath:
/* Error message doesn't matter: the error is ignored anyway. */
DUK_DD(DUK_DDPRINT("aborting fast path"));
DUK_ERROR_INTERNAL(js_ctx->thr);
- return 0; /* unreachable */
+ DUK_WO_NORETURN(return 0;);
}
DUK_LOCAL duk_ret_t duk__json_stringify_fast(duk_hthread *thr, void *udata) {
@@ -36080,22 +40141,19 @@ DUK_LOCAL duk_ret_t duk__json_stringify_fast(duk_hthread *thr, void *udata) {
tv = DUK_GET_TVAL_NEGIDX(thr, -1);
if (duk__json_stringify_fast_value(js_ctx, tv) == 0) {
DUK_DD(DUK_DDPRINT("top level value not supported, fail fast path"));
- DUK_DCERROR_TYPE_INVALID_ARGS(thr); /* Error message is ignored, so doesn't matter. */
+ DUK_DCERROR_TYPE_INVALID_ARGS(thr); /* Error message is ignored, so doesn't matter. */
}
return 0;
}
-#endif /* DUK_USE_JSON_STRINGIFY_FASTPATH */
+#endif /* DUK_USE_JSON_STRINGIFY_FASTPATH */
/*
* Top level wrappers
*/
DUK_INTERNAL
-void duk_bi_json_parse_helper(duk_hthread *thr,
- duk_idx_t idx_value,
- duk_idx_t idx_reviver,
- duk_small_uint_t flags) {
+void duk_bi_json_parse_helper(duk_hthread *thr, duk_idx_t idx_value, duk_idx_t idx_reviver, duk_small_uint_t flags) {
duk_json_dec_ctx js_ctx_alloc;
duk_json_dec_ctx *js_ctx = &js_ctx_alloc;
duk_hstring *h_text;
@@ -36113,7 +40171,7 @@ void duk_bi_json_parse_helper(duk_hthread *thr,
(unsigned long) flags,
(long) duk_get_top(thr)));
- DUK_MEMZERO(&js_ctx_alloc, sizeof(js_ctx_alloc));
+ duk_memzero(&js_ctx_alloc, sizeof(js_ctx_alloc));
js_ctx->thr = thr;
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
/* nothing now */
@@ -36136,7 +40194,7 @@ void duk_bi_json_parse_helper(duk_hthread *thr,
js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
#endif
- h_text = duk_to_hstring(thr, idx_value); /* coerce in-place; rejects Symbols */
+ h_text = duk_to_hstring(thr, idx_value); /* coerce in-place; rejects Symbols */
DUK_ASSERT(h_text != NULL);
/* JSON parsing code is allowed to read [p_start,p_end]: p_end is
@@ -36145,40 +40203,41 @@ void duk_bi_json_parse_helper(duk_hthread *thr,
*/
js_ctx->p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text);
js_ctx->p = js_ctx->p_start;
- js_ctx->p_end = ((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) +
- DUK_HSTRING_GET_BYTELEN(h_text);
+ js_ctx->p_end = ((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) + DUK_HSTRING_GET_BYTELEN(h_text);
DUK_ASSERT(*(js_ctx->p_end) == 0x00);
- duk__dec_value(js_ctx); /* -> [ ... value ] */
+ duk__json_dec_value(js_ctx); /* -> [ ... value ] */
+ DUK_ASSERT(js_ctx->recursion_depth == 0);
- /* Trailing whitespace has been eaten by duk__dec_value(), so if
+ /* Trailing whitespace has been eaten by duk__json_dec_value(), so if
* we're not at end of input here, it's a SyntaxError.
*/
if (js_ctx->p != js_ctx->p_end) {
- duk__dec_syntax_error(js_ctx);
+ duk__json_dec_syntax_error(js_ctx);
}
if (duk_is_callable(thr, idx_reviver)) {
- DUK_DDD(DUK_DDDPRINT("applying reviver: %!T",
- (duk_tval *) duk_get_tval(thr, idx_reviver)));
+ DUK_DDD(DUK_DDDPRINT("applying reviver: %!T", (duk_tval *) duk_get_tval(thr, idx_reviver)));
js_ctx->idx_reviver = idx_reviver;
duk_push_object(thr);
- duk_dup_m2(thr); /* -> [ ... val root val ] */
- duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_EMPTY_STRING); /* default attrs ok */
- duk_push_hstring_stridx(thr, DUK_STRIDX_EMPTY_STRING); /* -> [ ... val root "" ] */
+ duk_dup_m2(thr); /* -> [ ... val root val ] */
+ duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_EMPTY_STRING); /* default attrs ok */
+ duk_push_hstring_stridx(thr, DUK_STRIDX_EMPTY_STRING); /* -> [ ... val root "" ] */
DUK_DDD(DUK_DDDPRINT("start reviver walk, root=%!T, name=%!T",
(duk_tval *) duk_get_tval(thr, -2),
(duk_tval *) duk_get_tval(thr, -1)));
- duk__dec_reviver_walk(js_ctx); /* [ ... val root "" ] -> [ ... val val' ] */
- duk_remove_m2(thr); /* -> [ ... val' ] */
+ DUK_ASSERT(js_ctx->recursion_depth == 0);
+ duk__json_dec_reviver_walk(js_ctx); /* [ ... val root "" ] -> [ ... val val' ] */
+ DUK_ASSERT(js_ctx->recursion_depth == 0);
+ duk_remove_m2(thr); /* -> [ ... val' ] */
} else {
- DUK_DDD(DUK_DDDPRINT("reviver does not exist or is not callable: %!T",
- (duk_tval *) duk_get_tval(thr, idx_reviver)));
+ DUK_DDD(
+ DUK_DDDPRINT("reviver does not exist or is not callable: %!T", (duk_tval *) duk_get_tval(thr, idx_reviver)));
}
/* Final result is at stack top. */
@@ -36223,7 +40282,7 @@ void duk_bi_json_stringify_helper(duk_hthread *thr,
* Context init
*/
- DUK_MEMZERO(&js_ctx_alloc, sizeof(js_ctx_alloc));
+ duk_memzero(&js_ctx_alloc, sizeof(js_ctx_alloc));
js_ctx->thr = thr;
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
js_ctx->h_replacer = NULL;
@@ -36252,7 +40311,7 @@ void duk_bi_json_stringify_helper(duk_hthread *thr,
* combinations properly.
*/
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
- js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_NULL; /* standard JSON; array gaps */
+ js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_NULL; /* standard JSON; array gaps */
#if defined(DUK_USE_JX)
if (flags & DUK_JSON_FLAG_EXT_CUSTOM) {
js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_UNDEFINED;
@@ -36260,41 +40319,35 @@ void duk_bi_json_stringify_helper(duk_hthread *thr,
js_ctx->stridx_custom_neginf = DUK_STRIDX_MINUS_INFINITY;
js_ctx->stridx_custom_posinf = DUK_STRIDX_INFINITY;
js_ctx->stridx_custom_function =
- (flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES) ?
- DUK_STRIDX_JSON_EXT_FUNCTION2 :
- DUK_STRIDX_JSON_EXT_FUNCTION1;
+ (flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES) ? DUK_STRIDX_JSON_EXT_FUNCTION2 : DUK_STRIDX_JSON_EXT_FUNCTION1;
}
-#endif /* DUK_USE_JX */
+#endif /* DUK_USE_JX */
#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
else
-#endif /* DUK_USE_JX && DUK_USE_JC */
+#endif /* DUK_USE_JX && DUK_USE_JC */
#if defined(DUK_USE_JC)
- if (js_ctx->flags & DUK_JSON_FLAG_EXT_COMPATIBLE) {
+ if (js_ctx->flags & DUK_JSON_FLAG_EXT_COMPATIBLE) {
js_ctx->stridx_custom_undefined = DUK_STRIDX_JSON_EXT_UNDEFINED;
js_ctx->stridx_custom_nan = DUK_STRIDX_JSON_EXT_NAN;
js_ctx->stridx_custom_neginf = DUK_STRIDX_JSON_EXT_NEGINF;
js_ctx->stridx_custom_posinf = DUK_STRIDX_JSON_EXT_POSINF;
js_ctx->stridx_custom_function = DUK_STRIDX_JSON_EXT_FUNCTION1;
}
-#endif /* DUK_USE_JC */
-#endif /* DUK_USE_JX || DUK_USE_JC */
+#endif /* DUK_USE_JC */
+#endif /* DUK_USE_JX || DUK_USE_JC */
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
- if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
- DUK_JSON_FLAG_EXT_COMPATIBLE)) {
- DUK_ASSERT(js_ctx->mask_for_undefined == 0); /* already zero */
- }
- else
-#endif /* DUK_USE_JX || DUK_USE_JC */
+ if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE)) {
+ DUK_ASSERT(js_ctx->mask_for_undefined == 0); /* already zero */
+ } else
+#endif /* DUK_USE_JX || DUK_USE_JC */
{
/* Plain buffer is treated like ArrayBuffer and serialized.
* Lightfuncs are treated like objects, but JSON explicitly
* skips serializing Function objects so we can just reject
* lightfuncs here.
*/
- js_ctx->mask_for_undefined = DUK_TYPE_MASK_UNDEFINED |
- DUK_TYPE_MASK_POINTER |
- DUK_TYPE_MASK_LIGHTFUNC;
+ js_ctx->mask_for_undefined = DUK_TYPE_MASK_UNDEFINED | DUK_TYPE_MASK_POINTER | DUK_TYPE_MASK_LIGHTFUNC;
}
DUK_BW_INIT_PUSHBUF(thr, &js_ctx->bw, DUK__JSON_STRINGIFY_BUFSIZE);
@@ -36312,7 +40365,7 @@ void duk_bi_json_stringify_helper(duk_hthread *thr,
if (h != NULL) {
if (DUK_HOBJECT_IS_CALLABLE(h)) {
js_ctx->h_replacer = h;
- } else if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
+ } else if (duk_js_isarray_hobject(h)) {
/* Here the specification requires correct array index enumeration
* which is a bit tricky for sparse arrays (it is handled by the
* enum setup code). We now enumerate ancestors too, although the
@@ -36322,20 +40375,19 @@ void duk_bi_json_stringify_helper(duk_hthread *thr,
duk_uarridx_t plist_idx = 0;
duk_small_uint_t enum_flags;
- js_ctx->idx_proplist = duk_push_array(thr); /* XXX: array internal? */
+ js_ctx->idx_proplist = duk_push_bare_array(thr);
- enum_flags = DUK_ENUM_ARRAY_INDICES_ONLY |
- DUK_ENUM_SORT_ARRAY_INDICES; /* expensive flag */
+ enum_flags = DUK_ENUM_ARRAY_INDICES_ONLY | DUK_ENUM_SORT_ARRAY_INDICES; /* expensive flag */
duk_enum(thr, idx_replacer, enum_flags);
while (duk_next(thr, -1 /*enum_index*/, 1 /*get_value*/)) {
/* [ ... proplist enum_obj key val ] */
- if (duk__enc_allow_into_proplist(duk_get_tval(thr, -1))) {
+ if (duk__json_enc_allow_into_proplist(duk_get_tval(thr, -1))) {
/* XXX: duplicates should be eliminated here */
DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> accept",
(duk_tval *) duk_get_tval(thr, -2),
(duk_tval *) duk_get_tval(thr, -1)));
- duk_to_string(thr, -1); /* extra coercion of strings is OK */
- duk_put_prop_index(thr, -4, plist_idx); /* -> [ ... proplist enum_obj key ] */
+ duk_to_string(thr, -1); /* extra coercion of strings is OK */
+ duk_put_prop_index(thr, -4, plist_idx); /* -> [ ... proplist enum_obj key ] */
plist_idx++;
duk_pop(thr);
} else {
@@ -36344,8 +40396,8 @@ void duk_bi_json_stringify_helper(duk_hthread *thr,
(duk_tval *) duk_get_tval(thr, -1)));
duk_pop_2(thr);
}
- }
- duk_pop(thr); /* pop enum */
+ }
+ duk_pop(thr); /* pop enum */
/* [ ... proplist ] */
}
@@ -36371,10 +40423,9 @@ void duk_bi_json_stringify_helper(duk_hthread *thr,
duk_small_int_t nspace;
/* spaces[] must be static to allow initializer with old compilers like BCC */
static const char spaces[10] = {
- DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
- DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
- DUK_ASC_SPACE, DUK_ASC_SPACE
- }; /* XXX: helper */
+ DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
+ DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE
+ }; /* XXX: helper */
/* ToInteger() coercion; NaN -> 0, infinities are clamped to 0 and 10 */
nspace = (duk_small_int_t) duk_to_int_clamped(thr, idx_space, 0 /*minval*/, 10 /*maxval*/);
@@ -36385,7 +40436,7 @@ void duk_bi_json_stringify_helper(duk_hthread *thr,
DUK_ASSERT(js_ctx->h_gap != NULL);
} else if (duk_is_string_notsymbol(thr, idx_space)) {
duk_dup(thr, idx_space);
- duk_substring(thr, -1, 0, 10); /* clamp to 10 chars */
+ duk_substring(thr, -1, 0, 10); /* clamp to 10 chars */
js_ctx->h_gap = duk_known_hstring(thr, -1);
} else {
/* nop */
@@ -36409,8 +40460,8 @@ void duk_bi_json_stringify_helper(duk_hthread *thr,
*/
#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
- if (js_ctx->h_replacer == NULL && /* replacer is a mutation risk */
- js_ctx->idx_proplist == -1) { /* proplist is very rare */
+ if (js_ctx->h_replacer == NULL && /* replacer is a mutation risk */
+ js_ctx->idx_proplist == -1) { /* proplist is very rare */
duk_int_t pcall_rc;
duk_small_uint_t prev_ms_base_flags;
@@ -36435,10 +40486,9 @@ void duk_bi_json_stringify_helper(duk_hthread *thr,
/* Must prevent finalizers which may have arbitrary side effects. */
prev_ms_base_flags = thr->heap->ms_base_flags;
- thr->heap->ms_base_flags |=
- DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* Avoid attempt to compact any objects. */
- thr->heap->pf_prevent_count++; /* Prevent finalizers. */
- DUK_ASSERT(thr->heap->pf_prevent_count != 0); /* Wrap. */
+ thr->heap->ms_base_flags |= DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* Avoid attempt to compact any objects. */
+ thr->heap->pf_prevent_count++; /* Prevent finalizers. */
+ DUK_ASSERT(thr->heap->pf_prevent_count != 0); /* Wrap. */
pcall_rc = duk_safe_call(thr, duk__json_stringify_fast, (void *) js_ctx /*udata*/, 1 /*nargs*/, 0 /*nret*/);
@@ -36489,7 +40539,7 @@ void duk_bi_json_stringify_helper(duk_hthread *thr,
js_ctx->recursion_limit = DUK_USE_JSON_ENC_RECLIMIT;
DUK_ASSERT(js_ctx->recursion_depth == 0);
- if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_holder) == 0)) { /* [ ... holder key ] -> [ ... holder ] */
+ if (DUK_UNLIKELY(duk__json_enc_value(js_ctx, idx_holder) == 0)) { /* [ ... holder key ] -> [ ... holder ] */
/* Result is undefined. */
duk_push_undefined(thr);
} else {
@@ -36511,7 +40561,7 @@ void duk_bi_json_stringify_helper(duk_hthread *thr,
*/
#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
- replace_finished:
+replace_finished:
#endif
duk_replace(thr, entry_top);
duk_set_top(thr, entry_top + 1);
@@ -36535,25 +40585,18 @@ void duk_bi_json_stringify_helper(duk_hthread *thr,
*/
DUK_INTERNAL duk_ret_t duk_bi_json_object_parse(duk_hthread *thr) {
- duk_bi_json_parse_helper(thr,
- 0 /*idx_value*/,
- 1 /*idx_replacer*/,
- 0 /*flags*/);
+ duk_bi_json_parse_helper(thr, 0 /*idx_value*/, 1 /*idx_replacer*/, 0 /*flags*/);
return 1;
}
DUK_INTERNAL duk_ret_t duk_bi_json_object_stringify(duk_hthread *thr) {
- duk_bi_json_stringify_helper(thr,
- 0 /*idx_value*/,
- 1 /*idx_replacer*/,
- 2 /*idx_space*/,
- 0 /*flags*/);
+ duk_bi_json_stringify_helper(thr, 0 /*idx_value*/, 1 /*idx_replacer*/, 2 /*idx_space*/, 0 /*flags*/);
return 1;
}
-#endif /* DUK_USE_JSON_BUILTIN */
+#endif /* DUK_USE_JSON_BUILTIN */
-#endif /* DUK_USE_JSON_SUPPORT */
+#endif /* DUK_USE_JSON_SUPPORT */
/* automatic undefs */
#undef DUK__EMIT_1
@@ -36621,9 +40664,9 @@ DUK_LOCAL duk_ret_t duk__math_minmax(duk_hthread *thr, duk_double_t initial, duk
DUK_LOCAL double duk__fmin_fixed(double x, double y) {
/* fmin() with args -0 and +0 is not guaranteed to return
- * -0 as Ecmascript requires.
+ * -0 as ECMAScript requires.
*/
- if (x == 0 && y == 0) {
+ if (duk_double_equals(x, 0.0) && duk_double_equals(y, 0.0)) {
duk_double_union du1, du2;
du1.d = x;
du2.d = y;
@@ -36648,9 +40691,9 @@ DUK_LOCAL double duk__fmin_fixed(double x, double y) {
DUK_LOCAL double duk__fmax_fixed(double x, double y) {
/* fmax() with args -0 and +0 is not guaranteed to return
- * +0 as Ecmascript requires.
+ * +0 as ECMAScript requires.
*/
- if (x == 0 && y == 0) {
+ if (duk_double_equals(x, 0.0) && duk_double_equals(y, 0.0)) {
if (DUK_SIGNBIT(x) == 0 || DUK_SIGNBIT(y) == 0) {
return +0.0;
} else {
@@ -36711,7 +40754,7 @@ DUK_LOCAL double duk__trunc(double x) {
return x >= 0.0 ? DUK_FLOOR(x) : DUK_CEIL(x);
#endif
}
-#endif /* DUK_USE_ES6 */
+#endif /* DUK_USE_ES6 */
DUK_LOCAL double duk__round_fixed(double x) {
/* Numbers half-way between integers must be rounded towards +Infinity,
@@ -36817,59 +40860,32 @@ DUK_LOCAL double duk__atan2_fixed(double x, double y) {
}
#else
/* Some ISO C assumptions. */
- DUK_ASSERT(DUK_ATAN2(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY) == 0.7853981633974483);
- DUK_ASSERT(DUK_ATAN2(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY) == -0.7853981633974483);
- DUK_ASSERT(DUK_ATAN2(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY) == 2.356194490192345);
- DUK_ASSERT(DUK_ATAN2(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY) == -2.356194490192345);
+
+ DUK_ASSERT(duk_double_equals(DUK_ATAN2(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY), 0.7853981633974483));
+ DUK_ASSERT(duk_double_equals(DUK_ATAN2(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY), -0.7853981633974483));
+ DUK_ASSERT(duk_double_equals(DUK_ATAN2(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY), 2.356194490192345));
+ DUK_ASSERT(duk_double_equals(DUK_ATAN2(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY), -2.356194490192345));
#endif
return DUK_ATAN2(x, y);
}
-#endif /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
+#endif /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
/* order must match constants in genbuiltins.py */
DUK_LOCAL const duk__one_arg_func duk__one_arg_funcs[] = {
#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
- duk__fabs,
- duk__acos,
- duk__asin,
- duk__atan,
- duk__ceil,
- duk__cos,
- duk__exp,
- duk__floor,
- duk__log,
- duk__round_fixed,
- duk__sin,
- duk__sqrt,
- duk__tan,
+ duk__fabs, duk__acos, duk__asin, duk__atan, duk__ceil, duk__cos, duk__exp,
+ duk__floor, duk__log, duk__round_fixed, duk__sin, duk__sqrt, duk__tan,
#if defined(DUK_USE_ES6)
- duk__cbrt,
- duk__log2,
- duk__log10,
- duk__trunc
-#endif
-#else /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
- DUK_FABS,
- DUK_ACOS,
- DUK_ASIN,
- DUK_ATAN,
- DUK_CEIL,
- DUK_COS,
- DUK_EXP,
- DUK_FLOOR,
- DUK_LOG,
- duk__round_fixed,
- DUK_SIN,
- DUK_SQRT,
- DUK_TAN,
+ duk__cbrt, duk__log2, duk__log10, duk__trunc
+#endif
+#else /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
+ DUK_FABS, DUK_ACOS, DUK_ASIN, DUK_ATAN, DUK_CEIL, DUK_COS, DUK_EXP,
+ DUK_FLOOR, DUK_LOG, duk__round_fixed, DUK_SIN, DUK_SQRT, DUK_TAN,
#if defined(DUK_USE_ES6)
- duk__cbrt,
- duk__log2,
- duk__log10,
- duk__trunc
+ duk__cbrt, duk__log2, duk__log10, duk__trunc
#endif
-#endif /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
+#endif /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
};
/* order must match constants in genbuiltins.py */
@@ -36904,7 +40920,7 @@ DUK_INTERNAL duk_ret_t duk_bi_math_object_twoarg_shared(duk_hthread *thr) {
DUK_ASSERT(fun_idx >= 0);
DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__two_arg_funcs) / sizeof(duk__two_arg_func)));
- arg1 = duk_to_number(thr, 0); /* explicit ordered evaluation to match coercion semantics */
+ arg1 = duk_to_number(thr, 0); /* explicit ordered evaluation to match coercion semantics */
arg2 = duk_to_number(thr, 1);
fun = duk__two_arg_funcs[fun_idx];
duk_push_number(thr, (duk_double_t) fun((double) arg1, (double) arg2));
@@ -36920,7 +40936,7 @@ DUK_INTERNAL duk_ret_t duk_bi_math_object_min(duk_hthread *thr) {
}
DUK_INTERNAL duk_ret_t duk_bi_math_object_random(duk_hthread *thr) {
- duk_push_number(thr, (duk_double_t) DUK_UTIL_GET_RANDOM_DOUBLE(thr));
+ duk_push_number(thr, (duk_double_t) duk_util_get_random_double(thr));
return 1;
}
@@ -36960,13 +40976,13 @@ DUK_INTERNAL duk_ret_t duk_bi_math_object_hypot(duk_hthread *thr) {
}
/* Early return cases. */
- if (max == DUK_DOUBLE_INFINITY) {
+ if (duk_double_equals(max, DUK_DOUBLE_INFINITY)) {
duk_push_number(thr, DUK_DOUBLE_INFINITY);
return 1;
} else if (found_nan) {
duk_push_number(thr, DUK_DOUBLE_NAN);
return 1;
- } else if (max == 0.0) {
+ } else if (duk_double_equals(max, 0.0)) {
duk_push_number(thr, 0.0);
/* Otherwise we'd divide by zero. */
return 1;
@@ -36990,7 +41006,7 @@ DUK_INTERNAL duk_ret_t duk_bi_math_object_hypot(duk_hthread *thr) {
duk_push_number(thr, (duk_double_t) DUK_SQRT(sum) * max);
return 1;
}
-#endif /* DUK_USE_ES6 */
+#endif /* DUK_USE_ES6 */
#if defined(DUK_USE_ES6)
DUK_INTERNAL duk_ret_t duk_bi_math_object_sign(duk_hthread *thr) {
@@ -36999,16 +41015,16 @@ DUK_INTERNAL duk_ret_t duk_bi_math_object_sign(duk_hthread *thr) {
d = duk_to_number(thr, 0);
if (duk_double_is_nan(d)) {
DUK_ASSERT(duk_is_nan(thr, -1));
- return 1; /* NaN input -> return NaN */
+ return 1; /* NaN input -> return NaN */
}
- if (d == 0.0) {
+ if (duk_double_equals(d, 0.0)) {
/* Zero sign kept, i.e. -0 -> -0, +0 -> +0. */
return 1;
}
duk_push_int(thr, (d > 0.0 ? 1 : -1));
return 1;
}
-#endif /* DUK_USE_ES6 */
+#endif /* DUK_USE_ES6 */
#if defined(DUK_USE_ES6)
DUK_INTERNAL duk_ret_t duk_bi_math_object_clz32(duk_hthread *thr) {
@@ -37028,7 +41044,7 @@ DUK_INTERNAL duk_ret_t duk_bi_math_object_clz32(duk_hthread *thr) {
DUK_ASSERT(i <= 32);
duk_push_uint(thr, i);
return 1;
-#else /* DUK_USE_PREFER_SIZE */
+#else /* DUK_USE_PREFER_SIZE */
i = 0;
x = duk_to_uint32(thr, 0);
if (x & 0xffff0000UL) {
@@ -37064,9 +41080,9 @@ DUK_INTERNAL duk_ret_t duk_bi_math_object_clz32(duk_hthread *thr) {
DUK_ASSERT(i <= 32);
duk_push_uint(thr, i);
return 1;
-#endif /* DUK_USE_PREFER_SIZE */
+#endif /* DUK_USE_PREFER_SIZE */
}
-#endif /* DUK_USE_ES6 */
+#endif /* DUK_USE_ES6 */
#if defined(DUK_USE_ES6)
DUK_INTERNAL duk_ret_t duk_bi_math_object_imul(duk_hthread *thr) {
@@ -37083,9 +41099,9 @@ DUK_INTERNAL duk_ret_t duk_bi_math_object_imul(duk_hthread *thr) {
duk_push_i32(thr, (duk_int32_t) z);
return 1;
}
-#endif /* DUK_USE_ES6 */
+#endif /* DUK_USE_ES6 */
-#endif /* DUK_USE_MATH_BUILTIN */
+#endif /* DUK_USE_MATH_BUILTIN */
/*
* Number built-ins
*/
@@ -37107,18 +41123,19 @@ DUK_LOCAL duk_double_t duk__push_this_number_plain(duk_hthread *thr) {
goto done;
}
h = duk_get_hobject(thr, -1);
- if (!h ||
- (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_NUMBER)) {
+ if (!h || (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_NUMBER)) {
DUK_DDD(DUK_DDDPRINT("unacceptable this value: %!T", (duk_tval *) duk_get_tval(thr, -1)));
DUK_ERROR_TYPE(thr, "number expected");
+ DUK_WO_NORETURN(return 0.0;);
}
- duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
+ duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
DUK_ASSERT(duk_is_number(thr, -1));
DUK_DDD(DUK_DDDPRINT("number object: %!T, internal value: %!T",
- (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
+ (duk_tval *) duk_get_tval(thr, -2),
+ (duk_tval *) duk_get_tval(thr, -1)));
duk_remove_m2(thr);
- done:
+done:
return duk_get_number(thr, -1);
}
@@ -37167,9 +41184,9 @@ DUK_INTERNAL duk_ret_t duk_bi_number_constructor(duk_hthread *thr) {
DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_this) == DUK_HOBJECT_CLASS_NUMBER);
DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_this));
- duk_dup_0(thr); /* -> [ val obj val ] */
+ duk_dup_0(thr); /* -> [ val obj val ] */
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
- return 0; /* no return value -> don't replace created value */
+ return 0; /* no return value -> don't replace created value */
}
DUK_INTERNAL duk_ret_t duk_bi_number_prototype_value_of(duk_hthread *thr) {
@@ -37191,10 +41208,7 @@ DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_string(duk_hthread *thr) {
n2s_flags = 0;
- duk_numconv_stringify(thr,
- radix /*radix*/,
- 0 /*digits*/,
- n2s_flags /*flags*/);
+ duk_numconv_stringify(thr, radix /*radix*/, 0 /*digits*/, n2s_flags /*flags*/);
return 1;
}
@@ -37217,8 +41231,11 @@ DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_fixed(duk_hthread *thr) {
duk_small_int_t c;
duk_small_uint_t n2s_flags;
- frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);
+ /* In ES5.1 frac_digits is coerced first; in ES2015 the 'this number
+ * value' check is done first.
+ */
d = duk__push_this_number_plain(thr);
+ frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);
c = (duk_small_int_t) DUK_FPCLASSIFY(d);
if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
@@ -37229,16 +41246,12 @@ DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_fixed(duk_hthread *thr) {
goto use_to_string;
}
- n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
- DUK_N2S_FLAG_FRACTION_DIGITS;
+ n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT | DUK_N2S_FLAG_FRACTION_DIGITS;
- duk_numconv_stringify(thr,
- 10 /*radix*/,
- frac_digits /*digits*/,
- n2s_flags /*flags*/);
+ duk_numconv_stringify(thr, 10 /*radix*/, frac_digits /*digits*/, n2s_flags /*flags*/);
return 1;
- use_to_string:
+use_to_string:
DUK_ASSERT_TOP(thr, 2);
duk_to_string(thr, -1);
return 1;
@@ -37254,7 +41267,7 @@ DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_exponential(duk_hthread *thr)
d = duk__push_this_number_plain(thr);
frac_undefined = duk_is_undefined(thr, 0);
- duk_to_int(thr, 0); /* for side effects */
+ duk_to_int(thr, 0); /* for side effects */
c = (duk_small_int_t) DUK_FPCLASSIFY(d);
if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
@@ -37263,16 +41276,12 @@ DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_exponential(duk_hthread *thr)
frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);
- n2s_flags = DUK_N2S_FLAG_FORCE_EXP |
- (frac_undefined ? 0 : DUK_N2S_FLAG_FIXED_FORMAT);
+ n2s_flags = DUK_N2S_FLAG_FORCE_EXP | (frac_undefined ? 0 : DUK_N2S_FLAG_FIXED_FORMAT);
- duk_numconv_stringify(thr,
- 10 /*radix*/,
- frac_digits + 1 /*leading digit + fractions*/,
- n2s_flags /*flags*/);
+ duk_numconv_stringify(thr, 10 /*radix*/, frac_digits + 1 /*leading digit + fractions*/, n2s_flags /*flags*/);
return 1;
- use_to_string:
+use_to_string:
DUK_ASSERT_TOP(thr, 2);
duk_to_string(thr, -1);
return 1;
@@ -37297,7 +41306,7 @@ DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_precision(duk_hthread *thr) {
}
DUK_ASSERT_TOP(thr, 2);
- duk_to_int(thr, 0); /* for side effects */
+ duk_to_int(thr, 0); /* for side effects */
c = (duk_small_int_t) DUK_FPCLASSIFY(d);
if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
@@ -37306,16 +41315,12 @@ DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_precision(duk_hthread *thr) {
prec = (duk_small_int_t) duk_to_int_check_range(thr, 0, 1, 21);
- n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
- DUK_N2S_FLAG_NO_ZERO_PAD;
+ n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT | DUK_N2S_FLAG_NO_ZERO_PAD;
- duk_numconv_stringify(thr,
- 10 /*radix*/,
- prec /*digits*/,
- n2s_flags /*flags*/);
+ duk_numconv_stringify(thr, 10 /*radix*/, prec /*digits*/, n2s_flags /*flags*/);
return 1;
- use_to_string:
+use_to_string:
/* Used when precision is undefined; also used for NaN (-> "NaN"),
* and +/- infinity (-> "Infinity", "-Infinity").
*/
@@ -37325,7 +41330,43 @@ DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_precision(duk_hthread *thr) {
return 1;
}
-#endif /* DUK_USE_NUMBER_BUILTIN */
+/*
+ * ES2015 isFinite() etc
+ */
+
+#if defined(DUK_USE_ES6)
+DUK_INTERNAL duk_ret_t duk_bi_number_check_shared(duk_hthread *thr) {
+ duk_int_t magic;
+ duk_bool_t ret = 0;
+
+ if (duk_is_number(thr, 0)) {
+ duk_double_t d;
+
+ magic = duk_get_current_magic(thr);
+ d = duk_get_number(thr, 0);
+
+ switch (magic) {
+ case 0: /* isFinite() */
+ ret = duk_double_is_finite(d);
+ break;
+ case 1: /* isInteger() */
+ ret = duk_double_is_integer(d);
+ break;
+ case 2: /* isNaN() */
+ ret = duk_double_is_nan(d);
+ break;
+ default: /* isSafeInteger() */
+ DUK_ASSERT(magic == 3);
+ ret = duk_double_is_safe_integer(d);
+ }
+ }
+
+ duk_push_boolean(thr, ret);
+ return 1;
+}
+#endif /* DUK_USE_ES6 */
+
+#endif /* DUK_USE_NUMBER_BUILTIN */
/*
* Object built-ins
*/
@@ -37335,12 +41376,9 @@ DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_precision(duk_hthread *thr) {
/* Needed even when Object built-in disabled. */
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_string(duk_hthread *thr) {
duk_tval *tv;
+
tv = DUK_HTHREAD_THIS_PTR(thr);
- /* XXX: This is not entirely correct anymore; in ES2015 the
- * default lookup should use @@toStringTag to come up with
- * e.g. [object Symbol].
- */
- duk_push_class_string_tval(thr, tv);
+ duk_push_class_string_tval(thr, tv, 0 /*avoid_side_effects*/);
return 1;
}
@@ -37350,8 +41388,8 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor(duk_hthread *thr) {
arg_mask = duk_get_type_mask(thr, 0);
- if (!duk_is_constructor_call(thr) && /* not a constructor call */
- ((arg_mask & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED)) == 0)) { /* and argument not null or undefined */
+ if (!duk_is_constructor_call(thr) && /* not a constructor call */
+ ((arg_mask & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED)) == 0)) { /* and argument not null or undefined */
duk_to_object(thr, 0);
return 1;
}
@@ -37361,13 +41399,8 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor(duk_hthread *thr) {
* promote to an object value. Lightfuncs and plain buffers are
* coerced with ToObject() even they could also be returned as is.
*/
- if (arg_mask & (DUK_TYPE_MASK_OBJECT |
- DUK_TYPE_MASK_STRING |
- DUK_TYPE_MASK_BOOLEAN |
- DUK_TYPE_MASK_NUMBER |
- DUK_TYPE_MASK_POINTER |
- DUK_TYPE_MASK_BUFFER |
- DUK_TYPE_MASK_LIGHTFUNC)) {
+ if (arg_mask & (DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_BOOLEAN | DUK_TYPE_MASK_NUMBER |
+ DUK_TYPE_MASK_POINTER | DUK_TYPE_MASK_BUFFER | DUK_TYPE_MASK_LIGHTFUNC)) {
/* For DUK_TYPE_OBJECT the coercion is a no-op and could
* be checked for explicitly, but Object(obj) calls are
* not very common so opt for minimal footprint.
@@ -37377,13 +41410,12 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor(duk_hthread *thr) {
}
(void) duk_push_object_helper(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
DUK_BIDX_OBJECT_PROTOTYPE);
return 1;
}
-#endif /* DUK_USE_OBJECT_BUILTIN */
+#endif /* DUK_USE_OBJECT_BUILTIN */
#if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_assign(duk_hthread *thr) {
@@ -37440,9 +41472,8 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_create(duk_hthread *thr) {
DUK_ASSERT(proto != NULL || duk_is_null(thr, 0));
(void) duk_push_object_helper_proto(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
proto);
if (!duk_is_undefined(thr, 1)) {
@@ -37463,7 +41494,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_create(duk_hthread *thr) {
return 1;
}
-#endif /* DUK_USE_OBJECT_BUILTIN */
+#endif /* DUK_USE_OBJECT_BUILTIN */
#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_hthread *thr) {
@@ -37478,11 +41509,9 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_hthread *
obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
DUK_ASSERT(obj != NULL);
- duk_to_object(thr, 1); /* properties object */
+ duk_to_object(thr, 1); /* properties object */
- DUK_DDD(DUK_DDDPRINT("target=%!iT, properties=%!iT",
- (duk_tval *) duk_get_tval(thr, 0),
- (duk_tval *) duk_get_tval(thr, 1)));
+ DUK_DDD(DUK_DDDPRINT("target=%!iT, properties=%!iT", (duk_tval *) duk_get_tval(thr, 0), (duk_tval *) duk_get_tval(thr, 1)));
/*
* Two pass approach to processing the property descriptors.
@@ -37495,7 +41524,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_hthread *
*/
for (pass = 0; pass < 2; pass++) {
- duk_set_top(thr, 2); /* -> [ hobject props ] */
+ duk_set_top(thr, 2); /* -> [ hobject props ] */
duk_enum(thr, 1, DUK_ENUM_OWN_PROPERTIES_ONLY | DUK_ENUM_INCLUDE_SYMBOLS /*enum_flags*/);
for (;;) {
@@ -37515,12 +41544,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_hthread *
/* [ hobject props enum(props) key desc ] */
- duk_hobject_prepare_property_descriptor(thr,
- 4 /*idx_desc*/,
- &defprop_flags,
- &idx_value,
- &get,
- &set);
+ duk_hobject_prepare_property_descriptor(thr, 4 /*idx_desc*/, &defprop_flags, &idx_value, &get, &set);
/* [ hobject props enum(props) key desc [multiple values] ] */
@@ -37532,14 +41556,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_hthread *
key = duk_known_hstring(thr, 3);
DUK_ASSERT(key != NULL);
- duk_hobject_define_property_helper(thr,
- defprop_flags,
- obj,
- key,
- idx_value,
- get,
- set,
- 1 /*throw_flag*/);
+ duk_hobject_define_property_helper(thr, defprop_flags, obj, key, idx_value, get, set, 1 /*throw_flag*/);
}
}
@@ -37550,7 +41567,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_hthread *
duk_dup_0(thr);
return 1;
}
-#endif /* DUK_USE_OBJECT_BUILTIN */
+#endif /* DUK_USE_OBJECT_BUILTIN */
#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_hthread *thr) {
@@ -37559,7 +41576,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_hthread
duk_seal_freeze_raw(thr, 0, (duk_bool_t) duk_get_current_magic(thr) /*is_freeze*/);
return 1;
}
-#endif /* DUK_USE_OBJECT_BUILTIN */
+#endif /* DUK_USE_OBJECT_BUILTIN */
#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_hthread *thr) {
@@ -37571,34 +41588,33 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_hth
mask = duk_get_type_mask(thr, 0);
if (mask & (DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
DUK_ASSERT(is_frozen == 0 || is_frozen == 1);
- duk_push_boolean(thr, (mask & DUK_TYPE_MASK_LIGHTFUNC) ?
- 1 : /* lightfunc always frozen and sealed */
- (is_frozen ^ 1)); /* buffer sealed but not frozen (index props writable) */
+ duk_push_boolean(thr,
+ (mask & DUK_TYPE_MASK_LIGHTFUNC) ? 1 : /* lightfunc always frozen and sealed */
+ (is_frozen ^ 1)); /* buffer sealed but not frozen (index props writable) */
} else {
/* ES2015 Sections 19.1.2.12, 19.1.2.13: anything other than an object
* is considered to be already sealed and frozen.
*/
h = duk_get_hobject(thr, 0);
- duk_push_boolean(thr, (h == NULL) ||
- duk_hobject_object_is_sealed_frozen_helper(thr, h, is_frozen /*is_frozen*/));
+ duk_push_boolean(thr, (h == NULL) || duk_hobject_object_is_sealed_frozen_helper(thr, h, is_frozen /*is_frozen*/));
}
return 1;
}
-#endif /* DUK_USE_OBJECT_BUILTIN */
+#endif /* DUK_USE_OBJECT_BUILTIN */
#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_hthread *thr) {
DUK_ASSERT_TOP(thr, 0);
(void) duk_push_this_coercible_to_object(thr);
duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_TO_STRING);
-#if 0 /* This is mentioned explicitly in the E5.1 spec, but duk_call_method() checks for it in practice. */
+#if 0 /* This is mentioned explicitly in the E5.1 spec, but duk_call_method() checks for it in practice. */
duk_require_callable(thr, 1);
#endif
- duk_dup_0(thr); /* -> [ O toString O ] */
- duk_call_method(thr, 0); /* XXX: call method tail call? */
+ duk_dup_0(thr); /* -> [ O toString O ] */
+ duk_call_method(thr, 0); /* XXX: call method tail call? */
return 1;
}
-#endif /* DUK_USE_OBJECT_BUILTIN */
+#endif /* DUK_USE_OBJECT_BUILTIN */
#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_value_of(duk_hthread *thr) {
@@ -37606,7 +41622,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_prototype_value_of(duk_hthread *thr) {
(void) duk_push_this_coercible_to_object(thr);
return 1;
}
-#endif /* DUK_USE_OBJECT_BUILTIN */
+#endif /* DUK_USE_OBJECT_BUILTIN */
#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_hthread *thr) {
@@ -37617,7 +41633,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_hthread *thr)
h_v = duk_get_hobject(thr, 0);
if (!h_v) {
- duk_push_false(thr); /* XXX: tail call: return duk_push_false(thr) */
+ duk_push_false(thr); /* XXX: tail call: return duk_push_false(thr) */
return 1;
}
@@ -37627,22 +41643,24 @@ DUK_INTERNAL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_hthread *thr)
/* E5.1 Section 15.2.4.6, step 3.a, lookup proto once before compare.
* Prototype loops should cause an error to be thrown.
*/
- duk_push_boolean(thr, duk_hobject_prototype_chain_contains(thr, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_v), h_obj, 0 /*ignore_loop*/));
+ duk_push_boolean(
+ thr,
+ duk_hobject_prototype_chain_contains(thr, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_v), h_obj, 0 /*ignore_loop*/));
return 1;
}
-#endif /* DUK_USE_OBJECT_BUILTIN */
+#endif /* DUK_USE_OBJECT_BUILTIN */
#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_has_own_property(duk_hthread *thr) {
return (duk_ret_t) duk_hobject_object_ownprop_helper(thr, 0 /*required_desc_flags*/);
}
-#endif /* DUK_USE_OBJECT_BUILTIN */
+#endif /* DUK_USE_OBJECT_BUILTIN */
#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_hthread *thr) {
return (duk_ret_t) duk_hobject_object_ownprop_helper(thr, DUK_PROPDESC_FLAG_ENUMERABLE /*required_desc_flags*/);
}
-#endif /* DUK_USE_OBJECT_BUILTIN */
+#endif /* DUK_USE_OBJECT_BUILTIN */
#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
/* Shared helper to implement Object.getPrototypeOf,
@@ -37699,7 +41717,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_getprototype_shared(duk_hthread *thr) {
}
return 1;
}
-#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
+#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
/* Shared helper to implement ES2015 Object.setPrototypeOf,
@@ -37718,7 +41736,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_setprototype_shared(duk_hthread *thr) {
duk_hobject *h_obj;
duk_hobject *h_new_proto;
duk_hobject *h_curr;
- duk_ret_t ret_success = 1; /* retval for success path */
+ duk_ret_t ret_success = 1; /* retval for success path */
duk_uint_t mask;
duk_int_t magic;
@@ -37739,9 +41757,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_setprototype_shared(duk_hthread *thr) {
if (magic == 1) {
duk_require_object_coercible(thr, 0);
} else {
- duk_require_hobject_accept_mask(thr, 0,
- DUK_TYPE_MASK_LIGHTFUNC |
- DUK_TYPE_MASK_BUFFER);
+ duk_require_hobject_accept_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
}
duk_require_type_mask(thr, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT);
}
@@ -37752,9 +41768,8 @@ DUK_INTERNAL duk_ret_t duk_bi_object_setprototype_shared(duk_hthread *thr) {
mask = duk_get_type_mask(thr, 0);
if (mask & (DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
duk_hobject *curr_proto;
- curr_proto = thr->builtins[(mask & DUK_TYPE_MASK_LIGHTFUNC) ?
- DUK_BIDX_FUNCTION_PROTOTYPE :
- DUK_BIDX_UINT8ARRAY_PROTOTYPE];
+ curr_proto =
+ thr->builtins[(mask & DUK_TYPE_MASK_LIGHTFUNC) ? DUK_BIDX_FUNCTION_PROTOTYPE : DUK_BIDX_UINT8ARRAY_PROTOTYPE];
if (h_new_proto == curr_proto) {
goto skip;
}
@@ -37784,15 +41799,15 @@ DUK_INTERNAL duk_ret_t duk_bi_object_setprototype_shared(duk_hthread *thr) {
DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h_obj, h_new_proto);
/* fall thru */
- skip:
+skip:
duk_set_top(thr, 1);
if (magic == 2) {
duk_push_true(thr);
}
return ret_success;
- fail_nonextensible:
- fail_loop:
+fail_nonextensible:
+fail_loop:
if (magic != 2) {
DUK_DCERROR_TYPE_INVALID_ARGS(thr);
} else {
@@ -37800,7 +41815,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_setprototype_shared(duk_hthread *thr) {
return 1;
}
}
-#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
+#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_property(duk_hthread *thr) {
@@ -37845,19 +41860,14 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_property(duk_hthread *th
DUK_ASSERT(duk_get_hobject(thr, 2) != NULL);
/*
- * Validate and convert argument property descriptor (an Ecmascript
+ * Validate and convert argument property descriptor (an ECMAScript
* object) into a set of defprop_flags and possibly property value,
* getter, and/or setter values on the value stack.
*
* Lightfunc set/get values are coerced to full Functions.
*/
- duk_hobject_prepare_property_descriptor(thr,
- 2 /*idx_desc*/,
- &defprop_flags,
- &idx_value,
- &get,
- &set);
+ duk_hobject_prepare_property_descriptor(thr, 2 /*idx_desc*/, &defprop_flags, &idx_value, &get, &set);
/*
* Use Object.defineProperty() helper for the actual operation.
@@ -37865,14 +41875,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_property(duk_hthread *th
DUK_ASSERT(magic == 0U || magic == 1U);
throw_flag = magic ^ 1U;
- ret = duk_hobject_define_property_helper(thr,
- defprop_flags,
- obj,
- key,
- idx_value,
- get,
- set,
- throw_flag);
+ ret = duk_hobject_define_property_helper(thr, defprop_flags, obj, key, idx_value, get, set, throw_flag);
/* Ignore the normalize/validate helper outputs on the value stack,
* they're popped automatically.
@@ -37887,7 +41890,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_property(duk_hthread *th
}
return 1;
}
-#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
+#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_hthread *thr) {
@@ -37903,7 +41906,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk
duk_hobject_object_get_own_property_descriptor(thr, -2);
return 1;
}
-#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
+#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_extensible(duk_hthread *thr) {
@@ -37926,7 +41929,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_extensible(duk_hthread *thr)
duk_push_boolean(thr, (h != NULL) && DUK_HOBJECT_HAS_EXTENSIBLE(h));
return 1;
}
-#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
+#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
/* Shared helper for various key/symbol listings, magic:
@@ -37937,26 +41940,17 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_extensible(duk_hthread *thr)
*/
DUK_LOCAL const duk_small_uint_t duk__object_keys_enum_flags[4] = {
/* Object.keys() */
- DUK_ENUM_OWN_PROPERTIES_ONLY |
- DUK_ENUM_NO_PROXY_BEHAVIOR,
+ DUK_ENUM_OWN_PROPERTIES_ONLY | DUK_ENUM_NO_PROXY_BEHAVIOR,
/* Object.getOwnPropertyNames() */
- DUK_ENUM_INCLUDE_NONENUMERABLE |
- DUK_ENUM_OWN_PROPERTIES_ONLY |
- DUK_ENUM_NO_PROXY_BEHAVIOR,
+ DUK_ENUM_INCLUDE_NONENUMERABLE | DUK_ENUM_OWN_PROPERTIES_ONLY | DUK_ENUM_NO_PROXY_BEHAVIOR,
/* Object.getOwnPropertySymbols() */
- DUK_ENUM_INCLUDE_SYMBOLS |
- DUK_ENUM_OWN_PROPERTIES_ONLY |
- DUK_ENUM_EXCLUDE_STRINGS |
- DUK_ENUM_INCLUDE_NONENUMERABLE |
+ DUK_ENUM_INCLUDE_SYMBOLS | DUK_ENUM_OWN_PROPERTIES_ONLY | DUK_ENUM_EXCLUDE_STRINGS | DUK_ENUM_INCLUDE_NONENUMERABLE |
DUK_ENUM_NO_PROXY_BEHAVIOR,
/* Reflect.ownKeys() */
- DUK_ENUM_INCLUDE_SYMBOLS |
- DUK_ENUM_OWN_PROPERTIES_ONLY |
- DUK_ENUM_INCLUDE_NONENUMERABLE |
- DUK_ENUM_NO_PROXY_BEHAVIOR
+ DUK_ENUM_INCLUDE_SYMBOLS | DUK_ENUM_OWN_PROPERTIES_ONLY | DUK_ENUM_INCLUDE_NONENUMERABLE | DUK_ENUM_NO_PROXY_BEHAVIOR
};
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_hthread *thr) {
@@ -37988,9 +41982,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_hthread *thr) {
#if defined(DUK_USE_ES6_PROXY)
/* XXX: better sharing of code between proxy target call sites */
- if (DUK_LIKELY(!duk_hobject_proxy_check(obj,
- &h_proxy_target,
- &h_proxy_handler))) {
+ if (DUK_LIKELY(!duk_hobject_proxy_check(obj, &h_proxy_target, &h_proxy_handler))) {
goto skip_proxy;
}
@@ -38009,8 +42001,8 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_hthread *thr) {
/* [ obj handler trap ] */
duk_insert(thr, -2);
- duk_push_hobject(thr, h_proxy_target); /* -> [ obj trap handler target ] */
- duk_call_method(thr, 1 /*nargs*/); /* -> [ obj trap_result ] */
+ duk_push_hobject(thr, h_proxy_target); /* -> [ obj trap handler target ] */
+ duk_call_method(thr, 1 /*nargs*/); /* -> [ obj trap_result ] */
h_trap_result = duk_require_hobject(thr, -1);
DUK_UNREF(h_trap_result);
@@ -38021,8 +42013,8 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_hthread *thr) {
duk_proxy_ownkeys_postprocess(thr, h_proxy_target, enum_flags);
return 1;
- skip_proxy:
-#endif /* DUK_USE_ES6_PROXY */
+skip_proxy:
+#endif /* DUK_USE_ES6_PROXY */
DUK_ASSERT_TOP(thr, 1);
magic = duk_get_current_magic(thr);
@@ -38030,7 +42022,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_hthread *thr) {
enum_flags = duk__object_keys_enum_flags[magic];
return duk_hobject_get_enumerated_keys(thr, enum_flags);
}
-#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
+#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_hthread *thr) {
@@ -38050,12 +42042,8 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_hthread
/* Object.preventExtensions() silent success for non-object. */
if (magic == 0) {
- mask |= DUK_TYPE_MASK_UNDEFINED |
- DUK_TYPE_MASK_NULL |
- DUK_TYPE_MASK_BOOLEAN |
- DUK_TYPE_MASK_NUMBER |
- DUK_TYPE_MASK_STRING |
- DUK_TYPE_MASK_POINTER;
+ mask |= DUK_TYPE_MASK_UNDEFINED | DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_BOOLEAN | DUK_TYPE_MASK_NUMBER |
+ DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_POINTER;
}
if (duk_check_type_mask(thr, 0, mask)) {
@@ -38072,13 +42060,13 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_hthread
*/
duk_hobject_compact_props(thr, h);
- done:
+done:
if (magic == 1) {
duk_push_true(thr);
}
return 1;
}
-#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
+#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
/*
* __defineGetter__, __defineSetter__, __lookupGetter__, __lookupSetter__
@@ -38094,9 +42082,10 @@ DUK_INTERNAL duk_ret_t duk_bi_object_prototype_defineaccessor(duk_hthread *thr)
/* [ ToObject(this) key getter/setter ] */
/* ToPropertyKey() coercion is not needed, duk_def_prop() does it. */
- duk_def_prop(thr, 0, DUK_DEFPROP_SET_ENUMERABLE |
- DUK_DEFPROP_SET_CONFIGURABLE |
- (duk_get_current_magic(thr) ? DUK_DEFPROP_HAVE_SETTER : DUK_DEFPROP_HAVE_GETTER));
+ duk_def_prop(thr,
+ 0,
+ DUK_DEFPROP_SET_ENUMERABLE | DUK_DEFPROP_SET_CONFIGURABLE |
+ (duk_get_current_magic(thr) ? DUK_DEFPROP_HAVE_SETTER : DUK_DEFPROP_HAVE_GETTER));
return 0;
}
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_hthread *thr) {
@@ -38123,6 +42112,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_hthread *thr)
if (DUK_UNLIKELY(sanity-- == 0)) {
DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
+ DUK_WO_NORETURN(return 0;);
}
duk_get_prototype(thr, -1);
@@ -38130,7 +42120,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_hthread *thr)
}
return 1;
}
-#endif /* DUK_USE_ES8 */
+#endif /* DUK_USE_ES8 */
/*
* High resolution time API (performance.now() et al)
*
@@ -38151,7 +42141,7 @@ DUK_INTERNAL duk_ret_t duk_bi_performance_now(duk_hthread *thr) {
return 1;
}
-#if 0 /* Missing until semantics decided. */
+#if 0 /* Missing until semantics decided. */
DUK_INTERNAL duk_ret_t duk_bi_performance_timeorigin_getter(duk_hthread *thr) {
/* No decision yet how to handle timeOrigins, e.g. should one be
* initialized per heap, or per global object set. See
@@ -38160,8 +42150,8 @@ DUK_INTERNAL duk_ret_t duk_bi_performance_timeorigin_getter(duk_hthread *thr) {
duk_push_uint(thr, 0);
return 1;
}
-#endif /* 0 */
-#endif /* DUK_USE_PERFORMANCE_BUILTIN */
+#endif /* 0 */
+#endif /* DUK_USE_PERFORMANCE_BUILTIN */
/*
* Pointer built-ins
*/
@@ -38187,12 +42177,11 @@ DUK_INTERNAL duk_ret_t duk_bi_pointer_constructor(duk_hthread *thr) {
if (duk_is_constructor_call(thr)) {
(void) duk_push_object_helper(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER),
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER),
DUK_BIDX_POINTER_PROTOTYPE);
- /* Pointer object internal value is immutable */
+ /* Pointer object internal value is immutable. */
duk_dup_0(thr);
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
}
@@ -38224,7 +42213,7 @@ DUK_INTERNAL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_hthread *thr
goto type_error;
}
- duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
+ duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
} else {
goto type_error;
}
@@ -38234,7 +42223,7 @@ DUK_INTERNAL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_hthread *thr
}
return 1;
- type_error:
+type_error:
DUK_DCERROR_TYPE_INVALID_ARGS(thr);
}
/*
@@ -38247,40 +42236,40 @@ DUK_INTERNAL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_hthread *thr
DUK_INTERNAL duk_ret_t duk_bi_promise_constructor(duk_hthread *thr) {
DUK_ERROR_TYPE(thr, "unimplemented");
- return 0;
+ DUK_WO_NORETURN(return 0;);
}
DUK_INTERNAL duk_ret_t duk_bi_promise_all(duk_hthread *thr) {
DUK_ERROR_TYPE(thr, "unimplemented");
- return 0;
+ DUK_WO_NORETURN(return 0;);
}
DUK_INTERNAL duk_ret_t duk_bi_promise_race(duk_hthread *thr) {
DUK_ERROR_TYPE(thr, "unimplemented");
- return 0;
+ DUK_WO_NORETURN(return 0;);
}
DUK_INTERNAL duk_ret_t duk_bi_promise_reject(duk_hthread *thr) {
DUK_ERROR_TYPE(thr, "unimplemented");
- return 0;
+ DUK_WO_NORETURN(return 0;);
}
DUK_INTERNAL duk_ret_t duk_bi_promise_resolve(duk_hthread *thr) {
DUK_ERROR_TYPE(thr, "unimplemented");
- return 0;
+ DUK_WO_NORETURN(return 0;);
}
DUK_INTERNAL duk_ret_t duk_bi_promise_catch(duk_hthread *thr) {
DUK_ERROR_TYPE(thr, "unimplemented");
- return 0;
+ DUK_WO_NORETURN(return 0;);
}
DUK_INTERNAL duk_ret_t duk_bi_promise_then(duk_hthread *thr) {
DUK_ERROR_TYPE(thr, "unimplemented");
- return 0;
+ DUK_WO_NORETURN(return 0;);
}
-#endif /* DUK_USE_PROMISE_BUILTIN */
+#endif /* DUK_USE_PROMISE_BUILTIN */
/*
* Proxy built-in (ES2015)
*/
@@ -38296,7 +42285,7 @@ DUK_INTERNAL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h
duk_uarridx_t i, len, idx;
duk_propdesc desc;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
DUK_ASSERT(h_proxy_target != NULL);
len = (duk_uarridx_t) duk_get_length(thr, -1);
@@ -38311,6 +42300,7 @@ DUK_INTERNAL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h
h = duk_get_hstring(thr, -1);
if (h == NULL) {
DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr);
+ DUK_WO_NORETURN(return;);
}
if (!(flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
@@ -38345,10 +42335,12 @@ DUK_INTERNAL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h
}
/* [ obj trap_result res_arr propname ] */
- duk_put_prop_index(thr, -2, idx++);
+ duk_push_uarridx(thr, idx++);
+ duk_insert(thr, -2);
+ duk_def_prop(thr, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_SET_WEC);
continue;
- skip_key:
+ skip_key:
duk_pop(thr);
continue;
}
@@ -38365,17 +42357,17 @@ DUK_INTERNAL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h
* handled above.
*/
}
-#endif /* DUK_USE_ES6_PROXY */
+#endif /* DUK_USE_ES6_PROXY */
#if defined(DUK_USE_ES6_PROXY)
DUK_INTERNAL duk_ret_t duk_bi_proxy_constructor(duk_hthread *thr) {
- DUK_ASSERT_TOP(thr, 2); /* [ target handler ] */
+ DUK_ASSERT_TOP(thr, 2); /* [ target handler ] */
duk_require_constructor_call(thr);
- duk_push_proxy(thr, 0 /*flags*/); /* [ target handler ] -> [ proxy ] */
- return 1; /* replacement */
+ duk_push_proxy(thr, 0 /*flags*/); /* [ target handler ] -> [ proxy ] */
+ return 1; /* replacement */
}
-#endif /* DUK_USE_ES6_PROXY */
+#endif /* DUK_USE_ES6_PROXY */
/*
* 'Reflect' built-in (ES2016 Section 26.1)
* http://www.ecma-international.org/ecma-262/7.0/#sec-reflect-object
@@ -38418,13 +42410,14 @@ DUK_INTERNAL duk_ret_t duk_bi_reflect_object_get(duk_hthread *thr) {
if (nargs >= 3 && !duk_strict_equals(thr, 0, 2)) {
/* XXX: [[Get]] receiver currently unsupported */
DUK_ERROR_UNSUPPORTED(thr);
+ DUK_WO_NORETURN(return 0;);
}
/* [ target key receiver? ...? ] */
tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
- (void) duk_hobject_getprop(thr, tv_obj, tv_key); /* This could also be a duk_get_prop(). */
+ (void) duk_hobject_getprop(thr, tv_obj, tv_key); /* This could also be a duk_get_prop(). */
return 1;
}
@@ -38461,6 +42454,7 @@ DUK_INTERNAL duk_ret_t duk_bi_reflect_object_set(duk_hthread *thr) {
if (nargs >= 4 && !duk_strict_equals(thr, 0, 3)) {
/* XXX: [[Set]] receiver currently unsupported */
DUK_ERROR_UNSUPPORTED(thr);
+ DUK_WO_NORETURN(return 0;);
}
/* [ target key value receiver? ...? ] */
@@ -38472,7 +42466,7 @@ DUK_INTERNAL duk_ret_t duk_bi_reflect_object_set(duk_hthread *thr) {
duk_push_boolean(thr, ret);
return 1;
}
-#endif /* DUK_USE_REFLECT_BUILTIN */
+#endif /* DUK_USE_REFLECT_BUILTIN */
/*
* RegExp built-ins
*/
@@ -38488,7 +42482,7 @@ DUK_LOCAL void duk__get_this_regexp(duk_hthread *thr) {
h = duk_require_hobject_with_class(thr, -1, DUK_HOBJECT_CLASS_REGEXP);
DUK_ASSERT(h != NULL);
DUK_UNREF(h);
- duk_insert(thr, 0); /* prepend regexp to valstack 0 index */
+ duk_insert(thr, 0); /* prepend regexp to valstack 0 index */
}
/* XXX: much to improve (code size) */
@@ -38498,10 +42492,8 @@ DUK_INTERNAL duk_ret_t duk_bi_regexp_constructor(duk_hthread *thr) {
DUK_ASSERT_TOP(thr, 2);
h_pattern = duk_get_hobject(thr, 0);
- if (!duk_is_constructor_call(thr) &&
- h_pattern != NULL &&
- DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP &&
- duk_is_undefined(thr, 1)) {
+ if (!duk_is_constructor_call(thr) && h_pattern != NULL &&
+ DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP && duk_is_undefined(thr, 1)) {
/* Called as a function, pattern has [[Class]] "RegExp" and
* flags is undefined -> return object as is.
*/
@@ -38516,8 +42508,7 @@ DUK_INTERNAL duk_ret_t duk_bi_regexp_constructor(duk_hthread *thr) {
* call.
*/
- if (h_pattern != NULL &&
- DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP) {
+ if (h_pattern != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP) {
duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_SOURCE);
if (duk_is_undefined(thr, 1)) {
/* In ES5 one would need to read the flags individually;
@@ -38533,20 +42524,21 @@ DUK_INTERNAL duk_ret_t duk_bi_regexp_constructor(duk_hthread *thr) {
duk_push_hstring_empty(thr);
} else {
duk_dup_0(thr);
- duk_to_string(thr, -1); /* Rejects Symbols. */
+ duk_to_string(thr, -1); /* Rejects Symbols. */
}
if (duk_is_undefined(thr, 1)) {
duk_push_hstring_empty(thr);
} else {
duk_dup_1(thr);
- duk_to_string(thr, -1); /* Rejects Symbols. */
+ duk_to_string(thr, -1); /* Rejects Symbols. */
}
/* [ ... pattern flags ] */
}
DUK_DDD(DUK_DDDPRINT("RegExp constructor/function call, pattern=%!T, flags=%!T",
- (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
+ (duk_tval *) duk_get_tval(thr, -2),
+ (duk_tval *) duk_get_tval(thr, -1)));
/* [ ... pattern flags ] (both uncoerced) */
@@ -38594,9 +42586,9 @@ DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_tostring(duk_hthread *thr) {
/* This must be generic in ES2015 and later. */
DUK_ASSERT_TOP(thr, 0);
duk_push_this(thr);
- duk_push_string(thr, "/");
+ duk_push_literal(thr, "/");
duk_get_prop_stridx(thr, 0, DUK_STRIDX_SOURCE);
- duk_dup_m2(thr); /* another "/" */
+ duk_dup_m2(thr); /* another "/" */
duk_get_prop_stridx(thr, 0, DUK_STRIDX_FLAGS);
duk_concat(thr, 4);
return 1;
@@ -38606,7 +42598,7 @@ DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_flags(duk_hthread *thr) {
/* .flags is ES2015 but present even when ES2015 bindings are
* disabled because the constructor relies on it.
*/
- duk_uint8_t buf[8]; /* enough for all flags + NUL */
+ duk_uint8_t buf[8]; /* enough for all flags + NUL */
duk_uint8_t *p = buf;
/* .flags is generic and works on any object. */
@@ -38644,10 +42636,10 @@ DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_hthread *thr) {
magic = duk_get_current_magic(thr);
if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_REGEXP) {
- duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_INT_SOURCE);
- duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_INT_BYTECODE);
+ duk_xget_owndataprop_stridx_short(thr, 0, DUK_STRIDX_INT_SOURCE);
+ duk_xget_owndataprop_stridx_short(thr, 0, DUK_STRIDX_INT_BYTECODE);
h_bc = duk_require_hstring(thr, -1);
- re_flags = (duk_small_uint_t) DUK_HSTRING_GET_DATA(h_bc)[0]; /* Safe even if h_bc length is 0 (= NUL) */
+ re_flags = (duk_small_uint_t) DUK_HSTRING_GET_DATA(h_bc)[0]; /* Safe even if h_bc length is 0 (= NUL) */
duk_pop(thr);
} else if (h == thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]) {
/* In ES2015 and ES2016 a TypeError would be thrown here.
@@ -38658,7 +42650,7 @@ DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_hthread *thr) {
if (magic != 16 /* .source */) {
return 0;
}
- duk_push_string(thr, "(?:)"); /* .source handled by switch-case */
+ duk_push_literal(thr, "(?:)"); /* .source handled by switch-case */
re_flags = 0;
} else {
DUK_DCERROR_TYPE_INVALID_ARGS(thr);
@@ -38667,15 +42659,15 @@ DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_hthread *thr) {
/* [ regexp source ] */
switch (magic) {
- case 0: { /* global */
+ case 0: { /* global */
duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_GLOBAL));
break;
}
- case 1: { /* ignoreCase */
+ case 1: { /* ignoreCase */
duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_IGNORE_CASE));
break;
}
- case 2: { /* multiline */
+ case 2: { /* multiline */
duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_MULTILINE));
break;
}
@@ -38689,7 +42681,7 @@ DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_hthread *thr) {
break;
}
#endif
- default: { /* source */
+ default: { /* source */
/* leave 'source' on top */
break;
}
@@ -38698,7 +42690,7 @@ DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_hthread *thr) {
return 1;
}
-#endif /* DUK_USE_REGEXP_SUPPORT */
+#endif /* DUK_USE_REGEXP_SUPPORT */
/*
* String built-ins
*
@@ -38729,6 +42721,7 @@ DUK_LOCAL duk_hstring *duk__str_tostring_notregexp(duk_hthread *thr, duk_idx_t i
if (duk_get_class_number(thr, idx) == DUK_HOBJECT_CLASS_REGEXP) {
DUK_ERROR_TYPE_INVALID_ARGS(thr);
+ DUK_WO_NORETURN(return NULL;);
}
h = duk_to_hstring(thr, idx);
DUK_ASSERT(h != NULL);
@@ -38736,7 +42729,8 @@ DUK_LOCAL duk_hstring *duk__str_tostring_notregexp(duk_hthread *thr, duk_idx_t i
return h;
}
-DUK_LOCAL duk_int_t duk__str_search_shared(duk_hthread *thr, duk_hstring *h_this, duk_hstring *h_search, duk_int_t start_cpos, duk_bool_t backwards) {
+DUK_LOCAL duk_int_t
+duk__str_search_shared(duk_hthread *thr, duk_hstring *h_this, duk_hstring *h_search, duk_int_t start_cpos, duk_bool_t backwards) {
duk_int_t cpos;
duk_int_t bpos;
const duk_uint8_t *p_start, *p_end, *p;
@@ -38771,18 +42765,18 @@ DUK_LOCAL duk_int_t duk__str_search_shared(duk_hthread *thr, duk_hstring *h_this
* must be updated if 'p' is wound back (backward scanning).
*/
- firstbyte = q_start[0]; /* leading byte of match string */
+ firstbyte = q_start[0]; /* leading byte of match string */
while (p <= p_end && p >= p_start) {
t = *p;
- /* For Ecmascript strings, this check can only match for
+ /* For ECMAScript strings, this check can only match for
* initial UTF-8 bytes (not continuation bytes). For other
* strings all bets are off.
*/
if ((t == firstbyte) && ((duk_size_t) (p_end - p) >= (duk_size_t) q_blen)) {
- DUK_ASSERT(q_blen > 0); /* no issues with memcmp() zero size, even if broken */
- if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
+ DUK_ASSERT(q_blen > 0);
+ if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
return cpos;
}
}
@@ -38837,15 +42831,13 @@ DUK_INTERNAL duk_ret_t duk_bi_string_constructor(duk_hthread *thr) {
duk_replace(thr, 0);
}
}
- duk_to_string(thr, 0); /* catches symbol argument for constructor call */
+ duk_to_string(thr, 0); /* catches symbol argument for constructor call */
DUK_ASSERT(duk_is_string(thr, 0));
- duk_set_top(thr, 1); /* Top may be 1 or larger. */
+ duk_set_top(thr, 1); /* Top may be 1 or larger. */
if (duk_is_constructor_call(thr)) {
/* String object internal value is immutable */
- flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
+ flags = DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS | DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
duk_push_object_helper(thr, flags, DUK_BIDX_STRING_PROTOTYPE);
duk_dup_0(thr);
@@ -38871,7 +42863,7 @@ DUK_LOCAL duk_ret_t duk__construct_from_codepoints(duk_hthread *thr, duk_bool_t
n = duk_get_top(thr);
bw = &bw_alloc;
- DUK_BW_INIT_PUSHBUF(thr, bw, (duk_size_t) n); /* initial estimate for ASCII only codepoints */
+ DUK_BW_INIT_PUSHBUF(thr, bw, (duk_size_t) n); /* initial estimate for ASCII only codepoints */
for (i = 0; i < n; i++) {
/* XXX: could improve bufwriter handling to write multiple codepoints
@@ -38885,8 +42877,7 @@ DUK_LOCAL duk_ret_t duk__construct_from_codepoints(duk_hthread *thr, duk_bool_t
* the same.
*/
duk_int32_t i32 = 0;
- if (!duk_is_whole_get_int32(duk_to_number(thr, i), &i32) ||
- i32 < 0 || i32 > 0x10ffffL) {
+ if (!duk_is_whole_get_int32(duk_to_number(thr, i), &i32) || i32 < 0 || i32 > 0x10ffffL) {
DUK_DCERROR_RANGE_INVALID_ARGS(thr);
}
DUK_ASSERT(i32 >= 0 && i32 <= 0x10ffffL);
@@ -38910,7 +42901,7 @@ DUK_LOCAL duk_ret_t duk__construct_from_codepoints(duk_hthread *thr, duk_bool_t
}
DUK_BW_COMPACT(thr, bw);
- (void) duk_buffer_to_string(thr, -1); /* Safe, extended UTF-8 or CESU-8 encoded. */
+ (void) duk_buffer_to_string(thr, -1); /* Safe, extended UTF-8 or CESU-8 encoded. */
return 1;
}
@@ -38946,16 +42937,16 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_to_string(duk_hthread *thr) {
goto type_error;
}
- duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
+ duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
DUK_ASSERT(duk_is_string(thr, -1));
} else {
goto type_error;
}
- (void) duk_require_hstring_notsymbol(thr, -1); /* Reject symbols (and wrapped symbols). */
+ (void) duk_require_hstring_notsymbol(thr, -1); /* Reject symbols (and wrapped symbols). */
return 1;
- type_error:
+type_error:
DUK_DCERROR_TYPE_INVALID_ARGS(thr);
}
@@ -38964,13 +42955,37 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_to_string(duk_hthread *thr) {
*/
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_at(duk_hthread *thr) {
+ duk_hstring *h;
duk_int_t pos;
/* XXX: faster implementation */
- (void) duk_push_this_coercible_to_string(thr);
+ h = duk_push_this_coercible_to_string(thr);
+ DUK_ASSERT(h != NULL);
+
pos = duk_to_int(thr, 0);
- duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) (pos + 1));
+
+ if (sizeof(duk_size_t) >= sizeof(duk_uint_t)) {
+ /* Cast to duk_size_t works in this case:
+ * - If pos < 0, (duk_size_t) pos will always be
+ * >= max_charlen, and result will be the empty string
+ * (see duk_substring()).
+ * - If pos >= 0, pos + 1 cannot wrap.
+ */
+ DUK_ASSERT((duk_size_t) DUK_INT_MIN >= DUK_HSTRING_MAX_BYTELEN);
+ DUK_ASSERT((duk_size_t) DUK_INT_MAX + 1U > (duk_size_t) DUK_INT_MAX);
+ duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) pos + 1U);
+ } else {
+ /* If size_t is smaller than int, explicit bounds checks
+ * are needed because an int may wrap multiple times.
+ */
+ if (DUK_UNLIKELY(pos < 0 || (duk_uint_t) pos >= (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h))) {
+ duk_push_hstring_empty(thr);
+ } else {
+ duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) pos + 1U);
+ }
+ }
+
return 1;
}
@@ -39067,7 +43082,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substr(duk_hthread *thr) {
* ("undefined" and "null").
*/
duk_push_this(thr);
- h = duk_to_hstring_m1(thr); /* Reject Symbols. */
+ h = duk_to_hstring_m1(thr); /* Reject Symbols. */
DUK_ASSERT(h != NULL);
len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
@@ -39099,7 +43114,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substr(duk_hthread *thr) {
duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
return 1;
}
-#endif /* DUK_USE_SECTION_B */
+#endif /* DUK_USE_SECTION_B */
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_slice(duk_hthread *thr) {
duk_hstring *h;
@@ -39158,7 +43173,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_hthread *thr)
duk_hstring *h_search;
duk_int_t clen_this;
duk_int_t cpos;
- duk_small_uint_t is_lastindexof = (duk_small_uint_t) duk_get_current_magic(thr); /* 0=indexOf, 1=lastIndexOf */
+ duk_small_uint_t is_lastindexof = (duk_small_uint_t) duk_get_current_magic(thr); /* 0=indexOf, 1=lastIndexOf */
h_this = duk_push_this_coercible_to_string(thr);
DUK_ASSERT(h_this != NULL);
@@ -39215,7 +43230,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
duk_int_t match_caps;
#endif
duk_uint32_t prev_match_end_boff;
- const duk_uint8_t *r_start, *r_end, *r; /* repl string scan */
+ const duk_uint8_t *r_start, *r_end, *r; /* repl string scan */
duk_size_t tmp_sz;
DUK_ASSERT_TOP(thr, 2);
@@ -39223,7 +43238,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
DUK_ASSERT(h_input != NULL);
bw = &bw_alloc;
- DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input)); /* input size is good output starting point */
+ DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input)); /* input size is good output starting point */
DUK_ASSERT_TOP(thr, 4);
@@ -39244,11 +43259,11 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
duk_push_int(thr, 0);
duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
}
-#else /* DUK_USE_REGEXP_SUPPORT */
+#else /* DUK_USE_REGEXP_SUPPORT */
DUK_DCERROR_UNSUPPORTED(thr);
-#endif /* DUK_USE_REGEXP_SUPPORT */
+#endif /* DUK_USE_REGEXP_SUPPORT */
} else {
- duk_to_string(thr, 0); /* rejects symbols */
+ duk_to_string(thr, 0); /* rejects symbols */
#if defined(DUK_USE_REGEXP_SUPPORT)
is_regexp = 0;
is_global = 0;
@@ -39263,7 +43278,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
duk_hstring *h_repl;
is_repl_func = 0;
- h_repl = duk_to_hstring(thr, 1); /* reject symbols */
+ h_repl = duk_to_hstring(thr, 1); /* reject symbols */
DUK_ASSERT(h_repl != NULL);
r_start = DUK_HSTRING_GET_DATA(h_repl);
r_end = r_start + DUK_HSTRING_GET_BYTELEN(h_repl);
@@ -39301,7 +43316,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
if (is_regexp) {
duk_dup_0(thr);
duk_dup_2(thr);
- duk_regexp_match(thr); /* [ ... regexp input ] -> [ res_obj ] */
+ duk_regexp_match(thr); /* [ ... regexp input ] -> [ res_obj ] */
if (!duk_is_object(thr, -1)) {
duk_pop(thr);
break;
@@ -39315,7 +43330,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
duk_get_prop_index(thr, -1, 0);
DUK_ASSERT(duk_is_string(thr, -1));
h_match = duk_known_hstring(thr, -1);
- duk_pop(thr); /* h_match is borrowed, remains reachable through match_obj */
+ duk_pop(thr); /* h_match is borrowed, remains reachable through match_obj */
if (DUK_HSTRING_GET_BYTELEN(h_match) == 0) {
/* This should be equivalent to match() algorithm step 8.f.iii.2:
@@ -39326,41 +43341,49 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
last_index = (duk_uint32_t) duk_get_uint(thr, -1);
DUK_DDD(DUK_DDDPRINT("empty match, bump lastIndex: %ld -> %ld",
- (long) last_index, (long) (last_index + 1)));
+ (long) last_index,
+ (long) (last_index + 1)));
duk_pop(thr);
duk_push_uint(thr, (duk_uint_t) (last_index + 1));
duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
}
- DUK_ASSERT(duk_get_length(thr, -1) <= DUK_INT_MAX); /* string limits */
+ DUK_ASSERT(duk_get_length(thr, -1) <= DUK_INT_MAX); /* string limits */
match_caps = (duk_int_t) duk_get_length(thr, -1);
} else {
-#else /* DUK_USE_REGEXP_SUPPORT */
- { /* unconditionally */
-#endif /* DUK_USE_REGEXP_SUPPORT */
- const duk_uint8_t *p_start, *p_end, *p; /* input string scan */
- const duk_uint8_t *q_start; /* match string */
+#else /* DUK_USE_REGEXP_SUPPORT */
+ { /* unconditionally */
+#endif /* DUK_USE_REGEXP_SUPPORT */
+ const duk_uint8_t *p_start, *p_end, *p; /* input string scan */
+ const duk_uint8_t *q_start; /* match string */
+ duk_size_t p_blen;
duk_size_t q_blen;
#if defined(DUK_USE_REGEXP_SUPPORT)
- DUK_ASSERT(!is_global); /* single match always */
+ DUK_ASSERT(!is_global); /* single match always */
#endif
p_start = DUK_HSTRING_GET_DATA(h_input);
p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
+ p_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_input);
p = p_start;
h_search = duk_known_hstring(thr, 0);
q_start = DUK_HSTRING_GET_DATA(h_search);
q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search);
- p_end -= q_blen; /* ensure full memcmp() fits in while */
+ if (q_blen > p_blen) {
+ break; /* no match */
+ }
+
+ p_end -= q_blen; /* ensure full memcmp() fits in while */
+ DUK_ASSERT(p_end >= p);
match_start_coff = 0;
while (p <= p_end) {
DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
- if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
+ if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
duk_dup_0(thr);
h_match = duk_known_hstring(thr, -1);
#if defined(DUK_USE_REGEXP_SUPPORT)
@@ -39379,7 +43402,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
/* not found */
break;
}
- found:
+ found:
/* stack[0] = search value
* stack[1] = replace value
@@ -39413,9 +43436,9 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
duk_get_prop_index(thr, 4, (duk_uarridx_t) idx);
}
} else {
-#else /* DUK_USE_REGEXP_SUPPORT */
- { /* unconditionally */
-#endif /* DUK_USE_REGEXP_SUPPORT */
+#else /* DUK_USE_REGEXP_SUPPORT */
+ { /* unconditionally */
+#endif /* DUK_USE_REGEXP_SUPPORT */
/* match == search string, by definition */
duk_dup_0(thr);
}
@@ -39425,12 +43448,12 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
/* [ ... replacer match [captures] match_char_offset input ] */
duk_call(thr, duk_get_top(thr) - idx_args);
- h_repl = duk_to_hstring_m1(thr); /* -> [ ... repl_value ] */
+ h_repl = duk_to_hstring_m1(thr); /* -> [ ... repl_value ] */
DUK_ASSERT(h_repl != NULL);
DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_repl);
- duk_pop(thr); /* repl_value */
+ duk_pop(thr); /* repl_value */
} else {
r = r_start;
@@ -39477,9 +43500,10 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
* match codepoint encodings would have different lengths.
*/
/* XXX: charlen computed here, and also in char2byte helper. */
- match_end_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr,
- h_input,
- match_start_coff + (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_match));
+ match_end_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(
+ thr,
+ h_input,
+ match_start_coff + (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_match));
tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff);
DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + match_end_boff, tmp_sz);
@@ -39515,7 +43539,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
}
if (capnum > 0 && capnum < match_caps) {
- DUK_ASSERT(is_regexp != 0); /* match_caps == 0 without regexps */
+ DUK_ASSERT(is_regexp != 0); /* match_caps == 0 without regexps */
/* regexp res_obj is at offset 4 */
duk_get_prop_index(thr, 4, (duk_uarridx_t) capnum);
@@ -39534,26 +43558,26 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
} else {
goto repl_write;
}
-#else /* DUK_USE_REGEXP_SUPPORT */
- goto repl_write; /* unconditionally */
-#endif /* DUK_USE_REGEXP_SUPPORT */
- } /* default case */
- } /* switch (ch2) */
+#else /* DUK_USE_REGEXP_SUPPORT */
+ goto repl_write; /* unconditionally */
+#endif /* DUK_USE_REGEXP_SUPPORT */
+ } /* default case */
+ } /* switch (ch2) */
- repl_write:
+ repl_write:
/* ch1 = (r_increment << 8) + byte */
DUK_BW_WRITE_ENSURE_U8(thr, bw, (duk_uint8_t) (ch1 & 0xff));
r += ch1 >> 8;
- } /* while repl */
- } /* if (is_repl_func) */
+ } /* while repl */
+ } /* if (is_repl_func) */
- duk_pop(thr); /* pop regexp res_obj or match string */
+ duk_pop(thr); /* pop regexp res_obj or match string */
#if defined(DUK_USE_REGEXP_SUPPORT)
if (!is_global) {
#else
- { /* unconditionally; is_global==0 */
+ { /* unconditionally; is_global==0 */
#endif
break;
}
@@ -39565,7 +43589,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
DUK_ASSERT_TOP(thr, 4);
DUK_BW_COMPACT(thr, bw);
- (void) duk_buffer_to_string(thr, -1); /* Safe if inputs are safe. */
+ (void) duk_buffer_to_string(thr, -1); /* Safe if inputs are safe. */
return 1;
}
@@ -39585,7 +43609,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {
#if defined(DUK_USE_REGEXP_SUPPORT)
duk_bool_t is_regexp;
#endif
- duk_bool_t matched; /* set to 1 if any match exists (needed for empty input special case) */
+ duk_bool_t matched; /* set to 1 if any match exists (needed for empty input special case) */
duk_uint32_t prev_match_end_coff, prev_match_end_boff;
duk_uint32_t match_start_boff, match_start_coff;
duk_uint32_t match_end_boff, match_end_coff;
@@ -39623,7 +43647,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {
#if defined(DUK_USE_REGEXP_SUPPORT)
duk_push_hobject_bidx(thr, DUK_BIDX_REGEXP_CONSTRUCTOR);
duk_dup_0(thr);
- duk_new(thr, 1); /* [ ... RegExp val ] -> [ ... res ] */
+ duk_new(thr, 1); /* [ ... RegExp val ] -> [ ... res ] */
duk_replace(thr, 0);
/* lastIndex is initialized to zero by new RegExp() */
is_regexp = 1;
@@ -39662,7 +43686,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {
if (is_regexp) {
duk_dup_0(thr);
duk_dup_2(thr);
- duk_regexp_match_force_global(thr); /* [ ... regexp input ] -> [ res_obj ] */
+ duk_regexp_match_force_global(thr); /* [ ... regexp input ] -> [ res_obj ] */
if (!duk_is_object(thr, -1)) {
duk_pop(thr);
break;
@@ -39695,23 +43719,23 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {
continue;
}
} else {
-#else /* DUK_USE_REGEXP_SUPPORT */
- { /* unconditionally */
-#endif /* DUK_USE_REGEXP_SUPPORT */
- const duk_uint8_t *p_start, *p_end, *p; /* input string scan */
- const duk_uint8_t *q_start; /* match string */
+#else /* DUK_USE_REGEXP_SUPPORT */
+ { /* unconditionally */
+#endif /* DUK_USE_REGEXP_SUPPORT */
+ const duk_uint8_t *p_start, *p_end, *p; /* input string scan */
+ const duk_uint8_t *q_start; /* match string */
duk_size_t q_blen, q_clen;
p_start = DUK_HSTRING_GET_DATA(h_input);
p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
p = p_start + prev_match_end_boff;
- h_sep = duk_known_hstring(thr, 0); /* symbol already rejected above */
+ h_sep = duk_known_hstring(thr, 0); /* symbol already rejected above */
q_start = DUK_HSTRING_GET_DATA(h_sep);
q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sep);
q_clen = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_sep);
- p_end -= q_blen; /* ensure full memcmp() fits in while */
+ p_end -= q_blen; /* ensure full memcmp() fits in while */
match_start_coff = prev_match_end_coff;
@@ -39724,7 +43748,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {
* Don't allow an empty string to match at the end of the input.
*/
- matched = 1; /* empty separator can always match */
+ matched = 1; /* empty separator can always match */
match_start_coff++;
p++;
@@ -39740,8 +43764,8 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {
DUK_ASSERT(q_blen > 0 && q_clen > 0);
while (p <= p_end) {
DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
- DUK_ASSERT(q_blen > 0); /* no issues with empty memcmp() */
- if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
+ DUK_ASSERT(q_blen > 0); /* no issues with empty memcmp() */
+ if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
/* never an empty match, so step 13.c.iii can't be triggered */
goto found;
}
@@ -39753,15 +43777,15 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {
p++;
}
- not_found:
+ not_found:
/* not found */
break;
- found:
+ found:
matched = 1;
match_start_boff = (duk_uint32_t) (p - p_start);
- match_end_coff = (duk_uint32_t) (match_start_coff + q_clen); /* constrained by string length */
- match_end_boff = (duk_uint32_t) (match_start_boff + q_blen); /* ditto */
+ match_end_coff = (duk_uint32_t) (match_start_coff + q_clen); /* constrained by string length */
+ match_end_boff = (duk_uint32_t) (match_start_boff + q_blen); /* ditto */
/* empty match (may happen with empty separator) -> bump and continue */
if (prev_match_end_boff == match_end_boff) {
@@ -39769,7 +43793,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {
prev_match_end_coff++;
continue;
}
- } /* if (is_regexp) */
+ } /* if (is_regexp) */
/* stack[0] = separator (string or regexp)
* stack[1] = limit
@@ -39779,9 +43803,12 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {
*/
DUK_DDD(DUK_DDDPRINT("split; match_start b=%ld,c=%ld, match_end b=%ld,c=%ld, prev_end b=%ld,c=%ld",
- (long) match_start_boff, (long) match_start_coff,
- (long) match_end_boff, (long) match_end_coff,
- (long) prev_match_end_boff, (long) prev_match_end_coff));
+ (long) match_start_boff,
+ (long) match_start_coff,
+ (long) match_end_boff,
+ (long) match_end_coff,
+ (long) prev_match_end_boff,
+ (long) prev_match_end_coff));
duk_push_lstring(thr,
(const char *) (DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff),
@@ -39798,7 +43825,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {
len = duk_get_length(thr, 4);
for (i = 1; i < len; i++) {
- DUK_ASSERT(i <= DUK_UARRIDX_MAX); /* cannot have >4G captures */
+ DUK_ASSERT(i <= DUK_UARRIDX_MAX); /* cannot have >4G captures */
duk_get_prop_index(thr, 4, (duk_uarridx_t) i);
duk_put_prop_index(thr, 3, arr_idx);
arr_idx++;
@@ -39810,21 +43837,21 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {
duk_pop(thr);
/* lastIndex already set up for next match */
} else {
-#else /* DUK_USE_REGEXP_SUPPORT */
- { /* unconditionally */
-#endif /* DUK_USE_REGEXP_SUPPORT */
+#else /* DUK_USE_REGEXP_SUPPORT */
+ {
+ /* unconditionally */
+#endif /* DUK_USE_REGEXP_SUPPORT */
/* no action */
}
prev_match_end_boff = match_end_boff;
prev_match_end_coff = match_end_coff;
continue;
- } /* for */
+ } /* for */
/* Combined step 11 (empty string special case) and 14-15. */
- DUK_DDD(DUK_DDDPRINT("split trailer; prev_end b=%ld,c=%ld",
- (long) prev_match_end_boff, (long) prev_match_end_coff));
+ DUK_DDD(DUK_DDDPRINT("split trailer; prev_end b=%ld,c=%ld", (long) prev_match_end_boff, (long) prev_match_end_coff));
if (DUK_HSTRING_GET_BYTELEN(h_input) > 0 || !matched) {
/* Add trailer if:
@@ -39841,7 +43868,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {
return 1;
- hit_limit:
+hit_limit:
#if defined(DUK_USE_REGEXP_SUPPORT)
if (is_regexp) {
duk_pop(thr);
@@ -39873,13 +43900,13 @@ DUK_LOCAL void duk__to_regexp_helper(duk_hthread *thr, duk_idx_t idx, duk_bool_t
}
return;
- do_new:
+do_new:
duk_push_hobject_bidx(thr, DUK_BIDX_REGEXP_CONSTRUCTOR);
duk_dup(thr, idx);
- duk_new(thr, 1); /* [ ... RegExp val ] -> [ ... res ] */
+ duk_new(thr, 1); /* [ ... RegExp val ] -> [ ... res ] */
duk_replace(thr, idx);
}
-#endif /* DUK_USE_REGEXP_SUPPORT */
+#endif /* DUK_USE_REGEXP_SUPPORT */
#if defined(DUK_USE_REGEXP_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_search(duk_hthread *thr) {
@@ -39894,7 +43921,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_search(duk_hthread *thr) {
*/
DUK_ASSERT_TOP(thr, 1);
- (void) duk_push_this_coercible_to_string(thr); /* at index 1 */
+ (void) duk_push_this_coercible_to_string(thr); /* at index 1 */
duk__to_regexp_helper(thr, 0 /*index*/, 1 /*force_new*/);
/* stack[0] = regexp
@@ -39906,8 +43933,8 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_search(duk_hthread *thr) {
*/
duk_dup_0(thr);
- duk_dup_1(thr); /* [ ... re_obj input ] */
- duk_regexp_match(thr); /* -> [ ... res_obj ] */
+ duk_dup_1(thr); /* [ ... re_obj input ] */
+ duk_regexp_match(thr); /* -> [ ... res_obj ] */
if (!duk_is_object(thr, -1)) {
duk_push_int(thr, -1);
@@ -39918,7 +43945,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_search(duk_hthread *thr) {
DUK_ASSERT(duk_is_number(thr, -1));
return 1;
}
-#endif /* DUK_USE_REGEXP_SUPPORT */
+#endif /* DUK_USE_REGEXP_SUPPORT */
#if defined(DUK_USE_REGEXP_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_match(duk_hthread *thr) {
@@ -39938,8 +43965,8 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_match(duk_hthread *thr) {
*/
if (!global) {
- duk_regexp_match(thr); /* -> [ res_obj ] */
- return 1; /* return 'res_obj' */
+ duk_regexp_match(thr); /* -> [ res_obj ] */
+ return 1; /* return 'res_obj' */
}
/* Global case is more complex. */
@@ -39960,7 +43987,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_match(duk_hthread *thr) {
duk_dup_0(thr);
duk_dup_1(thr);
- duk_regexp_match(thr); /* -> [ ... regexp string ] -> [ ... res_obj ] */
+ duk_regexp_match(thr); /* -> [ ... regexp string ] -> [ ... res_obj ] */
if (!duk_is_object(thr, -1)) {
duk_pop(thr);
@@ -39979,24 +44006,24 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_match(duk_hthread *thr) {
}
prev_last_index = this_index;
- duk_get_prop_index(thr, -1, 0); /* match string */
+ duk_get_prop_index(thr, -1, 0); /* match string */
duk_put_prop_index(thr, 2, (duk_uarridx_t) arr_idx);
arr_idx++;
- duk_pop(thr); /* res_obj */
+ duk_pop(thr); /* res_obj */
}
if (arr_idx == 0) {
duk_push_null(thr);
}
- return 1; /* return 'res_arr' or 'null' */
+ return 1; /* return 'res_arr' or 'null' */
}
-#endif /* DUK_USE_REGEXP_SUPPORT */
+#endif /* DUK_USE_REGEXP_SUPPORT */
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_concat(duk_hthread *thr) {
/* duk_concat() coerces arguments with ToString() in correct order */
(void) duk_push_this_coercible_to_string(thr);
- duk_insert(thr, 0); /* this is relatively expensive */
+ duk_insert(thr, 0); /* this is relatively expensive */
duk_concat(thr, duk_get_top(thr));
return 1;
}
@@ -40054,15 +44081,17 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_repeat(duk_hthread *thr) {
/* Temporary fixed buffer, later converted to string. */
buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, result_len);
+ DUK_ASSERT(buf != NULL);
src = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
+ DUK_ASSERT(src != NULL);
#if defined(DUK_USE_PREFER_SIZE)
p = buf;
while (count-- > 0) {
- DUK_MEMCPY((void *) p, (const void *) src, input_blen); /* copy size may be zero */
+ duk_memcpy((void *) p, (const void *) src, input_blen); /* copy size may be zero, but pointers are valid */
p += input_blen;
}
-#else /* DUK_USE_PREFER_SIZE */
+#else /* DUK_USE_PREFER_SIZE */
/* Take advantage of already copied pieces to speed up the process
* especially for small repeated strings.
*/
@@ -40072,23 +44101,25 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_repeat(duk_hthread *thr) {
for (;;) {
duk_size_t remain = (duk_size_t) (p_end - p);
DUK_DDD(DUK_DDDPRINT("remain=%ld, copy_size=%ld, input_blen=%ld, result_len=%ld",
- (long) remain, (long) copy_size, (long) input_blen,
+ (long) remain,
+ (long) copy_size,
+ (long) input_blen,
(long) result_len));
if (remain <= copy_size) {
/* If result_len is zero, this case is taken and does
- * a zero size copy.
+ * a zero size copy (with valid pointers).
*/
- DUK_MEMCPY((void *) p, (const void *) src, remain);
+ duk_memcpy((void *) p, (const void *) src, remain);
break;
} else {
- DUK_MEMCPY((void *) p, (const void *) src, copy_size);
+ duk_memcpy((void *) p, (const void *) src, copy_size);
p += copy_size;
}
- src = (const duk_uint8_t *) buf; /* Use buf as source for larger copies. */
+ src = (const duk_uint8_t *) buf; /* Use buf as source for larger copies. */
copy_size = (duk_size_t) (p - buf);
}
-#endif /* DUK_USE_PREFER_SIZE */
+#endif /* DUK_USE_PREFER_SIZE */
/* XXX: It would be useful to be able to create a duk_hstring with
* a certain byte size whose data area wasn't initialized and which
@@ -40099,13 +44130,13 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_repeat(duk_hthread *thr) {
* intern table (they are not in heap_allocated).
*/
- duk_buffer_to_string(thr, -1); /* Safe if input is safe. */
+ duk_buffer_to_string(thr, -1); /* Safe if input is safe. */
return 1;
- fail_range:
+fail_range:
DUK_DCERROR_RANGE_INVALID_ARGS(thr);
}
-#endif /* DUK_USE_ES6 */
+#endif /* DUK_USE_ES6 */
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_locale_compare(duk_hthread *thr) {
duk_hstring *h1;
@@ -40136,8 +44167,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_locale_compare(duk_hthread *thr)
h2_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
prefix_len = (h1_len <= h2_len ? h1_len : h2_len);
- /* Zero size compare not an issue with DUK_MEMCMP. */
- rc = (duk_small_int_t) DUK_MEMCMP((const void *) DUK_HSTRING_GET_DATA(h1),
+ rc = (duk_small_int_t) duk_memcmp((const void *) DUK_HSTRING_GET_DATA(h1),
(const void *) DUK_HSTRING_GET_DATA(h2),
(size_t) prefix_len);
@@ -40160,7 +44190,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_locale_compare(duk_hthread *thr)
ret = -1;
goto done;
- done:
+done:
duk_push_int(thr, (duk_int_t) ret);
return 1;
}
@@ -40168,44 +44198,65 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_locale_compare(duk_hthread *thr)
#if defined(DUK_USE_ES6)
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_hthread *thr) {
duk_int_t magic;
- duk_hstring *h;
+ duk_hstring *h_target;
+ duk_size_t blen_target;
duk_hstring *h_search;
duk_size_t blen_search;
- const duk_uint8_t *p_cmp_start;
- duk_bool_t result;
+ duk_int_t off;
+ duk_bool_t result = 0;
+ duk_size_t blen_left;
- h = duk_push_this_coercible_to_string(thr);
- DUK_ASSERT(h != NULL);
+ /* Because string byte lengths are in [0,DUK_INT_MAX] it's safe to
+ * subtract two string lengths without overflow.
+ */
+ DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= DUK_INT_MAX);
+
+ h_target = duk_push_this_coercible_to_string(thr);
+ DUK_ASSERT(h_target != NULL);
h_search = duk__str_tostring_notregexp(thr, 0);
DUK_ASSERT(h_search != NULL);
magic = duk_get_current_magic(thr);
- p_cmp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
+ /* Careful to avoid pointer overflows in the matching logic. */
+
+ blen_target = DUK_HSTRING_GET_BYTELEN(h_target);
blen_search = DUK_HSTRING_GET_BYTELEN(h_search);
+#if 0
+ /* If search string is longer than the target string, we can
+ * never match. Could check explicitly, but should be handled
+ * correctly below.
+ */
+ if (blen_search > blen_target) {
+ goto finish;
+ }
+#endif
+
+ off = 0;
if (duk_is_undefined(thr, 1)) {
if (magic) {
- p_cmp_start += DUK_HSTRING_GET_BYTELEN(h) - blen_search;
+ off = (duk_int_t) blen_target - (duk_int_t) blen_search;
} else {
- /* p_cmp_start already OK */
+ DUK_ASSERT(off == 0);
}
} else {
duk_int_t len;
duk_int_t pos;
DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= DUK_INT_MAX);
- len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
+ len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_target);
pos = duk_to_int_clamped(thr, 1, 0, len);
DUK_ASSERT(pos >= 0 && pos <= len);
+ off = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_target, (duk_uint_fast32_t) pos);
if (magic) {
- p_cmp_start -= blen_search; /* Conceptually subtracted last, but do already here. */
+ off -= (duk_int_t) blen_search;
}
- DUK_ASSERT(pos >= 0 && pos <= len);
-
- p_cmp_start += duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) pos);
+ }
+ if (off < 0 || off > (duk_int_t) blen_target) {
+ goto finish;
}
/* The main comparison can be done using a memcmp() rather than
@@ -40215,20 +44266,22 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_hthread *
* comparison range.
*/
- result = 0;
- if (p_cmp_start >= DUK_HSTRING_GET_DATA(h) &&
- (duk_size_t) (p_cmp_start - (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h)) + blen_search <= DUK_HSTRING_GET_BYTELEN(h)) {
- if (DUK_MEMCMP((const void *) p_cmp_start,
- (const void *) DUK_HSTRING_GET_DATA(h_search),
- (size_t) blen_search) == 0) {
+ DUK_ASSERT(off >= 0);
+ DUK_ASSERT((duk_size_t) off <= blen_target);
+ blen_left = blen_target - (duk_size_t) off;
+ if (blen_left >= blen_search) {
+ const duk_uint8_t *p_cmp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_target) + off;
+ const duk_uint8_t *p_search = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_search);
+ if (duk_memcmp_unsafe((const void *) p_cmp_start, (const void *) p_search, (size_t) blen_search) == 0) {
result = 1;
}
}
+finish:
duk_push_boolean(thr, result);
return 1;
}
-#endif /* DUK_USE_ES6 */
+#endif /* DUK_USE_ES6 */
#if defined(DUK_USE_ES6)
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_includes(duk_hthread *thr) {
@@ -40251,8 +44304,8 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_includes(duk_hthread *thr) {
duk_push_boolean(thr, pos >= 0);
return 1;
}
-#endif /* DUK_USE_ES6 */
-#endif /* DUK_USE_STRING_BUILTIN */
+#endif /* DUK_USE_ES6 */
+#endif /* DUK_USE_STRING_BUILTIN */
/*
* Symbol built-in
*/
@@ -40292,9 +44345,10 @@ DUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_hthread *thr) {
* +1 0xff after unique suffix for symbols with undefined description
*/
buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, 1 + len + 1 + 17 + 1);
+ DUK_ASSERT(buf != NULL);
p = buf + 1;
- DUK_ASSERT(desc != NULL || len == 0); /* may be NULL if len is 0 */
- DUK_MEMCPY((void *) p, (const void *) desc, len);
+ DUK_ASSERT(desc != NULL || len == 0); /* may be NULL if len is 0 */
+ duk_memcpy_unsafe((void *) p, (const void *) desc, len);
p += len;
if (magic == 0) {
/* Symbol(): create unique symbol. Use two 32-bit values
@@ -40304,7 +44358,9 @@ DUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_hthread *thr) {
if (++thr->heap->sym_counter[0] == 0) {
thr->heap->sym_counter[1]++;
}
- p += DUK_SPRINTF((char *) p, "\xFF" "%lx-%lx",
+ p += DUK_SPRINTF((char *) p,
+ "\xFF"
+ "%lx-%lx",
(unsigned long) thr->heap->sym_counter[1],
(unsigned long) thr->heap->sym_counter[0]);
if (desc == NULL) {
@@ -40327,7 +44383,6 @@ DUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_hthread *thr) {
DUK_LOCAL duk_hstring *duk__auto_unbox_symbol(duk_hthread *thr, duk_tval *tv_arg) {
duk_tval *tv;
- duk_tval tv_val;
duk_hobject *h_obj;
duk_hstring *h_str;
@@ -40341,10 +44396,10 @@ DUK_LOCAL duk_hstring *duk__auto_unbox_symbol(duk_hthread *thr, duk_tval *tv_arg
h_obj = DUK_TVAL_GET_OBJECT(tv);
DUK_ASSERT(h_obj != NULL);
if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_SYMBOL) {
- if (!duk_hobject_get_internal_value(thr->heap, h_obj, &tv_val)) {
+ tv = duk_hobject_get_internal_value_tval_ptr(thr->heap, h_obj);
+ if (tv == NULL) {
return NULL;
}
- tv = &tv_val;
} else {
return NULL;
}
@@ -40422,7 +44477,7 @@ DUK_INTERNAL duk_ret_t duk_bi_symbol_toprimitive(duk_hthread *thr) {
return 1;
}
-#endif /* DUK_USE_SYMBOL_BUILTIN */
+#endif /* DUK_USE_SYMBOL_BUILTIN */
/*
* Thread builtins
*/
@@ -40456,7 +44511,7 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_constructor(duk_hthread *thr) {
*/
duk_push_hobject(new_thr, func);
- return 1; /* return thread */
+ return 1; /* return thread */
}
#endif
@@ -40465,7 +44520,7 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_constructor(duk_hthread *thr) {
*
* The thread must be in resumable state, either (a) new thread which hasn't
* yet started, or (b) a thread which has previously yielded. This method
- * must be called from an Ecmascript function.
+ * must be called from an ECMAScript function.
*
* Args:
* - thread
@@ -40491,8 +44546,9 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_hthread *ctx) {
DUK_ASSERT(thr->heap->curr_thread == thr);
thr_resume = duk_require_hthread(thr, 0);
- is_error = (duk_small_uint_t) duk_to_boolean(thr, 2);
- duk_set_top(thr, 2);
+ DUK_ASSERT(duk_get_top(thr) == 3);
+ is_error = (duk_small_uint_t) duk_to_boolean_top_pop(thr);
+ DUK_ASSERT(duk_get_top(thr) == 2);
/* [ thread value ] */
@@ -40501,18 +44557,19 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_hthread *ctx) {
*/
if (thr->callstack_top < 2) {
- DUK_DD(DUK_DDPRINT("resume state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.resume)"));
+ DUK_DD(DUK_DDPRINT(
+ "resume state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.resume)"));
goto state_error;
}
DUK_ASSERT(thr->callstack_curr != NULL);
DUK_ASSERT(thr->callstack_curr->parent != NULL);
- DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL); /* us */
+ DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL); /* us */
DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
- DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL); /* caller */
+ DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL); /* caller */
caller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent);
if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {
- DUK_DD(DUK_DDPRINT("resume state invalid: caller must be Ecmascript code"));
+ DUK_DD(DUK_DDPRINT("resume state invalid: caller must be ECMAScript code"));
goto state_error;
}
@@ -40520,14 +44577,12 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_hthread *ctx) {
* like for yield.
*/
- if (thr_resume->state != DUK_HTHREAD_STATE_INACTIVE &&
- thr_resume->state != DUK_HTHREAD_STATE_YIELDED) {
+ if (thr_resume->state != DUK_HTHREAD_STATE_INACTIVE && thr_resume->state != DUK_HTHREAD_STATE_YIELDED) {
DUK_DD(DUK_DDPRINT("resume state invalid: target thread must be INACTIVE or YIELDED"));
goto state_error;
}
- DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE ||
- thr_resume->state == DUK_HTHREAD_STATE_YIELDED);
+ DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE || thr_resume->state == DUK_HTHREAD_STATE_YIELDED);
/* Further state-dependent pre-checks */
@@ -40540,25 +44595,36 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_hthread *ctx) {
DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE);
- /* The initial function must be an Ecmascript function (but
+ /* The initial function must be an ECMAScript function (but
* can be bound). We must make sure of that before we longjmp
* because an error in the RESUME handler call processing will
* not be handled very cleanly.
*/
- if ((thr_resume->callstack_top != 0) ||
- (thr_resume->valstack_top - thr_resume->valstack != 1)) {
+ if ((thr_resume->callstack_top != 0) || (thr_resume->valstack_top - thr_resume->valstack != 1)) {
goto state_error;
}
duk_push_tval(thr, DUK_GET_TVAL_NEGIDX(thr_resume, -1));
duk_resolve_nonbound_function(thr);
- h_fun = duk_require_hobject(thr, -1); /* reject lightfuncs on purpose */
+ h_fun = duk_require_hobject(thr, -1); /* reject lightfuncs on purpose */
if (!DUK_HOBJECT_IS_CALLABLE(h_fun) || !DUK_HOBJECT_IS_COMPFUNC(h_fun)) {
goto state_error;
}
duk_pop(thr);
}
+#if 0
+ /* This check would prevent a heap destruction time finalizer from
+ * launching a coroutine, which would ensure that during finalization
+ * 'thr' would always equal heap_thread. Normal runtime finalizers
+ * run with ms_running == 0, i.e. outside mark-and-sweep. See GH-2030.
+ */
+ if (thr->heap->ms_running) {
+ DUK_D(DUK_DPRINT("refuse Duktape.Thread.resume() when ms_running != 0"));
+ goto state_error;
+ }
+#endif
+
/*
* The error object has been augmented with a traceback and other
* info from its creation point -- usually another thread. The
@@ -40569,8 +44635,8 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_hthread *ctx) {
#if defined(DUK_USE_AUGMENT_ERROR_THROW)
if (is_error) {
- DUK_ASSERT_TOP(thr, 2); /* value (error) is at stack top */
- duk_err_augment_error_throw(thr); /* in resumer's context */
+ DUK_ASSERT_TOP(thr, 2); /* value (error) is at stack top */
+ duk_err_augment_error_throw(thr); /* in resumer's context */
}
#endif
@@ -40594,21 +44660,21 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_hthread *ctx) {
/* lj value2: thread */
DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
- DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value2, &thr->valstack_bottom[0]); /* side effects */
+ DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value2, &thr->valstack_bottom[0]); /* side effects */
/* lj value1: value */
DUK_ASSERT(thr->valstack_bottom + 1 < thr->valstack_top);
- DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[1]); /* side effects */
+ DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[1]); /* side effects */
DUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);
thr->heap->lj.iserror = is_error;
- DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* call is from executor, so we know we have a jmpbuf */
- duk_err_longjmp(thr); /* execution resumes in bytecode executor */
+ DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* call is from executor, so we know we have a jmpbuf */
+ duk_err_longjmp(thr); /* execution resumes in bytecode executor */
DUK_UNREACHABLE();
/* Never here, fall through to error (from compiler point of view). */
- state_error:
+state_error:
DUK_DCERROR_TYPE_INVALID_STATE(thr);
}
#endif
@@ -40619,7 +44685,7 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_hthread *ctx) {
* The thread must be in yieldable state: it must have a resumer, and there
* must not be any yield-preventing calls (native calls and constructor calls,
* currently) in the thread's call stack (otherwise a resume would not be
- * possible later). This method must be called from an Ecmascript function.
+ * possible later). This method must be called from an ECMAScript function.
*
* Args:
* - value
@@ -40640,8 +44706,9 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_yield(duk_hthread *thr) {
DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
DUK_ASSERT(thr->heap->curr_thread == thr);
- is_error = (duk_small_uint_t) duk_to_boolean(thr, 1);
- duk_set_top(thr, 1);
+ DUK_ASSERT(duk_get_top(thr) == 2);
+ is_error = (duk_small_uint_t) duk_to_boolean_top_pop(thr);
+ DUK_ASSERT(duk_get_top(thr) == 1);
/* [ value ] */
@@ -40656,25 +44723,27 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_yield(duk_hthread *thr) {
DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
if (thr->callstack_top < 2) {
- DUK_DD(DUK_DDPRINT("yield state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.yield)"));
+ DUK_DD(DUK_DDPRINT(
+ "yield state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.yield)"));
goto state_error;
}
DUK_ASSERT(thr->callstack_curr != NULL);
DUK_ASSERT(thr->callstack_curr->parent != NULL);
- DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL); /* us */
+ DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL); /* us */
DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
- DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL); /* caller */
+ DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL); /* caller */
caller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent);
if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {
- DUK_DD(DUK_DDPRINT("yield state invalid: caller must be Ecmascript code"));
+ DUK_DD(DUK_DDPRINT("yield state invalid: caller must be ECMAScript code"));
goto state_error;
}
- DUK_ASSERT(thr->callstack_preventcount >= 1); /* should never be zero, because we (Duktape.Thread.yield) are on the stack */
+ DUK_ASSERT(thr->callstack_preventcount >= 1); /* should never be zero, because we (Duktape.Thread.yield) are on the stack */
if (thr->callstack_preventcount != 1) {
/* Note: the only yield-preventing call is Duktape.Thread.yield(), hence check for 1, not 0 */
- DUK_DD(DUK_DDPRINT("yield state invalid: there must be no yield-preventing calls in current thread callstack (preventcount is %ld)",
+ DUK_DD(DUK_DDPRINT("yield state invalid: there must be no yield-preventing calls in current thread callstack "
+ "(preventcount is %ld)",
(long) thr->callstack_preventcount));
goto state_error;
}
@@ -40688,18 +44757,16 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_yield(duk_hthread *thr) {
#if defined(DUK_USE_AUGMENT_ERROR_THROW)
if (is_error) {
- DUK_ASSERT_TOP(thr, 1); /* value (error) is at stack top */
- duk_err_augment_error_throw(thr); /* in yielder's context */
+ DUK_ASSERT_TOP(thr, 1); /* value (error) is at stack top */
+ duk_err_augment_error_throw(thr); /* in yielder's context */
}
#endif
#if defined(DUK_USE_DEBUG)
if (is_error) {
- DUK_DDD(DUK_DDDPRINT("YIELD ERROR: value=%!T",
- (duk_tval *) duk_get_tval(thr, 0)));
+ DUK_DDD(DUK_DDDPRINT("YIELD ERROR: value=%!T", (duk_tval *) duk_get_tval(thr, 0)));
} else {
- DUK_DDD(DUK_DDDPRINT("YIELD NORMAL: value=%!T",
- (duk_tval *) duk_get_tval(thr, 0)));
+ DUK_DDD(DUK_DDDPRINT("YIELD NORMAL: value=%!T", (duk_tval *) duk_get_tval(thr, 0)));
}
#endif
@@ -40714,17 +44781,17 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_yield(duk_hthread *thr) {
/* lj value1: value */
DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
- DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[0]); /* side effects */
+ DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[0]); /* side effects */
DUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);
thr->heap->lj.iserror = is_error;
- DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* call is from executor, so we know we have a jmpbuf */
- duk_err_longjmp(thr); /* execution resumes in bytecode executor */
+ DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* call is from executor, so we know we have a jmpbuf */
+ duk_err_longjmp(thr); /* execution resumes in bytecode executor */
DUK_UNREACHABLE();
/* Never here, fall through to error (from compiler point of view). */
- state_error:
+state_error:
DUK_DCERROR_TYPE_INVALID_STATE(thr);
}
#endif
@@ -40764,7 +44831,7 @@ DUK_INTERNAL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffe
} else {
copylen = length;
}
- DUK_MEMCPY(fb->buffer + fb->offset, buffer, copylen);
+ duk_memcpy_unsafe(fb->buffer + fb->offset, buffer, copylen);
fb->offset += copylen;
}
@@ -40802,7 +44869,7 @@ DUK_INTERNAL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...) {
}
DUK_INTERNAL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size) {
- char buf[64+1];
+ char buf[64 + 1];
duk_debug_format_funcptr(buf, sizeof(buf), fptr, fptr_size);
buf[sizeof(buf) - 1] = (char) 0;
duk_fb_put_cstring(fb, buf);
@@ -40812,7 +44879,7 @@ DUK_INTERNAL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) {
return (fb->offset >= fb->length);
}
-#endif /* DUK_USE_DEBUG */
+#endif /* DUK_USE_DEBUG */
/*
* Custom formatter for debug printing, allowing Duktape specific data
* structures (such as tagged values and heap objects) to be printed with
@@ -40826,7 +44893,9 @@ DUK_INTERNAL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) {
* %!T tagged value (duk_tval *)
* %!O heap object (duk_heaphdr *)
* %!I decoded bytecode instruction
- * %!C bytecode instruction opcode name (arg is long)
+ * %!X bytecode instruction opcode name (arg is long)
+ * %!C catcher (duk_catcher *)
+ * %!A activation (duk_activation *)
*
* Everything is serialized in a JSON-like manner. The default depth is one
* level, internal prototype is not followed, and internal properties are not
@@ -40850,7 +44919,7 @@ DUK_INTERNAL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) {
* (excluding the null terminator). If retval == buffer size,
* output was truncated (except for corner cases).
*
- * * Output format is intentionally different from Ecmascript
+ * * Output format is intentionally different from ECMAScript
* formatting requirements, as formatting here serves debugging
* of internals.
*
@@ -40876,58 +44945,58 @@ DUK_INTERNAL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) {
/* list of conversion specifiers that terminate a format tag;
* this is unfortunately guesswork.
*/
-#define DUK__ALLOWED_STANDARD_SPECIFIERS "diouxXeEfFgGaAcsCSpnm"
+#define DUK__ALLOWED_STANDARD_SPECIFIERS "diouxXeEfFgGaAcsCSpnm"
/* maximum length of standard format tag that we support */
-#define DUK__MAX_FORMAT_TAG_LENGTH 32
+#define DUK__MAX_FORMAT_TAG_LENGTH 32
/* heapobj recursion depth when deep printing is selected */
-#define DUK__DEEP_DEPTH_LIMIT 8
+#define DUK__DEEP_DEPTH_LIMIT 8
/* maximum recursion depth for loop detection stacks */
-#define DUK__LOOP_STACK_DEPTH 256
+#define DUK__LOOP_STACK_DEPTH 256
/* must match bytecode defines now; build autogenerate? */
DUK_LOCAL const char * const duk__bc_optab[256] = {
- "LDREG", "STREG", "JUMP", "LDCONST", "LDINT", "LDINTX", "LDTHIS", "LDUNDEF",
- "LDNULL", "LDTRUE", "LDFALSE", "GETVAR", "BNOT", "LNOT", "UNM", "UNP",
- "EQ_RR", "EQ_CR", "EQ_RC", "EQ_CC", "NEQ_RR", "NEQ_CR", "NEQ_RC", "NEQ_CC",
- "SEQ_RR", "SEQ_CR", "SEQ_RC", "SEQ_CC", "SNEQ_RR", "SNEQ_CR", "SNEQ_RC", "SNEQ_CC",
-
- "GT_RR", "GT_CR", "GT_RC", "GT_CC", "GE_RR", "GE_CR", "GE_RC", "GE_CC",
- "LT_RR", "LT_CR", "LT_RC", "LT_CC", "LE_RR", "LE_CR", "LE_RC", "LE_CC",
- "IFTRUE_R", "IFTRUE_C", "IFFALSE_R", "IFFALSE_C", "ADD_RR", "ADD_CR", "ADD_RC", "ADD_CC",
- "SUB_RR", "SUB_CR", "SUB_RC", "SUB_CC", "MUL_RR", "MUL_CR", "MUL_RC", "MUL_CC",
-
- "DIV_RR", "DIV_CR", "DIV_RC", "DIV_CC", "MOD_RR", "MOD_CR", "MOD_RC", "MOD_CC",
- "EXP_RR", "EXP_CR", "EXP_RC", "EXP_CC", "BAND_RR", "BAND_CR", "BAND_RC", "BAND_CC",
- "BOR_RR", "BOR_CR", "BOR_RC", "BOR_CC", "BXOR_RR", "BXOR_CR", "BXOR_RC", "BXOR_CC",
- "BASL_RR", "BASL_CR", "BASL_RC", "BASL_CC", "BLSR_RR", "BLSR_CR", "BLSR_RC", "BLSR_CC",
-
- "BASR_RR", "BASR_CR", "BASR_RC", "BASR_CC", "INSTOF_RR", "INSTOF_CR", "INSTOF_RC", "INSTOF_CC",
- "IN_RR", "IN_CR", "IN_RC", "IN_CC", "GETPROP_RR", "GETPROP_CR", "GETPROP_RC", "GETPROP_CC",
- "PUTPROP_RR", "PUTPROP_CR", "PUTPROP_RC", "PUTPROP_CC", "DELPROP_RR", "DELPROP_CR", "DELPROP_RC", "DELPROP_CC",
- "PREINCR", "PREDECR", "POSTINCR", "POSTDECR", "PREINCV", "PREDECV", "POSTINCV", "POSTDECV",
-
- "PREINCP_RR", "PREINCP_CR", "PREINCP_RC", "PREINCP_CC", "PREDECP_RR", "PREDECP_CR", "PREDECP_RC", "PREDECP_CC",
+ "LDREG", "STREG", "JUMP", "LDCONST", "LDINT", "LDINTX", "LDTHIS", "LDUNDEF",
+ "LDNULL", "LDTRUE", "LDFALSE", "GETVAR", "BNOT", "LNOT", "UNM", "UNP",
+ "EQ_RR", "EQ_CR", "EQ_RC", "EQ_CC", "NEQ_RR", "NEQ_CR", "NEQ_RC", "NEQ_CC",
+ "SEQ_RR", "SEQ_CR", "SEQ_RC", "SEQ_CC", "SNEQ_RR", "SNEQ_CR", "SNEQ_RC", "SNEQ_CC",
+
+ "GT_RR", "GT_CR", "GT_RC", "GT_CC", "GE_RR", "GE_CR", "GE_RC", "GE_CC",
+ "LT_RR", "LT_CR", "LT_RC", "LT_CC", "LE_RR", "LE_CR", "LE_RC", "LE_CC",
+ "IFTRUE_R", "IFTRUE_C", "IFFALSE_R", "IFFALSE_C", "ADD_RR", "ADD_CR", "ADD_RC", "ADD_CC",
+ "SUB_RR", "SUB_CR", "SUB_RC", "SUB_CC", "MUL_RR", "MUL_CR", "MUL_RC", "MUL_CC",
+
+ "DIV_RR", "DIV_CR", "DIV_RC", "DIV_CC", "MOD_RR", "MOD_CR", "MOD_RC", "MOD_CC",
+ "EXP_RR", "EXP_CR", "EXP_RC", "EXP_CC", "BAND_RR", "BAND_CR", "BAND_RC", "BAND_CC",
+ "BOR_RR", "BOR_CR", "BOR_RC", "BOR_CC", "BXOR_RR", "BXOR_CR", "BXOR_RC", "BXOR_CC",
+ "BASL_RR", "BASL_CR", "BASL_RC", "BASL_CC", "BLSR_RR", "BLSR_CR", "BLSR_RC", "BLSR_CC",
+
+ "BASR_RR", "BASR_CR", "BASR_RC", "BASR_CC", "INSTOF_RR", "INSTOF_CR", "INSTOF_RC", "INSTOF_CC",
+ "IN_RR", "IN_CR", "IN_RC", "IN_CC", "GETPROP_RR", "GETPROP_CR", "GETPROP_RC", "GETPROP_CC",
+ "PUTPROP_RR", "PUTPROP_CR", "PUTPROP_RC", "PUTPROP_CC", "DELPROP_RR", "DELPROP_CR", "DELPROP_RC", "DELPROP_CC",
+ "PREINCR", "PREDECR", "POSTINCR", "POSTDECR", "PREINCV", "PREDECV", "POSTINCV", "POSTDECV",
+
+ "PREINCP_RR", "PREINCP_CR", "PREINCP_RC", "PREINCP_CC", "PREDECP_RR", "PREDECP_CR", "PREDECP_RC", "PREDECP_CC",
"POSTINCP_RR", "POSTINCP_CR", "POSTINCP_RC", "POSTINCP_CC", "POSTDECP_RR", "POSTDECP_CR", "POSTDECP_RC", "POSTDECP_CC",
- "DECLVAR_RR", "DECLVAR_CR", "DECLVAR_RC", "DECLVAR_CC", "REGEXP_RR", "REGEXP_RC", "REGEXP_CR", "REGEXP_CC",
- "CLOSURE", "TYPEOF", "TYPEOFID", "PUTVAR", "DELVAR", "RETREG", "RETUNDEF", "RETCONST",
-
- "RETCONSTN", "LABEL", "ENDLABEL", "BREAK", "CONTINUE", "TRYCATCH", "ENDTRY", "ENDCATCH",
- "ENDFIN", "THROW", "INVLHS", "CSREG", "CSVAR_RR", "CSVAR_CR", "CSVAR_RC", "CSVAR_CC",
- "CALL0", "CALL1", "CALL2", "CALL3", "CALL4", "CALL5", "CALL6", "CALL7",
- "CALL8", "CALL9", "CALL10", "CALL11", "CALL12", "CALL13", "CALL14", "CALL15",
-
- "NEWOBJ", "NEWARR", "MPUTOBJ", "MPUTOBJI", "INITSET", "INITGET", "MPUTARR", "MPUTARRI",
- "SETALEN", "INITENUM", "NEXTENUM", "NEWTARGET", "DEBUGGER", "NOP", "INVALID", "UNUSED207",
- "GETPROPC_RR", "GETPROPC_CR", "GETPROPC_RC", "GETPROPC_CC", "UNUSED212", "UNUSED213", "UNUSED214", "UNUSED215",
- "UNUSED216", "UNUSED217", "UNUSED218", "UNUSED219", "UNUSED220", "UNUSED221", "UNUSED222", "UNUSED223",
-
- "UNUSED224", "UNUSED225", "UNUSED226", "UNUSED227", "UNUSED228", "UNUSED229", "UNUSED230", "UNUSED231",
- "UNUSED232", "UNUSED233", "UNUSED234", "UNUSED235", "UNUSED236", "UNUSED237", "UNUSED238", "UNUSED239",
- "UNUSED240", "UNUSED241", "UNUSED242", "UNUSED243", "UNUSED244", "UNUSED245", "UNUSED246", "UNUSED247",
- "UNUSED248", "UNUSED249", "UNUSED250", "UNUSED251", "UNUSED252", "UNUSED253", "UNUSED254", "UNUSED255"
+ "DECLVAR_RR", "DECLVAR_CR", "DECLVAR_RC", "DECLVAR_CC", "REGEXP_RR", "REGEXP_RC", "REGEXP_CR", "REGEXP_CC",
+ "CLOSURE", "TYPEOF", "TYPEOFID", "PUTVAR", "DELVAR", "RETREG", "RETUNDEF", "RETCONST",
+
+ "RETCONSTN", "LABEL", "ENDLABEL", "BREAK", "CONTINUE", "TRYCATCH", "ENDTRY", "ENDCATCH",
+ "ENDFIN", "THROW", "INVLHS", "CSREG", "CSVAR_RR", "CSVAR_CR", "CSVAR_RC", "CSVAR_CC",
+ "CALL0", "CALL1", "CALL2", "CALL3", "CALL4", "CALL5", "CALL6", "CALL7",
+ "CALL8", "CALL9", "CALL10", "CALL11", "CALL12", "CALL13", "CALL14", "CALL15",
+
+ "NEWOBJ", "NEWARR", "MPUTOBJ", "MPUTOBJI", "INITSET", "INITGET", "MPUTARR", "MPUTARRI",
+ "SETALEN", "INITENUM", "NEXTENUM", "NEWTARGET", "DEBUGGER", "NOP", "INVALID", "UNUSED207",
+ "GETPROPC_RR", "GETPROPC_CR", "GETPROPC_RC", "GETPROPC_CC", "UNUSED212", "UNUSED213", "UNUSED214", "UNUSED215",
+ "UNUSED216", "UNUSED217", "UNUSED218", "UNUSED219", "UNUSED220", "UNUSED221", "UNUSED222", "UNUSED223",
+
+ "UNUSED224", "UNUSED225", "UNUSED226", "UNUSED227", "UNUSED228", "UNUSED229", "UNUSED230", "UNUSED231",
+ "UNUSED232", "UNUSED233", "UNUSED234", "UNUSED235", "UNUSED236", "UNUSED237", "UNUSED238", "UNUSED239",
+ "UNUSED240", "UNUSED241", "UNUSED242", "UNUSED243", "UNUSED244", "UNUSED245", "UNUSED246", "UNUSED247",
+ "UNUSED248", "UNUSED249", "UNUSED250", "UNUSED251", "UNUSED252", "UNUSED253", "UNUSED254", "UNUSED255"
};
typedef struct duk__dprint_state duk__dprint_state;
@@ -40977,14 +45046,15 @@ DUK_LOCAL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h)
duk_size_t i;
duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
- duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
+ duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *) h)[i]);
}
duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
}
-#if defined(DUK_USE_REFERENCE_COUNTING) /* currently implicitly also DUK_USE_DOUBLE_LINKED_HEAP */
+#if defined(DUK_USE_REFERENCE_COUNTING) /* currently implicitly also DUK_USE_DOUBLE_LINKED_HEAP */
if (st->heavy) {
- duk_fb_sprintf(fb, "[h_next=%p,h_prev=%p,h_refcount=%lu,h_flags=%08lx,type=%ld,"
+ duk_fb_sprintf(fb,
+ "[h_next=%p,h_prev=%p,h_refcount=%lu,h_flags=%08lx,type=%ld,"
"reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
(void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
(void *) DUK_HEAPHDR_GET_PREV(NULL, h),
@@ -40998,7 +45068,8 @@ DUK_LOCAL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h)
}
#else
if (st->heavy) {
- duk_fb_sprintf(fb, "[h_next=%p,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
+ duk_fb_sprintf(fb,
+ "[h_next=%p,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
(void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
(unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
(long) DUK_HEAPHDR_GET_TYPE(h),
@@ -41025,14 +45096,15 @@ DUK_LOCAL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaph
duk_size_t i;
duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
- duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
+ duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *) h)[i]);
}
duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
}
#if defined(DUK_USE_REFERENCE_COUNTING)
if (st->heavy) {
- duk_fb_sprintf(fb, "[h_refcount=%lu,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
+ duk_fb_sprintf(fb,
+ "[h_refcount=%lu,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
(unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h),
(unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
(long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
@@ -41043,7 +45115,8 @@ DUK_LOCAL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaph
}
#else
if (st->heavy) {
- duk_fb_sprintf(fb, "[h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
+ duk_fb_sprintf(fb,
+ "[h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
(unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
(long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
(long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
@@ -41114,7 +45187,8 @@ DUK_LOCAL void duk__print_hstring(duk__dprint_state *st, duk_hstring *h, duk_boo
#endif
}
-#define DUK__COMMA() do { \
+#define DUK__COMMA() \
+ do { \
if (first) { \
first = 0; \
} else { \
@@ -41227,7 +45301,8 @@ DUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) {
duk__print_hstring(st, key, 0);
duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COLON);
if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(NULL, h, i)) {
- duk_fb_sprintf(fb, "[get:%p,set:%p]",
+ duk_fb_sprintf(fb,
+ "[get:%p,set:%p]",
(void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.get,
(void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.set);
} else {
@@ -41241,158 +45316,238 @@ DUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) {
}
if (st->internal) {
if (DUK_HOBJECT_IS_ARRAY(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__array:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__array:true");
}
if (DUK_HOBJECT_HAS_EXTENSIBLE(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__extensible:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__extensible:true");
}
if (DUK_HOBJECT_HAS_CONSTRUCTABLE(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__constructable:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__constructable:true");
}
if (DUK_HOBJECT_HAS_BOUNDFUNC(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__boundfunc:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__boundfunc:true");
}
if (DUK_HOBJECT_HAS_COMPFUNC(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__compfunc:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__compfunc:true");
}
if (DUK_HOBJECT_HAS_NATFUNC(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__natfunc:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__natfunc:true");
}
if (DUK_HOBJECT_HAS_BUFOBJ(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__bufobj:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__bufobj:true");
}
if (DUK_HOBJECT_IS_THREAD(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__thread:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__thread:true");
}
if (DUK_HOBJECT_HAS_ARRAY_PART(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__array_part:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__array_part:true");
}
if (DUK_HOBJECT_HAS_STRICT(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__strict:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__strict:true");
}
if (DUK_HOBJECT_HAS_NOTAIL(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__notail:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__notail:true");
}
if (DUK_HOBJECT_HAS_NEWENV(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__newenv:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__newenv:true");
}
if (DUK_HOBJECT_HAS_NAMEBINDING(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__namebinding:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__namebinding:true");
}
if (DUK_HOBJECT_HAS_CREATEARGS(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__createargs:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__createargs:true");
}
if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_array:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__exotic_array:true");
}
if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_stringobj:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__exotic_stringobj:true");
}
if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_arguments:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__exotic_arguments:true");
}
if (DUK_HOBJECT_IS_BUFOBJ(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_bufobj:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__exotic_bufobj:true");
}
if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_proxyobj:true");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__exotic_proxyobj:true");
}
}
if (st->internal && DUK_HOBJECT_IS_ARRAY(h)) {
duk_harray *a = (duk_harray *) h;
- DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) a->length);
- DUK__COMMA(); duk_fb_sprintf(fb, "__length_nonwritable:%ld", (long) a->length_nonwritable);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__length:%ld", (long) a->length);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__length_nonwritable:%ld", (long) a->length_nonwritable);
} else if (st->internal && DUK_HOBJECT_IS_COMPFUNC(h)) {
duk_hcompfunc *f = (duk_hcompfunc *) h;
- DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
+ DUK__COMMA();
+ duk_fb_put_cstring(fb, "__data:");
duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
- DUK__COMMA(); duk_fb_put_cstring(fb, "__lexenv:"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_LEXENV(NULL, f));
- DUK__COMMA(); duk_fb_put_cstring(fb, "__varenv:"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_VARENV(NULL, f));
- DUK__COMMA(); duk_fb_sprintf(fb, "__nregs:%ld", (long) f->nregs);
- DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
+ DUK__COMMA();
+ duk_fb_put_cstring(fb, "__lexenv:");
+ duk__print_hobject(st, DUK_HCOMPFUNC_GET_LEXENV(NULL, f));
+ DUK__COMMA();
+ duk_fb_put_cstring(fb, "__varenv:");
+ duk__print_hobject(st, DUK_HCOMPFUNC_GET_VARENV(NULL, f));
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__nregs:%ld", (long) f->nregs);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
#if defined(DUK_USE_DEBUGGER_SUPPORT)
- DUK__COMMA(); duk_fb_sprintf(fb, "__start_line:%ld", (long) f->start_line);
- DUK__COMMA(); duk_fb_sprintf(fb, "__end_line:%ld", (long) f->end_line);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__start_line:%ld", (long) f->start_line);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__end_line:%ld", (long) f->end_line);
#endif
- DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
+ DUK__COMMA();
+ duk_fb_put_cstring(fb, "__data:");
duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
} else if (st->internal && DUK_HOBJECT_IS_NATFUNC(h)) {
duk_hnatfunc *f = (duk_hnatfunc *) h;
- DUK__COMMA(); duk_fb_sprintf(fb, "__func:");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__func:");
duk_fb_put_funcptr(fb, (duk_uint8_t *) &f->func, sizeof(f->func));
- DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
- DUK__COMMA(); duk_fb_sprintf(fb, "__magic:%ld", (long) f->magic);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__magic:%ld", (long) f->magic);
} else if (st->internal && DUK_HOBJECT_IS_DECENV(h)) {
duk_hdecenv *e = (duk_hdecenv *) h;
- DUK__COMMA(); duk_fb_sprintf(fb, "__thread:"); duk__print_hobject(st, (duk_hobject *) e->thread);
- DUK__COMMA(); duk_fb_sprintf(fb, "__varmap:"); duk__print_hobject(st, (duk_hobject *) e->varmap);
- DUK__COMMA(); duk_fb_sprintf(fb, "__regbase_byteoff:%ld", (long) e->regbase_byteoff);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__thread:");
+ duk__print_hobject(st, (duk_hobject *) e->thread);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__varmap:");
+ duk__print_hobject(st, (duk_hobject *) e->varmap);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__regbase_byteoff:%ld", (long) e->regbase_byteoff);
} else if (st->internal && DUK_HOBJECT_IS_OBJENV(h)) {
duk_hobjenv *e = (duk_hobjenv *) h;
- DUK__COMMA(); duk_fb_sprintf(fb, "__target:"); duk__print_hobject(st, (duk_hobject *) e->target);
- DUK__COMMA(); duk_fb_sprintf(fb, "__has_this:%ld", (long) e->has_this);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__target:");
+ duk__print_hobject(st, (duk_hobject *) e->target);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__has_this:%ld", (long) e->has_this);
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
} else if (st->internal && DUK_HOBJECT_IS_BUFOBJ(h)) {
duk_hbufobj *b = (duk_hbufobj *) h;
- DUK__COMMA(); duk_fb_sprintf(fb, "__buf:");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__buf:");
duk__print_hbuffer(st, (duk_hbuffer *) b->buf);
- DUK__COMMA(); duk_fb_sprintf(fb, "__buf_prop:");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__buf_prop:");
duk__print_hobject(st, (duk_hobject *) b->buf_prop);
- DUK__COMMA(); duk_fb_sprintf(fb, "__offset:%ld", (long) b->offset);
- DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) b->length);
- DUK__COMMA(); duk_fb_sprintf(fb, "__shift:%ld", (long) b->shift);
- DUK__COMMA(); duk_fb_sprintf(fb, "__elemtype:%ld", (long) b->elem_type);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__offset:%ld", (long) b->offset);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__length:%ld", (long) b->length);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__shift:%ld", (long) b->shift);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__elemtype:%ld", (long) b->elem_type);
#endif
} else if (st->internal && DUK_HOBJECT_IS_PROXY(h)) {
duk_hproxy *p = (duk_hproxy *) h;
- DUK__COMMA(); duk_fb_sprintf(fb, "__target:");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__target:");
duk__print_hobject(st, p->target);
- DUK__COMMA(); duk_fb_sprintf(fb, "__handler:");
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__handler:");
duk__print_hobject(st, p->handler);
} else if (st->internal && DUK_HOBJECT_IS_THREAD(h)) {
duk_hthread *t = (duk_hthread *) h;
- DUK__COMMA(); duk_fb_sprintf(fb, "__ptr_curr_pc:%p", (void *) t->ptr_curr_pc);
- DUK__COMMA(); duk_fb_sprintf(fb, "__heap:%p", (void *) t->heap);
- DUK__COMMA(); duk_fb_sprintf(fb, "__strict:%ld", (long) t->strict);
- DUK__COMMA(); duk_fb_sprintf(fb, "__state:%ld", (long) t->state);
- DUK__COMMA(); duk_fb_sprintf(fb, "__unused1:%ld", (long) t->unused1);
- DUK__COMMA(); duk_fb_sprintf(fb, "__unused2:%ld", (long) t->unused2);
- DUK__COMMA(); duk_fb_sprintf(fb, "__valstack:%p", (void *) t->valstack);
- DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_end:%p/%ld", (void *) t->valstack_end, (long) (t->valstack_end - t->valstack));
- DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_alloc_end:%p/%ld", (void *) t->valstack_alloc_end, (long) (t->valstack_alloc_end - t->valstack));
- DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_bottom:%p/%ld", (void *) t->valstack_bottom, (long) (t->valstack_bottom - t->valstack));
- DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_top:%p/%ld", (void *) t->valstack_top, (long) (t->valstack_top - t->valstack));
- DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_curr:%p", (void *) t->callstack_curr);
- DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_top:%ld", (long) t->callstack_top);
- DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_preventcount:%ld", (long) t->callstack_preventcount);
- DUK__COMMA(); duk_fb_sprintf(fb, "__resumer:"); duk__print_hobject(st, (duk_hobject *) t->resumer);
- DUK__COMMA(); duk_fb_sprintf(fb, "__compile_ctx:%p", (void *) t->compile_ctx);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__ptr_curr_pc:%p", (void *) t->ptr_curr_pc);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__heap:%p", (void *) t->heap);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__strict:%ld", (long) t->strict);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__state:%ld", (long) t->state);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__unused1:%ld", (long) t->unused1);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__unused2:%ld", (long) t->unused2);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__valstack:%p", (void *) t->valstack);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__valstack_end:%p/%ld", (void *) t->valstack_end, (long) (t->valstack_end - t->valstack));
+ DUK__COMMA();
+ duk_fb_sprintf(fb,
+ "__valstack_alloc_end:%p/%ld",
+ (void *) t->valstack_alloc_end,
+ (long) (t->valstack_alloc_end - t->valstack));
+ DUK__COMMA();
+ duk_fb_sprintf(fb,
+ "__valstack_bottom:%p/%ld",
+ (void *) t->valstack_bottom,
+ (long) (t->valstack_bottom - t->valstack));
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__valstack_top:%p/%ld", (void *) t->valstack_top, (long) (t->valstack_top - t->valstack));
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__callstack_curr:%p", (void *) t->callstack_curr);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__callstack_top:%ld", (long) t->callstack_top);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__callstack_preventcount:%ld", (long) t->callstack_preventcount);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__resumer:");
+ duk__print_hobject(st, (duk_hobject *) t->resumer);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__compile_ctx:%p", (void *) t->compile_ctx);
#if defined(DUK_USE_INTERRUPT_COUNTER)
- DUK__COMMA(); duk_fb_sprintf(fb, "__interrupt_counter:%ld", (long) t->interrupt_counter);
- DUK__COMMA(); duk_fb_sprintf(fb, "__interrupt_init:%ld", (long) t->interrupt_init);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__interrupt_counter:%ld", (long) t->interrupt_counter);
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__interrupt_init:%ld", (long) t->interrupt_init);
#endif
/* XXX: print built-ins array? */
-
}
#if defined(DUK_USE_REFERENCE_COUNTING)
if (st->internal) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__refcount:%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h));
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__refcount:%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h));
}
#endif
if (st->internal) {
- DUK__COMMA(); duk_fb_sprintf(fb, "__class:%ld", (long) DUK_HOBJECT_GET_CLASS_NUMBER(h));
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__class:%ld", (long) DUK_HOBJECT_GET_CLASS_NUMBER(h));
}
- DUK__COMMA(); duk_fb_sprintf(fb, "__heapptr:%p", (void *) h); /* own pointer */
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__heapptr:%p", (void *) h); /* own pointer */
/* prototype should be last, for readability */
if (DUK_HOBJECT_GET_PROTOTYPE(NULL, h)) {
if (st->follow_proto) {
- DUK__COMMA(); duk_fb_put_cstring(fb, "__prototype:"); duk__print_hobject(st, DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
+ DUK__COMMA();
+ duk_fb_put_cstring(fb, "__prototype:");
+ duk__print_hobject(st, DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
} else {
- DUK__COMMA(); duk_fb_sprintf(fb, "__prototype:%p", (void *) DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
+ DUK__COMMA();
+ duk_fb_sprintf(fb, "__prototype:%p", (void *) DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
}
}
@@ -41418,7 +45573,7 @@ DUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) {
}
#endif
- finished:
+finished:
st->depth--;
if (pushed_loopstack) {
st->loop_stack_index--;
@@ -41445,12 +45600,14 @@ DUK_LOCAL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h) {
if (DUK_HBUFFER_HAS_DYNAMIC(h)) {
if (DUK_HBUFFER_HAS_EXTERNAL(h)) {
duk_hbuffer_external *g = (duk_hbuffer_external *) h;
- duk_fb_sprintf(fb, "buffer:external:%p:%ld",
+ duk_fb_sprintf(fb,
+ "buffer:external:%p:%ld",
(void *) DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(NULL, g),
(long) DUK_HBUFFER_EXTERNAL_GET_SIZE(g));
} else {
duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
- duk_fb_sprintf(fb, "buffer:dynamic:%p:%ld",
+ duk_fb_sprintf(fb,
+ "buffer:dynamic:%p:%ld",
(void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(NULL, g),
(long) DUK_HBUFFER_DYNAMIC_GET_SIZE(g));
}
@@ -41523,7 +45680,7 @@ DUK_LOCAL void duk__print_tval(duk__dprint_state *st, duk_tval *tv) {
duk_size_t i;
duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
for (i = 0; i < (duk_size_t) sizeof(*tv); i++) {
- duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)tv)[i]);
+ duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *) tv)[i]);
}
duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
}
@@ -41606,17 +45763,22 @@ DUK_LOCAL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins) {
/* XXX: option to fix opcode length so it lines up nicely */
if (op == DUK_OP_JUMP) {
- duk_int_t diff1 = (duk_int_t) (DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS); /* from next pc */
- duk_int_t diff2 = diff1 + 1; /* from curr pc */
-
- duk_fb_sprintf(fb, "%s %ld (to pc%c%ld)",
- (const char *) op_name, (long) diff1,
- (int) (diff2 >= 0 ? '+' : '-'), /* char format: use int */
+ duk_int_t diff1 = (duk_int_t) (DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS); /* from next pc */
+ duk_int_t diff2 = diff1 + 1; /* from curr pc */
+
+ duk_fb_sprintf(fb,
+ "%s %ld (to pc%c%ld)",
+ (const char *) op_name,
+ (long) diff1,
+ (int) (diff2 >= 0 ? '+' : '-'), /* char format: use int */
(long) (diff2 >= 0 ? diff2 : -diff2));
} else {
- duk_fb_sprintf(fb, "%s %ld, %ld, %ld",
- (const char *) op_name, (long) DUK_DEC_A(ins),
- (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));
+ duk_fb_sprintf(fb,
+ "%s %ld, %ld, %ld",
+ (const char *) op_name,
+ (long) DUK_DEC_A(ins),
+ (long) DUK_DEC_B(ins),
+ (long) DUK_DEC_C(ins));
}
}
@@ -41630,13 +45792,65 @@ DUK_LOCAL void duk__print_opcode(duk__dprint_state *st, duk_small_int_t opcode)
}
}
+DUK_LOCAL void duk__print_catcher(duk__dprint_state *st, duk_catcher *cat) {
+ duk_fixedbuffer *fb = st->fb;
+
+ if (duk_fb_is_full(fb)) {
+ return;
+ }
+
+ if (!cat) {
+ duk_fb_put_cstring(fb, "NULL");
+ return;
+ }
+
+ duk_fb_sprintf(fb,
+ "[catcher ptr=%p parent=%p varname=%p pc_base=%p, idx_base=%ld, flags=0x%08lx]",
+ (void *) cat,
+ (void *) cat->parent,
+ (void *) cat->h_varname,
+ (void *) cat->pc_base,
+ (long) cat->idx_base,
+ (unsigned long) cat->flags);
+}
+
+DUK_LOCAL void duk__print_activation(duk__dprint_state *st, duk_activation *act) {
+ duk_fixedbuffer *fb = st->fb;
+
+ if (duk_fb_is_full(fb)) {
+ return;
+ }
+
+ if (!act) {
+ duk_fb_put_cstring(fb, "NULL");
+ return;
+ }
+
+ /* prev_caller: conditional, omitted on purpose, it's rarely used. */
+ /* prev_line: conditional, omitted on purpose (but would be nice). */
+ duk_fb_sprintf(fb,
+ "[activation ptr=%p tv_func=<omit> func=%p parent=%p var_env=%p lex_env=%p cat=%p curr_pc=%p "
+ "bottom_byteoff=%ld retval_byteoff=%ld reserve_byteoff=%ld flags=%ld]",
+ (void *) act,
+ (void *) act->func,
+ (void *) act->parent,
+ (void *) act->var_env,
+ (void *) act->lex_env,
+ (void *) act->cat,
+ (void *) act->curr_pc,
+ (long) act->bottom_byteoff,
+ (long) act->retval_byteoff,
+ (long) act->reserve_byteoff,
+ (long) act->flags);
+}
+
DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap) {
duk_fixedbuffer fb;
const char *p = format;
const char *p_end = p + DUK_STRLEN(format);
duk_int_t retval;
- DUK_MEMZERO(&fb, sizeof(fb));
+ duk_memzero(&fb, sizeof(fb));
fb.buffer = (duk_uint8_t *) str;
fb.length = size;
fb.offset = 0;
@@ -41646,7 +45860,7 @@ DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const cha
char ch = *p++;
const char *p_begfmt = NULL;
duk_bool_t got_exclamation = 0;
- duk_bool_t got_long = 0; /* %lf, %ld etc */
+ duk_bool_t got_long = 0; /* %lf, %ld etc */
duk__dprint_state st;
if (ch != DUK_ASC_PERCENT) {
@@ -41661,7 +45875,7 @@ DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const cha
* understand. See man 3 printf.
*/
- DUK_MEMZERO(&st, sizeof(st));
+ duk_memzero(&st, sizeof(st));
st.fb = &fb;
st.depth = 0;
st.depth_limit = 1;
@@ -41714,10 +45928,18 @@ DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const cha
duk_instr_t t = va_arg(ap, duk_instr_t);
duk__print_instr(&st, t);
break;
- } else if (got_exclamation && ch == DUK_ASC_UC_C) {
+ } else if (got_exclamation && ch == DUK_ASC_UC_X) {
long t = va_arg(ap, long);
duk__print_opcode(&st, (duk_small_int_t) t);
break;
+ } else if (got_exclamation && ch == DUK_ASC_UC_C) {
+ duk_catcher *t = va_arg(ap, duk_catcher *);
+ duk__print_catcher(&st, t);
+ break;
+ } else if (got_exclamation && ch == DUK_ASC_UC_A) {
+ duk_activation *t = va_arg(ap, duk_activation *);
+ duk__print_activation(&st, t);
+ break;
} else if (!got_exclamation && strchr(DUK__ALLOWED_STANDARD_SPECIFIERS, (int) ch)) {
char fmtbuf[DUK__MAX_FORMAT_TAG_LENGTH];
duk_size_t fmtlen;
@@ -41728,8 +45950,8 @@ DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const cha
/* format is too large, abort */
goto format_error;
}
- DUK_MEMZERO(fmtbuf, sizeof(fmtbuf));
- DUK_MEMCPY(fmtbuf, p_begfmt, fmtlen);
+ duk_memzero(fmtbuf, sizeof(fmtbuf));
+ duk_memcpy(fmtbuf, p_begfmt, fmtlen);
/* assume exactly 1 arg, which is why '*' is forbidden; arg size still
* depends on type though.
@@ -41801,11 +46023,11 @@ DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const cha
}
goto done;
- format_error:
+format_error:
duk_fb_put_cstring(&fb, "FMTERR");
/* fall through */
- done:
+done:
retval = (duk_int_t) fb.offset;
duk_fb_put_byte(&fb, (duk_uint8_t) 0);
@@ -41813,7 +46035,7 @@ DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const cha
return retval;
}
-#if 0 /*unused*/
+#if 0 /*unused*/
DUK_INTERNAL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...) {
duk_int_t retval;
va_list ap;
@@ -41834,7 +46056,8 @@ DUK_INTERNAL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_u
duk_uint8_t *p = (duk_uint8_t *) buf;
duk_uint8_t *p_end = (duk_uint8_t *) (buf + buf_size - 1);
- DUK_MEMZERO(buf, buf_size);
+ DUK_ASSERT(buf != NULL);
+ duk_memzero(buf, buf_size);
for (i = 0; i < fptr_size; i++) {
duk_int_t left = (duk_int_t) (p_end - p);
@@ -41853,7 +46076,7 @@ DUK_INTERNAL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_u
}
}
-#endif /* DUK_USE_DEBUG */
+#endif /* DUK_USE_DEBUG */
/* automatic undefs */
#undef DUK__ALLOWED_STANDARD_SPECIFIERS
@@ -41874,17 +46097,23 @@ DUK_INTERNAL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_u
*/
#if defined(DUK_USE_ASSERTIONS)
-#define DUK__DBG_TPORT_ENTER() do { \
+#define DUK__DBG_TPORT_ENTER() \
+ do { \
DUK_ASSERT(heap->dbg_calling_transport == 0); \
heap->dbg_calling_transport = 1; \
} while (0)
-#define DUK__DBG_TPORT_EXIT() do { \
+#define DUK__DBG_TPORT_EXIT() \
+ do { \
DUK_ASSERT(heap->dbg_calling_transport == 1); \
heap->dbg_calling_transport = 0; \
} while (0)
#else
-#define DUK__DBG_TPORT_ENTER() do {} while (0)
-#define DUK__DBG_TPORT_EXIT() do {} while (0)
+#define DUK__DBG_TPORT_ENTER() \
+ do { \
+ } while (0)
+#define DUK__DBG_TPORT_EXIT() \
+ do { \
+ } while (0)
#endif
/*
@@ -41904,7 +46133,8 @@ typedef union {
* Detach handling
*/
-#define DUK__SET_CONN_BROKEN(thr,reason) do { \
+#define DUK__SET_CONN_BROKEN(thr, reason) \
+ do { \
/* For now shared handler is fine. */ \
duk__debug_do_detach1((thr)->heap, (reason)); \
} while (0)
@@ -41925,7 +46155,7 @@ DUK_LOCAL void duk__debug_do_detach1(duk_heap *heap, duk_int_t reason) {
DUK_D(DUK_DPRINT("debugger transport detaching, marking transport broken"));
- heap->dbg_detaching = 1; /* prevent multiple in-progress detaches */
+ heap->dbg_detaching = 1; /* prevent multiple in-progress detaches */
if (heap->dbg_write_cb != NULL) {
duk_hthread *thr;
@@ -41953,8 +46183,8 @@ DUK_LOCAL void duk__debug_do_detach1(duk_heap *heap, duk_int_t reason) {
heap->dbg_pause_act = NULL;
heap->dbg_pause_startline = 0;
heap->dbg_have_next_byte = 0;
- duk_debug_clear_paused(heap); /* XXX: some overlap with field inits above */
- heap->dbg_state_dirty = 0; /* XXX: clear_paused sets dirty; rework? */
+ duk_debug_clear_paused(heap); /* XXX: some overlap with field inits above */
+ heap->dbg_state_dirty = 0; /* XXX: clear_paused sets dirty; rework? */
/* Ensure there are no stale active breakpoint pointers.
* Breakpoint list is currently kept - we could empty it
@@ -42014,7 +46244,7 @@ DUK_LOCAL void duk__debug_null_most_callbacks(duk_hthread *thr) {
heap = thr->heap;
DUK_D(DUK_DPRINT("transport read/write error, NULL all callbacks expected detached"));
heap->dbg_read_cb = NULL;
- heap->dbg_write_cb = NULL; /* this is especially critical to avoid another write call in detach1() */
+ heap->dbg_write_cb = NULL; /* this is especially critical to avoid another write call in detach1() */
heap->dbg_peek_cb = NULL;
heap->dbg_read_flush_cb = NULL;
heap->dbg_write_flush_cb = NULL;
@@ -42036,7 +46266,8 @@ DUK_LOCAL void duk__debug_set_pause_state(duk_hthread *thr, duk_heap *heap, duk_
updated_flags = pause_flags & ~(DUK_PAUSE_FLAG_LINE_CHANGE);
DUK_D(DUK_DPRINT("no line info for current activation, disable line-based pause flags: 0x%08lx -> 0x%08lx",
- (long) pause_flags, (long) updated_flags));
+ (long) pause_flags,
+ (long) updated_flags));
pause_flags = updated_flags;
}
@@ -42046,7 +46277,8 @@ DUK_LOCAL void duk__debug_set_pause_state(duk_hthread *thr, duk_heap *heap, duk_
heap->dbg_state_dirty = 1;
DUK_D(DUK_DPRINT("set state for automatic pause triggers, flags=0x%08lx, act=%p, startline=%ld",
- (long) heap->dbg_pause_flags, (void *) heap->dbg_pause_act,
+ (long) heap->dbg_pause_flags,
+ (void *) heap->dbg_pause_act,
(long) heap->dbg_pause_startline));
}
@@ -42172,6 +46404,7 @@ DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_
DUK_ASSERT(thr != NULL);
heap = thr->heap;
DUK_ASSERT(heap != NULL);
+ DUK_ASSERT(data != NULL);
if (heap->dbg_read_cb == NULL) {
DUK_D(DUK_DPRINT("attempt to read %ld bytes in detached state, return zero data", (long) length));
@@ -42200,7 +46433,7 @@ DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_
if (got == 0 || got > left) {
DUK_D(DUK_DPRINT("connection error during read, return zero data"));
- duk__debug_null_most_callbacks(thr); /* avoid calling write callback in detach1() */
+ duk__debug_null_most_callbacks(thr); /* avoid calling write callback in detach1() */
DUK__SET_CONN_BROKEN(thr, 1);
goto fail;
}
@@ -42208,14 +46441,14 @@ DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_
}
return;
- fail:
- DUK_MEMZERO((void *) data, (size_t) length);
+fail:
+ duk_memzero((void *) data, (size_t) length);
}
DUK_INTERNAL duk_uint8_t duk_debug_read_byte(duk_hthread *thr) {
duk_uint8_t x;
- x = 0; /* just in case callback is broken and won't write 'x' */
+ x = 0; /* just in case callback is broken and won't write 'x' */
duk_debug_read_bytes(thr, &x, 1);
return x;
}
@@ -42226,10 +46459,7 @@ DUK_LOCAL duk_uint32_t duk__debug_read_uint32_raw(duk_hthread *thr) {
DUK_ASSERT(thr != NULL);
duk_debug_read_bytes(thr, buf, 4);
- return ((duk_uint32_t) buf[0] << 24) |
- ((duk_uint32_t) buf[1] << 16) |
- ((duk_uint32_t) buf[2] << 8) |
- (duk_uint32_t) buf[3];
+ return ((duk_uint32_t) buf[0] << 24) | ((duk_uint32_t) buf[1] << 16) | ((duk_uint32_t) buf[2] << 8) | (duk_uint32_t) buf[3];
}
DUK_LOCAL duk_int32_t duk__debug_read_int32_raw(duk_hthread *thr) {
@@ -42242,8 +46472,7 @@ DUK_LOCAL duk_uint16_t duk__debug_read_uint16_raw(duk_hthread *thr) {
DUK_ASSERT(thr != NULL);
duk_debug_read_bytes(thr, buf, 2);
- return ((duk_uint16_t) buf[0] << 8) |
- (duk_uint16_t) buf[1];
+ return ((duk_uint16_t) buf[0] << 8) | (duk_uint16_t) buf[1];
}
DUK_INTERNAL duk_int32_t duk_debug_read_int(duk_hthread *thr) {
@@ -42275,10 +46504,10 @@ DUK_LOCAL duk_hstring *duk__debug_read_hstring_raw(duk_hthread *thr, duk_uint32_
duk_debug_read_bytes(thr, buf, (duk_size_t) len);
duk_push_lstring(thr, (const char *) buf, (duk_size_t) len);
} else {
- p = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len); /* zero for paranoia */
+ p = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len); /* zero for paranoia */
DUK_ASSERT(p != NULL);
duk_debug_read_bytes(thr, p, (duk_size_t) len);
- (void) duk_buffer_to_string(thr, -1); /* Safety relies on debug client, which is OK. */
+ (void) duk_buffer_to_string(thr, -1); /* Safety relies on debug client, which is OK. */
}
return duk_require_hstring(thr, -1);
@@ -42304,17 +46533,17 @@ DUK_INTERNAL duk_hstring *duk_debug_read_hstring(duk_hthread *thr) {
return duk__debug_read_hstring_raw(thr, len);
- fail:
+fail:
DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
DUK__SET_CONN_BROKEN(thr, 1);
- duk_push_hstring_empty(thr); /* always push some string */
+ duk_push_hstring_empty(thr); /* always push some string */
return duk_require_hstring(thr, -1);
}
DUK_LOCAL duk_hbuffer *duk__debug_read_hbuffer_raw(duk_hthread *thr, duk_uint32_t len) {
duk_uint8_t *p;
- p = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len); /* zero for paranoia */
+ p = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len); /* zero for paranoia */
DUK_ASSERT(p != NULL);
duk_debug_read_bytes(thr, p, (duk_size_t) len);
@@ -42337,7 +46566,7 @@ DUK_LOCAL void *duk__debug_read_pointer_raw(duk_hthread *thr) {
#endif
return (void *) pu.p;
- fail:
+fail:
DUK_D(DUK_DPRINT("debug connection error: failed to decode pointer"));
DUK__SET_CONN_BROKEN(thr, 1);
return (void *) NULL;
@@ -42395,7 +46624,7 @@ DUK_INTERNAL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr) {
return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
- fail:
+fail:
DUK_D(DUK_DPRINT("debug connection error: failed to decode any pointer (object, pointer, heapptr)"));
DUK__SET_CONN_BROKEN(thr, 1);
return NULL;
@@ -42501,15 +46730,15 @@ DUK_INTERNAL duk_tval *duk_debug_read_tval(duk_hthread *thr) {
duk_push_heapptr(thr, (void *) h);
break;
}
- case DUK_DBG_IB_UNUSED: /* unused: not accepted in inbound messages */
+ case DUK_DBG_IB_UNUSED: /* unused: not accepted in inbound messages */
default:
goto fail;
}
- return_ptr:
+return_ptr:
return DUK_GET_TVAL_NEGIDX(thr, -1);
- fail:
+fail:
DUK_D(DUK_DPRINT("debug connection error: failed to decode tval"));
DUK__SET_CONN_BROKEN(thr, 1);
return NULL;
@@ -42559,7 +46788,7 @@ DUK_INTERNAL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *dat
DUK__DBG_TPORT_EXIT();
if (got == 0 || got > left) {
- duk__debug_null_most_callbacks(thr); /* avoid calling write callback in detach1() */
+ duk__debug_null_most_callbacks(thr); /* avoid calling write callback in detach1() */
DUK_D(DUK_DPRINT("connection error during write"));
DUK__SET_CONN_BROKEN(thr, 1);
return;
@@ -42626,8 +46855,7 @@ DUK_INTERNAL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x) {
* unsigned 32-bit dvalue.
*/
if (x >= 0x80000000UL) {
- DUK_D(DUK_DPRINT("writing unsigned integer 0x%08lx as signed integer",
- (long) x));
+ DUK_D(DUK_DPRINT("writing unsigned integer 0x%08lx as signed integer", (long) x));
}
duk_debug_write_int(thr, (duk_int32_t) x);
}
@@ -42668,9 +46896,7 @@ DUK_INTERNAL void duk_debug_write_string(duk_hthread *thr, const char *data, duk
DUK_INTERNAL void duk_debug_write_cstring(duk_hthread *thr, const char *data) {
DUK_ASSERT(thr != NULL);
- duk_debug_write_string(thr,
- data,
- data ? DUK_STRLEN(data) : 0);
+ duk_debug_write_string(thr, data, data ? DUK_STRLEN(data) : 0);
}
DUK_INTERNAL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h) {
@@ -42724,7 +46950,7 @@ DUK_INTERNAL void duk_debug_write_pointer(duk_hthread *thr, void *ptr) {
DUK_INTERNAL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h) {
duk__debug_write_pointer_raw(thr, (void *) h, DUK_DBG_IB_HEAPPTR);
}
-#endif /* DUK_USE_DEBUGGER_DUMPHEAP || DUK_USE_DEBUGGER_INSPECT */
+#endif /* DUK_USE_DEBUGGER_DUMPHEAP || DUK_USE_DEBUGGER_INSPECT */
DUK_INTERNAL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj) {
duk_uint8_t buf[3];
@@ -42767,8 +46993,7 @@ DUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) {
duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
break;
case DUK_TAG_BOOLEAN:
- DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 ||
- DUK_TVAL_GET_BOOLEAN(tv) == 1);
+ DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 || DUK_TVAL_GET_BOOLEAN(tv) == 1);
duk_debug_write_boolean(thr, DUK_TVAL_GET_BOOLEAN(tv));
break;
case DUK_TAG_POINTER:
@@ -42813,16 +47038,24 @@ DUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) {
DUK_DD(DUK_DDPRINT("i32=%ld du1=%02x%02x%02x%02x%02x%02x%02x%02x "
"du2=%02x%02x%02x%02x%02x%02x%02x%02x",
(long) i32,
- (unsigned int) du1.uc[0], (unsigned int) du1.uc[1],
- (unsigned int) du1.uc[2], (unsigned int) du1.uc[3],
- (unsigned int) du1.uc[4], (unsigned int) du1.uc[5],
- (unsigned int) du1.uc[6], (unsigned int) du1.uc[7],
- (unsigned int) du2.uc[0], (unsigned int) du2.uc[1],
- (unsigned int) du2.uc[2], (unsigned int) du2.uc[3],
- (unsigned int) du2.uc[4], (unsigned int) du2.uc[5],
- (unsigned int) du2.uc[6], (unsigned int) du2.uc[7]));
-
- if (DUK_MEMCMP((const void *) du1.uc, (const void *) du2.uc, sizeof(du1.uc)) == 0) {
+ (unsigned int) du1.uc[0],
+ (unsigned int) du1.uc[1],
+ (unsigned int) du1.uc[2],
+ (unsigned int) du1.uc[3],
+ (unsigned int) du1.uc[4],
+ (unsigned int) du1.uc[5],
+ (unsigned int) du1.uc[6],
+ (unsigned int) du1.uc[7],
+ (unsigned int) du2.uc[0],
+ (unsigned int) du2.uc[1],
+ (unsigned int) du2.uc[2],
+ (unsigned int) du2.uc[3],
+ (unsigned int) du2.uc[4],
+ (unsigned int) du2.uc[5],
+ (unsigned int) du2.uc[6],
+ (unsigned int) du2.uc[7]));
+
+ if (duk_memcmp((const void *) du1.uc, (const void *) du2.uc, sizeof(du1.uc)) == 0) {
duk_debug_write_int(thr, i32);
} else {
DUK_DBLUNION_DOUBLE_HTON(&du1);
@@ -42844,13 +47077,13 @@ DUK_LOCAL void duk__debug_write_tval_heapptr(duk_hthread *thr, duk_tval *tv) {
duk_debug_write_tval(thr, tv);
}
}
-#endif /* DUK_USE_DEBUGGER_DUMPHEAP */
+#endif /* DUK_USE_DEBUGGER_DUMPHEAP */
/*
* Debug connection message write helpers
*/
-#if 0 /* unused */
+#if 0 /* unused */
DUK_INTERNAL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command) {
duk_debug_write_byte(thr, DUK_DBG_IB_REQUEST);
duk_debug_write_int(thr, command);
@@ -42931,9 +47164,9 @@ DUK_INTERNAL void duk_debug_send_status(duk_hthread *thr) {
duk_debug_write_int(thr, 0);
} else {
duk_push_tval(thr, &act->tv_func);
- duk_get_prop_string(thr, -1, "fileName");
+ duk_get_prop_literal(thr, -1, "fileName");
duk__debug_write_hstring_safe_top(thr);
- duk_get_prop_string(thr, -2, "name");
+ duk_get_prop_literal(thr, -2, "name");
duk__debug_write_hstring_safe_top(thr);
duk_pop_3(thr);
/* Report next pc/line to be executed. */
@@ -42953,7 +47186,7 @@ DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {
duk_activation *act;
duk_uint32_t pc;
- DUK_ASSERT(thr->valstack_top > thr->valstack); /* At least: ... [err] */
+ DUK_ASSERT(thr->valstack_top > thr->valstack); /* At least: ... [err] */
duk_debug_write_notify(thr, DUK_DBG_CMD_THROW);
duk_debug_write_int(thr, (duk_int32_t) fatal);
@@ -42978,7 +47211,7 @@ DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {
act = thr->callstack_curr;
if (act != NULL) {
duk_push_tval(thr, &act->tv_func);
- duk_get_prop_string(thr, -1, "fileName");
+ duk_get_prop_literal(thr, -1, "fileName");
duk__debug_write_hstring_safe_top(thr);
pc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr, act);
duk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(thr, -2, pc));
@@ -42994,7 +47227,7 @@ DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {
duk_debug_write_eom(thr);
}
-#endif /* DUK_USE_DEBUGGER_THROW_NOTIFY */
+#endif /* DUK_USE_DEBUGGER_THROW_NOTIFY */
/*
* Debug message processing
@@ -43018,9 +47251,9 @@ DUK_LOCAL duk_bool_t duk__debug_skip_dvalue(duk_hthread *thr) {
duk_debug_skip_bytes(thr, (duk_size_t) (x - 0x60));
return 0;
}
- switch(x) {
+ switch (x) {
case DUK_DBG_IB_EOM:
- return 1; /* Return 1: got EOM */
+ return 1; /* Return 1: got EOM */
case DUK_DBG_IB_REQUEST:
case DUK_DBG_IB_REPLY:
case DUK_DBG_IB_ERROR:
@@ -43069,9 +47302,9 @@ DUK_LOCAL duk_bool_t duk__debug_skip_dvalue(duk_hthread *thr) {
return 0;
- fail:
+fail:
DUK__SET_CONN_BROKEN(thr, 1);
- return 1; /* Pretend like we got EOM */
+ return 1; /* Pretend like we got EOM */
}
/* Skip dvalues to EOM. */
@@ -43091,7 +47324,7 @@ DUK_LOCAL duk_int32_t duk__debug_read_validate_csindex(duk_hthread *thr) {
level = duk_debug_read_int(thr);
if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
- return 0; /* zero indicates failure */
+ return 0; /* zero indicates failure */
}
return level;
}
@@ -43160,7 +47393,7 @@ DUK_LOCAL void duk__debug_handle_resume(duk_hthread *thr, duk_heap *heap) {
duk_debug_clear_paused(heap);
pause_flags = 0;
-#if 0 /* manual testing */
+#if 0 /* manual testing */
pause_flags |= DUK_PAUSE_FLAG_ONE_OPCODE;
pause_flags |= DUK_PAUSE_FLAG_CAUGHT_ERROR;
pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
@@ -43181,12 +47414,9 @@ DUK_LOCAL void duk__debug_handle_step(duk_hthread *thr, duk_heap *heap, duk_int3
DUK_D(DUK_DPRINT("debug command StepInto/StepOver/StepOut: %d", (int) cmd));
if (cmd == DUK_DBG_CMD_STEPINTO) {
- pause_flags = DUK_PAUSE_FLAG_LINE_CHANGE |
- DUK_PAUSE_FLAG_FUNC_ENTRY |
- DUK_PAUSE_FLAG_FUNC_EXIT;
+ pause_flags = DUK_PAUSE_FLAG_LINE_CHANGE | DUK_PAUSE_FLAG_FUNC_ENTRY | DUK_PAUSE_FLAG_FUNC_EXIT;
} else if (cmd == DUK_DBG_CMD_STEPOVER) {
- pause_flags = DUK_PAUSE_FLAG_LINE_CHANGE |
- DUK_PAUSE_FLAG_FUNC_EXIT;
+ pause_flags = DUK_PAUSE_FLAG_LINE_CHANGE | DUK_PAUSE_FLAG_FUNC_EXIT;
} else {
DUK_ASSERT(cmd == DUK_DBG_CMD_STEPOUT);
pause_flags = DUK_PAUSE_FLAG_FUNC_EXIT;
@@ -43265,7 +47495,7 @@ DUK_LOCAL void duk__debug_handle_get_var(duk_hthread *thr, duk_heap *heap) {
if (act == NULL) {
return;
}
- str = duk_debug_read_hstring(thr); /* push to stack */
+ str = duk_debug_read_hstring(thr); /* push to stack */
DUK_ASSERT(str != NULL);
rc = duk_js_getvar_activation(thr, act, str, 0);
@@ -43294,7 +47524,7 @@ DUK_LOCAL void duk__debug_handle_put_var(duk_hthread *thr, duk_heap *heap) {
if (act == NULL) {
return;
}
- str = duk_debug_read_hstring(thr); /* push to stack */
+ str = duk_debug_read_hstring(thr); /* push to stack */
DUK_ASSERT(str != NULL);
tv = duk_debug_read_tval(thr);
if (tv == NULL) {
@@ -43377,18 +47607,25 @@ DUK_LOCAL void duk__debug_handle_get_locals(duk_hthread *thr, duk_heap *heap) {
* - If side effects are possible, add error catching
*/
- duk_push_tval(thr, &act->tv_func);
- duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VARMAP);
- if (duk_is_object(thr, -1)) {
- duk_enum(thr, -1, 0 /*enum_flags*/);
- while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
- varname = duk_known_hstring(thr, -1);
-
- duk_js_getvar_activation(thr, act, varname, 0 /*throw_flag*/);
- /* [ ... func varmap enum key value this ] */
- duk_debug_write_hstring(thr, duk_get_hstring(thr, -3));
- duk_debug_write_tval(thr, duk_get_tval(thr, -2));
- duk_pop_3(thr); /* -> [ ... func varmap enum ] */
+ if (DUK_TVAL_IS_OBJECT(&act->tv_func)) {
+ duk_hobject *h_func = DUK_TVAL_GET_OBJECT(&act->tv_func);
+ duk_hobject *h_varmap;
+
+ h_varmap = duk_hobject_get_varmap(thr, h_func);
+ if (h_varmap != NULL) {
+ duk_push_hobject(thr, h_varmap);
+ duk_enum(thr, -1, 0 /*enum_flags*/);
+ while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
+ varname = duk_known_hstring(thr, -1);
+
+ duk_js_getvar_activation(thr, act, varname, 0 /*throw_flag*/);
+ /* [ ... func varmap enum key value this ] */
+ duk_debug_write_hstring(thr, duk_get_hstring(thr, -3));
+ duk_debug_write_tval(thr, duk_get_tval(thr, -2));
+ duk_pop_3(thr); /* -> [ ... func varmap enum ] */
+ }
+ } else {
+ DUK_D(DUK_DPRINT("varmap missing in GetLocals, ignore"));
}
} else {
DUK_D(DUK_DPRINT("varmap is not an object in GetLocals, ignore"));
@@ -43420,12 +47657,12 @@ DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {
/* nargs == 2 so we can pass a callstack index to eval(). */
idx_func = duk_get_top(thr);
duk_push_c_function(thr, duk_bi_global_object_eval, 2 /*nargs*/);
- duk_push_undefined(thr); /* 'this' binding shouldn't matter here */
+ duk_push_undefined(thr); /* 'this' binding shouldn't matter here */
/* Read callstack index, if non-null. */
if (duk_debug_peek_byte(thr) == DUK_DBG_IB_NULL) {
direct_eval = 0;
- level = -1; /* Not needed, but silences warning. */
+ level = -1; /* Not needed, but silences warning. */
(void) duk_debug_read_byte(thr);
} else {
direct_eval = 1;
@@ -43435,12 +47672,11 @@ DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {
}
}
- DUK_ASSERT(!direct_eval ||
- (level < 0 && -level <= (duk_int32_t) thr->callstack_top));
+ DUK_ASSERT(!direct_eval || (level < 0 && -level <= (duk_int32_t) thr->callstack_top));
(void) duk_debug_read_hstring(thr);
if (direct_eval) {
- duk_push_int(thr, level - 1); /* compensate for eval() call */
+ duk_push_int(thr, level - 1); /* compensate for eval() call */
}
/* [ ... eval "eval" eval_input level? ] */
@@ -43455,7 +47691,7 @@ DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {
fun = DUK_ACT_GET_FUNC(act);
if (fun != NULL && DUK_HOBJECT_IS_COMPFUNC(fun)) {
/* Direct eval requires that there's a current
- * activation and it is an Ecmascript function.
+ * activation and it is an ECMAScript function.
* When Eval is executed from e.g. cooperate API
* call we'll need to do an indirect eval instead.
*/
@@ -43495,7 +47731,7 @@ DUK_LOCAL void duk__debug_handle_detach(duk_hthread *thr, duk_heap *heap) {
duk_debug_write_eom(thr);
DUK_D(DUK_DPRINT("debug connection detached, mark broken"));
- DUK__SET_CONN_BROKEN(thr, 0); /* not an error */
+ DUK__SET_CONN_BROKEN(thr, 0); /* not an error */
}
DUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {
@@ -43503,7 +47739,7 @@ DUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {
DUK_D(DUK_DPRINT("debug command AppRequest"));
- old_top = duk_get_top(thr); /* save stack top */
+ old_top = duk_get_top(thr); /* save stack top */
if (heap->dbg_request_cb != NULL) {
duk_idx_t nrets;
@@ -43519,7 +47755,7 @@ DUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {
DUK_D(DUK_DPRINT("failed to allocate space for request dvalue(s)"));
goto fail;
}
- tv = duk_debug_read_tval(thr); /* push to stack */
+ tv = duk_debug_read_tval(thr); /* push to stack */
if (tv == NULL) {
/* detached */
return;
@@ -43530,17 +47766,24 @@ DUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {
/* Request callback should push values for reply to client onto valstack */
DUK_D(DUK_DPRINT("calling into AppRequest request_cb with nvalues=%ld, old_top=%ld, top=%ld",
- (long) nvalues, (long) old_top, (long) duk_get_top(thr)));
+ (long) nvalues,
+ (long) old_top,
+ (long) duk_get_top(thr)));
nrets = heap->dbg_request_cb(thr, heap->dbg_udata, nvalues);
DUK_D(DUK_DPRINT("returned from AppRequest request_cb; nvalues=%ld -> nrets=%ld, old_top=%ld, top=%ld",
- (long) nvalues, (long) nrets, (long) old_top, (long) duk_get_top(thr)));
+ (long) nvalues,
+ (long) nrets,
+ (long) old_top,
+ (long) duk_get_top(thr)));
if (nrets >= 0) {
DUK_ASSERT(duk_get_top(thr) >= old_top + nrets);
if (duk_get_top(thr) < old_top + nrets) {
DUK_D(DUK_DPRINT("AppRequest callback doesn't match value stack configuration, "
"top=%ld < old_top=%ld + nrets=%ld; "
"this might mean it's unsafe to continue!",
- (long) duk_get_top(thr), (long) old_top, (long) nrets));
+ (long) duk_get_top(thr),
+ (long) old_top,
+ (long) nrets));
goto fail;
}
@@ -43560,7 +47803,7 @@ DUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {
duk_debug_write_error_eom(thr, DUK_DBG_ERR_APPLICATION, duk_get_string(thr, -1));
}
- duk_set_top(thr, old_top); /* restore stack top */
+ duk_set_top(thr, old_top); /* restore stack top */
} else {
DUK_D(DUK_DPRINT("no request callback, treat AppRequest as unsupported"));
duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "AppRequest unsupported by target");
@@ -43568,8 +47811,8 @@ DUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {
return;
- fail:
- duk_set_top(thr, old_top); /* restore stack top */
+fail:
+ duk_set_top(thr, old_top); /* restore stack top */
DUK__SET_CONN_BROKEN(thr, 1);
}
@@ -43620,16 +47863,16 @@ DUK_LOCAL void duk__debug_dump_heaphdr(duk_hthread *thr, duk_heap *heap, duk_hea
k = DUK_HOBJECT_E_GET_KEY(heap, h, i);
duk_debug_write_heapptr(thr, (duk_heaphdr *) k);
if (k == NULL) {
- duk_debug_write_int(thr, 0); /* isAccessor */
+ duk_debug_write_int(thr, 0); /* isAccessor */
duk_debug_write_unused(thr);
continue;
}
if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
- duk_debug_write_int(thr, 1); /* isAccessor */
+ duk_debug_write_int(thr, 1); /* isAccessor */
duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
} else {
- duk_debug_write_int(thr, 0); /* isAccessor */
+ duk_debug_write_int(thr, 0); /* isAccessor */
duk__debug_write_tval_heapptr(thr, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
}
@@ -43691,7 +47934,7 @@ DUK_LOCAL void duk__debug_handle_dump_heap(duk_hthread *thr, duk_heap *heap) {
duk__debug_dump_strtab(thr, heap);
duk_debug_write_eom(thr);
}
-#endif /* DUK_USE_DEBUGGER_DUMPHEAP */
+#endif /* DUK_USE_DEBUGGER_DUMPHEAP */
DUK_LOCAL void duk__debug_handle_get_bytecode(duk_hthread *thr, duk_heap *heap) {
duk_activation *act;
@@ -43760,11 +48003,11 @@ DUK_LOCAL void duk__debug_handle_get_bytecode(duk_hthread *thr, duk_heap *heap)
duk_debug_write_eom(thr);
return;
- fail_args:
+fail_args:
duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid argument");
return;
- fail_index:
+fail_index:
duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
return;
}
@@ -43816,53 +48059,22 @@ DUK_LOCAL duk_uint_t duk__debug_getinfo_hstring_masks[] = {
DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS,
#endif
DUK_HSTRING_FLAG_EXTDATA,
- 0 /* terminator */
+ 0 /* terminator */
};
DUK_LOCAL const char * const duk__debug_getinfo_hobject_keys[] = {
- "extensible",
- "constructable",
- "callable",
- "boundfunc",
- "compfunc",
- "natfunc",
- "bufobj",
- "fastrefs",
- "array_part",
- "strict",
- "notail",
- "newenv",
- "namebinding",
- "createargs",
- "have_finalizer",
- "exotic_array",
- "exotic_stringobj",
- "exotic_arguments",
- "exotic_proxyobj",
- "special_call"
+ "extensible", "constructable", "callable", "boundfunc", "compfunc", "natfunc", "bufobj",
+ "fastrefs", "array_part", "strict", "notail", "newenv", "namebinding", "createargs",
+ "have_finalizer", "exotic_array", "exotic_stringobj", "exotic_arguments", "exotic_proxyobj", "special_call"
/* NULL not needed here */
};
DUK_LOCAL duk_uint_t duk__debug_getinfo_hobject_masks[] = {
- DUK_HOBJECT_FLAG_EXTENSIBLE,
- DUK_HOBJECT_FLAG_CONSTRUCTABLE,
- DUK_HOBJECT_FLAG_CALLABLE,
- DUK_HOBJECT_FLAG_BOUNDFUNC,
- DUK_HOBJECT_FLAG_COMPFUNC,
- DUK_HOBJECT_FLAG_NATFUNC,
- DUK_HOBJECT_FLAG_BUFOBJ,
- DUK_HOBJECT_FLAG_FASTREFS,
- DUK_HOBJECT_FLAG_ARRAY_PART,
- DUK_HOBJECT_FLAG_STRICT,
- DUK_HOBJECT_FLAG_NOTAIL,
- DUK_HOBJECT_FLAG_NEWENV,
- DUK_HOBJECT_FLAG_NAMEBINDING,
- DUK_HOBJECT_FLAG_CREATEARGS,
- DUK_HOBJECT_FLAG_HAVE_FINALIZER,
- DUK_HOBJECT_FLAG_EXOTIC_ARRAY,
- DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ,
- DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS,
- DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ,
- DUK_HOBJECT_FLAG_SPECIAL_CALL,
- 0 /* terminator */
+ DUK_HOBJECT_FLAG_EXTENSIBLE, DUK_HOBJECT_FLAG_CONSTRUCTABLE, DUK_HOBJECT_FLAG_CALLABLE,
+ DUK_HOBJECT_FLAG_BOUNDFUNC, DUK_HOBJECT_FLAG_COMPFUNC, DUK_HOBJECT_FLAG_NATFUNC,
+ DUK_HOBJECT_FLAG_BUFOBJ, DUK_HOBJECT_FLAG_FASTREFS, DUK_HOBJECT_FLAG_ARRAY_PART,
+ DUK_HOBJECT_FLAG_STRICT, DUK_HOBJECT_FLAG_NOTAIL, DUK_HOBJECT_FLAG_NEWENV,
+ DUK_HOBJECT_FLAG_NAMEBINDING, DUK_HOBJECT_FLAG_CREATEARGS, DUK_HOBJECT_FLAG_HAVE_FINALIZER,
+ DUK_HOBJECT_FLAG_EXOTIC_ARRAY, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS,
+ DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ, DUK_HOBJECT_FLAG_SPECIAL_CALL, 0 /* terminator */
};
DUK_LOCAL const char * const duk__debug_getinfo_hbuffer_keys[] = {
"dynamic",
@@ -43872,7 +48084,7 @@ DUK_LOCAL const char * const duk__debug_getinfo_hbuffer_keys[] = {
DUK_LOCAL duk_uint_t duk__debug_getinfo_hbuffer_masks[] = {
DUK_HBUFFER_FLAG_DYNAMIC,
DUK_HBUFFER_FLAG_EXTERNAL,
- 0 /* terminator */
+ 0 /* terminator */
};
DUK_LOCAL void duk__debug_getinfo_flags_key(duk_hthread *thr, const char *key) {
@@ -43898,7 +48110,7 @@ DUK_LOCAL void duk__debug_getinfo_prop_bool(duk_hthread *thr, const char *key, d
duk_debug_write_boolean(thr, val);
}
-DUK_LOCAL void duk__debug_getinfo_bitmask(duk_hthread *thr, const char * const * keys, duk_uint_t *masks, duk_uint_t flags) {
+DUK_LOCAL void duk__debug_getinfo_bitmask(duk_hthread *thr, const char * const *keys, duk_uint_t *masks, duk_uint_t flags) {
const char *key;
duk_uint_t mask;
@@ -43910,7 +48122,10 @@ DUK_LOCAL void duk__debug_getinfo_bitmask(duk_hthread *thr, const char * const *
key = *keys++;
DUK_ASSERT(key != NULL);
- DUK_DD(DUK_DDPRINT("inspect bitmask: key=%s, mask=0x%08lx, flags=0x%08lx", key, (unsigned long) mask, (unsigned long) flags));
+ DUK_DD(DUK_DDPRINT("inspect bitmask: key=%s, mask=0x%08lx, flags=0x%08lx",
+ key,
+ (unsigned long) mask,
+ (unsigned long) flags));
duk__debug_getinfo_prop_bool(thr, key, flags & mask);
}
}
@@ -43986,9 +48201,12 @@ DUK_LOCAL void duk__debug_handle_get_heap_obj_info(duk_hthread *thr, duk_heap *h
DUK_D(DUK_DPRINT("debug command GetHeapObjInfo"));
DUK_UNREF(heap);
- DUK_ASSERT(sizeof(duk__debug_getinfo_hstring_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hstring_masks) / sizeof(duk_uint_t) - 1);
- DUK_ASSERT(sizeof(duk__debug_getinfo_hobject_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hobject_masks) / sizeof(duk_uint_t) - 1);
- DUK_ASSERT(sizeof(duk__debug_getinfo_hbuffer_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hbuffer_masks) / sizeof(duk_uint_t) - 1);
+ DUK_ASSERT(sizeof(duk__debug_getinfo_hstring_keys) / sizeof(const char *) ==
+ sizeof(duk__debug_getinfo_hstring_masks) / sizeof(duk_uint_t) - 1);
+ DUK_ASSERT(sizeof(duk__debug_getinfo_hobject_keys) / sizeof(const char *) ==
+ sizeof(duk__debug_getinfo_hobject_masks) / sizeof(duk_uint_t) - 1);
+ DUK_ASSERT(sizeof(duk__debug_getinfo_hbuffer_keys) / sizeof(const char *) ==
+ sizeof(duk__debug_getinfo_hbuffer_masks) / sizeof(duk_uint_t) - 1);
h = duk_debug_read_any_ptr(thr);
if (!h) {
@@ -44121,7 +48339,7 @@ DUK_LOCAL void duk__debug_handle_get_heap_obj_info(duk_hthread *thr, duk_heap *h
if (DUK_HOBJECT_IS_BOUNDFUNC(h_obj)) {
duk_hboundfunc *h_bfun;
- h_bfun = (duk_hboundfunc *) h_obj;
+ h_bfun = (duk_hboundfunc *) (void *) h_obj;
duk__debug_getinfo_flags_key(thr, "target");
duk_debug_write_tval(thr, &h_bfun->target);
@@ -44176,7 +48394,7 @@ DUK_LOCAL void duk__debug_handle_get_heap_obj_info(duk_hthread *thr, duk_heap *h
duk_debug_write_heapptr(thr, (duk_heaphdr *) h_bufobj->buf);
}
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
break;
}
case DUK_HTYPE_BUFFER: {
@@ -44191,7 +48409,7 @@ DUK_LOCAL void duk__debug_handle_get_heap_obj_info(duk_hthread *thr, duk_heap *h
duk__debug_getinfo_flags_key(thr, "dataptr");
duk_debug_write_pointer(thr, (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf));
duk__debug_getinfo_flags_key(thr, "data");
- duk_debug_write_hbuffer(thr, h_buf); /* tolerates NULL h_buf */
+ duk_debug_write_hbuffer(thr, h_buf); /* tolerates NULL h_buf */
break;
}
default: {
@@ -44229,8 +48447,7 @@ DUK_LOCAL void duk__debug_handle_get_obj_prop_desc(duk_hthread *thr, duk_heap *h
/* To use the shared helper need the virtual index. */
DUK_ASSERT(desc.e_idx >= 0 || desc.a_idx >= 0);
- virtual_idx = (desc.a_idx >= 0 ? desc.a_idx :
- (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj) + desc.e_idx);
+ virtual_idx = (desc.a_idx >= 0 ? desc.a_idx : (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj) + desc.e_idx);
duk_debug_write_reply(thr);
rc = duk__debug_getprop_index(thr, heap, h_obj, (duk_uint_t) virtual_idx);
@@ -44242,7 +48459,7 @@ DUK_LOCAL void duk__debug_handle_get_obj_prop_desc(duk_hthread *thr, duk_heap *h
}
return;
- fail_args:
+fail_args:
duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
}
@@ -44278,11 +48495,11 @@ DUK_LOCAL void duk__debug_handle_get_obj_prop_desc_range(duk_hthread *thr, duk_h
duk_debug_write_eom(thr);
return;
- fail_args:
+fail_args:
duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
}
-#endif /* DUK_USE_DEBUGGER_INSPECT */
+#endif /* DUK_USE_DEBUGGER_INSPECT */
/*
* Process incoming debug requests
@@ -44380,7 +48597,7 @@ DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
duk__debug_handle_dump_heap(thr, heap);
break;
}
-#endif /* DUK_USE_DEBUGGER_DUMPHEAP */
+#endif /* DUK_USE_DEBUGGER_DUMPHEAP */
case DUK_DBG_CMD_GETBYTECODE: {
duk__debug_handle_get_bytecode(thr, heap);
break;
@@ -44402,12 +48619,12 @@ DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
duk__debug_handle_get_obj_prop_desc_range(thr, heap);
break;
}
-#endif /* DUK_USE_DEBUGGER_INSPECT */
+#endif /* DUK_USE_DEBUGGER_INSPECT */
default: {
DUK_D(DUK_DPRINT("debug command unsupported: %d", (int) cmd));
duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "unsupported command");
}
- } /* switch cmd */
+ } /* switch cmd */
break;
}
case DUK_DBG_IB_REPLY: {
@@ -44426,14 +48643,14 @@ DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
DUK_D(DUK_DPRINT("invalid initial byte, drop connection: %d", (int) x));
goto fail;
}
- } /* switch initial byte */
+ } /* switch initial byte */
DUK_ASSERT(duk_get_top(thr) >= entry_top);
duk_set_top(thr, entry_top);
duk__debug_skip_to_eom(thr);
return;
- fail:
+fail:
DUK_ASSERT(duk_get_top(thr) >= entry_top);
duk_set_top(thr, entry_top);
DUK__SET_CONN_BROKEN(thr, 1);
@@ -44460,8 +48677,10 @@ DUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t
#endif
DUK_D(DUK_DPRINT("process debug messages: read_cb=%s, no_block=%ld, detaching=%ld, processing=%ld",
- thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) no_block,
- (long) thr->heap->dbg_detaching, (long) thr->heap->dbg_processing));
+ thr->heap->dbg_read_cb ? "not NULL" : "NULL",
+ (long) no_block,
+ (long) thr->heap->dbg_detaching,
+ (long) thr->heap->dbg_processing));
DUK_DD(DUK_DDPRINT("top at entry: %ld", (long) duk_get_top(thr)));
/* thr->heap->dbg_detaching may be != 0 if a debugger write outside
@@ -44508,13 +48727,14 @@ DUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t
DUK_D(DUK_DPRINT("detach pending (dbg_read_cb == NULL, dbg_detaching != 0), call detach2"));
duk__debug_do_detach2(thr->heap);
- thr->heap->dbg_processing = 1; /* may be set to 0 by duk_debugger_attach() inside callback */
+ thr->heap->dbg_processing = 1; /* may be set to 0 by duk_debugger_attach() inside callback */
DUK_D(DUK_DPRINT("after detach2 (and possible reattach): dbg_read_cb=%s, dbg_detaching=%ld",
- thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) thr->heap->dbg_detaching));
+ thr->heap->dbg_read_cb ? "not NULL" : "NULL",
+ (long) thr->heap->dbg_detaching));
}
- DUK_ASSERT(thr->heap->dbg_detaching == 0); /* true even with reattach */
- DUK_ASSERT(thr->heap->dbg_processing == 1); /* even after a detach and possible reattach */
+ DUK_ASSERT(thr->heap->dbg_detaching == 0); /* true even with reattach */
+ DUK_ASSERT(thr->heap->dbg_processing == 1); /* even after a detach and possible reattach */
if (thr->heap->dbg_read_cb == NULL) {
DUK_D(DUK_DPRINT("debug connection broken (and not detaching), stop processing messages"));
@@ -44539,7 +48759,7 @@ DUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t
duk__debug_process_message(thr);
duk__check_resend_status(thr);
- retval = 1; /* processed one or more messages */
+ retval = 1; /* processed one or more messages */
}
DUK_ASSERT(thr->heap->dbg_detaching == 0);
@@ -44549,7 +48769,7 @@ DUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t
/* As an initial implementation, read flush after exiting the message
* loop. If transport is broken, this is a no-op (with debug logs).
*/
- duk_debug_read_flush(thr); /* this cannot initiate a detach */
+ duk_debug_read_flush(thr); /* this cannot initiate a detach */
DUK_ASSERT(thr->heap->dbg_detaching == 0);
DUK_DD(DUK_DDPRINT("top at exit: %ld", (long) duk_get_top(thr)));
@@ -44598,13 +48818,10 @@ DUK_INTERNAL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev
fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
/* Short circuit if is safe: if act->curr_pc != NULL, 'fun' is
- * guaranteed to be a non-NULL Ecmascript function.
+ * guaranteed to be a non-NULL ECMAScript function.
*/
- DUK_ASSERT(act->curr_pc == NULL ||
- (fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)));
- if (use_prev_pc &&
- act->curr_pc != NULL &&
- act->curr_pc > DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, fun)) {
+ DUK_ASSERT(act->curr_pc == NULL || (fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)));
+ if (use_prev_pc && act->curr_pc != NULL && act->curr_pc > DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, fun)) {
act->curr_pc--;
}
}
@@ -44631,7 +48848,7 @@ DUK_INTERNAL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev
* with PC values.
*/
if (act != NULL) {
- act->curr_pc = old_pc; /* restore PC */
+ act->curr_pc = old_pc; /* restore PC */
}
}
@@ -44655,7 +48872,8 @@ DUK_INTERNAL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstr
if (heap->dbg_breakpoint_count >= DUK_HEAP_MAX_BREAKPOINTS) {
DUK_D(DUK_DPRINT("failed to add breakpoint for %O:%ld, all breakpoint slots used",
- (duk_heaphdr *) filename, (long) line));
+ (duk_heaphdr *) filename,
+ (long) line));
return -1;
}
heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
@@ -44664,7 +48882,7 @@ DUK_INTERNAL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstr
b->line = line;
DUK_HSTRING_INCREF(thr, filename);
- return (duk_small_int_t) (heap->dbg_breakpoint_count - 1); /* index */
+ return (duk_small_int_t) (heap->dbg_breakpoint_count - 1); /* index */
}
DUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index) {
@@ -44682,7 +48900,7 @@ DUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_
heap = thr->heap;
DUK_ASSERT(heap != NULL);
DUK_ASSERT(duk_debug_is_attached(thr->heap));
- DUK_ASSERT_DISABLE(breakpoint_index >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(breakpoint_index >= 0); /* unsigned */
if (breakpoint_index >= heap->dbg_breakpoint_count) {
DUK_D(DUK_DPRINT("invalid breakpoint index: %ld", (long) breakpoint_index));
@@ -44694,16 +48912,13 @@ DUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_
DUK_ASSERT(h != NULL);
move_size = sizeof(duk_breakpoint) * (heap->dbg_breakpoint_count - breakpoint_index - 1);
- if (move_size > 0) {
- DUK_MEMMOVE((void *) b,
- (const void *) (b + 1),
- (size_t) move_size);
- }
+ duk_memmove((void *) b, (const void *) (b + 1), (size_t) move_size);
+
heap->dbg_breakpoint_count--;
heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
- DUK_HSTRING_DECREF(thr, h); /* side effects */
- DUK_UNREF(h); /* w/o refcounting */
+ DUK_HSTRING_DECREF(thr, h); /* side effects */
+ DUK_UNREF(h); /* w/o refcounting */
/* Breakpoint entries above the used area are left as garbage. */
@@ -44729,10 +48944,10 @@ DUK_INTERNAL void duk_debug_set_paused(duk_heap *heap) {
DUK_HEAP_SET_DEBUGGER_PAUSED(heap);
heap->dbg_state_dirty = 1;
duk_debug_clear_pause_state(heap);
- DUK_ASSERT(heap->ms_running == 0); /* debugger can't be triggered within mark-and-sweep */
- heap->ms_running = 1; /* prevent mark-and-sweep, prevent refzero queueing */
+ DUK_ASSERT(heap->ms_running == 0); /* debugger can't be triggered within mark-and-sweep */
+ heap->ms_running = 2; /* prevent mark-and-sweep, prevent refzero queueing */
heap->ms_prevent_count++;
- DUK_ASSERT(heap->ms_prevent_count != 0); /* Wrap. */
+ DUK_ASSERT(heap->ms_prevent_count != 0); /* Wrap. */
DUK_ASSERT(heap->heap_thread != NULL);
}
}
@@ -44742,7 +48957,7 @@ DUK_INTERNAL void duk_debug_clear_paused(duk_heap *heap) {
DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap);
heap->dbg_state_dirty = 1;
duk_debug_clear_pause_state(heap);
- DUK_ASSERT(heap->ms_running == 1);
+ DUK_ASSERT(heap->ms_running == 2);
DUK_ASSERT(heap->ms_prevent_count > 0);
heap->ms_prevent_count--;
heap->ms_running = 0;
@@ -44758,11 +48973,11 @@ DUK_INTERNAL void duk_debug_clear_pause_state(duk_heap *heap) {
heap->dbg_pause_startline = 0;
}
-#else /* DUK_USE_DEBUGGER_SUPPORT */
+#else /* DUK_USE_DEBUGGER_SUPPORT */
/* No debugger support. */
-#endif /* DUK_USE_DEBUGGER_SUPPORT */
+#endif /* DUK_USE_DEBUGGER_SUPPORT */
/* automatic undefs */
#undef DUK__DBG_TPORT_ENTER
@@ -44784,7 +48999,7 @@ DUK_INTERNAL void duk_debug_clear_pause_state(duk_heap *heap) {
*
* Error augmentation may throw an internal error (e.g. alloc error).
*
- * Ecmascript allows throwing any values, so all values cannot be
+ * ECMAScript allows throwing any values, so all values cannot be
* augmented. Currently, the built-in augmentation at error creation
* only augments error values which are Error instances (= have the
* built-in Error.prototype in their prototype chain) and are also
@@ -44852,7 +49067,7 @@ DUK_LOCAL void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_c
* when it is called and that error replaces the original one.
*/
- DUK_ASSERT_VALSTACK_SPACE(thr, 4); /* 3 entries actually needed below */
+ DUK_ASSERT_VALSTACK_SPACE(thr, 4); /* 3 entries actually needed below */
/* [ ... errval ] */
@@ -44863,23 +49078,19 @@ DUK_LOCAL void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_c
DUK_DD(DUK_DDPRINT("error occurred when DUK_BIDX_DUKTAPE is NULL, ignoring"));
return;
}
- tv_hnd = duk_hobject_find_existing_entry_tval_ptr(thr->heap,
- thr->builtins[DUK_BIDX_DUKTAPE],
- DUK_HTHREAD_GET_STRING(thr, stridx_cb));
+ tv_hnd = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, thr->builtins[DUK_BIDX_DUKTAPE], stridx_cb);
if (tv_hnd == NULL) {
- DUK_DD(DUK_DDPRINT("error handler does not exist or is not a plain value: %!T",
- (duk_tval *) tv_hnd));
+ DUK_DD(DUK_DDPRINT("error handler does not exist or is not a plain value: %!T", (duk_tval *) tv_hnd));
return;
}
- DUK_DDD(DUK_DDDPRINT("error handler dump (callability not checked): %!T",
- (duk_tval *) tv_hnd));
+ DUK_DDD(DUK_DDDPRINT("error handler dump (callability not checked): %!T", (duk_tval *) tv_hnd));
duk_push_tval(thr, tv_hnd);
/* [ ... errval errhandler ] */
- duk_insert(thr, -2); /* -> [ ... errhandler errval ] */
+ duk_insert(thr, -2); /* -> [ ... errhandler errval ] */
duk_push_undefined(thr);
- duk_insert(thr, -2); /* -> [ ... errhandler undefined(= this) errval ] */
+ duk_insert(thr, -2); /* -> [ ... errhandler undefined(= this) errval ] */
/* [ ... errhandler undefined errval ] */
@@ -44896,21 +49107,25 @@ DUK_LOCAL void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_c
thr->heap->augmenting_error = 1;
rc = duk_pcall_method(thr, 1);
- DUK_UNREF(rc); /* no need to check now: both success and error are OK */
+ DUK_UNREF(rc); /* no need to check now: both success and error are OK */
DUK_ASSERT(thr->heap->augmenting_error == 1);
thr->heap->augmenting_error = 0;
/* [ ... errval ] */
}
-#endif /* DUK_USE_ERRTHROW || DUK_USE_ERRCREATE */
+#endif /* DUK_USE_ERRTHROW || DUK_USE_ERRCREATE */
/*
* Add ._Tracedata to an error on the stack top.
*/
#if defined(DUK_USE_TRACEBACKS)
-DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_small_uint_t flags) {
+DUK_LOCAL void duk__add_traceback(duk_hthread *thr,
+ duk_hthread *thr_callstack,
+ const char *c_filename,
+ duk_int_t c_line,
+ duk_small_uint_t flags) {
duk_activation *act;
duk_int_t depth;
duk_int_t arr_size;
@@ -44932,15 +49147,14 @@ DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack,
* See doc/error-objects.rst.
*/
- DUK_DDD(DUK_DDDPRINT("adding traceback to object: %!T",
- (duk_tval *) duk_get_tval(thr, -1)));
+ DUK_DDD(DUK_DDDPRINT("adding traceback to object: %!T", (duk_tval *) duk_get_tval(thr, -1)));
/* Preallocate array to correct size, so that we can just write out
* the _Tracedata values into the array part.
*/
act = thr->callstack_curr;
depth = DUK_USE_TRACEBACK_DEPTH;
- DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX); /* callstack limits */
+ DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX); /* callstack limits */
if (depth > (duk_int_t) thr_callstack->callstack_top) {
depth = (duk_int_t) thr_callstack->callstack_top;
}
@@ -44964,9 +49178,13 @@ DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack,
arr_size += 2;
}
- /* XXX: uninitialized would be OK */
+ /* XXX: Uninitialized would be OK. Maybe add internal primitive to
+ * push bare duk_harray with size?
+ */
DUK_D(DUK_DPRINT("preallocated _Tracedata to %ld items", (long) arr_size));
tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) arr_size);
+ duk_clear_prototype(thr, -1);
+ DUK_ASSERT(duk_is_bare_object(thr, -1));
DUK_ASSERT(arr_size == 0 || tv != NULL);
/* Compiler SyntaxErrors (and other errors) come first, and are
@@ -44978,7 +49196,7 @@ DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack,
DUK_HSTRING_INCREF(thr, s);
tv++;
- u32 = (duk_uint32_t) thr->compile_ctx->curr_token.start_line; /* (flags<<32) + (line), flags = 0 */
+ u32 = (duk_uint32_t) thr->compile_ctx->curr_token.start_line; /* (flags<<32) + (line), flags = 0 */
DUK_TVAL_SET_U32(tv, u32);
tv++;
}
@@ -44992,13 +49210,15 @@ DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack,
if (c_filename) {
DUK_ASSERT(DUK_TVAL_IS_STRING(thr->valstack_top - 2));
- s = DUK_TVAL_GET_STRING(thr->valstack_top - 2); /* interned c_filename */
+ s = DUK_TVAL_GET_STRING(thr->valstack_top - 2); /* interned c_filename */
DUK_ASSERT(s != NULL);
DUK_TVAL_SET_STRING(tv, s);
DUK_HSTRING_INCREF(thr, s);
tv++;
- d = ((flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE) ? ((duk_double_t) DUK_TB_FLAG_NOBLAME_FILELINE) * DUK_DOUBLE_2TO32 : 0.0) +
+ d = ((flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE) ?
+ ((duk_double_t) DUK_TB_FLAG_NOBLAME_FILELINE) * DUK_DOUBLE_2TO32 :
+ 0.0) +
(duk_double_t) c_line;
DUK_TVAL_SET_DOUBLE(tv, d);
tv++;
@@ -45013,11 +49233,11 @@ DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack,
/* [... arr] */
- DUK_ASSERT(act != NULL); /* depth check above, assumes book-keeping is correct */
- DUK_ASSERT_DISABLE(act->pc >= 0); /* unsigned */
+ DUK_ASSERT(act != NULL); /* depth check above, assumes book-keeping is correct */
+ DUK_ASSERT_DISABLE(act->pc >= 0); /* unsigned */
/* Add function object. */
- tv_src = &act->tv_func; /* object (function) or lightfunc */
+ tv_src = &act->tv_func; /* object (function) or lightfunc */
DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_src) || DUK_TVAL_IS_LIGHTFUNC(tv_src));
DUK_TVAL_SET_TVAL(tv, tv_src);
DUK_TVAL_INCREF(thr, tv);
@@ -45029,8 +49249,8 @@ DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack,
* PC == 0 for native code.
*/
pc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr_callstack, act);
- DUK_ASSERT_DISABLE(pc >= 0); /* unsigned */
- DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32); /* assume PC is at most 32 bits and non-negative */
+ DUK_ASSERT_DISABLE(pc >= 0); /* unsigned */
+ DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32); /* assume PC is at most 32 bits and non-negative */
d = ((duk_double_t) act->flags) * DUK_DOUBLE_2TO32 + (duk_double_t) pc;
DUK_TVAL_SET_DOUBLE(tv, d);
tv++;
@@ -45043,6 +49263,7 @@ DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack,
DUK_ASSERT(a != NULL);
DUK_ASSERT((duk_uint32_t) (tv - DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a)) == a->length);
DUK_ASSERT(a->length == (duk_uint32_t) arr_size);
+ DUK_ASSERT(duk_is_bare_object(thr, -1));
}
#endif
@@ -45054,16 +49275,20 @@ DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack,
/* [ ... error arr ] */
- duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INT_TRACEDATA); /* -> [ ... error ] */
+ duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INT_TRACEDATA); /* -> [ ... error ] */
}
-#endif /* DUK_USE_TRACEBACKS */
+#endif /* DUK_USE_TRACEBACKS */
/*
* Add .fileName and .lineNumber to an error on the stack top.
*/
#if defined(DUK_USE_AUGMENT_ERROR_CREATE) && !defined(DUK_USE_TRACEBACKS)
-DUK_LOCAL void duk__add_fileline(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_small_uint_t flags) {
+DUK_LOCAL void duk__add_fileline(duk_hthread *thr,
+ duk_hthread *thr_callstack,
+ const char *c_filename,
+ duk_int_t c_line,
+ duk_small_uint_t flags) {
#if defined(DUK_USE_ASSERTIONS)
duk_int_t entry_top;
#endif
@@ -45101,7 +49326,7 @@ DUK_LOCAL void duk__add_fileline(duk_hthread *thr, duk_hthread *thr_callstack, c
duk_uint32_t ecma_line;
duk_activation *act;
- DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX); /* callstack limits */
+ DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX); /* callstack limits */
depth = DUK_USE_TRACEBACK_DEPTH;
if (depth > thr_callstack->callstack_top) {
depth = thr_callstack->callstack_top;
@@ -45120,11 +49345,12 @@ DUK_LOCAL void duk__add_fileline(duk_hthread *thr, duk_hthread *thr_callstack, c
/* PC points to next instruction, find offending PC,
* PC == 0 for native code.
*/
- pc = duk_hthread_get_act_prev_pc(thr, act); /* thr argument only used for thr->heap, so specific thread doesn't matter */
+ pc = duk_hthread_get_act_prev_pc(
+ thr,
+ act); /* thr argument only used for thr->heap, so specific thread doesn't matter */
DUK_UNREF(pc);
- DUK_ASSERT_DISABLE(pc >= 0); /* unsigned */
- DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32); /* assume PC is at most 32 bits and non-negative */
- act = NULL; /* invalidated by pushes, so get out of the way */
+ DUK_ASSERT_DISABLE(pc >= 0); /* unsigned */
+ DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32); /* assume PC is at most 32 bits and non-negative */
duk_push_hobject(thr, func);
@@ -45145,7 +49371,7 @@ DUK_LOCAL void duk__add_fileline(duk_hthread *thr, duk_hthread *thr_callstack, c
} else {
/* Native function, no relevant lineNumber. */
}
-#endif /* DUK_USE_PC2LINE */
+#endif /* DUK_USE_PC2LINE */
duk_push_u32(thr, ecma_line);
/* [ ... error func fileName lineNumber ] */
@@ -45164,7 +49390,7 @@ DUK_LOCAL void duk__add_fileline(duk_hthread *thr, duk_hthread *thr_callstack, c
duk_push_undefined(thr);
}
- define_props:
+define_props:
/* [ ... error lineNumber fileName ] */
#if defined(DUK_USE_ASSERTIONS)
DUK_ASSERT(duk_get_top(thr) == entry_top + 2);
@@ -45172,7 +49398,7 @@ DUK_LOCAL void duk__add_fileline(duk_hthread *thr, duk_hthread *thr_callstack, c
duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C | DUK_PROPDESC_FLAG_NO_OVERWRITE);
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LINE_NUMBER, DUK_PROPDESC_FLAGS_C | DUK_PROPDESC_FLAG_NO_OVERWRITE);
}
-#endif /* DUK_USE_AUGMENT_ERROR_CREATE && !DUK_USE_TRACEBACKS */
+#endif /* DUK_USE_AUGMENT_ERROR_CREATE && !DUK_USE_TRACEBACKS */
/*
* Add line number to a compiler error.
@@ -45180,7 +49406,6 @@ DUK_LOCAL void duk__add_fileline(duk_hthread *thr, duk_hthread *thr_callstack, c
#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
DUK_LOCAL void duk__add_compiler_error_line(duk_hthread *thr) {
-
/* Append a "(line NNN)" to the "message" property of any error
* thrown during compilation. Usually compilation errors are
* SyntaxErrors but they can also be out-of-memory errors and
@@ -45195,21 +49420,41 @@ DUK_LOCAL void duk__add_compiler_error_line(duk_hthread *thr) {
return;
}
- DUK_DDD(DUK_DDDPRINT("compile error, before adding line info: %!T",
- (duk_tval *) duk_get_tval(thr, -1)));
+ DUK_DDD(DUK_DDDPRINT("compile error, before adding line info: %!T", (duk_tval *) duk_get_tval(thr, -1)));
if (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_MESSAGE)) {
- duk_push_sprintf(thr, " (line %ld)", (long) thr->compile_ctx->curr_token.start_line);
+ duk_bool_t at_end;
+
+ /* Best guesstimate that error occurred at end of input, token
+ * truncated by end of input, etc.
+ */
+#if 0
+ at_end = (thr->compile_ctx->curr_token.start_offset + 1 >= thr->compile_ctx->lex.input_length);
+ at_end = (thr->compile_ctx->lex.window[0].codepoint < 0 || thr->compile_ctx->lex.window[1].codepoint < 0);
+#endif
+ at_end = (thr->compile_ctx->lex.window[0].codepoint < 0);
+
+ DUK_D(DUK_DPRINT("syntax error, determined at_end=%ld; curr_token.start_offset=%ld, "
+ "lex.input_length=%ld, window[0].codepoint=%ld, window[1].codepoint=%ld",
+ (long) at_end,
+ (long) thr->compile_ctx->curr_token.start_offset,
+ (long) thr->compile_ctx->lex.input_length,
+ (long) thr->compile_ctx->lex.window[0].codepoint,
+ (long) thr->compile_ctx->lex.window[1].codepoint));
+
+ duk_push_sprintf(thr,
+ " (line %ld%s)",
+ (long) thr->compile_ctx->curr_token.start_line,
+ at_end ? ", end of input" : "");
duk_concat(thr, 2);
duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE);
} else {
duk_pop(thr);
}
- DUK_DDD(DUK_DDDPRINT("compile error, after adding line info: %!T",
- (duk_tval *) duk_get_tval(thr, -1)));
+ DUK_DDD(DUK_DDDPRINT("compile error, after adding line info: %!T", (duk_tval *) duk_get_tval(thr, -1)));
}
-#endif /* DUK_USE_AUGMENT_ERROR_CREATE */
+#endif /* DUK_USE_AUGMENT_ERROR_CREATE */
/*
* Augment an error being created using Duktape specific properties
@@ -45217,7 +49462,12 @@ DUK_LOCAL void duk__add_compiler_error_line(duk_hthread *thr) {
*/
#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
-DUK_LOCAL void duk__err_augment_builtin_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_hobject *obj, duk_small_uint_t flags) {
+DUK_LOCAL void duk__err_augment_builtin_create(duk_hthread *thr,
+ duk_hthread *thr_callstack,
+ const char *c_filename,
+ duk_int_t c_line,
+ duk_hobject *obj,
+ duk_small_uint_t flags) {
#if defined(DUK_USE_ASSERTIONS)
duk_int_t entry_top;
#endif
@@ -45227,16 +49477,16 @@ DUK_LOCAL void duk__err_augment_builtin_create(duk_hthread *thr, duk_hthread *th
#endif
DUK_ASSERT(obj != NULL);
- DUK_UNREF(obj); /* unreferenced w/o tracebacks */
+ DUK_UNREF(obj); /* unreferenced w/o tracebacks */
duk__add_compiler_error_line(thr);
#if defined(DUK_USE_TRACEBACKS)
/* If tracebacks are enabled, the '_Tracedata' property is the only
* thing we need: 'fileName' and 'lineNumber' are virtual properties
- * which use '_Tracedata'.
+ * which use '_Tracedata'. (Check _Tracedata only as own property.)
*/
- if (duk_hobject_hasprop_raw(thr, obj, DUK_HTHREAD_STRING_INT_TRACEDATA(thr))) {
+ if (duk_hobject_find_entry_tval_ptr_stridx(thr->heap, obj, DUK_STRIDX_INT_TRACEDATA) != NULL) {
DUK_DDD(DUK_DDDPRINT("error value already has a '_Tracedata' property, not modifying it"));
} else {
duk__add_traceback(thr, thr_callstack, c_filename, c_line, flags);
@@ -45252,7 +49502,7 @@ DUK_LOCAL void duk__err_augment_builtin_create(duk_hthread *thr, duk_hthread *th
DUK_ASSERT(duk_get_top(thr) == entry_top);
#endif
}
-#endif /* DUK_USE_AUGMENT_ERROR_CREATE */
+#endif /* DUK_USE_AUGMENT_ERROR_CREATE */
/*
* Augment an error at creation time with _Tracedata/fileName/lineNumber
@@ -45270,7 +49520,11 @@ DUK_LOCAL void duk__err_augment_builtin_create(duk_hthread *thr, duk_hthread *th
*/
#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
-DUK_INTERNAL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_small_uint_t flags) {
+DUK_INTERNAL void duk_err_augment_error_create(duk_hthread *thr,
+ duk_hthread *thr_callstack,
+ const char *c_filename,
+ duk_int_t c_line,
+ duk_small_uint_t flags) {
duk_hobject *obj;
DUK_ASSERT(thr != NULL);
@@ -45316,7 +49570,7 @@ DUK_INTERNAL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *th
duk__err_augment_user(thr, DUK_STRIDX_ERR_CREATE);
#endif
}
-#endif /* DUK_USE_AUGMENT_ERROR_CREATE */
+#endif /* DUK_USE_AUGMENT_ERROR_CREATE */
/*
* Augment an error at throw time; allow a user error handler (if defined)
@@ -45328,9 +49582,9 @@ DUK_INTERNAL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *th
DUK_INTERNAL void duk_err_augment_error_throw(duk_hthread *thr) {
#if defined(DUK_USE_ERRTHROW)
duk__err_augment_user(thr, DUK_STRIDX_ERR_THROW);
-#endif /* DUK_USE_ERRTHROW */
+#endif /* DUK_USE_ERRTHROW */
}
-#endif /* DUK_USE_AUGMENT_ERROR_THROW */
+#endif /* DUK_USE_AUGMENT_ERROR_THROW */
/*
* Do a longjmp call, calling the fatal error handler if no
* catchpoint exists.
@@ -45339,12 +49593,15 @@ DUK_INTERNAL void duk_err_augment_error_throw(duk_hthread *thr) {
/* #include duk_internal.h -> already included */
#if defined(DUK_USE_PREFER_SIZE)
+DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_minimal(duk_hthread *thr));
DUK_LOCAL void duk__uncaught_minimal(duk_hthread *thr) {
(void) duk_fatal(thr, "uncaught error");
+ DUK_WO_NORETURN(return;);
}
#endif
#if 0
+DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_readable(duk_hthread *thr));
DUK_LOCAL void duk__uncaught_readable(duk_hthread *thr) {
const char *summary;
char buf[DUK_USE_FATAL_MAXLEN];
@@ -45353,10 +49610,12 @@ DUK_LOCAL void duk__uncaught_readable(duk_hthread *thr) {
DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary);
buf[sizeof(buf) - 1] = (char) 0;
(void) duk_fatal(thr, (const char *) buf);
+ DUK_WO_NORETURN(return;);
}
#endif
#if !defined(DUK_USE_PREFER_SIZE)
+DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_error_aware(duk_hthread *thr));
DUK_LOCAL void duk__uncaught_error_aware(duk_hthread *thr) {
const char *summary;
char buf[DUK_USE_FATAL_MAXLEN];
@@ -45366,6 +49625,7 @@ DUK_LOCAL void duk__uncaught_error_aware(duk_hthread *thr) {
DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary);
buf[sizeof(buf) - 1] = (char) 0;
(void) duk_fatal(thr, (const char *) buf);
+ DUK_WO_NORETURN(return;);
}
#endif
@@ -45374,8 +49634,10 @@ DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr) {
DUK_ASSERT(thr->heap != NULL);
DUK_DD(DUK_DDPRINT("longjmp error: type=%d iserror=%d value1=%!T value2=%!T",
- (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
- &thr->heap->lj.value1, &thr->heap->lj.value2));
+ (int) thr->heap->lj.type,
+ (int) thr->heap->lj.iserror,
+ &thr->heap->lj.value1,
+ &thr->heap->lj.value2));
/* Prevent finalizer execution during error handling. All error
* handling sites will process pending finalizers once error handling
@@ -45393,29 +49655,26 @@ DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr) {
DUK_ASSERT_LJSTATE_SET(thr->heap);
thr->heap->pf_prevent_count++;
- DUK_ASSERT(thr->heap->pf_prevent_count != 0); /* Wrap. */
+ DUK_ASSERT(thr->heap->pf_prevent_count != 0); /* Wrap. */
#if defined(DUK_USE_ASSERTIONS)
/* XXX: set this immediately when longjmp state is set */
- DUK_ASSERT(thr->heap->error_not_allowed == 0); /* Detect error within critical section. */
+ DUK_ASSERT(thr->heap->error_not_allowed == 0); /* Detect error within critical section. */
thr->heap->error_not_allowed = 1;
#endif
DUK_DD(DUK_DDPRINT("about to longjmp, pf_prevent_count=%ld", (long) thr->heap->pf_prevent_count));
-#if !defined(DUK_USE_CPP_EXCEPTIONS)
/* If we don't have a jmpbuf_ptr, there is little we can do except
* cause a fatal error. The caller's expectation is that we never
* return.
- *
- * With C++ exceptions we now just propagate an uncaught error
- * instead of invoking the fatal error handler. Because there's
- * a dummy jmpbuf for C++ exceptions now, this could be changed.
*/
if (!thr->heap->lj.jmpbuf_ptr) {
DUK_D(DUK_DPRINT("uncaught error: type=%d iserror=%d value1=%!T value2=%!T",
- (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
- &thr->heap->lj.value1, &thr->heap->lj.value2));
+ (int) thr->heap->lj.type,
+ (int) thr->heap->lj.iserror,
+ &thr->heap->lj.value1,
+ &thr->heap->lj.value2));
#if defined(DUK_USE_PREFER_SIZE)
duk__uncaught_minimal(thr);
@@ -45424,16 +49683,12 @@ DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr) {
#endif
DUK_UNREACHABLE();
}
-#endif /* DUK_USE_CPP_EXCEPTIONS */
#if defined(DUK_USE_CPP_EXCEPTIONS)
- {
- duk_internal_exception exc; /* dummy */
- throw exc;
- }
-#else /* DUK_USE_CPP_EXCEPTIONS */
+ throw duk_internal_exception(); /* dummy */
+#else
DUK_LONGJMP(thr->heap->lj.jmpbuf_ptr->jb);
-#endif /* DUK_USE_CPP_EXCEPTIONS */
+#endif
DUK_UNREACHABLE();
}
@@ -45465,14 +49720,14 @@ DUK_LOCAL duk_bool_t duk__have_active_catcher(duk_hthread *thr) {
for (act = thr->callstack_curr; act != NULL; act = act->parent) {
for (cat = act->cat; cat != NULL; cat = cat->parent) {
if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
- return 1; /* all we need to know */
+ return 1; /* all we need to know */
}
}
}
}
return 0;
}
-#endif /* DUK_USE_DEBUGGER_SUPPORT */
+#endif /* DUK_USE_DEBUGGER_SUPPORT */
/*
* Get prototype object for an integer error code.
@@ -45522,11 +49777,10 @@ DUK_INTERNAL void duk_err_check_debugger_integration(duk_hthread *thr) {
* config options.
*/
- if (!duk_debug_is_attached(thr->heap) ||
- thr->heap->dbg_processing ||
- thr->heap->lj.type != DUK_LJ_TYPE_THROW ||
+ if (!duk_debug_is_attached(thr->heap) || thr->heap->dbg_processing || thr->heap->lj.type != DUK_LJ_TYPE_THROW ||
thr->heap->creating_error) {
- DUK_D(DUK_DPRINT("skip debugger error integration; not attached, debugger processing, not THROW, or error thrown while creating error"));
+ DUK_D(DUK_DPRINT("skip debugger error integration; not attached, debugger processing, not THROW, or error thrown "
+ "while creating error"));
return;
}
@@ -45554,7 +49808,7 @@ DUK_INTERNAL void duk_err_check_debugger_integration(duk_hthread *thr) {
/* Store and reset longjmp state. */
DUK_ASSERT_LJSTATE_SET(thr->heap);
DUK_TVAL_DECREF_NORZ(thr, tv_obj);
- DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2)); /* Always for THROW type. */
+ DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2)); /* Always for THROW type. */
DUK_TVAL_SET_UNDEFINED(tv_obj);
thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
DUK_ASSERT_LJSTATE_UNSET(thr->heap);
@@ -45589,7 +49843,7 @@ DUK_INTERNAL void duk_err_check_debugger_integration(duk_hthread *thr) {
duk_pop(thr);
}
-#endif /* DUK_USE_DEBUGGER_SUPPORT */
+#endif /* DUK_USE_DEBUGGER_SUPPORT */
/*
* Helpers for setting up heap longjmp state.
@@ -45612,10 +49866,10 @@ DUK_INTERNAL void duk_err_setup_ljstate1(duk_hthread *thr, duk_small_uint_t lj_t
DUK_ASSERT_LJSTATE_SET(heap);
}
/*
- * Create and throw an Ecmascript error object based on a code and a message.
+ * Create and throw an ECMAScript error object based on a code and a message.
*
- * Used when we throw errors internally. Ecmascript generated error objects
- * are created by Ecmascript code, and the throwing is handled by the bytecode
+ * Used when we throw errors internally. ECMAScript generated error objects
+ * are created by ECMAScript code, and the throwing is handled by the bytecode
* executor.
*/
@@ -45634,14 +49888,20 @@ DUK_INTERNAL void duk_err_setup_ljstate1(duk_hthread *thr, duk_small_uint_t lj_t
*/
#if defined(DUK_USE_VERBOSE_ERRORS)
-DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line) {
+DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr,
+ duk_errcode_t code,
+ const char *msg,
+ const char *filename,
+ duk_int_t line) {
#else
DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code) {
#endif
#if defined(DUK_USE_VERBOSE_ERRORS)
DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld, msg=%s, filename=%s, line=%ld",
- (long) code, (const char *) msg,
- (const char *) filename, (long) line));
+ (long) code,
+ (const char *) msg,
+ (const char *) filename,
+ (long) line));
#else
DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld", (long) code));
#endif
@@ -45701,18 +49961,9 @@ DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code)
* use 'msg' as a format string directly.
*/
#if defined(DUK_USE_VERBOSE_ERRORS)
- duk_push_error_object_raw(thr,
- code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
- filename,
- line,
- "%s",
- (const char *) msg);
+ duk_push_error_object_raw(thr, code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE, filename, line, "%s", (const char *) msg);
#else
- duk_push_error_object_raw(thr,
- code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
- NULL,
- 0,
- NULL);
+ duk_push_error_object_raw(thr, code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE, NULL, 0, NULL);
#endif
/* Note that an alloc error may happen during error augmentation.
@@ -45722,8 +49973,7 @@ DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code)
* avoiding it for alloc errors (this differs from Duktape 1.x).
*/
#if defined(DUK_USE_AUGMENT_ERROR_THROW)
- DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT (before throw augment)",
- (duk_tval *) duk_get_tval(thr, -1)));
+ DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT (before throw augment)", (duk_tval *) duk_get_tval(thr, -1)));
duk_err_augment_error_throw(thr);
#endif
@@ -45746,7 +49996,8 @@ DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code)
*/
DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT, %!iT (after throw augment)",
- (duk_tval *) &thr->heap->lj.value1, (duk_tval *) &thr->heap->lj.value2));
+ (duk_tval *) &thr->heap->lj.value1,
+ (duk_tval *) &thr->heap->lj.value2));
duk_err_longjmp(thr);
DUK_UNREACHABLE();
@@ -45771,7 +50022,7 @@ DUK_INTERNAL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t r
*/
duk_error_raw(thr, -rc, NULL, 0, "error (rc %ld)", (long) rc);
- DUK_UNREACHABLE();
+ DUK_WO_NORETURN(return;);
}
/*
* duk_hbuffer allocation and freeing.
@@ -45800,7 +50051,7 @@ DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk
*/
if (size > DUK_HBUFFER_MAX_BYTELEN) {
DUK_D(DUK_DPRINT("hbuffer alloc failed: size too large: %ld", (long) size));
- return NULL; /* no need to write 'out_bufdata' */
+ return NULL; /* no need to write 'out_bufdata' */
}
if (flags & DUK_BUF_FLAG_EXTERNAL) {
@@ -45812,7 +50063,7 @@ DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk
} else {
header_size = sizeof(duk_hbuffer_fixed);
alloc_size = sizeof(duk_hbuffer_fixed) + size;
- DUK_ASSERT(alloc_size >= sizeof(duk_hbuffer_fixed)); /* no wrapping */
+ DUK_ASSERT(alloc_size >= sizeof(duk_hbuffer_fixed)); /* no wrapping */
}
res = (duk_hbuffer *) DUK_ALLOC(heap, alloc_size);
@@ -45822,10 +50073,9 @@ DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk
/* zero everything unless requested not to do so */
#if defined(DUK_USE_ZERO_BUFFER_DATA)
- DUK_MEMZERO((void *) res,
- (flags & DUK_BUF_FLAG_NOZERO) ? header_size : alloc_size);
+ duk_memzero((void *) res, (flags & DUK_BUF_FLAG_NOZERO) ? header_size : alloc_size);
#else
- DUK_MEMZERO((void *) res, header_size);
+ duk_memzero((void *) res, header_size);
#endif
if (flags & DUK_BUF_FLAG_EXTERNAL) {
@@ -45846,7 +50096,7 @@ DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk
void *ptr;
if (size > 0) {
- DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL)); /* alloc external with size zero */
+ DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL)); /* alloc external with size zero */
DUK_DDD(DUK_DDDPRINT("dynamic buffer with nonzero size, alloc actual buffer"));
#if defined(DUK_USE_ZERO_BUFFER_DATA)
ptr = DUK_ALLOC_ZEROED(heap, size);
@@ -45872,7 +50122,7 @@ DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk
DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, h) == NULL);
}
} else {
- *out_bufdata = (void *) ((duk_hbuffer_fixed *) res + 1);
+ *out_bufdata = (void *) ((duk_hbuffer_fixed *) (void *) res + 1);
}
DUK_HBUFFER_SET_SIZE(res, size);
@@ -45886,16 +50136,16 @@ DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk
} else {
DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));
}
- DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &res->hdr);
+ DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &res->hdr);
DUK_DDD(DUK_DDDPRINT("allocated hbuffer: %p", (void *) res));
return res;
- alloc_error:
+alloc_error:
DUK_DD(DUK_DDPRINT("hbuffer allocation failed"));
DUK_FREE(heap, res);
- return NULL; /* no need to write 'out_bufdata' */
+ return NULL; /* no need to write 'out_bufdata' */
}
/* For indirect allocs. */
@@ -45906,6 +50156,19 @@ DUK_INTERNAL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud) {
return (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, buf);
}
/*
+ * duk_hbuffer assertion helpers
+ */
+
+/* #include duk_internal.h -> already included */
+
+#if defined(DUK_USE_ASSERTIONS)
+
+DUK_INTERNAL void duk_hbuffer_assert_valid(duk_hbuffer *h) {
+ DUK_ASSERT(h != NULL);
+}
+
+#endif /* DUK_USE_ASSERTIONS */
+/*
* duk_hbuffer operations such as resizing and inserting/appending data to
* a dynamic buffer.
*/
@@ -45931,6 +50194,7 @@ DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf,
if (new_size > DUK_HBUFFER_MAX_BYTELEN) {
DUK_ERROR_RANGE(thr, "buffer too long");
+ DUK_WO_NORETURN(return;);
}
/*
@@ -45959,8 +50223,7 @@ DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf,
if (new_size > prev_size) {
DUK_ASSERT(new_size - prev_size > 0);
#if defined(DUK_USE_ZERO_BUFFER_DATA)
- DUK_MEMZERO((void *) ((char *) res + prev_size),
- (duk_size_t) (new_size - prev_size));
+ duk_memzero((void *) ((char *) res + prev_size), (duk_size_t) (new_size - prev_size));
#endif
}
@@ -45968,6 +50231,7 @@ DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf,
DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr->heap, buf, res);
} else {
DUK_ERROR_ALLOC_FAILED(thr);
+ DUK_WO_NORETURN(return;);
}
DUK_ASSERT(res != NULL || new_size == 0);
@@ -46000,7 +50264,7 @@ DUK_INTERNAL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_
return buf_avail >= len ? len : buf_avail;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
* duk_heap allocation and freeing.
*/
@@ -46009,7 +50273,7 @@ DUK_INTERNAL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_
#if defined(DUK_USE_ROM_STRINGS)
/* Fixed seed value used with ROM strings. */
-#define DUK__FIXED_HASH_SEED 0xabcd1234
+#define DUK__FIXED_HASH_SEED 0xabcd1234
#endif
/*
@@ -46069,7 +50333,7 @@ DUK_INTERNAL void duk_free_hobject(duk_heap *heap, duk_hobject *h) {
* functions in the callstack.
*/
} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
- duk_hboundfunc *f = (duk_hboundfunc *) h;
+ duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
DUK_FREE(heap, f->args);
}
@@ -46098,8 +50362,8 @@ DUK_INTERNAL void duk_free_hstring(duk_heap *heap, duk_hstring *h) {
#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_FREE)
if (DUK_HSTRING_HAS_EXTDATA(h)) {
- DUK_DDD(DUK_DDDPRINT("free extstr: hstring %!O, extdata: %p",
- h, DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h)));
+ DUK_DDD(
+ DUK_DDDPRINT("free extstr: hstring %!O, extdata: %p", h, DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h)));
DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h));
}
#endif
@@ -46123,7 +50387,6 @@ DUK_INTERNAL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr) {
DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) == DUK_HTYPE_BUFFER);
duk_free_hbuffer(heap, (duk_hbuffer *) hdr);
}
-
}
/*
@@ -46153,10 +50416,10 @@ DUK_LOCAL duk_size_t duk__heap_free_activation_freelist(duk_heap *heap) {
count_act++;
#endif
}
- heap->activation_free = NULL; /* needed when called from mark-and-sweep */
+ heap->activation_free = NULL; /* needed when called from mark-and-sweep */
return count_act;
}
-#endif /* DUK_USE_CACHE_ACTIVATION */
+#endif /* DUK_USE_CACHE_ACTIVATION */
#if defined(DUK_USE_CACHE_CATCHER)
DUK_LOCAL duk_size_t duk__heap_free_catcher_freelist(duk_heap *heap) {
@@ -46172,11 +50435,11 @@ DUK_LOCAL duk_size_t duk__heap_free_catcher_freelist(duk_heap *heap) {
count_cat++;
#endif
}
- heap->catcher_free = NULL; /* needed when called from mark-and-sweep */
+ heap->catcher_free = NULL; /* needed when called from mark-and-sweep */
return count_cat;
}
-#endif /* DUK_USE_CACHE_CATCHER */
+#endif /* DUK_USE_CACHE_CATCHER */
DUK_INTERNAL void duk_heap_free_freelists(duk_heap *heap) {
duk_size_t count_act = 0;
@@ -46192,8 +50455,8 @@ DUK_INTERNAL void duk_heap_free_freelists(duk_heap *heap) {
DUK_UNREF(count_act);
DUK_UNREF(count_cat);
- DUK_D(DUK_DPRINT("freed %ld activation freelist entries, %ld catcher freelist entries",
- (long) count_act, (long) count_cat));
+ DUK_D(
+ DUK_DPRINT("freed %ld activation freelist entries, %ld catcher freelist entries", (long) count_act, (long) count_cat));
}
DUK_LOCAL void duk__free_allocated(duk_heap *heap) {
@@ -46206,8 +50469,7 @@ DUK_LOCAL void duk__free_allocated(duk_heap *heap) {
* because they may happen with finalizer processing.
*/
- DUK_DDD(DUK_DDDPRINT("FINALFREE (allocated): %!iO",
- (duk_heaphdr *) curr));
+ DUK_DDD(DUK_DDDPRINT("FINALFREE (allocated): %!iO", (duk_heaphdr *) curr));
next = DUK_HEAPHDR_GET_NEXT(heap, curr);
duk_heap_free_heaphdr_raw(heap, curr);
curr = next;
@@ -46221,14 +50483,13 @@ DUK_LOCAL void duk__free_finalize_list(duk_heap *heap) {
curr = heap->finalize_list;
while (curr) {
- DUK_DDD(DUK_DDDPRINT("FINALFREE (finalize_list): %!iO",
- (duk_heaphdr *) curr));
+ DUK_DDD(DUK_DDDPRINT("FINALFREE (finalize_list): %!iO", (duk_heaphdr *) curr));
next = DUK_HEAPHDR_GET_NEXT(heap, curr);
duk_heap_free_heaphdr_raw(heap, curr);
curr = next;
}
}
-#endif /* DUK_USE_FINALIZER_SUPPORT */
+#endif /* DUK_USE_FINALIZER_SUPPORT */
DUK_LOCAL void duk__free_stringtable(duk_heap *heap) {
/* strings are only tracked by stringtable */
@@ -46246,9 +50507,9 @@ DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap) {
DUK_ASSERT(heap != NULL);
#if defined(DUK_USE_REFERENCE_COUNTING)
- DUK_ASSERT(heap->refzero_list == NULL); /* refzero not running -> must be empty */
+ DUK_ASSERT(heap->refzero_list == NULL); /* refzero not running -> must be empty */
#endif
- DUK_ASSERT(heap->finalize_list == NULL); /* mark-and-sweep last pass */
+ DUK_ASSERT(heap->finalize_list == NULL); /* mark-and-sweep last pass */
if (heap->heap_thread == NULL) {
/* May happen when heap allocation fails right off. There
@@ -46259,19 +50520,23 @@ DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap) {
}
/* Prevent finalize_list processing and mark-and-sweep entirely.
- * Setting ms_running = 1 also prevents refzero handling from moving
- * objects away from the heap_allocated list (the flag name is a bit
- * misleading here).
+ * Setting ms_running != 0 also prevents refzero handling from moving
+ * objects away from the heap_allocated list. The flag name is a bit
+ * misleading here.
+ *
+ * Use a distinct value for ms_running here (== 2) so that assertions
+ * can detect this situation separate from the normal runtime
+ * mark-and-sweep case. This allows better assertions (GH-2030).
*/
DUK_ASSERT(heap->pf_prevent_count == 0);
- heap->pf_prevent_count = 1;
DUK_ASSERT(heap->ms_running == 0);
- heap->ms_running = 1;
DUK_ASSERT(heap->ms_prevent_count == 0);
- heap->ms_prevent_count = 1; /* Bump, because mark-and-sweep assumes it's bumped when ms_running is set. */
+ heap->pf_prevent_count = 1;
+ heap->ms_running = 2; /* Use distinguishable value. */
+ heap->ms_prevent_count = 1; /* Bump, because mark-and-sweep assumes it's bumped when ms_running is set. */
- curr_limit = 0; /* suppress warning, not used */
- for (round_no = 0; ; round_no++) {
+ curr_limit = 0; /* suppress warning, not used */
+ for (round_no = 0;; round_no++) {
curr = heap->heap_allocated;
count_all = 0;
count_finalized = 0;
@@ -46286,7 +50551,8 @@ DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap) {
if (DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) curr)) {
if (!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) curr)) {
- DUK_ASSERT(DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)); /* maps to finalizer 2nd argument */
+ DUK_ASSERT(
+ DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)); /* maps to finalizer 2nd argument */
duk_heap_run_finalizer(heap, (duk_hobject *) curr);
count_finalized++;
}
@@ -46313,10 +50579,13 @@ DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap) {
*/
curr_limit = count_all * 2;
} else {
- curr_limit = (curr_limit * 3) / 4; /* Decrease by 25% every round */
+ curr_limit = (curr_limit * 3) / 4; /* Decrease by 25% every round */
}
DUK_D(DUK_DPRINT("finalizer round %ld complete, %ld objects, tried to execute %ld finalizers, current limit is %ld",
- (long) round_no, (long) count_all, (long) count_finalized, (long) curr_limit));
+ (long) round_no,
+ (long) count_all,
+ (long) count_finalized,
+ (long) curr_limit));
if (count_finalized == 0) {
DUK_D(DUK_DPRINT("no more finalizable objects, forced finalization finished"));
@@ -46328,12 +50597,12 @@ DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap) {
}
}
- DUK_ASSERT(heap->ms_running == 1);
- heap->ms_running = 0;
+ DUK_ASSERT(heap->ms_running == 2);
DUK_ASSERT(heap->pf_prevent_count == 1);
+ heap->ms_running = 0;
heap->pf_prevent_count = 0;
}
-#endif /* DUK_USE_FINALIZER_SUPPORT */
+#endif /* DUK_USE_FINALIZER_SUPPORT */
DUK_INTERNAL void duk_heap_free(duk_heap *heap) {
DUK_D(DUK_DPRINT("free heap: %p", (void *) heap));
@@ -46376,7 +50645,7 @@ DUK_INTERNAL void duk_heap_free(duk_heap *heap) {
duk_heap_mark_and_sweep(heap, 0);
DUK_D(DUK_DPRINT("forced gc #3 in heap destruction (don't run finalizers)"));
heap->pf_skip_finalizers = 1;
- duk_heap_mark_and_sweep(heap, 0); /* Skip finalizers; queue finalizable objects to heap_allocated. */
+ duk_heap_mark_and_sweep(heap, 0); /* Skip finalizers; queue finalizable objects to heap_allocated. */
/* There are never objects in refzero_list at this point, or at any
* point beyond a DECREF (even a DECREF_NORZ). Since Duktape 2.1
@@ -46385,17 +50654,17 @@ DUK_INTERNAL void duk_heap_free(duk_heap *heap) {
* refcount.
*/
#if defined(DUK_USE_REFERENCE_COUNTING)
- DUK_ASSERT(heap->refzero_list == NULL); /* Always processed to completion inline. */
+ DUK_ASSERT(heap->refzero_list == NULL); /* Always processed to completion inline. */
#endif
#if defined(DUK_USE_FINALIZER_SUPPORT)
- DUK_ASSERT(heap->finalize_list == NULL); /* Last mark-and-sweep with skip_finalizers. */
+ DUK_ASSERT(heap->finalize_list == NULL); /* Last mark-and-sweep with skip_finalizers. */
#endif
#if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_D(DUK_DPRINT("run finalizers for remaining finalizable objects"));
- DUK_HEAP_SET_FINALIZER_NORESCUE(heap); /* Rescue no longer supported. */
+ DUK_HEAP_SET_FINALIZER_NORESCUE(heap); /* Rescue no longer supported. */
duk__free_run_finalizers(heap);
-#endif /* DUK_USE_FINALIZER_SUPPORT */
+#endif /* DUK_USE_FINALIZER_SUPPORT */
/* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object
* are on the heap allocated list.
@@ -46408,7 +50677,7 @@ DUK_INTERNAL void duk_heap_free(duk_heap *heap) {
duk__free_allocated(heap);
#if defined(DUK_USE_REFERENCE_COUNTING)
- DUK_ASSERT(heap->refzero_list == NULL); /* Always processed to completion inline. */
+ DUK_ASSERT(heap->refzero_list == NULL); /* Always processed to completion inline. */
#endif
#if defined(DUK_USE_FINALIZER_SUPPORT)
@@ -46451,7 +50720,9 @@ DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
while (h != NULL) {
hash = duk_heap_hashstring(heap, (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
DUK_DD(DUK_DDPRINT("duk_rom_strings_lookup[%d] -> hash 0x%08lx, computed 0x%08lx",
- (int) i, (unsigned long) DUK_HSTRING_GET_HASH(h), (unsigned long) hash));
+ (int) i,
+ (unsigned long) DUK_HSTRING_GET_HASH(h),
+ (unsigned long) hash));
DUK_ASSERT(hash == (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
h = (const duk_hstring *) h->hdr.h_next;
@@ -46460,14 +50731,14 @@ DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
#endif
return 1;
}
-#else /* DUK_USE_ROM_STRINGS */
+#else /* DUK_USE_ROM_STRINGS */
DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
duk_bitdecoder_ctx bd_ctx;
- duk_bitdecoder_ctx *bd = &bd_ctx; /* convenience */
+ duk_bitdecoder_ctx *bd = &bd_ctx; /* convenience */
duk_small_uint_t i;
- DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
+ duk_memzero(&bd_ctx, sizeof(bd_ctx));
bd->data = (const duk_uint8_t *) duk_strings_data;
bd->length = (duk_size_t) DUK_STRDATA_DATA_LENGTH;
@@ -46520,18 +50791,16 @@ DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
return 1;
- failed:
+failed:
return 0;
}
-#endif /* DUK_USE_ROM_STRINGS */
+#endif /* DUK_USE_ROM_STRINGS */
DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap) {
duk_hthread *thr;
DUK_D(DUK_DPRINT("heap init: alloc heap thread"));
- thr = duk_hthread_alloc_unchecked(heap,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
+ thr = duk_hthread_alloc_unchecked(heap, DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
if (thr == NULL) {
DUK_D(DUK_DPRINT("failed to alloc heap_thread"));
return 0;
@@ -46539,16 +50808,16 @@ DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap) {
thr->state = DUK_HTHREAD_STATE_INACTIVE;
#if defined(DUK_USE_ROM_STRINGS)
/* No strs[] pointer. */
-#else /* DUK_USE_ROM_STRINGS */
+#else /* DUK_USE_ROM_STRINGS */
#if defined(DUK_USE_HEAPPTR16)
thr->strs16 = heap->strs16;
#else
thr->strs = heap->strs;
#endif
-#endif /* DUK_USE_ROM_STRINGS */
+#endif /* DUK_USE_ROM_STRINGS */
heap->heap_thread = thr;
- DUK_HTHREAD_INCREF(thr, thr); /* Note: first argument not really used */
+ DUK_HTHREAD_INCREF(thr, thr); /* Note: first argument not really used */
/* 'thr' is now reachable */
@@ -46567,7 +50836,8 @@ DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap) {
}
#if defined(DUK_USE_DEBUG)
-#define DUK__DUMPSZ(t) do { \
+#define DUK__DUMPSZ(t) \
+ do { \
DUK_D(DUK_DPRINT("" #t "=%ld", (long) sizeof(t))); \
} while (0)
@@ -46576,20 +50846,20 @@ DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap) {
* enough; the limits will then not be printed accurately but the magnitude
* will be correct.
*/
-#define DUK__DUMPLM_SIGNED_RAW(t,a,b) do { \
- DUK_D(DUK_DPRINT(t "=[%ld,%ld]=[%lf,%lf]", \
- (long) (a), (long) (b), \
- (double) (a), (double) (b))); \
+#define DUK__DUMPLM_SIGNED_RAW(t, a, b) \
+ do { \
+ DUK_D(DUK_DPRINT(t "=[%ld,%ld]=[%lf,%lf]", (long) (a), (long) (b), (double) (a), (double) (b))); \
} while (0)
-#define DUK__DUMPLM_UNSIGNED_RAW(t,a,b) do { \
- DUK_D(DUK_DPRINT(t "=[%lu,%lu]=[%lf,%lf]", \
- (unsigned long) (a), (unsigned long) (b), \
- (double) (a), (double) (b))); \
+#define DUK__DUMPLM_UNSIGNED_RAW(t, a, b) \
+ do { \
+ DUK_D(DUK_DPRINT(t "=[%lu,%lu]=[%lf,%lf]", (unsigned long) (a), (unsigned long) (b), (double) (a), (double) (b))); \
} while (0)
-#define DUK__DUMPLM_SIGNED(t) do { \
+#define DUK__DUMPLM_SIGNED(t) \
+ do { \
DUK__DUMPLM_SIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
} while (0)
-#define DUK__DUMPLM_UNSIGNED(t) do { \
+#define DUK__DUMPLM_UNSIGNED(t) \
+ do { \
DUK__DUMPLM_UNSIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
} while (0)
@@ -46662,7 +50932,7 @@ DUK_LOCAL void duk__dump_type_sizes(void) {
DUK__DUMPSZ(duk_tval);
/* structs from duk_forwdecl.h */
- DUK__DUMPSZ(duk_jmpbuf); /* just one 'int' for C++ exceptions */
+ DUK__DUMPSZ(duk_jmpbuf); /* just one 'int' for C++ exceptions */
DUK__DUMPSZ(duk_heaphdr);
DUK__DUMPSZ(duk_heaphdr_string);
DUK__DUMPSZ(duk_hstring);
@@ -46688,7 +50958,8 @@ DUK_LOCAL void duk__dump_type_sizes(void) {
DUK__DUMPSZ(duk_heap);
DUK__DUMPSZ(duk_activation);
DUK__DUMPSZ(duk_catcher);
- DUK__DUMPSZ(duk_strcache);
+ DUK__DUMPSZ(duk_strcache_entry);
+ DUK__DUMPSZ(duk_litcache_entry);
DUK__DUMPSZ(duk_ljstate);
DUK__DUMPSZ(duk_fixedbuffer);
DUK__DUMPSZ(duk_bitdecoder_ctx);
@@ -46785,7 +51056,7 @@ DUK_LOCAL void duk__dump_misc_options(void) {
DUK_D(DUK_DPRINT("IEEE double endianness: ???"));
#endif
}
-#endif /* DUK_USE_DEBUG */
+#endif /* DUK_USE_DEBUG */
DUK_INTERNAL
duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
@@ -46806,7 +51077,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
DUK_ASSERT((DUK_HTYPE_STRING & 0x01U) == 0);
DUK_ASSERT((DUK_HTYPE_BUFFER & 0x01U) == 0);
- DUK_ASSERT((DUK_HTYPE_OBJECT & 0x01U) == 1); /* DUK_HEAPHDR_IS_OBJECT() relies ont his. */
+ DUK_ASSERT((DUK_HTYPE_OBJECT & 0x01U) == 1); /* DUK_HEAPHDR_IS_OBJECT() relies ont his. */
/*
* Debug dump type sizes
@@ -46847,7 +51118,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
#endif
fatal_func(heap_udata, "sizeof(duk_tval) not 8 or 16, cannot use DUK_USE_EXEC_REGCONST_OPTIMIZE option");
}
-#endif /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
+#endif /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
/*
* Computed values (e.g. INFINITY)
@@ -46897,7 +51168,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
* Zero the struct, and start initializing roughly in order
*/
- DUK_MEMZERO(res, sizeof(*res));
+ duk_memzero(res, sizeof(*res));
#if defined(DUK_USE_ASSERTIONS)
res->heap_initializing = 1;
#endif
@@ -46931,18 +51202,18 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
#endif
#if defined(DUK_USE_ROM_STRINGS)
/* no res->strs[] */
-#else /* DUK_USE_ROM_STRINGS */
+#else /* DUK_USE_ROM_STRINGS */
#if defined(DUK_USE_HEAPPTR16)
/* res->strs16[] is zeroed and zero decodes to NULL, so no NULL inits. */
#else
{
duk_small_uint_t i;
- for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
+ for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
res->strs[i] = NULL;
- }
+ }
}
#endif
-#endif /* DUK_USE_ROM_STRINGS */
+#endif /* DUK_USE_ROM_STRINGS */
#if defined(DUK_USE_DEBUGGER_SUPPORT)
res->dbg_read_cb = NULL;
res->dbg_write_cb = NULL;
@@ -46953,7 +51224,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
res->dbg_udata = NULL;
res->dbg_pause_act = NULL;
#endif
-#endif /* DUK_USE_EXPLICIT_NULL_INIT */
+#endif /* DUK_USE_EXPLICIT_NULL_INIT */
res->alloc_func = alloc_func;
res->realloc_func = realloc_func;
@@ -46982,7 +51253,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
/* XXX: use the pointer as a seed for now: mix in time at least */
- /* The casts through duk_intptr_t is to avoid the following GCC warning:
+ /* The casts through duk_uintptr_t is to avoid the following GCC warning:
*
* warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
*
@@ -46992,17 +51263,17 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
/* XXX: make a common DUK_USE_ option, and allow custom fixed seed? */
DUK_D(DUK_DPRINT("using rom strings, force heap hash_seed to fixed value 0x%08lx", (long) DUK__FIXED_HASH_SEED));
res->hash_seed = (duk_uint32_t) DUK__FIXED_HASH_SEED;
-#else /* DUK_USE_ROM_STRINGS */
- res->hash_seed = (duk_uint32_t) (duk_intptr_t) res;
+#else /* DUK_USE_ROM_STRINGS */
+ res->hash_seed = (duk_uint32_t) (duk_uintptr_t) res;
#if !defined(DUK_USE_STRHASH_DENSE)
- res->hash_seed ^= 5381; /* Bernstein hash init value is normally 5381; XOR it in in case pointer low bits are 0 */
+ res->hash_seed ^= 5381; /* Bernstein hash init value is normally 5381; XOR it in in case pointer low bits are 0 */
#endif
-#endif /* DUK_USE_ROM_STRINGS */
+#endif /* DUK_USE_ROM_STRINGS */
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
res->lj.jmpbuf_ptr = NULL;
#endif
- DUK_ASSERT(res->lj.type == DUK_LJ_TYPE_UNKNOWN); /* zero */
+ DUK_ASSERT(res->lj.type == DUK_LJ_TYPE_UNKNOWN); /* zero */
DUK_ASSERT(res->lj.iserror == 0);
DUK_TVAL_SET_UNDEFINED(&res->lj.value1);
DUK_TVAL_SET_UNDEFINED(&res->lj.value2);
@@ -47033,19 +51304,19 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
#if defined(DUK_USE_STRTAB_PTRCOMP)
/* zero assumption */
- DUK_MEMZERO(res->strtable16, sizeof(duk_uint16_t) * st_initsize);
+ duk_memzero(res->strtable16, sizeof(duk_uint16_t) * st_initsize);
#else
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
{
- duk_small_uint_t i;
- for (i = 0; i < st_initsize; i++) {
+ duk_uint32_t i;
+ for (i = 0; i < st_initsize; i++) {
res->strtable[i] = NULL;
- }
+ }
}
#else
- DUK_MEMZERO(res->strtable, sizeof(duk_hstring *) * st_initsize);
-#endif /* DUK_USE_EXPLICIT_NULL_INIT */
-#endif /* DUK_USE_STRTAB_PTRCOMP */
+ duk_memzero(res->strtable, sizeof(duk_hstring *) * st_initsize);
+#endif /* DUK_USE_EXPLICIT_NULL_INIT */
+#endif /* DUK_USE_STRTAB_PTRCOMP */
/*
* Init stringcache
@@ -47053,13 +51324,30 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
{
- duk_small_uint_t i;
+ duk_uint_t i;
for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
res->strcache[i].h = NULL;
}
}
#endif
+ /*
+ * Init litcache
+ */
+#if defined(DUK_USE_LITCACHE_SIZE)
+ DUK_ASSERT(DUK_USE_LITCACHE_SIZE > 0);
+ DUK_ASSERT(DUK_IS_POWER_OF_TWO((duk_uint_t) DUK_USE_LITCACHE_SIZE));
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
+ {
+ duk_uint_t i;
+ for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
+ res->litcache[i].addr = NULL;
+ res->litcache[i].h = NULL;
+ }
+ }
+#endif
+#endif /* DUK_USE_LITCACHE_SIZE */
+
/* XXX: error handling is incomplete. It would be cleanest if
* there was a setjmp catchpoint, so that all init code could
* freely throw errors. If that were the case, the return code
@@ -47099,9 +51387,9 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
#endif
DUK_D(DUK_DPRINT("heap init: initialize heap object"));
DUK_ASSERT(res->heap_thread != NULL);
- res->heap_object = duk_hobject_alloc_unchecked(res, DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT));
+ res->heap_object = duk_hobject_alloc_unchecked(res,
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT));
if (res->heap_object == NULL) {
goto failed;
}
@@ -47117,8 +51405,8 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
duk_util_tinyrandom_prepare_seed(res->heap_thread);
#else
res->rnd_state[0] = (duk_uint64_t) duk_time_get_ecmascript_time(res->heap_thread);
- DUK_ASSERT(res->rnd_state[1] == 0); /* Not filled here, filled in by seed preparation. */
-#if 0 /* Manual test values matching misc/xoroshiro128plus_test.c. */
+ DUK_ASSERT(res->rnd_state[1] == 0); /* Not filled here, filled in by seed preparation. */
+#if 0 /* Manual test values matching misc/xoroshiro128plus_test.c. */
res->rnd_state[0] = DUK_U64_CONSTANT(0xdeadbeef12345678);
res->rnd_state[1] = DUK_U64_CONSTANT(0xcafed00d12345678);
#endif
@@ -47131,7 +51419,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
{
duk_uint64_t tmp_u64;
tmp_u64 = 0;
- DUK_MEMCPY((void *) &tmp_u64,
+ duk_memcpy((void *) &tmp_u64,
(const void *) &res,
(size_t) (sizeof(void *) >= sizeof(duk_uint64_t) ? sizeof(duk_uint64_t) : sizeof(void *)));
res->rnd_state[1] ^= tmp_u64;
@@ -47170,7 +51458,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
DUK_D(DUK_DPRINT("allocated heap: %p", (void *) res));
return res;
- failed:
+failed:
DUK_D(DUK_DPRINT("heap allocation failed"));
if (res != NULL) {
@@ -47230,14 +51518,14 @@ DUK_LOCAL duk_ret_t duk__fake_global_finalizer(duk_hthread *thr) {
/* Inner function call, error throw. */
duk_eval_string_noresult(thr,
- "(function dummy() {\n"
- " dummy.prototype = null; /* break reference loop */\n"
- " try {\n"
- " throw 'fake-finalizer-dummy-error';\n"
- " } catch (e) {\n"
- " void e;\n"
- " }\n"
- "})()");
+ "(function dummy() {\n"
+ " dummy.prototype = null; /* break reference loop */\n"
+ " try {\n"
+ " throw 'fake-finalizer-dummy-error';\n"
+ " } catch (e) {\n"
+ " void e;\n"
+ " }\n"
+ "})()");
/* The above creates garbage (e.g. a function instance). Because
* the function/prototype reference loop is broken, it gets collected
@@ -47269,7 +51557,7 @@ DUK_LOCAL void duk__run_global_torture_finalizer(duk_hthread *thr) {
(void) duk_pcall(thr, 0 /*nargs*/);
duk_pop(thr);
}
-#endif /* DUK_USE_FINALIZER_TORTURE */
+#endif /* DUK_USE_FINALIZER_TORTURE */
/*
* Process the finalize_list to completion.
@@ -47381,12 +51669,13 @@ DUK_INTERNAL void duk_heap_process_finalize_list(duk_heap *heap) {
DUK_DD(DUK_DDPRINT("processing finalize_list entry: %p -> %!iO", (void *) curr, curr));
- DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT); /* Only objects have finalizers. */
+ DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT); /* Only objects have finalizers. */
DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));
DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(curr));
- DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(curr)); /* All objects on finalize_list will have this flag (except object being finalized right now). */
- DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr)); /* Queueing code ensures. */
- DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr)); /* ROM objects never get freed (or finalized). */
+ DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(
+ curr)); /* All objects on finalize_list will have this flag (except object being finalized right now). */
+ DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr)); /* Queueing code ensures. */
+ DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr)); /* ROM objects never get freed (or finalized). */
#if defined(DUK_USE_ASSERTIONS)
DUK_ASSERT(heap->currently_finalizing == NULL);
@@ -47414,11 +51703,11 @@ DUK_INTERNAL void duk_heap_process_finalize_list(duk_heap *heap) {
*/
#if defined(DUK_USE_REFERENCE_COUNTING)
DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);
- had_zero_refcount = (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1); /* Preincremented on finalize_list insert. */
+ had_zero_refcount = (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1); /* Preincremented on finalize_list insert. */
#endif
DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
- duk_heap_run_finalizer(heap, (duk_hobject *) curr); /* must never longjmp */
+ duk_heap_run_finalizer(heap, (duk_hobject *) curr); /* must never longjmp */
DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(curr));
/* XXX: assert that object is still in finalize_list
* when duk_push_heapptr() allows automatic rescue.
@@ -47426,12 +51715,14 @@ DUK_INTERNAL void duk_heap_process_finalize_list(duk_heap *heap) {
#if defined(DUK_USE_REFERENCE_COUNTING)
DUK_DD(DUK_DDPRINT("refcount after finalizer (includes bump): %ld", (long) DUK_HEAPHDR_GET_REFCOUNT(curr)));
- if (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1) { /* Only artificial bump in refcount? */
+ if (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1) { /* Only artificial bump in refcount? */
#if defined(DUK_USE_DEBUG)
if (had_zero_refcount) {
- DUK_DD(DUK_DDPRINT("finalized object's refcount is zero -> free immediately (refcount queued)"));
+ DUK_DD(DUK_DDPRINT(
+ "finalized object's refcount is zero -> free immediately (refcount queued)"));
} else {
- DUK_DD(DUK_DDPRINT("finalized object's refcount is zero -> free immediately (mark-and-sweep queued)"));
+ DUK_DD(DUK_DDPRINT(
+ "finalized object's refcount is zero -> free immediately (mark-and-sweep queued)"));
}
#endif
queue_back = 0;
@@ -47481,21 +51772,21 @@ DUK_INTERNAL void duk_heap_process_finalize_list(duk_heap *heap) {
* decision.
*/
DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);
- DUK_HEAPHDR_PREDEC_REFCOUNT(curr); /* Remove artificial refcount bump. */
+ DUK_HEAPHDR_PREDEC_REFCOUNT(curr); /* Remove artificial refcount bump. */
DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);
} else {
/* No need to remove the refcount bump here. */
- DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT); /* currently, always the case */
+ DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT); /* currently, always the case */
DUK_DD(DUK_DDPRINT("refcount finalize after finalizer call: %!O", curr));
duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) curr);
duk_free_hobject(heap, (duk_hobject *) curr);
DUK_DD(DUK_DDPRINT("freed hobject after finalization: %p", (void *) curr));
}
-#else /* DUK_USE_REFERENCE_COUNTING */
+#else /* DUK_USE_REFERENCE_COUNTING */
DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);
-#endif /* DUK_USE_REFERENCE_COUNTING */
+#endif /* DUK_USE_REFERENCE_COUNTING */
#if defined(DUK_USE_DEBUG)
count++;
@@ -47561,11 +51852,11 @@ DUK_LOCAL duk_ret_t duk__finalize_helper(duk_hthread *thr, void *udata) {
* caller must ensure that this function is not called if the target is
* a Proxy.
*/
- duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_FINALIZER); /* -> [... obj finalizer] */
+ duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_FINALIZER); /* -> [... obj finalizer] */
duk_dup_m2(thr);
duk_push_boolean(thr, DUK_HEAP_HAS_FINALIZER_NORESCUE(thr->heap));
DUK_DDD(DUK_DDDPRINT("calling finalizer"));
- duk_call(thr, 2); /* [ ... obj finalizer obj heapDestruct ] -> [ ... obj retval ] */
+ duk_call(thr, 2); /* [ ... obj finalizer obj heapDestruct ] -> [ ... obj retval ] */
DUK_DDD(DUK_DDDPRINT("finalizer returned successfully"));
return 0;
@@ -47614,7 +51905,7 @@ DUK_INTERNAL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj) {
return;
}
#endif
- DUK_HEAPHDR_SET_FINALIZED((duk_heaphdr *) obj); /* ensure never re-entered until rescue cycle complete */
+ DUK_HEAPHDR_SET_FINALIZED((duk_heaphdr *) obj); /* ensure never re-entered until rescue cycle complete */
#if defined(DUK_USE_ES6_PROXY)
if (DUK_HOBJECT_IS_PROXY(obj)) {
@@ -47626,29 +51917,30 @@ DUK_INTERNAL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj) {
DUK_D(DUK_DPRINT("object is a Proxy, skip finalizer call"));
return;
}
-#endif /* DUK_USE_ES6_PROXY */
+#endif /* DUK_USE_ES6_PROXY */
- duk_push_hobject(thr, obj); /* this also increases refcount by one */
- rc = duk_safe_call(thr, duk__finalize_helper, NULL /*udata*/, 0 /*nargs*/, 1 /*nrets*/); /* -> [... obj retval/error] */
- DUK_ASSERT_TOP(thr, entry_top + 2); /* duk_safe_call discipline */
+ duk_push_hobject(thr, obj); /* this also increases refcount by one */
+ rc = duk_safe_call(thr, duk__finalize_helper, NULL /*udata*/, 0 /*nargs*/, 1 /*nrets*/); /* -> [... obj retval/error] */
+ DUK_ASSERT_TOP(thr, entry_top + 2); /* duk_safe_call discipline */
if (rc != DUK_EXEC_SUCCESS) {
/* Note: we ask for one return value from duk_safe_call to get this
* error debugging here.
*/
DUK_D(DUK_DPRINT("wrapped finalizer call failed for object %p (ignored); error: %!T",
- (void *) obj, (duk_tval *) duk_get_tval(thr, -1)));
+ (void *) obj,
+ (duk_tval *) duk_get_tval(thr, -1)));
}
- duk_pop_2(thr); /* -> [...] */
+ duk_pop_2(thr); /* -> [...] */
DUK_ASSERT_TOP(thr, entry_top);
}
-#else /* DUK_USE_FINALIZER_SUPPORT */
+#else /* DUK_USE_FINALIZER_SUPPORT */
/* nothing */
-#endif /* DUK_USE_FINALIZER_SUPPORT */
+#endif /* DUK_USE_FINALIZER_SUPPORT */
/*
* String hash computation (interning).
*
@@ -47672,9 +51964,9 @@ DUK_INTERNAL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj) {
#if defined(DUK_USE_STRHASH_DENSE)
/* Constants for duk_hashstring(). */
-#define DUK__STRHASH_SHORTSTRING 4096L
-#define DUK__STRHASH_MEDIUMSTRING (256L * 1024L)
-#define DUK__STRHASH_BLOCKSIZE 256L
+#define DUK__STRHASH_SHORTSTRING 4096L
+#define DUK__STRHASH_MEDIUMSTRING (256L * 1024L)
+#define DUK__STRHASH_BLOCKSIZE 256L
DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
duk_uint32_t hash;
@@ -47731,7 +52023,7 @@ DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t
#endif
return hash;
}
-#else /* DUK_USE_STRHASH_DENSE */
+#else /* DUK_USE_STRHASH_DENSE */
DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
duk_uint32_t hash;
duk_size_t step;
@@ -47749,10 +52041,10 @@ DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t
* more often in the suffix than in the prefix.
*/
- hash = heap->hash_seed ^ ((duk_uint32_t) len); /* Bernstein hash init value is normally 5381 */
+ hash = heap->hash_seed ^ ((duk_uint32_t) len); /* Bernstein hash init value is normally 5381 */
step = (len >> DUK_USE_STRHASH_SKIP_SHIFT) + 1;
for (off = len; off >= step; off -= step) {
- DUK_ASSERT(off >= 1); /* off >= step, and step >= 1 */
+ DUK_ASSERT(off >= 1); /* off >= step, and step >= 1 */
hash = (hash * 33) + str[off - 1];
}
@@ -47764,7 +52056,7 @@ DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t
#endif
return hash;
}
-#endif /* DUK_USE_STRHASH_DENSE */
+#endif /* DUK_USE_STRHASH_DENSE */
/* automatic undefs */
#undef DUK__STRHASH_BLOCKSIZE
@@ -47791,6 +52083,7 @@ DUK_LOCAL void duk__mark_hstring(duk_heap *heap, duk_hstring *h) {
DUK_DDD(DUK_DDDPRINT("duk__mark_hstring: %p", (void *) h));
DUK_ASSERT(h);
+ DUK_HSTRING_ASSERT_VALID(h);
/* nothing to process */
}
@@ -47801,6 +52094,7 @@ DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
DUK_DDD(DUK_DDDPRINT("duk__mark_hobject: %p", (void *) h));
DUK_ASSERT(h);
+ DUK_HOBJECT_ASSERT_VALID(h);
/* XXX: use advancing pointers instead of index macros -> faster and smaller? */
@@ -47841,7 +52135,7 @@ DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
duk_tval *tv, *tv_end;
duk_hobject **fn, **fn_end;
- DUK_ASSERT_HCOMPFUNC_VALID(f);
+ DUK_HCOMPFUNC_ASSERT_VALID(f);
/* 'data' is reachable through every compiled function which
* contains a reference.
@@ -47871,39 +52165,39 @@ DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
}
} else if (DUK_HOBJECT_IS_DECENV(h)) {
duk_hdecenv *e = (duk_hdecenv *) h;
- DUK_ASSERT_HDECENV_VALID(e);
+ DUK_HDECENV_ASSERT_VALID(e);
duk__mark_heaphdr(heap, (duk_heaphdr *) e->thread);
duk__mark_heaphdr(heap, (duk_heaphdr *) e->varmap);
} else if (DUK_HOBJECT_IS_OBJENV(h)) {
duk_hobjenv *e = (duk_hobjenv *) h;
- DUK_ASSERT_HOBJENV_VALID(e);
+ DUK_HOBJENV_ASSERT_VALID(e);
duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) e->target);
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
duk_hbufobj *b = (duk_hbufobj *) h;
- DUK_ASSERT_HBUFOBJ_VALID(b);
+ DUK_HBUFOBJ_ASSERT_VALID(b);
duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf);
duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf_prop);
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
- duk_hboundfunc *f = (duk_hboundfunc *) h;
- DUK_ASSERT_HBOUNDFUNC_VALID(f);
+ duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
+ DUK_HBOUNDFUNC_ASSERT_VALID(f);
duk__mark_tval(heap, &f->target);
duk__mark_tval(heap, &f->this_binding);
duk__mark_tvals(heap, f->args, f->nargs);
#if defined(DUK_USE_ES6_PROXY)
} else if (DUK_HOBJECT_IS_PROXY(h)) {
duk_hproxy *p = (duk_hproxy *) h;
- DUK_ASSERT_HPROXY_VALID(p);
+ DUK_HPROXY_ASSERT_VALID(p);
duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) p->target);
duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) p->handler);
-#endif /* DUK_USE_ES6_PROXY */
+#endif /* DUK_USE_ES6_PROXY */
} else if (DUK_HOBJECT_IS_THREAD(h)) {
duk_hthread *t = (duk_hthread *) h;
duk_activation *act;
duk_tval *tv;
- DUK_ASSERT_HTHREAD_VALID(t);
+ DUK_HTHREAD_ASSERT_VALID(t);
tv = t->valstack;
while (tv < t->valstack_top) {
@@ -47918,7 +52212,7 @@ DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
duk__mark_heaphdr(heap, (duk_heaphdr *) act->prev_caller);
#endif
-#if 0 /* nothing now */
+#if 0 /* nothing now */
for (cat = act->cat; cat != NULL; cat = cat->parent) {
}
#endif
@@ -47941,20 +52235,20 @@ DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
/* Mark any duk_heaphdr type. Recursion tracking happens only here. */
DUK_LOCAL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h) {
- DUK_DDD(DUK_DDDPRINT("duk__mark_heaphdr %p, type %ld",
- (void *) h,
- (h != NULL ? (long) DUK_HEAPHDR_GET_TYPE(h) : (long) -1)));
+ DUK_DDD(
+ DUK_DDDPRINT("duk__mark_heaphdr %p, type %ld", (void *) h, (h != NULL ? (long) DUK_HEAPHDR_GET_TYPE(h) : (long) -1)));
/* XXX: add non-null variant? */
if (h == NULL) {
return;
}
+ DUK_HEAPHDR_ASSERT_VALID(h);
DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(h) || DUK_HEAPHDR_HAS_REACHABLE(h));
#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
if (!DUK_HEAPHDR_HAS_READONLY(h)) {
- h->h_assert_refcount++; /* Comparison refcount: bump even if already reachable. */
+ h->h_assert_refcount++; /* Comparison refcount: bump even if already reachable. */
}
#endif
if (DUK_HEAPHDR_HAS_REACHABLE(h)) {
@@ -47978,7 +52272,7 @@ DUK_LOCAL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h) {
}
heap->ms_recursion_depth++;
- DUK_ASSERT(heap->ms_recursion_depth != 0); /* Wrap. */
+ DUK_ASSERT(heap->ms_recursion_depth != 0); /* Wrap. */
switch (DUK_HEAPHDR_GET_TYPE(h)) {
case DUK_HTYPE_STRING:
@@ -48004,6 +52298,7 @@ DUK_LOCAL void duk__mark_tval(duk_heap *heap, duk_tval *tv) {
if (tv == NULL) {
return;
}
+ DUK_TVAL_ASSERT_VALID(tv);
if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
duk_heaphdr *h;
h = DUK_TVAL_GET_HEAPHDR(tv);
@@ -48016,6 +52311,7 @@ DUK_LOCAL void duk__mark_tvals(duk_heap *heap, duk_tval *tv, duk_idx_t count) {
DUK_ASSERT(count == 0 || tv != NULL);
while (count-- > 0) {
+ DUK_TVAL_ASSERT_VALID(tv);
if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
duk_heaphdr *h;
h = DUK_TVAL_GET_HEAPHDR(tv);
@@ -48091,9 +52387,7 @@ DUK_LOCAL void duk__mark_finalizable(duk_heap *heap) {
* of a _Finalizer hidden symbol.
*/
- if (!DUK_HEAPHDR_HAS_REACHABLE(hdr) &&
- DUK_HEAPHDR_IS_OBJECT(hdr) &&
- !DUK_HEAPHDR_HAS_FINALIZED(hdr) &&
+ if (!DUK_HEAPHDR_HAS_REACHABLE(hdr) && DUK_HEAPHDR_IS_OBJECT(hdr) && !DUK_HEAPHDR_HAS_FINALIZED(hdr) &&
DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) hdr)) {
/* heaphdr:
* - is not reachable
@@ -48118,8 +52412,7 @@ DUK_LOCAL void duk__mark_finalizable(duk_heap *heap) {
return;
}
- DUK_DD(DUK_DDPRINT("marked %ld heap objects as finalizable, now mark them reachable",
- (long) count_finalizable));
+ DUK_DD(DUK_DDPRINT("marked %ld heap objects as finalizable, now mark them reachable", (long) count_finalizable));
hdr = heap->heap_allocated;
while (hdr != NULL) {
@@ -48132,7 +52425,7 @@ DUK_LOCAL void duk__mark_finalizable(duk_heap *heap) {
/* Caller will finish the marking process if we hit a recursion limit. */
}
-#endif /* DUK_USE_FINALIZER_SUPPORT */
+#endif /* DUK_USE_FINALIZER_SUPPORT */
/*
* Mark objects on finalize_list.
@@ -48163,7 +52456,7 @@ DUK_LOCAL void duk__mark_finalize_list(duk_heap *heap) {
}
#endif
}
-#endif /* DUK_USE_FINALIZER_SUPPORT */
+#endif /* DUK_USE_FINALIZER_SUPPORT */
/*
* Fallback marking handler if recursion limit is reached.
@@ -48196,9 +52489,9 @@ DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr) {
DUK_DDD(DUK_DDDPRINT("found a temp root: %p", (void *) hdr));
DUK_HEAPHDR_CLEAR_TEMPROOT(hdr);
- DUK_HEAPHDR_CLEAR_REACHABLE(hdr); /* Done so that duk__mark_heaphdr() works correctly. */
+ DUK_HEAPHDR_CLEAR_REACHABLE(hdr); /* Done so that duk__mark_heaphdr() works correctly. */
#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
- hdr->h_assert_refcount--; /* Same node visited twice. */
+ hdr->h_assert_refcount--; /* Same node visited twice. */
#endif
duk__mark_heaphdr_nonnull(heap, hdr);
@@ -48293,7 +52586,7 @@ DUK_LOCAL void duk__finalize_refcounts(duk_heap *heap) {
hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
}
}
-#endif /* DUK_USE_REFERENCE_COUNTING */
+#endif /* DUK_USE_REFERENCE_COUNTING */
/*
* Clear (reachable) flags of finalize_list.
@@ -48316,15 +52609,14 @@ DUK_LOCAL void duk__clear_finalize_list_flags(duk_heap *heap) {
while (hdr) {
DUK_HEAPHDR_CLEAR_REACHABLE(hdr);
#if defined(DUK_USE_ASSERTIONS)
- DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(hdr) || \
- (heap->currently_finalizing == hdr));
+ DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(hdr) || (heap->currently_finalizing == hdr));
#endif
/* DUK_HEAPHDR_FLAG_FINALIZED may be set. */
DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
}
}
-#endif /* DUK_USE_FINALIZER_SUPPORT */
+#endif /* DUK_USE_FINALIZER_SUPPORT */
/*
* Sweep stringtable.
@@ -48369,13 +52661,26 @@ DUK_LOCAL void duk__sweep_stringtable(duk_heap *heap, duk_size_t *out_count_keep
count_free++;
#endif
+ /* For pinned strings the refcount has been
+ * bumped. We could unbump it here before
+ * freeing, but that's actually not necessary
+ * except for assertions.
+ */
+#if 0
+ if (DUK_HSTRING_HAS_PINNED_LITERAL(h)) {
+ DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) > 0U);
+ DUK_HSTRING_DECREF_NORZ(heap->heap_thread, h);
+ DUK_HSTRING_CLEAR_PINNED_LITERAL(h);
+ }
+#endif
#if defined(DUK_USE_REFERENCE_COUNTING)
/* Non-zero refcounts should not happen for unreachable strings,
* because we refcount finalize all unreachable objects which
* should have decreased unreachable string refcounts to zero
- * (even for cycles).
+ * (even for cycles). However, pinned strings have a +1 bump.
*/
- DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) == 0);
+ DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) == DUK_HSTRING_HAS_PINNED_LITERAL(h) ? 1U :
+ 0U);
#endif
/* Deal with weak references first. */
@@ -48396,10 +52701,9 @@ DUK_LOCAL void duk__sweep_stringtable(duk_heap *heap, duk_size_t *out_count_keep
}
}
- done:
+done:
#if defined(DUK_USE_DEBUG)
- DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept",
- (long) count_free, (long) count_keep));
+ DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept", (long) count_free, (long) count_keep));
#endif
*out_count_keep = count_keep;
}
@@ -48409,7 +52713,7 @@ DUK_LOCAL void duk__sweep_stringtable(duk_heap *heap, duk_size_t *out_count_keep
*/
DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_small_uint_t flags, duk_size_t *out_count_keep) {
- duk_heaphdr *prev; /* last element that was left in the heap */
+ duk_heaphdr *prev; /* last element that was left in the heap */
duk_heaphdr *curr;
duk_heaphdr *next;
#if defined(DUK_USE_DEBUG)
@@ -48452,25 +52756,28 @@ DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_small_uint_t flags, duk_size_
DUK_DD(DUK_DDPRINT("sweep; reachable, finalizable --> move to finalize_list: %p", (void *) curr));
#if defined(DUK_USE_REFERENCE_COUNTING)
- DUK_HEAPHDR_PREINC_REFCOUNT(curr); /* Bump refcount so that refzero never occurs when pending a finalizer call. */
+ DUK_HEAPHDR_PREINC_REFCOUNT(
+ curr); /* Bump refcount so that refzero never occurs when pending a finalizer call. */
#endif
DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap, curr);
#if defined(DUK_USE_DEBUG)
count_finalize++;
#endif
- }
- else
-#endif /* DUK_USE_FINALIZER_SUPPORT */
+ } else
+#endif /* DUK_USE_FINALIZER_SUPPORT */
{
if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZED(curr))) {
DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);
if (flags & DUK_MS_FLAG_POSTPONE_RESCUE) {
- DUK_DD(DUK_DDPRINT("sweep; reachable, finalized, but postponing rescue decisions --> keep object (with FINALIZED set): %!iO", curr));
+ DUK_DD(DUK_DDPRINT("sweep; reachable, finalized, but postponing rescue decisions "
+ "--> keep object (with FINALIZED set): %!iO",
+ curr));
count_keep++;
} else {
- DUK_DD(DUK_DDPRINT("sweep; reachable, finalized --> rescued after finalization: %p", (void *) curr));
+ DUK_DD(DUK_DDPRINT("sweep; reachable, finalized --> rescued after finalization: %p",
+ (void *) curr));
#if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_HEAPHDR_CLEAR_FINALIZED(curr);
#endif
@@ -48493,8 +52800,8 @@ DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_small_uint_t flags, duk_size_
#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
DUK_HEAPHDR_SET_PREV(heap, curr, prev);
#endif
- DUK_ASSERT_HEAPHDR_LINKS(heap, prev);
- DUK_ASSERT_HEAPHDR_LINKS(heap, curr);
+ DUK_HEAPHDR_ASSERT_LINKS(heap, prev);
+ DUK_HEAPHDR_ASSERT_LINKS(heap, curr);
prev = curr;
}
@@ -48539,7 +52846,8 @@ DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_small_uint_t flags, duk_size_
#if defined(DUK_USE_DEBUG)
if (DUK_HEAPHDR_HAS_FINALIZED(curr)) {
- DUK_DD(DUK_DDPRINT("sweep; unreachable, finalized --> finalized object not rescued: %p", (void *) curr));
+ DUK_DD(DUK_DDPRINT("sweep; unreachable, finalized --> finalized object not rescued: %p",
+ (void *) curr));
} else {
DUK_DD(DUK_DDPRINT("sweep; not reachable --> free: %p", (void *) curr));
}
@@ -48569,16 +52877,39 @@ DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_small_uint_t flags, duk_size_
if (prev != NULL) {
DUK_HEAPHDR_SET_NEXT(heap, prev, NULL);
}
- DUK_ASSERT_HEAPHDR_LINKS(heap, prev);
+ DUK_HEAPHDR_ASSERT_LINKS(heap, prev);
#if defined(DUK_USE_DEBUG)
DUK_D(DUK_DPRINT("mark-and-sweep sweep objects (non-string): %ld freed, %ld kept, %ld rescued, %ld queued for finalization",
- (long) count_free, (long) count_keep, (long) count_rescue, (long) count_finalize));
+ (long) count_free,
+ (long) count_keep,
+ (long) count_rescue,
+ (long) count_finalize));
#endif
*out_count_keep = count_keep;
}
/*
+ * Litcache helpers.
+ */
+
+#if defined(DUK_USE_LITCACHE_SIZE)
+DUK_LOCAL void duk__wipe_litcache(duk_heap *heap) {
+ duk_uint_t i;
+ duk_litcache_entry *e;
+
+ e = heap->litcache;
+ for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
+ e->addr = NULL;
+ /* e->h does not need to be invalidated: when e->addr is
+ * NULL, e->h is considered garbage.
+ */
+ e++;
+ }
+}
+#endif /* DUK_USE_LITCACHE_SIZE */
+
+/*
* Object compaction.
*
* Compaction is assumed to never throw an error.
@@ -48595,7 +52926,12 @@ DUK_LOCAL int duk__protected_compact_object(duk_hthread *thr, void *udata) {
}
#if defined(DUK_USE_DEBUG)
-DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start, duk_size_t *p_count_check, duk_size_t *p_count_compact, duk_size_t *p_count_bytes_saved) {
+DUK_LOCAL void duk__compact_object_list(duk_heap *heap,
+ duk_hthread *thr,
+ duk_heaphdr *start,
+ duk_size_t *p_count_check,
+ duk_size_t *p_count_compact,
+ duk_size_t *p_count_bytes_saved) {
#else
DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start) {
#endif
@@ -48617,9 +52953,8 @@ DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_he
obj = (duk_hobject *) curr;
#if defined(DUK_USE_DEBUG)
- old_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
- DUK_HOBJECT_GET_ASIZE(obj),
- DUK_HOBJECT_GET_HSIZE(obj));
+ old_size =
+ DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj), DUK_HOBJECT_GET_ASIZE(obj), DUK_HOBJECT_GET_HSIZE(obj));
#endif
DUK_DD(DUK_DDPRINT("compact object: %p", (void *) obj));
@@ -48628,9 +52963,8 @@ DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_he
duk_safe_call(thr, duk__protected_compact_object, NULL, 1, 0);
#if defined(DUK_USE_DEBUG)
- new_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
- DUK_HOBJECT_GET_ASIZE(obj),
- DUK_HOBJECT_GET_HSIZE(obj));
+ new_size =
+ DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj), DUK_HOBJECT_GET_ASIZE(obj), DUK_HOBJECT_GET_HSIZE(obj));
#endif
#if defined(DUK_USE_DEBUG)
@@ -48638,7 +52972,7 @@ DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_he
(*p_count_bytes_saved) += (duk_size_t) (old_size - new_size);
#endif
- next:
+ next:
curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
#if defined(DUK_USE_DEBUG)
(*p_count_check)++;
@@ -48670,12 +53004,14 @@ DUK_LOCAL void duk__compact_objects(duk_heap *heap) {
#endif
#endif
#if defined(DUK_USE_REFERENCE_COUNTING)
- DUK_ASSERT(heap->refzero_list == NULL); /* Always handled to completion inline in DECREF. */
+ DUK_ASSERT(heap->refzero_list == NULL); /* Always handled to completion inline in DECREF. */
#endif
#if defined(DUK_USE_DEBUG)
DUK_D(DUK_DPRINT("mark-and-sweep compact objects: %ld checked, %ld compaction attempts, %ld bytes saved by compaction",
- (long) count_check, (long) count_compact, (long) count_bytes_saved));
+ (long) count_check,
+ (long) count_compact,
+ (long) count_bytes_saved));
#endif
}
@@ -48684,67 +53020,19 @@ DUK_LOCAL void duk__compact_objects(duk_heap *heap) {
*/
#if defined(DUK_USE_ASSERTIONS)
-DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
- duk_heaphdr *hdr;
-
- hdr = heap->heap_allocated;
- while (hdr) {
- DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(hdr));
- DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
- DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
- /* may have FINALIZED */
- hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
- }
-
-#if defined(DUK_USE_REFERENCE_COUNTING)
- DUK_ASSERT(heap->refzero_list == NULL); /* Always handled to completion inline in DECREF. */
-#endif
-}
+typedef void (*duk__gc_heaphdr_assert)(duk_heap *heap, duk_heaphdr *h);
+typedef void (*duk__gc_hstring_assert)(duk_heap *heap, duk_hstring *h);
-#if defined(DUK_USE_REFERENCE_COUNTING)
-DUK_LOCAL void duk__assert_valid_refcounts(duk_heap *heap) {
- duk_heaphdr *hdr = heap->heap_allocated;
- while (hdr) {
- /* Cannot really assert much w.r.t. refcounts now. */
-
- if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0 &&
- DUK_HEAPHDR_HAS_FINALIZED(hdr)) {
- /* An object may be in heap_allocated list with a zero
- * refcount if it has just been finalized and is waiting
- * to be collected by the next cycle.
- * (This doesn't currently happen however.)
- */
- } else if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0) {
- /* An object may be in heap_allocated list with a zero
- * refcount also if it is a temporary object created
- * during debugger paused state. It will get collected
- * by mark-and-sweep based on its reachability status
- * (presumably not reachable because refcount is 0).
- */
- }
- DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(hdr) >= 0); /* Unsigned. */
- hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
+DUK_LOCAL void duk__assert_walk_list(duk_heap *heap, duk_heaphdr *start, duk__gc_heaphdr_assert func) {
+ duk_heaphdr *curr;
+ for (curr = start; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
+ func(heap, curr);
}
}
-DUK_LOCAL void duk__clear_assert_refcounts(duk_heap *heap) {
- duk_heaphdr *curr;
+DUK_LOCAL void duk__assert_walk_strtable(duk_heap *heap, duk__gc_hstring_assert func) {
duk_uint32_t i;
- for (curr = heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
- curr->h_assert_refcount = 0;
- }
-#if defined(DUK_USE_FINALIZER_SUPPORT)
- for (curr = heap->finalize_list; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
- curr->h_assert_refcount = 0;
- }
-#endif
-#if defined(DUK_USE_REFERENCE_COUNTING)
- for (curr = heap->refzero_list; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
- curr->h_assert_refcount = 0;
- }
-#endif
-
for (i = 0; i < heap->st_size; i++) {
duk_hstring *h;
@@ -48754,14 +53042,95 @@ DUK_LOCAL void duk__clear_assert_refcounts(duk_heap *heap) {
h = heap->strtable[i];
#endif
while (h != NULL) {
- ((duk_heaphdr *) h)->h_assert_refcount = 0;
+ func(heap, h);
h = h->hdr.h_next;
}
}
}
+DUK_LOCAL void duk__assert_heaphdr_flags_cb(duk_heap *heap, duk_heaphdr *h) {
+ DUK_UNREF(heap);
+ DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(h));
+ DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(h));
+ DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(h));
+ /* may have FINALIZED */
+}
+DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
+ duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_heaphdr_flags_cb);
+#if defined(DUK_USE_REFERENCE_COUNTING)
+ DUK_ASSERT(heap->refzero_list == NULL); /* Always handled to completion inline in DECREF. */
+#endif
+ /* XXX: Assertions for finalize_list? */
+}
+
+DUK_LOCAL void duk__assert_validity_cb1(duk_heap *heap, duk_heaphdr *h) {
+ DUK_UNREF(heap);
+ DUK_ASSERT(DUK_HEAPHDR_IS_OBJECT(h) || DUK_HEAPHDR_IS_BUFFER(h));
+ duk_heaphdr_assert_valid_subclassed(h);
+}
+DUK_LOCAL void duk__assert_validity_cb2(duk_heap *heap, duk_hstring *h) {
+ DUK_UNREF(heap);
+ DUK_ASSERT(DUK_HEAPHDR_IS_STRING((duk_heaphdr *) h));
+ duk_heaphdr_assert_valid_subclassed((duk_heaphdr *) h);
+}
+DUK_LOCAL void duk__assert_validity(duk_heap *heap) {
+ duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_validity_cb1);
+#if defined(DUK_USE_FINALIZER_SUPPORT)
+ duk__assert_walk_list(heap, heap->finalize_list, duk__assert_validity_cb1);
+#endif
+#if defined(DUK_USE_REFERENCE_COUNTING)
+ duk__assert_walk_list(heap, heap->refzero_list, duk__assert_validity_cb1);
+#endif
+ duk__assert_walk_strtable(heap, duk__assert_validity_cb2);
+}
+
+#if defined(DUK_USE_REFERENCE_COUNTING)
+DUK_LOCAL void duk__assert_valid_refcounts_cb(duk_heap *heap, duk_heaphdr *h) {
+ /* Cannot really assert much w.r.t. refcounts now. */
+
+ DUK_UNREF(heap);
+ if (DUK_HEAPHDR_GET_REFCOUNT(h) == 0 && DUK_HEAPHDR_HAS_FINALIZED(h)) {
+ /* An object may be in heap_allocated list with a zero
+ * refcount if it has just been finalized and is waiting
+ * to be collected by the next cycle.
+ * (This doesn't currently happen however.)
+ */
+ } else if (DUK_HEAPHDR_GET_REFCOUNT(h) == 0) {
+ /* An object may be in heap_allocated list with a zero
+ * refcount also if it is a temporary object created
+ * during debugger paused state. It will get collected
+ * by mark-and-sweep based on its reachability status
+ * (presumably not reachable because refcount is 0).
+ */
+ }
+ DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0); /* Unsigned. */
+}
+DUK_LOCAL void duk__assert_valid_refcounts(duk_heap *heap) {
+ duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_valid_refcounts_cb);
+}
+
+DUK_LOCAL void duk__clear_assert_refcounts_cb1(duk_heap *heap, duk_heaphdr *h) {
+ DUK_UNREF(heap);
+ h->h_assert_refcount = 0;
+}
+DUK_LOCAL void duk__clear_assert_refcounts_cb2(duk_heap *heap, duk_hstring *h) {
+ DUK_UNREF(heap);
+ ((duk_heaphdr *) h)->h_assert_refcount = 0;
+}
+DUK_LOCAL void duk__clear_assert_refcounts(duk_heap *heap) {
+ duk__assert_walk_list(heap, heap->heap_allocated, duk__clear_assert_refcounts_cb1);
+#if defined(DUK_USE_FINALIZER_SUPPORT)
+ duk__assert_walk_list(heap, heap->finalize_list, duk__clear_assert_refcounts_cb1);
+#endif
+#if defined(DUK_USE_REFERENCE_COUNTING)
+ duk__assert_walk_list(heap, heap->refzero_list, duk__clear_assert_refcounts_cb1);
+#endif
+ duk__assert_walk_strtable(heap, duk__clear_assert_refcounts_cb2);
+}
+
DUK_LOCAL void duk__check_refcount_heaphdr(duk_heaphdr *hdr) {
duk_bool_t count_ok;
+ duk_size_t expect_refc;
/* The refcount check only makes sense for reachable objects on
* heap_allocated or string table, after the sweep phase. Prior to
@@ -48778,44 +53147,55 @@ DUK_LOCAL void duk__check_refcount_heaphdr(duk_heaphdr *hdr) {
*/
DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr));
- count_ok = ((duk_size_t) DUK_HEAPHDR_GET_REFCOUNT(hdr) == hdr->h_assert_refcount);
+ expect_refc = hdr->h_assert_refcount;
+ if (DUK_HEAPHDR_IS_STRING(hdr) && DUK_HSTRING_HAS_PINNED_LITERAL((duk_hstring *) hdr)) {
+ expect_refc++;
+ }
+ count_ok = ((duk_size_t) DUK_HEAPHDR_GET_REFCOUNT(hdr) == expect_refc);
if (!count_ok) {
DUK_D(DUK_DPRINT("refcount mismatch for: %p: header=%ld counted=%ld --> %!iO",
- (void *) hdr, (long) DUK_HEAPHDR_GET_REFCOUNT(hdr),
- (long) hdr->h_assert_refcount, hdr));
+ (void *) hdr,
+ (long) DUK_HEAPHDR_GET_REFCOUNT(hdr),
+ (long) hdr->h_assert_refcount,
+ hdr));
DUK_ASSERT(0);
}
}
+DUK_LOCAL void duk__check_assert_refcounts_cb1(duk_heap *heap, duk_heaphdr *h) {
+ DUK_UNREF(heap);
+ duk__check_refcount_heaphdr(h);
+}
+DUK_LOCAL void duk__check_assert_refcounts_cb2(duk_heap *heap, duk_hstring *h) {
+ DUK_UNREF(heap);
+ duk__check_refcount_heaphdr((duk_heaphdr *) h);
+}
DUK_LOCAL void duk__check_assert_refcounts(duk_heap *heap) {
- duk_heaphdr *curr;
- duk_uint32_t i;
-
- for (curr = heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
- duk__check_refcount_heaphdr(curr);
- }
+ duk__assert_walk_list(heap, heap->heap_allocated, duk__check_assert_refcounts_cb1);
#if defined(DUK_USE_FINALIZER_SUPPORT)
- for (curr = heap->finalize_list; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
- duk__check_refcount_heaphdr(curr);
- }
+ duk__assert_walk_list(heap, heap->finalize_list, duk__check_assert_refcounts_cb1);
#endif
+ /* XXX: Assert anything for refzero_list? */
+ duk__assert_walk_strtable(heap, duk__check_assert_refcounts_cb2);
+}
+#endif /* DUK_USE_REFERENCE_COUNTING */
- for (i = 0; i < heap->st_size; i++) {
- duk_hstring *h;
+#if defined(DUK_USE_LITCACHE_SIZE)
+DUK_LOCAL void duk__assert_litcache_nulls(duk_heap *heap) {
+ duk_uint_t i;
+ duk_litcache_entry *e;
-#if defined(DUK_USE_STRTAB_PTRCOMP)
- h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
-#else
- h = heap->strtable[i];
-#endif
- while (h != NULL) {
- duk__check_refcount_heaphdr((duk_heaphdr *) h);
- h = h->hdr.h_next;
- }
+ e = heap->litcache;
+ for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
+ /* Entry addresses were NULLed before mark-and-sweep, check
+ * that they're still NULL afterwards to ensure no pointers
+ * were recorded through any side effects.
+ */
+ DUK_ASSERT(e->addr == NULL);
}
}
-#endif /* DUK_USE_REFERENCE_COUNTING */
-#endif /* DUK_USE_ASSERTIONS */
+#endif /* DUK_USE_LITCACHE_SIZE */
+#endif /* DUK_USE_ASSERTIONS */
/*
* Stats dump.
@@ -48824,48 +53204,72 @@ DUK_LOCAL void duk__check_assert_refcounts(duk_heap *heap) {
#if defined(DUK_USE_DEBUG)
DUK_LOCAL void duk__dump_stats(duk_heap *heap) {
DUK_D(DUK_DPRINT("stats executor: opcodes=%ld, interrupt=%ld, throw=%ld",
- (long) heap->stats_exec_opcodes, (long) heap->stats_exec_interrupt,
+ (long) heap->stats_exec_opcodes,
+ (long) heap->stats_exec_interrupt,
(long) heap->stats_exec_throw));
DUK_D(DUK_DPRINT("stats call: all=%ld, tailcall=%ld, ecmatoecma=%ld",
- (long) heap->stats_call_all, (long) heap->stats_call_tailcall,
+ (long) heap->stats_call_all,
+ (long) heap->stats_call_tailcall,
(long) heap->stats_call_ecmatoecma));
DUK_D(DUK_DPRINT("stats safecall: all=%ld, nothrow=%ld, throw=%ld",
- (long) heap->stats_safecall_all, (long) heap->stats_safecall_nothrow,
+ (long) heap->stats_safecall_all,
+ (long) heap->stats_safecall_nothrow,
(long) heap->stats_safecall_throw));
DUK_D(DUK_DPRINT("stats mark-and-sweep: try_count=%ld, skip_count=%ld, emergency_count=%ld",
- (long) heap->stats_ms_try_count, (long) heap->stats_ms_skip_count,
+ (long) heap->stats_ms_try_count,
+ (long) heap->stats_ms_skip_count,
(long) heap->stats_ms_emergency_count));
- DUK_D(DUK_DPRINT("stats stringtable: intern_hit=%ld, intern_miss=%ld, resize_check=%ld, resize_grow=%ld, resize_shrink=%ld",
- (long) heap->stats_strtab_intern_hit, (long) heap->stats_strtab_intern_miss,
- (long) heap->stats_strtab_resize_check, (long) heap->stats_strtab_resize_grow,
- (long) heap->stats_strtab_resize_shrink));
+ DUK_D(DUK_DPRINT("stats stringtable: intern_hit=%ld, intern_miss=%ld, "
+ "resize_check=%ld, resize_grow=%ld, resize_shrink=%ld, "
+ "litcache_hit=%ld, litcache_miss=%ld, litcache_pin=%ld",
+ (long) heap->stats_strtab_intern_hit,
+ (long) heap->stats_strtab_intern_miss,
+ (long) heap->stats_strtab_resize_check,
+ (long) heap->stats_strtab_resize_grow,
+ (long) heap->stats_strtab_resize_shrink,
+ (long) heap->stats_strtab_litcache_hit,
+ (long) heap->stats_strtab_litcache_miss,
+ (long) heap->stats_strtab_litcache_pin));
DUK_D(DUK_DPRINT("stats object: realloc_props=%ld, abandon_array=%ld",
- (long) heap->stats_object_realloc_props, (long) heap->stats_object_abandon_array));
+ (long) heap->stats_object_realloc_props,
+ (long) heap->stats_object_abandon_array));
DUK_D(DUK_DPRINT("stats getownpropdesc: count=%ld, hit=%ld, miss=%ld",
- (long) heap->stats_getownpropdesc_count, (long) heap->stats_getownpropdesc_hit,
+ (long) heap->stats_getownpropdesc_count,
+ (long) heap->stats_getownpropdesc_hit,
(long) heap->stats_getownpropdesc_miss));
DUK_D(DUK_DPRINT("stats getpropdesc: count=%ld, hit=%ld, miss=%ld",
- (long) heap->stats_getpropdesc_count, (long) heap->stats_getpropdesc_hit,
+ (long) heap->stats_getpropdesc_count,
+ (long) heap->stats_getpropdesc_hit,
(long) heap->stats_getpropdesc_miss));
DUK_D(DUK_DPRINT("stats getprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, "
"bufferidx=%ld, bufferlen=%ld, stringidx=%ld, stringlen=%ld, "
"proxy=%ld, arguments=%ld",
- (long) heap->stats_getprop_all, (long) heap->stats_getprop_arrayidx,
- (long) heap->stats_getprop_bufobjidx, (long) heap->stats_getprop_bufferidx,
- (long) heap->stats_getprop_bufferlen, (long) heap->stats_getprop_stringidx,
- (long) heap->stats_getprop_stringlen, (long) heap->stats_getprop_proxy,
+ (long) heap->stats_getprop_all,
+ (long) heap->stats_getprop_arrayidx,
+ (long) heap->stats_getprop_bufobjidx,
+ (long) heap->stats_getprop_bufferidx,
+ (long) heap->stats_getprop_bufferlen,
+ (long) heap->stats_getprop_stringidx,
+ (long) heap->stats_getprop_stringlen,
+ (long) heap->stats_getprop_proxy,
(long) heap->stats_getprop_arguments));
DUK_D(DUK_DPRINT("stats putprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, "
"bufferidx=%ld, proxy=%ld",
- (long) heap->stats_putprop_all, (long) heap->stats_putprop_arrayidx,
- (long) heap->stats_putprop_bufobjidx, (long) heap->stats_putprop_bufferidx,
+ (long) heap->stats_putprop_all,
+ (long) heap->stats_putprop_arrayidx,
+ (long) heap->stats_putprop_bufobjidx,
+ (long) heap->stats_putprop_bufferidx,
(long) heap->stats_putprop_proxy));
- DUK_D(DUK_DPRINT("stats getvar: all=%ld",
- (long) heap->stats_getvar_all));
- DUK_D(DUK_DPRINT("stats putvar: all=%ld",
- (long) heap->stats_putvar_all));
+ DUK_D(DUK_DPRINT("stats getvar: all=%ld", (long) heap->stats_getvar_all));
+ DUK_D(DUK_DPRINT("stats putvar: all=%ld", (long) heap->stats_putvar_all));
+ DUK_D(DUK_DPRINT("stats envrec: delayedcreate=%ld, create=%ld, newenv=%ld, oldenv=%ld, pushclosure=%ld",
+ (long) heap->stats_envrec_delayedcreate,
+ (long) heap->stats_envrec_create,
+ (long) heap->stats_envrec_newenv,
+ (long) heap->stats_envrec_oldenv,
+ (long) heap->stats_envrec_pushclosure));
}
-#endif /* DUK_USE_DEBUG */
+#endif /* DUK_USE_DEBUG */
/*
* Main mark-and-sweep function.
@@ -48881,6 +53285,7 @@ DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags
#if defined(DUK_USE_VOLUNTARY_GC)
duk_size_t tmp;
#endif
+ duk_bool_t entry_creating_error;
DUK_STATS_INC(heap, stats_ms_try_count);
#if defined(DUK_USE_DEBUG)
@@ -48903,7 +53308,7 @@ DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags
DUK_STATS_INC(heap, stats_ms_skip_count);
return;
}
- DUK_ASSERT(heap->ms_running == 0); /* ms_prevent_count is bumped when ms_running is set */
+ DUK_ASSERT(heap->ms_running == 0); /* ms_prevent_count is bumped when ms_running is set */
/* Heap_thread is used during mark-and-sweep for refcount finalization
* (it's also used for finalizer execution once mark-and-sweep is
@@ -48914,7 +53319,8 @@ DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags
DUK_ASSERT(heap->heap_thread->valstack != NULL);
DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) starting, requested flags: 0x%08lx, effective flags: 0x%08lx",
- (unsigned long) flags, (unsigned long) (flags | heap->ms_base_flags)));
+ (unsigned long) flags,
+ (unsigned long) (flags | heap->ms_base_flags)));
flags |= heap->ms_base_flags;
#if defined(DUK_USE_FINALIZER_SUPPORT)
@@ -48934,13 +53340,14 @@ DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags
DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
DUK_ASSERT(heap->ms_recursion_depth == 0);
duk__assert_heaphdr_flags(heap);
+ duk__assert_validity(heap);
#if defined(DUK_USE_REFERENCE_COUNTING)
/* Note: heap->refzero_free_running may be true; a refcount
* finalizer may trigger a mark-and-sweep.
*/
duk__assert_valid_refcounts(heap);
-#endif /* DUK_USE_REFERENCE_COUNTING */
-#endif /* DUK_USE_ASSERTIONS */
+#endif /* DUK_USE_REFERENCE_COUNTING */
+#endif /* DUK_USE_ASSERTIONS */
/*
* Begin
@@ -48950,6 +53357,8 @@ DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags
DUK_ASSERT(heap->ms_running == 0);
heap->ms_prevent_count = 1;
heap->ms_running = 1;
+ entry_creating_error = heap->creating_error;
+ heap->creating_error = 0;
/*
* Free activation/catcher freelists on every mark-and-sweep for now.
@@ -48979,17 +53388,20 @@ DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags
#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
duk__clear_assert_refcounts(heap);
#endif
- duk__mark_roots_heap(heap); /* Mark main reachability roots. */
+#if defined(DUK_USE_LITCACHE_SIZE)
+ duk__wipe_litcache(heap);
+#endif
+ duk__mark_roots_heap(heap); /* Mark main reachability roots. */
#if defined(DUK_USE_REFERENCE_COUNTING)
- DUK_ASSERT(heap->refzero_list == NULL); /* Always handled to completion inline in DECREF. */
+ DUK_ASSERT(heap->refzero_list == NULL); /* Always handled to completion inline in DECREF. */
#endif
- duk__mark_temproots_by_heap_scan(heap); /* Temproots. */
+ duk__mark_temproots_by_heap_scan(heap); /* Temproots. */
#if defined(DUK_USE_FINALIZER_SUPPORT)
- duk__mark_finalizable(heap); /* Mark finalizable as reachability roots. */
- duk__mark_finalize_list(heap); /* Mark finalizer work list as reachability roots. */
+ duk__mark_finalizable(heap); /* Mark finalizable as reachability roots. */
+ duk__mark_finalize_list(heap); /* Mark finalizer work list as reachability roots. */
#endif
- duk__mark_temproots_by_heap_scan(heap); /* Temproots. */
+ duk__mark_temproots_by_heap_scan(heap); /* Temproots. */
/*
* Sweep garbage and remove marking flags, and move objects with
@@ -49016,7 +53428,7 @@ DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags
duk__check_assert_refcounts(heap);
#endif
#if defined(DUK_USE_REFERENCE_COUNTING)
- DUK_ASSERT(heap->refzero_list == NULL); /* Always handled to completion inline in DECREF. */
+ DUK_ASSERT(heap->refzero_list == NULL); /* Always handled to completion inline in DECREF. */
#endif
#if defined(DUK_USE_FINALIZER_SUPPORT)
duk__clear_finalize_list_flags(heap);
@@ -49037,11 +53449,19 @@ DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags
*
* The object insertions go to the front of the list, so they do not
* cause an infinite loop (they are not compacted).
+ *
+ * At present compaction is not allowed when mark-and-sweep runs
+ * during error handling because it involves a duk_safe_call()
+ * interfering with error state.
*/
- if ((flags & DUK_MS_FLAG_EMERGENCY) &&
- !(flags & DUK_MS_FLAG_NO_OBJECT_COMPACTION)) {
- duk__compact_objects(heap);
+ if ((flags & DUK_MS_FLAG_EMERGENCY) && !(flags & DUK_MS_FLAG_NO_OBJECT_COMPACTION)) {
+ if (heap->lj.type != DUK_LJ_TYPE_UNKNOWN) {
+ DUK_D(DUK_DPRINT("lj.type (%ld) not DUK_LJ_TYPE_UNKNOWN, skip object compaction", (long) heap->lj.type));
+ } else {
+ DUK_D(DUK_DPRINT("object compaction"));
+ duk__compact_objects(heap);
+ }
}
/*
@@ -49065,9 +53485,10 @@ DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags
*/
DUK_ASSERT(heap->ms_prevent_count == 1);
- heap->ms_prevent_count = 0;
DUK_ASSERT(heap->ms_running == 1);
+ heap->ms_prevent_count = 0;
heap->ms_running = 0;
+ heap->creating_error = entry_creating_error; /* for nested error handling, see GH-2278 */
/*
* Assertions after
@@ -49078,13 +53499,17 @@ DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags
DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
DUK_ASSERT(heap->ms_recursion_depth == 0);
duk__assert_heaphdr_flags(heap);
+ duk__assert_validity(heap);
#if defined(DUK_USE_REFERENCE_COUNTING)
/* Note: heap->refzero_free_running may be true; a refcount
* finalizer may trigger a mark-and-sweep.
*/
duk__assert_valid_refcounts(heap);
-#endif /* DUK_USE_REFERENCE_COUNTING */
-#endif /* DUK_USE_ASSERTIONS */
+#endif /* DUK_USE_REFERENCE_COUNTING */
+#if defined(DUK_USE_LITCACHE_SIZE)
+ duk__assert_litcache_nulls(heap);
+#endif /* DUK_USE_LITCACHE_SIZE */
+#endif /* DUK_USE_ASSERTIONS */
/*
* Reset trigger counter
@@ -49092,14 +53517,15 @@ DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags
#if defined(DUK_USE_VOLUNTARY_GC)
tmp = (count_keep_obj + count_keep_str) / 256;
- heap->ms_trigger_counter = (duk_int_t) (
- (tmp * DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT) +
- DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD);
+ heap->ms_trigger_counter = (duk_int_t) ((tmp * DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT) + DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD);
DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, trigger reset to %ld",
- (long) count_keep_obj, (long) count_keep_str, (long) heap->ms_trigger_counter));
+ (long) count_keep_obj,
+ (long) count_keep_str,
+ (long) heap->ms_trigger_counter));
#else
DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, no voluntary trigger",
- (long) count_keep_obj, (long) count_keep_str));
+ (long) count_keep_obj,
+ (long) count_keep_str));
#endif
/*
@@ -49142,7 +53568,7 @@ DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags
* is inside the target.
*/
duk_heap_process_finalize_list(heap);
-#endif /* DUK_USE_FINALIZER_SUPPORT */
+#endif /* DUK_USE_FINALIZER_SUPPORT */
}
/*
* Memory allocation handling.
@@ -49151,84 +53577,31 @@ DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags
/* #include duk_internal.h -> already included */
/*
- * Voluntary GC check
+ * Allocate memory with garbage collection.
*/
-#if defined(DUK_USE_VOLUNTARY_GC)
-DUK_LOCAL DUK_INLINE void duk__check_voluntary_gc(duk_heap *heap) {
- if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
-#if defined(DUK_USE_DEBUG)
- if (heap->ms_prevent_count == 0) {
- DUK_D(DUK_DPRINT("triggering voluntary mark-and-sweep"));
- } else {
- DUK_DD(DUK_DDPRINT("gc blocked -> skip voluntary mark-and-sweep now"));
- }
-#endif
-
- /* Prevention checks in the call target handle cases where
- * voluntary GC is not allowed. The voluntary GC trigger
- * counter is only rewritten if mark-and-sweep actually runs.
- */
- duk_heap_mark_and_sweep(heap, DUK_MS_FLAG_VOLUNTARY /*flags*/);
- }
-}
-#define DUK__VOLUNTARY_PERIODIC_GC(heap) do { duk__check_voluntary_gc((heap)); } while (0)
-#else
-#define DUK__VOLUNTARY_PERIODIC_GC(heap) /* no voluntary gc */
-#endif /* DUK_USE_VOLUNTARY_GC */
-
-/*
- * Allocate memory with garbage collection
- */
-
-DUK_INTERNAL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
+/* Slow path: voluntary GC triggered, first alloc attempt failed, or zero size. */
+DUK_LOCAL DUK_NOINLINE_PERF DUK_COLD void *duk__heap_mem_alloc_slowpath(duk_heap *heap, duk_size_t size) {
void *res;
duk_small_int_t i;
DUK_ASSERT(heap != NULL);
+ DUK_ASSERT(heap->alloc_func != NULL);
DUK_ASSERT_DISABLE(size >= 0);
- /*
- * Voluntary periodic GC (if enabled)
- */
-
- DUK__VOLUNTARY_PERIODIC_GC(heap);
-
- /*
- * First attempt
- */
-
-#if defined(DUK_USE_GC_TORTURE)
- /* Simulate alloc failure on every alloc, except when mark-and-sweep
- * is running.
- */
- if (heap->ms_prevent_count == 0) {
- DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first alloc attempt fails"));
- res = NULL;
- DUK_UNREF(res);
- goto skip_attempt;
- }
-#endif
- res = heap->alloc_func(heap->heap_udata, size);
- if (DUK_LIKELY(res || size == 0)) {
- /* For zero size allocations NULL is allowed. */
- return res;
+ if (size == 0) {
+ DUK_D(DUK_DPRINT("zero size alloc in slow path, return NULL"));
+ return NULL;
}
-#if defined(DUK_USE_GC_TORTURE)
- skip_attempt:
-#endif
- DUK_D(DUK_DPRINT("first alloc attempt failed, attempt to gc and retry"));
+ DUK_D(DUK_DPRINT("first alloc attempt failed or voluntary GC limit reached, attempt to gc and retry"));
#if 0
/*
- * Avoid a GC if GC is already running. This can happen at a late
- * stage in a GC when we try to e.g. resize the stringtable
- * or compact objects.
- *
- * NOTE: explicit handling isn't actually be needed: if the GC is
- * not allowed, duk_heap_mark_and_sweep() will reject it for every
- * attempt in the loop below, resulting in a NULL same as here.
+ * If GC is already running there is no point in attempting a GC
+ * because it will be skipped. This could be checked for explicitly,
+ * but it isn't actually needed: the loop below will eventually
+ * fail resulting in a NULL.
*/
if (heap->ms_prevent_count != 0) {
@@ -49253,10 +53626,12 @@ DUK_INTERNAL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
duk_heap_mark_and_sweep(heap, flags);
+ DUK_ASSERT(size > 0);
res = heap->alloc_func(heap->heap_udata, size);
- if (res) {
+ if (res != NULL) {
DUK_D(DUK_DPRINT("duk_heap_mem_alloc() succeeded after gc (pass %ld), alloc size %ld",
- (long) (i + 1), (long) size));
+ (long) (i + 1),
+ (long) size));
return res;
}
}
@@ -49265,85 +53640,117 @@ DUK_INTERNAL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
return NULL;
}
-DUK_INTERNAL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size) {
+DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
void *res;
DUK_ASSERT(heap != NULL);
+ DUK_ASSERT(heap->alloc_func != NULL);
+ DUK_ASSERT_DISABLE(size >= 0);
+
+#if defined(DUK_USE_VOLUNTARY_GC)
+ /* Voluntary periodic GC (if enabled). */
+ if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
+ goto slowpath;
+ }
+#endif
+
+#if defined(DUK_USE_GC_TORTURE)
+ /* Simulate alloc failure on every alloc, except when mark-and-sweep
+ * is running.
+ */
+ if (heap->ms_prevent_count == 0) {
+ DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first alloc attempt fails"));
+ res = NULL;
+ DUK_UNREF(res);
+ goto slowpath;
+ }
+#endif
+
+ /* Zero-size allocation should happen very rarely (if at all), so
+ * don't check zero size on NULL; handle it in the slow path
+ * instead. This reduces size of inlined code.
+ */
+ res = heap->alloc_func(heap->heap_udata, size);
+ if (DUK_LIKELY(res != NULL)) {
+ return res;
+ }
+
+slowpath:
+
+ if (size == 0) {
+ DUK_D(DUK_DPRINT("first alloc attempt returned NULL for zero size alloc, use slow path to deal with it"));
+ } else {
+ DUK_D(DUK_DPRINT("first alloc attempt failed, attempt to gc and retry"));
+ }
+ return duk__heap_mem_alloc_slowpath(heap, size);
+}
+
+DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size) {
+ void *res;
+
+ DUK_ASSERT(heap != NULL);
+ DUK_ASSERT(heap->alloc_func != NULL);
DUK_ASSERT_DISABLE(size >= 0);
res = DUK_ALLOC(heap, size);
if (DUK_LIKELY(res != NULL)) {
- /* assume memset with zero size is OK */
- DUK_MEMZERO(res, size);
+ duk_memzero(res, size);
}
return res;
}
-DUK_INTERNAL void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size) {
+DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size) {
void *res;
DUK_ASSERT(thr != NULL);
+ DUK_ASSERT(thr->heap != NULL);
+ DUK_ASSERT(thr->heap->alloc_func != NULL);
+
res = duk_heap_mem_alloc(thr->heap, size);
- if (DUK_LIKELY(res != NULL || size == 0)) {
+ if (DUK_LIKELY(res != NULL)) {
+ return res;
+ } else if (size == 0) {
+ DUK_ASSERT(res == NULL);
return res;
}
DUK_ERROR_ALLOC_FAILED(thr);
- return NULL;
+ DUK_WO_NORETURN(return NULL;);
}
-DUK_INTERNAL void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size) {
+DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size) {
void *res;
DUK_ASSERT(thr != NULL);
- res = duk_heap_mem_alloc_zeroed(thr->heap, size);
- if (DUK_LIKELY(res != NULL || size == 0)) {
+ DUK_ASSERT(thr->heap != NULL);
+ DUK_ASSERT(thr->heap->alloc_func != NULL);
+
+ res = duk_heap_mem_alloc(thr->heap, size);
+ if (DUK_LIKELY(res != NULL)) {
+ duk_memzero(res, size);
+ return res;
+ } else if (size == 0) {
+ DUK_ASSERT(res == NULL);
return res;
}
DUK_ERROR_ALLOC_FAILED(thr);
- return NULL;
+ DUK_WO_NORETURN(return NULL;);
}
/*
- * Reallocate memory with garbage collection
+ * Reallocate memory with garbage collection.
*/
-DUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
+/* Slow path: voluntary GC triggered, first realloc attempt failed, or zero size. */
+DUK_LOCAL DUK_NOINLINE_PERF DUK_COLD void *duk__heap_mem_realloc_slowpath(duk_heap *heap, void *ptr, duk_size_t newsize) {
void *res;
duk_small_int_t i;
DUK_ASSERT(heap != NULL);
+ DUK_ASSERT(heap->realloc_func != NULL);
/* ptr may be NULL */
DUK_ASSERT_DISABLE(newsize >= 0);
- /*
- * Voluntary periodic GC (if enabled)
- */
-
- DUK__VOLUNTARY_PERIODIC_GC(heap);
-
- /*
- * First attempt
- */
-
-#if defined(DUK_USE_GC_TORTURE)
- /* Simulate alloc failure on every realloc, except when mark-and-sweep
- * is running.
- */
- if (heap->ms_prevent_count == 0) {
- DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first realloc attempt fails"));
- res = NULL;
- DUK_UNREF(res);
- goto skip_attempt;
- }
-#endif
- res = heap->realloc_func(heap->heap_udata, ptr, newsize);
- if (DUK_LIKELY(res || newsize == 0)) {
- /* For zero size allocations NULL is allowed. */
- return res;
- }
-#if defined(DUK_USE_GC_TORTURE)
- skip_attempt:
-#endif
+ /* Unlike for malloc(), zero size NULL result check happens at the call site. */
DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));
@@ -49375,9 +53782,10 @@ DUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t ne
duk_heap_mark_and_sweep(heap, flags);
res = heap->realloc_func(heap->heap_udata, ptr, newsize);
- if (res || newsize == 0) {
+ if (res != NULL || newsize == 0) {
DUK_D(DUK_DPRINT("duk_heap_mem_realloc() succeeded after gc (pass %ld), alloc size %ld",
- (long) (i + 1), (long) newsize));
+ (long) (i + 1),
+ (long) newsize));
return res;
}
}
@@ -49386,48 +53794,67 @@ DUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t ne
return NULL;
}
-/*
- * Reallocate memory with garbage collection, using a callback to provide
- * the current allocated pointer. This variant is used when a mark-and-sweep
- * (e.g. finalizers) might change the original pointer.
- */
-
-DUK_INTERNAL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
+DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
void *res;
- duk_small_int_t i;
DUK_ASSERT(heap != NULL);
+ DUK_ASSERT(heap->realloc_func != NULL);
+ /* ptr may be NULL */
DUK_ASSERT_DISABLE(newsize >= 0);
- /*
- * Voluntary periodic GC (if enabled)
- */
-
- DUK__VOLUNTARY_PERIODIC_GC(heap);
-
- /*
- * First attempt
- */
+#if defined(DUK_USE_VOLUNTARY_GC)
+ /* Voluntary periodic GC (if enabled). */
+ if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
+ goto gc_retry;
+ }
+#endif
#if defined(DUK_USE_GC_TORTURE)
/* Simulate alloc failure on every realloc, except when mark-and-sweep
* is running.
*/
if (heap->ms_prevent_count == 0) {
- DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first indirect realloc attempt fails"));
+ DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first realloc attempt fails"));
res = NULL;
DUK_UNREF(res);
- goto skip_attempt;
+ goto gc_retry;
}
#endif
- res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
- if (DUK_LIKELY(res || newsize == 0)) {
- /* For zero size allocations NULL is allowed. */
+
+ res = heap->realloc_func(heap->heap_udata, ptr, newsize);
+ if (DUK_LIKELY(res != NULL) || newsize == 0) {
+ if (res != NULL && newsize == 0) {
+ DUK_DD(DUK_DDPRINT("first realloc attempt returned NULL for zero size realloc, accept and return NULL"));
+ }
return res;
+ } else {
+ goto gc_retry;
}
-#if defined(DUK_USE_GC_TORTURE)
- skip_attempt:
-#endif
+ /* Never here. */
+
+gc_retry:
+ return duk__heap_mem_realloc_slowpath(heap, ptr, newsize);
+}
+
+/*
+ * Reallocate memory with garbage collection, using a callback to provide
+ * the current allocated pointer. This variant is used when a mark-and-sweep
+ * (e.g. finalizers) might change the original pointer.
+ */
+
+/* Slow path: voluntary GC triggered, first realloc attempt failed, or zero size. */
+DUK_LOCAL DUK_NOINLINE_PERF DUK_COLD void *duk__heap_mem_realloc_indirect_slowpath(duk_heap *heap,
+ duk_mem_getptr cb,
+ void *ud,
+ duk_size_t newsize) {
+ void *res;
+ duk_small_int_t i;
+
+ DUK_ASSERT(heap != NULL);
+ DUK_ASSERT(heap->realloc_func != NULL);
+ DUK_ASSERT_DISABLE(newsize >= 0);
+
+ /* Unlike for malloc(), zero size NULL result check happens at the call site. */
DUK_D(DUK_DPRINT("first indirect realloc attempt failed, attempt to gc and retry"));
@@ -49469,7 +53896,8 @@ DUK_INTERNAL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr
ptr_post = cb(heap, ud);
if (ptr_pre != ptr_post) {
DUK_DD(DUK_DDPRINT("realloc base pointer changed by mark-and-sweep: %p -> %p",
- (void *) ptr_pre, (void *) ptr_post));
+ (void *) ptr_pre,
+ (void *) ptr_post));
}
#endif
@@ -49478,9 +53906,10 @@ DUK_INTERNAL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr
*/
res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
- if (res || newsize == 0) {
+ if (res != NULL || newsize == 0) {
DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() succeeded after gc (pass %ld), alloc size %ld",
- (long) (i + 1), (long) newsize));
+ (long) (i + 1),
+ (long) newsize));
return res;
}
}
@@ -49489,12 +53918,58 @@ DUK_INTERNAL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr
return NULL;
}
+DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_realloc_indirect(duk_heap *heap,
+ duk_mem_getptr cb,
+ void *ud,
+ duk_size_t newsize) {
+ void *res;
+
+ DUK_ASSERT(heap != NULL);
+ DUK_ASSERT(heap->realloc_func != NULL);
+ DUK_ASSERT_DISABLE(newsize >= 0);
+
+#if defined(DUK_USE_VOLUNTARY_GC)
+ /* Voluntary periodic GC (if enabled). */
+ if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
+ goto gc_retry;
+ }
+#endif
+
+#if defined(DUK_USE_GC_TORTURE)
+ /* Simulate alloc failure on every realloc, except when mark-and-sweep
+ * is running.
+ */
+ if (heap->ms_prevent_count == 0) {
+ DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first indirect realloc attempt fails"));
+ res = NULL;
+ DUK_UNREF(res);
+ goto gc_retry;
+ }
+#endif
+
+ res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
+ if (DUK_LIKELY(res != NULL) || newsize == 0) {
+ if (res != NULL && newsize == 0) {
+ DUK_DD(DUK_DDPRINT(
+ "first indirect realloc attempt returned NULL for zero size realloc, accept and return NULL"));
+ }
+ return res;
+ } else {
+ goto gc_retry;
+ }
+ /* Never here. */
+
+gc_retry:
+ return duk__heap_mem_realloc_indirect_slowpath(heap, cb, ud, newsize);
+}
+
/*
* Free memory
*/
-DUK_INTERNAL void duk_heap_mem_free(duk_heap *heap, void *ptr) {
+DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void duk_heap_mem_free(duk_heap *heap, void *ptr) {
DUK_ASSERT(heap != NULL);
+ DUK_ASSERT(heap->free_func != NULL);
/* ptr may be NULL */
/* Must behave like a no-op with NULL and any pointer returned from
@@ -49507,9 +53982,6 @@ DUK_INTERNAL void duk_heap_mem_free(duk_heap *heap, void *ptr) {
* No need to update voluntary GC counter either.
*/
}
-
-/* automatic undefs */
-#undef DUK__VOLUNTARY_PERIODIC_GC
/*
* Support functions for duk_heap.
*/
@@ -49530,8 +54002,8 @@ DUK_INTERNAL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphd
DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
#endif
DUK_HEAPHDR_SET_NEXT(heap, hdr, root);
- DUK_ASSERT_HEAPHDR_LINKS(heap, hdr);
- DUK_ASSERT_HEAPHDR_LINKS(heap, root);
+ DUK_HEAPHDR_ASSERT_LINKS(heap, hdr);
+ DUK_HEAPHDR_ASSERT_LINKS(heap, root);
heap->heap_allocated = hdr;
}
@@ -49576,7 +54048,7 @@ DUK_INTERNAL void duk_heap_remove_from_heap_allocated(duk_heap *heap, duk_heaphd
;
}
}
-#endif /* DUK_USE_REFERENCE_COUNTING */
+#endif /* DUK_USE_REFERENCE_COUNTING */
#if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_INTERNAL void duk_heap_insert_into_finalize_list(duk_heap *heap, duk_heaphdr *hdr) {
@@ -49591,11 +54063,11 @@ DUK_INTERNAL void duk_heap_insert_into_finalize_list(duk_heap *heap, duk_heaphdr
}
#endif
DUK_HEAPHDR_SET_NEXT(heap, hdr, root);
- DUK_ASSERT_HEAPHDR_LINKS(heap, hdr);
- DUK_ASSERT_HEAPHDR_LINKS(heap, root);
+ DUK_HEAPHDR_ASSERT_LINKS(heap, hdr);
+ DUK_HEAPHDR_ASSERT_LINKS(heap, root);
heap->finalize_list = hdr;
}
-#endif /* DUK_USE_FINALIZER_SUPPORT */
+#endif /* DUK_USE_FINALIZER_SUPPORT */
#if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_INTERNAL void duk_heap_remove_from_finalize_list(duk_heap *heap, duk_heaphdr *hdr) {
@@ -49629,7 +54101,7 @@ DUK_INTERNAL void duk_heap_remove_from_finalize_list(duk_heap *heap, duk_heaphdr
} else {
DUK_ASSERT(hdr != heap->finalize_list);
for (;;) {
- DUK_ASSERT(curr != NULL); /* Caller responsibility. */
+ DUK_ASSERT(curr != NULL); /* Caller responsibility. */
next = DUK_HEAPHDR_GET_NEXT(heap, curr);
if (next == hdr) {
@@ -49641,7 +54113,7 @@ DUK_INTERNAL void duk_heap_remove_from_finalize_list(duk_heap *heap, duk_heaphdr
}
#endif
}
-#endif /* DUK_USE_FINALIZER_SUPPORT */
+#endif /* DUK_USE_FINALIZER_SUPPORT */
#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL duk_bool_t duk_heap_in_heap_allocated(duk_heap *heap, duk_heaphdr *ptr) {
@@ -49655,7 +54127,7 @@ DUK_INTERNAL duk_bool_t duk_heap_in_heap_allocated(duk_heap *heap, duk_heaphdr *
}
return 0;
}
-#endif /* DUK_USE_ASSERTIONS */
+#endif /* DUK_USE_ASSERTIONS */
#if defined(DUK_USE_INTERRUPT_COUNTER)
DUK_INTERNAL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr) {
@@ -49688,9 +54160,15 @@ DUK_INTERNAL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr) {
DUK_DD(DUK_DDPRINT("switch thread, new thread is NULL, no interrupt counter changes"));
}
- heap->curr_thread = new_thr; /* may be NULL */
+ heap->curr_thread = new_thr; /* may be NULL */
}
-#endif /* DUK_USE_INTERRUPT_COUNTER */
+#endif /* DUK_USE_INTERRUPT_COUNTER */
+
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL void duk_heap_assert_valid(duk_heap *heap) {
+ DUK_ASSERT(heap != NULL);
+}
+#endif
/*
* Reference counting implementation.
*
@@ -49817,7 +54295,7 @@ DUK_INTERNAL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject
duk_tval *tv, *tv_end;
duk_hobject **funcs, **funcs_end;
- DUK_ASSERT_HCOMPFUNC_VALID(f);
+ DUK_HCOMPFUNC_ASSERT_VALID(f);
if (DUK_LIKELY(DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL)) {
tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
@@ -49847,40 +54325,40 @@ DUK_INTERNAL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject
DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(heap, f));
} else if (DUK_HOBJECT_IS_DECENV(h)) {
duk_hdecenv *e = (duk_hdecenv *) h;
- DUK_ASSERT_HDECENV_VALID(e);
+ DUK_HDECENV_ASSERT_VALID(e);
DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, e->thread);
DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, e->varmap);
} else if (DUK_HOBJECT_IS_OBJENV(h)) {
duk_hobjenv *e = (duk_hobjenv *) h;
- DUK_ASSERT_HOBJENV_VALID(e);
- DUK_ASSERT(e->target != NULL); /* Required for object environments. */
+ DUK_HOBJENV_ASSERT_VALID(e);
+ DUK_ASSERT(e->target != NULL); /* Required for object environments. */
DUK_HOBJECT_DECREF_NORZ(thr, e->target);
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
duk_hbufobj *b = (duk_hbufobj *) h;
- DUK_ASSERT_HBUFOBJ_VALID(b);
+ DUK_HBUFOBJ_ASSERT_VALID(b);
DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr, (duk_hbuffer *) b->buf);
DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) b->buf_prop);
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
- duk_hboundfunc *f = (duk_hboundfunc *) h;
- DUK_ASSERT_HBOUNDFUNC_VALID(f);
+ duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
+ DUK_HBOUNDFUNC_ASSERT_VALID(f);
DUK_TVAL_DECREF_NORZ(thr, &f->target);
DUK_TVAL_DECREF_NORZ(thr, &f->this_binding);
duk__decref_tvals_norz(thr, f->args, f->nargs);
#if defined(DUK_USE_ES6_PROXY)
} else if (DUK_HOBJECT_IS_PROXY(h)) {
duk_hproxy *p = (duk_hproxy *) h;
- DUK_ASSERT_HPROXY_VALID(p);
+ DUK_HPROXY_ASSERT_VALID(p);
DUK_HOBJECT_DECREF_NORZ(thr, p->target);
DUK_HOBJECT_DECREF_NORZ(thr, p->handler);
-#endif /* DUK_USE_ES6_PROXY */
+#endif /* DUK_USE_ES6_PROXY */
} else if (DUK_HOBJECT_IS_THREAD(h)) {
duk_hthread *t = (duk_hthread *) h;
duk_activation *act;
duk_tval *tv;
- DUK_ASSERT_HTHREAD_VALID(t);
+ DUK_HTHREAD_ASSERT_VALID(t);
tv = t->valstack;
while (tv < t->valstack_top) {
@@ -49895,13 +54373,12 @@ DUK_INTERNAL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject
#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->prev_caller);
#endif
-#if 0 /* nothing now */
+#if 0 /* nothing now */
for (cat = act->cat; cat != NULL; cat = cat->parent) {
}
#endif
}
-
for (i = 0; i < DUK_NUM_BUILTINS; i++) {
DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) t->builtins[i]);
}
@@ -49986,7 +54463,7 @@ DUK_LOCAL void duk__refcount_free_pending(duk_heap *heap) {
curr = heap->refzero_list;
DUK_ASSERT(curr != NULL);
- DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, curr) == NULL); /* We're called on initial insert only. */
+ DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, curr) == NULL); /* We're called on initial insert only. */
/* curr->next is GARBAGE. */
do {
@@ -49999,7 +54476,7 @@ DUK_LOCAL void duk__refcount_free_pending(duk_heap *heap) {
#endif
DUK_ASSERT(curr != NULL);
- DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT); /* currently, always the case */
+ DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT); /* currently, always the case */
/* FINALIZED may be set; don't care about flags here. */
/* Refcount finalize 'curr'. Refzero_list must be non-NULL
@@ -50009,11 +54486,10 @@ DUK_LOCAL void duk__refcount_free_pending(duk_heap *heap) {
duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) curr);
prev = DUK_HEAPHDR_GET_PREV(heap, curr);
- DUK_ASSERT((prev == NULL && heap->refzero_list == curr) || \
- (prev != NULL && heap->refzero_list != curr));
+ DUK_ASSERT((prev == NULL && heap->refzero_list == curr) || (prev != NULL && heap->refzero_list != curr));
/* prev->next is intentionally not updated and is garbage. */
- duk_free_hobject(heap, (duk_hobject *) curr); /* Invalidates 'curr'. */
+ duk_free_hobject(heap, (duk_hobject *) curr); /* Invalidates 'curr'. */
curr = prev;
} while (curr != NULL);
@@ -50089,7 +54565,7 @@ DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hobject(duk_heap *heap, duk_hobj
return;
}
}
-#endif /* DUK_USE_FINALIZER_SUPPORT */
+#endif /* DUK_USE_FINALIZER_SUPPORT */
/* No need to finalize, free object via refzero_list. */
@@ -50133,7 +54609,7 @@ DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hobject(duk_heap *heap, duk_hobj
DUK_INTERNAL DUK_ALWAYS_INLINE void duk_refzero_check_fast(duk_hthread *thr) {
DUK_ASSERT(thr != NULL);
DUK_ASSERT(thr->heap != NULL);
- DUK_ASSERT(thr->heap->refzero_list == NULL); /* Processed to completion inline. */
+ DUK_ASSERT(thr->heap->refzero_list == NULL); /* Processed to completion inline. */
if (DUK_UNLIKELY(thr->heap->finalize_list != NULL)) {
duk_heap_process_finalize_list(thr->heap);
@@ -50143,13 +54619,13 @@ DUK_INTERNAL DUK_ALWAYS_INLINE void duk_refzero_check_fast(duk_hthread *thr) {
DUK_INTERNAL void duk_refzero_check_slow(duk_hthread *thr) {
DUK_ASSERT(thr != NULL);
DUK_ASSERT(thr->heap != NULL);
- DUK_ASSERT(thr->heap->refzero_list == NULL); /* Processed to completion inline. */
+ DUK_ASSERT(thr->heap->refzero_list == NULL); /* Processed to completion inline. */
if (DUK_UNLIKELY(thr->heap->finalize_list != NULL)) {
duk_heap_process_finalize_list(thr->heap);
}
}
-#endif /* DUK_USE_FINALIZER_SUPPORT */
+#endif /* DUK_USE_FINALIZER_SUPPORT */
/*
* Refzero processing for duk_hstring.
@@ -50209,16 +54685,20 @@ DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hbuffer(duk_heap *heap, duk_hbuf
* The suppress condition is important to performance.
*/
-#define DUK__RZ_SUPPRESS_ASSERT1() do { \
+#define DUK__RZ_SUPPRESS_ASSERT1() \
+ do { \
DUK_ASSERT(thr != NULL); \
DUK_ASSERT(thr->heap != NULL); \
/* When mark-and-sweep runs, heap_thread must exist. */ \
DUK_ASSERT(thr->heap->ms_running == 0 || thr->heap->heap_thread != NULL); \
- /* When mark-and-sweep runs, the 'thr' argument always matches heap_thread. \
- * This could be used to e.g. suppress check against 'thr' directly (and \
- * knowing it would be heap_thread); not really used now. \
+ /* In normal operation finalizers are executed with ms_running == 0 \
+ * so we should never see ms_running == 1 and thr != heap_thread. \
+ * In heap destruction finalizers are executed with ms_running != 0 \
+ * to e.g. prevent refzero; a special value ms_running == 2 is used \
+ * in that case so it can be distinguished from the normal runtime \
+ * case, and allows a stronger assertion here (GH-2030). \
*/ \
- DUK_ASSERT(thr->heap->ms_running == 0 || thr == thr->heap->heap_thread); \
+ DUK_ASSERT(!(thr->heap->ms_running == 1 && thr != thr->heap->heap_thread)); \
/* We may be called when the heap is initializing and we process \
* refzeros normally, but mark-and-sweep and finalizers are prevented \
* if that's the case. \
@@ -50228,32 +54708,41 @@ DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hbuffer(duk_heap *heap, duk_hbuf
} while (0)
#if defined(DUK_USE_DEBUGGER_SUPPORT)
-#define DUK__RZ_SUPPRESS_ASSERT2() do { \
+#define DUK__RZ_SUPPRESS_ASSERT2() \
+ do { \
/* When debugger is paused, ms_running is set. */ \
DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || thr->heap->ms_running != 0); \
} while (0)
-#define DUK__RZ_SUPPRESS_COND() (heap->ms_running != 0)
+#define DUK__RZ_SUPPRESS_COND() (heap->ms_running != 0)
#else
-#define DUK__RZ_SUPPRESS_ASSERT2() do { } while (0)
-#define DUK__RZ_SUPPRESS_COND() (heap->ms_running != 0)
-#endif /* DUK_USE_DEBUGGER_SUPPORT */
+#define DUK__RZ_SUPPRESS_ASSERT2() \
+ do { \
+ } while (0)
+#define DUK__RZ_SUPPRESS_COND() (heap->ms_running != 0)
+#endif /* DUK_USE_DEBUGGER_SUPPORT */
-#define DUK__RZ_SUPPRESS_CHECK() do { \
+#define DUK__RZ_SUPPRESS_CHECK() \
+ do { \
DUK__RZ_SUPPRESS_ASSERT1(); \
DUK__RZ_SUPPRESS_ASSERT2(); \
if (DUK_UNLIKELY(DUK__RZ_SUPPRESS_COND())) { \
- DUK_DDD(DUK_DDDPRINT("refzero handling suppressed (not even queued) when mark-and-sweep running, object: %p", (void *) h)); \
+ DUK_DDD( \
+ DUK_DDDPRINT("refzero handling suppressed (not even queued) when mark-and-sweep running, object: %p", \
+ (void *) h)); \
return; \
} \
} while (0)
-#define DUK__RZ_STRING() do { \
+#define DUK__RZ_STRING() \
+ do { \
duk__refcount_refzero_hstring(heap, (duk_hstring *) h); \
} while (0)
-#define DUK__RZ_BUFFER() do { \
+#define DUK__RZ_BUFFER() \
+ do { \
duk__refcount_refzero_hbuffer(heap, (duk_hbuffer *) h); \
} while (0)
-#define DUK__RZ_OBJECT() do { \
+#define DUK__RZ_OBJECT() \
+ do { \
duk__refcount_refzero_hobject(heap, (duk_hobject *) h, skip_free_pending); \
} while (0)
@@ -50306,6 +54795,7 @@ DUK_LOCAL DUK__RZ_INLINE void duk__heaphdr_refzero_helper(duk_hthread *thr, duk_
heap = thr->heap;
htype = (duk_small_uint_t) DUK_HEAPHDR_GET_TYPE(h);
+ DUK_DDD(DUK_DDDPRINT("ms_running=%ld, heap_thread=%p", (long) thr->heap->ms_running, thr->heap->heap_thread));
DUK__RZ_SUPPRESS_CHECK();
switch (htype) {
@@ -50373,7 +54863,7 @@ DUK_INTERNAL void duk_tval_incref(duk_tval *tv) {
DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
DUK_ASSERT_DISABLE(h->h_refcount >= 0);
DUK_HEAPHDR_PREINC_REFCOUNT(h);
- DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) != 0); /* No wrapping. */
+ DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) != 0); /* No wrapping. */
}
}
@@ -50416,9 +54906,10 @@ DUK_INTERNAL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv) {
#endif
}
}
-#endif /* !DUK_USE_FAST_REFCOUNT_DEFAULT */
+#endif /* !DUK_USE_FAST_REFCOUNT_DEFAULT */
-#define DUK__DECREF_ASSERTS() do { \
+#define DUK__DECREF_ASSERTS() \
+ do { \
DUK_ASSERT(thr != NULL); \
DUK_ASSERT(thr->heap != NULL); \
DUK_ASSERT(h != NULL); \
@@ -50426,14 +54917,16 @@ DUK_INTERNAL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv) {
DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) >= 1); \
} while (0)
#if defined(DUK_USE_ROM_OBJECTS)
-#define DUK__INCREF_SHARED() do { \
+#define DUK__INCREF_SHARED() \
+ do { \
if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
return; \
} \
DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
- DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0); /* No wrapping. */ \
+ DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0); /* No wrapping. */ \
} while (0)
-#define DUK__DECREF_SHARED() do { \
+#define DUK__DECREF_SHARED() \
+ do { \
if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
return; \
} \
@@ -50442,11 +54935,13 @@ DUK_INTERNAL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv) {
} \
} while (0)
#else
-#define DUK__INCREF_SHARED() do { \
+#define DUK__INCREF_SHARED() \
+ do { \
DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
- DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0); /* No wrapping. */ \
+ DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0); /* No wrapping. */ \
} while (0)
-#define DUK__DECREF_SHARED() do { \
+#define DUK__DECREF_SHARED() \
+ do { \
if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
return; \
} \
@@ -50480,9 +54975,9 @@ DUK_INTERNAL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h) {
DUK__DECREF_SHARED();
duk_heaphdr_refzero_norz(thr, h);
}
-#endif /* !DUK_USE_FAST_REFCOUNT_DEFAULT */
+#endif /* !DUK_USE_FAST_REFCOUNT_DEFAULT */
-#if 0 /* Not needed. */
+#if 0 /* Not needed. */
DUK_INTERNAL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h) {
DUK__DECREF_ASSERTS();
DUK__DECREF_SHARED();
@@ -50515,11 +55010,11 @@ DUK_INTERNAL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h) {
}
#endif
-#else /* DUK_USE_REFERENCE_COUNTING */
+#else /* DUK_USE_REFERENCE_COUNTING */
/* no refcounting */
-#endif /* DUK_USE_REFERENCE_COUNTING */
+#endif /* DUK_USE_REFERENCE_COUNTING */
/* automatic undefs */
#undef DUK__DECREF_ASSERTS
@@ -50553,12 +55048,12 @@ DUK_INTERNAL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h) {
*/
DUK_INTERNAL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h) {
- duk_small_int_t i;
+ duk_uint_t i;
for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
- duk_strcache *c = heap->strcache + i;
+ duk_strcache_entry *c = heap->strcache + i;
if (c->h == h) {
- DUK_DD(DUK_DDPRINT("deleting weak strcache reference to hstring %p from heap %p",
- (void *) h, (void *) heap));
+ DUK_DD(
+ DUK_DDPRINT("deleting weak strcache reference to hstring %p from heap %p", (void *) h, (void *) heap));
c->h = NULL;
/* XXX: the string shouldn't appear twice, but we now loop to the
@@ -50627,9 +55122,9 @@ DUK_LOCAL const duk_uint8_t *duk__scan_backwards(const duk_uint8_t *p, const duk
DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset) {
duk_heap *heap;
- duk_strcache *sce;
+ duk_strcache_entry *sce;
duk_uint_fast32_t byte_offset;
- duk_small_int_t i;
+ duk_uint_t i;
duk_bool_t use_cache;
duk_uint_fast32_t dist_start, dist_end, dist_sce;
duk_uint_fast32_t char_length;
@@ -50668,7 +55163,8 @@ DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *t
*/
DUK_DDD(DUK_DDDPRINT("non-ascii string %p, char_offset=%ld, clen=%ld, blen=%ld",
- (void *) h, (long) char_offset,
+ (void *) h,
+ (long) char_offset,
(long) DUK_HSTRING_GET_CHARLEN(h),
(long) DUK_HSTRING_GET_BYTELEN(h)));
@@ -50680,14 +55176,17 @@ DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *t
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
DUK_DDD(DUK_DDDPRINT("stringcache before char2byte (using cache):"));
for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
- duk_strcache *c = heap->strcache + i;
+ duk_strcache_entry *c = heap->strcache + i;
DUK_DDD(DUK_DDDPRINT(" [%ld] -> h=%p, cidx=%ld, bidx=%ld",
- (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
+ (long) i,
+ (void *) c->h,
+ (long) c->cidx,
+ (long) c->bidx));
}
#endif
for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
- duk_strcache *c = heap->strcache + i;
+ duk_strcache_entry *c = heap->strcache + i;
if (c->h == h) {
sce = c;
@@ -50706,7 +55205,8 @@ DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *t
DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h) >= char_offset);
dist_start = char_offset;
dist_end = char_length - char_offset;
- dist_sce = 0; DUK_UNREF(dist_sce); /* initialize for debug prints, needed if sce==NULL */
+ dist_sce = 0;
+ DUK_UNREF(dist_sce); /* initialize for debug prints, needed if sce==NULL */
p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
p_end = (const duk_uint8_t *) (p_start + DUK_HSTRING_GET_BYTELEN(h));
@@ -50719,14 +55219,15 @@ DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *t
DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
"dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
"scan forwards from sce",
- (long) use_cache, (void *) (sce ? sce->h : NULL),
+ (long) use_cache,
+ (void *) (sce ? sce->h : NULL),
(sce ? (long) sce->cidx : (long) -1),
(sce ? (long) sce->bidx : (long) -1),
- (long) dist_start, (long) dist_end, (long) dist_sce));
+ (long) dist_start,
+ (long) dist_end,
+ (long) dist_sce));
- p_found = duk__scan_forwards(p_start + sce->bidx,
- p_end,
- dist_sce);
+ p_found = duk__scan_forwards(p_start + sce->bidx, p_end, dist_sce);
goto scan_done;
}
} else {
@@ -50735,14 +55236,15 @@ DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *t
DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
"dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
"scan backwards from sce",
- (long) use_cache, (void *) (sce ? sce->h : NULL),
+ (long) use_cache,
+ (void *) (sce ? sce->h : NULL),
(sce ? (long) sce->cidx : (long) -1),
(sce ? (long) sce->bidx : (long) -1),
- (long) dist_start, (long) dist_end, (long) dist_sce));
+ (long) dist_start,
+ (long) dist_end,
+ (long) dist_sce));
- p_found = duk__scan_backwards(p_start + sce->bidx,
- p_start,
- dist_sce);
+ p_found = duk__scan_backwards(p_start + sce->bidx, p_start, dist_sce);
goto scan_done;
}
}
@@ -50754,29 +55256,31 @@ DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *t
DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
"dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
"scan forwards from string start",
- (long) use_cache, (void *) (sce ? sce->h : NULL),
+ (long) use_cache,
+ (void *) (sce ? sce->h : NULL),
(sce ? (long) sce->cidx : (long) -1),
(sce ? (long) sce->bidx : (long) -1),
- (long) dist_start, (long) dist_end, (long) dist_sce));
+ (long) dist_start,
+ (long) dist_end,
+ (long) dist_sce));
- p_found = duk__scan_forwards(p_start,
- p_end,
- dist_start);
+ p_found = duk__scan_forwards(p_start, p_end, dist_start);
} else {
DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
"dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
"scan backwards from string end",
- (long) use_cache, (void *) (sce ? sce->h : NULL),
+ (long) use_cache,
+ (void *) (sce ? sce->h : NULL),
(sce ? (long) sce->cidx : (long) -1),
(sce ? (long) sce->bidx : (long) -1),
- (long) dist_start, (long) dist_end, (long) dist_sce));
+ (long) dist_start,
+ (long) dist_end,
+ (long) dist_sce));
- p_found = duk__scan_backwards(p_end,
- p_start,
- dist_end);
+ p_found = duk__scan_backwards(p_end, p_start, dist_end);
}
- scan_done:
+scan_done:
if (DUK_UNLIKELY(p_found == NULL)) {
/* Scan error: this shouldn't normally happen; it could happen if
@@ -50787,11 +55291,10 @@ DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *t
}
DUK_ASSERT(p_found >= p_start);
- DUK_ASSERT(p_found <= p_end); /* may be equal */
+ DUK_ASSERT(p_found <= p_end); /* may be equal */
byte_offset = (duk_uint32_t) (p_found - p_start);
- DUK_DDD(DUK_DDDPRINT("-> string %p, cidx %ld -> bidx %ld",
- (void *) h, (long) char_offset, (long) byte_offset));
+ DUK_DDD(DUK_DDDPRINT("-> string %p, cidx %ld -> bidx %ld", (void *) h, (long) char_offset, (long) byte_offset));
/*
* Update cache entry (allocating if necessary), and move the
@@ -50801,7 +55304,7 @@ DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *t
if (use_cache) {
/* update entry, allocating if necessary */
if (!sce) {
- sce = heap->strcache + DUK_HEAP_STRCACHE_SIZE - 1; /* take last entry */
+ sce = heap->strcache + DUK_HEAP_STRCACHE_SIZE - 1; /* take last entry */
sce->h = h;
}
DUK_ASSERT(sce != NULL);
@@ -50816,10 +55319,10 @@ DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *t
* C <- sce ==> B
* D D
*/
- duk_strcache tmp;
+ duk_strcache_entry tmp;
tmp = *sce;
- DUK_MEMMOVE((void *) (&heap->strcache[1]),
+ duk_memmove((void *) (&heap->strcache[1]),
(const void *) (&heap->strcache[0]),
(size_t) (((char *) sce) - ((char *) &heap->strcache[0])));
heap->strcache[0] = tmp;
@@ -50829,18 +55332,21 @@ DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *t
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
DUK_DDD(DUK_DDDPRINT("stringcache after char2byte (using cache):"));
for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
- duk_strcache *c = heap->strcache + i;
+ duk_strcache_entry *c = heap->strcache + i;
DUK_DDD(DUK_DDDPRINT(" [%ld] -> h=%p, cidx=%ld, bidx=%ld",
- (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
+ (long) i,
+ (void *) c->h,
+ (long) c->cidx,
+ (long) c->bidx));
}
#endif
}
return byte_offset;
- scan_error:
+scan_error:
DUK_ERROR_INTERNAL(thr);
- return 0;
+ DUK_WO_NORETURN(return 0;);
}
/*
* Heap string table handling, string interning.
@@ -50857,16 +55363,16 @@ DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *t
#endif
#if defined(DUK_USE_STRTAB_PTRCOMP)
-#define DUK__HEAPPTR_ENC16(heap,ptr) DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (ptr))
-#define DUK__HEAPPTR_DEC16(heap,val) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (val))
-#define DUK__GET_STRTABLE(heap) ((heap)->strtable16)
+#define DUK__HEAPPTR_ENC16(heap, ptr) DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (ptr))
+#define DUK__HEAPPTR_DEC16(heap, val) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (val))
+#define DUK__GET_STRTABLE(heap) ((heap)->strtable16)
#else
-#define DUK__HEAPPTR_ENC16(heap,ptr) (ptr)
-#define DUK__HEAPPTR_DEC16(heap,val) (val)
-#define DUK__GET_STRTABLE(heap) ((heap)->strtable)
+#define DUK__HEAPPTR_ENC16(heap, ptr) (ptr)
+#define DUK__HEAPPTR_DEC16(heap, val) (val)
+#define DUK__GET_STRTABLE(heap) ((heap)->strtable)
#endif
-#define DUK__STRTAB_U32_MAX_STRLEN 10 /* 4'294'967'295 */
+#define DUK__STRTAB_U32_MAX_STRLEN 10 /* 4'294'967'295 */
/*
* Debug dump stringtable.
@@ -50885,7 +55391,7 @@ DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap) {
duk_size_t count_chain;
duk_size_t count_chain_min = DUK_SIZE_MAX;
duk_size_t count_chain_max = 0;
- duk_size_t count_len[8]; /* chain lengths from 0 to 7 */
+ duk_size_t count_len[8]; /* chain lengths from 0 to 7 */
if (heap == NULL) {
DUK_D(DUK_DPRINT("string table, heap=NULL"));
@@ -50898,7 +55404,7 @@ DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap) {
return;
}
- DUK_MEMZERO((void *) count_len, sizeof(count_len));
+ duk_memzero((void *) count_len, sizeof(count_len));
for (i = 0; i < heap->st_size; i++) {
h = DUK__HEAPPTR_DEC16(heap, strtable[i]);
count_chain = 0;
@@ -50916,15 +55422,21 @@ DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap) {
DUK_D(DUK_DPRINT("string table, strtab=%p, count=%lu, chain min=%lu max=%lu avg=%lf: "
"counts: %lu %lu %lu %lu %lu %lu %lu %lu ...",
- (void *) heap->strtable, (unsigned long) count_total,
- (unsigned long) count_chain_min, (unsigned long) count_chain_max,
+ (void *) heap->strtable,
+ (unsigned long) count_total,
+ (unsigned long) count_chain_min,
+ (unsigned long) count_chain_max,
(double) count_total / (double) heap->st_size,
- (unsigned long) count_len[0], (unsigned long) count_len[1],
- (unsigned long) count_len[2], (unsigned long) count_len[3],
- (unsigned long) count_len[4], (unsigned long) count_len[5],
- (unsigned long) count_len[6], (unsigned long) count_len[7]));
+ (unsigned long) count_len[0],
+ (unsigned long) count_len[1],
+ (unsigned long) count_len[2],
+ (unsigned long) count_len[3],
+ (unsigned long) count_len[4],
+ (unsigned long) count_len[5],
+ (unsigned long) count_len[6],
+ (unsigned long) count_len[7]));
}
-#endif /* DUK_USE_DEBUG */
+#endif /* DUK_USE_DEBUG */
/*
* Assertion helper to ensure strtable is populated correctly.
@@ -50965,7 +55477,7 @@ DUK_LOCAL void duk__strtable_assert_checks(duk_heap *heap) {
DUK_ASSERT(count == (duk_size_t) heap->st_count);
#endif
}
-#endif /* DUK_USE_ASSERTIONS */
+#endif /* DUK_USE_ASSERTIONS */
/*
* Allocate and initialize a duk_hstring.
@@ -51010,34 +55522,34 @@ DUK_LOCAL duk_hstring *duk__strtable_alloc_hstring(duk_heap *heap,
if (DUK_UNLIKELY(res == NULL)) {
goto alloc_error;
}
- DUK_MEMZERO(res, sizeof(duk_hstring_external));
+ duk_memzero(res, sizeof(duk_hstring_external));
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
#endif
DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, DUK_HSTRING_FLAG_EXTDATA);
- DUK_ASSERT(extdata[blen] == 0); /* Application responsibility. */
+ DUK_ASSERT(extdata[blen] == 0); /* Application responsibility. */
data = extdata;
((duk_hstring_external *) res)->extdata = extdata;
} else
-#endif /* DUK_USE_HSTRING_EXTDATA && DUK_USE_EXTSTR_INTERN_CHECK */
+#endif /* DUK_USE_HSTRING_EXTDATA && DUK_USE_EXTSTR_INTERN_CHECK */
{
duk_uint8_t *data_tmp;
/* NUL terminate for convenient C access */
- DUK_ASSERT(sizeof(duk_hstring) + blen + 1 > blen); /* No wrap, limits ensure. */
+ DUK_ASSERT(sizeof(duk_hstring) + blen + 1 > blen); /* No wrap, limits ensure. */
res = (duk_hstring *) DUK_ALLOC(heap, sizeof(duk_hstring) + blen + 1);
if (DUK_UNLIKELY(res == NULL)) {
goto alloc_error;
}
- DUK_MEMZERO(res, sizeof(duk_hstring));
+ duk_memzero(res, sizeof(duk_hstring));
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
#endif
DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0);
data_tmp = (duk_uint8_t *) (res + 1);
- DUK_MEMCPY(data_tmp, str, blen);
+ duk_memcpy(data_tmp, str, blen);
data_tmp[blen] = (duk_uint8_t) 0;
data = (const duk_uint8_t *) data_tmp;
}
@@ -51084,7 +55596,7 @@ DUK_LOCAL duk_hstring *duk__strtable_alloc_hstring(duk_heap *heap,
#if defined(DUK_USE_HSTRING_LAZY_CLEN)
/* Charlen initialized to 0, updated on-the-fly. */
#else
- duk_hstring_init_charlen(res); /* Also sets ASCII flag. */
+ duk_hstring_init_charlen(res); /* Also sets ASCII flag. */
#endif
}
@@ -51097,7 +55609,7 @@ DUK_LOCAL duk_hstring *duk__strtable_alloc_hstring(duk_heap *heap,
DUK_ASSERT(res != NULL);
return res;
- alloc_error:
+alloc_error:
return NULL;
}
@@ -51126,13 +55638,13 @@ DUK_LOCAL void duk__strtable_grow_inplace(duk_heap *heap) {
DUK_ASSERT(heap != NULL);
DUK_ASSERT(heap->st_resizing == 1);
DUK_ASSERT(heap->st_size >= 2);
- DUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0); /* 2^N */
+ DUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0); /* 2^N */
DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
DUK_STATS_INC(heap, stats_strtab_resize_grow);
new_st_size = heap->st_size << 1U;
- DUK_ASSERT(new_st_size > heap->st_size); /* No overflow. */
+ DUK_ASSERT(new_st_size > heap->st_size); /* No overflow. */
/* Reallocate the strtable first and then work in-place to rehash
* strings. We don't need an indirect allocation here: even if GC
@@ -51216,7 +55728,7 @@ DUK_LOCAL void duk__strtable_grow_inplace(duk_heap *heap) {
duk__strtable_assert_checks(heap);
#endif
}
-#endif /* DUK__STRTAB_RESIZE_CHECK */
+#endif /* DUK__STRTAB_RESIZE_CHECK */
/*
* Shrink strtable allocation in-place.
@@ -51244,7 +55756,7 @@ DUK_LOCAL void duk__strtable_shrink_inplace(duk_heap *heap) {
DUK_ASSERT(heap != NULL);
DUK_ASSERT(heap->st_resizing == 1);
DUK_ASSERT(heap->st_size >= 2);
- DUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0); /* 2^N */
+ DUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0); /* 2^N */
DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
DUK_STATS_INC(heap, stats_strtab_resize_shrink);
@@ -51302,7 +55814,7 @@ DUK_LOCAL void duk__strtable_shrink_inplace(duk_heap *heap) {
duk__strtable_assert_checks(heap);
#endif
}
-#endif /* DUK__STRTAB_RESIZE_CHECK */
+#endif /* DUK__STRTAB_RESIZE_CHECK */
/*
* Grow/shrink check.
@@ -51310,7 +55822,7 @@ DUK_LOCAL void duk__strtable_shrink_inplace(duk_heap *heap) {
#if defined(DUK__STRTAB_RESIZE_CHECK)
DUK_LOCAL DUK_COLD DUK_NOINLINE void duk__strtable_resize_check(duk_heap *heap) {
- duk_uint32_t load_factor; /* fixed point */
+ duk_uint32_t load_factor; /* fixed point */
DUK_ASSERT(heap != NULL);
#if defined(DUK_USE_STRTAB_PTRCOMP)
@@ -51334,7 +55846,8 @@ DUK_LOCAL DUK_COLD DUK_NOINLINE void duk__strtable_resize_check(duk_heap *heap)
load_factor = heap->st_count / (heap->st_size >> 4U);
DUK_DD(DUK_DDPRINT("resize check string table: size=%lu, count=%lu, load_factor=%lu (fixed point .4; float %lf)",
- (unsigned long) heap->st_size, (unsigned long) heap->st_count,
+ (unsigned long) heap->st_size,
+ (unsigned long) heap->st_count,
(unsigned long) load_factor,
(double) heap->st_count / (double) heap->st_size));
@@ -51342,7 +55855,9 @@ DUK_LOCAL DUK_COLD DUK_NOINLINE void duk__strtable_resize_check(duk_heap *heap)
if (heap->st_size >= DUK_USE_STRTAB_MAXSIZE) {
DUK_DD(DUK_DDPRINT("want to grow strtable (based on load factor) but already maximum size"));
} else {
- DUK_D(DUK_DPRINT("grow string table: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size * 2));
+ DUK_D(DUK_DPRINT("grow string table: %lu -> %lu",
+ (unsigned long) heap->st_size,
+ (unsigned long) heap->st_size * 2));
#if defined(DUK_USE_DEBUG)
duk_heap_strtable_dump(heap);
#endif
@@ -51352,7 +55867,9 @@ DUK_LOCAL DUK_COLD DUK_NOINLINE void duk__strtable_resize_check(duk_heap *heap)
if (heap->st_size <= DUK_USE_STRTAB_MINSIZE) {
DUK_DD(DUK_DDPRINT("want to shrink strtable (based on load factor) but already minimum size"));
} else {
- DUK_D(DUK_DPRINT("shrink string table: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size / 2));
+ DUK_D(DUK_DPRINT("shrink string table: %lu -> %lu",
+ (unsigned long) heap->st_size,
+ (unsigned long) heap->st_size / 2));
#if defined(DUK_USE_DEBUG)
duk_heap_strtable_dump(heap);
#endif
@@ -51364,7 +55881,7 @@ DUK_LOCAL DUK_COLD DUK_NOINLINE void duk__strtable_resize_check(duk_heap *heap)
heap->st_resizing = 0;
}
-#endif /* DUK__STRTAB_RESIZE_CHECK */
+#endif /* DUK__STRTAB_RESIZE_CHECK */
/*
* Torture grow/shrink: unconditionally grow and shrink back.
@@ -51388,7 +55905,7 @@ DUK_LOCAL void duk__strtable_resize_torture(duk_heap *heap) {
}
heap->st_resizing = 0;
}
-#endif /* DUK_USE_STRTAB_TORTURE && DUK__STRTAB_RESIZE_CHECK */
+#endif /* DUK_USE_STRTAB_TORTURE && DUK__STRTAB_RESIZE_CHECK */
/*
* Raw intern; string already checked not to be present.
@@ -51404,8 +55921,12 @@ DUK_LOCAL duk_hstring *duk__strtable_do_intern(duk_heap *heap, const duk_uint8_t
#endif
DUK_DDD(DUK_DDDPRINT("do_intern: heap=%p, str=%p, blen=%lu, strhash=%lx, st_size=%lu, st_count=%lu, load=%lf",
- (void *) heap, (const void *) str, (unsigned long) blen, (unsigned long) strhash,
- (unsigned long) heap->st_size, (unsigned long) heap->st_count,
+ (void *) heap,
+ (const void *) str,
+ (unsigned long) blen,
+ (unsigned long) strhash,
+ (unsigned long) heap->st_size,
+ (unsigned long) heap->st_count,
(double) heap->st_count / (double) heap->st_size));
DUK_ASSERT(heap != NULL);
@@ -51421,7 +55942,7 @@ DUK_LOCAL duk_hstring *duk__strtable_do_intern(duk_heap *heap, const duk_uint8_t
*/
heap->pf_prevent_count++;
- DUK_ASSERT(heap->pf_prevent_count != 0); /* Wrap. */
+ DUK_ASSERT(heap->pf_prevent_count != 0); /* Wrap. */
#if defined(DUK_USE_STRTAB_TORTURE) && defined(DUK__STRTAB_RESIZE_CHECK)
duk__strtable_resize_torture(heap);
@@ -51448,7 +55969,8 @@ DUK_LOCAL duk_hstring *duk__strtable_do_intern(duk_heap *heap, const duk_uint8_t
/* External string check (low memory optimization). */
#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
- extdata = (const duk_uint8_t *) DUK_USE_EXTSTR_INTERN_CHECK(heap->heap_udata, (void *) DUK_LOSE_CONST(str), (duk_size_t) blen);
+ extdata =
+ (const duk_uint8_t *) DUK_USE_EXTSTR_INTERN_CHECK(heap->heap_udata, (void *) DUK_LOSE_CONST(str), (duk_size_t) blen);
#else
extdata = (const duk_uint8_t *) NULL;
#endif
@@ -51486,7 +56008,7 @@ DUK_LOCAL duk_hstring *duk__strtable_do_intern(duk_heap *heap, const duk_uint8_t
#else
slot = heap->strtable + (strhash & heap->st_mask);
#endif
- DUK_ASSERT(res->hdr.h_next == NULL); /* This is the case now, but unnecessary zeroing/NULLing. */
+ DUK_ASSERT(res->hdr.h_next == NULL); /* This is the case now, but unnecessary zeroing/NULLing. */
res->hdr.h_next = DUK__HEAPPTR_DEC16(heap, *slot);
*slot = DUK__HEAPPTR_ENC16(heap, res);
@@ -51530,13 +56052,15 @@ DUK_LOCAL duk_hstring *duk__strtab_romstring_lookup(duk_heap *heap, const duk_ui
}
lookup_hash &= 0xff;
- curr = DUK_LOSE_CONST(duk_rom_strings_lookup[lookup_hash]);
+ curr = (duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_lookup[lookup_hash]);
while (curr != NULL) {
- if (strhash == DUK_HSTRING_GET_HASH(curr) &&
- blen == DUK_HSTRING_GET_BYTELEN(curr) &&
- DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(curr), blen) == 0) {
+ /* Unsafe memcmp() because for zero blen, str may be NULL. */
+ if (strhash == DUK_HSTRING_GET_HASH(curr) && blen == DUK_HSTRING_GET_BYTELEN(curr) &&
+ duk_memcmp_unsafe((const void *) str, (const void *) DUK_HSTRING_GET_DATA(curr), blen) == 0) {
DUK_DDD(DUK_DDDPRINT("intern check: rom string: %!O, computed hash 0x%08lx, rom hash 0x%08lx",
- curr, (unsigned long) strhash, (unsigned long) DUK_HSTRING_GET_HASH(curr)));
+ curr,
+ (unsigned long) strhash,
+ (unsigned long) DUK_HSTRING_GET_HASH(curr)));
return curr;
}
curr = curr->hdr.h_next;
@@ -51544,7 +56068,7 @@ DUK_LOCAL duk_hstring *duk__strtab_romstring_lookup(duk_heap *heap, const duk_ui
return NULL;
}
-#endif /* DUK_USE_ROM_STRINGS */
+#endif /* DUK_USE_ROM_STRINGS */
DUK_INTERNAL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {
duk_uint32_t strhash;
@@ -51554,9 +56078,10 @@ DUK_INTERNAL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uin
/* Preliminaries. */
+ /* XXX: maybe just require 'str != NULL' even for zero size? */
DUK_ASSERT(heap != NULL);
DUK_ASSERT(blen == 0 || str != NULL);
- DUK_ASSERT(blen <= DUK_HSTRING_MAX_BYTELEN); /* Caller is responsible for ensuring this. */
+ DUK_ASSERT(blen <= DUK_HSTRING_MAX_BYTELEN); /* Caller is responsible for ensuring this. */
strhash = duk_heap_hashstring(heap, str, (duk_size_t) blen);
/* String table lookup. */
@@ -51570,9 +56095,8 @@ DUK_INTERNAL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uin
h = heap->strtable[strhash & heap->st_mask];
#endif
while (h != NULL) {
- if (DUK_HSTRING_GET_HASH(h) == strhash &&
- DUK_HSTRING_GET_BYTELEN(h) == blen &&
- DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
+ if (DUK_HSTRING_GET_HASH(h) == strhash && DUK_HSTRING_GET_BYTELEN(h) == blen &&
+ duk_memcmp_unsafe((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
/* Found existing entry. */
DUK_STATS_INC(heap, stats_strtab_intern_hit);
return h;
@@ -51597,7 +56121,7 @@ DUK_INTERNAL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uin
DUK_STATS_INC(heap, stats_strtab_intern_miss);
h = duk__strtable_do_intern(heap, str, blen, strhash);
- return h; /* may be NULL */
+ return h; /* may be NULL */
}
/*
@@ -51620,7 +56144,7 @@ DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32(duk_heap *heap, duk_uint3
p--;
*p = duk_lc_digits[val % 10];
val = val / 10;
- } while (val != 0); /* For val == 0, emit exactly one '0'. */
+ } while (val != 0); /* For val == 0, emit exactly one '0'. */
DUK_ASSERT(p >= buf);
return duk_heap_strtable_intern(heap, (const duk_uint8_t *) p, (duk_uint32_t) ((buf + sizeof(buf)) - p));
@@ -51645,10 +56169,69 @@ DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, con
res = duk_heap_strtable_intern(thr->heap, str, blen);
if (DUK_UNLIKELY(res == NULL)) {
DUK_ERROR_ALLOC_FAILED(thr);
+ DUK_WO_NORETURN(return NULL;);
}
return res;
}
+#if defined(DUK_USE_LITCACHE_SIZE)
+DUK_LOCAL duk_uint_t duk__strtable_litcache_key(const duk_uint8_t *str, duk_uint32_t blen) {
+ duk_uintptr_t key;
+
+ DUK_ASSERT(DUK_USE_LITCACHE_SIZE > 0);
+ DUK_ASSERT(DUK_IS_POWER_OF_TWO((duk_uint_t) DUK_USE_LITCACHE_SIZE));
+
+ key = (duk_uintptr_t) blen ^ (duk_uintptr_t) str;
+ key &= (duk_uintptr_t) (DUK_USE_LITCACHE_SIZE - 1); /* Assumes size is power of 2. */
+ /* Due to masking, cast is in 32-bit range. */
+ DUK_ASSERT(key <= DUK_UINT_MAX);
+ return (duk_uint_t) key;
+}
+
+DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_literal_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
+ duk_uint_t key;
+ duk_litcache_entry *ent;
+ duk_hstring *h;
+
+ /* Fast path check: literal exists in literal cache. */
+ key = duk__strtable_litcache_key(str, blen);
+ ent = thr->heap->litcache + key;
+ if (ent->addr == str) {
+ DUK_DD(DUK_DDPRINT("intern check for cached, pinned literal: str=%p, blen=%ld -> duk_hstring %!O",
+ (const void *) str,
+ (long) blen,
+ (duk_heaphdr *) ent->h));
+ DUK_ASSERT(ent->h != NULL);
+ DUK_ASSERT(DUK_HSTRING_HAS_PINNED_LITERAL(ent->h));
+ DUK_STATS_INC(thr->heap, stats_strtab_litcache_hit);
+ return ent->h;
+ }
+
+ /* Intern and update (overwrite) cache entry. */
+ h = duk_heap_strtable_intern_checked(thr, str, blen);
+ ent->addr = str;
+ ent->h = h;
+ DUK_STATS_INC(thr->heap, stats_strtab_litcache_miss);
+
+ /* Pin the duk_hstring until the next mark-and-sweep. This means
+ * litcache entries don't need to be invalidated until the next
+ * mark-and-sweep as their target duk_hstring is not freed before
+ * the mark-and-sweep happens. The pin remains even if the literal
+ * cache entry is overwritten, and is still useful to avoid string
+ * table traffic.
+ */
+ if (!DUK_HSTRING_HAS_PINNED_LITERAL(h)) {
+ DUK_DD(DUK_DDPRINT("pin duk_hstring because it is a literal: %!O", (duk_heaphdr *) h));
+ DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
+ DUK_HSTRING_INCREF(thr, h);
+ DUK_HSTRING_SET_PINNED_LITERAL(h);
+ DUK_STATS_INC(thr->heap, stats_strtab_litcache_pin);
+ }
+
+ return h;
+}
+#endif /* DUK_USE_LITCACHE_SIZE */
+
DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val) {
duk_hstring *res;
@@ -51658,6 +56241,7 @@ DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr,
res = duk_heap_strtable_intern_u32(thr->heap, val);
if (DUK_UNLIKELY(res == NULL)) {
DUK_ERROR_ALLOC_FAILED(thr);
+ DUK_WO_NORETURN(return NULL;);
}
return res;
}
@@ -51681,7 +56265,8 @@ DUK_INTERNAL void duk_heap_strtable_unlink(duk_heap *heap, duk_hstring *h) {
duk_hstring *prev;
DUK_DDD(DUK_DDDPRINT("remove: heap=%p, h=%p, blen=%lu, strhash=%lx",
- (void *) heap, (void *) h,
+ (void *) heap,
+ (void *) h,
(unsigned long) (h != NULL ? DUK_HSTRING_GET_BYTELEN(h) : 0),
(unsigned long) (h != NULL ? DUK_HSTRING_GET_HASH(h) : 0)));
@@ -51699,13 +56284,13 @@ DUK_INTERNAL void duk_heap_strtable_unlink(duk_heap *heap, duk_hstring *h) {
slot = heap->strtable + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
#endif
other = DUK__HEAPPTR_DEC16(heap, *slot);
- DUK_ASSERT(other != NULL); /* At least argument string is in the chain. */
+ DUK_ASSERT(other != NULL); /* At least argument string is in the chain. */
prev = NULL;
while (other != h) {
prev = other;
other = other->hdr.h_next;
- DUK_ASSERT(other != NULL); /* We'll eventually find 'h'. */
+ DUK_ASSERT(other != NULL); /* We'll eventually find 'h'. */
}
if (prev != NULL) {
/* Middle of list. */
@@ -51719,7 +56304,7 @@ DUK_INTERNAL void duk_heap_strtable_unlink(duk_heap *heap, duk_hstring *h) {
* intern will do one.
*/
}
-#endif /* DUK_USE_REFERENCE_COUNTING */
+#endif /* DUK_USE_REFERENCE_COUNTING */
/* Unlink with a 'prev' pointer. */
DUK_INTERNAL void duk_heap_strtable_unlink_prev(duk_heap *heap, duk_hstring *h, duk_hstring *prev) {
@@ -51730,7 +56315,9 @@ DUK_INTERNAL void duk_heap_strtable_unlink_prev(duk_heap *heap, duk_hstring *h,
#endif
DUK_DDD(DUK_DDDPRINT("remove: heap=%p, prev=%p, h=%p, blen=%lu, strhash=%lx",
- (void *) heap, (void *) prev, (void *) h,
+ (void *) heap,
+ (void *) prev,
+ (void *) h,
(unsigned long) (h != NULL ? DUK_HSTRING_GET_BYTELEN(h) : 0),
(unsigned long) (h != NULL ? DUK_HSTRING_GET_HASH(h) : 0)));
@@ -51832,6 +56419,84 @@ DUK_INTERNAL void duk_heap_strtable_free(duk_heap *heap) {
#undef DUK__HEAPPTR_ENC16
#undef DUK__STRTAB_U32_MAX_STRLEN
/*
+ * duk_heaphdr assertion helpers
+ */
+
+/* #include duk_internal.h -> already included */
+
+#if defined(DUK_USE_ASSERTIONS)
+
+#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
+DUK_INTERNAL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h) {
+ DUK_UNREF(heap);
+ if (h != NULL) {
+ duk_heaphdr *h_prev, *h_next;
+ h_prev = DUK_HEAPHDR_GET_PREV(heap, h);
+ h_next = DUK_HEAPHDR_GET_NEXT(heap, h);
+ DUK_ASSERT(h_prev == NULL || (DUK_HEAPHDR_GET_NEXT(heap, h_prev) == h));
+ DUK_ASSERT(h_next == NULL || (DUK_HEAPHDR_GET_PREV(heap, h_next) == h));
+ }
+}
+#else
+DUK_INTERNAL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h) {
+ DUK_UNREF(heap);
+ DUK_UNREF(h);
+}
+#endif
+
+DUK_INTERNAL void duk_heaphdr_assert_valid(duk_heaphdr *h) {
+ DUK_ASSERT(h != NULL);
+ DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
+}
+
+/* Assert validity of a heaphdr, including all subclasses. */
+DUK_INTERNAL void duk_heaphdr_assert_valid_subclassed(duk_heaphdr *h) {
+ switch (DUK_HEAPHDR_GET_TYPE(h)) {
+ case DUK_HTYPE_OBJECT: {
+ duk_hobject *h_obj = (duk_hobject *) h;
+ DUK_HOBJECT_ASSERT_VALID(h_obj);
+ if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
+ DUK_HCOMPFUNC_ASSERT_VALID((duk_hcompfunc *) h_obj);
+ } else if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
+ DUK_HNATFUNC_ASSERT_VALID((duk_hnatfunc *) h_obj);
+ } else if (DUK_HOBJECT_IS_DECENV(h_obj)) {
+ DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) h_obj);
+ } else if (DUK_HOBJECT_IS_OBJENV(h_obj)) {
+ DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) h_obj);
+ } else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+ DUK_HBUFOBJ_ASSERT_VALID((duk_hbufobj *) h_obj);
+#endif
+ } else if (DUK_HOBJECT_IS_BOUNDFUNC(h_obj)) {
+ DUK_HBOUNDFUNC_ASSERT_VALID((duk_hboundfunc *) h_obj);
+ } else if (DUK_HOBJECT_IS_PROXY(h_obj)) {
+ DUK_HPROXY_ASSERT_VALID((duk_hproxy *) h_obj);
+ } else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
+ DUK_HTHREAD_ASSERT_VALID((duk_hthread *) h_obj);
+ } else {
+ /* Just a plain object. */
+ ;
+ }
+ break;
+ }
+ case DUK_HTYPE_STRING: {
+ duk_hstring *h_str = (duk_hstring *) h;
+ DUK_HSTRING_ASSERT_VALID(h_str);
+ break;
+ }
+ case DUK_HTYPE_BUFFER: {
+ duk_hbuffer *h_buf = (duk_hbuffer *) h;
+ DUK_HBUFFER_ASSERT_VALID(h_buf);
+ break;
+ }
+ default: {
+ DUK_ASSERT(0);
+ }
+ }
+}
+
+#endif /* DUK_USE_ASSERTIONS */
+/*
* Hobject allocation.
*
* Provides primitive allocation functions for all object types (plain object,
@@ -51854,7 +56519,7 @@ DUK_LOCAL void duk__init_object_parts(duk_heap *heap, duk_uint_t hobject_flags,
/* Zeroed by caller. */
obj->hdr.h_flags = hobject_flags | DUK_HTYPE_OBJECT;
- DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(&obj->hdr) == DUK_HTYPE_OBJECT); /* Assume zero shift. */
+ DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(&obj->hdr) == DUK_HTYPE_OBJECT); /* Assume zero shift. */
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
DUK_HOBJECT_SET_PROTOTYPE(heap, obj, NULL);
@@ -51867,7 +56532,7 @@ DUK_LOCAL void duk__init_object_parts(duk_heap *heap, duk_uint_t hobject_flags,
DUK_HEAPHDR_SET_PREV(heap, &obj->hdr, NULL);
#endif
#endif
- DUK_ASSERT_HEAPHDR_LINKS(heap, &obj->hdr);
+ DUK_HEAPHDR_ASSERT_LINKS(heap, &obj->hdr);
DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &obj->hdr);
/* obj->props is intentionally left as NULL, and duk_hobject_props.c must deal
@@ -51963,7 +56628,7 @@ DUK_INTERNAL duk_hboundfunc *duk_hboundfunc_alloc(duk_heap *heap, duk_uint_t hob
if (!res) {
return NULL;
}
- DUK_MEMZERO(res, sizeof(duk_hboundfunc));
+ duk_memzero(res, sizeof(duk_hboundfunc));
duk__init_object_parts(heap, hobject_flags, &res->obj);
@@ -51987,10 +56652,10 @@ DUK_INTERNAL duk_hbufobj *duk_hbufobj_alloc(duk_hthread *thr, duk_uint_t hobject
res->buf_prop = NULL;
#endif
- DUK_ASSERT_HBUFOBJ_VALID(res);
+ DUK_HBUFOBJ_ASSERT_VALID(res);
return res;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/* Allocate a new thread.
*
@@ -52005,7 +56670,7 @@ DUK_INTERNAL duk_hthread *duk_hthread_alloc_unchecked(duk_heap *heap, duk_uint_t
if (DUK_UNLIKELY(res == NULL)) {
return NULL;
}
- DUK_MEMZERO(res, sizeof(duk_hthread));
+ duk_memzero(res, sizeof(duk_hthread));
duk__init_object_parts(heap, hobject_flags, &res->obj);
@@ -52047,6 +56712,7 @@ DUK_INTERNAL duk_hthread *duk_hthread_alloc(duk_hthread *thr, duk_uint_t hobject
res = duk_hthread_alloc_unchecked(thr->heap, hobject_flags);
if (res == NULL) {
DUK_ERROR_ALLOC_FAILED(thr);
+ DUK_WO_NORETURN(return NULL;);
}
return res;
}
@@ -52102,6 +56768,130 @@ DUK_INTERNAL duk_hproxy *duk_hproxy_alloc(duk_hthread *thr, duk_uint_t hobject_f
return res;
}
/*
+ * duk_hobject and subclass assertion helpers
+ */
+
+/* #include duk_internal.h -> already included */
+
+#if defined(DUK_USE_ASSERTIONS)
+
+DUK_INTERNAL void duk_hobject_assert_valid(duk_hobject *h) {
+ DUK_ASSERT(h != NULL);
+ DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE(h) || DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_FUNCTION);
+ DUK_ASSERT(!DUK_HOBJECT_IS_BUFOBJ(h) || (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAYBUFFER ||
+ DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_DATAVIEW ||
+ DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_INT8ARRAY ||
+ DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT8ARRAY ||
+ DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY ||
+ DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_INT16ARRAY ||
+ DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT16ARRAY ||
+ DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_INT32ARRAY ||
+ DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT32ARRAY ||
+ DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_FLOAT32ARRAY ||
+ DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_FLOAT64ARRAY));
+ /* Object is an Array <=> object has exotic array behavior */
+ DUK_ASSERT((DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY && DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)) ||
+ (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_ARRAY && !DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)));
+}
+
+DUK_INTERNAL void duk_harray_assert_valid(duk_harray *h) {
+ DUK_ASSERT(h != NULL);
+ DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) h));
+ DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY((duk_hobject *) h));
+}
+
+DUK_INTERNAL void duk_hboundfunc_assert_valid(duk_hboundfunc *h) {
+ DUK_ASSERT(h != NULL);
+ DUK_ASSERT(DUK_HOBJECT_IS_BOUNDFUNC((duk_hobject *) h));
+ DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&h->target) ||
+ (DUK_TVAL_IS_OBJECT(&h->target) && DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(&h->target))));
+ DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&h->this_binding));
+ DUK_ASSERT(h->nargs == 0 || h->args != NULL);
+}
+
+#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
+DUK_INTERNAL void duk_hbufobj_assert_valid(duk_hbufobj *h) {
+ DUK_ASSERT(h != NULL);
+ DUK_ASSERT(h->shift <= 3);
+ DUK_ASSERT(h->elem_type <= DUK_HBUFOBJ_ELEM_MAX);
+ DUK_ASSERT((h->shift == 0 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT8) ||
+ (h->shift == 0 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT8CLAMPED) ||
+ (h->shift == 0 && h->elem_type == DUK_HBUFOBJ_ELEM_INT8) ||
+ (h->shift == 1 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT16) ||
+ (h->shift == 1 && h->elem_type == DUK_HBUFOBJ_ELEM_INT16) ||
+ (h->shift == 2 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT32) ||
+ (h->shift == 2 && h->elem_type == DUK_HBUFOBJ_ELEM_INT32) ||
+ (h->shift == 2 && h->elem_type == DUK_HBUFOBJ_ELEM_FLOAT32) ||
+ (h->shift == 3 && h->elem_type == DUK_HBUFOBJ_ELEM_FLOAT64));
+ DUK_ASSERT(h->is_typedarray == 0 || h->is_typedarray == 1);
+ DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h));
+ if (h->buf == NULL) {
+ DUK_ASSERT(h->offset == 0);
+ DUK_ASSERT(h->length == 0);
+ } else {
+ /* No assertions for offset or length; in particular,
+ * it's OK for length to be longer than underlying
+ * buffer. Just ensure they don't wrap when added.
+ */
+ DUK_ASSERT(h->offset + h->length >= h->offset);
+ }
+}
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+
+DUK_INTERNAL void duk_hcompfunc_assert_valid(duk_hcompfunc *h) {
+ DUK_ASSERT(h != NULL);
+}
+
+DUK_INTERNAL void duk_hnatfunc_assert_valid(duk_hnatfunc *h) {
+ DUK_ASSERT(h != NULL);
+}
+
+DUK_INTERNAL void duk_hdecenv_assert_valid(duk_hdecenv *h) {
+ DUK_ASSERT(h != NULL);
+ DUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) h));
+ DUK_ASSERT(h->thread == NULL || h->varmap != NULL);
+}
+
+DUK_INTERNAL void duk_hobjenv_assert_valid(duk_hobjenv *h) {
+ DUK_ASSERT(h != NULL);
+ DUK_ASSERT(DUK_HOBJECT_IS_OBJENV((duk_hobject *) h));
+ DUK_ASSERT(h->target != NULL);
+ DUK_ASSERT(h->has_this == 0 || h->has_this == 1);
+}
+
+DUK_INTERNAL void duk_hproxy_assert_valid(duk_hproxy *h) {
+ DUK_ASSERT(h != NULL);
+ DUK_ASSERT(h->target != NULL);
+ DUK_ASSERT(h->handler != NULL);
+ DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((duk_hobject *) h));
+}
+
+DUK_INTERNAL void duk_hthread_assert_valid(duk_hthread *thr) {
+ DUK_ASSERT(thr != NULL);
+ DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) thr) == DUK_HTYPE_OBJECT);
+ DUK_ASSERT(DUK_HOBJECT_IS_THREAD((duk_hobject *) thr));
+ DUK_ASSERT(thr->unused1 == 0);
+ DUK_ASSERT(thr->unused2 == 0);
+}
+
+DUK_INTERNAL void duk_ctx_assert_valid(duk_hthread *thr) {
+ DUK_ASSERT(thr != NULL);
+ DUK_HTHREAD_ASSERT_VALID(thr);
+ DUK_ASSERT(thr->valstack != NULL);
+ DUK_ASSERT(thr->valstack_bottom != NULL);
+ DUK_ASSERT(thr->valstack_top != NULL);
+ DUK_ASSERT(thr->valstack_end != NULL);
+ DUK_ASSERT(thr->valstack_alloc_end != NULL);
+ DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack);
+ DUK_ASSERT(thr->valstack_end >= thr->valstack);
+ DUK_ASSERT(thr->valstack_top >= thr->valstack);
+ DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
+ DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
+ DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
+}
+
+#endif /* DUK_USE_ASSERTIONS */
+/*
* Object enumeration support.
*
* Creates an internal enumeration state object to be used e.g. with for-in
@@ -52127,7 +56917,7 @@ DUK_INTERNAL duk_hproxy *duk_hproxy_alloc(duk_hthread *thr, duk_uint_t hobject_f
/* First enumerated key index in enumerator object, must match exactly the
* number of control properties inserted to the enumerator.
*/
-#define DUK__ENUM_START_INDEX 2
+#define DUK__ENUM_START_INDEX 2
/* Current implementation suffices for ES2015 for now because there's no symbol
* sorting, so commented out for now.
@@ -52196,7 +56986,7 @@ DUK_LOCAL duk_bool_t duk__sort_compare_es6(duk_hstring *a, duk_hstring *b, duk__
DUK_ASSERT(a != NULL);
DUK_ASSERT(b != NULL);
- DUK_UNREF(b); /* Not actually needed now, val_b suffices. */
+ DUK_UNREF(b); /* Not actually needed now, val_b suffices. */
val_a = duk__hstring_sort_key(a);
@@ -52217,7 +57007,7 @@ DUK_LOCAL void duk__sort_enum_keys_es6(duk_hthread *thr, duk_hobject *h_obj, duk
DUK_UNREF(thr);
if (idx_end <= idx_start + 1) {
- return; /* Zero or one element(s). */
+ return; /* Zero or one element(s). */
}
keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, h_obj);
@@ -52235,7 +57025,7 @@ DUK_LOCAL void duk__sort_enum_keys_es6(duk_hthread *thr, duk_hobject *h_obj, duk
* (and optimized for) case.
*/
- val_curr = duk__hstring_sort_key(h_curr); /* Remains same during scanning. */
+ val_curr = duk__hstring_sort_key(h_curr); /* Remains same during scanning. */
for (idx_insert = idx - 1; idx_insert >= idx_start; idx_insert--) {
duk_hstring *h_insert;
h_insert = keys[idx_insert];
@@ -52262,12 +57052,19 @@ DUK_LOCAL void duk__sort_enum_keys_es6(duk_hthread *thr, duk_hobject *h_obj, duk
* are very often in order already.
*/
if (idx != idx_insert) {
- DUK_MEMMOVE((void *) (keys + idx_insert + 1),
+ duk_memmove((void *) (keys + idx_insert + 1),
(const void *) (keys + idx_insert),
((size_t) (idx - idx_insert) * sizeof(duk_hstring *)));
keys[idx_insert] = h_curr;
}
}
+
+ /* Entry part has been reordered now with no side effects.
+ * If the object has a hash part, it will now be incorrect
+ * and we need to rehash. Do that by forcing a resize to
+ * the current size.
+ */
+ duk_hobject_resize_entrypart(thr, h_obj, DUK_HOBJECT_GET_ESIZE(h_obj));
}
/*
@@ -52301,7 +57098,7 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint
duk_hobject *h_proxy_handler;
duk_hobject *h_trap_result;
#endif
- duk_uint_fast32_t i, len; /* used for array, stack, and entry indices */
+ duk_uint_fast32_t i, len; /* used for array, stack, and entry indices */
duk_uint_fast32_t sort_start_index;
DUK_ASSERT(thr != NULL);
@@ -52320,11 +57117,11 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint
* real object to check against.
*/
duk_push_hobject(thr, enum_target);
- duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_TARGET);
+ duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_TARGET); /* Target is bare, plain put OK. */
/* Initialize index so that we skip internal control keys. */
duk_push_int(thr, DUK__ENUM_START_INDEX);
- duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_NEXT);
+ duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_NEXT); /* Target is bare, plain put OK. */
/*
* Proxy object handling
@@ -52334,9 +57131,7 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint
if (DUK_LIKELY((enum_flags & DUK_ENUM_NO_PROXY_BEHAVIOR) != 0)) {
goto skip_proxy;
}
- if (DUK_LIKELY(!duk_hobject_proxy_check(enum_target,
- &h_proxy_target,
- &h_proxy_handler))) {
+ if (DUK_LIKELY(!duk_hobject_proxy_check(enum_target, &h_proxy_target, &h_proxy_handler))) {
goto skip_proxy;
}
@@ -52357,17 +57152,17 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint
DUK_DDD(DUK_DDDPRINT("h_proxy_target=%!O", (duk_heaphdr *) h_proxy_target));
enum_target = h_proxy_target;
- duk_push_hobject(thr, enum_target); /* -> [ ... enum_target res handler undefined target ] */
- duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_INT_TARGET);
+ duk_push_hobject(thr, enum_target); /* -> [ ... enum_target res handler undefined target ] */
+ duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_INT_TARGET); /* Target is bare, plain put OK. */
- duk_pop_2(thr); /* -> [ ... enum_target res ] */
+ duk_pop_2(thr); /* -> [ ... enum_target res ] */
goto skip_proxy;
}
/* [ ... enum_target res handler trap ] */
duk_insert(thr, -2);
- duk_push_hobject(thr, h_proxy_target); /* -> [ ... enum_target res trap handler target ] */
- duk_call_method(thr, 1 /*nargs*/); /* -> [ ... enum_target res trap_result ] */
+ duk_push_hobject(thr, h_proxy_target); /* -> [ ... enum_target res trap handler target ] */
+ duk_call_method(thr, 1 /*nargs*/); /* -> [ ... enum_target res trap_result ] */
h_trap_result = duk_require_hobject(thr, -1);
DUK_UNREF(h_trap_result);
@@ -52380,7 +57175,7 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint
len = (duk_uint_fast32_t) duk_get_length(thr, -1);
for (i = 0; i < len; i++) {
(void) duk_get_prop_index(thr, -1, (duk_uarridx_t) i);
- DUK_ASSERT(duk_is_string(thr, -1)); /* postprocess cleaned up */
+ DUK_ASSERT(duk_is_string(thr, -1)); /* postprocess cleaned up */
/* [ ... enum_target res trap_result keys_array val ] */
duk_push_true(thr);
/* [ ... enum_target res trap_result keys_array val true ] */
@@ -52401,8 +57196,8 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint
DUK_DDD(DUK_DDDPRINT("proxy enumeration, final res: %!O", (duk_heaphdr *) res));
goto compact_and_return;
- skip_proxy:
-#endif /* DUK_USE_ES6_PROXY */
+skip_proxy:
+#endif /* DUK_USE_ES6_PROXY */
curr = enum_target;
sort_start_index = DUK__ENUM_START_INDEX;
@@ -52412,6 +57207,7 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint
#if !defined(DUK_USE_PREFER_SIZE)
duk_bool_t need_sort = 0;
#endif
+ duk_bool_t cond;
/* Enumeration proceeds by inheritance level. Virtual
* properties need to be handled specially, followed by
@@ -52438,10 +57234,12 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint
*/
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
- if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr) || DUK_HOBJECT_IS_BUFOBJ(curr)) {
+ cond = DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr) || DUK_HOBJECT_IS_BUFOBJ(curr);
#else
- if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr)) {
+ cond = DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr);
#endif
+ cond = cond && !(enum_flags & DUK_ENUM_EXCLUDE_STRINGS);
+ if (cond) {
duk_bool_t have_length = 1;
/* String and buffer enumeration behavior is identical now,
@@ -52450,7 +57248,7 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint
if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr)) {
duk_hstring *h_val;
h_val = duk_hobject_get_internal_value_string(thr->heap, curr);
- DUK_ASSERT(h_val != NULL); /* string objects must not created without internal value */
+ DUK_ASSERT(h_val != NULL); /* string objects must not created without internal value */
len = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_val);
}
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
@@ -52473,7 +57271,7 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint
len = (duk_uint_fast32_t) (h_bufobj->length >> h_bufobj->shift);
}
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
for (i = 0; i < len; i++) {
duk_hstring *k;
@@ -52503,26 +57301,29 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint
* Array part
*/
- for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(curr); i++) {
- duk_hstring *k;
- duk_tval *tv;
+ cond = !(enum_flags & DUK_ENUM_EXCLUDE_STRINGS);
+ if (cond) {
+ for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(curr); i++) {
+ duk_hstring *k;
+ duk_tval *tv;
- tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, curr, i);
- if (DUK_TVAL_IS_UNUSED(tv)) {
- continue;
- }
- k = duk_heap_strtable_intern_u32_checked(thr, (duk_uint32_t) i); /* Fragile reachability. */
- DUK_ASSERT(k);
+ tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, curr, i);
+ if (DUK_TVAL_IS_UNUSED(tv)) {
+ continue;
+ }
+ k = duk_heap_strtable_intern_u32_checked(thr, (duk_uint32_t) i); /* Fragile reachability. */
+ DUK_ASSERT(k);
- duk__add_enum_key(thr, k);
+ duk__add_enum_key(thr, k);
- /* [enum_target res] */
- }
+ /* [enum_target res] */
+ }
- if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(curr)) {
- /* Array .length comes after numeric indices. */
- if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
- duk__add_enum_key_stridx(thr, DUK_STRIDX_LENGTH);
+ if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(curr)) {
+ /* Array .length comes after numeric indices. */
+ if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
+ duk__add_enum_key_stridx(thr, DUK_STRIDX_LENGTH);
+ }
}
}
@@ -52542,8 +57343,7 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint
continue;
}
if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(k))) {
- if (!(enum_flags & DUK_ENUM_INCLUDE_HIDDEN) &&
- DUK_HSTRING_HAS_HIDDEN(k)) {
+ if (!(enum_flags & DUK_ENUM_INCLUDE_HIDDEN) && DUK_HSTRING_HAS_HIDDEN(k)) {
continue;
}
if (!(enum_flags & DUK_ENUM_INCLUDE_SYMBOLS)) {
@@ -52553,7 +57353,7 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint
need_sort = 1;
#endif
} else {
- DUK_ASSERT(!DUK_HSTRING_HAS_HIDDEN(k)); /* would also have symbol flag */
+ DUK_ASSERT(!DUK_HSTRING_HAS_HIDDEN(k)); /* would also have symbol flag */
if (enum_flags & DUK_ENUM_EXCLUDE_STRINGS) {
continue;
}
@@ -52602,7 +57402,10 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint
#else
if (need_sort) {
DUK_DDD(DUK_DDDPRINT("need to sort"));
- duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) sort_start_index, (duk_int_fast32_t) sort_end_index);
+ duk__sort_enum_keys_es6(thr,
+ res,
+ (duk_int_fast32_t) sort_start_index,
+ (duk_int_fast32_t) sort_end_index);
} else {
DUK_DDD(DUK_DDDPRINT("no need to sort"));
}
@@ -52635,11 +57438,14 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint
/* Sort to ES2015 order which works for pure array incides but
* also for mixed keys.
*/
- duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) DUK__ENUM_START_INDEX, (duk_int_fast32_t) DUK_HOBJECT_GET_ENEXT(res));
+ duk__sort_enum_keys_es6(thr,
+ res,
+ (duk_int_fast32_t) DUK__ENUM_START_INDEX,
+ (duk_int_fast32_t) DUK_HOBJECT_GET_ENEXT(res));
}
#if defined(DUK_USE_ES6_PROXY)
- compact_and_return:
+compact_and_return:
#endif
/* compact; no need to seal because object is internal */
duk_hobject_compact_props(thr, res);
@@ -52679,7 +57485,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t
* be the proxy, and checking key existence against the proxy is not
* required (or sensible, as the keys may be fully virtual).
*/
- duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_TARGET);
+ duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_TARGET);
enum_target = duk_require_hobject(thr, -1);
DUK_ASSERT(enum_target != NULL);
#if defined(DUK_USE_ES6_PROXY)
@@ -52687,10 +57493,11 @@ DUK_INTERNAL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t
#else
check_existence = 1;
#endif
- duk_pop(thr); /* still reachable */
+ duk_pop(thr); /* still reachable */
DUK_DDD(DUK_DDDPRINT("getting next enum value, enum_target=%!iO, enumerator=%!iT",
- (duk_heaphdr *) enum_target, (duk_tval *) duk_get_tval(thr, -1)));
+ (duk_heaphdr *) enum_target,
+ (duk_tval *) duk_get_tval(thr, -1)));
/* no array part */
for (;;) {
@@ -52731,22 +57538,22 @@ DUK_INTERNAL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t
duk_push_hstring(thr, res);
if (get_value) {
duk_push_hobject(thr, enum_target);
- duk_dup_m2(thr); /* -> [... enum key enum_target key] */
+ duk_dup_m2(thr); /* -> [... enum key enum_target key] */
duk_get_prop(thr, -2); /* -> [... enum key enum_target val] */
- duk_remove_m2(thr); /* -> [... enum key val] */
- duk_remove(thr, -3); /* -> [... key val] */
+ duk_remove_m2(thr); /* -> [... enum key val] */
+ duk_remove(thr, -3); /* -> [... key val] */
} else {
- duk_remove_m2(thr); /* -> [... key] */
+ duk_remove_m2(thr); /* -> [... key] */
}
return 1;
} else {
- duk_pop(thr); /* -> [...] */
+ duk_pop(thr); /* -> [...] */
return 0;
}
}
/*
- * Get enumerated keys in an Ecmascript array. Matches Object.keys() behavior
+ * Get enumerated keys in an ECMAScript array. Matches Object.keys() behavior
* described in E5 Section 15.2.3.14.
*/
@@ -52776,6 +57583,7 @@ DUK_INTERNAL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_sma
/* XXX: uninit would be OK */
tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count);
DUK_ASSERT(count == 0 || tv != NULL);
+ DUK_ASSERT(!duk_is_bare_object(thr, -1));
/* Fill result array, no side effects. */
@@ -52786,7 +57594,7 @@ DUK_INTERNAL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_sma
duk_hstring *k;
k = *keys++;
- DUK_ASSERT(k != NULL); /* enumerator must have no keys deleted */
+ DUK_ASSERT(k != NULL); /* enumerator must have no keys deleted */
DUK_TVAL_SET_STRING(tv, k);
tv++;
@@ -52798,7 +57606,7 @@ DUK_INTERNAL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_sma
/* [enum_target res] */
- return 1; /* return 1 to allow callers to tail call */
+ return 1; /* return 1 to allow callers to tail call */
}
/* automatic undefs */
@@ -52809,7 +57617,10 @@ DUK_INTERNAL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_sma
/* #include duk_internal.h -> already included */
-DUK_INTERNAL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p, duk_bool_t ignore_loop) {
+DUK_INTERNAL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr,
+ duk_hobject *h,
+ duk_hobject *p,
+ duk_bool_t ignore_loop) {
duk_uint_t sanity;
DUK_ASSERT(thr != NULL);
@@ -52832,6 +57643,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, d
break;
} else {
DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
+ DUK_WO_NORETURN(return 0;);
}
}
h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
@@ -52847,7 +57659,7 @@ DUK_INTERNAL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject
DUK_ASSERT(h);
tmp = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
- DUK_HOBJECT_INCREF_ALLOWNULL(thr, p); /* avoid problems if p == h->prototype */
+ DUK_HOBJECT_INCREF_ALLOWNULL(thr, p); /* avoid problems if p == h->prototype */
DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
#else
DUK_ASSERT(h);
@@ -52892,7 +57704,7 @@ DUK_INTERNAL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr
hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
DUK_ASSERT(hdr != NULL);
- hdr[0] = (duk_uint32_t) length; /* valid pc range is [0, length[ */
+ hdr[0] = (duk_uint32_t) length; /* valid pc range is [0, length[ */
curr_pc = 0U;
while (curr_pc < length) {
@@ -52915,14 +57727,14 @@ DUK_INTERNAL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr
(long) hdr[hdr_index + 1]));
#endif
- DUK_MEMZERO(be_ctx, sizeof(*be_ctx));
+ duk_memzero(be_ctx, sizeof(*be_ctx));
be_ctx->data = ((duk_uint8_t *) hdr) + curr_offset;
be_ctx->length = (duk_size_t) DUK_PC2LINE_MAX_DIFF_LENGTH;
for (;;) {
curr_pc++;
- if ( ((curr_pc % DUK_PC2LINE_SKIP) == 0) || /* end of diff run */
- (curr_pc >= length) ) { /* end of bytecode */
+ if (((curr_pc % DUK_PC2LINE_SKIP) == 0) || /* end of diff run */
+ (curr_pc >= length)) { /* end of bytecode */
break;
}
DUK_ASSERT(curr_pc < length);
@@ -52969,7 +57781,9 @@ DUK_INTERNAL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr
(void) duk_to_fixed_buffer(thr, -1, NULL);
DUK_DDD(DUK_DDDPRINT("final pc2line data: pc_limit=%ld, length=%ld, %lf bits/opcode --> %!ixT",
- (long) length, (long) new_size, (double) new_size * 8.0 / (double) length,
+ (long) length,
+ (long) new_size,
+ (double) new_size * 8.0 / (double) length,
(duk_tval *) duk_get_tval(thr, -1)));
}
@@ -53009,8 +57823,7 @@ DUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk
pc_limit = hdr[0];
if (pc >= pc_limit) {
/* Note: pc is unsigned and cannot be negative */
- DUK_DD(DUK_DDPRINT("pc2line lookup failed: pc out of bounds (pc=%ld, limit=%ld)",
- (long) pc, (long) pc_limit));
+ DUK_DD(DUK_DDPRINT("pc2line lookup failed: pc out of bounds (pc=%ld, limit=%ld)", (long) pc, (long) pc_limit));
goto pc2line_error;
}
@@ -53018,7 +57831,8 @@ DUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk
start_offset = hdr[1 + hdr_index * 2 + 1];
if ((duk_size_t) start_offset > DUK_HBUFFER_FIXED_GET_SIZE(buf)) {
DUK_DD(DUK_DDPRINT("pc2line lookup failed: start_offset out of bounds (start_offset=%ld, buffer_size=%ld)",
- (long) start_offset, (long) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) buf)));
+ (long) start_offset,
+ (long) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) buf)));
goto pc2line_error;
}
@@ -53026,7 +57840,7 @@ DUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk
* Iterate the bitstream (line diffs) until PC is reached
*/
- DUK_MEMZERO(bd_ctx, sizeof(*bd_ctx));
+ duk_memzero(bd_ctx, sizeof(*bd_ctx));
bd_ctx->data = ((duk_uint8_t *) hdr) + start_offset;
bd_ctx->length = (duk_size_t) (DUK_HBUFFER_FIXED_GET_SIZE(buf) - start_offset);
@@ -53045,7 +57859,7 @@ DUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk
if (duk_bd_decode_flag(bd_ctx)) {
/* 1 1 1 <32 bits> */
duk_uint_fast32_t t;
- t = duk_bd_decode(bd_ctx, 16); /* workaround: max nbits = 24 now */
+ t = duk_bd_decode(bd_ctx, 16); /* workaround: max nbits = 24 now */
t = (t << 16) + duk_bd_decode(bd_ctx, 16);
curr_line = t;
} else {
@@ -53070,7 +57884,7 @@ DUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk
DUK_DDD(DUK_DDDPRINT("pc2line lookup result: pc %ld -> line %ld", (long) pc, (long) curr_line));
return curr_line;
- pc2line_error:
+pc2line_error:
DUK_D(DUK_DPRINT("pc2line conversion failed for pc=%ld", (long) pc));
return 0;
}
@@ -53085,8 +57899,8 @@ DUK_INTERNAL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_i
* future work in debugger.rst).
*/
- duk_get_prop_stridx(thr, idx_func, DUK_STRIDX_INT_PC2LINE);
- pc2line = (duk_hbuffer_fixed *) duk_get_hbuffer(thr, -1);
+ duk_xget_owndataprop_stridx_short(thr, idx_func, DUK_STRIDX_INT_PC2LINE);
+ pc2line = (duk_hbuffer_fixed *) (void *) duk_get_hbuffer(thr, -1);
if (pc2line != NULL) {
DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) pc2line) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) pc2line));
line = duk__hobject_pc2line_query_raw(thr, pc2line, (duk_uint_fast32_t) pc);
@@ -53098,7 +57912,7 @@ DUK_INTERNAL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_i
return line;
}
-#endif /* DUK_USE_PC2LINE */
+#endif /* DUK_USE_PC2LINE */
/*
* duk_hobject property access functionality.
*
@@ -53147,35 +57961,59 @@ DUK_INTERNAL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_i
* Local defines
*/
-#define DUK__NO_ARRAY_INDEX DUK_HSTRING_NO_ARRAY_INDEX
+#define DUK__NO_ARRAY_INDEX DUK_HSTRING_NO_ARRAY_INDEX
/* Marker values for hash part. */
-#define DUK__HASH_UNUSED DUK_HOBJECT_HASHIDX_UNUSED
-#define DUK__HASH_DELETED DUK_HOBJECT_HASHIDX_DELETED
+#define DUK__HASH_UNUSED DUK_HOBJECT_HASHIDX_UNUSED
+#define DUK__HASH_DELETED DUK_HOBJECT_HASHIDX_DELETED
/* Valstack space that suffices for all local calls, excluding any recursion
- * into Ecmascript or Duktape/C calls (Proxy, getters, etc).
+ * into ECMAScript or Duktape/C calls (Proxy, getters, etc).
*/
-#define DUK__VALSTACK_SPACE 10
+#define DUK__VALSTACK_SPACE 10
/* Valstack space allocated especially for proxy lookup which does a
* recursive property lookup.
*/
-#define DUK__VALSTACK_PROXY_LOOKUP 20
+#define DUK__VALSTACK_PROXY_LOOKUP 20
/*
* Local prototypes
*/
-DUK_LOCAL_DECL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc);
-DUK_LOCAL_DECL void duk__check_arguments_map_for_put(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc, duk_bool_t throw_flag);
-DUK_LOCAL_DECL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc);
-
-DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr, duk_hobject *obj, duk_uint32_t old_len, duk_uint32_t new_len, duk_bool_t force_flag, duk_uint32_t *out_result_len);
+DUK_LOCAL_DECL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr,
+ duk_hobject *obj,
+ duk_hstring *key,
+ duk_propdesc *temp_desc);
+DUK_LOCAL_DECL void duk__check_arguments_map_for_put(duk_hthread *thr,
+ duk_hobject *obj,
+ duk_hstring *key,
+ duk_propdesc *temp_desc,
+ duk_bool_t throw_flag);
+DUK_LOCAL_DECL void duk__check_arguments_map_for_delete(duk_hthread *thr,
+ duk_hobject *obj,
+ duk_hstring *key,
+ duk_propdesc *temp_desc);
+
+DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
+ duk_hobject *obj,
+ duk_uint32_t old_len,
+ duk_uint32_t new_len,
+ duk_bool_t force_flag,
+ duk_uint32_t *out_result_len);
DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj);
-DUK_LOCAL_DECL duk_bool_t duk__get_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags);
-DUK_LOCAL_DECL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_uint32_t arr_idx, duk_propdesc *out_desc, duk_small_uint_t flags);
+DUK_LOCAL_DECL duk_bool_t
+duk__get_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags);
+DUK_LOCAL_DECL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr,
+ duk_hobject *obj,
+ duk_hstring *key,
+ duk_uint32_t arr_idx,
+ duk_propdesc *out_desc,
+ duk_small_uint_t flags);
+
+DUK_LOCAL_DECL void duk__abandon_array_part(duk_hthread *thr, duk_hobject *obj);
+DUK_LOCAL_DECL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx);
/*
* Misc helpers
@@ -53200,8 +58038,8 @@ DUK_LOCAL duk_uint32_t duk__tval_number_to_arr_idx(duk_tval *tv) {
*/
dbl = DUK_TVAL_GET_NUMBER(tv);
idx = (duk_uint32_t) dbl;
- if ((duk_double_t) idx == dbl) {
- /* Is whole and within 32 bit range. If the value happens to be 0xFFFFFFFF,
+ if (duk_double_equals((duk_double_t) idx, dbl)) {
+ /* Is whole and within 32 bit range. If the value happens to be 0xFFFFFFFF,
* it's not a valid array index but will then match DUK__NO_ARRAY_INDEX.
*/
return idx;
@@ -53228,7 +58066,7 @@ DUK_LOCAL duk_uint32_t duk__tval_fastint_to_arr_idx(duk_tval *tv) {
*/
return (duk_uint32_t) t;
}
-#endif /* DUK_USE_FASTINT */
+#endif /* DUK_USE_FASTINT */
/* Convert a duk_tval on the value stack (in a trusted index we don't validate)
* to a string or symbol using ES2015 ToPropertyKey():
@@ -53253,7 +58091,7 @@ DUK_LOCAL duk_uint32_t duk__to_property_key(duk_hthread *thr, duk_idx_t idx, duk
* but still be compliant and share code.
*/
- tv_dst = DUK_GET_TVAL_NEGIDX(thr, idx); /* intentionally unvalidated */
+ tv_dst = DUK_GET_TVAL_NEGIDX(thr, idx); /* intentionally unvalidated */
if (DUK_TVAL_IS_STRING(tv_dst)) {
/* Most important path: strings and plain symbols are used as
* is. For symbols the array index check below is unnecessary
@@ -53273,7 +58111,7 @@ DUK_LOCAL duk_uint32_t duk__to_property_key(duk_hthread *thr, duk_idx_t idx, duk
}
DUK_LOCAL duk_uint32_t duk__push_tval_to_property_key(duk_hthread *thr, duk_tval *tv_key, duk_hstring **out_h) {
- duk_push_tval(thr, tv_key); /* XXX: could use an unsafe push here */
+ duk_push_tval(thr, tv_key); /* XXX: could use an unsafe push here */
return duk__to_property_key(thr, -1, out_h);
}
@@ -53313,7 +58151,7 @@ DUK_LOCAL duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size) {
* is relatively sparse.
*/
tmp = e_size;
- res = 2; /* Result will be 2 ** (N + 1). */
+ res = 2; /* Result will be 2 ** (N + 1). */
while (tmp >= 0x40) {
tmp >>= 6;
res <<= 6;
@@ -53322,23 +58160,21 @@ DUK_LOCAL duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size) {
tmp >>= 1;
res <<= 1;
}
- DUK_ASSERT((DUK_HOBJECT_MAX_PROPERTIES << 2U) > DUK_HOBJECT_MAX_PROPERTIES); /* Won't wrap, even shifted by 2. */
+ DUK_ASSERT((DUK_HOBJECT_MAX_PROPERTIES << 2U) > DUK_HOBJECT_MAX_PROPERTIES); /* Won't wrap, even shifted by 2. */
DUK_ASSERT(res > e_size);
return res;
} else {
return 0;
}
}
-#endif /* USE_PROP_HASH_PART */
+#endif /* USE_PROP_HASH_PART */
/* Get minimum entry part growth for a certain size. */
DUK_LOCAL duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size) {
duk_uint32_t res;
- DUK_ASSERT(e_size <= DUK_HOBJECT_MAX_PROPERTIES);
-
res = (e_size + DUK_USE_HOBJECT_ENTRY_MINGROW_ADD) / DUK_USE_HOBJECT_ENTRY_MINGROW_DIVISOR;
- DUK_ASSERT(res >= 1); /* important for callers */
+ DUK_ASSERT(res >= 1); /* important for callers */
return res;
}
@@ -53346,10 +58182,8 @@ DUK_LOCAL duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size) {
DUK_LOCAL duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size) {
duk_uint32_t res;
- DUK_ASSERT((duk_size_t) a_size <= DUK_HOBJECT_MAX_PROPERTIES);
-
res = (a_size + DUK_USE_HOBJECT_ARRAY_MINGROW_ADD) / DUK_USE_HOBJECT_ARRAY_MINGROW_DIVISOR;
- DUK_ASSERT(res >= 1); /* important for callers */
+ DUK_ASSERT(res >= 1); /* important for callers */
return res;
}
@@ -53379,7 +58213,7 @@ DUK_LOCAL duk_uint32_t duk__count_used_e_keys(duk_hthread *thr, duk_hobject *obj
DUK_LOCAL void duk__compute_a_stats(duk_hthread *thr, duk_hobject *obj, duk_uint32_t *out_used, duk_uint32_t *out_min_size) {
duk_uint_fast32_t i;
duk_uint_fast32_t used = 0;
- duk_uint_fast32_t highest_idx = (duk_uint_fast32_t) -1; /* see below */
+ duk_uint_fast32_t highest_idx = (duk_uint_fast32_t) -1; /* see below */
duk_tval *a;
DUK_ASSERT(obj != NULL);
@@ -53402,7 +58236,7 @@ DUK_LOCAL void duk__compute_a_stats(duk_hthread *thr, duk_hobject *obj, duk_uint
*/
*out_used = (duk_uint32_t) used;
- *out_min_size = (duk_uint32_t) (highest_idx + 1); /* 0 if no used entries */
+ *out_min_size = (duk_uint32_t) (highest_idx + 1); /* 0 if no used entries */
}
/* Check array density and indicate whether or not the array part should be abandoned. */
@@ -53428,6 +58262,8 @@ DUK_LOCAL duk_bool_t duk__abandon_array_density_check(duk_uint32_t a_used, duk_u
/* Fast check for extending array: check whether or not a slow density check is required. */
DUK_LOCAL duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, duk_uint32_t old_size) {
+ duk_uint32_t new_size_min;
+
/*
* In a fast check we assume old_size equals old_used (i.e., existing
* array is fully dense).
@@ -53449,7 +58285,111 @@ DUK_LOCAL duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx
* arr_idx > limit'' * ((old_size + 7) / 8)
*/
- return (arr_idx > DUK_USE_HOBJECT_ARRAY_FAST_RESIZE_LIMIT * ((old_size + 7) >> 3));
+ new_size_min = arr_idx + 1;
+ return (new_size_min >= DUK_USE_HOBJECT_ARRAY_ABANDON_MINSIZE) &&
+ (arr_idx > DUK_USE_HOBJECT_ARRAY_FAST_RESIZE_LIMIT * ((old_size + 7) >> 3));
+}
+
+DUK_LOCAL duk_bool_t duk__abandon_array_check(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj) {
+ duk_uint32_t min_size;
+ duk_uint32_t old_used;
+ duk_uint32_t old_size;
+
+ if (!duk__abandon_array_slow_check_required(arr_idx, DUK_HOBJECT_GET_ASIZE(obj))) {
+ DUK_DDD(DUK_DDDPRINT("=> fast resize is OK"));
+ return 0;
+ }
+
+ duk__compute_a_stats(thr, obj, &old_used, &old_size);
+
+ DUK_DDD(DUK_DDDPRINT("abandon check, array stats: old_used=%ld, old_size=%ld, arr_idx=%ld",
+ (long) old_used,
+ (long) old_size,
+ (long) arr_idx));
+
+ min_size = arr_idx + 1;
+#if defined(DUK_USE_OBJSIZES16)
+ if (min_size > DUK_UINT16_MAX) {
+ goto do_abandon;
+ }
+#endif
+ DUK_UNREF(min_size);
+
+ /* Note: intentionally use approximations to shave a few instructions:
+ * a_used = old_used (accurate: old_used + 1)
+ * a_size = arr_idx (accurate: arr_idx + 1)
+ */
+ if (duk__abandon_array_density_check(old_used, arr_idx)) {
+ DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
+ "decided to abandon array part (would become too sparse)"));
+
+ /* Abandoning requires a props allocation resize and
+ * 'rechecks' the valstack, invalidating any existing
+ * valstack value pointers.
+ */
+ goto do_abandon;
+ }
+
+ DUK_DDD(DUK_DDDPRINT("=> decided to keep array part"));
+ return 0;
+
+do_abandon:
+ duk__abandon_array_part(thr, obj);
+ DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
+ return 1;
+}
+
+DUK_LOCAL duk_tval *duk__obtain_arridx_slot_slowpath(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj) {
+ /*
+ * Array needs to grow, but we don't want it becoming too sparse.
+ * If it were to become sparse, abandon array part, moving all
+ * array entries into the entries part (for good).
+ *
+ * Since we don't keep track of actual density (used vs. size) of
+ * the array part, we need to estimate somehow. The check is made
+ * in two parts:
+ *
+ * - Check whether the resize need is small compared to the
+ * current size (relatively); if so, resize without further
+ * checking (essentially we assume that the original part is
+ * "dense" so that the result would be dense enough).
+ *
+ * - Otherwise, compute the resize using an actual density
+ * measurement based on counting the used array entries.
+ */
+
+ DUK_DDD(DUK_DDDPRINT("write to new array requires array resize, decide whether to do a "
+ "fast resize without abandon check (arr_idx=%ld, old_size=%ld)",
+ (long) arr_idx,
+ (long) DUK_HOBJECT_GET_ASIZE(obj)));
+
+ if (DUK_UNLIKELY(duk__abandon_array_check(thr, arr_idx, obj) != 0)) {
+ DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
+ return NULL;
+ }
+
+ DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
+ "decided to extend current allocation"));
+
+ /* In principle it's possible to run out of memory extending the
+ * array but with the allocation going through if we were to abandon
+ * the array part and try again. In practice this should be rare
+ * because abandoned arrays have a higher per-entry footprint.
+ */
+
+ duk__grow_props_for_array_item(thr, obj, arr_idx);
+
+ DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(obj));
+ DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
+ return DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
+}
+
+DUK_LOCAL DUK_INLINE duk_tval *duk__obtain_arridx_slot(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj) {
+ if (DUK_LIKELY(arr_idx < DUK_HOBJECT_GET_ASIZE(obj))) {
+ return DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
+ } else {
+ return duk__obtain_arridx_slot_slowpath(thr, arr_idx, obj);
+ }
}
/*
@@ -53471,7 +58411,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_proxy_check(duk_hobject *obj, duk_hobject **
return 0;
}
h_proxy = (duk_hproxy *) obj;
- DUK_ASSERT_HPROXY_VALID(h_proxy);
+ DUK_HPROXY_ASSERT_VALID(h_proxy);
DUK_ASSERT(h_proxy->handler != NULL);
DUK_ASSERT(h_proxy->target != NULL);
@@ -53480,7 +58420,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_proxy_check(duk_hobject *obj, duk_hobject **
return 1;
}
-#endif /* DUK_USE_ES6_PROXY */
+#endif /* DUK_USE_ES6_PROXY */
/* Get Proxy target object. If the argument is not a Proxy, return it as is.
* If a Proxy is revoked, an error is thrown.
@@ -53498,7 +58438,7 @@ DUK_INTERNAL duk_hobject *duk_hobject_resolve_proxy_target(duk_hobject *obj) {
duk_hproxy *h_proxy;
h_proxy = (duk_hproxy *) obj;
- DUK_ASSERT_HPROXY_VALID(h_proxy);
+ DUK_HPROXY_ASSERT_VALID(h_proxy);
obj = h_proxy->target;
DUK_ASSERT(obj != NULL);
}
@@ -53506,10 +58446,14 @@ DUK_INTERNAL duk_hobject *duk_hobject_resolve_proxy_target(duk_hobject *obj) {
DUK_ASSERT(obj != NULL);
return obj;
}
-#endif /* DUK_USE_ES6_PROXY */
+#endif /* DUK_USE_ES6_PROXY */
#if defined(DUK_USE_ES6_PROXY)
-DUK_LOCAL duk_bool_t duk__proxy_check_prop(duk_hthread *thr, duk_hobject *obj, duk_small_uint_t stridx_trap, duk_tval *tv_key, duk_hobject **out_target) {
+DUK_LOCAL duk_bool_t duk__proxy_check_prop(duk_hthread *thr,
+ duk_hobject *obj,
+ duk_small_uint_t stridx_trap,
+ duk_tval *tv_key,
+ duk_hobject **out_target) {
duk_hobject *h_handler;
DUK_ASSERT(thr != NULL);
@@ -53563,7 +58507,7 @@ DUK_LOCAL duk_bool_t duk__proxy_check_prop(duk_hthread *thr, duk_hobject *obj, d
duk_push_hobject(thr, h_handler);
if (duk_get_prop_stridx_short(thr, -1, stridx_trap)) {
/* -> [ ... handler trap ] */
- duk_insert(thr, -2); /* -> [ ... trap handler ] */
+ duk_insert(thr, -2); /* -> [ ... trap handler ] */
/* stack prepped for func call: [ ... trap handler ] */
return 1;
@@ -53572,7 +58516,7 @@ DUK_LOCAL duk_bool_t duk__proxy_check_prop(duk_hthread *thr, duk_hobject *obj, d
return 0;
}
}
-#endif /* DUK_USE_ES6_PROXY */
+#endif /* DUK_USE_ES6_PROXY */
/*
* Reallocate property allocation, moving properties to the new allocation.
@@ -53627,11 +58571,12 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
DUK_ASSERT(thr != NULL);
DUK_ASSERT(obj != NULL);
- DUK_ASSERT(!abandon_array || new_a_size == 0); /* if abandon_array, new_a_size must be 0 */
- DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || (DUK_HOBJECT_GET_ESIZE(obj) == 0 && DUK_HOBJECT_GET_ASIZE(obj) == 0));
- DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size); /* required to guarantee success of rehashing,
- * intentionally use unadjusted new_e_size
- */
+ DUK_ASSERT(!abandon_array || new_a_size == 0); /* if abandon_array, new_a_size must be 0 */
+ DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL ||
+ (DUK_HOBJECT_GET_ESIZE(obj) == 0 && DUK_HOBJECT_GET_ASIZE(obj) == 0));
+ DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size); /* required to guarantee success of rehashing,
+ * intentionally use unadjusted new_e_size
+ */
DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
@@ -53661,10 +58606,12 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
DUK_DDD(DUK_DDDPRINT("using layout 1, but no need to pad e_size: %ld", (long) new_e_size));
new_e_size_adjusted = new_e_size;
#elif defined(DUK_USE_HOBJECT_LAYOUT_1) && ((DUK_HOBJECT_ALIGN_TARGET == 4) || (DUK_HOBJECT_ALIGN_TARGET == 8))
- new_e_size_adjusted = (new_e_size + (duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U) &
- (~((duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U));
+ new_e_size_adjusted =
+ (new_e_size + (duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U) & (~((duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U));
DUK_DDD(DUK_DDDPRINT("using layout 1, and alignment target is %ld, adjusted e_size: %ld -> %ld",
- (long) DUK_HOBJECT_ALIGN_TARGET, (long) new_e_size, (long) new_e_size_adjusted));
+ (long) DUK_HOBJECT_ALIGN_TARGET,
+ (long) new_e_size,
+ (long) new_e_size_adjusted));
DUK_ASSERT(new_e_size_adjusted >= new_e_size);
#else
#error invalid hobject layout defines
@@ -53674,23 +58621,22 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
* Debug logging after adjustment.
*/
- DUK_DDD(DUK_DDDPRINT("attempt to resize hobject %p props (%ld -> %ld bytes), from {p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld} to "
- "{e_size=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
- (void *) obj,
- (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
- DUK_HOBJECT_GET_ASIZE(obj),
- DUK_HOBJECT_GET_HSIZE(obj)),
- (long) DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size),
- (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
- (long) DUK_HOBJECT_GET_ESIZE(obj),
- (long) DUK_HOBJECT_GET_ENEXT(obj),
- (long) DUK_HOBJECT_GET_ASIZE(obj),
- (long) DUK_HOBJECT_GET_HSIZE(obj),
- (long) new_e_size_adjusted,
- (long) new_a_size,
- (long) new_h_size,
- (long) abandon_array,
- (long) new_e_size));
+ DUK_DDD(DUK_DDDPRINT(
+ "attempt to resize hobject %p props (%ld -> %ld bytes), from {p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld} to "
+ "{e_size=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
+ (void *) obj,
+ (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj), DUK_HOBJECT_GET_ASIZE(obj), DUK_HOBJECT_GET_HSIZE(obj)),
+ (long) DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size),
+ (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
+ (long) DUK_HOBJECT_GET_ESIZE(obj),
+ (long) DUK_HOBJECT_GET_ENEXT(obj),
+ (long) DUK_HOBJECT_GET_ASIZE(obj),
+ (long) DUK_HOBJECT_GET_HSIZE(obj),
+ (long) new_e_size_adjusted,
+ (long) new_a_size,
+ (long) new_h_size,
+ (long) abandon_array,
+ (long) new_e_size));
/*
* Property count check. This is the only point where we ensure that
@@ -53704,7 +58650,18 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
if (new_e_size_adjusted + new_a_size > DUK_HOBJECT_MAX_PROPERTIES) {
DUK_ERROR_ALLOC_FAILED(thr);
+ DUK_WO_NORETURN(return;);
}
+#if defined(DUK_USE_OBJSIZES16)
+ if (new_e_size_adjusted > DUK_UINT16_MAX || new_a_size > DUK_UINT16_MAX) {
+ /* If caller gave us sizes larger than what we can store,
+ * fail memory safely with an internal error rather than
+ * truncating the sizes.
+ */
+ DUK_ERROR_INTERNAL(thr);
+ DUK_WO_NORETURN(return;);
+ }
+#endif
/*
* Compute new alloc size and alloc new area.
@@ -53722,9 +58679,9 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
#endif
prev_ms_base_flags = thr->heap->ms_base_flags;
thr->heap->ms_base_flags |=
- DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* Avoid attempt to compact the current object (all objects really). */
- thr->heap->pf_prevent_count++; /* Avoid finalizers. */
- DUK_ASSERT(thr->heap->pf_prevent_count != 0); /* Wrap. */
+ DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* Avoid attempt to compact the current object (all objects really). */
+ thr->heap->pf_prevent_count++; /* Avoid finalizers. */
+ DUK_ASSERT(thr->heap->pf_prevent_count != 0); /* Wrap. */
new_alloc_size = DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size);
DUK_DDD(DUK_DDDPRINT("new hobject allocation size is %ld", (long) new_alloc_size));
@@ -53737,7 +58694,7 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
/* Alloc may trigger mark-and-sweep but no compaction, and
* cannot throw.
*/
-#if 0 /* XXX: inject test */
+#if 0 /* XXX: inject test */
if (1) {
new_p = NULL;
goto alloc_failed;
@@ -53755,19 +58712,28 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
/* Set up pointers to the new property area: this is hidden behind a macro
* because it is memory layout specific.
*/
- DUK_HOBJECT_P_SET_REALLOC_PTRS(new_p, new_e_k, new_e_pv, new_e_f, new_a, new_h,
- new_e_size_adjusted, new_a_size, new_h_size);
- DUK_UNREF(new_h); /* happens when hash part dropped */
+ DUK_HOBJECT_P_SET_REALLOC_PTRS(new_p,
+ new_e_k,
+ new_e_pv,
+ new_e_f,
+ new_a,
+ new_h,
+ new_e_size_adjusted,
+ new_a_size,
+ new_h_size);
+ DUK_UNREF(new_h); /* happens when hash part dropped */
new_e_next = 0;
/* if new_p == NULL, all of these pointers are NULL */
- DUK_ASSERT((new_p != NULL) ||
- (new_e_k == NULL && new_e_pv == NULL && new_e_f == NULL &&
- new_a == NULL && new_h == NULL));
+ DUK_ASSERT((new_p != NULL) || (new_e_k == NULL && new_e_pv == NULL && new_e_f == NULL && new_a == NULL && new_h == NULL));
DUK_DDD(DUK_DDDPRINT("new alloc size %ld, new_e_k=%p, new_e_pv=%p, new_e_f=%p, new_a=%p, new_h=%p",
- (long) new_alloc_size, (void *) new_e_k, (void *) new_e_pv, (void *) new_e_f,
- (void *) new_a, (void *) new_h));
+ (long) new_alloc_size,
+ (void *) new_e_k,
+ (void *) new_e_pv,
+ (void *) new_e_f,
+ (void *) new_a,
+ (void *) new_h));
/*
* Migrate array part to start of entries if requested.
@@ -53808,8 +58774,7 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
continue;
}
- DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
- new_e_pv != NULL && new_e_f != NULL);
+ DUK_ASSERT(new_p != NULL && new_e_k != NULL && new_e_pv != NULL && new_e_f != NULL);
/*
* Intern key via the valstack to ensure reachability behaves
@@ -53821,7 +58786,7 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
* must be careful.
*/
-#if 0 /* XXX: inject test */
+#if 0 /* XXX: inject test */
if (1) {
goto abandon_error;
}
@@ -53837,7 +58802,7 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
if (key == NULL) {
goto abandon_error;
}
- duk_push_hstring(thr, key); /* keep key reachable for GC etc; guaranteed not to fail */
+ duk_push_hstring(thr, key); /* keep key reachable for GC etc; guaranteed not to fail */
/* Key is now reachable in the valstack, don't INCREF
* the new allocation yet (we'll steal the refcounts
@@ -53845,11 +58810,10 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
*/
new_e_k[new_e_next] = key;
- tv2 = &new_e_pv[new_e_next].v; /* array entries are all plain values */
+ tv2 = &new_e_pv[new_e_next].v; /* array entries are all plain values */
DUK_TVAL_SET_TVAL(tv2, tv1);
- new_e_f[new_e_next] = DUK_PROPDESC_FLAG_WRITABLE |
- DUK_PROPDESC_FLAG_ENUMERABLE |
- DUK_PROPDESC_FLAG_CONFIGURABLE;
+ new_e_f[new_e_next] =
+ DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE;
new_e_next++;
/* Note: new_e_next matches pushed temp key count, and nothing can
@@ -53876,8 +58840,7 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
continue;
}
- DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
- new_e_pv != NULL && new_e_f != NULL);
+ DUK_ASSERT(new_p != NULL && new_e_k != NULL && new_e_pv != NULL && new_e_f != NULL);
new_e_k[new_e_next] = key;
new_e_pv[new_e_next] = DUK_HOBJECT_E_GET_VALUE(thr->heap, obj, i);
@@ -53907,18 +58870,12 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
} else {
array_copy_size = sizeof(duk_tval) * new_a_size;
}
- if (array_copy_size > 0) {
- /* Avoid zero copy with an invalid pointer. If obj->p is NULL,
- * the 'new_a' pointer will be invalid which is not allowed even
- * when copy size is zero.
- */
- DUK_ASSERT(new_a != NULL);
- DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
- DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) > 0);
- DUK_MEMCPY((void *) new_a,
- (const void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj),
- array_copy_size);
- }
+
+ DUK_ASSERT(new_a != NULL || array_copy_size == 0U);
+ DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || array_copy_size == 0U);
+ DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) > 0 || array_copy_size == 0U);
+ duk_memcpy_unsafe((void *) new_a, (const void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj), array_copy_size);
+
for (i = DUK_HOBJECT_GET_ASIZE(obj); i < new_a_size; i++) {
duk_tval *tv = &new_a[i];
DUK_TVAL_SET_UNUSED(tv);
@@ -53943,9 +58900,9 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
/* fill new_h with u32 0xff = UNUSED */
DUK_ASSERT(new_h_size > 0);
- DUK_MEMSET(new_h, 0xff, sizeof(duk_uint32_t) * new_h_size);
+ duk_memset(new_h, 0xff, sizeof(duk_uint32_t) * new_h_size);
- DUK_ASSERT(new_e_next <= new_h_size); /* equality not actually possible */
+ DUK_ASSERT(new_e_next <= new_h_size); /* equality not actually possible */
mask = new_h_size - 1;
for (i = 0; i < new_e_next; i++) {
@@ -53954,10 +58911,10 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
DUK_ASSERT(key != NULL);
j = DUK_HSTRING_GET_HASH(key) & mask;
- step = 1; /* Cache friendly but clustering prone. */
+ step = 1; /* Cache friendly but clustering prone. */
for (;;) {
- DUK_ASSERT(new_h[j] != DUK__HASH_DELETED); /* should never happen */
+ DUK_ASSERT(new_h[j] != DUK__HASH_DELETED); /* should never happen */
if (new_h[j] == DUK__HASH_UNUSED) {
DUK_DDD(DUK_DDDPRINT("rebuild hit %ld -> %ld", (long) j, (long) i));
new_h[j] = (duk_uint32_t) i;
@@ -53970,37 +58927,36 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
}
}
}
-#endif /* DUK_USE_HOBJECT_HASH_PART */
+#endif /* DUK_USE_HOBJECT_HASH_PART */
/*
* Nice debug log.
*/
- DUK_DD(DUK_DDPRINT("resized hobject %p props (%ld -> %ld bytes), from {p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld} to "
- "{p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
- (void *) obj,
- (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
- DUK_HOBJECT_GET_ASIZE(obj),
- DUK_HOBJECT_GET_HSIZE(obj)),
- (long) new_alloc_size,
- (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
- (long) DUK_HOBJECT_GET_ESIZE(obj),
- (long) DUK_HOBJECT_GET_ENEXT(obj),
- (long) DUK_HOBJECT_GET_ASIZE(obj),
- (long) DUK_HOBJECT_GET_HSIZE(obj),
- (void *) new_p,
- (long) new_e_size_adjusted,
- (long) new_e_next,
- (long) new_a_size,
- (long) new_h_size,
- (long) abandon_array,
- (long) new_e_size));
+ DUK_DD(DUK_DDPRINT(
+ "resized hobject %p props (%ld -> %ld bytes), from {p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld} to "
+ "{p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
+ (void *) obj,
+ (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj), DUK_HOBJECT_GET_ASIZE(obj), DUK_HOBJECT_GET_HSIZE(obj)),
+ (long) new_alloc_size,
+ (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
+ (long) DUK_HOBJECT_GET_ESIZE(obj),
+ (long) DUK_HOBJECT_GET_ENEXT(obj),
+ (long) DUK_HOBJECT_GET_ASIZE(obj),
+ (long) DUK_HOBJECT_GET_HSIZE(obj),
+ (void *) new_p,
+ (long) new_e_size_adjusted,
+ (long) new_e_next,
+ (long) new_a_size,
+ (long) new_h_size,
+ (long) abandon_array,
+ (long) new_e_size));
/*
* All done, switch properties ('p') allocation to new one.
*/
- DUK_FREE_CHECKED(thr, DUK_HOBJECT_GET_PROPS(thr->heap, obj)); /* NULL obj->p is OK */
+ DUK_FREE_CHECKED(thr, DUK_HOBJECT_GET_PROPS(thr->heap, obj)); /* NULL obj->p is OK */
DUK_HOBJECT_SET_PROPS(thr->heap, obj, new_p);
DUK_HOBJECT_SET_ESIZE(obj, new_e_size_adjusted);
DUK_HOBJECT_SET_ENEXT(obj, new_e_next);
@@ -54039,11 +58995,11 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
* unwind.
*/
- abandon_error:
- alloc_failed:
+abandon_error:
+alloc_failed:
DUK_D(DUK_DPRINT("object property table resize failed"));
- DUK_FREE_CHECKED(thr, new_p); /* OK for NULL. */
+ DUK_FREE_CHECKED(thr, new_p); /* OK for NULL. */
thr->heap->pf_prevent_count--;
thr->heap->ms_base_flags = prev_ms_base_flags;
@@ -54053,15 +59009,14 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
#endif
DUK_ERROR_ALLOC_FAILED(thr);
+ DUK_WO_NORETURN(return;);
}
/*
* Helpers to resize properties allocation on specific needs.
*/
-DUK_INTERNAL void duk_hobject_resize_entrypart(duk_hthread *thr,
- duk_hobject *obj,
- duk_uint32_t new_e_size) {
+DUK_INTERNAL void duk_hobject_resize_entrypart(duk_hthread *thr, duk_hobject *obj, duk_uint32_t new_e_size) {
duk_uint32_t old_e_size;
duk_uint32_t new_a_size;
duk_uint32_t new_h_size;
@@ -54083,34 +59038,10 @@ DUK_INTERNAL void duk_hobject_resize_entrypart(duk_hthread *thr,
duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
}
-#if 0 /*unused */
-DUK_INTERNAL void duk_hobject_resize_arraypart(duk_hthread *thr,
- duk_hobject *obj,
- duk_uint32_t new_a_size) {
- duk_uint32_t old_a_size;
- duk_uint32_t new_e_size;
- duk_uint32_t new_h_size;
-
- DUK_ASSERT(thr != NULL);
- DUK_ASSERT(obj != NULL);
-
- if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
- return;
- }
- old_a_size = DUK_HOBJECT_GET_ASIZE(obj);
- if (old_a_size > new_a_size) {
- new_a_size = old_a_size;
- }
- new_e_size = DUK_HOBJECT_GET_ESIZE(obj);
- new_h_size = DUK_HOBJECT_GET_HSIZE(obj);
-
- duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
-}
-#endif
-
/* Grow entry part allocation for one additional entry. */
DUK_LOCAL void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject *obj) {
- duk_uint32_t old_e_used; /* actually used, non-NULL entries */
+ duk_uint32_t old_e_used; /* actually used, non-NULL entries */
+ duk_uint32_t new_e_size_minimum;
duk_uint32_t new_e_size;
duk_uint32_t new_a_size;
duk_uint32_t new_h_size;
@@ -54126,6 +59057,7 @@ DUK_LOCAL void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject
*/
old_e_used = duk__count_used_e_keys(thr, obj);
+ new_e_size_minimum = old_e_used + 1;
new_e_size = old_e_used + duk__get_min_grow_e(old_e_used);
#if defined(DUK_USE_HOBJECT_HASH_PART)
new_h_size = duk__get_default_h_size(new_e_size);
@@ -54133,7 +59065,24 @@ DUK_LOCAL void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject
new_h_size = 0;
#endif
new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
- DUK_ASSERT(new_e_size >= old_e_used + 1); /* duk__get_min_grow_e() is always >= 1 */
+
+#if defined(DUK_USE_OBJSIZES16)
+ if (new_e_size > DUK_UINT16_MAX) {
+ new_e_size = DUK_UINT16_MAX;
+ }
+ if (new_h_size > DUK_UINT16_MAX) {
+ new_h_size = DUK_UINT16_MAX;
+ }
+ if (new_a_size > DUK_UINT16_MAX) {
+ new_a_size = DUK_UINT16_MAX;
+ }
+#endif
+ DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size);
+
+ if (!(new_e_size >= new_e_size_minimum)) {
+ DUK_ERROR_ALLOC_FAILED(thr);
+ DUK_WO_NORETURN(return;);
+ }
duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
}
@@ -54142,18 +59091,35 @@ DUK_LOCAL void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject
DUK_LOCAL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx) {
duk_uint32_t new_e_size;
duk_uint32_t new_a_size;
+ duk_uint32_t new_a_size_minimum;
duk_uint32_t new_h_size;
DUK_ASSERT(thr != NULL);
DUK_ASSERT(obj != NULL);
DUK_ASSERT(highest_arr_idx >= DUK_HOBJECT_GET_ASIZE(obj));
- /* minimum new length is highest_arr_idx + 1 */
-
new_e_size = DUK_HOBJECT_GET_ESIZE(obj);
new_h_size = DUK_HOBJECT_GET_HSIZE(obj);
+ new_a_size_minimum = highest_arr_idx + 1;
new_a_size = highest_arr_idx + duk__get_min_grow_a(highest_arr_idx);
- DUK_ASSERT(new_a_size >= highest_arr_idx + 1); /* duk__get_min_grow_a() is always >= 1 */
+ DUK_ASSERT(new_a_size >= highest_arr_idx + 1); /* duk__get_min_grow_a() is always >= 1 */
+
+#if defined(DUK_USE_OBJSIZES16)
+ if (new_e_size > DUK_UINT16_MAX) {
+ new_e_size = DUK_UINT16_MAX;
+ }
+ if (new_h_size > DUK_UINT16_MAX) {
+ new_h_size = DUK_UINT16_MAX;
+ }
+ if (new_a_size > DUK_UINT16_MAX) {
+ new_a_size = DUK_UINT16_MAX;
+ }
+#endif
+
+ if (!(new_a_size >= new_a_size_minimum)) {
+ DUK_ERROR_ALLOC_FAILED(thr);
+ DUK_WO_NORETURN(return;);
+ }
duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
}
@@ -54163,11 +59129,12 @@ DUK_LOCAL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj
* We also compact the entries part while we're at it, although
* this is not strictly required.
*/
-DUK_LOCAL void duk__abandon_array_checked(duk_hthread *thr, duk_hobject *obj) {
+DUK_LOCAL void duk__abandon_array_part(duk_hthread *thr, duk_hobject *obj) {
+ duk_uint32_t new_e_size_minimum;
duk_uint32_t new_e_size;
duk_uint32_t new_a_size;
duk_uint32_t new_h_size;
- duk_uint32_t e_used; /* actually used, non-NULL keys */
+ duk_uint32_t e_used; /* actually used, non-NULL keys */
duk_uint32_t a_used;
duk_uint32_t a_size;
@@ -54183,8 +59150,8 @@ DUK_LOCAL void duk__abandon_array_checked(duk_hthread *thr, duk_hobject *obj) {
* of space right away.
*/
- new_e_size = e_used + a_used;
- new_e_size = new_e_size + duk__get_min_grow_e(new_e_size);
+ new_e_size_minimum = e_used + a_used;
+ new_e_size = new_e_size_minimum + duk__get_min_grow_e(new_e_size_minimum);
new_a_size = 0;
#if defined(DUK_USE_HOBJECT_HASH_PART)
new_h_size = duk__get_default_h_size(new_e_size);
@@ -54192,11 +59159,33 @@ DUK_LOCAL void duk__abandon_array_checked(duk_hthread *thr, duk_hobject *obj) {
new_h_size = 0;
#endif
+#if defined(DUK_USE_OBJSIZES16)
+ if (new_e_size > DUK_UINT16_MAX) {
+ new_e_size = DUK_UINT16_MAX;
+ }
+ if (new_h_size > DUK_UINT16_MAX) {
+ new_h_size = DUK_UINT16_MAX;
+ }
+ if (new_a_size > DUK_UINT16_MAX) {
+ new_a_size = DUK_UINT16_MAX;
+ }
+#endif
+
+ if (!(new_e_size >= new_e_size_minimum)) {
+ DUK_ERROR_ALLOC_FAILED(thr);
+ DUK_WO_NORETURN(return;);
+ }
+
DUK_DD(DUK_DDPRINT("abandon array part for hobject %p, "
"array stats before: e_used=%ld, a_used=%ld, a_size=%ld; "
"resize to e_size=%ld, a_size=%ld, h_size=%ld",
- (void *) obj, (long) e_used, (long) a_used, (long) a_size,
- (long) new_e_size, (long) new_a_size, (long) new_h_size));
+ (void *) obj,
+ (long) e_used,
+ (long) a_used,
+ (long) a_size,
+ (long) new_e_size,
+ (long) new_a_size,
+ (long) new_h_size));
duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 1);
}
@@ -54214,9 +59203,9 @@ DUK_LOCAL void duk__abandon_array_checked(duk_hthread *thr, duk_hobject *obj) {
*/
DUK_INTERNAL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj) {
- duk_uint32_t e_size; /* currently used -> new size */
- duk_uint32_t a_size; /* currently required */
- duk_uint32_t a_used; /* actually used */
+ duk_uint32_t e_size; /* currently used -> new size */
+ duk_uint32_t a_size; /* currently required */
+ duk_uint32_t a_used; /* actually used */
duk_uint32_t h_size;
duk_bool_t abandon_array;
@@ -54235,13 +59224,17 @@ DUK_INTERNAL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj)
DUK_DD(DUK_DDPRINT("compacting hobject, used e keys %ld, used a keys %ld, min a size %ld, "
"resized array density would be: %ld/%ld = %lf",
- (long) e_size, (long) a_used, (long) a_size,
- (long) a_used, (long) a_size,
+ (long) e_size,
+ (long) a_used,
+ (long) a_size,
+ (long) a_used,
+ (long) a_size,
(double) a_used / (double) a_size));
if (duk__abandon_array_density_check(a_used, a_size)) {
DUK_DD(DUK_DDPRINT("decided to abandon array during compaction, a_used=%ld, a_size=%ld",
- (long) a_used, (long) a_size));
+ (long) a_used,
+ (long) a_size));
abandon_array = 1;
e_size += a_used;
a_size = 0;
@@ -54261,7 +59254,10 @@ DUK_INTERNAL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj)
#endif
DUK_DD(DUK_DDPRINT("compacting hobject -> new e_size %ld, new a_size=%ld, new h_size=%ld, abandon_array=%ld",
- (long) e_size, (long) a_size, (long) h_size, (long) abandon_array));
+ (long) e_size,
+ (long) a_size,
+ (long) h_size,
+ (long) abandon_array));
duk_hobject_realloc_props(thr, obj, e_size, a_size, h_size, abandon_array);
}
@@ -54276,15 +59272,15 @@ DUK_INTERNAL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj)
* but there is no hash part, h_idx is set to -1.
*/
-DUK_INTERNAL duk_bool_t duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx) {
+DUK_INTERNAL duk_bool_t
+duk_hobject_find_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx) {
DUK_ASSERT(obj != NULL);
DUK_ASSERT(key != NULL);
DUK_ASSERT(e_idx != NULL);
DUK_ASSERT(h_idx != NULL);
DUK_UNREF(heap);
- if (DUK_LIKELY(DUK_HOBJECT_GET_HSIZE(obj) == 0))
- {
+ if (DUK_LIKELY(DUK_HOBJECT_GET_HSIZE(obj) == 0)) {
/* Linear scan: more likely because most objects are small.
* This is an important fast path.
*
@@ -54293,7 +59289,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_find_existing_entry(duk_heap *heap, duk_hobj
duk_uint_fast32_t i;
duk_uint_fast32_t n;
duk_hstring **h_keys_base;
- DUK_DDD(DUK_DDDPRINT("duk_hobject_find_existing_entry() using linear scan for lookup"));
+ DUK_DDD(DUK_DDDPRINT("duk_hobject_find_entry() using linear scan for lookup"));
h_keys_base = DUK_HOBJECT_E_GET_KEY_BASE(heap, obj);
n = DUK_HOBJECT_GET_ENEXT(obj);
@@ -54306,61 +59302,58 @@ DUK_INTERNAL duk_bool_t duk_hobject_find_existing_entry(duk_heap *heap, duk_hobj
}
}
#if defined(DUK_USE_HOBJECT_HASH_PART)
- else
- {
+ else {
/* hash lookup */
duk_uint32_t n;
duk_uint32_t i, step;
duk_uint32_t *h_base;
duk_uint32_t mask;
- DUK_DDD(DUK_DDDPRINT("duk_hobject_find_existing_entry() using hash part for lookup"));
+ DUK_DDD(DUK_DDDPRINT("duk_hobject_find_entry() using hash part for lookup"));
h_base = DUK_HOBJECT_H_GET_BASE(heap, obj);
n = DUK_HOBJECT_GET_HSIZE(obj);
mask = n - 1;
i = DUK_HSTRING_GET_HASH(key) & mask;
- step = 1; /* Cache friendly but clustering prone. */
+ step = 1; /* Cache friendly but clustering prone. */
for (;;) {
duk_uint32_t t;
- DUK_ASSERT_DISABLE(i >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(i >= 0); /* unsigned */
DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
t = h_base[i];
DUK_ASSERT(t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED ||
- (t < DUK_HOBJECT_GET_ESIZE(obj))); /* t >= 0 always true, unsigned */
+ (t < DUK_HOBJECT_GET_ESIZE(obj))); /* t >= 0 always true, unsigned */
if (t == DUK__HASH_UNUSED) {
break;
} else if (t == DUK__HASH_DELETED) {
- DUK_DDD(DUK_DDDPRINT("lookup miss (deleted) i=%ld, t=%ld",
- (long) i, (long) t));
+ DUK_DDD(DUK_DDDPRINT("lookup miss (deleted) i=%ld, t=%ld", (long) i, (long) t));
} else {
DUK_ASSERT(t < DUK_HOBJECT_GET_ESIZE(obj));
if (DUK_HOBJECT_E_GET_KEY(heap, obj, t) == key) {
- DUK_DDD(DUK_DDDPRINT("lookup hit i=%ld, t=%ld -> key %p",
- (long) i, (long) t, (void *) key));
+ DUK_DDD(
+ DUK_DDDPRINT("lookup hit i=%ld, t=%ld -> key %p", (long) i, (long) t, (void *) key));
*e_idx = (duk_int_t) t;
*h_idx = (duk_int_t) i;
return 1;
}
- DUK_DDD(DUK_DDDPRINT("lookup miss i=%ld, t=%ld",
- (long) i, (long) t));
+ DUK_DDD(DUK_DDDPRINT("lookup miss i=%ld, t=%ld", (long) i, (long) t));
}
i = (i + step) & mask;
/* Guaranteed to finish (hash is larger than #props). */
}
}
-#endif /* DUK_USE_HOBJECT_HASH_PART */
+#endif /* DUK_USE_HOBJECT_HASH_PART */
/* Not found, leave e_idx and h_idx unset. */
return 0;
}
/* For internal use: get non-accessor entry value */
-DUK_INTERNAL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key) {
+DUK_INTERNAL duk_tval *duk_hobject_find_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key) {
duk_int_t e_idx;
duk_int_t h_idx;
@@ -54368,7 +59361,7 @@ DUK_INTERNAL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap,
DUK_ASSERT(key != NULL);
DUK_UNREF(heap);
- if (duk_hobject_find_existing_entry(heap, obj, key, &e_idx, &h_idx)) {
+ if (duk_hobject_find_entry(heap, obj, key, &e_idx, &h_idx)) {
DUK_ASSERT(e_idx >= 0);
if (!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
@@ -54377,8 +59370,15 @@ DUK_INTERNAL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap,
return NULL;
}
+DUK_INTERNAL duk_tval *duk_hobject_find_entry_tval_ptr_stridx(duk_heap *heap, duk_hobject *obj, duk_small_uint_t stridx) {
+ return duk_hobject_find_entry_tval_ptr(heap, obj, DUK_HEAP_GET_STRING(heap, stridx));
+}
+
/* For internal use: get non-accessor entry value and attributes */
-DUK_INTERNAL duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint_t *out_attrs) {
+DUK_INTERNAL duk_tval *duk_hobject_find_entry_tval_ptr_and_attrs(duk_heap *heap,
+ duk_hobject *obj,
+ duk_hstring *key,
+ duk_uint_t *out_attrs) {
duk_int_t e_idx;
duk_int_t h_idx;
@@ -54387,7 +59387,7 @@ DUK_INTERNAL duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_he
DUK_ASSERT(out_attrs != NULL);
DUK_UNREF(heap);
- if (duk_hobject_find_existing_entry(heap, obj, key, &e_idx, &h_idx)) {
+ if (duk_hobject_find_entry(heap, obj, key, &e_idx, &h_idx)) {
DUK_ASSERT(e_idx >= 0);
if (!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
*out_attrs = DUK_HOBJECT_E_GET_FLAGS(heap, obj, e_idx);
@@ -54399,7 +59399,7 @@ DUK_INTERNAL duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_he
}
/* For internal use: get array part value */
-DUK_INTERNAL duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i) {
+DUK_INTERNAL duk_tval *duk_hobject_find_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i) {
duk_tval *tv;
DUK_ASSERT(obj != NULL);
@@ -54463,14 +59463,15 @@ DUK_LOCAL duk_int_t duk__hobject_alloc_entry_checked(duk_hthread *thr, duk_hobje
n = DUK_HOBJECT_GET_HSIZE(obj);
mask = n - 1;
i = DUK_HSTRING_GET_HASH(key) & mask;
- step = 1; /* Cache friendly but clustering prone. */
+ step = 1; /* Cache friendly but clustering prone. */
for (;;) {
duk_uint32_t t = h_base[i];
if (t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED) {
DUK_DDD(DUK_DDDPRINT("duk__hobject_alloc_entry_checked() inserted key into hash part, %ld -> %ld",
- (long) i, (long) idx));
- DUK_ASSERT_DISABLE(i >= 0); /* unsigned */
+ (long) i,
+ (long) idx));
+ DUK_ASSERT_DISABLE(i >= 0); /* unsigned */
DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
DUK_ASSERT_DISABLE(idx >= 0);
DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
@@ -54483,7 +59484,7 @@ DUK_LOCAL duk_int_t duk__hobject_alloc_entry_checked(duk_hthread *thr, duk_hobje
/* Guaranteed to finish (hash is larger than #props). */
}
}
-#endif /* DUK_USE_HOBJECT_HASH_PART */
+#endif /* DUK_USE_HOBJECT_HASH_PART */
/* Note: we could return the hash index here too, but it's not
* needed right now.
@@ -54502,47 +59503,67 @@ DUK_LOCAL duk_int_t duk__hobject_alloc_entry_checked(duk_hthread *thr, duk_hobje
* to incref OR decref. No proxies or accessors are invoked, no prototype walk.
*/
-DUK_INTERNAL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv_out) {
- duk_int_t e_idx;
- duk_int_t h_idx;
+DUK_INTERNAL duk_tval *duk_hobject_get_internal_value_tval_ptr(duk_heap *heap, duk_hobject *obj) {
+ return duk_hobject_find_entry_tval_ptr_stridx(heap, obj, DUK_STRIDX_INT_VALUE);
+}
+
+DUK_LOCAL duk_heaphdr *duk_hobject_get_internal_value_heaphdr(duk_heap *heap, duk_hobject *obj) {
+ duk_tval *tv;
DUK_ASSERT(heap != NULL);
DUK_ASSERT(obj != NULL);
- DUK_ASSERT(tv_out != NULL);
- /* Always in entry part, no need to look up parents etc. */
- if (duk_hobject_find_existing_entry(heap, obj, DUK_HEAP_STRING_INT_VALUE(heap), &e_idx, &h_idx)) {
- DUK_ASSERT(e_idx >= 0);
- DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx));
- DUK_TVAL_SET_TVAL(tv_out, DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx));
- return 1;
+ tv = duk_hobject_get_internal_value_tval_ptr(heap, obj);
+ if (tv != NULL) {
+ duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
+ DUK_ASSERT(h != NULL);
+ return h;
}
- DUK_TVAL_SET_UNDEFINED(tv_out);
- return 0;
+
+ return NULL;
}
DUK_INTERNAL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj) {
- duk_tval tv;
+ duk_hstring *h;
- DUK_ASSERT(heap != NULL);
- DUK_ASSERT(obj != NULL);
+ h = (duk_hstring *) duk_hobject_get_internal_value_heaphdr(heap, obj);
+ if (h != NULL) {
+ DUK_ASSERT(DUK_HEAPHDR_IS_STRING((duk_heaphdr *) h));
+ }
+ return h;
+}
- /* This is not strictly necessary, but avoids compiler warnings; e.g.
- * gcc won't reliably detect that no uninitialized data is read below.
- */
- DUK_MEMZERO((void *) &tv, sizeof(duk_tval));
+DUK_LOCAL duk_hobject *duk__hobject_get_entry_object_stridx(duk_heap *heap, duk_hobject *obj, duk_small_uint_t stridx) {
+ duk_tval *tv;
+ duk_hobject *h;
- if (duk_hobject_get_internal_value(heap, obj, &tv)) {
- duk_hstring *h;
- DUK_ASSERT(DUK_TVAL_IS_STRING(&tv));
- h = DUK_TVAL_GET_STRING(&tv);
- /* No explicit check for string vs. symbol, accept both. */
+ tv = duk_hobject_find_entry_tval_ptr_stridx(heap, obj, stridx);
+ if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
+ h = DUK_TVAL_GET_OBJECT(tv);
+ DUK_ASSERT(h != NULL);
return h;
}
-
return NULL;
}
+DUK_INTERNAL duk_harray *duk_hobject_get_formals(duk_hthread *thr, duk_hobject *obj) {
+ duk_harray *h;
+
+ h = (duk_harray *) duk__hobject_get_entry_object_stridx(thr->heap, obj, DUK_STRIDX_INT_FORMALS);
+ if (h != NULL) {
+ DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) h));
+ DUK_ASSERT(h->length <= DUK_HOBJECT_GET_ASIZE((duk_hobject *) h));
+ }
+ return h;
+}
+
+DUK_INTERNAL duk_hobject *duk_hobject_get_varmap(duk_hthread *thr, duk_hobject *obj) {
+ duk_hobject *h;
+
+ h = duk__hobject_get_entry_object_stridx(thr->heap, obj, DUK_STRIDX_INT_VARMAP);
+ return h;
+}
+
/*
* Arguments handling helpers (argument map mainly).
*
@@ -54571,8 +59592,12 @@ duk_bool_t duk__lookup_arguments_map(duk_hthread *thr,
DUK_DDD(DUK_DDDPRINT("arguments map lookup: thr=%p, obj=%p, key=%p, temp_desc=%p "
"(obj -> %!O, key -> %!O)",
- (void *) thr, (void *) obj, (void *) key, (void *) temp_desc,
- (duk_heaphdr *) obj, (duk_heaphdr *) key));
+ (void *) thr,
+ (void *) obj,
+ (void *) key,
+ (void *) temp_desc,
+ (duk_heaphdr *) obj,
+ (duk_heaphdr *) key));
if (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
DUK_DDD(DUK_DDDPRINT("-> no 'map'"));
@@ -54581,7 +59606,7 @@ duk_bool_t duk__lookup_arguments_map(duk_hthread *thr,
map = duk_require_hobject(thr, -1);
DUK_ASSERT(map != NULL);
- duk_pop_unsafe(thr); /* map is reachable through obj */
+ duk_pop_unsafe(thr); /* map is reachable through obj */
if (!duk_hobject_get_own_propdesc(thr, map, key, temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
DUK_DDD(DUK_DDDPRINT("-> 'map' exists, but key not in map"));
@@ -54591,29 +59616,32 @@ duk_bool_t duk__lookup_arguments_map(duk_hthread *thr,
/* [... varname] */
DUK_DDD(DUK_DDDPRINT("-> 'map' exists, and contains key, key is mapped to argument/variable binding %!T",
(duk_tval *) duk_get_tval(thr, -1)));
- DUK_ASSERT(duk_is_string(thr, -1)); /* guaranteed when building arguments */
+ DUK_ASSERT(duk_is_string(thr, -1)); /* guaranteed when building arguments */
/* get varenv for varname (callee's declarative lexical environment) */
rc = duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_VARENV(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE);
DUK_UNREF(rc);
- DUK_ASSERT(rc != 0); /* arguments MUST have an initialized lexical environment reference */
+ DUK_ASSERT(rc != 0); /* arguments MUST have an initialized lexical environment reference */
varenv = duk_require_hobject(thr, -1);
DUK_ASSERT(varenv != NULL);
- duk_pop_unsafe(thr); /* varenv remains reachable through 'obj' */
+ duk_pop_unsafe(thr); /* varenv remains reachable through 'obj' */
DUK_DDD(DUK_DDDPRINT("arguments varenv is: %!dO", (duk_heaphdr *) varenv));
/* success: leave varname in stack */
*out_map = map;
*out_varenv = varenv;
- return 1; /* [... varname] */
+ return 1; /* [... varname] */
}
/* Lookup 'key' from arguments internal 'map', and leave replacement value
* on stack top if mapped (and return non-zero).
* Used in E5 Section 10.6 algorithm for [[GetOwnProperty]] (used by [[Get]]).
*/
-DUK_LOCAL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
+DUK_LOCAL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr,
+ duk_hobject *obj,
+ duk_hstring *key,
+ duk_propdesc *temp_desc) {
duk_hobject *map;
duk_hobject *varenv;
duk_hstring *varname;
@@ -54629,7 +59657,7 @@ DUK_LOCAL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobj
varname = duk_require_hstring(thr, -1);
DUK_ASSERT(varname != NULL);
- duk_pop_unsafe(thr); /* varname is still reachable */
+ duk_pop_unsafe(thr); /* varname is still reachable */
DUK_DDD(DUK_DDDPRINT("arguments object automatic getvar for a bound variable; "
"key=%!O, varname=%!O",
@@ -54650,7 +59678,11 @@ DUK_LOCAL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobj
* Used in E5 Section 10.6 algorithm for [[DefineOwnProperty]] (used by [[Put]]).
* Assumes stack top contains 'put' value (which is NOT popped).
*/
-DUK_LOCAL void duk__check_arguments_map_for_put(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc, duk_bool_t throw_flag) {
+DUK_LOCAL void duk__check_arguments_map_for_put(duk_hthread *thr,
+ duk_hobject *obj,
+ duk_hstring *key,
+ duk_propdesc *temp_desc,
+ duk_bool_t throw_flag) {
duk_hobject *map;
duk_hobject *varenv;
duk_hstring *varname;
@@ -54666,7 +59698,7 @@ DUK_LOCAL void duk__check_arguments_map_for_put(duk_hthread *thr, duk_hobject *o
varname = duk_require_hstring(thr, -1);
DUK_ASSERT(varname != NULL);
- duk_pop_unsafe(thr); /* varname is still reachable */
+ duk_pop_unsafe(thr); /* varname is still reachable */
DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
"key=%!O, varname=%!O, value=%!T",
@@ -54705,20 +59737,19 @@ DUK_LOCAL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject
map = duk_require_hobject(thr, -1);
DUK_ASSERT(map != NULL);
- duk_pop_unsafe(thr); /* map is reachable through obj */
+ duk_pop_unsafe(thr); /* map is reachable through obj */
- DUK_DDD(DUK_DDDPRINT("-> have 'map', delete key %!O from map (if exists)); ignore result",
- (duk_heaphdr *) key));
+ DUK_DDD(DUK_DDDPRINT("-> have 'map', delete key %!O from map (if exists)); ignore result", (duk_heaphdr *) key));
/* Note: no recursion issue, we can trust 'map' to behave */
DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(map));
DUK_DDD(DUK_DDDPRINT("map before deletion: %!O", (duk_heaphdr *) map));
- (void) duk_hobject_delprop_raw(thr, map, key, 0); /* ignore result */
+ (void) duk_hobject_delprop_raw(thr, map, key, 0); /* ignore result */
DUK_DDD(DUK_DDDPRINT("map after deletion: %!O", (duk_heaphdr *) map));
}
/*
- * Ecmascript compliant [[GetOwnProperty]](P), for internal use only.
+ * ECMAScript compliant [[GetOwnProperty]](P), for internal use only.
*
* If property is found:
* - Fills descriptor fields to 'out_desc'
@@ -54756,14 +59787,24 @@ DUK_LOCAL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject
* accessor properties later, this would need to change.
*/
-DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_uint32_t arr_idx, duk_propdesc *out_desc, duk_small_uint_t flags) {
+DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr,
+ duk_hobject *obj,
+ duk_hstring *key,
+ duk_uint32_t arr_idx,
+ duk_propdesc *out_desc,
+ duk_small_uint_t flags) {
duk_tval *tv;
DUK_DDD(DUK_DDDPRINT("duk_hobject_get_own_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
"arr_idx=%ld (obj -> %!O, key -> %!O)",
- (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
- (long) flags, (long) arr_idx,
- (duk_heaphdr *) obj, (duk_heaphdr *) key));
+ (void *) thr,
+ (void *) obj,
+ (void *) key,
+ (void *) out_desc,
+ (long) flags,
+ (long) arr_idx,
+ (duk_heaphdr *) obj,
+ (duk_heaphdr *) key));
DUK_ASSERT(thr != NULL);
DUK_ASSERT(thr->heap != NULL);
@@ -54797,7 +59838,7 @@ DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *ob
* same keys so the entry part vs. array part order doesn't matter.
*/
- if (duk_hobject_find_existing_entry(thr->heap, obj, key, &out_desc->e_idx, &out_desc->h_idx)) {
+ if (duk_hobject_find_entry(thr->heap, obj, key, &out_desc->e_idx, &out_desc->h_idx)) {
duk_int_t e_idx = out_desc->e_idx;
DUK_ASSERT(out_desc->e_idx >= 0);
out_desc->a_idx = -1;
@@ -54837,14 +59878,13 @@ DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *ob
duk_push_tval(thr, tv);
}
/* implicit attributes */
- out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
- DUK_PROPDESC_FLAG_CONFIGURABLE |
- DUK_PROPDESC_FLAG_ENUMERABLE;
+ out_desc->flags =
+ DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE | DUK_PROPDESC_FLAG_ENUMERABLE;
out_desc->get = NULL;
out_desc->set = NULL;
out_desc->e_idx = -1;
out_desc->h_idx = -1;
- out_desc->a_idx = (duk_int_t) arr_idx; /* XXX: limit 2G due to being signed */
+ out_desc->a_idx = (duk_int_t) arr_idx; /* XXX: limit 2G due to being signed */
goto prop_found;
}
}
@@ -54865,10 +59905,11 @@ DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *ob
duk_harray *a;
DUK_DDD(DUK_DDDPRINT("array object exotic property get for key: %!O, arr_idx: %ld",
- (duk_heaphdr *) key, (long) arr_idx));
+ (duk_heaphdr *) key,
+ (long) arr_idx));
a = (duk_harray *) obj;
- DUK_ASSERT_HARRAY_VALID(a);
+ DUK_HARRAY_ASSERT_VALID(a);
if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
@@ -54887,11 +59928,12 @@ DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *ob
out_desc->a_idx = -1;
DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
- goto prop_found_noexotic; /* cannot be arguments exotic */
+ goto prop_found_noexotic; /* cannot be arguments exotic */
}
} else if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj)) {
DUK_DDD(DUK_DDDPRINT("string object exotic property get for key: %!O, arr_idx: %ld",
- (duk_heaphdr *) key, (long) arr_idx));
+ (duk_heaphdr *) key,
+ (long) arr_idx));
/* XXX: charlen; avoid multiple lookups? */
@@ -54906,9 +59948,9 @@ DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *ob
DUK_DDD(DUK_DDDPRINT("-> found, array index inside string"));
if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
duk_push_hstring(thr, h_val);
- duk_substring(thr, -1, arr_idx, arr_idx + 1); /* [str] -> [substr] */
+ duk_substring(thr, -1, arr_idx, arr_idx + 1); /* [str] -> [substr] */
}
- out_desc->flags = DUK_PROPDESC_FLAG_ENUMERABLE | /* E5 Section 15.5.5.2 */
+ out_desc->flags = DUK_PROPDESC_FLAG_ENUMERABLE | /* E5 Section 15.5.5.2 */
DUK_PROPDESC_FLAG_VIRTUAL;
out_desc->get = NULL;
out_desc->set = NULL;
@@ -54917,7 +59959,7 @@ DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *ob
out_desc->a_idx = -1;
DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
- goto prop_found_noexotic; /* cannot be arguments exotic */
+ goto prop_found_noexotic; /* cannot be arguments exotic */
} else {
/* index is above internal string length -> property is fully normal */
DUK_DDD(DUK_DDDPRINT("array index outside string -> normal property"));
@@ -54932,7 +59974,7 @@ DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *ob
if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
duk_push_uint(thr, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_val));
}
- out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL; /* E5 Section 15.5.5.1 */
+ out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL; /* E5 Section 15.5.5.1 */
out_desc->get = NULL;
out_desc->set = NULL;
out_desc->e_idx = -1;
@@ -54940,7 +59982,7 @@ DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *ob
out_desc->a_idx = -1;
DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
- goto prop_found_noexotic; /* cannot be arguments exotic */
+ goto prop_found_noexotic; /* cannot be arguments exotic */
}
}
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
@@ -54950,9 +59992,8 @@ DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *ob
duk_small_uint_t elem_size;
h_bufobj = (duk_hbufobj *) obj;
- DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
- DUK_DDD(DUK_DDDPRINT("bufobj property get for key: %!O, arr_idx: %ld",
- (duk_heaphdr *) key, (long) arr_idx));
+ DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
+ DUK_DDD(DUK_DDDPRINT("bufobj property get for key: %!O, arr_idx: %ld", (duk_heaphdr *) key, (long) arr_idx));
if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
DUK_DDD(DUK_DDDPRINT("array index exists"));
@@ -54961,21 +60002,22 @@ DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *ob
* length downshift won't.
*/
if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) {
- byte_off = arr_idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
+ byte_off = arr_idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
duk_uint8_t *data;
- if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
- data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
+ if (h_bufobj->buf != NULL &&
+ DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
+ data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) +
+ h_bufobj->offset + byte_off;
duk_hbufobj_push_validated_read(thr, h_bufobj, data, elem_size);
} else {
DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (read zero)"));
duk_push_uint(thr, 0);
}
}
- out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
- DUK_PROPDESC_FLAG_VIRTUAL;
+ out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_VIRTUAL;
if (DUK_HOBJECT_GET_CLASS_NUMBER(obj) != DUK_HOBJECT_CLASS_ARRAYBUFFER) {
/* ArrayBuffer indices are non-standard and are
* non-enumerable to avoid their serialization.
@@ -54989,7 +60031,8 @@ DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *ob
out_desc->a_idx = -1;
DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
- goto prop_found_noexotic; /* cannot be e.g. arguments exotic, since exotic 'traits' are mutually exclusive */
+ goto prop_found_noexotic; /* cannot be e.g. arguments exotic, since exotic 'traits' are mutually
+ exclusive */
} else {
/* index is above internal buffer length -> property is fully normal */
DUK_DDD(DUK_DDDPRINT("array index outside buffer -> normal property"));
@@ -55011,10 +60054,10 @@ DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *ob
out_desc->a_idx = -1;
DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
- goto prop_found_noexotic; /* cannot be arguments exotic */
+ goto prop_found_noexotic; /* cannot be arguments exotic */
}
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/* Array properties have exotic behavior but they are concrete,
* so no special handling here.
@@ -55028,7 +60071,7 @@ DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *ob
* Not found as concrete or virtual.
*/
- prop_not_found:
+prop_not_found:
DUK_DDD(DUK_DDDPRINT("-> not found (virtual, entry part, or array part)"));
DUK_STATS_INC(thr->heap, stats_getownpropdesc_miss);
return 0;
@@ -55040,7 +60083,7 @@ DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *ob
* description of [[GetOwnProperty]] variant for arguments.
*/
- prop_found:
+prop_found:
DUK_DDD(DUK_DDDPRINT("-> property found, checking for arguments exotic post-behavior"));
/* Notes:
@@ -55050,8 +60093,7 @@ DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *ob
* DUK_GETDESC_FLAG_PUSH_VALUE is not set.
*/
- if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
- arr_idx != DUK__NO_ARRAY_INDEX &&
+ if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) && arr_idx != DUK__NO_ARRAY_INDEX &&
(flags & DUK_GETDESC_FLAG_PUSH_VALUE))) {
duk_propdesc temp_desc;
@@ -55077,12 +60119,13 @@ DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *ob
}
}
- prop_found_noexotic:
+prop_found_noexotic:
DUK_STATS_INC(thr->heap, stats_getownpropdesc_hit);
return 1;
}
-DUK_INTERNAL duk_bool_t duk_hobject_get_own_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags) {
+DUK_INTERNAL duk_bool_t
+duk_hobject_get_own_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags) {
DUK_ASSERT(thr != NULL);
DUK_ASSERT(obj != NULL);
DUK_ASSERT(key != NULL);
@@ -55093,7 +60136,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_get_own_propdesc(duk_hthread *thr, duk_hobje
}
/*
- * Ecmascript compliant [[GetProperty]](P), for internal use only.
+ * ECMAScript compliant [[GetProperty]](P), for internal use only.
*
* If property is found:
* - Fills descriptor fields to 'out_desc'
@@ -55111,7 +60154,8 @@ DUK_INTERNAL duk_bool_t duk_hobject_get_own_propdesc(duk_hthread *thr, duk_hobje
* pointers.
*/
-DUK_LOCAL duk_bool_t duk__get_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags) {
+DUK_LOCAL duk_bool_t
+duk__get_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags) {
duk_hobject *curr;
duk_uint32_t arr_idx;
duk_uint_t sanity;
@@ -55129,9 +60173,14 @@ DUK_LOCAL duk_bool_t duk__get_propdesc(duk_hthread *thr, duk_hobject *obj, duk_h
DUK_DDD(DUK_DDDPRINT("duk__get_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
"arr_idx=%ld (obj -> %!O, key -> %!O)",
- (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
- (long) flags, (long) arr_idx,
- (duk_heaphdr *) obj, (duk_heaphdr *) key));
+ (void *) thr,
+ (void *) obj,
+ (void *) key,
+ (void *) out_desc,
+ (long) flags,
+ (long) arr_idx,
+ (duk_heaphdr *) obj,
+ (duk_heaphdr *) key));
curr = obj;
DUK_ASSERT(curr != NULL);
@@ -55150,6 +60199,7 @@ DUK_LOCAL duk_bool_t duk__get_propdesc(duk_hthread *thr, duk_hobject *obj, duk_h
break;
} else {
DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
+ DUK_WO_NORETURN(return 0;);
}
}
curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
@@ -55190,11 +60240,8 @@ DUK_LOCAL duk_tval *duk__getprop_shallow_fastpath_array_tval(duk_hthread *thr, d
DUK_UNREF(thr);
- if (!(DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
- !DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
- !DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj) &&
- !DUK_HOBJECT_IS_BUFOBJ(obj) &&
- !DUK_HOBJECT_IS_PROXY(obj))) {
+ if (!(DUK_HOBJECT_HAS_ARRAY_PART(obj) && !DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) && !DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj) &&
+ !DUK_HOBJECT_IS_BUFOBJ(obj) && !DUK_HOBJECT_IS_PROXY(obj))) {
/* Must have array part and no conflicting exotic behaviors.
* Doesn't need to have array special behavior, e.g. Arguments
* object has array part.
@@ -55212,7 +60259,7 @@ DUK_LOCAL duk_tval *duk__getprop_shallow_fastpath_array_tval(duk_hthread *thr, d
idx = duk__tval_fastint_to_arr_idx(tv_key);
} else
#endif
- if (DUK_TVAL_IS_DOUBLE(tv_key)) {
+ if (DUK_TVAL_IS_DOUBLE(tv_key)) {
idx = duk__tval_number_to_arr_idx(tv_key);
} else {
DUK_DDD(DUK_DDDPRINT("key is not a number"));
@@ -55246,28 +60293,29 @@ DUK_LOCAL duk_tval *duk__getprop_shallow_fastpath_array_tval(duk_hthread *thr, d
return NULL;
}
-DUK_LOCAL duk_bool_t duk__putprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val) {
+DUK_LOCAL duk_bool_t duk__putprop_shallow_fastpath_array_tval(duk_hthread *thr,
+ duk_hobject *obj,
+ duk_tval *tv_key,
+ duk_tval *tv_val) {
duk_tval *tv;
duk_harray *a;
duk_uint32_t idx;
duk_uint32_t old_len, new_len;
- if (!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj) &&
- DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
- DUK_HOBJECT_HAS_EXTENSIBLE(obj))) {
+ if (!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj) && DUK_HOBJECT_HAS_ARRAY_PART(obj) && DUK_HOBJECT_HAS_EXTENSIBLE(obj))) {
return 0;
}
- DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)); /* caller ensures */
+ DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)); /* caller ensures */
a = (duk_harray *) obj;
- DUK_ASSERT_HARRAY_VALID(a);
+ DUK_HARRAY_ASSERT_VALID(a);
#if defined(DUK_USE_FASTINT)
if (DUK_TVAL_IS_FASTINT(tv_key)) {
idx = duk__tval_fastint_to_arr_idx(tv_key);
} else
#endif
- if (DUK_TVAL_IS_DOUBLE(tv_key)) {
+ if (DUK_TVAL_IS_DOUBLE(tv_key)) {
idx = duk__tval_number_to_arr_idx(tv_key);
} else {
DUK_DDD(DUK_DDDPRINT("key is not a number"));
@@ -55279,7 +60327,7 @@ DUK_LOCAL duk_bool_t duk__putprop_shallow_fastpath_array_tval(duk_hthread *thr,
* because 0xffffffffUL will never be inside object 'a_size'.
*/
- if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) { /* for resizing of array part, use slow path */
+ if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) { /* for resizing of array part, use slow path */
return 0;
}
DUK_ASSERT(idx != 0xffffffffUL);
@@ -55290,7 +60338,8 @@ DUK_LOCAL duk_bool_t duk__putprop_shallow_fastpath_array_tval(duk_hthread *thr,
if (idx >= old_len) {
DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
"(arr_idx=%ld, old_len=%ld)",
- (long) idx, (long) old_len));
+ (long) idx,
+ (long) old_len));
if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
/* The correct behavior here is either a silent error
* or a TypeError, depending on strictness. Fall back
@@ -55304,12 +60353,12 @@ DUK_LOCAL duk_bool_t duk__putprop_shallow_fastpath_array_tval(duk_hthread *thr,
}
tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
- DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects */
+ DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects */
DUK_DDD(DUK_DDDPRINT("array fast path success for index %ld", (long) idx));
return 1;
}
-#endif /* DUK_USE_ARRAY_PROP_FASTPATH */
+#endif /* DUK_USE_ARRAY_PROP_FASTPATH */
/*
* Fast path for bufobj getprop/putprop
@@ -55336,7 +60385,7 @@ DUK_LOCAL duk_bool_t duk__getprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hob
idx = duk__tval_fastint_to_arr_idx(tv_key);
} else
#endif
- if (DUK_TVAL_IS_DOUBLE(tv_key)) {
+ if (DUK_TVAL_IS_DOUBLE(tv_key)) {
idx = duk__tval_number_to_arr_idx(tv_key);
} else {
return 0;
@@ -55353,7 +60402,7 @@ DUK_LOCAL duk_bool_t duk__getprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hob
}
DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
- byte_off = idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
+ byte_off = idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
@@ -55366,7 +60415,7 @@ DUK_LOCAL duk_bool_t duk__getprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hob
return 1;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val) {
@@ -55376,11 +60425,10 @@ DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hob
duk_small_uint_t elem_size;
duk_uint8_t *data;
- if (!(DUK_HOBJECT_IS_BUFOBJ(obj) &&
- DUK_TVAL_IS_NUMBER(tv_val))) {
+ if (!(DUK_HOBJECT_IS_BUFOBJ(obj) && DUK_TVAL_IS_NUMBER(tv_val))) {
return 0;
}
- DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)); /* caller ensures; rom objects are never bufobjs now */
+ DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)); /* caller ensures; rom objects are never bufobjs now */
h_bufobj = (duk_hbufobj *) obj;
if (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
@@ -55392,7 +60440,7 @@ DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hob
idx = duk__tval_fastint_to_arr_idx(tv_key);
} else
#endif
- if (DUK_TVAL_IS_DOUBLE(tv_key)) {
+ if (DUK_TVAL_IS_DOUBLE(tv_key)) {
idx = duk__tval_number_to_arr_idx(tv_key);
} else {
return 0;
@@ -55409,7 +60457,7 @@ DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hob
}
DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
- byte_off = idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
+ byte_off = idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
/* Value is required to be a number in the fast path so there
@@ -55428,10 +60476,10 @@ DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hob
duk_pop_unsafe(thr);
return 1;
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
/*
- * GETPROP: Ecmascript property read.
+ * GETPROP: ECMAScript property read.
*/
DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
@@ -55444,8 +60492,11 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
duk_uint_t sanity;
DUK_DDD(DUK_DDDPRINT("getprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
- (void *) thr, (void *) tv_obj, (void *) tv_key,
- (duk_tval *) tv_obj, (duk_tval *) tv_key));
+ (void *) thr,
+ (void *) tv_obj,
+ (void *) tv_key,
+ (duk_tval *) tv_obj,
+ (duk_tval *) tv_key));
DUK_ASSERT(thr != NULL);
DUK_ASSERT(thr->heap != NULL);
@@ -55482,10 +60533,14 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
#if defined(DUK_USE_PARANOID_ERRORS)
DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
#else
- DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot read property %s of %s",
- duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
+ DUK_ERROR_FMT2(thr,
+ DUK_ERR_TYPE_ERROR,
+ "cannot read property %s of %s",
+ duk_push_string_tval_readable(thr, tv_key),
+ duk_push_string_tval_readable(thr, tv_obj));
#endif
- return 0;
+ DUK_WO_NORETURN(return 0;);
+ break;
}
case DUK_TAG_BOOLEAN: {
@@ -55512,7 +60567,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
pop_count = 0;
} else
#endif
- if (DUK_TVAL_IS_NUMBER(tv_key)) {
+ if (DUK_TVAL_IS_NUMBER(tv_key)) {
arr_idx = duk__tval_number_to_arr_idx(tv_key);
DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path number; arr_idx %ld", (long) arr_idx));
pop_count = 0;
@@ -55521,15 +60576,15 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
DUK_ASSERT(key != NULL);
DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
"coercion key is %!T, arr_idx %ld",
- (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
+ (duk_tval *) duk_get_tval(thr, -1),
+ (long) arr_idx));
pop_count = 1;
}
- if (arr_idx != DUK__NO_ARRAY_INDEX &&
- arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
+ if (arr_idx != DUK__NO_ARRAY_INDEX && arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
duk_pop_n_unsafe(thr, pop_count);
duk_push_hstring(thr, h);
- duk_substring(thr, -1, arr_idx, arr_idx + 1); /* [str] -> [substr] */
+ duk_substring(thr, -1, arr_idx, arr_idx + 1); /* [str] -> [substr] */
DUK_STATS_INC(thr->heap, stats_getprop_stringidx);
DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is an index inside string length "
@@ -55546,12 +60601,13 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
DUK_ASSERT(key != NULL);
DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
"coercion key is %!T, arr_idx %ld",
- (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
+ (duk_tval *) duk_get_tval(thr, -1),
+ (long) arr_idx));
}
if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
- duk_pop_unsafe(thr); /* [key] -> [] */
- duk_push_uint(thr, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h)); /* [] -> [res] */
+ duk_pop_unsafe(thr); /* [key] -> [] */
+ duk_push_uint(thr, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h)); /* [] -> [res] */
DUK_STATS_INC(thr->heap, stats_getprop_stringlen);
DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is 'length' after coercion -> "
@@ -55562,7 +60618,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
- goto lookup; /* avoid double coercion */
+ goto lookup; /* avoid double coercion */
}
case DUK_TAG_OBJECT: {
@@ -55607,9 +60663,9 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
/* -> [ ... trap handler ] */
DUK_DDD(DUK_DDDPRINT("-> proxy object 'get' for key %!T", (duk_tval *) tv_key));
DUK_STATS_INC(thr->heap, stats_getprop_proxy);
- duk_push_hobject(thr, h_target); /* target */
- duk_push_tval(thr, tv_key); /* P */
- duk_push_tval(thr, tv_obj); /* Receiver: Proxy object */
+ duk_push_hobject(thr, h_target); /* target */
+ duk_push_tval(thr, tv_key); /* P */
+ duk_push_tval(thr, tv_obj); /* Receiver: Proxy object */
duk_call_method(thr, 3 /*nargs*/);
/* Target object must be checked for a conflicting
@@ -55619,41 +60675,44 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
DUK_ASSERT(key != NULL);
if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
- duk_tval *tv_hook = duk_require_tval(thr, -3); /* value from hook */
- duk_tval *tv_targ = duk_require_tval(thr, -1); /* value from target */
+ duk_tval *tv_hook = duk_require_tval(thr, -3); /* value from hook */
+ duk_tval *tv_targ = duk_require_tval(thr, -1); /* value from target */
duk_bool_t datadesc_reject;
duk_bool_t accdesc_reject;
DUK_DDD(DUK_DDDPRINT("proxy 'get': target has matching property %!O, check for "
"conflicting property; tv_hook=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
"desc.get=%p, desc.set=%p",
- (duk_heaphdr *) key, (duk_tval *) tv_hook, (duk_tval *) tv_targ,
+ (duk_heaphdr *) key,
+ (duk_tval *) tv_hook,
+ (duk_tval *) tv_targ,
(unsigned long) desc.flags,
- (void *) desc.get, (void *) desc.set));
+ (void *) desc.get,
+ (void *) desc.set));
datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
!(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&
!duk_js_samevalue(tv_hook, tv_targ);
accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
- !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
- (desc.get == NULL) &&
+ !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && (desc.get == NULL) &&
!DUK_TVAL_IS_UNDEFINED(tv_hook);
if (datadesc_reject || accdesc_reject) {
DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
+ DUK_WO_NORETURN(return 0;);
}
duk_pop_2_unsafe(thr);
} else {
duk_pop_unsafe(thr);
}
- return 1; /* return value */
+ return 1; /* return value */
}
- curr = h_target; /* resume lookup from target */
+ curr = h_target; /* resume lookup from target */
DUK_TVAL_SET_OBJECT(tv_obj, curr);
}
-#endif /* DUK_USE_ES6_PROXY */
+#endif /* DUK_USE_ES6_PROXY */
if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(curr)) {
arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
@@ -55668,11 +60727,11 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
/* no need for 'caller' post-check, because 'key' must be an array index */
- duk_remove_m2(thr); /* [key result] -> [result] */
+ duk_remove_m2(thr); /* [key result] -> [result] */
return 1;
}
- goto lookup; /* avoid double coercion */
+ goto lookup; /* avoid double coercion */
}
break;
}
@@ -55694,10 +60753,9 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
pop_count = 0;
- }
- else
+ } else
#endif
- if (DUK_TVAL_IS_NUMBER(tv_key)) {
+ if (DUK_TVAL_IS_NUMBER(tv_key)) {
arr_idx = duk__tval_number_to_arr_idx(tv_key);
DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
pop_count = 0;
@@ -55706,12 +60764,12 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
DUK_ASSERT(key != NULL);
DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
"coercion key is %!T, arr_idx %ld",
- (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
+ (duk_tval *) duk_get_tval(thr, -1),
+ (long) arr_idx));
pop_count = 1;
}
- if (arr_idx != DUK__NO_ARRAY_INDEX &&
- arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
+ if (arr_idx != DUK__NO_ARRAY_INDEX && arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
duk_pop_n_unsafe(thr, pop_count);
duk_push_uint(thr, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h))[arr_idx]);
DUK_STATS_INC(thr->heap, stats_getprop_bufferidx);
@@ -55729,12 +60787,13 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
DUK_ASSERT(key != NULL);
DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
"coercion key is %!T, arr_idx %ld",
- (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
+ (duk_tval *) duk_get_tval(thr, -1),
+ (long) arr_idx));
}
if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
- duk_pop_unsafe(thr); /* [key] -> [] */
- duk_push_uint(thr, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h)); /* [] -> [res] */
+ duk_pop_unsafe(thr); /* [key] -> [] */
+ duk_push_uint(thr, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h)); /* [] -> [res] */
DUK_STATS_INC(thr->heap, stats_getprop_bufferlen);
DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'length' "
@@ -55745,7 +60804,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from Uint8Array prototype"));
curr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
- goto lookup; /* avoid double coercion */
+ goto lookup; /* avoid double coercion */
}
case DUK_TAG_POINTER: {
@@ -55782,7 +60841,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
* Property lookup
*/
- lookup:
+lookup:
/* [key] (coerced) */
DUK_ASSERT(curr != NULL);
DUK_ASSERT(key != NULL);
@@ -55797,25 +60856,23 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
/* accessor with defined getter */
DUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0);
- duk_pop_unsafe(thr); /* [key undefined] -> [key] */
+ duk_pop_unsafe(thr); /* [key undefined] -> [key] */
duk_push_hobject(thr, desc.get);
- duk_push_tval(thr, tv_obj); /* note: original, uncoerced base */
+ duk_push_tval(thr, tv_obj); /* note: original, uncoerced base */
#if defined(DUK_USE_NONSTD_GETTER_KEY_ARGUMENT)
duk_dup_m3(thr);
- duk_call_method(thr, 1); /* [key getter this key] -> [key retval] */
+ duk_call_method(thr, 1); /* [key getter this key] -> [key retval] */
#else
- duk_call_method(thr, 0); /* [key getter this] -> [key retval] */
+ duk_call_method(thr, 0); /* [key getter this] -> [key retval] */
#endif
} else {
/* [key value] or [key undefined] */
/* data property or accessor without getter */
- DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||
- (desc.get == NULL));
+ DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) || (desc.get == NULL));
/* if accessor without getter, return value is undefined */
- DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||
- duk_is_undefined(thr, -1));
+ DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) || duk_is_undefined(thr, -1));
/* Note: for an accessor without getter, falling through to
* check for "caller" exotic behavior is unnecessary as
@@ -55824,14 +60881,15 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
*/
}
- goto found; /* [key result] */
+ goto found; /* [key result] */
- next_in_chain:
+ next_in_chain:
/* XXX: option to pretend property doesn't exist if sanity limit is
* hit might be useful.
*/
if (DUK_UNLIKELY(sanity-- == 0)) {
DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
+ DUK_WO_NORETURN(return 0;);
}
curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
} while (curr != NULL);
@@ -55840,7 +60898,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
* Not found
*/
- duk_to_undefined(thr, -1); /* [key] -> [undefined] (default value) */
+ duk_to_undefined(thr, -1); /* [key] -> [undefined] (default value) */
DUK_DDD(DUK_DDDPRINT("-> %!T (not found)", (duk_tval *) duk_get_tval(thr, -1)));
return 0;
@@ -55849,7 +60907,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
* Found; post-processing (Function and arguments objects)
*/
- found:
+found:
/* [key result] */
#if !defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
@@ -55879,13 +60937,11 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
* This exotic behavior is disabled when the non-standard 'caller' property
* is enabled, as it conflicts with the free use of 'caller'.
*/
- if (key == DUK_HTHREAD_STRING_CALLER(thr) &&
- DUK_TVAL_IS_OBJECT(tv_obj)) {
+ if (key == DUK_HTHREAD_STRING_CALLER(thr) && DUK_TVAL_IS_OBJECT(tv_obj)) {
duk_hobject *orig = DUK_TVAL_GET_OBJECT(tv_obj);
DUK_ASSERT(orig != NULL);
- if (DUK_HOBJECT_IS_NONBOUND_FUNCTION(orig) ||
- DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
+ if (DUK_HOBJECT_IS_NONBOUND_FUNCTION(orig) || DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
duk_hobject *h;
/* XXX: The TypeError is currently not applied to bound
@@ -55896,25 +60952,24 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
*/
DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(orig));
- h = duk_get_hobject(thr, -1); /* NULL if not an object */
- if (h &&
- DUK_HOBJECT_IS_FUNCTION(h) &&
- DUK_HOBJECT_HAS_STRICT(h)) {
+ h = duk_get_hobject(thr, -1); /* NULL if not an object */
+ if (h && DUK_HOBJECT_IS_FUNCTION(h) && DUK_HOBJECT_HAS_STRICT(h)) {
/* XXX: sufficient to check 'strict', assert for 'is function' */
DUK_ERROR_TYPE(thr, DUK_STR_STRICT_CALLER_READ);
+ DUK_WO_NORETURN(return 0;);
}
}
}
-#endif /* !DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
+#endif /* !DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
- duk_remove_m2(thr); /* [key result] -> [result] */
+ duk_remove_m2(thr); /* [key result] -> [result] */
DUK_DDD(DUK_DDDPRINT("-> %!T (found)", (duk_tval *) duk_get_tval(thr, -1)));
return 1;
}
/*
- * HASPROP: Ecmascript property existence check ("in" operator).
+ * HASPROP: ECMAScript property existence check ("in" operator).
*
* Interestingly, the 'in' operator does not do any coercion of
* the target object.
@@ -55929,8 +60984,11 @@ DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj,
duk_propdesc desc;
DUK_DDD(DUK_DDDPRINT("hasprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
- (void *) thr, (void *) tv_obj, (void *) tv_key,
- (duk_tval *) tv_obj, (duk_tval *) tv_key));
+ (void *) thr,
+ (void *) tv_obj,
+ (void *) tv_key,
+ (duk_tval *) tv_obj,
+ (duk_tval *) tv_key));
DUK_ASSERT(thr != NULL);
DUK_ASSERT(thr->heap != NULL);
@@ -55980,6 +61038,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj,
/* Note: unconditional throw */
DUK_DDD(DUK_DDDPRINT("base object is not an object -> reject"));
DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
+ DUK_WO_NORETURN(return 0;);
}
/* XXX: fast path for arrays? */
@@ -56001,47 +61060,51 @@ DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj,
if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_HAS, tv_key, &h_target)) {
/* [ ... key trap handler ] */
DUK_DDD(DUK_DDDPRINT("-> proxy object 'has' for key %!T", (duk_tval *) tv_key));
- duk_push_hobject(thr, h_target); /* target */
- duk_push_tval(thr, tv_key); /* P */
+ duk_push_hobject(thr, h_target); /* target */
+ duk_push_tval(thr, tv_key); /* P */
duk_call_method(thr, 2 /*nargs*/);
- tmp_bool = duk_to_boolean(thr, -1);
+ tmp_bool = duk_to_boolean_top_pop(thr);
if (!tmp_bool) {
/* Target object must be checked for a conflicting
* non-configurable property.
*/
- if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
+ if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push
+ value */
DUK_DDD(DUK_DDDPRINT("proxy 'has': target has matching property %!O, check for "
"conflicting property; desc.flags=0x%08lx, "
"desc.get=%p, desc.set=%p",
- (duk_heaphdr *) key, (unsigned long) desc.flags,
- (void *) desc.get, (void *) desc.set));
+ (duk_heaphdr *) key,
+ (unsigned long) desc.flags,
+ (void *) desc.get,
+ (void *) desc.set));
/* XXX: Extensibility check for target uses IsExtensible(). If we
* implemented the isExtensible trap and didn't reject proxies as
* proxy targets, it should be respected here.
*/
- if (!((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && /* property is configurable and */
- DUK_HOBJECT_HAS_EXTENSIBLE(h_target))) { /* ... target is extensible */
+ if (!((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && /* property is configurable and */
+ DUK_HOBJECT_HAS_EXTENSIBLE(h_target))) { /* ... target is extensible */
DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
+ DUK_WO_NORETURN(return 0;);
}
}
}
- duk_pop_2_unsafe(thr); /* [ key trap_result ] -> [] */
+ duk_pop_unsafe(thr); /* [ key ] -> [] */
return tmp_bool;
}
- obj = h_target; /* resume check from proxy target */
+ obj = h_target; /* resume check from proxy target */
}
-#endif /* DUK_USE_ES6_PROXY */
+#endif /* DUK_USE_ES6_PROXY */
/* XXX: inline into a prototype walking loop? */
- rc = duk__get_propdesc(thr, obj, key, &desc, 0 /*flags*/); /* don't push value */
+ rc = duk__get_propdesc(thr, obj, key, &desc, 0 /*flags*/); /* don't push value */
/* fall through */
- pop_and_return:
- duk_pop_unsafe(thr); /* [ key ] -> [] */
+pop_and_return:
+ duk_pop_unsafe(thr); /* [ key ] -> [] */
return rc;
}
@@ -56067,7 +61130,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *o
DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
- return duk__get_propdesc(thr, obj, key, &dummy, DUK_GETDESC_FLAG_IGNORE_PROTOLOOP); /* don't push value */
+ return duk__get_propdesc(thr, obj, key, &dummy, DUK_GETDESC_FLAG_IGNORE_PROTOLOOP); /* don't push value */
}
/*
@@ -56099,16 +61162,16 @@ DUK_LOCAL duk_uint32_t duk__to_new_array_length_checked(duk_hthread *thr, duk_tv
}
return (duk_uint32_t) fi;
}
-#else /* DUK_USE_FASTINT */
+#else /* DUK_USE_FASTINT */
/* When fastints are not enabled, the most interesting case is any
* number.
*/
if (DUK_TVAL_IS_DOUBLE(tv)) {
d = DUK_TVAL_GET_NUMBER(tv);
}
-#endif /* DUK_USE_FASTINT */
+#endif /* DUK_USE_FASTINT */
else
-#endif /* !DUK_USE_PREFER_SIZE */
+#endif /* !DUK_USE_PREFER_SIZE */
{
/* In all other cases, and when doing a size optimized build,
* fall back to the comprehensive handler.
@@ -56119,16 +61182,16 @@ DUK_LOCAL duk_uint32_t duk__to_new_array_length_checked(duk_hthread *thr, duk_tv
/* Refuse to update an Array's 'length' to a value outside the
* 32-bit range. Negative zero is accepted as zero.
*/
- res = (duk_uint32_t) d;
- if ((duk_double_t) res != d) {
+ res = duk_double_to_uint32_t(d);
+ if (!duk_double_equals((duk_double_t) res, d)) {
goto fail_range;
}
return res;
- fail_range:
+fail_range:
DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARRAY_LENGTH);
- return 0; /* unreachable */
+ DUK_WO_NORETURN(return 0;);
}
/* Delete elements required by a smaller length, taking into account
@@ -56154,7 +61217,8 @@ duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
DUK_DDD(DUK_DDDPRINT("new array length smaller than old (%ld -> %ld), "
"probably need to remove elements",
- (long) old_len, (long) new_len));
+ (long) old_len,
+ (long) new_len));
/*
* New length is smaller than old length, need to delete properties above
@@ -56200,7 +61264,7 @@ duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
while (i > new_len) {
i--;
tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
- DUK_TVAL_SET_UNUSED_UPDREF(thr, tv); /* side effects */
+ DUK_TVAL_SET_UNUSED_UPDREF(thr, tv); /* side effects */
}
*out_result_len = new_len;
@@ -56235,19 +61299,22 @@ duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
continue;
}
- DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key)); /* XXX: macro checks for array index flag, which is unnecessary here */
+ DUK_ASSERT(
+ DUK_HSTRING_HAS_ARRIDX(key)); /* XXX: macro checks for array index flag, which is unnecessary here */
arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
- DUK_ASSERT(arr_idx < old_len); /* consistency requires this */
+ DUK_ASSERT(arr_idx < old_len); /* consistency requires this */
if (arr_idx < new_len) {
DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below new_len",
- (long) i, (long) arr_idx));
+ (long) i,
+ (long) arr_idx));
continue;
}
if (DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)) {
DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is a relevant array index %ld, but configurable",
- (long) i, (long) arr_idx));
+ (long) i,
+ (long) arr_idx));
continue;
}
@@ -56255,17 +61322,19 @@ duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
if (arr_idx >= target_len) {
DUK_DDD(DUK_DDDPRINT("entry at index %ld has arr_idx %ld, is not configurable, "
"update target_len %ld -> %ld",
- (long) i, (long) arr_idx, (long) target_len,
+ (long) i,
+ (long) arr_idx,
+ (long) target_len,
(long) (arr_idx + 1)));
target_len = arr_idx + 1;
}
}
- skip_stage1:
+ skip_stage1:
/* stage 2: delete configurable entries above target length */
- DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld, target_len=%ld",
- (long) old_len, (long) new_len, (long) target_len));
+ DUK_DDD(
+ DUK_DDDPRINT("old_len=%ld, new_len=%ld, target_len=%ld", (long) old_len, (long) new_len, (long) target_len));
DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 2: remove "
"entries >= target_len"));
@@ -56281,20 +61350,21 @@ duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
continue;
}
- DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key)); /* XXX: macro checks for array index flag, which is unnecessary here */
+ DUK_ASSERT(
+ DUK_HSTRING_HAS_ARRIDX(key)); /* XXX: macro checks for array index flag, which is unnecessary here */
arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
- DUK_ASSERT(arr_idx < old_len); /* consistency requires this */
+ DUK_ASSERT(arr_idx < old_len); /* consistency requires this */
if (arr_idx < target_len) {
DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below target_len",
- (long) i, (long) arr_idx));
+ (long) i,
+ (long) arr_idx));
continue;
}
- DUK_ASSERT(force_flag || DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)); /* stage 1 guarantees */
+ DUK_ASSERT(force_flag || DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)); /* stage 1 guarantees */
- DUK_DDD(DUK_DDDPRINT("delete entry index %ld: key is array index %ld",
- (long) i, (long) arr_idx));
+ DUK_DDD(DUK_DDDPRINT("delete entry index %ld: key is array index %ld", (long) i, (long) arr_idx));
/*
* Slow delete, but we don't care as we're already in a very slow path.
@@ -56344,7 +61414,7 @@ DUK_LOCAL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject
DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));
DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(obj));
a = (duk_harray *) obj;
- DUK_ASSERT_HARRAY_VALID(a);
+ DUK_HARRAY_ASSERT_VALID(a);
DUK_ASSERT(duk_is_valid_index(thr, -1));
@@ -56397,9 +61467,9 @@ DUK_LOCAL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject
}
/*
- * PUTPROP: Ecmascript property write.
+ * PUTPROP: ECMAScript property write.
*
- * Unlike Ecmascript primitive which returns nothing, returns 1 to indicate
+ * Unlike ECMAScript primitive which returns nothing, returns 1 to indicate
* success and 0 to indicate failure (assuming throw is not set).
*
* This is an extremely tricky function. Some examples:
@@ -56425,11 +61495,12 @@ DUK_LOCAL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject
* (We currently make a copy of all of the input values to avoid issues.)
*/
-DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag) {
+DUK_INTERNAL duk_bool_t
+duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag) {
duk_tval tv_obj_copy;
duk_tval tv_key_copy;
duk_tval tv_val_copy;
- duk_hobject *orig = NULL; /* NULL if tv_obj is primitive */
+ duk_hobject *orig = NULL; /* NULL if tv_obj is primitive */
duk_hobject *curr;
duk_hstring *key = NULL;
duk_propdesc desc;
@@ -56438,12 +61509,18 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
duk_bool_t rc;
duk_int_t e_idx;
duk_uint_t sanity;
- duk_uint32_t new_array_length = 0; /* 0 = no update */
+ duk_uint32_t new_array_length = 0; /* 0 = no update */
DUK_DDD(DUK_DDDPRINT("putprop: thr=%p, obj=%p, key=%p, val=%p, throw=%ld "
"(obj -> %!T, key -> %!T, val -> %!T)",
- (void *) thr, (void *) tv_obj, (void *) tv_key, (void *) tv_val,
- (long) throw_flag, (duk_tval *) tv_obj, (duk_tval *) tv_key, (duk_tval *) tv_val));
+ (void *) thr,
+ (void *) tv_obj,
+ (void *) tv_key,
+ (void *) tv_val,
+ (long) throw_flag,
+ (duk_tval *) tv_obj,
+ (duk_tval *) tv_key,
+ (duk_tval *) tv_val));
DUK_ASSERT(thr != NULL);
DUK_ASSERT(thr->heap != NULL);
@@ -56478,15 +61555,18 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
case DUK_TAG_UNDEFINED:
case DUK_TAG_NULL: {
/* Note: unconditional throw */
- DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject (object=%!iT)",
- (duk_tval *) tv_obj));
+ DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject (object=%!iT)", (duk_tval *) tv_obj));
#if defined(DUK_USE_PARANOID_ERRORS)
DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
#else
- DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
- duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
+ DUK_ERROR_FMT2(thr,
+ DUK_ERR_TYPE_ERROR,
+ "cannot write property %s of %s",
+ duk_push_string_tval_readable(thr, tv_key),
+ duk_push_string_tval_readable(thr, tv_obj));
#endif
- return 0;
+ DUK_WO_NORETURN(return 0;);
+ break;
}
case DUK_TAG_BOOLEAN: {
@@ -56517,14 +61597,13 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
goto fail_not_writable;
}
- if (arr_idx != DUK__NO_ARRAY_INDEX &&
- arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
+ if (arr_idx != DUK__NO_ARRAY_INDEX && arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
goto fail_not_writable;
}
DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
- goto lookup; /* avoid double coercion */
+ goto lookup; /* avoid double coercion */
}
case DUK_TAG_OBJECT: {
@@ -56539,7 +61618,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
*/
if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
DUK_DD(DUK_DDPRINT("attempt to putprop on read-only target object"));
- goto fail_not_writable_no_pop; /* Must avoid duk_pop() in exit path */
+ goto fail_not_writable_no_pop; /* Must avoid duk_pop() in exit path */
}
#endif
@@ -56585,13 +61664,12 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
/* -> [ ... trap handler ] */
DUK_DDD(DUK_DDDPRINT("-> proxy object 'set' for key %!T", (duk_tval *) tv_key));
DUK_STATS_INC(thr->heap, stats_putprop_proxy);
- duk_push_hobject(thr, h_target); /* target */
- duk_push_tval(thr, tv_key); /* P */
- duk_push_tval(thr, tv_val); /* V */
- duk_push_tval(thr, tv_obj); /* Receiver: Proxy object */
+ duk_push_hobject(thr, h_target); /* target */
+ duk_push_tval(thr, tv_key); /* P */
+ duk_push_tval(thr, tv_val); /* V */
+ duk_push_tval(thr, tv_obj); /* Receiver: Proxy object */
duk_call_method(thr, 4 /*nargs*/);
- tmp_bool = duk_to_boolean(thr, -1);
- duk_pop_nodecref_unsafe(thr);
+ tmp_bool = duk_to_boolean_top_pop(thr);
if (!tmp_bool) {
goto fail_proxy_rejected;
}
@@ -56610,32 +61688,35 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
DUK_DDD(DUK_DDDPRINT("proxy 'set': target has matching property %!O, check for "
"conflicting property; tv_val=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
"desc.get=%p, desc.set=%p",
- (duk_heaphdr *) key, (duk_tval *) tv_val, (duk_tval *) tv_targ,
+ (duk_heaphdr *) key,
+ (duk_tval *) tv_val,
+ (duk_tval *) tv_targ,
(unsigned long) desc.flags,
- (void *) desc.get, (void *) desc.set));
+ (void *) desc.get,
+ (void *) desc.set));
datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
!(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&
!duk_js_samevalue(tv_val, tv_targ);
accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
- !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
- (desc.set == NULL);
+ !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && (desc.set == NULL);
if (datadesc_reject || accdesc_reject) {
DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
+ DUK_WO_NORETURN(return 0;);
}
duk_pop_2_unsafe(thr);
} else {
duk_pop_unsafe(thr);
}
- return 1; /* success */
+ return 1; /* success */
}
- orig = h_target; /* resume write to target */
+ orig = h_target; /* resume write to target */
DUK_TVAL_SET_OBJECT(tv_obj, orig);
}
-#endif /* DUK_USE_ES6_PROXY */
+#endif /* DUK_USE_ES6_PROXY */
curr = orig;
break;
@@ -56657,7 +61738,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
pop_count = 0;
} else
#endif
- if (DUK_TVAL_IS_NUMBER(tv_key)) {
+ if (DUK_TVAL_IS_NUMBER(tv_key)) {
arr_idx = duk__tval_number_to_arr_idx(tv_key);
DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
pop_count = 0;
@@ -56666,12 +61747,12 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
DUK_ASSERT(key != NULL);
DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
"coercion key is %!T, arr_idx %ld",
- (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
+ (duk_tval *) duk_get_tval(thr, -1),
+ (long) arr_idx));
pop_count = 1;
}
- if (arr_idx != DUK__NO_ARRAY_INDEX &&
- arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
+ if (arr_idx != DUK__NO_ARRAY_INDEX && arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
duk_uint8_t *data;
DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
@@ -56683,8 +61764,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
/* Buffer writes are often integers. */
if (DUK_TVAL_IS_FASTINT(tv_val)) {
data[arr_idx] = (duk_uint8_t) DUK_TVAL_GET_FASTINT_U32(tv_val);
- }
- else
+ } else
#endif
{
duk_push_tval(thr, tv_val);
@@ -56706,7 +61786,8 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
DUK_ASSERT(key != NULL);
DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
"coercion key is %!T, arr_idx %ld",
- (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
+ (duk_tval *) duk_get_tval(thr, -1),
+ (long) arr_idx));
}
if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
@@ -56715,7 +61796,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from Uint8Array prototype"));
curr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
- goto lookup; /* avoid double coercion */
+ goto lookup; /* avoid double coercion */
}
case DUK_TAG_POINTER: {
@@ -56750,7 +61831,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
DUK_ASSERT(key != NULL);
- lookup:
+lookup:
/*
* Check whether the property already exists in the prototype chain.
@@ -56763,7 +61844,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
DUK_ASSERT(curr != NULL);
sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
do {
- if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
+ if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
goto next_in_chain;
}
@@ -56786,15 +61867,15 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
goto fail_no_setter;
}
duk_push_hobject(thr, setter);
- duk_push_tval(thr, tv_obj); /* note: original, uncoerced base */
- duk_push_tval(thr, tv_val); /* [key setter this val] */
+ duk_push_tval(thr, tv_obj); /* note: original, uncoerced base */
+ duk_push_tval(thr, tv_val); /* [key setter this val] */
#if defined(DUK_USE_NONSTD_SETTER_KEY_ARGUMENT)
duk_dup_m4(thr);
- duk_call_method(thr, 2); /* [key setter this val key] -> [key retval] */
+ duk_call_method(thr, 2); /* [key setter this val key] -> [key retval] */
#else
- duk_call_method(thr, 1); /* [key setter this val] -> [key retval] */
+ duk_call_method(thr, 1); /* [key setter this val] -> [key retval] */
#endif
- duk_pop_unsafe(thr); /* ignore retval -> [key] */
+ duk_pop_unsafe(thr); /* ignore retval -> [key] */
goto success_no_arguments_exotic;
}
@@ -56814,11 +61895,13 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
* new property to 'orig'.
*/
if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
- DUK_DD(DUK_DDPRINT("found existing inherited plain property, but original object is not extensible"));
+ DUK_DD(
+ DUK_DDPRINT("found existing inherited plain property, but original object is not extensible"));
goto fail_not_extensible;
}
if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
- DUK_DD(DUK_DDPRINT("found existing inherited plain property, original object is extensible, but inherited property is not writable"));
+ DUK_DD(DUK_DDPRINT("found existing inherited plain property, original object is extensible, but "
+ "inherited property is not writable"));
goto fail_not_writable;
}
DUK_DD(DUK_DDPRINT("put to new property, object extensible, inherited property found and is writable"));
@@ -56830,7 +61913,8 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
*/
if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
- DUK_DD(DUK_DDPRINT("found existing own (non-inherited) plain property, but property is not writable"));
+ DUK_DD(
+ DUK_DDPRINT("found existing own (non-inherited) plain property, but property is not writable"));
goto fail_not_writable;
}
if (desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) {
@@ -56847,18 +61931,19 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
* Note: the helper has an unnecessary writability check
* for 'length', we already know it is writable.
*/
- DUK_ASSERT(key == DUK_HTHREAD_STRING_LENGTH(thr)); /* only virtual array property */
+ DUK_ASSERT(key == DUK_HTHREAD_STRING_LENGTH(thr)); /* only virtual array property */
- DUK_DDD(DUK_DDDPRINT("writing existing 'length' property to array exotic, invoke complex helper"));
+ DUK_DDD(DUK_DDDPRINT(
+ "writing existing 'length' property to array exotic, invoke complex helper"));
/* XXX: the helper currently assumes stack top contains new
* 'length' value and the whole calling convention is not very
* compatible with what we need.
*/
- duk_push_tval(thr, tv_val); /* [key val] */
+ duk_push_tval(thr, tv_val); /* [key val] */
rc = duk__handle_put_array_length(thr, orig);
- duk_pop_unsafe(thr); /* [key val] -> [key] */
+ duk_pop_unsafe(thr); /* [key val] -> [key] */
if (!rc) {
goto fail_array_length_partial;
}
@@ -56873,19 +61958,21 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
duk_small_uint_t elem_size;
h_bufobj = (duk_hbufobj *) curr;
- DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+ DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
DUK_DD(DUK_DDPRINT("writable virtual property is in buffer object"));
/* Careful with wrapping: arr_idx upshift may easily wrap, whereas
* length downshift won't.
*/
- if (arr_idx < (h_bufobj->length >> h_bufobj->shift) && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
+ if (arr_idx < (h_bufobj->length >> h_bufobj->shift) &&
+ DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
duk_uint8_t *data;
DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
- DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX); /* index/length check guarantees */
- byte_off = arr_idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
+ DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX); /* index/length check guarantees */
+ byte_off = arr_idx
+ << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
/* Coerce to number before validating pointers etc so that the
@@ -56896,32 +61983,36 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
duk_push_tval(thr, tv_val);
(void) duk_to_number_m1(thr);
- if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
- data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
+ if (h_bufobj->buf != NULL &&
+ DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
+ data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) +
+ h_bufobj->offset + byte_off;
duk_hbufobj_validated_write(thr, h_bufobj, data, elem_size);
} else {
- DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (write skipped)"));
+ DUK_D(DUK_DPRINT(
+ "bufobj access out of underlying buffer, ignoring (write skipped)"));
}
duk_pop_unsafe(thr);
goto success_no_arguments_exotic;
}
}
-#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
+#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
DUK_D(DUK_DPRINT("should not happen, key %!O", key));
- goto fail_internal; /* should not happen */
+ goto fail_internal; /* should not happen */
}
DUK_DD(DUK_DDPRINT("put to existing own plain property, property is writable"));
goto update_old;
}
DUK_UNREACHABLE();
- next_in_chain:
+ next_in_chain:
/* XXX: option to pretend property doesn't exist if sanity limit is
* hit might be useful.
*/
if (DUK_UNLIKELY(sanity-- == 0)) {
DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
+ DUK_WO_NORETURN(return 0;);
}
curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
} while (curr != NULL);
@@ -56944,7 +62035,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
goto create_new;
- update_old:
+update_old:
/*
* Update an existing property of the base object.
@@ -56977,10 +62068,9 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
if (desc.e_idx >= 0) {
tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);
DUK_DDD(DUK_DDDPRINT("previous entry value: %!iT", (duk_tval *) tv));
- DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects; e_idx may be invalidated */
+ DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects; e_idx may be invalidated */
/* don't touch property attributes or hash part */
- DUK_DD(DUK_DDPRINT("put to an existing entry at index %ld -> new value %!iT",
- (long) desc.e_idx, (duk_tval *) tv));
+ DUK_DD(DUK_DDPRINT("put to an existing entry at index %ld -> new value %!iT", (long) desc.e_idx, (duk_tval *) tv));
} else {
/* Note: array entries are always writable, so the writability check
* above is pointless for them. The check could be avoided with some
@@ -56990,9 +62080,10 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
DUK_ASSERT(desc.a_idx >= 0);
tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, desc.a_idx);
DUK_DDD(DUK_DDDPRINT("previous array value: %!iT", (duk_tval *) tv));
- DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects; a_idx may be invalidated */
+ DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects; a_idx may be invalidated */
DUK_DD(DUK_DDPRINT("put to an existing array entry at index %ld -> new value %!iT",
- (long) desc.a_idx, (duk_tval *) tv));
+ (long) desc.a_idx,
+ (duk_tval *) tv));
}
/* Regardless of whether property is found in entry or array part,
@@ -57001,7 +62092,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
*/
goto success_with_arguments_exotic;
- create_new:
+create_new:
/*
* Create a new property in the original object.
@@ -57034,24 +62125,23 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
* from its creation and cannot be deleted, and is thus
* caught as an existing property above.
*/
- DUK_ASSERT(!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
- key == DUK_HTHREAD_STRING_LENGTH(thr)));
+ DUK_ASSERT(!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) && key == DUK_HTHREAD_STRING_LENGTH(thr)));
- if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
- arr_idx != DUK__NO_ARRAY_INDEX) {
+ if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) && arr_idx != DUK__NO_ARRAY_INDEX) {
/* automatic length update */
duk_uint32_t old_len;
duk_harray *a;
a = (duk_harray *) orig;
- DUK_ASSERT_HARRAY_VALID(a);
+ DUK_HARRAY_ASSERT_VALID(a);
old_len = a->length;
if (arr_idx >= old_len) {
DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
"(arr_idx=%ld, old_len=%ld)",
- (long) arr_idx, (long) old_len));
+ (long) arr_idx,
+ (long) old_len));
if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
DUK_DD(DUK_DDPRINT("attempt to extend array, but array 'length' is not writable"));
@@ -57065,15 +62155,16 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
*/
DUK_ASSERT(arr_idx != 0xffffffffUL);
- new_array_length = arr_idx + 1; /* flag for later write */
+ new_array_length = arr_idx + 1; /* flag for later write */
} else {
DUK_DDD(DUK_DDDPRINT("write new array entry does not require length update "
"(arr_idx=%ld, old_len=%ld)",
- (long) arr_idx, (long) old_len));
+ (long) arr_idx,
+ (long) old_len));
}
}
- /* write_to_array_part: */
+ /* write_to_array_part: */
/*
* Write to array part?
@@ -57084,90 +62175,18 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
* tv_obj, tv_key, and tv_val are copies of the original inputs.
*/
- if (arr_idx != DUK__NO_ARRAY_INDEX &&
- DUK_HOBJECT_HAS_ARRAY_PART(orig)) {
- if (arr_idx < DUK_HOBJECT_GET_ASIZE(orig)) {
- goto no_array_growth;
- }
-
- /*
- * Array needs to grow, but we don't want it becoming too sparse.
- * If it were to become sparse, abandon array part, moving all
- * array entries into the entries part (for good).
- *
- * Since we don't keep track of actual density (used vs. size) of
- * the array part, we need to estimate somehow. The check is made
- * in two parts:
- *
- * - Check whether the resize need is small compared to the
- * current size (relatively); if so, resize without further
- * checking (essentially we assume that the original part is
- * "dense" so that the result would be dense enough).
- *
- * - Otherwise, compute the resize using an actual density
- * measurement based on counting the used array entries.
- */
-
- DUK_DDD(DUK_DDDPRINT("write to new array requires array resize, decide whether to do a "
- "fast resize without abandon check (arr_idx=%ld, old_size=%ld)",
- (long) arr_idx, (long) DUK_HOBJECT_GET_ASIZE(orig)));
-
- if (duk__abandon_array_slow_check_required(arr_idx, DUK_HOBJECT_GET_ASIZE(orig))) {
- duk_uint32_t old_used;
- duk_uint32_t old_size;
-
- DUK_DDD(DUK_DDDPRINT("=> fast check is NOT OK, do slow check for array abandon"));
-
- duk__compute_a_stats(thr, orig, &old_used, &old_size);
-
- DUK_DDD(DUK_DDDPRINT("abandon check, array stats: old_used=%ld, old_size=%ld, arr_idx=%ld",
- (long) old_used, (long) old_size, (long) arr_idx));
-
- /* Note: intentionally use approximations to shave a few instructions:
- * a_used = old_used (accurate: old_used + 1)
- * a_size = arr_idx (accurate: arr_idx + 1)
- */
- if (duk__abandon_array_density_check(old_used, arr_idx)) {
- DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
- "decided to abandon array part (would become too sparse)"));
-
- /* abandoning requires a props allocation resize and
- * 'rechecks' the valstack, invalidating any existing
- * valstack value pointers!
- */
- duk__abandon_array_checked(thr, orig);
- DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(orig));
-
- goto write_to_entry_part;
- }
-
- DUK_DDD(DUK_DDDPRINT("=> decided to keep array part"));
- } else {
- DUK_DDD(DUK_DDDPRINT("=> fast resize is OK"));
+ if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(orig)) {
+ tv = duk__obtain_arridx_slot(thr, arr_idx, orig);
+ if (tv == NULL) {
+ DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(orig));
+ goto write_to_entry_part;
}
- DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
- "decided to extend current allocation"));
-
- duk__grow_props_for_array_item(thr, orig, arr_idx);
-
- no_array_growth:
-
- /* Note: assume array part is comprehensive, so that either
- * the write goes to the array part, or we've abandoned the
- * array above (and will not come here).
- */
-
- DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(orig));
- DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(orig));
-
- tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, arr_idx);
/* prev value must be unused, no decref */
DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
DUK_TVAL_SET_TVAL(tv, tv_val);
DUK_TVAL_INCREF(thr, tv);
- DUK_DD(DUK_DDPRINT("put to new array entry: %ld -> %!T",
- (long) arr_idx, (duk_tval *) tv));
+ DUK_DD(DUK_DDPRINT("put to new array entry: %ld -> %!T", (long) arr_idx, (duk_tval *) tv));
/* Note: array part values are [[Writable]], [[Enumerable]],
* and [[Configurable]] which matches the required attributes
@@ -57176,7 +62195,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
goto entry_updated;
}
- write_to_entry_part:
+write_to_entry_part:
/*
* Write to entry part
@@ -57196,7 +62215,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
DUK_HOBJECT_E_SET_FLAGS(thr->heap, orig, e_idx, DUK_PROPDESC_FLAGS_WEC);
goto entry_updated;
- entry_updated:
+entry_updated:
/*
* Possible pending array length update, which must only be done
@@ -57210,8 +62229,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig));
- DUK_DDD(DUK_DDDPRINT("write successful, pending array length update to: %ld",
- (long) new_array_length));
+ DUK_DDD(DUK_DDDPRINT("write successful, pending array length update to: %ld", (long) new_array_length));
((duk_harray *) orig)->length = new_array_length;
}
@@ -57225,7 +62243,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
goto success_no_arguments_exotic;
- success_with_arguments_exotic:
+success_with_arguments_exotic:
/*
* Arguments objects have exotic [[DefineOwnProperty]] which updates
@@ -57240,8 +62258,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
* we end up in step 5.b.i.
*/
- if (arr_idx != DUK__NO_ARRAY_INDEX &&
- DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
+ if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
/* Note: only numbered indices are relevant, so arr_idx fast reject
* is good (this is valid unless there are more than 4**32-1 arguments).
*/
@@ -57260,87 +62277,98 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
}
/* fall thru */
- success_no_arguments_exotic:
+success_no_arguments_exotic:
/* shared exit path now */
DUK_DDD(DUK_DDDPRINT("result: success"));
- duk_pop_unsafe(thr); /* remove key */
+ duk_pop_unsafe(thr); /* remove key */
return 1;
#if defined(DUK_USE_ES6_PROXY)
- fail_proxy_rejected:
+fail_proxy_rejected:
DUK_DDD(DUK_DDDPRINT("result: error, proxy rejects"));
if (throw_flag) {
DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
+ DUK_WO_NORETURN(return 0;);
}
/* Note: no key on stack */
return 0;
#endif
- fail_base_primitive:
+fail_base_primitive:
DUK_DDD(DUK_DDDPRINT("result: error, base primitive"));
if (throw_flag) {
#if defined(DUK_USE_PARANOID_ERRORS)
DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
#else
- DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
- duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
+ DUK_ERROR_FMT2(thr,
+ DUK_ERR_TYPE_ERROR,
+ "cannot write property %s of %s",
+ duk_push_string_tval_readable(thr, tv_key),
+ duk_push_string_tval_readable(thr, tv_obj));
#endif
+ DUK_WO_NORETURN(return 0;);
}
- duk_pop_unsafe(thr); /* remove key */
+ duk_pop_unsafe(thr); /* remove key */
return 0;
- fail_not_extensible:
+fail_not_extensible:
DUK_DDD(DUK_DDDPRINT("result: error, not extensible"));
if (throw_flag) {
DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);
+ DUK_WO_NORETURN(return 0;);
}
- duk_pop_unsafe(thr); /* remove key */
+ duk_pop_unsafe(thr); /* remove key */
return 0;
- fail_not_writable:
+fail_not_writable:
DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
if (throw_flag) {
DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
+ DUK_WO_NORETURN(return 0;);
}
- duk_pop_unsafe(thr); /* remove key */
+ duk_pop_unsafe(thr); /* remove key */
return 0;
#if defined(DUK_USE_ROM_OBJECTS)
- fail_not_writable_no_pop:
+fail_not_writable_no_pop:
DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
if (throw_flag) {
DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
+ DUK_WO_NORETURN(return 0;);
}
return 0;
#endif
- fail_array_length_partial:
+fail_array_length_partial:
DUK_DD(DUK_DDPRINT("result: error, array length write only partially successful"));
if (throw_flag) {
DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
+ DUK_WO_NORETURN(return 0;);
}
- duk_pop_unsafe(thr); /* remove key */
+ duk_pop_unsafe(thr); /* remove key */
return 0;
- fail_no_setter:
+fail_no_setter:
DUK_DDD(DUK_DDDPRINT("result: error, accessor property without setter"));
if (throw_flag) {
DUK_ERROR_TYPE(thr, DUK_STR_SETTER_UNDEFINED);
+ DUK_WO_NORETURN(return 0;);
}
- duk_pop_unsafe(thr); /* remove key */
+ duk_pop_unsafe(thr); /* remove key */
return 0;
- fail_internal:
+fail_internal:
DUK_DDD(DUK_DDDPRINT("result: error, internal"));
if (throw_flag) {
DUK_ERROR_INTERNAL(thr);
+ DUK_WO_NORETURN(return 0;);
}
- duk_pop_unsafe(thr); /* remove key */
+ duk_pop_unsafe(thr); /* remove key */
return 0;
}
/*
- * Ecmascript compliant [[Delete]](P, Throw).
+ * ECMAScript compliant [[Delete]](P, Throw).
*/
DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
@@ -57354,8 +62382,13 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *o
force_flag = (flags & DUK_DELPROP_FLAG_FORCE);
DUK_DDD(DUK_DDDPRINT("delprop_raw: thr=%p, obj=%p, key=%p, throw=%ld, force=%ld (obj -> %!O, key -> %!O)",
- (void *) thr, (void *) obj, (void *) key, (long) throw_flag, (long) force_flag,
- (duk_heaphdr *) obj, (duk_heaphdr *) key));
+ (void *) thr,
+ (void *) obj,
+ (void *) key,
+ (long) throw_flag,
+ (long) force_flag,
+ (duk_heaphdr *) obj,
+ (duk_heaphdr *) key));
DUK_ASSERT(thr != NULL);
DUK_ASSERT(thr->heap != NULL);
@@ -57367,7 +62400,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *o
arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
/* 0 = don't push current value */
- if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
+ if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
DUK_DDD(DUK_DDDPRINT("property not found, succeed always"));
goto success;
}
@@ -57394,7 +62427,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *o
DUK_ASSERT(desc.e_idx < 0);
tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
- DUK_TVAL_SET_UNUSED_UPDREF(thr, tv); /* side effects */
+ DUK_TVAL_SET_UNUSED_UPDREF(thr, tv); /* side effects */
goto success;
} else {
DUK_ASSERT(desc.a_idx < 0);
@@ -57420,7 +62453,9 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *o
* invalidated.
*/
DUK_DDD(DUK_DDDPRINT("before removing value, e_idx %ld, key %p, key at slot %p",
- (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
+ (long) desc.e_idx,
+ (void *) key,
+ (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
DUK_DDD(DUK_DDDPRINT("removing value at e_idx %ld", (long) desc.e_idx));
if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx)) {
duk_hobject *tmp;
@@ -57445,7 +62480,9 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *o
/* Remove key. */
DUK_DDD(DUK_DDDPRINT("before removing key, e_idx %ld, key %p, key at slot %p",
- (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
+ (long) desc.e_idx,
+ (void *) key,
+ (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
DUK_DDD(DUK_DDDPRINT("removing key at e_idx %ld", (long) desc.e_idx));
DUK_ASSERT(key == DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx));
DUK_HOBJECT_E_SET_KEY(thr->heap, obj, desc.e_idx, NULL);
@@ -57461,7 +62498,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *o
DUK_UNREACHABLE();
- success:
+success:
/*
* Argument exotic [[Delete]] behavior (E5 Section 10.6) is
* a post-check, keeping arguments internal 'map' in sync with
@@ -57488,18 +62525,19 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *o
DUK_DDD(DUK_DDDPRINT("delete successful"));
return 1;
- fail_virtual: /* just use the same "not configurable" error message */
- fail_not_configurable:
+fail_virtual: /* just use the same "not configurable" error message */
+fail_not_configurable:
DUK_DDD(DUK_DDDPRINT("delete failed: property found, not configurable"));
if (throw_flag) {
DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
+ DUK_WO_NORETURN(return 0;);
}
return 0;
}
/*
- * DELPROP: Ecmascript property deletion.
+ * DELPROP: ECMAScript property deletion.
*/
DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag) {
@@ -57512,8 +62550,11 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj,
duk_bool_t rc;
DUK_DDD(DUK_DDDPRINT("delprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
- (void *) thr, (void *) tv_obj, (void *) tv_key,
- (duk_tval *) tv_obj, (duk_tval *) tv_key));
+ (void *) thr,
+ (void *) tv_obj,
+ (void *) tv_key,
+ (duk_tval *) tv_obj,
+ (duk_tval *) tv_key));
DUK_ASSERT(thr != NULL);
DUK_ASSERT(thr->heap != NULL);
@@ -57527,8 +62568,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj,
*/
entry_top = duk_get_top(thr);
- if (DUK_TVAL_IS_UNDEFINED(tv_obj) ||
- DUK_TVAL_IS_NULL(tv_obj)) {
+ if (DUK_TVAL_IS_UNDEFINED(tv_obj) || DUK_TVAL_IS_NULL(tv_obj)) {
DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
goto fail_invalid_base_uncond;
}
@@ -57551,13 +62591,12 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj,
if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_DELETE_PROPERTY, tv_key, &h_target)) {
/* -> [ ... obj key trap handler ] */
DUK_DDD(DUK_DDDPRINT("-> proxy object 'deleteProperty' for key %!T", (duk_tval *) tv_key));
- duk_push_hobject(thr, h_target); /* target */
- duk_dup_m4(thr); /* P */
+ duk_push_hobject(thr, h_target); /* target */
+ duk_dup_m4(thr); /* P */
duk_call_method(thr, 2 /*nargs*/);
- tmp_bool = duk_to_boolean(thr, -1);
- duk_pop_nodecref_unsafe(thr);
+ tmp_bool = duk_to_boolean_top_pop(thr);
if (!tmp_bool) {
- goto fail_proxy_rejected; /* retval indicates delete failed */
+ goto fail_proxy_rejected; /* retval indicates delete failed */
}
/* Target object must be checked for a conflicting
@@ -57567,28 +62606,32 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj,
arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
DUK_ASSERT(key != NULL);
- if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
+ if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push
+ value */
duk_small_int_t desc_reject;
DUK_DDD(DUK_DDDPRINT("proxy 'deleteProperty': target has matching property %!O, check for "
"conflicting property; desc.flags=0x%08lx, "
"desc.get=%p, desc.set=%p",
- (duk_heaphdr *) key, (unsigned long) desc.flags,
- (void *) desc.get, (void *) desc.set));
+ (duk_heaphdr *) key,
+ (unsigned long) desc.flags,
+ (void *) desc.get,
+ (void *) desc.set));
desc_reject = !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE);
if (desc_reject) {
/* unconditional */
DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
+ DUK_WO_NORETURN(return 0;);
}
}
- rc = 1; /* success */
+ rc = 1; /* success */
goto done_rc;
}
- obj = h_target; /* resume delete to target */
+ obj = h_target; /* resume delete to target */
}
-#endif /* DUK_USE_ES6_PROXY */
+#endif /* DUK_USE_ES6_PROXY */
arr_idx = duk__to_property_key(thr, -1, &key);
DUK_ASSERT(key != NULL);
@@ -57613,8 +62656,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj,
goto fail_not_configurable;
}
- if (arr_idx != DUK__NO_ARRAY_INDEX &&
- arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
+ if (arr_idx != DUK__NO_ARRAY_INDEX && arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
goto fail_not_configurable;
}
} else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
@@ -57632,8 +62674,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj,
goto fail_not_configurable;
}
- if (arr_idx != DUK__NO_ARRAY_INDEX &&
- arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
+ if (arr_idx != DUK__NO_ARRAY_INDEX && arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
goto fail_not_configurable;
}
} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
@@ -57650,33 +62691,38 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj,
rc = 1;
goto done_rc;
- done_rc:
+done_rc:
duk_set_top_unsafe(thr, entry_top);
return rc;
- fail_invalid_base_uncond:
+fail_invalid_base_uncond:
/* Note: unconditional throw */
DUK_ASSERT(duk_get_top(thr) == entry_top);
#if defined(DUK_USE_PARANOID_ERRORS)
DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
#else
- DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot delete property %s of %s",
- duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
+ DUK_ERROR_FMT2(thr,
+ DUK_ERR_TYPE_ERROR,
+ "cannot delete property %s of %s",
+ duk_push_string_tval_readable(thr, tv_key),
+ duk_push_string_tval_readable(thr, tv_obj));
#endif
- return 0;
+ DUK_WO_NORETURN(return 0;);
#if defined(DUK_USE_ES6_PROXY)
- fail_proxy_rejected:
+fail_proxy_rejected:
if (throw_flag) {
DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
+ DUK_WO_NORETURN(return 0;);
}
duk_set_top_unsafe(thr, entry_top);
return 0;
#endif
- fail_not_configurable:
+fail_not_configurable:
if (throw_flag) {
DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
+ DUK_WO_NORETURN(return 0;);
}
duk_set_top_unsafe(thr, entry_top);
return 0;
@@ -57701,17 +62747,23 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj,
* operations.
*/
-DUK_INTERNAL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
+DUK_INTERNAL void duk_hobject_define_property_internal(duk_hthread *thr,
+ duk_hobject *obj,
+ duk_hstring *key,
+ duk_small_uint_t flags) {
duk_propdesc desc;
duk_uint32_t arr_idx;
duk_int_t e_idx;
duk_tval *tv1 = NULL;
duk_tval *tv2 = NULL;
- duk_small_uint_t propflags = flags & DUK_PROPDESC_FLAGS_MASK; /* mask out flags not actually stored */
+ duk_small_uint_t propflags = flags & DUK_PROPDESC_FLAGS_MASK; /* mask out flags not actually stored */
DUK_DDD(DUK_DDDPRINT("define new property (internal): thr=%p, obj=%!O, key=%!O, flags=0x%02lx, val=%!T",
- (void *) thr, (duk_heaphdr *) obj, (duk_heaphdr *) key,
- (unsigned long) flags, (duk_tval *) duk_get_tval(thr, -1)));
+ (void *) thr,
+ (duk_heaphdr *) obj,
+ (duk_heaphdr *) key,
+ (unsigned long) flags,
+ (duk_tval *) duk_get_tval(thr, -1)));
DUK_ASSERT(thr != NULL);
DUK_ASSERT(thr->heap != NULL);
@@ -57719,11 +62771,11 @@ DUK_INTERNAL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hob
DUK_ASSERT(key != NULL);
DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
- DUK_ASSERT(duk_is_valid_index(thr, -1)); /* contains value */
+ DUK_ASSERT(duk_is_valid_index(thr, -1)); /* contains value */
arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
- if (duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
+ if (duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
if (desc.e_idx >= 0) {
if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> skip as requested"));
@@ -57763,8 +62815,9 @@ DUK_INTERNAL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hob
#endif
new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_NEGIDX(thr, -1));
((duk_harray *) obj)->length = new_len;
- DUK_D(DUK_DPRINT("internal define property for array .length: %ld -> %ld",
- (long) prev_len, (long) ((duk_harray *) obj)->length));
+ DUK_DD(DUK_DDPRINT("internal define property for array .length: %ld -> %ld",
+ (long) prev_len,
+ (long) ((duk_harray *) obj)->length));
goto pop_exit;
}
DUK_DD(DUK_DDPRINT("property already exists but is virtual -> failure"));
@@ -57776,22 +62829,25 @@ DUK_INTERNAL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hob
if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
if (arr_idx != DUK__NO_ARRAY_INDEX) {
- DUK_DDD(DUK_DDDPRINT("property does not exist, object has array part -> possibly extend array part and write value (assert attributes)"));
+ DUK_DDD(DUK_DDDPRINT("property does not exist, object has array part -> possibly extend array part and "
+ "write value (assert attributes)"));
DUK_ASSERT(propflags == DUK_PROPDESC_FLAGS_WEC);
- /* always grow the array, no sparse / abandon support here */
- if (arr_idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
- duk__grow_props_for_array_item(thr, obj, arr_idx);
+ tv1 = duk__obtain_arridx_slot(thr, arr_idx, obj);
+ if (tv1 == NULL) {
+ DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
+ goto write_to_entry_part;
}
- DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
goto write_value;
}
}
- DUK_DDD(DUK_DDDPRINT("property does not exist, object belongs in entry part -> allocate new entry and write value and attributes"));
- e_idx = duk__hobject_alloc_entry_checked(thr, obj, key); /* increases key refcount */
+write_to_entry_part:
+ DUK_DDD(DUK_DDDPRINT(
+ "property does not exist, object belongs in entry part -> allocate new entry and write value and attributes"));
+ e_idx = duk__hobject_alloc_entry_checked(thr, obj, key); /* increases key refcount */
DUK_ASSERT(e_idx >= 0);
DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, propflags);
tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
@@ -57799,24 +62855,23 @@ DUK_INTERNAL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hob
DUK_TVAL_SET_UNDEFINED(tv1);
goto write_value;
- write_value:
+write_value:
/* tv1 points to value storage */
- tv2 = duk_require_tval(thr, -1); /* late lookup, avoid side effects */
- DUK_DDD(DUK_DDDPRINT("writing/updating value: %!T -> %!T",
- (duk_tval *) tv1, (duk_tval *) tv2));
+ tv2 = duk_require_tval(thr, -1); /* late lookup, avoid side effects */
+ DUK_DDD(DUK_DDDPRINT("writing/updating value: %!T -> %!T", (duk_tval *) tv1, (duk_tval *) tv2));
- DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
+ DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
goto pop_exit;
- pop_exit:
- duk_pop_unsafe(thr); /* remove in_val */
+pop_exit:
+ duk_pop_unsafe(thr); /* remove in_val */
return;
- error_virtual: /* share error message */
- error_internal:
+error_virtual: /* share error message */
+error_internal:
DUK_ERROR_INTERNAL(thr);
- return;
+ DUK_WO_NORETURN(return;);
}
/*
@@ -57825,13 +62880,19 @@ DUK_INTERNAL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hob
* must avoid interning.
*/
-DUK_INTERNAL void duk_hobject_define_property_internal_arridx(duk_hthread *thr, duk_hobject *obj, duk_uarridx_t arr_idx, duk_small_uint_t flags) {
+DUK_INTERNAL void duk_hobject_define_property_internal_arridx(duk_hthread *thr,
+ duk_hobject *obj,
+ duk_uarridx_t arr_idx,
+ duk_small_uint_t flags) {
duk_hstring *key;
duk_tval *tv1, *tv2;
DUK_DDD(DUK_DDDPRINT("define new property (internal) arr_idx fast path: thr=%p, obj=%!O, "
"arr_idx=%ld, flags=0x%02lx, val=%!T",
- (void *) thr, obj, (long) arr_idx, (unsigned long) flags,
+ (void *) thr,
+ obj,
+ (long) arr_idx,
+ (unsigned long) flags,
(duk_tval *) duk_get_tval(thr, -1)));
DUK_ASSERT(thr != NULL);
@@ -57839,37 +62900,34 @@ DUK_INTERNAL void duk_hobject_define_property_internal_arridx(duk_hthread *thr,
DUK_ASSERT(obj != NULL);
DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
- if (DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
- arr_idx != DUK__NO_ARRAY_INDEX &&
- flags == DUK_PROPDESC_FLAGS_WEC) {
- DUK_ASSERT((flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) == 0); /* covered by comparison */
+ if (DUK_HOBJECT_HAS_ARRAY_PART(obj) && arr_idx != DUK__NO_ARRAY_INDEX && flags == DUK_PROPDESC_FLAGS_WEC) {
+ DUK_ASSERT((flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) == 0); /* covered by comparison */
DUK_DDD(DUK_DDDPRINT("define property to array part (property may or may not exist yet)"));
- /* always grow the array, no sparse / abandon support here */
- if (arr_idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
- duk__grow_props_for_array_item(thr, obj, arr_idx);
+ tv1 = duk__obtain_arridx_slot(thr, arr_idx, obj);
+ if (tv1 == NULL) {
+ DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
+ goto write_slow;
}
-
- DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
- tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
tv2 = duk_require_tval(thr, -1);
- DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
+ DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
- duk_pop_unsafe(thr); /* [ ...val ] -> [ ... ] */
+ duk_pop_unsafe(thr); /* [ ...val ] -> [ ... ] */
return;
}
+write_slow:
DUK_DDD(DUK_DDDPRINT("define property fast path didn't work, use slow path"));
key = duk_push_uint_to_hstring(thr, (duk_uint_t) arr_idx);
DUK_ASSERT(key != NULL);
- duk_insert(thr, -2); /* [ ... val key ] -> [ ... key val ] */
+ duk_insert(thr, -2); /* [ ... val key ] -> [ ... key val ] */
duk_hobject_define_property_internal(thr, obj, key, flags);
- duk_pop_unsafe(thr); /* [ ... key ] -> [ ... ] */
+ duk_pop_unsafe(thr); /* [ ... key ] -> [ ... ] */
}
/*
@@ -57879,7 +62937,7 @@ DUK_INTERNAL void duk_hobject_define_property_internal_arridx(duk_hthread *thr,
DUK_INTERNAL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj) {
duk_double_t val;
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
DUK_ASSERT(obj != NULL);
/* Fast path for Arrays. */
@@ -57890,13 +62948,11 @@ DUK_INTERNAL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *ob
/* Slow path, .length can be e.g. accessor, obj can be a Proxy, etc. */
duk_push_hobject(thr, obj);
duk_push_hstring_stridx(thr, DUK_STRIDX_LENGTH);
- (void) duk_hobject_getprop(thr,
- DUK_GET_TVAL_NEGIDX(thr, -2),
- DUK_GET_TVAL_NEGIDX(thr, -1));
+ (void) duk_hobject_getprop(thr, DUK_GET_TVAL_NEGIDX(thr, -2), DUK_GET_TVAL_NEGIDX(thr, -1));
val = duk_to_number_m1(thr);
duk_pop_3_unsafe(thr);
- /* This isn't part of Ecmascript semantics; return a value within
+ /* This isn't part of ECMAScript semantics; return a value within
* duk_size_t range, or 0 otherwise.
*/
if (val >= 0.0 && val <= (duk_double_t) DUK_SIZE_MAX) {
@@ -57933,7 +62989,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_hobject *obj) {
DUK_ASSERT(heap != NULL);
obj = DUK_HOBJECT_GET_PROTOTYPE(heap, obj);
#else
- obj = DUK_HOBJECT_GET_PROTOTYPE(NULL, obj); /* 'heap' arg ignored */
+ obj = DUK_HOBJECT_GET_PROTOTYPE(NULL, obj); /* 'heap' arg ignored */
#endif
} while (obj != NULL);
@@ -58000,14 +63056,14 @@ DUK_INTERNAL void duk_hobject_object_get_own_property_descriptor(duk_hthread *th
/* [ ... key value desc ] */
duk_replace(thr, -3);
- duk_pop_unsafe(thr); /* -> [ ... desc ] */
+ duk_pop_unsafe(thr); /* -> [ ... desc ] */
}
/*
* NormalizePropertyDescriptor() related helper.
*
* Internal helper which validates and normalizes a property descriptor
- * represented as an Ecmascript object (e.g. argument to defineProperty()).
+ * represented as an ECMAScript object (e.g. argument to defineProperty()).
* The output of this conversion is a set of defprop_flags and possibly
* some values pushed on the value stack to (1) ensure borrowed pointers
* remain valid, and (2) avoid unnecessary pops for footprint reasons.
@@ -58037,7 +63093,7 @@ void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
DUK_ASSERT(out_idx_value != NULL);
DUK_ASSERT(out_getter != NULL);
DUK_ASSERT(out_setter != NULL);
- DUK_ASSERT(idx_in <= 0x7fffL); /* short variants would be OK, but not used to avoid shifts */
+ DUK_ASSERT(idx_in <= 0x7fffL); /* short variants would be OK, but not used to avoid shifts */
/* Must be an object, otherwise TypeError (E5.1 Section 8.10.5, step 1). */
idx_in = duk_require_normalize_index(thr, idx_in);
@@ -58057,7 +63113,7 @@ void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_WRITABLE)) {
is_data_desc = 1;
- if (duk_to_boolean(thr, -1)) {
+ if (duk_to_boolean_top_pop(thr)) {
defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE;
} else {
defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE;
@@ -58093,7 +63149,7 @@ void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
if (DUK_TVAL_IS_UNDEFINED(tv)) {
/* undefined is accepted */
DUK_ASSERT(setter == NULL);
- } else {
+ } else {
/* NOTE: lightfuncs are coerced to full functions because
* lightfuncs don't fit into a property value slot. This
* has some side effects, see test-dev-lightfunc-accessor.js.
@@ -58109,7 +63165,7 @@ void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
}
if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_ENUMERABLE)) {
- if (duk_to_boolean(thr, -1)) {
+ if (duk_to_boolean_top_pop(thr)) {
defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE;
} else {
defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE;
@@ -58117,7 +63173,7 @@ void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
}
if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_CONFIGURABLE)) {
- if (duk_to_boolean(thr, -1)) {
+ if (duk_to_boolean_top_pop(thr)) {
defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE;
} else {
defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE;
@@ -58136,8 +63192,9 @@ void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
/* [ ... [multiple values] ] */
return;
- type_error:
+type_error:
DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
+ DUK_WO_NORETURN(return;);
}
/*
@@ -58146,7 +63203,7 @@ void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
*
* Inlines all [[DefineOwnProperty]] exotic behaviors.
*
- * Note: Ecmascript compliant [[DefineOwnProperty]](P, Desc, Throw) is not
+ * Note: ECMAScript compliant [[DefineOwnProperty]](P, Desc, Throw) is not
* implemented directly, but Object.defineProperty() serves its purpose.
* We don't need the [[DefineOwnProperty]] internally and we don't have a
* property descriptor with 'missing values' so it's easier to avoid it
@@ -58183,7 +63240,7 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
duk_bool_t force_flag;
duk_small_uint_t new_flags;
duk_propdesc curr;
- duk_uint32_t arridx_new_array_length; /* != 0 => post-update for array 'length' (used when key is an array index) */
+ duk_uint32_t arridx_new_array_length; /* != 0 => post-update for array 'length' (used when key is an array index) */
duk_uint32_t arrlen_old_len;
duk_uint32_t arrlen_new_len;
duk_bool_t pending_write_protect;
@@ -58223,13 +63280,22 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
"has_get=%ld get=%p=%!O "
"has_set=%ld set=%p=%!O "
"arr_idx=%ld throw_flag=!%ld",
- (long) has_enumerable, (long) is_enumerable,
- (long) has_configurable, (long) is_configurable,
- (long) has_writable, (long) is_writable,
- (long) has_value, (duk_tval *) (idx_value >= 0 ? duk_get_tval(thr, idx_value) : NULL),
- (long) has_get, (void *) get, (duk_heaphdr *) get,
- (long) has_set, (void *) set, (duk_heaphdr *) set,
- (long) arr_idx, (long) throw_flag));
+ (long) has_enumerable,
+ (long) is_enumerable,
+ (long) has_configurable,
+ (long) is_configurable,
+ (long) has_writable,
+ (long) is_writable,
+ (long) has_value,
+ (duk_tval *) (idx_value >= 0 ? duk_get_tval(thr, idx_value) : NULL),
+ (long) has_get,
+ (void *) get,
+ (duk_heaphdr *) get,
+ (long) has_set,
+ (void *) set,
+ (duk_heaphdr *) set,
+ (long) arr_idx,
+ (long) throw_flag));
/*
* Array exotic behaviors can be implemented at this point. The local variables
@@ -58257,13 +63323,13 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
*/
a = (duk_harray *) obj;
- DUK_ASSERT_HARRAY_VALID(a);
+ DUK_HARRAY_ASSERT_VALID(a);
arrlen_old_len = a->length;
DUK_ASSERT(idx_value >= 0);
arrlen_new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_POSIDX(thr, idx_value));
duk_push_u32(thr, arrlen_new_len);
- duk_replace(thr, idx_value); /* step 3.e: replace 'Desc.[[Value]]' */
+ duk_replace(thr, idx_value); /* step 3.e: replace 'Desc.[[Value]]' */
DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) arrlen_old_len, (long) arrlen_new_len));
@@ -58298,14 +63364,15 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
duk_harray *a;
a = (duk_harray *) obj;
- DUK_ASSERT_HARRAY_VALID(a);
+ DUK_HARRAY_ASSERT_VALID(a);
old_len = a->length;
if (arr_idx >= old_len) {
DUK_DDD(DUK_DDDPRINT("defineProperty requires array length update "
"(arr_idx=%ld, old_len=%ld)",
- (long) arr_idx, (long) old_len));
+ (long) arr_idx,
+ (long) old_len));
if (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {
/* Array .length is always non-configurable, so
@@ -58323,10 +63390,11 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
} else {
DUK_DDD(DUK_DDDPRINT("defineProperty does not require length update "
"(arr_idx=%ld, old_len=%ld) -> standard behavior",
- (long) arr_idx, (long) old_len));
+ (long) arr_idx,
+ (long) old_len));
}
}
- skip_array_exotic:
+skip_array_exotic:
/* XXX: There is currently no support for writing buffer object
* indexed elements here. Attempt to do so will succeed and
@@ -58378,7 +63446,7 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
DUK_ASSERT(!has_value);
DUK_ASSERT(!has_writable);
- new_flags = DUK_PROPDESC_FLAG_ACCESSOR; /* defaults, E5 Section 8.6.1, Table 7 */
+ new_flags = DUK_PROPDESC_FLAG_ACCESSOR; /* defaults, E5 Section 8.6.1, Table 7 */
if (has_enumerable && is_enumerable) {
new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
}
@@ -58388,7 +63456,7 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
DUK_DDD(DUK_DDDPRINT("accessor cannot go to array part, abandon array"));
- duk__abandon_array_checked(thr, obj);
+ duk__abandon_array_part(thr, obj);
}
/* write to entry part */
@@ -58411,7 +63479,7 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
DUK_ASSERT(!has_set);
DUK_ASSERT(!has_get);
- new_flags = 0; /* defaults, E5 Section 8.6.1, Table 7 */
+ new_flags = 0; /* defaults, E5 Section 8.6.1, Table 7 */
if (has_writable && is_writable) {
new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
}
@@ -58425,22 +63493,28 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
duk_tval *tv_tmp = duk_require_tval(thr, idx_value);
DUK_TVAL_SET_TVAL(&tv, tv_tmp);
} else {
- DUK_TVAL_SET_UNDEFINED(&tv); /* default value */
+ DUK_TVAL_SET_UNDEFINED(&tv); /* default value */
}
if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
-#if 0
- DUK_DDD(DUK_DDDPRINT("new data property attributes match array defaults, attempt to write to array part"));
- /* may become sparse...*/
-#endif
- /* XXX: handling for array part missing now; this doesn't affect
- * compliance but causes array entry writes using defineProperty()
- * to always abandon array part.
- */
+ DUK_DDD(DUK_DDDPRINT(
+ "new data property attributes match array defaults, attempt to write to array part"));
+ tv2 = duk__obtain_arridx_slot(thr, arr_idx, obj);
+ if (tv2 == NULL) {
+ DUK_DDD(DUK_DDDPRINT("failed writing to array part, abandoned array"));
+ } else {
+ DUK_DDD(DUK_DDDPRINT("success in writing to array part"));
+ DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(obj));
+ DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv2));
+ DUK_TVAL_SET_TVAL(tv2, &tv);
+ DUK_TVAL_INCREF(thr, tv2);
+ goto success_exotics;
+ }
+ } else {
+ DUK_DDD(DUK_DDDPRINT("new data property cannot go to array part, abandon array"));
+ duk__abandon_array_part(thr, obj);
}
- DUK_DDD(DUK_DDDPRINT("new data property cannot go to array part, abandon array"));
- duk__abandon_array_checked(thr, obj);
/* fall through */
}
@@ -58498,8 +63572,8 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
goto need_check;
}
- tmp1 = duk_require_tval(thr, -1); /* curr value */
- tmp2 = duk_require_tval(thr, idx_value); /* new value */
+ tmp1 = duk_require_tval(thr, -1); /* curr value */
+ tmp2 = duk_require_tval(thr, idx_value); /* new value */
if (!duk_js_samevalue(tmp1, tmp2)) {
goto need_check;
}
@@ -58544,7 +63618,7 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
*/
goto success_no_exotics;
- need_check:
+need_check:
/*
* Some change(s) need to be made. Steps 7-11.
@@ -58616,9 +63690,10 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
DUK_DDD(DUK_DDDPRINT("convert property to accessor property"));
if (curr.a_idx >= 0) {
- DUK_DDD(DUK_DDDPRINT("property to convert is stored in an array entry, abandon array and re-lookup"));
- duk__abandon_array_checked(thr, obj);
- duk_pop_unsafe(thr); /* remove old value */
+ DUK_DDD(
+ DUK_DDDPRINT("property to convert is stored in an array entry, abandon array and re-lookup"));
+ duk__abandon_array_part(thr, obj);
+ duk_pop_unsafe(thr); /* remove old value */
rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
DUK_UNREF(rc);
DUK_ASSERT(rc != 0);
@@ -58626,14 +63701,14 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
}
if (curr.e_idx < 0) {
DUK_ASSERT(curr.a_idx < 0 && curr.e_idx < 0);
- goto fail_virtual; /* safeguard for virtual property */
+ goto fail_virtual; /* safeguard for virtual property */
}
DUK_ASSERT(curr.e_idx >= 0);
DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
- DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv1); /* XXX: just decref */
+ DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv1); /* XXX: just decref */
DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
@@ -58662,7 +63737,7 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
/* curr is accessor -> cannot be in array part. */
DUK_ASSERT(curr.a_idx < 0);
if (curr.e_idx < 0) {
- goto fail_virtual; /* safeguard; no virtual accessors now */
+ goto fail_virtual; /* safeguard; no virtual accessors now */
}
DUK_DDD(DUK_DDDPRINT("convert property to data property"));
@@ -58694,8 +63769,8 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
}
/* Note: changing from writable to non-writable is OK */
if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_value) {
- duk_tval *tmp1 = duk_require_tval(thr, -1); /* curr value */
- duk_tval *tmp2 = duk_require_tval(thr, idx_value); /* new value */
+ duk_tval *tmp1 = duk_require_tval(thr, -1); /* curr value */
+ duk_tval *tmp2 = duk_require_tval(thr, idx_value); /* new value */
if (!duk_js_samevalue(tmp1, tmp2)) {
goto fail_not_configurable;
}
@@ -58744,8 +63819,7 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
/* XXX: write protect after flag? -> any chance of handling it here? */
- DUK_DDD(DUK_DDDPRINT("new flags that we want to write: 0x%02lx",
- (unsigned long) new_flags));
+ DUK_DDD(DUK_DDDPRINT("new flags that we want to write: 0x%02lx", (unsigned long) new_flags));
/*
* Check whether we need to abandon an array part (if it exists)
@@ -58761,20 +63835,23 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
DUK_DDD(DUK_DDDPRINT("array index, new property attributes match array defaults, update in-place"));
- DUK_ASSERT(curr.flags == DUK_PROPDESC_FLAGS_WEC); /* must have been, since in array part */
+ DUK_ASSERT(curr.flags == DUK_PROPDESC_FLAGS_WEC); /* must have been, since in array part */
DUK_ASSERT(!has_set);
DUK_ASSERT(!has_get);
- DUK_ASSERT(idx_value >= 0); /* must be: if attributes match and we get here the value must differ (otherwise no change) */
+ DUK_ASSERT(
+ idx_value >=
+ 0); /* must be: if attributes match and we get here the value must differ (otherwise no change) */
tv2 = duk_require_tval(thr, idx_value);
tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, curr.a_idx);
- DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects; may invalidate a_idx */
+ DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects; may invalidate a_idx */
goto success_exotics;
}
- DUK_DDD(DUK_DDDPRINT("array index, new property attributes do not match array defaults, abandon array and re-lookup"));
- duk__abandon_array_checked(thr, obj);
- duk_pop_unsafe(thr); /* remove old value */
+ DUK_DDD(
+ DUK_DDDPRINT("array index, new property attributes do not match array defaults, abandon array and re-lookup"));
+ duk__abandon_array_part(thr, obj);
+ duk_pop_unsafe(thr); /* remove old value */
rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
DUK_UNREF(rc);
DUK_ASSERT(rc != 0);
@@ -58798,10 +63875,12 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
duk_harray *a;
a = (duk_harray *) obj;
- DUK_DD(DUK_DDPRINT("Object.defineProperty() attribute update for duk_harray .length -> %02lx", (unsigned long) new_flags));
- DUK_ASSERT_HARRAY_VALID(a);
+ DUK_DD(DUK_DDPRINT("Object.defineProperty() attribute update for duk_harray .length -> %02lx",
+ (unsigned long) new_flags));
+ DUK_HARRAY_ASSERT_VALID(a);
if ((new_flags & DUK_PROPDESC_FLAGS_EC) != (curr.flags & DUK_PROPDESC_FLAGS_EC)) {
- DUK_D(DUK_DPRINT("Object.defineProperty() attempt to change virtual array .length enumerable or configurable attribute, fail"));
+ DUK_D(DUK_DPRINT("Object.defineProperty() attempt to change virtual array .length enumerable or "
+ "configurable attribute, fail"));
goto fail_virtual;
}
if (new_flags & DUK_PROPDESC_FLAG_WRITABLE) {
@@ -58829,7 +63908,7 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
DUK_UNREF(tmp);
DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, set);
DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);
- DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp); /* side effects; may invalidate e_idx */
+ DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp); /* side effects; may invalidate e_idx */
}
if (has_get) {
duk_hobject *tmp;
@@ -58845,7 +63924,7 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
DUK_UNREF(tmp);
DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, get);
DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
- DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp); /* side effects; may invalidate e_idx */
+ DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp); /* side effects; may invalidate e_idx */
}
if (has_value) {
duk_tval *tv1, *tv2;
@@ -58856,9 +63935,9 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
tv2 = duk_require_tval(thr, idx_value);
tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
- DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects; may invalidate e_idx */
+ DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects; may invalidate e_idx */
} else {
- DUK_ASSERT(curr.a_idx < 0); /* array part case handled comprehensively previously */
+ DUK_ASSERT(curr.a_idx < 0); /* array part case handled comprehensively previously */
DUK_DD(DUK_DDPRINT("Object.defineProperty(), value update for virtual property"));
/* XXX: Uint8Array and other typed array virtual writes not currently
@@ -58867,11 +63946,12 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
duk_harray *a;
a = (duk_harray *) obj;
- DUK_DD(DUK_DDPRINT("Object.defineProperty() value update for duk_harray .length -> %ld", (long) arrlen_new_len));
- DUK_ASSERT_HARRAY_VALID(a);
+ DUK_DD(DUK_DDPRINT("Object.defineProperty() value update for duk_harray .length -> %ld",
+ (long) arrlen_new_len));
+ DUK_HARRAY_ASSERT_VALID(a);
a->length = arrlen_new_len;
} else {
- goto fail_virtual; /* should not happen */
+ goto fail_virtual; /* should not happen */
}
}
}
@@ -58888,7 +63968,7 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
* - for 'length' key the element deletion and 'length' update occurs here
*/
- success_exotics:
+success_exotics:
/* curr.a_idx or curr.e_idx may have been invalidated by side effects
* above.
@@ -58900,7 +63980,7 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
duk_harray *a;
a = (duk_harray *) obj;
- DUK_ASSERT_HARRAY_VALID(a);
+ DUK_HARRAY_ASSERT_VALID(a);
if (arridx_new_array_length > 0) {
/*
@@ -58932,7 +64012,8 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
DUK_DDD(DUK_DDDPRINT("defineProperty successful, key is 'length', exotic array behavior, "
"doing array element deletion and length update"));
- rc = duk__handle_put_array_length_smaller(thr, obj, arrlen_old_len, arrlen_new_len, force_flag, &result_len);
+ rc =
+ duk__handle_put_array_length_smaller(thr, obj, arrlen_old_len, arrlen_new_len, force_flag, &result_len);
/* update length (curr points to length, and we assume it's still valid) */
DUK_ASSERT(result_len >= arrlen_new_len && result_len <= arrlen_old_len);
@@ -58955,7 +64036,7 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
duk_hobject *varenv;
DUK_ASSERT(arridx_new_array_length == 0);
- DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)); /* traits are separate; in particular, arguments not an array */
+ DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)); /* traits are separate; in particular, arguments not an array */
map = NULL;
varenv = NULL;
@@ -58972,7 +64053,7 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map' "
"changed to an accessor, delete arguments binding"));
- (void) duk_hobject_delprop_raw(thr, map, key, 0); /* ignore result */
+ (void) duk_hobject_delprop_raw(thr, map, key, 0); /* ignore result */
} else {
/* Note: this order matters (final value before deleting map entry must be done) */
DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
@@ -59000,7 +64081,7 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
"changed to non-writable, delete arguments binding"));
- (void) duk_hobject_delprop_raw(thr, map, key, 0); /* ignore result */
+ (void) duk_hobject_delprop_raw(thr, map, key, 0); /* ignore result */
}
}
@@ -59009,23 +64090,25 @@ duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
*/
}
- success_no_exotics:
+success_no_exotics:
/* Some code paths use NORZ macros for simplicity, ensure refzero
* handling is completed.
*/
DUK_REFZERO_CHECK_SLOW(thr);
return 1;
- fail_not_extensible:
+fail_not_extensible:
if (throw_flag) {
DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);
+ DUK_WO_NORETURN(return 0;);
}
return 0;
- fail_virtual: /* just use the same "not configurable" error message" */
- fail_not_configurable:
+fail_virtual: /* just use the same "not configurable" error message" */
+fail_not_configurable:
if (throw_flag) {
DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
+ DUK_WO_NORETURN(return 0;);
}
return 0;
}
@@ -59047,7 +64130,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_
h_obj = duk_push_this_coercible_to_object(thr);
DUK_ASSERT(h_obj != NULL);
- ret = duk_hobject_get_own_propdesc(thr, h_obj, h_v, &desc, 0 /*flags*/); /* don't push value */
+ ret = duk_hobject_get_own_propdesc(thr, h_obj, h_v, &desc, 0 /*flags*/); /* don't push value */
duk_push_boolean(thr, ret && ((desc.flags & required_desc_flags) == required_desc_flags));
return 1;
@@ -59081,6 +64164,7 @@ DUK_INTERNAL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_ho
if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
DUK_DD(DUK_DDPRINT("attempt to seal/freeze a readonly object, reject"));
DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
+ DUK_WO_NORETURN(return;);
}
#endif
@@ -59091,13 +64175,13 @@ DUK_INTERNAL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_ho
* for the same object; not likely).
*/
- duk__abandon_array_checked(thr, obj);
+ duk__abandon_array_part(thr, obj);
DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) == 0);
for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
duk_uint8_t *fp;
- /* since duk__abandon_array_checked() causes a resize, there should be no gaps in keys */
+ /* since duk__abandon_array_part() causes a resize, there should be no gaps in keys */
DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != NULL);
/* avoid multiple computations of flags address; bypasses macros */
@@ -59111,7 +64195,7 @@ DUK_INTERNAL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_ho
DUK_HOBJECT_CLEAR_EXTENSIBLE(obj);
- /* no need to compact since we already did that in duk__abandon_array_checked()
+ /* no need to compact since we already did that in duk__abandon_array_part()
* (regardless of whether an array part existed or not.
*/
@@ -59160,9 +64244,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *
if (flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
return 0;
}
- if (is_frozen &&
- !(flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
- (flags & DUK_PROPDESC_FLAG_WRITABLE)) {
+ if (is_frozen && !(flags & DUK_PROPDESC_FLAG_ACCESSOR) && (flags & DUK_PROPDESC_FLAG_WRITABLE)) {
return 0;
}
}
@@ -59194,6 +64276,19 @@ DUK_INTERNAL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *
#undef DUK__VALSTACK_PROXY_LOOKUP
#undef DUK__VALSTACK_SPACE
/*
+ * duk_hstring assertion helpers.
+ */
+
+/* #include duk_internal.h -> already included */
+
+#if defined(DUK_USE_ASSERTIONS)
+
+DUK_INTERNAL void duk_hstring_assert_valid(duk_hstring *h) {
+ DUK_ASSERT(h != NULL);
+}
+
+#endif /* DUK_USE_ASSERTIONS */
+/*
* Misc support functions
*/
@@ -59203,7 +64298,10 @@ DUK_INTERNAL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *
* duk_hstring charCodeAt, with and without surrogate awareness
*/
-DUK_INTERNAL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos, duk_bool_t surrogate_aware) {
+DUK_INTERNAL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr,
+ duk_hstring *h,
+ duk_uint_t pos,
+ duk_bool_t surrogate_aware) {
duk_uint32_t boff;
const duk_uint8_t *p, *p_start, *p_end;
duk_ucodepoint_t cp1;
@@ -59212,23 +64310,20 @@ DUK_INTERNAL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk
/* Caller must check character offset to be inside the string. */
DUK_ASSERT(thr != NULL);
DUK_ASSERT(h != NULL);
- DUK_ASSERT_DISABLE(pos >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(pos >= 0); /* unsigned */
DUK_ASSERT(pos < (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h));
boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint32_t) pos);
- DUK_DDD(DUK_DDDPRINT("charCodeAt: pos=%ld -> boff=%ld, str=%!O",
- (long) pos, (long) boff, (duk_heaphdr *) h));
+ DUK_DDD(DUK_DDDPRINT("charCodeAt: pos=%ld -> boff=%ld, str=%!O", (long) pos, (long) boff, (duk_heaphdr *) h));
DUK_ASSERT_DISABLE(boff >= 0);
DUK_ASSERT(boff < DUK_HSTRING_GET_BYTELEN(h));
p_start = DUK_HSTRING_GET_DATA(h);
p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
p = p_start + boff;
- DUK_DDD(DUK_DDDPRINT("p_start=%p, p_end=%p, p=%p",
- (const void *) p_start, (const void *) p_end,
- (const void *) p));
+ DUK_DDD(DUK_DDDPRINT("p_start=%p, p_end=%p, p=%p", (const void *) p_start, (const void *) p_end, (const void *) p));
- /* For invalid UTF-8 (never happens for standard Ecmascript strings)
+ /* For invalid UTF-8 (never happens for standard ECMAScript strings)
* return U+FFFD replacement character.
*/
if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp1)) {
@@ -59237,7 +64332,7 @@ DUK_INTERNAL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk
* decoded at the end of the string and 'p' is no longer
* within string memory range.
*/
- cp2 = 0; /* If call fails, this is left untouched and won't match cp2 check. */
+ cp2 = 0; /* If call fails, this is left untouched and won't match cp2 check. */
(void) duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp2);
if (cp2 >= 0xdc00UL && cp2 <= 0xdfffUL) {
cp1 = (duk_ucodepoint_t) (((cp1 - 0xd800UL) << 10) + (cp2 - 0xdc00UL) + 0x10000UL);
@@ -59267,7 +64362,7 @@ DUK_INTERNAL void duk_hstring_init_charlen(duk_hstring *h) {
clen = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
#if defined(DUK_USE_STRLEN16)
- DUK_ASSERT(clen <= 0xffffUL); /* Bytelength checked during interning. */
+ DUK_ASSERT(clen <= 0xffffUL); /* Bytelength checked during interning. */
h->clen16 = (duk_uint16_t) clen;
#else
h->clen = (duk_uint32_t) clen;
@@ -59284,7 +64379,7 @@ DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
return h->clen;
#endif
}
-#endif /* !DUK_USE_HSTRING_LAZY_CLEN */
+#endif /* !DUK_USE_HSTRING_LAZY_CLEN */
/*
* duk_hstring charlen, when lazy charlen enabled
@@ -59295,7 +64390,7 @@ DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
DUK_LOCAL DUK_COLD duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h) {
duk_size_t res;
- DUK_ASSERT(h->clen == 0); /* Checked by caller. */
+ DUK_ASSERT(h->clen == 0); /* Checked by caller. */
#if defined(DUK_USE_ROM_STRINGS)
/* ROM strings have precomputed clen, but if the computed clen is zero
@@ -59308,7 +64403,7 @@ DUK_LOCAL DUK_COLD duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h)
res = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
#if defined(DUK_USE_STRLEN16)
- DUK_ASSERT(res <= 0xffffUL); /* Bytelength checked during interning. */
+ DUK_ASSERT(res <= 0xffffUL); /* Bytelength checked during interning. */
h->clen16 = (duk_uint16_t) res;
#else
h->clen = (duk_uint32_t) res;
@@ -59318,7 +64413,7 @@ DUK_LOCAL DUK_COLD duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h)
}
return res;
}
-#else /* DUK_USE_HSTRING_CLEN */
+#else /* DUK_USE_HSTRING_CLEN */
DUK_LOCAL duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h) {
if (DUK_LIKELY(DUK_HSTRING_HAS_ASCII(h))) {
/* Most practical strings will go here. */
@@ -59347,7 +64442,7 @@ DUK_LOCAL duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h) {
return res;
}
}
-#endif /* DUK_USE_HSTRING_CLEN */
+#endif /* DUK_USE_HSTRING_CLEN */
#if defined(DUK_USE_HSTRING_CLEN)
DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
@@ -59362,13 +64457,13 @@ DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
#endif
return duk__hstring_get_charlen_slowpath(h);
}
-#else /* DUK_USE_HSTRING_CLEN */
+#else /* DUK_USE_HSTRING_CLEN */
DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
/* Always use slow path. */
return duk__hstring_get_charlen_slowpath(h);
}
-#endif /* DUK_USE_HSTRING_CLEN */
-#endif /* DUK_USE_HSTRING_LAZY_CLEN */
+#endif /* DUK_USE_HSTRING_CLEN */
+#endif /* DUK_USE_HSTRING_LAZY_CLEN */
/*
* Compare duk_hstring to an ASCII cstring.
@@ -59384,7 +64479,7 @@ DUK_INTERNAL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const c
if (len != DUK_HSTRING_GET_BYTELEN(h)) {
return 0;
}
- if (DUK_MEMCMP((const void *) cstr, (const void *) DUK_HSTRING_GET_DATA(h), len) == 0) {
+ if (duk_memcmp((const void *) cstr, (const void *) DUK_HSTRING_GET_DATA(h), len) == 0) {
return 1;
}
return 0;
@@ -59421,7 +64516,7 @@ DUK_INTERNAL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr
if (!thr->valstack) {
goto fail;
}
- DUK_MEMZERO(thr->valstack, alloc_size);
+ duk_memzero(thr->valstack, alloc_size);
thr->valstack_end = thr->valstack + DUK_VALSTACK_API_ENTRY_MINIMUM;
thr->valstack_alloc_end = thr->valstack + DUK_VALSTACK_INITIAL_SIZE;
thr->valstack_bottom = thr->valstack;
@@ -59433,7 +64528,7 @@ DUK_INTERNAL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr
return 1;
- fail:
+fail:
DUK_FREE(heap, thr->valstack);
DUK_ASSERT(thr->callstack_curr == NULL);
@@ -59460,21 +64555,21 @@ DUK_INTERNAL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud) {
* Encoding constants, must match genbuiltins.py
*/
-#define DUK__PROP_FLAGS_BITS 3
-#define DUK__LENGTH_PROP_BITS 3
-#define DUK__NARGS_BITS 3
-#define DUK__PROP_TYPE_BITS 3
+#define DUK__PROP_FLAGS_BITS 3
+#define DUK__LENGTH_PROP_BITS 3
+#define DUK__NARGS_BITS 3
+#define DUK__PROP_TYPE_BITS 3
-#define DUK__NARGS_VARARGS_MARKER 0x07
+#define DUK__NARGS_VARARGS_MARKER 0x07
-#define DUK__PROP_TYPE_DOUBLE 0
-#define DUK__PROP_TYPE_STRING 1
-#define DUK__PROP_TYPE_STRIDX 2
-#define DUK__PROP_TYPE_BUILTIN 3
-#define DUK__PROP_TYPE_UNDEFINED 4
-#define DUK__PROP_TYPE_BOOLEAN_TRUE 5
-#define DUK__PROP_TYPE_BOOLEAN_FALSE 6
-#define DUK__PROP_TYPE_ACCESSOR 7
+#define DUK__PROP_TYPE_DOUBLE 0
+#define DUK__PROP_TYPE_STRING 1
+#define DUK__PROP_TYPE_STRIDX 2
+#define DUK__PROP_TYPE_BUILTIN 3
+#define DUK__PROP_TYPE_UNDEFINED 4
+#define DUK__PROP_TYPE_BOOLEAN_TRUE 5
+#define DUK__PROP_TYPE_BOOLEAN_FALSE 6
+#define DUK__PROP_TYPE_ACCESSOR 7
/*
* Create built-in objects by parsing an init bitstream generated
@@ -59497,9 +64592,8 @@ DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
#if defined(DUK_USE_ROM_GLOBAL_INHERIT)
/* Inherit from ROM-based global object: less RAM usage, less transparent. */
h_global = duk_push_object_helper(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
DUK_BIDX_GLOBAL);
DUK_ASSERT(h_global != NULL);
#elif defined(DUK_USE_ROM_GLOBAL_CLONE)
@@ -59508,9 +64602,8 @@ DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
* model but more compliant.
*/
h_global = duk_push_object_helper(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
DUK_BIDX_OBJECT_PROTOTYPE);
DUK_ASSERT(h_global != NULL);
h_oldglobal = thr->builtins[DUK_BIDX_GLOBAL];
@@ -59525,7 +64618,7 @@ DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
props = DUK_ALLOC_CHECKED(thr, alloc_size);
DUK_ASSERT(props != NULL);
DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal) != NULL);
- DUK_MEMCPY((void *) props, (const void *) DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal), alloc_size);
+ duk_memcpy((void *) props, (const void *) DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal), alloc_size);
/* XXX: keep property attributes or tweak them here?
* Properties will now be non-configurable even when they're
@@ -59544,7 +64637,8 @@ DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
duk_hobject_compact_props(thr, h_global);
DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
- DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL])); /* no need to decref: ROM object */
+ DUK_ASSERT(
+ !DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL])); /* no need to decref: ROM object */
thr->builtins[DUK_BIDX_GLOBAL] = h_global;
DUK_HOBJECT_INCREF(thr, h_global);
DUK_D(DUK_DPRINT("duplicated global object: %!O", h_global));
@@ -59553,9 +64647,9 @@ DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
* needed so that the global scope points to the newly created RAM-based
* global object.
*/
- h_objenv = (duk_hobject *) duk_hobjenv_alloc(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
+ h_objenv =
+ (duk_hobject *) duk_hobjenv_alloc(thr,
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
DUK_ASSERT(h_objenv != NULL);
DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_objenv) == NULL);
duk_push_hobject(thr, h_objenv);
@@ -59566,16 +64660,17 @@ DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
DUK_ASSERT(((duk_hobjenv *) h_objenv)->has_this == 0);
DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL);
- DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL_ENV])); /* no need to decref: ROM object */
+ DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(
+ (duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL_ENV])); /* no need to decref: ROM object */
thr->builtins[DUK_BIDX_GLOBAL_ENV] = h_objenv;
DUK_HOBJECT_INCREF(thr, h_objenv);
DUK_D(DUK_DPRINT("duplicated global env: %!O", h_objenv));
- DUK_ASSERT_HOBJENV_VALID((duk_hobjenv *) h_objenv);
+ DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) h_objenv);
- duk_pop_2(thr); /* Pop global object and global env. */
+ duk_pop_2(thr); /* Pop global object and global env. */
}
-#endif /* DUK_USE_ROM_GLOBAL_CLONE || DUK_USE_ROM_GLOBAL_INHERIT */
+#endif /* DUK_USE_ROM_GLOBAL_CLONE || DUK_USE_ROM_GLOBAL_INHERIT */
DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
/* Setup builtins from ROM objects. All heaps/threads will share
@@ -59599,12 +64694,12 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
duk__duplicate_ram_global_object(thr);
#endif
}
-#else /* DUK_USE_ROM_OBJECTS */
+#else /* DUK_USE_ROM_OBJECTS */
DUK_LOCAL void duk__push_stridx(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
duk_small_uint_t n;
n = (duk_small_uint_t) duk_bd_decode_varuint(bd);
- DUK_ASSERT_DISABLE(n >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(n >= 0); /* unsigned */
DUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);
duk_push_hstring_stridx(thr, n);
}
@@ -59641,18 +64736,20 @@ DUK_LOCAL void duk__push_double(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
du.uc[i] = (duk_uint8_t) duk_bd_decode(bd, 8);
}
- duk_push_number(thr, du.d); /* push operation normalizes NaNs */
+ duk_push_number(thr, du.d); /* push operation normalizes NaNs */
}
DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
duk_bitdecoder_ctx bd_ctx;
- duk_bitdecoder_ctx *bd = &bd_ctx; /* convenience */
+ duk_bitdecoder_ctx *bd = &bd_ctx; /* convenience */
duk_hobject *h;
duk_small_uint_t i, j;
- DUK_D(DUK_DPRINT("INITBUILTINS BEGIN: DUK_NUM_BUILTINS=%d, DUK_NUM_BUILTINS_ALL=%d", (int) DUK_NUM_BUILTINS, (int) DUK_NUM_ALL_BUILTINS));
+ DUK_D(DUK_DPRINT("INITBUILTINS BEGIN: DUK_NUM_BUILTINS=%d, DUK_NUM_BUILTINS_ALL=%d",
+ (int) DUK_NUM_BUILTINS,
+ (int) DUK_NUM_ALL_BUILTINS));
- DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
+ duk_memzero(&bd_ctx, sizeof(bd_ctx));
bd->data = (const duk_uint8_t *) duk_builtins_data;
bd->length = (duk_size_t) DUK_BUILTINS_DATA_LENGTH;
@@ -59677,14 +64774,14 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
DUK_ASSERT_TOP(thr, 0);
for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
duk_small_uint_t class_num;
- duk_small_int_t len = -1; /* must be signed */
+ duk_small_int_t len = -1; /* must be signed */
class_num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
len = (duk_small_int_t) duk_bd_decode_flagged_signed(bd, DUK__LENGTH_PROP_BITS, (duk_int32_t) -1 /*def_value*/);
if (class_num == DUK_HOBJECT_CLASS_FUNCTION) {
duk_small_uint_t natidx;
- duk_small_int_t c_nargs; /* must hold DUK_VARARGS */
+ duk_small_int_t c_nargs; /* must hold DUK_VARARGS */
duk_c_function c_func;
duk_int16_t magic;
@@ -59715,12 +64812,9 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
duk__push_stridx_or_string(thr, bd);
#if defined(DUK_USE_FUNC_NAME_PROPERTY)
- duk_xdef_prop_stridx_short(thr,
- -2,
- DUK_STRIDX_NAME,
- DUK_PROPDESC_FLAGS_C);
+ duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
#else
- duk_pop(thr); /* Not very ideal but good enough for now. */
+ duk_pop(thr); /* Not very ideal but good enough for now. */
#endif
/* Almost all global level Function objects are constructable
@@ -59746,8 +64840,7 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
DUK_ASSERT(DUK_BIDX_GLOBAL_ENV > DUK_BIDX_GLOBAL);
env = duk_hobjenv_alloc(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
DUK_ASSERT(env->target == NULL);
duk_push_hobject(thr, (duk_hobject *) env);
@@ -59757,15 +64850,13 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
DUK_HOBJECT_INCREF(thr, global);
DUK_ASSERT(env->has_this == 0);
- DUK_ASSERT_HOBJENV_VALID(env);
+ DUK_HOBJENV_ASSERT_VALID(env);
} else {
DUK_ASSERT(class_num != DUK_HOBJECT_CLASS_DECENV);
(void) duk_push_object_helper(thr,
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_FLAG_EXTENSIBLE,
- -1); /* no prototype or class yet */
-
+ DUK_HOBJECT_FLAG_FASTREFS | DUK_HOBJECT_FLAG_EXTENSIBLE,
+ -1); /* no prototype or class yet */
}
h = duk_known_hobject(thr, -1);
@@ -59787,18 +64878,15 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
* not encoded explicitly in init data.
*/
- DUK_ASSERT(class_num != DUK_HOBJECT_CLASS_ARRAY); /* .length is virtual */
+ DUK_ASSERT(class_num != DUK_HOBJECT_CLASS_ARRAY); /* .length is virtual */
duk_push_int(thr, len);
- duk_xdef_prop_stridx_short(thr,
- -2,
- DUK_STRIDX_LENGTH,
- DUK_PROPDESC_FLAGS_C);
+ duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
}
/* enable exotic behaviors last */
if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
- DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)); /* set by duk_push_array() */
+ DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)); /* set by duk_push_array() */
}
if (class_num == DUK_HOBJECT_CLASS_STRING) {
DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h);
@@ -59812,9 +64900,10 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
DUK_ASSERT(!DUK_HOBJECT_HAS_COMPFUNC(h));
/* DUK_HOBJECT_FLAG_NATFUNC varies */
DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(h));
+ DUK_ASSERT(!DUK_HOBJECT_IS_PROXY(h));
DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(h) || class_num == DUK_HOBJECT_CLASS_ARRAY);
/* DUK_HOBJECT_FLAG_STRICT varies */
- DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(h) || /* all native functions have NEWENV */
+ DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(h) || /* all native functions have NEWENV */
DUK_HOBJECT_HAS_NEWENV(h));
DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(h));
DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(h));
@@ -59894,16 +64983,12 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
* signaled using a single flag bit in the bitstream.
*/
- if (duk_bd_decode_flag(bd)) {
- defprop_flags = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_FLAGS_BITS);
- } else {
- defprop_flags = DUK_PROPDESC_FLAGS_WC;
- }
- defprop_flags |= DUK_DEFPROP_FORCE |
- DUK_DEFPROP_HAVE_VALUE |
- DUK_DEFPROP_HAVE_WRITABLE |
+ defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd,
+ DUK__PROP_FLAGS_BITS,
+ (duk_uint32_t) DUK_PROPDESC_FLAGS_WC);
+ defprop_flags |= DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE |
DUK_DEFPROP_HAVE_ENUMERABLE |
- DUK_DEFPROP_HAVE_CONFIGURABLE; /* Defaults for data properties. */
+ DUK_DEFPROP_HAVE_CONFIGURABLE; /* Defaults for data properties. */
/* The writable, enumerable, configurable flags in prop_flags
* match both duk_def_prop() and internal property flags.
@@ -59915,7 +65000,11 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
t = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_TYPE_BITS);
DUK_DDD(DUK_DDDPRINT("built-in %ld, normal-valued property %ld, key %!T, flags 0x%02lx, type %ld",
- (long) i, (long) j, duk_get_tval(thr, -1), (unsigned long) defprop_flags, (long) t));
+ (long) i,
+ (long) j,
+ duk_get_tval(thr, -1),
+ (unsigned long) defprop_flags,
+ (long) t));
switch (t) {
case DUK__PROP_TYPE_DOUBLE: {
@@ -59956,24 +65045,29 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
duk_c_function c_func_getter;
duk_c_function c_func_setter;
- DUK_DDD(DUK_DDDPRINT("built-in accessor property: objidx=%ld, key=%!T, getteridx=%ld, setteridx=%ld, flags=0x%04lx",
- (long) i, duk_get_tval(thr, -1), (long) natidx_getter, (long) natidx_setter, (unsigned long) defprop_flags));
+ DUK_DDD(DUK_DDDPRINT(
+ "built-in accessor property: objidx=%ld, key=%!T, getteridx=%ld, setteridx=%ld, flags=0x%04lx",
+ (long) i,
+ duk_get_tval(thr, -1),
+ (long) natidx_getter,
+ (long) natidx_setter,
+ (unsigned long) defprop_flags));
c_func_getter = duk_bi_native_functions[natidx_getter];
if (c_func_getter != NULL) {
- duk_push_c_function_builtin_noconstruct(thr, c_func_getter, 0); /* always 0 args */
+ duk_push_c_function_builtin_noconstruct(thr, c_func_getter, 0); /* always 0 args */
duk_set_magic(thr, -1, (duk_int_t) accessor_magic);
defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
}
c_func_setter = duk_bi_native_functions[natidx_setter];
if (c_func_setter != NULL) {
- duk_push_c_function_builtin_noconstruct(thr, c_func_setter, 1); /* always 1 arg */
+ duk_push_c_function_builtin_noconstruct(thr, c_func_setter, 1); /* always 1 arg */
duk_set_magic(thr, -1, (duk_int_t) accessor_magic);
defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
}
/* Writable flag doesn't make sense for an accessor. */
- DUK_ASSERT((defprop_flags & DUK_PROPDESC_FLAG_WRITABLE) == 0); /* genbuiltins.py ensures */
+ DUK_ASSERT((defprop_flags & DUK_PROPDESC_FLAG_WRITABLE) == 0); /* genbuiltins.py ensures */
defprop_flags &= ~(DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE;
@@ -59995,7 +65089,7 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
for (j = 0; j < num; j++) {
duk_hstring *h_key;
duk_small_uint_t natidx;
- duk_int_t c_nargs; /* must hold DUK_VARARGS */
+ duk_int_t c_nargs; /* must hold DUK_VARARGS */
duk_small_uint_t c_length;
duk_int16_t magic;
duk_c_function c_func;
@@ -60003,6 +65097,7 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
duk_small_int_t lightfunc_eligible;
#endif
+ duk_small_uint_t defprop_flags;
duk__push_stridx_or_string(thr, bd);
h_key = duk_known_hstring(thr, -1);
@@ -60017,51 +65112,66 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
c_func = duk_bi_native_functions[natidx];
- DUK_DDD(DUK_DDDPRINT("built-in %ld, function-valued property %ld, key %!O, natidx %ld, length %ld, nargs %ld",
- (long) i, (long) j, (duk_heaphdr *) h_key, (long) natidx, (long) c_length,
- (c_nargs == DUK_VARARGS ? (long) -1 : (long) c_nargs)));
+ DUK_DDD(
+ DUK_DDDPRINT("built-in %ld, function-valued property %ld, key %!O, natidx %ld, length %ld, nargs %ld",
+ (long) i,
+ (long) j,
+ (duk_heaphdr *) h_key,
+ (long) natidx,
+ (long) c_length,
+ (c_nargs == DUK_VARARGS ? (long) -1 : (long) c_nargs)));
/* Cast converts magic to 16-bit signed value */
magic = (duk_int16_t) duk_bd_decode_varuint(bd);
#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
lightfunc_eligible =
- ((c_nargs >= DUK_LFUNC_NARGS_MIN && c_nargs <= DUK_LFUNC_NARGS_MAX) || (c_nargs == DUK_VARARGS)) &&
- (c_length <= DUK_LFUNC_LENGTH_MAX) &&
- (magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX);
+ ((c_nargs >= DUK_LFUNC_NARGS_MIN && c_nargs <= DUK_LFUNC_NARGS_MAX) || (c_nargs == DUK_VARARGS)) &&
+ (c_length <= DUK_LFUNC_LENGTH_MAX) && (magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX);
/* These functions have trouble working as lightfuncs.
* Some of them have specific asserts and some may have
- * additional properties (e.g. 'require.id' may be written).
+ * additional properties (e.g. 'require.id' may be written).
*/
if (c_func == duk_bi_global_object_eval) {
lightfunc_eligible = 0;
}
#if defined(DUK_USE_COROUTINE_SUPPORT)
- if (c_func == duk_bi_thread_yield ||
- c_func == duk_bi_thread_resume) {
+ if (c_func == duk_bi_thread_yield || c_func == duk_bi_thread_resume) {
lightfunc_eligible = 0;
}
#endif
- if (c_func == duk_bi_function_prototype_call ||
- c_func == duk_bi_function_prototype_apply ||
- c_func == duk_bi_reflect_apply ||
- c_func == duk_bi_reflect_construct) {
+ if (c_func == duk_bi_function_prototype_call || c_func == duk_bi_function_prototype_apply ||
+ c_func == duk_bi_reflect_apply || c_func == duk_bi_reflect_construct) {
lightfunc_eligible = 0;
}
if (lightfunc_eligible) {
duk_tval tv_lfunc;
- duk_small_uint_t lf_nargs = (duk_small_uint_t) (c_nargs == DUK_VARARGS ? DUK_LFUNC_NARGS_VARARGS : c_nargs);
+ duk_small_uint_t lf_nargs =
+ (duk_small_uint_t) (c_nargs == DUK_VARARGS ? DUK_LFUNC_NARGS_VARARGS : c_nargs);
duk_small_uint_t lf_flags = DUK_LFUNC_FLAGS_PACK(magic, c_length, lf_nargs);
DUK_TVAL_SET_LIGHTFUNC(&tv_lfunc, c_func, lf_flags);
duk_push_tval(thr, &tv_lfunc);
- DUK_D(DUK_DPRINT("built-in function eligible as light function: i=%d, j=%d c_length=%ld, c_nargs=%ld, magic=%ld -> %!iT", (int) i, (int) j, (long) c_length, (long) c_nargs, (long) magic, duk_get_tval(thr, -1)));
+ DUK_D(DUK_DPRINT("built-in function eligible as light function: i=%d, j=%d c_length=%ld, "
+ "c_nargs=%ld, magic=%ld -> %!iT",
+ (int) i,
+ (int) j,
+ (long) c_length,
+ (long) c_nargs,
+ (long) magic,
+ duk_get_tval(thr, -1)));
goto lightfunc_skip;
}
- DUK_D(DUK_DPRINT("built-in function NOT ELIGIBLE as light function: i=%d, j=%d c_length=%ld, c_nargs=%ld, magic=%ld", (int) i, (int) j, (long) c_length, (long) c_nargs, (long) magic));
-#endif /* DUK_USE_LIGHTFUNC_BUILTINS */
+ DUK_D(DUK_DPRINT(
+ "built-in function NOT ELIGIBLE as light function: i=%d, j=%d c_length=%ld, c_nargs=%ld, magic=%ld",
+ (int) i,
+ (int) j,
+ (long) c_length,
+ (long) c_nargs,
+ (long) magic));
+#endif /* DUK_USE_LIGHTFUNC_BUILTINS */
/* [ (builtin objects) name ] */
@@ -60072,10 +65182,8 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
/* XXX: add into init data? */
/* Special call handling, not described in init data. */
- if (c_func == duk_bi_global_object_eval ||
- c_func == duk_bi_function_prototype_call ||
- c_func == duk_bi_function_prototype_apply ||
- c_func == duk_bi_reflect_apply ||
+ if (c_func == duk_bi_global_object_eval || c_func == duk_bi_function_prototype_call ||
+ c_func == duk_bi_function_prototype_apply || c_func == duk_bi_reflect_apply ||
c_func == duk_bi_reflect_construct) {
DUK_HOBJECT_SET_SPECIAL_CALL((duk_hobject *) h_func);
}
@@ -60109,7 +65217,9 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
/* XXX: other properties of function instances; 'arguments', 'caller'. */
DUK_DD(DUK_DDPRINT("built-in object %ld, function property %ld -> %!T",
- (long) i, (long) j, (duk_tval *) duk_get_tval(thr, -1)));
+ (long) i,
+ (long) j,
+ (duk_tval *) duk_get_tval(thr, -1)));
/* [ (builtin objects) name func ] */
@@ -60119,13 +65229,19 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
*/
#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
- lightfunc_skip:
+ lightfunc_skip:
#endif
- /* XXX: So far all ES builtins are 'wc' but e.g.
- * performance.now() should be 'wec'.
- */
- duk_xdef_prop(thr, (duk_idx_t) i, DUK_PROPDESC_FLAGS_WC);
+ defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd,
+ DUK__PROP_FLAGS_BITS,
+ (duk_uint32_t) DUK_PROPDESC_FLAGS_WC);
+ defprop_flags |= DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE |
+ DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE;
+ DUK_ASSERT(DUK_PROPDESC_FLAG_WRITABLE == DUK_DEFPROP_WRITABLE);
+ DUK_ASSERT(DUK_PROPDESC_FLAG_ENUMERABLE == DUK_DEFPROP_ENUMERABLE);
+ DUK_ASSERT(DUK_PROPDESC_FLAG_CONFIGURABLE == DUK_DEFPROP_CONFIGURABLE);
+
+ duk_def_prop(thr, (duk_idx_t) i, defprop_flags);
/* [ (builtin objects) ] */
}
@@ -60158,22 +65274,28 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
#if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY)
DUK_DD(DUK_DDPRINT("delete Object.prototype.__proto__ built-in which is not enabled in features"));
- (void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_PROTOTYPE], DUK_HTHREAD_STRING___PROTO__(thr), DUK_DELPROP_FLAG_THROW);
+ (void) duk_hobject_delprop_raw(thr,
+ thr->builtins[DUK_BIDX_OBJECT_PROTOTYPE],
+ DUK_HTHREAD_STRING___PROTO__(thr),
+ DUK_DELPROP_FLAG_THROW);
#endif
#if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF)
DUK_DD(DUK_DDPRINT("delete Object.setPrototypeOf built-in which is not enabled in features"));
- (void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_CONSTRUCTOR], DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr), DUK_DELPROP_FLAG_THROW);
+ (void) duk_hobject_delprop_raw(thr,
+ thr->builtins[DUK_BIDX_OBJECT_CONSTRUCTOR],
+ DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr),
+ DUK_DELPROP_FLAG_THROW);
#endif
/* XXX: relocate */
duk_push_string(thr,
- /* Endianness indicator */
+ /* Endianness indicator */
#if defined(DUK_USE_INTEGER_LE)
"l"
#elif defined(DUK_USE_INTEGER_BE)
"b"
-#elif defined(DUK_USE_INTEGER_ME) /* integer mixed endian not really used now */
+#elif defined(DUK_USE_INTEGER_ME) /* integer mixed endian not really used now */
"m"
#else
"?"
@@ -60188,86 +65310,85 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
"?"
#endif
" "
- /* Packed or unpacked tval */
+ /* Packed or unpacked tval */
#if defined(DUK_USE_PACKED_TVAL)
"p"
#else
"u"
#endif
#if defined(DUK_USE_FASTINT)
- "f"
+ "f"
#endif
- " "
- /* Low memory options */
+ " "
+ /* Low memory/performance options */
#if defined(DUK_USE_STRTAB_PTRCOMP)
- "s"
+ "s"
#endif
#if !defined(DUK_USE_HEAPPTR16) && !defined(DUK_DATAPTR16) && !defined(DUK_FUNCPTR16)
- "n"
+ "n"
#endif
#if defined(DUK_USE_HEAPPTR16)
- "h"
+ "h"
#endif
#if defined(DUK_USE_DATAPTR16)
- "d"
+ "d"
#endif
#if defined(DUK_USE_FUNCPTR16)
- "f"
+ "f"
#endif
#if defined(DUK_USE_REFCOUNT16)
- "R"
+ "R"
#endif
#if defined(DUK_USE_STRHASH16)
- "H"
+ "H"
#endif
#if defined(DUK_USE_STRLEN16)
- "S"
+ "S"
#endif
#if defined(DUK_USE_BUFLEN16)
- "B"
+ "B"
#endif
#if defined(DUK_USE_OBJSIZES16)
- "O"
+ "O"
#endif
#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
- "L"
+ "L"
#endif
#if defined(DUK_USE_ROM_STRINGS) || defined(DUK_USE_ROM_OBJECTS)
- /* XXX: This won't be shown in practice now
- * because this code is not run when builtins
- * are in ROM.
- */
- "Z"
+ /* XXX: This won't be shown in practice now
+ * because this code is not run when builtins
+ * are in ROM.
+ */
+ "Z"
+#endif
+#if defined(DUK_USE_LITCACHE_SIZE)
+ "l"
#endif
" "
- /* Object property allocation layout */
+ /* Object property allocation layout */
#if defined(DUK_USE_HOBJECT_LAYOUT_1)
- "p1"
+ "p1"
#elif defined(DUK_USE_HOBJECT_LAYOUT_2)
- "p2"
+ "p2"
#elif defined(DUK_USE_HOBJECT_LAYOUT_3)
- "p3"
+ "p3"
#else
- "p?"
+ "p?"
#endif
- " "
- /* Alignment guarantee */
+ " "
+ /* Alignment guarantee */
#if (DUK_USE_ALIGN_BY == 4)
- "a4"
+ "a4"
#elif (DUK_USE_ALIGN_BY == 8)
- "a8"
+ "a8"
#elif (DUK_USE_ALIGN_BY == 1)
- "a1"
+ "a1"
#else
#error invalid DUK_USE_ALIGN_BY
#endif
- " "
- /* Architecture, OS, and compiler strings */
- DUK_USE_ARCH_STRING
- " "
- DUK_USE_OS_STRING
- " "
- DUK_USE_COMPILER_STRING);
+ " "
+ /* Architecture, OS, and compiler strings */
+ DUK_USE_ARCH_STRING " " DUK_USE_OS_STRING " " DUK_USE_COMPILER_STRING);
duk_xdef_prop_stridx_short(thr, DUK_BIDX_DUKTAPE, DUK_STRIDX_ENV, DUK_PROPDESC_FLAGS_WC);
/*
@@ -60284,7 +65405,8 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
DUK_DD(DUK_DDPRINT("built-in object %ld after initialization and compacting: %!@iO",
- (long) i, (duk_heaphdr *) duk_require_hobject(thr, i)));
+ (long) i,
+ (duk_heaphdr *) duk_require_hobject(thr, (duk_idx_t) i)));
}
#endif
@@ -60297,14 +65419,14 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
duk_set_top(thr, 0);
DUK_ASSERT_TOP(thr, 0);
}
-#endif /* DUK_USE_ROM_OBJECTS */
+#endif /* DUK_USE_ROM_OBJECTS */
DUK_INTERNAL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to) {
duk_small_uint_t i;
for (i = 0; i < DUK_NUM_BUILTINS; i++) {
thr_to->builtins[i] = thr_from->builtins[i];
- DUK_HOBJECT_INCREF_ALLOWNULL(thr_to, thr_to->builtins[i]); /* side effect free */
+ DUK_HOBJECT_INCREF_ALLOWNULL(thr_to, thr_to->builtins[i]); /* side effect free */
}
}
@@ -60336,7 +65458,7 @@ DUK_INTERNAL void duk_hthread_terminate(duk_hthread *thr) {
}
thr->valstack_bottom = thr->valstack;
- duk_set_top(thr, 0); /* unwinds valstack, updating refcounts */
+ duk_set_top(thr, 0); /* unwinds valstack, updating refcounts */
thr->state = DUK_HTHREAD_STATE_TERMINATED;
@@ -60367,7 +65489,7 @@ DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk
}
return 0;
}
-#endif /* DUK_USE_DEBUGGER_SUPPORT */
+#endif /* DUK_USE_DEBUGGER_SUPPORT */
DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act) {
duk_instr_t *bcode;
@@ -60436,7 +65558,7 @@ DUK_INTERNAL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activati
DUK_ASSERT(thr != NULL);
DUK_ASSERT(act != NULL);
- DUK_ASSERT(act->cat != NULL); /* caller must check */
+ DUK_ASSERT(act->cat != NULL); /* caller must check */
cat = act->cat;
DUK_ASSERT(cat != NULL);
@@ -60445,9 +65567,9 @@ DUK_INTERNAL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activati
if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
duk_hobject *env;
- env = act->lex_env; /* current lex_env of the activation (created for catcher) */
- DUK_ASSERT(env != NULL); /* must be, since env was created when catcher was created */
- act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env); /* prototype is lex_env before catcher created */
+ env = act->lex_env; /* current lex_env of the activation (created for catcher) */
+ DUK_ASSERT(env != NULL); /* must be, since env was created when catcher was created */
+ act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env); /* prototype is lex_env before catcher created */
DUK_HOBJECT_INCREF(thr, act->lex_env);
DUK_HOBJECT_DECREF_NORZ(thr, env);
@@ -60466,7 +65588,7 @@ DUK_INTERNAL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk
DUK_ASSERT(thr != NULL);
DUK_ASSERT(act != NULL);
- DUK_ASSERT(act->cat != NULL); /* caller must check */
+ DUK_ASSERT(act->cat != NULL); /* caller must check */
cat = act->cat;
DUK_ASSERT(cat != NULL);
@@ -60504,11 +65626,11 @@ DUK_INTERNAL DUK_INLINE duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr)
return duk__hthread_catcher_alloc_slow(thr);
}
-#else /* DUK_USE_CACHE_CATCHER */
+#else /* DUK_USE_CACHE_CATCHER */
DUK_INTERNAL duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr) {
return duk__hthread_catcher_alloc_slow(thr);
}
-#endif /* DUK_USE_CACHE_CATCHER */
+#endif /* DUK_USE_CACHE_CATCHER */
DUK_INTERNAL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat) {
DUK_ASSERT(thr != NULL);
@@ -60549,12 +65671,11 @@ DUK_INTERNAL DUK_INLINE duk_activation *duk_hthread_activation_alloc(duk_hthread
return duk__hthread_activation_alloc_slow(thr);
}
-#else /* DUK_USE_CACHE_ACTIVATION */
+#else /* DUK_USE_CACHE_ACTIVATION */
DUK_INTERNAL duk_activation *duk_hthread_activation_alloc(duk_hthread *thr) {
return duk__hthread_activation_alloc_slow(thr);
}
-#endif /* DUK_USE_CACHE_ACTIVATION */
-
+#endif /* DUK_USE_CACHE_ACTIVATION */
DUK_INTERNAL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act) {
DUK_ASSERT(thr != NULL);
@@ -60581,7 +65702,7 @@ DUK_LOCAL void duk__activation_unwind_nofree_norz(duk_hthread *thr) {
duk_hobject *tmp;
DUK_ASSERT(thr != NULL);
- DUK_ASSERT(thr->callstack_curr != NULL); /* caller must check */
+ DUK_ASSERT(thr->callstack_curr != NULL); /* caller must check */
DUK_ASSERT(thr->callstack_top > 0);
act = thr->callstack_curr;
DUK_ASSERT(act != NULL);
@@ -60602,7 +65723,7 @@ DUK_LOCAL void duk__activation_unwind_nofree_norz(duk_hthread *thr) {
duk_tval tv_tmp;
duk_hobject *h_tmp;
- tv_caller = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_CALLER(thr));
+ tv_caller = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, func, DUK_STRIDX_CALLER);
/* The act->prev_caller should only be set if the entry for 'caller'
* exists (as it is only set in that case, and the property is not
@@ -60618,7 +65739,7 @@ DUK_LOCAL void duk__activation_unwind_nofree_norz(duk_hthread *thr) {
DUK_TVAL_SET_OBJECT(tv_caller, act->prev_caller);
act->prev_caller = NULL;
} else {
- DUK_TVAL_SET_NULL(tv_caller); /* no incref needed */
+ DUK_TVAL_SET_NULL(tv_caller); /* no incref needed */
DUK_ASSERT(act->prev_caller == NULL);
}
DUK_TVAL_DECREF_NORZ(thr, &tv_tmp);
@@ -60647,7 +65768,7 @@ DUK_LOCAL void duk__activation_unwind_nofree_norz(duk_hthread *thr) {
duk_debug_set_paused(heap);
} else {
DUK_D(DUK_DPRINT("unwound past dbg_pause_act, set to NULL"));
- heap->dbg_pause_act = NULL; /* avoid stale pointers */
+ heap->dbg_pause_act = NULL; /* avoid stale pointers */
}
DUK_ASSERT(heap->dbg_pause_act == NULL);
}
@@ -60696,12 +65817,11 @@ DUK_LOCAL void duk__activation_unwind_nofree_norz(duk_hthread *thr) {
* fixed e.g. by preallocating the scope property slots.
*/
if (act->var_env != NULL) {
- DUK_DDD(DUK_DDDPRINT("closing var_env record %p -> %!O",
- (void *) act->var_env, (duk_heaphdr *) act->var_env));
+ DUK_DDD(DUK_DDDPRINT("closing var_env record %p -> %!O", (void *) act->var_env, (duk_heaphdr *) act->var_env));
duk_js_close_environment_record(thr, act->var_env);
}
- skip_env_close:
+skip_env_close:
/*
* Update preventcount
@@ -60813,8 +65933,8 @@ DUK_INTERNAL void duk_hthread_valstack_torture_realloc(duk_hthread *thr) {
/* Use DUK_ALLOC_RAW() to avoid side effects. */
new_ptr = (duk_tval *) DUK_ALLOC_RAW(thr->heap, alloc_size);
if (new_ptr != NULL) {
- DUK_MEMCPY((void *) new_ptr, (const void *) thr->valstack, alloc_size);
- DUK_MEMSET((void *) thr->valstack, 0x55, alloc_size);
+ duk_memcpy((void *) new_ptr, (const void *) thr->valstack, alloc_size);
+ duk_memset((void *) thr->valstack, 0x55, alloc_size);
DUK_FREE_CHECKED(thr, (void *) thr->valstack);
thr->valstack = new_ptr;
thr->valstack_alloc_end = (duk_tval *) ((duk_uint8_t *) new_ptr + alloc_end_off);
@@ -60825,14 +65945,14 @@ DUK_INTERNAL void duk_hthread_valstack_torture_realloc(duk_hthread *thr) {
DUK_D(DUK_DPRINT("failed to realloc valstack for torture, ignore"));
}
}
-#endif /* DUK_USE_FINALIZER_TORTURE */
+#endif /* DUK_USE_FINALIZER_TORTURE */
/*
* Shared helpers for arithmetic operations
*/
/* #include duk_internal.h -> already included */
-/* Ecmascript modulus ('%') does not match IEEE 754 "remainder" operation
+/* ECMAScript modulus ('%') does not match IEEE 754 "remainder" operation
* (implemented by remainder() in C99) but does seem to match ANSI C fmod().
* Compare E5 Section 11.5.3 and "man fmod".
*/
@@ -60847,11 +65967,11 @@ DUK_INTERNAL double duk_js_arith_mod(double d1, double d2) {
} else {
return d1;
}
- } else if (d1 == 0.0) {
+ } else if (duk_double_equals(d1, 0.0)) {
/* d1 +/-0 is returned as is (preserving sign) except when
* d2 is zero or NaN.
*/
- if (d2 == 0.0 || DUK_ISNAN(d2)) {
+ if (duk_double_equals(d2, 0.0) || DUK_ISNAN(d2)) {
return DUK_DOUBLE_NAN;
} else {
return d1;
@@ -60859,20 +65979,24 @@ DUK_INTERNAL double duk_js_arith_mod(double d1, double d2) {
}
#else
/* Some ISO C assumptions. */
- DUK_ASSERT(DUK_FMOD(1.0, DUK_DOUBLE_INFINITY) == 1.0);
- DUK_ASSERT(DUK_FMOD(-1.0, DUK_DOUBLE_INFINITY) == -1.0);
- DUK_ASSERT(DUK_FMOD(1.0, -DUK_DOUBLE_INFINITY) == 1.0);
- DUK_ASSERT(DUK_FMOD(-1.0, -DUK_DOUBLE_INFINITY) == -1.0);
+ DUK_ASSERT(duk_double_equals(DUK_FMOD(1.0, DUK_DOUBLE_INFINITY), 1.0));
+ DUK_ASSERT(duk_double_equals(DUK_FMOD(-1.0, DUK_DOUBLE_INFINITY), -1.0));
+ DUK_ASSERT(duk_double_equals(DUK_FMOD(1.0, -DUK_DOUBLE_INFINITY), 1.0));
+ DUK_ASSERT(duk_double_equals(DUK_FMOD(-1.0, -DUK_DOUBLE_INFINITY), -1.0));
DUK_ASSERT(DUK_ISNAN(DUK_FMOD(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY)));
DUK_ASSERT(DUK_ISNAN(DUK_FMOD(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY)));
DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY)));
DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY)));
- DUK_ASSERT(DUK_FMOD(0.0, 1.0) == 0.0 && DUK_SIGNBIT(DUK_FMOD(0.0, 1.0)) == 0);
- DUK_ASSERT(DUK_FMOD(-0.0, 1.0) == 0.0 && DUK_SIGNBIT(DUK_FMOD(-0.0, 1.0)) != 0);
- DUK_ASSERT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);
- DUK_ASSERT(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY)) != 0);
- DUK_ASSERT(DUK_FMOD(0.0, -DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);
- DUK_ASSERT(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY)) != 0);
+ DUK_ASSERT(duk_double_equals(DUK_FMOD(0.0, 1.0), 0.0) && DUK_SIGNBIT(DUK_FMOD(0.0, 1.0)) == 0);
+ DUK_ASSERT(duk_double_equals(DUK_FMOD(-0.0, 1.0), 0.0) && DUK_SIGNBIT(DUK_FMOD(-0.0, 1.0)) != 0);
+ DUK_ASSERT(duk_double_equals(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY), 0.0) &&
+ DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);
+ DUK_ASSERT(duk_double_equals(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY), 0.0) &&
+ DUK_SIGNBIT(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY)) != 0);
+ DUK_ASSERT(duk_double_equals(DUK_FMOD(0.0, -DUK_DOUBLE_INFINITY), 0.0) &&
+ DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);
+ DUK_ASSERT(duk_double_equals(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY), 0.0) &&
+ DUK_SIGNBIT(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY)) != 0);
DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, 0.0)));
DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, 0.0)));
DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, -0.0)));
@@ -60886,9 +66010,9 @@ DUK_INTERNAL double duk_js_arith_mod(double d1, double d2) {
/* Shared helper for Math.pow() and exponentiation operator. */
DUK_INTERNAL double duk_js_arith_pow(double x, double y) {
- /* The ANSI C pow() semantics differ from Ecmascript.
+ /* The ANSI C pow() semantics differ from ECMAScript.
*
- * E.g. when x==1 and y is +/- infinite, the Ecmascript required
+ * E.g. when x==1 and y is +/- infinite, the ECMAScript required
* result is NaN, while at least Linux pow() returns 1.
*/
@@ -60901,7 +66025,7 @@ DUK_INTERNAL double duk_js_arith_pow(double x, double y) {
if (cy == DUK_FP_NAN) {
goto ret_nan;
}
- if (DUK_FABS(x) == 1.0 && cy == DUK_FP_INFINITE) {
+ if (duk_double_equals(DUK_FABS(x), 1.0) && cy == DUK_FP_INFINITE) {
goto ret_nan;
}
@@ -60943,7 +66067,7 @@ DUK_INTERNAL double duk_js_arith_pow(double x, double y) {
}
}
} else if (cx == DUK_FP_NAN) {
- if (y == 0.0) {
+ if (duk_double_equals(y, 0.0)) {
/* NaN ** +/- 0 should always be 1, but is NaN on
* at least some Cygwin/MinGW versions.
*/
@@ -60952,7 +66076,7 @@ DUK_INTERNAL double duk_js_arith_pow(double x, double y) {
}
#else
/* Some ISO C assumptions. */
- DUK_ASSERT(DUK_POW(DUK_DOUBLE_NAN, 0.0) == 1.0);
+ DUK_ASSERT(duk_double_equals(DUK_POW(DUK_DOUBLE_NAN, 0.0), 1.0));
DUK_ASSERT(DUK_ISINF(DUK_POW(0.0, -1.0)) && DUK_SIGNBIT(DUK_POW(0.0, -1.0)) == 0);
DUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -2.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -2.0)) == 0);
DUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -3.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -3.0)) != 0);
@@ -60960,7 +66084,7 @@ DUK_INTERNAL double duk_js_arith_pow(double x, double y) {
return DUK_POW(x, y);
- ret_nan:
+ret_nan:
return DUK_DOUBLE_NAN;
}
/*
@@ -60968,7 +66092,7 @@ DUK_INTERNAL double duk_js_arith_pow(double x, double y) {
*
* duk_handle_call_unprotected():
*
- * - Unprotected call to Ecmascript or Duktape/C function, from native
+ * - Unprotected call to ECMAScript or Duktape/C function, from native
* code or bytecode executor.
*
* - Also handles Ecma-to-Ecma calls which reuses a currently running
@@ -61000,12 +66124,26 @@ DUK_INTERNAL double duk_js_arith_pow(double x, double y) {
* Limit check helpers.
*/
+/* Check native stack space if DUK_USE_NATIVE_STACK_CHECK() defined. */
+DUK_INTERNAL void duk_native_stack_check(duk_hthread *thr) {
+#if defined(DUK_USE_NATIVE_STACK_CHECK)
+ if (DUK_USE_NATIVE_STACK_CHECK() != 0) {
+ DUK_ERROR_RANGE(thr, DUK_STR_NATIVE_STACK_LIMIT);
+ }
+#else
+ DUK_UNREF(thr);
+#endif
+}
+
/* Allow headroom for calls during error augmentation (see GH-191).
* We allow space for 10 additional recursions, with one extra
* for, e.g. a print() call at the deepest level, and an extra
* +1 for protected call wrapping.
*/
-#define DUK__AUGMENT_CALL_RELAX_COUNT (10 + 2)
+#define DUK__AUGMENT_CALL_RELAX_COUNT (10 + 2)
+
+/* Stack space required by call handling entry. */
+#define DUK__CALL_HANDLING_REQUIRE_STACK 8
DUK_LOCAL DUK_NOINLINE void duk__call_c_recursion_limit_check_slowpath(duk_hthread *thr) {
/* When augmenting an error, the effective limit is a bit higher.
@@ -61021,13 +66159,16 @@ DUK_LOCAL DUK_NOINLINE void duk__call_c_recursion_limit_check_slowpath(duk_hthre
#endif
DUK_D(DUK_DPRINT("call prevented because C recursion limit reached"));
- DUK_ERROR_RANGE(thr, DUK_STR_C_CALLSTACK_LIMIT);
+ DUK_ERROR_RANGE(thr, DUK_STR_NATIVE_STACK_LIMIT);
+ DUK_WO_NORETURN(return;);
}
DUK_LOCAL DUK_ALWAYS_INLINE void duk__call_c_recursion_limit_check(duk_hthread *thr) {
DUK_ASSERT(thr->heap->call_recursion_depth >= 0);
DUK_ASSERT(thr->heap->call_recursion_depth <= thr->heap->call_recursion_limit);
+ duk_native_stack_check(thr);
+
/* This check is forcibly inlined because it's very cheap and almost
* always passes. The slow path is forcibly noinline.
*/
@@ -61057,6 +66198,7 @@ DUK_LOCAL DUK_NOINLINE void duk__call_callstack_limit_check_slowpath(duk_hthread
*/
DUK_D(DUK_DPRINT("call prevented because call stack limit reached"));
DUK_ERROR_RANGE(thr, DUK_STR_CALLSTACK_LIMIT);
+ DUK_WO_NORETURN(return;);
}
DUK_LOCAL DUK_ALWAYS_INLINE void duk__call_callstack_limit_check(duk_hthread *thr) {
@@ -61095,7 +66237,8 @@ DUK_LOCAL void duk__interrupt_fixup(duk_hthread *thr, duk_hthread *entry_curr_th
thr->heap->inst_count_interrupt += thr->interrupt_init;
DUK_DD(DUK_DDPRINT("debug test: updated interrupt count on exit to "
"user code, instruction counts: executor=%ld, interrupt=%ld",
- (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
+ (long) thr->heap->inst_count_exec,
+ (long) thr->heap->inst_count_interrupt));
DUK_ASSERT(thr->heap->inst_count_exec == thr->heap->inst_count_interrupt);
}
#else
@@ -61114,12 +66257,9 @@ DUK_LOCAL void duk__interrupt_fixup(duk_hthread *thr, duk_hthread *entry_curr_th
* object flag DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS.
*/
-DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
- duk_hobject *func,
- duk_hobject *varenv,
- duk_idx_t idx_args) {
- duk_hobject *arg; /* 'arguments' */
- duk_hobject *formals; /* formals for 'func' (may be NULL if func is a C function) */
+DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr, duk_hobject *func, duk_hobject *varenv, duk_idx_t idx_args) {
+ duk_hobject *arg; /* 'arguments' */
+ duk_hobject *formals; /* formals for 'func' (may be NULL if func is a C function) */
duk_idx_t i_arg;
duk_idx_t i_map;
duk_idx_t i_mappednames;
@@ -61146,11 +66286,10 @@ DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
DUK_ASSERT(i_argbase >= 0);
DUK_ASSERT(num_stack_args >= 0);
- duk_push_hobject(thr, func);
- duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_FORMALS);
- formals = duk_get_hobject(thr, -1);
+ formals = (duk_hobject *) duk_hobject_get_formals(thr, (duk_hobject *) func);
if (formals) {
- n_formals = (duk_idx_t) duk_get_length(thr, -1);
+ n_formals = (duk_idx_t) ((duk_harray *) formals)->length;
+ duk_push_hobject(thr, formals);
} else {
/* This shouldn't happen without tampering of internal
* properties: if a function accesses 'arguments', _Formals
@@ -61159,46 +66298,44 @@ DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
*/
DUK_D(DUK_DPRINT("_Formals is undefined when creating arguments, use n_formals == 0"));
n_formals = 0;
+ duk_push_undefined(thr);
}
- duk_remove_m2(thr); /* leave formals on stack for later use */
i_formals = duk_require_top_index(thr);
DUK_ASSERT(n_formals >= 0);
DUK_ASSERT(formals != NULL || n_formals == 0);
- DUK_DDD(DUK_DDDPRINT("func=%!O, formals=%!O, n_formals=%ld",
- (duk_heaphdr *) func, (duk_heaphdr *) formals,
- (long) n_formals));
+ DUK_DDD(
+ DUK_DDDPRINT("func=%!O, formals=%!O, n_formals=%ld", (duk_heaphdr *) func, (duk_heaphdr *) formals, (long) n_formals));
/* [ ... formals ] */
/*
* Create required objects:
* - 'arguments' object: array-like, but not an array
- * - 'map' object: internal object, tied to 'arguments'
- * - 'mappedNames' object: temporary value used during construction
+ * - 'map' object: internal object, tied to 'arguments' (bare)
+ * - 'mappedNames' object: temporary value used during construction (bare)
*/
arg = duk_push_object_helper(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_FLAG_ARRAY_PART |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARGUMENTS),
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS | DUK_HOBJECT_FLAG_ARRAY_PART |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARGUMENTS),
DUK_BIDX_OBJECT_PROTOTYPE);
DUK_ASSERT(arg != NULL);
(void) duk_push_object_helper(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
- -1); /* no prototype */
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
+ -1); /* no prototype */
(void) duk_push_object_helper(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_FLAG_FASTREFS |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
- -1); /* no prototype */
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_FASTREFS |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
+ -1); /* no prototype */
i_arg = duk_get_top(thr) - 3;
i_map = i_arg + 1;
i_mappednames = i_arg + 2;
+ DUK_ASSERT(!duk_is_bare_object(thr, -3)); /* arguments */
+ DUK_ASSERT(duk_is_bare_object(thr, -2)); /* map */
+ DUK_ASSERT(duk_is_bare_object(thr, -1)); /* mappedNames */
/* [ ... formals arguments map mappedNames ] */
@@ -61206,9 +66343,12 @@ DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
"arguments at index %ld -> %!O "
"map at index %ld -> %!O "
"mappednames at index %ld -> %!O",
- (long) i_arg, (duk_heaphdr *) duk_get_hobject(thr, i_arg),
- (long) i_map, (duk_heaphdr *) duk_get_hobject(thr, i_map),
- (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));
+ (long) i_arg,
+ (duk_heaphdr *) duk_get_hobject(thr, i_arg),
+ (long) i_map,
+ (duk_heaphdr *) duk_get_hobject(thr, i_map),
+ (long) i_mappednames,
+ (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));
/*
* Init arguments properties, map, etc.
@@ -61224,8 +66364,8 @@ DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
/* step 11 */
idx = num_stack_args - 1;
while (idx >= 0) {
- DUK_DDD(DUK_DDDPRINT("arg idx %ld, argbase=%ld, argidx=%ld",
- (long) idx, (long) i_argbase, (long) (i_argbase + idx)));
+ DUK_DDD(
+ DUK_DDDPRINT("arg idx %ld, argbase=%ld, argidx=%ld", (long) idx, (long) i_argbase, (long) (i_argbase + idx)));
DUK_DDD(DUK_DDDPRINT("define arguments[%ld]=arg", (long) idx));
duk_dup(thr, i_argbase + idx);
@@ -61236,13 +66376,12 @@ DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
if (!DUK_HOBJECT_HAS_STRICT(func) && idx < n_formals) {
DUK_ASSERT(formals != NULL);
- DUK_DDD(DUK_DDDPRINT("strict function, index within formals (%ld < %ld)",
- (long) idx, (long) n_formals));
+ DUK_DDD(DUK_DDDPRINT("strict function, index within formals (%ld < %ld)", (long) idx, (long) n_formals));
duk_get_prop_index(thr, i_formals, (duk_uarridx_t) idx);
DUK_ASSERT(duk_is_string(thr, -1));
- duk_dup_top(thr); /* [ ... name name ] */
+ duk_dup_top(thr); /* [ ... name name ] */
if (!duk_has_prop(thr, i_mappednames)) {
/* steps 11.c.ii.1 - 11.c.ii.4, but our internal book-keeping
@@ -61253,24 +66392,21 @@ DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
need_map = 1;
- DUK_DDD(DUK_DDDPRINT("set mappednames[%s]=%ld",
- (const char *) duk_get_string(thr, -1),
- (long) idx));
- duk_dup_top(thr); /* name */
- (void) duk_push_uint_to_hstring(thr, (duk_uint_t) idx); /* index */
- duk_xdef_prop_wec(thr, i_mappednames); /* out of spec, must be configurable */
+ DUK_DDD(
+ DUK_DDDPRINT("set mappednames[%s]=%ld", (const char *) duk_get_string(thr, -1), (long) idx));
+ duk_dup_top(thr); /* name */
+ (void) duk_push_uint_to_hstring(thr, (duk_uint_t) idx); /* index */
+ duk_xdef_prop_wec(thr, i_mappednames); /* out of spec, must be configurable */
- DUK_DDD(DUK_DDDPRINT("set map[%ld]=%s",
- (long) idx,
- duk_get_string(thr, -1)));
- duk_dup_top(thr); /* name */
- duk_xdef_prop_index_wec(thr, i_map, (duk_uarridx_t) idx); /* out of spec, must be configurable */
+ DUK_DDD(DUK_DDDPRINT("set map[%ld]=%s", (long) idx, duk_get_string(thr, -1)));
+ duk_dup_top(thr); /* name */
+ duk_xdef_prop_index_wec(thr, i_map, (duk_uarridx_t) idx); /* out of spec, must be configurable */
} else {
/* duk_has_prop() popped the second 'name' */
}
/* [ ... name ] */
- duk_pop(thr); /* pop 'name' */
+ duk_pop(thr); /* pop 'name' */
}
idx--;
@@ -61286,7 +66422,7 @@ DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));
duk_dup(thr, i_map);
- duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_MAP, DUK_PROPDESC_FLAGS_NONE); /* out of spec, don't care */
+ duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_MAP, DUK_PROPDESC_FLAGS_NONE); /* out of spec, don't care */
/* The variable environment for magic variable bindings needs to be
* given by the caller and recorded in the arguments object.
@@ -61298,7 +66434,7 @@ DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
*/
duk_push_hobject(thr, varenv);
- duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_NONE); /* out of spec, don't care */
+ duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_NONE); /* out of spec, don't care */
}
/* steps 13-14 */
@@ -61318,7 +66454,7 @@ DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
DUK_DDD(DUK_DDDPRINT("strict function, setting caller/callee to throwers"));
- duk_xdef_prop_stridx_thrower(thr, i_arg, DUK_STRIDX_CALLER);
+ /* In ES2017 .caller is no longer set at all. */
duk_xdef_prop_stridx_thrower(thr, i_arg, DUK_STRIDX_CALLEE);
} else {
DUK_DDD(DUK_DDDPRINT("non-strict function, setting callee to actual value"));
@@ -61351,9 +66487,12 @@ DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
"arguments at index %ld -> %!O "
"map at index %ld -> %!O "
"mappednames at index %ld -> %!O",
- (long) i_arg, (duk_heaphdr *) duk_get_hobject(thr, i_arg),
- (long) i_map, (duk_heaphdr *) duk_get_hobject(thr, i_map),
- (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));
+ (long) i_arg,
+ (duk_heaphdr *) duk_get_hobject(thr, i_arg),
+ (long) i_map,
+ (duk_heaphdr *) duk_get_hobject(thr, i_map),
+ (long) i_mappednames,
+ (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));
/* [ args(n) envobj formals arguments map mappednames ] */
@@ -61366,10 +66505,7 @@ DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
/* Helper for creating the arguments object and adding it to the env record
* on top of the value stack.
*/
-DUK_LOCAL void duk__handle_createargs_for_call(duk_hthread *thr,
- duk_hobject *func,
- duk_hobject *env,
- duk_idx_t idx_args) {
+DUK_LOCAL void duk__handle_createargs_for_call(duk_hthread *thr, duk_hobject *func, duk_hobject *env, duk_idx_t idx_args) {
DUK_DDD(DUK_DDDPRINT("creating arguments object for function call"));
DUK_ASSERT(thr != NULL);
@@ -61379,18 +66515,15 @@ DUK_LOCAL void duk__handle_createargs_for_call(duk_hthread *thr,
/* [ ... arg1 ... argN envobj ] */
- duk__create_arguments_object(thr,
- func,
- env,
- idx_args);
+ duk__create_arguments_object(thr, func, env, idx_args);
/* [ ... arg1 ... argN envobj argobj ] */
duk_xdef_prop_stridx_short(thr,
-2,
DUK_STRIDX_LC_ARGUMENTS,
- DUK_HOBJECT_HAS_STRICT(func) ? DUK_PROPDESC_FLAGS_E : /* strict: non-deletable, non-writable */
- DUK_PROPDESC_FLAGS_WE); /* non-strict: non-deletable, writable */
+ DUK_HOBJECT_HAS_STRICT(func) ? DUK_PROPDESC_FLAGS_E : /* strict: non-deletable, non-writable */
+ DUK_PROPDESC_FLAGS_WE); /* non-strict: non-deletable, writable */
/* [ ... arg1 ... argN envobj ] */
}
@@ -61440,7 +66573,8 @@ DUK_LOCAL void duk__update_default_instance_proto(duk_hthread *thr, duk_idx_t id
"-> leave standard Object prototype as fallback prototype"));
} else {
DUK_DDD(DUK_DDDPRINT("constructor has 'prototype' property with object value "
- "-> set fallback prototype to that value: %!iO", (duk_heaphdr *) proto));
+ "-> set fallback prototype to that value: %!iO",
+ (duk_heaphdr *) proto));
/* Original fallback (default instance) is untouched when
* resolving bound functions etc.
*/
@@ -61462,14 +66596,13 @@ DUK_INTERNAL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uin
* Object (we accept object-like values like buffers and
* lightfuncs too). If not, TypeError.
*/
- if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
- DUK_TYPE_MASK_BUFFER |
- DUK_TYPE_MASK_LIGHTFUNC)) {
+ if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_BUFFER | DUK_TYPE_MASK_LIGHTFUNC)) {
DUK_DDD(DUK_DDDPRINT("replacement value"));
} else {
if (DUK_UNLIKELY(proxy_invariant != 0U)) {
/* Proxy 'construct' return value invariant violated. */
DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr);
+ DUK_WO_NORETURN(return;);
}
/* XXX: direct value stack access */
duk_pop(thr);
@@ -61485,8 +66618,7 @@ DUK_INTERNAL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uin
* out right; however it is always synced here so just assert for it.
*/
DUK_ASSERT(thr->ptr_curr_pc == NULL);
- duk_err_augment_error_create(thr, thr, NULL, 0, DUK_AUGMENT_FLAG_NOBLAME_FILELINE |
- DUK_AUGMENT_FLAG_SKIP_ONE);
+ duk_err_augment_error_create(thr, thr, NULL, 0, DUK_AUGMENT_FLAG_NOBLAME_FILELINE | DUK_AUGMENT_FLAG_SKIP_ONE);
#endif
}
@@ -61503,9 +66635,7 @@ DUK_INTERNAL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uin
* [[BoundThis]].
*/
-DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr,
- duk_idx_t idx_func,
- duk_bool_t is_constructor_call) {
+DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr, duk_idx_t idx_func, duk_bool_t is_constructor_call) {
duk_tval *tv_func;
duk_hobject *func;
duk_idx_t len;
@@ -61530,13 +66660,14 @@ DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr,
duk_tval *tv_args;
duk_tval *tv_gap;
- h_bound = (duk_hboundfunc *) func;
+ h_bound = (duk_hboundfunc *) (void *) func;
tv_args = h_bound->args;
len = h_bound->nargs;
DUK_ASSERT(len == 0 || tv_args != NULL);
DUK_DDD(DUK_DDDPRINT("bound function encountered, ptr=%p: %!T",
- (void *) DUK_TVAL_GET_OBJECT(tv_func), tv_func));
+ (void *) DUK_TVAL_GET_OBJECT(tv_func),
+ tv_func));
/* [ ... func this arg1 ... argN ] */
@@ -61546,7 +66677,7 @@ DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr,
} else {
/* XXX: duk_replace_tval */
duk_push_tval(thr, &h_bound->this_binding);
- duk_replace(thr, idx_func + 1); /* idx_this = idx_func + 1 */
+ duk_replace(thr, idx_func + 1); /* idx_this = idx_func + 1 */
}
/* [ ... func this arg1 ... argN ] */
@@ -61559,10 +66690,11 @@ DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr,
/* [ ... func this <bound args> arg1 ... argN ] */
duk_push_tval(thr, &h_bound->target);
- duk_replace(thr, idx_func); /* replace in stack */
+ duk_replace(thr, idx_func); /* replace in stack */
DUK_DDD(DUK_DDDPRINT("bound function handled, idx_func=%ld, curr func=%!T",
- (long) idx_func, duk_get_tval(thr, idx_func)));
+ (long) idx_func,
+ duk_get_tval(thr, idx_func)));
}
} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
/* Lightweight function: never bound, so terminate. */
@@ -61570,6 +66702,7 @@ DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr,
} else {
/* Shouldn't happen, so ugly error is enough. */
DUK_ERROR_INTERNAL(thr);
+ DUK_WO_NORETURN(return;);
}
DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
@@ -61583,8 +66716,7 @@ DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr,
func = DUK_TVAL_GET_OBJECT(tv_func);
DUK_ASSERT(func != NULL);
DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
- DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func) ||
- DUK_HOBJECT_HAS_NATFUNC(func));
+ DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func) || DUK_HOBJECT_HAS_NATFUNC(func) || DUK_HOBJECT_IS_PROXY(func));
}
#endif
}
@@ -61593,14 +66725,18 @@ DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr,
* Helper for inline handling of .call(), .apply(), and .construct().
*/
-DUK_LOCAL duk_bool_t duk__handle_specialfuncs_for_call(duk_hthread *thr, duk_idx_t idx_func, duk_hobject *func, duk_small_uint_t *call_flags, duk_bool_t first) {
+DUK_LOCAL duk_bool_t duk__handle_specialfuncs_for_call(duk_hthread *thr,
+ duk_idx_t idx_func,
+ duk_hobject *func,
+ duk_small_uint_t *call_flags,
+ duk_bool_t first) {
#if defined(DUK_USE_ASSERTIONS)
duk_c_function natfunc;
#endif
duk_tval *tv_args;
DUK_ASSERT(func != NULL);
- DUK_ASSERT((*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0); /* Caller. */
+ DUK_ASSERT((*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0); /* Caller. */
#if defined(DUK_USE_ASSERTIONS)
natfunc = ((duk_hnatfunc *) func)->func;
@@ -61628,7 +66764,7 @@ DUK_LOCAL duk_bool_t duk__handle_specialfuncs_for_call(duk_hthread *thr, duk_idx
*call_flags = (*call_flags & ~DUK_CALL_FLAG_CALLED_AS_EVAL) | DUK_CALL_FLAG_DIRECT_EVAL;
}
DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
- return 1; /* stop resolving */
+ return 1; /* stop resolving */
}
/* Handle special functions based on the DUK_HOBJECT_FLAG_SPECIAL_CALL
@@ -61638,7 +66774,7 @@ DUK_LOCAL duk_bool_t duk__handle_specialfuncs_for_call(duk_hthread *thr, duk_idx
* for the result values (unlike most other value stack calls).
*/
switch (((duk_hnatfunc *) func)->magic) {
- case 0: { /* 0=Function.prototype.call() */
+ case 0: { /* 0=Function.prototype.call() */
/* Value stack:
* idx_func + 0: Function.prototype.call() [removed]
* idx_func + 1: this binding for .call (target function)
@@ -61657,11 +66793,11 @@ DUK_LOCAL duk_bool_t duk__handle_specialfuncs_for_call(duk_hthread *thr, duk_idx
tv_args = thr->valstack_bottom + idx_func + 2;
if (thr->valstack_top < tv_args) {
DUK_ASSERT(tv_args <= thr->valstack_end);
- thr->valstack_top = tv_args; /* at least target function and 'this' binding present */
+ thr->valstack_top = tv_args; /* at least target function and 'this' binding present */
}
break;
}
- case 1: { /* 1=Function.prototype.apply() */
+ case 1: { /* 1=Function.prototype.apply() */
/* Value stack:
* idx_func + 0: Function.prototype.apply() [removed]
* idx_func + 1: this binding for .apply (target function)
@@ -61680,7 +66816,7 @@ DUK_LOCAL duk_bool_t duk__handle_specialfuncs_for_call(duk_hthread *thr, duk_idx
goto apply_shared;
}
#if defined(DUK_USE_REFLECT_BUILTIN)
- case 2: { /* 2=Reflect.apply() */
+ case 2: { /* 2=Reflect.apply() */
/* Value stack:
* idx_func + 0: Reflect.apply() [removed]
* idx_func + 1: this binding for .apply (ignored, usually Reflect) [removed]
@@ -61699,7 +66835,7 @@ DUK_LOCAL duk_bool_t duk__handle_specialfuncs_for_call(duk_hthread *thr, duk_idx
duk_remove_n_unsafe(thr, idx_func, 2);
goto apply_shared;
}
- case 3: { /* 3=Reflect.construct() */
+ case 3: { /* 3=Reflect.construct() */
/* Value stack:
* idx_func + 0: Reflect.construct() [removed]
* idx_func + 1: this binding for .construct (ignored, usually Reflect) [removed]
@@ -61733,11 +66869,11 @@ DUK_LOCAL duk_bool_t duk__handle_specialfuncs_for_call(duk_hthread *thr, duk_idx
* unpacking argArray (which may cause side effects).
* Just return; caller will throw the error.
*/
- duk_set_top_unsafe(thr, idx_func + 2); /* satisfy asserts */
+ duk_set_top_unsafe(thr, idx_func + 2); /* satisfy asserts */
break;
}
duk_push_object(thr);
- duk_insert(thr, idx_func + 1); /* default instance */
+ duk_insert(thr, idx_func + 1); /* default instance */
/* [ ... func default_instance argArray newTarget? ] */
@@ -61745,22 +66881,25 @@ DUK_LOCAL duk_bool_t duk__handle_specialfuncs_for_call(duk_hthread *thr, duk_idx
if (top < idx_func + 3) {
/* argArray is a mandatory argument for Reflect.construct(). */
DUK_ERROR_TYPE_INVALID_ARGS(thr);
+ DUK_WO_NORETURN(return 0;);
}
if (top > idx_func + 3) {
if (!duk_strict_equals(thr, idx_func, idx_func + 3)) {
/* XXX: [[Construct]] newTarget currently unsupported */
DUK_ERROR_UNSUPPORTED(thr);
+ DUK_WO_NORETURN(return 0;);
}
- duk_set_top_unsafe(thr, idx_func + 3); /* remove any args beyond argArray */
+ duk_set_top_unsafe(thr, idx_func + 3); /* remove any args beyond argArray */
}
DUK_ASSERT(duk_get_top(thr) == idx_func + 3);
DUK_ASSERT(duk_is_valid_index(thr, idx_func + 2));
- (void) duk_unpack_array_like(thr, idx_func + 2); /* XXX: should also remove target to be symmetric with duk_pack()? */
+ (void) duk_unpack_array_like(thr,
+ idx_func + 2); /* XXX: should also remove target to be symmetric with duk_pack()? */
duk_remove(thr, idx_func + 2);
DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
break;
}
-#endif /* DUK_USE_REFLECT_BUILTIN */
+#endif /* DUK_USE_REFLECT_BUILTIN */
default: {
DUK_ASSERT(0);
DUK_UNREACHABLE();
@@ -61768,18 +66907,18 @@ DUK_LOCAL duk_bool_t duk__handle_specialfuncs_for_call(duk_hthread *thr, duk_idx
}
DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
- return 0; /* keep resolving */
+ return 0; /* keep resolving */
- apply_shared:
+apply_shared:
tv_args = thr->valstack_bottom + idx_func + 2;
if (thr->valstack_top <= tv_args) {
DUK_ASSERT(tv_args <= thr->valstack_end);
- thr->valstack_top = tv_args; /* at least target func and 'this' binding present */
+ thr->valstack_top = tv_args; /* at least target func and 'this' binding present */
/* No need to check for argArray. */
} else {
- DUK_ASSERT(duk_get_top(thr) >= idx_func + 3); /* idx_func + 2 covered above */
+ DUK_ASSERT(duk_get_top(thr) >= idx_func + 3); /* idx_func + 2 covered above */
if (thr->valstack_top > tv_args + 1) {
- duk_set_top_unsafe(thr, idx_func + 3); /* remove any args beyond argArray */
+ duk_set_top_unsafe(thr, idx_func + 3); /* remove any args beyond argArray */
}
DUK_ASSERT(duk_is_valid_index(thr, idx_func + 2));
if (!duk_is_callable(thr, idx_func)) {
@@ -61792,7 +66931,7 @@ DUK_LOCAL duk_bool_t duk__handle_specialfuncs_for_call(duk_hthread *thr, duk_idx
}
}
DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
- return 0; /* keep resolving */
+ return 0; /* keep resolving */
}
/*
@@ -61877,6 +67016,7 @@ DUK_LOCAL void duk__handle_proxy_for_call(duk_hthread *thr, duk_idx_t idx_func,
duk_push_hobject(thr, h_proxy->target);
duk_insert(thr, idx_func + 3);
duk_pack(thr, duk_get_top(thr) - (idx_func + 5));
+ DUK_ASSERT(!duk_is_bare_object(thr, -1));
/* Here:
* idx_func + 0: Proxy object
@@ -61889,8 +67029,8 @@ DUK_LOCAL void duk__handle_proxy_for_call(duk_hthread *thr, duk_idx_t idx_func,
DUK_ASSERT(duk_get_top(thr) == idx_func + 6);
if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
- *call_flags |= DUK_CALL_FLAG_CONSTRUCT_PROXY; /* Enable 'construct' trap return invariant check. */
- *call_flags &= ~(DUK_CALL_FLAG_CONSTRUCT); /* Resume as non-constructor call to the trap. */
+ *call_flags |= DUK_CALL_FLAG_CONSTRUCT_PROXY; /* Enable 'construct' trap return invariant check. */
+ *call_flags &= ~(DUK_CALL_FLAG_CONSTRUCT); /* Resume as non-constructor call to the trap. */
/* 'apply' args: target, thisArg, argArray
* 'construct' args: target, argArray, newTarget
@@ -61901,19 +67041,17 @@ DUK_LOCAL void duk__handle_proxy_for_call(duk_hthread *thr, duk_idx_t idx_func,
/* Finalize value stack layout by removing Proxy reference. */
duk_remove(thr, idx_func);
- h_proxy = NULL; /* invalidated */
+ h_proxy = NULL; /* invalidated */
DUK_ASSERT(duk_get_top(thr) == idx_func + 5);
}
-#endif /* DUK_USE_ES6_PROXY */
+#endif /* DUK_USE_ES6_PROXY */
/*
* Helper for setting up var_env and lex_env of an activation,
* assuming it does NOT have the DUK_HOBJECT_FLAG_NEWENV flag.
*/
-DUK_LOCAL void duk__handle_oldenv_for_call(duk_hthread *thr,
- duk_hobject *func,
- duk_activation *act) {
+DUK_LOCAL void duk__handle_oldenv_for_call(duk_hthread *thr, duk_hobject *func, duk_activation *act) {
duk_hcompfunc *f;
duk_hobject *h_lex;
duk_hobject *h_var;
@@ -61929,7 +67067,7 @@ DUK_LOCAL void duk__handle_oldenv_for_call(duk_hthread *thr,
f = (duk_hcompfunc *) func;
h_lex = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
h_var = DUK_HCOMPFUNC_GET_VARENV(thr->heap, f);
- DUK_ASSERT(h_lex != NULL); /* Always true for closures (not for templates) */
+ DUK_ASSERT(h_lex != NULL); /* Always true for closures (not for templates) */
DUK_ASSERT(h_var != NULL);
act->lex_env = h_lex;
act->var_env = h_var;
@@ -61950,7 +67088,7 @@ DUK_LOCAL void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func)
DUK_ASSERT(thr != NULL);
DUK_ASSERT(func != NULL);
- DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func)); /* bound chain resolved */
+ DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func)); /* bound chain resolved */
DUK_ASSERT(thr->callstack_top >= 1);
if (DUK_HOBJECT_HAS_STRICT(func)) {
@@ -61966,7 +67104,7 @@ DUK_LOCAL void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func)
/* XXX: check .caller writability? */
/* Backup 'caller' property and update its value. */
- tv_caller = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_CALLER(thr));
+ tv_caller = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, func, DUK_STRIDX_CALLER);
if (tv_caller) {
/* If caller is global/eval code, 'caller' should be set to
* 'null'.
@@ -62004,7 +67142,7 @@ DUK_LOCAL void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func)
DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
DUK_TVAL_INCREF(thr, tv_caller);
} else {
- DUK_TVAL_SET_NULL(tv_caller); /* no incref */
+ DUK_TVAL_SET_NULL(tv_caller); /* no incref */
}
} else {
/* 'caller' must only take on 'null' or function value */
@@ -62017,12 +67155,12 @@ DUK_LOCAL void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func)
DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
DUK_TVAL_INCREF(thr, tv_caller);
} else {
- DUK_TVAL_SET_NULL(tv_caller); /* no incref */
+ DUK_TVAL_SET_NULL(tv_caller); /* no incref */
}
}
}
}
-#endif /* DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
+#endif /* DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
/*
* Shared helpers for resolving the final, non-bound target function of the
@@ -62068,7 +67206,7 @@ DUK_LOCAL DUK_INLINE void duk__coerce_nonstrict_this_binding(duk_hthread *thr, d
obj_global = thr->builtins[DUK_BIDX_GLOBAL];
/* XXX: avoid this check somehow */
if (DUK_LIKELY(obj_global != NULL)) {
- DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this)); /* no need to decref previous value */
+ DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this)); /* no need to decref previous value */
DUK_TVAL_SET_OBJECT(tv_this, obj_global);
DUK_HOBJECT_INCREF(thr, obj_global);
} else {
@@ -62076,8 +67214,8 @@ DUK_LOCAL DUK_INLINE void duk__coerce_nonstrict_this_binding(duk_hthread *thr, d
* This behavior is out of specification scope.
*/
DUK_D(DUK_DPRINT("this binding: wanted to use global object, but it is NULL -> using undefined instead"));
- DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this)); /* no need to decref previous value */
- DUK_TVAL_SET_UNDEFINED(tv_this); /* nothing to incref */
+ DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this)); /* no need to decref previous value */
+ DUK_TVAL_SET_UNDEFINED(tv_this); /* nothing to incref */
}
break;
default:
@@ -62088,18 +67226,21 @@ DUK_LOCAL DUK_INLINE void duk__coerce_nonstrict_this_binding(duk_hthread *thr, d
*/
DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_this));
DUK_DDD(DUK_DDDPRINT("this binding: non-strict, not object/undefined/null -> use ToObject(value)"));
- duk_to_object(thr, idx_this); /* may have side effects */
+ duk_to_object(thr, idx_this); /* may have side effects */
break;
}
}
-DUK_LOCAL DUK_ALWAYS_INLINE duk_bool_t duk__resolve_target_fastpath_check(duk_hthread *thr, duk_idx_t idx_func, duk_hobject **out_func, duk_small_uint_t call_flags) {
+DUK_LOCAL DUK_ALWAYS_INLINE duk_bool_t duk__resolve_target_fastpath_check(duk_hthread *thr,
+ duk_idx_t idx_func,
+ duk_hobject **out_func,
+ duk_small_uint_t call_flags) {
#if defined(DUK_USE_PREFER_SIZE)
DUK_UNREF(thr);
DUK_UNREF(idx_func);
DUK_UNREF(out_func);
DUK_UNREF(call_flags);
-#else /* DUK_USE_PREFER_SIZE */
+#else /* DUK_USE_PREFER_SIZE */
duk_tval *tv_func;
duk_hobject *func;
@@ -62112,9 +67253,7 @@ DUK_LOCAL DUK_ALWAYS_INLINE duk_bool_t duk__resolve_target_fastpath_check(duk_ht
if (DUK_LIKELY(DUK_TVAL_IS_OBJECT(tv_func))) {
func = DUK_TVAL_GET_OBJECT(tv_func);
- if (DUK_HOBJECT_IS_CALLABLE(func) &&
- !DUK_HOBJECT_HAS_BOUNDFUNC(func) &&
- !DUK_HOBJECT_HAS_SPECIAL_CALL(func)) {
+ if (DUK_HOBJECT_IS_CALLABLE(func) && !DUK_HOBJECT_HAS_BOUNDFUNC(func) && !DUK_HOBJECT_HAS_SPECIAL_CALL(func)) {
*out_func = func;
if (DUK_HOBJECT_HAS_STRICT(func)) {
@@ -62134,8 +67273,8 @@ DUK_LOCAL DUK_ALWAYS_INLINE duk_bool_t duk__resolve_target_fastpath_check(duk_ht
*/
return 1;
}
-#endif /* DUK_USE_PREFER_SIZE */
- return 0; /* let slow path deal with it */
+#endif /* DUK_USE_PREFER_SIZE */
+ return 0; /* let slow path deal with it */
}
DUK_LOCAL duk_hobject *duk__resolve_target_func_and_this_binding(duk_hthread *thr,
@@ -62153,6 +67292,8 @@ DUK_LOCAL duk_hobject *duk__resolve_target_func_and_this_binding(duk_hthread *th
tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
DUK_ASSERT(tv_func != NULL);
+ DUK_DD(DUK_DDPRINT("target func: %!iT", tv_func));
+
if (DUK_TVAL_IS_OBJECT(tv_func)) {
func = DUK_TVAL_GET_OBJECT(tv_func);
@@ -62166,8 +67307,7 @@ DUK_LOCAL duk_hobject *duk__resolve_target_func_and_this_binding(duk_hthread *th
}
}
- if (DUK_LIKELY(!DUK_HOBJECT_HAS_BOUNDFUNC(func) &&
- !DUK_HOBJECT_HAS_SPECIAL_CALL(func) &&
+ if (DUK_LIKELY(!DUK_HOBJECT_HAS_BOUNDFUNC(func) && !DUK_HOBJECT_HAS_SPECIAL_CALL(func) &&
!DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(func))) {
/* Common case, so test for using a single bitfield test.
* Break out to handle this coercion etc.
@@ -62203,8 +67343,7 @@ DUK_LOCAL duk_hobject *duk__resolve_target_func_and_this_binding(duk_hthread *th
* the trap may be bound.
*/
duk__handle_proxy_for_call(thr, idx_func, (duk_hproxy *) func, call_flags);
- }
- else
+ } else
#endif
{
DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(func));
@@ -62251,41 +67390,43 @@ DUK_LOCAL duk_hobject *duk__resolve_target_func_and_this_binding(duk_hthread *th
}
}
- finished:
-
+finished :
#if defined(DUK_USE_ASSERTIONS)
- {
- duk_tval *tv_tmp;
+{
+ duk_tval *tv_tmp;
- tv_tmp = duk_get_tval(thr, idx_func);
- DUK_ASSERT(tv_tmp != NULL);
+ tv_tmp = duk_get_tval(thr, idx_func);
+ DUK_ASSERT(tv_tmp != NULL);
- DUK_ASSERT((DUK_TVAL_IS_OBJECT(tv_tmp) && DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(tv_tmp))) ||
- DUK_TVAL_IS_LIGHTFUNC(tv_tmp));
- DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
- DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) ||
- DUK_HOBJECT_IS_NATFUNC(func)));
- DUK_ASSERT(func == NULL || (DUK_HOBJECT_HAS_CONSTRUCTABLE(func) ||
- (*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0));
- }
+ DUK_ASSERT((DUK_TVAL_IS_OBJECT(tv_tmp) && DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(tv_tmp))) ||
+ DUK_TVAL_IS_LIGHTFUNC(tv_tmp));
+ DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
+ DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) || DUK_HOBJECT_IS_NATFUNC(func)));
+ DUK_ASSERT(func == NULL || (DUK_HOBJECT_HAS_CONSTRUCTABLE(func) || (*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0));
+}
#endif
return func;
- not_callable:
+not_callable:
DUK_ASSERT(tv_func != NULL);
#if defined(DUK_USE_VERBOSE_ERRORS)
/* GETPROPC delayed error handling: when target is not callable,
- * GETPROPC replaces idx_func+0 with an Error (non-callable) with
- * a hidden Symbol to signify it's to be thrown as is here. The
+ * GETPROPC replaces idx_func+0 with a non-callable wrapper object
+ * with a hidden Symbol to signify it's to be handled here. If
+ * found, unwrap the original Error and throw it as is here. The
* hidden Symbol is only checked as an own property, not inherited
* (which would be dangerous).
*/
if (DUK_TVAL_IS_OBJECT(tv_func)) {
- if (duk_hobject_find_existing_entry_tval_ptr(thr->heap, DUK_TVAL_GET_OBJECT(tv_func), DUK_HTHREAD_STRING_INT_TARGET(thr)) != NULL) {
- duk_push_tval(thr, tv_func);
+ duk_tval *tv_wrap =
+ duk_hobject_find_entry_tval_ptr_stridx(thr->heap, DUK_TVAL_GET_OBJECT(tv_func), DUK_STRIDX_INT_TARGET);
+ if (tv_wrap != NULL) {
+ DUK_DD(DUK_DDPRINT("delayed error from GETPROPC: %!T", tv_wrap));
+ duk_push_tval(thr, tv_wrap);
(void) duk_throw(thr);
+ DUK_WO_NORETURN(return NULL;);
}
}
#endif
@@ -62299,10 +67440,9 @@ DUK_LOCAL duk_hobject *duk__resolve_target_func_and_this_binding(duk_hthread *th
#else
DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
#endif
- DUK_UNREACHABLE();
- return NULL; /* never executed */
+ DUK_WO_NORETURN(return NULL;);
- not_constructable:
+not_constructable:
/* For now GETPROPC delayed error not needed for constructor calls. */
#if defined(DUK_USE_VERBOSE_ERRORS)
#if defined(DUK_USE_PARANOID_ERRORS)
@@ -62313,8 +67453,7 @@ DUK_LOCAL duk_hobject *duk__resolve_target_func_and_this_binding(duk_hthread *th
#else
DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONSTRUCTABLE);
#endif
- DUK_UNREACHABLE();
- return NULL; /* never executed */
+ DUK_WO_NORETURN(return NULL;);
}
/*
@@ -62327,7 +67466,10 @@ DUK_LOCAL duk_hobject *duk__resolve_target_func_and_this_binding(duk_hthread *th
* empty (below idx_retbase).
*/
-DUK_LOCAL void duk__safe_call_adjust_valstack(duk_hthread *thr, duk_idx_t idx_retbase, duk_idx_t num_stack_rets, duk_idx_t num_actual_rets) {
+DUK_LOCAL void duk__safe_call_adjust_valstack(duk_hthread *thr,
+ duk_idx_t idx_retbase,
+ duk_idx_t num_stack_rets,
+ duk_idx_t num_actual_rets) {
duk_idx_t idx_rcbase;
DUK_ASSERT(thr != NULL);
@@ -62335,17 +67477,21 @@ DUK_LOCAL void duk__safe_call_adjust_valstack(duk_hthread *thr, duk_idx_t idx_re
DUK_ASSERT(num_stack_rets >= 0);
DUK_ASSERT(num_actual_rets >= 0);
- idx_rcbase = duk_get_top(thr) - num_actual_rets; /* base of known return values */
+ idx_rcbase = duk_get_top(thr) - num_actual_rets; /* base of known return values */
if (DUK_UNLIKELY(idx_rcbase < 0)) {
DUK_ERROR_TYPE(thr, DUK_STR_INVALID_CFUNC_RC);
+ DUK_WO_NORETURN(return;);
}
DUK_DDD(DUK_DDDPRINT("adjust valstack after func call: "
"num_stack_rets=%ld, num_actual_rets=%ld, stack_top=%ld, idx_retbase=%ld, idx_rcbase=%ld",
- (long) num_stack_rets, (long) num_actual_rets, (long) duk_get_top(thr),
- (long) idx_retbase, (long) idx_rcbase));
+ (long) num_stack_rets,
+ (long) num_actual_rets,
+ (long) duk_get_top(thr),
+ (long) idx_retbase,
+ (long) idx_rcbase));
- DUK_ASSERT(idx_rcbase >= 0); /* caller must check */
+ DUK_ASSERT(idx_rcbase >= 0); /* caller must check */
/* Space for num_stack_rets was reserved before the safe call.
* Because value stack reserve cannot shrink except in call returns,
@@ -62360,24 +67506,28 @@ DUK_LOCAL void duk__safe_call_adjust_valstack(duk_hthread *thr, duk_idx_t idx_re
duk_idx_t count = idx_rcbase - idx_retbase;
DUK_DDD(DUK_DDDPRINT("elements at/after idx_retbase have enough to cover func retvals "
- "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
+ "(idx_retbase=%ld, idx_rcbase=%ld)",
+ (long) idx_retbase,
+ (long) idx_rcbase));
/* Remove values between irc_rcbase (start of intended return
* values) and idx_retbase to lower return values to idx_retbase.
*/
DUK_ASSERT(count > 0);
- duk_remove_n(thr, idx_retbase, count); /* may be NORZ */
+ duk_remove_n(thr, idx_retbase, count); /* may be NORZ */
} else {
duk_idx_t count = idx_retbase - idx_rcbase;
DUK_DDD(DUK_DDDPRINT("not enough elements at/after idx_retbase to cover func retvals "
- "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
+ "(idx_retbase=%ld, idx_rcbase=%ld)",
+ (long) idx_retbase,
+ (long) idx_rcbase));
/* Insert 'undefined' at idx_rcbase (start of intended return
* values) to lift return values to idx_retbase.
*/
DUK_ASSERT(count >= 0);
- DUK_ASSERT(thr->valstack_end - thr->valstack_top >= count); /* reserve cannot shrink */
+ DUK_ASSERT(thr->valstack_end - thr->valstack_top >= count); /* reserve cannot shrink */
duk_insert_undefined_n(thr, idx_rcbase, count);
}
@@ -62438,12 +67588,12 @@ DUK_LOCAL duk_small_uint_t duk__call_setup_act_attempt_tailcall(duk_hthread *thr
#if defined(DUK_USE_ES6_PROXY)
| (duk_small_uint_t) ((act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) ? 2 : 0)
#endif
- ;
+ ;
flags2 = (duk_small_uint_t) ((call_flags & DUK_CALL_FLAG_CONSTRUCT) ? 1 : 0)
#if defined(DUK_USE_ES6_PROXY)
| (duk_small_uint_t) ((call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) ? 2 : 0);
#endif
- ;
+ ;
if (flags1 != flags2) {
DUK_DDD(DUK_DDDPRINT("tail call prevented by incompatible return value handling"));
return 0;
@@ -62472,16 +67622,16 @@ DUK_LOCAL duk_small_uint_t duk__call_setup_act_attempt_tailcall(duk_hthread *thr
* - Disable StepOut processing for the activation unwind because
* we reuse the activation, see:
* https://github.com/svaarala/duktape/issues/1684.
- * - Disable line change pause flag permanently (if set) because
- * it would no longer be relevant, see:
- * https://github.com/svaarala/duktape/issues/1726.
+ * - Disable line change pause flag permanently if act == dbg_pause_act
+ * (if set) because it would no longer be relevant, see:
+ * https://github.com/svaarala/duktape/issues/1726,
+ * https://github.com/svaarala/duktape/issues/1786.
* - Check for function entry (e.g. StepInto) pause flag here, because
* the executor pause check won't trigger due to shared activation, see:
* https://github.com/svaarala/duktape/issues/1726.
*/
- DUK_DDD(DUK_DDDPRINT("is tail call, reusing activation at callstack top, at index %ld",
- (long) (thr->callstack_top - 1)));
+ DUK_DDD(DUK_DDDPRINT("is tail call, reusing activation at callstack top, at index %ld", (long) (thr->callstack_top - 1)));
DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(func));
@@ -62495,9 +67645,12 @@ DUK_LOCAL duk_small_uint_t duk__call_setup_act_attempt_tailcall(duk_hthread *thr
DUK_ASSERT(thr->callstack_top > 0);
DUK_ASSERT(thr->callstack_curr != NULL);
#if defined(DUK_USE_DEBUGGER_SUPPORT)
+ if (act == thr->heap->dbg_pause_act) {
+ thr->heap->dbg_pause_flags &= ~DUK_PAUSE_FLAG_LINE_CHANGE;
+ }
+
prev_pause_act = thr->heap->dbg_pause_act;
thr->heap->dbg_pause_act = NULL;
- thr->heap->dbg_pause_flags &= ~DUK_PAUSE_FLAG_LINE_CHANGE;
if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) {
DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function entry (tailcall)"));
duk_debug_set_paused(thr->heap);
@@ -62522,7 +67675,7 @@ DUK_LOCAL duk_small_uint_t duk__call_setup_act_attempt_tailcall(duk_hthread *thr
act->lex_env = NULL;
DUK_ASSERT(func != NULL);
DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
- act->func = func; /* don't want an intermediate exposed state with func == NULL */
+ act->func = func; /* don't want an intermediate exposed state with func == NULL */
#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
act->prev_caller = NULL;
#endif
@@ -62531,7 +67684,7 @@ DUK_LOCAL duk_small_uint_t duk__call_setup_act_attempt_tailcall(duk_hthread *thr
#if defined(DUK_USE_DEBUGGER_SUPPORT)
act->prev_line = 0;
#endif
- DUK_TVAL_SET_OBJECT(&act->tv_func, func); /* borrowed, no refcount */
+ DUK_TVAL_SET_OBJECT(&act->tv_func, func); /* borrowed, no refcount */
DUK_HOBJECT_INCREF(thr, func);
act->flags = DUK_ACT_FLAG_TAILCALLED;
@@ -62547,10 +67700,10 @@ DUK_LOCAL duk_small_uint_t duk__call_setup_act_attempt_tailcall(duk_hthread *thr
}
#endif
- DUK_ASSERT(DUK_ACT_GET_FUNC(act) == func); /* already updated */
+ DUK_ASSERT(DUK_ACT_GET_FUNC(act) == func); /* already updated */
DUK_ASSERT(act->var_env == NULL);
DUK_ASSERT(act->lex_env == NULL);
- act->bottom_byteoff = entry_valstack_bottom_byteoff; /* tail call -> reuse current "frame" */
+ act->bottom_byteoff = entry_valstack_bottom_byteoff; /* tail call -> reuse current "frame" */
#if 0
/* Topmost activation retval_byteoff is considered garbage, no need to init. */
act->retval_byteoff = 0;
@@ -62575,22 +67728,23 @@ DUK_LOCAL duk_small_uint_t duk__call_setup_act_attempt_tailcall(duk_hthread *thr
tv1 = thr->valstack_bottom - 1;
tv2 = thr->valstack_bottom + idx_func + 1;
- DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top); /* tv1 is -below- valstack_bottom */
+ DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top); /* tv1 is -below- valstack_bottom */
DUK_ASSERT(tv2 >= thr->valstack_bottom && tv2 < thr->valstack_top);
- DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
+ DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
idx_args = idx_func + 2;
- duk_remove_n(thr, 0, idx_args); /* may be NORZ */
+ duk_remove_n(thr, 0, idx_args); /* may be NORZ */
- idx_func = 0; DUK_UNREF(idx_func); /* really 'not applicable' anymore, should not be referenced after this */
+ idx_func = 0;
+ DUK_UNREF(idx_func); /* really 'not applicable' anymore, should not be referenced after this */
idx_args = 0;
*out_nargs = ((duk_hcompfunc *) func)->nargs;
*out_nregs = ((duk_hcompfunc *) func)->nregs;
DUK_ASSERT(*out_nregs >= 0);
DUK_ASSERT(*out_nregs >= *out_nargs);
- *out_vs_min_bytes = entry_valstack_bottom_byteoff + sizeof(duk_tval) * ((duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);
-
+ *out_vs_min_bytes =
+ entry_valstack_bottom_byteoff + sizeof(duk_tval) * ((duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);
#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
#if defined(DUK_USE_TAILCALL)
@@ -62607,7 +67761,7 @@ DUK_LOCAL duk_small_uint_t duk__call_setup_act_attempt_tailcall(duk_hthread *thr
return 1;
}
-#endif /* DUK_USE_TAILCALL */
+#endif /* DUK_USE_TAILCALL */
DUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr,
duk_small_uint_t call_flags,
@@ -62624,8 +67778,7 @@ DUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr,
DUK_UNREF(entry_valstack_end_byteoff);
- DUK_DDD(DUK_DDDPRINT("not a tail call, pushing a new activation to callstack, to index %ld",
- (long) (thr->callstack_top)));
+ DUK_DDD(DUK_DDDPRINT("not a tail call, pushing a new activation to callstack, to index %ld", (long) (thr->callstack_top)));
duk__call_callstack_limit_check(thr);
new_act = duk_hthread_activation_alloc(thr);
@@ -62637,10 +67790,10 @@ DUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr,
* Update return value stack index of current activation (if any).
*
* Although it might seem this is not necessary (bytecode executor
- * does this for Ecmascript-to-Ecmascript calls; other calls are
+ * does this for ECMAScript-to-ECMAScript calls; other calls are
* handled here), this turns out to be necessary for handling yield
- * and resume. For them, an Ecmascript-to-native call happens, and
- * the Ecmascript call's retval_byteoff must be set for things to work.
+ * and resume. For them, an ECMAScript-to-native call happens, and
+ * the ECMAScript call's retval_byteoff must be set for things to work.
*/
act->retval_byteoff = entry_valstack_bottom_byteoff + (duk_size_t) idx_func * sizeof(duk_tval);
@@ -62652,7 +67805,7 @@ DUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr,
act = new_act;
*out_act = act;
- DUK_ASSERT(thr->valstack_top > thr->valstack_bottom); /* at least effective 'this' */
+ DUK_ASSERT(thr->valstack_top > thr->valstack_bottom); /* at least effective 'this' */
DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
act->cat = NULL;
@@ -62671,9 +67824,9 @@ DUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr,
}
/* start of arguments: idx_func + 2. */
- act->func = func; /* NULL for lightfunc */
+ act->func = func; /* NULL for lightfunc */
if (DUK_LIKELY(func != NULL)) {
- DUK_TVAL_SET_OBJECT(&act->tv_func, func); /* borrowed, no refcount */
+ DUK_TVAL_SET_OBJECT(&act->tv_func, func); /* borrowed, no refcount */
if (DUK_HOBJECT_HAS_STRICT(func)) {
act->flags |= DUK_ACT_FLAG_STRICT;
}
@@ -62682,8 +67835,9 @@ DUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr,
*out_nregs = ((duk_hcompfunc *) func)->nregs;
DUK_ASSERT(*out_nregs >= 0);
DUK_ASSERT(*out_nregs >= *out_nargs);
- *out_vs_min_bytes = entry_valstack_bottom_byteoff +
- sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);
+ *out_vs_min_bytes =
+ entry_valstack_bottom_byteoff +
+ sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);
} else {
/* True because of call target lookup checks. */
DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(func));
@@ -62691,13 +67845,16 @@ DUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr,
*out_nargs = ((duk_hnatfunc *) func)->nargs;
*out_nregs = *out_nargs;
if (*out_nargs >= 0) {
- *out_vs_min_bytes = entry_valstack_bottom_byteoff +
- sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs + DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
+ *out_vs_min_bytes =
+ entry_valstack_bottom_byteoff +
+ sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs +
+ DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
} else {
/* Vararg function. */
- duk_size_t valstack_top_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));
- *out_vs_min_bytes = valstack_top_byteoff +
- sizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
+ duk_size_t valstack_top_byteoff =
+ (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));
+ *out_vs_min_bytes = valstack_top_byteoff + sizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM +
+ DUK_VALSTACK_INTERNAL_EXTRA);
}
}
} else {
@@ -62708,18 +67865,20 @@ DUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr,
tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func));
- DUK_TVAL_SET_TVAL(&act->tv_func, tv_func); /* borrowed, no refcount */
+ DUK_TVAL_SET_TVAL(&act->tv_func, tv_func); /* borrowed, no refcount */
lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_func);
*out_nargs = DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
if (*out_nargs != DUK_LFUNC_NARGS_VARARGS) {
*out_vs_min_bytes = entry_valstack_bottom_byteoff +
- sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nargs + DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
+ sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nargs +
+ DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
} else {
- duk_size_t valstack_top_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));
+ duk_size_t valstack_top_byteoff =
+ (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));
*out_vs_min_bytes = valstack_top_byteoff +
- sizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
- *out_nargs = -1; /* vararg */
+ sizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
+ *out_nargs = -1; /* vararg */
}
*out_nregs = *out_nargs;
}
@@ -62741,13 +67900,13 @@ DUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr,
* even in error unwind because reserve_byteoff is only used when
* returning to -this- activation.
*/
- act->reserve_byteoff = 0; /* filled in by caller */
+ act->reserve_byteoff = 0; /* filled in by caller */
/* XXX: Is this INCREF necessary? 'func' is always a borrowed
* reference reachable through the value stack? If changed, stack
* unwind code also needs to be fixed to match.
*/
- DUK_HOBJECT_INCREF_ALLOWNULL(thr, func); /* act->func */
+ DUK_HOBJECT_INCREF_ALLOWNULL(thr, func); /* act->func */
#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
if (func) {
@@ -62763,10 +67922,11 @@ DUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr,
DUK_LOCAL void duk__call_env_setup(duk_hthread *thr, duk_hobject *func, duk_activation *act, duk_idx_t idx_args) {
duk_hobject *env;
- DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func)); /* bound function has already been resolved */
+ DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func)); /* bound function has already been resolved */
if (DUK_LIKELY(func != NULL)) {
if (DUK_LIKELY(DUK_HOBJECT_HAS_NEWENV(func))) {
+ DUK_STATS_INC(thr->heap, stats_envrec_newenv);
if (DUK_LIKELY(!DUK_HOBJECT_HAS_CREATEARGS(func))) {
/* Use a new environment but there's no 'arguments' object;
* delayed environment initialization. This is the most
@@ -62793,7 +67953,7 @@ DUK_LOCAL void duk__call_env_setup(duk_hthread *thr, duk_hobject *func, duk_acti
act->lex_env = env;
act->var_env = env;
DUK_HOBJECT_INCREF(thr, env);
- DUK_HOBJECT_INCREF(thr, env); /* XXX: incref by count (2) directly */
+ DUK_HOBJECT_INCREF(thr, env); /* XXX: incref by count (2) directly */
duk_pop(thr);
}
} else {
@@ -62803,6 +67963,7 @@ DUK_LOCAL void duk__call_env_setup(duk_hthread *thr, duk_hobject *func, duk_acti
DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
+ DUK_STATS_INC(thr->heap, stats_envrec_oldenv);
duk__handle_oldenv_for_call(thr, func, act);
DUK_ASSERT(act->lex_env != NULL);
@@ -62812,6 +67973,7 @@ DUK_LOCAL void duk__call_env_setup(duk_hthread *thr, duk_hobject *func, duk_acti
/* Lightfuncs are always native functions and have "newenv". */
DUK_ASSERT(act->lex_env == NULL);
DUK_ASSERT(act->var_env == NULL);
+ DUK_STATS_INC(thr->heap, stats_envrec_newenv);
}
}
@@ -62829,8 +67991,7 @@ DUK_LOCAL void duk__call_thread_state_update(duk_hthread *thr) {
goto thread_state_error;
}
} else {
- DUK_ASSERT(thr->heap->curr_thread == NULL ||
- thr->heap->curr_thread->state == DUK_HTHREAD_STATE_RUNNING);
+ DUK_ASSERT(thr->heap->curr_thread == NULL || thr->heap->curr_thread->state == DUK_HTHREAD_STATE_RUNNING);
if (DUK_UNLIKELY(thr->state != DUK_HTHREAD_STATE_INACTIVE)) {
goto thread_state_error;
}
@@ -62845,18 +68006,18 @@ DUK_LOCAL void duk__call_thread_state_update(duk_hthread *thr) {
DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
return;
- thread_state_error:
+thread_state_error:
DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "invalid thread state (%ld)", (long) thr->state);
- DUK_UNREACHABLE();
+ DUK_WO_NORETURN(return;);
}
/*
* Main unprotected call handler, handles:
*
- * - All combinations of native/Ecmascript caller and native/Ecmascript
+ * - All combinations of native/ECMAScript caller and native/ECMAScript
* target.
*
- * - Optimized Ecmascript-to-Ecmascript call where call handling only
+ * - Optimized ECMAScript-to-ECMAScript call where call handling only
* sets up a new duk_activation but reuses an existing bytecode executor
* (the caller) without native recursion.
*
@@ -62871,9 +68032,7 @@ DUK_LOCAL void duk__call_thread_state_update(duk_hthread *thr) {
* place; the only guarantee is that the state is consistent for unwinding.
*/
-DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
- duk_idx_t idx_func,
- duk_small_uint_t call_flags) {
+DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr, duk_idx_t idx_func, duk_small_uint_t call_flags) {
#if defined(DUK_USE_ASSERTIONS)
duk_activation *entry_act;
duk_size_t entry_callstack_top;
@@ -62885,10 +68044,10 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
duk_uint_fast8_t entry_thread_state;
duk_instr_t **entry_ptr_curr_pc;
duk_idx_t idx_args;
- duk_idx_t nargs; /* # argument registers target function wants (< 0 => "as is") */
- duk_idx_t nregs; /* # total registers target function wants on entry (< 0 => "as is") */
- duk_size_t vs_min_bytes; /* minimum value stack size (bytes) for handling call */
- duk_hobject *func; /* 'func' on stack (borrowed reference) */
+ duk_idx_t nargs; /* # argument registers target function wants (< 0 => "as is") */
+ duk_idx_t nregs; /* # total registers target function wants on entry (< 0 => "as is") */
+ duk_size_t vs_min_bytes; /* minimum value stack size (bytes) for handling call */
+ duk_hobject *func; /* 'func' on stack (borrowed reference) */
duk_activation *act;
duk_ret_t rc;
duk_small_uint_t use_tailcall;
@@ -62898,14 +68057,14 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
/* Asserts for heap->curr_thread omitted: it may be NULL, 'thr', or
* any other thread (e.g. when heap thread is used to run finalizers).
*/
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
DUK_ASSERT(duk_is_valid_index(thr, idx_func));
DUK_ASSERT(idx_func >= 0);
DUK_STATS_INC(thr->heap, stats_call_all);
/* If a tail call:
- * - an Ecmascript activation must be on top of the callstack
+ * - an ECMAScript activation must be on top of the callstack
* - there cannot be any catch stack entries that would catch
* a return
*/
@@ -62929,7 +68088,7 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
DUK_ASSERT(DUK_CAT_GET_TYPE(tmp_cat) == DUK_CAT_TYPE_LABEL); /* a non-catching entry */
}
}
-#endif /* DUK_USE_ASSERTIONS */
+#endif /* DUK_USE_ASSERTIONS */
/*
* Store entry state.
@@ -62942,9 +68101,9 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
entry_valstack_bottom_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
entry_valstack_end_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
entry_call_recursion_depth = thr->heap->call_recursion_depth;
- entry_curr_thread = thr->heap->curr_thread; /* may be NULL if first call */
+ entry_curr_thread = thr->heap->curr_thread; /* may be NULL if first call */
entry_thread_state = thr->state;
- entry_ptr_curr_pc = thr->ptr_curr_pc; /* may be NULL */
+ entry_ptr_curr_pc = thr->ptr_curr_pc; /* may be NULL */
/* If thr->ptr_curr_pc is set, sync curr_pc to act->pc. Then NULL
* thr->ptr_curr_pc so that it's not accidentally used with an incorrect
@@ -62981,6 +68140,26 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
duk__call_thread_state_update(thr);
/*
+ * Increase call recursion depth as early as possible so that if we
+ * enter a recursive call for any reason there's a backstop to native
+ * recursion. This can happen e.g. for almost any property read
+ * because it may cause a getter call or a Proxy trap (GC and finalizers
+ * are not an issue because they are not recursive). If we end up
+ * doing an Ecma-to-Ecma call, revert the increase. (See GH-2032.)
+ *
+ * For similar reasons, ensure there is a known value stack spare
+ * even before we actually prepare the value stack for the target
+ * function. If this isn't done, early recursion may consume the
+ * value stack space.
+ *
+ * XXX: Should bump yield preventcount early, for the same reason.
+ */
+
+ duk__call_c_recursion_limit_check(thr);
+ thr->heap->call_recursion_depth++;
+ duk_require_stack(thr, DUK__CALL_HANDLING_REQUIRE_STACK);
+
+ /*
* Resolve final target function; handle bound functions and special
* functions like .call() and .apply(). Also figure out the effective
* 'this' binding, which replaces the current value at idx_func + 1.
@@ -62992,11 +68171,10 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
DUK_DDD(DUK_DDDPRINT("slow path target resolve"));
func = duk__resolve_target_func_and_this_binding(thr, idx_func, &call_flags);
}
- DUK_ASSERT(duk_get_top(thr) - idx_func >= 2); /* at least func and this present */
+ DUK_ASSERT(duk_get_top(thr) - idx_func >= 2); /* at least func and this present */
DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
- DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) ||
- DUK_HOBJECT_IS_NATFUNC(func)));
+ DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) || DUK_HOBJECT_IS_NATFUNC(func)));
/* [ ... func this arg1 ... argN ] */
@@ -63010,6 +68188,12 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
* Because 'act' is not zeroed, all fields must be filled in.
*/
+ /* Should not be necessary, but initialize to silence warnings. */
+ act = NULL;
+ nargs = 0;
+ nregs = 0;
+ vs_min_bytes = 0;
+
#if defined(DUK_USE_TAILCALL)
use_tailcall = (call_flags & DUK_CALL_FLAG_TAILCALL);
if (use_tailcall) {
@@ -63025,7 +68209,7 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
&act);
}
#else
- DUK_ASSERT((call_flags & DUK_CALL_FLAG_TAILCALL) == 0); /* compiler ensures this */
+ DUK_ASSERT((call_flags & DUK_CALL_FLAG_TAILCALL) == 0); /* compiler ensures this */
use_tailcall = 0;
#endif
@@ -63052,12 +68236,21 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
/* [ ... func this arg1 ... argN ] */
/*
+ * Grow value stack to required size before env setup. This
+ * must happen before env setup to handle some corner cases
+ * correctly, e.g. test-bug-scope-segv-gh2448.js.
+ */
+
+ duk_valstack_grow_check_throw(thr, vs_min_bytes);
+ act->reserve_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
+
+ /*
* Environment record creation and 'arguments' object creation.
* Named function expression name binding is handled by the
* compiler; the compiled function's parent env will contain
* the (immutable) binding already.
*
- * This handling is now identical for C and Ecmascript functions.
+ * This handling is now identical for C and ECMAScript functions.
* C functions always have the 'NEWENV' flag set, so their
* environment record initialization is delayed (which is good).
*
@@ -63072,13 +68265,8 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
* Setup value stack: clamp to 'nargs', fill up to 'nregs',
* ensure value stack size matches target requirements, and
* switch value stack bottom. Valstack top is kept.
- *
- * Value stack can only grow here.
*/
- duk_valstack_grow_check_throw(thr, vs_min_bytes);
- act->reserve_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
-
if (use_tailcall) {
DUK_ASSERT(nregs >= 0);
DUK_ASSERT(nregs >= nargs);
@@ -63104,7 +68292,7 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
if (func != NULL && DUK_HOBJECT_IS_COMPFUNC(func)) {
/*
- * Ecmascript call.
+ * ECMAScript call.
*/
DUK_ASSERT(func != NULL);
@@ -63117,7 +68305,8 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
DUK_REFZERO_CHECK_FAST(thr);
DUK_ASSERT(thr->ptr_curr_pc == NULL);
- return 1; /* 1=reuse executor */
+ thr->heap->call_recursion_depth--; /* No recursion increase for this case. */
+ return 1; /* 1=reuse executor */
}
DUK_ASSERT(use_tailcall == 0);
@@ -63126,12 +68315,6 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;
thr->callstack_preventcount++;
- /* XXX: we could just do this on entry regardless of reuse, as long
- * as recursion depth is decreased for e2e case.
- */
- duk__call_c_recursion_limit_check(thr);
- thr->heap->call_recursion_depth++;
-
/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
/*
@@ -63166,12 +68349,6 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;
thr->callstack_preventcount++;
- /* XXX: we could just do this on entry regardless of reuse, as long
- * as recursion depth is decreased for e2e case.
- */
- duk__call_c_recursion_limit_check(thr);
- thr->heap->call_recursion_depth++;
-
/* For native calls must be NULL so we don't sync back */
DUK_ASSERT(thr->ptr_curr_pc == NULL);
@@ -63198,9 +68375,10 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
;
} else if (rc < 0) {
duk_error_throw_from_negative_rc(thr, rc);
- DUK_UNREACHABLE();
+ DUK_WO_NORETURN(return 0;);
} else {
DUK_ERROR_TYPE(thr, DUK_STR_INVALID_CFUNC_RC);
+ DUK_WO_NORETURN(return 0;);
}
}
DUK_ASSERT(thr->ptr_curr_pc == NULL);
@@ -63252,7 +68430,7 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
/* Explicit check for fastint downgrade. */
DUK_TVAL_CHKFAST_INPLACE_FAST(tv_funret);
#endif
- DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret); /* side effects */
+ DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret); /* side effects */
}
duk_set_top_unsafe(thr, idx_func + 1);
@@ -63271,7 +68449,7 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
/* Restore entry thread executor curr_pc stack frame pointer. */
thr->ptr_curr_pc = entry_ptr_curr_pc;
- DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread); /* may be NULL */
+ DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread); /* may be NULL */
thr->state = (duk_uint8_t) entry_thread_state;
/* Disabled assert: triggered with some torture tests. */
@@ -63288,7 +68466,7 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
* calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see
* GH-303. Only needed for success path, error path always causes a
* breakpoint recheck in the executor. It would be enough to set this
- * only when returning to an Ecmascript activation, but setting the flag
+ * only when returning to an ECMAScript activation, but setting the flag
* on every return should have no ill effect.
*/
#if defined(DUK_USE_DEBUGGER_SUPPORT)
@@ -63312,12 +68490,10 @@ DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
DUK_REFZERO_CHECK_FAST(thr);
- return 0; /* 0=call handled inline */
+ return 0; /* 0=call handled inline */
}
-DUK_INTERNAL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr,
- duk_idx_t nargs,
- duk_small_uint_t call_flags) {
+DUK_INTERNAL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags) {
duk_idx_t idx_func;
DUK_ASSERT(duk_get_top(thr) >= nargs + 2);
idx_func = duk_get_top(thr) - (nargs + 2);
@@ -63325,9 +68501,7 @@ DUK_INTERNAL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr,
return duk_handle_call_unprotected(thr, idx_func, call_flags);
}
-DUK_INTERNAL duk_int_t duk_handle_call_unprotected(duk_hthread *thr,
- duk_idx_t idx_func,
- duk_small_uint_t call_flags) {
+DUK_INTERNAL duk_int_t duk_handle_call_unprotected(duk_hthread *thr, duk_idx_t idx_func, duk_small_uint_t call_flags) {
DUK_ASSERT(duk_is_valid_index(thr, idx_func));
DUK_ASSERT(idx_func >= 0);
return duk__handle_call_raw(thr, idx_func, call_flags);
@@ -63364,7 +68538,7 @@ DUK_LOCAL void duk__handle_safe_call_inner(duk_hthread *thr,
duk_ret_t rc;
DUK_ASSERT(thr != NULL);
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
/*
* Thread state check and book-keeping.
@@ -63394,18 +68568,20 @@ DUK_LOCAL void duk__handle_safe_call_inner(duk_hthread *thr,
/* we're running inside the caller's activation, so no change in call/catch stack or valstack bottom */
DUK_ASSERT(thr->callstack_top == entry_callstack_top);
DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
- DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) == entry_valstack_bottom_byteoff);
+ DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) ==
+ entry_valstack_bottom_byteoff);
DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
if (DUK_UNLIKELY(rc < 0)) {
duk_error_throw_from_negative_rc(thr, rc);
+ DUK_WO_NORETURN(return;);
}
DUK_ASSERT(rc >= 0);
- duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, rc); /* throws for insane rc */
+ duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, rc); /* throws for insane rc */
- DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread); /* may be NULL */
+ DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread); /* may be NULL */
thr->state = (duk_uint8_t) entry_thread_state;
}
@@ -63421,7 +68597,7 @@ DUK_LOCAL void duk__handle_safe_call_error(duk_hthread *thr,
duk_size_t entry_valstack_bottom_byteoff,
duk_jmpbuf *old_jmpbuf_ptr) {
DUK_ASSERT(thr != NULL);
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
/*
* Error during call. The error value is at heap->lj.value1.
@@ -63458,7 +68634,7 @@ DUK_LOCAL void duk__handle_safe_call_error(duk_hthread *thr,
/* Switch active thread before any side effects to avoid a
* dangling curr_thread pointer.
*/
- DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread); /* may be NULL */
+ DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread); /* may be NULL */
thr->state = (duk_uint8_t) entry_thread_state;
DUK_ASSERT(thr->heap->curr_thread == entry_curr_thread);
@@ -63474,9 +68650,9 @@ DUK_LOCAL void duk__handle_safe_call_error(duk_hthread *thr,
/* [ ... | (crud) errobj ] */
- DUK_ASSERT(duk_get_top(thr) >= 1); /* at least errobj must be on stack */
+ DUK_ASSERT(duk_get_top(thr) >= 1); /* at least errobj must be on stack */
- duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, 1); /* 1 = num actual 'return values' */
+ duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, 1); /* 1 = num actual 'return values' */
/* [ ... | ] or [ ... | errobj (M * undefined)] where M = num_stack_rets - 1 */
@@ -63513,7 +68689,7 @@ DUK_LOCAL void duk__handle_safe_call_shared_unwind(duk_hthread *thr,
duk_hthread *entry_curr_thread,
duk_instr_t **entry_ptr_curr_pc) {
DUK_ASSERT(thr != NULL);
- DUK_ASSERT_CTX_VALID(thr);
+ DUK_CTX_ASSERT_VALID(thr);
DUK_UNREF(idx_retbase);
DUK_UNREF(num_stack_rets);
DUK_UNREF(entry_curr_thread);
@@ -63562,7 +68738,7 @@ DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
duk_int_t retval;
DUK_ASSERT(thr != NULL);
- DUK_ASSERT(duk_get_top(thr) >= num_stack_args); /* Caller ensures. */
+ DUK_ASSERT(duk_get_top(thr) >= num_stack_args); /* Caller ensures. */
DUK_STATS_INC(thr->heap, stats_safecall_all);
@@ -63581,14 +68757,14 @@ DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
entry_callstack_preventcount = thr->callstack_preventcount;
#endif
entry_call_recursion_depth = thr->heap->call_recursion_depth;
- entry_curr_thread = thr->heap->curr_thread; /* may be NULL if first call */
+ entry_curr_thread = thr->heap->curr_thread; /* may be NULL if first call */
entry_thread_state = thr->state;
- entry_ptr_curr_pc = thr->ptr_curr_pc; /* may be NULL */
- idx_retbase = duk_get_top(thr) - num_stack_args; /* not a valid stack index if num_stack_args == 0 */
+ entry_ptr_curr_pc = thr->ptr_curr_pc; /* may be NULL */
+ idx_retbase = duk_get_top(thr) - num_stack_args; /* not a valid stack index if num_stack_args == 0 */
DUK_ASSERT(idx_retbase >= 0);
- DUK_ASSERT((duk_idx_t) (thr->valstack_top - thr->valstack_bottom) >= num_stack_args); /* Caller ensures. */
- DUK_ASSERT((duk_idx_t) (thr->valstack_end - (thr->valstack_bottom + idx_retbase)) >= num_stack_rets); /* Caller ensures. */
+ DUK_ASSERT((duk_idx_t) (thr->valstack_top - thr->valstack_bottom) >= num_stack_args); /* Caller ensures. */
+ DUK_ASSERT((duk_idx_t) (thr->valstack_end - (thr->valstack_bottom + idx_retbase)) >= num_stack_rets); /* Caller ensures. */
/* Cannot portably debug print a function pointer, hence 'func' not printed! */
DUK_DD(DUK_DDPRINT("duk_handle_safe_call: thr=%p, num_stack_args=%ld, num_stack_rets=%ld, "
@@ -63648,7 +68824,8 @@ DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
* whatever calls are made. Reserve cannot decrease.
*/
DUK_ASSERT(thr->callstack_curr == entry_act);
- DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
+ DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >=
+ entry_valstack_end_byteoff);
retval = DUK_EXEC_SUCCESS;
#if defined(DUK_USE_CPP_EXCEPTIONS)
@@ -63658,7 +68835,8 @@ DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
} else {
/* Error path. */
#endif
- DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
+ DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >=
+ entry_valstack_end_byteoff);
DUK_STATS_INC(thr->heap, stats_safecall_throw);
@@ -63677,16 +68855,25 @@ DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
retval = DUK_EXEC_ERROR;
}
#if defined(DUK_USE_CPP_EXCEPTIONS)
- catch (std::exception &exc) {
+ catch (duk_fatal_exception &exc) {
+ DUK_D(DUK_DPRINT("rethrow duk_fatal_exception"));
+ DUK_UNREF(exc);
+ throw;
+ } catch (std::exception &exc) {
const char *what = exc.what();
- DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
+ DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >=
+ entry_valstack_end_byteoff);
DUK_STATS_INC(thr->heap, stats_safecall_throw);
if (!what) {
what = "unknown";
}
DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
try {
- DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
+ DUK_ERROR_FMT1(thr,
+ DUK_ERR_TYPE_ERROR,
+ "caught invalid c++ std::exception '%s' (perhaps thrown by user code)",
+ what);
+ DUK_WO_NORETURN(return 0;);
} catch (duk_internal_exception exc) {
DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
DUK_UNREF(exc);
@@ -63705,10 +68892,12 @@ DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
}
} catch (...) {
DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
- DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
+ DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >=
+ entry_valstack_end_byteoff);
DUK_STATS_INC(thr->heap, stats_safecall_throw);
try {
DUK_ERROR_TYPE(thr, "caught invalid c++ exception (perhaps thrown by user code)");
+ DUK_WO_NORETURN(return 0;);
} catch (duk_internal_exception exc) {
DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
DUK_UNREF(exc);
@@ -63728,7 +68917,7 @@ DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
}
#endif
- DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == old_jmpbuf_ptr); /* success/error path both do this */
+ DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == old_jmpbuf_ptr); /* success/error path both do this */
DUK_ASSERT_LJSTATE_UNSET(thr->heap);
@@ -63749,7 +68938,8 @@ DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
/* Final asserts. */
DUK_ASSERT(thr->callstack_curr == entry_act);
- DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) == entry_valstack_bottom_byteoff);
+ DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) ==
+ entry_valstack_bottom_byteoff);
DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
DUK_ASSERT(thr->callstack_top == entry_callstack_top);
DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
@@ -63767,66 +68957,86 @@ DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
/*
* Property-based call (foo.noSuch()) error setup: replace target function
- * on stack top with a specially tagged (hidden Symbol) error which gets
- * thrown in call handling at the proper spot to follow Ecmascript semantics.
+ * on stack top with a hidden Symbol tagged non-callable wrapper object
+ * holding the error. The error gets thrown in call handling at the
+ * proper spot to follow ECMAScript semantics.
*/
#if defined(DUK_USE_VERBOSE_ERRORS)
-DUK_INTERNAL DUK_NOINLINE DUK_COLD void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_targ, duk_tval *tv_base, duk_tval *tv_key) {
- const char *str1, *str2, *str3;
+DUK_INTERNAL DUK_NOINLINE DUK_COLD void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_base, duk_tval *tv_key) {
+ const char *str_targ, *str_key, *str_base;
duk_idx_t entry_top;
entry_top = duk_get_top(thr);
- /* Must stabilize pointers first. Argument convention is a bit awkward,
- * it comes from the executor call site where some arguments may not be
- * on the value stack (consts).
- */
+ /* [ <nargs> target ] */
+
+ /* Must stabilize pointers first. tv_targ is already on stack top. */
duk_push_tval(thr, tv_base);
duk_push_tval(thr, tv_key);
- duk_push_tval(thr, tv_targ);
DUK_GC_TORTURE(thr->heap);
- /* We only push an error, replacing the call target (at idx_func)
- * with the error to ensure side effects come out correctly:
+ duk_push_bare_object(thr);
+
+ /* [ <nargs> target base key {} ] */
+
+ /* We only push a wrapped error, replacing the call target (at
+ * idx_func) with the error to ensure side effects come out
+ * correctly:
* - Property read
* - Call argument evaluation
- * - Callability check and error thrown.
+ * - Callability check and error thrown
*
- * A hidden Symbol on the error object pushed here is used by
+ * A hidden Symbol on the wrapper object pushed above is used by
* call handling to figure out the error is to be thrown as is.
* It is CRITICAL that the hidden Symbol can never occur on a
* user visible object that may get thrown.
*/
#if defined(DUK_USE_PARANOID_ERRORS)
- str1 = duk_get_type_name(thr, -1);
- str2 = duk_get_type_name(thr, -2);
- str3 = duk_get_type_name(thr, -3);
- duk_push_error_object(thr, DUK_ERR_TYPE_ERROR | DUK_ERRCODE_FLAG_NOBLAME_FILELINE, "%s not callable (property %s of %s)", str1, str2, str3);
-#else
- str1 = duk_push_string_readable(thr, -1);
- str2 = duk_push_string_readable(thr, -3);
- str3 = duk_push_string_readable(thr, -5);
- duk_push_error_object(thr, DUK_ERR_TYPE_ERROR | DUK_ERRCODE_FLAG_NOBLAME_FILELINE, "%s not callable (property %s of %s)", str1, str2, str3);
-#endif
-
- duk_push_true(thr);
- duk_put_prop_stridx(thr, -2, DUK_STRIDX_INT_TARGET); /* Marker property, reuse _Target. */
-
- /* [ <nregs> propValue <variable> error ] */
+ str_targ = duk_get_type_name(thr, -4);
+ str_key = duk_get_type_name(thr, -2);
+ str_base = duk_get_type_name(thr, -3);
+ duk_push_error_object(thr,
+ DUK_ERR_TYPE_ERROR | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
+ "%s not callable (property %s of %s)",
+ str_targ,
+ str_key,
+ str_base);
+ duk_xdef_prop_stridx(thr, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE); /* Marker property, reuse _Target. */
+ /* [ <nargs> target base key { _Target: error } ] */
duk_replace(thr, entry_top - 1);
+#else
+ str_targ = duk_push_string_readable(thr, -4);
+ str_key = duk_push_string_readable(thr, -3);
+ str_base = duk_push_string_readable(thr, -5);
+ duk_push_error_object(thr,
+ DUK_ERR_TYPE_ERROR | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
+ "%s not callable (property %s of %s)",
+ str_targ,
+ str_key,
+ str_base);
+ /* [ <nargs> target base key {} str_targ str_key str_base error ] */
+ duk_xdef_prop_stridx(thr, -5, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE); /* Marker property, reuse _Target. */
+ /* [ <nargs> target base key { _Target: error } str_targ str_key str_base ] */
+ duk_swap(thr, -4, entry_top - 1);
+ /* [ <nargs> { _Target: error } base key target str_targ str_key str_base ] */
+#endif
+
+ /* [ <nregs> { _Target: error } <variable> */
duk_set_top(thr, entry_top);
- DUK_ASSERT(!duk_is_callable(thr, -1)); /* Critical so that call handling will throw the error. */
+ /* [ <nregs> { _Target: error } */
+ DUK_ASSERT(!duk_is_callable(thr, -1)); /* Critical so that call handling will throw the error. */
}
-#endif /* DUK_USE_VERBOSE_ERRORS */
+#endif /* DUK_USE_VERBOSE_ERRORS */
/* automatic undefs */
#undef DUK__AUGMENT_CALL_RELAX_COUNT
+#undef DUK__CALL_HANDLING_REQUIRE_STACK
/*
- * Ecmascript compiler.
+ * ECMAScript compiler.
*
* Parses an input string and generates a function template result.
* Compilation may happen in multiple contexts (global code, eval
@@ -63861,45 +69071,51 @@ DUK_INTERNAL DUK_NOINLINE DUK_COLD void duk_call_setup_propcall_error(duk_hthrea
* uses this approach to avoid an explicit DUK__ISREG() check (the condition is
* logically "'x' is a register AND 'x' >= temp_first").
*/
-#define DUK__CONST_MARKER DUK_REGCONST_CONST_MARKER
-#define DUK__REMOVECONST(x) ((x) & ~DUK__CONST_MARKER)
-#define DUK__ISREG(x) ((x) >= 0)
-#define DUK__ISCONST(x) ((x) < 0)
-#define DUK__ISREG_TEMP(comp_ctx,x) ((duk_int32_t) (x) >= (duk_int32_t) ((comp_ctx)->curr_func.temp_first)) /* Check for x >= temp_first && x >= 0 by comparing as signed. */
-#define DUK__ISREG_NOTTEMP(comp_ctx,x) ((duk_uint32_t) (x) < (duk_uint32_t) ((comp_ctx)->curr_func.temp_first)) /* Check for x >= 0 && x < temp_first by interpreting as unsigned. */
-#define DUK__GETTEMP(comp_ctx) ((comp_ctx)->curr_func.temp_next)
-#define DUK__SETTEMP(comp_ctx,x) ((comp_ctx)->curr_func.temp_next = (x)) /* dangerous: must only lower (temp_max not updated) */
-#define DUK__SETTEMP_CHECKMAX(comp_ctx,x) duk__settemp_checkmax((comp_ctx),(x))
-#define DUK__ALLOCTEMP(comp_ctx) duk__alloctemp((comp_ctx))
-#define DUK__ALLOCTEMPS(comp_ctx,count) duk__alloctemps((comp_ctx),(count))
+#define DUK__CONST_MARKER DUK_REGCONST_CONST_MARKER
+#define DUK__REMOVECONST(x) ((x) & ~DUK__CONST_MARKER)
+#define DUK__ISREG(x) ((x) >= 0)
+#define DUK__ISCONST(x) ((x) < 0)
+#define DUK__ISREG_TEMP(comp_ctx, x) \
+ ((duk_int32_t) (x) >= \
+ (duk_int32_t) ((comp_ctx)->curr_func.temp_first)) /* Check for x >= temp_first && x >= 0 by comparing as signed. */
+#define DUK__ISREG_NOTTEMP(comp_ctx, x) \
+ ((duk_uint32_t) (x) < \
+ (duk_uint32_t) ((comp_ctx)->curr_func.temp_first)) /* Check for x >= 0 && x < temp_first by interpreting as unsigned. */
+#define DUK__GETTEMP(comp_ctx) ((comp_ctx)->curr_func.temp_next)
+#define DUK__SETTEMP(comp_ctx, x) ((comp_ctx)->curr_func.temp_next = (x)) /* dangerous: must only lower (temp_max not updated) */
+#define DUK__SETTEMP_CHECKMAX(comp_ctx, x) duk__settemp_checkmax((comp_ctx), (x))
+#define DUK__ALLOCTEMP(comp_ctx) duk__alloctemp((comp_ctx))
+#define DUK__ALLOCTEMPS(comp_ctx, count) duk__alloctemps((comp_ctx), (count))
/* Init value set size for array and object literals. */
-#define DUK__MAX_ARRAY_INIT_VALUES 20
-#define DUK__MAX_OBJECT_INIT_PAIRS 10
+#define DUK__MAX_ARRAY_INIT_VALUES 20
+#define DUK__MAX_OBJECT_INIT_PAIRS 10
/* XXX: hack, remove when const lookup is not O(n) */
-#define DUK__GETCONST_MAX_CONSTS_CHECK 256
+#define DUK__GETCONST_MAX_CONSTS_CHECK 256
/* These limits are based on bytecode limits. Max temps is limited
* by duk_hcompfunc nargs/nregs fields being 16 bits.
*/
-#define DUK__MAX_CONSTS DUK_BC_BC_MAX
-#define DUK__MAX_FUNCS DUK_BC_BC_MAX
-#define DUK__MAX_TEMPS 0xffffL
+#define DUK__MAX_CONSTS DUK_BC_BC_MAX
+#define DUK__MAX_FUNCS DUK_BC_BC_MAX
+#define DUK__MAX_TEMPS 0xffffL
/* Initial bytecode size allocation. */
#if defined(DUK_USE_PREFER_SIZE)
-#define DUK__BC_INITIAL_INSTS 16
+#define DUK__BC_INITIAL_INSTS 16
#else
-#define DUK__BC_INITIAL_INSTS 256
+#define DUK__BC_INITIAL_INSTS 256
#endif
-#define DUK__RECURSION_INCREASE(comp_ctx,thr) do { \
+#define DUK__RECURSION_INCREASE(comp_ctx, thr) \
+ do { \
DUK_DDD(DUK_DDDPRINT("RECURSION INCREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
duk__comp_recursion_increase((comp_ctx)); \
} while (0)
-#define DUK__RECURSION_DECREASE(comp_ctx,thr) do { \
+#define DUK__RECURSION_DECREASE(comp_ctx, thr) \
+ do { \
DUK_DDD(DUK_DDDPRINT("RECURSION DECREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
duk__comp_recursion_decrease((comp_ctx)); \
} while (0)
@@ -63907,11 +69123,11 @@ DUK_INTERNAL DUK_NOINLINE DUK_COLD void duk_call_setup_propcall_error(duk_hthrea
/* Value stack slot limits: these are quite approximate right now, and
* because they overlap in control flow, some could be eliminated.
*/
-#define DUK__COMPILE_ENTRY_SLOTS 8
-#define DUK__FUNCTION_INIT_REQUIRE_SLOTS 16
-#define DUK__FUNCTION_BODY_REQUIRE_SLOTS 16
-#define DUK__PARSE_STATEMENTS_SLOTS 16
-#define DUK__PARSE_EXPR_SLOTS 16
+#define DUK__COMPILE_ENTRY_SLOTS 8
+#define DUK__FUNCTION_INIT_REQUIRE_SLOTS 16
+#define DUK__FUNCTION_BODY_REQUIRE_SLOTS 16
+#define DUK__PARSE_STATEMENTS_SLOTS 16
+#define DUK__PARSE_EXPR_SLOTS 16
/* Temporary structure used to pass a stack allocated region through
* duk_safe_call().
@@ -63943,10 +69159,14 @@ DUK_LOCAL_DECL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx);
DUK_LOCAL_DECL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc);
DUK_LOCAL_DECL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins);
DUK_LOCAL_DECL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op);
-DUK_LOCAL_DECL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b, duk_regconst_t c);
+DUK_LOCAL_DECL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx,
+ duk_small_uint_t op_flags,
+ duk_regconst_t a,
+ duk_regconst_t b,
+ duk_regconst_t c);
DUK_LOCAL_DECL void duk__emit_a_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b);
DUK_LOCAL_DECL void duk__emit_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b, duk_regconst_t c);
-#if 0 /* unused */
+#if 0 /* unused */
DUK_LOCAL_DECL void duk__emit_a(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a);
DUK_LOCAL_DECL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b);
#endif
@@ -63960,7 +69180,12 @@ DUK_LOCAL_DECL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx);
DUK_LOCAL_DECL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
DUK_LOCAL_DECL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc);
DUK_LOCAL_DECL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
-DUK_LOCAL_DECL void duk__patch_trycatch(duk_compiler_ctx *comp_ctx, duk_int_t ldconst_pc, duk_int_t trycatch_pc, duk_regconst_t reg_catch, duk_regconst_t const_varname, duk_small_uint_t flags);
+DUK_LOCAL_DECL void duk__patch_trycatch(duk_compiler_ctx *comp_ctx,
+ duk_int_t ldconst_pc,
+ duk_int_t trycatch_pc,
+ duk_regconst_t reg_catch,
+ duk_regconst_t const_varname,
+ duk_small_uint_t flags);
DUK_LOCAL_DECL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
DUK_LOCAL_DECL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
DUK_LOCAL_DECL void duk__emit_invalid(duk_compiler_ctx *comp_ctx);
@@ -63991,7 +69216,7 @@ duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
duk_regconst_t forced_reg,
duk_small_uint_t flags);
DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
-#if 0 /* unused */
+#if 0 /* unused */
DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
#endif
DUK_LOCAL_DECL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg);
@@ -64005,7 +69230,13 @@ DUK_LOCAL_DECL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *ctx, duk_regconst_t
/* label handling */
DUK_LOCAL_DECL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_int_t pc_label, duk_int_t label_id);
DUK_LOCAL_DECL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags);
-DUK_LOCAL_DECL void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_bool_t is_break, duk_int_t *out_label_id, duk_int_t *out_label_catch_depth, duk_int_t *out_label_pc, duk_bool_t *out_is_closest);
+DUK_LOCAL_DECL void duk__lookup_active_label(duk_compiler_ctx *comp_ctx,
+ duk_hstring *h_label,
+ duk_bool_t is_break,
+ duk_int_t *out_label_id,
+ duk_int_t *out_label_catch_depth,
+ duk_int_t *out_label_pc,
+ duk_bool_t *out_is_closest);
DUK_LOCAL_DECL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_size_t len);
/* top-down expression parser */
@@ -64019,26 +69250,32 @@ DUK_LOCAL_DECL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_s
DUK_LOCAL_DECL void duk__exprtop(duk_compiler_ctx *ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
/* convenience helpers */
-#if 0 /* unused */
+#if 0 /* unused */
DUK_LOCAL_DECL duk_regconst_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
#endif
-#if 0 /* unused */
+#if 0 /* unused */
DUK_LOCAL_DECL duk_regconst_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
#endif
-DUK_LOCAL_DECL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_regconst_t forced_reg);
+DUK_LOCAL_DECL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx,
+ duk_ivalue *res,
+ duk_small_uint_t rbp_flags,
+ duk_regconst_t forced_reg);
DUK_LOCAL_DECL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
-#if 0 /* unused */
+#if 0 /* unused */
DUK_LOCAL_DECL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
#endif
DUK_LOCAL_DECL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
DUK_LOCAL_DECL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
-#if 0 /* unused */
+#if 0 /* unused */
DUK_LOCAL_DECL duk_regconst_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
#endif
-DUK_LOCAL_DECL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_regconst_t forced_reg);
+DUK_LOCAL_DECL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx,
+ duk_ivalue *res,
+ duk_small_uint_t rbp_flags,
+ duk_regconst_t forced_reg);
DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
-#if 0 /* unused */
+#if 0 /* unused */
DUK_LOCAL_DECL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
#endif
@@ -64048,7 +69285,11 @@ DUK_LOCAL_DECL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalu
DUK_LOCAL_DECL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
/* statement parsing */
-DUK_LOCAL_DECL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_regconst_t *out_reg_varbind, duk_regconst_t *out_rc_varname);
+DUK_LOCAL_DECL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx,
+ duk_ivalue *res,
+ duk_small_uint_t expr_flags,
+ duk_regconst_t *out_reg_varbind,
+ duk_regconst_t *out_rc_varname);
DUK_LOCAL_DECL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags);
DUK_LOCAL_DECL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
DUK_LOCAL_DECL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
@@ -64062,18 +69303,25 @@ DUK_LOCAL_DECL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *
DUK_LOCAL_DECL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
DUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem);
DUK_LOCAL_DECL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id);
-DUK_LOCAL_DECL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof);
-
-DUK_LOCAL_DECL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_small_int_t expect_token);
+DUK_LOCAL_DECL void duk__parse_stmts(duk_compiler_ctx *comp_ctx,
+ duk_bool_t allow_source_elem,
+ duk_bool_t expect_eof,
+ duk_bool_t regexp_after);
+
+DUK_LOCAL_DECL void duk__parse_func_body(duk_compiler_ctx *comp_ctx,
+ duk_bool_t expect_eof,
+ duk_bool_t implicit_return_value,
+ duk_bool_t regexp_after,
+ duk_small_int_t expect_token);
DUK_LOCAL_DECL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx);
DUK_LOCAL_DECL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);
DUK_LOCAL_DECL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);
-#define DUK__FUNC_FLAG_DECL (1 << 0) /* Parsing a function declaration. */
-#define DUK__FUNC_FLAG_GETSET (1 << 1) /* Parsing an object literal getter/setter. */
-#define DUK__FUNC_FLAG_METDEF (1 << 2) /* Parsing an object literal method definition shorthand. */
-#define DUK__FUNC_FLAG_PUSHNAME_PASS1 (1 << 3) /* Push function name when creating template (first pass only). */
-#define DUK__FUNC_FLAG_USE_PREVTOKEN (1 << 4) /* Use prev_token to start function parsing (workaround for object literal). */
+#define DUK__FUNC_FLAG_DECL (1 << 0) /* Parsing a function declaration. */
+#define DUK__FUNC_FLAG_GETSET (1 << 1) /* Parsing an object literal getter/setter. */
+#define DUK__FUNC_FLAG_METDEF (1 << 2) /* Parsing an object literal method definition shorthand. */
+#define DUK__FUNC_FLAG_PUSHNAME_PASS1 (1 << 3) /* Push function name when creating template (first pass only). */
+#define DUK__FUNC_FLAG_USE_PREVTOKEN (1 << 4) /* Use prev_token to start function parsing (workaround for object literal). */
/*
* Parser control values for tokens. The token table is ordered by the
@@ -64090,141 +69338,141 @@ DUK_LOCAL_DECL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, d
/* XXX: actually single step levels would work just fine, clean up */
/* binding power "levels" (see doc/compiler.rst) */
-#define DUK__BP_INVALID 0 /* always terminates led() */
-#define DUK__BP_EOF 2
-#define DUK__BP_CLOSING 4 /* token closes expression, e.g. ')', ']' */
-#define DUK__BP_FOR_EXPR DUK__BP_CLOSING /* bp to use when parsing a top level Expression */
-#define DUK__BP_COMMA 6
-#define DUK__BP_ASSIGNMENT 8
-#define DUK__BP_CONDITIONAL 10
-#define DUK__BP_LOR 12
-#define DUK__BP_LAND 14
-#define DUK__BP_BOR 16
-#define DUK__BP_BXOR 18
-#define DUK__BP_BAND 20
-#define DUK__BP_EQUALITY 22
-#define DUK__BP_RELATIONAL 24
-#define DUK__BP_SHIFT 26
-#define DUK__BP_ADDITIVE 28
-#define DUK__BP_MULTIPLICATIVE 30
-#define DUK__BP_EXPONENTIATION 32
-#define DUK__BP_POSTFIX 34
-#define DUK__BP_CALL 36
-#define DUK__BP_MEMBER 38
+#define DUK__BP_INVALID 0 /* always terminates led() */
+#define DUK__BP_EOF 2
+#define DUK__BP_CLOSING 4 /* token closes expression, e.g. ')', ']' */
+#define DUK__BP_FOR_EXPR DUK__BP_CLOSING /* bp to use when parsing a top level Expression */
+#define DUK__BP_COMMA 6
+#define DUK__BP_ASSIGNMENT 8
+#define DUK__BP_CONDITIONAL 10
+#define DUK__BP_LOR 12
+#define DUK__BP_LAND 14
+#define DUK__BP_BOR 16
+#define DUK__BP_BXOR 18
+#define DUK__BP_BAND 20
+#define DUK__BP_EQUALITY 22
+#define DUK__BP_RELATIONAL 24
+#define DUK__BP_SHIFT 26
+#define DUK__BP_ADDITIVE 28
+#define DUK__BP_MULTIPLICATIVE 30
+#define DUK__BP_EXPONENTIATION 32
+#define DUK__BP_POSTFIX 34
+#define DUK__BP_CALL 36
+#define DUK__BP_MEMBER 38
#define DUK__TOKEN_LBP_BP_MASK 0x1f
-#define DUK__TOKEN_LBP_FLAG_NO_REGEXP (1 << 5) /* regexp literal must not follow this token */
-#define DUK__TOKEN_LBP_FLAG_TERMINATES (1 << 6) /* terminates expression; e.g. post-increment/-decrement */
-#define DUK__TOKEN_LBP_FLAG_UNUSED (1 << 7) /* unused */
+#define DUK__TOKEN_LBP_FLAG_NO_REGEXP (1 << 5) /* regexp literal must not follow this token */
+#define DUK__TOKEN_LBP_FLAG_TERMINATES (1 << 6) /* terminates expression; e.g. post-increment/-decrement */
+#define DUK__TOKEN_LBP_FLAG_UNUSED (1 << 7) /* unused */
-#define DUK__TOKEN_LBP_GET_BP(x) ((duk_small_uint_t) (((x) & DUK__TOKEN_LBP_BP_MASK) * 2))
+#define DUK__TOKEN_LBP_GET_BP(x) ((duk_small_uint_t) (((x) &DUK__TOKEN_LBP_BP_MASK) * 2))
-#define DUK__MK_LBP(bp) ((bp) >> 1) /* bp is assumed to be even */
-#define DUK__MK_LBP_FLAGS(bp,flags) (((bp) >> 1) | (flags))
+#define DUK__MK_LBP(bp) ((bp) >> 1) /* bp is assumed to be even */
+#define DUK__MK_LBP_FLAGS(bp, flags) (((bp) >> 1) | (flags))
DUK_LOCAL const duk_uint8_t duk__token_lbp[] = {
- DUK__MK_LBP(DUK__BP_EOF), /* DUK_TOK_EOF */
- DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_IDENTIFIER */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_BREAK */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CASE */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CATCH */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CONTINUE */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DEBUGGER */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DEFAULT */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DELETE */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DO */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_ELSE */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_FINALLY */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_FOR */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_FUNCTION */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_IF */
- DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_IN */
- DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_INSTANCEOF */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_NEW */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_RETURN */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SWITCH */
- DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_THIS */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_THROW */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_TRY */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_TYPEOF */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_VAR */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CONST */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_VOID */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_WHILE */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_WITH */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CLASS */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_ENUM */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_EXPORT */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_EXTENDS */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_IMPORT */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SUPER */
- DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_NULL */
- DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_TRUE */
- DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_FALSE */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_GET */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SET */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_IMPLEMENTS */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_INTERFACE */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LET */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PACKAGE */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PRIVATE */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PROTECTED */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PUBLIC */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_STATIC */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_YIELD */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LCURLY */
- DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_RCURLY */
- DUK__MK_LBP(DUK__BP_MEMBER), /* DUK_TOK_LBRACKET */
- DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_RBRACKET */
- DUK__MK_LBP(DUK__BP_CALL), /* DUK_TOK_LPAREN */
- DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_RPAREN */
- DUK__MK_LBP(DUK__BP_MEMBER), /* DUK_TOK_PERIOD */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SEMICOLON */
- DUK__MK_LBP(DUK__BP_COMMA), /* DUK_TOK_COMMA */
- DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_LT */
- DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_GT */
- DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_LE */
- DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_GE */
- DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_EQ */
- DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_NEQ */
- DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_SEQ */
- DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_SNEQ */
- DUK__MK_LBP(DUK__BP_ADDITIVE), /* DUK_TOK_ADD */
- DUK__MK_LBP(DUK__BP_ADDITIVE), /* DUK_TOK_SUB */
- DUK__MK_LBP(DUK__BP_MULTIPLICATIVE), /* DUK_TOK_MUL */
- DUK__MK_LBP(DUK__BP_MULTIPLICATIVE), /* DUK_TOK_DIV */
- DUK__MK_LBP(DUK__BP_MULTIPLICATIVE), /* DUK_TOK_MOD */
- DUK__MK_LBP(DUK__BP_EXPONENTIATION), /* DUK_TOK_EXP */
- DUK__MK_LBP(DUK__BP_POSTFIX), /* DUK_TOK_INCREMENT */
- DUK__MK_LBP(DUK__BP_POSTFIX), /* DUK_TOK_DECREMENT */
- DUK__MK_LBP(DUK__BP_SHIFT), /* DUK_TOK_ALSHIFT */
- DUK__MK_LBP(DUK__BP_SHIFT), /* DUK_TOK_ARSHIFT */
- DUK__MK_LBP(DUK__BP_SHIFT), /* DUK_TOK_RSHIFT */
- DUK__MK_LBP(DUK__BP_BAND), /* DUK_TOK_BAND */
- DUK__MK_LBP(DUK__BP_BOR), /* DUK_TOK_BOR */
- DUK__MK_LBP(DUK__BP_BXOR), /* DUK_TOK_BXOR */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LNOT */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_BNOT */
- DUK__MK_LBP(DUK__BP_LAND), /* DUK_TOK_LAND */
- DUK__MK_LBP(DUK__BP_LOR), /* DUK_TOK_LOR */
- DUK__MK_LBP(DUK__BP_CONDITIONAL), /* DUK_TOK_QUESTION */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_COLON */
- DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_EQUALSIGN */
- DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_ADD_EQ */
- DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_SUB_EQ */
- DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_MUL_EQ */
- DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_DIV_EQ */
- DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_MOD_EQ */
- DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_EXP_EQ */
- DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_ALSHIFT_EQ */
- DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_ARSHIFT_EQ */
- DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_RSHIFT_EQ */
- DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_BAND_EQ */
- DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_BOR_EQ */
- DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_BXOR_EQ */
- DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_NUMBER */
- DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_STRING */
- DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_REGEXP */
+ DUK__MK_LBP(DUK__BP_EOF), /* DUK_TOK_EOF */
+ DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_IDENTIFIER */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_BREAK */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CASE */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CATCH */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CONTINUE */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DEBUGGER */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DEFAULT */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DELETE */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DO */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_ELSE */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_FINALLY */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_FOR */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_FUNCTION */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_IF */
+ DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_IN */
+ DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_INSTANCEOF */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_NEW */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_RETURN */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SWITCH */
+ DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_THIS */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_THROW */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_TRY */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_TYPEOF */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_VAR */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CONST */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_VOID */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_WHILE */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_WITH */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CLASS */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_ENUM */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_EXPORT */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_EXTENDS */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_IMPORT */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SUPER */
+ DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_NULL */
+ DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_TRUE */
+ DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_FALSE */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_GET */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SET */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_IMPLEMENTS */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_INTERFACE */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LET */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PACKAGE */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PRIVATE */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PROTECTED */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PUBLIC */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_STATIC */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_YIELD */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LCURLY */
+ DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_RCURLY */
+ DUK__MK_LBP(DUK__BP_MEMBER), /* DUK_TOK_LBRACKET */
+ DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_RBRACKET */
+ DUK__MK_LBP(DUK__BP_CALL), /* DUK_TOK_LPAREN */
+ DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_RPAREN */
+ DUK__MK_LBP(DUK__BP_MEMBER), /* DUK_TOK_PERIOD */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SEMICOLON */
+ DUK__MK_LBP(DUK__BP_COMMA), /* DUK_TOK_COMMA */
+ DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_LT */
+ DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_GT */
+ DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_LE */
+ DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_GE */
+ DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_EQ */
+ DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_NEQ */
+ DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_SEQ */
+ DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_SNEQ */
+ DUK__MK_LBP(DUK__BP_ADDITIVE), /* DUK_TOK_ADD */
+ DUK__MK_LBP(DUK__BP_ADDITIVE), /* DUK_TOK_SUB */
+ DUK__MK_LBP(DUK__BP_MULTIPLICATIVE), /* DUK_TOK_MUL */
+ DUK__MK_LBP(DUK__BP_MULTIPLICATIVE), /* DUK_TOK_DIV */
+ DUK__MK_LBP(DUK__BP_MULTIPLICATIVE), /* DUK_TOK_MOD */
+ DUK__MK_LBP(DUK__BP_EXPONENTIATION), /* DUK_TOK_EXP */
+ DUK__MK_LBP_FLAGS(DUK__BP_POSTFIX, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_INCREMENT */
+ DUK__MK_LBP_FLAGS(DUK__BP_POSTFIX, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_DECREMENT */
+ DUK__MK_LBP(DUK__BP_SHIFT), /* DUK_TOK_ALSHIFT */
+ DUK__MK_LBP(DUK__BP_SHIFT), /* DUK_TOK_ARSHIFT */
+ DUK__MK_LBP(DUK__BP_SHIFT), /* DUK_TOK_RSHIFT */
+ DUK__MK_LBP(DUK__BP_BAND), /* DUK_TOK_BAND */
+ DUK__MK_LBP(DUK__BP_BOR), /* DUK_TOK_BOR */
+ DUK__MK_LBP(DUK__BP_BXOR), /* DUK_TOK_BXOR */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LNOT */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_BNOT */
+ DUK__MK_LBP(DUK__BP_LAND), /* DUK_TOK_LAND */
+ DUK__MK_LBP(DUK__BP_LOR), /* DUK_TOK_LOR */
+ DUK__MK_LBP(DUK__BP_CONDITIONAL), /* DUK_TOK_QUESTION */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_COLON */
+ DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_EQUALSIGN */
+ DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_ADD_EQ */
+ DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_SUB_EQ */
+ DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_MUL_EQ */
+ DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_DIV_EQ */
+ DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_MOD_EQ */
+ DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_EXP_EQ */
+ DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_ALSHIFT_EQ */
+ DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_ARSHIFT_EQ */
+ DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_RSHIFT_EQ */
+ DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_BAND_EQ */
+ DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_BOR_EQ */
+ DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_BXOR_EQ */
+ DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_NUMBER */
+ DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_STRING */
+ DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_REGEXP */
};
/*
@@ -64236,6 +69484,7 @@ DUK_LOCAL void duk__comp_recursion_increase(duk_compiler_ctx *comp_ctx) {
DUK_ASSERT(comp_ctx->recursion_depth >= 0);
if (comp_ctx->recursion_depth >= comp_ctx->recursion_limit) {
DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_COMPILER_RECURSION_LIMIT);
+ DUK_WO_NORETURN(return;);
}
comp_ctx->recursion_depth++;
}
@@ -64254,8 +69503,7 @@ DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments(duk_compiler_ctx *comp_ct
DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments_in_strict_mode(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
DUK_ASSERT(h != NULL);
- return (comp_ctx->curr_func.is_strict &&
- DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h));
+ return (comp_ctx->curr_func.is_strict && DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h));
}
/*
@@ -64270,8 +69518,8 @@ DUK_LOCAL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t e
duk_hthread *thr = comp_ctx->thr;
duk_bool_t regexp;
- DUK_ASSERT_DISABLE(comp_ctx->curr_token.t >= 0); /* unsigned */
- DUK_ASSERT(comp_ctx->curr_token.t <= DUK_TOK_MAXVAL); /* MAXVAL is inclusive */
+ DUK_ASSERT_DISABLE(comp_ctx->curr_token.t >= 0); /* unsigned */
+ DUK_ASSERT(comp_ctx->curr_token.t <= DUK_TOK_MAXVAL); /* MAXVAL is inclusive */
/*
* Use current token to decide whether a RegExp can follow.
@@ -64290,23 +69538,24 @@ DUK_LOCAL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t e
comp_ctx->curr_func.reject_regexp_in_adv = 0;
regexp = 0;
}
+ if (comp_ctx->curr_func.allow_regexp_in_adv) {
+ comp_ctx->curr_func.allow_regexp_in_adv = 0;
+ regexp = 1;
+ }
if (expect >= 0 && comp_ctx->curr_token.t != (duk_small_uint_t) expect) {
- DUK_D(DUK_DPRINT("parse error: expect=%ld, got=%ld",
- (long) expect, (long) comp_ctx->curr_token.t));
+ DUK_D(DUK_DPRINT("parse error: expect=%ld, got=%ld", (long) expect, (long) comp_ctx->curr_token.t));
DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
+ DUK_WO_NORETURN(return;);
}
/* make current token the previous; need to fiddle with valstack "backing store" */
- DUK_MEMCPY(&comp_ctx->prev_token, &comp_ctx->curr_token, sizeof(duk_token));
+ duk_memcpy(&comp_ctx->prev_token, &comp_ctx->curr_token, sizeof(duk_token));
duk_copy(thr, comp_ctx->tok11_idx, comp_ctx->tok21_idx);
duk_copy(thr, comp_ctx->tok12_idx, comp_ctx->tok22_idx);
/* parse new token */
- duk_lexer_parse_js_input_element(&comp_ctx->lex,
- &comp_ctx->curr_token,
- comp_ctx->curr_func.is_strict,
- regexp);
+ duk_lexer_parse_js_input_element(&comp_ctx->lex, &comp_ctx->curr_token, comp_ctx->curr_func.is_strict, regexp);
DUK_DDD(DUK_DDDPRINT("advance: curr: tok=%ld/%ld,%ld,term=%ld,%!T,%!T "
"prev: tok=%ld/%ld,%ld,term=%ld,%!T,%!T",
@@ -64346,7 +69595,7 @@ DUK_LOCAL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) {
entry_top = duk_get_top(thr);
- DUK_MEMZERO(func, sizeof(*func)); /* intentional overlap with earlier memzero */
+ duk_memzero(func, sizeof(*func)); /* intentional overlap with earlier memzero */
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
func->h_name = NULL;
func->h_consts = NULL;
@@ -64363,23 +69612,23 @@ DUK_LOCAL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) {
DUK_BW_INIT_PUSHBUF(thr, &func->bw_code, DUK__BC_INITIAL_INSTS * sizeof(duk_compiler_instr));
/* code_idx = entry_top + 0 */
- duk_push_array(thr);
+ duk_push_bare_array(thr);
func->consts_idx = entry_top + 1;
func->h_consts = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 1);
DUK_ASSERT(func->h_consts != NULL);
- duk_push_array(thr);
+ duk_push_bare_array(thr);
func->funcs_idx = entry_top + 2;
func->h_funcs = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 2);
DUK_ASSERT(func->h_funcs != NULL);
DUK_ASSERT(func->fnum_next == 0);
- duk_push_array(thr);
+ duk_push_bare_array(thr);
func->decls_idx = entry_top + 3;
func->h_decls = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 3);
DUK_ASSERT(func->h_decls != NULL);
- duk_push_array(thr);
+ duk_push_bare_array(thr);
func->labelnames_idx = entry_top + 4;
func->h_labelnames = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 4);
DUK_ASSERT(func->h_labelnames != NULL);
@@ -64390,7 +69639,7 @@ DUK_LOCAL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) {
DUK_ASSERT(func->h_labelinfos != NULL);
DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(func->h_labelinfos) && !DUK_HBUFFER_HAS_EXTERNAL(func->h_labelinfos));
- duk_push_array(thr);
+ duk_push_bare_array(thr);
func->argnames_idx = entry_top + 6;
func->h_argnames = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 6);
DUK_ASSERT(func->h_argnames != NULL);
@@ -64512,7 +69761,7 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
h_res = duk_push_hcompfunc(thr);
DUK_ASSERT(h_res != NULL);
DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_res) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
- DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) h_res, NULL); /* Function templates are "bare objects". */
+ DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) h_res, NULL); /* Function templates are "bare objects". */
if (func->is_function) {
DUK_DDD(DUK_DDDPRINT("function -> set NEWENV"));
@@ -64581,31 +69830,34 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
code_count = DUK_BW_GET_SIZE(thr, &func->bw_code) / sizeof(duk_compiler_instr);
code_size = code_count * sizeof(duk_instr_t);
- data_size = consts_count * sizeof(duk_tval) +
- funcs_count * sizeof(duk_hobject *) +
- code_size;
+ data_size = consts_count * sizeof(duk_tval) + funcs_count * sizeof(duk_hobject *) + code_size;
DUK_DDD(DUK_DDDPRINT("consts_count=%ld, funcs_count=%ld, code_size=%ld -> "
"data_size=%ld*%ld + %ld*%ld + %ld = %ld",
- (long) consts_count, (long) funcs_count, (long) code_size,
- (long) consts_count, (long) sizeof(duk_tval),
- (long) funcs_count, (long) sizeof(duk_hobject *),
- (long) code_size, (long) data_size));
+ (long) consts_count,
+ (long) funcs_count,
+ (long) code_size,
+ (long) consts_count,
+ (long) sizeof(duk_tval),
+ (long) funcs_count,
+ (long) sizeof(duk_hobject *),
+ (long) code_size,
+ (long) data_size));
duk_push_fixed_buffer_nozero(thr, data_size);
- h_data = (duk_hbuffer_fixed *) duk_known_hbuffer(thr, -1);
+ h_data = (duk_hbuffer_fixed *) (void *) duk_known_hbuffer(thr, -1);
DUK_HCOMPFUNC_SET_DATA(thr->heap, h_res, (duk_hbuffer *) h_data);
DUK_HEAPHDR_INCREF(thr, h_data);
p_const = (duk_tval *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data);
for (i = 0; i < consts_count; i++) {
- DUK_ASSERT(i <= DUK_UARRIDX_MAX); /* const limits */
- tv = duk_hobject_find_existing_array_entry_tval_ptr(thr->heap, func->h_consts, (duk_uarridx_t) i);
+ DUK_ASSERT(i <= DUK_UARRIDX_MAX); /* const limits */
+ tv = duk_hobject_find_array_entry_tval_ptr(thr->heap, func->h_consts, (duk_uarridx_t) i);
DUK_ASSERT(tv != NULL);
DUK_TVAL_SET_TVAL(p_const, tv);
p_const++;
- DUK_TVAL_INCREF(thr, tv); /* may be a string constant */
+ DUK_TVAL_INCREF(thr, tv); /* may be a string constant */
DUK_DDD(DUK_DDDPRINT("constant: %!T", (duk_tval *) tv));
}
@@ -64614,8 +69866,8 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_res, p_func);
for (i = 0; i < funcs_count; i++) {
duk_hobject *h;
- DUK_ASSERT(i * 3 <= DUK_UARRIDX_MAX); /* func limits */
- tv = duk_hobject_find_existing_array_entry_tval_ptr(thr->heap, func->h_funcs, (duk_uarridx_t) (i * 3));
+ DUK_ASSERT(i * 3 <= DUK_UARRIDX_MAX); /* func limits */
+ tv = duk_hobject_find_array_entry_tval_ptr(thr->heap, func->h_funcs, (duk_uarridx_t) (i * 3));
DUK_ASSERT(tv != NULL);
DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
h = DUK_TVAL_GET_OBJECT(tv);
@@ -64624,8 +69876,7 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
*p_func++ = h;
DUK_HOBJECT_INCREF(thr, h);
- DUK_DDD(DUK_DDDPRINT("inner function: %p -> %!iO",
- (void *) h, (duk_heaphdr *) h));
+ DUK_DDD(DUK_DDDPRINT("inner function: %p -> %!iO", (void *) h, (duk_heaphdr *) h));
}
p_instr = (duk_instr_t *) p_func;
@@ -64640,7 +69891,7 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
DUK_ASSERT((duk_uint8_t *) (p_instr + code_count) == DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data) + data_size);
- duk_pop(thr); /* 'data' (and everything in it) is reachable through h_res now */
+ duk_pop(thr); /* 'data' (and everything in it) is reachable through h_res now */
/*
* Init non-property result fields
@@ -64655,7 +69906,7 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
DUK_ASSERT(func->temp_max >= 0);
h_res->nregs = (duk_uint16_t) func->temp_max;
h_res->nargs = (duk_uint16_t) duk_hobject_get_length(thr, func->h_argnames);
- DUK_ASSERT(h_res->nregs >= h_res->nargs); /* pass2 allocation handles this */
+ DUK_ASSERT(h_res->nregs >= h_res->nargs); /* pass2 allocation handles this */
#if defined(DUK_USE_DEBUGGER_SUPPORT)
h_res->start_line = (duk_uint32_t) func->min_line;
h_res->end_line = (duk_uint32_t) func->max_line;
@@ -64683,11 +69934,13 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
DUK_DD(DUK_DDPRINT("keeping _Varmap because debugger support is enabled"));
keep_varmap = 1;
#else
- if (func->id_access_slow_own || /* directly uses slow accesses that may match own variables */
- func->id_access_arguments || /* accesses 'arguments' directly */
- func->may_direct_eval || /* may indirectly slow access through a direct eval */
- funcs_count > 0) { /* has inner functions which may slow access (XXX: this can be optimized by looking at the inner functions) */
- DUK_DD(DUK_DDPRINT("keeping _Varmap because of direct eval, slow path access that may match local variables, or presence of inner functions"));
+ if (func->id_access_slow_own || /* directly uses slow accesses that may match own variables */
+ func->id_access_arguments || /* accesses 'arguments' directly */
+ func->may_direct_eval || /* may indirectly slow access through a direct eval */
+ funcs_count >
+ 0) { /* has inner functions which may slow access (XXX: this can be optimized by looking at the inner functions) */
+ DUK_DD(DUK_DDPRINT("keeping _Varmap because of direct eval, slow path access that may match local variables, or "
+ "presence of inner functions"));
keep_varmap = 1;
} else {
DUK_DD(DUK_DDPRINT("dropping _Varmap"));
@@ -64699,8 +69952,7 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
duk_int_t num_used;
duk_dup(thr, func->varmap_idx);
num_used = duk__cleanup_varmap(comp_ctx);
- DUK_DDD(DUK_DDDPRINT("cleaned up varmap: %!T (num_used=%ld)",
- (duk_tval *) duk_get_tval(thr, -1), (long) num_used));
+ DUK_DDD(DUK_DDDPRINT("cleaned up varmap: %!T (num_used=%ld)", (duk_tval *) duk_get_tval(thr, -1), (long) num_used));
if (num_used > 0) {
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
@@ -64729,12 +69981,12 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
*/
DUK_DD(DUK_DDPRINT("keeping _Formals because _Formals.length != nargs"));
keep_formals = 1;
- } else if ((func->id_access_arguments || func->may_direct_eval) &&
- (formals_length > 0)) {
+ } else if ((func->id_access_arguments || func->may_direct_eval) && (formals_length > 0)) {
/* Direct eval (may access 'arguments') or accesses 'arguments'
* explicitly: keep _Formals unless it is zero length.
*/
- DUK_DD(DUK_DDPRINT("keeping _Formals because of direct eval or explicit access to 'arguments', and _Formals.length != 0"));
+ DUK_DD(DUK_DDPRINT(
+ "keeping _Formals because of direct eval or explicit access to 'arguments', and _Formals.length != 0"));
keep_formals = 1;
} else {
DUK_DD(DUK_DDPRINT("omitting _Formals, nargs matches _Formals.length, so no properties added"));
@@ -64754,7 +70006,7 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
DUK_DD(DUK_DDPRINT("setting function template .name to %!T", duk_get_tval(thr, -1)));
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
}
-#endif /* DUK_USE_FUNC_NAME_PROPERTY */
+#endif /* DUK_USE_FUNC_NAME_PROPERTY */
/* _Source */
#if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
@@ -64798,11 +70050,11 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
*/
#if 0
- duk_push_string(thr, "XXX");
+ duk_push_literal(thr, "XXX");
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);
#endif
}
-#endif /* DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY */
+#endif /* DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY */
/* _Pc2line */
#if defined(DUK_USE_PC2LINE)
@@ -64812,14 +70064,14 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
*/
DUK_ASSERT(code_count <= DUK_COMPILER_MAX_BYTECODE_LENGTH);
- duk_hobject_pc2line_pack(thr, q_instr, (duk_uint_fast32_t) code_count); /* -> pushes fixed buffer */
+ duk_hobject_pc2line_pack(thr, q_instr, (duk_uint_fast32_t) code_count); /* -> pushes fixed buffer */
duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_NONE);
/* XXX: if assertions enabled, walk through all valid PCs
* and check line mapping.
*/
}
-#endif /* DUK_USE_PC2LINE */
+#endif /* DUK_USE_PC2LINE */
/* fileName */
#if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
@@ -64833,8 +70085,7 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
}
#endif
- DUK_DD(DUK_DDPRINT("converted function: %!ixT",
- (duk_tval *) duk_get_tval(thr, -1)));
+ DUK_DD(DUK_DDPRINT("converted function: %!ixT", (duk_tval *) duk_get_tval(thr, -1)));
/*
* Compact the function template.
@@ -64857,7 +70108,7 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
p = p_start;
while (p < p_end) {
- DUK_DDD(DUK_DDDPRINT("BC %04ld: %!I ; 0x%08lx op=%ld (%!C) a=%ld b=%ld c=%ld",
+ DUK_DDD(DUK_DDDPRINT("BC %04ld: %!I ; 0x%08lx op=%ld (%!X) a=%ld b=%ld c=%ld",
(long) (p - p_start),
(duk_instr_t) (*p),
(unsigned long) (*p),
@@ -64906,14 +70157,14 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
/* Code emission flags, passed in the 'opcode' field. Opcode + flags
* fit into 16 bits for now, so use duk_small_uint_t.
*/
-#define DUK__EMIT_FLAG_NO_SHUFFLE_A (1 << 8)
-#define DUK__EMIT_FLAG_NO_SHUFFLE_B (1 << 9)
-#define DUK__EMIT_FLAG_NO_SHUFFLE_C (1 << 10)
-#define DUK__EMIT_FLAG_A_IS_SOURCE (1 << 11) /* slot A is a source (default: target) */
-#define DUK__EMIT_FLAG_B_IS_TARGET (1 << 12) /* slot B is a target (default: source) */
-#define DUK__EMIT_FLAG_C_IS_TARGET (1 << 13) /* slot C is a target (default: source) */
-#define DUK__EMIT_FLAG_BC_REGCONST (1 << 14) /* slots B and C are reg/const */
-#define DUK__EMIT_FLAG_RESERVE_JUMPSLOT (1 << 15) /* reserve a jumpslot after instr before target spilling, used for NEXTENUM */
+#define DUK__EMIT_FLAG_NO_SHUFFLE_A (1 << 8)
+#define DUK__EMIT_FLAG_NO_SHUFFLE_B (1 << 9)
+#define DUK__EMIT_FLAG_NO_SHUFFLE_C (1 << 10)
+#define DUK__EMIT_FLAG_A_IS_SOURCE (1 << 11) /* slot A is a source (default: target) */
+#define DUK__EMIT_FLAG_B_IS_TARGET (1 << 12) /* slot B is a target (default: source) */
+#define DUK__EMIT_FLAG_C_IS_TARGET (1 << 13) /* slot C is a target (default: source) */
+#define DUK__EMIT_FLAG_BC_REGCONST (1 << 14) /* slots B and C are reg/const */
+#define DUK__EMIT_FLAG_RESERVE_JUMPSLOT (1 << 15) /* reserve a jumpslot after instr before target spilling, used for NEXTENUM */
/* XXX: macro smaller than call? */
DUK_LOCAL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx) {
@@ -64924,7 +70175,8 @@ DUK_LOCAL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx) {
DUK_LOCAL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc) {
DUK_ASSERT(pc >= 0);
- DUK_ASSERT((duk_size_t) pc < (duk_size_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr)));
+ DUK_ASSERT((duk_size_t) pc <
+ (duk_size_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr)));
return ((duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code)) + pc;
}
@@ -64944,7 +70196,9 @@ DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) {
(long) duk__get_current_pc(comp_ctx),
(duk_instr_t) ins));
- instr = (duk_compiler_instr *) (void *) DUK_BW_ENSURE_GETPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
+ instr = (duk_compiler_instr *) (void *) DUK_BW_ENSURE_GETPTR(comp_ctx->thr,
+ &comp_ctx->curr_func.bw_code,
+ sizeof(duk_compiler_instr));
DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
#if defined(DUK_USE_PC2LINE)
@@ -64995,8 +70249,9 @@ DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) {
return;
- fail_bc_limit:
+fail_bc_limit:
DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);
+ DUK_WO_NORETURN(return;);
}
/* Update function min/max line from current token. Needed to improve
@@ -65028,7 +70283,11 @@ DUK_LOCAL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op
}
/* Important main primitive. */
-DUK_LOCAL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b, duk_regconst_t c) {
+DUK_LOCAL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx,
+ duk_small_uint_t op_flags,
+ duk_regconst_t a,
+ duk_regconst_t b,
+ duk_regconst_t c) {
duk_instr_t ins = 0;
duk_int_t a_out = -1;
duk_int_t b_out = -1;
@@ -65036,8 +70295,7 @@ DUK_LOCAL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_f
duk_int_t tmp;
duk_small_uint_t op = op_flags & 0xffU;
- DUK_DDD(DUK_DDDPRINT("emit: op_flags=%04lx, a=%ld, b=%ld, c=%ld",
- (unsigned long) op_flags, (long) a, (long) b, (long) c));
+ DUK_DDD(DUK_DDDPRINT("emit: op_flags=%04lx, a=%ld, b=%ld, c=%ld", (unsigned long) op_flags, (long) a, (long) b, (long) c));
/* We could rely on max temp/const checks: if they don't exceed BC
* limit, nothing here can either (just asserts would be enough).
@@ -65046,11 +70304,11 @@ DUK_LOCAL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_f
* bugs.
*/
- DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN); /* unsigned */
+ DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN); /* unsigned */
DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
DUK_ASSERT(DUK__ISREG(a));
- DUK_ASSERT(b != -1); /* Not 'none'. */
- DUK_ASSERT(c != -1); /* Not 'none'. */
+ DUK_ASSERT(b != -1); /* Not 'none'. */
+ DUK_ASSERT(c != -1); /* Not 'none'. */
/* Input shuffling happens before the actual operation, while output
* shuffling happens afterwards. Output shuffling decisions are still
@@ -65112,7 +70370,7 @@ DUK_LOCAL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_f
if (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {
/* Opcode follows B/C reg/const convention. */
DUK_ASSERT((op & 0x01) == 0);
- ins |= DUK_ENC_OP_A_B_C(0x01, 0, 0, 0); /* const flag for B */
+ ins |= DUK_ENC_OP_A_B_C(0x01, 0, 0, 0); /* const flag for B */
} else {
DUK_D(DUK_DPRINT("B is const, opcode is not B/C reg/const: %x", op_flags));
}
@@ -65135,7 +70393,8 @@ DUK_LOCAL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_f
} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) {
if (b > DUK_BC_B_MAX) {
/* Note: 0xff != DUK_BC_B_MAX */
- DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but shuffle prohibited, b: %ld", (long) b));
+ DUK_D(
+ DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but shuffle prohibited, b: %ld", (long) b));
goto error_outofregs;
}
} else if (b <= DUK_BC_BC_MAX) {
@@ -65156,7 +70415,7 @@ DUK_LOCAL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_f
duk__emit_load_int32_noshuffle(comp_ctx, tmp, b);
DUK_ASSERT(DUK_OP_MPUTOBJI == DUK_OP_MPUTOBJ + 1);
DUK_ASSERT(DUK_OP_MPUTARRI == DUK_OP_MPUTARR + 1);
- op_flags++; /* indirect opcode follows direct */
+ op_flags++; /* indirect opcode follows direct */
} else {
duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, b));
}
@@ -65182,7 +70441,7 @@ DUK_LOCAL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_f
if (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {
/* Opcode follows B/C reg/const convention. */
DUK_ASSERT((op & 0x02) == 0);
- ins |= DUK_ENC_OP_A_B_C(0x02, 0, 0, 0); /* const flag for C */
+ ins |= DUK_ENC_OP_A_B_C(0x02, 0, 0, 0); /* const flag for C */
} else {
DUK_D(DUK_DPRINT("C is const, opcode is not B/C reg/const: %x", op_flags));
}
@@ -65205,7 +70464,8 @@ DUK_LOCAL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_f
} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) {
if (c > DUK_BC_C_MAX) {
/* Note: 0xff != DUK_BC_C_MAX */
- DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but shuffle prohibited, c: %ld", (long) c));
+ DUK_D(
+ DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but shuffle prohibited, c: %ld", (long) c));
goto error_outofregs;
}
} else if (c <= DUK_BC_BC_MAX) {
@@ -65279,8 +70539,9 @@ DUK_LOCAL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_f
return;
- error_outofregs:
+error_outofregs:
DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
+ DUK_WO_NORETURN(return;);
}
/* For many of the helpers below it'd be technically correct to add
@@ -65306,7 +70567,7 @@ DUK_LOCAL void duk__emit_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_fla
duk__emit_a_b_c(comp_ctx, op_flags, 0, b, c);
}
-#if 0 /* unused */
+#if 0 /* unused */
DUK_LOCAL void duk__emit_a(duk_compiler_ctx *comp_ctx, int op_flags, int a) {
#if defined(DUK_USE_SHUFFLE_TORTURE)
op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_B | DUK__EMIT_FLAG_NO_SHUFFLE_C;
@@ -65315,7 +70576,7 @@ DUK_LOCAL void duk__emit_a(duk_compiler_ctx *comp_ctx, int op_flags, int a) {
}
#endif
-#if 0 /* unused */
+#if 0 /* unused */
DUK_LOCAL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b) {
#if defined(DUK_USE_SHUFFLE_TORTURE)
op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_NO_SHUFFLE_C;
@@ -65329,10 +70590,10 @@ DUK_LOCAL void duk__emit_a_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_fl
duk_int_t tmp;
/* allow caller to give a const number with the DUK__CONST_MARKER */
- DUK_ASSERT(bc != -1); /* Not 'none'. */
+ DUK_ASSERT(bc != -1); /* Not 'none'. */
bc = bc & (~DUK__CONST_MARKER);
- DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN); /* unsigned */
+ DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN); /* unsigned */
DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
DUK_ASSERT(bc >= DUK_BC_BC_MIN);
DUK_ASSERT(bc <= DUK_BC_BC_MAX);
@@ -65377,8 +70638,9 @@ DUK_LOCAL void duk__emit_a_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_fl
}
return;
- error_outofregs:
+error_outofregs:
DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
+ DUK_WO_NORETURN(return;);
}
DUK_LOCAL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc) {
@@ -65391,12 +70653,12 @@ DUK_LOCAL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk
DUK_LOCAL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc) {
duk_instr_t ins;
- DUK_ASSERT_DISABLE(op >= DUK_BC_OP_MIN); /* unsigned */
+ DUK_ASSERT_DISABLE(op >= DUK_BC_OP_MIN); /* unsigned */
DUK_ASSERT(op <= DUK_BC_OP_MAX);
- DUK_ASSERT_DISABLE(abc >= DUK_BC_ABC_MIN); /* unsigned */
+ DUK_ASSERT_DISABLE(abc >= DUK_BC_ABC_MIN); /* unsigned */
DUK_ASSERT(abc <= DUK_BC_ABC_MAX);
DUK_ASSERT((abc & DUK__CONST_MARKER) == 0);
- DUK_ASSERT(abc != -1); /* Not 'none'. */
+ DUK_ASSERT(abc != -1); /* Not 'none'. */
if (abc <= DUK_BC_ABC_MAX) {
;
@@ -65404,18 +70666,26 @@ DUK_LOCAL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, du
goto error_outofregs;
}
ins = DUK_ENC_OP_ABC(op, abc);
- DUK_DDD(DUK_DDDPRINT("duk__emit_abc: 0x%08lx line=%ld pc=%ld op=%ld (%!C) abc=%ld (%!I)",
- (unsigned long) ins, (long) comp_ctx->curr_token.start_line,
- (long) duk__get_current_pc(comp_ctx), (long) op, (long) op,
- (long) abc, (duk_instr_t) ins));
+ DUK_DDD(DUK_DDDPRINT("duk__emit_abc: 0x%08lx line=%ld pc=%ld op=%ld (%!X) abc=%ld (%!I)",
+ (unsigned long) ins,
+ (long) comp_ctx->curr_token.start_line,
+ (long) duk__get_current_pc(comp_ctx),
+ (long) op,
+ (long) op,
+ (long) abc,
+ (duk_instr_t) ins));
duk__emit(comp_ctx, ins);
return;
- error_outofregs:
+error_outofregs:
DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
+ DUK_WO_NORETURN(return;);
}
-DUK_LOCAL void duk__emit_load_int32_raw(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val, duk_small_uint_t op_flags) {
+DUK_LOCAL void duk__emit_load_int32_raw(duk_compiler_ctx *comp_ctx,
+ duk_regconst_t reg,
+ duk_int32_t val,
+ duk_small_uint_t op_flags) {
/* XXX: Shuffling support could be implemented here so that LDINT+LDINTX
* would only shuffle once (instead of twice). The current code works
* though, and has a smaller compiler footprint.
@@ -65430,7 +70700,10 @@ DUK_LOCAL void duk__emit_load_int32_raw(duk_compiler_ctx *comp_ctx, duk_regconst
duk_int32_t lo = val & ((((duk_int32_t) 1) << DUK_BC_LDINTX_SHIFT) - 1);
DUK_ASSERT(lo >= 0);
DUK_DDD(DUK_DDDPRINT("emit LDINT+LDINTX to reg %ld for %ld -> hi %ld, lo %ld",
- (long) reg, (long) val, (long) hi, (long) lo));
+ (long) reg,
+ (long) val,
+ (long) hi,
+ (long) lo));
duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (hi + (duk_int32_t) DUK_BC_LDINT_BIAS));
duk__emit_a_bc(comp_ctx, DUK_OP_LDINTX | op_flags, reg, (duk_regconst_t) lo);
}
@@ -65471,7 +70744,7 @@ DUK_LOCAL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc) {
DUK_LOCAL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx) {
duk_int_t ret;
- ret = duk__get_current_pc(comp_ctx); /* useful for patching jumps later */
+ ret = duk__get_current_pc(comp_ctx); /* useful for patching jumps later */
duk__emit_op_only(comp_ctx, DUK_OP_JUMP);
return ret;
}
@@ -65489,13 +70762,10 @@ DUK_LOCAL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump
DUK_ASSERT(jump_pc >= 0);
offset = (duk_size_t) jump_pc * sizeof(duk_compiler_instr);
instr = (duk_compiler_instr *) (void *)
- DUK_BW_INSERT_ENSURE_AREA(comp_ctx->thr,
- &comp_ctx->curr_func.bw_code,
- offset,
- sizeof(duk_compiler_instr));
+ DUK_BW_INSERT_ENSURE_AREA(comp_ctx->thr, &comp_ctx->curr_func.bw_code, offset, sizeof(duk_compiler_instr));
#if defined(DUK_USE_PC2LINE)
- line = comp_ctx->curr_token.start_line; /* approximation, close enough */
+ line = comp_ctx->curr_token.start_line; /* approximation, close enough */
#endif
instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, 0);
#if defined(DUK_USE_PC2LINE)
@@ -65508,8 +70778,9 @@ DUK_LOCAL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump
}
return;
- fail_bc_limit:
+fail_bc_limit:
DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);
+ DUK_WO_NORETURN(return;);
}
/* Does not assume that jump_pc contains a DUK_OP_JUMP previously; this is intentional
@@ -65521,8 +70792,8 @@ DUK_LOCAL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, du
/* allow negative PCs, behave as a no-op */
if (jump_pc < 0) {
- DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): nop call, jump_pc=%ld (<0), target_pc=%ld",
- (long) jump_pc, (long) target_pc));
+ DUK_DDD(
+ DUK_DDDPRINT("duk__patch_jump(): nop call, jump_pc=%ld (<0), target_pc=%ld", (long) jump_pc, (long) target_pc));
return;
}
DUK_ASSERT(jump_pc >= 0);
@@ -65536,14 +70807,21 @@ DUK_LOCAL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, du
instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, offset + DUK_BC_JUMP_BIAS);
DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): jump_pc=%ld, target_pc=%ld, offset=%ld",
- (long) jump_pc, (long) target_pc, (long) offset));
+ (long) jump_pc,
+ (long) target_pc,
+ (long) offset));
}
DUK_LOCAL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
duk__patch_jump(comp_ctx, jump_pc, duk__get_current_pc(comp_ctx));
}
-DUK_LOCAL void duk__patch_trycatch(duk_compiler_ctx *comp_ctx, duk_int_t ldconst_pc, duk_int_t trycatch_pc, duk_regconst_t reg_catch, duk_regconst_t const_varname, duk_small_uint_t flags) {
+DUK_LOCAL void duk__patch_trycatch(duk_compiler_ctx *comp_ctx,
+ duk_int_t ldconst_pc,
+ duk_int_t trycatch_pc,
+ duk_regconst_t reg_catch,
+ duk_regconst_t const_varname,
+ duk_small_uint_t flags) {
duk_compiler_instr *instr;
DUK_ASSERT(DUK__ISREG(reg_catch));
@@ -65563,8 +70841,12 @@ DUK_LOCAL void duk__patch_trycatch(duk_compiler_ctx *comp_ctx, duk_int_t ldconst
* See: test-bug-trycatch-many-constants.js.
*/
DUK_D(DUK_DPRINT("failed to patch trycatch: flags=%ld, reg_catch=%ld, const_varname=%ld (0x%08lx)",
- (long) flags, (long) reg_catch, (long) const_varname, (long) const_varname));
+ (long) flags,
+ (long) reg_catch,
+ (long) const_varname,
+ (long) const_varname));
DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
+ DUK_WO_NORETURN(return;);
}
instr->ins |= DUK_ENC_OP_A_BC(0, 0, const_varname);
} else {
@@ -65585,14 +70867,14 @@ DUK_LOCAL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_
duk_small_uint_t op;
op = DUK__ISREG(regconst) ? DUK_OP_IFFALSE_R : DUK_OP_IFFALSE_C;
- duk__emit_bc(comp_ctx, op, regconst); /* helper will remove const flag */
+ duk__emit_bc(comp_ctx, op, regconst); /* helper will remove const flag */
}
DUK_LOCAL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
duk_small_uint_t op;
op = DUK__ISREG(regconst) ? DUK_OP_IFTRUE_R : DUK_OP_IFTRUE_C;
- duk__emit_bc(comp_ctx, op, regconst); /* helper will remove const flag */
+ duk__emit_bc(comp_ctx, op, regconst); /* helper will remove const flag */
}
DUK_LOCAL void duk__emit_invalid(duk_compiler_ctx *comp_ctx) {
@@ -65616,7 +70898,8 @@ DUK_LOCAL void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx) {
#if defined(DUK_USE_BUFLEN16)
/* No need to assert, buffer size maximum is 0xffff. */
#else
- DUK_ASSERT((duk_size_t) DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr) <= (duk_size_t) DUK_INT_MAX); /* bytecode limits */
+ DUK_ASSERT((duk_size_t) DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr) <=
+ (duk_size_t) DUK_INT_MAX); /* bytecode limits */
#endif
n = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
@@ -65651,7 +70934,9 @@ DUK_LOCAL void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx) {
target_pc2 = target_pc1 + 1 + (duk_int_t) DUK_DEC_ABC(ins) - (duk_int_t) DUK_BC_JUMP_BIAS;
DUK_DDD(DUK_DDDPRINT("optimizing jump at pc %ld; old target is %ld -> new target is %ld",
- (long) i, (long) target_pc1, (long) target_pc2));
+ (long) i,
+ (long) target_pc1,
+ (long) target_pc2));
bc[i].ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, target_pc2 - (i + 1) + DUK_BC_JUMP_BIAS);
@@ -65677,15 +70962,21 @@ DUK_LOCAL void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx) {
/* XXX: DUK__IVAL_FLAG_REQUIRE_SHORT is passed but not currently implemented
* by ispec/ivalue operations.
*/
-#define DUK__IVAL_FLAG_ALLOW_CONST (1 << 0) /* allow a constant to be returned */
-#define DUK__IVAL_FLAG_REQUIRE_TEMP (1 << 1) /* require a (mutable) temporary as a result (or a const if allowed) */
-#define DUK__IVAL_FLAG_REQUIRE_SHORT (1 << 2) /* require a short (8-bit) reg/const which fits into bytecode B/C slot */
+#define DUK__IVAL_FLAG_ALLOW_CONST (1 << 0) /* allow a constant to be returned */
+#define DUK__IVAL_FLAG_REQUIRE_TEMP (1 << 1) /* require a (mutable) temporary as a result (or a const if allowed) */
+#define DUK__IVAL_FLAG_REQUIRE_SHORT (1 << 2) /* require a short (8-bit) reg/const which fits into bytecode B/C slot */
/* XXX: some code might benefit from DUK__SETTEMP_IFTEMP(thr,x) */
-#if 0 /* enable manually for dumping */
-#define DUK__DUMP_ISPEC(compctx,ispec) do { duk__dump_ispec((compctx), (ispec)); } while (0)
-#define DUK__DUMP_IVALUE(compctx,ivalue) do { duk__dump_ivalue((compctx), (ivalue)); } while (0)
+#if 0 /* enable manually for dumping */
+#define DUK__DUMP_ISPEC(compctx, ispec) \
+ do { \
+ duk__dump_ispec((compctx), (ispec)); \
+ } while (0)
+#define DUK__DUMP_IVALUE(compctx, ivalue) \
+ do { \
+ duk__dump_ivalue((compctx), (ivalue)); \
+ } while (0)
DUK_LOCAL void duk__dump_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *x) {
DUK_D(DUK_DPRINT("ispec dump: t=%ld regconst=0x%08lx, valstack_idx=%ld, value=%!T",
@@ -65703,8 +70994,12 @@ DUK_LOCAL void duk__dump_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
duk_get_tval(comp_ctx->thr, x->x2.valstack_idx)));
}
#else
-#define DUK__DUMP_ISPEC(comp_ctx,x) do {} while (0)
-#define DUK__DUMP_IVALUE(comp_ctx,x) do {} while (0)
+#define DUK__DUMP_ISPEC(comp_ctx, x) \
+ do { \
+ } while (0)
+#define DUK__DUMP_IVALUE(comp_ctx, x) \
+ do { \
+ } while (0)
#endif
DUK_LOCAL void duk__ivalue_regconst(duk_ivalue *x, duk_regconst_t regconst) {
@@ -65754,8 +71049,9 @@ DUK_LOCAL duk_regconst_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_i
res = comp_ctx->curr_func.temp_next;
comp_ctx->curr_func.temp_next += num;
- if (comp_ctx->curr_func.temp_next > DUK__MAX_TEMPS) { /* == DUK__MAX_TEMPS is OK */
+ if (comp_ctx->curr_func.temp_next > DUK__MAX_TEMPS) { /* == DUK__MAX_TEMPS is OK */
DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_TEMP_LIMIT);
+ DUK_WO_NORETURN(return 0;);
}
/* maintain highest 'used' temporary, needed to figure out nregs of function */
@@ -65806,8 +71102,7 @@ DUK_LOCAL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx) {
* constant for e.g. +0 and -0.
*/
if (duk_js_samevalue(tv1, tv2)) {
- DUK_DDD(DUK_DDDPRINT("reused existing constant for %!T -> const index %ld",
- (duk_tval *) tv1, (long) i));
+ DUK_DDD(DUK_DDDPRINT("reused existing constant for %!T -> const index %ld", (duk_tval *) tv1, (long) i));
duk_pop(thr);
return (duk_regconst_t) i | (duk_regconst_t) DUK__CONST_MARKER;
}
@@ -65815,11 +71110,11 @@ DUK_LOCAL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx) {
if (n > DUK__MAX_CONSTS) {
DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_CONST_LIMIT);
+ DUK_WO_NORETURN(return 0;);
}
- DUK_DDD(DUK_DDDPRINT("allocating new constant for %!T -> const index %ld",
- (duk_tval *) tv1, (long) n));
- (void) duk_put_prop_index(thr, f->consts_idx, (duk_uarridx_t) n); /* invalidates tv1, tv2 */
+ DUK_DDD(DUK_DDDPRINT("allocating new constant for %!T -> const index %ld", (duk_tval *) tv1, (long) n));
+ (void) duk_put_prop_index(thr, f->consts_idx, (duk_uarridx_t) n); /* invalidates tv1, tv2 */
return (duk_regconst_t) n | (duk_regconst_t) DUK__CONST_MARKER;
}
@@ -65828,15 +71123,15 @@ DUK_LOCAL duk_bool_t duk__const_needs_refcount(duk_compiler_ctx *comp_ctx, duk_r
duk_compiler_func *f = &comp_ctx->curr_func;
duk_bool_t ret;
- DUK_ASSERT((rc & DUK__CONST_MARKER) == 0); /* caller removes const marker */
+ DUK_ASSERT((rc & DUK__CONST_MARKER) == 0); /* caller removes const marker */
(void) duk_get_prop_index(comp_ctx->thr, f->consts_idx, (duk_uarridx_t) rc);
- ret = !duk_is_number(comp_ctx->thr, -1); /* now only number/string, so conservative check */
+ ret = !duk_is_number(comp_ctx->thr, -1); /* now only number/string, so conservative check */
duk_pop(comp_ctx->thr);
return ret;
#else
DUK_UNREF(comp_ctx);
DUK_UNREF(rc);
- DUK_ASSERT((rc & DUK__CONST_MARKER) == 0); /* caller removes const marker */
+ DUK_ASSERT((rc & DUK__CONST_MARKER) == 0); /* caller removes const marker */
return 0;
#endif
}
@@ -65899,9 +71194,7 @@ duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
}
case DUK_TAG_BOOLEAN: {
duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
- duk__emit_bc(comp_ctx,
- (DUK_TVAL_GET_BOOLEAN(tv) ? DUK_OP_LDTRUE : DUK_OP_LDFALSE),
- dest);
+ duk__emit_bc(comp_ctx, (DUK_TVAL_GET_BOOLEAN(tv) ? DUK_OP_LDTRUE : DUK_OP_LDFALSE), dest);
return dest;
}
case DUK_TAG_POINTER: {
@@ -65917,7 +71210,7 @@ duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
DUK_UNREF(h);
DUK_ASSERT(h != NULL);
-#if 0 /* XXX: to be implemented? */
+#if 0 /* XXX: to be implemented? */
/* Use special opcodes to load short strings */
if (DUK_HSTRING_GET_BYTELEN(h) <= 2) {
/* Encode into a single opcode (18 bits can encode 1-2 bytes + length indicator) */
@@ -65987,7 +71280,8 @@ duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
return dest;
}
}
- } /* end switch */
+ } /* end switch */
+ goto fail_internal; /* never here */
}
case DUK_ISPEC_REGCONST: {
if (forced_reg >= 0) {
@@ -66020,12 +71314,13 @@ duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
return x->regconst;
}
default: {
- break;
+ break; /* never here */
}
}
+fail_internal:
DUK_ERROR_INTERNAL(thr);
- return 0;
+ DUK_WO_NORETURN(return 0;);
}
DUK_LOCAL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_regconst_t forced_reg) {
@@ -66043,10 +71338,13 @@ DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x
DUK_DDD(DUK_DDDPRINT("duk__ivalue_toplain_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
"forced_reg=%ld",
- (long) x->t, (long) x->op,
- (long) x->x1.t, (long) x->x1.regconst,
+ (long) x->t,
+ (long) x->op,
+ (long) x->x1.t,
+ (long) x->x1.regconst,
(duk_tval *) duk_get_tval(thr, x->x1.valstack_idx),
- (long) x->x2.t, (long) x->x2.regconst,
+ (long) x->x2.t,
+ (long) x->x2.regconst,
(duk_tval *) duk_get_tval(thr, x->x2.valstack_idx),
(long) forced_reg));
@@ -66072,9 +71370,7 @@ DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x
DUK_ASSERT(tv1 != NULL);
DUK_ASSERT(tv2 != NULL);
- DUK_DDD(DUK_DDDPRINT("arith: tv1=%!T, tv2=%!T",
- (duk_tval *) tv1,
- (duk_tval *) tv2));
+ DUK_DDD(DUK_DDDPRINT("arith: tv1=%!T, tv2=%!T", (duk_tval *) tv1, (duk_tval *) tv2));
if (DUK_TVAL_IS_NUMBER(tv1) && DUK_TVAL_IS_NUMBER(tv2)) {
duk_double_t d1 = DUK_TVAL_GET_NUMBER(tv1);
@@ -66083,7 +71379,9 @@ DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x
duk_bool_t accept_fold = 1;
DUK_DDD(DUK_DDDPRINT("arith inline check: d1=%lf, d2=%lf, op=%ld",
- (double) d1, (double) d2, (long) x->op));
+ (double) d1,
+ (double) d2,
+ (long) x->op));
switch (x->op) {
case DUK_OP_ADD: {
d3 = d1 + d2;
@@ -66098,7 +71396,10 @@ DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x
break;
}
case DUK_OP_DIV: {
- d3 = d1 / d2;
+ /* Division-by-zero is undefined
+ * behavior, so rely on a helper.
+ */
+ d3 = duk_double_div(d1, d2);
break;
}
case DUK_OP_EXP: {
@@ -66106,7 +71407,7 @@ DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x
break;
}
default: {
- d3 = 0.0; /* Won't be used, but silence MSVC /W4 warning. */
+ d3 = 0.0; /* Won't be used, but silence MSVC /W4 warning. */
accept_fold = 0;
break;
}
@@ -66120,12 +71421,12 @@ DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x
x->t = DUK_IVAL_PLAIN;
DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
- DUK_TVAL_SET_NUMBER(tv1, d3); /* old value is number: no refcount */
+ DUK_TVAL_SET_NUMBER(tv1, d3); /* old value is number: no refcount */
return;
}
} else if (x->op == DUK_OP_ADD && DUK_TVAL_IS_STRING(tv1) && DUK_TVAL_IS_STRING(tv2)) {
/* Inline string concatenation. No need to check for
- * symbols, as all inputs are valid Ecmascript strings.
+ * symbols, as all inputs are valid ECMAScript strings.
*/
duk_dup(thr, x->x1.valstack_idx);
duk_dup(thr, x->x2.valstack_idx);
@@ -66137,8 +71438,14 @@ DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x
}
}
- arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
- arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
+ arg1 = duk__ispec_toregconst_raw(comp_ctx,
+ &x->x1,
+ -1,
+ DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
+ arg2 = duk__ispec_toregconst_raw(comp_ctx,
+ &x->x2,
+ -1,
+ DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
/* If forced reg, use it as destination. Otherwise try to
* use either coerced ispec if it is a temporary.
@@ -66166,8 +71473,14 @@ DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x
duk_regconst_t dest;
/* Need a short reg/const, does not have to be a mutable temp. */
- arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
- arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
+ arg1 = duk__ispec_toregconst_raw(comp_ctx,
+ &x->x1,
+ -1,
+ DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
+ arg2 = duk__ispec_toregconst_raw(comp_ctx,
+ &x->x2,
+ -1,
+ DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
/* Pick a destination register. If either base value or key
* happens to be a temp value, reuse it as the destination.
@@ -66188,11 +71501,7 @@ DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x
dest = DUK__ALLOCTEMP(comp_ctx);
}
- duk__emit_a_b_c(comp_ctx,
- DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST,
- dest,
- arg1,
- arg2);
+ duk__emit_a_b_c(comp_ctx, DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST, dest, arg1, arg2);
duk__ivalue_regconst(x, dest);
return;
@@ -66223,7 +71532,7 @@ DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x
}
DUK_ERROR_INTERNAL(thr);
- return;
+ DUK_WO_NORETURN(return;);
}
/* evaluate to plain value, no forced register (temp/bound reg both ok) */
@@ -66260,10 +71569,13 @@ duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
DUK_DDD(DUK_DDDPRINT("duk__ivalue_toregconst_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
"forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
- (long) x->t, (long) x->op,
- (long) x->x1.t, (long) x->x1.regconst,
+ (long) x->t,
+ (long) x->op,
+ (long) x->x1.t,
+ (long) x->x1.regconst,
(duk_tval *) duk_get_tval(thr, x->x1.valstack_idx),
- (long) x->x2.t, (long) x->x2.regconst,
+ (long) x->x2.t,
+ (long) x->x2.regconst,
(duk_tval *) duk_get_tval(thr, x->x2.valstack_idx),
(long) forced_reg,
(unsigned long) flags,
@@ -66286,7 +71598,7 @@ DUK_LOCAL duk_regconst_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalu
return duk__ivalue_toregconst_raw(comp_ctx, x, -1, 0 /*flags*/);
}
-#if 0 /* unused */
+#if 0 /* unused */
DUK_LOCAL duk_regconst_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
}
@@ -66322,8 +71634,7 @@ DUK_LOCAL duk_regconst_t duk__lookup_active_register_binding(duk_compiler_ctx *c
duk_hstring *h_varname;
duk_regconst_t ret;
- DUK_DDD(DUK_DDDPRINT("resolving identifier reference to '%!T'",
- (duk_tval *) duk_get_tval(thr, -1)));
+ DUK_DDD(DUK_DDDPRINT("resolving identifier reference to '%!T'", (duk_tval *) duk_get_tval(thr, -1)));
/*
* Special name handling
@@ -66376,13 +71687,13 @@ DUK_LOCAL duk_regconst_t duk__lookup_active_register_binding(duk_compiler_ctx *c
DUK_DDD(DUK_DDDPRINT("identifier lookup -> reg %ld", (long) ret));
return ret;
- slow_path_notown:
+slow_path_notown:
DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path, not own variable"));
comp_ctx->curr_func.id_access_slow = 1;
return (duk_regconst_t) -1;
- slow_path_own:
+slow_path_own:
DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path, may be own variable"));
comp_ctx->curr_func.id_access_slow = 1;
@@ -66410,7 +71721,7 @@ DUK_LOCAL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *comp_ctx, duk_regconst_t
if (reg_varbind >= 0) {
*out_reg_varbind = reg_varbind;
- *out_rc_varname = 0; /* duk_regconst_t is unsigned, so use 0 as dummy value (ignored by caller) */
+ *out_rc_varname = 0; /* duk_regconst_t is unsigned, so use 0 as dummy value (ignored by caller) */
duk_pop(thr);
return 1;
} else {
@@ -66455,11 +71766,12 @@ DUK_LOCAL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label,
if (li->h_label == h_label && h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
DUK_ERROR_SYNTAX(thr, DUK_STR_DUPLICATE_LABEL);
+ DUK_WO_NORETURN(return;);
}
}
duk_push_hstring(thr, h_label);
- DUK_ASSERT(n <= DUK_UARRIDX_MAX); /* label limits */
+ DUK_ASSERT(n <= DUK_UARRIDX_MAX); /* label limits */
(void) duk_put_prop_index(thr, comp_ctx->curr_func.labelnames_idx, (duk_uarridx_t) n);
new_size = (n + 1) * sizeof(duk_labelinfo);
@@ -66469,7 +71781,7 @@ DUK_LOCAL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label,
/* relookup after possible realloc */
p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
li_start = (duk_labelinfo *) (void *) p;
- DUK_UNREF(li_start); /* silence scan-build warning */
+ DUK_UNREF(li_start); /* silence scan-build warning */
li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
li--;
@@ -66483,12 +71795,15 @@ DUK_LOCAL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label,
li->flags = DUK_LABEL_FLAG_ALLOW_BREAK;
li->label_id = label_id;
li->h_label = h_label;
- li->catch_depth = comp_ctx->curr_func.catch_depth; /* catch depth from current func */
+ li->catch_depth = comp_ctx->curr_func.catch_depth; /* catch depth from current func */
li->pc_label = pc_label;
DUK_DDD(DUK_DDDPRINT("registered label: flags=0x%08lx, id=%ld, name=%!O, catch_depth=%ld, pc_label=%ld",
- (unsigned long) li->flags, (long) li->label_id, (duk_heaphdr *) li->h_label,
- (long) li->catch_depth, (long) li->pc_label));
+ (unsigned long) li->flags,
+ (long) li->label_id,
+ (duk_heaphdr *) li->h_label,
+ (long) li->catch_depth,
+ (long) li->pc_label));
}
/* Update all labels with matching label_id. */
@@ -66512,7 +71827,9 @@ DUK_LOCAL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t lab
}
DUK_DDD(DUK_DDDPRINT("updating (overwriting) label flags for li=%p, label_id=%ld, flags=%ld",
- (void *) li, (long) label_id, (long) flags));
+ (void *) li,
+ (long) label_id,
+ (long) flags));
li->flags = flags;
}
@@ -66533,14 +71850,19 @@ DUK_LOCAL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t lab
*/
/* XXX: awkward, especially the bunch of separate output values -> output struct? */
-DUK_LOCAL void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_bool_t is_break, duk_int_t *out_label_id, duk_int_t *out_label_catch_depth, duk_int_t *out_label_pc, duk_bool_t *out_is_closest) {
+DUK_LOCAL void duk__lookup_active_label(duk_compiler_ctx *comp_ctx,
+ duk_hstring *h_label,
+ duk_bool_t is_break,
+ duk_int_t *out_label_id,
+ duk_int_t *out_label_catch_depth,
+ duk_int_t *out_label_pc,
+ duk_bool_t *out_is_closest) {
duk_hthread *thr = comp_ctx->thr;
duk_uint8_t *p;
duk_labelinfo *li_start, *li_end, *li;
duk_bool_t match = 0;
- DUK_DDD(DUK_DDDPRINT("looking up active label: label='%!O', is_break=%ld",
- (duk_heaphdr *) h_label, (long) is_break));
+ DUK_DDD(DUK_DDDPRINT("looking up active label: label='%!O', is_break=%ld", (duk_heaphdr *) h_label, (long) is_break));
DUK_UNREF(thr);
@@ -66564,7 +71886,8 @@ DUK_LOCAL void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring
}
DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] -> '%!O' label name matches (still need to check type)",
- (long) (li - li_start), (duk_heaphdr *) h_label));
+ (long) (li - li_start),
+ (duk_heaphdr *) h_label));
/* currently all labels accept a break, so no explicit check for it now */
DUK_ASSERT(li->flags & DUK_LABEL_FLAG_ALLOW_BREAK);
@@ -66584,6 +71907,7 @@ DUK_LOCAL void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring
*/
if (h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);
+ DUK_WO_NORETURN(return;);
} else {
DUK_DDD(DUK_DDDPRINT("continue matched an empty label which does not "
"allow a continue -> continue lookup deeper in label stack"));
@@ -66593,11 +71917,14 @@ DUK_LOCAL void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring
/* XXX: match flag is awkward, rework */
if (!match) {
DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);
+ DUK_WO_NORETURN(return;);
}
DUK_DDD(DUK_DDDPRINT("label match: %!O -> label_id %ld, catch_depth=%ld, pc_label=%ld",
- (duk_heaphdr *) h_label, (long) li->label_id,
- (long) li->catch_depth, (long) li->pc_label));
+ (duk_heaphdr *) h_label,
+ (long) li->label_id,
+ (long) li->catch_depth,
+ (long) li->pc_label));
*out_label_id = li->label_id;
*out_label_catch_depth = li->catch_depth;
@@ -66621,21 +71948,21 @@ DUK_LOCAL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_size_
*/
/* object literal key tracking flags */
-#define DUK__OBJ_LIT_KEY_PLAIN (1 << 0) /* key encountered as a plain property */
-#define DUK__OBJ_LIT_KEY_GET (1 << 1) /* key encountered as a getter */
-#define DUK__OBJ_LIT_KEY_SET (1 << 2) /* key encountered as a setter */
+#define DUK__OBJ_LIT_KEY_PLAIN (1 << 0) /* key encountered as a plain property */
+#define DUK__OBJ_LIT_KEY_GET (1 << 1) /* key encountered as a getter */
+#define DUK__OBJ_LIT_KEY_SET (1 << 2) /* key encountered as a setter */
DUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
duk_hthread *thr = comp_ctx->thr;
- duk_regconst_t reg_obj; /* result reg */
- duk_regconst_t reg_temp; /* temp reg */
- duk_regconst_t temp_start; /* temp reg value for start of loop */
- duk_small_uint_t max_init_values; /* max # of values initialized in one MPUTARR set */
- duk_small_uint_t num_values; /* number of values in current MPUTARR set */
- duk_uarridx_t curr_idx; /* current (next) array index */
- duk_uarridx_t start_idx; /* start array index of current MPUTARR set */
- duk_uarridx_t init_idx; /* last array index explicitly initialized, +1 */
- duk_bool_t require_comma; /* next loop requires a comma */
+ duk_regconst_t reg_obj; /* result reg */
+ duk_regconst_t reg_temp; /* temp reg */
+ duk_regconst_t temp_start; /* temp reg value for start of loop */
+ duk_small_uint_t max_init_values; /* max # of values initialized in one MPUTARR set */
+ duk_small_uint_t num_values; /* number of values in current MPUTARR set */
+ duk_uarridx_t curr_idx; /* current (next) array index */
+ duk_uarridx_t start_idx; /* start array index of current MPUTARR set */
+ duk_uarridx_t init_idx; /* last array index explicitly initialized, +1 */
+ duk_bool_t require_comma; /* next loop requires a comma */
#if !defined(DUK_USE_PREFER_SIZE)
duk_int_t pc_newarr;
duk_compiler_instr *instr;
@@ -66644,13 +71971,13 @@ DUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *re
/* DUK_TOK_LBRACKET already eaten, current token is right after that */
DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LBRACKET);
- max_init_values = DUK__MAX_ARRAY_INIT_VALUES; /* XXX: depend on available temps? */
+ max_init_values = DUK__MAX_ARRAY_INIT_VALUES; /* XXX: depend on available temps? */
reg_obj = DUK__ALLOCTEMP(comp_ctx);
#if !defined(DUK_USE_PREFER_SIZE)
pc_newarr = duk__get_current_pc(comp_ctx);
#endif
- duk__emit_bc(comp_ctx, DUK_OP_NEWARR, reg_obj); /* XXX: patch initial size hint afterwards? */
+ duk__emit_bc(comp_ctx, DUK_OP_NEWARR, reg_obj); /* XXX: patch initial size hint afterwards? */
temp_start = DUK__GETTEMP(comp_ctx);
/*
@@ -66666,7 +71993,7 @@ DUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *re
*/
curr_idx = 0;
- init_idx = 0; /* tracks maximum initialized index + 1 */
+ init_idx = 0; /* tracks maximum initialized index + 1 */
start_idx = 0;
require_comma = 0;
@@ -66712,7 +72039,7 @@ DUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *re
duk__emit_load_int32(comp_ctx, reg_temp, (duk_int32_t) start_idx);
}
- reg_temp = DUK__ALLOCTEMP(comp_ctx); /* alloc temp just in case, to update max temp */
+ reg_temp = DUK__ALLOCTEMP(comp_ctx); /* alloc temp just in case, to update max temp */
DUK__SETTEMP(comp_ctx, reg_temp);
duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);
DUK__SETTEMP(comp_ctx, reg_temp + 1);
@@ -66737,9 +72064,7 @@ DUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *re
* never needs to be.
*/
duk__emit_a_b_c(comp_ctx,
- DUK_OP_MPUTARR |
- DUK__EMIT_FLAG_NO_SHUFFLE_C |
- DUK__EMIT_FLAG_A_IS_SOURCE,
+ DUK_OP_MPUTARR | DUK__EMIT_FLAG_NO_SHUFFLE_C | DUK__EMIT_FLAG_A_IS_SOURCE,
reg_obj,
temp_start,
(duk_regconst_t) (num_values + 1));
@@ -66760,8 +72085,7 @@ DUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *re
DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RBRACKET);
duk__advance(comp_ctx);
- DUK_DDD(DUK_DDDPRINT("array literal done, curridx=%ld, initidx=%ld",
- (long) curr_idx, (long) init_idx));
+ DUK_DDD(DUK_DDDPRINT("array literal done, curridx=%ld, initidx=%ld", (long) curr_idx, (long) init_idx));
/* trailing elisions? */
if (curr_idx > init_idx) {
@@ -66769,10 +72093,7 @@ DUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *re
DUK_DDD(DUK_DDDPRINT("array literal has trailing elisions which affect its length"));
reg_temp = DUK__ALLOCTEMP(comp_ctx);
duk__emit_load_int32(comp_ctx, reg_temp, (duk_int_t) curr_idx);
- duk__emit_a_bc(comp_ctx,
- DUK_OP_SETALEN | DUK__EMIT_FLAG_A_IS_SOURCE,
- reg_obj,
- reg_temp);
+ duk__emit_a_bc(comp_ctx, DUK_OP_SETALEN | DUK__EMIT_FLAG_A_IS_SOURCE, reg_obj, reg_temp);
}
DUK__SETTEMP(comp_ctx, temp_start);
@@ -66780,8 +72101,9 @@ DUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *re
duk__ivalue_regconst(res, reg_obj);
return;
- syntax_error:
+syntax_error:
DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARRAY_LITERAL);
+ DUK_WO_NORETURN(return;);
}
typedef struct {
@@ -66803,9 +72125,7 @@ DUK_LOCAL void duk__objlit_flush_keys(duk_compiler_ctx *comp_ctx, duk__objlit_st
*/
DUK_ASSERT(st->num_pairs > 0);
duk__emit_a_b_c(comp_ctx,
- DUK_OP_MPUTOBJ |
- DUK__EMIT_FLAG_NO_SHUFFLE_C |
- DUK__EMIT_FLAG_A_IS_SOURCE,
+ DUK_OP_MPUTOBJ | DUK__EMIT_FLAG_NO_SHUFFLE_C | DUK__EMIT_FLAG_A_IS_SOURCE,
st->reg_obj,
st->temp_start,
(duk_regconst_t) (st->num_pairs * 2));
@@ -66824,7 +72144,7 @@ DUK_LOCAL duk_bool_t duk__objlit_load_key(duk_compiler_ctx *comp_ctx, duk_ivalue
/* numbers can be loaded as numbers and coerced on the fly */
duk_push_number(comp_ctx->thr, tok->num);
} else {
- return 1; /* error */
+ return 1; /* error */
}
duk__ivalue_plain_fromstack(comp_ctx, res);
@@ -66837,10 +72157,10 @@ DUK_LOCAL duk_bool_t duk__objlit_load_key(duk_compiler_ctx *comp_ctx, duk_ivalue
DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
duk_hthread *thr = comp_ctx->thr;
duk__objlit_state st;
- duk_regconst_t reg_temp; /* temp reg */
- duk_small_uint_t max_init_pairs; /* max # of key-value pairs initialized in one MPUTOBJ set */
- duk_bool_t first; /* first value: comma must not precede the value */
- duk_bool_t is_set, is_get; /* temps */
+ duk_regconst_t reg_temp; /* temp reg */
+ duk_small_uint_t max_init_pairs; /* max # of key-value pairs initialized in one MPUTOBJ set */
+ duk_bool_t first; /* first value: comma must not precede the value */
+ duk_bool_t is_set, is_get; /* temps */
#if !defined(DUK_USE_PREFER_SIZE)
duk_int_t pc_newobj;
duk_compiler_instr *instr;
@@ -66848,12 +72168,12 @@ DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *r
DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LCURLY);
- max_init_pairs = DUK__MAX_OBJECT_INIT_PAIRS; /* XXX: depend on available temps? */
+ max_init_pairs = DUK__MAX_OBJECT_INIT_PAIRS; /* XXX: depend on available temps? */
- st.reg_obj = DUK__ALLOCTEMP(comp_ctx); /* target object */
- st.temp_start = DUK__GETTEMP(comp_ctx); /* start of MPUTOBJ argument list */
- st.num_pairs = 0; /* number of key/value pairs emitted for current MPUTOBJ set */
- st.num_total_pairs = 0; /* number of key/value pairs emitted overall */
+ st.reg_obj = DUK__ALLOCTEMP(comp_ctx); /* target object */
+ st.temp_start = DUK__GETTEMP(comp_ctx); /* start of MPUTOBJ argument list */
+ st.num_pairs = 0; /* number of key/value pairs emitted for current MPUTOBJ set */
+ st.num_total_pairs = 0; /* number of key/value pairs emitted overall */
#if !defined(DUK_USE_PREFER_SIZE)
pc_newobj = duk__get_current_pc(comp_ctx);
@@ -66892,8 +72212,7 @@ DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *r
* worth the effort and would increase code size.
*/
- DUK_DDD(DUK_DDDPRINT("object literal loop, curr_token->t = %ld",
- (long) comp_ctx->curr_token.t));
+ DUK_DDD(DUK_DDDPRINT("object literal loop, curr_token->t = %ld", (long) comp_ctx->curr_token.t));
if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
break;
@@ -66933,16 +72252,15 @@ DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *r
* identifier string content.
*/
- is_get = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
- comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_GET(thr));
- is_set = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
- comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_SET(thr));
+ is_get = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER && comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_GET(thr));
+ is_set = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER && comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_SET(thr));
if ((is_get || is_set) && comp_ctx->curr_token.t != DUK_TOK_COLON) {
/* getter/setter */
duk_int_t fnum;
duk__objlit_flush_keys(comp_ctx, &st);
- DUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start); /* 2 regs are guaranteed to be allocated w.r.t. temp_max */
+ DUK_ASSERT(DUK__GETTEMP(comp_ctx) ==
+ st.temp_start); /* 2 regs are guaranteed to be allocated w.r.t. temp_max */
reg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);
if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->curr_token, reg_temp) != 0) {
@@ -66952,21 +72270,18 @@ DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *r
/* curr_token = get/set name */
fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_GETSET);
- duk__emit_a_bc(comp_ctx,
- DUK_OP_CLOSURE,
- st.temp_start + 1,
- (duk_regconst_t) fnum);
+ duk__emit_a_bc(comp_ctx, DUK_OP_CLOSURE, st.temp_start + 1, (duk_regconst_t) fnum);
/* Slot C is used in a non-standard fashion (range of regs),
* emitter code has special handling for it (must not set the
* "no shuffle" flag).
*/
duk__emit_a_bc(comp_ctx,
- (is_get ? DUK_OP_INITGET : DUK_OP_INITSET) | DUK__EMIT_FLAG_A_IS_SOURCE,
- st.reg_obj,
- st.temp_start); /* temp_start+0 = key, temp_start+1 = closure */
+ (is_get ? DUK_OP_INITGET : DUK_OP_INITSET) | DUK__EMIT_FLAG_A_IS_SOURCE,
+ st.reg_obj,
+ st.temp_start); /* temp_start+0 = key, temp_start+1 = closure */
- DUK_ASSERT(st.num_pairs == 0); /* temp state is reset on next loop */
+ DUK_ASSERT(st.num_pairs == 0); /* temp state is reset on next loop */
#if defined(DUK_USE_ES6)
} else if (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
(comp_ctx->curr_token.t == DUK_TOK_COMMA || comp_ctx->curr_token.t == DUK_TOK_RCURLY)) {
@@ -66974,15 +72289,14 @@ DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *r
load_rc = duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp);
DUK_UNREF(load_rc);
- DUK_ASSERT(load_rc == 0); /* always succeeds because token is identifier */
+ DUK_ASSERT(load_rc == 0); /* always succeeds because token is identifier */
duk__ivalue_var_hstring(comp_ctx, res, comp_ctx->prev_token.str1);
DUK_ASSERT(DUK__GETTEMP(comp_ctx) == reg_temp + 1);
duk__ivalue_toforcedreg(comp_ctx, res, reg_temp + 1);
st.num_pairs++;
- } else if ((comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER ||
- comp_ctx->prev_token.t == DUK_TOK_STRING ||
+ } else if ((comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER || comp_ctx->prev_token.t == DUK_TOK_STRING ||
comp_ctx->prev_token.t == DUK_TOK_NUMBER) &&
comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
duk_int_t fnum;
@@ -67000,13 +72314,10 @@ DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *r
fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_USE_PREVTOKEN | DUK__FUNC_FLAG_METDEF);
- duk__emit_a_bc(comp_ctx,
- DUK_OP_CLOSURE,
- reg_temp + 1,
- (duk_regconst_t) fnum);
+ duk__emit_a_bc(comp_ctx, DUK_OP_CLOSURE, reg_temp + 1, (duk_regconst_t) fnum);
st.num_pairs++;
-#endif /* DUK_USE_ES6 */
+#endif /* DUK_USE_ES6 */
} else {
#if defined(DUK_USE_ES6)
if (comp_ctx->prev_token.t == DUK_TOK_LBRACKET) {
@@ -67023,9 +72334,8 @@ DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *r
* form is not yet supported and causes a
* SyntaxError on the DUK_TOK_COLON check below.
*/
- }
- else
-#endif /* DUK_USE_ES6 */
+ } else
+#endif /* DUK_USE_ES6 */
{
if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {
goto syntax_error;
@@ -67039,7 +72349,7 @@ DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *r
st.num_pairs++;
}
- } /* property loop */
+ } /* property loop */
/* Flush remaining properties. */
duk__objlit_flush_keys(comp_ctx, &st);
@@ -67058,13 +72368,14 @@ DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *r
#endif
DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
- duk__advance(comp_ctx);
+ duk__advance(comp_ctx); /* No RegExp after object literal. */
duk__ivalue_regconst(res, st.reg_obj);
return;
- syntax_error:
+syntax_error:
DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_OBJECT_LITERAL);
+ DUK_WO_NORETURN(return;);
}
/* Parse argument list. Arguments are written to temps starting from
@@ -67078,7 +72389,8 @@ DUK_LOCAL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue
/* Note: expect that caller has already eaten the left paren */
DUK_DDD(DUK_DDDPRINT("start parsing arguments, prev_token.t=%ld, curr_token.t=%ld",
- (long) comp_ctx->prev_token.t, (long) comp_ctx->curr_token.t));
+ (long) comp_ctx->prev_token.t,
+ (long) comp_ctx->curr_token.t));
for (;;) {
if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
@@ -67095,11 +72407,14 @@ DUK_LOCAL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue
* This is not the cleanest possible approach.
*/
- reg_temp = DUK__ALLOCTEMP(comp_ctx); /* bump up "allocated" reg count, just in case */
+ reg_temp = DUK__ALLOCTEMP(comp_ctx); /* bump up "allocated" reg count, just in case */
DUK__SETTEMP(comp_ctx, reg_temp);
/* binding power must be high enough to NOT allow comma expressions directly */
- duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp); /* always allow 'in', coerce to 'tr' just in case */
+ duk__expr_toforcedreg(comp_ctx,
+ res,
+ DUK__BP_COMMA /*rbp_flags*/,
+ reg_temp); /* always allow 'in', coerce to 'tr' just in case */
DUK__SETTEMP(comp_ctx, reg_temp + 1);
nargs++;
@@ -67108,7 +72423,7 @@ DUK_LOCAL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue
}
/* eat the right paren */
- duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
+ duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* RegExp mode does not matter. */
DUK_DDD(DUK_DDDPRINT("end parsing arguments"));
@@ -67117,8 +72432,7 @@ DUK_LOCAL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue
DUK_LOCAL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx) {
/* empty expressions can be detected conveniently with nud/led counts */
- return (comp_ctx->curr_func.nud_count == 0) &&
- (comp_ctx->curr_func.led_count == 0);
+ return (comp_ctx->curr_func.nud_count == 0) && (comp_ctx->curr_func.led_count == 0);
}
DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
@@ -67126,7 +72440,7 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
duk_token *tk;
duk_regconst_t temp_at_entry;
duk_small_uint_t tok;
- duk_uint32_t args; /* temp variable to pass constants and flags to shared code */
+ duk_uint32_t args; /* temp variable to pass constants and flags to shared code */
/*
* ctx->prev_token token to process with duk__expr_nud()
@@ -67144,18 +72458,17 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
res->t = DUK_IVAL_NONE;
DUK_DDD(DUK_DDDPRINT("duk__expr_nud(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
- (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
+ (long) tk->t,
+ (long) comp_ctx->curr_func.allow_in,
+ (long) comp_ctx->curr_func.paren_level));
switch (tok) {
-
- /* PRIMARY EXPRESSIONS */
+ /* PRIMARY EXPRESSIONS */
case DUK_TOK_THIS: {
duk_regconst_t reg_temp;
reg_temp = DUK__ALLOCTEMP(comp_ctx);
- duk__emit_bc(comp_ctx,
- DUK_OP_LDTHIS,
- reg_temp);
+ duk__emit_bc(comp_ctx, DUK_OP_LDTHIS, reg_temp);
duk__ivalue_regconst(res, reg_temp);
return;
}
@@ -67187,15 +72500,13 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
case DUK_TOK_REGEXP: {
#if defined(DUK_USE_REGEXP_SUPPORT)
duk_regconst_t reg_temp;
- duk_regconst_t rc_re_bytecode; /* const */
- duk_regconst_t rc_re_source; /* const */
+ duk_regconst_t rc_re_bytecode; /* const */
+ duk_regconst_t rc_re_source; /* const */
DUK_ASSERT(tk->str1 != NULL);
DUK_ASSERT(tk->str2 != NULL);
- DUK_DDD(DUK_DDDPRINT("emitting regexp op, str1=%!O, str2=%!O",
- (duk_heaphdr *) tk->str1,
- (duk_heaphdr *) tk->str2));
+ DUK_DDD(DUK_DDDPRINT("emitting regexp op, str1=%!O, str2=%!O", (duk_heaphdr *) tk->str1, (duk_heaphdr *) tk->str2));
reg_temp = DUK__ALLOCTEMP(comp_ctx);
duk_push_hstring(thr, tk->str1);
@@ -67218,9 +72529,9 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
duk__ivalue_regconst(res, reg_temp);
return;
-#else /* DUK_USE_REGEXP_SUPPORT */
+#else /* DUK_USE_REGEXP_SUPPORT */
goto syntax_error;
-#endif /* DUK_USE_REGEXP_SUPPORT */
+#endif /* DUK_USE_REGEXP_SUPPORT */
}
case DUK_TOK_LBRACKET: {
DUK_DDD(DUK_DDDPRINT("parsing array literal"));
@@ -67239,15 +72550,15 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
prev_allow_in = comp_ctx->curr_func.allow_in;
comp_ctx->curr_func.allow_in = 1; /* reset 'allow_in' for parenthesized expression */
- duk__expr(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression, terminates at a ')' */
+ duk__expr(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression, terminates at a ')' */
- duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
+ duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* No RegExp after parenthesized expression. */
comp_ctx->curr_func.allow_in = prev_allow_in;
comp_ctx->curr_func.paren_level--;
return;
}
- /* MEMBER/NEW/CALL EXPRESSIONS */
+ /* MEMBER/NEW/CALL EXPRESSIONS */
case DUK_TOK_NEW: {
/*
@@ -67284,16 +72595,14 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
goto syntax_error_newtarget;
}
duk__advance(comp_ctx);
- duk__emit_bc(comp_ctx,
- DUK_OP_NEWTARGET,
- reg_target);
+ duk__emit_bc(comp_ctx, DUK_OP_NEWTARGET, reg_target);
duk__ivalue_regconst(res, reg_target);
return;
}
-#endif /* DUK_USE_ES6 */
+#endif /* DUK_USE_ES6 */
duk__expr_toforcedreg(comp_ctx, res, DUK__BP_CALL /*rbp_flags*/, reg_target /*forced_reg*/);
- duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, reg_target + 1); /* default instance */
+ duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, reg_target + 1); /* default instance */
DUK__SETTEMP(comp_ctx, reg_target + 2);
/* XXX: 'new obj.noSuch()' doesn't use GETPROPC now which
@@ -67304,7 +72613,7 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
/* 'new' MemberExpression Arguments */
DUK_DDD(DUK_DDDPRINT("new expression has argument list"));
duk__advance(comp_ctx);
- nargs = duk__parse_arguments(comp_ctx, res); /* parse args starting from "next temp", reg_target + 1 */
+ nargs = duk__parse_arguments(comp_ctx, res); /* parse args starting from "next temp", reg_target + 1 */
/* right paren eaten */
} else {
/* 'new' MemberExpression */
@@ -67312,10 +72621,7 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
nargs = 0;
}
- duk__emit_a_bc(comp_ctx,
- DUK_OP_CALL0 | DUK_BC_CALL_FLAG_CONSTRUCT,
- nargs /*num_args*/,
- reg_target /*target*/);
+ duk__emit_a_bc(comp_ctx, DUK_OP_CALL0 | DUK_BC_CALL_FLAG_CONSTRUCT, nargs /*num_args*/, reg_target /*target*/);
DUK_DDD(DUK_DDDPRINT("end parsing new expression"));
@@ -67323,7 +72629,7 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
return;
}
- /* FUNCTION EXPRESSIONS */
+ /* FUNCTION EXPRESSIONS */
case DUK_TOK_FUNCTION: {
/* Function expression. Note that any statement beginning with 'function'
@@ -67346,16 +72652,13 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
fnum = duk__parse_func_like_fnum(comp_ctx, 0 /*flags*/);
DUK_DDD(DUK_DDDPRINT("parsed inner function -> fnum %ld", (long) fnum));
- duk__emit_a_bc(comp_ctx,
- DUK_OP_CLOSURE,
- reg_temp /*a*/,
- (duk_regconst_t) fnum /*bc*/);
+ duk__emit_a_bc(comp_ctx, DUK_OP_CLOSURE, reg_temp /*a*/, (duk_regconst_t) fnum /*bc*/);
duk__ivalue_regconst(res, reg_temp);
return;
}
- /* UNARY EXPRESSIONS */
+ /* UNARY EXPRESSIONS */
case DUK_TOK_DELETE: {
/* Delete semantics are a bit tricky. The description in E5 specification
@@ -67363,7 +72666,7 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
* a reference (which is only known at runtime) seemingly at compile time
* (= SyntaxError throwing).
*/
- duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
+ duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
if (res->t == DUK_IVAL_VAR) {
/* not allowed in strict mode, regardless of whether resolves;
* in non-strict mode DELVAR handles both non-resolving and
@@ -67376,6 +72679,7 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
if (comp_ctx->curr_func.is_strict) {
DUK_ERROR_SYNTAX(thr, DUK_STR_CANNOT_DELETE_IDENTIFIER);
+ DUK_WO_NORETURN(return;);
}
DUK__SETTEMP(comp_ctx, temp_at_entry);
@@ -67384,16 +72688,11 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
duk_dup(thr, res->x1.valstack_idx);
if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
/* register bound variables are non-configurable -> always false */
- duk__emit_bc(comp_ctx,
- DUK_OP_LDFALSE,
- reg_temp);
+ duk__emit_bc(comp_ctx, DUK_OP_LDFALSE, reg_temp);
} else {
duk_dup(thr, res->x1.valstack_idx);
rc_varname = duk__getconst(comp_ctx);
- duk__emit_a_bc(comp_ctx,
- DUK_OP_DELVAR,
- reg_temp,
- rc_varname);
+ duk__emit_a_bc(comp_ctx, DUK_OP_DELVAR, reg_temp, rc_varname);
}
duk__ivalue_regconst(res, reg_temp);
} else if (res->t == DUK_IVAL_PROP) {
@@ -67403,13 +72702,11 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
DUK__SETTEMP(comp_ctx, temp_at_entry);
reg_temp = DUK__ALLOCTEMP(comp_ctx);
- reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
- rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
- duk__emit_a_b_c(comp_ctx,
- DUK_OP_DELPROP | DUK__EMIT_FLAG_BC_REGCONST,
- reg_temp,
- reg_obj,
- rc_key);
+ reg_obj =
+ duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
+ rc_key =
+ duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
+ duk__emit_a_b_c(comp_ctx, DUK_OP_DELPROP | DUK__EMIT_FLAG_BC_REGCONST, reg_temp, reg_obj, rc_key);
duk__ivalue_regconst(res, reg_temp);
} else {
@@ -67420,7 +72717,7 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
return;
}
case DUK_TOK_VOID: {
- duk__expr_toplain_ignore(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
+ duk__expr_toplain_ignore(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
duk_push_undefined(thr);
goto plain_value;
}
@@ -67430,7 +72727,7 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
* will never be unresolvable so special handling is only required
* when an identifier is a "slow path" one.
*/
- duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
+ duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
if (res->t == DUK_IVAL_VAR) {
duk_regconst_t reg_varbind;
@@ -67442,10 +72739,7 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
DUK_DDD(DUK_DDDPRINT("typeof for an identifier name which could not be resolved "
"at compile time, need to use special run-time handling"));
reg_temp = DUK__ALLOCTEMP(comp_ctx);
- duk__emit_a_bc(comp_ctx,
- DUK_OP_TYPEOFID,
- reg_temp,
- rc_varname);
+ duk__emit_a_bc(comp_ctx, DUK_OP_TYPEOFID, reg_temp, rc_varname);
duk__ivalue_regconst(res, reg_temp);
return;
}
@@ -67464,9 +72758,8 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
}
case DUK_TOK_ADD: {
/* unary plus */
- duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
- if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
- duk_is_number(thr, res->x1.valstack_idx)) {
+ duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
+ if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE && duk_is_number(thr, res->x1.valstack_idx)) {
/* unary plus of a number is identity */
return;
}
@@ -67475,9 +72768,8 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
}
case DUK_TOK_SUB: {
/* unary minus */
- duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
- if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
- duk_is_number(thr, res->x1.valstack_idx)) {
+ duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
+ if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE && duk_is_number(thr, res->x1.valstack_idx)) {
/* this optimization is important to handle negative literals
* (which are not directly provided by the lexical grammar)
*/
@@ -67497,12 +72789,12 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
goto unary;
}
case DUK_TOK_BNOT: {
- duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
+ duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
args = DUK_OP_BNOT;
goto unary;
}
case DUK_TOK_LNOT: {
- duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
+ duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE) {
/* Very minimal inlining to handle common idioms '!0' and '!1',
* and also boolean arguments like '!false' and '!true'.
@@ -67514,12 +72806,12 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
if (DUK_TVAL_IS_NUMBER(tv_val)) {
duk_double_t d;
d = DUK_TVAL_GET_NUMBER(tv_val);
- if (d == 0.0) {
+ if (duk_double_equals(d, 0.0)) {
/* Matches both +0 and -0 on purpose. */
DUK_DDD(DUK_DDDPRINT("inlined lnot: !0 -> true"));
DUK_TVAL_SET_BOOLEAN_TRUE(tv_val);
return;
- } else if (d == 1.0) {
+ } else if (duk_double_equals(d, 1.0)) {
DUK_DDD(DUK_DDDPRINT("inlined lnot: !1 -> false"));
DUK_TVAL_SET_BOOLEAN_FALSE(tv_val);
return;
@@ -67537,117 +72829,112 @@ DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
goto unary;
}
- } /* end switch */
+ } /* end switch */
DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
- return;
+ DUK_WO_NORETURN(return;);
- unary:
- {
- /* Unary opcodes use just the 'BC' register source because it
- * matches current shuffle limits, and maps cleanly to 16 high
- * bits of the opcode.
- */
+unary : {
+ /* Unary opcodes use just the 'BC' register source because it
+ * matches current shuffle limits, and maps cleanly to 16 high
+ * bits of the opcode.
+ */
- duk_regconst_t reg_src, reg_res;
+ duk_regconst_t reg_src, reg_res;
- reg_src = duk__ivalue_toregconst_raw(comp_ctx, res, -1 /*forced_reg*/, 0 /*flags*/);
- if (DUK__ISREG_TEMP(comp_ctx, reg_src)) {
- reg_res = reg_src;
- } else {
- reg_res = DUK__ALLOCTEMP(comp_ctx);
- }
- duk__emit_a_bc(comp_ctx,
- args,
- reg_res,
- reg_src);
- duk__ivalue_regconst(res, reg_res);
- return;
+ reg_src = duk__ivalue_toregconst_raw(comp_ctx, res, -1 /*forced_reg*/, 0 /*flags*/);
+ if (DUK__ISREG_TEMP(comp_ctx, reg_src)) {
+ reg_res = reg_src;
+ } else {
+ reg_res = DUK__ALLOCTEMP(comp_ctx);
}
+ duk__emit_a_bc(comp_ctx, args, reg_res, reg_src);
+ duk__ivalue_regconst(res, reg_res);
+ return;
+}
- preincdec:
- {
- /* preincrement and predecrement */
- duk_regconst_t reg_res;
- duk_small_uint_t args_op1 = args & 0xff; /* DUK_OP_PREINCR/DUK_OP_PREDECR */
- duk_small_uint_t args_op2 = args >> 8; /* DUK_OP_PREINCP_RR/DUK_OP_PREDECP_RR */
+preincdec : {
+ /* preincrement and predecrement */
+ duk_regconst_t reg_res;
+ duk_small_uint_t args_op1 = args & 0xff; /* DUK_OP_PREINCR/DUK_OP_PREDECR */
+ duk_small_uint_t args_op2 = args >> 8; /* DUK_OP_PREINCP_RR/DUK_OP_PREDECP_RR */
- /* Specific assumptions for opcode numbering. */
- DUK_ASSERT(DUK_OP_PREINCR + 4 == DUK_OP_PREINCV);
- DUK_ASSERT(DUK_OP_PREDECR + 4 == DUK_OP_PREDECV);
+ /* Specific assumptions for opcode numbering. */
+ DUK_ASSERT(DUK_OP_PREINCR + 4 == DUK_OP_PREINCV);
+ DUK_ASSERT(DUK_OP_PREDECR + 4 == DUK_OP_PREDECV);
- reg_res = DUK__ALLOCTEMP(comp_ctx);
+ reg_res = DUK__ALLOCTEMP(comp_ctx);
- duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
- if (res->t == DUK_IVAL_VAR) {
- duk_hstring *h_varname;
- duk_regconst_t reg_varbind;
- duk_regconst_t rc_varname;
-
- h_varname = duk_known_hstring(thr, res->x1.valstack_idx);
+ duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
+ if (res->t == DUK_IVAL_VAR) {
+ duk_hstring *h_varname;
+ duk_regconst_t reg_varbind;
+ duk_regconst_t rc_varname;
- if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
- goto syntax_error;
- }
+ h_varname = duk_known_hstring(thr, res->x1.valstack_idx);
- duk_dup(thr, res->x1.valstack_idx);
- if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
- duk__emit_a_bc(comp_ctx,
- args_op1, /* e.g. DUK_OP_PREINCR */
- reg_res,
- reg_varbind);
- } else {
- duk__emit_a_bc(comp_ctx,
- args_op1 + 4, /* e.g. DUK_OP_PREINCV */
- reg_res,
- rc_varname);
- }
+ if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
+ goto syntax_error;
+ }
- DUK_DDD(DUK_DDDPRINT("preincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
- (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
- } else if (res->t == DUK_IVAL_PROP) {
- duk_regconst_t reg_obj; /* allocate to reg only (not const) */
- duk_regconst_t rc_key;
- reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
- rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
- duk__emit_a_b_c(comp_ctx,
- args_op2 | DUK__EMIT_FLAG_BC_REGCONST, /* e.g. DUK_OP_PREINCP */
- reg_res,
- reg_obj,
- rc_key);
+ duk_dup(thr, res->x1.valstack_idx);
+ if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
+ duk__emit_a_bc(comp_ctx,
+ args_op1, /* e.g. DUK_OP_PREINCR */
+ reg_res,
+ reg_varbind);
} else {
- /* Technically return value is not needed because INVLHS will
- * unconditially throw a ReferenceError. Coercion is necessary
- * for proper semantics (consider ToNumber() called for an object).
- * Use DUK_OP_UNP with a dummy register to get ToNumber().
- */
-
- duk__ivalue_toforcedreg(comp_ctx, res, reg_res);
- duk__emit_bc(comp_ctx,
- DUK_OP_UNP,
- reg_res); /* for side effects, result ignored */
- duk__emit_op_only(comp_ctx,
- DUK_OP_INVLHS);
+ duk__emit_a_bc(comp_ctx,
+ args_op1 + 4, /* e.g. DUK_OP_PREINCV */
+ reg_res,
+ rc_varname);
}
- DUK__SETTEMP(comp_ctx, reg_res + 1);
- duk__ivalue_regconst(res, reg_res);
- return;
- }
- plain_value:
- {
- /* Stack top contains plain value */
- duk__ivalue_plain_fromstack(comp_ctx, res);
- return;
+ DUK_DDD(DUK_DDDPRINT("preincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
+ (duk_heaphdr *) h_varname,
+ (long) reg_varbind,
+ (long) rc_varname));
+ } else if (res->t == DUK_IVAL_PROP) {
+ duk_regconst_t reg_obj; /* allocate to reg only (not const) */
+ duk_regconst_t rc_key;
+ reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
+ rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
+ duk__emit_a_b_c(comp_ctx,
+ args_op2 | DUK__EMIT_FLAG_BC_REGCONST, /* e.g. DUK_OP_PREINCP */
+ reg_res,
+ reg_obj,
+ rc_key);
+ } else {
+ /* Technically return value is not needed because INVLHS will
+ * unconditially throw a ReferenceError. Coercion is necessary
+ * for proper semantics (consider ToNumber() called for an object).
+ * Use DUK_OP_UNP with a dummy register to get ToNumber().
+ */
+
+ duk__ivalue_toforcedreg(comp_ctx, res, reg_res);
+ duk__emit_bc(comp_ctx, DUK_OP_UNP, reg_res); /* for side effects, result ignored */
+ duk__emit_op_only(comp_ctx, DUK_OP_INVLHS);
}
+ DUK__SETTEMP(comp_ctx, reg_res + 1);
+ duk__ivalue_regconst(res, reg_res);
+ return;
+}
+
+plain_value : {
+ /* Stack top contains plain value */
+ duk__ivalue_plain_fromstack(comp_ctx, res);
+ return;
+}
#if defined(DUK_USE_ES6)
- syntax_error_newtarget:
+syntax_error_newtarget:
DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_NEWTARGET);
+ DUK_WO_NORETURN(return;);
#endif
- syntax_error:
+syntax_error:
DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
+ DUK_WO_NORETURN(return;);
}
/* XXX: add flag to indicate whether caller cares about return value; this
@@ -67658,7 +72945,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
duk_hthread *thr = comp_ctx->thr;
duk_token *tk;
duk_small_uint_t tok;
- duk_uint32_t args; /* temp variable to pass constants and flags to shared code */
+ duk_uint32_t args; /* temp variable to pass constants and flags to shared code */
/*
* ctx->prev_token token to process with duk__expr_led()
@@ -67672,13 +72959,14 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
tok = tk->t;
DUK_DDD(DUK_DDDPRINT("duk__expr_led(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
- (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
+ (long) tk->t,
+ (long) comp_ctx->curr_func.allow_in,
+ (long) comp_ctx->curr_func.paren_level));
/* XXX: default priority for infix operators is duk__expr_lbp(tok) -> get it here? */
switch (tok) {
-
- /* PRIMARY EXPRESSIONS */
+ /* PRIMARY EXPRESSIONS */
case DUK_TOK_PERIOD: {
/* Property access expressions are critical for correct LHS ordering,
@@ -67702,10 +72990,11 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
/* NB: must accept reserved words as property name */
if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER) {
DUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER);
+ DUK_WO_NORETURN(return;);
}
res->t = DUK_IVAL_PROP;
- duk__copy_ispec(comp_ctx, &left->x1, &res->x1); /* left.x1 -> res.x1 */
+ duk__copy_ispec(comp_ctx, &left->x1, &res->x1); /* left.x1 -> res.x1 */
DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
duk_push_hstring(thr, comp_ctx->curr_token.str1);
duk_replace(thr, res->x2.valstack_idx);
@@ -67740,12 +73029,12 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
* See: test-bug-nested-prop-mutate.js.
*/
duk__ivalue_totempconst(comp_ctx, left);
- duk__expr_toplain(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression, ']' terminates */
+ duk__expr_toplain(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression, ']' terminates */
duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);
res->t = DUK_IVAL_PROP;
- duk__copy_ispec(comp_ctx, &res->x1, &res->x2); /* res.x1 -> res.x2 */
- duk__copy_ispec(comp_ctx, &left->x1, &res->x1); /* left.x1 -> res.x1 */
+ duk__copy_ispec(comp_ctx, &res->x1, &res->x2); /* res.x1 -> res.x2 */
+ duk__copy_ispec(comp_ctx, &left->x1, &res->x1); /* left.x1 -> res.x1 */
return;
}
case DUK_TOK_LPAREN: {
@@ -67789,19 +73078,13 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
duk_dup(thr, left->x1.valstack_idx);
if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
- duk__emit_a_bc(comp_ctx,
- DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE,
- reg_varbind,
- reg_cs + 0);
+ duk__emit_a_bc(comp_ctx, DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE, reg_varbind, reg_cs + 0);
} else {
/* XXX: expand target register or constant field to
* reduce shuffling.
*/
DUK_ASSERT(DUK__ISCONST(rc_varname));
- duk__emit_a_b(comp_ctx,
- DUK_OP_CSVAR | DUK__EMIT_FLAG_BC_REGCONST,
- reg_cs + 0,
- rc_varname);
+ duk__emit_a_b(comp_ctx, DUK_OP_CSVAR | DUK__EMIT_FLAG_BC_REGCONST, reg_cs + 0, rc_varname);
}
} else if (left->t == DUK_IVAL_PROP) {
/* Call through a property lookup, E5 Section 11.2.3, step 6.a.i,
@@ -67823,16 +73106,12 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
* and reuse, but it would still be in the wrong position
* (reg_cs + 0 rather than reg_cs + 1).
*/
- duk__ispec_toforcedreg(comp_ctx, &left->x1, reg_cs + 1); /* base */
+ duk__ispec_toforcedreg(comp_ctx, &left->x1, reg_cs + 1); /* base */
#if defined(DUK_USE_VERBOSE_ERRORS)
reg_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
- duk__emit_a_b_c(comp_ctx,
- DUK_OP_GETPROPC | DUK__EMIT_FLAG_BC_REGCONST,
- reg_cs + 0,
- reg_cs + 1,
- reg_key);
+ duk__emit_a_b_c(comp_ctx, DUK_OP_GETPROPC | DUK__EMIT_FLAG_BC_REGCONST, reg_cs + 0, reg_cs + 1, reg_key);
#else
- duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0); /* base[key] */
+ duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0); /* base[key] */
#endif
} else {
DUK_DDD(DUK_DDDPRINT("function call with register base"));
@@ -67851,23 +73130,20 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
}
DUK__SETTEMP(comp_ctx, reg_cs + 2);
- nargs = duk__parse_arguments(comp_ctx, res); /* parse args starting from "next temp" */
+ nargs = duk__parse_arguments(comp_ctx, res); /* parse args starting from "next temp" */
/* Tailcalls are handled by back-patching the already emitted opcode
* later in return statement parser.
*/
- duk__emit_a_bc(comp_ctx,
- call_op,
- (duk_regconst_t) nargs /*numargs*/,
- reg_cs /*basereg*/);
- DUK__SETTEMP(comp_ctx, reg_cs + 1); /* result in csreg */
+ duk__emit_a_bc(comp_ctx, call_op, (duk_regconst_t) nargs /*numargs*/, reg_cs /*basereg*/);
+ DUK__SETTEMP(comp_ctx, reg_cs + 1); /* result in csreg */
duk__ivalue_regconst(res, reg_cs);
return;
}
- /* POSTFIX EXPRESSION */
+ /* POSTFIX EXPRESSION */
case DUK_TOK_INCREMENT: {
args = (DUK_OP_POSTINCP_RR << 16) + (DUK_OP_POSTINCR << 8) + 0;
@@ -67882,38 +73158,38 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
#if defined(DUK_USE_ES7_EXP_OPERATOR)
case DUK_TOK_EXP: {
- args = (DUK_OP_EXP << 8) + DUK__BP_EXPONENTIATION - 1; /* UnaryExpression */
+ args = (DUK_OP_EXP << 8) + DUK__BP_EXPONENTIATION - 1; /* UnaryExpression */
goto binary;
}
#endif
- /* MULTIPLICATIVE EXPRESSION */
+ /* MULTIPLICATIVE EXPRESSION */
case DUK_TOK_MUL: {
- args = (DUK_OP_MUL << 8) + DUK__BP_MULTIPLICATIVE; /* ExponentiationExpression */
+ args = (DUK_OP_MUL << 8) + DUK__BP_MULTIPLICATIVE; /* ExponentiationExpression */
goto binary;
}
case DUK_TOK_DIV: {
- args = (DUK_OP_DIV << 8) + DUK__BP_MULTIPLICATIVE; /* ExponentiationExpression */
+ args = (DUK_OP_DIV << 8) + DUK__BP_MULTIPLICATIVE; /* ExponentiationExpression */
goto binary;
}
case DUK_TOK_MOD: {
- args = (DUK_OP_MOD << 8) + DUK__BP_MULTIPLICATIVE; /* ExponentiationExpression */
+ args = (DUK_OP_MOD << 8) + DUK__BP_MULTIPLICATIVE; /* ExponentiationExpression */
goto binary;
}
- /* ADDITIVE EXPRESSION */
+ /* ADDITIVE EXPRESSION */
case DUK_TOK_ADD: {
- args = (DUK_OP_ADD << 8) + DUK__BP_ADDITIVE; /* MultiplicativeExpression */
+ args = (DUK_OP_ADD << 8) + DUK__BP_ADDITIVE; /* MultiplicativeExpression */
goto binary;
}
case DUK_TOK_SUB: {
- args = (DUK_OP_SUB << 8) + DUK__BP_ADDITIVE; /* MultiplicativeExpression */
+ args = (DUK_OP_SUB << 8) + DUK__BP_ADDITIVE; /* MultiplicativeExpression */
goto binary;
}
- /* SHIFT EXPRESSION */
+ /* SHIFT EXPRESSION */
case DUK_TOK_ALSHIFT: {
/* << */
@@ -67931,7 +73207,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
goto binary;
}
- /* RELATIONAL EXPRESSION */
+ /* RELATIONAL EXPRESSION */
case DUK_TOK_LT: {
/* < */
@@ -67959,7 +73235,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
goto binary;
}
- /* EQUALITY EXPRESSION */
+ /* EQUALITY EXPRESSION */
case DUK_TOK_EQ: {
args = (DUK_OP_EQ << 8) + DUK__BP_EQUALITY;
@@ -67978,7 +73254,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
goto binary;
}
- /* BITWISE EXPRESSIONS */
+ /* BITWISE EXPRESSIONS */
case DUK_TOK_BAND: {
args = (DUK_OP_BAND << 8) + DUK__BP_BAND;
@@ -67993,7 +73269,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
goto binary;
}
- /* LOGICAL EXPRESSIONS */
+ /* LOGICAL EXPRESSIONS */
case DUK_TOK_LAND: {
/* syntactically left-associative but parsed as right-associative */
@@ -68006,7 +73282,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
goto binary_logical;
}
- /* CONDITIONAL EXPRESSION */
+ /* CONDITIONAL EXPRESSION */
case DUK_TOK_QUESTION: {
/* XXX: common reg allocation need is to reuse a sub-expression's temp reg,
@@ -68019,12 +73295,18 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
reg_temp = DUK__ALLOCTEMP(comp_ctx);
duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
duk__emit_if_true_skip(comp_ctx, reg_temp);
- pc_jump1 = duk__emit_jump_empty(comp_ctx); /* jump to false */
- duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/); /* AssignmentExpression */
+ pc_jump1 = duk__emit_jump_empty(comp_ctx); /* jump to false */
+ duk__expr_toforcedreg(comp_ctx,
+ res,
+ DUK__BP_COMMA /*rbp_flags*/,
+ reg_temp /*forced_reg*/); /* AssignmentExpression */
duk__advance_expect(comp_ctx, DUK_TOK_COLON);
- pc_jump2 = duk__emit_jump_empty(comp_ctx); /* jump to end */
+ pc_jump2 = duk__emit_jump_empty(comp_ctx); /* jump to end */
duk__patch_jump_here(comp_ctx, pc_jump1);
- duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/); /* AssignmentExpression */
+ duk__expr_toforcedreg(comp_ctx,
+ res,
+ DUK__BP_COMMA /*rbp_flags*/,
+ reg_temp /*forced_reg*/); /* AssignmentExpression */
duk__patch_jump_here(comp_ctx, pc_jump2);
DUK__SETTEMP(comp_ctx, reg_temp + 1);
@@ -68032,7 +73314,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
return;
}
- /* ASSIGNMENT EXPRESSION */
+ /* ASSIGNMENT EXPRESSION */
case DUK_TOK_EQUALSIGN: {
/*
@@ -68046,7 +73328,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
*
* XXX: just use DUK__BP_COMMA (i.e. no need for 2-step bp levels)?
*/
- args = (DUK_OP_NONE << 8) + DUK__BP_ASSIGNMENT - 1; /* DUK_OP_NONE marks a 'plain' assignment */
+ args = (DUK_OP_NONE << 8) + DUK__BP_ASSIGNMENT - 1; /* DUK_OP_NONE marks a 'plain' assignment */
goto assign;
}
case DUK_TOK_ADD_EQ: {
@@ -68112,12 +73394,12 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
goto assign;
}
- /* COMMA */
+ /* COMMA */
case DUK_TOK_COMMA: {
/* right associative */
- duk__ivalue_toplain_ignore(comp_ctx, left); /* need side effects, not value */
+ duk__ivalue_toplain_ignore(comp_ctx, left); /* need side effects, not value */
duk__expr_toplain(comp_ctx, res, DUK__BP_COMMA - 1 /*rbp_flags*/);
/* return 'res' (of right part) as our result */
@@ -68131,7 +73413,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
DUK_D(DUK_DPRINT("parse error: unexpected token: %ld", (long) tok));
DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
- return;
+ DUK_WO_NORETURN(return;);
#if 0
/* XXX: shared handling for 'duk__expr_lhs'? */
@@ -68140,7 +73422,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
}
#endif
- binary:
+binary:
/*
* Shared handling of binary operations
*
@@ -68166,11 +73448,15 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
duk_copy(thr, left->x1.valstack_idx, res->x1.valstack_idx);
DUK_DDD(DUK_DDDPRINT("binary op, res: t=%ld, x1.t=%ld, x1.regconst=0x%08lx, x2.t=%ld, x2.regconst=0x%08lx",
- (long) res->t, (long) res->x1.t, (unsigned long) res->x1.regconst, (long) res->x2.t, (unsigned long) res->x2.regconst));
+ (long) res->t,
+ (long) res->x1.t,
+ (unsigned long) res->x1.regconst,
+ (long) res->x2.t,
+ (unsigned long) res->x2.regconst));
return;
}
- binary_logical:
+binary_logical:
/*
* Shared handling for logical AND and logical OR.
*
@@ -68203,8 +73489,8 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
DUK_ASSERT(DUK__ISREG(reg_temp));
duk__emit_bc(comp_ctx,
- (args_truthval ? DUK_OP_IFTRUE_R : DUK_OP_IFFALSE_R),
- reg_temp); /* skip jump conditionally */
+ (args_truthval ? DUK_OP_IFTRUE_R : DUK_OP_IFFALSE_R),
+ reg_temp); /* skip jump conditionally */
pc_jump = duk__emit_jump_empty(comp_ctx);
duk__expr_toforcedreg(comp_ctx, res, args_rbp /*rbp_flags*/, reg_temp /*forced_reg*/);
duk__patch_jump_here(comp_ctx, pc_jump);
@@ -68213,7 +73499,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
return;
}
- assign:
+assign:
/*
* Shared assignment expression handling
*
@@ -68266,7 +73552,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
* is relevant for e.g. eval code.
*/
toplevel_assign = (comp_ctx->curr_func.nud_count == 1 && /* one token before */
- comp_ctx->curr_func.led_count == 1); /* one operator (= assign) */
+ comp_ctx->curr_func.led_count == 1); /* one operator (= assign) */
DUK_DDD(DUK_DDDPRINT("assignment: nud_count=%ld, led_count=%ld, toplevel_assign=%ld",
(long) comp_ctx->curr_func.nud_count,
(long) comp_ctx->curr_func.led_count,
@@ -68277,7 +73563,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
duk_regconst_t reg_varbind;
duk_regconst_t rc_varname;
- DUK_ASSERT(left->x1.t == DUK_ISPEC_VALUE); /* LHS is already side effect free */
+ DUK_ASSERT(left->x1.t == DUK_ISPEC_VALUE); /* LHS is already side effect free */
h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
@@ -68294,9 +73580,10 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
DUK_DDD(DUK_DDDPRINT("plain assignment, toplevel assign, use as is"));
} else {
/* 'res' must be a plain ivalue, and not register-bound variable. */
- DUK_DDD(DUK_DDDPRINT("plain assignment, not toplevel assign, ensure not a reg-bound identifier"));
- if (res->t != DUK_IVAL_PLAIN || (res->x1.t == DUK_ISPEC_REGCONST &&
- DUK__ISREG_NOTTEMP(comp_ctx, res->x1.regconst))) {
+ DUK_DDD(DUK_DDDPRINT(
+ "plain assignment, not toplevel assign, ensure not a reg-bound identifier"));
+ if (res->t != DUK_IVAL_PLAIN ||
+ (res->x1.t == DUK_ISPEC_REGCONST && DUK__ISREG_NOTTEMP(comp_ctx, res->x1.regconst))) {
duk__ivalue_totempconst(comp_ctx, res);
}
}
@@ -68329,7 +73616,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
* value, so go through a temp.
*/
DUK_DD(DUK_DDPRINT("<op>= expression is not top level, write to reg_temp"));
- reg_res = reg_temp; /* reg_res should be smallest possible */
+ reg_res = reg_temp; /* reg_res should be smallest possible */
reg_temp = DUK__ALLOCTEMP(comp_ctx);
}
@@ -68341,10 +73628,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
*/
pc_temp_load = duk__get_current_pc(comp_ctx);
- duk__emit_a_bc(comp_ctx,
- DUK_OP_LDREG,
- reg_temp,
- reg_varbind);
+ duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, reg_temp, reg_varbind);
pc_before_rhs = duk__get_current_pc(comp_ctx);
duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
@@ -68352,7 +73636,8 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
pc_after_rhs = duk__get_current_pc(comp_ctx);
DUK_DD(DUK_DDPRINT("pc_temp_load=%ld, pc_before_rhs=%ld, pc_after_rhs=%ld",
- (long) pc_temp_load, (long) pc_before_rhs,
+ (long) pc_temp_load,
+ (long) pc_before_rhs,
(long) pc_after_rhs));
if (pc_after_rhs == pc_before_rhs) {
@@ -68360,11 +73645,16 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
* instructions, we may need to rewind more than
* one instruction, so use explicit PC computation.
*/
- DUK_DD(DUK_DDPRINT("rhs is side effect free, rewind and avoid unnecessary temp for reg-based <op>="));
- DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, (duk_size_t) (pc_temp_load - pc_before_rhs) * sizeof(duk_compiler_instr));
+ DUK_DD(DUK_DDPRINT("rhs is side effect free, rewind and avoid unnecessary temp for "
+ "reg-based <op>="));
+ DUK_BW_ADD_PTR(comp_ctx->thr,
+ &comp_ctx->curr_func.bw_code,
+ (pc_temp_load - pc_before_rhs) *
+ (duk_int_t) sizeof(duk_compiler_instr));
reg_src = reg_varbind;
} else {
- DUK_DD(DUK_DDPRINT("rhs evaluation emitted code, not sure if rhs is side effect free; use temp reg for LHS"));
+ DUK_DD(DUK_DDPRINT("rhs evaluation emitted code, not sure if rhs is side effect "
+ "free; use temp reg for LHS"));
reg_src = reg_temp;
}
@@ -68385,10 +73675,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
* temporary. No optimization for top level assignment.
*/
- duk__emit_a_bc(comp_ctx,
- DUK_OP_GETVAR,
- reg_temp,
- rc_varname);
+ duk__emit_a_bc(comp_ctx, DUK_OP_GETVAR, reg_temp, rc_varname);
duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
@@ -68421,7 +73708,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
duk__ivalue_toforcedreg(comp_ctx, res, (duk_int_t) reg_varbind);
} else {
duk__ivalue_totempconst(comp_ctx, res);
- duk__copy_ivalue(comp_ctx, res, left); /* use 'left' as a temp */
+ duk__copy_ivalue(comp_ctx, res, left); /* use 'left' as a temp */
duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
}
} else {
@@ -68429,7 +73716,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
* free and may be a plain value, a register, or a
* constant) and write it to the LHS binding too.
*/
- duk__copy_ivalue(comp_ctx, res, left); /* use 'left' as a temp */
+ duk__copy_ivalue(comp_ctx, res, left); /* use 'left' as a temp */
duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
}
} else {
@@ -68442,10 +73729,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
*/
duk__ivalue_toreg(comp_ctx, res);
- duk__emit_a_bc(comp_ctx,
- DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
- res->x1.regconst,
- rc_varname);
+ duk__emit_a_bc(comp_ctx, DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE, res->x1.regconst, rc_varname);
}
/* 'res' contains expression value */
@@ -68485,11 +73769,7 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
rc_res = res->x1.regconst;
} else {
reg_temp = DUK__ALLOCTEMP(comp_ctx);
- duk__emit_a_b_c(comp_ctx,
- DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST,
- reg_temp,
- reg_obj,
- rc_key);
+ duk__emit_a_b_c(comp_ctx, DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST, reg_temp, reg_obj, rc_key);
duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
@@ -68540,98 +73820,96 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
return;
}
- postincdec:
- {
- /*
- * Post-increment/decrement will return the original value as its
- * result value. However, even that value will be coerced using
- * ToNumber() which is quite awkward. Specific bytecode opcodes
- * are used to handle these semantics.
- *
- * Note that post increment/decrement has a "no LineTerminator here"
- * restriction. This is handled by duk__expr_lbp(), which forcibly terminates
- * the previous expression if a LineTerminator occurs before '++'/'--'.
- */
-
- duk_regconst_t reg_res;
- duk_small_uint_t args_op1 = (args >> 8) & 0xff; /* DUK_OP_POSTINCR/DUK_OP_POSTDECR */
- duk_small_uint_t args_op2 = args >> 16; /* DUK_OP_POSTINCP_RR/DUK_OP_POSTDECP_RR */
-
- /* Specific assumptions for opcode numbering. */
- DUK_ASSERT(DUK_OP_POSTINCR + 4 == DUK_OP_POSTINCV);
- DUK_ASSERT(DUK_OP_POSTDECR + 4 == DUK_OP_POSTDECV);
+postincdec : {
+ /*
+ * Post-increment/decrement will return the original value as its
+ * result value. However, even that value will be coerced using
+ * ToNumber() which is quite awkward. Specific bytecode opcodes
+ * are used to handle these semantics.
+ *
+ * Note that post increment/decrement has a "no LineTerminator here"
+ * restriction. This is handled by duk__expr_lbp(), which forcibly terminates
+ * the previous expression if a LineTerminator occurs before '++'/'--'.
+ */
- reg_res = DUK__ALLOCTEMP(comp_ctx);
+ duk_regconst_t reg_res;
+ duk_small_uint_t args_op1 = (args >> 8) & 0xff; /* DUK_OP_POSTINCR/DUK_OP_POSTDECR */
+ duk_small_uint_t args_op2 = args >> 16; /* DUK_OP_POSTINCP_RR/DUK_OP_POSTDECP_RR */
- if (left->t == DUK_IVAL_VAR) {
- duk_hstring *h_varname;
- duk_regconst_t reg_varbind;
- duk_regconst_t rc_varname;
+ /* Specific assumptions for opcode numbering. */
+ DUK_ASSERT(DUK_OP_POSTINCR + 4 == DUK_OP_POSTINCV);
+ DUK_ASSERT(DUK_OP_POSTDECR + 4 == DUK_OP_POSTDECV);
- h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
+ reg_res = DUK__ALLOCTEMP(comp_ctx);
- if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
- goto syntax_error;
- }
+ if (left->t == DUK_IVAL_VAR) {
+ duk_hstring *h_varname;
+ duk_regconst_t reg_varbind;
+ duk_regconst_t rc_varname;
- duk_dup(thr, left->x1.valstack_idx);
- if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
- duk__emit_a_bc(comp_ctx,
- args_op1, /* e.g. DUK_OP_POSTINCR */
- reg_res,
- reg_varbind);
- } else {
- duk__emit_a_bc(comp_ctx,
- args_op1 + 4, /* e.g. DUK_OP_POSTINCV */
- reg_res,
- rc_varname);
- }
+ h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
- DUK_DDD(DUK_DDDPRINT("postincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
- (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
- } else if (left->t == DUK_IVAL_PROP) {
- duk_regconst_t reg_obj; /* allocate to reg only (not const) */
- duk_regconst_t rc_key;
+ if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
+ goto syntax_error;
+ }
- reg_obj = duk__ispec_toregconst_raw(comp_ctx, &left->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
- rc_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
- duk__emit_a_b_c(comp_ctx,
- args_op2 | DUK__EMIT_FLAG_BC_REGCONST, /* e.g. DUK_OP_POSTINCP */
- reg_res,
- reg_obj,
- rc_key);
+ duk_dup(thr, left->x1.valstack_idx);
+ if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
+ duk__emit_a_bc(comp_ctx,
+ args_op1, /* e.g. DUK_OP_POSTINCR */
+ reg_res,
+ reg_varbind);
} else {
- /* Technically return value is not needed because INVLHS will
- * unconditially throw a ReferenceError. Coercion is necessary
- * for proper semantics (consider ToNumber() called for an object).
- * Use DUK_OP_UNP with a dummy register to get ToNumber().
- */
- duk__ivalue_toforcedreg(comp_ctx, left, reg_res);
- duk__emit_bc(comp_ctx,
- DUK_OP_UNP,
- reg_res); /* for side effects, result ignored */
- duk__emit_op_only(comp_ctx,
- DUK_OP_INVLHS);
+ duk__emit_a_bc(comp_ctx,
+ args_op1 + 4, /* e.g. DUK_OP_POSTINCV */
+ reg_res,
+ rc_varname);
}
- DUK__SETTEMP(comp_ctx, reg_res + 1);
- duk__ivalue_regconst(res, reg_res);
- return;
+ DUK_DDD(DUK_DDDPRINT("postincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
+ (duk_heaphdr *) h_varname,
+ (long) reg_varbind,
+ (long) rc_varname));
+ } else if (left->t == DUK_IVAL_PROP) {
+ duk_regconst_t reg_obj; /* allocate to reg only (not const) */
+ duk_regconst_t rc_key;
+
+ reg_obj = duk__ispec_toregconst_raw(comp_ctx, &left->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
+ rc_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
+ duk__emit_a_b_c(comp_ctx,
+ args_op2 | DUK__EMIT_FLAG_BC_REGCONST, /* e.g. DUK_OP_POSTINCP */
+ reg_res,
+ reg_obj,
+ rc_key);
+ } else {
+ /* Technically return value is not needed because INVLHS will
+ * unconditially throw a ReferenceError. Coercion is necessary
+ * for proper semantics (consider ToNumber() called for an object).
+ * Use DUK_OP_UNP with a dummy register to get ToNumber().
+ */
+ duk__ivalue_toforcedreg(comp_ctx, left, reg_res);
+ duk__emit_bc(comp_ctx, DUK_OP_UNP, reg_res); /* for side effects, result ignored */
+ duk__emit_op_only(comp_ctx, DUK_OP_INVLHS);
}
- syntax_error:
- DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
+ DUK__SETTEMP(comp_ctx, reg_res + 1);
+ duk__ivalue_regconst(res, reg_res);
return;
+}
- syntax_error_lvalue:
+syntax_error:
+ DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
+ DUK_WO_NORETURN(return;);
+
+syntax_error_lvalue:
DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LVALUE);
- return;
+ DUK_WO_NORETURN(return;);
}
DUK_LOCAL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx) {
duk_small_uint_t tok = comp_ctx->curr_token.t;
- DUK_ASSERT_DISABLE(tok >= DUK_TOK_MINVAL); /* unsigned */
+ DUK_ASSERT_DISABLE(tok >= DUK_TOK_MINVAL); /* unsigned */
DUK_ASSERT(tok <= DUK_TOK_MAXVAL);
DUK_ASSERT(sizeof(duk__token_lbp) == DUK_TOK_MAXVAL + 1);
@@ -68644,8 +73922,7 @@ DUK_LOCAL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx) {
return 0;
}
- if ((tok == DUK_TOK_DECREMENT || tok == DUK_TOK_INCREMENT) &&
- (comp_ctx->curr_token.lineterm)) {
+ if ((tok == DUK_TOK_DECREMENT || tok == DUK_TOK_INCREMENT) && (comp_ctx->curr_token.lineterm)) {
/* '++' or '--' in a post-increment/decrement position,
* and a LineTerminator occurs between the operator and
* the preceding expression. Force the previous expr
@@ -68655,7 +73932,7 @@ DUK_LOCAL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx) {
return 0;
}
- return DUK__TOKEN_LBP_GET_BP(duk__token_lbp[tok]); /* format is bit packed */
+ return DUK__TOKEN_LBP_GET_BP(duk__token_lbp[tok]); /* format is bit packed */
}
/*
@@ -68667,15 +73944,15 @@ DUK_LOCAL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx) {
* statement).
*/
-#define DUK__EXPR_RBP_MASK 0xff
-#define DUK__EXPR_FLAG_REJECT_IN (1 << 8) /* reject 'in' token (used for for-in) */
-#define DUK__EXPR_FLAG_ALLOW_EMPTY (1 << 9) /* allow empty expression */
-#define DUK__EXPR_FLAG_REQUIRE_INIT (1 << 10) /* require initializer for var/const */
+#define DUK__EXPR_RBP_MASK 0xff
+#define DUK__EXPR_FLAG_REJECT_IN (1 << 8) /* reject 'in' token (used for for-in) */
+#define DUK__EXPR_FLAG_ALLOW_EMPTY (1 << 9) /* allow empty expression */
+#define DUK__EXPR_FLAG_REQUIRE_INIT (1 << 10) /* require initializer for var/const */
/* main expression parser function */
DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
duk_hthread *thr = comp_ctx->thr;
- duk_ivalue tmp_alloc; /* 'res' is used for "left", and 'tmp' for "right" */
+ duk_ivalue tmp_alloc; /* 'res' is used for "left", and 'tmp' for "right" */
duk_ivalue *tmp = &tmp_alloc;
duk_small_uint_t rbp;
@@ -68687,10 +73964,12 @@ DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_
rbp = rbp_flags & DUK__EXPR_RBP_MASK;
DUK_DDD(DUK_DDDPRINT("duk__expr(), rbp_flags=%ld, rbp=%ld, allow_in=%ld, paren_level=%ld",
- (long) rbp_flags, (long) rbp, (long) comp_ctx->curr_func.allow_in,
+ (long) rbp_flags,
+ (long) rbp,
+ (long) comp_ctx->curr_func.allow_in,
(long) comp_ctx->curr_func.paren_level));
- DUK_MEMZERO(&tmp_alloc, sizeof(tmp_alloc));
+ duk_memzero(&tmp_alloc, sizeof(tmp_alloc));
tmp->x1.valstack_idx = duk_get_top(thr);
tmp->x2.valstack_idx = tmp->x1.valstack_idx + 1;
duk_push_undefined(thr);
@@ -68710,6 +73989,7 @@ DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_
DUK_DDD(DUK_DDDPRINT("empty expression"));
if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY)) {
DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);
+ DUK_WO_NORETURN(return;);
}
duk_push_undefined(thr);
duk__ivalue_plain_fromstack(comp_ctx, res);
@@ -68717,14 +73997,14 @@ DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_
}
duk__advance(comp_ctx);
- duk__expr_nud(comp_ctx, res); /* reuse 'res' as 'left' */
+ duk__expr_nud(comp_ctx, res); /* reuse 'res' as 'left' */
while (rbp < duk__expr_lbp(comp_ctx)) {
duk__advance(comp_ctx);
duk__expr_led(comp_ctx, res, tmp);
- duk__copy_ivalue(comp_ctx, tmp, res); /* tmp -> res */
+ duk__copy_ivalue(comp_ctx, tmp, res); /* tmp -> res */
}
- cleanup:
+cleanup:
/* final result is already in 'res' */
duk_pop_2(thr);
@@ -68748,6 +74028,7 @@ DUK_LOCAL void duk__exprtop(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_sma
if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY) && duk__expr_is_empty(comp_ctx)) {
DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);
+ DUK_WO_NORETURN(return;);
}
}
@@ -68757,21 +74038,24 @@ DUK_LOCAL void duk__exprtop(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_sma
* Each helper needs at least 2-3 calls to make it worth while to wrap.
*/
-#if 0 /* unused */
+#if 0 /* unused */
DUK_LOCAL duk_regconst_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
duk__expr(comp_ctx, res, rbp_flags);
return duk__ivalue_toreg(comp_ctx, res);
}
#endif
-#if 0 /* unused */
+#if 0 /* unused */
DUK_LOCAL duk_regconst_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
duk__expr(comp_ctx, res, rbp_flags);
return duk__ivalue_totemp(comp_ctx, res);
}
#endif
-DUK_LOCAL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_regconst_t forced_reg) {
+DUK_LOCAL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx,
+ duk_ivalue *res,
+ duk_small_uint_t rbp_flags,
+ duk_regconst_t forced_reg) {
DUK_ASSERT(forced_reg >= 0);
duk__expr(comp_ctx, res, rbp_flags);
duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
@@ -68782,7 +74066,7 @@ DUK_LOCAL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_iv
return duk__ivalue_toregconst(comp_ctx, res);
}
-#if 0 /* unused */
+#if 0 /* unused */
DUK_LOCAL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
duk__expr(comp_ctx, res, rbp_flags);
return duk__ivalue_totempconst(comp_ctx, res);
@@ -68804,14 +74088,17 @@ DUK_LOCAL duk_regconst_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ival
return duk__ivalue_toreg(comp_ctx, res);
}
-#if 0 /* unused */
+#if 0 /* unused */
DUK_LOCAL duk_regconst_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
duk__exprtop(comp_ctx, res, rbp_flags);
return duk__ivalue_totemp(comp_ctx, res);
}
#endif
-DUK_LOCAL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_regconst_t forced_reg) {
+DUK_LOCAL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx,
+ duk_ivalue *res,
+ duk_small_uint_t rbp_flags,
+ duk_regconst_t forced_reg) {
DUK_ASSERT(forced_reg >= 0);
duk__exprtop(comp_ctx, res, rbp_flags);
duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
@@ -68822,7 +74109,7 @@ DUK_LOCAL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk
return duk__ivalue_toregconst(comp_ctx, res);
}
-#if 0 /* unused */
+#if 0 /* unused */
DUK_LOCAL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, int rbp_flags) {
duk__exprtop(comp_ctx, res, rbp_flags);
duk__ivalue_toplain_ignore(comp_ctx, res);
@@ -68841,11 +74128,11 @@ DUK_LOCAL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalu
* the token after the terminator).
*/
-#define DUK__HAS_VAL (1 << 0) /* stmt has non-empty value */
-#define DUK__HAS_TERM (1 << 1) /* stmt has explicit/implicit semicolon terminator */
-#define DUK__ALLOW_AUTO_SEMI_ALWAYS (1 << 2) /* allow automatic semicolon even without lineterm (compatibility) */
-#define DUK__STILL_PROLOGUE (1 << 3) /* statement does not terminate directive prologue */
-#define DUK__IS_TERMINAL (1 << 4) /* statement is guaranteed to be terminal (control doesn't flow to next statement) */
+#define DUK__HAS_VAL (1 << 0) /* stmt has non-empty value */
+#define DUK__HAS_TERM (1 << 1) /* stmt has explicit/implicit semicolon terminator */
+#define DUK__ALLOW_AUTO_SEMI_ALWAYS (1 << 2) /* allow automatic semicolon even without lineterm (compatibility) */
+#define DUK__STILL_PROLOGUE (1 << 3) /* statement does not terminate directive prologue */
+#define DUK__IS_TERMINAL (1 << 4) /* statement is guaranteed to be terminal (control doesn't flow to next statement) */
/* Parse a single variable declaration (e.g. "i" or "i=10"). A leading 'var'
* has already been eaten. These is no return value in 'res', it is used only
@@ -68865,7 +74152,11 @@ DUK_LOCAL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalu
* as is done in 'for-in' parsing.
*/
-DUK_LOCAL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_regconst_t *out_reg_varbind, duk_regconst_t *out_rc_varname) {
+DUK_LOCAL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx,
+ duk_ivalue *res,
+ duk_small_uint_t expr_flags,
+ duk_regconst_t *out_reg_varbind,
+ duk_regconst_t *out_rc_varname) {
duk_hthread *thr = comp_ctx->thr;
duk_hstring *h_varname;
duk_regconst_t reg_varbind;
@@ -68889,8 +74180,7 @@ DUK_LOCAL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
/* register declarations in first pass */
if (comp_ctx->curr_func.in_scanning) {
duk_uarridx_t n;
- DUK_DDD(DUK_DDDPRINT("register variable declaration %!O in pass 1",
- (duk_heaphdr *) h_varname));
+ DUK_DDD(DUK_DDDPRINT("register variable declaration %!O in pass 1", (duk_heaphdr *) h_varname));
n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
duk_push_hstring(thr, h_varname);
duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n);
@@ -68898,31 +74188,30 @@ DUK_LOCAL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n + 1);
}
- duk_push_hstring(thr, h_varname); /* push before advancing to keep reachable */
+ duk_push_hstring(thr, h_varname); /* push before advancing to keep reachable */
/* register binding lookup is based on varmap (even in first pass) */
duk_dup_top(thr);
(void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
- duk__advance(comp_ctx); /* eat identifier */
+ duk__advance(comp_ctx); /* eat identifier */
if (comp_ctx->curr_token.t == DUK_TOK_EQUALSIGN) {
duk__advance(comp_ctx);
DUK_DDD(DUK_DDDPRINT("vardecl, assign to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
- (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
+ (duk_heaphdr *) h_varname,
+ (long) reg_varbind,
+ (long) rc_varname));
- duk__exprtop(comp_ctx, res, DUK__BP_COMMA | expr_flags /*rbp_flags*/); /* AssignmentExpression */
+ duk__exprtop(comp_ctx, res, DUK__BP_COMMA | expr_flags /*rbp_flags*/); /* AssignmentExpression */
if (reg_varbind >= 0) {
duk__ivalue_toforcedreg(comp_ctx, res, reg_varbind);
} else {
duk_regconst_t reg_val;
reg_val = duk__ivalue_toreg(comp_ctx, res);
- duk__emit_a_bc(comp_ctx,
- DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
- reg_val,
- rc_varname);
+ duk__emit_a_bc(comp_ctx, DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE, reg_val, rc_varname);
}
} else {
if (expr_flags & DUK__EXPR_FLAG_REQUIRE_INIT) {
@@ -68931,22 +74220,23 @@ DUK_LOCAL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
}
}
- duk_pop(thr); /* pop varname */
+ duk_pop(thr); /* pop varname */
*out_rc_varname = rc_varname;
*out_reg_varbind = reg_varbind;
return;
- syntax_error:
+syntax_error:
DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_VAR_DECLARATION);
+ DUK_WO_NORETURN(return;);
}
DUK_LOCAL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags) {
duk_regconst_t reg_varbind;
duk_regconst_t rc_varname;
- duk__advance(comp_ctx); /* eat 'var' */
+ duk__advance(comp_ctx); /* eat 'var' */
for (;;) {
/* rc_varname and reg_varbind are ignored here */
@@ -68961,9 +74251,9 @@ DUK_LOCAL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
duk_hthread *thr = comp_ctx->thr;
- duk_int_t pc_v34_lhs; /* start variant 3/4 left-hand-side code (L1 in doc/compiler.rst example) */
- duk_regconst_t temp_reset; /* knock back "next temp" to this whenever possible */
- duk_regconst_t reg_temps; /* preallocated temporaries (2) for variants 3 and 4 */
+ duk_int_t pc_v34_lhs; /* start variant 3/4 left-hand-side code (L1 in doc/compiler.rst example) */
+ duk_regconst_t temp_reset; /* knock back "next temp" to this whenever possible */
+ duk_regconst_t reg_temps; /* preallocated temporaries (2) for variants 3 and 4 */
DUK_DDD(DUK_DDDPRINT("start parsing a for/for-in statement"));
@@ -68992,7 +74282,7 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
* issues, evaluation order issues, etc.
*/
- duk__advance(comp_ctx); /* eat 'for' */
+ duk__advance(comp_ctx); /* eat 'for' */
duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
DUK_DDD(DUK_DDDPRINT("detecting for/for-in loop variant, pc=%ld", (long) duk__get_current_pc(comp_ctx)));
@@ -69006,10 +74296,10 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
* Variant 2 or 4
*/
- duk_regconst_t reg_varbind; /* variable binding register if register-bound (otherwise < 0) */
- duk_regconst_t rc_varname; /* variable name reg/const, if variable not register-bound */
+ duk_regconst_t reg_varbind; /* variable binding register if register-bound (otherwise < 0) */
+ duk_regconst_t rc_varname; /* variable name reg/const, if variable not register-bound */
- duk__advance(comp_ctx); /* eat 'var' */
+ duk__advance(comp_ctx); /* eat 'var' */
duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
DUK__SETTEMP(comp_ctx, temp_reset);
@@ -69019,17 +74309,11 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
*/
DUK_DDD(DUK_DDDPRINT("detected for variant 4: for (var VariableDeclarationNoIn in Expression) Statement"));
- pc_v34_lhs = duk__get_current_pc(comp_ctx); /* jump is inserted here */
+ pc_v34_lhs = duk__get_current_pc(comp_ctx); /* jump is inserted here */
if (reg_varbind >= 0) {
- duk__emit_a_bc(comp_ctx,
- DUK_OP_LDREG,
- reg_varbind,
- reg_temps + 0);
+ duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, reg_varbind, reg_temps + 0);
} else {
- duk__emit_a_bc(comp_ctx,
- DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
- reg_temps + 0,
- rc_varname);
+ duk__emit_a_bc(comp_ctx, DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE, reg_temps + 0, rc_varname);
}
goto parse_3_or_4;
} else {
@@ -69037,7 +74321,8 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
* Variant 2
*/
- DUK_DDD(DUK_DDDPRINT("detected for variant 2: for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement"));
+ DUK_DDD(DUK_DDDPRINT(
+ "detected for variant 2: for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement"));
for (;;) {
/* more initializers */
if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
@@ -69045,7 +74330,7 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
}
DUK_DDD(DUK_DDDPRINT("variant 2 has another variable initializer"));
- duk__advance(comp_ctx); /* eat comma */
+ duk__advance(comp_ctx); /* eat comma */
duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
}
goto parse_1_or_2;
@@ -69055,14 +74340,17 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
* Variant 1 or 3
*/
- pc_v34_lhs = duk__get_current_pc(comp_ctx); /* jump is inserted here (variant 3) */
+ pc_v34_lhs = duk__get_current_pc(comp_ctx); /* jump is inserted here (variant 3) */
/* Note that duk__exprtop() here can clobber any reg above current temp_next,
* so any loop variables (e.g. enumerator) must be "preallocated".
*/
/* don't coerce yet to a plain value (variant 3 needs special handling) */
- duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_REJECT_IN | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/); /* Expression */
+ duk__exprtop(comp_ctx,
+ res,
+ DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_REJECT_IN |
+ DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/); /* Expression */
if (comp_ctx->curr_token.t == DUK_TOK_IN) {
/*
* Variant 3
@@ -69071,7 +74359,7 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
/* XXX: need to determine LHS type, and check that it is LHS compatible */
DUK_DDD(DUK_DDDPRINT("detected for variant 3: for (LeftHandSideExpression in Expression) Statement"));
if (duk__expr_is_empty(comp_ctx)) {
- goto syntax_error; /* LeftHandSideExpression does not allow empty expression */
+ goto syntax_error; /* LeftHandSideExpression does not allow empty expression */
}
if (res->t == DUK_IVAL_VAR) {
@@ -69080,10 +74368,7 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
duk_dup(thr, res->x1.valstack_idx);
if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
- duk__emit_a_bc(comp_ctx,
- DUK_OP_LDREG,
- reg_varbind,
- reg_temps + 0);
+ duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, reg_varbind, reg_temps + 0);
} else {
duk__emit_a_bc(comp_ctx,
DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
@@ -69096,17 +74381,22 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
*/
duk_regconst_t reg_obj;
duk_regconst_t rc_key;
- reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
- rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
+ reg_obj = duk__ispec_toregconst_raw(comp_ctx,
+ &res->x1,
+ -1 /*forced_reg*/,
+ 0 /*flags*/); /* don't allow const */
+ rc_key = duk__ispec_toregconst_raw(comp_ctx,
+ &res->x2,
+ -1 /*forced_reg*/,
+ DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
duk__emit_a_b_c(comp_ctx,
DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE | DUK__EMIT_FLAG_BC_REGCONST,
reg_obj,
rc_key,
reg_temps + 0);
} else {
- duk__ivalue_toplain_ignore(comp_ctx, res); /* just in case */
- duk__emit_op_only(comp_ctx,
- DUK_OP_INVLHS);
+ duk__ivalue_toplain_ignore(comp_ctx, res); /* just in case */
+ duk__emit_op_only(comp_ctx, DUK_OP_INVLHS);
}
goto parse_3_or_4;
} else {
@@ -69114,13 +74404,14 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
* Variant 1
*/
- DUK_DDD(DUK_DDDPRINT("detected for variant 1: for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement"));
+ DUK_DDD(DUK_DDDPRINT(
+ "detected for variant 1: for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement"));
duk__ivalue_toplain_ignore(comp_ctx, res);
goto parse_1_or_2;
}
}
- parse_1_or_2:
+parse_1_or_2:
/*
* Parse variant 1 or 2. The first part expression (which differs
* in the variants) has already been parsed and its code emitted.
@@ -69143,23 +74434,23 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
duk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);
pc_l1 = duk__get_current_pc(comp_ctx);
- duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/); /* Expression_opt */
+ duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/); /* Expression_opt */
if (duk__expr_is_empty(comp_ctx)) {
/* no need to coerce */
- pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx); /* to body */
- pc_jumpto_l4 = -1; /* omitted */
+ pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx); /* to body */
+ pc_jumpto_l4 = -1; /* omitted */
} else {
rc_cond = duk__ivalue_toregconst(comp_ctx, res);
duk__emit_if_false_skip(comp_ctx, rc_cond);
- pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx); /* to body */
- pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx); /* to exit */
+ pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx); /* to body */
+ pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx); /* to exit */
}
DUK__SETTEMP(comp_ctx, temp_reset);
duk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);
pc_l2 = duk__get_current_pc(comp_ctx);
- duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/); /* Expression_opt */
+ duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/); /* Expression_opt */
if (duk__expr_is_empty(comp_ctx)) {
/* no need to coerce */
expr_c_empty = 1;
@@ -69171,7 +74462,8 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
}
DUK__SETTEMP(comp_ctx, temp_reset);
- duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
+ comp_ctx->curr_func.allow_regexp_in_adv = 1;
+ duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */
pc_l3 = duk__get_current_pc(comp_ctx);
duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
@@ -69186,21 +74478,23 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l3: %ld->%ld, jumpto_l4: %ld->%ld, "
"break: %ld->%ld, continue: %ld->%ld",
- (long) pc_jumpto_l3, (long) pc_l3, (long) pc_jumpto_l4, (long) pc_l4,
- (long) (pc_label_site + 1), (long) pc_l4, (long) (pc_label_site + 2), (long) pc_l2));
+ (long) pc_jumpto_l3,
+ (long) pc_l3,
+ (long) pc_jumpto_l4,
+ (long) pc_l4,
+ (long) (pc_label_site + 1),
+ (long) pc_l4,
+ (long) (pc_label_site + 2),
+ (long) pc_l2));
duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
- duk__patch_jump(comp_ctx,
- pc_label_site + 1,
- pc_l4); /* break jump */
- duk__patch_jump(comp_ctx,
- pc_label_site + 2,
- expr_c_empty ? pc_l1 : pc_l2); /* continue jump */
+ duk__patch_jump(comp_ctx, pc_label_site + 1, pc_l4); /* break jump */
+ duk__patch_jump(comp_ctx, pc_label_site + 2, expr_c_empty ? pc_l1 : pc_l2); /* continue jump */
}
goto finished;
- parse_3_or_4:
+parse_3_or_4:
/*
* Parse variant 3 or 4.
*
@@ -69236,16 +74530,16 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
*/
duk__insert_jump_entry(comp_ctx, pc_v34_lhs);
- pc_jumpto_l2 = pc_v34_lhs; /* inserted jump */
- pc_l1 = pc_v34_lhs + 1; /* +1, right after inserted jump */
+ pc_jumpto_l2 = pc_v34_lhs; /* inserted jump */
+ pc_l1 = pc_v34_lhs + 1; /* +1, right after inserted jump */
/* The code for writing reg_temps + 0 to the left hand side has already
* been emitted.
*/
- pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx); /* -> loop body */
+ pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx); /* -> loop body */
- duk__advance(comp_ctx); /* eat 'in' */
+ duk__advance(comp_ctx); /* eat 'in' */
/* Parse enumeration target and initialize enumerator. For 'null' and 'undefined',
* INITENUM will creates a 'null' enumerator which works like an empty enumerator
@@ -69254,15 +74548,13 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
*/
pc_l2 = duk__get_current_pc(comp_ctx);
- reg_target = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression */
- duk__emit_b_c(comp_ctx,
- DUK_OP_INITENUM | DUK__EMIT_FLAG_B_IS_TARGET,
- reg_temps + 1,
- reg_target);
+ reg_target = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression */
+ duk__emit_b_c(comp_ctx, DUK_OP_INITENUM | DUK__EMIT_FLAG_B_IS_TARGET, reg_temps + 1, reg_target);
pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);
DUK__SETTEMP(comp_ctx, temp_reset);
- duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
+ comp_ctx->curr_func.allow_regexp_in_adv = 1;
+ duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */
pc_l3 = duk__get_current_pc(comp_ctx);
duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
@@ -69279,8 +74571,8 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
DUK_OP_NEXTENUM | DUK__EMIT_FLAG_B_IS_TARGET | DUK__EMIT_FLAG_RESERVE_JUMPSLOT,
reg_temps + 0,
reg_temps + 1);
- pc_jumpto_l5 = comp_ctx->emit_jumpslot_pc; /* NEXTENUM jump slot: executed when enum finished */
- duk__emit_jump(comp_ctx, pc_l1); /* jump to next loop, using reg_v34_iter as iterated value */
+ pc_jumpto_l5 = comp_ctx->emit_jumpslot_pc; /* NEXTENUM jump slot: executed when enum finished */
+ duk__emit_jump(comp_ctx, pc_l1); /* jump to next loop, using reg_v34_iter as iterated value */
pc_l5 = duk__get_current_pc(comp_ctx);
@@ -69292,36 +74584,46 @@ DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l2: %ld->%ld, jumpto_l3: %ld->%ld, "
"jumpto_l4: %ld->%ld, jumpto_l5: %ld->%ld, "
"break: %ld->%ld, continue: %ld->%ld",
- (long) pc_jumpto_l2, (long) pc_l2, (long) pc_jumpto_l3, (long) pc_l3,
- (long) pc_jumpto_l4, (long) pc_l4, (long) pc_jumpto_l5, (long) pc_l5,
- (long) (pc_label_site + 1), (long) pc_l5, (long) (pc_label_site + 2), (long) pc_l4));
+ (long) pc_jumpto_l2,
+ (long) pc_l2,
+ (long) pc_jumpto_l3,
+ (long) pc_l3,
+ (long) pc_jumpto_l4,
+ (long) pc_l4,
+ (long) pc_jumpto_l5,
+ (long) pc_l5,
+ (long) (pc_label_site + 1),
+ (long) pc_l5,
+ (long) (pc_label_site + 2),
+ (long) pc_l4));
duk__patch_jump(comp_ctx, pc_jumpto_l2, pc_l2);
duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
duk__patch_jump(comp_ctx, pc_jumpto_l5, pc_l5);
- duk__patch_jump(comp_ctx, pc_label_site + 1, pc_l5); /* break jump */
- duk__patch_jump(comp_ctx, pc_label_site + 2, pc_l4); /* continue jump */
+ duk__patch_jump(comp_ctx, pc_label_site + 1, pc_l5); /* break jump */
+ duk__patch_jump(comp_ctx, pc_label_site + 2, pc_l4); /* continue jump */
}
goto finished;
- finished:
+finished:
DUK_DDD(DUK_DDDPRINT("end parsing a for/for-in statement"));
return;
- syntax_error:
+syntax_error:
DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FOR);
+ DUK_WO_NORETURN(return;);
}
DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
duk_hthread *thr = comp_ctx->thr;
duk_regconst_t temp_at_loop;
- duk_regconst_t rc_switch; /* reg/const for switch value */
- duk_regconst_t rc_case; /* reg/const for case value */
- duk_regconst_t reg_temp; /* general temp register */
+ duk_regconst_t rc_switch; /* reg/const for switch value */
+ duk_regconst_t rc_case; /* reg/const for case value */
+ duk_regconst_t reg_temp; /* general temp register */
duk_int_t pc_prevcase = -1;
duk_int_t pc_prevstmt = -1;
- duk_int_t pc_default = -1; /* -1 == not set, -2 == pending (next statement list) */
+ duk_int_t pc_default = -1; /* -1 == not set, -2 == pending (next statement list) */
/* Note: negative pc values are ignored when patching jumps, so no explicit checks needed */
@@ -69352,7 +74654,7 @@ DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *re
duk__advance(comp_ctx);
duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
rc_switch = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
- duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
+ duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* RegExp mode does not matter. */
duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
DUK_DDD(DUK_DDDPRINT("switch value in register %ld", (long) rc_switch));
@@ -69382,24 +74684,20 @@ DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *re
* because it may be a constant.
*/
- duk__patch_jump_here(comp_ctx, pc_prevcase); /* chain jumps for case
- * evaluation and checking
- */
+ duk__patch_jump_here(comp_ctx, pc_prevcase); /* chain jumps for case
+ * evaluation and checking
+ */
duk__advance(comp_ctx);
rc_case = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
duk__advance_expect(comp_ctx, DUK_TOK_COLON);
reg_temp = DUK__ALLOCTEMP(comp_ctx);
- duk__emit_a_b_c(comp_ctx,
- DUK_OP_SEQ | DUK__EMIT_FLAG_BC_REGCONST,
- reg_temp,
- rc_switch,
- rc_case);
+ duk__emit_a_b_c(comp_ctx, DUK_OP_SEQ | DUK__EMIT_FLAG_BC_REGCONST, reg_temp, rc_switch, rc_case);
duk__emit_if_true_skip(comp_ctx, reg_temp);
/* jump to next case clause */
- pc_prevcase = duk__emit_jump_empty(comp_ctx); /* no match, next case */
+ pc_prevcase = duk__emit_jump_empty(comp_ctx); /* no match, next case */
/* statements go here (if any) on next loop */
} else if (comp_ctx->curr_token.t == DUK_TOK_DEFAULT) {
@@ -69448,14 +74746,13 @@ DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *re
* they participate in 'fall-through' behavior even if the
* default clause is in the middle.
*/
- duk__patch_jump_here(comp_ctx, pc_prevstmt); /* chain jumps for 'fall-through'
- * after a case matches.
- */
+ duk__patch_jump_here(comp_ctx, pc_prevstmt); /* chain jumps for 'fall-through'
+ * after a case matches.
+ */
for (;;) {
tok = comp_ctx->curr_token.t;
- if (tok == DUK_TOK_CASE || tok == DUK_TOK_DEFAULT ||
- tok == DUK_TOK_RCURLY) {
+ if (tok == DUK_TOK_CASE || tok == DUK_TOK_DEFAULT || tok == DUK_TOK_RCURLY) {
break;
}
num_stmts++;
@@ -69477,7 +74774,8 @@ DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *re
}
DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
- duk__advance(comp_ctx);
+ comp_ctx->curr_func.allow_regexp_in_adv = 1;
+ duk__advance(comp_ctx); /* Allow RegExp as part of next stmt. */
/* default case control flow patchup; note that if pc_prevcase < 0
* (i.e. no case clauses), control enters default case automatically.
@@ -69498,7 +74796,7 @@ DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *re
duk__patch_jump_here(comp_ctx, pc_prevstmt);
/* continue jump not patched, an INVALID opcode remains there */
- duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
+ duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
/* Note: 'fast' breaks will jump to pc_label_site + 1, which will
* then jump here. The double jump will be eliminated by a
@@ -69508,8 +74806,9 @@ DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *re
return;
- syntax_error:
+syntax_error:
DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_SWITCH);
+ DUK_WO_NORETURN(return;);
}
DUK_LOCAL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
@@ -69521,15 +74820,16 @@ DUK_LOCAL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
temp_reset = DUK__GETTEMP(comp_ctx);
- duk__advance(comp_ctx); /* eat 'if' */
+ duk__advance(comp_ctx); /* eat 'if' */
duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
duk__emit_if_true_skip(comp_ctx, rc_cond);
- pc_jump_false = duk__emit_jump_empty(comp_ctx); /* jump to end or else part */
+ pc_jump_false = duk__emit_jump_empty(comp_ctx); /* jump to end or else part */
DUK__SETTEMP(comp_ctx, temp_reset);
- duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
+ comp_ctx->curr_func.allow_regexp_in_adv = 1;
+ duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */
duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
@@ -69544,7 +74844,7 @@ DUK_LOCAL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
duk__advance(comp_ctx);
- pc_jump_end = duk__emit_jump_empty(comp_ctx); /* jump from true part to end */
+ pc_jump_end = duk__emit_jump_empty(comp_ctx); /* jump from true part to end */
duk__patch_jump_here(comp_ctx, pc_jump_false);
duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
@@ -69565,11 +74865,11 @@ DUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, d
DUK_DDD(DUK_DDDPRINT("begin parsing do statement"));
- duk__advance(comp_ctx); /* eat 'do' */
+ duk__advance(comp_ctx); /* Eat 'do'; allow RegExp as part of next stmt. */
pc_start = duk__get_current_pc(comp_ctx);
duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
- duk__patch_jump_here(comp_ctx, pc_label_site + 2); /* continue jump */
+ duk__patch_jump_here(comp_ctx, pc_label_site + 2); /* continue jump */
duk__advance_expect(comp_ctx, DUK_TOK_WHILE);
duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
@@ -69579,9 +74879,10 @@ DUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, d
duk__emit_jump(comp_ctx, pc_start);
/* no need to reset temps, as we're finished emitting code */
+ comp_ctx->curr_func.allow_regexp_in_adv = 1; /* Allow RegExp as part of next stmt. */
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
- duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
+ duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
DUK_DDD(DUK_DDDPRINT("end parsing do statement"));
}
@@ -69596,25 +74897,26 @@ DUK_LOCAL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res
temp_reset = DUK__GETTEMP(comp_ctx);
- duk__advance(comp_ctx); /* eat 'while' */
+ duk__advance(comp_ctx); /* eat 'while' */
duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
pc_start = duk__get_current_pc(comp_ctx);
- duk__patch_jump_here(comp_ctx, pc_label_site + 2); /* continue jump */
+ duk__patch_jump_here(comp_ctx, pc_label_site + 2); /* continue jump */
rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
duk__emit_if_true_skip(comp_ctx, rc_cond);
pc_jump_false = duk__emit_jump_empty(comp_ctx);
DUK__SETTEMP(comp_ctx, temp_reset);
- duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
+ comp_ctx->curr_func.allow_regexp_in_adv = 1;
+ duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */
duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
duk__emit_jump(comp_ctx, pc_start);
duk__patch_jump_here(comp_ctx, pc_jump_false);
- duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
+ duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
DUK_DDD(DUK_DDDPRINT("end parsing while statement"));
}
@@ -69624,26 +74926,39 @@ DUK_LOCAL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk
duk_bool_t is_break = (comp_ctx->curr_token.t == DUK_TOK_BREAK);
duk_int_t label_id;
duk_int_t label_catch_depth;
- duk_int_t label_pc; /* points to LABEL; pc+1 = jump site for break; pc+2 = jump site for continue */
+ duk_int_t label_pc; /* points to LABEL; pc+1 = jump site for break; pc+2 = jump site for continue */
duk_bool_t label_is_closest;
DUK_UNREF(res);
- duk__advance(comp_ctx); /* eat 'break' or 'continue' */
+ duk__advance(comp_ctx); /* eat 'break' or 'continue' */
- if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || /* explicit semi follows */
- comp_ctx->curr_token.lineterm || /* automatic semi will be inserted */
- comp_ctx->curr_token.allow_auto_semi) { /* automatic semi will be inserted */
+ if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || /* explicit semi follows */
+ comp_ctx->curr_token.lineterm || /* automatic semi will be inserted */
+ comp_ctx->curr_token.allow_auto_semi) { /* automatic semi will be inserted */
/* break/continue without label */
- duk__lookup_active_label(comp_ctx, DUK_HTHREAD_STRING_EMPTY_STRING(thr), is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
+ duk__lookup_active_label(comp_ctx,
+ DUK_HTHREAD_STRING_EMPTY_STRING(thr),
+ is_break,
+ &label_id,
+ &label_catch_depth,
+ &label_pc,
+ &label_is_closest);
} else if (comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER) {
/* break/continue with label (label cannot be a reserved word, production is 'Identifier' */
DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
- duk__lookup_active_label(comp_ctx, comp_ctx->curr_token.str1, is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
+ duk__lookup_active_label(comp_ctx,
+ comp_ctx->curr_token.str1,
+ is_break,
+ &label_id,
+ &label_catch_depth,
+ &label_pc,
+ &label_is_closest);
duk__advance(comp_ctx);
} else {
DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BREAK_CONT_LABEL);
+ DUK_WO_NORETURN(return;);
}
/* Use a fast break/continue when possible. A fast break/continue is
@@ -69652,25 +74967,28 @@ DUK_LOCAL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk
* The peephole optimizer will optimize the jump to a direct one.
*/
- if (label_catch_depth == comp_ctx->curr_func.catch_depth &&
- label_is_closest) {
+ if (label_catch_depth == comp_ctx->curr_func.catch_depth && label_is_closest) {
DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
"label_catch_depth=%ld, catch_depth=%ld "
"-> use fast variant (direct jump)",
- (long) is_break, (long) label_id, (long) label_is_closest,
- (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
+ (long) is_break,
+ (long) label_id,
+ (long) label_is_closest,
+ (long) label_catch_depth,
+ (long) comp_ctx->curr_func.catch_depth));
duk__emit_jump(comp_ctx, label_pc + (is_break ? 1 : 2));
} else {
DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
"label_catch_depth=%ld, catch_depth=%ld "
"-> use slow variant (longjmp)",
- (long) is_break, (long) label_id, (long) label_is_closest,
- (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
+ (long) is_break,
+ (long) label_id,
+ (long) label_is_closest,
+ (long) label_catch_depth,
+ (long) comp_ctx->curr_func.catch_depth));
- duk__emit_bc(comp_ctx,
- is_break ? DUK_OP_BREAK : DUK_OP_CONTINUE,
- (duk_regconst_t) label_id);
+ duk__emit_bc(comp_ctx, is_break ? DUK_OP_BREAK : DUK_OP_CONTINUE, (duk_regconst_t) label_id);
}
}
@@ -69678,18 +74996,19 @@ DUK_LOCAL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *re
duk_hthread *thr = comp_ctx->thr;
duk_regconst_t rc_val;
- duk__advance(comp_ctx); /* eat 'return' */
+ duk__advance(comp_ctx); /* eat 'return' */
/* A 'return' statement is only allowed inside an actual function body,
* not as part of eval or global code.
*/
if (!comp_ctx->curr_func.is_function) {
DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_RETURN);
+ DUK_WO_NORETURN(return;);
}
- if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || /* explicit semi follows */
- comp_ctx->curr_token.lineterm || /* automatic semi will be inserted */
- comp_ctx->curr_token.allow_auto_semi) { /* automatic semi will be inserted */
+ if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || /* explicit semi follows */
+ comp_ctx->curr_token.lineterm || /* automatic semi will be inserted */
+ comp_ctx->curr_token.allow_auto_semi) { /* automatic semi will be inserted */
DUK_DDD(DUK_DDDPRINT("empty return value -> undefined"));
duk__emit_op_only(comp_ctx, DUK_OP_RETUNDEF);
} else {
@@ -69741,8 +75060,8 @@ DUK_LOCAL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *re
*/
#if defined(DUK_USE_TAILCALL)
- if (comp_ctx->curr_func.catch_depth == 0 && /* no catchers */
- pc_after_expr > pc_before_expr) { /* at least one opcode emitted */
+ if (comp_ctx->curr_func.catch_depth == 0 && /* no catchers */
+ pc_after_expr > pc_before_expr) { /* at least one opcode emitted */
duk_compiler_instr *instr;
duk_instr_t ins;
duk_small_uint_t op;
@@ -69752,8 +75071,7 @@ DUK_LOCAL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *re
ins = instr->ins;
op = (duk_small_uint_t) DUK_DEC_OP(ins);
- if ((op & ~0x0fU) == DUK_OP_CALL0 &&
- DUK__ISREG_TEMP(comp_ctx, rc_val) /* see above */) {
+ if ((op & ~0x0fU) == DUK_OP_CALL0 && DUK__ISREG_TEMP(comp_ctx, rc_val) /* see above */) {
DUK_DDD(DUK_DDDPRINT("return statement detected a tail call opportunity: "
"catch depth is 0, duk__exprtop() emitted >= 1 instructions, "
"and last instruction is a CALL "
@@ -69762,7 +75080,7 @@ DUK_LOCAL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *re
instr->ins = ins;
}
}
-#endif /* DUK_USE_TAILCALL */
+#endif /* DUK_USE_TAILCALL */
if (DUK__ISREG(rc_val)) {
duk__emit_bc(comp_ctx, DUK_OP_RETREG, rc_val);
@@ -69780,23 +75098,22 @@ DUK_LOCAL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *re
DUK_LOCAL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
duk_regconst_t reg_val;
- duk__advance(comp_ctx); /* eat 'throw' */
+ duk__advance(comp_ctx); /* eat 'throw' */
/* Unlike break/continue, throw statement does not allow an empty value. */
if (comp_ctx->curr_token.lineterm) {
DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_INVALID_THROW);
+ DUK_WO_NORETURN(return;);
}
reg_val = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
- duk__emit_bc(comp_ctx,
- DUK_OP_THROW,
- reg_val);
+ duk__emit_bc(comp_ctx, DUK_OP_THROW, reg_val);
}
DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
duk_hthread *thr = comp_ctx->thr;
- duk_regconst_t reg_catch; /* reg_catch+0 and reg_catch+1 are reserved for TRYCATCH */
+ duk_regconst_t reg_catch; /* reg_catch+0 and reg_catch+1 are reserved for TRYCATCH */
duk_regconst_t rc_varname = 0;
duk_small_uint_t trycatch_flags = 0;
duk_int_t pc_ldconst = -1;
@@ -69823,7 +75140,7 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
comp_ctx->curr_func.catch_depth++;
- duk__advance(comp_ctx); /* eat 'try' */
+ duk__advance(comp_ctx); /* eat 'try' */
reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
@@ -69836,16 +75153,15 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, reg_catch, 0 /*patched later*/);
pc_trycatch = duk__get_current_pc(comp_ctx);
- duk__emit_invalid(comp_ctx); /* TRYCATCH, cannot emit now (not enough info) */
- duk__emit_invalid(comp_ctx); /* jump for 'catch' case */
- duk__emit_invalid(comp_ctx); /* jump for 'finally' case or end (if no finally) */
+ duk__emit_invalid(comp_ctx); /* TRYCATCH, cannot emit now (not enough info) */
+ duk__emit_invalid(comp_ctx); /* jump for 'catch' case */
+ duk__emit_invalid(comp_ctx); /* jump for 'finally' case or end (if no finally) */
/* try part */
duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
- duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
+ duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
- duk__emit_op_only(comp_ctx,
- DUK_OP_ENDTRY);
+ duk__emit_op_only(comp_ctx, DUK_OP_ENDTRY);
if (comp_ctx->curr_token.t == DUK_TOK_CATCH) {
/*
@@ -69868,7 +75184,7 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
*/
duk_hstring *h_var;
- duk_int_t varmap_value; /* for storing/restoring the varmap binding for catch variable */
+ duk_int_t varmap_value; /* for storing/restoring the varmap binding for catch variable */
DUK_DDD(DUK_DDDPRINT("stack top at start of catch clause: %ld", (long) duk_get_top(thr)));
@@ -69886,19 +75202,17 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
h_var = comp_ctx->curr_token.str1;
DUK_ASSERT(h_var != NULL);
- duk_push_hstring(thr, h_var); /* keep in on valstack, use borrowed ref below */
+ duk_push_hstring(thr, h_var); /* keep in on valstack, use borrowed ref below */
if (comp_ctx->curr_func.is_strict &&
- ((h_var == DUK_HTHREAD_STRING_EVAL(thr)) ||
- (h_var == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)))) {
+ ((h_var == DUK_HTHREAD_STRING_EVAL(thr)) || (h_var == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)))) {
DUK_DDD(DUK_DDDPRINT("catch identifier 'eval' or 'arguments' in strict mode -> SyntaxError"));
goto syntax_error;
}
duk_dup_top(thr);
rc_varname = duk__getconst(comp_ctx);
- DUK_DDD(DUK_DDDPRINT("catch clause, rc_varname=0x%08lx (%ld)",
- (unsigned long) rc_varname, (long) rc_varname));
+ DUK_DDD(DUK_DDDPRINT("catch clause, rc_varname=0x%08lx (%ld)", (unsigned long) rc_varname, (long) rc_varname));
duk__advance(comp_ctx);
duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
@@ -69941,7 +75255,7 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
DUK_DDD(DUK_DDDPRINT("varmap before parsing catch clause: %!iT",
(duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
- duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
+ duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
if (varmap_value == -2) {
@@ -69961,8 +75275,7 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
DUK_DDD(DUK_DDDPRINT("varmap after restore catch clause: %!iT",
(duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
- duk__emit_op_only(comp_ctx,
- DUK_OP_ENDCATCH);
+ duk__emit_op_only(comp_ctx, DUK_OP_ENDCATCH);
/*
* XXX: for now, indicate that an expensive catch binding
@@ -69983,15 +75296,12 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
duk__advance(comp_ctx);
duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
- duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
+ duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
- duk__emit_abc(comp_ctx,
- DUK_OP_ENDFIN,
- reg_catch); /* rethrow */
+ duk__emit_abc(comp_ctx, DUK_OP_ENDFIN, reg_catch); /* rethrow */
}
- if (!(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) &&
- !(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY)) {
+ if (!(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) && !(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY)) {
/* must have catch and/or finally */
goto syntax_error;
}
@@ -70001,12 +75311,7 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
* constant 0) the DUK__CONST_MARKER flag will be set in rc_varname.
*/
- duk__patch_trycatch(comp_ctx,
- pc_ldconst,
- pc_trycatch,
- reg_catch,
- rc_varname,
- trycatch_flags);
+ duk__patch_trycatch(comp_ctx, pc_ldconst, pc_trycatch, reg_catch, rc_varname, trycatch_flags);
if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
DUK_ASSERT(pc_catch >= 0);
@@ -70024,8 +75329,9 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
comp_ctx->curr_func.catch_depth--;
return;
- syntax_error:
+syntax_error:
DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_TRY);
+ DUK_WO_NORETURN(return;);
}
DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
@@ -70036,30 +75342,31 @@ DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
if (comp_ctx->curr_func.is_strict) {
DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_WITH_IN_STRICT_MODE);
+ DUK_WO_NORETURN(return;);
}
comp_ctx->curr_func.catch_depth++;
- duk__advance(comp_ctx); /* eat 'with' */
+ duk__advance(comp_ctx); /* eat 'with' */
reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
duk__exprtop_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/, reg_catch);
- duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
+ comp_ctx->curr_func.allow_regexp_in_adv = 1;
+ duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); /* Allow RegExp as part of next stmt. */
pc_trycatch = duk__get_current_pc(comp_ctx);
trycatch_flags = DUK_BC_TRYCATCH_FLAG_WITH_BINDING;
duk__emit_a_bc(comp_ctx,
- DUK_OP_TRYCATCH | DUK__EMIT_FLAG_NO_SHUFFLE_A,
- (duk_regconst_t) trycatch_flags /*a*/,
- reg_catch /*bc*/);
- duk__emit_invalid(comp_ctx); /* catch jump */
- duk__emit_invalid(comp_ctx); /* finished jump */
+ DUK_OP_TRYCATCH | DUK__EMIT_FLAG_NO_SHUFFLE_A,
+ (duk_regconst_t) trycatch_flags /*a*/,
+ reg_catch /*bc*/);
+ duk__emit_invalid(comp_ctx); /* catch jump */
+ duk__emit_invalid(comp_ctx); /* finished jump */
duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
- duk__emit_op_only(comp_ctx,
- DUK_OP_ENDTRY);
+ duk__emit_op_only(comp_ctx, DUK_OP_ENDTRY);
pc_finished = duk__get_current_pc(comp_ctx);
@@ -70077,9 +75384,7 @@ DUK_LOCAL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t l
label_id = comp_ctx->curr_func.label_next++;
DUK_DDD(DUK_DDDPRINT("allocated new label id for label site: %ld", (long) label_id));
- duk__emit_bc(comp_ctx,
- DUK_OP_LABEL,
- (duk_regconst_t) label_id);
+ duk__emit_bc(comp_ctx, DUK_OP_LABEL, (duk_regconst_t) label_id);
duk__emit_invalid(comp_ctx);
duk__emit_invalid(comp_ctx);
@@ -70093,10 +75398,10 @@ DUK_LOCAL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t l
*/
DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem) {
duk_hthread *thr = comp_ctx->thr;
- duk_bool_t dir_prol_at_entry; /* directive prologue status at entry */
+ duk_bool_t dir_prol_at_entry; /* directive prologue status at entry */
duk_regconst_t temp_at_entry;
duk_size_t labels_len_at_entry;
- duk_int_t pc_at_entry; /* assumed to also be PC of "LABEL" */
+ duk_int_t pc_at_entry; /* assumed to also be PC of "LABEL" */
duk_int_t stmt_id;
duk_small_uint_t stmt_flags = 0;
duk_int_t label_id = -1;
@@ -70115,8 +75420,11 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
DUK_DDD(DUK_DDDPRINT("parsing a statement, stmt_id=%ld, temp_at_entry=%ld, labels_len_at_entry=%ld, "
"is_strict=%ld, in_directive_prologue=%ld, catch_depth=%ld",
- (long) stmt_id, (long) temp_at_entry, (long) labels_len_at_entry,
- (long) comp_ctx->curr_func.is_strict, (long) comp_ctx->curr_func.in_directive_prologue,
+ (long) stmt_id,
+ (long) temp_at_entry,
+ (long) labels_len_at_entry,
+ (long) comp_ctx->curr_func.is_strict,
+ (long) comp_ctx->curr_func.in_directive_prologue,
(long) comp_ctx->curr_func.catch_depth));
/* The directive prologue flag is cleared by default so that it is
@@ -70126,10 +75434,12 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
*/
comp_ctx->curr_func.in_directive_prologue = 0;
- retry_parse:
+retry_parse:
DUK_DDD(DUK_DDDPRINT("try stmt parse, stmt_id=%ld, label_id=%ld, allow_source_elem=%ld, catch_depth=%ld",
- (long) stmt_id, (long) label_id, (long) allow_source_elem,
+ (long) stmt_id,
+ (long) label_id,
+ (long) allow_source_elem,
(long) comp_ctx->curr_func.catch_depth));
/*
@@ -70138,15 +75448,11 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
*/
tok = comp_ctx->curr_token.t;
- if (tok == DUK_TOK_FOR || tok == DUK_TOK_DO || tok == DUK_TOK_WHILE ||
- tok == DUK_TOK_SWITCH) {
+ if (tok == DUK_TOK_FOR || tok == DUK_TOK_DO || tok == DUK_TOK_WHILE || tok == DUK_TOK_SWITCH) {
DUK_DDD(DUK_DDDPRINT("iteration/switch statement -> add empty label"));
label_id = duk__stmt_label_site(comp_ctx, label_id);
- duk__add_label(comp_ctx,
- DUK_HTHREAD_STRING_EMPTY_STRING(thr),
- pc_at_entry /*pc_label*/,
- label_id);
+ duk__add_label(comp_ctx, DUK_HTHREAD_STRING_EMPTY_STRING(thr), pc_at_entry /*pc_label*/, label_id);
}
/*
@@ -70169,11 +75475,12 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
*/
test_func_decl = allow_source_elem;
#if defined(DUK_USE_NONSTD_FUNC_STMT)
- /* Lenient: allow function declarations outside top level in
- * non-strict mode but reject them in strict mode.
+ /* Lenient: allow function declarations outside top level in both
+ * strict and non-strict modes. However, don't allow labelled
+ * function declarations in strict mode.
*/
- test_func_decl = test_func_decl || !comp_ctx->curr_func.is_strict;
-#endif /* DUK_USE_NONSTD_FUNC_STMT */
+ test_func_decl = test_func_decl || !comp_ctx->curr_func.is_strict || label_id < 0;
+#endif /* DUK_USE_NONSTD_FUNC_STMT */
/* Strict: never allow function declarations outside top level. */
if (test_func_decl) {
/* FunctionDeclaration: not strictly a statement but handled as such.
@@ -70195,7 +75502,7 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
top_before = duk_get_top(thr);
#endif
- duk__advance(comp_ctx); /* eat 'function' */
+ duk__advance(comp_ctx); /* eat 'function' */
fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_DECL | DUK__FUNC_FLAG_PUSHNAME_PASS1);
/* The value stack convention here is a bit odd: the function
@@ -70209,7 +75516,8 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
DUK_ASSERT(duk_get_top(thr) == top_before + 1);
#endif
DUK_DDD(DUK_DDDPRINT("register function declaration %!T in pass 1, fnum %ld",
- duk_get_tval(thr, -1), (long) fnum));
+ duk_get_tval(thr, -1),
+ (long) fnum));
n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
/* funcname is at index -1 */
duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n);
@@ -70226,16 +75534,17 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
break;
} else {
DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_STMT_NOT_ALLOWED);
+ DUK_WO_NORETURN(return;);
}
break;
}
case DUK_TOK_LCURLY: {
DUK_DDD(DUK_DDDPRINT("block statement"));
duk__advance(comp_ctx);
- duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
+ duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
if (label_id >= 0) {
- duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
+ duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
}
stmt_flags = 0;
break;
@@ -70262,7 +75571,7 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
DUK_DDD(DUK_DDDPRINT("if statement"));
duk__parse_if_stmt(comp_ctx, res);
if (label_id >= 0) {
- duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
+ duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
}
stmt_flags = 0;
break;
@@ -70279,19 +75588,15 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
*/
DUK_DDD(DUK_DDDPRINT("do statement"));
DUK_ASSERT(label_id >= 0);
- duk__update_label_flags(comp_ctx,
- label_id,
- DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
+ duk__update_label_flags(comp_ctx, label_id, DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
duk__parse_do_stmt(comp_ctx, res, pc_at_entry);
- stmt_flags = DUK__HAS_TERM | DUK__ALLOW_AUTO_SEMI_ALWAYS; /* DUK__ALLOW_AUTO_SEMI_ALWAYS workaround */
+ stmt_flags = DUK__HAS_TERM | DUK__ALLOW_AUTO_SEMI_ALWAYS; /* DUK__ALLOW_AUTO_SEMI_ALWAYS workaround */
break;
}
case DUK_TOK_WHILE: {
DUK_DDD(DUK_DDDPRINT("while statement"));
DUK_ASSERT(label_id >= 0);
- duk__update_label_flags(comp_ctx,
- label_id,
- DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
+ duk__update_label_flags(comp_ctx, label_id, DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
duk__parse_while_stmt(comp_ctx, res, pc_at_entry);
stmt_flags = 0;
break;
@@ -70306,9 +75611,7 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
*/
DUK_DDD(DUK_DDDPRINT("for/for-in statement"));
DUK_ASSERT(label_id >= 0);
- duk__update_label_flags(comp_ctx,
- label_id,
- DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
+ duk__update_label_flags(comp_ctx, label_id, DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
duk__parse_for_stmt(comp_ctx, res, pc_at_entry);
stmt_flags = 0;
break;
@@ -70331,7 +75634,7 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
comp_ctx->curr_func.with_depth++;
duk__parse_with_stmt(comp_ctx, res);
if (label_id >= 0) {
- duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
+ duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
}
comp_ctx->curr_func.with_depth--;
stmt_flags = 0;
@@ -70344,9 +75647,7 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
*/
DUK_DDD(DUK_DDDPRINT("switch statement"));
DUK_ASSERT(label_id >= 0);
- duk__update_label_flags(comp_ctx,
- label_id,
- DUK_LABEL_FLAG_ALLOW_BREAK); /* don't allow continue */
+ duk__update_label_flags(comp_ctx, label_id, DUK_LABEL_FLAG_ALLOW_BREAK); /* don't allow continue */
duk__parse_switch_stmt(comp_ctx, res, pc_at_entry);
stmt_flags = 0;
break;
@@ -70413,12 +75714,10 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
DUK_DDD(DUK_DDDPRINT("expression statement"));
duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
- single_token = (comp_ctx->curr_func.nud_count == 1 && /* one token */
- comp_ctx->curr_func.led_count == 0); /* no operators */
+ single_token = (comp_ctx->curr_func.nud_count == 1 && /* one token */
+ comp_ctx->curr_func.led_count == 0); /* no operators */
- if (single_token &&
- comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
- comp_ctx->curr_token.t == DUK_TOK_COLON) {
+ if (single_token && comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER && comp_ctx->curr_token.t == DUK_TOK_COLON) {
/*
* Detected label
*/
@@ -70432,17 +75731,13 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
h_lab = comp_ctx->prev_token.str1;
DUK_ASSERT(h_lab != NULL);
- DUK_DDD(DUK_DDDPRINT("explicit label site for label '%!O'",
- (duk_heaphdr *) h_lab));
+ DUK_DDD(DUK_DDDPRINT("explicit label site for label '%!O'", (duk_heaphdr *) h_lab));
- duk__advance(comp_ctx); /* eat colon */
+ duk__advance(comp_ctx); /* eat colon */
label_id = duk__stmt_label_site(comp_ctx, label_id);
- duk__add_label(comp_ctx,
- h_lab,
- pc_at_entry /*pc_label*/,
- label_id);
+ duk__add_label(comp_ctx, h_lab, pc_at_entry /*pc_label*/, label_id);
/* a statement following a label cannot be a source element
* (a function declaration).
@@ -70455,8 +75750,8 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
stmt_flags = 0;
- if (dir_prol_at_entry && /* still in prologue */
- single_token && /* single string token */
+ if (dir_prol_at_entry && /* still in prologue */
+ single_token && /* single string token */
comp_ctx->prev_token.t == DUK_TOK_STRING) {
/*
* Detected a directive
@@ -70486,32 +75781,35 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
*/
if (DUK_HSTRING_GET_BYTELEN(h_dir) == 10 &&
- DUK_STRNCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use strict", 10) == 0) {
+ DUK_STRCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use strict") == 0) {
#if defined(DUK_USE_STRICT_DECL)
DUK_DDD(DUK_DDDPRINT("use strict directive detected: strict flag %ld -> %ld",
- (long) comp_ctx->curr_func.is_strict, (long) 1));
+ (long) comp_ctx->curr_func.is_strict,
+ (long) 1));
comp_ctx->curr_func.is_strict = 1;
#else
DUK_DDD(DUK_DDDPRINT("use strict detected but strict declarations disabled, ignoring"));
#endif
} else if (DUK_HSTRING_GET_BYTELEN(h_dir) == 14 &&
- DUK_STRNCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use duk notail", 14) == 0) {
+ DUK_STRCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use duk notail") == 0) {
DUK_DDD(DUK_DDDPRINT("use duk notail directive detected: notail flag %ld -> %ld",
- (long) comp_ctx->curr_func.is_notail, (long) 1));
+ (long) comp_ctx->curr_func.is_notail,
+ (long) 1));
comp_ctx->curr_func.is_notail = 1;
} else {
DUK_DD(DUK_DDPRINT("unknown directive: '%!O', ignoring but not terminating "
- "directive prologue", (duk_hobject *) h_dir));
+ "directive prologue",
+ (duk_hobject *) h_dir));
}
}
} else {
DUK_DDD(DUK_DDDPRINT("non-directive expression statement or no longer in prologue; "
"prologue terminated if still active"));
- }
+ }
stmt_flags |= DUK__HAS_VAL | DUK__HAS_TERM;
}
- } /* end switch (tok) */
+ } /* end switch (tok) */
/*
* Statement value handling.
@@ -70563,6 +75861,7 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
"even though no lineterm present before next token)"));
} else {
DUK_ERROR_SYNTAX(thr, DUK_STR_UNTERMINATED_STMT);
+ DUK_WO_NORETURN(return;);
}
}
} else {
@@ -70586,9 +75885,7 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
*/
if (label_id >= 0) {
- duk__emit_bc(comp_ctx,
- DUK_OP_ENDLABEL,
- (duk_regconst_t) label_id);
+ duk__emit_bc(comp_ctx, DUK_OP_ENDLABEL, (duk_regconst_t) label_id);
}
DUK__SETTEMP(comp_ctx, temp_at_entry);
@@ -70611,7 +75908,10 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
* (EOF or closing brace).
*/
-DUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof) {
+DUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx,
+ duk_bool_t allow_source_elem,
+ duk_bool_t expect_eof,
+ duk_bool_t regexp_after) {
duk_hthread *thr = comp_ctx->thr;
duk_ivalue res_alloc;
duk_ivalue *res = &res_alloc;
@@ -70625,7 +75925,7 @@ DUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_sou
* for nested functions (which may occur inside expressions).
*/
- DUK_MEMZERO(&res_alloc, sizeof(res_alloc));
+ duk_memzero(&res_alloc, sizeof(res_alloc));
res->t = DUK_IVAL_PLAIN;
res->x1.t = DUK_ISPEC_VALUE;
res->x1.valstack_idx = duk_get_top(thr);
@@ -70659,6 +75959,15 @@ DUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_sou
duk__parse_stmt(comp_ctx, res, allow_source_elem);
}
+ /* RegExp is allowed / not allowed depending on context. For function
+ * declarations RegExp is allowed because it follows a function
+ * declaration statement and may appear as part of the next statement.
+ * For function expressions RegExp is not allowed, and it's possible
+ * to do something like '(function () {} / 123)'.
+ */
+ if (regexp_after) {
+ comp_ctx->curr_func.allow_regexp_in_adv = 1;
+ }
duk__advance(comp_ctx);
/* Tear down state. */
@@ -70768,7 +76077,7 @@ DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ct
/* only functions can have arguments */
DUK_ASSERT(comp_ctx->curr_func.is_function);
- duk_push_uarridx(thr, i); /* -> [ ... name index ] */
+ duk_push_uarridx(thr, i); /* -> [ ... name index ] */
duk_put_prop(thr, comp_ctx->curr_func.varmap_idx); /* -> [ ... ] */
/* no code needs to be emitted, the regs already have values */
@@ -70804,16 +76113,15 @@ DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ct
*/
num_decls = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
- DUK_DDD(DUK_DDDPRINT("num_decls=%ld -> %!T",
- (long) num_decls,
- (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.decls_idx)));
+ DUK_DDD(
+ DUK_DDDPRINT("num_decls=%ld -> %!T", (long) num_decls, (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.decls_idx)));
for (i = 0; i < num_decls; i += 2) {
duk_int_t decl_type;
duk_int_t fnum;
- duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1); /* decl type */
+ duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1); /* decl type */
decl_type = duk_to_int(thr, -1);
- fnum = decl_type >> 8; /* XXX: macros */
+ fnum = decl_type >> 8; /* XXX: macros */
decl_type = decl_type & 0xff;
duk_pop(thr);
@@ -70821,7 +76129,7 @@ DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ct
continue;
}
- duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i); /* decl name */
+ duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i); /* decl name */
/* XXX: spilling */
if (comp_ctx->curr_func.is_function) {
@@ -70831,18 +76139,12 @@ DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ct
/* shadowed; update value */
duk_dup_top(thr);
duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
- reg_bind = duk_to_int(thr, -1); /* [ ... name reg_bind ] */
- duk__emit_a_bc(comp_ctx,
- DUK_OP_CLOSURE,
- reg_bind,
- (duk_regconst_t) fnum);
+ reg_bind = duk_to_int(thr, -1); /* [ ... name reg_bind ] */
+ duk__emit_a_bc(comp_ctx, DUK_OP_CLOSURE, reg_bind, (duk_regconst_t) fnum);
} else {
/* function: always register bound */
reg_bind = DUK__ALLOCTEMP(comp_ctx);
- duk__emit_a_bc(comp_ctx,
- DUK_OP_CLOSURE,
- reg_bind,
- (duk_regconst_t) fnum);
+ duk__emit_a_bc(comp_ctx, DUK_OP_CLOSURE, reg_bind, (duk_regconst_t) fnum);
duk_push_int(thr, (duk_int_t) reg_bind);
}
} else {
@@ -70859,14 +76161,9 @@ DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ct
rc_name = duk__getconst(comp_ctx);
duk_push_null(thr);
- duk__emit_a_bc(comp_ctx,
- DUK_OP_CLOSURE,
- reg_temp,
- (duk_regconst_t) fnum);
+ duk__emit_a_bc(comp_ctx, DUK_OP_CLOSURE, reg_temp, (duk_regconst_t) fnum);
- declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
- DUK_PROPDESC_FLAG_ENUMERABLE |
- DUK_BC_DECLVAR_FLAG_FUNC_DECL;
+ declvar_flags = DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE | DUK_BC_DECLVAR_FLAG_FUNC_DECL;
if (configurable_bindings) {
declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
@@ -70878,7 +76175,7 @@ DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ct
rc_name /*name*/,
reg_temp /*value*/);
- DUK__SETTEMP(comp_ctx, reg_temp); /* forget temp */
+ DUK__SETTEMP(comp_ctx, reg_temp); /* forget temp */
}
DUK_DDD(DUK_DDDPRINT("function declaration to varmap: %!T -> %!T",
@@ -70888,7 +76185,7 @@ DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ct
#if defined(DUK_USE_FASTINT)
DUK_ASSERT(DUK_TVAL_IS_NULL(duk_get_tval(thr, -1)) || DUK_TVAL_IS_FASTINT(duk_get_tval(thr, -1)));
#endif
- duk_put_prop(thr, comp_ctx->curr_func.varmap_idx); /* [ ... name reg/null ] -> [ ... ] */
+ duk_put_prop(thr, comp_ctx->curr_func.varmap_idx); /* [ ... name reg/null ] -> [ ... ] */
}
/*
@@ -70915,7 +76212,7 @@ DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ct
for (i = 0; i < num_decls; i += 2) {
duk_int_t decl_type;
- duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1); /* decl type */
+ duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1); /* decl type */
decl_type = duk_to_int(thr, -1);
decl_type = decl_type & 0xff;
duk_pop(thr);
@@ -70924,16 +76221,15 @@ DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ct
continue;
}
- duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i); /* decl name */
+ duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i); /* decl name */
if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
/* shadowed, ignore */
} else {
- duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i); /* decl name */
+ duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i); /* decl name */
h_name = duk_known_hstring(thr, -1);
- if (h_name == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) &&
- !comp_ctx->curr_func.is_arguments_shadowed) {
+ if (h_name == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) && !comp_ctx->curr_func.is_arguments_shadowed) {
/* E5 Section steps 7-8 */
DUK_DDD(DUK_DDDPRINT("'arguments' not shadowed by a function declaration, "
"but appears as a variable declaration -> treat as "
@@ -70952,8 +76248,7 @@ DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ct
rc_name = duk__getconst(comp_ctx);
duk_push_null(thr);
- declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
- DUK_PROPDESC_FLAG_ENUMERABLE;
+ declvar_flags = DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE;
if (configurable_bindings) {
declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
}
@@ -70965,7 +76260,7 @@ DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ct
0 /*value*/);
}
- duk_put_prop(thr, comp_ctx->curr_func.varmap_idx); /* [ ... name reg/null ] -> [ ... ] */
+ duk_put_prop(thr, comp_ctx->curr_func.varmap_idx); /* [ ... name reg/null ] -> [ ... ] */
}
}
@@ -70980,15 +76275,13 @@ DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ct
DUK_ASSERT_TOP(thr, entry_top);
return;
- error_outofregs:
+error_outofregs:
DUK_ERROR_RANGE(thr, DUK_STR_REG_LIMIT);
- DUK_UNREACHABLE();
- return;
+ DUK_WO_NORETURN(return;);
- error_argname:
+error_argname:
DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARG_NAME);
- DUK_UNREACHABLE();
- return;
+ DUK_WO_NORETURN(return;);
}
/*
@@ -71025,7 +76318,11 @@ DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ct
* token (EOF or closing brace).
*/
-DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_small_int_t expect_token) {
+DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx,
+ duk_bool_t expect_eof,
+ duk_bool_t implicit_return_value,
+ duk_bool_t regexp_after,
+ duk_small_int_t expect_token) {
duk_compiler_func *func;
duk_hthread *thr;
duk_regconst_t reg_stmt_value = -1;
@@ -71097,7 +76394,9 @@ DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expec
func->max_line = 0;
#endif
- /* duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp literal" mode with current strictness */
+ /* duk__parse_stmts() expects curr_tok to be set; parse in "allow
+ * regexp literal" mode with current strictness.
+ */
if (expect_token >= 0) {
/* Eating a left curly; regexp mode is allowed by left curly
* based on duk__token_lbp[] automatically.
@@ -71115,8 +76414,9 @@ DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expec
DUK_DDD(DUK_DDDPRINT("begin 1st pass"));
duk__parse_stmts(comp_ctx,
- 1, /* allow source elements */
- expect_eof); /* expect EOF instead of } */
+ 1, /* allow source elements */
+ expect_eof, /* expect EOF instead of } */
+ regexp_after); /* regexp after */
DUK_DDD(DUK_DDDPRINT("end 1st pass"));
/*
@@ -71144,8 +76444,8 @@ DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expec
DUK_DDD(DUK_DDDPRINT("rewind lexer"));
DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
- comp_ctx->curr_token.t = 0; /* this is needed for regexp mode */
- comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
+ comp_ctx->curr_token.t = 0; /* this is needed for regexp mode */
+ comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
duk__advance(comp_ctx);
/*
@@ -71166,8 +76466,7 @@ DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expec
/* must be able to emit code, alloc consts, etc. */
- duk__init_varmap_and_prologue_for_pass2(comp_ctx,
- (implicit_return_value ? &reg_stmt_value : NULL));
+ duk__init_varmap_and_prologue_for_pass2(comp_ctx, (implicit_return_value ? &reg_stmt_value : NULL));
func->reg_stmt_value = reg_stmt_value;
temp_first = DUK__GETTEMP(comp_ctx);
@@ -71215,15 +76514,14 @@ DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expec
if (implicit_return_value) {
/* Default implicit return value. */
- duk__emit_bc(comp_ctx,
- DUK_OP_LDUNDEF,
- 0);
+ duk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, 0);
}
DUK_DDD(DUK_DDDPRINT("begin 2nd pass"));
duk__parse_stmts(comp_ctx,
- 1, /* allow source elements */
- expect_eof); /* expect EOF instead of } */
+ 1, /* allow source elements */
+ expect_eof, /* expect EOF instead of } */
+ regexp_after); /* regexp after */
DUK_DDD(DUK_DDDPRINT("end 2nd pass"));
duk__update_lineinfo_currtoken(comp_ctx);
@@ -71236,6 +76534,7 @@ DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expec
/* Should never happen but avoid infinite loop just in case. */
DUK_D(DUK_DPRINT("more than 3 compile passes needed, should never happen"));
DUK_ERROR_INTERNAL(thr);
+ DUK_WO_NORETURN(return;);
}
DUK_D(DUK_DPRINT("need additional round to compile function, round now %d", (int) compile_round));
}
@@ -71277,8 +76576,9 @@ DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expec
DUK__RECURSION_DECREASE(comp_ctx, thr);
return;
- error_funcname:
+error_funcname:
DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FUNC_NAME);
+ DUK_WO_NORETURN(return;);
}
/*
@@ -71327,18 +76627,18 @@ DUK_LOCAL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx) {
if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
DUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER);
+ DUK_WO_NORETURN(return;);
}
DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER);
DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
- DUK_DDD(DUK_DDDPRINT("formal argument: %!O",
- (duk_heaphdr *) comp_ctx->curr_token.str1));
+ DUK_DDD(DUK_DDDPRINT("formal argument: %!O", (duk_heaphdr *) comp_ctx->curr_token.str1));
/* XXX: append primitive */
duk_push_hstring(thr, comp_ctx->curr_token.str1);
n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.argnames_idx);
duk_put_prop_index(thr, comp_ctx->curr_func.argnames_idx, n);
- duk__advance(comp_ctx); /* eat identifier */
+ duk__advance(comp_ctx); /* eat identifier */
}
}
@@ -71386,22 +76686,23 @@ DUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_ui
if (flags & DUK__FUNC_FLAG_GETSET) {
/* PropertyName -> IdentifierName | StringLiteral | NumericLiteral */
if (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t == DUK_TOK_STRING) {
- duk_push_hstring(thr, tok->str1); /* keep in valstack */
+ duk_push_hstring(thr, tok->str1); /* keep in valstack */
} else if (tok->t == DUK_TOK_NUMBER) {
duk_push_number(thr, tok->num);
duk_to_string(thr, -1);
} else {
DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_GETSET_NAME);
+ DUK_WO_NORETURN(return;);
}
- comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1); /* borrowed reference */
+ comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1); /* borrowed reference */
} else {
/* Function name is an Identifier (not IdentifierName), but we get
* the raw name (not recognizing keywords) here and perform the name
* checks only after pass 1.
*/
if (tok->t_nores == DUK_TOK_IDENTIFIER) {
- duk_push_hstring(thr, tok->str1); /* keep in valstack */
- comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1); /* borrowed reference */
+ duk_push_hstring(thr, tok->str1); /* keep in valstack */
+ comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1); /* borrowed reference */
} else {
/* valstack will be unbalanced, which is OK */
DUK_ASSERT((flags & DUK__FUNC_FLAG_GETSET) == 0);
@@ -71409,12 +76710,12 @@ DUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_ui
no_advance = 1;
if (flags & DUK__FUNC_FLAG_DECL) {
DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_NAME_REQUIRED);
+ DUK_WO_NORETURN(return;);
}
}
}
- DUK_DD(DUK_DDPRINT("function name: %!O",
- (duk_heaphdr *) comp_ctx->curr_func.h_name));
+ DUK_DD(DUK_DDPRINT("function name: %!O", (duk_heaphdr *) comp_ctx->curr_func.h_name));
if (!no_advance) {
duk__advance(comp_ctx);
@@ -71440,16 +76741,17 @@ DUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_ui
*/
duk__parse_func_body(comp_ctx,
- 0, /* expect_eof */
- 0, /* implicit_return_value */
- DUK_TOK_LCURLY); /* expect_token */
+ 0, /* expect_eof */
+ 0, /* implicit_return_value */
+ flags & DUK__FUNC_FLAG_DECL, /* regexp_after */
+ DUK_TOK_LCURLY); /* expect_token */
/*
* Convert duk_compiler_func to a function template and add it
* to the parent function table.
*/
- duk__convert_to_func_template(comp_ctx); /* -> [ ... func ] */
+ duk__convert_to_func_template(comp_ctx); /* -> [ ... func ] */
}
/* Parse an inner function, adding the function template to the current function's
@@ -71487,13 +76789,23 @@ DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_sm
lex_pt.line = duk_to_int(thr, -1);
duk_pop(thr);
- DUK_DDD(DUK_DDDPRINT("second pass of an inner func, skip the function, reparse closing brace; lex offset=%ld, line=%ld",
- (long) lex_pt.offset, (long) lex_pt.line));
+ DUK_DDD(
+ DUK_DDDPRINT("second pass of an inner func, skip the function, reparse closing brace; lex offset=%ld, line=%ld",
+ (long) lex_pt.offset,
+ (long) lex_pt.line));
DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
- comp_ctx->curr_token.t = 0; /* this is needed for regexp mode */
- comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
+ comp_ctx->curr_token.t = 0; /* this is needed for regexp mode */
+ comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
duk__advance(comp_ctx);
+
+ /* RegExp is not allowed after a function expression, e.g. in
+ * (function () {} / 123). A RegExp *is* allowed after a
+ * function declaration!
+ */
+ if (flags & DUK__FUNC_FLAG_DECL) {
+ comp_ctx->curr_func.allow_regexp_in_adv = 1;
+ }
duk__advance_expect(comp_ctx, DUK_TOK_RCURLY);
return fnum;
@@ -71506,11 +76818,12 @@ DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_sm
entry_top = duk_get_top(thr);
DUK_DDD(DUK_DDDPRINT("before func: entry_top=%ld, curr_tok.start_offset=%ld",
- (long) entry_top, (long) comp_ctx->curr_token.start_offset));
+ (long) entry_top,
+ (long) comp_ctx->curr_token.start_offset));
- DUK_MEMCPY(&old_func, &comp_ctx->curr_func, sizeof(duk_compiler_func));
+ duk_memcpy(&old_func, &comp_ctx->curr_func, sizeof(duk_compiler_func));
- DUK_MEMZERO(&comp_ctx->curr_func, sizeof(duk_compiler_func));
+ duk_memzero(&comp_ctx->curr_func, sizeof(duk_compiler_func));
duk__init_func_valstack_slots(comp_ctx);
DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
@@ -71526,24 +76839,25 @@ DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_sm
DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
comp_ctx->curr_func.is_setget = ((flags & DUK__FUNC_FLAG_GETSET) != 0);
- comp_ctx->curr_func.is_namebinding = !(flags & (DUK__FUNC_FLAG_GETSET |
- DUK__FUNC_FLAG_METDEF |
- DUK__FUNC_FLAG_DECL)); /* no name binding for: declarations, objlit getset, objlit method def */
- comp_ctx->curr_func.is_constructable = !(flags & (DUK__FUNC_FLAG_GETSET |
- DUK__FUNC_FLAG_METDEF)); /* not constructable: objlit getset, objlit method def */
+ comp_ctx->curr_func.is_namebinding =
+ !(flags & (DUK__FUNC_FLAG_GETSET | DUK__FUNC_FLAG_METDEF |
+ DUK__FUNC_FLAG_DECL)); /* no name binding for: declarations, objlit getset, objlit method def */
+ comp_ctx->curr_func.is_constructable =
+ !(flags & (DUK__FUNC_FLAG_GETSET | DUK__FUNC_FLAG_METDEF)); /* not constructable: objlit getset, objlit method def */
/*
* Parse inner function
*/
- duk__parse_func_like_raw(comp_ctx, flags); /* pushes function template */
+ duk__parse_func_like_raw(comp_ctx, flags); /* pushes function template */
/* prev_token.start_offset points to the closing brace here; when skipping
* we're going to reparse the closing brace to ensure semicolon insertion
* etc work as expected.
*/
DUK_DDD(DUK_DDDPRINT("after func: prev_tok.start_offset=%ld, curr_tok.start_offset=%ld",
- (long) comp_ctx->prev_token.start_offset, (long) comp_ctx->curr_token.start_offset));
+ (long) comp_ctx->prev_token.start_offset,
+ (long) comp_ctx->curr_token.start_offset));
DUK_ASSERT(comp_ctx->lex.input[comp_ctx->prev_token.start_offset] == (duk_uint8_t) DUK_ASC_RCURLY);
/* XXX: append primitive */
@@ -71552,6 +76866,7 @@ DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_sm
if (fnum > DUK__MAX_FUNCS) {
DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_FUNC_LIMIT);
+ DUK_WO_NORETURN(return 0;);
}
/* array writes autoincrement length */
@@ -71576,7 +76891,7 @@ DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_sm
} else {
duk_set_top(thr, entry_top);
}
- DUK_MEMCPY((void *) &comp_ctx->curr_func, (void *) &old_func, sizeof(duk_compiler_func));
+ duk_memcpy((void *) &comp_ctx->curr_func, (void *) &old_func, sizeof(duk_compiler_func));
return fnum;
}
@@ -71585,7 +76900,7 @@ DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_sm
* Compile input string into an executable function template without
* arguments.
*
- * The string is parsed as the "Program" production of Ecmascript E5.
+ * The string is parsed as the "Program" production of ECMAScript E5.
* Compilation context can be either global code or eval code (see E5
* Sections 14 and 15.1.2.1).
*
@@ -71628,7 +76943,7 @@ DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_hthread *thr, void *udata) {
is_strict = (flags & DUK_COMPILE_STRICT ? 1 : 0);
is_funcexpr = (flags & DUK_COMPILE_FUNCEXPR ? 1 : 0);
- h_filename = duk_get_hstring(thr, -1); /* may be undefined */
+ h_filename = duk_get_hstring(thr, -1); /* may be undefined */
/*
* Init compiler and lexer contexts
@@ -71646,11 +76961,11 @@ DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_hthread *thr, void *udata) {
duk_require_stack(thr, DUK__COMPILE_ENTRY_SLOTS);
- duk_push_dynamic_buffer(thr, 0); /* entry_top + 0 */
- duk_push_undefined(thr); /* entry_top + 1 */
- duk_push_undefined(thr); /* entry_top + 2 */
- duk_push_undefined(thr); /* entry_top + 3 */
- duk_push_undefined(thr); /* entry_top + 4 */
+ duk_push_dynamic_buffer(thr, 0); /* entry_top + 0 */
+ duk_push_undefined(thr); /* entry_top + 1 */
+ duk_push_undefined(thr); /* entry_top + 2 */
+ duk_push_undefined(thr); /* entry_top + 3 */
+ duk_push_undefined(thr); /* entry_top + 4 */
comp_ctx->thr = thr;
comp_ctx->h_filename = h_filename;
@@ -71674,8 +76989,8 @@ DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_hthread *thr, void *udata) {
lex_pt->offset = 0;
lex_pt->line = 1;
- DUK_LEXER_SETPOINT(&comp_ctx->lex, lex_pt); /* fills window */
- comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
+ DUK_LEXER_SETPOINT(&comp_ctx->lex, lex_pt); /* fills window */
+ comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
/*
* Initialize function state for a zero-argument function
@@ -71691,8 +77006,7 @@ DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_hthread *thr, void *udata) {
*/
DUK_ASSERT(func->h_name == NULL);
} else {
- duk_push_hstring_stridx(thr, (is_eval ? DUK_STRIDX_EVAL :
- DUK_STRIDX_GLOBAL));
+ duk_push_hstring_stridx(thr, (is_eval ? DUK_STRIDX_EVAL : DUK_STRIDX_GLOBAL));
func->h_name = duk_get_hstring(thr, -1);
}
@@ -71712,7 +77026,7 @@ DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_hthread *thr, void *udata) {
func->is_namebinding = 1;
func->is_constructable = 1;
- duk__advance(comp_ctx); /* init 'curr_token' */
+ duk__advance(comp_ctx); /* init 'curr_token' */
duk__advance_expect(comp_ctx, DUK_TOK_FUNCTION);
(void) duk__parse_func_like_raw(comp_ctx, 0 /*flags*/);
} else {
@@ -71724,9 +77038,10 @@ DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_hthread *thr, void *udata) {
DUK_ASSERT(func->is_constructable == 0);
duk__parse_func_body(comp_ctx,
- 1, /* expect_eof */
- 1, /* implicit_return_value */
- -1); /* expect_token */
+ 1, /* expect_eof */
+ 1, /* implicit_return_value */
+ 1, /* regexp_after (does not matter) */
+ -1); /* expect_token */
}
/*
@@ -71753,23 +77068,24 @@ DUK_INTERNAL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer
DUK_ASSERT(src_buffer != NULL);
/* preinitialize lexer state partially */
- DUK_MEMZERO(&comp_stk, sizeof(comp_stk));
+ duk_memzero(&comp_stk, sizeof(comp_stk));
comp_stk.flags = flags;
DUK_LEXER_INITCTX(&comp_stk.comp_ctx_alloc.lex);
comp_stk.comp_ctx_alloc.lex.input = src_buffer;
comp_stk.comp_ctx_alloc.lex.input_length = src_length;
- comp_stk.comp_ctx_alloc.lex.flags = flags; /* Forward flags directly for now. */
+ comp_stk.comp_ctx_alloc.lex.flags = flags; /* Forward flags directly for now. */
/* [ ... filename ] */
prev_ctx = thr->compile_ctx;
- thr->compile_ctx = &comp_stk.comp_ctx_alloc; /* for duk_error_augment.c */
+ thr->compile_ctx = &comp_stk.comp_ctx_alloc; /* for duk_error_augment.c */
safe_rc = duk_safe_call(thr, duk__js_compile_raw, (void *) &comp_stk /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
- thr->compile_ctx = prev_ctx; /* must restore reliably before returning */
+ thr->compile_ctx = prev_ctx; /* must restore reliably before returning */
if (safe_rc != DUK_EXEC_SUCCESS) {
DUK_D(DUK_DPRINT("compilation failed: %!T", duk_get_tval(thr, -1)));
(void) duk_throw(thr);
+ DUK_WO_NORETURN(return;);
}
/* [ ... template ] */
@@ -71860,7 +77176,7 @@ DUK_INTERNAL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer
#undef DUK__TOKEN_LBP_FLAG_UNUSED
#undef DUK__TOKEN_LBP_GET_BP
/*
- * Ecmascript bytecode executor.
+ * ECMAScript bytecode executor.
*/
/* #include duk_internal.h -> already included */
@@ -71875,19 +77191,11 @@ DUK_LOCAL_DECL void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, du
* Misc helpers.
*/
-/* Forced inline declaration, only applied for performance oriented build. */
-#if defined(DUK_USE_EXEC_PREFER_SIZE)
-#define DUK__INLINE_PERF
-#define DUK__NOINLINE_PERF
-#else
-#define DUK__INLINE_PERF DUK_ALWAYS_INLINE
-#define DUK__NOINLINE_PERF DUK_NOINLINE
-#endif
-
/* Replace value stack top to value at 'tv_ptr'. Optimize for
* performance by only applying the net refcount change.
*/
-#define DUK__REPLACE_TO_TVPTR(thr,tv_ptr) do { \
+#define DUK__REPLACE_TO_TVPTR(thr, tv_ptr) \
+ do { \
duk_hthread *duk__thr; \
duk_tval *duk__tvsrc; \
duk_tval *duk__tvdst; \
@@ -71897,13 +77205,13 @@ DUK_LOCAL_DECL void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, du
duk__tvdst = (tv_ptr); \
DUK_TVAL_SET_TVAL(&duk__tvtmp, duk__tvdst); \
DUK_TVAL_SET_TVAL(duk__tvdst, duk__tvsrc); \
- DUK_TVAL_SET_UNDEFINED(duk__tvsrc); /* value stack init policy */ \
+ DUK_TVAL_SET_UNDEFINED(duk__tvsrc); /* value stack init policy */ \
duk__thr->valstack_top = duk__tvsrc; \
DUK_TVAL_DECREF(duk__thr, &duk__tvtmp); \
} while (0)
/* XXX: candidate of being an internal shared API call */
-#if 0 /* unused */
+#if 0 /* unused */
DUK_LOCAL void duk__push_tvals_incref_only(duk_hthread *thr, duk_tval *tv_src, duk_small_uint_fast_t count) {
duk_tval *tv_dst;
duk_size_t copy_size;
@@ -71911,7 +77219,7 @@ DUK_LOCAL void duk__push_tvals_incref_only(duk_hthread *thr, duk_tval *tv_src, d
tv_dst = thr->valstack_top;
copy_size = sizeof(duk_tval) * count;
- DUK_MEMCPY((void *) tv_dst, (const void *) tv_src, copy_size);
+ duk_memcpy((void *) tv_dst, (const void *) tv_src, copy_size);
for (i = 0; i < count; i++) {
DUK_TVAL_INCREF(thr, tv_dst);
tv_dst++;
@@ -71935,17 +77243,20 @@ DUK_LOCAL void duk__push_tvals_incref_only(duk_hthread *thr, duk_tval *tv_src, d
* possible.
*/
-DUK_LOCAL DUK__INLINE_PERF duk_double_t duk__compute_mod(duk_double_t d1, duk_double_t d2) {
+DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF duk_double_t duk__compute_mod(duk_double_t d1, duk_double_t d2) {
return (duk_double_t) duk_js_arith_mod((double) d1, (double) d2);
}
#if defined(DUK_USE_ES7_EXP_OPERATOR)
-DUK_LOCAL DUK__INLINE_PERF duk_double_t duk__compute_exp(duk_double_t d1, duk_double_t d2) {
+DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF duk_double_t duk__compute_exp(duk_double_t d1, duk_double_t d2) {
return (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);
}
#endif
-DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z) {
+DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_arith_add(duk_hthread *thr,
+ duk_tval *tv_x,
+ duk_tval *tv_y,
+ duk_small_uint_fast_t idx_z) {
/*
* Addition operator is different from other arithmetic
* operations in that it also provides string concatenation.
@@ -71965,9 +77276,9 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv
duk_double_union du;
DUK_ASSERT(thr != NULL);
- DUK_ASSERT(tv_x != NULL); /* may be reg or const */
- DUK_ASSERT(tv_y != NULL); /* may be reg or const */
- DUK_ASSERT_DISABLE(idx_z >= 0); /* unsigned */
+ DUK_ASSERT(tv_x != NULL); /* may be reg or const */
+ DUK_ASSERT(tv_y != NULL); /* may be reg or const */
+ DUK_ASSERT_DISABLE(idx_z >= 0); /* unsigned */
DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
/*
@@ -71990,14 +77301,14 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv
v3_hi = (duk_int32_t) (v3 >> 32);
if (DUK_LIKELY(v3_hi >= DUK_I64_CONSTANT(-0x8000) && v3_hi <= DUK_I64_CONSTANT(0x7fff))) {
tv_z = thr->valstack_bottom + idx_z;
- DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3); /* side effects */
+ DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3); /* side effects */
return;
} else {
/* overflow, fall through */
;
}
}
-#endif /* DUK_USE_FASTINT */
+#endif /* DUK_USE_FASTINT */
if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
#if !defined(DUK_USE_EXEC_PREFER_SIZE)
@@ -72006,14 +77317,14 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv
du.d = DUK_TVAL_GET_NUMBER(tv_x) + DUK_TVAL_GET_NUMBER(tv_y);
#if defined(DUK_USE_EXEC_PREFER_SIZE)
- duk_push_number(thr, du.d); /* will NaN normalize result */
+ duk_push_number(thr, du.d); /* will NaN normalize result */
duk_replace(thr, (duk_idx_t) idx_z);
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
tv_z = thr->valstack_bottom + idx_z;
- DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d); /* side effects */
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+ DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d); /* side effects */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
return;
}
@@ -72023,7 +77334,7 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv
duk_push_tval(thr, tv_x);
duk_push_tval(thr, tv_y);
- duk_to_primitive(thr, -2, DUK_HINT_NONE); /* side effects -> don't use tv_x, tv_y after */
+ duk_to_primitive(thr, -2, DUK_HINT_NONE); /* side effects -> don't use tv_x, tv_y after */
duk_to_primitive(thr, -1, DUK_HINT_NONE);
/* Since Duktape 2.x plain buffers are treated like ArrayBuffer. */
@@ -72034,7 +77345,7 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv
* in duk_concat_2() which also fails with TypeError so no
* explicit check is needed.
*/
- duk_concat_2(thr); /* [... s1 s2] -> [... s1+s2] */
+ duk_concat_2(thr); /* [... s1 s2] -> [... s1+s2] */
} else {
duk_double_t d1, d2;
@@ -72047,12 +77358,16 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv
du.d = d1 + d2;
duk_pop_2_unsafe(thr);
- duk_push_number(thr, du.d); /* will NaN normalize result */
+ duk_push_number(thr, du.d); /* will NaN normalize result */
}
- duk_replace(thr, (duk_idx_t) idx_z); /* side effects */
+ duk_replace(thr, (duk_idx_t) idx_z); /* side effects */
}
-DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_uint_fast_t idx_z, duk_small_uint_fast_t opcode) {
+DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_arith_binary_op(duk_hthread *thr,
+ duk_tval *tv_x,
+ duk_tval *tv_y,
+ duk_uint_fast_t idx_z,
+ duk_small_uint_fast_t opcode) {
/*
* Arithmetic operations other than '+' have number-only semantics
* and are implemented here. The separate switch-case here means a
@@ -72069,12 +77384,12 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_binary_op(duk_hthread *thr, duk_tv
#endif
DUK_ASSERT(thr != NULL);
- DUK_ASSERT(tv_x != NULL); /* may be reg or const */
- DUK_ASSERT(tv_y != NULL); /* may be reg or const */
- DUK_ASSERT_DISABLE(idx_z >= 0); /* unsigned */
+ DUK_ASSERT(tv_x != NULL); /* may be reg or const */
+ DUK_ASSERT(tv_y != NULL); /* may be reg or const */
+ DUK_ASSERT_DISABLE(idx_z >= 0); /* unsigned */
DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
- opcode_shifted = opcode >> 2; /* Get base opcode without reg/const modifiers. */
+ opcode_shifted = opcode >> 2; /* Get base opcode without reg/const modifiers. */
#if defined(DUK_USE_FASTINT)
if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
@@ -72141,13 +77456,13 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_binary_op(duk_hthread *thr, duk_tv
v3_hi = (duk_int32_t) (v3 >> 32);
if (DUK_LIKELY(v3_hi >= DUK_I64_CONSTANT(-0x8000) && v3_hi <= DUK_I64_CONSTANT(0x7fff))) {
tv_z = thr->valstack_bottom + idx_z;
- DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3); /* side effects */
+ DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3); /* side effects */
return;
}
/* fall through if overflow etc */
}
- skip_fastint:
-#endif /* DUK_USE_FASTINT */
+skip_fastint:
+#endif /* DUK_USE_FASTINT */
if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
/* fast path */
@@ -72156,7 +77471,7 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_binary_op(duk_hthread *thr, duk_tv
} else {
duk_push_tval(thr, tv_x);
duk_push_tval(thr, tv_y);
- d1 = duk_to_number_m2(thr); /* side effects */
+ d1 = duk_to_number_m2(thr); /* side effects */
d2 = duk_to_number_m1(thr);
DUK_ASSERT(duk_is_number(thr, -2));
DUK_ASSERT(duk_is_number(thr, -1));
@@ -72175,7 +77490,10 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_binary_op(duk_hthread *thr, duk_tv
break;
}
case DUK_OP_DIV >> 2: {
- du.d = d1 / d2;
+ /* Division-by-zero is undefined behavior, so
+ * rely on a helper.
+ */
+ du.d = duk_double_div(d1, d2);
break;
}
case DUK_OP_MOD >> 2: {
@@ -72190,24 +77508,28 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_binary_op(duk_hthread *thr, duk_tv
#endif
default: {
DUK_UNREACHABLE();
- du.d = DUK_DOUBLE_NAN; /* should not happen */
+ du.d = DUK_DOUBLE_NAN; /* should not happen */
break;
}
}
#if defined(DUK_USE_EXEC_PREFER_SIZE)
- duk_push_number(thr, du.d); /* will NaN normalize result */
+ duk_push_number(thr, du.d); /* will NaN normalize result */
duk_replace(thr, (duk_idx_t) idx_z);
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
/* important to use normalized NaN with 8-byte tagged types */
DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
tv_z = thr->valstack_bottom + idx_z;
- DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d); /* side effects */
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+ DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d); /* side effects */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
}
-DUK_LOCAL DUK__INLINE_PERF void duk__vm_bitwise_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z, duk_small_uint_fast_t opcode) {
+DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_bitwise_binary_op(duk_hthread *thr,
+ duk_tval *tv_x,
+ duk_tval *tv_y,
+ duk_small_uint_fast_t idx_z,
+ duk_small_uint_fast_t opcode) {
/*
* Binary bitwise operations use different coercions (ToInt32, ToUint32)
* depending on the operation. We coerce the arguments first using
@@ -72231,20 +77553,19 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_bitwise_binary_op(duk_hthread *thr, duk_
#endif
DUK_ASSERT(thr != NULL);
- DUK_ASSERT(tv_x != NULL); /* may be reg or const */
- DUK_ASSERT(tv_y != NULL); /* may be reg or const */
- DUK_ASSERT_DISABLE(idx_z >= 0); /* unsigned */
+ DUK_ASSERT(tv_x != NULL); /* may be reg or const */
+ DUK_ASSERT(tv_y != NULL); /* may be reg or const */
+ DUK_ASSERT_DISABLE(idx_z >= 0); /* unsigned */
DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
- opcode_shifted = opcode >> 2; /* Get base opcode without reg/const modifiers. */
+ opcode_shifted = opcode >> 2; /* Get base opcode without reg/const modifiers. */
#if defined(DUK_USE_FASTINT)
if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_x);
i2 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_y);
- }
- else
-#endif /* DUK_USE_FASTINT */
+ } else
+#endif /* DUK_USE_FASTINT */
{
duk_push_tval(thr, tv_x);
duk_push_tval(thr, tv_y);
@@ -72273,15 +77594,15 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_bitwise_binary_op(duk_hthread *thr, duk_
*/
u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
- i3 = (duk_int32_t) (((duk_uint32_t) i1) << (u2 & 0x1fUL)); /* E5 Section 11.7.1, steps 7 and 8 */
- i3 = i3 & ((duk_int32_t) 0xffffffffUL); /* Note: left shift, should mask */
+ i3 = (duk_int32_t) (((duk_uint32_t) i1) << (u2 & 0x1fUL)); /* E5 Section 11.7.1, steps 7 and 8 */
+ i3 = i3 & ((duk_int32_t) 0xffffffffUL); /* Note: left shift, should mask */
break;
}
case DUK_OP_BASR >> 2: {
/* signed shift */
u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
- i3 = i1 >> (u2 & 0x1fUL); /* E5 Section 11.7.2, steps 7 and 8 */
+ i3 = i1 >> (u2 & 0x1fUL); /* E5 Section 11.7.2, steps 7 and 8 */
break;
}
case DUK_OP_BLSR >> 2: {
@@ -72291,7 +77612,7 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_bitwise_binary_op(duk_hthread *thr, duk_
u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
/* special result value handling */
- u3 = u1 >> (u2 & 0x1fUL); /* E5 Section 11.7.2, steps 7 and 8 */
+ u3 = u1 >> (u2 & 0x1fUL); /* E5 Section 11.7.2, steps 7 and 8 */
#if defined(DUK_USE_FASTINT)
fi3 = (duk_int64_t) u3;
goto fastint_result_set;
@@ -72302,7 +77623,7 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_bitwise_binary_op(duk_hthread *thr, duk_
}
default: {
DUK_UNREACHABLE();
- i3 = 0; /* should not happen */
+ i3 = 0; /* should not happen */
break;
}
}
@@ -72314,28 +77635,31 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_bitwise_binary_op(duk_hthread *thr, duk_
*/
fi3 = (duk_int64_t) i3;
- fastint_result_set:
+fastint_result_set:
tv_z = thr->valstack_bottom + idx_z;
- DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, fi3); /* side effects */
-#else /* DUK_USE_FASTINT */
+ DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, fi3); /* side effects */
+#else /* DUK_USE_FASTINT */
d3 = (duk_double_t) i3;
- result_set:
- DUK_ASSERT(!DUK_ISNAN(d3)); /* 'd3' is never NaN, so no need to normalize */
- DUK_ASSERT_DOUBLE_IS_NORMALIZED(d3); /* always normalized */
+result_set:
+ DUK_ASSERT(!DUK_ISNAN(d3)); /* 'd3' is never NaN, so no need to normalize */
+ DUK_ASSERT_DOUBLE_IS_NORMALIZED(d3); /* always normalized */
#if defined(DUK_USE_EXEC_PREFER_SIZE)
- duk_push_number(thr, d3); /* would NaN normalize result, but unnecessary */
+ duk_push_number(thr, d3); /* would NaN normalize result, but unnecessary */
duk_replace(thr, (duk_idx_t) idx_z);
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
tv_z = thr->valstack_bottom + idx_z;
- DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d3); /* side effects */
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
-#endif /* DUK_USE_FASTINT */
+ DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d3); /* side effects */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
+#endif /* DUK_USE_FASTINT */
}
/* In-place unary operation. */
-DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_unary_op(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst, duk_small_uint_fast_t opcode) {
+DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_arith_unary_op(duk_hthread *thr,
+ duk_uint_fast_t idx_src,
+ duk_uint_fast_t idx_dst,
+ duk_small_uint_fast_t opcode) {
/*
* Arithmetic operations other than '+' have number-only semantics
* and are implemented here. The separate switch-case here means a
@@ -72381,12 +77705,12 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_unary_op(duk_hthread *thr, duk_uin
}
/* fall through if overflow etc */
}
-#endif /* DUK_USE_FASTINT */
+#endif /* DUK_USE_FASTINT */
if (DUK_TVAL_IS_NUMBER(tv)) {
d1 = DUK_TVAL_GET_NUMBER(tv);
} else {
- d1 = duk_to_number_tval(thr, tv); /* side effects */
+ d1 = duk_to_number_tval(thr, tv); /* side effects */
}
if (opcode == DUK_OP_UNP) {
@@ -72397,13 +77721,13 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_unary_op(duk_hthread *thr, duk_uin
DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
#if defined(DUK_USE_FASTINT)
tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
- DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF(thr, tv, du.d); /* always 'fast', i.e. inlined */
+ DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF(thr, tv, du.d); /* always 'fast', i.e. inlined */
return;
#endif
} else {
DUK_ASSERT(opcode == DUK_OP_UNM);
du.d = -d1;
- DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du); /* mandatory if du.d is a NaN */
+ DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du); /* mandatory if du.d is a NaN */
DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
}
@@ -72412,7 +77736,7 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_unary_op(duk_hthread *thr, duk_uin
DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, du.d);
}
-DUK_LOCAL DUK__INLINE_PERF void duk__vm_bitwise_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst) {
+DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_bitwise_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst) {
/*
* E5 Section 11.4.8
*/
@@ -72431,22 +77755,21 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_bitwise_not(duk_hthread *thr, duk_uint_f
#if defined(DUK_USE_FASTINT)
if (DUK_TVAL_IS_FASTINT(tv)) {
i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv);
- }
- else
-#endif /* DUK_USE_FASTINT */
+ } else
+#endif /* DUK_USE_FASTINT */
{
duk_push_tval(thr, tv);
- i1 = duk_to_int32(thr, -1); /* side effects */
+ i1 = duk_to_int32(thr, -1); /* side effects */
duk_pop_unsafe(thr);
}
/* Result is always fastint compatible. */
i2 = ~i1;
tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
- DUK_TVAL_SET_I32_UPDREF(thr, tv, i2); /* side effects */
+ DUK_TVAL_SET_I32_UPDREF(thr, tv, i2); /* side effects */
}
-DUK_LOCAL DUK__INLINE_PERF void duk__vm_logical_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst) {
+DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_logical_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst) {
/*
* E5 Section 11.4.9
*/
@@ -72465,16 +77788,19 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_logical_not(duk_hthread *thr, duk_uint_f
* duk_js_toboolean() and then push+replace to the result slot.
*/
tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
- res = duk_js_toboolean(tv); /* does not modify 'tv' */
+ res = duk_js_toboolean(tv); /* does not modify 'tv' */
DUK_ASSERT(res == 0 || res == 1);
res ^= 1;
tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
/* XXX: size optimize: push+replace? */
- DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, res); /* side effects */
+ DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, res); /* side effects */
}
/* XXX: size optimized variant */
-DUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_reg_helper(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_small_uint_t op) {
+DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__prepost_incdec_reg_helper(duk_hthread *thr,
+ duk_tval *tv_dst,
+ duk_tval *tv_src,
+ duk_small_uint_t op) {
duk_double_t x, y, z;
/* Two lowest bits of opcode are used to distinguish
@@ -72501,13 +77827,13 @@ DUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_reg_helper(duk_hthread *thr,
y_fi = x_fi + 1;
}
- DUK_TVAL_SET_FASTINT(tv_src, y_fi); /* no need for refcount update */
+ DUK_TVAL_SET_FASTINT(tv_src, y_fi); /* no need for refcount update */
z_fi = (op & 0x02) ? x_fi : y_fi;
- DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_dst, z_fi); /* side effects */
+ DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_dst, z_fi); /* side effects */
return;
}
- skip_fastint:
+skip_fastint:
#endif
if (DUK_TVAL_IS_NUMBER(tv_src)) {
/* Fast path for the case where the register
@@ -72521,7 +77847,7 @@ DUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_reg_helper(duk_hthread *thr,
y = x + 1.0;
}
- DUK_TVAL_SET_NUMBER(tv_src, y); /* no need for refcount update */
+ DUK_TVAL_SET_NUMBER(tv_src, y); /* no need for refcount update */
} else {
/* Preserve duk_tval pointer(s) across a potential valstack
* resize by converting them into offsets temporarily.
@@ -72530,8 +77856,8 @@ DUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_reg_helper(duk_hthread *thr,
duk_size_t off_dst;
off_dst = (duk_size_t) ((duk_uint8_t *) tv_dst - (duk_uint8_t *) thr->valstack_bottom);
- bc = (duk_idx_t) (tv_src - thr->valstack_bottom); /* XXX: pass index explicitly? */
- tv_src = NULL; /* no longer referenced */
+ bc = (duk_idx_t) (tv_src - thr->valstack_bottom); /* XXX: pass index explicitly? */
+ tv_src = NULL; /* no longer referenced */
x = duk_to_number(thr, bc);
if (op & 0x01) {
@@ -72547,10 +77873,14 @@ DUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_reg_helper(duk_hthread *thr,
}
z = (op & 0x02) ? x : y;
- DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z); /* side effects */
+ DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z); /* side effects */
}
-DUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_var_helper(duk_hthread *thr, duk_small_uint_t idx_dst, duk_tval *tv_id, duk_small_uint_t op, duk_small_uint_t is_strict) {
+DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__prepost_incdec_var_helper(duk_hthread *thr,
+ duk_small_uint_t idx_dst,
+ duk_tval *tv_id,
+ duk_small_uint_t op,
+ duk_small_uint_t is_strict) {
duk_activation *act;
duk_double_t x, y;
duk_hstring *name;
@@ -72576,7 +77906,7 @@ DUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_var_helper(duk_hthread *thr,
name = DUK_TVAL_GET_STRING(tv_id);
DUK_ASSERT(name != NULL);
act = thr->callstack_curr;
- (void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/); /* -> [ ... val this ] */
+ (void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/); /* -> [ ... val this ] */
/* XXX: Fastint fast path would be useful here. Also fastints
* now lose their fastint status in current handling which is
@@ -72593,22 +77923,22 @@ DUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_var_helper(duk_hthread *thr,
/* [... x this] */
if (op & 0x02) {
- duk_push_number(thr, y); /* -> [ ... x this y ] */
+ duk_push_number(thr, y); /* -> [ ... x this y ] */
DUK_ASSERT(act == thr->callstack_curr);
duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(thr, -1), is_strict);
- duk_pop_2_unsafe(thr); /* -> [ ... x ] */
+ duk_pop_2_unsafe(thr); /* -> [ ... x ] */
} else {
- duk_pop_2_unsafe(thr); /* -> [ ... ] */
- duk_push_number(thr, y); /* -> [ ... y ] */
+ duk_pop_2_unsafe(thr); /* -> [ ... ] */
+ duk_push_number(thr, y); /* -> [ ... y ] */
DUK_ASSERT(act == thr->callstack_curr);
duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(thr, -1), is_strict);
}
#if defined(DUK_USE_EXEC_PREFER_SIZE)
duk_replace(thr, (duk_idx_t) idx_dst);
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
DUK__REPLACE_TO_TVPTR(thr, DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst));
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
}
/*
@@ -72622,17 +77952,17 @@ DUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_var_helper(duk_hthread *thr,
* handled recursively.
*/
-#define DUK__LONGJMP_RESTART 0 /* state updated, restart bytecode execution */
-#define DUK__LONGJMP_RETHROW 1 /* exit bytecode executor by rethrowing an error to caller */
+#define DUK__LONGJMP_RESTART 0 /* state updated, restart bytecode execution */
+#define DUK__LONGJMP_RETHROW 1 /* exit bytecode executor by rethrowing an error to caller */
-#define DUK__RETHAND_RESTART 0 /* state updated, restart bytecode execution */
-#define DUK__RETHAND_FINISHED 1 /* exit bytecode execution with return value */
+#define DUK__RETHAND_RESTART 0 /* state updated, restart bytecode execution */
+#define DUK__RETHAND_FINISHED 1 /* exit bytecode execution with return value */
/* XXX: optimize reconfig valstack operations so that resize, clamp, and setting
* top are combined into one pass.
*/
-/* Reconfigure value stack for return to an Ecmascript function at
+/* Reconfigure value stack for return to an ECMAScript function at
* callstack top (caller unwinds).
*/
DUK_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr) {
@@ -72648,14 +77978,15 @@ DUK_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr) {
/* Clamp so that values at 'clamp_top' and above are wiped and won't
* retain reachable garbage. Then extend to 'nregs' because we're
- * returning to an Ecmascript function.
+ * returning to an ECMAScript function.
*/
h_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
DUK_ASSERT(act->retval_byteoff >= act->bottom_byteoff);
- clamp_top = (duk_idx_t) ((act->retval_byteoff - act->bottom_byteoff + sizeof(duk_tval)) / sizeof(duk_tval)); /* +1 = one retval */
+ clamp_top =
+ (duk_idx_t) ((act->retval_byteoff - act->bottom_byteoff + sizeof(duk_tval)) / sizeof(duk_tval)); /* +1 = one retval */
duk_set_top_and_wipe(thr, h_func->nregs, clamp_top);
DUK_ASSERT((duk_uint8_t *) thr->valstack_end >= (duk_uint8_t *) thr->valstack + act->reserve_byteoff);
@@ -72664,7 +77995,7 @@ DUK_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr) {
/* XXX: a best effort shrink check would be OK here */
}
-/* Reconfigure value stack for an Ecmascript catcher. Use topmost catcher
+/* Reconfigure value stack for an ECMAScript catcher. Use topmost catcher
* in 'act'.
*/
DUK_LOCAL void duk__reconfig_valstack_ecma_catcher(duk_hthread *thr, duk_activation *act) {
@@ -72685,7 +78016,7 @@ DUK_LOCAL void duk__reconfig_valstack_ecma_catcher(duk_hthread *thr, duk_activat
thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
idx_bottom = (duk_size_t) (thr->valstack_bottom - thr->valstack);
DUK_ASSERT(cat->idx_base >= idx_bottom);
- clamp_top = (duk_idx_t) (cat->idx_base - idx_bottom + 2); /* +2 = catcher value, catcher lj_type */
+ clamp_top = (duk_idx_t) (cat->idx_base - idx_bottom + 2); /* +2 = catcher value, catcher lj_type */
duk_set_top_and_wipe(thr, h_func->nregs, clamp_top);
DUK_ASSERT((duk_uint8_t *) thr->valstack_end >= (duk_uint8_t *) thr->valstack + act->reserve_byteoff);
@@ -72713,7 +78044,10 @@ DUK_LOCAL void duk__set_catcher_regs_norz(duk_hthread *thr, duk_catcher *cat, du
DUK_TVAL_SET_U32_UPDREF_NORZ(thr, tv1, (duk_uint32_t) lj_type);
}
-DUK_LOCAL void duk__handle_catch(duk_hthread *thr, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
+DUK_LOCAL void duk__handle_catch_part1(duk_hthread *thr,
+ duk_tval *tv_val_unstable,
+ duk_small_uint_t lj_type,
+ volatile duk_bool_t *out_delayed_catch_setup) {
duk_activation *act;
duk_catcher *cat;
@@ -72722,9 +78056,17 @@ DUK_LOCAL void duk__handle_catch(duk_hthread *thr, duk_tval *tv_val_unstable, du
act = thr->callstack_curr;
DUK_ASSERT(act != NULL);
+ DUK_DD(DUK_DDPRINT("handle catch, part 1; act=%!A, cat=%!C", act, act->cat));
+
DUK_ASSERT(act->cat != NULL);
DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);
+ /* The part1/part2 split could also be made here at the very top
+ * of catch handling. Value stack would be reconfigured inside
+ * part2's protection. Value stack reconfiguration should be free
+ * of allocs, however.
+ */
+
duk__set_catcher_regs_norz(thr, act->cat, tv_val_unstable, lj_type);
DUK_ASSERT(thr->callstack_top >= 1);
@@ -72743,11 +78085,47 @@ DUK_LOCAL void duk__handle_catch(duk_hthread *thr, duk_tval *tv_val_unstable, du
cat = act->cat;
DUK_ASSERT(cat != NULL);
- act->curr_pc = cat->pc_base + 0; /* +0 = catch */
+ act->curr_pc = cat->pc_base + 0; /* +0 = catch */
/*
- * If entering a 'catch' block which requires an automatic
- * catch variable binding, create the lexical environment.
+ * If the catch block has an automatic catch variable binding,
+ * we need to create a lexical environment for it which requires
+ * allocations. Move out of "error handling state" before the
+ * allocations to avoid e.g. out-of-memory errors (leading to
+ * GH-2022 or similar).
+ */
+
+ if (DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat)) {
+ DUK_DDD(DUK_DDDPRINT("catcher has an automatic catch binding, handle in part 2"));
+ *out_delayed_catch_setup = 1;
+ } else {
+ DUK_DDD(DUK_DDDPRINT("catcher has no catch binding"));
+ }
+
+ DUK_CAT_CLEAR_CATCH_ENABLED(cat);
+}
+
+DUK_LOCAL void duk__handle_catch_part2(duk_hthread *thr) {
+ duk_activation *act;
+ duk_catcher *cat;
+ duk_hdecenv *new_env;
+
+ DUK_ASSERT(thr != NULL);
+
+ act = thr->callstack_curr;
+ DUK_ASSERT(act != NULL);
+ DUK_DD(DUK_DDPRINT("handle catch, part 2; act=%!A, cat=%!C", act, act->cat));
+
+ DUK_ASSERT(act->cat != NULL);
+ cat = act->cat;
+ DUK_ASSERT(cat != NULL);
+ DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
+ DUK_ASSERT(DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat));
+ DUK_ASSERT(thr->valstack + cat->idx_base < thr->valstack_top);
+
+ /*
+ * Create lexical environment for the catch clause, containing
+ * a binding for the caught value.
*
* The binding is mutable (= writable) but not deletable.
* Step 4 for the catch production in E5 Section 12.14;
@@ -72755,70 +78133,54 @@ DUK_LOCAL void duk__handle_catch(duk_hthread *thr, duk_tval *tv_val_unstable, du
* which implies the binding is not deletable.
*/
- if (DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat)) {
- duk_hdecenv *new_env;
-
- DUK_DDD(DUK_DDDPRINT("catcher has an automatic catch binding"));
+ if (act->lex_env == NULL) {
+ DUK_ASSERT(act->var_env == NULL);
+ DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
- DUK_ASSERT(thr->callstack_top >= 1);
+ duk_js_init_activation_environment_records_delayed(thr, act);
DUK_ASSERT(act == thr->callstack_curr);
DUK_ASSERT(act != NULL);
+ }
+ DUK_ASSERT(act->lex_env != NULL);
+ DUK_ASSERT(act->var_env != NULL);
+ DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
- if (act->lex_env == NULL) {
- DUK_ASSERT(act->var_env == NULL);
- DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
-
- duk_js_init_activation_environment_records_delayed(thr, act);
- DUK_ASSERT(act == thr->callstack_curr);
- DUK_ASSERT(act != NULL);
- }
- DUK_ASSERT(act->lex_env != NULL);
- DUK_ASSERT(act->var_env != NULL);
- DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
+ new_env = duk_hdecenv_alloc(thr, DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
+ DUK_ASSERT(new_env != NULL);
+ duk_push_hobject(thr, (duk_hobject *) new_env);
+ DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
+ DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
- /* XXX: If an out-of-memory happens here, longjmp state asserts
- * will be triggered at present and a try-catch fails to catch.
- * That's not sandboxing fatal (C API protected calls are what
- * matters), and script catch code can immediately throw anyway
- * for almost any operation.
- */
- new_env = duk_hdecenv_alloc(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
- DUK_ASSERT(new_env != NULL);
- duk_push_hobject(thr, (duk_hobject *) new_env);
- DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
- DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
+ /* Note: currently the catch binding is handled without a register
+ * binding because we don't support dynamic register bindings (they
+ * must be fixed for an entire function). So, there is no need to
+ * record regbases etc.
+ */
- /* Note: currently the catch binding is handled without a register
- * binding because we don't support dynamic register bindings (they
- * must be fixed for an entire function). So, there is no need to
- * record regbases etc.
- */
+ /* [ ...env ] */
- /* XXX: duk_xdef_prop() may cause an out-of-memory, see above. */
- DUK_ASSERT(cat->h_varname != NULL);
- duk_push_hstring(thr, cat->h_varname);
- duk_push_tval(thr, thr->valstack + cat->idx_base);
- duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_W); /* writable, not configurable */
+ DUK_ASSERT(cat->h_varname != NULL);
+ duk_push_hstring(thr, cat->h_varname);
+ DUK_ASSERT(thr->valstack + cat->idx_base < thr->valstack_top);
+ duk_push_tval(thr, thr->valstack + cat->idx_base);
+ duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_W); /* writable, not configurable */
- DUK_ASSERT(act == thr->callstack_curr);
- DUK_ASSERT(act != NULL);
- DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, act->lex_env);
- act->lex_env = (duk_hobject *) new_env;
- DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env); /* reachable through activation */
- /* Net refcount change to act->lex_env is 0: incref for new_env's
- * prototype, decref for act->lex_env overwrite.
- */
+ /* [ ... env ] */
- DUK_CAT_SET_LEXENV_ACTIVE(cat);
+ DUK_ASSERT(act == thr->callstack_curr);
+ DUK_ASSERT(act != NULL);
+ DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, act->lex_env);
+ act->lex_env = (duk_hobject *) new_env;
+ DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env); /* reachable through activation */
+ /* Net refcount change to act->lex_env is 0: incref for new_env's
+ * prototype, decref for act->lex_env overwrite.
+ */
- duk_pop_unsafe(thr);
+ DUK_CAT_SET_LEXENV_ACTIVE(cat);
- DUK_DDD(DUK_DDDPRINT("new_env finished: %!iO", (duk_heaphdr *) new_env));
- }
+ duk_pop_unsafe(thr);
- DUK_CAT_CLEAR_CATCH_ENABLED(cat);
+ DUK_DDD(DUK_DDDPRINT("new_env finished: %!iO", (duk_heaphdr *) new_env));
}
DUK_LOCAL void duk__handle_finally(duk_hthread *thr, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
@@ -72851,7 +78213,7 @@ DUK_LOCAL void duk__handle_finally(duk_hthread *thr, duk_tval *tv_val_unstable,
cat = act->cat;
DUK_ASSERT(cat != NULL);
- act->curr_pc = cat->pc_base + 1; /* +1 = finally */
+ act->curr_pc = cat->pc_base + 1; /* +1 = finally */
DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
}
@@ -72900,18 +78262,21 @@ DUK_LOCAL void duk__handle_yield(duk_hthread *thr, duk_hthread *resumer, duk_tva
act_resumer = resumer->callstack_curr;
DUK_ASSERT(act_resumer != NULL);
DUK_ASSERT(DUK_ACT_GET_FUNC(act_resumer) != NULL);
- DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act_resumer))); /* resume caller must be an ecmascript func */
+ DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act_resumer))); /* resume caller must be an ECMAScript func */
- tv1 = (duk_tval *) (void *) ((duk_uint8_t *) resumer->valstack + act_resumer->retval_byteoff); /* return value from Duktape.Thread.resume() */
- DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable); /* side effects */ /* XXX: avoid side effects */
+ tv1 = (duk_tval *) (void *) ((duk_uint8_t *) resumer->valstack +
+ act_resumer->retval_byteoff); /* return value from Duktape.Thread.resume() */
+ DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable); /* side effects */ /* XXX: avoid side effects */
duk__reconfig_valstack_ecma_return(resumer);
/* caller must change active thread, and set thr->resumer to NULL */
}
-#endif /* DUK_USE_COROUTINE_SUPPORT */
+#endif /* DUK_USE_COROUTINE_SUPPORT */
-DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation *entry_act) {
+DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
+ duk_activation *entry_act,
+ volatile duk_bool_t *out_delayed_catch_setup) {
duk_small_uint_t retval = DUK__LONGJMP_RESTART;
DUK_ASSERT(thr != NULL);
@@ -72932,16 +78297,16 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation
* - 'thr' must reflect the "throwing" thread
*/
- check_longjmp:
+check_longjmp:
- DUK_DD(DUK_DDPRINT("handling longjmp: type=%ld, value1=%!T, value2=%!T, iserror=%ld",
+ DUK_DD(DUK_DDPRINT("handling longjmp: type=%ld, value1=%!T, value2=%!T, iserror=%ld, top=%ld",
(long) thr->heap->lj.type,
(duk_tval *) &thr->heap->lj.value1,
(duk_tval *) &thr->heap->lj.value2,
- (long) thr->heap->lj.iserror));
+ (long) thr->heap->lj.iserror,
+ (long) duk_get_top(thr)));
switch (thr->heap->lj.type) {
-
#if defined(DUK_USE_COROUTINE_SUPPORT)
case DUK_LJ_TYPE_RESUME: {
/*
@@ -72955,15 +78320,15 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation
/* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
- DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING); /* unchanged by Duktape.Thread.resume() */
- DUK_ASSERT(thr->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */
+ DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING); /* unchanged by Duktape.Thread.resume() */
+ DUK_ASSERT(thr->callstack_top >= 2); /* ECMAScript activation + Duktape.Thread.resume() activation */
DUK_ASSERT(thr->callstack_curr != NULL);
DUK_ASSERT(thr->callstack_curr->parent != NULL);
DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL &&
DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)) &&
((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack_curr))->func == duk_bi_thread_resume);
- tv = &thr->heap->lj.value2; /* resumee */
+ tv = &thr->heap->lj.value2; /* resumee */
DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv) != NULL);
DUK_ASSERT(DUK_HOBJECT_IS_THREAD(DUK_TVAL_GET_OBJECT(tv)));
@@ -72972,15 +78337,15 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation
DUK_ASSERT(resumee != NULL);
DUK_ASSERT(resumee->resumer == NULL);
DUK_ASSERT(resumee->state == DUK_HTHREAD_STATE_INACTIVE ||
- resumee->state == DUK_HTHREAD_STATE_YIELDED); /* checked by Duktape.Thread.resume() */
+ resumee->state == DUK_HTHREAD_STATE_YIELDED); /* checked by Duktape.Thread.resume() */
DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
- resumee->callstack_top >= 2); /* YIELDED: Ecmascript activation + Duktape.Thread.yield() activation */
+ resumee->callstack_top >= 2); /* YIELDED: ECMAScript activation + Duktape.Thread.yield() activation */
DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
(DUK_ACT_GET_FUNC(resumee->callstack_curr) != NULL &&
DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumee->callstack_curr)) &&
((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumee->callstack_curr))->func == duk_bi_thread_yield));
DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_INACTIVE ||
- resumee->callstack_top == 0); /* INACTIVE: no activation, single function value on valstack */
+ resumee->callstack_top == 0); /* INACTIVE: no activation, single function value on valstack */
if (thr->heap->lj.iserror) {
/*
@@ -73006,30 +78371,31 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation
/* thr->heap->lj.value1 is already the value to throw */
/* thr->heap->lj.value2 is 'thread', will be wiped out at the end */
- DUK_ASSERT(thr->heap->lj.iserror); /* already set */
+ DUK_ASSERT(thr->heap->lj.iserror); /* already set */
DUK_DD(DUK_DDPRINT("-> resume with an error, converted to a throw in the resumee, propagate"));
goto check_longjmp;
} else if (resumee->state == DUK_HTHREAD_STATE_YIELDED) {
/* Unwind previous Duktape.Thread.yield() call. The
- * activation remaining must always be an Ecmascript
- * call now (yield() accepts calls from Ecmascript
+ * activation remaining must always be an ECMAScript
+ * call now (yield() accepts calls from ECMAScript
* only).
*/
duk_activation *act_resumee;
DUK_ASSERT(resumee->callstack_top >= 2);
- act_resumee = resumee->callstack_curr; /* Duktape.Thread.yield() */
+ act_resumee = resumee->callstack_curr; /* Duktape.Thread.yield() */
DUK_ASSERT(act_resumee != NULL);
- act_resumee = act_resumee->parent; /* Ecmascript call site for yield() */
+ act_resumee = act_resumee->parent; /* ECMAScript call site for yield() */
DUK_ASSERT(act_resumee != NULL);
- tv = (duk_tval *) (void *) ((duk_uint8_t *) resumee->valstack + act_resumee->retval_byteoff); /* return value from Duktape.Thread.yield() */
+ tv = (duk_tval *) (void *) ((duk_uint8_t *) resumee->valstack +
+ act_resumee->retval_byteoff); /* return value from Duktape.Thread.yield() */
DUK_ASSERT(tv >= resumee->valstack && tv < resumee->valstack_top);
tv2 = &thr->heap->lj.value1;
- DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv2); /* side effects */ /* XXX: avoid side effects */
+ DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv2); /* side effects */ /* XXX: avoid side effects */
- duk_hthread_activation_unwind_norz(resumee); /* unwind to 'yield' caller */
+ duk_hthread_activation_unwind_norz(resumee); /* unwind to 'yield' caller */
/* no need to unwind catch stack */
duk__reconfig_valstack_ecma_return(resumee);
@@ -73059,7 +78425,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation
/* resumee: [... initial_func undefined(= this) resume_value ] */
- call_flags = DUK_CALL_FLAG_ALLOW_ECMATOECMA; /* not tailcall, ecma-to-ecma (assumed to succeed) */
+ call_flags = DUK_CALL_FLAG_ALLOW_ECMATOECMA; /* not tailcall, ecma-to-ecma (assumed to succeed) */
setup_rc = duk_handle_call_unprotected_nargs(resumee, 1 /*nargs*/, call_flags);
if (setup_rc == 0) {
@@ -73069,6 +78435,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation
* executor which can be quite misleading.
*/
DUK_ERROR_INTERNAL(thr);
+ DUK_WO_NORETURN(return 0;);
}
DUK_ASSERT(resumee->resumer == NULL);
@@ -73085,13 +78452,13 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation
goto wipe_and_return;
}
DUK_UNREACHABLE();
- break; /* never here */
+ break; /* never here */
}
case DUK_LJ_TYPE_YIELD: {
/*
* Currently only allowed only if yielding thread has only
- * Ecmascript activations (except for the Duktape.Thread.yield()
+ * ECMAScript activations (except for the Duktape.Thread.yield()
* call at the callstack top) and none of them constructor
* calls.
*
@@ -73103,31 +78470,31 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation
/* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
-#if 0 /* entry_thread not available for assert */
+#if 0 /* entry_thread not available for assert */
DUK_ASSERT(thr != entry_thread); /* Duktape.Thread.yield() should prevent */
#endif
- DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING); /* unchanged from Duktape.Thread.yield() */
- DUK_ASSERT(thr->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.yield() activation */
+ DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING); /* unchanged from Duktape.Thread.yield() */
+ DUK_ASSERT(thr->callstack_top >= 2); /* ECMAScript activation + Duktape.Thread.yield() activation */
DUK_ASSERT(thr->callstack_curr != NULL);
DUK_ASSERT(thr->callstack_curr->parent != NULL);
DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL &&
DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)) &&
((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack_curr))->func == duk_bi_thread_yield);
DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL &&
- DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent))); /* an Ecmascript function */
+ DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent))); /* an ECMAScript function */
resumer = thr->resumer;
DUK_ASSERT(resumer != NULL);
- DUK_ASSERT(resumer->state == DUK_HTHREAD_STATE_RESUMED); /* written by a previous RESUME handling */
- DUK_ASSERT(resumer->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */
+ DUK_ASSERT(resumer->state == DUK_HTHREAD_STATE_RESUMED); /* written by a previous RESUME handling */
+ DUK_ASSERT(resumer->callstack_top >= 2); /* ECMAScript activation + Duktape.Thread.resume() activation */
DUK_ASSERT(resumer->callstack_curr != NULL);
DUK_ASSERT(resumer->callstack_curr->parent != NULL);
DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr) != NULL &&
DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr)) &&
((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumer->callstack_curr))->func == duk_bi_thread_resume);
DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent) != NULL &&
- DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent))); /* an Ecmascript function */
+ DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent))); /* an ECMAScript function */
if (thr->heap->lj.iserror) {
thr->state = DUK_HTHREAD_STATE_YIELDED;
@@ -73139,31 +78506,35 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation
thr->heap->lj.type = DUK_LJ_TYPE_THROW;
/* lj.value1 is already set */
- DUK_ASSERT(thr->heap->lj.iserror); /* already set */
+ DUK_ASSERT(thr->heap->lj.iserror); /* already set */
DUK_DD(DUK_DDPRINT("-> yield an error, converted to a throw in the resumer, propagate"));
goto check_longjmp;
} else {
- duk_hthread_activation_unwind_norz(resumer);
- duk__handle_yield(thr, resumer, &thr->heap->lj.value1);
+ /* When handling the yield, the last reference to
+ * 'thr' may disappear.
+ */
+ DUK_GC_TORTURE(resumer->heap);
+ duk_hthread_activation_unwind_norz(resumer);
+ DUK_GC_TORTURE(resumer->heap);
thr->state = DUK_HTHREAD_STATE_YIELDED;
thr->resumer = NULL;
DUK_HTHREAD_DECREF_NORZ(thr, resumer);
resumer->state = DUK_HTHREAD_STATE_RUNNING;
DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
-#if 0
- thr = resumer; /* not needed, as we exit right away */
-#endif
+ duk__handle_yield(thr, resumer, &thr->heap->lj.value1);
+ thr = resumer;
+ DUK_GC_TORTURE(resumer->heap);
DUK_DD(DUK_DDPRINT("-> yield a value, restart execution in resumer"));
retval = DUK__LONGJMP_RESTART;
goto wipe_and_return;
}
DUK_UNREACHABLE();
- break; /* never here */
+ break; /* never here */
}
-#endif /* DUK_USE_COROUTINE_SUPPORT */
+#endif /* DUK_USE_COROUTINE_SUPPORT */
case DUK_LJ_TYPE_THROW: {
/*
@@ -73181,7 +78552,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation
* resumer in this case.)
*
* Note: until we hit the entry level, there can only be
- * Ecmascript activations.
+ * ECMAScript activations.
*/
duk_activation *act;
@@ -73203,9 +78574,14 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation
if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
- duk__handle_catch(thr,
- &thr->heap->lj.value1,
- DUK_LJ_TYPE_THROW);
+ DUK_DDD(DUK_DDDPRINT("before catch part 1: thr=%p, act=%p, cat=%p",
+ (void *) thr,
+ (void *) act,
+ (void *) act->cat));
+ duk__handle_catch_part1(thr,
+ &thr->heap->lj.value1,
+ DUK_LJ_TYPE_THROW,
+ out_delayed_catch_setup);
DUK_DD(DUK_DDPRINT("-> throw caught by a 'catch' clause, restart execution"));
retval = DUK__LONGJMP_RESTART;
@@ -73216,9 +78592,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation
DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));
- duk__handle_finally(thr,
- &thr->heap->lj.value1,
- DUK_LJ_TYPE_THROW);
+ duk__handle_finally(thr, &thr->heap->lj.value1, DUK_LJ_TYPE_THROW);
DUK_DD(DUK_DDPRINT("-> throw caught by a 'finally' clause, restart execution"));
retval = DUK__LONGJMP_RESTART;
@@ -73248,20 +78622,21 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation
*/
DUK_ASSERT(thr->resumer != NULL);
- DUK_ASSERT(thr->resumer->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */
+ DUK_ASSERT(thr->resumer->callstack_top >= 2); /* ECMAScript activation + Duktape.Thread.resume() activation */
DUK_ASSERT(thr->resumer->callstack_curr != NULL);
DUK_ASSERT(thr->resumer->callstack_curr->parent != NULL);
- DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL &&
- DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent))); /* an Ecmascript function */
+ DUK_ASSERT(
+ DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL &&
+ DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent))); /* an ECMAScript function */
resumer = thr->resumer;
/* reset longjmp */
- DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW); /* already set */
+ DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW); /* already set */
/* lj.value1 already set */
- duk_hthread_terminate(thr); /* updates thread state, minimizes its allocations */
+ duk_hthread_terminate(thr); /* updates thread state, minimizes its allocations */
DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
thr->resumer = NULL;
@@ -73272,7 +78647,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation
goto check_longjmp;
}
- case DUK_LJ_TYPE_BREAK: /* pseudotypes, not used in actual longjmps */
+ case DUK_LJ_TYPE_BREAK: /* pseudotypes, not used in actual longjmps */
case DUK_LJ_TYPE_CONTINUE:
case DUK_LJ_TYPE_RETURN:
case DUK_LJ_TYPE_NORMAL:
@@ -73282,40 +78657,39 @@ DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation
goto convert_to_internal_error;
}
- } /* end switch */
+ } /* end switch */
DUK_UNREACHABLE();
- wipe_and_return:
- /* this is not strictly necessary, but helps debugging */
+wipe_and_return:
+ DUK_DD(DUK_DDPRINT("handling longjmp done, wipe-and-return, top=%ld", (long) duk_get_top(thr)));
thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
thr->heap->lj.iserror = 0;
- DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1); /* side effects */
- DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2); /* side effects */
+ DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1); /* side effects */
+ DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2); /* side effects */
DUK_GC_TORTURE(thr->heap);
- just_return:
+just_return:
return retval;
- convert_to_internal_error:
+convert_to_internal_error:
/* This could also be thrown internally (set the error, goto check_longjmp),
* but it's better for internal errors to bubble outwards so that we won't
* infinite loop in this catchpoint.
*/
DUK_ERROR_INTERNAL(thr);
- DUK_UNREACHABLE();
- return retval;
+ DUK_WO_NORETURN(return 0;);
}
/* Handle a BREAK/CONTINUE opcode. Avoid using longjmp() for BREAK/CONTINUE
* handling because it has a measurable performance impact in ordinary
* environments and an extreme impact in Emscripten (GH-342).
*/
-DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_break_or_continue(duk_hthread *thr,
- duk_uint_t label_id,
- duk_small_uint_t lj_type) {
+DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_break_or_continue(duk_hthread *thr,
+ duk_uint_t label_id,
+ duk_small_uint_t lj_type) {
duk_activation *act;
duk_catcher *cat;
@@ -73346,8 +78720,7 @@ DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_break_or_continue(duk_hthread *thr
/* XXX: bit mask test; FINALLY <-> TCF, single bit mask would suffice? */
- if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
- DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
+ if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF && DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
duk_tval tv_tmp;
DUK_TVAL_SET_U32(&tv_tmp, (duk_uint32_t) label_id);
@@ -73356,11 +78729,11 @@ DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_break_or_continue(duk_hthread *thr
DUK_DD(DUK_DDPRINT("-> break/continue caught by 'finally', restart execution"));
return;
}
- if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL &&
- (duk_uint_t) DUK_CAT_GET_LABEL(cat) == label_id) {
+ if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL && (duk_uint_t) DUK_CAT_GET_LABEL(cat) == label_id) {
duk__handle_label(thr, lj_type);
- DUK_DD(DUK_DDPRINT("-> break/continue caught by a label catcher (in the same function), restart execution"));
+ DUK_DD(
+ DUK_DDPRINT("-> break/continue caught by a label catcher (in the same function), restart execution"));
return;
}
@@ -73368,9 +78741,10 @@ DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_break_or_continue(duk_hthread *thr
}
/* Should never happen, but be robust. */
- DUK_D(DUK_DPRINT("-> break/continue not caught by anything in the current function (should never happen), throw internal error"));
+ DUK_D(DUK_DPRINT(
+ "-> break/continue not caught by anything in the current function (should never happen), throw internal error"));
DUK_ERROR_INTERNAL(thr);
- return;
+ DUK_WO_NORETURN(return;);
}
/* Handle a RETURN opcode. Avoid using longjmp() for return handling because
@@ -73392,7 +78766,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation *
DUK_ASSERT(entry_act != NULL);
DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
tv1 = thr->valstack_top - 1;
- DUK_TVAL_CHKFAST_INPLACE_FAST(tv1); /* fastint downgrade check for return values */
+ DUK_TVAL_CHKFAST_INPLACE_FAST(tv1); /* fastint downgrade check for return values */
/*
* Four possible outcomes:
@@ -73405,7 +78779,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation *
* 2. The return happens at the entry level of the bytecode
* executor, so return from the executor (in C stack).
*
- * 3. There is a calling (Ecmascript) activation in the call
+ * 3. There is a calling (ECMAScript) activation in the call
* stack => return to it, in the same executor instance.
*
* 4. There is no calling activation, and the thread is
@@ -73427,8 +78801,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation *
break;
}
- if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
- DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
+ if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF && DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
duk__handle_finally(thr, thr->valstack_top - 1, DUK_LJ_TYPE_RETURN);
@@ -73450,31 +78823,33 @@ DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation *
}
if (thr->callstack_top >= 2) {
- /* There is a caller; it MUST be an Ecmascript caller (otherwise it would
+ /* There is a caller; it MUST be an ECMAScript caller (otherwise it would
* match entry_act check).
*/
- DUK_DDD(DUK_DDDPRINT("return to Ecmascript caller, retval_byteoff=%ld, lj_value1=%!T",
+ DUK_DDD(DUK_DDDPRINT("return to ECMAScript caller, retval_byteoff=%ld, lj_value1=%!T",
(long) (thr->callstack_curr->parent->retval_byteoff),
(duk_tval *) &thr->heap->lj.value1));
DUK_ASSERT(thr->callstack_curr != NULL);
DUK_ASSERT(thr->callstack_curr->parent != NULL);
- DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent))); /* must be ecmascript */
+ DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent))); /* must be ECMAScript */
#if defined(DUK_USE_ES6_PROXY)
if (thr->callstack_curr->flags & (DUK_ACT_FLAG_CONSTRUCT | DUK_ACT_FLAG_CONSTRUCT_PROXY)) {
- duk_call_construct_postprocess(thr, thr->callstack_curr->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY); /* side effects */
+ duk_call_construct_postprocess(thr,
+ thr->callstack_curr->flags &
+ DUK_ACT_FLAG_CONSTRUCT_PROXY); /* side effects */
}
#else
if (thr->callstack_curr->flags & DUK_ACT_FLAG_CONSTRUCT) {
- duk_call_construct_postprocess(thr, 0); /* side effects */
+ duk_call_construct_postprocess(thr, 0); /* side effects */
}
#endif
tv1 = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + thr->callstack_curr->parent->retval_byteoff);
DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
tv2 = thr->valstack_top - 1;
- DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
+ DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
/* Catch stack unwind happens inline in callstack unwind. */
duk_hthread_activation_unwind_norz(thr);
@@ -73489,31 +78864,52 @@ DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation *
DUK_DD(DUK_DDPRINT("no calling activation, thread finishes (similar to yield)"));
DUK_ASSERT(thr->resumer != NULL);
- DUK_ASSERT(thr->resumer->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */
+ DUK_ASSERT(thr->resumer->callstack_top >= 2); /* ECMAScript activation + Duktape.Thread.resume() activation */
DUK_ASSERT(thr->resumer->callstack_curr != NULL);
DUK_ASSERT(thr->resumer->callstack_curr->parent != NULL);
DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr) != NULL &&
- DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr)) &&
- ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->resumer->callstack_curr))->func == duk_bi_thread_resume); /* Duktape.Thread.resume() */
+ DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr)) &&
+ ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->resumer->callstack_curr))->func ==
+ duk_bi_thread_resume); /* Duktape.Thread.resume() */
DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL &&
- DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent))); /* an Ecmascript function */
+ DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent))); /* an ECMAScript function */
DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
resumer = thr->resumer;
- /* Share yield longjmp handler. */
- DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
- duk_hthread_activation_unwind_norz(resumer);
- duk__handle_yield(thr, resumer, thr->valstack_top - 1);
+ /* Share yield longjmp handler.
+ *
+ * This sequence of steps is a bit fragile (see GH-1845):
+ * - We need the return value from 'thr' (resumed thread) value stack.
+ * The termination unwinds its value stack, losing the value.
+ * - We need a refcounted reference for 'thr', which may only exist
+ * in the caller value stack. We can't unwind or reconfigure the
+ * caller's value stack without potentially freeing 'thr'.
+ *
+ * Current approach is to capture the 'thr' return value and store
+ * a reference to 'thr' in the caller value stack temporarily. This
+ * keeps 'thr' reachable until final yield/return handling which
+ * removes the references atomatically.
+ */
- duk_hthread_terminate(thr); /* updates thread state, minimizes its allocations */
- DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
+ DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
+ duk_hthread_activation_unwind_norz(resumer); /* May remove last reference to 'thr', but is NORZ. */
+ duk_push_tval(resumer, thr->valstack_top - 1); /* Capture return value, side effect free. */
+ duk_push_hthread(resumer, thr); /* Make 'thr' reachable again, before side effects. */
+ duk_hthread_terminate(thr); /* Updates thread state, minimizes its allocations. */
thr->resumer = NULL;
DUK_HTHREAD_DECREF(thr, resumer);
+ DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
+
resumer->state = DUK_HTHREAD_STATE_RUNNING;
DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
+
+ DUK_ASSERT(resumer->valstack_top - 2 >= resumer->valstack_bottom);
+ duk__handle_yield(thr, resumer, resumer->valstack_top - 2);
+ thr = NULL; /* 'thr' invalidated by call */
+
#if 0
thr = resumer; /* not needed */
#endif
@@ -73523,7 +78919,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation *
#else
/* Without coroutine support this case should never happen. */
DUK_ERROR_INTERNAL(thr);
- return DUK__RETHAND_FINISHED; /* not executed */
+ DUK_WO_NORETURN(return 0;);
#endif
}
@@ -73554,8 +78950,8 @@ DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation *
#if defined(DUK_USE_INTERRUPT_COUNTER)
-#define DUK__INT_NOACTION 0 /* no specific action, resume normal execution */
-#define DUK__INT_RESTART 1 /* must "goto restart_execution", e.g. breakpoints changed */
+#define DUK__INT_NOACTION 0 /* no specific action, resume normal execution */
+#define DUK__INT_RESTART 1 /* must "goto restart_execution", e.g. breakpoints changed */
#if defined(DUK_USE_DEBUGGER_SUPPORT)
DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_immediate, duk_small_uint_t *out_interrupt_retval) {
@@ -73566,7 +78962,7 @@ DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_
duk_bool_t process_messages;
duk_bool_t processed_messages = 0;
- DUK_ASSERT(thr->heap->dbg_processing == 0); /* don't re-enter e.g. during Eval */
+ DUK_ASSERT(thr->heap->dbg_processing == 0); /* don't re-enter e.g. during Eval */
act = thr->callstack_curr;
DUK_ASSERT(act != NULL);
@@ -73589,17 +78985,14 @@ DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_
* Breakpoint and step state checks
*/
- if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
- (thr->heap->dbg_pause_act == thr->callstack_curr)) {
+ if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE || (thr->heap->dbg_pause_act == thr->callstack_curr)) {
line = duk_debug_curr_line(thr);
if (act->prev_line != line) {
/* Stepped? Step out is handled by callstack unwind. */
if ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
- (thr->heap->dbg_pause_act == thr->callstack_curr) &&
- (line != thr->heap->dbg_pause_startline)) {
- DUK_D(DUK_DPRINT("PAUSE TRIGGERED by line change, at line %ld",
- (long) line));
+ (thr->heap->dbg_pause_act == thr->callstack_curr) && (line != thr->heap->dbg_pause_startline)) {
+ DUK_D(DUK_DPRINT("PAUSE TRIGGERED by line change, at line %ld", (long) line));
duk_debug_set_paused(thr->heap);
}
@@ -73625,7 +79018,8 @@ DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_
DUK_ASSERT(bp->filename != NULL);
if (act->prev_line != bp->line && line == bp->line) {
DUK_D(DUK_DPRINT("PAUSE TRIGGERED by breakpoint at %!O:%ld",
- (duk_heaphdr *) bp->filename, (long) bp->line));
+ (duk_heaphdr *) bp->filename,
+ (long) bp->line));
duk_debug_set_paused(thr->heap);
}
}
@@ -73673,7 +79067,7 @@ DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_
if (diff_last < 0.0 || diff_last >= (duk_double_t) DUK_HEAP_DBG_RATELIMIT_MILLISECS) {
/* Monotonic time should not experience time jumps,
* but the provider may be missing and we're actually
- * using Ecmascript time. So, tolerate negative values
+ * using ECMAScript time. So, tolerate negative values
* so that a time jump works reasonably.
*
* Same interval is now used for status sending and
@@ -73718,11 +79112,10 @@ DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_
if (duk_debug_is_attached(thr->heap)) {
DUK_ASSERT(act == thr->callstack_curr);
DUK_ASSERT(act != NULL);
- if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
- (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE) ||
+ if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE || (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE) ||
((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
thr->heap->dbg_pause_act == thr->callstack_curr) ||
- DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {
+ DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {
*out_immediate = 1;
}
@@ -73744,9 +79137,9 @@ DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_
DUK_D(DUK_DPRINT("debugger became detached, resume normal execution"));
}
}
-#endif /* DUK_USE_DEBUGGER_SUPPORT */
+#endif /* DUK_USE_DEBUGGER_SUPPORT */
-DUK_LOCAL DUK__NOINLINE_PERF DUK_COLD duk_small_uint_t duk__executor_interrupt(duk_hthread *thr) {
+DUK_LOCAL DUK_EXEC_NOINLINE_PERF DUK_COLD duk_small_uint_t duk__executor_interrupt(duk_hthread *thr) {
duk_int_t ctr;
duk_activation *act;
duk_hcompfunc *fun;
@@ -73761,8 +79154,10 @@ DUK_LOCAL DUK__NOINLINE_PERF DUK_COLD duk_small_uint_t duk__executor_interrupt(d
thr->heap->inst_count_interrupt += thr->interrupt_init;
DUK_DD(DUK_DDPRINT("execution interrupt, counter=%ld, init=%ld, "
"instruction counts: executor=%ld, interrupt=%ld",
- (long) thr->interrupt_counter, (long) thr->interrupt_init,
- (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
+ (long) thr->interrupt_counter,
+ (long) thr->interrupt_init,
+ (long) thr->heap->inst_count_exec,
+ (long) thr->heap->inst_count_interrupt));
#endif
retval = DUK__INT_NOACTION;
@@ -73822,19 +79217,19 @@ DUK_LOCAL DUK__NOINLINE_PERF DUK_COLD duk_small_uint_t duk__executor_interrupt(d
thr->interrupt_counter = 0;
DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);
DUK_ERROR_RANGE(thr, "execution timeout");
+ DUK_WO_NORETURN(return 0;);
}
-#endif /* DUK_USE_EXEC_TIMEOUT_CHECK */
+#endif /* DUK_USE_EXEC_TIMEOUT_CHECK */
#if defined(DUK_USE_DEBUGGER_SUPPORT)
- if (!thr->heap->dbg_processing &&
- (thr->heap->dbg_read_cb != NULL || thr->heap->dbg_detaching)) {
+ if (!thr->heap->dbg_processing && (thr->heap->dbg_read_cb != NULL || thr->heap->dbg_detaching)) {
/* Avoid recursive re-entry; enter when we're attached or
* detaching (to finish off the pending detach).
*/
duk__interrupt_handle_debugger(thr, &immediate, &retval);
DUK_ASSERT(act == thr->callstack_curr);
}
-#endif /* DUK_USE_DEBUGGER_SUPPORT */
+#endif /* DUK_USE_DEBUGGER_SUPPORT */
/*
* Update the interrupt counter
@@ -73857,7 +79252,7 @@ DUK_LOCAL DUK__NOINLINE_PERF DUK_COLD duk_small_uint_t duk__executor_interrupt(d
return retval;
}
-#endif /* DUK_USE_INTERRUPT_COUNTER */
+#endif /* DUK_USE_INTERRUPT_COUNTER */
/*
* Debugger handling for executor restart
@@ -73885,7 +79280,7 @@ DUK_LOCAL void duk__executor_recheck_debugger(duk_hthread *thr, duk_activation *
bp_active = heap->dbg_breakpoints_active;
act->flags &= ~DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
- tv_tmp = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) fun, DUK_HTHREAD_STRING_FILE_NAME(thr));
+ tv_tmp = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) fun, DUK_STRIDX_FILE_NAME);
if (tv_tmp && DUK_TVAL_IS_STRING(tv_tmp)) {
filename = DUK_TVAL_GET_STRING(tv_tmp);
@@ -73925,8 +79320,7 @@ DUK_LOCAL void duk__executor_recheck_debugger(duk_hthread *thr, duk_activation *
duk_hcompfunc *inner_fun;
duk_bool_t bp_match;
- if (bp->filename == filename &&
- bp->line >= fun->start_line && bp->line <= fun->end_line) {
+ if (bp->filename == filename && bp->line >= fun->start_line && bp->line <= fun->end_line) {
bp_match = 1;
DUK_DD(DUK_DDPRINT("breakpoint filename and line match: "
"%s:%ld vs. %s (line %ld vs. %ld-%ld)",
@@ -73963,13 +79357,12 @@ DUK_LOCAL void duk__executor_recheck_debugger(duk_hthread *thr, duk_activation *
}
}
- *bp_active = NULL; /* terminate */
+ *bp_active = NULL; /* terminate */
DUK_DD(DUK_DDPRINT("ACTIVE BREAKPOINTS: %ld", (long) (bp_active - thr->heap->dbg_breakpoints_active)));
/* Force pause if we were doing "step into" in another activation. */
- if ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) &&
- thr->heap->dbg_pause_act != thr->callstack_curr) {
+ if ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) && thr->heap->dbg_pause_act != thr->callstack_curr) {
DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function entry"));
duk_debug_set_paused(thr->heap);
}
@@ -73977,10 +79370,8 @@ DUK_LOCAL void duk__executor_recheck_debugger(duk_hthread *thr, duk_activation *
/* Force interrupt right away if we're paused or in "checked mode".
* Step out is handled by callstack unwind.
*/
- if ((act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE) ||
- DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ||
- ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
- thr->heap->dbg_pause_act == thr->callstack_curr)) {
+ if ((act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE) || DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ||
+ ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) && thr->heap->dbg_pause_act == thr->callstack_curr)) {
/* We'll need to interrupt early so recompute the init
* counter to reflect the number of bytecode instructions
* executed so that step counts for e.g. debugger rate
@@ -73991,14 +79382,14 @@ DUK_LOCAL void duk__executor_recheck_debugger(duk_hthread *thr, duk_activation *
thr->interrupt_counter = 0;
}
}
-#endif /* DUK_USE_DEBUGGER_SUPPORT */
+#endif /* DUK_USE_DEBUGGER_SUPPORT */
/*
* Opcode handlers for opcodes with a lot of code and which are relatively
* rare; NOINLINE to reduce amount of code in main bytecode dispatcher.
*/
-DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_initset_initget(duk_hthread *thr, duk_uint_fast32_t ins) {
+DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_op_initset_initget(duk_hthread *thr, duk_uint_fast32_t ins) {
duk_bool_t is_set = (DUK_DEC_OP(ins) == DUK_OP_INITSET);
duk_uint_fast_t idx;
duk_uint_t defprop_flags;
@@ -74015,23 +79406,19 @@ DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_initset_initget(duk_hthread *th
/* This could be made more optimal by accessing internals directly. */
idx = (duk_uint_fast_t) DUK_DEC_BC(ins);
- duk_dup(thr, (duk_idx_t) (idx + 0)); /* key */
- duk_dup(thr, (duk_idx_t) (idx + 1)); /* getter/setter */
+ duk_dup(thr, (duk_idx_t) (idx + 0)); /* key */
+ duk_dup(thr, (duk_idx_t) (idx + 1)); /* getter/setter */
if (is_set) {
- defprop_flags = DUK_DEFPROP_HAVE_SETTER |
- DUK_DEFPROP_FORCE |
- DUK_DEFPROP_SET_ENUMERABLE |
- DUK_DEFPROP_SET_CONFIGURABLE;
+ defprop_flags =
+ DUK_DEFPROP_HAVE_SETTER | DUK_DEFPROP_FORCE | DUK_DEFPROP_SET_ENUMERABLE | DUK_DEFPROP_SET_CONFIGURABLE;
} else {
- defprop_flags = DUK_DEFPROP_HAVE_GETTER |
- DUK_DEFPROP_FORCE |
- DUK_DEFPROP_SET_ENUMERABLE |
- DUK_DEFPROP_SET_CONFIGURABLE;
+ defprop_flags =
+ DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_FORCE | DUK_DEFPROP_SET_ENUMERABLE | DUK_DEFPROP_SET_CONFIGURABLE;
}
duk_def_prop(thr, (duk_idx_t) DUK_DEC_A(ins), defprop_flags);
}
-DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_trycatch(duk_hthread *thr, duk_uint_fast32_t ins, duk_instr_t *curr_pc) {
+DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_op_trycatch(duk_hthread *thr, duk_uint_fast32_t ins, duk_instr_t *curr_pc) {
duk_activation *act;
duk_catcher *cat;
duk_tval *tv1;
@@ -74091,7 +79478,7 @@ DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_trycatch(duk_hthread *thr, duk_
* error handling, so there's no side effect problem even if the
* error value has a finalizer.
*/
- duk_dup(thr, (duk_idx_t) bc); /* Stabilize value. */
+ duk_dup(thr, (duk_idx_t) bc); /* Stabilize value. */
duk_to_undefined(thr, (duk_idx_t) bc);
duk_to_undefined(thr, (duk_idx_t) (bc + 1));
@@ -74106,7 +79493,7 @@ DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_trycatch(duk_hthread *thr, duk_
cat->flags = DUK_CAT_TYPE_TCF;
cat->h_varname = NULL;
- cat->pc_base = (duk_instr_t *) curr_pc; /* pre-incremented, points to first jump slot */
+ cat->pc_base = (duk_instr_t *) curr_pc; /* pre-incremented, points to first jump slot */
cat->idx_base = (duk_size_t) (thr->valstack_bottom - thr->valstack) + bc;
act = thr->callstack_curr;
@@ -74145,7 +79532,7 @@ DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_trycatch(duk_hthread *thr, duk_
duk_js_init_activation_environment_records_delayed(thr, act);
DUK_ASSERT(act == thr->callstack_curr);
- DUK_UNREF(act); /* 'act' is no longer accessed, scanbuild fix */
+ DUK_UNREF(act); /* 'act' is no longer accessed, scanbuild fix */
}
DUK_ASSERT(act->lex_env != NULL);
DUK_ASSERT(act->var_env != NULL);
@@ -74158,22 +79545,20 @@ DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_trycatch(duk_hthread *thr, duk_
* so avoid side effects very carefully until it is
* referenced.
*/
- env = duk_hobjenv_alloc(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
+ env = duk_hobjenv_alloc(thr, DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
DUK_ASSERT(env != NULL);
DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
- env->target = target; /* always provideThis=true */
+ env->target = target; /* always provideThis=true */
DUK_HOBJECT_INCREF(thr, target);
env->has_this = 1;
- DUK_ASSERT_HOBJENV_VALID(env);
+ DUK_HOBJENV_ASSERT_VALID(env);
DUK_DDD(DUK_DDDPRINT("environment for with binding: %!iO", env));
DUK_ASSERT(act == thr->callstack_curr);
DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
DUK_ASSERT(act->lex_env != NULL);
DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) env, act->lex_env);
- act->lex_env = (duk_hobject *) env; /* Now reachable. */
+ act->lex_env = (duk_hobject *) env; /* Now reachable. */
DUK_HOBJECT_INCREF(thr, (duk_hobject *) env);
/* Net refcount change to act->lex_env is 0: incref for env's
* prototype, decref for act->lex_env overwrite.
@@ -74182,7 +79567,7 @@ DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_trycatch(duk_hthread *thr, duk_
/* Set catcher lex_env active (affects unwind)
* only when the whole setup is complete.
*/
- cat = act->cat; /* XXX: better to relookup? not mandatory because 'cat' is stable */
+ cat = act->cat; /* XXX: better to relookup? not mandatory because 'cat' is stable */
cat->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE;
} else {
;
@@ -74191,12 +79576,14 @@ DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_trycatch(duk_hthread *thr, duk_
DUK_DDD(DUK_DDDPRINT("TRYCATCH catcher: flags=0x%08lx, pc_base=%ld, "
"idx_base=%ld, h_varname=%!O",
(unsigned long) cat->flags,
- (long) cat->pc_base, (long) cat->idx_base, (duk_heaphdr *) cat->h_varname));
+ (long) cat->pc_base,
+ (long) cat->idx_base,
+ (duk_heaphdr *) cat->h_varname));
duk_pop_unsafe(thr);
}
-DUK_LOCAL DUK__NOINLINE_PERF duk_instr_t *duk__handle_op_endtry(duk_hthread *thr, duk_uint_fast32_t ins) {
+DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_instr_t *duk__handle_op_endtry(duk_hthread *thr, duk_uint_fast32_t ins) {
duk_activation *act;
duk_catcher *cat;
duk_tval *tv1;
@@ -74221,26 +79608,27 @@ DUK_LOCAL DUK__NOINLINE_PERF duk_instr_t *duk__handle_op_endtry(duk_hthread *thr
tv1 = thr->valstack + cat->idx_base;
DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
- DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1); /* side effects */
+ DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1); /* side effects */
tv1 = NULL;
tv1 = thr->valstack + cat->idx_base + 1;
DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
- DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL); /* side effects */
+ DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL); /* side effects */
tv1 = NULL;
DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
} else {
- DUK_DDD(DUK_DDDPRINT("ENDTRY: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
+ DUK_DDD(
+ DUK_DDDPRINT("ENDTRY: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
- duk_hthread_catcher_unwind_norz(thr, act); /* lexenv may be set for 'with' binding */
+ duk_hthread_catcher_unwind_norz(thr, act); /* lexenv may be set for 'with' binding */
/* no need to unwind callstack */
}
- return pc_base + 1; /* new curr_pc value */
+ return pc_base + 1; /* new curr_pc value */
}
-DUK_LOCAL DUK__NOINLINE_PERF duk_instr_t *duk__handle_op_endcatch(duk_hthread *thr, duk_uint_fast32_t ins) {
+DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_instr_t *duk__handle_op_endcatch(duk_hthread *thr, duk_uint_fast32_t ins) {
duk_activation *act;
duk_catcher *cat;
duk_tval *tv1;
@@ -74253,7 +79641,7 @@ DUK_LOCAL DUK__NOINLINE_PERF duk_instr_t *duk__handle_op_endcatch(duk_hthread *t
DUK_ASSERT(act != NULL);
cat = act->cat;
DUK_ASSERT(cat != NULL);
- DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat)); /* cleared before entering catch part */
+ DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat)); /* cleared before entering catch part */
if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
duk_hobject *prev_env;
@@ -74269,7 +79657,7 @@ DUK_LOCAL DUK__NOINLINE_PERF duk_instr_t *duk__handle_op_endcatch(duk_hthread *t
act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, prev_env);
DUK_CAT_CLEAR_LEXENV_ACTIVE(cat);
DUK_HOBJECT_INCREF(thr, act->lex_env);
- DUK_HOBJECT_DECREF(thr, prev_env); /* side effects */
+ DUK_HOBJECT_DECREF(thr, prev_env); /* side effects */
DUK_ASSERT(act == thr->callstack_curr);
DUK_ASSERT(act != NULL);
@@ -74282,26 +79670,29 @@ DUK_LOCAL DUK__NOINLINE_PERF duk_instr_t *duk__handle_op_endcatch(duk_hthread *t
tv1 = thr->valstack + cat->idx_base;
DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
- DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1); /* side effects */
+ DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1); /* side effects */
tv1 = NULL;
tv1 = thr->valstack + cat->idx_base + 1;
DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
- DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL); /* side effects */
+ DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL); /* side effects */
tv1 = NULL;
DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
} else {
- DUK_DDD(DUK_DDDPRINT("ENDCATCH: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
+ DUK_DDD(
+ DUK_DDDPRINT("ENDCATCH: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
duk_hthread_catcher_unwind_norz(thr, act);
/* no need to unwind callstack */
}
- return pc_base + 1; /* new curr_pc value */
+ return pc_base + 1; /* new curr_pc value */
}
-DUK_LOCAL DUK__NOINLINE_PERF duk_small_uint_t duk__handle_op_endfin(duk_hthread *thr, duk_uint_fast32_t ins, duk_activation *entry_act) {
+DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_small_uint_t duk__handle_op_endfin(duk_hthread *thr,
+ duk_uint_fast32_t ins,
+ duk_activation *entry_act) {
duk_activation *act;
duk_tval *tv1;
duk_uint_t reg_catch;
@@ -74323,7 +79714,7 @@ DUK_LOCAL DUK__NOINLINE_PERF duk_small_uint_t duk__handle_op_endfin(duk_hthread
(duk_tval *) (thr->valstack_bottom + reg_catch + 0),
(duk_tval *) (thr->valstack_bottom + reg_catch + 1)));
- tv1 = thr->valstack_bottom + reg_catch + 1; /* type */
+ tv1 = thr->valstack_bottom + reg_catch + 1; /* type */
DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
#if defined(DUK_USE_FASTINT)
DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
@@ -74332,7 +79723,7 @@ DUK_LOCAL DUK__NOINLINE_PERF duk_small_uint_t duk__handle_op_endfin(duk_hthread
cont_type = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
#endif
- tv1--; /* value */
+ tv1--; /* value */
switch (cont_type) {
case DUK_LJ_TYPE_NORMAL: {
@@ -74341,11 +79732,12 @@ DUK_LOCAL DUK__NOINLINE_PERF duk_small_uint_t duk__handle_op_endfin(duk_hthread
duk_hthread_catcher_unwind_norz(thr, act);
/* no need to unwind callstack */
- return 0; /* restart execution */
+ return 0; /* restart execution */
}
case DUK_LJ_TYPE_RETURN: {
DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'return' complation -> dismantle "
- "catcher, handle return, lj.value1=%!T", tv1));
+ "catcher, handle return, lj.value1=%!T",
+ tv1));
/* Not necessary to unwind catch stack: return handling will
* do it. The finally flag of 'cat' is no longer set. The
@@ -74355,12 +79747,12 @@ DUK_LOCAL DUK__NOINLINE_PERF duk_small_uint_t duk__handle_op_endfin(duk_hthread
duk_push_tval(thr, tv1);
ret_result = duk__handle_return(thr, entry_act);
if (ret_result == DUK__RETHAND_RESTART) {
- return 0; /* restart execution */
+ return 0; /* restart execution */
}
DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED);
DUK_DDD(DUK_DDDPRINT("exiting executor after ENDFIN and RETURN (pseudo) longjmp type"));
- return 1; /* exit executor */
+ return 1; /* exit executor */
}
case DUK_LJ_TYPE_BREAK:
case DUK_LJ_TYPE_CONTINUE: {
@@ -74382,7 +79774,7 @@ DUK_LOCAL DUK__NOINLINE_PERF duk_small_uint_t duk__handle_op_endfin(duk_hthread
#endif
lj_type = cont_type;
duk__handle_break_or_continue(thr, label_id, lj_type);
- return 0; /* restart execution */
+ return 0; /* restart execution */
}
default: {
DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with abrupt completion, lj_type=%ld -> "
@@ -74392,7 +79784,7 @@ DUK_LOCAL DUK__NOINLINE_PERF duk_small_uint_t duk__handle_op_endfin(duk_hthread
duk_err_setup_ljstate1(thr, (duk_small_uint_t) cont_type, tv1);
/* No debugger Throw notify check on purpose (rethrow). */
- DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* always in executor */
+ DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* always in executor */
duk_err_longjmp(thr);
DUK_UNREACHABLE();
}
@@ -74402,7 +79794,7 @@ DUK_LOCAL DUK__NOINLINE_PERF duk_small_uint_t duk__handle_op_endfin(duk_hthread
return 0;
}
-DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_initenum(duk_hthread *thr, duk_uint_fast32_t ins) {
+DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_op_initenum(duk_hthread *thr, duk_uint_fast32_t ins) {
duk_small_uint_t b;
duk_small_uint_t c;
@@ -74425,12 +79817,12 @@ DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_initenum(duk_hthread *thr, duk_
} else {
duk_dup(thr, (duk_idx_t) c);
duk_to_object(thr, -1);
- duk_hobject_enumerator_create(thr, 0 /*enum_flags*/); /* [ ... val ] --> [ ... enum ] */
+ duk_hobject_enumerator_create(thr, 0 /*enum_flags*/); /* [ ... val ] --> [ ... enum ] */
duk_replace(thr, (duk_idx_t) b);
}
}
-DUK_LOCAL DUK__NOINLINE_PERF duk_small_uint_t duk__handle_op_nextenum(duk_hthread *thr, duk_uint_fast32_t ins) {
+DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_small_uint_t duk__handle_op_nextenum(duk_hthread *thr, duk_uint_fast32_t ins) {
duk_small_uint_t b;
duk_small_uint_t c;
duk_small_uint_t pc_skip = 0;
@@ -74457,13 +79849,12 @@ DUK_LOCAL DUK__NOINLINE_PERF duk_small_uint_t duk__handle_op_nextenum(duk_hthrea
duk_dup(thr, (duk_idx_t) c);
if (duk_hobject_enumerator_next(thr, 0 /*get_value*/)) {
/* [ ... enum ] -> [ ... next_key ] */
- DUK_DDD(DUK_DDDPRINT("enum active, next key is %!T, skip jump slot ",
- (duk_tval *) duk_get_tval(thr, -1)));
+ DUK_DDD(DUK_DDDPRINT("enum active, next key is %!T, skip jump slot ", (duk_tval *) duk_get_tval(thr, -1)));
pc_skip = 1;
} else {
/* [ ... enum ] -> [ ... ] */
DUK_DDD(DUK_DDDPRINT("enum finished, execute jump slot"));
- DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top)); /* valstack policy */
+ DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top)); /* valstack policy */
thr->valstack_top++;
}
duk_replace(thr, (duk_idx_t) b);
@@ -74483,7 +79874,7 @@ DUK_LOCAL DUK__NOINLINE_PERF duk_small_uint_t duk__handle_op_nextenum(duk_hthrea
DUK_LOCAL duk_bool_t duk__executor_handle_call(duk_hthread *thr, duk_idx_t idx, duk_idx_t nargs, duk_small_uint_t call_flags) {
duk_bool_t rc;
- duk_set_top_unsafe(thr, (duk_idx_t) (idx + nargs + 2)); /* [ ... func this arg1 ... argN ] */
+ duk_set_top_unsafe(thr, (duk_idx_t) (idx + nargs + 2)); /* [ ... func this arg1 ... argN ] */
/* Attempt an Ecma-to-Ecma call setup. If the call
* target is (directly or indirectly) Reflect.construct(),
@@ -74507,7 +79898,7 @@ DUK_LOCAL duk_bool_t duk__executor_handle_call(duk_hthread *thr, duk_idx_t idx,
}
/*
- * Ecmascript bytecode executor.
+ * ECMAScript bytecode executor.
*
* Resume execution for the current thread from its current activation.
* Returns when execution would return from the entry level activation,
@@ -74516,7 +79907,7 @@ DUK_LOCAL duk_bool_t duk__executor_handle_call(duk_hthread *thr, duk_idx_t idx,
* a longjmp() with type DUK_LJ_TYPE_THROW is called on the entry level
* setjmp() jmpbuf.
*
- * Ecmascript function calls and coroutine resumptions are handled
+ * ECMAScript function calls and coroutine resumptions are handled
* internally (by the outer executor function) without recursive C calls.
* Other function calls are handled using duk_handle_call(), increasing
* C recursion depth.
@@ -74537,22 +79928,22 @@ DUK_LOCAL duk_bool_t duk__executor_handle_call(duk_hthread *thr, duk_idx_t idx,
* difference and the best option is architecture dependent.
*/
#if defined(DUK_USE_EXEC_FUN_LOCAL)
-#define DUK__FUN() fun
+#define DUK__FUN() fun
#else
-#define DUK__FUN() ((duk_hcompfunc *) DUK_ACT_GET_FUNC((thr)->callstack_curr))
+#define DUK__FUN() ((duk_hcompfunc *) DUK_ACT_GET_FUNC((thr)->callstack_curr))
#endif
/* Strict flag. */
-#define DUK__STRICT() ((duk_small_uint_t) DUK_HOBJECT_HAS_STRICT((duk_hobject *) DUK__FUN()))
+#define DUK__STRICT() ((duk_small_uint_t) DUK_HOBJECT_HAS_STRICT((duk_hobject *) DUK__FUN()))
/* Reg/const access macros: these are very footprint and performance sensitive
* so modify with care. Arguments are sometimes evaluated multiple times which
* is not ideal.
*/
-#define DUK__REG(x) (*(thr->valstack_bottom + (x)))
-#define DUK__REGP(x) (thr->valstack_bottom + (x))
-#define DUK__CONST(x) (*(consts + (x)))
-#define DUK__CONSTP(x) (consts + (x))
+#define DUK__REG(x) (*(thr->valstack_bottom + (x)))
+#define DUK__REGP(x) (thr->valstack_bottom + (x))
+#define DUK__CONST(x) (*(consts + (x)))
+#define DUK__CONSTP(x) (consts + (x))
/* Reg/const access macros which take the 32-bit instruction and avoid an
* explicit field decoding step by using shifts and masks. These must be
@@ -74561,67 +79952,74 @@ DUK_LOCAL duk_bool_t duk__executor_handle_call(duk_hthread *thr, duk_idx_t idx,
* instead of a duk_tval offset which needs further shifting (which is an
* issue on some, but not all, CPUs).
*/
-#define DUK__RCBIT_B DUK_BC_REGCONST_B
-#define DUK__RCBIT_C DUK_BC_REGCONST_C
+#define DUK__RCBIT_B DUK_BC_REGCONST_B
+#define DUK__RCBIT_C DUK_BC_REGCONST_C
#if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)
#if defined(DUK_USE_PACKED_TVAL)
-#define DUK__TVAL_SHIFT 3 /* sizeof(duk_tval) == 8 */
+#define DUK__TVAL_SHIFT 3 /* sizeof(duk_tval) == 8 */
#else
-#define DUK__TVAL_SHIFT 4 /* sizeof(duk_tval) == 16; not always the case so also asserted for */
-#endif
-#define DUK__SHIFT_A (DUK_BC_SHIFT_A - DUK__TVAL_SHIFT)
-#define DUK__SHIFT_B (DUK_BC_SHIFT_B - DUK__TVAL_SHIFT)
-#define DUK__SHIFT_C (DUK_BC_SHIFT_C - DUK__TVAL_SHIFT)
-#define DUK__SHIFT_BC (DUK_BC_SHIFT_BC - DUK__TVAL_SHIFT)
-#define DUK__MASK_A (DUK_BC_UNSHIFTED_MASK_A << DUK__TVAL_SHIFT)
-#define DUK__MASK_B (DUK_BC_UNSHIFTED_MASK_B << DUK__TVAL_SHIFT)
-#define DUK__MASK_C (DUK_BC_UNSHIFTED_MASK_C << DUK__TVAL_SHIFT)
-#define DUK__MASK_BC (DUK_BC_UNSHIFTED_MASK_BC << DUK__TVAL_SHIFT)
-#define DUK__BYTEOFF_A(ins) (((ins) >> DUK__SHIFT_A) & DUK__MASK_A)
-#define DUK__BYTEOFF_B(ins) (((ins) >> DUK__SHIFT_B) & DUK__MASK_B)
-#define DUK__BYTEOFF_C(ins) (((ins) >> DUK__SHIFT_C) & DUK__MASK_C)
-#define DUK__BYTEOFF_BC(ins) (((ins) >> DUK__SHIFT_BC) & DUK__MASK_BC)
-
-#define DUK__REGP_A(ins) ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_A((ins))))
-#define DUK__REGP_B(ins) ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_B((ins))))
-#define DUK__REGP_C(ins) ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_C((ins))))
-#define DUK__REGP_BC(ins) ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_BC((ins))))
-#define DUK__CONSTP_A(ins) ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_A((ins))))
-#define DUK__CONSTP_B(ins) ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_B((ins))))
-#define DUK__CONSTP_C(ins) ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_C((ins))))
-#define DUK__CONSTP_BC(ins) ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_BC((ins))))
-#define DUK__REGCONSTP_B(ins) ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) & DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_B((ins))))
-#define DUK__REGCONSTP_C(ins) ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) & DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_C((ins))))
-#else /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
+#define DUK__TVAL_SHIFT 4 /* sizeof(duk_tval) == 16; not always the case so also asserted for */
+#endif
+#define DUK__SHIFT_A (DUK_BC_SHIFT_A - DUK__TVAL_SHIFT)
+#define DUK__SHIFT_B (DUK_BC_SHIFT_B - DUK__TVAL_SHIFT)
+#define DUK__SHIFT_C (DUK_BC_SHIFT_C - DUK__TVAL_SHIFT)
+#define DUK__SHIFT_BC (DUK_BC_SHIFT_BC - DUK__TVAL_SHIFT)
+#define DUK__MASK_A (DUK_BC_UNSHIFTED_MASK_A << DUK__TVAL_SHIFT)
+#define DUK__MASK_B (DUK_BC_UNSHIFTED_MASK_B << DUK__TVAL_SHIFT)
+#define DUK__MASK_C (DUK_BC_UNSHIFTED_MASK_C << DUK__TVAL_SHIFT)
+#define DUK__MASK_BC (DUK_BC_UNSHIFTED_MASK_BC << DUK__TVAL_SHIFT)
+#define DUK__BYTEOFF_A(ins) (((ins) >> DUK__SHIFT_A) & DUK__MASK_A)
+#define DUK__BYTEOFF_B(ins) (((ins) >> DUK__SHIFT_B) & DUK__MASK_B)
+#define DUK__BYTEOFF_C(ins) (((ins) >> DUK__SHIFT_C) & DUK__MASK_C)
+#define DUK__BYTEOFF_BC(ins) (((ins) >> DUK__SHIFT_BC) & DUK__MASK_BC)
+
+#define DUK__REGP_A(ins) ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_A((ins))))
+#define DUK__REGP_B(ins) ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_B((ins))))
+#define DUK__REGP_C(ins) ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_C((ins))))
+#define DUK__REGP_BC(ins) ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_BC((ins))))
+#define DUK__CONSTP_A(ins) ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_A((ins))))
+#define DUK__CONSTP_B(ins) ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_B((ins))))
+#define DUK__CONSTP_C(ins) ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_C((ins))))
+#define DUK__CONSTP_BC(ins) ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_BC((ins))))
+#define DUK__REGCONSTP_B(ins) \
+ ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) &DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_B((ins))))
+#define DUK__REGCONSTP_C(ins) \
+ ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) &DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_C((ins))))
+#else /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
/* Safe alternatives, no assumption about duk_tval size. */
-#define DUK__REGP_A(ins) DUK__REGP(DUK_DEC_A((ins)))
-#define DUK__REGP_B(ins) DUK__REGP(DUK_DEC_B((ins)))
-#define DUK__REGP_C(ins) DUK__REGP(DUK_DEC_C((ins)))
-#define DUK__REGP_BC(ins) DUK__REGP(DUK_DEC_BC((ins)))
-#define DUK__CONSTP_A(ins) DUK__CONSTP(DUK_DEC_A((ins)))
-#define DUK__CONSTP_B(ins) DUK__CONSTP(DUK_DEC_B((ins)))
-#define DUK__CONSTP_C(ins) DUK__CONSTP(DUK_DEC_C((ins)))
-#define DUK__CONSTP_BC(ins) DUK__CONSTP(DUK_DEC_BC((ins)))
-#define DUK__REGCONSTP_B(ins) ((((ins) & DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK_DEC_B((ins)))
-#define DUK__REGCONSTP_C(ins) ((((ins) & DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK_DEC_C((ins)))
-#endif /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
+#define DUK__REGP_A(ins) DUK__REGP(DUK_DEC_A((ins)))
+#define DUK__REGP_B(ins) DUK__REGP(DUK_DEC_B((ins)))
+#define DUK__REGP_C(ins) DUK__REGP(DUK_DEC_C((ins)))
+#define DUK__REGP_BC(ins) DUK__REGP(DUK_DEC_BC((ins)))
+#define DUK__CONSTP_A(ins) DUK__CONSTP(DUK_DEC_A((ins)))
+#define DUK__CONSTP_B(ins) DUK__CONSTP(DUK_DEC_B((ins)))
+#define DUK__CONSTP_C(ins) DUK__CONSTP(DUK_DEC_C((ins)))
+#define DUK__CONSTP_BC(ins) DUK__CONSTP(DUK_DEC_BC((ins)))
+#define DUK__REGCONSTP_B(ins) ((((ins) &DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK_DEC_B((ins)))
+#define DUK__REGCONSTP_C(ins) ((((ins) &DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK_DEC_C((ins)))
+#endif /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
#if defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)
-#define DUK__INTERNAL_ERROR(msg) do { \
+#define DUK__INTERNAL_ERROR(msg) \
+ do { \
DUK_ERROR_ERROR(thr, (msg)); \
+ DUK_WO_NORETURN(return;); \
} while (0)
#else
-#define DUK__INTERNAL_ERROR(msg) do { \
+#define DUK__INTERNAL_ERROR(msg) \
+ do { \
goto internal_error; \
} while (0)
#endif
-#define DUK__SYNC_CURR_PC() do { \
+#define DUK__SYNC_CURR_PC() \
+ do { \
duk_activation *duk__act; \
duk__act = thr->callstack_curr; \
duk__act->curr_pc = curr_pc; \
} while (0)
-#define DUK__SYNC_AND_NULL_CURR_PC() do { \
+#define DUK__SYNC_AND_NULL_CURR_PC() \
+ do { \
duk_activation *duk__act; \
duk__act = thr->callstack_curr; \
duk__act->curr_pc = curr_pc; \
@@ -74629,19 +80027,22 @@ DUK_LOCAL duk_bool_t duk__executor_handle_call(duk_hthread *thr, duk_idx_t idx,
} while (0)
#if defined(DUK_USE_EXEC_PREFER_SIZE)
-#define DUK__LOOKUP_INDIRECT(idx) do { \
+#define DUK__LOOKUP_INDIRECT(idx) \
+ do { \
(idx) = (duk_uint_fast_t) duk_get_uint(thr, (duk_idx_t) (idx)); \
} while (0)
#elif defined(DUK_USE_FASTINT)
-#define DUK__LOOKUP_INDIRECT(idx) do { \
+#define DUK__LOOKUP_INDIRECT(idx) \
+ do { \
duk_tval *tv_ind; \
tv_ind = DUK__REGP((idx)); \
DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \
- DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_ind)); /* compiler guarantees */ \
+ DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_ind)); /* compiler guarantees */ \
(idx) = (duk_uint_fast_t) DUK_TVAL_GET_FASTINT_U32(tv_ind); \
} while (0)
#else
-#define DUK__LOOKUP_INDIRECT(idx) do { \
+#define DUK__LOOKUP_INDIRECT(idx) \
+ do { \
duk_tval *tv_ind; \
tv_ind = DUK__REGP(idx); \
DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \
@@ -74652,7 +80053,8 @@ DUK_LOCAL duk_bool_t duk__executor_handle_call(duk_hthread *thr, duk_idx_t idx,
DUK_LOCAL void duk__handle_executor_error(duk_heap *heap,
duk_activation *entry_act,
duk_int_t entry_call_recursion_depth,
- duk_jmpbuf *entry_jmpbuf_ptr) {
+ duk_jmpbuf *entry_jmpbuf_ptr,
+ volatile duk_bool_t *out_delayed_catch_setup) {
duk_small_uint_t lj_ret;
/* Longjmp callers are required to sync-and-null thr->ptr_curr_pc
@@ -74672,7 +80074,7 @@ DUK_LOCAL void duk__handle_executor_error(duk_heap *heap,
*/
heap->lj.jmpbuf_ptr = (duk_jmpbuf *) entry_jmpbuf_ptr;
- lj_ret = duk__handle_longjmp(heap->curr_thread, entry_act);
+ lj_ret = duk__handle_longjmp(heap->curr_thread, entry_act, out_delayed_catch_setup);
/* Error handling complete, remove side effect protections.
*/
@@ -74693,8 +80095,8 @@ DUK_LOCAL void duk__handle_executor_error(duk_heap *heap,
* will be re-bumped by the longjmp.
*/
- DUK_ASSERT(lj_ret == DUK__LONGJMP_RETHROW); /* Rethrow error to calling state. */
- DUK_ASSERT(heap->lj.jmpbuf_ptr == entry_jmpbuf_ptr); /* Longjmp handling has restored jmpbuf_ptr. */
+ DUK_ASSERT(lj_ret == DUK__LONGJMP_RETHROW); /* Rethrow error to calling state. */
+ DUK_ASSERT(heap->lj.jmpbuf_ptr == entry_jmpbuf_ptr); /* Longjmp handling has restored jmpbuf_ptr. */
/* Thread may have changed, e.g. YIELD converted to THROW. */
duk_err_longjmp(heap->curr_thread);
@@ -74711,12 +80113,13 @@ DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) {
duk_jmpbuf *entry_jmpbuf_ptr;
duk_jmpbuf our_jmpbuf;
duk_heap *heap;
+ volatile duk_bool_t delayed_catch_setup = 0;
DUK_ASSERT(exec_thr != NULL);
DUK_ASSERT(exec_thr->heap != NULL);
DUK_ASSERT(exec_thr->heap->curr_thread != NULL);
DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR((duk_heaphdr *) exec_thr);
- DUK_ASSERT(exec_thr->callstack_top >= 1); /* at least one activation, ours */
+ DUK_ASSERT(exec_thr->callstack_top >= 1); /* at least one activation, ours */
DUK_ASSERT(exec_thr->callstack_curr != NULL);
DUK_ASSERT(DUK_ACT_GET_FUNC(exec_thr->callstack_curr) != NULL);
DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(exec_thr->callstack_curr)));
@@ -74749,6 +80152,17 @@ DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) {
DUK_ASSERT(heap->lj.jmpbuf_ptr == &our_jmpbuf);
if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
#endif
+ DUK_DDD(DUK_DDDPRINT("after setjmp, delayed catch setup: %ld\n", (long) delayed_catch_setup));
+
+ if (DUK_UNLIKELY(delayed_catch_setup != 0)) {
+ duk_hthread *thr = entry_thread->heap->curr_thread;
+
+ delayed_catch_setup = 0;
+ duk__handle_catch_part2(thr);
+ DUK_ASSERT(delayed_catch_setup == 0);
+ DUK_DDD(DUK_DDDPRINT("top after delayed catch setup: %ld", (long) duk_get_top(entry_thread)));
+ }
+
/* Execute bytecode until returned or longjmp(). */
duk__js_execute_bytecode_inner(entry_thread, entry_act);
@@ -74770,10 +80184,15 @@ DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) {
duk__handle_executor_error(heap,
entry_act,
entry_call_recursion_depth,
- entry_jmpbuf_ptr);
+ entry_jmpbuf_ptr,
+ &delayed_catch_setup);
}
#if defined(DUK_USE_CPP_EXCEPTIONS)
- catch (std::exception &exc) {
+ catch (duk_fatal_exception &exc) {
+ DUK_D(DUK_DPRINT("rethrow duk_fatal_exception"));
+ DUK_UNREF(exc);
+ throw;
+ } catch (std::exception &exc) {
const char *what = exc.what();
if (!what) {
what = "unknown";
@@ -74782,14 +80201,19 @@ DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) {
DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
try {
DUK_ASSERT(heap->curr_thread != NULL);
- DUK_ERROR_FMT1(heap->curr_thread, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
+ DUK_ERROR_FMT1(heap->curr_thread,
+ DUK_ERR_TYPE_ERROR,
+ "caught invalid c++ std::exception '%s' (perhaps thrown by user code)",
+ what);
+ DUK_WO_NORETURN(return;);
} catch (duk_internal_exception exc) {
DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
DUK_UNREF(exc);
duk__handle_executor_error(heap,
entry_act,
entry_call_recursion_depth,
- entry_jmpbuf_ptr);
+ entry_jmpbuf_ptr,
+ &delayed_catch_setup);
}
} catch (...) {
DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
@@ -74797,19 +80221,21 @@ DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) {
try {
DUK_ASSERT(heap->curr_thread != NULL);
DUK_ERROR_TYPE(heap->curr_thread, "caught invalid c++ exception (perhaps thrown by user code)");
+ DUK_WO_NORETURN(return;);
} catch (duk_internal_exception exc) {
DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
DUK_UNREF(exc);
duk__handle_executor_error(heap,
entry_act,
entry_call_recursion_depth,
- entry_jmpbuf_ptr);
+ entry_jmpbuf_ptr,
+ &delayed_catch_setup);
}
}
#endif
}
- DUK_UNREACHABLE();
+ DUK_WO_NORETURN(return;);
}
/* Inner executor, performance critical. */
@@ -74819,13 +80245,13 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
* but that eliminates performance benefits; aliasing guarantees
* should be enough though.
*/
- duk_instr_t *curr_pc; /* bytecode has a stable pointer */
+ duk_instr_t *curr_pc; /* bytecode has a stable pointer */
/* Hot variables for interpretation. Critical for performance,
* but must add sparingly to minimize register shuffling.
*/
- duk_hthread *thr; /* stable */
- duk_tval *consts; /* stable */
+ duk_hthread *thr; /* stable */
+ duk_tval *consts; /* stable */
duk_uint_fast32_t ins;
/* 'funcs' is quite rarely used, so no local for it */
#if defined(DUK_USE_EXEC_FUN_LOCAL)
@@ -74839,7 +80265,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
#endif
#if defined(DUK_USE_ASSERTIONS)
- duk_size_t valstack_top_base; /* valstack top, should match before interpreting each op (no leftovers) */
+ duk_size_t valstack_top_base; /* valstack top, should match before interpreting each op (no leftovers) */
#endif
/* Optimized reg/const access macros assume sizeof(duk_tval) to be
@@ -74895,7 +80321,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
* See execution.rst for discussion.
*/
- restart_execution:
+restart_execution:
/* Lookup current thread; use the stable 'entry_thread' for this to
* avoid clobber warnings. Any valid, reachable 'thr' value would be
@@ -74936,7 +80362,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
DUK_ASSERT(act == thr->callstack_curr);
DUK_ASSERT(act != NULL);
}
-#endif /* DUK_USE_DEBUGGER_SUPPORT */
+#endif /* DUK_USE_DEBUGGER_SUPPORT */
#if defined(DUK_USE_ASSERTIONS)
valstack_top_base = (duk_size_t) (thr->valstack_top - thr->valstack);
@@ -75000,7 +80426,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
*/
#if defined(DUK_USE_DEBUGGER_SUPPORT)
if (thr->heap->dbg_force_restart) {
- DUK_DD(DUK_DDPRINT("dbg_force_restart flag forced restart execution")); /* GH-303 */
+ DUK_DD(DUK_DDPRINT("dbg_force_restart flag forced restart execution")); /* GH-303 */
thr->heap->dbg_force_restart = 0;
goto restart_execution;
}
@@ -75012,7 +80438,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
goto restart_execution;
}
}
-#endif /* DUK_USE_INTERRUPT_COUNTER */
+#endif /* DUK_USE_INTERRUPT_COUNTER */
#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
/* For cross-checking during development: ensure dispatch count
* matches cumulative interrupt counter init value sums.
@@ -75026,16 +80452,17 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
act = thr->callstack_curr;
DUK_ASSERT(curr_pc >= DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN()));
DUK_ASSERT(curr_pc < DUK_HCOMPFUNC_GET_CODE_END(thr->heap, DUK__FUN()));
- DUK_UNREF(act); /* if debugging disabled */
+ DUK_UNREF(act); /* if debugging disabled */
- DUK_DDD(DUK_DDDPRINT("executing bytecode: pc=%ld, ins=0x%08lx, op=%ld, valstack_top=%ld/%ld, nregs=%ld --> %!I",
- (long) (curr_pc - DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN())),
- (unsigned long) *curr_pc,
- (long) DUK_DEC_OP(*curr_pc),
- (long) (thr->valstack_top - thr->valstack),
- (long) (thr->valstack_end - thr->valstack),
- (long) (DUK__FUN() ? DUK__FUN()->nregs : -1),
- (duk_instr_t) *curr_pc));
+ DUK_DDD(DUK_DDDPRINT(
+ "executing bytecode: pc=%ld, ins=0x%08lx, op=%ld, valstack_top=%ld/%ld, nregs=%ld --> %!I",
+ (long) (curr_pc - DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN())),
+ (unsigned long) *curr_pc,
+ (long) DUK_DEC_OP(*curr_pc),
+ (long) (thr->valstack_top - thr->valstack),
+ (long) (thr->valstack_end - thr->valstack),
+ (long) (DUK__FUN() ? DUK__FUN()->nregs : -1),
+ (duk_instr_t) *curr_pc));
}
#endif
@@ -75072,14 +80499,16 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
*/
op = (duk_uint8_t) DUK_DEC_OP(ins);
switch (op) {
-
- /* Some useful macros. These access inner executor variables
- * directly so they only apply within the executor.
- */
+ /* Some useful macros. These access inner executor variables
+ * directly so they only apply within the executor.
+ */
#if defined(DUK_USE_EXEC_PREFER_SIZE)
-#define DUK__REPLACE_TOP_A_BREAK() { goto replace_top_a; }
-#define DUK__REPLACE_TOP_BC_BREAK() { goto replace_top_bc; }
-#define DUK__REPLACE_BOOL_A_BREAK(bval) { \
+#define DUK__REPLACE_TOP_A_BREAK() \
+ { goto replace_top_a; }
+#define DUK__REPLACE_TOP_BC_BREAK() \
+ { goto replace_top_bc; }
+#define DUK__REPLACE_BOOL_A_BREAK(bval) \
+ { \
duk_bool_t duk__bval; \
duk__bval = (bval); \
DUK_ASSERT(duk__bval == 0 || duk__bval == 1); \
@@ -75087,9 +80516,18 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
DUK__REPLACE_TOP_A_BREAK(); \
}
#else
-#define DUK__REPLACE_TOP_A_BREAK() { DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins)); break; }
-#define DUK__REPLACE_TOP_BC_BREAK() { DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins)); break; }
-#define DUK__REPLACE_BOOL_A_BREAK(bval) { \
+#define DUK__REPLACE_TOP_A_BREAK() \
+ { \
+ DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins)); \
+ break; \
+ }
+#define DUK__REPLACE_TOP_BC_BREAK() \
+ { \
+ DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins)); \
+ break; \
+ }
+#define DUK__REPLACE_BOOL_A_BREAK(bval) \
+ { \
duk_bool_t duk__bval; \
duk_tval *duk__tvdst; \
duk__bval = (bval); \
@@ -75113,7 +80551,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
tv1 = DUK__REGP_A(ins);
tv2 = DUK__REGP_BC(ins);
- DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2); /* side effects */
+ DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2); /* side effects */
break;
}
@@ -75122,7 +80560,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
tv1 = DUK__REGP_A(ins);
tv2 = DUK__REGP_BC(ins);
- DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv2, tv1); /* side effects */
+ DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv2, tv1); /* side effects */
break;
}
@@ -75131,7 +80569,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
tv1 = DUK__REGP_A(ins);
tv2 = DUK__CONSTP_BC(ins);
- DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2); /* side effects */
+ DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2); /* side effects */
break;
}
@@ -75151,18 +80589,18 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
duk_int32_t val;
val = (duk_int32_t) duk_get_int(thr, DUK_DEC_A(ins));
- val = (val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins); /* no bias */
+ val = (val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins); /* no bias */
duk_push_int(thr, val);
DUK__REPLACE_TOP_A_BREAK();
}
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
case DUK_OP_LDINT: {
duk_tval *tv1;
duk_int32_t val;
val = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;
tv1 = DUK__REGP_A(ins);
- DUK_TVAL_SET_I32_UPDREF(thr, tv1, val); /* side effects */
+ DUK_TVAL_SET_I32_UPDREF(thr, tv1, val); /* side effects */
break;
}
case DUK_OP_LDINTX: {
@@ -75178,11 +80616,12 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
/* XXX: fast double-to-int conversion, we know number is integer in [-0x80000000,0xffffffff]. */
val = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv1);
#endif
- val = (val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins); /* no bias */
- DUK_TVAL_SET_I32_UPDREF(thr, tv1, val); /* side effects */
+ val =
+ (duk_int32_t) ((duk_uint32_t) val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins); /* no bias */
+ DUK_TVAL_SET_I32_UPDREF(thr, tv1, val); /* side effects */
break;
}
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
#if defined(DUK_USE_EXEC_PREFER_SIZE)
case DUK_OP_LDTHIS: {
@@ -75205,46 +80644,46 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
duk_push_false(thr);
DUK__REPLACE_TOP_BC_BREAK();
}
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
case DUK_OP_LDTHIS: {
/* Note: 'this' may be bound to any value, not just an object */
duk_tval *tv1, *tv2;
tv1 = DUK__REGP_BC(ins);
- tv2 = thr->valstack_bottom - 1; /* 'this binding' is just under bottom */
+ tv2 = thr->valstack_bottom - 1; /* 'this binding' is just under bottom */
DUK_ASSERT(tv2 >= thr->valstack);
- DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2); /* side effects */
+ DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2); /* side effects */
break;
}
case DUK_OP_LDUNDEF: {
duk_tval *tv1;
tv1 = DUK__REGP_BC(ins);
- DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1); /* side effects */
+ DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1); /* side effects */
break;
}
case DUK_OP_LDNULL: {
duk_tval *tv1;
tv1 = DUK__REGP_BC(ins);
- DUK_TVAL_SET_NULL_UPDREF(thr, tv1); /* side effects */
+ DUK_TVAL_SET_NULL_UPDREF(thr, tv1); /* side effects */
break;
}
case DUK_OP_LDTRUE: {
duk_tval *tv1;
tv1 = DUK__REGP_BC(ins);
- DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 1); /* side effects */
+ DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 1); /* side effects */
break;
}
case DUK_OP_LDFALSE: {
duk_tval *tv1;
tv1 = DUK__REGP_BC(ins);
- DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 0); /* side effects */
+ DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 0); /* side effects */
break;
}
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
case DUK_OP_BNOT: {
duk__vm_bitwise_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));
@@ -75262,7 +80701,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), op);
break;
}
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
case DUK_OP_UNM: {
duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), DUK_OP_UNM);
break;
@@ -75271,7 +80710,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), DUK_OP_UNP);
break;
}
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
#if defined(DUK_USE_EXEC_PREFER_SIZE)
case DUK_OP_TYPEOF: {
@@ -75282,7 +80721,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
duk_push_hstring_stridx(thr, stridx);
DUK__REPLACE_TOP_A_BREAK();
}
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
case DUK_OP_TYPEOF: {
duk_tval *tv;
duk_small_uint_t stridx;
@@ -75296,7 +80735,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
DUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);
break;
}
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
case DUK_OP_TYPEOFID: {
duk_small_uint_t stridx;
@@ -75314,13 +80753,13 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
tv = DUK__CONSTP_BC(ins);
DUK_ASSERT(DUK_TVAL_IS_STRING(tv));
name = DUK_TVAL_GET_STRING(tv);
- tv = NULL; /* lookup has side effects */
+ tv = NULL; /* lookup has side effects */
act = thr->callstack_curr;
if (duk_js_getvar_activation(thr, act, name, 0 /*throw*/)) {
/* -> [... val this] */
tv = DUK_GET_TVAL_NEGIDX(thr, -2);
stridx = duk_js_typeof_stridx(tv);
- tv = NULL; /* no longer needed */
+ tv = NULL; /* no longer needed */
duk_pop_2_unsafe(thr);
} else {
/* unresolvable, no stack changes */
@@ -75330,36 +80769,40 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
#if defined(DUK_USE_EXEC_PREFER_SIZE)
duk_push_hstring_stridx(thr, stridx);
DUK__REPLACE_TOP_A_BREAK();
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
h_str = DUK_HTHREAD_GET_STRING(thr, stridx);
tv = DUK__REGP_A(ins);
DUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);
break;
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
}
/* Equality: E5 Sections 11.9.1, 11.9.3 */
-#define DUK__EQ_BODY(barg,carg) { \
+#define DUK__EQ_BODY(barg, carg) \
+ { \
duk_bool_t tmp; \
tmp = duk_js_equals(thr, (barg), (carg)); \
DUK_ASSERT(tmp == 0 || tmp == 1); \
DUK__REPLACE_BOOL_A_BREAK(tmp); \
}
-#define DUK__NEQ_BODY(barg,carg) { \
+#define DUK__NEQ_BODY(barg, carg) \
+ { \
duk_bool_t tmp; \
tmp = duk_js_equals(thr, (barg), (carg)); \
DUK_ASSERT(tmp == 0 || tmp == 1); \
tmp ^= 1; \
DUK__REPLACE_BOOL_A_BREAK(tmp); \
}
-#define DUK__SEQ_BODY(barg,carg) { \
+#define DUK__SEQ_BODY(barg, carg) \
+ { \
duk_bool_t tmp; \
tmp = duk_js_strict_equals((barg), (carg)); \
DUK_ASSERT(tmp == 0 || tmp == 1); \
DUK__REPLACE_BOOL_A_BREAK(tmp); \
}
-#define DUK__SNEQ_BODY(barg,carg) { \
+#define DUK__SNEQ_BODY(barg, carg) \
+ { \
duk_bool_t tmp; \
tmp = duk_js_strict_equals((barg), (carg)); \
DUK_ASSERT(tmp == 0 || tmp == 1); \
@@ -75387,7 +80830,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
case DUK_OP_SNEQ_RC:
case DUK_OP_SNEQ_CC:
DUK__SNEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
case DUK_OP_EQ_RR:
DUK__EQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
case DUK_OP_EQ_CR:
@@ -75420,18 +80863,19 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
DUK__SNEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
case DUK_OP_SNEQ_CC:
DUK__SNEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
-#define DUK__COMPARE_BODY(arg1,arg2,flags) { \
+#define DUK__COMPARE_BODY(arg1, arg2, flags) \
+ { \
duk_bool_t tmp; \
tmp = duk_js_compare_helper(thr, (arg1), (arg2), (flags)); \
DUK_ASSERT(tmp == 0 || tmp == 1); \
DUK__REPLACE_BOOL_A_BREAK(tmp); \
}
-#define DUK__GT_BODY(barg,carg) DUK__COMPARE_BODY((carg), (barg), 0)
-#define DUK__GE_BODY(barg,carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
-#define DUK__LT_BODY(barg,carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
-#define DUK__LE_BODY(barg,carg) DUK__COMPARE_BODY((carg), (barg), DUK_COMPARE_FLAG_NEGATE)
+#define DUK__GT_BODY(barg, carg) DUK__COMPARE_BODY((carg), (barg), 0)
+#define DUK__GE_BODY(barg, carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
+#define DUK__LT_BODY(barg, carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
+#define DUK__LE_BODY(barg, carg) DUK__COMPARE_BODY((carg), (barg), DUK_COMPARE_FLAG_NEGATE)
#if defined(DUK_USE_EXEC_PREFER_SIZE)
case DUK_OP_GT_RR:
case DUK_OP_GT_CR:
@@ -75453,7 +80897,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
case DUK_OP_LE_RC:
case DUK_OP_LE_CC:
DUK__LE_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
case DUK_OP_GT_RR:
DUK__GT_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
case DUK_OP_GT_CR:
@@ -75486,7 +80930,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
DUK__LE_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
case DUK_OP_LE_CC:
DUK__LE_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
/* No size optimized variant at present for IF. */
case DUK_OP_IFTRUE_R: {
@@ -75523,7 +80967,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
duk__vm_arith_add(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins));
break;
}
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
case DUK_OP_ADD_RR: {
duk__vm_arith_add(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins));
break;
@@ -75540,7 +80984,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
duk__vm_arith_add(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins));
break;
}
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
#if defined(DUK_USE_EXEC_PREFER_SIZE)
case DUK_OP_SUB_RR:
@@ -75564,13 +81008,13 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
case DUK_OP_EXP_CR:
case DUK_OP_EXP_RC:
case DUK_OP_EXP_CC:
-#endif /* DUK_USE_ES7_EXP_OPERATOR */
+#endif /* DUK_USE_ES7_EXP_OPERATOR */
{
/* XXX: could leave value on stack top and goto replace_top_a; */
duk__vm_arith_binary_op(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins), op);
break;
}
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
case DUK_OP_SUB_RR: {
duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
break;
@@ -75652,8 +81096,8 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
break;
}
-#endif /* DUK_USE_ES7_EXP_OPERATOR */
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+#endif /* DUK_USE_ES7_EXP_OPERATOR */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
#if defined(DUK_USE_EXEC_PREFER_SIZE)
case DUK_OP_BAND_RR:
@@ -75684,7 +81128,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
duk__vm_bitwise_binary_op(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins), op);
break;
}
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
case DUK_OP_BAND_RR: {
duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
break;
@@ -75781,16 +81225,18 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
break;
}
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
/* For INSTOF and IN, B is always a register. */
-#define DUK__INSTOF_BODY(barg,carg) { \
+#define DUK__INSTOF_BODY(barg, carg) \
+ { \
duk_bool_t tmp; \
tmp = duk_js_instanceof(thr, (barg), (carg)); \
DUK_ASSERT(tmp == 0 || tmp == 1); \
DUK__REPLACE_BOOL_A_BREAK(tmp); \
}
-#define DUK__IN_BODY(barg,carg) { \
+#define DUK__IN_BODY(barg, carg) \
+ { \
duk_bool_t tmp; \
tmp = duk_js_in(thr, (barg), (carg)); \
DUK_ASSERT(tmp == 0 || tmp == 1); \
@@ -75807,7 +81253,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
case DUK_OP_IN_RC:
case DUK_OP_IN_CC:
DUK__IN_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
case DUK_OP_INSTOF_RR:
DUK__INSTOF_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
case DUK_OP_INSTOF_CR:
@@ -75824,9 +81270,9 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
DUK__IN_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
case DUK_OP_IN_CC:
DUK__IN_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
- /* Pre/post inc/dec for register variables, important for loops. */
+ /* Pre/post inc/dec for register variables, important for loops. */
#if defined(DUK_USE_EXEC_PREFER_SIZE)
case DUK_OP_PREINCR:
case DUK_OP_PREDECR:
@@ -75842,7 +81288,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), op, DUK__STRICT());
break;
}
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
case DUK_OP_PREINCR: {
duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_PREINCR);
break;
@@ -75875,7 +81321,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_POSTDECV, DUK__STRICT());
break;
}
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
/* XXX: Move to separate helper, optimize for perf/size separately. */
/* Preinc/predec for object properties. */
@@ -75902,7 +81348,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
duk_double_t x, y, z;
#if !defined(DUK_USE_EXEC_PREFER_SIZE)
duk_tval *tv_dst;
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
/* A -> target reg
* B -> object reg/const (may be const e.g. in "'foo'[1]")
@@ -75920,10 +81366,10 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
tv_obj = DUK__REGCONSTP_B(ins);
tv_key = DUK__REGCONSTP_C(ins);
- rc = duk_hobject_getprop(thr, tv_obj, tv_key); /* -> [val] */
- DUK_UNREF(rc); /* ignore */
- tv_obj = NULL; /* invalidated */
- tv_key = NULL; /* invalidated */
+ rc = duk_hobject_getprop(thr, tv_obj, tv_key); /* -> [val] */
+ DUK_UNREF(rc); /* ignore */
+ tv_obj = NULL; /* invalidated */
+ tv_key = NULL; /* invalidated */
/* XXX: Fastint fast path would be useful here. Also fastints
* now lose their fastint status in current handling which is
@@ -75944,9 +81390,9 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
tv_obj = DUK__REGCONSTP_B(ins);
tv_key = DUK__REGCONSTP_C(ins);
rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT());
- DUK_UNREF(rc); /* ignore */
- tv_obj = NULL; /* invalidated */
- tv_key = NULL; /* invalidated */
+ DUK_UNREF(rc); /* ignore */
+ tv_obj = NULL; /* invalidated */
+ tv_key = NULL; /* invalidated */
duk_pop_unsafe(thr);
z = (ins & DUK_BC_INCDECP_FLAG_POST) ? x : y;
@@ -75964,7 +81410,8 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
* Occurs relatively often in object oriented code.
*/
-#define DUK__GETPROP_BODY(barg,carg) { \
+#define DUK__GETPROP_BODY(barg, carg) \
+ { \
/* A -> target reg \
* B -> object reg/const (may be const e.g. in "'foo'[1]") \
* C -> key reg/const \
@@ -75972,7 +81419,8 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
(void) duk_hobject_getprop(thr, (barg), (carg)); \
DUK__REPLACE_TOP_A_BREAK(); \
}
-#define DUK__GETPROPC_BODY(barg,carg) { \
+#define DUK__GETPROPC_BODY(barg, carg) \
+ { \
/* Same as GETPROP but callability check for property-based calls. */ \
duk_tval *tv__targ; \
(void) duk_hobject_getprop(thr, (barg), (carg)); \
@@ -75983,11 +81431,12 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
* arguments to deal with potentially changed \
* valstack base pointer! \
*/ \
- duk_call_setup_propcall_error(thr, tv__targ, (barg), (carg)); \
+ duk_call_setup_propcall_error(thr, (barg), (carg)); \
} \
DUK__REPLACE_TOP_A_BREAK(); \
}
-#define DUK__PUTPROP_BODY(aarg,barg,carg) { \
+#define DUK__PUTPROP_BODY(aarg, barg, carg) \
+ { \
/* A -> object reg \
* B -> key reg/const \
* C -> value reg/const \
@@ -75998,7 +81447,8 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
(void) duk_hobject_putprop(thr, (aarg), (barg), (carg), DUK__STRICT()); \
break; \
}
-#define DUK__DELPROP_BODY(barg,carg) { \
+#define DUK__DELPROP_BODY(barg, carg) \
+ { \
/* A -> result reg \
* B -> object reg \
* C -> key reg/const \
@@ -76027,9 +81477,9 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
case DUK_OP_PUTPROP_CC:
DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
case DUK_OP_DELPROP_RR:
- case DUK_OP_DELPROP_RC: /* B is always reg */
+ case DUK_OP_DELPROP_RC: /* B is always reg */
DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__REGCONSTP_C(ins));
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
case DUK_OP_GETPROP_RR:
DUK__GETPROP_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
case DUK_OP_GETPROP_CR:
@@ -76056,11 +81506,11 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGP_B(ins), DUK__CONSTP_C(ins));
case DUK_OP_PUTPROP_CC:
DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
- case DUK_OP_DELPROP_RR: /* B is always reg */
+ case DUK_OP_DELPROP_RR: /* B is always reg */
DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
case DUK_OP_DELPROP_RC:
DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
/* No fast path for DECLVAR now, it's quite a rare instruction. */
case DUK_OP_DECLVAR_RR:
@@ -76093,7 +81543,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
if (is_func_decl) {
duk_push_tval(thr, DUK__REGCONSTP_C(ins));
} else {
- DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top)); /* valstack policy */
+ DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top)); /* valstack policy */
thr->valstack_top++;
}
tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
@@ -76129,11 +81579,11 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
*/
duk_push_tval(thr, DUK__REGCONSTP_C(ins));
- duk_push_tval(thr, DUK__REGCONSTP_B(ins)); /* -> [ ... escaped_source bytecode ] */
- duk_regexp_create_instance(thr); /* -> [ ... regexp_instance ] */
+ duk_push_tval(thr, DUK__REGCONSTP_B(ins)); /* -> [ ... escaped_source bytecode ] */
+ duk_regexp_create_instance(thr); /* -> [ ... regexp_instance ] */
DUK__REPLACE_TOP_A_BREAK();
}
-#endif /* DUK_USE_REGEXP_SUPPORT */
+#endif /* DUK_USE_REGEXP_SUPPORT */
/* XXX: 'c' is unused, use whole BC, etc. */
case DUK_OP_CSVAR_RR:
@@ -76162,13 +81612,13 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
name = DUK_TVAL_GET_STRING(tv1);
DUK_ASSERT(name != NULL);
act = thr->callstack_curr;
- (void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/); /* -> [... val this] */
+ (void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/); /* -> [... val this] */
idx = (duk_uint_fast_t) DUK_DEC_A(ins);
/* Could add direct value stack handling. */
- duk_replace(thr, (duk_idx_t) (idx + 1)); /* 'this' binding */
- duk_replace(thr, (duk_idx_t) idx); /* variable value (function, we hope, not checked here) */
+ duk_replace(thr, (duk_idx_t) (idx + 1)); /* 'this' binding */
+ duk_replace(thr, (duk_idx_t) idx); /* variable value (function, we hope, not checked here) */
break;
}
@@ -76183,7 +81633,9 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
*/
DUK_DDD(DUK_DDDPRINT("CLOSURE to target register %ld, fnum %ld (count %ld)",
- (long) DUK_DEC_A(ins), (long) DUK_DEC_BC(ins), (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN())));
+ (long) DUK_DEC_A(ins),
+ (long) DUK_DEC_BC(ins),
+ (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN())));
DUK_ASSERT_DISABLE(bc >= 0); /* unsigned */
DUK_ASSERT((duk_uint_t) bc < (duk_uint_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN()));
@@ -76194,8 +81646,8 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
DUK_ASSERT(fun_temp != NULL);
DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(fun_temp));
- DUK_DDD(DUK_DDDPRINT("CLOSURE: function template is: %p -> %!O",
- (void *) fun_temp, (duk_heaphdr *) fun_temp));
+ DUK_DDD(
+ DUK_DDDPRINT("CLOSURE: function template is: %p -> %!O", (void *) fun_temp, (duk_heaphdr *) fun_temp));
if (act->lex_env == NULL) {
DUK_ASSERT(act->var_env == NULL);
@@ -76209,11 +81661,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
* new variable declaration environment, so only lex_env
* matters here.
*/
- duk_js_push_closure(thr,
- (duk_hcompfunc *) fun_temp,
- act->var_env,
- act->lex_env,
- 1 /*add_auto_proto*/);
+ duk_js_push_closure(thr, (duk_hcompfunc *) fun_temp, act->var_env, act->lex_env, 1 /*add_auto_proto*/);
DUK__REPLACE_TOP_A_BREAK();
}
@@ -76228,8 +81676,8 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
DUK_ASSERT(name != NULL);
act = thr->callstack_curr;
DUK_ASSERT(act != NULL);
- (void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/); /* -> [... val this] */
- duk_pop_unsafe(thr); /* 'this' binding is not needed here */
+ (void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/); /* -> [... val this] */
+ duk_pop_unsafe(thr); /* 'this' binding is not needed here */
DUK__REPLACE_TOP_A_BREAK();
}
@@ -76247,7 +81695,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
* should be reworked.
*/
- tv1 = DUK__REGP_A(ins); /* val */
+ tv1 = DUK__REGP_A(ins); /* val */
act = thr->callstack_curr;
duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
break;
@@ -76277,7 +81725,8 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
break;
}
-#define DUK__RETURN_SHARED() do { \
+#define DUK__RETURN_SHARED() \
+ do { \
duk_small_uint_t ret_result; \
/* duk__handle_return() is guaranteed never to throw, except \
* for potential out-of-memory situations which will then \
@@ -76296,14 +81745,14 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
case DUK_OP_RETCONST:
case DUK_OP_RETCONSTN:
case DUK_OP_RETUNDEF: {
- /* BC -> return value reg/const */
+ /* BC -> return value reg/const */
DUK__SYNC_AND_NULL_CURR_PC();
if (op == DUK_OP_RETREG) {
duk_push_tval(thr, DUK__REGP_BC(ins));
} else if (op == DUK_OP_RETUNDEF) {
- DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top)); /* valstack policy */
+ DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top)); /* valstack policy */
thr->valstack_top++;
} else {
DUK_ASSERT(op == DUK_OP_RETCONST || op == DUK_OP_RETCONSTN);
@@ -76312,7 +81761,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
DUK__RETURN_SHARED();
}
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
case DUK_OP_RETREG: {
duk_tval *tv;
@@ -76342,18 +81791,18 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
#if defined(DUK_USE_REFERENCE_COUNTING)
/* Without refcounting only RETCONSTN is used. */
- DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv)); /* no INCREF for this constant */
+ DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv)); /* no INCREF for this constant */
#endif
thr->valstack_top++;
DUK__RETURN_SHARED();
}
case DUK_OP_RETUNDEF: {
DUK__SYNC_AND_NULL_CURR_PC();
- thr->valstack_top++; /* value at valstack top is already undefined by valstack policy */
+ thr->valstack_top++; /* value at valstack top is already undefined by valstack policy */
DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
DUK__RETURN_SHARED();
}
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
case DUK_OP_LABEL: {
duk_activation *act;
@@ -76366,8 +81815,8 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
DUK_ASSERT(cat != NULL);
cat->flags = (duk_uint32_t) (DUK_CAT_TYPE_LABEL | (bc << DUK_CAT_LABEL_SHIFT));
- cat->pc_base = (duk_instr_t *) curr_pc; /* pre-incremented, points to first jump slot */
- cat->idx_base = 0; /* unused for label */
+ cat->pc_base = (duk_instr_t *) curr_pc; /* pre-incremented, points to first jump slot */
+ cat->idx_base = 0; /* unused for label */
cat->h_varname = NULL;
act = thr->callstack_curr;
@@ -76377,10 +81826,13 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
DUK_DDD(DUK_DDDPRINT("LABEL catcher: flags=0x%08lx, pc_base=%ld, "
"idx_base=%ld, h_varname=%!O, label_id=%ld",
- (long) cat->flags, (long) cat->pc_base,
- (long) cat->idx_base, (duk_heaphdr *) cat->h_varname, (long) DUK_CAT_GET_LABEL(cat)));
+ (long) cat->flags,
+ (long) cat->pc_base,
+ (long) cat->idx_base,
+ (duk_heaphdr *) cat->h_varname,
+ (long) DUK_CAT_GET_LABEL(cat)));
- curr_pc += 2; /* skip jump slots */
+ curr_pc += 2; /* skip jump slots */
break;
}
@@ -76422,7 +81874,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
/* XXX: move to helper, too large to be inline here */
case DUK_OP_TRYCATCH: {
duk__handle_op_trycatch(thr, ins, curr_pc);
- curr_pc += 2; /* skip jump slots */
+ curr_pc += 2; /* skip jump slots */
break;
}
@@ -76467,8 +81919,8 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
(duk_tval *) duk_get_tval(thr, -1)));
#if defined(DUK_USE_AUGMENT_ERROR_THROW)
duk_err_augment_error_throw(thr);
- DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (after throw augment)",
- (duk_tval *) duk_get_tval(thr, -1)));
+ DUK_DDD(
+ DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (after throw augment)", (duk_tval *) duk_get_tval(thr, -1)));
#endif
duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, DUK_GET_TVAL_NEGIDX(thr, -1));
@@ -76476,7 +81928,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
duk_err_check_debugger_integration(thr);
#endif
- DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* always in executor */
+ DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* always in executor */
duk_err_longjmp(thr);
DUK_UNREACHABLE();
break;
@@ -76513,20 +81965,19 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
DUK_TVAL_SET_TVAL(&tv_tmp2, tv2);
tv3 = DUK__REGP(a);
DUK_TVAL_SET_TVAL(tv1, tv3);
- DUK_TVAL_INCREF(thr, tv1); /* no side effects */
- DUK_TVAL_SET_UNDEFINED(tv2); /* no need for incref */
+ DUK_TVAL_INCREF(thr, tv1); /* no side effects */
+ DUK_TVAL_SET_UNDEFINED(tv2); /* no need for incref */
DUK_TVAL_DECREF(thr, &tv_tmp1);
DUK_TVAL_DECREF(thr, &tv_tmp2);
#endif
break;
}
-
- /* XXX: in some cases it's faster NOT to reuse the value
- * stack but rather copy the arguments on top of the stack
- * (mainly when the calling value stack is large and the value
- * stack resize would be large).
- */
+ /* XXX: in some cases it's faster NOT to reuse the value
+ * stack but rather copy the arguments on top of the stack
+ * (mainly when the calling value stack is large and the value
+ * stack resize would be large).
+ */
case DUK_OP_CALL0:
case DUK_OP_CALL1:
@@ -76687,7 +82138,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
}
count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
- DUK_ASSERT(count > 0); /* compiler guarantees */
+ DUK_ASSERT(count > 0); /* compiler guarantees */
idx_end = idx + count;
#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
@@ -76711,11 +82162,10 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
/* XXX: faster initialization (direct access or better primitives) */
duk_dup(thr, (duk_idx_t) idx);
duk_dup(thr, (duk_idx_t) (idx + 1));
- duk_def_prop(thr, obj_idx, DUK_DEFPROP_HAVE_VALUE |
- DUK_DEFPROP_FORCE |
- DUK_DEFPROP_SET_WRITABLE |
- DUK_DEFPROP_SET_ENUMERABLE |
- DUK_DEFPROP_SET_CONFIGURABLE);
+ duk_def_prop(thr,
+ obj_idx,
+ DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_FORCE | DUK_DEFPROP_SET_WRITABLE |
+ DUK_DEFPROP_SET_ENUMERABLE | DUK_DEFPROP_SET_CONFIGURABLE);
idx += 2;
} while (idx < idx_end);
break;
@@ -76750,7 +82200,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
}
count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
- DUK_ASSERT(count > 0 + 1); /* compiler guarantees */
+ DUK_ASSERT(count > 0 + 1); /* compiler guarantees */
idx_end = idx + count;
#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
@@ -76833,7 +82283,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
case DUK_OP_INVLHS: {
DUK_ERROR_REFERENCE(thr, DUK_STR_INVALID_LVALUE);
- DUK_UNREACHABLE();
+ DUK_WO_NORETURN(return;);
break;
}
@@ -76868,48 +82318,16 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
case DUK_OP_INVALID: {
DUK_ERROR_FMT1(thr, DUK_ERR_ERROR, "INVALID opcode (%ld)", (long) DUK_DEC_ABC(ins));
+ DUK_WO_NORETURN(return;);
break;
}
#if defined(DUK_USE_ES6)
case DUK_OP_NEWTARGET: {
- /* https://www.ecma-international.org/ecma-262/6.0/#sec-meta-properties-runtime-semantics-evaluation
- * https://www.ecma-international.org/ecma-262/6.0/#sec-getnewtarget
- *
- * No newTarget support now, so as a first approximation
- * use the resolved (non-bound) target function.
- */
- /* XXX: C API: push_new_target()? */
- duk_activation *act;
-
- act = thr->callstack_curr;
- DUK_ASSERT(act != NULL);
-
- /* Check CONSTRUCT flag from current function, or if running
- * direct eval, from a non-direct-eval parent (with possibly
- * more than one nested direct eval). An alternative to this
- * would be to store [[NewTarget]] as a hidden symbol of the
- * lexical scope, and then just look up that variable.
- */
- for (;;) {
- if (act == NULL) {
- duk_push_undefined(thr);
- break;
- }
- if (act->flags & DUK_ACT_FLAG_CONSTRUCT) {
- duk_push_tval(thr, &act->tv_func);
- break;
- } else if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
- act = act->parent;
- } else {
- duk_push_undefined(thr);
- break;
- }
- }
-
+ duk_push_new_target(thr);
DUK__REPLACE_TOP_BC_BREAK();
}
-#endif /* DUK_USE_ES6 */
+#endif /* DUK_USE_ES6 */
#if !defined(DUK_USE_EXEC_PREFER_SIZE)
#if !defined(DUK_USE_ES7_EXP_OPERATOR)
@@ -76972,16 +82390,16 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
case DUK_OP_UNUSED253:
case DUK_OP_UNUSED254:
case DUK_OP_UNUSED255:
- /* Force all case clauses to map to an actual handler
- * so that the compiler can emit a jump without a bounds
- * check: the switch argument is a duk_uint8_t so that
- * the compiler may be able to figure it out. This is
- * a small detail and obviously compiler dependent.
- */
- /* default: clause omitted on purpose */
-#else /* DUK_USE_EXEC_PREFER_SIZE */
+ /* Force all case clauses to map to an actual handler
+ * so that the compiler can emit a jump without a bounds
+ * check: the switch argument is a duk_uint8_t so that
+ * the compiler may be able to figure it out. This is
+ * a small detail and obviously compiler dependent.
+ */
+ /* default: clause omitted on purpose */
+#else /* DUK_USE_EXEC_PREFER_SIZE */
default:
-#endif /* DUK_USE_EXEC_PREFER_SIZE */
+#endif /* DUK_USE_EXEC_PREFER_SIZE */
{
/* Default case catches invalid/unsupported opcodes. */
DUK_D(DUK_DPRINT("invalid opcode: %ld - %!I", (long) op, ins));
@@ -76989,7 +82407,7 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
break;
}
- } /* end switch */
+ } /* end switch */
continue;
@@ -77000,19 +82418,20 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
*/
#if defined(DUK_USE_EXEC_PREFER_SIZE)
- replace_top_a:
+ replace_top_a:
DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins));
continue;
- replace_top_bc:
+ replace_top_bc:
DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins));
continue;
#endif
}
- DUK_UNREACHABLE();
+ DUK_WO_NORETURN(return;);
#if !defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)
- internal_error:
+internal_error:
DUK_ERROR_INTERNAL(thr);
+ DUK_WO_NORETURN(return;);
#endif
}
@@ -77035,7 +82454,6 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
#undef DUK__GETPROP_BODY
#undef DUK__GE_BODY
#undef DUK__GT_BODY
-#undef DUK__INLINE_PERF
#undef DUK__INSTOF_BODY
#undef DUK__INTERNAL_ERROR
#undef DUK__INT_NOACTION
@@ -77051,7 +82469,6 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
#undef DUK__MASK_BC
#undef DUK__MASK_C
#undef DUK__NEQ_BODY
-#undef DUK__NOINLINE_PERF
#undef DUK__PUTPROP_BODY
#undef DUK__RCBIT_B
#undef DUK__RCBIT_C
@@ -77081,9 +82498,9 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
#undef DUK__SYNC_CURR_PC
#undef DUK__TVAL_SHIFT
/*
- * Ecmascript specification algorithm and conversion helpers.
+ * ECMAScript specification algorithm and conversion helpers.
*
- * These helpers encapsulate the primitive Ecmascript operation semantics,
+ * These helpers encapsulate the primitive ECMAScript operation semantics,
* and are used by the bytecode executor and the API (among other places).
* Some primitives are only implemented as part of the API and have no
* "internal" helper. This is the case when an internal helper would not
@@ -77201,6 +82618,7 @@ DUK_INTERNAL duk_bool_t duk_js_toboolean(duk_tval *tv) {
}
}
DUK_UNREACHABLE();
+ DUK_WO_UNREACHABLE(return 0;);
}
/*
@@ -77228,7 +82646,8 @@ DUK_INTERNAL duk_bool_t duk_js_toboolean(duk_tval *tv) {
* ("0x123") and infinities
*
* - Unlike source code literals, ToNumber() coerces empty strings
- * and strings with only whitespace to zero (not NaN).
+ * and strings with only whitespace to zero (not NaN). However,
+ * while '' coerces to 0, '+' and '-' coerce to NaN.
*/
/* E5 Section 9.3.1 */
@@ -77241,19 +82660,10 @@ DUK_LOCAL duk_double_t duk__tonumber_string_raw(duk_hthread *thr) {
/* Quite lenient, e.g. allow empty as zero, but don't allow trailing
* garbage.
*/
- s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
- DUK_S2N_FLAG_ALLOW_EXP |
- DUK_S2N_FLAG_ALLOW_PLUS |
- DUK_S2N_FLAG_ALLOW_MINUS |
- DUK_S2N_FLAG_ALLOW_INF |
- DUK_S2N_FLAG_ALLOW_FRAC |
- DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
- DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
- DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO |
- DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
- DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT |
- DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT |
- DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT;
+ s2n_flags = DUK_S2N_FLAG_TRIM_WHITE | DUK_S2N_FLAG_ALLOW_EXP | DUK_S2N_FLAG_ALLOW_PLUS | DUK_S2N_FLAG_ALLOW_MINUS |
+ DUK_S2N_FLAG_ALLOW_INF | DUK_S2N_FLAG_ALLOW_FRAC | DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
+ DUK_S2N_FLAG_ALLOW_EMPTY_FRAC | DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO | DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
+ DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT | DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT | DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT;
duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
@@ -77263,9 +82673,9 @@ DUK_LOCAL duk_double_t duk__tonumber_string_raw(duk_hthread *thr) {
#else
thr->valstack_top--;
DUK_ASSERT(DUK_TVAL_IS_NUMBER(thr->valstack_top));
- DUK_ASSERT(DUK_TVAL_IS_DOUBLE(thr->valstack_top)); /* no fastint conversion in numconv now */
+ DUK_ASSERT(DUK_TVAL_IS_DOUBLE(thr->valstack_top)); /* no fastint conversion in numconv now */
DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(thr->valstack_top));
- d = DUK_TVAL_GET_DOUBLE(thr->valstack_top); /* assumes not a fastint */
+ d = DUK_TVAL_GET_DOUBLE(thr->valstack_top); /* assumes not a fastint */
DUK_TVAL_SET_UNDEFINED(thr->valstack_top);
#endif
@@ -77299,15 +82709,16 @@ DUK_INTERNAL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv) {
duk_hstring *h = DUK_TVAL_GET_STRING(tv);
if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
DUK_ERROR_TYPE(thr, DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL);
+ DUK_WO_NORETURN(return 0.0;);
}
duk_push_hstring(thr, h);
return duk__tonumber_string_raw(thr);
}
- case DUK_TAG_BUFFER: /* plain buffer treated like object */
+ case DUK_TAG_BUFFER: /* plain buffer treated like object */
case DUK_TAG_OBJECT: {
duk_double_t d;
duk_push_tval(thr, tv);
- duk_to_primitive(thr, -1, DUK_HINT_NUMBER); /* 'tv' becomes invalid */
+ duk_to_primitive(thr, -1, DUK_HINT_NUMBER); /* 'tv' becomes invalid */
/* recursive call for a primitive value (guaranteed not to cause second
* recursion).
@@ -77340,6 +82751,7 @@ DUK_INTERNAL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv) {
}
DUK_UNREACHABLE();
+ DUK_WO_UNREACHABLE(return 0.0;);
}
/*
@@ -77361,7 +82773,7 @@ DUK_INTERNAL duk_double_t duk_js_tointeger_number(duk_double_t x) {
*/
return duk_double_trunc_towards_zero(x);
}
-#else /* DUK_USE_PREFER_SIZE */
+#else /* DUK_USE_PREFER_SIZE */
/* NaN and Infinity have the same exponent so it's a cheap
* initial check for the rare path.
*/
@@ -77374,12 +82786,12 @@ DUK_INTERNAL duk_double_t duk_js_tointeger_number(duk_double_t x) {
} else {
return duk_double_trunc_towards_zero(x);
}
-#endif /* DUK_USE_PREFER_SIZE */
+#endif /* DUK_USE_PREFER_SIZE */
}
DUK_INTERNAL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv) {
/* XXX: fastint */
- duk_double_t d = duk_js_tonumber(thr, tv); /* invalidates tv */
+ duk_double_t d = duk_js_tonumber(thr, tv); /* invalidates tv */
return duk_js_tointeger_number(d);
}
@@ -77389,11 +82801,11 @@ DUK_INTERNAL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv) {
/* combined algorithm matching E5 Sections 9.5 and 9.6 */
DUK_LOCAL duk_double_t duk__toint32_touint32_helper(duk_double_t x, duk_bool_t is_toint32) {
-#if defined (DUK_USE_PREFER_SIZE)
+#if defined(DUK_USE_PREFER_SIZE)
duk_small_int_t c;
#endif
-#if defined (DUK_USE_PREFER_SIZE)
+#if defined(DUK_USE_PREFER_SIZE)
c = (duk_small_int_t) DUK_FPCLASSIFY(x);
if (c == DUK_FP_NAN || c == DUK_FP_ZERO || c == DUK_FP_INFINITE) {
return 0.0;
@@ -77411,18 +82823,18 @@ DUK_LOCAL duk_double_t duk__toint32_touint32_helper(duk_double_t x, duk_bool_t i
* differs from what Javascript wants (see Section 9.6).
*/
- x = DUK_FMOD(x, DUK_DOUBLE_2TO32); /* -> x in ]-2**32, 2**32[ */
+ x = DUK_FMOD(x, DUK_DOUBLE_2TO32); /* -> x in ]-2**32, 2**32[ */
if (x < 0.0) {
x += DUK_DOUBLE_2TO32;
}
- DUK_ASSERT(x >= 0 && x < DUK_DOUBLE_2TO32); /* -> x in [0, 2**32[ */
+ DUK_ASSERT(x >= 0 && x < DUK_DOUBLE_2TO32); /* -> x in [0, 2**32[ */
if (is_toint32) {
if (x >= DUK_DOUBLE_2TO31) {
/* x in [2**31, 2**32[ */
- x -= DUK_DOUBLE_2TO32; /* -> x in [-2**31,2**31[ */
+ x -= DUK_DOUBLE_2TO32; /* -> x in [-2**31,2**31[ */
}
}
@@ -77438,15 +82850,14 @@ DUK_INTERNAL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv) {
}
#endif
- d = duk_js_tonumber(thr, tv); /* invalidates tv */
+ d = duk_js_tonumber(thr, tv); /* invalidates tv */
d = duk__toint32_touint32_helper(d, 1);
DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
- DUK_ASSERT(d >= -2147483648.0 && d <= 2147483647.0); /* [-0x80000000,0x7fffffff] */
- DUK_ASSERT(d == ((duk_double_t) ((duk_int32_t) d))); /* whole, won't clip */
+ DUK_ASSERT(d >= -2147483648.0 && d <= 2147483647.0); /* [-0x80000000,0x7fffffff] */
+ DUK_ASSERT(duk_double_equals(d, (duk_double_t) ((duk_int32_t) d))); /* whole, won't clip */
return (duk_int32_t) d;
}
-
DUK_INTERNAL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv) {
duk_double_t d;
@@ -77456,13 +82867,12 @@ DUK_INTERNAL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv) {
}
#endif
- d = duk_js_tonumber(thr, tv); /* invalidates tv */
+ d = duk_js_tonumber(thr, tv); /* invalidates tv */
d = duk__toint32_touint32_helper(d, 0);
DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
- DUK_ASSERT(d >= 0.0 && d <= 4294967295.0); /* [0x00000000, 0xffffffff] */
- DUK_ASSERT(d == ((duk_double_t) ((duk_uint32_t) d))); /* whole, won't clip */
+ DUK_ASSERT(d >= 0.0 && d <= 4294967295.0); /* [0x00000000, 0xffffffff] */
+ DUK_ASSERT(duk_double_equals(d, (duk_double_t) ((duk_uint32_t) d))); /* whole, won't clip */
return (duk_uint32_t) d;
-
}
DUK_INTERNAL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv) {
@@ -77512,14 +82922,14 @@ DUK_LOCAL duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y) {
return 1;
}
return 0;
-#else /* DUK_USE_PARANOID_MATH */
+#else /* DUK_USE_PARANOID_MATH */
/* Better equivalent algorithm. If the compiler is compliant, C and
- * Ecmascript semantics are identical for this particular comparison.
+ * ECMAScript semantics are identical for this particular comparison.
* In particular, NaNs must never compare equal and zeroes must compare
* equal regardless of sign. Could also use a macro, but this inlines
* already nicely (no difference on gcc, for instance).
*/
- if (x == y) {
+ if (duk_double_equals(x, y)) {
/* IEEE requires that NaNs compare false */
DUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);
DUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);
@@ -77532,7 +82942,7 @@ DUK_LOCAL duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y) {
DUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));
return 0;
}
-#endif /* DUK_USE_PARANOID_MATH */
+#endif /* DUK_USE_PARANOID_MATH */
}
DUK_LOCAL duk_bool_t duk__js_samevalue_number(duk_double_t x, duk_double_t y) {
@@ -77562,11 +82972,11 @@ DUK_LOCAL duk_bool_t duk__js_samevalue_number(duk_double_t x, duk_double_t y) {
*/
return (x == y);
-#else /* DUK_USE_PARANOID_MATH */
+#else /* DUK_USE_PARANOID_MATH */
duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
- if (x == y) {
+ if (duk_double_equals(x, y)) {
/* IEEE requires that NaNs compare false */
DUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);
DUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);
@@ -77597,7 +83007,7 @@ DUK_LOCAL duk_bool_t duk__js_samevalue_number(duk_double_t x, duk_double_t y) {
}
return 0;
}
-#endif /* DUK_USE_PARANOID_MATH */
+#endif /* DUK_USE_PARANOID_MATH */
}
DUK_INTERNAL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags) {
@@ -77623,10 +83033,9 @@ DUK_INTERNAL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, d
} else {
return 0;
}
- }
- else
+ } else
#endif
- if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
+ if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
duk_double_t d1, d2;
/* Catches both doubles and cases where only one argument is
@@ -77691,7 +83100,7 @@ DUK_INTERNAL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, d
DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_y));
DUK_UNREACHABLE();
- return 0;
+ DUK_WO_UNREACHABLE(return 0;);
}
}
}
@@ -77700,7 +83109,7 @@ DUK_INTERNAL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, d
return 0;
}
- DUK_ASSERT(flags == 0); /* non-strict equality from here on */
+ DUK_ASSERT(flags == 0); /* non-strict equality from here on */
/*
* Types are different; various cases for non-strict comparison
@@ -77757,34 +83166,29 @@ DUK_INTERNAL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, d
}
/* String-number-symbol/object -> coerce object to primitive (apparently without hint), then try again. */
- if ((type_mask_x & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER)) &&
- (type_mask_y & DUK_TYPE_MASK_OBJECT)) {
+ if ((type_mask_x & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER)) && (type_mask_y & DUK_TYPE_MASK_OBJECT)) {
/* No symbol check needed because symbols and strings are accepted. */
duk_push_tval(thr, tv_x);
duk_push_tval(thr, tv_y);
- duk_to_primitive(thr, -1, DUK_HINT_NONE); /* apparently no hint? */
+ duk_to_primitive(thr, -1, DUK_HINT_NONE); /* apparently no hint? */
goto recursive_call;
}
- if ((type_mask_x & DUK_TYPE_MASK_OBJECT) &&
- (type_mask_y & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER))) {
+ if ((type_mask_x & DUK_TYPE_MASK_OBJECT) && (type_mask_y & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER))) {
/* No symbol check needed because symbols and strings are accepted. */
duk_push_tval(thr, tv_x);
duk_push_tval(thr, tv_y);
- duk_to_primitive(thr, -2, DUK_HINT_NONE); /* apparently no hint? */
+ duk_to_primitive(thr, -2, DUK_HINT_NONE); /* apparently no hint? */
goto recursive_call;
}
/* Nothing worked -> not equal. */
return 0;
- recursive_call:
+recursive_call:
/* Shared code path to call the helper again with arguments on stack top. */
{
duk_bool_t rc;
- rc = duk_js_equals_helper(thr,
- DUK_GET_TVAL_NEGIDX(thr, -2),
- DUK_GET_TVAL_NEGIDX(thr, -1),
- 0 /*flags:nonstrict*/);
+ rc = duk_js_equals_helper(thr, DUK_GET_TVAL_NEGIDX(thr, -2), DUK_GET_TVAL_NEGIDX(thr, -1), 0 /*flags:nonstrict*/);
duk_pop_2_unsafe(thr);
return rc;
}
@@ -77801,18 +83205,19 @@ DUK_INTERNAL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, d
* needs to push stuff on the stack anyway...
*/
-DUK_INTERNAL duk_small_int_t duk_js_data_compare(const duk_uint8_t *buf1, const duk_uint8_t *buf2, duk_size_t len1, duk_size_t len2) {
+DUK_INTERNAL duk_small_int_t duk_js_data_compare(const duk_uint8_t *buf1,
+ const duk_uint8_t *buf2,
+ duk_size_t len1,
+ duk_size_t len2) {
duk_size_t prefix_len;
duk_small_int_t rc;
prefix_len = (len1 <= len2 ? len1 : len2);
- /* DUK_MEMCMP() is guaranteed to return zero (equal) for zero length
- * inputs so no zero length check is needed.
+ /* duk_memcmp() is guaranteed to return zero (equal) for zero length
+ * inputs.
*/
- rc = DUK_MEMCMP((const void *) buf1,
- (const void *) buf2,
- (size_t) prefix_len);
+ rc = duk_memcmp_unsafe((const void *) buf1, (const void *) buf2, (size_t) prefix_len);
if (rc < 0) {
return -1;
@@ -77854,7 +83259,7 @@ DUK_INTERNAL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring
(duk_size_t) DUK_HSTRING_GET_BYTELEN(h2));
}
-#if 0 /* unused */
+#if 0 /* unused */
DUK_INTERNAL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2) {
/* Similar to String comparison. */
@@ -77891,47 +83296,47 @@ DUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk
s2 = (duk_small_int_t) DUK_SIGNBIT(d2);
if (c1 == DUK_FP_NAN || c2 == DUK_FP_NAN) {
- return 0; /* Always false, regardless of negation. */
+ return 0; /* Always false, regardless of negation. */
}
if (c1 == DUK_FP_ZERO && c2 == DUK_FP_ZERO) {
/* For all combinations: +0 < +0, +0 < -0, -0 < +0, -0 < -0,
* steps e, f, and g.
*/
- return retval; /* false */
+ return retval; /* false */
}
if (d1 == d2) {
- return retval; /* false */
+ return retval; /* false */
}
if (c1 == DUK_FP_INFINITE && s1 == 0) {
/* x == +Infinity */
- return retval; /* false */
+ return retval; /* false */
}
if (c2 == DUK_FP_INFINITE && s2 == 0) {
/* y == +Infinity */
- return retval ^ 1; /* true */
+ return retval ^ 1; /* true */
}
if (c2 == DUK_FP_INFINITE && s2 != 0) {
/* y == -Infinity */
- return retval; /* false */
+ return retval; /* false */
}
if (c1 == DUK_FP_INFINITE && s1 != 0) {
/* x == -Infinity */
- return retval ^ 1; /* true */
+ return retval ^ 1; /* true */
}
if (d1 < d2) {
- return retval ^ 1; /* true */
+ return retval ^ 1; /* true */
}
- return retval; /* false */
+ return retval; /* false */
}
-#else /* DUK_USE_PARANOID_MATH */
+#else /* DUK_USE_PARANOID_MATH */
DUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk_double_t d2) {
/* This comparison tree relies doesn't match the exact steps in
* E5 Section 11.8.5 but should produce the same results. The
@@ -77968,39 +83373,35 @@ DUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk
* results in false return (see e.g. Section
* 11.8.3) - hence special treatment here.
*/
- return 0; /* zero regardless of negation */
+ return 0; /* zero regardless of negation */
} else {
return retval;
}
}
}
}
-#endif /* DUK_USE_PARANOID_MATH */
+#endif /* DUK_USE_PARANOID_MATH */
DUK_INTERNAL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags) {
duk_double_t d1, d2;
duk_small_int_t rc;
duk_bool_t retval;
- DUK_ASSERT(DUK_COMPARE_FLAG_NEGATE == 1); /* Rely on this flag being lowest. */
+ DUK_ASSERT(DUK_COMPARE_FLAG_NEGATE == 1); /* Rely on this flag being lowest. */
retval = flags & DUK_COMPARE_FLAG_NEGATE;
DUK_ASSERT(retval == 0 || retval == 1);
/* Fast path for fastints */
#if defined(DUK_USE_FASTINT)
if (DUK_LIKELY(DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y))) {
- return duk__compare_fastint(retval,
- DUK_TVAL_GET_FASTINT(tv_x),
- DUK_TVAL_GET_FASTINT(tv_y));
+ return duk__compare_fastint(retval, DUK_TVAL_GET_FASTINT(tv_x), DUK_TVAL_GET_FASTINT(tv_y));
}
-#endif /* DUK_USE_FASTINT */
+#endif /* DUK_USE_FASTINT */
/* Fast path for numbers (one of which may be a fastint) */
#if !defined(DUK_USE_PREFER_SIZE)
if (DUK_LIKELY(DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y))) {
- return duk__compare_number(retval,
- DUK_TVAL_GET_NUMBER(tv_x),
- DUK_TVAL_GET_NUMBER(tv_y));
+ return duk__compare_number(retval, DUK_TVAL_GET_NUMBER(tv_x), DUK_TVAL_GET_NUMBER(tv_y));
}
#endif
@@ -78067,7 +83468,7 @@ DUK_INTERNAL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x,
thr->valstack_top -= 2;
tv_x = thr->valstack_top;
tv_y = tv_x + 1;
- DUK_TVAL_SET_UNDEFINED(tv_x); /* Value stack policy */
+ DUK_TVAL_SET_UNDEFINED(tv_x); /* Value stack policy */
DUK_TVAL_SET_UNDEFINED(tv_y);
#endif
@@ -78079,22 +83480,19 @@ DUK_INTERNAL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x,
*/
/*
- * E5 Section 11.8.6 describes the main algorithm, which uses
- * [[HasInstance]]. [[HasInstance]] is defined for only
- * function objects:
- *
- * - Normal functions:
- * E5 Section 15.3.5.3
- * - Functions established with Function.prototype.bind():
- * E5 Section 15.3.4.5.3
+ * ES2015 Section 7.3.19 describes the OrdinaryHasInstance() algorithm
+ * which covers both bound and non-bound functions; in effect the algorithm
+ * includes E5 Sections 11.8.6, 15.3.5.3, and 15.3.4.5.3.
*
- * For other objects, a TypeError is thrown.
+ * ES2015 Section 12.9.4 describes the instanceof operator which first
+ * checks @@hasInstance well-known symbol and falls back to
+ * OrdinaryHasInstance().
*
* Limited Proxy support: don't support 'getPrototypeOf' trap but
* continue lookup in Proxy target if the value is a Proxy.
*/
-DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
+DUK_LOCAL duk_bool_t duk__js_instanceof_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_bool_t skip_sym_check) {
duk_hobject *func;
duk_hobject *val;
duk_hobject *proto;
@@ -78117,6 +83515,23 @@ DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_
func = duk_require_hobject(thr, -1);
DUK_ASSERT(func != NULL);
+#if defined(DUK_USE_SYMBOL_BUILTIN)
+ /*
+ * @@hasInstance check, ES2015 Section 12.9.4, Steps 2-4.
+ */
+ if (!skip_sym_check) {
+ if (duk_get_method_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)) {
+ /* [ ... lhs rhs func ] */
+ duk_insert(thr, -3); /* -> [ ... func lhs rhs ] */
+ duk_swap_top(thr, -2); /* -> [ ... func rhs(this) lhs ] */
+ duk_call_method(thr, 1);
+ return duk_to_boolean_top_pop(thr);
+ }
+ }
+#else
+ DUK_UNREF(skip_sym_check);
+#endif
+
/*
* For bound objects, [[HasInstance]] just calls the target function
* [[HasInstance]]. If that is again a bound object, repeat until
@@ -78128,7 +83543,7 @@ DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_
if (!DUK_HOBJECT_IS_CALLABLE(func)) {
/*
- * Note: of native Ecmascript objects, only Function instances
+ * Note: of native ECMAScript objects, only Function instances
* have a [[HasInstance]] internal property. Custom objects might
* also have it, but not in current implementation.
*
@@ -78138,9 +83553,9 @@ DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_
}
if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
- duk_push_tval(thr, &((duk_hboundfunc *) func)->target);
+ duk_push_tval(thr, &((duk_hboundfunc *) (void *) func)->target);
duk_replace(thr, -2);
- func = duk_require_hobject(thr, -1); /* lightfunc throws */
+ func = duk_require_hobject(thr, -1); /* lightfunc throws */
/* Rely on Function.prototype.bind() never creating bound
* functions whose target is not proper.
@@ -78180,19 +83595,19 @@ DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_
DUK_ASSERT(val != NULL);
break;
case DUK_TAG_OBJECT:
- skip_first = 1; /* Ignore object itself on first round. */
+ skip_first = 1; /* Ignore object itself on first round. */
val = DUK_TVAL_GET_OBJECT(tv);
DUK_ASSERT(val != NULL);
break;
default:
goto pop2_and_false;
}
- DUK_ASSERT(val != NULL); /* Loop doesn't actually rely on this. */
+ DUK_ASSERT(val != NULL); /* Loop doesn't actually rely on this. */
/* Look up .prototype of rval. Leave it on the value stack in case it
* has been virtualized (e.g. getter, Proxy trap).
*/
- duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_PROTOTYPE); /* -> [ ... lval rval rval.prototype ] */
+ duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_PROTOTYPE); /* -> [ ... lval rval rval.prototype ] */
#if defined(DUK_USE_VERBOSE_ERRORS)
proto = duk_get_hobject(thr, -1);
if (proto == NULL) {
@@ -78241,34 +83656,43 @@ DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_
val = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, val);
} while (--sanity > 0);
- if (DUK_UNLIKELY(sanity == 0)) {
- DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
- }
- DUK_UNREACHABLE();
+ DUK_ASSERT(sanity == 0);
+ DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
+ DUK_WO_NORETURN(return 0;);
- pop2_and_false:
+pop2_and_false:
duk_pop_2_unsafe(thr);
return 0;
- pop3_and_false:
+pop3_and_false:
duk_pop_3_unsafe(thr);
return 0;
- pop3_and_true:
+pop3_and_true:
duk_pop_3_unsafe(thr);
return 1;
- error_invalid_rval:
+error_invalid_rval:
DUK_ERROR_TYPE(thr, DUK_STR_INVALID_INSTANCEOF_RVAL);
- return 0;
+ DUK_WO_NORETURN(return 0;);
#if defined(DUK_USE_VERBOSE_ERRORS)
- error_invalid_rval_noproto:
+error_invalid_rval_noproto:
DUK_ERROR_TYPE(thr, DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO);
- return 0;
+ DUK_WO_NORETURN(return 0;);
#endif
}
+#if defined(DUK_USE_SYMBOL_BUILTIN)
+DUK_INTERNAL duk_bool_t duk_js_instanceof_ordinary(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
+ return duk__js_instanceof_helper(thr, tv_x, tv_y, 1 /*skip_sym_check*/);
+}
+#endif
+
+DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
+ return duk__js_instanceof_helper(thr, tv_x, tv_y, 0 /*skip_sym_check*/);
+}
+
/*
* in
*/
@@ -78305,9 +83729,7 @@ DUK_INTERNAL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv
(void) duk_to_property_key_hstring(thr, -2);
- retval = duk_hobject_hasprop(thr,
- DUK_GET_TVAL_NEGIDX(thr, -1),
- DUK_GET_TVAL_NEGIDX(thr, -2));
+ retval = duk_hobject_hasprop(thr, DUK_GET_TVAL_NEGIDX(thr, -1), DUK_GET_TVAL_NEGIDX(thr, -2));
duk_pop_2_unsafe(thr);
return retval;
@@ -78401,6 +83823,26 @@ DUK_INTERNAL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x) {
}
/*
+ * IsArray()
+ */
+
+DUK_INTERNAL duk_bool_t duk_js_isarray_hobject(duk_hobject *h) {
+ DUK_ASSERT(h != NULL);
+#if defined(DUK_USE_ES6_PROXY)
+ h = duk_hobject_resolve_proxy_target(h);
+#endif
+ return (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY ? 1 : 0);
+}
+
+DUK_INTERNAL duk_bool_t duk_js_isarray(duk_tval *tv) {
+ DUK_ASSERT(tv != NULL);
+ if (DUK_TVAL_IS_OBJECT(tv)) {
+ return duk_js_isarray_hobject(DUK_TVAL_GET_OBJECT(tv));
+ }
+ return 0;
+}
+
+/*
* Array index and length
*
* Array index: E5 Section 15.4
@@ -78447,7 +83889,7 @@ DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, d
}
res = 0xfffffffaUL + dig;
DUK_ASSERT(res >= 0xfffffffaUL);
- DUK_ASSERT_DISABLE(res <= 0xffffffffUL); /* range */
+ DUK_ASSERT_DISABLE(res <= 0xffffffffUL); /* range */
} else {
res = res * 10U + dig;
if (DUK_UNLIKELY(res == 0)) {
@@ -78472,7 +83914,7 @@ DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, d
return res;
- parse_fail:
+parse_fail:
return DUK_HSTRING_NO_ARRAY_INDEX;
}
@@ -78510,7 +83952,7 @@ DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h) {
}
return duk_js_to_arrayindex_hstring_fast_known(h);
}
-#endif /* DUK_USE_HSTRING_ARRIDX */
+#endif /* DUK_USE_HSTRING_ARRIDX */
/*
* Identifier access and function closure handling.
*
@@ -78519,7 +83961,7 @@ DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h) {
* be used for most identifier accesses. Consequently, these slow path
* primitives should be optimized for maximum compactness.
*
- * Ecmascript environment records (declarative and object) are represented
+ * ECMAScript environment records (declarative and object) are represented
* as internal objects with control keys. Environment records have a
* parent record ("outer environment reference") which is represented by
* the implicit prototype for technical reasons (in other words, it is a
@@ -78551,17 +83993,17 @@ DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h) {
typedef struct {
duk_hobject *env;
- duk_hobject *holder; /* for object-bound identifiers */
- duk_tval *value; /* for register-bound and declarative env identifiers */
- duk_uint_t attrs; /* property attributes for identifier (relevant if value != NULL) */
- duk_bool_t has_this; /* for object-bound identifiers: provide 'this' binding */
+ duk_hobject *holder; /* for object-bound identifiers */
+ duk_tval *value; /* for register-bound and declarative env identifiers */
+ duk_uint_t attrs; /* property attributes for identifier (relevant if value != NULL) */
+ duk_bool_t has_this; /* for object-bound identifiers: provide 'this' binding */
} duk__id_lookup_result;
/*
* Create a new function object based on a "template function" which contains
* compiled bytecode, constants, etc, but lacks a lexical environment.
*
- * Ecmascript requires that each created closure is a separate object, with
+ * ECMAScript requires that each created closure is a separate object, with
* its own set of editable properties. However, structured property values
* (such as the formal arguments list and the variable map) are shared.
* Also the bytecode, constants, and inner functions are shared.
@@ -78640,6 +84082,7 @@ void duk_js_push_closure(duk_hthread *thr,
duk_hobject *outer_lex_env,
duk_bool_t add_auto_proto) {
duk_hcompfunc *fun_clos;
+ duk_harray *formals;
duk_small_uint_t i;
duk_uint_t len_value;
@@ -78651,11 +84094,13 @@ void duk_js_push_closure(duk_hthread *thr,
DUK_ASSERT(outer_lex_env != NULL);
DUK_UNREF(len_value);
+ DUK_STATS_INC(thr->heap, stats_envrec_pushclosure);
+
fun_clos = duk_push_hcompfunc(thr);
DUK_ASSERT(fun_clos != NULL);
DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) fun_clos) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
- duk_push_hobject(thr, &fun_temp->obj); /* -> [ ... closure template ] */
+ duk_push_hobject(thr, &fun_temp->obj); /* -> [ ... closure template ] */
DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun_clos));
DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) == NULL);
@@ -78763,9 +84208,9 @@ void duk_js_push_closure(duk_hthread *thr,
}
/* -> [ ... closure template env ] */
- new_env = duk_hdecenv_alloc(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
+ new_env =
+ duk_hdecenv_alloc(thr,
+ DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
DUK_ASSERT(new_env != NULL);
duk_push_hobject(thr, (duk_hobject *) new_env);
@@ -78773,7 +84218,7 @@ void duk_js_push_closure(duk_hthread *thr,
DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, proto);
DUK_HOBJECT_INCREF_ALLOWNULL(thr, proto);
- DUK_ASSERT(new_env->thread == NULL); /* Closed. */
+ DUK_ASSERT(new_env->thread == NULL); /* Closed. */
DUK_ASSERT(new_env->varmap == NULL);
/* It's important that duk_xdef_prop() is a 'raw define' so that any
@@ -78787,8 +84232,8 @@ void duk_js_push_closure(duk_hthread *thr,
*/
(void) duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
/* -> [ ... closure template env funcname ] */
- duk_dup_m4(thr); /* -> [ ... closure template env funcname closure ] */
- duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE); /* -> [ ... closure template env ] */
+ duk_dup_m4(thr); /* -> [ ... closure template env funcname closure ] */
+ duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE); /* -> [ ... closure template env ] */
/* env[funcname] = closure */
/* [ ... closure template env ] */
@@ -78800,9 +84245,8 @@ void duk_js_push_closure(duk_hthread *thr,
duk_pop_unsafe(thr);
/* [ ... closure template ] */
- }
- else
-#endif /* DUK_USE_FUNC_NAME_PROPERTY */
+ } else
+#endif /* DUK_USE_FUNC_NAME_PROPERTY */
{
/*
* Other cases (function declaration, anonymous function expression,
@@ -78830,7 +84274,7 @@ void duk_js_push_closure(duk_hthread *thr,
DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);
DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_var_env);
- DUK_HOBJECT_INCREF(thr, outer_lex_env); /* NULLs not allowed; asserted on entry */
+ DUK_HOBJECT_INCREF(thr, outer_lex_env); /* NULLs not allowed; asserted on entry */
DUK_HOBJECT_INCREF(thr, outer_var_env);
}
DUK_DDD(DUK_DDDPRINT("closure varenv -> %!ipO, lexenv -> %!ipO",
@@ -78846,6 +84290,11 @@ void duk_js_push_closure(duk_hthread *thr,
*
* The properties will be non-writable and non-enumerable, but
* configurable.
+ *
+ * Function templates are bare objects, so inheritance of internal
+ * Symbols is not an issue here even when using ordinary property
+ * reads. The function instance created is not bare, so internal
+ * Symbols must be defined without inheritance checks.
*/
/* [ ... closure template ] */
@@ -78856,7 +84305,7 @@ void duk_js_push_closure(duk_hthread *thr,
for (i = 0; i < (duk_small_uint_t) (sizeof(duk__closure_copy_proplist) / sizeof(duk_uint16_t)); i++) {
duk_small_int_t stridx = (duk_small_int_t) duk__closure_copy_proplist[i];
- if (duk_get_prop_stridx_short(thr, -1, stridx)) {
+ if (duk_xget_owndataprop_stridx_short(thr, -1, stridx)) {
/* [ ... closure template val ] */
DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> found", (long) stridx));
duk_xdef_prop_stridx_short(thr, -3, stridx, DUK_PROPDESC_FLAGS_C);
@@ -78875,20 +84324,16 @@ void duk_js_push_closure(duk_hthread *thr,
/* [ ... closure template ] */
- /* XXX: these lookups should be just own property lookups instead of
- * looking up the inheritance chain.
- */
- if (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_FORMALS)) {
- /* [ ... closure template formals ] */
- len_value = (duk_uint_t) duk_get_length(thr, -1); /* could access duk_harray directly, not important */
+ formals = duk_hobject_get_formals(thr, (duk_hobject *) fun_temp);
+ if (formals) {
+ len_value = (duk_uint_t) formals->length;
DUK_DD(DUK_DDPRINT("closure length from _Formals -> %ld", (long) len_value));
} else {
len_value = fun_temp->nargs;
DUK_DD(DUK_DDPRINT("closure length defaulted from nargs -> %ld", (long) len_value));
}
- duk_pop_unsafe(thr);
- duk_push_uint(thr, len_value); /* [ ... closure template len_value ] */
+ duk_push_uint(thr, len_value); /* [ ... closure template len_value ] */
duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
/*
@@ -78908,11 +84353,14 @@ void duk_js_push_closure(duk_hthread *thr,
/* [ ... closure template ] */
if (add_auto_proto) {
- duk_push_object(thr); /* -> [ ... closure template newobj ] */
- duk_dup_m3(thr); /* -> [ ... closure template newobj closure ] */
- duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC); /* -> [ ... closure template newobj ] */
- duk_compact(thr, -1); /* compact the prototype */
- duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W); /* -> [ ... closure template ] */
+ duk_push_object(thr); /* -> [ ... closure template newobj ] */
+ duk_dup_m3(thr); /* -> [ ... closure template newobj closure ] */
+ duk_xdef_prop_stridx_short(thr,
+ -2,
+ DUK_STRIDX_CONSTRUCTOR,
+ DUK_PROPDESC_FLAGS_WC); /* -> [ ... closure template newobj ] */
+ duk_compact(thr, -1); /* compact the prototype */
+ duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W); /* -> [ ... closure template ] */
}
/*
@@ -78953,7 +84401,7 @@ void duk_js_push_closure(duk_hthread *thr,
/* [ ... closure template name ] */
DUK_ASSERT(duk_is_string(thr, -1));
DUK_DD(DUK_DDPRINT("setting function instance name to %!T", duk_get_tval(thr, -1)));
- duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C); /* -> [ ... closure template ] */
+ duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C); /* -> [ ... closure template ] */
} else {
/* Anonymous functions don't have a .name in ES2015, so don't set
* it on the instance either. The instance will then inherit
@@ -78985,10 +84433,8 @@ void duk_js_push_closure(duk_hthread *thr,
DUK_ASSERT(duk_has_prop_stridx(thr, -2, DUK_STRIDX_LENGTH) != 0);
DUK_ASSERT(add_auto_proto == 0 || duk_has_prop_stridx(thr, -2, DUK_STRIDX_PROTOTYPE) != 0);
/* May be missing .name */
- DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
- duk_has_prop_stridx(thr, -2, DUK_STRIDX_CALLER) != 0);
- DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
- duk_has_prop_stridx(thr, -2, DUK_STRIDX_LC_ARGUMENTS) != 0);
+ DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) || duk_has_prop_stridx(thr, -2, DUK_STRIDX_CALLER) != 0);
+ DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) || duk_has_prop_stridx(thr, -2, DUK_STRIDX_LC_ARGUMENTS) != 0);
/*
* Finish
@@ -79012,11 +84458,32 @@ void duk_js_push_closure(duk_hthread *thr,
* The non-delayed initialization is handled by duk_handle_call().
*/
+DUK_LOCAL void duk__preallocate_env_entries(duk_hthread *thr, duk_hobject *varmap, duk_hobject *env) {
+ duk_uint_fast32_t i;
+
+ for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {
+ duk_hstring *key;
+
+ key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
+ DUK_ASSERT(key != NULL); /* assume keys are compact in _Varmap */
+ DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i)); /* assume plain values */
+
+ /* Predefine as 'undefined' to reserve a property slot.
+ * This makes the unwind process (where register values
+ * are copied to the env object) safe against throwing.
+ *
+ * XXX: This could be made much faster by creating the
+ * property table directly.
+ */
+ duk_push_undefined(thr);
+ DUK_DDD(DUK_DDDPRINT("preallocate env entry for key %!O", key));
+ duk_hobject_define_property_internal(thr, env, key, DUK_PROPDESC_FLAGS_WE);
+ }
+}
+
/* shared helper */
DUK_INTERNAL
-duk_hobject *duk_create_activation_environment_record(duk_hthread *thr,
- duk_hobject *func,
- duk_size_t bottom_byteoff) {
+duk_hobject *duk_create_activation_environment_record(duk_hthread *thr, duk_hobject *func, duk_size_t bottom_byteoff) {
duk_hdecenv *env;
duk_hobject *parent;
duk_hcompfunc *f;
@@ -79024,21 +84491,21 @@ duk_hobject *duk_create_activation_environment_record(duk_hthread *thr,
DUK_ASSERT(thr != NULL);
DUK_ASSERT(func != NULL);
+ DUK_STATS_INC(thr->heap, stats_envrec_create);
+
f = (duk_hcompfunc *) func;
parent = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
if (!parent) {
parent = thr->builtins[DUK_BIDX_GLOBAL_ENV];
}
- env = duk_hdecenv_alloc(thr,
- DUK_HOBJECT_FLAG_EXTENSIBLE |
- DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
+ env = duk_hdecenv_alloc(thr, DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
DUK_ASSERT(env != NULL);
duk_push_hobject(thr, (duk_hobject *) env);
DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) env, parent);
- DUK_HOBJECT_INCREF_ALLOWNULL(thr, parent); /* parent env is the prototype */
+ DUK_HOBJECT_INCREF_ALLOWNULL(thr, parent); /* parent env is the prototype */
/* open scope information, for compiled functions only */
@@ -79047,18 +84514,19 @@ duk_hobject *duk_create_activation_environment_record(duk_hthread *thr,
DUK_ASSERT(env->regbase_byteoff == 0);
if (DUK_HOBJECT_IS_COMPFUNC(func)) {
duk_hobject *varmap;
- duk_tval *tv;
- tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
- if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
- DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
- varmap = DUK_TVAL_GET_OBJECT(tv);
- DUK_ASSERT(varmap != NULL);
+ varmap = duk_hobject_get_varmap(thr, func);
+ if (varmap != NULL) {
env->varmap = varmap;
DUK_HOBJECT_INCREF(thr, varmap);
env->thread = thr;
DUK_HTHREAD_INCREF(thr, thr);
env->regbase_byteoff = bottom_byteoff;
+
+ /* Preallocate env property table to avoid potential
+ * for out-of-memory on unwind when the env is closed.
+ */
+ duk__preallocate_env_entries(thr, varmap, (duk_hobject *) env);
} else {
/* If function has no _Varmap, leave the environment closed. */
DUK_ASSERT(env->thread == NULL);
@@ -79071,15 +84539,14 @@ duk_hobject *duk_create_activation_environment_record(duk_hthread *thr,
}
DUK_INTERNAL
-void duk_js_init_activation_environment_records_delayed(duk_hthread *thr,
- duk_activation *act) {
+void duk_js_init_activation_environment_records_delayed(duk_hthread *thr, duk_activation *act) {
duk_hobject *func;
duk_hobject *env;
DUK_ASSERT(thr != NULL);
func = DUK_ACT_GET_FUNC(act);
DUK_ASSERT(func != NULL);
- DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func)); /* bound functions are never in act 'func' */
+ DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func)); /* bound functions are never in act 'func' */
/*
* Delayed initialization only occurs for 'NEWENV' functions.
@@ -79089,6 +84556,8 @@ void duk_js_init_activation_environment_records_delayed(duk_hthread *thr,
DUK_ASSERT(act->lex_env == NULL);
DUK_ASSERT(act->var_env == NULL);
+ DUK_STATS_INC(thr->heap, stats_envrec_delayedcreate);
+
env = duk_create_activation_environment_record(thr, func, act->bottom_byteoff);
DUK_ASSERT(env != NULL);
/* 'act' is a stable pointer, so still OK. */
@@ -79106,7 +84575,7 @@ void duk_js_init_activation_environment_records_delayed(duk_hthread *thr,
act->lex_env = env;
act->var_env = env;
- DUK_HOBJECT_INCREF(thr, env); /* XXX: incref by count (here 2 times) */
+ DUK_HOBJECT_INCREF(thr, env); /* XXX: incref by count (here 2 times) */
DUK_HOBJECT_INCREF(thr, env);
duk_pop_unsafe(thr);
@@ -79142,7 +84611,7 @@ DUK_INTERNAL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject
return;
}
DUK_ASSERT(((duk_hdecenv *) env)->thread != NULL);
- DUK_ASSERT_HDECENV_VALID((duk_hdecenv *) env);
+ DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) env);
DUK_DDD(DUK_DDDPRINT("closing env: %!iO", (duk_heaphdr *) env));
DUK_DDD(DUK_DDDPRINT("varmap: %!O", (duk_heaphdr *) varmap));
@@ -79176,12 +84645,12 @@ DUK_INTERNAL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject
duk_size_t regbase_byteoff;
key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
- DUK_ASSERT(key != NULL); /* assume keys are compact in _Varmap */
- DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i)); /* assume plain values */
+ DUK_ASSERT(key != NULL); /* assume keys are compact in _Varmap */
+ DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i)); /* assume plain values */
tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, varmap, i);
DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
- DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (duk_double_t) DUK_UINT32_MAX); /* limits */
+ DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (duk_double_t) DUK_UINT32_MAX); /* limits */
#if defined(DUK_USE_FASTINT)
DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
regnum = (duk_uint_t) DUK_TVAL_GET_FASTINT_U32(tv);
@@ -79190,14 +84659,25 @@ DUK_INTERNAL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject
#endif
regbase_byteoff = ((duk_hdecenv *) env)->regbase_byteoff;
- DUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum >= (duk_uint8_t *) thr->valstack);
- DUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum < (duk_uint8_t *) thr->valstack_top);
+ DUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum >=
+ (duk_uint8_t *) thr->valstack);
+ DUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum <
+ (duk_uint8_t *) thr->valstack_top);
- /* If property already exists, overwrites silently.
+ /* Write register value into env as named properties.
+ * If property already exists, overwrites silently.
* Property is writable, but not deletable (not configurable
* in terms of property attributes).
- */
- duk_push_tval(thr, (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum));
+ *
+ * This property write must not throw because we're unwinding
+ * and unwind code is not allowed to throw at present. The
+ * call itself has no such guarantees, but we've preallocated
+ * entries for each property when the env was created, so no
+ * out-of-memory error should be possible. If this guarantee
+ * is not provided, problems like GH-476 may happen.
+ */
+ duk_push_tval(thr,
+ (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum));
DUK_DDD(DUK_DDDPRINT("closing identifier %!O -> reg %ld, value %!T",
(duk_heaphdr *) key,
(long) regnum,
@@ -79239,10 +84719,7 @@ DUK_INTERNAL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject
/* lookup name from an open declarative record's registers */
DUK_LOCAL
-duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
- duk_hstring *name,
- duk_hdecenv *env,
- duk__id_lookup_result *out) {
+duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr, duk_hstring *name, duk_hdecenv *env, duk__id_lookup_result *out) {
duk_tval *tv;
duk_size_t reg_rel;
@@ -79252,7 +84729,7 @@ duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
DUK_ASSERT(out != NULL);
DUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) env));
- DUK_ASSERT_HDECENV_VALID(env);
+ DUK_HDECENV_ASSERT_VALID(env);
if (env->thread == NULL) {
/* already closed */
@@ -79260,26 +84737,26 @@ duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
}
DUK_ASSERT(env->varmap != NULL);
- tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env->varmap, name);
+ tv = duk_hobject_find_entry_tval_ptr(thr->heap, env->varmap, name);
if (DUK_UNLIKELY(tv == NULL)) {
return 0;
}
DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
- DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (duk_double_t) DUK_UINT32_MAX); /* limits */
+ DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (duk_double_t) DUK_UINT32_MAX); /* limits */
#if defined(DUK_USE_FASTINT)
DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
reg_rel = (duk_size_t) DUK_TVAL_GET_FASTINT_U32(tv);
#else
reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
#endif
- DUK_ASSERT_DISABLE(reg_rel >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(reg_rel >= 0); /* unsigned */
tv = (duk_tval *) (void *) ((duk_uint8_t *) env->thread->valstack + env->regbase_byteoff + sizeof(duk_tval) * reg_rel);
- DUK_ASSERT(tv >= env->thread->valstack && tv < env->thread->valstack_end); /* XXX: more accurate? */
+ DUK_ASSERT(tv >= env->thread->valstack && tv < env->thread->valstack_end); /* XXX: more accurate? */
out->value = tv;
- out->attrs = DUK_PROPDESC_FLAGS_W; /* registers are mutable, non-deletable */
+ out->attrs = DUK_PROPDESC_FLAGS_W; /* registers are mutable, non-deletable */
out->env = (duk_hobject *) env;
out->holder = NULL;
out->has_this = 0;
@@ -79288,10 +84765,7 @@ duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
/* lookup name from current activation record's functions' registers */
DUK_LOCAL
-duk_bool_t duk__getid_activation_regs(duk_hthread *thr,
- duk_hstring *name,
- duk_activation *act,
- duk__id_lookup_result *out) {
+duk_bool_t duk__getid_activation_regs(duk_hthread *thr, duk_hstring *name, duk_activation *act, duk__id_lookup_result *out) {
duk_tval *tv;
duk_hobject *func;
duk_hobject *varmap;
@@ -79310,16 +84784,13 @@ duk_bool_t duk__getid_activation_regs(duk_hthread *thr,
return 0;
}
- /* XXX: move varmap to duk_hcompfunc struct field. */
- tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
- if (!tv) {
+ /* XXX: move varmap to duk_hcompfunc struct field? */
+ varmap = duk_hobject_get_varmap(thr, func);
+ if (!varmap) {
return 0;
}
- DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
- varmap = DUK_TVAL_GET_OBJECT(tv);
- DUK_ASSERT(varmap != NULL);
- tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, varmap, name);
+ tv = duk_hobject_find_entry_tval_ptr(thr->heap, varmap, name);
if (!tv) {
return 0;
}
@@ -79332,7 +84803,7 @@ duk_bool_t duk__getid_activation_regs(duk_hthread *thr,
tv += reg_rel;
out->value = tv;
- out->attrs = DUK_PROPDESC_FLAGS_W; /* registers are mutable, non-deletable */
+ out->attrs = DUK_PROPDESC_FLAGS_W; /* registers are mutable, non-deletable */
out->env = NULL;
out->holder = NULL;
out->has_this = 0;
@@ -79388,9 +84859,12 @@ duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
"name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
"(found from register bindings when env=NULL)",
- (duk_heaphdr *) name, (duk_tval *) out->value,
- (long) out->attrs, (long) out->has_this,
- (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
+ (duk_heaphdr *) name,
+ (duk_tval *) out->value,
+ (long) out->attrs,
+ (long) out->has_this,
+ (duk_heaphdr *) out->env,
+ (duk_heaphdr *) out->holder));
return 1;
}
@@ -79427,8 +84901,7 @@ duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
}
- DUK_DDD(DUK_DDDPRINT("continue lookup from env: %!iO",
- (duk_heaphdr *) env));
+ DUK_DDD(DUK_DDDPRINT("continue lookup from env: %!iO", (duk_heaphdr *) env));
}
/*
@@ -79466,18 +84939,21 @@ duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
* register-bound variables.
*/
- DUK_ASSERT_HDECENV_VALID((duk_hdecenv *) env);
+ DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) env);
if (duk__getid_open_decl_env_regs(thr, name, (duk_hdecenv *) env, out)) {
DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
"name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
"(declarative environment record, scope open, found in regs)",
- (duk_heaphdr *) name, (duk_tval *) out->value,
- (long) out->attrs, (long) out->has_this,
- (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
+ (duk_heaphdr *) name,
+ (duk_tval *) out->value,
+ (long) out->attrs,
+ (long) out->has_this,
+ (duk_heaphdr *) out->env,
+ (duk_heaphdr *) out->holder));
return 1;
}
- tv = duk_hobject_find_existing_entry_tval_ptr_and_attrs(thr->heap, env, name, &attrs);
+ tv = duk_hobject_find_entry_tval_ptr_and_attrs(thr->heap, env, name, &attrs);
if (tv) {
out->value = tv;
out->attrs = attrs;
@@ -79488,9 +84964,12 @@ duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
"name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
"(declarative environment record, found in properties)",
- (duk_heaphdr *) name, (duk_tval *) out->value,
- (long) out->attrs, (long) out->has_this,
- (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
+ (duk_heaphdr *) name,
+ (duk_tval *) out->value,
+ (long) out->attrs,
+ (long) out->has_this,
+ (duk_heaphdr *) out->env,
+ (duk_heaphdr *) out->holder));
return 1;
}
} else {
@@ -79512,7 +84991,7 @@ duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
duk_bool_t found;
DUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV);
- DUK_ASSERT_HOBJENV_VALID((duk_hobjenv *) env);
+ DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) env);
target = ((duk_hobjenv *) env)->target;
DUK_ASSERT(target != NULL);
@@ -79535,7 +85014,7 @@ duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
found = duk_hobject_hasprop(thr, &tv_target_tmp, &tv_name);
} else
-#endif /* DUK_USE_ES6_PROXY */
+#endif /* DUK_USE_ES6_PROXY */
{
/* XXX: duk_hobject_hasprop() would be correct for
* non-Proxy objects too, but it is about ~20-25%
@@ -79546,8 +85025,8 @@ duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
}
if (found) {
- out->value = NULL; /* can't get value, may be accessor */
- out->attrs = 0; /* irrelevant when out->value == NULL */
+ out->value = NULL; /* can't get value, may be accessor */
+ out->attrs = 0; /* irrelevant when out->value == NULL */
out->env = env;
out->holder = target;
out->has_this = ((duk_hobjenv *) env)->has_this;
@@ -79555,9 +85034,12 @@ duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
"name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
"(object environment record)",
- (duk_heaphdr *) name, (duk_tval *) out->value,
- (long) out->attrs, (long) out->has_this,
- (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
+ (duk_heaphdr *) name,
+ (duk_tval *) out->value,
+ (long) out->attrs,
+ (long) out->has_this,
+ (duk_heaphdr *) out->env,
+ (duk_heaphdr *) out->holder));
return 1;
}
}
@@ -79568,9 +85050,10 @@ duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
goto fail_not_found;
}
- if (DUK_UNLIKELY(sanity-- == 0)) {
- DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
- }
+ if (DUK_UNLIKELY(sanity-- == 0)) {
+ DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
+ DUK_WO_NORETURN(return 0;);
+ }
env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);
}
@@ -79578,7 +85061,7 @@ duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
* Not found (even in global object)
*/
- fail_not_found:
+fail_not_found:
return 0;
}
@@ -79597,7 +85080,7 @@ duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
* a 'strict' parameter.
*/
-#if 0 /*unused*/
+#if 0 /*unused*/
DUK_INTERNAL
duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr,
duk_hobject *env,
@@ -79653,11 +85136,7 @@ duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr,
*/
DUK_LOCAL
-duk_bool_t duk__getvar_helper(duk_hthread *thr,
- duk_hobject *env,
- duk_activation *act,
- duk_hstring *name,
- duk_bool_t throw_flag) {
+duk_bool_t duk__getvar_helper(duk_hthread *thr, duk_hobject *env, duk_activation *act, duk_hstring *name, duk_bool_t throw_flag) {
duk__id_lookup_result ref;
duk_tval tv_tmp_obj;
duk_tval tv_tmp_key;
@@ -79665,8 +85144,11 @@ duk_bool_t duk__getvar_helper(duk_hthread *thr,
DUK_DDD(DUK_DDDPRINT("getvar: thr=%p, env=%p, act=%p, name=%!O "
"(env -> %!dO)",
- (void *) thr, (void *) env, (void *) act,
- (duk_heaphdr *) name, (duk_heaphdr *) env));
+ (void *) thr,
+ (void *) env,
+ (void *) act,
+ (duk_heaphdr *) name,
+ (duk_heaphdr *) env));
DUK_ASSERT(thr != NULL);
DUK_ASSERT(name != NULL);
@@ -79674,10 +85156,10 @@ duk_bool_t duk__getvar_helper(duk_hthread *thr,
DUK_STATS_INC(thr->heap, stats_getvar_all);
- DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
- DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
+ DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
+ DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
- parents = 1; /* follow parent chain */
+ parents = 1; /* follow parent chain */
if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
if (ref.value) {
duk_push_tval(thr, ref.value);
@@ -79692,7 +85174,7 @@ duk_bool_t duk__getvar_helper(duk_hthread *thr,
DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
DUK_TVAL_SET_STRING(&tv_tmp_key, name);
- (void) duk_hobject_getprop(thr, &tv_tmp_obj, &tv_tmp_key); /* [value] */
+ (void) duk_hobject_getprop(thr, &tv_tmp_obj, &tv_tmp_key); /* [value] */
if (ref.has_this) {
duk_push_hobject(thr, ref.holder);
@@ -79706,9 +85188,11 @@ duk_bool_t duk__getvar_helper(duk_hthread *thr,
return 1;
} else {
if (throw_flag) {
- DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,
+ DUK_ERROR_FMT1(thr,
+ DUK_ERR_REFERENCE_ERROR,
"identifier '%s' undefined",
(const char *) DUK_HSTRING_GET_DATA(name));
+ DUK_WO_NORETURN(return 0;);
}
return 0;
@@ -79716,18 +85200,12 @@ duk_bool_t duk__getvar_helper(duk_hthread *thr,
}
DUK_INTERNAL
-duk_bool_t duk_js_getvar_envrec(duk_hthread *thr,
- duk_hobject *env,
- duk_hstring *name,
- duk_bool_t throw_flag) {
+duk_bool_t duk_js_getvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_bool_t throw_flag) {
return duk__getvar_helper(thr, env, NULL, name, throw_flag);
}
DUK_INTERNAL
-duk_bool_t duk_js_getvar_activation(duk_hthread *thr,
- duk_activation *act,
- duk_hstring *name,
- duk_bool_t throw_flag) {
+duk_bool_t duk_js_getvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_bool_t throw_flag) {
DUK_ASSERT(act != NULL);
return duk__getvar_helper(thr, act->lex_env, act, name, throw_flag);
}
@@ -79755,6 +85233,7 @@ void duk__putvar_helper(duk_hthread *thr,
duk_tval *val,
duk_bool_t strict) {
duk__id_lookup_result ref;
+ duk_tval tv_tmp_val;
duk_tval tv_tmp_obj;
duk_tval tv_tmp_key;
duk_bool_t parents;
@@ -79763,19 +85242,27 @@ void duk__putvar_helper(duk_hthread *thr,
DUK_DDD(DUK_DDDPRINT("putvar: thr=%p, env=%p, act=%p, name=%!O, val=%p, strict=%ld "
"(env -> %!dO, val -> %!T)",
- (void *) thr, (void *) env, (void *) act,
- (duk_heaphdr *) name, (void *) val, (long) strict,
- (duk_heaphdr *) env, (duk_tval *) val));
+ (void *) thr,
+ (void *) env,
+ (void *) act,
+ (duk_heaphdr *) name,
+ (void *) val,
+ (long) strict,
+ (duk_heaphdr *) env,
+ (duk_tval *) val));
DUK_ASSERT(thr != NULL);
DUK_ASSERT(name != NULL);
DUK_ASSERT(val != NULL);
/* env and act may be NULL */
- DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
- DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
+ DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
+ DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
DUK_ASSERT_REFCOUNT_NONZERO_TVAL(val);
+ DUK_TVAL_SET_TVAL(&tv_tmp_val, val); /* Stabilize. */
+ val = NULL;
+
/*
* In strict mode E5 protects 'eval' and 'arguments' from being
* assigned to (or even declared anywhere). Attempt to do so
@@ -79786,15 +85273,13 @@ void duk__putvar_helper(duk_hthread *thr,
* and name 'eval' or 'arguments'.
*/
- DUK_ASSERT(!strict ||
- (name != DUK_HTHREAD_STRING_EVAL(thr) &&
- name != DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)));
+ DUK_ASSERT(!strict || (name != DUK_HTHREAD_STRING_EVAL(thr) && name != DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)));
/*
* Lookup variable and update in-place if found.
*/
- parents = 1; /* follow parent chain */
+ parents = 1; /* follow parent chain */
if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
if (ref.value && (ref.attrs & DUK_PROPDESC_FLAG_WRITABLE)) {
@@ -79807,7 +85292,7 @@ void duk__putvar_helper(duk_hthread *thr,
tv_val = ref.value;
DUK_ASSERT(tv_val != NULL);
- DUK_TVAL_SET_TVAL_UPDREF(thr, tv_val, val); /* side effects */
+ DUK_TVAL_SET_TVAL_UPDREF(thr, tv_val, &tv_tmp_val); /* side effects */
/* ref.value invalidated here */
} else {
@@ -79815,7 +85300,7 @@ void duk__putvar_helper(duk_hthread *thr,
DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
DUK_TVAL_SET_STRING(&tv_tmp_key, name);
- (void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, strict);
+ (void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, &tv_tmp_val, strict);
/* ref.value invalidated here */
}
@@ -79830,16 +85315,18 @@ void duk__putvar_helper(duk_hthread *thr,
if (strict) {
DUK_DDD(DUK_DDDPRINT("identifier binding not found, strict => reference error"));
- DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,
+ DUK_ERROR_FMT1(thr,
+ DUK_ERR_REFERENCE_ERROR,
"identifier '%s' undefined",
(const char *) DUK_HSTRING_GET_DATA(name));
+ DUK_WO_NORETURN(return;);
}
DUK_DDD(DUK_DDDPRINT("identifier binding not found, not strict => set to global"));
DUK_TVAL_SET_OBJECT(&tv_tmp_obj, thr->builtins[DUK_BIDX_GLOBAL]);
DUK_TVAL_SET_STRING(&tv_tmp_key, name);
- (void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, 0); /* 0 = no throw */
+ (void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, &tv_tmp_val, 0); /* 0 = no throw */
/* NB: 'val' may be invalidated here because put_value may realloc valstack,
* caller beware.
@@ -79847,20 +85334,12 @@ void duk__putvar_helper(duk_hthread *thr,
}
DUK_INTERNAL
-void duk_js_putvar_envrec(duk_hthread *thr,
- duk_hobject *env,
- duk_hstring *name,
- duk_tval *val,
- duk_bool_t strict) {
+void duk_js_putvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_tval *val, duk_bool_t strict) {
duk__putvar_helper(thr, env, NULL, name, val, strict);
}
DUK_INTERNAL
-void duk_js_putvar_activation(duk_hthread *thr,
- duk_activation *act,
- duk_hstring *name,
- duk_tval *val,
- duk_bool_t strict) {
+void duk_js_putvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_bool_t strict) {
DUK_ASSERT(act != NULL);
duk__putvar_helper(thr, act->lex_env, act, name, val, strict);
}
@@ -79885,25 +85364,25 @@ void duk_js_putvar_activation(duk_hthread *thr,
*/
DUK_LOCAL
-duk_bool_t duk__delvar_helper(duk_hthread *thr,
- duk_hobject *env,
- duk_activation *act,
- duk_hstring *name) {
+duk_bool_t duk__delvar_helper(duk_hthread *thr, duk_hobject *env, duk_activation *act, duk_hstring *name) {
duk__id_lookup_result ref;
duk_bool_t parents;
DUK_DDD(DUK_DDDPRINT("delvar: thr=%p, env=%p, act=%p, name=%!O "
"(env -> %!dO)",
- (void *) thr, (void *) env, (void *) act,
- (duk_heaphdr *) name, (duk_heaphdr *) env));
+ (void *) thr,
+ (void *) env,
+ (void *) act,
+ (duk_heaphdr *) name,
+ (duk_heaphdr *) env));
DUK_ASSERT(thr != NULL);
DUK_ASSERT(name != NULL);
/* env and act may be NULL */
- DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
+ DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
- parents = 1; /* follow parent chain */
+ parents = 1; /* follow parent chain */
if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
if (ref.value && !(ref.attrs & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
@@ -79931,7 +85410,7 @@ duk_bool_t duk__delvar_helper(duk_hthread *thr,
return 1;
}
-#if 0 /*unused*/
+#if 0 /*unused*/
DUK_INTERNAL
duk_bool_t duk_js_delvar_envrec(duk_hthread *thr,
duk_hobject *env,
@@ -79941,9 +85420,7 @@ duk_bool_t duk_js_delvar_envrec(duk_hthread *thr,
#endif
DUK_INTERNAL
-duk_bool_t duk_js_delvar_activation(duk_hthread *thr,
- duk_activation *act,
- duk_hstring *name) {
+duk_bool_t duk_js_delvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name) {
DUK_ASSERT(act != NULL);
return duk__delvar_helper(thr, act->lex_env, act, name);
}
@@ -80012,9 +85489,13 @@ duk_bool_t duk__declvar_helper(duk_hthread *thr,
DUK_DDD(DUK_DDDPRINT("declvar: thr=%p, env=%p, name=%!O, val=%!T, prop_flags=0x%08lx, is_func_decl=%ld "
"(env -> %!iO)",
- (void *) thr, (void *) env, (duk_heaphdr *) name,
- (duk_tval *) val, (unsigned long) prop_flags,
- (unsigned int) is_func_decl, (duk_heaphdr *) env));
+ (void *) thr,
+ (void *) env,
+ (duk_heaphdr *) name,
+ (duk_tval *) val,
+ (unsigned long) prop_flags,
+ (unsigned int) is_func_decl,
+ (duk_heaphdr *) env));
DUK_ASSERT(thr != NULL);
DUK_ASSERT(env != NULL);
@@ -80041,7 +85522,7 @@ duk_bool_t duk__declvar_helper(duk_hthread *thr,
* environment target object.
*/
- parents = 0; /* just check 'env' */
+ parents = 0; /* just check 'env' */
if (duk__get_identifier_reference(thr, env, name, NULL, parents, &ref)) {
duk_int_t e_idx;
duk_int_t h_idx;
@@ -80056,7 +85537,7 @@ duk_bool_t duk__declvar_helper(duk_hthread *thr,
if (!(is_func_decl && env == thr->builtins[DUK_BIDX_GLOBAL_ENV])) {
DUK_DDD(DUK_DDDPRINT("re-declare a binding, ignoring"));
- return 1; /* 1 -> needs a PUTVAR */
+ return 1; /* 1 -> needs a PUTVAR */
}
/*
@@ -80086,13 +85567,13 @@ duk_bool_t duk__declvar_helper(duk_hthread *thr,
* where the property was found (see duk__get_identifier_reference()).
*/
DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(holder) == DUK_HOBJECT_CLASS_GLOBAL);
- DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(holder)); /* global object doesn't have array part */
+ DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(holder)); /* global object doesn't have array part */
/* XXX: use a helper for prototype traversal; no loop check here */
/* must be found: was found earlier, and cannot be inherited */
for (;;) {
DUK_ASSERT(holder != NULL);
- if (duk_hobject_find_existing_entry(thr->heap, holder, name, &e_idx, &h_idx)) {
+ if (duk_hobject_find_entry(thr->heap, holder, name, &e_idx, &h_idx)) {
DUK_ASSERT(e_idx >= 0);
break;
}
@@ -80119,8 +85600,7 @@ duk_bool_t duk__declvar_helper(duk_hthread *thr,
"accessor -> reject"));
goto fail_existing_attributes;
}
- if (!((flags & DUK_PROPDESC_FLAG_WRITABLE) &&
- (flags & DUK_PROPDESC_FLAG_ENUMERABLE))) {
+ if (!((flags & DUK_PROPDESC_FLAG_WRITABLE) && (flags & DUK_PROPDESC_FLAG_ENUMERABLE))) {
DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
"plain property which is not writable and "
"enumerable -> reject"));
@@ -80189,10 +85669,10 @@ duk_bool_t duk__declvar_helper(duk_hthread *thr,
*/
if (DUK_HOBJECT_IS_DECENV(env)) {
- DUK_ASSERT_HDECENV_VALID((duk_hdecenv *) env);
+ DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) env);
holder = env;
} else {
- DUK_ASSERT_HOBJENV_VALID((duk_hobjenv *) env);
+ DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) env);
holder = ((duk_hobjenv *) env)->target;
DUK_ASSERT(holder != NULL);
}
@@ -80215,15 +85695,15 @@ duk_bool_t duk__declvar_helper(duk_hthread *thr,
duk_push_hobject(thr, holder);
duk_push_hstring(thr, name);
duk_push_tval(thr, val);
- duk_xdef_prop(thr, -3, prop_flags); /* [holder name val] -> [holder] */
+ duk_xdef_prop(thr, -3, prop_flags); /* [holder name val] -> [holder] */
duk_pop_unsafe(thr);
return 0;
- fail_existing_attributes:
- fail_not_extensible:
+fail_existing_attributes:
+fail_not_extensible:
DUK_ERROR_TYPE(thr, "declaration failed");
- return 0;
+ DUK_WO_NORETURN(return 0;);
}
DUK_INTERNAL
@@ -80268,7 +85748,7 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
* Lexer for source files, ToNumber() string conversions, RegExp expressions,
* and JSON.
*
- * Provides a stream of Ecmascript tokens from an UTF-8/CESU-8 buffer. The
+ * Provides a stream of ECMAScript tokens from an UTF-8/CESU-8 buffer. The
* caller can also rewind the token stream into a certain position which is
* needed by the compiler part for multi-pass scanning. Tokens are
* represented as duk_token structures, and contain line number information.
@@ -80291,14 +85771,14 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
*
* Token parsing supports the full range of Unicode characters as described
* in the E5 specification. Parsing has been optimized for ASCII characters
- * because ordinary Ecmascript code consists almost entirely of ASCII
+ * because ordinary ECMAScript code consists almost entirely of ASCII
* characters. Matching of complex Unicode codepoint sets (such as in the
* IdentifierStart and IdentifierPart productions) is optimized for size,
* and is done using a linear scan of a bit-packed list of ranges. This is
* very slow, but should never be entered unless the source code actually
* contains Unicode characters.
*
- * Ecmascript tokenization is partially context sensitive. First,
+ * ECMAScript tokenization is partially context sensitive. First,
* additional future reserved words are recognized in strict mode (see E5
* Section 7.6.1.2). Second, a forward slash character ('/') can be
* recognized either as starting a RegExp literal or as a division operator,
@@ -80342,34 +85822,34 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
* Various defines and file specific helper macros
*/
-#define DUK__MAX_RE_DECESC_DIGITS 9
-#define DUK__MAX_RE_QUANT_DIGITS 9 /* Does not allow e.g. 2**31-1, but one more would allow overflows of u32. */
+#define DUK__MAX_RE_DECESC_DIGITS 9
+#define DUK__MAX_RE_QUANT_DIGITS 9 /* Does not allow e.g. 2**31-1, but one more would allow overflows of u32. */
/* whether to use macros or helper function depends on call count */
-#define DUK__ISDIGIT(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_9)
-#define DUK__ISHEXDIGIT(x) duk__is_hex_digit((x))
-#define DUK__ISOCTDIGIT(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_7)
-#define DUK__ISDIGIT03(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_3)
-#define DUK__ISDIGIT47(x) ((x) >= DUK_ASC_4 && (x) <= DUK_ASC_7)
+#define DUK__ISDIGIT(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_9)
+#define DUK__ISHEXDIGIT(x) duk__is_hex_digit((x))
+#define DUK__ISOCTDIGIT(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_7)
+#define DUK__ISDIGIT03(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_3)
+#define DUK__ISDIGIT47(x) ((x) >= DUK_ASC_4 && (x) <= DUK_ASC_7)
/* lexer character window helpers */
-#define DUK__LOOKUP(lex_ctx,idx) ((lex_ctx)->window[(idx)].codepoint)
-#define DUK__ADVANCECHARS(lex_ctx,count) duk__advance_chars((lex_ctx), (count))
-#define DUK__ADVANCEBYTES(lex_ctx,count) duk__advance_bytes((lex_ctx), (count))
+#define DUK__LOOKUP(lex_ctx, idx) ((lex_ctx)->window[(idx)].codepoint)
+#define DUK__ADVANCECHARS(lex_ctx, count) duk__advance_chars((lex_ctx), (count))
+#define DUK__ADVANCEBYTES(lex_ctx, count) duk__advance_bytes((lex_ctx), (count))
#define DUK__INITBUFFER(lex_ctx) duk__initbuffer((lex_ctx))
-#define DUK__APPENDBUFFER(lex_ctx,x) duk__appendbuffer((lex_ctx), (duk_codepoint_t) (x))
-#define DUK__APPENDBUFFER_ASCII(lex_ctx,x) duk__appendbuffer_ascii((lex_ctx), (duk_codepoint_t) (x))
+#define DUK__APPENDBUFFER(lex_ctx, x) duk__appendbuffer((lex_ctx), (duk_codepoint_t) (x))
+#define DUK__APPENDBUFFER_ASCII(lex_ctx, x) duk__appendbuffer_ascii((lex_ctx), (duk_codepoint_t) (x))
/* lookup shorthands (note: assume context variable is named 'lex_ctx') */
-#define DUK__L0() DUK__LOOKUP(lex_ctx, 0)
-#define DUK__L1() DUK__LOOKUP(lex_ctx, 1)
-#define DUK__L2() DUK__LOOKUP(lex_ctx, 2)
-#define DUK__L3() DUK__LOOKUP(lex_ctx, 3)
-#define DUK__L4() DUK__LOOKUP(lex_ctx, 4)
-#define DUK__L5() DUK__LOOKUP(lex_ctx, 5)
+#define DUK__L0() DUK__LOOKUP(lex_ctx, 0)
+#define DUK__L1() DUK__LOOKUP(lex_ctx, 1)
+#define DUK__L2() DUK__LOOKUP(lex_ctx, 2)
+#define DUK__L3() DUK__LOOKUP(lex_ctx, 3)
+#define DUK__L4() DUK__LOOKUP(lex_ctx, 4)
+#define DUK__L5() DUK__LOOKUP(lex_ctx, 5)
/* packed advance/token number macro used by multiple functions */
-#define DUK__ADVTOK(advbytes,tok) ((((advbytes) * sizeof(duk_lexer_codepoint)) << 8) + (tok))
+#define DUK__ADVTOK(advbytes, tok) ((((advbytes) * sizeof(duk_lexer_codepoint)) << 8) + (tok))
/*
* Advance lookup window by N characters, filling in new characters as
@@ -80395,7 +85875,7 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
*
* * In particular, surrogate pairs are allowed and not combined, which
* allows source files to represent all SourceCharacters with CESU-8.
- * Broken surrogate pairs are allowed, as Ecmascript does not mandate
+ * Broken surrogate pairs are allowed, as ECMAScript does not mandate
* their validation.
*
* * Allow non-shortest UTF-8 encodings.
@@ -80403,20 +85883,20 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
* Leniency here causes few security concerns because all character data is
* decoded into Unicode codepoints before lexer processing, and is then
* re-encoded into CESU-8. The source can be parsed as strict UTF-8 with
- * a compiler option. However, Ecmascript source characters include -all-
+ * a compiler option. However, ECMAScript source characters include -all-
* 16-bit unsigned integer codepoints, so leniency seems to be appropriate.
*
* Note that codepoints above the BMP are not strictly SourceCharacters,
* but the lexer still accepts them as such. Before ending up in a string
* or an identifier name, codepoints above BMP are converted into surrogate
* pairs and then CESU-8 encoded, resulting in 16-bit Unicode data as
- * expected by Ecmascript.
+ * expected by ECMAScript.
*
* An alternative approach to dealing with invalid or partial sequences
* would be to skip them and replace them with e.g. the Unicode replacement
* character U+FFFD. This has limited utility because a replacement character
* will most likely cause a parse error, unless it occurs inside a string.
- * Further, Ecmascript source is typically pure ASCII.
+ * Further, ECMAScript source is typically pure ASCII.
*
* See:
*
@@ -80479,10 +85959,9 @@ DUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t s
/* Fast path. */
if (DUK_LIKELY(x < 0x80UL)) {
- DUK_ASSERT(x != 0x2028UL && x != 0x2029UL); /* not LS/PS */
+ DUK_ASSERT(x != 0x2028UL && x != 0x2029UL); /* not LS/PS */
if (DUK_UNLIKELY(x <= 0x000dUL)) {
- if ((x == 0x000aUL) ||
- ((x == 0x000dUL) && (p >= p_end || *p != 0x000aUL))) {
+ if ((x == 0x000aUL) || ((x == 0x000dUL) && (p >= p_end || *p != 0x000aUL))) {
/* lookup for 0x000a above assumes shortest encoding now */
/* E5 Section 7.3, treat the following as newlines:
@@ -80573,37 +86052,37 @@ DUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t s
lex_ctx->input_line = input_line;
return;
- error_clipped: /* clipped codepoint */
- error_encoding: /* invalid codepoint encoding or codepoint */
+error_clipped: /* clipped codepoint */
+error_encoding: /* invalid codepoint encoding or codepoint */
lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
lex_ctx->input_line = input_line;
DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_SOURCE_DECODE_FAILED);
+ DUK_WO_NORETURN(return;);
}
DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
duk_small_uint_t used_bytes, avail_bytes;
- DUK_ASSERT_DISABLE(count_bytes >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(count_bytes >= 0); /* unsigned */
DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
DUK_ASSERT(lex_ctx->window >= lex_ctx->buffer);
DUK_ASSERT(lex_ctx->window < lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE);
- DUK_ASSERT((duk_uint8_t *) lex_ctx->window + count_bytes <= (duk_uint8_t *) lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint));
+ DUK_ASSERT((duk_uint8_t *) lex_ctx->window + count_bytes <=
+ (duk_uint8_t *) lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint));
/* Zero 'count' is also allowed to make call sites easier.
* Arithmetic in bytes generates better code in GCC.
*/
- lex_ctx->window = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->window + count_bytes); /* avoid multiply */
+ lex_ctx->window = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->window + count_bytes); /* avoid multiply */
used_bytes = (duk_small_uint_t) ((duk_uint8_t *) lex_ctx->window - (duk_uint8_t *) lex_ctx->buffer);
avail_bytes = DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint) - used_bytes;
if (avail_bytes < (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint))) {
/* Not enough data to provide a full window, so "scroll" window to
* start of buffer and fill up the rest.
*/
- DUK_MEMMOVE((void *) lex_ctx->buffer,
- (const void *) lex_ctx->window,
- (size_t) avail_bytes);
+ duk_memmove((void *) lex_ctx->buffer, (const void *) lex_ctx->window, (size_t) avail_bytes);
lex_ctx->window = lex_ctx->buffer;
duk__fill_lexer_buffer(lex_ctx, avail_bytes);
}
@@ -80613,7 +86092,7 @@ DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
lex_ctx->window = lex_ctx->buffer;
duk__fill_lexer_buffer(lex_ctx, 0);
}
-#else /* DUK_USE_LEXER_SLIDING_WINDOW */
+#else /* DUK_USE_LEXER_SLIDING_WINDOW */
DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {
duk_ucodepoint_t x;
duk_small_uint_t len;
@@ -80643,11 +86122,10 @@ DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {
/* input offset tracking */
lex_ctx->input_offset++;
- DUK_ASSERT(x != 0x2028UL && x != 0x2029UL); /* not LS/PS */
+ DUK_ASSERT(x != 0x2028UL && x != 0x2029UL); /* not LS/PS */
if (DUK_UNLIKELY(x <= 0x000dUL)) {
- if ((x == 0x000aUL) ||
- ((x == 0x000dUL) && (lex_ctx->input_offset >= lex_ctx->input_length ||
- lex_ctx->input[lex_ctx->input_offset] != 0x000aUL))) {
+ if ((x == 0x000aUL) || ((x == 0x000dUL) && (lex_ctx->input_offset >= lex_ctx->input_length ||
+ lex_ctx->input[lex_ctx->input_offset] != 0x000aUL))) {
/* lookup for 0x000a above assumes shortest encoding now */
/* E5 Section 7.3, treat the following as newlines:
@@ -80736,25 +86214,23 @@ DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {
return (duk_codepoint_t) x;
- error_clipped: /* clipped codepoint */
- error_encoding: /* invalid codepoint encoding or codepoint */
+error_clipped: /* clipped codepoint */
+error_encoding: /* invalid codepoint encoding or codepoint */
DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_SOURCE_DECODE_FAILED);
- return 0;
+ DUK_WO_NORETURN(return 0;);
}
DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
duk_small_uint_t keep_bytes;
duk_lexer_codepoint *cp, *cp_end;
- DUK_ASSERT_DISABLE(count_bytes >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(count_bytes >= 0); /* unsigned */
DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
/* Zero 'count' is also allowed to make call sites easier. */
keep_bytes = DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint) - count_bytes;
- DUK_MEMMOVE((void *) lex_ctx->window,
- (const void *) ((duk_uint8_t *) lex_ctx->window + count_bytes),
- (size_t) keep_bytes);
+ duk_memmove((void *) lex_ctx->window, (const void *) ((duk_uint8_t *) lex_ctx->window + count_bytes), (size_t) keep_bytes);
cp = (duk_lexer_codepoint *) ((duk_uint8_t *) lex_ctx->window + keep_bytes);
cp_end = lex_ctx->window + DUK_LEXER_WINDOW_SIZE;
@@ -80767,9 +86243,9 @@ DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count
DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
/* Call with count == DUK_LEXER_WINDOW_SIZE to fill buffer initially. */
- duk__advance_bytes(lex_ctx, DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)); /* fill window */
+ duk__advance_bytes(lex_ctx, DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)); /* fill window */
}
-#endif /* DUK_USE_LEXER_SLIDING_WINDOW */
+#endif /* DUK_USE_LEXER_SLIDING_WINDOW */
DUK_LOCAL void duk__advance_chars(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_chars) {
duk__advance_bytes(lex_ctx, count_chars * sizeof(duk_lexer_codepoint));
@@ -80841,7 +86317,7 @@ DUK_LOCAL duk_hstring *duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valst
DUK_INTERNAL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx) {
DUK_ASSERT(lex_ctx != NULL);
- DUK_MEMZERO(lex_ctx, sizeof(*lex_ctx));
+ duk_memzero(lex_ctx, sizeof(*lex_ctx));
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
lex_ctx->window = NULL;
@@ -80862,7 +86338,7 @@ DUK_INTERNAL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt
}
DUK_INTERNAL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
- DUK_ASSERT_DISABLE(pt->offset >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(pt->offset >= 0); /* unsigned */
DUK_ASSERT(pt->line >= 1);
lex_ctx->input_offset = pt->offset;
lex_ctx->input_line = pt->line;
@@ -80896,8 +86372,7 @@ DUK_LOCAL duk_codepoint_t duk__hexval_validate(duk_codepoint_t x) {
DUK_LOCAL duk_codepoint_t duk__hexval(duk_codepoint_t x) {
duk_codepoint_t ret;
- DUK_ASSERT((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
- (x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_F) ||
+ DUK_ASSERT((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_F) ||
(x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_F));
ret = duk__hexval_validate(x);
DUK_ASSERT(ret >= 0 && ret <= 15);
@@ -80916,12 +86391,12 @@ DUK_LOCAL duk_bool_t duk__is_hex_digit(duk_codepoint_t x) {
* source and RegExp parsing.
*/
DUK_LOCAL duk_codepoint_t duk__lexer_parse_escape(duk_lexer_ctx *lex_ctx, duk_bool_t allow_es6) {
- duk_small_int_t digits; /* Initial value 2 or 4 for fixed length escapes, 0 for ES2015 \u{H+}. */
+ duk_small_int_t digits; /* Initial value 2 or 4 for fixed length escapes, 0 for ES2015 \u{H+}. */
duk_codepoint_t escval;
duk_codepoint_t x;
duk_small_uint_t adv;
- DUK_ASSERT(DUK__L0() == DUK_ASC_BACKSLASH); /* caller responsibilities */
+ DUK_ASSERT(DUK__L0() == DUK_ASC_BACKSLASH); /* caller responsibilities */
DUK_ASSERT(DUK__L1() == DUK_ASC_LC_X || DUK__L1() == DUK_ASC_LC_U);
DUK_UNREF(allow_es6);
@@ -80995,17 +86470,18 @@ DUK_LOCAL duk_codepoint_t duk__lexer_parse_escape(duk_lexer_ctx *lex_ctx, duk_bo
} else {
goto fail_escape;
}
- digits = -1; /* Indicate we have at least one digit. */
-#else /* DUK_USE_ES6_UNICODE_ESCAPE */
- DUK_ASSERT(0); /* Never happens if \u{H+} support disabled. */
-#endif /* DUK_USE_ES6_UNICODE_ESCAPE */
+ digits = -1; /* Indicate we have at least one digit. */
+#else /* DUK_USE_ES6_UNICODE_ESCAPE */
+ DUK_ASSERT(0); /* Never happens if \u{H+} support disabled. */
+#endif /* DUK_USE_ES6_UNICODE_ESCAPE */
}
}
return escval;
- fail_escape:
+fail_escape:
DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
+ DUK_WO_NORETURN(return 0;);
}
/* Parse legacy octal escape of the form \N{1,3}, e.g. \0, \5, \0377. Maximum
@@ -81013,7 +86489,9 @@ DUK_LOCAL duk_codepoint_t duk__lexer_parse_escape(duk_lexer_ctx *lex_ctx, duk_bo
* RegExp octal escape parsing. Window[0] must be the slash '\' and the first
* digit must already be validated to be in [0-9] by the caller.
*/
-DUK_LOCAL duk_codepoint_t duk__lexer_parse_legacy_octal(duk_lexer_ctx *lex_ctx, duk_small_uint_t *out_adv, duk_bool_t reject_annex_b) {
+DUK_LOCAL duk_codepoint_t duk__lexer_parse_legacy_octal(duk_lexer_ctx *lex_ctx,
+ duk_small_uint_t *out_adv,
+ duk_bool_t reject_annex_b) {
duk_codepoint_t cp;
duk_small_uint_t lookup_idx;
duk_small_uint_t adv;
@@ -81048,7 +86526,7 @@ DUK_LOCAL duk_codepoint_t duk__lexer_parse_legacy_octal(duk_lexer_ctx *lex_ctx,
DUK_DDD(DUK_DDDPRINT("\\8 or \\9 -> treat as literal, accept in strict mode too"));
DUK_ASSERT(tmp == DUK_ASC_8 || tmp == DUK_ASC_9);
cp = tmp;
- adv++; /* correction to above, eat offending character */
+ adv++; /* correction to above, eat offending character */
} else if (lookup_idx == 2 && cp == 0) {
/* Note: 'foo\0bar' is OK in strict mode, but 'foo\00bar' is not.
* It won't be interpreted as 'foo\u{0}0bar' but as a SyntaxError.
@@ -81072,18 +86550,21 @@ DUK_LOCAL duk_codepoint_t duk__lexer_parse_legacy_octal(duk_lexer_ctx *lex_ctx,
}
/* XXX: move strict mode to lex_ctx? */
-DUK_LOCAL void duk__lexer_parse_string_literal(duk_lexer_ctx *lex_ctx, duk_token *out_token, duk_small_int_t quote, duk_bool_t strict_mode) {
+DUK_LOCAL void duk__lexer_parse_string_literal(duk_lexer_ctx *lex_ctx,
+ duk_token *out_token,
+ duk_small_int_t quote,
+ duk_bool_t strict_mode) {
duk_small_uint_t adv;
- for (adv = 1 /* initial quote */ ;;) {
+ for (adv = 1 /* initial quote */;;) {
duk_codepoint_t x;
- DUK__ADVANCECHARS(lex_ctx, adv); /* eat opening quote on first loop */
+ DUK__ADVANCECHARS(lex_ctx, adv); /* eat opening quote on first loop */
x = DUK__L0();
adv = 1;
if (x == quote) {
- DUK__ADVANCECHARS(lex_ctx, 1); /* eat closing quote */
+ DUK__ADVANCECHARS(lex_ctx, 1); /* eat closing quote */
break;
} else if (x == '\\') {
/* DUK__L0 -> '\' char
@@ -81094,7 +86575,7 @@ DUK_LOCAL void duk__lexer_parse_string_literal(duk_lexer_ctx *lex_ctx, duk_token
x = DUK__L1();
/* How much to advance before next loop. */
- adv = 2; /* note: long live range */
+ adv = 2; /* note: long live range */
switch (x) {
case '\'':
@@ -81137,7 +86618,7 @@ DUK_LOCAL void duk__lexer_parse_string_literal(duk_lexer_ctx *lex_ctx, duk_token
/* line continuation */
if (x == 0x000d && DUK__L2() == 0x000a) {
/* CR LF again a special case */
- adv = 3; /* line terminator, CR, LF */
+ adv = 3; /* line terminator, CR, LF */
}
} else if (DUK__ISDIGIT(x)) {
/*
@@ -81166,8 +86647,8 @@ DUK_LOCAL void duk__lexer_parse_string_literal(duk_lexer_ctx *lex_ctx, duk_token
/* escaped NonEscapeCharacter */
DUK__APPENDBUFFER(lex_ctx, x);
}
- } /* end default clause */
- } /* end switch */
+ } /* end default clause */
+ } /* end switch */
/* Shared handling for single codepoint escapes. */
if (emitcp >= 0) {
@@ -81200,13 +86681,13 @@ DUK_LOCAL void duk__lexer_parse_string_literal(duk_lexer_ctx *lex_ctx, duk_token
return;
- fail_escape:
+fail_escape:
DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
- return;
+ DUK_WO_NORETURN(return;);
- fail_unterminated:
+fail_unterminated:
DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_STRING);
- return;
+ DUK_WO_NORETURN(return;);
}
/* Skip to end-of-line (or end-of-file), used for single line comments. */
@@ -81223,7 +86704,7 @@ DUK_LOCAL void duk__lexer_skip_to_endofline(duk_lexer_ctx *lex_ctx) {
}
/*
- * Parse Ecmascript source InputElementDiv or InputElementRegExp
+ * Parse ECMAScript source InputElementDiv or InputElementRegExp
* (E5 Section 7), skipping whitespace, comments, and line terminators.
*
* Possible results are:
@@ -81250,13 +86731,13 @@ DUK_LOCAL void duk__lexer_skip_to_endofline(duk_lexer_ctx *lex_ctx) {
* lookup window to quickly determine which production is the -longest-
* matching one, and then parse that. The top-level if-else clauses
* match the first character, and the code blocks for each clause
- * handle -all- alternatives for that first character. Ecmascript
+ * handle -all- alternatives for that first character. ECMAScript
* specification uses the "longest match wins" semantics, so the order
* of the if-clauses matters.
*
* Misc notes:
*
- * * Ecmascript numeric literals do not accept a sign character.
+ * * ECMAScript numeric literals do not accept a sign character.
* Consequently e.g. "-1.0" is parsed as two tokens: a negative
* sign and a positive numeric literal. The compiler performs
* the negation during compilation, so this has no adverse impact.
@@ -81291,19 +86772,19 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
duk_token *out_token,
duk_bool_t strict_mode,
duk_bool_t regexp_mode) {
- duk_codepoint_t x; /* temporary, must be signed and 32-bit to hold Unicode code points */
+ duk_codepoint_t x; /* temporary, must be signed and 32-bit to hold Unicode code points */
duk_small_uint_t advtok = 0; /* (advance << 8) + token_type, updated at function end,
* init is unnecessary but suppresses "may be used uninitialized" warnings.
*/
- duk_bool_t got_lineterm = 0; /* got lineterm preceding non-whitespace, non-lineterm token */
+ duk_bool_t got_lineterm = 0; /* got lineterm preceding non-whitespace, non-lineterm token */
if (++lex_ctx->token_count >= lex_ctx->token_limit) {
goto fail_token_limit;
}
out_token->t = DUK_TOK_EOF;
- out_token->t_nores = DUK_TOK_INVALID; /* marker: copy t if not changed */
-#if 0 /* not necessary to init, disabled for faster parsing */
+ out_token->t_nores = DUK_TOK_INVALID; /* marker: copy t if not changed */
+#if 0 /* not necessary to init, disabled for faster parsing */
out_token->num = DUK_DOUBLE_NAN;
out_token->str1 = NULL;
out_token->str2 = NULL;
@@ -81343,35 +86824,34 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
* in the clauses, so it's not trivial to convert to a switch.
*/
- restart_lineupdate:
+restart_lineupdate:
out_token->start_line = lex_ctx->window[0].line;
- restart:
+restart:
out_token->start_offset = lex_ctx->window[0].offset;
x = DUK__L0();
switch (x) {
case DUK_ASC_SPACE:
- case DUK_ASC_HT: /* fast paths for space and tab */
+ case DUK_ASC_HT: /* fast paths for space and tab */
DUK__ADVANCECHARS(lex_ctx, 1);
goto restart;
- case DUK_ASC_LF: /* LF line terminator; CR LF and Unicode lineterms are handled in slow path */
+ case DUK_ASC_LF: /* LF line terminator; CR LF and Unicode lineterms are handled in slow path */
DUK__ADVANCECHARS(lex_ctx, 1);
got_lineterm = 1;
goto restart_lineupdate;
#if defined(DUK_USE_SHEBANG_COMMENTS)
- case DUK_ASC_HASH: /* '#' */
- if (DUK__L1() == DUK_ASC_EXCLAMATION && lex_ctx->window[0].offset == 0 &&
- (lex_ctx->flags & DUK_COMPILE_SHEBANG)) {
+ case DUK_ASC_HASH: /* '#' */
+ if (DUK__L1() == DUK_ASC_EXCLAMATION && lex_ctx->window[0].offset == 0 && (lex_ctx->flags & DUK_COMPILE_SHEBANG)) {
/* "Shebang" comment ('#! ...') on first line. */
/* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but not necessary */
duk__lexer_skip_to_endofline(lex_ctx);
- goto restart; /* line terminator will be handled on next round */
+ goto restart; /* line terminator will be handled on next round */
}
goto fail_token;
-#endif /* DUK_USE_SHEBANG_COMMENTS */
- case DUK_ASC_SLASH: /* '/' */
+#endif /* DUK_USE_SHEBANG_COMMENTS */
+ case DUK_ASC_SLASH: /* '/' */
if (DUK__L1() == DUK_ASC_SLASH) {
/*
* E5 Section 7.4, allow SourceCharacter (which is any 16-bit
@@ -81380,7 +86860,7 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
/* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but not necessary */
duk__lexer_skip_to_endofline(lex_ctx);
- goto restart; /* line terminator will be handled on next round */
+ goto restart; /* line terminator will be handled on next round */
} else if (DUK__L1() == DUK_ASC_STAR) {
/*
* E5 Section 7.4. If the multi-line comment contains a newline,
@@ -81464,19 +86944,19 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
/* first, parse regexp body roughly */
- duk_small_int_t state = 0; /* 0=base, 1=esc, 2=class, 3=class+esc */
+ duk_small_int_t state = 0; /* 0=base, 1=esc, 2=class, 3=class+esc */
DUK__INITBUFFER(lex_ctx);
for (;;) {
- DUK__ADVANCECHARS(lex_ctx, 1); /* skip opening slash on first loop */
+ DUK__ADVANCECHARS(lex_ctx, 1); /* skip opening slash on first loop */
x = DUK__L0();
if (x < 0 || duk_unicode_is_line_terminator(x)) {
goto fail_unterm_regexp;
}
- x = DUK__L0(); /* re-read to avoid spill / fetch */
+ x = DUK__L0(); /* re-read to avoid spill / fetch */
if (state == 0) {
if (x == DUK_ASC_SLASH) {
- DUK__ADVANCECHARS(lex_ctx, 1); /* eat closing slash */
+ DUK__ADVANCECHARS(lex_ctx, 1); /* eat closing slash */
break;
} else if (x == DUK_ASC_BACKSLASH) {
state = 1;
@@ -81506,20 +86986,20 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
if (!duk_unicode_is_identifier_part(x)) {
break;
}
- x = DUK__L0(); /* re-read to avoid spill / fetch */
+ x = DUK__L0(); /* re-read to avoid spill / fetch */
DUK__APPENDBUFFER(lex_ctx, x);
DUK__ADVANCECHARS(lex_ctx, 1);
}
out_token->str2 = duk__internbuffer(lex_ctx, lex_ctx->slot2_idx);
- DUK__INITBUFFER(lex_ctx); /* free some memory */
+ DUK__INITBUFFER(lex_ctx); /* free some memory */
/* validation of the regexp is caller's responsibility */
advtok = DUK__ADVTOK(0, DUK_TOK_REGEXP);
-#else /* DUK_USE_REGEXP_SUPPORT */
+#else /* DUK_USE_REGEXP_SUPPORT */
goto fail_regexp_support;
-#endif /* DUK_USE_REGEXP_SUPPORT */
+#endif /* DUK_USE_REGEXP_SUPPORT */
} else if (DUK__L1() == DUK_ASC_EQUALS) {
/* "/=" and not in regexp mode */
advtok = DUK__ADVTOK(2, DUK_TOK_DIV_EQ);
@@ -81528,25 +87008,25 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
advtok = DUK__ADVTOK(1, DUK_TOK_DIV);
}
break;
- case DUK_ASC_LCURLY: /* '{' */
+ case DUK_ASC_LCURLY: /* '{' */
advtok = DUK__ADVTOK(1, DUK_TOK_LCURLY);
break;
- case DUK_ASC_RCURLY: /* '}' */
+ case DUK_ASC_RCURLY: /* '}' */
advtok = DUK__ADVTOK(1, DUK_TOK_RCURLY);
break;
- case DUK_ASC_LPAREN: /* '(' */
+ case DUK_ASC_LPAREN: /* '(' */
advtok = DUK__ADVTOK(1, DUK_TOK_LPAREN);
break;
- case DUK_ASC_RPAREN: /* ')' */
+ case DUK_ASC_RPAREN: /* ')' */
advtok = DUK__ADVTOK(1, DUK_TOK_RPAREN);
break;
- case DUK_ASC_LBRACKET: /* '[' */
+ case DUK_ASC_LBRACKET: /* '[' */
advtok = DUK__ADVTOK(1, DUK_TOK_LBRACKET);
break;
- case DUK_ASC_RBRACKET: /* ']' */
+ case DUK_ASC_RBRACKET: /* ']' */
advtok = DUK__ADVTOK(1, DUK_TOK_RBRACKET);
break;
- case DUK_ASC_PERIOD: /* '.' */
+ case DUK_ASC_PERIOD: /* '.' */
if (DUK__ISDIGIT(DUK__L1())) {
/* Period followed by a digit can only start DecimalLiteral
* (handled in slow path). We could jump straight into the
@@ -81557,13 +87037,13 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
}
advtok = DUK__ADVTOK(1, DUK_TOK_PERIOD);
break;
- case DUK_ASC_SEMICOLON: /* ';' */
+ case DUK_ASC_SEMICOLON: /* ';' */
advtok = DUK__ADVTOK(1, DUK_TOK_SEMICOLON);
break;
- case DUK_ASC_COMMA: /* ',' */
+ case DUK_ASC_COMMA: /* ',' */
advtok = DUK__ADVTOK(1, DUK_TOK_COMMA);
break;
- case DUK_ASC_LANGLE: /* '<' */
+ case DUK_ASC_LANGLE: /* '<' */
#if defined(DUK_USE_HTML_COMMENTS)
if (DUK__L1() == DUK_ASC_EXCLAMATION && DUK__L2() == DUK_ASC_MINUS && DUK__L3() == DUK_ASC_MINUS) {
/*
@@ -81572,11 +87052,10 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
/* DUK__ADVANCECHARS(lex_ctx, 4) would be correct here, but not necessary */
duk__lexer_skip_to_endofline(lex_ctx);
- goto restart; /* line terminator will be handled on next round */
- }
- else
-#endif /* DUK_USE_HTML_COMMENTS */
- if (DUK__L1() == DUK_ASC_LANGLE && DUK__L2() == DUK_ASC_EQUALS) {
+ goto restart; /* line terminator will be handled on next round */
+ } else
+#endif /* DUK_USE_HTML_COMMENTS */
+ if (DUK__L1() == DUK_ASC_LANGLE && DUK__L2() == DUK_ASC_EQUALS) {
advtok = DUK__ADVTOK(3, DUK_TOK_ALSHIFT_EQ);
} else if (DUK__L1() == DUK_ASC_EQUALS) {
advtok = DUK__ADVTOK(2, DUK_TOK_LE);
@@ -81586,7 +87065,7 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
advtok = DUK__ADVTOK(1, DUK_TOK_LT);
}
break;
- case DUK_ASC_RANGLE: /* '>' */
+ case DUK_ASC_RANGLE: /* '>' */
if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE && DUK__L3() == DUK_ASC_EQUALS) {
advtok = DUK__ADVTOK(4, DUK_TOK_RSHIFT_EQ);
} else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE) {
@@ -81601,7 +87080,7 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
advtok = DUK__ADVTOK(1, DUK_TOK_GT);
}
break;
- case DUK_ASC_EQUALS: /* '=' */
+ case DUK_ASC_EQUALS: /* '=' */
if (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {
advtok = DUK__ADVTOK(3, DUK_TOK_SEQ);
} else if (DUK__L1() == DUK_ASC_EQUALS) {
@@ -81610,7 +87089,7 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
advtok = DUK__ADVTOK(1, DUK_TOK_EQUALSIGN);
}
break;
- case DUK_ASC_EXCLAMATION: /* '!' */
+ case DUK_ASC_EXCLAMATION: /* '!' */
if (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {
advtok = DUK__ADVTOK(3, DUK_TOK_SNEQ);
} else if (DUK__L1() == DUK_ASC_EQUALS) {
@@ -81619,7 +87098,7 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
advtok = DUK__ADVTOK(1, DUK_TOK_LNOT);
}
break;
- case DUK_ASC_PLUS: /* '+' */
+ case DUK_ASC_PLUS: /* '+' */
if (DUK__L1() == DUK_ASC_PLUS) {
advtok = DUK__ADVTOK(2, DUK_TOK_INCREMENT);
} else if (DUK__L1() == DUK_ASC_EQUALS) {
@@ -81628,7 +87107,7 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
advtok = DUK__ADVTOK(1, DUK_TOK_ADD);
}
break;
- case DUK_ASC_MINUS: /* '-' */
+ case DUK_ASC_MINUS: /* '-' */
#if defined(DUK_USE_HTML_COMMENTS)
if (got_lineterm && DUK__L1() == DUK_ASC_MINUS && DUK__L2() == DUK_ASC_RANGLE) {
/*
@@ -81645,10 +87124,10 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
/* DUK__ADVANCECHARS(lex_ctx, 3) would be correct here, but not necessary */
duk__lexer_skip_to_endofline(lex_ctx);
- goto restart; /* line terminator will be handled on next round */
+ goto restart; /* line terminator will be handled on next round */
} else
-#endif /* DUK_USE_HTML_COMMENTS */
- if (DUK__L1() == DUK_ASC_MINUS) {
+#endif /* DUK_USE_HTML_COMMENTS */
+ if (DUK__L1() == DUK_ASC_MINUS) {
advtok = DUK__ADVTOK(2, DUK_TOK_DECREMENT);
} else if (DUK__L1() == DUK_ASC_EQUALS) {
advtok = DUK__ADVTOK(2, DUK_TOK_SUB_EQ);
@@ -81656,7 +87135,7 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
advtok = DUK__ADVTOK(1, DUK_TOK_SUB);
}
break;
- case DUK_ASC_STAR: /* '*' */
+ case DUK_ASC_STAR: /* '*' */
#if defined(DUK_USE_ES7_EXP_OPERATOR)
if (DUK__L1() == DUK_ASC_STAR && DUK__L2() == DUK_ASC_EQUALS) {
advtok = DUK__ADVTOK(3, DUK_TOK_EXP_EQ);
@@ -81664,20 +87143,20 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
advtok = DUK__ADVTOK(2, DUK_TOK_EXP);
} else
#endif
- if (DUK__L1() == DUK_ASC_EQUALS) {
+ if (DUK__L1() == DUK_ASC_EQUALS) {
advtok = DUK__ADVTOK(2, DUK_TOK_MUL_EQ);
} else {
advtok = DUK__ADVTOK(1, DUK_TOK_MUL);
}
break;
- case DUK_ASC_PERCENT: /* '%' */
+ case DUK_ASC_PERCENT: /* '%' */
if (DUK__L1() == DUK_ASC_EQUALS) {
advtok = DUK__ADVTOK(2, DUK_TOK_MOD_EQ);
} else {
advtok = DUK__ADVTOK(1, DUK_TOK_MOD);
}
break;
- case DUK_ASC_AMP: /* '&' */
+ case DUK_ASC_AMP: /* '&' */
if (DUK__L1() == DUK_ASC_AMP) {
advtok = DUK__ADVTOK(2, DUK_TOK_LAND);
} else if (DUK__L1() == DUK_ASC_EQUALS) {
@@ -81686,7 +87165,7 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
advtok = DUK__ADVTOK(1, DUK_TOK_BAND);
}
break;
- case DUK_ASC_PIPE: /* '|' */
+ case DUK_ASC_PIPE: /* '|' */
if (DUK__L1() == DUK_ASC_PIPE) {
advtok = DUK__ADVTOK(2, DUK_TOK_LOR);
} else if (DUK__L1() == DUK_ASC_EQUALS) {
@@ -81695,41 +87174,41 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
advtok = DUK__ADVTOK(1, DUK_TOK_BOR);
}
break;
- case DUK_ASC_CARET: /* '^' */
+ case DUK_ASC_CARET: /* '^' */
if (DUK__L1() == DUK_ASC_EQUALS) {
advtok = DUK__ADVTOK(2, DUK_TOK_BXOR_EQ);
} else {
advtok = DUK__ADVTOK(1, DUK_TOK_BXOR);
}
break;
- case DUK_ASC_TILDE: /* '~' */
+ case DUK_ASC_TILDE: /* '~' */
advtok = DUK__ADVTOK(1, DUK_TOK_BNOT);
break;
- case DUK_ASC_QUESTION: /* '?' */
+ case DUK_ASC_QUESTION: /* '?' */
advtok = DUK__ADVTOK(1, DUK_TOK_QUESTION);
break;
- case DUK_ASC_COLON: /* ':' */
+ case DUK_ASC_COLON: /* ':' */
advtok = DUK__ADVTOK(1, DUK_TOK_COLON);
break;
- case DUK_ASC_DOUBLEQUOTE: /* '"' */
- case DUK_ASC_SINGLEQUOTE: { /* '\'' */
+ case DUK_ASC_DOUBLEQUOTE: /* '"' */
+ case DUK_ASC_SINGLEQUOTE: { /* '\'' */
DUK__INITBUFFER(lex_ctx);
duk__lexer_parse_string_literal(lex_ctx, out_token, x /*quote*/, strict_mode);
duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
out_token->str1 = duk_known_hstring(lex_ctx->thr, lex_ctx->slot1_idx);
- DUK__INITBUFFER(lex_ctx); /* free some memory */
+ DUK__INITBUFFER(lex_ctx); /* free some memory */
advtok = DUK__ADVTOK(0, DUK_TOK_STRING);
break;
}
default:
goto slow_path;
- } /* switch */
+ } /* switch */
goto skip_slow_path;
- slow_path:
+slow_path:
if (duk_unicode_is_line_terminator(x)) {
if (x == 0x000d && DUK__L1() == 0x000a) {
/*
@@ -81766,7 +87245,7 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
* (the tokens DUK_TOK_GET and DUK_TOK_SET are actually not
* used now). The compiler needs to work around this.
*
- * Strictly speaking, following Ecmascript longest match
+ * Strictly speaking, following ECMAScript longest match
* specification, an invalid escape for the first character
* should cause a syntax error. However, an invalid escape
* for IdentifierParts should just terminate the identifier
@@ -81820,7 +87299,7 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
str = out_token->str1;
out_token->t_nores = DUK_TOK_IDENTIFIER;
- DUK__INITBUFFER(lex_ctx); /* free some memory */
+ DUK__INITBUFFER(lex_ctx); /* free some memory */
/*
* Interned identifier is compared against reserved words, which are
@@ -81847,7 +87326,7 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
advtok = DUK__ADVTOK(0, DUK_TOK_IDENTIFIER);
if (out_token->num_escapes == 0) {
for (i = DUK_STRIDX_START_RESERVED; i < i_end; i++) {
- DUK_ASSERT_DISABLE(i >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(i >= 0); /* unsigned */
DUK_ASSERT(i < DUK_HEAP_NUM_STRINGS);
if (DUK_HTHREAD_GET_STRING(lex_ctx->thr, i) == str) {
advtok = DUK__ADVTOK(0, DUK_STRIDX_TO_TOK(i));
@@ -81882,11 +87361,11 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
duk_double_t val;
duk_bool_t legacy_oct = 0;
- duk_small_int_t state; /* 0=before period/exp,
- * 1=after period, before exp
- * 2=after exp, allow '+' or '-'
- * 3=after exp and exp sign
- */
+ duk_small_int_t state; /* 0=before period/exp,
+ * 1=after period, before exp
+ * 2=after exp, allow '+' or '-'
+ * 3=after exp and exp sign
+ */
duk_small_uint_t s2n_flags;
duk_codepoint_t y, z;
duk_small_int_t s2n_radix = 10;
@@ -81898,7 +87377,7 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
if (x == DUK_ASC_0) {
z = DUK_LOWERCASE_CHAR_ASCII(y);
- pre_adv = 2; /* default for 0xNNN, 0oNNN, 0bNNN. */
+ pre_adv = 2; /* default for 0xNNN, 0oNNN, 0bNNN. */
if (z == DUK_ASC_LC_X) {
s2n_radix = 16;
} else if (z == DUK_ASC_LC_O) {
@@ -81921,7 +87400,7 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
DUK__APPENDBUFFER(lex_ctx, x);
pre_adv = 1;
legacy_oct = 1;
- s2n_radix = 8; /* tentative unless conflicting digits found */
+ s2n_radix = 8; /* tentative unless conflicting digits found */
}
}
}
@@ -81935,7 +87414,7 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
*/
state = 0;
for (;;) {
- x = DUK__L0(); /* re-lookup curr char on first round */
+ x = DUK__L0(); /* re-lookup curr char on first round */
if (DUK__ISDIGIT(x)) {
/* Note: intentionally allow leading zeroes here, as the
* actual parser will check for them.
@@ -81988,11 +87467,8 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
/* For bases other than 10, integer only. */
s2n_flags = DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
} else {
- s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
- DUK_S2N_FLAG_ALLOW_FRAC |
- DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
- DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
- DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
+ s2n_flags = DUK_S2N_FLAG_ALLOW_EXP | DUK_S2N_FLAG_ALLOW_FRAC | DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
+ DUK_S2N_FLAG_ALLOW_EMPTY_FRAC | DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
}
duk_dup(lex_ctx->thr, lex_ctx->slot1_idx);
@@ -82001,9 +87477,9 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
if (DUK_ISNAN(val)) {
goto fail_number_literal;
}
- duk_replace(lex_ctx->thr, lex_ctx->slot1_idx); /* could also just pop? */
+ duk_replace(lex_ctx->thr, lex_ctx->slot1_idx); /* could also just pop? */
- DUK__INITBUFFER(lex_ctx); /* free some memory */
+ DUK__INITBUFFER(lex_ctx); /* free some memory */
/* Section 7.8.3 (note): NumericLiteral must be followed by something other than
* IdentifierStart or DecimalDigit.
@@ -82023,7 +87499,7 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
} else {
goto fail_token;
}
- skip_slow_path:
+skip_slow_path:
/*
* Shared exit path
@@ -82048,34 +87524,34 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
return;
- fail_token_limit:
+fail_token_limit:
DUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT);
- return;
+ DUK_WO_NORETURN(return;);
- fail_token:
+fail_token:
DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_TOKEN);
- return;
+ DUK_WO_NORETURN(return;);
- fail_number_literal:
+fail_number_literal:
DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_NUMBER_LITERAL);
- return;
+ DUK_WO_NORETURN(return;);
- fail_escape:
+fail_escape:
DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
- return;
+ DUK_WO_NORETURN(return;);
- fail_unterm_regexp:
+fail_unterm_regexp:
DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_REGEXP);
- return;
+ DUK_WO_NORETURN(return;);
- fail_unterm_comment:
+fail_unterm_comment:
DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_COMMENT);
- return;
+ DUK_WO_NORETURN(return;);
#if !defined(DUK_USE_REGEXP_SUPPORT)
- fail_regexp_support:
+fail_regexp_support:
DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_REGEXP_SUPPORT_DISABLED);
- return;
+ DUK_WO_NORETURN(return;);
#endif
}
@@ -82091,14 +87567,14 @@ void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
*/
DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
- duk_small_uint_t advtok = 0; /* init is unnecessary but suppresses "may be used uninitialized" warnings */
+ duk_small_uint_t advtok = 0; /* init is unnecessary but suppresses "may be used uninitialized" warnings */
duk_codepoint_t x, y;
if (++lex_ctx->token_count >= lex_ctx->token_limit) {
goto fail_token_limit;
}
- DUK_MEMZERO(out_token, sizeof(*out_token));
+ duk_memzero(out_token, sizeof(*out_token));
x = DUK__L0();
y = DUK__L1();
@@ -82169,7 +87645,7 @@ DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token
#endif
for (;;) {
- DUK__ADVANCECHARS(lex_ctx, 1); /* eat '{' on entry */
+ DUK__ADVANCECHARS(lex_ctx, 1); /* eat '{' on entry */
x = DUK__L0();
if (DUK__ISDIGIT(x)) {
digits++;
@@ -82193,7 +87669,7 @@ DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token
}
val2 = val1;
val1 = 0;
- digits = 0; /* not strictly necessary because of lookahead '}' above */
+ digits = 0; /* not strictly necessary because of lookahead '}' above */
} else if (x == DUK_ASC_RCURLY) {
if (digits > DUK__MAX_RE_QUANT_DIGITS) {
goto invalid_quantifier;
@@ -82224,7 +87700,7 @@ DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token
}
advtok = DUK__ADVTOK(0, DUK_RETOK_QUANTIFIER);
break;
- invalid_quantifier:
+ invalid_quantifier:
#if defined(DUK_USE_ES6_REGEXP_SYNTAX)
/* Failed to match the quantifier, restore lexer and parse
* opening brace as a literal.
@@ -82250,7 +87726,7 @@ DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token
* ES2015 Annex B relaxes the rules to allow these (and other) real world forms.
*/
- advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR); /* default: char escape (two chars) */
+ advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR); /* default: char escape (two chars) */
if (y == DUK_ASC_LC_B) {
advtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_WORD_BOUNDARY);
} else if (y == DUK_ASC_UC_B) {
@@ -82267,8 +87743,7 @@ DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token
out_token->num = 0x000b;
} else if (y == DUK_ASC_LC_C) {
x = DUK__L2();
- if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) ||
- (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
+ if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) || (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
out_token->num = (duk_uint32_t) (x % 32);
advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_CHAR);
} else {
@@ -82306,11 +87781,11 @@ DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token
/* XXX: shared parsing? */
duk_uint32_t val = 0;
duk_small_int_t i;
- for (i = 0; ; i++) {
+ for (i = 0;; i++) {
if (i >= DUK__MAX_RE_DECESC_DIGITS) {
goto fail_escape;
}
- DUK__ADVANCECHARS(lex_ctx, 1); /* eat backslash on entry */
+ DUK__ADVANCECHARS(lex_ctx, 1); /* eat backslash on entry */
x = DUK__L0();
if (!DUK__ISDIGIT(x)) {
break;
@@ -82330,17 +87805,15 @@ DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token
* This is not yet full ES2015 Annex B because cases above
* (like hex escape) won't backtrack.
*/
- DUK_ASSERT(y != DUK_ASC_LC_C); /* covered above */
-#else /* DUK_USE_ES6_REGEXP_SYNTAX */
- } else if ((y >= 0 && !duk_unicode_is_identifier_part(y)) ||
- y == DUK_UNICODE_CP_ZWNJ ||
- y == DUK_UNICODE_CP_ZWJ) {
+ DUK_ASSERT(y != DUK_ASC_LC_C); /* covered above */
+#else /* DUK_USE_ES6_REGEXP_SYNTAX */
+ } else if ((y >= 0 && !duk_unicode_is_identifier_part(y)) || y == DUK_UNICODE_CP_ZWNJ || y == DUK_UNICODE_CP_ZWJ) {
/* For ES5.1 identity escapes are not allowed for identifier
* parts. This conflicts with a lot of real world code as this
* doesn't e.g. allow escaping a dollar sign as /\$/, see
* test-regexp-identity-escape-dollar.js.
*/
-#endif /* DUK_USE_ES6_REGEXP_SYNTAX */
+#endif /* DUK_USE_ES6_REGEXP_SYNTAX */
out_token->num = (duk_uint32_t) y;
} else {
goto fail_escape;
@@ -82421,26 +87894,26 @@ DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token
out_token->t = advtok & 0xff;
return;
- fail_token_limit:
+fail_token_limit:
DUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT);
- return;
+ DUK_WO_NORETURN(return;);
- fail_escape:
+fail_escape:
DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE);
- return;
+ DUK_WO_NORETURN(return;);
- fail_group:
+fail_group:
DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_GROUP);
- return;
+ DUK_WO_NORETURN(return;);
#if !defined(DUK_USE_ES6_REGEXP_SYNTAX)
- fail_invalid_char:
+fail_invalid_char:
DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_CHARACTER);
- return;
+ DUK_WO_NORETURN(return;);
- fail_quantifier:
+fail_quantifier:
DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_QUANTIFIER);
- return;
+ DUK_WO_NORETURN(return;);
#endif
}
@@ -82497,7 +87970,7 @@ DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range
x = DUK__L0();
- ch = -1; /* not strictly necessary, but avoids "uninitialized variable" warnings */
+ ch = -1; /* not strictly necessary, but avoids "uninitialized variable" warnings */
DUK_UNREF(ch);
if (x < 0) {
@@ -82506,7 +87979,7 @@ DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range
if (start >= 0) {
gen_range(userdata, start, start, 0);
}
- DUK__ADVANCECHARS(lex_ctx, 1); /* eat ']' before finishing */
+ DUK__ADVANCECHARS(lex_ctx, 1); /* eat ']' before finishing */
break;
} else if (x == DUK_ASC_MINUS) {
if (start >= 0 && !dash && DUK__L1() != DUK_ASC_RBRACKET) {
@@ -82551,8 +88024,7 @@ DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range
} else if (x == DUK_ASC_LC_C) {
x = DUK__L2();
adv = 3;
- if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) ||
- (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
+ if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) || (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
ch = (x % 32);
} else {
goto fail_escape;
@@ -82616,7 +88088,7 @@ DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range
#if defined(DUK_USE_ES6_REGEXP_SYNTAX)
ch = duk__lexer_parse_legacy_octal(lex_ctx, &adv, 0 /*reject_annex_b*/);
- DUK_ASSERT(ch >= 0); /* no rejections */
+ DUK_ASSERT(ch >= 0); /* no rejections */
#else
if (x == DUK_ASC_0 && !DUK__ISDIGIT(DUK__L2())) {
ch = 0x0000;
@@ -82631,7 +88103,7 @@ DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range
* EOF here.
*/
ch = x;
-#else /* DUK_USE_ES6_REGEXP_SYNTAX */
+#else /* DUK_USE_ES6_REGEXP_SYNTAX */
} else if (!duk_unicode_is_identifier_part(x)) {
/* IdentityEscape: ES5.1 doesn't allow identity escape
* for identifier part characters, which conflicts with
@@ -82639,7 +88111,7 @@ DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range
* /[\$]/ which is awkward.
*/
ch = x;
-#endif /* DUK_USE_ES6_REGEXP_SYNTAX */
+#endif /* DUK_USE_ES6_REGEXP_SYNTAX */
} else {
goto fail_escape;
}
@@ -82687,20 +88159,20 @@ DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range
return;
- fail_escape:
+fail_escape:
DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE);
- return;
+ DUK_WO_NORETURN(return;);
- fail_range:
+fail_range:
DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_RANGE);
- return;
+ DUK_WO_NORETURN(return;);
- fail_unterm_charclass:
+fail_unterm_charclass:
DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_CHARCLASS);
- return;
+ DUK_WO_NORETURN(return;);
}
-#endif /* DUK_USE_REGEXP_SUPPORT */
+#endif /* DUK_USE_REGEXP_SUPPORT */
/* automatic undefs */
#undef DUK__ADVANCEBYTES
@@ -82737,10 +88209,10 @@ DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range
/* #include duk_internal.h -> already included */
-#define DUK__IEEE_DOUBLE_EXP_BIAS 1023
-#define DUK__IEEE_DOUBLE_EXP_MIN (-1022) /* biased exp == 0 -> denormal, exp -1022 */
+#define DUK__IEEE_DOUBLE_EXP_BIAS 1023
+#define DUK__IEEE_DOUBLE_EXP_MIN (-1022) /* biased exp == 0 -> denormal, exp -1022 */
-#define DUK__DIGITCHAR(x) duk_lc_digits[(x)]
+#define DUK__DIGITCHAR(x) duk_lc_digits[(x)]
/*
* Tables generated with util/gennumdigits.py.
@@ -82758,10 +88230,10 @@ DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range
*/
DUK_LOCAL const duk_uint8_t duk__str2num_digits_for_radix[] = {
- 69, 44, 35, 30, 27, 25, 23, 22, 20, 20, /* 2 to 11 */
- 20, 19, 19, 18, 18, 17, 17, 17, 16, 16, /* 12 to 21 */
- 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, /* 22 to 31 */
- 14, 14, 14, 14, 14 /* 31 to 36 */
+ 69, 44, 35, 30, 27, 25, 23, 22, 20, 20, /* 2 to 11 */
+ 20, 19, 19, 18, 18, 17, 17, 17, 16, 16, /* 12 to 21 */
+ 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, /* 22 to 31 */
+ 14, 14, 14, 14, 14 /* 31 to 36 */
};
typedef struct {
@@ -82770,15 +88242,11 @@ typedef struct {
} duk__exp_limits;
DUK_LOCAL const duk__exp_limits duk__str2num_exp_limits[] = {
- { 957, -1147 }, { 605, -725 }, { 479, -575 }, { 414, -496 },
- { 372, -446 }, { 342, -411 }, { 321, -384 }, { 304, -364 },
- { 291, -346 }, { 279, -334 }, { 268, -323 }, { 260, -312 },
- { 252, -304 }, { 247, -296 }, { 240, -289 }, { 236, -283 },
- { 231, -278 }, { 227, -273 }, { 223, -267 }, { 220, -263 },
- { 216, -260 }, { 213, -256 }, { 210, -253 }, { 208, -249 },
- { 205, -246 }, { 203, -244 }, { 201, -241 }, { 198, -239 },
- { 196, -237 }, { 195, -234 }, { 193, -232 }, { 191, -230 },
- { 190, -228 }, { 188, -226 }, { 187, -225 },
+ { 957, -1147 }, { 605, -725 }, { 479, -575 }, { 414, -496 }, { 372, -446 }, { 342, -411 }, { 321, -384 },
+ { 304, -364 }, { 291, -346 }, { 279, -334 }, { 268, -323 }, { 260, -312 }, { 252, -304 }, { 247, -296 },
+ { 240, -289 }, { 236, -283 }, { 231, -278 }, { 227, -273 }, { 223, -267 }, { 220, -263 }, { 216, -260 },
+ { 213, -256 }, { 210, -253 }, { 208, -249 }, { 205, -246 }, { 203, -244 }, { 201, -241 }, { 198, -239 },
+ { 196, -237 }, { 195, -234 }, { 193, -232 }, { 191, -230 }, { 190, -228 }, { 188, -226 }, { 187, -225 },
};
/*
@@ -82796,18 +88264,18 @@ DUK_LOCAL const duk__exp_limits duk__str2num_exp_limits[] = {
/* This upper value has been experimentally determined; debug build will check
* bigint size with assertions.
*/
-#define DUK__BI_MAX_PARTS 37 /* 37x32 = 1184 bits */
+#define DUK__BI_MAX_PARTS 37 /* 37x32 = 1184 bits */
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
-#define DUK__BI_PRINT(name,x) duk__bi_print((name),(x))
+#define DUK__BI_PRINT(name, x) duk__bi_print((name), (x))
#else
-#define DUK__BI_PRINT(name,x)
+#define DUK__BI_PRINT(name, x)
#endif
/* Current size is about 152 bytes. */
typedef struct {
duk_small_int_t n;
- duk_uint32_t v[DUK__BI_MAX_PARTS]; /* low to high */
+ duk_uint32_t v[DUK__BI_MAX_PARTS]; /* low to high */
} duk__bigint;
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
@@ -82832,9 +88300,8 @@ DUK_LOCAL void duk__bi_print(const char *name, duk__bigint *x) {
#if defined(DUK_USE_ASSERTIONS)
DUK_LOCAL duk_small_int_t duk__bi_is_valid(duk__bigint *x) {
- return (duk_small_int_t)
- ( ((x->n >= 0) && (x->n <= DUK__BI_MAX_PARTS)) /* is valid size */ &&
- ((x->n == 0) || (x->v[x->n - 1] != 0)) /* is normalized */ );
+ return (duk_small_int_t) (((x->n >= 0) && (x->n <= DUK__BI_MAX_PARTS)) /* is valid size */ &&
+ ((x->n == 0) || (x->v[x->n - 1] != 0)) /* is normalized */);
}
#endif
@@ -82858,10 +88325,8 @@ DUK_LOCAL void duk__bi_copy(duk__bigint *x, duk__bigint *y) {
n = y->n;
x->n = n;
- if (n == 0) {
- return;
- }
- DUK_MEMCPY((void *) x->v, (const void *) y->v, (size_t) (sizeof(duk_uint32_t) * (size_t) n));
+ /* No need to special case n == 0. */
+ duk_memcpy((void *) x->v, (const void *) y->v, (size_t) (sizeof(duk_uint32_t) * (size_t) n));
}
DUK_LOCAL void duk__bi_set_small(duk__bigint *x, duk_uint32_t v) {
@@ -82907,10 +88372,10 @@ DUK_LOCAL int duk__bi_compare(duk__bigint *x, duk__bigint *y) {
return 0;
- ret_gt:
+ret_gt:
return 1;
- ret_lt:
+ret_lt:
return -1;
}
@@ -82925,11 +88390,14 @@ DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
if (z->n > y->n) {
duk__bigint *t;
- t = y; y = z; z = t;
+ t = y;
+ y = z;
+ z = t;
}
DUK_ASSERT(y->n >= z->n);
- ny = y->n; nz = z->n;
+ ny = y->n;
+ nz = z->n;
tmp = 0U;
for (i = 0; i < ny; i++) {
DUK_ASSERT(i < DUK__BI_MAX_PARTS);
@@ -82950,7 +88418,7 @@ DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
/* no need to normalize */
DUK_ASSERT(duk__bi_is_valid(x));
}
-#else /* DUK_USE_64BIT_OPS */
+#else /* DUK_USE_64BIT_OPS */
DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
duk_uint32_t carry, tmp1, tmp2;
duk_small_int_t i, ny, nz;
@@ -82960,11 +88428,14 @@ DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
if (z->n > y->n) {
duk__bigint *t;
- t = y; y = z; z = t;
+ t = y;
+ y = z;
+ z = t;
}
DUK_ASSERT(y->n >= z->n);
- ny = y->n; nz = z->n;
+ ny = y->n;
+ nz = z->n;
carry = 0U;
for (i = 0; i < ny; i++) {
/* Carry is detected based on wrapping which relies on exact 32-bit
@@ -83001,7 +88472,7 @@ DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
/* no need to normalize */
DUK_ASSERT(duk__bi_is_valid(x));
}
-#endif /* DUK_USE_64BIT_OPS */
+#endif /* DUK_USE_64BIT_OPS */
/* x <- y + z */
DUK_LOCAL void duk__bi_add_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
@@ -83016,7 +88487,7 @@ DUK_LOCAL void duk__bi_add_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z)
DUK_ASSERT(duk__bi_is_valid(x));
}
-#if 0 /* unused */
+#if 0 /* unused */
/* x <- x + y, use t as temp */
DUK_LOCAL void duk__bi_add_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
duk__bi_add(t, x, y);
@@ -83036,7 +88507,8 @@ DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
DUK_ASSERT(duk__bi_compare(y, z) >= 0);
DUK_ASSERT(y->n >= z->n);
- ny = y->n; nz = z->n;
+ ny = y->n;
+ nz = z->n;
tmp = 0;
for (i = 0; i < ny; i++) {
ty = y->v[i];
@@ -83047,12 +88519,12 @@ DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
}
tmp = (duk_int64_t) ty - (duk_int64_t) tz + tmp;
x->v[i] = (duk_uint32_t) ((duk_uint64_t) tmp & 0xffffffffUL);
- tmp = tmp >> 32; /* 0 or -1 */
+ tmp = tmp >> 32; /* 0 or -1 */
}
DUK_ASSERT(tmp == 0);
x->n = i;
- duk__bi_normalize(x); /* need to normalize, may even cancel to 0 */
+ duk__bi_normalize(x); /* need to normalize, may even cancel to 0 */
DUK_ASSERT(duk__bi_is_valid(x));
}
#else
@@ -83065,7 +88537,8 @@ DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
DUK_ASSERT(duk__bi_compare(y, z) >= 0);
DUK_ASSERT(y->n >= z->n);
- ny = y->n; nz = z->n;
+ ny = y->n;
+ nz = z->n;
borrow = 0U;
for (i = 0; i < ny; i++) {
/* Borrow is detected based on wrapping which relies on exact 32-bit
@@ -83093,12 +88566,12 @@ DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
DUK_ASSERT(borrow == 0U);
x->n = i;
- duk__bi_normalize(x); /* need to normalize, may even cancel to 0 */
+ duk__bi_normalize(x); /* need to normalize, may even cancel to 0 */
DUK_ASSERT(duk__bi_is_valid(x));
}
#endif
-#if 0 /* unused */
+#if 0 /* unused */
/* x <- y - z */
DUK_LOCAL void duk__bi_sub_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
duk__bigint tmp;
@@ -83126,7 +88599,7 @@ DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
DUK_ASSERT(duk__bi_is_valid(y));
DUK_ASSERT(duk__bi_is_valid(z));
- nx = y->n + z->n; /* max possible */
+ nx = y->n + z->n; /* max possible */
DUK_ASSERT(nx <= DUK__BI_MAX_PARTS);
if (nx == 0) {
@@ -83137,7 +88610,7 @@ DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
return;
}
- DUK_MEMZERO((void *) x->v, (size_t) (sizeof(duk_uint32_t) * (size_t) nx));
+ duk_memzero((void *) x->v, (size_t) (sizeof(duk_uint32_t) * (size_t) nx));
x->n = nx;
nz = z->n;
@@ -83145,15 +88618,15 @@ DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
#if defined(DUK_USE_64BIT_OPS)
duk_uint64_t tmp = 0U;
for (j = 0; j < nz; j++) {
- tmp += (duk_uint64_t) y->v[i] * (duk_uint64_t) z->v[j] + x->v[i+j];
- x->v[i+j] = (duk_uint32_t) (tmp & 0xffffffffUL);
+ tmp += (duk_uint64_t) y->v[i] * (duk_uint64_t) z->v[j] + x->v[i + j];
+ x->v[i + j] = (duk_uint32_t) (tmp & 0xffffffffUL);
tmp = tmp >> 32;
}
if (tmp > 0) {
DUK_ASSERT(i + j < nx);
DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
- DUK_ASSERT(x->v[i+j] == 0U);
- x->v[i+j] = (duk_uint32_t) tmp;
+ DUK_ASSERT(x->v[i + j] == 0U);
+ x->v[i + j] = (duk_uint32_t) tmp;
}
#else
/*
@@ -83173,12 +88646,16 @@ DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
duk_uint32_t a, b, c, d, e, f;
duk_uint32_t r, s, t;
- a = y->v[i]; b = a & 0xffffUL; a = a >> 16;
+ a = y->v[i];
+ b = a & 0xffffUL;
+ a = a >> 16;
f = 0;
for (j = 0; j < nz; j++) {
- c = z->v[j]; d = c & 0xffffUL; c = c >> 16;
- e = x->v[i+j];
+ c = z->v[j];
+ d = c & 0xffffUL;
+ c = c >> 16;
+ e = x->v[i + j];
/* build result as: (r << 32) + s: start with (BD + E + F) */
r = 0;
@@ -83186,26 +88663,34 @@ DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
/* add E */
t = s + e;
- if (t < s) { r++; } /* carry */
+ if (t < s) {
+ r++;
+ } /* carry */
s = t;
/* add F */
t = s + f;
- if (t < s) { r++; } /* carry */
+ if (t < s) {
+ r++;
+ } /* carry */
s = t;
/* add BC*2^16 */
t = b * c;
r += (t >> 16);
t = s + ((t & 0xffffUL) << 16);
- if (t < s) { r++; } /* carry */
+ if (t < s) {
+ r++;
+ } /* carry */
s = t;
/* add AD*2^16 */
t = a * d;
r += (t >> 16);
t = s + ((t & 0xffffUL) << 16);
- if (t < s) { r++; } /* carry */
+ if (t < s) {
+ r++;
+ } /* carry */
s = t;
/* add AC*2^32 */
@@ -83213,20 +88698,22 @@ DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
r += t;
DUK_DDD(DUK_DDDPRINT("ab=%08lx cd=%08lx ef=%08lx -> rs=%08lx %08lx",
- (unsigned long) y->v[i], (unsigned long) z->v[j],
- (unsigned long) x->v[i+j], (unsigned long) r,
+ (unsigned long) y->v[i],
+ (unsigned long) z->v[j],
+ (unsigned long) x->v[i + j],
+ (unsigned long) r,
(unsigned long) s));
- x->v[i+j] = s;
+ x->v[i + j] = s;
f = r;
}
if (f > 0U) {
DUK_ASSERT(i + j < nx);
DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
- DUK_ASSERT(x->v[i+j] == 0U);
- x->v[i+j] = (duk_uint32_t) f;
+ DUK_ASSERT(x->v[i + j] == 0U);
+ x->v[i + j] = (duk_uint32_t) f;
}
-#endif /* DUK_USE_64BIT_OPS */
+#endif /* DUK_USE_64BIT_OPS */
}
duk__bi_normalize(x);
@@ -83265,7 +88752,7 @@ DUK_LOCAL int duk__bi_is_even(duk__bigint *x) {
DUK_LOCAL int duk__bi_is_zero(duk__bigint *x) {
DUK_ASSERT(duk__bi_is_valid(x));
- return (x->n == 0); /* this is the case for normalized numbers */
+ return (x->n == 0); /* this is the case for normalized numbers */
}
/* Bigint is 2^52. Used to detect normalized IEEE double mantissa values
@@ -83276,8 +88763,7 @@ DUK_LOCAL int duk__bi_is_zero(duk__bigint *x) {
*/
DUK_LOCAL duk_small_int_t duk__bi_is_2to52(duk__bigint *x) {
DUK_ASSERT(duk__bi_is_valid(x));
- return (duk_small_int_t)
- (x->n == 2) && (x->v[0] == 0U) && (x->v[1] == (1U << (52-32)));
+ return (duk_small_int_t) (x->n == 2) && (x->v[0] == 0U) && (x->v[1] == (1U << (52 - 32)));
}
/* x <- (1<<y) */
@@ -83287,7 +88773,7 @@ DUK_LOCAL void duk__bi_twoexp(duk__bigint *x, duk_small_int_t y) {
n = (y / 32) + 1;
DUK_ASSERT(n > 0);
r = y % 32;
- DUK_MEMZERO((void *) x->v, sizeof(duk_uint32_t) * (size_t) n);
+ duk_memzero((void *) x->v, sizeof(duk_uint32_t) * (size_t) n);
x->n = n;
x->v[n - 1] = (((duk_uint32_t) 1) << r);
}
@@ -83296,7 +88782,7 @@ DUK_LOCAL void duk__bi_twoexp(duk__bigint *x, duk_small_int_t y) {
DUK_LOCAL void duk__bi_exp_small(duk__bigint *x, duk_small_int_t b, duk_small_int_t y, duk__bigint *t1, duk__bigint *t2) {
/* Fast path the binary case */
- DUK_ASSERT(x != t1 && x != t2 && t1 != t2); /* distinct bignums, easy mistake to make */
+ DUK_ASSERT(x != t1 && x != t2 && t1 != t2); /* distinct bignums, easy mistake to make */
DUK_ASSERT(b >= 0);
DUK_ASSERT(y >= 0);
@@ -83351,14 +88837,14 @@ DUK_LOCAL void duk__bi_exp_small(duk__bigint *x, duk_small_int_t b, duk_small_in
*/
/* Maximum number of digits generated. */
-#define DUK__MAX_OUTPUT_DIGITS 1040 /* (Number.MAX_VALUE).toString(2).length == 1024, + slack */
+#define DUK__MAX_OUTPUT_DIGITS 1040 /* (Number.MAX_VALUE).toString(2).length == 1024, + slack */
/* Maximum number of characters in formatted value. */
-#define DUK__MAX_FORMATTED_LENGTH 1040 /* (-Number.MAX_VALUE).toString(2).length == 1025, + slack */
+#define DUK__MAX_FORMATTED_LENGTH 1040 /* (-Number.MAX_VALUE).toString(2).length == 1025, + slack */
/* Number and (minimum) size of bigints in the nc_ctx structure. */
-#define DUK__NUMCONV_CTX_NUM_BIGINTS 7
-#define DUK__NUMCONV_CTX_BIGINTS_SIZE (sizeof(duk__bigint) * DUK__NUMCONV_CTX_NUM_BIGINTS)
+#define DUK__NUMCONV_CTX_NUM_BIGINTS 7
+#define DUK__NUMCONV_CTX_BIGINTS_SIZE (sizeof(duk__bigint) * DUK__NUMCONV_CTX_NUM_BIGINTS)
typedef struct {
/* Currently about 7*152 = 1064 bytes. The space for these
@@ -83368,31 +88854,32 @@ typedef struct {
*/
duk__bigint f, r, s, mp, mm, t1, t2;
- duk_small_int_t is_s2n; /* if 1, doing a string-to-number; else doing a number-to-string */
- duk_small_int_t is_fixed; /* if 1, doing a fixed format output (not free format) */
- duk_small_int_t req_digits; /* requested number of output digits; 0 = free-format */
- duk_small_int_t abs_pos; /* digit position is absolute, not relative */
- duk_small_int_t e; /* exponent for 'f' */
- duk_small_int_t b; /* input radix */
- duk_small_int_t B; /* output radix */
- duk_small_int_t k; /* see algorithm */
- duk_small_int_t low_ok; /* see algorithm */
- duk_small_int_t high_ok; /* see algorithm */
- duk_small_int_t unequal_gaps; /* m+ != m- (very rarely) */
+ duk_small_int_t is_s2n; /* if 1, doing a string-to-number; else doing a number-to-string */
+ duk_small_int_t is_fixed; /* if 1, doing a fixed format output (not free format) */
+ duk_small_int_t req_digits; /* requested number of output digits; 0 = free-format */
+ duk_small_int_t abs_pos; /* digit position is absolute, not relative */
+ duk_small_int_t e; /* exponent for 'f' */
+ duk_small_int_t b; /* input radix */
+ duk_small_int_t B; /* output radix */
+ duk_small_int_t k; /* see algorithm */
+ duk_small_int_t low_ok; /* see algorithm */
+ duk_small_int_t high_ok; /* see algorithm */
+ duk_small_int_t unequal_gaps; /* m+ != m- (very rarely) */
/* Buffer used for generated digits, values are in the range [0,B-1]. */
duk_uint8_t digits[DUK__MAX_OUTPUT_DIGITS];
- duk_small_int_t count; /* digit count */
+ duk_small_int_t count; /* digit count */
} duk__numconv_stringify_ctx;
/* Note: computes with 'idx' in assertions, so caller beware.
* 'idx' is preincremented, i.e. '1' on first call, because it
* is more convenient for the caller.
*/
-#define DUK__DRAGON4_OUTPUT_PREINC(nc_ctx,preinc_idx,x) do { \
- DUK_ASSERT((preinc_idx) - 1 >= 0); \
- DUK_ASSERT((preinc_idx) - 1 < DUK__MAX_OUTPUT_DIGITS); \
- ((nc_ctx)->digits[(preinc_idx) - 1]) = (duk_uint8_t) (x); \
+#define DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, preinc_idx, x) \
+ do { \
+ DUK_ASSERT((preinc_idx) -1 >= 0); \
+ DUK_ASSERT((preinc_idx) -1 < DUK__MAX_OUTPUT_DIGITS); \
+ ((nc_ctx)->digits[(preinc_idx) -1]) = (duk_uint8_t) (x); \
} while (0)
DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x, duk_small_int_t radix) {
@@ -83401,6 +88888,7 @@ DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x
duk_small_int_t dig;
duk_uint32_t t;
+ DUK_ASSERT(buf != NULL);
DUK_ASSERT(radix >= 2 && radix <= 36);
/* A 32-bit unsigned integer formats to at most 32 digits (the
@@ -83423,7 +88911,7 @@ DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x
}
len = (duk_size_t) ((buf + 32) - p);
- DUK_MEMMOVE((void *) buf, (const void *) p, (size_t) len);
+ duk_memmove((void *) buf, (const void *) p, (size_t) len);
return len;
}
@@ -83490,11 +88978,11 @@ DUK_LOCAL void duk__dragon4_prepare(duk__numconv_stringify_ctx *nc_ctx) {
"lowest mantissa value for this exponent -> "
"unequal gaps"));
- duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2); /* mm <- b^e */
- duk__bi_mul_small(&nc_ctx->mp, &nc_ctx->mm, (duk_uint32_t) nc_ctx->b); /* mp <- b^(e+1) */
+ duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2); /* mm <- b^e */
+ duk__bi_mul_small(&nc_ctx->mp, &nc_ctx->mm, (duk_uint32_t) nc_ctx->b); /* mp <- b^(e+1) */
duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
- duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp); /* r <- (2 * f) * b^(e+1) */
- duk__bi_set_small(&nc_ctx->s, (duk_uint32_t) (nc_ctx->b * 2)); /* s <- 2 * b */
+ duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp); /* r <- (2 * f) * b^(e+1) */
+ duk__bi_set_small(&nc_ctx->s, (duk_uint32_t) (nc_ctx->b * 2)); /* s <- 2 * b */
nc_ctx->unequal_gaps = 1;
} else {
/* (>= e 0) AND (not (= f (expt b (- p 1))))
@@ -83514,11 +89002,11 @@ DUK_LOCAL void duk__dragon4_prepare(duk__numconv_stringify_ctx *nc_ctx) {
"not lowest mantissa for this exponent -> "
"equal gaps"));
- duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2); /* mm <- b^e */
- duk__bi_copy(&nc_ctx->mp, &nc_ctx->mm); /* mp <- b^e */
+ duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2); /* mm <- b^e */
+ duk__bi_copy(&nc_ctx->mp, &nc_ctx->mm); /* mp <- b^e */
duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
- duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp); /* r <- (2 * f) * b^e */
- duk__bi_set_small(&nc_ctx->s, 2); /* s <- 2 */
+ duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp); /* r <- (2 * f) * b^e */
+ duk__bi_set_small(&nc_ctx->s, 2); /* s <- 2 */
}
} else {
/* When doing string-to-number, lowest_mantissa is always 0 so
@@ -83540,9 +89028,13 @@ DUK_LOCAL void duk__dragon4_prepare(duk__numconv_stringify_ctx *nc_ctx) {
"lowest mantissa for this exponent -> "
"unequal gaps"));
- duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, (duk_uint32_t) (nc_ctx->b * 2)); /* r <- (2 * b) * f */
- duk__bi_exp_small(&nc_ctx->t1, nc_ctx->b, 1 - nc_ctx->e, &nc_ctx->s, &nc_ctx->t2); /* NB: use 's' as temp on purpose */
- duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2); /* s <- b^(1-e) * 2 */
+ duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, (duk_uint32_t) (nc_ctx->b * 2)); /* r <- (2 * b) * f */
+ duk__bi_exp_small(&nc_ctx->t1,
+ nc_ctx->b,
+ 1 - nc_ctx->e,
+ &nc_ctx->s,
+ &nc_ctx->t2); /* NB: use 's' as temp on purpose */
+ duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2); /* s <- b^(1-e) * 2 */
duk__bi_set_small(&nc_ctx->mp, 2);
duk__bi_set_small(&nc_ctx->mm, 1);
nc_ctx->unequal_gaps = 1;
@@ -83561,9 +89053,13 @@ DUK_LOCAL void duk__dragon4_prepare(duk__numconv_stringify_ctx *nc_ctx) {
"lowest mantissa for this exponent -> "
"equal gaps"));
- duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, 2); /* r <- 2 * f */
- duk__bi_exp_small(&nc_ctx->t1, nc_ctx->b, -nc_ctx->e, &nc_ctx->s, &nc_ctx->t2); /* NB: use 's' as temp on purpose */
- duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2); /* s <- b^(-e) * 2 */
+ duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, 2); /* r <- 2 * f */
+ duk__bi_exp_small(&nc_ctx->t1,
+ nc_ctx->b,
+ -nc_ctx->e,
+ &nc_ctx->s,
+ &nc_ctx->t2); /* NB: use 's' as temp on purpose */
+ duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2); /* s <- b^(-e) * 2 */
duk__bi_set_small(&nc_ctx->mp, 1);
duk__bi_set_small(&nc_ctx->mm, 1);
}
@@ -83595,8 +89091,8 @@ DUK_LOCAL void duk__dragon4_scale(duk__numconv_stringify_ctx *nc_ctx) {
* impact for very large and very small numbers.
*/
- DUK_DDD(DUK_DDDPRINT("scale: B=%ld, low_ok=%ld, high_ok=%ld",
- (long) nc_ctx->B, (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
+ DUK_DDD(
+ DUK_DDDPRINT("scale: B=%ld, low_ok=%ld, high_ok=%ld", (long) nc_ctx->B, (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
DUK__BI_PRINT("r(init)", &nc_ctx->r);
DUK__BI_PRINT("s(init)", &nc_ctx->s);
DUK__BI_PRINT("mp(init)", &nc_ctx->mp);
@@ -83609,7 +89105,7 @@ DUK_LOCAL void duk__dragon4_scale(duk__numconv_stringify_ctx *nc_ctx) {
DUK__BI_PRINT("m+", &nc_ctx->mp);
DUK__BI_PRINT("m-", &nc_ctx->mm);
- duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 = (+ r m+) */
+ duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 = (+ r m+) */
if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1)) {
DUK_DDD(DUK_DDDPRINT("k is too low"));
/* r <- r
@@ -83638,8 +89134,8 @@ DUK_LOCAL void duk__dragon4_scale(duk__numconv_stringify_ctx *nc_ctx) {
DUK__BI_PRINT("m+", &nc_ctx->mp);
DUK__BI_PRINT("m-", &nc_ctx->mm);
- duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 = (+ r m+) */
- duk__bi_mul_small(&nc_ctx->t2, &nc_ctx->t1, (duk_uint32_t) nc_ctx->B); /* t2 = (* (+ r m+) B) */
+ duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 = (+ r m+) */
+ duk__bi_mul_small(&nc_ctx->t2, &nc_ctx->t1, (duk_uint32_t) nc_ctx->B); /* t2 = (* (+ r m+) B) */
if (duk__bi_compare(&nc_ctx->t2, &nc_ctx->s) <= (nc_ctx->high_ok ? -1 : 0)) {
DUK_DDD(DUK_DDDPRINT("k is too high"));
/* r <- (* r B)
@@ -83660,11 +89156,11 @@ DUK_LOCAL void duk__dragon4_scale(duk__numconv_stringify_ctx *nc_ctx) {
}
}
- skip_dec_k:
+skip_dec_k:
if (!nc_ctx->unequal_gaps) {
DUK_DDD(DUK_DDDPRINT("equal gaps, copy m- from m+"));
- duk__bi_copy(&nc_ctx->mm, &nc_ctx->mp); /* mm <- mp */
+ duk__bi_copy(&nc_ctx->mm, &nc_ctx->mp); /* mm <- mp */
}
nc_ctx->k = k;
@@ -83676,9 +89172,9 @@ DUK_LOCAL void duk__dragon4_scale(duk__numconv_stringify_ctx *nc_ctx) {
}
DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {
- duk_small_int_t tc1, tc2; /* terminating conditions */
- duk_small_int_t d; /* current digit */
- duk_small_int_t count = 0; /* digit count */
+ duk_small_int_t tc1, tc2; /* terminating conditions */
+ duk_small_int_t d; /* current digit */
+ duk_small_int_t count = 0; /* digit count */
/*
* Digit generation loop.
@@ -83700,25 +89196,28 @@ DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {
for (;;) {
DUK_DDD(DUK_DDDPRINT("generate loop, count=%ld, k=%ld, B=%ld, low_ok=%ld, high_ok=%ld",
- (long) count, (long) nc_ctx->k, (long) nc_ctx->B,
- (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
+ (long) count,
+ (long) nc_ctx->k,
+ (long) nc_ctx->B,
+ (long) nc_ctx->low_ok,
+ (long) nc_ctx->high_ok));
DUK__BI_PRINT("r", &nc_ctx->r);
DUK__BI_PRINT("s", &nc_ctx->s);
DUK__BI_PRINT("m+", &nc_ctx->mp);
DUK__BI_PRINT("m-", &nc_ctx->mm);
/* (quotient-remainder (* r B) s) using a dummy subtraction loop */
- duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, (duk_uint32_t) nc_ctx->B); /* t1 <- (* r B) */
+ duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, (duk_uint32_t) nc_ctx->B); /* t1 <- (* r B) */
d = 0;
for (;;) {
if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {
break;
}
- duk__bi_sub_copy(&nc_ctx->t1, &nc_ctx->s, &nc_ctx->t2); /* t1 <- t1 - s */
+ duk__bi_sub_copy(&nc_ctx->t1, &nc_ctx->s, &nc_ctx->t2); /* t1 <- t1 - s */
d++;
}
- duk__bi_copy(&nc_ctx->r, &nc_ctx->t1); /* r <- (remainder (* r B) s) */
- /* d <- (quotient (* r B) s) (in range 0...B-1) */
+ duk__bi_copy(&nc_ctx->r, &nc_ctx->t1); /* r <- (remainder (* r B) s) */
+ /* d <- (quotient (* r B) s) (in range 0...B-1) */
DUK_DDD(DUK_DDDPRINT("-> d(quot)=%ld", (long) d));
DUK__BI_PRINT("r(rem)", &nc_ctx->r);
@@ -83737,7 +89236,7 @@ DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {
/* free-form */
tc1 = (duk__bi_compare(&nc_ctx->r, &nc_ctx->mm) <= (nc_ctx->low_ok ? 0 : -1));
- duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 <- (+ r m+) */
+ duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 <- (+ r m+) */
tc2 = (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1));
DUK_DDD(DUK_DDDPRINT("tc1=%ld, tc2=%ld", (long) tc1, (long) tc2));
@@ -83756,20 +89255,21 @@ DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {
if (tc2) {
/* tc1 = true, tc2 = true */
duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, 2);
- if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) { /* (< (* r 2) s) */
+ if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) { /* (< (* r 2) s) */
DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r > s: output d --> %ld (k=%ld)",
- (long) d, (long) nc_ctx->k));
+ (long) d,
+ (long) nc_ctx->k));
DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
} else {
DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r <= s: output d+1 --> %ld (k=%ld)",
- (long) (d + 1), (long) nc_ctx->k));
+ (long) (d + 1),
+ (long) nc_ctx->k));
DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
}
break;
} else {
/* tc1 = true, tc2 = false */
- DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=false: output d --> %ld (k=%ld)",
- (long) d, (long) nc_ctx->k));
+ DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=false: output d --> %ld (k=%ld)", (long) d, (long) nc_ctx->k));
DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
break;
}
@@ -83777,13 +89277,13 @@ DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {
if (tc2) {
/* tc1 = false, tc2 = true */
DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=true: output d+1 --> %ld (k=%ld)",
- (long) (d + 1), (long) nc_ctx->k));
+ (long) (d + 1),
+ (long) nc_ctx->k));
DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
break;
} else {
/* tc1 = false, tc2 = false */
- DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=false: output d --> %ld (k=%ld)",
- (long) d, (long) nc_ctx->k));
+ DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=false: output d --> %ld (k=%ld)", (long) d, (long) nc_ctx->k));
DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
/* r <- r (updated above: r <- (remainder (* r B) s)
@@ -83800,23 +89300,28 @@ DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {
/* fixed-format termination conditions */
if (nc_ctx->is_fixed) {
if (nc_ctx->abs_pos) {
- int pos = nc_ctx->k - count + 1; /* count is already incremented, take into account */
+ int pos = nc_ctx->k - count + 1; /* count is already incremented, take into account */
DUK_DDD(DUK_DDDPRINT("fixed format, absolute: abs pos=%ld, k=%ld, count=%ld, req=%ld",
- (long) pos, (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
+ (long) pos,
+ (long) nc_ctx->k,
+ (long) count,
+ (long) nc_ctx->req_digits));
if (pos <= nc_ctx->req_digits) {
DUK_DDD(DUK_DDDPRINT("digit position reached req_digits, end generate loop"));
break;
}
} else {
DUK_DDD(DUK_DDDPRINT("fixed format, relative: k=%ld, count=%ld, req=%ld",
- (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
+ (long) nc_ctx->k,
+ (long) count,
+ (long) nc_ctx->req_digits));
if (count >= nc_ctx->req_digits) {
DUK_DDD(DUK_DDDPRINT("digit count reached req_digits, end generate loop"));
break;
}
}
}
- } /* for */
+ } /* for */
nc_ctx->count = count;
@@ -83826,7 +89331,7 @@ DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {
{
duk_uint8_t buf[2048];
duk_small_int_t i, t;
- DUK_MEMZERO(buf, sizeof(buf));
+ duk_memzero(buf, sizeof(buf));
for (i = 0; i < nc_ctx->count; i++) {
t = nc_ctx->digits[i];
if (t < 0 || t > 36) {
@@ -83835,8 +89340,7 @@ DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {
buf[i] = (duk_uint8_t) DUK__DIGITCHAR(t);
}
}
- DUK_DDD(DUK_DDDPRINT("-> generated digits; k=%ld, digits='%s'",
- (long) nc_ctx->k, (const char *) buf));
+ DUK_DDD(DUK_DDDPRINT("-> generated digits; k=%ld, digits='%s'", (long) nc_ctx->k, (const char *) buf));
}
#endif
}
@@ -83865,11 +89369,11 @@ DUK_LOCAL duk_small_int_t duk__dragon4_fixed_format_round(duk__numconv_stringify
if (round_idx >= nc_ctx->count) {
DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld >= %ld (count)) -> no rounding",
- (long) round_idx, (long) nc_ctx->count));
+ (long) round_idx,
+ (long) nc_ctx->count));
return 0;
} else if (round_idx < 0) {
- DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld < 0) -> no rounding",
- (long) round_idx));
+ DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld < 0) -> no rounding", (long) round_idx));
return 0;
}
@@ -83891,18 +89395,21 @@ DUK_LOCAL duk_small_int_t duk__dragon4_fixed_format_round(duk__numconv_stringify
*p = 0;
if (p == &nc_ctx->digits[0]) {
DUK_DDD(DUK_DDDPRINT("carry propagated to first digit -> special case handling"));
- DUK_MEMMOVE((void *) (&nc_ctx->digits[1]),
+ duk_memmove((void *) (&nc_ctx->digits[1]),
(const void *) (&nc_ctx->digits[0]),
(size_t) (sizeof(char) * (size_t) nc_ctx->count));
- nc_ctx->digits[0] = 1; /* don't increase 'count' */
- nc_ctx->k++; /* position of highest digit changed */
- nc_ctx->count++; /* number of digits changed */
+ nc_ctx->digits[0] = 1; /* don't increase 'count' */
+ nc_ctx->k++; /* position of highest digit changed */
+ nc_ctx->count++; /* number of digits changed */
ret = 1;
break;
}
DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry: B=%ld, roundup_limit=%ld, p=%p, digits=%p",
- (long) nc_ctx->B, (long) roundup_limit, (void *) p, (void *) nc_ctx->digits));
+ (long) nc_ctx->B,
+ (long) roundup_limit,
+ (void *) p,
+ (void *) nc_ctx->digits));
p--;
t = *p;
DUK_DDD(DUK_DDDPRINT("digit before carry: %ld", (long) t));
@@ -83919,7 +89426,7 @@ DUK_LOCAL duk_small_int_t duk__dragon4_fixed_format_round(duk__numconv_stringify
return ret;
}
-#define DUK__NO_EXP (65536) /* arbitrary marker, outside valid exp range */
+#define DUK__NO_EXP (65536) /* arbitrary marker, outside valid exp range */
DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx,
duk_hthread *thr,
@@ -83935,7 +89442,7 @@ DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx,
duk_uint8_t *buf;
/*
- * The string conversion here incorporates all the necessary Ecmascript
+ * The string conversion here incorporates all the necessary ECMAScript
* semantics without attempting to be generic. nc_ctx->digits contains
* nc_ctx->count digits (>= 1), with the topmost digit's 'position'
* indicated by nc_ctx->k as follows:
@@ -83946,11 +89453,11 @@ DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx,
* digits="123" count=3 k=-1 --> 0.0123
*
* Note that the identifier names used for format selection are different
- * in Burger-Dybvig paper and Ecmascript specification (quite confusingly
+ * in Burger-Dybvig paper and ECMAScript specification (quite confusingly
* so, because e.g. 'k' has a totally different meaning in each). See
* documentation for discussion.
*
- * Ecmascript doesn't specify any specific behavior for format selection
+ * ECMAScript doesn't specify any specific behavior for format selection
* (e.g. when to use exponent notation) for non-base-10 numbers.
*
* The bigint space in the context is reused for string output, as there
@@ -83962,7 +89469,7 @@ DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx,
DUK_ASSERT(nc_ctx->count >= 1);
k = nc_ctx->k;
- buf = (duk_uint8_t *) &nc_ctx->f; /* XXX: union would be more correct */
+ buf = (duk_uint8_t *) &nc_ctx->f; /* XXX: union would be more correct */
q = buf;
/* Exponent handling: if exponent format is used, record exponent value and
@@ -83974,14 +89481,13 @@ DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx,
expt = DUK__NO_EXP;
if (!nc_ctx->abs_pos /* toFixed() */) {
- if ((flags & DUK_N2S_FLAG_FORCE_EXP) || /* exponential notation forced */
- ((flags & DUK_N2S_FLAG_NO_ZERO_PAD) && /* fixed precision and zero padding would be required */
- (k - digits >= 1)) || /* (e.g. k=3, digits=2 -> "12X") */
- ((k > 21 || k <= -6) && (radix == 10))) { /* toString() conditions */
- DUK_DDD(DUK_DDDPRINT("use exponential notation: k=%ld -> expt=%ld",
- (long) k, (long) (k - 1)));
- expt = k - 1; /* e.g. 12.3 -> digits="123" k=2 -> 1.23e1 */
- k = 1; /* generate mantissa with a single leading whole number digit */
+ if ((flags & DUK_N2S_FLAG_FORCE_EXP) || /* exponential notation forced */
+ ((flags & DUK_N2S_FLAG_NO_ZERO_PAD) && /* fixed precision and zero padding would be required */
+ (k - digits >= 1)) || /* (e.g. k=3, digits=2 -> "12X") */
+ ((k > 21 || k <= -6) && (radix == 10))) { /* toString() conditions */
+ DUK_DDD(DUK_DDDPRINT("use exponential notation: k=%ld -> expt=%ld", (long) k, (long) (k - 1)));
+ expt = k - 1; /* e.g. 12.3 -> digits="123" k=2 -> 1.23e1 */
+ k = 1; /* generate mantissa with a single leading whole number digit */
}
}
@@ -84007,13 +89513,18 @@ DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx,
DUK_DDD(DUK_DDDPRINT("expt=%ld, k=%ld, count=%ld, pos=%ld, pos_end=%ld, is_fixed=%ld, "
"digits=%ld, abs_pos=%ld",
- (long) expt, (long) k, (long) nc_ctx->count, (long) pos, (long) pos_end,
- (long) nc_ctx->is_fixed, (long) digits, (long) nc_ctx->abs_pos));
+ (long) expt,
+ (long) k,
+ (long) nc_ctx->count,
+ (long) pos,
+ (long) pos_end,
+ (long) nc_ctx->is_fixed,
+ (long) digits,
+ (long) nc_ctx->abs_pos));
/* Digit generation */
while (pos > pos_end) {
- DUK_DDD(DUK_DDDPRINT("digit generation: pos=%ld, pos_end=%ld",
- (long) pos, (long) pos_end));
+ DUK_DDD(DUK_DDDPRINT("digit generation: pos=%ld, pos_end=%ld", (long) pos, (long) pos_end));
if (pos == 0) {
*q++ = (duk_uint8_t) '.';
}
@@ -84034,7 +89545,7 @@ DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx,
/* Exponent */
if (expt != DUK__NO_EXP) {
/*
- * Exponent notation for non-base-10 numbers isn't specified in Ecmascript
+ * Exponent notation for non-base-10 numbers isn't specified in ECMAScript
* specification, as it never explicitly turns up: non-decimal numbers can
* only be formatted with Number.prototype.toString([radix]) and for that,
* behavior is not explicitly specified.
@@ -84106,7 +89617,7 @@ DUK_LOCAL void duk__dragon4_double_to_ctx(duk__numconv_stringify_ctx *nc_ctx, du
/* normal: implicit leading 1-bit */
nc_ctx->f.v[1] |= 0x00100000UL;
expt = expt - DUK__IEEE_DOUBLE_EXP_BIAS - 52;
- DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f)); /* true, because v[1] has at least one bit set */
+ DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f)); /* true, because v[1] has at least one bit set */
}
DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));
@@ -84129,14 +89640,14 @@ DUK_LOCAL void duk__dragon4_ctx_to_double(duk__numconv_stringify_ctx *nc_ctx, du
/* Sometimes this assert is not true right now; it will be true after
* rounding. See: test-bug-numconv-mantissa-assert.js.
*/
- DUK_ASSERT_DISABLE(nc_ctx->digits[0] == 1); /* zero handled by caller */
+ DUK_ASSERT_DISABLE(nc_ctx->digits[0] == 1); /* zero handled by caller */
/* Should not be required because the code below always sets both high
* and low parts, but at least gcc-4.4.5 fails to deduce this correctly
* (perhaps because the low part is set (seemingly) conditionally in a
* loop), so this is here to avoid the bogus warning.
*/
- DUK_MEMZERO((void *) &u, sizeof(u));
+ duk_memzero((void *) &u, sizeof(u));
/*
* Figure out how generated digits match up with the mantissa,
@@ -84174,31 +89685,30 @@ DUK_LOCAL void duk__dragon4_ctx_to_double(duk__numconv_stringify_ctx *nc_ctx, du
skip_round = 0;
- recheck_exp:
+recheck_exp:
- expt = nc_ctx->k - 1; /* IEEE exp without bias */
+ expt = nc_ctx->k - 1; /* IEEE exp without bias */
if (expt > 1023) {
/* Infinity */
- bitstart = -255; /* needed for inf: causes mantissa to become zero,
- * and rounding to be skipped.
- */
+ bitstart = -255; /* needed for inf: causes mantissa to become zero,
+ * and rounding to be skipped.
+ */
expt = 2047;
} else if (expt >= -1022) {
/* normal */
- bitstart = 1; /* skip leading digit */
+ bitstart = 1; /* skip leading digit */
expt += DUK__IEEE_DOUBLE_EXP_BIAS;
DUK_ASSERT(expt >= 1 && expt <= 2046);
} else {
/* denormal or zero */
- bitstart = 1023 + expt; /* expt==-1023 -> bitstart=0 (leading 1);
- * expt==-1024 -> bitstart=-1 (one left of leading 1), etc
- */
+ bitstart = 1023 + expt; /* expt==-1023 -> bitstart=0 (leading 1);
+ * expt==-1024 -> bitstart=-1 (one left of leading 1), etc
+ */
expt = 0;
}
bitround = bitstart + 52;
- DUK_DDD(DUK_DDDPRINT("ieee expt=%ld, bitstart=%ld, bitround=%ld",
- (long) expt, (long) bitstart, (long) bitround));
+ DUK_DDD(DUK_DDDPRINT("ieee expt=%ld, bitstart=%ld, bitround=%ld", (long) expt, (long) bitstart, (long) bitround));
if (!skip_round) {
if (duk__dragon4_fixed_format_round(nc_ctx, bitround)) {
@@ -84236,13 +89746,11 @@ DUK_LOCAL void duk__dragon4_ctx_to_double(duk__numconv_stringify_ctx *nc_ctx, du
}
/* t has high mantissa */
- DUK_DDD(DUK_DDDPRINT("mantissa is complete: %08lx %08lx",
- (unsigned long) t,
- (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
+ DUK_DDD(DUK_DDDPRINT("mantissa is complete: %08lx %08lx", (unsigned long) t, (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
DUK_ASSERT(expt >= 0 && expt <= 0x7ffL);
t += ((duk_uint32_t) expt) << 20;
-#if 0 /* caller handles sign change */
+#if 0 /* caller handles sign change */
if (negative) {
t |= 0x80000000U;
}
@@ -84263,12 +89771,15 @@ DUK_LOCAL void duk__dragon4_ctx_to_double(duk__numconv_stringify_ctx *nc_ctx, du
* Output: [ string ]
*/
-DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags) {
+DUK_LOCAL DUK_NOINLINE void duk__numconv_stringify_raw(duk_hthread *thr,
+ duk_small_int_t radix,
+ duk_small_int_t digits,
+ duk_small_uint_t flags) {
duk_double_t x;
duk_small_int_t c;
duk_small_int_t neg;
duk_uint32_t uval;
- duk__numconv_stringify_ctx nc_ctx_alloc; /* large context; around 2kB now */
+ duk__numconv_stringify_ctx nc_ctx_alloc; /* large context; around 2kB now */
duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
x = (duk_double_t) duk_require_number(thr, -1);
@@ -84319,14 +89830,14 @@ DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix,
* sprintf "%lu" for the fast path and for exponent formatting.
*/
- uval = (unsigned int) x;
- if (((double) uval) == x && /* integer number in range */
- flags == 0) { /* no special formatting */
+ uval = duk_double_to_uint32_t(x);
+ if (duk_double_equals((double) uval, x) && /* integer number in range */
+ flags == 0) { /* no special formatting */
/* use bigint area as a temp */
duk_uint8_t *buf = (duk_uint8_t *) (&nc_ctx->f);
duk_uint8_t *p = buf;
- DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= 32 + 1); /* max size: radix=2 + sign */
+ DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= 32 + 1); /* max size: radix=2 + sign */
if (neg && uval != 0) {
/* no negative sign for zero */
*p++ = (duk_uint8_t) '-';
@@ -84351,7 +89862,7 @@ DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix,
* is 1-2 kilobytes and nothing should rely on it being zeroed.
*/
#if 0
- DUK_MEMZERO((void *) nc_ctx, sizeof(*nc_ctx)); /* slow init, do only for slow path cases */
+ duk_memzero((void *) nc_ctx, sizeof(*nc_ctx)); /* slow init, do only for slow path cases */
#endif
nc_ctx->is_s2n = 0;
@@ -84382,23 +89893,23 @@ DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix,
duk_small_int_t count;
if (nc_ctx->is_fixed) {
if (nc_ctx->abs_pos) {
- count = digits + 2; /* lead zero + 'digits' fractions + 1 for rounding */
+ count = digits + 2; /* lead zero + 'digits' fractions + 1 for rounding */
} else {
- count = digits + 1; /* + 1 for rounding */
+ count = digits + 1; /* + 1 for rounding */
}
} else {
count = 1;
}
DUK_DDD(DUK_DDDPRINT("count=%ld", (long) count));
DUK_ASSERT(count >= 1);
- DUK_MEMZERO((void *) nc_ctx->digits, (size_t) count);
+ duk_memzero((void *) nc_ctx->digits, (size_t) count);
nc_ctx->count = count;
- nc_ctx->k = 1; /* 0.000... */
+ nc_ctx->k = 1; /* 0.000... */
neg = 0;
goto zero_skip;
}
- duk__dragon4_double_to_ctx(nc_ctx, x); /* -> sets 'f' and 'e' */
+ duk__dragon4_double_to_ctx(nc_ctx, x); /* -> sets 'f' and 'e' */
DUK__BI_PRINT("f", &nc_ctx->f);
DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
@@ -84406,7 +89917,7 @@ DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix,
* Dragon4 slow path digit generation.
*/
- duk__dragon4_prepare(nc_ctx); /* setup many variables in nc_ctx */
+ duk__dragon4_prepare(nc_ctx); /* setup many variables in nc_ctx */
DUK_DDD(DUK_DDDPRINT("after prepare:"));
DUK__BI_PRINT("r", &nc_ctx->r);
@@ -84428,7 +89939,7 @@ DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix,
* Convert and push final string.
*/
- zero_skip:
+zero_skip:
if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
/* Perform fixed-format rounding. */
@@ -84437,13 +89948,16 @@ DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix,
/* 'roundpos' is relative to nc_ctx->k and increases to the right
* (opposite of how 'k' changes).
*/
- roundpos = -digits; /* absolute position for digit considered for rounding */
+ roundpos = -digits; /* absolute position for digit considered for rounding */
roundpos = nc_ctx->k - roundpos;
} else {
roundpos = digits;
}
DUK_DDD(DUK_DDDPRINT("rounding: k=%ld, count=%ld, digits=%ld, roundpos=%ld",
- (long) nc_ctx->k, (long) nc_ctx->count, (long) digits, (long) roundpos));
+ (long) nc_ctx->k,
+ (long) nc_ctx->count,
+ (long) digits,
+ (long) roundpos));
(void) duk__dragon4_fixed_format_round(nc_ctx, roundpos);
/* Note: 'count' is currently not adjusted by rounding (i.e. the
@@ -84456,6 +89970,11 @@ DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix,
duk__dragon4_convert_and_push(nc_ctx, thr, radix, digits, flags, neg);
}
+DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags) {
+ duk_native_stack_check(thr);
+ duk__numconv_stringify_raw(thr, radix, digits, flags);
+}
+
/*
* Exposed string-to-number API
*
@@ -84466,13 +89985,13 @@ DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix,
* fails due to an internal error, an InternalError is thrown.
*/
-DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags) {
- duk__numconv_stringify_ctx nc_ctx_alloc; /* large context; around 2kB now */
+DUK_LOCAL DUK_NOINLINE void duk__numconv_parse_raw(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags) {
+ duk__numconv_stringify_ctx nc_ctx_alloc; /* large context; around 2kB now */
duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
duk_double_t res;
duk_hstring *h_str;
- duk_small_int_t expt;
- duk_small_int_t expt_neg;
+ duk_int_t expt;
+ duk_bool_t expt_neg;
duk_small_int_t expt_adj;
duk_small_int_t neg;
duk_small_int_t dig;
@@ -84487,7 +90006,8 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk
DUK_DDD(DUK_DDDPRINT("parse number: %!T, radix=%ld, flags=0x%08lx",
(duk_tval *) duk_get_tval(thr, -1),
- (long) radix, (unsigned long) flags));
+ (long) radix,
+ (unsigned long) flags));
DUK_ASSERT(radix >= 2 && radix <= 36);
DUK_ASSERT(radix - 2 < (duk_small_int_t) sizeof(duk__str2num_digits_for_radix));
@@ -84560,7 +90080,7 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk
ch = *p;
if (ch == (duk_small_int_t) '0') {
duk_small_int_t detect_radix = 0;
- ch = DUK_LOWERCASE_CHAR_ASCII(p[1]); /* 'x' or 'X' -> 'x' */
+ ch = DUK_LOWERCASE_CHAR_ASCII(p[1]); /* 'x' or 'X' -> 'x' */
if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT) && ch == DUK_ASC_LC_X) {
DUK_DDD(DUK_DDDPRINT("detected 0x/0X hex prefix, changing radix and preventing fractions and exponent"));
detect_radix = 16;
@@ -84587,10 +90107,9 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk
if (detect_radix > 0) {
radix = detect_radix;
/* Clear empty as zero flag: interpret e.g. '0x' and '0xg' as a NaN (= parse error) */
- flags &= ~(DUK_S2N_FLAG_ALLOW_EXP | DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
- DUK_S2N_FLAG_ALLOW_FRAC | DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
- DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO);
- flags |= DUK_S2N_FLAG_ALLOW_LEADING_ZERO; /* allow e.g. '0x0009' and '0b00010001' */
+ flags &= ~(DUK_S2N_FLAG_ALLOW_EXP | DUK_S2N_FLAG_ALLOW_EMPTY_FRAC | DUK_S2N_FLAG_ALLOW_FRAC |
+ DUK_S2N_FLAG_ALLOW_NAKED_FRAC | DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO);
+ flags |= DUK_S2N_FLAG_ALLOW_LEADING_ZERO; /* allow e.g. '0x0009' and '0b00010001' */
p += 2;
}
}
@@ -84608,7 +90127,7 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk
* accuracy, so that Dragon4 will generate enough binary output digits.
* For decimal numbers, this means generating a 20-digit significand,
* which should yield enough practical accuracy to parse IEEE doubles.
- * In fact, the Ecmascript specification explicitly allows an
+ * In fact, the ECMAScript specification explicitly allows an
* implementation to treat digits beyond 20 as zeroes (and even
* to round the 20th digit upwards). For non-decimal numbers, the
* appropriate number of digits has been precomputed for comparable
@@ -84648,16 +90167,23 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk
dig_frac = -1;
dig_expt = -1;
expt = 0;
- expt_adj = 0; /* essentially tracks digit position of lowest 'f' digit */
+ expt_adj = 0; /* essentially tracks digit position of lowest 'f' digit */
expt_neg = 0;
for (;;) {
ch = *p++;
DUK_DDD(DUK_DDDPRINT("parse digits: p=%p, ch='%c' (%ld), expt=%ld, expt_adj=%ld, "
"dig_whole=%ld, dig_frac=%ld, dig_expt=%ld, dig_lzero=%ld, dig_prec=%ld",
- (const void *) p, (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : '?'), (long) ch,
- (long) expt, (long) expt_adj, (long) dig_whole, (long) dig_frac,
- (long) dig_expt, (long) dig_lzero, (long) dig_prec));
+ (const void *) p,
+ (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : '?'),
+ (long) ch,
+ (long) expt,
+ (long) expt_adj,
+ (long) dig_whole,
+ (long) dig_frac,
+ (long) dig_expt,
+ (long) dig_lzero,
+ (long) dig_prec));
DUK__BI_PRINT("f", &nc_ctx->f);
/* Most common cases first. */
@@ -84696,8 +90222,8 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk
} else if (ch == (duk_small_int_t) 0) {
DUK_DDD(DUK_DDDPRINT("NUL termination"));
break;
- } else if ((flags & DUK_S2N_FLAG_ALLOW_EXP) &&
- dig_expt < 0 && (ch == (duk_small_int_t) 'e' || ch == (duk_small_int_t) 'E')) {
+ } else if ((flags & DUK_S2N_FLAG_ALLOW_EXP) && dig_expt < 0 &&
+ (ch == (duk_small_int_t) 'e' || ch == (duk_small_int_t) 'E')) {
/* Note: we don't parse back exponent notation for anything else
* than radix 10, so this is not an ambiguous check (e.g. hex
* exponent values may have 'e' either as a significand digit
@@ -84727,7 +90253,7 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk
} else if (ch >= (duk_small_int_t) 'A' && ch <= (duk_small_int_t) 'Z') {
dig = (duk_small_int_t) (ch - (duk_small_int_t) 'A' + 0x0a);
} else {
- dig = 255; /* triggers garbage digit check below */
+ dig = 255; /* triggers garbage digit check below */
}
DUK_ASSERT((dig >= 0 && dig <= 35) || dig == 255);
@@ -84779,9 +90305,10 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk
} else {
/* exponent digit */
+ DUK_ASSERT(radix == 10);
expt = expt * radix + dig;
if (expt > DUK_S2N_MAX_EXPONENT) {
- /* impose a reasonable exponent limit, so that exp
+ /* Impose a reasonable exponent limit, so that exp
* doesn't need to get tracked using a bigint.
*/
DUK_DDD(DUK_DDDPRINT("parse failed: exponent too large"));
@@ -84815,10 +90342,17 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk
goto parse_fail;
}
} else {
- /* empty ("") is allowed in some formats (e.g. Number(''), as zero */
+ /* Empty ("") is allowed in some formats (e.g. Number(''), as zero,
+ * but it must not have a leading +/- sign (GH-2019). Note that
+ * for Number(), h_str is already trimmed so we can check for zero
+ * length and still get Number(' + ') == NaN.
+ */
if ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO) == 0) {
DUK_DDD(DUK_DDDPRINT("parse failed: empty string not allowed (as zero)"));
goto parse_fail;
+ } else if (DUK_HSTRING_GET_BYTELEN(h_str) != 0) {
+ DUK_DDD(DUK_DDDPRINT("parse failed: no digits, but not empty (had a +/- sign)"));
+ goto parse_fail;
}
}
} else {
@@ -84852,14 +90386,14 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk
if (expt_neg) {
expt = -expt;
}
- DUK_DDD(DUK_DDDPRINT("expt=%ld, expt_adj=%ld, net exponent -> %ld",
- (long) expt, (long) expt_adj, (long) (expt + expt_adj)));
+ DUK_DDD(
+ DUK_DDDPRINT("expt=%ld, expt_adj=%ld, net exponent -> %ld", (long) expt, (long) expt_adj, (long) (expt + expt_adj)));
expt += expt_adj;
/* Fast path check. */
- if (nc_ctx->f.n <= 1 && /* 32-bit value */
- expt == 0 /* no net exponent */) {
+ if (nc_ctx->f.n <= 1 && /* 32-bit value */
+ expt == 0 /* no net exponent */) {
/* Fast path is triggered for no exponent and also for balanced exponent
* and fraction parts, e.g. for "1.23e2" == "123". Remember to respect
* zero sign.
@@ -84901,7 +90435,6 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk
goto negcheck_and_ret;
}
-
/* Quick reject of too large or too small exponents. This check
* would be incorrect for zero (e.g. "0e1000" is zero, not Infinity)
* so zero check must be above.
@@ -84934,7 +90467,7 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk
* An extra digit is generated for rounding.
*/
- duk__dragon4_prepare(nc_ctx); /* setup many variables in nc_ctx */
+ duk__dragon4_prepare(nc_ctx); /* setup many variables in nc_ctx */
DUK_DDD(DUK_DDDPRINT("after prepare:"));
DUK__BI_PRINT("r", &nc_ctx->r);
@@ -84966,7 +90499,7 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk
duk__dragon4_ctx_to_double(nc_ctx, &res);
goto negcheck_and_ret;
- negcheck_and_ret:
+negcheck_and_ret:
if (neg) {
res = -res;
}
@@ -84975,16 +90508,21 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk
DUK_DDD(DUK_DDDPRINT("result: %!T", (duk_tval *) duk_get_tval(thr, -1)));
return;
- parse_fail:
+parse_fail:
DUK_DDD(DUK_DDDPRINT("parse failed"));
duk_pop(thr);
duk_push_nan(thr);
return;
- parse_explimit_error:
+parse_explimit_error:
DUK_DDD(DUK_DDDPRINT("parse failed, internal error, can't return a value"));
DUK_ERROR_RANGE(thr, "exponent too large");
- return;
+ DUK_WO_NORETURN(return;);
+}
+
+DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags) {
+ duk_native_stack_check(thr);
+ duk__numconv_parse_raw(thr, radix, flags);
}
/* automatic undefs */
@@ -85029,8 +90567,7 @@ DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk
#define DUK__RE_INITIAL_BUFSIZE 64
-#define DUK__RE_BUFLEN(re_ctx) \
- DUK_BW_GET_SIZE(re_ctx->thr, &re_ctx->bw)
+#define DUK__RE_BUFLEN(re_ctx) DUK_BW_GET_SIZE(re_ctx->thr, &re_ctx->bw)
/*
* Disjunction struct: result of parsing a disjunction
@@ -85120,7 +90657,7 @@ DUK_LOCAL void duk__append_reop(duk_re_compiler_ctx *re_ctx, duk_uint32_t reop)
(void) duk__append_7bit(re_ctx, reop);
}
-#if 0 /* unused */
+#if 0 /* unused */
DUK_LOCAL void duk__append_i32(duk_re_compiler_ctx *re_ctx, duk_int32_t x) {
duk__append_u32(re_ctx, duk__encode_i32(x));
}
@@ -85134,7 +90671,10 @@ DUK_LOCAL void duk__append_u16_list(duk_re_compiler_ctx *re_ctx, const duk_uint1
}
}
-DUK_LOCAL void duk__insert_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t data_offset, duk_uint32_t data_length) {
+DUK_LOCAL void duk__insert_slice(duk_re_compiler_ctx *re_ctx,
+ duk_uint32_t offset,
+ duk_uint32_t data_offset,
+ duk_uint32_t data_length) {
DUK_BW_INSERT_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, offset, data_offset, data_length);
}
@@ -85197,7 +90737,7 @@ DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_
skip--;
}
}
-#else /* DUK_USE_PREFER_SIZE */
+#else /* DUK_USE_PREFER_SIZE */
/* Closed form solution, this produces fastest code.
* See re_neg_jump_offset (closed1).
*/
@@ -85218,7 +90758,7 @@ DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_
skip -= 7;
}
}
-#endif /* DUK_USE_PREFER_SIZE */
+#endif /* DUK_USE_PREFER_SIZE */
return duk__insert_i32(re_ctx, offset, skip);
}
@@ -85351,10 +90891,10 @@ DUK_LOCAL duk_codepoint_t duk__re_canon_next_discontinuity(duk_codepoint_t start
}
}
}
- DUK_ASSERT(blk == end_blk + 1); /* Reached end block which is continuous. */
+ DUK_ASSERT(blk == end_blk + 1); /* Reached end block which is continuous. */
return end;
}
-#else /* DUK_USE_REGEXP_CANON_BITMAP */
+#else /* DUK_USE_REGEXP_CANON_BITMAP */
DUK_LOCAL duk_codepoint_t duk__re_canon_next_discontinuity(duk_codepoint_t start, duk_codepoint_t end) {
DUK_ASSERT(start >= 0);
DUK_ASSERT(end >= 0);
@@ -85365,7 +90905,7 @@ DUK_LOCAL duk_codepoint_t duk__re_canon_next_discontinuity(duk_codepoint_t start
}
return start;
}
-#endif /* DUK_USE_REGEXP_CANON_BITMAP */
+#endif /* DUK_USE_REGEXP_CANON_BITMAP */
DUK_LOCAL void duk__regexp_generate_ranges(void *userdata, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct) {
duk_re_compiler_ctx *re_ctx = (duk_re_compiler_ctx *) userdata;
@@ -85376,9 +90916,12 @@ DUK_LOCAL void duk__regexp_generate_ranges(void *userdata, duk_codepoint_t r1, d
duk_codepoint_t r_disc;
DUK_DD(DUK_DDPRINT("duk__regexp_generate_ranges(): re_ctx=%p, range=[%ld,%ld] direct=%ld",
- (void *) re_ctx, (long) r1, (long) r2, (long) direct));
+ (void *) re_ctx,
+ (long) r1,
+ (long) r2,
+ (long) direct));
- DUK_ASSERT(r2 >= r1); /* SyntaxError for out of order range. */
+ DUK_ASSERT(r2 >= r1); /* SyntaxError for out of order range. */
if (direct || (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) == 0) {
DUK_DD(DUK_DDPRINT("direct or not case sensitive, emit range: [%ld,%ld]", (long) r1, (long) r2));
@@ -85400,7 +90943,7 @@ DUK_LOCAL void duk__regexp_generate_ranges(void *userdata, duk_codepoint_t r1, d
DUK_ASSERT(r_disc >= i);
DUK_ASSERT(r_disc <= r2);
- r_end += r_disc - i; /* May be zero. */
+ r_end += r_disc - i; /* May be zero. */
t = duk_unicode_re_canonicalize_char(re_ctx->thr, r_disc);
if (t == r_end + 1) {
/* Not actually a discontinuity, continue range
@@ -85412,11 +90955,11 @@ DUK_LOCAL void duk__regexp_generate_ranges(void *userdata, duk_codepoint_t r1, d
r_start = t;
r_end = t;
}
- i = r_disc + 1; /* Guarantees progress. */
+ i = r_disc + 1; /* Guarantees progress. */
}
duk__regexp_emit_range(re_ctx, r_start, r_end);
-#if 0 /* Exhaustive search, very slow. */
+#if 0 /* Exhaustive search, very slow. */
r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
r_end = r_start;
for (i = r1 + 1; i <= r2; i++) {
@@ -85489,18 +91032,17 @@ DUK_LOCAL void duk__regexp_generate_ranges(void *userdata, duk_codepoint_t r1, d
* as complex though.
*/
-DUK_LOCAL const duk_uint16_t * const duk__re_range_lookup1[3] = {
- duk_unicode_re_ranges_digit,
- duk_unicode_re_ranges_white,
- duk_unicode_re_ranges_wordchar
-};
-DUK_LOCAL const duk_uint8_t duk__re_range_lookup2[3] = {
- sizeof(duk_unicode_re_ranges_digit) / (2 * sizeof(duk_uint16_t)),
- sizeof(duk_unicode_re_ranges_white) / (2 * sizeof(duk_uint16_t)),
- sizeof(duk_unicode_re_ranges_wordchar) / (2 * sizeof(duk_uint16_t))
-};
+DUK_LOCAL const duk_uint16_t * const duk__re_range_lookup1[3] = { duk_unicode_re_ranges_digit,
+ duk_unicode_re_ranges_white,
+ duk_unicode_re_ranges_wordchar };
+DUK_LOCAL const duk_uint8_t duk__re_range_lookup2[3] = { sizeof(duk_unicode_re_ranges_digit) / (2 * sizeof(duk_uint16_t)),
+ sizeof(duk_unicode_re_ranges_white) / (2 * sizeof(duk_uint16_t)),
+ sizeof(duk_unicode_re_ranges_wordchar) / (2 * sizeof(duk_uint16_t)) };
-DUK_LOCAL void duk__append_range_atom_matcher(duk_re_compiler_ctx *re_ctx, duk_small_uint_t re_op, const duk_uint16_t *ranges, duk_small_uint_t count) {
+DUK_LOCAL void duk__append_range_atom_matcher(duk_re_compiler_ctx *re_ctx,
+ duk_small_uint_t re_op,
+ const duk_uint16_t *ranges,
+ duk_small_uint_t count) {
#if 0
DUK_ASSERT(re_op <= 0x7fUL);
DUK_ASSERT(count <= 0x7fUL);
@@ -85512,19 +91054,21 @@ DUK_LOCAL void duk__append_range_atom_matcher(duk_re_compiler_ctx *re_ctx, duk_s
}
DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t expect_eof, duk__re_disjunction_info *out_atom_info) {
- duk_int32_t atom_start_offset = -1; /* negative -> no atom matched on previous round */
- duk_int32_t atom_char_length = 0; /* negative -> complex atom */
- duk_uint32_t atom_start_captures = re_ctx->captures; /* value of re_ctx->captures at start of atom */
+ duk_int32_t atom_start_offset = -1; /* negative -> no atom matched on previous round */
+ duk_int32_t atom_char_length = 0; /* negative -> complex atom */
+ duk_uint32_t atom_start_captures = re_ctx->captures; /* value of re_ctx->captures at start of atom */
duk_int32_t unpatched_disjunction_split = -1;
duk_int32_t unpatched_disjunction_jump = -1;
duk_uint32_t entry_offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
- duk_int32_t res_charlen = 0; /* -1 if disjunction is complex, char length if simple */
+ duk_int32_t res_charlen = 0; /* -1 if disjunction is complex, char length if simple */
duk__re_disjunction_info tmp_disj;
DUK_ASSERT(out_atom_info != NULL);
+ duk_native_stack_check(re_ctx->thr);
if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT);
+ DUK_WO_NORETURN(return;);
}
re_ctx->recursion_depth++;
@@ -85539,19 +91083,19 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
* new_atom_char_length etc are for the atom parsed on this round;
* they're written to atom_char_length etc at the end of the round.
*/
- duk_int32_t new_atom_char_length; /* char length of the atom parsed in this loop */
- duk_int32_t new_atom_start_offset; /* bytecode start offset of the atom parsed in this loop
- * (allows quantifiers to copy the atom bytecode)
- */
- duk_uint32_t new_atom_start_captures; /* re_ctx->captures at the start of the atom parsed in this loop */
+ duk_int32_t new_atom_char_length; /* char length of the atom parsed in this loop */
+ duk_int32_t new_atom_start_offset; /* bytecode start offset of the atom parsed in this loop
+ * (allows quantifiers to copy the atom bytecode)
+ */
+ duk_uint32_t new_atom_start_captures; /* re_ctx->captures at the start of the atom parsed in this loop */
duk_lexer_parse_re_token(&re_ctx->lex, &re_ctx->curr_token);
- DUK_DD(DUK_DDPRINT("re token: %ld (num=%ld, char=%c)",
- (long) re_ctx->curr_token.t,
- (long) re_ctx->curr_token.num,
- (re_ctx->curr_token.num >= 0x20 && re_ctx->curr_token.num <= 0x7e) ?
- (int) re_ctx->curr_token.num : (int) '?'));
+ DUK_DD(DUK_DDPRINT(
+ "re token: %ld (num=%ld, char=%c)",
+ (long) re_ctx->curr_token.t,
+ (long) re_ctx->curr_token.num,
+ (re_ctx->curr_token.num >= 0x20 && re_ctx->curr_token.num <= 0x7e) ? (int) re_ctx->curr_token.num : (int) '?'));
/* set by atom case clauses */
new_atom_start_offset = -1;
@@ -85572,9 +91116,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
DUK_ASSERT(unpatched_disjunction_split >= 0);
offset = (duk_uint32_t) unpatched_disjunction_jump;
- offset += duk__insert_jump_offset(re_ctx,
- offset,
- (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
+ offset += duk__insert_jump_offset(re_ctx, offset, (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
/* offset is now target of the pending split (right after jump) */
duk__insert_jump_offset(re_ctx,
(duk_uint32_t) unpatched_disjunction_split,
@@ -85582,10 +91124,8 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
}
/* add a new pending split to the beginning of the entire disjunction */
- (void) duk__insert_u32(re_ctx,
- entry_offset,
- DUK_REOP_SPLIT1); /* prefer direct execution */
- unpatched_disjunction_split = (duk_int32_t) (entry_offset + 1); /* +1 for opcode */
+ (void) duk__insert_u32(re_ctx, entry_offset, DUK_REOP_SPLIT1); /* prefer direct execution */
+ unpatched_disjunction_split = (duk_int32_t) (entry_offset + 1); /* +1 for opcode */
/* add a new pending match jump for latest finished alternative */
duk__append_reop(re_ctx, DUK_REOP_JUMP);
@@ -85598,9 +91138,11 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
case DUK_RETOK_QUANTIFIER: {
if (atom_start_offset < 0) {
DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_NO_ATOM);
+ DUK_WO_NORETURN(return;);
}
if (re_ctx->curr_token.qmin > re_ctx->curr_token.qmax) {
DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_VALUES);
+ DUK_WO_NORETURN(return;);
}
if (atom_char_length >= 0) {
/*
@@ -85631,7 +91173,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
}
}
- duk__append_reop(re_ctx, DUK_REOP_MATCH); /* complete 'sub atom' */
+ duk__append_reop(re_ctx, DUK_REOP_MATCH); /* complete 'sub atom' */
atom_code_length = (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (duk_size_t) atom_start_offset);
offset = (duk_uint32_t) atom_start_offset;
@@ -85647,7 +91189,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
offset += duk__insert_u32(re_ctx, offset, qmax);
offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
}
- DUK_UNREF(offset); /* silence scan-build warning */
+ DUK_UNREF(offset); /* silence scan-build warning */
} else {
/*
* Complex atom
@@ -85665,10 +91207,11 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
duk_uint32_t tmp_qmin, tmp_qmax;
/* pre-check how many atom copies we're willing to make (atom_copies not needed below) */
- atom_copies = (re_ctx->curr_token.qmax == DUK_RE_QUANTIFIER_INFINITE) ?
- re_ctx->curr_token.qmin : re_ctx->curr_token.qmax;
+ atom_copies = (re_ctx->curr_token.qmax == DUK_RE_QUANTIFIER_INFINITE) ? re_ctx->curr_token.qmin :
+ re_ctx->curr_token.qmax;
if (atom_copies > DUK_RE_MAX_ATOM_COPIES) {
DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_QUANTIFIER_TOO_MANY_COPIES);
+ DUK_WO_NORETURN(return;);
}
/* wipe the capture range made by the atom (if any) */
@@ -85676,15 +91219,19 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
if (atom_start_captures != re_ctx->captures) {
DUK_ASSERT(atom_start_captures < re_ctx->captures);
DUK_DDD(DUK_DDDPRINT("must wipe ]atom_start_captures,re_ctx->captures]: ]%ld,%ld]",
- (long) atom_start_captures, (long) re_ctx->captures));
+ (long) atom_start_captures,
+ (long) re_ctx->captures));
/* insert (DUK_REOP_WIPERANGE, start, count) in reverse order so the order ends up right */
- duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, (re_ctx->captures - atom_start_captures) * 2U);
+ duk__insert_u32(re_ctx,
+ (duk_uint32_t) atom_start_offset,
+ (re_ctx->captures - atom_start_captures) * 2U);
duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, (atom_start_captures + 1) * 2);
duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, DUK_REOP_WIPERANGE);
} else {
- DUK_DDD(DUK_DDDPRINT("no need to wipe captures: atom_start_captures == re_ctx->captures == %ld",
- (long) atom_start_captures));
+ DUK_DDD(
+ DUK_DDDPRINT("no need to wipe captures: atom_start_captures == re_ctx->captures == %ld",
+ (long) atom_start_captures));
}
atom_code_length = (duk_int32_t) DUK__RE_BUFLEN(re_ctx) - atom_start_offset;
@@ -85693,7 +91240,9 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
tmp_qmin = re_ctx->curr_token.qmin;
tmp_qmax = re_ctx->curr_token.qmax;
while (tmp_qmin > 0) {
- duk__append_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
+ duk__append_slice(re_ctx,
+ (duk_uint32_t) atom_start_offset,
+ (duk_uint32_t) atom_code_length);
tmp_qmin--;
if (tmp_qmax != DUK_RE_QUANTIFIER_INFINITE) {
tmp_qmax--;
@@ -85711,14 +91260,16 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
*/
duk__append_reop(re_ctx, DUK_REOP_JUMP);
duk__append_jump_offset(re_ctx, atom_code_length);
- duk__append_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
+ duk__append_slice(re_ctx,
+ (duk_uint32_t) atom_start_offset,
+ (duk_uint32_t) atom_code_length);
}
if (re_ctx->curr_token.greedy) {
- duk__append_reop(re_ctx, DUK_REOP_SPLIT2); /* prefer jump */
+ duk__append_reop(re_ctx, DUK_REOP_SPLIT2); /* prefer jump */
} else {
- duk__append_reop(re_ctx, DUK_REOP_SPLIT1); /* prefer direct */
+ duk__append_reop(re_ctx, DUK_REOP_SPLIT1); /* prefer direct */
}
- duk__append_jump_offset(re_ctx, -atom_code_length - 1); /* -1 for opcode */
+ duk__append_jump_offset(re_ctx, -atom_code_length - 1); /* -1 for opcode */
} else {
/*
* The remaining matches are emitted as sequence of SPLITs and atom
@@ -85738,14 +91289,17 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
*/
duk_uint32_t offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
while (tmp_qmax > 0) {
- duk__insert_slice(re_ctx, offset, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
+ duk__insert_slice(re_ctx,
+ offset,
+ (duk_uint32_t) atom_start_offset,
+ (duk_uint32_t) atom_code_length);
if (re_ctx->curr_token.greedy) {
- duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT1); /* prefer direct */
+ duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT1); /* prefer direct */
} else {
- duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT2); /* prefer jump */
+ duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT2); /* prefer jump */
}
duk__insert_jump_offset(re_ctx,
- offset + 1, /* +1 for opcode */
+ offset + 1, /* +1 for opcode */
(duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
tmp_qmax--;
}
@@ -85778,8 +91332,8 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
case DUK_RETOK_ASSERT_START_POS_LOOKAHEAD:
case DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD: {
duk_uint32_t offset;
- duk_uint32_t opcode = (re_ctx->curr_token.t == DUK_RETOK_ASSERT_START_POS_LOOKAHEAD) ?
- DUK_REOP_LOOKPOS : DUK_REOP_LOOKNEG;
+ duk_uint32_t opcode =
+ (re_ctx->curr_token.t == DUK_RETOK_ASSERT_START_POS_LOOKAHEAD) ? DUK_REOP_LOOKPOS : DUK_REOP_LOOKNEG;
offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
duk__parse_disjunction(re_ctx, 0, &tmp_disj);
@@ -85787,7 +91341,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
(void) duk__insert_u32(re_ctx, offset, opcode);
(void) duk__insert_jump_offset(re_ctx,
- offset + 1, /* +1 for opcode */
+ offset + 1, /* +1 for opcode */
(duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
/* 'taint' result as complex -- this is conservative,
@@ -85848,7 +91402,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
DUK_ASSERT(DUK_RETOK_ATOM_WHITE == DUK_RETOK_ATOM_DIGIT + 2);
DUK_ASSERT(DUK_RETOK_ATOM_WORD_CHAR == DUK_RETOK_ATOM_DIGIT + 4);
idx = (duk_small_uint_t) ((re_ctx->curr_token.t - DUK_RETOK_ATOM_DIGIT) >> 1U);
- DUK_ASSERT(idx <= 2U); /* Assume continuous token numbers; also checks negative underflow. */
+ DUK_ASSERT(idx <= 2U); /* Assume continuous token numbers; also checks negative underflow. */
duk__append_range_atom_matcher(re_ctx, re_op, duk__re_range_lookup1[idx], duk__re_range_lookup2[idx]);
break;
@@ -85858,7 +91412,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
if (backref > re_ctx->highest_backref) {
re_ctx->highest_backref = backref;
}
- new_atom_char_length = -1; /* mark as complex */
+ new_atom_char_length = -1; /* mark as complex */
new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
duk__append_reop(re_ctx, DUK_REOP_BACKREFERENCE);
duk__append_u32(re_ctx, backref);
@@ -85867,12 +91421,14 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
case DUK_RETOK_ATOM_START_CAPTURE_GROUP: {
duk_uint32_t cap;
- new_atom_char_length = -1; /* mark as complex (capture handling) */
+ new_atom_char_length = -1; /* mark as complex (capture handling) */
new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
cap = ++re_ctx->captures;
duk__append_reop(re_ctx, DUK_REOP_SAVE);
duk__append_u32(re_ctx, cap * 2);
- duk__parse_disjunction(re_ctx, 0, &tmp_disj); /* retval (sub-atom char length) unused, tainted as complex above */
+ duk__parse_disjunction(re_ctx,
+ 0,
+ &tmp_disj); /* retval (sub-atom char length) unused, tainted as complex above */
duk__append_reop(re_ctx, DUK_REOP_SAVE);
duk__append_u32(re_ctx, cap * 2 + 1);
break;
@@ -85917,12 +91473,12 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
new_atom_char_length = 1;
new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
duk__append_reop(re_ctx,
- (re_ctx->curr_token.t == DUK_RETOK_ATOM_START_CHARCLASS) ?
- DUK_REOP_RANGES : DUK_REOP_INVRANGES);
- offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx); /* patch in range count later */
+ (re_ctx->curr_token.t == DUK_RETOK_ATOM_START_CHARCLASS) ? DUK_REOP_RANGES :
+ DUK_REOP_INVRANGES);
+ offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx); /* patch in range count later */
/* parse ranges until character class ends */
- re_ctx->nranges = 0; /* note: ctx-wide temporary */
+ re_ctx->nranges = 0; /* note: ctx-wide temporary */
duk_lexer_parse_re_ranges(&re_ctx->lex, duk__regexp_generate_ranges, (void *) re_ctx);
/* insert range count */
@@ -85932,17 +91488,20 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
case DUK_RETOK_ATOM_END_GROUP: {
if (expect_eof) {
DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_CLOSING_PAREN);
+ DUK_WO_NORETURN(return;);
}
goto done;
}
case DUK_RETOK_EOF: {
if (!expect_eof) {
DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_END_OF_PATTERN);
+ DUK_WO_NORETURN(return;);
}
goto done;
}
default: {
DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_REGEXP_TOKEN);
+ DUK_WO_NORETURN(return;);
}
}
@@ -85962,7 +91521,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
atom_start_captures = new_atom_start_captures;
}
- done:
+done:
/* finish up pending jump and split for last alternative */
if (unpatched_disjunction_jump >= 0) {
@@ -85970,9 +91529,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
DUK_ASSERT(unpatched_disjunction_split >= 0);
offset = (duk_uint32_t) unpatched_disjunction_jump;
- offset += duk__insert_jump_offset(re_ctx,
- offset,
- (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
+ offset += duk__insert_jump_offset(re_ctx, offset, (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
/* offset is now target of the pending split (right after jump) */
duk__insert_jump_offset(re_ctx,
(duk_uint32_t) unpatched_disjunction_split,
@@ -85983,8 +91540,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex
out_atom_info->end_captures = re_ctx->captures;
#endif
out_atom_info->charlen = res_charlen;
- DUK_DDD(DUK_DDDPRINT("parse disjunction finished: charlen=%ld",
- (long) out_atom_info->charlen));
+ DUK_DDD(DUK_DDDPRINT("parse disjunction finished: charlen=%ld", (long) out_atom_info->charlen));
re_ctx->recursion_depth--;
}
@@ -86035,9 +91591,9 @@ DUK_LOCAL duk_uint32_t duk__parse_regexp_flags(duk_hthread *thr, duk_hstring *h)
return flags;
- flags_error:
+flags_error:
DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_REGEXP_FLAGS);
- return 0; /* never here */
+ DUK_WO_NORETURN(return 0U;);
}
/*
@@ -86074,7 +91630,7 @@ DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) {
n = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
if (n == 0) {
- duk_push_string(thr, "(?:)");
+ duk_push_literal(thr, "(?:)");
return;
}
@@ -86101,7 +91657,7 @@ DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) {
}
DUK_BW_SETPTR_AND_COMPACT(thr, bw, q);
- (void) duk_buffer_to_string(thr, -1); /* Safe if input is safe. */
+ (void) duk_buffer_to_string(thr, -1); /* Safe if input is safe. */
/* [ ... escaped_source ] */
}
@@ -86154,8 +91710,8 @@ DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) {
/* [ ... pattern flags escaped_source buffer ] */
- DUK_MEMZERO(&re_ctx, sizeof(re_ctx));
- DUK_LEXER_INITCTX(&re_ctx.lex); /* duplicate zeroing, expect for (possible) NULL inits */
+ duk_memzero(&re_ctx, sizeof(re_ctx));
+ DUK_LEXER_INITCTX(&re_ctx.lex); /* duplicate zeroing, expect for (possible) NULL inits */
re_ctx.thr = thr;
re_ctx.lex.thr = thr;
re_ctx.lex.input = DUK_HSTRING_GET_DATA(h_pattern);
@@ -86167,13 +91723,14 @@ DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) {
DUK_BW_INIT_PUSHBUF(thr, &re_ctx.bw, DUK__RE_INITIAL_BUFSIZE);
DUK_DD(DUK_DDPRINT("regexp compiler ctx initialized, flags=0x%08lx, recursion_limit=%ld",
- (unsigned long) re_ctx.re_flags, (long) re_ctx.recursion_limit));
+ (unsigned long) re_ctx.re_flags,
+ (long) re_ctx.recursion_limit));
/*
* Init lexer
*/
- lex_point.offset = 0; /* expensive init, just want to fill window */
+ lex_point.offset = 0; /* expensive init, just want to fill window */
lex_point.line = 1;
DUK_LEXER_SETPOINT(&re_ctx.lex, &lex_point);
@@ -86201,6 +91758,7 @@ DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) {
if (re_ctx.highest_backref > re_ctx.captures) {
DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BACKREFS);
+ DUK_WO_NORETURN(return;);
}
/*
@@ -86214,7 +91772,7 @@ DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) {
/* [ ... pattern flags escaped_source buffer ] */
DUK_BW_COMPACT(thr, &re_ctx.bw);
- (void) duk_buffer_to_string(thr, -1); /* Safe because flags is at most 7 bit. */
+ (void) duk_buffer_to_string(thr, -1); /* Safe because flags is at most 7 bit. */
/* [ ... pattern flags escaped_source bytecode ] */
@@ -86222,11 +91780,12 @@ DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) {
* Finalize stack
*/
- duk_remove(thr, -4); /* -> [ ... flags escaped_source bytecode ] */
- duk_remove(thr, -3); /* -> [ ... escaped_source bytecode ] */
+ duk_remove(thr, -4); /* -> [ ... flags escaped_source bytecode ] */
+ duk_remove(thr, -3); /* -> [ ... escaped_source bytecode ] */
DUK_DD(DUK_DDPRINT("regexp compilation successful, bytecode: %!T, escaped source: %!T",
- (duk_tval *) duk_get_tval(thr, -1), (duk_tval *) duk_get_tval(thr, -2)));
+ (duk_tval *) duk_get_tval(thr, -1),
+ (duk_tval *) duk_get_tval(thr, -2)));
}
/*
@@ -86272,11 +91831,11 @@ DUK_INTERNAL void duk_regexp_create_instance(duk_hthread *thr) {
/* [ ... regexp_object ] */
}
-#else /* DUK_USE_REGEXP_SUPPORT */
+#else /* DUK_USE_REGEXP_SUPPORT */
/* regexp support disabled */
-#endif /* DUK_USE_REGEXP_SUPPORT */
+#endif /* DUK_USE_REGEXP_SUPPORT */
/* automatic undefs */
#undef DUK__RE_BUFLEN
@@ -86284,7 +91843,7 @@ DUK_INTERNAL void duk_regexp_create_instance(duk_hthread *thr) {
/*
* Regexp executor.
*
- * Safety: the Ecmascript executor should prevent user from reading and
+ * Safety: the ECMAScript executor should prevent user from reading and
* replacing regexp bytecode. Even so, the executor must validate all
* memory accesses etc. When an invalid access is detected (e.g. a 'save'
* opcode to invalid, unallocated index) it should fail with an internal
@@ -86324,7 +91883,11 @@ DUK_LOCAL duk_int32_t duk__bc_get_i32(duk_re_matcher_ctx *re_ctx, const duk_uint
}
}
-DUK_LOCAL const duk_uint8_t *duk__utf8_backtrack(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_uint_fast32_t count) {
+DUK_LOCAL const duk_uint8_t *duk__utf8_backtrack(duk_hthread *thr,
+ const duk_uint8_t **ptr,
+ const duk_uint8_t *ptr_start,
+ const duk_uint8_t *ptr_end,
+ duk_uint_fast32_t count) {
const duk_uint8_t *p;
/* Note: allow backtracking from p == ptr_end */
@@ -86349,12 +91912,16 @@ DUK_LOCAL const duk_uint8_t *duk__utf8_backtrack(duk_hthread *thr, const duk_uin
*ptr = p;
return p;
- fail:
+fail:
DUK_ERROR_INTERNAL(thr);
- return NULL; /* never here */
+ DUK_WO_NORETURN(return NULL;);
}
-DUK_LOCAL const duk_uint8_t *duk__utf8_advance(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_uint_fast32_t count) {
+DUK_LOCAL const duk_uint8_t *duk__utf8_advance(duk_hthread *thr,
+ const duk_uint8_t **ptr,
+ const duk_uint8_t *ptr_start,
+ const duk_uint8_t *ptr_end,
+ duk_uint_fast32_t count) {
const duk_uint8_t *p;
p = *ptr;
@@ -86380,9 +91947,9 @@ DUK_LOCAL const duk_uint8_t *duk__utf8_advance(duk_hthread *thr, const duk_uint8
*ptr = p;
return p;
- fail:
+fail:
DUK_ERROR_INTERNAL(thr);
- return NULL; /* never here */
+ DUK_WO_NORETURN(return NULL;);
}
/*
@@ -86429,8 +91996,10 @@ DUK_LOCAL duk_codepoint_t duk__inp_get_prev_cp(duk_re_matcher_ctx *re_ctx, const
*/
DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *pc, const duk_uint8_t *sp) {
+ duk_native_stack_check(re_ctx->thr);
if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT);
+ DUK_WO_NORETURN(return NULL;);
}
re_ctx->recursion_depth++;
@@ -86439,6 +92008,7 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const
if (re_ctx->steps_count >= re_ctx->steps_limit) {
DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT);
+ DUK_WO_NORETURN(return NULL;);
}
re_ctx->steps_count++;
@@ -86481,7 +92051,7 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const
c1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
DUK_ASSERT(!(re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) ||
- c1 == duk_unicode_re_canonicalize_char(re_ctx->thr, c1)); /* canonicalized by compiler */
+ c1 == duk_unicode_re_canonicalize_char(re_ctx->thr, c1)); /* canonicalized by compiler */
c2 = duk__inp_get_cp(re_ctx, &sp);
/* No need to check for c2 < 0 (end of input): because c1 >= 0, it
* will fail the match below automatically and cause goto fail.
@@ -86527,7 +92097,10 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const
r1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
r2 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
DUK_DDD(DUK_DDDPRINT("matching ranges/invranges, n=%ld, r1=%ld, r2=%ld, c=%ld",
- (long) n, (long) r1, (long) r2, (long) c));
+ (long) n,
+ (long) r1,
+ (long) r2,
+ (long) c));
if (c >= r1 && c <= r2) {
/* Note: don't bail out early, we must read all the ranges from
* bytecode. Another option is to skip them efficiently after
@@ -86596,16 +92169,16 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const
duk_small_int_t w1, w2;
if (sp <= re_ctx->input) {
- w1 = 0; /* not a wordchar */
+ w1 = 0; /* not a wordchar */
} else {
duk_codepoint_t c;
c = duk__inp_get_prev_cp(re_ctx, sp);
w1 = duk_unicode_re_is_wordchar(c);
}
if (sp >= re_ctx->input_end) {
- w2 = 0; /* not a wordchar */
+ w2 = 0; /* not a wordchar */
} else {
- const duk_uint8_t *tmp_sp = sp; /* dummy so sp won't get updated */
+ const duk_uint8_t *tmp_sp = sp; /* dummy so sp won't get updated */
duk_codepoint_t c;
c = duk__inp_get_cp(re_ctx, &tmp_sp);
w2 = duk_unicode_re_is_wordchar(c);
@@ -86666,7 +92239,9 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const
qmax = duk__bc_get_u32(re_ctx, &pc);
skip = duk__bc_get_i32(re_ctx, &pc);
DUK_DDD(DUK_DDDPRINT("minimal quantifier, qmin=%lu, qmax=%lu, skip=%ld",
- (unsigned long) qmin, (unsigned long) qmax, (long) skip));
+ (unsigned long) qmin,
+ (unsigned long) qmax,
+ (long) skip));
q = 0;
while (q <= qmax) {
@@ -86696,7 +92271,10 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const
atomlen = duk__bc_get_u32(re_ctx, &pc);
skip = duk__bc_get_i32(re_ctx, &pc);
DUK_DDD(DUK_DDDPRINT("greedy quantifier, qmin=%lu, qmax=%lu, atomlen=%lu, skip=%ld",
- (unsigned long) qmin, (unsigned long) qmax, (unsigned long) atomlen, (long) skip));
+ (unsigned long) qmin,
+ (unsigned long) qmax,
+ (unsigned long) atomlen,
+ (long) skip));
q = 0;
while (q < qmax) {
@@ -86722,8 +92300,7 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const
* do not allow captures in their atom now, so this is not an issue.
*/
- DUK_DDD(DUK_DDDPRINT("greedy quantifier, backtrack %ld characters (atomlen)",
- (long) atomlen));
+ DUK_DDD(DUK_DDDPRINT("greedy quantifier, backtrack %ld characters (atomlen)", (long) atomlen));
sp = duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) atomlen);
q--;
}
@@ -86769,37 +92346,42 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const
idx_start = duk__bc_get_u32(re_ctx, &pc);
idx_count = duk__bc_get_u32(re_ctx, &pc);
DUK_DDD(DUK_DDDPRINT("wipe saved range: start=%ld, count=%ld -> [%ld,%ld] (captures [%ld,%ld])",
- (long) idx_start, (long) idx_count,
- (long) idx_start, (long) (idx_start + idx_count - 1),
- (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
+ (long) idx_start,
+ (long) idx_count,
+ (long) idx_start,
+ (long) (idx_start + idx_count - 1),
+ (long) (idx_start / 2),
+ (long) ((idx_start + idx_count - 1) / 2)));
if (idx_start + idx_count > re_ctx->nsaved || idx_count == 0) {
/* idx is unsigned, < 0 check is not necessary */
DUK_D(DUK_DPRINT("internal error, regexp wipe indices insane: idx_start=%ld, idx_count=%ld",
- (long) idx_start, (long) idx_count));
+ (long) idx_start,
+ (long) idx_count));
goto internal_error;
}
DUK_ASSERT(idx_count > 0);
duk_require_stack(re_ctx->thr, 1);
- range_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr,
- sizeof(duk_uint8_t *) * idx_count);
+ range_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr, sizeof(duk_uint8_t *) * idx_count);
DUK_ASSERT(range_save != NULL);
- DUK_MEMCPY(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count);
+ duk_memcpy(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count);
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
idx_end = idx_start + idx_count;
for (idx = idx_start; idx < idx_end; idx++) {
re_ctx->saved[idx] = NULL;
}
#else
- DUK_MEMZERO((void *) (re_ctx->saved + idx_start), sizeof(duk_uint8_t *) * idx_count);
+ duk_memzero((void *) (re_ctx->saved + idx_start), sizeof(duk_uint8_t *) * idx_count);
#endif
sub_sp = duk__match_regexp(re_ctx, pc, sp);
if (sub_sp) {
/* match: keep wiped/resaved values */
DUK_DDD(DUK_DDDPRINT("match: keep wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
- (long) idx_start, (long) (idx_start + idx_count - 1),
- (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
+ (long) idx_start,
+ (long) (idx_start + idx_count - 1),
+ (long) (idx_start / 2),
+ (long) ((idx_start + idx_count - 1) / 2)));
duk_pop_unsafe(re_ctx->thr);
sp = sub_sp;
goto match;
@@ -86807,9 +92389,11 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const
/* fail: restore saves */
DUK_DDD(DUK_DDDPRINT("fail: restore wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
- (long) idx_start, (long) (idx_start + idx_count - 1),
- (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
- DUK_MEMCPY((void *) (re_ctx->saved + idx_start),
+ (long) idx_start,
+ (long) (idx_start + idx_count - 1),
+ (long) (idx_start / 2),
+ (long) ((idx_start + idx_count - 1) / 2)));
+ duk_memcpy((void *) (re_ctx->saved + idx_start),
(const void *) range_save,
sizeof(duk_uint8_t *) * idx_count);
duk_pop_unsafe(re_ctx->thr);
@@ -86838,10 +92422,10 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const
DUK_ASSERT(re_ctx->nsaved > 0);
duk_require_stack(re_ctx->thr, 1);
- full_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr,
- sizeof(duk_uint8_t *) * re_ctx->nsaved);
+ full_save =
+ (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr, sizeof(duk_uint8_t *) * re_ctx->nsaved);
DUK_ASSERT(full_save != NULL);
- DUK_MEMCPY(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved);
+ duk_memcpy(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved);
skip = duk__bc_get_i32(re_ctx, &pc);
sub_sp = duk__match_regexp(re_ctx, pc, sp);
@@ -86864,11 +92448,9 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const
/* fall through */
- lookahead_fail:
+ lookahead_fail:
/* fail: restore saves */
- DUK_MEMCPY((void *) re_ctx->saved,
- (const void *) full_save,
- sizeof(duk_uint8_t *) * re_ctx->nsaved);
+ duk_memcpy((void *) re_ctx->saved, (const void *) full_save, sizeof(duk_uint8_t *) * re_ctx->nsaved);
duk_pop_unsafe(re_ctx->thr);
goto fail;
}
@@ -86891,22 +92473,23 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const
const duk_uint8_t *p;
idx = duk__bc_get_u32(re_ctx, &pc);
- idx = idx << 1; /* backref n -> saved indices [n*2, n*2+1] */
+ idx = idx << 1; /* backref n -> saved indices [n*2, n*2+1] */
if (idx < 2 || idx + 1 >= re_ctx->nsaved) {
/* regexp compiler should catch these */
DUK_D(DUK_DPRINT("internal error, backreference index insane"));
goto internal_error;
}
- if (!re_ctx->saved[idx] || !re_ctx->saved[idx+1]) {
+ if (!re_ctx->saved[idx] || !re_ctx->saved[idx + 1]) {
/* capture is 'undefined', always matches! */
DUK_DDD(DUK_DDDPRINT("backreference: saved[%ld,%ld] not complete, always match",
- (long) idx, (long) (idx + 1)));
+ (long) idx,
+ (long) (idx + 1)));
break;
}
DUK_DDD(DUK_DDDPRINT("backreference: match saved[%ld,%ld]", (long) idx, (long) (idx + 1)));
p = re_ctx->saved[idx];
- while (p < re_ctx->saved[idx+1]) {
+ while (p < re_ctx->saved[idx + 1]) {
duk_codepoint_t c1, c2;
/* Note: not necessary to check p against re_ctx->input_end:
@@ -86938,17 +92521,17 @@ DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const
}
}
- match:
+match:
re_ctx->recursion_depth--;
return sp;
- fail:
+fail:
re_ctx->recursion_depth--;
return NULL;
- internal_error:
+internal_error:
DUK_ERROR_INTERNAL(re_ctx->thr);
- return NULL; /* never here */
+ DUK_WO_NORETURN(return NULL;);
}
/*
@@ -86998,8 +92581,9 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_
h_input = duk_to_hstring(thr, -1);
DUK_ASSERT(h_input != NULL);
- duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_INT_BYTECODE); /* [ ... re_obj input ] -> [ ... re_obj input bc ] */
- h_bytecode = duk_require_hstring(thr, -1); /* no regexp instance should exist without a non-configurable bytecode property */
+ duk_xget_owndataprop_stridx_short(thr, -2, DUK_STRIDX_INT_BYTECODE); /* [ ... re_obj input ] -> [ ... re_obj input bc ] */
+ h_bytecode =
+ duk_require_hstring(thr, -1); /* no regexp instance should exist without a non-configurable bytecode property */
DUK_ASSERT(h_bytecode != NULL);
/*
@@ -87014,7 +92598,7 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_
/* [ ... re_obj input bc ] */
- DUK_MEMZERO(&re_ctx, sizeof(re_ctx));
+ duk_memzero(&re_ctx, sizeof(re_ctx));
re_ctx.thr = thr;
re_ctx.input = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
@@ -87031,13 +92615,13 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_
re_ctx.nsaved = duk__bc_get_u32(&re_ctx, &pc);
re_ctx.bytecode = pc;
- DUK_ASSERT(DUK_RE_FLAG_GLOBAL < 0x10000UL); /* must fit into duk_small_int_t */
+ DUK_ASSERT(DUK_RE_FLAG_GLOBAL < 0x10000UL); /* must fit into duk_small_int_t */
global = (duk_small_int_t) (force_global | (duk_small_int_t) (re_ctx.re_flags & DUK_RE_FLAG_GLOBAL));
DUK_ASSERT(re_ctx.nsaved >= 2);
DUK_ASSERT((re_ctx.nsaved % 2) == 0);
- p_buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, sizeof(duk_uint8_t *) * re_ctx.nsaved); /* rely on zeroing */
+ p_buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, sizeof(duk_uint8_t *) * re_ctx.nsaved); /* rely on zeroing */
DUK_UNREF(p_buf);
re_ctx.saved = (const duk_uint8_t **) duk_get_buffer(thr, -1, NULL);
DUK_ASSERT(re_ctx.saved != NULL);
@@ -87051,11 +92635,13 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_
#elif defined(DUK_USE_ZERO_BUFFER_DATA)
/* buffer is automatically zeroed */
#else
- DUK_MEMZERO((void *) p_buf, sizeof(duk_uint8_t *) * re_ctx.nsaved);
+ duk_memzero((void *) p_buf, sizeof(duk_uint8_t *) * re_ctx.nsaved);
#endif
DUK_DDD(DUK_DDDPRINT("regexp ctx initialized, flags=0x%08lx, nsaved=%ld, recursion_limit=%ld, steps_limit=%ld",
- (unsigned long) re_ctx.re_flags, (long) re_ctx.nsaved, (long) re_ctx.recursion_limit,
+ (unsigned long) re_ctx.re_flags,
+ (long) re_ctx.nsaved,
+ (long) re_ctx.recursion_limit,
(long) re_ctx.steps_limit));
/*
@@ -87077,15 +92663,15 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_
/* [ ... re_obj input bc saved_buf ] */
- duk_get_prop_stridx_short(thr, -4, DUK_STRIDX_LAST_INDEX); /* -> [ ... re_obj input bc saved_buf lastIndex ] */
- (void) duk_to_int(thr, -1); /* ToInteger(lastIndex) */
- d = duk_get_number(thr, -1); /* integer, but may be +/- Infinite, +/- zero (not NaN, though) */
+ duk_get_prop_stridx_short(thr, -4, DUK_STRIDX_LAST_INDEX); /* -> [ ... re_obj input bc saved_buf lastIndex ] */
+ (void) duk_to_int(thr, -1); /* ToInteger(lastIndex) */
+ d = duk_get_number(thr, -1); /* integer, but may be +/- Infinite, +/- zero (not NaN, though) */
duk_pop_nodecref_unsafe(thr);
if (global) {
if (d < 0.0 || d > (double) DUK_HSTRING_GET_CHARLEN(h_input)) {
/* match fail */
- char_offset = 0; /* not really necessary */
+ char_offset = 0; /* not really necessary */
DUK_ASSERT(match == 0);
goto match_over;
}
@@ -87121,8 +92707,10 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_
DUK_ASSERT(re_ctx.recursion_depth == 0);
DUK_DDD(DUK_DDDPRINT("attempt match at char offset %ld; %p [%p,%p]",
- (long) char_offset, (const void *) sp,
- (const void *) re_ctx.input, (const void *) re_ctx.input_end));
+ (long) char_offset,
+ (const void *) sp,
+ (const void *) re_ctx.input,
+ (const void *) re_ctx.input_end));
/*
* Note:
@@ -87136,7 +92724,7 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_
* internal/limit error occurs (which causes a longjmp())
*
* - If we supported anchored matches, we would break out here
- * unconditionally; however, Ecmascript regexps don't have anchored
+ * unconditionally; however, ECMAScript regexps don't have anchored
* matches. It might make sense to implement a fast bail-out if
* the regexp begins with '^' and sp is not 0: currently we'll just
* run through the entire input string, trivially failing the match
@@ -87169,7 +92757,7 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_
(void) duk__utf8_advance(thr, &sp, re_ctx.input, re_ctx.input_end, (duk_uint_fast32_t) 1);
}
- match_over:
+match_over:
/*
* Matching complete, create result array or return a 'null'. Update lastIndex
@@ -87195,8 +92783,8 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_
DUK_DDD(DUK_DDDPRINT("regexp matches at char_offset %ld", (long) char_offset));
- DUK_ASSERT(re_ctx.nsaved >= 2); /* must have start and end */
- DUK_ASSERT((re_ctx.nsaved % 2) == 0); /* and even number */
+ DUK_ASSERT(re_ctx.nsaved >= 2); /* must have start and end */
+ DUK_ASSERT((re_ctx.nsaved % 2) == 0); /* and even number */
/* XXX: Array size is known before and (2 * re_ctx.nsaved) but not taken
* advantage of now. The array is not compacted either, as regexp match
@@ -87225,24 +92813,26 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_
* as 'undefined'. The same is done when saved[] pointers are insane
* (this should, of course, never happen in practice).
*/
+ duk_push_uarridx(thr, (duk_uarridx_t) (i / 2));
+
if (re_ctx.saved[i] && re_ctx.saved[i + 1] && re_ctx.saved[i + 1] >= re_ctx.saved[i]) {
duk_push_lstring(thr,
(const char *) re_ctx.saved[i],
- (duk_size_t) (re_ctx.saved[i+1] - re_ctx.saved[i]));
+ (duk_size_t) (re_ctx.saved[i + 1] - re_ctx.saved[i]));
if (i == 0) {
/* Assumes that saved[0] and saved[1] are always
* set by regexp bytecode (if not, char_end_offset
* will be zero). Also assumes clen reflects the
* correct char length.
*/
- char_end_offset = char_offset + (duk_uint32_t) duk_get_length(thr, -1); /* add charlen */
+ char_end_offset = char_offset + (duk_uint32_t) duk_get_length(thr, -1); /* add charlen */
}
} else {
duk_push_undefined(thr);
}
- /* [ ... re_obj input bc saved_buf res_obj val ] */
- duk_put_prop_index(thr, -2, (duk_uarridx_t) (i / 2));
+ /* [ ... re_obj input bc saved_buf res_obj idx val ] */
+ duk_def_prop(thr, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_SET_WEC);
}
/* [ ... re_obj input bc saved_buf res_obj ] */
@@ -87300,11 +92890,11 @@ DUK_INTERNAL void duk_regexp_match_force_global(duk_hthread *thr) {
duk__regexp_match_helper(thr, 1 /*force_global*/);
}
-#else /* DUK_USE_REGEXP_SUPPORT */
+#else /* DUK_USE_REGEXP_SUPPORT */
/* regexp support disabled */
-#endif /* DUK_USE_REGEXP_SUPPORT */
+#endif /* DUK_USE_REGEXP_SUPPORT */
/*
* Self tests to ensure execution environment is sane. Intended to catch
* compiler/platform problems which cannot be detected at compile time.
@@ -87324,19 +92914,22 @@ typedef union {
} duk__test_double_union;
/* Self test failed. Expects a local variable 'error_count' to exist. */
-#define DUK__FAILED(msg) do { \
+#define DUK__FAILED(msg) \
+ do { \
DUK_D(DUK_DPRINT("self test failed: " #msg " at " DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO))); \
error_count++; \
} while (0)
-#define DUK__DBLUNION_CMP_TRUE(a,b) do { \
- if (DUK_MEMCMP((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) != 0) { \
+#define DUK__DBLUNION_CMP_TRUE(a, b) \
+ do { \
+ if (duk_memcmp((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) != 0) { \
DUK__FAILED("double union compares false (expected true)"); \
} \
} while (0)
-#define DUK__DBLUNION_CMP_FALSE(a,b) do { \
- if (DUK_MEMCMP((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) == 0) { \
+#define DUK__DBLUNION_CMP_FALSE(a, b) \
+ do { \
+ if (duk_memcmp((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) == 0) { \
DUK__FAILED("double union compares true (expected false)"); \
} \
} while (0)
@@ -87347,43 +92940,72 @@ typedef union {
} duk__test_u32_union;
#if defined(DUK_USE_INTEGER_LE)
-#define DUK__U32_INIT(u, a, b, c, d) do { \
- (u)->x[0] = (d); (u)->x[1] = (c); (u)->x[2] = (b); (u)->x[3] = (a); \
+#define DUK__U32_INIT(u, a, b, c, d) \
+ do { \
+ (u)->x[0] = (d); \
+ (u)->x[1] = (c); \
+ (u)->x[2] = (b); \
+ (u)->x[3] = (a); \
} while (0)
#elif defined(DUK_USE_INTEGER_ME)
#error integer mixed endian not supported now
#elif defined(DUK_USE_INTEGER_BE)
-#define DUK__U32_INIT(u, a, b, c, d) do { \
- (u)->x[0] = (a); (u)->x[1] = (b); (u)->x[2] = (c); (u)->x[3] = (d); \
+#define DUK__U32_INIT(u, a, b, c, d) \
+ do { \
+ (u)->x[0] = (a); \
+ (u)->x[1] = (b); \
+ (u)->x[2] = (c); \
+ (u)->x[3] = (d); \
} while (0)
#else
#error unknown integer endianness
#endif
#if defined(DUK_USE_DOUBLE_LE)
-#define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
- (u)->x[0] = (h); (u)->x[1] = (g); (u)->x[2] = (f); (u)->x[3] = (e); \
- (u)->x[4] = (d); (u)->x[5] = (c); (u)->x[6] = (b); (u)->x[7] = (a); \
+#define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) \
+ do { \
+ (u)->x[0] = (h); \
+ (u)->x[1] = (g); \
+ (u)->x[2] = (f); \
+ (u)->x[3] = (e); \
+ (u)->x[4] = (d); \
+ (u)->x[5] = (c); \
+ (u)->x[6] = (b); \
+ (u)->x[7] = (a); \
} while (0)
#define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
- ((u)->x[0] == (h) && (u)->x[1] == (g) && (u)->x[2] == (f) && (u)->x[3] == (e) && \
- (u)->x[4] == (d) && (u)->x[5] == (c) && (u)->x[6] == (b) && (u)->x[7] == (a))
+ ((u)->x[0] == (h) && (u)->x[1] == (g) && (u)->x[2] == (f) && (u)->x[3] == (e) && (u)->x[4] == (d) && (u)->x[5] == (c) && \
+ (u)->x[6] == (b) && (u)->x[7] == (a))
#elif defined(DUK_USE_DOUBLE_ME)
-#define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
- (u)->x[0] = (d); (u)->x[1] = (c); (u)->x[2] = (b); (u)->x[3] = (a); \
- (u)->x[4] = (h); (u)->x[5] = (g); (u)->x[6] = (f); (u)->x[7] = (e); \
+#define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) \
+ do { \
+ (u)->x[0] = (d); \
+ (u)->x[1] = (c); \
+ (u)->x[2] = (b); \
+ (u)->x[3] = (a); \
+ (u)->x[4] = (h); \
+ (u)->x[5] = (g); \
+ (u)->x[6] = (f); \
+ (u)->x[7] = (e); \
} while (0)
#define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
- ((u)->x[0] == (d) && (u)->x[1] == (c) && (u)->x[2] == (b) && (u)->x[3] == (a) && \
- (u)->x[4] == (h) && (u)->x[5] == (g) && (u)->x[6] == (f) && (u)->x[7] == (e))
+ ((u)->x[0] == (d) && (u)->x[1] == (c) && (u)->x[2] == (b) && (u)->x[3] == (a) && (u)->x[4] == (h) && (u)->x[5] == (g) && \
+ (u)->x[6] == (f) && (u)->x[7] == (e))
#elif defined(DUK_USE_DOUBLE_BE)
-#define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
- (u)->x[0] = (a); (u)->x[1] = (b); (u)->x[2] = (c); (u)->x[3] = (d); \
- (u)->x[4] = (e); (u)->x[5] = (f); (u)->x[6] = (g); (u)->x[7] = (h); \
+#define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) \
+ do { \
+ (u)->x[0] = (a); \
+ (u)->x[1] = (b); \
+ (u)->x[2] = (c); \
+ (u)->x[3] = (d); \
+ (u)->x[4] = (e); \
+ (u)->x[5] = (f); \
+ (u)->x[6] = (g); \
+ (u)->x[7] = (h); \
} while (0)
#define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
- ((u)->x[0] == (a) && (u)->x[1] == (b) && (u)->x[2] == (c) && (u)->x[3] == (d) && \
- (u)->x[4] == (e) && (u)->x[5] == (f) && (u)->x[6] == (g) && (u)->x[7] == (h))
+ ((u)->x[0] == (a) && (u)->x[1] == (b) && (u)->x[2] == (c) && (u)->x[3] == (d) && (u)->x[4] == (e) && (u)->x[5] == (f) && \
+ (u)->x[6] == (g) && (u)->x[7] == (h))
#else
#error unknown double endianness
#endif
@@ -87395,17 +93017,12 @@ typedef union {
DUK_LOCAL duk_uint_t duk__selftest_types(void) {
duk_uint_t error_count = 0;
- if (!(sizeof(duk_int8_t) == 1 &&
- sizeof(duk_uint8_t) == 1 &&
- sizeof(duk_int16_t) == 2 &&
- sizeof(duk_uint16_t) == 2 &&
- sizeof(duk_int32_t) == 4 &&
- sizeof(duk_uint32_t) == 4)) {
+ if (!(sizeof(duk_int8_t) == 1 && sizeof(duk_uint8_t) == 1 && sizeof(duk_int16_t) == 2 && sizeof(duk_uint16_t) == 2 &&
+ sizeof(duk_int32_t) == 4 && sizeof(duk_uint32_t) == 4)) {
DUK__FAILED("duk_(u)int{8,16,32}_t size");
}
#if defined(DUK_USE_64BIT_OPS)
- if (!(sizeof(duk_int64_t) == 8 &&
- sizeof(duk_uint64_t) == 8)) {
+ if (!(sizeof(duk_int64_t) == 8 && sizeof(duk_uint64_t) == 8)) {
DUK__FAILED("duk_(u)int64_t size");
}
#endif
@@ -87481,7 +93098,7 @@ DUK_LOCAL duk_uint_t duk__selftest_byte_order(void) {
DUK__FAILED("duk_uint32_t byte order");
}
- if (u2.d != (double) 102030405060.0) {
+ if (!duk_double_equals(u2.d, 102030405060.0)) {
DUK__FAILED("double byte order");
}
@@ -87494,10 +93111,28 @@ DUK_LOCAL duk_uint_t duk__selftest_byte_order(void) {
DUK_LOCAL duk_uint_t duk__selftest_bswap_macros(void) {
duk_uint_t error_count = 0;
+ volatile duk_uint32_t x32_input, x32_output;
duk_uint32_t x32;
+ volatile duk_uint16_t x16_input, x16_output;
duk_uint16_t x16;
duk_double_union du;
duk_double_t du_diff;
+#if defined(DUK_BSWAP64)
+ volatile duk_uint64_t x64_input, x64_output;
+ duk_uint64_t x64;
+#endif
+
+ /* Cover both compile time and runtime bswap operations, as these
+ * may have different bugs.
+ */
+
+ x16_input = 0xbeefUL;
+ x16 = x16_input;
+ x16 = DUK_BSWAP16(x16);
+ x16_output = x16;
+ if (x16_output != (duk_uint16_t) 0xefbeUL) {
+ DUK__FAILED("DUK_BSWAP16");
+ }
x16 = 0xbeefUL;
x16 = DUK_BSWAP16(x16);
@@ -87505,18 +93140,48 @@ DUK_LOCAL duk_uint_t duk__selftest_bswap_macros(void) {
DUK__FAILED("DUK_BSWAP16");
}
+ x32_input = 0xdeadbeefUL;
+ x32 = x32_input;
+ x32 = DUK_BSWAP32(x32);
+ x32_output = x32;
+ if (x32_output != (duk_uint32_t) 0xefbeaddeUL) {
+ DUK__FAILED("DUK_BSWAP32");
+ }
+
x32 = 0xdeadbeefUL;
x32 = DUK_BSWAP32(x32);
if (x32 != (duk_uint32_t) 0xefbeaddeUL) {
DUK__FAILED("DUK_BSWAP32");
}
+#if defined(DUK_BSWAP64)
+ x64_input = DUK_U64_CONSTANT(0x8899aabbccddeeff);
+ x64 = x64_input;
+ x64 = DUK_BSWAP64(x64);
+ x64_output = x64;
+ if (x64_output != (duk_uint64_t) DUK_U64_CONSTANT(0xffeeddccbbaa9988)) {
+ DUK__FAILED("DUK_BSWAP64");
+ }
+
+ x64 = DUK_U64_CONSTANT(0x8899aabbccddeeff);
+ x64 = DUK_BSWAP64(x64);
+ if (x64 != (duk_uint64_t) DUK_U64_CONSTANT(0xffeeddccbbaa9988)) {
+ DUK__FAILED("DUK_BSWAP64");
+ }
+#endif
+
/* >>> struct.unpack('>d', '4000112233445566'.decode('hex'))
* (2.008366013071895,)
*/
- du.uc[0] = 0x40; du.uc[1] = 0x00; du.uc[2] = 0x11; du.uc[3] = 0x22;
- du.uc[4] = 0x33; du.uc[5] = 0x44; du.uc[6] = 0x55; du.uc[7] = 0x66;
+ du.uc[0] = 0x40;
+ du.uc[1] = 0x00;
+ du.uc[2] = 0x11;
+ du.uc[3] = 0x22;
+ du.uc[4] = 0x33;
+ du.uc[5] = 0x44;
+ du.uc[6] = 0x55;
+ du.uc[7] = 0x66;
DUK_DBLUNION_DOUBLE_NTOH(&du);
du_diff = du.d - 2.008366013071895;
#if 0
@@ -87571,20 +93236,38 @@ DUK_LOCAL duk_uint_t duk__selftest_double_aliasing(void) {
*/
/* little endian */
- a.x[0] = 0x11; a.x[1] = 0x22; a.x[2] = 0x33; a.x[3] = 0x44;
- a.x[4] = 0x00; a.x[5] = 0x00; a.x[6] = 0xf1; a.x[7] = 0xff;
+ a.x[0] = 0x11;
+ a.x[1] = 0x22;
+ a.x[2] = 0x33;
+ a.x[3] = 0x44;
+ a.x[4] = 0x00;
+ a.x[5] = 0x00;
+ a.x[6] = 0xf1;
+ a.x[7] = 0xff;
b = a;
DUK__DBLUNION_CMP_TRUE(&a, &b);
/* big endian */
- a.x[0] = 0xff; a.x[1] = 0xf1; a.x[2] = 0x00; a.x[3] = 0x00;
- a.x[4] = 0x44; a.x[5] = 0x33; a.x[6] = 0x22; a.x[7] = 0x11;
+ a.x[0] = 0xff;
+ a.x[1] = 0xf1;
+ a.x[2] = 0x00;
+ a.x[3] = 0x00;
+ a.x[4] = 0x44;
+ a.x[5] = 0x33;
+ a.x[6] = 0x22;
+ a.x[7] = 0x11;
b = a;
DUK__DBLUNION_CMP_TRUE(&a, &b);
/* mixed endian */
- a.x[0] = 0x00; a.x[1] = 0x00; a.x[2] = 0xf1; a.x[3] = 0xff;
- a.x[4] = 0x11; a.x[5] = 0x22; a.x[6] = 0x33; a.x[7] = 0x44;
+ a.x[0] = 0x00;
+ a.x[1] = 0x00;
+ a.x[2] = 0xf1;
+ a.x[3] = 0xff;
+ a.x[4] = 0x11;
+ a.x[5] = 0x22;
+ a.x[6] = 0x33;
+ a.x[7] = 0x44;
b = a;
DUK__DBLUNION_CMP_TRUE(&a, &b);
@@ -87645,14 +93328,18 @@ DUK_LOCAL duk_uint_t duk__selftest_double_rounding(void) {
*/
DUK__DOUBLE_INIT(&a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
- DUK_MEMSET((void *) &c, 0, sizeof(c));
+ duk_memset((void *) &c, 0, sizeof(c));
c.d = a.d + b.d;
if (!DUK__DOUBLE_COMPARE(&c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)) {
DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x",
- (unsigned int) c.x[0], (unsigned int) c.x[1],
- (unsigned int) c.x[2], (unsigned int) c.x[3],
- (unsigned int) c.x[4], (unsigned int) c.x[5],
- (unsigned int) c.x[6], (unsigned int) c.x[7]));
+ (unsigned int) c.x[0],
+ (unsigned int) c.x[1],
+ (unsigned int) c.x[2],
+ (unsigned int) c.x[3],
+ (unsigned int) c.x[4],
+ (unsigned int) c.x[5],
+ (unsigned int) c.x[6],
+ (unsigned int) c.x[7]));
DUK__FAILED("invalid result from 1.0 + 0.5ulp");
}
@@ -87665,14 +93352,18 @@ DUK_LOCAL duk_uint_t duk__selftest_double_rounding(void) {
*/
DUK__DOUBLE_INIT(&a, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
- DUK_MEMSET((void *) &c, 0, sizeof(c));
+ duk_memset((void *) &c, 0, sizeof(c));
c.d = a.d + b.d;
if (!DUK__DOUBLE_COMPARE(&c, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02)) {
DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x",
- (unsigned int) c.x[0], (unsigned int) c.x[1],
- (unsigned int) c.x[2], (unsigned int) c.x[3],
- (unsigned int) c.x[4], (unsigned int) c.x[5],
- (unsigned int) c.x[6], (unsigned int) c.x[7]));
+ (unsigned int) c.x[0],
+ (unsigned int) c.x[1],
+ (unsigned int) c.x[2],
+ (unsigned int) c.x[3],
+ (unsigned int) c.x[4],
+ (unsigned int) c.x[5],
+ (unsigned int) c.x[6],
+ (unsigned int) c.x[7]));
DUK__FAILED("invalid result from (1.0 + ulp) + 0.5ulp");
}
@@ -87814,7 +93505,7 @@ DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_small_uint(void) {
u = (duk_small_uint_t) d1;
d2 = (duk_double_t) u;
- if (!(d1 == 1.0 && u == 1 && d2 == 1.0 && d1 == d2)) {
+ if (!(duk_double_equals(d1, 1.0) && u == 1 && duk_double_equals(d2, 1.0) && duk_double_equals(d1, d2))) {
DUK__FAILED("double to duk_small_uint_t cast failed");
}
@@ -87824,7 +93515,7 @@ DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_small_uint(void) {
uv = (duk_small_uint_t) d1v;
d2v = (duk_double_t) uv;
- if (!(d1v == 1.0 && uv == 1 && d2v == 1.0 && d1v == d2v)) {
+ if (!(duk_double_equals(d1v, 1.0) && uv == 1 && duk_double_equals(d2v, 1.0) && duk_double_equals(d1v, d2v))) {
DUK__FAILED("double to duk_small_uint_t cast failed");
}
@@ -87843,7 +93534,7 @@ DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_uint32(void) {
duk_double_t dv;
duk_uint32_t uv;
- dv = 3735928559.0; /* 0xdeadbeef in decimal */
+ dv = 3735928559.0; /* 0xdeadbeef in decimal */
uv = (duk_uint32_t) dv;
if (uv != 0xdeadbeefUL) {
@@ -87880,7 +93571,7 @@ DUK_LOCAL duk_uint_t duk__selftest_alloc_funcs(duk_alloc_function alloc_func,
ptr = alloc_func(udata, (duk_size_t) i);
if (ptr == NULL) {
DUK_D(DUK_DPRINT("alloc failed, ignore"));
- continue; /* alloc failed, ignore */
+ continue; /* alloc failed, ignore */
}
for (j = 0; j < i; j++) {
((unsigned char *) ptr)[j] = (unsigned char) (0x80 + j);
@@ -87889,14 +93580,15 @@ DUK_LOCAL duk_uint_t duk__selftest_alloc_funcs(duk_alloc_function alloc_func,
if (new_ptr == NULL) {
DUK_D(DUK_DPRINT("realloc failed, ignore"));
free_func(udata, ptr);
- continue; /* realloc failed, ignore */
+ continue; /* realloc failed, ignore */
}
ptr = new_ptr;
for (j = 0; j < i; j++) {
x = ((unsigned char *) ptr)[j];
if (x != (unsigned char) (0x80 + j)) {
DUK_D(DUK_DPRINT("byte at index %ld doesn't match after realloc: %02lx",
- (long) j, (unsigned long) x));
+ (long) j,
+ (unsigned long) x));
DUK__FAILED("byte compare after realloc");
break;
}
@@ -87940,7 +93632,7 @@ DUK_INTERNAL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,
return error_count;
}
-#endif /* DUK_USE_SELF_TESTS */
+#endif /* DUK_USE_SELF_TESTS */
/* automatic undefs */
#undef DUK__DBLUNION_CMP_FALSE
@@ -87983,11 +93675,11 @@ DUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast_fast(duk_tval *t
expt = (duk_small_int_t) ((i >> 52) & 0x07ff);
shift = expt - 1023;
- if (shift >= 0 && shift <= 46) { /* exponents 1023 to 1069 */
+ if (shift >= 0 && shift <= 46) { /* exponents 1023 to 1069 */
duk_int64_t t;
if (((DUK_I64_CONSTANT(0x000fffffffffffff) >> shift) & i) == 0) {
- t = i | DUK_I64_CONSTANT(0x0010000000000000); /* implicit leading one */
+ t = i | DUK_I64_CONSTANT(0x0010000000000000); /* implicit leading one */
t = t & DUK_I64_CONSTANT(0x001fffffffffffff);
t = t >> (52 - shift);
if (i < 0) {
@@ -87996,13 +93688,13 @@ DUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast_fast(duk_tval *t
DUK_TVAL_SET_FASTINT(tv, t);
return;
}
- } else if (shift == -1023) { /* exponent 0 */
+ } else if (shift == -1023) { /* exponent 0 */
if (i >= 0 && (i & DUK_I64_CONSTANT(0x000fffffffffffff)) == 0) {
/* Note: reject negative zero. */
DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) 0);
return;
}
- } else if (shift == 47) { /* exponent 1070 */
+ } else if (shift == 47) { /* exponent 1070 */
if (i < 0 && (i & DUK_I64_CONSTANT(0x000fffffffffffff)) == 0) {
DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) DUK_FASTINT_MIN);
return;
@@ -88030,23 +93722,23 @@ DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_packed(duk_tval
if ((t >> 48) != DUK_TAG_FASTINT) {
return tv->d;
} else if (t & DUK_U64_CONSTANT(0x0000800000000000)) {
- t = (duk_uint64_t) (-((duk_int64_t) t)); /* avoid unary minus on unsigned */
- t = t & DUK_U64_CONSTANT(0x0000ffffffffffff); /* negative */
+ t = (duk_uint64_t) (-((duk_int64_t) t)); /* avoid unary minus on unsigned */
+ t = t & DUK_U64_CONSTANT(0x0000ffffffffffff); /* negative */
t |= DUK_U64_CONSTANT(0xc330000000000000);
DUK_DBLUNION_SET_UINT64(&du, t);
- return du.d + 4503599627370496.0; /* 1 << 52 */
+ return du.d + 4503599627370496.0; /* 1 << 52 */
} else if (t != 0) {
- t &= DUK_U64_CONSTANT(0x0000ffffffffffff); /* positive */
+ t &= DUK_U64_CONSTANT(0x0000ffffffffffff); /* positive */
t |= DUK_U64_CONSTANT(0x4330000000000000);
DUK_DBLUNION_SET_UINT64(&du, t);
- return du.d - 4503599627370496.0; /* 1 << 52 */
+ return du.d - 4503599627370496.0; /* 1 << 52 */
} else {
- return 0.0; /* zero */
+ return 0.0; /* zero */
}
}
-#endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
+#endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
-#if 0 /* unused */
+#if 0 /* unused */
#if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked(duk_tval *tv) {
duk_double_union du;
@@ -88068,8 +93760,8 @@ DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked(duk_tva
return tv->v.d;
}
}
-#endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
-#endif /* 0 */
+#endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
+#endif /* 0 */
#if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv) {
@@ -88081,16 +93773,26 @@ DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint
if (tv->v.fi >= 0) {
t = DUK_U64_CONSTANT(0x4330000000000000) | (duk_uint64_t) tv->v.fi;
DUK_DBLUNION_SET_UINT64(&du, t);
- return du.d - 4503599627370496.0; /* 1 << 52 */
+ return du.d - 4503599627370496.0; /* 1 << 52 */
} else {
t = DUK_U64_CONSTANT(0xc330000000000000) | (duk_uint64_t) (-tv->v.fi);
DUK_DBLUNION_SET_UINT64(&du, t);
- return du.d + 4503599627370496.0; /* 1 << 52 */
+ return du.d + 4503599627370496.0; /* 1 << 52 */
}
}
-#endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
+#endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
+
+#endif /* DUK_USE_FASTINT */
+
+/*
+ * Assertion helpers.
+ */
-#endif /* DUK_USE_FASTINT */
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL void duk_tval_assert_valid(duk_tval *tv) {
+ DUK_ASSERT(tv != NULL);
+}
+#endif
/*
* Unicode support tables automatically generated during build.
*/
@@ -88102,7 +93804,7 @@ DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint
* packed format. These tables are used to match non-ASCII
* characters of complex productions by resorting to a linear
* range-by-range comparison. This is very slow, but is expected
- * to be very rare in practical Ecmascript source code, and thus
+ * to be very rare in practical ECMAScript source code, and thus
* compactness is most important.
*
* The tables are matched using uni_range_match() and the format
@@ -88116,54 +93818,57 @@ DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint
* Automatically generated by extract_chars.py, do not edit!
*/
-const duk_uint8_t duk_unicode_ids_noa[1036] = {
+const duk_uint8_t duk_unicode_ids_noa[1116] = {
249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,
-2,240,66,244,50,247,185,249,98,241,99,8,241,127,58,240,182,47,31,241,191,
+2,240,66,244,50,247,185,249,98,241,99,7,241,159,57,240,181,63,31,241,191,
21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
-101,10,4,15,9,240,159,57,240,82,127,56,242,100,15,4,8,159,1,240,5,115,19,
-240,98,98,4,52,15,2,14,18,47,0,31,5,85,19,240,98,98,18,18,31,17,50,15,5,47,
-2,130,34,240,98,98,18,68,15,4,15,1,31,9,12,115,19,240,98,98,18,68,15,16,18,
-47,1,15,3,2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,240,4,15,12,
-38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,6,
-41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50,98,
-34,2,3,18,50,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,2,
-85,52,4,24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35,
-63,17,35,54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227,
-240,18,240,166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,
-15,53,244,137,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40,
-240,122,242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27,
-43,241,67,143,82,50,52,26,251,15,50,255,224,8,53,63,22,53,55,32,32,32,47,
-15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,68,
-112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,52,
-29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,12,
-146,240,184,132,52,95,70,114,47,74,35,111,25,79,78,240,63,11,242,127,0,255,
-224,244,255,240,0,138,143,60,255,240,4,12,143,28,255,227,127,243,95,30,63,
-253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,20,39,243,26,34,
-35,47,7,240,255,36,240,15,34,243,5,64,32,223,12,191,7,240,191,13,143,31,
+101,10,4,15,9,240,152,175,39,240,82,127,56,242,100,15,4,8,159,1,240,5,115,
+19,240,98,98,4,52,15,2,14,18,47,0,27,9,85,19,240,98,98,18,18,31,17,50,15,5,
+47,2,130,34,240,98,98,18,68,15,4,15,1,31,9,12,115,19,240,98,98,18,68,15,16,
+18,47,1,15,3,2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,240,4,15,
+12,38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,
+6,41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,2,66,240,130,
+2,146,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,2,85,52,4,
+24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35,63,17,35,
+54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227,240,18,240,
+166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,15,53,244,
+152,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40,240,122,
+242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27,43,241,67,
+136,241,179,47,27,50,82,20,6,251,15,50,255,224,8,53,63,22,53,55,32,32,32,
+47,15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,
+68,112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,
+52,29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,
+12,146,240,184,132,52,95,70,114,47,74,35,111,27,47,78,240,63,11,242,127,0,
+255,224,244,255,240,0,138,143,60,255,240,4,14,47,2,255,227,127,243,95,30,
+63,253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,37,52,242,42,
+34,35,47,7,240,255,36,240,15,34,243,5,64,33,207,12,191,7,240,191,13,143,31,
240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,48,32,
-240,162,58,130,213,53,53,166,38,47,27,41,191,99,240,255,255,0,26,150,223,7,
+240,162,58,130,213,53,53,166,38,47,27,43,159,99,240,255,255,0,26,150,223,7,
95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,18,245,
207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,127,10,
207,73,69,53,53,50,241,91,47,10,47,3,33,46,61,241,79,107,243,127,37,255,
-223,13,79,33,242,31,16,240,47,11,111,22,191,14,63,20,87,36,241,207,142,240,
-79,20,95,20,95,24,159,36,248,239,254,2,154,240,107,127,138,83,2,241,194,20,
-3,240,123,240,122,240,255,51,240,50,27,240,107,240,175,56,242,135,31,50,15,
-1,50,34,240,191,30,240,212,240,223,21,114,240,207,13,242,107,240,107,240,
-62,240,47,96,243,159,41,242,62,242,63,254,32,79,37,243,223,29,241,47,9,240,
-207,20,241,191,19,64,223,32,240,3,240,112,32,241,95,2,47,9,244,102,32,35,
-46,41,143,31,241,135,49,63,6,38,33,36,64,240,64,212,249,15,37,240,67,242,
-127,32,240,97,32,250,175,31,241,179,241,111,32,240,96,242,223,27,244,127,
-10,255,224,122,243,15,17,15,254,11,79,41,255,152,47,21,240,48,242,63,14,
-255,226,100,255,226,140,245,143,95,240,63,180,255,233,176,255,227,33,255,
-238,197,255,225,57,255,240,1,10,223,254,18,184,240,255,99,240,239,4,242,15,
-2,63,17,240,86,240,63,254,38,79,53,192,243,76,243,32,241,31,255,0,6,223,
-240,95,254,30,95,255,0,20,1,31,254,175,47,91,108,72,137,255,240,0,101,175,
-69,47,55,33,48,49,51,43,32,38,47,49,35,55,38,47,12,35,36,32,70,47,254,4,99,
-240,146,240,146,240,242,240,146,240,242,240,146,240,242,240,146,240,242,
-240,146,127,254,242,143,181,242,223,52,255,227,176,50,240,178,18,3,2,146,
-50,2,7,5,2,2,2,34,18,3,2,2,2,2,2,18,3,50,98,50,50,2,146,240,22,34,66,240,
-31,255,0,0,56,255,240,9,92,159,27,255,239,39,207,206,63,255,0,5,116,255,
-240,1,133,47,254,17,0,
+223,13,79,33,242,31,16,239,14,111,22,191,14,63,20,87,36,241,207,142,240,79,
+20,95,20,95,24,159,36,248,239,254,2,154,240,107,127,138,83,2,241,194,20,3,
+240,123,240,122,240,255,51,240,50,27,240,107,240,175,56,242,135,31,50,15,1,
+50,34,240,223,28,240,212,240,223,21,114,240,207,13,242,107,240,107,240,62,
+240,47,96,243,159,41,242,62,242,62,241,79,254,13,15,13,176,159,6,248,207,7,
+223,37,243,223,29,241,47,9,240,207,20,240,240,207,19,64,223,32,240,3,240,
+112,32,241,95,2,47,9,244,102,32,35,46,41,143,31,241,135,49,63,6,38,33,36,
+64,240,64,212,249,15,37,240,67,240,96,241,47,32,240,97,32,250,175,31,241,
+179,241,111,32,240,96,242,223,27,224,243,159,11,253,127,28,246,111,48,241,
+16,249,39,63,23,240,32,32,240,224,191,24,128,240,112,207,30,240,80,241,79,
+41,255,152,47,21,240,48,242,63,14,246,38,33,47,22,240,112,240,181,33,47,16,
+240,0,255,224,59,240,63,254,0,31,254,40,207,88,245,255,3,251,79,254,155,15,
+254,50,31,254,236,95,254,19,159,255,0,16,173,255,225,43,143,15,246,63,14,
+240,79,32,240,35,241,31,5,111,3,255,225,164,243,15,114,243,182,15,52,207,
+50,18,15,14,255,240,0,110,169,255,225,229,255,240,1,64,31,254,1,31,35,47,3,
+57,255,224,126,255,231,248,245,182,196,136,159,255,0,6,90,244,82,243,114,
+19,3,19,50,178,2,98,243,18,51,114,98,240,194,50,66,4,98,255,224,70,63,9,47,
+9,47,15,47,9,47,15,47,9,47,15,47,9,47,15,47,9,39,255,232,40,241,219,111,2,
+15,254,6,95,28,255,228,8,251,95,45,243,72,15,254,58,131,47,11,33,32,48,41,
+35,32,32,112,80,32,32,34,33,32,48,32,32,32,32,33,32,51,38,35,35,32,41,47,1,
+98,36,47,1,255,240,0,3,143,255,0,149,201,241,191,254,242,124,252,227,255,
+240,0,87,79,0,255,240,0,194,63,254,177,63,254,17,0,
};
#else
/* IdentifierStart production with ASCII and non-BMP excluded */
@@ -88174,30 +93879,30 @@ const duk_uint8_t duk_unicode_ids_noa[1036] = {
const duk_uint8_t duk_unicode_ids_noabmp[625] = {
249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,
-2,240,66,244,50,247,185,249,98,241,99,8,241,127,58,240,182,47,31,241,191,
+2,240,66,244,50,247,185,249,98,241,99,7,241,159,57,240,181,63,31,241,191,
21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
-101,10,4,15,9,240,159,57,240,82,127,56,242,100,15,4,8,159,1,240,5,115,19,
-240,98,98,4,52,15,2,14,18,47,0,31,5,85,19,240,98,98,18,18,31,17,50,15,5,47,
-2,130,34,240,98,98,18,68,15,4,15,1,31,9,12,115,19,240,98,98,18,68,15,16,18,
-47,1,15,3,2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,240,4,15,12,
-38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,6,
-41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50,98,
-34,2,3,18,50,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,2,
-85,52,4,24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35,
-63,17,35,54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227,
-240,18,240,166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,
-15,53,244,137,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40,
-240,122,242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27,
-43,241,67,143,82,50,52,26,251,15,50,255,224,8,53,63,22,53,55,32,32,32,47,
-15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,68,
-112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,52,
-29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,12,
-146,240,184,132,52,95,70,114,47,74,35,111,25,79,78,240,63,11,242,127,0,255,
-224,244,255,240,0,138,143,60,255,240,4,12,143,28,255,227,127,243,95,30,63,
-253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,20,39,243,26,34,
-35,47,7,240,255,36,240,15,34,243,5,64,32,223,12,191,7,240,191,13,143,31,
+101,10,4,15,9,240,152,175,39,240,82,127,56,242,100,15,4,8,159,1,240,5,115,
+19,240,98,98,4,52,15,2,14,18,47,0,27,9,85,19,240,98,98,18,18,31,17,50,15,5,
+47,2,130,34,240,98,98,18,68,15,4,15,1,31,9,12,115,19,240,98,98,18,68,15,16,
+18,47,1,15,3,2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,240,4,15,
+12,38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,
+6,41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,2,66,240,130,
+2,146,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,2,85,52,4,
+24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35,63,17,35,
+54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227,240,18,240,
+166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,15,53,244,
+152,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40,240,122,
+242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27,43,241,67,
+136,241,179,47,27,50,82,20,6,251,15,50,255,224,8,53,63,22,53,55,32,32,32,
+47,15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,
+68,112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,
+52,29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,
+12,146,240,184,132,52,95,70,114,47,74,35,111,27,47,78,240,63,11,242,127,0,
+255,224,244,255,240,0,138,143,60,255,240,4,14,47,2,255,227,127,243,95,30,
+63,253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,37,52,242,42,
+34,35,47,7,240,255,36,240,15,34,243,5,64,33,207,12,191,7,240,191,13,143,31,
240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,48,32,
-240,162,58,130,213,53,53,166,38,47,27,41,191,99,240,255,255,0,26,150,223,7,
+240,162,58,130,213,53,53,166,38,47,27,43,159,99,240,255,255,0,26,150,223,7,
95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,18,245,
207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,127,10,
207,73,69,53,53,50,0,
@@ -88235,32 +93940,35 @@ const duk_uint8_t duk_unicode_ids_m_let_noabmp[24] = {
* Automatically generated by extract_chars.py, do not edit!
*/
-const duk_uint8_t duk_unicode_idp_m_ids_noa[530] = {
+const duk_uint8_t duk_unicode_idp_m_ids_noa[576] = {
255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
-245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,241,67,40,34,
-36,241,210,246,173,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
-160,177,57,240,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,240,
-97,57,240,50,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9,
-240,35,242,198,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,50,
-242,198,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,215,41,
-244,144,53,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,245,
-111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,241,
-241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,242,
-244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,57,
-241,237,242,47,4,153,121,246,130,47,5,80,82,65,251,143,38,100,255,225,0,31,
-35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,31,
-255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,242,
-79,2,185,127,2,240,9,240,231,240,188,241,227,242,29,240,25,192,185,242,29,
-208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
+245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,160,240,163,40,
+34,36,241,210,246,158,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
+160,177,57,240,0,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,
+240,97,57,181,34,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,
+9,240,36,242,182,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,
+35,242,145,38,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,
+215,41,244,144,56,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,
+245,111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,
+241,241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,
+242,244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,
+57,241,237,242,47,4,153,121,246,130,47,5,80,112,50,251,143,42,36,255,225,0,
+31,35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,
+31,255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,
+242,79,2,185,127,2,234,240,231,240,188,241,227,242,29,240,25,192,185,242,
+29,208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,15,254,27,16,253,64,
-248,116,255,224,25,159,254,68,178,33,99,241,162,80,249,113,255,228,13,47,
-39,239,17,159,1,63,31,175,39,151,47,22,210,159,37,13,47,34,218,36,159,68,
-183,15,146,182,151,63,42,2,99,19,42,11,19,100,79,178,240,42,159,72,240,77,
-159,199,99,143,13,31,68,240,31,1,159,67,201,159,69,229,159,254,9,169,255,
-226,57,114,127,2,159,42,240,98,223,255,0,60,157,159,120,79,45,111,11,159,
-254,46,191,30,240,35,255,240,3,191,225,255,240,0,59,164,69,151,54,241,3,
-248,98,255,228,125,242,47,254,15,79,39,95,34,144,240,0,240,132,46,255,228,
-68,98,240,19,98,18,79,254,121,150,245,246,105,255,240,192,105,175,224,0,
+248,116,255,224,25,159,254,68,178,33,99,241,162,80,249,113,255,225,49,57,
+159,254,16,10,250,18,242,126,241,25,240,19,241,250,242,121,114,241,109,41,
+97,241,224,210,242,45,147,73,244,75,112,249,43,105,115,242,145,38,49,50,
+160,177,54,68,251,47,2,169,80,244,63,4,217,252,118,56,240,209,244,79,1,240,
+25,244,60,153,244,94,89,254,78,249,121,253,150,54,64,240,233,241,166,35,
+144,170,242,15,0,255,224,137,114,127,2,159,42,240,98,223,108,84,2,18,98,9,
+159,34,66,18,73,159,254,3,211,255,240,3,165,217,247,132,242,214,240,185,
+255,226,233,2,242,120,63,255,0,59,254,31,255,0,3,186,68,89,115,111,16,63,
+134,47,254,71,223,34,255,224,244,242,117,242,41,15,0,15,8,66,239,254,68,70,
+47,1,54,33,36,255,118,169,255,224,150,223,254,76,166,245,246,105,255,240,
+192,105,175,224,0,
};
#else
/* IdentifierPart production with IdentifierStart, ASCII, and non-BMP excluded */
@@ -88269,23 +93977,23 @@ const duk_uint8_t duk_unicode_idp_m_ids_noa[530] = {
* Automatically generated by extract_chars.py, do not edit!
*/
-const duk_uint8_t duk_unicode_idp_m_ids_noabmp[357] = {
+const duk_uint8_t duk_unicode_idp_m_ids_noabmp[358] = {
255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
-245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,241,67,40,34,
-36,241,210,246,173,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
-160,177,57,240,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,240,
-97,57,240,50,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9,
-240,35,242,198,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,50,
-242,198,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,215,41,
-244,144,53,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,245,
-111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,241,
-241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,242,
-244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,57,
-241,237,242,47,4,153,121,246,130,47,5,80,82,65,251,143,38,100,255,225,0,31,
-35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,31,
-255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,242,
-79,2,185,127,2,240,9,240,231,240,188,241,227,242,29,240,25,192,185,242,29,
-208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
+245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,160,240,163,40,
+34,36,241,210,246,158,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
+160,177,57,240,0,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,
+240,97,57,181,34,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,
+9,240,36,242,182,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,
+35,242,145,38,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,
+215,41,244,144,56,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,
+245,111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,
+241,241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,
+242,244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,
+57,241,237,242,47,4,153,121,246,130,47,5,80,112,50,251,143,42,36,255,225,0,
+31,35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,
+31,255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,
+242,79,2,185,127,2,234,240,231,240,188,241,227,242,29,240,25,192,185,242,
+29,208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,0,
};
#endif
@@ -88301,102 +94009,106 @@ const duk_uint8_t duk_unicode_idp_m_ids_noabmp[357] = {
* Automatically generated by extract_caseconv.py, do not edit!
*/
-const duk_uint8_t duk_unicode_caseconv_uc[1386] = {
-144,3,128,3,0,184,7,192,6,192,112,35,242,199,224,64,74,192,49,32,128,162,
+const duk_uint8_t duk_unicode_caseconv_uc[1411] = {
+152,3,128,3,0,184,7,192,6,192,112,35,242,199,224,64,74,192,49,32,128,162,
128,108,65,1,189,129,254,131,3,173,3,136,6,7,98,7,34,68,15,12,14,140,72,30,
-104,28,112,32,67,0,65,4,0,138,0,128,4,1,88,65,76,83,9,252,9,248,6,28,131,4,
-33,4,62,0,62,16,32,124,64,124,96,48,249,0,249,64,129,243,1,243,129,3,232,3,
-233,1,135,216,7,218,4,15,184,15,221,2,31,114,31,200,8,62,236,63,180,8,125,
-224,127,224,16,251,208,255,80,33,247,193,255,160,67,246,3,247,0,135,244,7,
-246,1,15,240,15,244,2,33,112,33,96,32,73,160,73,108,104,176,192,176,1,121,
-104,0,133,2,106,183,1,58,10,31,232,63,228,38,162,1,1,1,0,48,2,102,2,100,12,
-4,232,4,228,64,10,88,10,81,112,23,160,23,144,96,48,96,48,64,128,104,64,104,
-1,128,218,0,217,130,1,206,1,205,16,3,190,3,188,36,7,228,7,224,160,17,24,17,
-16,144,36,112,36,96,160,110,32,110,0,128,246,64,246,6,2,48,130,48,17,4,139,
-4,138,54,9,132,9,130,28,19,68,19,65,128,240,8,240,4,177,234,17,234,6,3,234,
-35,235,33,11,26,11,25,193,150,64,150,64,50,44,236,44,235,5,76,131,76,128,
-94,154,6,154,0,117,57,29,57,16,122,115,58,115,35,244,239,84,239,32,169,223,
-233,223,130,211,200,211,200,2,167,151,167,150,21,79,107,79,104,8,112,26,
-208,26,192,64,56,160,56,128,192,113,128,113,1,128,249,0,248,130,2,128,1,
-166,4,7,240,7,238,8,177,204,177,200,16,96,49,0,48,224,128,110,64,110,1,1,
-51,83,213,2,0,48,35,192,35,176,64,77,32,50,192,139,73,196,49,193,127,48,2,
-212,14,112,3,252,5,224,4,196,1,36,5,252,1,76,6,0,9,12,6,72,6,68,6,84,7,216,
-6,100,6,96,6,104,8,244,6,120,8,128,6,160,6,156,6,252,7,220,7,116,6,56,7,
-204,7,196,9,64,177,188,9,68,177,180,9,72,177,192,9,76,6,4,9,80,6,24,9,100,
-6,60,9,108,6,64,9,114,158,172,9,128,6,76,9,134,158,176,9,140,6,80,9,150,
-158,52,9,160,6,92,9,172,177,136,9,178,158,180,9,196,177,184,9,200,6,116,9,
-212,6,124,9,244,177,144,10,30,158,196,10,32,6,184,10,36,9,16,10,48,9,20,10,
-72,6,220,10,118,158,200,10,122,158,192,13,20,14,100,13,220,13,216,14,176,
-14,24,15,8,14,140,15,48,14,48,15,64,14,72,15,68,14,96,15,84,14,152,15,88,
-14,128,15,92,15,60,15,192,14,104,15,196,14,132,15,200,15,228,15,204,13,252,
-15,212,14,84,19,60,19,0,114,0,16,72,114,4,16,80,114,8,16,120,114,20,16,136,
-114,24,16,168,114,28,17,136,114,34,153,40,117,230,157,244,117,244,177,140,
-122,108,121,128,126,248,14,100,127,148,127,176,133,56,132,200,134,16,134,
-12,177,132,177,128,177,148,8,232,177,152,8,248,179,204,179,202,158,50,158,
-46,173,78,158,207,48,6,252,0,166,0,166,2,147,1,94,0,39,0,248,64,9,64,97,
-128,114,24,28,200,24,64,24,8,29,134,7,74,6,16,6,2,11,15,2,154,130,169,15,
-75,64,9,0,102,35,210,240,2,160,24,64,244,196,0,174,6,20,61,51,0,44,129,133,
-15,77,64,8,32,87,195,234,16,29,40,24,152,250,150,7,74,6,38,6,0,62,169,129,
-210,129,137,129,128,143,171,96,116,160,98,96,104,67,240,16,248,64,28,200,
-252,12,62,18,7,50,63,5,15,133,1,204,143,193,195,225,96,115,35,240,144,248,
-96,28,200,252,44,62,26,7,50,63,13,15,135,1,204,143,195,195,225,224,115,35,
-241,16,248,64,28,200,252,76,62,18,7,50,63,21,15,133,1,204,143,197,195,225,
-96,115,35,241,144,248,96,28,200,252,108,62,26,7,50,63,29,15,135,1,204,143,
-199,195,225,224,115,35,242,16,249,64,28,200,252,140,62,82,7,50,63,37,15,
-149,1,204,143,201,195,229,96,115,35,242,144,249,96,28,200,252,172,62,90,7,
-50,63,45,15,151,1,204,143,203,195,229,224,115,35,243,16,249,64,28,200,252,
-204,62,82,7,50,63,53,15,149,1,204,143,205,195,229,96,115,35,243,144,249,96,
-28,200,252,236,62,90,7,50,63,61,15,151,1,204,143,207,195,229,224,115,35,
-244,16,251,64,28,200,253,12,62,210,7,50,63,69,15,181,1,204,143,209,195,237,
-96,115,35,244,144,251,96,28,200,253,44,62,218,7,50,63,77,15,183,1,204,143,
-211,195,237,224,115,35,245,16,251,64,28,200,253,76,62,210,7,50,63,85,15,
-181,1,204,143,213,195,237,96,115,35,245,144,251,96,28,200,253,108,62,218,7,
-50,63,93,15,183,1,204,143,215,195,237,224,115,35,246,80,253,208,28,200,253,
-156,7,34,7,50,63,105,1,195,1,204,143,219,64,114,32,104,67,246,248,28,136,
-26,16,28,200,253,228,7,34,7,50,63,133,15,229,1,204,143,225,192,114,224,115,
-35,248,144,28,72,28,200,254,52,7,46,6,132,63,143,129,203,129,161,1,204,143,
-230,64,114,224,115,35,250,88,28,200,24,64,24,0,254,158,7,50,6,16,6,2,63,
-173,1,204,129,161,15,235,224,115,32,97,0,104,67,252,88,29,40,24,64,24,0,
-255,30,7,74,6,16,6,2,63,201,1,208,129,137,143,243,64,116,160,104,67,252,
-248,29,40,24,64,26,16,255,148,63,244,7,50,63,231,1,212,129,204,143,250,64,
-113,224,115,35,254,208,29,72,26,16,255,190,7,82,6,132,7,50,63,249,1,212,
-129,204,253,128,64,8,192,8,223,96,48,2,48,2,79,216,20,0,140,0,153,246,7,
-128,35,0,35,0,36,253,130,96,8,192,8,192,9,159,96,176,2,152,2,167,216,52,0,
-166,0,169,246,39,2,162,2,163,125,138,64,168,128,166,191,98,176,42,32,41,
-223,216,180,10,156,10,141,246,47,2,162,2,158,128,
+104,28,112,32,67,0,65,4,0,138,0,128,4,1,88,65,76,83,8,104,14,72,43,16,253,
+28,189,6,39,240,39,224,24,114,12,16,132,16,248,0,248,64,129,241,1,241,128,
+195,228,3,229,2,7,204,7,206,4,15,160,15,164,6,31,96,31,104,16,62,224,63,
+116,8,125,200,127,32,32,251,176,254,208,33,247,129,255,128,67,239,67,253,
+64,135,223,7,254,129,15,216,15,220,2,31,208,31,216,4,63,192,63,208,8,133,
+192,133,128,129,38,129,37,177,162,195,2,192,5,229,160,2,20,9,170,220,4,232,
+40,127,160,255,144,154,136,4,4,4,0,192,9,152,9,144,48,19,160,19,145,0,41,
+96,41,69,192,94,128,94,65,128,193,128,193,2,1,161,1,160,6,3,104,3,102,8,7,
+56,7,52,64,14,248,14,240,144,31,144,31,130,128,68,96,68,66,64,145,192,145,
+130,129,184,129,184,2,3,217,3,216,24,8,194,8,192,68,18,44,18,40,216,38,16,
+38,8,112,77,16,77,6,3,192,35,192,18,199,168,71,168,24,15,168,143,172,132,
+44,104,44,103,6,89,2,89,0,200,179,176,179,172,21,50,13,50,1,122,104,26,104,
+1,212,228,116,228,65,233,204,233,204,143,211,189,83,188,130,167,127,167,
+126,11,79,35,79,32,10,158,94,158,88,85,61,173,61,160,97,192,107,64,107,1,0,
+226,128,226,3,1,198,1,196,6,3,228,3,226,8,10,0,6,152,16,31,192,31,184,34,
+199,50,199,32,65,128,196,0,195,130,1,185,1,184,4,4,205,79,84,8,0,192,143,0,
+142,193,1,52,128,203,2,45,39,16,199,5,253,0,11,80,57,192,15,240,23,128,19,
+16,4,144,23,240,5,48,24,0,36,48,25,32,25,16,25,80,31,96,25,144,25,128,25,
+160,35,208,25,224,34,0,26,128,26,112,27,240,31,112,29,208,24,224,31,48,31,
+16,37,2,198,240,37,18,198,208,37,34,199,0,37,48,24,16,37,64,24,96,37,144,
+24,240,37,176,25,0,37,202,122,176,38,0,25,48,38,26,122,192,38,48,25,64,38,
+90,120,208,38,128,25,112,38,178,198,32,38,202,122,208,39,18,198,224,39,32,
+25,208,39,80,25,240,39,210,198,64,40,42,124,80,40,122,123,16,40,128,26,224,
+40,144,36,64,40,192,36,80,41,32,27,112,41,218,123,32,41,234,123,0,52,80,57,
+144,55,112,55,96,58,192,56,96,60,32,58,48,60,192,56,192,61,0,57,32,61,16,
+57,128,61,80,58,96,61,96,58,0,61,112,60,240,63,0,57,160,63,16,58,16,63,32,
+63,144,63,48,55,240,63,80,57,80,76,240,76,1,200,0,65,33,200,16,65,65,200,
+32,65,225,200,80,66,33,200,96,66,161,200,112,70,33,200,138,100,161,215,154,
+119,209,215,210,198,49,216,234,124,97,233,177,230,1,251,224,57,145,254,81,
+254,194,20,226,19,34,24,66,24,50,198,18,198,2,198,80,35,162,198,96,35,226,
+207,50,207,42,120,202,120,186,121,74,124,74,124,58,124,42,181,58,123,60,
+192,27,240,2,152,2,152,10,76,5,120,0,156,3,225,0,37,1,134,1,200,96,115,32,
+97,0,96,32,118,24,29,40,24,64,24,8,44,60,10,106,10,164,61,45,0,36,1,152,
+143,75,192,10,128,97,3,211,16,2,184,24,80,244,204,0,178,6,20,61,53,0,32,
+129,95,15,168,64,116,160,98,99,234,88,29,40,24,152,24,0,250,166,7,74,6,38,
+6,2,62,173,129,210,129,137,129,161,15,192,67,225,0,115,35,240,48,248,72,28,
+200,252,20,62,20,7,50,63,7,15,133,129,204,143,194,67,225,128,115,35,240,
+176,248,104,28,200,252,52,62,28,7,50,63,15,15,135,129,204,143,196,67,225,0,
+115,35,241,48,248,72,28,200,252,84,62,20,7,50,63,23,15,133,129,204,143,198,
+67,225,128,115,35,241,176,248,104,28,200,252,116,62,28,7,50,63,31,15,135,
+129,204,143,200,67,229,0,115,35,242,48,249,72,28,200,252,148,62,84,7,50,63,
+39,15,149,129,204,143,202,67,229,128,115,35,242,176,249,104,28,200,252,180,
+62,92,7,50,63,47,15,151,129,204,143,204,67,229,0,115,35,243,48,249,72,28,
+200,252,212,62,84,7,50,63,55,15,149,129,204,143,206,67,229,128,115,35,243,
+176,249,104,28,200,252,244,62,92,7,50,63,63,15,151,129,204,143,208,67,237,
+0,115,35,244,48,251,72,28,200,253,20,62,212,7,50,63,71,15,181,129,204,143,
+210,67,237,128,115,35,244,176,251,104,28,200,253,52,62,220,7,50,63,79,15,
+183,129,204,143,212,67,237,0,115,35,245,48,251,72,28,200,253,84,62,212,7,
+50,63,87,15,181,129,204,143,214,67,237,128,115,35,245,176,251,104,28,200,
+253,116,62,220,7,50,63,95,15,183,129,204,143,217,67,247,64,115,35,246,112,
+28,136,28,200,253,164,7,12,7,50,63,109,1,200,129,161,15,219,224,114,32,104,
+64,115,35,247,144,28,136,28,200,254,20,63,148,7,50,63,135,1,203,129,204,
+143,226,64,113,32,115,35,248,208,28,184,26,16,254,62,7,46,6,132,7,50,63,
+153,1,203,129,204,143,233,96,115,32,97,0,96,3,250,120,28,200,24,64,24,8,
+254,180,7,50,6,132,63,175,129,204,129,132,1,161,15,241,96,116,160,97,0,96,
+3,252,120,29,40,24,64,24,8,255,36,7,66,6,38,63,205,1,210,129,161,15,243,
+224,116,160,97,0,104,67,254,80,255,208,28,200,255,156,7,82,7,50,63,233,1,
+199,129,204,143,251,64,117,32,104,67,254,248,29,72,26,16,28,200,255,228,7,
+82,7,51,246,1,0,35,0,35,125,128,192,8,192,9,63,96,80,2,48,2,103,216,30,0,
+140,0,140,0,147,246,9,128,35,0,35,0,38,125,130,192,10,96,10,159,96,208,2,
+152,2,167,216,156,10,136,10,141,246,41,2,162,2,154,253,138,192,168,128,167,
+127,98,208,42,112,42,55,216,188,10,136,10,122,
};
-const duk_uint8_t duk_unicode_caseconv_lc[680] = {
-152,3,0,3,128,184,6,192,7,192,112,24,144,37,96,64,54,32,81,64,128,226,0,
+const duk_uint8_t duk_unicode_caseconv_lc[706] = {
+160,3,0,3,128,184,6,192,7,192,112,24,144,37,96,64,54,32,81,64,128,226,0,
235,65,129,199,1,230,130,3,145,3,177,34,7,70,7,134,36,15,244,13,236,24,32,
0,34,129,0,65,0,67,4,0,166,32,172,41,132,40,11,64,19,9,208,85,184,80,19,
-240,19,248,12,62,16,62,0,32,124,96,124,64,48,249,64,249,0,129,243,129,243,
-1,3,233,3,232,1,135,218,7,216,4,15,196,15,192,8,31,152,31,144,16,63,80,63,
-64,32,126,224,126,192,16,253,208,251,128,33,252,129,247,32,131,251,3,250,0,
-135,246,135,221,129,15,244,15,240,2,31,234,31,122,4,63,240,62,240,8,127,
-232,125,240,17,11,1,11,129,2,75,98,77,3,69,128,5,134,11,203,31,128,143,193,
-127,144,255,160,154,140,4,0,4,4,192,9,144,9,152,48,19,144,19,161,0,41,64,
-41,101,192,94,64,94,129,128,193,0,193,130,1,160,1,161,6,3,102,3,104,8,7,44,
-7,48,72,14,240,14,248,144,31,32,31,48,64,63,0,63,37,0,136,128,136,196,129,
-35,1,35,133,3,112,3,113,4,7,176,7,178,48,17,128,17,132,136,36,80,36,89,176,
-76,16,76,32,224,154,0,154,44,7,128,7,128,101,143,80,15,80,176,31,89,31,81,
-8,88,206,88,208,12,178,0,178,5,145,103,89,103,96,42,100,10,100,18,244,208,
-20,208,35,169,200,169,200,195,211,153,83,153,159,167,121,167,122,5,78,253,
-78,254,22,158,66,158,68,21,60,181,60,184,170,123,74,123,80,67,0,211,1,64,2,
-1,172,1,173,4,3,136,3,140,12,7,20,7,24,16,31,184,31,192,34,199,34,199,48,
-65,128,195,128,196,2,1,184,1,185,5,79,84,4,204,8,0,192,101,128,154,65,1,29,
-129,30,2,16,199,45,39,5,251,240,23,128,15,240,24,16,37,48,24,96,37,64,24,
-224,29,208,24,240,37,144,25,0,37,176,25,16,25,32,25,48,38,0,25,64,38,48,25,
-112,38,128,25,128,25,144,25,208,39,32,25,240,39,80,26,112,26,128,26,224,40,
-128,27,112,41,32,31,16,31,48,31,96,25,80,31,112,27,240,34,0,25,224,35,162,
-198,80,35,208,25,160,35,226,198,96,36,48,24,0,36,64,40,144,36,80,40,192,55,
-96,55,112,55,240,63,48,56,96,58,192,56,192,60,192,60,240,61,112,63,64,59,
-128,63,144,63,32,76,0,76,241,233,224,13,241,251,193,251,49,252,193,252,49,
-254,193,254,81,255,193,255,50,18,96,60,146,18,160,6,178,18,176,14,82,19,34,
-20,226,24,50,24,66,198,2,198,18,198,32,38,178,198,49,215,210,198,64,39,210,
-198,208,37,18,198,224,39,18,198,240,37,2,199,0,37,34,207,34,207,58,119,209,
-215,154,120,186,120,202,120,208,38,90,122,176,37,202,122,192,38,26,122,208,
-38,202,123,0,41,234,123,16,40,122,123,32,41,218,123,58,181,48,32,38,16,3,
-72,24,56,
+240,19,248,12,57,32,33,160,172,114,244,67,244,24,248,64,248,0,129,241,129,
+241,0,195,229,3,228,2,7,206,7,204,4,15,164,15,160,6,31,104,31,96,16,63,16,
+63,0,32,126,96,126,64,64,253,64,253,0,129,251,129,251,0,67,247,67,238,0,
+135,242,7,220,130,15,236,15,232,2,31,218,31,118,4,63,208,63,192,8,127,168,
+125,232,16,255,192,251,192,33,255,161,247,192,68,44,4,46,4,9,45,137,52,13,
+22,0,22,24,47,44,126,2,63,5,254,67,254,130,106,48,16,0,16,19,0,38,64,38,96,
+192,78,64,78,132,0,165,0,165,151,1,121,1,122,6,3,4,3,6,8,6,128,6,132,24,13,
+152,13,160,32,28,176,28,193,32,59,192,59,226,64,124,128,124,193,0,252,0,
+252,148,2,34,2,35,18,4,140,4,142,20,13,192,13,196,16,30,192,30,200,192,70,
+0,70,18,32,145,64,145,102,193,48,65,48,131,130,104,2,104,176,30,0,30,1,150,
+61,64,61,66,192,125,100,125,68,33,99,57,99,64,50,200,2,200,22,69,157,101,
+157,128,169,144,41,144,75,211,64,83,64,142,167,34,167,35,15,78,101,78,102,
+126,157,230,157,232,21,59,245,59,248,90,121,10,121,16,84,242,212,242,226,
+169,237,41,237,67,12,3,76,5,0,8,6,176,6,180,16,14,32,14,48,48,28,80,28,96,
+64,126,224,127,0,139,28,139,28,193,6,3,14,3,16,8,6,224,6,228,21,61,80,19,
+48,32,3,1,150,2,105,4,4,118,4,120,8,67,28,180,156,23,240,192,94,0,63,192,
+96,64,148,192,97,128,149,0,99,128,119,64,99,192,150,64,100,0,150,192,100,
+64,100,128,100,192,152,0,101,0,152,192,101,192,154,0,102,0,102,64,103,64,
+156,128,103,192,157,64,105,192,106,0,107,128,162,0,109,192,164,128,124,64,
+124,192,125,128,101,64,125,192,111,192,136,0,103,128,142,139,25,64,143,64,
+102,128,143,139,25,128,144,192,96,0,145,0,162,64,145,64,163,0,221,128,221,
+192,223,192,252,192,225,128,235,0,227,0,243,0,243,192,245,192,253,0,238,0,
+254,64,252,129,48,1,51,199,167,128,55,199,239,7,236,199,243,7,240,199,251,
+7,249,71,255,7,252,200,73,128,242,72,74,128,26,200,74,192,57,72,76,136,83,
+136,96,200,97,11,24,11,24,75,24,128,154,203,24,199,95,75,25,0,159,75,27,64,
+148,75,27,128,156,75,27,192,148,11,28,0,148,139,60,139,60,233,223,71,94,
+105,226,233,227,41,227,64,153,105,234,192,151,41,235,0,152,105,235,64,155,
+41,236,0,167,169,236,64,161,233,236,128,167,105,236,234,212,233,240,169,
+240,233,241,41,229,41,241,64,160,169,241,135,99,128,128,152,64,13,32,96,
+224,
};
#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
@@ -88439,5797 +94151,5798 @@ const duk_uint16_t duk_unicode_re_canon_lookup[65536] = {
11373,11376,385,390,597,393,394,600,399,602,400,42923L,605,606,607,403,
42924L,610,404,612,42893L,42922L,615,407,406,42926L,11362,42925L,621,622,
412,624,11374,413,627,628,415,630,631,632,633,634,635,636,11364,638,639,
-422,641,642,425,644,645,646,42929L,430,580,433,434,581,653,654,655,656,657,
-439,659,660,661,662,663,664,665,666,667,668,42930L,42928L,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,
-921,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,880,882,882,884,885,886,886,888,889,890,
-1021,1022,1023,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,902,904,905,906,944,
-913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,
-931,932,933,934,935,936,937,938,939,908,910,911,975,914,920,978,979,980,
-934,928,975,984,984,986,986,988,988,990,990,992,992,994,994,996,996,998,
-998,1000,1000,1002,1002,1004,1004,1006,1006,922,929,1017,895,1012,917,1014,
-1015,1015,1017,1018,1018,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,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,1024,
-1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,
-1120,1120,1122,1122,1124,1124,1126,1126,1128,1128,1130,1130,1132,1132,1134,
-1134,1136,1136,1138,1138,1140,1140,1142,1142,1144,1144,1146,1146,1148,1148,
-1150,1150,1152,1152,1154,1155,1156,1157,1158,1159,1160,1161,1162,1162,1164,
-1164,1166,1166,1168,1168,1170,1170,1172,1172,1174,1174,1176,1176,1178,1178,
-1180,1180,1182,1182,1184,1184,1186,1186,1188,1188,1190,1190,1192,1192,1194,
-1194,1196,1196,1198,1198,1200,1200,1202,1202,1204,1204,1206,1206,1208,1208,
-1210,1210,1212,1212,1214,1214,1216,1217,1217,1219,1219,1221,1221,1223,1223,
-1225,1225,1227,1227,1229,1229,1216,1232,1232,1234,1234,1236,1236,1238,1238,
-1240,1240,1242,1242,1244,1244,1246,1246,1248,1248,1250,1250,1252,1252,1254,
-1254,1256,1256,1258,1258,1260,1260,1262,1262,1264,1264,1266,1266,1268,1268,
-1270,1270,1272,1272,1274,1274,1276,1276,1278,1278,1280,1280,1282,1282,1284,
-1284,1286,1286,1288,1288,1290,1290,1292,1292,1294,1294,1296,1296,1298,1298,
-1300,1300,1302,1302,1304,1304,1306,1306,1308,1308,1310,1310,1312,1312,1314,
-1314,1316,1316,1318,1318,1320,1320,1322,1322,1324,1324,1326,1326,1328,1329,
-1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,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,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,
-1375,1376,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,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,1365,1366,1415,1416,1417,1418,1419,
-1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,
-1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,
-1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,
-1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,
-1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,
-1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,
-1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,
-1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,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,
-1570,1571,1572,1573,1574,1575,1576,1577,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,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,
-1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,
-1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,
-1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,
-1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,
-1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,
-1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,
-1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,
-1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,
-1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,
-1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,
-1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,
-1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,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,1896,1897,1898,1899,
-1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,
-1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,
-1930,1931,1932,1933,1934,1935,1936,1937,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,1973,1974,
-1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,
-1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,
-2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,
-2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,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,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,
-2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,
-2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,
-2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,
-2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,
-2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,
-2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,
-2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,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,2224,2225,2226,2227,2228,2229,
-2230,2231,2232,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,2258,2259,
-2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,
-2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,
-2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,
-2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,
-2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,
-2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,
-2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,
-2365,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,
-2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,
-2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,
-2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,2424,
-2425,2426,2427,2428,2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,2439,
-2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,
-2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,
-2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,2484,
-2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,
-2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,
-2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,2529,
-2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,2544,
-2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,2559,
-2560,2561,2562,2563,2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,2574,
-2575,2576,2577,2578,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,2589,
-2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2601,2602,2603,2604,
-2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,
-2620,2621,2622,2623,2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,2634,
-2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,2649,
-2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,2664,
-2665,2666,2667,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2679,
-2680,2681,2682,2683,2684,2685,2686,2687,2688,2689,2690,2691,2692,2693,2694,
-2695,2696,2697,2698,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,2709,
-2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,
-2725,2726,2727,2728,2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,2739,
-2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,2754,
-2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,2769,
-2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,2784,
-2785,2786,2787,2788,2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,2799,
-2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,
-2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,
-2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844,
-2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,
-2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,
-2875,2876,2877,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,
-2890,2891,2892,2893,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,
-2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,2919,
-2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,2934,
-2935,2936,2937,2938,2939,2940,2941,2942,2943,2944,2945,2946,2947,2948,2949,
-2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,2964,
-2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,2979,
-2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,2994,
-2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,3009,
-3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,3024,
-3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,3039,
-3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3054,
-3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,3069,
-3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,
-3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,
-3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,3114,
-3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,3129,
-3130,3131,3132,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,3144,
-3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,3159,
-3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,
-3175,3176,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187,3188,3189,
-3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201,3202,3203,3204,
-3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,3219,
-3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,3234,
-3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,3249,
-3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,3264,
-3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,3279,
-3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,3294,
-3295,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,
-3310,3311,3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,
-3325,3326,3327,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,
-3340,3341,3342,3343,3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,3354,
-3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369,
-3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,
-3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,
-3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,3414,
-3415,3416,3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,3429,
-3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,
-3445,3446,3447,3448,3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,3459,
-3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,
-3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,3489,
-3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,
-3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,3519,
-3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,3534,
-3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,3549,
-3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,3564,
-3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,3579,
-3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,
-3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,
-3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,
-3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,
-3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,
-3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,
-3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,3684,
-3685,3686,3687,3688,3689,3690,3691,3692,3693,3694,3695,3696,3697,3698,3699,
-3700,3701,3702,3703,3704,3705,3706,3707,3708,3709,3710,3711,3712,3713,3714,
-3715,3716,3717,3718,3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,3729,
-3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,3744,
-3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,
-3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,
-3775,3776,3777,3778,3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,3789,
-3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3802,3803,3804,
-3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,3819,
-3820,3821,3822,3823,3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,3834,
-3835,3836,3837,3838,3839,3840,3841,3842,3843,3844,3845,3846,3847,3848,3849,
-3850,3851,3852,3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,3864,
-3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,3879,
-3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,3894,
-3895,3896,3897,3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,3909,
-3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,
-3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,
-3940,3941,3942,3943,3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,3954,
-3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,
-3970,3971,3972,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,3984,
-3985,3986,3987,3988,3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,3999,
-4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,
-4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4029,
-4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,
-4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,4059,
-4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,
-4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,
-4090,4091,4092,4093,4094,4095,4096,4097,4098,4099,4100,4101,4102,4103,4104,
-4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,4119,
-4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,
-4135,4136,4137,4138,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,
-4150,4151,4152,4153,4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,4164,
-4165,4166,4167,4168,4169,4170,4171,4172,4173,4174,4175,4176,4177,4178,4179,
-4180,4181,4182,4183,4184,4185,4186,4187,4188,4189,4190,4191,4192,4193,4194,
-4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205,4206,4207,4208,4209,
-4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,4224,
-4225,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4238,4239,
-4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,4254,
-4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,
-4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,
-4285,4286,4287,4288,4289,4290,4291,4292,4293,4294,4295,4296,4297,4298,4299,
-4300,4301,4302,4303,4304,4305,4306,4307,4308,4309,4310,4311,4312,4313,4314,
-4315,4316,4317,4318,4319,4320,4321,4322,4323,4324,4325,4326,4327,4328,4329,
-4330,4331,4332,4333,4334,4335,4336,4337,4338,4339,4340,4341,4342,4343,4344,
-4345,4346,4347,4348,4349,4350,4351,4352,4353,4354,4355,4356,4357,4358,4359,
-4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,4374,
-4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,4389,
-4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,4404,
-4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416,4417,4418,4419,
-4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,4434,
-4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,4449,
-4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,4464,
-4465,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,4479,
-4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,4494,
-4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,4509,
-4510,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,4524,
-4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,4539,
-4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,4554,
-4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,4569,
-4570,4571,4572,4573,4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,4584,
-4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,4599,
-4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,4614,
-4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,4629,
-4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,4644,
-4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,4659,
-4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,4674,
-4675,4676,4677,4678,4679,4680,4681,4682,4683,4684,4685,4686,4687,4688,4689,
-4690,4691,4692,4693,4694,4695,4696,4697,4698,4699,4700,4701,4702,4703,4704,
-4705,4706,4707,4708,4709,4710,4711,4712,4713,4714,4715,4716,4717,4718,4719,
-4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,4734,
-4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4745,4746,4747,4748,4749,
-4750,4751,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,4764,
-4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,4779,
-4780,4781,4782,4783,4784,4785,4786,4787,4788,4789,4790,4791,4792,4793,4794,
-4795,4796,4797,4798,4799,4800,4801,4802,4803,4804,4805,4806,4807,4808,4809,
-4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4823,4824,
-4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,4839,
-4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,4854,
-4855,4856,4857,4858,4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,4869,
-4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4881,4882,4883,4884,
-4885,4886,4887,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,4899,
-4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,4914,
-4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,4929,
-4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,4944,
-4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4955,4956,4957,4958,4959,
-4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970,4971,4972,4973,4974,
-4975,4976,4977,4978,4979,4980,4981,4982,4983,4984,4985,4986,4987,4988,4989,
-4990,4991,4992,4993,4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,5004,
-5005,5006,5007,5008,5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,5019,
-5020,5021,5022,5023,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,
-5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,
-5050,5051,5052,5053,5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,
-5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,
-5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,
-5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,5109,
-5110,5111,5104,5105,5106,5107,5108,5109,5118,5119,5120,5121,5122,5123,5124,
-5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,5139,
-5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,5154,
-5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,5169,
-5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,5184,
-5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,5199,
-5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,5214,
-5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,
-5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,
-5245,5246,5247,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,5259,
-5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,
-5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,5289,
-5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,
-5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,
-5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,5334,
-5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,5349,
-5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,5364,
-5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379,
-5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,
-5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,
-5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424,
-5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,
-5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,
-5455,5456,5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,
-5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,
-5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,
-5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,
-5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,5529,
-5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,5544,
-5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,5559,
-5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570,5571,5572,5573,5574,
-5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585,5586,5587,5588,5589,
-5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600,5601,5602,5603,5604,
-5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616,5617,5618,5619,
-5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632,5633,5634,
-5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648,5649,
-5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664,
-5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,
-5680,5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,
-5695,5696,5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,
-5710,5711,5712,5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,
-5725,5726,5727,5728,5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,
-5740,5741,5742,5743,5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,
-5755,5756,5757,5758,5759,5760,5761,5762,5763,5764,5765,5766,5767,5768,5769,
-5770,5771,5772,5773,5774,5775,5776,5777,5778,5779,5780,5781,5782,5783,5784,
-5785,5786,5787,5788,5789,5790,5791,5792,5793,5794,5795,5796,5797,5798,5799,
-5800,5801,5802,5803,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,5814,
-5815,5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,5829,
-5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844,
-5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,5859,
-5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872,5873,5874,
-5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888,5889,
-5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904,
-5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,
-5920,5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,
-5935,5936,5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,
-5950,5951,5952,5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,
-5965,5966,5967,5968,5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,
-5980,5981,5982,5983,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,
-5995,5996,5997,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6008,6009,
-6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020,6021,6022,6023,6024,
-6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,6039,
-6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,6054,
-6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068,6069,
-6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,
-6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,
-6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,
-6115,6116,6117,6118,6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,6129,
-6130,6131,6132,6133,6134,6135,6136,6137,6138,6139,6140,6141,6142,6143,6144,
-6145,6146,6147,6148,6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,6159,
-6160,6161,6162,6163,6164,6165,6166,6167,6168,6169,6170,6171,6172,6173,6174,
-6175,6176,6177,6178,6179,6180,6181,6182,6183,6184,6185,6186,6187,6188,6189,
-6190,6191,6192,6193,6194,6195,6196,6197,6198,6199,6200,6201,6202,6203,6204,
-6205,6206,6207,6208,6209,6210,6211,6212,6213,6214,6215,6216,6217,6218,6219,
-6220,6221,6222,6223,6224,6225,6226,6227,6228,6229,6230,6231,6232,6233,6234,
-6235,6236,6237,6238,6239,6240,6241,6242,6243,6244,6245,6246,6247,6248,6249,
-6250,6251,6252,6253,6254,6255,6256,6257,6258,6259,6260,6261,6262,6263,6264,
-6265,6266,6267,6268,6269,6270,6271,6272,6273,6274,6275,6276,6277,6278,6279,
-6280,6281,6282,6283,6284,6285,6286,6287,6288,6289,6290,6291,6292,6293,6294,
-6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305,6306,6307,6308,6309,
-6310,6311,6312,6313,6314,6315,6316,6317,6318,6319,6320,6321,6322,6323,6324,
-6325,6326,6327,6328,6329,6330,6331,6332,6333,6334,6335,6336,6337,6338,6339,
-6340,6341,6342,6343,6344,6345,6346,6347,6348,6349,6350,6351,6352,6353,6354,
-6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365,6366,6367,6368,6369,
-6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381,6382,6383,6384,
-6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395,6396,6397,6398,6399,
-6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,6414,
-6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,6426,6427,6428,6429,
-6430,6431,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,6444,
-6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,6459,
-6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472,6473,6474,
-6475,6476,6477,6478,6479,6480,6481,6482,6483,6484,6485,6486,6487,6488,6489,
-6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,6504,
-6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516,6517,6518,6519,
-6520,6521,6522,6523,6524,6525,6526,6527,6528,6529,6530,6531,6532,6533,6534,
-6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,6549,
-6550,6551,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,6564,
-6565,6566,6567,6568,6569,6570,6571,6572,6573,6574,6575,6576,6577,6578,6579,
-6580,6581,6582,6583,6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,6594,
-6595,6596,6597,6598,6599,6600,6601,6602,6603,6604,6605,6606,6607,6608,6609,
-6610,6611,6612,6613,6614,6615,6616,6617,6618,6619,6620,6621,6622,6623,6624,
-6625,6626,6627,6628,6629,6630,6631,6632,6633,6634,6635,6636,6637,6638,6639,
-6640,6641,6642,6643,6644,6645,6646,6647,6648,6649,6650,6651,6652,6653,6654,
-6655,6656,6657,6658,6659,6660,6661,6662,6663,6664,6665,6666,6667,6668,6669,
-6670,6671,6672,6673,6674,6675,6676,6677,6678,6679,6680,6681,6682,6683,6684,
-6685,6686,6687,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,6698,6699,
-6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,6714,
-6715,6716,6717,6718,6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,6729,
-6730,6731,6732,6733,6734,6735,6736,6737,6738,6739,6740,6741,6742,6743,6744,
-6745,6746,6747,6748,6749,6750,6751,6752,6753,6754,6755,6756,6757,6758,6759,
-6760,6761,6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,
-6775,6776,6777,6778,6779,6780,6781,6782,6783,6784,6785,6786,6787,6788,6789,
-6790,6791,6792,6793,6794,6795,6796,6797,6798,6799,6800,6801,6802,6803,6804,
-6805,6806,6807,6808,6809,6810,6811,6812,6813,6814,6815,6816,6817,6818,6819,
-6820,6821,6822,6823,6824,6825,6826,6827,6828,6829,6830,6831,6832,6833,6834,
-6835,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,6847,6848,6849,
-6850,6851,6852,6853,6854,6855,6856,6857,6858,6859,6860,6861,6862,6863,6864,
-6865,6866,6867,6868,6869,6870,6871,6872,6873,6874,6875,6876,6877,6878,6879,
-6880,6881,6882,6883,6884,6885,6886,6887,6888,6889,6890,6891,6892,6893,6894,
-6895,6896,6897,6898,6899,6900,6901,6902,6903,6904,6905,6906,6907,6908,6909,
-6910,6911,6912,6913,6914,6915,6916,6917,6918,6919,6920,6921,6922,6923,6924,
-6925,6926,6927,6928,6929,6930,6931,6932,6933,6934,6935,6936,6937,6938,6939,
-6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,6954,
-6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966,6967,6968,6969,
-6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,6981,6982,6983,6984,
-6985,6986,6987,6988,6989,6990,6991,6992,6993,6994,6995,6996,6997,6998,6999,
-7000,7001,7002,7003,7004,7005,7006,7007,7008,7009,7010,7011,7012,7013,7014,
-7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027,7028,7029,
-7030,7031,7032,7033,7034,7035,7036,7037,7038,7039,7040,7041,7042,7043,7044,
-7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,7059,
-7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,7071,7072,7073,7074,
-7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7086,7087,7088,7089,
-7090,7091,7092,7093,7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,7104,
-7105,7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,7119,
-7120,7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,
-7135,7136,7137,7138,7139,7140,7141,7142,7143,7144,7145,7146,7147,7148,7149,
-7150,7151,7152,7153,7154,7155,7156,7157,7158,7159,7160,7161,7162,7163,7164,
-7165,7166,7167,7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,7179,
-7180,7181,7182,7183,7184,7185,7186,7187,7188,7189,7190,7191,7192,7193,7194,
-7195,7196,7197,7198,7199,7200,7201,7202,7203,7204,7205,7206,7207,7208,7209,
-7210,7211,7212,7213,7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7224,
-7225,7226,7227,7228,7229,7230,7231,7232,7233,7234,7235,7236,7237,7238,7239,
-7240,7241,7242,7243,7244,7245,7246,7247,7248,7249,7250,7251,7252,7253,7254,
-7255,7256,7257,7258,7259,7260,7261,7262,7263,7264,7265,7266,7267,7268,7269,
-7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280,7281,7282,7283,7284,
-7285,7286,7287,7288,7289,7290,7291,7292,7293,7294,7295,1042,1044,1054,1057,
-1058,1058,1066,1122,42570L,7305,7306,7307,7308,7309,7310,7311,7312,7313,
-7314,7315,7316,7317,7318,7319,7320,7321,7322,7323,7324,7325,7326,7327,7328,
-7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339,7340,7341,7342,7343,
-7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,7354,7355,7356,7357,7358,
-7359,7360,7361,7362,7363,7364,7365,7366,7367,7368,7369,7370,7371,7372,7373,
-7374,7375,7376,7377,7378,7379,7380,7381,7382,7383,7384,7385,7386,7387,7388,
-7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400,7401,7402,7403,
-7404,7405,7406,7407,7408,7409,7410,7411,7412,7413,7414,7415,7416,7417,7418,
-7419,7420,7421,7422,7423,7424,7425,7426,7427,7428,7429,7430,7431,7432,7433,
-7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447,7448,
-7449,7450,7451,7452,7453,7454,7455,7456,7457,7458,7459,7460,7461,7462,7463,
-7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,7475,7476,7477,7478,
-7479,7480,7481,7482,7483,7484,7485,7486,7487,7488,7489,7490,7491,7492,7493,
-7494,7495,7496,7497,7498,7499,7500,7501,7502,7503,7504,7505,7506,7507,7508,
-7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,7522,7523,
-7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537,7538,
-7539,7540,7541,7542,7543,7544,42877L,7546,7547,7548,11363,7550,7551,7552,
-7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,7566,7567,
-7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,7580,7581,7582,
-7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,7595,7596,7597,
-7598,7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,7610,7611,7612,
-7613,7614,7615,7616,7617,7618,7619,7620,7621,7622,7623,7624,7625,7626,7627,
-7628,7629,7630,7631,7632,7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,
-7643,7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,
-7658,7659,7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,7670,7671,7672,
-7673,7674,7675,7676,7677,7678,7679,7680,7680,7682,7682,7684,7684,7686,7686,
-7688,7688,7690,7690,7692,7692,7694,7694,7696,7696,7698,7698,7700,7700,7702,
-7702,7704,7704,7706,7706,7708,7708,7710,7710,7712,7712,7714,7714,7716,7716,
-7718,7718,7720,7720,7722,7722,7724,7724,7726,7726,7728,7728,7730,7730,7732,
-7732,7734,7734,7736,7736,7738,7738,7740,7740,7742,7742,7744,7744,7746,7746,
-7748,7748,7750,7750,7752,7752,7754,7754,7756,7756,7758,7758,7760,7760,7762,
-7762,7764,7764,7766,7766,7768,7768,7770,7770,7772,7772,7774,7774,7776,7776,
-7778,7778,7780,7780,7782,7782,7784,7784,7786,7786,7788,7788,7790,7790,7792,
-7792,7794,7794,7796,7796,7798,7798,7800,7800,7802,7802,7804,7804,7806,7806,
-7808,7808,7810,7810,7812,7812,7814,7814,7816,7816,7818,7818,7820,7820,7822,
-7822,7824,7824,7826,7826,7828,7828,7830,7831,7832,7833,7834,7776,7836,7837,
-7838,7839,7840,7840,7842,7842,7844,7844,7846,7846,7848,7848,7850,7850,7852,
-7852,7854,7854,7856,7856,7858,7858,7860,7860,7862,7862,7864,7864,7866,7866,
-7868,7868,7870,7870,7872,7872,7874,7874,7876,7876,7878,7878,7880,7880,7882,
-7882,7884,7884,7886,7886,7888,7888,7890,7890,7892,7892,7894,7894,7896,7896,
-7898,7898,7900,7900,7902,7902,7904,7904,7906,7906,7908,7908,7910,7910,7912,
-7912,7914,7914,7916,7916,7918,7918,7920,7920,7922,7922,7924,7924,7926,7926,
-7928,7928,7930,7930,7932,7932,7934,7934,7944,7945,7946,7947,7948,7949,7950,
-7951,7944,7945,7946,7947,7948,7949,7950,7951,7960,7961,7962,7963,7964,7965,
-7958,7959,7960,7961,7962,7963,7964,7965,7966,7967,7976,7977,7978,7979,7980,
-7981,7982,7983,7976,7977,7978,7979,7980,7981,7982,7983,7992,7993,7994,7995,
-7996,7997,7998,7999,7992,7993,7994,7995,7996,7997,7998,7999,8008,8009,8010,
-8011,8012,8013,8006,8007,8008,8009,8010,8011,8012,8013,8014,8015,8016,8025,
-8018,8027,8020,8029,8022,8031,8024,8025,8026,8027,8028,8029,8030,8031,8040,
-8041,8042,8043,8044,8045,8046,8047,8040,8041,8042,8043,8044,8045,8046,8047,
-8122,8123,8136,8137,8138,8139,8154,8155,8184,8185,8170,8171,8186,8187,8062,
-8063,8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,
-8078,8079,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,
-8093,8094,8095,8096,8097,8098,8099,8100,8101,8102,8103,8104,8105,8106,8107,
-8108,8109,8110,8111,8120,8121,8114,8115,8116,8117,8118,8119,8120,8121,8122,
-8123,8124,8125,921,8127,8128,8129,8130,8131,8132,8133,8134,8135,8136,8137,
-8138,8139,8140,8141,8142,8143,8152,8153,8146,8147,8148,8149,8150,8151,8152,
-8153,8154,8155,8156,8157,8158,8159,8168,8169,8162,8163,8164,8172,8166,8167,
-8168,8169,8170,8171,8172,8173,8174,8175,8176,8177,8178,8179,8180,8181,8182,
-8183,8184,8185,8186,8187,8188,8189,8190,8191,8192,8193,8194,8195,8196,8197,
-8198,8199,8200,8201,8202,8203,8204,8205,8206,8207,8208,8209,8210,8211,8212,
-8213,8214,8215,8216,8217,8218,8219,8220,8221,8222,8223,8224,8225,8226,8227,
-8228,8229,8230,8231,8232,8233,8234,8235,8236,8237,8238,8239,8240,8241,8242,
-8243,8244,8245,8246,8247,8248,8249,8250,8251,8252,8253,8254,8255,8256,8257,
-8258,8259,8260,8261,8262,8263,8264,8265,8266,8267,8268,8269,8270,8271,8272,
-8273,8274,8275,8276,8277,8278,8279,8280,8281,8282,8283,8284,8285,8286,8287,
-8288,8289,8290,8291,8292,8293,8294,8295,8296,8297,8298,8299,8300,8301,8302,
-8303,8304,8305,8306,8307,8308,8309,8310,8311,8312,8313,8314,8315,8316,8317,
-8318,8319,8320,8321,8322,8323,8324,8325,8326,8327,8328,8329,8330,8331,8332,
-8333,8334,8335,8336,8337,8338,8339,8340,8341,8342,8343,8344,8345,8346,8347,
-8348,8349,8350,8351,8352,8353,8354,8355,8356,8357,8358,8359,8360,8361,8362,
-8363,8364,8365,8366,8367,8368,8369,8370,8371,8372,8373,8374,8375,8376,8377,
-8378,8379,8380,8381,8382,8383,8384,8385,8386,8387,8388,8389,8390,8391,8392,
-8393,8394,8395,8396,8397,8398,8399,8400,8401,8402,8403,8404,8405,8406,8407,
-8408,8409,8410,8411,8412,8413,8414,8415,8416,8417,8418,8419,8420,8421,8422,
-8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,8433,8434,8435,8436,8437,
-8438,8439,8440,8441,8442,8443,8444,8445,8446,8447,8448,8449,8450,8451,8452,
-8453,8454,8455,8456,8457,8458,8459,8460,8461,8462,8463,8464,8465,8466,8467,
-8468,8469,8470,8471,8472,8473,8474,8475,8476,8477,8478,8479,8480,8481,8482,
-8483,8484,8485,8486,8487,8488,8489,8490,8491,8492,8493,8494,8495,8496,8497,
-8498,8499,8500,8501,8502,8503,8504,8505,8506,8507,8508,8509,8510,8511,8512,
-8513,8514,8515,8516,8517,8518,8519,8520,8521,8522,8523,8524,8525,8498,8527,
-8528,8529,8530,8531,8532,8533,8534,8535,8536,8537,8538,8539,8540,8541,8542,
-8543,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,
-8558,8559,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,
-8557,8558,8559,8576,8577,8578,8579,8579,8581,8582,8583,8584,8585,8586,8587,
-8588,8589,8590,8591,8592,8593,8594,8595,8596,8597,8598,8599,8600,8601,8602,
-8603,8604,8605,8606,8607,8608,8609,8610,8611,8612,8613,8614,8615,8616,8617,
-8618,8619,8620,8621,8622,8623,8624,8625,8626,8627,8628,8629,8630,8631,8632,
-8633,8634,8635,8636,8637,8638,8639,8640,8641,8642,8643,8644,8645,8646,8647,
-8648,8649,8650,8651,8652,8653,8654,8655,8656,8657,8658,8659,8660,8661,8662,
-8663,8664,8665,8666,8667,8668,8669,8670,8671,8672,8673,8674,8675,8676,8677,
-8678,8679,8680,8681,8682,8683,8684,8685,8686,8687,8688,8689,8690,8691,8692,
-8693,8694,8695,8696,8697,8698,8699,8700,8701,8702,8703,8704,8705,8706,8707,
-8708,8709,8710,8711,8712,8713,8714,8715,8716,8717,8718,8719,8720,8721,8722,
-8723,8724,8725,8726,8727,8728,8729,8730,8731,8732,8733,8734,8735,8736,8737,
-8738,8739,8740,8741,8742,8743,8744,8745,8746,8747,8748,8749,8750,8751,8752,
-8753,8754,8755,8756,8757,8758,8759,8760,8761,8762,8763,8764,8765,8766,8767,
-8768,8769,8770,8771,8772,8773,8774,8775,8776,8777,8778,8779,8780,8781,8782,
-8783,8784,8785,8786,8787,8788,8789,8790,8791,8792,8793,8794,8795,8796,8797,
-8798,8799,8800,8801,8802,8803,8804,8805,8806,8807,8808,8809,8810,8811,8812,
-8813,8814,8815,8816,8817,8818,8819,8820,8821,8822,8823,8824,8825,8826,8827,
-8828,8829,8830,8831,8832,8833,8834,8835,8836,8837,8838,8839,8840,8841,8842,
-8843,8844,8845,8846,8847,8848,8849,8850,8851,8852,8853,8854,8855,8856,8857,
-8858,8859,8860,8861,8862,8863,8864,8865,8866,8867,8868,8869,8870,8871,8872,
-8873,8874,8875,8876,8877,8878,8879,8880,8881,8882,8883,8884,8885,8886,8887,
-8888,8889,8890,8891,8892,8893,8894,8895,8896,8897,8898,8899,8900,8901,8902,
-8903,8904,8905,8906,8907,8908,8909,8910,8911,8912,8913,8914,8915,8916,8917,
-8918,8919,8920,8921,8922,8923,8924,8925,8926,8927,8928,8929,8930,8931,8932,
-8933,8934,8935,8936,8937,8938,8939,8940,8941,8942,8943,8944,8945,8946,8947,
-8948,8949,8950,8951,8952,8953,8954,8955,8956,8957,8958,8959,8960,8961,8962,
-8963,8964,8965,8966,8967,8968,8969,8970,8971,8972,8973,8974,8975,8976,8977,
-8978,8979,8980,8981,8982,8983,8984,8985,8986,8987,8988,8989,8990,8991,8992,
-8993,8994,8995,8996,8997,8998,8999,9000,9001,9002,9003,9004,9005,9006,9007,
-9008,9009,9010,9011,9012,9013,9014,9015,9016,9017,9018,9019,9020,9021,9022,
-9023,9024,9025,9026,9027,9028,9029,9030,9031,9032,9033,9034,9035,9036,9037,
-9038,9039,9040,9041,9042,9043,9044,9045,9046,9047,9048,9049,9050,9051,9052,
-9053,9054,9055,9056,9057,9058,9059,9060,9061,9062,9063,9064,9065,9066,9067,
-9068,9069,9070,9071,9072,9073,9074,9075,9076,9077,9078,9079,9080,9081,9082,
-9083,9084,9085,9086,9087,9088,9089,9090,9091,9092,9093,9094,9095,9096,9097,
-9098,9099,9100,9101,9102,9103,9104,9105,9106,9107,9108,9109,9110,9111,9112,
-9113,9114,9115,9116,9117,9118,9119,9120,9121,9122,9123,9124,9125,9126,9127,
-9128,9129,9130,9131,9132,9133,9134,9135,9136,9137,9138,9139,9140,9141,9142,
-9143,9144,9145,9146,9147,9148,9149,9150,9151,9152,9153,9154,9155,9156,9157,
-9158,9159,9160,9161,9162,9163,9164,9165,9166,9167,9168,9169,9170,9171,9172,
-9173,9174,9175,9176,9177,9178,9179,9180,9181,9182,9183,9184,9185,9186,9187,
-9188,9189,9190,9191,9192,9193,9194,9195,9196,9197,9198,9199,9200,9201,9202,
-9203,9204,9205,9206,9207,9208,9209,9210,9211,9212,9213,9214,9215,9216,9217,
-9218,9219,9220,9221,9222,9223,9224,9225,9226,9227,9228,9229,9230,9231,9232,
-9233,9234,9235,9236,9237,9238,9239,9240,9241,9242,9243,9244,9245,9246,9247,
-9248,9249,9250,9251,9252,9253,9254,9255,9256,9257,9258,9259,9260,9261,9262,
-9263,9264,9265,9266,9267,9268,9269,9270,9271,9272,9273,9274,9275,9276,9277,
-9278,9279,9280,9281,9282,9283,9284,9285,9286,9287,9288,9289,9290,9291,9292,
-9293,9294,9295,9296,9297,9298,9299,9300,9301,9302,9303,9304,9305,9306,9307,
-9308,9309,9310,9311,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9322,
-9323,9324,9325,9326,9327,9328,9329,9330,9331,9332,9333,9334,9335,9336,9337,
-9338,9339,9340,9341,9342,9343,9344,9345,9346,9347,9348,9349,9350,9351,9352,
-9353,9354,9355,9356,9357,9358,9359,9360,9361,9362,9363,9364,9365,9366,9367,
-9368,9369,9370,9371,9372,9373,9374,9375,9376,9377,9378,9379,9380,9381,9382,
-9383,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,9395,9396,9397,
-9398,9399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,
-9413,9414,9415,9416,9417,9418,9419,9420,9421,9422,9423,9398,9399,9400,9401,
-9402,9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,9413,9414,9415,9416,
-9417,9418,9419,9420,9421,9422,9423,9450,9451,9452,9453,9454,9455,9456,9457,
-9458,9459,9460,9461,9462,9463,9464,9465,9466,9467,9468,9469,9470,9471,9472,
-9473,9474,9475,9476,9477,9478,9479,9480,9481,9482,9483,9484,9485,9486,9487,
-9488,9489,9490,9491,9492,9493,9494,9495,9496,9497,9498,9499,9500,9501,9502,
-9503,9504,9505,9506,9507,9508,9509,9510,9511,9512,9513,9514,9515,9516,9517,
-9518,9519,9520,9521,9522,9523,9524,9525,9526,9527,9528,9529,9530,9531,9532,
-9533,9534,9535,9536,9537,9538,9539,9540,9541,9542,9543,9544,9545,9546,9547,
-9548,9549,9550,9551,9552,9553,9554,9555,9556,9557,9558,9559,9560,9561,9562,
-9563,9564,9565,9566,9567,9568,9569,9570,9571,9572,9573,9574,9575,9576,9577,
-9578,9579,9580,9581,9582,9583,9584,9585,9586,9587,9588,9589,9590,9591,9592,
-9593,9594,9595,9596,9597,9598,9599,9600,9601,9602,9603,9604,9605,9606,9607,
-9608,9609,9610,9611,9612,9613,9614,9615,9616,9617,9618,9619,9620,9621,9622,
-9623,9624,9625,9626,9627,9628,9629,9630,9631,9632,9633,9634,9635,9636,9637,
-9638,9639,9640,9641,9642,9643,9644,9645,9646,9647,9648,9649,9650,9651,9652,
-9653,9654,9655,9656,9657,9658,9659,9660,9661,9662,9663,9664,9665,9666,9667,
-9668,9669,9670,9671,9672,9673,9674,9675,9676,9677,9678,9679,9680,9681,9682,
-9683,9684,9685,9686,9687,9688,9689,9690,9691,9692,9693,9694,9695,9696,9697,
-9698,9699,9700,9701,9702,9703,9704,9705,9706,9707,9708,9709,9710,9711,9712,
-9713,9714,9715,9716,9717,9718,9719,9720,9721,9722,9723,9724,9725,9726,9727,
-9728,9729,9730,9731,9732,9733,9734,9735,9736,9737,9738,9739,9740,9741,9742,
-9743,9744,9745,9746,9747,9748,9749,9750,9751,9752,9753,9754,9755,9756,9757,
-9758,9759,9760,9761,9762,9763,9764,9765,9766,9767,9768,9769,9770,9771,9772,
-9773,9774,9775,9776,9777,9778,9779,9780,9781,9782,9783,9784,9785,9786,9787,
-9788,9789,9790,9791,9792,9793,9794,9795,9796,9797,9798,9799,9800,9801,9802,
-9803,9804,9805,9806,9807,9808,9809,9810,9811,9812,9813,9814,9815,9816,9817,
-9818,9819,9820,9821,9822,9823,9824,9825,9826,9827,9828,9829,9830,9831,9832,
-9833,9834,9835,9836,9837,9838,9839,9840,9841,9842,9843,9844,9845,9846,9847,
-9848,9849,9850,9851,9852,9853,9854,9855,9856,9857,9858,9859,9860,9861,9862,
-9863,9864,9865,9866,9867,9868,9869,9870,9871,9872,9873,9874,9875,9876,9877,
-9878,9879,9880,9881,9882,9883,9884,9885,9886,9887,9888,9889,9890,9891,9892,
-9893,9894,9895,9896,9897,9898,9899,9900,9901,9902,9903,9904,9905,9906,9907,
-9908,9909,9910,9911,9912,9913,9914,9915,9916,9917,9918,9919,9920,9921,9922,
-9923,9924,9925,9926,9927,9928,9929,9930,9931,9932,9933,9934,9935,9936,9937,
-9938,9939,9940,9941,9942,9943,9944,9945,9946,9947,9948,9949,9950,9951,9952,
-9953,9954,9955,9956,9957,9958,9959,9960,9961,9962,9963,9964,9965,9966,9967,
-9968,9969,9970,9971,9972,9973,9974,9975,9976,9977,9978,9979,9980,9981,9982,
-9983,9984,9985,9986,9987,9988,9989,9990,9991,9992,9993,9994,9995,9996,9997,
-9998,9999,10000,10001,10002,10003,10004,10005,10006,10007,10008,10009,
-10010,10011,10012,10013,10014,10015,10016,10017,10018,10019,10020,10021,
-10022,10023,10024,10025,10026,10027,10028,10029,10030,10031,10032,10033,
-10034,10035,10036,10037,10038,10039,10040,10041,10042,10043,10044,10045,
-10046,10047,10048,10049,10050,10051,10052,10053,10054,10055,10056,10057,
-10058,10059,10060,10061,10062,10063,10064,10065,10066,10067,10068,10069,
-10070,10071,10072,10073,10074,10075,10076,10077,10078,10079,10080,10081,
-10082,10083,10084,10085,10086,10087,10088,10089,10090,10091,10092,10093,
-10094,10095,10096,10097,10098,10099,10100,10101,10102,10103,10104,10105,
-10106,10107,10108,10109,10110,10111,10112,10113,10114,10115,10116,10117,
-10118,10119,10120,10121,10122,10123,10124,10125,10126,10127,10128,10129,
-10130,10131,10132,10133,10134,10135,10136,10137,10138,10139,10140,10141,
-10142,10143,10144,10145,10146,10147,10148,10149,10150,10151,10152,10153,
-10154,10155,10156,10157,10158,10159,10160,10161,10162,10163,10164,10165,
-10166,10167,10168,10169,10170,10171,10172,10173,10174,10175,10176,10177,
-10178,10179,10180,10181,10182,10183,10184,10185,10186,10187,10188,10189,
-10190,10191,10192,10193,10194,10195,10196,10197,10198,10199,10200,10201,
-10202,10203,10204,10205,10206,10207,10208,10209,10210,10211,10212,10213,
-10214,10215,10216,10217,10218,10219,10220,10221,10222,10223,10224,10225,
-10226,10227,10228,10229,10230,10231,10232,10233,10234,10235,10236,10237,
-10238,10239,10240,10241,10242,10243,10244,10245,10246,10247,10248,10249,
-10250,10251,10252,10253,10254,10255,10256,10257,10258,10259,10260,10261,
-10262,10263,10264,10265,10266,10267,10268,10269,10270,10271,10272,10273,
-10274,10275,10276,10277,10278,10279,10280,10281,10282,10283,10284,10285,
-10286,10287,10288,10289,10290,10291,10292,10293,10294,10295,10296,10297,
-10298,10299,10300,10301,10302,10303,10304,10305,10306,10307,10308,10309,
-10310,10311,10312,10313,10314,10315,10316,10317,10318,10319,10320,10321,
-10322,10323,10324,10325,10326,10327,10328,10329,10330,10331,10332,10333,
-10334,10335,10336,10337,10338,10339,10340,10341,10342,10343,10344,10345,
-10346,10347,10348,10349,10350,10351,10352,10353,10354,10355,10356,10357,
-10358,10359,10360,10361,10362,10363,10364,10365,10366,10367,10368,10369,
-10370,10371,10372,10373,10374,10375,10376,10377,10378,10379,10380,10381,
-10382,10383,10384,10385,10386,10387,10388,10389,10390,10391,10392,10393,
-10394,10395,10396,10397,10398,10399,10400,10401,10402,10403,10404,10405,
-10406,10407,10408,10409,10410,10411,10412,10413,10414,10415,10416,10417,
-10418,10419,10420,10421,10422,10423,10424,10425,10426,10427,10428,10429,
-10430,10431,10432,10433,10434,10435,10436,10437,10438,10439,10440,10441,
-10442,10443,10444,10445,10446,10447,10448,10449,10450,10451,10452,10453,
-10454,10455,10456,10457,10458,10459,10460,10461,10462,10463,10464,10465,
-10466,10467,10468,10469,10470,10471,10472,10473,10474,10475,10476,10477,
-10478,10479,10480,10481,10482,10483,10484,10485,10486,10487,10488,10489,
-10490,10491,10492,10493,10494,10495,10496,10497,10498,10499,10500,10501,
-10502,10503,10504,10505,10506,10507,10508,10509,10510,10511,10512,10513,
-10514,10515,10516,10517,10518,10519,10520,10521,10522,10523,10524,10525,
-10526,10527,10528,10529,10530,10531,10532,10533,10534,10535,10536,10537,
-10538,10539,10540,10541,10542,10543,10544,10545,10546,10547,10548,10549,
-10550,10551,10552,10553,10554,10555,10556,10557,10558,10559,10560,10561,
-10562,10563,10564,10565,10566,10567,10568,10569,10570,10571,10572,10573,
-10574,10575,10576,10577,10578,10579,10580,10581,10582,10583,10584,10585,
-10586,10587,10588,10589,10590,10591,10592,10593,10594,10595,10596,10597,
-10598,10599,10600,10601,10602,10603,10604,10605,10606,10607,10608,10609,
-10610,10611,10612,10613,10614,10615,10616,10617,10618,10619,10620,10621,
-10622,10623,10624,10625,10626,10627,10628,10629,10630,10631,10632,10633,
-10634,10635,10636,10637,10638,10639,10640,10641,10642,10643,10644,10645,
-10646,10647,10648,10649,10650,10651,10652,10653,10654,10655,10656,10657,
-10658,10659,10660,10661,10662,10663,10664,10665,10666,10667,10668,10669,
-10670,10671,10672,10673,10674,10675,10676,10677,10678,10679,10680,10681,
-10682,10683,10684,10685,10686,10687,10688,10689,10690,10691,10692,10693,
-10694,10695,10696,10697,10698,10699,10700,10701,10702,10703,10704,10705,
-10706,10707,10708,10709,10710,10711,10712,10713,10714,10715,10716,10717,
-10718,10719,10720,10721,10722,10723,10724,10725,10726,10727,10728,10729,
-10730,10731,10732,10733,10734,10735,10736,10737,10738,10739,10740,10741,
-10742,10743,10744,10745,10746,10747,10748,10749,10750,10751,10752,10753,
-10754,10755,10756,10757,10758,10759,10760,10761,10762,10763,10764,10765,
-10766,10767,10768,10769,10770,10771,10772,10773,10774,10775,10776,10777,
-10778,10779,10780,10781,10782,10783,10784,10785,10786,10787,10788,10789,
-10790,10791,10792,10793,10794,10795,10796,10797,10798,10799,10800,10801,
-10802,10803,10804,10805,10806,10807,10808,10809,10810,10811,10812,10813,
-10814,10815,10816,10817,10818,10819,10820,10821,10822,10823,10824,10825,
-10826,10827,10828,10829,10830,10831,10832,10833,10834,10835,10836,10837,
-10838,10839,10840,10841,10842,10843,10844,10845,10846,10847,10848,10849,
-10850,10851,10852,10853,10854,10855,10856,10857,10858,10859,10860,10861,
-10862,10863,10864,10865,10866,10867,10868,10869,10870,10871,10872,10873,
-10874,10875,10876,10877,10878,10879,10880,10881,10882,10883,10884,10885,
-10886,10887,10888,10889,10890,10891,10892,10893,10894,10895,10896,10897,
-10898,10899,10900,10901,10902,10903,10904,10905,10906,10907,10908,10909,
-10910,10911,10912,10913,10914,10915,10916,10917,10918,10919,10920,10921,
-10922,10923,10924,10925,10926,10927,10928,10929,10930,10931,10932,10933,
-10934,10935,10936,10937,10938,10939,10940,10941,10942,10943,10944,10945,
-10946,10947,10948,10949,10950,10951,10952,10953,10954,10955,10956,10957,
-10958,10959,10960,10961,10962,10963,10964,10965,10966,10967,10968,10969,
-10970,10971,10972,10973,10974,10975,10976,10977,10978,10979,10980,10981,
-10982,10983,10984,10985,10986,10987,10988,10989,10990,10991,10992,10993,
-10994,10995,10996,10997,10998,10999,11000,11001,11002,11003,11004,11005,
-11006,11007,11008,11009,11010,11011,11012,11013,11014,11015,11016,11017,
-11018,11019,11020,11021,11022,11023,11024,11025,11026,11027,11028,11029,
-11030,11031,11032,11033,11034,11035,11036,11037,11038,11039,11040,11041,
-11042,11043,11044,11045,11046,11047,11048,11049,11050,11051,11052,11053,
-11054,11055,11056,11057,11058,11059,11060,11061,11062,11063,11064,11065,
-11066,11067,11068,11069,11070,11071,11072,11073,11074,11075,11076,11077,
-11078,11079,11080,11081,11082,11083,11084,11085,11086,11087,11088,11089,
-11090,11091,11092,11093,11094,11095,11096,11097,11098,11099,11100,11101,
-11102,11103,11104,11105,11106,11107,11108,11109,11110,11111,11112,11113,
-11114,11115,11116,11117,11118,11119,11120,11121,11122,11123,11124,11125,
-11126,11127,11128,11129,11130,11131,11132,11133,11134,11135,11136,11137,
-11138,11139,11140,11141,11142,11143,11144,11145,11146,11147,11148,11149,
-11150,11151,11152,11153,11154,11155,11156,11157,11158,11159,11160,11161,
-11162,11163,11164,11165,11166,11167,11168,11169,11170,11171,11172,11173,
-11174,11175,11176,11177,11178,11179,11180,11181,11182,11183,11184,11185,
-11186,11187,11188,11189,11190,11191,11192,11193,11194,11195,11196,11197,
-11198,11199,11200,11201,11202,11203,11204,11205,11206,11207,11208,11209,
-11210,11211,11212,11213,11214,11215,11216,11217,11218,11219,11220,11221,
-11222,11223,11224,11225,11226,11227,11228,11229,11230,11231,11232,11233,
-11234,11235,11236,11237,11238,11239,11240,11241,11242,11243,11244,11245,
-11246,11247,11248,11249,11250,11251,11252,11253,11254,11255,11256,11257,
-11258,11259,11260,11261,11262,11263,11264,11265,11266,11267,11268,11269,
-11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,11280,11281,
-11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,11292,11293,
-11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304,11305,
-11306,11307,11308,11309,11310,11311,11264,11265,11266,11267,11268,11269,
-11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,11280,11281,
-11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,11292,11293,
-11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304,11305,
-11306,11307,11308,11309,11310,11359,11360,11360,11362,11363,11364,570,574,
-11367,11367,11369,11369,11371,11371,11373,11374,11375,11376,11377,11378,
-11378,11380,11381,11381,11383,11384,11385,11386,11387,11388,11389,11390,
-11391,11392,11392,11394,11394,11396,11396,11398,11398,11400,11400,11402,
-11402,11404,11404,11406,11406,11408,11408,11410,11410,11412,11412,11414,
-11414,11416,11416,11418,11418,11420,11420,11422,11422,11424,11424,11426,
-11426,11428,11428,11430,11430,11432,11432,11434,11434,11436,11436,11438,
-11438,11440,11440,11442,11442,11444,11444,11446,11446,11448,11448,11450,
-11450,11452,11452,11454,11454,11456,11456,11458,11458,11460,11460,11462,
-11462,11464,11464,11466,11466,11468,11468,11470,11470,11472,11472,11474,
-11474,11476,11476,11478,11478,11480,11480,11482,11482,11484,11484,11486,
-11486,11488,11488,11490,11490,11492,11493,11494,11495,11496,11497,11498,
-11499,11499,11501,11501,11503,11504,11505,11506,11506,11508,11509,11510,
-11511,11512,11513,11514,11515,11516,11517,11518,11519,4256,4257,4258,4259,
-4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,4274,
-4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,4287,4288,4289,
-4290,4291,4292,4293,11558,4295,11560,11561,11562,11563,11564,4301,11566,
-11567,11568,11569,11570,11571,11572,11573,11574,11575,11576,11577,11578,
-11579,11580,11581,11582,11583,11584,11585,11586,11587,11588,11589,11590,
-11591,11592,11593,11594,11595,11596,11597,11598,11599,11600,11601,11602,
-11603,11604,11605,11606,11607,11608,11609,11610,11611,11612,11613,11614,
-11615,11616,11617,11618,11619,11620,11621,11622,11623,11624,11625,11626,
-11627,11628,11629,11630,11631,11632,11633,11634,11635,11636,11637,11638,
-11639,11640,11641,11642,11643,11644,11645,11646,11647,11648,11649,11650,
-11651,11652,11653,11654,11655,11656,11657,11658,11659,11660,11661,11662,
-11663,11664,11665,11666,11667,11668,11669,11670,11671,11672,11673,11674,
-11675,11676,11677,11678,11679,11680,11681,11682,11683,11684,11685,11686,
-11687,11688,11689,11690,11691,11692,11693,11694,11695,11696,11697,11698,
-11699,11700,11701,11702,11703,11704,11705,11706,11707,11708,11709,11710,
-11711,11712,11713,11714,11715,11716,11717,11718,11719,11720,11721,11722,
-11723,11724,11725,11726,11727,11728,11729,11730,11731,11732,11733,11734,
-11735,11736,11737,11738,11739,11740,11741,11742,11743,11744,11745,11746,
-11747,11748,11749,11750,11751,11752,11753,11754,11755,11756,11757,11758,
-11759,11760,11761,11762,11763,11764,11765,11766,11767,11768,11769,11770,
-11771,11772,11773,11774,11775,11776,11777,11778,11779,11780,11781,11782,
-11783,11784,11785,11786,11787,11788,11789,11790,11791,11792,11793,11794,
-11795,11796,11797,11798,11799,11800,11801,11802,11803,11804,11805,11806,
-11807,11808,11809,11810,11811,11812,11813,11814,11815,11816,11817,11818,
-11819,11820,11821,11822,11823,11824,11825,11826,11827,11828,11829,11830,
-11831,11832,11833,11834,11835,11836,11837,11838,11839,11840,11841,11842,
-11843,11844,11845,11846,11847,11848,11849,11850,11851,11852,11853,11854,
-11855,11856,11857,11858,11859,11860,11861,11862,11863,11864,11865,11866,
-11867,11868,11869,11870,11871,11872,11873,11874,11875,11876,11877,11878,
-11879,11880,11881,11882,11883,11884,11885,11886,11887,11888,11889,11890,
-11891,11892,11893,11894,11895,11896,11897,11898,11899,11900,11901,11902,
-11903,11904,11905,11906,11907,11908,11909,11910,11911,11912,11913,11914,
-11915,11916,11917,11918,11919,11920,11921,11922,11923,11924,11925,11926,
-11927,11928,11929,11930,11931,11932,11933,11934,11935,11936,11937,11938,
-11939,11940,11941,11942,11943,11944,11945,11946,11947,11948,11949,11950,
-11951,11952,11953,11954,11955,11956,11957,11958,11959,11960,11961,11962,
-11963,11964,11965,11966,11967,11968,11969,11970,11971,11972,11973,11974,
-11975,11976,11977,11978,11979,11980,11981,11982,11983,11984,11985,11986,
-11987,11988,11989,11990,11991,11992,11993,11994,11995,11996,11997,11998,
-11999,12000,12001,12002,12003,12004,12005,12006,12007,12008,12009,12010,
-12011,12012,12013,12014,12015,12016,12017,12018,12019,12020,12021,12022,
-12023,12024,12025,12026,12027,12028,12029,12030,12031,12032,12033,12034,
-12035,12036,12037,12038,12039,12040,12041,12042,12043,12044,12045,12046,
-12047,12048,12049,12050,12051,12052,12053,12054,12055,12056,12057,12058,
-12059,12060,12061,12062,12063,12064,12065,12066,12067,12068,12069,12070,
-12071,12072,12073,12074,12075,12076,12077,12078,12079,12080,12081,12082,
-12083,12084,12085,12086,12087,12088,12089,12090,12091,12092,12093,12094,
-12095,12096,12097,12098,12099,12100,12101,12102,12103,12104,12105,12106,
-12107,12108,12109,12110,12111,12112,12113,12114,12115,12116,12117,12118,
-12119,12120,12121,12122,12123,12124,12125,12126,12127,12128,12129,12130,
-12131,12132,12133,12134,12135,12136,12137,12138,12139,12140,12141,12142,
-12143,12144,12145,12146,12147,12148,12149,12150,12151,12152,12153,12154,
-12155,12156,12157,12158,12159,12160,12161,12162,12163,12164,12165,12166,
-12167,12168,12169,12170,12171,12172,12173,12174,12175,12176,12177,12178,
-12179,12180,12181,12182,12183,12184,12185,12186,12187,12188,12189,12190,
-12191,12192,12193,12194,12195,12196,12197,12198,12199,12200,12201,12202,
-12203,12204,12205,12206,12207,12208,12209,12210,12211,12212,12213,12214,
-12215,12216,12217,12218,12219,12220,12221,12222,12223,12224,12225,12226,
-12227,12228,12229,12230,12231,12232,12233,12234,12235,12236,12237,12238,
-12239,12240,12241,12242,12243,12244,12245,12246,12247,12248,12249,12250,
-12251,12252,12253,12254,12255,12256,12257,12258,12259,12260,12261,12262,
-12263,12264,12265,12266,12267,12268,12269,12270,12271,12272,12273,12274,
-12275,12276,12277,12278,12279,12280,12281,12282,12283,12284,12285,12286,
-12287,12288,12289,12290,12291,12292,12293,12294,12295,12296,12297,12298,
-12299,12300,12301,12302,12303,12304,12305,12306,12307,12308,12309,12310,
-12311,12312,12313,12314,12315,12316,12317,12318,12319,12320,12321,12322,
-12323,12324,12325,12326,12327,12328,12329,12330,12331,12332,12333,12334,
-12335,12336,12337,12338,12339,12340,12341,12342,12343,12344,12345,12346,
-12347,12348,12349,12350,12351,12352,12353,12354,12355,12356,12357,12358,
-12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,
-12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,
-12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,
-12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,
-12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,
-12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,
-12431,12432,12433,12434,12435,12436,12437,12438,12439,12440,12441,12442,
-12443,12444,12445,12446,12447,12448,12449,12450,12451,12452,12453,12454,
-12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,
-12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,
-12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,
-12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,
-12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,
-12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,
-12527,12528,12529,12530,12531,12532,12533,12534,12535,12536,12537,12538,
-12539,12540,12541,12542,12543,12544,12545,12546,12547,12548,12549,12550,
-12551,12552,12553,12554,12555,12556,12557,12558,12559,12560,12561,12562,
-12563,12564,12565,12566,12567,12568,12569,12570,12571,12572,12573,12574,
-12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,12585,12586,
-12587,12588,12589,12590,12591,12592,12593,12594,12595,12596,12597,12598,
-12599,12600,12601,12602,12603,12604,12605,12606,12607,12608,12609,12610,
-12611,12612,12613,12614,12615,12616,12617,12618,12619,12620,12621,12622,
-12623,12624,12625,12626,12627,12628,12629,12630,12631,12632,12633,12634,
-12635,12636,12637,12638,12639,12640,12641,12642,12643,12644,12645,12646,
-12647,12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,
-12659,12660,12661,12662,12663,12664,12665,12666,12667,12668,12669,12670,
-12671,12672,12673,12674,12675,12676,12677,12678,12679,12680,12681,12682,
-12683,12684,12685,12686,12687,12688,12689,12690,12691,12692,12693,12694,
-12695,12696,12697,12698,12699,12700,12701,12702,12703,12704,12705,12706,
-12707,12708,12709,12710,12711,12712,12713,12714,12715,12716,12717,12718,
-12719,12720,12721,12722,12723,12724,12725,12726,12727,12728,12729,12730,
-12731,12732,12733,12734,12735,12736,12737,12738,12739,12740,12741,12742,
-12743,12744,12745,12746,12747,12748,12749,12750,12751,12752,12753,12754,
-12755,12756,12757,12758,12759,12760,12761,12762,12763,12764,12765,12766,
-12767,12768,12769,12770,12771,12772,12773,12774,12775,12776,12777,12778,
-12779,12780,12781,12782,12783,12784,12785,12786,12787,12788,12789,12790,
-12791,12792,12793,12794,12795,12796,12797,12798,12799,12800,12801,12802,
-12803,12804,12805,12806,12807,12808,12809,12810,12811,12812,12813,12814,
-12815,12816,12817,12818,12819,12820,12821,12822,12823,12824,12825,12826,
-12827,12828,12829,12830,12831,12832,12833,12834,12835,12836,12837,12838,
-12839,12840,12841,12842,12843,12844,12845,12846,12847,12848,12849,12850,
-12851,12852,12853,12854,12855,12856,12857,12858,12859,12860,12861,12862,
-12863,12864,12865,12866,12867,12868,12869,12870,12871,12872,12873,12874,
-12875,12876,12877,12878,12879,12880,12881,12882,12883,12884,12885,12886,
-12887,12888,12889,12890,12891,12892,12893,12894,12895,12896,12897,12898,
-12899,12900,12901,12902,12903,12904,12905,12906,12907,12908,12909,12910,
-12911,12912,12913,12914,12915,12916,12917,12918,12919,12920,12921,12922,
-12923,12924,12925,12926,12927,12928,12929,12930,12931,12932,12933,12934,
-12935,12936,12937,12938,12939,12940,12941,12942,12943,12944,12945,12946,
-12947,12948,12949,12950,12951,12952,12953,12954,12955,12956,12957,12958,
-12959,12960,12961,12962,12963,12964,12965,12966,12967,12968,12969,12970,
-12971,12972,12973,12974,12975,12976,12977,12978,12979,12980,12981,12982,
-12983,12984,12985,12986,12987,12988,12989,12990,12991,12992,12993,12994,
-12995,12996,12997,12998,12999,13000,13001,13002,13003,13004,13005,13006,
-13007,13008,13009,13010,13011,13012,13013,13014,13015,13016,13017,13018,
-13019,13020,13021,13022,13023,13024,13025,13026,13027,13028,13029,13030,
-13031,13032,13033,13034,13035,13036,13037,13038,13039,13040,13041,13042,
-13043,13044,13045,13046,13047,13048,13049,13050,13051,13052,13053,13054,
-13055,13056,13057,13058,13059,13060,13061,13062,13063,13064,13065,13066,
-13067,13068,13069,13070,13071,13072,13073,13074,13075,13076,13077,13078,
-13079,13080,13081,13082,13083,13084,13085,13086,13087,13088,13089,13090,
-13091,13092,13093,13094,13095,13096,13097,13098,13099,13100,13101,13102,
-13103,13104,13105,13106,13107,13108,13109,13110,13111,13112,13113,13114,
-13115,13116,13117,13118,13119,13120,13121,13122,13123,13124,13125,13126,
-13127,13128,13129,13130,13131,13132,13133,13134,13135,13136,13137,13138,
-13139,13140,13141,13142,13143,13144,13145,13146,13147,13148,13149,13150,
-13151,13152,13153,13154,13155,13156,13157,13158,13159,13160,13161,13162,
-13163,13164,13165,13166,13167,13168,13169,13170,13171,13172,13173,13174,
-13175,13176,13177,13178,13179,13180,13181,13182,13183,13184,13185,13186,
-13187,13188,13189,13190,13191,13192,13193,13194,13195,13196,13197,13198,
-13199,13200,13201,13202,13203,13204,13205,13206,13207,13208,13209,13210,
-13211,13212,13213,13214,13215,13216,13217,13218,13219,13220,13221,13222,
-13223,13224,13225,13226,13227,13228,13229,13230,13231,13232,13233,13234,
-13235,13236,13237,13238,13239,13240,13241,13242,13243,13244,13245,13246,
-13247,13248,13249,13250,13251,13252,13253,13254,13255,13256,13257,13258,
-13259,13260,13261,13262,13263,13264,13265,13266,13267,13268,13269,13270,
-13271,13272,13273,13274,13275,13276,13277,13278,13279,13280,13281,13282,
-13283,13284,13285,13286,13287,13288,13289,13290,13291,13292,13293,13294,
-13295,13296,13297,13298,13299,13300,13301,13302,13303,13304,13305,13306,
-13307,13308,13309,13310,13311,13312,13313,13314,13315,13316,13317,13318,
-13319,13320,13321,13322,13323,13324,13325,13326,13327,13328,13329,13330,
-13331,13332,13333,13334,13335,13336,13337,13338,13339,13340,13341,13342,
-13343,13344,13345,13346,13347,13348,13349,13350,13351,13352,13353,13354,
-13355,13356,13357,13358,13359,13360,13361,13362,13363,13364,13365,13366,
-13367,13368,13369,13370,13371,13372,13373,13374,13375,13376,13377,13378,
-13379,13380,13381,13382,13383,13384,13385,13386,13387,13388,13389,13390,
-13391,13392,13393,13394,13395,13396,13397,13398,13399,13400,13401,13402,
-13403,13404,13405,13406,13407,13408,13409,13410,13411,13412,13413,13414,
-13415,13416,13417,13418,13419,13420,13421,13422,13423,13424,13425,13426,
-13427,13428,13429,13430,13431,13432,13433,13434,13435,13436,13437,13438,
-13439,13440,13441,13442,13443,13444,13445,13446,13447,13448,13449,13450,
-13451,13452,13453,13454,13455,13456,13457,13458,13459,13460,13461,13462,
-13463,13464,13465,13466,13467,13468,13469,13470,13471,13472,13473,13474,
-13475,13476,13477,13478,13479,13480,13481,13482,13483,13484,13485,13486,
-13487,13488,13489,13490,13491,13492,13493,13494,13495,13496,13497,13498,
-13499,13500,13501,13502,13503,13504,13505,13506,13507,13508,13509,13510,
-13511,13512,13513,13514,13515,13516,13517,13518,13519,13520,13521,13522,
-13523,13524,13525,13526,13527,13528,13529,13530,13531,13532,13533,13534,
-13535,13536,13537,13538,13539,13540,13541,13542,13543,13544,13545,13546,
-13547,13548,13549,13550,13551,13552,13553,13554,13555,13556,13557,13558,
-13559,13560,13561,13562,13563,13564,13565,13566,13567,13568,13569,13570,
-13571,13572,13573,13574,13575,13576,13577,13578,13579,13580,13581,13582,
-13583,13584,13585,13586,13587,13588,13589,13590,13591,13592,13593,13594,
-13595,13596,13597,13598,13599,13600,13601,13602,13603,13604,13605,13606,
-13607,13608,13609,13610,13611,13612,13613,13614,13615,13616,13617,13618,
-13619,13620,13621,13622,13623,13624,13625,13626,13627,13628,13629,13630,
-13631,13632,13633,13634,13635,13636,13637,13638,13639,13640,13641,13642,
-13643,13644,13645,13646,13647,13648,13649,13650,13651,13652,13653,13654,
-13655,13656,13657,13658,13659,13660,13661,13662,13663,13664,13665,13666,
-13667,13668,13669,13670,13671,13672,13673,13674,13675,13676,13677,13678,
-13679,13680,13681,13682,13683,13684,13685,13686,13687,13688,13689,13690,
-13691,13692,13693,13694,13695,13696,13697,13698,13699,13700,13701,13702,
-13703,13704,13705,13706,13707,13708,13709,13710,13711,13712,13713,13714,
-13715,13716,13717,13718,13719,13720,13721,13722,13723,13724,13725,13726,
-13727,13728,13729,13730,13731,13732,13733,13734,13735,13736,13737,13738,
-13739,13740,13741,13742,13743,13744,13745,13746,13747,13748,13749,13750,
-13751,13752,13753,13754,13755,13756,13757,13758,13759,13760,13761,13762,
-13763,13764,13765,13766,13767,13768,13769,13770,13771,13772,13773,13774,
-13775,13776,13777,13778,13779,13780,13781,13782,13783,13784,13785,13786,
-13787,13788,13789,13790,13791,13792,13793,13794,13795,13796,13797,13798,
-13799,13800,13801,13802,13803,13804,13805,13806,13807,13808,13809,13810,
-13811,13812,13813,13814,13815,13816,13817,13818,13819,13820,13821,13822,
-13823,13824,13825,13826,13827,13828,13829,13830,13831,13832,13833,13834,
-13835,13836,13837,13838,13839,13840,13841,13842,13843,13844,13845,13846,
-13847,13848,13849,13850,13851,13852,13853,13854,13855,13856,13857,13858,
-13859,13860,13861,13862,13863,13864,13865,13866,13867,13868,13869,13870,
-13871,13872,13873,13874,13875,13876,13877,13878,13879,13880,13881,13882,
-13883,13884,13885,13886,13887,13888,13889,13890,13891,13892,13893,13894,
-13895,13896,13897,13898,13899,13900,13901,13902,13903,13904,13905,13906,
-13907,13908,13909,13910,13911,13912,13913,13914,13915,13916,13917,13918,
-13919,13920,13921,13922,13923,13924,13925,13926,13927,13928,13929,13930,
-13931,13932,13933,13934,13935,13936,13937,13938,13939,13940,13941,13942,
-13943,13944,13945,13946,13947,13948,13949,13950,13951,13952,13953,13954,
-13955,13956,13957,13958,13959,13960,13961,13962,13963,13964,13965,13966,
-13967,13968,13969,13970,13971,13972,13973,13974,13975,13976,13977,13978,
-13979,13980,13981,13982,13983,13984,13985,13986,13987,13988,13989,13990,
-13991,13992,13993,13994,13995,13996,13997,13998,13999,14000,14001,14002,
-14003,14004,14005,14006,14007,14008,14009,14010,14011,14012,14013,14014,
-14015,14016,14017,14018,14019,14020,14021,14022,14023,14024,14025,14026,
-14027,14028,14029,14030,14031,14032,14033,14034,14035,14036,14037,14038,
-14039,14040,14041,14042,14043,14044,14045,14046,14047,14048,14049,14050,
-14051,14052,14053,14054,14055,14056,14057,14058,14059,14060,14061,14062,
-14063,14064,14065,14066,14067,14068,14069,14070,14071,14072,14073,14074,
-14075,14076,14077,14078,14079,14080,14081,14082,14083,14084,14085,14086,
-14087,14088,14089,14090,14091,14092,14093,14094,14095,14096,14097,14098,
-14099,14100,14101,14102,14103,14104,14105,14106,14107,14108,14109,14110,
-14111,14112,14113,14114,14115,14116,14117,14118,14119,14120,14121,14122,
-14123,14124,14125,14126,14127,14128,14129,14130,14131,14132,14133,14134,
-14135,14136,14137,14138,14139,14140,14141,14142,14143,14144,14145,14146,
-14147,14148,14149,14150,14151,14152,14153,14154,14155,14156,14157,14158,
-14159,14160,14161,14162,14163,14164,14165,14166,14167,14168,14169,14170,
-14171,14172,14173,14174,14175,14176,14177,14178,14179,14180,14181,14182,
-14183,14184,14185,14186,14187,14188,14189,14190,14191,14192,14193,14194,
-14195,14196,14197,14198,14199,14200,14201,14202,14203,14204,14205,14206,
-14207,14208,14209,14210,14211,14212,14213,14214,14215,14216,14217,14218,
-14219,14220,14221,14222,14223,14224,14225,14226,14227,14228,14229,14230,
-14231,14232,14233,14234,14235,14236,14237,14238,14239,14240,14241,14242,
-14243,14244,14245,14246,14247,14248,14249,14250,14251,14252,14253,14254,
-14255,14256,14257,14258,14259,14260,14261,14262,14263,14264,14265,14266,
-14267,14268,14269,14270,14271,14272,14273,14274,14275,14276,14277,14278,
-14279,14280,14281,14282,14283,14284,14285,14286,14287,14288,14289,14290,
-14291,14292,14293,14294,14295,14296,14297,14298,14299,14300,14301,14302,
-14303,14304,14305,14306,14307,14308,14309,14310,14311,14312,14313,14314,
-14315,14316,14317,14318,14319,14320,14321,14322,14323,14324,14325,14326,
-14327,14328,14329,14330,14331,14332,14333,14334,14335,14336,14337,14338,
-14339,14340,14341,14342,14343,14344,14345,14346,14347,14348,14349,14350,
-14351,14352,14353,14354,14355,14356,14357,14358,14359,14360,14361,14362,
-14363,14364,14365,14366,14367,14368,14369,14370,14371,14372,14373,14374,
-14375,14376,14377,14378,14379,14380,14381,14382,14383,14384,14385,14386,
-14387,14388,14389,14390,14391,14392,14393,14394,14395,14396,14397,14398,
-14399,14400,14401,14402,14403,14404,14405,14406,14407,14408,14409,14410,
-14411,14412,14413,14414,14415,14416,14417,14418,14419,14420,14421,14422,
-14423,14424,14425,14426,14427,14428,14429,14430,14431,14432,14433,14434,
-14435,14436,14437,14438,14439,14440,14441,14442,14443,14444,14445,14446,
-14447,14448,14449,14450,14451,14452,14453,14454,14455,14456,14457,14458,
-14459,14460,14461,14462,14463,14464,14465,14466,14467,14468,14469,14470,
-14471,14472,14473,14474,14475,14476,14477,14478,14479,14480,14481,14482,
-14483,14484,14485,14486,14487,14488,14489,14490,14491,14492,14493,14494,
-14495,14496,14497,14498,14499,14500,14501,14502,14503,14504,14505,14506,
-14507,14508,14509,14510,14511,14512,14513,14514,14515,14516,14517,14518,
-14519,14520,14521,14522,14523,14524,14525,14526,14527,14528,14529,14530,
-14531,14532,14533,14534,14535,14536,14537,14538,14539,14540,14541,14542,
-14543,14544,14545,14546,14547,14548,14549,14550,14551,14552,14553,14554,
-14555,14556,14557,14558,14559,14560,14561,14562,14563,14564,14565,14566,
-14567,14568,14569,14570,14571,14572,14573,14574,14575,14576,14577,14578,
-14579,14580,14581,14582,14583,14584,14585,14586,14587,14588,14589,14590,
-14591,14592,14593,14594,14595,14596,14597,14598,14599,14600,14601,14602,
-14603,14604,14605,14606,14607,14608,14609,14610,14611,14612,14613,14614,
-14615,14616,14617,14618,14619,14620,14621,14622,14623,14624,14625,14626,
-14627,14628,14629,14630,14631,14632,14633,14634,14635,14636,14637,14638,
-14639,14640,14641,14642,14643,14644,14645,14646,14647,14648,14649,14650,
-14651,14652,14653,14654,14655,14656,14657,14658,14659,14660,14661,14662,
-14663,14664,14665,14666,14667,14668,14669,14670,14671,14672,14673,14674,
-14675,14676,14677,14678,14679,14680,14681,14682,14683,14684,14685,14686,
-14687,14688,14689,14690,14691,14692,14693,14694,14695,14696,14697,14698,
-14699,14700,14701,14702,14703,14704,14705,14706,14707,14708,14709,14710,
-14711,14712,14713,14714,14715,14716,14717,14718,14719,14720,14721,14722,
-14723,14724,14725,14726,14727,14728,14729,14730,14731,14732,14733,14734,
-14735,14736,14737,14738,14739,14740,14741,14742,14743,14744,14745,14746,
-14747,14748,14749,14750,14751,14752,14753,14754,14755,14756,14757,14758,
-14759,14760,14761,14762,14763,14764,14765,14766,14767,14768,14769,14770,
-14771,14772,14773,14774,14775,14776,14777,14778,14779,14780,14781,14782,
-14783,14784,14785,14786,14787,14788,14789,14790,14791,14792,14793,14794,
-14795,14796,14797,14798,14799,14800,14801,14802,14803,14804,14805,14806,
-14807,14808,14809,14810,14811,14812,14813,14814,14815,14816,14817,14818,
-14819,14820,14821,14822,14823,14824,14825,14826,14827,14828,14829,14830,
-14831,14832,14833,14834,14835,14836,14837,14838,14839,14840,14841,14842,
-14843,14844,14845,14846,14847,14848,14849,14850,14851,14852,14853,14854,
-14855,14856,14857,14858,14859,14860,14861,14862,14863,14864,14865,14866,
-14867,14868,14869,14870,14871,14872,14873,14874,14875,14876,14877,14878,
-14879,14880,14881,14882,14883,14884,14885,14886,14887,14888,14889,14890,
-14891,14892,14893,14894,14895,14896,14897,14898,14899,14900,14901,14902,
-14903,14904,14905,14906,14907,14908,14909,14910,14911,14912,14913,14914,
-14915,14916,14917,14918,14919,14920,14921,14922,14923,14924,14925,14926,
-14927,14928,14929,14930,14931,14932,14933,14934,14935,14936,14937,14938,
-14939,14940,14941,14942,14943,14944,14945,14946,14947,14948,14949,14950,
-14951,14952,14953,14954,14955,14956,14957,14958,14959,14960,14961,14962,
-14963,14964,14965,14966,14967,14968,14969,14970,14971,14972,14973,14974,
-14975,14976,14977,14978,14979,14980,14981,14982,14983,14984,14985,14986,
-14987,14988,14989,14990,14991,14992,14993,14994,14995,14996,14997,14998,
-14999,15000,15001,15002,15003,15004,15005,15006,15007,15008,15009,15010,
-15011,15012,15013,15014,15015,15016,15017,15018,15019,15020,15021,15022,
-15023,15024,15025,15026,15027,15028,15029,15030,15031,15032,15033,15034,
-15035,15036,15037,15038,15039,15040,15041,15042,15043,15044,15045,15046,
-15047,15048,15049,15050,15051,15052,15053,15054,15055,15056,15057,15058,
-15059,15060,15061,15062,15063,15064,15065,15066,15067,15068,15069,15070,
-15071,15072,15073,15074,15075,15076,15077,15078,15079,15080,15081,15082,
-15083,15084,15085,15086,15087,15088,15089,15090,15091,15092,15093,15094,
-15095,15096,15097,15098,15099,15100,15101,15102,15103,15104,15105,15106,
-15107,15108,15109,15110,15111,15112,15113,15114,15115,15116,15117,15118,
-15119,15120,15121,15122,15123,15124,15125,15126,15127,15128,15129,15130,
-15131,15132,15133,15134,15135,15136,15137,15138,15139,15140,15141,15142,
-15143,15144,15145,15146,15147,15148,15149,15150,15151,15152,15153,15154,
-15155,15156,15157,15158,15159,15160,15161,15162,15163,15164,15165,15166,
-15167,15168,15169,15170,15171,15172,15173,15174,15175,15176,15177,15178,
-15179,15180,15181,15182,15183,15184,15185,15186,15187,15188,15189,15190,
-15191,15192,15193,15194,15195,15196,15197,15198,15199,15200,15201,15202,
-15203,15204,15205,15206,15207,15208,15209,15210,15211,15212,15213,15214,
-15215,15216,15217,15218,15219,15220,15221,15222,15223,15224,15225,15226,
-15227,15228,15229,15230,15231,15232,15233,15234,15235,15236,15237,15238,
-15239,15240,15241,15242,15243,15244,15245,15246,15247,15248,15249,15250,
-15251,15252,15253,15254,15255,15256,15257,15258,15259,15260,15261,15262,
-15263,15264,15265,15266,15267,15268,15269,15270,15271,15272,15273,15274,
-15275,15276,15277,15278,15279,15280,15281,15282,15283,15284,15285,15286,
-15287,15288,15289,15290,15291,15292,15293,15294,15295,15296,15297,15298,
-15299,15300,15301,15302,15303,15304,15305,15306,15307,15308,15309,15310,
-15311,15312,15313,15314,15315,15316,15317,15318,15319,15320,15321,15322,
-15323,15324,15325,15326,15327,15328,15329,15330,15331,15332,15333,15334,
-15335,15336,15337,15338,15339,15340,15341,15342,15343,15344,15345,15346,
-15347,15348,15349,15350,15351,15352,15353,15354,15355,15356,15357,15358,
-15359,15360,15361,15362,15363,15364,15365,15366,15367,15368,15369,15370,
-15371,15372,15373,15374,15375,15376,15377,15378,15379,15380,15381,15382,
-15383,15384,15385,15386,15387,15388,15389,15390,15391,15392,15393,15394,
-15395,15396,15397,15398,15399,15400,15401,15402,15403,15404,15405,15406,
-15407,15408,15409,15410,15411,15412,15413,15414,15415,15416,15417,15418,
-15419,15420,15421,15422,15423,15424,15425,15426,15427,15428,15429,15430,
-15431,15432,15433,15434,15435,15436,15437,15438,15439,15440,15441,15442,
-15443,15444,15445,15446,15447,15448,15449,15450,15451,15452,15453,15454,
-15455,15456,15457,15458,15459,15460,15461,15462,15463,15464,15465,15466,
-15467,15468,15469,15470,15471,15472,15473,15474,15475,15476,15477,15478,
-15479,15480,15481,15482,15483,15484,15485,15486,15487,15488,15489,15490,
-15491,15492,15493,15494,15495,15496,15497,15498,15499,15500,15501,15502,
-15503,15504,15505,15506,15507,15508,15509,15510,15511,15512,15513,15514,
-15515,15516,15517,15518,15519,15520,15521,15522,15523,15524,15525,15526,
-15527,15528,15529,15530,15531,15532,15533,15534,15535,15536,15537,15538,
-15539,15540,15541,15542,15543,15544,15545,15546,15547,15548,15549,15550,
-15551,15552,15553,15554,15555,15556,15557,15558,15559,15560,15561,15562,
-15563,15564,15565,15566,15567,15568,15569,15570,15571,15572,15573,15574,
-15575,15576,15577,15578,15579,15580,15581,15582,15583,15584,15585,15586,
-15587,15588,15589,15590,15591,15592,15593,15594,15595,15596,15597,15598,
-15599,15600,15601,15602,15603,15604,15605,15606,15607,15608,15609,15610,
-15611,15612,15613,15614,15615,15616,15617,15618,15619,15620,15621,15622,
-15623,15624,15625,15626,15627,15628,15629,15630,15631,15632,15633,15634,
-15635,15636,15637,15638,15639,15640,15641,15642,15643,15644,15645,15646,
-15647,15648,15649,15650,15651,15652,15653,15654,15655,15656,15657,15658,
-15659,15660,15661,15662,15663,15664,15665,15666,15667,15668,15669,15670,
-15671,15672,15673,15674,15675,15676,15677,15678,15679,15680,15681,15682,
-15683,15684,15685,15686,15687,15688,15689,15690,15691,15692,15693,15694,
-15695,15696,15697,15698,15699,15700,15701,15702,15703,15704,15705,15706,
-15707,15708,15709,15710,15711,15712,15713,15714,15715,15716,15717,15718,
-15719,15720,15721,15722,15723,15724,15725,15726,15727,15728,15729,15730,
-15731,15732,15733,15734,15735,15736,15737,15738,15739,15740,15741,15742,
-15743,15744,15745,15746,15747,15748,15749,15750,15751,15752,15753,15754,
-15755,15756,15757,15758,15759,15760,15761,15762,15763,15764,15765,15766,
-15767,15768,15769,15770,15771,15772,15773,15774,15775,15776,15777,15778,
-15779,15780,15781,15782,15783,15784,15785,15786,15787,15788,15789,15790,
-15791,15792,15793,15794,15795,15796,15797,15798,15799,15800,15801,15802,
-15803,15804,15805,15806,15807,15808,15809,15810,15811,15812,15813,15814,
-15815,15816,15817,15818,15819,15820,15821,15822,15823,15824,15825,15826,
-15827,15828,15829,15830,15831,15832,15833,15834,15835,15836,15837,15838,
-15839,15840,15841,15842,15843,15844,15845,15846,15847,15848,15849,15850,
-15851,15852,15853,15854,15855,15856,15857,15858,15859,15860,15861,15862,
-15863,15864,15865,15866,15867,15868,15869,15870,15871,15872,15873,15874,
-15875,15876,15877,15878,15879,15880,15881,15882,15883,15884,15885,15886,
-15887,15888,15889,15890,15891,15892,15893,15894,15895,15896,15897,15898,
-15899,15900,15901,15902,15903,15904,15905,15906,15907,15908,15909,15910,
-15911,15912,15913,15914,15915,15916,15917,15918,15919,15920,15921,15922,
-15923,15924,15925,15926,15927,15928,15929,15930,15931,15932,15933,15934,
-15935,15936,15937,15938,15939,15940,15941,15942,15943,15944,15945,15946,
-15947,15948,15949,15950,15951,15952,15953,15954,15955,15956,15957,15958,
-15959,15960,15961,15962,15963,15964,15965,15966,15967,15968,15969,15970,
-15971,15972,15973,15974,15975,15976,15977,15978,15979,15980,15981,15982,
-15983,15984,15985,15986,15987,15988,15989,15990,15991,15992,15993,15994,
-15995,15996,15997,15998,15999,16000,16001,16002,16003,16004,16005,16006,
-16007,16008,16009,16010,16011,16012,16013,16014,16015,16016,16017,16018,
-16019,16020,16021,16022,16023,16024,16025,16026,16027,16028,16029,16030,
-16031,16032,16033,16034,16035,16036,16037,16038,16039,16040,16041,16042,
-16043,16044,16045,16046,16047,16048,16049,16050,16051,16052,16053,16054,
-16055,16056,16057,16058,16059,16060,16061,16062,16063,16064,16065,16066,
-16067,16068,16069,16070,16071,16072,16073,16074,16075,16076,16077,16078,
-16079,16080,16081,16082,16083,16084,16085,16086,16087,16088,16089,16090,
-16091,16092,16093,16094,16095,16096,16097,16098,16099,16100,16101,16102,
-16103,16104,16105,16106,16107,16108,16109,16110,16111,16112,16113,16114,
-16115,16116,16117,16118,16119,16120,16121,16122,16123,16124,16125,16126,
-16127,16128,16129,16130,16131,16132,16133,16134,16135,16136,16137,16138,
-16139,16140,16141,16142,16143,16144,16145,16146,16147,16148,16149,16150,
-16151,16152,16153,16154,16155,16156,16157,16158,16159,16160,16161,16162,
-16163,16164,16165,16166,16167,16168,16169,16170,16171,16172,16173,16174,
-16175,16176,16177,16178,16179,16180,16181,16182,16183,16184,16185,16186,
-16187,16188,16189,16190,16191,16192,16193,16194,16195,16196,16197,16198,
-16199,16200,16201,16202,16203,16204,16205,16206,16207,16208,16209,16210,
-16211,16212,16213,16214,16215,16216,16217,16218,16219,16220,16221,16222,
-16223,16224,16225,16226,16227,16228,16229,16230,16231,16232,16233,16234,
-16235,16236,16237,16238,16239,16240,16241,16242,16243,16244,16245,16246,
-16247,16248,16249,16250,16251,16252,16253,16254,16255,16256,16257,16258,
-16259,16260,16261,16262,16263,16264,16265,16266,16267,16268,16269,16270,
-16271,16272,16273,16274,16275,16276,16277,16278,16279,16280,16281,16282,
-16283,16284,16285,16286,16287,16288,16289,16290,16291,16292,16293,16294,
-16295,16296,16297,16298,16299,16300,16301,16302,16303,16304,16305,16306,
-16307,16308,16309,16310,16311,16312,16313,16314,16315,16316,16317,16318,
-16319,16320,16321,16322,16323,16324,16325,16326,16327,16328,16329,16330,
-16331,16332,16333,16334,16335,16336,16337,16338,16339,16340,16341,16342,
-16343,16344,16345,16346,16347,16348,16349,16350,16351,16352,16353,16354,
-16355,16356,16357,16358,16359,16360,16361,16362,16363,16364,16365,16366,
-16367,16368,16369,16370,16371,16372,16373,16374,16375,16376,16377,16378,
-16379,16380,16381,16382,16383,16384,16385,16386,16387,16388,16389,16390,
-16391,16392,16393,16394,16395,16396,16397,16398,16399,16400,16401,16402,
-16403,16404,16405,16406,16407,16408,16409,16410,16411,16412,16413,16414,
-16415,16416,16417,16418,16419,16420,16421,16422,16423,16424,16425,16426,
-16427,16428,16429,16430,16431,16432,16433,16434,16435,16436,16437,16438,
-16439,16440,16441,16442,16443,16444,16445,16446,16447,16448,16449,16450,
-16451,16452,16453,16454,16455,16456,16457,16458,16459,16460,16461,16462,
-16463,16464,16465,16466,16467,16468,16469,16470,16471,16472,16473,16474,
-16475,16476,16477,16478,16479,16480,16481,16482,16483,16484,16485,16486,
-16487,16488,16489,16490,16491,16492,16493,16494,16495,16496,16497,16498,
-16499,16500,16501,16502,16503,16504,16505,16506,16507,16508,16509,16510,
-16511,16512,16513,16514,16515,16516,16517,16518,16519,16520,16521,16522,
-16523,16524,16525,16526,16527,16528,16529,16530,16531,16532,16533,16534,
-16535,16536,16537,16538,16539,16540,16541,16542,16543,16544,16545,16546,
-16547,16548,16549,16550,16551,16552,16553,16554,16555,16556,16557,16558,
-16559,16560,16561,16562,16563,16564,16565,16566,16567,16568,16569,16570,
-16571,16572,16573,16574,16575,16576,16577,16578,16579,16580,16581,16582,
-16583,16584,16585,16586,16587,16588,16589,16590,16591,16592,16593,16594,
-16595,16596,16597,16598,16599,16600,16601,16602,16603,16604,16605,16606,
-16607,16608,16609,16610,16611,16612,16613,16614,16615,16616,16617,16618,
-16619,16620,16621,16622,16623,16624,16625,16626,16627,16628,16629,16630,
-16631,16632,16633,16634,16635,16636,16637,16638,16639,16640,16641,16642,
-16643,16644,16645,16646,16647,16648,16649,16650,16651,16652,16653,16654,
-16655,16656,16657,16658,16659,16660,16661,16662,16663,16664,16665,16666,
-16667,16668,16669,16670,16671,16672,16673,16674,16675,16676,16677,16678,
-16679,16680,16681,16682,16683,16684,16685,16686,16687,16688,16689,16690,
-16691,16692,16693,16694,16695,16696,16697,16698,16699,16700,16701,16702,
-16703,16704,16705,16706,16707,16708,16709,16710,16711,16712,16713,16714,
-16715,16716,16717,16718,16719,16720,16721,16722,16723,16724,16725,16726,
-16727,16728,16729,16730,16731,16732,16733,16734,16735,16736,16737,16738,
-16739,16740,16741,16742,16743,16744,16745,16746,16747,16748,16749,16750,
-16751,16752,16753,16754,16755,16756,16757,16758,16759,16760,16761,16762,
-16763,16764,16765,16766,16767,16768,16769,16770,16771,16772,16773,16774,
-16775,16776,16777,16778,16779,16780,16781,16782,16783,16784,16785,16786,
-16787,16788,16789,16790,16791,16792,16793,16794,16795,16796,16797,16798,
-16799,16800,16801,16802,16803,16804,16805,16806,16807,16808,16809,16810,
-16811,16812,16813,16814,16815,16816,16817,16818,16819,16820,16821,16822,
-16823,16824,16825,16826,16827,16828,16829,16830,16831,16832,16833,16834,
-16835,16836,16837,16838,16839,16840,16841,16842,16843,16844,16845,16846,
-16847,16848,16849,16850,16851,16852,16853,16854,16855,16856,16857,16858,
-16859,16860,16861,16862,16863,16864,16865,16866,16867,16868,16869,16870,
-16871,16872,16873,16874,16875,16876,16877,16878,16879,16880,16881,16882,
-16883,16884,16885,16886,16887,16888,16889,16890,16891,16892,16893,16894,
-16895,16896,16897,16898,16899,16900,16901,16902,16903,16904,16905,16906,
-16907,16908,16909,16910,16911,16912,16913,16914,16915,16916,16917,16918,
-16919,16920,16921,16922,16923,16924,16925,16926,16927,16928,16929,16930,
-16931,16932,16933,16934,16935,16936,16937,16938,16939,16940,16941,16942,
-16943,16944,16945,16946,16947,16948,16949,16950,16951,16952,16953,16954,
-16955,16956,16957,16958,16959,16960,16961,16962,16963,16964,16965,16966,
-16967,16968,16969,16970,16971,16972,16973,16974,16975,16976,16977,16978,
-16979,16980,16981,16982,16983,16984,16985,16986,16987,16988,16989,16990,
-16991,16992,16993,16994,16995,16996,16997,16998,16999,17000,17001,17002,
-17003,17004,17005,17006,17007,17008,17009,17010,17011,17012,17013,17014,
-17015,17016,17017,17018,17019,17020,17021,17022,17023,17024,17025,17026,
-17027,17028,17029,17030,17031,17032,17033,17034,17035,17036,17037,17038,
-17039,17040,17041,17042,17043,17044,17045,17046,17047,17048,17049,17050,
-17051,17052,17053,17054,17055,17056,17057,17058,17059,17060,17061,17062,
-17063,17064,17065,17066,17067,17068,17069,17070,17071,17072,17073,17074,
-17075,17076,17077,17078,17079,17080,17081,17082,17083,17084,17085,17086,
-17087,17088,17089,17090,17091,17092,17093,17094,17095,17096,17097,17098,
-17099,17100,17101,17102,17103,17104,17105,17106,17107,17108,17109,17110,
-17111,17112,17113,17114,17115,17116,17117,17118,17119,17120,17121,17122,
-17123,17124,17125,17126,17127,17128,17129,17130,17131,17132,17133,17134,
-17135,17136,17137,17138,17139,17140,17141,17142,17143,17144,17145,17146,
-17147,17148,17149,17150,17151,17152,17153,17154,17155,17156,17157,17158,
-17159,17160,17161,17162,17163,17164,17165,17166,17167,17168,17169,17170,
-17171,17172,17173,17174,17175,17176,17177,17178,17179,17180,17181,17182,
-17183,17184,17185,17186,17187,17188,17189,17190,17191,17192,17193,17194,
-17195,17196,17197,17198,17199,17200,17201,17202,17203,17204,17205,17206,
-17207,17208,17209,17210,17211,17212,17213,17214,17215,17216,17217,17218,
-17219,17220,17221,17222,17223,17224,17225,17226,17227,17228,17229,17230,
-17231,17232,17233,17234,17235,17236,17237,17238,17239,17240,17241,17242,
-17243,17244,17245,17246,17247,17248,17249,17250,17251,17252,17253,17254,
-17255,17256,17257,17258,17259,17260,17261,17262,17263,17264,17265,17266,
-17267,17268,17269,17270,17271,17272,17273,17274,17275,17276,17277,17278,
-17279,17280,17281,17282,17283,17284,17285,17286,17287,17288,17289,17290,
-17291,17292,17293,17294,17295,17296,17297,17298,17299,17300,17301,17302,
-17303,17304,17305,17306,17307,17308,17309,17310,17311,17312,17313,17314,
-17315,17316,17317,17318,17319,17320,17321,17322,17323,17324,17325,17326,
-17327,17328,17329,17330,17331,17332,17333,17334,17335,17336,17337,17338,
-17339,17340,17341,17342,17343,17344,17345,17346,17347,17348,17349,17350,
-17351,17352,17353,17354,17355,17356,17357,17358,17359,17360,17361,17362,
-17363,17364,17365,17366,17367,17368,17369,17370,17371,17372,17373,17374,
-17375,17376,17377,17378,17379,17380,17381,17382,17383,17384,17385,17386,
-17387,17388,17389,17390,17391,17392,17393,17394,17395,17396,17397,17398,
-17399,17400,17401,17402,17403,17404,17405,17406,17407,17408,17409,17410,
-17411,17412,17413,17414,17415,17416,17417,17418,17419,17420,17421,17422,
-17423,17424,17425,17426,17427,17428,17429,17430,17431,17432,17433,17434,
-17435,17436,17437,17438,17439,17440,17441,17442,17443,17444,17445,17446,
-17447,17448,17449,17450,17451,17452,17453,17454,17455,17456,17457,17458,
-17459,17460,17461,17462,17463,17464,17465,17466,17467,17468,17469,17470,
-17471,17472,17473,17474,17475,17476,17477,17478,17479,17480,17481,17482,
-17483,17484,17485,17486,17487,17488,17489,17490,17491,17492,17493,17494,
-17495,17496,17497,17498,17499,17500,17501,17502,17503,17504,17505,17506,
-17507,17508,17509,17510,17511,17512,17513,17514,17515,17516,17517,17518,
-17519,17520,17521,17522,17523,17524,17525,17526,17527,17528,17529,17530,
-17531,17532,17533,17534,17535,17536,17537,17538,17539,17540,17541,17542,
-17543,17544,17545,17546,17547,17548,17549,17550,17551,17552,17553,17554,
-17555,17556,17557,17558,17559,17560,17561,17562,17563,17564,17565,17566,
-17567,17568,17569,17570,17571,17572,17573,17574,17575,17576,17577,17578,
-17579,17580,17581,17582,17583,17584,17585,17586,17587,17588,17589,17590,
-17591,17592,17593,17594,17595,17596,17597,17598,17599,17600,17601,17602,
-17603,17604,17605,17606,17607,17608,17609,17610,17611,17612,17613,17614,
-17615,17616,17617,17618,17619,17620,17621,17622,17623,17624,17625,17626,
-17627,17628,17629,17630,17631,17632,17633,17634,17635,17636,17637,17638,
-17639,17640,17641,17642,17643,17644,17645,17646,17647,17648,17649,17650,
-17651,17652,17653,17654,17655,17656,17657,17658,17659,17660,17661,17662,
-17663,17664,17665,17666,17667,17668,17669,17670,17671,17672,17673,17674,
-17675,17676,17677,17678,17679,17680,17681,17682,17683,17684,17685,17686,
-17687,17688,17689,17690,17691,17692,17693,17694,17695,17696,17697,17698,
-17699,17700,17701,17702,17703,17704,17705,17706,17707,17708,17709,17710,
-17711,17712,17713,17714,17715,17716,17717,17718,17719,17720,17721,17722,
-17723,17724,17725,17726,17727,17728,17729,17730,17731,17732,17733,17734,
-17735,17736,17737,17738,17739,17740,17741,17742,17743,17744,17745,17746,
-17747,17748,17749,17750,17751,17752,17753,17754,17755,17756,17757,17758,
-17759,17760,17761,17762,17763,17764,17765,17766,17767,17768,17769,17770,
-17771,17772,17773,17774,17775,17776,17777,17778,17779,17780,17781,17782,
-17783,17784,17785,17786,17787,17788,17789,17790,17791,17792,17793,17794,
-17795,17796,17797,17798,17799,17800,17801,17802,17803,17804,17805,17806,
-17807,17808,17809,17810,17811,17812,17813,17814,17815,17816,17817,17818,
-17819,17820,17821,17822,17823,17824,17825,17826,17827,17828,17829,17830,
-17831,17832,17833,17834,17835,17836,17837,17838,17839,17840,17841,17842,
-17843,17844,17845,17846,17847,17848,17849,17850,17851,17852,17853,17854,
-17855,17856,17857,17858,17859,17860,17861,17862,17863,17864,17865,17866,
-17867,17868,17869,17870,17871,17872,17873,17874,17875,17876,17877,17878,
-17879,17880,17881,17882,17883,17884,17885,17886,17887,17888,17889,17890,
-17891,17892,17893,17894,17895,17896,17897,17898,17899,17900,17901,17902,
-17903,17904,17905,17906,17907,17908,17909,17910,17911,17912,17913,17914,
-17915,17916,17917,17918,17919,17920,17921,17922,17923,17924,17925,17926,
-17927,17928,17929,17930,17931,17932,17933,17934,17935,17936,17937,17938,
-17939,17940,17941,17942,17943,17944,17945,17946,17947,17948,17949,17950,
-17951,17952,17953,17954,17955,17956,17957,17958,17959,17960,17961,17962,
-17963,17964,17965,17966,17967,17968,17969,17970,17971,17972,17973,17974,
-17975,17976,17977,17978,17979,17980,17981,17982,17983,17984,17985,17986,
-17987,17988,17989,17990,17991,17992,17993,17994,17995,17996,17997,17998,
-17999,18000,18001,18002,18003,18004,18005,18006,18007,18008,18009,18010,
-18011,18012,18013,18014,18015,18016,18017,18018,18019,18020,18021,18022,
-18023,18024,18025,18026,18027,18028,18029,18030,18031,18032,18033,18034,
-18035,18036,18037,18038,18039,18040,18041,18042,18043,18044,18045,18046,
-18047,18048,18049,18050,18051,18052,18053,18054,18055,18056,18057,18058,
-18059,18060,18061,18062,18063,18064,18065,18066,18067,18068,18069,18070,
-18071,18072,18073,18074,18075,18076,18077,18078,18079,18080,18081,18082,
-18083,18084,18085,18086,18087,18088,18089,18090,18091,18092,18093,18094,
-18095,18096,18097,18098,18099,18100,18101,18102,18103,18104,18105,18106,
-18107,18108,18109,18110,18111,18112,18113,18114,18115,18116,18117,18118,
-18119,18120,18121,18122,18123,18124,18125,18126,18127,18128,18129,18130,
-18131,18132,18133,18134,18135,18136,18137,18138,18139,18140,18141,18142,
-18143,18144,18145,18146,18147,18148,18149,18150,18151,18152,18153,18154,
-18155,18156,18157,18158,18159,18160,18161,18162,18163,18164,18165,18166,
-18167,18168,18169,18170,18171,18172,18173,18174,18175,18176,18177,18178,
-18179,18180,18181,18182,18183,18184,18185,18186,18187,18188,18189,18190,
-18191,18192,18193,18194,18195,18196,18197,18198,18199,18200,18201,18202,
-18203,18204,18205,18206,18207,18208,18209,18210,18211,18212,18213,18214,
-18215,18216,18217,18218,18219,18220,18221,18222,18223,18224,18225,18226,
-18227,18228,18229,18230,18231,18232,18233,18234,18235,18236,18237,18238,
-18239,18240,18241,18242,18243,18244,18245,18246,18247,18248,18249,18250,
-18251,18252,18253,18254,18255,18256,18257,18258,18259,18260,18261,18262,
-18263,18264,18265,18266,18267,18268,18269,18270,18271,18272,18273,18274,
-18275,18276,18277,18278,18279,18280,18281,18282,18283,18284,18285,18286,
-18287,18288,18289,18290,18291,18292,18293,18294,18295,18296,18297,18298,
-18299,18300,18301,18302,18303,18304,18305,18306,18307,18308,18309,18310,
-18311,18312,18313,18314,18315,18316,18317,18318,18319,18320,18321,18322,
-18323,18324,18325,18326,18327,18328,18329,18330,18331,18332,18333,18334,
-18335,18336,18337,18338,18339,18340,18341,18342,18343,18344,18345,18346,
-18347,18348,18349,18350,18351,18352,18353,18354,18355,18356,18357,18358,
-18359,18360,18361,18362,18363,18364,18365,18366,18367,18368,18369,18370,
-18371,18372,18373,18374,18375,18376,18377,18378,18379,18380,18381,18382,
-18383,18384,18385,18386,18387,18388,18389,18390,18391,18392,18393,18394,
-18395,18396,18397,18398,18399,18400,18401,18402,18403,18404,18405,18406,
-18407,18408,18409,18410,18411,18412,18413,18414,18415,18416,18417,18418,
-18419,18420,18421,18422,18423,18424,18425,18426,18427,18428,18429,18430,
-18431,18432,18433,18434,18435,18436,18437,18438,18439,18440,18441,18442,
-18443,18444,18445,18446,18447,18448,18449,18450,18451,18452,18453,18454,
-18455,18456,18457,18458,18459,18460,18461,18462,18463,18464,18465,18466,
-18467,18468,18469,18470,18471,18472,18473,18474,18475,18476,18477,18478,
-18479,18480,18481,18482,18483,18484,18485,18486,18487,18488,18489,18490,
-18491,18492,18493,18494,18495,18496,18497,18498,18499,18500,18501,18502,
-18503,18504,18505,18506,18507,18508,18509,18510,18511,18512,18513,18514,
-18515,18516,18517,18518,18519,18520,18521,18522,18523,18524,18525,18526,
-18527,18528,18529,18530,18531,18532,18533,18534,18535,18536,18537,18538,
-18539,18540,18541,18542,18543,18544,18545,18546,18547,18548,18549,18550,
-18551,18552,18553,18554,18555,18556,18557,18558,18559,18560,18561,18562,
-18563,18564,18565,18566,18567,18568,18569,18570,18571,18572,18573,18574,
-18575,18576,18577,18578,18579,18580,18581,18582,18583,18584,18585,18586,
-18587,18588,18589,18590,18591,18592,18593,18594,18595,18596,18597,18598,
-18599,18600,18601,18602,18603,18604,18605,18606,18607,18608,18609,18610,
-18611,18612,18613,18614,18615,18616,18617,18618,18619,18620,18621,18622,
-18623,18624,18625,18626,18627,18628,18629,18630,18631,18632,18633,18634,
-18635,18636,18637,18638,18639,18640,18641,18642,18643,18644,18645,18646,
-18647,18648,18649,18650,18651,18652,18653,18654,18655,18656,18657,18658,
-18659,18660,18661,18662,18663,18664,18665,18666,18667,18668,18669,18670,
-18671,18672,18673,18674,18675,18676,18677,18678,18679,18680,18681,18682,
-18683,18684,18685,18686,18687,18688,18689,18690,18691,18692,18693,18694,
-18695,18696,18697,18698,18699,18700,18701,18702,18703,18704,18705,18706,
-18707,18708,18709,18710,18711,18712,18713,18714,18715,18716,18717,18718,
-18719,18720,18721,18722,18723,18724,18725,18726,18727,18728,18729,18730,
-18731,18732,18733,18734,18735,18736,18737,18738,18739,18740,18741,18742,
-18743,18744,18745,18746,18747,18748,18749,18750,18751,18752,18753,18754,
-18755,18756,18757,18758,18759,18760,18761,18762,18763,18764,18765,18766,
-18767,18768,18769,18770,18771,18772,18773,18774,18775,18776,18777,18778,
-18779,18780,18781,18782,18783,18784,18785,18786,18787,18788,18789,18790,
-18791,18792,18793,18794,18795,18796,18797,18798,18799,18800,18801,18802,
-18803,18804,18805,18806,18807,18808,18809,18810,18811,18812,18813,18814,
-18815,18816,18817,18818,18819,18820,18821,18822,18823,18824,18825,18826,
-18827,18828,18829,18830,18831,18832,18833,18834,18835,18836,18837,18838,
-18839,18840,18841,18842,18843,18844,18845,18846,18847,18848,18849,18850,
-18851,18852,18853,18854,18855,18856,18857,18858,18859,18860,18861,18862,
-18863,18864,18865,18866,18867,18868,18869,18870,18871,18872,18873,18874,
-18875,18876,18877,18878,18879,18880,18881,18882,18883,18884,18885,18886,
-18887,18888,18889,18890,18891,18892,18893,18894,18895,18896,18897,18898,
-18899,18900,18901,18902,18903,18904,18905,18906,18907,18908,18909,18910,
-18911,18912,18913,18914,18915,18916,18917,18918,18919,18920,18921,18922,
-18923,18924,18925,18926,18927,18928,18929,18930,18931,18932,18933,18934,
-18935,18936,18937,18938,18939,18940,18941,18942,18943,18944,18945,18946,
-18947,18948,18949,18950,18951,18952,18953,18954,18955,18956,18957,18958,
-18959,18960,18961,18962,18963,18964,18965,18966,18967,18968,18969,18970,
-18971,18972,18973,18974,18975,18976,18977,18978,18979,18980,18981,18982,
-18983,18984,18985,18986,18987,18988,18989,18990,18991,18992,18993,18994,
-18995,18996,18997,18998,18999,19000,19001,19002,19003,19004,19005,19006,
-19007,19008,19009,19010,19011,19012,19013,19014,19015,19016,19017,19018,
-19019,19020,19021,19022,19023,19024,19025,19026,19027,19028,19029,19030,
-19031,19032,19033,19034,19035,19036,19037,19038,19039,19040,19041,19042,
-19043,19044,19045,19046,19047,19048,19049,19050,19051,19052,19053,19054,
-19055,19056,19057,19058,19059,19060,19061,19062,19063,19064,19065,19066,
-19067,19068,19069,19070,19071,19072,19073,19074,19075,19076,19077,19078,
-19079,19080,19081,19082,19083,19084,19085,19086,19087,19088,19089,19090,
-19091,19092,19093,19094,19095,19096,19097,19098,19099,19100,19101,19102,
-19103,19104,19105,19106,19107,19108,19109,19110,19111,19112,19113,19114,
-19115,19116,19117,19118,19119,19120,19121,19122,19123,19124,19125,19126,
-19127,19128,19129,19130,19131,19132,19133,19134,19135,19136,19137,19138,
-19139,19140,19141,19142,19143,19144,19145,19146,19147,19148,19149,19150,
-19151,19152,19153,19154,19155,19156,19157,19158,19159,19160,19161,19162,
-19163,19164,19165,19166,19167,19168,19169,19170,19171,19172,19173,19174,
-19175,19176,19177,19178,19179,19180,19181,19182,19183,19184,19185,19186,
-19187,19188,19189,19190,19191,19192,19193,19194,19195,19196,19197,19198,
-19199,19200,19201,19202,19203,19204,19205,19206,19207,19208,19209,19210,
-19211,19212,19213,19214,19215,19216,19217,19218,19219,19220,19221,19222,
-19223,19224,19225,19226,19227,19228,19229,19230,19231,19232,19233,19234,
-19235,19236,19237,19238,19239,19240,19241,19242,19243,19244,19245,19246,
-19247,19248,19249,19250,19251,19252,19253,19254,19255,19256,19257,19258,
-19259,19260,19261,19262,19263,19264,19265,19266,19267,19268,19269,19270,
-19271,19272,19273,19274,19275,19276,19277,19278,19279,19280,19281,19282,
-19283,19284,19285,19286,19287,19288,19289,19290,19291,19292,19293,19294,
-19295,19296,19297,19298,19299,19300,19301,19302,19303,19304,19305,19306,
-19307,19308,19309,19310,19311,19312,19313,19314,19315,19316,19317,19318,
-19319,19320,19321,19322,19323,19324,19325,19326,19327,19328,19329,19330,
-19331,19332,19333,19334,19335,19336,19337,19338,19339,19340,19341,19342,
-19343,19344,19345,19346,19347,19348,19349,19350,19351,19352,19353,19354,
-19355,19356,19357,19358,19359,19360,19361,19362,19363,19364,19365,19366,
-19367,19368,19369,19370,19371,19372,19373,19374,19375,19376,19377,19378,
-19379,19380,19381,19382,19383,19384,19385,19386,19387,19388,19389,19390,
-19391,19392,19393,19394,19395,19396,19397,19398,19399,19400,19401,19402,
-19403,19404,19405,19406,19407,19408,19409,19410,19411,19412,19413,19414,
-19415,19416,19417,19418,19419,19420,19421,19422,19423,19424,19425,19426,
-19427,19428,19429,19430,19431,19432,19433,19434,19435,19436,19437,19438,
-19439,19440,19441,19442,19443,19444,19445,19446,19447,19448,19449,19450,
-19451,19452,19453,19454,19455,19456,19457,19458,19459,19460,19461,19462,
-19463,19464,19465,19466,19467,19468,19469,19470,19471,19472,19473,19474,
-19475,19476,19477,19478,19479,19480,19481,19482,19483,19484,19485,19486,
-19487,19488,19489,19490,19491,19492,19493,19494,19495,19496,19497,19498,
-19499,19500,19501,19502,19503,19504,19505,19506,19507,19508,19509,19510,
-19511,19512,19513,19514,19515,19516,19517,19518,19519,19520,19521,19522,
-19523,19524,19525,19526,19527,19528,19529,19530,19531,19532,19533,19534,
-19535,19536,19537,19538,19539,19540,19541,19542,19543,19544,19545,19546,
-19547,19548,19549,19550,19551,19552,19553,19554,19555,19556,19557,19558,
-19559,19560,19561,19562,19563,19564,19565,19566,19567,19568,19569,19570,
-19571,19572,19573,19574,19575,19576,19577,19578,19579,19580,19581,19582,
-19583,19584,19585,19586,19587,19588,19589,19590,19591,19592,19593,19594,
-19595,19596,19597,19598,19599,19600,19601,19602,19603,19604,19605,19606,
-19607,19608,19609,19610,19611,19612,19613,19614,19615,19616,19617,19618,
-19619,19620,19621,19622,19623,19624,19625,19626,19627,19628,19629,19630,
-19631,19632,19633,19634,19635,19636,19637,19638,19639,19640,19641,19642,
-19643,19644,19645,19646,19647,19648,19649,19650,19651,19652,19653,19654,
-19655,19656,19657,19658,19659,19660,19661,19662,19663,19664,19665,19666,
-19667,19668,19669,19670,19671,19672,19673,19674,19675,19676,19677,19678,
-19679,19680,19681,19682,19683,19684,19685,19686,19687,19688,19689,19690,
-19691,19692,19693,19694,19695,19696,19697,19698,19699,19700,19701,19702,
-19703,19704,19705,19706,19707,19708,19709,19710,19711,19712,19713,19714,
-19715,19716,19717,19718,19719,19720,19721,19722,19723,19724,19725,19726,
-19727,19728,19729,19730,19731,19732,19733,19734,19735,19736,19737,19738,
-19739,19740,19741,19742,19743,19744,19745,19746,19747,19748,19749,19750,
-19751,19752,19753,19754,19755,19756,19757,19758,19759,19760,19761,19762,
-19763,19764,19765,19766,19767,19768,19769,19770,19771,19772,19773,19774,
-19775,19776,19777,19778,19779,19780,19781,19782,19783,19784,19785,19786,
-19787,19788,19789,19790,19791,19792,19793,19794,19795,19796,19797,19798,
-19799,19800,19801,19802,19803,19804,19805,19806,19807,19808,19809,19810,
-19811,19812,19813,19814,19815,19816,19817,19818,19819,19820,19821,19822,
-19823,19824,19825,19826,19827,19828,19829,19830,19831,19832,19833,19834,
-19835,19836,19837,19838,19839,19840,19841,19842,19843,19844,19845,19846,
-19847,19848,19849,19850,19851,19852,19853,19854,19855,19856,19857,19858,
-19859,19860,19861,19862,19863,19864,19865,19866,19867,19868,19869,19870,
-19871,19872,19873,19874,19875,19876,19877,19878,19879,19880,19881,19882,
-19883,19884,19885,19886,19887,19888,19889,19890,19891,19892,19893,19894,
-19895,19896,19897,19898,19899,19900,19901,19902,19903,19904,19905,19906,
-19907,19908,19909,19910,19911,19912,19913,19914,19915,19916,19917,19918,
-19919,19920,19921,19922,19923,19924,19925,19926,19927,19928,19929,19930,
-19931,19932,19933,19934,19935,19936,19937,19938,19939,19940,19941,19942,
-19943,19944,19945,19946,19947,19948,19949,19950,19951,19952,19953,19954,
-19955,19956,19957,19958,19959,19960,19961,19962,19963,19964,19965,19966,
-19967,19968,19969,19970,19971,19972,19973,19974,19975,19976,19977,19978,
-19979,19980,19981,19982,19983,19984,19985,19986,19987,19988,19989,19990,
-19991,19992,19993,19994,19995,19996,19997,19998,19999,20000,20001,20002,
-20003,20004,20005,20006,20007,20008,20009,20010,20011,20012,20013,20014,
-20015,20016,20017,20018,20019,20020,20021,20022,20023,20024,20025,20026,
-20027,20028,20029,20030,20031,20032,20033,20034,20035,20036,20037,20038,
-20039,20040,20041,20042,20043,20044,20045,20046,20047,20048,20049,20050,
-20051,20052,20053,20054,20055,20056,20057,20058,20059,20060,20061,20062,
-20063,20064,20065,20066,20067,20068,20069,20070,20071,20072,20073,20074,
-20075,20076,20077,20078,20079,20080,20081,20082,20083,20084,20085,20086,
-20087,20088,20089,20090,20091,20092,20093,20094,20095,20096,20097,20098,
-20099,20100,20101,20102,20103,20104,20105,20106,20107,20108,20109,20110,
-20111,20112,20113,20114,20115,20116,20117,20118,20119,20120,20121,20122,
-20123,20124,20125,20126,20127,20128,20129,20130,20131,20132,20133,20134,
-20135,20136,20137,20138,20139,20140,20141,20142,20143,20144,20145,20146,
-20147,20148,20149,20150,20151,20152,20153,20154,20155,20156,20157,20158,
-20159,20160,20161,20162,20163,20164,20165,20166,20167,20168,20169,20170,
-20171,20172,20173,20174,20175,20176,20177,20178,20179,20180,20181,20182,
-20183,20184,20185,20186,20187,20188,20189,20190,20191,20192,20193,20194,
-20195,20196,20197,20198,20199,20200,20201,20202,20203,20204,20205,20206,
-20207,20208,20209,20210,20211,20212,20213,20214,20215,20216,20217,20218,
-20219,20220,20221,20222,20223,20224,20225,20226,20227,20228,20229,20230,
-20231,20232,20233,20234,20235,20236,20237,20238,20239,20240,20241,20242,
-20243,20244,20245,20246,20247,20248,20249,20250,20251,20252,20253,20254,
-20255,20256,20257,20258,20259,20260,20261,20262,20263,20264,20265,20266,
-20267,20268,20269,20270,20271,20272,20273,20274,20275,20276,20277,20278,
-20279,20280,20281,20282,20283,20284,20285,20286,20287,20288,20289,20290,
-20291,20292,20293,20294,20295,20296,20297,20298,20299,20300,20301,20302,
-20303,20304,20305,20306,20307,20308,20309,20310,20311,20312,20313,20314,
-20315,20316,20317,20318,20319,20320,20321,20322,20323,20324,20325,20326,
-20327,20328,20329,20330,20331,20332,20333,20334,20335,20336,20337,20338,
-20339,20340,20341,20342,20343,20344,20345,20346,20347,20348,20349,20350,
-20351,20352,20353,20354,20355,20356,20357,20358,20359,20360,20361,20362,
-20363,20364,20365,20366,20367,20368,20369,20370,20371,20372,20373,20374,
-20375,20376,20377,20378,20379,20380,20381,20382,20383,20384,20385,20386,
-20387,20388,20389,20390,20391,20392,20393,20394,20395,20396,20397,20398,
-20399,20400,20401,20402,20403,20404,20405,20406,20407,20408,20409,20410,
-20411,20412,20413,20414,20415,20416,20417,20418,20419,20420,20421,20422,
-20423,20424,20425,20426,20427,20428,20429,20430,20431,20432,20433,20434,
-20435,20436,20437,20438,20439,20440,20441,20442,20443,20444,20445,20446,
-20447,20448,20449,20450,20451,20452,20453,20454,20455,20456,20457,20458,
-20459,20460,20461,20462,20463,20464,20465,20466,20467,20468,20469,20470,
-20471,20472,20473,20474,20475,20476,20477,20478,20479,20480,20481,20482,
-20483,20484,20485,20486,20487,20488,20489,20490,20491,20492,20493,20494,
-20495,20496,20497,20498,20499,20500,20501,20502,20503,20504,20505,20506,
-20507,20508,20509,20510,20511,20512,20513,20514,20515,20516,20517,20518,
-20519,20520,20521,20522,20523,20524,20525,20526,20527,20528,20529,20530,
-20531,20532,20533,20534,20535,20536,20537,20538,20539,20540,20541,20542,
-20543,20544,20545,20546,20547,20548,20549,20550,20551,20552,20553,20554,
-20555,20556,20557,20558,20559,20560,20561,20562,20563,20564,20565,20566,
-20567,20568,20569,20570,20571,20572,20573,20574,20575,20576,20577,20578,
-20579,20580,20581,20582,20583,20584,20585,20586,20587,20588,20589,20590,
-20591,20592,20593,20594,20595,20596,20597,20598,20599,20600,20601,20602,
-20603,20604,20605,20606,20607,20608,20609,20610,20611,20612,20613,20614,
-20615,20616,20617,20618,20619,20620,20621,20622,20623,20624,20625,20626,
-20627,20628,20629,20630,20631,20632,20633,20634,20635,20636,20637,20638,
-20639,20640,20641,20642,20643,20644,20645,20646,20647,20648,20649,20650,
-20651,20652,20653,20654,20655,20656,20657,20658,20659,20660,20661,20662,
-20663,20664,20665,20666,20667,20668,20669,20670,20671,20672,20673,20674,
-20675,20676,20677,20678,20679,20680,20681,20682,20683,20684,20685,20686,
-20687,20688,20689,20690,20691,20692,20693,20694,20695,20696,20697,20698,
-20699,20700,20701,20702,20703,20704,20705,20706,20707,20708,20709,20710,
-20711,20712,20713,20714,20715,20716,20717,20718,20719,20720,20721,20722,
-20723,20724,20725,20726,20727,20728,20729,20730,20731,20732,20733,20734,
-20735,20736,20737,20738,20739,20740,20741,20742,20743,20744,20745,20746,
-20747,20748,20749,20750,20751,20752,20753,20754,20755,20756,20757,20758,
-20759,20760,20761,20762,20763,20764,20765,20766,20767,20768,20769,20770,
-20771,20772,20773,20774,20775,20776,20777,20778,20779,20780,20781,20782,
-20783,20784,20785,20786,20787,20788,20789,20790,20791,20792,20793,20794,
-20795,20796,20797,20798,20799,20800,20801,20802,20803,20804,20805,20806,
-20807,20808,20809,20810,20811,20812,20813,20814,20815,20816,20817,20818,
-20819,20820,20821,20822,20823,20824,20825,20826,20827,20828,20829,20830,
-20831,20832,20833,20834,20835,20836,20837,20838,20839,20840,20841,20842,
-20843,20844,20845,20846,20847,20848,20849,20850,20851,20852,20853,20854,
-20855,20856,20857,20858,20859,20860,20861,20862,20863,20864,20865,20866,
-20867,20868,20869,20870,20871,20872,20873,20874,20875,20876,20877,20878,
-20879,20880,20881,20882,20883,20884,20885,20886,20887,20888,20889,20890,
-20891,20892,20893,20894,20895,20896,20897,20898,20899,20900,20901,20902,
-20903,20904,20905,20906,20907,20908,20909,20910,20911,20912,20913,20914,
-20915,20916,20917,20918,20919,20920,20921,20922,20923,20924,20925,20926,
-20927,20928,20929,20930,20931,20932,20933,20934,20935,20936,20937,20938,
-20939,20940,20941,20942,20943,20944,20945,20946,20947,20948,20949,20950,
-20951,20952,20953,20954,20955,20956,20957,20958,20959,20960,20961,20962,
-20963,20964,20965,20966,20967,20968,20969,20970,20971,20972,20973,20974,
-20975,20976,20977,20978,20979,20980,20981,20982,20983,20984,20985,20986,
-20987,20988,20989,20990,20991,20992,20993,20994,20995,20996,20997,20998,
-20999,21000,21001,21002,21003,21004,21005,21006,21007,21008,21009,21010,
-21011,21012,21013,21014,21015,21016,21017,21018,21019,21020,21021,21022,
-21023,21024,21025,21026,21027,21028,21029,21030,21031,21032,21033,21034,
-21035,21036,21037,21038,21039,21040,21041,21042,21043,21044,21045,21046,
-21047,21048,21049,21050,21051,21052,21053,21054,21055,21056,21057,21058,
-21059,21060,21061,21062,21063,21064,21065,21066,21067,21068,21069,21070,
-21071,21072,21073,21074,21075,21076,21077,21078,21079,21080,21081,21082,
-21083,21084,21085,21086,21087,21088,21089,21090,21091,21092,21093,21094,
-21095,21096,21097,21098,21099,21100,21101,21102,21103,21104,21105,21106,
-21107,21108,21109,21110,21111,21112,21113,21114,21115,21116,21117,21118,
-21119,21120,21121,21122,21123,21124,21125,21126,21127,21128,21129,21130,
-21131,21132,21133,21134,21135,21136,21137,21138,21139,21140,21141,21142,
-21143,21144,21145,21146,21147,21148,21149,21150,21151,21152,21153,21154,
-21155,21156,21157,21158,21159,21160,21161,21162,21163,21164,21165,21166,
-21167,21168,21169,21170,21171,21172,21173,21174,21175,21176,21177,21178,
-21179,21180,21181,21182,21183,21184,21185,21186,21187,21188,21189,21190,
-21191,21192,21193,21194,21195,21196,21197,21198,21199,21200,21201,21202,
-21203,21204,21205,21206,21207,21208,21209,21210,21211,21212,21213,21214,
-21215,21216,21217,21218,21219,21220,21221,21222,21223,21224,21225,21226,
-21227,21228,21229,21230,21231,21232,21233,21234,21235,21236,21237,21238,
-21239,21240,21241,21242,21243,21244,21245,21246,21247,21248,21249,21250,
-21251,21252,21253,21254,21255,21256,21257,21258,21259,21260,21261,21262,
-21263,21264,21265,21266,21267,21268,21269,21270,21271,21272,21273,21274,
-21275,21276,21277,21278,21279,21280,21281,21282,21283,21284,21285,21286,
-21287,21288,21289,21290,21291,21292,21293,21294,21295,21296,21297,21298,
-21299,21300,21301,21302,21303,21304,21305,21306,21307,21308,21309,21310,
-21311,21312,21313,21314,21315,21316,21317,21318,21319,21320,21321,21322,
-21323,21324,21325,21326,21327,21328,21329,21330,21331,21332,21333,21334,
-21335,21336,21337,21338,21339,21340,21341,21342,21343,21344,21345,21346,
-21347,21348,21349,21350,21351,21352,21353,21354,21355,21356,21357,21358,
-21359,21360,21361,21362,21363,21364,21365,21366,21367,21368,21369,21370,
-21371,21372,21373,21374,21375,21376,21377,21378,21379,21380,21381,21382,
-21383,21384,21385,21386,21387,21388,21389,21390,21391,21392,21393,21394,
-21395,21396,21397,21398,21399,21400,21401,21402,21403,21404,21405,21406,
-21407,21408,21409,21410,21411,21412,21413,21414,21415,21416,21417,21418,
-21419,21420,21421,21422,21423,21424,21425,21426,21427,21428,21429,21430,
-21431,21432,21433,21434,21435,21436,21437,21438,21439,21440,21441,21442,
-21443,21444,21445,21446,21447,21448,21449,21450,21451,21452,21453,21454,
-21455,21456,21457,21458,21459,21460,21461,21462,21463,21464,21465,21466,
-21467,21468,21469,21470,21471,21472,21473,21474,21475,21476,21477,21478,
-21479,21480,21481,21482,21483,21484,21485,21486,21487,21488,21489,21490,
-21491,21492,21493,21494,21495,21496,21497,21498,21499,21500,21501,21502,
-21503,21504,21505,21506,21507,21508,21509,21510,21511,21512,21513,21514,
-21515,21516,21517,21518,21519,21520,21521,21522,21523,21524,21525,21526,
-21527,21528,21529,21530,21531,21532,21533,21534,21535,21536,21537,21538,
-21539,21540,21541,21542,21543,21544,21545,21546,21547,21548,21549,21550,
-21551,21552,21553,21554,21555,21556,21557,21558,21559,21560,21561,21562,
-21563,21564,21565,21566,21567,21568,21569,21570,21571,21572,21573,21574,
-21575,21576,21577,21578,21579,21580,21581,21582,21583,21584,21585,21586,
-21587,21588,21589,21590,21591,21592,21593,21594,21595,21596,21597,21598,
-21599,21600,21601,21602,21603,21604,21605,21606,21607,21608,21609,21610,
-21611,21612,21613,21614,21615,21616,21617,21618,21619,21620,21621,21622,
-21623,21624,21625,21626,21627,21628,21629,21630,21631,21632,21633,21634,
-21635,21636,21637,21638,21639,21640,21641,21642,21643,21644,21645,21646,
-21647,21648,21649,21650,21651,21652,21653,21654,21655,21656,21657,21658,
-21659,21660,21661,21662,21663,21664,21665,21666,21667,21668,21669,21670,
-21671,21672,21673,21674,21675,21676,21677,21678,21679,21680,21681,21682,
-21683,21684,21685,21686,21687,21688,21689,21690,21691,21692,21693,21694,
-21695,21696,21697,21698,21699,21700,21701,21702,21703,21704,21705,21706,
-21707,21708,21709,21710,21711,21712,21713,21714,21715,21716,21717,21718,
-21719,21720,21721,21722,21723,21724,21725,21726,21727,21728,21729,21730,
-21731,21732,21733,21734,21735,21736,21737,21738,21739,21740,21741,21742,
-21743,21744,21745,21746,21747,21748,21749,21750,21751,21752,21753,21754,
-21755,21756,21757,21758,21759,21760,21761,21762,21763,21764,21765,21766,
-21767,21768,21769,21770,21771,21772,21773,21774,21775,21776,21777,21778,
-21779,21780,21781,21782,21783,21784,21785,21786,21787,21788,21789,21790,
-21791,21792,21793,21794,21795,21796,21797,21798,21799,21800,21801,21802,
-21803,21804,21805,21806,21807,21808,21809,21810,21811,21812,21813,21814,
-21815,21816,21817,21818,21819,21820,21821,21822,21823,21824,21825,21826,
-21827,21828,21829,21830,21831,21832,21833,21834,21835,21836,21837,21838,
-21839,21840,21841,21842,21843,21844,21845,21846,21847,21848,21849,21850,
-21851,21852,21853,21854,21855,21856,21857,21858,21859,21860,21861,21862,
-21863,21864,21865,21866,21867,21868,21869,21870,21871,21872,21873,21874,
-21875,21876,21877,21878,21879,21880,21881,21882,21883,21884,21885,21886,
-21887,21888,21889,21890,21891,21892,21893,21894,21895,21896,21897,21898,
-21899,21900,21901,21902,21903,21904,21905,21906,21907,21908,21909,21910,
-21911,21912,21913,21914,21915,21916,21917,21918,21919,21920,21921,21922,
-21923,21924,21925,21926,21927,21928,21929,21930,21931,21932,21933,21934,
-21935,21936,21937,21938,21939,21940,21941,21942,21943,21944,21945,21946,
-21947,21948,21949,21950,21951,21952,21953,21954,21955,21956,21957,21958,
-21959,21960,21961,21962,21963,21964,21965,21966,21967,21968,21969,21970,
-21971,21972,21973,21974,21975,21976,21977,21978,21979,21980,21981,21982,
-21983,21984,21985,21986,21987,21988,21989,21990,21991,21992,21993,21994,
-21995,21996,21997,21998,21999,22000,22001,22002,22003,22004,22005,22006,
-22007,22008,22009,22010,22011,22012,22013,22014,22015,22016,22017,22018,
-22019,22020,22021,22022,22023,22024,22025,22026,22027,22028,22029,22030,
-22031,22032,22033,22034,22035,22036,22037,22038,22039,22040,22041,22042,
-22043,22044,22045,22046,22047,22048,22049,22050,22051,22052,22053,22054,
-22055,22056,22057,22058,22059,22060,22061,22062,22063,22064,22065,22066,
-22067,22068,22069,22070,22071,22072,22073,22074,22075,22076,22077,22078,
-22079,22080,22081,22082,22083,22084,22085,22086,22087,22088,22089,22090,
-22091,22092,22093,22094,22095,22096,22097,22098,22099,22100,22101,22102,
-22103,22104,22105,22106,22107,22108,22109,22110,22111,22112,22113,22114,
-22115,22116,22117,22118,22119,22120,22121,22122,22123,22124,22125,22126,
-22127,22128,22129,22130,22131,22132,22133,22134,22135,22136,22137,22138,
-22139,22140,22141,22142,22143,22144,22145,22146,22147,22148,22149,22150,
-22151,22152,22153,22154,22155,22156,22157,22158,22159,22160,22161,22162,
-22163,22164,22165,22166,22167,22168,22169,22170,22171,22172,22173,22174,
-22175,22176,22177,22178,22179,22180,22181,22182,22183,22184,22185,22186,
-22187,22188,22189,22190,22191,22192,22193,22194,22195,22196,22197,22198,
-22199,22200,22201,22202,22203,22204,22205,22206,22207,22208,22209,22210,
-22211,22212,22213,22214,22215,22216,22217,22218,22219,22220,22221,22222,
-22223,22224,22225,22226,22227,22228,22229,22230,22231,22232,22233,22234,
-22235,22236,22237,22238,22239,22240,22241,22242,22243,22244,22245,22246,
-22247,22248,22249,22250,22251,22252,22253,22254,22255,22256,22257,22258,
-22259,22260,22261,22262,22263,22264,22265,22266,22267,22268,22269,22270,
-22271,22272,22273,22274,22275,22276,22277,22278,22279,22280,22281,22282,
-22283,22284,22285,22286,22287,22288,22289,22290,22291,22292,22293,22294,
-22295,22296,22297,22298,22299,22300,22301,22302,22303,22304,22305,22306,
-22307,22308,22309,22310,22311,22312,22313,22314,22315,22316,22317,22318,
-22319,22320,22321,22322,22323,22324,22325,22326,22327,22328,22329,22330,
-22331,22332,22333,22334,22335,22336,22337,22338,22339,22340,22341,22342,
-22343,22344,22345,22346,22347,22348,22349,22350,22351,22352,22353,22354,
-22355,22356,22357,22358,22359,22360,22361,22362,22363,22364,22365,22366,
-22367,22368,22369,22370,22371,22372,22373,22374,22375,22376,22377,22378,
-22379,22380,22381,22382,22383,22384,22385,22386,22387,22388,22389,22390,
-22391,22392,22393,22394,22395,22396,22397,22398,22399,22400,22401,22402,
-22403,22404,22405,22406,22407,22408,22409,22410,22411,22412,22413,22414,
-22415,22416,22417,22418,22419,22420,22421,22422,22423,22424,22425,22426,
-22427,22428,22429,22430,22431,22432,22433,22434,22435,22436,22437,22438,
-22439,22440,22441,22442,22443,22444,22445,22446,22447,22448,22449,22450,
-22451,22452,22453,22454,22455,22456,22457,22458,22459,22460,22461,22462,
-22463,22464,22465,22466,22467,22468,22469,22470,22471,22472,22473,22474,
-22475,22476,22477,22478,22479,22480,22481,22482,22483,22484,22485,22486,
-22487,22488,22489,22490,22491,22492,22493,22494,22495,22496,22497,22498,
-22499,22500,22501,22502,22503,22504,22505,22506,22507,22508,22509,22510,
-22511,22512,22513,22514,22515,22516,22517,22518,22519,22520,22521,22522,
-22523,22524,22525,22526,22527,22528,22529,22530,22531,22532,22533,22534,
-22535,22536,22537,22538,22539,22540,22541,22542,22543,22544,22545,22546,
-22547,22548,22549,22550,22551,22552,22553,22554,22555,22556,22557,22558,
-22559,22560,22561,22562,22563,22564,22565,22566,22567,22568,22569,22570,
-22571,22572,22573,22574,22575,22576,22577,22578,22579,22580,22581,22582,
-22583,22584,22585,22586,22587,22588,22589,22590,22591,22592,22593,22594,
-22595,22596,22597,22598,22599,22600,22601,22602,22603,22604,22605,22606,
-22607,22608,22609,22610,22611,22612,22613,22614,22615,22616,22617,22618,
-22619,22620,22621,22622,22623,22624,22625,22626,22627,22628,22629,22630,
-22631,22632,22633,22634,22635,22636,22637,22638,22639,22640,22641,22642,
-22643,22644,22645,22646,22647,22648,22649,22650,22651,22652,22653,22654,
-22655,22656,22657,22658,22659,22660,22661,22662,22663,22664,22665,22666,
-22667,22668,22669,22670,22671,22672,22673,22674,22675,22676,22677,22678,
-22679,22680,22681,22682,22683,22684,22685,22686,22687,22688,22689,22690,
-22691,22692,22693,22694,22695,22696,22697,22698,22699,22700,22701,22702,
-22703,22704,22705,22706,22707,22708,22709,22710,22711,22712,22713,22714,
-22715,22716,22717,22718,22719,22720,22721,22722,22723,22724,22725,22726,
-22727,22728,22729,22730,22731,22732,22733,22734,22735,22736,22737,22738,
-22739,22740,22741,22742,22743,22744,22745,22746,22747,22748,22749,22750,
-22751,22752,22753,22754,22755,22756,22757,22758,22759,22760,22761,22762,
-22763,22764,22765,22766,22767,22768,22769,22770,22771,22772,22773,22774,
-22775,22776,22777,22778,22779,22780,22781,22782,22783,22784,22785,22786,
-22787,22788,22789,22790,22791,22792,22793,22794,22795,22796,22797,22798,
-22799,22800,22801,22802,22803,22804,22805,22806,22807,22808,22809,22810,
-22811,22812,22813,22814,22815,22816,22817,22818,22819,22820,22821,22822,
-22823,22824,22825,22826,22827,22828,22829,22830,22831,22832,22833,22834,
-22835,22836,22837,22838,22839,22840,22841,22842,22843,22844,22845,22846,
-22847,22848,22849,22850,22851,22852,22853,22854,22855,22856,22857,22858,
-22859,22860,22861,22862,22863,22864,22865,22866,22867,22868,22869,22870,
-22871,22872,22873,22874,22875,22876,22877,22878,22879,22880,22881,22882,
-22883,22884,22885,22886,22887,22888,22889,22890,22891,22892,22893,22894,
-22895,22896,22897,22898,22899,22900,22901,22902,22903,22904,22905,22906,
-22907,22908,22909,22910,22911,22912,22913,22914,22915,22916,22917,22918,
-22919,22920,22921,22922,22923,22924,22925,22926,22927,22928,22929,22930,
-22931,22932,22933,22934,22935,22936,22937,22938,22939,22940,22941,22942,
-22943,22944,22945,22946,22947,22948,22949,22950,22951,22952,22953,22954,
-22955,22956,22957,22958,22959,22960,22961,22962,22963,22964,22965,22966,
-22967,22968,22969,22970,22971,22972,22973,22974,22975,22976,22977,22978,
-22979,22980,22981,22982,22983,22984,22985,22986,22987,22988,22989,22990,
-22991,22992,22993,22994,22995,22996,22997,22998,22999,23000,23001,23002,
-23003,23004,23005,23006,23007,23008,23009,23010,23011,23012,23013,23014,
-23015,23016,23017,23018,23019,23020,23021,23022,23023,23024,23025,23026,
-23027,23028,23029,23030,23031,23032,23033,23034,23035,23036,23037,23038,
-23039,23040,23041,23042,23043,23044,23045,23046,23047,23048,23049,23050,
-23051,23052,23053,23054,23055,23056,23057,23058,23059,23060,23061,23062,
-23063,23064,23065,23066,23067,23068,23069,23070,23071,23072,23073,23074,
-23075,23076,23077,23078,23079,23080,23081,23082,23083,23084,23085,23086,
-23087,23088,23089,23090,23091,23092,23093,23094,23095,23096,23097,23098,
-23099,23100,23101,23102,23103,23104,23105,23106,23107,23108,23109,23110,
-23111,23112,23113,23114,23115,23116,23117,23118,23119,23120,23121,23122,
-23123,23124,23125,23126,23127,23128,23129,23130,23131,23132,23133,23134,
-23135,23136,23137,23138,23139,23140,23141,23142,23143,23144,23145,23146,
-23147,23148,23149,23150,23151,23152,23153,23154,23155,23156,23157,23158,
-23159,23160,23161,23162,23163,23164,23165,23166,23167,23168,23169,23170,
-23171,23172,23173,23174,23175,23176,23177,23178,23179,23180,23181,23182,
-23183,23184,23185,23186,23187,23188,23189,23190,23191,23192,23193,23194,
-23195,23196,23197,23198,23199,23200,23201,23202,23203,23204,23205,23206,
-23207,23208,23209,23210,23211,23212,23213,23214,23215,23216,23217,23218,
-23219,23220,23221,23222,23223,23224,23225,23226,23227,23228,23229,23230,
-23231,23232,23233,23234,23235,23236,23237,23238,23239,23240,23241,23242,
-23243,23244,23245,23246,23247,23248,23249,23250,23251,23252,23253,23254,
-23255,23256,23257,23258,23259,23260,23261,23262,23263,23264,23265,23266,
-23267,23268,23269,23270,23271,23272,23273,23274,23275,23276,23277,23278,
-23279,23280,23281,23282,23283,23284,23285,23286,23287,23288,23289,23290,
-23291,23292,23293,23294,23295,23296,23297,23298,23299,23300,23301,23302,
-23303,23304,23305,23306,23307,23308,23309,23310,23311,23312,23313,23314,
-23315,23316,23317,23318,23319,23320,23321,23322,23323,23324,23325,23326,
-23327,23328,23329,23330,23331,23332,23333,23334,23335,23336,23337,23338,
-23339,23340,23341,23342,23343,23344,23345,23346,23347,23348,23349,23350,
-23351,23352,23353,23354,23355,23356,23357,23358,23359,23360,23361,23362,
-23363,23364,23365,23366,23367,23368,23369,23370,23371,23372,23373,23374,
-23375,23376,23377,23378,23379,23380,23381,23382,23383,23384,23385,23386,
-23387,23388,23389,23390,23391,23392,23393,23394,23395,23396,23397,23398,
-23399,23400,23401,23402,23403,23404,23405,23406,23407,23408,23409,23410,
-23411,23412,23413,23414,23415,23416,23417,23418,23419,23420,23421,23422,
-23423,23424,23425,23426,23427,23428,23429,23430,23431,23432,23433,23434,
-23435,23436,23437,23438,23439,23440,23441,23442,23443,23444,23445,23446,
-23447,23448,23449,23450,23451,23452,23453,23454,23455,23456,23457,23458,
-23459,23460,23461,23462,23463,23464,23465,23466,23467,23468,23469,23470,
-23471,23472,23473,23474,23475,23476,23477,23478,23479,23480,23481,23482,
-23483,23484,23485,23486,23487,23488,23489,23490,23491,23492,23493,23494,
-23495,23496,23497,23498,23499,23500,23501,23502,23503,23504,23505,23506,
-23507,23508,23509,23510,23511,23512,23513,23514,23515,23516,23517,23518,
-23519,23520,23521,23522,23523,23524,23525,23526,23527,23528,23529,23530,
-23531,23532,23533,23534,23535,23536,23537,23538,23539,23540,23541,23542,
-23543,23544,23545,23546,23547,23548,23549,23550,23551,23552,23553,23554,
-23555,23556,23557,23558,23559,23560,23561,23562,23563,23564,23565,23566,
-23567,23568,23569,23570,23571,23572,23573,23574,23575,23576,23577,23578,
-23579,23580,23581,23582,23583,23584,23585,23586,23587,23588,23589,23590,
-23591,23592,23593,23594,23595,23596,23597,23598,23599,23600,23601,23602,
-23603,23604,23605,23606,23607,23608,23609,23610,23611,23612,23613,23614,
-23615,23616,23617,23618,23619,23620,23621,23622,23623,23624,23625,23626,
-23627,23628,23629,23630,23631,23632,23633,23634,23635,23636,23637,23638,
-23639,23640,23641,23642,23643,23644,23645,23646,23647,23648,23649,23650,
-23651,23652,23653,23654,23655,23656,23657,23658,23659,23660,23661,23662,
-23663,23664,23665,23666,23667,23668,23669,23670,23671,23672,23673,23674,
-23675,23676,23677,23678,23679,23680,23681,23682,23683,23684,23685,23686,
-23687,23688,23689,23690,23691,23692,23693,23694,23695,23696,23697,23698,
-23699,23700,23701,23702,23703,23704,23705,23706,23707,23708,23709,23710,
-23711,23712,23713,23714,23715,23716,23717,23718,23719,23720,23721,23722,
-23723,23724,23725,23726,23727,23728,23729,23730,23731,23732,23733,23734,
-23735,23736,23737,23738,23739,23740,23741,23742,23743,23744,23745,23746,
-23747,23748,23749,23750,23751,23752,23753,23754,23755,23756,23757,23758,
-23759,23760,23761,23762,23763,23764,23765,23766,23767,23768,23769,23770,
-23771,23772,23773,23774,23775,23776,23777,23778,23779,23780,23781,23782,
-23783,23784,23785,23786,23787,23788,23789,23790,23791,23792,23793,23794,
-23795,23796,23797,23798,23799,23800,23801,23802,23803,23804,23805,23806,
-23807,23808,23809,23810,23811,23812,23813,23814,23815,23816,23817,23818,
-23819,23820,23821,23822,23823,23824,23825,23826,23827,23828,23829,23830,
-23831,23832,23833,23834,23835,23836,23837,23838,23839,23840,23841,23842,
-23843,23844,23845,23846,23847,23848,23849,23850,23851,23852,23853,23854,
-23855,23856,23857,23858,23859,23860,23861,23862,23863,23864,23865,23866,
-23867,23868,23869,23870,23871,23872,23873,23874,23875,23876,23877,23878,
-23879,23880,23881,23882,23883,23884,23885,23886,23887,23888,23889,23890,
-23891,23892,23893,23894,23895,23896,23897,23898,23899,23900,23901,23902,
-23903,23904,23905,23906,23907,23908,23909,23910,23911,23912,23913,23914,
-23915,23916,23917,23918,23919,23920,23921,23922,23923,23924,23925,23926,
-23927,23928,23929,23930,23931,23932,23933,23934,23935,23936,23937,23938,
-23939,23940,23941,23942,23943,23944,23945,23946,23947,23948,23949,23950,
-23951,23952,23953,23954,23955,23956,23957,23958,23959,23960,23961,23962,
-23963,23964,23965,23966,23967,23968,23969,23970,23971,23972,23973,23974,
-23975,23976,23977,23978,23979,23980,23981,23982,23983,23984,23985,23986,
-23987,23988,23989,23990,23991,23992,23993,23994,23995,23996,23997,23998,
-23999,24000,24001,24002,24003,24004,24005,24006,24007,24008,24009,24010,
-24011,24012,24013,24014,24015,24016,24017,24018,24019,24020,24021,24022,
-24023,24024,24025,24026,24027,24028,24029,24030,24031,24032,24033,24034,
-24035,24036,24037,24038,24039,24040,24041,24042,24043,24044,24045,24046,
-24047,24048,24049,24050,24051,24052,24053,24054,24055,24056,24057,24058,
-24059,24060,24061,24062,24063,24064,24065,24066,24067,24068,24069,24070,
-24071,24072,24073,24074,24075,24076,24077,24078,24079,24080,24081,24082,
-24083,24084,24085,24086,24087,24088,24089,24090,24091,24092,24093,24094,
-24095,24096,24097,24098,24099,24100,24101,24102,24103,24104,24105,24106,
-24107,24108,24109,24110,24111,24112,24113,24114,24115,24116,24117,24118,
-24119,24120,24121,24122,24123,24124,24125,24126,24127,24128,24129,24130,
-24131,24132,24133,24134,24135,24136,24137,24138,24139,24140,24141,24142,
-24143,24144,24145,24146,24147,24148,24149,24150,24151,24152,24153,24154,
-24155,24156,24157,24158,24159,24160,24161,24162,24163,24164,24165,24166,
-24167,24168,24169,24170,24171,24172,24173,24174,24175,24176,24177,24178,
-24179,24180,24181,24182,24183,24184,24185,24186,24187,24188,24189,24190,
-24191,24192,24193,24194,24195,24196,24197,24198,24199,24200,24201,24202,
-24203,24204,24205,24206,24207,24208,24209,24210,24211,24212,24213,24214,
-24215,24216,24217,24218,24219,24220,24221,24222,24223,24224,24225,24226,
-24227,24228,24229,24230,24231,24232,24233,24234,24235,24236,24237,24238,
-24239,24240,24241,24242,24243,24244,24245,24246,24247,24248,24249,24250,
-24251,24252,24253,24254,24255,24256,24257,24258,24259,24260,24261,24262,
-24263,24264,24265,24266,24267,24268,24269,24270,24271,24272,24273,24274,
-24275,24276,24277,24278,24279,24280,24281,24282,24283,24284,24285,24286,
-24287,24288,24289,24290,24291,24292,24293,24294,24295,24296,24297,24298,
-24299,24300,24301,24302,24303,24304,24305,24306,24307,24308,24309,24310,
-24311,24312,24313,24314,24315,24316,24317,24318,24319,24320,24321,24322,
-24323,24324,24325,24326,24327,24328,24329,24330,24331,24332,24333,24334,
-24335,24336,24337,24338,24339,24340,24341,24342,24343,24344,24345,24346,
-24347,24348,24349,24350,24351,24352,24353,24354,24355,24356,24357,24358,
-24359,24360,24361,24362,24363,24364,24365,24366,24367,24368,24369,24370,
-24371,24372,24373,24374,24375,24376,24377,24378,24379,24380,24381,24382,
-24383,24384,24385,24386,24387,24388,24389,24390,24391,24392,24393,24394,
-24395,24396,24397,24398,24399,24400,24401,24402,24403,24404,24405,24406,
-24407,24408,24409,24410,24411,24412,24413,24414,24415,24416,24417,24418,
-24419,24420,24421,24422,24423,24424,24425,24426,24427,24428,24429,24430,
-24431,24432,24433,24434,24435,24436,24437,24438,24439,24440,24441,24442,
-24443,24444,24445,24446,24447,24448,24449,24450,24451,24452,24453,24454,
-24455,24456,24457,24458,24459,24460,24461,24462,24463,24464,24465,24466,
-24467,24468,24469,24470,24471,24472,24473,24474,24475,24476,24477,24478,
-24479,24480,24481,24482,24483,24484,24485,24486,24487,24488,24489,24490,
-24491,24492,24493,24494,24495,24496,24497,24498,24499,24500,24501,24502,
-24503,24504,24505,24506,24507,24508,24509,24510,24511,24512,24513,24514,
-24515,24516,24517,24518,24519,24520,24521,24522,24523,24524,24525,24526,
-24527,24528,24529,24530,24531,24532,24533,24534,24535,24536,24537,24538,
-24539,24540,24541,24542,24543,24544,24545,24546,24547,24548,24549,24550,
-24551,24552,24553,24554,24555,24556,24557,24558,24559,24560,24561,24562,
-24563,24564,24565,24566,24567,24568,24569,24570,24571,24572,24573,24574,
-24575,24576,24577,24578,24579,24580,24581,24582,24583,24584,24585,24586,
-24587,24588,24589,24590,24591,24592,24593,24594,24595,24596,24597,24598,
-24599,24600,24601,24602,24603,24604,24605,24606,24607,24608,24609,24610,
-24611,24612,24613,24614,24615,24616,24617,24618,24619,24620,24621,24622,
-24623,24624,24625,24626,24627,24628,24629,24630,24631,24632,24633,24634,
-24635,24636,24637,24638,24639,24640,24641,24642,24643,24644,24645,24646,
-24647,24648,24649,24650,24651,24652,24653,24654,24655,24656,24657,24658,
-24659,24660,24661,24662,24663,24664,24665,24666,24667,24668,24669,24670,
-24671,24672,24673,24674,24675,24676,24677,24678,24679,24680,24681,24682,
-24683,24684,24685,24686,24687,24688,24689,24690,24691,24692,24693,24694,
-24695,24696,24697,24698,24699,24700,24701,24702,24703,24704,24705,24706,
-24707,24708,24709,24710,24711,24712,24713,24714,24715,24716,24717,24718,
-24719,24720,24721,24722,24723,24724,24725,24726,24727,24728,24729,24730,
-24731,24732,24733,24734,24735,24736,24737,24738,24739,24740,24741,24742,
-24743,24744,24745,24746,24747,24748,24749,24750,24751,24752,24753,24754,
-24755,24756,24757,24758,24759,24760,24761,24762,24763,24764,24765,24766,
-24767,24768,24769,24770,24771,24772,24773,24774,24775,24776,24777,24778,
-24779,24780,24781,24782,24783,24784,24785,24786,24787,24788,24789,24790,
-24791,24792,24793,24794,24795,24796,24797,24798,24799,24800,24801,24802,
-24803,24804,24805,24806,24807,24808,24809,24810,24811,24812,24813,24814,
-24815,24816,24817,24818,24819,24820,24821,24822,24823,24824,24825,24826,
-24827,24828,24829,24830,24831,24832,24833,24834,24835,24836,24837,24838,
-24839,24840,24841,24842,24843,24844,24845,24846,24847,24848,24849,24850,
-24851,24852,24853,24854,24855,24856,24857,24858,24859,24860,24861,24862,
-24863,24864,24865,24866,24867,24868,24869,24870,24871,24872,24873,24874,
-24875,24876,24877,24878,24879,24880,24881,24882,24883,24884,24885,24886,
-24887,24888,24889,24890,24891,24892,24893,24894,24895,24896,24897,24898,
-24899,24900,24901,24902,24903,24904,24905,24906,24907,24908,24909,24910,
-24911,24912,24913,24914,24915,24916,24917,24918,24919,24920,24921,24922,
-24923,24924,24925,24926,24927,24928,24929,24930,24931,24932,24933,24934,
-24935,24936,24937,24938,24939,24940,24941,24942,24943,24944,24945,24946,
-24947,24948,24949,24950,24951,24952,24953,24954,24955,24956,24957,24958,
-24959,24960,24961,24962,24963,24964,24965,24966,24967,24968,24969,24970,
-24971,24972,24973,24974,24975,24976,24977,24978,24979,24980,24981,24982,
-24983,24984,24985,24986,24987,24988,24989,24990,24991,24992,24993,24994,
-24995,24996,24997,24998,24999,25000,25001,25002,25003,25004,25005,25006,
-25007,25008,25009,25010,25011,25012,25013,25014,25015,25016,25017,25018,
-25019,25020,25021,25022,25023,25024,25025,25026,25027,25028,25029,25030,
-25031,25032,25033,25034,25035,25036,25037,25038,25039,25040,25041,25042,
-25043,25044,25045,25046,25047,25048,25049,25050,25051,25052,25053,25054,
-25055,25056,25057,25058,25059,25060,25061,25062,25063,25064,25065,25066,
-25067,25068,25069,25070,25071,25072,25073,25074,25075,25076,25077,25078,
-25079,25080,25081,25082,25083,25084,25085,25086,25087,25088,25089,25090,
-25091,25092,25093,25094,25095,25096,25097,25098,25099,25100,25101,25102,
-25103,25104,25105,25106,25107,25108,25109,25110,25111,25112,25113,25114,
-25115,25116,25117,25118,25119,25120,25121,25122,25123,25124,25125,25126,
-25127,25128,25129,25130,25131,25132,25133,25134,25135,25136,25137,25138,
-25139,25140,25141,25142,25143,25144,25145,25146,25147,25148,25149,25150,
-25151,25152,25153,25154,25155,25156,25157,25158,25159,25160,25161,25162,
-25163,25164,25165,25166,25167,25168,25169,25170,25171,25172,25173,25174,
-25175,25176,25177,25178,25179,25180,25181,25182,25183,25184,25185,25186,
-25187,25188,25189,25190,25191,25192,25193,25194,25195,25196,25197,25198,
-25199,25200,25201,25202,25203,25204,25205,25206,25207,25208,25209,25210,
-25211,25212,25213,25214,25215,25216,25217,25218,25219,25220,25221,25222,
-25223,25224,25225,25226,25227,25228,25229,25230,25231,25232,25233,25234,
-25235,25236,25237,25238,25239,25240,25241,25242,25243,25244,25245,25246,
-25247,25248,25249,25250,25251,25252,25253,25254,25255,25256,25257,25258,
-25259,25260,25261,25262,25263,25264,25265,25266,25267,25268,25269,25270,
-25271,25272,25273,25274,25275,25276,25277,25278,25279,25280,25281,25282,
-25283,25284,25285,25286,25287,25288,25289,25290,25291,25292,25293,25294,
-25295,25296,25297,25298,25299,25300,25301,25302,25303,25304,25305,25306,
-25307,25308,25309,25310,25311,25312,25313,25314,25315,25316,25317,25318,
-25319,25320,25321,25322,25323,25324,25325,25326,25327,25328,25329,25330,
-25331,25332,25333,25334,25335,25336,25337,25338,25339,25340,25341,25342,
-25343,25344,25345,25346,25347,25348,25349,25350,25351,25352,25353,25354,
-25355,25356,25357,25358,25359,25360,25361,25362,25363,25364,25365,25366,
-25367,25368,25369,25370,25371,25372,25373,25374,25375,25376,25377,25378,
-25379,25380,25381,25382,25383,25384,25385,25386,25387,25388,25389,25390,
-25391,25392,25393,25394,25395,25396,25397,25398,25399,25400,25401,25402,
-25403,25404,25405,25406,25407,25408,25409,25410,25411,25412,25413,25414,
-25415,25416,25417,25418,25419,25420,25421,25422,25423,25424,25425,25426,
-25427,25428,25429,25430,25431,25432,25433,25434,25435,25436,25437,25438,
-25439,25440,25441,25442,25443,25444,25445,25446,25447,25448,25449,25450,
-25451,25452,25453,25454,25455,25456,25457,25458,25459,25460,25461,25462,
-25463,25464,25465,25466,25467,25468,25469,25470,25471,25472,25473,25474,
-25475,25476,25477,25478,25479,25480,25481,25482,25483,25484,25485,25486,
-25487,25488,25489,25490,25491,25492,25493,25494,25495,25496,25497,25498,
-25499,25500,25501,25502,25503,25504,25505,25506,25507,25508,25509,25510,
-25511,25512,25513,25514,25515,25516,25517,25518,25519,25520,25521,25522,
-25523,25524,25525,25526,25527,25528,25529,25530,25531,25532,25533,25534,
-25535,25536,25537,25538,25539,25540,25541,25542,25543,25544,25545,25546,
-25547,25548,25549,25550,25551,25552,25553,25554,25555,25556,25557,25558,
-25559,25560,25561,25562,25563,25564,25565,25566,25567,25568,25569,25570,
-25571,25572,25573,25574,25575,25576,25577,25578,25579,25580,25581,25582,
-25583,25584,25585,25586,25587,25588,25589,25590,25591,25592,25593,25594,
-25595,25596,25597,25598,25599,25600,25601,25602,25603,25604,25605,25606,
-25607,25608,25609,25610,25611,25612,25613,25614,25615,25616,25617,25618,
-25619,25620,25621,25622,25623,25624,25625,25626,25627,25628,25629,25630,
-25631,25632,25633,25634,25635,25636,25637,25638,25639,25640,25641,25642,
-25643,25644,25645,25646,25647,25648,25649,25650,25651,25652,25653,25654,
-25655,25656,25657,25658,25659,25660,25661,25662,25663,25664,25665,25666,
-25667,25668,25669,25670,25671,25672,25673,25674,25675,25676,25677,25678,
-25679,25680,25681,25682,25683,25684,25685,25686,25687,25688,25689,25690,
-25691,25692,25693,25694,25695,25696,25697,25698,25699,25700,25701,25702,
-25703,25704,25705,25706,25707,25708,25709,25710,25711,25712,25713,25714,
-25715,25716,25717,25718,25719,25720,25721,25722,25723,25724,25725,25726,
-25727,25728,25729,25730,25731,25732,25733,25734,25735,25736,25737,25738,
-25739,25740,25741,25742,25743,25744,25745,25746,25747,25748,25749,25750,
-25751,25752,25753,25754,25755,25756,25757,25758,25759,25760,25761,25762,
-25763,25764,25765,25766,25767,25768,25769,25770,25771,25772,25773,25774,
-25775,25776,25777,25778,25779,25780,25781,25782,25783,25784,25785,25786,
-25787,25788,25789,25790,25791,25792,25793,25794,25795,25796,25797,25798,
-25799,25800,25801,25802,25803,25804,25805,25806,25807,25808,25809,25810,
-25811,25812,25813,25814,25815,25816,25817,25818,25819,25820,25821,25822,
-25823,25824,25825,25826,25827,25828,25829,25830,25831,25832,25833,25834,
-25835,25836,25837,25838,25839,25840,25841,25842,25843,25844,25845,25846,
-25847,25848,25849,25850,25851,25852,25853,25854,25855,25856,25857,25858,
-25859,25860,25861,25862,25863,25864,25865,25866,25867,25868,25869,25870,
-25871,25872,25873,25874,25875,25876,25877,25878,25879,25880,25881,25882,
-25883,25884,25885,25886,25887,25888,25889,25890,25891,25892,25893,25894,
-25895,25896,25897,25898,25899,25900,25901,25902,25903,25904,25905,25906,
-25907,25908,25909,25910,25911,25912,25913,25914,25915,25916,25917,25918,
-25919,25920,25921,25922,25923,25924,25925,25926,25927,25928,25929,25930,
-25931,25932,25933,25934,25935,25936,25937,25938,25939,25940,25941,25942,
-25943,25944,25945,25946,25947,25948,25949,25950,25951,25952,25953,25954,
-25955,25956,25957,25958,25959,25960,25961,25962,25963,25964,25965,25966,
-25967,25968,25969,25970,25971,25972,25973,25974,25975,25976,25977,25978,
-25979,25980,25981,25982,25983,25984,25985,25986,25987,25988,25989,25990,
-25991,25992,25993,25994,25995,25996,25997,25998,25999,26000,26001,26002,
-26003,26004,26005,26006,26007,26008,26009,26010,26011,26012,26013,26014,
-26015,26016,26017,26018,26019,26020,26021,26022,26023,26024,26025,26026,
-26027,26028,26029,26030,26031,26032,26033,26034,26035,26036,26037,26038,
-26039,26040,26041,26042,26043,26044,26045,26046,26047,26048,26049,26050,
-26051,26052,26053,26054,26055,26056,26057,26058,26059,26060,26061,26062,
-26063,26064,26065,26066,26067,26068,26069,26070,26071,26072,26073,26074,
-26075,26076,26077,26078,26079,26080,26081,26082,26083,26084,26085,26086,
-26087,26088,26089,26090,26091,26092,26093,26094,26095,26096,26097,26098,
-26099,26100,26101,26102,26103,26104,26105,26106,26107,26108,26109,26110,
-26111,26112,26113,26114,26115,26116,26117,26118,26119,26120,26121,26122,
-26123,26124,26125,26126,26127,26128,26129,26130,26131,26132,26133,26134,
-26135,26136,26137,26138,26139,26140,26141,26142,26143,26144,26145,26146,
-26147,26148,26149,26150,26151,26152,26153,26154,26155,26156,26157,26158,
-26159,26160,26161,26162,26163,26164,26165,26166,26167,26168,26169,26170,
-26171,26172,26173,26174,26175,26176,26177,26178,26179,26180,26181,26182,
-26183,26184,26185,26186,26187,26188,26189,26190,26191,26192,26193,26194,
-26195,26196,26197,26198,26199,26200,26201,26202,26203,26204,26205,26206,
-26207,26208,26209,26210,26211,26212,26213,26214,26215,26216,26217,26218,
-26219,26220,26221,26222,26223,26224,26225,26226,26227,26228,26229,26230,
-26231,26232,26233,26234,26235,26236,26237,26238,26239,26240,26241,26242,
-26243,26244,26245,26246,26247,26248,26249,26250,26251,26252,26253,26254,
-26255,26256,26257,26258,26259,26260,26261,26262,26263,26264,26265,26266,
-26267,26268,26269,26270,26271,26272,26273,26274,26275,26276,26277,26278,
-26279,26280,26281,26282,26283,26284,26285,26286,26287,26288,26289,26290,
-26291,26292,26293,26294,26295,26296,26297,26298,26299,26300,26301,26302,
-26303,26304,26305,26306,26307,26308,26309,26310,26311,26312,26313,26314,
-26315,26316,26317,26318,26319,26320,26321,26322,26323,26324,26325,26326,
-26327,26328,26329,26330,26331,26332,26333,26334,26335,26336,26337,26338,
-26339,26340,26341,26342,26343,26344,26345,26346,26347,26348,26349,26350,
-26351,26352,26353,26354,26355,26356,26357,26358,26359,26360,26361,26362,
-26363,26364,26365,26366,26367,26368,26369,26370,26371,26372,26373,26374,
-26375,26376,26377,26378,26379,26380,26381,26382,26383,26384,26385,26386,
-26387,26388,26389,26390,26391,26392,26393,26394,26395,26396,26397,26398,
-26399,26400,26401,26402,26403,26404,26405,26406,26407,26408,26409,26410,
-26411,26412,26413,26414,26415,26416,26417,26418,26419,26420,26421,26422,
-26423,26424,26425,26426,26427,26428,26429,26430,26431,26432,26433,26434,
-26435,26436,26437,26438,26439,26440,26441,26442,26443,26444,26445,26446,
-26447,26448,26449,26450,26451,26452,26453,26454,26455,26456,26457,26458,
-26459,26460,26461,26462,26463,26464,26465,26466,26467,26468,26469,26470,
-26471,26472,26473,26474,26475,26476,26477,26478,26479,26480,26481,26482,
-26483,26484,26485,26486,26487,26488,26489,26490,26491,26492,26493,26494,
-26495,26496,26497,26498,26499,26500,26501,26502,26503,26504,26505,26506,
-26507,26508,26509,26510,26511,26512,26513,26514,26515,26516,26517,26518,
-26519,26520,26521,26522,26523,26524,26525,26526,26527,26528,26529,26530,
-26531,26532,26533,26534,26535,26536,26537,26538,26539,26540,26541,26542,
-26543,26544,26545,26546,26547,26548,26549,26550,26551,26552,26553,26554,
-26555,26556,26557,26558,26559,26560,26561,26562,26563,26564,26565,26566,
-26567,26568,26569,26570,26571,26572,26573,26574,26575,26576,26577,26578,
-26579,26580,26581,26582,26583,26584,26585,26586,26587,26588,26589,26590,
-26591,26592,26593,26594,26595,26596,26597,26598,26599,26600,26601,26602,
-26603,26604,26605,26606,26607,26608,26609,26610,26611,26612,26613,26614,
-26615,26616,26617,26618,26619,26620,26621,26622,26623,26624,26625,26626,
-26627,26628,26629,26630,26631,26632,26633,26634,26635,26636,26637,26638,
-26639,26640,26641,26642,26643,26644,26645,26646,26647,26648,26649,26650,
-26651,26652,26653,26654,26655,26656,26657,26658,26659,26660,26661,26662,
-26663,26664,26665,26666,26667,26668,26669,26670,26671,26672,26673,26674,
-26675,26676,26677,26678,26679,26680,26681,26682,26683,26684,26685,26686,
-26687,26688,26689,26690,26691,26692,26693,26694,26695,26696,26697,26698,
-26699,26700,26701,26702,26703,26704,26705,26706,26707,26708,26709,26710,
-26711,26712,26713,26714,26715,26716,26717,26718,26719,26720,26721,26722,
-26723,26724,26725,26726,26727,26728,26729,26730,26731,26732,26733,26734,
-26735,26736,26737,26738,26739,26740,26741,26742,26743,26744,26745,26746,
-26747,26748,26749,26750,26751,26752,26753,26754,26755,26756,26757,26758,
-26759,26760,26761,26762,26763,26764,26765,26766,26767,26768,26769,26770,
-26771,26772,26773,26774,26775,26776,26777,26778,26779,26780,26781,26782,
-26783,26784,26785,26786,26787,26788,26789,26790,26791,26792,26793,26794,
-26795,26796,26797,26798,26799,26800,26801,26802,26803,26804,26805,26806,
-26807,26808,26809,26810,26811,26812,26813,26814,26815,26816,26817,26818,
-26819,26820,26821,26822,26823,26824,26825,26826,26827,26828,26829,26830,
-26831,26832,26833,26834,26835,26836,26837,26838,26839,26840,26841,26842,
-26843,26844,26845,26846,26847,26848,26849,26850,26851,26852,26853,26854,
-26855,26856,26857,26858,26859,26860,26861,26862,26863,26864,26865,26866,
-26867,26868,26869,26870,26871,26872,26873,26874,26875,26876,26877,26878,
-26879,26880,26881,26882,26883,26884,26885,26886,26887,26888,26889,26890,
-26891,26892,26893,26894,26895,26896,26897,26898,26899,26900,26901,26902,
-26903,26904,26905,26906,26907,26908,26909,26910,26911,26912,26913,26914,
-26915,26916,26917,26918,26919,26920,26921,26922,26923,26924,26925,26926,
-26927,26928,26929,26930,26931,26932,26933,26934,26935,26936,26937,26938,
-26939,26940,26941,26942,26943,26944,26945,26946,26947,26948,26949,26950,
-26951,26952,26953,26954,26955,26956,26957,26958,26959,26960,26961,26962,
-26963,26964,26965,26966,26967,26968,26969,26970,26971,26972,26973,26974,
-26975,26976,26977,26978,26979,26980,26981,26982,26983,26984,26985,26986,
-26987,26988,26989,26990,26991,26992,26993,26994,26995,26996,26997,26998,
-26999,27000,27001,27002,27003,27004,27005,27006,27007,27008,27009,27010,
-27011,27012,27013,27014,27015,27016,27017,27018,27019,27020,27021,27022,
-27023,27024,27025,27026,27027,27028,27029,27030,27031,27032,27033,27034,
-27035,27036,27037,27038,27039,27040,27041,27042,27043,27044,27045,27046,
-27047,27048,27049,27050,27051,27052,27053,27054,27055,27056,27057,27058,
-27059,27060,27061,27062,27063,27064,27065,27066,27067,27068,27069,27070,
-27071,27072,27073,27074,27075,27076,27077,27078,27079,27080,27081,27082,
-27083,27084,27085,27086,27087,27088,27089,27090,27091,27092,27093,27094,
-27095,27096,27097,27098,27099,27100,27101,27102,27103,27104,27105,27106,
-27107,27108,27109,27110,27111,27112,27113,27114,27115,27116,27117,27118,
-27119,27120,27121,27122,27123,27124,27125,27126,27127,27128,27129,27130,
-27131,27132,27133,27134,27135,27136,27137,27138,27139,27140,27141,27142,
-27143,27144,27145,27146,27147,27148,27149,27150,27151,27152,27153,27154,
-27155,27156,27157,27158,27159,27160,27161,27162,27163,27164,27165,27166,
-27167,27168,27169,27170,27171,27172,27173,27174,27175,27176,27177,27178,
-27179,27180,27181,27182,27183,27184,27185,27186,27187,27188,27189,27190,
-27191,27192,27193,27194,27195,27196,27197,27198,27199,27200,27201,27202,
-27203,27204,27205,27206,27207,27208,27209,27210,27211,27212,27213,27214,
-27215,27216,27217,27218,27219,27220,27221,27222,27223,27224,27225,27226,
-27227,27228,27229,27230,27231,27232,27233,27234,27235,27236,27237,27238,
-27239,27240,27241,27242,27243,27244,27245,27246,27247,27248,27249,27250,
-27251,27252,27253,27254,27255,27256,27257,27258,27259,27260,27261,27262,
-27263,27264,27265,27266,27267,27268,27269,27270,27271,27272,27273,27274,
-27275,27276,27277,27278,27279,27280,27281,27282,27283,27284,27285,27286,
-27287,27288,27289,27290,27291,27292,27293,27294,27295,27296,27297,27298,
-27299,27300,27301,27302,27303,27304,27305,27306,27307,27308,27309,27310,
-27311,27312,27313,27314,27315,27316,27317,27318,27319,27320,27321,27322,
-27323,27324,27325,27326,27327,27328,27329,27330,27331,27332,27333,27334,
-27335,27336,27337,27338,27339,27340,27341,27342,27343,27344,27345,27346,
-27347,27348,27349,27350,27351,27352,27353,27354,27355,27356,27357,27358,
-27359,27360,27361,27362,27363,27364,27365,27366,27367,27368,27369,27370,
-27371,27372,27373,27374,27375,27376,27377,27378,27379,27380,27381,27382,
-27383,27384,27385,27386,27387,27388,27389,27390,27391,27392,27393,27394,
-27395,27396,27397,27398,27399,27400,27401,27402,27403,27404,27405,27406,
-27407,27408,27409,27410,27411,27412,27413,27414,27415,27416,27417,27418,
-27419,27420,27421,27422,27423,27424,27425,27426,27427,27428,27429,27430,
-27431,27432,27433,27434,27435,27436,27437,27438,27439,27440,27441,27442,
-27443,27444,27445,27446,27447,27448,27449,27450,27451,27452,27453,27454,
-27455,27456,27457,27458,27459,27460,27461,27462,27463,27464,27465,27466,
-27467,27468,27469,27470,27471,27472,27473,27474,27475,27476,27477,27478,
-27479,27480,27481,27482,27483,27484,27485,27486,27487,27488,27489,27490,
-27491,27492,27493,27494,27495,27496,27497,27498,27499,27500,27501,27502,
-27503,27504,27505,27506,27507,27508,27509,27510,27511,27512,27513,27514,
-27515,27516,27517,27518,27519,27520,27521,27522,27523,27524,27525,27526,
-27527,27528,27529,27530,27531,27532,27533,27534,27535,27536,27537,27538,
-27539,27540,27541,27542,27543,27544,27545,27546,27547,27548,27549,27550,
-27551,27552,27553,27554,27555,27556,27557,27558,27559,27560,27561,27562,
-27563,27564,27565,27566,27567,27568,27569,27570,27571,27572,27573,27574,
-27575,27576,27577,27578,27579,27580,27581,27582,27583,27584,27585,27586,
-27587,27588,27589,27590,27591,27592,27593,27594,27595,27596,27597,27598,
-27599,27600,27601,27602,27603,27604,27605,27606,27607,27608,27609,27610,
-27611,27612,27613,27614,27615,27616,27617,27618,27619,27620,27621,27622,
-27623,27624,27625,27626,27627,27628,27629,27630,27631,27632,27633,27634,
-27635,27636,27637,27638,27639,27640,27641,27642,27643,27644,27645,27646,
-27647,27648,27649,27650,27651,27652,27653,27654,27655,27656,27657,27658,
-27659,27660,27661,27662,27663,27664,27665,27666,27667,27668,27669,27670,
-27671,27672,27673,27674,27675,27676,27677,27678,27679,27680,27681,27682,
-27683,27684,27685,27686,27687,27688,27689,27690,27691,27692,27693,27694,
-27695,27696,27697,27698,27699,27700,27701,27702,27703,27704,27705,27706,
-27707,27708,27709,27710,27711,27712,27713,27714,27715,27716,27717,27718,
-27719,27720,27721,27722,27723,27724,27725,27726,27727,27728,27729,27730,
-27731,27732,27733,27734,27735,27736,27737,27738,27739,27740,27741,27742,
-27743,27744,27745,27746,27747,27748,27749,27750,27751,27752,27753,27754,
-27755,27756,27757,27758,27759,27760,27761,27762,27763,27764,27765,27766,
-27767,27768,27769,27770,27771,27772,27773,27774,27775,27776,27777,27778,
-27779,27780,27781,27782,27783,27784,27785,27786,27787,27788,27789,27790,
-27791,27792,27793,27794,27795,27796,27797,27798,27799,27800,27801,27802,
-27803,27804,27805,27806,27807,27808,27809,27810,27811,27812,27813,27814,
-27815,27816,27817,27818,27819,27820,27821,27822,27823,27824,27825,27826,
-27827,27828,27829,27830,27831,27832,27833,27834,27835,27836,27837,27838,
-27839,27840,27841,27842,27843,27844,27845,27846,27847,27848,27849,27850,
-27851,27852,27853,27854,27855,27856,27857,27858,27859,27860,27861,27862,
-27863,27864,27865,27866,27867,27868,27869,27870,27871,27872,27873,27874,
-27875,27876,27877,27878,27879,27880,27881,27882,27883,27884,27885,27886,
-27887,27888,27889,27890,27891,27892,27893,27894,27895,27896,27897,27898,
-27899,27900,27901,27902,27903,27904,27905,27906,27907,27908,27909,27910,
-27911,27912,27913,27914,27915,27916,27917,27918,27919,27920,27921,27922,
-27923,27924,27925,27926,27927,27928,27929,27930,27931,27932,27933,27934,
-27935,27936,27937,27938,27939,27940,27941,27942,27943,27944,27945,27946,
-27947,27948,27949,27950,27951,27952,27953,27954,27955,27956,27957,27958,
-27959,27960,27961,27962,27963,27964,27965,27966,27967,27968,27969,27970,
-27971,27972,27973,27974,27975,27976,27977,27978,27979,27980,27981,27982,
-27983,27984,27985,27986,27987,27988,27989,27990,27991,27992,27993,27994,
-27995,27996,27997,27998,27999,28000,28001,28002,28003,28004,28005,28006,
-28007,28008,28009,28010,28011,28012,28013,28014,28015,28016,28017,28018,
-28019,28020,28021,28022,28023,28024,28025,28026,28027,28028,28029,28030,
-28031,28032,28033,28034,28035,28036,28037,28038,28039,28040,28041,28042,
-28043,28044,28045,28046,28047,28048,28049,28050,28051,28052,28053,28054,
-28055,28056,28057,28058,28059,28060,28061,28062,28063,28064,28065,28066,
-28067,28068,28069,28070,28071,28072,28073,28074,28075,28076,28077,28078,
-28079,28080,28081,28082,28083,28084,28085,28086,28087,28088,28089,28090,
-28091,28092,28093,28094,28095,28096,28097,28098,28099,28100,28101,28102,
-28103,28104,28105,28106,28107,28108,28109,28110,28111,28112,28113,28114,
-28115,28116,28117,28118,28119,28120,28121,28122,28123,28124,28125,28126,
-28127,28128,28129,28130,28131,28132,28133,28134,28135,28136,28137,28138,
-28139,28140,28141,28142,28143,28144,28145,28146,28147,28148,28149,28150,
-28151,28152,28153,28154,28155,28156,28157,28158,28159,28160,28161,28162,
-28163,28164,28165,28166,28167,28168,28169,28170,28171,28172,28173,28174,
-28175,28176,28177,28178,28179,28180,28181,28182,28183,28184,28185,28186,
-28187,28188,28189,28190,28191,28192,28193,28194,28195,28196,28197,28198,
-28199,28200,28201,28202,28203,28204,28205,28206,28207,28208,28209,28210,
-28211,28212,28213,28214,28215,28216,28217,28218,28219,28220,28221,28222,
-28223,28224,28225,28226,28227,28228,28229,28230,28231,28232,28233,28234,
-28235,28236,28237,28238,28239,28240,28241,28242,28243,28244,28245,28246,
-28247,28248,28249,28250,28251,28252,28253,28254,28255,28256,28257,28258,
-28259,28260,28261,28262,28263,28264,28265,28266,28267,28268,28269,28270,
-28271,28272,28273,28274,28275,28276,28277,28278,28279,28280,28281,28282,
-28283,28284,28285,28286,28287,28288,28289,28290,28291,28292,28293,28294,
-28295,28296,28297,28298,28299,28300,28301,28302,28303,28304,28305,28306,
-28307,28308,28309,28310,28311,28312,28313,28314,28315,28316,28317,28318,
-28319,28320,28321,28322,28323,28324,28325,28326,28327,28328,28329,28330,
-28331,28332,28333,28334,28335,28336,28337,28338,28339,28340,28341,28342,
-28343,28344,28345,28346,28347,28348,28349,28350,28351,28352,28353,28354,
-28355,28356,28357,28358,28359,28360,28361,28362,28363,28364,28365,28366,
-28367,28368,28369,28370,28371,28372,28373,28374,28375,28376,28377,28378,
-28379,28380,28381,28382,28383,28384,28385,28386,28387,28388,28389,28390,
-28391,28392,28393,28394,28395,28396,28397,28398,28399,28400,28401,28402,
-28403,28404,28405,28406,28407,28408,28409,28410,28411,28412,28413,28414,
-28415,28416,28417,28418,28419,28420,28421,28422,28423,28424,28425,28426,
-28427,28428,28429,28430,28431,28432,28433,28434,28435,28436,28437,28438,
-28439,28440,28441,28442,28443,28444,28445,28446,28447,28448,28449,28450,
-28451,28452,28453,28454,28455,28456,28457,28458,28459,28460,28461,28462,
-28463,28464,28465,28466,28467,28468,28469,28470,28471,28472,28473,28474,
-28475,28476,28477,28478,28479,28480,28481,28482,28483,28484,28485,28486,
-28487,28488,28489,28490,28491,28492,28493,28494,28495,28496,28497,28498,
-28499,28500,28501,28502,28503,28504,28505,28506,28507,28508,28509,28510,
-28511,28512,28513,28514,28515,28516,28517,28518,28519,28520,28521,28522,
-28523,28524,28525,28526,28527,28528,28529,28530,28531,28532,28533,28534,
-28535,28536,28537,28538,28539,28540,28541,28542,28543,28544,28545,28546,
-28547,28548,28549,28550,28551,28552,28553,28554,28555,28556,28557,28558,
-28559,28560,28561,28562,28563,28564,28565,28566,28567,28568,28569,28570,
-28571,28572,28573,28574,28575,28576,28577,28578,28579,28580,28581,28582,
-28583,28584,28585,28586,28587,28588,28589,28590,28591,28592,28593,28594,
-28595,28596,28597,28598,28599,28600,28601,28602,28603,28604,28605,28606,
-28607,28608,28609,28610,28611,28612,28613,28614,28615,28616,28617,28618,
-28619,28620,28621,28622,28623,28624,28625,28626,28627,28628,28629,28630,
-28631,28632,28633,28634,28635,28636,28637,28638,28639,28640,28641,28642,
-28643,28644,28645,28646,28647,28648,28649,28650,28651,28652,28653,28654,
-28655,28656,28657,28658,28659,28660,28661,28662,28663,28664,28665,28666,
-28667,28668,28669,28670,28671,28672,28673,28674,28675,28676,28677,28678,
-28679,28680,28681,28682,28683,28684,28685,28686,28687,28688,28689,28690,
-28691,28692,28693,28694,28695,28696,28697,28698,28699,28700,28701,28702,
-28703,28704,28705,28706,28707,28708,28709,28710,28711,28712,28713,28714,
-28715,28716,28717,28718,28719,28720,28721,28722,28723,28724,28725,28726,
-28727,28728,28729,28730,28731,28732,28733,28734,28735,28736,28737,28738,
-28739,28740,28741,28742,28743,28744,28745,28746,28747,28748,28749,28750,
-28751,28752,28753,28754,28755,28756,28757,28758,28759,28760,28761,28762,
-28763,28764,28765,28766,28767,28768,28769,28770,28771,28772,28773,28774,
-28775,28776,28777,28778,28779,28780,28781,28782,28783,28784,28785,28786,
-28787,28788,28789,28790,28791,28792,28793,28794,28795,28796,28797,28798,
-28799,28800,28801,28802,28803,28804,28805,28806,28807,28808,28809,28810,
-28811,28812,28813,28814,28815,28816,28817,28818,28819,28820,28821,28822,
-28823,28824,28825,28826,28827,28828,28829,28830,28831,28832,28833,28834,
-28835,28836,28837,28838,28839,28840,28841,28842,28843,28844,28845,28846,
-28847,28848,28849,28850,28851,28852,28853,28854,28855,28856,28857,28858,
-28859,28860,28861,28862,28863,28864,28865,28866,28867,28868,28869,28870,
-28871,28872,28873,28874,28875,28876,28877,28878,28879,28880,28881,28882,
-28883,28884,28885,28886,28887,28888,28889,28890,28891,28892,28893,28894,
-28895,28896,28897,28898,28899,28900,28901,28902,28903,28904,28905,28906,
-28907,28908,28909,28910,28911,28912,28913,28914,28915,28916,28917,28918,
-28919,28920,28921,28922,28923,28924,28925,28926,28927,28928,28929,28930,
-28931,28932,28933,28934,28935,28936,28937,28938,28939,28940,28941,28942,
-28943,28944,28945,28946,28947,28948,28949,28950,28951,28952,28953,28954,
-28955,28956,28957,28958,28959,28960,28961,28962,28963,28964,28965,28966,
-28967,28968,28969,28970,28971,28972,28973,28974,28975,28976,28977,28978,
-28979,28980,28981,28982,28983,28984,28985,28986,28987,28988,28989,28990,
-28991,28992,28993,28994,28995,28996,28997,28998,28999,29000,29001,29002,
-29003,29004,29005,29006,29007,29008,29009,29010,29011,29012,29013,29014,
-29015,29016,29017,29018,29019,29020,29021,29022,29023,29024,29025,29026,
-29027,29028,29029,29030,29031,29032,29033,29034,29035,29036,29037,29038,
-29039,29040,29041,29042,29043,29044,29045,29046,29047,29048,29049,29050,
-29051,29052,29053,29054,29055,29056,29057,29058,29059,29060,29061,29062,
-29063,29064,29065,29066,29067,29068,29069,29070,29071,29072,29073,29074,
-29075,29076,29077,29078,29079,29080,29081,29082,29083,29084,29085,29086,
-29087,29088,29089,29090,29091,29092,29093,29094,29095,29096,29097,29098,
-29099,29100,29101,29102,29103,29104,29105,29106,29107,29108,29109,29110,
-29111,29112,29113,29114,29115,29116,29117,29118,29119,29120,29121,29122,
-29123,29124,29125,29126,29127,29128,29129,29130,29131,29132,29133,29134,
-29135,29136,29137,29138,29139,29140,29141,29142,29143,29144,29145,29146,
-29147,29148,29149,29150,29151,29152,29153,29154,29155,29156,29157,29158,
-29159,29160,29161,29162,29163,29164,29165,29166,29167,29168,29169,29170,
-29171,29172,29173,29174,29175,29176,29177,29178,29179,29180,29181,29182,
-29183,29184,29185,29186,29187,29188,29189,29190,29191,29192,29193,29194,
-29195,29196,29197,29198,29199,29200,29201,29202,29203,29204,29205,29206,
-29207,29208,29209,29210,29211,29212,29213,29214,29215,29216,29217,29218,
-29219,29220,29221,29222,29223,29224,29225,29226,29227,29228,29229,29230,
-29231,29232,29233,29234,29235,29236,29237,29238,29239,29240,29241,29242,
-29243,29244,29245,29246,29247,29248,29249,29250,29251,29252,29253,29254,
-29255,29256,29257,29258,29259,29260,29261,29262,29263,29264,29265,29266,
-29267,29268,29269,29270,29271,29272,29273,29274,29275,29276,29277,29278,
-29279,29280,29281,29282,29283,29284,29285,29286,29287,29288,29289,29290,
-29291,29292,29293,29294,29295,29296,29297,29298,29299,29300,29301,29302,
-29303,29304,29305,29306,29307,29308,29309,29310,29311,29312,29313,29314,
-29315,29316,29317,29318,29319,29320,29321,29322,29323,29324,29325,29326,
-29327,29328,29329,29330,29331,29332,29333,29334,29335,29336,29337,29338,
-29339,29340,29341,29342,29343,29344,29345,29346,29347,29348,29349,29350,
-29351,29352,29353,29354,29355,29356,29357,29358,29359,29360,29361,29362,
-29363,29364,29365,29366,29367,29368,29369,29370,29371,29372,29373,29374,
-29375,29376,29377,29378,29379,29380,29381,29382,29383,29384,29385,29386,
-29387,29388,29389,29390,29391,29392,29393,29394,29395,29396,29397,29398,
-29399,29400,29401,29402,29403,29404,29405,29406,29407,29408,29409,29410,
-29411,29412,29413,29414,29415,29416,29417,29418,29419,29420,29421,29422,
-29423,29424,29425,29426,29427,29428,29429,29430,29431,29432,29433,29434,
-29435,29436,29437,29438,29439,29440,29441,29442,29443,29444,29445,29446,
-29447,29448,29449,29450,29451,29452,29453,29454,29455,29456,29457,29458,
-29459,29460,29461,29462,29463,29464,29465,29466,29467,29468,29469,29470,
-29471,29472,29473,29474,29475,29476,29477,29478,29479,29480,29481,29482,
-29483,29484,29485,29486,29487,29488,29489,29490,29491,29492,29493,29494,
-29495,29496,29497,29498,29499,29500,29501,29502,29503,29504,29505,29506,
-29507,29508,29509,29510,29511,29512,29513,29514,29515,29516,29517,29518,
-29519,29520,29521,29522,29523,29524,29525,29526,29527,29528,29529,29530,
-29531,29532,29533,29534,29535,29536,29537,29538,29539,29540,29541,29542,
-29543,29544,29545,29546,29547,29548,29549,29550,29551,29552,29553,29554,
-29555,29556,29557,29558,29559,29560,29561,29562,29563,29564,29565,29566,
-29567,29568,29569,29570,29571,29572,29573,29574,29575,29576,29577,29578,
-29579,29580,29581,29582,29583,29584,29585,29586,29587,29588,29589,29590,
-29591,29592,29593,29594,29595,29596,29597,29598,29599,29600,29601,29602,
-29603,29604,29605,29606,29607,29608,29609,29610,29611,29612,29613,29614,
-29615,29616,29617,29618,29619,29620,29621,29622,29623,29624,29625,29626,
-29627,29628,29629,29630,29631,29632,29633,29634,29635,29636,29637,29638,
-29639,29640,29641,29642,29643,29644,29645,29646,29647,29648,29649,29650,
-29651,29652,29653,29654,29655,29656,29657,29658,29659,29660,29661,29662,
-29663,29664,29665,29666,29667,29668,29669,29670,29671,29672,29673,29674,
-29675,29676,29677,29678,29679,29680,29681,29682,29683,29684,29685,29686,
-29687,29688,29689,29690,29691,29692,29693,29694,29695,29696,29697,29698,
-29699,29700,29701,29702,29703,29704,29705,29706,29707,29708,29709,29710,
-29711,29712,29713,29714,29715,29716,29717,29718,29719,29720,29721,29722,
-29723,29724,29725,29726,29727,29728,29729,29730,29731,29732,29733,29734,
-29735,29736,29737,29738,29739,29740,29741,29742,29743,29744,29745,29746,
-29747,29748,29749,29750,29751,29752,29753,29754,29755,29756,29757,29758,
-29759,29760,29761,29762,29763,29764,29765,29766,29767,29768,29769,29770,
-29771,29772,29773,29774,29775,29776,29777,29778,29779,29780,29781,29782,
-29783,29784,29785,29786,29787,29788,29789,29790,29791,29792,29793,29794,
-29795,29796,29797,29798,29799,29800,29801,29802,29803,29804,29805,29806,
-29807,29808,29809,29810,29811,29812,29813,29814,29815,29816,29817,29818,
-29819,29820,29821,29822,29823,29824,29825,29826,29827,29828,29829,29830,
-29831,29832,29833,29834,29835,29836,29837,29838,29839,29840,29841,29842,
-29843,29844,29845,29846,29847,29848,29849,29850,29851,29852,29853,29854,
-29855,29856,29857,29858,29859,29860,29861,29862,29863,29864,29865,29866,
-29867,29868,29869,29870,29871,29872,29873,29874,29875,29876,29877,29878,
-29879,29880,29881,29882,29883,29884,29885,29886,29887,29888,29889,29890,
-29891,29892,29893,29894,29895,29896,29897,29898,29899,29900,29901,29902,
-29903,29904,29905,29906,29907,29908,29909,29910,29911,29912,29913,29914,
-29915,29916,29917,29918,29919,29920,29921,29922,29923,29924,29925,29926,
-29927,29928,29929,29930,29931,29932,29933,29934,29935,29936,29937,29938,
-29939,29940,29941,29942,29943,29944,29945,29946,29947,29948,29949,29950,
-29951,29952,29953,29954,29955,29956,29957,29958,29959,29960,29961,29962,
-29963,29964,29965,29966,29967,29968,29969,29970,29971,29972,29973,29974,
-29975,29976,29977,29978,29979,29980,29981,29982,29983,29984,29985,29986,
-29987,29988,29989,29990,29991,29992,29993,29994,29995,29996,29997,29998,
-29999,30000,30001,30002,30003,30004,30005,30006,30007,30008,30009,30010,
-30011,30012,30013,30014,30015,30016,30017,30018,30019,30020,30021,30022,
-30023,30024,30025,30026,30027,30028,30029,30030,30031,30032,30033,30034,
-30035,30036,30037,30038,30039,30040,30041,30042,30043,30044,30045,30046,
-30047,30048,30049,30050,30051,30052,30053,30054,30055,30056,30057,30058,
-30059,30060,30061,30062,30063,30064,30065,30066,30067,30068,30069,30070,
-30071,30072,30073,30074,30075,30076,30077,30078,30079,30080,30081,30082,
-30083,30084,30085,30086,30087,30088,30089,30090,30091,30092,30093,30094,
-30095,30096,30097,30098,30099,30100,30101,30102,30103,30104,30105,30106,
-30107,30108,30109,30110,30111,30112,30113,30114,30115,30116,30117,30118,
-30119,30120,30121,30122,30123,30124,30125,30126,30127,30128,30129,30130,
-30131,30132,30133,30134,30135,30136,30137,30138,30139,30140,30141,30142,
-30143,30144,30145,30146,30147,30148,30149,30150,30151,30152,30153,30154,
-30155,30156,30157,30158,30159,30160,30161,30162,30163,30164,30165,30166,
-30167,30168,30169,30170,30171,30172,30173,30174,30175,30176,30177,30178,
-30179,30180,30181,30182,30183,30184,30185,30186,30187,30188,30189,30190,
-30191,30192,30193,30194,30195,30196,30197,30198,30199,30200,30201,30202,
-30203,30204,30205,30206,30207,30208,30209,30210,30211,30212,30213,30214,
-30215,30216,30217,30218,30219,30220,30221,30222,30223,30224,30225,30226,
-30227,30228,30229,30230,30231,30232,30233,30234,30235,30236,30237,30238,
-30239,30240,30241,30242,30243,30244,30245,30246,30247,30248,30249,30250,
-30251,30252,30253,30254,30255,30256,30257,30258,30259,30260,30261,30262,
-30263,30264,30265,30266,30267,30268,30269,30270,30271,30272,30273,30274,
-30275,30276,30277,30278,30279,30280,30281,30282,30283,30284,30285,30286,
-30287,30288,30289,30290,30291,30292,30293,30294,30295,30296,30297,30298,
-30299,30300,30301,30302,30303,30304,30305,30306,30307,30308,30309,30310,
-30311,30312,30313,30314,30315,30316,30317,30318,30319,30320,30321,30322,
-30323,30324,30325,30326,30327,30328,30329,30330,30331,30332,30333,30334,
-30335,30336,30337,30338,30339,30340,30341,30342,30343,30344,30345,30346,
-30347,30348,30349,30350,30351,30352,30353,30354,30355,30356,30357,30358,
-30359,30360,30361,30362,30363,30364,30365,30366,30367,30368,30369,30370,
-30371,30372,30373,30374,30375,30376,30377,30378,30379,30380,30381,30382,
-30383,30384,30385,30386,30387,30388,30389,30390,30391,30392,30393,30394,
-30395,30396,30397,30398,30399,30400,30401,30402,30403,30404,30405,30406,
-30407,30408,30409,30410,30411,30412,30413,30414,30415,30416,30417,30418,
-30419,30420,30421,30422,30423,30424,30425,30426,30427,30428,30429,30430,
-30431,30432,30433,30434,30435,30436,30437,30438,30439,30440,30441,30442,
-30443,30444,30445,30446,30447,30448,30449,30450,30451,30452,30453,30454,
-30455,30456,30457,30458,30459,30460,30461,30462,30463,30464,30465,30466,
-30467,30468,30469,30470,30471,30472,30473,30474,30475,30476,30477,30478,
-30479,30480,30481,30482,30483,30484,30485,30486,30487,30488,30489,30490,
-30491,30492,30493,30494,30495,30496,30497,30498,30499,30500,30501,30502,
-30503,30504,30505,30506,30507,30508,30509,30510,30511,30512,30513,30514,
-30515,30516,30517,30518,30519,30520,30521,30522,30523,30524,30525,30526,
-30527,30528,30529,30530,30531,30532,30533,30534,30535,30536,30537,30538,
-30539,30540,30541,30542,30543,30544,30545,30546,30547,30548,30549,30550,
-30551,30552,30553,30554,30555,30556,30557,30558,30559,30560,30561,30562,
-30563,30564,30565,30566,30567,30568,30569,30570,30571,30572,30573,30574,
-30575,30576,30577,30578,30579,30580,30581,30582,30583,30584,30585,30586,
-30587,30588,30589,30590,30591,30592,30593,30594,30595,30596,30597,30598,
-30599,30600,30601,30602,30603,30604,30605,30606,30607,30608,30609,30610,
-30611,30612,30613,30614,30615,30616,30617,30618,30619,30620,30621,30622,
-30623,30624,30625,30626,30627,30628,30629,30630,30631,30632,30633,30634,
-30635,30636,30637,30638,30639,30640,30641,30642,30643,30644,30645,30646,
-30647,30648,30649,30650,30651,30652,30653,30654,30655,30656,30657,30658,
-30659,30660,30661,30662,30663,30664,30665,30666,30667,30668,30669,30670,
-30671,30672,30673,30674,30675,30676,30677,30678,30679,30680,30681,30682,
-30683,30684,30685,30686,30687,30688,30689,30690,30691,30692,30693,30694,
-30695,30696,30697,30698,30699,30700,30701,30702,30703,30704,30705,30706,
-30707,30708,30709,30710,30711,30712,30713,30714,30715,30716,30717,30718,
-30719,30720,30721,30722,30723,30724,30725,30726,30727,30728,30729,30730,
-30731,30732,30733,30734,30735,30736,30737,30738,30739,30740,30741,30742,
-30743,30744,30745,30746,30747,30748,30749,30750,30751,30752,30753,30754,
-30755,30756,30757,30758,30759,30760,30761,30762,30763,30764,30765,30766,
-30767,30768,30769,30770,30771,30772,30773,30774,30775,30776,30777,30778,
-30779,30780,30781,30782,30783,30784,30785,30786,30787,30788,30789,30790,
-30791,30792,30793,30794,30795,30796,30797,30798,30799,30800,30801,30802,
-30803,30804,30805,30806,30807,30808,30809,30810,30811,30812,30813,30814,
-30815,30816,30817,30818,30819,30820,30821,30822,30823,30824,30825,30826,
-30827,30828,30829,30830,30831,30832,30833,30834,30835,30836,30837,30838,
-30839,30840,30841,30842,30843,30844,30845,30846,30847,30848,30849,30850,
-30851,30852,30853,30854,30855,30856,30857,30858,30859,30860,30861,30862,
-30863,30864,30865,30866,30867,30868,30869,30870,30871,30872,30873,30874,
-30875,30876,30877,30878,30879,30880,30881,30882,30883,30884,30885,30886,
-30887,30888,30889,30890,30891,30892,30893,30894,30895,30896,30897,30898,
-30899,30900,30901,30902,30903,30904,30905,30906,30907,30908,30909,30910,
-30911,30912,30913,30914,30915,30916,30917,30918,30919,30920,30921,30922,
-30923,30924,30925,30926,30927,30928,30929,30930,30931,30932,30933,30934,
-30935,30936,30937,30938,30939,30940,30941,30942,30943,30944,30945,30946,
-30947,30948,30949,30950,30951,30952,30953,30954,30955,30956,30957,30958,
-30959,30960,30961,30962,30963,30964,30965,30966,30967,30968,30969,30970,
-30971,30972,30973,30974,30975,30976,30977,30978,30979,30980,30981,30982,
-30983,30984,30985,30986,30987,30988,30989,30990,30991,30992,30993,30994,
-30995,30996,30997,30998,30999,31000,31001,31002,31003,31004,31005,31006,
-31007,31008,31009,31010,31011,31012,31013,31014,31015,31016,31017,31018,
-31019,31020,31021,31022,31023,31024,31025,31026,31027,31028,31029,31030,
-31031,31032,31033,31034,31035,31036,31037,31038,31039,31040,31041,31042,
-31043,31044,31045,31046,31047,31048,31049,31050,31051,31052,31053,31054,
-31055,31056,31057,31058,31059,31060,31061,31062,31063,31064,31065,31066,
-31067,31068,31069,31070,31071,31072,31073,31074,31075,31076,31077,31078,
-31079,31080,31081,31082,31083,31084,31085,31086,31087,31088,31089,31090,
-31091,31092,31093,31094,31095,31096,31097,31098,31099,31100,31101,31102,
-31103,31104,31105,31106,31107,31108,31109,31110,31111,31112,31113,31114,
-31115,31116,31117,31118,31119,31120,31121,31122,31123,31124,31125,31126,
-31127,31128,31129,31130,31131,31132,31133,31134,31135,31136,31137,31138,
-31139,31140,31141,31142,31143,31144,31145,31146,31147,31148,31149,31150,
-31151,31152,31153,31154,31155,31156,31157,31158,31159,31160,31161,31162,
-31163,31164,31165,31166,31167,31168,31169,31170,31171,31172,31173,31174,
-31175,31176,31177,31178,31179,31180,31181,31182,31183,31184,31185,31186,
-31187,31188,31189,31190,31191,31192,31193,31194,31195,31196,31197,31198,
-31199,31200,31201,31202,31203,31204,31205,31206,31207,31208,31209,31210,
-31211,31212,31213,31214,31215,31216,31217,31218,31219,31220,31221,31222,
-31223,31224,31225,31226,31227,31228,31229,31230,31231,31232,31233,31234,
-31235,31236,31237,31238,31239,31240,31241,31242,31243,31244,31245,31246,
-31247,31248,31249,31250,31251,31252,31253,31254,31255,31256,31257,31258,
-31259,31260,31261,31262,31263,31264,31265,31266,31267,31268,31269,31270,
-31271,31272,31273,31274,31275,31276,31277,31278,31279,31280,31281,31282,
-31283,31284,31285,31286,31287,31288,31289,31290,31291,31292,31293,31294,
-31295,31296,31297,31298,31299,31300,31301,31302,31303,31304,31305,31306,
-31307,31308,31309,31310,31311,31312,31313,31314,31315,31316,31317,31318,
-31319,31320,31321,31322,31323,31324,31325,31326,31327,31328,31329,31330,
-31331,31332,31333,31334,31335,31336,31337,31338,31339,31340,31341,31342,
-31343,31344,31345,31346,31347,31348,31349,31350,31351,31352,31353,31354,
-31355,31356,31357,31358,31359,31360,31361,31362,31363,31364,31365,31366,
-31367,31368,31369,31370,31371,31372,31373,31374,31375,31376,31377,31378,
-31379,31380,31381,31382,31383,31384,31385,31386,31387,31388,31389,31390,
-31391,31392,31393,31394,31395,31396,31397,31398,31399,31400,31401,31402,
-31403,31404,31405,31406,31407,31408,31409,31410,31411,31412,31413,31414,
-31415,31416,31417,31418,31419,31420,31421,31422,31423,31424,31425,31426,
-31427,31428,31429,31430,31431,31432,31433,31434,31435,31436,31437,31438,
-31439,31440,31441,31442,31443,31444,31445,31446,31447,31448,31449,31450,
-31451,31452,31453,31454,31455,31456,31457,31458,31459,31460,31461,31462,
-31463,31464,31465,31466,31467,31468,31469,31470,31471,31472,31473,31474,
-31475,31476,31477,31478,31479,31480,31481,31482,31483,31484,31485,31486,
-31487,31488,31489,31490,31491,31492,31493,31494,31495,31496,31497,31498,
-31499,31500,31501,31502,31503,31504,31505,31506,31507,31508,31509,31510,
-31511,31512,31513,31514,31515,31516,31517,31518,31519,31520,31521,31522,
-31523,31524,31525,31526,31527,31528,31529,31530,31531,31532,31533,31534,
-31535,31536,31537,31538,31539,31540,31541,31542,31543,31544,31545,31546,
-31547,31548,31549,31550,31551,31552,31553,31554,31555,31556,31557,31558,
-31559,31560,31561,31562,31563,31564,31565,31566,31567,31568,31569,31570,
-31571,31572,31573,31574,31575,31576,31577,31578,31579,31580,31581,31582,
-31583,31584,31585,31586,31587,31588,31589,31590,31591,31592,31593,31594,
-31595,31596,31597,31598,31599,31600,31601,31602,31603,31604,31605,31606,
-31607,31608,31609,31610,31611,31612,31613,31614,31615,31616,31617,31618,
-31619,31620,31621,31622,31623,31624,31625,31626,31627,31628,31629,31630,
-31631,31632,31633,31634,31635,31636,31637,31638,31639,31640,31641,31642,
-31643,31644,31645,31646,31647,31648,31649,31650,31651,31652,31653,31654,
-31655,31656,31657,31658,31659,31660,31661,31662,31663,31664,31665,31666,
-31667,31668,31669,31670,31671,31672,31673,31674,31675,31676,31677,31678,
-31679,31680,31681,31682,31683,31684,31685,31686,31687,31688,31689,31690,
-31691,31692,31693,31694,31695,31696,31697,31698,31699,31700,31701,31702,
-31703,31704,31705,31706,31707,31708,31709,31710,31711,31712,31713,31714,
-31715,31716,31717,31718,31719,31720,31721,31722,31723,31724,31725,31726,
-31727,31728,31729,31730,31731,31732,31733,31734,31735,31736,31737,31738,
-31739,31740,31741,31742,31743,31744,31745,31746,31747,31748,31749,31750,
-31751,31752,31753,31754,31755,31756,31757,31758,31759,31760,31761,31762,
-31763,31764,31765,31766,31767,31768,31769,31770,31771,31772,31773,31774,
-31775,31776,31777,31778,31779,31780,31781,31782,31783,31784,31785,31786,
-31787,31788,31789,31790,31791,31792,31793,31794,31795,31796,31797,31798,
-31799,31800,31801,31802,31803,31804,31805,31806,31807,31808,31809,31810,
-31811,31812,31813,31814,31815,31816,31817,31818,31819,31820,31821,31822,
-31823,31824,31825,31826,31827,31828,31829,31830,31831,31832,31833,31834,
-31835,31836,31837,31838,31839,31840,31841,31842,31843,31844,31845,31846,
-31847,31848,31849,31850,31851,31852,31853,31854,31855,31856,31857,31858,
-31859,31860,31861,31862,31863,31864,31865,31866,31867,31868,31869,31870,
-31871,31872,31873,31874,31875,31876,31877,31878,31879,31880,31881,31882,
-31883,31884,31885,31886,31887,31888,31889,31890,31891,31892,31893,31894,
-31895,31896,31897,31898,31899,31900,31901,31902,31903,31904,31905,31906,
-31907,31908,31909,31910,31911,31912,31913,31914,31915,31916,31917,31918,
-31919,31920,31921,31922,31923,31924,31925,31926,31927,31928,31929,31930,
-31931,31932,31933,31934,31935,31936,31937,31938,31939,31940,31941,31942,
-31943,31944,31945,31946,31947,31948,31949,31950,31951,31952,31953,31954,
-31955,31956,31957,31958,31959,31960,31961,31962,31963,31964,31965,31966,
-31967,31968,31969,31970,31971,31972,31973,31974,31975,31976,31977,31978,
-31979,31980,31981,31982,31983,31984,31985,31986,31987,31988,31989,31990,
-31991,31992,31993,31994,31995,31996,31997,31998,31999,32000,32001,32002,
-32003,32004,32005,32006,32007,32008,32009,32010,32011,32012,32013,32014,
-32015,32016,32017,32018,32019,32020,32021,32022,32023,32024,32025,32026,
-32027,32028,32029,32030,32031,32032,32033,32034,32035,32036,32037,32038,
-32039,32040,32041,32042,32043,32044,32045,32046,32047,32048,32049,32050,
-32051,32052,32053,32054,32055,32056,32057,32058,32059,32060,32061,32062,
-32063,32064,32065,32066,32067,32068,32069,32070,32071,32072,32073,32074,
-32075,32076,32077,32078,32079,32080,32081,32082,32083,32084,32085,32086,
-32087,32088,32089,32090,32091,32092,32093,32094,32095,32096,32097,32098,
-32099,32100,32101,32102,32103,32104,32105,32106,32107,32108,32109,32110,
-32111,32112,32113,32114,32115,32116,32117,32118,32119,32120,32121,32122,
-32123,32124,32125,32126,32127,32128,32129,32130,32131,32132,32133,32134,
-32135,32136,32137,32138,32139,32140,32141,32142,32143,32144,32145,32146,
-32147,32148,32149,32150,32151,32152,32153,32154,32155,32156,32157,32158,
-32159,32160,32161,32162,32163,32164,32165,32166,32167,32168,32169,32170,
-32171,32172,32173,32174,32175,32176,32177,32178,32179,32180,32181,32182,
-32183,32184,32185,32186,32187,32188,32189,32190,32191,32192,32193,32194,
-32195,32196,32197,32198,32199,32200,32201,32202,32203,32204,32205,32206,
-32207,32208,32209,32210,32211,32212,32213,32214,32215,32216,32217,32218,
-32219,32220,32221,32222,32223,32224,32225,32226,32227,32228,32229,32230,
-32231,32232,32233,32234,32235,32236,32237,32238,32239,32240,32241,32242,
-32243,32244,32245,32246,32247,32248,32249,32250,32251,32252,32253,32254,
-32255,32256,32257,32258,32259,32260,32261,32262,32263,32264,32265,32266,
-32267,32268,32269,32270,32271,32272,32273,32274,32275,32276,32277,32278,
-32279,32280,32281,32282,32283,32284,32285,32286,32287,32288,32289,32290,
-32291,32292,32293,32294,32295,32296,32297,32298,32299,32300,32301,32302,
-32303,32304,32305,32306,32307,32308,32309,32310,32311,32312,32313,32314,
-32315,32316,32317,32318,32319,32320,32321,32322,32323,32324,32325,32326,
-32327,32328,32329,32330,32331,32332,32333,32334,32335,32336,32337,32338,
-32339,32340,32341,32342,32343,32344,32345,32346,32347,32348,32349,32350,
-32351,32352,32353,32354,32355,32356,32357,32358,32359,32360,32361,32362,
-32363,32364,32365,32366,32367,32368,32369,32370,32371,32372,32373,32374,
-32375,32376,32377,32378,32379,32380,32381,32382,32383,32384,32385,32386,
-32387,32388,32389,32390,32391,32392,32393,32394,32395,32396,32397,32398,
-32399,32400,32401,32402,32403,32404,32405,32406,32407,32408,32409,32410,
-32411,32412,32413,32414,32415,32416,32417,32418,32419,32420,32421,32422,
-32423,32424,32425,32426,32427,32428,32429,32430,32431,32432,32433,32434,
-32435,32436,32437,32438,32439,32440,32441,32442,32443,32444,32445,32446,
-32447,32448,32449,32450,32451,32452,32453,32454,32455,32456,32457,32458,
-32459,32460,32461,32462,32463,32464,32465,32466,32467,32468,32469,32470,
-32471,32472,32473,32474,32475,32476,32477,32478,32479,32480,32481,32482,
-32483,32484,32485,32486,32487,32488,32489,32490,32491,32492,32493,32494,
-32495,32496,32497,32498,32499,32500,32501,32502,32503,32504,32505,32506,
-32507,32508,32509,32510,32511,32512,32513,32514,32515,32516,32517,32518,
-32519,32520,32521,32522,32523,32524,32525,32526,32527,32528,32529,32530,
-32531,32532,32533,32534,32535,32536,32537,32538,32539,32540,32541,32542,
-32543,32544,32545,32546,32547,32548,32549,32550,32551,32552,32553,32554,
-32555,32556,32557,32558,32559,32560,32561,32562,32563,32564,32565,32566,
-32567,32568,32569,32570,32571,32572,32573,32574,32575,32576,32577,32578,
-32579,32580,32581,32582,32583,32584,32585,32586,32587,32588,32589,32590,
-32591,32592,32593,32594,32595,32596,32597,32598,32599,32600,32601,32602,
-32603,32604,32605,32606,32607,32608,32609,32610,32611,32612,32613,32614,
-32615,32616,32617,32618,32619,32620,32621,32622,32623,32624,32625,32626,
-32627,32628,32629,32630,32631,32632,32633,32634,32635,32636,32637,32638,
-32639,32640,32641,32642,32643,32644,32645,32646,32647,32648,32649,32650,
-32651,32652,32653,32654,32655,32656,32657,32658,32659,32660,32661,32662,
-32663,32664,32665,32666,32667,32668,32669,32670,32671,32672,32673,32674,
-32675,32676,32677,32678,32679,32680,32681,32682,32683,32684,32685,32686,
-32687,32688,32689,32690,32691,32692,32693,32694,32695,32696,32697,32698,
-32699,32700,32701,32702,32703,32704,32705,32706,32707,32708,32709,32710,
-32711,32712,32713,32714,32715,32716,32717,32718,32719,32720,32721,32722,
-32723,32724,32725,32726,32727,32728,32729,32730,32731,32732,32733,32734,
-32735,32736,32737,32738,32739,32740,32741,32742,32743,32744,32745,32746,
-32747,32748,32749,32750,32751,32752,32753,32754,32755,32756,32757,32758,
-32759,32760,32761,32762,32763,32764,32765,32766,32767,32768L,32769L,32770L,
-32771L,32772L,32773L,32774L,32775L,32776L,32777L,32778L,32779L,32780L,
-32781L,32782L,32783L,32784L,32785L,32786L,32787L,32788L,32789L,32790L,
-32791L,32792L,32793L,32794L,32795L,32796L,32797L,32798L,32799L,32800L,
-32801L,32802L,32803L,32804L,32805L,32806L,32807L,32808L,32809L,32810L,
-32811L,32812L,32813L,32814L,32815L,32816L,32817L,32818L,32819L,32820L,
-32821L,32822L,32823L,32824L,32825L,32826L,32827L,32828L,32829L,32830L,
-32831L,32832L,32833L,32834L,32835L,32836L,32837L,32838L,32839L,32840L,
-32841L,32842L,32843L,32844L,32845L,32846L,32847L,32848L,32849L,32850L,
-32851L,32852L,32853L,32854L,32855L,32856L,32857L,32858L,32859L,32860L,
-32861L,32862L,32863L,32864L,32865L,32866L,32867L,32868L,32869L,32870L,
-32871L,32872L,32873L,32874L,32875L,32876L,32877L,32878L,32879L,32880L,
-32881L,32882L,32883L,32884L,32885L,32886L,32887L,32888L,32889L,32890L,
-32891L,32892L,32893L,32894L,32895L,32896L,32897L,32898L,32899L,32900L,
-32901L,32902L,32903L,32904L,32905L,32906L,32907L,32908L,32909L,32910L,
-32911L,32912L,32913L,32914L,32915L,32916L,32917L,32918L,32919L,32920L,
-32921L,32922L,32923L,32924L,32925L,32926L,32927L,32928L,32929L,32930L,
-32931L,32932L,32933L,32934L,32935L,32936L,32937L,32938L,32939L,32940L,
-32941L,32942L,32943L,32944L,32945L,32946L,32947L,32948L,32949L,32950L,
-32951L,32952L,32953L,32954L,32955L,32956L,32957L,32958L,32959L,32960L,
-32961L,32962L,32963L,32964L,32965L,32966L,32967L,32968L,32969L,32970L,
-32971L,32972L,32973L,32974L,32975L,32976L,32977L,32978L,32979L,32980L,
-32981L,32982L,32983L,32984L,32985L,32986L,32987L,32988L,32989L,32990L,
-32991L,32992L,32993L,32994L,32995L,32996L,32997L,32998L,32999L,33000L,
-33001L,33002L,33003L,33004L,33005L,33006L,33007L,33008L,33009L,33010L,
-33011L,33012L,33013L,33014L,33015L,33016L,33017L,33018L,33019L,33020L,
-33021L,33022L,33023L,33024L,33025L,33026L,33027L,33028L,33029L,33030L,
-33031L,33032L,33033L,33034L,33035L,33036L,33037L,33038L,33039L,33040L,
-33041L,33042L,33043L,33044L,33045L,33046L,33047L,33048L,33049L,33050L,
-33051L,33052L,33053L,33054L,33055L,33056L,33057L,33058L,33059L,33060L,
-33061L,33062L,33063L,33064L,33065L,33066L,33067L,33068L,33069L,33070L,
-33071L,33072L,33073L,33074L,33075L,33076L,33077L,33078L,33079L,33080L,
-33081L,33082L,33083L,33084L,33085L,33086L,33087L,33088L,33089L,33090L,
-33091L,33092L,33093L,33094L,33095L,33096L,33097L,33098L,33099L,33100L,
-33101L,33102L,33103L,33104L,33105L,33106L,33107L,33108L,33109L,33110L,
-33111L,33112L,33113L,33114L,33115L,33116L,33117L,33118L,33119L,33120L,
-33121L,33122L,33123L,33124L,33125L,33126L,33127L,33128L,33129L,33130L,
-33131L,33132L,33133L,33134L,33135L,33136L,33137L,33138L,33139L,33140L,
-33141L,33142L,33143L,33144L,33145L,33146L,33147L,33148L,33149L,33150L,
-33151L,33152L,33153L,33154L,33155L,33156L,33157L,33158L,33159L,33160L,
-33161L,33162L,33163L,33164L,33165L,33166L,33167L,33168L,33169L,33170L,
-33171L,33172L,33173L,33174L,33175L,33176L,33177L,33178L,33179L,33180L,
-33181L,33182L,33183L,33184L,33185L,33186L,33187L,33188L,33189L,33190L,
-33191L,33192L,33193L,33194L,33195L,33196L,33197L,33198L,33199L,33200L,
-33201L,33202L,33203L,33204L,33205L,33206L,33207L,33208L,33209L,33210L,
-33211L,33212L,33213L,33214L,33215L,33216L,33217L,33218L,33219L,33220L,
-33221L,33222L,33223L,33224L,33225L,33226L,33227L,33228L,33229L,33230L,
-33231L,33232L,33233L,33234L,33235L,33236L,33237L,33238L,33239L,33240L,
-33241L,33242L,33243L,33244L,33245L,33246L,33247L,33248L,33249L,33250L,
-33251L,33252L,33253L,33254L,33255L,33256L,33257L,33258L,33259L,33260L,
-33261L,33262L,33263L,33264L,33265L,33266L,33267L,33268L,33269L,33270L,
-33271L,33272L,33273L,33274L,33275L,33276L,33277L,33278L,33279L,33280L,
-33281L,33282L,33283L,33284L,33285L,33286L,33287L,33288L,33289L,33290L,
-33291L,33292L,33293L,33294L,33295L,33296L,33297L,33298L,33299L,33300L,
-33301L,33302L,33303L,33304L,33305L,33306L,33307L,33308L,33309L,33310L,
-33311L,33312L,33313L,33314L,33315L,33316L,33317L,33318L,33319L,33320L,
-33321L,33322L,33323L,33324L,33325L,33326L,33327L,33328L,33329L,33330L,
-33331L,33332L,33333L,33334L,33335L,33336L,33337L,33338L,33339L,33340L,
-33341L,33342L,33343L,33344L,33345L,33346L,33347L,33348L,33349L,33350L,
-33351L,33352L,33353L,33354L,33355L,33356L,33357L,33358L,33359L,33360L,
-33361L,33362L,33363L,33364L,33365L,33366L,33367L,33368L,33369L,33370L,
-33371L,33372L,33373L,33374L,33375L,33376L,33377L,33378L,33379L,33380L,
-33381L,33382L,33383L,33384L,33385L,33386L,33387L,33388L,33389L,33390L,
-33391L,33392L,33393L,33394L,33395L,33396L,33397L,33398L,33399L,33400L,
-33401L,33402L,33403L,33404L,33405L,33406L,33407L,33408L,33409L,33410L,
-33411L,33412L,33413L,33414L,33415L,33416L,33417L,33418L,33419L,33420L,
-33421L,33422L,33423L,33424L,33425L,33426L,33427L,33428L,33429L,33430L,
-33431L,33432L,33433L,33434L,33435L,33436L,33437L,33438L,33439L,33440L,
-33441L,33442L,33443L,33444L,33445L,33446L,33447L,33448L,33449L,33450L,
-33451L,33452L,33453L,33454L,33455L,33456L,33457L,33458L,33459L,33460L,
-33461L,33462L,33463L,33464L,33465L,33466L,33467L,33468L,33469L,33470L,
-33471L,33472L,33473L,33474L,33475L,33476L,33477L,33478L,33479L,33480L,
-33481L,33482L,33483L,33484L,33485L,33486L,33487L,33488L,33489L,33490L,
-33491L,33492L,33493L,33494L,33495L,33496L,33497L,33498L,33499L,33500L,
-33501L,33502L,33503L,33504L,33505L,33506L,33507L,33508L,33509L,33510L,
-33511L,33512L,33513L,33514L,33515L,33516L,33517L,33518L,33519L,33520L,
-33521L,33522L,33523L,33524L,33525L,33526L,33527L,33528L,33529L,33530L,
-33531L,33532L,33533L,33534L,33535L,33536L,33537L,33538L,33539L,33540L,
-33541L,33542L,33543L,33544L,33545L,33546L,33547L,33548L,33549L,33550L,
-33551L,33552L,33553L,33554L,33555L,33556L,33557L,33558L,33559L,33560L,
-33561L,33562L,33563L,33564L,33565L,33566L,33567L,33568L,33569L,33570L,
-33571L,33572L,33573L,33574L,33575L,33576L,33577L,33578L,33579L,33580L,
-33581L,33582L,33583L,33584L,33585L,33586L,33587L,33588L,33589L,33590L,
-33591L,33592L,33593L,33594L,33595L,33596L,33597L,33598L,33599L,33600L,
-33601L,33602L,33603L,33604L,33605L,33606L,33607L,33608L,33609L,33610L,
-33611L,33612L,33613L,33614L,33615L,33616L,33617L,33618L,33619L,33620L,
-33621L,33622L,33623L,33624L,33625L,33626L,33627L,33628L,33629L,33630L,
-33631L,33632L,33633L,33634L,33635L,33636L,33637L,33638L,33639L,33640L,
-33641L,33642L,33643L,33644L,33645L,33646L,33647L,33648L,33649L,33650L,
-33651L,33652L,33653L,33654L,33655L,33656L,33657L,33658L,33659L,33660L,
-33661L,33662L,33663L,33664L,33665L,33666L,33667L,33668L,33669L,33670L,
-33671L,33672L,33673L,33674L,33675L,33676L,33677L,33678L,33679L,33680L,
-33681L,33682L,33683L,33684L,33685L,33686L,33687L,33688L,33689L,33690L,
-33691L,33692L,33693L,33694L,33695L,33696L,33697L,33698L,33699L,33700L,
-33701L,33702L,33703L,33704L,33705L,33706L,33707L,33708L,33709L,33710L,
-33711L,33712L,33713L,33714L,33715L,33716L,33717L,33718L,33719L,33720L,
-33721L,33722L,33723L,33724L,33725L,33726L,33727L,33728L,33729L,33730L,
-33731L,33732L,33733L,33734L,33735L,33736L,33737L,33738L,33739L,33740L,
-33741L,33742L,33743L,33744L,33745L,33746L,33747L,33748L,33749L,33750L,
-33751L,33752L,33753L,33754L,33755L,33756L,33757L,33758L,33759L,33760L,
-33761L,33762L,33763L,33764L,33765L,33766L,33767L,33768L,33769L,33770L,
-33771L,33772L,33773L,33774L,33775L,33776L,33777L,33778L,33779L,33780L,
-33781L,33782L,33783L,33784L,33785L,33786L,33787L,33788L,33789L,33790L,
-33791L,33792L,33793L,33794L,33795L,33796L,33797L,33798L,33799L,33800L,
-33801L,33802L,33803L,33804L,33805L,33806L,33807L,33808L,33809L,33810L,
-33811L,33812L,33813L,33814L,33815L,33816L,33817L,33818L,33819L,33820L,
-33821L,33822L,33823L,33824L,33825L,33826L,33827L,33828L,33829L,33830L,
-33831L,33832L,33833L,33834L,33835L,33836L,33837L,33838L,33839L,33840L,
-33841L,33842L,33843L,33844L,33845L,33846L,33847L,33848L,33849L,33850L,
-33851L,33852L,33853L,33854L,33855L,33856L,33857L,33858L,33859L,33860L,
-33861L,33862L,33863L,33864L,33865L,33866L,33867L,33868L,33869L,33870L,
-33871L,33872L,33873L,33874L,33875L,33876L,33877L,33878L,33879L,33880L,
-33881L,33882L,33883L,33884L,33885L,33886L,33887L,33888L,33889L,33890L,
-33891L,33892L,33893L,33894L,33895L,33896L,33897L,33898L,33899L,33900L,
-33901L,33902L,33903L,33904L,33905L,33906L,33907L,33908L,33909L,33910L,
-33911L,33912L,33913L,33914L,33915L,33916L,33917L,33918L,33919L,33920L,
-33921L,33922L,33923L,33924L,33925L,33926L,33927L,33928L,33929L,33930L,
-33931L,33932L,33933L,33934L,33935L,33936L,33937L,33938L,33939L,33940L,
-33941L,33942L,33943L,33944L,33945L,33946L,33947L,33948L,33949L,33950L,
-33951L,33952L,33953L,33954L,33955L,33956L,33957L,33958L,33959L,33960L,
-33961L,33962L,33963L,33964L,33965L,33966L,33967L,33968L,33969L,33970L,
-33971L,33972L,33973L,33974L,33975L,33976L,33977L,33978L,33979L,33980L,
-33981L,33982L,33983L,33984L,33985L,33986L,33987L,33988L,33989L,33990L,
-33991L,33992L,33993L,33994L,33995L,33996L,33997L,33998L,33999L,34000L,
-34001L,34002L,34003L,34004L,34005L,34006L,34007L,34008L,34009L,34010L,
-34011L,34012L,34013L,34014L,34015L,34016L,34017L,34018L,34019L,34020L,
-34021L,34022L,34023L,34024L,34025L,34026L,34027L,34028L,34029L,34030L,
-34031L,34032L,34033L,34034L,34035L,34036L,34037L,34038L,34039L,34040L,
-34041L,34042L,34043L,34044L,34045L,34046L,34047L,34048L,34049L,34050L,
-34051L,34052L,34053L,34054L,34055L,34056L,34057L,34058L,34059L,34060L,
-34061L,34062L,34063L,34064L,34065L,34066L,34067L,34068L,34069L,34070L,
-34071L,34072L,34073L,34074L,34075L,34076L,34077L,34078L,34079L,34080L,
-34081L,34082L,34083L,34084L,34085L,34086L,34087L,34088L,34089L,34090L,
-34091L,34092L,34093L,34094L,34095L,34096L,34097L,34098L,34099L,34100L,
-34101L,34102L,34103L,34104L,34105L,34106L,34107L,34108L,34109L,34110L,
-34111L,34112L,34113L,34114L,34115L,34116L,34117L,34118L,34119L,34120L,
-34121L,34122L,34123L,34124L,34125L,34126L,34127L,34128L,34129L,34130L,
-34131L,34132L,34133L,34134L,34135L,34136L,34137L,34138L,34139L,34140L,
-34141L,34142L,34143L,34144L,34145L,34146L,34147L,34148L,34149L,34150L,
-34151L,34152L,34153L,34154L,34155L,34156L,34157L,34158L,34159L,34160L,
-34161L,34162L,34163L,34164L,34165L,34166L,34167L,34168L,34169L,34170L,
-34171L,34172L,34173L,34174L,34175L,34176L,34177L,34178L,34179L,34180L,
-34181L,34182L,34183L,34184L,34185L,34186L,34187L,34188L,34189L,34190L,
-34191L,34192L,34193L,34194L,34195L,34196L,34197L,34198L,34199L,34200L,
-34201L,34202L,34203L,34204L,34205L,34206L,34207L,34208L,34209L,34210L,
-34211L,34212L,34213L,34214L,34215L,34216L,34217L,34218L,34219L,34220L,
-34221L,34222L,34223L,34224L,34225L,34226L,34227L,34228L,34229L,34230L,
-34231L,34232L,34233L,34234L,34235L,34236L,34237L,34238L,34239L,34240L,
-34241L,34242L,34243L,34244L,34245L,34246L,34247L,34248L,34249L,34250L,
-34251L,34252L,34253L,34254L,34255L,34256L,34257L,34258L,34259L,34260L,
-34261L,34262L,34263L,34264L,34265L,34266L,34267L,34268L,34269L,34270L,
-34271L,34272L,34273L,34274L,34275L,34276L,34277L,34278L,34279L,34280L,
-34281L,34282L,34283L,34284L,34285L,34286L,34287L,34288L,34289L,34290L,
-34291L,34292L,34293L,34294L,34295L,34296L,34297L,34298L,34299L,34300L,
-34301L,34302L,34303L,34304L,34305L,34306L,34307L,34308L,34309L,34310L,
-34311L,34312L,34313L,34314L,34315L,34316L,34317L,34318L,34319L,34320L,
-34321L,34322L,34323L,34324L,34325L,34326L,34327L,34328L,34329L,34330L,
-34331L,34332L,34333L,34334L,34335L,34336L,34337L,34338L,34339L,34340L,
-34341L,34342L,34343L,34344L,34345L,34346L,34347L,34348L,34349L,34350L,
-34351L,34352L,34353L,34354L,34355L,34356L,34357L,34358L,34359L,34360L,
-34361L,34362L,34363L,34364L,34365L,34366L,34367L,34368L,34369L,34370L,
-34371L,34372L,34373L,34374L,34375L,34376L,34377L,34378L,34379L,34380L,
-34381L,34382L,34383L,34384L,34385L,34386L,34387L,34388L,34389L,34390L,
-34391L,34392L,34393L,34394L,34395L,34396L,34397L,34398L,34399L,34400L,
-34401L,34402L,34403L,34404L,34405L,34406L,34407L,34408L,34409L,34410L,
-34411L,34412L,34413L,34414L,34415L,34416L,34417L,34418L,34419L,34420L,
-34421L,34422L,34423L,34424L,34425L,34426L,34427L,34428L,34429L,34430L,
-34431L,34432L,34433L,34434L,34435L,34436L,34437L,34438L,34439L,34440L,
-34441L,34442L,34443L,34444L,34445L,34446L,34447L,34448L,34449L,34450L,
-34451L,34452L,34453L,34454L,34455L,34456L,34457L,34458L,34459L,34460L,
-34461L,34462L,34463L,34464L,34465L,34466L,34467L,34468L,34469L,34470L,
-34471L,34472L,34473L,34474L,34475L,34476L,34477L,34478L,34479L,34480L,
-34481L,34482L,34483L,34484L,34485L,34486L,34487L,34488L,34489L,34490L,
-34491L,34492L,34493L,34494L,34495L,34496L,34497L,34498L,34499L,34500L,
-34501L,34502L,34503L,34504L,34505L,34506L,34507L,34508L,34509L,34510L,
-34511L,34512L,34513L,34514L,34515L,34516L,34517L,34518L,34519L,34520L,
-34521L,34522L,34523L,34524L,34525L,34526L,34527L,34528L,34529L,34530L,
-34531L,34532L,34533L,34534L,34535L,34536L,34537L,34538L,34539L,34540L,
-34541L,34542L,34543L,34544L,34545L,34546L,34547L,34548L,34549L,34550L,
-34551L,34552L,34553L,34554L,34555L,34556L,34557L,34558L,34559L,34560L,
-34561L,34562L,34563L,34564L,34565L,34566L,34567L,34568L,34569L,34570L,
-34571L,34572L,34573L,34574L,34575L,34576L,34577L,34578L,34579L,34580L,
-34581L,34582L,34583L,34584L,34585L,34586L,34587L,34588L,34589L,34590L,
-34591L,34592L,34593L,34594L,34595L,34596L,34597L,34598L,34599L,34600L,
-34601L,34602L,34603L,34604L,34605L,34606L,34607L,34608L,34609L,34610L,
-34611L,34612L,34613L,34614L,34615L,34616L,34617L,34618L,34619L,34620L,
-34621L,34622L,34623L,34624L,34625L,34626L,34627L,34628L,34629L,34630L,
-34631L,34632L,34633L,34634L,34635L,34636L,34637L,34638L,34639L,34640L,
-34641L,34642L,34643L,34644L,34645L,34646L,34647L,34648L,34649L,34650L,
-34651L,34652L,34653L,34654L,34655L,34656L,34657L,34658L,34659L,34660L,
-34661L,34662L,34663L,34664L,34665L,34666L,34667L,34668L,34669L,34670L,
-34671L,34672L,34673L,34674L,34675L,34676L,34677L,34678L,34679L,34680L,
-34681L,34682L,34683L,34684L,34685L,34686L,34687L,34688L,34689L,34690L,
-34691L,34692L,34693L,34694L,34695L,34696L,34697L,34698L,34699L,34700L,
-34701L,34702L,34703L,34704L,34705L,34706L,34707L,34708L,34709L,34710L,
-34711L,34712L,34713L,34714L,34715L,34716L,34717L,34718L,34719L,34720L,
-34721L,34722L,34723L,34724L,34725L,34726L,34727L,34728L,34729L,34730L,
-34731L,34732L,34733L,34734L,34735L,34736L,34737L,34738L,34739L,34740L,
-34741L,34742L,34743L,34744L,34745L,34746L,34747L,34748L,34749L,34750L,
-34751L,34752L,34753L,34754L,34755L,34756L,34757L,34758L,34759L,34760L,
-34761L,34762L,34763L,34764L,34765L,34766L,34767L,34768L,34769L,34770L,
-34771L,34772L,34773L,34774L,34775L,34776L,34777L,34778L,34779L,34780L,
-34781L,34782L,34783L,34784L,34785L,34786L,34787L,34788L,34789L,34790L,
-34791L,34792L,34793L,34794L,34795L,34796L,34797L,34798L,34799L,34800L,
-34801L,34802L,34803L,34804L,34805L,34806L,34807L,34808L,34809L,34810L,
-34811L,34812L,34813L,34814L,34815L,34816L,34817L,34818L,34819L,34820L,
-34821L,34822L,34823L,34824L,34825L,34826L,34827L,34828L,34829L,34830L,
-34831L,34832L,34833L,34834L,34835L,34836L,34837L,34838L,34839L,34840L,
-34841L,34842L,34843L,34844L,34845L,34846L,34847L,34848L,34849L,34850L,
-34851L,34852L,34853L,34854L,34855L,34856L,34857L,34858L,34859L,34860L,
-34861L,34862L,34863L,34864L,34865L,34866L,34867L,34868L,34869L,34870L,
-34871L,34872L,34873L,34874L,34875L,34876L,34877L,34878L,34879L,34880L,
-34881L,34882L,34883L,34884L,34885L,34886L,34887L,34888L,34889L,34890L,
-34891L,34892L,34893L,34894L,34895L,34896L,34897L,34898L,34899L,34900L,
-34901L,34902L,34903L,34904L,34905L,34906L,34907L,34908L,34909L,34910L,
-34911L,34912L,34913L,34914L,34915L,34916L,34917L,34918L,34919L,34920L,
-34921L,34922L,34923L,34924L,34925L,34926L,34927L,34928L,34929L,34930L,
-34931L,34932L,34933L,34934L,34935L,34936L,34937L,34938L,34939L,34940L,
-34941L,34942L,34943L,34944L,34945L,34946L,34947L,34948L,34949L,34950L,
-34951L,34952L,34953L,34954L,34955L,34956L,34957L,34958L,34959L,34960L,
-34961L,34962L,34963L,34964L,34965L,34966L,34967L,34968L,34969L,34970L,
-34971L,34972L,34973L,34974L,34975L,34976L,34977L,34978L,34979L,34980L,
-34981L,34982L,34983L,34984L,34985L,34986L,34987L,34988L,34989L,34990L,
-34991L,34992L,34993L,34994L,34995L,34996L,34997L,34998L,34999L,35000L,
-35001L,35002L,35003L,35004L,35005L,35006L,35007L,35008L,35009L,35010L,
-35011L,35012L,35013L,35014L,35015L,35016L,35017L,35018L,35019L,35020L,
-35021L,35022L,35023L,35024L,35025L,35026L,35027L,35028L,35029L,35030L,
-35031L,35032L,35033L,35034L,35035L,35036L,35037L,35038L,35039L,35040L,
-35041L,35042L,35043L,35044L,35045L,35046L,35047L,35048L,35049L,35050L,
-35051L,35052L,35053L,35054L,35055L,35056L,35057L,35058L,35059L,35060L,
-35061L,35062L,35063L,35064L,35065L,35066L,35067L,35068L,35069L,35070L,
-35071L,35072L,35073L,35074L,35075L,35076L,35077L,35078L,35079L,35080L,
-35081L,35082L,35083L,35084L,35085L,35086L,35087L,35088L,35089L,35090L,
-35091L,35092L,35093L,35094L,35095L,35096L,35097L,35098L,35099L,35100L,
-35101L,35102L,35103L,35104L,35105L,35106L,35107L,35108L,35109L,35110L,
-35111L,35112L,35113L,35114L,35115L,35116L,35117L,35118L,35119L,35120L,
-35121L,35122L,35123L,35124L,35125L,35126L,35127L,35128L,35129L,35130L,
-35131L,35132L,35133L,35134L,35135L,35136L,35137L,35138L,35139L,35140L,
-35141L,35142L,35143L,35144L,35145L,35146L,35147L,35148L,35149L,35150L,
-35151L,35152L,35153L,35154L,35155L,35156L,35157L,35158L,35159L,35160L,
-35161L,35162L,35163L,35164L,35165L,35166L,35167L,35168L,35169L,35170L,
-35171L,35172L,35173L,35174L,35175L,35176L,35177L,35178L,35179L,35180L,
-35181L,35182L,35183L,35184L,35185L,35186L,35187L,35188L,35189L,35190L,
-35191L,35192L,35193L,35194L,35195L,35196L,35197L,35198L,35199L,35200L,
-35201L,35202L,35203L,35204L,35205L,35206L,35207L,35208L,35209L,35210L,
-35211L,35212L,35213L,35214L,35215L,35216L,35217L,35218L,35219L,35220L,
-35221L,35222L,35223L,35224L,35225L,35226L,35227L,35228L,35229L,35230L,
-35231L,35232L,35233L,35234L,35235L,35236L,35237L,35238L,35239L,35240L,
-35241L,35242L,35243L,35244L,35245L,35246L,35247L,35248L,35249L,35250L,
-35251L,35252L,35253L,35254L,35255L,35256L,35257L,35258L,35259L,35260L,
-35261L,35262L,35263L,35264L,35265L,35266L,35267L,35268L,35269L,35270L,
-35271L,35272L,35273L,35274L,35275L,35276L,35277L,35278L,35279L,35280L,
-35281L,35282L,35283L,35284L,35285L,35286L,35287L,35288L,35289L,35290L,
-35291L,35292L,35293L,35294L,35295L,35296L,35297L,35298L,35299L,35300L,
-35301L,35302L,35303L,35304L,35305L,35306L,35307L,35308L,35309L,35310L,
-35311L,35312L,35313L,35314L,35315L,35316L,35317L,35318L,35319L,35320L,
-35321L,35322L,35323L,35324L,35325L,35326L,35327L,35328L,35329L,35330L,
-35331L,35332L,35333L,35334L,35335L,35336L,35337L,35338L,35339L,35340L,
-35341L,35342L,35343L,35344L,35345L,35346L,35347L,35348L,35349L,35350L,
-35351L,35352L,35353L,35354L,35355L,35356L,35357L,35358L,35359L,35360L,
-35361L,35362L,35363L,35364L,35365L,35366L,35367L,35368L,35369L,35370L,
-35371L,35372L,35373L,35374L,35375L,35376L,35377L,35378L,35379L,35380L,
-35381L,35382L,35383L,35384L,35385L,35386L,35387L,35388L,35389L,35390L,
-35391L,35392L,35393L,35394L,35395L,35396L,35397L,35398L,35399L,35400L,
-35401L,35402L,35403L,35404L,35405L,35406L,35407L,35408L,35409L,35410L,
-35411L,35412L,35413L,35414L,35415L,35416L,35417L,35418L,35419L,35420L,
-35421L,35422L,35423L,35424L,35425L,35426L,35427L,35428L,35429L,35430L,
-35431L,35432L,35433L,35434L,35435L,35436L,35437L,35438L,35439L,35440L,
-35441L,35442L,35443L,35444L,35445L,35446L,35447L,35448L,35449L,35450L,
-35451L,35452L,35453L,35454L,35455L,35456L,35457L,35458L,35459L,35460L,
-35461L,35462L,35463L,35464L,35465L,35466L,35467L,35468L,35469L,35470L,
-35471L,35472L,35473L,35474L,35475L,35476L,35477L,35478L,35479L,35480L,
-35481L,35482L,35483L,35484L,35485L,35486L,35487L,35488L,35489L,35490L,
-35491L,35492L,35493L,35494L,35495L,35496L,35497L,35498L,35499L,35500L,
-35501L,35502L,35503L,35504L,35505L,35506L,35507L,35508L,35509L,35510L,
-35511L,35512L,35513L,35514L,35515L,35516L,35517L,35518L,35519L,35520L,
-35521L,35522L,35523L,35524L,35525L,35526L,35527L,35528L,35529L,35530L,
-35531L,35532L,35533L,35534L,35535L,35536L,35537L,35538L,35539L,35540L,
-35541L,35542L,35543L,35544L,35545L,35546L,35547L,35548L,35549L,35550L,
-35551L,35552L,35553L,35554L,35555L,35556L,35557L,35558L,35559L,35560L,
-35561L,35562L,35563L,35564L,35565L,35566L,35567L,35568L,35569L,35570L,
-35571L,35572L,35573L,35574L,35575L,35576L,35577L,35578L,35579L,35580L,
-35581L,35582L,35583L,35584L,35585L,35586L,35587L,35588L,35589L,35590L,
-35591L,35592L,35593L,35594L,35595L,35596L,35597L,35598L,35599L,35600L,
-35601L,35602L,35603L,35604L,35605L,35606L,35607L,35608L,35609L,35610L,
-35611L,35612L,35613L,35614L,35615L,35616L,35617L,35618L,35619L,35620L,
-35621L,35622L,35623L,35624L,35625L,35626L,35627L,35628L,35629L,35630L,
-35631L,35632L,35633L,35634L,35635L,35636L,35637L,35638L,35639L,35640L,
-35641L,35642L,35643L,35644L,35645L,35646L,35647L,35648L,35649L,35650L,
-35651L,35652L,35653L,35654L,35655L,35656L,35657L,35658L,35659L,35660L,
-35661L,35662L,35663L,35664L,35665L,35666L,35667L,35668L,35669L,35670L,
-35671L,35672L,35673L,35674L,35675L,35676L,35677L,35678L,35679L,35680L,
-35681L,35682L,35683L,35684L,35685L,35686L,35687L,35688L,35689L,35690L,
-35691L,35692L,35693L,35694L,35695L,35696L,35697L,35698L,35699L,35700L,
-35701L,35702L,35703L,35704L,35705L,35706L,35707L,35708L,35709L,35710L,
-35711L,35712L,35713L,35714L,35715L,35716L,35717L,35718L,35719L,35720L,
-35721L,35722L,35723L,35724L,35725L,35726L,35727L,35728L,35729L,35730L,
-35731L,35732L,35733L,35734L,35735L,35736L,35737L,35738L,35739L,35740L,
-35741L,35742L,35743L,35744L,35745L,35746L,35747L,35748L,35749L,35750L,
-35751L,35752L,35753L,35754L,35755L,35756L,35757L,35758L,35759L,35760L,
-35761L,35762L,35763L,35764L,35765L,35766L,35767L,35768L,35769L,35770L,
-35771L,35772L,35773L,35774L,35775L,35776L,35777L,35778L,35779L,35780L,
-35781L,35782L,35783L,35784L,35785L,35786L,35787L,35788L,35789L,35790L,
-35791L,35792L,35793L,35794L,35795L,35796L,35797L,35798L,35799L,35800L,
-35801L,35802L,35803L,35804L,35805L,35806L,35807L,35808L,35809L,35810L,
-35811L,35812L,35813L,35814L,35815L,35816L,35817L,35818L,35819L,35820L,
-35821L,35822L,35823L,35824L,35825L,35826L,35827L,35828L,35829L,35830L,
-35831L,35832L,35833L,35834L,35835L,35836L,35837L,35838L,35839L,35840L,
-35841L,35842L,35843L,35844L,35845L,35846L,35847L,35848L,35849L,35850L,
-35851L,35852L,35853L,35854L,35855L,35856L,35857L,35858L,35859L,35860L,
-35861L,35862L,35863L,35864L,35865L,35866L,35867L,35868L,35869L,35870L,
-35871L,35872L,35873L,35874L,35875L,35876L,35877L,35878L,35879L,35880L,
-35881L,35882L,35883L,35884L,35885L,35886L,35887L,35888L,35889L,35890L,
-35891L,35892L,35893L,35894L,35895L,35896L,35897L,35898L,35899L,35900L,
-35901L,35902L,35903L,35904L,35905L,35906L,35907L,35908L,35909L,35910L,
-35911L,35912L,35913L,35914L,35915L,35916L,35917L,35918L,35919L,35920L,
-35921L,35922L,35923L,35924L,35925L,35926L,35927L,35928L,35929L,35930L,
-35931L,35932L,35933L,35934L,35935L,35936L,35937L,35938L,35939L,35940L,
-35941L,35942L,35943L,35944L,35945L,35946L,35947L,35948L,35949L,35950L,
-35951L,35952L,35953L,35954L,35955L,35956L,35957L,35958L,35959L,35960L,
-35961L,35962L,35963L,35964L,35965L,35966L,35967L,35968L,35969L,35970L,
-35971L,35972L,35973L,35974L,35975L,35976L,35977L,35978L,35979L,35980L,
-35981L,35982L,35983L,35984L,35985L,35986L,35987L,35988L,35989L,35990L,
-35991L,35992L,35993L,35994L,35995L,35996L,35997L,35998L,35999L,36000L,
-36001L,36002L,36003L,36004L,36005L,36006L,36007L,36008L,36009L,36010L,
-36011L,36012L,36013L,36014L,36015L,36016L,36017L,36018L,36019L,36020L,
-36021L,36022L,36023L,36024L,36025L,36026L,36027L,36028L,36029L,36030L,
-36031L,36032L,36033L,36034L,36035L,36036L,36037L,36038L,36039L,36040L,
-36041L,36042L,36043L,36044L,36045L,36046L,36047L,36048L,36049L,36050L,
-36051L,36052L,36053L,36054L,36055L,36056L,36057L,36058L,36059L,36060L,
-36061L,36062L,36063L,36064L,36065L,36066L,36067L,36068L,36069L,36070L,
-36071L,36072L,36073L,36074L,36075L,36076L,36077L,36078L,36079L,36080L,
-36081L,36082L,36083L,36084L,36085L,36086L,36087L,36088L,36089L,36090L,
-36091L,36092L,36093L,36094L,36095L,36096L,36097L,36098L,36099L,36100L,
-36101L,36102L,36103L,36104L,36105L,36106L,36107L,36108L,36109L,36110L,
-36111L,36112L,36113L,36114L,36115L,36116L,36117L,36118L,36119L,36120L,
-36121L,36122L,36123L,36124L,36125L,36126L,36127L,36128L,36129L,36130L,
-36131L,36132L,36133L,36134L,36135L,36136L,36137L,36138L,36139L,36140L,
-36141L,36142L,36143L,36144L,36145L,36146L,36147L,36148L,36149L,36150L,
-36151L,36152L,36153L,36154L,36155L,36156L,36157L,36158L,36159L,36160L,
-36161L,36162L,36163L,36164L,36165L,36166L,36167L,36168L,36169L,36170L,
-36171L,36172L,36173L,36174L,36175L,36176L,36177L,36178L,36179L,36180L,
-36181L,36182L,36183L,36184L,36185L,36186L,36187L,36188L,36189L,36190L,
-36191L,36192L,36193L,36194L,36195L,36196L,36197L,36198L,36199L,36200L,
-36201L,36202L,36203L,36204L,36205L,36206L,36207L,36208L,36209L,36210L,
-36211L,36212L,36213L,36214L,36215L,36216L,36217L,36218L,36219L,36220L,
-36221L,36222L,36223L,36224L,36225L,36226L,36227L,36228L,36229L,36230L,
-36231L,36232L,36233L,36234L,36235L,36236L,36237L,36238L,36239L,36240L,
-36241L,36242L,36243L,36244L,36245L,36246L,36247L,36248L,36249L,36250L,
-36251L,36252L,36253L,36254L,36255L,36256L,36257L,36258L,36259L,36260L,
-36261L,36262L,36263L,36264L,36265L,36266L,36267L,36268L,36269L,36270L,
-36271L,36272L,36273L,36274L,36275L,36276L,36277L,36278L,36279L,36280L,
-36281L,36282L,36283L,36284L,36285L,36286L,36287L,36288L,36289L,36290L,
-36291L,36292L,36293L,36294L,36295L,36296L,36297L,36298L,36299L,36300L,
-36301L,36302L,36303L,36304L,36305L,36306L,36307L,36308L,36309L,36310L,
-36311L,36312L,36313L,36314L,36315L,36316L,36317L,36318L,36319L,36320L,
-36321L,36322L,36323L,36324L,36325L,36326L,36327L,36328L,36329L,36330L,
-36331L,36332L,36333L,36334L,36335L,36336L,36337L,36338L,36339L,36340L,
-36341L,36342L,36343L,36344L,36345L,36346L,36347L,36348L,36349L,36350L,
-36351L,36352L,36353L,36354L,36355L,36356L,36357L,36358L,36359L,36360L,
-36361L,36362L,36363L,36364L,36365L,36366L,36367L,36368L,36369L,36370L,
-36371L,36372L,36373L,36374L,36375L,36376L,36377L,36378L,36379L,36380L,
-36381L,36382L,36383L,36384L,36385L,36386L,36387L,36388L,36389L,36390L,
-36391L,36392L,36393L,36394L,36395L,36396L,36397L,36398L,36399L,36400L,
-36401L,36402L,36403L,36404L,36405L,36406L,36407L,36408L,36409L,36410L,
-36411L,36412L,36413L,36414L,36415L,36416L,36417L,36418L,36419L,36420L,
-36421L,36422L,36423L,36424L,36425L,36426L,36427L,36428L,36429L,36430L,
-36431L,36432L,36433L,36434L,36435L,36436L,36437L,36438L,36439L,36440L,
-36441L,36442L,36443L,36444L,36445L,36446L,36447L,36448L,36449L,36450L,
-36451L,36452L,36453L,36454L,36455L,36456L,36457L,36458L,36459L,36460L,
-36461L,36462L,36463L,36464L,36465L,36466L,36467L,36468L,36469L,36470L,
-36471L,36472L,36473L,36474L,36475L,36476L,36477L,36478L,36479L,36480L,
-36481L,36482L,36483L,36484L,36485L,36486L,36487L,36488L,36489L,36490L,
-36491L,36492L,36493L,36494L,36495L,36496L,36497L,36498L,36499L,36500L,
-36501L,36502L,36503L,36504L,36505L,36506L,36507L,36508L,36509L,36510L,
-36511L,36512L,36513L,36514L,36515L,36516L,36517L,36518L,36519L,36520L,
-36521L,36522L,36523L,36524L,36525L,36526L,36527L,36528L,36529L,36530L,
-36531L,36532L,36533L,36534L,36535L,36536L,36537L,36538L,36539L,36540L,
-36541L,36542L,36543L,36544L,36545L,36546L,36547L,36548L,36549L,36550L,
-36551L,36552L,36553L,36554L,36555L,36556L,36557L,36558L,36559L,36560L,
-36561L,36562L,36563L,36564L,36565L,36566L,36567L,36568L,36569L,36570L,
-36571L,36572L,36573L,36574L,36575L,36576L,36577L,36578L,36579L,36580L,
-36581L,36582L,36583L,36584L,36585L,36586L,36587L,36588L,36589L,36590L,
-36591L,36592L,36593L,36594L,36595L,36596L,36597L,36598L,36599L,36600L,
-36601L,36602L,36603L,36604L,36605L,36606L,36607L,36608L,36609L,36610L,
-36611L,36612L,36613L,36614L,36615L,36616L,36617L,36618L,36619L,36620L,
-36621L,36622L,36623L,36624L,36625L,36626L,36627L,36628L,36629L,36630L,
-36631L,36632L,36633L,36634L,36635L,36636L,36637L,36638L,36639L,36640L,
-36641L,36642L,36643L,36644L,36645L,36646L,36647L,36648L,36649L,36650L,
-36651L,36652L,36653L,36654L,36655L,36656L,36657L,36658L,36659L,36660L,
-36661L,36662L,36663L,36664L,36665L,36666L,36667L,36668L,36669L,36670L,
-36671L,36672L,36673L,36674L,36675L,36676L,36677L,36678L,36679L,36680L,
-36681L,36682L,36683L,36684L,36685L,36686L,36687L,36688L,36689L,36690L,
-36691L,36692L,36693L,36694L,36695L,36696L,36697L,36698L,36699L,36700L,
-36701L,36702L,36703L,36704L,36705L,36706L,36707L,36708L,36709L,36710L,
-36711L,36712L,36713L,36714L,36715L,36716L,36717L,36718L,36719L,36720L,
-36721L,36722L,36723L,36724L,36725L,36726L,36727L,36728L,36729L,36730L,
-36731L,36732L,36733L,36734L,36735L,36736L,36737L,36738L,36739L,36740L,
-36741L,36742L,36743L,36744L,36745L,36746L,36747L,36748L,36749L,36750L,
-36751L,36752L,36753L,36754L,36755L,36756L,36757L,36758L,36759L,36760L,
-36761L,36762L,36763L,36764L,36765L,36766L,36767L,36768L,36769L,36770L,
-36771L,36772L,36773L,36774L,36775L,36776L,36777L,36778L,36779L,36780L,
-36781L,36782L,36783L,36784L,36785L,36786L,36787L,36788L,36789L,36790L,
-36791L,36792L,36793L,36794L,36795L,36796L,36797L,36798L,36799L,36800L,
-36801L,36802L,36803L,36804L,36805L,36806L,36807L,36808L,36809L,36810L,
-36811L,36812L,36813L,36814L,36815L,36816L,36817L,36818L,36819L,36820L,
-36821L,36822L,36823L,36824L,36825L,36826L,36827L,36828L,36829L,36830L,
-36831L,36832L,36833L,36834L,36835L,36836L,36837L,36838L,36839L,36840L,
-36841L,36842L,36843L,36844L,36845L,36846L,36847L,36848L,36849L,36850L,
-36851L,36852L,36853L,36854L,36855L,36856L,36857L,36858L,36859L,36860L,
-36861L,36862L,36863L,36864L,36865L,36866L,36867L,36868L,36869L,36870L,
-36871L,36872L,36873L,36874L,36875L,36876L,36877L,36878L,36879L,36880L,
-36881L,36882L,36883L,36884L,36885L,36886L,36887L,36888L,36889L,36890L,
-36891L,36892L,36893L,36894L,36895L,36896L,36897L,36898L,36899L,36900L,
-36901L,36902L,36903L,36904L,36905L,36906L,36907L,36908L,36909L,36910L,
-36911L,36912L,36913L,36914L,36915L,36916L,36917L,36918L,36919L,36920L,
-36921L,36922L,36923L,36924L,36925L,36926L,36927L,36928L,36929L,36930L,
-36931L,36932L,36933L,36934L,36935L,36936L,36937L,36938L,36939L,36940L,
-36941L,36942L,36943L,36944L,36945L,36946L,36947L,36948L,36949L,36950L,
-36951L,36952L,36953L,36954L,36955L,36956L,36957L,36958L,36959L,36960L,
-36961L,36962L,36963L,36964L,36965L,36966L,36967L,36968L,36969L,36970L,
-36971L,36972L,36973L,36974L,36975L,36976L,36977L,36978L,36979L,36980L,
-36981L,36982L,36983L,36984L,36985L,36986L,36987L,36988L,36989L,36990L,
-36991L,36992L,36993L,36994L,36995L,36996L,36997L,36998L,36999L,37000L,
-37001L,37002L,37003L,37004L,37005L,37006L,37007L,37008L,37009L,37010L,
-37011L,37012L,37013L,37014L,37015L,37016L,37017L,37018L,37019L,37020L,
-37021L,37022L,37023L,37024L,37025L,37026L,37027L,37028L,37029L,37030L,
-37031L,37032L,37033L,37034L,37035L,37036L,37037L,37038L,37039L,37040L,
-37041L,37042L,37043L,37044L,37045L,37046L,37047L,37048L,37049L,37050L,
-37051L,37052L,37053L,37054L,37055L,37056L,37057L,37058L,37059L,37060L,
-37061L,37062L,37063L,37064L,37065L,37066L,37067L,37068L,37069L,37070L,
-37071L,37072L,37073L,37074L,37075L,37076L,37077L,37078L,37079L,37080L,
-37081L,37082L,37083L,37084L,37085L,37086L,37087L,37088L,37089L,37090L,
-37091L,37092L,37093L,37094L,37095L,37096L,37097L,37098L,37099L,37100L,
-37101L,37102L,37103L,37104L,37105L,37106L,37107L,37108L,37109L,37110L,
-37111L,37112L,37113L,37114L,37115L,37116L,37117L,37118L,37119L,37120L,
-37121L,37122L,37123L,37124L,37125L,37126L,37127L,37128L,37129L,37130L,
-37131L,37132L,37133L,37134L,37135L,37136L,37137L,37138L,37139L,37140L,
-37141L,37142L,37143L,37144L,37145L,37146L,37147L,37148L,37149L,37150L,
-37151L,37152L,37153L,37154L,37155L,37156L,37157L,37158L,37159L,37160L,
-37161L,37162L,37163L,37164L,37165L,37166L,37167L,37168L,37169L,37170L,
-37171L,37172L,37173L,37174L,37175L,37176L,37177L,37178L,37179L,37180L,
-37181L,37182L,37183L,37184L,37185L,37186L,37187L,37188L,37189L,37190L,
-37191L,37192L,37193L,37194L,37195L,37196L,37197L,37198L,37199L,37200L,
-37201L,37202L,37203L,37204L,37205L,37206L,37207L,37208L,37209L,37210L,
-37211L,37212L,37213L,37214L,37215L,37216L,37217L,37218L,37219L,37220L,
-37221L,37222L,37223L,37224L,37225L,37226L,37227L,37228L,37229L,37230L,
-37231L,37232L,37233L,37234L,37235L,37236L,37237L,37238L,37239L,37240L,
-37241L,37242L,37243L,37244L,37245L,37246L,37247L,37248L,37249L,37250L,
-37251L,37252L,37253L,37254L,37255L,37256L,37257L,37258L,37259L,37260L,
-37261L,37262L,37263L,37264L,37265L,37266L,37267L,37268L,37269L,37270L,
-37271L,37272L,37273L,37274L,37275L,37276L,37277L,37278L,37279L,37280L,
-37281L,37282L,37283L,37284L,37285L,37286L,37287L,37288L,37289L,37290L,
-37291L,37292L,37293L,37294L,37295L,37296L,37297L,37298L,37299L,37300L,
-37301L,37302L,37303L,37304L,37305L,37306L,37307L,37308L,37309L,37310L,
-37311L,37312L,37313L,37314L,37315L,37316L,37317L,37318L,37319L,37320L,
-37321L,37322L,37323L,37324L,37325L,37326L,37327L,37328L,37329L,37330L,
-37331L,37332L,37333L,37334L,37335L,37336L,37337L,37338L,37339L,37340L,
-37341L,37342L,37343L,37344L,37345L,37346L,37347L,37348L,37349L,37350L,
-37351L,37352L,37353L,37354L,37355L,37356L,37357L,37358L,37359L,37360L,
-37361L,37362L,37363L,37364L,37365L,37366L,37367L,37368L,37369L,37370L,
-37371L,37372L,37373L,37374L,37375L,37376L,37377L,37378L,37379L,37380L,
-37381L,37382L,37383L,37384L,37385L,37386L,37387L,37388L,37389L,37390L,
-37391L,37392L,37393L,37394L,37395L,37396L,37397L,37398L,37399L,37400L,
-37401L,37402L,37403L,37404L,37405L,37406L,37407L,37408L,37409L,37410L,
-37411L,37412L,37413L,37414L,37415L,37416L,37417L,37418L,37419L,37420L,
-37421L,37422L,37423L,37424L,37425L,37426L,37427L,37428L,37429L,37430L,
-37431L,37432L,37433L,37434L,37435L,37436L,37437L,37438L,37439L,37440L,
-37441L,37442L,37443L,37444L,37445L,37446L,37447L,37448L,37449L,37450L,
-37451L,37452L,37453L,37454L,37455L,37456L,37457L,37458L,37459L,37460L,
-37461L,37462L,37463L,37464L,37465L,37466L,37467L,37468L,37469L,37470L,
-37471L,37472L,37473L,37474L,37475L,37476L,37477L,37478L,37479L,37480L,
-37481L,37482L,37483L,37484L,37485L,37486L,37487L,37488L,37489L,37490L,
-37491L,37492L,37493L,37494L,37495L,37496L,37497L,37498L,37499L,37500L,
-37501L,37502L,37503L,37504L,37505L,37506L,37507L,37508L,37509L,37510L,
-37511L,37512L,37513L,37514L,37515L,37516L,37517L,37518L,37519L,37520L,
-37521L,37522L,37523L,37524L,37525L,37526L,37527L,37528L,37529L,37530L,
-37531L,37532L,37533L,37534L,37535L,37536L,37537L,37538L,37539L,37540L,
-37541L,37542L,37543L,37544L,37545L,37546L,37547L,37548L,37549L,37550L,
-37551L,37552L,37553L,37554L,37555L,37556L,37557L,37558L,37559L,37560L,
-37561L,37562L,37563L,37564L,37565L,37566L,37567L,37568L,37569L,37570L,
-37571L,37572L,37573L,37574L,37575L,37576L,37577L,37578L,37579L,37580L,
-37581L,37582L,37583L,37584L,37585L,37586L,37587L,37588L,37589L,37590L,
-37591L,37592L,37593L,37594L,37595L,37596L,37597L,37598L,37599L,37600L,
-37601L,37602L,37603L,37604L,37605L,37606L,37607L,37608L,37609L,37610L,
-37611L,37612L,37613L,37614L,37615L,37616L,37617L,37618L,37619L,37620L,
-37621L,37622L,37623L,37624L,37625L,37626L,37627L,37628L,37629L,37630L,
-37631L,37632L,37633L,37634L,37635L,37636L,37637L,37638L,37639L,37640L,
-37641L,37642L,37643L,37644L,37645L,37646L,37647L,37648L,37649L,37650L,
-37651L,37652L,37653L,37654L,37655L,37656L,37657L,37658L,37659L,37660L,
-37661L,37662L,37663L,37664L,37665L,37666L,37667L,37668L,37669L,37670L,
-37671L,37672L,37673L,37674L,37675L,37676L,37677L,37678L,37679L,37680L,
-37681L,37682L,37683L,37684L,37685L,37686L,37687L,37688L,37689L,37690L,
-37691L,37692L,37693L,37694L,37695L,37696L,37697L,37698L,37699L,37700L,
-37701L,37702L,37703L,37704L,37705L,37706L,37707L,37708L,37709L,37710L,
-37711L,37712L,37713L,37714L,37715L,37716L,37717L,37718L,37719L,37720L,
-37721L,37722L,37723L,37724L,37725L,37726L,37727L,37728L,37729L,37730L,
-37731L,37732L,37733L,37734L,37735L,37736L,37737L,37738L,37739L,37740L,
-37741L,37742L,37743L,37744L,37745L,37746L,37747L,37748L,37749L,37750L,
-37751L,37752L,37753L,37754L,37755L,37756L,37757L,37758L,37759L,37760L,
-37761L,37762L,37763L,37764L,37765L,37766L,37767L,37768L,37769L,37770L,
-37771L,37772L,37773L,37774L,37775L,37776L,37777L,37778L,37779L,37780L,
-37781L,37782L,37783L,37784L,37785L,37786L,37787L,37788L,37789L,37790L,
-37791L,37792L,37793L,37794L,37795L,37796L,37797L,37798L,37799L,37800L,
-37801L,37802L,37803L,37804L,37805L,37806L,37807L,37808L,37809L,37810L,
-37811L,37812L,37813L,37814L,37815L,37816L,37817L,37818L,37819L,37820L,
-37821L,37822L,37823L,37824L,37825L,37826L,37827L,37828L,37829L,37830L,
-37831L,37832L,37833L,37834L,37835L,37836L,37837L,37838L,37839L,37840L,
-37841L,37842L,37843L,37844L,37845L,37846L,37847L,37848L,37849L,37850L,
-37851L,37852L,37853L,37854L,37855L,37856L,37857L,37858L,37859L,37860L,
-37861L,37862L,37863L,37864L,37865L,37866L,37867L,37868L,37869L,37870L,
-37871L,37872L,37873L,37874L,37875L,37876L,37877L,37878L,37879L,37880L,
-37881L,37882L,37883L,37884L,37885L,37886L,37887L,37888L,37889L,37890L,
-37891L,37892L,37893L,37894L,37895L,37896L,37897L,37898L,37899L,37900L,
-37901L,37902L,37903L,37904L,37905L,37906L,37907L,37908L,37909L,37910L,
-37911L,37912L,37913L,37914L,37915L,37916L,37917L,37918L,37919L,37920L,
-37921L,37922L,37923L,37924L,37925L,37926L,37927L,37928L,37929L,37930L,
-37931L,37932L,37933L,37934L,37935L,37936L,37937L,37938L,37939L,37940L,
-37941L,37942L,37943L,37944L,37945L,37946L,37947L,37948L,37949L,37950L,
-37951L,37952L,37953L,37954L,37955L,37956L,37957L,37958L,37959L,37960L,
-37961L,37962L,37963L,37964L,37965L,37966L,37967L,37968L,37969L,37970L,
-37971L,37972L,37973L,37974L,37975L,37976L,37977L,37978L,37979L,37980L,
-37981L,37982L,37983L,37984L,37985L,37986L,37987L,37988L,37989L,37990L,
-37991L,37992L,37993L,37994L,37995L,37996L,37997L,37998L,37999L,38000L,
-38001L,38002L,38003L,38004L,38005L,38006L,38007L,38008L,38009L,38010L,
-38011L,38012L,38013L,38014L,38015L,38016L,38017L,38018L,38019L,38020L,
-38021L,38022L,38023L,38024L,38025L,38026L,38027L,38028L,38029L,38030L,
-38031L,38032L,38033L,38034L,38035L,38036L,38037L,38038L,38039L,38040L,
-38041L,38042L,38043L,38044L,38045L,38046L,38047L,38048L,38049L,38050L,
-38051L,38052L,38053L,38054L,38055L,38056L,38057L,38058L,38059L,38060L,
-38061L,38062L,38063L,38064L,38065L,38066L,38067L,38068L,38069L,38070L,
-38071L,38072L,38073L,38074L,38075L,38076L,38077L,38078L,38079L,38080L,
-38081L,38082L,38083L,38084L,38085L,38086L,38087L,38088L,38089L,38090L,
-38091L,38092L,38093L,38094L,38095L,38096L,38097L,38098L,38099L,38100L,
-38101L,38102L,38103L,38104L,38105L,38106L,38107L,38108L,38109L,38110L,
-38111L,38112L,38113L,38114L,38115L,38116L,38117L,38118L,38119L,38120L,
-38121L,38122L,38123L,38124L,38125L,38126L,38127L,38128L,38129L,38130L,
-38131L,38132L,38133L,38134L,38135L,38136L,38137L,38138L,38139L,38140L,
-38141L,38142L,38143L,38144L,38145L,38146L,38147L,38148L,38149L,38150L,
-38151L,38152L,38153L,38154L,38155L,38156L,38157L,38158L,38159L,38160L,
-38161L,38162L,38163L,38164L,38165L,38166L,38167L,38168L,38169L,38170L,
-38171L,38172L,38173L,38174L,38175L,38176L,38177L,38178L,38179L,38180L,
-38181L,38182L,38183L,38184L,38185L,38186L,38187L,38188L,38189L,38190L,
-38191L,38192L,38193L,38194L,38195L,38196L,38197L,38198L,38199L,38200L,
-38201L,38202L,38203L,38204L,38205L,38206L,38207L,38208L,38209L,38210L,
-38211L,38212L,38213L,38214L,38215L,38216L,38217L,38218L,38219L,38220L,
-38221L,38222L,38223L,38224L,38225L,38226L,38227L,38228L,38229L,38230L,
-38231L,38232L,38233L,38234L,38235L,38236L,38237L,38238L,38239L,38240L,
-38241L,38242L,38243L,38244L,38245L,38246L,38247L,38248L,38249L,38250L,
-38251L,38252L,38253L,38254L,38255L,38256L,38257L,38258L,38259L,38260L,
-38261L,38262L,38263L,38264L,38265L,38266L,38267L,38268L,38269L,38270L,
-38271L,38272L,38273L,38274L,38275L,38276L,38277L,38278L,38279L,38280L,
-38281L,38282L,38283L,38284L,38285L,38286L,38287L,38288L,38289L,38290L,
-38291L,38292L,38293L,38294L,38295L,38296L,38297L,38298L,38299L,38300L,
-38301L,38302L,38303L,38304L,38305L,38306L,38307L,38308L,38309L,38310L,
-38311L,38312L,38313L,38314L,38315L,38316L,38317L,38318L,38319L,38320L,
-38321L,38322L,38323L,38324L,38325L,38326L,38327L,38328L,38329L,38330L,
-38331L,38332L,38333L,38334L,38335L,38336L,38337L,38338L,38339L,38340L,
-38341L,38342L,38343L,38344L,38345L,38346L,38347L,38348L,38349L,38350L,
-38351L,38352L,38353L,38354L,38355L,38356L,38357L,38358L,38359L,38360L,
-38361L,38362L,38363L,38364L,38365L,38366L,38367L,38368L,38369L,38370L,
-38371L,38372L,38373L,38374L,38375L,38376L,38377L,38378L,38379L,38380L,
-38381L,38382L,38383L,38384L,38385L,38386L,38387L,38388L,38389L,38390L,
-38391L,38392L,38393L,38394L,38395L,38396L,38397L,38398L,38399L,38400L,
-38401L,38402L,38403L,38404L,38405L,38406L,38407L,38408L,38409L,38410L,
-38411L,38412L,38413L,38414L,38415L,38416L,38417L,38418L,38419L,38420L,
-38421L,38422L,38423L,38424L,38425L,38426L,38427L,38428L,38429L,38430L,
-38431L,38432L,38433L,38434L,38435L,38436L,38437L,38438L,38439L,38440L,
-38441L,38442L,38443L,38444L,38445L,38446L,38447L,38448L,38449L,38450L,
-38451L,38452L,38453L,38454L,38455L,38456L,38457L,38458L,38459L,38460L,
-38461L,38462L,38463L,38464L,38465L,38466L,38467L,38468L,38469L,38470L,
-38471L,38472L,38473L,38474L,38475L,38476L,38477L,38478L,38479L,38480L,
-38481L,38482L,38483L,38484L,38485L,38486L,38487L,38488L,38489L,38490L,
-38491L,38492L,38493L,38494L,38495L,38496L,38497L,38498L,38499L,38500L,
-38501L,38502L,38503L,38504L,38505L,38506L,38507L,38508L,38509L,38510L,
-38511L,38512L,38513L,38514L,38515L,38516L,38517L,38518L,38519L,38520L,
-38521L,38522L,38523L,38524L,38525L,38526L,38527L,38528L,38529L,38530L,
-38531L,38532L,38533L,38534L,38535L,38536L,38537L,38538L,38539L,38540L,
-38541L,38542L,38543L,38544L,38545L,38546L,38547L,38548L,38549L,38550L,
-38551L,38552L,38553L,38554L,38555L,38556L,38557L,38558L,38559L,38560L,
-38561L,38562L,38563L,38564L,38565L,38566L,38567L,38568L,38569L,38570L,
-38571L,38572L,38573L,38574L,38575L,38576L,38577L,38578L,38579L,38580L,
-38581L,38582L,38583L,38584L,38585L,38586L,38587L,38588L,38589L,38590L,
-38591L,38592L,38593L,38594L,38595L,38596L,38597L,38598L,38599L,38600L,
-38601L,38602L,38603L,38604L,38605L,38606L,38607L,38608L,38609L,38610L,
-38611L,38612L,38613L,38614L,38615L,38616L,38617L,38618L,38619L,38620L,
-38621L,38622L,38623L,38624L,38625L,38626L,38627L,38628L,38629L,38630L,
-38631L,38632L,38633L,38634L,38635L,38636L,38637L,38638L,38639L,38640L,
-38641L,38642L,38643L,38644L,38645L,38646L,38647L,38648L,38649L,38650L,
-38651L,38652L,38653L,38654L,38655L,38656L,38657L,38658L,38659L,38660L,
-38661L,38662L,38663L,38664L,38665L,38666L,38667L,38668L,38669L,38670L,
-38671L,38672L,38673L,38674L,38675L,38676L,38677L,38678L,38679L,38680L,
-38681L,38682L,38683L,38684L,38685L,38686L,38687L,38688L,38689L,38690L,
-38691L,38692L,38693L,38694L,38695L,38696L,38697L,38698L,38699L,38700L,
-38701L,38702L,38703L,38704L,38705L,38706L,38707L,38708L,38709L,38710L,
-38711L,38712L,38713L,38714L,38715L,38716L,38717L,38718L,38719L,38720L,
-38721L,38722L,38723L,38724L,38725L,38726L,38727L,38728L,38729L,38730L,
-38731L,38732L,38733L,38734L,38735L,38736L,38737L,38738L,38739L,38740L,
-38741L,38742L,38743L,38744L,38745L,38746L,38747L,38748L,38749L,38750L,
-38751L,38752L,38753L,38754L,38755L,38756L,38757L,38758L,38759L,38760L,
-38761L,38762L,38763L,38764L,38765L,38766L,38767L,38768L,38769L,38770L,
-38771L,38772L,38773L,38774L,38775L,38776L,38777L,38778L,38779L,38780L,
-38781L,38782L,38783L,38784L,38785L,38786L,38787L,38788L,38789L,38790L,
-38791L,38792L,38793L,38794L,38795L,38796L,38797L,38798L,38799L,38800L,
-38801L,38802L,38803L,38804L,38805L,38806L,38807L,38808L,38809L,38810L,
-38811L,38812L,38813L,38814L,38815L,38816L,38817L,38818L,38819L,38820L,
-38821L,38822L,38823L,38824L,38825L,38826L,38827L,38828L,38829L,38830L,
-38831L,38832L,38833L,38834L,38835L,38836L,38837L,38838L,38839L,38840L,
-38841L,38842L,38843L,38844L,38845L,38846L,38847L,38848L,38849L,38850L,
-38851L,38852L,38853L,38854L,38855L,38856L,38857L,38858L,38859L,38860L,
-38861L,38862L,38863L,38864L,38865L,38866L,38867L,38868L,38869L,38870L,
-38871L,38872L,38873L,38874L,38875L,38876L,38877L,38878L,38879L,38880L,
-38881L,38882L,38883L,38884L,38885L,38886L,38887L,38888L,38889L,38890L,
-38891L,38892L,38893L,38894L,38895L,38896L,38897L,38898L,38899L,38900L,
-38901L,38902L,38903L,38904L,38905L,38906L,38907L,38908L,38909L,38910L,
-38911L,38912L,38913L,38914L,38915L,38916L,38917L,38918L,38919L,38920L,
-38921L,38922L,38923L,38924L,38925L,38926L,38927L,38928L,38929L,38930L,
-38931L,38932L,38933L,38934L,38935L,38936L,38937L,38938L,38939L,38940L,
-38941L,38942L,38943L,38944L,38945L,38946L,38947L,38948L,38949L,38950L,
-38951L,38952L,38953L,38954L,38955L,38956L,38957L,38958L,38959L,38960L,
-38961L,38962L,38963L,38964L,38965L,38966L,38967L,38968L,38969L,38970L,
-38971L,38972L,38973L,38974L,38975L,38976L,38977L,38978L,38979L,38980L,
-38981L,38982L,38983L,38984L,38985L,38986L,38987L,38988L,38989L,38990L,
-38991L,38992L,38993L,38994L,38995L,38996L,38997L,38998L,38999L,39000L,
-39001L,39002L,39003L,39004L,39005L,39006L,39007L,39008L,39009L,39010L,
-39011L,39012L,39013L,39014L,39015L,39016L,39017L,39018L,39019L,39020L,
-39021L,39022L,39023L,39024L,39025L,39026L,39027L,39028L,39029L,39030L,
-39031L,39032L,39033L,39034L,39035L,39036L,39037L,39038L,39039L,39040L,
-39041L,39042L,39043L,39044L,39045L,39046L,39047L,39048L,39049L,39050L,
-39051L,39052L,39053L,39054L,39055L,39056L,39057L,39058L,39059L,39060L,
-39061L,39062L,39063L,39064L,39065L,39066L,39067L,39068L,39069L,39070L,
-39071L,39072L,39073L,39074L,39075L,39076L,39077L,39078L,39079L,39080L,
-39081L,39082L,39083L,39084L,39085L,39086L,39087L,39088L,39089L,39090L,
-39091L,39092L,39093L,39094L,39095L,39096L,39097L,39098L,39099L,39100L,
-39101L,39102L,39103L,39104L,39105L,39106L,39107L,39108L,39109L,39110L,
-39111L,39112L,39113L,39114L,39115L,39116L,39117L,39118L,39119L,39120L,
-39121L,39122L,39123L,39124L,39125L,39126L,39127L,39128L,39129L,39130L,
-39131L,39132L,39133L,39134L,39135L,39136L,39137L,39138L,39139L,39140L,
-39141L,39142L,39143L,39144L,39145L,39146L,39147L,39148L,39149L,39150L,
-39151L,39152L,39153L,39154L,39155L,39156L,39157L,39158L,39159L,39160L,
-39161L,39162L,39163L,39164L,39165L,39166L,39167L,39168L,39169L,39170L,
-39171L,39172L,39173L,39174L,39175L,39176L,39177L,39178L,39179L,39180L,
-39181L,39182L,39183L,39184L,39185L,39186L,39187L,39188L,39189L,39190L,
-39191L,39192L,39193L,39194L,39195L,39196L,39197L,39198L,39199L,39200L,
-39201L,39202L,39203L,39204L,39205L,39206L,39207L,39208L,39209L,39210L,
-39211L,39212L,39213L,39214L,39215L,39216L,39217L,39218L,39219L,39220L,
-39221L,39222L,39223L,39224L,39225L,39226L,39227L,39228L,39229L,39230L,
-39231L,39232L,39233L,39234L,39235L,39236L,39237L,39238L,39239L,39240L,
-39241L,39242L,39243L,39244L,39245L,39246L,39247L,39248L,39249L,39250L,
-39251L,39252L,39253L,39254L,39255L,39256L,39257L,39258L,39259L,39260L,
-39261L,39262L,39263L,39264L,39265L,39266L,39267L,39268L,39269L,39270L,
-39271L,39272L,39273L,39274L,39275L,39276L,39277L,39278L,39279L,39280L,
-39281L,39282L,39283L,39284L,39285L,39286L,39287L,39288L,39289L,39290L,
-39291L,39292L,39293L,39294L,39295L,39296L,39297L,39298L,39299L,39300L,
-39301L,39302L,39303L,39304L,39305L,39306L,39307L,39308L,39309L,39310L,
-39311L,39312L,39313L,39314L,39315L,39316L,39317L,39318L,39319L,39320L,
-39321L,39322L,39323L,39324L,39325L,39326L,39327L,39328L,39329L,39330L,
-39331L,39332L,39333L,39334L,39335L,39336L,39337L,39338L,39339L,39340L,
-39341L,39342L,39343L,39344L,39345L,39346L,39347L,39348L,39349L,39350L,
-39351L,39352L,39353L,39354L,39355L,39356L,39357L,39358L,39359L,39360L,
-39361L,39362L,39363L,39364L,39365L,39366L,39367L,39368L,39369L,39370L,
-39371L,39372L,39373L,39374L,39375L,39376L,39377L,39378L,39379L,39380L,
-39381L,39382L,39383L,39384L,39385L,39386L,39387L,39388L,39389L,39390L,
-39391L,39392L,39393L,39394L,39395L,39396L,39397L,39398L,39399L,39400L,
-39401L,39402L,39403L,39404L,39405L,39406L,39407L,39408L,39409L,39410L,
-39411L,39412L,39413L,39414L,39415L,39416L,39417L,39418L,39419L,39420L,
-39421L,39422L,39423L,39424L,39425L,39426L,39427L,39428L,39429L,39430L,
-39431L,39432L,39433L,39434L,39435L,39436L,39437L,39438L,39439L,39440L,
-39441L,39442L,39443L,39444L,39445L,39446L,39447L,39448L,39449L,39450L,
-39451L,39452L,39453L,39454L,39455L,39456L,39457L,39458L,39459L,39460L,
-39461L,39462L,39463L,39464L,39465L,39466L,39467L,39468L,39469L,39470L,
-39471L,39472L,39473L,39474L,39475L,39476L,39477L,39478L,39479L,39480L,
-39481L,39482L,39483L,39484L,39485L,39486L,39487L,39488L,39489L,39490L,
-39491L,39492L,39493L,39494L,39495L,39496L,39497L,39498L,39499L,39500L,
-39501L,39502L,39503L,39504L,39505L,39506L,39507L,39508L,39509L,39510L,
-39511L,39512L,39513L,39514L,39515L,39516L,39517L,39518L,39519L,39520L,
-39521L,39522L,39523L,39524L,39525L,39526L,39527L,39528L,39529L,39530L,
-39531L,39532L,39533L,39534L,39535L,39536L,39537L,39538L,39539L,39540L,
-39541L,39542L,39543L,39544L,39545L,39546L,39547L,39548L,39549L,39550L,
-39551L,39552L,39553L,39554L,39555L,39556L,39557L,39558L,39559L,39560L,
-39561L,39562L,39563L,39564L,39565L,39566L,39567L,39568L,39569L,39570L,
-39571L,39572L,39573L,39574L,39575L,39576L,39577L,39578L,39579L,39580L,
-39581L,39582L,39583L,39584L,39585L,39586L,39587L,39588L,39589L,39590L,
-39591L,39592L,39593L,39594L,39595L,39596L,39597L,39598L,39599L,39600L,
-39601L,39602L,39603L,39604L,39605L,39606L,39607L,39608L,39609L,39610L,
-39611L,39612L,39613L,39614L,39615L,39616L,39617L,39618L,39619L,39620L,
-39621L,39622L,39623L,39624L,39625L,39626L,39627L,39628L,39629L,39630L,
-39631L,39632L,39633L,39634L,39635L,39636L,39637L,39638L,39639L,39640L,
-39641L,39642L,39643L,39644L,39645L,39646L,39647L,39648L,39649L,39650L,
-39651L,39652L,39653L,39654L,39655L,39656L,39657L,39658L,39659L,39660L,
-39661L,39662L,39663L,39664L,39665L,39666L,39667L,39668L,39669L,39670L,
-39671L,39672L,39673L,39674L,39675L,39676L,39677L,39678L,39679L,39680L,
-39681L,39682L,39683L,39684L,39685L,39686L,39687L,39688L,39689L,39690L,
-39691L,39692L,39693L,39694L,39695L,39696L,39697L,39698L,39699L,39700L,
-39701L,39702L,39703L,39704L,39705L,39706L,39707L,39708L,39709L,39710L,
-39711L,39712L,39713L,39714L,39715L,39716L,39717L,39718L,39719L,39720L,
-39721L,39722L,39723L,39724L,39725L,39726L,39727L,39728L,39729L,39730L,
-39731L,39732L,39733L,39734L,39735L,39736L,39737L,39738L,39739L,39740L,
-39741L,39742L,39743L,39744L,39745L,39746L,39747L,39748L,39749L,39750L,
-39751L,39752L,39753L,39754L,39755L,39756L,39757L,39758L,39759L,39760L,
-39761L,39762L,39763L,39764L,39765L,39766L,39767L,39768L,39769L,39770L,
-39771L,39772L,39773L,39774L,39775L,39776L,39777L,39778L,39779L,39780L,
-39781L,39782L,39783L,39784L,39785L,39786L,39787L,39788L,39789L,39790L,
-39791L,39792L,39793L,39794L,39795L,39796L,39797L,39798L,39799L,39800L,
-39801L,39802L,39803L,39804L,39805L,39806L,39807L,39808L,39809L,39810L,
-39811L,39812L,39813L,39814L,39815L,39816L,39817L,39818L,39819L,39820L,
-39821L,39822L,39823L,39824L,39825L,39826L,39827L,39828L,39829L,39830L,
-39831L,39832L,39833L,39834L,39835L,39836L,39837L,39838L,39839L,39840L,
-39841L,39842L,39843L,39844L,39845L,39846L,39847L,39848L,39849L,39850L,
-39851L,39852L,39853L,39854L,39855L,39856L,39857L,39858L,39859L,39860L,
-39861L,39862L,39863L,39864L,39865L,39866L,39867L,39868L,39869L,39870L,
-39871L,39872L,39873L,39874L,39875L,39876L,39877L,39878L,39879L,39880L,
-39881L,39882L,39883L,39884L,39885L,39886L,39887L,39888L,39889L,39890L,
-39891L,39892L,39893L,39894L,39895L,39896L,39897L,39898L,39899L,39900L,
-39901L,39902L,39903L,39904L,39905L,39906L,39907L,39908L,39909L,39910L,
-39911L,39912L,39913L,39914L,39915L,39916L,39917L,39918L,39919L,39920L,
-39921L,39922L,39923L,39924L,39925L,39926L,39927L,39928L,39929L,39930L,
-39931L,39932L,39933L,39934L,39935L,39936L,39937L,39938L,39939L,39940L,
-39941L,39942L,39943L,39944L,39945L,39946L,39947L,39948L,39949L,39950L,
-39951L,39952L,39953L,39954L,39955L,39956L,39957L,39958L,39959L,39960L,
-39961L,39962L,39963L,39964L,39965L,39966L,39967L,39968L,39969L,39970L,
-39971L,39972L,39973L,39974L,39975L,39976L,39977L,39978L,39979L,39980L,
-39981L,39982L,39983L,39984L,39985L,39986L,39987L,39988L,39989L,39990L,
-39991L,39992L,39993L,39994L,39995L,39996L,39997L,39998L,39999L,40000L,
-40001L,40002L,40003L,40004L,40005L,40006L,40007L,40008L,40009L,40010L,
-40011L,40012L,40013L,40014L,40015L,40016L,40017L,40018L,40019L,40020L,
-40021L,40022L,40023L,40024L,40025L,40026L,40027L,40028L,40029L,40030L,
-40031L,40032L,40033L,40034L,40035L,40036L,40037L,40038L,40039L,40040L,
-40041L,40042L,40043L,40044L,40045L,40046L,40047L,40048L,40049L,40050L,
-40051L,40052L,40053L,40054L,40055L,40056L,40057L,40058L,40059L,40060L,
-40061L,40062L,40063L,40064L,40065L,40066L,40067L,40068L,40069L,40070L,
-40071L,40072L,40073L,40074L,40075L,40076L,40077L,40078L,40079L,40080L,
-40081L,40082L,40083L,40084L,40085L,40086L,40087L,40088L,40089L,40090L,
-40091L,40092L,40093L,40094L,40095L,40096L,40097L,40098L,40099L,40100L,
-40101L,40102L,40103L,40104L,40105L,40106L,40107L,40108L,40109L,40110L,
-40111L,40112L,40113L,40114L,40115L,40116L,40117L,40118L,40119L,40120L,
-40121L,40122L,40123L,40124L,40125L,40126L,40127L,40128L,40129L,40130L,
-40131L,40132L,40133L,40134L,40135L,40136L,40137L,40138L,40139L,40140L,
-40141L,40142L,40143L,40144L,40145L,40146L,40147L,40148L,40149L,40150L,
-40151L,40152L,40153L,40154L,40155L,40156L,40157L,40158L,40159L,40160L,
-40161L,40162L,40163L,40164L,40165L,40166L,40167L,40168L,40169L,40170L,
-40171L,40172L,40173L,40174L,40175L,40176L,40177L,40178L,40179L,40180L,
-40181L,40182L,40183L,40184L,40185L,40186L,40187L,40188L,40189L,40190L,
-40191L,40192L,40193L,40194L,40195L,40196L,40197L,40198L,40199L,40200L,
-40201L,40202L,40203L,40204L,40205L,40206L,40207L,40208L,40209L,40210L,
-40211L,40212L,40213L,40214L,40215L,40216L,40217L,40218L,40219L,40220L,
-40221L,40222L,40223L,40224L,40225L,40226L,40227L,40228L,40229L,40230L,
-40231L,40232L,40233L,40234L,40235L,40236L,40237L,40238L,40239L,40240L,
-40241L,40242L,40243L,40244L,40245L,40246L,40247L,40248L,40249L,40250L,
-40251L,40252L,40253L,40254L,40255L,40256L,40257L,40258L,40259L,40260L,
-40261L,40262L,40263L,40264L,40265L,40266L,40267L,40268L,40269L,40270L,
-40271L,40272L,40273L,40274L,40275L,40276L,40277L,40278L,40279L,40280L,
-40281L,40282L,40283L,40284L,40285L,40286L,40287L,40288L,40289L,40290L,
-40291L,40292L,40293L,40294L,40295L,40296L,40297L,40298L,40299L,40300L,
-40301L,40302L,40303L,40304L,40305L,40306L,40307L,40308L,40309L,40310L,
-40311L,40312L,40313L,40314L,40315L,40316L,40317L,40318L,40319L,40320L,
-40321L,40322L,40323L,40324L,40325L,40326L,40327L,40328L,40329L,40330L,
-40331L,40332L,40333L,40334L,40335L,40336L,40337L,40338L,40339L,40340L,
-40341L,40342L,40343L,40344L,40345L,40346L,40347L,40348L,40349L,40350L,
-40351L,40352L,40353L,40354L,40355L,40356L,40357L,40358L,40359L,40360L,
-40361L,40362L,40363L,40364L,40365L,40366L,40367L,40368L,40369L,40370L,
-40371L,40372L,40373L,40374L,40375L,40376L,40377L,40378L,40379L,40380L,
-40381L,40382L,40383L,40384L,40385L,40386L,40387L,40388L,40389L,40390L,
-40391L,40392L,40393L,40394L,40395L,40396L,40397L,40398L,40399L,40400L,
-40401L,40402L,40403L,40404L,40405L,40406L,40407L,40408L,40409L,40410L,
-40411L,40412L,40413L,40414L,40415L,40416L,40417L,40418L,40419L,40420L,
-40421L,40422L,40423L,40424L,40425L,40426L,40427L,40428L,40429L,40430L,
-40431L,40432L,40433L,40434L,40435L,40436L,40437L,40438L,40439L,40440L,
-40441L,40442L,40443L,40444L,40445L,40446L,40447L,40448L,40449L,40450L,
-40451L,40452L,40453L,40454L,40455L,40456L,40457L,40458L,40459L,40460L,
-40461L,40462L,40463L,40464L,40465L,40466L,40467L,40468L,40469L,40470L,
-40471L,40472L,40473L,40474L,40475L,40476L,40477L,40478L,40479L,40480L,
-40481L,40482L,40483L,40484L,40485L,40486L,40487L,40488L,40489L,40490L,
-40491L,40492L,40493L,40494L,40495L,40496L,40497L,40498L,40499L,40500L,
-40501L,40502L,40503L,40504L,40505L,40506L,40507L,40508L,40509L,40510L,
-40511L,40512L,40513L,40514L,40515L,40516L,40517L,40518L,40519L,40520L,
-40521L,40522L,40523L,40524L,40525L,40526L,40527L,40528L,40529L,40530L,
-40531L,40532L,40533L,40534L,40535L,40536L,40537L,40538L,40539L,40540L,
-40541L,40542L,40543L,40544L,40545L,40546L,40547L,40548L,40549L,40550L,
-40551L,40552L,40553L,40554L,40555L,40556L,40557L,40558L,40559L,40560L,
-40561L,40562L,40563L,40564L,40565L,40566L,40567L,40568L,40569L,40570L,
-40571L,40572L,40573L,40574L,40575L,40576L,40577L,40578L,40579L,40580L,
-40581L,40582L,40583L,40584L,40585L,40586L,40587L,40588L,40589L,40590L,
-40591L,40592L,40593L,40594L,40595L,40596L,40597L,40598L,40599L,40600L,
-40601L,40602L,40603L,40604L,40605L,40606L,40607L,40608L,40609L,40610L,
-40611L,40612L,40613L,40614L,40615L,40616L,40617L,40618L,40619L,40620L,
-40621L,40622L,40623L,40624L,40625L,40626L,40627L,40628L,40629L,40630L,
-40631L,40632L,40633L,40634L,40635L,40636L,40637L,40638L,40639L,40640L,
-40641L,40642L,40643L,40644L,40645L,40646L,40647L,40648L,40649L,40650L,
-40651L,40652L,40653L,40654L,40655L,40656L,40657L,40658L,40659L,40660L,
-40661L,40662L,40663L,40664L,40665L,40666L,40667L,40668L,40669L,40670L,
-40671L,40672L,40673L,40674L,40675L,40676L,40677L,40678L,40679L,40680L,
-40681L,40682L,40683L,40684L,40685L,40686L,40687L,40688L,40689L,40690L,
-40691L,40692L,40693L,40694L,40695L,40696L,40697L,40698L,40699L,40700L,
-40701L,40702L,40703L,40704L,40705L,40706L,40707L,40708L,40709L,40710L,
-40711L,40712L,40713L,40714L,40715L,40716L,40717L,40718L,40719L,40720L,
-40721L,40722L,40723L,40724L,40725L,40726L,40727L,40728L,40729L,40730L,
-40731L,40732L,40733L,40734L,40735L,40736L,40737L,40738L,40739L,40740L,
-40741L,40742L,40743L,40744L,40745L,40746L,40747L,40748L,40749L,40750L,
-40751L,40752L,40753L,40754L,40755L,40756L,40757L,40758L,40759L,40760L,
-40761L,40762L,40763L,40764L,40765L,40766L,40767L,40768L,40769L,40770L,
-40771L,40772L,40773L,40774L,40775L,40776L,40777L,40778L,40779L,40780L,
-40781L,40782L,40783L,40784L,40785L,40786L,40787L,40788L,40789L,40790L,
-40791L,40792L,40793L,40794L,40795L,40796L,40797L,40798L,40799L,40800L,
-40801L,40802L,40803L,40804L,40805L,40806L,40807L,40808L,40809L,40810L,
-40811L,40812L,40813L,40814L,40815L,40816L,40817L,40818L,40819L,40820L,
-40821L,40822L,40823L,40824L,40825L,40826L,40827L,40828L,40829L,40830L,
-40831L,40832L,40833L,40834L,40835L,40836L,40837L,40838L,40839L,40840L,
-40841L,40842L,40843L,40844L,40845L,40846L,40847L,40848L,40849L,40850L,
-40851L,40852L,40853L,40854L,40855L,40856L,40857L,40858L,40859L,40860L,
-40861L,40862L,40863L,40864L,40865L,40866L,40867L,40868L,40869L,40870L,
-40871L,40872L,40873L,40874L,40875L,40876L,40877L,40878L,40879L,40880L,
-40881L,40882L,40883L,40884L,40885L,40886L,40887L,40888L,40889L,40890L,
-40891L,40892L,40893L,40894L,40895L,40896L,40897L,40898L,40899L,40900L,
-40901L,40902L,40903L,40904L,40905L,40906L,40907L,40908L,40909L,40910L,
-40911L,40912L,40913L,40914L,40915L,40916L,40917L,40918L,40919L,40920L,
-40921L,40922L,40923L,40924L,40925L,40926L,40927L,40928L,40929L,40930L,
-40931L,40932L,40933L,40934L,40935L,40936L,40937L,40938L,40939L,40940L,
-40941L,40942L,40943L,40944L,40945L,40946L,40947L,40948L,40949L,40950L,
-40951L,40952L,40953L,40954L,40955L,40956L,40957L,40958L,40959L,40960L,
-40961L,40962L,40963L,40964L,40965L,40966L,40967L,40968L,40969L,40970L,
-40971L,40972L,40973L,40974L,40975L,40976L,40977L,40978L,40979L,40980L,
-40981L,40982L,40983L,40984L,40985L,40986L,40987L,40988L,40989L,40990L,
-40991L,40992L,40993L,40994L,40995L,40996L,40997L,40998L,40999L,41000L,
-41001L,41002L,41003L,41004L,41005L,41006L,41007L,41008L,41009L,41010L,
-41011L,41012L,41013L,41014L,41015L,41016L,41017L,41018L,41019L,41020L,
-41021L,41022L,41023L,41024L,41025L,41026L,41027L,41028L,41029L,41030L,
-41031L,41032L,41033L,41034L,41035L,41036L,41037L,41038L,41039L,41040L,
-41041L,41042L,41043L,41044L,41045L,41046L,41047L,41048L,41049L,41050L,
-41051L,41052L,41053L,41054L,41055L,41056L,41057L,41058L,41059L,41060L,
-41061L,41062L,41063L,41064L,41065L,41066L,41067L,41068L,41069L,41070L,
-41071L,41072L,41073L,41074L,41075L,41076L,41077L,41078L,41079L,41080L,
-41081L,41082L,41083L,41084L,41085L,41086L,41087L,41088L,41089L,41090L,
-41091L,41092L,41093L,41094L,41095L,41096L,41097L,41098L,41099L,41100L,
-41101L,41102L,41103L,41104L,41105L,41106L,41107L,41108L,41109L,41110L,
-41111L,41112L,41113L,41114L,41115L,41116L,41117L,41118L,41119L,41120L,
-41121L,41122L,41123L,41124L,41125L,41126L,41127L,41128L,41129L,41130L,
-41131L,41132L,41133L,41134L,41135L,41136L,41137L,41138L,41139L,41140L,
-41141L,41142L,41143L,41144L,41145L,41146L,41147L,41148L,41149L,41150L,
-41151L,41152L,41153L,41154L,41155L,41156L,41157L,41158L,41159L,41160L,
-41161L,41162L,41163L,41164L,41165L,41166L,41167L,41168L,41169L,41170L,
-41171L,41172L,41173L,41174L,41175L,41176L,41177L,41178L,41179L,41180L,
-41181L,41182L,41183L,41184L,41185L,41186L,41187L,41188L,41189L,41190L,
-41191L,41192L,41193L,41194L,41195L,41196L,41197L,41198L,41199L,41200L,
-41201L,41202L,41203L,41204L,41205L,41206L,41207L,41208L,41209L,41210L,
-41211L,41212L,41213L,41214L,41215L,41216L,41217L,41218L,41219L,41220L,
-41221L,41222L,41223L,41224L,41225L,41226L,41227L,41228L,41229L,41230L,
-41231L,41232L,41233L,41234L,41235L,41236L,41237L,41238L,41239L,41240L,
-41241L,41242L,41243L,41244L,41245L,41246L,41247L,41248L,41249L,41250L,
-41251L,41252L,41253L,41254L,41255L,41256L,41257L,41258L,41259L,41260L,
-41261L,41262L,41263L,41264L,41265L,41266L,41267L,41268L,41269L,41270L,
-41271L,41272L,41273L,41274L,41275L,41276L,41277L,41278L,41279L,41280L,
-41281L,41282L,41283L,41284L,41285L,41286L,41287L,41288L,41289L,41290L,
-41291L,41292L,41293L,41294L,41295L,41296L,41297L,41298L,41299L,41300L,
-41301L,41302L,41303L,41304L,41305L,41306L,41307L,41308L,41309L,41310L,
-41311L,41312L,41313L,41314L,41315L,41316L,41317L,41318L,41319L,41320L,
-41321L,41322L,41323L,41324L,41325L,41326L,41327L,41328L,41329L,41330L,
-41331L,41332L,41333L,41334L,41335L,41336L,41337L,41338L,41339L,41340L,
-41341L,41342L,41343L,41344L,41345L,41346L,41347L,41348L,41349L,41350L,
-41351L,41352L,41353L,41354L,41355L,41356L,41357L,41358L,41359L,41360L,
-41361L,41362L,41363L,41364L,41365L,41366L,41367L,41368L,41369L,41370L,
-41371L,41372L,41373L,41374L,41375L,41376L,41377L,41378L,41379L,41380L,
-41381L,41382L,41383L,41384L,41385L,41386L,41387L,41388L,41389L,41390L,
-41391L,41392L,41393L,41394L,41395L,41396L,41397L,41398L,41399L,41400L,
-41401L,41402L,41403L,41404L,41405L,41406L,41407L,41408L,41409L,41410L,
-41411L,41412L,41413L,41414L,41415L,41416L,41417L,41418L,41419L,41420L,
-41421L,41422L,41423L,41424L,41425L,41426L,41427L,41428L,41429L,41430L,
-41431L,41432L,41433L,41434L,41435L,41436L,41437L,41438L,41439L,41440L,
-41441L,41442L,41443L,41444L,41445L,41446L,41447L,41448L,41449L,41450L,
-41451L,41452L,41453L,41454L,41455L,41456L,41457L,41458L,41459L,41460L,
-41461L,41462L,41463L,41464L,41465L,41466L,41467L,41468L,41469L,41470L,
-41471L,41472L,41473L,41474L,41475L,41476L,41477L,41478L,41479L,41480L,
-41481L,41482L,41483L,41484L,41485L,41486L,41487L,41488L,41489L,41490L,
-41491L,41492L,41493L,41494L,41495L,41496L,41497L,41498L,41499L,41500L,
-41501L,41502L,41503L,41504L,41505L,41506L,41507L,41508L,41509L,41510L,
-41511L,41512L,41513L,41514L,41515L,41516L,41517L,41518L,41519L,41520L,
-41521L,41522L,41523L,41524L,41525L,41526L,41527L,41528L,41529L,41530L,
-41531L,41532L,41533L,41534L,41535L,41536L,41537L,41538L,41539L,41540L,
-41541L,41542L,41543L,41544L,41545L,41546L,41547L,41548L,41549L,41550L,
-41551L,41552L,41553L,41554L,41555L,41556L,41557L,41558L,41559L,41560L,
-41561L,41562L,41563L,41564L,41565L,41566L,41567L,41568L,41569L,41570L,
-41571L,41572L,41573L,41574L,41575L,41576L,41577L,41578L,41579L,41580L,
-41581L,41582L,41583L,41584L,41585L,41586L,41587L,41588L,41589L,41590L,
-41591L,41592L,41593L,41594L,41595L,41596L,41597L,41598L,41599L,41600L,
-41601L,41602L,41603L,41604L,41605L,41606L,41607L,41608L,41609L,41610L,
-41611L,41612L,41613L,41614L,41615L,41616L,41617L,41618L,41619L,41620L,
-41621L,41622L,41623L,41624L,41625L,41626L,41627L,41628L,41629L,41630L,
-41631L,41632L,41633L,41634L,41635L,41636L,41637L,41638L,41639L,41640L,
-41641L,41642L,41643L,41644L,41645L,41646L,41647L,41648L,41649L,41650L,
-41651L,41652L,41653L,41654L,41655L,41656L,41657L,41658L,41659L,41660L,
-41661L,41662L,41663L,41664L,41665L,41666L,41667L,41668L,41669L,41670L,
-41671L,41672L,41673L,41674L,41675L,41676L,41677L,41678L,41679L,41680L,
-41681L,41682L,41683L,41684L,41685L,41686L,41687L,41688L,41689L,41690L,
-41691L,41692L,41693L,41694L,41695L,41696L,41697L,41698L,41699L,41700L,
-41701L,41702L,41703L,41704L,41705L,41706L,41707L,41708L,41709L,41710L,
-41711L,41712L,41713L,41714L,41715L,41716L,41717L,41718L,41719L,41720L,
-41721L,41722L,41723L,41724L,41725L,41726L,41727L,41728L,41729L,41730L,
-41731L,41732L,41733L,41734L,41735L,41736L,41737L,41738L,41739L,41740L,
-41741L,41742L,41743L,41744L,41745L,41746L,41747L,41748L,41749L,41750L,
-41751L,41752L,41753L,41754L,41755L,41756L,41757L,41758L,41759L,41760L,
-41761L,41762L,41763L,41764L,41765L,41766L,41767L,41768L,41769L,41770L,
-41771L,41772L,41773L,41774L,41775L,41776L,41777L,41778L,41779L,41780L,
-41781L,41782L,41783L,41784L,41785L,41786L,41787L,41788L,41789L,41790L,
-41791L,41792L,41793L,41794L,41795L,41796L,41797L,41798L,41799L,41800L,
-41801L,41802L,41803L,41804L,41805L,41806L,41807L,41808L,41809L,41810L,
-41811L,41812L,41813L,41814L,41815L,41816L,41817L,41818L,41819L,41820L,
-41821L,41822L,41823L,41824L,41825L,41826L,41827L,41828L,41829L,41830L,
-41831L,41832L,41833L,41834L,41835L,41836L,41837L,41838L,41839L,41840L,
-41841L,41842L,41843L,41844L,41845L,41846L,41847L,41848L,41849L,41850L,
-41851L,41852L,41853L,41854L,41855L,41856L,41857L,41858L,41859L,41860L,
-41861L,41862L,41863L,41864L,41865L,41866L,41867L,41868L,41869L,41870L,
-41871L,41872L,41873L,41874L,41875L,41876L,41877L,41878L,41879L,41880L,
-41881L,41882L,41883L,41884L,41885L,41886L,41887L,41888L,41889L,41890L,
-41891L,41892L,41893L,41894L,41895L,41896L,41897L,41898L,41899L,41900L,
-41901L,41902L,41903L,41904L,41905L,41906L,41907L,41908L,41909L,41910L,
-41911L,41912L,41913L,41914L,41915L,41916L,41917L,41918L,41919L,41920L,
-41921L,41922L,41923L,41924L,41925L,41926L,41927L,41928L,41929L,41930L,
-41931L,41932L,41933L,41934L,41935L,41936L,41937L,41938L,41939L,41940L,
-41941L,41942L,41943L,41944L,41945L,41946L,41947L,41948L,41949L,41950L,
-41951L,41952L,41953L,41954L,41955L,41956L,41957L,41958L,41959L,41960L,
-41961L,41962L,41963L,41964L,41965L,41966L,41967L,41968L,41969L,41970L,
-41971L,41972L,41973L,41974L,41975L,41976L,41977L,41978L,41979L,41980L,
-41981L,41982L,41983L,41984L,41985L,41986L,41987L,41988L,41989L,41990L,
-41991L,41992L,41993L,41994L,41995L,41996L,41997L,41998L,41999L,42000L,
-42001L,42002L,42003L,42004L,42005L,42006L,42007L,42008L,42009L,42010L,
-42011L,42012L,42013L,42014L,42015L,42016L,42017L,42018L,42019L,42020L,
-42021L,42022L,42023L,42024L,42025L,42026L,42027L,42028L,42029L,42030L,
-42031L,42032L,42033L,42034L,42035L,42036L,42037L,42038L,42039L,42040L,
-42041L,42042L,42043L,42044L,42045L,42046L,42047L,42048L,42049L,42050L,
-42051L,42052L,42053L,42054L,42055L,42056L,42057L,42058L,42059L,42060L,
-42061L,42062L,42063L,42064L,42065L,42066L,42067L,42068L,42069L,42070L,
-42071L,42072L,42073L,42074L,42075L,42076L,42077L,42078L,42079L,42080L,
-42081L,42082L,42083L,42084L,42085L,42086L,42087L,42088L,42089L,42090L,
-42091L,42092L,42093L,42094L,42095L,42096L,42097L,42098L,42099L,42100L,
-42101L,42102L,42103L,42104L,42105L,42106L,42107L,42108L,42109L,42110L,
-42111L,42112L,42113L,42114L,42115L,42116L,42117L,42118L,42119L,42120L,
-42121L,42122L,42123L,42124L,42125L,42126L,42127L,42128L,42129L,42130L,
-42131L,42132L,42133L,42134L,42135L,42136L,42137L,42138L,42139L,42140L,
-42141L,42142L,42143L,42144L,42145L,42146L,42147L,42148L,42149L,42150L,
-42151L,42152L,42153L,42154L,42155L,42156L,42157L,42158L,42159L,42160L,
-42161L,42162L,42163L,42164L,42165L,42166L,42167L,42168L,42169L,42170L,
-42171L,42172L,42173L,42174L,42175L,42176L,42177L,42178L,42179L,42180L,
-42181L,42182L,42183L,42184L,42185L,42186L,42187L,42188L,42189L,42190L,
-42191L,42192L,42193L,42194L,42195L,42196L,42197L,42198L,42199L,42200L,
-42201L,42202L,42203L,42204L,42205L,42206L,42207L,42208L,42209L,42210L,
-42211L,42212L,42213L,42214L,42215L,42216L,42217L,42218L,42219L,42220L,
-42221L,42222L,42223L,42224L,42225L,42226L,42227L,42228L,42229L,42230L,
-42231L,42232L,42233L,42234L,42235L,42236L,42237L,42238L,42239L,42240L,
-42241L,42242L,42243L,42244L,42245L,42246L,42247L,42248L,42249L,42250L,
-42251L,42252L,42253L,42254L,42255L,42256L,42257L,42258L,42259L,42260L,
-42261L,42262L,42263L,42264L,42265L,42266L,42267L,42268L,42269L,42270L,
-42271L,42272L,42273L,42274L,42275L,42276L,42277L,42278L,42279L,42280L,
-42281L,42282L,42283L,42284L,42285L,42286L,42287L,42288L,42289L,42290L,
-42291L,42292L,42293L,42294L,42295L,42296L,42297L,42298L,42299L,42300L,
-42301L,42302L,42303L,42304L,42305L,42306L,42307L,42308L,42309L,42310L,
-42311L,42312L,42313L,42314L,42315L,42316L,42317L,42318L,42319L,42320L,
-42321L,42322L,42323L,42324L,42325L,42326L,42327L,42328L,42329L,42330L,
-42331L,42332L,42333L,42334L,42335L,42336L,42337L,42338L,42339L,42340L,
-42341L,42342L,42343L,42344L,42345L,42346L,42347L,42348L,42349L,42350L,
-42351L,42352L,42353L,42354L,42355L,42356L,42357L,42358L,42359L,42360L,
-42361L,42362L,42363L,42364L,42365L,42366L,42367L,42368L,42369L,42370L,
-42371L,42372L,42373L,42374L,42375L,42376L,42377L,42378L,42379L,42380L,
-42381L,42382L,42383L,42384L,42385L,42386L,42387L,42388L,42389L,42390L,
-42391L,42392L,42393L,42394L,42395L,42396L,42397L,42398L,42399L,42400L,
-42401L,42402L,42403L,42404L,42405L,42406L,42407L,42408L,42409L,42410L,
-42411L,42412L,42413L,42414L,42415L,42416L,42417L,42418L,42419L,42420L,
-42421L,42422L,42423L,42424L,42425L,42426L,42427L,42428L,42429L,42430L,
-42431L,42432L,42433L,42434L,42435L,42436L,42437L,42438L,42439L,42440L,
-42441L,42442L,42443L,42444L,42445L,42446L,42447L,42448L,42449L,42450L,
-42451L,42452L,42453L,42454L,42455L,42456L,42457L,42458L,42459L,42460L,
-42461L,42462L,42463L,42464L,42465L,42466L,42467L,42468L,42469L,42470L,
-42471L,42472L,42473L,42474L,42475L,42476L,42477L,42478L,42479L,42480L,
-42481L,42482L,42483L,42484L,42485L,42486L,42487L,42488L,42489L,42490L,
-42491L,42492L,42493L,42494L,42495L,42496L,42497L,42498L,42499L,42500L,
-42501L,42502L,42503L,42504L,42505L,42506L,42507L,42508L,42509L,42510L,
-42511L,42512L,42513L,42514L,42515L,42516L,42517L,42518L,42519L,42520L,
-42521L,42522L,42523L,42524L,42525L,42526L,42527L,42528L,42529L,42530L,
-42531L,42532L,42533L,42534L,42535L,42536L,42537L,42538L,42539L,42540L,
-42541L,42542L,42543L,42544L,42545L,42546L,42547L,42548L,42549L,42550L,
-42551L,42552L,42553L,42554L,42555L,42556L,42557L,42558L,42559L,42560L,
-42560L,42562L,42562L,42564L,42564L,42566L,42566L,42568L,42568L,42570L,
-42570L,42572L,42572L,42574L,42574L,42576L,42576L,42578L,42578L,42580L,
-42580L,42582L,42582L,42584L,42584L,42586L,42586L,42588L,42588L,42590L,
-42590L,42592L,42592L,42594L,42594L,42596L,42596L,42598L,42598L,42600L,
-42600L,42602L,42602L,42604L,42604L,42606L,42607L,42608L,42609L,42610L,
-42611L,42612L,42613L,42614L,42615L,42616L,42617L,42618L,42619L,42620L,
-42621L,42622L,42623L,42624L,42624L,42626L,42626L,42628L,42628L,42630L,
-42630L,42632L,42632L,42634L,42634L,42636L,42636L,42638L,42638L,42640L,
-42640L,42642L,42642L,42644L,42644L,42646L,42646L,42648L,42648L,42650L,
-42650L,42652L,42653L,42654L,42655L,42656L,42657L,42658L,42659L,42660L,
-42661L,42662L,42663L,42664L,42665L,42666L,42667L,42668L,42669L,42670L,
-42671L,42672L,42673L,42674L,42675L,42676L,42677L,42678L,42679L,42680L,
-42681L,42682L,42683L,42684L,42685L,42686L,42687L,42688L,42689L,42690L,
-42691L,42692L,42693L,42694L,42695L,42696L,42697L,42698L,42699L,42700L,
-42701L,42702L,42703L,42704L,42705L,42706L,42707L,42708L,42709L,42710L,
-42711L,42712L,42713L,42714L,42715L,42716L,42717L,42718L,42719L,42720L,
-42721L,42722L,42723L,42724L,42725L,42726L,42727L,42728L,42729L,42730L,
-42731L,42732L,42733L,42734L,42735L,42736L,42737L,42738L,42739L,42740L,
-42741L,42742L,42743L,42744L,42745L,42746L,42747L,42748L,42749L,42750L,
-42751L,42752L,42753L,42754L,42755L,42756L,42757L,42758L,42759L,42760L,
-42761L,42762L,42763L,42764L,42765L,42766L,42767L,42768L,42769L,42770L,
-42771L,42772L,42773L,42774L,42775L,42776L,42777L,42778L,42779L,42780L,
-42781L,42782L,42783L,42784L,42785L,42786L,42786L,42788L,42788L,42790L,
-42790L,42792L,42792L,42794L,42794L,42796L,42796L,42798L,42798L,42800L,
-42801L,42802L,42802L,42804L,42804L,42806L,42806L,42808L,42808L,42810L,
-42810L,42812L,42812L,42814L,42814L,42816L,42816L,42818L,42818L,42820L,
-42820L,42822L,42822L,42824L,42824L,42826L,42826L,42828L,42828L,42830L,
-42830L,42832L,42832L,42834L,42834L,42836L,42836L,42838L,42838L,42840L,
-42840L,42842L,42842L,42844L,42844L,42846L,42846L,42848L,42848L,42850L,
-42850L,42852L,42852L,42854L,42854L,42856L,42856L,42858L,42858L,42860L,
-42860L,42862L,42862L,42864L,42865L,42866L,42867L,42868L,42869L,42870L,
-42871L,42872L,42873L,42873L,42875L,42875L,42877L,42878L,42878L,42880L,
-42880L,42882L,42882L,42884L,42884L,42886L,42886L,42888L,42889L,42890L,
-42891L,42891L,42893L,42894L,42895L,42896L,42896L,42898L,42898L,42900L,
-42901L,42902L,42902L,42904L,42904L,42906L,42906L,42908L,42908L,42910L,
-42910L,42912L,42912L,42914L,42914L,42916L,42916L,42918L,42918L,42920L,
-42920L,42922L,42923L,42924L,42925L,42926L,42927L,42928L,42929L,42930L,
-42931L,42932L,42932L,42934L,42934L,42936L,42937L,42938L,42939L,42940L,
-42941L,42942L,42943L,42944L,42945L,42946L,42947L,42948L,42949L,42950L,
-42951L,42952L,42953L,42954L,42955L,42956L,42957L,42958L,42959L,42960L,
-42961L,42962L,42963L,42964L,42965L,42966L,42967L,42968L,42969L,42970L,
-42971L,42972L,42973L,42974L,42975L,42976L,42977L,42978L,42979L,42980L,
-42981L,42982L,42983L,42984L,42985L,42986L,42987L,42988L,42989L,42990L,
-42991L,42992L,42993L,42994L,42995L,42996L,42997L,42998L,42999L,43000L,
-43001L,43002L,43003L,43004L,43005L,43006L,43007L,43008L,43009L,43010L,
-43011L,43012L,43013L,43014L,43015L,43016L,43017L,43018L,43019L,43020L,
-43021L,43022L,43023L,43024L,43025L,43026L,43027L,43028L,43029L,43030L,
-43031L,43032L,43033L,43034L,43035L,43036L,43037L,43038L,43039L,43040L,
-43041L,43042L,43043L,43044L,43045L,43046L,43047L,43048L,43049L,43050L,
-43051L,43052L,43053L,43054L,43055L,43056L,43057L,43058L,43059L,43060L,
-43061L,43062L,43063L,43064L,43065L,43066L,43067L,43068L,43069L,43070L,
-43071L,43072L,43073L,43074L,43075L,43076L,43077L,43078L,43079L,43080L,
-43081L,43082L,43083L,43084L,43085L,43086L,43087L,43088L,43089L,43090L,
-43091L,43092L,43093L,43094L,43095L,43096L,43097L,43098L,43099L,43100L,
-43101L,43102L,43103L,43104L,43105L,43106L,43107L,43108L,43109L,43110L,
-43111L,43112L,43113L,43114L,43115L,43116L,43117L,43118L,43119L,43120L,
-43121L,43122L,43123L,43124L,43125L,43126L,43127L,43128L,43129L,43130L,
-43131L,43132L,43133L,43134L,43135L,43136L,43137L,43138L,43139L,43140L,
-43141L,43142L,43143L,43144L,43145L,43146L,43147L,43148L,43149L,43150L,
-43151L,43152L,43153L,43154L,43155L,43156L,43157L,43158L,43159L,43160L,
-43161L,43162L,43163L,43164L,43165L,43166L,43167L,43168L,43169L,43170L,
-43171L,43172L,43173L,43174L,43175L,43176L,43177L,43178L,43179L,43180L,
-43181L,43182L,43183L,43184L,43185L,43186L,43187L,43188L,43189L,43190L,
-43191L,43192L,43193L,43194L,43195L,43196L,43197L,43198L,43199L,43200L,
-43201L,43202L,43203L,43204L,43205L,43206L,43207L,43208L,43209L,43210L,
-43211L,43212L,43213L,43214L,43215L,43216L,43217L,43218L,43219L,43220L,
-43221L,43222L,43223L,43224L,43225L,43226L,43227L,43228L,43229L,43230L,
-43231L,43232L,43233L,43234L,43235L,43236L,43237L,43238L,43239L,43240L,
-43241L,43242L,43243L,43244L,43245L,43246L,43247L,43248L,43249L,43250L,
-43251L,43252L,43253L,43254L,43255L,43256L,43257L,43258L,43259L,43260L,
-43261L,43262L,43263L,43264L,43265L,43266L,43267L,43268L,43269L,43270L,
-43271L,43272L,43273L,43274L,43275L,43276L,43277L,43278L,43279L,43280L,
-43281L,43282L,43283L,43284L,43285L,43286L,43287L,43288L,43289L,43290L,
-43291L,43292L,43293L,43294L,43295L,43296L,43297L,43298L,43299L,43300L,
-43301L,43302L,43303L,43304L,43305L,43306L,43307L,43308L,43309L,43310L,
-43311L,43312L,43313L,43314L,43315L,43316L,43317L,43318L,43319L,43320L,
-43321L,43322L,43323L,43324L,43325L,43326L,43327L,43328L,43329L,43330L,
-43331L,43332L,43333L,43334L,43335L,43336L,43337L,43338L,43339L,43340L,
-43341L,43342L,43343L,43344L,43345L,43346L,43347L,43348L,43349L,43350L,
-43351L,43352L,43353L,43354L,43355L,43356L,43357L,43358L,43359L,43360L,
-43361L,43362L,43363L,43364L,43365L,43366L,43367L,43368L,43369L,43370L,
-43371L,43372L,43373L,43374L,43375L,43376L,43377L,43378L,43379L,43380L,
-43381L,43382L,43383L,43384L,43385L,43386L,43387L,43388L,43389L,43390L,
-43391L,43392L,43393L,43394L,43395L,43396L,43397L,43398L,43399L,43400L,
-43401L,43402L,43403L,43404L,43405L,43406L,43407L,43408L,43409L,43410L,
-43411L,43412L,43413L,43414L,43415L,43416L,43417L,43418L,43419L,43420L,
-43421L,43422L,43423L,43424L,43425L,43426L,43427L,43428L,43429L,43430L,
-43431L,43432L,43433L,43434L,43435L,43436L,43437L,43438L,43439L,43440L,
-43441L,43442L,43443L,43444L,43445L,43446L,43447L,43448L,43449L,43450L,
-43451L,43452L,43453L,43454L,43455L,43456L,43457L,43458L,43459L,43460L,
-43461L,43462L,43463L,43464L,43465L,43466L,43467L,43468L,43469L,43470L,
-43471L,43472L,43473L,43474L,43475L,43476L,43477L,43478L,43479L,43480L,
-43481L,43482L,43483L,43484L,43485L,43486L,43487L,43488L,43489L,43490L,
-43491L,43492L,43493L,43494L,43495L,43496L,43497L,43498L,43499L,43500L,
-43501L,43502L,43503L,43504L,43505L,43506L,43507L,43508L,43509L,43510L,
-43511L,43512L,43513L,43514L,43515L,43516L,43517L,43518L,43519L,43520L,
-43521L,43522L,43523L,43524L,43525L,43526L,43527L,43528L,43529L,43530L,
-43531L,43532L,43533L,43534L,43535L,43536L,43537L,43538L,43539L,43540L,
-43541L,43542L,43543L,43544L,43545L,43546L,43547L,43548L,43549L,43550L,
-43551L,43552L,43553L,43554L,43555L,43556L,43557L,43558L,43559L,43560L,
-43561L,43562L,43563L,43564L,43565L,43566L,43567L,43568L,43569L,43570L,
-43571L,43572L,43573L,43574L,43575L,43576L,43577L,43578L,43579L,43580L,
-43581L,43582L,43583L,43584L,43585L,43586L,43587L,43588L,43589L,43590L,
-43591L,43592L,43593L,43594L,43595L,43596L,43597L,43598L,43599L,43600L,
-43601L,43602L,43603L,43604L,43605L,43606L,43607L,43608L,43609L,43610L,
-43611L,43612L,43613L,43614L,43615L,43616L,43617L,43618L,43619L,43620L,
-43621L,43622L,43623L,43624L,43625L,43626L,43627L,43628L,43629L,43630L,
-43631L,43632L,43633L,43634L,43635L,43636L,43637L,43638L,43639L,43640L,
-43641L,43642L,43643L,43644L,43645L,43646L,43647L,43648L,43649L,43650L,
-43651L,43652L,43653L,43654L,43655L,43656L,43657L,43658L,43659L,43660L,
-43661L,43662L,43663L,43664L,43665L,43666L,43667L,43668L,43669L,43670L,
-43671L,43672L,43673L,43674L,43675L,43676L,43677L,43678L,43679L,43680L,
-43681L,43682L,43683L,43684L,43685L,43686L,43687L,43688L,43689L,43690L,
-43691L,43692L,43693L,43694L,43695L,43696L,43697L,43698L,43699L,43700L,
-43701L,43702L,43703L,43704L,43705L,43706L,43707L,43708L,43709L,43710L,
-43711L,43712L,43713L,43714L,43715L,43716L,43717L,43718L,43719L,43720L,
-43721L,43722L,43723L,43724L,43725L,43726L,43727L,43728L,43729L,43730L,
-43731L,43732L,43733L,43734L,43735L,43736L,43737L,43738L,43739L,43740L,
-43741L,43742L,43743L,43744L,43745L,43746L,43747L,43748L,43749L,43750L,
-43751L,43752L,43753L,43754L,43755L,43756L,43757L,43758L,43759L,43760L,
-43761L,43762L,43763L,43764L,43765L,43766L,43767L,43768L,43769L,43770L,
-43771L,43772L,43773L,43774L,43775L,43776L,43777L,43778L,43779L,43780L,
-43781L,43782L,43783L,43784L,43785L,43786L,43787L,43788L,43789L,43790L,
-43791L,43792L,43793L,43794L,43795L,43796L,43797L,43798L,43799L,43800L,
-43801L,43802L,43803L,43804L,43805L,43806L,43807L,43808L,43809L,43810L,
-43811L,43812L,43813L,43814L,43815L,43816L,43817L,43818L,43819L,43820L,
-43821L,43822L,43823L,43824L,43825L,43826L,43827L,43828L,43829L,43830L,
-43831L,43832L,43833L,43834L,43835L,43836L,43837L,43838L,43839L,43840L,
-43841L,43842L,43843L,43844L,43845L,43846L,43847L,43848L,43849L,43850L,
-43851L,43852L,43853L,43854L,43855L,43856L,43857L,43858L,42931L,43860L,
-43861L,43862L,43863L,43864L,43865L,43866L,43867L,43868L,43869L,43870L,
-43871L,43872L,43873L,43874L,43875L,43876L,43877L,43878L,43879L,43880L,
-43881L,43882L,43883L,43884L,43885L,43886L,43887L,5024,5025,5026,5027,5028,
-5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,5040,5041,5042,5043,
-5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,5055,5056,5057,5058,
-5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,
-5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,
-5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,
-43968L,43969L,43970L,43971L,43972L,43973L,43974L,43975L,43976L,43977L,
-43978L,43979L,43980L,43981L,43982L,43983L,43984L,43985L,43986L,43987L,
-43988L,43989L,43990L,43991L,43992L,43993L,43994L,43995L,43996L,43997L,
-43998L,43999L,44000L,44001L,44002L,44003L,44004L,44005L,44006L,44007L,
-44008L,44009L,44010L,44011L,44012L,44013L,44014L,44015L,44016L,44017L,
-44018L,44019L,44020L,44021L,44022L,44023L,44024L,44025L,44026L,44027L,
-44028L,44029L,44030L,44031L,44032L,44033L,44034L,44035L,44036L,44037L,
-44038L,44039L,44040L,44041L,44042L,44043L,44044L,44045L,44046L,44047L,
-44048L,44049L,44050L,44051L,44052L,44053L,44054L,44055L,44056L,44057L,
-44058L,44059L,44060L,44061L,44062L,44063L,44064L,44065L,44066L,44067L,
-44068L,44069L,44070L,44071L,44072L,44073L,44074L,44075L,44076L,44077L,
-44078L,44079L,44080L,44081L,44082L,44083L,44084L,44085L,44086L,44087L,
-44088L,44089L,44090L,44091L,44092L,44093L,44094L,44095L,44096L,44097L,
-44098L,44099L,44100L,44101L,44102L,44103L,44104L,44105L,44106L,44107L,
-44108L,44109L,44110L,44111L,44112L,44113L,44114L,44115L,44116L,44117L,
-44118L,44119L,44120L,44121L,44122L,44123L,44124L,44125L,44126L,44127L,
-44128L,44129L,44130L,44131L,44132L,44133L,44134L,44135L,44136L,44137L,
-44138L,44139L,44140L,44141L,44142L,44143L,44144L,44145L,44146L,44147L,
-44148L,44149L,44150L,44151L,44152L,44153L,44154L,44155L,44156L,44157L,
-44158L,44159L,44160L,44161L,44162L,44163L,44164L,44165L,44166L,44167L,
-44168L,44169L,44170L,44171L,44172L,44173L,44174L,44175L,44176L,44177L,
-44178L,44179L,44180L,44181L,44182L,44183L,44184L,44185L,44186L,44187L,
-44188L,44189L,44190L,44191L,44192L,44193L,44194L,44195L,44196L,44197L,
-44198L,44199L,44200L,44201L,44202L,44203L,44204L,44205L,44206L,44207L,
-44208L,44209L,44210L,44211L,44212L,44213L,44214L,44215L,44216L,44217L,
-44218L,44219L,44220L,44221L,44222L,44223L,44224L,44225L,44226L,44227L,
-44228L,44229L,44230L,44231L,44232L,44233L,44234L,44235L,44236L,44237L,
-44238L,44239L,44240L,44241L,44242L,44243L,44244L,44245L,44246L,44247L,
-44248L,44249L,44250L,44251L,44252L,44253L,44254L,44255L,44256L,44257L,
-44258L,44259L,44260L,44261L,44262L,44263L,44264L,44265L,44266L,44267L,
-44268L,44269L,44270L,44271L,44272L,44273L,44274L,44275L,44276L,44277L,
-44278L,44279L,44280L,44281L,44282L,44283L,44284L,44285L,44286L,44287L,
-44288L,44289L,44290L,44291L,44292L,44293L,44294L,44295L,44296L,44297L,
-44298L,44299L,44300L,44301L,44302L,44303L,44304L,44305L,44306L,44307L,
-44308L,44309L,44310L,44311L,44312L,44313L,44314L,44315L,44316L,44317L,
-44318L,44319L,44320L,44321L,44322L,44323L,44324L,44325L,44326L,44327L,
-44328L,44329L,44330L,44331L,44332L,44333L,44334L,44335L,44336L,44337L,
-44338L,44339L,44340L,44341L,44342L,44343L,44344L,44345L,44346L,44347L,
-44348L,44349L,44350L,44351L,44352L,44353L,44354L,44355L,44356L,44357L,
-44358L,44359L,44360L,44361L,44362L,44363L,44364L,44365L,44366L,44367L,
-44368L,44369L,44370L,44371L,44372L,44373L,44374L,44375L,44376L,44377L,
-44378L,44379L,44380L,44381L,44382L,44383L,44384L,44385L,44386L,44387L,
-44388L,44389L,44390L,44391L,44392L,44393L,44394L,44395L,44396L,44397L,
-44398L,44399L,44400L,44401L,44402L,44403L,44404L,44405L,44406L,44407L,
-44408L,44409L,44410L,44411L,44412L,44413L,44414L,44415L,44416L,44417L,
-44418L,44419L,44420L,44421L,44422L,44423L,44424L,44425L,44426L,44427L,
-44428L,44429L,44430L,44431L,44432L,44433L,44434L,44435L,44436L,44437L,
-44438L,44439L,44440L,44441L,44442L,44443L,44444L,44445L,44446L,44447L,
-44448L,44449L,44450L,44451L,44452L,44453L,44454L,44455L,44456L,44457L,
-44458L,44459L,44460L,44461L,44462L,44463L,44464L,44465L,44466L,44467L,
-44468L,44469L,44470L,44471L,44472L,44473L,44474L,44475L,44476L,44477L,
-44478L,44479L,44480L,44481L,44482L,44483L,44484L,44485L,44486L,44487L,
-44488L,44489L,44490L,44491L,44492L,44493L,44494L,44495L,44496L,44497L,
-44498L,44499L,44500L,44501L,44502L,44503L,44504L,44505L,44506L,44507L,
-44508L,44509L,44510L,44511L,44512L,44513L,44514L,44515L,44516L,44517L,
-44518L,44519L,44520L,44521L,44522L,44523L,44524L,44525L,44526L,44527L,
-44528L,44529L,44530L,44531L,44532L,44533L,44534L,44535L,44536L,44537L,
-44538L,44539L,44540L,44541L,44542L,44543L,44544L,44545L,44546L,44547L,
-44548L,44549L,44550L,44551L,44552L,44553L,44554L,44555L,44556L,44557L,
-44558L,44559L,44560L,44561L,44562L,44563L,44564L,44565L,44566L,44567L,
-44568L,44569L,44570L,44571L,44572L,44573L,44574L,44575L,44576L,44577L,
-44578L,44579L,44580L,44581L,44582L,44583L,44584L,44585L,44586L,44587L,
-44588L,44589L,44590L,44591L,44592L,44593L,44594L,44595L,44596L,44597L,
-44598L,44599L,44600L,44601L,44602L,44603L,44604L,44605L,44606L,44607L,
-44608L,44609L,44610L,44611L,44612L,44613L,44614L,44615L,44616L,44617L,
-44618L,44619L,44620L,44621L,44622L,44623L,44624L,44625L,44626L,44627L,
-44628L,44629L,44630L,44631L,44632L,44633L,44634L,44635L,44636L,44637L,
-44638L,44639L,44640L,44641L,44642L,44643L,44644L,44645L,44646L,44647L,
-44648L,44649L,44650L,44651L,44652L,44653L,44654L,44655L,44656L,44657L,
-44658L,44659L,44660L,44661L,44662L,44663L,44664L,44665L,44666L,44667L,
-44668L,44669L,44670L,44671L,44672L,44673L,44674L,44675L,44676L,44677L,
-44678L,44679L,44680L,44681L,44682L,44683L,44684L,44685L,44686L,44687L,
-44688L,44689L,44690L,44691L,44692L,44693L,44694L,44695L,44696L,44697L,
-44698L,44699L,44700L,44701L,44702L,44703L,44704L,44705L,44706L,44707L,
-44708L,44709L,44710L,44711L,44712L,44713L,44714L,44715L,44716L,44717L,
-44718L,44719L,44720L,44721L,44722L,44723L,44724L,44725L,44726L,44727L,
-44728L,44729L,44730L,44731L,44732L,44733L,44734L,44735L,44736L,44737L,
-44738L,44739L,44740L,44741L,44742L,44743L,44744L,44745L,44746L,44747L,
-44748L,44749L,44750L,44751L,44752L,44753L,44754L,44755L,44756L,44757L,
-44758L,44759L,44760L,44761L,44762L,44763L,44764L,44765L,44766L,44767L,
-44768L,44769L,44770L,44771L,44772L,44773L,44774L,44775L,44776L,44777L,
-44778L,44779L,44780L,44781L,44782L,44783L,44784L,44785L,44786L,44787L,
-44788L,44789L,44790L,44791L,44792L,44793L,44794L,44795L,44796L,44797L,
-44798L,44799L,44800L,44801L,44802L,44803L,44804L,44805L,44806L,44807L,
-44808L,44809L,44810L,44811L,44812L,44813L,44814L,44815L,44816L,44817L,
-44818L,44819L,44820L,44821L,44822L,44823L,44824L,44825L,44826L,44827L,
-44828L,44829L,44830L,44831L,44832L,44833L,44834L,44835L,44836L,44837L,
-44838L,44839L,44840L,44841L,44842L,44843L,44844L,44845L,44846L,44847L,
-44848L,44849L,44850L,44851L,44852L,44853L,44854L,44855L,44856L,44857L,
-44858L,44859L,44860L,44861L,44862L,44863L,44864L,44865L,44866L,44867L,
-44868L,44869L,44870L,44871L,44872L,44873L,44874L,44875L,44876L,44877L,
-44878L,44879L,44880L,44881L,44882L,44883L,44884L,44885L,44886L,44887L,
-44888L,44889L,44890L,44891L,44892L,44893L,44894L,44895L,44896L,44897L,
-44898L,44899L,44900L,44901L,44902L,44903L,44904L,44905L,44906L,44907L,
-44908L,44909L,44910L,44911L,44912L,44913L,44914L,44915L,44916L,44917L,
-44918L,44919L,44920L,44921L,44922L,44923L,44924L,44925L,44926L,44927L,
-44928L,44929L,44930L,44931L,44932L,44933L,44934L,44935L,44936L,44937L,
-44938L,44939L,44940L,44941L,44942L,44943L,44944L,44945L,44946L,44947L,
-44948L,44949L,44950L,44951L,44952L,44953L,44954L,44955L,44956L,44957L,
-44958L,44959L,44960L,44961L,44962L,44963L,44964L,44965L,44966L,44967L,
-44968L,44969L,44970L,44971L,44972L,44973L,44974L,44975L,44976L,44977L,
-44978L,44979L,44980L,44981L,44982L,44983L,44984L,44985L,44986L,44987L,
-44988L,44989L,44990L,44991L,44992L,44993L,44994L,44995L,44996L,44997L,
-44998L,44999L,45000L,45001L,45002L,45003L,45004L,45005L,45006L,45007L,
-45008L,45009L,45010L,45011L,45012L,45013L,45014L,45015L,45016L,45017L,
-45018L,45019L,45020L,45021L,45022L,45023L,45024L,45025L,45026L,45027L,
-45028L,45029L,45030L,45031L,45032L,45033L,45034L,45035L,45036L,45037L,
-45038L,45039L,45040L,45041L,45042L,45043L,45044L,45045L,45046L,45047L,
-45048L,45049L,45050L,45051L,45052L,45053L,45054L,45055L,45056L,45057L,
-45058L,45059L,45060L,45061L,45062L,45063L,45064L,45065L,45066L,45067L,
-45068L,45069L,45070L,45071L,45072L,45073L,45074L,45075L,45076L,45077L,
-45078L,45079L,45080L,45081L,45082L,45083L,45084L,45085L,45086L,45087L,
-45088L,45089L,45090L,45091L,45092L,45093L,45094L,45095L,45096L,45097L,
-45098L,45099L,45100L,45101L,45102L,45103L,45104L,45105L,45106L,45107L,
-45108L,45109L,45110L,45111L,45112L,45113L,45114L,45115L,45116L,45117L,
-45118L,45119L,45120L,45121L,45122L,45123L,45124L,45125L,45126L,45127L,
-45128L,45129L,45130L,45131L,45132L,45133L,45134L,45135L,45136L,45137L,
-45138L,45139L,45140L,45141L,45142L,45143L,45144L,45145L,45146L,45147L,
-45148L,45149L,45150L,45151L,45152L,45153L,45154L,45155L,45156L,45157L,
-45158L,45159L,45160L,45161L,45162L,45163L,45164L,45165L,45166L,45167L,
-45168L,45169L,45170L,45171L,45172L,45173L,45174L,45175L,45176L,45177L,
-45178L,45179L,45180L,45181L,45182L,45183L,45184L,45185L,45186L,45187L,
-45188L,45189L,45190L,45191L,45192L,45193L,45194L,45195L,45196L,45197L,
-45198L,45199L,45200L,45201L,45202L,45203L,45204L,45205L,45206L,45207L,
-45208L,45209L,45210L,45211L,45212L,45213L,45214L,45215L,45216L,45217L,
-45218L,45219L,45220L,45221L,45222L,45223L,45224L,45225L,45226L,45227L,
-45228L,45229L,45230L,45231L,45232L,45233L,45234L,45235L,45236L,45237L,
-45238L,45239L,45240L,45241L,45242L,45243L,45244L,45245L,45246L,45247L,
-45248L,45249L,45250L,45251L,45252L,45253L,45254L,45255L,45256L,45257L,
-45258L,45259L,45260L,45261L,45262L,45263L,45264L,45265L,45266L,45267L,
-45268L,45269L,45270L,45271L,45272L,45273L,45274L,45275L,45276L,45277L,
-45278L,45279L,45280L,45281L,45282L,45283L,45284L,45285L,45286L,45287L,
-45288L,45289L,45290L,45291L,45292L,45293L,45294L,45295L,45296L,45297L,
-45298L,45299L,45300L,45301L,45302L,45303L,45304L,45305L,45306L,45307L,
-45308L,45309L,45310L,45311L,45312L,45313L,45314L,45315L,45316L,45317L,
-45318L,45319L,45320L,45321L,45322L,45323L,45324L,45325L,45326L,45327L,
-45328L,45329L,45330L,45331L,45332L,45333L,45334L,45335L,45336L,45337L,
-45338L,45339L,45340L,45341L,45342L,45343L,45344L,45345L,45346L,45347L,
-45348L,45349L,45350L,45351L,45352L,45353L,45354L,45355L,45356L,45357L,
-45358L,45359L,45360L,45361L,45362L,45363L,45364L,45365L,45366L,45367L,
-45368L,45369L,45370L,45371L,45372L,45373L,45374L,45375L,45376L,45377L,
-45378L,45379L,45380L,45381L,45382L,45383L,45384L,45385L,45386L,45387L,
-45388L,45389L,45390L,45391L,45392L,45393L,45394L,45395L,45396L,45397L,
-45398L,45399L,45400L,45401L,45402L,45403L,45404L,45405L,45406L,45407L,
-45408L,45409L,45410L,45411L,45412L,45413L,45414L,45415L,45416L,45417L,
-45418L,45419L,45420L,45421L,45422L,45423L,45424L,45425L,45426L,45427L,
-45428L,45429L,45430L,45431L,45432L,45433L,45434L,45435L,45436L,45437L,
-45438L,45439L,45440L,45441L,45442L,45443L,45444L,45445L,45446L,45447L,
-45448L,45449L,45450L,45451L,45452L,45453L,45454L,45455L,45456L,45457L,
-45458L,45459L,45460L,45461L,45462L,45463L,45464L,45465L,45466L,45467L,
-45468L,45469L,45470L,45471L,45472L,45473L,45474L,45475L,45476L,45477L,
-45478L,45479L,45480L,45481L,45482L,45483L,45484L,45485L,45486L,45487L,
-45488L,45489L,45490L,45491L,45492L,45493L,45494L,45495L,45496L,45497L,
-45498L,45499L,45500L,45501L,45502L,45503L,45504L,45505L,45506L,45507L,
-45508L,45509L,45510L,45511L,45512L,45513L,45514L,45515L,45516L,45517L,
-45518L,45519L,45520L,45521L,45522L,45523L,45524L,45525L,45526L,45527L,
-45528L,45529L,45530L,45531L,45532L,45533L,45534L,45535L,45536L,45537L,
-45538L,45539L,45540L,45541L,45542L,45543L,45544L,45545L,45546L,45547L,
-45548L,45549L,45550L,45551L,45552L,45553L,45554L,45555L,45556L,45557L,
-45558L,45559L,45560L,45561L,45562L,45563L,45564L,45565L,45566L,45567L,
-45568L,45569L,45570L,45571L,45572L,45573L,45574L,45575L,45576L,45577L,
-45578L,45579L,45580L,45581L,45582L,45583L,45584L,45585L,45586L,45587L,
-45588L,45589L,45590L,45591L,45592L,45593L,45594L,45595L,45596L,45597L,
-45598L,45599L,45600L,45601L,45602L,45603L,45604L,45605L,45606L,45607L,
-45608L,45609L,45610L,45611L,45612L,45613L,45614L,45615L,45616L,45617L,
-45618L,45619L,45620L,45621L,45622L,45623L,45624L,45625L,45626L,45627L,
-45628L,45629L,45630L,45631L,45632L,45633L,45634L,45635L,45636L,45637L,
-45638L,45639L,45640L,45641L,45642L,45643L,45644L,45645L,45646L,45647L,
-45648L,45649L,45650L,45651L,45652L,45653L,45654L,45655L,45656L,45657L,
-45658L,45659L,45660L,45661L,45662L,45663L,45664L,45665L,45666L,45667L,
-45668L,45669L,45670L,45671L,45672L,45673L,45674L,45675L,45676L,45677L,
-45678L,45679L,45680L,45681L,45682L,45683L,45684L,45685L,45686L,45687L,
-45688L,45689L,45690L,45691L,45692L,45693L,45694L,45695L,45696L,45697L,
-45698L,45699L,45700L,45701L,45702L,45703L,45704L,45705L,45706L,45707L,
-45708L,45709L,45710L,45711L,45712L,45713L,45714L,45715L,45716L,45717L,
-45718L,45719L,45720L,45721L,45722L,45723L,45724L,45725L,45726L,45727L,
-45728L,45729L,45730L,45731L,45732L,45733L,45734L,45735L,45736L,45737L,
-45738L,45739L,45740L,45741L,45742L,45743L,45744L,45745L,45746L,45747L,
-45748L,45749L,45750L,45751L,45752L,45753L,45754L,45755L,45756L,45757L,
-45758L,45759L,45760L,45761L,45762L,45763L,45764L,45765L,45766L,45767L,
-45768L,45769L,45770L,45771L,45772L,45773L,45774L,45775L,45776L,45777L,
-45778L,45779L,45780L,45781L,45782L,45783L,45784L,45785L,45786L,45787L,
-45788L,45789L,45790L,45791L,45792L,45793L,45794L,45795L,45796L,45797L,
-45798L,45799L,45800L,45801L,45802L,45803L,45804L,45805L,45806L,45807L,
-45808L,45809L,45810L,45811L,45812L,45813L,45814L,45815L,45816L,45817L,
-45818L,45819L,45820L,45821L,45822L,45823L,45824L,45825L,45826L,45827L,
-45828L,45829L,45830L,45831L,45832L,45833L,45834L,45835L,45836L,45837L,
-45838L,45839L,45840L,45841L,45842L,45843L,45844L,45845L,45846L,45847L,
-45848L,45849L,45850L,45851L,45852L,45853L,45854L,45855L,45856L,45857L,
-45858L,45859L,45860L,45861L,45862L,45863L,45864L,45865L,45866L,45867L,
-45868L,45869L,45870L,45871L,45872L,45873L,45874L,45875L,45876L,45877L,
-45878L,45879L,45880L,45881L,45882L,45883L,45884L,45885L,45886L,45887L,
-45888L,45889L,45890L,45891L,45892L,45893L,45894L,45895L,45896L,45897L,
-45898L,45899L,45900L,45901L,45902L,45903L,45904L,45905L,45906L,45907L,
-45908L,45909L,45910L,45911L,45912L,45913L,45914L,45915L,45916L,45917L,
-45918L,45919L,45920L,45921L,45922L,45923L,45924L,45925L,45926L,45927L,
-45928L,45929L,45930L,45931L,45932L,45933L,45934L,45935L,45936L,45937L,
-45938L,45939L,45940L,45941L,45942L,45943L,45944L,45945L,45946L,45947L,
-45948L,45949L,45950L,45951L,45952L,45953L,45954L,45955L,45956L,45957L,
-45958L,45959L,45960L,45961L,45962L,45963L,45964L,45965L,45966L,45967L,
-45968L,45969L,45970L,45971L,45972L,45973L,45974L,45975L,45976L,45977L,
-45978L,45979L,45980L,45981L,45982L,45983L,45984L,45985L,45986L,45987L,
-45988L,45989L,45990L,45991L,45992L,45993L,45994L,45995L,45996L,45997L,
-45998L,45999L,46000L,46001L,46002L,46003L,46004L,46005L,46006L,46007L,
-46008L,46009L,46010L,46011L,46012L,46013L,46014L,46015L,46016L,46017L,
-46018L,46019L,46020L,46021L,46022L,46023L,46024L,46025L,46026L,46027L,
-46028L,46029L,46030L,46031L,46032L,46033L,46034L,46035L,46036L,46037L,
-46038L,46039L,46040L,46041L,46042L,46043L,46044L,46045L,46046L,46047L,
-46048L,46049L,46050L,46051L,46052L,46053L,46054L,46055L,46056L,46057L,
-46058L,46059L,46060L,46061L,46062L,46063L,46064L,46065L,46066L,46067L,
-46068L,46069L,46070L,46071L,46072L,46073L,46074L,46075L,46076L,46077L,
-46078L,46079L,46080L,46081L,46082L,46083L,46084L,46085L,46086L,46087L,
-46088L,46089L,46090L,46091L,46092L,46093L,46094L,46095L,46096L,46097L,
-46098L,46099L,46100L,46101L,46102L,46103L,46104L,46105L,46106L,46107L,
-46108L,46109L,46110L,46111L,46112L,46113L,46114L,46115L,46116L,46117L,
-46118L,46119L,46120L,46121L,46122L,46123L,46124L,46125L,46126L,46127L,
-46128L,46129L,46130L,46131L,46132L,46133L,46134L,46135L,46136L,46137L,
-46138L,46139L,46140L,46141L,46142L,46143L,46144L,46145L,46146L,46147L,
-46148L,46149L,46150L,46151L,46152L,46153L,46154L,46155L,46156L,46157L,
-46158L,46159L,46160L,46161L,46162L,46163L,46164L,46165L,46166L,46167L,
-46168L,46169L,46170L,46171L,46172L,46173L,46174L,46175L,46176L,46177L,
-46178L,46179L,46180L,46181L,46182L,46183L,46184L,46185L,46186L,46187L,
-46188L,46189L,46190L,46191L,46192L,46193L,46194L,46195L,46196L,46197L,
-46198L,46199L,46200L,46201L,46202L,46203L,46204L,46205L,46206L,46207L,
-46208L,46209L,46210L,46211L,46212L,46213L,46214L,46215L,46216L,46217L,
-46218L,46219L,46220L,46221L,46222L,46223L,46224L,46225L,46226L,46227L,
-46228L,46229L,46230L,46231L,46232L,46233L,46234L,46235L,46236L,46237L,
-46238L,46239L,46240L,46241L,46242L,46243L,46244L,46245L,46246L,46247L,
-46248L,46249L,46250L,46251L,46252L,46253L,46254L,46255L,46256L,46257L,
-46258L,46259L,46260L,46261L,46262L,46263L,46264L,46265L,46266L,46267L,
-46268L,46269L,46270L,46271L,46272L,46273L,46274L,46275L,46276L,46277L,
-46278L,46279L,46280L,46281L,46282L,46283L,46284L,46285L,46286L,46287L,
-46288L,46289L,46290L,46291L,46292L,46293L,46294L,46295L,46296L,46297L,
-46298L,46299L,46300L,46301L,46302L,46303L,46304L,46305L,46306L,46307L,
-46308L,46309L,46310L,46311L,46312L,46313L,46314L,46315L,46316L,46317L,
-46318L,46319L,46320L,46321L,46322L,46323L,46324L,46325L,46326L,46327L,
-46328L,46329L,46330L,46331L,46332L,46333L,46334L,46335L,46336L,46337L,
-46338L,46339L,46340L,46341L,46342L,46343L,46344L,46345L,46346L,46347L,
-46348L,46349L,46350L,46351L,46352L,46353L,46354L,46355L,46356L,46357L,
-46358L,46359L,46360L,46361L,46362L,46363L,46364L,46365L,46366L,46367L,
-46368L,46369L,46370L,46371L,46372L,46373L,46374L,46375L,46376L,46377L,
-46378L,46379L,46380L,46381L,46382L,46383L,46384L,46385L,46386L,46387L,
-46388L,46389L,46390L,46391L,46392L,46393L,46394L,46395L,46396L,46397L,
-46398L,46399L,46400L,46401L,46402L,46403L,46404L,46405L,46406L,46407L,
-46408L,46409L,46410L,46411L,46412L,46413L,46414L,46415L,46416L,46417L,
-46418L,46419L,46420L,46421L,46422L,46423L,46424L,46425L,46426L,46427L,
-46428L,46429L,46430L,46431L,46432L,46433L,46434L,46435L,46436L,46437L,
-46438L,46439L,46440L,46441L,46442L,46443L,46444L,46445L,46446L,46447L,
-46448L,46449L,46450L,46451L,46452L,46453L,46454L,46455L,46456L,46457L,
-46458L,46459L,46460L,46461L,46462L,46463L,46464L,46465L,46466L,46467L,
-46468L,46469L,46470L,46471L,46472L,46473L,46474L,46475L,46476L,46477L,
-46478L,46479L,46480L,46481L,46482L,46483L,46484L,46485L,46486L,46487L,
-46488L,46489L,46490L,46491L,46492L,46493L,46494L,46495L,46496L,46497L,
-46498L,46499L,46500L,46501L,46502L,46503L,46504L,46505L,46506L,46507L,
-46508L,46509L,46510L,46511L,46512L,46513L,46514L,46515L,46516L,46517L,
-46518L,46519L,46520L,46521L,46522L,46523L,46524L,46525L,46526L,46527L,
-46528L,46529L,46530L,46531L,46532L,46533L,46534L,46535L,46536L,46537L,
-46538L,46539L,46540L,46541L,46542L,46543L,46544L,46545L,46546L,46547L,
-46548L,46549L,46550L,46551L,46552L,46553L,46554L,46555L,46556L,46557L,
-46558L,46559L,46560L,46561L,46562L,46563L,46564L,46565L,46566L,46567L,
-46568L,46569L,46570L,46571L,46572L,46573L,46574L,46575L,46576L,46577L,
-46578L,46579L,46580L,46581L,46582L,46583L,46584L,46585L,46586L,46587L,
-46588L,46589L,46590L,46591L,46592L,46593L,46594L,46595L,46596L,46597L,
-46598L,46599L,46600L,46601L,46602L,46603L,46604L,46605L,46606L,46607L,
-46608L,46609L,46610L,46611L,46612L,46613L,46614L,46615L,46616L,46617L,
-46618L,46619L,46620L,46621L,46622L,46623L,46624L,46625L,46626L,46627L,
-46628L,46629L,46630L,46631L,46632L,46633L,46634L,46635L,46636L,46637L,
-46638L,46639L,46640L,46641L,46642L,46643L,46644L,46645L,46646L,46647L,
-46648L,46649L,46650L,46651L,46652L,46653L,46654L,46655L,46656L,46657L,
-46658L,46659L,46660L,46661L,46662L,46663L,46664L,46665L,46666L,46667L,
-46668L,46669L,46670L,46671L,46672L,46673L,46674L,46675L,46676L,46677L,
-46678L,46679L,46680L,46681L,46682L,46683L,46684L,46685L,46686L,46687L,
-46688L,46689L,46690L,46691L,46692L,46693L,46694L,46695L,46696L,46697L,
-46698L,46699L,46700L,46701L,46702L,46703L,46704L,46705L,46706L,46707L,
-46708L,46709L,46710L,46711L,46712L,46713L,46714L,46715L,46716L,46717L,
-46718L,46719L,46720L,46721L,46722L,46723L,46724L,46725L,46726L,46727L,
-46728L,46729L,46730L,46731L,46732L,46733L,46734L,46735L,46736L,46737L,
-46738L,46739L,46740L,46741L,46742L,46743L,46744L,46745L,46746L,46747L,
-46748L,46749L,46750L,46751L,46752L,46753L,46754L,46755L,46756L,46757L,
-46758L,46759L,46760L,46761L,46762L,46763L,46764L,46765L,46766L,46767L,
-46768L,46769L,46770L,46771L,46772L,46773L,46774L,46775L,46776L,46777L,
-46778L,46779L,46780L,46781L,46782L,46783L,46784L,46785L,46786L,46787L,
-46788L,46789L,46790L,46791L,46792L,46793L,46794L,46795L,46796L,46797L,
-46798L,46799L,46800L,46801L,46802L,46803L,46804L,46805L,46806L,46807L,
-46808L,46809L,46810L,46811L,46812L,46813L,46814L,46815L,46816L,46817L,
-46818L,46819L,46820L,46821L,46822L,46823L,46824L,46825L,46826L,46827L,
-46828L,46829L,46830L,46831L,46832L,46833L,46834L,46835L,46836L,46837L,
-46838L,46839L,46840L,46841L,46842L,46843L,46844L,46845L,46846L,46847L,
-46848L,46849L,46850L,46851L,46852L,46853L,46854L,46855L,46856L,46857L,
-46858L,46859L,46860L,46861L,46862L,46863L,46864L,46865L,46866L,46867L,
-46868L,46869L,46870L,46871L,46872L,46873L,46874L,46875L,46876L,46877L,
-46878L,46879L,46880L,46881L,46882L,46883L,46884L,46885L,46886L,46887L,
-46888L,46889L,46890L,46891L,46892L,46893L,46894L,46895L,46896L,46897L,
-46898L,46899L,46900L,46901L,46902L,46903L,46904L,46905L,46906L,46907L,
-46908L,46909L,46910L,46911L,46912L,46913L,46914L,46915L,46916L,46917L,
-46918L,46919L,46920L,46921L,46922L,46923L,46924L,46925L,46926L,46927L,
-46928L,46929L,46930L,46931L,46932L,46933L,46934L,46935L,46936L,46937L,
-46938L,46939L,46940L,46941L,46942L,46943L,46944L,46945L,46946L,46947L,
-46948L,46949L,46950L,46951L,46952L,46953L,46954L,46955L,46956L,46957L,
-46958L,46959L,46960L,46961L,46962L,46963L,46964L,46965L,46966L,46967L,
-46968L,46969L,46970L,46971L,46972L,46973L,46974L,46975L,46976L,46977L,
-46978L,46979L,46980L,46981L,46982L,46983L,46984L,46985L,46986L,46987L,
-46988L,46989L,46990L,46991L,46992L,46993L,46994L,46995L,46996L,46997L,
-46998L,46999L,47000L,47001L,47002L,47003L,47004L,47005L,47006L,47007L,
-47008L,47009L,47010L,47011L,47012L,47013L,47014L,47015L,47016L,47017L,
-47018L,47019L,47020L,47021L,47022L,47023L,47024L,47025L,47026L,47027L,
-47028L,47029L,47030L,47031L,47032L,47033L,47034L,47035L,47036L,47037L,
-47038L,47039L,47040L,47041L,47042L,47043L,47044L,47045L,47046L,47047L,
-47048L,47049L,47050L,47051L,47052L,47053L,47054L,47055L,47056L,47057L,
-47058L,47059L,47060L,47061L,47062L,47063L,47064L,47065L,47066L,47067L,
-47068L,47069L,47070L,47071L,47072L,47073L,47074L,47075L,47076L,47077L,
-47078L,47079L,47080L,47081L,47082L,47083L,47084L,47085L,47086L,47087L,
-47088L,47089L,47090L,47091L,47092L,47093L,47094L,47095L,47096L,47097L,
-47098L,47099L,47100L,47101L,47102L,47103L,47104L,47105L,47106L,47107L,
-47108L,47109L,47110L,47111L,47112L,47113L,47114L,47115L,47116L,47117L,
-47118L,47119L,47120L,47121L,47122L,47123L,47124L,47125L,47126L,47127L,
-47128L,47129L,47130L,47131L,47132L,47133L,47134L,47135L,47136L,47137L,
-47138L,47139L,47140L,47141L,47142L,47143L,47144L,47145L,47146L,47147L,
-47148L,47149L,47150L,47151L,47152L,47153L,47154L,47155L,47156L,47157L,
-47158L,47159L,47160L,47161L,47162L,47163L,47164L,47165L,47166L,47167L,
-47168L,47169L,47170L,47171L,47172L,47173L,47174L,47175L,47176L,47177L,
-47178L,47179L,47180L,47181L,47182L,47183L,47184L,47185L,47186L,47187L,
-47188L,47189L,47190L,47191L,47192L,47193L,47194L,47195L,47196L,47197L,
-47198L,47199L,47200L,47201L,47202L,47203L,47204L,47205L,47206L,47207L,
-47208L,47209L,47210L,47211L,47212L,47213L,47214L,47215L,47216L,47217L,
-47218L,47219L,47220L,47221L,47222L,47223L,47224L,47225L,47226L,47227L,
-47228L,47229L,47230L,47231L,47232L,47233L,47234L,47235L,47236L,47237L,
-47238L,47239L,47240L,47241L,47242L,47243L,47244L,47245L,47246L,47247L,
-47248L,47249L,47250L,47251L,47252L,47253L,47254L,47255L,47256L,47257L,
-47258L,47259L,47260L,47261L,47262L,47263L,47264L,47265L,47266L,47267L,
-47268L,47269L,47270L,47271L,47272L,47273L,47274L,47275L,47276L,47277L,
-47278L,47279L,47280L,47281L,47282L,47283L,47284L,47285L,47286L,47287L,
-47288L,47289L,47290L,47291L,47292L,47293L,47294L,47295L,47296L,47297L,
-47298L,47299L,47300L,47301L,47302L,47303L,47304L,47305L,47306L,47307L,
-47308L,47309L,47310L,47311L,47312L,47313L,47314L,47315L,47316L,47317L,
-47318L,47319L,47320L,47321L,47322L,47323L,47324L,47325L,47326L,47327L,
-47328L,47329L,47330L,47331L,47332L,47333L,47334L,47335L,47336L,47337L,
-47338L,47339L,47340L,47341L,47342L,47343L,47344L,47345L,47346L,47347L,
-47348L,47349L,47350L,47351L,47352L,47353L,47354L,47355L,47356L,47357L,
-47358L,47359L,47360L,47361L,47362L,47363L,47364L,47365L,47366L,47367L,
-47368L,47369L,47370L,47371L,47372L,47373L,47374L,47375L,47376L,47377L,
-47378L,47379L,47380L,47381L,47382L,47383L,47384L,47385L,47386L,47387L,
-47388L,47389L,47390L,47391L,47392L,47393L,47394L,47395L,47396L,47397L,
-47398L,47399L,47400L,47401L,47402L,47403L,47404L,47405L,47406L,47407L,
-47408L,47409L,47410L,47411L,47412L,47413L,47414L,47415L,47416L,47417L,
-47418L,47419L,47420L,47421L,47422L,47423L,47424L,47425L,47426L,47427L,
-47428L,47429L,47430L,47431L,47432L,47433L,47434L,47435L,47436L,47437L,
-47438L,47439L,47440L,47441L,47442L,47443L,47444L,47445L,47446L,47447L,
-47448L,47449L,47450L,47451L,47452L,47453L,47454L,47455L,47456L,47457L,
-47458L,47459L,47460L,47461L,47462L,47463L,47464L,47465L,47466L,47467L,
-47468L,47469L,47470L,47471L,47472L,47473L,47474L,47475L,47476L,47477L,
-47478L,47479L,47480L,47481L,47482L,47483L,47484L,47485L,47486L,47487L,
-47488L,47489L,47490L,47491L,47492L,47493L,47494L,47495L,47496L,47497L,
-47498L,47499L,47500L,47501L,47502L,47503L,47504L,47505L,47506L,47507L,
-47508L,47509L,47510L,47511L,47512L,47513L,47514L,47515L,47516L,47517L,
-47518L,47519L,47520L,47521L,47522L,47523L,47524L,47525L,47526L,47527L,
-47528L,47529L,47530L,47531L,47532L,47533L,47534L,47535L,47536L,47537L,
-47538L,47539L,47540L,47541L,47542L,47543L,47544L,47545L,47546L,47547L,
-47548L,47549L,47550L,47551L,47552L,47553L,47554L,47555L,47556L,47557L,
-47558L,47559L,47560L,47561L,47562L,47563L,47564L,47565L,47566L,47567L,
-47568L,47569L,47570L,47571L,47572L,47573L,47574L,47575L,47576L,47577L,
-47578L,47579L,47580L,47581L,47582L,47583L,47584L,47585L,47586L,47587L,
-47588L,47589L,47590L,47591L,47592L,47593L,47594L,47595L,47596L,47597L,
-47598L,47599L,47600L,47601L,47602L,47603L,47604L,47605L,47606L,47607L,
-47608L,47609L,47610L,47611L,47612L,47613L,47614L,47615L,47616L,47617L,
-47618L,47619L,47620L,47621L,47622L,47623L,47624L,47625L,47626L,47627L,
-47628L,47629L,47630L,47631L,47632L,47633L,47634L,47635L,47636L,47637L,
-47638L,47639L,47640L,47641L,47642L,47643L,47644L,47645L,47646L,47647L,
-47648L,47649L,47650L,47651L,47652L,47653L,47654L,47655L,47656L,47657L,
-47658L,47659L,47660L,47661L,47662L,47663L,47664L,47665L,47666L,47667L,
-47668L,47669L,47670L,47671L,47672L,47673L,47674L,47675L,47676L,47677L,
-47678L,47679L,47680L,47681L,47682L,47683L,47684L,47685L,47686L,47687L,
-47688L,47689L,47690L,47691L,47692L,47693L,47694L,47695L,47696L,47697L,
-47698L,47699L,47700L,47701L,47702L,47703L,47704L,47705L,47706L,47707L,
-47708L,47709L,47710L,47711L,47712L,47713L,47714L,47715L,47716L,47717L,
-47718L,47719L,47720L,47721L,47722L,47723L,47724L,47725L,47726L,47727L,
-47728L,47729L,47730L,47731L,47732L,47733L,47734L,47735L,47736L,47737L,
-47738L,47739L,47740L,47741L,47742L,47743L,47744L,47745L,47746L,47747L,
-47748L,47749L,47750L,47751L,47752L,47753L,47754L,47755L,47756L,47757L,
-47758L,47759L,47760L,47761L,47762L,47763L,47764L,47765L,47766L,47767L,
-47768L,47769L,47770L,47771L,47772L,47773L,47774L,47775L,47776L,47777L,
-47778L,47779L,47780L,47781L,47782L,47783L,47784L,47785L,47786L,47787L,
-47788L,47789L,47790L,47791L,47792L,47793L,47794L,47795L,47796L,47797L,
-47798L,47799L,47800L,47801L,47802L,47803L,47804L,47805L,47806L,47807L,
-47808L,47809L,47810L,47811L,47812L,47813L,47814L,47815L,47816L,47817L,
-47818L,47819L,47820L,47821L,47822L,47823L,47824L,47825L,47826L,47827L,
-47828L,47829L,47830L,47831L,47832L,47833L,47834L,47835L,47836L,47837L,
-47838L,47839L,47840L,47841L,47842L,47843L,47844L,47845L,47846L,47847L,
-47848L,47849L,47850L,47851L,47852L,47853L,47854L,47855L,47856L,47857L,
-47858L,47859L,47860L,47861L,47862L,47863L,47864L,47865L,47866L,47867L,
-47868L,47869L,47870L,47871L,47872L,47873L,47874L,47875L,47876L,47877L,
-47878L,47879L,47880L,47881L,47882L,47883L,47884L,47885L,47886L,47887L,
-47888L,47889L,47890L,47891L,47892L,47893L,47894L,47895L,47896L,47897L,
-47898L,47899L,47900L,47901L,47902L,47903L,47904L,47905L,47906L,47907L,
-47908L,47909L,47910L,47911L,47912L,47913L,47914L,47915L,47916L,47917L,
-47918L,47919L,47920L,47921L,47922L,47923L,47924L,47925L,47926L,47927L,
-47928L,47929L,47930L,47931L,47932L,47933L,47934L,47935L,47936L,47937L,
-47938L,47939L,47940L,47941L,47942L,47943L,47944L,47945L,47946L,47947L,
-47948L,47949L,47950L,47951L,47952L,47953L,47954L,47955L,47956L,47957L,
-47958L,47959L,47960L,47961L,47962L,47963L,47964L,47965L,47966L,47967L,
-47968L,47969L,47970L,47971L,47972L,47973L,47974L,47975L,47976L,47977L,
-47978L,47979L,47980L,47981L,47982L,47983L,47984L,47985L,47986L,47987L,
-47988L,47989L,47990L,47991L,47992L,47993L,47994L,47995L,47996L,47997L,
-47998L,47999L,48000L,48001L,48002L,48003L,48004L,48005L,48006L,48007L,
-48008L,48009L,48010L,48011L,48012L,48013L,48014L,48015L,48016L,48017L,
-48018L,48019L,48020L,48021L,48022L,48023L,48024L,48025L,48026L,48027L,
-48028L,48029L,48030L,48031L,48032L,48033L,48034L,48035L,48036L,48037L,
-48038L,48039L,48040L,48041L,48042L,48043L,48044L,48045L,48046L,48047L,
-48048L,48049L,48050L,48051L,48052L,48053L,48054L,48055L,48056L,48057L,
-48058L,48059L,48060L,48061L,48062L,48063L,48064L,48065L,48066L,48067L,
-48068L,48069L,48070L,48071L,48072L,48073L,48074L,48075L,48076L,48077L,
-48078L,48079L,48080L,48081L,48082L,48083L,48084L,48085L,48086L,48087L,
-48088L,48089L,48090L,48091L,48092L,48093L,48094L,48095L,48096L,48097L,
-48098L,48099L,48100L,48101L,48102L,48103L,48104L,48105L,48106L,48107L,
-48108L,48109L,48110L,48111L,48112L,48113L,48114L,48115L,48116L,48117L,
-48118L,48119L,48120L,48121L,48122L,48123L,48124L,48125L,48126L,48127L,
-48128L,48129L,48130L,48131L,48132L,48133L,48134L,48135L,48136L,48137L,
-48138L,48139L,48140L,48141L,48142L,48143L,48144L,48145L,48146L,48147L,
-48148L,48149L,48150L,48151L,48152L,48153L,48154L,48155L,48156L,48157L,
-48158L,48159L,48160L,48161L,48162L,48163L,48164L,48165L,48166L,48167L,
-48168L,48169L,48170L,48171L,48172L,48173L,48174L,48175L,48176L,48177L,
-48178L,48179L,48180L,48181L,48182L,48183L,48184L,48185L,48186L,48187L,
-48188L,48189L,48190L,48191L,48192L,48193L,48194L,48195L,48196L,48197L,
-48198L,48199L,48200L,48201L,48202L,48203L,48204L,48205L,48206L,48207L,
-48208L,48209L,48210L,48211L,48212L,48213L,48214L,48215L,48216L,48217L,
-48218L,48219L,48220L,48221L,48222L,48223L,48224L,48225L,48226L,48227L,
-48228L,48229L,48230L,48231L,48232L,48233L,48234L,48235L,48236L,48237L,
-48238L,48239L,48240L,48241L,48242L,48243L,48244L,48245L,48246L,48247L,
-48248L,48249L,48250L,48251L,48252L,48253L,48254L,48255L,48256L,48257L,
-48258L,48259L,48260L,48261L,48262L,48263L,48264L,48265L,48266L,48267L,
-48268L,48269L,48270L,48271L,48272L,48273L,48274L,48275L,48276L,48277L,
-48278L,48279L,48280L,48281L,48282L,48283L,48284L,48285L,48286L,48287L,
-48288L,48289L,48290L,48291L,48292L,48293L,48294L,48295L,48296L,48297L,
-48298L,48299L,48300L,48301L,48302L,48303L,48304L,48305L,48306L,48307L,
-48308L,48309L,48310L,48311L,48312L,48313L,48314L,48315L,48316L,48317L,
-48318L,48319L,48320L,48321L,48322L,48323L,48324L,48325L,48326L,48327L,
-48328L,48329L,48330L,48331L,48332L,48333L,48334L,48335L,48336L,48337L,
-48338L,48339L,48340L,48341L,48342L,48343L,48344L,48345L,48346L,48347L,
-48348L,48349L,48350L,48351L,48352L,48353L,48354L,48355L,48356L,48357L,
-48358L,48359L,48360L,48361L,48362L,48363L,48364L,48365L,48366L,48367L,
-48368L,48369L,48370L,48371L,48372L,48373L,48374L,48375L,48376L,48377L,
-48378L,48379L,48380L,48381L,48382L,48383L,48384L,48385L,48386L,48387L,
-48388L,48389L,48390L,48391L,48392L,48393L,48394L,48395L,48396L,48397L,
-48398L,48399L,48400L,48401L,48402L,48403L,48404L,48405L,48406L,48407L,
-48408L,48409L,48410L,48411L,48412L,48413L,48414L,48415L,48416L,48417L,
-48418L,48419L,48420L,48421L,48422L,48423L,48424L,48425L,48426L,48427L,
-48428L,48429L,48430L,48431L,48432L,48433L,48434L,48435L,48436L,48437L,
-48438L,48439L,48440L,48441L,48442L,48443L,48444L,48445L,48446L,48447L,
-48448L,48449L,48450L,48451L,48452L,48453L,48454L,48455L,48456L,48457L,
-48458L,48459L,48460L,48461L,48462L,48463L,48464L,48465L,48466L,48467L,
-48468L,48469L,48470L,48471L,48472L,48473L,48474L,48475L,48476L,48477L,
-48478L,48479L,48480L,48481L,48482L,48483L,48484L,48485L,48486L,48487L,
-48488L,48489L,48490L,48491L,48492L,48493L,48494L,48495L,48496L,48497L,
-48498L,48499L,48500L,48501L,48502L,48503L,48504L,48505L,48506L,48507L,
-48508L,48509L,48510L,48511L,48512L,48513L,48514L,48515L,48516L,48517L,
-48518L,48519L,48520L,48521L,48522L,48523L,48524L,48525L,48526L,48527L,
-48528L,48529L,48530L,48531L,48532L,48533L,48534L,48535L,48536L,48537L,
-48538L,48539L,48540L,48541L,48542L,48543L,48544L,48545L,48546L,48547L,
-48548L,48549L,48550L,48551L,48552L,48553L,48554L,48555L,48556L,48557L,
-48558L,48559L,48560L,48561L,48562L,48563L,48564L,48565L,48566L,48567L,
-48568L,48569L,48570L,48571L,48572L,48573L,48574L,48575L,48576L,48577L,
-48578L,48579L,48580L,48581L,48582L,48583L,48584L,48585L,48586L,48587L,
-48588L,48589L,48590L,48591L,48592L,48593L,48594L,48595L,48596L,48597L,
-48598L,48599L,48600L,48601L,48602L,48603L,48604L,48605L,48606L,48607L,
-48608L,48609L,48610L,48611L,48612L,48613L,48614L,48615L,48616L,48617L,
-48618L,48619L,48620L,48621L,48622L,48623L,48624L,48625L,48626L,48627L,
-48628L,48629L,48630L,48631L,48632L,48633L,48634L,48635L,48636L,48637L,
-48638L,48639L,48640L,48641L,48642L,48643L,48644L,48645L,48646L,48647L,
-48648L,48649L,48650L,48651L,48652L,48653L,48654L,48655L,48656L,48657L,
-48658L,48659L,48660L,48661L,48662L,48663L,48664L,48665L,48666L,48667L,
-48668L,48669L,48670L,48671L,48672L,48673L,48674L,48675L,48676L,48677L,
-48678L,48679L,48680L,48681L,48682L,48683L,48684L,48685L,48686L,48687L,
-48688L,48689L,48690L,48691L,48692L,48693L,48694L,48695L,48696L,48697L,
-48698L,48699L,48700L,48701L,48702L,48703L,48704L,48705L,48706L,48707L,
-48708L,48709L,48710L,48711L,48712L,48713L,48714L,48715L,48716L,48717L,
-48718L,48719L,48720L,48721L,48722L,48723L,48724L,48725L,48726L,48727L,
-48728L,48729L,48730L,48731L,48732L,48733L,48734L,48735L,48736L,48737L,
-48738L,48739L,48740L,48741L,48742L,48743L,48744L,48745L,48746L,48747L,
-48748L,48749L,48750L,48751L,48752L,48753L,48754L,48755L,48756L,48757L,
-48758L,48759L,48760L,48761L,48762L,48763L,48764L,48765L,48766L,48767L,
-48768L,48769L,48770L,48771L,48772L,48773L,48774L,48775L,48776L,48777L,
-48778L,48779L,48780L,48781L,48782L,48783L,48784L,48785L,48786L,48787L,
-48788L,48789L,48790L,48791L,48792L,48793L,48794L,48795L,48796L,48797L,
-48798L,48799L,48800L,48801L,48802L,48803L,48804L,48805L,48806L,48807L,
-48808L,48809L,48810L,48811L,48812L,48813L,48814L,48815L,48816L,48817L,
-48818L,48819L,48820L,48821L,48822L,48823L,48824L,48825L,48826L,48827L,
-48828L,48829L,48830L,48831L,48832L,48833L,48834L,48835L,48836L,48837L,
-48838L,48839L,48840L,48841L,48842L,48843L,48844L,48845L,48846L,48847L,
-48848L,48849L,48850L,48851L,48852L,48853L,48854L,48855L,48856L,48857L,
-48858L,48859L,48860L,48861L,48862L,48863L,48864L,48865L,48866L,48867L,
-48868L,48869L,48870L,48871L,48872L,48873L,48874L,48875L,48876L,48877L,
-48878L,48879L,48880L,48881L,48882L,48883L,48884L,48885L,48886L,48887L,
-48888L,48889L,48890L,48891L,48892L,48893L,48894L,48895L,48896L,48897L,
-48898L,48899L,48900L,48901L,48902L,48903L,48904L,48905L,48906L,48907L,
-48908L,48909L,48910L,48911L,48912L,48913L,48914L,48915L,48916L,48917L,
-48918L,48919L,48920L,48921L,48922L,48923L,48924L,48925L,48926L,48927L,
-48928L,48929L,48930L,48931L,48932L,48933L,48934L,48935L,48936L,48937L,
-48938L,48939L,48940L,48941L,48942L,48943L,48944L,48945L,48946L,48947L,
-48948L,48949L,48950L,48951L,48952L,48953L,48954L,48955L,48956L,48957L,
-48958L,48959L,48960L,48961L,48962L,48963L,48964L,48965L,48966L,48967L,
-48968L,48969L,48970L,48971L,48972L,48973L,48974L,48975L,48976L,48977L,
-48978L,48979L,48980L,48981L,48982L,48983L,48984L,48985L,48986L,48987L,
-48988L,48989L,48990L,48991L,48992L,48993L,48994L,48995L,48996L,48997L,
-48998L,48999L,49000L,49001L,49002L,49003L,49004L,49005L,49006L,49007L,
-49008L,49009L,49010L,49011L,49012L,49013L,49014L,49015L,49016L,49017L,
-49018L,49019L,49020L,49021L,49022L,49023L,49024L,49025L,49026L,49027L,
-49028L,49029L,49030L,49031L,49032L,49033L,49034L,49035L,49036L,49037L,
-49038L,49039L,49040L,49041L,49042L,49043L,49044L,49045L,49046L,49047L,
-49048L,49049L,49050L,49051L,49052L,49053L,49054L,49055L,49056L,49057L,
-49058L,49059L,49060L,49061L,49062L,49063L,49064L,49065L,49066L,49067L,
-49068L,49069L,49070L,49071L,49072L,49073L,49074L,49075L,49076L,49077L,
-49078L,49079L,49080L,49081L,49082L,49083L,49084L,49085L,49086L,49087L,
-49088L,49089L,49090L,49091L,49092L,49093L,49094L,49095L,49096L,49097L,
-49098L,49099L,49100L,49101L,49102L,49103L,49104L,49105L,49106L,49107L,
-49108L,49109L,49110L,49111L,49112L,49113L,49114L,49115L,49116L,49117L,
-49118L,49119L,49120L,49121L,49122L,49123L,49124L,49125L,49126L,49127L,
-49128L,49129L,49130L,49131L,49132L,49133L,49134L,49135L,49136L,49137L,
-49138L,49139L,49140L,49141L,49142L,49143L,49144L,49145L,49146L,49147L,
-49148L,49149L,49150L,49151L,49152L,49153L,49154L,49155L,49156L,49157L,
-49158L,49159L,49160L,49161L,49162L,49163L,49164L,49165L,49166L,49167L,
-49168L,49169L,49170L,49171L,49172L,49173L,49174L,49175L,49176L,49177L,
-49178L,49179L,49180L,49181L,49182L,49183L,49184L,49185L,49186L,49187L,
-49188L,49189L,49190L,49191L,49192L,49193L,49194L,49195L,49196L,49197L,
-49198L,49199L,49200L,49201L,49202L,49203L,49204L,49205L,49206L,49207L,
-49208L,49209L,49210L,49211L,49212L,49213L,49214L,49215L,49216L,49217L,
-49218L,49219L,49220L,49221L,49222L,49223L,49224L,49225L,49226L,49227L,
-49228L,49229L,49230L,49231L,49232L,49233L,49234L,49235L,49236L,49237L,
-49238L,49239L,49240L,49241L,49242L,49243L,49244L,49245L,49246L,49247L,
-49248L,49249L,49250L,49251L,49252L,49253L,49254L,49255L,49256L,49257L,
-49258L,49259L,49260L,49261L,49262L,49263L,49264L,49265L,49266L,49267L,
-49268L,49269L,49270L,49271L,49272L,49273L,49274L,49275L,49276L,49277L,
-49278L,49279L,49280L,49281L,49282L,49283L,49284L,49285L,49286L,49287L,
-49288L,49289L,49290L,49291L,49292L,49293L,49294L,49295L,49296L,49297L,
-49298L,49299L,49300L,49301L,49302L,49303L,49304L,49305L,49306L,49307L,
-49308L,49309L,49310L,49311L,49312L,49313L,49314L,49315L,49316L,49317L,
-49318L,49319L,49320L,49321L,49322L,49323L,49324L,49325L,49326L,49327L,
-49328L,49329L,49330L,49331L,49332L,49333L,49334L,49335L,49336L,49337L,
-49338L,49339L,49340L,49341L,49342L,49343L,49344L,49345L,49346L,49347L,
-49348L,49349L,49350L,49351L,49352L,49353L,49354L,49355L,49356L,49357L,
-49358L,49359L,49360L,49361L,49362L,49363L,49364L,49365L,49366L,49367L,
-49368L,49369L,49370L,49371L,49372L,49373L,49374L,49375L,49376L,49377L,
-49378L,49379L,49380L,49381L,49382L,49383L,49384L,49385L,49386L,49387L,
-49388L,49389L,49390L,49391L,49392L,49393L,49394L,49395L,49396L,49397L,
-49398L,49399L,49400L,49401L,49402L,49403L,49404L,49405L,49406L,49407L,
-49408L,49409L,49410L,49411L,49412L,49413L,49414L,49415L,49416L,49417L,
-49418L,49419L,49420L,49421L,49422L,49423L,49424L,49425L,49426L,49427L,
-49428L,49429L,49430L,49431L,49432L,49433L,49434L,49435L,49436L,49437L,
-49438L,49439L,49440L,49441L,49442L,49443L,49444L,49445L,49446L,49447L,
-49448L,49449L,49450L,49451L,49452L,49453L,49454L,49455L,49456L,49457L,
-49458L,49459L,49460L,49461L,49462L,49463L,49464L,49465L,49466L,49467L,
-49468L,49469L,49470L,49471L,49472L,49473L,49474L,49475L,49476L,49477L,
-49478L,49479L,49480L,49481L,49482L,49483L,49484L,49485L,49486L,49487L,
-49488L,49489L,49490L,49491L,49492L,49493L,49494L,49495L,49496L,49497L,
-49498L,49499L,49500L,49501L,49502L,49503L,49504L,49505L,49506L,49507L,
-49508L,49509L,49510L,49511L,49512L,49513L,49514L,49515L,49516L,49517L,
-49518L,49519L,49520L,49521L,49522L,49523L,49524L,49525L,49526L,49527L,
-49528L,49529L,49530L,49531L,49532L,49533L,49534L,49535L,49536L,49537L,
-49538L,49539L,49540L,49541L,49542L,49543L,49544L,49545L,49546L,49547L,
-49548L,49549L,49550L,49551L,49552L,49553L,49554L,49555L,49556L,49557L,
-49558L,49559L,49560L,49561L,49562L,49563L,49564L,49565L,49566L,49567L,
-49568L,49569L,49570L,49571L,49572L,49573L,49574L,49575L,49576L,49577L,
-49578L,49579L,49580L,49581L,49582L,49583L,49584L,49585L,49586L,49587L,
-49588L,49589L,49590L,49591L,49592L,49593L,49594L,49595L,49596L,49597L,
-49598L,49599L,49600L,49601L,49602L,49603L,49604L,49605L,49606L,49607L,
-49608L,49609L,49610L,49611L,49612L,49613L,49614L,49615L,49616L,49617L,
-49618L,49619L,49620L,49621L,49622L,49623L,49624L,49625L,49626L,49627L,
-49628L,49629L,49630L,49631L,49632L,49633L,49634L,49635L,49636L,49637L,
-49638L,49639L,49640L,49641L,49642L,49643L,49644L,49645L,49646L,49647L,
-49648L,49649L,49650L,49651L,49652L,49653L,49654L,49655L,49656L,49657L,
-49658L,49659L,49660L,49661L,49662L,49663L,49664L,49665L,49666L,49667L,
-49668L,49669L,49670L,49671L,49672L,49673L,49674L,49675L,49676L,49677L,
-49678L,49679L,49680L,49681L,49682L,49683L,49684L,49685L,49686L,49687L,
-49688L,49689L,49690L,49691L,49692L,49693L,49694L,49695L,49696L,49697L,
-49698L,49699L,49700L,49701L,49702L,49703L,49704L,49705L,49706L,49707L,
-49708L,49709L,49710L,49711L,49712L,49713L,49714L,49715L,49716L,49717L,
-49718L,49719L,49720L,49721L,49722L,49723L,49724L,49725L,49726L,49727L,
-49728L,49729L,49730L,49731L,49732L,49733L,49734L,49735L,49736L,49737L,
-49738L,49739L,49740L,49741L,49742L,49743L,49744L,49745L,49746L,49747L,
-49748L,49749L,49750L,49751L,49752L,49753L,49754L,49755L,49756L,49757L,
-49758L,49759L,49760L,49761L,49762L,49763L,49764L,49765L,49766L,49767L,
-49768L,49769L,49770L,49771L,49772L,49773L,49774L,49775L,49776L,49777L,
-49778L,49779L,49780L,49781L,49782L,49783L,49784L,49785L,49786L,49787L,
-49788L,49789L,49790L,49791L,49792L,49793L,49794L,49795L,49796L,49797L,
-49798L,49799L,49800L,49801L,49802L,49803L,49804L,49805L,49806L,49807L,
-49808L,49809L,49810L,49811L,49812L,49813L,49814L,49815L,49816L,49817L,
-49818L,49819L,49820L,49821L,49822L,49823L,49824L,49825L,49826L,49827L,
-49828L,49829L,49830L,49831L,49832L,49833L,49834L,49835L,49836L,49837L,
-49838L,49839L,49840L,49841L,49842L,49843L,49844L,49845L,49846L,49847L,
-49848L,49849L,49850L,49851L,49852L,49853L,49854L,49855L,49856L,49857L,
-49858L,49859L,49860L,49861L,49862L,49863L,49864L,49865L,49866L,49867L,
-49868L,49869L,49870L,49871L,49872L,49873L,49874L,49875L,49876L,49877L,
-49878L,49879L,49880L,49881L,49882L,49883L,49884L,49885L,49886L,49887L,
-49888L,49889L,49890L,49891L,49892L,49893L,49894L,49895L,49896L,49897L,
-49898L,49899L,49900L,49901L,49902L,49903L,49904L,49905L,49906L,49907L,
-49908L,49909L,49910L,49911L,49912L,49913L,49914L,49915L,49916L,49917L,
-49918L,49919L,49920L,49921L,49922L,49923L,49924L,49925L,49926L,49927L,
-49928L,49929L,49930L,49931L,49932L,49933L,49934L,49935L,49936L,49937L,
-49938L,49939L,49940L,49941L,49942L,49943L,49944L,49945L,49946L,49947L,
-49948L,49949L,49950L,49951L,49952L,49953L,49954L,49955L,49956L,49957L,
-49958L,49959L,49960L,49961L,49962L,49963L,49964L,49965L,49966L,49967L,
-49968L,49969L,49970L,49971L,49972L,49973L,49974L,49975L,49976L,49977L,
-49978L,49979L,49980L,49981L,49982L,49983L,49984L,49985L,49986L,49987L,
-49988L,49989L,49990L,49991L,49992L,49993L,49994L,49995L,49996L,49997L,
-49998L,49999L,50000L,50001L,50002L,50003L,50004L,50005L,50006L,50007L,
-50008L,50009L,50010L,50011L,50012L,50013L,50014L,50015L,50016L,50017L,
-50018L,50019L,50020L,50021L,50022L,50023L,50024L,50025L,50026L,50027L,
-50028L,50029L,50030L,50031L,50032L,50033L,50034L,50035L,50036L,50037L,
-50038L,50039L,50040L,50041L,50042L,50043L,50044L,50045L,50046L,50047L,
-50048L,50049L,50050L,50051L,50052L,50053L,50054L,50055L,50056L,50057L,
-50058L,50059L,50060L,50061L,50062L,50063L,50064L,50065L,50066L,50067L,
-50068L,50069L,50070L,50071L,50072L,50073L,50074L,50075L,50076L,50077L,
-50078L,50079L,50080L,50081L,50082L,50083L,50084L,50085L,50086L,50087L,
-50088L,50089L,50090L,50091L,50092L,50093L,50094L,50095L,50096L,50097L,
-50098L,50099L,50100L,50101L,50102L,50103L,50104L,50105L,50106L,50107L,
-50108L,50109L,50110L,50111L,50112L,50113L,50114L,50115L,50116L,50117L,
-50118L,50119L,50120L,50121L,50122L,50123L,50124L,50125L,50126L,50127L,
-50128L,50129L,50130L,50131L,50132L,50133L,50134L,50135L,50136L,50137L,
-50138L,50139L,50140L,50141L,50142L,50143L,50144L,50145L,50146L,50147L,
-50148L,50149L,50150L,50151L,50152L,50153L,50154L,50155L,50156L,50157L,
-50158L,50159L,50160L,50161L,50162L,50163L,50164L,50165L,50166L,50167L,
-50168L,50169L,50170L,50171L,50172L,50173L,50174L,50175L,50176L,50177L,
-50178L,50179L,50180L,50181L,50182L,50183L,50184L,50185L,50186L,50187L,
-50188L,50189L,50190L,50191L,50192L,50193L,50194L,50195L,50196L,50197L,
-50198L,50199L,50200L,50201L,50202L,50203L,50204L,50205L,50206L,50207L,
-50208L,50209L,50210L,50211L,50212L,50213L,50214L,50215L,50216L,50217L,
-50218L,50219L,50220L,50221L,50222L,50223L,50224L,50225L,50226L,50227L,
-50228L,50229L,50230L,50231L,50232L,50233L,50234L,50235L,50236L,50237L,
-50238L,50239L,50240L,50241L,50242L,50243L,50244L,50245L,50246L,50247L,
-50248L,50249L,50250L,50251L,50252L,50253L,50254L,50255L,50256L,50257L,
-50258L,50259L,50260L,50261L,50262L,50263L,50264L,50265L,50266L,50267L,
-50268L,50269L,50270L,50271L,50272L,50273L,50274L,50275L,50276L,50277L,
-50278L,50279L,50280L,50281L,50282L,50283L,50284L,50285L,50286L,50287L,
-50288L,50289L,50290L,50291L,50292L,50293L,50294L,50295L,50296L,50297L,
-50298L,50299L,50300L,50301L,50302L,50303L,50304L,50305L,50306L,50307L,
-50308L,50309L,50310L,50311L,50312L,50313L,50314L,50315L,50316L,50317L,
-50318L,50319L,50320L,50321L,50322L,50323L,50324L,50325L,50326L,50327L,
-50328L,50329L,50330L,50331L,50332L,50333L,50334L,50335L,50336L,50337L,
-50338L,50339L,50340L,50341L,50342L,50343L,50344L,50345L,50346L,50347L,
-50348L,50349L,50350L,50351L,50352L,50353L,50354L,50355L,50356L,50357L,
-50358L,50359L,50360L,50361L,50362L,50363L,50364L,50365L,50366L,50367L,
-50368L,50369L,50370L,50371L,50372L,50373L,50374L,50375L,50376L,50377L,
-50378L,50379L,50380L,50381L,50382L,50383L,50384L,50385L,50386L,50387L,
-50388L,50389L,50390L,50391L,50392L,50393L,50394L,50395L,50396L,50397L,
-50398L,50399L,50400L,50401L,50402L,50403L,50404L,50405L,50406L,50407L,
-50408L,50409L,50410L,50411L,50412L,50413L,50414L,50415L,50416L,50417L,
-50418L,50419L,50420L,50421L,50422L,50423L,50424L,50425L,50426L,50427L,
-50428L,50429L,50430L,50431L,50432L,50433L,50434L,50435L,50436L,50437L,
-50438L,50439L,50440L,50441L,50442L,50443L,50444L,50445L,50446L,50447L,
-50448L,50449L,50450L,50451L,50452L,50453L,50454L,50455L,50456L,50457L,
-50458L,50459L,50460L,50461L,50462L,50463L,50464L,50465L,50466L,50467L,
-50468L,50469L,50470L,50471L,50472L,50473L,50474L,50475L,50476L,50477L,
-50478L,50479L,50480L,50481L,50482L,50483L,50484L,50485L,50486L,50487L,
-50488L,50489L,50490L,50491L,50492L,50493L,50494L,50495L,50496L,50497L,
-50498L,50499L,50500L,50501L,50502L,50503L,50504L,50505L,50506L,50507L,
-50508L,50509L,50510L,50511L,50512L,50513L,50514L,50515L,50516L,50517L,
-50518L,50519L,50520L,50521L,50522L,50523L,50524L,50525L,50526L,50527L,
-50528L,50529L,50530L,50531L,50532L,50533L,50534L,50535L,50536L,50537L,
-50538L,50539L,50540L,50541L,50542L,50543L,50544L,50545L,50546L,50547L,
-50548L,50549L,50550L,50551L,50552L,50553L,50554L,50555L,50556L,50557L,
-50558L,50559L,50560L,50561L,50562L,50563L,50564L,50565L,50566L,50567L,
-50568L,50569L,50570L,50571L,50572L,50573L,50574L,50575L,50576L,50577L,
-50578L,50579L,50580L,50581L,50582L,50583L,50584L,50585L,50586L,50587L,
-50588L,50589L,50590L,50591L,50592L,50593L,50594L,50595L,50596L,50597L,
-50598L,50599L,50600L,50601L,50602L,50603L,50604L,50605L,50606L,50607L,
-50608L,50609L,50610L,50611L,50612L,50613L,50614L,50615L,50616L,50617L,
-50618L,50619L,50620L,50621L,50622L,50623L,50624L,50625L,50626L,50627L,
-50628L,50629L,50630L,50631L,50632L,50633L,50634L,50635L,50636L,50637L,
-50638L,50639L,50640L,50641L,50642L,50643L,50644L,50645L,50646L,50647L,
-50648L,50649L,50650L,50651L,50652L,50653L,50654L,50655L,50656L,50657L,
-50658L,50659L,50660L,50661L,50662L,50663L,50664L,50665L,50666L,50667L,
-50668L,50669L,50670L,50671L,50672L,50673L,50674L,50675L,50676L,50677L,
-50678L,50679L,50680L,50681L,50682L,50683L,50684L,50685L,50686L,50687L,
-50688L,50689L,50690L,50691L,50692L,50693L,50694L,50695L,50696L,50697L,
-50698L,50699L,50700L,50701L,50702L,50703L,50704L,50705L,50706L,50707L,
-50708L,50709L,50710L,50711L,50712L,50713L,50714L,50715L,50716L,50717L,
-50718L,50719L,50720L,50721L,50722L,50723L,50724L,50725L,50726L,50727L,
-50728L,50729L,50730L,50731L,50732L,50733L,50734L,50735L,50736L,50737L,
-50738L,50739L,50740L,50741L,50742L,50743L,50744L,50745L,50746L,50747L,
-50748L,50749L,50750L,50751L,50752L,50753L,50754L,50755L,50756L,50757L,
-50758L,50759L,50760L,50761L,50762L,50763L,50764L,50765L,50766L,50767L,
-50768L,50769L,50770L,50771L,50772L,50773L,50774L,50775L,50776L,50777L,
-50778L,50779L,50780L,50781L,50782L,50783L,50784L,50785L,50786L,50787L,
-50788L,50789L,50790L,50791L,50792L,50793L,50794L,50795L,50796L,50797L,
-50798L,50799L,50800L,50801L,50802L,50803L,50804L,50805L,50806L,50807L,
-50808L,50809L,50810L,50811L,50812L,50813L,50814L,50815L,50816L,50817L,
-50818L,50819L,50820L,50821L,50822L,50823L,50824L,50825L,50826L,50827L,
-50828L,50829L,50830L,50831L,50832L,50833L,50834L,50835L,50836L,50837L,
-50838L,50839L,50840L,50841L,50842L,50843L,50844L,50845L,50846L,50847L,
-50848L,50849L,50850L,50851L,50852L,50853L,50854L,50855L,50856L,50857L,
-50858L,50859L,50860L,50861L,50862L,50863L,50864L,50865L,50866L,50867L,
-50868L,50869L,50870L,50871L,50872L,50873L,50874L,50875L,50876L,50877L,
-50878L,50879L,50880L,50881L,50882L,50883L,50884L,50885L,50886L,50887L,
-50888L,50889L,50890L,50891L,50892L,50893L,50894L,50895L,50896L,50897L,
-50898L,50899L,50900L,50901L,50902L,50903L,50904L,50905L,50906L,50907L,
-50908L,50909L,50910L,50911L,50912L,50913L,50914L,50915L,50916L,50917L,
-50918L,50919L,50920L,50921L,50922L,50923L,50924L,50925L,50926L,50927L,
-50928L,50929L,50930L,50931L,50932L,50933L,50934L,50935L,50936L,50937L,
-50938L,50939L,50940L,50941L,50942L,50943L,50944L,50945L,50946L,50947L,
-50948L,50949L,50950L,50951L,50952L,50953L,50954L,50955L,50956L,50957L,
-50958L,50959L,50960L,50961L,50962L,50963L,50964L,50965L,50966L,50967L,
-50968L,50969L,50970L,50971L,50972L,50973L,50974L,50975L,50976L,50977L,
-50978L,50979L,50980L,50981L,50982L,50983L,50984L,50985L,50986L,50987L,
-50988L,50989L,50990L,50991L,50992L,50993L,50994L,50995L,50996L,50997L,
-50998L,50999L,51000L,51001L,51002L,51003L,51004L,51005L,51006L,51007L,
-51008L,51009L,51010L,51011L,51012L,51013L,51014L,51015L,51016L,51017L,
-51018L,51019L,51020L,51021L,51022L,51023L,51024L,51025L,51026L,51027L,
-51028L,51029L,51030L,51031L,51032L,51033L,51034L,51035L,51036L,51037L,
-51038L,51039L,51040L,51041L,51042L,51043L,51044L,51045L,51046L,51047L,
-51048L,51049L,51050L,51051L,51052L,51053L,51054L,51055L,51056L,51057L,
-51058L,51059L,51060L,51061L,51062L,51063L,51064L,51065L,51066L,51067L,
-51068L,51069L,51070L,51071L,51072L,51073L,51074L,51075L,51076L,51077L,
-51078L,51079L,51080L,51081L,51082L,51083L,51084L,51085L,51086L,51087L,
-51088L,51089L,51090L,51091L,51092L,51093L,51094L,51095L,51096L,51097L,
-51098L,51099L,51100L,51101L,51102L,51103L,51104L,51105L,51106L,51107L,
-51108L,51109L,51110L,51111L,51112L,51113L,51114L,51115L,51116L,51117L,
-51118L,51119L,51120L,51121L,51122L,51123L,51124L,51125L,51126L,51127L,
-51128L,51129L,51130L,51131L,51132L,51133L,51134L,51135L,51136L,51137L,
-51138L,51139L,51140L,51141L,51142L,51143L,51144L,51145L,51146L,51147L,
-51148L,51149L,51150L,51151L,51152L,51153L,51154L,51155L,51156L,51157L,
-51158L,51159L,51160L,51161L,51162L,51163L,51164L,51165L,51166L,51167L,
-51168L,51169L,51170L,51171L,51172L,51173L,51174L,51175L,51176L,51177L,
-51178L,51179L,51180L,51181L,51182L,51183L,51184L,51185L,51186L,51187L,
-51188L,51189L,51190L,51191L,51192L,51193L,51194L,51195L,51196L,51197L,
-51198L,51199L,51200L,51201L,51202L,51203L,51204L,51205L,51206L,51207L,
-51208L,51209L,51210L,51211L,51212L,51213L,51214L,51215L,51216L,51217L,
-51218L,51219L,51220L,51221L,51222L,51223L,51224L,51225L,51226L,51227L,
-51228L,51229L,51230L,51231L,51232L,51233L,51234L,51235L,51236L,51237L,
-51238L,51239L,51240L,51241L,51242L,51243L,51244L,51245L,51246L,51247L,
-51248L,51249L,51250L,51251L,51252L,51253L,51254L,51255L,51256L,51257L,
-51258L,51259L,51260L,51261L,51262L,51263L,51264L,51265L,51266L,51267L,
-51268L,51269L,51270L,51271L,51272L,51273L,51274L,51275L,51276L,51277L,
-51278L,51279L,51280L,51281L,51282L,51283L,51284L,51285L,51286L,51287L,
-51288L,51289L,51290L,51291L,51292L,51293L,51294L,51295L,51296L,51297L,
-51298L,51299L,51300L,51301L,51302L,51303L,51304L,51305L,51306L,51307L,
-51308L,51309L,51310L,51311L,51312L,51313L,51314L,51315L,51316L,51317L,
-51318L,51319L,51320L,51321L,51322L,51323L,51324L,51325L,51326L,51327L,
-51328L,51329L,51330L,51331L,51332L,51333L,51334L,51335L,51336L,51337L,
-51338L,51339L,51340L,51341L,51342L,51343L,51344L,51345L,51346L,51347L,
-51348L,51349L,51350L,51351L,51352L,51353L,51354L,51355L,51356L,51357L,
-51358L,51359L,51360L,51361L,51362L,51363L,51364L,51365L,51366L,51367L,
-51368L,51369L,51370L,51371L,51372L,51373L,51374L,51375L,51376L,51377L,
-51378L,51379L,51380L,51381L,51382L,51383L,51384L,51385L,51386L,51387L,
-51388L,51389L,51390L,51391L,51392L,51393L,51394L,51395L,51396L,51397L,
-51398L,51399L,51400L,51401L,51402L,51403L,51404L,51405L,51406L,51407L,
-51408L,51409L,51410L,51411L,51412L,51413L,51414L,51415L,51416L,51417L,
-51418L,51419L,51420L,51421L,51422L,51423L,51424L,51425L,51426L,51427L,
-51428L,51429L,51430L,51431L,51432L,51433L,51434L,51435L,51436L,51437L,
-51438L,51439L,51440L,51441L,51442L,51443L,51444L,51445L,51446L,51447L,
-51448L,51449L,51450L,51451L,51452L,51453L,51454L,51455L,51456L,51457L,
-51458L,51459L,51460L,51461L,51462L,51463L,51464L,51465L,51466L,51467L,
-51468L,51469L,51470L,51471L,51472L,51473L,51474L,51475L,51476L,51477L,
-51478L,51479L,51480L,51481L,51482L,51483L,51484L,51485L,51486L,51487L,
-51488L,51489L,51490L,51491L,51492L,51493L,51494L,51495L,51496L,51497L,
-51498L,51499L,51500L,51501L,51502L,51503L,51504L,51505L,51506L,51507L,
-51508L,51509L,51510L,51511L,51512L,51513L,51514L,51515L,51516L,51517L,
-51518L,51519L,51520L,51521L,51522L,51523L,51524L,51525L,51526L,51527L,
-51528L,51529L,51530L,51531L,51532L,51533L,51534L,51535L,51536L,51537L,
-51538L,51539L,51540L,51541L,51542L,51543L,51544L,51545L,51546L,51547L,
-51548L,51549L,51550L,51551L,51552L,51553L,51554L,51555L,51556L,51557L,
-51558L,51559L,51560L,51561L,51562L,51563L,51564L,51565L,51566L,51567L,
-51568L,51569L,51570L,51571L,51572L,51573L,51574L,51575L,51576L,51577L,
-51578L,51579L,51580L,51581L,51582L,51583L,51584L,51585L,51586L,51587L,
-51588L,51589L,51590L,51591L,51592L,51593L,51594L,51595L,51596L,51597L,
-51598L,51599L,51600L,51601L,51602L,51603L,51604L,51605L,51606L,51607L,
-51608L,51609L,51610L,51611L,51612L,51613L,51614L,51615L,51616L,51617L,
-51618L,51619L,51620L,51621L,51622L,51623L,51624L,51625L,51626L,51627L,
-51628L,51629L,51630L,51631L,51632L,51633L,51634L,51635L,51636L,51637L,
-51638L,51639L,51640L,51641L,51642L,51643L,51644L,51645L,51646L,51647L,
-51648L,51649L,51650L,51651L,51652L,51653L,51654L,51655L,51656L,51657L,
-51658L,51659L,51660L,51661L,51662L,51663L,51664L,51665L,51666L,51667L,
-51668L,51669L,51670L,51671L,51672L,51673L,51674L,51675L,51676L,51677L,
-51678L,51679L,51680L,51681L,51682L,51683L,51684L,51685L,51686L,51687L,
-51688L,51689L,51690L,51691L,51692L,51693L,51694L,51695L,51696L,51697L,
-51698L,51699L,51700L,51701L,51702L,51703L,51704L,51705L,51706L,51707L,
-51708L,51709L,51710L,51711L,51712L,51713L,51714L,51715L,51716L,51717L,
-51718L,51719L,51720L,51721L,51722L,51723L,51724L,51725L,51726L,51727L,
-51728L,51729L,51730L,51731L,51732L,51733L,51734L,51735L,51736L,51737L,
-51738L,51739L,51740L,51741L,51742L,51743L,51744L,51745L,51746L,51747L,
-51748L,51749L,51750L,51751L,51752L,51753L,51754L,51755L,51756L,51757L,
-51758L,51759L,51760L,51761L,51762L,51763L,51764L,51765L,51766L,51767L,
-51768L,51769L,51770L,51771L,51772L,51773L,51774L,51775L,51776L,51777L,
-51778L,51779L,51780L,51781L,51782L,51783L,51784L,51785L,51786L,51787L,
-51788L,51789L,51790L,51791L,51792L,51793L,51794L,51795L,51796L,51797L,
-51798L,51799L,51800L,51801L,51802L,51803L,51804L,51805L,51806L,51807L,
-51808L,51809L,51810L,51811L,51812L,51813L,51814L,51815L,51816L,51817L,
-51818L,51819L,51820L,51821L,51822L,51823L,51824L,51825L,51826L,51827L,
-51828L,51829L,51830L,51831L,51832L,51833L,51834L,51835L,51836L,51837L,
-51838L,51839L,51840L,51841L,51842L,51843L,51844L,51845L,51846L,51847L,
-51848L,51849L,51850L,51851L,51852L,51853L,51854L,51855L,51856L,51857L,
-51858L,51859L,51860L,51861L,51862L,51863L,51864L,51865L,51866L,51867L,
-51868L,51869L,51870L,51871L,51872L,51873L,51874L,51875L,51876L,51877L,
-51878L,51879L,51880L,51881L,51882L,51883L,51884L,51885L,51886L,51887L,
-51888L,51889L,51890L,51891L,51892L,51893L,51894L,51895L,51896L,51897L,
-51898L,51899L,51900L,51901L,51902L,51903L,51904L,51905L,51906L,51907L,
-51908L,51909L,51910L,51911L,51912L,51913L,51914L,51915L,51916L,51917L,
-51918L,51919L,51920L,51921L,51922L,51923L,51924L,51925L,51926L,51927L,
-51928L,51929L,51930L,51931L,51932L,51933L,51934L,51935L,51936L,51937L,
-51938L,51939L,51940L,51941L,51942L,51943L,51944L,51945L,51946L,51947L,
-51948L,51949L,51950L,51951L,51952L,51953L,51954L,51955L,51956L,51957L,
-51958L,51959L,51960L,51961L,51962L,51963L,51964L,51965L,51966L,51967L,
-51968L,51969L,51970L,51971L,51972L,51973L,51974L,51975L,51976L,51977L,
-51978L,51979L,51980L,51981L,51982L,51983L,51984L,51985L,51986L,51987L,
-51988L,51989L,51990L,51991L,51992L,51993L,51994L,51995L,51996L,51997L,
-51998L,51999L,52000L,52001L,52002L,52003L,52004L,52005L,52006L,52007L,
-52008L,52009L,52010L,52011L,52012L,52013L,52014L,52015L,52016L,52017L,
-52018L,52019L,52020L,52021L,52022L,52023L,52024L,52025L,52026L,52027L,
-52028L,52029L,52030L,52031L,52032L,52033L,52034L,52035L,52036L,52037L,
-52038L,52039L,52040L,52041L,52042L,52043L,52044L,52045L,52046L,52047L,
-52048L,52049L,52050L,52051L,52052L,52053L,52054L,52055L,52056L,52057L,
-52058L,52059L,52060L,52061L,52062L,52063L,52064L,52065L,52066L,52067L,
-52068L,52069L,52070L,52071L,52072L,52073L,52074L,52075L,52076L,52077L,
-52078L,52079L,52080L,52081L,52082L,52083L,52084L,52085L,52086L,52087L,
-52088L,52089L,52090L,52091L,52092L,52093L,52094L,52095L,52096L,52097L,
-52098L,52099L,52100L,52101L,52102L,52103L,52104L,52105L,52106L,52107L,
-52108L,52109L,52110L,52111L,52112L,52113L,52114L,52115L,52116L,52117L,
-52118L,52119L,52120L,52121L,52122L,52123L,52124L,52125L,52126L,52127L,
-52128L,52129L,52130L,52131L,52132L,52133L,52134L,52135L,52136L,52137L,
-52138L,52139L,52140L,52141L,52142L,52143L,52144L,52145L,52146L,52147L,
-52148L,52149L,52150L,52151L,52152L,52153L,52154L,52155L,52156L,52157L,
-52158L,52159L,52160L,52161L,52162L,52163L,52164L,52165L,52166L,52167L,
-52168L,52169L,52170L,52171L,52172L,52173L,52174L,52175L,52176L,52177L,
-52178L,52179L,52180L,52181L,52182L,52183L,52184L,52185L,52186L,52187L,
-52188L,52189L,52190L,52191L,52192L,52193L,52194L,52195L,52196L,52197L,
-52198L,52199L,52200L,52201L,52202L,52203L,52204L,52205L,52206L,52207L,
-52208L,52209L,52210L,52211L,52212L,52213L,52214L,52215L,52216L,52217L,
-52218L,52219L,52220L,52221L,52222L,52223L,52224L,52225L,52226L,52227L,
-52228L,52229L,52230L,52231L,52232L,52233L,52234L,52235L,52236L,52237L,
-52238L,52239L,52240L,52241L,52242L,52243L,52244L,52245L,52246L,52247L,
-52248L,52249L,52250L,52251L,52252L,52253L,52254L,52255L,52256L,52257L,
-52258L,52259L,52260L,52261L,52262L,52263L,52264L,52265L,52266L,52267L,
-52268L,52269L,52270L,52271L,52272L,52273L,52274L,52275L,52276L,52277L,
-52278L,52279L,52280L,52281L,52282L,52283L,52284L,52285L,52286L,52287L,
-52288L,52289L,52290L,52291L,52292L,52293L,52294L,52295L,52296L,52297L,
-52298L,52299L,52300L,52301L,52302L,52303L,52304L,52305L,52306L,52307L,
-52308L,52309L,52310L,52311L,52312L,52313L,52314L,52315L,52316L,52317L,
-52318L,52319L,52320L,52321L,52322L,52323L,52324L,52325L,52326L,52327L,
-52328L,52329L,52330L,52331L,52332L,52333L,52334L,52335L,52336L,52337L,
-52338L,52339L,52340L,52341L,52342L,52343L,52344L,52345L,52346L,52347L,
-52348L,52349L,52350L,52351L,52352L,52353L,52354L,52355L,52356L,52357L,
-52358L,52359L,52360L,52361L,52362L,52363L,52364L,52365L,52366L,52367L,
-52368L,52369L,52370L,52371L,52372L,52373L,52374L,52375L,52376L,52377L,
-52378L,52379L,52380L,52381L,52382L,52383L,52384L,52385L,52386L,52387L,
-52388L,52389L,52390L,52391L,52392L,52393L,52394L,52395L,52396L,52397L,
-52398L,52399L,52400L,52401L,52402L,52403L,52404L,52405L,52406L,52407L,
-52408L,52409L,52410L,52411L,52412L,52413L,52414L,52415L,52416L,52417L,
-52418L,52419L,52420L,52421L,52422L,52423L,52424L,52425L,52426L,52427L,
-52428L,52429L,52430L,52431L,52432L,52433L,52434L,52435L,52436L,52437L,
-52438L,52439L,52440L,52441L,52442L,52443L,52444L,52445L,52446L,52447L,
-52448L,52449L,52450L,52451L,52452L,52453L,52454L,52455L,52456L,52457L,
-52458L,52459L,52460L,52461L,52462L,52463L,52464L,52465L,52466L,52467L,
-52468L,52469L,52470L,52471L,52472L,52473L,52474L,52475L,52476L,52477L,
-52478L,52479L,52480L,52481L,52482L,52483L,52484L,52485L,52486L,52487L,
-52488L,52489L,52490L,52491L,52492L,52493L,52494L,52495L,52496L,52497L,
-52498L,52499L,52500L,52501L,52502L,52503L,52504L,52505L,52506L,52507L,
-52508L,52509L,52510L,52511L,52512L,52513L,52514L,52515L,52516L,52517L,
-52518L,52519L,52520L,52521L,52522L,52523L,52524L,52525L,52526L,52527L,
-52528L,52529L,52530L,52531L,52532L,52533L,52534L,52535L,52536L,52537L,
-52538L,52539L,52540L,52541L,52542L,52543L,52544L,52545L,52546L,52547L,
-52548L,52549L,52550L,52551L,52552L,52553L,52554L,52555L,52556L,52557L,
-52558L,52559L,52560L,52561L,52562L,52563L,52564L,52565L,52566L,52567L,
-52568L,52569L,52570L,52571L,52572L,52573L,52574L,52575L,52576L,52577L,
-52578L,52579L,52580L,52581L,52582L,52583L,52584L,52585L,52586L,52587L,
-52588L,52589L,52590L,52591L,52592L,52593L,52594L,52595L,52596L,52597L,
-52598L,52599L,52600L,52601L,52602L,52603L,52604L,52605L,52606L,52607L,
-52608L,52609L,52610L,52611L,52612L,52613L,52614L,52615L,52616L,52617L,
-52618L,52619L,52620L,52621L,52622L,52623L,52624L,52625L,52626L,52627L,
-52628L,52629L,52630L,52631L,52632L,52633L,52634L,52635L,52636L,52637L,
-52638L,52639L,52640L,52641L,52642L,52643L,52644L,52645L,52646L,52647L,
-52648L,52649L,52650L,52651L,52652L,52653L,52654L,52655L,52656L,52657L,
-52658L,52659L,52660L,52661L,52662L,52663L,52664L,52665L,52666L,52667L,
-52668L,52669L,52670L,52671L,52672L,52673L,52674L,52675L,52676L,52677L,
-52678L,52679L,52680L,52681L,52682L,52683L,52684L,52685L,52686L,52687L,
-52688L,52689L,52690L,52691L,52692L,52693L,52694L,52695L,52696L,52697L,
-52698L,52699L,52700L,52701L,52702L,52703L,52704L,52705L,52706L,52707L,
-52708L,52709L,52710L,52711L,52712L,52713L,52714L,52715L,52716L,52717L,
-52718L,52719L,52720L,52721L,52722L,52723L,52724L,52725L,52726L,52727L,
-52728L,52729L,52730L,52731L,52732L,52733L,52734L,52735L,52736L,52737L,
-52738L,52739L,52740L,52741L,52742L,52743L,52744L,52745L,52746L,52747L,
-52748L,52749L,52750L,52751L,52752L,52753L,52754L,52755L,52756L,52757L,
-52758L,52759L,52760L,52761L,52762L,52763L,52764L,52765L,52766L,52767L,
-52768L,52769L,52770L,52771L,52772L,52773L,52774L,52775L,52776L,52777L,
-52778L,52779L,52780L,52781L,52782L,52783L,52784L,52785L,52786L,52787L,
-52788L,52789L,52790L,52791L,52792L,52793L,52794L,52795L,52796L,52797L,
-52798L,52799L,52800L,52801L,52802L,52803L,52804L,52805L,52806L,52807L,
-52808L,52809L,52810L,52811L,52812L,52813L,52814L,52815L,52816L,52817L,
-52818L,52819L,52820L,52821L,52822L,52823L,52824L,52825L,52826L,52827L,
-52828L,52829L,52830L,52831L,52832L,52833L,52834L,52835L,52836L,52837L,
-52838L,52839L,52840L,52841L,52842L,52843L,52844L,52845L,52846L,52847L,
-52848L,52849L,52850L,52851L,52852L,52853L,52854L,52855L,52856L,52857L,
-52858L,52859L,52860L,52861L,52862L,52863L,52864L,52865L,52866L,52867L,
-52868L,52869L,52870L,52871L,52872L,52873L,52874L,52875L,52876L,52877L,
-52878L,52879L,52880L,52881L,52882L,52883L,52884L,52885L,52886L,52887L,
-52888L,52889L,52890L,52891L,52892L,52893L,52894L,52895L,52896L,52897L,
-52898L,52899L,52900L,52901L,52902L,52903L,52904L,52905L,52906L,52907L,
-52908L,52909L,52910L,52911L,52912L,52913L,52914L,52915L,52916L,52917L,
-52918L,52919L,52920L,52921L,52922L,52923L,52924L,52925L,52926L,52927L,
-52928L,52929L,52930L,52931L,52932L,52933L,52934L,52935L,52936L,52937L,
-52938L,52939L,52940L,52941L,52942L,52943L,52944L,52945L,52946L,52947L,
-52948L,52949L,52950L,52951L,52952L,52953L,52954L,52955L,52956L,52957L,
-52958L,52959L,52960L,52961L,52962L,52963L,52964L,52965L,52966L,52967L,
-52968L,52969L,52970L,52971L,52972L,52973L,52974L,52975L,52976L,52977L,
-52978L,52979L,52980L,52981L,52982L,52983L,52984L,52985L,52986L,52987L,
-52988L,52989L,52990L,52991L,52992L,52993L,52994L,52995L,52996L,52997L,
-52998L,52999L,53000L,53001L,53002L,53003L,53004L,53005L,53006L,53007L,
-53008L,53009L,53010L,53011L,53012L,53013L,53014L,53015L,53016L,53017L,
-53018L,53019L,53020L,53021L,53022L,53023L,53024L,53025L,53026L,53027L,
-53028L,53029L,53030L,53031L,53032L,53033L,53034L,53035L,53036L,53037L,
-53038L,53039L,53040L,53041L,53042L,53043L,53044L,53045L,53046L,53047L,
-53048L,53049L,53050L,53051L,53052L,53053L,53054L,53055L,53056L,53057L,
-53058L,53059L,53060L,53061L,53062L,53063L,53064L,53065L,53066L,53067L,
-53068L,53069L,53070L,53071L,53072L,53073L,53074L,53075L,53076L,53077L,
-53078L,53079L,53080L,53081L,53082L,53083L,53084L,53085L,53086L,53087L,
-53088L,53089L,53090L,53091L,53092L,53093L,53094L,53095L,53096L,53097L,
-53098L,53099L,53100L,53101L,53102L,53103L,53104L,53105L,53106L,53107L,
-53108L,53109L,53110L,53111L,53112L,53113L,53114L,53115L,53116L,53117L,
-53118L,53119L,53120L,53121L,53122L,53123L,53124L,53125L,53126L,53127L,
-53128L,53129L,53130L,53131L,53132L,53133L,53134L,53135L,53136L,53137L,
-53138L,53139L,53140L,53141L,53142L,53143L,53144L,53145L,53146L,53147L,
-53148L,53149L,53150L,53151L,53152L,53153L,53154L,53155L,53156L,53157L,
-53158L,53159L,53160L,53161L,53162L,53163L,53164L,53165L,53166L,53167L,
-53168L,53169L,53170L,53171L,53172L,53173L,53174L,53175L,53176L,53177L,
-53178L,53179L,53180L,53181L,53182L,53183L,53184L,53185L,53186L,53187L,
-53188L,53189L,53190L,53191L,53192L,53193L,53194L,53195L,53196L,53197L,
-53198L,53199L,53200L,53201L,53202L,53203L,53204L,53205L,53206L,53207L,
-53208L,53209L,53210L,53211L,53212L,53213L,53214L,53215L,53216L,53217L,
-53218L,53219L,53220L,53221L,53222L,53223L,53224L,53225L,53226L,53227L,
-53228L,53229L,53230L,53231L,53232L,53233L,53234L,53235L,53236L,53237L,
-53238L,53239L,53240L,53241L,53242L,53243L,53244L,53245L,53246L,53247L,
-53248L,53249L,53250L,53251L,53252L,53253L,53254L,53255L,53256L,53257L,
-53258L,53259L,53260L,53261L,53262L,53263L,53264L,53265L,53266L,53267L,
-53268L,53269L,53270L,53271L,53272L,53273L,53274L,53275L,53276L,53277L,
-53278L,53279L,53280L,53281L,53282L,53283L,53284L,53285L,53286L,53287L,
-53288L,53289L,53290L,53291L,53292L,53293L,53294L,53295L,53296L,53297L,
-53298L,53299L,53300L,53301L,53302L,53303L,53304L,53305L,53306L,53307L,
-53308L,53309L,53310L,53311L,53312L,53313L,53314L,53315L,53316L,53317L,
-53318L,53319L,53320L,53321L,53322L,53323L,53324L,53325L,53326L,53327L,
-53328L,53329L,53330L,53331L,53332L,53333L,53334L,53335L,53336L,53337L,
-53338L,53339L,53340L,53341L,53342L,53343L,53344L,53345L,53346L,53347L,
-53348L,53349L,53350L,53351L,53352L,53353L,53354L,53355L,53356L,53357L,
-53358L,53359L,53360L,53361L,53362L,53363L,53364L,53365L,53366L,53367L,
-53368L,53369L,53370L,53371L,53372L,53373L,53374L,53375L,53376L,53377L,
-53378L,53379L,53380L,53381L,53382L,53383L,53384L,53385L,53386L,53387L,
-53388L,53389L,53390L,53391L,53392L,53393L,53394L,53395L,53396L,53397L,
-53398L,53399L,53400L,53401L,53402L,53403L,53404L,53405L,53406L,53407L,
-53408L,53409L,53410L,53411L,53412L,53413L,53414L,53415L,53416L,53417L,
-53418L,53419L,53420L,53421L,53422L,53423L,53424L,53425L,53426L,53427L,
-53428L,53429L,53430L,53431L,53432L,53433L,53434L,53435L,53436L,53437L,
-53438L,53439L,53440L,53441L,53442L,53443L,53444L,53445L,53446L,53447L,
-53448L,53449L,53450L,53451L,53452L,53453L,53454L,53455L,53456L,53457L,
-53458L,53459L,53460L,53461L,53462L,53463L,53464L,53465L,53466L,53467L,
-53468L,53469L,53470L,53471L,53472L,53473L,53474L,53475L,53476L,53477L,
-53478L,53479L,53480L,53481L,53482L,53483L,53484L,53485L,53486L,53487L,
-53488L,53489L,53490L,53491L,53492L,53493L,53494L,53495L,53496L,53497L,
-53498L,53499L,53500L,53501L,53502L,53503L,53504L,53505L,53506L,53507L,
-53508L,53509L,53510L,53511L,53512L,53513L,53514L,53515L,53516L,53517L,
-53518L,53519L,53520L,53521L,53522L,53523L,53524L,53525L,53526L,53527L,
-53528L,53529L,53530L,53531L,53532L,53533L,53534L,53535L,53536L,53537L,
-53538L,53539L,53540L,53541L,53542L,53543L,53544L,53545L,53546L,53547L,
-53548L,53549L,53550L,53551L,53552L,53553L,53554L,53555L,53556L,53557L,
-53558L,53559L,53560L,53561L,53562L,53563L,53564L,53565L,53566L,53567L,
-53568L,53569L,53570L,53571L,53572L,53573L,53574L,53575L,53576L,53577L,
-53578L,53579L,53580L,53581L,53582L,53583L,53584L,53585L,53586L,53587L,
-53588L,53589L,53590L,53591L,53592L,53593L,53594L,53595L,53596L,53597L,
-53598L,53599L,53600L,53601L,53602L,53603L,53604L,53605L,53606L,53607L,
-53608L,53609L,53610L,53611L,53612L,53613L,53614L,53615L,53616L,53617L,
-53618L,53619L,53620L,53621L,53622L,53623L,53624L,53625L,53626L,53627L,
-53628L,53629L,53630L,53631L,53632L,53633L,53634L,53635L,53636L,53637L,
-53638L,53639L,53640L,53641L,53642L,53643L,53644L,53645L,53646L,53647L,
-53648L,53649L,53650L,53651L,53652L,53653L,53654L,53655L,53656L,53657L,
-53658L,53659L,53660L,53661L,53662L,53663L,53664L,53665L,53666L,53667L,
-53668L,53669L,53670L,53671L,53672L,53673L,53674L,53675L,53676L,53677L,
-53678L,53679L,53680L,53681L,53682L,53683L,53684L,53685L,53686L,53687L,
-53688L,53689L,53690L,53691L,53692L,53693L,53694L,53695L,53696L,53697L,
-53698L,53699L,53700L,53701L,53702L,53703L,53704L,53705L,53706L,53707L,
-53708L,53709L,53710L,53711L,53712L,53713L,53714L,53715L,53716L,53717L,
-53718L,53719L,53720L,53721L,53722L,53723L,53724L,53725L,53726L,53727L,
-53728L,53729L,53730L,53731L,53732L,53733L,53734L,53735L,53736L,53737L,
-53738L,53739L,53740L,53741L,53742L,53743L,53744L,53745L,53746L,53747L,
-53748L,53749L,53750L,53751L,53752L,53753L,53754L,53755L,53756L,53757L,
-53758L,53759L,53760L,53761L,53762L,53763L,53764L,53765L,53766L,53767L,
-53768L,53769L,53770L,53771L,53772L,53773L,53774L,53775L,53776L,53777L,
-53778L,53779L,53780L,53781L,53782L,53783L,53784L,53785L,53786L,53787L,
-53788L,53789L,53790L,53791L,53792L,53793L,53794L,53795L,53796L,53797L,
-53798L,53799L,53800L,53801L,53802L,53803L,53804L,53805L,53806L,53807L,
-53808L,53809L,53810L,53811L,53812L,53813L,53814L,53815L,53816L,53817L,
-53818L,53819L,53820L,53821L,53822L,53823L,53824L,53825L,53826L,53827L,
-53828L,53829L,53830L,53831L,53832L,53833L,53834L,53835L,53836L,53837L,
-53838L,53839L,53840L,53841L,53842L,53843L,53844L,53845L,53846L,53847L,
-53848L,53849L,53850L,53851L,53852L,53853L,53854L,53855L,53856L,53857L,
-53858L,53859L,53860L,53861L,53862L,53863L,53864L,53865L,53866L,53867L,
-53868L,53869L,53870L,53871L,53872L,53873L,53874L,53875L,53876L,53877L,
-53878L,53879L,53880L,53881L,53882L,53883L,53884L,53885L,53886L,53887L,
-53888L,53889L,53890L,53891L,53892L,53893L,53894L,53895L,53896L,53897L,
-53898L,53899L,53900L,53901L,53902L,53903L,53904L,53905L,53906L,53907L,
-53908L,53909L,53910L,53911L,53912L,53913L,53914L,53915L,53916L,53917L,
-53918L,53919L,53920L,53921L,53922L,53923L,53924L,53925L,53926L,53927L,
-53928L,53929L,53930L,53931L,53932L,53933L,53934L,53935L,53936L,53937L,
-53938L,53939L,53940L,53941L,53942L,53943L,53944L,53945L,53946L,53947L,
-53948L,53949L,53950L,53951L,53952L,53953L,53954L,53955L,53956L,53957L,
-53958L,53959L,53960L,53961L,53962L,53963L,53964L,53965L,53966L,53967L,
-53968L,53969L,53970L,53971L,53972L,53973L,53974L,53975L,53976L,53977L,
-53978L,53979L,53980L,53981L,53982L,53983L,53984L,53985L,53986L,53987L,
-53988L,53989L,53990L,53991L,53992L,53993L,53994L,53995L,53996L,53997L,
-53998L,53999L,54000L,54001L,54002L,54003L,54004L,54005L,54006L,54007L,
-54008L,54009L,54010L,54011L,54012L,54013L,54014L,54015L,54016L,54017L,
-54018L,54019L,54020L,54021L,54022L,54023L,54024L,54025L,54026L,54027L,
-54028L,54029L,54030L,54031L,54032L,54033L,54034L,54035L,54036L,54037L,
-54038L,54039L,54040L,54041L,54042L,54043L,54044L,54045L,54046L,54047L,
-54048L,54049L,54050L,54051L,54052L,54053L,54054L,54055L,54056L,54057L,
-54058L,54059L,54060L,54061L,54062L,54063L,54064L,54065L,54066L,54067L,
-54068L,54069L,54070L,54071L,54072L,54073L,54074L,54075L,54076L,54077L,
-54078L,54079L,54080L,54081L,54082L,54083L,54084L,54085L,54086L,54087L,
-54088L,54089L,54090L,54091L,54092L,54093L,54094L,54095L,54096L,54097L,
-54098L,54099L,54100L,54101L,54102L,54103L,54104L,54105L,54106L,54107L,
-54108L,54109L,54110L,54111L,54112L,54113L,54114L,54115L,54116L,54117L,
-54118L,54119L,54120L,54121L,54122L,54123L,54124L,54125L,54126L,54127L,
-54128L,54129L,54130L,54131L,54132L,54133L,54134L,54135L,54136L,54137L,
-54138L,54139L,54140L,54141L,54142L,54143L,54144L,54145L,54146L,54147L,
-54148L,54149L,54150L,54151L,54152L,54153L,54154L,54155L,54156L,54157L,
-54158L,54159L,54160L,54161L,54162L,54163L,54164L,54165L,54166L,54167L,
-54168L,54169L,54170L,54171L,54172L,54173L,54174L,54175L,54176L,54177L,
-54178L,54179L,54180L,54181L,54182L,54183L,54184L,54185L,54186L,54187L,
-54188L,54189L,54190L,54191L,54192L,54193L,54194L,54195L,54196L,54197L,
-54198L,54199L,54200L,54201L,54202L,54203L,54204L,54205L,54206L,54207L,
-54208L,54209L,54210L,54211L,54212L,54213L,54214L,54215L,54216L,54217L,
-54218L,54219L,54220L,54221L,54222L,54223L,54224L,54225L,54226L,54227L,
-54228L,54229L,54230L,54231L,54232L,54233L,54234L,54235L,54236L,54237L,
-54238L,54239L,54240L,54241L,54242L,54243L,54244L,54245L,54246L,54247L,
-54248L,54249L,54250L,54251L,54252L,54253L,54254L,54255L,54256L,54257L,
-54258L,54259L,54260L,54261L,54262L,54263L,54264L,54265L,54266L,54267L,
-54268L,54269L,54270L,54271L,54272L,54273L,54274L,54275L,54276L,54277L,
-54278L,54279L,54280L,54281L,54282L,54283L,54284L,54285L,54286L,54287L,
-54288L,54289L,54290L,54291L,54292L,54293L,54294L,54295L,54296L,54297L,
-54298L,54299L,54300L,54301L,54302L,54303L,54304L,54305L,54306L,54307L,
-54308L,54309L,54310L,54311L,54312L,54313L,54314L,54315L,54316L,54317L,
-54318L,54319L,54320L,54321L,54322L,54323L,54324L,54325L,54326L,54327L,
-54328L,54329L,54330L,54331L,54332L,54333L,54334L,54335L,54336L,54337L,
-54338L,54339L,54340L,54341L,54342L,54343L,54344L,54345L,54346L,54347L,
-54348L,54349L,54350L,54351L,54352L,54353L,54354L,54355L,54356L,54357L,
-54358L,54359L,54360L,54361L,54362L,54363L,54364L,54365L,54366L,54367L,
-54368L,54369L,54370L,54371L,54372L,54373L,54374L,54375L,54376L,54377L,
-54378L,54379L,54380L,54381L,54382L,54383L,54384L,54385L,54386L,54387L,
-54388L,54389L,54390L,54391L,54392L,54393L,54394L,54395L,54396L,54397L,
-54398L,54399L,54400L,54401L,54402L,54403L,54404L,54405L,54406L,54407L,
-54408L,54409L,54410L,54411L,54412L,54413L,54414L,54415L,54416L,54417L,
-54418L,54419L,54420L,54421L,54422L,54423L,54424L,54425L,54426L,54427L,
-54428L,54429L,54430L,54431L,54432L,54433L,54434L,54435L,54436L,54437L,
-54438L,54439L,54440L,54441L,54442L,54443L,54444L,54445L,54446L,54447L,
-54448L,54449L,54450L,54451L,54452L,54453L,54454L,54455L,54456L,54457L,
-54458L,54459L,54460L,54461L,54462L,54463L,54464L,54465L,54466L,54467L,
-54468L,54469L,54470L,54471L,54472L,54473L,54474L,54475L,54476L,54477L,
-54478L,54479L,54480L,54481L,54482L,54483L,54484L,54485L,54486L,54487L,
-54488L,54489L,54490L,54491L,54492L,54493L,54494L,54495L,54496L,54497L,
-54498L,54499L,54500L,54501L,54502L,54503L,54504L,54505L,54506L,54507L,
-54508L,54509L,54510L,54511L,54512L,54513L,54514L,54515L,54516L,54517L,
-54518L,54519L,54520L,54521L,54522L,54523L,54524L,54525L,54526L,54527L,
-54528L,54529L,54530L,54531L,54532L,54533L,54534L,54535L,54536L,54537L,
-54538L,54539L,54540L,54541L,54542L,54543L,54544L,54545L,54546L,54547L,
-54548L,54549L,54550L,54551L,54552L,54553L,54554L,54555L,54556L,54557L,
-54558L,54559L,54560L,54561L,54562L,54563L,54564L,54565L,54566L,54567L,
-54568L,54569L,54570L,54571L,54572L,54573L,54574L,54575L,54576L,54577L,
-54578L,54579L,54580L,54581L,54582L,54583L,54584L,54585L,54586L,54587L,
-54588L,54589L,54590L,54591L,54592L,54593L,54594L,54595L,54596L,54597L,
-54598L,54599L,54600L,54601L,54602L,54603L,54604L,54605L,54606L,54607L,
-54608L,54609L,54610L,54611L,54612L,54613L,54614L,54615L,54616L,54617L,
-54618L,54619L,54620L,54621L,54622L,54623L,54624L,54625L,54626L,54627L,
-54628L,54629L,54630L,54631L,54632L,54633L,54634L,54635L,54636L,54637L,
-54638L,54639L,54640L,54641L,54642L,54643L,54644L,54645L,54646L,54647L,
-54648L,54649L,54650L,54651L,54652L,54653L,54654L,54655L,54656L,54657L,
-54658L,54659L,54660L,54661L,54662L,54663L,54664L,54665L,54666L,54667L,
-54668L,54669L,54670L,54671L,54672L,54673L,54674L,54675L,54676L,54677L,
-54678L,54679L,54680L,54681L,54682L,54683L,54684L,54685L,54686L,54687L,
-54688L,54689L,54690L,54691L,54692L,54693L,54694L,54695L,54696L,54697L,
-54698L,54699L,54700L,54701L,54702L,54703L,54704L,54705L,54706L,54707L,
-54708L,54709L,54710L,54711L,54712L,54713L,54714L,54715L,54716L,54717L,
-54718L,54719L,54720L,54721L,54722L,54723L,54724L,54725L,54726L,54727L,
-54728L,54729L,54730L,54731L,54732L,54733L,54734L,54735L,54736L,54737L,
-54738L,54739L,54740L,54741L,54742L,54743L,54744L,54745L,54746L,54747L,
-54748L,54749L,54750L,54751L,54752L,54753L,54754L,54755L,54756L,54757L,
-54758L,54759L,54760L,54761L,54762L,54763L,54764L,54765L,54766L,54767L,
-54768L,54769L,54770L,54771L,54772L,54773L,54774L,54775L,54776L,54777L,
-54778L,54779L,54780L,54781L,54782L,54783L,54784L,54785L,54786L,54787L,
-54788L,54789L,54790L,54791L,54792L,54793L,54794L,54795L,54796L,54797L,
-54798L,54799L,54800L,54801L,54802L,54803L,54804L,54805L,54806L,54807L,
-54808L,54809L,54810L,54811L,54812L,54813L,54814L,54815L,54816L,54817L,
-54818L,54819L,54820L,54821L,54822L,54823L,54824L,54825L,54826L,54827L,
-54828L,54829L,54830L,54831L,54832L,54833L,54834L,54835L,54836L,54837L,
-54838L,54839L,54840L,54841L,54842L,54843L,54844L,54845L,54846L,54847L,
-54848L,54849L,54850L,54851L,54852L,54853L,54854L,54855L,54856L,54857L,
-54858L,54859L,54860L,54861L,54862L,54863L,54864L,54865L,54866L,54867L,
-54868L,54869L,54870L,54871L,54872L,54873L,54874L,54875L,54876L,54877L,
-54878L,54879L,54880L,54881L,54882L,54883L,54884L,54885L,54886L,54887L,
-54888L,54889L,54890L,54891L,54892L,54893L,54894L,54895L,54896L,54897L,
-54898L,54899L,54900L,54901L,54902L,54903L,54904L,54905L,54906L,54907L,
-54908L,54909L,54910L,54911L,54912L,54913L,54914L,54915L,54916L,54917L,
-54918L,54919L,54920L,54921L,54922L,54923L,54924L,54925L,54926L,54927L,
-54928L,54929L,54930L,54931L,54932L,54933L,54934L,54935L,54936L,54937L,
-54938L,54939L,54940L,54941L,54942L,54943L,54944L,54945L,54946L,54947L,
-54948L,54949L,54950L,54951L,54952L,54953L,54954L,54955L,54956L,54957L,
-54958L,54959L,54960L,54961L,54962L,54963L,54964L,54965L,54966L,54967L,
-54968L,54969L,54970L,54971L,54972L,54973L,54974L,54975L,54976L,54977L,
-54978L,54979L,54980L,54981L,54982L,54983L,54984L,54985L,54986L,54987L,
-54988L,54989L,54990L,54991L,54992L,54993L,54994L,54995L,54996L,54997L,
-54998L,54999L,55000L,55001L,55002L,55003L,55004L,55005L,55006L,55007L,
-55008L,55009L,55010L,55011L,55012L,55013L,55014L,55015L,55016L,55017L,
-55018L,55019L,55020L,55021L,55022L,55023L,55024L,55025L,55026L,55027L,
-55028L,55029L,55030L,55031L,55032L,55033L,55034L,55035L,55036L,55037L,
-55038L,55039L,55040L,55041L,55042L,55043L,55044L,55045L,55046L,55047L,
-55048L,55049L,55050L,55051L,55052L,55053L,55054L,55055L,55056L,55057L,
-55058L,55059L,55060L,55061L,55062L,55063L,55064L,55065L,55066L,55067L,
-55068L,55069L,55070L,55071L,55072L,55073L,55074L,55075L,55076L,55077L,
-55078L,55079L,55080L,55081L,55082L,55083L,55084L,55085L,55086L,55087L,
-55088L,55089L,55090L,55091L,55092L,55093L,55094L,55095L,55096L,55097L,
-55098L,55099L,55100L,55101L,55102L,55103L,55104L,55105L,55106L,55107L,
-55108L,55109L,55110L,55111L,55112L,55113L,55114L,55115L,55116L,55117L,
-55118L,55119L,55120L,55121L,55122L,55123L,55124L,55125L,55126L,55127L,
-55128L,55129L,55130L,55131L,55132L,55133L,55134L,55135L,55136L,55137L,
-55138L,55139L,55140L,55141L,55142L,55143L,55144L,55145L,55146L,55147L,
-55148L,55149L,55150L,55151L,55152L,55153L,55154L,55155L,55156L,55157L,
-55158L,55159L,55160L,55161L,55162L,55163L,55164L,55165L,55166L,55167L,
-55168L,55169L,55170L,55171L,55172L,55173L,55174L,55175L,55176L,55177L,
-55178L,55179L,55180L,55181L,55182L,55183L,55184L,55185L,55186L,55187L,
-55188L,55189L,55190L,55191L,55192L,55193L,55194L,55195L,55196L,55197L,
-55198L,55199L,55200L,55201L,55202L,55203L,55204L,55205L,55206L,55207L,
-55208L,55209L,55210L,55211L,55212L,55213L,55214L,55215L,55216L,55217L,
-55218L,55219L,55220L,55221L,55222L,55223L,55224L,55225L,55226L,55227L,
-55228L,55229L,55230L,55231L,55232L,55233L,55234L,55235L,55236L,55237L,
-55238L,55239L,55240L,55241L,55242L,55243L,55244L,55245L,55246L,55247L,
-55248L,55249L,55250L,55251L,55252L,55253L,55254L,55255L,55256L,55257L,
-55258L,55259L,55260L,55261L,55262L,55263L,55264L,55265L,55266L,55267L,
-55268L,55269L,55270L,55271L,55272L,55273L,55274L,55275L,55276L,55277L,
-55278L,55279L,55280L,55281L,55282L,55283L,55284L,55285L,55286L,55287L,
-55288L,55289L,55290L,55291L,55292L,55293L,55294L,55295L,55296L,55297L,
-55298L,55299L,55300L,55301L,55302L,55303L,55304L,55305L,55306L,55307L,
-55308L,55309L,55310L,55311L,55312L,55313L,55314L,55315L,55316L,55317L,
-55318L,55319L,55320L,55321L,55322L,55323L,55324L,55325L,55326L,55327L,
-55328L,55329L,55330L,55331L,55332L,55333L,55334L,55335L,55336L,55337L,
-55338L,55339L,55340L,55341L,55342L,55343L,55344L,55345L,55346L,55347L,
-55348L,55349L,55350L,55351L,55352L,55353L,55354L,55355L,55356L,55357L,
-55358L,55359L,55360L,55361L,55362L,55363L,55364L,55365L,55366L,55367L,
-55368L,55369L,55370L,55371L,55372L,55373L,55374L,55375L,55376L,55377L,
-55378L,55379L,55380L,55381L,55382L,55383L,55384L,55385L,55386L,55387L,
-55388L,55389L,55390L,55391L,55392L,55393L,55394L,55395L,55396L,55397L,
-55398L,55399L,55400L,55401L,55402L,55403L,55404L,55405L,55406L,55407L,
-55408L,55409L,55410L,55411L,55412L,55413L,55414L,55415L,55416L,55417L,
-55418L,55419L,55420L,55421L,55422L,55423L,55424L,55425L,55426L,55427L,
-55428L,55429L,55430L,55431L,55432L,55433L,55434L,55435L,55436L,55437L,
-55438L,55439L,55440L,55441L,55442L,55443L,55444L,55445L,55446L,55447L,
-55448L,55449L,55450L,55451L,55452L,55453L,55454L,55455L,55456L,55457L,
-55458L,55459L,55460L,55461L,55462L,55463L,55464L,55465L,55466L,55467L,
-55468L,55469L,55470L,55471L,55472L,55473L,55474L,55475L,55476L,55477L,
-55478L,55479L,55480L,55481L,55482L,55483L,55484L,55485L,55486L,55487L,
-55488L,55489L,55490L,55491L,55492L,55493L,55494L,55495L,55496L,55497L,
-55498L,55499L,55500L,55501L,55502L,55503L,55504L,55505L,55506L,55507L,
-55508L,55509L,55510L,55511L,55512L,55513L,55514L,55515L,55516L,55517L,
-55518L,55519L,55520L,55521L,55522L,55523L,55524L,55525L,55526L,55527L,
-55528L,55529L,55530L,55531L,55532L,55533L,55534L,55535L,55536L,55537L,
-55538L,55539L,55540L,55541L,55542L,55543L,55544L,55545L,55546L,55547L,
-55548L,55549L,55550L,55551L,55552L,55553L,55554L,55555L,55556L,55557L,
-55558L,55559L,55560L,55561L,55562L,55563L,55564L,55565L,55566L,55567L,
-55568L,55569L,55570L,55571L,55572L,55573L,55574L,55575L,55576L,55577L,
-55578L,55579L,55580L,55581L,55582L,55583L,55584L,55585L,55586L,55587L,
-55588L,55589L,55590L,55591L,55592L,55593L,55594L,55595L,55596L,55597L,
-55598L,55599L,55600L,55601L,55602L,55603L,55604L,55605L,55606L,55607L,
-55608L,55609L,55610L,55611L,55612L,55613L,55614L,55615L,55616L,55617L,
-55618L,55619L,55620L,55621L,55622L,55623L,55624L,55625L,55626L,55627L,
-55628L,55629L,55630L,55631L,55632L,55633L,55634L,55635L,55636L,55637L,
-55638L,55639L,55640L,55641L,55642L,55643L,55644L,55645L,55646L,55647L,
-55648L,55649L,55650L,55651L,55652L,55653L,55654L,55655L,55656L,55657L,
-55658L,55659L,55660L,55661L,55662L,55663L,55664L,55665L,55666L,55667L,
-55668L,55669L,55670L,55671L,55672L,55673L,55674L,55675L,55676L,55677L,
-55678L,55679L,55680L,55681L,55682L,55683L,55684L,55685L,55686L,55687L,
-55688L,55689L,55690L,55691L,55692L,55693L,55694L,55695L,55696L,55697L,
-55698L,55699L,55700L,55701L,55702L,55703L,55704L,55705L,55706L,55707L,
-55708L,55709L,55710L,55711L,55712L,55713L,55714L,55715L,55716L,55717L,
-55718L,55719L,55720L,55721L,55722L,55723L,55724L,55725L,55726L,55727L,
-55728L,55729L,55730L,55731L,55732L,55733L,55734L,55735L,55736L,55737L,
-55738L,55739L,55740L,55741L,55742L,55743L,55744L,55745L,55746L,55747L,
-55748L,55749L,55750L,55751L,55752L,55753L,55754L,55755L,55756L,55757L,
-55758L,55759L,55760L,55761L,55762L,55763L,55764L,55765L,55766L,55767L,
-55768L,55769L,55770L,55771L,55772L,55773L,55774L,55775L,55776L,55777L,
-55778L,55779L,55780L,55781L,55782L,55783L,55784L,55785L,55786L,55787L,
-55788L,55789L,55790L,55791L,55792L,55793L,55794L,55795L,55796L,55797L,
-55798L,55799L,55800L,55801L,55802L,55803L,55804L,55805L,55806L,55807L,
-55808L,55809L,55810L,55811L,55812L,55813L,55814L,55815L,55816L,55817L,
-55818L,55819L,55820L,55821L,55822L,55823L,55824L,55825L,55826L,55827L,
-55828L,55829L,55830L,55831L,55832L,55833L,55834L,55835L,55836L,55837L,
-55838L,55839L,55840L,55841L,55842L,55843L,55844L,55845L,55846L,55847L,
-55848L,55849L,55850L,55851L,55852L,55853L,55854L,55855L,55856L,55857L,
-55858L,55859L,55860L,55861L,55862L,55863L,55864L,55865L,55866L,55867L,
-55868L,55869L,55870L,55871L,55872L,55873L,55874L,55875L,55876L,55877L,
-55878L,55879L,55880L,55881L,55882L,55883L,55884L,55885L,55886L,55887L,
-55888L,55889L,55890L,55891L,55892L,55893L,55894L,55895L,55896L,55897L,
-55898L,55899L,55900L,55901L,55902L,55903L,55904L,55905L,55906L,55907L,
-55908L,55909L,55910L,55911L,55912L,55913L,55914L,55915L,55916L,55917L,
-55918L,55919L,55920L,55921L,55922L,55923L,55924L,55925L,55926L,55927L,
-55928L,55929L,55930L,55931L,55932L,55933L,55934L,55935L,55936L,55937L,
-55938L,55939L,55940L,55941L,55942L,55943L,55944L,55945L,55946L,55947L,
-55948L,55949L,55950L,55951L,55952L,55953L,55954L,55955L,55956L,55957L,
-55958L,55959L,55960L,55961L,55962L,55963L,55964L,55965L,55966L,55967L,
-55968L,55969L,55970L,55971L,55972L,55973L,55974L,55975L,55976L,55977L,
-55978L,55979L,55980L,55981L,55982L,55983L,55984L,55985L,55986L,55987L,
-55988L,55989L,55990L,55991L,55992L,55993L,55994L,55995L,55996L,55997L,
-55998L,55999L,56000L,56001L,56002L,56003L,56004L,56005L,56006L,56007L,
-56008L,56009L,56010L,56011L,56012L,56013L,56014L,56015L,56016L,56017L,
-56018L,56019L,56020L,56021L,56022L,56023L,56024L,56025L,56026L,56027L,
-56028L,56029L,56030L,56031L,56032L,56033L,56034L,56035L,56036L,56037L,
-56038L,56039L,56040L,56041L,56042L,56043L,56044L,56045L,56046L,56047L,
-56048L,56049L,56050L,56051L,56052L,56053L,56054L,56055L,56056L,56057L,
-56058L,56059L,56060L,56061L,56062L,56063L,56064L,56065L,56066L,56067L,
-56068L,56069L,56070L,56071L,56072L,56073L,56074L,56075L,56076L,56077L,
-56078L,56079L,56080L,56081L,56082L,56083L,56084L,56085L,56086L,56087L,
-56088L,56089L,56090L,56091L,56092L,56093L,56094L,56095L,56096L,56097L,
-56098L,56099L,56100L,56101L,56102L,56103L,56104L,56105L,56106L,56107L,
-56108L,56109L,56110L,56111L,56112L,56113L,56114L,56115L,56116L,56117L,
-56118L,56119L,56120L,56121L,56122L,56123L,56124L,56125L,56126L,56127L,
-56128L,56129L,56130L,56131L,56132L,56133L,56134L,56135L,56136L,56137L,
-56138L,56139L,56140L,56141L,56142L,56143L,56144L,56145L,56146L,56147L,
-56148L,56149L,56150L,56151L,56152L,56153L,56154L,56155L,56156L,56157L,
-56158L,56159L,56160L,56161L,56162L,56163L,56164L,56165L,56166L,56167L,
-56168L,56169L,56170L,56171L,56172L,56173L,56174L,56175L,56176L,56177L,
-56178L,56179L,56180L,56181L,56182L,56183L,56184L,56185L,56186L,56187L,
-56188L,56189L,56190L,56191L,56192L,56193L,56194L,56195L,56196L,56197L,
-56198L,56199L,56200L,56201L,56202L,56203L,56204L,56205L,56206L,56207L,
-56208L,56209L,56210L,56211L,56212L,56213L,56214L,56215L,56216L,56217L,
-56218L,56219L,56220L,56221L,56222L,56223L,56224L,56225L,56226L,56227L,
-56228L,56229L,56230L,56231L,56232L,56233L,56234L,56235L,56236L,56237L,
-56238L,56239L,56240L,56241L,56242L,56243L,56244L,56245L,56246L,56247L,
-56248L,56249L,56250L,56251L,56252L,56253L,56254L,56255L,56256L,56257L,
-56258L,56259L,56260L,56261L,56262L,56263L,56264L,56265L,56266L,56267L,
-56268L,56269L,56270L,56271L,56272L,56273L,56274L,56275L,56276L,56277L,
-56278L,56279L,56280L,56281L,56282L,56283L,56284L,56285L,56286L,56287L,
-56288L,56289L,56290L,56291L,56292L,56293L,56294L,56295L,56296L,56297L,
-56298L,56299L,56300L,56301L,56302L,56303L,56304L,56305L,56306L,56307L,
-56308L,56309L,56310L,56311L,56312L,56313L,56314L,56315L,56316L,56317L,
-56318L,56319L,56320L,56321L,56322L,56323L,56324L,56325L,56326L,56327L,
-56328L,56329L,56330L,56331L,56332L,56333L,56334L,56335L,56336L,56337L,
-56338L,56339L,56340L,56341L,56342L,56343L,56344L,56345L,56346L,56347L,
-56348L,56349L,56350L,56351L,56352L,56353L,56354L,56355L,56356L,56357L,
-56358L,56359L,56360L,56361L,56362L,56363L,56364L,56365L,56366L,56367L,
-56368L,56369L,56370L,56371L,56372L,56373L,56374L,56375L,56376L,56377L,
-56378L,56379L,56380L,56381L,56382L,56383L,56384L,56385L,56386L,56387L,
-56388L,56389L,56390L,56391L,56392L,56393L,56394L,56395L,56396L,56397L,
-56398L,56399L,56400L,56401L,56402L,56403L,56404L,56405L,56406L,56407L,
-56408L,56409L,56410L,56411L,56412L,56413L,56414L,56415L,56416L,56417L,
-56418L,56419L,56420L,56421L,56422L,56423L,56424L,56425L,56426L,56427L,
-56428L,56429L,56430L,56431L,56432L,56433L,56434L,56435L,56436L,56437L,
-56438L,56439L,56440L,56441L,56442L,56443L,56444L,56445L,56446L,56447L,
-56448L,56449L,56450L,56451L,56452L,56453L,56454L,56455L,56456L,56457L,
-56458L,56459L,56460L,56461L,56462L,56463L,56464L,56465L,56466L,56467L,
-56468L,56469L,56470L,56471L,56472L,56473L,56474L,56475L,56476L,56477L,
-56478L,56479L,56480L,56481L,56482L,56483L,56484L,56485L,56486L,56487L,
-56488L,56489L,56490L,56491L,56492L,56493L,56494L,56495L,56496L,56497L,
-56498L,56499L,56500L,56501L,56502L,56503L,56504L,56505L,56506L,56507L,
-56508L,56509L,56510L,56511L,56512L,56513L,56514L,56515L,56516L,56517L,
-56518L,56519L,56520L,56521L,56522L,56523L,56524L,56525L,56526L,56527L,
-56528L,56529L,56530L,56531L,56532L,56533L,56534L,56535L,56536L,56537L,
-56538L,56539L,56540L,56541L,56542L,56543L,56544L,56545L,56546L,56547L,
-56548L,56549L,56550L,56551L,56552L,56553L,56554L,56555L,56556L,56557L,
-56558L,56559L,56560L,56561L,56562L,56563L,56564L,56565L,56566L,56567L,
-56568L,56569L,56570L,56571L,56572L,56573L,56574L,56575L,56576L,56577L,
-56578L,56579L,56580L,56581L,56582L,56583L,56584L,56585L,56586L,56587L,
-56588L,56589L,56590L,56591L,56592L,56593L,56594L,56595L,56596L,56597L,
-56598L,56599L,56600L,56601L,56602L,56603L,56604L,56605L,56606L,56607L,
-56608L,56609L,56610L,56611L,56612L,56613L,56614L,56615L,56616L,56617L,
-56618L,56619L,56620L,56621L,56622L,56623L,56624L,56625L,56626L,56627L,
-56628L,56629L,56630L,56631L,56632L,56633L,56634L,56635L,56636L,56637L,
-56638L,56639L,56640L,56641L,56642L,56643L,56644L,56645L,56646L,56647L,
-56648L,56649L,56650L,56651L,56652L,56653L,56654L,56655L,56656L,56657L,
-56658L,56659L,56660L,56661L,56662L,56663L,56664L,56665L,56666L,56667L,
-56668L,56669L,56670L,56671L,56672L,56673L,56674L,56675L,56676L,56677L,
-56678L,56679L,56680L,56681L,56682L,56683L,56684L,56685L,56686L,56687L,
-56688L,56689L,56690L,56691L,56692L,56693L,56694L,56695L,56696L,56697L,
-56698L,56699L,56700L,56701L,56702L,56703L,56704L,56705L,56706L,56707L,
-56708L,56709L,56710L,56711L,56712L,56713L,56714L,56715L,56716L,56717L,
-56718L,56719L,56720L,56721L,56722L,56723L,56724L,56725L,56726L,56727L,
-56728L,56729L,56730L,56731L,56732L,56733L,56734L,56735L,56736L,56737L,
-56738L,56739L,56740L,56741L,56742L,56743L,56744L,56745L,56746L,56747L,
-56748L,56749L,56750L,56751L,56752L,56753L,56754L,56755L,56756L,56757L,
-56758L,56759L,56760L,56761L,56762L,56763L,56764L,56765L,56766L,56767L,
-56768L,56769L,56770L,56771L,56772L,56773L,56774L,56775L,56776L,56777L,
-56778L,56779L,56780L,56781L,56782L,56783L,56784L,56785L,56786L,56787L,
-56788L,56789L,56790L,56791L,56792L,56793L,56794L,56795L,56796L,56797L,
-56798L,56799L,56800L,56801L,56802L,56803L,56804L,56805L,56806L,56807L,
-56808L,56809L,56810L,56811L,56812L,56813L,56814L,56815L,56816L,56817L,
-56818L,56819L,56820L,56821L,56822L,56823L,56824L,56825L,56826L,56827L,
-56828L,56829L,56830L,56831L,56832L,56833L,56834L,56835L,56836L,56837L,
-56838L,56839L,56840L,56841L,56842L,56843L,56844L,56845L,56846L,56847L,
-56848L,56849L,56850L,56851L,56852L,56853L,56854L,56855L,56856L,56857L,
-56858L,56859L,56860L,56861L,56862L,56863L,56864L,56865L,56866L,56867L,
-56868L,56869L,56870L,56871L,56872L,56873L,56874L,56875L,56876L,56877L,
-56878L,56879L,56880L,56881L,56882L,56883L,56884L,56885L,56886L,56887L,
-56888L,56889L,56890L,56891L,56892L,56893L,56894L,56895L,56896L,56897L,
-56898L,56899L,56900L,56901L,56902L,56903L,56904L,56905L,56906L,56907L,
-56908L,56909L,56910L,56911L,56912L,56913L,56914L,56915L,56916L,56917L,
-56918L,56919L,56920L,56921L,56922L,56923L,56924L,56925L,56926L,56927L,
-56928L,56929L,56930L,56931L,56932L,56933L,56934L,56935L,56936L,56937L,
-56938L,56939L,56940L,56941L,56942L,56943L,56944L,56945L,56946L,56947L,
-56948L,56949L,56950L,56951L,56952L,56953L,56954L,56955L,56956L,56957L,
-56958L,56959L,56960L,56961L,56962L,56963L,56964L,56965L,56966L,56967L,
-56968L,56969L,56970L,56971L,56972L,56973L,56974L,56975L,56976L,56977L,
-56978L,56979L,56980L,56981L,56982L,56983L,56984L,56985L,56986L,56987L,
-56988L,56989L,56990L,56991L,56992L,56993L,56994L,56995L,56996L,56997L,
-56998L,56999L,57000L,57001L,57002L,57003L,57004L,57005L,57006L,57007L,
-57008L,57009L,57010L,57011L,57012L,57013L,57014L,57015L,57016L,57017L,
-57018L,57019L,57020L,57021L,57022L,57023L,57024L,57025L,57026L,57027L,
-57028L,57029L,57030L,57031L,57032L,57033L,57034L,57035L,57036L,57037L,
-57038L,57039L,57040L,57041L,57042L,57043L,57044L,57045L,57046L,57047L,
-57048L,57049L,57050L,57051L,57052L,57053L,57054L,57055L,57056L,57057L,
-57058L,57059L,57060L,57061L,57062L,57063L,57064L,57065L,57066L,57067L,
-57068L,57069L,57070L,57071L,57072L,57073L,57074L,57075L,57076L,57077L,
-57078L,57079L,57080L,57081L,57082L,57083L,57084L,57085L,57086L,57087L,
-57088L,57089L,57090L,57091L,57092L,57093L,57094L,57095L,57096L,57097L,
-57098L,57099L,57100L,57101L,57102L,57103L,57104L,57105L,57106L,57107L,
-57108L,57109L,57110L,57111L,57112L,57113L,57114L,57115L,57116L,57117L,
-57118L,57119L,57120L,57121L,57122L,57123L,57124L,57125L,57126L,57127L,
-57128L,57129L,57130L,57131L,57132L,57133L,57134L,57135L,57136L,57137L,
-57138L,57139L,57140L,57141L,57142L,57143L,57144L,57145L,57146L,57147L,
-57148L,57149L,57150L,57151L,57152L,57153L,57154L,57155L,57156L,57157L,
-57158L,57159L,57160L,57161L,57162L,57163L,57164L,57165L,57166L,57167L,
-57168L,57169L,57170L,57171L,57172L,57173L,57174L,57175L,57176L,57177L,
-57178L,57179L,57180L,57181L,57182L,57183L,57184L,57185L,57186L,57187L,
-57188L,57189L,57190L,57191L,57192L,57193L,57194L,57195L,57196L,57197L,
-57198L,57199L,57200L,57201L,57202L,57203L,57204L,57205L,57206L,57207L,
-57208L,57209L,57210L,57211L,57212L,57213L,57214L,57215L,57216L,57217L,
-57218L,57219L,57220L,57221L,57222L,57223L,57224L,57225L,57226L,57227L,
-57228L,57229L,57230L,57231L,57232L,57233L,57234L,57235L,57236L,57237L,
-57238L,57239L,57240L,57241L,57242L,57243L,57244L,57245L,57246L,57247L,
-57248L,57249L,57250L,57251L,57252L,57253L,57254L,57255L,57256L,57257L,
-57258L,57259L,57260L,57261L,57262L,57263L,57264L,57265L,57266L,57267L,
-57268L,57269L,57270L,57271L,57272L,57273L,57274L,57275L,57276L,57277L,
-57278L,57279L,57280L,57281L,57282L,57283L,57284L,57285L,57286L,57287L,
-57288L,57289L,57290L,57291L,57292L,57293L,57294L,57295L,57296L,57297L,
-57298L,57299L,57300L,57301L,57302L,57303L,57304L,57305L,57306L,57307L,
-57308L,57309L,57310L,57311L,57312L,57313L,57314L,57315L,57316L,57317L,
-57318L,57319L,57320L,57321L,57322L,57323L,57324L,57325L,57326L,57327L,
-57328L,57329L,57330L,57331L,57332L,57333L,57334L,57335L,57336L,57337L,
-57338L,57339L,57340L,57341L,57342L,57343L,57344L,57345L,57346L,57347L,
-57348L,57349L,57350L,57351L,57352L,57353L,57354L,57355L,57356L,57357L,
-57358L,57359L,57360L,57361L,57362L,57363L,57364L,57365L,57366L,57367L,
-57368L,57369L,57370L,57371L,57372L,57373L,57374L,57375L,57376L,57377L,
-57378L,57379L,57380L,57381L,57382L,57383L,57384L,57385L,57386L,57387L,
-57388L,57389L,57390L,57391L,57392L,57393L,57394L,57395L,57396L,57397L,
-57398L,57399L,57400L,57401L,57402L,57403L,57404L,57405L,57406L,57407L,
-57408L,57409L,57410L,57411L,57412L,57413L,57414L,57415L,57416L,57417L,
-57418L,57419L,57420L,57421L,57422L,57423L,57424L,57425L,57426L,57427L,
-57428L,57429L,57430L,57431L,57432L,57433L,57434L,57435L,57436L,57437L,
-57438L,57439L,57440L,57441L,57442L,57443L,57444L,57445L,57446L,57447L,
-57448L,57449L,57450L,57451L,57452L,57453L,57454L,57455L,57456L,57457L,
-57458L,57459L,57460L,57461L,57462L,57463L,57464L,57465L,57466L,57467L,
-57468L,57469L,57470L,57471L,57472L,57473L,57474L,57475L,57476L,57477L,
-57478L,57479L,57480L,57481L,57482L,57483L,57484L,57485L,57486L,57487L,
-57488L,57489L,57490L,57491L,57492L,57493L,57494L,57495L,57496L,57497L,
-57498L,57499L,57500L,57501L,57502L,57503L,57504L,57505L,57506L,57507L,
-57508L,57509L,57510L,57511L,57512L,57513L,57514L,57515L,57516L,57517L,
-57518L,57519L,57520L,57521L,57522L,57523L,57524L,57525L,57526L,57527L,
-57528L,57529L,57530L,57531L,57532L,57533L,57534L,57535L,57536L,57537L,
-57538L,57539L,57540L,57541L,57542L,57543L,57544L,57545L,57546L,57547L,
-57548L,57549L,57550L,57551L,57552L,57553L,57554L,57555L,57556L,57557L,
-57558L,57559L,57560L,57561L,57562L,57563L,57564L,57565L,57566L,57567L,
-57568L,57569L,57570L,57571L,57572L,57573L,57574L,57575L,57576L,57577L,
-57578L,57579L,57580L,57581L,57582L,57583L,57584L,57585L,57586L,57587L,
-57588L,57589L,57590L,57591L,57592L,57593L,57594L,57595L,57596L,57597L,
-57598L,57599L,57600L,57601L,57602L,57603L,57604L,57605L,57606L,57607L,
-57608L,57609L,57610L,57611L,57612L,57613L,57614L,57615L,57616L,57617L,
-57618L,57619L,57620L,57621L,57622L,57623L,57624L,57625L,57626L,57627L,
-57628L,57629L,57630L,57631L,57632L,57633L,57634L,57635L,57636L,57637L,
-57638L,57639L,57640L,57641L,57642L,57643L,57644L,57645L,57646L,57647L,
-57648L,57649L,57650L,57651L,57652L,57653L,57654L,57655L,57656L,57657L,
-57658L,57659L,57660L,57661L,57662L,57663L,57664L,57665L,57666L,57667L,
-57668L,57669L,57670L,57671L,57672L,57673L,57674L,57675L,57676L,57677L,
-57678L,57679L,57680L,57681L,57682L,57683L,57684L,57685L,57686L,57687L,
-57688L,57689L,57690L,57691L,57692L,57693L,57694L,57695L,57696L,57697L,
-57698L,57699L,57700L,57701L,57702L,57703L,57704L,57705L,57706L,57707L,
-57708L,57709L,57710L,57711L,57712L,57713L,57714L,57715L,57716L,57717L,
-57718L,57719L,57720L,57721L,57722L,57723L,57724L,57725L,57726L,57727L,
-57728L,57729L,57730L,57731L,57732L,57733L,57734L,57735L,57736L,57737L,
-57738L,57739L,57740L,57741L,57742L,57743L,57744L,57745L,57746L,57747L,
-57748L,57749L,57750L,57751L,57752L,57753L,57754L,57755L,57756L,57757L,
-57758L,57759L,57760L,57761L,57762L,57763L,57764L,57765L,57766L,57767L,
-57768L,57769L,57770L,57771L,57772L,57773L,57774L,57775L,57776L,57777L,
-57778L,57779L,57780L,57781L,57782L,57783L,57784L,57785L,57786L,57787L,
-57788L,57789L,57790L,57791L,57792L,57793L,57794L,57795L,57796L,57797L,
-57798L,57799L,57800L,57801L,57802L,57803L,57804L,57805L,57806L,57807L,
-57808L,57809L,57810L,57811L,57812L,57813L,57814L,57815L,57816L,57817L,
-57818L,57819L,57820L,57821L,57822L,57823L,57824L,57825L,57826L,57827L,
-57828L,57829L,57830L,57831L,57832L,57833L,57834L,57835L,57836L,57837L,
-57838L,57839L,57840L,57841L,57842L,57843L,57844L,57845L,57846L,57847L,
-57848L,57849L,57850L,57851L,57852L,57853L,57854L,57855L,57856L,57857L,
-57858L,57859L,57860L,57861L,57862L,57863L,57864L,57865L,57866L,57867L,
-57868L,57869L,57870L,57871L,57872L,57873L,57874L,57875L,57876L,57877L,
-57878L,57879L,57880L,57881L,57882L,57883L,57884L,57885L,57886L,57887L,
-57888L,57889L,57890L,57891L,57892L,57893L,57894L,57895L,57896L,57897L,
-57898L,57899L,57900L,57901L,57902L,57903L,57904L,57905L,57906L,57907L,
-57908L,57909L,57910L,57911L,57912L,57913L,57914L,57915L,57916L,57917L,
-57918L,57919L,57920L,57921L,57922L,57923L,57924L,57925L,57926L,57927L,
-57928L,57929L,57930L,57931L,57932L,57933L,57934L,57935L,57936L,57937L,
-57938L,57939L,57940L,57941L,57942L,57943L,57944L,57945L,57946L,57947L,
-57948L,57949L,57950L,57951L,57952L,57953L,57954L,57955L,57956L,57957L,
-57958L,57959L,57960L,57961L,57962L,57963L,57964L,57965L,57966L,57967L,
-57968L,57969L,57970L,57971L,57972L,57973L,57974L,57975L,57976L,57977L,
-57978L,57979L,57980L,57981L,57982L,57983L,57984L,57985L,57986L,57987L,
-57988L,57989L,57990L,57991L,57992L,57993L,57994L,57995L,57996L,57997L,
-57998L,57999L,58000L,58001L,58002L,58003L,58004L,58005L,58006L,58007L,
-58008L,58009L,58010L,58011L,58012L,58013L,58014L,58015L,58016L,58017L,
-58018L,58019L,58020L,58021L,58022L,58023L,58024L,58025L,58026L,58027L,
-58028L,58029L,58030L,58031L,58032L,58033L,58034L,58035L,58036L,58037L,
-58038L,58039L,58040L,58041L,58042L,58043L,58044L,58045L,58046L,58047L,
-58048L,58049L,58050L,58051L,58052L,58053L,58054L,58055L,58056L,58057L,
-58058L,58059L,58060L,58061L,58062L,58063L,58064L,58065L,58066L,58067L,
-58068L,58069L,58070L,58071L,58072L,58073L,58074L,58075L,58076L,58077L,
-58078L,58079L,58080L,58081L,58082L,58083L,58084L,58085L,58086L,58087L,
-58088L,58089L,58090L,58091L,58092L,58093L,58094L,58095L,58096L,58097L,
-58098L,58099L,58100L,58101L,58102L,58103L,58104L,58105L,58106L,58107L,
-58108L,58109L,58110L,58111L,58112L,58113L,58114L,58115L,58116L,58117L,
-58118L,58119L,58120L,58121L,58122L,58123L,58124L,58125L,58126L,58127L,
-58128L,58129L,58130L,58131L,58132L,58133L,58134L,58135L,58136L,58137L,
-58138L,58139L,58140L,58141L,58142L,58143L,58144L,58145L,58146L,58147L,
-58148L,58149L,58150L,58151L,58152L,58153L,58154L,58155L,58156L,58157L,
-58158L,58159L,58160L,58161L,58162L,58163L,58164L,58165L,58166L,58167L,
-58168L,58169L,58170L,58171L,58172L,58173L,58174L,58175L,58176L,58177L,
-58178L,58179L,58180L,58181L,58182L,58183L,58184L,58185L,58186L,58187L,
-58188L,58189L,58190L,58191L,58192L,58193L,58194L,58195L,58196L,58197L,
-58198L,58199L,58200L,58201L,58202L,58203L,58204L,58205L,58206L,58207L,
-58208L,58209L,58210L,58211L,58212L,58213L,58214L,58215L,58216L,58217L,
-58218L,58219L,58220L,58221L,58222L,58223L,58224L,58225L,58226L,58227L,
-58228L,58229L,58230L,58231L,58232L,58233L,58234L,58235L,58236L,58237L,
-58238L,58239L,58240L,58241L,58242L,58243L,58244L,58245L,58246L,58247L,
-58248L,58249L,58250L,58251L,58252L,58253L,58254L,58255L,58256L,58257L,
-58258L,58259L,58260L,58261L,58262L,58263L,58264L,58265L,58266L,58267L,
-58268L,58269L,58270L,58271L,58272L,58273L,58274L,58275L,58276L,58277L,
-58278L,58279L,58280L,58281L,58282L,58283L,58284L,58285L,58286L,58287L,
-58288L,58289L,58290L,58291L,58292L,58293L,58294L,58295L,58296L,58297L,
-58298L,58299L,58300L,58301L,58302L,58303L,58304L,58305L,58306L,58307L,
-58308L,58309L,58310L,58311L,58312L,58313L,58314L,58315L,58316L,58317L,
-58318L,58319L,58320L,58321L,58322L,58323L,58324L,58325L,58326L,58327L,
-58328L,58329L,58330L,58331L,58332L,58333L,58334L,58335L,58336L,58337L,
-58338L,58339L,58340L,58341L,58342L,58343L,58344L,58345L,58346L,58347L,
-58348L,58349L,58350L,58351L,58352L,58353L,58354L,58355L,58356L,58357L,
-58358L,58359L,58360L,58361L,58362L,58363L,58364L,58365L,58366L,58367L,
-58368L,58369L,58370L,58371L,58372L,58373L,58374L,58375L,58376L,58377L,
-58378L,58379L,58380L,58381L,58382L,58383L,58384L,58385L,58386L,58387L,
-58388L,58389L,58390L,58391L,58392L,58393L,58394L,58395L,58396L,58397L,
-58398L,58399L,58400L,58401L,58402L,58403L,58404L,58405L,58406L,58407L,
-58408L,58409L,58410L,58411L,58412L,58413L,58414L,58415L,58416L,58417L,
-58418L,58419L,58420L,58421L,58422L,58423L,58424L,58425L,58426L,58427L,
-58428L,58429L,58430L,58431L,58432L,58433L,58434L,58435L,58436L,58437L,
-58438L,58439L,58440L,58441L,58442L,58443L,58444L,58445L,58446L,58447L,
-58448L,58449L,58450L,58451L,58452L,58453L,58454L,58455L,58456L,58457L,
-58458L,58459L,58460L,58461L,58462L,58463L,58464L,58465L,58466L,58467L,
-58468L,58469L,58470L,58471L,58472L,58473L,58474L,58475L,58476L,58477L,
-58478L,58479L,58480L,58481L,58482L,58483L,58484L,58485L,58486L,58487L,
-58488L,58489L,58490L,58491L,58492L,58493L,58494L,58495L,58496L,58497L,
-58498L,58499L,58500L,58501L,58502L,58503L,58504L,58505L,58506L,58507L,
-58508L,58509L,58510L,58511L,58512L,58513L,58514L,58515L,58516L,58517L,
-58518L,58519L,58520L,58521L,58522L,58523L,58524L,58525L,58526L,58527L,
-58528L,58529L,58530L,58531L,58532L,58533L,58534L,58535L,58536L,58537L,
-58538L,58539L,58540L,58541L,58542L,58543L,58544L,58545L,58546L,58547L,
-58548L,58549L,58550L,58551L,58552L,58553L,58554L,58555L,58556L,58557L,
-58558L,58559L,58560L,58561L,58562L,58563L,58564L,58565L,58566L,58567L,
-58568L,58569L,58570L,58571L,58572L,58573L,58574L,58575L,58576L,58577L,
-58578L,58579L,58580L,58581L,58582L,58583L,58584L,58585L,58586L,58587L,
-58588L,58589L,58590L,58591L,58592L,58593L,58594L,58595L,58596L,58597L,
-58598L,58599L,58600L,58601L,58602L,58603L,58604L,58605L,58606L,58607L,
-58608L,58609L,58610L,58611L,58612L,58613L,58614L,58615L,58616L,58617L,
-58618L,58619L,58620L,58621L,58622L,58623L,58624L,58625L,58626L,58627L,
-58628L,58629L,58630L,58631L,58632L,58633L,58634L,58635L,58636L,58637L,
-58638L,58639L,58640L,58641L,58642L,58643L,58644L,58645L,58646L,58647L,
-58648L,58649L,58650L,58651L,58652L,58653L,58654L,58655L,58656L,58657L,
-58658L,58659L,58660L,58661L,58662L,58663L,58664L,58665L,58666L,58667L,
-58668L,58669L,58670L,58671L,58672L,58673L,58674L,58675L,58676L,58677L,
-58678L,58679L,58680L,58681L,58682L,58683L,58684L,58685L,58686L,58687L,
-58688L,58689L,58690L,58691L,58692L,58693L,58694L,58695L,58696L,58697L,
-58698L,58699L,58700L,58701L,58702L,58703L,58704L,58705L,58706L,58707L,
-58708L,58709L,58710L,58711L,58712L,58713L,58714L,58715L,58716L,58717L,
-58718L,58719L,58720L,58721L,58722L,58723L,58724L,58725L,58726L,58727L,
-58728L,58729L,58730L,58731L,58732L,58733L,58734L,58735L,58736L,58737L,
-58738L,58739L,58740L,58741L,58742L,58743L,58744L,58745L,58746L,58747L,
-58748L,58749L,58750L,58751L,58752L,58753L,58754L,58755L,58756L,58757L,
-58758L,58759L,58760L,58761L,58762L,58763L,58764L,58765L,58766L,58767L,
-58768L,58769L,58770L,58771L,58772L,58773L,58774L,58775L,58776L,58777L,
-58778L,58779L,58780L,58781L,58782L,58783L,58784L,58785L,58786L,58787L,
-58788L,58789L,58790L,58791L,58792L,58793L,58794L,58795L,58796L,58797L,
-58798L,58799L,58800L,58801L,58802L,58803L,58804L,58805L,58806L,58807L,
-58808L,58809L,58810L,58811L,58812L,58813L,58814L,58815L,58816L,58817L,
-58818L,58819L,58820L,58821L,58822L,58823L,58824L,58825L,58826L,58827L,
-58828L,58829L,58830L,58831L,58832L,58833L,58834L,58835L,58836L,58837L,
-58838L,58839L,58840L,58841L,58842L,58843L,58844L,58845L,58846L,58847L,
-58848L,58849L,58850L,58851L,58852L,58853L,58854L,58855L,58856L,58857L,
-58858L,58859L,58860L,58861L,58862L,58863L,58864L,58865L,58866L,58867L,
-58868L,58869L,58870L,58871L,58872L,58873L,58874L,58875L,58876L,58877L,
-58878L,58879L,58880L,58881L,58882L,58883L,58884L,58885L,58886L,58887L,
-58888L,58889L,58890L,58891L,58892L,58893L,58894L,58895L,58896L,58897L,
-58898L,58899L,58900L,58901L,58902L,58903L,58904L,58905L,58906L,58907L,
-58908L,58909L,58910L,58911L,58912L,58913L,58914L,58915L,58916L,58917L,
-58918L,58919L,58920L,58921L,58922L,58923L,58924L,58925L,58926L,58927L,
-58928L,58929L,58930L,58931L,58932L,58933L,58934L,58935L,58936L,58937L,
-58938L,58939L,58940L,58941L,58942L,58943L,58944L,58945L,58946L,58947L,
-58948L,58949L,58950L,58951L,58952L,58953L,58954L,58955L,58956L,58957L,
-58958L,58959L,58960L,58961L,58962L,58963L,58964L,58965L,58966L,58967L,
-58968L,58969L,58970L,58971L,58972L,58973L,58974L,58975L,58976L,58977L,
-58978L,58979L,58980L,58981L,58982L,58983L,58984L,58985L,58986L,58987L,
-58988L,58989L,58990L,58991L,58992L,58993L,58994L,58995L,58996L,58997L,
-58998L,58999L,59000L,59001L,59002L,59003L,59004L,59005L,59006L,59007L,
-59008L,59009L,59010L,59011L,59012L,59013L,59014L,59015L,59016L,59017L,
-59018L,59019L,59020L,59021L,59022L,59023L,59024L,59025L,59026L,59027L,
-59028L,59029L,59030L,59031L,59032L,59033L,59034L,59035L,59036L,59037L,
-59038L,59039L,59040L,59041L,59042L,59043L,59044L,59045L,59046L,59047L,
-59048L,59049L,59050L,59051L,59052L,59053L,59054L,59055L,59056L,59057L,
-59058L,59059L,59060L,59061L,59062L,59063L,59064L,59065L,59066L,59067L,
-59068L,59069L,59070L,59071L,59072L,59073L,59074L,59075L,59076L,59077L,
-59078L,59079L,59080L,59081L,59082L,59083L,59084L,59085L,59086L,59087L,
-59088L,59089L,59090L,59091L,59092L,59093L,59094L,59095L,59096L,59097L,
-59098L,59099L,59100L,59101L,59102L,59103L,59104L,59105L,59106L,59107L,
-59108L,59109L,59110L,59111L,59112L,59113L,59114L,59115L,59116L,59117L,
-59118L,59119L,59120L,59121L,59122L,59123L,59124L,59125L,59126L,59127L,
-59128L,59129L,59130L,59131L,59132L,59133L,59134L,59135L,59136L,59137L,
-59138L,59139L,59140L,59141L,59142L,59143L,59144L,59145L,59146L,59147L,
-59148L,59149L,59150L,59151L,59152L,59153L,59154L,59155L,59156L,59157L,
-59158L,59159L,59160L,59161L,59162L,59163L,59164L,59165L,59166L,59167L,
-59168L,59169L,59170L,59171L,59172L,59173L,59174L,59175L,59176L,59177L,
-59178L,59179L,59180L,59181L,59182L,59183L,59184L,59185L,59186L,59187L,
-59188L,59189L,59190L,59191L,59192L,59193L,59194L,59195L,59196L,59197L,
-59198L,59199L,59200L,59201L,59202L,59203L,59204L,59205L,59206L,59207L,
-59208L,59209L,59210L,59211L,59212L,59213L,59214L,59215L,59216L,59217L,
-59218L,59219L,59220L,59221L,59222L,59223L,59224L,59225L,59226L,59227L,
-59228L,59229L,59230L,59231L,59232L,59233L,59234L,59235L,59236L,59237L,
-59238L,59239L,59240L,59241L,59242L,59243L,59244L,59245L,59246L,59247L,
-59248L,59249L,59250L,59251L,59252L,59253L,59254L,59255L,59256L,59257L,
-59258L,59259L,59260L,59261L,59262L,59263L,59264L,59265L,59266L,59267L,
-59268L,59269L,59270L,59271L,59272L,59273L,59274L,59275L,59276L,59277L,
-59278L,59279L,59280L,59281L,59282L,59283L,59284L,59285L,59286L,59287L,
-59288L,59289L,59290L,59291L,59292L,59293L,59294L,59295L,59296L,59297L,
-59298L,59299L,59300L,59301L,59302L,59303L,59304L,59305L,59306L,59307L,
-59308L,59309L,59310L,59311L,59312L,59313L,59314L,59315L,59316L,59317L,
-59318L,59319L,59320L,59321L,59322L,59323L,59324L,59325L,59326L,59327L,
-59328L,59329L,59330L,59331L,59332L,59333L,59334L,59335L,59336L,59337L,
-59338L,59339L,59340L,59341L,59342L,59343L,59344L,59345L,59346L,59347L,
-59348L,59349L,59350L,59351L,59352L,59353L,59354L,59355L,59356L,59357L,
-59358L,59359L,59360L,59361L,59362L,59363L,59364L,59365L,59366L,59367L,
-59368L,59369L,59370L,59371L,59372L,59373L,59374L,59375L,59376L,59377L,
-59378L,59379L,59380L,59381L,59382L,59383L,59384L,59385L,59386L,59387L,
-59388L,59389L,59390L,59391L,59392L,59393L,59394L,59395L,59396L,59397L,
-59398L,59399L,59400L,59401L,59402L,59403L,59404L,59405L,59406L,59407L,
-59408L,59409L,59410L,59411L,59412L,59413L,59414L,59415L,59416L,59417L,
-59418L,59419L,59420L,59421L,59422L,59423L,59424L,59425L,59426L,59427L,
-59428L,59429L,59430L,59431L,59432L,59433L,59434L,59435L,59436L,59437L,
-59438L,59439L,59440L,59441L,59442L,59443L,59444L,59445L,59446L,59447L,
-59448L,59449L,59450L,59451L,59452L,59453L,59454L,59455L,59456L,59457L,
-59458L,59459L,59460L,59461L,59462L,59463L,59464L,59465L,59466L,59467L,
-59468L,59469L,59470L,59471L,59472L,59473L,59474L,59475L,59476L,59477L,
-59478L,59479L,59480L,59481L,59482L,59483L,59484L,59485L,59486L,59487L,
-59488L,59489L,59490L,59491L,59492L,59493L,59494L,59495L,59496L,59497L,
-59498L,59499L,59500L,59501L,59502L,59503L,59504L,59505L,59506L,59507L,
-59508L,59509L,59510L,59511L,59512L,59513L,59514L,59515L,59516L,59517L,
-59518L,59519L,59520L,59521L,59522L,59523L,59524L,59525L,59526L,59527L,
-59528L,59529L,59530L,59531L,59532L,59533L,59534L,59535L,59536L,59537L,
-59538L,59539L,59540L,59541L,59542L,59543L,59544L,59545L,59546L,59547L,
-59548L,59549L,59550L,59551L,59552L,59553L,59554L,59555L,59556L,59557L,
-59558L,59559L,59560L,59561L,59562L,59563L,59564L,59565L,59566L,59567L,
-59568L,59569L,59570L,59571L,59572L,59573L,59574L,59575L,59576L,59577L,
-59578L,59579L,59580L,59581L,59582L,59583L,59584L,59585L,59586L,59587L,
-59588L,59589L,59590L,59591L,59592L,59593L,59594L,59595L,59596L,59597L,
-59598L,59599L,59600L,59601L,59602L,59603L,59604L,59605L,59606L,59607L,
-59608L,59609L,59610L,59611L,59612L,59613L,59614L,59615L,59616L,59617L,
-59618L,59619L,59620L,59621L,59622L,59623L,59624L,59625L,59626L,59627L,
-59628L,59629L,59630L,59631L,59632L,59633L,59634L,59635L,59636L,59637L,
-59638L,59639L,59640L,59641L,59642L,59643L,59644L,59645L,59646L,59647L,
-59648L,59649L,59650L,59651L,59652L,59653L,59654L,59655L,59656L,59657L,
-59658L,59659L,59660L,59661L,59662L,59663L,59664L,59665L,59666L,59667L,
-59668L,59669L,59670L,59671L,59672L,59673L,59674L,59675L,59676L,59677L,
-59678L,59679L,59680L,59681L,59682L,59683L,59684L,59685L,59686L,59687L,
-59688L,59689L,59690L,59691L,59692L,59693L,59694L,59695L,59696L,59697L,
-59698L,59699L,59700L,59701L,59702L,59703L,59704L,59705L,59706L,59707L,
-59708L,59709L,59710L,59711L,59712L,59713L,59714L,59715L,59716L,59717L,
-59718L,59719L,59720L,59721L,59722L,59723L,59724L,59725L,59726L,59727L,
-59728L,59729L,59730L,59731L,59732L,59733L,59734L,59735L,59736L,59737L,
-59738L,59739L,59740L,59741L,59742L,59743L,59744L,59745L,59746L,59747L,
-59748L,59749L,59750L,59751L,59752L,59753L,59754L,59755L,59756L,59757L,
-59758L,59759L,59760L,59761L,59762L,59763L,59764L,59765L,59766L,59767L,
-59768L,59769L,59770L,59771L,59772L,59773L,59774L,59775L,59776L,59777L,
-59778L,59779L,59780L,59781L,59782L,59783L,59784L,59785L,59786L,59787L,
-59788L,59789L,59790L,59791L,59792L,59793L,59794L,59795L,59796L,59797L,
-59798L,59799L,59800L,59801L,59802L,59803L,59804L,59805L,59806L,59807L,
-59808L,59809L,59810L,59811L,59812L,59813L,59814L,59815L,59816L,59817L,
-59818L,59819L,59820L,59821L,59822L,59823L,59824L,59825L,59826L,59827L,
-59828L,59829L,59830L,59831L,59832L,59833L,59834L,59835L,59836L,59837L,
-59838L,59839L,59840L,59841L,59842L,59843L,59844L,59845L,59846L,59847L,
-59848L,59849L,59850L,59851L,59852L,59853L,59854L,59855L,59856L,59857L,
-59858L,59859L,59860L,59861L,59862L,59863L,59864L,59865L,59866L,59867L,
-59868L,59869L,59870L,59871L,59872L,59873L,59874L,59875L,59876L,59877L,
-59878L,59879L,59880L,59881L,59882L,59883L,59884L,59885L,59886L,59887L,
-59888L,59889L,59890L,59891L,59892L,59893L,59894L,59895L,59896L,59897L,
-59898L,59899L,59900L,59901L,59902L,59903L,59904L,59905L,59906L,59907L,
-59908L,59909L,59910L,59911L,59912L,59913L,59914L,59915L,59916L,59917L,
-59918L,59919L,59920L,59921L,59922L,59923L,59924L,59925L,59926L,59927L,
-59928L,59929L,59930L,59931L,59932L,59933L,59934L,59935L,59936L,59937L,
-59938L,59939L,59940L,59941L,59942L,59943L,59944L,59945L,59946L,59947L,
-59948L,59949L,59950L,59951L,59952L,59953L,59954L,59955L,59956L,59957L,
-59958L,59959L,59960L,59961L,59962L,59963L,59964L,59965L,59966L,59967L,
-59968L,59969L,59970L,59971L,59972L,59973L,59974L,59975L,59976L,59977L,
-59978L,59979L,59980L,59981L,59982L,59983L,59984L,59985L,59986L,59987L,
-59988L,59989L,59990L,59991L,59992L,59993L,59994L,59995L,59996L,59997L,
-59998L,59999L,60000L,60001L,60002L,60003L,60004L,60005L,60006L,60007L,
-60008L,60009L,60010L,60011L,60012L,60013L,60014L,60015L,60016L,60017L,
-60018L,60019L,60020L,60021L,60022L,60023L,60024L,60025L,60026L,60027L,
-60028L,60029L,60030L,60031L,60032L,60033L,60034L,60035L,60036L,60037L,
-60038L,60039L,60040L,60041L,60042L,60043L,60044L,60045L,60046L,60047L,
-60048L,60049L,60050L,60051L,60052L,60053L,60054L,60055L,60056L,60057L,
-60058L,60059L,60060L,60061L,60062L,60063L,60064L,60065L,60066L,60067L,
-60068L,60069L,60070L,60071L,60072L,60073L,60074L,60075L,60076L,60077L,
-60078L,60079L,60080L,60081L,60082L,60083L,60084L,60085L,60086L,60087L,
-60088L,60089L,60090L,60091L,60092L,60093L,60094L,60095L,60096L,60097L,
-60098L,60099L,60100L,60101L,60102L,60103L,60104L,60105L,60106L,60107L,
-60108L,60109L,60110L,60111L,60112L,60113L,60114L,60115L,60116L,60117L,
-60118L,60119L,60120L,60121L,60122L,60123L,60124L,60125L,60126L,60127L,
-60128L,60129L,60130L,60131L,60132L,60133L,60134L,60135L,60136L,60137L,
-60138L,60139L,60140L,60141L,60142L,60143L,60144L,60145L,60146L,60147L,
-60148L,60149L,60150L,60151L,60152L,60153L,60154L,60155L,60156L,60157L,
-60158L,60159L,60160L,60161L,60162L,60163L,60164L,60165L,60166L,60167L,
-60168L,60169L,60170L,60171L,60172L,60173L,60174L,60175L,60176L,60177L,
-60178L,60179L,60180L,60181L,60182L,60183L,60184L,60185L,60186L,60187L,
-60188L,60189L,60190L,60191L,60192L,60193L,60194L,60195L,60196L,60197L,
-60198L,60199L,60200L,60201L,60202L,60203L,60204L,60205L,60206L,60207L,
-60208L,60209L,60210L,60211L,60212L,60213L,60214L,60215L,60216L,60217L,
-60218L,60219L,60220L,60221L,60222L,60223L,60224L,60225L,60226L,60227L,
-60228L,60229L,60230L,60231L,60232L,60233L,60234L,60235L,60236L,60237L,
-60238L,60239L,60240L,60241L,60242L,60243L,60244L,60245L,60246L,60247L,
-60248L,60249L,60250L,60251L,60252L,60253L,60254L,60255L,60256L,60257L,
-60258L,60259L,60260L,60261L,60262L,60263L,60264L,60265L,60266L,60267L,
-60268L,60269L,60270L,60271L,60272L,60273L,60274L,60275L,60276L,60277L,
-60278L,60279L,60280L,60281L,60282L,60283L,60284L,60285L,60286L,60287L,
-60288L,60289L,60290L,60291L,60292L,60293L,60294L,60295L,60296L,60297L,
-60298L,60299L,60300L,60301L,60302L,60303L,60304L,60305L,60306L,60307L,
-60308L,60309L,60310L,60311L,60312L,60313L,60314L,60315L,60316L,60317L,
-60318L,60319L,60320L,60321L,60322L,60323L,60324L,60325L,60326L,60327L,
-60328L,60329L,60330L,60331L,60332L,60333L,60334L,60335L,60336L,60337L,
-60338L,60339L,60340L,60341L,60342L,60343L,60344L,60345L,60346L,60347L,
-60348L,60349L,60350L,60351L,60352L,60353L,60354L,60355L,60356L,60357L,
-60358L,60359L,60360L,60361L,60362L,60363L,60364L,60365L,60366L,60367L,
-60368L,60369L,60370L,60371L,60372L,60373L,60374L,60375L,60376L,60377L,
-60378L,60379L,60380L,60381L,60382L,60383L,60384L,60385L,60386L,60387L,
-60388L,60389L,60390L,60391L,60392L,60393L,60394L,60395L,60396L,60397L,
-60398L,60399L,60400L,60401L,60402L,60403L,60404L,60405L,60406L,60407L,
-60408L,60409L,60410L,60411L,60412L,60413L,60414L,60415L,60416L,60417L,
-60418L,60419L,60420L,60421L,60422L,60423L,60424L,60425L,60426L,60427L,
-60428L,60429L,60430L,60431L,60432L,60433L,60434L,60435L,60436L,60437L,
-60438L,60439L,60440L,60441L,60442L,60443L,60444L,60445L,60446L,60447L,
-60448L,60449L,60450L,60451L,60452L,60453L,60454L,60455L,60456L,60457L,
-60458L,60459L,60460L,60461L,60462L,60463L,60464L,60465L,60466L,60467L,
-60468L,60469L,60470L,60471L,60472L,60473L,60474L,60475L,60476L,60477L,
-60478L,60479L,60480L,60481L,60482L,60483L,60484L,60485L,60486L,60487L,
-60488L,60489L,60490L,60491L,60492L,60493L,60494L,60495L,60496L,60497L,
-60498L,60499L,60500L,60501L,60502L,60503L,60504L,60505L,60506L,60507L,
-60508L,60509L,60510L,60511L,60512L,60513L,60514L,60515L,60516L,60517L,
-60518L,60519L,60520L,60521L,60522L,60523L,60524L,60525L,60526L,60527L,
-60528L,60529L,60530L,60531L,60532L,60533L,60534L,60535L,60536L,60537L,
-60538L,60539L,60540L,60541L,60542L,60543L,60544L,60545L,60546L,60547L,
-60548L,60549L,60550L,60551L,60552L,60553L,60554L,60555L,60556L,60557L,
-60558L,60559L,60560L,60561L,60562L,60563L,60564L,60565L,60566L,60567L,
-60568L,60569L,60570L,60571L,60572L,60573L,60574L,60575L,60576L,60577L,
-60578L,60579L,60580L,60581L,60582L,60583L,60584L,60585L,60586L,60587L,
-60588L,60589L,60590L,60591L,60592L,60593L,60594L,60595L,60596L,60597L,
-60598L,60599L,60600L,60601L,60602L,60603L,60604L,60605L,60606L,60607L,
-60608L,60609L,60610L,60611L,60612L,60613L,60614L,60615L,60616L,60617L,
-60618L,60619L,60620L,60621L,60622L,60623L,60624L,60625L,60626L,60627L,
-60628L,60629L,60630L,60631L,60632L,60633L,60634L,60635L,60636L,60637L,
-60638L,60639L,60640L,60641L,60642L,60643L,60644L,60645L,60646L,60647L,
-60648L,60649L,60650L,60651L,60652L,60653L,60654L,60655L,60656L,60657L,
-60658L,60659L,60660L,60661L,60662L,60663L,60664L,60665L,60666L,60667L,
-60668L,60669L,60670L,60671L,60672L,60673L,60674L,60675L,60676L,60677L,
-60678L,60679L,60680L,60681L,60682L,60683L,60684L,60685L,60686L,60687L,
-60688L,60689L,60690L,60691L,60692L,60693L,60694L,60695L,60696L,60697L,
-60698L,60699L,60700L,60701L,60702L,60703L,60704L,60705L,60706L,60707L,
-60708L,60709L,60710L,60711L,60712L,60713L,60714L,60715L,60716L,60717L,
-60718L,60719L,60720L,60721L,60722L,60723L,60724L,60725L,60726L,60727L,
-60728L,60729L,60730L,60731L,60732L,60733L,60734L,60735L,60736L,60737L,
-60738L,60739L,60740L,60741L,60742L,60743L,60744L,60745L,60746L,60747L,
-60748L,60749L,60750L,60751L,60752L,60753L,60754L,60755L,60756L,60757L,
-60758L,60759L,60760L,60761L,60762L,60763L,60764L,60765L,60766L,60767L,
-60768L,60769L,60770L,60771L,60772L,60773L,60774L,60775L,60776L,60777L,
-60778L,60779L,60780L,60781L,60782L,60783L,60784L,60785L,60786L,60787L,
-60788L,60789L,60790L,60791L,60792L,60793L,60794L,60795L,60796L,60797L,
-60798L,60799L,60800L,60801L,60802L,60803L,60804L,60805L,60806L,60807L,
-60808L,60809L,60810L,60811L,60812L,60813L,60814L,60815L,60816L,60817L,
-60818L,60819L,60820L,60821L,60822L,60823L,60824L,60825L,60826L,60827L,
-60828L,60829L,60830L,60831L,60832L,60833L,60834L,60835L,60836L,60837L,
-60838L,60839L,60840L,60841L,60842L,60843L,60844L,60845L,60846L,60847L,
-60848L,60849L,60850L,60851L,60852L,60853L,60854L,60855L,60856L,60857L,
-60858L,60859L,60860L,60861L,60862L,60863L,60864L,60865L,60866L,60867L,
-60868L,60869L,60870L,60871L,60872L,60873L,60874L,60875L,60876L,60877L,
-60878L,60879L,60880L,60881L,60882L,60883L,60884L,60885L,60886L,60887L,
-60888L,60889L,60890L,60891L,60892L,60893L,60894L,60895L,60896L,60897L,
-60898L,60899L,60900L,60901L,60902L,60903L,60904L,60905L,60906L,60907L,
-60908L,60909L,60910L,60911L,60912L,60913L,60914L,60915L,60916L,60917L,
-60918L,60919L,60920L,60921L,60922L,60923L,60924L,60925L,60926L,60927L,
-60928L,60929L,60930L,60931L,60932L,60933L,60934L,60935L,60936L,60937L,
-60938L,60939L,60940L,60941L,60942L,60943L,60944L,60945L,60946L,60947L,
-60948L,60949L,60950L,60951L,60952L,60953L,60954L,60955L,60956L,60957L,
-60958L,60959L,60960L,60961L,60962L,60963L,60964L,60965L,60966L,60967L,
-60968L,60969L,60970L,60971L,60972L,60973L,60974L,60975L,60976L,60977L,
-60978L,60979L,60980L,60981L,60982L,60983L,60984L,60985L,60986L,60987L,
-60988L,60989L,60990L,60991L,60992L,60993L,60994L,60995L,60996L,60997L,
-60998L,60999L,61000L,61001L,61002L,61003L,61004L,61005L,61006L,61007L,
-61008L,61009L,61010L,61011L,61012L,61013L,61014L,61015L,61016L,61017L,
-61018L,61019L,61020L,61021L,61022L,61023L,61024L,61025L,61026L,61027L,
-61028L,61029L,61030L,61031L,61032L,61033L,61034L,61035L,61036L,61037L,
-61038L,61039L,61040L,61041L,61042L,61043L,61044L,61045L,61046L,61047L,
-61048L,61049L,61050L,61051L,61052L,61053L,61054L,61055L,61056L,61057L,
-61058L,61059L,61060L,61061L,61062L,61063L,61064L,61065L,61066L,61067L,
-61068L,61069L,61070L,61071L,61072L,61073L,61074L,61075L,61076L,61077L,
-61078L,61079L,61080L,61081L,61082L,61083L,61084L,61085L,61086L,61087L,
-61088L,61089L,61090L,61091L,61092L,61093L,61094L,61095L,61096L,61097L,
-61098L,61099L,61100L,61101L,61102L,61103L,61104L,61105L,61106L,61107L,
-61108L,61109L,61110L,61111L,61112L,61113L,61114L,61115L,61116L,61117L,
-61118L,61119L,61120L,61121L,61122L,61123L,61124L,61125L,61126L,61127L,
-61128L,61129L,61130L,61131L,61132L,61133L,61134L,61135L,61136L,61137L,
-61138L,61139L,61140L,61141L,61142L,61143L,61144L,61145L,61146L,61147L,
-61148L,61149L,61150L,61151L,61152L,61153L,61154L,61155L,61156L,61157L,
-61158L,61159L,61160L,61161L,61162L,61163L,61164L,61165L,61166L,61167L,
-61168L,61169L,61170L,61171L,61172L,61173L,61174L,61175L,61176L,61177L,
-61178L,61179L,61180L,61181L,61182L,61183L,61184L,61185L,61186L,61187L,
-61188L,61189L,61190L,61191L,61192L,61193L,61194L,61195L,61196L,61197L,
-61198L,61199L,61200L,61201L,61202L,61203L,61204L,61205L,61206L,61207L,
-61208L,61209L,61210L,61211L,61212L,61213L,61214L,61215L,61216L,61217L,
-61218L,61219L,61220L,61221L,61222L,61223L,61224L,61225L,61226L,61227L,
-61228L,61229L,61230L,61231L,61232L,61233L,61234L,61235L,61236L,61237L,
-61238L,61239L,61240L,61241L,61242L,61243L,61244L,61245L,61246L,61247L,
-61248L,61249L,61250L,61251L,61252L,61253L,61254L,61255L,61256L,61257L,
-61258L,61259L,61260L,61261L,61262L,61263L,61264L,61265L,61266L,61267L,
-61268L,61269L,61270L,61271L,61272L,61273L,61274L,61275L,61276L,61277L,
-61278L,61279L,61280L,61281L,61282L,61283L,61284L,61285L,61286L,61287L,
-61288L,61289L,61290L,61291L,61292L,61293L,61294L,61295L,61296L,61297L,
-61298L,61299L,61300L,61301L,61302L,61303L,61304L,61305L,61306L,61307L,
-61308L,61309L,61310L,61311L,61312L,61313L,61314L,61315L,61316L,61317L,
-61318L,61319L,61320L,61321L,61322L,61323L,61324L,61325L,61326L,61327L,
-61328L,61329L,61330L,61331L,61332L,61333L,61334L,61335L,61336L,61337L,
-61338L,61339L,61340L,61341L,61342L,61343L,61344L,61345L,61346L,61347L,
-61348L,61349L,61350L,61351L,61352L,61353L,61354L,61355L,61356L,61357L,
-61358L,61359L,61360L,61361L,61362L,61363L,61364L,61365L,61366L,61367L,
-61368L,61369L,61370L,61371L,61372L,61373L,61374L,61375L,61376L,61377L,
-61378L,61379L,61380L,61381L,61382L,61383L,61384L,61385L,61386L,61387L,
-61388L,61389L,61390L,61391L,61392L,61393L,61394L,61395L,61396L,61397L,
-61398L,61399L,61400L,61401L,61402L,61403L,61404L,61405L,61406L,61407L,
-61408L,61409L,61410L,61411L,61412L,61413L,61414L,61415L,61416L,61417L,
-61418L,61419L,61420L,61421L,61422L,61423L,61424L,61425L,61426L,61427L,
-61428L,61429L,61430L,61431L,61432L,61433L,61434L,61435L,61436L,61437L,
-61438L,61439L,61440L,61441L,61442L,61443L,61444L,61445L,61446L,61447L,
-61448L,61449L,61450L,61451L,61452L,61453L,61454L,61455L,61456L,61457L,
-61458L,61459L,61460L,61461L,61462L,61463L,61464L,61465L,61466L,61467L,
-61468L,61469L,61470L,61471L,61472L,61473L,61474L,61475L,61476L,61477L,
-61478L,61479L,61480L,61481L,61482L,61483L,61484L,61485L,61486L,61487L,
-61488L,61489L,61490L,61491L,61492L,61493L,61494L,61495L,61496L,61497L,
-61498L,61499L,61500L,61501L,61502L,61503L,61504L,61505L,61506L,61507L,
-61508L,61509L,61510L,61511L,61512L,61513L,61514L,61515L,61516L,61517L,
-61518L,61519L,61520L,61521L,61522L,61523L,61524L,61525L,61526L,61527L,
-61528L,61529L,61530L,61531L,61532L,61533L,61534L,61535L,61536L,61537L,
-61538L,61539L,61540L,61541L,61542L,61543L,61544L,61545L,61546L,61547L,
-61548L,61549L,61550L,61551L,61552L,61553L,61554L,61555L,61556L,61557L,
-61558L,61559L,61560L,61561L,61562L,61563L,61564L,61565L,61566L,61567L,
-61568L,61569L,61570L,61571L,61572L,61573L,61574L,61575L,61576L,61577L,
-61578L,61579L,61580L,61581L,61582L,61583L,61584L,61585L,61586L,61587L,
-61588L,61589L,61590L,61591L,61592L,61593L,61594L,61595L,61596L,61597L,
-61598L,61599L,61600L,61601L,61602L,61603L,61604L,61605L,61606L,61607L,
-61608L,61609L,61610L,61611L,61612L,61613L,61614L,61615L,61616L,61617L,
-61618L,61619L,61620L,61621L,61622L,61623L,61624L,61625L,61626L,61627L,
-61628L,61629L,61630L,61631L,61632L,61633L,61634L,61635L,61636L,61637L,
-61638L,61639L,61640L,61641L,61642L,61643L,61644L,61645L,61646L,61647L,
-61648L,61649L,61650L,61651L,61652L,61653L,61654L,61655L,61656L,61657L,
-61658L,61659L,61660L,61661L,61662L,61663L,61664L,61665L,61666L,61667L,
-61668L,61669L,61670L,61671L,61672L,61673L,61674L,61675L,61676L,61677L,
-61678L,61679L,61680L,61681L,61682L,61683L,61684L,61685L,61686L,61687L,
-61688L,61689L,61690L,61691L,61692L,61693L,61694L,61695L,61696L,61697L,
-61698L,61699L,61700L,61701L,61702L,61703L,61704L,61705L,61706L,61707L,
-61708L,61709L,61710L,61711L,61712L,61713L,61714L,61715L,61716L,61717L,
-61718L,61719L,61720L,61721L,61722L,61723L,61724L,61725L,61726L,61727L,
-61728L,61729L,61730L,61731L,61732L,61733L,61734L,61735L,61736L,61737L,
-61738L,61739L,61740L,61741L,61742L,61743L,61744L,61745L,61746L,61747L,
-61748L,61749L,61750L,61751L,61752L,61753L,61754L,61755L,61756L,61757L,
-61758L,61759L,61760L,61761L,61762L,61763L,61764L,61765L,61766L,61767L,
-61768L,61769L,61770L,61771L,61772L,61773L,61774L,61775L,61776L,61777L,
-61778L,61779L,61780L,61781L,61782L,61783L,61784L,61785L,61786L,61787L,
-61788L,61789L,61790L,61791L,61792L,61793L,61794L,61795L,61796L,61797L,
-61798L,61799L,61800L,61801L,61802L,61803L,61804L,61805L,61806L,61807L,
-61808L,61809L,61810L,61811L,61812L,61813L,61814L,61815L,61816L,61817L,
-61818L,61819L,61820L,61821L,61822L,61823L,61824L,61825L,61826L,61827L,
-61828L,61829L,61830L,61831L,61832L,61833L,61834L,61835L,61836L,61837L,
-61838L,61839L,61840L,61841L,61842L,61843L,61844L,61845L,61846L,61847L,
-61848L,61849L,61850L,61851L,61852L,61853L,61854L,61855L,61856L,61857L,
-61858L,61859L,61860L,61861L,61862L,61863L,61864L,61865L,61866L,61867L,
-61868L,61869L,61870L,61871L,61872L,61873L,61874L,61875L,61876L,61877L,
-61878L,61879L,61880L,61881L,61882L,61883L,61884L,61885L,61886L,61887L,
-61888L,61889L,61890L,61891L,61892L,61893L,61894L,61895L,61896L,61897L,
-61898L,61899L,61900L,61901L,61902L,61903L,61904L,61905L,61906L,61907L,
-61908L,61909L,61910L,61911L,61912L,61913L,61914L,61915L,61916L,61917L,
-61918L,61919L,61920L,61921L,61922L,61923L,61924L,61925L,61926L,61927L,
-61928L,61929L,61930L,61931L,61932L,61933L,61934L,61935L,61936L,61937L,
-61938L,61939L,61940L,61941L,61942L,61943L,61944L,61945L,61946L,61947L,
-61948L,61949L,61950L,61951L,61952L,61953L,61954L,61955L,61956L,61957L,
-61958L,61959L,61960L,61961L,61962L,61963L,61964L,61965L,61966L,61967L,
-61968L,61969L,61970L,61971L,61972L,61973L,61974L,61975L,61976L,61977L,
-61978L,61979L,61980L,61981L,61982L,61983L,61984L,61985L,61986L,61987L,
-61988L,61989L,61990L,61991L,61992L,61993L,61994L,61995L,61996L,61997L,
-61998L,61999L,62000L,62001L,62002L,62003L,62004L,62005L,62006L,62007L,
-62008L,62009L,62010L,62011L,62012L,62013L,62014L,62015L,62016L,62017L,
-62018L,62019L,62020L,62021L,62022L,62023L,62024L,62025L,62026L,62027L,
-62028L,62029L,62030L,62031L,62032L,62033L,62034L,62035L,62036L,62037L,
-62038L,62039L,62040L,62041L,62042L,62043L,62044L,62045L,62046L,62047L,
-62048L,62049L,62050L,62051L,62052L,62053L,62054L,62055L,62056L,62057L,
-62058L,62059L,62060L,62061L,62062L,62063L,62064L,62065L,62066L,62067L,
-62068L,62069L,62070L,62071L,62072L,62073L,62074L,62075L,62076L,62077L,
-62078L,62079L,62080L,62081L,62082L,62083L,62084L,62085L,62086L,62087L,
-62088L,62089L,62090L,62091L,62092L,62093L,62094L,62095L,62096L,62097L,
-62098L,62099L,62100L,62101L,62102L,62103L,62104L,62105L,62106L,62107L,
-62108L,62109L,62110L,62111L,62112L,62113L,62114L,62115L,62116L,62117L,
-62118L,62119L,62120L,62121L,62122L,62123L,62124L,62125L,62126L,62127L,
-62128L,62129L,62130L,62131L,62132L,62133L,62134L,62135L,62136L,62137L,
-62138L,62139L,62140L,62141L,62142L,62143L,62144L,62145L,62146L,62147L,
-62148L,62149L,62150L,62151L,62152L,62153L,62154L,62155L,62156L,62157L,
-62158L,62159L,62160L,62161L,62162L,62163L,62164L,62165L,62166L,62167L,
-62168L,62169L,62170L,62171L,62172L,62173L,62174L,62175L,62176L,62177L,
-62178L,62179L,62180L,62181L,62182L,62183L,62184L,62185L,62186L,62187L,
-62188L,62189L,62190L,62191L,62192L,62193L,62194L,62195L,62196L,62197L,
-62198L,62199L,62200L,62201L,62202L,62203L,62204L,62205L,62206L,62207L,
-62208L,62209L,62210L,62211L,62212L,62213L,62214L,62215L,62216L,62217L,
-62218L,62219L,62220L,62221L,62222L,62223L,62224L,62225L,62226L,62227L,
-62228L,62229L,62230L,62231L,62232L,62233L,62234L,62235L,62236L,62237L,
-62238L,62239L,62240L,62241L,62242L,62243L,62244L,62245L,62246L,62247L,
-62248L,62249L,62250L,62251L,62252L,62253L,62254L,62255L,62256L,62257L,
-62258L,62259L,62260L,62261L,62262L,62263L,62264L,62265L,62266L,62267L,
-62268L,62269L,62270L,62271L,62272L,62273L,62274L,62275L,62276L,62277L,
-62278L,62279L,62280L,62281L,62282L,62283L,62284L,62285L,62286L,62287L,
-62288L,62289L,62290L,62291L,62292L,62293L,62294L,62295L,62296L,62297L,
-62298L,62299L,62300L,62301L,62302L,62303L,62304L,62305L,62306L,62307L,
-62308L,62309L,62310L,62311L,62312L,62313L,62314L,62315L,62316L,62317L,
-62318L,62319L,62320L,62321L,62322L,62323L,62324L,62325L,62326L,62327L,
-62328L,62329L,62330L,62331L,62332L,62333L,62334L,62335L,62336L,62337L,
-62338L,62339L,62340L,62341L,62342L,62343L,62344L,62345L,62346L,62347L,
-62348L,62349L,62350L,62351L,62352L,62353L,62354L,62355L,62356L,62357L,
-62358L,62359L,62360L,62361L,62362L,62363L,62364L,62365L,62366L,62367L,
-62368L,62369L,62370L,62371L,62372L,62373L,62374L,62375L,62376L,62377L,
-62378L,62379L,62380L,62381L,62382L,62383L,62384L,62385L,62386L,62387L,
-62388L,62389L,62390L,62391L,62392L,62393L,62394L,62395L,62396L,62397L,
-62398L,62399L,62400L,62401L,62402L,62403L,62404L,62405L,62406L,62407L,
-62408L,62409L,62410L,62411L,62412L,62413L,62414L,62415L,62416L,62417L,
-62418L,62419L,62420L,62421L,62422L,62423L,62424L,62425L,62426L,62427L,
-62428L,62429L,62430L,62431L,62432L,62433L,62434L,62435L,62436L,62437L,
-62438L,62439L,62440L,62441L,62442L,62443L,62444L,62445L,62446L,62447L,
-62448L,62449L,62450L,62451L,62452L,62453L,62454L,62455L,62456L,62457L,
-62458L,62459L,62460L,62461L,62462L,62463L,62464L,62465L,62466L,62467L,
-62468L,62469L,62470L,62471L,62472L,62473L,62474L,62475L,62476L,62477L,
-62478L,62479L,62480L,62481L,62482L,62483L,62484L,62485L,62486L,62487L,
-62488L,62489L,62490L,62491L,62492L,62493L,62494L,62495L,62496L,62497L,
-62498L,62499L,62500L,62501L,62502L,62503L,62504L,62505L,62506L,62507L,
-62508L,62509L,62510L,62511L,62512L,62513L,62514L,62515L,62516L,62517L,
-62518L,62519L,62520L,62521L,62522L,62523L,62524L,62525L,62526L,62527L,
-62528L,62529L,62530L,62531L,62532L,62533L,62534L,62535L,62536L,62537L,
-62538L,62539L,62540L,62541L,62542L,62543L,62544L,62545L,62546L,62547L,
-62548L,62549L,62550L,62551L,62552L,62553L,62554L,62555L,62556L,62557L,
-62558L,62559L,62560L,62561L,62562L,62563L,62564L,62565L,62566L,62567L,
-62568L,62569L,62570L,62571L,62572L,62573L,62574L,62575L,62576L,62577L,
-62578L,62579L,62580L,62581L,62582L,62583L,62584L,62585L,62586L,62587L,
-62588L,62589L,62590L,62591L,62592L,62593L,62594L,62595L,62596L,62597L,
-62598L,62599L,62600L,62601L,62602L,62603L,62604L,62605L,62606L,62607L,
-62608L,62609L,62610L,62611L,62612L,62613L,62614L,62615L,62616L,62617L,
-62618L,62619L,62620L,62621L,62622L,62623L,62624L,62625L,62626L,62627L,
-62628L,62629L,62630L,62631L,62632L,62633L,62634L,62635L,62636L,62637L,
-62638L,62639L,62640L,62641L,62642L,62643L,62644L,62645L,62646L,62647L,
-62648L,62649L,62650L,62651L,62652L,62653L,62654L,62655L,62656L,62657L,
-62658L,62659L,62660L,62661L,62662L,62663L,62664L,62665L,62666L,62667L,
-62668L,62669L,62670L,62671L,62672L,62673L,62674L,62675L,62676L,62677L,
-62678L,62679L,62680L,62681L,62682L,62683L,62684L,62685L,62686L,62687L,
-62688L,62689L,62690L,62691L,62692L,62693L,62694L,62695L,62696L,62697L,
-62698L,62699L,62700L,62701L,62702L,62703L,62704L,62705L,62706L,62707L,
-62708L,62709L,62710L,62711L,62712L,62713L,62714L,62715L,62716L,62717L,
-62718L,62719L,62720L,62721L,62722L,62723L,62724L,62725L,62726L,62727L,
-62728L,62729L,62730L,62731L,62732L,62733L,62734L,62735L,62736L,62737L,
-62738L,62739L,62740L,62741L,62742L,62743L,62744L,62745L,62746L,62747L,
-62748L,62749L,62750L,62751L,62752L,62753L,62754L,62755L,62756L,62757L,
-62758L,62759L,62760L,62761L,62762L,62763L,62764L,62765L,62766L,62767L,
-62768L,62769L,62770L,62771L,62772L,62773L,62774L,62775L,62776L,62777L,
-62778L,62779L,62780L,62781L,62782L,62783L,62784L,62785L,62786L,62787L,
-62788L,62789L,62790L,62791L,62792L,62793L,62794L,62795L,62796L,62797L,
-62798L,62799L,62800L,62801L,62802L,62803L,62804L,62805L,62806L,62807L,
-62808L,62809L,62810L,62811L,62812L,62813L,62814L,62815L,62816L,62817L,
-62818L,62819L,62820L,62821L,62822L,62823L,62824L,62825L,62826L,62827L,
-62828L,62829L,62830L,62831L,62832L,62833L,62834L,62835L,62836L,62837L,
-62838L,62839L,62840L,62841L,62842L,62843L,62844L,62845L,62846L,62847L,
-62848L,62849L,62850L,62851L,62852L,62853L,62854L,62855L,62856L,62857L,
-62858L,62859L,62860L,62861L,62862L,62863L,62864L,62865L,62866L,62867L,
-62868L,62869L,62870L,62871L,62872L,62873L,62874L,62875L,62876L,62877L,
-62878L,62879L,62880L,62881L,62882L,62883L,62884L,62885L,62886L,62887L,
-62888L,62889L,62890L,62891L,62892L,62893L,62894L,62895L,62896L,62897L,
-62898L,62899L,62900L,62901L,62902L,62903L,62904L,62905L,62906L,62907L,
-62908L,62909L,62910L,62911L,62912L,62913L,62914L,62915L,62916L,62917L,
-62918L,62919L,62920L,62921L,62922L,62923L,62924L,62925L,62926L,62927L,
-62928L,62929L,62930L,62931L,62932L,62933L,62934L,62935L,62936L,62937L,
-62938L,62939L,62940L,62941L,62942L,62943L,62944L,62945L,62946L,62947L,
-62948L,62949L,62950L,62951L,62952L,62953L,62954L,62955L,62956L,62957L,
-62958L,62959L,62960L,62961L,62962L,62963L,62964L,62965L,62966L,62967L,
-62968L,62969L,62970L,62971L,62972L,62973L,62974L,62975L,62976L,62977L,
-62978L,62979L,62980L,62981L,62982L,62983L,62984L,62985L,62986L,62987L,
-62988L,62989L,62990L,62991L,62992L,62993L,62994L,62995L,62996L,62997L,
-62998L,62999L,63000L,63001L,63002L,63003L,63004L,63005L,63006L,63007L,
-63008L,63009L,63010L,63011L,63012L,63013L,63014L,63015L,63016L,63017L,
-63018L,63019L,63020L,63021L,63022L,63023L,63024L,63025L,63026L,63027L,
-63028L,63029L,63030L,63031L,63032L,63033L,63034L,63035L,63036L,63037L,
-63038L,63039L,63040L,63041L,63042L,63043L,63044L,63045L,63046L,63047L,
-63048L,63049L,63050L,63051L,63052L,63053L,63054L,63055L,63056L,63057L,
-63058L,63059L,63060L,63061L,63062L,63063L,63064L,63065L,63066L,63067L,
-63068L,63069L,63070L,63071L,63072L,63073L,63074L,63075L,63076L,63077L,
-63078L,63079L,63080L,63081L,63082L,63083L,63084L,63085L,63086L,63087L,
-63088L,63089L,63090L,63091L,63092L,63093L,63094L,63095L,63096L,63097L,
-63098L,63099L,63100L,63101L,63102L,63103L,63104L,63105L,63106L,63107L,
-63108L,63109L,63110L,63111L,63112L,63113L,63114L,63115L,63116L,63117L,
-63118L,63119L,63120L,63121L,63122L,63123L,63124L,63125L,63126L,63127L,
-63128L,63129L,63130L,63131L,63132L,63133L,63134L,63135L,63136L,63137L,
-63138L,63139L,63140L,63141L,63142L,63143L,63144L,63145L,63146L,63147L,
-63148L,63149L,63150L,63151L,63152L,63153L,63154L,63155L,63156L,63157L,
-63158L,63159L,63160L,63161L,63162L,63163L,63164L,63165L,63166L,63167L,
-63168L,63169L,63170L,63171L,63172L,63173L,63174L,63175L,63176L,63177L,
-63178L,63179L,63180L,63181L,63182L,63183L,63184L,63185L,63186L,63187L,
-63188L,63189L,63190L,63191L,63192L,63193L,63194L,63195L,63196L,63197L,
-63198L,63199L,63200L,63201L,63202L,63203L,63204L,63205L,63206L,63207L,
-63208L,63209L,63210L,63211L,63212L,63213L,63214L,63215L,63216L,63217L,
-63218L,63219L,63220L,63221L,63222L,63223L,63224L,63225L,63226L,63227L,
-63228L,63229L,63230L,63231L,63232L,63233L,63234L,63235L,63236L,63237L,
-63238L,63239L,63240L,63241L,63242L,63243L,63244L,63245L,63246L,63247L,
-63248L,63249L,63250L,63251L,63252L,63253L,63254L,63255L,63256L,63257L,
-63258L,63259L,63260L,63261L,63262L,63263L,63264L,63265L,63266L,63267L,
-63268L,63269L,63270L,63271L,63272L,63273L,63274L,63275L,63276L,63277L,
-63278L,63279L,63280L,63281L,63282L,63283L,63284L,63285L,63286L,63287L,
-63288L,63289L,63290L,63291L,63292L,63293L,63294L,63295L,63296L,63297L,
-63298L,63299L,63300L,63301L,63302L,63303L,63304L,63305L,63306L,63307L,
-63308L,63309L,63310L,63311L,63312L,63313L,63314L,63315L,63316L,63317L,
-63318L,63319L,63320L,63321L,63322L,63323L,63324L,63325L,63326L,63327L,
-63328L,63329L,63330L,63331L,63332L,63333L,63334L,63335L,63336L,63337L,
-63338L,63339L,63340L,63341L,63342L,63343L,63344L,63345L,63346L,63347L,
-63348L,63349L,63350L,63351L,63352L,63353L,63354L,63355L,63356L,63357L,
-63358L,63359L,63360L,63361L,63362L,63363L,63364L,63365L,63366L,63367L,
-63368L,63369L,63370L,63371L,63372L,63373L,63374L,63375L,63376L,63377L,
-63378L,63379L,63380L,63381L,63382L,63383L,63384L,63385L,63386L,63387L,
-63388L,63389L,63390L,63391L,63392L,63393L,63394L,63395L,63396L,63397L,
-63398L,63399L,63400L,63401L,63402L,63403L,63404L,63405L,63406L,63407L,
-63408L,63409L,63410L,63411L,63412L,63413L,63414L,63415L,63416L,63417L,
-63418L,63419L,63420L,63421L,63422L,63423L,63424L,63425L,63426L,63427L,
-63428L,63429L,63430L,63431L,63432L,63433L,63434L,63435L,63436L,63437L,
-63438L,63439L,63440L,63441L,63442L,63443L,63444L,63445L,63446L,63447L,
-63448L,63449L,63450L,63451L,63452L,63453L,63454L,63455L,63456L,63457L,
-63458L,63459L,63460L,63461L,63462L,63463L,63464L,63465L,63466L,63467L,
-63468L,63469L,63470L,63471L,63472L,63473L,63474L,63475L,63476L,63477L,
-63478L,63479L,63480L,63481L,63482L,63483L,63484L,63485L,63486L,63487L,
-63488L,63489L,63490L,63491L,63492L,63493L,63494L,63495L,63496L,63497L,
-63498L,63499L,63500L,63501L,63502L,63503L,63504L,63505L,63506L,63507L,
-63508L,63509L,63510L,63511L,63512L,63513L,63514L,63515L,63516L,63517L,
-63518L,63519L,63520L,63521L,63522L,63523L,63524L,63525L,63526L,63527L,
-63528L,63529L,63530L,63531L,63532L,63533L,63534L,63535L,63536L,63537L,
-63538L,63539L,63540L,63541L,63542L,63543L,63544L,63545L,63546L,63547L,
-63548L,63549L,63550L,63551L,63552L,63553L,63554L,63555L,63556L,63557L,
-63558L,63559L,63560L,63561L,63562L,63563L,63564L,63565L,63566L,63567L,
-63568L,63569L,63570L,63571L,63572L,63573L,63574L,63575L,63576L,63577L,
-63578L,63579L,63580L,63581L,63582L,63583L,63584L,63585L,63586L,63587L,
-63588L,63589L,63590L,63591L,63592L,63593L,63594L,63595L,63596L,63597L,
-63598L,63599L,63600L,63601L,63602L,63603L,63604L,63605L,63606L,63607L,
-63608L,63609L,63610L,63611L,63612L,63613L,63614L,63615L,63616L,63617L,
-63618L,63619L,63620L,63621L,63622L,63623L,63624L,63625L,63626L,63627L,
-63628L,63629L,63630L,63631L,63632L,63633L,63634L,63635L,63636L,63637L,
-63638L,63639L,63640L,63641L,63642L,63643L,63644L,63645L,63646L,63647L,
-63648L,63649L,63650L,63651L,63652L,63653L,63654L,63655L,63656L,63657L,
-63658L,63659L,63660L,63661L,63662L,63663L,63664L,63665L,63666L,63667L,
-63668L,63669L,63670L,63671L,63672L,63673L,63674L,63675L,63676L,63677L,
-63678L,63679L,63680L,63681L,63682L,63683L,63684L,63685L,63686L,63687L,
-63688L,63689L,63690L,63691L,63692L,63693L,63694L,63695L,63696L,63697L,
-63698L,63699L,63700L,63701L,63702L,63703L,63704L,63705L,63706L,63707L,
-63708L,63709L,63710L,63711L,63712L,63713L,63714L,63715L,63716L,63717L,
-63718L,63719L,63720L,63721L,63722L,63723L,63724L,63725L,63726L,63727L,
-63728L,63729L,63730L,63731L,63732L,63733L,63734L,63735L,63736L,63737L,
-63738L,63739L,63740L,63741L,63742L,63743L,63744L,63745L,63746L,63747L,
-63748L,63749L,63750L,63751L,63752L,63753L,63754L,63755L,63756L,63757L,
-63758L,63759L,63760L,63761L,63762L,63763L,63764L,63765L,63766L,63767L,
-63768L,63769L,63770L,63771L,63772L,63773L,63774L,63775L,63776L,63777L,
-63778L,63779L,63780L,63781L,63782L,63783L,63784L,63785L,63786L,63787L,
-63788L,63789L,63790L,63791L,63792L,63793L,63794L,63795L,63796L,63797L,
-63798L,63799L,63800L,63801L,63802L,63803L,63804L,63805L,63806L,63807L,
-63808L,63809L,63810L,63811L,63812L,63813L,63814L,63815L,63816L,63817L,
-63818L,63819L,63820L,63821L,63822L,63823L,63824L,63825L,63826L,63827L,
-63828L,63829L,63830L,63831L,63832L,63833L,63834L,63835L,63836L,63837L,
-63838L,63839L,63840L,63841L,63842L,63843L,63844L,63845L,63846L,63847L,
-63848L,63849L,63850L,63851L,63852L,63853L,63854L,63855L,63856L,63857L,
-63858L,63859L,63860L,63861L,63862L,63863L,63864L,63865L,63866L,63867L,
-63868L,63869L,63870L,63871L,63872L,63873L,63874L,63875L,63876L,63877L,
-63878L,63879L,63880L,63881L,63882L,63883L,63884L,63885L,63886L,63887L,
-63888L,63889L,63890L,63891L,63892L,63893L,63894L,63895L,63896L,63897L,
-63898L,63899L,63900L,63901L,63902L,63903L,63904L,63905L,63906L,63907L,
-63908L,63909L,63910L,63911L,63912L,63913L,63914L,63915L,63916L,63917L,
-63918L,63919L,63920L,63921L,63922L,63923L,63924L,63925L,63926L,63927L,
-63928L,63929L,63930L,63931L,63932L,63933L,63934L,63935L,63936L,63937L,
-63938L,63939L,63940L,63941L,63942L,63943L,63944L,63945L,63946L,63947L,
-63948L,63949L,63950L,63951L,63952L,63953L,63954L,63955L,63956L,63957L,
-63958L,63959L,63960L,63961L,63962L,63963L,63964L,63965L,63966L,63967L,
-63968L,63969L,63970L,63971L,63972L,63973L,63974L,63975L,63976L,63977L,
-63978L,63979L,63980L,63981L,63982L,63983L,63984L,63985L,63986L,63987L,
-63988L,63989L,63990L,63991L,63992L,63993L,63994L,63995L,63996L,63997L,
-63998L,63999L,64000L,64001L,64002L,64003L,64004L,64005L,64006L,64007L,
-64008L,64009L,64010L,64011L,64012L,64013L,64014L,64015L,64016L,64017L,
-64018L,64019L,64020L,64021L,64022L,64023L,64024L,64025L,64026L,64027L,
-64028L,64029L,64030L,64031L,64032L,64033L,64034L,64035L,64036L,64037L,
-64038L,64039L,64040L,64041L,64042L,64043L,64044L,64045L,64046L,64047L,
-64048L,64049L,64050L,64051L,64052L,64053L,64054L,64055L,64056L,64057L,
-64058L,64059L,64060L,64061L,64062L,64063L,64064L,64065L,64066L,64067L,
-64068L,64069L,64070L,64071L,64072L,64073L,64074L,64075L,64076L,64077L,
-64078L,64079L,64080L,64081L,64082L,64083L,64084L,64085L,64086L,64087L,
-64088L,64089L,64090L,64091L,64092L,64093L,64094L,64095L,64096L,64097L,
-64098L,64099L,64100L,64101L,64102L,64103L,64104L,64105L,64106L,64107L,
-64108L,64109L,64110L,64111L,64112L,64113L,64114L,64115L,64116L,64117L,
-64118L,64119L,64120L,64121L,64122L,64123L,64124L,64125L,64126L,64127L,
-64128L,64129L,64130L,64131L,64132L,64133L,64134L,64135L,64136L,64137L,
-64138L,64139L,64140L,64141L,64142L,64143L,64144L,64145L,64146L,64147L,
-64148L,64149L,64150L,64151L,64152L,64153L,64154L,64155L,64156L,64157L,
-64158L,64159L,64160L,64161L,64162L,64163L,64164L,64165L,64166L,64167L,
-64168L,64169L,64170L,64171L,64172L,64173L,64174L,64175L,64176L,64177L,
-64178L,64179L,64180L,64181L,64182L,64183L,64184L,64185L,64186L,64187L,
-64188L,64189L,64190L,64191L,64192L,64193L,64194L,64195L,64196L,64197L,
-64198L,64199L,64200L,64201L,64202L,64203L,64204L,64205L,64206L,64207L,
-64208L,64209L,64210L,64211L,64212L,64213L,64214L,64215L,64216L,64217L,
-64218L,64219L,64220L,64221L,64222L,64223L,64224L,64225L,64226L,64227L,
-64228L,64229L,64230L,64231L,64232L,64233L,64234L,64235L,64236L,64237L,
-64238L,64239L,64240L,64241L,64242L,64243L,64244L,64245L,64246L,64247L,
-64248L,64249L,64250L,64251L,64252L,64253L,64254L,64255L,64256L,64257L,
-64258L,64259L,64260L,64261L,64262L,64263L,64264L,64265L,64266L,64267L,
-64268L,64269L,64270L,64271L,64272L,64273L,64274L,64275L,64276L,64277L,
-64278L,64279L,64280L,64281L,64282L,64283L,64284L,64285L,64286L,64287L,
-64288L,64289L,64290L,64291L,64292L,64293L,64294L,64295L,64296L,64297L,
-64298L,64299L,64300L,64301L,64302L,64303L,64304L,64305L,64306L,64307L,
-64308L,64309L,64310L,64311L,64312L,64313L,64314L,64315L,64316L,64317L,
-64318L,64319L,64320L,64321L,64322L,64323L,64324L,64325L,64326L,64327L,
-64328L,64329L,64330L,64331L,64332L,64333L,64334L,64335L,64336L,64337L,
-64338L,64339L,64340L,64341L,64342L,64343L,64344L,64345L,64346L,64347L,
-64348L,64349L,64350L,64351L,64352L,64353L,64354L,64355L,64356L,64357L,
-64358L,64359L,64360L,64361L,64362L,64363L,64364L,64365L,64366L,64367L,
-64368L,64369L,64370L,64371L,64372L,64373L,64374L,64375L,64376L,64377L,
-64378L,64379L,64380L,64381L,64382L,64383L,64384L,64385L,64386L,64387L,
-64388L,64389L,64390L,64391L,64392L,64393L,64394L,64395L,64396L,64397L,
-64398L,64399L,64400L,64401L,64402L,64403L,64404L,64405L,64406L,64407L,
-64408L,64409L,64410L,64411L,64412L,64413L,64414L,64415L,64416L,64417L,
-64418L,64419L,64420L,64421L,64422L,64423L,64424L,64425L,64426L,64427L,
-64428L,64429L,64430L,64431L,64432L,64433L,64434L,64435L,64436L,64437L,
-64438L,64439L,64440L,64441L,64442L,64443L,64444L,64445L,64446L,64447L,
-64448L,64449L,64450L,64451L,64452L,64453L,64454L,64455L,64456L,64457L,
-64458L,64459L,64460L,64461L,64462L,64463L,64464L,64465L,64466L,64467L,
-64468L,64469L,64470L,64471L,64472L,64473L,64474L,64475L,64476L,64477L,
-64478L,64479L,64480L,64481L,64482L,64483L,64484L,64485L,64486L,64487L,
-64488L,64489L,64490L,64491L,64492L,64493L,64494L,64495L,64496L,64497L,
-64498L,64499L,64500L,64501L,64502L,64503L,64504L,64505L,64506L,64507L,
-64508L,64509L,64510L,64511L,64512L,64513L,64514L,64515L,64516L,64517L,
-64518L,64519L,64520L,64521L,64522L,64523L,64524L,64525L,64526L,64527L,
-64528L,64529L,64530L,64531L,64532L,64533L,64534L,64535L,64536L,64537L,
-64538L,64539L,64540L,64541L,64542L,64543L,64544L,64545L,64546L,64547L,
-64548L,64549L,64550L,64551L,64552L,64553L,64554L,64555L,64556L,64557L,
-64558L,64559L,64560L,64561L,64562L,64563L,64564L,64565L,64566L,64567L,
-64568L,64569L,64570L,64571L,64572L,64573L,64574L,64575L,64576L,64577L,
-64578L,64579L,64580L,64581L,64582L,64583L,64584L,64585L,64586L,64587L,
-64588L,64589L,64590L,64591L,64592L,64593L,64594L,64595L,64596L,64597L,
-64598L,64599L,64600L,64601L,64602L,64603L,64604L,64605L,64606L,64607L,
-64608L,64609L,64610L,64611L,64612L,64613L,64614L,64615L,64616L,64617L,
-64618L,64619L,64620L,64621L,64622L,64623L,64624L,64625L,64626L,64627L,
-64628L,64629L,64630L,64631L,64632L,64633L,64634L,64635L,64636L,64637L,
-64638L,64639L,64640L,64641L,64642L,64643L,64644L,64645L,64646L,64647L,
-64648L,64649L,64650L,64651L,64652L,64653L,64654L,64655L,64656L,64657L,
-64658L,64659L,64660L,64661L,64662L,64663L,64664L,64665L,64666L,64667L,
-64668L,64669L,64670L,64671L,64672L,64673L,64674L,64675L,64676L,64677L,
-64678L,64679L,64680L,64681L,64682L,64683L,64684L,64685L,64686L,64687L,
-64688L,64689L,64690L,64691L,64692L,64693L,64694L,64695L,64696L,64697L,
-64698L,64699L,64700L,64701L,64702L,64703L,64704L,64705L,64706L,64707L,
-64708L,64709L,64710L,64711L,64712L,64713L,64714L,64715L,64716L,64717L,
-64718L,64719L,64720L,64721L,64722L,64723L,64724L,64725L,64726L,64727L,
-64728L,64729L,64730L,64731L,64732L,64733L,64734L,64735L,64736L,64737L,
-64738L,64739L,64740L,64741L,64742L,64743L,64744L,64745L,64746L,64747L,
-64748L,64749L,64750L,64751L,64752L,64753L,64754L,64755L,64756L,64757L,
-64758L,64759L,64760L,64761L,64762L,64763L,64764L,64765L,64766L,64767L,
-64768L,64769L,64770L,64771L,64772L,64773L,64774L,64775L,64776L,64777L,
-64778L,64779L,64780L,64781L,64782L,64783L,64784L,64785L,64786L,64787L,
-64788L,64789L,64790L,64791L,64792L,64793L,64794L,64795L,64796L,64797L,
-64798L,64799L,64800L,64801L,64802L,64803L,64804L,64805L,64806L,64807L,
-64808L,64809L,64810L,64811L,64812L,64813L,64814L,64815L,64816L,64817L,
-64818L,64819L,64820L,64821L,64822L,64823L,64824L,64825L,64826L,64827L,
-64828L,64829L,64830L,64831L,64832L,64833L,64834L,64835L,64836L,64837L,
-64838L,64839L,64840L,64841L,64842L,64843L,64844L,64845L,64846L,64847L,
-64848L,64849L,64850L,64851L,64852L,64853L,64854L,64855L,64856L,64857L,
-64858L,64859L,64860L,64861L,64862L,64863L,64864L,64865L,64866L,64867L,
-64868L,64869L,64870L,64871L,64872L,64873L,64874L,64875L,64876L,64877L,
-64878L,64879L,64880L,64881L,64882L,64883L,64884L,64885L,64886L,64887L,
-64888L,64889L,64890L,64891L,64892L,64893L,64894L,64895L,64896L,64897L,
-64898L,64899L,64900L,64901L,64902L,64903L,64904L,64905L,64906L,64907L,
-64908L,64909L,64910L,64911L,64912L,64913L,64914L,64915L,64916L,64917L,
-64918L,64919L,64920L,64921L,64922L,64923L,64924L,64925L,64926L,64927L,
-64928L,64929L,64930L,64931L,64932L,64933L,64934L,64935L,64936L,64937L,
-64938L,64939L,64940L,64941L,64942L,64943L,64944L,64945L,64946L,64947L,
-64948L,64949L,64950L,64951L,64952L,64953L,64954L,64955L,64956L,64957L,
-64958L,64959L,64960L,64961L,64962L,64963L,64964L,64965L,64966L,64967L,
-64968L,64969L,64970L,64971L,64972L,64973L,64974L,64975L,64976L,64977L,
-64978L,64979L,64980L,64981L,64982L,64983L,64984L,64985L,64986L,64987L,
-64988L,64989L,64990L,64991L,64992L,64993L,64994L,64995L,64996L,64997L,
-64998L,64999L,65000L,65001L,65002L,65003L,65004L,65005L,65006L,65007L,
-65008L,65009L,65010L,65011L,65012L,65013L,65014L,65015L,65016L,65017L,
-65018L,65019L,65020L,65021L,65022L,65023L,65024L,65025L,65026L,65027L,
-65028L,65029L,65030L,65031L,65032L,65033L,65034L,65035L,65036L,65037L,
-65038L,65039L,65040L,65041L,65042L,65043L,65044L,65045L,65046L,65047L,
-65048L,65049L,65050L,65051L,65052L,65053L,65054L,65055L,65056L,65057L,
-65058L,65059L,65060L,65061L,65062L,65063L,65064L,65065L,65066L,65067L,
-65068L,65069L,65070L,65071L,65072L,65073L,65074L,65075L,65076L,65077L,
-65078L,65079L,65080L,65081L,65082L,65083L,65084L,65085L,65086L,65087L,
-65088L,65089L,65090L,65091L,65092L,65093L,65094L,65095L,65096L,65097L,
-65098L,65099L,65100L,65101L,65102L,65103L,65104L,65105L,65106L,65107L,
-65108L,65109L,65110L,65111L,65112L,65113L,65114L,65115L,65116L,65117L,
-65118L,65119L,65120L,65121L,65122L,65123L,65124L,65125L,65126L,65127L,
-65128L,65129L,65130L,65131L,65132L,65133L,65134L,65135L,65136L,65137L,
-65138L,65139L,65140L,65141L,65142L,65143L,65144L,65145L,65146L,65147L,
-65148L,65149L,65150L,65151L,65152L,65153L,65154L,65155L,65156L,65157L,
-65158L,65159L,65160L,65161L,65162L,65163L,65164L,65165L,65166L,65167L,
-65168L,65169L,65170L,65171L,65172L,65173L,65174L,65175L,65176L,65177L,
-65178L,65179L,65180L,65181L,65182L,65183L,65184L,65185L,65186L,65187L,
-65188L,65189L,65190L,65191L,65192L,65193L,65194L,65195L,65196L,65197L,
-65198L,65199L,65200L,65201L,65202L,65203L,65204L,65205L,65206L,65207L,
-65208L,65209L,65210L,65211L,65212L,65213L,65214L,65215L,65216L,65217L,
-65218L,65219L,65220L,65221L,65222L,65223L,65224L,65225L,65226L,65227L,
-65228L,65229L,65230L,65231L,65232L,65233L,65234L,65235L,65236L,65237L,
-65238L,65239L,65240L,65241L,65242L,65243L,65244L,65245L,65246L,65247L,
-65248L,65249L,65250L,65251L,65252L,65253L,65254L,65255L,65256L,65257L,
-65258L,65259L,65260L,65261L,65262L,65263L,65264L,65265L,65266L,65267L,
-65268L,65269L,65270L,65271L,65272L,65273L,65274L,65275L,65276L,65277L,
-65278L,65279L,65280L,65281L,65282L,65283L,65284L,65285L,65286L,65287L,
-65288L,65289L,65290L,65291L,65292L,65293L,65294L,65295L,65296L,65297L,
-65298L,65299L,65300L,65301L,65302L,65303L,65304L,65305L,65306L,65307L,
-65308L,65309L,65310L,65311L,65312L,65313L,65314L,65315L,65316L,65317L,
-65318L,65319L,65320L,65321L,65322L,65323L,65324L,65325L,65326L,65327L,
-65328L,65329L,65330L,65331L,65332L,65333L,65334L,65335L,65336L,65337L,
-65338L,65339L,65340L,65341L,65342L,65343L,65344L,65313L,65314L,65315L,
-65316L,65317L,65318L,65319L,65320L,65321L,65322L,65323L,65324L,65325L,
-65326L,65327L,65328L,65329L,65330L,65331L,65332L,65333L,65334L,65335L,
-65336L,65337L,65338L,65371L,65372L,65373L,65374L,65375L,65376L,65377L,
-65378L,65379L,65380L,65381L,65382L,65383L,65384L,65385L,65386L,65387L,
-65388L,65389L,65390L,65391L,65392L,65393L,65394L,65395L,65396L,65397L,
-65398L,65399L,65400L,65401L,65402L,65403L,65404L,65405L,65406L,65407L,
-65408L,65409L,65410L,65411L,65412L,65413L,65414L,65415L,65416L,65417L,
-65418L,65419L,65420L,65421L,65422L,65423L,65424L,65425L,65426L,65427L,
-65428L,65429L,65430L,65431L,65432L,65433L,65434L,65435L,65436L,65437L,
-65438L,65439L,65440L,65441L,65442L,65443L,65444L,65445L,65446L,65447L,
-65448L,65449L,65450L,65451L,65452L,65453L,65454L,65455L,65456L,65457L,
-65458L,65459L,65460L,65461L,65462L,65463L,65464L,65465L,65466L,65467L,
-65468L,65469L,65470L,65471L,65472L,65473L,65474L,65475L,65476L,65477L,
-65478L,65479L,65480L,65481L,65482L,65483L,65484L,65485L,65486L,65487L,
-65488L,65489L,65490L,65491L,65492L,65493L,65494L,65495L,65496L,65497L,
-65498L,65499L,65500L,65501L,65502L,65503L,65504L,65505L,65506L,65507L,
-65508L,65509L,65510L,65511L,65512L,65513L,65514L,65515L,65516L,65517L,
-65518L,65519L,65520L,65521L,65522L,65523L,65524L,65525L,65526L,65527L,
-65528L,65529L,65530L,65531L,65532L,65533L,65534L,65535L,
+422,641,42949L,425,644,645,646,42929L,430,580,433,434,581,653,654,655,656,
+657,439,659,660,661,662,663,664,665,666,667,668,42930L,42928L,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,921,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,880,882,882,884,885,886,886,888,889,
+890,1021,1022,1023,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,902,904,905,906,
+944,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,
+931,931,932,933,934,935,936,937,938,939,908,910,911,975,914,920,978,979,
+980,934,928,975,984,984,986,986,988,988,990,990,992,992,994,994,996,996,
+998,998,1000,1000,1002,1002,1004,1004,1006,1006,922,929,1017,895,1012,917,
+1014,1015,1015,1017,1018,1018,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,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,
+1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,
+1039,1120,1120,1122,1122,1124,1124,1126,1126,1128,1128,1130,1130,1132,1132,
+1134,1134,1136,1136,1138,1138,1140,1140,1142,1142,1144,1144,1146,1146,1148,
+1148,1150,1150,1152,1152,1154,1155,1156,1157,1158,1159,1160,1161,1162,1162,
+1164,1164,1166,1166,1168,1168,1170,1170,1172,1172,1174,1174,1176,1176,1178,
+1178,1180,1180,1182,1182,1184,1184,1186,1186,1188,1188,1190,1190,1192,1192,
+1194,1194,1196,1196,1198,1198,1200,1200,1202,1202,1204,1204,1206,1206,1208,
+1208,1210,1210,1212,1212,1214,1214,1216,1217,1217,1219,1219,1221,1221,1223,
+1223,1225,1225,1227,1227,1229,1229,1216,1232,1232,1234,1234,1236,1236,1238,
+1238,1240,1240,1242,1242,1244,1244,1246,1246,1248,1248,1250,1250,1252,1252,
+1254,1254,1256,1256,1258,1258,1260,1260,1262,1262,1264,1264,1266,1266,1268,
+1268,1270,1270,1272,1272,1274,1274,1276,1276,1278,1278,1280,1280,1282,1282,
+1284,1284,1286,1286,1288,1288,1290,1290,1292,1292,1294,1294,1296,1296,1298,
+1298,1300,1300,1302,1302,1304,1304,1306,1306,1308,1308,1310,1310,1312,1312,
+1314,1314,1316,1316,1318,1318,1320,1320,1322,1322,1324,1324,1326,1326,1328,
+1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,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,1365,1366,1367,1368,1369,1370,1371,1372,1373,
+1374,1375,1376,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,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,1365,1366,1415,1416,1417,1418,
+1419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,
+1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,
+1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,
+1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,
+1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,
+1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,
+1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,
+1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,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,1570,1571,1572,1573,1574,1575,1576,1577,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,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,
+1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,
+1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,
+1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,
+1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,
+1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,
+1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,
+1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,
+1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,
+1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,
+1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,
+1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,
+1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,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,1896,1897,1898,
+1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,
+1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,
+1929,1930,1931,1932,1933,1934,1935,1936,1937,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,1973,
+1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,
+1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,
+2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,
+2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,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,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,
+2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,
+2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,
+2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,
+2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,
+2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,
+2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,
+2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,
+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,2224,2225,2226,2227,2228,
+2229,2230,2231,2232,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,2258,
+2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,
+2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,
+2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,
+2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,
+2319,2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,
+2334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,
+2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,
+2364,2365,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,
+2379,2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,
+2394,2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,
+2409,2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,
+2424,2425,2426,2427,2428,2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,
+2439,2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,
+2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,
+2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,
+2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,
+2499,2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,
+2514,2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,
+2529,2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,
+2544,2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,
+2559,2560,2561,2562,2563,2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,
+2574,2575,2576,2577,2578,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,
+2589,2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2601,2602,2603,
+2604,2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,
+2619,2620,2621,2622,2623,2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,
+2634,2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,
+2649,2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,
+2664,2665,2666,2667,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,
+2679,2680,2681,2682,2683,2684,2685,2686,2687,2688,2689,2690,2691,2692,2693,
+2694,2695,2696,2697,2698,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,
+2709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,
+2724,2725,2726,2727,2728,2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,
+2739,2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,
+2754,2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,
+2769,2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,
+2784,2785,2786,2787,2788,2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,
+2799,2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,
+2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,
+2829,2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,
+2844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,
+2859,2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,
+2874,2875,2876,2877,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,
+2889,2890,2891,2892,2893,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,
+2904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,
+2919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,
+2934,2935,2936,2937,2938,2939,2940,2941,2942,2943,2944,2945,2946,2947,2948,
+2949,2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,
+2964,2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,
+2979,2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,
+2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,
+3009,3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,
+3024,3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,
+3039,3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,
+3054,3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,
+3069,3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,
+3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,
+3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,
+3114,3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,
+3129,3130,3131,3132,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,
+3144,3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,
+3159,3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,
+3174,3175,3176,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187,3188,
+3189,3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201,3202,3203,
+3204,3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,
+3219,3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,
+3234,3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,
+3249,3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,
+3264,3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,
+3279,3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,
+3294,3295,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,
+3309,3310,3311,3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,
+3324,3325,3326,3327,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,
+3339,3340,3341,3342,3343,3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,
+3354,3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,
+3369,3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,
+3384,3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,
+3399,3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,
+3414,3415,3416,3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,
+3429,3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,
+3444,3445,3446,3447,3448,3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,
+3459,3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,
+3474,3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,
+3489,3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,
+3504,3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,
+3519,3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,
+3534,3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,
+3549,3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,
+3564,3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,
+3579,3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593,
+3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,
+3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,
+3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,
+3639,3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,
+3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,
+3669,3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,
+3684,3685,3686,3687,3688,3689,3690,3691,3692,3693,3694,3695,3696,3697,3698,
+3699,3700,3701,3702,3703,3704,3705,3706,3707,3708,3709,3710,3711,3712,3713,
+3714,3715,3716,3717,3718,3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,
+3729,3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,
+3744,3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,
+3759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,
+3774,3775,3776,3777,3778,3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,
+3789,3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3802,3803,
+3804,3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,
+3819,3820,3821,3822,3823,3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,
+3834,3835,3836,3837,3838,3839,3840,3841,3842,3843,3844,3845,3846,3847,3848,
+3849,3850,3851,3852,3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,
+3864,3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,
+3879,3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,
+3894,3895,3896,3897,3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,
+3909,3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,
+3924,3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,
+3939,3940,3941,3942,3943,3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,
+3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,
+3969,3970,3971,3972,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,
+3984,3985,3986,3987,3988,3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,
+3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,
+4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,
+4029,4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,
+4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,
+4059,4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,
+4074,4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,
+4089,4090,4091,4092,4093,4094,4095,4096,4097,4098,4099,4100,4101,4102,4103,
+4104,4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,
+4119,4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,
+4134,4135,4136,4137,4138,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,
+4149,4150,4151,4152,4153,4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,
+4164,4165,4166,4167,4168,4169,4170,4171,4172,4173,4174,4175,4176,4177,4178,
+4179,4180,4181,4182,4183,4184,4185,4186,4187,4188,4189,4190,4191,4192,4193,
+4194,4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205,4206,4207,4208,
+4209,4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,
+4224,4225,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4238,
+4239,4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,
+4254,4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,
+4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,
+4284,4285,4286,4287,4288,4289,4290,4291,4292,4293,4294,4295,4296,4297,4298,
+4299,4300,4301,4302,4303,7312,7313,7314,7315,7316,7317,7318,7319,7320,7321,
+7322,7323,7324,7325,7326,7327,7328,7329,7330,7331,7332,7333,7334,7335,7336,
+7337,7338,7339,7340,7341,7342,7343,7344,7345,7346,7347,7348,7349,7350,7351,
+7352,7353,7354,4347,4348,7357,7358,7359,4352,4353,4354,4355,4356,4357,4358,
+4359,4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,
+4374,4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,
+4389,4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,
+4404,4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416,4417,4418,
+4419,4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,
+4434,4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,
+4449,4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,
+4464,4465,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,
+4479,4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,
+4494,4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,
+4509,4510,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,
+4524,4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,
+4539,4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,
+4554,4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,
+4569,4570,4571,4572,4573,4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,
+4584,4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,
+4599,4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,
+4614,4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,
+4629,4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,
+4644,4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,
+4659,4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,
+4674,4675,4676,4677,4678,4679,4680,4681,4682,4683,4684,4685,4686,4687,4688,
+4689,4690,4691,4692,4693,4694,4695,4696,4697,4698,4699,4700,4701,4702,4703,
+4704,4705,4706,4707,4708,4709,4710,4711,4712,4713,4714,4715,4716,4717,4718,
+4719,4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,
+4734,4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4745,4746,4747,4748,
+4749,4750,4751,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,
+4764,4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,
+4779,4780,4781,4782,4783,4784,4785,4786,4787,4788,4789,4790,4791,4792,4793,
+4794,4795,4796,4797,4798,4799,4800,4801,4802,4803,4804,4805,4806,4807,4808,
+4809,4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4823,
+4824,4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,
+4839,4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,
+4854,4855,4856,4857,4858,4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,
+4869,4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4881,4882,4883,
+4884,4885,4886,4887,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,
+4899,4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,
+4914,4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,
+4929,4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,
+4944,4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4955,4956,4957,4958,
+4959,4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970,4971,4972,4973,
+4974,4975,4976,4977,4978,4979,4980,4981,4982,4983,4984,4985,4986,4987,4988,
+4989,4990,4991,4992,4993,4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,
+5004,5005,5006,5007,5008,5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,
+5019,5020,5021,5022,5023,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,
+5034,5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,
+5049,5050,5051,5052,5053,5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,
+5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,
+5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,
+5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,
+5109,5110,5111,5104,5105,5106,5107,5108,5109,5118,5119,5120,5121,5122,5123,
+5124,5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,
+5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,
+5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,
+5169,5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,
+5184,5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,
+5199,5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,
+5214,5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,
+5229,5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,
+5244,5245,5246,5247,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,
+5259,5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,
+5274,5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,
+5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,
+5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,
+5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,
+5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,
+5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,
+5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,
+5379,5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,
+5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,
+5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,
+5424,5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,
+5439,5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,
+5454,5455,5456,5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,
+5469,5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,
+5484,5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,
+5499,5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,
+5514,5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,
+5529,5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,
+5544,5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,
+5559,5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570,5571,5572,5573,
+5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585,5586,5587,5588,
+5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600,5601,5602,5603,
+5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616,5617,5618,
+5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632,5633,
+5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648,
+5649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,
+5664,5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,
+5679,5680,5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,
+5694,5695,5696,5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,
+5709,5710,5711,5712,5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,
+5724,5725,5726,5727,5728,5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,
+5739,5740,5741,5742,5743,5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,
+5754,5755,5756,5757,5758,5759,5760,5761,5762,5763,5764,5765,5766,5767,5768,
+5769,5770,5771,5772,5773,5774,5775,5776,5777,5778,5779,5780,5781,5782,5783,
+5784,5785,5786,5787,5788,5789,5790,5791,5792,5793,5794,5795,5796,5797,5798,
+5799,5800,5801,5802,5803,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,
+5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,
+5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,
+5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,
+5859,5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872,5873,
+5874,5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888,
+5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,
+5904,5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,
+5919,5920,5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,
+5934,5935,5936,5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,
+5949,5950,5951,5952,5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,
+5964,5965,5966,5967,5968,5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,
+5979,5980,5981,5982,5983,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,
+5994,5995,5996,5997,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6008,
+6009,6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020,6021,6022,6023,
+6024,6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,
+6039,6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,
+6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068,
+6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,
+6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,
+6099,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,
+6114,6115,6116,6117,6118,6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,
+6129,6130,6131,6132,6133,6134,6135,6136,6137,6138,6139,6140,6141,6142,6143,
+6144,6145,6146,6147,6148,6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,
+6159,6160,6161,6162,6163,6164,6165,6166,6167,6168,6169,6170,6171,6172,6173,
+6174,6175,6176,6177,6178,6179,6180,6181,6182,6183,6184,6185,6186,6187,6188,
+6189,6190,6191,6192,6193,6194,6195,6196,6197,6198,6199,6200,6201,6202,6203,
+6204,6205,6206,6207,6208,6209,6210,6211,6212,6213,6214,6215,6216,6217,6218,
+6219,6220,6221,6222,6223,6224,6225,6226,6227,6228,6229,6230,6231,6232,6233,
+6234,6235,6236,6237,6238,6239,6240,6241,6242,6243,6244,6245,6246,6247,6248,
+6249,6250,6251,6252,6253,6254,6255,6256,6257,6258,6259,6260,6261,6262,6263,
+6264,6265,6266,6267,6268,6269,6270,6271,6272,6273,6274,6275,6276,6277,6278,
+6279,6280,6281,6282,6283,6284,6285,6286,6287,6288,6289,6290,6291,6292,6293,
+6294,6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305,6306,6307,6308,
+6309,6310,6311,6312,6313,6314,6315,6316,6317,6318,6319,6320,6321,6322,6323,
+6324,6325,6326,6327,6328,6329,6330,6331,6332,6333,6334,6335,6336,6337,6338,
+6339,6340,6341,6342,6343,6344,6345,6346,6347,6348,6349,6350,6351,6352,6353,
+6354,6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365,6366,6367,6368,
+6369,6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381,6382,6383,
+6384,6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395,6396,6397,6398,
+6399,6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,
+6414,6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,6426,6427,6428,
+6429,6430,6431,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,
+6444,6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,
+6459,6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472,6473,
+6474,6475,6476,6477,6478,6479,6480,6481,6482,6483,6484,6485,6486,6487,6488,
+6489,6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,
+6504,6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516,6517,6518,
+6519,6520,6521,6522,6523,6524,6525,6526,6527,6528,6529,6530,6531,6532,6533,
+6534,6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,
+6549,6550,6551,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,
+6564,6565,6566,6567,6568,6569,6570,6571,6572,6573,6574,6575,6576,6577,6578,
+6579,6580,6581,6582,6583,6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,
+6594,6595,6596,6597,6598,6599,6600,6601,6602,6603,6604,6605,6606,6607,6608,
+6609,6610,6611,6612,6613,6614,6615,6616,6617,6618,6619,6620,6621,6622,6623,
+6624,6625,6626,6627,6628,6629,6630,6631,6632,6633,6634,6635,6636,6637,6638,
+6639,6640,6641,6642,6643,6644,6645,6646,6647,6648,6649,6650,6651,6652,6653,
+6654,6655,6656,6657,6658,6659,6660,6661,6662,6663,6664,6665,6666,6667,6668,
+6669,6670,6671,6672,6673,6674,6675,6676,6677,6678,6679,6680,6681,6682,6683,
+6684,6685,6686,6687,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,6698,
+6699,6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,
+6714,6715,6716,6717,6718,6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,
+6729,6730,6731,6732,6733,6734,6735,6736,6737,6738,6739,6740,6741,6742,6743,
+6744,6745,6746,6747,6748,6749,6750,6751,6752,6753,6754,6755,6756,6757,6758,
+6759,6760,6761,6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,
+6774,6775,6776,6777,6778,6779,6780,6781,6782,6783,6784,6785,6786,6787,6788,
+6789,6790,6791,6792,6793,6794,6795,6796,6797,6798,6799,6800,6801,6802,6803,
+6804,6805,6806,6807,6808,6809,6810,6811,6812,6813,6814,6815,6816,6817,6818,
+6819,6820,6821,6822,6823,6824,6825,6826,6827,6828,6829,6830,6831,6832,6833,
+6834,6835,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,6847,6848,
+6849,6850,6851,6852,6853,6854,6855,6856,6857,6858,6859,6860,6861,6862,6863,
+6864,6865,6866,6867,6868,6869,6870,6871,6872,6873,6874,6875,6876,6877,6878,
+6879,6880,6881,6882,6883,6884,6885,6886,6887,6888,6889,6890,6891,6892,6893,
+6894,6895,6896,6897,6898,6899,6900,6901,6902,6903,6904,6905,6906,6907,6908,
+6909,6910,6911,6912,6913,6914,6915,6916,6917,6918,6919,6920,6921,6922,6923,
+6924,6925,6926,6927,6928,6929,6930,6931,6932,6933,6934,6935,6936,6937,6938,
+6939,6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,
+6954,6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966,6967,6968,
+6969,6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,6981,6982,6983,
+6984,6985,6986,6987,6988,6989,6990,6991,6992,6993,6994,6995,6996,6997,6998,
+6999,7000,7001,7002,7003,7004,7005,7006,7007,7008,7009,7010,7011,7012,7013,
+7014,7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027,7028,
+7029,7030,7031,7032,7033,7034,7035,7036,7037,7038,7039,7040,7041,7042,7043,
+7044,7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,
+7059,7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,7071,7072,7073,
+7074,7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7086,7087,7088,
+7089,7090,7091,7092,7093,7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,
+7104,7105,7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,
+7119,7120,7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,
+7134,7135,7136,7137,7138,7139,7140,7141,7142,7143,7144,7145,7146,7147,7148,
+7149,7150,7151,7152,7153,7154,7155,7156,7157,7158,7159,7160,7161,7162,7163,
+7164,7165,7166,7167,7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,
+7179,7180,7181,7182,7183,7184,7185,7186,7187,7188,7189,7190,7191,7192,7193,
+7194,7195,7196,7197,7198,7199,7200,7201,7202,7203,7204,7205,7206,7207,7208,
+7209,7210,7211,7212,7213,7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,
+7224,7225,7226,7227,7228,7229,7230,7231,7232,7233,7234,7235,7236,7237,7238,
+7239,7240,7241,7242,7243,7244,7245,7246,7247,7248,7249,7250,7251,7252,7253,
+7254,7255,7256,7257,7258,7259,7260,7261,7262,7263,7264,7265,7266,7267,7268,
+7269,7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280,7281,7282,7283,
+7284,7285,7286,7287,7288,7289,7290,7291,7292,7293,7294,7295,1042,1044,1054,
+1057,1058,1058,1066,1122,42570L,7305,7306,7307,7308,7309,7310,7311,7312,
+7313,7314,7315,7316,7317,7318,7319,7320,7321,7322,7323,7324,7325,7326,7327,
+7328,7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339,7340,7341,7342,
+7343,7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,7354,7355,7356,7357,
+7358,7359,7360,7361,7362,7363,7364,7365,7366,7367,7368,7369,7370,7371,7372,
+7373,7374,7375,7376,7377,7378,7379,7380,7381,7382,7383,7384,7385,7386,7387,
+7388,7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400,7401,7402,
+7403,7404,7405,7406,7407,7408,7409,7410,7411,7412,7413,7414,7415,7416,7417,
+7418,7419,7420,7421,7422,7423,7424,7425,7426,7427,7428,7429,7430,7431,7432,
+7433,7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447,
+7448,7449,7450,7451,7452,7453,7454,7455,7456,7457,7458,7459,7460,7461,7462,
+7463,7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,7475,7476,7477,
+7478,7479,7480,7481,7482,7483,7484,7485,7486,7487,7488,7489,7490,7491,7492,
+7493,7494,7495,7496,7497,7498,7499,7500,7501,7502,7503,7504,7505,7506,7507,
+7508,7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,7522,
+7523,7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537,
+7538,7539,7540,7541,7542,7543,7544,42877L,7546,7547,7548,11363,7550,7551,
+7552,7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,
+42950L,7567,7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,
+7580,7581,7582,7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,
+7595,7596,7597,7598,7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,
+7610,7611,7612,7613,7614,7615,7616,7617,7618,7619,7620,7621,7622,7623,7624,
+7625,7626,7627,7628,7629,7630,7631,7632,7633,7634,7635,7636,7637,7638,7639,
+7640,7641,7642,7643,7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,
+7655,7656,7657,7658,7659,7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,
+7670,7671,7672,7673,7674,7675,7676,7677,7678,7679,7680,7680,7682,7682,7684,
+7684,7686,7686,7688,7688,7690,7690,7692,7692,7694,7694,7696,7696,7698,7698,
+7700,7700,7702,7702,7704,7704,7706,7706,7708,7708,7710,7710,7712,7712,7714,
+7714,7716,7716,7718,7718,7720,7720,7722,7722,7724,7724,7726,7726,7728,7728,
+7730,7730,7732,7732,7734,7734,7736,7736,7738,7738,7740,7740,7742,7742,7744,
+7744,7746,7746,7748,7748,7750,7750,7752,7752,7754,7754,7756,7756,7758,7758,
+7760,7760,7762,7762,7764,7764,7766,7766,7768,7768,7770,7770,7772,7772,7774,
+7774,7776,7776,7778,7778,7780,7780,7782,7782,7784,7784,7786,7786,7788,7788,
+7790,7790,7792,7792,7794,7794,7796,7796,7798,7798,7800,7800,7802,7802,7804,
+7804,7806,7806,7808,7808,7810,7810,7812,7812,7814,7814,7816,7816,7818,7818,
+7820,7820,7822,7822,7824,7824,7826,7826,7828,7828,7830,7831,7832,7833,7834,
+7776,7836,7837,7838,7839,7840,7840,7842,7842,7844,7844,7846,7846,7848,7848,
+7850,7850,7852,7852,7854,7854,7856,7856,7858,7858,7860,7860,7862,7862,7864,
+7864,7866,7866,7868,7868,7870,7870,7872,7872,7874,7874,7876,7876,7878,7878,
+7880,7880,7882,7882,7884,7884,7886,7886,7888,7888,7890,7890,7892,7892,7894,
+7894,7896,7896,7898,7898,7900,7900,7902,7902,7904,7904,7906,7906,7908,7908,
+7910,7910,7912,7912,7914,7914,7916,7916,7918,7918,7920,7920,7922,7922,7924,
+7924,7926,7926,7928,7928,7930,7930,7932,7932,7934,7934,7944,7945,7946,7947,
+7948,7949,7950,7951,7944,7945,7946,7947,7948,7949,7950,7951,7960,7961,7962,
+7963,7964,7965,7958,7959,7960,7961,7962,7963,7964,7965,7966,7967,7976,7977,
+7978,7979,7980,7981,7982,7983,7976,7977,7978,7979,7980,7981,7982,7983,7992,
+7993,7994,7995,7996,7997,7998,7999,7992,7993,7994,7995,7996,7997,7998,7999,
+8008,8009,8010,8011,8012,8013,8006,8007,8008,8009,8010,8011,8012,8013,8014,
+8015,8016,8025,8018,8027,8020,8029,8022,8031,8024,8025,8026,8027,8028,8029,
+8030,8031,8040,8041,8042,8043,8044,8045,8046,8047,8040,8041,8042,8043,8044,
+8045,8046,8047,8122,8123,8136,8137,8138,8139,8154,8155,8184,8185,8170,8171,
+8186,8187,8062,8063,8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,
+8075,8076,8077,8078,8079,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,
+8090,8091,8092,8093,8094,8095,8096,8097,8098,8099,8100,8101,8102,8103,8104,
+8105,8106,8107,8108,8109,8110,8111,8120,8121,8114,8115,8116,8117,8118,8119,
+8120,8121,8122,8123,8124,8125,921,8127,8128,8129,8130,8131,8132,8133,8134,
+8135,8136,8137,8138,8139,8140,8141,8142,8143,8152,8153,8146,8147,8148,8149,
+8150,8151,8152,8153,8154,8155,8156,8157,8158,8159,8168,8169,8162,8163,8164,
+8172,8166,8167,8168,8169,8170,8171,8172,8173,8174,8175,8176,8177,8178,8179,
+8180,8181,8182,8183,8184,8185,8186,8187,8188,8189,8190,8191,8192,8193,8194,
+8195,8196,8197,8198,8199,8200,8201,8202,8203,8204,8205,8206,8207,8208,8209,
+8210,8211,8212,8213,8214,8215,8216,8217,8218,8219,8220,8221,8222,8223,8224,
+8225,8226,8227,8228,8229,8230,8231,8232,8233,8234,8235,8236,8237,8238,8239,
+8240,8241,8242,8243,8244,8245,8246,8247,8248,8249,8250,8251,8252,8253,8254,
+8255,8256,8257,8258,8259,8260,8261,8262,8263,8264,8265,8266,8267,8268,8269,
+8270,8271,8272,8273,8274,8275,8276,8277,8278,8279,8280,8281,8282,8283,8284,
+8285,8286,8287,8288,8289,8290,8291,8292,8293,8294,8295,8296,8297,8298,8299,
+8300,8301,8302,8303,8304,8305,8306,8307,8308,8309,8310,8311,8312,8313,8314,
+8315,8316,8317,8318,8319,8320,8321,8322,8323,8324,8325,8326,8327,8328,8329,
+8330,8331,8332,8333,8334,8335,8336,8337,8338,8339,8340,8341,8342,8343,8344,
+8345,8346,8347,8348,8349,8350,8351,8352,8353,8354,8355,8356,8357,8358,8359,
+8360,8361,8362,8363,8364,8365,8366,8367,8368,8369,8370,8371,8372,8373,8374,
+8375,8376,8377,8378,8379,8380,8381,8382,8383,8384,8385,8386,8387,8388,8389,
+8390,8391,8392,8393,8394,8395,8396,8397,8398,8399,8400,8401,8402,8403,8404,
+8405,8406,8407,8408,8409,8410,8411,8412,8413,8414,8415,8416,8417,8418,8419,
+8420,8421,8422,8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,8433,8434,
+8435,8436,8437,8438,8439,8440,8441,8442,8443,8444,8445,8446,8447,8448,8449,
+8450,8451,8452,8453,8454,8455,8456,8457,8458,8459,8460,8461,8462,8463,8464,
+8465,8466,8467,8468,8469,8470,8471,8472,8473,8474,8475,8476,8477,8478,8479,
+8480,8481,8482,8483,8484,8485,8486,8487,8488,8489,8490,8491,8492,8493,8494,
+8495,8496,8497,8498,8499,8500,8501,8502,8503,8504,8505,8506,8507,8508,8509,
+8510,8511,8512,8513,8514,8515,8516,8517,8518,8519,8520,8521,8522,8523,8524,
+8525,8498,8527,8528,8529,8530,8531,8532,8533,8534,8535,8536,8537,8538,8539,
+8540,8541,8542,8543,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,
+8555,8556,8557,8558,8559,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,
+8554,8555,8556,8557,8558,8559,8576,8577,8578,8579,8579,8581,8582,8583,8584,
+8585,8586,8587,8588,8589,8590,8591,8592,8593,8594,8595,8596,8597,8598,8599,
+8600,8601,8602,8603,8604,8605,8606,8607,8608,8609,8610,8611,8612,8613,8614,
+8615,8616,8617,8618,8619,8620,8621,8622,8623,8624,8625,8626,8627,8628,8629,
+8630,8631,8632,8633,8634,8635,8636,8637,8638,8639,8640,8641,8642,8643,8644,
+8645,8646,8647,8648,8649,8650,8651,8652,8653,8654,8655,8656,8657,8658,8659,
+8660,8661,8662,8663,8664,8665,8666,8667,8668,8669,8670,8671,8672,8673,8674,
+8675,8676,8677,8678,8679,8680,8681,8682,8683,8684,8685,8686,8687,8688,8689,
+8690,8691,8692,8693,8694,8695,8696,8697,8698,8699,8700,8701,8702,8703,8704,
+8705,8706,8707,8708,8709,8710,8711,8712,8713,8714,8715,8716,8717,8718,8719,
+8720,8721,8722,8723,8724,8725,8726,8727,8728,8729,8730,8731,8732,8733,8734,
+8735,8736,8737,8738,8739,8740,8741,8742,8743,8744,8745,8746,8747,8748,8749,
+8750,8751,8752,8753,8754,8755,8756,8757,8758,8759,8760,8761,8762,8763,8764,
+8765,8766,8767,8768,8769,8770,8771,8772,8773,8774,8775,8776,8777,8778,8779,
+8780,8781,8782,8783,8784,8785,8786,8787,8788,8789,8790,8791,8792,8793,8794,
+8795,8796,8797,8798,8799,8800,8801,8802,8803,8804,8805,8806,8807,8808,8809,
+8810,8811,8812,8813,8814,8815,8816,8817,8818,8819,8820,8821,8822,8823,8824,
+8825,8826,8827,8828,8829,8830,8831,8832,8833,8834,8835,8836,8837,8838,8839,
+8840,8841,8842,8843,8844,8845,8846,8847,8848,8849,8850,8851,8852,8853,8854,
+8855,8856,8857,8858,8859,8860,8861,8862,8863,8864,8865,8866,8867,8868,8869,
+8870,8871,8872,8873,8874,8875,8876,8877,8878,8879,8880,8881,8882,8883,8884,
+8885,8886,8887,8888,8889,8890,8891,8892,8893,8894,8895,8896,8897,8898,8899,
+8900,8901,8902,8903,8904,8905,8906,8907,8908,8909,8910,8911,8912,8913,8914,
+8915,8916,8917,8918,8919,8920,8921,8922,8923,8924,8925,8926,8927,8928,8929,
+8930,8931,8932,8933,8934,8935,8936,8937,8938,8939,8940,8941,8942,8943,8944,
+8945,8946,8947,8948,8949,8950,8951,8952,8953,8954,8955,8956,8957,8958,8959,
+8960,8961,8962,8963,8964,8965,8966,8967,8968,8969,8970,8971,8972,8973,8974,
+8975,8976,8977,8978,8979,8980,8981,8982,8983,8984,8985,8986,8987,8988,8989,
+8990,8991,8992,8993,8994,8995,8996,8997,8998,8999,9000,9001,9002,9003,9004,
+9005,9006,9007,9008,9009,9010,9011,9012,9013,9014,9015,9016,9017,9018,9019,
+9020,9021,9022,9023,9024,9025,9026,9027,9028,9029,9030,9031,9032,9033,9034,
+9035,9036,9037,9038,9039,9040,9041,9042,9043,9044,9045,9046,9047,9048,9049,
+9050,9051,9052,9053,9054,9055,9056,9057,9058,9059,9060,9061,9062,9063,9064,
+9065,9066,9067,9068,9069,9070,9071,9072,9073,9074,9075,9076,9077,9078,9079,
+9080,9081,9082,9083,9084,9085,9086,9087,9088,9089,9090,9091,9092,9093,9094,
+9095,9096,9097,9098,9099,9100,9101,9102,9103,9104,9105,9106,9107,9108,9109,
+9110,9111,9112,9113,9114,9115,9116,9117,9118,9119,9120,9121,9122,9123,9124,
+9125,9126,9127,9128,9129,9130,9131,9132,9133,9134,9135,9136,9137,9138,9139,
+9140,9141,9142,9143,9144,9145,9146,9147,9148,9149,9150,9151,9152,9153,9154,
+9155,9156,9157,9158,9159,9160,9161,9162,9163,9164,9165,9166,9167,9168,9169,
+9170,9171,9172,9173,9174,9175,9176,9177,9178,9179,9180,9181,9182,9183,9184,
+9185,9186,9187,9188,9189,9190,9191,9192,9193,9194,9195,9196,9197,9198,9199,
+9200,9201,9202,9203,9204,9205,9206,9207,9208,9209,9210,9211,9212,9213,9214,
+9215,9216,9217,9218,9219,9220,9221,9222,9223,9224,9225,9226,9227,9228,9229,
+9230,9231,9232,9233,9234,9235,9236,9237,9238,9239,9240,9241,9242,9243,9244,
+9245,9246,9247,9248,9249,9250,9251,9252,9253,9254,9255,9256,9257,9258,9259,
+9260,9261,9262,9263,9264,9265,9266,9267,9268,9269,9270,9271,9272,9273,9274,
+9275,9276,9277,9278,9279,9280,9281,9282,9283,9284,9285,9286,9287,9288,9289,
+9290,9291,9292,9293,9294,9295,9296,9297,9298,9299,9300,9301,9302,9303,9304,
+9305,9306,9307,9308,9309,9310,9311,9312,9313,9314,9315,9316,9317,9318,9319,
+9320,9321,9322,9323,9324,9325,9326,9327,9328,9329,9330,9331,9332,9333,9334,
+9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345,9346,9347,9348,9349,
+9350,9351,9352,9353,9354,9355,9356,9357,9358,9359,9360,9361,9362,9363,9364,
+9365,9366,9367,9368,9369,9370,9371,9372,9373,9374,9375,9376,9377,9378,9379,
+9380,9381,9382,9383,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,
+9395,9396,9397,9398,9399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,
+9410,9411,9412,9413,9414,9415,9416,9417,9418,9419,9420,9421,9422,9423,9398,
+9399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,9413,
+9414,9415,9416,9417,9418,9419,9420,9421,9422,9423,9450,9451,9452,9453,9454,
+9455,9456,9457,9458,9459,9460,9461,9462,9463,9464,9465,9466,9467,9468,9469,
+9470,9471,9472,9473,9474,9475,9476,9477,9478,9479,9480,9481,9482,9483,9484,
+9485,9486,9487,9488,9489,9490,9491,9492,9493,9494,9495,9496,9497,9498,9499,
+9500,9501,9502,9503,9504,9505,9506,9507,9508,9509,9510,9511,9512,9513,9514,
+9515,9516,9517,9518,9519,9520,9521,9522,9523,9524,9525,9526,9527,9528,9529,
+9530,9531,9532,9533,9534,9535,9536,9537,9538,9539,9540,9541,9542,9543,9544,
+9545,9546,9547,9548,9549,9550,9551,9552,9553,9554,9555,9556,9557,9558,9559,
+9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,9570,9571,9572,9573,9574,
+9575,9576,9577,9578,9579,9580,9581,9582,9583,9584,9585,9586,9587,9588,9589,
+9590,9591,9592,9593,9594,9595,9596,9597,9598,9599,9600,9601,9602,9603,9604,
+9605,9606,9607,9608,9609,9610,9611,9612,9613,9614,9615,9616,9617,9618,9619,
+9620,9621,9622,9623,9624,9625,9626,9627,9628,9629,9630,9631,9632,9633,9634,
+9635,9636,9637,9638,9639,9640,9641,9642,9643,9644,9645,9646,9647,9648,9649,
+9650,9651,9652,9653,9654,9655,9656,9657,9658,9659,9660,9661,9662,9663,9664,
+9665,9666,9667,9668,9669,9670,9671,9672,9673,9674,9675,9676,9677,9678,9679,
+9680,9681,9682,9683,9684,9685,9686,9687,9688,9689,9690,9691,9692,9693,9694,
+9695,9696,9697,9698,9699,9700,9701,9702,9703,9704,9705,9706,9707,9708,9709,
+9710,9711,9712,9713,9714,9715,9716,9717,9718,9719,9720,9721,9722,9723,9724,
+9725,9726,9727,9728,9729,9730,9731,9732,9733,9734,9735,9736,9737,9738,9739,
+9740,9741,9742,9743,9744,9745,9746,9747,9748,9749,9750,9751,9752,9753,9754,
+9755,9756,9757,9758,9759,9760,9761,9762,9763,9764,9765,9766,9767,9768,9769,
+9770,9771,9772,9773,9774,9775,9776,9777,9778,9779,9780,9781,9782,9783,9784,
+9785,9786,9787,9788,9789,9790,9791,9792,9793,9794,9795,9796,9797,9798,9799,
+9800,9801,9802,9803,9804,9805,9806,9807,9808,9809,9810,9811,9812,9813,9814,
+9815,9816,9817,9818,9819,9820,9821,9822,9823,9824,9825,9826,9827,9828,9829,
+9830,9831,9832,9833,9834,9835,9836,9837,9838,9839,9840,9841,9842,9843,9844,
+9845,9846,9847,9848,9849,9850,9851,9852,9853,9854,9855,9856,9857,9858,9859,
+9860,9861,9862,9863,9864,9865,9866,9867,9868,9869,9870,9871,9872,9873,9874,
+9875,9876,9877,9878,9879,9880,9881,9882,9883,9884,9885,9886,9887,9888,9889,
+9890,9891,9892,9893,9894,9895,9896,9897,9898,9899,9900,9901,9902,9903,9904,
+9905,9906,9907,9908,9909,9910,9911,9912,9913,9914,9915,9916,9917,9918,9919,
+9920,9921,9922,9923,9924,9925,9926,9927,9928,9929,9930,9931,9932,9933,9934,
+9935,9936,9937,9938,9939,9940,9941,9942,9943,9944,9945,9946,9947,9948,9949,
+9950,9951,9952,9953,9954,9955,9956,9957,9958,9959,9960,9961,9962,9963,9964,
+9965,9966,9967,9968,9969,9970,9971,9972,9973,9974,9975,9976,9977,9978,9979,
+9980,9981,9982,9983,9984,9985,9986,9987,9988,9989,9990,9991,9992,9993,9994,
+9995,9996,9997,9998,9999,10000,10001,10002,10003,10004,10005,10006,10007,
+10008,10009,10010,10011,10012,10013,10014,10015,10016,10017,10018,10019,
+10020,10021,10022,10023,10024,10025,10026,10027,10028,10029,10030,10031,
+10032,10033,10034,10035,10036,10037,10038,10039,10040,10041,10042,10043,
+10044,10045,10046,10047,10048,10049,10050,10051,10052,10053,10054,10055,
+10056,10057,10058,10059,10060,10061,10062,10063,10064,10065,10066,10067,
+10068,10069,10070,10071,10072,10073,10074,10075,10076,10077,10078,10079,
+10080,10081,10082,10083,10084,10085,10086,10087,10088,10089,10090,10091,
+10092,10093,10094,10095,10096,10097,10098,10099,10100,10101,10102,10103,
+10104,10105,10106,10107,10108,10109,10110,10111,10112,10113,10114,10115,
+10116,10117,10118,10119,10120,10121,10122,10123,10124,10125,10126,10127,
+10128,10129,10130,10131,10132,10133,10134,10135,10136,10137,10138,10139,
+10140,10141,10142,10143,10144,10145,10146,10147,10148,10149,10150,10151,
+10152,10153,10154,10155,10156,10157,10158,10159,10160,10161,10162,10163,
+10164,10165,10166,10167,10168,10169,10170,10171,10172,10173,10174,10175,
+10176,10177,10178,10179,10180,10181,10182,10183,10184,10185,10186,10187,
+10188,10189,10190,10191,10192,10193,10194,10195,10196,10197,10198,10199,
+10200,10201,10202,10203,10204,10205,10206,10207,10208,10209,10210,10211,
+10212,10213,10214,10215,10216,10217,10218,10219,10220,10221,10222,10223,
+10224,10225,10226,10227,10228,10229,10230,10231,10232,10233,10234,10235,
+10236,10237,10238,10239,10240,10241,10242,10243,10244,10245,10246,10247,
+10248,10249,10250,10251,10252,10253,10254,10255,10256,10257,10258,10259,
+10260,10261,10262,10263,10264,10265,10266,10267,10268,10269,10270,10271,
+10272,10273,10274,10275,10276,10277,10278,10279,10280,10281,10282,10283,
+10284,10285,10286,10287,10288,10289,10290,10291,10292,10293,10294,10295,
+10296,10297,10298,10299,10300,10301,10302,10303,10304,10305,10306,10307,
+10308,10309,10310,10311,10312,10313,10314,10315,10316,10317,10318,10319,
+10320,10321,10322,10323,10324,10325,10326,10327,10328,10329,10330,10331,
+10332,10333,10334,10335,10336,10337,10338,10339,10340,10341,10342,10343,
+10344,10345,10346,10347,10348,10349,10350,10351,10352,10353,10354,10355,
+10356,10357,10358,10359,10360,10361,10362,10363,10364,10365,10366,10367,
+10368,10369,10370,10371,10372,10373,10374,10375,10376,10377,10378,10379,
+10380,10381,10382,10383,10384,10385,10386,10387,10388,10389,10390,10391,
+10392,10393,10394,10395,10396,10397,10398,10399,10400,10401,10402,10403,
+10404,10405,10406,10407,10408,10409,10410,10411,10412,10413,10414,10415,
+10416,10417,10418,10419,10420,10421,10422,10423,10424,10425,10426,10427,
+10428,10429,10430,10431,10432,10433,10434,10435,10436,10437,10438,10439,
+10440,10441,10442,10443,10444,10445,10446,10447,10448,10449,10450,10451,
+10452,10453,10454,10455,10456,10457,10458,10459,10460,10461,10462,10463,
+10464,10465,10466,10467,10468,10469,10470,10471,10472,10473,10474,10475,
+10476,10477,10478,10479,10480,10481,10482,10483,10484,10485,10486,10487,
+10488,10489,10490,10491,10492,10493,10494,10495,10496,10497,10498,10499,
+10500,10501,10502,10503,10504,10505,10506,10507,10508,10509,10510,10511,
+10512,10513,10514,10515,10516,10517,10518,10519,10520,10521,10522,10523,
+10524,10525,10526,10527,10528,10529,10530,10531,10532,10533,10534,10535,
+10536,10537,10538,10539,10540,10541,10542,10543,10544,10545,10546,10547,
+10548,10549,10550,10551,10552,10553,10554,10555,10556,10557,10558,10559,
+10560,10561,10562,10563,10564,10565,10566,10567,10568,10569,10570,10571,
+10572,10573,10574,10575,10576,10577,10578,10579,10580,10581,10582,10583,
+10584,10585,10586,10587,10588,10589,10590,10591,10592,10593,10594,10595,
+10596,10597,10598,10599,10600,10601,10602,10603,10604,10605,10606,10607,
+10608,10609,10610,10611,10612,10613,10614,10615,10616,10617,10618,10619,
+10620,10621,10622,10623,10624,10625,10626,10627,10628,10629,10630,10631,
+10632,10633,10634,10635,10636,10637,10638,10639,10640,10641,10642,10643,
+10644,10645,10646,10647,10648,10649,10650,10651,10652,10653,10654,10655,
+10656,10657,10658,10659,10660,10661,10662,10663,10664,10665,10666,10667,
+10668,10669,10670,10671,10672,10673,10674,10675,10676,10677,10678,10679,
+10680,10681,10682,10683,10684,10685,10686,10687,10688,10689,10690,10691,
+10692,10693,10694,10695,10696,10697,10698,10699,10700,10701,10702,10703,
+10704,10705,10706,10707,10708,10709,10710,10711,10712,10713,10714,10715,
+10716,10717,10718,10719,10720,10721,10722,10723,10724,10725,10726,10727,
+10728,10729,10730,10731,10732,10733,10734,10735,10736,10737,10738,10739,
+10740,10741,10742,10743,10744,10745,10746,10747,10748,10749,10750,10751,
+10752,10753,10754,10755,10756,10757,10758,10759,10760,10761,10762,10763,
+10764,10765,10766,10767,10768,10769,10770,10771,10772,10773,10774,10775,
+10776,10777,10778,10779,10780,10781,10782,10783,10784,10785,10786,10787,
+10788,10789,10790,10791,10792,10793,10794,10795,10796,10797,10798,10799,
+10800,10801,10802,10803,10804,10805,10806,10807,10808,10809,10810,10811,
+10812,10813,10814,10815,10816,10817,10818,10819,10820,10821,10822,10823,
+10824,10825,10826,10827,10828,10829,10830,10831,10832,10833,10834,10835,
+10836,10837,10838,10839,10840,10841,10842,10843,10844,10845,10846,10847,
+10848,10849,10850,10851,10852,10853,10854,10855,10856,10857,10858,10859,
+10860,10861,10862,10863,10864,10865,10866,10867,10868,10869,10870,10871,
+10872,10873,10874,10875,10876,10877,10878,10879,10880,10881,10882,10883,
+10884,10885,10886,10887,10888,10889,10890,10891,10892,10893,10894,10895,
+10896,10897,10898,10899,10900,10901,10902,10903,10904,10905,10906,10907,
+10908,10909,10910,10911,10912,10913,10914,10915,10916,10917,10918,10919,
+10920,10921,10922,10923,10924,10925,10926,10927,10928,10929,10930,10931,
+10932,10933,10934,10935,10936,10937,10938,10939,10940,10941,10942,10943,
+10944,10945,10946,10947,10948,10949,10950,10951,10952,10953,10954,10955,
+10956,10957,10958,10959,10960,10961,10962,10963,10964,10965,10966,10967,
+10968,10969,10970,10971,10972,10973,10974,10975,10976,10977,10978,10979,
+10980,10981,10982,10983,10984,10985,10986,10987,10988,10989,10990,10991,
+10992,10993,10994,10995,10996,10997,10998,10999,11000,11001,11002,11003,
+11004,11005,11006,11007,11008,11009,11010,11011,11012,11013,11014,11015,
+11016,11017,11018,11019,11020,11021,11022,11023,11024,11025,11026,11027,
+11028,11029,11030,11031,11032,11033,11034,11035,11036,11037,11038,11039,
+11040,11041,11042,11043,11044,11045,11046,11047,11048,11049,11050,11051,
+11052,11053,11054,11055,11056,11057,11058,11059,11060,11061,11062,11063,
+11064,11065,11066,11067,11068,11069,11070,11071,11072,11073,11074,11075,
+11076,11077,11078,11079,11080,11081,11082,11083,11084,11085,11086,11087,
+11088,11089,11090,11091,11092,11093,11094,11095,11096,11097,11098,11099,
+11100,11101,11102,11103,11104,11105,11106,11107,11108,11109,11110,11111,
+11112,11113,11114,11115,11116,11117,11118,11119,11120,11121,11122,11123,
+11124,11125,11126,11127,11128,11129,11130,11131,11132,11133,11134,11135,
+11136,11137,11138,11139,11140,11141,11142,11143,11144,11145,11146,11147,
+11148,11149,11150,11151,11152,11153,11154,11155,11156,11157,11158,11159,
+11160,11161,11162,11163,11164,11165,11166,11167,11168,11169,11170,11171,
+11172,11173,11174,11175,11176,11177,11178,11179,11180,11181,11182,11183,
+11184,11185,11186,11187,11188,11189,11190,11191,11192,11193,11194,11195,
+11196,11197,11198,11199,11200,11201,11202,11203,11204,11205,11206,11207,
+11208,11209,11210,11211,11212,11213,11214,11215,11216,11217,11218,11219,
+11220,11221,11222,11223,11224,11225,11226,11227,11228,11229,11230,11231,
+11232,11233,11234,11235,11236,11237,11238,11239,11240,11241,11242,11243,
+11244,11245,11246,11247,11248,11249,11250,11251,11252,11253,11254,11255,
+11256,11257,11258,11259,11260,11261,11262,11263,11264,11265,11266,11267,
+11268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,
+11280,11281,11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,
+11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,
+11304,11305,11306,11307,11308,11309,11310,11311,11264,11265,11266,11267,
+11268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,
+11280,11281,11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,
+11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,
+11304,11305,11306,11307,11308,11309,11310,11359,11360,11360,11362,11363,
+11364,570,574,11367,11367,11369,11369,11371,11371,11373,11374,11375,11376,
+11377,11378,11378,11380,11381,11381,11383,11384,11385,11386,11387,11388,
+11389,11390,11391,11392,11392,11394,11394,11396,11396,11398,11398,11400,
+11400,11402,11402,11404,11404,11406,11406,11408,11408,11410,11410,11412,
+11412,11414,11414,11416,11416,11418,11418,11420,11420,11422,11422,11424,
+11424,11426,11426,11428,11428,11430,11430,11432,11432,11434,11434,11436,
+11436,11438,11438,11440,11440,11442,11442,11444,11444,11446,11446,11448,
+11448,11450,11450,11452,11452,11454,11454,11456,11456,11458,11458,11460,
+11460,11462,11462,11464,11464,11466,11466,11468,11468,11470,11470,11472,
+11472,11474,11474,11476,11476,11478,11478,11480,11480,11482,11482,11484,
+11484,11486,11486,11488,11488,11490,11490,11492,11493,11494,11495,11496,
+11497,11498,11499,11499,11501,11501,11503,11504,11505,11506,11506,11508,
+11509,11510,11511,11512,11513,11514,11515,11516,11517,11518,11519,4256,
+4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,
+4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,
+4287,4288,4289,4290,4291,4292,4293,11558,4295,11560,11561,11562,11563,
+11564,4301,11566,11567,11568,11569,11570,11571,11572,11573,11574,11575,
+11576,11577,11578,11579,11580,11581,11582,11583,11584,11585,11586,11587,
+11588,11589,11590,11591,11592,11593,11594,11595,11596,11597,11598,11599,
+11600,11601,11602,11603,11604,11605,11606,11607,11608,11609,11610,11611,
+11612,11613,11614,11615,11616,11617,11618,11619,11620,11621,11622,11623,
+11624,11625,11626,11627,11628,11629,11630,11631,11632,11633,11634,11635,
+11636,11637,11638,11639,11640,11641,11642,11643,11644,11645,11646,11647,
+11648,11649,11650,11651,11652,11653,11654,11655,11656,11657,11658,11659,
+11660,11661,11662,11663,11664,11665,11666,11667,11668,11669,11670,11671,
+11672,11673,11674,11675,11676,11677,11678,11679,11680,11681,11682,11683,
+11684,11685,11686,11687,11688,11689,11690,11691,11692,11693,11694,11695,
+11696,11697,11698,11699,11700,11701,11702,11703,11704,11705,11706,11707,
+11708,11709,11710,11711,11712,11713,11714,11715,11716,11717,11718,11719,
+11720,11721,11722,11723,11724,11725,11726,11727,11728,11729,11730,11731,
+11732,11733,11734,11735,11736,11737,11738,11739,11740,11741,11742,11743,
+11744,11745,11746,11747,11748,11749,11750,11751,11752,11753,11754,11755,
+11756,11757,11758,11759,11760,11761,11762,11763,11764,11765,11766,11767,
+11768,11769,11770,11771,11772,11773,11774,11775,11776,11777,11778,11779,
+11780,11781,11782,11783,11784,11785,11786,11787,11788,11789,11790,11791,
+11792,11793,11794,11795,11796,11797,11798,11799,11800,11801,11802,11803,
+11804,11805,11806,11807,11808,11809,11810,11811,11812,11813,11814,11815,
+11816,11817,11818,11819,11820,11821,11822,11823,11824,11825,11826,11827,
+11828,11829,11830,11831,11832,11833,11834,11835,11836,11837,11838,11839,
+11840,11841,11842,11843,11844,11845,11846,11847,11848,11849,11850,11851,
+11852,11853,11854,11855,11856,11857,11858,11859,11860,11861,11862,11863,
+11864,11865,11866,11867,11868,11869,11870,11871,11872,11873,11874,11875,
+11876,11877,11878,11879,11880,11881,11882,11883,11884,11885,11886,11887,
+11888,11889,11890,11891,11892,11893,11894,11895,11896,11897,11898,11899,
+11900,11901,11902,11903,11904,11905,11906,11907,11908,11909,11910,11911,
+11912,11913,11914,11915,11916,11917,11918,11919,11920,11921,11922,11923,
+11924,11925,11926,11927,11928,11929,11930,11931,11932,11933,11934,11935,
+11936,11937,11938,11939,11940,11941,11942,11943,11944,11945,11946,11947,
+11948,11949,11950,11951,11952,11953,11954,11955,11956,11957,11958,11959,
+11960,11961,11962,11963,11964,11965,11966,11967,11968,11969,11970,11971,
+11972,11973,11974,11975,11976,11977,11978,11979,11980,11981,11982,11983,
+11984,11985,11986,11987,11988,11989,11990,11991,11992,11993,11994,11995,
+11996,11997,11998,11999,12000,12001,12002,12003,12004,12005,12006,12007,
+12008,12009,12010,12011,12012,12013,12014,12015,12016,12017,12018,12019,
+12020,12021,12022,12023,12024,12025,12026,12027,12028,12029,12030,12031,
+12032,12033,12034,12035,12036,12037,12038,12039,12040,12041,12042,12043,
+12044,12045,12046,12047,12048,12049,12050,12051,12052,12053,12054,12055,
+12056,12057,12058,12059,12060,12061,12062,12063,12064,12065,12066,12067,
+12068,12069,12070,12071,12072,12073,12074,12075,12076,12077,12078,12079,
+12080,12081,12082,12083,12084,12085,12086,12087,12088,12089,12090,12091,
+12092,12093,12094,12095,12096,12097,12098,12099,12100,12101,12102,12103,
+12104,12105,12106,12107,12108,12109,12110,12111,12112,12113,12114,12115,
+12116,12117,12118,12119,12120,12121,12122,12123,12124,12125,12126,12127,
+12128,12129,12130,12131,12132,12133,12134,12135,12136,12137,12138,12139,
+12140,12141,12142,12143,12144,12145,12146,12147,12148,12149,12150,12151,
+12152,12153,12154,12155,12156,12157,12158,12159,12160,12161,12162,12163,
+12164,12165,12166,12167,12168,12169,12170,12171,12172,12173,12174,12175,
+12176,12177,12178,12179,12180,12181,12182,12183,12184,12185,12186,12187,
+12188,12189,12190,12191,12192,12193,12194,12195,12196,12197,12198,12199,
+12200,12201,12202,12203,12204,12205,12206,12207,12208,12209,12210,12211,
+12212,12213,12214,12215,12216,12217,12218,12219,12220,12221,12222,12223,
+12224,12225,12226,12227,12228,12229,12230,12231,12232,12233,12234,12235,
+12236,12237,12238,12239,12240,12241,12242,12243,12244,12245,12246,12247,
+12248,12249,12250,12251,12252,12253,12254,12255,12256,12257,12258,12259,
+12260,12261,12262,12263,12264,12265,12266,12267,12268,12269,12270,12271,
+12272,12273,12274,12275,12276,12277,12278,12279,12280,12281,12282,12283,
+12284,12285,12286,12287,12288,12289,12290,12291,12292,12293,12294,12295,
+12296,12297,12298,12299,12300,12301,12302,12303,12304,12305,12306,12307,
+12308,12309,12310,12311,12312,12313,12314,12315,12316,12317,12318,12319,
+12320,12321,12322,12323,12324,12325,12326,12327,12328,12329,12330,12331,
+12332,12333,12334,12335,12336,12337,12338,12339,12340,12341,12342,12343,
+12344,12345,12346,12347,12348,12349,12350,12351,12352,12353,12354,12355,
+12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,
+12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,
+12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,
+12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,
+12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,
+12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,
+12428,12429,12430,12431,12432,12433,12434,12435,12436,12437,12438,12439,
+12440,12441,12442,12443,12444,12445,12446,12447,12448,12449,12450,12451,
+12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,
+12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,
+12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,
+12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,
+12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,
+12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,
+12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,12535,
+12536,12537,12538,12539,12540,12541,12542,12543,12544,12545,12546,12547,
+12548,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,
+12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,
+12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,
+12584,12585,12586,12587,12588,12589,12590,12591,12592,12593,12594,12595,
+12596,12597,12598,12599,12600,12601,12602,12603,12604,12605,12606,12607,
+12608,12609,12610,12611,12612,12613,12614,12615,12616,12617,12618,12619,
+12620,12621,12622,12623,12624,12625,12626,12627,12628,12629,12630,12631,
+12632,12633,12634,12635,12636,12637,12638,12639,12640,12641,12642,12643,
+12644,12645,12646,12647,12648,12649,12650,12651,12652,12653,12654,12655,
+12656,12657,12658,12659,12660,12661,12662,12663,12664,12665,12666,12667,
+12668,12669,12670,12671,12672,12673,12674,12675,12676,12677,12678,12679,
+12680,12681,12682,12683,12684,12685,12686,12687,12688,12689,12690,12691,
+12692,12693,12694,12695,12696,12697,12698,12699,12700,12701,12702,12703,
+12704,12705,12706,12707,12708,12709,12710,12711,12712,12713,12714,12715,
+12716,12717,12718,12719,12720,12721,12722,12723,12724,12725,12726,12727,
+12728,12729,12730,12731,12732,12733,12734,12735,12736,12737,12738,12739,
+12740,12741,12742,12743,12744,12745,12746,12747,12748,12749,12750,12751,
+12752,12753,12754,12755,12756,12757,12758,12759,12760,12761,12762,12763,
+12764,12765,12766,12767,12768,12769,12770,12771,12772,12773,12774,12775,
+12776,12777,12778,12779,12780,12781,12782,12783,12784,12785,12786,12787,
+12788,12789,12790,12791,12792,12793,12794,12795,12796,12797,12798,12799,
+12800,12801,12802,12803,12804,12805,12806,12807,12808,12809,12810,12811,
+12812,12813,12814,12815,12816,12817,12818,12819,12820,12821,12822,12823,
+12824,12825,12826,12827,12828,12829,12830,12831,12832,12833,12834,12835,
+12836,12837,12838,12839,12840,12841,12842,12843,12844,12845,12846,12847,
+12848,12849,12850,12851,12852,12853,12854,12855,12856,12857,12858,12859,
+12860,12861,12862,12863,12864,12865,12866,12867,12868,12869,12870,12871,
+12872,12873,12874,12875,12876,12877,12878,12879,12880,12881,12882,12883,
+12884,12885,12886,12887,12888,12889,12890,12891,12892,12893,12894,12895,
+12896,12897,12898,12899,12900,12901,12902,12903,12904,12905,12906,12907,
+12908,12909,12910,12911,12912,12913,12914,12915,12916,12917,12918,12919,
+12920,12921,12922,12923,12924,12925,12926,12927,12928,12929,12930,12931,
+12932,12933,12934,12935,12936,12937,12938,12939,12940,12941,12942,12943,
+12944,12945,12946,12947,12948,12949,12950,12951,12952,12953,12954,12955,
+12956,12957,12958,12959,12960,12961,12962,12963,12964,12965,12966,12967,
+12968,12969,12970,12971,12972,12973,12974,12975,12976,12977,12978,12979,
+12980,12981,12982,12983,12984,12985,12986,12987,12988,12989,12990,12991,
+12992,12993,12994,12995,12996,12997,12998,12999,13000,13001,13002,13003,
+13004,13005,13006,13007,13008,13009,13010,13011,13012,13013,13014,13015,
+13016,13017,13018,13019,13020,13021,13022,13023,13024,13025,13026,13027,
+13028,13029,13030,13031,13032,13033,13034,13035,13036,13037,13038,13039,
+13040,13041,13042,13043,13044,13045,13046,13047,13048,13049,13050,13051,
+13052,13053,13054,13055,13056,13057,13058,13059,13060,13061,13062,13063,
+13064,13065,13066,13067,13068,13069,13070,13071,13072,13073,13074,13075,
+13076,13077,13078,13079,13080,13081,13082,13083,13084,13085,13086,13087,
+13088,13089,13090,13091,13092,13093,13094,13095,13096,13097,13098,13099,
+13100,13101,13102,13103,13104,13105,13106,13107,13108,13109,13110,13111,
+13112,13113,13114,13115,13116,13117,13118,13119,13120,13121,13122,13123,
+13124,13125,13126,13127,13128,13129,13130,13131,13132,13133,13134,13135,
+13136,13137,13138,13139,13140,13141,13142,13143,13144,13145,13146,13147,
+13148,13149,13150,13151,13152,13153,13154,13155,13156,13157,13158,13159,
+13160,13161,13162,13163,13164,13165,13166,13167,13168,13169,13170,13171,
+13172,13173,13174,13175,13176,13177,13178,13179,13180,13181,13182,13183,
+13184,13185,13186,13187,13188,13189,13190,13191,13192,13193,13194,13195,
+13196,13197,13198,13199,13200,13201,13202,13203,13204,13205,13206,13207,
+13208,13209,13210,13211,13212,13213,13214,13215,13216,13217,13218,13219,
+13220,13221,13222,13223,13224,13225,13226,13227,13228,13229,13230,13231,
+13232,13233,13234,13235,13236,13237,13238,13239,13240,13241,13242,13243,
+13244,13245,13246,13247,13248,13249,13250,13251,13252,13253,13254,13255,
+13256,13257,13258,13259,13260,13261,13262,13263,13264,13265,13266,13267,
+13268,13269,13270,13271,13272,13273,13274,13275,13276,13277,13278,13279,
+13280,13281,13282,13283,13284,13285,13286,13287,13288,13289,13290,13291,
+13292,13293,13294,13295,13296,13297,13298,13299,13300,13301,13302,13303,
+13304,13305,13306,13307,13308,13309,13310,13311,13312,13313,13314,13315,
+13316,13317,13318,13319,13320,13321,13322,13323,13324,13325,13326,13327,
+13328,13329,13330,13331,13332,13333,13334,13335,13336,13337,13338,13339,
+13340,13341,13342,13343,13344,13345,13346,13347,13348,13349,13350,13351,
+13352,13353,13354,13355,13356,13357,13358,13359,13360,13361,13362,13363,
+13364,13365,13366,13367,13368,13369,13370,13371,13372,13373,13374,13375,
+13376,13377,13378,13379,13380,13381,13382,13383,13384,13385,13386,13387,
+13388,13389,13390,13391,13392,13393,13394,13395,13396,13397,13398,13399,
+13400,13401,13402,13403,13404,13405,13406,13407,13408,13409,13410,13411,
+13412,13413,13414,13415,13416,13417,13418,13419,13420,13421,13422,13423,
+13424,13425,13426,13427,13428,13429,13430,13431,13432,13433,13434,13435,
+13436,13437,13438,13439,13440,13441,13442,13443,13444,13445,13446,13447,
+13448,13449,13450,13451,13452,13453,13454,13455,13456,13457,13458,13459,
+13460,13461,13462,13463,13464,13465,13466,13467,13468,13469,13470,13471,
+13472,13473,13474,13475,13476,13477,13478,13479,13480,13481,13482,13483,
+13484,13485,13486,13487,13488,13489,13490,13491,13492,13493,13494,13495,
+13496,13497,13498,13499,13500,13501,13502,13503,13504,13505,13506,13507,
+13508,13509,13510,13511,13512,13513,13514,13515,13516,13517,13518,13519,
+13520,13521,13522,13523,13524,13525,13526,13527,13528,13529,13530,13531,
+13532,13533,13534,13535,13536,13537,13538,13539,13540,13541,13542,13543,
+13544,13545,13546,13547,13548,13549,13550,13551,13552,13553,13554,13555,
+13556,13557,13558,13559,13560,13561,13562,13563,13564,13565,13566,13567,
+13568,13569,13570,13571,13572,13573,13574,13575,13576,13577,13578,13579,
+13580,13581,13582,13583,13584,13585,13586,13587,13588,13589,13590,13591,
+13592,13593,13594,13595,13596,13597,13598,13599,13600,13601,13602,13603,
+13604,13605,13606,13607,13608,13609,13610,13611,13612,13613,13614,13615,
+13616,13617,13618,13619,13620,13621,13622,13623,13624,13625,13626,13627,
+13628,13629,13630,13631,13632,13633,13634,13635,13636,13637,13638,13639,
+13640,13641,13642,13643,13644,13645,13646,13647,13648,13649,13650,13651,
+13652,13653,13654,13655,13656,13657,13658,13659,13660,13661,13662,13663,
+13664,13665,13666,13667,13668,13669,13670,13671,13672,13673,13674,13675,
+13676,13677,13678,13679,13680,13681,13682,13683,13684,13685,13686,13687,
+13688,13689,13690,13691,13692,13693,13694,13695,13696,13697,13698,13699,
+13700,13701,13702,13703,13704,13705,13706,13707,13708,13709,13710,13711,
+13712,13713,13714,13715,13716,13717,13718,13719,13720,13721,13722,13723,
+13724,13725,13726,13727,13728,13729,13730,13731,13732,13733,13734,13735,
+13736,13737,13738,13739,13740,13741,13742,13743,13744,13745,13746,13747,
+13748,13749,13750,13751,13752,13753,13754,13755,13756,13757,13758,13759,
+13760,13761,13762,13763,13764,13765,13766,13767,13768,13769,13770,13771,
+13772,13773,13774,13775,13776,13777,13778,13779,13780,13781,13782,13783,
+13784,13785,13786,13787,13788,13789,13790,13791,13792,13793,13794,13795,
+13796,13797,13798,13799,13800,13801,13802,13803,13804,13805,13806,13807,
+13808,13809,13810,13811,13812,13813,13814,13815,13816,13817,13818,13819,
+13820,13821,13822,13823,13824,13825,13826,13827,13828,13829,13830,13831,
+13832,13833,13834,13835,13836,13837,13838,13839,13840,13841,13842,13843,
+13844,13845,13846,13847,13848,13849,13850,13851,13852,13853,13854,13855,
+13856,13857,13858,13859,13860,13861,13862,13863,13864,13865,13866,13867,
+13868,13869,13870,13871,13872,13873,13874,13875,13876,13877,13878,13879,
+13880,13881,13882,13883,13884,13885,13886,13887,13888,13889,13890,13891,
+13892,13893,13894,13895,13896,13897,13898,13899,13900,13901,13902,13903,
+13904,13905,13906,13907,13908,13909,13910,13911,13912,13913,13914,13915,
+13916,13917,13918,13919,13920,13921,13922,13923,13924,13925,13926,13927,
+13928,13929,13930,13931,13932,13933,13934,13935,13936,13937,13938,13939,
+13940,13941,13942,13943,13944,13945,13946,13947,13948,13949,13950,13951,
+13952,13953,13954,13955,13956,13957,13958,13959,13960,13961,13962,13963,
+13964,13965,13966,13967,13968,13969,13970,13971,13972,13973,13974,13975,
+13976,13977,13978,13979,13980,13981,13982,13983,13984,13985,13986,13987,
+13988,13989,13990,13991,13992,13993,13994,13995,13996,13997,13998,13999,
+14000,14001,14002,14003,14004,14005,14006,14007,14008,14009,14010,14011,
+14012,14013,14014,14015,14016,14017,14018,14019,14020,14021,14022,14023,
+14024,14025,14026,14027,14028,14029,14030,14031,14032,14033,14034,14035,
+14036,14037,14038,14039,14040,14041,14042,14043,14044,14045,14046,14047,
+14048,14049,14050,14051,14052,14053,14054,14055,14056,14057,14058,14059,
+14060,14061,14062,14063,14064,14065,14066,14067,14068,14069,14070,14071,
+14072,14073,14074,14075,14076,14077,14078,14079,14080,14081,14082,14083,
+14084,14085,14086,14087,14088,14089,14090,14091,14092,14093,14094,14095,
+14096,14097,14098,14099,14100,14101,14102,14103,14104,14105,14106,14107,
+14108,14109,14110,14111,14112,14113,14114,14115,14116,14117,14118,14119,
+14120,14121,14122,14123,14124,14125,14126,14127,14128,14129,14130,14131,
+14132,14133,14134,14135,14136,14137,14138,14139,14140,14141,14142,14143,
+14144,14145,14146,14147,14148,14149,14150,14151,14152,14153,14154,14155,
+14156,14157,14158,14159,14160,14161,14162,14163,14164,14165,14166,14167,
+14168,14169,14170,14171,14172,14173,14174,14175,14176,14177,14178,14179,
+14180,14181,14182,14183,14184,14185,14186,14187,14188,14189,14190,14191,
+14192,14193,14194,14195,14196,14197,14198,14199,14200,14201,14202,14203,
+14204,14205,14206,14207,14208,14209,14210,14211,14212,14213,14214,14215,
+14216,14217,14218,14219,14220,14221,14222,14223,14224,14225,14226,14227,
+14228,14229,14230,14231,14232,14233,14234,14235,14236,14237,14238,14239,
+14240,14241,14242,14243,14244,14245,14246,14247,14248,14249,14250,14251,
+14252,14253,14254,14255,14256,14257,14258,14259,14260,14261,14262,14263,
+14264,14265,14266,14267,14268,14269,14270,14271,14272,14273,14274,14275,
+14276,14277,14278,14279,14280,14281,14282,14283,14284,14285,14286,14287,
+14288,14289,14290,14291,14292,14293,14294,14295,14296,14297,14298,14299,
+14300,14301,14302,14303,14304,14305,14306,14307,14308,14309,14310,14311,
+14312,14313,14314,14315,14316,14317,14318,14319,14320,14321,14322,14323,
+14324,14325,14326,14327,14328,14329,14330,14331,14332,14333,14334,14335,
+14336,14337,14338,14339,14340,14341,14342,14343,14344,14345,14346,14347,
+14348,14349,14350,14351,14352,14353,14354,14355,14356,14357,14358,14359,
+14360,14361,14362,14363,14364,14365,14366,14367,14368,14369,14370,14371,
+14372,14373,14374,14375,14376,14377,14378,14379,14380,14381,14382,14383,
+14384,14385,14386,14387,14388,14389,14390,14391,14392,14393,14394,14395,
+14396,14397,14398,14399,14400,14401,14402,14403,14404,14405,14406,14407,
+14408,14409,14410,14411,14412,14413,14414,14415,14416,14417,14418,14419,
+14420,14421,14422,14423,14424,14425,14426,14427,14428,14429,14430,14431,
+14432,14433,14434,14435,14436,14437,14438,14439,14440,14441,14442,14443,
+14444,14445,14446,14447,14448,14449,14450,14451,14452,14453,14454,14455,
+14456,14457,14458,14459,14460,14461,14462,14463,14464,14465,14466,14467,
+14468,14469,14470,14471,14472,14473,14474,14475,14476,14477,14478,14479,
+14480,14481,14482,14483,14484,14485,14486,14487,14488,14489,14490,14491,
+14492,14493,14494,14495,14496,14497,14498,14499,14500,14501,14502,14503,
+14504,14505,14506,14507,14508,14509,14510,14511,14512,14513,14514,14515,
+14516,14517,14518,14519,14520,14521,14522,14523,14524,14525,14526,14527,
+14528,14529,14530,14531,14532,14533,14534,14535,14536,14537,14538,14539,
+14540,14541,14542,14543,14544,14545,14546,14547,14548,14549,14550,14551,
+14552,14553,14554,14555,14556,14557,14558,14559,14560,14561,14562,14563,
+14564,14565,14566,14567,14568,14569,14570,14571,14572,14573,14574,14575,
+14576,14577,14578,14579,14580,14581,14582,14583,14584,14585,14586,14587,
+14588,14589,14590,14591,14592,14593,14594,14595,14596,14597,14598,14599,
+14600,14601,14602,14603,14604,14605,14606,14607,14608,14609,14610,14611,
+14612,14613,14614,14615,14616,14617,14618,14619,14620,14621,14622,14623,
+14624,14625,14626,14627,14628,14629,14630,14631,14632,14633,14634,14635,
+14636,14637,14638,14639,14640,14641,14642,14643,14644,14645,14646,14647,
+14648,14649,14650,14651,14652,14653,14654,14655,14656,14657,14658,14659,
+14660,14661,14662,14663,14664,14665,14666,14667,14668,14669,14670,14671,
+14672,14673,14674,14675,14676,14677,14678,14679,14680,14681,14682,14683,
+14684,14685,14686,14687,14688,14689,14690,14691,14692,14693,14694,14695,
+14696,14697,14698,14699,14700,14701,14702,14703,14704,14705,14706,14707,
+14708,14709,14710,14711,14712,14713,14714,14715,14716,14717,14718,14719,
+14720,14721,14722,14723,14724,14725,14726,14727,14728,14729,14730,14731,
+14732,14733,14734,14735,14736,14737,14738,14739,14740,14741,14742,14743,
+14744,14745,14746,14747,14748,14749,14750,14751,14752,14753,14754,14755,
+14756,14757,14758,14759,14760,14761,14762,14763,14764,14765,14766,14767,
+14768,14769,14770,14771,14772,14773,14774,14775,14776,14777,14778,14779,
+14780,14781,14782,14783,14784,14785,14786,14787,14788,14789,14790,14791,
+14792,14793,14794,14795,14796,14797,14798,14799,14800,14801,14802,14803,
+14804,14805,14806,14807,14808,14809,14810,14811,14812,14813,14814,14815,
+14816,14817,14818,14819,14820,14821,14822,14823,14824,14825,14826,14827,
+14828,14829,14830,14831,14832,14833,14834,14835,14836,14837,14838,14839,
+14840,14841,14842,14843,14844,14845,14846,14847,14848,14849,14850,14851,
+14852,14853,14854,14855,14856,14857,14858,14859,14860,14861,14862,14863,
+14864,14865,14866,14867,14868,14869,14870,14871,14872,14873,14874,14875,
+14876,14877,14878,14879,14880,14881,14882,14883,14884,14885,14886,14887,
+14888,14889,14890,14891,14892,14893,14894,14895,14896,14897,14898,14899,
+14900,14901,14902,14903,14904,14905,14906,14907,14908,14909,14910,14911,
+14912,14913,14914,14915,14916,14917,14918,14919,14920,14921,14922,14923,
+14924,14925,14926,14927,14928,14929,14930,14931,14932,14933,14934,14935,
+14936,14937,14938,14939,14940,14941,14942,14943,14944,14945,14946,14947,
+14948,14949,14950,14951,14952,14953,14954,14955,14956,14957,14958,14959,
+14960,14961,14962,14963,14964,14965,14966,14967,14968,14969,14970,14971,
+14972,14973,14974,14975,14976,14977,14978,14979,14980,14981,14982,14983,
+14984,14985,14986,14987,14988,14989,14990,14991,14992,14993,14994,14995,
+14996,14997,14998,14999,15000,15001,15002,15003,15004,15005,15006,15007,
+15008,15009,15010,15011,15012,15013,15014,15015,15016,15017,15018,15019,
+15020,15021,15022,15023,15024,15025,15026,15027,15028,15029,15030,15031,
+15032,15033,15034,15035,15036,15037,15038,15039,15040,15041,15042,15043,
+15044,15045,15046,15047,15048,15049,15050,15051,15052,15053,15054,15055,
+15056,15057,15058,15059,15060,15061,15062,15063,15064,15065,15066,15067,
+15068,15069,15070,15071,15072,15073,15074,15075,15076,15077,15078,15079,
+15080,15081,15082,15083,15084,15085,15086,15087,15088,15089,15090,15091,
+15092,15093,15094,15095,15096,15097,15098,15099,15100,15101,15102,15103,
+15104,15105,15106,15107,15108,15109,15110,15111,15112,15113,15114,15115,
+15116,15117,15118,15119,15120,15121,15122,15123,15124,15125,15126,15127,
+15128,15129,15130,15131,15132,15133,15134,15135,15136,15137,15138,15139,
+15140,15141,15142,15143,15144,15145,15146,15147,15148,15149,15150,15151,
+15152,15153,15154,15155,15156,15157,15158,15159,15160,15161,15162,15163,
+15164,15165,15166,15167,15168,15169,15170,15171,15172,15173,15174,15175,
+15176,15177,15178,15179,15180,15181,15182,15183,15184,15185,15186,15187,
+15188,15189,15190,15191,15192,15193,15194,15195,15196,15197,15198,15199,
+15200,15201,15202,15203,15204,15205,15206,15207,15208,15209,15210,15211,
+15212,15213,15214,15215,15216,15217,15218,15219,15220,15221,15222,15223,
+15224,15225,15226,15227,15228,15229,15230,15231,15232,15233,15234,15235,
+15236,15237,15238,15239,15240,15241,15242,15243,15244,15245,15246,15247,
+15248,15249,15250,15251,15252,15253,15254,15255,15256,15257,15258,15259,
+15260,15261,15262,15263,15264,15265,15266,15267,15268,15269,15270,15271,
+15272,15273,15274,15275,15276,15277,15278,15279,15280,15281,15282,15283,
+15284,15285,15286,15287,15288,15289,15290,15291,15292,15293,15294,15295,
+15296,15297,15298,15299,15300,15301,15302,15303,15304,15305,15306,15307,
+15308,15309,15310,15311,15312,15313,15314,15315,15316,15317,15318,15319,
+15320,15321,15322,15323,15324,15325,15326,15327,15328,15329,15330,15331,
+15332,15333,15334,15335,15336,15337,15338,15339,15340,15341,15342,15343,
+15344,15345,15346,15347,15348,15349,15350,15351,15352,15353,15354,15355,
+15356,15357,15358,15359,15360,15361,15362,15363,15364,15365,15366,15367,
+15368,15369,15370,15371,15372,15373,15374,15375,15376,15377,15378,15379,
+15380,15381,15382,15383,15384,15385,15386,15387,15388,15389,15390,15391,
+15392,15393,15394,15395,15396,15397,15398,15399,15400,15401,15402,15403,
+15404,15405,15406,15407,15408,15409,15410,15411,15412,15413,15414,15415,
+15416,15417,15418,15419,15420,15421,15422,15423,15424,15425,15426,15427,
+15428,15429,15430,15431,15432,15433,15434,15435,15436,15437,15438,15439,
+15440,15441,15442,15443,15444,15445,15446,15447,15448,15449,15450,15451,
+15452,15453,15454,15455,15456,15457,15458,15459,15460,15461,15462,15463,
+15464,15465,15466,15467,15468,15469,15470,15471,15472,15473,15474,15475,
+15476,15477,15478,15479,15480,15481,15482,15483,15484,15485,15486,15487,
+15488,15489,15490,15491,15492,15493,15494,15495,15496,15497,15498,15499,
+15500,15501,15502,15503,15504,15505,15506,15507,15508,15509,15510,15511,
+15512,15513,15514,15515,15516,15517,15518,15519,15520,15521,15522,15523,
+15524,15525,15526,15527,15528,15529,15530,15531,15532,15533,15534,15535,
+15536,15537,15538,15539,15540,15541,15542,15543,15544,15545,15546,15547,
+15548,15549,15550,15551,15552,15553,15554,15555,15556,15557,15558,15559,
+15560,15561,15562,15563,15564,15565,15566,15567,15568,15569,15570,15571,
+15572,15573,15574,15575,15576,15577,15578,15579,15580,15581,15582,15583,
+15584,15585,15586,15587,15588,15589,15590,15591,15592,15593,15594,15595,
+15596,15597,15598,15599,15600,15601,15602,15603,15604,15605,15606,15607,
+15608,15609,15610,15611,15612,15613,15614,15615,15616,15617,15618,15619,
+15620,15621,15622,15623,15624,15625,15626,15627,15628,15629,15630,15631,
+15632,15633,15634,15635,15636,15637,15638,15639,15640,15641,15642,15643,
+15644,15645,15646,15647,15648,15649,15650,15651,15652,15653,15654,15655,
+15656,15657,15658,15659,15660,15661,15662,15663,15664,15665,15666,15667,
+15668,15669,15670,15671,15672,15673,15674,15675,15676,15677,15678,15679,
+15680,15681,15682,15683,15684,15685,15686,15687,15688,15689,15690,15691,
+15692,15693,15694,15695,15696,15697,15698,15699,15700,15701,15702,15703,
+15704,15705,15706,15707,15708,15709,15710,15711,15712,15713,15714,15715,
+15716,15717,15718,15719,15720,15721,15722,15723,15724,15725,15726,15727,
+15728,15729,15730,15731,15732,15733,15734,15735,15736,15737,15738,15739,
+15740,15741,15742,15743,15744,15745,15746,15747,15748,15749,15750,15751,
+15752,15753,15754,15755,15756,15757,15758,15759,15760,15761,15762,15763,
+15764,15765,15766,15767,15768,15769,15770,15771,15772,15773,15774,15775,
+15776,15777,15778,15779,15780,15781,15782,15783,15784,15785,15786,15787,
+15788,15789,15790,15791,15792,15793,15794,15795,15796,15797,15798,15799,
+15800,15801,15802,15803,15804,15805,15806,15807,15808,15809,15810,15811,
+15812,15813,15814,15815,15816,15817,15818,15819,15820,15821,15822,15823,
+15824,15825,15826,15827,15828,15829,15830,15831,15832,15833,15834,15835,
+15836,15837,15838,15839,15840,15841,15842,15843,15844,15845,15846,15847,
+15848,15849,15850,15851,15852,15853,15854,15855,15856,15857,15858,15859,
+15860,15861,15862,15863,15864,15865,15866,15867,15868,15869,15870,15871,
+15872,15873,15874,15875,15876,15877,15878,15879,15880,15881,15882,15883,
+15884,15885,15886,15887,15888,15889,15890,15891,15892,15893,15894,15895,
+15896,15897,15898,15899,15900,15901,15902,15903,15904,15905,15906,15907,
+15908,15909,15910,15911,15912,15913,15914,15915,15916,15917,15918,15919,
+15920,15921,15922,15923,15924,15925,15926,15927,15928,15929,15930,15931,
+15932,15933,15934,15935,15936,15937,15938,15939,15940,15941,15942,15943,
+15944,15945,15946,15947,15948,15949,15950,15951,15952,15953,15954,15955,
+15956,15957,15958,15959,15960,15961,15962,15963,15964,15965,15966,15967,
+15968,15969,15970,15971,15972,15973,15974,15975,15976,15977,15978,15979,
+15980,15981,15982,15983,15984,15985,15986,15987,15988,15989,15990,15991,
+15992,15993,15994,15995,15996,15997,15998,15999,16000,16001,16002,16003,
+16004,16005,16006,16007,16008,16009,16010,16011,16012,16013,16014,16015,
+16016,16017,16018,16019,16020,16021,16022,16023,16024,16025,16026,16027,
+16028,16029,16030,16031,16032,16033,16034,16035,16036,16037,16038,16039,
+16040,16041,16042,16043,16044,16045,16046,16047,16048,16049,16050,16051,
+16052,16053,16054,16055,16056,16057,16058,16059,16060,16061,16062,16063,
+16064,16065,16066,16067,16068,16069,16070,16071,16072,16073,16074,16075,
+16076,16077,16078,16079,16080,16081,16082,16083,16084,16085,16086,16087,
+16088,16089,16090,16091,16092,16093,16094,16095,16096,16097,16098,16099,
+16100,16101,16102,16103,16104,16105,16106,16107,16108,16109,16110,16111,
+16112,16113,16114,16115,16116,16117,16118,16119,16120,16121,16122,16123,
+16124,16125,16126,16127,16128,16129,16130,16131,16132,16133,16134,16135,
+16136,16137,16138,16139,16140,16141,16142,16143,16144,16145,16146,16147,
+16148,16149,16150,16151,16152,16153,16154,16155,16156,16157,16158,16159,
+16160,16161,16162,16163,16164,16165,16166,16167,16168,16169,16170,16171,
+16172,16173,16174,16175,16176,16177,16178,16179,16180,16181,16182,16183,
+16184,16185,16186,16187,16188,16189,16190,16191,16192,16193,16194,16195,
+16196,16197,16198,16199,16200,16201,16202,16203,16204,16205,16206,16207,
+16208,16209,16210,16211,16212,16213,16214,16215,16216,16217,16218,16219,
+16220,16221,16222,16223,16224,16225,16226,16227,16228,16229,16230,16231,
+16232,16233,16234,16235,16236,16237,16238,16239,16240,16241,16242,16243,
+16244,16245,16246,16247,16248,16249,16250,16251,16252,16253,16254,16255,
+16256,16257,16258,16259,16260,16261,16262,16263,16264,16265,16266,16267,
+16268,16269,16270,16271,16272,16273,16274,16275,16276,16277,16278,16279,
+16280,16281,16282,16283,16284,16285,16286,16287,16288,16289,16290,16291,
+16292,16293,16294,16295,16296,16297,16298,16299,16300,16301,16302,16303,
+16304,16305,16306,16307,16308,16309,16310,16311,16312,16313,16314,16315,
+16316,16317,16318,16319,16320,16321,16322,16323,16324,16325,16326,16327,
+16328,16329,16330,16331,16332,16333,16334,16335,16336,16337,16338,16339,
+16340,16341,16342,16343,16344,16345,16346,16347,16348,16349,16350,16351,
+16352,16353,16354,16355,16356,16357,16358,16359,16360,16361,16362,16363,
+16364,16365,16366,16367,16368,16369,16370,16371,16372,16373,16374,16375,
+16376,16377,16378,16379,16380,16381,16382,16383,16384,16385,16386,16387,
+16388,16389,16390,16391,16392,16393,16394,16395,16396,16397,16398,16399,
+16400,16401,16402,16403,16404,16405,16406,16407,16408,16409,16410,16411,
+16412,16413,16414,16415,16416,16417,16418,16419,16420,16421,16422,16423,
+16424,16425,16426,16427,16428,16429,16430,16431,16432,16433,16434,16435,
+16436,16437,16438,16439,16440,16441,16442,16443,16444,16445,16446,16447,
+16448,16449,16450,16451,16452,16453,16454,16455,16456,16457,16458,16459,
+16460,16461,16462,16463,16464,16465,16466,16467,16468,16469,16470,16471,
+16472,16473,16474,16475,16476,16477,16478,16479,16480,16481,16482,16483,
+16484,16485,16486,16487,16488,16489,16490,16491,16492,16493,16494,16495,
+16496,16497,16498,16499,16500,16501,16502,16503,16504,16505,16506,16507,
+16508,16509,16510,16511,16512,16513,16514,16515,16516,16517,16518,16519,
+16520,16521,16522,16523,16524,16525,16526,16527,16528,16529,16530,16531,
+16532,16533,16534,16535,16536,16537,16538,16539,16540,16541,16542,16543,
+16544,16545,16546,16547,16548,16549,16550,16551,16552,16553,16554,16555,
+16556,16557,16558,16559,16560,16561,16562,16563,16564,16565,16566,16567,
+16568,16569,16570,16571,16572,16573,16574,16575,16576,16577,16578,16579,
+16580,16581,16582,16583,16584,16585,16586,16587,16588,16589,16590,16591,
+16592,16593,16594,16595,16596,16597,16598,16599,16600,16601,16602,16603,
+16604,16605,16606,16607,16608,16609,16610,16611,16612,16613,16614,16615,
+16616,16617,16618,16619,16620,16621,16622,16623,16624,16625,16626,16627,
+16628,16629,16630,16631,16632,16633,16634,16635,16636,16637,16638,16639,
+16640,16641,16642,16643,16644,16645,16646,16647,16648,16649,16650,16651,
+16652,16653,16654,16655,16656,16657,16658,16659,16660,16661,16662,16663,
+16664,16665,16666,16667,16668,16669,16670,16671,16672,16673,16674,16675,
+16676,16677,16678,16679,16680,16681,16682,16683,16684,16685,16686,16687,
+16688,16689,16690,16691,16692,16693,16694,16695,16696,16697,16698,16699,
+16700,16701,16702,16703,16704,16705,16706,16707,16708,16709,16710,16711,
+16712,16713,16714,16715,16716,16717,16718,16719,16720,16721,16722,16723,
+16724,16725,16726,16727,16728,16729,16730,16731,16732,16733,16734,16735,
+16736,16737,16738,16739,16740,16741,16742,16743,16744,16745,16746,16747,
+16748,16749,16750,16751,16752,16753,16754,16755,16756,16757,16758,16759,
+16760,16761,16762,16763,16764,16765,16766,16767,16768,16769,16770,16771,
+16772,16773,16774,16775,16776,16777,16778,16779,16780,16781,16782,16783,
+16784,16785,16786,16787,16788,16789,16790,16791,16792,16793,16794,16795,
+16796,16797,16798,16799,16800,16801,16802,16803,16804,16805,16806,16807,
+16808,16809,16810,16811,16812,16813,16814,16815,16816,16817,16818,16819,
+16820,16821,16822,16823,16824,16825,16826,16827,16828,16829,16830,16831,
+16832,16833,16834,16835,16836,16837,16838,16839,16840,16841,16842,16843,
+16844,16845,16846,16847,16848,16849,16850,16851,16852,16853,16854,16855,
+16856,16857,16858,16859,16860,16861,16862,16863,16864,16865,16866,16867,
+16868,16869,16870,16871,16872,16873,16874,16875,16876,16877,16878,16879,
+16880,16881,16882,16883,16884,16885,16886,16887,16888,16889,16890,16891,
+16892,16893,16894,16895,16896,16897,16898,16899,16900,16901,16902,16903,
+16904,16905,16906,16907,16908,16909,16910,16911,16912,16913,16914,16915,
+16916,16917,16918,16919,16920,16921,16922,16923,16924,16925,16926,16927,
+16928,16929,16930,16931,16932,16933,16934,16935,16936,16937,16938,16939,
+16940,16941,16942,16943,16944,16945,16946,16947,16948,16949,16950,16951,
+16952,16953,16954,16955,16956,16957,16958,16959,16960,16961,16962,16963,
+16964,16965,16966,16967,16968,16969,16970,16971,16972,16973,16974,16975,
+16976,16977,16978,16979,16980,16981,16982,16983,16984,16985,16986,16987,
+16988,16989,16990,16991,16992,16993,16994,16995,16996,16997,16998,16999,
+17000,17001,17002,17003,17004,17005,17006,17007,17008,17009,17010,17011,
+17012,17013,17014,17015,17016,17017,17018,17019,17020,17021,17022,17023,
+17024,17025,17026,17027,17028,17029,17030,17031,17032,17033,17034,17035,
+17036,17037,17038,17039,17040,17041,17042,17043,17044,17045,17046,17047,
+17048,17049,17050,17051,17052,17053,17054,17055,17056,17057,17058,17059,
+17060,17061,17062,17063,17064,17065,17066,17067,17068,17069,17070,17071,
+17072,17073,17074,17075,17076,17077,17078,17079,17080,17081,17082,17083,
+17084,17085,17086,17087,17088,17089,17090,17091,17092,17093,17094,17095,
+17096,17097,17098,17099,17100,17101,17102,17103,17104,17105,17106,17107,
+17108,17109,17110,17111,17112,17113,17114,17115,17116,17117,17118,17119,
+17120,17121,17122,17123,17124,17125,17126,17127,17128,17129,17130,17131,
+17132,17133,17134,17135,17136,17137,17138,17139,17140,17141,17142,17143,
+17144,17145,17146,17147,17148,17149,17150,17151,17152,17153,17154,17155,
+17156,17157,17158,17159,17160,17161,17162,17163,17164,17165,17166,17167,
+17168,17169,17170,17171,17172,17173,17174,17175,17176,17177,17178,17179,
+17180,17181,17182,17183,17184,17185,17186,17187,17188,17189,17190,17191,
+17192,17193,17194,17195,17196,17197,17198,17199,17200,17201,17202,17203,
+17204,17205,17206,17207,17208,17209,17210,17211,17212,17213,17214,17215,
+17216,17217,17218,17219,17220,17221,17222,17223,17224,17225,17226,17227,
+17228,17229,17230,17231,17232,17233,17234,17235,17236,17237,17238,17239,
+17240,17241,17242,17243,17244,17245,17246,17247,17248,17249,17250,17251,
+17252,17253,17254,17255,17256,17257,17258,17259,17260,17261,17262,17263,
+17264,17265,17266,17267,17268,17269,17270,17271,17272,17273,17274,17275,
+17276,17277,17278,17279,17280,17281,17282,17283,17284,17285,17286,17287,
+17288,17289,17290,17291,17292,17293,17294,17295,17296,17297,17298,17299,
+17300,17301,17302,17303,17304,17305,17306,17307,17308,17309,17310,17311,
+17312,17313,17314,17315,17316,17317,17318,17319,17320,17321,17322,17323,
+17324,17325,17326,17327,17328,17329,17330,17331,17332,17333,17334,17335,
+17336,17337,17338,17339,17340,17341,17342,17343,17344,17345,17346,17347,
+17348,17349,17350,17351,17352,17353,17354,17355,17356,17357,17358,17359,
+17360,17361,17362,17363,17364,17365,17366,17367,17368,17369,17370,17371,
+17372,17373,17374,17375,17376,17377,17378,17379,17380,17381,17382,17383,
+17384,17385,17386,17387,17388,17389,17390,17391,17392,17393,17394,17395,
+17396,17397,17398,17399,17400,17401,17402,17403,17404,17405,17406,17407,
+17408,17409,17410,17411,17412,17413,17414,17415,17416,17417,17418,17419,
+17420,17421,17422,17423,17424,17425,17426,17427,17428,17429,17430,17431,
+17432,17433,17434,17435,17436,17437,17438,17439,17440,17441,17442,17443,
+17444,17445,17446,17447,17448,17449,17450,17451,17452,17453,17454,17455,
+17456,17457,17458,17459,17460,17461,17462,17463,17464,17465,17466,17467,
+17468,17469,17470,17471,17472,17473,17474,17475,17476,17477,17478,17479,
+17480,17481,17482,17483,17484,17485,17486,17487,17488,17489,17490,17491,
+17492,17493,17494,17495,17496,17497,17498,17499,17500,17501,17502,17503,
+17504,17505,17506,17507,17508,17509,17510,17511,17512,17513,17514,17515,
+17516,17517,17518,17519,17520,17521,17522,17523,17524,17525,17526,17527,
+17528,17529,17530,17531,17532,17533,17534,17535,17536,17537,17538,17539,
+17540,17541,17542,17543,17544,17545,17546,17547,17548,17549,17550,17551,
+17552,17553,17554,17555,17556,17557,17558,17559,17560,17561,17562,17563,
+17564,17565,17566,17567,17568,17569,17570,17571,17572,17573,17574,17575,
+17576,17577,17578,17579,17580,17581,17582,17583,17584,17585,17586,17587,
+17588,17589,17590,17591,17592,17593,17594,17595,17596,17597,17598,17599,
+17600,17601,17602,17603,17604,17605,17606,17607,17608,17609,17610,17611,
+17612,17613,17614,17615,17616,17617,17618,17619,17620,17621,17622,17623,
+17624,17625,17626,17627,17628,17629,17630,17631,17632,17633,17634,17635,
+17636,17637,17638,17639,17640,17641,17642,17643,17644,17645,17646,17647,
+17648,17649,17650,17651,17652,17653,17654,17655,17656,17657,17658,17659,
+17660,17661,17662,17663,17664,17665,17666,17667,17668,17669,17670,17671,
+17672,17673,17674,17675,17676,17677,17678,17679,17680,17681,17682,17683,
+17684,17685,17686,17687,17688,17689,17690,17691,17692,17693,17694,17695,
+17696,17697,17698,17699,17700,17701,17702,17703,17704,17705,17706,17707,
+17708,17709,17710,17711,17712,17713,17714,17715,17716,17717,17718,17719,
+17720,17721,17722,17723,17724,17725,17726,17727,17728,17729,17730,17731,
+17732,17733,17734,17735,17736,17737,17738,17739,17740,17741,17742,17743,
+17744,17745,17746,17747,17748,17749,17750,17751,17752,17753,17754,17755,
+17756,17757,17758,17759,17760,17761,17762,17763,17764,17765,17766,17767,
+17768,17769,17770,17771,17772,17773,17774,17775,17776,17777,17778,17779,
+17780,17781,17782,17783,17784,17785,17786,17787,17788,17789,17790,17791,
+17792,17793,17794,17795,17796,17797,17798,17799,17800,17801,17802,17803,
+17804,17805,17806,17807,17808,17809,17810,17811,17812,17813,17814,17815,
+17816,17817,17818,17819,17820,17821,17822,17823,17824,17825,17826,17827,
+17828,17829,17830,17831,17832,17833,17834,17835,17836,17837,17838,17839,
+17840,17841,17842,17843,17844,17845,17846,17847,17848,17849,17850,17851,
+17852,17853,17854,17855,17856,17857,17858,17859,17860,17861,17862,17863,
+17864,17865,17866,17867,17868,17869,17870,17871,17872,17873,17874,17875,
+17876,17877,17878,17879,17880,17881,17882,17883,17884,17885,17886,17887,
+17888,17889,17890,17891,17892,17893,17894,17895,17896,17897,17898,17899,
+17900,17901,17902,17903,17904,17905,17906,17907,17908,17909,17910,17911,
+17912,17913,17914,17915,17916,17917,17918,17919,17920,17921,17922,17923,
+17924,17925,17926,17927,17928,17929,17930,17931,17932,17933,17934,17935,
+17936,17937,17938,17939,17940,17941,17942,17943,17944,17945,17946,17947,
+17948,17949,17950,17951,17952,17953,17954,17955,17956,17957,17958,17959,
+17960,17961,17962,17963,17964,17965,17966,17967,17968,17969,17970,17971,
+17972,17973,17974,17975,17976,17977,17978,17979,17980,17981,17982,17983,
+17984,17985,17986,17987,17988,17989,17990,17991,17992,17993,17994,17995,
+17996,17997,17998,17999,18000,18001,18002,18003,18004,18005,18006,18007,
+18008,18009,18010,18011,18012,18013,18014,18015,18016,18017,18018,18019,
+18020,18021,18022,18023,18024,18025,18026,18027,18028,18029,18030,18031,
+18032,18033,18034,18035,18036,18037,18038,18039,18040,18041,18042,18043,
+18044,18045,18046,18047,18048,18049,18050,18051,18052,18053,18054,18055,
+18056,18057,18058,18059,18060,18061,18062,18063,18064,18065,18066,18067,
+18068,18069,18070,18071,18072,18073,18074,18075,18076,18077,18078,18079,
+18080,18081,18082,18083,18084,18085,18086,18087,18088,18089,18090,18091,
+18092,18093,18094,18095,18096,18097,18098,18099,18100,18101,18102,18103,
+18104,18105,18106,18107,18108,18109,18110,18111,18112,18113,18114,18115,
+18116,18117,18118,18119,18120,18121,18122,18123,18124,18125,18126,18127,
+18128,18129,18130,18131,18132,18133,18134,18135,18136,18137,18138,18139,
+18140,18141,18142,18143,18144,18145,18146,18147,18148,18149,18150,18151,
+18152,18153,18154,18155,18156,18157,18158,18159,18160,18161,18162,18163,
+18164,18165,18166,18167,18168,18169,18170,18171,18172,18173,18174,18175,
+18176,18177,18178,18179,18180,18181,18182,18183,18184,18185,18186,18187,
+18188,18189,18190,18191,18192,18193,18194,18195,18196,18197,18198,18199,
+18200,18201,18202,18203,18204,18205,18206,18207,18208,18209,18210,18211,
+18212,18213,18214,18215,18216,18217,18218,18219,18220,18221,18222,18223,
+18224,18225,18226,18227,18228,18229,18230,18231,18232,18233,18234,18235,
+18236,18237,18238,18239,18240,18241,18242,18243,18244,18245,18246,18247,
+18248,18249,18250,18251,18252,18253,18254,18255,18256,18257,18258,18259,
+18260,18261,18262,18263,18264,18265,18266,18267,18268,18269,18270,18271,
+18272,18273,18274,18275,18276,18277,18278,18279,18280,18281,18282,18283,
+18284,18285,18286,18287,18288,18289,18290,18291,18292,18293,18294,18295,
+18296,18297,18298,18299,18300,18301,18302,18303,18304,18305,18306,18307,
+18308,18309,18310,18311,18312,18313,18314,18315,18316,18317,18318,18319,
+18320,18321,18322,18323,18324,18325,18326,18327,18328,18329,18330,18331,
+18332,18333,18334,18335,18336,18337,18338,18339,18340,18341,18342,18343,
+18344,18345,18346,18347,18348,18349,18350,18351,18352,18353,18354,18355,
+18356,18357,18358,18359,18360,18361,18362,18363,18364,18365,18366,18367,
+18368,18369,18370,18371,18372,18373,18374,18375,18376,18377,18378,18379,
+18380,18381,18382,18383,18384,18385,18386,18387,18388,18389,18390,18391,
+18392,18393,18394,18395,18396,18397,18398,18399,18400,18401,18402,18403,
+18404,18405,18406,18407,18408,18409,18410,18411,18412,18413,18414,18415,
+18416,18417,18418,18419,18420,18421,18422,18423,18424,18425,18426,18427,
+18428,18429,18430,18431,18432,18433,18434,18435,18436,18437,18438,18439,
+18440,18441,18442,18443,18444,18445,18446,18447,18448,18449,18450,18451,
+18452,18453,18454,18455,18456,18457,18458,18459,18460,18461,18462,18463,
+18464,18465,18466,18467,18468,18469,18470,18471,18472,18473,18474,18475,
+18476,18477,18478,18479,18480,18481,18482,18483,18484,18485,18486,18487,
+18488,18489,18490,18491,18492,18493,18494,18495,18496,18497,18498,18499,
+18500,18501,18502,18503,18504,18505,18506,18507,18508,18509,18510,18511,
+18512,18513,18514,18515,18516,18517,18518,18519,18520,18521,18522,18523,
+18524,18525,18526,18527,18528,18529,18530,18531,18532,18533,18534,18535,
+18536,18537,18538,18539,18540,18541,18542,18543,18544,18545,18546,18547,
+18548,18549,18550,18551,18552,18553,18554,18555,18556,18557,18558,18559,
+18560,18561,18562,18563,18564,18565,18566,18567,18568,18569,18570,18571,
+18572,18573,18574,18575,18576,18577,18578,18579,18580,18581,18582,18583,
+18584,18585,18586,18587,18588,18589,18590,18591,18592,18593,18594,18595,
+18596,18597,18598,18599,18600,18601,18602,18603,18604,18605,18606,18607,
+18608,18609,18610,18611,18612,18613,18614,18615,18616,18617,18618,18619,
+18620,18621,18622,18623,18624,18625,18626,18627,18628,18629,18630,18631,
+18632,18633,18634,18635,18636,18637,18638,18639,18640,18641,18642,18643,
+18644,18645,18646,18647,18648,18649,18650,18651,18652,18653,18654,18655,
+18656,18657,18658,18659,18660,18661,18662,18663,18664,18665,18666,18667,
+18668,18669,18670,18671,18672,18673,18674,18675,18676,18677,18678,18679,
+18680,18681,18682,18683,18684,18685,18686,18687,18688,18689,18690,18691,
+18692,18693,18694,18695,18696,18697,18698,18699,18700,18701,18702,18703,
+18704,18705,18706,18707,18708,18709,18710,18711,18712,18713,18714,18715,
+18716,18717,18718,18719,18720,18721,18722,18723,18724,18725,18726,18727,
+18728,18729,18730,18731,18732,18733,18734,18735,18736,18737,18738,18739,
+18740,18741,18742,18743,18744,18745,18746,18747,18748,18749,18750,18751,
+18752,18753,18754,18755,18756,18757,18758,18759,18760,18761,18762,18763,
+18764,18765,18766,18767,18768,18769,18770,18771,18772,18773,18774,18775,
+18776,18777,18778,18779,18780,18781,18782,18783,18784,18785,18786,18787,
+18788,18789,18790,18791,18792,18793,18794,18795,18796,18797,18798,18799,
+18800,18801,18802,18803,18804,18805,18806,18807,18808,18809,18810,18811,
+18812,18813,18814,18815,18816,18817,18818,18819,18820,18821,18822,18823,
+18824,18825,18826,18827,18828,18829,18830,18831,18832,18833,18834,18835,
+18836,18837,18838,18839,18840,18841,18842,18843,18844,18845,18846,18847,
+18848,18849,18850,18851,18852,18853,18854,18855,18856,18857,18858,18859,
+18860,18861,18862,18863,18864,18865,18866,18867,18868,18869,18870,18871,
+18872,18873,18874,18875,18876,18877,18878,18879,18880,18881,18882,18883,
+18884,18885,18886,18887,18888,18889,18890,18891,18892,18893,18894,18895,
+18896,18897,18898,18899,18900,18901,18902,18903,18904,18905,18906,18907,
+18908,18909,18910,18911,18912,18913,18914,18915,18916,18917,18918,18919,
+18920,18921,18922,18923,18924,18925,18926,18927,18928,18929,18930,18931,
+18932,18933,18934,18935,18936,18937,18938,18939,18940,18941,18942,18943,
+18944,18945,18946,18947,18948,18949,18950,18951,18952,18953,18954,18955,
+18956,18957,18958,18959,18960,18961,18962,18963,18964,18965,18966,18967,
+18968,18969,18970,18971,18972,18973,18974,18975,18976,18977,18978,18979,
+18980,18981,18982,18983,18984,18985,18986,18987,18988,18989,18990,18991,
+18992,18993,18994,18995,18996,18997,18998,18999,19000,19001,19002,19003,
+19004,19005,19006,19007,19008,19009,19010,19011,19012,19013,19014,19015,
+19016,19017,19018,19019,19020,19021,19022,19023,19024,19025,19026,19027,
+19028,19029,19030,19031,19032,19033,19034,19035,19036,19037,19038,19039,
+19040,19041,19042,19043,19044,19045,19046,19047,19048,19049,19050,19051,
+19052,19053,19054,19055,19056,19057,19058,19059,19060,19061,19062,19063,
+19064,19065,19066,19067,19068,19069,19070,19071,19072,19073,19074,19075,
+19076,19077,19078,19079,19080,19081,19082,19083,19084,19085,19086,19087,
+19088,19089,19090,19091,19092,19093,19094,19095,19096,19097,19098,19099,
+19100,19101,19102,19103,19104,19105,19106,19107,19108,19109,19110,19111,
+19112,19113,19114,19115,19116,19117,19118,19119,19120,19121,19122,19123,
+19124,19125,19126,19127,19128,19129,19130,19131,19132,19133,19134,19135,
+19136,19137,19138,19139,19140,19141,19142,19143,19144,19145,19146,19147,
+19148,19149,19150,19151,19152,19153,19154,19155,19156,19157,19158,19159,
+19160,19161,19162,19163,19164,19165,19166,19167,19168,19169,19170,19171,
+19172,19173,19174,19175,19176,19177,19178,19179,19180,19181,19182,19183,
+19184,19185,19186,19187,19188,19189,19190,19191,19192,19193,19194,19195,
+19196,19197,19198,19199,19200,19201,19202,19203,19204,19205,19206,19207,
+19208,19209,19210,19211,19212,19213,19214,19215,19216,19217,19218,19219,
+19220,19221,19222,19223,19224,19225,19226,19227,19228,19229,19230,19231,
+19232,19233,19234,19235,19236,19237,19238,19239,19240,19241,19242,19243,
+19244,19245,19246,19247,19248,19249,19250,19251,19252,19253,19254,19255,
+19256,19257,19258,19259,19260,19261,19262,19263,19264,19265,19266,19267,
+19268,19269,19270,19271,19272,19273,19274,19275,19276,19277,19278,19279,
+19280,19281,19282,19283,19284,19285,19286,19287,19288,19289,19290,19291,
+19292,19293,19294,19295,19296,19297,19298,19299,19300,19301,19302,19303,
+19304,19305,19306,19307,19308,19309,19310,19311,19312,19313,19314,19315,
+19316,19317,19318,19319,19320,19321,19322,19323,19324,19325,19326,19327,
+19328,19329,19330,19331,19332,19333,19334,19335,19336,19337,19338,19339,
+19340,19341,19342,19343,19344,19345,19346,19347,19348,19349,19350,19351,
+19352,19353,19354,19355,19356,19357,19358,19359,19360,19361,19362,19363,
+19364,19365,19366,19367,19368,19369,19370,19371,19372,19373,19374,19375,
+19376,19377,19378,19379,19380,19381,19382,19383,19384,19385,19386,19387,
+19388,19389,19390,19391,19392,19393,19394,19395,19396,19397,19398,19399,
+19400,19401,19402,19403,19404,19405,19406,19407,19408,19409,19410,19411,
+19412,19413,19414,19415,19416,19417,19418,19419,19420,19421,19422,19423,
+19424,19425,19426,19427,19428,19429,19430,19431,19432,19433,19434,19435,
+19436,19437,19438,19439,19440,19441,19442,19443,19444,19445,19446,19447,
+19448,19449,19450,19451,19452,19453,19454,19455,19456,19457,19458,19459,
+19460,19461,19462,19463,19464,19465,19466,19467,19468,19469,19470,19471,
+19472,19473,19474,19475,19476,19477,19478,19479,19480,19481,19482,19483,
+19484,19485,19486,19487,19488,19489,19490,19491,19492,19493,19494,19495,
+19496,19497,19498,19499,19500,19501,19502,19503,19504,19505,19506,19507,
+19508,19509,19510,19511,19512,19513,19514,19515,19516,19517,19518,19519,
+19520,19521,19522,19523,19524,19525,19526,19527,19528,19529,19530,19531,
+19532,19533,19534,19535,19536,19537,19538,19539,19540,19541,19542,19543,
+19544,19545,19546,19547,19548,19549,19550,19551,19552,19553,19554,19555,
+19556,19557,19558,19559,19560,19561,19562,19563,19564,19565,19566,19567,
+19568,19569,19570,19571,19572,19573,19574,19575,19576,19577,19578,19579,
+19580,19581,19582,19583,19584,19585,19586,19587,19588,19589,19590,19591,
+19592,19593,19594,19595,19596,19597,19598,19599,19600,19601,19602,19603,
+19604,19605,19606,19607,19608,19609,19610,19611,19612,19613,19614,19615,
+19616,19617,19618,19619,19620,19621,19622,19623,19624,19625,19626,19627,
+19628,19629,19630,19631,19632,19633,19634,19635,19636,19637,19638,19639,
+19640,19641,19642,19643,19644,19645,19646,19647,19648,19649,19650,19651,
+19652,19653,19654,19655,19656,19657,19658,19659,19660,19661,19662,19663,
+19664,19665,19666,19667,19668,19669,19670,19671,19672,19673,19674,19675,
+19676,19677,19678,19679,19680,19681,19682,19683,19684,19685,19686,19687,
+19688,19689,19690,19691,19692,19693,19694,19695,19696,19697,19698,19699,
+19700,19701,19702,19703,19704,19705,19706,19707,19708,19709,19710,19711,
+19712,19713,19714,19715,19716,19717,19718,19719,19720,19721,19722,19723,
+19724,19725,19726,19727,19728,19729,19730,19731,19732,19733,19734,19735,
+19736,19737,19738,19739,19740,19741,19742,19743,19744,19745,19746,19747,
+19748,19749,19750,19751,19752,19753,19754,19755,19756,19757,19758,19759,
+19760,19761,19762,19763,19764,19765,19766,19767,19768,19769,19770,19771,
+19772,19773,19774,19775,19776,19777,19778,19779,19780,19781,19782,19783,
+19784,19785,19786,19787,19788,19789,19790,19791,19792,19793,19794,19795,
+19796,19797,19798,19799,19800,19801,19802,19803,19804,19805,19806,19807,
+19808,19809,19810,19811,19812,19813,19814,19815,19816,19817,19818,19819,
+19820,19821,19822,19823,19824,19825,19826,19827,19828,19829,19830,19831,
+19832,19833,19834,19835,19836,19837,19838,19839,19840,19841,19842,19843,
+19844,19845,19846,19847,19848,19849,19850,19851,19852,19853,19854,19855,
+19856,19857,19858,19859,19860,19861,19862,19863,19864,19865,19866,19867,
+19868,19869,19870,19871,19872,19873,19874,19875,19876,19877,19878,19879,
+19880,19881,19882,19883,19884,19885,19886,19887,19888,19889,19890,19891,
+19892,19893,19894,19895,19896,19897,19898,19899,19900,19901,19902,19903,
+19904,19905,19906,19907,19908,19909,19910,19911,19912,19913,19914,19915,
+19916,19917,19918,19919,19920,19921,19922,19923,19924,19925,19926,19927,
+19928,19929,19930,19931,19932,19933,19934,19935,19936,19937,19938,19939,
+19940,19941,19942,19943,19944,19945,19946,19947,19948,19949,19950,19951,
+19952,19953,19954,19955,19956,19957,19958,19959,19960,19961,19962,19963,
+19964,19965,19966,19967,19968,19969,19970,19971,19972,19973,19974,19975,
+19976,19977,19978,19979,19980,19981,19982,19983,19984,19985,19986,19987,
+19988,19989,19990,19991,19992,19993,19994,19995,19996,19997,19998,19999,
+20000,20001,20002,20003,20004,20005,20006,20007,20008,20009,20010,20011,
+20012,20013,20014,20015,20016,20017,20018,20019,20020,20021,20022,20023,
+20024,20025,20026,20027,20028,20029,20030,20031,20032,20033,20034,20035,
+20036,20037,20038,20039,20040,20041,20042,20043,20044,20045,20046,20047,
+20048,20049,20050,20051,20052,20053,20054,20055,20056,20057,20058,20059,
+20060,20061,20062,20063,20064,20065,20066,20067,20068,20069,20070,20071,
+20072,20073,20074,20075,20076,20077,20078,20079,20080,20081,20082,20083,
+20084,20085,20086,20087,20088,20089,20090,20091,20092,20093,20094,20095,
+20096,20097,20098,20099,20100,20101,20102,20103,20104,20105,20106,20107,
+20108,20109,20110,20111,20112,20113,20114,20115,20116,20117,20118,20119,
+20120,20121,20122,20123,20124,20125,20126,20127,20128,20129,20130,20131,
+20132,20133,20134,20135,20136,20137,20138,20139,20140,20141,20142,20143,
+20144,20145,20146,20147,20148,20149,20150,20151,20152,20153,20154,20155,
+20156,20157,20158,20159,20160,20161,20162,20163,20164,20165,20166,20167,
+20168,20169,20170,20171,20172,20173,20174,20175,20176,20177,20178,20179,
+20180,20181,20182,20183,20184,20185,20186,20187,20188,20189,20190,20191,
+20192,20193,20194,20195,20196,20197,20198,20199,20200,20201,20202,20203,
+20204,20205,20206,20207,20208,20209,20210,20211,20212,20213,20214,20215,
+20216,20217,20218,20219,20220,20221,20222,20223,20224,20225,20226,20227,
+20228,20229,20230,20231,20232,20233,20234,20235,20236,20237,20238,20239,
+20240,20241,20242,20243,20244,20245,20246,20247,20248,20249,20250,20251,
+20252,20253,20254,20255,20256,20257,20258,20259,20260,20261,20262,20263,
+20264,20265,20266,20267,20268,20269,20270,20271,20272,20273,20274,20275,
+20276,20277,20278,20279,20280,20281,20282,20283,20284,20285,20286,20287,
+20288,20289,20290,20291,20292,20293,20294,20295,20296,20297,20298,20299,
+20300,20301,20302,20303,20304,20305,20306,20307,20308,20309,20310,20311,
+20312,20313,20314,20315,20316,20317,20318,20319,20320,20321,20322,20323,
+20324,20325,20326,20327,20328,20329,20330,20331,20332,20333,20334,20335,
+20336,20337,20338,20339,20340,20341,20342,20343,20344,20345,20346,20347,
+20348,20349,20350,20351,20352,20353,20354,20355,20356,20357,20358,20359,
+20360,20361,20362,20363,20364,20365,20366,20367,20368,20369,20370,20371,
+20372,20373,20374,20375,20376,20377,20378,20379,20380,20381,20382,20383,
+20384,20385,20386,20387,20388,20389,20390,20391,20392,20393,20394,20395,
+20396,20397,20398,20399,20400,20401,20402,20403,20404,20405,20406,20407,
+20408,20409,20410,20411,20412,20413,20414,20415,20416,20417,20418,20419,
+20420,20421,20422,20423,20424,20425,20426,20427,20428,20429,20430,20431,
+20432,20433,20434,20435,20436,20437,20438,20439,20440,20441,20442,20443,
+20444,20445,20446,20447,20448,20449,20450,20451,20452,20453,20454,20455,
+20456,20457,20458,20459,20460,20461,20462,20463,20464,20465,20466,20467,
+20468,20469,20470,20471,20472,20473,20474,20475,20476,20477,20478,20479,
+20480,20481,20482,20483,20484,20485,20486,20487,20488,20489,20490,20491,
+20492,20493,20494,20495,20496,20497,20498,20499,20500,20501,20502,20503,
+20504,20505,20506,20507,20508,20509,20510,20511,20512,20513,20514,20515,
+20516,20517,20518,20519,20520,20521,20522,20523,20524,20525,20526,20527,
+20528,20529,20530,20531,20532,20533,20534,20535,20536,20537,20538,20539,
+20540,20541,20542,20543,20544,20545,20546,20547,20548,20549,20550,20551,
+20552,20553,20554,20555,20556,20557,20558,20559,20560,20561,20562,20563,
+20564,20565,20566,20567,20568,20569,20570,20571,20572,20573,20574,20575,
+20576,20577,20578,20579,20580,20581,20582,20583,20584,20585,20586,20587,
+20588,20589,20590,20591,20592,20593,20594,20595,20596,20597,20598,20599,
+20600,20601,20602,20603,20604,20605,20606,20607,20608,20609,20610,20611,
+20612,20613,20614,20615,20616,20617,20618,20619,20620,20621,20622,20623,
+20624,20625,20626,20627,20628,20629,20630,20631,20632,20633,20634,20635,
+20636,20637,20638,20639,20640,20641,20642,20643,20644,20645,20646,20647,
+20648,20649,20650,20651,20652,20653,20654,20655,20656,20657,20658,20659,
+20660,20661,20662,20663,20664,20665,20666,20667,20668,20669,20670,20671,
+20672,20673,20674,20675,20676,20677,20678,20679,20680,20681,20682,20683,
+20684,20685,20686,20687,20688,20689,20690,20691,20692,20693,20694,20695,
+20696,20697,20698,20699,20700,20701,20702,20703,20704,20705,20706,20707,
+20708,20709,20710,20711,20712,20713,20714,20715,20716,20717,20718,20719,
+20720,20721,20722,20723,20724,20725,20726,20727,20728,20729,20730,20731,
+20732,20733,20734,20735,20736,20737,20738,20739,20740,20741,20742,20743,
+20744,20745,20746,20747,20748,20749,20750,20751,20752,20753,20754,20755,
+20756,20757,20758,20759,20760,20761,20762,20763,20764,20765,20766,20767,
+20768,20769,20770,20771,20772,20773,20774,20775,20776,20777,20778,20779,
+20780,20781,20782,20783,20784,20785,20786,20787,20788,20789,20790,20791,
+20792,20793,20794,20795,20796,20797,20798,20799,20800,20801,20802,20803,
+20804,20805,20806,20807,20808,20809,20810,20811,20812,20813,20814,20815,
+20816,20817,20818,20819,20820,20821,20822,20823,20824,20825,20826,20827,
+20828,20829,20830,20831,20832,20833,20834,20835,20836,20837,20838,20839,
+20840,20841,20842,20843,20844,20845,20846,20847,20848,20849,20850,20851,
+20852,20853,20854,20855,20856,20857,20858,20859,20860,20861,20862,20863,
+20864,20865,20866,20867,20868,20869,20870,20871,20872,20873,20874,20875,
+20876,20877,20878,20879,20880,20881,20882,20883,20884,20885,20886,20887,
+20888,20889,20890,20891,20892,20893,20894,20895,20896,20897,20898,20899,
+20900,20901,20902,20903,20904,20905,20906,20907,20908,20909,20910,20911,
+20912,20913,20914,20915,20916,20917,20918,20919,20920,20921,20922,20923,
+20924,20925,20926,20927,20928,20929,20930,20931,20932,20933,20934,20935,
+20936,20937,20938,20939,20940,20941,20942,20943,20944,20945,20946,20947,
+20948,20949,20950,20951,20952,20953,20954,20955,20956,20957,20958,20959,
+20960,20961,20962,20963,20964,20965,20966,20967,20968,20969,20970,20971,
+20972,20973,20974,20975,20976,20977,20978,20979,20980,20981,20982,20983,
+20984,20985,20986,20987,20988,20989,20990,20991,20992,20993,20994,20995,
+20996,20997,20998,20999,21000,21001,21002,21003,21004,21005,21006,21007,
+21008,21009,21010,21011,21012,21013,21014,21015,21016,21017,21018,21019,
+21020,21021,21022,21023,21024,21025,21026,21027,21028,21029,21030,21031,
+21032,21033,21034,21035,21036,21037,21038,21039,21040,21041,21042,21043,
+21044,21045,21046,21047,21048,21049,21050,21051,21052,21053,21054,21055,
+21056,21057,21058,21059,21060,21061,21062,21063,21064,21065,21066,21067,
+21068,21069,21070,21071,21072,21073,21074,21075,21076,21077,21078,21079,
+21080,21081,21082,21083,21084,21085,21086,21087,21088,21089,21090,21091,
+21092,21093,21094,21095,21096,21097,21098,21099,21100,21101,21102,21103,
+21104,21105,21106,21107,21108,21109,21110,21111,21112,21113,21114,21115,
+21116,21117,21118,21119,21120,21121,21122,21123,21124,21125,21126,21127,
+21128,21129,21130,21131,21132,21133,21134,21135,21136,21137,21138,21139,
+21140,21141,21142,21143,21144,21145,21146,21147,21148,21149,21150,21151,
+21152,21153,21154,21155,21156,21157,21158,21159,21160,21161,21162,21163,
+21164,21165,21166,21167,21168,21169,21170,21171,21172,21173,21174,21175,
+21176,21177,21178,21179,21180,21181,21182,21183,21184,21185,21186,21187,
+21188,21189,21190,21191,21192,21193,21194,21195,21196,21197,21198,21199,
+21200,21201,21202,21203,21204,21205,21206,21207,21208,21209,21210,21211,
+21212,21213,21214,21215,21216,21217,21218,21219,21220,21221,21222,21223,
+21224,21225,21226,21227,21228,21229,21230,21231,21232,21233,21234,21235,
+21236,21237,21238,21239,21240,21241,21242,21243,21244,21245,21246,21247,
+21248,21249,21250,21251,21252,21253,21254,21255,21256,21257,21258,21259,
+21260,21261,21262,21263,21264,21265,21266,21267,21268,21269,21270,21271,
+21272,21273,21274,21275,21276,21277,21278,21279,21280,21281,21282,21283,
+21284,21285,21286,21287,21288,21289,21290,21291,21292,21293,21294,21295,
+21296,21297,21298,21299,21300,21301,21302,21303,21304,21305,21306,21307,
+21308,21309,21310,21311,21312,21313,21314,21315,21316,21317,21318,21319,
+21320,21321,21322,21323,21324,21325,21326,21327,21328,21329,21330,21331,
+21332,21333,21334,21335,21336,21337,21338,21339,21340,21341,21342,21343,
+21344,21345,21346,21347,21348,21349,21350,21351,21352,21353,21354,21355,
+21356,21357,21358,21359,21360,21361,21362,21363,21364,21365,21366,21367,
+21368,21369,21370,21371,21372,21373,21374,21375,21376,21377,21378,21379,
+21380,21381,21382,21383,21384,21385,21386,21387,21388,21389,21390,21391,
+21392,21393,21394,21395,21396,21397,21398,21399,21400,21401,21402,21403,
+21404,21405,21406,21407,21408,21409,21410,21411,21412,21413,21414,21415,
+21416,21417,21418,21419,21420,21421,21422,21423,21424,21425,21426,21427,
+21428,21429,21430,21431,21432,21433,21434,21435,21436,21437,21438,21439,
+21440,21441,21442,21443,21444,21445,21446,21447,21448,21449,21450,21451,
+21452,21453,21454,21455,21456,21457,21458,21459,21460,21461,21462,21463,
+21464,21465,21466,21467,21468,21469,21470,21471,21472,21473,21474,21475,
+21476,21477,21478,21479,21480,21481,21482,21483,21484,21485,21486,21487,
+21488,21489,21490,21491,21492,21493,21494,21495,21496,21497,21498,21499,
+21500,21501,21502,21503,21504,21505,21506,21507,21508,21509,21510,21511,
+21512,21513,21514,21515,21516,21517,21518,21519,21520,21521,21522,21523,
+21524,21525,21526,21527,21528,21529,21530,21531,21532,21533,21534,21535,
+21536,21537,21538,21539,21540,21541,21542,21543,21544,21545,21546,21547,
+21548,21549,21550,21551,21552,21553,21554,21555,21556,21557,21558,21559,
+21560,21561,21562,21563,21564,21565,21566,21567,21568,21569,21570,21571,
+21572,21573,21574,21575,21576,21577,21578,21579,21580,21581,21582,21583,
+21584,21585,21586,21587,21588,21589,21590,21591,21592,21593,21594,21595,
+21596,21597,21598,21599,21600,21601,21602,21603,21604,21605,21606,21607,
+21608,21609,21610,21611,21612,21613,21614,21615,21616,21617,21618,21619,
+21620,21621,21622,21623,21624,21625,21626,21627,21628,21629,21630,21631,
+21632,21633,21634,21635,21636,21637,21638,21639,21640,21641,21642,21643,
+21644,21645,21646,21647,21648,21649,21650,21651,21652,21653,21654,21655,
+21656,21657,21658,21659,21660,21661,21662,21663,21664,21665,21666,21667,
+21668,21669,21670,21671,21672,21673,21674,21675,21676,21677,21678,21679,
+21680,21681,21682,21683,21684,21685,21686,21687,21688,21689,21690,21691,
+21692,21693,21694,21695,21696,21697,21698,21699,21700,21701,21702,21703,
+21704,21705,21706,21707,21708,21709,21710,21711,21712,21713,21714,21715,
+21716,21717,21718,21719,21720,21721,21722,21723,21724,21725,21726,21727,
+21728,21729,21730,21731,21732,21733,21734,21735,21736,21737,21738,21739,
+21740,21741,21742,21743,21744,21745,21746,21747,21748,21749,21750,21751,
+21752,21753,21754,21755,21756,21757,21758,21759,21760,21761,21762,21763,
+21764,21765,21766,21767,21768,21769,21770,21771,21772,21773,21774,21775,
+21776,21777,21778,21779,21780,21781,21782,21783,21784,21785,21786,21787,
+21788,21789,21790,21791,21792,21793,21794,21795,21796,21797,21798,21799,
+21800,21801,21802,21803,21804,21805,21806,21807,21808,21809,21810,21811,
+21812,21813,21814,21815,21816,21817,21818,21819,21820,21821,21822,21823,
+21824,21825,21826,21827,21828,21829,21830,21831,21832,21833,21834,21835,
+21836,21837,21838,21839,21840,21841,21842,21843,21844,21845,21846,21847,
+21848,21849,21850,21851,21852,21853,21854,21855,21856,21857,21858,21859,
+21860,21861,21862,21863,21864,21865,21866,21867,21868,21869,21870,21871,
+21872,21873,21874,21875,21876,21877,21878,21879,21880,21881,21882,21883,
+21884,21885,21886,21887,21888,21889,21890,21891,21892,21893,21894,21895,
+21896,21897,21898,21899,21900,21901,21902,21903,21904,21905,21906,21907,
+21908,21909,21910,21911,21912,21913,21914,21915,21916,21917,21918,21919,
+21920,21921,21922,21923,21924,21925,21926,21927,21928,21929,21930,21931,
+21932,21933,21934,21935,21936,21937,21938,21939,21940,21941,21942,21943,
+21944,21945,21946,21947,21948,21949,21950,21951,21952,21953,21954,21955,
+21956,21957,21958,21959,21960,21961,21962,21963,21964,21965,21966,21967,
+21968,21969,21970,21971,21972,21973,21974,21975,21976,21977,21978,21979,
+21980,21981,21982,21983,21984,21985,21986,21987,21988,21989,21990,21991,
+21992,21993,21994,21995,21996,21997,21998,21999,22000,22001,22002,22003,
+22004,22005,22006,22007,22008,22009,22010,22011,22012,22013,22014,22015,
+22016,22017,22018,22019,22020,22021,22022,22023,22024,22025,22026,22027,
+22028,22029,22030,22031,22032,22033,22034,22035,22036,22037,22038,22039,
+22040,22041,22042,22043,22044,22045,22046,22047,22048,22049,22050,22051,
+22052,22053,22054,22055,22056,22057,22058,22059,22060,22061,22062,22063,
+22064,22065,22066,22067,22068,22069,22070,22071,22072,22073,22074,22075,
+22076,22077,22078,22079,22080,22081,22082,22083,22084,22085,22086,22087,
+22088,22089,22090,22091,22092,22093,22094,22095,22096,22097,22098,22099,
+22100,22101,22102,22103,22104,22105,22106,22107,22108,22109,22110,22111,
+22112,22113,22114,22115,22116,22117,22118,22119,22120,22121,22122,22123,
+22124,22125,22126,22127,22128,22129,22130,22131,22132,22133,22134,22135,
+22136,22137,22138,22139,22140,22141,22142,22143,22144,22145,22146,22147,
+22148,22149,22150,22151,22152,22153,22154,22155,22156,22157,22158,22159,
+22160,22161,22162,22163,22164,22165,22166,22167,22168,22169,22170,22171,
+22172,22173,22174,22175,22176,22177,22178,22179,22180,22181,22182,22183,
+22184,22185,22186,22187,22188,22189,22190,22191,22192,22193,22194,22195,
+22196,22197,22198,22199,22200,22201,22202,22203,22204,22205,22206,22207,
+22208,22209,22210,22211,22212,22213,22214,22215,22216,22217,22218,22219,
+22220,22221,22222,22223,22224,22225,22226,22227,22228,22229,22230,22231,
+22232,22233,22234,22235,22236,22237,22238,22239,22240,22241,22242,22243,
+22244,22245,22246,22247,22248,22249,22250,22251,22252,22253,22254,22255,
+22256,22257,22258,22259,22260,22261,22262,22263,22264,22265,22266,22267,
+22268,22269,22270,22271,22272,22273,22274,22275,22276,22277,22278,22279,
+22280,22281,22282,22283,22284,22285,22286,22287,22288,22289,22290,22291,
+22292,22293,22294,22295,22296,22297,22298,22299,22300,22301,22302,22303,
+22304,22305,22306,22307,22308,22309,22310,22311,22312,22313,22314,22315,
+22316,22317,22318,22319,22320,22321,22322,22323,22324,22325,22326,22327,
+22328,22329,22330,22331,22332,22333,22334,22335,22336,22337,22338,22339,
+22340,22341,22342,22343,22344,22345,22346,22347,22348,22349,22350,22351,
+22352,22353,22354,22355,22356,22357,22358,22359,22360,22361,22362,22363,
+22364,22365,22366,22367,22368,22369,22370,22371,22372,22373,22374,22375,
+22376,22377,22378,22379,22380,22381,22382,22383,22384,22385,22386,22387,
+22388,22389,22390,22391,22392,22393,22394,22395,22396,22397,22398,22399,
+22400,22401,22402,22403,22404,22405,22406,22407,22408,22409,22410,22411,
+22412,22413,22414,22415,22416,22417,22418,22419,22420,22421,22422,22423,
+22424,22425,22426,22427,22428,22429,22430,22431,22432,22433,22434,22435,
+22436,22437,22438,22439,22440,22441,22442,22443,22444,22445,22446,22447,
+22448,22449,22450,22451,22452,22453,22454,22455,22456,22457,22458,22459,
+22460,22461,22462,22463,22464,22465,22466,22467,22468,22469,22470,22471,
+22472,22473,22474,22475,22476,22477,22478,22479,22480,22481,22482,22483,
+22484,22485,22486,22487,22488,22489,22490,22491,22492,22493,22494,22495,
+22496,22497,22498,22499,22500,22501,22502,22503,22504,22505,22506,22507,
+22508,22509,22510,22511,22512,22513,22514,22515,22516,22517,22518,22519,
+22520,22521,22522,22523,22524,22525,22526,22527,22528,22529,22530,22531,
+22532,22533,22534,22535,22536,22537,22538,22539,22540,22541,22542,22543,
+22544,22545,22546,22547,22548,22549,22550,22551,22552,22553,22554,22555,
+22556,22557,22558,22559,22560,22561,22562,22563,22564,22565,22566,22567,
+22568,22569,22570,22571,22572,22573,22574,22575,22576,22577,22578,22579,
+22580,22581,22582,22583,22584,22585,22586,22587,22588,22589,22590,22591,
+22592,22593,22594,22595,22596,22597,22598,22599,22600,22601,22602,22603,
+22604,22605,22606,22607,22608,22609,22610,22611,22612,22613,22614,22615,
+22616,22617,22618,22619,22620,22621,22622,22623,22624,22625,22626,22627,
+22628,22629,22630,22631,22632,22633,22634,22635,22636,22637,22638,22639,
+22640,22641,22642,22643,22644,22645,22646,22647,22648,22649,22650,22651,
+22652,22653,22654,22655,22656,22657,22658,22659,22660,22661,22662,22663,
+22664,22665,22666,22667,22668,22669,22670,22671,22672,22673,22674,22675,
+22676,22677,22678,22679,22680,22681,22682,22683,22684,22685,22686,22687,
+22688,22689,22690,22691,22692,22693,22694,22695,22696,22697,22698,22699,
+22700,22701,22702,22703,22704,22705,22706,22707,22708,22709,22710,22711,
+22712,22713,22714,22715,22716,22717,22718,22719,22720,22721,22722,22723,
+22724,22725,22726,22727,22728,22729,22730,22731,22732,22733,22734,22735,
+22736,22737,22738,22739,22740,22741,22742,22743,22744,22745,22746,22747,
+22748,22749,22750,22751,22752,22753,22754,22755,22756,22757,22758,22759,
+22760,22761,22762,22763,22764,22765,22766,22767,22768,22769,22770,22771,
+22772,22773,22774,22775,22776,22777,22778,22779,22780,22781,22782,22783,
+22784,22785,22786,22787,22788,22789,22790,22791,22792,22793,22794,22795,
+22796,22797,22798,22799,22800,22801,22802,22803,22804,22805,22806,22807,
+22808,22809,22810,22811,22812,22813,22814,22815,22816,22817,22818,22819,
+22820,22821,22822,22823,22824,22825,22826,22827,22828,22829,22830,22831,
+22832,22833,22834,22835,22836,22837,22838,22839,22840,22841,22842,22843,
+22844,22845,22846,22847,22848,22849,22850,22851,22852,22853,22854,22855,
+22856,22857,22858,22859,22860,22861,22862,22863,22864,22865,22866,22867,
+22868,22869,22870,22871,22872,22873,22874,22875,22876,22877,22878,22879,
+22880,22881,22882,22883,22884,22885,22886,22887,22888,22889,22890,22891,
+22892,22893,22894,22895,22896,22897,22898,22899,22900,22901,22902,22903,
+22904,22905,22906,22907,22908,22909,22910,22911,22912,22913,22914,22915,
+22916,22917,22918,22919,22920,22921,22922,22923,22924,22925,22926,22927,
+22928,22929,22930,22931,22932,22933,22934,22935,22936,22937,22938,22939,
+22940,22941,22942,22943,22944,22945,22946,22947,22948,22949,22950,22951,
+22952,22953,22954,22955,22956,22957,22958,22959,22960,22961,22962,22963,
+22964,22965,22966,22967,22968,22969,22970,22971,22972,22973,22974,22975,
+22976,22977,22978,22979,22980,22981,22982,22983,22984,22985,22986,22987,
+22988,22989,22990,22991,22992,22993,22994,22995,22996,22997,22998,22999,
+23000,23001,23002,23003,23004,23005,23006,23007,23008,23009,23010,23011,
+23012,23013,23014,23015,23016,23017,23018,23019,23020,23021,23022,23023,
+23024,23025,23026,23027,23028,23029,23030,23031,23032,23033,23034,23035,
+23036,23037,23038,23039,23040,23041,23042,23043,23044,23045,23046,23047,
+23048,23049,23050,23051,23052,23053,23054,23055,23056,23057,23058,23059,
+23060,23061,23062,23063,23064,23065,23066,23067,23068,23069,23070,23071,
+23072,23073,23074,23075,23076,23077,23078,23079,23080,23081,23082,23083,
+23084,23085,23086,23087,23088,23089,23090,23091,23092,23093,23094,23095,
+23096,23097,23098,23099,23100,23101,23102,23103,23104,23105,23106,23107,
+23108,23109,23110,23111,23112,23113,23114,23115,23116,23117,23118,23119,
+23120,23121,23122,23123,23124,23125,23126,23127,23128,23129,23130,23131,
+23132,23133,23134,23135,23136,23137,23138,23139,23140,23141,23142,23143,
+23144,23145,23146,23147,23148,23149,23150,23151,23152,23153,23154,23155,
+23156,23157,23158,23159,23160,23161,23162,23163,23164,23165,23166,23167,
+23168,23169,23170,23171,23172,23173,23174,23175,23176,23177,23178,23179,
+23180,23181,23182,23183,23184,23185,23186,23187,23188,23189,23190,23191,
+23192,23193,23194,23195,23196,23197,23198,23199,23200,23201,23202,23203,
+23204,23205,23206,23207,23208,23209,23210,23211,23212,23213,23214,23215,
+23216,23217,23218,23219,23220,23221,23222,23223,23224,23225,23226,23227,
+23228,23229,23230,23231,23232,23233,23234,23235,23236,23237,23238,23239,
+23240,23241,23242,23243,23244,23245,23246,23247,23248,23249,23250,23251,
+23252,23253,23254,23255,23256,23257,23258,23259,23260,23261,23262,23263,
+23264,23265,23266,23267,23268,23269,23270,23271,23272,23273,23274,23275,
+23276,23277,23278,23279,23280,23281,23282,23283,23284,23285,23286,23287,
+23288,23289,23290,23291,23292,23293,23294,23295,23296,23297,23298,23299,
+23300,23301,23302,23303,23304,23305,23306,23307,23308,23309,23310,23311,
+23312,23313,23314,23315,23316,23317,23318,23319,23320,23321,23322,23323,
+23324,23325,23326,23327,23328,23329,23330,23331,23332,23333,23334,23335,
+23336,23337,23338,23339,23340,23341,23342,23343,23344,23345,23346,23347,
+23348,23349,23350,23351,23352,23353,23354,23355,23356,23357,23358,23359,
+23360,23361,23362,23363,23364,23365,23366,23367,23368,23369,23370,23371,
+23372,23373,23374,23375,23376,23377,23378,23379,23380,23381,23382,23383,
+23384,23385,23386,23387,23388,23389,23390,23391,23392,23393,23394,23395,
+23396,23397,23398,23399,23400,23401,23402,23403,23404,23405,23406,23407,
+23408,23409,23410,23411,23412,23413,23414,23415,23416,23417,23418,23419,
+23420,23421,23422,23423,23424,23425,23426,23427,23428,23429,23430,23431,
+23432,23433,23434,23435,23436,23437,23438,23439,23440,23441,23442,23443,
+23444,23445,23446,23447,23448,23449,23450,23451,23452,23453,23454,23455,
+23456,23457,23458,23459,23460,23461,23462,23463,23464,23465,23466,23467,
+23468,23469,23470,23471,23472,23473,23474,23475,23476,23477,23478,23479,
+23480,23481,23482,23483,23484,23485,23486,23487,23488,23489,23490,23491,
+23492,23493,23494,23495,23496,23497,23498,23499,23500,23501,23502,23503,
+23504,23505,23506,23507,23508,23509,23510,23511,23512,23513,23514,23515,
+23516,23517,23518,23519,23520,23521,23522,23523,23524,23525,23526,23527,
+23528,23529,23530,23531,23532,23533,23534,23535,23536,23537,23538,23539,
+23540,23541,23542,23543,23544,23545,23546,23547,23548,23549,23550,23551,
+23552,23553,23554,23555,23556,23557,23558,23559,23560,23561,23562,23563,
+23564,23565,23566,23567,23568,23569,23570,23571,23572,23573,23574,23575,
+23576,23577,23578,23579,23580,23581,23582,23583,23584,23585,23586,23587,
+23588,23589,23590,23591,23592,23593,23594,23595,23596,23597,23598,23599,
+23600,23601,23602,23603,23604,23605,23606,23607,23608,23609,23610,23611,
+23612,23613,23614,23615,23616,23617,23618,23619,23620,23621,23622,23623,
+23624,23625,23626,23627,23628,23629,23630,23631,23632,23633,23634,23635,
+23636,23637,23638,23639,23640,23641,23642,23643,23644,23645,23646,23647,
+23648,23649,23650,23651,23652,23653,23654,23655,23656,23657,23658,23659,
+23660,23661,23662,23663,23664,23665,23666,23667,23668,23669,23670,23671,
+23672,23673,23674,23675,23676,23677,23678,23679,23680,23681,23682,23683,
+23684,23685,23686,23687,23688,23689,23690,23691,23692,23693,23694,23695,
+23696,23697,23698,23699,23700,23701,23702,23703,23704,23705,23706,23707,
+23708,23709,23710,23711,23712,23713,23714,23715,23716,23717,23718,23719,
+23720,23721,23722,23723,23724,23725,23726,23727,23728,23729,23730,23731,
+23732,23733,23734,23735,23736,23737,23738,23739,23740,23741,23742,23743,
+23744,23745,23746,23747,23748,23749,23750,23751,23752,23753,23754,23755,
+23756,23757,23758,23759,23760,23761,23762,23763,23764,23765,23766,23767,
+23768,23769,23770,23771,23772,23773,23774,23775,23776,23777,23778,23779,
+23780,23781,23782,23783,23784,23785,23786,23787,23788,23789,23790,23791,
+23792,23793,23794,23795,23796,23797,23798,23799,23800,23801,23802,23803,
+23804,23805,23806,23807,23808,23809,23810,23811,23812,23813,23814,23815,
+23816,23817,23818,23819,23820,23821,23822,23823,23824,23825,23826,23827,
+23828,23829,23830,23831,23832,23833,23834,23835,23836,23837,23838,23839,
+23840,23841,23842,23843,23844,23845,23846,23847,23848,23849,23850,23851,
+23852,23853,23854,23855,23856,23857,23858,23859,23860,23861,23862,23863,
+23864,23865,23866,23867,23868,23869,23870,23871,23872,23873,23874,23875,
+23876,23877,23878,23879,23880,23881,23882,23883,23884,23885,23886,23887,
+23888,23889,23890,23891,23892,23893,23894,23895,23896,23897,23898,23899,
+23900,23901,23902,23903,23904,23905,23906,23907,23908,23909,23910,23911,
+23912,23913,23914,23915,23916,23917,23918,23919,23920,23921,23922,23923,
+23924,23925,23926,23927,23928,23929,23930,23931,23932,23933,23934,23935,
+23936,23937,23938,23939,23940,23941,23942,23943,23944,23945,23946,23947,
+23948,23949,23950,23951,23952,23953,23954,23955,23956,23957,23958,23959,
+23960,23961,23962,23963,23964,23965,23966,23967,23968,23969,23970,23971,
+23972,23973,23974,23975,23976,23977,23978,23979,23980,23981,23982,23983,
+23984,23985,23986,23987,23988,23989,23990,23991,23992,23993,23994,23995,
+23996,23997,23998,23999,24000,24001,24002,24003,24004,24005,24006,24007,
+24008,24009,24010,24011,24012,24013,24014,24015,24016,24017,24018,24019,
+24020,24021,24022,24023,24024,24025,24026,24027,24028,24029,24030,24031,
+24032,24033,24034,24035,24036,24037,24038,24039,24040,24041,24042,24043,
+24044,24045,24046,24047,24048,24049,24050,24051,24052,24053,24054,24055,
+24056,24057,24058,24059,24060,24061,24062,24063,24064,24065,24066,24067,
+24068,24069,24070,24071,24072,24073,24074,24075,24076,24077,24078,24079,
+24080,24081,24082,24083,24084,24085,24086,24087,24088,24089,24090,24091,
+24092,24093,24094,24095,24096,24097,24098,24099,24100,24101,24102,24103,
+24104,24105,24106,24107,24108,24109,24110,24111,24112,24113,24114,24115,
+24116,24117,24118,24119,24120,24121,24122,24123,24124,24125,24126,24127,
+24128,24129,24130,24131,24132,24133,24134,24135,24136,24137,24138,24139,
+24140,24141,24142,24143,24144,24145,24146,24147,24148,24149,24150,24151,
+24152,24153,24154,24155,24156,24157,24158,24159,24160,24161,24162,24163,
+24164,24165,24166,24167,24168,24169,24170,24171,24172,24173,24174,24175,
+24176,24177,24178,24179,24180,24181,24182,24183,24184,24185,24186,24187,
+24188,24189,24190,24191,24192,24193,24194,24195,24196,24197,24198,24199,
+24200,24201,24202,24203,24204,24205,24206,24207,24208,24209,24210,24211,
+24212,24213,24214,24215,24216,24217,24218,24219,24220,24221,24222,24223,
+24224,24225,24226,24227,24228,24229,24230,24231,24232,24233,24234,24235,
+24236,24237,24238,24239,24240,24241,24242,24243,24244,24245,24246,24247,
+24248,24249,24250,24251,24252,24253,24254,24255,24256,24257,24258,24259,
+24260,24261,24262,24263,24264,24265,24266,24267,24268,24269,24270,24271,
+24272,24273,24274,24275,24276,24277,24278,24279,24280,24281,24282,24283,
+24284,24285,24286,24287,24288,24289,24290,24291,24292,24293,24294,24295,
+24296,24297,24298,24299,24300,24301,24302,24303,24304,24305,24306,24307,
+24308,24309,24310,24311,24312,24313,24314,24315,24316,24317,24318,24319,
+24320,24321,24322,24323,24324,24325,24326,24327,24328,24329,24330,24331,
+24332,24333,24334,24335,24336,24337,24338,24339,24340,24341,24342,24343,
+24344,24345,24346,24347,24348,24349,24350,24351,24352,24353,24354,24355,
+24356,24357,24358,24359,24360,24361,24362,24363,24364,24365,24366,24367,
+24368,24369,24370,24371,24372,24373,24374,24375,24376,24377,24378,24379,
+24380,24381,24382,24383,24384,24385,24386,24387,24388,24389,24390,24391,
+24392,24393,24394,24395,24396,24397,24398,24399,24400,24401,24402,24403,
+24404,24405,24406,24407,24408,24409,24410,24411,24412,24413,24414,24415,
+24416,24417,24418,24419,24420,24421,24422,24423,24424,24425,24426,24427,
+24428,24429,24430,24431,24432,24433,24434,24435,24436,24437,24438,24439,
+24440,24441,24442,24443,24444,24445,24446,24447,24448,24449,24450,24451,
+24452,24453,24454,24455,24456,24457,24458,24459,24460,24461,24462,24463,
+24464,24465,24466,24467,24468,24469,24470,24471,24472,24473,24474,24475,
+24476,24477,24478,24479,24480,24481,24482,24483,24484,24485,24486,24487,
+24488,24489,24490,24491,24492,24493,24494,24495,24496,24497,24498,24499,
+24500,24501,24502,24503,24504,24505,24506,24507,24508,24509,24510,24511,
+24512,24513,24514,24515,24516,24517,24518,24519,24520,24521,24522,24523,
+24524,24525,24526,24527,24528,24529,24530,24531,24532,24533,24534,24535,
+24536,24537,24538,24539,24540,24541,24542,24543,24544,24545,24546,24547,
+24548,24549,24550,24551,24552,24553,24554,24555,24556,24557,24558,24559,
+24560,24561,24562,24563,24564,24565,24566,24567,24568,24569,24570,24571,
+24572,24573,24574,24575,24576,24577,24578,24579,24580,24581,24582,24583,
+24584,24585,24586,24587,24588,24589,24590,24591,24592,24593,24594,24595,
+24596,24597,24598,24599,24600,24601,24602,24603,24604,24605,24606,24607,
+24608,24609,24610,24611,24612,24613,24614,24615,24616,24617,24618,24619,
+24620,24621,24622,24623,24624,24625,24626,24627,24628,24629,24630,24631,
+24632,24633,24634,24635,24636,24637,24638,24639,24640,24641,24642,24643,
+24644,24645,24646,24647,24648,24649,24650,24651,24652,24653,24654,24655,
+24656,24657,24658,24659,24660,24661,24662,24663,24664,24665,24666,24667,
+24668,24669,24670,24671,24672,24673,24674,24675,24676,24677,24678,24679,
+24680,24681,24682,24683,24684,24685,24686,24687,24688,24689,24690,24691,
+24692,24693,24694,24695,24696,24697,24698,24699,24700,24701,24702,24703,
+24704,24705,24706,24707,24708,24709,24710,24711,24712,24713,24714,24715,
+24716,24717,24718,24719,24720,24721,24722,24723,24724,24725,24726,24727,
+24728,24729,24730,24731,24732,24733,24734,24735,24736,24737,24738,24739,
+24740,24741,24742,24743,24744,24745,24746,24747,24748,24749,24750,24751,
+24752,24753,24754,24755,24756,24757,24758,24759,24760,24761,24762,24763,
+24764,24765,24766,24767,24768,24769,24770,24771,24772,24773,24774,24775,
+24776,24777,24778,24779,24780,24781,24782,24783,24784,24785,24786,24787,
+24788,24789,24790,24791,24792,24793,24794,24795,24796,24797,24798,24799,
+24800,24801,24802,24803,24804,24805,24806,24807,24808,24809,24810,24811,
+24812,24813,24814,24815,24816,24817,24818,24819,24820,24821,24822,24823,
+24824,24825,24826,24827,24828,24829,24830,24831,24832,24833,24834,24835,
+24836,24837,24838,24839,24840,24841,24842,24843,24844,24845,24846,24847,
+24848,24849,24850,24851,24852,24853,24854,24855,24856,24857,24858,24859,
+24860,24861,24862,24863,24864,24865,24866,24867,24868,24869,24870,24871,
+24872,24873,24874,24875,24876,24877,24878,24879,24880,24881,24882,24883,
+24884,24885,24886,24887,24888,24889,24890,24891,24892,24893,24894,24895,
+24896,24897,24898,24899,24900,24901,24902,24903,24904,24905,24906,24907,
+24908,24909,24910,24911,24912,24913,24914,24915,24916,24917,24918,24919,
+24920,24921,24922,24923,24924,24925,24926,24927,24928,24929,24930,24931,
+24932,24933,24934,24935,24936,24937,24938,24939,24940,24941,24942,24943,
+24944,24945,24946,24947,24948,24949,24950,24951,24952,24953,24954,24955,
+24956,24957,24958,24959,24960,24961,24962,24963,24964,24965,24966,24967,
+24968,24969,24970,24971,24972,24973,24974,24975,24976,24977,24978,24979,
+24980,24981,24982,24983,24984,24985,24986,24987,24988,24989,24990,24991,
+24992,24993,24994,24995,24996,24997,24998,24999,25000,25001,25002,25003,
+25004,25005,25006,25007,25008,25009,25010,25011,25012,25013,25014,25015,
+25016,25017,25018,25019,25020,25021,25022,25023,25024,25025,25026,25027,
+25028,25029,25030,25031,25032,25033,25034,25035,25036,25037,25038,25039,
+25040,25041,25042,25043,25044,25045,25046,25047,25048,25049,25050,25051,
+25052,25053,25054,25055,25056,25057,25058,25059,25060,25061,25062,25063,
+25064,25065,25066,25067,25068,25069,25070,25071,25072,25073,25074,25075,
+25076,25077,25078,25079,25080,25081,25082,25083,25084,25085,25086,25087,
+25088,25089,25090,25091,25092,25093,25094,25095,25096,25097,25098,25099,
+25100,25101,25102,25103,25104,25105,25106,25107,25108,25109,25110,25111,
+25112,25113,25114,25115,25116,25117,25118,25119,25120,25121,25122,25123,
+25124,25125,25126,25127,25128,25129,25130,25131,25132,25133,25134,25135,
+25136,25137,25138,25139,25140,25141,25142,25143,25144,25145,25146,25147,
+25148,25149,25150,25151,25152,25153,25154,25155,25156,25157,25158,25159,
+25160,25161,25162,25163,25164,25165,25166,25167,25168,25169,25170,25171,
+25172,25173,25174,25175,25176,25177,25178,25179,25180,25181,25182,25183,
+25184,25185,25186,25187,25188,25189,25190,25191,25192,25193,25194,25195,
+25196,25197,25198,25199,25200,25201,25202,25203,25204,25205,25206,25207,
+25208,25209,25210,25211,25212,25213,25214,25215,25216,25217,25218,25219,
+25220,25221,25222,25223,25224,25225,25226,25227,25228,25229,25230,25231,
+25232,25233,25234,25235,25236,25237,25238,25239,25240,25241,25242,25243,
+25244,25245,25246,25247,25248,25249,25250,25251,25252,25253,25254,25255,
+25256,25257,25258,25259,25260,25261,25262,25263,25264,25265,25266,25267,
+25268,25269,25270,25271,25272,25273,25274,25275,25276,25277,25278,25279,
+25280,25281,25282,25283,25284,25285,25286,25287,25288,25289,25290,25291,
+25292,25293,25294,25295,25296,25297,25298,25299,25300,25301,25302,25303,
+25304,25305,25306,25307,25308,25309,25310,25311,25312,25313,25314,25315,
+25316,25317,25318,25319,25320,25321,25322,25323,25324,25325,25326,25327,
+25328,25329,25330,25331,25332,25333,25334,25335,25336,25337,25338,25339,
+25340,25341,25342,25343,25344,25345,25346,25347,25348,25349,25350,25351,
+25352,25353,25354,25355,25356,25357,25358,25359,25360,25361,25362,25363,
+25364,25365,25366,25367,25368,25369,25370,25371,25372,25373,25374,25375,
+25376,25377,25378,25379,25380,25381,25382,25383,25384,25385,25386,25387,
+25388,25389,25390,25391,25392,25393,25394,25395,25396,25397,25398,25399,
+25400,25401,25402,25403,25404,25405,25406,25407,25408,25409,25410,25411,
+25412,25413,25414,25415,25416,25417,25418,25419,25420,25421,25422,25423,
+25424,25425,25426,25427,25428,25429,25430,25431,25432,25433,25434,25435,
+25436,25437,25438,25439,25440,25441,25442,25443,25444,25445,25446,25447,
+25448,25449,25450,25451,25452,25453,25454,25455,25456,25457,25458,25459,
+25460,25461,25462,25463,25464,25465,25466,25467,25468,25469,25470,25471,
+25472,25473,25474,25475,25476,25477,25478,25479,25480,25481,25482,25483,
+25484,25485,25486,25487,25488,25489,25490,25491,25492,25493,25494,25495,
+25496,25497,25498,25499,25500,25501,25502,25503,25504,25505,25506,25507,
+25508,25509,25510,25511,25512,25513,25514,25515,25516,25517,25518,25519,
+25520,25521,25522,25523,25524,25525,25526,25527,25528,25529,25530,25531,
+25532,25533,25534,25535,25536,25537,25538,25539,25540,25541,25542,25543,
+25544,25545,25546,25547,25548,25549,25550,25551,25552,25553,25554,25555,
+25556,25557,25558,25559,25560,25561,25562,25563,25564,25565,25566,25567,
+25568,25569,25570,25571,25572,25573,25574,25575,25576,25577,25578,25579,
+25580,25581,25582,25583,25584,25585,25586,25587,25588,25589,25590,25591,
+25592,25593,25594,25595,25596,25597,25598,25599,25600,25601,25602,25603,
+25604,25605,25606,25607,25608,25609,25610,25611,25612,25613,25614,25615,
+25616,25617,25618,25619,25620,25621,25622,25623,25624,25625,25626,25627,
+25628,25629,25630,25631,25632,25633,25634,25635,25636,25637,25638,25639,
+25640,25641,25642,25643,25644,25645,25646,25647,25648,25649,25650,25651,
+25652,25653,25654,25655,25656,25657,25658,25659,25660,25661,25662,25663,
+25664,25665,25666,25667,25668,25669,25670,25671,25672,25673,25674,25675,
+25676,25677,25678,25679,25680,25681,25682,25683,25684,25685,25686,25687,
+25688,25689,25690,25691,25692,25693,25694,25695,25696,25697,25698,25699,
+25700,25701,25702,25703,25704,25705,25706,25707,25708,25709,25710,25711,
+25712,25713,25714,25715,25716,25717,25718,25719,25720,25721,25722,25723,
+25724,25725,25726,25727,25728,25729,25730,25731,25732,25733,25734,25735,
+25736,25737,25738,25739,25740,25741,25742,25743,25744,25745,25746,25747,
+25748,25749,25750,25751,25752,25753,25754,25755,25756,25757,25758,25759,
+25760,25761,25762,25763,25764,25765,25766,25767,25768,25769,25770,25771,
+25772,25773,25774,25775,25776,25777,25778,25779,25780,25781,25782,25783,
+25784,25785,25786,25787,25788,25789,25790,25791,25792,25793,25794,25795,
+25796,25797,25798,25799,25800,25801,25802,25803,25804,25805,25806,25807,
+25808,25809,25810,25811,25812,25813,25814,25815,25816,25817,25818,25819,
+25820,25821,25822,25823,25824,25825,25826,25827,25828,25829,25830,25831,
+25832,25833,25834,25835,25836,25837,25838,25839,25840,25841,25842,25843,
+25844,25845,25846,25847,25848,25849,25850,25851,25852,25853,25854,25855,
+25856,25857,25858,25859,25860,25861,25862,25863,25864,25865,25866,25867,
+25868,25869,25870,25871,25872,25873,25874,25875,25876,25877,25878,25879,
+25880,25881,25882,25883,25884,25885,25886,25887,25888,25889,25890,25891,
+25892,25893,25894,25895,25896,25897,25898,25899,25900,25901,25902,25903,
+25904,25905,25906,25907,25908,25909,25910,25911,25912,25913,25914,25915,
+25916,25917,25918,25919,25920,25921,25922,25923,25924,25925,25926,25927,
+25928,25929,25930,25931,25932,25933,25934,25935,25936,25937,25938,25939,
+25940,25941,25942,25943,25944,25945,25946,25947,25948,25949,25950,25951,
+25952,25953,25954,25955,25956,25957,25958,25959,25960,25961,25962,25963,
+25964,25965,25966,25967,25968,25969,25970,25971,25972,25973,25974,25975,
+25976,25977,25978,25979,25980,25981,25982,25983,25984,25985,25986,25987,
+25988,25989,25990,25991,25992,25993,25994,25995,25996,25997,25998,25999,
+26000,26001,26002,26003,26004,26005,26006,26007,26008,26009,26010,26011,
+26012,26013,26014,26015,26016,26017,26018,26019,26020,26021,26022,26023,
+26024,26025,26026,26027,26028,26029,26030,26031,26032,26033,26034,26035,
+26036,26037,26038,26039,26040,26041,26042,26043,26044,26045,26046,26047,
+26048,26049,26050,26051,26052,26053,26054,26055,26056,26057,26058,26059,
+26060,26061,26062,26063,26064,26065,26066,26067,26068,26069,26070,26071,
+26072,26073,26074,26075,26076,26077,26078,26079,26080,26081,26082,26083,
+26084,26085,26086,26087,26088,26089,26090,26091,26092,26093,26094,26095,
+26096,26097,26098,26099,26100,26101,26102,26103,26104,26105,26106,26107,
+26108,26109,26110,26111,26112,26113,26114,26115,26116,26117,26118,26119,
+26120,26121,26122,26123,26124,26125,26126,26127,26128,26129,26130,26131,
+26132,26133,26134,26135,26136,26137,26138,26139,26140,26141,26142,26143,
+26144,26145,26146,26147,26148,26149,26150,26151,26152,26153,26154,26155,
+26156,26157,26158,26159,26160,26161,26162,26163,26164,26165,26166,26167,
+26168,26169,26170,26171,26172,26173,26174,26175,26176,26177,26178,26179,
+26180,26181,26182,26183,26184,26185,26186,26187,26188,26189,26190,26191,
+26192,26193,26194,26195,26196,26197,26198,26199,26200,26201,26202,26203,
+26204,26205,26206,26207,26208,26209,26210,26211,26212,26213,26214,26215,
+26216,26217,26218,26219,26220,26221,26222,26223,26224,26225,26226,26227,
+26228,26229,26230,26231,26232,26233,26234,26235,26236,26237,26238,26239,
+26240,26241,26242,26243,26244,26245,26246,26247,26248,26249,26250,26251,
+26252,26253,26254,26255,26256,26257,26258,26259,26260,26261,26262,26263,
+26264,26265,26266,26267,26268,26269,26270,26271,26272,26273,26274,26275,
+26276,26277,26278,26279,26280,26281,26282,26283,26284,26285,26286,26287,
+26288,26289,26290,26291,26292,26293,26294,26295,26296,26297,26298,26299,
+26300,26301,26302,26303,26304,26305,26306,26307,26308,26309,26310,26311,
+26312,26313,26314,26315,26316,26317,26318,26319,26320,26321,26322,26323,
+26324,26325,26326,26327,26328,26329,26330,26331,26332,26333,26334,26335,
+26336,26337,26338,26339,26340,26341,26342,26343,26344,26345,26346,26347,
+26348,26349,26350,26351,26352,26353,26354,26355,26356,26357,26358,26359,
+26360,26361,26362,26363,26364,26365,26366,26367,26368,26369,26370,26371,
+26372,26373,26374,26375,26376,26377,26378,26379,26380,26381,26382,26383,
+26384,26385,26386,26387,26388,26389,26390,26391,26392,26393,26394,26395,
+26396,26397,26398,26399,26400,26401,26402,26403,26404,26405,26406,26407,
+26408,26409,26410,26411,26412,26413,26414,26415,26416,26417,26418,26419,
+26420,26421,26422,26423,26424,26425,26426,26427,26428,26429,26430,26431,
+26432,26433,26434,26435,26436,26437,26438,26439,26440,26441,26442,26443,
+26444,26445,26446,26447,26448,26449,26450,26451,26452,26453,26454,26455,
+26456,26457,26458,26459,26460,26461,26462,26463,26464,26465,26466,26467,
+26468,26469,26470,26471,26472,26473,26474,26475,26476,26477,26478,26479,
+26480,26481,26482,26483,26484,26485,26486,26487,26488,26489,26490,26491,
+26492,26493,26494,26495,26496,26497,26498,26499,26500,26501,26502,26503,
+26504,26505,26506,26507,26508,26509,26510,26511,26512,26513,26514,26515,
+26516,26517,26518,26519,26520,26521,26522,26523,26524,26525,26526,26527,
+26528,26529,26530,26531,26532,26533,26534,26535,26536,26537,26538,26539,
+26540,26541,26542,26543,26544,26545,26546,26547,26548,26549,26550,26551,
+26552,26553,26554,26555,26556,26557,26558,26559,26560,26561,26562,26563,
+26564,26565,26566,26567,26568,26569,26570,26571,26572,26573,26574,26575,
+26576,26577,26578,26579,26580,26581,26582,26583,26584,26585,26586,26587,
+26588,26589,26590,26591,26592,26593,26594,26595,26596,26597,26598,26599,
+26600,26601,26602,26603,26604,26605,26606,26607,26608,26609,26610,26611,
+26612,26613,26614,26615,26616,26617,26618,26619,26620,26621,26622,26623,
+26624,26625,26626,26627,26628,26629,26630,26631,26632,26633,26634,26635,
+26636,26637,26638,26639,26640,26641,26642,26643,26644,26645,26646,26647,
+26648,26649,26650,26651,26652,26653,26654,26655,26656,26657,26658,26659,
+26660,26661,26662,26663,26664,26665,26666,26667,26668,26669,26670,26671,
+26672,26673,26674,26675,26676,26677,26678,26679,26680,26681,26682,26683,
+26684,26685,26686,26687,26688,26689,26690,26691,26692,26693,26694,26695,
+26696,26697,26698,26699,26700,26701,26702,26703,26704,26705,26706,26707,
+26708,26709,26710,26711,26712,26713,26714,26715,26716,26717,26718,26719,
+26720,26721,26722,26723,26724,26725,26726,26727,26728,26729,26730,26731,
+26732,26733,26734,26735,26736,26737,26738,26739,26740,26741,26742,26743,
+26744,26745,26746,26747,26748,26749,26750,26751,26752,26753,26754,26755,
+26756,26757,26758,26759,26760,26761,26762,26763,26764,26765,26766,26767,
+26768,26769,26770,26771,26772,26773,26774,26775,26776,26777,26778,26779,
+26780,26781,26782,26783,26784,26785,26786,26787,26788,26789,26790,26791,
+26792,26793,26794,26795,26796,26797,26798,26799,26800,26801,26802,26803,
+26804,26805,26806,26807,26808,26809,26810,26811,26812,26813,26814,26815,
+26816,26817,26818,26819,26820,26821,26822,26823,26824,26825,26826,26827,
+26828,26829,26830,26831,26832,26833,26834,26835,26836,26837,26838,26839,
+26840,26841,26842,26843,26844,26845,26846,26847,26848,26849,26850,26851,
+26852,26853,26854,26855,26856,26857,26858,26859,26860,26861,26862,26863,
+26864,26865,26866,26867,26868,26869,26870,26871,26872,26873,26874,26875,
+26876,26877,26878,26879,26880,26881,26882,26883,26884,26885,26886,26887,
+26888,26889,26890,26891,26892,26893,26894,26895,26896,26897,26898,26899,
+26900,26901,26902,26903,26904,26905,26906,26907,26908,26909,26910,26911,
+26912,26913,26914,26915,26916,26917,26918,26919,26920,26921,26922,26923,
+26924,26925,26926,26927,26928,26929,26930,26931,26932,26933,26934,26935,
+26936,26937,26938,26939,26940,26941,26942,26943,26944,26945,26946,26947,
+26948,26949,26950,26951,26952,26953,26954,26955,26956,26957,26958,26959,
+26960,26961,26962,26963,26964,26965,26966,26967,26968,26969,26970,26971,
+26972,26973,26974,26975,26976,26977,26978,26979,26980,26981,26982,26983,
+26984,26985,26986,26987,26988,26989,26990,26991,26992,26993,26994,26995,
+26996,26997,26998,26999,27000,27001,27002,27003,27004,27005,27006,27007,
+27008,27009,27010,27011,27012,27013,27014,27015,27016,27017,27018,27019,
+27020,27021,27022,27023,27024,27025,27026,27027,27028,27029,27030,27031,
+27032,27033,27034,27035,27036,27037,27038,27039,27040,27041,27042,27043,
+27044,27045,27046,27047,27048,27049,27050,27051,27052,27053,27054,27055,
+27056,27057,27058,27059,27060,27061,27062,27063,27064,27065,27066,27067,
+27068,27069,27070,27071,27072,27073,27074,27075,27076,27077,27078,27079,
+27080,27081,27082,27083,27084,27085,27086,27087,27088,27089,27090,27091,
+27092,27093,27094,27095,27096,27097,27098,27099,27100,27101,27102,27103,
+27104,27105,27106,27107,27108,27109,27110,27111,27112,27113,27114,27115,
+27116,27117,27118,27119,27120,27121,27122,27123,27124,27125,27126,27127,
+27128,27129,27130,27131,27132,27133,27134,27135,27136,27137,27138,27139,
+27140,27141,27142,27143,27144,27145,27146,27147,27148,27149,27150,27151,
+27152,27153,27154,27155,27156,27157,27158,27159,27160,27161,27162,27163,
+27164,27165,27166,27167,27168,27169,27170,27171,27172,27173,27174,27175,
+27176,27177,27178,27179,27180,27181,27182,27183,27184,27185,27186,27187,
+27188,27189,27190,27191,27192,27193,27194,27195,27196,27197,27198,27199,
+27200,27201,27202,27203,27204,27205,27206,27207,27208,27209,27210,27211,
+27212,27213,27214,27215,27216,27217,27218,27219,27220,27221,27222,27223,
+27224,27225,27226,27227,27228,27229,27230,27231,27232,27233,27234,27235,
+27236,27237,27238,27239,27240,27241,27242,27243,27244,27245,27246,27247,
+27248,27249,27250,27251,27252,27253,27254,27255,27256,27257,27258,27259,
+27260,27261,27262,27263,27264,27265,27266,27267,27268,27269,27270,27271,
+27272,27273,27274,27275,27276,27277,27278,27279,27280,27281,27282,27283,
+27284,27285,27286,27287,27288,27289,27290,27291,27292,27293,27294,27295,
+27296,27297,27298,27299,27300,27301,27302,27303,27304,27305,27306,27307,
+27308,27309,27310,27311,27312,27313,27314,27315,27316,27317,27318,27319,
+27320,27321,27322,27323,27324,27325,27326,27327,27328,27329,27330,27331,
+27332,27333,27334,27335,27336,27337,27338,27339,27340,27341,27342,27343,
+27344,27345,27346,27347,27348,27349,27350,27351,27352,27353,27354,27355,
+27356,27357,27358,27359,27360,27361,27362,27363,27364,27365,27366,27367,
+27368,27369,27370,27371,27372,27373,27374,27375,27376,27377,27378,27379,
+27380,27381,27382,27383,27384,27385,27386,27387,27388,27389,27390,27391,
+27392,27393,27394,27395,27396,27397,27398,27399,27400,27401,27402,27403,
+27404,27405,27406,27407,27408,27409,27410,27411,27412,27413,27414,27415,
+27416,27417,27418,27419,27420,27421,27422,27423,27424,27425,27426,27427,
+27428,27429,27430,27431,27432,27433,27434,27435,27436,27437,27438,27439,
+27440,27441,27442,27443,27444,27445,27446,27447,27448,27449,27450,27451,
+27452,27453,27454,27455,27456,27457,27458,27459,27460,27461,27462,27463,
+27464,27465,27466,27467,27468,27469,27470,27471,27472,27473,27474,27475,
+27476,27477,27478,27479,27480,27481,27482,27483,27484,27485,27486,27487,
+27488,27489,27490,27491,27492,27493,27494,27495,27496,27497,27498,27499,
+27500,27501,27502,27503,27504,27505,27506,27507,27508,27509,27510,27511,
+27512,27513,27514,27515,27516,27517,27518,27519,27520,27521,27522,27523,
+27524,27525,27526,27527,27528,27529,27530,27531,27532,27533,27534,27535,
+27536,27537,27538,27539,27540,27541,27542,27543,27544,27545,27546,27547,
+27548,27549,27550,27551,27552,27553,27554,27555,27556,27557,27558,27559,
+27560,27561,27562,27563,27564,27565,27566,27567,27568,27569,27570,27571,
+27572,27573,27574,27575,27576,27577,27578,27579,27580,27581,27582,27583,
+27584,27585,27586,27587,27588,27589,27590,27591,27592,27593,27594,27595,
+27596,27597,27598,27599,27600,27601,27602,27603,27604,27605,27606,27607,
+27608,27609,27610,27611,27612,27613,27614,27615,27616,27617,27618,27619,
+27620,27621,27622,27623,27624,27625,27626,27627,27628,27629,27630,27631,
+27632,27633,27634,27635,27636,27637,27638,27639,27640,27641,27642,27643,
+27644,27645,27646,27647,27648,27649,27650,27651,27652,27653,27654,27655,
+27656,27657,27658,27659,27660,27661,27662,27663,27664,27665,27666,27667,
+27668,27669,27670,27671,27672,27673,27674,27675,27676,27677,27678,27679,
+27680,27681,27682,27683,27684,27685,27686,27687,27688,27689,27690,27691,
+27692,27693,27694,27695,27696,27697,27698,27699,27700,27701,27702,27703,
+27704,27705,27706,27707,27708,27709,27710,27711,27712,27713,27714,27715,
+27716,27717,27718,27719,27720,27721,27722,27723,27724,27725,27726,27727,
+27728,27729,27730,27731,27732,27733,27734,27735,27736,27737,27738,27739,
+27740,27741,27742,27743,27744,27745,27746,27747,27748,27749,27750,27751,
+27752,27753,27754,27755,27756,27757,27758,27759,27760,27761,27762,27763,
+27764,27765,27766,27767,27768,27769,27770,27771,27772,27773,27774,27775,
+27776,27777,27778,27779,27780,27781,27782,27783,27784,27785,27786,27787,
+27788,27789,27790,27791,27792,27793,27794,27795,27796,27797,27798,27799,
+27800,27801,27802,27803,27804,27805,27806,27807,27808,27809,27810,27811,
+27812,27813,27814,27815,27816,27817,27818,27819,27820,27821,27822,27823,
+27824,27825,27826,27827,27828,27829,27830,27831,27832,27833,27834,27835,
+27836,27837,27838,27839,27840,27841,27842,27843,27844,27845,27846,27847,
+27848,27849,27850,27851,27852,27853,27854,27855,27856,27857,27858,27859,
+27860,27861,27862,27863,27864,27865,27866,27867,27868,27869,27870,27871,
+27872,27873,27874,27875,27876,27877,27878,27879,27880,27881,27882,27883,
+27884,27885,27886,27887,27888,27889,27890,27891,27892,27893,27894,27895,
+27896,27897,27898,27899,27900,27901,27902,27903,27904,27905,27906,27907,
+27908,27909,27910,27911,27912,27913,27914,27915,27916,27917,27918,27919,
+27920,27921,27922,27923,27924,27925,27926,27927,27928,27929,27930,27931,
+27932,27933,27934,27935,27936,27937,27938,27939,27940,27941,27942,27943,
+27944,27945,27946,27947,27948,27949,27950,27951,27952,27953,27954,27955,
+27956,27957,27958,27959,27960,27961,27962,27963,27964,27965,27966,27967,
+27968,27969,27970,27971,27972,27973,27974,27975,27976,27977,27978,27979,
+27980,27981,27982,27983,27984,27985,27986,27987,27988,27989,27990,27991,
+27992,27993,27994,27995,27996,27997,27998,27999,28000,28001,28002,28003,
+28004,28005,28006,28007,28008,28009,28010,28011,28012,28013,28014,28015,
+28016,28017,28018,28019,28020,28021,28022,28023,28024,28025,28026,28027,
+28028,28029,28030,28031,28032,28033,28034,28035,28036,28037,28038,28039,
+28040,28041,28042,28043,28044,28045,28046,28047,28048,28049,28050,28051,
+28052,28053,28054,28055,28056,28057,28058,28059,28060,28061,28062,28063,
+28064,28065,28066,28067,28068,28069,28070,28071,28072,28073,28074,28075,
+28076,28077,28078,28079,28080,28081,28082,28083,28084,28085,28086,28087,
+28088,28089,28090,28091,28092,28093,28094,28095,28096,28097,28098,28099,
+28100,28101,28102,28103,28104,28105,28106,28107,28108,28109,28110,28111,
+28112,28113,28114,28115,28116,28117,28118,28119,28120,28121,28122,28123,
+28124,28125,28126,28127,28128,28129,28130,28131,28132,28133,28134,28135,
+28136,28137,28138,28139,28140,28141,28142,28143,28144,28145,28146,28147,
+28148,28149,28150,28151,28152,28153,28154,28155,28156,28157,28158,28159,
+28160,28161,28162,28163,28164,28165,28166,28167,28168,28169,28170,28171,
+28172,28173,28174,28175,28176,28177,28178,28179,28180,28181,28182,28183,
+28184,28185,28186,28187,28188,28189,28190,28191,28192,28193,28194,28195,
+28196,28197,28198,28199,28200,28201,28202,28203,28204,28205,28206,28207,
+28208,28209,28210,28211,28212,28213,28214,28215,28216,28217,28218,28219,
+28220,28221,28222,28223,28224,28225,28226,28227,28228,28229,28230,28231,
+28232,28233,28234,28235,28236,28237,28238,28239,28240,28241,28242,28243,
+28244,28245,28246,28247,28248,28249,28250,28251,28252,28253,28254,28255,
+28256,28257,28258,28259,28260,28261,28262,28263,28264,28265,28266,28267,
+28268,28269,28270,28271,28272,28273,28274,28275,28276,28277,28278,28279,
+28280,28281,28282,28283,28284,28285,28286,28287,28288,28289,28290,28291,
+28292,28293,28294,28295,28296,28297,28298,28299,28300,28301,28302,28303,
+28304,28305,28306,28307,28308,28309,28310,28311,28312,28313,28314,28315,
+28316,28317,28318,28319,28320,28321,28322,28323,28324,28325,28326,28327,
+28328,28329,28330,28331,28332,28333,28334,28335,28336,28337,28338,28339,
+28340,28341,28342,28343,28344,28345,28346,28347,28348,28349,28350,28351,
+28352,28353,28354,28355,28356,28357,28358,28359,28360,28361,28362,28363,
+28364,28365,28366,28367,28368,28369,28370,28371,28372,28373,28374,28375,
+28376,28377,28378,28379,28380,28381,28382,28383,28384,28385,28386,28387,
+28388,28389,28390,28391,28392,28393,28394,28395,28396,28397,28398,28399,
+28400,28401,28402,28403,28404,28405,28406,28407,28408,28409,28410,28411,
+28412,28413,28414,28415,28416,28417,28418,28419,28420,28421,28422,28423,
+28424,28425,28426,28427,28428,28429,28430,28431,28432,28433,28434,28435,
+28436,28437,28438,28439,28440,28441,28442,28443,28444,28445,28446,28447,
+28448,28449,28450,28451,28452,28453,28454,28455,28456,28457,28458,28459,
+28460,28461,28462,28463,28464,28465,28466,28467,28468,28469,28470,28471,
+28472,28473,28474,28475,28476,28477,28478,28479,28480,28481,28482,28483,
+28484,28485,28486,28487,28488,28489,28490,28491,28492,28493,28494,28495,
+28496,28497,28498,28499,28500,28501,28502,28503,28504,28505,28506,28507,
+28508,28509,28510,28511,28512,28513,28514,28515,28516,28517,28518,28519,
+28520,28521,28522,28523,28524,28525,28526,28527,28528,28529,28530,28531,
+28532,28533,28534,28535,28536,28537,28538,28539,28540,28541,28542,28543,
+28544,28545,28546,28547,28548,28549,28550,28551,28552,28553,28554,28555,
+28556,28557,28558,28559,28560,28561,28562,28563,28564,28565,28566,28567,
+28568,28569,28570,28571,28572,28573,28574,28575,28576,28577,28578,28579,
+28580,28581,28582,28583,28584,28585,28586,28587,28588,28589,28590,28591,
+28592,28593,28594,28595,28596,28597,28598,28599,28600,28601,28602,28603,
+28604,28605,28606,28607,28608,28609,28610,28611,28612,28613,28614,28615,
+28616,28617,28618,28619,28620,28621,28622,28623,28624,28625,28626,28627,
+28628,28629,28630,28631,28632,28633,28634,28635,28636,28637,28638,28639,
+28640,28641,28642,28643,28644,28645,28646,28647,28648,28649,28650,28651,
+28652,28653,28654,28655,28656,28657,28658,28659,28660,28661,28662,28663,
+28664,28665,28666,28667,28668,28669,28670,28671,28672,28673,28674,28675,
+28676,28677,28678,28679,28680,28681,28682,28683,28684,28685,28686,28687,
+28688,28689,28690,28691,28692,28693,28694,28695,28696,28697,28698,28699,
+28700,28701,28702,28703,28704,28705,28706,28707,28708,28709,28710,28711,
+28712,28713,28714,28715,28716,28717,28718,28719,28720,28721,28722,28723,
+28724,28725,28726,28727,28728,28729,28730,28731,28732,28733,28734,28735,
+28736,28737,28738,28739,28740,28741,28742,28743,28744,28745,28746,28747,
+28748,28749,28750,28751,28752,28753,28754,28755,28756,28757,28758,28759,
+28760,28761,28762,28763,28764,28765,28766,28767,28768,28769,28770,28771,
+28772,28773,28774,28775,28776,28777,28778,28779,28780,28781,28782,28783,
+28784,28785,28786,28787,28788,28789,28790,28791,28792,28793,28794,28795,
+28796,28797,28798,28799,28800,28801,28802,28803,28804,28805,28806,28807,
+28808,28809,28810,28811,28812,28813,28814,28815,28816,28817,28818,28819,
+28820,28821,28822,28823,28824,28825,28826,28827,28828,28829,28830,28831,
+28832,28833,28834,28835,28836,28837,28838,28839,28840,28841,28842,28843,
+28844,28845,28846,28847,28848,28849,28850,28851,28852,28853,28854,28855,
+28856,28857,28858,28859,28860,28861,28862,28863,28864,28865,28866,28867,
+28868,28869,28870,28871,28872,28873,28874,28875,28876,28877,28878,28879,
+28880,28881,28882,28883,28884,28885,28886,28887,28888,28889,28890,28891,
+28892,28893,28894,28895,28896,28897,28898,28899,28900,28901,28902,28903,
+28904,28905,28906,28907,28908,28909,28910,28911,28912,28913,28914,28915,
+28916,28917,28918,28919,28920,28921,28922,28923,28924,28925,28926,28927,
+28928,28929,28930,28931,28932,28933,28934,28935,28936,28937,28938,28939,
+28940,28941,28942,28943,28944,28945,28946,28947,28948,28949,28950,28951,
+28952,28953,28954,28955,28956,28957,28958,28959,28960,28961,28962,28963,
+28964,28965,28966,28967,28968,28969,28970,28971,28972,28973,28974,28975,
+28976,28977,28978,28979,28980,28981,28982,28983,28984,28985,28986,28987,
+28988,28989,28990,28991,28992,28993,28994,28995,28996,28997,28998,28999,
+29000,29001,29002,29003,29004,29005,29006,29007,29008,29009,29010,29011,
+29012,29013,29014,29015,29016,29017,29018,29019,29020,29021,29022,29023,
+29024,29025,29026,29027,29028,29029,29030,29031,29032,29033,29034,29035,
+29036,29037,29038,29039,29040,29041,29042,29043,29044,29045,29046,29047,
+29048,29049,29050,29051,29052,29053,29054,29055,29056,29057,29058,29059,
+29060,29061,29062,29063,29064,29065,29066,29067,29068,29069,29070,29071,
+29072,29073,29074,29075,29076,29077,29078,29079,29080,29081,29082,29083,
+29084,29085,29086,29087,29088,29089,29090,29091,29092,29093,29094,29095,
+29096,29097,29098,29099,29100,29101,29102,29103,29104,29105,29106,29107,
+29108,29109,29110,29111,29112,29113,29114,29115,29116,29117,29118,29119,
+29120,29121,29122,29123,29124,29125,29126,29127,29128,29129,29130,29131,
+29132,29133,29134,29135,29136,29137,29138,29139,29140,29141,29142,29143,
+29144,29145,29146,29147,29148,29149,29150,29151,29152,29153,29154,29155,
+29156,29157,29158,29159,29160,29161,29162,29163,29164,29165,29166,29167,
+29168,29169,29170,29171,29172,29173,29174,29175,29176,29177,29178,29179,
+29180,29181,29182,29183,29184,29185,29186,29187,29188,29189,29190,29191,
+29192,29193,29194,29195,29196,29197,29198,29199,29200,29201,29202,29203,
+29204,29205,29206,29207,29208,29209,29210,29211,29212,29213,29214,29215,
+29216,29217,29218,29219,29220,29221,29222,29223,29224,29225,29226,29227,
+29228,29229,29230,29231,29232,29233,29234,29235,29236,29237,29238,29239,
+29240,29241,29242,29243,29244,29245,29246,29247,29248,29249,29250,29251,
+29252,29253,29254,29255,29256,29257,29258,29259,29260,29261,29262,29263,
+29264,29265,29266,29267,29268,29269,29270,29271,29272,29273,29274,29275,
+29276,29277,29278,29279,29280,29281,29282,29283,29284,29285,29286,29287,
+29288,29289,29290,29291,29292,29293,29294,29295,29296,29297,29298,29299,
+29300,29301,29302,29303,29304,29305,29306,29307,29308,29309,29310,29311,
+29312,29313,29314,29315,29316,29317,29318,29319,29320,29321,29322,29323,
+29324,29325,29326,29327,29328,29329,29330,29331,29332,29333,29334,29335,
+29336,29337,29338,29339,29340,29341,29342,29343,29344,29345,29346,29347,
+29348,29349,29350,29351,29352,29353,29354,29355,29356,29357,29358,29359,
+29360,29361,29362,29363,29364,29365,29366,29367,29368,29369,29370,29371,
+29372,29373,29374,29375,29376,29377,29378,29379,29380,29381,29382,29383,
+29384,29385,29386,29387,29388,29389,29390,29391,29392,29393,29394,29395,
+29396,29397,29398,29399,29400,29401,29402,29403,29404,29405,29406,29407,
+29408,29409,29410,29411,29412,29413,29414,29415,29416,29417,29418,29419,
+29420,29421,29422,29423,29424,29425,29426,29427,29428,29429,29430,29431,
+29432,29433,29434,29435,29436,29437,29438,29439,29440,29441,29442,29443,
+29444,29445,29446,29447,29448,29449,29450,29451,29452,29453,29454,29455,
+29456,29457,29458,29459,29460,29461,29462,29463,29464,29465,29466,29467,
+29468,29469,29470,29471,29472,29473,29474,29475,29476,29477,29478,29479,
+29480,29481,29482,29483,29484,29485,29486,29487,29488,29489,29490,29491,
+29492,29493,29494,29495,29496,29497,29498,29499,29500,29501,29502,29503,
+29504,29505,29506,29507,29508,29509,29510,29511,29512,29513,29514,29515,
+29516,29517,29518,29519,29520,29521,29522,29523,29524,29525,29526,29527,
+29528,29529,29530,29531,29532,29533,29534,29535,29536,29537,29538,29539,
+29540,29541,29542,29543,29544,29545,29546,29547,29548,29549,29550,29551,
+29552,29553,29554,29555,29556,29557,29558,29559,29560,29561,29562,29563,
+29564,29565,29566,29567,29568,29569,29570,29571,29572,29573,29574,29575,
+29576,29577,29578,29579,29580,29581,29582,29583,29584,29585,29586,29587,
+29588,29589,29590,29591,29592,29593,29594,29595,29596,29597,29598,29599,
+29600,29601,29602,29603,29604,29605,29606,29607,29608,29609,29610,29611,
+29612,29613,29614,29615,29616,29617,29618,29619,29620,29621,29622,29623,
+29624,29625,29626,29627,29628,29629,29630,29631,29632,29633,29634,29635,
+29636,29637,29638,29639,29640,29641,29642,29643,29644,29645,29646,29647,
+29648,29649,29650,29651,29652,29653,29654,29655,29656,29657,29658,29659,
+29660,29661,29662,29663,29664,29665,29666,29667,29668,29669,29670,29671,
+29672,29673,29674,29675,29676,29677,29678,29679,29680,29681,29682,29683,
+29684,29685,29686,29687,29688,29689,29690,29691,29692,29693,29694,29695,
+29696,29697,29698,29699,29700,29701,29702,29703,29704,29705,29706,29707,
+29708,29709,29710,29711,29712,29713,29714,29715,29716,29717,29718,29719,
+29720,29721,29722,29723,29724,29725,29726,29727,29728,29729,29730,29731,
+29732,29733,29734,29735,29736,29737,29738,29739,29740,29741,29742,29743,
+29744,29745,29746,29747,29748,29749,29750,29751,29752,29753,29754,29755,
+29756,29757,29758,29759,29760,29761,29762,29763,29764,29765,29766,29767,
+29768,29769,29770,29771,29772,29773,29774,29775,29776,29777,29778,29779,
+29780,29781,29782,29783,29784,29785,29786,29787,29788,29789,29790,29791,
+29792,29793,29794,29795,29796,29797,29798,29799,29800,29801,29802,29803,
+29804,29805,29806,29807,29808,29809,29810,29811,29812,29813,29814,29815,
+29816,29817,29818,29819,29820,29821,29822,29823,29824,29825,29826,29827,
+29828,29829,29830,29831,29832,29833,29834,29835,29836,29837,29838,29839,
+29840,29841,29842,29843,29844,29845,29846,29847,29848,29849,29850,29851,
+29852,29853,29854,29855,29856,29857,29858,29859,29860,29861,29862,29863,
+29864,29865,29866,29867,29868,29869,29870,29871,29872,29873,29874,29875,
+29876,29877,29878,29879,29880,29881,29882,29883,29884,29885,29886,29887,
+29888,29889,29890,29891,29892,29893,29894,29895,29896,29897,29898,29899,
+29900,29901,29902,29903,29904,29905,29906,29907,29908,29909,29910,29911,
+29912,29913,29914,29915,29916,29917,29918,29919,29920,29921,29922,29923,
+29924,29925,29926,29927,29928,29929,29930,29931,29932,29933,29934,29935,
+29936,29937,29938,29939,29940,29941,29942,29943,29944,29945,29946,29947,
+29948,29949,29950,29951,29952,29953,29954,29955,29956,29957,29958,29959,
+29960,29961,29962,29963,29964,29965,29966,29967,29968,29969,29970,29971,
+29972,29973,29974,29975,29976,29977,29978,29979,29980,29981,29982,29983,
+29984,29985,29986,29987,29988,29989,29990,29991,29992,29993,29994,29995,
+29996,29997,29998,29999,30000,30001,30002,30003,30004,30005,30006,30007,
+30008,30009,30010,30011,30012,30013,30014,30015,30016,30017,30018,30019,
+30020,30021,30022,30023,30024,30025,30026,30027,30028,30029,30030,30031,
+30032,30033,30034,30035,30036,30037,30038,30039,30040,30041,30042,30043,
+30044,30045,30046,30047,30048,30049,30050,30051,30052,30053,30054,30055,
+30056,30057,30058,30059,30060,30061,30062,30063,30064,30065,30066,30067,
+30068,30069,30070,30071,30072,30073,30074,30075,30076,30077,30078,30079,
+30080,30081,30082,30083,30084,30085,30086,30087,30088,30089,30090,30091,
+30092,30093,30094,30095,30096,30097,30098,30099,30100,30101,30102,30103,
+30104,30105,30106,30107,30108,30109,30110,30111,30112,30113,30114,30115,
+30116,30117,30118,30119,30120,30121,30122,30123,30124,30125,30126,30127,
+30128,30129,30130,30131,30132,30133,30134,30135,30136,30137,30138,30139,
+30140,30141,30142,30143,30144,30145,30146,30147,30148,30149,30150,30151,
+30152,30153,30154,30155,30156,30157,30158,30159,30160,30161,30162,30163,
+30164,30165,30166,30167,30168,30169,30170,30171,30172,30173,30174,30175,
+30176,30177,30178,30179,30180,30181,30182,30183,30184,30185,30186,30187,
+30188,30189,30190,30191,30192,30193,30194,30195,30196,30197,30198,30199,
+30200,30201,30202,30203,30204,30205,30206,30207,30208,30209,30210,30211,
+30212,30213,30214,30215,30216,30217,30218,30219,30220,30221,30222,30223,
+30224,30225,30226,30227,30228,30229,30230,30231,30232,30233,30234,30235,
+30236,30237,30238,30239,30240,30241,30242,30243,30244,30245,30246,30247,
+30248,30249,30250,30251,30252,30253,30254,30255,30256,30257,30258,30259,
+30260,30261,30262,30263,30264,30265,30266,30267,30268,30269,30270,30271,
+30272,30273,30274,30275,30276,30277,30278,30279,30280,30281,30282,30283,
+30284,30285,30286,30287,30288,30289,30290,30291,30292,30293,30294,30295,
+30296,30297,30298,30299,30300,30301,30302,30303,30304,30305,30306,30307,
+30308,30309,30310,30311,30312,30313,30314,30315,30316,30317,30318,30319,
+30320,30321,30322,30323,30324,30325,30326,30327,30328,30329,30330,30331,
+30332,30333,30334,30335,30336,30337,30338,30339,30340,30341,30342,30343,
+30344,30345,30346,30347,30348,30349,30350,30351,30352,30353,30354,30355,
+30356,30357,30358,30359,30360,30361,30362,30363,30364,30365,30366,30367,
+30368,30369,30370,30371,30372,30373,30374,30375,30376,30377,30378,30379,
+30380,30381,30382,30383,30384,30385,30386,30387,30388,30389,30390,30391,
+30392,30393,30394,30395,30396,30397,30398,30399,30400,30401,30402,30403,
+30404,30405,30406,30407,30408,30409,30410,30411,30412,30413,30414,30415,
+30416,30417,30418,30419,30420,30421,30422,30423,30424,30425,30426,30427,
+30428,30429,30430,30431,30432,30433,30434,30435,30436,30437,30438,30439,
+30440,30441,30442,30443,30444,30445,30446,30447,30448,30449,30450,30451,
+30452,30453,30454,30455,30456,30457,30458,30459,30460,30461,30462,30463,
+30464,30465,30466,30467,30468,30469,30470,30471,30472,30473,30474,30475,
+30476,30477,30478,30479,30480,30481,30482,30483,30484,30485,30486,30487,
+30488,30489,30490,30491,30492,30493,30494,30495,30496,30497,30498,30499,
+30500,30501,30502,30503,30504,30505,30506,30507,30508,30509,30510,30511,
+30512,30513,30514,30515,30516,30517,30518,30519,30520,30521,30522,30523,
+30524,30525,30526,30527,30528,30529,30530,30531,30532,30533,30534,30535,
+30536,30537,30538,30539,30540,30541,30542,30543,30544,30545,30546,30547,
+30548,30549,30550,30551,30552,30553,30554,30555,30556,30557,30558,30559,
+30560,30561,30562,30563,30564,30565,30566,30567,30568,30569,30570,30571,
+30572,30573,30574,30575,30576,30577,30578,30579,30580,30581,30582,30583,
+30584,30585,30586,30587,30588,30589,30590,30591,30592,30593,30594,30595,
+30596,30597,30598,30599,30600,30601,30602,30603,30604,30605,30606,30607,
+30608,30609,30610,30611,30612,30613,30614,30615,30616,30617,30618,30619,
+30620,30621,30622,30623,30624,30625,30626,30627,30628,30629,30630,30631,
+30632,30633,30634,30635,30636,30637,30638,30639,30640,30641,30642,30643,
+30644,30645,30646,30647,30648,30649,30650,30651,30652,30653,30654,30655,
+30656,30657,30658,30659,30660,30661,30662,30663,30664,30665,30666,30667,
+30668,30669,30670,30671,30672,30673,30674,30675,30676,30677,30678,30679,
+30680,30681,30682,30683,30684,30685,30686,30687,30688,30689,30690,30691,
+30692,30693,30694,30695,30696,30697,30698,30699,30700,30701,30702,30703,
+30704,30705,30706,30707,30708,30709,30710,30711,30712,30713,30714,30715,
+30716,30717,30718,30719,30720,30721,30722,30723,30724,30725,30726,30727,
+30728,30729,30730,30731,30732,30733,30734,30735,30736,30737,30738,30739,
+30740,30741,30742,30743,30744,30745,30746,30747,30748,30749,30750,30751,
+30752,30753,30754,30755,30756,30757,30758,30759,30760,30761,30762,30763,
+30764,30765,30766,30767,30768,30769,30770,30771,30772,30773,30774,30775,
+30776,30777,30778,30779,30780,30781,30782,30783,30784,30785,30786,30787,
+30788,30789,30790,30791,30792,30793,30794,30795,30796,30797,30798,30799,
+30800,30801,30802,30803,30804,30805,30806,30807,30808,30809,30810,30811,
+30812,30813,30814,30815,30816,30817,30818,30819,30820,30821,30822,30823,
+30824,30825,30826,30827,30828,30829,30830,30831,30832,30833,30834,30835,
+30836,30837,30838,30839,30840,30841,30842,30843,30844,30845,30846,30847,
+30848,30849,30850,30851,30852,30853,30854,30855,30856,30857,30858,30859,
+30860,30861,30862,30863,30864,30865,30866,30867,30868,30869,30870,30871,
+30872,30873,30874,30875,30876,30877,30878,30879,30880,30881,30882,30883,
+30884,30885,30886,30887,30888,30889,30890,30891,30892,30893,30894,30895,
+30896,30897,30898,30899,30900,30901,30902,30903,30904,30905,30906,30907,
+30908,30909,30910,30911,30912,30913,30914,30915,30916,30917,30918,30919,
+30920,30921,30922,30923,30924,30925,30926,30927,30928,30929,30930,30931,
+30932,30933,30934,30935,30936,30937,30938,30939,30940,30941,30942,30943,
+30944,30945,30946,30947,30948,30949,30950,30951,30952,30953,30954,30955,
+30956,30957,30958,30959,30960,30961,30962,30963,30964,30965,30966,30967,
+30968,30969,30970,30971,30972,30973,30974,30975,30976,30977,30978,30979,
+30980,30981,30982,30983,30984,30985,30986,30987,30988,30989,30990,30991,
+30992,30993,30994,30995,30996,30997,30998,30999,31000,31001,31002,31003,
+31004,31005,31006,31007,31008,31009,31010,31011,31012,31013,31014,31015,
+31016,31017,31018,31019,31020,31021,31022,31023,31024,31025,31026,31027,
+31028,31029,31030,31031,31032,31033,31034,31035,31036,31037,31038,31039,
+31040,31041,31042,31043,31044,31045,31046,31047,31048,31049,31050,31051,
+31052,31053,31054,31055,31056,31057,31058,31059,31060,31061,31062,31063,
+31064,31065,31066,31067,31068,31069,31070,31071,31072,31073,31074,31075,
+31076,31077,31078,31079,31080,31081,31082,31083,31084,31085,31086,31087,
+31088,31089,31090,31091,31092,31093,31094,31095,31096,31097,31098,31099,
+31100,31101,31102,31103,31104,31105,31106,31107,31108,31109,31110,31111,
+31112,31113,31114,31115,31116,31117,31118,31119,31120,31121,31122,31123,
+31124,31125,31126,31127,31128,31129,31130,31131,31132,31133,31134,31135,
+31136,31137,31138,31139,31140,31141,31142,31143,31144,31145,31146,31147,
+31148,31149,31150,31151,31152,31153,31154,31155,31156,31157,31158,31159,
+31160,31161,31162,31163,31164,31165,31166,31167,31168,31169,31170,31171,
+31172,31173,31174,31175,31176,31177,31178,31179,31180,31181,31182,31183,
+31184,31185,31186,31187,31188,31189,31190,31191,31192,31193,31194,31195,
+31196,31197,31198,31199,31200,31201,31202,31203,31204,31205,31206,31207,
+31208,31209,31210,31211,31212,31213,31214,31215,31216,31217,31218,31219,
+31220,31221,31222,31223,31224,31225,31226,31227,31228,31229,31230,31231,
+31232,31233,31234,31235,31236,31237,31238,31239,31240,31241,31242,31243,
+31244,31245,31246,31247,31248,31249,31250,31251,31252,31253,31254,31255,
+31256,31257,31258,31259,31260,31261,31262,31263,31264,31265,31266,31267,
+31268,31269,31270,31271,31272,31273,31274,31275,31276,31277,31278,31279,
+31280,31281,31282,31283,31284,31285,31286,31287,31288,31289,31290,31291,
+31292,31293,31294,31295,31296,31297,31298,31299,31300,31301,31302,31303,
+31304,31305,31306,31307,31308,31309,31310,31311,31312,31313,31314,31315,
+31316,31317,31318,31319,31320,31321,31322,31323,31324,31325,31326,31327,
+31328,31329,31330,31331,31332,31333,31334,31335,31336,31337,31338,31339,
+31340,31341,31342,31343,31344,31345,31346,31347,31348,31349,31350,31351,
+31352,31353,31354,31355,31356,31357,31358,31359,31360,31361,31362,31363,
+31364,31365,31366,31367,31368,31369,31370,31371,31372,31373,31374,31375,
+31376,31377,31378,31379,31380,31381,31382,31383,31384,31385,31386,31387,
+31388,31389,31390,31391,31392,31393,31394,31395,31396,31397,31398,31399,
+31400,31401,31402,31403,31404,31405,31406,31407,31408,31409,31410,31411,
+31412,31413,31414,31415,31416,31417,31418,31419,31420,31421,31422,31423,
+31424,31425,31426,31427,31428,31429,31430,31431,31432,31433,31434,31435,
+31436,31437,31438,31439,31440,31441,31442,31443,31444,31445,31446,31447,
+31448,31449,31450,31451,31452,31453,31454,31455,31456,31457,31458,31459,
+31460,31461,31462,31463,31464,31465,31466,31467,31468,31469,31470,31471,
+31472,31473,31474,31475,31476,31477,31478,31479,31480,31481,31482,31483,
+31484,31485,31486,31487,31488,31489,31490,31491,31492,31493,31494,31495,
+31496,31497,31498,31499,31500,31501,31502,31503,31504,31505,31506,31507,
+31508,31509,31510,31511,31512,31513,31514,31515,31516,31517,31518,31519,
+31520,31521,31522,31523,31524,31525,31526,31527,31528,31529,31530,31531,
+31532,31533,31534,31535,31536,31537,31538,31539,31540,31541,31542,31543,
+31544,31545,31546,31547,31548,31549,31550,31551,31552,31553,31554,31555,
+31556,31557,31558,31559,31560,31561,31562,31563,31564,31565,31566,31567,
+31568,31569,31570,31571,31572,31573,31574,31575,31576,31577,31578,31579,
+31580,31581,31582,31583,31584,31585,31586,31587,31588,31589,31590,31591,
+31592,31593,31594,31595,31596,31597,31598,31599,31600,31601,31602,31603,
+31604,31605,31606,31607,31608,31609,31610,31611,31612,31613,31614,31615,
+31616,31617,31618,31619,31620,31621,31622,31623,31624,31625,31626,31627,
+31628,31629,31630,31631,31632,31633,31634,31635,31636,31637,31638,31639,
+31640,31641,31642,31643,31644,31645,31646,31647,31648,31649,31650,31651,
+31652,31653,31654,31655,31656,31657,31658,31659,31660,31661,31662,31663,
+31664,31665,31666,31667,31668,31669,31670,31671,31672,31673,31674,31675,
+31676,31677,31678,31679,31680,31681,31682,31683,31684,31685,31686,31687,
+31688,31689,31690,31691,31692,31693,31694,31695,31696,31697,31698,31699,
+31700,31701,31702,31703,31704,31705,31706,31707,31708,31709,31710,31711,
+31712,31713,31714,31715,31716,31717,31718,31719,31720,31721,31722,31723,
+31724,31725,31726,31727,31728,31729,31730,31731,31732,31733,31734,31735,
+31736,31737,31738,31739,31740,31741,31742,31743,31744,31745,31746,31747,
+31748,31749,31750,31751,31752,31753,31754,31755,31756,31757,31758,31759,
+31760,31761,31762,31763,31764,31765,31766,31767,31768,31769,31770,31771,
+31772,31773,31774,31775,31776,31777,31778,31779,31780,31781,31782,31783,
+31784,31785,31786,31787,31788,31789,31790,31791,31792,31793,31794,31795,
+31796,31797,31798,31799,31800,31801,31802,31803,31804,31805,31806,31807,
+31808,31809,31810,31811,31812,31813,31814,31815,31816,31817,31818,31819,
+31820,31821,31822,31823,31824,31825,31826,31827,31828,31829,31830,31831,
+31832,31833,31834,31835,31836,31837,31838,31839,31840,31841,31842,31843,
+31844,31845,31846,31847,31848,31849,31850,31851,31852,31853,31854,31855,
+31856,31857,31858,31859,31860,31861,31862,31863,31864,31865,31866,31867,
+31868,31869,31870,31871,31872,31873,31874,31875,31876,31877,31878,31879,
+31880,31881,31882,31883,31884,31885,31886,31887,31888,31889,31890,31891,
+31892,31893,31894,31895,31896,31897,31898,31899,31900,31901,31902,31903,
+31904,31905,31906,31907,31908,31909,31910,31911,31912,31913,31914,31915,
+31916,31917,31918,31919,31920,31921,31922,31923,31924,31925,31926,31927,
+31928,31929,31930,31931,31932,31933,31934,31935,31936,31937,31938,31939,
+31940,31941,31942,31943,31944,31945,31946,31947,31948,31949,31950,31951,
+31952,31953,31954,31955,31956,31957,31958,31959,31960,31961,31962,31963,
+31964,31965,31966,31967,31968,31969,31970,31971,31972,31973,31974,31975,
+31976,31977,31978,31979,31980,31981,31982,31983,31984,31985,31986,31987,
+31988,31989,31990,31991,31992,31993,31994,31995,31996,31997,31998,31999,
+32000,32001,32002,32003,32004,32005,32006,32007,32008,32009,32010,32011,
+32012,32013,32014,32015,32016,32017,32018,32019,32020,32021,32022,32023,
+32024,32025,32026,32027,32028,32029,32030,32031,32032,32033,32034,32035,
+32036,32037,32038,32039,32040,32041,32042,32043,32044,32045,32046,32047,
+32048,32049,32050,32051,32052,32053,32054,32055,32056,32057,32058,32059,
+32060,32061,32062,32063,32064,32065,32066,32067,32068,32069,32070,32071,
+32072,32073,32074,32075,32076,32077,32078,32079,32080,32081,32082,32083,
+32084,32085,32086,32087,32088,32089,32090,32091,32092,32093,32094,32095,
+32096,32097,32098,32099,32100,32101,32102,32103,32104,32105,32106,32107,
+32108,32109,32110,32111,32112,32113,32114,32115,32116,32117,32118,32119,
+32120,32121,32122,32123,32124,32125,32126,32127,32128,32129,32130,32131,
+32132,32133,32134,32135,32136,32137,32138,32139,32140,32141,32142,32143,
+32144,32145,32146,32147,32148,32149,32150,32151,32152,32153,32154,32155,
+32156,32157,32158,32159,32160,32161,32162,32163,32164,32165,32166,32167,
+32168,32169,32170,32171,32172,32173,32174,32175,32176,32177,32178,32179,
+32180,32181,32182,32183,32184,32185,32186,32187,32188,32189,32190,32191,
+32192,32193,32194,32195,32196,32197,32198,32199,32200,32201,32202,32203,
+32204,32205,32206,32207,32208,32209,32210,32211,32212,32213,32214,32215,
+32216,32217,32218,32219,32220,32221,32222,32223,32224,32225,32226,32227,
+32228,32229,32230,32231,32232,32233,32234,32235,32236,32237,32238,32239,
+32240,32241,32242,32243,32244,32245,32246,32247,32248,32249,32250,32251,
+32252,32253,32254,32255,32256,32257,32258,32259,32260,32261,32262,32263,
+32264,32265,32266,32267,32268,32269,32270,32271,32272,32273,32274,32275,
+32276,32277,32278,32279,32280,32281,32282,32283,32284,32285,32286,32287,
+32288,32289,32290,32291,32292,32293,32294,32295,32296,32297,32298,32299,
+32300,32301,32302,32303,32304,32305,32306,32307,32308,32309,32310,32311,
+32312,32313,32314,32315,32316,32317,32318,32319,32320,32321,32322,32323,
+32324,32325,32326,32327,32328,32329,32330,32331,32332,32333,32334,32335,
+32336,32337,32338,32339,32340,32341,32342,32343,32344,32345,32346,32347,
+32348,32349,32350,32351,32352,32353,32354,32355,32356,32357,32358,32359,
+32360,32361,32362,32363,32364,32365,32366,32367,32368,32369,32370,32371,
+32372,32373,32374,32375,32376,32377,32378,32379,32380,32381,32382,32383,
+32384,32385,32386,32387,32388,32389,32390,32391,32392,32393,32394,32395,
+32396,32397,32398,32399,32400,32401,32402,32403,32404,32405,32406,32407,
+32408,32409,32410,32411,32412,32413,32414,32415,32416,32417,32418,32419,
+32420,32421,32422,32423,32424,32425,32426,32427,32428,32429,32430,32431,
+32432,32433,32434,32435,32436,32437,32438,32439,32440,32441,32442,32443,
+32444,32445,32446,32447,32448,32449,32450,32451,32452,32453,32454,32455,
+32456,32457,32458,32459,32460,32461,32462,32463,32464,32465,32466,32467,
+32468,32469,32470,32471,32472,32473,32474,32475,32476,32477,32478,32479,
+32480,32481,32482,32483,32484,32485,32486,32487,32488,32489,32490,32491,
+32492,32493,32494,32495,32496,32497,32498,32499,32500,32501,32502,32503,
+32504,32505,32506,32507,32508,32509,32510,32511,32512,32513,32514,32515,
+32516,32517,32518,32519,32520,32521,32522,32523,32524,32525,32526,32527,
+32528,32529,32530,32531,32532,32533,32534,32535,32536,32537,32538,32539,
+32540,32541,32542,32543,32544,32545,32546,32547,32548,32549,32550,32551,
+32552,32553,32554,32555,32556,32557,32558,32559,32560,32561,32562,32563,
+32564,32565,32566,32567,32568,32569,32570,32571,32572,32573,32574,32575,
+32576,32577,32578,32579,32580,32581,32582,32583,32584,32585,32586,32587,
+32588,32589,32590,32591,32592,32593,32594,32595,32596,32597,32598,32599,
+32600,32601,32602,32603,32604,32605,32606,32607,32608,32609,32610,32611,
+32612,32613,32614,32615,32616,32617,32618,32619,32620,32621,32622,32623,
+32624,32625,32626,32627,32628,32629,32630,32631,32632,32633,32634,32635,
+32636,32637,32638,32639,32640,32641,32642,32643,32644,32645,32646,32647,
+32648,32649,32650,32651,32652,32653,32654,32655,32656,32657,32658,32659,
+32660,32661,32662,32663,32664,32665,32666,32667,32668,32669,32670,32671,
+32672,32673,32674,32675,32676,32677,32678,32679,32680,32681,32682,32683,
+32684,32685,32686,32687,32688,32689,32690,32691,32692,32693,32694,32695,
+32696,32697,32698,32699,32700,32701,32702,32703,32704,32705,32706,32707,
+32708,32709,32710,32711,32712,32713,32714,32715,32716,32717,32718,32719,
+32720,32721,32722,32723,32724,32725,32726,32727,32728,32729,32730,32731,
+32732,32733,32734,32735,32736,32737,32738,32739,32740,32741,32742,32743,
+32744,32745,32746,32747,32748,32749,32750,32751,32752,32753,32754,32755,
+32756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,
+32768L,32769L,32770L,32771L,32772L,32773L,32774L,32775L,32776L,32777L,
+32778L,32779L,32780L,32781L,32782L,32783L,32784L,32785L,32786L,32787L,
+32788L,32789L,32790L,32791L,32792L,32793L,32794L,32795L,32796L,32797L,
+32798L,32799L,32800L,32801L,32802L,32803L,32804L,32805L,32806L,32807L,
+32808L,32809L,32810L,32811L,32812L,32813L,32814L,32815L,32816L,32817L,
+32818L,32819L,32820L,32821L,32822L,32823L,32824L,32825L,32826L,32827L,
+32828L,32829L,32830L,32831L,32832L,32833L,32834L,32835L,32836L,32837L,
+32838L,32839L,32840L,32841L,32842L,32843L,32844L,32845L,32846L,32847L,
+32848L,32849L,32850L,32851L,32852L,32853L,32854L,32855L,32856L,32857L,
+32858L,32859L,32860L,32861L,32862L,32863L,32864L,32865L,32866L,32867L,
+32868L,32869L,32870L,32871L,32872L,32873L,32874L,32875L,32876L,32877L,
+32878L,32879L,32880L,32881L,32882L,32883L,32884L,32885L,32886L,32887L,
+32888L,32889L,32890L,32891L,32892L,32893L,32894L,32895L,32896L,32897L,
+32898L,32899L,32900L,32901L,32902L,32903L,32904L,32905L,32906L,32907L,
+32908L,32909L,32910L,32911L,32912L,32913L,32914L,32915L,32916L,32917L,
+32918L,32919L,32920L,32921L,32922L,32923L,32924L,32925L,32926L,32927L,
+32928L,32929L,32930L,32931L,32932L,32933L,32934L,32935L,32936L,32937L,
+32938L,32939L,32940L,32941L,32942L,32943L,32944L,32945L,32946L,32947L,
+32948L,32949L,32950L,32951L,32952L,32953L,32954L,32955L,32956L,32957L,
+32958L,32959L,32960L,32961L,32962L,32963L,32964L,32965L,32966L,32967L,
+32968L,32969L,32970L,32971L,32972L,32973L,32974L,32975L,32976L,32977L,
+32978L,32979L,32980L,32981L,32982L,32983L,32984L,32985L,32986L,32987L,
+32988L,32989L,32990L,32991L,32992L,32993L,32994L,32995L,32996L,32997L,
+32998L,32999L,33000L,33001L,33002L,33003L,33004L,33005L,33006L,33007L,
+33008L,33009L,33010L,33011L,33012L,33013L,33014L,33015L,33016L,33017L,
+33018L,33019L,33020L,33021L,33022L,33023L,33024L,33025L,33026L,33027L,
+33028L,33029L,33030L,33031L,33032L,33033L,33034L,33035L,33036L,33037L,
+33038L,33039L,33040L,33041L,33042L,33043L,33044L,33045L,33046L,33047L,
+33048L,33049L,33050L,33051L,33052L,33053L,33054L,33055L,33056L,33057L,
+33058L,33059L,33060L,33061L,33062L,33063L,33064L,33065L,33066L,33067L,
+33068L,33069L,33070L,33071L,33072L,33073L,33074L,33075L,33076L,33077L,
+33078L,33079L,33080L,33081L,33082L,33083L,33084L,33085L,33086L,33087L,
+33088L,33089L,33090L,33091L,33092L,33093L,33094L,33095L,33096L,33097L,
+33098L,33099L,33100L,33101L,33102L,33103L,33104L,33105L,33106L,33107L,
+33108L,33109L,33110L,33111L,33112L,33113L,33114L,33115L,33116L,33117L,
+33118L,33119L,33120L,33121L,33122L,33123L,33124L,33125L,33126L,33127L,
+33128L,33129L,33130L,33131L,33132L,33133L,33134L,33135L,33136L,33137L,
+33138L,33139L,33140L,33141L,33142L,33143L,33144L,33145L,33146L,33147L,
+33148L,33149L,33150L,33151L,33152L,33153L,33154L,33155L,33156L,33157L,
+33158L,33159L,33160L,33161L,33162L,33163L,33164L,33165L,33166L,33167L,
+33168L,33169L,33170L,33171L,33172L,33173L,33174L,33175L,33176L,33177L,
+33178L,33179L,33180L,33181L,33182L,33183L,33184L,33185L,33186L,33187L,
+33188L,33189L,33190L,33191L,33192L,33193L,33194L,33195L,33196L,33197L,
+33198L,33199L,33200L,33201L,33202L,33203L,33204L,33205L,33206L,33207L,
+33208L,33209L,33210L,33211L,33212L,33213L,33214L,33215L,33216L,33217L,
+33218L,33219L,33220L,33221L,33222L,33223L,33224L,33225L,33226L,33227L,
+33228L,33229L,33230L,33231L,33232L,33233L,33234L,33235L,33236L,33237L,
+33238L,33239L,33240L,33241L,33242L,33243L,33244L,33245L,33246L,33247L,
+33248L,33249L,33250L,33251L,33252L,33253L,33254L,33255L,33256L,33257L,
+33258L,33259L,33260L,33261L,33262L,33263L,33264L,33265L,33266L,33267L,
+33268L,33269L,33270L,33271L,33272L,33273L,33274L,33275L,33276L,33277L,
+33278L,33279L,33280L,33281L,33282L,33283L,33284L,33285L,33286L,33287L,
+33288L,33289L,33290L,33291L,33292L,33293L,33294L,33295L,33296L,33297L,
+33298L,33299L,33300L,33301L,33302L,33303L,33304L,33305L,33306L,33307L,
+33308L,33309L,33310L,33311L,33312L,33313L,33314L,33315L,33316L,33317L,
+33318L,33319L,33320L,33321L,33322L,33323L,33324L,33325L,33326L,33327L,
+33328L,33329L,33330L,33331L,33332L,33333L,33334L,33335L,33336L,33337L,
+33338L,33339L,33340L,33341L,33342L,33343L,33344L,33345L,33346L,33347L,
+33348L,33349L,33350L,33351L,33352L,33353L,33354L,33355L,33356L,33357L,
+33358L,33359L,33360L,33361L,33362L,33363L,33364L,33365L,33366L,33367L,
+33368L,33369L,33370L,33371L,33372L,33373L,33374L,33375L,33376L,33377L,
+33378L,33379L,33380L,33381L,33382L,33383L,33384L,33385L,33386L,33387L,
+33388L,33389L,33390L,33391L,33392L,33393L,33394L,33395L,33396L,33397L,
+33398L,33399L,33400L,33401L,33402L,33403L,33404L,33405L,33406L,33407L,
+33408L,33409L,33410L,33411L,33412L,33413L,33414L,33415L,33416L,33417L,
+33418L,33419L,33420L,33421L,33422L,33423L,33424L,33425L,33426L,33427L,
+33428L,33429L,33430L,33431L,33432L,33433L,33434L,33435L,33436L,33437L,
+33438L,33439L,33440L,33441L,33442L,33443L,33444L,33445L,33446L,33447L,
+33448L,33449L,33450L,33451L,33452L,33453L,33454L,33455L,33456L,33457L,
+33458L,33459L,33460L,33461L,33462L,33463L,33464L,33465L,33466L,33467L,
+33468L,33469L,33470L,33471L,33472L,33473L,33474L,33475L,33476L,33477L,
+33478L,33479L,33480L,33481L,33482L,33483L,33484L,33485L,33486L,33487L,
+33488L,33489L,33490L,33491L,33492L,33493L,33494L,33495L,33496L,33497L,
+33498L,33499L,33500L,33501L,33502L,33503L,33504L,33505L,33506L,33507L,
+33508L,33509L,33510L,33511L,33512L,33513L,33514L,33515L,33516L,33517L,
+33518L,33519L,33520L,33521L,33522L,33523L,33524L,33525L,33526L,33527L,
+33528L,33529L,33530L,33531L,33532L,33533L,33534L,33535L,33536L,33537L,
+33538L,33539L,33540L,33541L,33542L,33543L,33544L,33545L,33546L,33547L,
+33548L,33549L,33550L,33551L,33552L,33553L,33554L,33555L,33556L,33557L,
+33558L,33559L,33560L,33561L,33562L,33563L,33564L,33565L,33566L,33567L,
+33568L,33569L,33570L,33571L,33572L,33573L,33574L,33575L,33576L,33577L,
+33578L,33579L,33580L,33581L,33582L,33583L,33584L,33585L,33586L,33587L,
+33588L,33589L,33590L,33591L,33592L,33593L,33594L,33595L,33596L,33597L,
+33598L,33599L,33600L,33601L,33602L,33603L,33604L,33605L,33606L,33607L,
+33608L,33609L,33610L,33611L,33612L,33613L,33614L,33615L,33616L,33617L,
+33618L,33619L,33620L,33621L,33622L,33623L,33624L,33625L,33626L,33627L,
+33628L,33629L,33630L,33631L,33632L,33633L,33634L,33635L,33636L,33637L,
+33638L,33639L,33640L,33641L,33642L,33643L,33644L,33645L,33646L,33647L,
+33648L,33649L,33650L,33651L,33652L,33653L,33654L,33655L,33656L,33657L,
+33658L,33659L,33660L,33661L,33662L,33663L,33664L,33665L,33666L,33667L,
+33668L,33669L,33670L,33671L,33672L,33673L,33674L,33675L,33676L,33677L,
+33678L,33679L,33680L,33681L,33682L,33683L,33684L,33685L,33686L,33687L,
+33688L,33689L,33690L,33691L,33692L,33693L,33694L,33695L,33696L,33697L,
+33698L,33699L,33700L,33701L,33702L,33703L,33704L,33705L,33706L,33707L,
+33708L,33709L,33710L,33711L,33712L,33713L,33714L,33715L,33716L,33717L,
+33718L,33719L,33720L,33721L,33722L,33723L,33724L,33725L,33726L,33727L,
+33728L,33729L,33730L,33731L,33732L,33733L,33734L,33735L,33736L,33737L,
+33738L,33739L,33740L,33741L,33742L,33743L,33744L,33745L,33746L,33747L,
+33748L,33749L,33750L,33751L,33752L,33753L,33754L,33755L,33756L,33757L,
+33758L,33759L,33760L,33761L,33762L,33763L,33764L,33765L,33766L,33767L,
+33768L,33769L,33770L,33771L,33772L,33773L,33774L,33775L,33776L,33777L,
+33778L,33779L,33780L,33781L,33782L,33783L,33784L,33785L,33786L,33787L,
+33788L,33789L,33790L,33791L,33792L,33793L,33794L,33795L,33796L,33797L,
+33798L,33799L,33800L,33801L,33802L,33803L,33804L,33805L,33806L,33807L,
+33808L,33809L,33810L,33811L,33812L,33813L,33814L,33815L,33816L,33817L,
+33818L,33819L,33820L,33821L,33822L,33823L,33824L,33825L,33826L,33827L,
+33828L,33829L,33830L,33831L,33832L,33833L,33834L,33835L,33836L,33837L,
+33838L,33839L,33840L,33841L,33842L,33843L,33844L,33845L,33846L,33847L,
+33848L,33849L,33850L,33851L,33852L,33853L,33854L,33855L,33856L,33857L,
+33858L,33859L,33860L,33861L,33862L,33863L,33864L,33865L,33866L,33867L,
+33868L,33869L,33870L,33871L,33872L,33873L,33874L,33875L,33876L,33877L,
+33878L,33879L,33880L,33881L,33882L,33883L,33884L,33885L,33886L,33887L,
+33888L,33889L,33890L,33891L,33892L,33893L,33894L,33895L,33896L,33897L,
+33898L,33899L,33900L,33901L,33902L,33903L,33904L,33905L,33906L,33907L,
+33908L,33909L,33910L,33911L,33912L,33913L,33914L,33915L,33916L,33917L,
+33918L,33919L,33920L,33921L,33922L,33923L,33924L,33925L,33926L,33927L,
+33928L,33929L,33930L,33931L,33932L,33933L,33934L,33935L,33936L,33937L,
+33938L,33939L,33940L,33941L,33942L,33943L,33944L,33945L,33946L,33947L,
+33948L,33949L,33950L,33951L,33952L,33953L,33954L,33955L,33956L,33957L,
+33958L,33959L,33960L,33961L,33962L,33963L,33964L,33965L,33966L,33967L,
+33968L,33969L,33970L,33971L,33972L,33973L,33974L,33975L,33976L,33977L,
+33978L,33979L,33980L,33981L,33982L,33983L,33984L,33985L,33986L,33987L,
+33988L,33989L,33990L,33991L,33992L,33993L,33994L,33995L,33996L,33997L,
+33998L,33999L,34000L,34001L,34002L,34003L,34004L,34005L,34006L,34007L,
+34008L,34009L,34010L,34011L,34012L,34013L,34014L,34015L,34016L,34017L,
+34018L,34019L,34020L,34021L,34022L,34023L,34024L,34025L,34026L,34027L,
+34028L,34029L,34030L,34031L,34032L,34033L,34034L,34035L,34036L,34037L,
+34038L,34039L,34040L,34041L,34042L,34043L,34044L,34045L,34046L,34047L,
+34048L,34049L,34050L,34051L,34052L,34053L,34054L,34055L,34056L,34057L,
+34058L,34059L,34060L,34061L,34062L,34063L,34064L,34065L,34066L,34067L,
+34068L,34069L,34070L,34071L,34072L,34073L,34074L,34075L,34076L,34077L,
+34078L,34079L,34080L,34081L,34082L,34083L,34084L,34085L,34086L,34087L,
+34088L,34089L,34090L,34091L,34092L,34093L,34094L,34095L,34096L,34097L,
+34098L,34099L,34100L,34101L,34102L,34103L,34104L,34105L,34106L,34107L,
+34108L,34109L,34110L,34111L,34112L,34113L,34114L,34115L,34116L,34117L,
+34118L,34119L,34120L,34121L,34122L,34123L,34124L,34125L,34126L,34127L,
+34128L,34129L,34130L,34131L,34132L,34133L,34134L,34135L,34136L,34137L,
+34138L,34139L,34140L,34141L,34142L,34143L,34144L,34145L,34146L,34147L,
+34148L,34149L,34150L,34151L,34152L,34153L,34154L,34155L,34156L,34157L,
+34158L,34159L,34160L,34161L,34162L,34163L,34164L,34165L,34166L,34167L,
+34168L,34169L,34170L,34171L,34172L,34173L,34174L,34175L,34176L,34177L,
+34178L,34179L,34180L,34181L,34182L,34183L,34184L,34185L,34186L,34187L,
+34188L,34189L,34190L,34191L,34192L,34193L,34194L,34195L,34196L,34197L,
+34198L,34199L,34200L,34201L,34202L,34203L,34204L,34205L,34206L,34207L,
+34208L,34209L,34210L,34211L,34212L,34213L,34214L,34215L,34216L,34217L,
+34218L,34219L,34220L,34221L,34222L,34223L,34224L,34225L,34226L,34227L,
+34228L,34229L,34230L,34231L,34232L,34233L,34234L,34235L,34236L,34237L,
+34238L,34239L,34240L,34241L,34242L,34243L,34244L,34245L,34246L,34247L,
+34248L,34249L,34250L,34251L,34252L,34253L,34254L,34255L,34256L,34257L,
+34258L,34259L,34260L,34261L,34262L,34263L,34264L,34265L,34266L,34267L,
+34268L,34269L,34270L,34271L,34272L,34273L,34274L,34275L,34276L,34277L,
+34278L,34279L,34280L,34281L,34282L,34283L,34284L,34285L,34286L,34287L,
+34288L,34289L,34290L,34291L,34292L,34293L,34294L,34295L,34296L,34297L,
+34298L,34299L,34300L,34301L,34302L,34303L,34304L,34305L,34306L,34307L,
+34308L,34309L,34310L,34311L,34312L,34313L,34314L,34315L,34316L,34317L,
+34318L,34319L,34320L,34321L,34322L,34323L,34324L,34325L,34326L,34327L,
+34328L,34329L,34330L,34331L,34332L,34333L,34334L,34335L,34336L,34337L,
+34338L,34339L,34340L,34341L,34342L,34343L,34344L,34345L,34346L,34347L,
+34348L,34349L,34350L,34351L,34352L,34353L,34354L,34355L,34356L,34357L,
+34358L,34359L,34360L,34361L,34362L,34363L,34364L,34365L,34366L,34367L,
+34368L,34369L,34370L,34371L,34372L,34373L,34374L,34375L,34376L,34377L,
+34378L,34379L,34380L,34381L,34382L,34383L,34384L,34385L,34386L,34387L,
+34388L,34389L,34390L,34391L,34392L,34393L,34394L,34395L,34396L,34397L,
+34398L,34399L,34400L,34401L,34402L,34403L,34404L,34405L,34406L,34407L,
+34408L,34409L,34410L,34411L,34412L,34413L,34414L,34415L,34416L,34417L,
+34418L,34419L,34420L,34421L,34422L,34423L,34424L,34425L,34426L,34427L,
+34428L,34429L,34430L,34431L,34432L,34433L,34434L,34435L,34436L,34437L,
+34438L,34439L,34440L,34441L,34442L,34443L,34444L,34445L,34446L,34447L,
+34448L,34449L,34450L,34451L,34452L,34453L,34454L,34455L,34456L,34457L,
+34458L,34459L,34460L,34461L,34462L,34463L,34464L,34465L,34466L,34467L,
+34468L,34469L,34470L,34471L,34472L,34473L,34474L,34475L,34476L,34477L,
+34478L,34479L,34480L,34481L,34482L,34483L,34484L,34485L,34486L,34487L,
+34488L,34489L,34490L,34491L,34492L,34493L,34494L,34495L,34496L,34497L,
+34498L,34499L,34500L,34501L,34502L,34503L,34504L,34505L,34506L,34507L,
+34508L,34509L,34510L,34511L,34512L,34513L,34514L,34515L,34516L,34517L,
+34518L,34519L,34520L,34521L,34522L,34523L,34524L,34525L,34526L,34527L,
+34528L,34529L,34530L,34531L,34532L,34533L,34534L,34535L,34536L,34537L,
+34538L,34539L,34540L,34541L,34542L,34543L,34544L,34545L,34546L,34547L,
+34548L,34549L,34550L,34551L,34552L,34553L,34554L,34555L,34556L,34557L,
+34558L,34559L,34560L,34561L,34562L,34563L,34564L,34565L,34566L,34567L,
+34568L,34569L,34570L,34571L,34572L,34573L,34574L,34575L,34576L,34577L,
+34578L,34579L,34580L,34581L,34582L,34583L,34584L,34585L,34586L,34587L,
+34588L,34589L,34590L,34591L,34592L,34593L,34594L,34595L,34596L,34597L,
+34598L,34599L,34600L,34601L,34602L,34603L,34604L,34605L,34606L,34607L,
+34608L,34609L,34610L,34611L,34612L,34613L,34614L,34615L,34616L,34617L,
+34618L,34619L,34620L,34621L,34622L,34623L,34624L,34625L,34626L,34627L,
+34628L,34629L,34630L,34631L,34632L,34633L,34634L,34635L,34636L,34637L,
+34638L,34639L,34640L,34641L,34642L,34643L,34644L,34645L,34646L,34647L,
+34648L,34649L,34650L,34651L,34652L,34653L,34654L,34655L,34656L,34657L,
+34658L,34659L,34660L,34661L,34662L,34663L,34664L,34665L,34666L,34667L,
+34668L,34669L,34670L,34671L,34672L,34673L,34674L,34675L,34676L,34677L,
+34678L,34679L,34680L,34681L,34682L,34683L,34684L,34685L,34686L,34687L,
+34688L,34689L,34690L,34691L,34692L,34693L,34694L,34695L,34696L,34697L,
+34698L,34699L,34700L,34701L,34702L,34703L,34704L,34705L,34706L,34707L,
+34708L,34709L,34710L,34711L,34712L,34713L,34714L,34715L,34716L,34717L,
+34718L,34719L,34720L,34721L,34722L,34723L,34724L,34725L,34726L,34727L,
+34728L,34729L,34730L,34731L,34732L,34733L,34734L,34735L,34736L,34737L,
+34738L,34739L,34740L,34741L,34742L,34743L,34744L,34745L,34746L,34747L,
+34748L,34749L,34750L,34751L,34752L,34753L,34754L,34755L,34756L,34757L,
+34758L,34759L,34760L,34761L,34762L,34763L,34764L,34765L,34766L,34767L,
+34768L,34769L,34770L,34771L,34772L,34773L,34774L,34775L,34776L,34777L,
+34778L,34779L,34780L,34781L,34782L,34783L,34784L,34785L,34786L,34787L,
+34788L,34789L,34790L,34791L,34792L,34793L,34794L,34795L,34796L,34797L,
+34798L,34799L,34800L,34801L,34802L,34803L,34804L,34805L,34806L,34807L,
+34808L,34809L,34810L,34811L,34812L,34813L,34814L,34815L,34816L,34817L,
+34818L,34819L,34820L,34821L,34822L,34823L,34824L,34825L,34826L,34827L,
+34828L,34829L,34830L,34831L,34832L,34833L,34834L,34835L,34836L,34837L,
+34838L,34839L,34840L,34841L,34842L,34843L,34844L,34845L,34846L,34847L,
+34848L,34849L,34850L,34851L,34852L,34853L,34854L,34855L,34856L,34857L,
+34858L,34859L,34860L,34861L,34862L,34863L,34864L,34865L,34866L,34867L,
+34868L,34869L,34870L,34871L,34872L,34873L,34874L,34875L,34876L,34877L,
+34878L,34879L,34880L,34881L,34882L,34883L,34884L,34885L,34886L,34887L,
+34888L,34889L,34890L,34891L,34892L,34893L,34894L,34895L,34896L,34897L,
+34898L,34899L,34900L,34901L,34902L,34903L,34904L,34905L,34906L,34907L,
+34908L,34909L,34910L,34911L,34912L,34913L,34914L,34915L,34916L,34917L,
+34918L,34919L,34920L,34921L,34922L,34923L,34924L,34925L,34926L,34927L,
+34928L,34929L,34930L,34931L,34932L,34933L,34934L,34935L,34936L,34937L,
+34938L,34939L,34940L,34941L,34942L,34943L,34944L,34945L,34946L,34947L,
+34948L,34949L,34950L,34951L,34952L,34953L,34954L,34955L,34956L,34957L,
+34958L,34959L,34960L,34961L,34962L,34963L,34964L,34965L,34966L,34967L,
+34968L,34969L,34970L,34971L,34972L,34973L,34974L,34975L,34976L,34977L,
+34978L,34979L,34980L,34981L,34982L,34983L,34984L,34985L,34986L,34987L,
+34988L,34989L,34990L,34991L,34992L,34993L,34994L,34995L,34996L,34997L,
+34998L,34999L,35000L,35001L,35002L,35003L,35004L,35005L,35006L,35007L,
+35008L,35009L,35010L,35011L,35012L,35013L,35014L,35015L,35016L,35017L,
+35018L,35019L,35020L,35021L,35022L,35023L,35024L,35025L,35026L,35027L,
+35028L,35029L,35030L,35031L,35032L,35033L,35034L,35035L,35036L,35037L,
+35038L,35039L,35040L,35041L,35042L,35043L,35044L,35045L,35046L,35047L,
+35048L,35049L,35050L,35051L,35052L,35053L,35054L,35055L,35056L,35057L,
+35058L,35059L,35060L,35061L,35062L,35063L,35064L,35065L,35066L,35067L,
+35068L,35069L,35070L,35071L,35072L,35073L,35074L,35075L,35076L,35077L,
+35078L,35079L,35080L,35081L,35082L,35083L,35084L,35085L,35086L,35087L,
+35088L,35089L,35090L,35091L,35092L,35093L,35094L,35095L,35096L,35097L,
+35098L,35099L,35100L,35101L,35102L,35103L,35104L,35105L,35106L,35107L,
+35108L,35109L,35110L,35111L,35112L,35113L,35114L,35115L,35116L,35117L,
+35118L,35119L,35120L,35121L,35122L,35123L,35124L,35125L,35126L,35127L,
+35128L,35129L,35130L,35131L,35132L,35133L,35134L,35135L,35136L,35137L,
+35138L,35139L,35140L,35141L,35142L,35143L,35144L,35145L,35146L,35147L,
+35148L,35149L,35150L,35151L,35152L,35153L,35154L,35155L,35156L,35157L,
+35158L,35159L,35160L,35161L,35162L,35163L,35164L,35165L,35166L,35167L,
+35168L,35169L,35170L,35171L,35172L,35173L,35174L,35175L,35176L,35177L,
+35178L,35179L,35180L,35181L,35182L,35183L,35184L,35185L,35186L,35187L,
+35188L,35189L,35190L,35191L,35192L,35193L,35194L,35195L,35196L,35197L,
+35198L,35199L,35200L,35201L,35202L,35203L,35204L,35205L,35206L,35207L,
+35208L,35209L,35210L,35211L,35212L,35213L,35214L,35215L,35216L,35217L,
+35218L,35219L,35220L,35221L,35222L,35223L,35224L,35225L,35226L,35227L,
+35228L,35229L,35230L,35231L,35232L,35233L,35234L,35235L,35236L,35237L,
+35238L,35239L,35240L,35241L,35242L,35243L,35244L,35245L,35246L,35247L,
+35248L,35249L,35250L,35251L,35252L,35253L,35254L,35255L,35256L,35257L,
+35258L,35259L,35260L,35261L,35262L,35263L,35264L,35265L,35266L,35267L,
+35268L,35269L,35270L,35271L,35272L,35273L,35274L,35275L,35276L,35277L,
+35278L,35279L,35280L,35281L,35282L,35283L,35284L,35285L,35286L,35287L,
+35288L,35289L,35290L,35291L,35292L,35293L,35294L,35295L,35296L,35297L,
+35298L,35299L,35300L,35301L,35302L,35303L,35304L,35305L,35306L,35307L,
+35308L,35309L,35310L,35311L,35312L,35313L,35314L,35315L,35316L,35317L,
+35318L,35319L,35320L,35321L,35322L,35323L,35324L,35325L,35326L,35327L,
+35328L,35329L,35330L,35331L,35332L,35333L,35334L,35335L,35336L,35337L,
+35338L,35339L,35340L,35341L,35342L,35343L,35344L,35345L,35346L,35347L,
+35348L,35349L,35350L,35351L,35352L,35353L,35354L,35355L,35356L,35357L,
+35358L,35359L,35360L,35361L,35362L,35363L,35364L,35365L,35366L,35367L,
+35368L,35369L,35370L,35371L,35372L,35373L,35374L,35375L,35376L,35377L,
+35378L,35379L,35380L,35381L,35382L,35383L,35384L,35385L,35386L,35387L,
+35388L,35389L,35390L,35391L,35392L,35393L,35394L,35395L,35396L,35397L,
+35398L,35399L,35400L,35401L,35402L,35403L,35404L,35405L,35406L,35407L,
+35408L,35409L,35410L,35411L,35412L,35413L,35414L,35415L,35416L,35417L,
+35418L,35419L,35420L,35421L,35422L,35423L,35424L,35425L,35426L,35427L,
+35428L,35429L,35430L,35431L,35432L,35433L,35434L,35435L,35436L,35437L,
+35438L,35439L,35440L,35441L,35442L,35443L,35444L,35445L,35446L,35447L,
+35448L,35449L,35450L,35451L,35452L,35453L,35454L,35455L,35456L,35457L,
+35458L,35459L,35460L,35461L,35462L,35463L,35464L,35465L,35466L,35467L,
+35468L,35469L,35470L,35471L,35472L,35473L,35474L,35475L,35476L,35477L,
+35478L,35479L,35480L,35481L,35482L,35483L,35484L,35485L,35486L,35487L,
+35488L,35489L,35490L,35491L,35492L,35493L,35494L,35495L,35496L,35497L,
+35498L,35499L,35500L,35501L,35502L,35503L,35504L,35505L,35506L,35507L,
+35508L,35509L,35510L,35511L,35512L,35513L,35514L,35515L,35516L,35517L,
+35518L,35519L,35520L,35521L,35522L,35523L,35524L,35525L,35526L,35527L,
+35528L,35529L,35530L,35531L,35532L,35533L,35534L,35535L,35536L,35537L,
+35538L,35539L,35540L,35541L,35542L,35543L,35544L,35545L,35546L,35547L,
+35548L,35549L,35550L,35551L,35552L,35553L,35554L,35555L,35556L,35557L,
+35558L,35559L,35560L,35561L,35562L,35563L,35564L,35565L,35566L,35567L,
+35568L,35569L,35570L,35571L,35572L,35573L,35574L,35575L,35576L,35577L,
+35578L,35579L,35580L,35581L,35582L,35583L,35584L,35585L,35586L,35587L,
+35588L,35589L,35590L,35591L,35592L,35593L,35594L,35595L,35596L,35597L,
+35598L,35599L,35600L,35601L,35602L,35603L,35604L,35605L,35606L,35607L,
+35608L,35609L,35610L,35611L,35612L,35613L,35614L,35615L,35616L,35617L,
+35618L,35619L,35620L,35621L,35622L,35623L,35624L,35625L,35626L,35627L,
+35628L,35629L,35630L,35631L,35632L,35633L,35634L,35635L,35636L,35637L,
+35638L,35639L,35640L,35641L,35642L,35643L,35644L,35645L,35646L,35647L,
+35648L,35649L,35650L,35651L,35652L,35653L,35654L,35655L,35656L,35657L,
+35658L,35659L,35660L,35661L,35662L,35663L,35664L,35665L,35666L,35667L,
+35668L,35669L,35670L,35671L,35672L,35673L,35674L,35675L,35676L,35677L,
+35678L,35679L,35680L,35681L,35682L,35683L,35684L,35685L,35686L,35687L,
+35688L,35689L,35690L,35691L,35692L,35693L,35694L,35695L,35696L,35697L,
+35698L,35699L,35700L,35701L,35702L,35703L,35704L,35705L,35706L,35707L,
+35708L,35709L,35710L,35711L,35712L,35713L,35714L,35715L,35716L,35717L,
+35718L,35719L,35720L,35721L,35722L,35723L,35724L,35725L,35726L,35727L,
+35728L,35729L,35730L,35731L,35732L,35733L,35734L,35735L,35736L,35737L,
+35738L,35739L,35740L,35741L,35742L,35743L,35744L,35745L,35746L,35747L,
+35748L,35749L,35750L,35751L,35752L,35753L,35754L,35755L,35756L,35757L,
+35758L,35759L,35760L,35761L,35762L,35763L,35764L,35765L,35766L,35767L,
+35768L,35769L,35770L,35771L,35772L,35773L,35774L,35775L,35776L,35777L,
+35778L,35779L,35780L,35781L,35782L,35783L,35784L,35785L,35786L,35787L,
+35788L,35789L,35790L,35791L,35792L,35793L,35794L,35795L,35796L,35797L,
+35798L,35799L,35800L,35801L,35802L,35803L,35804L,35805L,35806L,35807L,
+35808L,35809L,35810L,35811L,35812L,35813L,35814L,35815L,35816L,35817L,
+35818L,35819L,35820L,35821L,35822L,35823L,35824L,35825L,35826L,35827L,
+35828L,35829L,35830L,35831L,35832L,35833L,35834L,35835L,35836L,35837L,
+35838L,35839L,35840L,35841L,35842L,35843L,35844L,35845L,35846L,35847L,
+35848L,35849L,35850L,35851L,35852L,35853L,35854L,35855L,35856L,35857L,
+35858L,35859L,35860L,35861L,35862L,35863L,35864L,35865L,35866L,35867L,
+35868L,35869L,35870L,35871L,35872L,35873L,35874L,35875L,35876L,35877L,
+35878L,35879L,35880L,35881L,35882L,35883L,35884L,35885L,35886L,35887L,
+35888L,35889L,35890L,35891L,35892L,35893L,35894L,35895L,35896L,35897L,
+35898L,35899L,35900L,35901L,35902L,35903L,35904L,35905L,35906L,35907L,
+35908L,35909L,35910L,35911L,35912L,35913L,35914L,35915L,35916L,35917L,
+35918L,35919L,35920L,35921L,35922L,35923L,35924L,35925L,35926L,35927L,
+35928L,35929L,35930L,35931L,35932L,35933L,35934L,35935L,35936L,35937L,
+35938L,35939L,35940L,35941L,35942L,35943L,35944L,35945L,35946L,35947L,
+35948L,35949L,35950L,35951L,35952L,35953L,35954L,35955L,35956L,35957L,
+35958L,35959L,35960L,35961L,35962L,35963L,35964L,35965L,35966L,35967L,
+35968L,35969L,35970L,35971L,35972L,35973L,35974L,35975L,35976L,35977L,
+35978L,35979L,35980L,35981L,35982L,35983L,35984L,35985L,35986L,35987L,
+35988L,35989L,35990L,35991L,35992L,35993L,35994L,35995L,35996L,35997L,
+35998L,35999L,36000L,36001L,36002L,36003L,36004L,36005L,36006L,36007L,
+36008L,36009L,36010L,36011L,36012L,36013L,36014L,36015L,36016L,36017L,
+36018L,36019L,36020L,36021L,36022L,36023L,36024L,36025L,36026L,36027L,
+36028L,36029L,36030L,36031L,36032L,36033L,36034L,36035L,36036L,36037L,
+36038L,36039L,36040L,36041L,36042L,36043L,36044L,36045L,36046L,36047L,
+36048L,36049L,36050L,36051L,36052L,36053L,36054L,36055L,36056L,36057L,
+36058L,36059L,36060L,36061L,36062L,36063L,36064L,36065L,36066L,36067L,
+36068L,36069L,36070L,36071L,36072L,36073L,36074L,36075L,36076L,36077L,
+36078L,36079L,36080L,36081L,36082L,36083L,36084L,36085L,36086L,36087L,
+36088L,36089L,36090L,36091L,36092L,36093L,36094L,36095L,36096L,36097L,
+36098L,36099L,36100L,36101L,36102L,36103L,36104L,36105L,36106L,36107L,
+36108L,36109L,36110L,36111L,36112L,36113L,36114L,36115L,36116L,36117L,
+36118L,36119L,36120L,36121L,36122L,36123L,36124L,36125L,36126L,36127L,
+36128L,36129L,36130L,36131L,36132L,36133L,36134L,36135L,36136L,36137L,
+36138L,36139L,36140L,36141L,36142L,36143L,36144L,36145L,36146L,36147L,
+36148L,36149L,36150L,36151L,36152L,36153L,36154L,36155L,36156L,36157L,
+36158L,36159L,36160L,36161L,36162L,36163L,36164L,36165L,36166L,36167L,
+36168L,36169L,36170L,36171L,36172L,36173L,36174L,36175L,36176L,36177L,
+36178L,36179L,36180L,36181L,36182L,36183L,36184L,36185L,36186L,36187L,
+36188L,36189L,36190L,36191L,36192L,36193L,36194L,36195L,36196L,36197L,
+36198L,36199L,36200L,36201L,36202L,36203L,36204L,36205L,36206L,36207L,
+36208L,36209L,36210L,36211L,36212L,36213L,36214L,36215L,36216L,36217L,
+36218L,36219L,36220L,36221L,36222L,36223L,36224L,36225L,36226L,36227L,
+36228L,36229L,36230L,36231L,36232L,36233L,36234L,36235L,36236L,36237L,
+36238L,36239L,36240L,36241L,36242L,36243L,36244L,36245L,36246L,36247L,
+36248L,36249L,36250L,36251L,36252L,36253L,36254L,36255L,36256L,36257L,
+36258L,36259L,36260L,36261L,36262L,36263L,36264L,36265L,36266L,36267L,
+36268L,36269L,36270L,36271L,36272L,36273L,36274L,36275L,36276L,36277L,
+36278L,36279L,36280L,36281L,36282L,36283L,36284L,36285L,36286L,36287L,
+36288L,36289L,36290L,36291L,36292L,36293L,36294L,36295L,36296L,36297L,
+36298L,36299L,36300L,36301L,36302L,36303L,36304L,36305L,36306L,36307L,
+36308L,36309L,36310L,36311L,36312L,36313L,36314L,36315L,36316L,36317L,
+36318L,36319L,36320L,36321L,36322L,36323L,36324L,36325L,36326L,36327L,
+36328L,36329L,36330L,36331L,36332L,36333L,36334L,36335L,36336L,36337L,
+36338L,36339L,36340L,36341L,36342L,36343L,36344L,36345L,36346L,36347L,
+36348L,36349L,36350L,36351L,36352L,36353L,36354L,36355L,36356L,36357L,
+36358L,36359L,36360L,36361L,36362L,36363L,36364L,36365L,36366L,36367L,
+36368L,36369L,36370L,36371L,36372L,36373L,36374L,36375L,36376L,36377L,
+36378L,36379L,36380L,36381L,36382L,36383L,36384L,36385L,36386L,36387L,
+36388L,36389L,36390L,36391L,36392L,36393L,36394L,36395L,36396L,36397L,
+36398L,36399L,36400L,36401L,36402L,36403L,36404L,36405L,36406L,36407L,
+36408L,36409L,36410L,36411L,36412L,36413L,36414L,36415L,36416L,36417L,
+36418L,36419L,36420L,36421L,36422L,36423L,36424L,36425L,36426L,36427L,
+36428L,36429L,36430L,36431L,36432L,36433L,36434L,36435L,36436L,36437L,
+36438L,36439L,36440L,36441L,36442L,36443L,36444L,36445L,36446L,36447L,
+36448L,36449L,36450L,36451L,36452L,36453L,36454L,36455L,36456L,36457L,
+36458L,36459L,36460L,36461L,36462L,36463L,36464L,36465L,36466L,36467L,
+36468L,36469L,36470L,36471L,36472L,36473L,36474L,36475L,36476L,36477L,
+36478L,36479L,36480L,36481L,36482L,36483L,36484L,36485L,36486L,36487L,
+36488L,36489L,36490L,36491L,36492L,36493L,36494L,36495L,36496L,36497L,
+36498L,36499L,36500L,36501L,36502L,36503L,36504L,36505L,36506L,36507L,
+36508L,36509L,36510L,36511L,36512L,36513L,36514L,36515L,36516L,36517L,
+36518L,36519L,36520L,36521L,36522L,36523L,36524L,36525L,36526L,36527L,
+36528L,36529L,36530L,36531L,36532L,36533L,36534L,36535L,36536L,36537L,
+36538L,36539L,36540L,36541L,36542L,36543L,36544L,36545L,36546L,36547L,
+36548L,36549L,36550L,36551L,36552L,36553L,36554L,36555L,36556L,36557L,
+36558L,36559L,36560L,36561L,36562L,36563L,36564L,36565L,36566L,36567L,
+36568L,36569L,36570L,36571L,36572L,36573L,36574L,36575L,36576L,36577L,
+36578L,36579L,36580L,36581L,36582L,36583L,36584L,36585L,36586L,36587L,
+36588L,36589L,36590L,36591L,36592L,36593L,36594L,36595L,36596L,36597L,
+36598L,36599L,36600L,36601L,36602L,36603L,36604L,36605L,36606L,36607L,
+36608L,36609L,36610L,36611L,36612L,36613L,36614L,36615L,36616L,36617L,
+36618L,36619L,36620L,36621L,36622L,36623L,36624L,36625L,36626L,36627L,
+36628L,36629L,36630L,36631L,36632L,36633L,36634L,36635L,36636L,36637L,
+36638L,36639L,36640L,36641L,36642L,36643L,36644L,36645L,36646L,36647L,
+36648L,36649L,36650L,36651L,36652L,36653L,36654L,36655L,36656L,36657L,
+36658L,36659L,36660L,36661L,36662L,36663L,36664L,36665L,36666L,36667L,
+36668L,36669L,36670L,36671L,36672L,36673L,36674L,36675L,36676L,36677L,
+36678L,36679L,36680L,36681L,36682L,36683L,36684L,36685L,36686L,36687L,
+36688L,36689L,36690L,36691L,36692L,36693L,36694L,36695L,36696L,36697L,
+36698L,36699L,36700L,36701L,36702L,36703L,36704L,36705L,36706L,36707L,
+36708L,36709L,36710L,36711L,36712L,36713L,36714L,36715L,36716L,36717L,
+36718L,36719L,36720L,36721L,36722L,36723L,36724L,36725L,36726L,36727L,
+36728L,36729L,36730L,36731L,36732L,36733L,36734L,36735L,36736L,36737L,
+36738L,36739L,36740L,36741L,36742L,36743L,36744L,36745L,36746L,36747L,
+36748L,36749L,36750L,36751L,36752L,36753L,36754L,36755L,36756L,36757L,
+36758L,36759L,36760L,36761L,36762L,36763L,36764L,36765L,36766L,36767L,
+36768L,36769L,36770L,36771L,36772L,36773L,36774L,36775L,36776L,36777L,
+36778L,36779L,36780L,36781L,36782L,36783L,36784L,36785L,36786L,36787L,
+36788L,36789L,36790L,36791L,36792L,36793L,36794L,36795L,36796L,36797L,
+36798L,36799L,36800L,36801L,36802L,36803L,36804L,36805L,36806L,36807L,
+36808L,36809L,36810L,36811L,36812L,36813L,36814L,36815L,36816L,36817L,
+36818L,36819L,36820L,36821L,36822L,36823L,36824L,36825L,36826L,36827L,
+36828L,36829L,36830L,36831L,36832L,36833L,36834L,36835L,36836L,36837L,
+36838L,36839L,36840L,36841L,36842L,36843L,36844L,36845L,36846L,36847L,
+36848L,36849L,36850L,36851L,36852L,36853L,36854L,36855L,36856L,36857L,
+36858L,36859L,36860L,36861L,36862L,36863L,36864L,36865L,36866L,36867L,
+36868L,36869L,36870L,36871L,36872L,36873L,36874L,36875L,36876L,36877L,
+36878L,36879L,36880L,36881L,36882L,36883L,36884L,36885L,36886L,36887L,
+36888L,36889L,36890L,36891L,36892L,36893L,36894L,36895L,36896L,36897L,
+36898L,36899L,36900L,36901L,36902L,36903L,36904L,36905L,36906L,36907L,
+36908L,36909L,36910L,36911L,36912L,36913L,36914L,36915L,36916L,36917L,
+36918L,36919L,36920L,36921L,36922L,36923L,36924L,36925L,36926L,36927L,
+36928L,36929L,36930L,36931L,36932L,36933L,36934L,36935L,36936L,36937L,
+36938L,36939L,36940L,36941L,36942L,36943L,36944L,36945L,36946L,36947L,
+36948L,36949L,36950L,36951L,36952L,36953L,36954L,36955L,36956L,36957L,
+36958L,36959L,36960L,36961L,36962L,36963L,36964L,36965L,36966L,36967L,
+36968L,36969L,36970L,36971L,36972L,36973L,36974L,36975L,36976L,36977L,
+36978L,36979L,36980L,36981L,36982L,36983L,36984L,36985L,36986L,36987L,
+36988L,36989L,36990L,36991L,36992L,36993L,36994L,36995L,36996L,36997L,
+36998L,36999L,37000L,37001L,37002L,37003L,37004L,37005L,37006L,37007L,
+37008L,37009L,37010L,37011L,37012L,37013L,37014L,37015L,37016L,37017L,
+37018L,37019L,37020L,37021L,37022L,37023L,37024L,37025L,37026L,37027L,
+37028L,37029L,37030L,37031L,37032L,37033L,37034L,37035L,37036L,37037L,
+37038L,37039L,37040L,37041L,37042L,37043L,37044L,37045L,37046L,37047L,
+37048L,37049L,37050L,37051L,37052L,37053L,37054L,37055L,37056L,37057L,
+37058L,37059L,37060L,37061L,37062L,37063L,37064L,37065L,37066L,37067L,
+37068L,37069L,37070L,37071L,37072L,37073L,37074L,37075L,37076L,37077L,
+37078L,37079L,37080L,37081L,37082L,37083L,37084L,37085L,37086L,37087L,
+37088L,37089L,37090L,37091L,37092L,37093L,37094L,37095L,37096L,37097L,
+37098L,37099L,37100L,37101L,37102L,37103L,37104L,37105L,37106L,37107L,
+37108L,37109L,37110L,37111L,37112L,37113L,37114L,37115L,37116L,37117L,
+37118L,37119L,37120L,37121L,37122L,37123L,37124L,37125L,37126L,37127L,
+37128L,37129L,37130L,37131L,37132L,37133L,37134L,37135L,37136L,37137L,
+37138L,37139L,37140L,37141L,37142L,37143L,37144L,37145L,37146L,37147L,
+37148L,37149L,37150L,37151L,37152L,37153L,37154L,37155L,37156L,37157L,
+37158L,37159L,37160L,37161L,37162L,37163L,37164L,37165L,37166L,37167L,
+37168L,37169L,37170L,37171L,37172L,37173L,37174L,37175L,37176L,37177L,
+37178L,37179L,37180L,37181L,37182L,37183L,37184L,37185L,37186L,37187L,
+37188L,37189L,37190L,37191L,37192L,37193L,37194L,37195L,37196L,37197L,
+37198L,37199L,37200L,37201L,37202L,37203L,37204L,37205L,37206L,37207L,
+37208L,37209L,37210L,37211L,37212L,37213L,37214L,37215L,37216L,37217L,
+37218L,37219L,37220L,37221L,37222L,37223L,37224L,37225L,37226L,37227L,
+37228L,37229L,37230L,37231L,37232L,37233L,37234L,37235L,37236L,37237L,
+37238L,37239L,37240L,37241L,37242L,37243L,37244L,37245L,37246L,37247L,
+37248L,37249L,37250L,37251L,37252L,37253L,37254L,37255L,37256L,37257L,
+37258L,37259L,37260L,37261L,37262L,37263L,37264L,37265L,37266L,37267L,
+37268L,37269L,37270L,37271L,37272L,37273L,37274L,37275L,37276L,37277L,
+37278L,37279L,37280L,37281L,37282L,37283L,37284L,37285L,37286L,37287L,
+37288L,37289L,37290L,37291L,37292L,37293L,37294L,37295L,37296L,37297L,
+37298L,37299L,37300L,37301L,37302L,37303L,37304L,37305L,37306L,37307L,
+37308L,37309L,37310L,37311L,37312L,37313L,37314L,37315L,37316L,37317L,
+37318L,37319L,37320L,37321L,37322L,37323L,37324L,37325L,37326L,37327L,
+37328L,37329L,37330L,37331L,37332L,37333L,37334L,37335L,37336L,37337L,
+37338L,37339L,37340L,37341L,37342L,37343L,37344L,37345L,37346L,37347L,
+37348L,37349L,37350L,37351L,37352L,37353L,37354L,37355L,37356L,37357L,
+37358L,37359L,37360L,37361L,37362L,37363L,37364L,37365L,37366L,37367L,
+37368L,37369L,37370L,37371L,37372L,37373L,37374L,37375L,37376L,37377L,
+37378L,37379L,37380L,37381L,37382L,37383L,37384L,37385L,37386L,37387L,
+37388L,37389L,37390L,37391L,37392L,37393L,37394L,37395L,37396L,37397L,
+37398L,37399L,37400L,37401L,37402L,37403L,37404L,37405L,37406L,37407L,
+37408L,37409L,37410L,37411L,37412L,37413L,37414L,37415L,37416L,37417L,
+37418L,37419L,37420L,37421L,37422L,37423L,37424L,37425L,37426L,37427L,
+37428L,37429L,37430L,37431L,37432L,37433L,37434L,37435L,37436L,37437L,
+37438L,37439L,37440L,37441L,37442L,37443L,37444L,37445L,37446L,37447L,
+37448L,37449L,37450L,37451L,37452L,37453L,37454L,37455L,37456L,37457L,
+37458L,37459L,37460L,37461L,37462L,37463L,37464L,37465L,37466L,37467L,
+37468L,37469L,37470L,37471L,37472L,37473L,37474L,37475L,37476L,37477L,
+37478L,37479L,37480L,37481L,37482L,37483L,37484L,37485L,37486L,37487L,
+37488L,37489L,37490L,37491L,37492L,37493L,37494L,37495L,37496L,37497L,
+37498L,37499L,37500L,37501L,37502L,37503L,37504L,37505L,37506L,37507L,
+37508L,37509L,37510L,37511L,37512L,37513L,37514L,37515L,37516L,37517L,
+37518L,37519L,37520L,37521L,37522L,37523L,37524L,37525L,37526L,37527L,
+37528L,37529L,37530L,37531L,37532L,37533L,37534L,37535L,37536L,37537L,
+37538L,37539L,37540L,37541L,37542L,37543L,37544L,37545L,37546L,37547L,
+37548L,37549L,37550L,37551L,37552L,37553L,37554L,37555L,37556L,37557L,
+37558L,37559L,37560L,37561L,37562L,37563L,37564L,37565L,37566L,37567L,
+37568L,37569L,37570L,37571L,37572L,37573L,37574L,37575L,37576L,37577L,
+37578L,37579L,37580L,37581L,37582L,37583L,37584L,37585L,37586L,37587L,
+37588L,37589L,37590L,37591L,37592L,37593L,37594L,37595L,37596L,37597L,
+37598L,37599L,37600L,37601L,37602L,37603L,37604L,37605L,37606L,37607L,
+37608L,37609L,37610L,37611L,37612L,37613L,37614L,37615L,37616L,37617L,
+37618L,37619L,37620L,37621L,37622L,37623L,37624L,37625L,37626L,37627L,
+37628L,37629L,37630L,37631L,37632L,37633L,37634L,37635L,37636L,37637L,
+37638L,37639L,37640L,37641L,37642L,37643L,37644L,37645L,37646L,37647L,
+37648L,37649L,37650L,37651L,37652L,37653L,37654L,37655L,37656L,37657L,
+37658L,37659L,37660L,37661L,37662L,37663L,37664L,37665L,37666L,37667L,
+37668L,37669L,37670L,37671L,37672L,37673L,37674L,37675L,37676L,37677L,
+37678L,37679L,37680L,37681L,37682L,37683L,37684L,37685L,37686L,37687L,
+37688L,37689L,37690L,37691L,37692L,37693L,37694L,37695L,37696L,37697L,
+37698L,37699L,37700L,37701L,37702L,37703L,37704L,37705L,37706L,37707L,
+37708L,37709L,37710L,37711L,37712L,37713L,37714L,37715L,37716L,37717L,
+37718L,37719L,37720L,37721L,37722L,37723L,37724L,37725L,37726L,37727L,
+37728L,37729L,37730L,37731L,37732L,37733L,37734L,37735L,37736L,37737L,
+37738L,37739L,37740L,37741L,37742L,37743L,37744L,37745L,37746L,37747L,
+37748L,37749L,37750L,37751L,37752L,37753L,37754L,37755L,37756L,37757L,
+37758L,37759L,37760L,37761L,37762L,37763L,37764L,37765L,37766L,37767L,
+37768L,37769L,37770L,37771L,37772L,37773L,37774L,37775L,37776L,37777L,
+37778L,37779L,37780L,37781L,37782L,37783L,37784L,37785L,37786L,37787L,
+37788L,37789L,37790L,37791L,37792L,37793L,37794L,37795L,37796L,37797L,
+37798L,37799L,37800L,37801L,37802L,37803L,37804L,37805L,37806L,37807L,
+37808L,37809L,37810L,37811L,37812L,37813L,37814L,37815L,37816L,37817L,
+37818L,37819L,37820L,37821L,37822L,37823L,37824L,37825L,37826L,37827L,
+37828L,37829L,37830L,37831L,37832L,37833L,37834L,37835L,37836L,37837L,
+37838L,37839L,37840L,37841L,37842L,37843L,37844L,37845L,37846L,37847L,
+37848L,37849L,37850L,37851L,37852L,37853L,37854L,37855L,37856L,37857L,
+37858L,37859L,37860L,37861L,37862L,37863L,37864L,37865L,37866L,37867L,
+37868L,37869L,37870L,37871L,37872L,37873L,37874L,37875L,37876L,37877L,
+37878L,37879L,37880L,37881L,37882L,37883L,37884L,37885L,37886L,37887L,
+37888L,37889L,37890L,37891L,37892L,37893L,37894L,37895L,37896L,37897L,
+37898L,37899L,37900L,37901L,37902L,37903L,37904L,37905L,37906L,37907L,
+37908L,37909L,37910L,37911L,37912L,37913L,37914L,37915L,37916L,37917L,
+37918L,37919L,37920L,37921L,37922L,37923L,37924L,37925L,37926L,37927L,
+37928L,37929L,37930L,37931L,37932L,37933L,37934L,37935L,37936L,37937L,
+37938L,37939L,37940L,37941L,37942L,37943L,37944L,37945L,37946L,37947L,
+37948L,37949L,37950L,37951L,37952L,37953L,37954L,37955L,37956L,37957L,
+37958L,37959L,37960L,37961L,37962L,37963L,37964L,37965L,37966L,37967L,
+37968L,37969L,37970L,37971L,37972L,37973L,37974L,37975L,37976L,37977L,
+37978L,37979L,37980L,37981L,37982L,37983L,37984L,37985L,37986L,37987L,
+37988L,37989L,37990L,37991L,37992L,37993L,37994L,37995L,37996L,37997L,
+37998L,37999L,38000L,38001L,38002L,38003L,38004L,38005L,38006L,38007L,
+38008L,38009L,38010L,38011L,38012L,38013L,38014L,38015L,38016L,38017L,
+38018L,38019L,38020L,38021L,38022L,38023L,38024L,38025L,38026L,38027L,
+38028L,38029L,38030L,38031L,38032L,38033L,38034L,38035L,38036L,38037L,
+38038L,38039L,38040L,38041L,38042L,38043L,38044L,38045L,38046L,38047L,
+38048L,38049L,38050L,38051L,38052L,38053L,38054L,38055L,38056L,38057L,
+38058L,38059L,38060L,38061L,38062L,38063L,38064L,38065L,38066L,38067L,
+38068L,38069L,38070L,38071L,38072L,38073L,38074L,38075L,38076L,38077L,
+38078L,38079L,38080L,38081L,38082L,38083L,38084L,38085L,38086L,38087L,
+38088L,38089L,38090L,38091L,38092L,38093L,38094L,38095L,38096L,38097L,
+38098L,38099L,38100L,38101L,38102L,38103L,38104L,38105L,38106L,38107L,
+38108L,38109L,38110L,38111L,38112L,38113L,38114L,38115L,38116L,38117L,
+38118L,38119L,38120L,38121L,38122L,38123L,38124L,38125L,38126L,38127L,
+38128L,38129L,38130L,38131L,38132L,38133L,38134L,38135L,38136L,38137L,
+38138L,38139L,38140L,38141L,38142L,38143L,38144L,38145L,38146L,38147L,
+38148L,38149L,38150L,38151L,38152L,38153L,38154L,38155L,38156L,38157L,
+38158L,38159L,38160L,38161L,38162L,38163L,38164L,38165L,38166L,38167L,
+38168L,38169L,38170L,38171L,38172L,38173L,38174L,38175L,38176L,38177L,
+38178L,38179L,38180L,38181L,38182L,38183L,38184L,38185L,38186L,38187L,
+38188L,38189L,38190L,38191L,38192L,38193L,38194L,38195L,38196L,38197L,
+38198L,38199L,38200L,38201L,38202L,38203L,38204L,38205L,38206L,38207L,
+38208L,38209L,38210L,38211L,38212L,38213L,38214L,38215L,38216L,38217L,
+38218L,38219L,38220L,38221L,38222L,38223L,38224L,38225L,38226L,38227L,
+38228L,38229L,38230L,38231L,38232L,38233L,38234L,38235L,38236L,38237L,
+38238L,38239L,38240L,38241L,38242L,38243L,38244L,38245L,38246L,38247L,
+38248L,38249L,38250L,38251L,38252L,38253L,38254L,38255L,38256L,38257L,
+38258L,38259L,38260L,38261L,38262L,38263L,38264L,38265L,38266L,38267L,
+38268L,38269L,38270L,38271L,38272L,38273L,38274L,38275L,38276L,38277L,
+38278L,38279L,38280L,38281L,38282L,38283L,38284L,38285L,38286L,38287L,
+38288L,38289L,38290L,38291L,38292L,38293L,38294L,38295L,38296L,38297L,
+38298L,38299L,38300L,38301L,38302L,38303L,38304L,38305L,38306L,38307L,
+38308L,38309L,38310L,38311L,38312L,38313L,38314L,38315L,38316L,38317L,
+38318L,38319L,38320L,38321L,38322L,38323L,38324L,38325L,38326L,38327L,
+38328L,38329L,38330L,38331L,38332L,38333L,38334L,38335L,38336L,38337L,
+38338L,38339L,38340L,38341L,38342L,38343L,38344L,38345L,38346L,38347L,
+38348L,38349L,38350L,38351L,38352L,38353L,38354L,38355L,38356L,38357L,
+38358L,38359L,38360L,38361L,38362L,38363L,38364L,38365L,38366L,38367L,
+38368L,38369L,38370L,38371L,38372L,38373L,38374L,38375L,38376L,38377L,
+38378L,38379L,38380L,38381L,38382L,38383L,38384L,38385L,38386L,38387L,
+38388L,38389L,38390L,38391L,38392L,38393L,38394L,38395L,38396L,38397L,
+38398L,38399L,38400L,38401L,38402L,38403L,38404L,38405L,38406L,38407L,
+38408L,38409L,38410L,38411L,38412L,38413L,38414L,38415L,38416L,38417L,
+38418L,38419L,38420L,38421L,38422L,38423L,38424L,38425L,38426L,38427L,
+38428L,38429L,38430L,38431L,38432L,38433L,38434L,38435L,38436L,38437L,
+38438L,38439L,38440L,38441L,38442L,38443L,38444L,38445L,38446L,38447L,
+38448L,38449L,38450L,38451L,38452L,38453L,38454L,38455L,38456L,38457L,
+38458L,38459L,38460L,38461L,38462L,38463L,38464L,38465L,38466L,38467L,
+38468L,38469L,38470L,38471L,38472L,38473L,38474L,38475L,38476L,38477L,
+38478L,38479L,38480L,38481L,38482L,38483L,38484L,38485L,38486L,38487L,
+38488L,38489L,38490L,38491L,38492L,38493L,38494L,38495L,38496L,38497L,
+38498L,38499L,38500L,38501L,38502L,38503L,38504L,38505L,38506L,38507L,
+38508L,38509L,38510L,38511L,38512L,38513L,38514L,38515L,38516L,38517L,
+38518L,38519L,38520L,38521L,38522L,38523L,38524L,38525L,38526L,38527L,
+38528L,38529L,38530L,38531L,38532L,38533L,38534L,38535L,38536L,38537L,
+38538L,38539L,38540L,38541L,38542L,38543L,38544L,38545L,38546L,38547L,
+38548L,38549L,38550L,38551L,38552L,38553L,38554L,38555L,38556L,38557L,
+38558L,38559L,38560L,38561L,38562L,38563L,38564L,38565L,38566L,38567L,
+38568L,38569L,38570L,38571L,38572L,38573L,38574L,38575L,38576L,38577L,
+38578L,38579L,38580L,38581L,38582L,38583L,38584L,38585L,38586L,38587L,
+38588L,38589L,38590L,38591L,38592L,38593L,38594L,38595L,38596L,38597L,
+38598L,38599L,38600L,38601L,38602L,38603L,38604L,38605L,38606L,38607L,
+38608L,38609L,38610L,38611L,38612L,38613L,38614L,38615L,38616L,38617L,
+38618L,38619L,38620L,38621L,38622L,38623L,38624L,38625L,38626L,38627L,
+38628L,38629L,38630L,38631L,38632L,38633L,38634L,38635L,38636L,38637L,
+38638L,38639L,38640L,38641L,38642L,38643L,38644L,38645L,38646L,38647L,
+38648L,38649L,38650L,38651L,38652L,38653L,38654L,38655L,38656L,38657L,
+38658L,38659L,38660L,38661L,38662L,38663L,38664L,38665L,38666L,38667L,
+38668L,38669L,38670L,38671L,38672L,38673L,38674L,38675L,38676L,38677L,
+38678L,38679L,38680L,38681L,38682L,38683L,38684L,38685L,38686L,38687L,
+38688L,38689L,38690L,38691L,38692L,38693L,38694L,38695L,38696L,38697L,
+38698L,38699L,38700L,38701L,38702L,38703L,38704L,38705L,38706L,38707L,
+38708L,38709L,38710L,38711L,38712L,38713L,38714L,38715L,38716L,38717L,
+38718L,38719L,38720L,38721L,38722L,38723L,38724L,38725L,38726L,38727L,
+38728L,38729L,38730L,38731L,38732L,38733L,38734L,38735L,38736L,38737L,
+38738L,38739L,38740L,38741L,38742L,38743L,38744L,38745L,38746L,38747L,
+38748L,38749L,38750L,38751L,38752L,38753L,38754L,38755L,38756L,38757L,
+38758L,38759L,38760L,38761L,38762L,38763L,38764L,38765L,38766L,38767L,
+38768L,38769L,38770L,38771L,38772L,38773L,38774L,38775L,38776L,38777L,
+38778L,38779L,38780L,38781L,38782L,38783L,38784L,38785L,38786L,38787L,
+38788L,38789L,38790L,38791L,38792L,38793L,38794L,38795L,38796L,38797L,
+38798L,38799L,38800L,38801L,38802L,38803L,38804L,38805L,38806L,38807L,
+38808L,38809L,38810L,38811L,38812L,38813L,38814L,38815L,38816L,38817L,
+38818L,38819L,38820L,38821L,38822L,38823L,38824L,38825L,38826L,38827L,
+38828L,38829L,38830L,38831L,38832L,38833L,38834L,38835L,38836L,38837L,
+38838L,38839L,38840L,38841L,38842L,38843L,38844L,38845L,38846L,38847L,
+38848L,38849L,38850L,38851L,38852L,38853L,38854L,38855L,38856L,38857L,
+38858L,38859L,38860L,38861L,38862L,38863L,38864L,38865L,38866L,38867L,
+38868L,38869L,38870L,38871L,38872L,38873L,38874L,38875L,38876L,38877L,
+38878L,38879L,38880L,38881L,38882L,38883L,38884L,38885L,38886L,38887L,
+38888L,38889L,38890L,38891L,38892L,38893L,38894L,38895L,38896L,38897L,
+38898L,38899L,38900L,38901L,38902L,38903L,38904L,38905L,38906L,38907L,
+38908L,38909L,38910L,38911L,38912L,38913L,38914L,38915L,38916L,38917L,
+38918L,38919L,38920L,38921L,38922L,38923L,38924L,38925L,38926L,38927L,
+38928L,38929L,38930L,38931L,38932L,38933L,38934L,38935L,38936L,38937L,
+38938L,38939L,38940L,38941L,38942L,38943L,38944L,38945L,38946L,38947L,
+38948L,38949L,38950L,38951L,38952L,38953L,38954L,38955L,38956L,38957L,
+38958L,38959L,38960L,38961L,38962L,38963L,38964L,38965L,38966L,38967L,
+38968L,38969L,38970L,38971L,38972L,38973L,38974L,38975L,38976L,38977L,
+38978L,38979L,38980L,38981L,38982L,38983L,38984L,38985L,38986L,38987L,
+38988L,38989L,38990L,38991L,38992L,38993L,38994L,38995L,38996L,38997L,
+38998L,38999L,39000L,39001L,39002L,39003L,39004L,39005L,39006L,39007L,
+39008L,39009L,39010L,39011L,39012L,39013L,39014L,39015L,39016L,39017L,
+39018L,39019L,39020L,39021L,39022L,39023L,39024L,39025L,39026L,39027L,
+39028L,39029L,39030L,39031L,39032L,39033L,39034L,39035L,39036L,39037L,
+39038L,39039L,39040L,39041L,39042L,39043L,39044L,39045L,39046L,39047L,
+39048L,39049L,39050L,39051L,39052L,39053L,39054L,39055L,39056L,39057L,
+39058L,39059L,39060L,39061L,39062L,39063L,39064L,39065L,39066L,39067L,
+39068L,39069L,39070L,39071L,39072L,39073L,39074L,39075L,39076L,39077L,
+39078L,39079L,39080L,39081L,39082L,39083L,39084L,39085L,39086L,39087L,
+39088L,39089L,39090L,39091L,39092L,39093L,39094L,39095L,39096L,39097L,
+39098L,39099L,39100L,39101L,39102L,39103L,39104L,39105L,39106L,39107L,
+39108L,39109L,39110L,39111L,39112L,39113L,39114L,39115L,39116L,39117L,
+39118L,39119L,39120L,39121L,39122L,39123L,39124L,39125L,39126L,39127L,
+39128L,39129L,39130L,39131L,39132L,39133L,39134L,39135L,39136L,39137L,
+39138L,39139L,39140L,39141L,39142L,39143L,39144L,39145L,39146L,39147L,
+39148L,39149L,39150L,39151L,39152L,39153L,39154L,39155L,39156L,39157L,
+39158L,39159L,39160L,39161L,39162L,39163L,39164L,39165L,39166L,39167L,
+39168L,39169L,39170L,39171L,39172L,39173L,39174L,39175L,39176L,39177L,
+39178L,39179L,39180L,39181L,39182L,39183L,39184L,39185L,39186L,39187L,
+39188L,39189L,39190L,39191L,39192L,39193L,39194L,39195L,39196L,39197L,
+39198L,39199L,39200L,39201L,39202L,39203L,39204L,39205L,39206L,39207L,
+39208L,39209L,39210L,39211L,39212L,39213L,39214L,39215L,39216L,39217L,
+39218L,39219L,39220L,39221L,39222L,39223L,39224L,39225L,39226L,39227L,
+39228L,39229L,39230L,39231L,39232L,39233L,39234L,39235L,39236L,39237L,
+39238L,39239L,39240L,39241L,39242L,39243L,39244L,39245L,39246L,39247L,
+39248L,39249L,39250L,39251L,39252L,39253L,39254L,39255L,39256L,39257L,
+39258L,39259L,39260L,39261L,39262L,39263L,39264L,39265L,39266L,39267L,
+39268L,39269L,39270L,39271L,39272L,39273L,39274L,39275L,39276L,39277L,
+39278L,39279L,39280L,39281L,39282L,39283L,39284L,39285L,39286L,39287L,
+39288L,39289L,39290L,39291L,39292L,39293L,39294L,39295L,39296L,39297L,
+39298L,39299L,39300L,39301L,39302L,39303L,39304L,39305L,39306L,39307L,
+39308L,39309L,39310L,39311L,39312L,39313L,39314L,39315L,39316L,39317L,
+39318L,39319L,39320L,39321L,39322L,39323L,39324L,39325L,39326L,39327L,
+39328L,39329L,39330L,39331L,39332L,39333L,39334L,39335L,39336L,39337L,
+39338L,39339L,39340L,39341L,39342L,39343L,39344L,39345L,39346L,39347L,
+39348L,39349L,39350L,39351L,39352L,39353L,39354L,39355L,39356L,39357L,
+39358L,39359L,39360L,39361L,39362L,39363L,39364L,39365L,39366L,39367L,
+39368L,39369L,39370L,39371L,39372L,39373L,39374L,39375L,39376L,39377L,
+39378L,39379L,39380L,39381L,39382L,39383L,39384L,39385L,39386L,39387L,
+39388L,39389L,39390L,39391L,39392L,39393L,39394L,39395L,39396L,39397L,
+39398L,39399L,39400L,39401L,39402L,39403L,39404L,39405L,39406L,39407L,
+39408L,39409L,39410L,39411L,39412L,39413L,39414L,39415L,39416L,39417L,
+39418L,39419L,39420L,39421L,39422L,39423L,39424L,39425L,39426L,39427L,
+39428L,39429L,39430L,39431L,39432L,39433L,39434L,39435L,39436L,39437L,
+39438L,39439L,39440L,39441L,39442L,39443L,39444L,39445L,39446L,39447L,
+39448L,39449L,39450L,39451L,39452L,39453L,39454L,39455L,39456L,39457L,
+39458L,39459L,39460L,39461L,39462L,39463L,39464L,39465L,39466L,39467L,
+39468L,39469L,39470L,39471L,39472L,39473L,39474L,39475L,39476L,39477L,
+39478L,39479L,39480L,39481L,39482L,39483L,39484L,39485L,39486L,39487L,
+39488L,39489L,39490L,39491L,39492L,39493L,39494L,39495L,39496L,39497L,
+39498L,39499L,39500L,39501L,39502L,39503L,39504L,39505L,39506L,39507L,
+39508L,39509L,39510L,39511L,39512L,39513L,39514L,39515L,39516L,39517L,
+39518L,39519L,39520L,39521L,39522L,39523L,39524L,39525L,39526L,39527L,
+39528L,39529L,39530L,39531L,39532L,39533L,39534L,39535L,39536L,39537L,
+39538L,39539L,39540L,39541L,39542L,39543L,39544L,39545L,39546L,39547L,
+39548L,39549L,39550L,39551L,39552L,39553L,39554L,39555L,39556L,39557L,
+39558L,39559L,39560L,39561L,39562L,39563L,39564L,39565L,39566L,39567L,
+39568L,39569L,39570L,39571L,39572L,39573L,39574L,39575L,39576L,39577L,
+39578L,39579L,39580L,39581L,39582L,39583L,39584L,39585L,39586L,39587L,
+39588L,39589L,39590L,39591L,39592L,39593L,39594L,39595L,39596L,39597L,
+39598L,39599L,39600L,39601L,39602L,39603L,39604L,39605L,39606L,39607L,
+39608L,39609L,39610L,39611L,39612L,39613L,39614L,39615L,39616L,39617L,
+39618L,39619L,39620L,39621L,39622L,39623L,39624L,39625L,39626L,39627L,
+39628L,39629L,39630L,39631L,39632L,39633L,39634L,39635L,39636L,39637L,
+39638L,39639L,39640L,39641L,39642L,39643L,39644L,39645L,39646L,39647L,
+39648L,39649L,39650L,39651L,39652L,39653L,39654L,39655L,39656L,39657L,
+39658L,39659L,39660L,39661L,39662L,39663L,39664L,39665L,39666L,39667L,
+39668L,39669L,39670L,39671L,39672L,39673L,39674L,39675L,39676L,39677L,
+39678L,39679L,39680L,39681L,39682L,39683L,39684L,39685L,39686L,39687L,
+39688L,39689L,39690L,39691L,39692L,39693L,39694L,39695L,39696L,39697L,
+39698L,39699L,39700L,39701L,39702L,39703L,39704L,39705L,39706L,39707L,
+39708L,39709L,39710L,39711L,39712L,39713L,39714L,39715L,39716L,39717L,
+39718L,39719L,39720L,39721L,39722L,39723L,39724L,39725L,39726L,39727L,
+39728L,39729L,39730L,39731L,39732L,39733L,39734L,39735L,39736L,39737L,
+39738L,39739L,39740L,39741L,39742L,39743L,39744L,39745L,39746L,39747L,
+39748L,39749L,39750L,39751L,39752L,39753L,39754L,39755L,39756L,39757L,
+39758L,39759L,39760L,39761L,39762L,39763L,39764L,39765L,39766L,39767L,
+39768L,39769L,39770L,39771L,39772L,39773L,39774L,39775L,39776L,39777L,
+39778L,39779L,39780L,39781L,39782L,39783L,39784L,39785L,39786L,39787L,
+39788L,39789L,39790L,39791L,39792L,39793L,39794L,39795L,39796L,39797L,
+39798L,39799L,39800L,39801L,39802L,39803L,39804L,39805L,39806L,39807L,
+39808L,39809L,39810L,39811L,39812L,39813L,39814L,39815L,39816L,39817L,
+39818L,39819L,39820L,39821L,39822L,39823L,39824L,39825L,39826L,39827L,
+39828L,39829L,39830L,39831L,39832L,39833L,39834L,39835L,39836L,39837L,
+39838L,39839L,39840L,39841L,39842L,39843L,39844L,39845L,39846L,39847L,
+39848L,39849L,39850L,39851L,39852L,39853L,39854L,39855L,39856L,39857L,
+39858L,39859L,39860L,39861L,39862L,39863L,39864L,39865L,39866L,39867L,
+39868L,39869L,39870L,39871L,39872L,39873L,39874L,39875L,39876L,39877L,
+39878L,39879L,39880L,39881L,39882L,39883L,39884L,39885L,39886L,39887L,
+39888L,39889L,39890L,39891L,39892L,39893L,39894L,39895L,39896L,39897L,
+39898L,39899L,39900L,39901L,39902L,39903L,39904L,39905L,39906L,39907L,
+39908L,39909L,39910L,39911L,39912L,39913L,39914L,39915L,39916L,39917L,
+39918L,39919L,39920L,39921L,39922L,39923L,39924L,39925L,39926L,39927L,
+39928L,39929L,39930L,39931L,39932L,39933L,39934L,39935L,39936L,39937L,
+39938L,39939L,39940L,39941L,39942L,39943L,39944L,39945L,39946L,39947L,
+39948L,39949L,39950L,39951L,39952L,39953L,39954L,39955L,39956L,39957L,
+39958L,39959L,39960L,39961L,39962L,39963L,39964L,39965L,39966L,39967L,
+39968L,39969L,39970L,39971L,39972L,39973L,39974L,39975L,39976L,39977L,
+39978L,39979L,39980L,39981L,39982L,39983L,39984L,39985L,39986L,39987L,
+39988L,39989L,39990L,39991L,39992L,39993L,39994L,39995L,39996L,39997L,
+39998L,39999L,40000L,40001L,40002L,40003L,40004L,40005L,40006L,40007L,
+40008L,40009L,40010L,40011L,40012L,40013L,40014L,40015L,40016L,40017L,
+40018L,40019L,40020L,40021L,40022L,40023L,40024L,40025L,40026L,40027L,
+40028L,40029L,40030L,40031L,40032L,40033L,40034L,40035L,40036L,40037L,
+40038L,40039L,40040L,40041L,40042L,40043L,40044L,40045L,40046L,40047L,
+40048L,40049L,40050L,40051L,40052L,40053L,40054L,40055L,40056L,40057L,
+40058L,40059L,40060L,40061L,40062L,40063L,40064L,40065L,40066L,40067L,
+40068L,40069L,40070L,40071L,40072L,40073L,40074L,40075L,40076L,40077L,
+40078L,40079L,40080L,40081L,40082L,40083L,40084L,40085L,40086L,40087L,
+40088L,40089L,40090L,40091L,40092L,40093L,40094L,40095L,40096L,40097L,
+40098L,40099L,40100L,40101L,40102L,40103L,40104L,40105L,40106L,40107L,
+40108L,40109L,40110L,40111L,40112L,40113L,40114L,40115L,40116L,40117L,
+40118L,40119L,40120L,40121L,40122L,40123L,40124L,40125L,40126L,40127L,
+40128L,40129L,40130L,40131L,40132L,40133L,40134L,40135L,40136L,40137L,
+40138L,40139L,40140L,40141L,40142L,40143L,40144L,40145L,40146L,40147L,
+40148L,40149L,40150L,40151L,40152L,40153L,40154L,40155L,40156L,40157L,
+40158L,40159L,40160L,40161L,40162L,40163L,40164L,40165L,40166L,40167L,
+40168L,40169L,40170L,40171L,40172L,40173L,40174L,40175L,40176L,40177L,
+40178L,40179L,40180L,40181L,40182L,40183L,40184L,40185L,40186L,40187L,
+40188L,40189L,40190L,40191L,40192L,40193L,40194L,40195L,40196L,40197L,
+40198L,40199L,40200L,40201L,40202L,40203L,40204L,40205L,40206L,40207L,
+40208L,40209L,40210L,40211L,40212L,40213L,40214L,40215L,40216L,40217L,
+40218L,40219L,40220L,40221L,40222L,40223L,40224L,40225L,40226L,40227L,
+40228L,40229L,40230L,40231L,40232L,40233L,40234L,40235L,40236L,40237L,
+40238L,40239L,40240L,40241L,40242L,40243L,40244L,40245L,40246L,40247L,
+40248L,40249L,40250L,40251L,40252L,40253L,40254L,40255L,40256L,40257L,
+40258L,40259L,40260L,40261L,40262L,40263L,40264L,40265L,40266L,40267L,
+40268L,40269L,40270L,40271L,40272L,40273L,40274L,40275L,40276L,40277L,
+40278L,40279L,40280L,40281L,40282L,40283L,40284L,40285L,40286L,40287L,
+40288L,40289L,40290L,40291L,40292L,40293L,40294L,40295L,40296L,40297L,
+40298L,40299L,40300L,40301L,40302L,40303L,40304L,40305L,40306L,40307L,
+40308L,40309L,40310L,40311L,40312L,40313L,40314L,40315L,40316L,40317L,
+40318L,40319L,40320L,40321L,40322L,40323L,40324L,40325L,40326L,40327L,
+40328L,40329L,40330L,40331L,40332L,40333L,40334L,40335L,40336L,40337L,
+40338L,40339L,40340L,40341L,40342L,40343L,40344L,40345L,40346L,40347L,
+40348L,40349L,40350L,40351L,40352L,40353L,40354L,40355L,40356L,40357L,
+40358L,40359L,40360L,40361L,40362L,40363L,40364L,40365L,40366L,40367L,
+40368L,40369L,40370L,40371L,40372L,40373L,40374L,40375L,40376L,40377L,
+40378L,40379L,40380L,40381L,40382L,40383L,40384L,40385L,40386L,40387L,
+40388L,40389L,40390L,40391L,40392L,40393L,40394L,40395L,40396L,40397L,
+40398L,40399L,40400L,40401L,40402L,40403L,40404L,40405L,40406L,40407L,
+40408L,40409L,40410L,40411L,40412L,40413L,40414L,40415L,40416L,40417L,
+40418L,40419L,40420L,40421L,40422L,40423L,40424L,40425L,40426L,40427L,
+40428L,40429L,40430L,40431L,40432L,40433L,40434L,40435L,40436L,40437L,
+40438L,40439L,40440L,40441L,40442L,40443L,40444L,40445L,40446L,40447L,
+40448L,40449L,40450L,40451L,40452L,40453L,40454L,40455L,40456L,40457L,
+40458L,40459L,40460L,40461L,40462L,40463L,40464L,40465L,40466L,40467L,
+40468L,40469L,40470L,40471L,40472L,40473L,40474L,40475L,40476L,40477L,
+40478L,40479L,40480L,40481L,40482L,40483L,40484L,40485L,40486L,40487L,
+40488L,40489L,40490L,40491L,40492L,40493L,40494L,40495L,40496L,40497L,
+40498L,40499L,40500L,40501L,40502L,40503L,40504L,40505L,40506L,40507L,
+40508L,40509L,40510L,40511L,40512L,40513L,40514L,40515L,40516L,40517L,
+40518L,40519L,40520L,40521L,40522L,40523L,40524L,40525L,40526L,40527L,
+40528L,40529L,40530L,40531L,40532L,40533L,40534L,40535L,40536L,40537L,
+40538L,40539L,40540L,40541L,40542L,40543L,40544L,40545L,40546L,40547L,
+40548L,40549L,40550L,40551L,40552L,40553L,40554L,40555L,40556L,40557L,
+40558L,40559L,40560L,40561L,40562L,40563L,40564L,40565L,40566L,40567L,
+40568L,40569L,40570L,40571L,40572L,40573L,40574L,40575L,40576L,40577L,
+40578L,40579L,40580L,40581L,40582L,40583L,40584L,40585L,40586L,40587L,
+40588L,40589L,40590L,40591L,40592L,40593L,40594L,40595L,40596L,40597L,
+40598L,40599L,40600L,40601L,40602L,40603L,40604L,40605L,40606L,40607L,
+40608L,40609L,40610L,40611L,40612L,40613L,40614L,40615L,40616L,40617L,
+40618L,40619L,40620L,40621L,40622L,40623L,40624L,40625L,40626L,40627L,
+40628L,40629L,40630L,40631L,40632L,40633L,40634L,40635L,40636L,40637L,
+40638L,40639L,40640L,40641L,40642L,40643L,40644L,40645L,40646L,40647L,
+40648L,40649L,40650L,40651L,40652L,40653L,40654L,40655L,40656L,40657L,
+40658L,40659L,40660L,40661L,40662L,40663L,40664L,40665L,40666L,40667L,
+40668L,40669L,40670L,40671L,40672L,40673L,40674L,40675L,40676L,40677L,
+40678L,40679L,40680L,40681L,40682L,40683L,40684L,40685L,40686L,40687L,
+40688L,40689L,40690L,40691L,40692L,40693L,40694L,40695L,40696L,40697L,
+40698L,40699L,40700L,40701L,40702L,40703L,40704L,40705L,40706L,40707L,
+40708L,40709L,40710L,40711L,40712L,40713L,40714L,40715L,40716L,40717L,
+40718L,40719L,40720L,40721L,40722L,40723L,40724L,40725L,40726L,40727L,
+40728L,40729L,40730L,40731L,40732L,40733L,40734L,40735L,40736L,40737L,
+40738L,40739L,40740L,40741L,40742L,40743L,40744L,40745L,40746L,40747L,
+40748L,40749L,40750L,40751L,40752L,40753L,40754L,40755L,40756L,40757L,
+40758L,40759L,40760L,40761L,40762L,40763L,40764L,40765L,40766L,40767L,
+40768L,40769L,40770L,40771L,40772L,40773L,40774L,40775L,40776L,40777L,
+40778L,40779L,40780L,40781L,40782L,40783L,40784L,40785L,40786L,40787L,
+40788L,40789L,40790L,40791L,40792L,40793L,40794L,40795L,40796L,40797L,
+40798L,40799L,40800L,40801L,40802L,40803L,40804L,40805L,40806L,40807L,
+40808L,40809L,40810L,40811L,40812L,40813L,40814L,40815L,40816L,40817L,
+40818L,40819L,40820L,40821L,40822L,40823L,40824L,40825L,40826L,40827L,
+40828L,40829L,40830L,40831L,40832L,40833L,40834L,40835L,40836L,40837L,
+40838L,40839L,40840L,40841L,40842L,40843L,40844L,40845L,40846L,40847L,
+40848L,40849L,40850L,40851L,40852L,40853L,40854L,40855L,40856L,40857L,
+40858L,40859L,40860L,40861L,40862L,40863L,40864L,40865L,40866L,40867L,
+40868L,40869L,40870L,40871L,40872L,40873L,40874L,40875L,40876L,40877L,
+40878L,40879L,40880L,40881L,40882L,40883L,40884L,40885L,40886L,40887L,
+40888L,40889L,40890L,40891L,40892L,40893L,40894L,40895L,40896L,40897L,
+40898L,40899L,40900L,40901L,40902L,40903L,40904L,40905L,40906L,40907L,
+40908L,40909L,40910L,40911L,40912L,40913L,40914L,40915L,40916L,40917L,
+40918L,40919L,40920L,40921L,40922L,40923L,40924L,40925L,40926L,40927L,
+40928L,40929L,40930L,40931L,40932L,40933L,40934L,40935L,40936L,40937L,
+40938L,40939L,40940L,40941L,40942L,40943L,40944L,40945L,40946L,40947L,
+40948L,40949L,40950L,40951L,40952L,40953L,40954L,40955L,40956L,40957L,
+40958L,40959L,40960L,40961L,40962L,40963L,40964L,40965L,40966L,40967L,
+40968L,40969L,40970L,40971L,40972L,40973L,40974L,40975L,40976L,40977L,
+40978L,40979L,40980L,40981L,40982L,40983L,40984L,40985L,40986L,40987L,
+40988L,40989L,40990L,40991L,40992L,40993L,40994L,40995L,40996L,40997L,
+40998L,40999L,41000L,41001L,41002L,41003L,41004L,41005L,41006L,41007L,
+41008L,41009L,41010L,41011L,41012L,41013L,41014L,41015L,41016L,41017L,
+41018L,41019L,41020L,41021L,41022L,41023L,41024L,41025L,41026L,41027L,
+41028L,41029L,41030L,41031L,41032L,41033L,41034L,41035L,41036L,41037L,
+41038L,41039L,41040L,41041L,41042L,41043L,41044L,41045L,41046L,41047L,
+41048L,41049L,41050L,41051L,41052L,41053L,41054L,41055L,41056L,41057L,
+41058L,41059L,41060L,41061L,41062L,41063L,41064L,41065L,41066L,41067L,
+41068L,41069L,41070L,41071L,41072L,41073L,41074L,41075L,41076L,41077L,
+41078L,41079L,41080L,41081L,41082L,41083L,41084L,41085L,41086L,41087L,
+41088L,41089L,41090L,41091L,41092L,41093L,41094L,41095L,41096L,41097L,
+41098L,41099L,41100L,41101L,41102L,41103L,41104L,41105L,41106L,41107L,
+41108L,41109L,41110L,41111L,41112L,41113L,41114L,41115L,41116L,41117L,
+41118L,41119L,41120L,41121L,41122L,41123L,41124L,41125L,41126L,41127L,
+41128L,41129L,41130L,41131L,41132L,41133L,41134L,41135L,41136L,41137L,
+41138L,41139L,41140L,41141L,41142L,41143L,41144L,41145L,41146L,41147L,
+41148L,41149L,41150L,41151L,41152L,41153L,41154L,41155L,41156L,41157L,
+41158L,41159L,41160L,41161L,41162L,41163L,41164L,41165L,41166L,41167L,
+41168L,41169L,41170L,41171L,41172L,41173L,41174L,41175L,41176L,41177L,
+41178L,41179L,41180L,41181L,41182L,41183L,41184L,41185L,41186L,41187L,
+41188L,41189L,41190L,41191L,41192L,41193L,41194L,41195L,41196L,41197L,
+41198L,41199L,41200L,41201L,41202L,41203L,41204L,41205L,41206L,41207L,
+41208L,41209L,41210L,41211L,41212L,41213L,41214L,41215L,41216L,41217L,
+41218L,41219L,41220L,41221L,41222L,41223L,41224L,41225L,41226L,41227L,
+41228L,41229L,41230L,41231L,41232L,41233L,41234L,41235L,41236L,41237L,
+41238L,41239L,41240L,41241L,41242L,41243L,41244L,41245L,41246L,41247L,
+41248L,41249L,41250L,41251L,41252L,41253L,41254L,41255L,41256L,41257L,
+41258L,41259L,41260L,41261L,41262L,41263L,41264L,41265L,41266L,41267L,
+41268L,41269L,41270L,41271L,41272L,41273L,41274L,41275L,41276L,41277L,
+41278L,41279L,41280L,41281L,41282L,41283L,41284L,41285L,41286L,41287L,
+41288L,41289L,41290L,41291L,41292L,41293L,41294L,41295L,41296L,41297L,
+41298L,41299L,41300L,41301L,41302L,41303L,41304L,41305L,41306L,41307L,
+41308L,41309L,41310L,41311L,41312L,41313L,41314L,41315L,41316L,41317L,
+41318L,41319L,41320L,41321L,41322L,41323L,41324L,41325L,41326L,41327L,
+41328L,41329L,41330L,41331L,41332L,41333L,41334L,41335L,41336L,41337L,
+41338L,41339L,41340L,41341L,41342L,41343L,41344L,41345L,41346L,41347L,
+41348L,41349L,41350L,41351L,41352L,41353L,41354L,41355L,41356L,41357L,
+41358L,41359L,41360L,41361L,41362L,41363L,41364L,41365L,41366L,41367L,
+41368L,41369L,41370L,41371L,41372L,41373L,41374L,41375L,41376L,41377L,
+41378L,41379L,41380L,41381L,41382L,41383L,41384L,41385L,41386L,41387L,
+41388L,41389L,41390L,41391L,41392L,41393L,41394L,41395L,41396L,41397L,
+41398L,41399L,41400L,41401L,41402L,41403L,41404L,41405L,41406L,41407L,
+41408L,41409L,41410L,41411L,41412L,41413L,41414L,41415L,41416L,41417L,
+41418L,41419L,41420L,41421L,41422L,41423L,41424L,41425L,41426L,41427L,
+41428L,41429L,41430L,41431L,41432L,41433L,41434L,41435L,41436L,41437L,
+41438L,41439L,41440L,41441L,41442L,41443L,41444L,41445L,41446L,41447L,
+41448L,41449L,41450L,41451L,41452L,41453L,41454L,41455L,41456L,41457L,
+41458L,41459L,41460L,41461L,41462L,41463L,41464L,41465L,41466L,41467L,
+41468L,41469L,41470L,41471L,41472L,41473L,41474L,41475L,41476L,41477L,
+41478L,41479L,41480L,41481L,41482L,41483L,41484L,41485L,41486L,41487L,
+41488L,41489L,41490L,41491L,41492L,41493L,41494L,41495L,41496L,41497L,
+41498L,41499L,41500L,41501L,41502L,41503L,41504L,41505L,41506L,41507L,
+41508L,41509L,41510L,41511L,41512L,41513L,41514L,41515L,41516L,41517L,
+41518L,41519L,41520L,41521L,41522L,41523L,41524L,41525L,41526L,41527L,
+41528L,41529L,41530L,41531L,41532L,41533L,41534L,41535L,41536L,41537L,
+41538L,41539L,41540L,41541L,41542L,41543L,41544L,41545L,41546L,41547L,
+41548L,41549L,41550L,41551L,41552L,41553L,41554L,41555L,41556L,41557L,
+41558L,41559L,41560L,41561L,41562L,41563L,41564L,41565L,41566L,41567L,
+41568L,41569L,41570L,41571L,41572L,41573L,41574L,41575L,41576L,41577L,
+41578L,41579L,41580L,41581L,41582L,41583L,41584L,41585L,41586L,41587L,
+41588L,41589L,41590L,41591L,41592L,41593L,41594L,41595L,41596L,41597L,
+41598L,41599L,41600L,41601L,41602L,41603L,41604L,41605L,41606L,41607L,
+41608L,41609L,41610L,41611L,41612L,41613L,41614L,41615L,41616L,41617L,
+41618L,41619L,41620L,41621L,41622L,41623L,41624L,41625L,41626L,41627L,
+41628L,41629L,41630L,41631L,41632L,41633L,41634L,41635L,41636L,41637L,
+41638L,41639L,41640L,41641L,41642L,41643L,41644L,41645L,41646L,41647L,
+41648L,41649L,41650L,41651L,41652L,41653L,41654L,41655L,41656L,41657L,
+41658L,41659L,41660L,41661L,41662L,41663L,41664L,41665L,41666L,41667L,
+41668L,41669L,41670L,41671L,41672L,41673L,41674L,41675L,41676L,41677L,
+41678L,41679L,41680L,41681L,41682L,41683L,41684L,41685L,41686L,41687L,
+41688L,41689L,41690L,41691L,41692L,41693L,41694L,41695L,41696L,41697L,
+41698L,41699L,41700L,41701L,41702L,41703L,41704L,41705L,41706L,41707L,
+41708L,41709L,41710L,41711L,41712L,41713L,41714L,41715L,41716L,41717L,
+41718L,41719L,41720L,41721L,41722L,41723L,41724L,41725L,41726L,41727L,
+41728L,41729L,41730L,41731L,41732L,41733L,41734L,41735L,41736L,41737L,
+41738L,41739L,41740L,41741L,41742L,41743L,41744L,41745L,41746L,41747L,
+41748L,41749L,41750L,41751L,41752L,41753L,41754L,41755L,41756L,41757L,
+41758L,41759L,41760L,41761L,41762L,41763L,41764L,41765L,41766L,41767L,
+41768L,41769L,41770L,41771L,41772L,41773L,41774L,41775L,41776L,41777L,
+41778L,41779L,41780L,41781L,41782L,41783L,41784L,41785L,41786L,41787L,
+41788L,41789L,41790L,41791L,41792L,41793L,41794L,41795L,41796L,41797L,
+41798L,41799L,41800L,41801L,41802L,41803L,41804L,41805L,41806L,41807L,
+41808L,41809L,41810L,41811L,41812L,41813L,41814L,41815L,41816L,41817L,
+41818L,41819L,41820L,41821L,41822L,41823L,41824L,41825L,41826L,41827L,
+41828L,41829L,41830L,41831L,41832L,41833L,41834L,41835L,41836L,41837L,
+41838L,41839L,41840L,41841L,41842L,41843L,41844L,41845L,41846L,41847L,
+41848L,41849L,41850L,41851L,41852L,41853L,41854L,41855L,41856L,41857L,
+41858L,41859L,41860L,41861L,41862L,41863L,41864L,41865L,41866L,41867L,
+41868L,41869L,41870L,41871L,41872L,41873L,41874L,41875L,41876L,41877L,
+41878L,41879L,41880L,41881L,41882L,41883L,41884L,41885L,41886L,41887L,
+41888L,41889L,41890L,41891L,41892L,41893L,41894L,41895L,41896L,41897L,
+41898L,41899L,41900L,41901L,41902L,41903L,41904L,41905L,41906L,41907L,
+41908L,41909L,41910L,41911L,41912L,41913L,41914L,41915L,41916L,41917L,
+41918L,41919L,41920L,41921L,41922L,41923L,41924L,41925L,41926L,41927L,
+41928L,41929L,41930L,41931L,41932L,41933L,41934L,41935L,41936L,41937L,
+41938L,41939L,41940L,41941L,41942L,41943L,41944L,41945L,41946L,41947L,
+41948L,41949L,41950L,41951L,41952L,41953L,41954L,41955L,41956L,41957L,
+41958L,41959L,41960L,41961L,41962L,41963L,41964L,41965L,41966L,41967L,
+41968L,41969L,41970L,41971L,41972L,41973L,41974L,41975L,41976L,41977L,
+41978L,41979L,41980L,41981L,41982L,41983L,41984L,41985L,41986L,41987L,
+41988L,41989L,41990L,41991L,41992L,41993L,41994L,41995L,41996L,41997L,
+41998L,41999L,42000L,42001L,42002L,42003L,42004L,42005L,42006L,42007L,
+42008L,42009L,42010L,42011L,42012L,42013L,42014L,42015L,42016L,42017L,
+42018L,42019L,42020L,42021L,42022L,42023L,42024L,42025L,42026L,42027L,
+42028L,42029L,42030L,42031L,42032L,42033L,42034L,42035L,42036L,42037L,
+42038L,42039L,42040L,42041L,42042L,42043L,42044L,42045L,42046L,42047L,
+42048L,42049L,42050L,42051L,42052L,42053L,42054L,42055L,42056L,42057L,
+42058L,42059L,42060L,42061L,42062L,42063L,42064L,42065L,42066L,42067L,
+42068L,42069L,42070L,42071L,42072L,42073L,42074L,42075L,42076L,42077L,
+42078L,42079L,42080L,42081L,42082L,42083L,42084L,42085L,42086L,42087L,
+42088L,42089L,42090L,42091L,42092L,42093L,42094L,42095L,42096L,42097L,
+42098L,42099L,42100L,42101L,42102L,42103L,42104L,42105L,42106L,42107L,
+42108L,42109L,42110L,42111L,42112L,42113L,42114L,42115L,42116L,42117L,
+42118L,42119L,42120L,42121L,42122L,42123L,42124L,42125L,42126L,42127L,
+42128L,42129L,42130L,42131L,42132L,42133L,42134L,42135L,42136L,42137L,
+42138L,42139L,42140L,42141L,42142L,42143L,42144L,42145L,42146L,42147L,
+42148L,42149L,42150L,42151L,42152L,42153L,42154L,42155L,42156L,42157L,
+42158L,42159L,42160L,42161L,42162L,42163L,42164L,42165L,42166L,42167L,
+42168L,42169L,42170L,42171L,42172L,42173L,42174L,42175L,42176L,42177L,
+42178L,42179L,42180L,42181L,42182L,42183L,42184L,42185L,42186L,42187L,
+42188L,42189L,42190L,42191L,42192L,42193L,42194L,42195L,42196L,42197L,
+42198L,42199L,42200L,42201L,42202L,42203L,42204L,42205L,42206L,42207L,
+42208L,42209L,42210L,42211L,42212L,42213L,42214L,42215L,42216L,42217L,
+42218L,42219L,42220L,42221L,42222L,42223L,42224L,42225L,42226L,42227L,
+42228L,42229L,42230L,42231L,42232L,42233L,42234L,42235L,42236L,42237L,
+42238L,42239L,42240L,42241L,42242L,42243L,42244L,42245L,42246L,42247L,
+42248L,42249L,42250L,42251L,42252L,42253L,42254L,42255L,42256L,42257L,
+42258L,42259L,42260L,42261L,42262L,42263L,42264L,42265L,42266L,42267L,
+42268L,42269L,42270L,42271L,42272L,42273L,42274L,42275L,42276L,42277L,
+42278L,42279L,42280L,42281L,42282L,42283L,42284L,42285L,42286L,42287L,
+42288L,42289L,42290L,42291L,42292L,42293L,42294L,42295L,42296L,42297L,
+42298L,42299L,42300L,42301L,42302L,42303L,42304L,42305L,42306L,42307L,
+42308L,42309L,42310L,42311L,42312L,42313L,42314L,42315L,42316L,42317L,
+42318L,42319L,42320L,42321L,42322L,42323L,42324L,42325L,42326L,42327L,
+42328L,42329L,42330L,42331L,42332L,42333L,42334L,42335L,42336L,42337L,
+42338L,42339L,42340L,42341L,42342L,42343L,42344L,42345L,42346L,42347L,
+42348L,42349L,42350L,42351L,42352L,42353L,42354L,42355L,42356L,42357L,
+42358L,42359L,42360L,42361L,42362L,42363L,42364L,42365L,42366L,42367L,
+42368L,42369L,42370L,42371L,42372L,42373L,42374L,42375L,42376L,42377L,
+42378L,42379L,42380L,42381L,42382L,42383L,42384L,42385L,42386L,42387L,
+42388L,42389L,42390L,42391L,42392L,42393L,42394L,42395L,42396L,42397L,
+42398L,42399L,42400L,42401L,42402L,42403L,42404L,42405L,42406L,42407L,
+42408L,42409L,42410L,42411L,42412L,42413L,42414L,42415L,42416L,42417L,
+42418L,42419L,42420L,42421L,42422L,42423L,42424L,42425L,42426L,42427L,
+42428L,42429L,42430L,42431L,42432L,42433L,42434L,42435L,42436L,42437L,
+42438L,42439L,42440L,42441L,42442L,42443L,42444L,42445L,42446L,42447L,
+42448L,42449L,42450L,42451L,42452L,42453L,42454L,42455L,42456L,42457L,
+42458L,42459L,42460L,42461L,42462L,42463L,42464L,42465L,42466L,42467L,
+42468L,42469L,42470L,42471L,42472L,42473L,42474L,42475L,42476L,42477L,
+42478L,42479L,42480L,42481L,42482L,42483L,42484L,42485L,42486L,42487L,
+42488L,42489L,42490L,42491L,42492L,42493L,42494L,42495L,42496L,42497L,
+42498L,42499L,42500L,42501L,42502L,42503L,42504L,42505L,42506L,42507L,
+42508L,42509L,42510L,42511L,42512L,42513L,42514L,42515L,42516L,42517L,
+42518L,42519L,42520L,42521L,42522L,42523L,42524L,42525L,42526L,42527L,
+42528L,42529L,42530L,42531L,42532L,42533L,42534L,42535L,42536L,42537L,
+42538L,42539L,42540L,42541L,42542L,42543L,42544L,42545L,42546L,42547L,
+42548L,42549L,42550L,42551L,42552L,42553L,42554L,42555L,42556L,42557L,
+42558L,42559L,42560L,42560L,42562L,42562L,42564L,42564L,42566L,42566L,
+42568L,42568L,42570L,42570L,42572L,42572L,42574L,42574L,42576L,42576L,
+42578L,42578L,42580L,42580L,42582L,42582L,42584L,42584L,42586L,42586L,
+42588L,42588L,42590L,42590L,42592L,42592L,42594L,42594L,42596L,42596L,
+42598L,42598L,42600L,42600L,42602L,42602L,42604L,42604L,42606L,42607L,
+42608L,42609L,42610L,42611L,42612L,42613L,42614L,42615L,42616L,42617L,
+42618L,42619L,42620L,42621L,42622L,42623L,42624L,42624L,42626L,42626L,
+42628L,42628L,42630L,42630L,42632L,42632L,42634L,42634L,42636L,42636L,
+42638L,42638L,42640L,42640L,42642L,42642L,42644L,42644L,42646L,42646L,
+42648L,42648L,42650L,42650L,42652L,42653L,42654L,42655L,42656L,42657L,
+42658L,42659L,42660L,42661L,42662L,42663L,42664L,42665L,42666L,42667L,
+42668L,42669L,42670L,42671L,42672L,42673L,42674L,42675L,42676L,42677L,
+42678L,42679L,42680L,42681L,42682L,42683L,42684L,42685L,42686L,42687L,
+42688L,42689L,42690L,42691L,42692L,42693L,42694L,42695L,42696L,42697L,
+42698L,42699L,42700L,42701L,42702L,42703L,42704L,42705L,42706L,42707L,
+42708L,42709L,42710L,42711L,42712L,42713L,42714L,42715L,42716L,42717L,
+42718L,42719L,42720L,42721L,42722L,42723L,42724L,42725L,42726L,42727L,
+42728L,42729L,42730L,42731L,42732L,42733L,42734L,42735L,42736L,42737L,
+42738L,42739L,42740L,42741L,42742L,42743L,42744L,42745L,42746L,42747L,
+42748L,42749L,42750L,42751L,42752L,42753L,42754L,42755L,42756L,42757L,
+42758L,42759L,42760L,42761L,42762L,42763L,42764L,42765L,42766L,42767L,
+42768L,42769L,42770L,42771L,42772L,42773L,42774L,42775L,42776L,42777L,
+42778L,42779L,42780L,42781L,42782L,42783L,42784L,42785L,42786L,42786L,
+42788L,42788L,42790L,42790L,42792L,42792L,42794L,42794L,42796L,42796L,
+42798L,42798L,42800L,42801L,42802L,42802L,42804L,42804L,42806L,42806L,
+42808L,42808L,42810L,42810L,42812L,42812L,42814L,42814L,42816L,42816L,
+42818L,42818L,42820L,42820L,42822L,42822L,42824L,42824L,42826L,42826L,
+42828L,42828L,42830L,42830L,42832L,42832L,42834L,42834L,42836L,42836L,
+42838L,42838L,42840L,42840L,42842L,42842L,42844L,42844L,42846L,42846L,
+42848L,42848L,42850L,42850L,42852L,42852L,42854L,42854L,42856L,42856L,
+42858L,42858L,42860L,42860L,42862L,42862L,42864L,42865L,42866L,42867L,
+42868L,42869L,42870L,42871L,42872L,42873L,42873L,42875L,42875L,42877L,
+42878L,42878L,42880L,42880L,42882L,42882L,42884L,42884L,42886L,42886L,
+42888L,42889L,42890L,42891L,42891L,42893L,42894L,42895L,42896L,42896L,
+42898L,42898L,42948L,42901L,42902L,42902L,42904L,42904L,42906L,42906L,
+42908L,42908L,42910L,42910L,42912L,42912L,42914L,42914L,42916L,42916L,
+42918L,42918L,42920L,42920L,42922L,42923L,42924L,42925L,42926L,42927L,
+42928L,42929L,42930L,42931L,42932L,42932L,42934L,42934L,42936L,42936L,
+42938L,42938L,42940L,42940L,42942L,42942L,42944L,42945L,42946L,42946L,
+42948L,42949L,42950L,42951L,42952L,42953L,42954L,42955L,42956L,42957L,
+42958L,42959L,42960L,42961L,42962L,42963L,42964L,42965L,42966L,42967L,
+42968L,42969L,42970L,42971L,42972L,42973L,42974L,42975L,42976L,42977L,
+42978L,42979L,42980L,42981L,42982L,42983L,42984L,42985L,42986L,42987L,
+42988L,42989L,42990L,42991L,42992L,42993L,42994L,42995L,42996L,42997L,
+42998L,42999L,43000L,43001L,43002L,43003L,43004L,43005L,43006L,43007L,
+43008L,43009L,43010L,43011L,43012L,43013L,43014L,43015L,43016L,43017L,
+43018L,43019L,43020L,43021L,43022L,43023L,43024L,43025L,43026L,43027L,
+43028L,43029L,43030L,43031L,43032L,43033L,43034L,43035L,43036L,43037L,
+43038L,43039L,43040L,43041L,43042L,43043L,43044L,43045L,43046L,43047L,
+43048L,43049L,43050L,43051L,43052L,43053L,43054L,43055L,43056L,43057L,
+43058L,43059L,43060L,43061L,43062L,43063L,43064L,43065L,43066L,43067L,
+43068L,43069L,43070L,43071L,43072L,43073L,43074L,43075L,43076L,43077L,
+43078L,43079L,43080L,43081L,43082L,43083L,43084L,43085L,43086L,43087L,
+43088L,43089L,43090L,43091L,43092L,43093L,43094L,43095L,43096L,43097L,
+43098L,43099L,43100L,43101L,43102L,43103L,43104L,43105L,43106L,43107L,
+43108L,43109L,43110L,43111L,43112L,43113L,43114L,43115L,43116L,43117L,
+43118L,43119L,43120L,43121L,43122L,43123L,43124L,43125L,43126L,43127L,
+43128L,43129L,43130L,43131L,43132L,43133L,43134L,43135L,43136L,43137L,
+43138L,43139L,43140L,43141L,43142L,43143L,43144L,43145L,43146L,43147L,
+43148L,43149L,43150L,43151L,43152L,43153L,43154L,43155L,43156L,43157L,
+43158L,43159L,43160L,43161L,43162L,43163L,43164L,43165L,43166L,43167L,
+43168L,43169L,43170L,43171L,43172L,43173L,43174L,43175L,43176L,43177L,
+43178L,43179L,43180L,43181L,43182L,43183L,43184L,43185L,43186L,43187L,
+43188L,43189L,43190L,43191L,43192L,43193L,43194L,43195L,43196L,43197L,
+43198L,43199L,43200L,43201L,43202L,43203L,43204L,43205L,43206L,43207L,
+43208L,43209L,43210L,43211L,43212L,43213L,43214L,43215L,43216L,43217L,
+43218L,43219L,43220L,43221L,43222L,43223L,43224L,43225L,43226L,43227L,
+43228L,43229L,43230L,43231L,43232L,43233L,43234L,43235L,43236L,43237L,
+43238L,43239L,43240L,43241L,43242L,43243L,43244L,43245L,43246L,43247L,
+43248L,43249L,43250L,43251L,43252L,43253L,43254L,43255L,43256L,43257L,
+43258L,43259L,43260L,43261L,43262L,43263L,43264L,43265L,43266L,43267L,
+43268L,43269L,43270L,43271L,43272L,43273L,43274L,43275L,43276L,43277L,
+43278L,43279L,43280L,43281L,43282L,43283L,43284L,43285L,43286L,43287L,
+43288L,43289L,43290L,43291L,43292L,43293L,43294L,43295L,43296L,43297L,
+43298L,43299L,43300L,43301L,43302L,43303L,43304L,43305L,43306L,43307L,
+43308L,43309L,43310L,43311L,43312L,43313L,43314L,43315L,43316L,43317L,
+43318L,43319L,43320L,43321L,43322L,43323L,43324L,43325L,43326L,43327L,
+43328L,43329L,43330L,43331L,43332L,43333L,43334L,43335L,43336L,43337L,
+43338L,43339L,43340L,43341L,43342L,43343L,43344L,43345L,43346L,43347L,
+43348L,43349L,43350L,43351L,43352L,43353L,43354L,43355L,43356L,43357L,
+43358L,43359L,43360L,43361L,43362L,43363L,43364L,43365L,43366L,43367L,
+43368L,43369L,43370L,43371L,43372L,43373L,43374L,43375L,43376L,43377L,
+43378L,43379L,43380L,43381L,43382L,43383L,43384L,43385L,43386L,43387L,
+43388L,43389L,43390L,43391L,43392L,43393L,43394L,43395L,43396L,43397L,
+43398L,43399L,43400L,43401L,43402L,43403L,43404L,43405L,43406L,43407L,
+43408L,43409L,43410L,43411L,43412L,43413L,43414L,43415L,43416L,43417L,
+43418L,43419L,43420L,43421L,43422L,43423L,43424L,43425L,43426L,43427L,
+43428L,43429L,43430L,43431L,43432L,43433L,43434L,43435L,43436L,43437L,
+43438L,43439L,43440L,43441L,43442L,43443L,43444L,43445L,43446L,43447L,
+43448L,43449L,43450L,43451L,43452L,43453L,43454L,43455L,43456L,43457L,
+43458L,43459L,43460L,43461L,43462L,43463L,43464L,43465L,43466L,43467L,
+43468L,43469L,43470L,43471L,43472L,43473L,43474L,43475L,43476L,43477L,
+43478L,43479L,43480L,43481L,43482L,43483L,43484L,43485L,43486L,43487L,
+43488L,43489L,43490L,43491L,43492L,43493L,43494L,43495L,43496L,43497L,
+43498L,43499L,43500L,43501L,43502L,43503L,43504L,43505L,43506L,43507L,
+43508L,43509L,43510L,43511L,43512L,43513L,43514L,43515L,43516L,43517L,
+43518L,43519L,43520L,43521L,43522L,43523L,43524L,43525L,43526L,43527L,
+43528L,43529L,43530L,43531L,43532L,43533L,43534L,43535L,43536L,43537L,
+43538L,43539L,43540L,43541L,43542L,43543L,43544L,43545L,43546L,43547L,
+43548L,43549L,43550L,43551L,43552L,43553L,43554L,43555L,43556L,43557L,
+43558L,43559L,43560L,43561L,43562L,43563L,43564L,43565L,43566L,43567L,
+43568L,43569L,43570L,43571L,43572L,43573L,43574L,43575L,43576L,43577L,
+43578L,43579L,43580L,43581L,43582L,43583L,43584L,43585L,43586L,43587L,
+43588L,43589L,43590L,43591L,43592L,43593L,43594L,43595L,43596L,43597L,
+43598L,43599L,43600L,43601L,43602L,43603L,43604L,43605L,43606L,43607L,
+43608L,43609L,43610L,43611L,43612L,43613L,43614L,43615L,43616L,43617L,
+43618L,43619L,43620L,43621L,43622L,43623L,43624L,43625L,43626L,43627L,
+43628L,43629L,43630L,43631L,43632L,43633L,43634L,43635L,43636L,43637L,
+43638L,43639L,43640L,43641L,43642L,43643L,43644L,43645L,43646L,43647L,
+43648L,43649L,43650L,43651L,43652L,43653L,43654L,43655L,43656L,43657L,
+43658L,43659L,43660L,43661L,43662L,43663L,43664L,43665L,43666L,43667L,
+43668L,43669L,43670L,43671L,43672L,43673L,43674L,43675L,43676L,43677L,
+43678L,43679L,43680L,43681L,43682L,43683L,43684L,43685L,43686L,43687L,
+43688L,43689L,43690L,43691L,43692L,43693L,43694L,43695L,43696L,43697L,
+43698L,43699L,43700L,43701L,43702L,43703L,43704L,43705L,43706L,43707L,
+43708L,43709L,43710L,43711L,43712L,43713L,43714L,43715L,43716L,43717L,
+43718L,43719L,43720L,43721L,43722L,43723L,43724L,43725L,43726L,43727L,
+43728L,43729L,43730L,43731L,43732L,43733L,43734L,43735L,43736L,43737L,
+43738L,43739L,43740L,43741L,43742L,43743L,43744L,43745L,43746L,43747L,
+43748L,43749L,43750L,43751L,43752L,43753L,43754L,43755L,43756L,43757L,
+43758L,43759L,43760L,43761L,43762L,43763L,43764L,43765L,43766L,43767L,
+43768L,43769L,43770L,43771L,43772L,43773L,43774L,43775L,43776L,43777L,
+43778L,43779L,43780L,43781L,43782L,43783L,43784L,43785L,43786L,43787L,
+43788L,43789L,43790L,43791L,43792L,43793L,43794L,43795L,43796L,43797L,
+43798L,43799L,43800L,43801L,43802L,43803L,43804L,43805L,43806L,43807L,
+43808L,43809L,43810L,43811L,43812L,43813L,43814L,43815L,43816L,43817L,
+43818L,43819L,43820L,43821L,43822L,43823L,43824L,43825L,43826L,43827L,
+43828L,43829L,43830L,43831L,43832L,43833L,43834L,43835L,43836L,43837L,
+43838L,43839L,43840L,43841L,43842L,43843L,43844L,43845L,43846L,43847L,
+43848L,43849L,43850L,43851L,43852L,43853L,43854L,43855L,43856L,43857L,
+43858L,42931L,43860L,43861L,43862L,43863L,43864L,43865L,43866L,43867L,
+43868L,43869L,43870L,43871L,43872L,43873L,43874L,43875L,43876L,43877L,
+43878L,43879L,43880L,43881L,43882L,43883L,43884L,43885L,43886L,43887L,5024,
+5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,
+5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,
+5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,
+5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,
+5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,
+5100,5101,5102,5103,43968L,43969L,43970L,43971L,43972L,43973L,43974L,
+43975L,43976L,43977L,43978L,43979L,43980L,43981L,43982L,43983L,43984L,
+43985L,43986L,43987L,43988L,43989L,43990L,43991L,43992L,43993L,43994L,
+43995L,43996L,43997L,43998L,43999L,44000L,44001L,44002L,44003L,44004L,
+44005L,44006L,44007L,44008L,44009L,44010L,44011L,44012L,44013L,44014L,
+44015L,44016L,44017L,44018L,44019L,44020L,44021L,44022L,44023L,44024L,
+44025L,44026L,44027L,44028L,44029L,44030L,44031L,44032L,44033L,44034L,
+44035L,44036L,44037L,44038L,44039L,44040L,44041L,44042L,44043L,44044L,
+44045L,44046L,44047L,44048L,44049L,44050L,44051L,44052L,44053L,44054L,
+44055L,44056L,44057L,44058L,44059L,44060L,44061L,44062L,44063L,44064L,
+44065L,44066L,44067L,44068L,44069L,44070L,44071L,44072L,44073L,44074L,
+44075L,44076L,44077L,44078L,44079L,44080L,44081L,44082L,44083L,44084L,
+44085L,44086L,44087L,44088L,44089L,44090L,44091L,44092L,44093L,44094L,
+44095L,44096L,44097L,44098L,44099L,44100L,44101L,44102L,44103L,44104L,
+44105L,44106L,44107L,44108L,44109L,44110L,44111L,44112L,44113L,44114L,
+44115L,44116L,44117L,44118L,44119L,44120L,44121L,44122L,44123L,44124L,
+44125L,44126L,44127L,44128L,44129L,44130L,44131L,44132L,44133L,44134L,
+44135L,44136L,44137L,44138L,44139L,44140L,44141L,44142L,44143L,44144L,
+44145L,44146L,44147L,44148L,44149L,44150L,44151L,44152L,44153L,44154L,
+44155L,44156L,44157L,44158L,44159L,44160L,44161L,44162L,44163L,44164L,
+44165L,44166L,44167L,44168L,44169L,44170L,44171L,44172L,44173L,44174L,
+44175L,44176L,44177L,44178L,44179L,44180L,44181L,44182L,44183L,44184L,
+44185L,44186L,44187L,44188L,44189L,44190L,44191L,44192L,44193L,44194L,
+44195L,44196L,44197L,44198L,44199L,44200L,44201L,44202L,44203L,44204L,
+44205L,44206L,44207L,44208L,44209L,44210L,44211L,44212L,44213L,44214L,
+44215L,44216L,44217L,44218L,44219L,44220L,44221L,44222L,44223L,44224L,
+44225L,44226L,44227L,44228L,44229L,44230L,44231L,44232L,44233L,44234L,
+44235L,44236L,44237L,44238L,44239L,44240L,44241L,44242L,44243L,44244L,
+44245L,44246L,44247L,44248L,44249L,44250L,44251L,44252L,44253L,44254L,
+44255L,44256L,44257L,44258L,44259L,44260L,44261L,44262L,44263L,44264L,
+44265L,44266L,44267L,44268L,44269L,44270L,44271L,44272L,44273L,44274L,
+44275L,44276L,44277L,44278L,44279L,44280L,44281L,44282L,44283L,44284L,
+44285L,44286L,44287L,44288L,44289L,44290L,44291L,44292L,44293L,44294L,
+44295L,44296L,44297L,44298L,44299L,44300L,44301L,44302L,44303L,44304L,
+44305L,44306L,44307L,44308L,44309L,44310L,44311L,44312L,44313L,44314L,
+44315L,44316L,44317L,44318L,44319L,44320L,44321L,44322L,44323L,44324L,
+44325L,44326L,44327L,44328L,44329L,44330L,44331L,44332L,44333L,44334L,
+44335L,44336L,44337L,44338L,44339L,44340L,44341L,44342L,44343L,44344L,
+44345L,44346L,44347L,44348L,44349L,44350L,44351L,44352L,44353L,44354L,
+44355L,44356L,44357L,44358L,44359L,44360L,44361L,44362L,44363L,44364L,
+44365L,44366L,44367L,44368L,44369L,44370L,44371L,44372L,44373L,44374L,
+44375L,44376L,44377L,44378L,44379L,44380L,44381L,44382L,44383L,44384L,
+44385L,44386L,44387L,44388L,44389L,44390L,44391L,44392L,44393L,44394L,
+44395L,44396L,44397L,44398L,44399L,44400L,44401L,44402L,44403L,44404L,
+44405L,44406L,44407L,44408L,44409L,44410L,44411L,44412L,44413L,44414L,
+44415L,44416L,44417L,44418L,44419L,44420L,44421L,44422L,44423L,44424L,
+44425L,44426L,44427L,44428L,44429L,44430L,44431L,44432L,44433L,44434L,
+44435L,44436L,44437L,44438L,44439L,44440L,44441L,44442L,44443L,44444L,
+44445L,44446L,44447L,44448L,44449L,44450L,44451L,44452L,44453L,44454L,
+44455L,44456L,44457L,44458L,44459L,44460L,44461L,44462L,44463L,44464L,
+44465L,44466L,44467L,44468L,44469L,44470L,44471L,44472L,44473L,44474L,
+44475L,44476L,44477L,44478L,44479L,44480L,44481L,44482L,44483L,44484L,
+44485L,44486L,44487L,44488L,44489L,44490L,44491L,44492L,44493L,44494L,
+44495L,44496L,44497L,44498L,44499L,44500L,44501L,44502L,44503L,44504L,
+44505L,44506L,44507L,44508L,44509L,44510L,44511L,44512L,44513L,44514L,
+44515L,44516L,44517L,44518L,44519L,44520L,44521L,44522L,44523L,44524L,
+44525L,44526L,44527L,44528L,44529L,44530L,44531L,44532L,44533L,44534L,
+44535L,44536L,44537L,44538L,44539L,44540L,44541L,44542L,44543L,44544L,
+44545L,44546L,44547L,44548L,44549L,44550L,44551L,44552L,44553L,44554L,
+44555L,44556L,44557L,44558L,44559L,44560L,44561L,44562L,44563L,44564L,
+44565L,44566L,44567L,44568L,44569L,44570L,44571L,44572L,44573L,44574L,
+44575L,44576L,44577L,44578L,44579L,44580L,44581L,44582L,44583L,44584L,
+44585L,44586L,44587L,44588L,44589L,44590L,44591L,44592L,44593L,44594L,
+44595L,44596L,44597L,44598L,44599L,44600L,44601L,44602L,44603L,44604L,
+44605L,44606L,44607L,44608L,44609L,44610L,44611L,44612L,44613L,44614L,
+44615L,44616L,44617L,44618L,44619L,44620L,44621L,44622L,44623L,44624L,
+44625L,44626L,44627L,44628L,44629L,44630L,44631L,44632L,44633L,44634L,
+44635L,44636L,44637L,44638L,44639L,44640L,44641L,44642L,44643L,44644L,
+44645L,44646L,44647L,44648L,44649L,44650L,44651L,44652L,44653L,44654L,
+44655L,44656L,44657L,44658L,44659L,44660L,44661L,44662L,44663L,44664L,
+44665L,44666L,44667L,44668L,44669L,44670L,44671L,44672L,44673L,44674L,
+44675L,44676L,44677L,44678L,44679L,44680L,44681L,44682L,44683L,44684L,
+44685L,44686L,44687L,44688L,44689L,44690L,44691L,44692L,44693L,44694L,
+44695L,44696L,44697L,44698L,44699L,44700L,44701L,44702L,44703L,44704L,
+44705L,44706L,44707L,44708L,44709L,44710L,44711L,44712L,44713L,44714L,
+44715L,44716L,44717L,44718L,44719L,44720L,44721L,44722L,44723L,44724L,
+44725L,44726L,44727L,44728L,44729L,44730L,44731L,44732L,44733L,44734L,
+44735L,44736L,44737L,44738L,44739L,44740L,44741L,44742L,44743L,44744L,
+44745L,44746L,44747L,44748L,44749L,44750L,44751L,44752L,44753L,44754L,
+44755L,44756L,44757L,44758L,44759L,44760L,44761L,44762L,44763L,44764L,
+44765L,44766L,44767L,44768L,44769L,44770L,44771L,44772L,44773L,44774L,
+44775L,44776L,44777L,44778L,44779L,44780L,44781L,44782L,44783L,44784L,
+44785L,44786L,44787L,44788L,44789L,44790L,44791L,44792L,44793L,44794L,
+44795L,44796L,44797L,44798L,44799L,44800L,44801L,44802L,44803L,44804L,
+44805L,44806L,44807L,44808L,44809L,44810L,44811L,44812L,44813L,44814L,
+44815L,44816L,44817L,44818L,44819L,44820L,44821L,44822L,44823L,44824L,
+44825L,44826L,44827L,44828L,44829L,44830L,44831L,44832L,44833L,44834L,
+44835L,44836L,44837L,44838L,44839L,44840L,44841L,44842L,44843L,44844L,
+44845L,44846L,44847L,44848L,44849L,44850L,44851L,44852L,44853L,44854L,
+44855L,44856L,44857L,44858L,44859L,44860L,44861L,44862L,44863L,44864L,
+44865L,44866L,44867L,44868L,44869L,44870L,44871L,44872L,44873L,44874L,
+44875L,44876L,44877L,44878L,44879L,44880L,44881L,44882L,44883L,44884L,
+44885L,44886L,44887L,44888L,44889L,44890L,44891L,44892L,44893L,44894L,
+44895L,44896L,44897L,44898L,44899L,44900L,44901L,44902L,44903L,44904L,
+44905L,44906L,44907L,44908L,44909L,44910L,44911L,44912L,44913L,44914L,
+44915L,44916L,44917L,44918L,44919L,44920L,44921L,44922L,44923L,44924L,
+44925L,44926L,44927L,44928L,44929L,44930L,44931L,44932L,44933L,44934L,
+44935L,44936L,44937L,44938L,44939L,44940L,44941L,44942L,44943L,44944L,
+44945L,44946L,44947L,44948L,44949L,44950L,44951L,44952L,44953L,44954L,
+44955L,44956L,44957L,44958L,44959L,44960L,44961L,44962L,44963L,44964L,
+44965L,44966L,44967L,44968L,44969L,44970L,44971L,44972L,44973L,44974L,
+44975L,44976L,44977L,44978L,44979L,44980L,44981L,44982L,44983L,44984L,
+44985L,44986L,44987L,44988L,44989L,44990L,44991L,44992L,44993L,44994L,
+44995L,44996L,44997L,44998L,44999L,45000L,45001L,45002L,45003L,45004L,
+45005L,45006L,45007L,45008L,45009L,45010L,45011L,45012L,45013L,45014L,
+45015L,45016L,45017L,45018L,45019L,45020L,45021L,45022L,45023L,45024L,
+45025L,45026L,45027L,45028L,45029L,45030L,45031L,45032L,45033L,45034L,
+45035L,45036L,45037L,45038L,45039L,45040L,45041L,45042L,45043L,45044L,
+45045L,45046L,45047L,45048L,45049L,45050L,45051L,45052L,45053L,45054L,
+45055L,45056L,45057L,45058L,45059L,45060L,45061L,45062L,45063L,45064L,
+45065L,45066L,45067L,45068L,45069L,45070L,45071L,45072L,45073L,45074L,
+45075L,45076L,45077L,45078L,45079L,45080L,45081L,45082L,45083L,45084L,
+45085L,45086L,45087L,45088L,45089L,45090L,45091L,45092L,45093L,45094L,
+45095L,45096L,45097L,45098L,45099L,45100L,45101L,45102L,45103L,45104L,
+45105L,45106L,45107L,45108L,45109L,45110L,45111L,45112L,45113L,45114L,
+45115L,45116L,45117L,45118L,45119L,45120L,45121L,45122L,45123L,45124L,
+45125L,45126L,45127L,45128L,45129L,45130L,45131L,45132L,45133L,45134L,
+45135L,45136L,45137L,45138L,45139L,45140L,45141L,45142L,45143L,45144L,
+45145L,45146L,45147L,45148L,45149L,45150L,45151L,45152L,45153L,45154L,
+45155L,45156L,45157L,45158L,45159L,45160L,45161L,45162L,45163L,45164L,
+45165L,45166L,45167L,45168L,45169L,45170L,45171L,45172L,45173L,45174L,
+45175L,45176L,45177L,45178L,45179L,45180L,45181L,45182L,45183L,45184L,
+45185L,45186L,45187L,45188L,45189L,45190L,45191L,45192L,45193L,45194L,
+45195L,45196L,45197L,45198L,45199L,45200L,45201L,45202L,45203L,45204L,
+45205L,45206L,45207L,45208L,45209L,45210L,45211L,45212L,45213L,45214L,
+45215L,45216L,45217L,45218L,45219L,45220L,45221L,45222L,45223L,45224L,
+45225L,45226L,45227L,45228L,45229L,45230L,45231L,45232L,45233L,45234L,
+45235L,45236L,45237L,45238L,45239L,45240L,45241L,45242L,45243L,45244L,
+45245L,45246L,45247L,45248L,45249L,45250L,45251L,45252L,45253L,45254L,
+45255L,45256L,45257L,45258L,45259L,45260L,45261L,45262L,45263L,45264L,
+45265L,45266L,45267L,45268L,45269L,45270L,45271L,45272L,45273L,45274L,
+45275L,45276L,45277L,45278L,45279L,45280L,45281L,45282L,45283L,45284L,
+45285L,45286L,45287L,45288L,45289L,45290L,45291L,45292L,45293L,45294L,
+45295L,45296L,45297L,45298L,45299L,45300L,45301L,45302L,45303L,45304L,
+45305L,45306L,45307L,45308L,45309L,45310L,45311L,45312L,45313L,45314L,
+45315L,45316L,45317L,45318L,45319L,45320L,45321L,45322L,45323L,45324L,
+45325L,45326L,45327L,45328L,45329L,45330L,45331L,45332L,45333L,45334L,
+45335L,45336L,45337L,45338L,45339L,45340L,45341L,45342L,45343L,45344L,
+45345L,45346L,45347L,45348L,45349L,45350L,45351L,45352L,45353L,45354L,
+45355L,45356L,45357L,45358L,45359L,45360L,45361L,45362L,45363L,45364L,
+45365L,45366L,45367L,45368L,45369L,45370L,45371L,45372L,45373L,45374L,
+45375L,45376L,45377L,45378L,45379L,45380L,45381L,45382L,45383L,45384L,
+45385L,45386L,45387L,45388L,45389L,45390L,45391L,45392L,45393L,45394L,
+45395L,45396L,45397L,45398L,45399L,45400L,45401L,45402L,45403L,45404L,
+45405L,45406L,45407L,45408L,45409L,45410L,45411L,45412L,45413L,45414L,
+45415L,45416L,45417L,45418L,45419L,45420L,45421L,45422L,45423L,45424L,
+45425L,45426L,45427L,45428L,45429L,45430L,45431L,45432L,45433L,45434L,
+45435L,45436L,45437L,45438L,45439L,45440L,45441L,45442L,45443L,45444L,
+45445L,45446L,45447L,45448L,45449L,45450L,45451L,45452L,45453L,45454L,
+45455L,45456L,45457L,45458L,45459L,45460L,45461L,45462L,45463L,45464L,
+45465L,45466L,45467L,45468L,45469L,45470L,45471L,45472L,45473L,45474L,
+45475L,45476L,45477L,45478L,45479L,45480L,45481L,45482L,45483L,45484L,
+45485L,45486L,45487L,45488L,45489L,45490L,45491L,45492L,45493L,45494L,
+45495L,45496L,45497L,45498L,45499L,45500L,45501L,45502L,45503L,45504L,
+45505L,45506L,45507L,45508L,45509L,45510L,45511L,45512L,45513L,45514L,
+45515L,45516L,45517L,45518L,45519L,45520L,45521L,45522L,45523L,45524L,
+45525L,45526L,45527L,45528L,45529L,45530L,45531L,45532L,45533L,45534L,
+45535L,45536L,45537L,45538L,45539L,45540L,45541L,45542L,45543L,45544L,
+45545L,45546L,45547L,45548L,45549L,45550L,45551L,45552L,45553L,45554L,
+45555L,45556L,45557L,45558L,45559L,45560L,45561L,45562L,45563L,45564L,
+45565L,45566L,45567L,45568L,45569L,45570L,45571L,45572L,45573L,45574L,
+45575L,45576L,45577L,45578L,45579L,45580L,45581L,45582L,45583L,45584L,
+45585L,45586L,45587L,45588L,45589L,45590L,45591L,45592L,45593L,45594L,
+45595L,45596L,45597L,45598L,45599L,45600L,45601L,45602L,45603L,45604L,
+45605L,45606L,45607L,45608L,45609L,45610L,45611L,45612L,45613L,45614L,
+45615L,45616L,45617L,45618L,45619L,45620L,45621L,45622L,45623L,45624L,
+45625L,45626L,45627L,45628L,45629L,45630L,45631L,45632L,45633L,45634L,
+45635L,45636L,45637L,45638L,45639L,45640L,45641L,45642L,45643L,45644L,
+45645L,45646L,45647L,45648L,45649L,45650L,45651L,45652L,45653L,45654L,
+45655L,45656L,45657L,45658L,45659L,45660L,45661L,45662L,45663L,45664L,
+45665L,45666L,45667L,45668L,45669L,45670L,45671L,45672L,45673L,45674L,
+45675L,45676L,45677L,45678L,45679L,45680L,45681L,45682L,45683L,45684L,
+45685L,45686L,45687L,45688L,45689L,45690L,45691L,45692L,45693L,45694L,
+45695L,45696L,45697L,45698L,45699L,45700L,45701L,45702L,45703L,45704L,
+45705L,45706L,45707L,45708L,45709L,45710L,45711L,45712L,45713L,45714L,
+45715L,45716L,45717L,45718L,45719L,45720L,45721L,45722L,45723L,45724L,
+45725L,45726L,45727L,45728L,45729L,45730L,45731L,45732L,45733L,45734L,
+45735L,45736L,45737L,45738L,45739L,45740L,45741L,45742L,45743L,45744L,
+45745L,45746L,45747L,45748L,45749L,45750L,45751L,45752L,45753L,45754L,
+45755L,45756L,45757L,45758L,45759L,45760L,45761L,45762L,45763L,45764L,
+45765L,45766L,45767L,45768L,45769L,45770L,45771L,45772L,45773L,45774L,
+45775L,45776L,45777L,45778L,45779L,45780L,45781L,45782L,45783L,45784L,
+45785L,45786L,45787L,45788L,45789L,45790L,45791L,45792L,45793L,45794L,
+45795L,45796L,45797L,45798L,45799L,45800L,45801L,45802L,45803L,45804L,
+45805L,45806L,45807L,45808L,45809L,45810L,45811L,45812L,45813L,45814L,
+45815L,45816L,45817L,45818L,45819L,45820L,45821L,45822L,45823L,45824L,
+45825L,45826L,45827L,45828L,45829L,45830L,45831L,45832L,45833L,45834L,
+45835L,45836L,45837L,45838L,45839L,45840L,45841L,45842L,45843L,45844L,
+45845L,45846L,45847L,45848L,45849L,45850L,45851L,45852L,45853L,45854L,
+45855L,45856L,45857L,45858L,45859L,45860L,45861L,45862L,45863L,45864L,
+45865L,45866L,45867L,45868L,45869L,45870L,45871L,45872L,45873L,45874L,
+45875L,45876L,45877L,45878L,45879L,45880L,45881L,45882L,45883L,45884L,
+45885L,45886L,45887L,45888L,45889L,45890L,45891L,45892L,45893L,45894L,
+45895L,45896L,45897L,45898L,45899L,45900L,45901L,45902L,45903L,45904L,
+45905L,45906L,45907L,45908L,45909L,45910L,45911L,45912L,45913L,45914L,
+45915L,45916L,45917L,45918L,45919L,45920L,45921L,45922L,45923L,45924L,
+45925L,45926L,45927L,45928L,45929L,45930L,45931L,45932L,45933L,45934L,
+45935L,45936L,45937L,45938L,45939L,45940L,45941L,45942L,45943L,45944L,
+45945L,45946L,45947L,45948L,45949L,45950L,45951L,45952L,45953L,45954L,
+45955L,45956L,45957L,45958L,45959L,45960L,45961L,45962L,45963L,45964L,
+45965L,45966L,45967L,45968L,45969L,45970L,45971L,45972L,45973L,45974L,
+45975L,45976L,45977L,45978L,45979L,45980L,45981L,45982L,45983L,45984L,
+45985L,45986L,45987L,45988L,45989L,45990L,45991L,45992L,45993L,45994L,
+45995L,45996L,45997L,45998L,45999L,46000L,46001L,46002L,46003L,46004L,
+46005L,46006L,46007L,46008L,46009L,46010L,46011L,46012L,46013L,46014L,
+46015L,46016L,46017L,46018L,46019L,46020L,46021L,46022L,46023L,46024L,
+46025L,46026L,46027L,46028L,46029L,46030L,46031L,46032L,46033L,46034L,
+46035L,46036L,46037L,46038L,46039L,46040L,46041L,46042L,46043L,46044L,
+46045L,46046L,46047L,46048L,46049L,46050L,46051L,46052L,46053L,46054L,
+46055L,46056L,46057L,46058L,46059L,46060L,46061L,46062L,46063L,46064L,
+46065L,46066L,46067L,46068L,46069L,46070L,46071L,46072L,46073L,46074L,
+46075L,46076L,46077L,46078L,46079L,46080L,46081L,46082L,46083L,46084L,
+46085L,46086L,46087L,46088L,46089L,46090L,46091L,46092L,46093L,46094L,
+46095L,46096L,46097L,46098L,46099L,46100L,46101L,46102L,46103L,46104L,
+46105L,46106L,46107L,46108L,46109L,46110L,46111L,46112L,46113L,46114L,
+46115L,46116L,46117L,46118L,46119L,46120L,46121L,46122L,46123L,46124L,
+46125L,46126L,46127L,46128L,46129L,46130L,46131L,46132L,46133L,46134L,
+46135L,46136L,46137L,46138L,46139L,46140L,46141L,46142L,46143L,46144L,
+46145L,46146L,46147L,46148L,46149L,46150L,46151L,46152L,46153L,46154L,
+46155L,46156L,46157L,46158L,46159L,46160L,46161L,46162L,46163L,46164L,
+46165L,46166L,46167L,46168L,46169L,46170L,46171L,46172L,46173L,46174L,
+46175L,46176L,46177L,46178L,46179L,46180L,46181L,46182L,46183L,46184L,
+46185L,46186L,46187L,46188L,46189L,46190L,46191L,46192L,46193L,46194L,
+46195L,46196L,46197L,46198L,46199L,46200L,46201L,46202L,46203L,46204L,
+46205L,46206L,46207L,46208L,46209L,46210L,46211L,46212L,46213L,46214L,
+46215L,46216L,46217L,46218L,46219L,46220L,46221L,46222L,46223L,46224L,
+46225L,46226L,46227L,46228L,46229L,46230L,46231L,46232L,46233L,46234L,
+46235L,46236L,46237L,46238L,46239L,46240L,46241L,46242L,46243L,46244L,
+46245L,46246L,46247L,46248L,46249L,46250L,46251L,46252L,46253L,46254L,
+46255L,46256L,46257L,46258L,46259L,46260L,46261L,46262L,46263L,46264L,
+46265L,46266L,46267L,46268L,46269L,46270L,46271L,46272L,46273L,46274L,
+46275L,46276L,46277L,46278L,46279L,46280L,46281L,46282L,46283L,46284L,
+46285L,46286L,46287L,46288L,46289L,46290L,46291L,46292L,46293L,46294L,
+46295L,46296L,46297L,46298L,46299L,46300L,46301L,46302L,46303L,46304L,
+46305L,46306L,46307L,46308L,46309L,46310L,46311L,46312L,46313L,46314L,
+46315L,46316L,46317L,46318L,46319L,46320L,46321L,46322L,46323L,46324L,
+46325L,46326L,46327L,46328L,46329L,46330L,46331L,46332L,46333L,46334L,
+46335L,46336L,46337L,46338L,46339L,46340L,46341L,46342L,46343L,46344L,
+46345L,46346L,46347L,46348L,46349L,46350L,46351L,46352L,46353L,46354L,
+46355L,46356L,46357L,46358L,46359L,46360L,46361L,46362L,46363L,46364L,
+46365L,46366L,46367L,46368L,46369L,46370L,46371L,46372L,46373L,46374L,
+46375L,46376L,46377L,46378L,46379L,46380L,46381L,46382L,46383L,46384L,
+46385L,46386L,46387L,46388L,46389L,46390L,46391L,46392L,46393L,46394L,
+46395L,46396L,46397L,46398L,46399L,46400L,46401L,46402L,46403L,46404L,
+46405L,46406L,46407L,46408L,46409L,46410L,46411L,46412L,46413L,46414L,
+46415L,46416L,46417L,46418L,46419L,46420L,46421L,46422L,46423L,46424L,
+46425L,46426L,46427L,46428L,46429L,46430L,46431L,46432L,46433L,46434L,
+46435L,46436L,46437L,46438L,46439L,46440L,46441L,46442L,46443L,46444L,
+46445L,46446L,46447L,46448L,46449L,46450L,46451L,46452L,46453L,46454L,
+46455L,46456L,46457L,46458L,46459L,46460L,46461L,46462L,46463L,46464L,
+46465L,46466L,46467L,46468L,46469L,46470L,46471L,46472L,46473L,46474L,
+46475L,46476L,46477L,46478L,46479L,46480L,46481L,46482L,46483L,46484L,
+46485L,46486L,46487L,46488L,46489L,46490L,46491L,46492L,46493L,46494L,
+46495L,46496L,46497L,46498L,46499L,46500L,46501L,46502L,46503L,46504L,
+46505L,46506L,46507L,46508L,46509L,46510L,46511L,46512L,46513L,46514L,
+46515L,46516L,46517L,46518L,46519L,46520L,46521L,46522L,46523L,46524L,
+46525L,46526L,46527L,46528L,46529L,46530L,46531L,46532L,46533L,46534L,
+46535L,46536L,46537L,46538L,46539L,46540L,46541L,46542L,46543L,46544L,
+46545L,46546L,46547L,46548L,46549L,46550L,46551L,46552L,46553L,46554L,
+46555L,46556L,46557L,46558L,46559L,46560L,46561L,46562L,46563L,46564L,
+46565L,46566L,46567L,46568L,46569L,46570L,46571L,46572L,46573L,46574L,
+46575L,46576L,46577L,46578L,46579L,46580L,46581L,46582L,46583L,46584L,
+46585L,46586L,46587L,46588L,46589L,46590L,46591L,46592L,46593L,46594L,
+46595L,46596L,46597L,46598L,46599L,46600L,46601L,46602L,46603L,46604L,
+46605L,46606L,46607L,46608L,46609L,46610L,46611L,46612L,46613L,46614L,
+46615L,46616L,46617L,46618L,46619L,46620L,46621L,46622L,46623L,46624L,
+46625L,46626L,46627L,46628L,46629L,46630L,46631L,46632L,46633L,46634L,
+46635L,46636L,46637L,46638L,46639L,46640L,46641L,46642L,46643L,46644L,
+46645L,46646L,46647L,46648L,46649L,46650L,46651L,46652L,46653L,46654L,
+46655L,46656L,46657L,46658L,46659L,46660L,46661L,46662L,46663L,46664L,
+46665L,46666L,46667L,46668L,46669L,46670L,46671L,46672L,46673L,46674L,
+46675L,46676L,46677L,46678L,46679L,46680L,46681L,46682L,46683L,46684L,
+46685L,46686L,46687L,46688L,46689L,46690L,46691L,46692L,46693L,46694L,
+46695L,46696L,46697L,46698L,46699L,46700L,46701L,46702L,46703L,46704L,
+46705L,46706L,46707L,46708L,46709L,46710L,46711L,46712L,46713L,46714L,
+46715L,46716L,46717L,46718L,46719L,46720L,46721L,46722L,46723L,46724L,
+46725L,46726L,46727L,46728L,46729L,46730L,46731L,46732L,46733L,46734L,
+46735L,46736L,46737L,46738L,46739L,46740L,46741L,46742L,46743L,46744L,
+46745L,46746L,46747L,46748L,46749L,46750L,46751L,46752L,46753L,46754L,
+46755L,46756L,46757L,46758L,46759L,46760L,46761L,46762L,46763L,46764L,
+46765L,46766L,46767L,46768L,46769L,46770L,46771L,46772L,46773L,46774L,
+46775L,46776L,46777L,46778L,46779L,46780L,46781L,46782L,46783L,46784L,
+46785L,46786L,46787L,46788L,46789L,46790L,46791L,46792L,46793L,46794L,
+46795L,46796L,46797L,46798L,46799L,46800L,46801L,46802L,46803L,46804L,
+46805L,46806L,46807L,46808L,46809L,46810L,46811L,46812L,46813L,46814L,
+46815L,46816L,46817L,46818L,46819L,46820L,46821L,46822L,46823L,46824L,
+46825L,46826L,46827L,46828L,46829L,46830L,46831L,46832L,46833L,46834L,
+46835L,46836L,46837L,46838L,46839L,46840L,46841L,46842L,46843L,46844L,
+46845L,46846L,46847L,46848L,46849L,46850L,46851L,46852L,46853L,46854L,
+46855L,46856L,46857L,46858L,46859L,46860L,46861L,46862L,46863L,46864L,
+46865L,46866L,46867L,46868L,46869L,46870L,46871L,46872L,46873L,46874L,
+46875L,46876L,46877L,46878L,46879L,46880L,46881L,46882L,46883L,46884L,
+46885L,46886L,46887L,46888L,46889L,46890L,46891L,46892L,46893L,46894L,
+46895L,46896L,46897L,46898L,46899L,46900L,46901L,46902L,46903L,46904L,
+46905L,46906L,46907L,46908L,46909L,46910L,46911L,46912L,46913L,46914L,
+46915L,46916L,46917L,46918L,46919L,46920L,46921L,46922L,46923L,46924L,
+46925L,46926L,46927L,46928L,46929L,46930L,46931L,46932L,46933L,46934L,
+46935L,46936L,46937L,46938L,46939L,46940L,46941L,46942L,46943L,46944L,
+46945L,46946L,46947L,46948L,46949L,46950L,46951L,46952L,46953L,46954L,
+46955L,46956L,46957L,46958L,46959L,46960L,46961L,46962L,46963L,46964L,
+46965L,46966L,46967L,46968L,46969L,46970L,46971L,46972L,46973L,46974L,
+46975L,46976L,46977L,46978L,46979L,46980L,46981L,46982L,46983L,46984L,
+46985L,46986L,46987L,46988L,46989L,46990L,46991L,46992L,46993L,46994L,
+46995L,46996L,46997L,46998L,46999L,47000L,47001L,47002L,47003L,47004L,
+47005L,47006L,47007L,47008L,47009L,47010L,47011L,47012L,47013L,47014L,
+47015L,47016L,47017L,47018L,47019L,47020L,47021L,47022L,47023L,47024L,
+47025L,47026L,47027L,47028L,47029L,47030L,47031L,47032L,47033L,47034L,
+47035L,47036L,47037L,47038L,47039L,47040L,47041L,47042L,47043L,47044L,
+47045L,47046L,47047L,47048L,47049L,47050L,47051L,47052L,47053L,47054L,
+47055L,47056L,47057L,47058L,47059L,47060L,47061L,47062L,47063L,47064L,
+47065L,47066L,47067L,47068L,47069L,47070L,47071L,47072L,47073L,47074L,
+47075L,47076L,47077L,47078L,47079L,47080L,47081L,47082L,47083L,47084L,
+47085L,47086L,47087L,47088L,47089L,47090L,47091L,47092L,47093L,47094L,
+47095L,47096L,47097L,47098L,47099L,47100L,47101L,47102L,47103L,47104L,
+47105L,47106L,47107L,47108L,47109L,47110L,47111L,47112L,47113L,47114L,
+47115L,47116L,47117L,47118L,47119L,47120L,47121L,47122L,47123L,47124L,
+47125L,47126L,47127L,47128L,47129L,47130L,47131L,47132L,47133L,47134L,
+47135L,47136L,47137L,47138L,47139L,47140L,47141L,47142L,47143L,47144L,
+47145L,47146L,47147L,47148L,47149L,47150L,47151L,47152L,47153L,47154L,
+47155L,47156L,47157L,47158L,47159L,47160L,47161L,47162L,47163L,47164L,
+47165L,47166L,47167L,47168L,47169L,47170L,47171L,47172L,47173L,47174L,
+47175L,47176L,47177L,47178L,47179L,47180L,47181L,47182L,47183L,47184L,
+47185L,47186L,47187L,47188L,47189L,47190L,47191L,47192L,47193L,47194L,
+47195L,47196L,47197L,47198L,47199L,47200L,47201L,47202L,47203L,47204L,
+47205L,47206L,47207L,47208L,47209L,47210L,47211L,47212L,47213L,47214L,
+47215L,47216L,47217L,47218L,47219L,47220L,47221L,47222L,47223L,47224L,
+47225L,47226L,47227L,47228L,47229L,47230L,47231L,47232L,47233L,47234L,
+47235L,47236L,47237L,47238L,47239L,47240L,47241L,47242L,47243L,47244L,
+47245L,47246L,47247L,47248L,47249L,47250L,47251L,47252L,47253L,47254L,
+47255L,47256L,47257L,47258L,47259L,47260L,47261L,47262L,47263L,47264L,
+47265L,47266L,47267L,47268L,47269L,47270L,47271L,47272L,47273L,47274L,
+47275L,47276L,47277L,47278L,47279L,47280L,47281L,47282L,47283L,47284L,
+47285L,47286L,47287L,47288L,47289L,47290L,47291L,47292L,47293L,47294L,
+47295L,47296L,47297L,47298L,47299L,47300L,47301L,47302L,47303L,47304L,
+47305L,47306L,47307L,47308L,47309L,47310L,47311L,47312L,47313L,47314L,
+47315L,47316L,47317L,47318L,47319L,47320L,47321L,47322L,47323L,47324L,
+47325L,47326L,47327L,47328L,47329L,47330L,47331L,47332L,47333L,47334L,
+47335L,47336L,47337L,47338L,47339L,47340L,47341L,47342L,47343L,47344L,
+47345L,47346L,47347L,47348L,47349L,47350L,47351L,47352L,47353L,47354L,
+47355L,47356L,47357L,47358L,47359L,47360L,47361L,47362L,47363L,47364L,
+47365L,47366L,47367L,47368L,47369L,47370L,47371L,47372L,47373L,47374L,
+47375L,47376L,47377L,47378L,47379L,47380L,47381L,47382L,47383L,47384L,
+47385L,47386L,47387L,47388L,47389L,47390L,47391L,47392L,47393L,47394L,
+47395L,47396L,47397L,47398L,47399L,47400L,47401L,47402L,47403L,47404L,
+47405L,47406L,47407L,47408L,47409L,47410L,47411L,47412L,47413L,47414L,
+47415L,47416L,47417L,47418L,47419L,47420L,47421L,47422L,47423L,47424L,
+47425L,47426L,47427L,47428L,47429L,47430L,47431L,47432L,47433L,47434L,
+47435L,47436L,47437L,47438L,47439L,47440L,47441L,47442L,47443L,47444L,
+47445L,47446L,47447L,47448L,47449L,47450L,47451L,47452L,47453L,47454L,
+47455L,47456L,47457L,47458L,47459L,47460L,47461L,47462L,47463L,47464L,
+47465L,47466L,47467L,47468L,47469L,47470L,47471L,47472L,47473L,47474L,
+47475L,47476L,47477L,47478L,47479L,47480L,47481L,47482L,47483L,47484L,
+47485L,47486L,47487L,47488L,47489L,47490L,47491L,47492L,47493L,47494L,
+47495L,47496L,47497L,47498L,47499L,47500L,47501L,47502L,47503L,47504L,
+47505L,47506L,47507L,47508L,47509L,47510L,47511L,47512L,47513L,47514L,
+47515L,47516L,47517L,47518L,47519L,47520L,47521L,47522L,47523L,47524L,
+47525L,47526L,47527L,47528L,47529L,47530L,47531L,47532L,47533L,47534L,
+47535L,47536L,47537L,47538L,47539L,47540L,47541L,47542L,47543L,47544L,
+47545L,47546L,47547L,47548L,47549L,47550L,47551L,47552L,47553L,47554L,
+47555L,47556L,47557L,47558L,47559L,47560L,47561L,47562L,47563L,47564L,
+47565L,47566L,47567L,47568L,47569L,47570L,47571L,47572L,47573L,47574L,
+47575L,47576L,47577L,47578L,47579L,47580L,47581L,47582L,47583L,47584L,
+47585L,47586L,47587L,47588L,47589L,47590L,47591L,47592L,47593L,47594L,
+47595L,47596L,47597L,47598L,47599L,47600L,47601L,47602L,47603L,47604L,
+47605L,47606L,47607L,47608L,47609L,47610L,47611L,47612L,47613L,47614L,
+47615L,47616L,47617L,47618L,47619L,47620L,47621L,47622L,47623L,47624L,
+47625L,47626L,47627L,47628L,47629L,47630L,47631L,47632L,47633L,47634L,
+47635L,47636L,47637L,47638L,47639L,47640L,47641L,47642L,47643L,47644L,
+47645L,47646L,47647L,47648L,47649L,47650L,47651L,47652L,47653L,47654L,
+47655L,47656L,47657L,47658L,47659L,47660L,47661L,47662L,47663L,47664L,
+47665L,47666L,47667L,47668L,47669L,47670L,47671L,47672L,47673L,47674L,
+47675L,47676L,47677L,47678L,47679L,47680L,47681L,47682L,47683L,47684L,
+47685L,47686L,47687L,47688L,47689L,47690L,47691L,47692L,47693L,47694L,
+47695L,47696L,47697L,47698L,47699L,47700L,47701L,47702L,47703L,47704L,
+47705L,47706L,47707L,47708L,47709L,47710L,47711L,47712L,47713L,47714L,
+47715L,47716L,47717L,47718L,47719L,47720L,47721L,47722L,47723L,47724L,
+47725L,47726L,47727L,47728L,47729L,47730L,47731L,47732L,47733L,47734L,
+47735L,47736L,47737L,47738L,47739L,47740L,47741L,47742L,47743L,47744L,
+47745L,47746L,47747L,47748L,47749L,47750L,47751L,47752L,47753L,47754L,
+47755L,47756L,47757L,47758L,47759L,47760L,47761L,47762L,47763L,47764L,
+47765L,47766L,47767L,47768L,47769L,47770L,47771L,47772L,47773L,47774L,
+47775L,47776L,47777L,47778L,47779L,47780L,47781L,47782L,47783L,47784L,
+47785L,47786L,47787L,47788L,47789L,47790L,47791L,47792L,47793L,47794L,
+47795L,47796L,47797L,47798L,47799L,47800L,47801L,47802L,47803L,47804L,
+47805L,47806L,47807L,47808L,47809L,47810L,47811L,47812L,47813L,47814L,
+47815L,47816L,47817L,47818L,47819L,47820L,47821L,47822L,47823L,47824L,
+47825L,47826L,47827L,47828L,47829L,47830L,47831L,47832L,47833L,47834L,
+47835L,47836L,47837L,47838L,47839L,47840L,47841L,47842L,47843L,47844L,
+47845L,47846L,47847L,47848L,47849L,47850L,47851L,47852L,47853L,47854L,
+47855L,47856L,47857L,47858L,47859L,47860L,47861L,47862L,47863L,47864L,
+47865L,47866L,47867L,47868L,47869L,47870L,47871L,47872L,47873L,47874L,
+47875L,47876L,47877L,47878L,47879L,47880L,47881L,47882L,47883L,47884L,
+47885L,47886L,47887L,47888L,47889L,47890L,47891L,47892L,47893L,47894L,
+47895L,47896L,47897L,47898L,47899L,47900L,47901L,47902L,47903L,47904L,
+47905L,47906L,47907L,47908L,47909L,47910L,47911L,47912L,47913L,47914L,
+47915L,47916L,47917L,47918L,47919L,47920L,47921L,47922L,47923L,47924L,
+47925L,47926L,47927L,47928L,47929L,47930L,47931L,47932L,47933L,47934L,
+47935L,47936L,47937L,47938L,47939L,47940L,47941L,47942L,47943L,47944L,
+47945L,47946L,47947L,47948L,47949L,47950L,47951L,47952L,47953L,47954L,
+47955L,47956L,47957L,47958L,47959L,47960L,47961L,47962L,47963L,47964L,
+47965L,47966L,47967L,47968L,47969L,47970L,47971L,47972L,47973L,47974L,
+47975L,47976L,47977L,47978L,47979L,47980L,47981L,47982L,47983L,47984L,
+47985L,47986L,47987L,47988L,47989L,47990L,47991L,47992L,47993L,47994L,
+47995L,47996L,47997L,47998L,47999L,48000L,48001L,48002L,48003L,48004L,
+48005L,48006L,48007L,48008L,48009L,48010L,48011L,48012L,48013L,48014L,
+48015L,48016L,48017L,48018L,48019L,48020L,48021L,48022L,48023L,48024L,
+48025L,48026L,48027L,48028L,48029L,48030L,48031L,48032L,48033L,48034L,
+48035L,48036L,48037L,48038L,48039L,48040L,48041L,48042L,48043L,48044L,
+48045L,48046L,48047L,48048L,48049L,48050L,48051L,48052L,48053L,48054L,
+48055L,48056L,48057L,48058L,48059L,48060L,48061L,48062L,48063L,48064L,
+48065L,48066L,48067L,48068L,48069L,48070L,48071L,48072L,48073L,48074L,
+48075L,48076L,48077L,48078L,48079L,48080L,48081L,48082L,48083L,48084L,
+48085L,48086L,48087L,48088L,48089L,48090L,48091L,48092L,48093L,48094L,
+48095L,48096L,48097L,48098L,48099L,48100L,48101L,48102L,48103L,48104L,
+48105L,48106L,48107L,48108L,48109L,48110L,48111L,48112L,48113L,48114L,
+48115L,48116L,48117L,48118L,48119L,48120L,48121L,48122L,48123L,48124L,
+48125L,48126L,48127L,48128L,48129L,48130L,48131L,48132L,48133L,48134L,
+48135L,48136L,48137L,48138L,48139L,48140L,48141L,48142L,48143L,48144L,
+48145L,48146L,48147L,48148L,48149L,48150L,48151L,48152L,48153L,48154L,
+48155L,48156L,48157L,48158L,48159L,48160L,48161L,48162L,48163L,48164L,
+48165L,48166L,48167L,48168L,48169L,48170L,48171L,48172L,48173L,48174L,
+48175L,48176L,48177L,48178L,48179L,48180L,48181L,48182L,48183L,48184L,
+48185L,48186L,48187L,48188L,48189L,48190L,48191L,48192L,48193L,48194L,
+48195L,48196L,48197L,48198L,48199L,48200L,48201L,48202L,48203L,48204L,
+48205L,48206L,48207L,48208L,48209L,48210L,48211L,48212L,48213L,48214L,
+48215L,48216L,48217L,48218L,48219L,48220L,48221L,48222L,48223L,48224L,
+48225L,48226L,48227L,48228L,48229L,48230L,48231L,48232L,48233L,48234L,
+48235L,48236L,48237L,48238L,48239L,48240L,48241L,48242L,48243L,48244L,
+48245L,48246L,48247L,48248L,48249L,48250L,48251L,48252L,48253L,48254L,
+48255L,48256L,48257L,48258L,48259L,48260L,48261L,48262L,48263L,48264L,
+48265L,48266L,48267L,48268L,48269L,48270L,48271L,48272L,48273L,48274L,
+48275L,48276L,48277L,48278L,48279L,48280L,48281L,48282L,48283L,48284L,
+48285L,48286L,48287L,48288L,48289L,48290L,48291L,48292L,48293L,48294L,
+48295L,48296L,48297L,48298L,48299L,48300L,48301L,48302L,48303L,48304L,
+48305L,48306L,48307L,48308L,48309L,48310L,48311L,48312L,48313L,48314L,
+48315L,48316L,48317L,48318L,48319L,48320L,48321L,48322L,48323L,48324L,
+48325L,48326L,48327L,48328L,48329L,48330L,48331L,48332L,48333L,48334L,
+48335L,48336L,48337L,48338L,48339L,48340L,48341L,48342L,48343L,48344L,
+48345L,48346L,48347L,48348L,48349L,48350L,48351L,48352L,48353L,48354L,
+48355L,48356L,48357L,48358L,48359L,48360L,48361L,48362L,48363L,48364L,
+48365L,48366L,48367L,48368L,48369L,48370L,48371L,48372L,48373L,48374L,
+48375L,48376L,48377L,48378L,48379L,48380L,48381L,48382L,48383L,48384L,
+48385L,48386L,48387L,48388L,48389L,48390L,48391L,48392L,48393L,48394L,
+48395L,48396L,48397L,48398L,48399L,48400L,48401L,48402L,48403L,48404L,
+48405L,48406L,48407L,48408L,48409L,48410L,48411L,48412L,48413L,48414L,
+48415L,48416L,48417L,48418L,48419L,48420L,48421L,48422L,48423L,48424L,
+48425L,48426L,48427L,48428L,48429L,48430L,48431L,48432L,48433L,48434L,
+48435L,48436L,48437L,48438L,48439L,48440L,48441L,48442L,48443L,48444L,
+48445L,48446L,48447L,48448L,48449L,48450L,48451L,48452L,48453L,48454L,
+48455L,48456L,48457L,48458L,48459L,48460L,48461L,48462L,48463L,48464L,
+48465L,48466L,48467L,48468L,48469L,48470L,48471L,48472L,48473L,48474L,
+48475L,48476L,48477L,48478L,48479L,48480L,48481L,48482L,48483L,48484L,
+48485L,48486L,48487L,48488L,48489L,48490L,48491L,48492L,48493L,48494L,
+48495L,48496L,48497L,48498L,48499L,48500L,48501L,48502L,48503L,48504L,
+48505L,48506L,48507L,48508L,48509L,48510L,48511L,48512L,48513L,48514L,
+48515L,48516L,48517L,48518L,48519L,48520L,48521L,48522L,48523L,48524L,
+48525L,48526L,48527L,48528L,48529L,48530L,48531L,48532L,48533L,48534L,
+48535L,48536L,48537L,48538L,48539L,48540L,48541L,48542L,48543L,48544L,
+48545L,48546L,48547L,48548L,48549L,48550L,48551L,48552L,48553L,48554L,
+48555L,48556L,48557L,48558L,48559L,48560L,48561L,48562L,48563L,48564L,
+48565L,48566L,48567L,48568L,48569L,48570L,48571L,48572L,48573L,48574L,
+48575L,48576L,48577L,48578L,48579L,48580L,48581L,48582L,48583L,48584L,
+48585L,48586L,48587L,48588L,48589L,48590L,48591L,48592L,48593L,48594L,
+48595L,48596L,48597L,48598L,48599L,48600L,48601L,48602L,48603L,48604L,
+48605L,48606L,48607L,48608L,48609L,48610L,48611L,48612L,48613L,48614L,
+48615L,48616L,48617L,48618L,48619L,48620L,48621L,48622L,48623L,48624L,
+48625L,48626L,48627L,48628L,48629L,48630L,48631L,48632L,48633L,48634L,
+48635L,48636L,48637L,48638L,48639L,48640L,48641L,48642L,48643L,48644L,
+48645L,48646L,48647L,48648L,48649L,48650L,48651L,48652L,48653L,48654L,
+48655L,48656L,48657L,48658L,48659L,48660L,48661L,48662L,48663L,48664L,
+48665L,48666L,48667L,48668L,48669L,48670L,48671L,48672L,48673L,48674L,
+48675L,48676L,48677L,48678L,48679L,48680L,48681L,48682L,48683L,48684L,
+48685L,48686L,48687L,48688L,48689L,48690L,48691L,48692L,48693L,48694L,
+48695L,48696L,48697L,48698L,48699L,48700L,48701L,48702L,48703L,48704L,
+48705L,48706L,48707L,48708L,48709L,48710L,48711L,48712L,48713L,48714L,
+48715L,48716L,48717L,48718L,48719L,48720L,48721L,48722L,48723L,48724L,
+48725L,48726L,48727L,48728L,48729L,48730L,48731L,48732L,48733L,48734L,
+48735L,48736L,48737L,48738L,48739L,48740L,48741L,48742L,48743L,48744L,
+48745L,48746L,48747L,48748L,48749L,48750L,48751L,48752L,48753L,48754L,
+48755L,48756L,48757L,48758L,48759L,48760L,48761L,48762L,48763L,48764L,
+48765L,48766L,48767L,48768L,48769L,48770L,48771L,48772L,48773L,48774L,
+48775L,48776L,48777L,48778L,48779L,48780L,48781L,48782L,48783L,48784L,
+48785L,48786L,48787L,48788L,48789L,48790L,48791L,48792L,48793L,48794L,
+48795L,48796L,48797L,48798L,48799L,48800L,48801L,48802L,48803L,48804L,
+48805L,48806L,48807L,48808L,48809L,48810L,48811L,48812L,48813L,48814L,
+48815L,48816L,48817L,48818L,48819L,48820L,48821L,48822L,48823L,48824L,
+48825L,48826L,48827L,48828L,48829L,48830L,48831L,48832L,48833L,48834L,
+48835L,48836L,48837L,48838L,48839L,48840L,48841L,48842L,48843L,48844L,
+48845L,48846L,48847L,48848L,48849L,48850L,48851L,48852L,48853L,48854L,
+48855L,48856L,48857L,48858L,48859L,48860L,48861L,48862L,48863L,48864L,
+48865L,48866L,48867L,48868L,48869L,48870L,48871L,48872L,48873L,48874L,
+48875L,48876L,48877L,48878L,48879L,48880L,48881L,48882L,48883L,48884L,
+48885L,48886L,48887L,48888L,48889L,48890L,48891L,48892L,48893L,48894L,
+48895L,48896L,48897L,48898L,48899L,48900L,48901L,48902L,48903L,48904L,
+48905L,48906L,48907L,48908L,48909L,48910L,48911L,48912L,48913L,48914L,
+48915L,48916L,48917L,48918L,48919L,48920L,48921L,48922L,48923L,48924L,
+48925L,48926L,48927L,48928L,48929L,48930L,48931L,48932L,48933L,48934L,
+48935L,48936L,48937L,48938L,48939L,48940L,48941L,48942L,48943L,48944L,
+48945L,48946L,48947L,48948L,48949L,48950L,48951L,48952L,48953L,48954L,
+48955L,48956L,48957L,48958L,48959L,48960L,48961L,48962L,48963L,48964L,
+48965L,48966L,48967L,48968L,48969L,48970L,48971L,48972L,48973L,48974L,
+48975L,48976L,48977L,48978L,48979L,48980L,48981L,48982L,48983L,48984L,
+48985L,48986L,48987L,48988L,48989L,48990L,48991L,48992L,48993L,48994L,
+48995L,48996L,48997L,48998L,48999L,49000L,49001L,49002L,49003L,49004L,
+49005L,49006L,49007L,49008L,49009L,49010L,49011L,49012L,49013L,49014L,
+49015L,49016L,49017L,49018L,49019L,49020L,49021L,49022L,49023L,49024L,
+49025L,49026L,49027L,49028L,49029L,49030L,49031L,49032L,49033L,49034L,
+49035L,49036L,49037L,49038L,49039L,49040L,49041L,49042L,49043L,49044L,
+49045L,49046L,49047L,49048L,49049L,49050L,49051L,49052L,49053L,49054L,
+49055L,49056L,49057L,49058L,49059L,49060L,49061L,49062L,49063L,49064L,
+49065L,49066L,49067L,49068L,49069L,49070L,49071L,49072L,49073L,49074L,
+49075L,49076L,49077L,49078L,49079L,49080L,49081L,49082L,49083L,49084L,
+49085L,49086L,49087L,49088L,49089L,49090L,49091L,49092L,49093L,49094L,
+49095L,49096L,49097L,49098L,49099L,49100L,49101L,49102L,49103L,49104L,
+49105L,49106L,49107L,49108L,49109L,49110L,49111L,49112L,49113L,49114L,
+49115L,49116L,49117L,49118L,49119L,49120L,49121L,49122L,49123L,49124L,
+49125L,49126L,49127L,49128L,49129L,49130L,49131L,49132L,49133L,49134L,
+49135L,49136L,49137L,49138L,49139L,49140L,49141L,49142L,49143L,49144L,
+49145L,49146L,49147L,49148L,49149L,49150L,49151L,49152L,49153L,49154L,
+49155L,49156L,49157L,49158L,49159L,49160L,49161L,49162L,49163L,49164L,
+49165L,49166L,49167L,49168L,49169L,49170L,49171L,49172L,49173L,49174L,
+49175L,49176L,49177L,49178L,49179L,49180L,49181L,49182L,49183L,49184L,
+49185L,49186L,49187L,49188L,49189L,49190L,49191L,49192L,49193L,49194L,
+49195L,49196L,49197L,49198L,49199L,49200L,49201L,49202L,49203L,49204L,
+49205L,49206L,49207L,49208L,49209L,49210L,49211L,49212L,49213L,49214L,
+49215L,49216L,49217L,49218L,49219L,49220L,49221L,49222L,49223L,49224L,
+49225L,49226L,49227L,49228L,49229L,49230L,49231L,49232L,49233L,49234L,
+49235L,49236L,49237L,49238L,49239L,49240L,49241L,49242L,49243L,49244L,
+49245L,49246L,49247L,49248L,49249L,49250L,49251L,49252L,49253L,49254L,
+49255L,49256L,49257L,49258L,49259L,49260L,49261L,49262L,49263L,49264L,
+49265L,49266L,49267L,49268L,49269L,49270L,49271L,49272L,49273L,49274L,
+49275L,49276L,49277L,49278L,49279L,49280L,49281L,49282L,49283L,49284L,
+49285L,49286L,49287L,49288L,49289L,49290L,49291L,49292L,49293L,49294L,
+49295L,49296L,49297L,49298L,49299L,49300L,49301L,49302L,49303L,49304L,
+49305L,49306L,49307L,49308L,49309L,49310L,49311L,49312L,49313L,49314L,
+49315L,49316L,49317L,49318L,49319L,49320L,49321L,49322L,49323L,49324L,
+49325L,49326L,49327L,49328L,49329L,49330L,49331L,49332L,49333L,49334L,
+49335L,49336L,49337L,49338L,49339L,49340L,49341L,49342L,49343L,49344L,
+49345L,49346L,49347L,49348L,49349L,49350L,49351L,49352L,49353L,49354L,
+49355L,49356L,49357L,49358L,49359L,49360L,49361L,49362L,49363L,49364L,
+49365L,49366L,49367L,49368L,49369L,49370L,49371L,49372L,49373L,49374L,
+49375L,49376L,49377L,49378L,49379L,49380L,49381L,49382L,49383L,49384L,
+49385L,49386L,49387L,49388L,49389L,49390L,49391L,49392L,49393L,49394L,
+49395L,49396L,49397L,49398L,49399L,49400L,49401L,49402L,49403L,49404L,
+49405L,49406L,49407L,49408L,49409L,49410L,49411L,49412L,49413L,49414L,
+49415L,49416L,49417L,49418L,49419L,49420L,49421L,49422L,49423L,49424L,
+49425L,49426L,49427L,49428L,49429L,49430L,49431L,49432L,49433L,49434L,
+49435L,49436L,49437L,49438L,49439L,49440L,49441L,49442L,49443L,49444L,
+49445L,49446L,49447L,49448L,49449L,49450L,49451L,49452L,49453L,49454L,
+49455L,49456L,49457L,49458L,49459L,49460L,49461L,49462L,49463L,49464L,
+49465L,49466L,49467L,49468L,49469L,49470L,49471L,49472L,49473L,49474L,
+49475L,49476L,49477L,49478L,49479L,49480L,49481L,49482L,49483L,49484L,
+49485L,49486L,49487L,49488L,49489L,49490L,49491L,49492L,49493L,49494L,
+49495L,49496L,49497L,49498L,49499L,49500L,49501L,49502L,49503L,49504L,
+49505L,49506L,49507L,49508L,49509L,49510L,49511L,49512L,49513L,49514L,
+49515L,49516L,49517L,49518L,49519L,49520L,49521L,49522L,49523L,49524L,
+49525L,49526L,49527L,49528L,49529L,49530L,49531L,49532L,49533L,49534L,
+49535L,49536L,49537L,49538L,49539L,49540L,49541L,49542L,49543L,49544L,
+49545L,49546L,49547L,49548L,49549L,49550L,49551L,49552L,49553L,49554L,
+49555L,49556L,49557L,49558L,49559L,49560L,49561L,49562L,49563L,49564L,
+49565L,49566L,49567L,49568L,49569L,49570L,49571L,49572L,49573L,49574L,
+49575L,49576L,49577L,49578L,49579L,49580L,49581L,49582L,49583L,49584L,
+49585L,49586L,49587L,49588L,49589L,49590L,49591L,49592L,49593L,49594L,
+49595L,49596L,49597L,49598L,49599L,49600L,49601L,49602L,49603L,49604L,
+49605L,49606L,49607L,49608L,49609L,49610L,49611L,49612L,49613L,49614L,
+49615L,49616L,49617L,49618L,49619L,49620L,49621L,49622L,49623L,49624L,
+49625L,49626L,49627L,49628L,49629L,49630L,49631L,49632L,49633L,49634L,
+49635L,49636L,49637L,49638L,49639L,49640L,49641L,49642L,49643L,49644L,
+49645L,49646L,49647L,49648L,49649L,49650L,49651L,49652L,49653L,49654L,
+49655L,49656L,49657L,49658L,49659L,49660L,49661L,49662L,49663L,49664L,
+49665L,49666L,49667L,49668L,49669L,49670L,49671L,49672L,49673L,49674L,
+49675L,49676L,49677L,49678L,49679L,49680L,49681L,49682L,49683L,49684L,
+49685L,49686L,49687L,49688L,49689L,49690L,49691L,49692L,49693L,49694L,
+49695L,49696L,49697L,49698L,49699L,49700L,49701L,49702L,49703L,49704L,
+49705L,49706L,49707L,49708L,49709L,49710L,49711L,49712L,49713L,49714L,
+49715L,49716L,49717L,49718L,49719L,49720L,49721L,49722L,49723L,49724L,
+49725L,49726L,49727L,49728L,49729L,49730L,49731L,49732L,49733L,49734L,
+49735L,49736L,49737L,49738L,49739L,49740L,49741L,49742L,49743L,49744L,
+49745L,49746L,49747L,49748L,49749L,49750L,49751L,49752L,49753L,49754L,
+49755L,49756L,49757L,49758L,49759L,49760L,49761L,49762L,49763L,49764L,
+49765L,49766L,49767L,49768L,49769L,49770L,49771L,49772L,49773L,49774L,
+49775L,49776L,49777L,49778L,49779L,49780L,49781L,49782L,49783L,49784L,
+49785L,49786L,49787L,49788L,49789L,49790L,49791L,49792L,49793L,49794L,
+49795L,49796L,49797L,49798L,49799L,49800L,49801L,49802L,49803L,49804L,
+49805L,49806L,49807L,49808L,49809L,49810L,49811L,49812L,49813L,49814L,
+49815L,49816L,49817L,49818L,49819L,49820L,49821L,49822L,49823L,49824L,
+49825L,49826L,49827L,49828L,49829L,49830L,49831L,49832L,49833L,49834L,
+49835L,49836L,49837L,49838L,49839L,49840L,49841L,49842L,49843L,49844L,
+49845L,49846L,49847L,49848L,49849L,49850L,49851L,49852L,49853L,49854L,
+49855L,49856L,49857L,49858L,49859L,49860L,49861L,49862L,49863L,49864L,
+49865L,49866L,49867L,49868L,49869L,49870L,49871L,49872L,49873L,49874L,
+49875L,49876L,49877L,49878L,49879L,49880L,49881L,49882L,49883L,49884L,
+49885L,49886L,49887L,49888L,49889L,49890L,49891L,49892L,49893L,49894L,
+49895L,49896L,49897L,49898L,49899L,49900L,49901L,49902L,49903L,49904L,
+49905L,49906L,49907L,49908L,49909L,49910L,49911L,49912L,49913L,49914L,
+49915L,49916L,49917L,49918L,49919L,49920L,49921L,49922L,49923L,49924L,
+49925L,49926L,49927L,49928L,49929L,49930L,49931L,49932L,49933L,49934L,
+49935L,49936L,49937L,49938L,49939L,49940L,49941L,49942L,49943L,49944L,
+49945L,49946L,49947L,49948L,49949L,49950L,49951L,49952L,49953L,49954L,
+49955L,49956L,49957L,49958L,49959L,49960L,49961L,49962L,49963L,49964L,
+49965L,49966L,49967L,49968L,49969L,49970L,49971L,49972L,49973L,49974L,
+49975L,49976L,49977L,49978L,49979L,49980L,49981L,49982L,49983L,49984L,
+49985L,49986L,49987L,49988L,49989L,49990L,49991L,49992L,49993L,49994L,
+49995L,49996L,49997L,49998L,49999L,50000L,50001L,50002L,50003L,50004L,
+50005L,50006L,50007L,50008L,50009L,50010L,50011L,50012L,50013L,50014L,
+50015L,50016L,50017L,50018L,50019L,50020L,50021L,50022L,50023L,50024L,
+50025L,50026L,50027L,50028L,50029L,50030L,50031L,50032L,50033L,50034L,
+50035L,50036L,50037L,50038L,50039L,50040L,50041L,50042L,50043L,50044L,
+50045L,50046L,50047L,50048L,50049L,50050L,50051L,50052L,50053L,50054L,
+50055L,50056L,50057L,50058L,50059L,50060L,50061L,50062L,50063L,50064L,
+50065L,50066L,50067L,50068L,50069L,50070L,50071L,50072L,50073L,50074L,
+50075L,50076L,50077L,50078L,50079L,50080L,50081L,50082L,50083L,50084L,
+50085L,50086L,50087L,50088L,50089L,50090L,50091L,50092L,50093L,50094L,
+50095L,50096L,50097L,50098L,50099L,50100L,50101L,50102L,50103L,50104L,
+50105L,50106L,50107L,50108L,50109L,50110L,50111L,50112L,50113L,50114L,
+50115L,50116L,50117L,50118L,50119L,50120L,50121L,50122L,50123L,50124L,
+50125L,50126L,50127L,50128L,50129L,50130L,50131L,50132L,50133L,50134L,
+50135L,50136L,50137L,50138L,50139L,50140L,50141L,50142L,50143L,50144L,
+50145L,50146L,50147L,50148L,50149L,50150L,50151L,50152L,50153L,50154L,
+50155L,50156L,50157L,50158L,50159L,50160L,50161L,50162L,50163L,50164L,
+50165L,50166L,50167L,50168L,50169L,50170L,50171L,50172L,50173L,50174L,
+50175L,50176L,50177L,50178L,50179L,50180L,50181L,50182L,50183L,50184L,
+50185L,50186L,50187L,50188L,50189L,50190L,50191L,50192L,50193L,50194L,
+50195L,50196L,50197L,50198L,50199L,50200L,50201L,50202L,50203L,50204L,
+50205L,50206L,50207L,50208L,50209L,50210L,50211L,50212L,50213L,50214L,
+50215L,50216L,50217L,50218L,50219L,50220L,50221L,50222L,50223L,50224L,
+50225L,50226L,50227L,50228L,50229L,50230L,50231L,50232L,50233L,50234L,
+50235L,50236L,50237L,50238L,50239L,50240L,50241L,50242L,50243L,50244L,
+50245L,50246L,50247L,50248L,50249L,50250L,50251L,50252L,50253L,50254L,
+50255L,50256L,50257L,50258L,50259L,50260L,50261L,50262L,50263L,50264L,
+50265L,50266L,50267L,50268L,50269L,50270L,50271L,50272L,50273L,50274L,
+50275L,50276L,50277L,50278L,50279L,50280L,50281L,50282L,50283L,50284L,
+50285L,50286L,50287L,50288L,50289L,50290L,50291L,50292L,50293L,50294L,
+50295L,50296L,50297L,50298L,50299L,50300L,50301L,50302L,50303L,50304L,
+50305L,50306L,50307L,50308L,50309L,50310L,50311L,50312L,50313L,50314L,
+50315L,50316L,50317L,50318L,50319L,50320L,50321L,50322L,50323L,50324L,
+50325L,50326L,50327L,50328L,50329L,50330L,50331L,50332L,50333L,50334L,
+50335L,50336L,50337L,50338L,50339L,50340L,50341L,50342L,50343L,50344L,
+50345L,50346L,50347L,50348L,50349L,50350L,50351L,50352L,50353L,50354L,
+50355L,50356L,50357L,50358L,50359L,50360L,50361L,50362L,50363L,50364L,
+50365L,50366L,50367L,50368L,50369L,50370L,50371L,50372L,50373L,50374L,
+50375L,50376L,50377L,50378L,50379L,50380L,50381L,50382L,50383L,50384L,
+50385L,50386L,50387L,50388L,50389L,50390L,50391L,50392L,50393L,50394L,
+50395L,50396L,50397L,50398L,50399L,50400L,50401L,50402L,50403L,50404L,
+50405L,50406L,50407L,50408L,50409L,50410L,50411L,50412L,50413L,50414L,
+50415L,50416L,50417L,50418L,50419L,50420L,50421L,50422L,50423L,50424L,
+50425L,50426L,50427L,50428L,50429L,50430L,50431L,50432L,50433L,50434L,
+50435L,50436L,50437L,50438L,50439L,50440L,50441L,50442L,50443L,50444L,
+50445L,50446L,50447L,50448L,50449L,50450L,50451L,50452L,50453L,50454L,
+50455L,50456L,50457L,50458L,50459L,50460L,50461L,50462L,50463L,50464L,
+50465L,50466L,50467L,50468L,50469L,50470L,50471L,50472L,50473L,50474L,
+50475L,50476L,50477L,50478L,50479L,50480L,50481L,50482L,50483L,50484L,
+50485L,50486L,50487L,50488L,50489L,50490L,50491L,50492L,50493L,50494L,
+50495L,50496L,50497L,50498L,50499L,50500L,50501L,50502L,50503L,50504L,
+50505L,50506L,50507L,50508L,50509L,50510L,50511L,50512L,50513L,50514L,
+50515L,50516L,50517L,50518L,50519L,50520L,50521L,50522L,50523L,50524L,
+50525L,50526L,50527L,50528L,50529L,50530L,50531L,50532L,50533L,50534L,
+50535L,50536L,50537L,50538L,50539L,50540L,50541L,50542L,50543L,50544L,
+50545L,50546L,50547L,50548L,50549L,50550L,50551L,50552L,50553L,50554L,
+50555L,50556L,50557L,50558L,50559L,50560L,50561L,50562L,50563L,50564L,
+50565L,50566L,50567L,50568L,50569L,50570L,50571L,50572L,50573L,50574L,
+50575L,50576L,50577L,50578L,50579L,50580L,50581L,50582L,50583L,50584L,
+50585L,50586L,50587L,50588L,50589L,50590L,50591L,50592L,50593L,50594L,
+50595L,50596L,50597L,50598L,50599L,50600L,50601L,50602L,50603L,50604L,
+50605L,50606L,50607L,50608L,50609L,50610L,50611L,50612L,50613L,50614L,
+50615L,50616L,50617L,50618L,50619L,50620L,50621L,50622L,50623L,50624L,
+50625L,50626L,50627L,50628L,50629L,50630L,50631L,50632L,50633L,50634L,
+50635L,50636L,50637L,50638L,50639L,50640L,50641L,50642L,50643L,50644L,
+50645L,50646L,50647L,50648L,50649L,50650L,50651L,50652L,50653L,50654L,
+50655L,50656L,50657L,50658L,50659L,50660L,50661L,50662L,50663L,50664L,
+50665L,50666L,50667L,50668L,50669L,50670L,50671L,50672L,50673L,50674L,
+50675L,50676L,50677L,50678L,50679L,50680L,50681L,50682L,50683L,50684L,
+50685L,50686L,50687L,50688L,50689L,50690L,50691L,50692L,50693L,50694L,
+50695L,50696L,50697L,50698L,50699L,50700L,50701L,50702L,50703L,50704L,
+50705L,50706L,50707L,50708L,50709L,50710L,50711L,50712L,50713L,50714L,
+50715L,50716L,50717L,50718L,50719L,50720L,50721L,50722L,50723L,50724L,
+50725L,50726L,50727L,50728L,50729L,50730L,50731L,50732L,50733L,50734L,
+50735L,50736L,50737L,50738L,50739L,50740L,50741L,50742L,50743L,50744L,
+50745L,50746L,50747L,50748L,50749L,50750L,50751L,50752L,50753L,50754L,
+50755L,50756L,50757L,50758L,50759L,50760L,50761L,50762L,50763L,50764L,
+50765L,50766L,50767L,50768L,50769L,50770L,50771L,50772L,50773L,50774L,
+50775L,50776L,50777L,50778L,50779L,50780L,50781L,50782L,50783L,50784L,
+50785L,50786L,50787L,50788L,50789L,50790L,50791L,50792L,50793L,50794L,
+50795L,50796L,50797L,50798L,50799L,50800L,50801L,50802L,50803L,50804L,
+50805L,50806L,50807L,50808L,50809L,50810L,50811L,50812L,50813L,50814L,
+50815L,50816L,50817L,50818L,50819L,50820L,50821L,50822L,50823L,50824L,
+50825L,50826L,50827L,50828L,50829L,50830L,50831L,50832L,50833L,50834L,
+50835L,50836L,50837L,50838L,50839L,50840L,50841L,50842L,50843L,50844L,
+50845L,50846L,50847L,50848L,50849L,50850L,50851L,50852L,50853L,50854L,
+50855L,50856L,50857L,50858L,50859L,50860L,50861L,50862L,50863L,50864L,
+50865L,50866L,50867L,50868L,50869L,50870L,50871L,50872L,50873L,50874L,
+50875L,50876L,50877L,50878L,50879L,50880L,50881L,50882L,50883L,50884L,
+50885L,50886L,50887L,50888L,50889L,50890L,50891L,50892L,50893L,50894L,
+50895L,50896L,50897L,50898L,50899L,50900L,50901L,50902L,50903L,50904L,
+50905L,50906L,50907L,50908L,50909L,50910L,50911L,50912L,50913L,50914L,
+50915L,50916L,50917L,50918L,50919L,50920L,50921L,50922L,50923L,50924L,
+50925L,50926L,50927L,50928L,50929L,50930L,50931L,50932L,50933L,50934L,
+50935L,50936L,50937L,50938L,50939L,50940L,50941L,50942L,50943L,50944L,
+50945L,50946L,50947L,50948L,50949L,50950L,50951L,50952L,50953L,50954L,
+50955L,50956L,50957L,50958L,50959L,50960L,50961L,50962L,50963L,50964L,
+50965L,50966L,50967L,50968L,50969L,50970L,50971L,50972L,50973L,50974L,
+50975L,50976L,50977L,50978L,50979L,50980L,50981L,50982L,50983L,50984L,
+50985L,50986L,50987L,50988L,50989L,50990L,50991L,50992L,50993L,50994L,
+50995L,50996L,50997L,50998L,50999L,51000L,51001L,51002L,51003L,51004L,
+51005L,51006L,51007L,51008L,51009L,51010L,51011L,51012L,51013L,51014L,
+51015L,51016L,51017L,51018L,51019L,51020L,51021L,51022L,51023L,51024L,
+51025L,51026L,51027L,51028L,51029L,51030L,51031L,51032L,51033L,51034L,
+51035L,51036L,51037L,51038L,51039L,51040L,51041L,51042L,51043L,51044L,
+51045L,51046L,51047L,51048L,51049L,51050L,51051L,51052L,51053L,51054L,
+51055L,51056L,51057L,51058L,51059L,51060L,51061L,51062L,51063L,51064L,
+51065L,51066L,51067L,51068L,51069L,51070L,51071L,51072L,51073L,51074L,
+51075L,51076L,51077L,51078L,51079L,51080L,51081L,51082L,51083L,51084L,
+51085L,51086L,51087L,51088L,51089L,51090L,51091L,51092L,51093L,51094L,
+51095L,51096L,51097L,51098L,51099L,51100L,51101L,51102L,51103L,51104L,
+51105L,51106L,51107L,51108L,51109L,51110L,51111L,51112L,51113L,51114L,
+51115L,51116L,51117L,51118L,51119L,51120L,51121L,51122L,51123L,51124L,
+51125L,51126L,51127L,51128L,51129L,51130L,51131L,51132L,51133L,51134L,
+51135L,51136L,51137L,51138L,51139L,51140L,51141L,51142L,51143L,51144L,
+51145L,51146L,51147L,51148L,51149L,51150L,51151L,51152L,51153L,51154L,
+51155L,51156L,51157L,51158L,51159L,51160L,51161L,51162L,51163L,51164L,
+51165L,51166L,51167L,51168L,51169L,51170L,51171L,51172L,51173L,51174L,
+51175L,51176L,51177L,51178L,51179L,51180L,51181L,51182L,51183L,51184L,
+51185L,51186L,51187L,51188L,51189L,51190L,51191L,51192L,51193L,51194L,
+51195L,51196L,51197L,51198L,51199L,51200L,51201L,51202L,51203L,51204L,
+51205L,51206L,51207L,51208L,51209L,51210L,51211L,51212L,51213L,51214L,
+51215L,51216L,51217L,51218L,51219L,51220L,51221L,51222L,51223L,51224L,
+51225L,51226L,51227L,51228L,51229L,51230L,51231L,51232L,51233L,51234L,
+51235L,51236L,51237L,51238L,51239L,51240L,51241L,51242L,51243L,51244L,
+51245L,51246L,51247L,51248L,51249L,51250L,51251L,51252L,51253L,51254L,
+51255L,51256L,51257L,51258L,51259L,51260L,51261L,51262L,51263L,51264L,
+51265L,51266L,51267L,51268L,51269L,51270L,51271L,51272L,51273L,51274L,
+51275L,51276L,51277L,51278L,51279L,51280L,51281L,51282L,51283L,51284L,
+51285L,51286L,51287L,51288L,51289L,51290L,51291L,51292L,51293L,51294L,
+51295L,51296L,51297L,51298L,51299L,51300L,51301L,51302L,51303L,51304L,
+51305L,51306L,51307L,51308L,51309L,51310L,51311L,51312L,51313L,51314L,
+51315L,51316L,51317L,51318L,51319L,51320L,51321L,51322L,51323L,51324L,
+51325L,51326L,51327L,51328L,51329L,51330L,51331L,51332L,51333L,51334L,
+51335L,51336L,51337L,51338L,51339L,51340L,51341L,51342L,51343L,51344L,
+51345L,51346L,51347L,51348L,51349L,51350L,51351L,51352L,51353L,51354L,
+51355L,51356L,51357L,51358L,51359L,51360L,51361L,51362L,51363L,51364L,
+51365L,51366L,51367L,51368L,51369L,51370L,51371L,51372L,51373L,51374L,
+51375L,51376L,51377L,51378L,51379L,51380L,51381L,51382L,51383L,51384L,
+51385L,51386L,51387L,51388L,51389L,51390L,51391L,51392L,51393L,51394L,
+51395L,51396L,51397L,51398L,51399L,51400L,51401L,51402L,51403L,51404L,
+51405L,51406L,51407L,51408L,51409L,51410L,51411L,51412L,51413L,51414L,
+51415L,51416L,51417L,51418L,51419L,51420L,51421L,51422L,51423L,51424L,
+51425L,51426L,51427L,51428L,51429L,51430L,51431L,51432L,51433L,51434L,
+51435L,51436L,51437L,51438L,51439L,51440L,51441L,51442L,51443L,51444L,
+51445L,51446L,51447L,51448L,51449L,51450L,51451L,51452L,51453L,51454L,
+51455L,51456L,51457L,51458L,51459L,51460L,51461L,51462L,51463L,51464L,
+51465L,51466L,51467L,51468L,51469L,51470L,51471L,51472L,51473L,51474L,
+51475L,51476L,51477L,51478L,51479L,51480L,51481L,51482L,51483L,51484L,
+51485L,51486L,51487L,51488L,51489L,51490L,51491L,51492L,51493L,51494L,
+51495L,51496L,51497L,51498L,51499L,51500L,51501L,51502L,51503L,51504L,
+51505L,51506L,51507L,51508L,51509L,51510L,51511L,51512L,51513L,51514L,
+51515L,51516L,51517L,51518L,51519L,51520L,51521L,51522L,51523L,51524L,
+51525L,51526L,51527L,51528L,51529L,51530L,51531L,51532L,51533L,51534L,
+51535L,51536L,51537L,51538L,51539L,51540L,51541L,51542L,51543L,51544L,
+51545L,51546L,51547L,51548L,51549L,51550L,51551L,51552L,51553L,51554L,
+51555L,51556L,51557L,51558L,51559L,51560L,51561L,51562L,51563L,51564L,
+51565L,51566L,51567L,51568L,51569L,51570L,51571L,51572L,51573L,51574L,
+51575L,51576L,51577L,51578L,51579L,51580L,51581L,51582L,51583L,51584L,
+51585L,51586L,51587L,51588L,51589L,51590L,51591L,51592L,51593L,51594L,
+51595L,51596L,51597L,51598L,51599L,51600L,51601L,51602L,51603L,51604L,
+51605L,51606L,51607L,51608L,51609L,51610L,51611L,51612L,51613L,51614L,
+51615L,51616L,51617L,51618L,51619L,51620L,51621L,51622L,51623L,51624L,
+51625L,51626L,51627L,51628L,51629L,51630L,51631L,51632L,51633L,51634L,
+51635L,51636L,51637L,51638L,51639L,51640L,51641L,51642L,51643L,51644L,
+51645L,51646L,51647L,51648L,51649L,51650L,51651L,51652L,51653L,51654L,
+51655L,51656L,51657L,51658L,51659L,51660L,51661L,51662L,51663L,51664L,
+51665L,51666L,51667L,51668L,51669L,51670L,51671L,51672L,51673L,51674L,
+51675L,51676L,51677L,51678L,51679L,51680L,51681L,51682L,51683L,51684L,
+51685L,51686L,51687L,51688L,51689L,51690L,51691L,51692L,51693L,51694L,
+51695L,51696L,51697L,51698L,51699L,51700L,51701L,51702L,51703L,51704L,
+51705L,51706L,51707L,51708L,51709L,51710L,51711L,51712L,51713L,51714L,
+51715L,51716L,51717L,51718L,51719L,51720L,51721L,51722L,51723L,51724L,
+51725L,51726L,51727L,51728L,51729L,51730L,51731L,51732L,51733L,51734L,
+51735L,51736L,51737L,51738L,51739L,51740L,51741L,51742L,51743L,51744L,
+51745L,51746L,51747L,51748L,51749L,51750L,51751L,51752L,51753L,51754L,
+51755L,51756L,51757L,51758L,51759L,51760L,51761L,51762L,51763L,51764L,
+51765L,51766L,51767L,51768L,51769L,51770L,51771L,51772L,51773L,51774L,
+51775L,51776L,51777L,51778L,51779L,51780L,51781L,51782L,51783L,51784L,
+51785L,51786L,51787L,51788L,51789L,51790L,51791L,51792L,51793L,51794L,
+51795L,51796L,51797L,51798L,51799L,51800L,51801L,51802L,51803L,51804L,
+51805L,51806L,51807L,51808L,51809L,51810L,51811L,51812L,51813L,51814L,
+51815L,51816L,51817L,51818L,51819L,51820L,51821L,51822L,51823L,51824L,
+51825L,51826L,51827L,51828L,51829L,51830L,51831L,51832L,51833L,51834L,
+51835L,51836L,51837L,51838L,51839L,51840L,51841L,51842L,51843L,51844L,
+51845L,51846L,51847L,51848L,51849L,51850L,51851L,51852L,51853L,51854L,
+51855L,51856L,51857L,51858L,51859L,51860L,51861L,51862L,51863L,51864L,
+51865L,51866L,51867L,51868L,51869L,51870L,51871L,51872L,51873L,51874L,
+51875L,51876L,51877L,51878L,51879L,51880L,51881L,51882L,51883L,51884L,
+51885L,51886L,51887L,51888L,51889L,51890L,51891L,51892L,51893L,51894L,
+51895L,51896L,51897L,51898L,51899L,51900L,51901L,51902L,51903L,51904L,
+51905L,51906L,51907L,51908L,51909L,51910L,51911L,51912L,51913L,51914L,
+51915L,51916L,51917L,51918L,51919L,51920L,51921L,51922L,51923L,51924L,
+51925L,51926L,51927L,51928L,51929L,51930L,51931L,51932L,51933L,51934L,
+51935L,51936L,51937L,51938L,51939L,51940L,51941L,51942L,51943L,51944L,
+51945L,51946L,51947L,51948L,51949L,51950L,51951L,51952L,51953L,51954L,
+51955L,51956L,51957L,51958L,51959L,51960L,51961L,51962L,51963L,51964L,
+51965L,51966L,51967L,51968L,51969L,51970L,51971L,51972L,51973L,51974L,
+51975L,51976L,51977L,51978L,51979L,51980L,51981L,51982L,51983L,51984L,
+51985L,51986L,51987L,51988L,51989L,51990L,51991L,51992L,51993L,51994L,
+51995L,51996L,51997L,51998L,51999L,52000L,52001L,52002L,52003L,52004L,
+52005L,52006L,52007L,52008L,52009L,52010L,52011L,52012L,52013L,52014L,
+52015L,52016L,52017L,52018L,52019L,52020L,52021L,52022L,52023L,52024L,
+52025L,52026L,52027L,52028L,52029L,52030L,52031L,52032L,52033L,52034L,
+52035L,52036L,52037L,52038L,52039L,52040L,52041L,52042L,52043L,52044L,
+52045L,52046L,52047L,52048L,52049L,52050L,52051L,52052L,52053L,52054L,
+52055L,52056L,52057L,52058L,52059L,52060L,52061L,52062L,52063L,52064L,
+52065L,52066L,52067L,52068L,52069L,52070L,52071L,52072L,52073L,52074L,
+52075L,52076L,52077L,52078L,52079L,52080L,52081L,52082L,52083L,52084L,
+52085L,52086L,52087L,52088L,52089L,52090L,52091L,52092L,52093L,52094L,
+52095L,52096L,52097L,52098L,52099L,52100L,52101L,52102L,52103L,52104L,
+52105L,52106L,52107L,52108L,52109L,52110L,52111L,52112L,52113L,52114L,
+52115L,52116L,52117L,52118L,52119L,52120L,52121L,52122L,52123L,52124L,
+52125L,52126L,52127L,52128L,52129L,52130L,52131L,52132L,52133L,52134L,
+52135L,52136L,52137L,52138L,52139L,52140L,52141L,52142L,52143L,52144L,
+52145L,52146L,52147L,52148L,52149L,52150L,52151L,52152L,52153L,52154L,
+52155L,52156L,52157L,52158L,52159L,52160L,52161L,52162L,52163L,52164L,
+52165L,52166L,52167L,52168L,52169L,52170L,52171L,52172L,52173L,52174L,
+52175L,52176L,52177L,52178L,52179L,52180L,52181L,52182L,52183L,52184L,
+52185L,52186L,52187L,52188L,52189L,52190L,52191L,52192L,52193L,52194L,
+52195L,52196L,52197L,52198L,52199L,52200L,52201L,52202L,52203L,52204L,
+52205L,52206L,52207L,52208L,52209L,52210L,52211L,52212L,52213L,52214L,
+52215L,52216L,52217L,52218L,52219L,52220L,52221L,52222L,52223L,52224L,
+52225L,52226L,52227L,52228L,52229L,52230L,52231L,52232L,52233L,52234L,
+52235L,52236L,52237L,52238L,52239L,52240L,52241L,52242L,52243L,52244L,
+52245L,52246L,52247L,52248L,52249L,52250L,52251L,52252L,52253L,52254L,
+52255L,52256L,52257L,52258L,52259L,52260L,52261L,52262L,52263L,52264L,
+52265L,52266L,52267L,52268L,52269L,52270L,52271L,52272L,52273L,52274L,
+52275L,52276L,52277L,52278L,52279L,52280L,52281L,52282L,52283L,52284L,
+52285L,52286L,52287L,52288L,52289L,52290L,52291L,52292L,52293L,52294L,
+52295L,52296L,52297L,52298L,52299L,52300L,52301L,52302L,52303L,52304L,
+52305L,52306L,52307L,52308L,52309L,52310L,52311L,52312L,52313L,52314L,
+52315L,52316L,52317L,52318L,52319L,52320L,52321L,52322L,52323L,52324L,
+52325L,52326L,52327L,52328L,52329L,52330L,52331L,52332L,52333L,52334L,
+52335L,52336L,52337L,52338L,52339L,52340L,52341L,52342L,52343L,52344L,
+52345L,52346L,52347L,52348L,52349L,52350L,52351L,52352L,52353L,52354L,
+52355L,52356L,52357L,52358L,52359L,52360L,52361L,52362L,52363L,52364L,
+52365L,52366L,52367L,52368L,52369L,52370L,52371L,52372L,52373L,52374L,
+52375L,52376L,52377L,52378L,52379L,52380L,52381L,52382L,52383L,52384L,
+52385L,52386L,52387L,52388L,52389L,52390L,52391L,52392L,52393L,52394L,
+52395L,52396L,52397L,52398L,52399L,52400L,52401L,52402L,52403L,52404L,
+52405L,52406L,52407L,52408L,52409L,52410L,52411L,52412L,52413L,52414L,
+52415L,52416L,52417L,52418L,52419L,52420L,52421L,52422L,52423L,52424L,
+52425L,52426L,52427L,52428L,52429L,52430L,52431L,52432L,52433L,52434L,
+52435L,52436L,52437L,52438L,52439L,52440L,52441L,52442L,52443L,52444L,
+52445L,52446L,52447L,52448L,52449L,52450L,52451L,52452L,52453L,52454L,
+52455L,52456L,52457L,52458L,52459L,52460L,52461L,52462L,52463L,52464L,
+52465L,52466L,52467L,52468L,52469L,52470L,52471L,52472L,52473L,52474L,
+52475L,52476L,52477L,52478L,52479L,52480L,52481L,52482L,52483L,52484L,
+52485L,52486L,52487L,52488L,52489L,52490L,52491L,52492L,52493L,52494L,
+52495L,52496L,52497L,52498L,52499L,52500L,52501L,52502L,52503L,52504L,
+52505L,52506L,52507L,52508L,52509L,52510L,52511L,52512L,52513L,52514L,
+52515L,52516L,52517L,52518L,52519L,52520L,52521L,52522L,52523L,52524L,
+52525L,52526L,52527L,52528L,52529L,52530L,52531L,52532L,52533L,52534L,
+52535L,52536L,52537L,52538L,52539L,52540L,52541L,52542L,52543L,52544L,
+52545L,52546L,52547L,52548L,52549L,52550L,52551L,52552L,52553L,52554L,
+52555L,52556L,52557L,52558L,52559L,52560L,52561L,52562L,52563L,52564L,
+52565L,52566L,52567L,52568L,52569L,52570L,52571L,52572L,52573L,52574L,
+52575L,52576L,52577L,52578L,52579L,52580L,52581L,52582L,52583L,52584L,
+52585L,52586L,52587L,52588L,52589L,52590L,52591L,52592L,52593L,52594L,
+52595L,52596L,52597L,52598L,52599L,52600L,52601L,52602L,52603L,52604L,
+52605L,52606L,52607L,52608L,52609L,52610L,52611L,52612L,52613L,52614L,
+52615L,52616L,52617L,52618L,52619L,52620L,52621L,52622L,52623L,52624L,
+52625L,52626L,52627L,52628L,52629L,52630L,52631L,52632L,52633L,52634L,
+52635L,52636L,52637L,52638L,52639L,52640L,52641L,52642L,52643L,52644L,
+52645L,52646L,52647L,52648L,52649L,52650L,52651L,52652L,52653L,52654L,
+52655L,52656L,52657L,52658L,52659L,52660L,52661L,52662L,52663L,52664L,
+52665L,52666L,52667L,52668L,52669L,52670L,52671L,52672L,52673L,52674L,
+52675L,52676L,52677L,52678L,52679L,52680L,52681L,52682L,52683L,52684L,
+52685L,52686L,52687L,52688L,52689L,52690L,52691L,52692L,52693L,52694L,
+52695L,52696L,52697L,52698L,52699L,52700L,52701L,52702L,52703L,52704L,
+52705L,52706L,52707L,52708L,52709L,52710L,52711L,52712L,52713L,52714L,
+52715L,52716L,52717L,52718L,52719L,52720L,52721L,52722L,52723L,52724L,
+52725L,52726L,52727L,52728L,52729L,52730L,52731L,52732L,52733L,52734L,
+52735L,52736L,52737L,52738L,52739L,52740L,52741L,52742L,52743L,52744L,
+52745L,52746L,52747L,52748L,52749L,52750L,52751L,52752L,52753L,52754L,
+52755L,52756L,52757L,52758L,52759L,52760L,52761L,52762L,52763L,52764L,
+52765L,52766L,52767L,52768L,52769L,52770L,52771L,52772L,52773L,52774L,
+52775L,52776L,52777L,52778L,52779L,52780L,52781L,52782L,52783L,52784L,
+52785L,52786L,52787L,52788L,52789L,52790L,52791L,52792L,52793L,52794L,
+52795L,52796L,52797L,52798L,52799L,52800L,52801L,52802L,52803L,52804L,
+52805L,52806L,52807L,52808L,52809L,52810L,52811L,52812L,52813L,52814L,
+52815L,52816L,52817L,52818L,52819L,52820L,52821L,52822L,52823L,52824L,
+52825L,52826L,52827L,52828L,52829L,52830L,52831L,52832L,52833L,52834L,
+52835L,52836L,52837L,52838L,52839L,52840L,52841L,52842L,52843L,52844L,
+52845L,52846L,52847L,52848L,52849L,52850L,52851L,52852L,52853L,52854L,
+52855L,52856L,52857L,52858L,52859L,52860L,52861L,52862L,52863L,52864L,
+52865L,52866L,52867L,52868L,52869L,52870L,52871L,52872L,52873L,52874L,
+52875L,52876L,52877L,52878L,52879L,52880L,52881L,52882L,52883L,52884L,
+52885L,52886L,52887L,52888L,52889L,52890L,52891L,52892L,52893L,52894L,
+52895L,52896L,52897L,52898L,52899L,52900L,52901L,52902L,52903L,52904L,
+52905L,52906L,52907L,52908L,52909L,52910L,52911L,52912L,52913L,52914L,
+52915L,52916L,52917L,52918L,52919L,52920L,52921L,52922L,52923L,52924L,
+52925L,52926L,52927L,52928L,52929L,52930L,52931L,52932L,52933L,52934L,
+52935L,52936L,52937L,52938L,52939L,52940L,52941L,52942L,52943L,52944L,
+52945L,52946L,52947L,52948L,52949L,52950L,52951L,52952L,52953L,52954L,
+52955L,52956L,52957L,52958L,52959L,52960L,52961L,52962L,52963L,52964L,
+52965L,52966L,52967L,52968L,52969L,52970L,52971L,52972L,52973L,52974L,
+52975L,52976L,52977L,52978L,52979L,52980L,52981L,52982L,52983L,52984L,
+52985L,52986L,52987L,52988L,52989L,52990L,52991L,52992L,52993L,52994L,
+52995L,52996L,52997L,52998L,52999L,53000L,53001L,53002L,53003L,53004L,
+53005L,53006L,53007L,53008L,53009L,53010L,53011L,53012L,53013L,53014L,
+53015L,53016L,53017L,53018L,53019L,53020L,53021L,53022L,53023L,53024L,
+53025L,53026L,53027L,53028L,53029L,53030L,53031L,53032L,53033L,53034L,
+53035L,53036L,53037L,53038L,53039L,53040L,53041L,53042L,53043L,53044L,
+53045L,53046L,53047L,53048L,53049L,53050L,53051L,53052L,53053L,53054L,
+53055L,53056L,53057L,53058L,53059L,53060L,53061L,53062L,53063L,53064L,
+53065L,53066L,53067L,53068L,53069L,53070L,53071L,53072L,53073L,53074L,
+53075L,53076L,53077L,53078L,53079L,53080L,53081L,53082L,53083L,53084L,
+53085L,53086L,53087L,53088L,53089L,53090L,53091L,53092L,53093L,53094L,
+53095L,53096L,53097L,53098L,53099L,53100L,53101L,53102L,53103L,53104L,
+53105L,53106L,53107L,53108L,53109L,53110L,53111L,53112L,53113L,53114L,
+53115L,53116L,53117L,53118L,53119L,53120L,53121L,53122L,53123L,53124L,
+53125L,53126L,53127L,53128L,53129L,53130L,53131L,53132L,53133L,53134L,
+53135L,53136L,53137L,53138L,53139L,53140L,53141L,53142L,53143L,53144L,
+53145L,53146L,53147L,53148L,53149L,53150L,53151L,53152L,53153L,53154L,
+53155L,53156L,53157L,53158L,53159L,53160L,53161L,53162L,53163L,53164L,
+53165L,53166L,53167L,53168L,53169L,53170L,53171L,53172L,53173L,53174L,
+53175L,53176L,53177L,53178L,53179L,53180L,53181L,53182L,53183L,53184L,
+53185L,53186L,53187L,53188L,53189L,53190L,53191L,53192L,53193L,53194L,
+53195L,53196L,53197L,53198L,53199L,53200L,53201L,53202L,53203L,53204L,
+53205L,53206L,53207L,53208L,53209L,53210L,53211L,53212L,53213L,53214L,
+53215L,53216L,53217L,53218L,53219L,53220L,53221L,53222L,53223L,53224L,
+53225L,53226L,53227L,53228L,53229L,53230L,53231L,53232L,53233L,53234L,
+53235L,53236L,53237L,53238L,53239L,53240L,53241L,53242L,53243L,53244L,
+53245L,53246L,53247L,53248L,53249L,53250L,53251L,53252L,53253L,53254L,
+53255L,53256L,53257L,53258L,53259L,53260L,53261L,53262L,53263L,53264L,
+53265L,53266L,53267L,53268L,53269L,53270L,53271L,53272L,53273L,53274L,
+53275L,53276L,53277L,53278L,53279L,53280L,53281L,53282L,53283L,53284L,
+53285L,53286L,53287L,53288L,53289L,53290L,53291L,53292L,53293L,53294L,
+53295L,53296L,53297L,53298L,53299L,53300L,53301L,53302L,53303L,53304L,
+53305L,53306L,53307L,53308L,53309L,53310L,53311L,53312L,53313L,53314L,
+53315L,53316L,53317L,53318L,53319L,53320L,53321L,53322L,53323L,53324L,
+53325L,53326L,53327L,53328L,53329L,53330L,53331L,53332L,53333L,53334L,
+53335L,53336L,53337L,53338L,53339L,53340L,53341L,53342L,53343L,53344L,
+53345L,53346L,53347L,53348L,53349L,53350L,53351L,53352L,53353L,53354L,
+53355L,53356L,53357L,53358L,53359L,53360L,53361L,53362L,53363L,53364L,
+53365L,53366L,53367L,53368L,53369L,53370L,53371L,53372L,53373L,53374L,
+53375L,53376L,53377L,53378L,53379L,53380L,53381L,53382L,53383L,53384L,
+53385L,53386L,53387L,53388L,53389L,53390L,53391L,53392L,53393L,53394L,
+53395L,53396L,53397L,53398L,53399L,53400L,53401L,53402L,53403L,53404L,
+53405L,53406L,53407L,53408L,53409L,53410L,53411L,53412L,53413L,53414L,
+53415L,53416L,53417L,53418L,53419L,53420L,53421L,53422L,53423L,53424L,
+53425L,53426L,53427L,53428L,53429L,53430L,53431L,53432L,53433L,53434L,
+53435L,53436L,53437L,53438L,53439L,53440L,53441L,53442L,53443L,53444L,
+53445L,53446L,53447L,53448L,53449L,53450L,53451L,53452L,53453L,53454L,
+53455L,53456L,53457L,53458L,53459L,53460L,53461L,53462L,53463L,53464L,
+53465L,53466L,53467L,53468L,53469L,53470L,53471L,53472L,53473L,53474L,
+53475L,53476L,53477L,53478L,53479L,53480L,53481L,53482L,53483L,53484L,
+53485L,53486L,53487L,53488L,53489L,53490L,53491L,53492L,53493L,53494L,
+53495L,53496L,53497L,53498L,53499L,53500L,53501L,53502L,53503L,53504L,
+53505L,53506L,53507L,53508L,53509L,53510L,53511L,53512L,53513L,53514L,
+53515L,53516L,53517L,53518L,53519L,53520L,53521L,53522L,53523L,53524L,
+53525L,53526L,53527L,53528L,53529L,53530L,53531L,53532L,53533L,53534L,
+53535L,53536L,53537L,53538L,53539L,53540L,53541L,53542L,53543L,53544L,
+53545L,53546L,53547L,53548L,53549L,53550L,53551L,53552L,53553L,53554L,
+53555L,53556L,53557L,53558L,53559L,53560L,53561L,53562L,53563L,53564L,
+53565L,53566L,53567L,53568L,53569L,53570L,53571L,53572L,53573L,53574L,
+53575L,53576L,53577L,53578L,53579L,53580L,53581L,53582L,53583L,53584L,
+53585L,53586L,53587L,53588L,53589L,53590L,53591L,53592L,53593L,53594L,
+53595L,53596L,53597L,53598L,53599L,53600L,53601L,53602L,53603L,53604L,
+53605L,53606L,53607L,53608L,53609L,53610L,53611L,53612L,53613L,53614L,
+53615L,53616L,53617L,53618L,53619L,53620L,53621L,53622L,53623L,53624L,
+53625L,53626L,53627L,53628L,53629L,53630L,53631L,53632L,53633L,53634L,
+53635L,53636L,53637L,53638L,53639L,53640L,53641L,53642L,53643L,53644L,
+53645L,53646L,53647L,53648L,53649L,53650L,53651L,53652L,53653L,53654L,
+53655L,53656L,53657L,53658L,53659L,53660L,53661L,53662L,53663L,53664L,
+53665L,53666L,53667L,53668L,53669L,53670L,53671L,53672L,53673L,53674L,
+53675L,53676L,53677L,53678L,53679L,53680L,53681L,53682L,53683L,53684L,
+53685L,53686L,53687L,53688L,53689L,53690L,53691L,53692L,53693L,53694L,
+53695L,53696L,53697L,53698L,53699L,53700L,53701L,53702L,53703L,53704L,
+53705L,53706L,53707L,53708L,53709L,53710L,53711L,53712L,53713L,53714L,
+53715L,53716L,53717L,53718L,53719L,53720L,53721L,53722L,53723L,53724L,
+53725L,53726L,53727L,53728L,53729L,53730L,53731L,53732L,53733L,53734L,
+53735L,53736L,53737L,53738L,53739L,53740L,53741L,53742L,53743L,53744L,
+53745L,53746L,53747L,53748L,53749L,53750L,53751L,53752L,53753L,53754L,
+53755L,53756L,53757L,53758L,53759L,53760L,53761L,53762L,53763L,53764L,
+53765L,53766L,53767L,53768L,53769L,53770L,53771L,53772L,53773L,53774L,
+53775L,53776L,53777L,53778L,53779L,53780L,53781L,53782L,53783L,53784L,
+53785L,53786L,53787L,53788L,53789L,53790L,53791L,53792L,53793L,53794L,
+53795L,53796L,53797L,53798L,53799L,53800L,53801L,53802L,53803L,53804L,
+53805L,53806L,53807L,53808L,53809L,53810L,53811L,53812L,53813L,53814L,
+53815L,53816L,53817L,53818L,53819L,53820L,53821L,53822L,53823L,53824L,
+53825L,53826L,53827L,53828L,53829L,53830L,53831L,53832L,53833L,53834L,
+53835L,53836L,53837L,53838L,53839L,53840L,53841L,53842L,53843L,53844L,
+53845L,53846L,53847L,53848L,53849L,53850L,53851L,53852L,53853L,53854L,
+53855L,53856L,53857L,53858L,53859L,53860L,53861L,53862L,53863L,53864L,
+53865L,53866L,53867L,53868L,53869L,53870L,53871L,53872L,53873L,53874L,
+53875L,53876L,53877L,53878L,53879L,53880L,53881L,53882L,53883L,53884L,
+53885L,53886L,53887L,53888L,53889L,53890L,53891L,53892L,53893L,53894L,
+53895L,53896L,53897L,53898L,53899L,53900L,53901L,53902L,53903L,53904L,
+53905L,53906L,53907L,53908L,53909L,53910L,53911L,53912L,53913L,53914L,
+53915L,53916L,53917L,53918L,53919L,53920L,53921L,53922L,53923L,53924L,
+53925L,53926L,53927L,53928L,53929L,53930L,53931L,53932L,53933L,53934L,
+53935L,53936L,53937L,53938L,53939L,53940L,53941L,53942L,53943L,53944L,
+53945L,53946L,53947L,53948L,53949L,53950L,53951L,53952L,53953L,53954L,
+53955L,53956L,53957L,53958L,53959L,53960L,53961L,53962L,53963L,53964L,
+53965L,53966L,53967L,53968L,53969L,53970L,53971L,53972L,53973L,53974L,
+53975L,53976L,53977L,53978L,53979L,53980L,53981L,53982L,53983L,53984L,
+53985L,53986L,53987L,53988L,53989L,53990L,53991L,53992L,53993L,53994L,
+53995L,53996L,53997L,53998L,53999L,54000L,54001L,54002L,54003L,54004L,
+54005L,54006L,54007L,54008L,54009L,54010L,54011L,54012L,54013L,54014L,
+54015L,54016L,54017L,54018L,54019L,54020L,54021L,54022L,54023L,54024L,
+54025L,54026L,54027L,54028L,54029L,54030L,54031L,54032L,54033L,54034L,
+54035L,54036L,54037L,54038L,54039L,54040L,54041L,54042L,54043L,54044L,
+54045L,54046L,54047L,54048L,54049L,54050L,54051L,54052L,54053L,54054L,
+54055L,54056L,54057L,54058L,54059L,54060L,54061L,54062L,54063L,54064L,
+54065L,54066L,54067L,54068L,54069L,54070L,54071L,54072L,54073L,54074L,
+54075L,54076L,54077L,54078L,54079L,54080L,54081L,54082L,54083L,54084L,
+54085L,54086L,54087L,54088L,54089L,54090L,54091L,54092L,54093L,54094L,
+54095L,54096L,54097L,54098L,54099L,54100L,54101L,54102L,54103L,54104L,
+54105L,54106L,54107L,54108L,54109L,54110L,54111L,54112L,54113L,54114L,
+54115L,54116L,54117L,54118L,54119L,54120L,54121L,54122L,54123L,54124L,
+54125L,54126L,54127L,54128L,54129L,54130L,54131L,54132L,54133L,54134L,
+54135L,54136L,54137L,54138L,54139L,54140L,54141L,54142L,54143L,54144L,
+54145L,54146L,54147L,54148L,54149L,54150L,54151L,54152L,54153L,54154L,
+54155L,54156L,54157L,54158L,54159L,54160L,54161L,54162L,54163L,54164L,
+54165L,54166L,54167L,54168L,54169L,54170L,54171L,54172L,54173L,54174L,
+54175L,54176L,54177L,54178L,54179L,54180L,54181L,54182L,54183L,54184L,
+54185L,54186L,54187L,54188L,54189L,54190L,54191L,54192L,54193L,54194L,
+54195L,54196L,54197L,54198L,54199L,54200L,54201L,54202L,54203L,54204L,
+54205L,54206L,54207L,54208L,54209L,54210L,54211L,54212L,54213L,54214L,
+54215L,54216L,54217L,54218L,54219L,54220L,54221L,54222L,54223L,54224L,
+54225L,54226L,54227L,54228L,54229L,54230L,54231L,54232L,54233L,54234L,
+54235L,54236L,54237L,54238L,54239L,54240L,54241L,54242L,54243L,54244L,
+54245L,54246L,54247L,54248L,54249L,54250L,54251L,54252L,54253L,54254L,
+54255L,54256L,54257L,54258L,54259L,54260L,54261L,54262L,54263L,54264L,
+54265L,54266L,54267L,54268L,54269L,54270L,54271L,54272L,54273L,54274L,
+54275L,54276L,54277L,54278L,54279L,54280L,54281L,54282L,54283L,54284L,
+54285L,54286L,54287L,54288L,54289L,54290L,54291L,54292L,54293L,54294L,
+54295L,54296L,54297L,54298L,54299L,54300L,54301L,54302L,54303L,54304L,
+54305L,54306L,54307L,54308L,54309L,54310L,54311L,54312L,54313L,54314L,
+54315L,54316L,54317L,54318L,54319L,54320L,54321L,54322L,54323L,54324L,
+54325L,54326L,54327L,54328L,54329L,54330L,54331L,54332L,54333L,54334L,
+54335L,54336L,54337L,54338L,54339L,54340L,54341L,54342L,54343L,54344L,
+54345L,54346L,54347L,54348L,54349L,54350L,54351L,54352L,54353L,54354L,
+54355L,54356L,54357L,54358L,54359L,54360L,54361L,54362L,54363L,54364L,
+54365L,54366L,54367L,54368L,54369L,54370L,54371L,54372L,54373L,54374L,
+54375L,54376L,54377L,54378L,54379L,54380L,54381L,54382L,54383L,54384L,
+54385L,54386L,54387L,54388L,54389L,54390L,54391L,54392L,54393L,54394L,
+54395L,54396L,54397L,54398L,54399L,54400L,54401L,54402L,54403L,54404L,
+54405L,54406L,54407L,54408L,54409L,54410L,54411L,54412L,54413L,54414L,
+54415L,54416L,54417L,54418L,54419L,54420L,54421L,54422L,54423L,54424L,
+54425L,54426L,54427L,54428L,54429L,54430L,54431L,54432L,54433L,54434L,
+54435L,54436L,54437L,54438L,54439L,54440L,54441L,54442L,54443L,54444L,
+54445L,54446L,54447L,54448L,54449L,54450L,54451L,54452L,54453L,54454L,
+54455L,54456L,54457L,54458L,54459L,54460L,54461L,54462L,54463L,54464L,
+54465L,54466L,54467L,54468L,54469L,54470L,54471L,54472L,54473L,54474L,
+54475L,54476L,54477L,54478L,54479L,54480L,54481L,54482L,54483L,54484L,
+54485L,54486L,54487L,54488L,54489L,54490L,54491L,54492L,54493L,54494L,
+54495L,54496L,54497L,54498L,54499L,54500L,54501L,54502L,54503L,54504L,
+54505L,54506L,54507L,54508L,54509L,54510L,54511L,54512L,54513L,54514L,
+54515L,54516L,54517L,54518L,54519L,54520L,54521L,54522L,54523L,54524L,
+54525L,54526L,54527L,54528L,54529L,54530L,54531L,54532L,54533L,54534L,
+54535L,54536L,54537L,54538L,54539L,54540L,54541L,54542L,54543L,54544L,
+54545L,54546L,54547L,54548L,54549L,54550L,54551L,54552L,54553L,54554L,
+54555L,54556L,54557L,54558L,54559L,54560L,54561L,54562L,54563L,54564L,
+54565L,54566L,54567L,54568L,54569L,54570L,54571L,54572L,54573L,54574L,
+54575L,54576L,54577L,54578L,54579L,54580L,54581L,54582L,54583L,54584L,
+54585L,54586L,54587L,54588L,54589L,54590L,54591L,54592L,54593L,54594L,
+54595L,54596L,54597L,54598L,54599L,54600L,54601L,54602L,54603L,54604L,
+54605L,54606L,54607L,54608L,54609L,54610L,54611L,54612L,54613L,54614L,
+54615L,54616L,54617L,54618L,54619L,54620L,54621L,54622L,54623L,54624L,
+54625L,54626L,54627L,54628L,54629L,54630L,54631L,54632L,54633L,54634L,
+54635L,54636L,54637L,54638L,54639L,54640L,54641L,54642L,54643L,54644L,
+54645L,54646L,54647L,54648L,54649L,54650L,54651L,54652L,54653L,54654L,
+54655L,54656L,54657L,54658L,54659L,54660L,54661L,54662L,54663L,54664L,
+54665L,54666L,54667L,54668L,54669L,54670L,54671L,54672L,54673L,54674L,
+54675L,54676L,54677L,54678L,54679L,54680L,54681L,54682L,54683L,54684L,
+54685L,54686L,54687L,54688L,54689L,54690L,54691L,54692L,54693L,54694L,
+54695L,54696L,54697L,54698L,54699L,54700L,54701L,54702L,54703L,54704L,
+54705L,54706L,54707L,54708L,54709L,54710L,54711L,54712L,54713L,54714L,
+54715L,54716L,54717L,54718L,54719L,54720L,54721L,54722L,54723L,54724L,
+54725L,54726L,54727L,54728L,54729L,54730L,54731L,54732L,54733L,54734L,
+54735L,54736L,54737L,54738L,54739L,54740L,54741L,54742L,54743L,54744L,
+54745L,54746L,54747L,54748L,54749L,54750L,54751L,54752L,54753L,54754L,
+54755L,54756L,54757L,54758L,54759L,54760L,54761L,54762L,54763L,54764L,
+54765L,54766L,54767L,54768L,54769L,54770L,54771L,54772L,54773L,54774L,
+54775L,54776L,54777L,54778L,54779L,54780L,54781L,54782L,54783L,54784L,
+54785L,54786L,54787L,54788L,54789L,54790L,54791L,54792L,54793L,54794L,
+54795L,54796L,54797L,54798L,54799L,54800L,54801L,54802L,54803L,54804L,
+54805L,54806L,54807L,54808L,54809L,54810L,54811L,54812L,54813L,54814L,
+54815L,54816L,54817L,54818L,54819L,54820L,54821L,54822L,54823L,54824L,
+54825L,54826L,54827L,54828L,54829L,54830L,54831L,54832L,54833L,54834L,
+54835L,54836L,54837L,54838L,54839L,54840L,54841L,54842L,54843L,54844L,
+54845L,54846L,54847L,54848L,54849L,54850L,54851L,54852L,54853L,54854L,
+54855L,54856L,54857L,54858L,54859L,54860L,54861L,54862L,54863L,54864L,
+54865L,54866L,54867L,54868L,54869L,54870L,54871L,54872L,54873L,54874L,
+54875L,54876L,54877L,54878L,54879L,54880L,54881L,54882L,54883L,54884L,
+54885L,54886L,54887L,54888L,54889L,54890L,54891L,54892L,54893L,54894L,
+54895L,54896L,54897L,54898L,54899L,54900L,54901L,54902L,54903L,54904L,
+54905L,54906L,54907L,54908L,54909L,54910L,54911L,54912L,54913L,54914L,
+54915L,54916L,54917L,54918L,54919L,54920L,54921L,54922L,54923L,54924L,
+54925L,54926L,54927L,54928L,54929L,54930L,54931L,54932L,54933L,54934L,
+54935L,54936L,54937L,54938L,54939L,54940L,54941L,54942L,54943L,54944L,
+54945L,54946L,54947L,54948L,54949L,54950L,54951L,54952L,54953L,54954L,
+54955L,54956L,54957L,54958L,54959L,54960L,54961L,54962L,54963L,54964L,
+54965L,54966L,54967L,54968L,54969L,54970L,54971L,54972L,54973L,54974L,
+54975L,54976L,54977L,54978L,54979L,54980L,54981L,54982L,54983L,54984L,
+54985L,54986L,54987L,54988L,54989L,54990L,54991L,54992L,54993L,54994L,
+54995L,54996L,54997L,54998L,54999L,55000L,55001L,55002L,55003L,55004L,
+55005L,55006L,55007L,55008L,55009L,55010L,55011L,55012L,55013L,55014L,
+55015L,55016L,55017L,55018L,55019L,55020L,55021L,55022L,55023L,55024L,
+55025L,55026L,55027L,55028L,55029L,55030L,55031L,55032L,55033L,55034L,
+55035L,55036L,55037L,55038L,55039L,55040L,55041L,55042L,55043L,55044L,
+55045L,55046L,55047L,55048L,55049L,55050L,55051L,55052L,55053L,55054L,
+55055L,55056L,55057L,55058L,55059L,55060L,55061L,55062L,55063L,55064L,
+55065L,55066L,55067L,55068L,55069L,55070L,55071L,55072L,55073L,55074L,
+55075L,55076L,55077L,55078L,55079L,55080L,55081L,55082L,55083L,55084L,
+55085L,55086L,55087L,55088L,55089L,55090L,55091L,55092L,55093L,55094L,
+55095L,55096L,55097L,55098L,55099L,55100L,55101L,55102L,55103L,55104L,
+55105L,55106L,55107L,55108L,55109L,55110L,55111L,55112L,55113L,55114L,
+55115L,55116L,55117L,55118L,55119L,55120L,55121L,55122L,55123L,55124L,
+55125L,55126L,55127L,55128L,55129L,55130L,55131L,55132L,55133L,55134L,
+55135L,55136L,55137L,55138L,55139L,55140L,55141L,55142L,55143L,55144L,
+55145L,55146L,55147L,55148L,55149L,55150L,55151L,55152L,55153L,55154L,
+55155L,55156L,55157L,55158L,55159L,55160L,55161L,55162L,55163L,55164L,
+55165L,55166L,55167L,55168L,55169L,55170L,55171L,55172L,55173L,55174L,
+55175L,55176L,55177L,55178L,55179L,55180L,55181L,55182L,55183L,55184L,
+55185L,55186L,55187L,55188L,55189L,55190L,55191L,55192L,55193L,55194L,
+55195L,55196L,55197L,55198L,55199L,55200L,55201L,55202L,55203L,55204L,
+55205L,55206L,55207L,55208L,55209L,55210L,55211L,55212L,55213L,55214L,
+55215L,55216L,55217L,55218L,55219L,55220L,55221L,55222L,55223L,55224L,
+55225L,55226L,55227L,55228L,55229L,55230L,55231L,55232L,55233L,55234L,
+55235L,55236L,55237L,55238L,55239L,55240L,55241L,55242L,55243L,55244L,
+55245L,55246L,55247L,55248L,55249L,55250L,55251L,55252L,55253L,55254L,
+55255L,55256L,55257L,55258L,55259L,55260L,55261L,55262L,55263L,55264L,
+55265L,55266L,55267L,55268L,55269L,55270L,55271L,55272L,55273L,55274L,
+55275L,55276L,55277L,55278L,55279L,55280L,55281L,55282L,55283L,55284L,
+55285L,55286L,55287L,55288L,55289L,55290L,55291L,55292L,55293L,55294L,
+55295L,55296L,55297L,55298L,55299L,55300L,55301L,55302L,55303L,55304L,
+55305L,55306L,55307L,55308L,55309L,55310L,55311L,55312L,55313L,55314L,
+55315L,55316L,55317L,55318L,55319L,55320L,55321L,55322L,55323L,55324L,
+55325L,55326L,55327L,55328L,55329L,55330L,55331L,55332L,55333L,55334L,
+55335L,55336L,55337L,55338L,55339L,55340L,55341L,55342L,55343L,55344L,
+55345L,55346L,55347L,55348L,55349L,55350L,55351L,55352L,55353L,55354L,
+55355L,55356L,55357L,55358L,55359L,55360L,55361L,55362L,55363L,55364L,
+55365L,55366L,55367L,55368L,55369L,55370L,55371L,55372L,55373L,55374L,
+55375L,55376L,55377L,55378L,55379L,55380L,55381L,55382L,55383L,55384L,
+55385L,55386L,55387L,55388L,55389L,55390L,55391L,55392L,55393L,55394L,
+55395L,55396L,55397L,55398L,55399L,55400L,55401L,55402L,55403L,55404L,
+55405L,55406L,55407L,55408L,55409L,55410L,55411L,55412L,55413L,55414L,
+55415L,55416L,55417L,55418L,55419L,55420L,55421L,55422L,55423L,55424L,
+55425L,55426L,55427L,55428L,55429L,55430L,55431L,55432L,55433L,55434L,
+55435L,55436L,55437L,55438L,55439L,55440L,55441L,55442L,55443L,55444L,
+55445L,55446L,55447L,55448L,55449L,55450L,55451L,55452L,55453L,55454L,
+55455L,55456L,55457L,55458L,55459L,55460L,55461L,55462L,55463L,55464L,
+55465L,55466L,55467L,55468L,55469L,55470L,55471L,55472L,55473L,55474L,
+55475L,55476L,55477L,55478L,55479L,55480L,55481L,55482L,55483L,55484L,
+55485L,55486L,55487L,55488L,55489L,55490L,55491L,55492L,55493L,55494L,
+55495L,55496L,55497L,55498L,55499L,55500L,55501L,55502L,55503L,55504L,
+55505L,55506L,55507L,55508L,55509L,55510L,55511L,55512L,55513L,55514L,
+55515L,55516L,55517L,55518L,55519L,55520L,55521L,55522L,55523L,55524L,
+55525L,55526L,55527L,55528L,55529L,55530L,55531L,55532L,55533L,55534L,
+55535L,55536L,55537L,55538L,55539L,55540L,55541L,55542L,55543L,55544L,
+55545L,55546L,55547L,55548L,55549L,55550L,55551L,55552L,55553L,55554L,
+55555L,55556L,55557L,55558L,55559L,55560L,55561L,55562L,55563L,55564L,
+55565L,55566L,55567L,55568L,55569L,55570L,55571L,55572L,55573L,55574L,
+55575L,55576L,55577L,55578L,55579L,55580L,55581L,55582L,55583L,55584L,
+55585L,55586L,55587L,55588L,55589L,55590L,55591L,55592L,55593L,55594L,
+55595L,55596L,55597L,55598L,55599L,55600L,55601L,55602L,55603L,55604L,
+55605L,55606L,55607L,55608L,55609L,55610L,55611L,55612L,55613L,55614L,
+55615L,55616L,55617L,55618L,55619L,55620L,55621L,55622L,55623L,55624L,
+55625L,55626L,55627L,55628L,55629L,55630L,55631L,55632L,55633L,55634L,
+55635L,55636L,55637L,55638L,55639L,55640L,55641L,55642L,55643L,55644L,
+55645L,55646L,55647L,55648L,55649L,55650L,55651L,55652L,55653L,55654L,
+55655L,55656L,55657L,55658L,55659L,55660L,55661L,55662L,55663L,55664L,
+55665L,55666L,55667L,55668L,55669L,55670L,55671L,55672L,55673L,55674L,
+55675L,55676L,55677L,55678L,55679L,55680L,55681L,55682L,55683L,55684L,
+55685L,55686L,55687L,55688L,55689L,55690L,55691L,55692L,55693L,55694L,
+55695L,55696L,55697L,55698L,55699L,55700L,55701L,55702L,55703L,55704L,
+55705L,55706L,55707L,55708L,55709L,55710L,55711L,55712L,55713L,55714L,
+55715L,55716L,55717L,55718L,55719L,55720L,55721L,55722L,55723L,55724L,
+55725L,55726L,55727L,55728L,55729L,55730L,55731L,55732L,55733L,55734L,
+55735L,55736L,55737L,55738L,55739L,55740L,55741L,55742L,55743L,55744L,
+55745L,55746L,55747L,55748L,55749L,55750L,55751L,55752L,55753L,55754L,
+55755L,55756L,55757L,55758L,55759L,55760L,55761L,55762L,55763L,55764L,
+55765L,55766L,55767L,55768L,55769L,55770L,55771L,55772L,55773L,55774L,
+55775L,55776L,55777L,55778L,55779L,55780L,55781L,55782L,55783L,55784L,
+55785L,55786L,55787L,55788L,55789L,55790L,55791L,55792L,55793L,55794L,
+55795L,55796L,55797L,55798L,55799L,55800L,55801L,55802L,55803L,55804L,
+55805L,55806L,55807L,55808L,55809L,55810L,55811L,55812L,55813L,55814L,
+55815L,55816L,55817L,55818L,55819L,55820L,55821L,55822L,55823L,55824L,
+55825L,55826L,55827L,55828L,55829L,55830L,55831L,55832L,55833L,55834L,
+55835L,55836L,55837L,55838L,55839L,55840L,55841L,55842L,55843L,55844L,
+55845L,55846L,55847L,55848L,55849L,55850L,55851L,55852L,55853L,55854L,
+55855L,55856L,55857L,55858L,55859L,55860L,55861L,55862L,55863L,55864L,
+55865L,55866L,55867L,55868L,55869L,55870L,55871L,55872L,55873L,55874L,
+55875L,55876L,55877L,55878L,55879L,55880L,55881L,55882L,55883L,55884L,
+55885L,55886L,55887L,55888L,55889L,55890L,55891L,55892L,55893L,55894L,
+55895L,55896L,55897L,55898L,55899L,55900L,55901L,55902L,55903L,55904L,
+55905L,55906L,55907L,55908L,55909L,55910L,55911L,55912L,55913L,55914L,
+55915L,55916L,55917L,55918L,55919L,55920L,55921L,55922L,55923L,55924L,
+55925L,55926L,55927L,55928L,55929L,55930L,55931L,55932L,55933L,55934L,
+55935L,55936L,55937L,55938L,55939L,55940L,55941L,55942L,55943L,55944L,
+55945L,55946L,55947L,55948L,55949L,55950L,55951L,55952L,55953L,55954L,
+55955L,55956L,55957L,55958L,55959L,55960L,55961L,55962L,55963L,55964L,
+55965L,55966L,55967L,55968L,55969L,55970L,55971L,55972L,55973L,55974L,
+55975L,55976L,55977L,55978L,55979L,55980L,55981L,55982L,55983L,55984L,
+55985L,55986L,55987L,55988L,55989L,55990L,55991L,55992L,55993L,55994L,
+55995L,55996L,55997L,55998L,55999L,56000L,56001L,56002L,56003L,56004L,
+56005L,56006L,56007L,56008L,56009L,56010L,56011L,56012L,56013L,56014L,
+56015L,56016L,56017L,56018L,56019L,56020L,56021L,56022L,56023L,56024L,
+56025L,56026L,56027L,56028L,56029L,56030L,56031L,56032L,56033L,56034L,
+56035L,56036L,56037L,56038L,56039L,56040L,56041L,56042L,56043L,56044L,
+56045L,56046L,56047L,56048L,56049L,56050L,56051L,56052L,56053L,56054L,
+56055L,56056L,56057L,56058L,56059L,56060L,56061L,56062L,56063L,56064L,
+56065L,56066L,56067L,56068L,56069L,56070L,56071L,56072L,56073L,56074L,
+56075L,56076L,56077L,56078L,56079L,56080L,56081L,56082L,56083L,56084L,
+56085L,56086L,56087L,56088L,56089L,56090L,56091L,56092L,56093L,56094L,
+56095L,56096L,56097L,56098L,56099L,56100L,56101L,56102L,56103L,56104L,
+56105L,56106L,56107L,56108L,56109L,56110L,56111L,56112L,56113L,56114L,
+56115L,56116L,56117L,56118L,56119L,56120L,56121L,56122L,56123L,56124L,
+56125L,56126L,56127L,56128L,56129L,56130L,56131L,56132L,56133L,56134L,
+56135L,56136L,56137L,56138L,56139L,56140L,56141L,56142L,56143L,56144L,
+56145L,56146L,56147L,56148L,56149L,56150L,56151L,56152L,56153L,56154L,
+56155L,56156L,56157L,56158L,56159L,56160L,56161L,56162L,56163L,56164L,
+56165L,56166L,56167L,56168L,56169L,56170L,56171L,56172L,56173L,56174L,
+56175L,56176L,56177L,56178L,56179L,56180L,56181L,56182L,56183L,56184L,
+56185L,56186L,56187L,56188L,56189L,56190L,56191L,56192L,56193L,56194L,
+56195L,56196L,56197L,56198L,56199L,56200L,56201L,56202L,56203L,56204L,
+56205L,56206L,56207L,56208L,56209L,56210L,56211L,56212L,56213L,56214L,
+56215L,56216L,56217L,56218L,56219L,56220L,56221L,56222L,56223L,56224L,
+56225L,56226L,56227L,56228L,56229L,56230L,56231L,56232L,56233L,56234L,
+56235L,56236L,56237L,56238L,56239L,56240L,56241L,56242L,56243L,56244L,
+56245L,56246L,56247L,56248L,56249L,56250L,56251L,56252L,56253L,56254L,
+56255L,56256L,56257L,56258L,56259L,56260L,56261L,56262L,56263L,56264L,
+56265L,56266L,56267L,56268L,56269L,56270L,56271L,56272L,56273L,56274L,
+56275L,56276L,56277L,56278L,56279L,56280L,56281L,56282L,56283L,56284L,
+56285L,56286L,56287L,56288L,56289L,56290L,56291L,56292L,56293L,56294L,
+56295L,56296L,56297L,56298L,56299L,56300L,56301L,56302L,56303L,56304L,
+56305L,56306L,56307L,56308L,56309L,56310L,56311L,56312L,56313L,56314L,
+56315L,56316L,56317L,56318L,56319L,56320L,56321L,56322L,56323L,56324L,
+56325L,56326L,56327L,56328L,56329L,56330L,56331L,56332L,56333L,56334L,
+56335L,56336L,56337L,56338L,56339L,56340L,56341L,56342L,56343L,56344L,
+56345L,56346L,56347L,56348L,56349L,56350L,56351L,56352L,56353L,56354L,
+56355L,56356L,56357L,56358L,56359L,56360L,56361L,56362L,56363L,56364L,
+56365L,56366L,56367L,56368L,56369L,56370L,56371L,56372L,56373L,56374L,
+56375L,56376L,56377L,56378L,56379L,56380L,56381L,56382L,56383L,56384L,
+56385L,56386L,56387L,56388L,56389L,56390L,56391L,56392L,56393L,56394L,
+56395L,56396L,56397L,56398L,56399L,56400L,56401L,56402L,56403L,56404L,
+56405L,56406L,56407L,56408L,56409L,56410L,56411L,56412L,56413L,56414L,
+56415L,56416L,56417L,56418L,56419L,56420L,56421L,56422L,56423L,56424L,
+56425L,56426L,56427L,56428L,56429L,56430L,56431L,56432L,56433L,56434L,
+56435L,56436L,56437L,56438L,56439L,56440L,56441L,56442L,56443L,56444L,
+56445L,56446L,56447L,56448L,56449L,56450L,56451L,56452L,56453L,56454L,
+56455L,56456L,56457L,56458L,56459L,56460L,56461L,56462L,56463L,56464L,
+56465L,56466L,56467L,56468L,56469L,56470L,56471L,56472L,56473L,56474L,
+56475L,56476L,56477L,56478L,56479L,56480L,56481L,56482L,56483L,56484L,
+56485L,56486L,56487L,56488L,56489L,56490L,56491L,56492L,56493L,56494L,
+56495L,56496L,56497L,56498L,56499L,56500L,56501L,56502L,56503L,56504L,
+56505L,56506L,56507L,56508L,56509L,56510L,56511L,56512L,56513L,56514L,
+56515L,56516L,56517L,56518L,56519L,56520L,56521L,56522L,56523L,56524L,
+56525L,56526L,56527L,56528L,56529L,56530L,56531L,56532L,56533L,56534L,
+56535L,56536L,56537L,56538L,56539L,56540L,56541L,56542L,56543L,56544L,
+56545L,56546L,56547L,56548L,56549L,56550L,56551L,56552L,56553L,56554L,
+56555L,56556L,56557L,56558L,56559L,56560L,56561L,56562L,56563L,56564L,
+56565L,56566L,56567L,56568L,56569L,56570L,56571L,56572L,56573L,56574L,
+56575L,56576L,56577L,56578L,56579L,56580L,56581L,56582L,56583L,56584L,
+56585L,56586L,56587L,56588L,56589L,56590L,56591L,56592L,56593L,56594L,
+56595L,56596L,56597L,56598L,56599L,56600L,56601L,56602L,56603L,56604L,
+56605L,56606L,56607L,56608L,56609L,56610L,56611L,56612L,56613L,56614L,
+56615L,56616L,56617L,56618L,56619L,56620L,56621L,56622L,56623L,56624L,
+56625L,56626L,56627L,56628L,56629L,56630L,56631L,56632L,56633L,56634L,
+56635L,56636L,56637L,56638L,56639L,56640L,56641L,56642L,56643L,56644L,
+56645L,56646L,56647L,56648L,56649L,56650L,56651L,56652L,56653L,56654L,
+56655L,56656L,56657L,56658L,56659L,56660L,56661L,56662L,56663L,56664L,
+56665L,56666L,56667L,56668L,56669L,56670L,56671L,56672L,56673L,56674L,
+56675L,56676L,56677L,56678L,56679L,56680L,56681L,56682L,56683L,56684L,
+56685L,56686L,56687L,56688L,56689L,56690L,56691L,56692L,56693L,56694L,
+56695L,56696L,56697L,56698L,56699L,56700L,56701L,56702L,56703L,56704L,
+56705L,56706L,56707L,56708L,56709L,56710L,56711L,56712L,56713L,56714L,
+56715L,56716L,56717L,56718L,56719L,56720L,56721L,56722L,56723L,56724L,
+56725L,56726L,56727L,56728L,56729L,56730L,56731L,56732L,56733L,56734L,
+56735L,56736L,56737L,56738L,56739L,56740L,56741L,56742L,56743L,56744L,
+56745L,56746L,56747L,56748L,56749L,56750L,56751L,56752L,56753L,56754L,
+56755L,56756L,56757L,56758L,56759L,56760L,56761L,56762L,56763L,56764L,
+56765L,56766L,56767L,56768L,56769L,56770L,56771L,56772L,56773L,56774L,
+56775L,56776L,56777L,56778L,56779L,56780L,56781L,56782L,56783L,56784L,
+56785L,56786L,56787L,56788L,56789L,56790L,56791L,56792L,56793L,56794L,
+56795L,56796L,56797L,56798L,56799L,56800L,56801L,56802L,56803L,56804L,
+56805L,56806L,56807L,56808L,56809L,56810L,56811L,56812L,56813L,56814L,
+56815L,56816L,56817L,56818L,56819L,56820L,56821L,56822L,56823L,56824L,
+56825L,56826L,56827L,56828L,56829L,56830L,56831L,56832L,56833L,56834L,
+56835L,56836L,56837L,56838L,56839L,56840L,56841L,56842L,56843L,56844L,
+56845L,56846L,56847L,56848L,56849L,56850L,56851L,56852L,56853L,56854L,
+56855L,56856L,56857L,56858L,56859L,56860L,56861L,56862L,56863L,56864L,
+56865L,56866L,56867L,56868L,56869L,56870L,56871L,56872L,56873L,56874L,
+56875L,56876L,56877L,56878L,56879L,56880L,56881L,56882L,56883L,56884L,
+56885L,56886L,56887L,56888L,56889L,56890L,56891L,56892L,56893L,56894L,
+56895L,56896L,56897L,56898L,56899L,56900L,56901L,56902L,56903L,56904L,
+56905L,56906L,56907L,56908L,56909L,56910L,56911L,56912L,56913L,56914L,
+56915L,56916L,56917L,56918L,56919L,56920L,56921L,56922L,56923L,56924L,
+56925L,56926L,56927L,56928L,56929L,56930L,56931L,56932L,56933L,56934L,
+56935L,56936L,56937L,56938L,56939L,56940L,56941L,56942L,56943L,56944L,
+56945L,56946L,56947L,56948L,56949L,56950L,56951L,56952L,56953L,56954L,
+56955L,56956L,56957L,56958L,56959L,56960L,56961L,56962L,56963L,56964L,
+56965L,56966L,56967L,56968L,56969L,56970L,56971L,56972L,56973L,56974L,
+56975L,56976L,56977L,56978L,56979L,56980L,56981L,56982L,56983L,56984L,
+56985L,56986L,56987L,56988L,56989L,56990L,56991L,56992L,56993L,56994L,
+56995L,56996L,56997L,56998L,56999L,57000L,57001L,57002L,57003L,57004L,
+57005L,57006L,57007L,57008L,57009L,57010L,57011L,57012L,57013L,57014L,
+57015L,57016L,57017L,57018L,57019L,57020L,57021L,57022L,57023L,57024L,
+57025L,57026L,57027L,57028L,57029L,57030L,57031L,57032L,57033L,57034L,
+57035L,57036L,57037L,57038L,57039L,57040L,57041L,57042L,57043L,57044L,
+57045L,57046L,57047L,57048L,57049L,57050L,57051L,57052L,57053L,57054L,
+57055L,57056L,57057L,57058L,57059L,57060L,57061L,57062L,57063L,57064L,
+57065L,57066L,57067L,57068L,57069L,57070L,57071L,57072L,57073L,57074L,
+57075L,57076L,57077L,57078L,57079L,57080L,57081L,57082L,57083L,57084L,
+57085L,57086L,57087L,57088L,57089L,57090L,57091L,57092L,57093L,57094L,
+57095L,57096L,57097L,57098L,57099L,57100L,57101L,57102L,57103L,57104L,
+57105L,57106L,57107L,57108L,57109L,57110L,57111L,57112L,57113L,57114L,
+57115L,57116L,57117L,57118L,57119L,57120L,57121L,57122L,57123L,57124L,
+57125L,57126L,57127L,57128L,57129L,57130L,57131L,57132L,57133L,57134L,
+57135L,57136L,57137L,57138L,57139L,57140L,57141L,57142L,57143L,57144L,
+57145L,57146L,57147L,57148L,57149L,57150L,57151L,57152L,57153L,57154L,
+57155L,57156L,57157L,57158L,57159L,57160L,57161L,57162L,57163L,57164L,
+57165L,57166L,57167L,57168L,57169L,57170L,57171L,57172L,57173L,57174L,
+57175L,57176L,57177L,57178L,57179L,57180L,57181L,57182L,57183L,57184L,
+57185L,57186L,57187L,57188L,57189L,57190L,57191L,57192L,57193L,57194L,
+57195L,57196L,57197L,57198L,57199L,57200L,57201L,57202L,57203L,57204L,
+57205L,57206L,57207L,57208L,57209L,57210L,57211L,57212L,57213L,57214L,
+57215L,57216L,57217L,57218L,57219L,57220L,57221L,57222L,57223L,57224L,
+57225L,57226L,57227L,57228L,57229L,57230L,57231L,57232L,57233L,57234L,
+57235L,57236L,57237L,57238L,57239L,57240L,57241L,57242L,57243L,57244L,
+57245L,57246L,57247L,57248L,57249L,57250L,57251L,57252L,57253L,57254L,
+57255L,57256L,57257L,57258L,57259L,57260L,57261L,57262L,57263L,57264L,
+57265L,57266L,57267L,57268L,57269L,57270L,57271L,57272L,57273L,57274L,
+57275L,57276L,57277L,57278L,57279L,57280L,57281L,57282L,57283L,57284L,
+57285L,57286L,57287L,57288L,57289L,57290L,57291L,57292L,57293L,57294L,
+57295L,57296L,57297L,57298L,57299L,57300L,57301L,57302L,57303L,57304L,
+57305L,57306L,57307L,57308L,57309L,57310L,57311L,57312L,57313L,57314L,
+57315L,57316L,57317L,57318L,57319L,57320L,57321L,57322L,57323L,57324L,
+57325L,57326L,57327L,57328L,57329L,57330L,57331L,57332L,57333L,57334L,
+57335L,57336L,57337L,57338L,57339L,57340L,57341L,57342L,57343L,57344L,
+57345L,57346L,57347L,57348L,57349L,57350L,57351L,57352L,57353L,57354L,
+57355L,57356L,57357L,57358L,57359L,57360L,57361L,57362L,57363L,57364L,
+57365L,57366L,57367L,57368L,57369L,57370L,57371L,57372L,57373L,57374L,
+57375L,57376L,57377L,57378L,57379L,57380L,57381L,57382L,57383L,57384L,
+57385L,57386L,57387L,57388L,57389L,57390L,57391L,57392L,57393L,57394L,
+57395L,57396L,57397L,57398L,57399L,57400L,57401L,57402L,57403L,57404L,
+57405L,57406L,57407L,57408L,57409L,57410L,57411L,57412L,57413L,57414L,
+57415L,57416L,57417L,57418L,57419L,57420L,57421L,57422L,57423L,57424L,
+57425L,57426L,57427L,57428L,57429L,57430L,57431L,57432L,57433L,57434L,
+57435L,57436L,57437L,57438L,57439L,57440L,57441L,57442L,57443L,57444L,
+57445L,57446L,57447L,57448L,57449L,57450L,57451L,57452L,57453L,57454L,
+57455L,57456L,57457L,57458L,57459L,57460L,57461L,57462L,57463L,57464L,
+57465L,57466L,57467L,57468L,57469L,57470L,57471L,57472L,57473L,57474L,
+57475L,57476L,57477L,57478L,57479L,57480L,57481L,57482L,57483L,57484L,
+57485L,57486L,57487L,57488L,57489L,57490L,57491L,57492L,57493L,57494L,
+57495L,57496L,57497L,57498L,57499L,57500L,57501L,57502L,57503L,57504L,
+57505L,57506L,57507L,57508L,57509L,57510L,57511L,57512L,57513L,57514L,
+57515L,57516L,57517L,57518L,57519L,57520L,57521L,57522L,57523L,57524L,
+57525L,57526L,57527L,57528L,57529L,57530L,57531L,57532L,57533L,57534L,
+57535L,57536L,57537L,57538L,57539L,57540L,57541L,57542L,57543L,57544L,
+57545L,57546L,57547L,57548L,57549L,57550L,57551L,57552L,57553L,57554L,
+57555L,57556L,57557L,57558L,57559L,57560L,57561L,57562L,57563L,57564L,
+57565L,57566L,57567L,57568L,57569L,57570L,57571L,57572L,57573L,57574L,
+57575L,57576L,57577L,57578L,57579L,57580L,57581L,57582L,57583L,57584L,
+57585L,57586L,57587L,57588L,57589L,57590L,57591L,57592L,57593L,57594L,
+57595L,57596L,57597L,57598L,57599L,57600L,57601L,57602L,57603L,57604L,
+57605L,57606L,57607L,57608L,57609L,57610L,57611L,57612L,57613L,57614L,
+57615L,57616L,57617L,57618L,57619L,57620L,57621L,57622L,57623L,57624L,
+57625L,57626L,57627L,57628L,57629L,57630L,57631L,57632L,57633L,57634L,
+57635L,57636L,57637L,57638L,57639L,57640L,57641L,57642L,57643L,57644L,
+57645L,57646L,57647L,57648L,57649L,57650L,57651L,57652L,57653L,57654L,
+57655L,57656L,57657L,57658L,57659L,57660L,57661L,57662L,57663L,57664L,
+57665L,57666L,57667L,57668L,57669L,57670L,57671L,57672L,57673L,57674L,
+57675L,57676L,57677L,57678L,57679L,57680L,57681L,57682L,57683L,57684L,
+57685L,57686L,57687L,57688L,57689L,57690L,57691L,57692L,57693L,57694L,
+57695L,57696L,57697L,57698L,57699L,57700L,57701L,57702L,57703L,57704L,
+57705L,57706L,57707L,57708L,57709L,57710L,57711L,57712L,57713L,57714L,
+57715L,57716L,57717L,57718L,57719L,57720L,57721L,57722L,57723L,57724L,
+57725L,57726L,57727L,57728L,57729L,57730L,57731L,57732L,57733L,57734L,
+57735L,57736L,57737L,57738L,57739L,57740L,57741L,57742L,57743L,57744L,
+57745L,57746L,57747L,57748L,57749L,57750L,57751L,57752L,57753L,57754L,
+57755L,57756L,57757L,57758L,57759L,57760L,57761L,57762L,57763L,57764L,
+57765L,57766L,57767L,57768L,57769L,57770L,57771L,57772L,57773L,57774L,
+57775L,57776L,57777L,57778L,57779L,57780L,57781L,57782L,57783L,57784L,
+57785L,57786L,57787L,57788L,57789L,57790L,57791L,57792L,57793L,57794L,
+57795L,57796L,57797L,57798L,57799L,57800L,57801L,57802L,57803L,57804L,
+57805L,57806L,57807L,57808L,57809L,57810L,57811L,57812L,57813L,57814L,
+57815L,57816L,57817L,57818L,57819L,57820L,57821L,57822L,57823L,57824L,
+57825L,57826L,57827L,57828L,57829L,57830L,57831L,57832L,57833L,57834L,
+57835L,57836L,57837L,57838L,57839L,57840L,57841L,57842L,57843L,57844L,
+57845L,57846L,57847L,57848L,57849L,57850L,57851L,57852L,57853L,57854L,
+57855L,57856L,57857L,57858L,57859L,57860L,57861L,57862L,57863L,57864L,
+57865L,57866L,57867L,57868L,57869L,57870L,57871L,57872L,57873L,57874L,
+57875L,57876L,57877L,57878L,57879L,57880L,57881L,57882L,57883L,57884L,
+57885L,57886L,57887L,57888L,57889L,57890L,57891L,57892L,57893L,57894L,
+57895L,57896L,57897L,57898L,57899L,57900L,57901L,57902L,57903L,57904L,
+57905L,57906L,57907L,57908L,57909L,57910L,57911L,57912L,57913L,57914L,
+57915L,57916L,57917L,57918L,57919L,57920L,57921L,57922L,57923L,57924L,
+57925L,57926L,57927L,57928L,57929L,57930L,57931L,57932L,57933L,57934L,
+57935L,57936L,57937L,57938L,57939L,57940L,57941L,57942L,57943L,57944L,
+57945L,57946L,57947L,57948L,57949L,57950L,57951L,57952L,57953L,57954L,
+57955L,57956L,57957L,57958L,57959L,57960L,57961L,57962L,57963L,57964L,
+57965L,57966L,57967L,57968L,57969L,57970L,57971L,57972L,57973L,57974L,
+57975L,57976L,57977L,57978L,57979L,57980L,57981L,57982L,57983L,57984L,
+57985L,57986L,57987L,57988L,57989L,57990L,57991L,57992L,57993L,57994L,
+57995L,57996L,57997L,57998L,57999L,58000L,58001L,58002L,58003L,58004L,
+58005L,58006L,58007L,58008L,58009L,58010L,58011L,58012L,58013L,58014L,
+58015L,58016L,58017L,58018L,58019L,58020L,58021L,58022L,58023L,58024L,
+58025L,58026L,58027L,58028L,58029L,58030L,58031L,58032L,58033L,58034L,
+58035L,58036L,58037L,58038L,58039L,58040L,58041L,58042L,58043L,58044L,
+58045L,58046L,58047L,58048L,58049L,58050L,58051L,58052L,58053L,58054L,
+58055L,58056L,58057L,58058L,58059L,58060L,58061L,58062L,58063L,58064L,
+58065L,58066L,58067L,58068L,58069L,58070L,58071L,58072L,58073L,58074L,
+58075L,58076L,58077L,58078L,58079L,58080L,58081L,58082L,58083L,58084L,
+58085L,58086L,58087L,58088L,58089L,58090L,58091L,58092L,58093L,58094L,
+58095L,58096L,58097L,58098L,58099L,58100L,58101L,58102L,58103L,58104L,
+58105L,58106L,58107L,58108L,58109L,58110L,58111L,58112L,58113L,58114L,
+58115L,58116L,58117L,58118L,58119L,58120L,58121L,58122L,58123L,58124L,
+58125L,58126L,58127L,58128L,58129L,58130L,58131L,58132L,58133L,58134L,
+58135L,58136L,58137L,58138L,58139L,58140L,58141L,58142L,58143L,58144L,
+58145L,58146L,58147L,58148L,58149L,58150L,58151L,58152L,58153L,58154L,
+58155L,58156L,58157L,58158L,58159L,58160L,58161L,58162L,58163L,58164L,
+58165L,58166L,58167L,58168L,58169L,58170L,58171L,58172L,58173L,58174L,
+58175L,58176L,58177L,58178L,58179L,58180L,58181L,58182L,58183L,58184L,
+58185L,58186L,58187L,58188L,58189L,58190L,58191L,58192L,58193L,58194L,
+58195L,58196L,58197L,58198L,58199L,58200L,58201L,58202L,58203L,58204L,
+58205L,58206L,58207L,58208L,58209L,58210L,58211L,58212L,58213L,58214L,
+58215L,58216L,58217L,58218L,58219L,58220L,58221L,58222L,58223L,58224L,
+58225L,58226L,58227L,58228L,58229L,58230L,58231L,58232L,58233L,58234L,
+58235L,58236L,58237L,58238L,58239L,58240L,58241L,58242L,58243L,58244L,
+58245L,58246L,58247L,58248L,58249L,58250L,58251L,58252L,58253L,58254L,
+58255L,58256L,58257L,58258L,58259L,58260L,58261L,58262L,58263L,58264L,
+58265L,58266L,58267L,58268L,58269L,58270L,58271L,58272L,58273L,58274L,
+58275L,58276L,58277L,58278L,58279L,58280L,58281L,58282L,58283L,58284L,
+58285L,58286L,58287L,58288L,58289L,58290L,58291L,58292L,58293L,58294L,
+58295L,58296L,58297L,58298L,58299L,58300L,58301L,58302L,58303L,58304L,
+58305L,58306L,58307L,58308L,58309L,58310L,58311L,58312L,58313L,58314L,
+58315L,58316L,58317L,58318L,58319L,58320L,58321L,58322L,58323L,58324L,
+58325L,58326L,58327L,58328L,58329L,58330L,58331L,58332L,58333L,58334L,
+58335L,58336L,58337L,58338L,58339L,58340L,58341L,58342L,58343L,58344L,
+58345L,58346L,58347L,58348L,58349L,58350L,58351L,58352L,58353L,58354L,
+58355L,58356L,58357L,58358L,58359L,58360L,58361L,58362L,58363L,58364L,
+58365L,58366L,58367L,58368L,58369L,58370L,58371L,58372L,58373L,58374L,
+58375L,58376L,58377L,58378L,58379L,58380L,58381L,58382L,58383L,58384L,
+58385L,58386L,58387L,58388L,58389L,58390L,58391L,58392L,58393L,58394L,
+58395L,58396L,58397L,58398L,58399L,58400L,58401L,58402L,58403L,58404L,
+58405L,58406L,58407L,58408L,58409L,58410L,58411L,58412L,58413L,58414L,
+58415L,58416L,58417L,58418L,58419L,58420L,58421L,58422L,58423L,58424L,
+58425L,58426L,58427L,58428L,58429L,58430L,58431L,58432L,58433L,58434L,
+58435L,58436L,58437L,58438L,58439L,58440L,58441L,58442L,58443L,58444L,
+58445L,58446L,58447L,58448L,58449L,58450L,58451L,58452L,58453L,58454L,
+58455L,58456L,58457L,58458L,58459L,58460L,58461L,58462L,58463L,58464L,
+58465L,58466L,58467L,58468L,58469L,58470L,58471L,58472L,58473L,58474L,
+58475L,58476L,58477L,58478L,58479L,58480L,58481L,58482L,58483L,58484L,
+58485L,58486L,58487L,58488L,58489L,58490L,58491L,58492L,58493L,58494L,
+58495L,58496L,58497L,58498L,58499L,58500L,58501L,58502L,58503L,58504L,
+58505L,58506L,58507L,58508L,58509L,58510L,58511L,58512L,58513L,58514L,
+58515L,58516L,58517L,58518L,58519L,58520L,58521L,58522L,58523L,58524L,
+58525L,58526L,58527L,58528L,58529L,58530L,58531L,58532L,58533L,58534L,
+58535L,58536L,58537L,58538L,58539L,58540L,58541L,58542L,58543L,58544L,
+58545L,58546L,58547L,58548L,58549L,58550L,58551L,58552L,58553L,58554L,
+58555L,58556L,58557L,58558L,58559L,58560L,58561L,58562L,58563L,58564L,
+58565L,58566L,58567L,58568L,58569L,58570L,58571L,58572L,58573L,58574L,
+58575L,58576L,58577L,58578L,58579L,58580L,58581L,58582L,58583L,58584L,
+58585L,58586L,58587L,58588L,58589L,58590L,58591L,58592L,58593L,58594L,
+58595L,58596L,58597L,58598L,58599L,58600L,58601L,58602L,58603L,58604L,
+58605L,58606L,58607L,58608L,58609L,58610L,58611L,58612L,58613L,58614L,
+58615L,58616L,58617L,58618L,58619L,58620L,58621L,58622L,58623L,58624L,
+58625L,58626L,58627L,58628L,58629L,58630L,58631L,58632L,58633L,58634L,
+58635L,58636L,58637L,58638L,58639L,58640L,58641L,58642L,58643L,58644L,
+58645L,58646L,58647L,58648L,58649L,58650L,58651L,58652L,58653L,58654L,
+58655L,58656L,58657L,58658L,58659L,58660L,58661L,58662L,58663L,58664L,
+58665L,58666L,58667L,58668L,58669L,58670L,58671L,58672L,58673L,58674L,
+58675L,58676L,58677L,58678L,58679L,58680L,58681L,58682L,58683L,58684L,
+58685L,58686L,58687L,58688L,58689L,58690L,58691L,58692L,58693L,58694L,
+58695L,58696L,58697L,58698L,58699L,58700L,58701L,58702L,58703L,58704L,
+58705L,58706L,58707L,58708L,58709L,58710L,58711L,58712L,58713L,58714L,
+58715L,58716L,58717L,58718L,58719L,58720L,58721L,58722L,58723L,58724L,
+58725L,58726L,58727L,58728L,58729L,58730L,58731L,58732L,58733L,58734L,
+58735L,58736L,58737L,58738L,58739L,58740L,58741L,58742L,58743L,58744L,
+58745L,58746L,58747L,58748L,58749L,58750L,58751L,58752L,58753L,58754L,
+58755L,58756L,58757L,58758L,58759L,58760L,58761L,58762L,58763L,58764L,
+58765L,58766L,58767L,58768L,58769L,58770L,58771L,58772L,58773L,58774L,
+58775L,58776L,58777L,58778L,58779L,58780L,58781L,58782L,58783L,58784L,
+58785L,58786L,58787L,58788L,58789L,58790L,58791L,58792L,58793L,58794L,
+58795L,58796L,58797L,58798L,58799L,58800L,58801L,58802L,58803L,58804L,
+58805L,58806L,58807L,58808L,58809L,58810L,58811L,58812L,58813L,58814L,
+58815L,58816L,58817L,58818L,58819L,58820L,58821L,58822L,58823L,58824L,
+58825L,58826L,58827L,58828L,58829L,58830L,58831L,58832L,58833L,58834L,
+58835L,58836L,58837L,58838L,58839L,58840L,58841L,58842L,58843L,58844L,
+58845L,58846L,58847L,58848L,58849L,58850L,58851L,58852L,58853L,58854L,
+58855L,58856L,58857L,58858L,58859L,58860L,58861L,58862L,58863L,58864L,
+58865L,58866L,58867L,58868L,58869L,58870L,58871L,58872L,58873L,58874L,
+58875L,58876L,58877L,58878L,58879L,58880L,58881L,58882L,58883L,58884L,
+58885L,58886L,58887L,58888L,58889L,58890L,58891L,58892L,58893L,58894L,
+58895L,58896L,58897L,58898L,58899L,58900L,58901L,58902L,58903L,58904L,
+58905L,58906L,58907L,58908L,58909L,58910L,58911L,58912L,58913L,58914L,
+58915L,58916L,58917L,58918L,58919L,58920L,58921L,58922L,58923L,58924L,
+58925L,58926L,58927L,58928L,58929L,58930L,58931L,58932L,58933L,58934L,
+58935L,58936L,58937L,58938L,58939L,58940L,58941L,58942L,58943L,58944L,
+58945L,58946L,58947L,58948L,58949L,58950L,58951L,58952L,58953L,58954L,
+58955L,58956L,58957L,58958L,58959L,58960L,58961L,58962L,58963L,58964L,
+58965L,58966L,58967L,58968L,58969L,58970L,58971L,58972L,58973L,58974L,
+58975L,58976L,58977L,58978L,58979L,58980L,58981L,58982L,58983L,58984L,
+58985L,58986L,58987L,58988L,58989L,58990L,58991L,58992L,58993L,58994L,
+58995L,58996L,58997L,58998L,58999L,59000L,59001L,59002L,59003L,59004L,
+59005L,59006L,59007L,59008L,59009L,59010L,59011L,59012L,59013L,59014L,
+59015L,59016L,59017L,59018L,59019L,59020L,59021L,59022L,59023L,59024L,
+59025L,59026L,59027L,59028L,59029L,59030L,59031L,59032L,59033L,59034L,
+59035L,59036L,59037L,59038L,59039L,59040L,59041L,59042L,59043L,59044L,
+59045L,59046L,59047L,59048L,59049L,59050L,59051L,59052L,59053L,59054L,
+59055L,59056L,59057L,59058L,59059L,59060L,59061L,59062L,59063L,59064L,
+59065L,59066L,59067L,59068L,59069L,59070L,59071L,59072L,59073L,59074L,
+59075L,59076L,59077L,59078L,59079L,59080L,59081L,59082L,59083L,59084L,
+59085L,59086L,59087L,59088L,59089L,59090L,59091L,59092L,59093L,59094L,
+59095L,59096L,59097L,59098L,59099L,59100L,59101L,59102L,59103L,59104L,
+59105L,59106L,59107L,59108L,59109L,59110L,59111L,59112L,59113L,59114L,
+59115L,59116L,59117L,59118L,59119L,59120L,59121L,59122L,59123L,59124L,
+59125L,59126L,59127L,59128L,59129L,59130L,59131L,59132L,59133L,59134L,
+59135L,59136L,59137L,59138L,59139L,59140L,59141L,59142L,59143L,59144L,
+59145L,59146L,59147L,59148L,59149L,59150L,59151L,59152L,59153L,59154L,
+59155L,59156L,59157L,59158L,59159L,59160L,59161L,59162L,59163L,59164L,
+59165L,59166L,59167L,59168L,59169L,59170L,59171L,59172L,59173L,59174L,
+59175L,59176L,59177L,59178L,59179L,59180L,59181L,59182L,59183L,59184L,
+59185L,59186L,59187L,59188L,59189L,59190L,59191L,59192L,59193L,59194L,
+59195L,59196L,59197L,59198L,59199L,59200L,59201L,59202L,59203L,59204L,
+59205L,59206L,59207L,59208L,59209L,59210L,59211L,59212L,59213L,59214L,
+59215L,59216L,59217L,59218L,59219L,59220L,59221L,59222L,59223L,59224L,
+59225L,59226L,59227L,59228L,59229L,59230L,59231L,59232L,59233L,59234L,
+59235L,59236L,59237L,59238L,59239L,59240L,59241L,59242L,59243L,59244L,
+59245L,59246L,59247L,59248L,59249L,59250L,59251L,59252L,59253L,59254L,
+59255L,59256L,59257L,59258L,59259L,59260L,59261L,59262L,59263L,59264L,
+59265L,59266L,59267L,59268L,59269L,59270L,59271L,59272L,59273L,59274L,
+59275L,59276L,59277L,59278L,59279L,59280L,59281L,59282L,59283L,59284L,
+59285L,59286L,59287L,59288L,59289L,59290L,59291L,59292L,59293L,59294L,
+59295L,59296L,59297L,59298L,59299L,59300L,59301L,59302L,59303L,59304L,
+59305L,59306L,59307L,59308L,59309L,59310L,59311L,59312L,59313L,59314L,
+59315L,59316L,59317L,59318L,59319L,59320L,59321L,59322L,59323L,59324L,
+59325L,59326L,59327L,59328L,59329L,59330L,59331L,59332L,59333L,59334L,
+59335L,59336L,59337L,59338L,59339L,59340L,59341L,59342L,59343L,59344L,
+59345L,59346L,59347L,59348L,59349L,59350L,59351L,59352L,59353L,59354L,
+59355L,59356L,59357L,59358L,59359L,59360L,59361L,59362L,59363L,59364L,
+59365L,59366L,59367L,59368L,59369L,59370L,59371L,59372L,59373L,59374L,
+59375L,59376L,59377L,59378L,59379L,59380L,59381L,59382L,59383L,59384L,
+59385L,59386L,59387L,59388L,59389L,59390L,59391L,59392L,59393L,59394L,
+59395L,59396L,59397L,59398L,59399L,59400L,59401L,59402L,59403L,59404L,
+59405L,59406L,59407L,59408L,59409L,59410L,59411L,59412L,59413L,59414L,
+59415L,59416L,59417L,59418L,59419L,59420L,59421L,59422L,59423L,59424L,
+59425L,59426L,59427L,59428L,59429L,59430L,59431L,59432L,59433L,59434L,
+59435L,59436L,59437L,59438L,59439L,59440L,59441L,59442L,59443L,59444L,
+59445L,59446L,59447L,59448L,59449L,59450L,59451L,59452L,59453L,59454L,
+59455L,59456L,59457L,59458L,59459L,59460L,59461L,59462L,59463L,59464L,
+59465L,59466L,59467L,59468L,59469L,59470L,59471L,59472L,59473L,59474L,
+59475L,59476L,59477L,59478L,59479L,59480L,59481L,59482L,59483L,59484L,
+59485L,59486L,59487L,59488L,59489L,59490L,59491L,59492L,59493L,59494L,
+59495L,59496L,59497L,59498L,59499L,59500L,59501L,59502L,59503L,59504L,
+59505L,59506L,59507L,59508L,59509L,59510L,59511L,59512L,59513L,59514L,
+59515L,59516L,59517L,59518L,59519L,59520L,59521L,59522L,59523L,59524L,
+59525L,59526L,59527L,59528L,59529L,59530L,59531L,59532L,59533L,59534L,
+59535L,59536L,59537L,59538L,59539L,59540L,59541L,59542L,59543L,59544L,
+59545L,59546L,59547L,59548L,59549L,59550L,59551L,59552L,59553L,59554L,
+59555L,59556L,59557L,59558L,59559L,59560L,59561L,59562L,59563L,59564L,
+59565L,59566L,59567L,59568L,59569L,59570L,59571L,59572L,59573L,59574L,
+59575L,59576L,59577L,59578L,59579L,59580L,59581L,59582L,59583L,59584L,
+59585L,59586L,59587L,59588L,59589L,59590L,59591L,59592L,59593L,59594L,
+59595L,59596L,59597L,59598L,59599L,59600L,59601L,59602L,59603L,59604L,
+59605L,59606L,59607L,59608L,59609L,59610L,59611L,59612L,59613L,59614L,
+59615L,59616L,59617L,59618L,59619L,59620L,59621L,59622L,59623L,59624L,
+59625L,59626L,59627L,59628L,59629L,59630L,59631L,59632L,59633L,59634L,
+59635L,59636L,59637L,59638L,59639L,59640L,59641L,59642L,59643L,59644L,
+59645L,59646L,59647L,59648L,59649L,59650L,59651L,59652L,59653L,59654L,
+59655L,59656L,59657L,59658L,59659L,59660L,59661L,59662L,59663L,59664L,
+59665L,59666L,59667L,59668L,59669L,59670L,59671L,59672L,59673L,59674L,
+59675L,59676L,59677L,59678L,59679L,59680L,59681L,59682L,59683L,59684L,
+59685L,59686L,59687L,59688L,59689L,59690L,59691L,59692L,59693L,59694L,
+59695L,59696L,59697L,59698L,59699L,59700L,59701L,59702L,59703L,59704L,
+59705L,59706L,59707L,59708L,59709L,59710L,59711L,59712L,59713L,59714L,
+59715L,59716L,59717L,59718L,59719L,59720L,59721L,59722L,59723L,59724L,
+59725L,59726L,59727L,59728L,59729L,59730L,59731L,59732L,59733L,59734L,
+59735L,59736L,59737L,59738L,59739L,59740L,59741L,59742L,59743L,59744L,
+59745L,59746L,59747L,59748L,59749L,59750L,59751L,59752L,59753L,59754L,
+59755L,59756L,59757L,59758L,59759L,59760L,59761L,59762L,59763L,59764L,
+59765L,59766L,59767L,59768L,59769L,59770L,59771L,59772L,59773L,59774L,
+59775L,59776L,59777L,59778L,59779L,59780L,59781L,59782L,59783L,59784L,
+59785L,59786L,59787L,59788L,59789L,59790L,59791L,59792L,59793L,59794L,
+59795L,59796L,59797L,59798L,59799L,59800L,59801L,59802L,59803L,59804L,
+59805L,59806L,59807L,59808L,59809L,59810L,59811L,59812L,59813L,59814L,
+59815L,59816L,59817L,59818L,59819L,59820L,59821L,59822L,59823L,59824L,
+59825L,59826L,59827L,59828L,59829L,59830L,59831L,59832L,59833L,59834L,
+59835L,59836L,59837L,59838L,59839L,59840L,59841L,59842L,59843L,59844L,
+59845L,59846L,59847L,59848L,59849L,59850L,59851L,59852L,59853L,59854L,
+59855L,59856L,59857L,59858L,59859L,59860L,59861L,59862L,59863L,59864L,
+59865L,59866L,59867L,59868L,59869L,59870L,59871L,59872L,59873L,59874L,
+59875L,59876L,59877L,59878L,59879L,59880L,59881L,59882L,59883L,59884L,
+59885L,59886L,59887L,59888L,59889L,59890L,59891L,59892L,59893L,59894L,
+59895L,59896L,59897L,59898L,59899L,59900L,59901L,59902L,59903L,59904L,
+59905L,59906L,59907L,59908L,59909L,59910L,59911L,59912L,59913L,59914L,
+59915L,59916L,59917L,59918L,59919L,59920L,59921L,59922L,59923L,59924L,
+59925L,59926L,59927L,59928L,59929L,59930L,59931L,59932L,59933L,59934L,
+59935L,59936L,59937L,59938L,59939L,59940L,59941L,59942L,59943L,59944L,
+59945L,59946L,59947L,59948L,59949L,59950L,59951L,59952L,59953L,59954L,
+59955L,59956L,59957L,59958L,59959L,59960L,59961L,59962L,59963L,59964L,
+59965L,59966L,59967L,59968L,59969L,59970L,59971L,59972L,59973L,59974L,
+59975L,59976L,59977L,59978L,59979L,59980L,59981L,59982L,59983L,59984L,
+59985L,59986L,59987L,59988L,59989L,59990L,59991L,59992L,59993L,59994L,
+59995L,59996L,59997L,59998L,59999L,60000L,60001L,60002L,60003L,60004L,
+60005L,60006L,60007L,60008L,60009L,60010L,60011L,60012L,60013L,60014L,
+60015L,60016L,60017L,60018L,60019L,60020L,60021L,60022L,60023L,60024L,
+60025L,60026L,60027L,60028L,60029L,60030L,60031L,60032L,60033L,60034L,
+60035L,60036L,60037L,60038L,60039L,60040L,60041L,60042L,60043L,60044L,
+60045L,60046L,60047L,60048L,60049L,60050L,60051L,60052L,60053L,60054L,
+60055L,60056L,60057L,60058L,60059L,60060L,60061L,60062L,60063L,60064L,
+60065L,60066L,60067L,60068L,60069L,60070L,60071L,60072L,60073L,60074L,
+60075L,60076L,60077L,60078L,60079L,60080L,60081L,60082L,60083L,60084L,
+60085L,60086L,60087L,60088L,60089L,60090L,60091L,60092L,60093L,60094L,
+60095L,60096L,60097L,60098L,60099L,60100L,60101L,60102L,60103L,60104L,
+60105L,60106L,60107L,60108L,60109L,60110L,60111L,60112L,60113L,60114L,
+60115L,60116L,60117L,60118L,60119L,60120L,60121L,60122L,60123L,60124L,
+60125L,60126L,60127L,60128L,60129L,60130L,60131L,60132L,60133L,60134L,
+60135L,60136L,60137L,60138L,60139L,60140L,60141L,60142L,60143L,60144L,
+60145L,60146L,60147L,60148L,60149L,60150L,60151L,60152L,60153L,60154L,
+60155L,60156L,60157L,60158L,60159L,60160L,60161L,60162L,60163L,60164L,
+60165L,60166L,60167L,60168L,60169L,60170L,60171L,60172L,60173L,60174L,
+60175L,60176L,60177L,60178L,60179L,60180L,60181L,60182L,60183L,60184L,
+60185L,60186L,60187L,60188L,60189L,60190L,60191L,60192L,60193L,60194L,
+60195L,60196L,60197L,60198L,60199L,60200L,60201L,60202L,60203L,60204L,
+60205L,60206L,60207L,60208L,60209L,60210L,60211L,60212L,60213L,60214L,
+60215L,60216L,60217L,60218L,60219L,60220L,60221L,60222L,60223L,60224L,
+60225L,60226L,60227L,60228L,60229L,60230L,60231L,60232L,60233L,60234L,
+60235L,60236L,60237L,60238L,60239L,60240L,60241L,60242L,60243L,60244L,
+60245L,60246L,60247L,60248L,60249L,60250L,60251L,60252L,60253L,60254L,
+60255L,60256L,60257L,60258L,60259L,60260L,60261L,60262L,60263L,60264L,
+60265L,60266L,60267L,60268L,60269L,60270L,60271L,60272L,60273L,60274L,
+60275L,60276L,60277L,60278L,60279L,60280L,60281L,60282L,60283L,60284L,
+60285L,60286L,60287L,60288L,60289L,60290L,60291L,60292L,60293L,60294L,
+60295L,60296L,60297L,60298L,60299L,60300L,60301L,60302L,60303L,60304L,
+60305L,60306L,60307L,60308L,60309L,60310L,60311L,60312L,60313L,60314L,
+60315L,60316L,60317L,60318L,60319L,60320L,60321L,60322L,60323L,60324L,
+60325L,60326L,60327L,60328L,60329L,60330L,60331L,60332L,60333L,60334L,
+60335L,60336L,60337L,60338L,60339L,60340L,60341L,60342L,60343L,60344L,
+60345L,60346L,60347L,60348L,60349L,60350L,60351L,60352L,60353L,60354L,
+60355L,60356L,60357L,60358L,60359L,60360L,60361L,60362L,60363L,60364L,
+60365L,60366L,60367L,60368L,60369L,60370L,60371L,60372L,60373L,60374L,
+60375L,60376L,60377L,60378L,60379L,60380L,60381L,60382L,60383L,60384L,
+60385L,60386L,60387L,60388L,60389L,60390L,60391L,60392L,60393L,60394L,
+60395L,60396L,60397L,60398L,60399L,60400L,60401L,60402L,60403L,60404L,
+60405L,60406L,60407L,60408L,60409L,60410L,60411L,60412L,60413L,60414L,
+60415L,60416L,60417L,60418L,60419L,60420L,60421L,60422L,60423L,60424L,
+60425L,60426L,60427L,60428L,60429L,60430L,60431L,60432L,60433L,60434L,
+60435L,60436L,60437L,60438L,60439L,60440L,60441L,60442L,60443L,60444L,
+60445L,60446L,60447L,60448L,60449L,60450L,60451L,60452L,60453L,60454L,
+60455L,60456L,60457L,60458L,60459L,60460L,60461L,60462L,60463L,60464L,
+60465L,60466L,60467L,60468L,60469L,60470L,60471L,60472L,60473L,60474L,
+60475L,60476L,60477L,60478L,60479L,60480L,60481L,60482L,60483L,60484L,
+60485L,60486L,60487L,60488L,60489L,60490L,60491L,60492L,60493L,60494L,
+60495L,60496L,60497L,60498L,60499L,60500L,60501L,60502L,60503L,60504L,
+60505L,60506L,60507L,60508L,60509L,60510L,60511L,60512L,60513L,60514L,
+60515L,60516L,60517L,60518L,60519L,60520L,60521L,60522L,60523L,60524L,
+60525L,60526L,60527L,60528L,60529L,60530L,60531L,60532L,60533L,60534L,
+60535L,60536L,60537L,60538L,60539L,60540L,60541L,60542L,60543L,60544L,
+60545L,60546L,60547L,60548L,60549L,60550L,60551L,60552L,60553L,60554L,
+60555L,60556L,60557L,60558L,60559L,60560L,60561L,60562L,60563L,60564L,
+60565L,60566L,60567L,60568L,60569L,60570L,60571L,60572L,60573L,60574L,
+60575L,60576L,60577L,60578L,60579L,60580L,60581L,60582L,60583L,60584L,
+60585L,60586L,60587L,60588L,60589L,60590L,60591L,60592L,60593L,60594L,
+60595L,60596L,60597L,60598L,60599L,60600L,60601L,60602L,60603L,60604L,
+60605L,60606L,60607L,60608L,60609L,60610L,60611L,60612L,60613L,60614L,
+60615L,60616L,60617L,60618L,60619L,60620L,60621L,60622L,60623L,60624L,
+60625L,60626L,60627L,60628L,60629L,60630L,60631L,60632L,60633L,60634L,
+60635L,60636L,60637L,60638L,60639L,60640L,60641L,60642L,60643L,60644L,
+60645L,60646L,60647L,60648L,60649L,60650L,60651L,60652L,60653L,60654L,
+60655L,60656L,60657L,60658L,60659L,60660L,60661L,60662L,60663L,60664L,
+60665L,60666L,60667L,60668L,60669L,60670L,60671L,60672L,60673L,60674L,
+60675L,60676L,60677L,60678L,60679L,60680L,60681L,60682L,60683L,60684L,
+60685L,60686L,60687L,60688L,60689L,60690L,60691L,60692L,60693L,60694L,
+60695L,60696L,60697L,60698L,60699L,60700L,60701L,60702L,60703L,60704L,
+60705L,60706L,60707L,60708L,60709L,60710L,60711L,60712L,60713L,60714L,
+60715L,60716L,60717L,60718L,60719L,60720L,60721L,60722L,60723L,60724L,
+60725L,60726L,60727L,60728L,60729L,60730L,60731L,60732L,60733L,60734L,
+60735L,60736L,60737L,60738L,60739L,60740L,60741L,60742L,60743L,60744L,
+60745L,60746L,60747L,60748L,60749L,60750L,60751L,60752L,60753L,60754L,
+60755L,60756L,60757L,60758L,60759L,60760L,60761L,60762L,60763L,60764L,
+60765L,60766L,60767L,60768L,60769L,60770L,60771L,60772L,60773L,60774L,
+60775L,60776L,60777L,60778L,60779L,60780L,60781L,60782L,60783L,60784L,
+60785L,60786L,60787L,60788L,60789L,60790L,60791L,60792L,60793L,60794L,
+60795L,60796L,60797L,60798L,60799L,60800L,60801L,60802L,60803L,60804L,
+60805L,60806L,60807L,60808L,60809L,60810L,60811L,60812L,60813L,60814L,
+60815L,60816L,60817L,60818L,60819L,60820L,60821L,60822L,60823L,60824L,
+60825L,60826L,60827L,60828L,60829L,60830L,60831L,60832L,60833L,60834L,
+60835L,60836L,60837L,60838L,60839L,60840L,60841L,60842L,60843L,60844L,
+60845L,60846L,60847L,60848L,60849L,60850L,60851L,60852L,60853L,60854L,
+60855L,60856L,60857L,60858L,60859L,60860L,60861L,60862L,60863L,60864L,
+60865L,60866L,60867L,60868L,60869L,60870L,60871L,60872L,60873L,60874L,
+60875L,60876L,60877L,60878L,60879L,60880L,60881L,60882L,60883L,60884L,
+60885L,60886L,60887L,60888L,60889L,60890L,60891L,60892L,60893L,60894L,
+60895L,60896L,60897L,60898L,60899L,60900L,60901L,60902L,60903L,60904L,
+60905L,60906L,60907L,60908L,60909L,60910L,60911L,60912L,60913L,60914L,
+60915L,60916L,60917L,60918L,60919L,60920L,60921L,60922L,60923L,60924L,
+60925L,60926L,60927L,60928L,60929L,60930L,60931L,60932L,60933L,60934L,
+60935L,60936L,60937L,60938L,60939L,60940L,60941L,60942L,60943L,60944L,
+60945L,60946L,60947L,60948L,60949L,60950L,60951L,60952L,60953L,60954L,
+60955L,60956L,60957L,60958L,60959L,60960L,60961L,60962L,60963L,60964L,
+60965L,60966L,60967L,60968L,60969L,60970L,60971L,60972L,60973L,60974L,
+60975L,60976L,60977L,60978L,60979L,60980L,60981L,60982L,60983L,60984L,
+60985L,60986L,60987L,60988L,60989L,60990L,60991L,60992L,60993L,60994L,
+60995L,60996L,60997L,60998L,60999L,61000L,61001L,61002L,61003L,61004L,
+61005L,61006L,61007L,61008L,61009L,61010L,61011L,61012L,61013L,61014L,
+61015L,61016L,61017L,61018L,61019L,61020L,61021L,61022L,61023L,61024L,
+61025L,61026L,61027L,61028L,61029L,61030L,61031L,61032L,61033L,61034L,
+61035L,61036L,61037L,61038L,61039L,61040L,61041L,61042L,61043L,61044L,
+61045L,61046L,61047L,61048L,61049L,61050L,61051L,61052L,61053L,61054L,
+61055L,61056L,61057L,61058L,61059L,61060L,61061L,61062L,61063L,61064L,
+61065L,61066L,61067L,61068L,61069L,61070L,61071L,61072L,61073L,61074L,
+61075L,61076L,61077L,61078L,61079L,61080L,61081L,61082L,61083L,61084L,
+61085L,61086L,61087L,61088L,61089L,61090L,61091L,61092L,61093L,61094L,
+61095L,61096L,61097L,61098L,61099L,61100L,61101L,61102L,61103L,61104L,
+61105L,61106L,61107L,61108L,61109L,61110L,61111L,61112L,61113L,61114L,
+61115L,61116L,61117L,61118L,61119L,61120L,61121L,61122L,61123L,61124L,
+61125L,61126L,61127L,61128L,61129L,61130L,61131L,61132L,61133L,61134L,
+61135L,61136L,61137L,61138L,61139L,61140L,61141L,61142L,61143L,61144L,
+61145L,61146L,61147L,61148L,61149L,61150L,61151L,61152L,61153L,61154L,
+61155L,61156L,61157L,61158L,61159L,61160L,61161L,61162L,61163L,61164L,
+61165L,61166L,61167L,61168L,61169L,61170L,61171L,61172L,61173L,61174L,
+61175L,61176L,61177L,61178L,61179L,61180L,61181L,61182L,61183L,61184L,
+61185L,61186L,61187L,61188L,61189L,61190L,61191L,61192L,61193L,61194L,
+61195L,61196L,61197L,61198L,61199L,61200L,61201L,61202L,61203L,61204L,
+61205L,61206L,61207L,61208L,61209L,61210L,61211L,61212L,61213L,61214L,
+61215L,61216L,61217L,61218L,61219L,61220L,61221L,61222L,61223L,61224L,
+61225L,61226L,61227L,61228L,61229L,61230L,61231L,61232L,61233L,61234L,
+61235L,61236L,61237L,61238L,61239L,61240L,61241L,61242L,61243L,61244L,
+61245L,61246L,61247L,61248L,61249L,61250L,61251L,61252L,61253L,61254L,
+61255L,61256L,61257L,61258L,61259L,61260L,61261L,61262L,61263L,61264L,
+61265L,61266L,61267L,61268L,61269L,61270L,61271L,61272L,61273L,61274L,
+61275L,61276L,61277L,61278L,61279L,61280L,61281L,61282L,61283L,61284L,
+61285L,61286L,61287L,61288L,61289L,61290L,61291L,61292L,61293L,61294L,
+61295L,61296L,61297L,61298L,61299L,61300L,61301L,61302L,61303L,61304L,
+61305L,61306L,61307L,61308L,61309L,61310L,61311L,61312L,61313L,61314L,
+61315L,61316L,61317L,61318L,61319L,61320L,61321L,61322L,61323L,61324L,
+61325L,61326L,61327L,61328L,61329L,61330L,61331L,61332L,61333L,61334L,
+61335L,61336L,61337L,61338L,61339L,61340L,61341L,61342L,61343L,61344L,
+61345L,61346L,61347L,61348L,61349L,61350L,61351L,61352L,61353L,61354L,
+61355L,61356L,61357L,61358L,61359L,61360L,61361L,61362L,61363L,61364L,
+61365L,61366L,61367L,61368L,61369L,61370L,61371L,61372L,61373L,61374L,
+61375L,61376L,61377L,61378L,61379L,61380L,61381L,61382L,61383L,61384L,
+61385L,61386L,61387L,61388L,61389L,61390L,61391L,61392L,61393L,61394L,
+61395L,61396L,61397L,61398L,61399L,61400L,61401L,61402L,61403L,61404L,
+61405L,61406L,61407L,61408L,61409L,61410L,61411L,61412L,61413L,61414L,
+61415L,61416L,61417L,61418L,61419L,61420L,61421L,61422L,61423L,61424L,
+61425L,61426L,61427L,61428L,61429L,61430L,61431L,61432L,61433L,61434L,
+61435L,61436L,61437L,61438L,61439L,61440L,61441L,61442L,61443L,61444L,
+61445L,61446L,61447L,61448L,61449L,61450L,61451L,61452L,61453L,61454L,
+61455L,61456L,61457L,61458L,61459L,61460L,61461L,61462L,61463L,61464L,
+61465L,61466L,61467L,61468L,61469L,61470L,61471L,61472L,61473L,61474L,
+61475L,61476L,61477L,61478L,61479L,61480L,61481L,61482L,61483L,61484L,
+61485L,61486L,61487L,61488L,61489L,61490L,61491L,61492L,61493L,61494L,
+61495L,61496L,61497L,61498L,61499L,61500L,61501L,61502L,61503L,61504L,
+61505L,61506L,61507L,61508L,61509L,61510L,61511L,61512L,61513L,61514L,
+61515L,61516L,61517L,61518L,61519L,61520L,61521L,61522L,61523L,61524L,
+61525L,61526L,61527L,61528L,61529L,61530L,61531L,61532L,61533L,61534L,
+61535L,61536L,61537L,61538L,61539L,61540L,61541L,61542L,61543L,61544L,
+61545L,61546L,61547L,61548L,61549L,61550L,61551L,61552L,61553L,61554L,
+61555L,61556L,61557L,61558L,61559L,61560L,61561L,61562L,61563L,61564L,
+61565L,61566L,61567L,61568L,61569L,61570L,61571L,61572L,61573L,61574L,
+61575L,61576L,61577L,61578L,61579L,61580L,61581L,61582L,61583L,61584L,
+61585L,61586L,61587L,61588L,61589L,61590L,61591L,61592L,61593L,61594L,
+61595L,61596L,61597L,61598L,61599L,61600L,61601L,61602L,61603L,61604L,
+61605L,61606L,61607L,61608L,61609L,61610L,61611L,61612L,61613L,61614L,
+61615L,61616L,61617L,61618L,61619L,61620L,61621L,61622L,61623L,61624L,
+61625L,61626L,61627L,61628L,61629L,61630L,61631L,61632L,61633L,61634L,
+61635L,61636L,61637L,61638L,61639L,61640L,61641L,61642L,61643L,61644L,
+61645L,61646L,61647L,61648L,61649L,61650L,61651L,61652L,61653L,61654L,
+61655L,61656L,61657L,61658L,61659L,61660L,61661L,61662L,61663L,61664L,
+61665L,61666L,61667L,61668L,61669L,61670L,61671L,61672L,61673L,61674L,
+61675L,61676L,61677L,61678L,61679L,61680L,61681L,61682L,61683L,61684L,
+61685L,61686L,61687L,61688L,61689L,61690L,61691L,61692L,61693L,61694L,
+61695L,61696L,61697L,61698L,61699L,61700L,61701L,61702L,61703L,61704L,
+61705L,61706L,61707L,61708L,61709L,61710L,61711L,61712L,61713L,61714L,
+61715L,61716L,61717L,61718L,61719L,61720L,61721L,61722L,61723L,61724L,
+61725L,61726L,61727L,61728L,61729L,61730L,61731L,61732L,61733L,61734L,
+61735L,61736L,61737L,61738L,61739L,61740L,61741L,61742L,61743L,61744L,
+61745L,61746L,61747L,61748L,61749L,61750L,61751L,61752L,61753L,61754L,
+61755L,61756L,61757L,61758L,61759L,61760L,61761L,61762L,61763L,61764L,
+61765L,61766L,61767L,61768L,61769L,61770L,61771L,61772L,61773L,61774L,
+61775L,61776L,61777L,61778L,61779L,61780L,61781L,61782L,61783L,61784L,
+61785L,61786L,61787L,61788L,61789L,61790L,61791L,61792L,61793L,61794L,
+61795L,61796L,61797L,61798L,61799L,61800L,61801L,61802L,61803L,61804L,
+61805L,61806L,61807L,61808L,61809L,61810L,61811L,61812L,61813L,61814L,
+61815L,61816L,61817L,61818L,61819L,61820L,61821L,61822L,61823L,61824L,
+61825L,61826L,61827L,61828L,61829L,61830L,61831L,61832L,61833L,61834L,
+61835L,61836L,61837L,61838L,61839L,61840L,61841L,61842L,61843L,61844L,
+61845L,61846L,61847L,61848L,61849L,61850L,61851L,61852L,61853L,61854L,
+61855L,61856L,61857L,61858L,61859L,61860L,61861L,61862L,61863L,61864L,
+61865L,61866L,61867L,61868L,61869L,61870L,61871L,61872L,61873L,61874L,
+61875L,61876L,61877L,61878L,61879L,61880L,61881L,61882L,61883L,61884L,
+61885L,61886L,61887L,61888L,61889L,61890L,61891L,61892L,61893L,61894L,
+61895L,61896L,61897L,61898L,61899L,61900L,61901L,61902L,61903L,61904L,
+61905L,61906L,61907L,61908L,61909L,61910L,61911L,61912L,61913L,61914L,
+61915L,61916L,61917L,61918L,61919L,61920L,61921L,61922L,61923L,61924L,
+61925L,61926L,61927L,61928L,61929L,61930L,61931L,61932L,61933L,61934L,
+61935L,61936L,61937L,61938L,61939L,61940L,61941L,61942L,61943L,61944L,
+61945L,61946L,61947L,61948L,61949L,61950L,61951L,61952L,61953L,61954L,
+61955L,61956L,61957L,61958L,61959L,61960L,61961L,61962L,61963L,61964L,
+61965L,61966L,61967L,61968L,61969L,61970L,61971L,61972L,61973L,61974L,
+61975L,61976L,61977L,61978L,61979L,61980L,61981L,61982L,61983L,61984L,
+61985L,61986L,61987L,61988L,61989L,61990L,61991L,61992L,61993L,61994L,
+61995L,61996L,61997L,61998L,61999L,62000L,62001L,62002L,62003L,62004L,
+62005L,62006L,62007L,62008L,62009L,62010L,62011L,62012L,62013L,62014L,
+62015L,62016L,62017L,62018L,62019L,62020L,62021L,62022L,62023L,62024L,
+62025L,62026L,62027L,62028L,62029L,62030L,62031L,62032L,62033L,62034L,
+62035L,62036L,62037L,62038L,62039L,62040L,62041L,62042L,62043L,62044L,
+62045L,62046L,62047L,62048L,62049L,62050L,62051L,62052L,62053L,62054L,
+62055L,62056L,62057L,62058L,62059L,62060L,62061L,62062L,62063L,62064L,
+62065L,62066L,62067L,62068L,62069L,62070L,62071L,62072L,62073L,62074L,
+62075L,62076L,62077L,62078L,62079L,62080L,62081L,62082L,62083L,62084L,
+62085L,62086L,62087L,62088L,62089L,62090L,62091L,62092L,62093L,62094L,
+62095L,62096L,62097L,62098L,62099L,62100L,62101L,62102L,62103L,62104L,
+62105L,62106L,62107L,62108L,62109L,62110L,62111L,62112L,62113L,62114L,
+62115L,62116L,62117L,62118L,62119L,62120L,62121L,62122L,62123L,62124L,
+62125L,62126L,62127L,62128L,62129L,62130L,62131L,62132L,62133L,62134L,
+62135L,62136L,62137L,62138L,62139L,62140L,62141L,62142L,62143L,62144L,
+62145L,62146L,62147L,62148L,62149L,62150L,62151L,62152L,62153L,62154L,
+62155L,62156L,62157L,62158L,62159L,62160L,62161L,62162L,62163L,62164L,
+62165L,62166L,62167L,62168L,62169L,62170L,62171L,62172L,62173L,62174L,
+62175L,62176L,62177L,62178L,62179L,62180L,62181L,62182L,62183L,62184L,
+62185L,62186L,62187L,62188L,62189L,62190L,62191L,62192L,62193L,62194L,
+62195L,62196L,62197L,62198L,62199L,62200L,62201L,62202L,62203L,62204L,
+62205L,62206L,62207L,62208L,62209L,62210L,62211L,62212L,62213L,62214L,
+62215L,62216L,62217L,62218L,62219L,62220L,62221L,62222L,62223L,62224L,
+62225L,62226L,62227L,62228L,62229L,62230L,62231L,62232L,62233L,62234L,
+62235L,62236L,62237L,62238L,62239L,62240L,62241L,62242L,62243L,62244L,
+62245L,62246L,62247L,62248L,62249L,62250L,62251L,62252L,62253L,62254L,
+62255L,62256L,62257L,62258L,62259L,62260L,62261L,62262L,62263L,62264L,
+62265L,62266L,62267L,62268L,62269L,62270L,62271L,62272L,62273L,62274L,
+62275L,62276L,62277L,62278L,62279L,62280L,62281L,62282L,62283L,62284L,
+62285L,62286L,62287L,62288L,62289L,62290L,62291L,62292L,62293L,62294L,
+62295L,62296L,62297L,62298L,62299L,62300L,62301L,62302L,62303L,62304L,
+62305L,62306L,62307L,62308L,62309L,62310L,62311L,62312L,62313L,62314L,
+62315L,62316L,62317L,62318L,62319L,62320L,62321L,62322L,62323L,62324L,
+62325L,62326L,62327L,62328L,62329L,62330L,62331L,62332L,62333L,62334L,
+62335L,62336L,62337L,62338L,62339L,62340L,62341L,62342L,62343L,62344L,
+62345L,62346L,62347L,62348L,62349L,62350L,62351L,62352L,62353L,62354L,
+62355L,62356L,62357L,62358L,62359L,62360L,62361L,62362L,62363L,62364L,
+62365L,62366L,62367L,62368L,62369L,62370L,62371L,62372L,62373L,62374L,
+62375L,62376L,62377L,62378L,62379L,62380L,62381L,62382L,62383L,62384L,
+62385L,62386L,62387L,62388L,62389L,62390L,62391L,62392L,62393L,62394L,
+62395L,62396L,62397L,62398L,62399L,62400L,62401L,62402L,62403L,62404L,
+62405L,62406L,62407L,62408L,62409L,62410L,62411L,62412L,62413L,62414L,
+62415L,62416L,62417L,62418L,62419L,62420L,62421L,62422L,62423L,62424L,
+62425L,62426L,62427L,62428L,62429L,62430L,62431L,62432L,62433L,62434L,
+62435L,62436L,62437L,62438L,62439L,62440L,62441L,62442L,62443L,62444L,
+62445L,62446L,62447L,62448L,62449L,62450L,62451L,62452L,62453L,62454L,
+62455L,62456L,62457L,62458L,62459L,62460L,62461L,62462L,62463L,62464L,
+62465L,62466L,62467L,62468L,62469L,62470L,62471L,62472L,62473L,62474L,
+62475L,62476L,62477L,62478L,62479L,62480L,62481L,62482L,62483L,62484L,
+62485L,62486L,62487L,62488L,62489L,62490L,62491L,62492L,62493L,62494L,
+62495L,62496L,62497L,62498L,62499L,62500L,62501L,62502L,62503L,62504L,
+62505L,62506L,62507L,62508L,62509L,62510L,62511L,62512L,62513L,62514L,
+62515L,62516L,62517L,62518L,62519L,62520L,62521L,62522L,62523L,62524L,
+62525L,62526L,62527L,62528L,62529L,62530L,62531L,62532L,62533L,62534L,
+62535L,62536L,62537L,62538L,62539L,62540L,62541L,62542L,62543L,62544L,
+62545L,62546L,62547L,62548L,62549L,62550L,62551L,62552L,62553L,62554L,
+62555L,62556L,62557L,62558L,62559L,62560L,62561L,62562L,62563L,62564L,
+62565L,62566L,62567L,62568L,62569L,62570L,62571L,62572L,62573L,62574L,
+62575L,62576L,62577L,62578L,62579L,62580L,62581L,62582L,62583L,62584L,
+62585L,62586L,62587L,62588L,62589L,62590L,62591L,62592L,62593L,62594L,
+62595L,62596L,62597L,62598L,62599L,62600L,62601L,62602L,62603L,62604L,
+62605L,62606L,62607L,62608L,62609L,62610L,62611L,62612L,62613L,62614L,
+62615L,62616L,62617L,62618L,62619L,62620L,62621L,62622L,62623L,62624L,
+62625L,62626L,62627L,62628L,62629L,62630L,62631L,62632L,62633L,62634L,
+62635L,62636L,62637L,62638L,62639L,62640L,62641L,62642L,62643L,62644L,
+62645L,62646L,62647L,62648L,62649L,62650L,62651L,62652L,62653L,62654L,
+62655L,62656L,62657L,62658L,62659L,62660L,62661L,62662L,62663L,62664L,
+62665L,62666L,62667L,62668L,62669L,62670L,62671L,62672L,62673L,62674L,
+62675L,62676L,62677L,62678L,62679L,62680L,62681L,62682L,62683L,62684L,
+62685L,62686L,62687L,62688L,62689L,62690L,62691L,62692L,62693L,62694L,
+62695L,62696L,62697L,62698L,62699L,62700L,62701L,62702L,62703L,62704L,
+62705L,62706L,62707L,62708L,62709L,62710L,62711L,62712L,62713L,62714L,
+62715L,62716L,62717L,62718L,62719L,62720L,62721L,62722L,62723L,62724L,
+62725L,62726L,62727L,62728L,62729L,62730L,62731L,62732L,62733L,62734L,
+62735L,62736L,62737L,62738L,62739L,62740L,62741L,62742L,62743L,62744L,
+62745L,62746L,62747L,62748L,62749L,62750L,62751L,62752L,62753L,62754L,
+62755L,62756L,62757L,62758L,62759L,62760L,62761L,62762L,62763L,62764L,
+62765L,62766L,62767L,62768L,62769L,62770L,62771L,62772L,62773L,62774L,
+62775L,62776L,62777L,62778L,62779L,62780L,62781L,62782L,62783L,62784L,
+62785L,62786L,62787L,62788L,62789L,62790L,62791L,62792L,62793L,62794L,
+62795L,62796L,62797L,62798L,62799L,62800L,62801L,62802L,62803L,62804L,
+62805L,62806L,62807L,62808L,62809L,62810L,62811L,62812L,62813L,62814L,
+62815L,62816L,62817L,62818L,62819L,62820L,62821L,62822L,62823L,62824L,
+62825L,62826L,62827L,62828L,62829L,62830L,62831L,62832L,62833L,62834L,
+62835L,62836L,62837L,62838L,62839L,62840L,62841L,62842L,62843L,62844L,
+62845L,62846L,62847L,62848L,62849L,62850L,62851L,62852L,62853L,62854L,
+62855L,62856L,62857L,62858L,62859L,62860L,62861L,62862L,62863L,62864L,
+62865L,62866L,62867L,62868L,62869L,62870L,62871L,62872L,62873L,62874L,
+62875L,62876L,62877L,62878L,62879L,62880L,62881L,62882L,62883L,62884L,
+62885L,62886L,62887L,62888L,62889L,62890L,62891L,62892L,62893L,62894L,
+62895L,62896L,62897L,62898L,62899L,62900L,62901L,62902L,62903L,62904L,
+62905L,62906L,62907L,62908L,62909L,62910L,62911L,62912L,62913L,62914L,
+62915L,62916L,62917L,62918L,62919L,62920L,62921L,62922L,62923L,62924L,
+62925L,62926L,62927L,62928L,62929L,62930L,62931L,62932L,62933L,62934L,
+62935L,62936L,62937L,62938L,62939L,62940L,62941L,62942L,62943L,62944L,
+62945L,62946L,62947L,62948L,62949L,62950L,62951L,62952L,62953L,62954L,
+62955L,62956L,62957L,62958L,62959L,62960L,62961L,62962L,62963L,62964L,
+62965L,62966L,62967L,62968L,62969L,62970L,62971L,62972L,62973L,62974L,
+62975L,62976L,62977L,62978L,62979L,62980L,62981L,62982L,62983L,62984L,
+62985L,62986L,62987L,62988L,62989L,62990L,62991L,62992L,62993L,62994L,
+62995L,62996L,62997L,62998L,62999L,63000L,63001L,63002L,63003L,63004L,
+63005L,63006L,63007L,63008L,63009L,63010L,63011L,63012L,63013L,63014L,
+63015L,63016L,63017L,63018L,63019L,63020L,63021L,63022L,63023L,63024L,
+63025L,63026L,63027L,63028L,63029L,63030L,63031L,63032L,63033L,63034L,
+63035L,63036L,63037L,63038L,63039L,63040L,63041L,63042L,63043L,63044L,
+63045L,63046L,63047L,63048L,63049L,63050L,63051L,63052L,63053L,63054L,
+63055L,63056L,63057L,63058L,63059L,63060L,63061L,63062L,63063L,63064L,
+63065L,63066L,63067L,63068L,63069L,63070L,63071L,63072L,63073L,63074L,
+63075L,63076L,63077L,63078L,63079L,63080L,63081L,63082L,63083L,63084L,
+63085L,63086L,63087L,63088L,63089L,63090L,63091L,63092L,63093L,63094L,
+63095L,63096L,63097L,63098L,63099L,63100L,63101L,63102L,63103L,63104L,
+63105L,63106L,63107L,63108L,63109L,63110L,63111L,63112L,63113L,63114L,
+63115L,63116L,63117L,63118L,63119L,63120L,63121L,63122L,63123L,63124L,
+63125L,63126L,63127L,63128L,63129L,63130L,63131L,63132L,63133L,63134L,
+63135L,63136L,63137L,63138L,63139L,63140L,63141L,63142L,63143L,63144L,
+63145L,63146L,63147L,63148L,63149L,63150L,63151L,63152L,63153L,63154L,
+63155L,63156L,63157L,63158L,63159L,63160L,63161L,63162L,63163L,63164L,
+63165L,63166L,63167L,63168L,63169L,63170L,63171L,63172L,63173L,63174L,
+63175L,63176L,63177L,63178L,63179L,63180L,63181L,63182L,63183L,63184L,
+63185L,63186L,63187L,63188L,63189L,63190L,63191L,63192L,63193L,63194L,
+63195L,63196L,63197L,63198L,63199L,63200L,63201L,63202L,63203L,63204L,
+63205L,63206L,63207L,63208L,63209L,63210L,63211L,63212L,63213L,63214L,
+63215L,63216L,63217L,63218L,63219L,63220L,63221L,63222L,63223L,63224L,
+63225L,63226L,63227L,63228L,63229L,63230L,63231L,63232L,63233L,63234L,
+63235L,63236L,63237L,63238L,63239L,63240L,63241L,63242L,63243L,63244L,
+63245L,63246L,63247L,63248L,63249L,63250L,63251L,63252L,63253L,63254L,
+63255L,63256L,63257L,63258L,63259L,63260L,63261L,63262L,63263L,63264L,
+63265L,63266L,63267L,63268L,63269L,63270L,63271L,63272L,63273L,63274L,
+63275L,63276L,63277L,63278L,63279L,63280L,63281L,63282L,63283L,63284L,
+63285L,63286L,63287L,63288L,63289L,63290L,63291L,63292L,63293L,63294L,
+63295L,63296L,63297L,63298L,63299L,63300L,63301L,63302L,63303L,63304L,
+63305L,63306L,63307L,63308L,63309L,63310L,63311L,63312L,63313L,63314L,
+63315L,63316L,63317L,63318L,63319L,63320L,63321L,63322L,63323L,63324L,
+63325L,63326L,63327L,63328L,63329L,63330L,63331L,63332L,63333L,63334L,
+63335L,63336L,63337L,63338L,63339L,63340L,63341L,63342L,63343L,63344L,
+63345L,63346L,63347L,63348L,63349L,63350L,63351L,63352L,63353L,63354L,
+63355L,63356L,63357L,63358L,63359L,63360L,63361L,63362L,63363L,63364L,
+63365L,63366L,63367L,63368L,63369L,63370L,63371L,63372L,63373L,63374L,
+63375L,63376L,63377L,63378L,63379L,63380L,63381L,63382L,63383L,63384L,
+63385L,63386L,63387L,63388L,63389L,63390L,63391L,63392L,63393L,63394L,
+63395L,63396L,63397L,63398L,63399L,63400L,63401L,63402L,63403L,63404L,
+63405L,63406L,63407L,63408L,63409L,63410L,63411L,63412L,63413L,63414L,
+63415L,63416L,63417L,63418L,63419L,63420L,63421L,63422L,63423L,63424L,
+63425L,63426L,63427L,63428L,63429L,63430L,63431L,63432L,63433L,63434L,
+63435L,63436L,63437L,63438L,63439L,63440L,63441L,63442L,63443L,63444L,
+63445L,63446L,63447L,63448L,63449L,63450L,63451L,63452L,63453L,63454L,
+63455L,63456L,63457L,63458L,63459L,63460L,63461L,63462L,63463L,63464L,
+63465L,63466L,63467L,63468L,63469L,63470L,63471L,63472L,63473L,63474L,
+63475L,63476L,63477L,63478L,63479L,63480L,63481L,63482L,63483L,63484L,
+63485L,63486L,63487L,63488L,63489L,63490L,63491L,63492L,63493L,63494L,
+63495L,63496L,63497L,63498L,63499L,63500L,63501L,63502L,63503L,63504L,
+63505L,63506L,63507L,63508L,63509L,63510L,63511L,63512L,63513L,63514L,
+63515L,63516L,63517L,63518L,63519L,63520L,63521L,63522L,63523L,63524L,
+63525L,63526L,63527L,63528L,63529L,63530L,63531L,63532L,63533L,63534L,
+63535L,63536L,63537L,63538L,63539L,63540L,63541L,63542L,63543L,63544L,
+63545L,63546L,63547L,63548L,63549L,63550L,63551L,63552L,63553L,63554L,
+63555L,63556L,63557L,63558L,63559L,63560L,63561L,63562L,63563L,63564L,
+63565L,63566L,63567L,63568L,63569L,63570L,63571L,63572L,63573L,63574L,
+63575L,63576L,63577L,63578L,63579L,63580L,63581L,63582L,63583L,63584L,
+63585L,63586L,63587L,63588L,63589L,63590L,63591L,63592L,63593L,63594L,
+63595L,63596L,63597L,63598L,63599L,63600L,63601L,63602L,63603L,63604L,
+63605L,63606L,63607L,63608L,63609L,63610L,63611L,63612L,63613L,63614L,
+63615L,63616L,63617L,63618L,63619L,63620L,63621L,63622L,63623L,63624L,
+63625L,63626L,63627L,63628L,63629L,63630L,63631L,63632L,63633L,63634L,
+63635L,63636L,63637L,63638L,63639L,63640L,63641L,63642L,63643L,63644L,
+63645L,63646L,63647L,63648L,63649L,63650L,63651L,63652L,63653L,63654L,
+63655L,63656L,63657L,63658L,63659L,63660L,63661L,63662L,63663L,63664L,
+63665L,63666L,63667L,63668L,63669L,63670L,63671L,63672L,63673L,63674L,
+63675L,63676L,63677L,63678L,63679L,63680L,63681L,63682L,63683L,63684L,
+63685L,63686L,63687L,63688L,63689L,63690L,63691L,63692L,63693L,63694L,
+63695L,63696L,63697L,63698L,63699L,63700L,63701L,63702L,63703L,63704L,
+63705L,63706L,63707L,63708L,63709L,63710L,63711L,63712L,63713L,63714L,
+63715L,63716L,63717L,63718L,63719L,63720L,63721L,63722L,63723L,63724L,
+63725L,63726L,63727L,63728L,63729L,63730L,63731L,63732L,63733L,63734L,
+63735L,63736L,63737L,63738L,63739L,63740L,63741L,63742L,63743L,63744L,
+63745L,63746L,63747L,63748L,63749L,63750L,63751L,63752L,63753L,63754L,
+63755L,63756L,63757L,63758L,63759L,63760L,63761L,63762L,63763L,63764L,
+63765L,63766L,63767L,63768L,63769L,63770L,63771L,63772L,63773L,63774L,
+63775L,63776L,63777L,63778L,63779L,63780L,63781L,63782L,63783L,63784L,
+63785L,63786L,63787L,63788L,63789L,63790L,63791L,63792L,63793L,63794L,
+63795L,63796L,63797L,63798L,63799L,63800L,63801L,63802L,63803L,63804L,
+63805L,63806L,63807L,63808L,63809L,63810L,63811L,63812L,63813L,63814L,
+63815L,63816L,63817L,63818L,63819L,63820L,63821L,63822L,63823L,63824L,
+63825L,63826L,63827L,63828L,63829L,63830L,63831L,63832L,63833L,63834L,
+63835L,63836L,63837L,63838L,63839L,63840L,63841L,63842L,63843L,63844L,
+63845L,63846L,63847L,63848L,63849L,63850L,63851L,63852L,63853L,63854L,
+63855L,63856L,63857L,63858L,63859L,63860L,63861L,63862L,63863L,63864L,
+63865L,63866L,63867L,63868L,63869L,63870L,63871L,63872L,63873L,63874L,
+63875L,63876L,63877L,63878L,63879L,63880L,63881L,63882L,63883L,63884L,
+63885L,63886L,63887L,63888L,63889L,63890L,63891L,63892L,63893L,63894L,
+63895L,63896L,63897L,63898L,63899L,63900L,63901L,63902L,63903L,63904L,
+63905L,63906L,63907L,63908L,63909L,63910L,63911L,63912L,63913L,63914L,
+63915L,63916L,63917L,63918L,63919L,63920L,63921L,63922L,63923L,63924L,
+63925L,63926L,63927L,63928L,63929L,63930L,63931L,63932L,63933L,63934L,
+63935L,63936L,63937L,63938L,63939L,63940L,63941L,63942L,63943L,63944L,
+63945L,63946L,63947L,63948L,63949L,63950L,63951L,63952L,63953L,63954L,
+63955L,63956L,63957L,63958L,63959L,63960L,63961L,63962L,63963L,63964L,
+63965L,63966L,63967L,63968L,63969L,63970L,63971L,63972L,63973L,63974L,
+63975L,63976L,63977L,63978L,63979L,63980L,63981L,63982L,63983L,63984L,
+63985L,63986L,63987L,63988L,63989L,63990L,63991L,63992L,63993L,63994L,
+63995L,63996L,63997L,63998L,63999L,64000L,64001L,64002L,64003L,64004L,
+64005L,64006L,64007L,64008L,64009L,64010L,64011L,64012L,64013L,64014L,
+64015L,64016L,64017L,64018L,64019L,64020L,64021L,64022L,64023L,64024L,
+64025L,64026L,64027L,64028L,64029L,64030L,64031L,64032L,64033L,64034L,
+64035L,64036L,64037L,64038L,64039L,64040L,64041L,64042L,64043L,64044L,
+64045L,64046L,64047L,64048L,64049L,64050L,64051L,64052L,64053L,64054L,
+64055L,64056L,64057L,64058L,64059L,64060L,64061L,64062L,64063L,64064L,
+64065L,64066L,64067L,64068L,64069L,64070L,64071L,64072L,64073L,64074L,
+64075L,64076L,64077L,64078L,64079L,64080L,64081L,64082L,64083L,64084L,
+64085L,64086L,64087L,64088L,64089L,64090L,64091L,64092L,64093L,64094L,
+64095L,64096L,64097L,64098L,64099L,64100L,64101L,64102L,64103L,64104L,
+64105L,64106L,64107L,64108L,64109L,64110L,64111L,64112L,64113L,64114L,
+64115L,64116L,64117L,64118L,64119L,64120L,64121L,64122L,64123L,64124L,
+64125L,64126L,64127L,64128L,64129L,64130L,64131L,64132L,64133L,64134L,
+64135L,64136L,64137L,64138L,64139L,64140L,64141L,64142L,64143L,64144L,
+64145L,64146L,64147L,64148L,64149L,64150L,64151L,64152L,64153L,64154L,
+64155L,64156L,64157L,64158L,64159L,64160L,64161L,64162L,64163L,64164L,
+64165L,64166L,64167L,64168L,64169L,64170L,64171L,64172L,64173L,64174L,
+64175L,64176L,64177L,64178L,64179L,64180L,64181L,64182L,64183L,64184L,
+64185L,64186L,64187L,64188L,64189L,64190L,64191L,64192L,64193L,64194L,
+64195L,64196L,64197L,64198L,64199L,64200L,64201L,64202L,64203L,64204L,
+64205L,64206L,64207L,64208L,64209L,64210L,64211L,64212L,64213L,64214L,
+64215L,64216L,64217L,64218L,64219L,64220L,64221L,64222L,64223L,64224L,
+64225L,64226L,64227L,64228L,64229L,64230L,64231L,64232L,64233L,64234L,
+64235L,64236L,64237L,64238L,64239L,64240L,64241L,64242L,64243L,64244L,
+64245L,64246L,64247L,64248L,64249L,64250L,64251L,64252L,64253L,64254L,
+64255L,64256L,64257L,64258L,64259L,64260L,64261L,64262L,64263L,64264L,
+64265L,64266L,64267L,64268L,64269L,64270L,64271L,64272L,64273L,64274L,
+64275L,64276L,64277L,64278L,64279L,64280L,64281L,64282L,64283L,64284L,
+64285L,64286L,64287L,64288L,64289L,64290L,64291L,64292L,64293L,64294L,
+64295L,64296L,64297L,64298L,64299L,64300L,64301L,64302L,64303L,64304L,
+64305L,64306L,64307L,64308L,64309L,64310L,64311L,64312L,64313L,64314L,
+64315L,64316L,64317L,64318L,64319L,64320L,64321L,64322L,64323L,64324L,
+64325L,64326L,64327L,64328L,64329L,64330L,64331L,64332L,64333L,64334L,
+64335L,64336L,64337L,64338L,64339L,64340L,64341L,64342L,64343L,64344L,
+64345L,64346L,64347L,64348L,64349L,64350L,64351L,64352L,64353L,64354L,
+64355L,64356L,64357L,64358L,64359L,64360L,64361L,64362L,64363L,64364L,
+64365L,64366L,64367L,64368L,64369L,64370L,64371L,64372L,64373L,64374L,
+64375L,64376L,64377L,64378L,64379L,64380L,64381L,64382L,64383L,64384L,
+64385L,64386L,64387L,64388L,64389L,64390L,64391L,64392L,64393L,64394L,
+64395L,64396L,64397L,64398L,64399L,64400L,64401L,64402L,64403L,64404L,
+64405L,64406L,64407L,64408L,64409L,64410L,64411L,64412L,64413L,64414L,
+64415L,64416L,64417L,64418L,64419L,64420L,64421L,64422L,64423L,64424L,
+64425L,64426L,64427L,64428L,64429L,64430L,64431L,64432L,64433L,64434L,
+64435L,64436L,64437L,64438L,64439L,64440L,64441L,64442L,64443L,64444L,
+64445L,64446L,64447L,64448L,64449L,64450L,64451L,64452L,64453L,64454L,
+64455L,64456L,64457L,64458L,64459L,64460L,64461L,64462L,64463L,64464L,
+64465L,64466L,64467L,64468L,64469L,64470L,64471L,64472L,64473L,64474L,
+64475L,64476L,64477L,64478L,64479L,64480L,64481L,64482L,64483L,64484L,
+64485L,64486L,64487L,64488L,64489L,64490L,64491L,64492L,64493L,64494L,
+64495L,64496L,64497L,64498L,64499L,64500L,64501L,64502L,64503L,64504L,
+64505L,64506L,64507L,64508L,64509L,64510L,64511L,64512L,64513L,64514L,
+64515L,64516L,64517L,64518L,64519L,64520L,64521L,64522L,64523L,64524L,
+64525L,64526L,64527L,64528L,64529L,64530L,64531L,64532L,64533L,64534L,
+64535L,64536L,64537L,64538L,64539L,64540L,64541L,64542L,64543L,64544L,
+64545L,64546L,64547L,64548L,64549L,64550L,64551L,64552L,64553L,64554L,
+64555L,64556L,64557L,64558L,64559L,64560L,64561L,64562L,64563L,64564L,
+64565L,64566L,64567L,64568L,64569L,64570L,64571L,64572L,64573L,64574L,
+64575L,64576L,64577L,64578L,64579L,64580L,64581L,64582L,64583L,64584L,
+64585L,64586L,64587L,64588L,64589L,64590L,64591L,64592L,64593L,64594L,
+64595L,64596L,64597L,64598L,64599L,64600L,64601L,64602L,64603L,64604L,
+64605L,64606L,64607L,64608L,64609L,64610L,64611L,64612L,64613L,64614L,
+64615L,64616L,64617L,64618L,64619L,64620L,64621L,64622L,64623L,64624L,
+64625L,64626L,64627L,64628L,64629L,64630L,64631L,64632L,64633L,64634L,
+64635L,64636L,64637L,64638L,64639L,64640L,64641L,64642L,64643L,64644L,
+64645L,64646L,64647L,64648L,64649L,64650L,64651L,64652L,64653L,64654L,
+64655L,64656L,64657L,64658L,64659L,64660L,64661L,64662L,64663L,64664L,
+64665L,64666L,64667L,64668L,64669L,64670L,64671L,64672L,64673L,64674L,
+64675L,64676L,64677L,64678L,64679L,64680L,64681L,64682L,64683L,64684L,
+64685L,64686L,64687L,64688L,64689L,64690L,64691L,64692L,64693L,64694L,
+64695L,64696L,64697L,64698L,64699L,64700L,64701L,64702L,64703L,64704L,
+64705L,64706L,64707L,64708L,64709L,64710L,64711L,64712L,64713L,64714L,
+64715L,64716L,64717L,64718L,64719L,64720L,64721L,64722L,64723L,64724L,
+64725L,64726L,64727L,64728L,64729L,64730L,64731L,64732L,64733L,64734L,
+64735L,64736L,64737L,64738L,64739L,64740L,64741L,64742L,64743L,64744L,
+64745L,64746L,64747L,64748L,64749L,64750L,64751L,64752L,64753L,64754L,
+64755L,64756L,64757L,64758L,64759L,64760L,64761L,64762L,64763L,64764L,
+64765L,64766L,64767L,64768L,64769L,64770L,64771L,64772L,64773L,64774L,
+64775L,64776L,64777L,64778L,64779L,64780L,64781L,64782L,64783L,64784L,
+64785L,64786L,64787L,64788L,64789L,64790L,64791L,64792L,64793L,64794L,
+64795L,64796L,64797L,64798L,64799L,64800L,64801L,64802L,64803L,64804L,
+64805L,64806L,64807L,64808L,64809L,64810L,64811L,64812L,64813L,64814L,
+64815L,64816L,64817L,64818L,64819L,64820L,64821L,64822L,64823L,64824L,
+64825L,64826L,64827L,64828L,64829L,64830L,64831L,64832L,64833L,64834L,
+64835L,64836L,64837L,64838L,64839L,64840L,64841L,64842L,64843L,64844L,
+64845L,64846L,64847L,64848L,64849L,64850L,64851L,64852L,64853L,64854L,
+64855L,64856L,64857L,64858L,64859L,64860L,64861L,64862L,64863L,64864L,
+64865L,64866L,64867L,64868L,64869L,64870L,64871L,64872L,64873L,64874L,
+64875L,64876L,64877L,64878L,64879L,64880L,64881L,64882L,64883L,64884L,
+64885L,64886L,64887L,64888L,64889L,64890L,64891L,64892L,64893L,64894L,
+64895L,64896L,64897L,64898L,64899L,64900L,64901L,64902L,64903L,64904L,
+64905L,64906L,64907L,64908L,64909L,64910L,64911L,64912L,64913L,64914L,
+64915L,64916L,64917L,64918L,64919L,64920L,64921L,64922L,64923L,64924L,
+64925L,64926L,64927L,64928L,64929L,64930L,64931L,64932L,64933L,64934L,
+64935L,64936L,64937L,64938L,64939L,64940L,64941L,64942L,64943L,64944L,
+64945L,64946L,64947L,64948L,64949L,64950L,64951L,64952L,64953L,64954L,
+64955L,64956L,64957L,64958L,64959L,64960L,64961L,64962L,64963L,64964L,
+64965L,64966L,64967L,64968L,64969L,64970L,64971L,64972L,64973L,64974L,
+64975L,64976L,64977L,64978L,64979L,64980L,64981L,64982L,64983L,64984L,
+64985L,64986L,64987L,64988L,64989L,64990L,64991L,64992L,64993L,64994L,
+64995L,64996L,64997L,64998L,64999L,65000L,65001L,65002L,65003L,65004L,
+65005L,65006L,65007L,65008L,65009L,65010L,65011L,65012L,65013L,65014L,
+65015L,65016L,65017L,65018L,65019L,65020L,65021L,65022L,65023L,65024L,
+65025L,65026L,65027L,65028L,65029L,65030L,65031L,65032L,65033L,65034L,
+65035L,65036L,65037L,65038L,65039L,65040L,65041L,65042L,65043L,65044L,
+65045L,65046L,65047L,65048L,65049L,65050L,65051L,65052L,65053L,65054L,
+65055L,65056L,65057L,65058L,65059L,65060L,65061L,65062L,65063L,65064L,
+65065L,65066L,65067L,65068L,65069L,65070L,65071L,65072L,65073L,65074L,
+65075L,65076L,65077L,65078L,65079L,65080L,65081L,65082L,65083L,65084L,
+65085L,65086L,65087L,65088L,65089L,65090L,65091L,65092L,65093L,65094L,
+65095L,65096L,65097L,65098L,65099L,65100L,65101L,65102L,65103L,65104L,
+65105L,65106L,65107L,65108L,65109L,65110L,65111L,65112L,65113L,65114L,
+65115L,65116L,65117L,65118L,65119L,65120L,65121L,65122L,65123L,65124L,
+65125L,65126L,65127L,65128L,65129L,65130L,65131L,65132L,65133L,65134L,
+65135L,65136L,65137L,65138L,65139L,65140L,65141L,65142L,65143L,65144L,
+65145L,65146L,65147L,65148L,65149L,65150L,65151L,65152L,65153L,65154L,
+65155L,65156L,65157L,65158L,65159L,65160L,65161L,65162L,65163L,65164L,
+65165L,65166L,65167L,65168L,65169L,65170L,65171L,65172L,65173L,65174L,
+65175L,65176L,65177L,65178L,65179L,65180L,65181L,65182L,65183L,65184L,
+65185L,65186L,65187L,65188L,65189L,65190L,65191L,65192L,65193L,65194L,
+65195L,65196L,65197L,65198L,65199L,65200L,65201L,65202L,65203L,65204L,
+65205L,65206L,65207L,65208L,65209L,65210L,65211L,65212L,65213L,65214L,
+65215L,65216L,65217L,65218L,65219L,65220L,65221L,65222L,65223L,65224L,
+65225L,65226L,65227L,65228L,65229L,65230L,65231L,65232L,65233L,65234L,
+65235L,65236L,65237L,65238L,65239L,65240L,65241L,65242L,65243L,65244L,
+65245L,65246L,65247L,65248L,65249L,65250L,65251L,65252L,65253L,65254L,
+65255L,65256L,65257L,65258L,65259L,65260L,65261L,65262L,65263L,65264L,
+65265L,65266L,65267L,65268L,65269L,65270L,65271L,65272L,65273L,65274L,
+65275L,65276L,65277L,65278L,65279L,65280L,65281L,65282L,65283L,65284L,
+65285L,65286L,65287L,65288L,65289L,65290L,65291L,65292L,65293L,65294L,
+65295L,65296L,65297L,65298L,65299L,65300L,65301L,65302L,65303L,65304L,
+65305L,65306L,65307L,65308L,65309L,65310L,65311L,65312L,65313L,65314L,
+65315L,65316L,65317L,65318L,65319L,65320L,65321L,65322L,65323L,65324L,
+65325L,65326L,65327L,65328L,65329L,65330L,65331L,65332L,65333L,65334L,
+65335L,65336L,65337L,65338L,65339L,65340L,65341L,65342L,65343L,65344L,
+65313L,65314L,65315L,65316L,65317L,65318L,65319L,65320L,65321L,65322L,
+65323L,65324L,65325L,65326L,65327L,65328L,65329L,65330L,65331L,65332L,
+65333L,65334L,65335L,65336L,65337L,65338L,65371L,65372L,65373L,65374L,
+65375L,65376L,65377L,65378L,65379L,65380L,65381L,65382L,65383L,65384L,
+65385L,65386L,65387L,65388L,65389L,65390L,65391L,65392L,65393L,65394L,
+65395L,65396L,65397L,65398L,65399L,65400L,65401L,65402L,65403L,65404L,
+65405L,65406L,65407L,65408L,65409L,65410L,65411L,65412L,65413L,65414L,
+65415L,65416L,65417L,65418L,65419L,65420L,65421L,65422L,65423L,65424L,
+65425L,65426L,65427L,65428L,65429L,65430L,65431L,65432L,65433L,65434L,
+65435L,65436L,65437L,65438L,65439L,65440L,65441L,65442L,65443L,65444L,
+65445L,65446L,65447L,65448L,65449L,65450L,65451L,65452L,65453L,65454L,
+65455L,65456L,65457L,65458L,65459L,65460L,65461L,65462L,65463L,65464L,
+65465L,65466L,65467L,65468L,65469L,65470L,65471L,65472L,65473L,65474L,
+65475L,65476L,65477L,65478L,65479L,65480L,65481L,65482L,65483L,65484L,
+65485L,65486L,65487L,65488L,65489L,65490L,65491L,65492L,65493L,65494L,
+65495L,65496L,65497L,65498L,65499L,65500L,65501L,65502L,65503L,65504L,
+65505L,65506L,65507L,65508L,65509L,65510L,65511L,65512L,65513L,65514L,
+65515L,65516L,65517L,65518L,65519L,65520L,65521L,65522L,65523L,65524L,
+65525L,65526L,65527L,65528L,65529L,65530L,65531L,65532L,65533L,65534L,
+65535L,
};
#endif
@@ -94239,8 +99952,8 @@ const duk_uint16_t duk_unicode_re_canon_lookup[65536] = {
*/
const duk_uint8_t duk_unicode_re_canon_bitmap[256] = {
-23,0,224,19,1,228,255,255,255,255,255,255,255,255,255,255,255,255,255,127,
-255,255,255,255,255,255,255,255,231,247,0,16,255,227,255,255,63,255,255,
+23,0,224,19,1,228,255,255,255,255,255,255,255,255,255,255,63,254,255,127,
+255,255,255,255,255,255,255,255,231,231,0,16,255,227,255,255,63,255,255,
255,255,255,255,255,1,252,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
@@ -94248,7 +99961,7 @@ const duk_uint8_t duk_unicode_re_canon_bitmap[256] = {
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-227,193,255,255,255,147,255,255,255,255,255,255,255,255,255,255,255,255,
+227,129,255,255,255,147,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
@@ -94300,7 +100013,7 @@ DUK_INTERNAL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t
shift = ctx->currbits - bits;
mask = (((duk_uint32_t) 1U) << bits) - 1U;
tmp = (ctx->currval >> shift) & mask;
- ctx->currbits = shift; /* remaining */
+ ctx->currbits = shift; /* remaining */
#if 0
DUK_DDD(DUK_DDDPRINT("decode_bits: %ld bits -> 0x%08lx (%ld), currbits=%ld, currval=0x%08lx",
@@ -94339,17 +100052,17 @@ DUK_INTERNAL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx) {
*/
switch (duk_bd_decode(ctx, 2)) {
case 0:
- return 0; /* [0,0] */
+ return 0; /* [0,0] */
case 1:
- return duk_bd_decode(ctx, 2) + 1; /* [1,4] */
+ return duk_bd_decode(ctx, 2) + 1; /* [1,4] */
case 2:
- return duk_bd_decode(ctx, 5) + 5; /* [5,36] */
+ return duk_bd_decode(ctx, 5) + 5; /* [5,36] */
default:
t = duk_bd_decode(ctx, 7);
if (t == 0) {
return duk_bd_decode(ctx, 20);
}
- return (t - 1) + 37; /* [37,163] */
+ return (t - 1) + 37; /* [37,163] */
}
}
@@ -94358,20 +100071,18 @@ DUK_INTERNAL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx) {
* Caller must supply the output buffer whose size is NOT checked!
*/
-#define DUK__BITPACK_LETTER_LIMIT 26
-#define DUK__BITPACK_LOOKUP1 26
-#define DUK__BITPACK_LOOKUP2 27
-#define DUK__BITPACK_SWITCH1 28
-#define DUK__BITPACK_SWITCH 29
-#define DUK__BITPACK_UNUSED1 30
-#define DUK__BITPACK_EIGHTBIT 31
+#define DUK__BITPACK_LETTER_LIMIT 26
+#define DUK__BITPACK_LOOKUP1 26
+#define DUK__BITPACK_LOOKUP2 27
+#define DUK__BITPACK_SWITCH1 28
+#define DUK__BITPACK_SWITCH 29
+#define DUK__BITPACK_UNUSED1 30
+#define DUK__BITPACK_EIGHTBIT 31
-DUK_LOCAL const duk_uint8_t duk__bitpacked_lookup[16] = {
- DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
- DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
- DUK_ASC_8, DUK_ASC_9, DUK_ASC_UNDERSCORE, DUK_ASC_SPACE,
- 0x82, 0x80, DUK_ASC_DOUBLEQUOTE, DUK_ASC_LCURLY
-};
+DUK_LOCAL const duk_uint8_t duk__bitpacked_lookup[16] = { DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
+ DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
+ DUK_ASC_8, DUK_ASC_9, DUK_ASC_UNDERSCORE, DUK_ASC_SPACE,
+ 0x82, 0x80, DUK_ASC_DOUBLEQUOTE, DUK_ASC_LCURLY };
DUK_INTERNAL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out) {
duk_small_uint_t len;
@@ -94381,10 +100092,10 @@ DUK_INTERNAL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx
len = duk_bd_decode(bd, 5);
if (len == 31) {
- len = duk_bd_decode(bd, 8); /* Support up to 256 bytes; rare. */
+ len = duk_bd_decode(bd, 8); /* Support up to 256 bytes; rare. */
}
- mode = 32; /* 0 = uppercase, 32 = lowercase (= 'a' - 'A') */
+ mode = 32; /* 0 = uppercase, 32 = lowercase (= 'a' - 'A') */
for (i = 0; i < len; i++) {
t = duk_bd_decode(bd, 5);
if (t < DUK__BITPACK_LETTER_LIMIT) {
@@ -94395,7 +100106,7 @@ DUK_INTERNAL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx
t = duk__bitpacked_lookup[8 + duk_bd_decode(bd, 3)];
} else if (t == DUK__BITPACK_SWITCH1) {
t = duk_bd_decode(bd, 5);
- DUK_ASSERT_DISABLE(t >= 0); /* unsigned */
+ DUK_ASSERT_DISABLE(t >= 0); /* unsigned */
DUK_ASSERT(t <= 25);
t = t + DUK_ASC_UC_A + (mode ^ 32);
} else if (t == DUK__BITPACK_SWITCH) {
@@ -94470,6 +100181,10 @@ DUK_INTERNAL void duk_be_finish(duk_bitencoder_ctx *ctx) {
/* #include duk_internal.h -> already included */
+/* XXX: Avoid duk_{memcmp,memmove}_unsafe() by imposing a minimum length of
+ * >0 for the underlying dynamic buffer.
+ */
+
/*
* Macro support functions (use only macros in calling code)
*/
@@ -94481,6 +100196,9 @@ DUK_LOCAL void duk__bw_update_ptrs(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx,
DUK_ASSERT(bw_ctx != NULL);
DUK_UNREF(thr);
+ /* 'p' might be NULL when the underlying buffer is zero size. If so,
+ * the resulting pointers are not used unsafely.
+ */
p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, bw_ctx->buf);
DUK_ASSERT(p != NULL || (DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0 && curr_offset == 0 && new_length == 0));
bw_ctx->p = p + curr_offset;
@@ -94489,7 +100207,6 @@ DUK_LOCAL void duk__bw_update_ptrs(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx,
}
DUK_INTERNAL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf) {
-
DUK_ASSERT(thr != NULL);
DUK_ASSERT(bw_ctx != NULL);
DUK_ASSERT(h_buf != NULL);
@@ -94504,6 +100221,7 @@ DUK_INTERNAL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ct
(void) duk_push_dynamic_buffer(thr, buf_size);
bw_ctx->buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, -1);
+ DUK_ASSERT(bw_ctx->buf != NULL);
duk__bw_update_ptrs(thr, bw_ctx, 0, buf_size);
}
@@ -94528,9 +100246,9 @@ DUK_INTERNAL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_
if (DUK_UNLIKELY(new_sz < curr_off)) {
/* overflow */
DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
- return NULL; /* not reachable */
+ DUK_WO_NORETURN(return NULL;);
}
-#if 0 /* for manual torture testing: tight allocation, useful with valgrind */
+#if 0 /* for manual torture testing: tight allocation, useful with valgrind */
new_sz = curr_off + sz;
#endif
@@ -94571,9 +100289,7 @@ DUK_INTERNAL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw
DUK_UNREF(thr);
p_base = bw->p_base;
- DUK_MEMCPY((void *) bw->p,
- (const void *) (p_base + src_off),
- (size_t) len);
+ duk_memcpy_unsafe((void *) bw->p, (const void *) (p_base + src_off), (size_t) len);
bw->p += len;
}
@@ -94588,7 +100304,11 @@ DUK_INTERNAL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx
duk_bw_write_raw_slice(thr, bw, src_off, len);
}
-DUK_INTERNAL void duk_bw_insert_raw_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len) {
+DUK_INTERNAL void duk_bw_insert_raw_bytes(duk_hthread *thr,
+ duk_bufwriter_ctx *bw,
+ duk_size_t dst_off,
+ const duk_uint8_t *buf,
+ duk_size_t len) {
duk_uint8_t *p_base;
duk_size_t buf_sz, move_sz;
@@ -94599,20 +100319,20 @@ DUK_INTERNAL void duk_bw_insert_raw_bytes(duk_hthread *thr, duk_bufwriter_ctx *b
DUK_UNREF(thr);
p_base = bw->p_base;
- buf_sz = (duk_size_t) (bw->p - p_base); /* constrained by maximum buffer size */
+ buf_sz = (duk_size_t) (bw->p - p_base); /* constrained by maximum buffer size */
move_sz = buf_sz - dst_off;
- DUK_ASSERT(p_base != NULL); /* buffer size is >= 1 */
- DUK_MEMMOVE((void *) (p_base + dst_off + len),
- (const void *) (p_base + dst_off),
- (size_t) move_sz);
- DUK_MEMCPY((void *) (p_base + dst_off),
- (const void *) buf,
- (size_t) len);
+ DUK_ASSERT(p_base != NULL); /* buffer size is >= 1 */
+ duk_memmove_unsafe((void *) (p_base + dst_off + len), (const void *) (p_base + dst_off), (size_t) move_sz);
+ duk_memcpy_unsafe((void *) (p_base + dst_off), (const void *) buf, (size_t) len);
bw->p += len;
}
-DUK_INTERNAL void duk_bw_insert_ensure_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len) {
+DUK_INTERNAL void duk_bw_insert_ensure_bytes(duk_hthread *thr,
+ duk_bufwriter_ctx *bw,
+ duk_size_t dst_off,
+ const duk_uint8_t *buf,
+ duk_size_t len) {
DUK_ASSERT(thr != NULL);
DUK_ASSERT(bw != NULL);
DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
@@ -94622,7 +100342,11 @@ DUK_INTERNAL void duk_bw_insert_ensure_bytes(duk_hthread *thr, duk_bufwriter_ctx
duk_bw_insert_raw_bytes(thr, bw, dst_off, buf, len);
}
-DUK_INTERNAL void duk_bw_insert_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len) {
+DUK_INTERNAL void duk_bw_insert_raw_slice(duk_hthread *thr,
+ duk_bufwriter_ctx *bw,
+ duk_size_t dst_off,
+ duk_size_t src_off,
+ duk_size_t len) {
duk_uint8_t *p_base;
duk_size_t buf_sz, move_sz;
@@ -94649,17 +100373,17 @@ DUK_INTERNAL void duk_bw_insert_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *b
buf_sz = (duk_size_t) (bw->p - p_base);
move_sz = buf_sz - dst_off;
- DUK_ASSERT(p_base != NULL); /* buffer size is >= 1 */
- DUK_MEMMOVE((void *) (p_base + dst_off + len),
- (const void *) (p_base + dst_off),
- (size_t) move_sz);
- DUK_MEMCPY((void *) (p_base + dst_off),
- (const void *) (p_base + src_off),
- (size_t) len);
+ DUK_ASSERT(p_base != NULL); /* buffer size is >= 1 */
+ duk_memmove_unsafe((void *) (p_base + dst_off + len), (const void *) (p_base + dst_off), (size_t) move_sz);
+ duk_memcpy_unsafe((void *) (p_base + dst_off), (const void *) (p_base + src_off), (size_t) len);
bw->p += len;
}
-DUK_INTERNAL void duk_bw_insert_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len) {
+DUK_INTERNAL void duk_bw_insert_ensure_slice(duk_hthread *thr,
+ duk_bufwriter_ctx *bw,
+ duk_size_t dst_off,
+ duk_size_t src_off,
+ duk_size_t len) {
DUK_ASSERT(thr != NULL);
DUK_ASSERT(bw != NULL);
DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
@@ -94688,8 +100412,8 @@ DUK_INTERNAL duk_uint8_t *duk_bw_insert_raw_area(duk_hthread *thr, duk_bufwriter
move_sz = buf_sz - off;
p_dst = p_base + off + len;
p_src = p_base + off;
- DUK_MEMMOVE((void *) p_dst, (const void *) p_src, (size_t) move_sz);
- return p_src; /* point to start of 'reserved area' */
+ duk_memmove_unsafe((void *) p_dst, (const void *) p_src, (size_t) move_sz);
+ return p_src; /* point to start of 'reserved area' */
}
DUK_INTERNAL duk_uint8_t *duk_bw_insert_ensure_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {
@@ -94719,103 +100443,539 @@ DUK_INTERNAL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *b
p_dst = p_base + off;
p_src = p_dst + len;
move_sz = (duk_size_t) (bw->p - p_src);
- DUK_MEMMOVE((void *) p_dst,
- (const void *) p_src,
- (size_t) move_sz);
+ duk_memmove_unsafe((void *) p_dst, (const void *) p_src, (size_t) move_sz);
bw->p -= len;
}
/*
- * Macro support functions for reading/writing raw data.
+ * Assertion helpers
+ */
+
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL void duk_bw_assert_valid(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx) {
+ DUK_UNREF(thr);
+ DUK_ASSERT(bw_ctx != NULL);
+ DUK_ASSERT(bw_ctx->buf != NULL);
+ DUK_ASSERT((DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0) ||
+ (bw_ctx->p != NULL && bw_ctx->p_base != NULL && bw_ctx->p_limit != NULL && bw_ctx->p_limit >= bw_ctx->p_base &&
+ bw_ctx->p >= bw_ctx->p_base && bw_ctx->p <= bw_ctx->p_limit));
+}
+#endif
+/*
+ * Cast helpers.
*
- * These are done using mempcy to ensure they're valid even for unaligned
- * reads/writes on platforms where alignment counts. On x86 at least gcc
- * is able to compile these into a bswap+mov. "Always inline" is used to
- * ensure these macros compile to minimal code.
+ * C99+ coercion is challenging portability-wise because out-of-range casts
+ * may invoke implementation defined or even undefined behavior. See e.g.
+ * http://blog.frama-c.com/index.php?post/2013/10/09/Overflow-float-integer.
*
- * Not really bufwriter related, but currently used together.
+ * Provide explicit cast helpers which try to avoid implementation defined
+ * or undefined behavior. These helpers can then be simplified in the vast
+ * majority of cases where the implementation defined or undefined behavior
+ * is not problematic.
*/
-DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p) {
- union {
- duk_uint8_t b[2];
- duk_uint16_t x;
- } u;
+/* #include duk_internal.h -> already included */
- DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 2);
- u.x = DUK_NTOH16(u.x);
- *p += 2;
- return u.x;
+/* Portable double-to-integer cast which avoids undefined behavior and avoids
+ * relying on fmin(), fmax(), or other intrinsics. Out-of-range results are
+ * not assumed by caller, but here value is clamped, NaN converts to minval.
+ */
+#define DUK__DOUBLE_INT_CAST1(tname, minval, maxval) \
+ do { \
+ if (DUK_LIKELY(x >= (duk_double_t) (minval))) { \
+ DUK_ASSERT(!DUK_ISNAN(x)); \
+ if (DUK_LIKELY(x <= (duk_double_t) (maxval))) { \
+ return (tname) x; \
+ } else { \
+ return (tname) (maxval); \
+ } \
+ } else { \
+ /* NaN or below minval. Since we don't care about the result \
+ * for out-of-range values, just return the minimum value for \
+ * both. \
+ */ \
+ return (tname) (minval); \
+ } \
+ } while (0)
+
+/* Rely on specific NaN behavior for duk_double_{fmin,fmax}(): if either
+ * argument is a NaN, return the second argument. This avoids a
+ * NaN-to-integer cast which is undefined behavior.
+ */
+#define DUK__DOUBLE_INT_CAST2(tname, minval, maxval) \
+ do { \
+ return (tname) duk_double_fmin(duk_double_fmax(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
+ } while (0)
+
+/* Another solution which doesn't need C99+ behavior for fmin() and fmax(). */
+#define DUK__DOUBLE_INT_CAST3(tname, minval, maxval) \
+ do { \
+ if (DUK_ISNAN(x)) { \
+ /* 0 or any other value is fine. */ \
+ return (tname) 0; \
+ } else \
+ return (tname) DUK_FMIN(DUK_FMAX(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
+ } \
+ } \
+ while (0)
+
+/* C99+ solution: relies on specific fmin() and fmax() behavior in C99: if
+ * one argument is NaN but the other isn't, the non-NaN argument is returned.
+ * Because the limits are non-NaN values, explicit NaN check is not needed.
+ * This may not work on all legacy platforms, and also doesn't seem to inline
+ * the fmin() and fmax() calls (unless one uses -ffast-math which we don't
+ * support).
+ */
+#define DUK__DOUBLE_INT_CAST4(tname, minval, maxval) \
+ do { \
+ return (tname) DUK_FMIN(DUK_FMAX(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
+ } while (0)
+
+DUK_INTERNAL duk_int_t duk_double_to_int_t(duk_double_t x) {
+#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
+ /* Real world solution: almost any practical platform will provide
+ * an integer value without any guarantees what it is (which is fine).
+ */
+ return (duk_int_t) x;
+#else
+ DUK__DOUBLE_INT_CAST1(duk_int_t, DUK_INT_MIN, DUK_INT_MAX);
+#endif
}
-DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p) {
- union {
- duk_uint8_t b[4];
- duk_uint32_t x;
- } u;
+DUK_INTERNAL duk_uint_t duk_double_to_uint_t(duk_double_t x) {
+#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
+ return (duk_uint_t) x;
+#else
+ DUK__DOUBLE_INT_CAST1(duk_uint_t, DUK_UINT_MIN, DUK_UINT_MAX);
+#endif
+}
- DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 4);
- u.x = DUK_NTOH32(u.x);
- *p += 4;
- return u.x;
+DUK_INTERNAL duk_int32_t duk_double_to_int32_t(duk_double_t x) {
+#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
+ return (duk_int32_t) x;
+#else
+ DUK__DOUBLE_INT_CAST1(duk_int32_t, DUK_INT32_MIN, DUK_INT32_MAX);
+#endif
+}
+
+DUK_INTERNAL duk_uint32_t duk_double_to_uint32_t(duk_double_t x) {
+#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
+ return (duk_uint32_t) x;
+#else
+ DUK__DOUBLE_INT_CAST1(duk_uint32_t, DUK_UINT32_MIN, DUK_UINT32_MAX);
+#endif
+}
+
+/* Largest IEEE double that doesn't round to infinity in the default rounding
+ * mode. The exact midpoint between (1 - 2^(-24)) * 2^128 and 2^128 rounds to
+ * infinity, at least on x64. This number is one double unit below that
+ * midpoint. See misc/float_cast.c.
+ */
+#define DUK__FLOAT_ROUND_LIMIT 340282356779733623858607532500980858880.0
+
+/* Maximum IEEE float. Double-to-float conversion above this would be out of
+ * range and thus technically undefined behavior.
+ */
+#define DUK__FLOAT_MAX 340282346638528859811704183484516925440.0
+
+DUK_INTERNAL duk_float_t duk_double_to_float_t(duk_double_t x) {
+ /* Even a double-to-float cast is technically undefined behavior if
+ * the double is out-of-range. C99 Section 6.3.1.5:
+ *
+ * If the value being converted is in the range of values that can
+ * be represented but cannot be represented exactly, the result is
+ * either the nearest higher or nearest lower representable value,
+ * chosen in an implementation-defined manner. If the value being
+ * converted is outside the range of values that can be represented,
+ * the behavior is undefined.
+ */
+#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
+ return (duk_float_t) x;
+#else
+ duk_double_t t;
+
+ t = DUK_FABS(x);
+ DUK_ASSERT((DUK_ISNAN(x) && DUK_ISNAN(t)) || (!DUK_ISNAN(x) && !DUK_ISNAN(t)));
+
+ if (DUK_LIKELY(t <= DUK__FLOAT_MAX)) {
+ /* Standard in-range case, try to get here with a minimum
+ * number of checks and branches.
+ */
+ DUK_ASSERT(!DUK_ISNAN(x));
+ return (duk_float_t) x;
+ } else if (t <= DUK__FLOAT_ROUND_LIMIT) {
+ /* Out-of-range, but rounds to min/max float. */
+ DUK_ASSERT(!DUK_ISNAN(x));
+ if (x < 0.0) {
+ return (duk_float_t) -DUK__FLOAT_MAX;
+ } else {
+ return (duk_float_t) DUK__FLOAT_MAX;
+ }
+ } else if (DUK_ISNAN(x)) {
+ /* Assumes double NaN -> float NaN considered "in range". */
+ DUK_ASSERT(DUK_ISNAN(x));
+ return (duk_float_t) x;
+ } else {
+ /* Out-of-range, rounds to +/- Infinity. */
+ if (x < 0.0) {
+ return (duk_float_t) -DUK_DOUBLE_INFINITY;
+ } else {
+ return (duk_float_t) DUK_DOUBLE_INFINITY;
+ }
+ }
+#endif
}
-DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_read_double_be(duk_uint8_t **p) {
+/* automatic undefs */
+#undef DUK__DOUBLE_INT_CAST1
+#undef DUK__DOUBLE_INT_CAST2
+#undef DUK__DOUBLE_INT_CAST3
+#undef DUK__DOUBLE_INT_CAST4
+#undef DUK__FLOAT_MAX
+#undef DUK__FLOAT_ROUND_LIMIT
+/*
+ * IEEE double helpers.
+ */
+
+/* #include duk_internal.h -> already included */
+
+DUK_INTERNAL duk_bool_t duk_double_is_anyinf(duk_double_t x) {
duk_double_union du;
- union {
- duk_uint8_t b[4];
- duk_uint32_t x;
- } u;
+ du.d = x;
+ return DUK_DBLUNION_IS_ANYINF(&du);
+}
- DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 4);
- u.x = DUK_NTOH32(u.x);
- du.ui[DUK_DBL_IDX_UI0] = u.x;
- DUK_MEMCPY((void *) u.b, (const void *) (*p + 4), (size_t) 4);
- u.x = DUK_NTOH32(u.x);
- du.ui[DUK_DBL_IDX_UI1] = u.x;
- *p += 8;
+DUK_INTERNAL duk_bool_t duk_double_is_posinf(duk_double_t x) {
+ duk_double_union du;
+ du.d = x;
+ return DUK_DBLUNION_IS_POSINF(&du);
+}
- return du.d;
+DUK_INTERNAL duk_bool_t duk_double_is_neginf(duk_double_t x) {
+ duk_double_union du;
+ du.d = x;
+ return DUK_DBLUNION_IS_NEGINF(&du);
}
-DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val) {
- union {
- duk_uint8_t b[2];
- duk_uint16_t x;
- } u;
+DUK_INTERNAL duk_bool_t duk_double_is_nan(duk_double_t x) {
+ duk_double_union du;
+ du.d = x;
+ /* Assumes we're dealing with a Duktape internal NaN which is
+ * NaN normalized if duk_tval requires it.
+ */
+ DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
+ return DUK_DBLUNION_IS_NAN(&du);
+}
- u.x = DUK_HTON16(val);
- DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 2);
- *p += 2;
+DUK_INTERNAL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x) {
+ duk_double_union du;
+ du.d = x;
+ /* Assumes we're dealing with a Duktape internal NaN which is
+ * NaN normalized if duk_tval requires it.
+ */
+ DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
+ return DUK_DBLUNION_IS_NAN(&du) || DUK_DBLUNION_IS_ANYZERO(&du);
}
-DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val) {
- union {
- duk_uint8_t b[4];
- duk_uint32_t x;
- } u;
+DUK_INTERNAL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x) {
+ duk_double_union du;
+ du.d = x;
+ /* If exponent is 0x7FF the argument is either a NaN or an
+ * infinity. We don't need to check any other fields.
+ */
+#if defined(DUK_USE_64BIT_OPS)
+#if defined(DUK_USE_DOUBLE_ME)
+ return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000);
+#else
+ return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000);
+#endif
+#else
+ return (du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL;
+#endif
+}
- u.x = DUK_HTON32(val);
- DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 4);
- *p += 4;
+DUK_INTERNAL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x) {
+ duk_double_union du;
+#if defined(DUK_USE_64BIT_OPS)
+ duk_uint64_t t;
+#else
+ duk_uint32_t t;
+#endif
+ du.d = x;
+#if defined(DUK_USE_64BIT_OPS)
+#if defined(DUK_USE_DOUBLE_ME)
+ t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000);
+ if (t == DUK_U64_CONSTANT(0x0000000000000000)) {
+ t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x0000000080000000);
+ return t == 0;
+ }
+ if (t == DUK_U64_CONSTANT(0x000000007ff00000)) {
+ return 1;
+ }
+#else
+ t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000);
+ if (t == DUK_U64_CONSTANT(0x0000000000000000)) {
+ t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000);
+ return t == 0;
+ }
+ if (t == DUK_U64_CONSTANT(0x7ff0000000000000)) {
+ return 1;
+ }
+#endif
+#else
+ t = du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL;
+ if (t == 0x00000000UL) {
+ return DUK_DBLUNION_IS_ANYZERO(&du);
+ }
+ if (t == 0x7ff00000UL) {
+ return 1;
+ }
+#endif
+ return 0;
}
-DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val) {
+DUK_INTERNAL duk_small_uint_t duk_double_signbit(duk_double_t x) {
duk_double_union du;
- union {
- duk_uint8_t b[4];
- duk_uint32_t x;
- } u;
+ du.d = x;
+ return (duk_small_uint_t) DUK_DBLUNION_GET_SIGNBIT(&du);
+}
- du.d = val;
- u.x = du.ui[DUK_DBL_IDX_UI0];
- u.x = DUK_HTON32(u.x);
- DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 4);
- u.x = du.ui[DUK_DBL_IDX_UI1];
- u.x = DUK_HTON32(u.x);
- DUK_MEMCPY((void *) (*p + 4), (const void *) u.b, (size_t) 4);
- *p += 8;
+DUK_INTERNAL duk_double_t duk_double_trunc_towards_zero(duk_double_t x) {
+ /* XXX: optimize */
+ duk_small_uint_t s = duk_double_signbit(x);
+ x = DUK_FLOOR(DUK_FABS(x)); /* truncate towards zero */
+ if (s) {
+ x = -x;
+ }
+ return x;
+}
+
+DUK_INTERNAL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y) {
+ duk_double_union du1;
+ duk_double_union du2;
+ du1.d = x;
+ du2.d = y;
+
+ return (((du1.ui[DUK_DBL_IDX_UI0] ^ du2.ui[DUK_DBL_IDX_UI0]) & 0x80000000UL) == 0);
+}
+
+DUK_INTERNAL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y) {
+ /* Doesn't replicate fmin() behavior exactly: for fmin() if one
+ * argument is a NaN, the other argument should be returned.
+ * Duktape doesn't rely on this behavior so the replacement can
+ * be simplified.
+ */
+ return (x < y ? x : y);
+}
+
+DUK_INTERNAL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y) {
+ /* Doesn't replicate fmax() behavior exactly: for fmax() if one
+ * argument is a NaN, the other argument should be returned.
+ * Duktape doesn't rely on this behavior so the replacement can
+ * be simplified.
+ */
+ return (x > y ? x : y);
+}
+
+DUK_INTERNAL duk_bool_t duk_double_is_finite(duk_double_t x) {
+ return !duk_double_is_nan_or_inf(x);
+}
+
+DUK_INTERNAL duk_bool_t duk_double_is_integer(duk_double_t x) {
+ if (duk_double_is_nan_or_inf(x)) {
+ return 0;
+ } else {
+ return duk_double_equals(duk_js_tointeger_number(x), x);
+ }
+}
+
+DUK_INTERNAL duk_bool_t duk_double_is_safe_integer(duk_double_t x) {
+ /* >>> 2**53-1
+ * 9007199254740991
+ */
+ return duk_double_is_integer(x) && DUK_FABS(x) <= 9007199254740991.0;
+}
+
+/* Check whether a duk_double_t is a whole number in the 32-bit range (reject
+ * negative zero), and if so, return a duk_int32_t.
+ * For compiler use: don't allow negative zero as it will cause trouble with
+ * LDINT+LDINTX, positive zero is OK.
+ */
+DUK_INTERNAL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival) {
+ duk_int32_t t;
+
+ t = duk_double_to_int32_t(x);
+ if (!duk_double_equals((duk_double_t) t, x)) {
+ return 0;
+ }
+ if (t == 0) {
+ duk_double_union du;
+ du.d = x;
+ if (DUK_DBLUNION_HAS_SIGNBIT(&du)) {
+ return 0;
+ }
+ }
+ *ival = t;
+ return 1;
}
+
+/* Check whether a duk_double_t is a whole number in the 32-bit range, and if
+ * so, return a duk_int32_t.
+ */
+DUK_INTERNAL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival) {
+ duk_int32_t t;
+
+ t = duk_double_to_int32_t(x);
+ if (!duk_double_equals((duk_double_t) t, x)) {
+ return 0;
+ }
+ *ival = t;
+ return 1;
+}
+
+/* Division: division by zero is undefined behavior (and may in fact trap)
+ * so it needs special handling for portability.
+ */
+
+DUK_INTERNAL DUK_INLINE duk_double_t duk_double_div(duk_double_t x, duk_double_t y) {
+#if !defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
+ if (DUK_UNLIKELY(duk_double_equals(y, 0.0) != 0)) {
+ /* In C99+ division by zero is undefined behavior so
+ * avoid it entirely. Hopefully the compiler is
+ * smart enough to avoid emitting any actual code
+ * because almost all practical platforms behave as
+ * expected.
+ */
+ if (x > 0.0) {
+ if (DUK_SIGNBIT(y)) {
+ return -DUK_DOUBLE_INFINITY;
+ } else {
+ return DUK_DOUBLE_INFINITY;
+ }
+ } else if (x < 0.0) {
+ if (DUK_SIGNBIT(y)) {
+ return DUK_DOUBLE_INFINITY;
+ } else {
+ return -DUK_DOUBLE_INFINITY;
+ }
+ } else {
+ /* +/- 0, NaN */
+ return DUK_DOUBLE_NAN;
+ }
+ }
+#endif
+
+ return x / y;
+}
+
+/* Double and float byteorder changes. */
+
+DUK_INTERNAL DUK_INLINE void duk_dblunion_host_to_little(duk_double_union *u) {
+#if defined(DUK_USE_DOUBLE_LE)
+ /* HGFEDCBA -> HGFEDCBA */
+ DUK_UNREF(u);
+#elif defined(DUK_USE_DOUBLE_ME)
+ duk_uint32_t a, b;
+
+ /* DCBAHGFE -> HGFEDCBA */
+ a = u->ui[0];
+ b = u->ui[1];
+ u->ui[0] = b;
+ u->ui[1] = a;
+#elif defined(DUK_USE_DOUBLE_BE)
+ /* ABCDEFGH -> HGFEDCBA */
+#if defined(DUK_USE_64BIT_OPS)
+ u->ull[0] = DUK_BSWAP64(u->ull[0]);
+#else
+ duk_uint32_t a, b;
+
+ a = u->ui[0];
+ b = u->ui[1];
+ u->ui[0] = DUK_BSWAP32(b);
+ u->ui[1] = DUK_BSWAP32(a);
+#endif
+#else
+#error internal error
+#endif
+}
+
+DUK_INTERNAL DUK_INLINE void duk_dblunion_little_to_host(duk_double_union *u) {
+ duk_dblunion_host_to_little(u);
+}
+
+DUK_INTERNAL DUK_INLINE void duk_dblunion_host_to_big(duk_double_union *u) {
+#if defined(DUK_USE_DOUBLE_LE)
+ /* HGFEDCBA -> ABCDEFGH */
+#if defined(DUK_USE_64BIT_OPS)
+ u->ull[0] = DUK_BSWAP64(u->ull[0]);
+#else
+ duk_uint32_t a, b;
+
+ a = u->ui[0];
+ b = u->ui[1];
+ u->ui[0] = DUK_BSWAP32(b);
+ u->ui[1] = DUK_BSWAP32(a);
+#endif
+#elif defined(DUK_USE_DOUBLE_ME)
+ duk_uint32_t a, b;
+
+ /* DCBAHGFE -> ABCDEFGH */
+ a = u->ui[0];
+ b = u->ui[1];
+ u->ui[0] = DUK_BSWAP32(a);
+ u->ui[1] = DUK_BSWAP32(b);
+#elif defined(DUK_USE_DOUBLE_BE)
+ /* ABCDEFGH -> ABCDEFGH */
+ DUK_UNREF(u);
+#else
+#error internal error
+#endif
+}
+
+DUK_INTERNAL DUK_INLINE void duk_dblunion_big_to_host(duk_double_union *u) {
+ duk_dblunion_host_to_big(u);
+}
+
+DUK_INTERNAL DUK_INLINE void duk_fltunion_host_to_big(duk_float_union *u) {
+#if defined(DUK_USE_DOUBLE_LE) || defined(DUK_USE_DOUBLE_ME)
+ /* DCBA -> ABCD */
+ u->ui[0] = DUK_BSWAP32(u->ui[0]);
+#elif defined(DUK_USE_DOUBLE_BE)
+ /* ABCD -> ABCD */
+ DUK_UNREF(u);
+#else
+#error internal error
+#endif
+}
+
+DUK_INTERNAL DUK_INLINE void duk_fltunion_big_to_host(duk_float_union *u) {
+ duk_fltunion_host_to_big(u);
+}
+
+/* Comparison: ensures comparison operates on exactly correct types, avoiding
+ * some floating point comparison pitfalls (e.g. atan2() assertions failed on
+ * -m32 with direct comparison, even with explicit casts).
+ */
+#if defined(DUK_USE_GCC_PRAGMAS)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#elif defined(DUK_USE_CLANG_PRAGMAS)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wfloat-equal"
+#endif
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_bool_t duk_double_equals(duk_double_t x, duk_double_t y) {
+ return x == y;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_bool_t duk_float_equals(duk_float_t x, duk_float_t y) {
+ return x == y;
+}
+#if defined(DUK_USE_GCC_PRAGMAS)
+#pragma GCC diagnostic pop
+#elif defined(DUK_USE_CLANG_PRAGMAS)
+#pragma clang diagnostic pop
+#endif
/*
* Hash function duk_util_hashbytes().
*
@@ -94829,8 +100989,8 @@ DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_double_be(duk_uint8_t **p, duk
#if defined(DUK_USE_STRHASH_DENSE)
/* 'magic' constants for Murmurhash2 */
-#define DUK__MAGIC_M ((duk_uint32_t) 0x5bd1e995UL)
-#define DUK__MAGIC_R 24
+#define DUK__MAGIC_M ((duk_uint32_t) 0x5bd1e995UL)
+#define DUK__MAGIC_R 24
DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed) {
duk_uint32_t h = seed ^ ((duk_uint32_t) len);
@@ -94844,9 +101004,7 @@ DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t
#if defined(DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS)
duk_uint32_t k = *((const duk_uint32_t *) (const void *) data);
#else
- duk_uint32_t k = ((duk_uint32_t) data[0]) |
- (((duk_uint32_t) data[1]) << 8) |
- (((duk_uint32_t) data[2]) << 16) |
+ duk_uint32_t k = ((duk_uint32_t) data[0]) | (((duk_uint32_t) data[1]) << 8) | (((duk_uint32_t) data[2]) << 16) |
(((duk_uint32_t) data[3]) << 24);
#endif
@@ -94860,11 +101018,14 @@ DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t
}
switch (len) {
- case 3: h ^= data[2] << 16;
- case 2: h ^= data[1] << 8;
- case 1: h ^= data[0];
- h *= DUK__MAGIC_M;
- }
+ case 3:
+ h ^= data[2] << 16;
+ case 2:
+ h ^= data[1] << 8;
+ case 1:
+ h ^= data[0];
+ h *= DUK__MAGIC_M;
+ }
h ^= h >> 13;
h *= DUK__MAGIC_M;
@@ -94872,12 +101033,48 @@ DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t
return h;
}
-#endif /* DUK_USE_STRHASH_DENSE */
+#endif /* DUK_USE_STRHASH_DENSE */
/* automatic undefs */
#undef DUK__MAGIC_M
#undef DUK__MAGIC_R
/*
+ * Memory utils.
+ */
+
+/* #include duk_internal.h -> already included */
+
+#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
+DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len) {
+ DUK_ASSERT(s1 != NULL || len == 0U);
+ DUK_ASSERT(s2 != NULL || len == 0U);
+ return DUK_MEMCMP(s1, s2, (size_t) len);
+}
+
+DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len) {
+ DUK_ASSERT(s1 != NULL);
+ DUK_ASSERT(s2 != NULL);
+ return DUK_MEMCMP(s1, s2, (size_t) len);
+}
+#else /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
+DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len) {
+ DUK_ASSERT(s1 != NULL || len == 0U);
+ DUK_ASSERT(s2 != NULL || len == 0U);
+ if (DUK_UNLIKELY(len == 0U)) {
+ return 0;
+ }
+ DUK_ASSERT(s1 != NULL);
+ DUK_ASSERT(s2 != NULL);
+ return duk_memcmp(s1, s2, len);
+}
+
+DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len) {
+ DUK_ASSERT(s1 != NULL);
+ DUK_ASSERT(s2 != NULL);
+ return DUK_MEMCMP(s1, s2, (size_t) len);
+}
+#endif /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
+/*
* A tiny random number generator used for Math.random() and other internals.
*
* Default algorithm is xoroshiro128+: http://xoroshiro.di.unimi.it/xoroshiro128plus.c
@@ -94900,15 +101097,16 @@ DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t
#endif
#if defined(DUK__RANDOM_SHAMIR3OP)
-#define DUK__UPDATE_RND(rnd) do { \
+#define DUK__UPDATE_RND(rnd) \
+ do { \
(rnd) += ((rnd) * (rnd)) | 0x05UL; \
- (rnd) = ((rnd) & 0xffffffffUL); /* if duk_uint32_t is exactly 32 bits, this is a NOP */ \
+ (rnd) = ((rnd) &0xffffffffUL); /* if duk_uint32_t is exactly 32 bits, this is a NOP */ \
} while (0)
-#define DUK__RND_BIT(rnd) ((rnd) >> 31) /* only use the highest bit */
+#define DUK__RND_BIT(rnd) ((rnd) >> 31) /* only use the highest bit */
DUK_INTERNAL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr) {
- DUK_UNREF(thr); /* Nothing now. */
+ DUK_UNREF(thr); /* Nothing now. */
}
DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
@@ -94918,7 +101116,7 @@ DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
rnd = thr->heap->rnd_state;
- n = 53; /* enough to cover the whole mantissa */
+ n = 53; /* enough to cover the whole mantissa */
t = 0.0;
do {
@@ -94934,7 +101132,7 @@ DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
return t;
}
-#endif /* DUK__RANDOM_SHAMIR3OP */
+#endif /* DUK__RANDOM_SHAMIR3OP */
#if defined(DUK__RANDOM_XOROSHIRO128PLUS)
DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_splitmix64(duk_uint64_t *x) {
@@ -94973,9 +101171,9 @@ DUK_INTERNAL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr) {
* because current seed is Date.now()) result in different xoroshiro128+
* seeds.
*/
- x = thr->heap->rnd_state[0]; /* Only [0] is used as input here. */
+ x = thr->heap->rnd_state[0]; /* Only [0] is used as input here. */
for (i = 0; i < 64; i++) {
- thr->heap->rnd_state[i & 0x01] = duk__rnd_splitmix64(&x); /* Keep last 2 values. */
+ thr->heap->rnd_state[i & 0x01] = duk__rnd_splitmix64(&x); /* Keep last 2 values. */
}
}
@@ -94999,9 +101197,9 @@ DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
#endif
return du.d - 1.0;
}
-#endif /* DUK__RANDOM_XOROSHIRO128PLUS */
+#endif /* DUK__RANDOM_XOROSHIRO128PLUS */
-#endif /* !DUK_USE_GET_RANDOM_DOUBLE */
+#endif /* !DUK_USE_GET_RANDOM_DOUBLE */
/* automatic undefs */
#undef DUK__RANDOM_SHAMIR3OP
diff --git a/content/handlers/javascript/duktape/duktape.h b/content/handlers/javascript/duktape/duktape.h
index a3b4f546e..d3cba119e 100644
--- a/content/handlers/javascript/duktape/duktape.h
+++ b/content/handlers/javascript/duktape/duktape.h
@@ -1,5 +1,5 @@
/*
- * Duktape public API for Duktape 2.2.0.
+ * Duktape public API for Duktape 2.7.0.
*
* See the API reference for documentation on call semantics. The exposed,
* supported API is between the "BEGIN PUBLIC API" and "END PUBLIC API"
@@ -21,7 +21,7 @@
*
* (http://opensource.org/licenses/MIT)
*
- * Copyright (c) 2013-2017 by Duktape authors (see AUTHORS.rst)
+ * Copyright (c) 2013-present by Duktape authors (see AUTHORS.rst)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -92,6 +92,30 @@
* * Steven Don (https://github.com/shdon)
* * Simon Stone (https://github.com/sstone1)
* * \J. McC. (https://github.com/jmhmccr)
+ * * Jakub Nowakowski (https://github.com/jimvonmoon)
+ * * Tommy Nguyen (https://github.com/tn0502)
+ * * Fabrice Fontaine (https://github.com/ffontaine)
+ * * Christopher Hiller (https://github.com/boneskull)
+ * * Gonzalo Diethelm (https://github.com/gonzus)
+ * * Michal Kasperek (https://github.com/michalkas)
+ * * Andrew Janke (https://github.com/apjanke)
+ * * Steve Fan (https://github.com/stevefan1999)
+ * * Edward Betts (https://github.com/edwardbetts)
+ * * Ozhan Duz (https://github.com/webfolderio)
+ * * Akos Kiss (https://github.com/akosthekiss)
+ * * TheBrokenRail (https://github.com/TheBrokenRail)
+ * * Jesse Doyle (https://github.com/jessedoyle)
+ * * Gero Kuehn (https://github.com/dc6jgk)
+ * * James Swift (https://github.com/phraemer)
+ * * Luis de Bethencourt (https://github.com/luisbg)
+ * * Ian Whyman (https://github.com/v00d00)
+ * * Rick Sayre (https://github.com/whorfin)
+ * * Craig Leres (https://github.com/leres)
+ * * Maurici Abad (https://github.com/mauriciabad)
+ * * Nancy Li (https://github.com/NancyLi1013)
+ * * William Parks (https://github.com/WilliamParks)
+ * * Sam Hellawell (https://github.com/samhellawell)
+ * * Vladislavs Sokurenko (https://github.com/sokurenko)
*
* Other contributions
* ===================
@@ -130,6 +154,10 @@
* * https://github.com/chris-y
* * Laurent Zubiaur (https://github.com/lzubiaur)
* * Neil Kolban (https://github.com/nkolban)
+ * * Wilhelm Wanecek (https://github.com/wanecek)
+ * * Andrew Janke (https://github.com/apjanke)
+ * * Unamer (https://github.com/unamer)
+ * * Karl Dahlke (eklhad@gmail.com)
*
* If you are accidentally missing from this list, send me an e-mail
* (``sami.vaarala@iki.fi``) and I'll fix the omission.
@@ -150,15 +178,15 @@
/* Duktape version, (major * 10000) + (minor * 100) + patch. Allows C code
* to #if (DUK_VERSION >= NNN) against Duktape API version. The same value
- * is also available to Ecmascript code in Duktape.version. Unofficial
+ * is also available to ECMAScript code in Duktape.version. Unofficial
* development snapshots have 99 for patch level (e.g. 0.10.99 would be a
* development version after 0.10.0 but before the next official release).
*/
-#define DUK_VERSION 20200L
+#define DUK_VERSION 20700L
/* Git commit, describe, and branch for Duktape build. Useful for
* non-official snapshot builds so that application code can easily log
- * which Duktape snapshot was used. Not available in the Ecmascript
+ * which Duktape snapshot was used. Not available in the ECMAScript
* environment.
*/
#define DUK_GIT_COMMIT "external"
@@ -258,7 +286,7 @@ struct duk_number_list_entry {
};
struct duk_time_components {
- duk_double_t year; /* year, e.g. 2016, Ecmascript year range */
+ duk_double_t year; /* year, e.g. 2016, ECMAScript year range */
duk_double_t month; /* month: 1-12 */
duk_double_t day; /* day: 1-31 */
duk_double_t hours; /* hour: 0-59 */
@@ -294,12 +322,12 @@ struct duk_time_components {
/* Value types, used by e.g. duk_get_type() */
#define DUK_TYPE_MIN 0U
#define DUK_TYPE_NONE 0U /* no value, e.g. invalid index */
-#define DUK_TYPE_UNDEFINED 1U /* Ecmascript undefined */
-#define DUK_TYPE_NULL 2U /* Ecmascript null */
-#define DUK_TYPE_BOOLEAN 3U /* Ecmascript boolean: 0 or 1 */
-#define DUK_TYPE_NUMBER 4U /* Ecmascript number: double */
-#define DUK_TYPE_STRING 5U /* Ecmascript string: CESU-8 / extended UTF-8 encoded */
-#define DUK_TYPE_OBJECT 6U /* Ecmascript object: includes objects, arrays, functions, threads */
+#define DUK_TYPE_UNDEFINED 1U /* ECMAScript undefined */
+#define DUK_TYPE_NULL 2U /* ECMAScript null */
+#define DUK_TYPE_BOOLEAN 3U /* ECMAScript boolean: 0 or 1 */
+#define DUK_TYPE_NUMBER 4U /* ECMAScript number: double */
+#define DUK_TYPE_STRING 5U /* ECMAScript string: CESU-8 / extended UTF-8 encoded */
+#define DUK_TYPE_OBJECT 6U /* ECMAScript object: includes objects, arrays, functions, threads */
#define DUK_TYPE_BUFFER 7U /* fixed or dynamic, garbage collected byte buffer */
#define DUK_TYPE_POINTER 8U /* raw void pointer */
#define DUK_TYPE_LIGHTFUNC 9U /* lightweight function pointer */
@@ -373,30 +401,35 @@ struct duk_time_components {
#define DUK_DEFPROP_C DUK_DEFPROP_CONFIGURABLE
#define DUK_DEFPROP_WE (DUK_DEFPROP_WRITABLE | DUK_DEFPROP_ENUMERABLE)
#define DUK_DEFPROP_WC (DUK_DEFPROP_WRITABLE | DUK_DEFPROP_CONFIGURABLE)
+#define DUK_DEFPROP_EC (DUK_DEFPROP_ENUMERABLE | DUK_DEFPROP_CONFIGURABLE)
#define DUK_DEFPROP_WEC (DUK_DEFPROP_WRITABLE | DUK_DEFPROP_ENUMERABLE | DUK_DEFPROP_CONFIGURABLE)
#define DUK_DEFPROP_HAVE_W DUK_DEFPROP_HAVE_WRITABLE
#define DUK_DEFPROP_HAVE_E DUK_DEFPROP_HAVE_ENUMERABLE
#define DUK_DEFPROP_HAVE_C DUK_DEFPROP_HAVE_CONFIGURABLE
#define DUK_DEFPROP_HAVE_WE (DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_HAVE_ENUMERABLE)
#define DUK_DEFPROP_HAVE_WC (DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_HAVE_CONFIGURABLE)
+#define DUK_DEFPROP_HAVE_EC (DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE)
#define DUK_DEFPROP_HAVE_WEC (DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE)
#define DUK_DEFPROP_SET_W DUK_DEFPROP_SET_WRITABLE
#define DUK_DEFPROP_SET_E DUK_DEFPROP_SET_ENUMERABLE
#define DUK_DEFPROP_SET_C DUK_DEFPROP_SET_CONFIGURABLE
#define DUK_DEFPROP_SET_WE (DUK_DEFPROP_SET_WRITABLE | DUK_DEFPROP_SET_ENUMERABLE)
#define DUK_DEFPROP_SET_WC (DUK_DEFPROP_SET_WRITABLE | DUK_DEFPROP_SET_CONFIGURABLE)
+#define DUK_DEFPROP_SET_EC (DUK_DEFPROP_SET_ENUMERABLE | DUK_DEFPROP_SET_CONFIGURABLE)
#define DUK_DEFPROP_SET_WEC (DUK_DEFPROP_SET_WRITABLE | DUK_DEFPROP_SET_ENUMERABLE | DUK_DEFPROP_SET_CONFIGURABLE)
#define DUK_DEFPROP_CLEAR_W DUK_DEFPROP_CLEAR_WRITABLE
#define DUK_DEFPROP_CLEAR_E DUK_DEFPROP_CLEAR_ENUMERABLE
#define DUK_DEFPROP_CLEAR_C DUK_DEFPROP_CLEAR_CONFIGURABLE
#define DUK_DEFPROP_CLEAR_WE (DUK_DEFPROP_CLEAR_WRITABLE | DUK_DEFPROP_CLEAR_ENUMERABLE)
#define DUK_DEFPROP_CLEAR_WC (DUK_DEFPROP_CLEAR_WRITABLE | DUK_DEFPROP_CLEAR_CONFIGURABLE)
+#define DUK_DEFPROP_CLEAR_EC (DUK_DEFPROP_CLEAR_ENUMERABLE | DUK_DEFPROP_CLEAR_CONFIGURABLE)
#define DUK_DEFPROP_CLEAR_WEC (DUK_DEFPROP_CLEAR_WRITABLE | DUK_DEFPROP_CLEAR_ENUMERABLE | DUK_DEFPROP_CLEAR_CONFIGURABLE)
#define DUK_DEFPROP_ATTR_W (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_W)
#define DUK_DEFPROP_ATTR_E (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_E)
#define DUK_DEFPROP_ATTR_C (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_C)
#define DUK_DEFPROP_ATTR_WE (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_WE)
#define DUK_DEFPROP_ATTR_WC (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_WC)
+#define DUK_DEFPROP_ATTR_EC (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_EC)
#define DUK_DEFPROP_ATTR_WEC (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_WEC)
/* Flags for duk_push_thread_raw() */
@@ -437,18 +470,24 @@ struct duk_time_components {
* Macros to create Symbols as C statically constructed strings.
*
* Call e.g. as DUK_HIDDEN_SYMBOL("myProperty") <=> ("\xFF" "myProperty").
+ *
* Local symbols have a unique suffix, caller should take care to avoid
* conflicting with the Duktape internal representation by e.g. prepending
* a '!' character: DUK_LOCAL_SYMBOL("myLocal", "!123").
*
* Note that these can only be used for string constants, not dynamically
* created strings.
+ *
+ * You shouldn't normally use DUK_INTERNAL_SYMBOL() at all. It is reserved
+ * for Duktape internal symbols only. There are no versioning guarantees
+ * for internal symbols.
*/
#define DUK_HIDDEN_SYMBOL(x) ("\xFF" x)
#define DUK_GLOBAL_SYMBOL(x) ("\x80" x)
#define DUK_LOCAL_SYMBOL(x,uniq) ("\x81" x "\xff" uniq)
#define DUK_WELLKNOWN_SYMBOL(x) ("\x81" x "\xff")
+#define DUK_INTERNAL_SYMBOL(x) ("\x82" x)
/*
* If no variadic macros, __FILE__ and __LINE__ are passed through globals
@@ -634,6 +673,7 @@ DUK_EXTERNAL_DECL void duk_swap_top(duk_context *ctx, duk_idx_t idx);
DUK_EXTERNAL_DECL void duk_dup(duk_context *ctx, duk_idx_t from_idx);
DUK_EXTERNAL_DECL void duk_dup_top(duk_context *ctx);
DUK_EXTERNAL_DECL void duk_insert(duk_context *ctx, duk_idx_t to_idx);
+DUK_EXTERNAL_DECL void duk_pull(duk_context *ctx, duk_idx_t from_idx);
DUK_EXTERNAL_DECL void duk_replace(duk_context *ctx, duk_idx_t to_idx);
DUK_EXTERNAL_DECL void duk_copy(duk_context *ctx, duk_idx_t from_idx, duk_idx_t to_idx);
DUK_EXTERNAL_DECL void duk_remove(duk_context *ctx, duk_idx_t idx);
@@ -668,7 +708,21 @@ DUK_EXTERNAL_DECL void duk_push_pointer(duk_context *ctx, void *p);
DUK_EXTERNAL_DECL const char *duk_push_sprintf(duk_context *ctx, const char *fmt, ...);
DUK_EXTERNAL_DECL const char *duk_push_vsprintf(duk_context *ctx, const char *fmt, va_list ap);
+/* duk_push_literal() may evaluate its argument (a C string literal) more than
+ * once on purpose. When speed is preferred, sizeof() avoids an unnecessary
+ * strlen() at runtime. Sizeof("foo") == 4, so subtract 1. The argument
+ * must be non-NULL and should not contain internal NUL characters as the
+ * behavior will then depend on config options.
+ */
+#if defined(DUK_USE_PREFER_SIZE)
+#define duk_push_literal(ctx,cstring) duk_push_string((ctx), (cstring))
+#else
+DUK_EXTERNAL_DECL const char *duk_push_literal_raw(duk_context *ctx, const char *str, duk_size_t len);
+#define duk_push_literal(ctx,cstring) duk_push_literal_raw((ctx), (cstring), sizeof((cstring)) - 1U)
+#endif
+
DUK_EXTERNAL_DECL void duk_push_this(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_push_new_target(duk_context *ctx);
DUK_EXTERNAL_DECL void duk_push_current_function(duk_context *ctx);
DUK_EXTERNAL_DECL void duk_push_current_thread(duk_context *ctx);
DUK_EXTERNAL_DECL void duk_push_global_object(duk_context *ctx);
@@ -679,6 +733,7 @@ DUK_EXTERNAL_DECL void duk_push_thread_stash(duk_context *ctx, duk_context *targ
DUK_EXTERNAL_DECL duk_idx_t duk_push_object(duk_context *ctx);
DUK_EXTERNAL_DECL duk_idx_t duk_push_bare_object(duk_context *ctx);
DUK_EXTERNAL_DECL duk_idx_t duk_push_array(duk_context *ctx);
+DUK_EXTERNAL_DECL duk_idx_t duk_push_bare_array(duk_context *ctx);
DUK_EXTERNAL_DECL duk_idx_t duk_push_c_function(duk_context *ctx, duk_c_function func, duk_idx_t nargs);
DUK_EXTERNAL_DECL duk_idx_t duk_push_c_lightfunc(duk_context *ctx, duk_c_function func, duk_idx_t nargs, duk_idx_t length, duk_int_t magic);
DUK_EXTERNAL_DECL duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags);
@@ -913,6 +968,8 @@ DUK_EXTERNAL_DECL duk_context *duk_require_context(duk_context *ctx, duk_idx_t i
DUK_EXTERNAL_DECL void duk_require_function(duk_context *ctx, duk_idx_t idx);
#define duk_require_callable(ctx,idx) \
duk_require_function((ctx), (idx))
+DUK_EXTERNAL_DECL void duk_require_constructor_call(duk_context *ctx);
+DUK_EXTERNAL_DECL void duk_require_constructable(duk_context *ctx, duk_idx_t idx);
DUK_EXTERNAL_DECL void *duk_require_heapptr(duk_context *ctx, duk_idx_t idx);
/* Symbols are object coercible and covered by DUK_TYPE_MASK_STRING. */
@@ -962,6 +1019,8 @@ DUK_EXTERNAL_DECL void duk_to_primitive(duk_context *ctx, duk_idx_t idx, duk_int
/* safe variants of a few coercion operations */
DUK_EXTERNAL_DECL const char *duk_safe_to_lstring(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len);
+DUK_EXTERNAL_DECL const char *duk_to_stacktrace(duk_context *ctx, duk_idx_t idx);
+DUK_EXTERNAL_DECL const char *duk_safe_to_stacktrace(duk_context *ctx, duk_idx_t idx);
#define duk_safe_to_string(ctx,idx) \
duk_safe_to_lstring((ctx), (idx), NULL)
@@ -986,6 +1045,8 @@ DUK_EXTERNAL_DECL const char *duk_hex_encode(duk_context *ctx, duk_idx_t idx);
DUK_EXTERNAL_DECL void duk_hex_decode(duk_context *ctx, duk_idx_t idx);
DUK_EXTERNAL_DECL const char *duk_json_encode(duk_context *ctx, duk_idx_t idx);
DUK_EXTERNAL_DECL void duk_json_decode(duk_context *ctx, duk_idx_t idx);
+DUK_EXTERNAL_DECL void duk_cbor_encode(duk_context *ctx, duk_idx_t idx, duk_uint_t encode_flags);
+DUK_EXTERNAL_DECL void duk_cbor_decode(duk_context *ctx, duk_idx_t idx, duk_uint_t decode_flags);
DUK_EXTERNAL_DECL const char *duk_buffer_to_string(duk_context *ctx, duk_idx_t idx);
@@ -1000,29 +1061,55 @@ DUK_EXTERNAL_DECL void duk_config_buffer(duk_context *ctx, duk_idx_t idx, void *
/*
* Property access
*
- * The basic function assumes key is on stack. The _string variant takes
- * a C string as a property name, while the _index variant takes an array
- * index as a property name (e.g. 123 is equivalent to the key "123").
+ * The basic function assumes key is on stack. The _(l)string variant takes
+ * a C string as a property name; the _literal variant takes a C literal.
+ * The _index variant takes an array index as a property name (e.g. 123 is
+ * equivalent to the key "123"). The _heapptr variant takes a raw, borrowed
+ * heap pointer.
*/
DUK_EXTERNAL_DECL duk_bool_t duk_get_prop(duk_context *ctx, duk_idx_t obj_idx);
DUK_EXTERNAL_DECL duk_bool_t duk_get_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key);
DUK_EXTERNAL_DECL duk_bool_t duk_get_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len);
+#if defined(DUK_USE_PREFER_SIZE)
+#define duk_get_prop_literal(ctx,obj_idx,key) duk_get_prop_string((ctx), (obj_idx), (key))
+#else
+DUK_EXTERNAL_DECL duk_bool_t duk_get_prop_literal_raw(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len);
+#define duk_get_prop_literal(ctx,obj_idx,key) duk_get_prop_literal_raw((ctx), (obj_idx), (key), sizeof((key)) - 1U)
+#endif
DUK_EXTERNAL_DECL duk_bool_t duk_get_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx);
DUK_EXTERNAL_DECL duk_bool_t duk_get_prop_heapptr(duk_context *ctx, duk_idx_t obj_idx, void *ptr);
DUK_EXTERNAL_DECL duk_bool_t duk_put_prop(duk_context *ctx, duk_idx_t obj_idx);
DUK_EXTERNAL_DECL duk_bool_t duk_put_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key);
DUK_EXTERNAL_DECL duk_bool_t duk_put_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len);
+#if defined(DUK_USE_PREFER_SIZE)
+#define duk_put_prop_literal(ctx,obj_idx,key) duk_put_prop_string((ctx), (obj_idx), (key))
+#else
+DUK_EXTERNAL_DECL duk_bool_t duk_put_prop_literal_raw(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len);
+#define duk_put_prop_literal(ctx,obj_idx,key) duk_put_prop_literal_raw((ctx), (obj_idx), (key), sizeof((key)) - 1U)
+#endif
DUK_EXTERNAL_DECL duk_bool_t duk_put_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx);
DUK_EXTERNAL_DECL duk_bool_t duk_put_prop_heapptr(duk_context *ctx, duk_idx_t obj_idx, void *ptr);
DUK_EXTERNAL_DECL duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_idx);
DUK_EXTERNAL_DECL duk_bool_t duk_del_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key);
DUK_EXTERNAL_DECL duk_bool_t duk_del_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len);
+#if defined(DUK_USE_PREFER_SIZE)
+#define duk_del_prop_literal(ctx,obj_idx,key) duk_del_prop_string((ctx), (obj_idx), (key))
+#else
+DUK_EXTERNAL_DECL duk_bool_t duk_del_prop_literal_raw(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len);
+#define duk_del_prop_literal(ctx,obj_idx,key) duk_del_prop_literal_raw((ctx), (obj_idx), (key), sizeof((key)) - 1U)
+#endif
DUK_EXTERNAL_DECL duk_bool_t duk_del_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx);
DUK_EXTERNAL_DECL duk_bool_t duk_del_prop_heapptr(duk_context *ctx, duk_idx_t obj_idx, void *ptr);
DUK_EXTERNAL_DECL duk_bool_t duk_has_prop(duk_context *ctx, duk_idx_t obj_idx);
DUK_EXTERNAL_DECL duk_bool_t duk_has_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key);
DUK_EXTERNAL_DECL duk_bool_t duk_has_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len);
+#if defined(DUK_USE_PREFER_SIZE)
+#define duk_has_prop_literal(ctx,obj_idx,key) duk_has_prop_string((ctx), (obj_idx), (key))
+#else
+DUK_EXTERNAL_DECL duk_bool_t duk_has_prop_literal_raw(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len);
+#define duk_has_prop_literal(ctx,obj_idx,key) duk_has_prop_literal_raw((ctx), (obj_idx), (key), sizeof((key)) - 1U)
+#endif
DUK_EXTERNAL_DECL duk_bool_t duk_has_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx);
DUK_EXTERNAL_DECL duk_bool_t duk_has_prop_heapptr(duk_context *ctx, duk_idx_t obj_idx, void *ptr);
@@ -1031,8 +1118,22 @@ DUK_EXTERNAL_DECL void duk_def_prop(duk_context *ctx, duk_idx_t obj_idx, duk_uin
DUK_EXTERNAL_DECL duk_bool_t duk_get_global_string(duk_context *ctx, const char *key);
DUK_EXTERNAL_DECL duk_bool_t duk_get_global_lstring(duk_context *ctx, const char *key, duk_size_t key_len);
+#if defined(DUK_USE_PREFER_SIZE)
+#define duk_get_global_literal(ctx,key) duk_get_global_string((ctx), (key))
+#else
+DUK_EXTERNAL_DECL duk_bool_t duk_get_global_literal_raw(duk_context *ctx, const char *key, duk_size_t key_len);
+#define duk_get_global_literal(ctx,key) duk_get_global_literal_raw((ctx), (key), sizeof((key)) - 1U)
+#endif
+DUK_EXTERNAL_DECL duk_bool_t duk_get_global_heapptr(duk_context *ctx, void *ptr);
DUK_EXTERNAL_DECL duk_bool_t duk_put_global_string(duk_context *ctx, const char *key);
DUK_EXTERNAL_DECL duk_bool_t duk_put_global_lstring(duk_context *ctx, const char *key, duk_size_t key_len);
+#if defined(DUK_USE_PREFER_SIZE)
+#define duk_put_global_literal(ctx,key) duk_put_global_string((ctx), (key))
+#else
+DUK_EXTERNAL_DECL duk_bool_t duk_put_global_literal_raw(duk_context *ctx, const char *key, duk_size_t key_len);
+#define duk_put_global_literal(ctx,key) duk_put_global_literal_raw((ctx), (key), sizeof((key)) - 1U)
+#endif
+DUK_EXTERNAL_DECL duk_bool_t duk_put_global_heapptr(duk_context *ctx, void *ptr);
/*
* Inspection
@@ -1099,7 +1200,7 @@ DUK_EXTERNAL_DECL void duk_trim(duk_context *ctx, duk_idx_t idx);
DUK_EXTERNAL_DECL duk_codepoint_t duk_char_code_at(duk_context *ctx, duk_idx_t idx, duk_size_t char_offset);
/*
- * Ecmascript operators
+ * ECMAScript operators
*/
DUK_EXTERNAL_DECL duk_bool_t duk_equals(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2);
@@ -1108,6 +1209,12 @@ DUK_EXTERNAL_DECL duk_bool_t duk_samevalue(duk_context *ctx, duk_idx_t idx1, duk
DUK_EXTERNAL_DECL duk_bool_t duk_instanceof(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2);
/*
+ * Random
+ */
+
+DUK_EXTERNAL_DECL duk_double_t duk_random(duk_context *ctx);
+
+/*
* Function (method) calls
*/
@@ -1257,7 +1364,7 @@ DUK_EXTERNAL_DECL duk_double_t duk_components_to_time(duk_context *ctx, duk_time
#define DUK_DATE_MSEC_HOUR (60L * 60L * 1000L)
#define DUK_DATE_MSEC_DAY (24L * 60L * 60L * 1000L)
-/* Ecmascript date range is 100 million days from Epoch:
+/* ECMAScript date range is 100 million days from Epoch:
* > 100e6 * 24 * 60 * 60 * 1000 // 100M days in millisecs
* 8640000000000000
* (= 8.64e15)
@@ -1265,7 +1372,7 @@ DUK_EXTERNAL_DECL duk_double_t duk_components_to_time(duk_context *ctx, duk_time
#define DUK_DATE_MSEC_100M_DAYS (8.64e15)
#define DUK_DATE_MSEC_100M_DAYS_LEEWAY (8.64e15 + 24 * 3600e3)
-/* Ecmascript year range:
+/* ECMAScript year range:
* > new Date(100e6 * 24 * 3600e3).toISOString()
* '+275760-09-13T00:00:00.000Z'
* > new Date(-100e6 * 24 * 3600e3).toISOString()
@@ -1275,7 +1382,7 @@ DUK_EXTERNAL_DECL duk_double_t duk_components_to_time(duk_context *ctx, duk_time
#define DUK_DATE_MAX_ECMA_YEAR 275760L
/* Part indices for internal breakdowns. Part order from DUK_DATE_IDX_YEAR
- * to DUK_DATE_IDX_MILLISECOND matches argument ordering of Ecmascript API
+ * to DUK_DATE_IDX_MILLISECOND matches argument ordering of ECMAScript API
* calls (like Date constructor call). Some functions in duk_bi_date.c
* depend on the specific ordering, so change with care. 16 bits are not
* enough for all parts (year, specifically).
diff --git a/content/handlers/javascript/duktape/generics.js b/content/handlers/javascript/duktape/generics.js
new file mode 100644
index 000000000..e6e952a46
--- /dev/null
+++ b/content/handlers/javascript/duktape/generics.js
@@ -0,0 +1,129 @@
+/*
+ * Generics for Duktape binding in NetSurf
+ *
+ * The result of this *MUST* be setting a NetSurf object only.
+ *
+ * That object will then be absorbed into the global object as a hidden
+ * object which is used by the rest of the bindings.
+ */
+
+var NetSurf = {
+ /* The make-proxy call for list-type objects */
+ makeListProxy: function(inner) {
+ return new Proxy(inner, {
+ has: function(target, key) {
+ if (typeof key == 'number') {
+ return (key >= 0) && (key < target.length);
+ } else {
+ return key in target;
+ }
+ },
+ get: function(target, key) {
+ if (typeof key == 'number') {
+ return target.item(key);
+ } else {
+ return target[key];
+ }
+ },
+ });
+ },
+ /* The make-proxy call for nodemap-type objects */
+ makeNodeMapProxy: function(inner) {
+ return new Proxy(inner, {
+ has: function(target, key) {
+ if (typeof key == 'number') {
+ return (key >= 0) && (key < target.length);
+ } else {
+ return target.getNamedItem(key) || (key in target);
+ }
+ },
+ get: function(target, key) {
+ if (typeof key == 'number') {
+ return target.item(key);
+ } else {
+ var attr = target.getNamedItem(key);
+ if (attr) {
+ return attr;
+ }
+ return target[key];
+ }
+ },
+ });
+ },
+ consoleFormatter: function Formatter() {
+
+ if (arguments.length == 0) {
+ return new Array("");
+ } else if (arguments.length == 1) {
+ return new Array(arguments[0].toString());
+ }
+
+ const target = arguments[0];
+ const current = arguments[1];
+
+ if (typeof target !== "string") {
+ return Array.from(arguments);
+ }
+
+ const offset = target.search("%");
+
+ if (offset == -1 || offset >= (target.length - 1)) {
+ // We've a string, but the % either doesn't exist or is
+ // at the end of it, so give up
+ return Array.from(arguments);
+ }
+
+ const specifier = target[offset + 1];
+
+ var converted = undefined;
+
+ if (specifier === 's') {
+ // Stringification
+ converted = current.toString();
+ } else if (specifier === 'd' || specifier === 'i') {
+ converted = parseInt(current, 10).toString();
+ } else if (specifier === 'f') {
+ converted = parseFloat(current).toString();
+ } else if (specifier === 'o') {
+ // TODO: Objectification?
+ converted = current.toString();
+ } else if (specifier === 'O') {
+ // TODO: JSONification
+ converted = current.toString();
+ }
+
+ var result = new Array();
+
+ if (converted !== undefined) {
+ // We converted it, so we need to absorb the formatted thing
+ // and move on
+ var newtarget = "";
+ if (offset > 0) {
+ newtarget = target.substring(0, offset);
+ }
+ newtarget = newtarget + converted;
+ if (offset < target.length - 2) {
+ newtarget = newtarget + target.substring(offset + 2, target.length);
+ }
+ result.push(newtarget);
+ } else {
+ // Undefined, so we drop this argument and move on
+ result.push(target);
+ }
+
+ var i;
+ for (i = 2; i < arguments.length; i++) {
+ result.push(arguments[i]);
+ }
+
+ if (result[0].search("%") == -1) {
+ return result;
+ }
+
+ if (result.length === 1) {
+ return result;
+ }
+
+ return Formatter.apply(result);
+ }
+};
diff --git a/content/handlers/javascript/duktape/netsurf.bnd b/content/handlers/javascript/duktape/netsurf.bnd
index 2a56cccb5..483f3471f 100644
--- a/content/handlers/javascript/duktape/netsurf.bnd
+++ b/content/handlers/javascript/duktape/netsurf.bnd
@@ -60,14 +60,19 @@ struct dom_html_br_element;
#include "Document.bnd"
#include "Node.bnd"
#include "NodeList.bnd"
+#include "DOMTokenList.bnd"
+#include "DOMSettableTokenList.bnd"
+#include "NamedNodeMap.bnd"
#include "Element.bnd"
#include "HTMLCollection.bnd"
#include "Location.bnd"
#include "Navigator.bnd"
+#include "DOMImplementation.bnd"
/* events */
#include "Event.bnd"
+#include "KeyboardEvent.bnd"
init MutationEvent(struct dom_mutation_event *evt::evt);
init UIEvent(struct dom_ui_event *evt::evt);
@@ -76,7 +81,6 @@ init MutationNameEvent(struct dom_mutation_name_event *evt::evt);
init MouseWheelEvent(struct dom_mouse_wheel_event *evt::evt);
init MouseMultiWheelEvent(struct dom_mouse_multi_wheel_event *evt::evt);
init MouseEvent(struct dom_mouse_event *evt::evt);
-init KeyboardEvent(struct dom_keyboard_event *evt::evt);
init DocumentEvent(struct dom_document_event *evt::evt);
init CustomEvent(struct dom_custom_event *evt::evt);
init CompositionEvent(struct dom_ui_event *evt::evt);
@@ -107,6 +111,7 @@ init TrackEvent(struct dom_event *evt::evt);
#include "HTMLBodyElement.bnd"
#include "HTMLButtonElement.bnd"
#include "HTMLBRElement.bnd"
+#include "HTMLCanvasElement.bnd"
#include "HTMLDivElement.bnd"
#include "HTMLFontElement.bnd"
#include "HTMLFormElement.bnd"
@@ -147,7 +152,6 @@ init TrackEvent(struct dom_event *evt::evt);
init HTMLUnknownElement(struct dom_html_element *html_unknown_element::html_element);
init HTMLDirectoryElement(struct dom_html_element *html_directory_element::html_element);
-init HTMLCanvasElement(struct dom_html_element *html_canvas_element::html_element);
init HTMLTemplateElement(struct dom_html_element *html_template_element::html_element);
init HTMLDialogElement(struct dom_html_element *html_dialog_element::html_element);
init HTMLMenuItemElement(struct dom_html_element *html_menu_item_element::html_element);
@@ -198,4 +202,12 @@ init HTMLFormControlsCollection(struct dom_html_collection *coll);
init HTMLOptionsCollection(struct dom_html_collection *coll);
init HTMLPropertiesCollection(struct dom_html_collection *coll);
+/* Stuff to do with canvasses */
+#include "CanvasRenderingContext2D.bnd"
+#include "ImageData.bnd"
+
+/* CSS Object model */
+
+#include "CSSRule.bnd"
+#include "CSSStyleSheet.bnd"
diff --git a/content/handlers/javascript/duktape/polyfill.js b/content/handlers/javascript/duktape/polyfill.js
new file mode 100644
index 000000000..6c85ce1a0
--- /dev/null
+++ b/content/handlers/javascript/duktape/polyfill.js
@@ -0,0 +1,103 @@
+/* Polyfiller for Duktape for NetSurf
+ *
+ * This JavaScript will be loaded into heaps before the generics
+ *
+ * We only care for the side-effects of this, be careful.
+ */
+
+// Production steps of ECMA-262, Edition 6, 22.1.2.1
+if (!Array.from) {
+ Array.from = (function () {
+ var toStr = Object.prototype.toString;
+ var isCallable = function (fn) {
+ return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
+ };
+ var toInteger = function (value) {
+ var number = Number(value);
+ if (isNaN(number)) { return 0; }
+ if (number === 0 || !isFinite(number)) { return number; }
+ return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
+ };
+ var maxSafeInteger = Math.pow(2, 53) - 1;
+ var toLength = function (value) {
+ var len = toInteger(value);
+ return Math.min(Math.max(len, 0), maxSafeInteger);
+ };
+
+ // The length property of the from method is 1.
+ return function from(arrayLike/*, mapFn, thisArg */) {
+ // 1. Let C be the this value.
+ var C = this;
+
+ // 2. Let items be ToObject(arrayLike).
+ var items = Object(arrayLike);
+
+ // 3. ReturnIfAbrupt(items).
+ if (arrayLike == null) {
+ throw new TypeError('Array.from requires an array-like object - not null or undefined');
+ }
+
+ // 4. If mapfn is undefined, then let mapping be false.
+ var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
+ var T;
+ if (typeof mapFn !== 'undefined') {
+ // 5. else
+ // 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
+ if (!isCallable(mapFn)) {
+ throw new TypeError('Array.from: when provided, the second argument must be a function');
+ }
+
+ // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
+ if (arguments.length > 2) {
+ T = arguments[2];
+ }
+ }
+
+ // 10. Let lenValue be Get(items, "length").
+ // 11. Let len be ToLength(lenValue).
+ var len = toLength(items.length);
+
+ // 13. If IsConstructor(C) is true, then
+ // 13. a. Let A be the result of calling the [[Construct]] internal method
+ // of C with an argument list containing the single item len.
+ // 14. a. Else, Let A be ArrayCreate(len).
+ var A = isCallable(C) ? Object(new C(len)) : new Array(len);
+
+ // 16. Let k be 0.
+ var k = 0;
+ // 17. Repeat, while k < len… (also steps a - h)
+ var kValue;
+ while (k < len) {
+ kValue = items[k];
+ if (mapFn) {
+ A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
+ } else {
+ A[k] = kValue;
+ }
+ k += 1;
+ }
+ // 18. Let putStatus be Put(A, "length", len, true).
+ A.length = len;
+ // 20. Return A.
+ return A;
+ };
+ }());
+}
+
+// DOMTokenList formatter, in theory we can remove this if we do the stringifier IDL support
+
+DOMTokenList.prototype.toString = function () {
+ if (this.length == 0) {
+ return "";
+ }
+
+ var ret = this.item(0);
+ for (var index = 1; index < this.length; index++) {
+ ret = ret + " " + this.item(index);
+ }
+
+ return ret;
+}
+
+// Inherit the same toString for settable lists
+DOMSettableTokenList.prototype.toString = DOMTokenList.prototype.toString; \ No newline at end of file
diff --git a/content/handlers/javascript/js.h b/content/handlers/javascript/js.h
index 2929d0b5e..55f8e22ef 100644
--- a/content/handlers/javascript/js.h
+++ b/content/handlers/javascript/js.h
@@ -20,61 +20,121 @@
* Interface to javascript engine functions.
*/
-#ifndef _NETSURF_JAVASCRIPT_JS_H_
-#define _NETSURF_JAVASCRIPT_JS_H_
+#ifndef NETSURF_JAVASCRIPT_JS_H_
+#define NETSURF_JAVASCRIPT_JS_H_
#include "utils/errors.h"
-
-typedef struct jscontext jscontext;
-typedef struct jsobject jsobject;
-
-typedef bool(jscallback)(void *ctx);
-
struct dom_event;
struct dom_document;
struct dom_node;
struct dom_element;
struct dom_string;
-/** Initialise javascript interpreter */
+/**
+ * JavaScript interpreter heap
+ *
+ * In order to try and be moderately performant, we create a heap
+ * per browser window. This heap is shared by all browsing contexts
+ * we end up creating in that window.
+ */
+typedef struct jsheap jsheap;
+
+/**
+ * JavaScript interpreter thread
+ *
+ * When we create a browsing context itself (window+content) we have
+ * to create a JS thread to attach to the browsing context.
+ *
+ * JS threads are associated with heaps and will be destroyed when
+ * the heap is destroyed. They can be shut down manually though
+ * and should be for object lifetime safety reasons.
+ */
+typedef struct jsthread jsthread;
+
+/**
+ * Initialise javascript interpreter
+ */
void js_initialise(void);
-/** finalise javascript interpreter */
+/**
+ * finalise javascript interpreter
+ */
void js_finalise(void);
-/** Create a new javascript context.
+/**
+ * Create a new javascript heap.
*
- * There is usually one context per browser context
+ * There is usually one heap per browser window.
*
- * \param timeout elapsed wallclock time (in seconds) before \a callback is called
- * \param cb the callback when the runtime exceeds the timeout
- * \param cbctx The context to pass to the callback
- * \param jsctx Updated to the created JS context
+ * \param timeout elapsed wallclock time (in seconds) before \a callback is called
+ * \param heap Updated to the created JS heap
* \return NSERROR_OK on success, appropriate error otherwise.
*/
-nserror js_newcontext(int timeout, jscallback *cb, void *cbctx,
- jscontext **jsctx);
+nserror js_newheap(int timeout, jsheap **heap);
-/** Destroy a previously created context */
-void js_destroycontext(jscontext *ctx);
+/**
+ * Destroy a previously created heap.
+ *
+ * \param heap The heap to destroy
+ */
+void js_destroyheap(jsheap *heap);
-/** Create a new javascript compartment
+/**
+ * Create a new javascript thread
*
* This is called once for a page with javascript script tags on
- * it. It constructs a fresh global window object.
+ * it. It constructs a fresh global window object and prepares the JS
+ * browsing context. It's important that threads are shut down cleanly
+ * when the browsing context is going to be cleaned up.
+ *
+ * \param heap The heap to create the thread within
+ * \param win_priv The value to give to the Window constructor as the window
+ * \param doc_priv The value to give to the Document constructor as the document
+ * \param thread Updated to the created thread
+ * \return NSERROR_OK on success, appropriate error otherwise
+ */
+nserror js_newthread(jsheap *heap, void *win_priv, void *doc_priv, jsthread **thread);
+
+/**
+ * Close a javascript thread
+ *
+ * This should be called when the HTML content which owns the thread is
+ * being closed. This is a separate process from destroying the thread
+ * and merely disconnects any callbacks and thus hopefully stops
+ * additional JS things from triggering. If any code runs and attempts to
+ * register callbacks after closedown, they will fail.
+ *
+ * \param thread The thread to close down
+ * \return NSERROR_OK on success, appropriate error otherwise
*/
-jsobject *js_newcompartment(jscontext *ctx, void *win_priv, void *doc_priv);
+nserror js_closethread(jsthread *thread);
-/* execute some javascript in a context */
-bool js_exec(jscontext *ctx, const char *txt, size_t txtlen);
+/**
+ * Destroy a javascript thread
+ *
+ * This should be called when the browsing context is done with the thread.
+ *
+ * This will be called when the HTML content associated with the browsing
+ * context is being destroyed. The thread should have already been closed
+ * down during the HTML content close.
+ *
+ * \param thread The thread to be destroyed
+ */
+void js_destroythread(jsthread *thread);
+/**
+ * execute some javascript in a context
+ */
+bool js_exec(jsthread *thread, const uint8_t *txt, size_t txtlen, const char *name);
-/* fire an event at a dom node */
-bool js_fire_event(jscontext *ctx, const char *type, struct dom_document *doc, struct dom_node *target);
+/**
+ * fire an event at a dom node
+ */
+bool js_fire_event(jsthread *thread, const char *type, struct dom_document *doc, struct dom_node *target);
bool
-js_dom_event_add_listener(jscontext *ctx,
+js_dom_event_add_listener(jsthread *thread,
struct dom_document *document,
struct dom_node *node,
struct dom_string *event_type_dom,
@@ -82,21 +142,23 @@ js_dom_event_add_listener(jscontext *ctx,
/*** New Events ***/
-/** Handle a new element being created.
+/**
+ * Handle a new element being created.
*
* This is called once an element is inserted into the DOM document handled
* by the context provided. The JS implementation must then scan the element
* for on* attributes and register appropriate listeners for those handlers.
*/
-void js_handle_new_element(jscontext *ctx, struct dom_element *node);
+void js_handle_new_element(jsthread *thread, struct dom_element *node);
-/** Handle an event propagation finished callback.
+/**
+ * Handle an event propagation finished callback.
*
* This is called once an event finishes propagating, no matter how it
* finishes. The intent here is that the JS context can perform any cleanups
* it may need to perform before the DOM finishes and the event may end up
* freed.
*/
-void js_event_cleanup(jscontext *ctx, struct dom_event *evt);
+void js_event_cleanup(jsthread *thread, struct dom_event *evt);
-#endif /* _NETSURF_JAVASCRIPT_JS_H_ */
+#endif /* NETSURF_JAVASCRIPT_JS_H_ */
diff --git a/content/handlers/javascript/none/none.c b/content/handlers/javascript/none/none.c
index 9a8b0a49d..12dbc9a02 100644
--- a/content/handlers/javascript/none/none.c
+++ b/content/handlers/javascript/none/none.c
@@ -20,6 +20,7 @@
* Dummy implementation of javascript engine functions.
*/
+#include "utils/errors.h"
#include "content/content.h"
#include "utils/nsoption.h"
@@ -35,36 +36,45 @@ void js_finalise(void)
{
}
-nserror js_newcontext(int timeout, jscallback *cb, void *cbctx,
- jscontext **jsctx)
+nserror js_newheap(int timeout, jsheap **heap)
{
- *jsctx = NULL;
+ *heap = NULL;
return NSERROR_OK;
}
-void js_destroycontext(jscontext *ctx)
+void js_destroyheap(jsheap *heap)
{
}
-jsobject *js_newcompartment(jscontext *ctx, void *win_priv, void *doc_priv)
+nserror js_newthread(jsheap *heap, void *win_priv, void *doc_priv, jsthread **thread)
{
- return NULL;
+ *thread = NULL;
+ return NSERROR_NOT_IMPLEMENTED;
}
-bool js_exec(jscontext *ctx, const char *txt, size_t txtlen)
+nserror js_closethread(jsthread *thread)
+{
+ return NSERROR_OK;
+}
+
+void js_destroythread(jsthread *thread)
+{
+}
+
+bool js_exec(jsthread *thread, const uint8_t *txt, size_t txtlen, const char *name)
{
return true;
}
-bool js_fire_event(jscontext *ctx, const char *type, struct dom_document *doc, struct dom_node *target)
+bool js_fire_event(jsthread *thread, const char *type, struct dom_document *doc, struct dom_node *target)
{
return true;
}
-void js_handle_new_element(jscontext *ctx, struct dom_element *node)
+void js_handle_new_element(jsthread *thread, struct dom_element *node)
{
}
-void js_event_cleanup(jscontext *ctx, struct dom_event *evt)
+void js_event_cleanup(jsthread *thread, struct dom_event *evt)
{
}
diff --git a/content/handlers/text/Makefile b/content/handlers/text/Makefile
new file mode 100644
index 000000000..83d5dbd1e
--- /dev/null
+++ b/content/handlers/text/Makefile
@@ -0,0 +1,3 @@
+# text content handler sources
+
+S_TEXT := textplain.c
diff --git a/render/textplain.c b/content/handlers/text/textplain.c
index 0036eb5c0..cee89a1a5 100644
--- a/render/textplain.c
+++ b/content/handlers/text/textplain.c
@@ -23,45 +23,40 @@
* plain text content handling implementation.
*/
-#include <assert.h>
-#include <errno.h>
-#include <stddef.h>
#include <string.h>
-#include <strings.h>
-#include <math.h>
-
#include <parserutils/input/inputstream.h>
-#include <parserutils/charset/utf8.h>
+#include "utils/errors.h"
#include "utils/corestrings.h"
#include "utils/http.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utils.h"
#include "utils/utf8.h"
+#include "utils/nsoption.h"
#include "netsurf/content.h"
#include "netsurf/keypress.h"
#include "netsurf/browser_window.h"
#include "netsurf/plotters.h"
#include "netsurf/layout.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
#include "content/hlcache.h"
-#include "css/utils.h"
-#include "utils/nsoption.h"
-#include "desktop/search.h"
+#include "content/textsearch.h"
+#include "content/handlers/css/utils.h"
#include "desktop/selection.h"
#include "desktop/gui_internal.h"
-#include "render/search.h"
-#include "render/textplain.h"
-#include "render/html.h"
-#include "render/search.h"
+#include "text/textplain.h"
struct textplain_line {
size_t start;
size_t length;
};
+/**
+ * plain text content
+ */
typedef struct textplain_content {
struct content base;
@@ -75,12 +70,8 @@ typedef struct textplain_content {
int formatted_width;
struct browser_window *bw;
- struct selection sel; /** Selection state */
+ struct selection *sel; /** Selection state */
- /** Context for free text search, or NULL if none */
- struct search_context *search;
- /** Current search string, or NULL if none */
- char *search_string;
} textplain_content;
@@ -88,7 +79,7 @@ typedef struct textplain_content {
#define MARGIN 4
#define TAB_WIDTH 8 /* must be power of 2 currently */
-#define TEXT_SIZE 10 * FONT_SIZE_SCALE /* Unscaled text size in pt */
+#define TEXT_SIZE 10 * PLOT_STYLE_SCALE /* Unscaled text size in pt */
static plot_font_style_t textplain_style = {
.family = PLOT_FONT_FAMILY_MONOSPACE,
@@ -151,7 +142,7 @@ textplain_create_internal(textplain_content *c, lwc_string *encoding)
parserutils_inputstream *stream;
parserutils_error error;
- textplain_style.size = (nsoption_int(font_size) * FONT_SIZE_SCALE) / 10;
+ textplain_style.size = (nsoption_int(font_size) * PLOT_STYLE_SCALE) / 10;
utf8_data = malloc(CHUNK);
if (utf8_data == NULL)
@@ -178,13 +169,12 @@ textplain_create_internal(textplain_content *c, lwc_string *encoding)
c->physical_line_count = 0;
c->formatted_width = 0;
c->bw = NULL;
-
- selection_prepare(&c->sel, (struct content *)c, false);
+ c->sel = selection_create((struct content *)c);
return NSERROR_OK;
no_memory:
- content_broadcast_errorcode(&c->base, NSERROR_NOMEM);
+ content_broadcast_error(&c->base, NSERROR_NOMEM, NULL);
return NSERROR_NOMEM;
}
@@ -196,7 +186,7 @@ no_memory:
static nserror
textplain_create(const content_handler *handler,
lwc_string *imime_type,
- const http_parameter *params,
+ const struct http_parameter *params,
llcache_handle *llcache,
const char *fallback_charset,
bool quirks,
@@ -274,7 +264,7 @@ textplain_drain_input(textplain_content *c,
parserutils_inputstream *stream,
parserutils_error terminator)
{
- static const uint8_t *u_fffd = (const uint8_t *) "\xef\xbf\xfd";
+ static const uint8_t *u_fffd = (const uint8_t *) "\xef\xbf\xbd";
const uint8_t *ch;
size_t chlen, offset = 0;
@@ -359,7 +349,7 @@ textplain_process_data(struct content *c, const char *data, unsigned int size)
return true;
no_memory:
- content_broadcast_errorcode(c, NSERROR_NOMEM);
+ content_broadcast_error(c, NSERROR_NOMEM, NULL);
return false;
}
@@ -402,7 +392,7 @@ static float textplain_line_height(void)
/* Size is in points, so convert to pixels.
* Then use a constant line height of 1.2 x font size.
*/
- return FIXTOFLT(FDIV((FMUL(FLTTOFIX(1.2), FMUL(nscss_screen_dpi, INTTOFIX((textplain_style.size / FONT_SIZE_SCALE))))), F_72));
+ return FIXTOFLT(FDIV((FMUL(FLTTOFIX(1.2), FMUL(nscss_screen_dpi, INTTOFIX((textplain_style.size / PLOT_STYLE_SCALE))))), F_72));
}
@@ -548,6 +538,10 @@ static void textplain_destroy(struct content *c)
if (text->utf8_data != NULL) {
free(text->utf8_data);
}
+
+ if (text->sel != NULL) {
+ selection_destroy(text->sel);
+ }
}
@@ -556,8 +550,8 @@ static nserror textplain_clone(const struct content *old, struct content **newc)
const textplain_content *old_text = (textplain_content *) old;
textplain_content *text;
nserror error;
- const char *data;
- unsigned long size;
+ const uint8_t *data;
+ size_t size;
text = calloc(1, sizeof(textplain_content));
if (text == NULL)
@@ -578,7 +572,9 @@ static nserror textplain_clone(const struct content *old, struct content **newc)
data = content__get_source_data(&text->base, &size);
if (size > 0) {
- if (textplain_process_data(&text->base, data, size) == false) {
+ if (textplain_process_data(&text->base,
+ (const char *)data,
+ size) == false) {
content_destroy(&text->base);
return NSERROR_NOMEM;
}
@@ -603,6 +599,94 @@ static content_type textplain_content_type(void)
/**
+ * Return byte offset within UTF8 textplain content.
+ *
+ * given the co-ordinates of a point within a textplain content. 'dir'
+ * specifies the direction in which to search (-1 = above-left, +1 =
+ * below-right) if the co-ordinates are not contained within a line.
+ *
+ * \param[in] c content of type CONTENT_TEXTPLAIN
+ * \param[in] x x ordinate of point
+ * \param[in] y y ordinate of point
+ * \param[in] dir direction of search if not within line
+ * \return byte offset of character containing (or nearest to) point
+ */
+static size_t
+textplain_offset_from_coords(struct content *c, int x, int y, int dir)
+{
+ textplain_content *textc = (textplain_content *) c;
+ float line_height = textplain_line_height();
+ struct textplain_line *line;
+ const char *text;
+ unsigned nlines;
+ size_t length;
+ int idx;
+
+ assert(c != NULL);
+
+ y = (int)((float)(y - MARGIN) / line_height);
+ x -= MARGIN;
+
+ nlines = textc->physical_line_count;
+ if (!nlines)
+ return 0;
+
+ if (y <= 0) y = 0;
+ else if ((unsigned)y >= nlines)
+ y = nlines - 1;
+
+ line = &textc->physical_line[y];
+ text = textc->utf8_data + line->start;
+ length = line->length;
+ idx = 0;
+
+ while (x > 0) {
+ size_t next_offset = 0;
+ int width = INT_MAX;
+
+ while (next_offset < length && text[next_offset] != '\t') {
+ next_offset = utf8_next(text, length, next_offset);
+ }
+
+ if (next_offset < length) {
+ guit->layout->width(&textplain_style,
+ text,
+ next_offset,
+ &width);
+ }
+
+ if (x <= width) {
+ int pixel_offset;
+ size_t char_offset;
+
+ guit->layout->position(&textplain_style,
+ text, next_offset, x,
+ &char_offset, &pixel_offset);
+
+ idx += char_offset;
+ break;
+ }
+
+ x -= width;
+ length -= next_offset;
+ text += next_offset;
+ idx += next_offset;
+
+ /* check if it's within the tab */
+ width = textplain_tab_width - (width % textplain_tab_width);
+ if (x <= width) break;
+
+ x -= width;
+ length--;
+ text++;
+ idx++;
+ }
+
+ return line->start + idx;
+}
+
+
+/**
* Handle mouse clicks and movements in a TEXTPLAIN content window.
*
* \param c content of type textplain
@@ -611,7 +695,7 @@ static content_type textplain_content_type(void)
* \param x coordinate of mouse
* \param y coordinate of mouse
*/
-static void
+static nserror
textplain_mouse_action(struct content *c,
struct browser_window *bw,
browser_mouse_state mouse,
@@ -627,9 +711,9 @@ textplain_mouse_action(struct content *c,
browser_window_set_drag_type(bw, DRAGGING_NONE, NULL);
idx = textplain_offset_from_coords(c, x, y, dir);
- if (selection_click(&text->sel, mouse, idx)) {
+ if (selection_click(text->sel, text->bw, mouse, idx)) {
- if (selection_dragging(&text->sel)) {
+ if (selection_dragging(text->sel)) {
browser_window_set_drag_type(bw,
DRAGGING_SELECTION, NULL);
status = messages_get("Selecting");
@@ -647,6 +731,8 @@ textplain_mouse_action(struct content *c,
msg_data.pointer = pointer;
content_broadcast(c, CONTENT_MSG_POINTER, &msg_data);
+
+ return NSERROR_OK;
}
@@ -659,7 +745,7 @@ textplain_mouse_action(struct content *c,
* \param x coordinate of mouse
* \param y coordinate of mouse
*/
-static void
+static nserror
textplain_mouse_track(struct content *c,
struct browser_window *bw,
browser_mouse_state mouse,
@@ -671,11 +757,11 @@ textplain_mouse_track(struct content *c,
int dir = -1;
size_t idx;
- if (selection_dragging_start(&text->sel))
+ if (selection_dragging_start(text->sel))
dir = 1;
idx = textplain_offset_from_coords(c, x, y, dir);
- selection_track(&text->sel, mouse, idx);
+ selection_track(text->sel, mouse, idx);
browser_window_set_drag_type(bw, DRAGGING_NONE, NULL);
}
@@ -686,10 +772,10 @@ textplain_mouse_track(struct content *c,
int dir = -1;
size_t idx;
- if (selection_dragging_start(&text->sel)) dir = 1;
+ if (selection_dragging_start(text->sel)) dir = 1;
idx = textplain_offset_from_coords(c, x, y, dir);
- selection_track(&text->sel, mouse, idx);
+ selection_track(text->sel, mouse, idx);
}
break;
@@ -697,6 +783,8 @@ textplain_mouse_track(struct content *c,
textplain_mouse_action(c, bw, mouse, x, y);
break;
}
+
+ return NSERROR_OK;
}
@@ -710,7 +798,7 @@ textplain_mouse_track(struct content *c,
static bool textplain_keypress(struct content *c, uint32_t key)
{
textplain_content *text = (textplain_content *) c;
- struct selection *sel = &text->sel;
+ struct selection *sel = text->sel;
switch (key) {
case NS_KEY_COPY_SELECTION:
@@ -726,13 +814,8 @@ static bool textplain_keypress(struct content *c, uint32_t key)
return true;
case NS_KEY_ESCAPE:
- if (selection_defined(sel)) {
- selection_clear(sel, true);
- return true;
- }
-
/* if there's no selection, leave Escape for the caller */
- return false;
+ return selection_clear(sel, true);
}
return false;
@@ -740,74 +823,216 @@ static bool textplain_keypress(struct content *c, uint32_t key)
/**
- * Terminate a search.
+ * Redraw a text string with highlighting
+ * (for selection/search)
*
- * \param c content of type text
+ * \param utf8_text pointer to UTF-8 text string
+ * \param utf8_len length of string, in bytes
+ * \param offset byte offset within textual representation
+ * \param x x ordinate at which to plot text
+ * \param y y ordinate at which to plot text
+ * \param clip pointer to current clip rectangle
+ * \param height height of text string
+ * \param scale current display scale (1.0 = 100%)
+ * \param text Content being redrawn.
+ * \param sel Selection context
+ * \param search Search context
+ * \param ctx current redraw context
+ * \return true iff successful and redraw should proceed
*/
-static void textplain_search_clear(struct content *c)
+static bool
+text_draw(const char *utf8_text,
+ size_t utf8_len,
+ size_t offset,
+ int x,
+ int y,
+ const struct rect *clip,
+ int height,
+ float scale,
+ textplain_content *text,
+ const struct selection *sel,
+ const struct redraw_context *ctx)
{
- textplain_content *text = (textplain_content *) c;
+ bool highlighted = false;
+ plot_font_style_t plot_fstyle;
+ nserror res;
- assert(c != NULL);
+ /* Need scaled text size to pass to plotters */
+ plot_fstyle = textplain_style;
+ plot_fstyle.size *= scale;
+
+ /* is this box part of a selection? */
+ if (ctx->interactive == true) {
+ unsigned len = utf8_len;
+ unsigned start_idx;
+ unsigned end_idx;
+
+ /* first try the browser window's current selection */
+ if (selection_highlighted(sel,
+ offset,
+ offset + len,
+ &start_idx,
+ &end_idx)) {
+ highlighted = true;
+ }
- free(text->search_string);
- text->search_string = NULL;
+ /* what about the current search operation, if any? */
+ if (!highlighted &&
+ (text->base.textsearch.context != NULL) &&
+ content_textsearch_ishighlighted(text->base.textsearch.context,
+ offset,
+ offset + len,
+ &start_idx,
+ &end_idx)) {
+ highlighted = true;
+ }
- if (text->search != NULL) {
- search_destroy_context(text->search);
- }
- text->search = NULL;
-}
+ /* \todo make search terms visible within selected text */
+ if (highlighted) {
+ struct rect r;
+ unsigned endtxt_idx = end_idx;
+ bool clip_changed = false;
+ bool text_visible = true;
+ int startx, endx;
+ plot_style_t pstyle_fill_hback = *plot_style_fill_white;
+ plot_font_style_t fstyle_hback = plot_fstyle;
+
+ if (end_idx > utf8_len) {
+ /* adjust for trailing space, not present in
+ * utf8_text
+ */
+ assert(end_idx == utf8_len + 1);
+ endtxt_idx = utf8_len;
+ }
+ res = guit->layout->width(&textplain_style,
+ utf8_text,
+ start_idx,
+ &startx);
+ if (res != NSERROR_OK) {
+ startx = 0;
+ }
-/**
- * Handle search.
- *
- * \param c content of type text
- * \param gui_data front end private data
- * \param flags search flags
- * \param string search string
- */
-static void textplain_search(struct content *c, void *gui_data,
- search_flags_t flags, const char *string)
-{
- textplain_content *text = (textplain_content *) c;
+ res = guit->layout->width(&textplain_style,
+ utf8_text,
+ endtxt_idx,
+ &endx);
+ if (res != NSERROR_OK) {
+ endx = 0;
+ }
- assert(c != NULL);
+ if (scale != 1.0) {
+ startx *= scale;
+ endx *= scale;
+ }
- if (string != NULL && text->search_string != NULL &&
- strcmp(string, text->search_string) == 0 &&
- text->search != NULL) {
- /* Continue prev. search */
- search_step(text->search, flags, string);
-
- } else if (string != NULL) {
- /* New search */
- free(text->search_string);
- text->search_string = strdup(string);
- if (text->search_string == NULL)
- return;
-
- if (text->search != NULL) {
- search_destroy_context(text->search);
- text->search = NULL;
- }
+ /* draw any text preceding highlighted portion */
+ if (start_idx > 0) {
+ res = ctx->plot->text(ctx,
+ &plot_fstyle,
+ x,
+ y + (int)(height * 0.75 * scale),
+ utf8_text,
+ start_idx);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+ }
- text->search = search_create_context(c, CONTENT_TEXTPLAIN,
- gui_data);
+ pstyle_fill_hback.fill_colour = textplain_style.foreground;
- if (text->search == NULL)
- return;
+ /* highlighted portion */
+ r.x0 = x + startx;
+ r.y0 = y;
+ r.x1 = x + endx;
+ r.y1 = y + height * scale;
+ res = ctx->plot->rectangle(ctx, &pstyle_fill_hback, &r);
+ if (res != NSERROR_OK) {
+ return false;
+ }
- search_step(text->search, flags, string);
+ if (start_idx > 0) {
+ int px0 = max(x + startx, clip->x0);
+ int px1 = min(x + endx, clip->x1);
- } else {
- /* Clear search */
- textplain_search_clear(c);
+ if (px0 < px1) {
+ r.x0 = px0;
+ r.y0 = clip->y0;
+ r.x1 = px1;
+ r.y1 = clip->y1;
+ res = ctx->plot->clip(ctx, &r);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+
+ clip_changed = true;
+ } else {
+ text_visible = false;
+ }
+ }
+
+ fstyle_hback.background =
+ pstyle_fill_hback.fill_colour;
+ fstyle_hback.foreground = colour_to_bw_furthest(
+ pstyle_fill_hback.fill_colour);
+
+ if (text_visible &&
+ (ctx->plot->text(ctx,
+ &fstyle_hback,
+ x,
+ y + (int)(height * 0.75 * scale),
+ utf8_text,
+ endtxt_idx) != NSERROR_OK)) {
+ return false;
+ }
+
+ /* draw any text succeeding highlighted portion */
+ if (endtxt_idx < utf8_len) {
+ int px0 = max(x + endx, clip->x0);
+ if (px0 < clip->x1) {
+
+ r.x0 = px0;
+ r.y0 = clip->y0;
+ r.x1 = clip->x1;
+ r.y1 = clip->y1;
+ res = ctx->plot->clip(ctx, &r);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+
+ clip_changed = true;
+
+ res = ctx->plot->text(ctx,
+ &plot_fstyle,
+ x,
+ y + (int)(height * 0.75 * scale),
+ utf8_text,
+ utf8_len);
+ if (res != NSERROR_OK) {
+ return false;
+ }
+ }
+ }
+
+ if (clip_changed &&
+ (ctx->plot->clip(ctx, clip) != NSERROR_OK)) {
+ return false;
+ }
+ }
+ }
- free(text->search_string);
- text->search_string = NULL;
+ if (!highlighted) {
+ res = ctx->plot->text(ctx,
+ &plot_fstyle,
+ x,
+ y + (int) (height * 0.75 * scale),
+ utf8_text,
+ utf8_len);
+ if (res != NSERROR_OK) {
+ return false;
+ }
}
+ return true;
}
@@ -892,17 +1117,26 @@ textplain_redraw(struct content *c,
int ntx;
nserror res;
- while (next_offset < length && text_d[next_offset] != '\t')
- next_offset = utf8_next(text_d, length, next_offset);
+ while ((next_offset < length) &&
+ (text_d[next_offset] != '\t')) {
+ next_offset = utf8_next(text_d,
+ length,
+ next_offset);
+ }
- if (!text_redraw(text_d + offset, next_offset - offset,
- line[lineno].start + offset, 0,
- &textplain_style,
- tx, y + (lineno * scaled_line_height),
- clip, line_height, data->scale, false,
- (struct content *)text, &text->sel,
- text->search, ctx))
+ if (!text_draw(text_d + offset,
+ next_offset - offset,
+ line[lineno].start + offset,
+ tx,
+ y + (lineno * scaled_line_height),
+ clip,
+ line_height,
+ data->scale,
+ text,
+ text->sel,
+ ctx)) {
return false;
+ }
if (next_offset >= length)
break;
@@ -926,28 +1160,30 @@ textplain_redraw(struct content *c,
if (bw) {
unsigned tab_ofst = line[lineno].start + next_offset;
- struct selection *sel = &text->sel;
+ struct selection *sel = text->sel;
bool highlighted = false;
- if (selection_defined(sel)) {
- unsigned start_idx, end_idx;
- if (selection_highlighted(sel,
- tab_ofst,
- tab_ofst + 1,
- &start_idx,
- &end_idx))
- highlighted = true;
+ unsigned start_idx, end_idx;
+ if (selection_highlighted(sel,
+ tab_ofst,
+ tab_ofst + 1,
+ &start_idx,
+ &end_idx)) {
+ highlighted = true;
}
- if (!highlighted && (text->search != NULL)) {
+
+ if (!highlighted &&
+ (c->textsearch.context != NULL)) {
unsigned start_idx, end_idx;
- if (search_term_highlighted(c,
- tab_ofst,
- tab_ofst + 1,
- &start_idx,
- &end_idx,
- text->search))
+ if (content_textsearch_ishighlighted(
+ c->textsearch.context,
+ tab_ofst,
+ tab_ofst + 1,
+ &start_idx,
+ &end_idx)) {
highlighted = true;
+ }
}
if (highlighted) {
@@ -977,7 +1213,7 @@ textplain_redraw(struct content *c,
/**
* Handle a window containing a CONTENT_TEXTPLAIN being opened.
*/
-static void
+static nserror
textplain_open(struct content *c,
struct browser_window *bw,
struct content *page,
@@ -988,22 +1224,22 @@ textplain_open(struct content *c,
text->bw = bw;
/* text selection */
- selection_init(&text->sel, NULL, NULL);
+ selection_init(text->sel);
+
+ return NSERROR_OK;
}
/**
* Handle a window containing a CONTENT_TEXTPLAIN being closed.
*/
-static void textplain_close(struct content *c)
+static nserror textplain_close(struct content *c)
{
textplain_content *text = (textplain_content *) c;
- if (text->search != NULL) {
- search_destroy_context(text->search);
- }
-
text->bw = NULL;
+
+ return NSERROR_OK;
}
@@ -1014,7 +1250,7 @@ static char *textplain_get_selection(struct content *c)
{
textplain_content *text = (textplain_content *) c;
- return selection_get_copy(&text->sel);
+ return selection_get_copy(text->sel);
}
@@ -1063,55 +1299,12 @@ textplain_coord_from_offset(const char *text, size_t offset, size_t length)
/**
- * plain text content handler table
+ * Retrieve number of lines in content
+ *
+ * \param[in] c Content to retrieve line count from
+ * \return Number of lines
*/
-static const content_handler textplain_content_handler = {
- .fini = textplain_fini,
- .create = textplain_create,
- .process_data = textplain_process_data,
- .data_complete = textplain_convert,
- .reformat = textplain_reformat,
- .destroy = textplain_destroy,
- .mouse_track = textplain_mouse_track,
- .mouse_action = textplain_mouse_action,
- .keypress = textplain_keypress,
- .search = textplain_search,
- .search_clear = textplain_search_clear,
- .redraw = textplain_redraw,
- .open = textplain_open,
- .close = textplain_close,
- .get_selection = textplain_get_selection,
- .clone = textplain_clone,
- .type = textplain_content_type,
- .no_share = true,
-};
-
-
-/* exported interface documented in render/textplain.h */
-nserror textplain_init(void)
-{
- lwc_error lerror;
- nserror error;
-
- lerror = lwc_intern_string("Windows-1252",
- SLEN("Windows-1252"),
- &textplain_default_charset);
- if (lerror != lwc_error_ok) {
- return NSERROR_NOMEM;
- }
-
- error = content_factory_register_handler("text/plain",
- &textplain_content_handler);
- if (error != NSERROR_OK) {
- lwc_string_unref(textplain_default_charset);
- }
-
- return error;
-}
-
-
-/* exported interface documented in render/textplain.h */
-unsigned long textplain_line_count(struct content *c)
+static unsigned long textplain_line_count(struct content *c)
{
textplain_content *text = (textplain_content *) c;
@@ -1121,94 +1314,150 @@ unsigned long textplain_line_count(struct content *c)
}
-/* exported interface documented in render/textplain.h */
-size_t textplain_size(struct content *c)
+/**
+ * Return a pointer to the requested line of text.
+ *
+ * \param[in] c content of type CONTENT_TEXTPLAIN
+ * \param[in] lineno line number
+ * \param[out] poffset receives byte offset of line start within text
+ * \param[out] plen receives length of returned line
+ * \return pointer to text, or NULL if invalid line number
+ */
+static char *
+textplain_get_line(struct content *c,
+ unsigned lineno,
+ size_t *poffset,
+ size_t *plen)
{
textplain_content *text = (textplain_content *) c;
+ struct textplain_line *line;
assert(c != NULL);
- return text->utf8_data_size;
+ if (lineno >= text->physical_line_count)
+ return NULL;
+ line = &text->physical_line[lineno];
+
+ *poffset = line->start;
+ *plen = line->length;
+ return text->utf8_data + line->start;
}
-/* exported interface documented in render/textplain.h */
-size_t textplain_offset_from_coords(struct content *c, int x, int y, int dir)
+/**
+ * Find line number of byte in text
+ *
+ * Given a byte offset within the text, return the line number
+ * of the line containing that offset.
+ *
+ * \param[in] c content of type CONTENT_TEXTPLAIN
+ * \param[in] offset byte offset within textual representation
+ * \return line number, or -1 if offset invalid (larger than size)
+ */
+static int textplain_find_line(struct content *c, unsigned offset)
{
- textplain_content *textc = (textplain_content *) c;
- float line_height = textplain_line_height();
+ textplain_content *text = (textplain_content *) c;
struct textplain_line *line;
- const char *text;
- unsigned nlines;
- size_t length;
- int idx;
+ int nlines;
+ int lineno = 0;
assert(c != NULL);
- y = (int)((float)(y - MARGIN) / line_height);
- x -= MARGIN;
-
- nlines = textc->physical_line_count;
- if (!nlines)
- return 0;
-
- if (y <= 0) y = 0;
- else if ((unsigned)y >= nlines)
- y = nlines - 1;
-
- line = &textc->physical_line[y];
- text = textc->utf8_data + line->start;
- length = line->length;
- idx = 0;
+ line = text->physical_line;
+ nlines = text->physical_line_count;
- while (x > 0) {
- size_t next_offset = 0;
- int width = INT_MAX;
+ if (offset > text->utf8_data_size) {
+ return -1;
+ }
- while (next_offset < length && text[next_offset] != '\t') {
- next_offset = utf8_next(text, length, next_offset);
- }
+/* \todo - implement binary search here */
+ while (lineno < nlines && line[lineno].start < offset) {
+ lineno++;
+ }
+ if (line[lineno].start > offset) {
+ lineno--;
+ }
- if (next_offset < length) {
- guit->layout->width(&textplain_style,
- text,
- next_offset,
- &width);
- }
+ return lineno;
+}
- if (x <= width) {
- int pixel_offset;
- size_t char_offset;
- guit->layout->position(&textplain_style,
- text, next_offset, x,
- &char_offset, &pixel_offset);
+/**
+ * Finds all occurrences of a given string in a textplain content
+ *
+ * \param c the content to be searched
+ * \param context The search context to add the entry to.
+ * \param pattern the string pattern to search for
+ * \param p_len pattern length
+ * \param case_sens whether to perform a case sensitive search
+ * \return NSERROR_OK on success else error code on faliure
+ */
+static nserror
+textplain_textsearch_find(struct content *c,
+ struct textsearch_context *context,
+ const char *pattern,
+ int p_len,
+ bool case_sens)
+{
+ int nlines = textplain_line_count(c);
+ int line;
+ nserror res = NSERROR_OK;
+
+ for(line = 0; line < nlines; line++) {
+ size_t offset, length;
+ const char *text;
+
+ text = textplain_get_line(c, line, &offset, &length);
+ if (text) {
+ while (length > 0) {
+ unsigned match_length;
+ size_t start_idx;
+ const char *new_text;
+ const char *pos;
+
+ pos = content_textsearch_find_pattern(
+ text,
+ length,
+ pattern,
+ p_len,
+ case_sens,
+ &match_length);
+ if (!pos)
+ break;
+
+ /* found string in line => add to list */
+ start_idx = offset + (pos - text);
+ res = content_textsearch_add_match(context,
+ start_idx,
+ start_idx + match_length,
+ NULL,
+ NULL);
+ if (res != NSERROR_OK) {
+ return res;
+ }
- idx += char_offset;
- break;
+ new_text = pos + match_length;
+ offset += (new_text - text);
+ length -= (new_text - text);
+ text = new_text;
+ }
}
-
- x -= width;
- length -= next_offset;
- text += next_offset;
- idx += next_offset;
-
- /* check if it's within the tab */
- width = textplain_tab_width - (width % textplain_tab_width);
- if (x <= width) break;
-
- x -= width;
- length--;
- text++;
- idx++;
}
- return line->start + idx;
+ return res;
}
-/* exported interface documented in render/textplain.h */
-void
+/**
+ * Given a range of byte offsets within a UTF8 textplain content,
+ * return a box that fully encloses the text
+ *
+ * \param[in] c content of type CONTENT_TEXTPLAIN
+ * \param[in] start byte offset of start of text range
+ * \param[in] end byte offset of end
+ * \param[out] r rectangle to be completed
+ */
+static void
textplain_coords_from_range(struct content *c,
unsigned start,
unsigned end,
@@ -1261,91 +1510,174 @@ textplain_coords_from_range(struct content *c,
}
-/* exported interface documented in render/textplain.h */
-char *
-textplain_get_line(struct content *c,
- unsigned lineno,
- size_t *poffset,
- size_t *plen)
+/**
+ * Return a pointer to the raw UTF-8 data, as opposed to the reformatted
+ * text to fit the window width. Thus only hard newlines are preserved
+ * in the saved/copied text of a selection.
+ *
+ * \param[in] c content of type CONTENT_TEXTPLAIN
+ * \param[in] start starting byte offset within UTF-8 text
+ * \param[in] end ending byte offset
+ * \param[out] plen receives validated length
+ * \return pointer to text, or NULL if no text
+ */
+static char *
+textplain_get_raw_data(struct content *c,
+ unsigned start,
+ unsigned end,
+ size_t *plen)
{
textplain_content *text = (textplain_content *) c;
- struct textplain_line *line;
+ size_t utf8_size;
assert(c != NULL);
- if (lineno >= text->physical_line_count)
- return NULL;
- line = &text->physical_line[lineno];
+ utf8_size = text->utf8_data_size;
- *poffset = line->start;
- *plen = line->length;
- return text->utf8_data + line->start;
+ /* any text at all? */
+ if (!utf8_size) return NULL;
+
+ /* clamp to valid offset range */
+ if (start >= utf8_size) start = utf8_size;
+ if (end >= utf8_size) end = utf8_size;
+
+ *plen = end - start;
+
+ return text->utf8_data + start;
}
-/* exported interface documented in render/textplain.h */
-int textplain_find_line(struct content *c, unsigned offset)
+/**
+ * get bounds of a free text search match
+ */
+static nserror
+textplain_textsearch_bounds(struct content *c,
+ unsigned start_idx,
+ unsigned end_idx,
+ struct box *start_box,
+ struct box *end_box,
+ struct rect *bounds)
{
- textplain_content *text = (textplain_content *) c;
- struct textplain_line *line;
- int nlines;
- int lineno = 0;
+ textplain_coords_from_range(c, start_idx, end_idx, bounds);
- assert(c != NULL);
+ return NSERROR_OK;
+}
- line = text->physical_line;
- nlines = text->physical_line_count;
- if (offset > text->utf8_data_size) {
- return -1;
+/**
+ * invalidate a region based on offsets into the text cauing a redraw
+ */
+static nserror
+textplain_textselection_redraw(struct content *c,
+ unsigned start_idx,
+ unsigned end_idx)
+{
+ struct rect r;
+
+ if (end_idx <= start_idx) {
+ return NSERROR_BAD_PARAMETER;
}
-/* \todo - implement binary search here */
- while (lineno < nlines && line[lineno].start < offset) {
- lineno++;
+ textplain_coords_from_range(c, start_idx, end_idx, &r);
+
+ content__request_redraw(c, r.x0, r.y0, r.x1 - r.x0, r.y1 - r.y0);
+
+ return NSERROR_OK;
+}
+
+static nserror
+textplain_textselection_copy(struct content *c,
+ unsigned start_idx,
+ unsigned end_idx,
+ struct selection_string *selstr)
+{
+ const char *text;
+ size_t length;
+ bool res = false;
+
+ text = textplain_get_raw_data(c, start_idx, end_idx, &length);
+ if (text != NULL) {
+ res = selection_string_append(text, length, false, NULL, selstr);
}
- if (line[lineno].start > offset) {
- lineno--;
+ if (res == false) {
+ return NSERROR_NOMEM;
}
-
- return lineno;
+ return NSERROR_OK;
}
-/* exported interface documented in render/textplain.h */
-char *
-textplain_get_raw_data(struct content *c,
- unsigned start,
- unsigned end,
- size_t *plen)
+/**
+ * Retrieve the index of the end of the text
+ *
+ * \param[in] c Content to retrieve size of
+ * \return Size, in bytes, of data
+ */
+static nserror
+textplain_textselection_get_end(struct content *c, unsigned *end_idx)
{
- textplain_content *text = (textplain_content *) c;
- size_t utf8_size;
+ textplain_content *text = (textplain_content *)c;
- assert(c != NULL);
+ *end_idx = text->utf8_data_size;
+ return NSERROR_OK;
+}
- utf8_size = text->utf8_data_size;
- /* any text at all? */
- if (!utf8_size) return NULL;
+/**
+ * plain text content handler table
+ */
+static const content_handler textplain_content_handler = {
+ .fini = textplain_fini,
+ .create = textplain_create,
+ .process_data = textplain_process_data,
+ .data_complete = textplain_convert,
+ .reformat = textplain_reformat,
+ .destroy = textplain_destroy,
+ .mouse_track = textplain_mouse_track,
+ .mouse_action = textplain_mouse_action,
+ .keypress = textplain_keypress,
+ .redraw = textplain_redraw,
+ .open = textplain_open,
+ .close = textplain_close,
+ .get_selection = textplain_get_selection,
+ .clone = textplain_clone,
+ .type = textplain_content_type,
+ .textsearch_find = textplain_textsearch_find,
+ .textsearch_bounds = textplain_textsearch_bounds,
+ .textselection_redraw = textplain_textselection_redraw,
+ .textselection_copy = textplain_textselection_copy,
+ .textselection_get_end = textplain_textselection_get_end,
+ .no_share = true,
+};
- /* clamp to valid offset range */
- if (start >= utf8_size) start = utf8_size;
- if (end >= utf8_size) end = utf8_size;
- *plen = end - start;
+/* exported interface documented in html/textplain.h */
+nserror textplain_init(void)
+{
+ lwc_error lerror;
+ nserror error;
- return text->utf8_data + start;
+ lerror = lwc_intern_string("Windows-1252",
+ SLEN("Windows-1252"),
+ &textplain_default_charset);
+ if (lerror != lwc_error_ok) {
+ return NSERROR_NOMEM;
+ }
+
+ error = content_factory_register_handler("text/plain",
+ &textplain_content_handler);
+ if (error != NSERROR_OK) {
+ lwc_string_unref(textplain_default_charset);
+ }
+
+ error = content_factory_register_handler("application/json",
+ &textplain_content_handler);
+ if (error != NSERROR_OK) {
+ lwc_string_unref(textplain_default_charset);
+ }
+
+ return error;
}
-/* exported interface documented in render/textplain.h */
-struct browser_window *textplain_get_browser_window(struct content *c)
-{
- textplain_content *text = (textplain_content *) c;
- assert(c != NULL);
- assert(c->handler == &textplain_content_handler);
- return text->bw;
-}
diff --git a/content/handlers/text/textplain.h b/content/handlers/text/textplain.h
new file mode 100644
index 000000000..6cc2716bc
--- /dev/null
+++ b/content/handlers/text/textplain.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2006 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2006 Adrian Lees <adrianl@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ *
+ * Interface to content handler for plain text.
+ */
+
+#ifndef NETSURF_HTML_TEXTPLAIN_H
+#define NETSURF_HTML_TEXTPLAIN_H
+
+/**
+ * Initialise the text content handler
+ *
+ * \return NSERROR_OK on success else appropriate error code.
+ */
+nserror textplain_init(void);
+
+
+#endif
diff --git a/content/hlcache.c b/content/hlcache.c
index 33436f7ed..5cba88bc6 100644
--- a/content/hlcache.c
+++ b/content/hlcache.c
@@ -30,12 +30,16 @@
#include "utils/messages.h"
#include "utils/ring.h"
#include "utils/utils.h"
+#include "netsurf/inttypes.h"
#include "netsurf/misc.h"
#include "netsurf/content.h"
#include "desktop/gui_internal.h"
#include "content/mimesniff.h"
#include "content/hlcache.h"
+// Note, this is *ONLY* so that we can abort cleanly during shutdown of the cache
+#include "content/content_protected.h"
+#include "content/content_factory.h"
typedef struct hlcache_entry hlcache_entry;
typedef struct hlcache_retrieval_ctx hlcache_retrieval_ctx;
@@ -104,9 +108,10 @@ static struct hlcache_s *hlcache = NULL;
/**
* Attempt to clean the cache
*/
-static void hlcache_clean(void *ignored)
+static void hlcache_clean(void *force_clean_flag)
{
hlcache_entry *entry, *next;
+ bool force_clean = (force_clean_flag != NULL);
for (entry = hlcache->content_list; entry != NULL; entry = next) {
next = entry->next;
@@ -114,12 +119,17 @@ static void hlcache_clean(void *ignored)
if (entry->content == NULL)
continue;
- if (content__get_status(entry->content) == CONTENT_STATUS_LOADING)
- continue;
-
if (content_count_users(entry->content) != 0)
continue;
+ if (content__get_status(entry->content) == CONTENT_STATUS_LOADING) {
+ if (force_clean == false)
+ continue;
+ NSLOG(netsurf, DEBUG, "Forcing content cleanup during shutdown");
+ content_abort(entry->content);
+ content_set_error(entry->content);
+ }
+
/** \todo This is over-zealous: all unused contents
* will be immediately destroyed. Ideally, we want to
* purge all unused contents that are using stale
@@ -353,7 +363,8 @@ static nserror hlcache_migrate_ctx(hlcache_retrieval_ctx *ctx,
hlcache_event hlevent;
hlevent.type = CONTENT_MSG_ERROR;
- hlevent.data.error = messages_get("MiscError");
+ hlevent.data.errordata.errorcode = NSERROR_UNKNOWN;
+ hlevent.data.errordata.errormsg = messages_get("MiscError");
ctx->handle->cb(ctx->handle, &hlevent,
ctx->handle->pw);
@@ -385,7 +396,8 @@ static nserror hlcache_migrate_ctx(hlcache_retrieval_ctx *ctx,
hlcache_event hlevent;
hlevent.type = CONTENT_MSG_ERROR;
- hlevent.data.error = messages_get("UnacceptableType");
+ hlevent.data.errordata.errorcode = NSERROR_UNKNOWN;
+ hlevent.data.errordata.errormsg = messages_get("UnacceptableType");
ctx->handle->cb(ctx->handle, &hlevent,
ctx->handle->pw);
@@ -413,8 +425,10 @@ static nserror hlcache_migrate_ctx(hlcache_retrieval_ctx *ctx,
* \param pw Pointer to client-specific data
* \return NSERROR_OK on success, appropriate error otherwise
*/
-static nserror hlcache_llcache_callback(llcache_handle *handle,
- const llcache_event *event, void *pw)
+static nserror
+hlcache_llcache_callback(llcache_handle *handle,
+ const llcache_event *event,
+ void *pw)
{
hlcache_retrieval_ctx *ctx = pw;
lwc_string *effective_type = NULL;
@@ -423,6 +437,17 @@ static nserror hlcache_llcache_callback(llcache_handle *handle,
assert(ctx->llcache == handle);
switch (event->type) {
+ case LLCACHE_EVENT_GOT_CERTS:
+ /* Pass them on upward */
+ if (ctx->handle->cb != NULL) {
+ hlcache_event hlevent;
+
+ hlevent.type = CONTENT_MSG_SSL_CERTS;
+ hlevent.data.chain = event->data.chain;
+
+ ctx->handle->cb(ctx->handle, &hlevent, ctx->handle->pw);
+ }
+ break;
case LLCACHE_EVENT_HAD_HEADERS:
error = mimesniff_compute_effective_type(llcache_handle_get_header(handle, "Content-Type"), NULL, 0,
ctx->flags & HLCACHE_RETRIEVE_SNIFF_TYPE,
@@ -481,8 +506,9 @@ static nserror hlcache_llcache_callback(llcache_handle *handle,
if (ctx->handle->cb != NULL) {
hlcache_event hlevent;
- hlevent.type = CONTENT_MSG_ERRORCODE;
- hlevent.data.errorcode = error;
+ hlevent.type = CONTENT_MSG_ERROR;
+ hlevent.data.errordata.errorcode = error;
+ hlevent.data.errordata.errormsg = NULL;
ctx->handle->cb(ctx->handle, &hlevent, ctx->handle->pw);
}
@@ -492,7 +518,8 @@ static nserror hlcache_llcache_callback(llcache_handle *handle,
hlcache_event hlevent;
hlevent.type = CONTENT_MSG_ERROR;
- hlevent.data.error = event->data.msg;
+ hlevent.data.errordata.errorcode = event->data.error.code;
+ hlevent.data.errordata.errormsg = event->data.error.msg;
ctx->handle->cb(ctx->handle, &hlevent, ctx->handle->pw);
}
@@ -566,7 +593,7 @@ void hlcache_finalise(void)
num_contents++;
}
- NSLOG(netsurf, INFO, "%d contents remain before cache drain",
+ NSLOG(netsurf, INFO, "%"PRIu32" contents remain before cache drain",
num_contents);
/* Drain cache */
@@ -581,12 +608,27 @@ void hlcache_finalise(void)
}
} while (num_contents > 0 && num_contents != prev_contents);
- NSLOG(netsurf, INFO, "%d contents remaining:", num_contents);
+ NSLOG(netsurf, INFO, "%"PRIu32" contents remaining after being polite",
+ num_contents);
+
+ /* Drain cache again, forcing the matter */
+ do {
+ prev_contents = num_contents;
+
+ hlcache_clean(&entry); // Any non-NULL pointer will do
+
+ for (num_contents = 0, entry = hlcache->content_list;
+ entry != NULL; entry = entry->next) {
+ num_contents++;
+ }
+ } while (num_contents > 0 && num_contents != prev_contents);
+
+ NSLOG(netsurf, INFO, "%"PRIu32" contents remaining:", num_contents);
for (entry = hlcache->content_list; entry != NULL; entry = entry->next) {
hlcache_handle entry_handle = { entry, NULL, NULL };
if (entry->content != NULL) {
- NSLOG(netsurf, INFO, " %p : %s (%d users)",
+ NSLOG(netsurf, INFO, " %p : %s (%"PRIu32" users)",
entry,
nsurl_access(hlcache_handle_get_url(&entry_handle)),
content_count_users(entry->content));
@@ -622,6 +664,9 @@ void hlcache_finalise(void)
NSLOG(netsurf, INFO, "hit/miss %d/%d", hlcache->hit_count,
hlcache->miss_count);
+ /* De-schedule ourselves */
+ guit->misc->schedule(-1, hlcache_clean, NULL);
+
free(hlcache);
hlcache = NULL;
@@ -630,11 +675,15 @@ void hlcache_finalise(void)
}
/* See hlcache.h for documentation */
-nserror hlcache_handle_retrieve(nsurl *url, uint32_t flags,
- nsurl *referer, llcache_post_data *post,
- hlcache_handle_callback cb, void *pw,
- hlcache_child_context *child,
- content_type accepted_types, hlcache_handle **result)
+nserror
+hlcache_handle_retrieve(nsurl *url,
+ uint32_t flags,
+ nsurl *referer,
+ llcache_post_data *post,
+ hlcache_handle_callback cb, void *pw,
+ hlcache_child_context *child,
+ content_type accepted_types,
+ hlcache_handle **result)
{
hlcache_retrieval_ctx *ctx;
nserror error;
diff --git a/content/hlcache.h b/content/hlcache.h
index 3d9f41cdb..986bdd3f4 100644
--- a/content/hlcache.h
+++ b/content/hlcache.h
@@ -16,8 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * High-level resource cache (interface)
+/**
+ * \file
+ * High-level resource cache interface
*/
#ifndef NETSURF_CONTENT_HLCACHE_H_
diff --git a/content/llcache.c b/content/llcache.c
index 29b42a1c0..32c7449d2 100644
--- a/content/llcache.c
+++ b/content/llcache.c
@@ -36,6 +36,7 @@
#include <string.h>
#include <strings.h>
#include <nsutils/time.h>
+#include <nsutils/base64.h>
#include "netsurf/inttypes.h"
#include "utils/config.h"
@@ -45,6 +46,8 @@
#include "utils/nsurl.h"
#include "utils/utils.h"
#include "utils/time.h"
+#include "utils/http.h"
+#include "utils/nsoption.h"
#include "netsurf/misc.h"
#include "desktop/gui_internal.h"
@@ -113,9 +116,7 @@ typedef struct {
bool tried_with_auth; /**< Whether we've tried with auth */
- bool tried_with_tls_downgrade; /**< Whether we've tried TLS <= 1.0 */
-
- bool outstanding_query; /**< Waiting for a query response */
+ bool tried_with_tls_downgrade; /**< Whether we've tried TLS 1.2 */
bool tainted_tls; /**< Whether the TLS transport is tainted */
} llcache_fetch_ctx;
@@ -176,6 +177,8 @@ struct llcache_object {
size_t source_len; /**< Byte length of source data */
size_t source_alloc; /**< Allocated size of source buffer */
+ struct cert_chain *chain; /**< Certificate chain from the fetch */
+
llcache_store_state store_state; /**< where the data for the object is stored */
llcache_object_user *users; /**< List of users */
@@ -205,12 +208,6 @@ struct llcache_object {
* Core llcache control context.
*/
struct llcache_s {
- /** Handler for fetch-related queries */
- llcache_query_callback query_cb;
-
- /** Data for fetch-related query handler */
- void *query_cb_pw;
-
/** Head of the low-level cached object list */
llcache_object *cached_objects;
@@ -392,6 +389,7 @@ static nserror llcache_send_event_to_users(llcache_object *object,
user = object->users;
while (user != NULL) {
+ bool was_target = user->iterator_target;
user->iterator_target = true;
error = user->handle->cb(user->handle, event,
@@ -399,9 +397,9 @@ static nserror llcache_send_event_to_users(llcache_object *object,
next_user = user->next;
- user->iterator_target = false;
+ user->iterator_target = was_target;
- if (user->queued_for_delete) {
+ if (user->queued_for_delete && !was_target) {
llcache_object_remove_user(object, user);
llcache_object_user_destroy(user);
}
@@ -481,6 +479,14 @@ static nserror llcache_post_data_clone(const llcache_post_data *orig,
/**
* Split a fetch header into name and value
*
+ * HTTP header splitting according to grammar defined in RFC7230 section 3.2
+ * https://tools.ietf.org/html/rfc7230#section-3.2
+ *
+ * This implementation is non conformant in that it:
+ * - includes carrige return and newline in whitespace (3.2.3)
+ * - allows whitespace before and after the field-name token (3.2.4)
+ * - does not handle obsolete line folding (3.2.4)
+ *
* \param data Header string
* \param len Byte length of header
* \param name Pointer to location to receive header name
@@ -566,128 +572,123 @@ static nserror llcache_fetch_split_header(const uint8_t *data, size_t len,
}
/**
- * Parse a fetch header
+ * parse cache control header value
*
- * \param object Object to parse header for
- * \param data Header string
- * \param len Byte length of header
- * \param name Pointer to location to receive header name
- * \param value Pointer to location to receive header value
+ * \param object Object to parse header for
+ * \param value header value
* \return NSERROR_OK on success, appropriate error otherwise
- *
- * \note This function also has the side-effect of updating
- * the cache control data for the object if an interesting
- * header is encountered
*/
-static nserror llcache_fetch_parse_header(llcache_object *object,
- const uint8_t *data, size_t len, char **name, char **value)
+static nserror
+llcache_fetch_parse_cache_control(llcache_object *object, char *value)
{
- nserror res;
+ http_cache_control *cc;
+ nserror error;
- /* Set fetch response time if not already set */
- if (object->cache.res_time == 0) {
- object->cache.res_time = time(NULL);
- }
+ error = http_parse_cache_control(value, &cc);
+ if (error != NSERROR_OK) {
+ /* Ignore parse errors */
+ return NSERROR_OK;
+ }
- /* Decompose header into name-value pair */
- res = llcache_fetch_split_header(data, len, name, value);
- if (res != NSERROR_OK) {
- return res;
- }
+ if (http_cache_control_no_cache(cc) ||
+ http_cache_control_no_store(cc)) {
+ /**
+ * \todo When we get a disk cache we should
+ * distinguish between these two.
+ */
+ object->cache.no_cache = LLCACHE_VALIDATE_ALWAYS;
+ }
- /* Parse cache headers to populate cache control data */
+ if (http_cache_control_has_max_age(cc)) {
+ object->cache.max_age = http_cache_control_max_age(cc);
+ }
- if ((5 < len) &&
- strcasecmp(*name, "Date") == 0) {
- /* extract Date header */
- nsc_strntimet(*value,
- strlen(*value),
- &object->cache.date);
- } else if ((4 < len) &&
- strcasecmp(*name, "Age") == 0) {
- /* extract Age header */
- if ('0' <= **value && **value <= '9') {
- object->cache.age = atoi(*value);
- }
- } else if ((8 < len) &&
- strcasecmp(*name, "Expires") == 0) {
- /* extract Expires header */
- res = nsc_strntimet(*value,
- strlen(*value),
- &object->cache.expires);
- if (res != NSERROR_OK) {
- object->cache.expires = (time_t)0x7fffffff;
- }
- } else if ((14 < len) &&
- strcasecmp(*name, "Cache-Control") == 0) {
- /* extract and parse Cache-Control header */
- const char *start = *value;
- const char *comma = *value;
-
- while (*comma != '\0') {
- while (*comma != '\0' && *comma != ',') {
- comma++;
- }
-
- if ((8 < comma - start) &&
- (strncasecmp(start, "no-cache", 8) == 0 ||
- strncasecmp(start, "no-store", 8) == 0)) {
- /**
- * \todo When we get a disk cache we should
- * distinguish between these two.
- */
- object->cache.no_cache = LLCACHE_VALIDATE_ALWAYS;
- } else if ((7 < comma - start) &&
- strncasecmp(start, "max-age", 7) == 0) {
- /* Find '=' */
- while (start < comma && *start != '=') {
- start++;
- }
-
- /* Skip over it */
- start++;
-
-#define SKIP_ST(p) while (*p != '\0' && (*p == ' ' || *p == '\t')) p++
-
- /* Skip whitespace */
- SKIP_ST(start);
-
- if (start < comma) {
- object->cache.max_age = atoi(start);
- }
- }
+ http_cache_control_destroy(cc);
+
+ return NSERROR_OK;
+}
+
+/**
+ * Update cache control from appropriate header
+ *
+ * \param object Object to parse header for
+ * \param name header name
+ * \param value header value
+ * \return NSERROR_OK on success, appropriate error otherwise
+ */
+static nserror
+llcache_fetch_header_cache_control(llcache_object *object,
+ char *name,
+ char *value)
+{
+ nserror res;
+ size_t name_len;
- if (*comma != '\0') {
- /* Skip past comma */
- comma++;
- /* Skip whitespace */
- SKIP_ST(comma);
+ /* Parse cache headers to populate cache control data */
+ name_len = strlen(name);
+
+ switch (name_len) {
+ case 3:
+ if (strcasecmp(name, "Age") == 0) {
+ /* extract Age header */
+ if ('0' <= *value && *value <= '9') {
+ object->cache.age = atoi(value);
}
-#undef SKIP_ST
+ }
+ break;
+
+ case 4:
+ if (strcasecmp(name, "Date") == 0) {
+ /* extract Date header */
+ res = nsc_strntimet(value,
+ strlen(value),
+ &object->cache.date);
+ if (res != NSERROR_OK) {
+ NSLOG(llcache, INFO,
+ "Processing Date header value \"%s\" returned %d",
+ value, res);
+ }
+ } else if (strcasecmp(name, "ETag") == 0) {
+ /* extract ETag header */
+ free(object->cache.etag);
+ object->cache.etag = strdup(value);
+ if (object->cache.etag == NULL) {
+ NSLOG(llcache, INFO,
+ "No memory to duplicate ETag");
+ return NSERROR_NOMEM;
+ }
+ }
+ break;
- /* Set start for next token */
- start = comma;
+ case 7:
+ if (strcasecmp(name, "Expires") == 0) {
+ /* process Expires header value */
+ res = nsc_strntimet(value,
+ strlen(value),
+ &object->cache.expires);
+ if (res != NSERROR_OK) {
+ NSLOG(llcache, INFO,
+ "Processing Expires header value \"%s\" returned %d",
+ value, res);
+ object->cache.expires = (time_t)0x7fffffff;
+ }
}
- } else if ((5 < len) &&
- (strcasecmp(*name, "ETag") == 0)) {
- /* extract ETag header */
- free(object->cache.etag);
- object->cache.etag = strdup(*value);
- if (object->cache.etag == NULL) {
- free(*name);
- free(*value);
- return NSERROR_NOMEM;
+ break;
+
+ case 13:
+ if (strcasecmp(name, "Cache-Control") == 0) {
+ /* parse Cache-Control header value */
+ llcache_fetch_parse_cache_control(object,value);
+ } else if (strcasecmp(name, "Last-Modified") == 0) {
+ /* parse Last-Modified header value */
+ nsc_strntimet(value,
+ strlen(value),
+ &object->cache.last_modified);
}
- } else if ((14 < len) &&
- (strcasecmp(*name, "Last-Modified") == 0)) {
- /* extract Last-Modified header */
- nsc_strntimet(*value,
- strlen(*value),
- &object->cache.last_modified);
+ break;
}
-
return NSERROR_OK;
}
@@ -733,7 +734,7 @@ static inline void llcache_invalidate_cache_control_data(llcache_object *object)
static nserror llcache_fetch_process_header(llcache_object *object,
const uint8_t *data, size_t len)
{
- nserror error;
+ nserror res;
char *name, *value;
llcache_header *temp;
@@ -761,9 +762,15 @@ static nserror llcache_fetch_process_header(llcache_object *object,
llcache_destroy_headers(object);
}
- error = llcache_fetch_parse_header(object, data, len, &name, &value);
- if (error != NSERROR_OK) {
- return error;
+ /* Set fetch response time if not already set */
+ if (object->cache.res_time == 0) {
+ object->cache.res_time = time(NULL);
+ }
+
+ /* Parse header into name-value pair */
+ res = llcache_fetch_split_header(data, len, &name, &value);
+ if (res != NSERROR_OK) {
+ return res;
}
/* deal with empty header */
@@ -773,9 +780,17 @@ static nserror llcache_fetch_process_header(llcache_object *object,
return NSERROR_OK;
}
+ /* update cache control data from header */
+ res = llcache_fetch_header_cache_control(object, name, value);
+ if (res != NSERROR_OK) {
+ free(name);
+ free(value);
+ return res;
+ }
+
/* Append header data to the object's headers array */
- temp = realloc(object->headers, (object->num_headers + 1) *
- sizeof(llcache_header));
+ temp = realloc(object->headers,
+ (object->num_headers + 1) * sizeof(llcache_header));
if (temp == NULL) {
free(name);
free(value);
@@ -793,6 +808,87 @@ static nserror llcache_fetch_process_header(llcache_object *object,
}
/**
+ * construct a Referer header appropriate for the request
+ *
+ * \param url The url being navigated to
+ * \param referer The referring url
+ * \param header_out A pointer to receive the header. The buffer must
+ * be freed by the caller.
+ * \return NSERROR_OK and \a header_out updated on success else error code
+ */
+static nserror get_referer_header(nsurl *url, nsurl *referer, char **header_out)
+{
+ nserror res = NSERROR_INVALID;
+ lwc_string *ref_scheme;
+ lwc_string *scheme;
+ bool match;
+ bool match1;
+ bool match2;
+ char *header;
+
+ /* Determine whether to send the Referer header */
+ if (!nsoption_bool(send_referer)) {
+ return NSERROR_INVALID;
+ }
+
+ scheme = nsurl_get_component(url, NSURL_SCHEME);
+ if (scheme == NULL) {
+ return NSERROR_BAD_URL;
+ }
+
+ ref_scheme = nsurl_get_component(referer, NSURL_SCHEME);
+ if (ref_scheme == NULL) {
+ /* referer has no scheme so no header */
+ lwc_string_unref(scheme);
+ return NSERROR_INVALID;
+ }
+
+ /* User permits us to send the header
+ * Only send it if:
+ * 1) The fetch and referer schemes match
+ * or 2) The fetch is https and the referer is http
+ *
+ * This ensures that referer information is only sent
+ * across schemes in the special case of an https
+ * request from a page served over http. The inverse
+ * (https -> http) should not send the referer (15.1.3)
+ */
+ if (lwc_string_isequal(scheme, ref_scheme,
+ &match) != lwc_error_ok) {
+ match = false;
+ }
+ if (lwc_string_isequal(scheme, corestring_lwc_https,
+ &match1) != lwc_error_ok) {
+ match1 = false;
+ }
+ if (lwc_string_isequal(ref_scheme, corestring_lwc_http,
+ &match2) != lwc_error_ok) {
+ match2 = false;
+ }
+ if (match == true || (match1 == true && match2 == true)) {
+ const size_t len = SLEN("Referer: ") +
+ nsurl_length(referer) + 1;
+
+ header = malloc(len);
+ if (header == NULL) {
+ res = NSERROR_NOMEM;
+ } else {
+ snprintf(header, len, "Referer: %s",
+ nsurl_access(referer));
+
+ *header_out = header;
+ res = NSERROR_OK;
+ }
+ }
+
+
+ lwc_string_unref(scheme);
+ lwc_string_unref(ref_scheme);
+
+ return res;
+}
+
+/**
* (Re)fetch an object
*
* Sets up headers and attempts to start an actual fetch from the
@@ -820,12 +916,13 @@ static nserror llcache_object_refetch(llcache_object *object)
}
}
- /* Generate cache-control headers */
- headers = malloc(3 * sizeof(char *));
+ /* Generate headers */
+ headers = malloc(4 * sizeof(char *));
if (headers == NULL) {
return NSERROR_NOMEM;
}
+ /* cache-control header for etag */
if (object->cache.etag != NULL) {
const size_t len = SLEN("If-None-Match: ") +
strlen(object->cache.etag) + 1;
@@ -842,7 +939,8 @@ static nserror llcache_object_refetch(llcache_object *object)
header_idx++;
}
- if (object->cache.date != 0) {
+ /* cache-control header for modification time */
+ if (object->cache.last_modified != 0) {
/* Maximum length of an RFC 1123 date is 29 bytes */
const size_t len = SLEN("If-Modified-Since: ") + 29 + 1;
@@ -855,10 +953,19 @@ static nserror llcache_object_refetch(llcache_object *object)
}
snprintf(headers[header_idx], len, "If-Modified-Since: %s",
- rfc1123_date(object->cache.date));
+ rfc1123_date(object->cache.last_modified));
header_idx++;
}
+
+ /* Referer header */
+ if (object->fetch.referer != NULL) {
+ if (get_referer_header(object->url,
+ object->fetch.referer,
+ &headers[header_idx]) == NSERROR_OK) {
+ header_idx++;
+ }
+ }
headers[header_idx] = NULL;
/* Reset cache control data */
@@ -955,6 +1062,8 @@ static nserror llcache_object_destroy(llcache_object *object)
NSLOG(llcache, DEBUG, "Destroying object %p, %s", object,
nsurl_access(object->url));
+ cert_chain_free(object->chain);
+
if (object->source_data != NULL) {
if (object->store_state == LLCACHE_STATE_DISC) {
guit->llcache->release(object->url, BACKING_STORE_NONE);
@@ -1220,6 +1329,13 @@ llcache_serialise_metadata(llcache_object *object,
char *op;
unsigned int hloop;
int use;
+ size_t cert_chain_depth;
+
+ if (object->chain != NULL) {
+ cert_chain_depth = object->chain->depth;
+ } else {
+ cert_chain_depth = 0;
+ }
allocsize = 10 + 1; /* object length */
@@ -1231,13 +1347,21 @@ llcache_serialise_metadata(llcache_object *object,
allocsize += 10 + 1; /* space for number of header entries */
- allocsize += nsurl_length(object->url) + 1;
-
for (hloop = 0 ; hloop < object->num_headers ; hloop++) {
allocsize += strlen(object->headers[hloop].name) + 1;
allocsize += strlen(object->headers[hloop].value) + 1;
}
+ allocsize += nsurl_length(object->url) + 1;
+
+ /* space for number of DER formatted certificates */
+ allocsize += 10 + 1;
+
+ for (hloop = 0; hloop < cert_chain_depth; hloop++) {
+ allocsize += 10 + 1; /* error status */
+ allocsize += 4 * ((object->chain->certs[hloop].der_length + 2) / 3);
+ }
+
data = malloc(allocsize);
if (data == NULL) {
return NSERROR_NOMEM;
@@ -1320,6 +1444,56 @@ llcache_serialise_metadata(llcache_object *object,
datasize -= use;
}
+ /* number of DER formatted ssl certificates */
+ use = snprintf(op, datasize, "%" PRIsizet, cert_chain_depth);
+ if (use < 0) {
+ goto operror;
+ }
+ use++; /* does not count the null */
+ if (use > datasize)
+ goto overflow;
+ op += use;
+ datasize -= use;
+
+ /* SSL certificates */
+ for (hloop = 0; hloop < cert_chain_depth; hloop++) {
+ nsuerror res;
+
+ /* Certificate error code */
+ use = snprintf(op, datasize, "%d",
+ (int)(object->chain->certs[hloop].err));
+ if (use < 0) {
+ goto operror;
+ }
+ use++; /* does not count the null */
+ if (use > datasize)
+ goto overflow;
+ op += use;
+ datasize -= use;
+
+ /* DER certificate data in base64 encoding */
+ if (object->chain->certs[hloop].der != NULL) {
+ size_t output_length = datasize;
+ res = nsu_base64_encode(
+ object->chain->certs[hloop].der,
+ object->chain->certs[hloop].der_length,
+ (uint8_t *)op,
+ &output_length);
+ if (res != NSUERROR_OK) {
+ goto operror;
+ }
+ use = output_length;
+ } else {
+ use = 0;
+ }
+ use++; /* allow for null */
+ if (use > datasize)
+ goto overflow;
+ op += use;
+ *(op - 1) = 0;
+ datasize -= use;
+ }
+
NSLOG(llcache, DEBUG, "Filled buffer with %d spare", datasize);
*data_out = data;
@@ -1360,6 +1534,7 @@ llcache_process_metadata(llcache_object *object)
nserror res;
uint8_t *metadata = NULL;
size_t metadatalen = 0;
+ size_t remaining = 0;
nsurl *metadataurl;
unsigned int line;
char *ln;
@@ -1371,6 +1546,8 @@ llcache_process_metadata(llcache_object *object)
time_t completion_time;
size_t num_headers;
size_t hloop;
+ size_t ssl_cert_count = 0;
+ struct cert_chain *chain = NULL;
NSLOG(llcache, INFO, "Retrieving metadata");
@@ -1385,10 +1562,20 @@ llcache_process_metadata(llcache_object *object)
NSLOG(llcache, INFO, "Processing retrieved data");
+ /* metadata is stored as a sequence of NULL terminated strings
+ * which we call 'line's here.
+ */
+
+ /* We track remaining data because as we extend this data structure
+ * we need to know if we should continue to parse
+ */
+ remaining = metadatalen;
+
/* metadata line 1 is the url the metadata referrs to */
line = 1;
ln = (char *)metadata;
lnsize = strlen(ln);
+ remaining -= lnsize + 1;
if (lnsize < 7) {
res = NSERROR_INVALID;
@@ -1422,6 +1609,7 @@ llcache_process_metadata(llcache_object *object)
line = 2;
ln += lnsize + 1;
lnsize = strlen(ln);
+ remaining -= lnsize + 1;
if ((lnsize < 1) || (sscanf(ln, "%" PRIsizet, &source_length) != 1)) {
res = NSERROR_INVALID;
@@ -1433,6 +1621,7 @@ llcache_process_metadata(llcache_object *object)
line = 3;
ln += lnsize + 1;
lnsize = strlen(ln);
+ remaining -= lnsize + 1;
res = nsc_snptimet(ln, lnsize, &request_time);
if (res != NSERROR_OK)
@@ -1443,6 +1632,7 @@ llcache_process_metadata(llcache_object *object)
line = 4;
ln += lnsize + 1;
lnsize = strlen(ln);
+ remaining -= lnsize + 1;
res = nsc_snptimet(ln, lnsize, &response_time);
if (res != NSERROR_OK)
@@ -1453,6 +1643,7 @@ llcache_process_metadata(llcache_object *object)
line = 5;
ln += lnsize + 1;
lnsize = strlen(ln);
+ remaining -= lnsize + 1;
res = nsc_snptimet(ln, lnsize, &completion_time);
if (res != NSERROR_OK)
@@ -1463,6 +1654,7 @@ llcache_process_metadata(llcache_object *object)
line = 6;
ln += lnsize + 1;
lnsize = strlen(ln);
+ remaining -= lnsize + 1;
if ((lnsize < 1) || (sscanf(ln, "%" PRIsizet, &num_headers) != 1)) {
res = NSERROR_INVALID;
@@ -1474,6 +1666,7 @@ llcache_process_metadata(llcache_object *object)
line++;
ln += lnsize + 1;
lnsize = strlen(ln);
+ remaining -= lnsize + 1;
res = llcache_fetch_process_header(object,
(uint8_t *)ln,
@@ -1482,6 +1675,74 @@ llcache_process_metadata(llcache_object *object)
goto format_error;
}
+ if (remaining == 0) {
+ goto skip_ssl_certificates;
+ }
+
+ /* Next line is the number of DER base64 encoded certificates */
+ line++;
+ ln += lnsize + 1;
+ lnsize = strlen(ln);
+ remaining -= lnsize + 1;
+
+ if ((lnsize < 1) || (sscanf(ln, "%" PRIsizet, &ssl_cert_count) != 1)) {
+ res = NSERROR_INVALID;
+ goto format_error;
+ }
+
+ if (ssl_cert_count == 0) {
+ goto skip_ssl_certificates;
+ }
+
+ if (ssl_cert_count > MAX_CERT_DEPTH) {
+ res = NSERROR_INVALID;
+ goto format_error;
+ }
+
+ res = cert_chain_alloc(ssl_cert_count, &chain);
+ if (res != NSERROR_OK) {
+ goto format_error;
+ }
+
+ for (hloop = 0; hloop < ssl_cert_count; hloop++) {
+ int errcode;
+ nsuerror nsures;
+
+ /* Certificate error code */
+ line++;
+ ln += lnsize + 1;
+ lnsize = strlen(ln);
+ remaining -= lnsize + 1;
+ if ((lnsize < 1) || (sscanf(ln, "%d", &errcode) != 1)) {
+ res = NSERROR_INVALID;
+ goto format_error;
+ }
+ if (errcode < SSL_CERT_ERR_OK ||
+ errcode > SSL_CERT_ERR_MAX_KNOWN) {
+ /* Error with the cert code, assume UNKNOWN */
+ chain->certs[hloop].err = SSL_CERT_ERR_UNKNOWN;
+ } else {
+ chain->certs[hloop].err = (ssl_cert_err)errcode;
+ }
+
+ /* base64 encoded DER certificate data */
+ line++;
+ ln += lnsize + 1;
+ lnsize = strlen(ln);
+ remaining -= lnsize + 1;
+ if (lnsize > 0) {
+ nsures = nsu_base64_decode_alloc((const uint8_t *)ln,
+ lnsize,
+ &chain->certs[hloop].der,
+ &chain->certs[hloop].der_length);
+ if (nsures != NSUERROR_OK) {
+ res = NSERROR_NOMEM;
+ goto format_error;
+ }
+ }
+ }
+
+skip_ssl_certificates:
guit->llcache->release(object->url, BACKING_STORE_META);
/* update object on successful parse of metadata */
@@ -1494,6 +1755,8 @@ llcache_process_metadata(llcache_object *object)
object->cache.res_time = response_time;
object->cache.fin_time = completion_time;
+ object->chain = chain;
+
/* object stored in backing store */
object->store_state = LLCACHE_STATE_DISC;
@@ -1505,10 +1768,77 @@ format_error:
line, res);
guit->llcache->release(object->url, BACKING_STORE_META);
+ cert_chain_free(chain);
+
return res;
}
/**
+ * Check whether a scheme is persistable.
+ *
+ * \param url URL to check.
+ * \return true iff url has a persistable scheme.
+ */
+static inline bool llcache__scheme_is_persistable(const nsurl *url)
+{
+ lwc_string *scheme = nsurl_get_component(url, NSURL_SCHEME);
+ bool persistable = false;
+ bool match;
+
+ /* nsurl ensures lower case schemes, and corestrings are lower
+ * case, so it's safe to use case-sensitive comparison. */
+ if ((lwc_string_isequal(scheme, corestring_lwc_http,
+ &match) == lwc_error_ok &&
+ (match == true)) ||
+ (lwc_string_isequal(scheme, corestring_lwc_https,
+ &match) == lwc_error_ok &&
+ (match == true))) {
+ persistable = true;
+ }
+
+ lwc_string_unref(scheme);
+
+ return persistable;
+}
+
+/**
+ * Check whether a scheme is cachable.
+ *
+ * \param url URL to check.
+ * \return true iff url has a cachable scheme.
+ */
+static inline bool llcache__scheme_is_cachable(const nsurl *url)
+{
+ lwc_string *scheme = nsurl_get_component(url, NSURL_SCHEME);
+ bool cachable = false;
+ bool match;
+
+ /* nsurl ensures lower case schemes, and corestrings are lower
+ * case, so it's safe to use case-sensitive comparison. */
+ if ((lwc_string_isequal(scheme, corestring_lwc_http,
+ &match) == lwc_error_ok &&
+ (match == true)) ||
+ (lwc_string_isequal(scheme, corestring_lwc_https,
+ &match) == lwc_error_ok &&
+ (match == true)) ||
+ (lwc_string_isequal(scheme, corestring_lwc_data,
+ &match) == lwc_error_ok &&
+ (match == true)) ||
+ (lwc_string_isequal(scheme, corestring_lwc_resource,
+ &match) == lwc_error_ok &&
+ (match == true)) ||
+ (lwc_string_isequal(scheme, corestring_lwc_file,
+ &match) == lwc_error_ok &&
+ (match == true))) {
+ cachable = true;
+ }
+
+ lwc_string_unref(scheme);
+
+ return cachable;
+}
+
+/**
* Attempt to retrieve an object from persistent storage.
*
* \param object The object to populate from persistent store.
@@ -1530,6 +1860,12 @@ llcache_object_fetch_persistent(llcache_object *object,
nsurl *referer_clone = NULL;
llcache_post_data *post_clone = NULL;
+ if (!llcache__scheme_is_persistable(object->url)) {
+ /* Don't bother looking up non-http(s) stuff; we don't
+ * persist it. */
+ return NSERROR_NOT_FOUND;
+ }
+
object->cache.req_time = time(NULL);
object->cache.fin_time = object->cache.req_time;
@@ -1586,9 +1922,11 @@ llcache_object_retrieve_from_cache(nsurl *url,
nserror error;
llcache_object *obj, *newest = NULL;
- NSLOG(llcache, DEBUG, "Searching cache for %s flags:%x referer:%s post:%p",
- nsurl_access(url), flags,
- referer==NULL?"":nsurl_access(referer), post);
+ NSLOG(llcache, DEBUG,
+ "Searching cache for %s flags:%"PRIx32" referer:%s post:%p",
+ nsurl_access(url), flags,
+ referer==NULL?"":nsurl_access(referer),
+ post);
/* Search for the most recently fetched matching object */
for (obj = llcache->cached_objects; obj != NULL; obj = obj->next) {
@@ -1762,7 +2100,7 @@ llcache_object_retrieve(nsurl *url,
nsurl *defragmented_url;
bool uncachable = false;
- NSLOG(llcache, DEBUG, "Retrieve %s (%x, %s, %p)", nsurl_access(url), flags,
+ NSLOG(llcache, DEBUG, "Retrieve %s (%"PRIx32", %s, %p)", nsurl_access(url), flags,
referer==NULL?"":nsurl_access(referer), post);
@@ -1779,26 +2117,9 @@ llcache_object_retrieve(nsurl *url,
/* POST requests are never cached */
uncachable = true;
} else {
- /* only http and https schemes are cached */
- lwc_string *scheme;
- bool match;
-
- scheme = nsurl_get_component(defragmented_url, NSURL_SCHEME);
-
- if (lwc_string_caseless_isequal(scheme, corestring_lwc_http,
- &match) == lwc_error_ok &&
- (match == false)) {
- if (lwc_string_caseless_isequal(scheme,
- corestring_lwc_https, &match) ==
- lwc_error_ok &&
- (match == false)) {
- uncachable = true;
- }
- }
- lwc_string_unref(scheme);
+ uncachable = !llcache__scheme_is_cachable(defragmented_url);
}
-
if (uncachable) {
/* Create new object */
error = llcache_object_new(defragmented_url, &obj);
@@ -1886,10 +2207,17 @@ static nserror llcache_hsts_transform_url(nsurl *url, nsurl **result,
scheme = nsurl_get_component(url, NSURL_SCHEME);
if (lwc_string_caseless_isequal(scheme, corestring_lwc_http,
&match) != lwc_error_ok || match == false) {
- /* Non-HTTP fetch: ignore */
+ /* Non-HTTP fetch: no transform required */
+ if (lwc_string_caseless_isequal(scheme, corestring_lwc_https,
+ &match) == lwc_error_ok && match) {
+ /* HTTPS: ask urldb if HSTS is enabled */
+ *hsts_in_use = urldb_get_hsts_enabled(url);
+ } else {
+ /* Anything else: no HSTS */
+ *hsts_in_use = false;
+ }
lwc_string_unref(scheme);
*result = nsurl_ref(url);
- *hsts_in_use = false;
return error;
}
lwc_string_unref(scheme);
@@ -1989,7 +2317,8 @@ static nserror llcache_fetch_redirect(llcache_object *object,
NSLOG(llcache, INFO, "Too many nested redirects");
event.type = LLCACHE_EVENT_ERROR;
- event.data.msg = messages_get("BadRedirect");
+ event.data.error.code = NSERROR_BAD_REDIRECT;
+ event.data.error.msg = messages_get("BadRedirect");
return llcache_send_event_to_users(object, &event);
}
@@ -2234,37 +2563,6 @@ llcache_fetch_process_data(llcache_object *object,
return NSERROR_OK;
}
-/**
- * Handle a query response
- *
- * \param proceed Whether to proceed with fetch
- * \param cbpw Our context for query
- * \return NSERROR_OK on success, appropriate error otherwise
- */
-static nserror llcache_query_handle_response(bool proceed, void *cbpw)
-{
- llcache_event event;
- llcache_object *object = cbpw;
-
- object->fetch.outstanding_query = false;
-
- /* Refetch, using existing fetch parameters, if client allows us to */
- if (proceed)
- return llcache_object_refetch(object);
-
- /* Invalidate cache-control data */
- llcache_invalidate_cache_control_data(object);
-
- /* Mark it complete */
- object->fetch.state = LLCACHE_FETCH_COMPLETE;
-
- /* Inform client(s) that object fetch failed */
- event.type = LLCACHE_EVENT_ERROR;
- /** \todo More appropriate error message */
- event.data.msg = messages_get("FetchFailed");
-
- return llcache_send_event_to_users(object, &event);
-}
/**
* Handle an authentication request
@@ -2296,39 +2594,20 @@ static nserror llcache_fetch_auth(llcache_object *object, const char *realm)
auth = urldb_get_auth_details(object->url, realm);
if (auth == NULL || object->fetch.tried_with_auth == true) {
+ llcache_event event;
/* No authentication details, or tried what we had, so ask */
object->fetch.tried_with_auth = false;
- if (llcache->query_cb != NULL) {
- llcache_query query;
-
- /* Emit query for authentication details */
- query.type = LLCACHE_QUERY_AUTH;
- query.url = object->url;
- query.data.auth.realm = realm;
-
- object->fetch.outstanding_query = true;
-
- error = llcache->query_cb(&query, llcache->query_cb_pw,
- llcache_query_handle_response, object);
- if (error != NSERROR_OK) {
- /* do not continue if error querying user */
- error = llcache_query_handle_response(false,
- object);
- }
- } else {
- llcache_event event;
-
- /* Mark object complete */
- object->fetch.state = LLCACHE_FETCH_COMPLETE;
+ /* Mark object complete */
+ object->fetch.state = LLCACHE_FETCH_COMPLETE;
- /* Inform client(s) that object fetch failed */
- event.type = LLCACHE_EVENT_ERROR;
- /** \todo More appropriate error message */
- event.data.msg = messages_get("FetchFailed");
+ /* Inform client(s) that object fetch failed */
+ event.type = LLCACHE_EVENT_ERROR;
+ /** \todo More appropriate error message */
+ event.data.error.code = NSERROR_BAD_AUTH;
+ event.data.error.msg = realm;
- error = llcache_send_event_to_users(object, &event);
- }
+ error = llcache_send_event_to_users(object, &event);
} else {
/* Flag that we've tried to refetch with credentials, so
* that if the fetch fails again, we ask the user again */
@@ -2343,12 +2622,9 @@ static nserror llcache_fetch_auth(llcache_object *object, const char *realm)
* Handle a TLS certificate verification failure
*
* \param object Object being fetched
- * \param certs Certificate chain
- * \param num Number of certificates in chain
* \return NSERROR_OK on success, appropriate error otherwise
*/
-static nserror llcache_fetch_cert_error(llcache_object *object,
- const struct ssl_cert_info *certs, size_t num)
+static nserror llcache_fetch_cert_error(llcache_object *object)
{
nserror error = NSERROR_OK;
@@ -2362,23 +2638,19 @@ static nserror llcache_fetch_cert_error(llcache_object *object,
object->fetch.tainted_tls = true;
/* Only give the user a chance if HSTS isn't in use for this fetch */
- if (object->fetch.hsts_in_use == false && llcache->query_cb != NULL) {
- llcache_query query;
+ if (object->fetch.hsts_in_use == false) {
+ llcache_event event;
- /* Emit query for TLS */
- query.type = LLCACHE_QUERY_SSL;
- query.url = object->url;
- query.data.ssl.certs = certs;
- query.data.ssl.num = num;
+ /* Mark object complete */
+ object->fetch.state = LLCACHE_FETCH_COMPLETE;
- object->fetch.outstanding_query = true;
+ /* Inform client(s) that object fetch failed */
+ event.type = LLCACHE_EVENT_ERROR;
+ /** \todo More appropriate error message */
+ event.data.error.code = NSERROR_BAD_CERTS;
+ event.data.error.msg = messages_get("FetchFailed");
- error = llcache->query_cb(&query, llcache->query_cb_pw,
- llcache_query_handle_response, object);
- if (error != NSERROR_OK) {
- /* do not continue if error querying user */
- error = llcache_query_handle_response(false, object);
- }
+ error = llcache_send_event_to_users(object, &event);
} else {
llcache_event event;
@@ -2388,7 +2660,8 @@ static nserror llcache_fetch_cert_error(llcache_object *object,
/* Inform client(s) that object fetch failed */
event.type = LLCACHE_EVENT_ERROR;
/** \todo More appropriate error message */
- event.data.msg = messages_get("FetchFailed");
+ event.data.error.code = NSERROR_UNKNOWN;
+ event.data.error.msg = messages_get("FetchFailed");
error = llcache_send_event_to_users(object, &event);
}
@@ -2396,6 +2669,7 @@ static nserror llcache_fetch_cert_error(llcache_object *object,
return error;
}
+
/**
* Handle a TLS connection setup failure
*
@@ -2418,7 +2692,7 @@ static nserror llcache_fetch_ssl_error(llcache_object *object)
/* Make no attempt to downgrade if HSTS is in use
* (i.e. assume server does TLS properly) */
if (object->fetch.hsts_in_use ||
- object->fetch.tried_with_tls_downgrade) {
+ object->fetch.tried_with_tls_downgrade) {
/* Have already tried to downgrade, so give up */
llcache_event event;
@@ -2428,7 +2702,8 @@ static nserror llcache_fetch_ssl_error(llcache_object *object)
/* Inform client(s) that object fetch failed */
event.type = LLCACHE_EVENT_ERROR;
/** \todo More appropriate error message */
- event.data.msg = messages_get("FetchFailed");
+ event.data.error.code = NSERROR_UNKNOWN;
+ event.data.error.msg = messages_get("FetchFailed");
error = llcache_send_event_to_users(object, &event);
} else {
@@ -2441,6 +2716,46 @@ static nserror llcache_fetch_ssl_error(llcache_object *object)
return error;
}
+
+/**
+ * handle time out while trying to fetch.
+ *
+ * \param object Object being fetched
+ * \return NSERROR_OK on success otherwise error code
+ */
+static nserror llcache_fetch_timeout(llcache_object *object)
+{
+ llcache_event event;
+
+ /* The fetch has already been cleaned up by the fetcher but
+ * we would like to retry if we can.
+ */
+ if (object->fetch.retries_remaining > 1) {
+ object->fetch.retries_remaining--;
+ return llcache_object_refetch(object);
+ }
+
+ /* The fetch has has already been cleaned up by the fetcher */
+ object->fetch.state = LLCACHE_FETCH_COMPLETE;
+ object->fetch.fetch = NULL;
+
+ /* Release candidate, if any */
+ if (object->candidate != NULL) {
+ object->candidate->candidate_count--;
+ object->candidate = NULL;
+ }
+
+ /* Invalidate cache control data */
+ llcache_invalidate_cache_control_data(object);
+
+ event.type = LLCACHE_EVENT_ERROR;
+ event.data.error.code = NSERROR_TIMEOUT;
+ event.data.error.msg = NULL;
+
+ return llcache_send_event_to_users(object, &event);
+}
+
+
/**
* Construct a sorted list of objects available for writeout operation.
*
@@ -2474,6 +2789,11 @@ build_candidate_list(struct llcache_object ***lst_out, int *lst_len_out)
for (object = llcache->cached_objects; object != NULL; object = next) {
next = object->next;
+ /* Only consider http(s) for the disc cache. */
+ if (!llcache__scheme_is_persistable(object->url)) {
+ continue;
+ }
+
remaining_lifetime = llcache_object_rfc2616_remaining_lifetime(
&object->cache);
@@ -2483,7 +2803,6 @@ build_candidate_list(struct llcache_object ***lst_out, int *lst_len_out)
*/
if ((object->candidate_count == 0) &&
(object->fetch.fetch == NULL) &&
- (object->fetch.outstanding_query == false) &&
(object->store_state == LLCACHE_STATE_RAM) &&
(remaining_lifetime > llcache->minimum_lifetime)) {
lst[lst_len] = object;
@@ -2653,9 +2972,10 @@ static void llcache_persist(void *p)
total_elapsed += elapsed;
total_bandwidth = (total_written * 1000) / total_elapsed;
- NSLOG(llcache, DEBUG, "Wrote %zd bytes in %lums bw:%lu %s",
- written, elapsed, (written * 1000) / elapsed,
- nsurl_access(lst[idx]->url) );
+ NSLOG(llcache, DEBUG,
+ "Wrote %"PRIsizet" bytes in %lums bw:%lu %s",
+ written, elapsed, (written * 1000) / elapsed,
+ nsurl_access(lst[idx]->url) );
/* check to for the time quantum or the size
* (bandwidth) for this run being exceeded.
@@ -2720,8 +3040,9 @@ static void llcache_persist(void *p)
llcache->total_written += total_written;
llcache->total_elapsed += total_elapsed;
- NSLOG(llcache, DEBUG, "writeout size:%zd time:%lu bandwidth:%lubytes/s",
- total_written, total_elapsed, total_bandwidth);
+ NSLOG(llcache, DEBUG,
+ "writeout size:%"PRIsizet" time:%lu bandwidth:%lubytes/s",
+ total_written, total_elapsed, total_bandwidth);
NSLOG(llcache, DEBUG, "Rescheduling writeout in %dms", next);
guit->misc->schedule(next, llcache_persist, NULL);
@@ -2740,6 +3061,13 @@ static void llcache_fetch_callback(const fetch_msg *msg, void *p)
llcache_object *object = p;
llcache_event event;
+ if (llcache == NULL) {
+ NSLOG(llcache, CRITICAL, "Callback happened after llcache finalisation");
+ assert(false);
+ /* In case assertions are off, return here */
+ return;
+ }
+
NSLOG(llcache, DEBUG, "Fetch event %d for %p", msg->type, object);
switch (msg->type) {
@@ -2765,6 +3093,7 @@ static void llcache_fetch_callback(const fetch_msg *msg, void *p)
error = llcache_fetch_redirect(object,
msg->data.redirect, &object);
break;
+
case FETCH_NOTMODIFIED:
/* Conditional request determined that cached object is fresh */
error = llcache_fetch_notmodified(object, &object);
@@ -2777,6 +3106,7 @@ static void llcache_fetch_callback(const fetch_msg *msg, void *p)
msg->data.header_or_data.buf,
msg->data.header_or_data.len);
break;
+
case FETCH_FINISHED:
/* Finished fetching */
{
@@ -2808,14 +3138,9 @@ static void llcache_fetch_callback(const fetch_msg *msg, void *p)
/* Out-of-band information */
case FETCH_TIMEDOUT:
/* Timed out while trying to fetch. */
- /* The fetch has already been cleaned up by the fetcher but
- * we would like to retry if we can. */
- if (object->fetch.retries_remaining > 1) {
- object->fetch.retries_remaining--;
- error = llcache_object_refetch(object);
- break;
- }
- /* Fall through */
+ error = llcache_fetch_timeout(object);
+ break;
+
case FETCH_ERROR:
/* An error occurred while fetching */
/* The fetch has has already been cleaned up by the fetcher */
@@ -2834,15 +3159,41 @@ static void llcache_fetch_callback(const fetch_msg *msg, void *p)
/** \todo Consider using errorcode for something */
event.type = LLCACHE_EVENT_ERROR;
- event.data.msg = msg->data.error;
+ event.data.error.code = NSERROR_UNKNOWN;
+ event.data.error.msg = msg->data.error;
error = llcache_send_event_to_users(object, &event);
break;
+
case FETCH_PROGRESS:
/* Progress update */
event.type = LLCACHE_EVENT_PROGRESS;
- event.data.msg = msg->data.progress;
+ event.data.progress_msg = msg->data.progress;
+
+ error = llcache_send_event_to_users(object, &event);
+
+ break;
+
+ case FETCH_CERTS:
+ /* Certificate information from the fetch */
+
+ if (object->chain != NULL) {
+ cert_chain_free(object->chain);
+ object->chain = NULL;
+ }
+
+ /* Persist the chain onto our object */
+ error = cert_chain_dup(msg->data.chain, &object->chain);
+ if (error != NSERROR_OK) {
+ NSLOG(llcache, ERROR,
+ "Unable to duplicate cert chain into cache: %s",
+ messages_get_errorcode(error));
+ }
+
+ /* Now pass on the event */
+ event.type = LLCACHE_EVENT_GOT_CERTS;
+ event.data.chain = msg->data.chain;
error = llcache_send_event_to_users(object, &event);
@@ -2860,6 +3211,7 @@ static void llcache_fetch_callback(const fetch_msg *msg, void *p)
error = llcache_fetch_auth(object, msg->data.auth.realm);
break;
+
case FETCH_CERT_ERR:
/* Something went wrong when validating TLS certificates */
@@ -2869,10 +3221,9 @@ static void llcache_fetch_callback(const fetch_msg *msg, void *p)
object->candidate = NULL;
}
- error = llcache_fetch_cert_error(object,
- msg->data.cert_err.certs,
- msg->data.cert_err.num_certs);
+ error = llcache_fetch_cert_error(object);
break;
+
case FETCH_SSL_ERR:
/* TLS connection setup failed */
@@ -3044,6 +3395,39 @@ static nserror llcache_object_notify_users(llcache_object *object)
if (handle->state == LLCACHE_FETCH_INIT &&
objstate > LLCACHE_FETCH_INIT) {
handle->state = LLCACHE_FETCH_HEADERS;
+
+ /* Emit any certificate data we hold */
+ if (object->chain != NULL) {
+ event.type = LLCACHE_EVENT_GOT_CERTS;
+ event.data.chain = object->chain;
+ error = handle->cb(handle, &event, handle->pw);
+ } else {
+ error = NSERROR_OK;
+ }
+
+ if (user->queued_for_delete) {
+ next_user = user->next;
+ llcache_object_remove_user(object, user);
+ llcache_object_user_destroy(user);
+
+ if (error != NSERROR_OK)
+ return error;
+
+ continue;
+ } else if (error == NSERROR_NEED_DATA) {
+ /* User requested replay */
+ handle->state = LLCACHE_FETCH_HEADERS;
+
+ /* Continue with the next user -- we'll
+ * reemit the event next time round */
+ user->iterator_target = false;
+ next_user = user->next;
+ llcache_users_not_caught_up();
+ continue;
+ } else if (error != NSERROR_OK) {
+ user->iterator_target = false;
+ return error;
+ }
}
/* User: HEADERS, Obj: DATA, COMPLETE => User->DATA */
@@ -3237,6 +3621,14 @@ llcache_object_snapshot(llcache_object *object, llcache_object **snapshot)
}
}
+ if (object->chain != NULL) {
+ error = cert_chain_dup(object->chain, &newobj->chain);
+ if (error != NSERROR_OK) {
+ llcache_object_destroy(newobj);
+ return error;
+ }
+ }
+
newobj->fetch.state = LLCACHE_FETCH_COMPLETE;
*snapshot = newobj;
@@ -3274,9 +3666,51 @@ total_object_size(llcache_object *object)
}
}
+ tot += cert_chain_size(object->chain);
+
return tot;
}
+/**
+ * Catch up the cache users with state changes from fetchers.
+ *
+ * \param ignored We ignore this because all our state comes from llcache.
+ */
+static void llcache_catch_up_all_users(void *ignored)
+{
+ llcache_object *object;
+
+ /* Assume after this we'll be all caught up. If any user of a handle
+ * defers then we'll invalidate all_caught_up and reschedule via
+ * llcache_users_not_caught_up()
+ */
+ llcache->all_caught_up = true;
+
+ /* Catch new users up with state of objects */
+ for (object = llcache->cached_objects; object != NULL;
+ object = object->next) {
+ llcache_object_notify_users(object);
+ }
+
+ for (object = llcache->uncached_objects; object != NULL;
+ object = object->next) {
+ llcache_object_notify_users(object);
+ }
+}
+
+/**
+ * Ask for ::llcache_catch_up_all_users to be scheduled ASAP to pump the
+ * user state machines.
+ */
+static void llcache_users_not_caught_up(void)
+{
+ if (llcache->all_caught_up) {
+ llcache->all_caught_up = false;
+ guit->misc->schedule(0, llcache_catch_up_all_users, NULL);
+ }
+}
+
+
/******************************************************************************
* Public API *
******************************************************************************/
@@ -3313,8 +3747,7 @@ void llcache_clean(bool purge)
/* The candidate count of uncacheable objects is always 0 */
if ((object->users == NULL) &&
(object->candidate_count == 0) &&
- (object->fetch.fetch == NULL) &&
- (object->fetch.outstanding_query == false)) {
+ (object->fetch.fetch == NULL)) {
NSLOG(llcache, DEBUG, "Discarding uncachable object with no users (%p) %s",
object, nsurl_access(object->url));
@@ -3339,7 +3772,6 @@ void llcache_clean(bool purge)
if ((object->users == NULL) &&
(object->candidate_count == 0) &&
(object->fetch.fetch == NULL) &&
- (object->fetch.outstanding_query == false) &&
(remaining_lifetime <= 0)) {
/* object is stale */
NSLOG(llcache, DEBUG, "discarding stale cacheable object with no "
@@ -3380,7 +3812,6 @@ void llcache_clean(bool purge)
if ((object->users == NULL) &&
(object->candidate_count == 0) &&
(object->fetch.fetch == NULL) &&
- (object->fetch.outstanding_query == false) &&
(object->store_state == LLCACHE_STATE_DISC)) {
guit->llcache->release(object->url, BACKING_STORE_NONE);
@@ -3388,9 +3819,9 @@ void llcache_clean(bool purge)
llcache_size -= object->source_len;
- NSLOG(llcache, DEBUG, "Freeing source data for %p len:%zd",
- object,
- object->source_len);
+ NSLOG(llcache, DEBUG,
+ "Freeing source data for %p len:%"PRIsizet,
+ object, object->source_len);
}
}
@@ -3405,11 +3836,10 @@ void llcache_clean(bool purge)
if ((object->users == NULL) &&
(object->candidate_count == 0) &&
(object->fetch.fetch == NULL) &&
- (object->fetch.outstanding_query == false) &&
(object->store_state == LLCACHE_STATE_DISC) &&
(object->source_data == NULL)) {
NSLOG(llcache, DEBUG,
- "discarding backed object len:%zd age:%ld (%p) %s",
+ "discarding backed object len:%"PRIsizet" age:%ld (%p) %s",
object->source_len,
(long)(time(NULL) - object->last_used),
object,
@@ -3437,10 +3867,9 @@ void llcache_clean(bool purge)
if ((object->users == NULL) &&
(object->candidate_count == 0) &&
(object->fetch.fetch == NULL) &&
- (object->fetch.outstanding_query == false) &&
(object->store_state == LLCACHE_STATE_RAM)) {
NSLOG(llcache, DEBUG,
- "discarding fresh object len:%zd age:%ld (%p) %s",
+ "discarding fresh object len:%"PRIsizet" age:%ld (%p) %s",
object->source_len,
(long)(time(NULL) - object->last_used),
object,
@@ -3454,7 +3883,7 @@ void llcache_clean(bool purge)
}
}
- NSLOG(llcache, DEBUG, "Size: %u (limit: %u)", llcache_size, limit);
+ NSLOG(llcache, DEBUG, "Size: %"PRIu32" (limit: %"PRIu32")", llcache_size, limit);
}
/* Exported interface documented in content/llcache.h */
@@ -3466,8 +3895,6 @@ llcache_initialise(const struct llcache_parameters *prm)
return NSERROR_NOMEM;
}
- llcache->query_cb = prm->cb;
- llcache->query_cb_pw = prm->cb_ctx;
llcache->limit = prm->limit;
llcache->minimum_lifetime = prm->minimum_lifetime;
llcache->minimum_bandwidth = prm->minimum_bandwidth;
@@ -3477,7 +3904,7 @@ llcache_initialise(const struct llcache_parameters *prm)
llcache->all_caught_up = true;
NSLOG(llcache, INFO,
- "llcache initialising with a limit of %d bytes",
+ "llcache initialising with a limit of %"PRIu32" bytes",
llcache->limit);
/* backing store initialisation */
@@ -3491,6 +3918,11 @@ void llcache_finalise(void)
llcache_object *object, *next;
uint64_t total_bandwidth = 0; /* total bandwidth */
+ /* Attempt to persist anything we have left lying around */
+ llcache_persist(NULL);
+ /* Now clear the persistence callback */
+ guit->misc->schedule(-1, llcache_persist, NULL);
+
/* Clean uncached objects */
for (object = llcache->uncached_objects; object != NULL; object = next) {
llcache_object_user *user, *next_user;
@@ -3551,51 +3983,16 @@ void llcache_finalise(void)
llcache = NULL;
}
-/**
- * Catch up the cache users with state changes from fetchers.
- *
- * \param ignored We ignore this because all our state comes from llcache.
- */
-static void llcache_catch_up_all_users(void *ignored)
-{
- llcache_object *object;
-
- /* Assume after this we'll be all caught up. If any user of a handle
- * defers then we'll invalidate all_caught_up and reschedule via
- * llcache_users_not_caught_up()
- */
- llcache->all_caught_up = true;
-
- /* Catch new users up with state of objects */
- for (object = llcache->cached_objects; object != NULL;
- object = object->next) {
- llcache_object_notify_users(object);
- }
-
- for (object = llcache->uncached_objects; object != NULL;
- object = object->next) {
- llcache_object_notify_users(object);
- }
-}
-
-/**
- * Ask for ::llcache_catch_up_all_users to be scheduled ASAP to pump the
- * user state machines.
- */
-static void llcache_users_not_caught_up(void)
-{
- if (llcache->all_caught_up) {
- llcache->all_caught_up = false;
- guit->misc->schedule(0, llcache_catch_up_all_users, NULL);
- }
-}
/* Exported interface documented in content/llcache.h */
-nserror llcache_handle_retrieve(nsurl *url, uint32_t flags,
- nsurl *referer, const llcache_post_data *post,
- llcache_handle_callback cb, void *pw,
- llcache_handle **result)
+nserror
+llcache_handle_retrieve(nsurl *url,
+ uint32_t flags,
+ nsurl *referer,
+ const llcache_post_data *post,
+ llcache_handle_callback cb, void *pw,
+ llcache_handle **result)
{
nserror error;
llcache_object_user *user;
@@ -3784,9 +4181,10 @@ nserror llcache_handle_force_stream(llcache_handle *handle)
/* See llcache.h for documentation */
nserror llcache_handle_invalidate_cache_data(llcache_handle *handle)
{
- if (handle->object != NULL && handle->object->fetch.fetch == NULL &&
- handle->object->cache.no_cache ==
- LLCACHE_VALIDATE_FRESH) {
+ if ((handle->object != NULL) &&
+ (handle->object->fetch.fetch == NULL) &&
+ (handle->object->cache.no_cache == LLCACHE_VALIDATE_FRESH)) {
+ /* mark the cached object as requiring validation */
handle->object->cache.no_cache = LLCACHE_VALIDATE_ONCE;
}
diff --git a/content/llcache.h b/content/llcache.h
index 796db66f8..f9a3016c6 100644
--- a/content/llcache.h
+++ b/content/llcache.h
@@ -30,7 +30,7 @@
#include "utils/errors.h"
#include "utils/nsurl.h"
-struct ssl_cert_info;
+struct cert_chain;
struct fetch_multipart_data;
/** Handle for low-level cache object */
@@ -48,8 +48,24 @@ typedef struct llcache_post_data {
} data; /**< POST data content */
} llcache_post_data;
+/** Flags for low-level cache object retrieval */
+enum llcache_retrieve_flag {
+ /* Note: We're permitted a maximum of 16 flags which must reside in the
+ * bottom 16 bits of the flags word. See hlcache.h for further details.
+ */
+ /** Force a new fetch */
+ LLCACHE_RETRIEVE_FORCE_FETCH = (1 << 0),
+ /** Requested URL was verified */
+ LLCACHE_RETRIEVE_VERIFIABLE = (1 << 1),
+ /**< No error pages */
+ LLCACHE_RETRIEVE_NO_ERROR_PAGES = (1 << 2),
+ /**< Stream data (implies that object is not cacheable) */
+ LLCACHE_RETRIEVE_STREAM_DATA = (1 << 3)
+};
+
/** Low-level cache event types */
typedef enum {
+ LLCACHE_EVENT_GOT_CERTS, /**< SSL certificates arrived */
LLCACHE_EVENT_HAD_HEADERS, /**< Received all headers */
LLCACHE_EVENT_HAD_DATA, /**< Received some data */
LLCACHE_EVENT_DONE, /**< Finished fetching data */
@@ -60,20 +76,30 @@ typedef enum {
LLCACHE_EVENT_REDIRECT /**< Fetch URL redirect occured */
} llcache_event_type;
-/** Low-level cache events */
+/**
+ * Low-level cache events.
+ *
+ * Lifetime of contained information is only for the duration of the event
+ * and must be copied if it is desirable to retain.
+ */
typedef struct {
- llcache_event_type type; /**< Type of event */
+ llcache_event_type type; /**< Type of event */
union {
struct {
- const uint8_t *buf; /**< Buffer of data */
- size_t len; /**< Length of buffer, in bytes */
- } data; /**< Received data */
- const char *msg; /**< Error or progress message */
+ const uint8_t *buf; /**< Buffer of data */
+ size_t len; /**< Byte length of buffer */
+ } data; /**< Received data */
struct {
- nsurl *from; /**< Redirect origin */
- nsurl *to; /**< Redirect target */
- } redirect; /**< Fetch URL redirect occured */
- } data; /**< Event data */
+ nserror code; /**< The error code */
+ const char *msg; /**< Error message */
+ } error;
+ const char *progress_msg; /**< Progress message */
+ struct {
+ nsurl *from; /**< Redirect origin */
+ nsurl *to; /**< Redirect target */
+ } redirect; /**< Fetch URL redirect occured */
+ const struct cert_chain *chain; /**< Certificate chain */
+ } data; /**< Event data */
} llcache_event;
/**
@@ -87,75 +113,6 @@ typedef struct {
typedef nserror (*llcache_handle_callback)(llcache_handle *handle,
const llcache_event *event, void *pw);
-/** Flags for low-level cache object retrieval */
-enum llcache_retrieve_flag {
- /* Note: We're permitted a maximum of 16 flags which must reside in the
- * bottom 16 bits of the flags word. See hlcache.h for further details.
- */
- /** Force a new fetch */
- LLCACHE_RETRIEVE_FORCE_FETCH = (1 << 0),
- /** Requested URL was verified */
- LLCACHE_RETRIEVE_VERIFIABLE = (1 << 1),
- /**< No error pages */
- LLCACHE_RETRIEVE_NO_ERROR_PAGES = (1 << 2),
- /**< Stream data (implies that object is not cacheable) */
- LLCACHE_RETRIEVE_STREAM_DATA = (1 << 3)
-};
-
-/** Low-level cache query types */
-typedef enum {
- LLCACHE_QUERY_AUTH, /**< Need authentication details */
- LLCACHE_QUERY_REDIRECT, /**< Need permission to redirect */
- LLCACHE_QUERY_SSL /**< SSL chain needs inspection */
-} llcache_query_type;
-
-/** Low-level cache query */
-typedef struct {
- llcache_query_type type; /**< Type of query */
-
- nsurl *url; /**< URL being fetched */
-
- union {
- struct {
- const char *realm; /**< Authentication realm */
- } auth;
-
- struct {
- const char *target; /**< Redirect target */
- } redirect;
-
- struct {
- const struct ssl_cert_info *certs;
- size_t num; /**< Number of certs in chain */
- } ssl;
- } data;
-} llcache_query;
-
-/**
- * Response handler for fetch-related queries
- *
- * \param proceed Whether to proceed with the fetch or not
- * \param cbpw Opaque value provided to llcache_query_callback
- * \return NSERROR_OK on success, appropriate error otherwise
- */
-typedef nserror (*llcache_query_response)(bool proceed, void *cbpw);
-
-/**
- * Callback to handle fetch-related queries
- *
- * \param query Object containing details of query
- * \param pw Pointer to callback-specific data
- * \param cb Callback that client should call once query is satisfied
- * \param cbpw Opaque value to pass into \a cb
- * \return NSERROR_OK on success, appropriate error otherwise
- *
- * \note This callback should return immediately. Once a suitable answer to
- * the query has been obtained, the provided response callback should be
- * called. This is intended to be an entirely asynchronous process.
- */
-typedef nserror (*llcache_query_callback)(const llcache_query *query, void *pw,
- llcache_query_response cb, void *cbpw);
-
/**
* Parameters to configure the low level cache backing store.
*/
@@ -164,67 +121,27 @@ struct llcache_store_parameters {
size_t limit; /**< The backing store upper bound target size */
size_t hysteresis; /**< The hysteresis around the target size */
-
- /** log2 of the default maximum number of entries the cache
- * can track.
- *
- * If unset this defaults to 16 (65536 entries) The cache
- * control file takes precedence so cache data remains
- * portable between builds with differing defaults.
- */
- unsigned int entry_size;
-
- /** log2 of the default number of entries in the mapping between
- * the url and cache entries.
- *
- * @note This is exposing an internal implementation detail of
- * the filesystem based default backing store implementation.
- * However it is likely any backing store implementation will
- * need some way to map url to cache entries so it is a
- * generally useful configuration value.
- *
- * Too small a value will cause unecessary collisions and
- * cache misses and larger values cause proportionaly larger
- * amounts of memory to be used.
- *
- * The "birthday paradox" means that the hash will experience
- * a collision in every 2^(address_size/2) urls the cache
- * stores.
- *
- * A value of 20 means one object stored in every 1024 will
- * cause a collion and a cache miss while using two megabytes
- * of storage.
- *
- * If unset this defaults to 20 (1048576 entries using two
- * megabytes) The cache control file takes precedence so cache
- * data remains portable between builds with differing
- * defaults.
- */
- unsigned int address_size;
};
/**
* Parameters to configure the low level cache.
*/
struct llcache_parameters {
- llcache_query_callback cb; /**< Query handler for llcache */
- void *cb_ctx; /**< Pointer to llcache query handler data */
-
size_t limit; /**< The target upper bound for the RAM cache size */
size_t hysteresis; /**< The hysteresis around the target size */
/** The minimum lifetime to consider sending objects to backing store.*/
- int minimum_lifetime;
+ int minimum_lifetime;
/** The minimum bandwidth to allow the backing store to
* use in bytes/second
*/
- size_t minimum_bandwidth;
+ size_t minimum_bandwidth;
/** The maximum bandwidth to allow the backing store to use in
* bytes/second
*/
- size_t maximum_bandwidth;
+ size_t maximum_bandwidth;
/** The time quantum over which to calculate the bandwidth values
*/
diff --git a/content/mimesniff.c b/content/mimesniff.c
index 9a11834f9..adc000dd7 100644
--- a/content/mimesniff.c
+++ b/content/mimesniff.c
@@ -260,6 +260,13 @@ static nserror mimesniff__match_unknown_exact(const uint8_t *data, size_t len,
SIG(&corestring_lwc_application_x_gzip, "\x1f\x8b\x08", true),
SIG(&corestring_lwc_application_postscript, "%!PS-Adobe-",true),
SIG(&corestring_lwc_application_pdf, "%PDF-", false),
+ SIG(&corestring_lwc_image_jxl, "\xFF\x0A", true), /* containerless jpeg xl*/
+ {
+ (const uint8_t *)"\x00\x00\x00\x0CJXL \x0D\x0A\x87\x0A",
+ 12,
+ true,
+ &corestring_lwc_image_jxl
+ }, /* containered jpeg xl*/
{ NULL, 0, false, NULL }
};
#undef SIG
@@ -376,6 +383,12 @@ static nserror mimesniff__compute_image(lwc_string *official_type,
SIG(&corestring_lwc_image_jpeg, "\xff\xd8\xff"),
SIG(&corestring_lwc_image_bmp, "BM"),
SIG(&corestring_lwc_image_vnd_microsoft_icon, "\x00\x00\x01\x00"),
+ SIG(&corestring_lwc_image_jxl, "\xFF\x0A"), /* containerless jpeg xl*/
+ {
+ (const uint8_t *)"\x00\x00\x00\x0CJXL \x0D\x0A\x87\x0A",
+ 12,
+ &corestring_lwc_image_jxl
+ }, /* containered jpeg xl*/
{ NULL, 0, NULL }
};
#undef SIG
diff --git a/content/textsearch.c b/content/textsearch.c
new file mode 100644
index 000000000..3f97d42ee
--- /dev/null
+++ b/content/textsearch.c
@@ -0,0 +1,740 @@
+/*
+ * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Free text search
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils/errors.h"
+#include "utils/utils.h"
+#include "utils/ascii.h"
+#include "netsurf/types.h"
+#include "desktop/selection.h"
+
+#include "content/content.h"
+#include "content/content_protected.h"
+#include "content/hlcache.h"
+#include "content/textsearch.h"
+
+/**
+ * search match
+ */
+struct list_entry {
+ /**
+ * previous match
+ */
+ struct list_entry *prev;
+
+ /**
+ * next match
+ */
+ struct list_entry *next;
+
+ /**
+ * start position of match
+ */
+ unsigned start_idx;
+
+ /**
+ * end of match
+ */
+ unsigned end_idx;
+
+ /**
+ * content opaque start pointer
+ */
+ struct box *start_box;
+
+ /**
+ * content opaque end pointer
+ */
+ struct box *end_box;
+
+ /**
+ * content specific selection object
+ */
+ struct selection *sel;
+};
+
+/**
+ * The context for a free text search
+ */
+struct textsearch_context {
+
+ /**
+ * content search was performed upon
+ */
+ struct content *c;
+
+ /**
+ * opaque pointer passed to constructor.
+ */
+ void *gui_p;
+
+ /**
+ * List of matches
+ */
+ struct list_entry *found;
+
+ /**
+ * current selected match
+ */
+ struct list_entry *current; /* first for select all */
+
+ /**
+ * query string search results are for
+ */
+ char *string;
+ bool prev_case_sens;
+ bool newsearch;
+};
+
+
+/**
+ * broadcast textsearch message
+ */
+static inline void
+textsearch_broadcast(struct textsearch_context *textsearch,
+ int type,
+ bool state,
+ const char *string)
+{
+ union content_msg_data msg_data;
+ msg_data.textsearch.type = type;
+ msg_data.textsearch.ctx = textsearch->gui_p;
+ msg_data.textsearch.state = state;
+ msg_data.textsearch.string = string;
+ content_broadcast(textsearch->c, CONTENT_MSG_TEXTSEARCH, &msg_data);
+}
+
+
+/**
+ * Release the memory used by the list of matches,
+ * deleting selection objects too
+ */
+static void free_matches(struct textsearch_context *textsearch)
+{
+ struct list_entry *cur;
+ struct list_entry *nxt;
+
+ cur = textsearch->found->next;
+
+ /*
+ * empty the list before clearing and deleting the selections
+ * because the the clearing may update the toolkit immediately,
+ * causing nested accesses to the list
+ */
+
+ textsearch->found->prev = NULL;
+ textsearch->found->next = NULL;
+
+ for (; cur; cur = nxt) {
+ nxt = cur->next;
+ if (cur->sel) {
+ selection_destroy(cur->sel);
+ }
+ free(cur);
+ }
+}
+
+
+/**
+ * Specifies whether all matches or just the current match should
+ * be highlighted in the search text.
+ */
+static void search_show_all(bool all, struct textsearch_context *context)
+{
+ struct list_entry *a;
+
+ for (a = context->found->next; a; a = a->next) {
+ bool add = true;
+ if (!all && a != context->current) {
+ add = false;
+ if (a->sel) {
+ selection_destroy(a->sel);
+ a->sel = NULL;
+ }
+ }
+
+ if (add && !a->sel) {
+
+ a->sel = selection_create(context->c);
+ if (a->sel != NULL) {
+ selection_init(a->sel);
+ selection_set_position(a->sel,
+ a->start_idx,
+ a->end_idx);
+ }
+ }
+ }
+}
+
+
+/**
+ * Search for a string in a content.
+ *
+ * \param context The search context.
+ * \param string the string to search for
+ * \param string_len length of search string
+ * \param flags flags to control the search.
+ */
+static nserror
+search_text(struct textsearch_context *context,
+ const char *string,
+ int string_len,
+ search_flags_t flags)
+{
+ struct rect bounds;
+ union content_msg_data msg_data;
+ bool case_sensitive, forwards, showall;
+ nserror res = NSERROR_OK;
+
+ case_sensitive = ((flags & SEARCH_FLAG_CASE_SENSITIVE) != 0) ?
+ true : false;
+ forwards = ((flags & SEARCH_FLAG_FORWARDS) != 0) ? true : false;
+ showall = ((flags & SEARCH_FLAG_SHOWALL) != 0) ? true : false;
+
+ if (context->c == NULL) {
+ return res;
+ }
+
+ /* check if we need to start a new search or continue an old one */
+ if ((context->newsearch) ||
+ (context->prev_case_sens != case_sensitive)) {
+
+ if (context->string != NULL) {
+ free(context->string);
+ }
+
+ context->current = NULL;
+ free_matches(context);
+
+ context->string = malloc(string_len + 1);
+ if (context->string != NULL) {
+ memcpy(context->string, string, string_len);
+ context->string[string_len] = '\0';
+ }
+
+ /* indicate find operation starting */
+ textsearch_broadcast(context, CONTENT_TEXTSEARCH_FIND, true, NULL);
+
+
+ /* call content find handler */
+ res = context->c->handler->textsearch_find(context->c,
+ context,
+ string,
+ string_len,
+ case_sensitive);
+
+ /* indicate find operation finished */
+ textsearch_broadcast(context, CONTENT_TEXTSEARCH_FIND, false, NULL);
+
+ if (res != NSERROR_OK) {
+ free_matches(context);
+ return res;
+ }
+
+ context->prev_case_sens = case_sensitive;
+
+ /* new search, beginning at the top of the page */
+ context->current = context->found->next;
+ context->newsearch = false;
+
+ } else if (context->current != NULL) {
+ /* continued search in the direction specified */
+ if (forwards) {
+ if (context->current->next)
+ context->current = context->current->next;
+ } else {
+ if (context->current->prev)
+ context->current = context->current->prev;
+ }
+ }
+
+ /* update match state */
+ textsearch_broadcast(context,
+ CONTENT_TEXTSEARCH_MATCH,
+ (context->current != NULL),
+ NULL);
+
+ search_show_all(showall, context);
+
+ /* update back state */
+ textsearch_broadcast(context,
+ CONTENT_TEXTSEARCH_BACK,
+ ((context->current != NULL) &&
+ (context->current->prev != NULL)),
+ NULL);
+
+ /* update forward state */
+ textsearch_broadcast(context,
+ CONTENT_TEXTSEARCH_FORWARD,
+ ((context->current != NULL) &&
+ (context->current->next != NULL)),
+ NULL);
+
+
+ if (context->current == NULL) {
+ /* no current match */
+ return res;
+ }
+
+ /* call content match bounds handler */
+ res = context->c->handler->textsearch_bounds(context->c,
+ context->current->start_idx,
+ context->current->end_idx,
+ context->current->start_box,
+ context->current->end_box,
+ &bounds);
+ if (res == NSERROR_OK) {
+ msg_data.scroll.area = true;
+ msg_data.scroll.x0 = bounds.x0;
+ msg_data.scroll.y0 = bounds.y0;
+ msg_data.scroll.x1 = bounds.x1;
+ msg_data.scroll.y1 = bounds.y1;
+ content_broadcast(context->c, CONTENT_MSG_SCROLL, &msg_data);
+ }
+
+ return res;
+}
+
+
+/**
+ * Begins/continues the search process
+ *
+ * \note that this may be called many times for a single search.
+ *
+ * \param context The search context in use.
+ * \param flags The flags forward/back etc
+ * \param string The string to match
+ */
+static nserror
+content_textsearch_step(struct textsearch_context *textsearch,
+ search_flags_t flags,
+ const char *string)
+{
+ int string_len;
+ int i = 0;
+ nserror res = NSERROR_OK;
+
+ assert(textsearch != NULL);
+
+ /* broadcast recent query string */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_RECENT,
+ false,
+ string);
+
+ string_len = strlen(string);
+ for (i = 0; i < string_len; i++) {
+ if (string[i] != '#' && string[i] != '*')
+ break;
+ }
+
+ if (i < string_len) {
+ res = search_text(textsearch, string, string_len, flags);
+ } else {
+ union content_msg_data msg_data;
+
+ free_matches(textsearch);
+
+ /* update match state */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_MATCH,
+ true,
+ NULL);
+
+ /* update back state */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_BACK,
+ false,
+ NULL);
+
+ /* update forward state */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_FORWARD,
+ false,
+ NULL);
+
+ /* clear scroll */
+ msg_data.scroll.area = false;
+ msg_data.scroll.x0 = 0;
+ msg_data.scroll.y0 = 0;
+ content_broadcast(textsearch->c,
+ CONTENT_MSG_SCROLL,
+ &msg_data);
+ }
+
+ return res;
+}
+
+
+/**
+ * Terminate a search.
+ *
+ * \param c content to clear
+ */
+static nserror content_textsearch__clear(struct content *c)
+{
+ free(c->textsearch.string);
+ c->textsearch.string = NULL;
+
+ if (c->textsearch.context != NULL) {
+ content_textsearch_destroy(c->textsearch.context);
+ c->textsearch.context = NULL;
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * create a search_context
+ *
+ * \param c The content the search_context is connected to
+ * \param context A context pointer passed to the provider routines.
+ * \param search_out A pointer to recive the new text search context
+ * \return NSERROR_OK on success and \a search_out updated else error code
+ */
+static nserror
+content_textsearch_create(struct content *c,
+ void *gui_data,
+ struct textsearch_context **textsearch_out)
+{
+ struct textsearch_context *context;
+ struct list_entry *search_head;
+ content_type type;
+
+ if ((c->handler->textsearch_find == NULL) ||
+ (c->handler->textsearch_bounds == NULL)) {
+ /*
+ * content has no free text find handler so searching
+ * is unsupported.
+ */
+ return NSERROR_NOT_IMPLEMENTED;
+ }
+
+ type = c->handler->type();
+
+ context = malloc(sizeof(struct textsearch_context));
+ if (context == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ search_head = malloc(sizeof(struct list_entry));
+ if (search_head == NULL) {
+ free(context);
+ return NSERROR_NOMEM;
+ }
+
+ search_head->start_idx = 0;
+ search_head->end_idx = 0;
+ search_head->start_box = NULL;
+ search_head->end_box = NULL;
+ search_head->sel = NULL;
+ search_head->prev = NULL;
+ search_head->next = NULL;
+
+ context->found = search_head;
+ context->current = NULL;
+ context->string = NULL;
+ context->prev_case_sens = false;
+ context->newsearch = true;
+ context->c = c;
+ context->gui_p = gui_data;
+
+ *textsearch_out = context;
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface, documented in content/textsearch.h */
+const char *
+content_textsearch_find_pattern(const char *string,
+ int s_len,
+ const char *pattern,
+ int p_len,
+ bool case_sens,
+ unsigned int *m_len)
+{
+ struct { const char *ss, *s, *p; bool first; } context[16];
+ const char *ep = pattern + p_len;
+ const char *es = string + s_len;
+ const char *p = pattern - 1; /* a virtual '*' before the pattern */
+ const char *ss = string;
+ const char *s = string;
+ bool first = true;
+ int top = 0;
+
+ while (p < ep) {
+ bool matches;
+ if (p < pattern || *p == '*') {
+ char ch;
+
+ /* skip any further asterisks; one is the same as many
+ */
+ do p++; while (p < ep && *p == '*');
+
+ /* if we're at the end of the pattern, yes, it matches
+ */
+ if (p >= ep) break;
+
+ /* anything matches a # so continue matching from
+ here, and stack a context that will try to match
+ the wildcard against the next character */
+
+ ch = *p;
+ if (ch != '#') {
+ /* scan forwards until we find a match for
+ this char */
+ if (!case_sens) ch = ascii_to_upper(ch);
+ while (s < es) {
+ if (case_sens) {
+ if (*s == ch) break;
+ } else if (ascii_to_upper(*s) == ch)
+ break;
+ s++;
+ }
+ }
+
+ if (s < es) {
+ /* remember where we are in case the match
+ fails; we may then resume */
+ if (top < (int)NOF_ELEMENTS(context)) {
+ context[top].ss = ss;
+ context[top].s = s + 1;
+ context[top].p = p - 1;
+ /* ptr to last asterisk */
+ context[top].first = first;
+ top++;
+ }
+
+ if (first) {
+ ss = s;
+ /* remember first non-'*' char */
+ first = false;
+ }
+
+ matches = true;
+ } else {
+ matches = false;
+ }
+
+ } else if (s < es) {
+ char ch = *p;
+ if (ch == '#')
+ matches = true;
+ else {
+ if (case_sens)
+ matches = (*s == ch);
+ else
+ matches = (ascii_to_upper(*s) == ascii_to_upper(ch));
+ }
+ if (matches && first) {
+ ss = s; /* remember first non-'*' char */
+ first = false;
+ }
+ } else {
+ matches = false;
+ }
+
+ if (matches) {
+ p++; s++;
+ } else {
+ /* doesn't match,
+ * resume with stacked context if we have one */
+ if (--top < 0)
+ return NULL; /* no match, give up */
+
+ ss = context[top].ss;
+ s = context[top].s;
+ p = context[top].p;
+ first = context[top].first;
+ }
+ }
+
+ /* end of pattern reached */
+ *m_len = max(s - ss, 1);
+ return ss;
+}
+
+
+/* exported interface, documented in content/textsearch.h */
+nserror
+content_textsearch_add_match(struct textsearch_context *context,
+ unsigned start_idx,
+ unsigned end_idx,
+ struct box *start_box,
+ struct box *end_box)
+{
+ struct list_entry *entry;
+
+ /* found string in box => add to list */
+ entry = calloc(1, sizeof(*entry));
+ if (entry == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ entry->start_idx = start_idx;
+ entry->end_idx = end_idx;
+ entry->start_box = start_box;
+ entry->end_box = end_box;
+ entry->sel = NULL;
+
+ entry->next = NULL;
+ entry->prev = context->found->prev;
+
+ if (context->found->prev == NULL) {
+ context->found->next = entry;
+ } else {
+ context->found->prev->next = entry;
+ }
+
+ context->found->prev = entry;
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface, documented in content/textsearch.h */
+bool
+content_textsearch_ishighlighted(struct textsearch_context *textsearch,
+ unsigned start_offset,
+ unsigned end_offset,
+ unsigned *start_idx,
+ unsigned *end_idx)
+{
+ struct list_entry *cur;
+
+ for (cur = textsearch->found->next; cur != NULL; cur = cur->next) {
+ if (cur->sel &&
+ selection_highlighted(cur->sel,
+ start_offset,
+ end_offset,
+ start_idx,
+ end_idx)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+/* exported interface, documented in content/textsearch.h */
+nserror content_textsearch_destroy(struct textsearch_context *textsearch)
+{
+ assert(textsearch != NULL);
+
+ if (textsearch->string != NULL) {
+ /* broadcast recent query string */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_RECENT,
+ false,
+ textsearch->string);
+
+ free(textsearch->string);
+ }
+
+ /* update back state */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_BACK,
+ true,
+ NULL);
+
+ /* update forward state */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_FORWARD,
+ true,
+ NULL);
+
+ free_matches(textsearch);
+ free(textsearch);
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface, documented in content/content.h */
+nserror
+content_textsearch(struct hlcache_handle *h,
+ void *context,
+ search_flags_t flags,
+ const char *string)
+{
+ struct content *c = hlcache_handle_get_content(h);
+ nserror res;
+
+ assert(c != NULL);
+
+ if (string != NULL &&
+ c->textsearch.string != NULL &&
+ c->textsearch.context != NULL &&
+ strcmp(string, c->textsearch.string) == 0) {
+ /* Continue prev. search */
+ content_textsearch_step(c->textsearch.context, flags, string);
+
+ } else if (string != NULL) {
+ /* New search */
+ free(c->textsearch.string);
+ c->textsearch.string = strdup(string);
+ if (c->textsearch.string == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ if (c->textsearch.context != NULL) {
+ content_textsearch_destroy(c->textsearch.context);
+ c->textsearch.context = NULL;
+ }
+
+ res = content_textsearch_create(c,
+ context,
+ &c->textsearch.context);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ content_textsearch_step(c->textsearch.context, flags, string);
+
+ } else {
+ /* Clear search */
+ content_textsearch__clear(c);
+
+ free(c->textsearch.string);
+ c->textsearch.string = NULL;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface, documented in content/content.h */
+nserror content_textsearch_clear(struct hlcache_handle *h)
+{
+ struct content *c = hlcache_handle_get_content(h);
+ assert(c != 0);
+
+ return(content_textsearch__clear(c));
+}
diff --git a/content/textsearch.h b/content/textsearch.h
new file mode 100644
index 000000000..c32b17cca
--- /dev/null
+++ b/content/textsearch.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Interface to HTML searching.
+ */
+
+#ifndef NETSURF_CONTENT_SEARCH_H
+#define NETSURF_CONTENT_SEARCH_H
+
+#include "desktop/search.h"
+
+struct textsearch_context;
+struct content;
+struct hlcache_handle;
+struct box;
+
+/**
+ * Free text search a content
+ *
+ * \param[in] h Handle to content to search.
+ * \param[in] context The context passed to gui table search handlers
+ * \param[in] flags The flags that control the search
+ * \param[in] The string being searched for.
+ * \retun NSERROR_OK on success else error code on faliure
+ */
+nserror content_textsearch(struct hlcache_handle *h, void *context, search_flags_t flags, const char *string);
+
+/**
+ * Clear a search
+ *
+ * \param[in] h Handle to content to clear search from.
+ */
+nserror content_textsearch_clear(struct hlcache_handle *h);
+
+/**
+ * Ends the search process, invalidating all state freeing the list of
+ * found boxes.
+ */
+nserror content_textsearch_destroy(struct textsearch_context *textsearch);
+
+/**
+ * Determines whether any portion of the given text box should be
+ * selected because it matches the current search string.
+ *
+ * \param textsearch The search context to hilight entries from.
+ * \param c The content to highlight within.
+ * \param start_offset byte offset within text of string to be checked
+ * \param end_offset byte offset within text
+ * \param start_idx byte offset within string of highlight start
+ * \param end_idx byte offset of highlight end
+ * \return true iff part of the box should be highlighted
+ */
+bool content_textsearch_ishighlighted(struct textsearch_context *textsearch,
+ unsigned start_offset,
+ unsigned end_offset,
+ unsigned *start_idx,
+ unsigned *end_idx);
+
+/**
+ * Find the first occurrence of 'match' in 'string' and return its index
+ *
+ * \param string the string to be searched (unterminated)
+ * \param s_len length of the string to be searched
+ * \param pattern the pattern for which we are searching (unterminated)
+ * \param p_len length of pattern
+ * \param case_sens true iff case sensitive match required
+ * \param m_len accepts length of match in bytes
+ * \return pointer to first match, NULL if none
+ */
+const char *content_textsearch_find_pattern(const char *string, int s_len, const char *pattern, int p_len, bool case_sens, unsigned int *m_len);
+
+/**
+ * Add a new entry to the list of matches
+ *
+ * \param context The search context to add the entry to.
+ * \param start_idx Offset of match start within textual representation
+ * \param end_idx Offset of match end
+ * \param start A pointer for the start
+ * \param end A pointer for the end
+ * \return NSERROR_OK on sucess else error code on faliure
+ */
+nserror content_textsearch_add_match(struct textsearch_context *context, unsigned start_idx, unsigned end_idx, struct box *start_ptr, struct box *end_ptr);
+
+#endif
diff --git a/content/urldb.c b/content/urldb.c
index 4bdb10e66..881f76f6d 100644
--- a/content/urldb.c
+++ b/content/urldb.c
@@ -111,7 +111,6 @@
#include "utils/http.h"
#include "netsurf/bitmap.h"
#include "desktop/cookie_manager.h"
-#include "desktop/gui_internal.h"
#include "content/content.h"
#include "content/urldb.h"
@@ -1522,7 +1521,10 @@ static void urldb_dump_search(struct search_node *parent, int depth)
for (h = parent->data; h; h = h->parent) {
if (h->part) {
r = snprintf(&s[i], sl - i, "%s", h->part);
- if ((i + r) > sl) {
+ if (r < 0) {
+ break;
+ }
+ if ((i + r) >= sl) {
break;
}
i += r;
@@ -2969,7 +2971,7 @@ nserror urldb_load(const char *filename)
for (i = 0; i < urls; i++) {
struct path_data *p = NULL;
char scheme[64], ports[10];
- char url[64 + 3 + 256 + 6 + 4096 + 1];
+ char url[64 + 3 + 256 + 6 + 4096 + 1 + 1];
unsigned int port;
bool is_file = false;
nsurl *nsurl;
diff --git a/content/urldb.h b/content/urldb.h
index 0ad64267f..c68c2a611 100644
--- a/content/urldb.h
+++ b/content/urldb.h
@@ -75,6 +75,27 @@ nserror urldb_set_url_content_type(struct nsurl *url, content_type type);
/**
+ * Set authentication data for an URL
+ *
+ * \param url The URL to consider
+ * \param realm The authentication realm
+ * \param auth The authentication details (in form username:password)
+ */
+void urldb_set_auth_details(struct nsurl *url, const char *realm, const char *auth);
+
+
+/**
+ * Look up authentication details in database
+ *
+ * \param url Absolute URL to search for
+ * \param realm When non-NULL, it is realm which can be used to determine
+ * the protection space when that's not been done before for given URL.
+ * \return Pointer to authentication details, or NULL if not found
+ */
+const char *urldb_get_auth_details(struct nsurl *url, const char *realm);
+
+
+/**
* Update an URL's visit data
*
* \param url The URL to update
diff --git a/desktop/Makefile b/desktop/Makefile
index ffd932177..5e190275d 100644
--- a/desktop/Makefile
+++ b/desktop/Makefile
@@ -2,8 +2,8 @@
S_DESKTOP := cookie_manager.c knockout.c hotlist.c mouse.c \
plot_style.c print.c search.c searchweb.c scrollbar.c \
- sslcert_viewer.c textarea.c version.c system_colour.c \
- local_history.c global_history.c treeview.c
+ textarea.c version.c system_colour.c \
+ local_history.c global_history.c treeview.c page-info.c
S_DESKTOP := $(addprefix desktop/,$(S_DESKTOP))
@@ -12,7 +12,8 @@ desktop/version.c: testament $(OBJROOT)/testament.h
# S_BROWSER are sources related to full browsers but are common
# between RISC OS, GTK, BeOS and AmigaOS builds
-S_BROWSER := browser.c browser_history.c download.c frames.c netsurf.c \
+S_BROWSER := bitmap.c browser.c browser_window.c browser_history.c \
+ download.c frames.c netsurf.c cw_helper.c \
save_complete.c save_text.c selection.c textinput.c gui_factory.c \
save_pdf.c font_haru.c
diff --git a/desktop/bitmap.c b/desktop/bitmap.c
new file mode 100644
index 000000000..0602773ca
--- /dev/null
+++ b/desktop/bitmap.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright 2022 Michael Drake <tlsa@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Internal core bitmap interface.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "utils/log.h"
+#include "utils/errors.h"
+
+#include "desktop/bitmap.h"
+#include "desktop/gui_internal.h"
+
+/** The client bitmap format. */
+bitmap_fmt_t bitmap_fmt;
+
+/** The client bitmap colour channel layout. */
+struct bitmap_colour_layout bitmap_layout = {
+ .r = 0,
+ .g = 1,
+ .b = 2,
+ .a = 3,
+};
+
+/**
+ * Get the colour layout for the given bitmap format.
+ *
+ * \param[in] fmt Pixel format to get channel layout for,
+ * \return channel layout structure.
+ */
+static struct bitmap_colour_layout bitmap__get_colour_layout(
+ const bitmap_fmt_t *fmt)
+{
+ switch (fmt->layout) {
+ default:
+ /* Fall through. */
+ case BITMAP_LAYOUT_R8G8B8A8:
+ return (struct bitmap_colour_layout) {
+ .r = 0,
+ .g = 1,
+ .b = 2,
+ .a = 3,
+ };
+
+ case BITMAP_LAYOUT_B8G8R8A8:
+ return (struct bitmap_colour_layout) {
+ .b = 0,
+ .g = 1,
+ .r = 2,
+ .a = 3,
+ };
+
+ case BITMAP_LAYOUT_A8R8G8B8:
+ return (struct bitmap_colour_layout) {
+ .a = 0,
+ .r = 1,
+ .g = 2,
+ .b = 3,
+ };
+
+ case BITMAP_LAYOUT_A8B8G8R8:
+ return (struct bitmap_colour_layout) {
+ .a = 0,
+ .b = 1,
+ .g = 2,
+ .r = 3,
+ };
+ }
+}
+
+/**
+ * Get string for given pixel layout.
+ *
+ * \param[in] layout The pixel layout to get string for,
+ * \return String for given layout.
+ */
+static const char *bitmap__layout_to_str(enum bitmap_layout layout)
+{
+ const char *const str[] = {
+ [BITMAP_LAYOUT_R8G8B8A8] = "Byte-wise RGBA",
+ [BITMAP_LAYOUT_B8G8R8A8] = "Byte-wise BGRA",
+ [BITMAP_LAYOUT_A8R8G8B8] = "Byte-wise ARGB",
+ [BITMAP_LAYOUT_A8B8G8R8] = "Byte-wise ABGR",
+ [BITMAP_LAYOUT_RGBA8888] = "0xRRGGBBAA (native endian)",
+ [BITMAP_LAYOUT_BGRA8888] = "0xBBGGRRAA (native endian)",
+ [BITMAP_LAYOUT_ARGB8888] = "0xAARRGGBB (native endian)",
+ [BITMAP_LAYOUT_ABGR8888] = "0xAABBGGRR (native endian)",
+ };
+
+ if ((size_t)layout >= (sizeof(str)) / sizeof(*str) ||
+ str[layout] == NULL) {
+ return "Unknown";
+ }
+
+ return str[layout];
+}
+
+/* Exported function, documented in include/netsurf/bitmap.h */
+void bitmap_set_format(const bitmap_fmt_t *bitmap_format)
+{
+ bitmap_fmt = *bitmap_format;
+
+ NSLOG(netsurf, INFO, "Setting core bitmap format to: %s%s",
+ bitmap__layout_to_str(bitmap_format->layout),
+ bitmap_format->pma ? " pre multiplied alpha" : "");
+
+ bitmap_fmt.layout = bitmap_sanitise_bitmap_layout(bitmap_fmt.layout);
+
+ if (bitmap_format->layout != bitmap_fmt.layout) {
+ NSLOG(netsurf, INFO, "Sanitised layout to: %s",
+ bitmap__layout_to_str(bitmap_fmt.layout));
+ }
+
+ bitmap_layout = bitmap__get_colour_layout(&bitmap_fmt);
+}
+
+/**
+ * Swap colour component order.
+ *
+ * \param[in] width Bitmap width in pixels.
+ * \param[in] height Bitmap height in pixels.
+ * \param[in] buffer Pixel buffer.
+ * \param[in] rowstride Pixel buffer row stride in bytes.
+ * \param[in] to Pixel layout to convert to.
+ * \param[in] from Pixel layout to convert from.
+ */
+static inline void bitmap__format_convert(
+ int width,
+ int height,
+ uint8_t *buffer,
+ size_t rowstride,
+ struct bitmap_colour_layout to,
+ struct bitmap_colour_layout from)
+{
+ /* Just swapping the components around */
+ for (int y = 0; y < height; y++) {
+ uint8_t *row = buffer;
+
+ for (int x = 0; x < width; x++) {
+ const uint32_t px = *((uint32_t *)(void *) row);
+
+ row[to.r] = ((const uint8_t *) &px)[from.r];
+ row[to.g] = ((const uint8_t *) &px)[from.g];
+ row[to.b] = ((const uint8_t *) &px)[from.b];
+ row[to.a] = ((const uint8_t *) &px)[from.a];
+
+ row += sizeof(uint32_t);
+ }
+
+ buffer += rowstride;
+ }
+}
+
+/**
+ * Convert plain alpha to premultiplied alpha.
+ *
+ * \param[in] width Bitmap width in pixels.
+ * \param[in] height Bitmap height in pixels.
+ * \param[in] buffer Pixel buffer.
+ * \param[in] rowstride Pixel buffer row stride in bytes.
+ * \param[in] to Pixel layout to convert to.
+ * \param[in] from Pixel layout to convert from.
+ */
+static inline void bitmap__format_convert_to_pma(
+ int width,
+ int height,
+ uint8_t *buffer,
+ size_t rowstride,
+ struct bitmap_colour_layout to,
+ struct bitmap_colour_layout from)
+{
+ for (int y = 0; y < height; y++) {
+ uint8_t *row = buffer;
+
+ for (int x = 0; x < width; x++) {
+ const uint32_t px = *((uint32_t *)(void *) row);
+ uint32_t a, r, g, b;
+
+ r = ((const uint8_t *) &px)[from.r];
+ g = ((const uint8_t *) &px)[from.g];
+ b = ((const uint8_t *) &px)[from.b];
+ a = ((const uint8_t *) &px)[from.a];
+
+ if (a != 0) {
+ r = ((r * (a + 1)) >> 8) & 0xff;
+ g = ((g * (a + 1)) >> 8) & 0xff;
+ b = ((b * (a + 1)) >> 8) & 0xff;
+ } else {
+ r = g = b = 0;
+ }
+
+ row[to.r] = r;
+ row[to.g] = g;
+ row[to.b] = b;
+ row[to.a] = a;
+
+ row += sizeof(uint32_t);
+ }
+
+ buffer += rowstride;
+ }
+}
+
+/**
+ * Convert from premultiplied alpha to plain alpha.
+ *
+ * \param[in] width Bitmap width in pixels.
+ * \param[in] height Bitmap height in pixels.
+ * \param[in] buffer Pixel buffer.
+ * \param[in] rowstride Pixel buffer row stride in bytes.
+ * \param[in] to Pixel layout to convert to.
+ * \param[in] from Pixel layout to convert from.
+ */
+static inline void bitmap__format_convert_from_pma(
+ int width,
+ int height,
+ uint8_t *buffer,
+ size_t rowstride,
+ struct bitmap_colour_layout to,
+ struct bitmap_colour_layout from)
+{
+ for (int y = 0; y < height; y++) {
+ uint8_t *row = buffer;
+
+ for (int x = 0; x < width; x++) {
+ const uint32_t px = *((uint32_t *)(void *) row);
+ uint32_t a, r, g, b;
+
+ r = ((const uint8_t *) &px)[from.r];
+ g = ((const uint8_t *) &px)[from.g];
+ b = ((const uint8_t *) &px)[from.b];
+ a = ((const uint8_t *) &px)[from.a];
+
+ if (a != 0) {
+ r = (r << 8) / a;
+ g = (g << 8) / a;
+ b = (b << 8) / a;
+
+ r = (r > 255) ? 255 : r;
+ g = (g > 255) ? 255 : g;
+ b = (b > 255) ? 255 : b;
+ } else {
+ r = g = b = 0;
+ }
+
+ row[to.r] = r;
+ row[to.g] = g;
+ row[to.b] = b;
+ row[to.a] = a;
+
+ row += sizeof(uint32_t);
+ }
+
+ buffer += rowstride;
+ }
+}
+
+/* Exported function, documented in desktop/bitmap.h */
+void bitmap_format_convert(void *bitmap,
+ const bitmap_fmt_t *fmt_from,
+ const bitmap_fmt_t *fmt_to)
+{
+ int width = guit->bitmap->get_width(bitmap);
+ int height = guit->bitmap->get_height(bitmap);
+ bool opaque = guit->bitmap->get_opaque(bitmap);
+ uint8_t *buffer = guit->bitmap->get_buffer(bitmap);
+ size_t rowstride = guit->bitmap->get_rowstride(bitmap);
+ struct bitmap_colour_layout to = bitmap__get_colour_layout(fmt_to);
+ struct bitmap_colour_layout from = bitmap__get_colour_layout(fmt_from);
+
+ NSLOG(netsurf, DEEPDEBUG, "%p: format conversion (%u%s --> %u%s)",
+ bitmap,
+ fmt_from->layout, fmt_from->pma ? " pma" : "",
+ fmt_to->layout, fmt_to->pma ? " pma" : "");
+
+ if (fmt_from->pma == fmt_to->pma) {
+ /* Just component order to switch. */
+ bitmap__format_convert(
+ width, height, buffer,
+ rowstride, to, from);
+
+ } else if (opaque == false) {
+ /* Need to do conversion to/from premultiplied alpha. */
+ if (fmt_to->pma) {
+ bitmap__format_convert_to_pma(
+ width, height, buffer,
+ rowstride, to, from);
+ } else {
+ bitmap__format_convert_from_pma(
+ width, height, buffer,
+ rowstride, to, from);
+ }
+ }
+}
+
+/* Exported function, documented in desktop/bitmap.h */
+bool bitmap_test_opaque(void *bitmap)
+{
+ int width = guit->bitmap->get_width(bitmap);
+ int height = guit->bitmap->get_height(bitmap);
+ size_t rowstride = guit->bitmap->get_rowstride(bitmap);
+ const uint8_t *buffer = guit->bitmap->get_buffer(bitmap);
+
+ width *= sizeof(uint32_t);
+
+ for (int y = 0; y < height; y++) {
+ const uint8_t *row = buffer;
+
+ for (int x = bitmap_layout.a; x < width; x += 4) {
+ if (row[x] != 0xff) {
+ return false;
+ }
+ }
+
+ buffer += rowstride;
+ }
+
+ return true;
+}
diff --git a/desktop/bitmap.h b/desktop/bitmap.h
new file mode 100644
index 000000000..51ce2c908
--- /dev/null
+++ b/desktop/bitmap.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2022 Michael Drake <tlsa@nesturf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Internal core bitmap interface.
+ */
+
+#ifndef _NETSURF_DESKTOP_BITMAP_H_
+#define _NETSURF_DESKTOP_BITMAP_H_
+
+#include <nsutils/endian.h>
+
+#include "netsurf/types.h"
+#include "netsurf/bitmap.h"
+
+/** Pixel format: colour component order. */
+struct bitmap_colour_layout {
+ uint8_t r; /**< Byte offset within pixel to red component. */
+ uint8_t g; /**< Byte offset within pixel to green component. */
+ uint8_t b; /**< Byte offset within pixel to blue component. */
+ uint8_t a; /**< Byte offset within pixel to alpha component. */
+};
+
+/** The client bitmap format. */
+extern bitmap_fmt_t bitmap_fmt;
+
+/** The client bitmap colour channel layout. */
+extern struct bitmap_colour_layout bitmap_layout;
+
+/**
+ * Convert a bitmap pixel to a NetSurf colour (0xAARRGGBB).
+ *
+ * The bitmap must be in the client format.
+ *
+ * \param[in] Pointer to a pixel in the bitmap's pixel data.
+ * \return The corresponding NetSurf colour.
+ */
+static inline colour bitmap_pixel_to_colour(const uint8_t *pixel)
+{
+ return (pixel[bitmap_layout.r] << 0) |
+ (pixel[bitmap_layout.g] << 8) |
+ (pixel[bitmap_layout.b] << 16) |
+ (pixel[bitmap_layout.a] << 24);
+}
+
+/**
+ * Sanitise bitmap pixel component layout.
+ *
+ * Map endian-dependant layouts to byte-wise layout for the host.
+ *
+ * \param[in] layout Layout to convert.
+ * \return sanitised layout.
+ */
+static inline enum bitmap_layout bitmap_sanitise_bitmap_layout(
+ enum bitmap_layout layout)
+{
+ bool le = endian_host_is_le();
+
+ switch (layout) {
+ case BITMAP_LAYOUT_RGBA8888:
+ layout = (le) ? BITMAP_LAYOUT_A8B8G8R8
+ : BITMAP_LAYOUT_R8G8B8A8;
+ break;
+ case BITMAP_LAYOUT_BGRA8888:
+ layout = (le) ? BITMAP_LAYOUT_A8R8G8B8
+ : BITMAP_LAYOUT_B8G8R8A8;
+ break;
+ case BITMAP_LAYOUT_ARGB8888:
+ layout = (le) ? BITMAP_LAYOUT_B8G8R8A8
+ : BITMAP_LAYOUT_A8R8G8B8;
+ break;
+ case BITMAP_LAYOUT_ABGR8888:
+ layout = (le) ? BITMAP_LAYOUT_R8G8B8A8
+ : BITMAP_LAYOUT_A8B8G8R8;
+ break;
+ default:
+ break;
+ }
+
+ return layout;
+}
+
+/**
+ * Convert bitmap from one format to another.
+ *
+ * Note that both formats should be sanitised.
+ *
+ * \param[in] bitmap The bitmap to convert.
+ * \param[in] from The current bitmap format specifier.
+ * \param[in] to The bitmap format to convert to.
+ */
+void bitmap_format_convert(void *bitmap,
+ const bitmap_fmt_t *from,
+ const bitmap_fmt_t *to);
+
+/**
+ * Convert a bitmap to the client bitmap format.
+ *
+ * \param[in] bitmap The bitmap to convert.
+ * \param[in] current_fmt The current bitmap format specifier.
+ */
+static inline void bitmap_format_to_client(
+ void *bitmap,
+ const bitmap_fmt_t *current_fmt)
+{
+ bitmap_fmt_t from = *current_fmt;
+
+ from.layout = bitmap_sanitise_bitmap_layout(from.layout);
+ if (from.layout != bitmap_fmt.layout || from.pma != bitmap_fmt.pma) {
+ bitmap_format_convert(bitmap, &from, &bitmap_fmt);
+ }
+}
+
+/**
+ * Convert a bitmap to the client bitmap format.
+ *
+ * \param[in] bitmap The bitmap to convert.
+ * \param[in] target_fmt The target bitmap format specifier.
+ */
+static inline void bitmap_format_from_client(
+ void *bitmap,
+ const bitmap_fmt_t *target_fmt)
+{
+ bitmap_fmt_t to = *target_fmt;
+
+ to.layout = bitmap_sanitise_bitmap_layout(to.layout);
+ if (to.layout != bitmap_fmt.layout || to.pma != bitmap_fmt.pma) {
+ bitmap_format_convert(bitmap, &bitmap_fmt, &to);
+ }
+}
+
+#endif
diff --git a/desktop/browser.c b/desktop/browser.c
index 88d78ba95..6968bf21b 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -1,11 +1,5 @@
/*
- * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
- * Copyright 2006 James Bursa <bursa@users.sourceforge.net>
- * Copyright 2004 Andrew Timmins <atimmins@blueyonder.co.uk>
- * Copyright 2004 John Tytgat <joty@netsurf-browser.org>
- * Copyright 2006 Richard Wilson <info@tinct.net>
- * Copyright 2008 Michael Drake <tlsa@netsurf-browser.org>
- * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
+ * Copyright 2019 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -25,3353 +19,29 @@
/**
* \file
*
- * Browser window creation and manipulation implementation.
+ * Browser core functionality
*/
-#include "utils/config.h"
-
-#include <assert.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <math.h>
-#include <nsutils/time.h>
-
-#include "utils/corestrings.h"
+#include "utils/errors.h"
#include "utils/log.h"
-#include "utils/messages.h"
-#include "utils/nsurl.h"
#include "utils/utils.h"
-#include "utils/utf8.h"
-#include "utils/nsoption.h"
-#include "netsurf/misc.h"
-#include "netsurf/window.h"
-#include "netsurf/content.h"
-#include "netsurf/plotters.h"
-#include "content/content_debug.h"
-#include "content/fetch.h"
-#include "content/hlcache.h"
-#include "content/urldb.h"
+#include "netsurf/browser.h"
#include "css/utils.h"
-#include "render/form_internal.h"
-#include "render/html.h"
-#include "render/box.h"
-#include "javascript/js.h"
-
-#include "desktop/browser_history.h"
-#include "desktop/browser_private.h"
-#include "desktop/download.h"
-#include "desktop/frames.h"
-#include "desktop/global_history.h"
-#include "desktop/hotlist.h"
-#include "desktop/knockout.h"
-#include "desktop/scrollbar.h"
-#include "desktop/selection.h"
-#include "desktop/theme.h"
-#include "desktop/gui_internal.h"
-#include "desktop/textinput.h"
-
-
-/** maximum frame depth */
-#define FRAME_DEPTH 8
-
-
-/**
- * Get position of scrollbar widget within browser window.
- *
- * \param bw The browser window
- * \param horizontal Whether to get position of horizontal scrollbar
- * \param x Updated to x-coord of top left of scrollbar widget
- * \param y Updated to y-coord of top left of scrollbar widget
- */
-static inline void browser_window_get_scrollbar_pos(struct browser_window *bw,
- bool horizontal, int *x, int *y)
-{
- if (horizontal) {
- *x = 0;
- *y = bw->height - SCROLLBAR_WIDTH;
- } else {
- *x = bw->width - SCROLLBAR_WIDTH;
- *y = 0;
- }
-}
-
-
-/**
- * Get browser window scrollbar widget length
- *
- * \param bw The browser window
- * \param horizontal Whether to get length of horizontal scrollbar
- * \return the scrollbar's length
- */
-static inline int browser_window_get_scrollbar_len(struct browser_window *bw,
- bool horizontal)
-{
- if (horizontal)
- return bw->width - (bw->scroll_y != NULL ? SCROLLBAR_WIDTH : 0);
- else
- return bw->height;
-}
-
-
-/* exported interface, documented in browser.h */
-nserror
-browser_window_get_name(struct browser_window *bw, const char **out_name)
-{
- assert(bw != NULL);
-
- *out_name = bw->name;
-
- return NSERROR_OK;
-}
-
-
-/* exported interface, documented in browser.h */
-nserror
-browser_window_set_name(struct browser_window *bw, const char *name)
-{
- char *nname = NULL;
-
- assert(bw != NULL);
-
- if (name != NULL) {
- nname = strdup(name);
- if (nname == NULL) {
- return NSERROR_NOMEM;
- }
- }
-
- if (bw->name != NULL) {
- free(bw->name);
- }
-
- bw->name = nname;
-
- return NSERROR_OK;
-}
-
-
-/* exported interface, documented in browser.h */
-bool
-browser_window_redraw(struct browser_window *bw,
- int x, int y,
- const struct rect *clip,
- const struct redraw_context *ctx)
-{
- struct redraw_context new_ctx = *ctx;
- int width = 0;
- int height = 0;
- bool plot_ok = true;
- content_type content_type;
- struct content_redraw_data data;
- struct rect content_clip;
- nserror res;
-
- if (bw == NULL) {
- NSLOG(netsurf, INFO, "NULL browser window");
- return false;
- }
-
- if ((bw->current_content == NULL) &&
- (bw->children == NULL)) {
- /* Browser window has no content, render blank fill */
- ctx->plot->clip(ctx, clip);
- return (ctx->plot->rectangle(ctx, plot_style_fill_white, clip) == NSERROR_OK);
- }
-
- /* Browser window has content OR children (frames) */
- if ((bw->window != NULL) &&
- (ctx->plot->option_knockout)) {
- /* Root browser window: start knockout */
- knockout_plot_start(ctx, &new_ctx);
- }
-
- new_ctx.plot->clip(ctx, clip);
-
- /* Handle redraw of any browser window children */
- if (bw->children) {
- struct browser_window *child;
- int cur_child;
- int children = bw->rows * bw->cols;
-
- if (bw->window != NULL) {
- /* Root browser window; start with blank fill */
- plot_ok &= (new_ctx.plot->rectangle(ctx,
- plot_style_fill_white,
- clip) == NSERROR_OK);
- }
-
- /* Loop through all children of bw */
- for (cur_child = 0; cur_child < children; cur_child++) {
- /* Set current child */
- child = &bw->children[cur_child];
-
- /* Get frame edge box in global coordinates */
- content_clip.x0 = (x + child->x) * child->scale;
- content_clip.y0 = (y + child->y) * child->scale;
- content_clip.x1 = content_clip.x0 +
- child->width * child->scale;
- content_clip.y1 = content_clip.y0 +
- child->height * child->scale;
-
- /* Intersect it with clip rectangle */
- if (content_clip.x0 < clip->x0)
- content_clip.x0 = clip->x0;
- if (content_clip.y0 < clip->y0)
- content_clip.y0 = clip->y0;
- if (clip->x1 < content_clip.x1)
- content_clip.x1 = clip->x1;
- if (clip->y1 < content_clip.y1)
- content_clip.y1 = clip->y1;
-
- /* Skip this frame if it lies outside clip rectangle */
- if (content_clip.x0 >= content_clip.x1 ||
- content_clip.y0 >= content_clip.y1)
- continue;
-
- /* Redraw frame */
- plot_ok &= browser_window_redraw(child,
- x + child->x, y + child->y,
- &content_clip, &new_ctx);
- }
-
- /* Nothing else to redraw for browser windows with children;
- * cleanup and return
- */
- if (bw->window != NULL && ctx->plot->option_knockout) {
- /* Root browser window: knockout end */
- knockout_plot_end(ctx);
- }
-
- return plot_ok;
- }
-
- /* Handle browser windows with content to redraw */
-
- content_type = content_get_type(bw->current_content);
- if (content_type != CONTENT_HTML && content_type != CONTENT_TEXTPLAIN) {
- /* Set render area according to scale */
- width = content_get_width(bw->current_content) * bw->scale;
- height = content_get_height(bw->current_content) * bw->scale;
-
- /* Non-HTML may not fill viewport to extents, so plot white
- * background fill */
- plot_ok &= (new_ctx.plot->rectangle(&new_ctx,
- plot_style_fill_white,
- clip) == NSERROR_OK);
- }
-
- /* Set up content redraw data */
- data.x = x - scrollbar_get_offset(bw->scroll_x);
- data.y = y - scrollbar_get_offset(bw->scroll_y);
- data.width = width;
- data.height = height;
-
- data.background_colour = 0xFFFFFF;
- data.scale = bw->scale;
- data.repeat_x = false;
- data.repeat_y = false;
-
- content_clip = *clip;
-
- if (!bw->window) {
- int x0 = x * bw->scale;
- int y0 = y * bw->scale;
- int x1 = (x + bw->width - ((bw->scroll_y != NULL) ?
- SCROLLBAR_WIDTH : 0)) * bw->scale;
- int y1 = (y + bw->height - ((bw->scroll_x != NULL) ?
- SCROLLBAR_WIDTH : 0)) * bw->scale;
-
- if (content_clip.x0 < x0) content_clip.x0 = x0;
- if (content_clip.y0 < y0) content_clip.y0 = y0;
- if (x1 < content_clip.x1) content_clip.x1 = x1;
- if (y1 < content_clip.y1) content_clip.y1 = y1;
- }
-
- /* Render the content */
- plot_ok &= content_redraw(bw->current_content, &data,
- &content_clip, &new_ctx);
-
- /* Back to full clip rect */
- new_ctx.plot->clip(&new_ctx, clip);
-
- if (!bw->window) {
- /* Render scrollbars */
- int off_x, off_y;
- if (bw->scroll_x != NULL) {
- browser_window_get_scrollbar_pos(bw, true,
- &off_x, &off_y);
- res = scrollbar_redraw(bw->scroll_x,
- x + off_x, y + off_y, clip,
- bw->scale, &new_ctx);
- if (res != NSERROR_OK) {
- plot_ok = false;
- }
- }
- if (bw->scroll_y != NULL) {
- browser_window_get_scrollbar_pos(bw, false,
- &off_x, &off_y);
- res = scrollbar_redraw(bw->scroll_y,
- x + off_x, y + off_y, clip,
- bw->scale, &new_ctx);
- if (res != NSERROR_OK) {
- plot_ok = false;
- }
- }
- }
-
- if (bw->window != NULL && ctx->plot->option_knockout) {
- /* Root browser window: end knockout */
- knockout_plot_end(ctx);
- }
-
- return plot_ok;
-}
-
-
-/* exported interface, documented in browser.h */
-bool browser_window_redraw_ready(struct browser_window *bw)
-{
- if (bw == NULL) {
- NSLOG(netsurf, INFO, "NULL browser window");
- return false;
- } else if (bw->current_content != NULL) {
- /* Can't render locked contents */
- return !content_is_locked(bw->current_content);
- }
-
- return true;
-}
-
-
-/* exported interface, documented in browser_private.h */
-void browser_window_update_extent(struct browser_window *bw)
-{
- if (bw->window != NULL)
- /* Front end window */
- guit->window->update_extent(bw->window);
- else
- /* Core-managed browser window */
- browser_window_handle_scrollbars(bw);
-}
-
-
-/* exported interface, documented in browser.h */
-void
-browser_window_get_position(struct browser_window *bw,
- bool root,
- int *pos_x,
- int *pos_y)
-{
- *pos_x = 0;
- *pos_y = 0;
-
- assert(bw != NULL);
-
- while (bw) {
- switch (bw->browser_window_type) {
-
- case BROWSER_WINDOW_FRAMESET:
- *pos_x += bw->x * bw->scale;
- *pos_y += bw->y * bw->scale;
- break;
-
- case BROWSER_WINDOW_NORMAL:
- /* There is no offset to the root browser window */
- break;
-
- case BROWSER_WINDOW_FRAME:
- /* Iframe and Frame handling is identical;
- * fall though */
- case BROWSER_WINDOW_IFRAME:
- *pos_x += (bw->x - scrollbar_get_offset(bw->scroll_x)) *
- bw->scale;
- *pos_y += (bw->y - scrollbar_get_offset(bw->scroll_y)) *
- bw->scale;
- break;
- }
-
- bw = bw->parent;
-
- if (!root) {
- /* return if we just wanted the position in the parent
- * browser window. */
- return;
- }
- }
-}
-
-
-/* exported interface, documented in browser.h */
-void browser_window_set_position(struct browser_window *bw, int x, int y)
-{
- assert(bw != NULL);
-
- if (bw->window == NULL) {
- /* Core managed browser window */
- bw->x = x;
- bw->y = y;
- } else {
- NSLOG(netsurf, INFO,
- "Asked to set position of front end window.");
- assert(0);
- }
-}
-
-/* exported interface, documented in browser.h */
-void
-browser_window_set_drag_type(struct browser_window *bw,
- browser_drag_type type,
- const struct rect *rect)
-{
- struct browser_window *top_bw = browser_window_get_root(bw);
- gui_drag_type gtype;
-
- bw->drag.type = type;
-
- if (type == DRAGGING_NONE) {
- top_bw->drag.window = NULL;
- } else {
- top_bw->drag.window = bw;
-
- switch (type) {
- case DRAGGING_SELECTION:
- /** \todo tell front end */
- return;
- case DRAGGING_SCR_X:
- case DRAGGING_SCR_Y:
- case DRAGGING_CONTENT_SCROLLBAR:
- gtype = GDRAGGING_SCROLLBAR;
- break;
- default:
- gtype = GDRAGGING_OTHER;
- break;
- }
-
- guit->window->drag_start(top_bw->window, gtype, rect);
- }
-}
-
-/* exported interface, documented in browser.h */
-browser_drag_type browser_window_get_drag_type(struct browser_window *bw)
-{
- return bw->drag.type;
-}
-
-/* exported interface, documented in browser.h */
-struct browser_window * browser_window_get_root(struct browser_window *bw)
-{
- while (bw && bw->parent) {
- bw = bw->parent;
- }
- return bw;
-}
-
-/* exported interface, documented in browser.h */
-browser_editor_flags browser_window_get_editor_flags(struct browser_window *bw)
-{
- browser_editor_flags ed_flags = BW_EDITOR_NONE;
- assert(bw->window);
- assert(bw->parent == NULL);
-
- if (bw->selection.bw != NULL) {
- ed_flags |= BW_EDITOR_CAN_COPY;
-
- if (!bw->selection.read_only)
- ed_flags |= BW_EDITOR_CAN_CUT;
- }
-
- if (bw->can_edit)
- ed_flags |= BW_EDITOR_CAN_PASTE;
-
- return ed_flags;
-}
-
-/* exported interface, documented in browser.h */
-bool browser_window_can_select(struct browser_window *bw)
-{
- if (bw == NULL || bw->current_content == NULL)
- return false;
-
- /* TODO: We shouldn't have to know about specific content types
- * here. There should be a content_is_selectable() call. */
- if (content_get_type(bw->current_content) != CONTENT_HTML &&
- content_get_type(bw->current_content) !=
- CONTENT_TEXTPLAIN)
- return false;
-
- return true;
-}
-
-/* exported interface, documented in browser.h */
-char * browser_window_get_selection(struct browser_window *bw)
-{
- assert(bw->window);
- assert(bw->parent == NULL);
-
- if (bw->selection.bw == NULL ||
- bw->selection.bw->current_content == NULL)
- return NULL;
-
- return content_get_selection(bw->selection.bw->current_content);
-}
-
-/* exported interface, documented in netsurf/browser_window.h */
-bool browser_window_can_search(struct browser_window *bw)
-{
- if (bw == NULL || bw->current_content == NULL)
- return false;
-
- /** \todo We shouldn't have to know about specific content
- * types here. There should be a content_is_searchable() call.
- */
- if ((content_get_type(bw->current_content) != CONTENT_HTML) &&
- (content_get_type(bw->current_content) != CONTENT_TEXTPLAIN)) {
- return false;
- }
-
- return true;
-}
-
-
-/* exported interface, documented in netsurf/browser_window.h */
-bool browser_window_is_frameset(struct browser_window *bw)
-{
- return (bw->children != NULL);
-}
-
-
-/* exported interface, documented in netsurf/browser_window.h */
-nserror browser_window_get_scrollbar_type(struct browser_window *bw,
- browser_scrolling *h, browser_scrolling *v)
-{
- *h = bw->scrolling;
- *v = bw->scrolling;
-
- return NSERROR_OK;
-}
-
-/**
- * Set or remove a selection.
- *
- * \param bw browser window with selection
- * \param selection true if bw has a selection, false if removing selection
- * \param read_only true iff selection is read only (e.g. can't cut it)
- */
-static void browser_window_set_selection(struct browser_window *bw,
- bool selection, bool read_only)
-{
- struct browser_window *top;
-
- assert(bw != NULL);
-
- top = browser_window_get_root(bw);
-
- assert(top != NULL);
-
- if (bw != top->selection.bw && top->selection.bw != NULL &&
- top->selection.bw->current_content != NULL) {
- /* clear old selection */
- content_clear_selection(top->selection.bw->current_content);
- }
-
- if (selection) {
- top->selection.bw = bw;
- } else {
- top->selection.bw = NULL;
- }
-
- top->selection.read_only = read_only;
-}
-
-
-/**
- * Set the scroll position of a browser window.
- *
- * scrolls the viewport to ensure the specified rectangle of the
- * content is shown.
- *
- * \param bw window to scroll
- * \param rect The rectangle to ensure is shown.
- * \return NSERROR_OK on success or apropriate error code.
- */
-static nserror
-browser_window_set_scroll(struct browser_window *bw,
- const struct rect *rect)
-{
- if (bw->window != NULL) {
- return guit->window->set_scroll(bw->window, rect);
- }
-
- if (bw->scroll_x != NULL) {
- scrollbar_set(bw->scroll_x, rect->x0, false);
- }
- if (bw->scroll_y != NULL) {
- scrollbar_set(bw->scroll_y, rect->y0, false);
- }
-
- return NSERROR_OK;
-}
-
-/**
- * Internal helper for getting the positional features
- *
- * \param[in] bw browser window to examine.
- * \param[in] x x-coordinate of point of interest
- * \param[in] y y-coordinate of point of interest
- * \param[out] data Feature structure to update.
- * \return NSERROR_OK or appropriate error code on faliure.
- */
-static nserror
-browser_window__get_contextual_content(struct browser_window *bw,
- int x, int y, struct browser_window_features *data)
-{
- nserror ret = NSERROR_OK;
-
- /* Handle (i)frame scroll offset (core-managed browser windows only) */
- x += scrollbar_get_offset(bw->scroll_x);
- y += scrollbar_get_offset(bw->scroll_y);
-
- if (bw->children) {
- /* Browser window has children, so pass request on to
- * appropriate child.
- */
- struct browser_window *bwc;
- int cur_child;
- int children = bw->rows * bw->cols;
-
- /* Loop through all children of bw */
- for (cur_child = 0; cur_child < children; cur_child++) {
- /* Set current child */
- bwc = &bw->children[cur_child];
-
- /* Skip this frame if (x, y) coord lies outside */
- if ((x < bwc->x) ||
- (bwc->x + bwc->width < x) ||
- (y < bwc->y) ||
- (bwc->y + bwc->height < y)) {
- continue;
- }
-
- /* Pass request into this child */
- return browser_window__get_contextual_content(bwc,
- (x - bwc->x), (y - bwc->y), data);
- }
-
- /* Coordinate not contained by any frame */
-
- } else if (bw->current_content != NULL) {
- /* Pass request to content */
- ret = content_get_contextual_content(bw->current_content,
- x, y, data);
- data->main = bw->current_content;
- }
-
- return ret;
-}
-
-/* exported interface, documented in browser.h */
-nserror browser_window_get_features(struct browser_window *bw,
- int x, int y, struct browser_window_features *data)
-{
- /* clear the features structure to empty values */
- data->link = NULL;
- data->object = NULL;
- data->main = NULL;
- data->form_features = CTX_FORM_NONE;
-
- return browser_window__get_contextual_content(bw, x, y, data);
-}
-
-/* exported interface, documented in browser.h */
-bool browser_window_scroll_at_point(struct browser_window *bw,
- int x, int y, int scrx, int scry)
-{
- bool handled_scroll = false;
- assert(bw != NULL);
-
- /* Handle (i)frame scroll offset (core-managed browser windows only) */
- x += scrollbar_get_offset(bw->scroll_x);
- y += scrollbar_get_offset(bw->scroll_y);
-
- if (bw->children) {
- /* Browser window has children, so pass request on to
- * appropriate child */
- struct browser_window *bwc;
- int cur_child;
- int children = bw->rows * bw->cols;
-
- /* Loop through all children of bw */
- for (cur_child = 0; cur_child < children; cur_child++) {
- /* Set current child */
- bwc = &bw->children[cur_child];
-
- /* Skip this frame if (x, y) coord lies outside */
- if (x < bwc->x || bwc->x + bwc->width < x ||
- y < bwc->y || bwc->y + bwc->height < y)
- continue;
-
- /* Pass request into this child */
- return browser_window_scroll_at_point(bwc,
- (x - bwc->x), (y - bwc->y),
- scrx, scry);
- }
- }
-
- /* Try to scroll any current content */
- if (bw->current_content != NULL && content_scroll_at_point(
- bw->current_content, x, y, scrx, scry) == true)
- /* Scroll handled by current content */
- return true;
-
- /* Try to scroll this window, if scroll not already handled */
- if (handled_scroll == false) {
- if (bw->scroll_y && scrollbar_scroll(bw->scroll_y, scry))
- handled_scroll = true;
-
- if (bw->scroll_x && scrollbar_scroll(bw->scroll_x, scrx))
- handled_scroll = true;
- }
-
- return handled_scroll;
-}
-
-/* exported interface, documented in browser.h */
-bool browser_window_drop_file_at_point(struct browser_window *bw,
- int x, int y, char *file)
-{
- assert(bw != NULL);
-
- /* Handle (i)frame scroll offset (core-managed browser windows only) */
- x += scrollbar_get_offset(bw->scroll_x);
- y += scrollbar_get_offset(bw->scroll_y);
-
- if (bw->children) {
- /* Browser window has children, so pass request on to
- * appropriate child */
- struct browser_window *bwc;
- int cur_child;
- int children = bw->rows * bw->cols;
-
- /* Loop through all children of bw */
- for (cur_child = 0; cur_child < children; cur_child++) {
- /* Set current child */
- bwc = &bw->children[cur_child];
-
- /* Skip this frame if (x, y) coord lies outside */
- if (x < bwc->x || bwc->x + bwc->width < x ||
- y < bwc->y || bwc->y + bwc->height < y)
- continue;
-
- /* Pass request into this child */
- return browser_window_drop_file_at_point(bwc,
- (x - bwc->x), (y - bwc->y),
- file);
- }
- }
-
- /* Pass file drop on to any content */
- if (bw->current_content != NULL)
- return content_drop_file_at_point(bw->current_content,
- x, y, file);
-
- return false;
-}
-
-/* exported interface, documented in netsurf/browser_window.h */
-void browser_window_set_gadget_filename(struct browser_window *bw,
- struct form_control *gadget, const char *fn)
-{
- html_set_file_gadget_filename(bw->current_content, gadget, fn);
-}
-
-/* exported interface, documented in browser.h */
-nserror browser_window_debug_dump(struct browser_window *bw,
- FILE *f, enum content_debug op)
-{
- if (bw->current_content != NULL) {
- return content_debug_dump(bw->current_content, f, op);
- }
- return NSERROR_OK;
-}
-
-/* exported interface, documented in browser.h */
-nserror browser_window_debug(struct browser_window *bw, enum content_debug op)
-{
- if (bw->current_content != NULL) {
- return content_debug(bw->current_content, op);
- }
- return NSERROR_OK;
-}
-
-/** slow script handler
-*/
-static bool slow_script(void *ctx)
-{
- static int count = 0;
- NSLOG(netsurf, INFO, "Continuing execution %d", count);
- count++;
- if (count > 1) {
- count = 0;
- return false;
- }
- return true;
-}
-
-/* exported interface, documented in netsurf/browser_window.h */
-nserror browser_window_create(enum browser_window_create_flags flags,
- nsurl *url, nsurl *referrer,
- struct browser_window *existing,
- struct browser_window **bw)
-{
- gui_window_create_flags gw_flags = GW_CREATE_NONE;
- struct browser_window *ret;
- nserror err;
-
- /* Check parameters */
- if (flags & BW_CREATE_CLONE) {
- if (existing == NULL) {
- assert(0 && "Failed: No existing window provided.");
- return NSERROR_BAD_PARAMETER;
- }
- }
- if (!(flags & BW_CREATE_HISTORY)) {
- if (!(flags & BW_CREATE_CLONE) || existing == NULL) {
- assert(0 && "Failed: Must have existing for history.");
- return NSERROR_BAD_PARAMETER;
- }
- }
-
-
- if ((ret = calloc(1, sizeof(struct browser_window))) == NULL) {
- return NSERROR_NOMEM;
- }
-
- /* Initialise common parts */
- err = browser_window_initialise_common(flags, ret, existing);
- if (err != NSERROR_OK) {
- browser_window_destroy(ret);
- return err;
- }
-
- /* window characteristics */
- ret->browser_window_type = BROWSER_WINDOW_NORMAL;
- ret->scrolling = BW_SCROLLING_YES;
- ret->border = true;
- ret->no_resize = true;
- ret->focus = ret;
-
- /* initialise last action with creation time */
- nsu_getmonotonic_ms(&ret->last_action);
-
- /* The existing gui_window is on the top-level existing
- * browser_window. */
- existing = browser_window_get_root(existing);
-
- /* Set up gui_window creation flags */
- if (flags & BW_CREATE_TAB)
- gw_flags |= GW_CREATE_TAB;
- if (flags & BW_CREATE_CLONE)
- gw_flags |= GW_CREATE_CLONE;
-
- ret->window = guit->window->create(ret,
- (existing != NULL) ? existing->window : NULL,
- gw_flags);
-
- if (ret->window == NULL) {
- browser_window_destroy(ret);
- return NSERROR_BAD_PARAMETER;
- }
-
- if (url != NULL) {
- enum browser_window_nav_flags nav_flags = BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE;
- if (flags & BW_CREATE_UNVERIFIABLE)
- nav_flags |= BW_NAVIGATE_UNVERIFIABLE;
- if (flags & BW_CREATE_HISTORY)
- nav_flags |= BW_NAVIGATE_HISTORY;
- browser_window_navigate(ret, url, referrer, nav_flags, NULL,
- NULL, NULL);
- }
-
- if (bw != NULL) {
- *bw = ret;
- }
-
- return NSERROR_OK;
-}
-
-
-/* exported internal interface, documented in desktop/browser_private.h */
-nserror browser_window_initialise_common(enum browser_window_create_flags flags,
- struct browser_window *bw, struct browser_window *existing)
-{
- nserror err;
- assert(bw);
-
- /* new javascript context for each window/(i)frame */
- err = js_newcontext(nsoption_int(script_timeout),
- slow_script, NULL, &bw->jsctx);
- if (err != NSERROR_OK)
- return err;
-
- if (flags & BW_CREATE_CLONE) {
- assert(existing != NULL);
-
- /* clone history */
- err = browser_window_history_clone(existing, bw);
-
- /* copy the scale */
- bw->scale = existing->scale;
- } else {
- /* create history */
- err = browser_window_history_create(bw);
-
- /* default scale */
- bw->scale = (float) nsoption_int(scale) / 100.0;
- }
-
- if (err != NSERROR_OK)
- return err;
-
- /* window characteristics */
- bw->refresh_interval = -1;
-
- bw->drag.type = DRAGGING_NONE;
-
- bw->scroll_x = NULL;
- bw->scroll_y = NULL;
-
- bw->focus = NULL;
-
- /* initialise status text cache */
- bw->status.text = NULL;
- bw->status.text_len = 0;
- bw->status.match = 0;
- bw->status.miss = 0;
-
- return NSERROR_OK;
-}
-
-/**
- * implements the download operation of a window navigate
- */
-static nserror
-browser_window_download(struct browser_window *bw,
- nsurl *url,
- nsurl *nsref,
- uint32_t fetch_flags,
- bool fetch_is_post,
- llcache_post_data *post)
-{
- llcache_handle *l;
- struct browser_window *root;
- nserror error;
-
- root = browser_window_get_root(bw);
- assert(root != NULL);
-
- fetch_flags |= LLCACHE_RETRIEVE_FORCE_FETCH;
- fetch_flags |= LLCACHE_RETRIEVE_STREAM_DATA;
-
- error = llcache_handle_retrieve(url, fetch_flags, nsref,
- fetch_is_post ? post : NULL,
- NULL, NULL, &l);
- if (error == NSERROR_NO_FETCH_HANDLER) {
- /* no internal handler for this type, call out to frontend */
- error = guit->misc->launch_url(url);
- } else if (error != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Failed to fetch download: %d", error);
- } else {
- error = download_context_create(l, root->window);
- if (error != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Failed creating download context: %d", error);
- llcache_handle_abort(l);
- llcache_handle_release(l);
- }
- }
-
- return error;
-}
-
-
-static bool browser_window_check_throbber(struct browser_window *bw)
-{
- int children, index;
-
- if (bw->throbbing)
- return true;
-
- if (bw->children) {
- children = bw->rows * bw->cols;
- for (index = 0; index < children; index++) {
- if (browser_window_check_throbber(&bw->children[index]))
- return true;
- }
- }
- if (bw->iframes) {
- for (index = 0; index < bw->iframe_count; index++) {
- if (browser_window_check_throbber(&bw->iframes[index]))
- return true;
- }
- }
- return false;
-}
-
-
-/**
- * Start the busy indicator.
- *
- * \param bw browser window
- */
-
-static void browser_window_start_throbber(struct browser_window *bw)
-{
- bw->throbbing = true;
-
- while (bw->parent)
- bw = bw->parent;
-
- guit->window->start_throbber(bw->window);
-}
-
-
-/**
- * Stop the busy indicator.
- *
- * \param bw browser window
- */
-static void browser_window_stop_throbber(struct browser_window *bw)
-{
- bw->throbbing = false;
-
- while (bw->parent)
- bw = bw->parent;
-
- if (!browser_window_check_throbber(bw)) {
- guit->window->stop_throbber(bw->window);
- }
-}
-
-
-
-/**
- * Callback for fetchcache() for browser window favicon fetches.
- *
- * \param c content handle of favicon
- * \param event The event to process
- * \param pw a context containing the browser window
- * \return NSERROR_OK on success else appropriate error code.
- */
-static nserror
-browser_window_favicon_callback(hlcache_handle *c,
- const hlcache_event *event,
- void *pw)
-{
- struct browser_window *bw = pw;
-
- switch (event->type) {
- case CONTENT_MSG_DONE:
- if (bw->favicon.current != NULL) {
- content_status status =
- content_get_status(bw->favicon.current);
-
- if ((status == CONTENT_STATUS_READY) ||
- (status == CONTENT_STATUS_DONE))
- content_close(bw->favicon.current);
-
- hlcache_handle_release(bw->favicon.current);
- }
-
- bw->favicon.current = c;
- bw->favicon.loading = NULL;
-
- /* content_get_bitmap on the hlcache_handle should give
- * the favicon bitmap at this point
- */
- guit->window->set_icon(bw->window, c);
- break;
-
- case CONTENT_MSG_ERROR:
- case CONTENT_MSG_ERRORCODE:
-
- /* clean up after ourselves */
- if (c == bw->favicon.loading) {
- bw->favicon.loading = NULL;
- } else if (c == bw->favicon.current) {
- bw->favicon.current = NULL;
- }
-
- hlcache_handle_release(c);
-
- if (bw->favicon.failed == false) {
- nsurl *nsref = NULL;
- nsurl *nsurl;
- nserror error;
-
- bw->favicon.failed = true;
-
- error = nsurl_create("resource:favicon.ico", &nsurl);
- if (error != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Unable to create default location url");
- } else {
- hlcache_handle_retrieve(nsurl,
- HLCACHE_RETRIEVE_SNIFF_TYPE,
- nsref, NULL,
- browser_window_favicon_callback,
- bw, NULL, CONTENT_IMAGE,
- &bw->favicon.loading);
-
- nsurl_unref(nsurl);
- }
-
- }
- break;
-
- default:
- break;
- }
- return NSERROR_OK;
-}
-
-
-/**
- * update the favicon associated with the browser window
- *
- * \param c the page content handle.
- * \param bw A top level browser window.
- * \param link A link context or NULL to attempt fallback scanning.
- */
-static void
-browser_window_update_favicon(hlcache_handle *c,
- struct browser_window *bw,
- struct content_rfc5988_link *link)
-{
- nsurl *nsref = NULL;
- nsurl *nsurl;
- nserror error;
-
- assert(c != NULL);
- assert(bw !=NULL);
-
- if (bw->window == NULL)
- /* Not top-level browser window; not interested */
- return;
-
- /* already fetching the favicon - use that */
- if (bw->favicon.loading != NULL)
- return;
-
- bw->favicon.failed = false;
-
- if (link == NULL) {
- /* Look for "icon" */
- link = content_find_rfc5988_link(c, corestring_lwc_icon);
- }
-
- if (link == NULL) {
- /* Look for "shortcut icon" */
- link = content_find_rfc5988_link(c,
- corestring_lwc_shortcut_icon);
- }
-
- if (link == NULL) {
- lwc_string *scheme;
- bool speculative_default = false;
- bool match;
-
- nsurl = hlcache_handle_get_url(c);
-
- scheme = nsurl_get_component(nsurl, NSURL_SCHEME);
-
- /* If the document was fetched over http(s), then speculate
- * that there's a favicon living at /favicon.ico */
- if ((lwc_string_caseless_isequal(scheme, corestring_lwc_http,
- &match) == lwc_error_ok && match) ||
- (lwc_string_caseless_isequal(scheme, corestring_lwc_https,
- &match) == lwc_error_ok && match)) {
- speculative_default = true;
- }
-
- lwc_string_unref(scheme);
-
- if (speculative_default) {
- /* no favicon via link, try for the default location */
- error = nsurl_join(nsurl, "/favicon.ico", &nsurl);
- } else {
- bw->favicon.failed = true;
- error = nsurl_create("resource:favicon.ico", &nsurl);
- }
- if (error != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Unable to create default location url");
- return;
- }
- } else {
- nsurl = nsurl_ref(link->href);
- }
-
- if (link == NULL) {
- NSLOG(netsurf, INFO, "fetching general favicon from '%s'",
- nsurl_access(nsurl));
- } else {
- NSLOG(netsurf, INFO, "fetching favicon rel:%s '%s'",
- lwc_string_data(link->rel), nsurl_access(nsurl));
- }
-
- hlcache_handle_retrieve(nsurl, HLCACHE_RETRIEVE_SNIFF_TYPE,
- nsref, NULL, browser_window_favicon_callback,
- bw, NULL, CONTENT_IMAGE, &bw->favicon.loading);
-
- nsurl_unref(nsurl);
-}
-
-/**
- * window callback errorcode handling.
- */
-static void
-browser_window_callback_errorcode(hlcache_handle *c,
- struct browser_window *bw,
- nserror code)
-{
- const char* message;
-
- message = messages_get_errorcode(code);
-
- browser_window_set_status(bw, message);
-
- /* Only warn the user about errors in top-level windows */
- if (bw->browser_window_type == BROWSER_WINDOW_NORMAL) {
- guit->misc->warning(message, NULL);
- }
-
- if (c == bw->loading_content) {
- bw->loading_content = NULL;
- } else if (c == bw->current_content) {
- bw->current_content = NULL;
- browser_window_remove_caret(bw, false);
- }
-
- hlcache_handle_release(c);
-
- browser_window_stop_throbber(bw);
-}
-
-
-/**
- * Handle meta http-equiv refresh time elapsing by loading a new page.
- *
- * \param p browser window to refresh with new page
- */
-static void browser_window_refresh(void *p)
-{
- struct browser_window *bw = p;
- nsurl *url;
- nsurl *refresh;
- hlcache_handle *parent = NULL;
- enum browser_window_nav_flags flags = BW_NAVIGATE_UNVERIFIABLE;
-
- assert(bw->current_content != NULL &&
- (content_get_status(bw->current_content) ==
- CONTENT_STATUS_READY ||
- content_get_status(bw->current_content) ==
- CONTENT_STATUS_DONE));
-
- /* Ignore if the refresh URL has gone
- * (may happen if a fetch error occurred) */
- refresh = content_get_refresh_url(bw->current_content);
- if (refresh == NULL)
- return;
-
- /* mark this content as invalid so it gets flushed from the cache */
- content_invalidate_reuse_data(bw->current_content);
-
- url = hlcache_handle_get_url(bw->current_content);
- if ((url == NULL) || (nsurl_compare(url, refresh, NSURL_COMPLETE))) {
- flags |= BW_NAVIGATE_HISTORY;
- }
-
- /* Treat an (almost) immediate refresh in a top-level browser window as
- * if it were an HTTP redirect, and thus make the resulting fetch
- * verifiable.
- *
- * See fetchcache.c for why redirected fetches should be verifiable at
- * all.
- */
- if (bw->refresh_interval <= 100 && bw->parent == NULL) {
- flags &= ~BW_NAVIGATE_UNVERIFIABLE;
- } else {
- parent = bw->current_content;
- }
-
- browser_window_navigate(bw,
- refresh,
- url,
- flags,
- NULL,
- NULL,
- parent);
-
-}
-
-
-/**
- * Transfer the loading_content to a new download window.
- */
-
-static void browser_window_convert_to_download(struct browser_window *bw,
- llcache_handle *stream)
-{
- struct browser_window *root = browser_window_get_root(bw);
- nserror error;
-
- assert(root != NULL);
-
- error = download_context_create(stream, root->window);
- if (error != NSERROR_OK) {
- llcache_handle_abort(stream);
- llcache_handle_release(stream);
- }
-
- /* remove content from browser window */
- hlcache_handle_release(bw->loading_content);
- bw->loading_content = NULL;
-
- browser_window_stop_throbber(bw);
-}
-
-
-/**
- * Browser window content event callback handler.
- */
-static nserror
-browser_window_callback(hlcache_handle *c,
- const hlcache_event *event,
- void *pw)
-{
- struct browser_window *bw = pw;
- nserror res = NSERROR_OK;
- float sx, sy;
-
- switch (event->type) {
- case CONTENT_MSG_DOWNLOAD:
- assert(bw->loading_content == c);
-
- browser_window_convert_to_download(bw, event->data.download);
-
- if (bw->current_content != NULL) {
- browser_window_refresh_url_bar(bw);
- }
- break;
-
- case CONTENT_MSG_LOADING:
- assert(bw->loading_content == c);
-
-#ifdef WITH_THEME_INSTALL
- if (content_get_type(c) == CONTENT_THEME) {
- theme_install_start(c);
- bw->loading_content = NULL;
- browser_window_stop_throbber(bw);
- } else
-#endif
- {
- bw->refresh_interval = -1;
- browser_window_set_status(bw,
- content_get_status_message(c));
- }
- break;
-
- case CONTENT_MSG_READY:
- {
- int width, height;
-
- assert(bw->loading_content == c);
-
- if (bw->current_content != NULL) {
- content_status status =
- content_get_status(bw->current_content);
-
- if (status == CONTENT_STATUS_READY ||
- status == CONTENT_STATUS_DONE)
- content_close(bw->current_content);
-
- hlcache_handle_release(bw->current_content);
- }
-
- bw->current_content = c;
- bw->loading_content = NULL;
-
- /* Format the new content to the correct dimensions */
- browser_window_get_dimensions(bw, &width, &height, true);
- content_reformat(c, false, width, height);
-
- /* history */
- if (bw->history_add && bw->history) {
- nsurl *url = hlcache_handle_get_url(c);
-
- if (urldb_add_url(url)) {
- urldb_set_url_title(url, content_get_title(c));
- urldb_update_url_visit_data(url);
- urldb_set_url_content_type(url,
- content_get_type(c));
-
- /* This is safe as we've just added the URL */
- global_history_add(urldb_get_url(url));
- }
- /** \todo Urldb / Thumbnails / Local history brokenness
- *
- * We add to local history after calling urldb_add_url
- * rather than in the block above. If urldb_add_url
- * fails (as it will for urls like "about:about",
- * "about:config" etc), there would be no local history
- * node, and later calls to history_update will either
- * explode or overwrite the node for the previous URL.
- *
- * We call it after, rather than before urldb_add_url
- * because history_add calls bitmap render, which
- * tries to register the thumbnail with urldb. That
- * thumbnail registration fails if the url doesn't
- * exist in urldb already, and only urldb-registered
- * thumbnails get freed. So if we called history_add
- * before urldb_add_url we would leak thumbnails for
- * all newly visited URLs. With the history_add call
- * after, we only leak the thumbnails when urldb does
- * not add the URL.
- *
- * Also, since browser_window_history_add can create
- * a thumbnail (content_redraw), we need to do it after
- * content_reformat.
- */
- browser_window_history_add(bw, c, bw->frag_id);
- }
-
- browser_window_remove_caret(bw, false);
-
- if (bw->window != NULL) {
- guit->window->new_content(bw->window);
-
- browser_window_refresh_url_bar(bw);
- }
-
- /* new content; set scroll_to_top */
- browser_window_update(bw, true);
- content_open(c, bw, 0, 0);
- browser_window_set_status(bw, content_get_status_message(c));
-
- /* frames */
- if ((content_get_type(c) == CONTENT_HTML) &&
- (html_get_frameset(c) != NULL)) {
- res = browser_window_create_frameset(bw,
- html_get_frameset(c));
- }
- if (content_get_type(c) == CONTENT_HTML &&
- html_get_iframe(c) != NULL)
- browser_window_create_iframes(bw, html_get_iframe(c));
- }
- break;
-
- case CONTENT_MSG_DONE:
- assert(bw->current_content == c);
-
- if (bw->window == NULL) {
- /* Updated browser window's scrollbars.
- * TODO: do this before CONTENT_MSG_DONE */
- browser_window_reformat(bw, true,
- bw->width, bw->height);
- browser_window_handle_scrollbars(bw);
- }
-
- browser_window_update(bw, false);
- browser_window_set_status(bw, content_get_status_message(c));
- browser_window_stop_throbber(bw);
- browser_window_update_favicon(c, bw, NULL);
-
- if (browser_window_history_get_scroll(bw, &sx, &sy) == NSERROR_OK) {
- int scrollx = (int)((float)content_get_width(bw->current_content) * sx);
- int scrolly = (int)((float)content_get_height(bw->current_content) * sy);
- struct rect rect;
- rect.x0 = rect.x1 = scrollx;
- rect.y0 = rect.y1 = scrolly;
- if (browser_window_set_scroll(bw, &rect) != NSERROR_OK) {
- NSLOG(netsurf, WARNING,
- "Unable to set browser scroll offsets to %d by %d",
- scrollx, scrolly);
- }
- }
-
- browser_window_history_update(bw, c);
- hotlist_update_url(hlcache_handle_get_url(c));
-
- if (bw->refresh_interval != -1) {
- guit->misc->schedule(bw->refresh_interval * 10,
- browser_window_refresh, bw);
- }
- break;
-
- case CONTENT_MSG_ERRORCODE:
- browser_window_callback_errorcode(c, bw, event->data.errorcode);
- break;
-
- case CONTENT_MSG_ERROR:
- browser_window_set_status(bw, event->data.error);
-
- /* Only warn the user about errors in top-level windows */
- if (bw->browser_window_type == BROWSER_WINDOW_NORMAL) {
- guit->misc->warning(event->data.error, NULL);
- }
-
- if (c == bw->loading_content)
- bw->loading_content = NULL;
- else if (c == bw->current_content) {
- bw->current_content = NULL;
- browser_window_remove_caret(bw, false);
- }
-
- hlcache_handle_release(c);
-
- browser_window_stop_throbber(bw);
- break;
-
- case CONTENT_MSG_REDIRECT:
- if (urldb_add_url(event->data.redirect.from))
- urldb_update_url_visit_data(event->data.redirect.from);
- break;
-
- case CONTENT_MSG_STATUS:
- if (event->data.explicit_status_text == NULL) {
- /* Object content's status text updated */
- const char *status = NULL;
- if (bw->loading_content != NULL)
- /* Give preference to any loading content */
- status = content_get_status_message(
- bw->loading_content);
-
- if (status == NULL)
- status = content_get_status_message(c);
-
- if (status != NULL)
- browser_window_set_status(bw, status);
- } else {
- /* Object content wants to set explicit message */
- browser_window_set_status(bw,
- event->data.explicit_status_text);
- }
- break;
-
- case CONTENT_MSG_REFORMAT:
- if (c == bw->current_content &&
- content_get_type(c) == CONTENT_HTML) {
- /* reposition frames */
- if (html_get_frameset(c) != NULL)
- browser_window_recalculate_frameset(bw);
- /* reflow iframe positions */
- if (html_get_iframe(c) != NULL)
- browser_window_recalculate_iframes(bw);
- }
-
- /* Hide any caret, but don't remove it */
- browser_window_remove_caret(bw, true);
-
- if (!(event->data.background)) {
- /* Reformatted content should be redrawn */
- browser_window_update(bw, false);
- }
- break;
-
- case CONTENT_MSG_REDRAW:
- {
- struct rect rect = {
- .x0 = event->data.redraw.x,
- .y0 = event->data.redraw.y,
- .x1 = event->data.redraw.x + event->data.redraw.width,
- .y1 = event->data.redraw.y + event->data.redraw.height
- };
-
- browser_window_update_box(bw, &rect);
- }
- break;
-
- case CONTENT_MSG_REFRESH:
- bw->refresh_interval = event->data.delay * 100;
- break;
-
- case CONTENT_MSG_LINK: /* content has an rfc5988 link element */
- {
- bool match;
-
- /* Handle "icon" and "shortcut icon" */
- if ((lwc_string_caseless_isequal(
- event->data.rfc5988_link->rel,
- corestring_lwc_icon,
- &match) == lwc_error_ok && match) ||
- (lwc_string_caseless_isequal(
- event->data.rfc5988_link->rel,
- corestring_lwc_shortcut_icon,
- &match) == lwc_error_ok && match)) {
- /* it's a favicon perhaps start a fetch for it */
- browser_window_update_favicon(c, bw,
- event->data.rfc5988_link);
- }
- }
- break;
-
- case CONTENT_MSG_GETCTX:
- /* only the content object created by the browser
- * window requires a new global compartment object
- */
- assert(bw->loading_content == c);
- if (js_newcompartment(bw->jsctx,
- bw,
- hlcache_handle_get_content(c)) != NULL) {
- *(event->data.jscontext) = bw->jsctx;
- }
- break;
-
- case CONTENT_MSG_SCROLL:
- {
- struct rect rect = {
- .x0 = event->data.scroll.x0,
- .y0 = event->data.scroll.y0,
- };
-
- /* Content wants to be scrolled */
- if (bw->current_content != c) {
- break;
- }
-
- if (event->data.scroll.area) {
- rect.x1 = event->data.scroll.x1;
- rect.y1 = event->data.scroll.y1;
- } else {
- rect.x1 = event->data.scroll.x0;
- rect.y1 = event->data.scroll.y0;
- }
- browser_window_set_scroll(bw, &rect);
-
- break;
- }
-
- case CONTENT_MSG_DRAGSAVE:
- {
- /* Content wants drag save of a content */
- struct browser_window *root = browser_window_get_root(bw);
- hlcache_handle *save = event->data.dragsave.content;
-
- if (save == NULL) {
- save = c;
- }
-
- switch(event->data.dragsave.type) {
- case CONTENT_SAVE_ORIG:
- guit->window->drag_save_object(root->window, save,
- GUI_SAVE_OBJECT_ORIG);
- break;
-
- case CONTENT_SAVE_NATIVE:
- guit->window->drag_save_object(root->window, save,
- GUI_SAVE_OBJECT_NATIVE);
- break;
-
- case CONTENT_SAVE_COMPLETE:
- guit->window->drag_save_object(root->window, save,
- GUI_SAVE_COMPLETE);
- break;
-
- case CONTENT_SAVE_SOURCE:
- guit->window->drag_save_object(root->window, save,
- GUI_SAVE_SOURCE);
- break;
- }
- }
- break;
-
- case CONTENT_MSG_SAVELINK:
- {
- /* Content wants a link to be saved */
- struct browser_window *root = browser_window_get_root(bw);
- guit->window->save_link(root->window,
- event->data.savelink.url,
- event->data.savelink.title);
- }
- break;
-
- case CONTENT_MSG_POINTER:
- /* Content wants to have specific mouse pointer */
- browser_window_set_pointer(bw, event->data.pointer);
- break;
-
- case CONTENT_MSG_DRAG:
- {
- browser_drag_type bdt = DRAGGING_NONE;
-
- switch (event->data.drag.type) {
- case CONTENT_DRAG_NONE:
- bdt = DRAGGING_NONE;
- break;
- case CONTENT_DRAG_SCROLL:
- bdt = DRAGGING_CONTENT_SCROLLBAR;
- break;
- case CONTENT_DRAG_SELECTION:
- bdt = DRAGGING_SELECTION;
- break;
- }
- browser_window_set_drag_type(bw, bdt, event->data.drag.rect);
- }
- break;
-
- case CONTENT_MSG_CARET:
- switch (event->data.caret.type) {
- case CONTENT_CARET_REMOVE:
- browser_window_remove_caret(bw, false);
- break;
- case CONTENT_CARET_HIDE:
- browser_window_remove_caret(bw, true);
- break;
- case CONTENT_CARET_SET_POS:
- browser_window_place_caret(bw,
- event->data.caret.pos.x,
- event->data.caret.pos.y,
- event->data.caret.pos.height,
- event->data.caret.pos.clip);
- break;
- }
- break;
-
- case CONTENT_MSG_SELECTION:
- browser_window_set_selection(bw,
- event->data.selection.selection,
- event->data.selection.read_only);
- break;
-
- case CONTENT_MSG_SELECTMENU:
- if (event->data.select_menu.gadget->type == GADGET_SELECT) {
- struct browser_window *root =
- browser_window_get_root(bw);
- guit->window->create_form_select_menu(root->window,
- event->data.select_menu.gadget);
- }
-
- break;
-
- case CONTENT_MSG_GADGETCLICK:
- if (event->data.gadget_click.gadget->type == GADGET_FILE) {
- struct browser_window *root =
- browser_window_get_root(bw);
- guit->window->file_gadget_open(root->window, c,
- event->data.gadget_click.gadget);
- }
-
- break;
-
- default:
- break;
- }
- return res;
-}
-
-
-/* Have to forward declare browser_window_destroy_internal */
-static void browser_window_destroy_internal(struct browser_window *bw);
-
-/**
- * Close and destroy all child browser window.
- *
- * \param bw browser window
- */
-static void browser_window_destroy_children(struct browser_window *bw)
-{
- int i;
-
- if (bw->children) {
- for (i = 0; i < (bw->rows * bw->cols); i++)
- browser_window_destroy_internal(&bw->children[i]);
- free(bw->children);
- bw->children = NULL;
- bw->rows = 0;
- bw->cols = 0;
- }
- if (bw->iframes) {
- for (i = 0; i < bw->iframe_count; i++)
- browser_window_destroy_internal(&bw->iframes[i]);
- free(bw->iframes);
- bw->iframes = NULL;
- bw->iframe_count = 0;
- }
-}
-
-
-/**
- * internal scheduled reformat callback.
- *
- * scheduled reformat callback to allow reformats from unthreaded context.
- *
- * \param vbw The browser window to be reformatted
- */
-static void scheduled_reformat(void *vbw)
-{
- struct browser_window *bw = vbw;
- int width;
- int height;
- nserror res;
-
- res = guit->window->get_dimensions(bw->window, &width, &height, false);
- if (res == NSERROR_OK) {
- browser_window_reformat(bw, false, width, height);
- }
-}
-
-
-/**
- * Release all memory associated with a browser window.
- *
- * \param bw browser window
- */
-static void browser_window_destroy_internal(struct browser_window *bw)
-{
- assert(bw);
-
- NSLOG(netsurf, INFO, "Destroying window");
-
- if (bw->children != NULL || bw->iframes != NULL) {
- browser_window_destroy_children(bw);
- }
-
- /* Destroy scrollbars */
- if (bw->scroll_x != NULL) {
- scrollbar_destroy(bw->scroll_x);
- }
-
- if (bw->scroll_y != NULL) {
- scrollbar_destroy(bw->scroll_y);
- }
-
- /* clear any pending callbacks */
- guit->misc->schedule(-1, browser_window_refresh, bw);
- /* The ugly cast here is so the reformat function can be
- * passed a gui window pointer in its API rather than void*
- */
- NSLOG(netsurf, INFO,
- "Clearing reformat schedule for browser window %p", bw);
- guit->misc->schedule(-1, scheduled_reformat, bw);
-
- /* If this brower window is not the root window, and has focus, unset
- * the root browser window's focus pointer. */
- if (!bw->window) {
- struct browser_window *top = browser_window_get_root(bw);
-
- if (top->focus == bw)
- top->focus = top;
-
- if (top->selection.bw == bw) {
- browser_window_set_selection(top, false, false);
- }
- }
-
- /* Destruction order is important: we must ensure that the frontend
- * destroys any window(s) associated with this browser window before
- * we attempt any destructive cleanup.
- */
-
- if (bw->window) {
- /* Only the root window has a GUI window */
- guit->window->destroy(bw->window);
- }
-
- if (bw->loading_content != NULL) {
- hlcache_handle_abort(bw->loading_content);
- hlcache_handle_release(bw->loading_content);
- bw->loading_content = NULL;
- }
-
- if (bw->current_content != NULL) {
- content_status status = content_get_status(bw->current_content);
- if (status == CONTENT_STATUS_READY ||
- status == CONTENT_STATUS_DONE)
- content_close(bw->current_content);
-
- hlcache_handle_release(bw->current_content);
- bw->current_content = NULL;
- }
-
- if (bw->favicon.loading != NULL) {
- hlcache_handle_abort(bw->favicon.loading);
- hlcache_handle_release(bw->favicon.loading);
- bw->favicon.loading = NULL;
- }
-
- if (bw->favicon.current != NULL) {
- content_status status = content_get_status(bw->favicon.current);
-
- if (status == CONTENT_STATUS_READY ||
- status == CONTENT_STATUS_DONE) {
- content_close(bw->favicon.current);
- }
-
- hlcache_handle_release(bw->favicon.current);
- bw->favicon.current = NULL;
- }
-
- if (bw->box != NULL) {
- bw->box->iframe = NULL;
- bw->box = NULL;
- }
-
- if (bw->jsctx != NULL) {
- js_destroycontext(bw->jsctx);
- }
-
- /* These simply free memory, so are safe here */
-
- if (bw->frag_id != NULL) {
- lwc_string_unref(bw->frag_id);
- }
-
- browser_window_history_destroy(bw);
-
- free(bw->name);
- free(bw->status.text);
- bw->status.text = NULL;
- NSLOG(netsurf, INFO, "Status text cache match:miss %d:%d",
- bw->status.match, bw->status.miss);
-}
-
-/**
- * Update URL bar for a given browser window to given URL
- *
- * \param bw Browser window to update URL bar for.
- * \param url URL for content displayed by bw including any fragment.
- */
-static inline nserror
-browser_window_refresh_url_bar_internal(struct browser_window *bw, nsurl *url)
-{
- assert(bw);
- assert(url);
-
- if ((bw->parent != NULL) || (bw->window == NULL)) {
- /* Not root window or no gui window so do not set a URL */
- return NSERROR_OK;
- }
-
- return guit->window->set_url(bw->window, url);
-}
-
-
-/* exported interface, documented in netsurf/browser_window.h */
-void browser_window_destroy(struct browser_window *bw)
-{
- /* can't destoy child windows on their own */
- assert(!bw->parent);
-
- /* destroy */
- browser_window_destroy_internal(bw);
- free(bw);
-}
-
-/* exported interface, documented in netsurf/browser_window.h */
-nserror browser_window_refresh_url_bar(struct browser_window *bw)
-{
- nserror ret;
- nsurl *display_url;
-
- assert(bw);
-
- if (bw->parent != NULL) {
- /* Not root window; don't set a URL in GUI URL bar */
- return NSERROR_OK;
- }
-
- if (bw->current_content == NULL) {
- /* no content so return about:blank */
- ret = browser_window_refresh_url_bar_internal(bw,
- corestring_nsurl_about_blank);
- } else if (bw->frag_id == NULL) {
- ret = browser_window_refresh_url_bar_internal(bw,
- hlcache_handle_get_url(bw->current_content));
- } else {
- /* Combine URL and Fragment */
- ret = nsurl_refragment(
- hlcache_handle_get_url(bw->current_content),
- bw->frag_id, &display_url);
- if (ret == NSERROR_OK) {
- ret = browser_window_refresh_url_bar_internal(bw,
- display_url);
- nsurl_unref(display_url);
- }
- }
-
- return ret;
-}
-
-
-/* exported interface documented in netsurf/browser_window.h */
-nserror
-browser_window_navigate(struct browser_window *bw,
- nsurl *url,
- nsurl *referrer,
- enum browser_window_nav_flags flags,
- char *post_urlenc,
- struct fetch_multipart_data *post_multipart,
- hlcache_handle *parent)
-{
- hlcache_handle *c;
- int depth = 0;
- struct browser_window *cur;
- uint32_t fetch_flags = 0;
- bool fetch_is_post = (post_urlenc != NULL || post_multipart != NULL);
- llcache_post_data post;
- hlcache_child_context child;
- nserror error;
-
- assert(bw);
- assert(url);
-
- NSLOG(netsurf, INFO, "bw %p, url %s", bw, nsurl_access(url));
-
- /* If we're navigating and we have a history entry and a content
- * then update the history entry before we navigate to save our
- * current state. However since history navigation pre-moves
- * the history state, we ensure that we only do this if we've not
- * been suppressed. In the suppressed case, the history code
- * updates the history itself before navigating.
- */
- if (bw->current_content != NULL &&
- bw->history != NULL &&
- bw->history->current != NULL &&
- !(flags & BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE)) {
- browser_window_history_update(bw, bw->current_content);
- }
-
- /* don't allow massively nested framesets */
- for (cur = bw; cur->parent; cur = cur->parent) {
- depth++;
- }
- if (depth > FRAME_DEPTH) {
- NSLOG(netsurf, INFO, "frame depth too high.");
- return NSERROR_FRAME_DEPTH;
- }
-
- /* Set up retrieval parameters */
- if (!(flags & BW_NAVIGATE_UNVERIFIABLE)) {
- fetch_flags |= LLCACHE_RETRIEVE_VERIFIABLE;
- }
-
- if (post_multipart != NULL) {
- post.type = LLCACHE_POST_MULTIPART;
- post.data.multipart = post_multipart;
- } else if (post_urlenc != NULL) {
- post.type = LLCACHE_POST_URL_ENCODED;
- post.data.urlenc = post_urlenc;
- }
-
- child.charset = content_get_encoding(parent, CONTENT_ENCODING_NORMAL);
- if ((parent != NULL) && (content_get_type(parent) == CONTENT_HTML)) {
- child.quirks = content_get_quirks(parent);
- }
-
- url = nsurl_ref(url);
-
- if (referrer != NULL) {
- referrer = nsurl_ref(referrer);
- }
-
- /* Get download out of the way */
- if ((flags & BW_NAVIGATE_DOWNLOAD) != 0) {
- error = browser_window_download(bw,
- url,
- referrer,
- fetch_flags,
- fetch_is_post,
- &post);
- nsurl_unref(url);
- if (referrer != NULL) {
- nsurl_unref(referrer);
- }
- return error;
- }
-
- if (bw->frag_id != NULL) {
- lwc_string_unref(bw->frag_id);
- }
- bw->frag_id = NULL;
-
- if (nsurl_has_component(url, NSURL_FRAGMENT)) {
- bool same_url = false;
-
- bw->frag_id = nsurl_get_component(url, NSURL_FRAGMENT);
-
- /* Compare new URL with existing one (ignoring fragments) */
- if ((bw->current_content != NULL) &&
- (hlcache_handle_get_url(bw->current_content) != NULL)) {
- same_url = nsurl_compare(url,
- hlcache_handle_get_url(
- bw->current_content),
- NSURL_COMPLETE);
- }
-
- /* if we're simply moving to another ID on the same page,
- * don't bother to fetch, just update the window.
- */
- if ((same_url) &&
- (fetch_is_post == false) &&
- (nsurl_has_component(url, NSURL_QUERY) == false)) {
- nsurl_unref(url);
-
- if (referrer != NULL) {
- nsurl_unref(referrer);
- }
-
- if ((flags & BW_NAVIGATE_HISTORY) != 0) {
- browser_window_history_add(bw,
- bw->current_content, bw->frag_id);
- }
-
- browser_window_update(bw, false);
-
- if (bw->current_content != NULL) {
- browser_window_refresh_url_bar(bw);
- }
- return NSERROR_OK;
- }
- }
-
- browser_window_stop(bw);
- browser_window_remove_caret(bw, false);
- browser_window_destroy_children(bw);
-
- NSLOG(netsurf, INFO, "Loading '%s'", nsurl_access(url));
-
- browser_window_set_status(bw, messages_get("Loading"));
- bw->history_add = (flags & BW_NAVIGATE_HISTORY);
-
- /* Verifiable fetches may trigger a download */
- if (!(flags & BW_NAVIGATE_UNVERIFIABLE)) {
- fetch_flags |= HLCACHE_RETRIEVE_MAY_DOWNLOAD;
- }
-
- error = hlcache_handle_retrieve(url,
- fetch_flags | HLCACHE_RETRIEVE_SNIFF_TYPE,
- referrer,
- fetch_is_post ? &post : NULL,
- browser_window_callback, bw,
- parent != NULL ? &child : NULL,
- CONTENT_ANY, &c);
-
- switch (error) {
- case NSERROR_OK:
- bw->loading_content = c;
- browser_window_start_throbber(bw);
- error = browser_window_refresh_url_bar_internal(bw, url);
- break;
-
- case NSERROR_NO_FETCH_HANDLER: /* no handler for this type */
- /** \todo does this always try and download even
- * unverifiable content?
- */
- error = guit->misc->launch_url(url);
- break;
-
- default: /* report error to user */
- browser_window_set_status(bw, messages_get_errorcode(error));
- /** @todo should the caller report the error? */
- guit->misc->warning(messages_get_errorcode(error), NULL);
- break;
-
- }
-
- nsurl_unref(url);
- if (referrer != NULL) {
- nsurl_unref(referrer);
- }
-
- /* Record time */
- nsu_getmonotonic_ms(&bw->last_action);
-
- return error;
-}
-
-
-/* Exported interface, documented in browser.h */
-bool browser_window_up_available(struct browser_window *bw)
-{
- bool result = false;
-
- if (bw != NULL && bw->current_content != NULL) {
- nsurl *parent;
- nserror err = nsurl_parent(hlcache_handle_get_url(
- bw->current_content), &parent);
- if (err == NSERROR_OK) {
- result = nsurl_compare(hlcache_handle_get_url(
- bw->current_content), parent,
- NSURL_COMPLETE) == false;
- nsurl_unref(parent);
- }
- }
-
- return result;
-}
-
-
-/* Exported interface, documented in browser.h */
-nserror browser_window_navigate_up(struct browser_window *bw, bool new_window)
-{
- nsurl *current, *parent;
- nserror err;
-
- if (bw == NULL)
- return NSERROR_BAD_PARAMETER;
-
- current = browser_window_get_url(bw);
-
- err = nsurl_parent(current, &parent);
- if (err != NSERROR_OK) {
- return err;
- }
-
- if (nsurl_compare(current, parent, NSURL_COMPLETE) == true) {
- /* Can't go up to parent from here */
- nsurl_unref(parent);
- return NSERROR_OK;
- }
-
- if (new_window) {
- err = browser_window_create(BW_CREATE_CLONE,
- parent, NULL, bw, NULL);
- } else {
- err = browser_window_navigate(bw, parent, NULL,
- BW_NAVIGATE_HISTORY, NULL, NULL, NULL);
- }
-
- nsurl_unref(parent);
- return err;
-}
-
-
-/* Exported interface, documented in browser.h */
-nsurl* browser_window_get_url(struct browser_window *bw)
-{
- assert(bw != NULL);
-
- if (bw->current_content != NULL) {
- return hlcache_handle_get_url(bw->current_content);
-
- } else if (bw->loading_content != NULL) {
- /* TODO: should we return this? */
- return hlcache_handle_get_url(bw->loading_content);
- }
-
- return corestring_nsurl_about_blank;
-}
-
-/* Exported interface, documented in browser.h */
-const char* browser_window_get_title(struct browser_window *bw)
-{
- assert(bw != NULL);
-
- if (bw->current_content != NULL) {
- return content_get_title(bw->current_content);
- }
-
- /* no content so return about:blank */
- return nsurl_access(corestring_nsurl_about_blank);
-}
-
-/* Exported interface, documented in browser.h */
-struct history * browser_window_get_history(struct browser_window *bw)
-{
- assert(bw != NULL);
-
- return bw->history;
-}
-
-
-/* Exported interface, documented in browser.h */
-bool browser_window_has_content(struct browser_window *bw)
-{
- assert(bw != NULL);
-
- if (bw->current_content == NULL) {
- return false;
- }
-
- return true;
-}
-
-/* Exported interface, documented in browser.h */
-struct hlcache_handle *browser_window_get_content(struct browser_window *bw)
-{
- return bw->current_content;
-}
-
-/* Exported interface, documented in browser.h */
-nserror browser_window_get_extents(struct browser_window *bw, bool scaled,
- int *width, int *height)
-{
- assert(bw != NULL);
-
- if (bw->current_content == NULL) {
- *width = 0;
- *height = 0;
- return NSERROR_BAD_CONTENT;
- }
-
- *width = content_get_width(bw->current_content);
- *height = content_get_height(bw->current_content);
-
- if (scaled) {
- *width *= bw->scale;
- *height *= bw->scale;
- }
-
- return NSERROR_OK;
-}
-
-
-/* exported internal interface, documented in desktop/browser_private.h */
-void browser_window_get_dimensions(struct browser_window *bw,
- int *width, int *height, bool scaled)
-{
- assert(bw);
-
- if (bw->window == NULL) {
- /* Core managed browser window */
- *width = bw->width;
- *height = bw->height;
- } else {
- /* Front end window */
- guit->window->get_dimensions(bw->window, width, height, scaled);
- }
-}
-
-
-/* Exported interface, documented in browser.h */
-void browser_window_set_dimensions(struct browser_window *bw,
- int width, int height)
-{
- assert(bw);
-
- if (bw->window == NULL) {
- /* Core managed browser window */
- bw->width = width;
- bw->height = height;
- } else {
- NSLOG(netsurf, INFO,
- "Asked to set dimensions of front end window.");
- assert(0);
- }
-}
-
-
-/**
- * scroll to a fragment if present
- *
- * \param bw browser window
- * \return true if the scroll was sucessful
- */
-static bool frag_scroll(struct browser_window *bw)
-{
- struct rect rect;
-
- if (bw->frag_id == NULL) {
- return false;
- }
-
- if (!html_get_id_offset(bw->current_content,
- bw->frag_id,
- &rect.x0,
- &rect.y0)) {
- return false;
- }
-
- rect.x1 = rect.x0;
- rect.y1 = rect.y0;
- if (browser_window_set_scroll(bw, &rect) == NSERROR_OK) {
- if (bw->current_content != NULL &&
- bw->history != NULL &&
- bw->history->current != NULL) {
- browser_window_history_update(bw, bw->current_content);
- }
- return true;
- }
- return false;
-}
-
-/* Exported interface, documented in browser.h */
-void browser_window_update(struct browser_window *bw, bool scroll_to_top)
-{
- static const struct rect zrect = {
- .x0 = 0,
- .y0 = 0,
- .x1 = 0,
- .y1 = 0
- };
-
- if (bw->current_content == NULL) {
- return;
- }
-
- switch (bw->browser_window_type) {
-
- case BROWSER_WINDOW_NORMAL:
- /* Root browser window, constituting a front end window/tab */
- guit->window->set_title(bw->window,
- content_get_title(bw->current_content));
-
- browser_window_update_extent(bw);
-
- /* if frag_id exists, then try to scroll to it */
- /** @todo don't do this if the user has scrolled */
- if (!frag_scroll(bw)) {
- if (scroll_to_top) {
- browser_window_set_scroll(bw, &zrect);
- }
- }
-
- guit->window->invalidate(bw->window, NULL);
-
- break;
-
- case BROWSER_WINDOW_IFRAME:
- /* Internal iframe browser window */
- assert(bw->parent != NULL);
- assert(bw->parent->current_content != NULL);
-
- browser_window_update_extent(bw);
-
- if (scroll_to_top) {
- browser_window_set_scroll(bw, &zrect);
- }
-
- /* if frag_id exists, then try to scroll to it */
- /** @todo don't do this if the user has scrolled */
- frag_scroll(bw);
-
- html_redraw_a_box(bw->parent->current_content, bw->box);
- break;
-
- case BROWSER_WINDOW_FRAME:
- {
- struct rect rect;
- browser_window_update_extent(bw);
-
- if (scroll_to_top) {
- browser_window_set_scroll(bw, &zrect);
- }
-
- /* if frag_id exists, then try to scroll to it */
- /** @todo don't do this if the user has scrolled */
- frag_scroll(bw);
-
- rect.x0 = scrollbar_get_offset(bw->scroll_x);
- rect.y0 = scrollbar_get_offset(bw->scroll_y);
- rect.x1 = rect.x0 + bw->width;
- rect.y1 = rect.y0 + bw->height;
-
- browser_window_update_box(bw, &rect);
- }
- break;
-
- default:
- case BROWSER_WINDOW_FRAMESET:
- /* Nothing to do */
- break;
- }
-}
-
-/* Exported interface, documented in netsurf/browser_window.h */
-void browser_window_update_box(struct browser_window *bw, struct rect *rect)
-{
- int pos_x;
- int pos_y;
- struct browser_window *top;
-
- assert(bw);
-
- if (bw->window != NULL) {
- /* Front end window */
- guit->window->invalidate(bw->window, rect);
- } else {
- /* Core managed browser window */
- browser_window_get_position(bw, true, &pos_x, &pos_y);
-
- top = browser_window_get_root(bw);
-
- rect->x0 += pos_x / bw->scale;
- rect->y0 += pos_y / bw->scale;
- rect->x1 += pos_x / bw->scale;
- rect->y1 += pos_y / bw->scale;
-
- guit->window->invalidate(top->window, rect);
- }
-}
-
-/* Exported interface, documented in netsurf/browser_window.h */
-void browser_window_stop(struct browser_window *bw)
-{
- int children, index;
-
- if (bw->loading_content != NULL) {
- hlcache_handle_abort(bw->loading_content);
- hlcache_handle_release(bw->loading_content);
- bw->loading_content = NULL;
- }
-
- if (bw->current_content != NULL && content_get_status(
- bw->current_content) != CONTENT_STATUS_DONE) {
- nserror error;
- assert(content_get_status(bw->current_content) ==
- CONTENT_STATUS_READY);
- error = hlcache_handle_abort(bw->current_content);
- assert(error == NSERROR_OK);
- }
-
- guit->misc->schedule(-1, browser_window_refresh, bw);
-
- if (bw->children) {
- children = bw->rows * bw->cols;
- for (index = 0; index < children; index++)
- browser_window_stop(&bw->children[index]);
- }
- if (bw->iframes) {
- children = bw->iframe_count;
- for (index = 0; index < children; index++)
- browser_window_stop(&bw->iframes[index]);
- }
-
- if (bw->current_content != NULL) {
- browser_window_refresh_url_bar(bw);
- }
-
- browser_window_stop_throbber(bw);
-}
-
-
-/* Exported interface, documented in netsurf/browser_window.h */
-void browser_window_reload(struct browser_window *bw, bool all)
-{
- hlcache_handle *c;
- unsigned int i;
-
- if (bw->current_content == NULL || bw->loading_content != NULL)
- return;
-
- if (all && content_get_type(bw->current_content) == CONTENT_HTML) {
- struct html_stylesheet *sheets;
- struct content_html_object *object;
- unsigned int count;
-
- c = bw->current_content;
-
- /* invalidate objects */
- object = html_get_objects(c, &count);
-
- for (; object != NULL; object = object->next) {
- if (object->content != NULL)
- content_invalidate_reuse_data(object->content);
- }
-
- /* invalidate stylesheets */
- sheets = html_get_stylesheets(c, &count);
-
- for (i = STYLESHEET_START; i != count; i++) {
- if (sheets[i].sheet != NULL) {
- content_invalidate_reuse_data(sheets[i].sheet);
- }
- }
- }
-
- content_invalidate_reuse_data(bw->current_content);
-
- browser_window_navigate(bw,
- hlcache_handle_get_url(bw->current_content),
- NULL,
- BW_NAVIGATE_NONE,
- NULL,
- NULL,
- NULL);
-}
-
-
-/* Exported interface, documented in netsurf/browser_window.h */
-void browser_window_set_status(struct browser_window *bw, const char *text)
-{
- int text_len;
- /* find topmost window */
- while (bw->parent)
- bw = bw->parent;
-
- if ((bw->status.text != NULL) &&
- (strcmp(text, bw->status.text) == 0)) {
- /* status text is unchanged */
- bw->status.match++;
- return;
- }
-
- /* status text is changed */
-
- text_len = strlen(text);
-
- if ((bw->status.text == NULL) || (bw->status.text_len < text_len)) {
- /* no current string allocation or it is not long enough */
- free(bw->status.text);
- bw->status.text = strdup(text);
- bw->status.text_len = text_len;
- } else {
- /* current allocation has enough space */
- memcpy(bw->status.text, text, text_len + 1);
- }
-
- bw->status.miss++;
- guit->window->set_status(bw->window, bw->status.text);
-}
-
-
-/* Exported interface, documented in netsurf/browser_window.h */
-void browser_window_set_pointer(struct browser_window *bw,
- browser_pointer_shape shape)
-{
- struct browser_window *root = browser_window_get_root(bw);
- gui_pointer_shape gui_shape;
- bool loading;
- uint64_t ms_now;
-
- assert(root);
- assert(root->window);
-
- loading = ((bw->loading_content != NULL) ||
- ((bw->current_content != NULL) &&
- (content_get_status(bw->current_content) == CONTENT_STATUS_READY)));
-
- nsu_getmonotonic_ms(&ms_now);
-
- if (loading && ((ms_now - bw->last_action) < 1000)) {
- /* If loading and less than 1 second since last link followed,
- * force progress indicator pointer */
- gui_shape = GUI_POINTER_PROGRESS;
-
- } else if (shape == BROWSER_POINTER_AUTO) {
- /* Up to browser window to decide */
- if (loading) {
- gui_shape = GUI_POINTER_PROGRESS;
- } else {
- gui_shape = GUI_POINTER_DEFAULT;
- }
-
- } else {
- /* Use what we were told */
- gui_shape = (gui_pointer_shape)shape;
- }
-
- guit->window->set_pointer(root->window, gui_shape);
-}
-
-
-/* exported function documented in netsurf/browser_window.h */
-nserror browser_window_schedule_reformat(struct browser_window *bw)
-{
- if (bw->window == NULL) {
- return NSERROR_BAD_PARAMETER;
- }
-
- guit->misc->schedule(0, scheduled_reformat, bw);
-
- return NSERROR_OK;
-}
-
-
-/* exported function documented in netsurf/browser_window.h */
-void browser_window_reformat(struct browser_window *bw, bool background,
- int width, int height)
-{
- hlcache_handle *c = bw->current_content;
-
- if (c == NULL)
- return;
-
- if (bw->browser_window_type != BROWSER_WINDOW_IFRAME) {
- /* Iframe dimensions are already scaled in parent's layout */
- width /= bw->scale;
- height /= bw->scale;
- }
-
- if (bw->window == NULL) {
- /* Core managed browser window; subtract scrollbar width */
- width -= bw->scroll_y ? SCROLLBAR_WIDTH : 0;
- height -= bw->scroll_x ? SCROLLBAR_WIDTH : 0;
-
- width = width > 0 ? width : 0;
- height = height > 0 ? height : 0;
- }
-
- content_reformat(c, background, width, height);
-}
-
-/**
- * Set browser window scale.
- *
- * \param bw Browser window.
- * \param scale value.
- */
-static void browser_window_set_scale_internal(struct browser_window *bw,
- float scale)
-{
- int i;
- hlcache_handle *c;
-
- if (fabs(bw->scale-scale) < 0.0001)
- return;
-
- bw->scale = scale;
- c = bw->current_content;
-
- if (c != NULL) {
- if (content_can_reformat(c) == false) {
- browser_window_update(bw, false);
- } else {
- browser_window_schedule_reformat(bw);
- }
- }
-
- for (i = 0; i < (bw->cols * bw->rows); i++)
- browser_window_set_scale_internal(&bw->children[i], scale);
- for (i = 0; i < bw->iframe_count; i++)
- browser_window_set_scale_internal(&bw->iframes[i], scale);
-}
-
-
-/* exported interface documented in netsurf/browser_window.h */
-void browser_window_set_scale(struct browser_window *bw, float scale, bool all)
-{
- while (bw->parent && all)
- bw = bw->parent;
-
- browser_window_set_scale_internal(bw, scale);
-
- if (bw->parent)
- bw = bw->parent;
-
- browser_window_recalculate_frameset(bw);
-}
-
-
-/* exported interface documented in netsurf/browser_window.h */
-float browser_window_get_scale(struct browser_window *bw)
-{
- if (bw == NULL) {
- return 1.0;
- }
-
- return bw->scale;
-}
-
-/**
- * Find browser window.
- *
- * \param bw Browser window.
- * \param target Name of target.
- * \param depth Depth to scan.
- * \param page The browser window page.
- * \param rdepth The rdepth.
- * \param bw_target the output browser window.
- */
-static void browser_window_find_target_internal(struct browser_window *bw,
- const char *target, int depth, struct browser_window *page,
- int *rdepth, struct browser_window **bw_target)
-{
- int i;
-
- if ((bw->name) && (!strcasecmp(bw->name, target))) {
- if ((bw == page) || (depth > *rdepth)) {
- *rdepth = depth;
- *bw_target = bw;
- }
- }
-
- if ((!bw->children) && (!bw->iframes))
- return;
-
- depth++;
-
- if (bw->children != NULL) {
- for (i = 0; i < (bw->cols * bw->rows); i++) {
- if ((bw->children[i].name) &&
- (!strcasecmp(bw->children[i].name,
- target))) {
- if ((page == &bw->children[i]) ||
- (depth > *rdepth)) {
- *rdepth = depth;
- *bw_target = &bw->children[i];
- }
- }
- if (bw->children[i].children)
- browser_window_find_target_internal(
- &bw->children[i],
- target, depth, page,
- rdepth, bw_target);
- }
- }
-
- if (bw->iframes != NULL) {
- for (i = 0; i < bw->iframe_count; i++)
- browser_window_find_target_internal(&bw->iframes[i],
- target, depth, page, rdepth, bw_target);
- }
-}
-
-
-/* exported interface documented in netsurf/browser_window.h */
-struct browser_window *browser_window_find_target(struct browser_window *bw,
- const char *target, browser_mouse_state mouse)
-{
- struct browser_window *bw_target;
- struct browser_window *top;
- hlcache_handle *c;
- int rdepth;
- nserror error;
-
- /* use the base target if we don't have one */
- c = bw->current_content;
- if (target == NULL && c != NULL && content_get_type(c) == CONTENT_HTML)
- target = html_get_base_target(c);
- if (target == NULL)
- target = TARGET_SELF;
-
- /* allow the simple case of target="_blank" to be ignored if requested
- */
- if ((!(mouse & BROWSER_MOUSE_CLICK_2)) &&
- (!((mouse & BROWSER_MOUSE_CLICK_2) &&
- (mouse & BROWSER_MOUSE_MOD_2))) &&
- (!nsoption_bool(target_blank))) {
- /* not a mouse button 2 click
- * not a mouse button 1 click with ctrl pressed
- * configured to ignore target="_blank" */
- if ((target == TARGET_BLANK) || (!strcasecmp(target, "_blank")))
- return bw;
- }
-
- /* handle reserved keywords */
- if (((nsoption_bool(button_2_tab)) &&
- (mouse & BROWSER_MOUSE_CLICK_2))||
- ((!nsoption_bool(button_2_tab)) &&
- ((mouse & BROWSER_MOUSE_CLICK_1) &&
- (mouse & BROWSER_MOUSE_MOD_2))) ||
- ((nsoption_bool(button_2_tab)) &&
- ((target == TARGET_BLANK) ||
- (!strcasecmp(target, "_blank"))))) {
- /* open in new tab if:
- * - button_2 opens in new tab and button_2 was pressed
- * OR
- * - button_2 doesn't open in new tabs and button_1 was
- * pressed with ctrl held
- * OR
- * - button_2 opens in new tab and the link target is "_blank"
- */
- error = browser_window_create(BW_CREATE_TAB |
- BW_CREATE_HISTORY |
- BW_CREATE_CLONE,
- NULL,
- NULL,
- bw,
- &bw_target);
- if (error != NSERROR_OK) {
- return bw;
- }
- return bw_target;
- } else if (((!nsoption_bool(button_2_tab)) &&
- (mouse & BROWSER_MOUSE_CLICK_2)) ||
- ((nsoption_bool(button_2_tab)) &&
- ((mouse & BROWSER_MOUSE_CLICK_1) &&
- (mouse & BROWSER_MOUSE_MOD_2))) ||
- ((!nsoption_bool(button_2_tab)) &&
- ((target == TARGET_BLANK) ||
- (!strcasecmp(target, "_blank"))))) {
- /* open in new window if:
- * - button_2 doesn't open in new tabs and button_2 was pressed
- * OR
- * - button_2 opens in new tab and button_1 was pressed with
- * ctrl held
- * OR
- * - button_2 doesn't open in new tabs and the link target is
- * "_blank"
- */
- error = browser_window_create(BW_CREATE_HISTORY |
- BW_CREATE_CLONE,
- NULL,
- NULL,
- bw,
- &bw_target);
- if (error != NSERROR_OK) {
- return bw;
- }
- return bw_target;
- } else if ((target == TARGET_SELF) || (!strcasecmp(target, "_self"))) {
- return bw;
- } else if ((target == TARGET_PARENT) ||
- (!strcasecmp(target, "_parent"))) {
- if (bw->parent)
- return bw->parent;
- return bw;
- } else if ((target == TARGET_TOP) || (!strcasecmp(target, "_top"))) {
- while (bw->parent)
- bw = bw->parent;
- return bw;
- }
-
- /* find frame according to B.8, ie using the following priorities:
- *
- * 1) current frame
- * 2) closest to front
- */
- rdepth = -1;
- bw_target = NULL;
- for (top = bw; top->parent; top = top->parent);
- browser_window_find_target_internal(top, target, 0, bw, &rdepth,
- &bw_target);
- if (bw_target)
- return bw_target;
-
- /* we require a new window using the target name */
- if (!nsoption_bool(target_blank))
- return bw;
-
- error = browser_window_create(BW_CREATE_CLONE | BW_CREATE_HISTORY,
- NULL,
- NULL,
- bw,
- &bw_target);
- if (error != NSERROR_OK) {
- return bw;
- }
-
- /* frame names should begin with an alphabetic character (a-z,A-Z),
- * however in practice you get things such as '_new' and '2left'. The
- * only real effect this has is when giving out names as it can be
- * assumed that an author intended '_new' to create a new nameless
- * window (ie '_blank') whereas in the case of '2left' the intention
- * was for a new named window. As such we merely special case windows
- * that begin with an underscore. */
- if (target[0] != '_') {
- bw_target->name = strdup(target);
- if (!bw_target->name)
- guit->misc->warning("NoMemory", NULL);
- }
- return bw_target;
-}
-
-
-/**
- * Handles the end of a drag operation in a browser window.
- *
- * \param bw browser window
- * \param mouse state of mouse buttons and modifier keys
- * \param x coordinate of mouse
- * \param y coordinate of mouse
- *
- * \todo Remove this function, once these things are associated with content,
- * rather than bw.
- */
-static void browser_window_mouse_drag_end(struct browser_window *bw,
- browser_mouse_state mouse, int x, int y)
-{
- int scr_x, scr_y;
-
- switch (bw->drag.type) {
- case DRAGGING_SELECTION:
- case DRAGGING_OTHER:
- case DRAGGING_CONTENT_SCROLLBAR:
- /* Drag handled by content handler */
- break;
-
- case DRAGGING_SCR_X:
-
- browser_window_get_scrollbar_pos(bw, true, &scr_x, &scr_y);
-
- scr_x = x - scr_x - scrollbar_get_offset(bw->scroll_x);
- scr_y = y - scr_y - scrollbar_get_offset(bw->scroll_y);
-
- scrollbar_mouse_drag_end(bw->scroll_x, mouse, scr_x, scr_y);
-
- bw->drag.type = DRAGGING_NONE;
- break;
-
- case DRAGGING_SCR_Y:
-
- browser_window_get_scrollbar_pos(bw, false, &scr_x, &scr_y);
-
- scr_x = x - scr_x - scrollbar_get_offset(bw->scroll_x);
- scr_y = y - scr_y - scrollbar_get_offset(bw->scroll_y);
-
- scrollbar_mouse_drag_end(bw->scroll_y, mouse, scr_x, scr_y);
-
- bw->drag.type = DRAGGING_NONE;
- break;
-
- default:
- browser_window_set_drag_type(bw, DRAGGING_NONE, NULL);
- break;
- }
-}
-
-
-/* exported interface documented in netsurf/browser_window.h */
-void browser_window_mouse_track(struct browser_window *bw,
- browser_mouse_state mouse, int x, int y)
-{
- hlcache_handle *c = bw->current_content;
- const char *status = NULL;
- browser_pointer_shape pointer = BROWSER_POINTER_DEFAULT;
-
- if (bw->window != NULL && bw->drag.window && bw != bw->drag.window) {
- /* This is the root browser window and there's an active drag
- * in a sub window.
- * Pass the mouse action straight on to that bw. */
- struct browser_window *drag_bw = bw->drag.window;
- int off_x = 0;
- int off_y = 0;
-
- browser_window_get_position(drag_bw, true, &off_x, &off_y);
-
- if (drag_bw->browser_window_type == BROWSER_WINDOW_FRAME) {
- browser_window_mouse_track(drag_bw, mouse,
- x - off_x, y - off_y);
-
- } else if (drag_bw->browser_window_type ==
- BROWSER_WINDOW_IFRAME) {
- browser_window_mouse_track(drag_bw, mouse,
- x - off_x / bw->scale,
- y - off_y / bw->scale);
- }
- return;
- }
-
- if (bw->children) {
- /* Browser window has children (frames) */
- struct browser_window *child;
- int cur_child;
- int children = bw->rows * bw->cols;
-
- for (cur_child = 0; cur_child < children; cur_child++) {
-
- child = &bw->children[cur_child];
-
- if (x < child->x || y < child->y ||
- child->x + child->width < x ||
- child->y + child->height < y) {
- /* Click not in this child */
- continue;
- }
-
- /* It's this child that contains the mouse; pass
- * mouse action on to child */
- browser_window_mouse_track(child, mouse,
- x - child->x + scrollbar_get_offset(
- child->scroll_x),
- y - child->y + scrollbar_get_offset(
- child->scroll_y));
-
- /* Mouse action was for this child, we're done */
- return;
- }
-
- /* Odd if we reached here, but nothing else can use the click
- * when there are children. */
- return;
- }
-
- if (c == NULL && bw->drag.type != DRAGGING_FRAME) {
- return;
- }
-
- if (bw->drag.type != DRAGGING_NONE && !mouse) {
- browser_window_mouse_drag_end(bw, mouse, x, y);
- }
-
- /* Browser window's horizontal scrollbar */
- if (bw->scroll_x != NULL && bw->drag.type != DRAGGING_SCR_Y) {
- int scr_x, scr_y;
- browser_window_get_scrollbar_pos(bw, true, &scr_x, &scr_y);
- scr_x = x - scr_x - scrollbar_get_offset(bw->scroll_x);
- scr_y = y - scr_y - scrollbar_get_offset(bw->scroll_y);
-
- if ((bw->drag.type == DRAGGING_SCR_X) ||
- (scr_x > 0 &&
- scr_x < browser_window_get_scrollbar_len(bw, true) &&
- scr_y > 0 &&
- scr_y < SCROLLBAR_WIDTH &&
- bw->drag.type == DRAGGING_NONE)) {
- /* Start a scrollbar drag, or continue existing drag */
- status = scrollbar_mouse_status_to_message(
- scrollbar_mouse_action(
- bw->scroll_x, mouse,
- scr_x, scr_y));
- pointer = BROWSER_POINTER_DEFAULT;
-
- if (status != NULL) {
- browser_window_set_status(bw, status);
- }
-
- browser_window_set_pointer(bw, pointer);
- return;
- }
- }
-
- /* Browser window's vertical scrollbar */
- if (bw->scroll_y != NULL) {
- int scr_x, scr_y;
- browser_window_get_scrollbar_pos(bw, false, &scr_x, &scr_y);
- scr_x = x - scr_x - scrollbar_get_offset(bw->scroll_x);
- scr_y = y - scr_y - scrollbar_get_offset(bw->scroll_y);
-
- if ((bw->drag.type == DRAGGING_SCR_Y) ||
- (scr_y > 0 &&
- scr_y < browser_window_get_scrollbar_len(bw, false) &&
- scr_x > 0 &&
- scr_x < SCROLLBAR_WIDTH &&
- bw->drag.type == DRAGGING_NONE)) {
- /* Start a scrollbar drag, or continue existing drag */
- status = scrollbar_mouse_status_to_message(
- scrollbar_mouse_action(
- bw->scroll_y, mouse,
- scr_x, scr_y));
- pointer = BROWSER_POINTER_DEFAULT;
-
- if (status != NULL) {
- browser_window_set_status(bw, status);
- }
-
- browser_window_set_pointer(bw, pointer);
- return;
- }
- }
-
- if (bw->drag.type == DRAGGING_FRAME) {
- browser_window_resize_frame(bw, bw->x + x, bw->y + y);
- } else if (bw->drag.type == DRAGGING_PAGE_SCROLL) {
- /* mouse movement since drag started */
- struct rect rect;
-
- rect.x0 = bw->drag.start_x - x;
- rect.y0 = bw->drag.start_y - y;
-
- /* new scroll offsets */
- rect.x0 += bw->drag.start_scroll_x;
- rect.y0 += bw->drag.start_scroll_y;
-
- bw->drag.start_scroll_x = rect.x1 = rect.x0;
- bw->drag.start_scroll_y = rect.y1 = rect.y0;
-
- browser_window_set_scroll(bw, &rect);
- } else {
- assert(c != NULL);
- content_mouse_track(c, bw, mouse, x, y);
- }
-}
-
-
-/* exported interface documented in netsurf/browser_window.h */
-void browser_window_mouse_click(struct browser_window *bw,
- browser_mouse_state mouse, int x, int y)
-{
- hlcache_handle *c = bw->current_content;
- const char *status = NULL;
- browser_pointer_shape pointer = BROWSER_POINTER_DEFAULT;
-
- if (bw->children) {
- /* Browser window has children (frames) */
- struct browser_window *child;
- int cur_child;
- int children = bw->rows * bw->cols;
-
- for (cur_child = 0; cur_child < children; cur_child++) {
-
- child = &bw->children[cur_child];
-
- if (x < child->x || y < child->y ||
- child->x + child->width < x ||
- child->y + child->height < y) {
- /* Click not in this child */
- continue;
- }
-
- /* It's this child that contains the click; pass it
- * on to child. */
- browser_window_mouse_click(child, mouse,
- x - child->x + scrollbar_get_offset(
- child->scroll_x),
- y - child->y + scrollbar_get_offset(
- child->scroll_y));
-
- /* Mouse action was for this child, we're done */
- return;
- }
-
- return;
- }
-
- if (!c)
- return;
-
- if (bw->scroll_x != NULL) {
- int scr_x, scr_y;
- browser_window_get_scrollbar_pos(bw, true, &scr_x, &scr_y);
- scr_x = x - scr_x - scrollbar_get_offset(bw->scroll_x);
- scr_y = y - scr_y - scrollbar_get_offset(bw->scroll_y);
-
- if (scr_x > 0 && scr_x < browser_window_get_scrollbar_len(bw,
- true) &&
- scr_y > 0 && scr_y < SCROLLBAR_WIDTH) {
- status = scrollbar_mouse_status_to_message(
- scrollbar_mouse_action(
- bw->scroll_x, mouse,
- scr_x, scr_y));
- pointer = BROWSER_POINTER_DEFAULT;
-
- if (status != NULL)
- browser_window_set_status(bw, status);
-
- browser_window_set_pointer(bw, pointer);
- return;
- }
- }
-
- if (bw->scroll_y != NULL) {
- int scr_x, scr_y;
- browser_window_get_scrollbar_pos(bw, false, &scr_x, &scr_y);
- scr_x = x - scr_x - scrollbar_get_offset(bw->scroll_x);
- scr_y = y - scr_y - scrollbar_get_offset(bw->scroll_y);
-
- if (scr_y > 0 && scr_y < browser_window_get_scrollbar_len(bw,
- false) &&
- scr_x > 0 && scr_x < SCROLLBAR_WIDTH) {
- status = scrollbar_mouse_status_to_message(
- scrollbar_mouse_action(
- bw->scroll_y, mouse,
- scr_x, scr_y));
- pointer = BROWSER_POINTER_DEFAULT;
-
- if (status != NULL)
- browser_window_set_status(bw, status);
-
- browser_window_set_pointer(bw, pointer);
- return;
- }
- }
-
- switch (content_get_type(c)) {
- case CONTENT_HTML:
- case CONTENT_TEXTPLAIN:
- {
- /* Give bw focus */
- struct browser_window *root_bw = browser_window_get_root(bw);
- if (bw != root_bw->focus) {
- browser_window_remove_caret(bw, false);
- browser_window_set_selection(bw, false, true);
- root_bw->focus = bw;
- }
-
- /* Pass mouse action to content */
- content_mouse_action(c, bw, mouse, x, y);
- }
- break;
- default:
- if (mouse & BROWSER_MOUSE_MOD_2) {
- if (mouse & BROWSER_MOUSE_DRAG_2) {
- guit->window->drag_save_object(bw->window, c,
- GUI_SAVE_OBJECT_NATIVE);
- } else if (mouse & BROWSER_MOUSE_DRAG_1) {
- guit->window->drag_save_object(bw->window, c,
- GUI_SAVE_OBJECT_ORIG);
- }
- } else if (mouse & (BROWSER_MOUSE_DRAG_1 |
- BROWSER_MOUSE_DRAG_2)) {
- browser_window_page_drag_start(bw, x, y);
- browser_window_set_pointer(bw, BROWSER_POINTER_MOVE);
- }
- break;
- }
-}
-
-
-
-/* exported interface documented in netsurf/browser_window.h */
-void browser_window_redraw_rect(struct browser_window *bw, int x, int y,
- int width, int height)
-{
- content_request_redraw(bw->current_content, x, y, width, height);
-}
-
-
-/* exported interface documented in netsurf/browser_window.h */
-void browser_window_page_drag_start(struct browser_window *bw, int x, int y)
-{
- assert(bw != NULL);
-
- browser_window_set_drag_type(bw, DRAGGING_PAGE_SCROLL, NULL);
-
- bw->drag.start_x = x;
- bw->drag.start_y = y;
-
- if (bw->window != NULL) {
- /* Front end window */
- guit->window->get_scroll(bw->window,
- &bw->drag.start_scroll_x,
- &bw->drag.start_scroll_y);
-
- guit->window->scroll_start(bw->window);
- } else {
- /* Core managed browser window */
- bw->drag.start_scroll_x = scrollbar_get_offset(bw->scroll_x);
- bw->drag.start_scroll_y = scrollbar_get_offset(bw->scroll_y);
- }
-}
-
-
-
-/* exported interface documented in netsurf/browser_window.h */
-bool browser_window_back_available(struct browser_window *bw)
-{
- return (bw && bw->history &&
- browser_window_history_back_available(bw));
-}
-
-
-
-/* exported interface documented in netsurf/browser_window.h */
-bool browser_window_forward_available(struct browser_window *bw)
-{
- return (bw && bw->history &&
- browser_window_history_forward_available(bw));
-}
-
-/* exported interface documented in netsurf/browser_window.h */
-bool browser_window_reload_available(struct browser_window *bw)
-{
- return (bw && bw->current_content && !bw->loading_content);
-}
-
-
-/* exported interface documented in netsurf/browser_window.h */
-bool browser_window_stop_available(struct browser_window *bw)
-{
- return (bw && (bw->loading_content ||
- (bw->current_content &&
- (content_get_status(bw->current_content) !=
- CONTENT_STATUS_DONE))));
-}
-
-/* exported interface documented in browser.h */
+/* exported interface documented in netsurf/browser.h */
nserror browser_set_dpi(int dpi)
{
+ if (dpi < 72 || dpi > 250) {
+ int bad = dpi;
+ dpi = min(max(dpi, 72), 250);
+ NSLOG(netsurf, INFO, "Clamping invalid DPI %d to %d", bad, dpi);
+ }
nscss_screen_dpi = INTTOFIX(dpi);
return NSERROR_OK;
}
-/* exported interface documented in browser.h */
+/* exported interface documented in netsurf/browser.h */
int browser_get_dpi(void)
{
return FIXTOINT(nscss_screen_dpi);
diff --git a/desktop/browser_history.c b/desktop/browser_history.c
index d9db0eb18..ce9821af8 100644
--- a/desktop/browser_history.c
+++ b/desktop/browser_history.c
@@ -33,19 +33,16 @@
#include "netsurf/layout.h"
#include "netsurf/content.h"
#include "netsurf/window.h"
+#include "netsurf/browser_window.h"
#include "content/hlcache.h"
#include "content/urldb.h"
#include "netsurf/bitmap.h"
+#include "utils/corestrings.h"
#include "desktop/gui_internal.h"
-#include "desktop/browser_history.h"
#include "desktop/browser_private.h"
-
-#define WIDTH 100
-#define HEIGHT 86
-#define RIGHT_MARGIN 50
-#define BOTTOM_MARGIN 30
-
+#include "desktop/local_history_private.h"
+#include "desktop/browser_history.h"
/**
* Clone a history entry
@@ -106,8 +103,10 @@ browser_window_history__clone_entry(struct history *history,
unsigned char *bmdst_data;
size_t bmsize;
- new_entry->page.bitmap = guit->bitmap->create(WIDTH, HEIGHT,
- BITMAP_NEW | BITMAP_OPAQUE);
+ new_entry->page.bitmap = guit->bitmap->create(
+ LOCAL_HISTORY_WIDTH,
+ LOCAL_HISTORY_HEIGHT,
+ BITMAP_OPAQUE);
if (new_entry->page.bitmap != NULL) {
bmsrc_data = guit->bitmap->get_buffer(entry->page.bitmap);
@@ -201,26 +200,26 @@ static int browser_window_history__layout_subtree(struct history *history,
struct history_entry *child;
int y1 = y;
- if (history->width < x + WIDTH)
- history->width = x + WIDTH;
+ if (history->width < x + LOCAL_HISTORY_WIDTH)
+ history->width = x + LOCAL_HISTORY_WIDTH;
if (!entry->forward) {
entry->x = x;
entry->y = y;
- return y + HEIGHT;
+ return y + LOCAL_HISTORY_HEIGHT;
}
/* layout child subtrees below each other */
for (child = entry->forward; child; child = child->next) {
y1 = browser_window_history__layout_subtree(history, child,
- x + WIDTH + RIGHT_MARGIN, y1);
+ x + LOCAL_HISTORY_WIDTH + LOCAL_HISTORY_RIGHT_MARGIN, y1);
if (child->next)
- y1 += BOTTOM_MARGIN;
+ y1 += LOCAL_HISTORY_BOTTOM_MARGIN;
}
/* place ourselves in the middle */
entry->x = x;
- entry->y = (y + y1) / 2 - HEIGHT / 2;
+ entry->y = (y + y1) / 2 - LOCAL_HISTORY_HEIGHT / 2;
return y1;
}
@@ -243,12 +242,13 @@ static void browser_window_history__layout(struct history *history)
if (history->start)
history->height = browser_window_history__layout_subtree(
history, history->start,
- RIGHT_MARGIN / 2, BOTTOM_MARGIN / 2);
+ LOCAL_HISTORY_RIGHT_MARGIN / 2,
+ LOCAL_HISTORY_BOTTOM_MARGIN / 2);
else
history->height = 0;
- history->width += RIGHT_MARGIN / 2;
- history->height += BOTTOM_MARGIN / 2;
+ history->width += LOCAL_HISTORY_RIGHT_MARGIN / 2;
+ history->height += LOCAL_HISTORY_BOTTOM_MARGIN / 2;
}
@@ -274,7 +274,8 @@ static bool browser_window_history__enumerate_entry(
const struct history_entry *child;
if (!cb(bw, entry->x, entry->y,
- entry->x + WIDTH, entry->y + HEIGHT,
+ entry->x + LOCAL_HISTORY_WIDTH,
+ entry->y + LOCAL_HISTORY_HEIGHT,
entry, ud))
return false;
@@ -303,8 +304,8 @@ nserror browser_window_history_create(struct browser_window *bw)
return NSERROR_NOMEM;
}
- history->width = RIGHT_MARGIN / 2;
- history->height = BOTTOM_MARGIN / 2;
+ history->width = LOCAL_HISTORY_RIGHT_MARGIN / 2;
+ history->height = LOCAL_HISTORY_BOTTOM_MARGIN / 2;
bw->history = history;
@@ -385,8 +386,9 @@ browser_window_history_add(struct browser_window *bw,
NSLOG(netsurf, DEBUG,
"Creating thumbnail for %s", nsurl_access(entry->page.url));
- entry->page.bitmap = guit->bitmap->create(WIDTH, HEIGHT,
- BITMAP_NEW | BITMAP_CLEAR_MEMORY | BITMAP_OPAQUE);
+ entry->page.bitmap = guit->bitmap->create(
+ LOCAL_HISTORY_WIDTH, LOCAL_HISTORY_HEIGHT,
+ BITMAP_CLEAR | BITMAP_OPAQUE);
if (entry->page.bitmap != NULL) {
ret = guit->bitmap->render(entry->page.bitmap, content);
if (ret != NSERROR_OK) {
@@ -433,9 +435,7 @@ nserror browser_window_history_update(struct browser_window *bw,
history = bw->history;
- if (!history ||
- !history->current ||
- !history->current->page.bitmap) {
+ if ((history == NULL) || (history->current == NULL)) {
return NSERROR_INVALID;
}
@@ -454,13 +454,22 @@ nserror browser_window_history_update(struct browser_window *bw,
guit->bitmap->render(history->current->page.bitmap, content);
}
- if (bw->window != NULL &&
+ if ((bw->window != NULL) &&
guit->window->get_scroll(bw->window, &sx, &sy)) {
+ int content_height = content_get_height(content);
+ int content_width = content_get_width(content);
+ /* clamp width and height values */
+ if (content_height < 1) {
+ content_height = 1;
+ }
+ if (content_width < 1) {
+ content_width = 1;
+ }
/* Successfully got scroll offsets, update the entry */
history->current->page.scroll_x = \
- (float)sx / (float)content_get_width(content);
+ (float)sx / (float)content_width;
history->current->page.scroll_y = \
- (float)sy / (float)content_get_height(content);
+ (float)sy / (float)content_height;
NSLOG(netsurf, INFO, "Updated scroll offsets to %g by %g",
history->current->page.scroll_x,
history->current->page.scroll_y);
@@ -479,9 +488,7 @@ browser_window_history_get_scroll(struct browser_window *bw,
history = bw->history;
- if (!history ||
- !history->current ||
- !history->current->page.bitmap) {
+ if ((history== NULL) || (history->current == NULL)) {
return NSERROR_INVALID;
}
@@ -510,6 +517,24 @@ void browser_window_history_destroy(struct browser_window *bw)
/* exported interface documented in desktop/browser_history.h */
nserror browser_window_history_back(struct browser_window *bw, bool new_window)
{
+ if (bw != NULL && bw->internal_nav) {
+ /* All internal nav back operations ignore new_window */
+ if (bw->current_parameters.url != NULL) {
+ /* There are some internal parameters, restart from there */
+ return browser_window__reload_current_parameters(bw);
+ } else {
+ /* No internal parameters, just navigate to about:blank */
+ return browser_window_navigate(
+ bw,
+ corestring_nsurl_about_blank,
+ NULL, /* Referer */
+ BW_NAVIGATE_HISTORY,
+ NULL, /* Post */
+ NULL, /* Post */
+ NULL /* parent fetch */);
+ }
+ }
+
if (!bw || !bw->history || !bw->history->current ||
!bw->history->current->back) {
return NSERROR_BAD_PARAMETER;
@@ -627,7 +652,8 @@ void browser_window_history_enumerate_forward(const struct browser_window *bw,
e = bw->history->current->forward_pref;
for (; e != NULL; e = e->forward_pref) {
- if (!cb(bw, e->x, e->y, e->x + WIDTH, e->y + HEIGHT,
+ if (!cb(bw, e->x, e->y, e->x + LOCAL_HISTORY_WIDTH,
+ e->y + LOCAL_HISTORY_HEIGHT,
e, user_data))
break;
}
@@ -644,7 +670,8 @@ void browser_window_history_enumerate_back(const struct browser_window *bw,
return;
for (e = bw->history->current->back; e != NULL; e = e->back) {
- if (!cb(bw, e->x, e->y, e->x + WIDTH, e->y + HEIGHT,
+ if (!cb(bw, e->x, e->y, e->x + LOCAL_HISTORY_WIDTH,
+ e->y + LOCAL_HISTORY_HEIGHT,
e, user_data))
break;
}
diff --git a/desktop/browser_private.h b/desktop/browser_private.h
index 192d22bf0..40c3b43ce 100644
--- a/desktop/browser_private.h
+++ b/desktop/browser_private.h
@@ -22,14 +22,10 @@
* Browser window private structure.
*/
-#ifndef _NETSURF_DESKTOP_BROWSER_PRIVATE_H_
-#define _NETSURF_DESKTOP_BROWSER_PRIVATE_H_
-
-#include <libwapcaplet/libwapcaplet.h>
-
-#include "netsurf/types.h"
-#include "netsurf/browser_window.h"
+#ifndef NETSURF_DESKTOP_BROWSER_PRIVATE_H_
+#define NETSURF_DESKTOP_BROWSER_PRIVATE_H_
+#include "content/fetch.h"
#include "desktop/frame_types.h"
struct box;
@@ -81,6 +77,20 @@ struct history {
};
/**
+ * The parameters for a fetch.
+ */
+struct browser_fetch_parameters {
+ struct nsurl *url; /**< The URL to fetch */
+ struct nsurl *referrer; /**< Optional refererer */
+ enum browser_window_nav_flags flags; /**< Navigation flags */
+ char *post_urlenc; /**< URL encoded post data */
+ struct fetch_multipart_data *post_multipart; /**< Multipart post data */
+ char *parent_charset; /**< Optional parent character set */
+ bool parent_quirks; /**< Optional parent quirks */
+};
+
+
+/**
* Browser window data.
*/
struct browser_window {
@@ -89,6 +99,17 @@ struct browser_window {
* READY or DONE status or NULL for no content.
*/
struct hlcache_handle *current_content;
+
+ /**
+ * The fetch parameters for the current content
+ */
+ struct browser_fetch_parameters current_parameters;
+
+ /**
+ * The certificate chain for the current content
+ */
+ struct cert_chain *current_cert_chain;
+
/**
* Content handle of page in process of being loaded or NULL
* if no page is being loaded.
@@ -96,6 +117,16 @@ struct browser_window {
struct hlcache_handle *loading_content;
/**
+ * The fetch parameters for the loading content
+ */
+ struct browser_fetch_parameters loading_parameters;
+
+ /**
+ * The certificate chain for the loading content
+ */
+ struct cert_chain *loading_cert_chain;
+
+ /**
* Favicon
*/
struct {
@@ -129,6 +160,8 @@ struct browser_window {
bool throbbing;
/** Add loading_content to the window history when it loads. */
bool history_add;
+ /** Internal navigation, do not update URL etc */
+ bool internal_nav;
/** Fragment identifier for current_content. */
lwc_string *frag_id;
@@ -230,7 +263,7 @@ struct browser_window {
bool can_edit;
/** current javascript context */
- struct jscontext *jsctx;
+ struct jsheap *jsheap;
/** cache of the currently displayed status text. */
struct {
@@ -250,19 +283,27 @@ struct browser_window {
* \param existing The existing window if cloning, else NULL
*/
nserror browser_window_initialise_common(enum browser_window_create_flags flags,
- struct browser_window *bw, struct browser_window *existing);
+ struct browser_window *bw,
+ const struct browser_window *existing);
/**
+ * Release all memory associated with a browser window.
+ *
+ * \param bw browser window
+ */
+nserror browser_window_destroy_internal(struct browser_window *bw);
+
+/**
* Get the dimensions of the area a browser window occupies
*
* \param bw The browser window to get dimensions of
* \param width Updated to the browser window viewport width
* \param height Updated to the browser window viewport height
- * \param scaled Whether we want the height with scale applied
+ * \return NSERROR_OK and width and height updated otherwise error code
*/
-void browser_window_get_dimensions(struct browser_window *bw,
- int *width, int *height, bool scaled);
+nserror browser_window_get_dimensions(struct browser_window *bw,
+ int *width, int *height);
/**
@@ -275,6 +316,15 @@ void browser_window_update_extent(struct browser_window *bw);
/**
+ * Cause an area of a browser window to be marked invalid and hence redrawn.
+ *
+ * \param bw The browser window to update.
+ * \param rect The area to redraw
+ */
+nserror browser_window_invalidate_rect(struct browser_window *bw, struct rect *rect);
+
+
+/**
* Change the status bar of a browser window.
*
* \param bw browser window
@@ -289,7 +339,8 @@ void browser_window_set_status(struct browser_window *bw, const char *text);
* \param bw browser window to set the type of the current drag for
* \return root browser window
*/
-struct browser_window * browser_window_get_root(struct browser_window *bw);
+struct browser_window * browser_window_get_root(
+ struct browser_window *bw);
/**
@@ -354,5 +405,16 @@ nserror browser_window_history_get_scroll(struct browser_window *bw,
*/
void browser_window_history_destroy(struct browser_window *bw);
+/**
+ * Type for handling query responses short-term
+ */
+typedef nserror (*browser_window_query_callback)(bool proceed, void *pw);
+
+/**
+ * Navigate a browser window to the current parameters
+ *
+ * \param bw The browser window to cause to navigate
+ */
+nserror browser_window__reload_current_parameters(struct browser_window *bw);
#endif
diff --git a/desktop/browser_window.c b/desktop/browser_window.c
new file mode 100644
index 000000000..c70db7cf1
--- /dev/null
+++ b/desktop/browser_window.c
@@ -0,0 +1,4813 @@
+/*
+ * Copyright 2008 Michael Drake <tlsa@netsurf-browser.org>
+ * Copyright 2010 Daniel Silverstone <dsilvers@digital-scurf.org>
+ * Copyright 2010-2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ *
+ * Browser window creation and manipulation implementation.
+ */
+
+#include "utils/config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <nsutils/time.h>
+
+#include "utils/errors.h"
+#include "utils/log.h"
+#include "utils/corestrings.h"
+#include "utils/messages.h"
+#include "utils/nsoption.h"
+#include "netsurf/types.h"
+#include "netsurf/browser_window.h"
+#include "netsurf/window.h"
+#include "netsurf/misc.h"
+#include "netsurf/content.h"
+#include "netsurf/search.h"
+#include "netsurf/plotters.h"
+#include "content/content.h"
+#include "content/hlcache.h"
+#include "content/urldb.h"
+#include "content/content_debug.h"
+
+#include "html/html.h"
+#include "html/form_internal.h"
+#include "javascript/js.h"
+
+#include "desktop/browser_private.h"
+#include "desktop/scrollbar.h"
+#include "desktop/gui_internal.h"
+#include "desktop/download.h"
+#include "desktop/frames.h"
+#include "desktop/global_history.h"
+#include "desktop/textinput.h"
+#include "desktop/hotlist.h"
+#include "desktop/knockout.h"
+#include "desktop/browser_history.h"
+#include "desktop/theme.h"
+
+#ifdef WITH_THEME_INSTALL
+#include "desktop/theme.h"
+#endif
+
+/**
+ * smallest scale that can be applied to a browser window
+ */
+#define SCALE_MINIMUM 0.2
+
+/**
+ * largests scale that can be applied to a browser window
+ */
+#define SCALE_MAXIMUM 10.0
+
+/**
+ * maximum frame depth
+ */
+#define FRAME_DEPTH 8
+
+/* Forward declare internal navigation function */
+static nserror browser_window__navigate_internal(
+ struct browser_window *bw, struct browser_fetch_parameters *params);
+
+
+/**
+ * Close and destroy all child browser window.
+ *
+ * \param bw browser window
+ */
+static void browser_window_destroy_children(struct browser_window *bw)
+{
+ int i;
+
+ if (bw->children) {
+ for (i = 0; i < (bw->rows * bw->cols); i++) {
+ browser_window_destroy_internal(&bw->children[i]);
+ }
+ free(bw->children);
+ bw->children = NULL;
+ bw->rows = 0;
+ bw->cols = 0;
+ }
+}
+
+
+/**
+ * Free the stored fetch parameters
+ *
+ * \param bw The browser window
+ */
+static void
+browser_window__free_fetch_parameters(struct browser_fetch_parameters *params)
+{
+ if (params->url != NULL) {
+ nsurl_unref(params->url);
+ params->url = NULL;
+ }
+ if (params->referrer != NULL) {
+ nsurl_unref(params->referrer);
+ params->referrer = NULL;
+ }
+ if (params->post_urlenc != NULL) {
+ free(params->post_urlenc);
+ params->post_urlenc = NULL;
+ }
+ if (params->post_multipart != NULL) {
+ fetch_multipart_data_destroy(params->post_multipart);
+ params->post_multipart = NULL;
+ }
+ if (params->parent_charset != NULL) {
+ free(params->parent_charset);
+ params->parent_charset = NULL;
+ }
+}
+
+
+/**
+ * Get position of scrollbar widget within browser window.
+ *
+ * \param bw The browser window
+ * \param horizontal Whether to get position of horizontal scrollbar
+ * \param x Updated to x-coord of top left of scrollbar widget
+ * \param y Updated to y-coord of top left of scrollbar widget
+ */
+static inline void
+browser_window_get_scrollbar_pos(struct browser_window *bw,
+ bool horizontal,
+ int *x, int *y)
+{
+ if (horizontal) {
+ *x = 0;
+ *y = bw->height - SCROLLBAR_WIDTH;
+ } else {
+ *x = bw->width - SCROLLBAR_WIDTH;
+ *y = 0;
+ }
+}
+
+
+/**
+ * Get browser window horizontal scrollbar widget length
+ *
+ * \param bw The browser window
+ * \return the scrollbar's length
+ */
+static inline int get_horz_scrollbar_len(struct browser_window *bw)
+{
+ if (bw->scroll_y == NULL) {
+ return bw->width;
+ }
+ return bw->width - SCROLLBAR_WIDTH;
+}
+
+
+/**
+ * Get browser window vertical scrollbar widget length
+ *
+ * \param bw The browser window
+ * \return the scrollbar's length
+ */
+static inline int get_vert_scrollbar_len(struct browser_window *bw)
+{
+ return bw->height;
+}
+
+
+/**
+ * Set or remove a selection.
+ *
+ * \param bw browser window with selection
+ * \param selection true if bw has a selection, false if removing selection
+ * \param read_only true iff selection is read only (e.g. can't cut it)
+ */
+static void
+browser_window_set_selection(struct browser_window *bw,
+ bool selection,
+ bool read_only)
+{
+ struct browser_window *top;
+
+ assert(bw != NULL);
+
+ top = browser_window_get_root(bw);
+
+ assert(top != NULL);
+
+ if (bw != top->selection.bw &&
+ top->selection.bw != NULL &&
+ top->selection.bw->current_content != NULL) {
+ /* clear old selection */
+ content_clear_selection(top->selection.bw->current_content);
+ }
+
+ if (selection) {
+ top->selection.bw = bw;
+ } else {
+ top->selection.bw = NULL;
+ }
+
+ top->selection.read_only = read_only;
+}
+
+
+/**
+ * Set the scroll position of a browser window.
+ *
+ * scrolls the viewport to ensure the specified rectangle of the
+ * content is shown.
+ *
+ * \param bw window to scroll
+ * \param rect The rectangle to ensure is shown.
+ * \return NSERROR_OK on success or apropriate error code.
+ */
+static nserror
+browser_window_set_scroll(struct browser_window *bw, const struct rect *rect)
+{
+ if (bw->window != NULL) {
+ return guit->window->set_scroll(bw->window, rect);
+ }
+
+ if (bw->scroll_x != NULL) {
+ scrollbar_set(bw->scroll_x, rect->x0, false);
+ }
+ if (bw->scroll_y != NULL) {
+ scrollbar_set(bw->scroll_y, rect->y0, false);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Internal helper for getting the positional features
+ *
+ * \param[in] bw browser window to examine.
+ * \param[in] x x-coordinate of point of interest
+ * \param[in] y y-coordinate of point of interest
+ * \param[out] data Feature structure to update.
+ * \return NSERROR_OK or appropriate error code on faliure.
+ */
+static nserror
+browser_window__get_contextual_content(struct browser_window *bw,
+ int x, int y,
+ struct browser_window_features *data)
+{
+ nserror ret = NSERROR_OK;
+
+ /* Handle (i)frame scroll offset (core-managed browser windows only) */
+ x += scrollbar_get_offset(bw->scroll_x);
+ y += scrollbar_get_offset(bw->scroll_y);
+
+ if (bw->children) {
+ /* Browser window has children, so pass request on to
+ * appropriate child.
+ */
+ struct browser_window *bwc;
+ int cur_child;
+ int children = bw->rows * bw->cols;
+
+ /* Loop through all children of bw */
+ for (cur_child = 0; cur_child < children; cur_child++) {
+ /* Set current child */
+ bwc = &bw->children[cur_child];
+
+ /* Skip this frame if (x, y) coord lies outside */
+ if ((x < bwc->x) ||
+ (bwc->x + bwc->width < x) ||
+ (y < bwc->y) ||
+ (bwc->y + bwc->height < y)) {
+ continue;
+ }
+
+ /* Pass request into this child */
+ return browser_window__get_contextual_content(bwc,
+ (x - bwc->x), (y - bwc->y), data);
+ }
+
+ /* Coordinate not contained by any frame */
+
+ } else if (bw->current_content != NULL) {
+ /* Pass request to content */
+ ret = content_get_contextual_content(bw->current_content,
+ x, y, data);
+ data->main = bw->current_content;
+ }
+
+ return ret;
+}
+
+
+/**
+ * implements the download operation of a window navigate
+ */
+static nserror
+browser_window_download(struct browser_window *bw,
+ nsurl *url,
+ nsurl *nsref,
+ uint32_t fetch_flags,
+ bool fetch_is_post,
+ llcache_post_data *post)
+{
+ llcache_handle *l;
+ struct browser_window *root;
+ nserror error;
+
+ root = browser_window_get_root(bw);
+ assert(root != NULL);
+
+ fetch_flags |= LLCACHE_RETRIEVE_FORCE_FETCH;
+ fetch_flags |= LLCACHE_RETRIEVE_STREAM_DATA;
+
+ error = llcache_handle_retrieve(url, fetch_flags, nsref,
+ fetch_is_post ? post : NULL,
+ NULL, NULL, &l);
+ if (error == NSERROR_NO_FETCH_HANDLER) {
+ /* no internal handler for this type, call out to frontend */
+ error = guit->misc->launch_url(url);
+ } else if (error != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Failed to fetch download: %d", error);
+ } else {
+ error = download_context_create(l, root->window);
+ if (error != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Failed creating download context: %d", error);
+ llcache_handle_abort(l);
+ llcache_handle_release(l);
+ }
+ }
+
+ return error;
+}
+
+
+/**
+ * recursively check browser windows for activity
+ *
+ * \param bw browser window to start checking from.
+ */
+static bool browser_window_check_throbber(struct browser_window *bw)
+{
+ int children, index;
+
+ if (bw->throbbing)
+ return true;
+
+ if (bw->children) {
+ children = bw->rows * bw->cols;
+ for (index = 0; index < children; index++) {
+ if (browser_window_check_throbber(&bw->children[index]))
+ return true;
+ }
+ }
+
+ if (bw->iframes) {
+ for (index = 0; index < bw->iframe_count; index++) {
+ if (browser_window_check_throbber(&bw->iframes[index]))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+/**
+ * Start the busy indicator.
+ *
+ * \param bw browser window
+ */
+static nserror browser_window_start_throbber(struct browser_window *bw)
+{
+ bw->throbbing = true;
+
+ while (bw->parent)
+ bw = bw->parent;
+
+ return guit->window->event(bw->window, GW_EVENT_START_THROBBER);
+}
+
+
+/**
+ * Stop the busy indicator.
+ *
+ * \param bw browser window
+ */
+static nserror browser_window_stop_throbber(struct browser_window *bw)
+{
+ nserror res = NSERROR_OK;
+
+ bw->throbbing = false;
+
+ while (bw->parent) {
+ bw = bw->parent;
+ }
+
+ if (!browser_window_check_throbber(bw)) {
+ res = guit->window->event(bw->window, GW_EVENT_STOP_THROBBER);
+ }
+ return res;
+}
+
+
+/**
+ * Callback for fetchcache() for browser window favicon fetches.
+ *
+ * \param c content handle of favicon
+ * \param event The event to process
+ * \param pw a context containing the browser window
+ * \return NSERROR_OK on success else appropriate error code.
+ */
+static nserror
+browser_window_favicon_callback(hlcache_handle *c,
+ const hlcache_event *event,
+ void *pw)
+{
+ struct browser_window *bw = pw;
+
+ switch (event->type) {
+ case CONTENT_MSG_DONE:
+ if (bw->favicon.current != NULL) {
+ content_close(bw->favicon.current);
+ hlcache_handle_release(bw->favicon.current);
+ }
+
+ bw->favicon.current = c;
+ bw->favicon.loading = NULL;
+
+ /* content_get_bitmap on the hlcache_handle should give
+ * the favicon bitmap at this point
+ */
+ guit->window->set_icon(bw->window, c);
+ break;
+
+ case CONTENT_MSG_ERROR:
+
+ /* clean up after ourselves */
+ if (c == bw->favicon.loading) {
+ bw->favicon.loading = NULL;
+ } else if (c == bw->favicon.current) {
+ bw->favicon.current = NULL;
+ }
+
+ hlcache_handle_release(c);
+
+ if (bw->favicon.failed == false) {
+ nsurl *nsref = NULL;
+ nsurl *nsurl;
+ nserror error;
+
+ bw->favicon.failed = true;
+
+ error = nsurl_create("resource:favicon.ico", &nsurl);
+ if (error != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Unable to create default location url");
+ } else {
+ hlcache_handle_retrieve(nsurl,
+ HLCACHE_RETRIEVE_SNIFF_TYPE,
+ nsref, NULL,
+ browser_window_favicon_callback,
+ bw, NULL, CONTENT_IMAGE,
+ &bw->favicon.loading);
+
+ nsurl_unref(nsurl);
+ }
+
+ }
+ break;
+
+ default:
+ break;
+
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * update the favicon associated with the browser window
+ *
+ * \param c the page content handle.
+ * \param bw A top level browser window.
+ * \param link A link context or NULL to attempt fallback scanning.
+ */
+static nserror
+browser_window_update_favicon(hlcache_handle *c,
+ struct browser_window *bw,
+ struct content_rfc5988_link *link)
+{
+ nsurl *nsref = NULL;
+ nsurl *nsurl;
+ nserror res;
+
+ assert(c != NULL);
+ assert(bw !=NULL);
+
+ if (bw->window == NULL) {
+ /* Not top-level browser window; not interested */
+ return NSERROR_OK;
+ }
+
+ /* already fetching the favicon - use that */
+ if (bw->favicon.loading != NULL) {
+ return NSERROR_OK;
+ }
+
+ bw->favicon.failed = false;
+
+ if (link == NULL) {
+ /* Look for "icon" */
+ link = content_find_rfc5988_link(c, corestring_lwc_icon);
+ }
+
+ if (link == NULL) {
+ /* Look for "shortcut icon" */
+ link = content_find_rfc5988_link(c, corestring_lwc_shortcut_icon);
+ }
+
+ if (link == NULL) {
+ lwc_string *scheme;
+ bool speculative_default = false;
+ bool match;
+
+ nsurl = hlcache_handle_get_url(c);
+
+ scheme = nsurl_get_component(nsurl, NSURL_SCHEME);
+
+ /* If the document was fetched over http(s), then speculate
+ * that there's a favicon living at /favicon.ico */
+ if ((lwc_string_caseless_isequal(scheme,
+ corestring_lwc_http,
+ &match) == lwc_error_ok &&
+ match) ||
+ (lwc_string_caseless_isequal(scheme,
+ corestring_lwc_https,
+ &match) == lwc_error_ok &&
+ match)) {
+ speculative_default = true;
+ }
+
+ lwc_string_unref(scheme);
+
+ if (speculative_default) {
+ /* no favicon via link, try for the default location */
+ res = nsurl_join(nsurl, "/favicon.ico", &nsurl);
+ } else {
+ bw->favicon.failed = true;
+ res = nsurl_create("resource:favicon.ico", &nsurl);
+ }
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Unable to create default location url");
+ return res;
+ }
+ } else {
+ nsurl = nsurl_ref(link->href);
+ }
+
+ if (link == NULL) {
+ NSLOG(netsurf, INFO,
+ "fetching general favicon from '%s'",
+ nsurl_access(nsurl));
+ } else {
+ NSLOG(netsurf, INFO,
+ "fetching favicon rel:%s '%s'",
+ lwc_string_data(link->rel),
+ nsurl_access(nsurl));
+ }
+
+ res = hlcache_handle_retrieve(nsurl,
+ HLCACHE_RETRIEVE_SNIFF_TYPE,
+ nsref,
+ NULL,
+ browser_window_favicon_callback,
+ bw,
+ NULL,
+ CONTENT_IMAGE,
+ &bw->favicon.loading);
+
+ nsurl_unref(nsurl);
+
+ return res;
+}
+
+
+/**
+ * Handle meta http-equiv refresh time elapsing by loading a new page.
+ *
+ * \param p browser window to refresh with new page
+ */
+static void browser_window_refresh(void *p)
+{
+ struct browser_window *bw = p;
+ nsurl *url;
+ nsurl *refresh;
+ hlcache_handle *parent = NULL;
+ enum browser_window_nav_flags flags = BW_NAVIGATE_UNVERIFIABLE;
+
+ assert(bw->current_content != NULL &&
+ (content_get_status(bw->current_content) ==
+ CONTENT_STATUS_READY ||
+ content_get_status(bw->current_content) ==
+ CONTENT_STATUS_DONE));
+
+ /* Ignore if the refresh URL has gone
+ * (may happen if a fetch error occurred) */
+ refresh = content_get_refresh_url(bw->current_content);
+ if (refresh == NULL)
+ return;
+
+ /* mark this content as invalid so it gets flushed from the cache */
+ content_invalidate_reuse_data(bw->current_content);
+
+ url = hlcache_handle_get_url(bw->current_content);
+ if ((url == NULL) || (nsurl_compare(url, refresh, NSURL_COMPLETE))) {
+ flags |= BW_NAVIGATE_HISTORY;
+ }
+
+ /* Treat an (almost) immediate refresh in a top-level browser window as
+ * if it were an HTTP redirect, and thus make the resulting fetch
+ * verifiable.
+ *
+ * See fetchcache.c for why redirected fetches should be verifiable at
+ * all.
+ */
+ if (bw->refresh_interval <= 100 && bw->parent == NULL) {
+ flags &= ~BW_NAVIGATE_UNVERIFIABLE;
+ } else {
+ parent = bw->current_content;
+ }
+
+ browser_window_navigate(bw,
+ refresh,
+ url,
+ flags,
+ NULL,
+ NULL,
+ parent);
+
+}
+
+
+/**
+ * Transfer the loading_content to a new download window.
+ */
+static void
+browser_window_convert_to_download(struct browser_window *bw,
+ llcache_handle *stream)
+{
+ struct browser_window *root = browser_window_get_root(bw);
+ nserror error;
+
+ assert(root != NULL);
+
+ error = download_context_create(stream, root->window);
+ if (error != NSERROR_OK) {
+ llcache_handle_abort(stream);
+ llcache_handle_release(stream);
+ }
+
+ /* remove content from browser window */
+ hlcache_handle_release(bw->loading_content);
+ bw->loading_content = NULL;
+
+ browser_window_stop_throbber(bw);
+}
+
+
+/**
+ * scroll to a fragment if present
+ *
+ * \param bw browser window
+ * \return true if the scroll was sucessful
+ */
+static bool frag_scroll(struct browser_window *bw)
+{
+ struct rect rect;
+
+ if (bw->frag_id == NULL) {
+ return false;
+ }
+
+ if (!html_get_id_offset(bw->current_content,
+ bw->frag_id,
+ &rect.x0,
+ &rect.y0)) {
+ return false;
+ }
+
+ rect.x1 = rect.x0;
+ rect.y1 = rect.y0;
+ if (browser_window_set_scroll(bw, &rect) == NSERROR_OK) {
+ if (bw->current_content != NULL &&
+ bw->history != NULL &&
+ bw->history->current != NULL) {
+ browser_window_history_update(bw, bw->current_content);
+ }
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ * Redraw browser window, set extent to content, and update title.
+ *
+ * \param bw browser_window
+ * \param scroll_to_top move view to top of page
+ */
+static void browser_window_update(struct browser_window *bw, bool scroll_to_top)
+{
+ static const struct rect zrect = {
+ .x0 = 0,
+ .y0 = 0,
+ .x1 = 0,
+ .y1 = 0
+ };
+
+ if (bw->current_content == NULL) {
+ return;
+ }
+
+ switch (bw->browser_window_type) {
+
+ case BROWSER_WINDOW_NORMAL:
+ /* Root browser window, constituting a front end window/tab */
+ guit->window->set_title(bw->window,
+ content_get_title(bw->current_content));
+
+ browser_window_update_extent(bw);
+
+ /* if frag_id exists, then try to scroll to it */
+ /** @todo don't do this if the user has scrolled */
+ if (!frag_scroll(bw)) {
+ if (scroll_to_top) {
+ browser_window_set_scroll(bw, &zrect);
+ }
+ }
+
+ guit->window->invalidate(bw->window, NULL);
+
+ break;
+
+ case BROWSER_WINDOW_IFRAME:
+ /* Internal iframe browser window */
+ assert(bw->parent != NULL);
+ assert(bw->parent->current_content != NULL);
+
+ browser_window_update_extent(bw);
+
+ if (scroll_to_top) {
+ browser_window_set_scroll(bw, &zrect);
+ }
+
+ /* if frag_id exists, then try to scroll to it */
+ /** @todo don't do this if the user has scrolled */
+ frag_scroll(bw);
+
+ browser_window_invalidate_iframe(bw);
+
+ break;
+
+ case BROWSER_WINDOW_FRAME:
+ {
+ struct rect rect;
+ browser_window_update_extent(bw);
+
+ if (scroll_to_top) {
+ browser_window_set_scroll(bw, &zrect);
+ }
+
+ /* if frag_id exists, then try to scroll to it */
+ /** @todo don't do this if the user has scrolled */
+ frag_scroll(bw);
+
+ rect.x0 = scrollbar_get_offset(bw->scroll_x);
+ rect.y0 = scrollbar_get_offset(bw->scroll_y);
+ rect.x1 = rect.x0 + bw->width;
+ rect.y1 = rect.y0 + bw->height;
+
+ browser_window_invalidate_rect(bw, &rect);
+ }
+ break;
+
+ default:
+ case BROWSER_WINDOW_FRAMESET:
+ /* Nothing to do */
+ break;
+ }
+}
+
+
+/**
+ * handle message for content ready on browser window
+ */
+static nserror browser_window_content_ready(struct browser_window *bw)
+{
+ int width, height;
+ nserror res = NSERROR_OK;
+
+ /* close and release the current window content */
+ if (bw->current_content != NULL) {
+ content_close(bw->current_content);
+ hlcache_handle_release(bw->current_content);
+ }
+
+ bw->current_content = bw->loading_content;
+ bw->loading_content = NULL;
+
+ if (!bw->internal_nav) {
+ /* Transfer the fetch parameters */
+ browser_window__free_fetch_parameters(&bw->current_parameters);
+ bw->current_parameters = bw->loading_parameters;
+ memset(&bw->loading_parameters, 0, sizeof(bw->loading_parameters));
+ /* Transfer the certificate chain */
+ cert_chain_free(bw->current_cert_chain);
+ bw->current_cert_chain = bw->loading_cert_chain;
+ bw->loading_cert_chain = NULL;
+ }
+
+ /* Format the new content to the correct dimensions */
+ browser_window_get_dimensions(bw, &width, &height);
+ width /= bw->scale;
+ height /= bw->scale;
+ content_reformat(bw->current_content, false, width, height);
+
+ /* history */
+ if (bw->history_add && bw->history && !bw->internal_nav) {
+ nsurl *url = hlcache_handle_get_url(bw->current_content);
+
+ if (urldb_add_url(url)) {
+ urldb_set_url_title(url, content_get_title(bw->current_content));
+ urldb_update_url_visit_data(url);
+ urldb_set_url_content_type(url,
+ content_get_type(bw->current_content));
+
+ /* This is safe as we've just added the URL */
+ global_history_add(urldb_get_url(url));
+ }
+ /**
+ * \todo Urldb / Thumbnails / Local history brokenness
+ *
+ * We add to local history after calling urldb_add_url rather
+ * than in the block above. If urldb_add_url fails (as it
+ * will for urls like "about:about", "about:config" etc),
+ * there would be no local history node, and later calls to
+ * history_update will either explode or overwrite the node
+ * for the previous URL.
+ *
+ * We call it after, rather than before urldb_add_url because
+ * history_add calls bitmap render, which tries to register
+ * the thumbnail with urldb. That thumbnail registration
+ * fails if the url doesn't exist in urldb already, and only
+ * urldb-registered thumbnails get freed. So if we called
+ * history_add before urldb_add_url we would leak thumbnails
+ * for all newly visited URLs. With the history_add call
+ * after, we only leak the thumbnails when urldb does not add
+ * the URL.
+ *
+ * Also, since browser_window_history_add can create a
+ * thumbnail (content_redraw), we need to do it after
+ * content_reformat.
+ */
+ browser_window_history_add(bw, bw->current_content, bw->frag_id);
+ }
+
+ browser_window_remove_caret(bw, false);
+
+ if (bw->window != NULL) {
+ guit->window->event(bw->window, GW_EVENT_NEW_CONTENT);
+
+ browser_window_refresh_url_bar(bw);
+ }
+
+ /* new content; set scroll_to_top */
+ browser_window_update(bw, true);
+ content_open(bw->current_content, bw, 0, 0);
+ browser_window_set_status(bw, content_get_status_message(bw->current_content));
+
+ /* frames */
+ res = browser_window_create_frameset(bw);
+
+ /* iframes */
+ res = browser_window_create_iframes(bw);
+
+ /* Indicate page status may have changed */
+ if (res == NSERROR_OK) {
+ struct browser_window *root = browser_window_get_root(bw);
+ res = guit->window->event(root->window, GW_EVENT_PAGE_INFO_CHANGE);
+ }
+
+ return res;
+}
+
+
+/**
+ * handle message for content done on browser window
+ */
+static nserror
+browser_window_content_done(struct browser_window *bw)
+{
+ float sx, sy;
+ struct rect rect;
+ int scrollx;
+ int scrolly;
+
+ if (bw->window == NULL) {
+ /* Updated browser window's scrollbars. */
+ /**
+ * \todo update browser window scrollbars before CONTENT_MSG_DONE
+ */
+ browser_window_reformat(bw, true, bw->width, bw->height);
+ browser_window_handle_scrollbars(bw);
+ }
+
+ browser_window_update(bw, false);
+ browser_window_set_status(bw, content_get_status_message(bw->current_content));
+ browser_window_stop_throbber(bw);
+ browser_window_update_favicon(bw->current_content, bw, NULL);
+
+ if (browser_window_history_get_scroll(bw, &sx, &sy) == NSERROR_OK) {
+ scrollx = (int)((float)content_get_width(bw->current_content) * sx);
+ scrolly = (int)((float)content_get_height(bw->current_content) * sy);
+ rect.x0 = rect.x1 = scrollx;
+ rect.y0 = rect.y1 = scrolly;
+ if (browser_window_set_scroll(bw, &rect) != NSERROR_OK) {
+ NSLOG(netsurf, WARNING,
+ "Unable to set browser scroll offsets to %d by %d",
+ scrollx, scrolly);
+ }
+ }
+
+ if (!bw->internal_nav) {
+ browser_window_history_update(bw, bw->current_content);
+ hotlist_update_url(hlcache_handle_get_url(bw->current_content));
+ }
+
+ if (bw->refresh_interval != -1) {
+ guit->misc->schedule(bw->refresh_interval * 10,
+ browser_window_refresh, bw);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Handle query responses from SSL requests
+ */
+static nserror
+browser_window__handle_ssl_query_response(bool proceed, void *pw)
+{
+ struct browser_window *bw = (struct browser_window *)pw;
+
+ /* If we're in the process of loading, stop the load */
+ if (bw->loading_content != NULL) {
+ /* We had a loading content (maybe auth page?) */
+ browser_window_stop(bw);
+ browser_window_remove_caret(bw, false);
+ browser_window_destroy_children(bw);
+ browser_window_destroy_iframes(bw);
+ }
+
+ if (!proceed) {
+ /* We're processing a "back to safety", do a rough-and-ready
+ * nav to the old 'current' parameters, with any post data
+ * stripped away
+ */
+ return browser_window__reload_current_parameters(bw);
+ }
+
+ /* We're processing a "proceed" attempt from the form */
+ /* First, we permit the SSL */
+ urldb_set_cert_permissions(bw->loading_parameters.url, true);
+
+ /* And then we navigate to the original loading parameters */
+ bw->internal_nav = false;
+
+ return browser_window__navigate_internal(bw, &bw->loading_parameters);
+}
+
+
+/**
+ * Unpack a "username:password" to components.
+ *
+ * \param[in] userpass The input string to split.
+ * \param[in] username_out Returns username on success. Owned by caller.
+ * \param[out] password_out Returns password on success. Owned by caller.
+ * \return NSERROR_OK, or appropriate error code.
+ */
+static nserror
+browser_window__unpack_userpass(const char *userpass,
+ char **username_out,
+ char **password_out)
+{
+ const char *tmp;
+ char *username;
+ char *password;
+ size_t len;
+
+ if (userpass == NULL) {
+ username = malloc(1);
+ password = malloc(1);
+ if (username == NULL || password == NULL) {
+ free(username);
+ free(password);
+ return NSERROR_NOMEM;
+ }
+ username[0] = '\0';
+ password[0] = '\0';
+
+ *username_out = username;
+ *password_out = password;
+ return NSERROR_OK;
+ }
+
+ tmp = strchr(userpass, ':');
+ if (tmp == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ } else {
+ size_t len2;
+ len = tmp - userpass;
+ len2 = strlen(++tmp);
+
+ username = malloc(len + 1);
+ password = malloc(len2 + 1);
+ if (username == NULL || password == NULL) {
+ free(username);
+ free(password);
+ return NSERROR_NOMEM;
+ }
+ memcpy(username, userpass, len);
+ username[len] = '\0';
+ memcpy(password, tmp, len2 + 1);
+ }
+
+ *username_out = username;
+ *password_out = password;
+ return NSERROR_OK;
+}
+
+
+/**
+ * Build a "username:password" from components.
+ *
+ * \param[in] username The username component.
+ * \param[in] password The password component.
+ * \param[out] userpass_out Returns combined string on success.
+ * Owned by caller.
+ * \return NSERROR_OK, or appropriate error code.
+ */
+static nserror
+browser_window__build_userpass(const char *username,
+ const char *password,
+ char **userpass_out)
+{
+ char *userpass;
+ size_t len;
+
+ len = strlen(username) + 1 + strlen(password) + 1;
+
+ userpass = malloc(len);
+ if (userpass == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ snprintf(userpass, len, "%s:%s", username, password);
+
+ *userpass_out = userpass;
+ return NSERROR_OK;
+}
+
+
+/**
+ * Handle a response from the UI when prompted for credentials
+ */
+static nserror
+browser_window__handle_userpass_response(nsurl *url,
+ const char *realm,
+ const char *username,
+ const char *password,
+ void *pw)
+{
+ struct browser_window *bw = (struct browser_window *)pw;
+ char *userpass;
+ nserror err;
+
+ err = browser_window__build_userpass(username, password, &userpass);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
+ urldb_set_auth_details(url, realm, userpass);
+
+ free(userpass);
+
+ /**
+ * \todo QUERY - Eventually this should fill out the form *NOT* nav
+ * to the original location
+ */
+ /* Finally navigate to the original loading parameters */
+ if (bw->loading_content != NULL) {
+ /* We had a loading content (maybe auth page?) */
+ browser_window_stop(bw);
+ browser_window_remove_caret(bw, false);
+ browser_window_destroy_children(bw);
+ browser_window_destroy_iframes(bw);
+ }
+ bw->internal_nav = false;
+ return browser_window__navigate_internal(bw, &bw->loading_parameters);
+}
+
+
+/**
+ * Handle login request (BAD_AUTH) during fetch
+ *
+ */
+static nserror
+browser_window__handle_login(struct browser_window *bw,
+ const char *realm,
+ nsurl *url) {
+ char *username = NULL, *password = NULL;
+ nserror err = NSERROR_OK;
+ struct browser_fetch_parameters params;
+
+ memset(&params, 0, sizeof(params));
+
+ /* Step one, retrieve what we have */
+ err = browser_window__unpack_userpass(
+ urldb_get_auth_details(url, realm),
+ &username, &password);
+ if (err != NSERROR_OK) {
+ goto out;
+ }
+
+ /* Step two, construct our fetch parameters */
+ params.url = nsurl_ref(corestring_nsurl_about_query_auth);
+ params.referrer = nsurl_ref(url);
+ params.flags = BW_NAVIGATE_HISTORY | BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE | BW_NAVIGATE_INTERNAL;
+
+ err = fetch_multipart_data_new_kv(&params.post_multipart,
+ "siteurl",
+ nsurl_access(url));
+ if (err != NSERROR_OK) {
+ goto out;
+ }
+
+ err = fetch_multipart_data_new_kv(&params.post_multipart,
+ "realm",
+ realm);
+ if (err != NSERROR_OK) {
+ goto out;
+ }
+
+ err = fetch_multipart_data_new_kv(&params.post_multipart,
+ "username",
+ username);
+ if (err != NSERROR_OK) {
+ goto out;
+ }
+
+ err = fetch_multipart_data_new_kv(&params.post_multipart,
+ "password",
+ password);
+ if (err != NSERROR_OK) {
+ goto out;
+ }
+
+ /* Now we issue the fetch */
+ bw->internal_nav = true;
+ err = browser_window__navigate_internal(bw, &params);
+
+ if (err != NSERROR_OK) {
+ goto out;
+ }
+
+ err = guit->misc->login(url, realm, username, password,
+ browser_window__handle_userpass_response, bw);
+
+ if (err == NSERROR_NOT_IMPLEMENTED) {
+ err = NSERROR_OK;
+ }
+ out:
+ if (username != NULL) {
+ free(username);
+ }
+ if (password != NULL) {
+ free(password);
+ }
+ browser_window__free_fetch_parameters(&params);
+ return err;
+}
+
+
+/**
+ * Handle a certificate verification request (BAD_CERTS) during a fetch
+ */
+static nserror
+browser_window__handle_bad_certs(struct browser_window *bw,
+ nsurl *url)
+{
+ struct browser_fetch_parameters params;
+ nserror err;
+ /* Initially we don't know WHY the SSL cert was bad */
+ const char *reason = messages_get_sslcode(SSL_CERT_ERR_UNKNOWN);
+ size_t depth;
+ nsurl *chainurl = NULL;
+
+ memset(&params, 0, sizeof(params));
+
+ params.url = nsurl_ref(corestring_nsurl_about_query_ssl);
+ params.referrer = nsurl_ref(url);
+ params.flags = BW_NAVIGATE_HISTORY | BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE | BW_NAVIGATE_INTERNAL;
+
+ err = fetch_multipart_data_new_kv(&params.post_multipart,
+ "siteurl",
+ nsurl_access(url));
+ if (err != NSERROR_OK) {
+ goto out;
+ }
+
+ if (bw->loading_cert_chain != NULL) {
+ for (depth = 0; depth < bw->loading_cert_chain->depth; ++depth) {
+ size_t idx = bw->loading_cert_chain->depth - (depth + 1);
+ ssl_cert_err err = bw->loading_cert_chain->certs[idx].err;
+ if (err != SSL_CERT_ERR_OK) {
+ reason = messages_get_sslcode(err);
+ break;
+ }
+ }
+
+ err = cert_chain_to_query(bw->loading_cert_chain, &chainurl);
+ if (err != NSERROR_OK) {
+ goto out;
+ }
+
+ err = fetch_multipart_data_new_kv(&params.post_multipart,
+ "chainurl",
+ nsurl_access(chainurl));
+ if (err != NSERROR_OK) {
+ goto out;
+ }
+ }
+
+ err = fetch_multipart_data_new_kv(&params.post_multipart,
+ "reason",
+ reason);
+ if (err != NSERROR_OK) {
+ goto out;
+ }
+
+ /* Now we issue the fetch */
+ bw->internal_nav = true;
+ err = browser_window__navigate_internal(bw, &params);
+ if (err != NSERROR_OK) {
+ goto out;
+ }
+
+ out:
+ browser_window__free_fetch_parameters(&params);
+ if (chainurl != NULL)
+ nsurl_unref(chainurl);
+ return err;
+}
+
+
+/**
+ * Handle a timeout during a fetch
+ */
+static nserror
+browser_window__handle_timeout(struct browser_window *bw, nsurl *url)
+{
+ struct browser_fetch_parameters params;
+ nserror err;
+
+ memset(&params, 0, sizeof(params));
+
+ params.url = nsurl_ref(corestring_nsurl_about_query_timeout);
+ params.referrer = nsurl_ref(url);
+ params.flags = BW_NAVIGATE_HISTORY | BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE | BW_NAVIGATE_INTERNAL;
+
+ err = fetch_multipart_data_new_kv(&params.post_multipart,
+ "siteurl",
+ nsurl_access(url));
+ if (err != NSERROR_OK) {
+ goto out;
+ }
+
+ /* Now we issue the fetch */
+ bw->internal_nav = true;
+ err = browser_window__navigate_internal(bw, &params);
+ if (err != NSERROR_OK) {
+ goto out;
+ }
+
+ out:
+ browser_window__free_fetch_parameters(&params);
+ return err;
+}
+
+
+/**
+ * Handle non specific errors during a fetch
+ */
+static nserror
+browser_window__handle_fetcherror(struct browser_window *bw,
+ const char *reason,
+ nsurl *url)
+{
+ struct browser_fetch_parameters params;
+ nserror err;
+
+ memset(&params, 0, sizeof(params));
+
+ params.url = nsurl_ref(corestring_nsurl_about_query_fetcherror);
+ params.referrer = nsurl_ref(url);
+ params.flags = BW_NAVIGATE_HISTORY | BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE | BW_NAVIGATE_INTERNAL;
+
+ err = fetch_multipart_data_new_kv(&params.post_multipart,
+ "siteurl",
+ nsurl_access(url));
+ if (err != NSERROR_OK) {
+ goto out;
+ }
+
+ err = fetch_multipart_data_new_kv(&params.post_multipart,
+ "reason",
+ reason);
+ if (err != NSERROR_OK) {
+ goto out;
+ }
+
+ /* Now we issue the fetch */
+ bw->internal_nav = true;
+ err = browser_window__navigate_internal(bw, &params);
+ if (err != NSERROR_OK) {
+ goto out;
+ }
+
+ out:
+ browser_window__free_fetch_parameters(&params);
+ return err;
+}
+
+
+/**
+ * Handle errors during content fetch
+ */
+static nserror
+browser_window__handle_error(struct browser_window *bw,
+ hlcache_handle *c,
+ const hlcache_event *event)
+{
+ const char *message = event->data.errordata.errormsg;
+ nserror code = event->data.errordata.errorcode;
+ nserror res;
+ nsurl *url = hlcache_handle_get_url(c);
+
+ /* Unexpected OK? */
+ assert(code != NSERROR_OK);
+
+ if (message == NULL) {
+ message = messages_get_errorcode(code);
+ } else {
+ message = messages_get(message);
+ }
+
+ if (c == bw->loading_content) {
+ bw->loading_content = NULL;
+ } else if (c == bw->current_content) {
+ bw->current_content = NULL;
+ browser_window_remove_caret(bw, false);
+ }
+
+ hlcache_handle_release(c);
+
+ switch (code) {
+ case NSERROR_BAD_AUTH:
+ res = browser_window__handle_login(bw, message, url);
+ break;
+
+ case NSERROR_BAD_CERTS:
+ res = browser_window__handle_bad_certs(bw, url);
+ break;
+
+ case NSERROR_TIMEOUT:
+ res = browser_window__handle_timeout(bw, url);
+ break;
+
+ default:
+ res = browser_window__handle_fetcherror(bw, message, url);
+ break;
+ }
+
+ return res;
+}
+
+
+/**
+ * Update URL bar for a given browser window to given URL
+ *
+ * \param bw Browser window to update URL bar for.
+ * \param url URL for content displayed by bw including any fragment.
+ */
+static inline nserror
+browser_window_refresh_url_bar_internal(struct browser_window *bw, nsurl *url)
+{
+ assert(bw);
+ assert(url);
+
+ if ((bw->parent != NULL) || (bw->window == NULL)) {
+ /* Not root window or no gui window so do not set a URL */
+ return NSERROR_OK;
+ }
+
+ return guit->window->set_url(bw->window, url);
+}
+
+
+/**
+ * Browser window content event callback handler.
+ */
+static nserror
+browser_window_callback(hlcache_handle *c, const hlcache_event *event, void *pw)
+{
+ struct browser_window *bw = pw;
+ nserror res = NSERROR_OK;
+
+ switch (event->type) {
+ case CONTENT_MSG_SSL_CERTS:
+ /* SSL certificate information has arrived, store it */
+ cert_chain_free(bw->loading_cert_chain);
+ cert_chain_dup(event->data.chain, &bw->loading_cert_chain);
+ break;
+
+ case CONTENT_MSG_LOG:
+ browser_window_console_log(bw,
+ event->data.log.src,
+ event->data.log.msg,
+ event->data.log.msglen,
+ event->data.log.flags);
+ break;
+
+ case CONTENT_MSG_DOWNLOAD:
+ assert(bw->loading_content == c);
+
+ browser_window_convert_to_download(bw, event->data.download);
+
+ if (bw->current_content != NULL) {
+ browser_window_refresh_url_bar(bw);
+ }
+ break;
+
+ case CONTENT_MSG_LOADING:
+ assert(bw->loading_content == c);
+
+#ifdef WITH_THEME_INSTALL
+ if (content_get_type(c) == CONTENT_THEME) {
+ theme_install_start(c);
+ bw->loading_content = NULL;
+ browser_window_stop_throbber(bw);
+ } else
+#endif
+ {
+ bw->refresh_interval = -1;
+ browser_window_set_status(bw,
+ content_get_status_message(c));
+ }
+ break;
+
+ case CONTENT_MSG_READY:
+ assert(bw->loading_content == c);
+
+ res = browser_window_content_ready(bw);
+ break;
+
+ case CONTENT_MSG_DONE:
+ assert(bw->current_content == c);
+
+ res = browser_window_content_done(bw);
+ break;
+
+ case CONTENT_MSG_ERROR:
+ res = browser_window__handle_error(bw, c, event);
+ break;
+
+ case CONTENT_MSG_REDIRECT:
+ if (urldb_add_url(event->data.redirect.from)) {
+ urldb_update_url_visit_data(event->data.redirect.from);
+ }
+ browser_window_refresh_url_bar_internal(bw, event->data.redirect.to);
+ break;
+
+ case CONTENT_MSG_STATUS:
+ if (event->data.explicit_status_text == NULL) {
+ /* Object content's status text updated */
+ const char *status = NULL;
+ if (bw->loading_content != NULL) {
+ /* Give preference to any loading content */
+ status = content_get_status_message(
+ bw->loading_content);
+ }
+
+ if (status == NULL) {
+ status = content_get_status_message(c);
+ }
+
+ if (status != NULL) {
+ browser_window_set_status(bw, status);
+ }
+ } else {
+ /* Object content wants to set explicit message */
+ browser_window_set_status(bw,
+ event->data.explicit_status_text);
+ }
+ break;
+
+ case CONTENT_MSG_REFORMAT:
+ if (c == bw->current_content) {
+ /* recompute frameset */
+ browser_window_recalculate_frameset(bw);
+
+ /* recompute iframe positions, sizes and scrollbars */
+ browser_window_recalculate_iframes(bw);
+ }
+
+ /* Hide any caret, but don't remove it */
+ browser_window_remove_caret(bw, true);
+
+ if (!(event->data.background)) {
+ /* Reformatted content should be redrawn */
+ browser_window_update(bw, false);
+ }
+ break;
+
+ case CONTENT_MSG_REDRAW:
+ {
+ struct rect rect = {
+ .x0 = event->data.redraw.x,
+ .y0 = event->data.redraw.y,
+ .x1 = event->data.redraw.x + event->data.redraw.width,
+ .y1 = event->data.redraw.y + event->data.redraw.height
+ };
+
+ browser_window_invalidate_rect(bw, &rect);
+ }
+ break;
+
+ case CONTENT_MSG_REFRESH:
+ bw->refresh_interval = event->data.delay * 100;
+ break;
+
+ case CONTENT_MSG_LINK: /* content has an rfc5988 link element */
+ {
+ bool match;
+
+ /* Handle "icon" and "shortcut icon" */
+ if ((lwc_string_caseless_isequal(
+ event->data.rfc5988_link->rel,
+ corestring_lwc_icon,
+ &match) == lwc_error_ok && match) ||
+ (lwc_string_caseless_isequal(
+ event->data.rfc5988_link->rel,
+ corestring_lwc_shortcut_icon,
+ &match) == lwc_error_ok && match)) {
+ /* it's a favicon perhaps start a fetch for it */
+ browser_window_update_favicon(c, bw,
+ event->data.rfc5988_link);
+ }
+ }
+ break;
+
+ case CONTENT_MSG_GETTHREAD:
+ {
+ /* only the content object created by the browser
+ * window requires a new javascript thread object
+ */
+ jsthread *thread;
+ assert(bw->loading_content == c);
+
+ if (js_newthread(bw->jsheap,
+ bw,
+ hlcache_handle_get_content(c),
+ &thread) == NSERROR_OK) {
+ /* The content which is requesting the thread
+ * is required to keep hold of it and
+ * to destroy it when it is finished with it.
+ */
+ *(event->data.jsthread) = thread;
+ }
+ }
+ break;
+
+ case CONTENT_MSG_GETDIMS:
+ {
+ int width;
+ int height;
+
+ browser_window_get_dimensions(bw, &width, &height);
+
+ *(event->data.getdims.viewport_width) = width / bw->scale;
+ *(event->data.getdims.viewport_height) = height / bw->scale;
+ break;
+ }
+
+ case CONTENT_MSG_SCROLL:
+ {
+ struct rect rect = {
+ .x0 = event->data.scroll.x0,
+ .y0 = event->data.scroll.y0,
+ };
+
+ /* Content wants to be scrolled */
+ if (bw->current_content != c) {
+ break;
+ }
+
+ if (event->data.scroll.area) {
+ rect.x1 = event->data.scroll.x1;
+ rect.y1 = event->data.scroll.y1;
+ } else {
+ rect.x1 = event->data.scroll.x0;
+ rect.y1 = event->data.scroll.y0;
+ }
+ browser_window_set_scroll(bw, &rect);
+
+ break;
+ }
+
+ case CONTENT_MSG_DRAGSAVE:
+ {
+ /* Content wants drag save of a content */
+ struct browser_window *root = browser_window_get_root(bw);
+ hlcache_handle *save = event->data.dragsave.content;
+
+ if (save == NULL) {
+ save = c;
+ }
+
+ switch(event->data.dragsave.type) {
+ case CONTENT_SAVE_ORIG:
+ guit->window->drag_save_object(root->window,
+ save,
+ GUI_SAVE_OBJECT_ORIG);
+ break;
+
+ case CONTENT_SAVE_NATIVE:
+ guit->window->drag_save_object(root->window,
+ save,
+ GUI_SAVE_OBJECT_NATIVE);
+ break;
+
+ case CONTENT_SAVE_COMPLETE:
+ guit->window->drag_save_object(root->window,
+ save,
+ GUI_SAVE_COMPLETE);
+ break;
+
+ case CONTENT_SAVE_SOURCE:
+ guit->window->drag_save_object(root->window,
+ save,
+ GUI_SAVE_SOURCE);
+ break;
+ }
+ }
+ break;
+
+ case CONTENT_MSG_SAVELINK:
+ {
+ /* Content wants a link to be saved */
+ struct browser_window *root = browser_window_get_root(bw);
+ guit->window->save_link(root->window,
+ event->data.savelink.url,
+ event->data.savelink.title);
+ }
+ break;
+
+ case CONTENT_MSG_POINTER:
+ /* Content wants to have specific mouse pointer */
+ browser_window_set_pointer(bw, event->data.pointer);
+ break;
+
+ case CONTENT_MSG_DRAG:
+ {
+ browser_drag_type bdt = DRAGGING_NONE;
+
+ switch (event->data.drag.type) {
+ case CONTENT_DRAG_NONE:
+ bdt = DRAGGING_NONE;
+ break;
+ case CONTENT_DRAG_SCROLL:
+ bdt = DRAGGING_CONTENT_SCROLLBAR;
+ break;
+ case CONTENT_DRAG_SELECTION:
+ bdt = DRAGGING_SELECTION;
+ break;
+ }
+ browser_window_set_drag_type(bw, bdt, event->data.drag.rect);
+ }
+ break;
+
+ case CONTENT_MSG_CARET:
+ switch (event->data.caret.type) {
+ case CONTENT_CARET_REMOVE:
+ browser_window_remove_caret(bw, false);
+ break;
+ case CONTENT_CARET_HIDE:
+ browser_window_remove_caret(bw, true);
+ break;
+ case CONTENT_CARET_SET_POS:
+ browser_window_place_caret(bw,
+ event->data.caret.pos.x,
+ event->data.caret.pos.y,
+ event->data.caret.pos.height,
+ event->data.caret.pos.clip);
+ break;
+ }
+ break;
+
+ case CONTENT_MSG_SELECTION:
+ browser_window_set_selection(bw,
+ event->data.selection.selection,
+ event->data.selection.read_only);
+ break;
+
+ case CONTENT_MSG_SELECTMENU:
+ if (event->data.select_menu.gadget->type == GADGET_SELECT) {
+ struct browser_window *root =
+ browser_window_get_root(bw);
+ guit->window->create_form_select_menu(root->window,
+ event->data.select_menu.gadget);
+ }
+
+ break;
+
+ case CONTENT_MSG_GADGETCLICK:
+ if (event->data.gadget_click.gadget->type == GADGET_FILE) {
+ struct browser_window *root =
+ browser_window_get_root(bw);
+ guit->window->file_gadget_open(root->window, c,
+ event->data.gadget_click.gadget);
+ }
+
+ break;
+
+
+ case CONTENT_MSG_TEXTSEARCH:
+ switch (event->data.textsearch.type) {
+ case CONTENT_TEXTSEARCH_FIND:
+ guit->search->hourglass(event->data.textsearch.state,
+ event->data.textsearch.ctx);
+ break;
+
+ case CONTENT_TEXTSEARCH_MATCH:
+ guit->search->status(event->data.textsearch.state,
+ event->data.textsearch.ctx);
+ break;
+
+ case CONTENT_TEXTSEARCH_BACK:
+ guit->search->back_state(event->data.textsearch.state,
+ event->data.textsearch.ctx);
+ break;
+
+ case CONTENT_TEXTSEARCH_FORWARD:
+ guit->search->forward_state(event->data.textsearch.state,
+ event->data.textsearch.ctx);
+ break;
+
+ case CONTENT_TEXTSEARCH_RECENT:
+ guit->search->add_recent(event->data.textsearch.string,
+ event->data.textsearch.ctx);
+
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return res;
+}
+
+
+/**
+ * internal scheduled reformat callback.
+ *
+ * scheduled reformat callback to allow reformats from unthreaded context.
+ *
+ * \param vbw The browser window to be reformatted
+ */
+static void scheduled_reformat(void *vbw)
+{
+ struct browser_window *bw = vbw;
+ int width;
+ int height;
+ nserror res;
+
+ res = guit->window->get_dimensions(bw->window, &width, &height);
+ if (res == NSERROR_OK) {
+ browser_window_reformat(bw, false, width, height);
+ }
+}
+
+/* exported interface documented in desktop/browser_private.h */
+nserror browser_window_destroy_internal(struct browser_window *bw)
+{
+ assert(bw);
+
+ browser_window_destroy_children(bw);
+ browser_window_destroy_iframes(bw);
+
+ /* Destroy scrollbars */
+ if (bw->scroll_x != NULL) {
+ scrollbar_destroy(bw->scroll_x);
+ }
+
+ if (bw->scroll_y != NULL) {
+ scrollbar_destroy(bw->scroll_y);
+ }
+
+ /* clear any pending callbacks */
+ guit->misc->schedule(-1, browser_window_refresh, bw);
+ NSLOG(netsurf, INFO,
+ "Clearing reformat schedule for browser window %p", bw);
+ guit->misc->schedule(-1, scheduled_reformat, bw);
+
+ /* If this brower window is not the root window, and has focus, unset
+ * the root browser window's focus pointer. */
+ if (!bw->window) {
+ struct browser_window *top = browser_window_get_root(bw);
+
+ if (top->focus == bw)
+ top->focus = top;
+
+ if (top->selection.bw == bw) {
+ browser_window_set_selection(top, false, false);
+ }
+ }
+
+ /* Destruction order is important: we must ensure that the frontend
+ * destroys any window(s) associated with this browser window before
+ * we attempt any destructive cleanup.
+ */
+
+ if (bw->window) {
+ /* Only the root window has a GUI window */
+ guit->window->destroy(bw->window);
+ }
+
+ if (bw->loading_content != NULL) {
+ hlcache_handle_abort(bw->loading_content);
+ hlcache_handle_release(bw->loading_content);
+ bw->loading_content = NULL;
+ }
+
+ if (bw->current_content != NULL) {
+ content_close(bw->current_content);
+ hlcache_handle_release(bw->current_content);
+ bw->current_content = NULL;
+ }
+
+ if (bw->favicon.loading != NULL) {
+ hlcache_handle_abort(bw->favicon.loading);
+ hlcache_handle_release(bw->favicon.loading);
+ bw->favicon.loading = NULL;
+ }
+
+ if (bw->favicon.current != NULL) {
+ content_close(bw->favicon.current);
+ hlcache_handle_release(bw->favicon.current);
+ bw->favicon.current = NULL;
+ }
+
+ if (bw->jsheap != NULL) {
+ js_destroyheap(bw->jsheap);
+ bw->jsheap = NULL;
+ }
+
+ /* These simply free memory, so are safe here */
+
+ if (bw->frag_id != NULL) {
+ lwc_string_unref(bw->frag_id);
+ }
+
+ browser_window_history_destroy(bw);
+
+ cert_chain_free(bw->current_cert_chain);
+ cert_chain_free(bw->loading_cert_chain);
+ bw->current_cert_chain = NULL;
+ bw->loading_cert_chain = NULL;
+
+ free(bw->name);
+ free(bw->status.text);
+ bw->status.text = NULL;
+ browser_window__free_fetch_parameters(&bw->current_parameters);
+ browser_window__free_fetch_parameters(&bw->loading_parameters);
+ NSLOG(netsurf, INFO, "Status text cache match:miss %d:%d",
+ bw->status.match, bw->status.miss);
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Set browser window scale.
+ *
+ * \param bw Browser window.
+ * \param absolute scale value.
+ * \return NSERROR_OK on success else error code
+ */
+static nserror
+browser_window_set_scale_internal(struct browser_window *bw, float scale)
+{
+ int i;
+ nserror res = NSERROR_OK;
+
+ /* do not apply tiny changes in scale */
+ if (fabs(bw->scale - scale) < 0.0001)
+ return res;
+
+ bw->scale = scale;
+
+ if (bw->current_content != NULL) {
+ if (content_can_reformat(bw->current_content) == false) {
+ browser_window_update(bw, false);
+ } else {
+ res = browser_window_schedule_reformat(bw);
+ }
+ }
+
+ /* scale frames */
+ for (i = 0; i < (bw->cols * bw->rows); i++) {
+ res = browser_window_set_scale_internal(&bw->children[i], scale);
+ }
+
+ /* scale iframes */
+ for (i = 0; i < bw->iframe_count; i++) {
+ res = browser_window_set_scale_internal(&bw->iframes[i], scale);
+ }
+
+ return res;
+}
+
+
+/**
+ * Find browser window.
+ *
+ * \param bw Browser window.
+ * \param target Name of target.
+ * \param depth Depth to scan.
+ * \param page The browser window page.
+ * \param rdepth The rdepth.
+ * \param bw_target the output browser window.
+ */
+static void
+browser_window_find_target_internal(struct browser_window *bw,
+ const char *target,
+ int depth,
+ struct browser_window *page,
+ int *rdepth,
+ struct browser_window **bw_target)
+{
+ int i;
+
+ if ((bw->name) && (!strcasecmp(bw->name, target))) {
+ if ((bw == page) || (depth > *rdepth)) {
+ *rdepth = depth;
+ *bw_target = bw;
+ }
+ }
+
+ if ((!bw->children) && (!bw->iframes))
+ return;
+
+ depth++;
+
+ if (bw->children != NULL) {
+ for (i = 0; i < (bw->cols * bw->rows); i++) {
+ if ((bw->children[i].name) &&
+ (!strcasecmp(bw->children[i].name,
+ target))) {
+ if ((page == &bw->children[i]) ||
+ (depth > *rdepth)) {
+ *rdepth = depth;
+ *bw_target = &bw->children[i];
+ }
+ }
+ if (bw->children[i].children)
+ browser_window_find_target_internal(
+ &bw->children[i],
+ target, depth, page,
+ rdepth, bw_target);
+ }
+ }
+
+ if (bw->iframes != NULL) {
+ for (i = 0; i < bw->iframe_count; i++) {
+ browser_window_find_target_internal(&bw->iframes[i],
+ target,
+ depth,
+ page,
+ rdepth,
+ bw_target);
+ }
+ }
+}
+
+
+/**
+ * Handles the end of a drag operation in a browser window.
+ *
+ * \param bw browser window
+ * \param mouse state of mouse buttons and modifier keys
+ * \param x coordinate of mouse
+ * \param y coordinate of mouse
+ *
+ * \todo Remove this function, once these things are associated with content,
+ * rather than bw.
+ */
+static void
+browser_window_mouse_drag_end(struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ int scr_x, scr_y;
+
+ switch (bw->drag.type) {
+ case DRAGGING_SELECTION:
+ case DRAGGING_OTHER:
+ case DRAGGING_CONTENT_SCROLLBAR:
+ /* Drag handled by content handler */
+ break;
+
+ case DRAGGING_SCR_X:
+
+ browser_window_get_scrollbar_pos(bw, true, &scr_x, &scr_y);
+
+ scr_x = x - scr_x - scrollbar_get_offset(bw->scroll_x);
+ scr_y = y - scr_y - scrollbar_get_offset(bw->scroll_y);
+
+ scrollbar_mouse_drag_end(bw->scroll_x, mouse, scr_x, scr_y);
+
+ bw->drag.type = DRAGGING_NONE;
+ break;
+
+ case DRAGGING_SCR_Y:
+
+ browser_window_get_scrollbar_pos(bw, false, &scr_x, &scr_y);
+
+ scr_x = x - scr_x - scrollbar_get_offset(bw->scroll_x);
+ scr_y = y - scr_y - scrollbar_get_offset(bw->scroll_y);
+
+ scrollbar_mouse_drag_end(bw->scroll_y, mouse, scr_x, scr_y);
+
+ bw->drag.type = DRAGGING_NONE;
+ break;
+
+ default:
+ browser_window_set_drag_type(bw, DRAGGING_NONE, NULL);
+ break;
+ }
+}
+
+/**
+ * Process mouse click event
+ *
+ * \param bw The browsing context receiving the event
+ * \param mouse The mouse event state
+ * \param x The scaled x co-ordinate of the event
+ * \param y The scaled y co-ordinate of the event
+ */
+static void
+browser_window_mouse_click_internal(struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ hlcache_handle *c = bw->current_content;
+ const char *status = NULL;
+ browser_pointer_shape pointer = BROWSER_POINTER_DEFAULT;
+
+ if (bw->children) {
+ /* Browser window has children (frames) */
+ struct browser_window *child;
+ int cur_child;
+ int children = bw->rows * bw->cols;
+
+ for (cur_child = 0; cur_child < children; cur_child++) {
+
+ child = &bw->children[cur_child];
+
+ if ((x < child->x) ||
+ (y < child->y) ||
+ (child->x + child->width < x) ||
+ (child->y + child->height < y)) {
+ /* Click not in this child */
+ continue;
+ }
+
+ /* It's this child that contains the click; pass it
+ * on to child. */
+ browser_window_mouse_click_internal(
+ child,
+ mouse,
+ x - child->x + scrollbar_get_offset(child->scroll_x),
+ y - child->y + scrollbar_get_offset(child->scroll_y));
+
+ /* Mouse action was for this child, we're done */
+ return;
+ }
+
+ return;
+ }
+
+ if (!c)
+ return;
+
+ if (bw->scroll_x != NULL) {
+ int scr_x, scr_y;
+ browser_window_get_scrollbar_pos(bw, true, &scr_x, &scr_y);
+ scr_x = x - scr_x - scrollbar_get_offset(bw->scroll_x);
+ scr_y = y - scr_y - scrollbar_get_offset(bw->scroll_y);
+
+ if (scr_x > 0 && scr_x < get_horz_scrollbar_len(bw) &&
+ scr_y > 0 && scr_y < SCROLLBAR_WIDTH) {
+ status = scrollbar_mouse_status_to_message(
+ scrollbar_mouse_action(
+ bw->scroll_x, mouse,
+ scr_x, scr_y));
+ pointer = BROWSER_POINTER_DEFAULT;
+
+ if (status != NULL)
+ browser_window_set_status(bw, status);
+
+ browser_window_set_pointer(bw, pointer);
+ return;
+ }
+ }
+
+ if (bw->scroll_y != NULL) {
+ int scr_x, scr_y;
+ browser_window_get_scrollbar_pos(bw, false, &scr_x, &scr_y);
+ scr_x = x - scr_x - scrollbar_get_offset(bw->scroll_x);
+ scr_y = y - scr_y - scrollbar_get_offset(bw->scroll_y);
+
+ if (scr_y > 0 && scr_y < get_vert_scrollbar_len(bw) &&
+ scr_x > 0 && scr_x < SCROLLBAR_WIDTH) {
+ status = scrollbar_mouse_status_to_message(
+ scrollbar_mouse_action(
+ bw->scroll_y,
+ mouse,
+ scr_x,
+ scr_y));
+ pointer = BROWSER_POINTER_DEFAULT;
+
+ if (status != NULL) {
+ browser_window_set_status(bw, status);
+ }
+
+ browser_window_set_pointer(bw, pointer);
+ return;
+ }
+ }
+
+ switch (content_get_type(c)) {
+ case CONTENT_HTML:
+ case CONTENT_TEXTPLAIN:
+ {
+ /* Give bw focus */
+ struct browser_window *root_bw = browser_window_get_root(bw);
+ if (bw != root_bw->focus) {
+ browser_window_remove_caret(bw, false);
+ browser_window_set_selection(bw, false, true);
+ root_bw->focus = bw;
+ }
+
+ /* Pass mouse action to content */
+ content_mouse_action(c, bw, mouse, x, y);
+ }
+ break;
+ default:
+ if (mouse & BROWSER_MOUSE_MOD_2) {
+ if (mouse & BROWSER_MOUSE_DRAG_2) {
+ guit->window->drag_save_object(bw->window, c,
+ GUI_SAVE_OBJECT_NATIVE);
+ } else if (mouse & BROWSER_MOUSE_DRAG_1) {
+ guit->window->drag_save_object(bw->window, c,
+ GUI_SAVE_OBJECT_ORIG);
+ }
+ } else if (mouse & (BROWSER_MOUSE_DRAG_1 |
+ BROWSER_MOUSE_DRAG_2)) {
+ browser_window_page_drag_start(bw, x, y);
+ browser_window_set_pointer(bw, BROWSER_POINTER_MOVE);
+ }
+ break;
+ }
+}
+
+
+/**
+ * Process mouse movement event
+ *
+ * \param bw The browsing context receiving the event
+ * \param mouse The mouse event state
+ * \param x The scaled x co-ordinate of the event
+ * \param y The scaled y co-ordinate of the event
+ */
+static void
+browser_window_mouse_track_internal(struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ hlcache_handle *c = bw->current_content;
+ const char *status = NULL;
+ browser_pointer_shape pointer = BROWSER_POINTER_DEFAULT;
+
+ if (bw->window != NULL && bw->drag.window && bw != bw->drag.window) {
+ /* This is the root browser window and there's an active drag
+ * in a sub window.
+ * Pass the mouse action straight on to that bw. */
+ struct browser_window *drag_bw = bw->drag.window;
+ int off_x = 0;
+ int off_y = 0;
+
+ browser_window_get_position(drag_bw, true, &off_x, &off_y);
+
+ if (drag_bw->browser_window_type == BROWSER_WINDOW_FRAME) {
+ browser_window_mouse_track_internal(drag_bw,
+ mouse,
+ x - off_x,
+ y - off_y);
+
+ } else if (drag_bw->browser_window_type == BROWSER_WINDOW_IFRAME) {
+ browser_window_mouse_track_internal(drag_bw, mouse,
+ x - off_x / bw->scale,
+ y - off_y / bw->scale);
+ }
+ return;
+ }
+
+ if (bw->children) {
+ /* Browser window has children (frames) */
+ struct browser_window *child;
+ int cur_child;
+ int children = bw->rows * bw->cols;
+
+ for (cur_child = 0; cur_child < children; cur_child++) {
+
+ child = &bw->children[cur_child];
+
+ if ((x < child->x) ||
+ (y < child->y) ||
+ (child->x + child->width < x) ||
+ (child->y + child->height < y)) {
+ /* Click not in this child */
+ continue;
+ }
+
+ /* It's this child that contains the mouse; pass
+ * mouse action on to child */
+ browser_window_mouse_track_internal(
+ child,
+ mouse,
+ x - child->x + scrollbar_get_offset(child->scroll_x),
+ y - child->y + scrollbar_get_offset(child->scroll_y));
+
+ /* Mouse action was for this child, we're done */
+ return;
+ }
+
+ /* Odd if we reached here, but nothing else can use the click
+ * when there are children. */
+ return;
+ }
+
+ if (c == NULL && bw->drag.type != DRAGGING_FRAME) {
+ return;
+ }
+
+ if (bw->drag.type != DRAGGING_NONE && !mouse) {
+ browser_window_mouse_drag_end(bw, mouse, x, y);
+ }
+
+ /* Browser window's horizontal scrollbar */
+ if (bw->scroll_x != NULL && bw->drag.type != DRAGGING_SCR_Y) {
+ int scr_x, scr_y;
+ browser_window_get_scrollbar_pos(bw, true, &scr_x, &scr_y);
+ scr_x = x - scr_x - scrollbar_get_offset(bw->scroll_x);
+ scr_y = y - scr_y - scrollbar_get_offset(bw->scroll_y);
+
+ if ((bw->drag.type == DRAGGING_SCR_X) ||
+ (scr_x > 0 &&
+ scr_x < get_horz_scrollbar_len(bw) &&
+ scr_y > 0 &&
+ scr_y < SCROLLBAR_WIDTH &&
+ bw->drag.type == DRAGGING_NONE)) {
+ /* Start a scrollbar drag, or continue existing drag */
+ status = scrollbar_mouse_status_to_message(
+ scrollbar_mouse_action(bw->scroll_x,
+ mouse,
+ scr_x,
+ scr_y));
+ pointer = BROWSER_POINTER_DEFAULT;
+
+ if (status != NULL) {
+ browser_window_set_status(bw, status);
+ }
+
+ browser_window_set_pointer(bw, pointer);
+ return;
+ }
+ }
+
+ /* Browser window's vertical scrollbar */
+ if (bw->scroll_y != NULL) {
+ int scr_x, scr_y;
+ browser_window_get_scrollbar_pos(bw, false, &scr_x, &scr_y);
+ scr_x = x - scr_x - scrollbar_get_offset(bw->scroll_x);
+ scr_y = y - scr_y - scrollbar_get_offset(bw->scroll_y);
+
+ if ((bw->drag.type == DRAGGING_SCR_Y) ||
+ (scr_y > 0 &&
+ scr_y < get_vert_scrollbar_len(bw) &&
+ scr_x > 0 &&
+ scr_x < SCROLLBAR_WIDTH &&
+ bw->drag.type == DRAGGING_NONE)) {
+ /* Start a scrollbar drag, or continue existing drag */
+ status = scrollbar_mouse_status_to_message(
+ scrollbar_mouse_action(bw->scroll_y,
+ mouse,
+ scr_x,
+ scr_y));
+ pointer = BROWSER_POINTER_DEFAULT;
+
+ if (status != NULL) {
+ browser_window_set_status(bw, status);
+ }
+
+ browser_window_set_pointer(bw, pointer);
+ return;
+ }
+ }
+
+ if (bw->drag.type == DRAGGING_FRAME) {
+ browser_window_resize_frame(bw, bw->x + x, bw->y + y);
+ } else if (bw->drag.type == DRAGGING_PAGE_SCROLL) {
+ /* mouse movement since drag started */
+ struct rect rect;
+
+ rect.x0 = bw->drag.start_x - x;
+ rect.y0 = bw->drag.start_y - y;
+
+ /* new scroll offsets */
+ rect.x0 += bw->drag.start_scroll_x;
+ rect.y0 += bw->drag.start_scroll_y;
+
+ bw->drag.start_scroll_x = rect.x1 = rect.x0;
+ bw->drag.start_scroll_y = rect.y1 = rect.y0;
+
+ browser_window_set_scroll(bw, &rect);
+ } else {
+ assert(c != NULL);
+ content_mouse_track(c, bw, mouse, x, y);
+ }
+}
+
+
+/**
+ * perform a scroll operation at a given coordinate
+ *
+ * \param bw The browsing context receiving the event
+ * \param x The scaled x co-ordinate of the event
+ * \param y The scaled y co-ordinate of the event
+ */
+static bool
+browser_window_scroll_at_point_internal(struct browser_window *bw,
+ int x, int y,
+ int scrx, int scry)
+{
+ bool handled_scroll = false;
+ assert(bw != NULL);
+
+ /* Handle (i)frame scroll offset (core-managed browser windows only) */
+ x += scrollbar_get_offset(bw->scroll_x);
+ y += scrollbar_get_offset(bw->scroll_y);
+
+ if (bw->children) {
+ /* Browser window has children, so pass request on to
+ * appropriate child */
+ struct browser_window *bwc;
+ int cur_child;
+ int children = bw->rows * bw->cols;
+
+ /* Loop through all children of bw */
+ for (cur_child = 0; cur_child < children; cur_child++) {
+ /* Set current child */
+ bwc = &bw->children[cur_child];
+
+ /* Skip this frame if (x, y) coord lies outside */
+ if (x < bwc->x || bwc->x + bwc->width < x ||
+ y < bwc->y || bwc->y + bwc->height < y)
+ continue;
+
+ /* Pass request into this child */
+ return browser_window_scroll_at_point_internal(
+ bwc,
+ (x - bwc->x),
+ (y - bwc->y),
+ scrx, scry);
+ }
+ }
+
+ /* Try to scroll any current content */
+ if (bw->current_content != NULL &&
+ content_scroll_at_point(bw->current_content, x, y, scrx, scry) == true) {
+ /* Scroll handled by current content */
+ return true;
+ }
+
+ /* Try to scroll this window, if scroll not already handled */
+ if (handled_scroll == false) {
+ if (bw->scroll_y && scrollbar_scroll(bw->scroll_y, scry)) {
+ handled_scroll = true;
+ }
+
+ if (bw->scroll_x && scrollbar_scroll(bw->scroll_x, scrx)) {
+ handled_scroll = true;
+ }
+ }
+
+ return handled_scroll;
+}
+
+
+/**
+ * allows a dragged file to be dropped into a browser window at a position
+ *
+ * \param bw The browsing context receiving the event
+ * \param x The scaled x co-ordinate of the event
+ * \param y The scaled y co-ordinate of the event
+ * \param file filename to be put in the widget
+ */
+static bool
+browser_window_drop_file_at_point_internal(struct browser_window *bw,
+ int x, int y,
+ char *file)
+{
+ assert(bw != NULL);
+
+ /* Handle (i)frame scroll offset (core-managed browser windows only) */
+ x += scrollbar_get_offset(bw->scroll_x);
+ y += scrollbar_get_offset(bw->scroll_y);
+
+ if (bw->children) {
+ /* Browser window has children, so pass request on to
+ * appropriate child */
+ struct browser_window *bwc;
+ int cur_child;
+ int children = bw->rows * bw->cols;
+
+ /* Loop through all children of bw */
+ for (cur_child = 0; cur_child < children; cur_child++) {
+ /* Set current child */
+ bwc = &bw->children[cur_child];
+
+ /* Skip this frame if (x, y) coord lies outside */
+ if (x < bwc->x || bwc->x + bwc->width < x ||
+ y < bwc->y || bwc->y + bwc->height < y)
+ continue;
+
+ /* Pass request into this child */
+ return browser_window_drop_file_at_point_internal(
+ bwc,
+ (x - bwc->x),
+ (y - bwc->y),
+ file);
+ }
+ }
+
+ /* Pass file drop on to any content */
+ if (bw->current_content != NULL) {
+ return content_drop_file_at_point(bw->current_content,
+ x, y, file);
+ }
+
+ return false;
+}
+
+
+/**
+ * Check if this is an internal navigation URL.
+ *
+ * This safely checks if the given url is an internal navigation even
+ * for urls with no scheme or path.
+ *
+ * \param url The URL to check
+ * \return true if an internal navigation url else false
+ */
+static bool
+is_internal_navigate_url(nsurl *url)
+{
+ bool is_internal = false;
+ lwc_string *scheme, *path;
+
+ scheme = nsurl_get_component(url, NSURL_SCHEME);
+ if (scheme != NULL) {
+ path = nsurl_get_component(url, NSURL_PATH);
+ if (path != NULL) {
+ if (scheme == corestring_lwc_about) {
+ if (path == corestring_lwc_query_auth) {
+ is_internal = true;
+ } else if (path == corestring_lwc_query_ssl) {
+ is_internal = true;
+ } else if (path == corestring_lwc_query_timeout) {
+ is_internal = true;
+ } else if (path == corestring_lwc_query_fetcherror) {
+ is_internal = true;
+ }
+ }
+ lwc_string_unref(path);
+ }
+ lwc_string_unref(scheme);
+ }
+ return is_internal;
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+nserror
+browser_window_get_name(struct browser_window *bw, const char **out_name)
+{
+ assert(bw != NULL);
+
+ *out_name = bw->name;
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+nserror
+browser_window_set_name(struct browser_window *bw, const char *name)
+{
+ char *nname = NULL;
+
+ assert(bw != NULL);
+
+ if (name != NULL) {
+ nname = strdup(name);
+ if (nname == NULL) {
+ return NSERROR_NOMEM;
+ }
+ }
+
+ if (bw->name != NULL) {
+ free(bw->name);
+ }
+
+ bw->name = nname;
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+bool
+browser_window_redraw(struct browser_window *bw,
+ int x, int y,
+ const struct rect *clip,
+ const struct redraw_context *ctx)
+{
+ struct redraw_context new_ctx = *ctx;
+ int width = 0;
+ int height = 0;
+ bool plot_ok = true;
+ content_type content_type;
+ struct content_redraw_data data;
+ struct rect content_clip;
+ nserror res;
+
+ if (bw == NULL) {
+ NSLOG(netsurf, INFO, "NULL browser window");
+ return false;
+ }
+
+ x /= bw->scale;
+ y /= bw->scale;
+
+ if ((bw->current_content == NULL) &&
+ (bw->children == NULL)) {
+ /* Browser window has no content, render blank fill */
+ ctx->plot->clip(ctx, clip);
+ return (ctx->plot->rectangle(ctx, plot_style_fill_white, clip) == NSERROR_OK);
+ }
+
+ /* Browser window has content OR children (frames) */
+ if ((bw->window != NULL) &&
+ (ctx->plot->option_knockout)) {
+ /* Root browser window: start knockout */
+ knockout_plot_start(ctx, &new_ctx);
+ }
+
+ new_ctx.plot->clip(ctx, clip);
+
+ /* Handle redraw of any browser window children */
+ if (bw->children) {
+ struct browser_window *child;
+ int cur_child;
+ int children = bw->rows * bw->cols;
+
+ if (bw->window != NULL) {
+ /* Root browser window; start with blank fill */
+ plot_ok &= (new_ctx.plot->rectangle(ctx,
+ plot_style_fill_white,
+ clip) == NSERROR_OK);
+ }
+
+ /* Loop through all children of bw */
+ for (cur_child = 0; cur_child < children; cur_child++) {
+ /* Set current child */
+ child = &bw->children[cur_child];
+
+ /* Get frame edge area in global coordinates */
+ content_clip.x0 = (x + child->x) * child->scale;
+ content_clip.y0 = (y + child->y) * child->scale;
+ content_clip.x1 = content_clip.x0 +
+ child->width * child->scale;
+ content_clip.y1 = content_clip.y0 +
+ child->height * child->scale;
+
+ /* Intersect it with clip rectangle */
+ if (content_clip.x0 < clip->x0)
+ content_clip.x0 = clip->x0;
+ if (content_clip.y0 < clip->y0)
+ content_clip.y0 = clip->y0;
+ if (clip->x1 < content_clip.x1)
+ content_clip.x1 = clip->x1;
+ if (clip->y1 < content_clip.y1)
+ content_clip.y1 = clip->y1;
+
+ /* Skip this frame if it lies outside clip rectangle */
+ if (content_clip.x0 >= content_clip.x1 ||
+ content_clip.y0 >= content_clip.y1)
+ continue;
+
+ /* Redraw frame */
+ plot_ok &= browser_window_redraw(child,
+ x + child->x,
+ y + child->y,
+ &content_clip,
+ &new_ctx);
+ }
+
+ /* Nothing else to redraw for browser windows with children;
+ * cleanup and return
+ */
+ if (bw->window != NULL && ctx->plot->option_knockout) {
+ /* Root browser window: knockout end */
+ knockout_plot_end(ctx);
+ }
+
+ return plot_ok;
+ }
+
+ /* Handle browser windows with content to redraw */
+
+ content_type = content_get_type(bw->current_content);
+ if (content_type != CONTENT_HTML && content_type != CONTENT_TEXTPLAIN) {
+ /* Set render area according to scale */
+ width = content_get_width(bw->current_content) * bw->scale;
+ height = content_get_height(bw->current_content) * bw->scale;
+
+ /* Non-HTML may not fill viewport to extents, so plot white
+ * background fill */
+ plot_ok &= (new_ctx.plot->rectangle(&new_ctx,
+ plot_style_fill_white,
+ clip) == NSERROR_OK);
+ }
+
+ /* Set up content redraw data */
+ data.x = x - scrollbar_get_offset(bw->scroll_x);
+ data.y = y - scrollbar_get_offset(bw->scroll_y);
+ data.width = width;
+ data.height = height;
+
+ data.background_colour = 0xFFFFFF;
+ data.scale = bw->scale;
+ data.repeat_x = false;
+ data.repeat_y = false;
+
+ content_clip = *clip;
+
+ if (!bw->window) {
+ int x0 = x * bw->scale;
+ int y0 = y * bw->scale;
+ int x1 = (x + bw->width - ((bw->scroll_y != NULL) ?
+ SCROLLBAR_WIDTH : 0)) * bw->scale;
+ int y1 = (y + bw->height - ((bw->scroll_x != NULL) ?
+ SCROLLBAR_WIDTH : 0)) * bw->scale;
+
+ if (content_clip.x0 < x0) content_clip.x0 = x0;
+ if (content_clip.y0 < y0) content_clip.y0 = y0;
+ if (x1 < content_clip.x1) content_clip.x1 = x1;
+ if (y1 < content_clip.y1) content_clip.y1 = y1;
+ }
+
+ /* Render the content */
+ plot_ok &= content_redraw(bw->current_content, &data,
+ &content_clip, &new_ctx);
+
+ /* Back to full clip rect */
+ new_ctx.plot->clip(&new_ctx, clip);
+
+ if (!bw->window) {
+ /* Render scrollbars */
+ int off_x, off_y;
+ if (bw->scroll_x != NULL) {
+ browser_window_get_scrollbar_pos(bw, true,
+ &off_x, &off_y);
+ res = scrollbar_redraw(bw->scroll_x,
+ x + off_x, y + off_y, clip,
+ bw->scale, &new_ctx);
+ if (res != NSERROR_OK) {
+ plot_ok = false;
+ }
+ }
+ if (bw->scroll_y != NULL) {
+ browser_window_get_scrollbar_pos(bw, false,
+ &off_x, &off_y);
+ res = scrollbar_redraw(bw->scroll_y,
+ x + off_x, y + off_y, clip,
+ bw->scale, &new_ctx);
+ if (res != NSERROR_OK) {
+ plot_ok = false;
+ }
+ }
+ }
+
+ if (bw->window != NULL && ctx->plot->option_knockout) {
+ /* Root browser window: end knockout */
+ knockout_plot_end(ctx);
+ }
+
+ return plot_ok;
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+bool browser_window_redraw_ready(struct browser_window *bw)
+{
+ if (bw == NULL) {
+ NSLOG(netsurf, INFO, "NULL browser window");
+ return false;
+ } else if (bw->current_content != NULL) {
+ /* Can't render locked contents */
+ return !content_is_locked(bw->current_content);
+ }
+
+ return true;
+}
+
+
+/* exported interface, documented in browser_private.h */
+void browser_window_update_extent(struct browser_window *bw)
+{
+ if (bw->window != NULL) {
+ /* Front end window */
+ guit->window->event(bw->window, GW_EVENT_UPDATE_EXTENT);
+ } else {
+ /* Core-managed browser window */
+ browser_window_handle_scrollbars(bw);
+ }
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+void
+browser_window_get_position(struct browser_window *bw,
+ bool root,
+ int *pos_x,
+ int *pos_y)
+{
+ *pos_x = 0;
+ *pos_y = 0;
+
+ assert(bw != NULL);
+
+ while (bw) {
+ switch (bw->browser_window_type) {
+
+ case BROWSER_WINDOW_FRAMESET:
+ *pos_x += bw->x * bw->scale;
+ *pos_y += bw->y * bw->scale;
+ break;
+
+ case BROWSER_WINDOW_NORMAL:
+ /* There is no offset to the root browser window */
+ break;
+
+ case BROWSER_WINDOW_FRAME:
+ /* Iframe and Frame handling is identical;
+ * fall though */
+ case BROWSER_WINDOW_IFRAME:
+ *pos_x += (bw->x - scrollbar_get_offset(bw->scroll_x)) *
+ bw->scale;
+ *pos_y += (bw->y - scrollbar_get_offset(bw->scroll_y)) *
+ bw->scale;
+ break;
+ }
+
+ bw = bw->parent;
+
+ if (!root) {
+ /* return if we just wanted the position in the parent
+ * browser window. */
+ return;
+ }
+ }
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+void browser_window_set_position(struct browser_window *bw, int x, int y)
+{
+ assert(bw != NULL);
+
+ if (bw->window == NULL) {
+ /* Core managed browser window */
+ bw->x = x;
+ bw->y = y;
+ } else {
+ NSLOG(netsurf, INFO,
+ "Asked to set position of front end window.");
+ assert(0);
+ }
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+void
+browser_window_set_drag_type(struct browser_window *bw,
+ browser_drag_type type,
+ const struct rect *rect)
+{
+ struct browser_window *top_bw = browser_window_get_root(bw);
+ gui_drag_type gtype;
+
+ bw->drag.type = type;
+
+ if (type == DRAGGING_NONE) {
+ top_bw->drag.window = NULL;
+ } else {
+ top_bw->drag.window = bw;
+
+ switch (type) {
+ case DRAGGING_SELECTION:
+ /** \todo tell front end */
+ return;
+ case DRAGGING_SCR_X:
+ case DRAGGING_SCR_Y:
+ case DRAGGING_CONTENT_SCROLLBAR:
+ gtype = GDRAGGING_SCROLLBAR;
+ break;
+ default:
+ gtype = GDRAGGING_OTHER;
+ break;
+ }
+
+ guit->window->drag_start(top_bw->window, gtype, rect);
+ }
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+browser_drag_type browser_window_get_drag_type(struct browser_window *bw)
+{
+ return bw->drag.type;
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+struct browser_window * browser_window_get_root(struct browser_window *bw)
+{
+ while (bw && bw->parent) {
+ bw = bw->parent;
+ }
+ return bw;
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+browser_editor_flags browser_window_get_editor_flags(struct browser_window *bw)
+{
+ browser_editor_flags ed_flags = BW_EDITOR_NONE;
+ assert(bw->window);
+ assert(bw->parent == NULL);
+
+ if (bw->selection.bw != NULL) {
+ ed_flags |= BW_EDITOR_CAN_COPY;
+
+ if (!bw->selection.read_only)
+ ed_flags |= BW_EDITOR_CAN_CUT;
+ }
+
+ if (bw->can_edit)
+ ed_flags |= BW_EDITOR_CAN_PASTE;
+
+ return ed_flags;
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+bool browser_window_can_select(struct browser_window *bw)
+{
+ if (bw == NULL || bw->current_content == NULL)
+ return false;
+
+ /* TODO: We shouldn't have to know about specific content types
+ * here. There should be a content_is_selectable() call. */
+ if (content_get_type(bw->current_content) != CONTENT_HTML &&
+ content_get_type(bw->current_content) !=
+ CONTENT_TEXTPLAIN)
+ return false;
+
+ return true;
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+char * browser_window_get_selection(struct browser_window *bw)
+{
+ assert(bw->window);
+ assert(bw->parent == NULL);
+
+ if (bw->selection.bw == NULL ||
+ bw->selection.bw->current_content == NULL)
+ return NULL;
+
+ return content_get_selection(bw->selection.bw->current_content);
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+bool browser_window_can_search(struct browser_window *bw)
+{
+ if (bw == NULL || bw->current_content == NULL)
+ return false;
+
+ /** \todo We shouldn't have to know about specific content
+ * types here. There should be a content_is_searchable() call.
+ */
+ if ((content_get_type(bw->current_content) != CONTENT_HTML) &&
+ (content_get_type(bw->current_content) != CONTENT_TEXTPLAIN)) {
+ return false;
+ }
+
+ return true;
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+bool browser_window_is_frameset(struct browser_window *bw)
+{
+ return (bw->children != NULL);
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+nserror
+browser_window_get_scrollbar_type(struct browser_window *bw,
+ browser_scrolling *h,
+ browser_scrolling *v)
+{
+ *h = bw->scrolling;
+ *v = bw->scrolling;
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+nserror
+browser_window_get_features(struct browser_window *bw,
+ int x, int y,
+ struct browser_window_features *data)
+{
+ /* clear the features structure to empty values */
+ data->link = NULL;
+ data->object = NULL;
+ data->main = NULL;
+ data->form_features = CTX_FORM_NONE;
+
+ return browser_window__get_contextual_content(bw,
+ x / bw->scale,
+ y / bw->scale,
+ data);
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+bool
+browser_window_scroll_at_point(struct browser_window *bw,
+ int x, int y,
+ int scrx, int scry)
+{
+ return browser_window_scroll_at_point_internal(bw,
+ x / bw->scale,
+ y / bw->scale,
+ scrx,
+ scry);
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+bool
+browser_window_drop_file_at_point(struct browser_window *bw,
+ int x, int y,
+ char *file)
+{
+ return browser_window_drop_file_at_point_internal(bw,
+ x / bw->scale,
+ y / bw->scale,
+ file);
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+void
+browser_window_set_gadget_filename(struct browser_window *bw,
+ struct form_control *gadget,
+ const char *fn)
+{
+ html_set_file_gadget_filename(bw->current_content, gadget, fn);
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+nserror
+browser_window_debug_dump(struct browser_window *bw,
+ FILE *f,
+ enum content_debug op)
+{
+ if (bw->current_content != NULL) {
+ return content_debug_dump(bw->current_content, f, op);
+ }
+ return NSERROR_OK;
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+nserror browser_window_debug(struct browser_window *bw, enum content_debug op)
+{
+ if (bw->current_content != NULL) {
+ return content_debug(bw->current_content, op);
+ }
+ return NSERROR_OK;
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+nserror
+browser_window_create(enum browser_window_create_flags flags,
+ nsurl *url,
+ nsurl *referrer,
+ struct browser_window *existing,
+ struct browser_window **bw)
+{
+ gui_window_create_flags gw_flags = GW_CREATE_NONE;
+ struct browser_window *ret;
+ nserror err;
+
+ /* Check parameters */
+ if (flags & BW_CREATE_CLONE) {
+ if (existing == NULL) {
+ assert(0 && "Failed: No existing window provided.");
+ return NSERROR_BAD_PARAMETER;
+ }
+ }
+
+ if (!(flags & BW_CREATE_HISTORY)) {
+ if (!(flags & BW_CREATE_CLONE) || existing == NULL) {
+ assert(0 && "Failed: Must have existing for history.");
+ return NSERROR_BAD_PARAMETER;
+ }
+ }
+
+ ret = calloc(1, sizeof(struct browser_window));
+ if (ret == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ /* Initialise common parts */
+ err = browser_window_initialise_common(flags, ret, existing);
+ if (err != NSERROR_OK) {
+ browser_window_destroy(ret);
+ return err;
+ }
+
+ /* window characteristics */
+ ret->browser_window_type = BROWSER_WINDOW_NORMAL;
+ ret->scrolling = BW_SCROLLING_YES;
+ ret->border = true;
+ ret->no_resize = true;
+ ret->focus = ret;
+
+ /* initialise last action with creation time */
+ nsu_getmonotonic_ms(&ret->last_action);
+
+ /* The existing gui_window is on the top-level existing
+ * browser_window. */
+ existing = browser_window_get_root(existing);
+
+ /* Set up gui_window creation flags */
+ if (flags & BW_CREATE_TAB)
+ gw_flags |= GW_CREATE_TAB;
+ if (flags & BW_CREATE_CLONE)
+ gw_flags |= GW_CREATE_CLONE;
+ if (flags & BW_CREATE_FOREGROUND)
+ gw_flags |= GW_CREATE_FOREGROUND;
+ if (flags & BW_CREATE_FOCUS_LOCATION)
+ gw_flags |= GW_CREATE_FOCUS_LOCATION;
+
+ ret->window = guit->window->create(ret,
+ (existing != NULL) ? existing->window : NULL,
+ gw_flags);
+
+ if (ret->window == NULL) {
+ browser_window_destroy(ret);
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if (url != NULL) {
+ enum browser_window_nav_flags nav_flags;
+ nav_flags = BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE;
+ if (flags & BW_CREATE_UNVERIFIABLE) {
+ nav_flags |= BW_NAVIGATE_UNVERIFIABLE;
+ }
+ if (flags & BW_CREATE_HISTORY) {
+ nav_flags |= BW_NAVIGATE_HISTORY;
+ }
+ browser_window_navigate(ret,
+ url,
+ referrer,
+ nav_flags,
+ NULL,
+ NULL,
+ NULL);
+ }
+
+ if (bw != NULL) {
+ *bw = ret;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/* exported internal interface, documented in desktop/browser_private.h */
+nserror
+browser_window_initialise_common(enum browser_window_create_flags flags,
+ struct browser_window *bw,
+ const struct browser_window *existing)
+{
+ nserror err;
+ assert(bw);
+
+ /* new javascript context for each window/(i)frame */
+ err = js_newheap(nsoption_int(script_timeout), &bw->jsheap);
+ if (err != NSERROR_OK)
+ return err;
+
+ if (flags & BW_CREATE_CLONE) {
+ assert(existing != NULL);
+
+ /* clone history */
+ err = browser_window_history_clone(existing, bw);
+
+ /* copy the scale */
+ bw->scale = existing->scale;
+ } else {
+ /* create history */
+ err = browser_window_history_create(bw);
+
+ /* default scale */
+ bw->scale = (float) nsoption_int(scale) / 100.0;
+ }
+
+ if (err != NSERROR_OK)
+ return err;
+
+ /* window characteristics */
+ bw->refresh_interval = -1;
+
+ bw->drag.type = DRAGGING_NONE;
+
+ bw->scroll_x = NULL;
+ bw->scroll_y = NULL;
+
+ bw->focus = NULL;
+
+ /* initialise status text cache */
+ bw->status.text = NULL;
+ bw->status.text_len = 0;
+ bw->status.match = 0;
+ bw->status.miss = 0;
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+void browser_window_destroy(struct browser_window *bw)
+{
+ /* can't destoy child windows on their own */
+ assert(!bw->parent);
+
+ /* destroy */
+ browser_window_destroy_internal(bw);
+ free(bw);
+}
+
+
+/* exported interface, documented in netsurf/browser_window.h */
+nserror browser_window_refresh_url_bar(struct browser_window *bw)
+{
+ nserror ret;
+ nsurl *display_url, *url;
+
+ assert(bw);
+
+ if (bw->parent != NULL) {
+ /* Not root window; don't set a URL in GUI URL bar */
+ return NSERROR_OK;
+ }
+
+ if (bw->current_content == NULL) {
+ /* no content so return about:blank */
+ ret = browser_window_refresh_url_bar_internal(bw,
+ corestring_nsurl_about_blank);
+ } else if (bw->throbbing && bw->loading_parameters.url != NULL) {
+ /* Throbbing and we have loading parameters, use those */
+ url = bw->loading_parameters.url;
+ ret = browser_window_refresh_url_bar_internal(bw, url);
+ } else if (bw->frag_id == NULL) {
+ if (bw->internal_nav) {
+ url = bw->loading_parameters.url;
+ } else {
+ url = hlcache_handle_get_url(bw->current_content);
+ }
+ ret = browser_window_refresh_url_bar_internal(bw, url);
+ } else {
+ /* Combine URL and Fragment */
+ if (bw->internal_nav) {
+ url = bw->loading_parameters.url;
+ } else {
+ url = hlcache_handle_get_url(bw->current_content);
+ }
+ ret = nsurl_refragment(
+ url,
+ bw->frag_id, &display_url);
+ if (ret == NSERROR_OK) {
+ ret = browser_window_refresh_url_bar_internal(bw,
+ display_url);
+ nsurl_unref(display_url);
+ }
+ }
+
+ return ret;
+}
+
+
+/* exported interface documented in netsurf/browser_window.h */
+nserror
+browser_window_navigate(struct browser_window *bw,
+ nsurl *url,
+ nsurl *referrer,
+ enum browser_window_nav_flags flags,
+ char *post_urlenc,
+ struct fetch_multipart_data *post_multipart,
+ hlcache_handle *parent)
+{
+ int depth = 0;
+ struct browser_window *cur;
+ uint32_t fetch_flags = 0;
+ bool fetch_is_post = (post_urlenc != NULL || post_multipart != NULL);
+ llcache_post_data post;
+ hlcache_child_context child;
+ nserror error;
+ bool is_internal = false;
+ struct browser_fetch_parameters params, *pass_params = NULL;
+
+ assert(bw);
+ assert(url);
+
+ NSLOG(netsurf, INFO, "bw %p, url %s", bw, nsurl_access(url));
+
+ /*
+ * determine if navigation is internal url, if so, we do not
+ * do certain things during the load.
+ */
+ is_internal = is_internal_navigate_url(url);
+
+ if (is_internal &&
+ !(flags & BW_NAVIGATE_INTERNAL)) {
+ /* Internal navigation detected, but flag not set, only allow
+ * this is there's a fetch multipart
+ */
+ if (post_multipart == NULL) {
+ return NSERROR_NEED_DATA;
+ }
+ /* It *is* internal, set it as such */
+ flags |= BW_NAVIGATE_INTERNAL | BW_NAVIGATE_HISTORY;
+ /* If we were previously internal, don't update again */
+ if (bw->internal_nav) {
+ flags |= BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE;
+ }
+ }
+
+ /* If we're navigating and we have a history entry and a content
+ * then update the history entry before we navigate to save our
+ * current state. However since history navigation pre-moves
+ * the history state, we ensure that we only do this if we've not
+ * been suppressed. In the suppressed case, the history code
+ * updates the history itself before navigating.
+ */
+ if (bw->current_content != NULL &&
+ bw->history != NULL &&
+ bw->history->current != NULL &&
+ !is_internal &&
+ !(flags & BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE)) {
+ browser_window_history_update(bw, bw->current_content);
+ }
+
+ /* don't allow massively nested framesets */
+ for (cur = bw; cur->parent; cur = cur->parent) {
+ depth++;
+ }
+ if (depth > FRAME_DEPTH) {
+ NSLOG(netsurf, INFO, "frame depth too high.");
+ return NSERROR_FRAME_DEPTH;
+ }
+
+ /* Set up retrieval parameters */
+ if (!(flags & BW_NAVIGATE_UNVERIFIABLE)) {
+ fetch_flags |= LLCACHE_RETRIEVE_VERIFIABLE;
+ }
+
+ if (post_multipart != NULL) {
+ post.type = LLCACHE_POST_MULTIPART;
+ post.data.multipart = post_multipart;
+ } else if (post_urlenc != NULL) {
+ post.type = LLCACHE_POST_URL_ENCODED;
+ post.data.urlenc = post_urlenc;
+ }
+
+ child.charset = content_get_encoding(parent, CONTENT_ENCODING_NORMAL);
+ if ((parent != NULL) && (content_get_type(parent) == CONTENT_HTML)) {
+ child.quirks = content_get_quirks(parent);
+ } else {
+ child.quirks = false;
+ }
+
+ url = nsurl_ref(url);
+
+ if (referrer != NULL) {
+ referrer = nsurl_ref(referrer);
+ }
+
+ /* Get download out of the way */
+ if ((flags & BW_NAVIGATE_DOWNLOAD) != 0) {
+ error = browser_window_download(bw,
+ url,
+ referrer,
+ fetch_flags,
+ fetch_is_post,
+ &post);
+ nsurl_unref(url);
+ if (referrer != NULL) {
+ nsurl_unref(referrer);
+ }
+ return error;
+ }
+
+ if (bw->frag_id != NULL) {
+ lwc_string_unref(bw->frag_id);
+ }
+ bw->frag_id = NULL;
+
+ if (nsurl_has_component(url, NSURL_FRAGMENT)) {
+ bool same_url = false;
+
+ bw->frag_id = nsurl_get_component(url, NSURL_FRAGMENT);
+
+ /* Compare new URL with existing one (ignoring fragments) */
+ if ((bw->current_content != NULL) &&
+ (hlcache_handle_get_url(bw->current_content) != NULL)) {
+ same_url = nsurl_compare(
+ url,
+ hlcache_handle_get_url(bw->current_content),
+ NSURL_COMPLETE);
+ }
+
+ /* if we're simply moving to another ID on the same page,
+ * don't bother to fetch, just update the window.
+ */
+ if ((same_url) &&
+ (fetch_is_post == false) &&
+ (nsurl_has_component(url, NSURL_QUERY) == false)) {
+ nsurl_unref(url);
+
+ if (referrer != NULL) {
+ nsurl_unref(referrer);
+ }
+
+ if ((flags & BW_NAVIGATE_HISTORY) != 0) {
+ browser_window_history_add(bw,
+ bw->current_content,
+ bw->frag_id);
+ }
+
+ browser_window_update(bw, false);
+
+ if (bw->current_content != NULL) {
+ browser_window_refresh_url_bar(bw);
+ }
+ return NSERROR_OK;
+ }
+ }
+
+ browser_window_stop(bw);
+ browser_window_remove_caret(bw, false);
+ browser_window_destroy_children(bw);
+ browser_window_destroy_iframes(bw);
+
+ /* Set up the fetch parameters */
+ memset(&params, 0, sizeof(params));
+
+ params.url = nsurl_ref(url);
+
+ if (referrer != NULL) {
+ params.referrer = nsurl_ref(referrer);
+ }
+
+ params.flags = flags;
+
+ if (post_urlenc != NULL) {
+ params.post_urlenc = strdup(post_urlenc);
+ }
+
+ if (post_multipart != NULL) {
+ params.post_multipart = fetch_multipart_data_clone(post_multipart);
+ }
+
+ if (parent != NULL) {
+ params.parent_charset = strdup(child.charset);
+ params.parent_quirks = child.quirks;
+ }
+
+ bw->internal_nav = is_internal;
+
+ if (is_internal) {
+ pass_params = &params;
+ } else {
+ /* At this point, we're navigating, so store the fetch parameters */
+ browser_window__free_fetch_parameters(&bw->loading_parameters);
+ memcpy(&bw->loading_parameters, &params, sizeof(params));
+ memset(&params, 0, sizeof(params));
+ pass_params = &bw->loading_parameters;
+ }
+
+ error = browser_window__navigate_internal(bw, pass_params);
+
+ nsurl_unref(url);
+
+ if (referrer != NULL) {
+ nsurl_unref(referrer);
+ }
+
+ if (is_internal) {
+ browser_window__free_fetch_parameters(&params);
+ }
+
+ return error;
+}
+
+
+/**
+ * Internal navigation handler for normal fetches
+ */
+static nserror
+navigate_internal_real(struct browser_window *bw,
+ struct browser_fetch_parameters *params)
+{
+ uint32_t fetch_flags = 0;
+ bool fetch_is_post;
+ llcache_post_data post;
+ hlcache_child_context child;
+ nserror res;
+ hlcache_handle *c;
+
+ NSLOG(netsurf, INFO, "Loading '%s'", nsurl_access(params->url));
+
+ fetch_is_post = (params->post_urlenc != NULL || params->post_multipart != NULL);
+
+ /* Clear SSL info for load */
+ cert_chain_free(bw->loading_cert_chain);
+ bw->loading_cert_chain = NULL;
+
+ /* Set up retrieval parameters */
+ if (!(params->flags & BW_NAVIGATE_UNVERIFIABLE)) {
+ fetch_flags |= LLCACHE_RETRIEVE_VERIFIABLE;
+ }
+
+ if (params->post_multipart != NULL) {
+ post.type = LLCACHE_POST_MULTIPART;
+ post.data.multipart = params->post_multipart;
+ } else if (params->post_urlenc != NULL) {
+ post.type = LLCACHE_POST_URL_ENCODED;
+ post.data.urlenc = params->post_urlenc;
+ }
+
+ if (params->parent_charset != NULL) {
+ child.charset = params->parent_charset;
+ child.quirks = params->parent_quirks;
+ }
+
+ browser_window_set_status(bw, messages_get("Loading"));
+ bw->history_add = (params->flags & BW_NAVIGATE_HISTORY);
+
+ /* Verifiable fetches may trigger a download */
+ if (!(params->flags & BW_NAVIGATE_UNVERIFIABLE)) {
+ fetch_flags |= HLCACHE_RETRIEVE_MAY_DOWNLOAD;
+ }
+
+ res = hlcache_handle_retrieve(params->url,
+ fetch_flags | HLCACHE_RETRIEVE_SNIFF_TYPE,
+ params->referrer,
+ fetch_is_post ? &post : NULL,
+ browser_window_callback,
+ bw,
+ params->parent_charset != NULL ? &child : NULL,
+ CONTENT_ANY,
+ &c);
+
+ switch (res) {
+ case NSERROR_OK:
+ bw->loading_content = c;
+ browser_window_start_throbber(bw);
+ if (bw->window != NULL) {
+ guit->window->set_icon(bw->window, NULL);
+ }
+ if (bw->internal_nav == false) {
+ res = browser_window_refresh_url_bar_internal(bw,
+ params->url);
+ }
+ break;
+
+ case NSERROR_NO_FETCH_HANDLER: /* no handler for this type */
+ /** \todo does this always try and download even
+ * unverifiable content?
+ */
+ res = guit->misc->launch_url(params->url);
+ break;
+
+ default: /* report error to user */
+ browser_window_set_status(bw, messages_get_errorcode(res));
+ break;
+
+ }
+
+ /* Record time */
+ nsu_getmonotonic_ms(&bw->last_action);
+
+ return res;
+}
+
+
+/**
+ * Internal navigation handler for the authentication query handler
+ *
+ * If the parameters indicate we're processing a *response* from the handler
+ * then we deal with that, otherwise we pass it on to the about: handler
+ */
+static nserror
+navigate_internal_query_auth(struct browser_window *bw,
+ struct browser_fetch_parameters *params)
+{
+ char *userpass = NULL;
+ const char *username, *password, *realm, *siteurl;
+ nsurl *sitensurl;
+ nserror res;
+ bool is_login = false, is_cancel = false;
+
+ assert(params->post_multipart != NULL);
+
+ is_login = fetch_multipart_data_find(params->post_multipart, "login") != NULL;
+ is_cancel = fetch_multipart_data_find(params->post_multipart, "cancel") != NULL;
+
+ if (!(is_login || is_cancel)) {
+ /* This is a request, so pass it on */
+ return navigate_internal_real(bw, params);
+ }
+
+ if (is_cancel) {
+ /* We're processing a cancel, do a rough-and-ready nav to
+ * about:blank
+ */
+ browser_window__free_fetch_parameters(&bw->loading_parameters);
+ bw->loading_parameters.url = nsurl_ref(corestring_nsurl_about_blank);
+ bw->loading_parameters.flags = BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE | BW_NAVIGATE_INTERNAL;
+ bw->internal_nav = true;
+ return browser_window__navigate_internal(bw, &bw->loading_parameters);
+ }
+
+ /* We're processing a "login" attempt from the form */
+
+ /* Retrieve the data */
+ username = fetch_multipart_data_find(params->post_multipart, "username");
+ password = fetch_multipart_data_find(params->post_multipart, "password");
+ realm = fetch_multipart_data_find(params->post_multipart, "realm");
+ siteurl = fetch_multipart_data_find(params->post_multipart, "siteurl");
+
+ if (username == NULL || password == NULL ||
+ realm == NULL || siteurl == NULL) {
+ /* Bad inputs, simply fail */
+ return NSERROR_INVALID;
+ }
+
+ /* Parse the URL */
+ res = nsurl_create(siteurl, &sitensurl);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* Construct the username/password */
+ res = browser_window__build_userpass(username, password, &userpass);
+ if (res != NSERROR_OK) {
+ nsurl_unref(sitensurl);
+ return res;
+ }
+
+ /* And let urldb know */
+ urldb_set_auth_details(sitensurl, realm, userpass);
+
+ /* Clean up */
+ free(userpass);
+ nsurl_unref(sitensurl);
+
+ /* Finally navigate to the original loading parameters */
+ bw->internal_nav = false;
+ return navigate_internal_real(bw, &bw->loading_parameters);
+}
+
+
+/**
+ * Internal navigation handler for the SSL/privacy query page.
+ *
+ * If the parameters indicate we're processing a *response* from the handler
+ * then we deal with that, otherwise we pass it on to the about: handler
+ */
+static nserror
+navigate_internal_query_ssl(struct browser_window *bw,
+ struct browser_fetch_parameters *params)
+{
+ bool is_proceed = false, is_back = false;
+ const char *siteurl = NULL;
+ nsurl *siteurl_ns;
+
+ assert(params->post_multipart != NULL);
+
+ is_proceed = fetch_multipart_data_find(params->post_multipart, "proceed") != NULL;
+ is_back = fetch_multipart_data_find(params->post_multipart, "back") != NULL;
+ siteurl = fetch_multipart_data_find(params->post_multipart, "siteurl");
+
+ if (!(is_proceed || is_back) || siteurl == NULL) {
+ /* This is a request, so pass it on */
+ return navigate_internal_real(bw, params);
+ }
+
+ if (nsurl_create(siteurl, &siteurl_ns) != NSERROR_OK) {
+ NSLOG(netsurf, ERROR, "Unable to reset ssl loading parameters");
+ } else {
+ /* In order that we may proceed, replace the loading parameters */
+ nsurl_unref(bw->loading_parameters.url);
+ bw->loading_parameters.url = siteurl_ns;
+ }
+
+ return browser_window__handle_ssl_query_response(is_proceed, bw);
+}
+
+
+/**
+ * Internal navigation handler for the timeout query page.
+ *
+ * If the parameters indicate we're processing a *response* from the handler
+ * then we deal with that, otherwise we pass it on to the about: handler
+ */
+static nserror
+navigate_internal_query_timeout(struct browser_window *bw,
+ struct browser_fetch_parameters *params)
+{
+ bool is_retry = false, is_back = false;
+
+ NSLOG(netsurf, INFO, "bw:%p params:%p", bw, params);
+
+ assert(params->post_multipart != NULL);
+
+ is_retry = fetch_multipart_data_find(params->post_multipart, "retry") != NULL;
+ is_back = fetch_multipart_data_find(params->post_multipart, "back") != NULL;
+
+ if (is_back) {
+ /* do a rough-and-ready nav to the old 'current'
+ * parameters, with any post data stripped away
+ */
+ return browser_window__reload_current_parameters(bw);
+ }
+
+ if (is_retry) {
+ /* Finally navigate to the original loading parameters */
+ bw->internal_nav = false;
+ return navigate_internal_real(bw, &bw->loading_parameters);
+ }
+
+ return navigate_internal_real(bw, params);
+}
+
+
+/**
+ * Internal navigation handler for the fetch error query page.
+ *
+ * If the parameters indicate we're processing a *response* from the handler
+ * then we deal with that, otherwise we pass it on to the about: handler
+ */
+static nserror
+navigate_internal_query_fetcherror(struct browser_window *bw,
+ struct browser_fetch_parameters *params)
+{
+ bool is_retry = false, is_back = false;
+
+ NSLOG(netsurf, INFO, "bw:%p params:%p", bw, params);
+
+ assert(params->post_multipart != NULL);
+
+ is_retry = fetch_multipart_data_find(params->post_multipart, "retry") != NULL;
+ is_back = fetch_multipart_data_find(params->post_multipart, "back") != NULL;
+
+ if (is_back) {
+ /* do a rough-and-ready nav to the old 'current'
+ * parameters, with any post data stripped away
+ */
+ return browser_window__reload_current_parameters(bw);
+ }
+
+ if (is_retry) {
+ /* Finally navigate to the original loading parameters */
+ bw->internal_nav = false;
+ return navigate_internal_real(bw, &bw->loading_parameters);
+ }
+
+ return navigate_internal_real(bw, params);
+}
+
+
+/**
+ * dispatch to internal query handlers or normal navigation
+ *
+ * Here we determine if we're navigating to an internal query URI and
+ * if so, what we need to do about it.
+ *
+ * \note these check must match those in is_internal_navigate_url()
+ *
+ * If we're not, then we just move on to the real navigate.
+ */
+nserror
+browser_window__navigate_internal(struct browser_window *bw,
+ struct browser_fetch_parameters *params)
+{
+ lwc_string *scheme, *path;
+
+ /* All our special URIs are in the about: scheme */
+ scheme = nsurl_get_component(params->url, NSURL_SCHEME);
+ if (scheme != corestring_lwc_about) {
+ lwc_string_unref(scheme);
+ goto normal_fetch;
+ }
+ lwc_string_unref(scheme);
+
+ /* Is it the auth query handler? */
+ path = nsurl_get_component(params->url, NSURL_PATH);
+ if (path == corestring_lwc_query_auth) {
+ lwc_string_unref(path);
+ return navigate_internal_query_auth(bw, params);
+ }
+ if (path == corestring_lwc_query_ssl) {
+ lwc_string_unref(path);
+ return navigate_internal_query_ssl(bw, params);
+ }
+ if (path == corestring_lwc_query_timeout) {
+ lwc_string_unref(path);
+ return navigate_internal_query_timeout(bw, params);
+ }
+ if (path == corestring_lwc_query_fetcherror) {
+ lwc_string_unref(path);
+ return navigate_internal_query_fetcherror(bw, params);
+ }
+ if (path != NULL) {
+ lwc_string_unref(path);
+ }
+
+ /* Fall through to a normal about: fetch */
+
+ normal_fetch:
+ return navigate_internal_real(bw, params);
+}
+
+
+/* Exported interface, documented in netsurf/browser_window.h */
+bool browser_window_up_available(struct browser_window *bw)
+{
+ bool result = false;
+
+ if (bw != NULL && bw->current_content != NULL) {
+ nsurl *parent;
+ nserror err;
+ err = nsurl_parent(hlcache_handle_get_url(bw->current_content),
+ &parent);
+ if (err == NSERROR_OK) {
+ result = nsurl_compare(hlcache_handle_get_url(
+ bw->current_content),
+ parent,
+ NSURL_COMPLETE) == false;
+ nsurl_unref(parent);
+ }
+ }
+
+ return result;
+}
+
+
+/* Exported interface, documented in netsurf/browser_window.h */
+nserror browser_window_navigate_up(struct browser_window *bw, bool new_window)
+{
+ nsurl *current, *parent;
+ nserror err;
+
+ if (bw == NULL)
+ return NSERROR_BAD_PARAMETER;
+
+ current = browser_window_access_url(bw);
+
+ err = nsurl_parent(current, &parent);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
+ if (nsurl_compare(current, parent, NSURL_COMPLETE) == true) {
+ /* Can't go up to parent from here */
+ nsurl_unref(parent);
+ return NSERROR_OK;
+ }
+
+ if (new_window) {
+ err = browser_window_create(BW_CREATE_CLONE,
+ parent, NULL, bw, NULL);
+ } else {
+ err = browser_window_navigate(bw, parent, NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL, NULL, NULL);
+ }
+
+ nsurl_unref(parent);
+ return err;
+}
+
+
+/* Exported interface, documented in include/netsurf/browser_window.h */
+nsurl* browser_window_access_url(const struct browser_window *bw)
+{
+ assert(bw != NULL);
+
+ if (bw->current_content != NULL) {
+ return hlcache_handle_get_url(bw->current_content);
+
+ } else if (bw->loading_content != NULL) {
+ /* TODO: should we return this? */
+ return hlcache_handle_get_url(bw->loading_content);
+ }
+
+ return corestring_nsurl_about_blank;
+}
+
+
+/* Exported interface, documented in include/netsurf/browser_window.h */
+nserror
+browser_window_get_url(struct browser_window *bw, bool fragment,nsurl** url_out)
+{
+ nserror err;
+ nsurl *url;
+
+ assert(bw != NULL);
+
+ if (!fragment || bw->frag_id == NULL || bw->loading_content != NULL) {
+ /* If there's a loading content, then the bw->frag_id will have
+ * been trampled, possibly with a new frag_id, but we will
+ * still be returning the current URL, so in this edge case
+ * we just drop any fragment. */
+ url = nsurl_ref(browser_window_access_url(bw));
+
+ } else {
+ err = nsurl_refragment(browser_window_access_url(bw),
+ bw->frag_id, &url);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+ }
+
+ *url_out = url;
+ return NSERROR_OK;
+}
+
+
+/* Exported interface, documented in netsurf/browser_window.h */
+const char* browser_window_get_title(struct browser_window *bw)
+{
+ assert(bw != NULL);
+
+ if (bw->current_content != NULL) {
+ return content_get_title(bw->current_content);
+ }
+
+ /* no content so return about:blank */
+ return nsurl_access(corestring_nsurl_about_blank);
+}
+
+
+/* Exported interface, documented in netsurf/browser_window.h */
+struct history * browser_window_get_history(struct browser_window *bw)
+{
+ assert(bw != NULL);
+
+ return bw->history;
+}
+
+
+/* Exported interface, documented in netsurf/browser_window.h */
+bool browser_window_has_content(struct browser_window *bw)
+{
+ assert(bw != NULL);
+
+ if (bw->current_content == NULL) {
+ return false;
+ }
+
+ return true;
+}
+
+
+/* Exported interface, documented in netsurf/browser_window.h */
+struct hlcache_handle *browser_window_get_content(struct browser_window *bw)
+{
+ return bw->current_content;
+}
+
+
+/* Exported interface, documented in netsurf/browser_window.h */
+nserror browser_window_get_extents(struct browser_window *bw, bool scaled,
+ int *width, int *height)
+{
+ assert(bw != NULL);
+
+ if (bw->current_content == NULL) {
+ *width = 0;
+ *height = 0;
+ return NSERROR_BAD_CONTENT;
+ }
+
+ *width = content_get_width(bw->current_content);
+ *height = content_get_height(bw->current_content);
+
+ if (scaled) {
+ *width *= bw->scale;
+ *height *= bw->scale;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/* exported internal interface, documented in desktop/browser_private.h */
+nserror
+browser_window_get_dimensions(struct browser_window *bw,
+ int *width,
+ int *height)
+{
+ nserror res;
+ assert(bw);
+
+ if (bw->window == NULL) {
+ /* Core managed browser window */
+ *width = bw->width;
+ *height = bw->height;
+ res = NSERROR_OK;
+ } else {
+ /* Front end window */
+ res = guit->window->get_dimensions(bw->window, width, height);
+ }
+ return res;
+}
+
+
+/* Exported interface, documented in netsurf/browser_window.h */
+void
+browser_window_set_dimensions(struct browser_window *bw, int width, int height)
+{
+ assert(bw);
+
+ if (bw->window == NULL) {
+ /* Core managed browser window */
+ bw->width = width;
+ bw->height = height;
+ } else {
+ NSLOG(netsurf, INFO,
+ "Asked to set dimensions of front end window.");
+ assert(0);
+ }
+}
+
+
+/* Exported interface, documented in browser/browser_private.h */
+nserror
+browser_window_invalidate_rect(struct browser_window *bw, struct rect *rect)
+{
+ int pos_x;
+ int pos_y;
+ struct browser_window *top = bw;
+
+ assert(bw);
+
+ if (bw->window == NULL) {
+ /* Core managed browser window */
+ browser_window_get_position(bw, true, &pos_x, &pos_y);
+
+ top = browser_window_get_root(bw);
+
+ rect->x0 += pos_x / bw->scale;
+ rect->y0 += pos_y / bw->scale;
+ rect->x1 += pos_x / bw->scale;
+ rect->y1 += pos_y / bw->scale;
+ }
+
+ rect->x0 *= top->scale;
+ rect->y0 *= top->scale;
+ rect->x1 *= top->scale;
+ rect->y1 *= top->scale;
+
+ return guit->window->invalidate(top->window, rect);
+}
+
+
+/* Exported interface, documented in netsurf/browser_window.h */
+void browser_window_stop(struct browser_window *bw)
+{
+ int children, index;
+
+ if (bw->loading_content != NULL) {
+ hlcache_handle_abort(bw->loading_content);
+ hlcache_handle_release(bw->loading_content);
+ bw->loading_content = NULL;
+ }
+
+ if (bw->current_content != NULL &&
+ content_get_status(bw->current_content) != CONTENT_STATUS_DONE) {
+ nserror error;
+ assert(content_get_status(bw->current_content) ==
+ CONTENT_STATUS_READY);
+ error = hlcache_handle_abort(bw->current_content);
+ assert(error == NSERROR_OK);
+ }
+
+ guit->misc->schedule(-1, browser_window_refresh, bw);
+
+ if (bw->children) {
+ children = bw->rows * bw->cols;
+ for (index = 0; index < children; index++)
+ browser_window_stop(&bw->children[index]);
+ }
+ if (bw->iframes) {
+ children = bw->iframe_count;
+ for (index = 0; index < children; index++)
+ browser_window_stop(&bw->iframes[index]);
+ }
+
+ if (bw->current_content != NULL) {
+ browser_window_refresh_url_bar(bw);
+ }
+
+ browser_window_stop_throbber(bw);
+}
+
+
+/* Exported interface, documented in netsurf/browser_window.h */
+nserror browser_window_reload(struct browser_window *bw, bool all)
+{
+ hlcache_handle *c;
+ unsigned int i;
+ struct nsurl *reload_url;
+
+ if ((bw->current_content) == NULL ||
+ (bw->loading_content) != NULL) {
+ return NSERROR_INVALID;
+ }
+
+ if (all && content_get_type(bw->current_content) == CONTENT_HTML) {
+ struct html_stylesheet *sheets;
+ struct content_html_object *object;
+ unsigned int count;
+
+ c = bw->current_content;
+
+ /* invalidate objects */
+ object = html_get_objects(c, &count);
+
+ for (; object != NULL; object = object->next) {
+ if (object->content != NULL)
+ content_invalidate_reuse_data(object->content);
+ }
+
+ /* invalidate stylesheets */
+ sheets = html_get_stylesheets(c, &count);
+
+ for (i = STYLESHEET_START; i != count; i++) {
+ if (sheets[i].sheet != NULL) {
+ content_invalidate_reuse_data(sheets[i].sheet);
+ }
+ }
+ }
+
+ content_invalidate_reuse_data(bw->current_content);
+
+ reload_url = hlcache_handle_get_url(bw->current_content);
+
+ return browser_window_navigate(bw,
+ reload_url,
+ NULL,
+ BW_NAVIGATE_NONE,
+ NULL,
+ NULL,
+ NULL);
+}
+
+
+/* Exported interface, documented in netsurf/browser_window.h */
+void browser_window_set_status(struct browser_window *bw, const char *text)
+{
+ int text_len;
+ /* find topmost window */
+ while (bw->parent)
+ bw = bw->parent;
+
+ if ((bw->status.text != NULL) &&
+ (strcmp(text, bw->status.text) == 0)) {
+ /* status text is unchanged */
+ bw->status.match++;
+ return;
+ }
+
+ /* status text is changed */
+
+ text_len = strlen(text);
+
+ if ((bw->status.text == NULL) || (bw->status.text_len < text_len)) {
+ /* no current string allocation or it is not long enough */
+ free(bw->status.text);
+ bw->status.text = strdup(text);
+ bw->status.text_len = text_len;
+ } else {
+ /* current allocation has enough space */
+ memcpy(bw->status.text, text, text_len + 1);
+ }
+
+ bw->status.miss++;
+ guit->window->set_status(bw->window, bw->status.text);
+}
+
+
+/* Exported interface, documented in netsurf/browser_window.h */
+void browser_window_set_pointer(struct browser_window *bw,
+ browser_pointer_shape shape)
+{
+ struct browser_window *root = browser_window_get_root(bw);
+ gui_pointer_shape gui_shape;
+ bool loading;
+ uint64_t ms_now;
+
+ assert(root);
+ assert(root->window);
+
+ loading = ((bw->loading_content != NULL) ||
+ ((bw->current_content != NULL) &&
+ (content_get_status(bw->current_content) == CONTENT_STATUS_READY)));
+
+ nsu_getmonotonic_ms(&ms_now);
+
+ if (loading && ((ms_now - bw->last_action) < 1000)) {
+ /* If loading and less than 1 second since last link followed,
+ * force progress indicator pointer */
+ gui_shape = GUI_POINTER_PROGRESS;
+
+ } else if (shape == BROWSER_POINTER_AUTO) {
+ /* Up to browser window to decide */
+ if (loading) {
+ gui_shape = GUI_POINTER_PROGRESS;
+ } else {
+ gui_shape = GUI_POINTER_DEFAULT;
+ }
+
+ } else {
+ /* Use what we were told */
+ gui_shape = (gui_pointer_shape)shape;
+ }
+
+ guit->window->set_pointer(root->window, gui_shape);
+}
+
+
+/* exported function documented in netsurf/browser_window.h */
+nserror browser_window_schedule_reformat(struct browser_window *bw)
+{
+ if (bw->window == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ return guit->misc->schedule(0, scheduled_reformat, bw);
+}
+
+
+/* exported function documented in netsurf/browser_window.h */
+void
+browser_window_reformat(struct browser_window *bw,
+ bool background,
+ int width,
+ int height)
+{
+ hlcache_handle *c = bw->current_content;
+
+ if (c == NULL)
+ return;
+
+ if (bw->browser_window_type != BROWSER_WINDOW_IFRAME) {
+ /* Iframe dimensions are already scaled in parent's layout */
+ width /= bw->scale;
+ height /= bw->scale;
+ }
+
+ if (bw->window == NULL) {
+ /* Core managed browser window; subtract scrollbar width */
+ width -= bw->scroll_y ? SCROLLBAR_WIDTH : 0;
+ height -= bw->scroll_x ? SCROLLBAR_WIDTH : 0;
+
+ width = width > 0 ? width : 0;
+ height = height > 0 ? height : 0;
+ }
+
+ content_reformat(c, background, width, height);
+}
+
+
+/* exported interface documented in netsurf/browser_window.h */
+nserror
+browser_window_set_scale(struct browser_window *bw, float scale, bool absolute)
+{
+ nserror res;
+
+ /* get top browser window */
+ while (bw->parent) {
+ bw = bw->parent;
+ }
+
+ if (!absolute) {
+ /* snap small values around 1.0 */
+ if ((scale + bw->scale) > (1.01 - scale) &&
+ (scale + bw->scale) < (0.99 + scale)) {
+ scale = 1.0;
+ } else {
+ scale += bw->scale;
+ }
+ }
+
+ /* clamp range between 0.1 and 10 (10% and 1000%) */
+ if (scale < SCALE_MINIMUM) {
+ scale = SCALE_MINIMUM;
+ } else if (scale > SCALE_MAXIMUM) {
+ scale = SCALE_MAXIMUM;
+ }
+
+ res = browser_window_set_scale_internal(bw, scale);
+ if (res == NSERROR_OK) {
+ browser_window_recalculate_frameset(bw);
+ }
+
+ return res;
+}
+
+
+/* exported interface documented in netsurf/browser_window.h */
+float browser_window_get_scale(struct browser_window *bw)
+{
+ if (bw == NULL) {
+ return 1.0;
+ }
+
+ return bw->scale;
+}
+
+
+/* exported interface documented in netsurf/browser_window.h */
+struct browser_window *
+browser_window_find_target(struct browser_window *bw,
+ const char *target,
+ browser_mouse_state mouse)
+{
+ struct browser_window *bw_target;
+ struct browser_window *top;
+ hlcache_handle *c;
+ int rdepth;
+ nserror error;
+
+ /* use the base target if we don't have one */
+ c = bw->current_content;
+ if (target == NULL &&
+ c != NULL &&
+ content_get_type(c) == CONTENT_HTML) {
+ target = html_get_base_target(c);
+ }
+ if (target == NULL) {
+ target = "_self";
+ }
+
+ /* allow the simple case of target="_blank" to be ignored if requested
+ */
+ if ((!(mouse & BROWSER_MOUSE_CLICK_2)) &&
+ (!((mouse & BROWSER_MOUSE_CLICK_2) &&
+ (mouse & BROWSER_MOUSE_MOD_2))) &&
+ (!nsoption_bool(target_blank))) {
+ /* not a mouse button 2 click
+ * not a mouse button 1 click with ctrl pressed
+ * configured to ignore target="_blank" */
+ if (!strcasecmp(target, "_blank"))
+ return bw;
+ }
+
+ /* handle reserved keywords */
+ if (((nsoption_bool(button_2_tab)) &&
+ (mouse & BROWSER_MOUSE_CLICK_2))||
+ ((!nsoption_bool(button_2_tab)) &&
+ ((mouse & BROWSER_MOUSE_CLICK_1) &&
+ (mouse & BROWSER_MOUSE_MOD_2))) ||
+ ((nsoption_bool(button_2_tab)) &&
+ (!strcasecmp(target, "_blank")))) {
+ /* open in new tab if:
+ * - button_2 opens in new tab and button_2 was pressed
+ * OR
+ * - button_2 doesn't open in new tabs and button_1 was
+ * pressed with ctrl held
+ * OR
+ * - button_2 opens in new tab and the link target is "_blank"
+ */
+ error = browser_window_create(BW_CREATE_TAB |
+ BW_CREATE_HISTORY |
+ BW_CREATE_CLONE,
+ NULL,
+ NULL,
+ bw,
+ &bw_target);
+ if (error != NSERROR_OK) {
+ return bw;
+ }
+ return bw_target;
+ } else if (((!nsoption_bool(button_2_tab)) &&
+ (mouse & BROWSER_MOUSE_CLICK_2)) ||
+ ((nsoption_bool(button_2_tab)) &&
+ ((mouse & BROWSER_MOUSE_CLICK_1) &&
+ (mouse & BROWSER_MOUSE_MOD_2))) ||
+ ((!nsoption_bool(button_2_tab)) &&
+ (!strcasecmp(target, "_blank")))) {
+ /* open in new window if:
+ * - button_2 doesn't open in new tabs and button_2 was pressed
+ * OR
+ * - button_2 opens in new tab and button_1 was pressed with
+ * ctrl held
+ * OR
+ * - button_2 doesn't open in new tabs and the link target is
+ * "_blank"
+ */
+ error = browser_window_create(BW_CREATE_HISTORY |
+ BW_CREATE_CLONE,
+ NULL,
+ NULL,
+ bw,
+ &bw_target);
+ if (error != NSERROR_OK) {
+ return bw;
+ }
+ return bw_target;
+ } else if (!strcasecmp(target, "_self")) {
+ return bw;
+ } else if (!strcasecmp(target, "_parent")) {
+ if (bw->parent)
+ return bw->parent;
+ return bw;
+ } else if (!strcasecmp(target, "_top")) {
+ while (bw->parent)
+ bw = bw->parent;
+ return bw;
+ }
+
+ /* find frame according to B.8, ie using the following priorities:
+ *
+ * 1) current frame
+ * 2) closest to front
+ */
+ rdepth = -1;
+ bw_target = NULL;
+ for (top = bw; top->parent; top = top->parent);
+ browser_window_find_target_internal(top, target, 0, bw, &rdepth,
+ &bw_target);
+ if (bw_target)
+ return bw_target;
+
+ /* we require a new window using the target name */
+ if (!nsoption_bool(target_blank))
+ return bw;
+
+ error = browser_window_create(BW_CREATE_CLONE | BW_CREATE_HISTORY,
+ NULL,
+ NULL,
+ bw,
+ &bw_target);
+ if (error != NSERROR_OK) {
+ return bw;
+ }
+
+ /* frame names should begin with an alphabetic character (a-z,A-Z),
+ * however in practice you get things such as '_new' and '2left'. The
+ * only real effect this has is when giving out names as it can be
+ * assumed that an author intended '_new' to create a new nameless
+ * window (ie '_blank') whereas in the case of '2left' the intention
+ * was for a new named window. As such we merely special case windows
+ * that begin with an underscore. */
+ if (target[0] != '_') {
+ bw_target->name = strdup(target);
+ }
+ return bw_target;
+}
+
+
+/* exported interface documented in netsurf/browser_window.h */
+void
+browser_window_mouse_track(struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ browser_window_mouse_track_internal(bw,
+ mouse,
+ x / bw->scale,
+ y / bw->scale);
+}
+
+/* exported interface documented in netsurf/browser_window.h */
+void
+browser_window_mouse_click(struct browser_window *bw,
+ browser_mouse_state mouse,
+ int x, int y)
+{
+ browser_window_mouse_click_internal(bw,
+ mouse,
+ x / bw->scale,
+ y / bw->scale);
+}
+
+
+/* exported interface documented in netsurf/browser_window.h */
+void browser_window_page_drag_start(struct browser_window *bw, int x, int y)
+{
+ assert(bw != NULL);
+
+ browser_window_set_drag_type(bw, DRAGGING_PAGE_SCROLL, NULL);
+
+ bw->drag.start_x = x;
+ bw->drag.start_y = y;
+
+ if (bw->window != NULL) {
+ /* Front end window */
+ guit->window->get_scroll(bw->window,
+ &bw->drag.start_scroll_x,
+ &bw->drag.start_scroll_y);
+
+ guit->window->event(bw->window, GW_EVENT_SCROLL_START);
+ } else {
+ /* Core managed browser window */
+ bw->drag.start_scroll_x = scrollbar_get_offset(bw->scroll_x);
+ bw->drag.start_scroll_y = scrollbar_get_offset(bw->scroll_y);
+ }
+}
+
+
+/* exported interface documented in netsurf/browser_window.h */
+bool browser_window_back_available(struct browser_window *bw)
+{
+ if (bw != NULL && bw->internal_nav) {
+ /* Internal nav, back is possible */
+ return true;
+ }
+ return (bw && bw->history && browser_window_history_back_available(bw));
+}
+
+
+/* exported interface documented in netsurf/browser_window.h */
+bool browser_window_forward_available(struct browser_window *bw)
+{
+ return (bw && bw->history && browser_window_history_forward_available(bw));
+}
+
+/* exported interface documented in netsurf/browser_window.h */
+bool browser_window_reload_available(struct browser_window *bw)
+{
+ return (bw && bw->current_content && !bw->loading_content);
+}
+
+
+/* exported interface documented in netsurf/browser_window.h */
+bool browser_window_stop_available(struct browser_window *bw)
+{
+ return (bw && (bw->loading_content ||
+ (bw->current_content &&
+ (content_get_status(bw->current_content) !=
+ CONTENT_STATUS_DONE))));
+}
+
+/* exported interface documented in netsurf/browser_window.h */
+bool
+browser_window_exec(struct browser_window *bw, const char *src, size_t srclen)
+{
+ assert(bw != NULL);
+
+ if (!bw->current_content) {
+ NSLOG(netsurf, DEEPDEBUG, "Unable to exec, no content");
+ return false;
+ }
+
+ if (content_get_status(bw->current_content) != CONTENT_STATUS_DONE) {
+ NSLOG(netsurf, DEEPDEBUG, "Unable to exec, content not done");
+ return false;
+ }
+
+ /* Okay it should be safe, forward the request through to the content
+ * itself. Only HTML contents currently support executing code
+ */
+ return content_exec(bw->current_content, src, srclen);
+}
+
+
+/* exported interface documented in browser_window.h */
+nserror
+browser_window_console_log(struct browser_window *bw,
+ browser_window_console_source src,
+ const char *msg,
+ size_t msglen,
+ browser_window_console_flags flags)
+{
+ browser_window_console_flags log_level = flags & BW_CS_FLAG_LEVEL_MASK;
+ struct browser_window *root = browser_window_get_root(bw);
+
+ assert(msg != NULL);
+ /* We don't assert msglen > 0, if someone wants to log a real empty
+ * string then we won't stop them. It does sometimes happen from
+ * JavaScript for example.
+ */
+
+ /* bw is the target of the log, but root is where we log it */
+
+ NSLOG(netsurf, DEEPDEBUG, "Logging message in %p targetted at %p", root, bw);
+ NSLOG(netsurf, DEEPDEBUG, "Log came from %s",
+ ((src == BW_CS_INPUT) ? "user input" :
+ (src == BW_CS_SCRIPT_ERROR) ? "script error" :
+ (src == BW_CS_SCRIPT_CONSOLE) ? "script console" :
+ "unknown input location"));
+
+ switch (log_level) {
+ case BW_CS_FLAG_LEVEL_DEBUG:
+ NSLOG(netsurf, DEBUG, "%.*s", (int)msglen, msg);
+ break;
+ case BW_CS_FLAG_LEVEL_LOG:
+ NSLOG(netsurf, VERBOSE, "%.*s", (int)msglen, msg);
+ break;
+ case BW_CS_FLAG_LEVEL_INFO:
+ NSLOG(netsurf, INFO, "%.*s", (int)msglen, msg);
+ break;
+ case BW_CS_FLAG_LEVEL_WARN:
+ NSLOG(netsurf, WARNING, "%.*s", (int)msglen, msg);
+ break;
+ case BW_CS_FLAG_LEVEL_ERROR:
+ NSLOG(netsurf, ERROR, "%.*s", (int)msglen, msg);
+ break;
+ default:
+ /* Unreachable */
+ break;
+ }
+
+ guit->window->console_log(root->window, src, msg, msglen, flags);
+
+ return NSERROR_OK;
+}
+
+
+/* Exported interface, documented in browser_private.h */
+nserror
+browser_window__reload_current_parameters(struct browser_window *bw)
+{
+ assert(bw != NULL);
+
+ if (bw->current_parameters.post_urlenc != NULL) {
+ free(bw->current_parameters.post_urlenc);
+ bw->current_parameters.post_urlenc = NULL;
+ }
+
+ if (bw->current_parameters.post_multipart != NULL) {
+ fetch_multipart_data_destroy(bw->current_parameters.post_multipart);
+ bw->current_parameters.post_multipart = NULL;
+ }
+
+ if (bw->current_parameters.url == NULL) {
+ /* We have never navigated so go to about:blank */
+ bw->current_parameters.url = nsurl_ref(corestring_nsurl_about_blank);
+ }
+
+ bw->current_parameters.flags &= ~BW_NAVIGATE_HISTORY;
+ bw->internal_nav = false;
+
+ browser_window__free_fetch_parameters(&bw->loading_parameters);
+ memcpy(&bw->loading_parameters, &bw->current_parameters, sizeof(bw->loading_parameters));
+ memset(&bw->current_parameters, 0, sizeof(bw->current_parameters));
+ return browser_window__navigate_internal(bw, &bw->loading_parameters);
+}
+
+/* Exported interface, documented in browser_window.h */
+browser_window_page_info_state browser_window_get_page_info_state(
+ const struct browser_window *bw)
+{
+ lwc_string *scheme;
+ bool match;
+
+ assert(bw != NULL);
+
+ /* Do we have any content? If not -- UNKNOWN */
+ if (bw->current_content == NULL) {
+ return PAGE_STATE_UNKNOWN;
+ }
+
+ scheme = nsurl_get_component(
+ hlcache_handle_get_url(bw->current_content), NSURL_SCHEME);
+
+ /* Is this an internal scheme? */
+ if ((lwc_string_isequal(scheme, corestring_lwc_about,
+ &match) == lwc_error_ok &&
+ (match == true)) ||
+ (lwc_string_isequal(scheme, corestring_lwc_data,
+ &match) == lwc_error_ok &&
+ (match == true)) ||
+ (lwc_string_isequal(scheme, corestring_lwc_resource,
+ &match) == lwc_error_ok &&
+ (match == true))) {
+ lwc_string_unref(scheme);
+ return PAGE_STATE_INTERNAL;
+ }
+
+ /* Is this file:/// ? */
+ if (lwc_string_isequal(scheme, corestring_lwc_file,
+ &match) == lwc_error_ok &&
+ match == true) {
+ lwc_string_unref(scheme);
+ return PAGE_STATE_LOCAL;
+ }
+
+ /* If not https, from here on down that'd be insecure */
+ if ((lwc_string_isequal(scheme, corestring_lwc_https,
+ &match) == lwc_error_ok &&
+ (match == false))) {
+ /* Some remote content, not https, therefore insecure */
+ lwc_string_unref(scheme);
+ return PAGE_STATE_INSECURE;
+ }
+
+ lwc_string_unref(scheme);
+
+ /* Did we have to override this SSL setting? */
+ if (urldb_get_cert_permissions(hlcache_handle_get_url(bw->current_content))) {
+ return PAGE_STATE_SECURE_OVERRIDE;
+ }
+
+ /* If we've seen insecure content internally then we need to say so */
+ if (content_saw_insecure_objects(bw->current_content)) {
+ return PAGE_STATE_SECURE_ISSUES;
+ }
+
+ /* All is well, return secure state */
+ return PAGE_STATE_SECURE;
+}
+
+/* Exported interface, documented in browser_window.h */
+nserror
+browser_window_get_ssl_chain(struct browser_window *bw,
+ struct cert_chain **chain)
+{
+ assert(bw != NULL);
+
+ if (bw->current_cert_chain == NULL) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ *chain = bw->current_cert_chain;
+
+ return NSERROR_OK;
+}
+
+/* Exported interface, documented in browser_window.h */
+int browser_window_get_cookie_count(
+ const struct browser_window *bw)
+{
+ int count = 0;
+ char *cookies = urldb_get_cookie(browser_window_access_url(bw), true);
+ if (cookies == NULL) {
+ return 0;
+ }
+
+ for (char *c = cookies; *c != '\0'; c++) {
+ if (*c == ';')
+ count++;
+ }
+
+ free(cookies);
+
+ return count;
+}
+
+/* Exported interface, documented in browser_window.h */
+nserror browser_window_show_cookies(
+ const struct browser_window *bw)
+{
+ nserror err;
+ nsurl *url = browser_window_access_url(bw);
+ lwc_string *host = nsurl_get_component(url, NSURL_HOST);
+ const char *string = (host != NULL) ? lwc_string_data(host) : NULL;
+
+ err = guit->misc->present_cookies(string);
+
+ if (host != NULL) {
+ lwc_string_unref(host);
+ }
+ return err;
+}
+
+/* Exported interface, documented in browser_window.h */
+nserror browser_window_show_certificates(struct browser_window *bw)
+{
+ nserror res;
+ nsurl *url;
+
+ if (bw->current_cert_chain == NULL) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ res = cert_chain_to_query(bw->current_cert_chain, &url);
+ if (res == NSERROR_OK) {
+ res = browser_window_create(BW_CREATE_HISTORY |
+ BW_CREATE_FOREGROUND |
+ BW_CREATE_TAB,
+ url,
+ NULL,
+ bw,
+ NULL);
+
+ nsurl_unref(url);
+ }
+
+ return res;
+}
diff --git a/desktop/cookie_manager.c b/desktop/cookie_manager.c
index a2aab8e9f..b5ec89618 100644
--- a/desktop/cookie_manager.c
+++ b/desktop/cookie_manager.c
@@ -232,10 +232,6 @@ cookie_manager_field_builder(enum cookie_manager_field field,
*
* The time should be converted to text in the users locacle
*
- * \todo This should probably generate the user text using localtime
- * and strftime with the c format specifier. Currently ctime will
- * always generate output in the C locale.
- *
* \param field Cookie manager treeview field to build
* \param fdata Cookie manager entry field data to set
* \param value Time to show in field
@@ -246,22 +242,20 @@ cookie_manager_field_builder_time(enum cookie_manager_field field,
struct treeview_field_data *fdata,
const time_t *value)
{
- const char *date;
- char *date2;
+ struct tm *ftime;
fdata->field = cm_ctx.fields[field].field;
-
- date = ctime(value);
- date2 = strdup(date);
- if (date2 == NULL) {
- fdata->value = NULL;
- fdata->value_len = 0;
- } else {
- assert(date2[24] == '\n');
- date2[24] = '\0';
-
- fdata->value = date2;
- fdata->value_len = strlen(date2);
+ fdata->value = NULL;
+ fdata->value_len = 0;
+
+ if ((ftime = localtime(value)) != NULL) {
+ const size_t vsize = 256;
+ char *value = malloc(vsize);
+ if (value != NULL) {
+ fdata->value = value;
+ fdata->value_len = strftime(value, vsize,
+ "%a %b %e %H:%M:%S %Y", ftime);
+ }
}
return NSERROR_OK;
@@ -545,6 +539,19 @@ void cookie_manager_remove(const struct cookie_data *data)
}
+/* exported interface documented in cookie_manager.h */
+nserror cookie_manager_set_search_string(
+ const char *string)
+{
+ /* If we don't have a cookie manager at the moment, just return */
+ if (cm_ctx.tree == NULL) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ return treeview_set_search_string(cm_ctx.tree, string);
+}
+
+
/**
* Initialise the treeview entry feilds
*
diff --git a/desktop/cookie_manager.h b/desktop/cookie_manager.h
index 4ae74a25f..11d03252e 100644
--- a/desktop/cookie_manager.h
+++ b/desktop/cookie_manager.h
@@ -76,6 +76,15 @@ bool cookie_manager_add(const struct cookie_data *data);
void cookie_manager_remove(const struct cookie_data *data);
/**
+ * Set the cookie manager search string.
+ *
+ * \param string Sering to set as search string.
+ * \return NSERROR_OK on success, appropriate error otherwise
+ */
+nserror cookie_manager_set_search_string(
+ const char *string);
+
+/**
* Redraw the cookies manager.
*
* \param x X coordinate to render treeview at
diff --git a/desktop/cw_helper.c b/desktop/cw_helper.c
new file mode 100644
index 000000000..5844e88bd
--- /dev/null
+++ b/desktop/cw_helper.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2019 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ * Copyright 2019 Michael Drake <tlsa@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ *
+ * Helpers to simplify core use of corewindow.
+ */
+
+#include "utils/errors.h"
+#include "netsurf/browser.h"
+#include "netsurf/core_window.h"
+#include "netsurf/types.h"
+#include "css/utils.h"
+#include "desktop/cw_helper.h"
+
+/* exported interface documented in cw_helper.h */
+nserror cw_helper_scroll_visible(
+ const struct core_window_callback_table *cw_t,
+ struct core_window *cw_h,
+ const struct rect *r)
+{
+ nserror err;
+ int height;
+ int width;
+ int x0;
+ int y0;
+ int x1;
+ int y1;
+
+ assert(cw_t != NULL);
+ assert(cw_h != NULL);
+ assert(cw_t->get_scroll != NULL);
+ assert(cw_t->set_scroll != NULL);
+ assert(cw_t->get_window_dimensions != NULL);
+
+ err = cw_t->get_window_dimensions(cw_h, &width, &height);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
+ cw_t->get_scroll(cw_h, &x0, &y0);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
+ y1 = y0 + height;
+ x1 = x0 + width;
+
+ if (r->y1 > y1) {
+ /* The bottom of the rectangle is off the bottom of the
+ * window, so scroll down to fit it
+ */
+ y0 = r->y1 - height;
+ }
+ if (r->y0 < y0) {
+ /* The top of the rectangle is off the top of the window,
+ * so scroll up to fit it
+ */
+ y0 = r->y0;
+ }
+ if (r->x1 > x1) {
+ /* The right of the rectangle is off the right of the window
+ * so scroll right to fit it
+ */
+ x0 = r->x1 - width;
+ }
+ if (r->x0 < x0) {
+ /* The left of the rectangle is off the left of the window
+ * so scroll left to fit it
+ */
+ x0 = r->x0;
+ }
+
+ return cw_t->set_scroll(cw_h, x0, y0);
+}
diff --git a/desktop/cw_helper.h b/desktop/cw_helper.h
new file mode 100644
index 000000000..14e699342
--- /dev/null
+++ b/desktop/cw_helper.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2019 Michael Drake <tlsa@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ *
+ * Helpers to simplify core use of corewindow.
+ */
+
+#ifndef NETSURF_DESKTOP_CW_HELPER_H_
+#define NETSURF_DESKTOP_CW_HELPER_H_
+
+struct rect;
+struct core_window;
+struct core_window_callback_table;
+
+/**
+ * Scroll a core window to make the given rectangle visible.
+ *
+ * \param[in] cw_t The core window callback table to use.
+ * \param[in] cw_h The core window's handle.
+ * \param[in] r The rectangle to make visisble by scrolling.
+ * \return NSERROR_OK on success or appropriate error code
+ */
+nserror cw_helper_scroll_visible(
+ const struct core_window_callback_table *cw_t,
+ struct core_window *cw_h,
+ const struct rect *r);
+
+#endif
diff --git a/desktop/download.c b/desktop/download.c
index 76c294977..4931371fb 100644
--- a/desktop/download.c
+++ b/desktop/download.c
@@ -29,6 +29,7 @@
#include "utils/corestrings.h"
#include "utils/http.h"
#include "utils/utils.h"
+#include "utils/log.h"
#include "desktop/download.h"
#include "netsurf/download.h"
#include "desktop/gui_internal.h"
@@ -41,7 +42,7 @@ struct download_context {
struct gui_window *parent; /**< Parent window */
lwc_string *mime_type; /**< MIME type of download */
- unsigned long total_length; /**< Length of data, in bytes */
+ unsigned long long int total_length; /**< Length of data, in bytes */
char *filename; /**< Suggested filename */
struct gui_download_window *window; /**< GUI download window */
@@ -93,7 +94,7 @@ static nserror download_context_process_headers(download_context *ctx)
{
const char *http_header;
http_content_type *content_type;
- unsigned long length;
+ unsigned long long int length;
nserror error;
/* Retrieve and parse Content-Type */
@@ -107,10 +108,11 @@ static nserror download_context_process_headers(download_context *ctx)
/* Retrieve and parse Content-Length */
http_header = llcache_handle_get_header(ctx->llcache, "Content-Length");
- if (http_header == NULL)
+ if (http_header == NULL) {
length = 0;
- else
- length = strtoul(http_header, NULL, 10);
+ } else {
+ length = strtoull(http_header, NULL, 10);
+ }
/* Retrieve and parse Content-Disposition */
http_header = llcache_handle_get_header(ctx->llcache,
@@ -180,6 +182,9 @@ static nserror download_callback(llcache_handle *handle,
nserror error = NSERROR_OK;
switch (event->type) {
+ case LLCACHE_EVENT_GOT_CERTS:
+ /* Nominally not interested in these */
+ break;
case LLCACHE_EVENT_HAD_HEADERS:
error = download_context_process_headers(ctx);
if (error != NSERROR_OK) {
@@ -223,7 +228,7 @@ static nserror download_callback(llcache_handle *handle,
case LLCACHE_EVENT_ERROR:
if (ctx->window != NULL)
- guit->download->error(ctx->window, event->data.msg);
+ guit->download->error(ctx->window, event->data.error.msg);
else
download_context_destroy(ctx);
@@ -295,7 +300,8 @@ const char *download_context_get_mime_type(const download_context *ctx)
}
/* See download.h for documentation */
-unsigned long download_context_get_total_length(const download_context *ctx)
+unsigned long long int
+download_context_get_total_length(const download_context *ctx)
{
return ctx->total_length;
}
diff --git a/desktop/download.h b/desktop/download.h
index dc2befd90..b704c4c7d 100644
--- a/desktop/download.h
+++ b/desktop/download.h
@@ -91,7 +91,7 @@ const char *download_context_get_mime_type(const download_context *ctx);
* \param ctx Context to retrieve byte length from
* \return Total length, in bytes, or 0 if unknown
*/
-unsigned long download_context_get_total_length(const download_context *ctx);
+unsigned long long int download_context_get_total_length(const download_context *ctx);
/**
* Retrieve the filename for a download
diff --git a/desktop/font_haru.c b/desktop/font_haru.c
index f92d89197..4ee9824f0 100644
--- a/desktop/font_haru.c
+++ b/desktop/font_haru.c
@@ -352,7 +352,7 @@ bool haru_nsfont_apply_style(const plot_font_style_t *fstyle,
if (size <= 0)
return true;
- size /= FONT_SIZE_SCALE;
+ size /= PLOT_STYLE_SCALE;
if (size > HPDF_MAX_FONTSIZE)
size = HPDF_MAX_FONTSIZE;
diff --git a/desktop/frames.c b/desktop/frames.c
index e22287630..85f18793e 100644
--- a/desktop/frames.c
+++ b/desktop/frames.c
@@ -33,8 +33,9 @@
#include "utils/utils.h"
#include "netsurf/content.h"
#include "content/hlcache.h"
-#include "render/html.h"
-#include "render/box.h"
+#include "html/html.h"
+#include "html/box.h"
+#include "html/box_inspect.h"
#include "desktop/browser_private.h"
#include "desktop/frames.h"
@@ -68,7 +69,7 @@ void browser_window_scroll_callback(void *client_data,
rect.x1 = rect.x0 + bw->width;
rect.y1 = rect.y0 + bw->height;
- browser_window_update_box(bw, &rect);
+ browser_window_invalidate_rect(bw, &rect);
}
break;
case SCROLLBAR_MSG_SCROLL_START:
@@ -180,20 +181,35 @@ void browser_window_handle_scrollbars(struct browser_window *bw)
scrollbar_make_pair(bw->scroll_x, bw->scroll_y);
}
+/* exported function documented in desktop/frames.h */
+nserror browser_window_invalidate_iframe(struct browser_window *bw)
+{
+ html_redraw_a_box(bw->parent->current_content, bw->box);
+ return NSERROR_OK;
+}
/* exported function documented in desktop/frames.h */
-nserror browser_window_create_iframes(struct browser_window *bw,
- struct content_html_iframe *iframe)
+nserror browser_window_create_iframes(struct browser_window *bw)
{
+ nserror ret = NSERROR_OK;
struct browser_window *window;
struct content_html_iframe *cur;
struct rect rect;
int iframes = 0;
int index;
- nserror ret = NSERROR_OK;
+ struct content_html_iframe *iframe;
+
+ bw->iframe_count = 0;
+
+ /* only html contents can have iframes */
+ if (content_get_type(bw->current_content) != CONTENT_HTML) {
+ return NSERROR_OK;
+ }
+ /* obtain the iframes for this content */
+ iframe = html_get_iframe(bw->current_content);
if (iframe == NULL) {
- return NSERROR_BAD_PARAMETER;
+ return NSERROR_OK;
}
/* Count iframe list and allocate enough space within the
@@ -271,12 +287,7 @@ nserror browser_window_create_iframes(struct browser_window *bw,
}
-/**
- * Recalculate iframe positions following a resize.
- *
- * \param bw The browser window to reposition iframes for
- */
-
+/* exported function documented in desktop/frames.h */
void browser_window_recalculate_iframes(struct browser_window *bw)
{
struct browser_window *window;
@@ -292,123 +303,23 @@ void browser_window_recalculate_iframes(struct browser_window *bw)
}
-/* exported interface documented in desktop/frames.h */
-nserror browser_window_create_frameset(struct browser_window *bw,
- struct content_html_frames *frameset)
+/* exported function documented in desktop/frames.h */
+nserror browser_window_destroy_iframes(struct browser_window *bw)
{
- int row, col, index;
- struct content_html_frames *frame;
- struct browser_window *window;
- hlcache_handle *parent;
-
- assert(bw && frameset);
-
- /* 1. Create children */
- assert(bw->children == NULL);
- assert(frameset->cols + frameset->rows != 0);
-
- bw->children = calloc((frameset->cols * frameset->rows), sizeof(*bw));
- if (!bw->children) {
- return NSERROR_NOMEM;
- }
-
- bw->cols = frameset->cols;
- bw->rows = frameset->rows;
- for (row = 0; row < bw->rows; row++) {
- for (col = 0; col < bw->cols; col++) {
- index = (row * bw->cols) + col;
- frame = &frameset->children[index];
- window = &bw->children[index];
-
- /* Initialise common parts */
- browser_window_initialise_common(BW_CREATE_NONE,
- window, NULL);
+ int i;
- /* window characteristics */
- if (frame->children)
- window->browser_window_type =
- BROWSER_WINDOW_FRAMESET;
- else
- window->browser_window_type =
- BROWSER_WINDOW_FRAME;
- window->scrolling = frame->scrolling;
- window->border = frame->border;
- window->border_colour = frame->border_colour;
- window->no_resize = frame->no_resize;
- window->frame_width = frame->width;
- window->frame_height = frame->height;
- window->margin_width = frame->margin_width;
- window->margin_height = frame->margin_height;
- if (frame->name) {
- window->name = strdup(frame->name);
- if (!window->name) {
- free(bw->children);
- bw->children = NULL;
- return NSERROR_NOMEM;
- }
+ if (bw->iframes != NULL) {
+ for (i = 0; i < bw->iframe_count; i++) {
+ if (bw->iframes[i].box != NULL) {
+ bw->iframes[i].box->iframe = NULL;
+ bw->iframes[i].box = NULL;
}
-
- window->scale = bw->scale;
-
- /* linking */
- window->parent = bw;
-
- if (window->name)
- NSLOG(netsurf, INFO, "Created frame '%s'",
- window->name);
- else
- NSLOG(netsurf, INFO,
- "Created frame (unnamed)");
- }
- }
-
- /* 2. Calculate dimensions */
- browser_window_update_extent(bw);
- browser_window_recalculate_frameset(bw);
-
- /* 3. Recurse for grandchildren */
- for (row = 0; row < bw->rows; row++) {
- for (col = 0; col < bw->cols; col++) {
- index = (row * bw->cols) + col;
- frame = &frameset->children[index];
- window = &bw->children[index];
-
- if (frame->children)
- browser_window_create_frameset(window, frame);
+ browser_window_destroy_internal(&bw->iframes[i]);
}
+ free(bw->iframes);
+ bw->iframes = NULL;
+ bw->iframe_count = 0;
}
-
- /* Use the URL of the first ancestor window containing html content
- * as the referer */
- for (window = bw; window->parent; window = window->parent) {
- if (window->current_content &&
- content_get_type(window->current_content) ==
- CONTENT_HTML)
- break;
- }
-
- parent = window->current_content;
-
- /* 4. Launch content */
- for (row = 0; row < bw->rows; row++) {
- for (col = 0; col < bw->cols; col++) {
- index = (row * bw->cols) + col;
- frame = &frameset->children[index];
- window = &bw->children[index];
-
- if (frame->url) {
- browser_window_navigate(window,
- frame->url,
- hlcache_handle_get_url(parent),
- BW_NAVIGATE_HISTORY |
- BW_NAVIGATE_UNVERIFIABLE,
- NULL,
- NULL,
- parent);
- }
- }
- }
-
return NSERROR_OK;
}
@@ -416,10 +327,9 @@ nserror browser_window_create_frameset(struct browser_window *bw,
/**
* Recalculate frameset positions following a resize.
*
- * \param bw The browser window to reposition framesets for
+ * \param bw The browser window to reposition framesets for
*/
-
-void browser_window_recalculate_frameset(struct browser_window *bw)
+static void browser_window_recalculate_frameset_internal(struct browser_window *bw)
{
int widths[bw->cols][bw->rows];
int heights[bw->cols][bw->rows];
@@ -436,7 +346,9 @@ void browser_window_recalculate_frameset(struct browser_window *bw)
/* window dimensions */
if (!bw->parent) {
- browser_window_get_dimensions(bw, &bw_width, &bw_height, true);
+ browser_window_get_dimensions(bw, &bw_width, &bw_height);
+ bw_width /= bw->scale;
+ bw_height /= bw->scale;
bw->x = 0;
bw->y = 0;
bw->width = bw_width;
@@ -643,9 +555,177 @@ void browser_window_recalculate_frameset(struct browser_window *bw)
x += widths[col][row];
if (window->children)
- browser_window_recalculate_frameset(window);
+ browser_window_recalculate_frameset_internal(window);
+ }
+ }
+}
+
+
+/**
+ * Create and open a frameset for a browser window.
+ *
+ * \param[in,out] bw The browser window to create the frameset for
+ * \param[in] frameset The frameset to create
+ * \return NSERROR_OK or error code on faliure
+ */
+static nserror
+browser_window_create_frameset_internal(struct browser_window *bw,
+ struct content_html_frames *frameset)
+{
+ int row, col, index;
+ struct content_html_frames *frame;
+ struct browser_window *window;
+ hlcache_handle *parent;
+
+ assert(bw && frameset);
+
+ /* 1. Create children */
+ assert(bw->children == NULL);
+ assert(frameset->cols + frameset->rows != 0);
+
+ bw->children = calloc((frameset->cols * frameset->rows), sizeof(*bw));
+ if (!bw->children) {
+ return NSERROR_NOMEM;
+ }
+
+ bw->cols = frameset->cols;
+ bw->rows = frameset->rows;
+ for (row = 0; row < bw->rows; row++) {
+ for (col = 0; col < bw->cols; col++) {
+ index = (row * bw->cols) + col;
+ frame = &frameset->children[index];
+ window = &bw->children[index];
+
+ /* Initialise common parts */
+ browser_window_initialise_common(BW_CREATE_NONE,
+ window, NULL);
+
+ /* window characteristics */
+ if (frame->children)
+ window->browser_window_type =
+ BROWSER_WINDOW_FRAMESET;
+ else
+ window->browser_window_type =
+ BROWSER_WINDOW_FRAME;
+ window->scrolling = frame->scrolling;
+ window->border = frame->border;
+ window->border_colour = frame->border_colour;
+ window->no_resize = frame->no_resize;
+ window->frame_width = frame->width;
+ window->frame_height = frame->height;
+ window->margin_width = frame->margin_width;
+ window->margin_height = frame->margin_height;
+ if (frame->name) {
+ window->name = strdup(frame->name);
+ if (!window->name) {
+ free(bw->children);
+ bw->children = NULL;
+ return NSERROR_NOMEM;
+ }
+ }
+
+ window->scale = bw->scale;
+
+ /* linking */
+ window->parent = bw;
+
+ if (window->name)
+ NSLOG(netsurf, INFO, "Created frame '%s'",
+ window->name);
+ else
+ NSLOG(netsurf, INFO,
+ "Created frame (unnamed)");
}
}
+
+ /* 2. Calculate dimensions */
+ browser_window_update_extent(bw);
+ browser_window_recalculate_frameset_internal(bw);
+
+ /* 3. Recurse for grandchildren */
+ for (row = 0; row < bw->rows; row++) {
+ for (col = 0; col < bw->cols; col++) {
+ index = (row * bw->cols) + col;
+ frame = &frameset->children[index];
+ window = &bw->children[index];
+
+ if (frame->children)
+ browser_window_create_frameset_internal(window, frame);
+ }
+ }
+
+ /* Use the URL of the first ancestor window containing html content
+ * as the referer */
+ for (window = bw; window->parent; window = window->parent) {
+ if (window->current_content &&
+ content_get_type(window->current_content) ==
+ CONTENT_HTML)
+ break;
+ }
+
+ parent = window->current_content;
+
+ /* 4. Launch content */
+ for (row = 0; row < bw->rows; row++) {
+ for (col = 0; col < bw->cols; col++) {
+ index = (row * bw->cols) + col;
+ frame = &frameset->children[index];
+ window = &bw->children[index];
+
+ if (frame->url) {
+ browser_window_navigate(window,
+ frame->url,
+ hlcache_handle_get_url(parent),
+ BW_NAVIGATE_HISTORY |
+ BW_NAVIGATE_UNVERIFIABLE,
+ NULL,
+ NULL,
+ parent);
+ }
+ }
+ }
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in desktop/frames.h */
+nserror browser_window_create_frameset(struct browser_window *bw)
+{
+ struct content_html_frames *frameset;
+
+ if (content_get_type(bw->current_content) != CONTENT_HTML) {
+ return NSERROR_OK;
+ }
+
+ frameset = html_get_frameset(bw->current_content);
+ if (frameset == NULL) {
+ return NSERROR_OK;
+ }
+
+ return browser_window_create_frameset_internal(bw, frameset);
+}
+
+
+
+
+/**
+ * Recalculate frameset positions following a resize.
+ *
+ * \param bw The browser window to reposition framesets for
+ */
+
+void browser_window_recalculate_frameset(struct browser_window *bw)
+{
+ if (content_get_type(bw->current_content) != CONTENT_HTML) {
+ return;
+ }
+
+ if (html_get_frameset(bw->current_content) == NULL) {
+ return;
+ }
+
+ browser_window_recalculate_frameset_internal(bw);
}
@@ -700,7 +780,7 @@ void browser_window_resize_frame(struct browser_window *bw, int x, int y)
}
if (change) {
- browser_window_recalculate_frameset(parent);
+ browser_window_recalculate_frameset_internal(parent);
}
}
diff --git a/desktop/frames.h b/desktop/frames.h
index 063e2c558..dda31824b 100644
--- a/desktop/frames.h
+++ b/desktop/frames.h
@@ -16,12 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Frame and frameset creation and manipulation (interface).
*/
-#ifndef _NETSURF_DESKTOP_FRAMES_H_
-#define _NETSURF_DESKTOP_FRAMES_H_
+#ifndef NETSURF_DESKTOP_FRAMES_H_
+#define NETSURF_DESKTOP_FRAMES_H_
struct scrollbar_msg_data;
struct content_html_iframe;
@@ -30,23 +31,40 @@ struct content_html_frames;
/**
* Create and open iframes for a browser window.
*
- * \param bw The browser window to create iframes for.
- * \param iframe The iframes to create from.
+ * \param bw The browser window to create iframes for.
* \return NSERROR_OK or error code on faliure.
*/
-nserror browser_window_create_iframes(struct browser_window *bw,
- struct content_html_iframe *iframe);
+nserror browser_window_create_iframes(struct browser_window *bw);
+
+/**
+ * Recalculate iframe positions following a resize.
+ *
+ * \param bw The browser window to reposition iframes for
+ */
void browser_window_recalculate_iframes(struct browser_window *bw);
/**
+ * Invalidate an iframe causing a redraw.
+ *
+ * \param bw The browser window to invalidate
+ */
+nserror browser_window_invalidate_iframe(struct browser_window *bw);
+
+/**
+ * Destroy iframes opened in browser_window_create_iframes()
+ *
+ * \param bw The browser window to destroy iframes for.
+ * \return NSERROR_OK
+ */
+nserror browser_window_destroy_iframes(struct browser_window *bw);
+
+/**
* Create and open a frameset for a browser window.
*
* \param[in,out] bw The browser window to create the frameset for
- * \param[in] frameset The frameset to create
* \return NSERROR_OK or error code on faliure
*/
-nserror browser_window_create_frameset(struct browser_window *bw,
- struct content_html_frames *frameset);
+nserror browser_window_create_frameset(struct browser_window *bw);
void browser_window_recalculate_frameset(struct browser_window *bw);
bool browser_window_frame_resize_start(struct browser_window *bw,
diff --git a/desktop/global_history.c b/desktop/global_history.c
index ad39a3e41..e98e4cb29 100644
--- a/desktop/global_history.c
+++ b/desktop/global_history.c
@@ -266,9 +266,9 @@ static nserror global_history_create_treeview_field_data(
const char *title = (data->title != NULL) ?
data->title : messages_get("NoTitle");
char buffer[16];
- const char *last_visited;
- char *last_visited2;
- int len;
+ struct tm *lvtime;
+ char *last_visited = NULL;
+ size_t len = 0;
e->data[GH_TITLE].field = gh_ctx.fields[GH_TITLE].field;
e->data[GH_TITLE].value = strdup(title);
@@ -279,16 +279,18 @@ static nserror global_history_create_treeview_field_data(
e->data[GH_URL].value = nsurl_access(e->url);
e->data[GH_URL].value_len = nsurl_length(e->url);
- last_visited = ctime(&data->last_visit);
- last_visited2 = strdup(last_visited);
- if (last_visited2 != NULL) {
- assert(last_visited2[24] == '\n');
- last_visited2[24] = '\0';
+ if ((lvtime = localtime(&data->last_visit)) != NULL) {
+ const size_t lvsize = 256;
+ last_visited = malloc(lvsize);
+ if (last_visited != NULL) {
+ len = strftime(last_visited, lvsize,
+ "%a %b %e %H:%M:%S %Y", lvtime);
+ }
}
e->data[GH_LAST_VISIT].field = gh_ctx.fields[GH_LAST_VISIT].field;
- e->data[GH_LAST_VISIT].value = last_visited2;
- e->data[GH_LAST_VISIT].value_len = (last_visited2 != NULL) ? 24 : 0;
+ e->data[GH_LAST_VISIT].value = last_visited;
+ e->data[GH_LAST_VISIT].value_len = len;
len = snprintf(buffer, 16, "%u", data->visits);
if (len == 16) {
diff --git a/desktop/gui_factory.c b/desktop/gui_factory.c
index ca9eff1da..0d4d9a904 100644
--- a/desktop/gui_factory.c
+++ b/desktop/gui_factory.c
@@ -19,10 +19,13 @@
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
#include "utils/config.h"
#include "utils/errors.h"
#include "utils/file.h"
+#include "utils/inet.h"
#include "netsurf/bitmap.h"
#include "content/hlcache.h"
#include "content/backing_store.h"
@@ -55,14 +58,6 @@ static nserror gui_default_window_set_url(struct gui_window *g, struct nsurl *ur
return NSERROR_OK;
}
-static void gui_default_window_start_throbber(struct gui_window *g)
-{
-}
-
-static void gui_default_window_stop_throbber(struct gui_window *g)
-{
-}
-
static bool gui_default_window_drag_start(struct gui_window *g,
gui_drag_type type,
const struct rect *rect)
@@ -82,17 +77,6 @@ static void gui_default_window_set_icon(struct gui_window *g,
{
}
-
-static void gui_default_window_new_content(struct gui_window *g)
-{
-}
-
-
-static bool gui_default_window_scroll_start(struct gui_window *g)
-{
- return true;
-}
-
static void gui_default_window_set_pointer(struct gui_window *g,
gui_pointer_shape shape)
{
@@ -109,10 +93,6 @@ static void gui_default_window_place_caret(struct gui_window *g,
{
}
-static void gui_default_window_remove_caret(struct gui_window *g)
-{
-}
-
static void gui_default_window_create_form_select_menu(struct gui_window *g,
struct form_control *control)
{
@@ -135,7 +115,13 @@ static void gui_default_window_drag_save_selection(struct gui_window *g,
{
}
-static void gui_default_window_start_selection(struct gui_window *g)
+
+static void
+gui_default_console_log(struct gui_window *gw,
+ browser_window_console_source src,
+ const char *msg,
+ size_t msglen,
+ browser_window_console_flags flags)
{
}
@@ -167,7 +153,7 @@ static nserror verify_window_register(struct gui_window_table *gwt)
if (gwt->get_dimensions == NULL) {
return NSERROR_BAD_PARAMETER;
}
- if (gwt->update_extent == NULL) {
+ if (gwt->event == NULL) {
return NSERROR_BAD_PARAMETER;
}
@@ -191,27 +177,12 @@ static nserror verify_window_register(struct gui_window_table *gwt)
if (gwt->place_caret == NULL) {
gwt->place_caret = gui_default_window_place_caret;
}
- if (gwt->remove_caret == NULL) {
- gwt->remove_caret = gui_default_window_remove_caret;
- }
- if (gwt->start_throbber == NULL) {
- gwt->start_throbber = gui_default_window_start_throbber;
- }
- if (gwt->stop_throbber == NULL) {
- gwt->stop_throbber = gui_default_window_stop_throbber;
- }
if (gwt->drag_start == NULL) {
gwt->drag_start = gui_default_window_drag_start;
}
if (gwt->save_link == NULL) {
gwt->save_link = gui_default_window_save_link;
}
- if (gwt->new_content == NULL) {
- gwt->new_content = gui_default_window_new_content;
- }
- if (gwt->scroll_start == NULL) {
- gwt->scroll_start = gui_default_window_scroll_start;
- }
if (gwt->create_form_select_menu == NULL) {
gwt->create_form_select_menu =
gui_default_window_create_form_select_menu;
@@ -225,8 +196,8 @@ static nserror verify_window_register(struct gui_window_table *gwt)
if (gwt->drag_save_selection == NULL) {
gwt->drag_save_selection = gui_default_window_drag_save_selection;
}
- if (gwt->start_selection == NULL) {
- gwt->start_selection = gui_default_window_start_selection;
+ if (gwt->console_log == NULL) {
+ gwt->console_log = gui_default_console_log;
}
return NSERROR_OK;
@@ -503,6 +474,16 @@ static char *gui_default_mimetype(const char *path)
return strdup(guit->fetch->filetype(path));
}
+static int gui_default_socket_open(int domain, int type, int protocol)
+{
+ return (int) socket(domain, type, protocol);
+}
+
+static int gui_default_socket_close(int fd)
+{
+ return (int) ns_close_socket(fd);
+}
+
/** verify fetch table is valid */
static nserror verify_fetch_register(struct gui_fetch_table *gft)
{
@@ -529,6 +510,12 @@ static nserror verify_fetch_register(struct gui_fetch_table *gft)
if (gft->mimetype == NULL) {
gft->mimetype = gui_default_mimetype;
}
+ if (gft->socket_open == NULL) {
+ gft->socket_open = gui_default_socket_open;
+ }
+ if (gft->socket_close == NULL) {
+ gft->socket_close = gui_default_socket_close;
+ }
return NSERROR_OK;
}
@@ -565,7 +552,7 @@ static nserror verify_file_register(struct gui_file_table *gft)
* verify bitmap table is valid
*
* \param gbt The bitmap table to verify.
- * \return NSERROR_OK if teh table is valid else NSERROR_BAD_PARAMETER.
+ * \return NSERROR_OK if the table is valid else NSERROR_BAD_PARAMETER.
*/
static nserror verify_bitmap_register(struct gui_bitmap_table *gbt)
{
@@ -591,10 +578,6 @@ static nserror verify_bitmap_register(struct gui_bitmap_table *gbt)
return NSERROR_BAD_PARAMETER;
}
- if (gbt->test_opaque == NULL) {
- return NSERROR_BAD_PARAMETER;
- }
-
if (gbt->get_buffer == NULL) {
return NSERROR_BAD_PARAMETER;
}
@@ -611,14 +594,6 @@ static nserror verify_bitmap_register(struct gui_bitmap_table *gbt)
return NSERROR_BAD_PARAMETER;
}
- if (gbt->get_bpp == NULL) {
- return NSERROR_BAD_PARAMETER;
- }
-
- if (gbt->save == NULL) {
- return NSERROR_BAD_PARAMETER;
- }
-
if (gbt->modified == NULL) {
return NSERROR_BAD_PARAMETER;
}
@@ -670,21 +645,18 @@ static nserror gui_default_launch_url(struct nsurl *url)
}
-static nserror gui_default_cert_verify(nsurl *url,
- const struct ssl_cert_info *certs,
- unsigned long num,
- nserror (*cb)(bool proceed, void *pw),
- void *cbpw)
+static nserror gui_default_401login_open(
+ nsurl *url, const char *realm,
+ const char *username, const char *password,
+ nserror (*cb)(nsurl *url, const char * realm,
+ const char *username,
+ const char *password,
+ void *pw),
+ void *cbpw)
{
return NSERROR_NOT_IMPLEMENTED;
}
-static void gui_default_401login_open(nsurl *url, const char *realm,
- nserror (*cb)(bool proceed, void *pw), void *cbpw)
-{
- cb(false, cbpw);
-}
-
static void
gui_default_pdf_password(char **owner_pass, char **user_pass, char *path)
{
@@ -692,6 +664,12 @@ gui_default_pdf_password(char **owner_pass, char **user_pass, char *path)
save_pdf(path);
}
+static nserror
+gui_default_present_cookies(const char *search_term)
+{
+ return NSERROR_NOT_IMPLEMENTED;
+}
+
/** verify misc table is valid */
static nserror verify_misc_register(struct gui_misc_table *gmt)
{
@@ -704,9 +682,6 @@ static nserror verify_misc_register(struct gui_misc_table *gmt)
if (gmt->schedule == NULL) {
return NSERROR_BAD_PARAMETER;
}
- if (gmt->warning == NULL) {
- return NSERROR_BAD_PARAMETER;
- }
/* fill in the optional entries with defaults */
if (gmt->quit == NULL) {
@@ -715,15 +690,15 @@ static nserror verify_misc_register(struct gui_misc_table *gmt)
if (gmt->launch_url == NULL) {
gmt->launch_url = gui_default_launch_url;
}
- if (gmt->cert_verify == NULL) {
- gmt->cert_verify = gui_default_cert_verify;
- }
if (gmt->login == NULL) {
gmt->login = gui_default_401login_open;
}
if (gmt->pdf_password == NULL) {
gmt->pdf_password = gui_default_pdf_password;
}
+ if (gmt->present_cookies == NULL) {
+ gmt->present_cookies = gui_default_present_cookies;
+ }
return NSERROR_OK;
}
diff --git a/desktop/hotlist.c b/desktop/hotlist.c
index 4bdd7c8cb..20c0890a1 100644
--- a/desktop/hotlist.c
+++ b/desktop/hotlist.c
@@ -193,29 +193,32 @@ static nserror hotlist_create_treeview_field_visits_data(
struct hotlist_entry *e, const struct url_data *data)
{
char buffer[16];
- const char *last_visited;
- char *last_visited2;
- int len;
+ char *last_visited = NULL;
+ size_t len = 0;
/* Last visited */
if (data->visits != 0) {
- last_visited = ctime(&data->last_visit);
- last_visited2 = strdup(last_visited);
- len = 24;
+ const size_t lvsize = 256;
+ struct tm *lvtime;
+
+ if ((lvtime = localtime(&data->last_visit)) != NULL) {
+ last_visited = malloc(lvsize);
+ if (last_visited != NULL) {
+ len = strftime(last_visited, lvsize,
+ "%a %b %e %H:%M:%S %Y",
+ lvtime);
+ }
+ }
} else {
- last_visited2 = strdup("-");
+ last_visited = strdup("-");
len = 1;
}
- if (last_visited2 == NULL) {
+ if (last_visited == NULL) {
return NSERROR_NOMEM;
-
- } else if (len == 24) {
- assert(last_visited2[24] == '\n');
- last_visited2[24] = '\0';
}
e->data[HL_LAST_VISIT].field = hl_ctx.fields[HL_LAST_VISIT].field;
- e->data[HL_LAST_VISIT].value = last_visited2;
+ e->data[HL_LAST_VISIT].value = last_visited;
e->data[HL_LAST_VISIT].value_len = len;
/* Visits */
@@ -890,7 +893,9 @@ static nserror hotlist_load(const char *path, bool *loaded)
corestring_lwc_html);
if (html == NULL) {
dom_node_unref(document);
- guit->misc->warning("TreeLoadError", "(<html> not found)");
+ NSLOG(netsurf, WARNING,
+ "%s (<html> not found)",
+ messages_get("TreeLoadError"));
return NSERROR_OK;
}
@@ -899,7 +904,9 @@ static nserror hotlist_load(const char *path, bool *loaded)
if (body == NULL) {
dom_node_unref(html);
dom_node_unref(document);
- guit->misc->warning("TreeLoadError", "(<html>...<body> not found)");
+ NSLOG(netsurf, WARNING,
+ "%s (<html>...<body> not found)",
+ messages_get("TreeLoadError"));
return NSERROR_OK;
}
@@ -909,8 +916,9 @@ static nserror hotlist_load(const char *path, bool *loaded)
dom_node_unref(body);
dom_node_unref(html);
dom_node_unref(document);
- guit->misc->warning("TreeLoadError",
- "(<html>...<body>...<ul> not found.)");
+ NSLOG(netsurf, WARNING,
+ "%s (<html>...<body>...<ul> not found.)",
+ messages_get("TreeLoadError"));
return NSERROR_OK;
}
@@ -934,7 +942,9 @@ static nserror hotlist_load(const char *path, bool *loaded)
dom_node_unref(document);
if (err != NSERROR_OK) {
- guit->misc->warning("TreeLoadError", "(Failed building tree.)");
+ NSLOG(netsurf, WARNING,
+ "%s (Failed building tree.)",
+ messages_get("TreeLoadError"));
return NSERROR_OK;
}
@@ -961,13 +971,13 @@ static nserror hotlist_generate(void)
const char *url;
const char *msg_key;
} default_entries[] = {
- { "http://www.netsurf-browser.org/",
+ { "https://www.netsurf-browser.org/",
"HotlistHomepage" },
- { "http://www.netsurf-browser.org/downloads/",
+ { "https://www.netsurf-browser.org/downloads/",
"HotlistDownloads" },
- { "http://www.netsurf-browser.org/documentation",
+ { "https://www.netsurf-browser.org/documentation",
"HotlistDocumentation" },
- { "http://www.netsurf-browser.org/contact",
+ { "https://www.netsurf-browser.org/contact",
"HotlistContact" }
};
const int n_entries = sizeof(default_entries) /
@@ -1396,6 +1406,9 @@ nserror hotlist_fini(void)
/* Destroy the hotlist treeview */
err = treeview_destroy(hl_ctx.tree);
+ if (err != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Problem destroying the hotlist treeview.");
+ }
hl_ctx.built = false;
/* Free hotlist treeview entry fields */
@@ -1616,7 +1629,7 @@ nserror hotlist_add_entry(nsurl *url, const char *title, bool at_y, int y)
enum treeview_relationship rel;
if (url == NULL) {
- err = nsurl_create("http://netsurf-browser.org/", &url);
+ err = nsurl_create("https://netsurf-browser.org/", &url);
if (err != NSERROR_OK) {
return err;
}
diff --git a/desktop/knockout.c b/desktop/knockout.c
index 6dbf4ebcf..127a48cdb 100644
--- a/desktop/knockout.c
+++ b/desktop/knockout.c
@@ -671,7 +671,6 @@ knockout_plot_polygon(const struct redraw_context *ctx,
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
- * \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
@@ -680,14 +679,13 @@ knockout_plot_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
- float width,
const float transform[6])
{
nserror res;
nserror ffres;
ffres = knockout_plot_flush(ctx);
- res = real_plot.path(ctx, pstyle, p, n, width, transform);
+ res = real_plot.path(ctx, pstyle, p, n, transform);
/* return the first error */
if ((res != NSERROR_OK) && (ffres == NSERROR_OK)) {
diff --git a/desktop/local_history.c b/desktop/local_history.c
index 3219de90c..5227c97e1 100644
--- a/desktop/local_history.c
+++ b/desktop/local_history.c
@@ -24,22 +24,26 @@
#include <stdlib.h>
#include <string.h>
-#include "utils/errors.h"
#include "utils/nsurl.h"
+#include "utils/errors.h"
+
#include "netsurf/types.h"
#include "netsurf/layout.h"
+#include "netsurf/browser_window.h"
#include "netsurf/core_window.h"
#include "netsurf/plotters.h"
+#include "netsurf/keypress.h"
+
+#include "utils/nscolour.h"
+#include "desktop/cw_helper.h"
#include "desktop/gui_internal.h"
#include "desktop/system_colour.h"
#include "desktop/browser_private.h"
#include "desktop/browser_history.h"
+#include "desktop/local_history_private.h"
#include "desktop/local_history.h"
-#define WIDTH 100
-#define HEIGHT 86
-
/**
* local history viewer context
*/
@@ -47,6 +51,7 @@ struct local_history_session {
struct browser_window *bw;
struct core_window_callback_table *cw_t;
void *core_window_handle;
+ struct history_entry *cursor;
};
@@ -55,7 +60,7 @@ struct local_history_session {
*/
static plot_style_t pstyle_line = {
.stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_width = 2,
+ .stroke_width = plot_style_int_to_fixed(2),
};
@@ -72,7 +77,7 @@ static plot_style_t pstyle_bg = {
*/
static plot_style_t pstyle_rect = {
.stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_width = 1,
+ .stroke_width = plot_style_int_to_fixed(1),
};
@@ -81,7 +86,16 @@ static plot_style_t pstyle_rect = {
*/
static plot_style_t pstyle_rect_sel = {
.stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_width = 3,
+ .stroke_width = plot_style_int_to_fixed(3),
+};
+
+
+/**
+ * plot style for drawing rectangle round the cursor node
+ */
+static plot_style_t pstyle_rect_cursor = {
+ .stroke_type = PLOT_OP_TYPE_DASH,
+ .stroke_width = plot_style_int_to_fixed(3),
};
@@ -90,7 +104,7 @@ static plot_style_t pstyle_rect_sel = {
*/
static plot_font_style_t pfstyle_node = {
.family = PLOT_FONT_FAMILY_SANS_SERIF,
- .size = 8 * FONT_SIZE_SCALE,
+ .size = 8 * PLOT_STYLE_SCALE,
.weight = 400,
.flags = FONTF_NONE,
};
@@ -101,7 +115,7 @@ static plot_font_style_t pfstyle_node = {
*/
static plot_font_style_t pfstyle_node_sel = {
.family = PLOT_FONT_FAMILY_SANS_SERIF,
- .size = 8 * FONT_SIZE_SCALE,
+ .size = 8 * PLOT_STYLE_SCALE,
.weight = 900,
.flags = FONTF_NONE,
};
@@ -120,6 +134,7 @@ static plot_font_style_t pfstyle_node_sel = {
static nserror
redraw_entry(struct history *history,
struct history_entry *entry,
+ struct history_entry *cursor,
struct rect *clip,
int x, int y,
const struct redraw_context *ctx)
@@ -149,7 +164,8 @@ redraw_entry(struct history *history,
entry->page.bitmap,
entry->x + x,
entry->y + y,
- WIDTH, HEIGHT,
+ LOCAL_HISTORY_WIDTH,
+ LOCAL_HISTORY_HEIGHT,
0xffffff,
0);
if (res != NSERROR_OK) {
@@ -159,15 +175,27 @@ redraw_entry(struct history *history,
rect.x0 = entry->x - 1 + x;
rect.y0 = entry->y - 1 + y;
- rect.x1 = entry->x + x + WIDTH;
- rect.y1 = entry->y + y + HEIGHT;
- res = ctx->plot->rectangle(ctx, pstyle, &rect);
- if (res != NSERROR_OK) {
- return res;
+ rect.x1 = entry->x + x + LOCAL_HISTORY_WIDTH;
+ rect.y1 = entry->y + y + LOCAL_HISTORY_HEIGHT;
+
+ /* Border */
+ if (entry != cursor) {
+ /* Not cursor position */
+ res = ctx->plot->rectangle(ctx, pstyle, &rect);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ } else {
+ /* Cursor position */
+ rect.x0 -= 1;
+ rect.y0 -= 1;
+ rect.x1 += 1;
+ rect.y1 += 1;
+ ctx->plot->rectangle(ctx, &pstyle_rect_cursor, &rect);
}
res = guit->layout->position(plot_style_font, entry->page.title,
- strlen(entry->page.title), WIDTH,
+ strlen(entry->page.title), LOCAL_HISTORY_WIDTH,
&char_offset, &actual_x);
if (res != NSERROR_OK) {
return res;
@@ -176,7 +204,7 @@ redraw_entry(struct history *history,
res = ctx->plot->text(ctx,
pfstyle,
entry->x + x,
- entry->y + HEIGHT + 12 + y,
+ entry->y + LOCAL_HISTORY_HEIGHT + 12 + y,
entry->page.title,
char_offset);
if (res != NSERROR_OK) {
@@ -185,34 +213,34 @@ redraw_entry(struct history *history,
/* for each child node draw a line and recurse redraw into it */
for (child = entry->forward; child; child = child->next) {
- rect.x0 = entry->x + WIDTH + x;
- rect.y0 = entry->y + HEIGHT / 2 + y;
- rect.x1 = entry->x + WIDTH + tailsize + x;
- rect.y1 = entry->y + HEIGHT / 2 + y;
+ rect.x0 = entry->x + LOCAL_HISTORY_WIDTH + x;
+ rect.y0 = entry->y + LOCAL_HISTORY_HEIGHT / 2 + y;
+ rect.x1 = entry->x + LOCAL_HISTORY_WIDTH + tailsize + x;
+ rect.y1 = entry->y + LOCAL_HISTORY_HEIGHT / 2 + y;
res = ctx->plot->line(ctx, &pstyle_line, &rect);
if (res != NSERROR_OK) {
return res;
}
- rect.x0 = entry->x + WIDTH + tailsize + x;
- rect.y0 = entry->y + HEIGHT / 2 + y;
+ rect.x0 = entry->x + LOCAL_HISTORY_WIDTH + tailsize + x;
+ rect.y0 = entry->y + LOCAL_HISTORY_HEIGHT / 2 + y;
rect.x1 = child->x - tailsize + x;
- rect.y1 = child->y + HEIGHT / 2 + y;
+ rect.y1 = child->y + LOCAL_HISTORY_HEIGHT / 2 + y;
res = ctx->plot->line(ctx, &pstyle_line, &rect);
if (res != NSERROR_OK) {
return res;
}
rect.x0 = child->x - tailsize + x;
- rect.y0 = child->y + HEIGHT / 2 + y;
+ rect.y0 = child->y + LOCAL_HISTORY_HEIGHT / 2 + y;
rect.x1 = child->x + x;
- rect.y1 = child->y + HEIGHT / 2 + y;
+ rect.y1 = child->y + LOCAL_HISTORY_HEIGHT / 2 + y;
res = ctx->plot->line(ctx, &pstyle_line, &rect);
if (res != NSERROR_OK) {
return res;
}
- res = redraw_entry(history, child, clip, x, y, ctx);
+ res = redraw_entry(history, child, cursor, clip, x, y, ctx);
if (res != NSERROR_OK) {
return res;
}
@@ -241,9 +269,9 @@ find_entry_position(struct history_entry *entry, int x, int y)
}
if ((entry->x <= x) &&
- (x <= entry->x + WIDTH) &&
+ (x <= entry->x + LOCAL_HISTORY_WIDTH) &&
(entry->y <= y) &&
- (y <= entry->y + HEIGHT)) {
+ (y <= entry->y + LOCAL_HISTORY_HEIGHT)) {
return entry;
}
@@ -257,6 +285,27 @@ find_entry_position(struct history_entry *entry, int x, int y)
return NULL;
}
+/* exported interface documented in desktop/local_history.h */
+nserror
+local_history_scroll_to_cursor(struct local_history_session *session)
+{
+ rect cursor;
+
+ if (session->cursor == NULL) {
+ return NSERROR_OK;
+ }
+
+ cursor.x0 = session->cursor->x - LOCAL_HISTORY_RIGHT_MARGIN / 2;
+ cursor.y0 = session->cursor->y - LOCAL_HISTORY_BOTTOM_MARGIN / 2;
+ cursor.x1 = cursor.x0 + LOCAL_HISTORY_WIDTH +
+ LOCAL_HISTORY_RIGHT_MARGIN / 2;
+ cursor.y1 = cursor.y0 + LOCAL_HISTORY_HEIGHT +
+ LOCAL_HISTORY_BOTTOM_MARGIN / 2;
+
+ return cw_helper_scroll_visible(session->cw_t,
+ session->core_window_handle,
+ &cursor);
+}
/* exported interface documented in desktop/local_history.h */
nserror
@@ -265,28 +314,19 @@ local_history_init(struct core_window_callback_table *cw_t,
struct browser_window *bw,
struct local_history_session **session)
{
- nserror res;
struct local_history_session *nses;
- res = ns_system_colour_char("Window", &pstyle_bg.fill_colour);
- if (res != NSERROR_OK) {
- return res;
- }
- pfstyle_node.background = pstyle_bg.fill_colour;
- pfstyle_node_sel.background = pstyle_bg.fill_colour;
+ pstyle_bg.fill_colour = nscolours[NSCOLOUR_WIN_EVEN_BG];
+ pstyle_line.stroke_colour = nscolours[NSCOLOUR_WIN_EVEN_BORDER];
- res = ns_system_colour_char("GrayText", &pstyle_line.stroke_colour);
- if (res != NSERROR_OK) {
- return res;
- }
pstyle_rect.stroke_colour = pstyle_line.stroke_colour;
- pfstyle_node.foreground = pstyle_line.stroke_colour;
+ pstyle_rect_sel.stroke_colour = nscolours[NSCOLOUR_WIN_EVEN_BORDER];
+ pstyle_rect_cursor.stroke_colour = nscolours[NSCOLOUR_SEL_BG];
- res = ns_system_colour_char("Highlight", &pstyle_rect_sel.stroke_colour);
- if (res != NSERROR_OK) {
- return res;
- }
- pfstyle_node_sel.foreground = pstyle_rect_sel.stroke_colour;
+ pfstyle_node.foreground = nscolours[NSCOLOUR_WIN_EVEN_FG];
+ pfstyle_node.background = nscolours[NSCOLOUR_WIN_EVEN_BG];
+ pfstyle_node_sel.foreground = nscolours[NSCOLOUR_WIN_EVEN_FG];
+ pfstyle_node_sel.background = nscolours[NSCOLOUR_WIN_EVEN_BG];
nses = calloc(1, sizeof(struct local_history_session));
if (nses == NULL) {
@@ -338,11 +378,13 @@ local_history_redraw(struct local_history_session *session,
ctx->plot->clip(ctx, &r);
ctx->plot->rectangle(ctx, &pstyle_bg, &r);
- return redraw_entry(session->bw->history,
- session->bw->history->start,
- clip,
- x, y,
- ctx);
+ return redraw_entry(
+ session->bw->history,
+ session->bw->history->start,
+ session->cursor,
+ clip,
+ x, y,
+ ctx);
}
/* exported interface documented in desktop/local_history.h */
@@ -385,10 +427,120 @@ local_history_mouse_action(struct local_history_session *session,
return NSERROR_OK;
}
+/**
+ * Determine the point on the parent line where this history line branches.
+ *
+ * If `branch_point` gets set then there is a guarantee that (a) `ent` is
+ * a transitive child (forward) of that point. and (b) `branch_point` has a
+ * parent.
+ *
+ * \param[in] ent The entry to work backward from
+ * \param[out] branch_point The entry to set to the branch point if one is found
+ */
+static void
+_local_history_find_branch_point(struct history_entry *ent,
+ struct history_entry **branch_point)
+{
+ if (ent->back == NULL) {
+ /* We're at the root, nothing to do */
+ return;
+ }
+ /* Start from our immediate parent */
+ ent = ent->back;
+ while (ent->back != NULL) {
+ if (ent->back->forward != ent->back->forward_last) {
+ /* This point is a branch */
+ *branch_point = ent;
+ break;
+ }
+ ent = ent->back;
+ }
+}
+
/* exported interface documented in desktop/local_history.h */
bool
local_history_keypress(struct local_history_session *session, uint32_t key)
{
+ switch (key) {
+ case NS_KEY_NL:
+ case NS_KEY_CR:
+ /* pressed enter */
+ if (session->cursor != session->bw->history->current) {
+ browser_window_history_go(session->bw, session->cursor,
+ false);
+ local_history_scroll_to_cursor(session);
+ session->cw_t->invalidate(session->core_window_handle, NULL);
+ }
+ /* We have handled this keypress */
+ return true;
+ case NS_KEY_LEFT:
+ /* Go to parent */
+ if (session->cursor->back != NULL) {
+ session->cursor = session->cursor->back;
+ local_history_scroll_to_cursor(session);
+ session->cw_t->invalidate(session->core_window_handle, NULL);
+ }
+ /* We have handled this keypress */
+ return true;
+ case NS_KEY_RIGHT:
+ /* Go to preferred child if there is one */
+ if (session->cursor->forward_pref != NULL) {
+ session->cursor = session->cursor->forward_pref;
+ local_history_scroll_to_cursor(session);
+ session->cw_t->invalidate(session->core_window_handle, NULL);
+ }
+ /* We have handled this keypress */
+ return true;
+ case NS_KEY_DOWN:
+ /* Go to next sibling down, if there is one */
+ if (session->cursor->next != NULL) {
+ session->cursor = session->cursor->next;
+ } else {
+ struct history_entry *branch_point = NULL;
+ _local_history_find_branch_point(
+ session->cursor,
+ &branch_point);
+ if (branch_point != NULL) {
+ if (branch_point->next != NULL) {
+ branch_point = branch_point->next;
+ }
+ session->cursor = branch_point;
+ }
+ }
+ /* We have handled this keypress */
+ local_history_scroll_to_cursor(session);
+ session->cw_t->invalidate(session->core_window_handle, NULL);
+ return true;
+ case NS_KEY_UP:
+ /* Go to next sibling up, if there is one */
+ if (session->cursor->back != NULL) {
+ struct history_entry *ent = session->cursor->back->forward;
+ while (ent != session->cursor &&
+ ent->next != NULL &&
+ ent->next != session->cursor) {
+ ent = ent->next;
+ }
+ if (session->cursor != ent) {
+ session->cursor = ent;
+ } else {
+ struct history_entry *branch_point = NULL;
+ _local_history_find_branch_point(
+ session->cursor,
+ &branch_point);
+ if (branch_point != NULL) {
+ struct history_entry *ent = branch_point->back->forward;
+ while (ent->next != NULL && ent->next != branch_point) {
+ ent = ent->next;
+ }
+ session->cursor = ent;
+ }
+ }
+ }
+ /* We have handled this keypress */
+ local_history_scroll_to_cursor(session);
+ session->cw_t->invalidate(session->core_window_handle, NULL);
+ return true;
+ }
return false;
}
@@ -398,12 +550,16 @@ local_history_set(struct local_history_session *session,
struct browser_window *bw)
{
session->bw = bw;
+ session->cursor = NULL;
+
if (bw != NULL) {
assert(session->bw->history != NULL);
+ session->cursor = bw->history->current;
session->cw_t->update_size(session->core_window_handle,
session->bw->history->width,
session->bw->history->height);
+ local_history_scroll_to_cursor(session);
}
return NSERROR_OK;
diff --git a/desktop/local_history.h b/desktop/local_history.h
index 7f85a633e..d0d9209a1 100644
--- a/desktop/local_history.h
+++ b/desktop/local_history.h
@@ -140,5 +140,12 @@ nserror local_history_get_size(struct local_history_session *session, int *width
*/
nserror local_history_get_url(struct local_history_session *session, int x, int y, struct nsurl **url_out);
+/**
+ * Scroll the local history window to ensure the current cursor is shown.
+ *
+ * \param session The local history session
+ */
+nserror local_history_scroll_to_cursor(struct local_history_session *session);
+
#endif
diff --git a/desktop/local_history_private.h b/desktop/local_history_private.h
new file mode 100644
index 000000000..fd25ab4d3
--- /dev/null
+++ b/desktop/local_history_private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2006 James Bursa <bursa@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Interface to browser history private operations
+ */
+
+#ifndef NETSURF_DESKTOP_BROWSER_HISTORY_PRIVATE_H
+#define NETSURF_DESKTOP_BROWSER_HISTORY_PRIVATE_H
+
+#include "content/handlers/css/utils.h"
+
+#define LOCAL_HISTORY_WIDTH \
+ (FIXTOINT(css_unit_css2device_px(INTTOFIX(116), nscss_screen_dpi)))
+#define LOCAL_HISTORY_HEIGHT \
+ (FIXTOINT(css_unit_css2device_px(INTTOFIX(100), nscss_screen_dpi)))
+#define LOCAL_HISTORY_RIGHT_MARGIN \
+ (FIXTOINT(css_unit_css2device_px(INTTOFIX( 50), nscss_screen_dpi)))
+#define LOCAL_HISTORY_BOTTOM_MARGIN \
+ (FIXTOINT(css_unit_css2device_px(INTTOFIX( 30), nscss_screen_dpi)))
+
+#endif
diff --git a/desktop/netsurf.c b/desktop/netsurf.c
index 8aa949a5a..bd785898f 100644
--- a/desktop/netsurf.c
+++ b/desktop/netsurf.c
@@ -24,14 +24,19 @@
#include <stdio.h>
#include <stdlib.h>
#include <libwapcaplet/libwapcaplet.h>
+#include <dom/dom.h>
#include "netsurf/inttypes.h"
#include "utils/config.h"
+#include "utils/errors.h"
+#include "utils/nscolour.h"
#include "utils/nsoption.h"
#include "utils/corestrings.h"
#include "utils/log.h"
+#include "utils/string.h"
#include "utils/utf8.h"
#include "utils/messages.h"
+#include "utils/useragent.h"
#include "content/content_factory.h"
#include "content/fetchers.h"
#include "content/hlcache.h"
@@ -41,16 +46,21 @@
#include "image/image.h"
#include "image/image_cache.h"
#include "javascript/js.h"
-#include "render/html.h"
-#include "render/textplain.h"
+#include "html/html.h"
+#include "text/textplain.h"
#include "netsurf/browser_window.h"
#include "desktop/system_colour.h"
+#include "desktop/page-info.h"
#include "desktop/searchweb.h"
#include "netsurf/misc.h"
#include "desktop/gui_internal.h"
#include "netsurf/netsurf.h"
+
+/** \todo QUERY - Remove this import later */
+#include "desktop/browser_private.h"
+
/** speculative pre-conversion small image size
*
* Experimenting by visiting every page from default page in order and
@@ -89,43 +99,10 @@
static void netsurf_lwc_iterator(lwc_string *str, void *pw)
{
- NSLOG(netsurf, INFO, "[%3u] %.*s", str->refcnt,
+ NSLOG(netsurf, WARNING, "[%3"PRIu32"] %.*s", str->refcnt,
(int)lwc_string_length(str), lwc_string_data(str));
}
-/**
- * Dispatch a low-level cache query to the frontend
- *
- * \param query Query descriptor
- * \param pw Private data
- * \param cb Continuation callback
- * \param cbpw Private data for continuation
- * \return NSERROR_OK
- */
-static nserror netsurf_llcache_query_handler(const llcache_query *query,
- void *pw, llcache_query_response cb, void *cbpw)
-{
- nserror res = NSERROR_OK;
-
- switch (query->type) {
- case LLCACHE_QUERY_AUTH:
- guit->misc->login(query->url, query->data.auth.realm, cb, cbpw);
- break;
-
- case LLCACHE_QUERY_REDIRECT:
- /** \todo Need redirect query dialog */
- /* For now, do nothing, as this query type isn't emitted yet */
- break;
-
- case LLCACHE_QUERY_SSL:
- res = guit->misc->cert_verify(query->url, query->data.ssl.certs,
- query->data.ssl.num, cb, cbpw);
- break;
- }
-
- return res;
-}
-
/* exported interface documented in netsurf/netsurf.h */
nserror netsurf_init(const char *store_path)
{
@@ -133,7 +110,6 @@ nserror netsurf_init(const char *store_path)
struct hlcache_parameters hlcache_parameters = {
.bg_clean_time = HL_CACHE_CLEAN_TIME,
.llcache = {
- .cb = netsurf_llcache_query_handler,
.minimum_lifetime = LLCACHE_STORE_MIN_LIFETIME,
.minimum_bandwidth = LLCACHE_STORE_MIN_BANDWIDTH,
.maximum_bandwidth = LLCACHE_STORE_MAX_BANDWIDTH,
@@ -161,6 +137,10 @@ nserror netsurf_init(const char *store_path)
if (ret != NSERROR_OK)
return ret;
+ ret = nscolour_update();
+ if (ret != NSERROR_OK)
+ return ret;
+
/* set up cache limits based on the memory cache size option */
hlcache_parameters.llcache.limit = nsoption_int(memory_cache_size);
@@ -175,10 +155,10 @@ nserror netsurf_init(const char *store_path)
hlcache_parameters.llcache.fetch_attempts = nsoption_uint(max_retried_fetches);
/* image cache is 25% of total memory cache size */
- image_cache_parameters.limit = (hlcache_parameters.llcache.limit * 25) / 100;
+ image_cache_parameters.limit = hlcache_parameters.llcache.limit / 4;
/* image cache hysteresis is 20% of the image cache size */
- image_cache_parameters.hysteresis = (image_cache_parameters.limit * 20) / 100;
+ image_cache_parameters.hysteresis = image_cache_parameters.limit / 5;
/* account for image cache use from total */
hlcache_parameters.llcache.limit -= image_cache_parameters.limit;
@@ -187,10 +167,13 @@ nserror netsurf_init(const char *store_path)
hlcache_parameters.llcache.store.limit = nsoption_uint(disc_cache_size);
/* set backing store hysterissi to 20% */
- hlcache_parameters.llcache.store.hysteresis = (hlcache_parameters.llcache.store.limit * 20) / 100;;
+ hlcache_parameters.llcache.store.hysteresis = hlcache_parameters.llcache.store.limit / 5;
/* set the path to the backing store */
- hlcache_parameters.llcache.store.path = store_path;
+ hlcache_parameters.llcache.store.path =
+ nsoption_charp(disc_cache_path) ?
+ nsoption_charp(disc_cache_path) :
+ store_path;
/* image handler bitmap cache */
ret = image_cache_init(&image_cache_parameters);
@@ -233,6 +216,11 @@ nserror netsurf_init(const char *store_path)
js_initialise();
+ ret = page_info_init();
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
return NSERROR_OK;
}
@@ -247,7 +235,10 @@ void netsurf_exit(void)
NSLOG(netsurf, INFO, "Closing GUI");
guit->misc->quit();
-
+
+ NSLOG(netsurf, INFO, "Finalising page-info module");
+ page_info_fini();
+
NSLOG(netsurf, INFO, "Finalising JavaScript");
js_finalise();
@@ -259,6 +250,8 @@ void netsurf_exit(void)
NSLOG(netsurf, INFO, "Closing fetches");
fetcher_quit();
+ /* Now the fetchers are done, our user-agent string can go */
+ free_user_agent_string();
/* dump any remaining cache entries */
image_cache_fini();
@@ -279,6 +272,9 @@ void netsurf_exit(void)
messages_destroy();
corestrings_fini();
+ if (dom_namespace_finalise() != DOM_NO_ERR) {
+ NSLOG(netsurf, WARNING, "Unable to finalise DOM namespace strings");
+ }
NSLOG(netsurf, INFO, "Remaining lwc strings:");
lwc_iterate_strings(netsurf_lwc_iterator, NULL);
diff --git a/desktop/options.h b/desktop/options.h
index 9b7064efa..b74fab829 100644
--- a/desktop/options.h
+++ b/desktop/options.h
@@ -16,7 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Option available on all platforms
*
* Non-platform specific options can be added by editing this file
@@ -27,8 +28,8 @@
* with different macro definitions so there is no guard
*/
-#ifndef _NETSURF_DESKTOP_OPTIONS_H_
-#define _NETSURF_DESKTOP_OPTIONS_H_
+#ifndef NETSURF_DESKTOP_OPTIONS_H_
+#define NETSURF_DESKTOP_OPTIONS_H_
#include "netsurf/types.h"
@@ -91,6 +92,9 @@ NSOPTION_STRING(accept_charset, NULL)
/** Preferred maximum size of memory cache / bytes. */
NSOPTION_INTEGER(memory_cache_size, 12 * 1024 * 1024)
+/** Preferred location of disc cache, or NULL for system provided location */
+NSOPTION_STRING(disc_cache_path, NULL)
+
/** Preferred expiry size of disc cache / bytes. */
NSOPTION_UINT(disc_cache_size, 1024 * 1024 * 1024)
@@ -104,9 +108,6 @@ NSOPTION_BOOL(block_advertisements, false)
* http://www.w3.org/Submission/2011/SUBM-web-tracking-protection-20110224/#dnt-uas */
NSOPTION_BOOL(do_not_track, false)
-/** Minimum GIF animation delay */
-NSOPTION_INTEGER(minimum_gif_delay, 10)
-
/** Whether to send the referer HTTP header */
NSOPTION_BOOL(send_referer, true)
@@ -122,6 +123,9 @@ NSOPTION_BOOL(animate_images, true)
/** Whether to execute javascript */
NSOPTION_BOOL(enable_javascript, false)
+/** Whether to allow Author level CSS. */
+NSOPTION_BOOL(author_level_css, true)
+
/** Maximum time (in seconds) to wait for a script to run */
NSOPTION_INTEGER(script_timeout, 10)
@@ -167,12 +171,6 @@ NSOPTION_INTEGER(window_width, 0)
/** default height of new windows */
NSOPTION_INTEGER(window_height, 0)
-/** width of screen when above options were saved */
-NSOPTION_INTEGER(window_screen_width, 0)
-
-/** height of screen when above options were saved */
-NSOPTION_INTEGER(window_screen_height, 0)
-
/** default size of status bar vs. h scroll bar */
NSOPTION_INTEGER(toolbar_status_size, 6667)
@@ -260,6 +258,9 @@ NSOPTION_BOOL(enable_PDF_compression, true)
/** setting a password and encoding PDF documents */
NSOPTION_BOOL(enable_PDF_password, false)
+/** whether to prefer dark mode (light on dark) */
+NSOPTION_BOOL(prefer_dark_mode, false)
+
/******** System colours ********/
NSOPTION_COLOUR(sys_colour_ActiveBorder, 0x00d3d3d3)
NSOPTION_COLOUR(sys_colour_ActiveCaption, 0x00f1f1f1)
@@ -291,6 +292,6 @@ NSOPTION_COLOUR(sys_colour_WindowFrame, 0x004e4e4e)
NSOPTION_COLOUR(sys_colour_WindowText, 0x00000000)
/** Filter for non-verbose logging */
-NSOPTION_STRING(log_filter, "level:WARNING")
+NSOPTION_STRING(log_filter, NETSURF_BUILTIN_LOG_FILTER)
/** Filter for verbose logging */
-NSOPTION_STRING(verbose_filter, "level:VERBOSE")
+NSOPTION_STRING(verbose_filter, NETSURF_BUILTIN_VERBOSE_FILTER)
diff --git a/desktop/page-info.c b/desktop/page-info.c
new file mode 100644
index 000000000..0991d071b
--- /dev/null
+++ b/desktop/page-info.c
@@ -0,0 +1,836 @@
+/*
+ * Copyright 2020 Michael Drake <tlsa@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Pave info viewer window implementation
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "css/utils.h"
+
+#include "utils/nsurl.h"
+#include "utils/nscolour.h"
+
+#include "netsurf/mouse.h"
+#include "netsurf/layout.h"
+#include "netsurf/keypress.h"
+#include "netsurf/plotters.h"
+#include "netsurf/core_window.h"
+#include "netsurf/browser_window.h"
+
+#include "desktop/knockout.h"
+#include "desktop/page-info.h"
+#include "desktop/gui_internal.h"
+#include "desktop/system_colour.h"
+
+/**
+ * Plot style for heading font.
+ */
+static plot_font_style_t pi__heading[PAGE_STATE__COUNT] = {
+ [PAGE_STATE_UNKNOWN] = {
+ .family = PLOT_FONT_FAMILY_SANS_SERIF,
+ .size = 14 * PLOT_STYLE_SCALE,
+ .flags = FONTF_NONE,
+ .weight = 400,
+ },
+ [PAGE_STATE_INTERNAL] = {
+ .family = PLOT_FONT_FAMILY_SANS_SERIF,
+ .size = 14 * PLOT_STYLE_SCALE,
+ .flags = FONTF_NONE,
+ .weight = 400,
+ },
+ [PAGE_STATE_LOCAL] = {
+ .family = PLOT_FONT_FAMILY_SANS_SERIF,
+ .size = 14 * PLOT_STYLE_SCALE,
+ .flags = FONTF_NONE,
+ .weight = 400,
+ },
+ [PAGE_STATE_INSECURE] = {
+ .family = PLOT_FONT_FAMILY_SANS_SERIF,
+ .size = 14 * PLOT_STYLE_SCALE,
+ .flags = FONTF_NONE,
+ .weight = 400,
+ },
+ [PAGE_STATE_SECURE_OVERRIDE] = {
+ .family = PLOT_FONT_FAMILY_SANS_SERIF,
+ .size = 14 * PLOT_STYLE_SCALE,
+ .flags = FONTF_NONE,
+ .weight = 400,
+ },
+ [PAGE_STATE_SECURE_ISSUES] = {
+ .family = PLOT_FONT_FAMILY_SANS_SERIF,
+ .size = 14 * PLOT_STYLE_SCALE,
+ .flags = FONTF_NONE,
+ .weight = 400,
+ },
+ [PAGE_STATE_SECURE] = {
+ .family = PLOT_FONT_FAMILY_SANS_SERIF,
+ .size = 14 * PLOT_STYLE_SCALE,
+ .flags = FONTF_NONE,
+ .weight = 400,
+ },
+};
+
+/**
+ * Plot style for domain font.
+ */
+static plot_font_style_t pi__domain = {
+ .family = PLOT_FONT_FAMILY_SANS_SERIF,
+ .size = 8 * PLOT_STYLE_SCALE,
+ .flags = FONTF_NONE,
+ .weight = 700,
+};
+
+/**
+ * Plot style for item font.
+ */
+static plot_font_style_t pi__item = {
+ .family = PLOT_FONT_FAMILY_SANS_SERIF,
+ .size = 11 * PLOT_STYLE_SCALE,
+ .flags = FONTF_NONE,
+ .weight = 400,
+};
+
+/**
+ * Plot style for item detail font.
+ */
+static plot_font_style_t pi__item_detail = {
+ .family = PLOT_FONT_FAMILY_SANS_SERIF,
+ .size = 11 * PLOT_STYLE_SCALE,
+ .flags = FONTF_NONE,
+ .weight = 400,
+};
+
+/**
+ * Plot style for window background.
+ */
+static plot_style_t pi__bg = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+};
+
+/**
+ * Plot style for hover background.
+ */
+static plot_style_t pi__hover = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+};
+
+/**
+ * An "text" type page info entry.
+ */
+struct page_info_text {
+ const char *text;
+ const plot_font_style_t *style;
+ int width;
+ int height;
+ int padding_bottom;
+};
+
+/**
+ * An "item" type page info entry.
+ */
+struct page_info_item {
+ struct page_info_text item;
+ struct page_info_text detail;
+ const plot_style_t *hover_bg;
+ int padding_bottom;
+ int padding_top;
+ bool hover;
+};
+
+/**
+ * List of page info window entries.
+ */
+enum pi_entry {
+ PI_ENTRY_HEADER,
+ PI_ENTRY_DOMAIN,
+ PI_ENTRY_CERT,
+ PI_ENTRY_COOKIES,
+ PI_ENTRY__COUNT,
+};
+
+/**
+ * An entry on a page info window.
+ */
+struct page_info_entry {
+ /**
+ * List of page info entry types.
+ */
+ enum page_info_entry_type {
+ PAGE_INFO_ENTRY_TYPE_TEXT,
+ PAGE_INFO_ENTRY_TYPE_ITEM,
+ } type;
+ /**
+ * Type-specific page info entry data.
+ */
+ union {
+ struct page_info_text text;
+ struct page_info_item item;
+ } u;
+};
+
+/**
+ * The default page info window data.
+ */
+struct page_info_entry pi__entries[PI_ENTRY__COUNT] = {
+ [PI_ENTRY_HEADER] = {
+ .type = PAGE_INFO_ENTRY_TYPE_TEXT,
+ },
+ [PI_ENTRY_DOMAIN] = {
+ .type = PAGE_INFO_ENTRY_TYPE_TEXT,
+ .u = {
+ .text = {
+ .style = &pi__domain,
+ },
+ },
+ },
+ [PI_ENTRY_CERT] = {
+ .type = PAGE_INFO_ENTRY_TYPE_ITEM,
+ .u = {
+ .item = {
+ .item = {
+ .style = &pi__item,
+ },
+ .detail = {
+ .style = &pi__item_detail,
+ },
+ .hover_bg = &pi__hover,
+ },
+ },
+ },
+ [PI_ENTRY_COOKIES] = {
+ .type = PAGE_INFO_ENTRY_TYPE_ITEM,
+ .u = {
+ .item = {
+ .item = {
+ .style = &pi__item,
+ },
+ .detail = {
+ .style = &pi__item_detail,
+ },
+ .hover_bg = &pi__hover,
+ },
+ },
+ },
+};
+
+/**
+ * The page info window structure.
+ */
+struct page_info {
+ const struct core_window_callback_table *cw_t;
+ struct core_window *cw_h;
+
+ struct browser_window *bw;
+ lwc_string *domain;
+ enum nsurl_scheme_type scheme;
+
+ browser_window_page_info_state state;
+ unsigned cookies;
+
+ char cookie_text[64];
+ struct page_info_entry entries[PI_ENTRY__COUNT];
+
+ int width;
+ int height;
+
+ int window_padding;
+};
+
+/* Exported interface documented in desktop/page_info.h */
+nserror page_info_init(void)
+{
+ pi__bg.fill_colour = nscolours[NSCOLOUR_WIN_EVEN_BG];
+ pi__hover.fill_colour = nscolours[NSCOLOUR_WIN_EVEN_BG_HOVER];
+
+ pi__domain.background = nscolours[NSCOLOUR_WIN_EVEN_BG];
+ pi__domain.foreground = nscolours[NSCOLOUR_WIN_EVEN_FG];
+
+ pi__item.background = nscolours[NSCOLOUR_WIN_EVEN_BG];
+ pi__item.foreground = nscolours[NSCOLOUR_WIN_EVEN_FG];
+
+ pi__item_detail.background = nscolours[NSCOLOUR_WIN_EVEN_BG];
+ pi__item_detail.foreground = nscolours[NSCOLOUR_WIN_EVEN_FG_FADED];
+
+ pi__heading[PAGE_STATE_UNKNOWN].background = nscolours[NSCOLOUR_WIN_EVEN_BG];
+ pi__heading[PAGE_STATE_UNKNOWN].foreground = nscolours[NSCOLOUR_WIN_EVEN_FG_BAD];
+ pi__heading[PAGE_STATE_INTERNAL].background = nscolours[NSCOLOUR_WIN_EVEN_BG];
+ pi__heading[PAGE_STATE_INTERNAL].foreground = nscolours[NSCOLOUR_WIN_EVEN_FG];
+ pi__heading[PAGE_STATE_LOCAL].background = nscolours[NSCOLOUR_WIN_EVEN_BG];
+ pi__heading[PAGE_STATE_LOCAL].foreground = nscolours[NSCOLOUR_WIN_EVEN_FG];
+ pi__heading[PAGE_STATE_INSECURE].background = nscolours[NSCOLOUR_WIN_EVEN_BG];
+ pi__heading[PAGE_STATE_INSECURE].foreground = nscolours[NSCOLOUR_WIN_EVEN_FG_BAD];
+ pi__heading[PAGE_STATE_SECURE_OVERRIDE].background = nscolours[NSCOLOUR_WIN_EVEN_BG];
+ pi__heading[PAGE_STATE_SECURE_OVERRIDE].foreground = nscolours[NSCOLOUR_WIN_EVEN_FG_BAD];
+ pi__heading[PAGE_STATE_SECURE_ISSUES].background = nscolours[NSCOLOUR_WIN_EVEN_BG];
+ pi__heading[PAGE_STATE_SECURE_ISSUES].foreground = nscolours[NSCOLOUR_WIN_EVEN_FG_BAD];
+ pi__heading[PAGE_STATE_SECURE].background = nscolours[NSCOLOUR_WIN_EVEN_BG];
+ pi__heading[PAGE_STATE_SECURE].foreground = nscolours[NSCOLOUR_WIN_EVEN_FG_GOOD];
+
+ return NSERROR_OK;
+}
+
+/* Exported interface documented in desktop/page_info.h */
+nserror page_info_fini(void)
+{
+ return NSERROR_OK;
+}
+
+/**
+ * Measure the text in the page_info window.
+ *
+ * \param[in] pi The page info window handle.
+ * \return NSERROR_OK on success, appropriate error code otherwise.
+ */
+static nserror page_info__measure_text_entry(
+ struct page_info_text *pit)
+{
+ nserror err;
+ int height_px;
+
+ err = guit->layout->width(pit->style,
+ pit->text, strlen(pit->text),
+ &pit->width);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+
+ /* \todo: This needs to be a helper in plot style or in nscss. */
+ height_px = ((pit->style->size / PLOT_STYLE_SCALE) *
+ FIXTOINT(nscss_screen_dpi) + 36) / 72;
+
+ pit->height = (height_px * 8 + 3) / 6;
+
+ return NSERROR_OK;
+}
+
+/**
+ * Measure the text in the page_info window.
+ *
+ * \param[in] pi The page info window handle.
+ * \return NSERROR_OK on success, appropriate error code otherwise.
+ */
+static nserror page_info__measure_text(
+ struct page_info *pi)
+{
+ nserror err;
+
+ for (unsigned i = 0; i < PI_ENTRY__COUNT; i++) {
+ struct page_info_entry *entry = pi->entries + i;
+ int padding;
+
+ switch (entry->type) {
+ case PAGE_INFO_ENTRY_TYPE_TEXT:
+ err = page_info__measure_text_entry(
+ &entry->u.text);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+ if (i == PI_ENTRY_DOMAIN) {
+ entry->u.text.padding_bottom =
+ entry->u.text.height * 3 / 2;
+ }
+ break;
+
+ case PAGE_INFO_ENTRY_TYPE_ITEM:
+ err = page_info__measure_text_entry(
+ &entry->u.item.item);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+ err = page_info__measure_text_entry(
+ &entry->u.item.detail);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+ padding = entry->u.item.item.height / 4;
+ entry->u.item.padding_top = padding;
+ entry->u.item.padding_bottom = padding;
+
+ break;
+ }
+ }
+
+ pi->window_padding = pi->entries[PI_ENTRY_DOMAIN]
+ .u.item.item.height / 2;
+
+ return NSERROR_OK;
+}
+
+/**
+ * Set the text for the page_info window.
+ *
+ * \todo Use messages for internationalisation.
+ *
+ * \param[in] pi The page info window handle.
+ * \return NSERROR_OK on success, appropriate error code otherwise.
+ */
+static nserror page_info__set_text(
+ struct page_info *pi)
+{
+ int printed;
+ static const char *header[PAGE_STATE__COUNT] = {
+ [PAGE_STATE_UNKNOWN] = "Provenance unknown",
+ [PAGE_STATE_INTERNAL] = "NetSurf data",
+ [PAGE_STATE_LOCAL] = "Local data",
+ [PAGE_STATE_INSECURE] = "Connection not secure",
+ [PAGE_STATE_SECURE_OVERRIDE] = "Connection not secure",
+ [PAGE_STATE_SECURE_ISSUES] = "Connection not secure",
+ [PAGE_STATE_SECURE] = "Connection is secure",
+ };
+ static const char *certificate[PAGE_STATE__COUNT] = {
+ [PAGE_STATE_UNKNOWN] = "Missing",
+ [PAGE_STATE_INTERNAL] = "None",
+ [PAGE_STATE_LOCAL] = "None",
+ [PAGE_STATE_INSECURE] = "Not valid",
+ [PAGE_STATE_SECURE_OVERRIDE] = "Not valid",
+ [PAGE_STATE_SECURE_ISSUES] = "Not valid",
+ [PAGE_STATE_SECURE] = "Valid",
+ };
+
+ assert(pi != NULL);
+ assert(pi->state < PAGE_STATE__COUNT);
+
+ pi->entries[PI_ENTRY_HEADER].u.text.style = &pi__heading[pi->state];
+ pi->entries[PI_ENTRY_HEADER].u.text.text = header[pi->state];
+ pi->entries[PI_ENTRY_DOMAIN].u.text.text = (pi->domain) ?
+ lwc_string_data(pi->domain) : "<No domain>";
+
+ pi->entries[PI_ENTRY_CERT].u.item.item.text = "Certificate: ";
+ pi->entries[PI_ENTRY_CERT].u.item.detail.text = certificate[pi->state];
+
+ printed = snprintf(pi->cookie_text, sizeof(pi->cookie_text),
+ "(%u in use)", pi->cookies);
+ if (printed < 0) {
+ return NSERROR_UNKNOWN;
+
+ } else if ((unsigned) printed >= sizeof(pi->cookie_text)) {
+ return NSERROR_NOSPACE;
+ }
+ pi->entries[PI_ENTRY_COOKIES].u.item.item.text = "Cookies: ";
+ pi->entries[PI_ENTRY_COOKIES].u.item.detail.text = pi->cookie_text;
+
+ return page_info__measure_text(pi);
+}
+
+/**
+ * Create page info from a browser window.
+ *
+ * \param[in] pi The page info window handle.
+ * \param[in] bw Browser window to show page info for.
+ * \return NSERROR_OK on success, appropriate error code otherwise.
+ */
+static nserror page_info__create_from_bw(
+ struct page_info *pi,
+ struct browser_window *bw)
+{
+ nsurl *url = browser_window_access_url(bw);
+
+ pi->bw = bw;
+ pi->state = browser_window_get_page_info_state(bw);
+ pi->cookies = browser_window_get_cookie_count(bw);
+ pi->domain = nsurl_get_component(url, NSURL_HOST);
+ pi->scheme = nsurl_get_scheme_type(url);
+
+ return page_info__set_text(pi);
+}
+
+/**
+ * Check whether an entry is relevant.
+ *
+ * \param[in] entry The page info entry to consider.
+ * \param[in] scheme URL scheme that the page info is for.
+ * \return true if the entry should be hidden, otherwise false.
+ */
+static inline bool page_info__hide_entry(
+ enum pi_entry entry,
+ enum nsurl_scheme_type scheme)
+{
+ switch (entry) {
+ case PI_ENTRY_CERT:
+ if (scheme != NSURL_SCHEME_HTTPS) {
+ return true;
+ }
+ break;
+ case PI_ENTRY_COOKIES:
+ if (scheme != NSURL_SCHEME_HTTP &&
+ scheme != NSURL_SCHEME_HTTPS) {
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+/**
+ * Lay out the page info window.
+ *
+ * \param[in] pi The page info window handle.
+ * \return NSERROR_OK on success, appropriate error code otherwise.
+ */
+static nserror page_info__layout(
+ struct page_info *pi)
+{
+ int cur_y = 0;
+ int max_x = 0;
+
+ cur_y += pi->window_padding;
+ for (unsigned i = 0; i < PI_ENTRY__COUNT; i++) {
+ struct page_info_entry *entry = pi->entries + i;
+
+ if (page_info__hide_entry(i, pi->scheme)) {
+ continue;
+ }
+
+ switch (entry->type) {
+ case PAGE_INFO_ENTRY_TYPE_TEXT:
+ cur_y += entry->u.text.height;
+ if (max_x < entry->u.text.width) {
+ max_x = entry->u.text.width;
+ }
+ cur_y += entry->u.text.padding_bottom;
+ break;
+
+ case PAGE_INFO_ENTRY_TYPE_ITEM:
+ {
+ int full_width = entry->u.item.item.width +
+ entry->u.item.detail.width;
+ cur_y += entry->u.item.padding_top;
+ cur_y += entry->u.item.item.height;
+ if (max_x < full_width) {
+ max_x = full_width;
+ }
+ cur_y += entry->u.item.padding_bottom;
+ }
+ break;
+ }
+ }
+ cur_y += pi->window_padding;
+ max_x += pi->window_padding * 2;
+
+ pi->width = max_x;
+ pi->height = cur_y;
+ return pi->cw_t->update_size(pi->cw_h, max_x, cur_y);
+}
+
+/* Exported interface documented in desktop/page_info.h */
+nserror page_info_create(
+ const struct core_window_callback_table *cw_t,
+ struct core_window *cw_h,
+ struct browser_window *bw,
+ struct page_info **pi_out)
+{
+ struct page_info *pi;
+ nserror err;
+
+ pi = calloc(1, sizeof(*pi));
+ if (pi == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ pi->cw_t = cw_t;
+ pi->cw_h = cw_h;
+
+ memcpy(pi->entries, pi__entries, sizeof(pi__entries));
+
+ err = page_info__create_from_bw(pi, bw);
+ if (err != NSERROR_OK) {
+ page_info_destroy(pi);
+ return err;
+ }
+
+ err = page_info__layout(pi);
+ if (err != NSERROR_OK) {
+ page_info_destroy(pi);
+ return err;
+ }
+
+ *pi_out = pi;
+ return NSERROR_OK;
+}
+
+/* Exported interface documented in desktop/page_info.h */
+nserror page_info_destroy(struct page_info *pi)
+{
+ if (pi->domain != NULL) {
+ lwc_string_unref(pi->domain);
+ }
+ free(pi);
+ return NSERROR_OK;
+}
+
+/* Exported interface documented in desktop/page_info.h */
+nserror page_info_set(struct page_info *pgi, struct browser_window *bw)
+{
+ nserror res;
+
+ if (pgi->domain != NULL) {
+ lwc_string_unref(pgi->domain);
+ }
+
+ res = page_info__create_from_bw(pgi, bw);
+ if (res == NSERROR_OK) {
+ res = page_info__layout(pgi);
+ }
+
+ return res;
+}
+
+/**
+ * Render a text entry.
+ *
+ * \param[in] pit The page info window handle.
+ * \param[in] x X-coordinate to plot at.
+ * \param[in] y Y-coordinate to plot at.
+ * \param[in] ctx Current redraw context.
+ * \return NSERROR_OK on success, appropriate error code otherwise.
+ */
+static nserror page_info__redraw_text_entry(
+ const struct page_info_text *pit,
+ int x,
+ int y,
+ const struct redraw_context *ctx)
+{
+ int baseline = (pit->height * 3 + 2) / 4;
+
+ ctx->plot->text(ctx, pit->style, x, y + baseline,
+ pit->text, strlen(pit->text));
+
+ return NSERROR_OK;
+}
+
+/* Exported interface documented in desktop/page_info.h */
+nserror page_info_redraw(
+ const struct page_info *pi,
+ int x,
+ int y,
+ const struct rect *clip,
+ const struct redraw_context *ctx)
+{
+ struct redraw_context new_ctx = *ctx;
+ struct rect r = {
+ .x0 = clip->x0 + x,
+ .y0 = clip->y0 + y,
+ .x1 = clip->x1 + x,
+ .y1 = clip->y1 + y,
+ };
+ int cur_y = y;
+ nserror err;
+
+ /* Start knockout rendering if it's available for this plotter. */
+ if (ctx->plot->option_knockout) {
+ bool res = knockout_plot_start(ctx, &new_ctx);
+ if (res == false) {
+ return NSERROR_UNKNOWN;
+ }
+ }
+
+ /* Set up clip rectangle and draw background. */
+ new_ctx.plot->clip(&new_ctx, &r);
+ new_ctx.plot->rectangle(&new_ctx, &pi__bg, &r);
+
+ cur_y += pi->window_padding;
+ for (unsigned i = 0; i < PI_ENTRY__COUNT; i++) {
+ const struct page_info_entry *entry = pi->entries + i;
+ int cur_x = x + pi->window_padding;
+
+ if (page_info__hide_entry(i, pi->scheme)) {
+ continue;
+ }
+
+ switch (entry->type) {
+ case PAGE_INFO_ENTRY_TYPE_TEXT:
+ err = page_info__redraw_text_entry(
+ &entry->u.text,
+ cur_x, cur_y,
+ &new_ctx);
+ if (err != NSERROR_OK) {
+ goto cleanup;
+ }
+ cur_y += entry->u.text.height;
+ cur_y += entry->u.text.padding_bottom;
+ break;
+
+ case PAGE_INFO_ENTRY_TYPE_ITEM:
+ if (entry->u.item.hover) {
+ r.y0 = cur_y;
+ r.y1 = cur_y + entry->u.item.padding_top +
+ entry->u.item.item.height +
+ entry->u.item.padding_bottom;
+ new_ctx.plot->rectangle(&new_ctx,
+ &pi__hover, &r);
+ }
+ cur_y += entry->u.item.padding_top;
+ err = page_info__redraw_text_entry(
+ &entry->u.item.item,
+ cur_x, cur_y,
+ &new_ctx);
+ if (err != NSERROR_OK) {
+ goto cleanup;
+ }
+ cur_x += entry->u.item.item.width;
+ err = page_info__redraw_text_entry(
+ &entry->u.item.detail,
+ cur_x, cur_y,
+ &new_ctx);
+ if (err != NSERROR_OK) {
+ goto cleanup;
+ }
+ cur_y += entry->u.item.item.height;
+ cur_y += entry->u.item.padding_bottom;
+ break;
+ }
+ }
+
+cleanup:
+ /* Rendering complete */
+ if (ctx->plot->option_knockout) {
+ bool res = knockout_plot_end(ctx);
+ if (res == false) {
+ return NSERROR_UNKNOWN;
+ }
+ }
+
+ return NSERROR_OK;
+}
+
+/**
+ * Handle any clicks on an item.
+ *
+ * \param[in] pi The page info window handle.
+ * \param[in] mouse The current mouse state.
+ * \param[in] clicked The page info window entry to consider clicks on.
+ * \param[out] did_something Set to true if this click did something
+ * \return NSERROR_OK on success, appropriate error code otherwise.
+ */
+static nserror page_info__handle_item_click(
+ struct page_info *pi,
+ enum browser_mouse_state mouse,
+ enum pi_entry clicked,
+ bool *did_something)
+{
+ nserror err;
+
+ if (!(mouse & BROWSER_MOUSE_CLICK_1)) {
+ return NSERROR_OK;
+ }
+
+ switch (clicked) {
+ case PI_ENTRY_CERT:
+ err = browser_window_show_certificates(pi->bw);
+ *did_something = true;
+ break;
+ case PI_ENTRY_COOKIES:
+ err = browser_window_show_cookies(pi->bw);
+ *did_something = true;
+ break;
+ default:
+ err = NSERROR_OK;
+ break;
+ }
+
+ return err;
+}
+
+/* Exported interface documented in desktop/page_info.h */
+nserror page_info_mouse_action(
+ struct page_info *pi,
+ enum browser_mouse_state mouse,
+ int x,
+ int y,
+ bool *did_something)
+{
+ int cur_y = 0;
+ nserror err;
+
+ cur_y += pi->window_padding;
+ for (unsigned i = 0; i < PI_ENTRY__COUNT; i++) {
+ struct page_info_entry *entry = pi->entries + i;
+ bool hovering = false;
+ int height;
+
+ if (page_info__hide_entry(i, pi->scheme)) {
+ continue;
+ }
+
+ switch (entry->type) {
+ case PAGE_INFO_ENTRY_TYPE_TEXT:
+ cur_y += entry->u.text.height;
+ cur_y += entry->u.text.padding_bottom;
+ break;
+
+ case PAGE_INFO_ENTRY_TYPE_ITEM:
+ height = entry->u.item.padding_top +
+ entry->u.item.item.height +
+ entry->u.item.padding_bottom;
+
+ if (y >= cur_y && y < cur_y + height) {
+ hovering = true;
+ err = page_info__handle_item_click(
+ pi, mouse, i, did_something);
+ if (err != NSERROR_OK) {
+ return err;
+ }
+ }
+ if (entry->u.item.hover != hovering) {
+ int w, h;
+ struct rect r = {
+ .x0 = 0,
+ .y0 = cur_y,
+ .y1 = cur_y + height,
+ };
+ pi->cw_t->get_window_dimensions(
+ pi->cw_h, &w, &h);
+ r.x1 = (pi->width > w) ? pi->width : w;
+
+ pi->cw_t->invalidate(pi->cw_h, &r);
+ }
+ entry->u.item.hover = hovering;
+ cur_y += height;
+ break;
+ }
+ }
+
+ return NSERROR_OK;
+}
+
+/* Exported interface documented in desktop/page_info.h */
+bool page_info_keypress(
+ struct page_info *pi,
+ int32_t key)
+{
+ return NSERROR_OK;
+}
+
+/* Exported interface documented in desktop/page_info.h */
+nserror page_info_get_size(
+ struct page_info *pi,
+ int *width,
+ int *height)
+{
+ *width = pi->width;
+ *height = pi->height;
+
+ return NSERROR_OK;
+}
diff --git a/desktop/page-info.h b/desktop/page-info.h
new file mode 100644
index 000000000..152a88496
--- /dev/null
+++ b/desktop/page-info.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2020 Michael Drake <tlsa@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Pave info viewer window interface
+ */
+
+#ifndef NETSURF_DESKTOP_PAGE_INFO_H
+#define NETSURF_DESKTOP_PAGE_INFO_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "utils/errors.h"
+#include "netsurf/mouse.h"
+
+struct rect;
+struct nsurl;
+struct page_info;
+struct core_window;
+struct browser_window;
+struct redraw_context;
+struct core_window_callback_table;
+
+/**
+ * Initialise the page_info module.
+ *
+ * \return NSERROR_OK on success, appropriate error code otherwise.
+ */
+nserror page_info_init(void);
+
+/**
+ * Finalise the page_info module.
+ *
+ * \return NSERROR_OK on success, appropriate error code otherwise.
+ */
+nserror page_info_fini(void);
+
+/**
+ * Create a page info corewindow.
+ *
+ * The page info window is opened for a particular browser window.
+ * It can be destroyed before the browser window is destroyed by calling
+ * \ref page_info_destroy.
+ *
+ * \param[in] cw_t Callback table for the containing core_window.
+ * \param[in] cw_h Handle for the containing core_window.
+ * \param[in] bw Browser window to show page info for.
+ * \param[out] pi_out The created page info window handle.
+ * \return NSERROR_OK on success, appropriate error code otherwise.
+ */
+nserror page_info_create(
+ const struct core_window_callback_table *cw_t,
+ struct core_window *cw_h,
+ struct browser_window *bw,
+ struct page_info **pi_out);
+
+/**
+ * Destroy a page info corewindow.
+ *
+ * \param[in] pi The page info window handle.
+ */
+nserror page_info_destroy(struct page_info *pi);
+
+/**
+ * change the browser window the page information refers to
+ *
+ * \param[in] pgi The page info window context
+ * \param[in] bw The new browser window
+ * \return NSERROR_OK on sucess else error code.
+ */
+nserror page_info_set(struct page_info *pgi, struct browser_window *bw);
+
+/**
+ * Redraw the page info window.
+ *
+ * Causes the page info window to issue plot operations to redraw
+ * the specified area of the viewport.
+ *
+ * \param[in] pi The page info window handle.
+ * \param[in] x X coordinate to render page_info at.
+ * \param[in] y Y coordinate to render page_info at.
+ * \param[in] clip Current clip rectangle.
+ * \param[in] ctx Current redraw context.
+ * \return NSERROR_OK on success, appropriate error code otherwise.
+ */
+nserror page_info_redraw(
+ const struct page_info *pi,
+ int x,
+ int y,
+ const struct rect *clip,
+ const struct redraw_context *ctx);
+
+/**
+ * Mouse action handling.
+ *
+ * \param[in] pi The page info window handle.
+ * \param[in] mouse The current mouse state
+ * \param[in] x The current mouse X coordinate
+ * \param[in] y The current mouse Y coordinate
+ * \param[out] did_something Set to true if this resulted in some action
+ * \return NSERROR_OK on success, appropriate error code otherwise.
+ */
+nserror page_info_mouse_action(
+ struct page_info *pi,
+ enum browser_mouse_state mouse,
+ int x,
+ int y,
+ bool *did_something);
+
+/**
+ * Key press handling.
+ *
+ * \param[in] pi The page info window handle.
+ * \param[in] key The ucs4 character codepoint.
+ * \return true if the keypress is dealt with, false otherwise.
+ */
+bool page_info_keypress(
+ struct page_info *pi,
+ int32_t key);
+
+/**
+ * Get size of page info content area.
+ *
+ * \param[in] pi The page info window handle.
+ * \param[out] width On success, return the page info content width.
+ * \param[out] height On success, return the page info content height.
+ * \return NSERROR_OK on success, appropriate error code otherwise.
+ */
+nserror page_info_get_size(
+ struct page_info *pi,
+ int *width,
+ int *height);
+
+#endif
diff --git a/desktop/plot_style.c b/desktop/plot_style.c
index 1f0ac39cf..05954144a 100644
--- a/desktop/plot_style.c
+++ b/desktop/plot_style.c
@@ -47,7 +47,7 @@ plot_style_t *plot_style_fill_red = &plot_style_fill_red_static;
static const plot_style_t plot_style_content_edge_static = {
.stroke_type = PLOT_OP_TYPE_SOLID,
.stroke_colour = 0x00ff0000,
- .stroke_width = 1,
+ .stroke_width = plot_style_int_to_fixed(1),
};
plot_style_t const * const plot_style_content_edge =
&plot_style_content_edge_static;
@@ -55,7 +55,7 @@ plot_style_t const * const plot_style_content_edge =
static const plot_style_t plot_style_padding_edge_static = {
.stroke_type = PLOT_OP_TYPE_SOLID,
.stroke_colour = 0x000000ff,
- .stroke_width = 1,
+ .stroke_width = plot_style_int_to_fixed(1),
};
plot_style_t const * const plot_style_padding_edge =
&plot_style_padding_edge_static;
@@ -63,7 +63,7 @@ plot_style_t const * const plot_style_padding_edge =
static const plot_style_t plot_style_margin_edge_static = {
.stroke_type = PLOT_OP_TYPE_SOLID,
.stroke_colour = 0x0000ffff,
- .stroke_width = 1,
+ .stroke_width = plot_style_int_to_fixed(1),
};
plot_style_t const * const plot_style_margin_edge =
&plot_style_margin_edge_static;
@@ -74,14 +74,14 @@ static const plot_style_t plot_style_broken_object_static = {
.fill_colour = 0x008888ff,
.stroke_type = PLOT_OP_TYPE_SOLID,
.stroke_colour = 0x000000ff,
- .stroke_width = 1,
+ .stroke_width = plot_style_int_to_fixed(1),
};
plot_style_t const * const plot_style_broken_object =
&plot_style_broken_object_static;
static const plot_font_style_t plot_fstyle_broken_object_static = {
.family = PLOT_FONT_FAMILY_SANS_SERIF,
- .size = 16 * FONT_SIZE_SCALE,
+ .size = 16 * PLOT_STYLE_SCALE,
.weight = 400,
.flags = FONTF_NONE,
.background = 0x8888ff,
@@ -134,7 +134,7 @@ plot_style_t *plot_style_fill_wblobc = &plot_style_fill_wblobc_static;
static plot_style_t plot_style_stroke_wblobc_static = {
.stroke_type = PLOT_OP_TYPE_SOLID,
.stroke_colour = WIDGET_BLOBC,
- .stroke_width = 2,
+ .stroke_width = plot_style_int_to_fixed(2),
};
plot_style_t *plot_style_stroke_wblobc = &plot_style_stroke_wblobc_static;
@@ -156,7 +156,7 @@ plot_style_t *plot_style_stroke_lightwbasec = &plot_style_stroke_lightwbasec_sta
/* Generic font style */
static const plot_font_style_t plot_style_font_static = {
.family = PLOT_FONT_FAMILY_SANS_SERIF,
- .size = 8 * FONT_SIZE_SCALE,
+ .size = 8 * PLOT_STYLE_SCALE,
.weight = 400,
.flags = FONTF_NONE,
.background = 0xffffff,
diff --git a/desktop/print.c b/desktop/print.c
index 5c0333a96..e90e322ac 100644
--- a/desktop/print.c
+++ b/desktop/print.c
@@ -34,7 +34,7 @@
#include "netsurf/plotters.h"
#include "content/hlcache.h"
#include "css/utils.h"
-#include "render/box.h"
+#include "html/box.h"
#include "desktop/print.h"
#include "desktop/printer.h"
@@ -257,9 +257,9 @@ struct print_settings *print_make_settings(print_configuration configuration,
struct print_settings *settings;
css_fixed length = 0;
css_unit unit = CSS_UNIT_MM;
- nscss_len_ctx len_ctx = {
- .vw = DEFAULT_PAGE_WIDTH,
- .vh = DEFAULT_PAGE_HEIGHT,
+ css_unit_ctx unit_len_ctx = {
+ .viewport_width = DEFAULT_PAGE_WIDTH,
+ .viewport_height = DEFAULT_PAGE_HEIGHT,
.root_style = NULL,
};
@@ -277,17 +277,17 @@ struct print_settings *print_make_settings(print_configuration configuration,
settings->scale = DEFAULT_EXPORT_SCALE;
length = INTTOFIX(DEFAULT_MARGIN_LEFT_MM);
- settings->margins[MARGINLEFT] = nscss_len2px(
- &len_ctx, length, unit, NULL);
+ settings->margins[MARGINLEFT] = css_unit_len2device_px(
+ NULL, &unit_len_ctx, length, unit);
length = INTTOFIX(DEFAULT_MARGIN_RIGHT_MM);
- settings->margins[MARGINRIGHT] = nscss_len2px(
- &len_ctx, length, unit, NULL);
+ settings->margins[MARGINRIGHT] = css_unit_len2device_px(
+ NULL, &unit_len_ctx, length, unit);
length = INTTOFIX(DEFAULT_MARGIN_TOP_MM);
- settings->margins[MARGINTOP] = nscss_len2px(
- &len_ctx, length, unit, NULL);
+ settings->margins[MARGINTOP] = css_unit_len2device_px(
+ NULL, &unit_len_ctx, length, unit);
length = INTTOFIX(DEFAULT_MARGIN_BOTTOM_MM);
- settings->margins[MARGINBOTTOM] = nscss_len2px(
- &len_ctx, length, unit, NULL);
+ settings->margins[MARGINBOTTOM] = css_unit_len2device_px(
+ NULL, &unit_len_ctx, length, unit);
break;
/* use settings from the Export options tab */
case PRINT_OPTIONS:
@@ -303,17 +303,17 @@ struct print_settings *print_make_settings(print_configuration configuration,
settings->scale = (float)nsoption_int(export_scale) / 100;
length = INTTOFIX(nsoption_int(margin_left));
- settings->margins[MARGINLEFT] = nscss_len2px(
- &len_ctx, length, unit, NULL);
+ settings->margins[MARGINLEFT] = css_unit_len2device_px(
+ NULL, &unit_len_ctx, length, unit);
length = INTTOFIX(nsoption_int(margin_right));
- settings->margins[MARGINRIGHT] = nscss_len2px(
- &len_ctx, length, unit, NULL);
+ settings->margins[MARGINRIGHT] = css_unit_len2device_px(
+ NULL, &unit_len_ctx, length, unit);
length = INTTOFIX(nsoption_int(margin_top));
- settings->margins[MARGINTOP] = nscss_len2px(
- &len_ctx, length, unit, NULL);
+ settings->margins[MARGINTOP] = css_unit_len2device_px(
+ NULL, &unit_len_ctx, length, unit);
length = INTTOFIX(nsoption_int(margin_bottom));
- settings->margins[MARGINBOTTOM] = nscss_len2px(
- &len_ctx, length, unit, NULL);
+ settings->margins[MARGINBOTTOM] = css_unit_len2device_px(
+ NULL, &unit_len_ctx, length, unit);
break;
default:
return NULL;
diff --git a/desktop/save_complete.c b/desktop/save_complete.c
index 9a88ad180..e4fadd274 100644
--- a/desktop/save_complete.c
+++ b/desktop/save_complete.c
@@ -28,10 +28,10 @@
#include <string.h>
#include <strings.h>
#include <sys/types.h>
-#include <regex.h>
#include <dom/dom.h>
#include "utils/config.h"
+#include "utils/regex.h"
#include "utils/corestrings.h"
#include "utils/log.h"
#include "utils/nsurl.h"
@@ -43,14 +43,15 @@
#include "netsurf/content.h"
#include "content/hlcache.h"
#include "css/css.h"
-#include "render/box.h"
-#include "render/html.h"
+#include "html/box.h"
+#include "html/html_save.h"
+#include "html/html.h"
#include "netsurf/misc.h"
#include "desktop/gui_internal.h"
#include "desktop/save_complete.h"
-regex_t save_complete_import_re;
+static regex_t save_complete_import_re;
/** An entry in save_complete_list. */
typedef struct save_complete_entry {
@@ -74,9 +75,8 @@ typedef enum {
} save_complete_event_type;
-static bool save_complete_save_html(save_complete_ctx *ctx, struct hlcache_handle *c,
- bool index);
-static bool save_complete_save_imported_sheets(save_complete_ctx *ctx,
+static nserror save_complete_save_html(save_complete_ctx *ctx, struct hlcache_handle *c, bool index);
+static nserror save_complete_save_imported_sheets(save_complete_ctx *ctx,
struct nscss_import *imports, uint32_t import_count);
@@ -99,20 +99,22 @@ static void save_complete_ctx_finalise(save_complete_ctx *ctx)
}
}
-static bool save_complete_ctx_add_content(save_complete_ctx *ctx,
- struct hlcache_handle *content)
+static nserror
+save_complete_ctx_add_content(save_complete_ctx *ctx,
+ struct hlcache_handle *content)
{
save_complete_entry *entry;
entry = malloc(sizeof (*entry));
- if (entry == NULL)
- return false;
+ if (entry == NULL) {
+ return NSERROR_NOMEM;
+ }
entry->content = content;
entry->next = ctx->list;
ctx->list = entry;
- return true;
+ return NSERROR_OK;
}
/**
@@ -139,21 +141,27 @@ save_complete_ctx_find_content(save_complete_ctx *ctx, const nsurl *url)
}
-static bool save_complete_ctx_has_content(save_complete_ctx *ctx,
- struct hlcache_handle *content)
+static bool
+save_complete_ctx_has_content(save_complete_ctx *ctx,
+ struct hlcache_handle *content)
{
save_complete_entry *entry;
- for (entry = ctx->list; entry != NULL; entry = entry->next)
- if (entry->content == content)
+ for (entry = ctx->list; entry != NULL; entry = entry->next) {
+ if (hlcache_handle_get_content(entry->content) ==
+ hlcache_handle_get_content(content))
return true;
+ }
return false;
}
-static bool save_complete_save_buffer(save_complete_ctx *ctx,
- const char *leafname, const char *data, size_t data_len,
- lwc_string *mime_type)
+static nserror
+save_complete_save_buffer(save_complete_ctx *ctx,
+ const char *leafname,
+ const uint8_t *data,
+ size_t data_len,
+ lwc_string *mime_type)
{
nserror ret;
FILE *fp;
@@ -161,16 +169,14 @@ static bool save_complete_save_buffer(save_complete_ctx *ctx,
ret = netsurf_mkpath(&fname, NULL, 2, ctx->path, leafname);
if (ret != NSERROR_OK) {
- guit->misc->warning(messages_get_errorcode(ret), 0);
- return false;
+ return ret;
}
fp = fopen(fname, "wb");
if (fp == NULL) {
free(fname);
- NSLOG(netsurf, INFO, "fopen(): errno = %i", errno);
- guit->misc->warning("SaveError", strerror(errno));
- return false;
+ NSLOG(netsurf, INFO, "fopen(): %s", strerror(errno));
+ return NSERROR_SAVE_FAILED;
}
fwrite(data, sizeof(*data), data_len, fp);
@@ -182,9 +188,38 @@ static bool save_complete_save_buffer(save_complete_ctx *ctx,
}
free(fname);
- return true;
+ return NSERROR_OK;
+}
+
+
+/**
+ * perform a posix regexec on a string without a null terminator
+ */
+static int
+snregexec(regex_t *preg,
+ const char *string,
+ size_t stringlen,
+ size_t nmatch,
+ regmatch_t pmatch[],
+ int eflags)
+{
+ char *strbuf;
+ int matches;
+
+ strbuf = calloc(1, stringlen + 1);
+ if (strbuf == NULL) {
+ return -1;
+ }
+ memcpy(strbuf, string, stringlen);
+
+ matches = regexec(preg, strbuf, nmatch, pmatch, eflags);
+
+ free(strbuf);
+
+ return matches;
}
+
/**
* Rewrite stylesheet \@import rules for save complete.
*
@@ -195,14 +230,14 @@ static bool save_complete_save_buffer(save_complete_ctx *ctx,
* \param osize updated with the size of the result.
* \return converted source, or NULL on out of memory.
*/
-static char *
+static uint8_t *
save_complete_rewrite_stylesheet_urls(save_complete_ctx *ctx,
- const char *source,
- unsigned long size,
+ const uint8_t *source,
+ size_t size,
const nsurl *base,
- unsigned long *osize)
+ size_t *osize)
{
- char *rewritten;
+ uint8_t *rewritten;
unsigned long offset = 0;
unsigned int imports = 0;
nserror error;
@@ -230,13 +265,19 @@ save_complete_rewrite_stylesheet_urls(save_complete_ctx *ctx,
offset = 0;
while (offset < size) {
- const char *import_url = NULL;
+ const uint8_t *import_url = NULL;
char *import_url_copy;
int import_url_len = 0;
nsurl *url = NULL;
regmatch_t match[11];
- int m = regexec(&save_complete_import_re, source + offset,
- 11, match, 0);
+ int m;
+
+ m = snregexec(&save_complete_import_re,
+ (const char *)source + offset,
+ size - offset,
+ 11,
+ match,
+ 0);
if (m)
break;
@@ -258,7 +299,8 @@ save_complete_rewrite_stylesheet_urls(save_complete_ctx *ctx,
}
assert(import_url != NULL);
- import_url_copy = strndup(import_url, import_url_len);
+ import_url_copy = strndup((const char *)import_url,
+ import_url_len);
if (import_url_copy == NULL) {
free(rewritten);
return NULL;
@@ -314,44 +356,52 @@ save_complete_rewrite_stylesheet_urls(save_complete_ctx *ctx,
return rewritten;
}
-static bool save_complete_save_stylesheet(save_complete_ctx *ctx,
- hlcache_handle *css)
+static nserror
+save_complete_save_stylesheet(save_complete_ctx *ctx, hlcache_handle *css)
{
- const char *css_data;
- unsigned long css_size;
- char *source;
- unsigned long source_len;
+ const uint8_t *css_data;
+ size_t css_size;
+ uint8_t *source;
+ size_t source_len;
struct nscss_import *imports;
uint32_t import_count;
lwc_string *type;
char filename[32];
- bool result;
+ nserror result;
- if (save_complete_ctx_has_content(ctx, css))
- return true;
+ if (save_complete_ctx_find_content(ctx,
+ hlcache_handle_get_url(css)) != NULL) {
+ return NSERROR_OK;
+ }
- if (save_complete_ctx_add_content(ctx, css) == false) {
- guit->misc->warning("NoMemory", 0);
- return false;
+ result = save_complete_ctx_add_content(ctx, css);
+ if (result != NSERROR_OK) {
+ return result;
}
imports = nscss_get_imports(css, &import_count);
- if (save_complete_save_imported_sheets(ctx,
- imports, import_count) == false)
- return false;
+ result = save_complete_save_imported_sheets(ctx,
+ imports,
+ import_count);
+ if (result != NSERROR_OK) {
+ return result;
+ }
css_data = content_get_source_data(css, &css_size);
- source = save_complete_rewrite_stylesheet_urls(ctx, css_data, css_size,
- hlcache_handle_get_url(css), &source_len);
+ source = save_complete_rewrite_stylesheet_urls(
+ ctx,
+ css_data,
+ css_size,
+ hlcache_handle_get_url(css),
+ &source_len);
if (source == NULL) {
- guit->misc->warning("NoMemory", 0);
- return false;
+ return NSERROR_NOMEM;
}
type = content_get_mime_type(css);
if (type == NULL) {
free(source);
- return false;
+ return NSERROR_NOMEM;
}
snprintf(filename, sizeof filename, "%p", css);
@@ -365,70 +415,84 @@ static bool save_complete_save_stylesheet(save_complete_ctx *ctx,
return result;
}
-static bool save_complete_save_imported_sheets(save_complete_ctx *ctx,
- struct nscss_import *imports, uint32_t import_count)
+static nserror
+save_complete_save_imported_sheets(save_complete_ctx *ctx,
+ struct nscss_import *imports,
+ uint32_t import_count)
{
+ nserror res = NSERROR_OK;
uint32_t i;
for (i = 0; i < import_count; i++) {
/* treat a valid content as a stylesheet to save */
- if ((imports[i].c != NULL) &&
- (save_complete_save_stylesheet(ctx, imports[i].c) == false)) {
- return false;
+ if (imports[i].c != NULL) {
+ res = save_complete_save_stylesheet(ctx, imports[i].c);
+ if (res != NSERROR_OK) {
+ return res;
+ }
}
}
- return true;
+ return res;
}
-static bool save_complete_save_html_stylesheet(save_complete_ctx *ctx,
- struct html_stylesheet *sheet)
+static nserror
+save_complete_save_html_stylesheet(save_complete_ctx *ctx,
+ struct html_stylesheet *sheet)
{
- if (sheet->sheet == NULL)
- return true;
+ if (sheet->sheet == NULL) {
+ return NSERROR_OK;
+ }
return save_complete_save_stylesheet(ctx, sheet->sheet);
}
-static bool save_complete_save_html_stylesheets(save_complete_ctx *ctx,
- hlcache_handle *c)
+static nserror
+save_complete_save_html_stylesheets(save_complete_ctx *ctx,
+ hlcache_handle *c)
{
struct html_stylesheet *sheets;
unsigned int i, count;
+ nserror res;
sheets = html_get_stylesheets(c, &count);
for (i = STYLESHEET_START; i != count; i++) {
- if (save_complete_save_html_stylesheet(ctx,
- &sheets[i]) == false)
- return false;
+ res = save_complete_save_html_stylesheet(ctx, &sheets[i]);
+ if (res != NSERROR_OK) {
+ return res;
+ }
}
- return true;
+ return NSERROR_OK;
}
-static bool save_complete_save_html_object(save_complete_ctx *ctx,
- hlcache_handle *obj)
+static nserror
+save_complete_save_html_object(save_complete_ctx *ctx, hlcache_handle *obj)
{
- const char *obj_data;
- unsigned long obj_size;
+ const uint8_t *obj_data;
+ size_t obj_size;
lwc_string *type;
- bool result;
+ nserror result;
char filename[32];
- if (content_get_type(obj) == CONTENT_NONE)
- return true;
+ if (content_get_type(obj) == CONTENT_NONE) {
+ return NSERROR_OK;
+ }
obj_data = content_get_source_data(obj, &obj_size);
- if (obj_data == NULL)
- return true;
+ if (obj_data == NULL) {
+ return NSERROR_OK;
+ }
- if (save_complete_ctx_has_content(ctx, obj))
- return true;
+ if (save_complete_ctx_find_content(ctx,
+ hlcache_handle_get_url(obj)) != NULL) {
+ return NSERROR_OK;
+ }
- if (save_complete_ctx_add_content(ctx, obj) == false) {
- guit->misc->warning("NoMemory", 0);
- return false;
+ result = save_complete_ctx_add_content(ctx, obj);
+ if (result != NSERROR_OK) {
+ return result;
}
if (content_get_type(obj) == CONTENT_HTML) {
@@ -438,40 +502,46 @@ static bool save_complete_save_html_object(save_complete_ctx *ctx,
snprintf(filename, sizeof filename, "%p", obj);
type = content_get_mime_type(obj);
- if (type == NULL)
- return false;
+ if (type == NULL) {
+ return NSERROR_NOMEM;
+ }
- result = save_complete_save_buffer(ctx, filename,
- obj_data, obj_size, type);
+ result = save_complete_save_buffer(ctx, filename, obj_data, obj_size, type);
lwc_string_unref(type);
return result;
}
-static bool save_complete_save_html_objects(save_complete_ctx *ctx,
- hlcache_handle *c)
+static nserror
+save_complete_save_html_objects(save_complete_ctx *ctx,
+ hlcache_handle *c)
{
struct content_html_object *object;
unsigned int count;
+ nserror res;
object = html_get_objects(c, &count);
for (; object != NULL; object = object->next) {
- if ((object->content != NULL) && (object->box != NULL)) {
- if (save_complete_save_html_object(ctx,
- object->content) == false)
- return false;
+ if ((object->content != NULL) &&
+ (object->box != NULL)) {
+ res = save_complete_save_html_object(ctx, object->content);
+ if (res != NSERROR_OK) {
+ return res;
+ }
}
}
- return true;
+ return NSERROR_OK;
}
-static bool save_complete_libdom_treewalk(dom_node *root,
- bool (*callback)(dom_node *node,
- save_complete_event_type event_type, void *ctx),
- void *ctx)
+static bool
+save_complete_libdom_treewalk(dom_node *root,
+ bool (*callback)(dom_node *node,
+ save_complete_event_type event_type,
+ void *ctx),
+ void *ctx)
{
dom_node *node;
@@ -646,7 +716,7 @@ static bool save_complete_handle_attr_value(save_complete_ctx *ctx,
* 4) background any (except those above)
*/
/* 1 */
- if (name_len == SLEN("data") &&
+ if (name_len == SLEN("data") &&
strncasecmp(name_data, "data", name_len) == 0) {
if (node_len == SLEN("object") &&
strncasecmp(node_data,
@@ -661,13 +731,13 @@ static bool save_complete_handle_attr_value(save_complete_ctx *ctx,
/* 2 */
else if (name_len == SLEN("href") &&
strncasecmp(name_data, "href", name_len) == 0) {
- if ((node_len == SLEN("a") &&
+ if ((node_len == SLEN("a") &&
strncasecmp(node_data, "a", node_len) == 0) ||
(node_len == SLEN("area") &&
- strncasecmp(node_data, "area",
+ strncasecmp(node_data, "area",
node_len) == 0) ||
- (node_len == SLEN("link") &&
- strncasecmp(node_data, "link",
+ (node_len == SLEN("link") &&
+ strncasecmp(node_data, "link",
node_len) == 0)) {
return save_complete_rewrite_url_value(ctx,
value_data, value_len);
@@ -675,7 +745,7 @@ static bool save_complete_handle_attr_value(save_complete_ctx *ctx,
return save_complete_write_value(ctx,
value_data, value_len);
}
- }
+ }
/* 3 */
else if (name_len == SLEN("src") &&
strncasecmp(name_data, "src", name_len) == 0) {
@@ -712,8 +782,10 @@ static bool save_complete_handle_attr_value(save_complete_ctx *ctx,
}
}
-static bool save_complete_handle_attr(save_complete_ctx *ctx,
- dom_string *node_name, dom_attr *attr)
+static bool
+save_complete_handle_attr(save_complete_ctx *ctx,
+ dom_string *node_name,
+ dom_attr *attr)
{
dom_string *name;
const char *name_data;
@@ -742,12 +814,13 @@ static bool save_complete_handle_attr(save_complete_ctx *ctx,
if (value != NULL) {
fputc('=', ctx->fp);
- if (save_complete_handle_attr_value(ctx, node_name,
+ if (save_complete_handle_attr_value(ctx, node_name,
name, value) == false) {
dom_string_unref(value);
dom_string_unref(name);
return false;
}
+ dom_string_unref(value);
}
dom_string_unref(name);
@@ -755,8 +828,10 @@ static bool save_complete_handle_attr(save_complete_ctx *ctx,
return true;
}
-static bool save_complete_handle_attrs(save_complete_ctx *ctx,
- dom_string *node_name, dom_namednodemap *attrs)
+static bool
+save_complete_handle_attrs(save_complete_ctx *ctx,
+ dom_string *node_name,
+ dom_namednodemap *attrs)
{
uint32_t length, i;
dom_exception error;
@@ -786,8 +861,10 @@ static bool save_complete_handle_attrs(save_complete_ctx *ctx,
return true;
}
-static bool save_complete_handle_element(save_complete_ctx *ctx,
- dom_node *node, save_complete_event_type event_type)
+static bool
+save_complete_handle_element(save_complete_ctx *ctx,
+ dom_node *node,
+ save_complete_event_type event_type)
{
dom_string *name;
dom_namednodemap *attrs;
@@ -808,12 +885,12 @@ static bool save_complete_handle_element(save_complete_ctx *ctx,
name_data = dom_string_data(name);
name_len = dom_string_byte_length(name);
- if (name_len == SLEN("base") &&
- strncasecmp(name_data, "base", name_len) == 0) {
+ if ((name_len == SLEN("base")) &&
+ (strncasecmp(name_data, "base", name_len) == 0)) {
/* Elide BASE elements from the output */
process = false;
- } else if (name_len == SLEN("meta") &&
- strncasecmp(name_data, "meta", name_len) == 0) {
+ } else if ((name_len == SLEN("meta")) &&
+ (strncasecmp(name_data, "meta", name_len) == 0)) {
/* Don't emit close tags for META elements */
if (event_type == EVENT_LEAVE) {
process = false;
@@ -821,7 +898,8 @@ static bool save_complete_handle_element(save_complete_ctx *ctx,
/* Elide meta charsets */
dom_string *value;
error = dom_element_get_attribute(node,
- corestring_dom_http_equiv, &value);
+ corestring_dom_http_equiv,
+ &value);
if (error != DOM_NO_ERR) {
dom_string_unref(name);
return false;
@@ -850,8 +928,8 @@ static bool save_complete_handle_element(save_complete_ctx *ctx,
process = false;
}
}
- } else if (event_type == EVENT_LEAVE &&
- ((name_len == SLEN("link") &&
+ } else if (event_type == EVENT_LEAVE &&
+ ((name_len == SLEN("link") &&
strncasecmp(name_data, "link", name_len) == 0))) {
/* Don't emit close tags for void elements */
process = false;
@@ -863,8 +941,9 @@ static bool save_complete_handle_element(save_complete_ctx *ctx,
}
fputc('<', ctx->fp);
- if (event_type == EVENT_LEAVE)
+ if (event_type == EVENT_LEAVE) {
fputc('/', ctx->fp);
+ }
fwrite(name_data, sizeof(*name_data), name_len, ctx->fp);
if (event_type == EVENT_ENTER) {
@@ -897,13 +976,13 @@ static bool save_complete_handle_element(save_complete_ctx *ctx,
}
if (content != NULL) {
- char *rewritten;
- unsigned long len;
+ uint8_t *rewritten;
+ size_t len;
/* Rewrite @import rules */
rewritten = save_complete_rewrite_stylesheet_urls(
ctx,
- dom_string_data(content),
+ (const uint8_t *)dom_string_data(content),
dom_string_byte_length(content),
ctx->base,
&len);
@@ -934,8 +1013,10 @@ static bool save_complete_handle_element(save_complete_ctx *ctx,
return true;
}
-static bool save_complete_node_handler(dom_node *node,
- save_complete_event_type event_type, void *ctxin)
+static bool
+save_complete_node_handler(dom_node *node,
+ save_complete_event_type event_type,
+ void *ctxin)
{
save_complete_ctx *ctx = ctxin;
dom_node_type type;
@@ -977,7 +1058,7 @@ static bool save_complete_node_handler(dom_node *node,
if (ret != NSERROR_OK)
return false;
- fwrite(escaped, sizeof(*escaped),
+ fwrite(escaped, sizeof(*escaped),
strlen(escaped), ctx->fp);
free(escaped);
@@ -1053,8 +1134,10 @@ static bool save_complete_node_handler(dom_node *node,
return true;
}
-static bool save_complete_save_html_document(save_complete_ctx *ctx,
- hlcache_handle *c, bool index)
+static nserror
+save_complete_save_html_document(save_complete_ctx *ctx,
+ hlcache_handle *c,
+ bool index)
{
nserror ret;
FILE *fp;
@@ -1071,16 +1154,14 @@ static bool save_complete_save_html_document(save_complete_ctx *ctx,
ret = netsurf_mkpath(&fname, NULL, 2, ctx->path, filename);
if (ret != NSERROR_OK) {
- guit->misc->warning(messages_get_errorcode(ret), NULL);
- return false;
+ return ret;
}
fp = fopen(fname, "wb");
if (fp == NULL) {
free(fname);
- NSLOG(netsurf, INFO, "fopen(): errno = %i", errno);
- guit->misc->warning("SaveError", strerror(errno));
- return false;
+ NSLOG(netsurf, INFO, "fopen(): %s", strerror(errno));
+ return NSERROR_SAVE_FAILED;
}
ctx->base = html_get_base_url(c);
@@ -1089,26 +1170,27 @@ static bool save_complete_save_html_document(save_complete_ctx *ctx,
doc = html_get_document(c);
- if (save_complete_libdom_treewalk((dom_node *) doc,
- save_complete_node_handler, ctx) == false) {
+ if (save_complete_libdom_treewalk((dom_node *)doc,
+ save_complete_node_handler,
+ ctx) == false) {
free(fname);
- guit->misc->warning("NoMemory", 0);
fclose(fp);
- return false;
+ return NSERROR_NOMEM;
}
fclose(fp);
mime_type = content_get_mime_type(c);
if (mime_type != NULL) {
- if (ctx->set_type != NULL)
+ if (ctx->set_type != NULL) {
ctx->set_type(fname, mime_type);
+ }
lwc_string_unref(mime_type);
}
free(fname);
- return true;
+ return NSERROR_OK;
}
/**
@@ -1119,20 +1201,30 @@ static bool save_complete_save_html_document(save_complete_ctx *ctx,
* \param index true to save as "index"
* \return true on success, false on error and error reported
*/
-static bool save_complete_save_html(save_complete_ctx *ctx, hlcache_handle *c,
- bool index)
+static nserror
+save_complete_save_html(save_complete_ctx *ctx,
+ hlcache_handle *c,
+ bool index)
{
- if (content_get_type(c) != CONTENT_HTML)
- return false;
+ nserror res;
- if (save_complete_ctx_has_content(ctx, c))
- return true;
+ if (content_get_type(c) != CONTENT_HTML) {
+ return NSERROR_INVALID;
+ }
- if (save_complete_save_html_stylesheets(ctx, c) == false)
- return false;
+ if (save_complete_ctx_has_content(ctx, c)) {
+ return NSERROR_OK;
+ }
- if (save_complete_save_html_objects(ctx, c) == false)
- return false;
+ res = save_complete_save_html_stylesheets(ctx, c);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = save_complete_save_html_objects(ctx, c);
+ if (res != NSERROR_OK) {
+ return res;
+ }
return save_complete_save_html_document(ctx, c, index);
}
@@ -1142,7 +1234,7 @@ static bool save_complete_save_html(save_complete_ctx *ctx, hlcache_handle *c,
* Create the inventory file listing original URLs.
*/
-static bool save_complete_inventory(save_complete_ctx *ctx)
+static nserror save_complete_inventory(save_complete_ctx *ctx)
{
nserror ret;
FILE *fp;
@@ -1151,26 +1243,26 @@ static bool save_complete_inventory(save_complete_ctx *ctx)
ret = netsurf_mkpath(&fname, NULL, 2, ctx->path, "Inventory");
if (ret != NSERROR_OK) {
- return false;
+ return ret;
}
fp = fopen(fname, "w");
free(fname);
if (fp == NULL) {
- NSLOG(netsurf, INFO, "fopen(): errno = %i", errno);
- guit->misc->warning("SaveError", strerror(errno));
- return false;
+ NSLOG(netsurf, INFO, "fopen(): %s", strerror(errno));
+ return NSERROR_SAVE_FAILED;
}
for (entry = ctx->list; entry != NULL; entry = entry->next) {
- fprintf(fp, "%p %s\n", entry->content,
- nsurl_access(hlcache_handle_get_url(
- entry->content)));
+ fprintf(fp, "%p %s\n",
+ entry->content,
+ nsurl_access(hlcache_handle_get_url(
+ entry->content)));
}
fclose(fp);
- return true;
+ return NSERROR_OK;
}
/**
@@ -1227,17 +1319,26 @@ void save_complete_init(void)
}
/* Documented in save_complete.h */
-bool save_complete(hlcache_handle *c, const char *path,
- save_complete_set_type_cb set_type)
+nserror save_complete_finalise(void)
+{
+ regfree(&save_complete_import_re);
+ return NSERROR_OK;
+}
+
+/* Documented in save_complete.h */
+nserror
+save_complete(hlcache_handle *c,
+ const char *path,
+ save_complete_set_type_cb set_type)
{
- bool result;
+ nserror result;
save_complete_ctx ctx;
save_complete_ctx_initialise(&ctx, path, set_type);
-
+
result = save_complete_save_html(&ctx, c, true);
- if (result) {
+ if (result == NSERROR_OK) {
result = save_complete_inventory(&ctx);
}
@@ -1245,4 +1346,3 @@ bool save_complete(hlcache_handle *c, const char *path,
return result;
}
-
diff --git a/desktop/save_complete.h b/desktop/save_complete.h
index 3c389a56f..7df89f0b5 100644
--- a/desktop/save_complete.h
+++ b/desktop/save_complete.h
@@ -21,8 +21,8 @@
* Save HTML document with dependencies (interface).
*/
-#ifndef _NETSURF_DESKTOP_SAVE_COMPLETE_H_
-#define _NETSURF_DESKTOP_SAVE_COMPLETE_H_
+#ifndef NETSURF_DESKTOP_SAVE_COMPLETE_H_
+#define NETSURF_DESKTOP_SAVE_COMPLETE_H_
#include <stdbool.h>
@@ -44,15 +44,21 @@ typedef void (*save_complete_set_type_cb)(const char *path,
*/
void save_complete_init(void);
+
+/**
+ * Finalise save complete module.
+ */
+nserror save_complete_finalise(void);
+
/**
* Save an HTML page with all dependencies.
*
* \param c CONTENT_HTML to save
* \param path Native path to directory to save in to (must exist)
* \param set_type Callback to set type of a file, or NULL
- * \return true on success, false on error and error reported
+ * \return NSERROR_OK on success else error code
*/
-bool save_complete(struct hlcache_handle *c, const char *path,
+nserror save_complete(struct hlcache_handle *c, const char *path,
save_complete_set_type_cb set_type);
#endif
diff --git a/desktop/save_pdf.c b/desktop/save_pdf.c
index 83e3d4f31..889190089 100644
--- a/desktop/save_pdf.c
+++ b/desktop/save_pdf.c
@@ -213,10 +213,10 @@ bool pdf_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *psty
}
apply_clip_and_mode(false,
- NS_TRANSPARENT,
- pstyle->stroke_colour,
- pstyle->stroke_width,
- dash);
+ NS_TRANSPARENT,
+ pstyle->stroke_colour,
+ plot_style_int_to_fixed(pstyle->stroke_width),
+ dash);
HPDF_Page_Rectangle(pdf_page, x0, page_height - y0, x1 - x0, -(y1 - y0));
HPDF_Page_Stroke(pdf_page);
@@ -245,10 +245,10 @@ bool pdf_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *pstyle)
}
apply_clip_and_mode(false,
- NS_TRANSPARENT,
- pstyle->stroke_colour,
- pstyle->stroke_width,
- dash);
+ NS_TRANSPARENT,
+ pstyle->stroke_colour,
+ plot_style_int_to_fixed(pstyle->stroke_width),
+ dash);
HPDF_Page_MoveTo(pdf_page, x0, page_height - y0);
HPDF_Page_LineTo(pdf_page, x1, page_height - y1);
diff --git a/desktop/save_text.c b/desktop/save_text.c
index 791ae9201..a86f173b0 100644
--- a/desktop/save_text.c
+++ b/desktop/save_text.c
@@ -32,8 +32,8 @@
#include "utils/utf8.h"
#include "utils/utils.h"
#include "netsurf/content.h"
-#include "render/box.h"
-#include "render/html.h"
+#include "html/box.h"
+#include "html/html_save.h"
#include "netsurf/utf8.h"
#include "desktop/gui_internal.h"
diff --git a/desktop/scrollbar.c b/desktop/scrollbar.c
index 5a7420ae1..90ea924cc 100644
--- a/desktop/scrollbar.c
+++ b/desktop/scrollbar.c
@@ -29,6 +29,7 @@
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utils.h"
+#include "utils/nscolour.h"
#include "utils/nsoption.h"
#include "netsurf/browser_window.h"
#include "netsurf/mouse.h"
@@ -164,17 +165,17 @@ scrollbar_rectangle(const struct redraw_context *ctx,
static plot_style_t c0 = {
.stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_width = 1,
+ .stroke_width = plot_style_int_to_fixed(1),
};
static plot_style_t c1 = {
.stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_width = 1,
+ .stroke_width = plot_style_int_to_fixed(1),
};
static plot_style_t c2 = {
.stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_width = 1,
+ .stroke_width = plot_style_int_to_fixed(1),
};
if (inset) {
@@ -250,29 +251,17 @@ scrollbar_redraw(struct scrollbar *s,
plot_style_t bg_fill_style = {
.fill_type = PLOT_OP_TYPE_SOLID,
+ .fill_colour = nscolours[NSCOLOUR_SCROLL_WELL],
};
plot_style_t fg_fill_style = {
.fill_type = PLOT_OP_TYPE_SOLID,
+ .fill_colour = nscolours[NSCOLOUR_BUTTON_BG],
};
plot_style_t arrow_fill_style = {
.fill_type = PLOT_OP_TYPE_SOLID,
+ .fill_colour = nscolours[NSCOLOUR_BUTTON_FG],
};
- res = ns_system_colour_char("Scrollbar", &bg_fill_style.fill_colour);
- if (res != NSERROR_OK) {
- return res;
- }
-
- res = ns_system_colour_char("ButtonFace", &fg_fill_style.fill_colour);
- if (res != NSERROR_OK) {
- return res;
- }
-
- res = ns_system_colour_char("ButtonText", &arrow_fill_style.fill_colour);
- if (res != NSERROR_OK) {
- return res;
- }
-
area.x0 = x;
area.y0 = y;
area.x1 = x + (s->horizontal ? s->length : SCROLLBAR_WIDTH) - 1;
diff --git a/desktop/scrollbar.h b/desktop/scrollbar.h
index fa5e167f2..796520724 100644
--- a/desktop/scrollbar.h
+++ b/desktop/scrollbar.h
@@ -38,6 +38,7 @@
#define SCROLL_BOTTOM INT_MAX
struct scrollbar;
+struct redraw_context;
/**
* scrollbar message types
diff --git a/desktop/search.c b/desktop/search.c
index 201d416dd..e21f520a6 100644
--- a/desktop/search.c
+++ b/desktop/search.c
@@ -18,11 +18,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
- /** \file
+/**
+ * \file
* Free text search (core)
*/
-#include "content/content.h"
+#include <stdbool.h>
+
+#include "utils/errors.h"
+#include "content/textsearch.h"
+#include "netsurf/types.h"
+#include "netsurf/browser_window.h"
#include "desktop/browser_private.h"
#include "desktop/search.h"
@@ -33,7 +39,7 @@ void browser_window_search(struct browser_window *bw, void *context,
{
if ((bw != NULL) &&
(bw->current_content != NULL)) {
- content_search(bw->current_content, context, flags, string);
+ content_textsearch(bw->current_content, context, flags, string);
}
}
@@ -42,6 +48,6 @@ void browser_window_search_clear(struct browser_window *bw)
{
if ((bw != NULL) &&
(bw->current_content != NULL)) {
- content_search_clear(bw->current_content);
+ content_textsearch_clear(bw->current_content);
}
}
diff --git a/desktop/search.h b/desktop/search.h
index baf382e77..c39d1d8a3 100644
--- a/desktop/search.h
+++ b/desktop/search.h
@@ -16,11 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_DESKTOP_SEARCH_H_
-#define _NETSURF_DESKTOP_SEARCH_H_
+/**
+ * \file
+ * Browseing window text search interface
+ */
-#include <ctype.h>
-#include <string.h>
+#ifndef NETSURF_DESKTOP_SEARCH_H_
+#define NETSURF_DESKTOP_SEARCH_H_
struct browser_window;
diff --git a/desktop/searchweb.c b/desktop/searchweb.c
index c07cac9d5..361860190 100644
--- a/desktop/searchweb.c
+++ b/desktop/searchweb.c
@@ -17,11 +17,12 @@
*/
/**
- * \file desktop/searchweb.c
+ * \file
* \brief core web search facilities implementation.
*/
#include <stdlib.h>
+#include <string.h>
#include "utils/utils.h"
#include "utils/log.h"
@@ -52,7 +53,7 @@ static struct search_web_ctx_s {
} search_web_ctx;
-static const char *default_providers = "Google|www.google.com|http://www.google.com/search?q=%s|http://www.google.com/favicon.ico|\n";
+static const char *default_providers = "Google|www.google.com|https://www.google.com/search?q=%s|https://www.google.com/favicon.ico|\n";
static const char *default_search_icon_url = "resource:icons/search.png";
@@ -298,10 +299,8 @@ search_web_ico_callback(hlcache_handle *ico,
case CONTENT_MSG_ERROR:
NSLOG(netsurf, INFO, "icon %s error: %s",
nsurl_access(hlcache_handle_get_url(ico)),
- event->data.error);
- /* fall through */
+ event->data.errordata.errormsg);
- case CONTENT_MSG_ERRORCODE:
hlcache_handle_release(ico);
/* clear reference to released handle */
provider->ico_handle = NULL;
@@ -334,11 +333,11 @@ search_web_omni(const char *term,
}
/* try with adding default scheme */
- eterm = malloc(strlen(term) + SLEN("http://") + 1);
+ eterm = malloc(strlen(term) + SLEN("https://") + 1);
if (eterm == NULL) {
return NSERROR_NOMEM;
}
- sprintf(eterm, "http://%s", term);
+ sprintf(eterm, "https://%s", term);
ret = nsurl_create(eterm, &url);
free(eterm);
if (ret == NSERROR_OK) {
@@ -368,6 +367,33 @@ search_web_omni(const char *term,
}
/* exported interface documented in desktop/searchweb.h */
+nserror search_web_get_provider_bitmap(struct bitmap **bitmap_out)
+{
+ struct search_provider *provider;
+ struct bitmap *ico_bitmap = NULL;
+
+ /* must be initialised */
+ if (search_web_ctx.providers == NULL) {
+ return NSERROR_INIT_FAILED;
+ }
+
+ provider = &search_web_ctx.providers[search_web_ctx.current];
+
+ /* set the icon now (if we can) at least to the default */
+ if (provider->ico_handle != NULL) {
+ ico_bitmap = content_get_bitmap(provider->ico_handle);
+ }
+ if ((ico_bitmap == NULL) &&
+ (search_web_ctx.default_ico_handle != NULL)) {
+ ico_bitmap = content_get_bitmap(search_web_ctx.default_ico_handle);
+ }
+
+ *bitmap_out = ico_bitmap;
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in desktop/searchweb.h */
nserror search_web_select_provider(int selection)
{
struct search_provider *provider;
@@ -458,10 +484,8 @@ default_ico_callback(hlcache_handle *ico,
case CONTENT_MSG_ERROR:
NSLOG(netsurf, INFO, "icon %s error: %s",
nsurl_access(hlcache_handle_get_url(ico)),
- event->data.error);
- /* fall through */
+ event->data.errordata.errormsg);
- case CONTENT_MSG_ERRORCODE:
hlcache_handle_release(ico);
/* clear reference to released handle */
ctx->default_ico_handle = NULL;
@@ -524,10 +548,14 @@ nserror search_web_init(const char *provider_fname)
}
/* get default search icon */
- ret = hlcache_handle_retrieve(icon_nsurl, 0, NULL, NULL,
+ ret = hlcache_handle_retrieve(icon_nsurl,
+ 0,
+ NULL,
+ NULL,
default_ico_callback,
&search_web_ctx,
- NULL, CONTENT_IMAGE,
+ NULL,
+ CONTENT_IMAGE,
&search_web_ctx.default_ico_handle);
nsurl_unref(icon_nsurl);
if (ret != NSERROR_OK) {
diff --git a/desktop/searchweb.h b/desktop/searchweb.h
index a96e7787b..0712de9fe 100644
--- a/desktop/searchweb.h
+++ b/desktop/searchweb.h
@@ -62,7 +62,7 @@ enum search_web_omni_flags {
* term. The flags allow control over the operation. By default the
* operations are:
* - interpret the \a term as a url
- * - if missing a scheme as a http: url
+ * - if missing a scheme as a https: url
* - combined with the search providers url into a url for that provider.
*
* \param term The search term.
@@ -72,6 +72,17 @@ enum search_web_omni_flags {
*/
nserror search_web_omni(const char *term, enum search_web_omni_flags flags, struct nsurl **url_out);
+
+/**
+ * obtain the current providers bitmap
+ *
+ * obtain the icon representing the current web search provider
+ *
+ * \param bitmap_out recives the resulting bitmap which may be NULL
+ * \return NSERROR_OK on success or NSERROR_INIT_FAILED if not initialised
+ */
+nserror search_web_get_provider_bitmap(struct bitmap **bitmap_out);
+
/**
* Change the currently selected web search provider.
*
diff --git a/desktop/selection.c b/desktop/selection.c
index 5cb43b8c3..8b1f127c4 100644
--- a/desktop/selection.c
+++ b/desktop/selection.c
@@ -17,47 +17,24 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Text selection within browser windows (implementation).
- */
+/**
+ * \file
+ * implementation of text selection within browser windows.
+ */
-#include <assert.h>
-#include <stdio.h>
#include <stdlib.h>
-#include <stdbool.h>
#include <string.h>
-#include <dom/dom.h>
-#include "utils/log.h"
-#include "utils/utf8.h"
+#include "netsurf/clipboard.h"
+#include "netsurf/browser_window.h"
+#include "netsurf/window.h"
#include "utils/utils.h"
-#include "netsurf/form.h"
-#include "render/box.h"
-#include "render/html_internal.h"
-#include "render/font.h"
-#include "render/textplain.h"
+#include "content/content_protected.h"
-#include "netsurf/mouse.h"
#include "desktop/browser_private.h"
-#include "netsurf/plotters.h"
-#include "desktop/save_text.h"
-#include "desktop/selection.h"
-#include "netsurf/clipboard.h"
-#include "netsurf/window.h"
#include "desktop/gui_internal.h"
+#include "desktop/selection.h"
-/**
- * Text selection works by labelling each node in the box tree with its
- * start index in the textual representation of the tree's content.
- */
-
-#define SPACE_LEN(b) ((b->space == 0) ? 0 : 1)
-
-
-struct rdw_info {
- bool inited;
- struct rect r;
-};
struct selection_string {
char *buffer;
@@ -69,750 +46,414 @@ struct selection_string {
};
-typedef bool (*seln_traverse_handler)(const char *text, size_t length,
- struct box *box, const nscss_len_ctx *len_ctx, void *handle,
- const char *whitespace_text, size_t whitespace_length);
+typedef enum {
+ DRAG_NONE,
+ DRAG_START,
+ DRAG_END
+} seln_drag_state;
+struct selection {
+ struct content *c;
-static bool redraw_handler(const char *text, size_t length,
- struct box *box, const nscss_len_ctx *len_ctx,
- void *handle, const char *whitespace_text,
- size_t whitespace_length);
-static void selection_redraw(struct selection *s, unsigned start_idx,
- unsigned end_idx);
-static bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx,
- unsigned *start_offset, unsigned *end_offset);
-static bool traverse_tree(struct box *box, const nscss_len_ctx *len_ctx,
- unsigned start_idx, unsigned end_idx,
- seln_traverse_handler handler,
- void *handle, save_text_whitespace *before, bool *first,
- bool do_marker);
-static unsigned selection_label_subtree(struct box *box, unsigned idx);
+ unsigned max_idx; /* total bytes in text representation */
-/**
- * Get the browser window containing the content a selection object belongs to.
- *
- * \param s selection object
- * \return the browser window
- */
-static struct browser_window * selection_get_browser_window(struct selection *s)
-{
- if (s->is_html)
- return html_get_browser_window(s->c);
- else
- return textplain_get_browser_window(s->c);
-}
+ unsigned start_idx; /* offset in bytes within text representation */
+ unsigned end_idx;
+ bool defined;
+
+ seln_drag_state drag_state;
+};
/**
- * Creates a new selection object associated with a browser window.
+ * Redraws the given range of text.
*
- * \return new selection context
+ * \param s selection object
+ * \param start_idx start offset (bytes) within the textual representation
+ * \param end_idx end offset (bytes) within the textual representation
*/
-
-struct selection *selection_create(struct content *c, bool is_html)
+static nserror
+selection_redraw(struct selection *s, unsigned start_idx, unsigned end_idx)
{
- struct selection *s = calloc(1, sizeof(struct selection));
- if (s) {
- selection_prepare(s, c, is_html);
+ nserror res;
+
+ if (s->c->handler->textselection_redraw != NULL) {
+ res = s->c->handler->textselection_redraw(s->c,
+ start_idx,
+ end_idx);
+ } else {
+ res = NSERROR_NOT_IMPLEMENTED;
}
- return s;
+ return res;
}
+
/**
- * Prepare a newly created selection object for use.
+ * Set the start position of the current selection, updating the screen.
*
- * \param s selection object
- * \param c content
- * \param is_html true if content is html false if content is textplain
+ * \param s selection object
+ * \param offset byte offset within textual representation
*/
-
-void selection_prepare(struct selection *s, struct content *c, bool is_html)
+static void selection_set_start(struct selection *s, unsigned offset)
{
- if (s) {
- s->c = c;
- s->is_html = is_html;
- s->root = NULL;
- s->drag_state = DRAG_NONE;
- s->max_idx = 0;
- selection_clear(s, false);
- }
-}
+ bool was_defined;
+ unsigned old_start;
+ old_start = s->start_idx;
+ s->start_idx = offset;
-/**
- * Destroys a selection object, without updating the
- * owning window (caller should call selection_clear()
- * first if update is desired)
- *
- * \param s selection object
- */
+ was_defined = s->defined;
+ s->defined = (s->start_idx < s->end_idx);
-void selection_destroy(struct selection *s)
-{
- if (s != NULL)
- free(s);
+ if (was_defined) {
+ if (offset < old_start) {
+ selection_redraw(s, s->start_idx, old_start);
+ } else {
+ selection_redraw(s, old_start, s->start_idx);
+ }
+ } else if (s->defined) {
+ selection_redraw(s, s->start_idx, s->end_idx);
+ }
}
/**
- * Initialise the selection object to use the given box subtree as its root,
- * ie. selections are confined to that subtree, whilst maintaining the current
- * selection whenever possible because, for example, it's just the page being
- * resized causing the layout to change.
+ * Set the end position of the current selection, updating the screen.
*
- * \param s selection object
- * \param root the root box for html document or NULL for text/plain
+ * \param s selection object
+ * \param offset byte offset within textual representation
*/
-
-void selection_reinit(struct selection *s, struct box *root)
+static void selection_set_end(struct selection *s, unsigned offset)
{
- unsigned root_idx;
-
- assert(s);
+ bool was_defined;
+ unsigned old_end;
- root_idx = 0;
+ old_end = s->end_idx;
+ s->end_idx = offset;
- s->root = root;
- if (root) {
- s->max_idx = selection_label_subtree(root, root_idx);
- } else {
- if (s->is_html == false)
- s->max_idx = textplain_size(s->c);
- else
- s->max_idx = 0;
- }
+ was_defined = s->defined;
+ s->defined = (s->start_idx < s->end_idx);
- if (s->defined) {
- if (s->end_idx > s->max_idx) s->end_idx = s->max_idx;
- if (s->start_idx > s->max_idx) s->start_idx = s->max_idx;
- s->defined = (s->end_idx > s->start_idx);
+ if (was_defined) {
+ if (offset < old_end) {
+ selection_redraw(s, s->end_idx, old_end);
+ } else {
+ selection_redraw(s, old_end, s->end_idx);
+ }
+ } else if (s->defined) {
+ selection_redraw(s, s->start_idx, s->end_idx);
}
}
/**
- * Initialise the selection object to use the given box subtree as its root,
- * ie. selections are confined to that subtree.
+ * Traverse the current selection, calling the handler function (with its
+ * handle) for all boxes that lie (partially) within the given range
*
- * \param s selection object
- * \param root the root box for html document or NULL for text/plain
+ * \param s The selection context.
+ * \param handler handler function to call
+ * \param handle handle to pass
+ * \return false iff traversal abandoned part-way through
*/
-
-void selection_init(
- struct selection *s,
- struct box *root,
- const nscss_len_ctx *len_ctx)
+static bool
+selection_copy(struct selection *s, struct selection_string *selstr)
{
- if (s->defined)
- selection_clear(s, true);
+ nserror res;
- s->defined = false;
- s->start_idx = 0;
- s->end_idx = 0;
- s->drag_state = DRAG_NONE;
- if (len_ctx != NULL) {
- s->len_ctx = *len_ctx;
+ if (s->c->handler->textselection_copy != NULL) {
+ res = s->c->handler->textselection_copy(s->c,
+ s->start_idx,
+ s->end_idx,
+ selstr);
} else {
- s->len_ctx.vw = 0;
- s->len_ctx.vh = 0;
- s->len_ctx.root_style = NULL;
+ res = NSERROR_NOT_IMPLEMENTED;
}
- selection_reinit(s, root);
-}
-
-
-/**
- * Label each text box in the given box subtree with its position
- * in a textual representation of the content.
- *
- * \param box The box at root of subtree
- * \param idx current position within textual representation
- * \return updated position
- */
-
-unsigned selection_label_subtree(struct box *box, unsigned idx)
-{
- struct box *child = box->children;
-
- box->byte_offset = idx;
-
- if (box->text)
- idx += box->length + SPACE_LEN(box);
-
- while (child) {
- if (child->list_marker)
- idx = selection_label_subtree(child->list_marker, idx);
-
- idx = selection_label_subtree(child, idx);
- child = child->next;
+ if (res != NSERROR_OK) {
+ return false;
}
-
- return idx;
+ return true;
}
/**
- * Handles mouse clicks (including drag starts) in or near a selection
- *
- * \param s selection object
- * \param mouse state of mouse buttons and modifier keys
- * \param idx byte offset within textual representation
+ * Append text to selection string.
*
- * \return true iff the click has been handled by the selection code
+ * \param text text to be added
+ * \param length length of text in bytes
+ * \param space indicates whether a trailing space should be appended
+ * \param style The font style to use.
+ * \param sel_string string to append to, may be resized
+ * \return true iff successful
*/
-
-bool selection_click(struct selection *s, browser_mouse_state mouse,
- unsigned idx)
+bool
+selection_string_append(const char *text,
+ size_t length,
+ bool space,
+ plot_font_style_t *style,
+ struct selection_string *sel_string)
{
- browser_mouse_state modkeys =
- (mouse & (BROWSER_MOUSE_MOD_1 | BROWSER_MOUSE_MOD_2));
- int pos = -1; /* 0 = inside selection, 1 = after it */
- struct browser_window *top = selection_get_browser_window(s);
- top = browser_window_get_root(top);
-
- if (selection_defined(s)) {
- if (idx > s->start_idx) {
- if (idx <= s->end_idx)
- pos = 0;
- else
- pos = 1;
- }
- }
-
- if (!pos &&
- ((mouse & BROWSER_MOUSE_DRAG_1) ||
- (modkeys && (mouse & BROWSER_MOUSE_DRAG_2)))) {
- /* drag-saving selection */
- char *sel = selection_get_copy(s);
- guit->window->drag_save_selection(top->window, sel);
- free(sel);
- }
- else if (!modkeys) {
- if (pos && (mouse & BROWSER_MOUSE_PRESS_1)) {
- /* Clear the selection if mouse is pressed outside the
- * selection, Otherwise clear on release (to allow for drags) */
-
- selection_clear(s, true);
- } else if (mouse & BROWSER_MOUSE_DRAG_1) {
- /* start new selection drag */
+ size_t new_length = sel_string->length + length + (space ? 1 : 0) + 1;
- selection_clear(s, true);
-
- selection_set_start(s, idx);
- selection_set_end(s, idx);
+ if (style != NULL) {
+ /* Add text run style */
+ nsclipboard_styles *new_styles;
- s->drag_state = DRAG_END;
+ if (sel_string->n_styles == 0) {
+ assert(sel_string->length == 0);
+ }
- guit->window->start_selection(top->window);
+ new_styles = realloc(sel_string->styles,
+ (sel_string->n_styles + 1) *
+ sizeof(nsclipboard_styles));
+ if (new_styles == NULL) {
+ return false;
}
- else if (mouse & BROWSER_MOUSE_DRAG_2) {
- /* adjust selection, but only if there is one */
- if (!selection_defined(s))
- return false; /* ignore Adjust drags */
+ sel_string->styles = new_styles;
- if (pos >= 0) {
- selection_set_end(s, idx);
+ sel_string->styles[sel_string->n_styles].style = *style;
+ sel_string->styles[sel_string->n_styles].start =
+ sel_string->length;
- s->drag_state = DRAG_END;
- }
- else {
- selection_set_start(s, idx);
+ sel_string->n_styles++;
+ }
- s->drag_state = DRAG_START;
- }
+ if (new_length > sel_string->buffer_len) {
+ /* Need to extend buffer */
+ size_t new_alloc = new_length + (new_length / 4);
+ char *new_buff;
- guit->window->start_selection(top->window);
+ new_buff = realloc(sel_string->buffer, new_alloc);
+ if (new_buff == NULL) {
+ return false;
}
- else if (mouse & BROWSER_MOUSE_CLICK_2) {
-
- /* ignore Adjust clicks when there's no selection */
- if (!selection_defined(s))
- return false;
- if (pos >= 0)
- selection_set_end(s, idx);
- else
- selection_set_start(s, idx);
- s->drag_state = DRAG_NONE;
- }
- else
- return false;
- }
- else {
- /* not our problem */
- return false;
+ sel_string->buffer = new_buff;
+ sel_string->buffer_len = new_alloc;
}
- /* this mouse click is selection-related */
- return true;
-}
-
-
-/**
- * Handles movements related to the selection, eg. dragging of start and
- * end points.
- *
- * \param s selection object
- * \param mouse state of mouse buttons and modifier keys
- * \param idx byte offset within text representation
- */
+ /* Copy text onto end of existing text in buffer */
+ memcpy(sel_string->buffer + sel_string->length, text, length);
+ sel_string->length += length;
-void selection_track(struct selection *s, browser_mouse_state mouse,
- unsigned idx)
-{
- if (!mouse) {
- s->drag_state = DRAG_NONE;
+ if (space) {
+ sel_string->buffer[sel_string->length++] = ' ';
}
- switch (s->drag_state) {
-
- case DRAG_START:
- if (idx > s->end_idx) {
- unsigned old_end = s->end_idx;
- selection_set_end(s, idx);
- selection_set_start(s, old_end);
- s->drag_state = DRAG_END;
- }
- else
- selection_set_start(s, idx);
- break;
-
- case DRAG_END:
- if (idx < s->start_idx) {
- unsigned old_start = s->start_idx;
- selection_set_start(s, idx);
- selection_set_end(s, old_start);
- s->drag_state = DRAG_START;
- }
- else
- selection_set_end(s, idx);
- break;
+ /* Ensure NULL termination */
+ sel_string->buffer[sel_string->length] = '\0';
- default:
- break;
- }
+ return true;
}
-/**
- * Tests whether a text box lies partially within the given range of
- * byte offsets, returning the start and end indexes of the bytes
- * that are enclosed.
- *
- * \param box box to be tested
- * \param start_idx byte offset of start of range
- * \param end_idx byte offset of end of range
- * \param start_offset receives the start offset of the selected part
- * \param end_offset receives the end offset of the selected part
- * \return true iff the range encloses at least part of the box
- */
-
-bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx,
- unsigned *start_offset, unsigned *end_offset)
+/* exported interface documented in desktop/selection.h */
+struct selection *selection_create(struct content *c)
{
- size_t box_length = box->length + SPACE_LEN(box);
-
- if (box_length > 0) {
- if (box->byte_offset >= start_idx &&
- box->byte_offset + box_length <= end_idx) {
-
- /* fully enclosed */
- *start_offset = 0;
- *end_offset = box_length;
- return true;
- }
- else if (box->byte_offset + box_length > start_idx &&
- box->byte_offset < end_idx) {
- /* partly enclosed */
- int offset = 0;
- int len;
-
- if (box->byte_offset < start_idx)
- offset = start_idx - box->byte_offset;
-
- len = box_length - offset;
-
- if (box->byte_offset + box_length > end_idx)
- len = end_idx - (box->byte_offset + offset);
-
- *start_offset = offset;
- *end_offset = offset + len;
-
- return true;
- }
+ struct selection *sel;
+ sel = calloc(1, sizeof(struct selection));
+ if (sel) {
+ sel->c = c;
+ sel->drag_state = DRAG_NONE;
+ sel->max_idx = 0;
+ selection_clear(sel, false);
}
- return false;
-}
+ return sel;
+}
-/**
- * Traverse the given box subtree, calling the handler function (with its handle)
- * for all boxes that lie (partially) within the given range
- *
- * \param box box subtree
- * \param len_ctx Length conversion context.
- * \param start_idx start of range within textual representation (bytes)
- * \param end_idx end of range
- * \param handler handler function to call
- * \param handle handle to pass
- * \param before type of whitespace to place before next encountered text
- * \param first whether this is the first box with text
- * \param do_marker whether deal enter any marker box
- * \return false iff traversal abandoned part-way through
- */
-bool traverse_tree(
- struct box *box, const nscss_len_ctx *len_ctx,
- unsigned start_idx, unsigned end_idx,
- seln_traverse_handler handler,
- void *handle, save_text_whitespace *before, bool *first,
- bool do_marker)
+/* exported interface documented in desktop/selection.h */
+void selection_destroy(struct selection *s)
{
- struct box *child;
- const char *whitespace_text = "";
- size_t whitespace_length = 0;
-
- assert(box);
-
- /* If selection starts inside marker */
- if (box->parent && box->parent->list_marker == box && !do_marker) {
- /* set box to main list element */
- box = box->parent;
+ if (s == NULL) {
+ return;
}
- /* If box has a list marker */
- if (box->list_marker) {
- /* do the marker box before continuing with the rest of the
- * list element */
- if (!traverse_tree(box->list_marker, len_ctx,
- start_idx, end_idx, handler, handle,
- before, first, true))
- return false;
- }
+ selection_clear(s, true);
+ free(s);
+}
- /* we can prune this subtree, it's after the selection */
- if (box->byte_offset >= end_idx)
- return true;
- /* read before calling the handler in case it modifies the tree */
- child = box->children;
+/* exported interface documented in desktop/selection.h */
+void selection_reinit(struct selection *s)
+{
+ s->max_idx = 0;
- /* If nicely formatted output of the selected text is required, work
- * out what whitespace should be placed before the next bit of text */
- if (before) {
- save_text_solve_whitespace(box, first, before, &whitespace_text,
- &whitespace_length);
- }
- else {
- whitespace_text = NULL;
- }
- if (box->type != BOX_BR &&
- !((box->type == BOX_FLOAT_LEFT ||
- box->type == BOX_FLOAT_RIGHT) &&
- !box->text)) {
- unsigned start_offset;
- unsigned end_offset;
-
- if (selected_part(box, start_idx, end_idx, &start_offset,
- &end_offset)) {
- if (!handler(box->text + start_offset, min(box->length,
- end_offset) - start_offset,
- box, len_ctx, handle, whitespace_text,
- whitespace_length))
- return false;
- if (before) {
- *first = false;
- *before = WHITESPACE_NONE;
- }
- }
+ if (s->c->handler->textselection_get_end != NULL) {
+ s->c->handler->textselection_get_end(s->c, &s->max_idx);
}
- /* find the first child that could lie partially within the selection;
- * this is important at the top-levels of the tree for pruning subtrees
- * that lie entirely before the selection */
-
- if (child) {
- struct box *next = child->next;
-
- while (next && next->byte_offset < start_idx) {
- child = next;
- next = child->next;
+ if (s->defined) {
+ if (s->end_idx > s->max_idx) {
+ s->end_idx = s->max_idx;
}
-
- while (child) {
- /* read before calling the handler in case it modifies
- * the tree */
- struct box *next = child->next;
-
- if (!traverse_tree(child, len_ctx, start_idx, end_idx,
- handler, handle, before, first, false))
- return false;
-
- child = next;
+ if (s->start_idx > s->max_idx) {
+ s->start_idx = s->max_idx;
}
+ s->defined = (s->end_idx > s->start_idx);
}
-
- return true;
}
-/**
- * Traverse the current selection, calling the handler function (with its
- * handle) for all boxes that lie (partially) within the given range
- *
- * \param s The selection context.
- * \param handler handler function to call
- * \param handle handle to pass
- * \return false iff traversal abandoned part-way through
- */
-
-static bool selection_traverse(struct selection *s,
- seln_traverse_handler handler, void *handle)
+/* exported interface documented in desktop/selection.h */
+void selection_init(struct selection *s)
{
- save_text_whitespace before = WHITESPACE_NONE;
- bool first = true;
- const char *text;
- size_t length;
-
- if (!selection_defined(s))
- return true; /* easy case, nothing to do */
-
- if (s->root) {
- /* HTML */
- return traverse_tree(s->root, &s->len_ctx,
- s->start_idx, s->end_idx,
- handler, handle,
- &before, &first, false);
+ if (s->defined) {
+ selection_clear(s, true);
}
- /* Text */
- text = textplain_get_raw_data(s->c, s->start_idx, s->end_idx, &length);
-
- if (text && !handler(text, length, NULL, NULL, handle, NULL, 0))
- return false;
+ s->defined = false;
+ s->start_idx = 0;
+ s->end_idx = 0;
+ s->drag_state = DRAG_NONE;
- return true;
+ selection_reinit(s);
}
-/**
- * Selection traversal handler for redrawing the screen when the selection
- * has been altered.
- *
- * \param text pointer to text string
- * \param length length of text to be appended (bytes)
- * \param box pointer to text box being (partially) added
- * \param handle unused handle, we don't need one
- * \param whitespace_text whitespace to place before text for formatting
- * may be NULL
- * \param whitespace_length length of whitespace_text
- * \return true iff successful and traversal should continue
- */
-
-bool redraw_handler(const char *text, size_t length, struct box *box,
- const nscss_len_ctx *len_ctx, void *handle,
- const char *whitespace_text, size_t whitespace_length)
+/* exported interface documented in desktop/selection.h */
+bool
+selection_click(struct selection *s,
+ struct browser_window *top,
+ browser_mouse_state mouse,
+ unsigned idx)
{
- if (box) {
- struct rdw_info *r = (struct rdw_info*)handle;
- int width, height;
- int x, y;
- plot_font_style_t fstyle;
-
- font_plot_style_from_css(len_ctx, box->style, &fstyle);
-
- /* \todo - it should be possible to reduce the redrawn area by
- * considering the 'text', 'length' and 'space' parameters */
- box_coords(box, &x, &y);
+ browser_mouse_state modkeys;
+ int pos = -1; /* 0 = inside selection, 1 = after it */
- width = box->padding[LEFT] + box->width + box->padding[RIGHT];
- height = box->padding[TOP] + box->height + box->padding[BOTTOM];
+ modkeys = (mouse & (BROWSER_MOUSE_MOD_1 | BROWSER_MOUSE_MOD_2));
- if (box->type == BOX_TEXT && box->space != 0)
- width += box->space;
+ top = browser_window_get_root(top);
- if (r->inited) {
- if (x < r->r.x0) r->r.x0 = x;
- if (y < r->r.y0) r->r.y0 = y;
- if (x + width > r->r.x1) r->r.x1 = x + width;
- if (y + height > r->r.y1) r->r.y1 = y + height;
- }
- else {
- r->inited = true;
- r->r.x0 = x;
- r->r.y0 = y;
- r->r.x1 = x + width;
- r->r.y1 = y + height;
+ if (s->defined) {
+ if (idx > s->start_idx) {
+ if (idx <= s->end_idx) {
+ pos = 0;
+ } else {
+ pos = 1;
+ }
}
}
- return true;
-}
+ if (!pos &&
+ ((mouse & BROWSER_MOUSE_DRAG_1) ||
+ (modkeys && (mouse & BROWSER_MOUSE_DRAG_2)))) {
+ /* drag-saving selection */
+ char *sel = selection_get_copy(s);
+ guit->window->drag_save_selection(top->window, sel);
+ free(sel);
+ } else if (!modkeys) {
+ if (pos && (mouse & BROWSER_MOUSE_PRESS_1)) {
+ /* Clear the selection if mouse is pressed
+ * outside the selection, Otherwise clear on
+ * release (to allow for drags)
+ */
-/**
- * Redraws the given range of text.
- *
- * \param s selection object
- * \param start_idx start offset (bytes) within the textual representation
- * \param end_idx end offset (bytes) within the textual representation
- */
+ selection_clear(s, true);
-void selection_redraw(struct selection *s, unsigned start_idx, unsigned end_idx)
-{
- struct rdw_info rdw;
+ } else if (mouse & BROWSER_MOUSE_DRAG_1) {
+ /* start new selection drag */
- assert(end_idx >= start_idx);
- rdw.inited = false;
+ selection_clear(s, true);
- if (s->root) {
- if (!traverse_tree(s->root, &s->len_ctx, start_idx, end_idx,
- redraw_handler, &rdw,
- NULL, NULL, false))
- return;
- }
- else {
- if (s->is_html == false && end_idx > start_idx) {
- textplain_coords_from_range(s->c, start_idx,
- end_idx, &rdw.r);
- rdw.inited = true;
- }
- }
+ selection_set_start(s, idx);
+ selection_set_end(s, idx);
- if (rdw.inited)
- content__request_redraw(s->c, rdw.r.x0, rdw.r.y0,
- rdw.r.x1 - rdw.r.x0, rdw.r.y1 - rdw.r.y0);
-}
+ s->drag_state = DRAG_END;
+ guit->window->event(top->window,
+ GW_EVENT_START_SELECTION);
-/**
- * Append text to selection string.
- *
- * \param text text to be added
- * \param length length of text in bytes
- * \param space indicates whether a trailing space should be appended
- * \param style The font style to use.
- * \param sel_string string to append to, may be resized
- * \return true iff successful
- */
+ } else if (mouse & BROWSER_MOUSE_DRAG_2) {
-static bool selection_string_append(const char *text, size_t length, bool space,
- plot_font_style_t *style, struct selection_string *sel_string)
-{
- size_t new_length = sel_string->length + length + (space ? 1 : 0) + 1;
+ /* adjust selection, but only if there is one */
+ if (!s->defined) {
+ return false; /* ignore Adjust drags */
+ }
- if (style != NULL) {
- /* Add text run style */
- nsclipboard_styles *new_styles;
+ if (pos >= 0) {
+ selection_set_end(s, idx);
- if (sel_string->n_styles == 0)
- assert(sel_string->length == 0);
+ s->drag_state = DRAG_END;
+ } else {
+ selection_set_start(s, idx);
- new_styles = realloc(sel_string->styles,
- (sel_string->n_styles + 1) *
- sizeof(nsclipboard_styles));
- if (new_styles == NULL)
- return false;
+ s->drag_state = DRAG_START;
+ }
- sel_string->styles = new_styles;
+ guit->window->event(top->window,
+ GW_EVENT_START_SELECTION);
- sel_string->styles[sel_string->n_styles].style = *style;
- sel_string->styles[sel_string->n_styles].start =
- sel_string->length;
+ } else if (mouse & BROWSER_MOUSE_CLICK_2) {
- sel_string->n_styles++;
- }
+ /* ignore Adjust clicks when there's no selection */
+ if (!s->defined) {
+ return false;
+ }
- if (new_length > sel_string->buffer_len) {
- /* Need to extend buffer */
- size_t new_alloc = new_length + (new_length / 4);
- char *new_buff;
+ if (pos >= 0) {
+ selection_set_end(s, idx);
+ } else {
+ selection_set_start(s, idx);
+ }
+ s->drag_state = DRAG_NONE;
- new_buff = realloc(sel_string->buffer, new_alloc);
- if (new_buff == NULL)
+ } else {
return false;
+ }
- sel_string->buffer = new_buff;
- sel_string->buffer_len = new_alloc;
+ } else {
+ /* not our problem */
+ return false;
}
- /* Copy text onto end of existing text in buffer */
- memcpy(sel_string->buffer + sel_string->length, text, length);
- sel_string->length += length;
-
- if (space)
- sel_string->buffer[sel_string->length++] = ' ';
-
- /* Ensure NULL termination */
- sel_string->buffer[sel_string->length] = '\0';
-
+ /* this mouse click is selection-related */
return true;
}
-/**
- * Selection traversal routine for appending text to a string
- *
- * \param text pointer to text being added, or NULL for newline
- * \param length length of text to be appended (bytes)
- * \param box pointer to text box, or NULL if from textplain
- * \param len_ctx Length conversion context
- * \param handle selection string to append to
- * \param whitespace_text whitespace to place before text for formatting
- * may be NULL
- * \param whitespace_length length of whitespace_text
- * \return true iff successful and traversal should continue
- */
-
-static bool selection_copy_handler(const char *text, size_t length,
- struct box *box, const nscss_len_ctx *len_ctx,
- void *handle, const char *whitespace_text,
- size_t whitespace_length)
+/* exported interface documented in desktop/selection.h */
+void
+selection_track(struct selection *s, browser_mouse_state mouse, unsigned idx)
{
- bool add_space = false;
- plot_font_style_t style;
- plot_font_style_t *pstyle = NULL;
-
- /* add any whitespace which precedes the text from this box */
- if (whitespace_text != NULL && whitespace_length > 0) {
- if (!selection_string_append(whitespace_text,
- whitespace_length, false, pstyle, handle)) {
- return false;
- }
+ if (!mouse) {
+ s->drag_state = DRAG_NONE;
}
- if (box != NULL) {
- /* HTML */
- add_space = (box->space != 0);
+ switch (s->drag_state) {
- if (box->style != NULL) {
- /* Override default font style */
- font_plot_style_from_css(len_ctx, box->style, &style);
- pstyle = &style;
+ case DRAG_START:
+ if (idx > s->end_idx) {
+ unsigned old_end = s->end_idx;
+ selection_set_end(s, idx);
+ selection_set_start(s, old_end);
+ s->drag_state = DRAG_END;
} else {
- /* If there's no style, there must be no text */
- assert(box->text == NULL);
+ selection_set_start(s, idx);
}
- }
+ break;
- /* add the text from this box */
- if (!selection_string_append(text, length, add_space, pstyle, handle))
- return false;
+ case DRAG_END:
+ if (idx < s->start_idx) {
+ unsigned old_start = s->start_idx;
+ selection_set_start(s, idx);
+ selection_set_end(s, old_start);
+ s->drag_state = DRAG_START;
+ } else {
+ selection_set_end(s, idx);
+ }
+ break;
- return true;
+ default:
+ break;
+ }
}
-/**
- * Get copy of selection as string
- *
- * \param s selection
- * \return string of selected text, or NULL. Ownership passed to caller.
- */
-
+/* exported interface documented in desktop/selection.h */
char *selection_get_copy(struct selection *s)
{
struct selection_string sel_string = {
@@ -827,7 +468,7 @@ char *selection_get_copy(struct selection *s)
if (s == NULL || !s->defined)
return NULL;
- if (!selection_traverse(s, selection_copy_handler, &sel_string)) {
+ if (!selection_copy(s, &sel_string)) {
free(sel_string.buffer);
free(sel_string.styles);
return NULL;
@@ -839,13 +480,7 @@ char *selection_get_copy(struct selection *s)
}
-
-/**
- * Copy the selected contents to the clipboard
- *
- * \param s selection
- * \return true iff successful
- */
+/* exported interface documented in desktop/selection.h */
bool selection_copy_to_clipboard(struct selection *s)
{
struct selection_string sel_string = {
@@ -857,17 +492,20 @@ bool selection_copy_to_clipboard(struct selection *s)
.styles = NULL
};
- if (s == NULL || !s->defined)
+ if (s == NULL || !s->defined) {
return false;
+ }
- if (!selection_traverse(s, selection_copy_handler, &sel_string)) {
+ if (!selection_copy(s, &sel_string)) {
free(sel_string.buffer);
free(sel_string.styles);
return false;
}
- guit->clipboard->set(sel_string.buffer, sel_string.length,
- sel_string.styles, sel_string.n_styles);
+ guit->clipboard->set(sel_string.buffer,
+ sel_string.length,
+ sel_string.styles,
+ sel_string.n_styles);
free(sel_string.buffer);
free(sel_string.styles);
@@ -876,21 +514,15 @@ bool selection_copy_to_clipboard(struct selection *s)
}
-/**
- * Clears the current selection, optionally causing the screen to be updated.
- *
- * \param s selection object
- * \param redraw true iff the previously selected region of the browser
- * window should be redrawn
- */
-
-void selection_clear(struct selection *s, bool redraw)
+/* exported interface documented in desktop/selection.h */
+bool selection_clear(struct selection *s, bool redraw)
{
int old_start, old_end;
bool was_defined;
assert(s);
- was_defined = selection_defined(s);
+
+ was_defined = s->defined;
old_start = s->start_idx;
old_end = s->end_idx;
@@ -898,106 +530,75 @@ void selection_clear(struct selection *s, bool redraw)
s->start_idx = 0;
s->end_idx = 0;
- if (redraw && was_defined)
+ if (redraw && was_defined) {
selection_redraw(s, old_start, old_end);
-}
+ }
+ return was_defined;
+}
-/**
- * Selects all the text within the box subtree controlled by
- * this selection object, updating the screen accordingly.
- *
- * \param s selection object
- */
+/* exported interface documented in desktop/selection.h */
void selection_select_all(struct selection *s)
{
assert(s);
s->defined = true;
-
+
selection_set_start(s, 0);
selection_set_end(s, s->max_idx);
}
-/**
- * Set the start position of the current selection, updating the screen.
- *
- * \param s selection object
- * \param offset byte offset within textual representation
- */
-
-void selection_set_start(struct selection *s, unsigned offset)
+/* exported interface documented in desktop/selection.h */
+void selection_set_position(struct selection *s, unsigned start, unsigned end)
{
- bool was_defined = selection_defined(s);
- unsigned old_start = s->start_idx;
-
- s->start_idx = offset;
- s->defined = (s->start_idx < s->end_idx);
-
- if (was_defined) {
- if (offset < old_start)
- selection_redraw(s, s->start_idx, old_start);
- else
- selection_redraw(s, old_start, s->start_idx);
- }
- else if (selection_defined(s))
- selection_redraw(s, s->start_idx, s->end_idx);
+ selection_set_start(s, start);
+ selection_set_end(s, end);
}
-/**
- * Set the end position of the current selection, updating the screen.
- *
- * \param s selection object
- * \param offset byte offset within textual representation
- */
-
-void selection_set_end(struct selection *s, unsigned offset)
+/* exported interface documented in desktop/selection.h */
+bool
+selection_highlighted(const struct selection *s,
+ unsigned start,
+ unsigned end,
+ unsigned *start_idx,
+ unsigned *end_idx)
{
- bool was_defined = selection_defined(s);
- unsigned old_end = s->end_idx;
+ assert(s);
- s->end_idx = offset;
- s->defined = (s->start_idx < s->end_idx);
+ if (!s->defined) {
+ return false;
+ }
- if (was_defined) {
- if (offset < old_end)
- selection_redraw(s, s->end_idx, old_end);
- else
- selection_redraw(s, old_end, s->end_idx);
+ if ((end <= s->start_idx) ||
+ (start >= s->end_idx)) {
+ return false;
}
- else if (selection_defined(s))
- selection_redraw(s, s->start_idx, s->end_idx);
-}
+ *start_idx = (s->start_idx >= start) ? (s->start_idx - start) : 0;
+ *end_idx = min(end, s->end_idx) - start;
-/**
- * Tests whether a text range lies partially within the selection, if there is
- * a selection defined, returning the start and end indexes of the bytes
- * that should be selected.
- *
- * \param s the selection object
- * \param start byte offset of start of text
- * \param end byte offset of end of text
- * \param start_idx receives the start index (in bytes) of the highlighted portion
- * \param end_idx receives the end index (in bytes)
- * \return true iff part of the given box lies within the selection
- */
+ return true;
+}
-bool selection_highlighted(const struct selection *s,
- unsigned start, unsigned end,
- unsigned *start_idx, unsigned *end_idx)
+/* exported interface documented in desktop/selection.h */
+bool selection_active(struct selection *s)
{
- /* caller should have checked first for efficiency */
- assert(s);
- assert(selection_defined(s));
+ return s->defined;
+}
- if (end <= s->start_idx || start >= s->end_idx)
- return false;
+bool selection_dragging(struct selection *s)
+{
+ return s->drag_state != DRAG_NONE;
+}
- *start_idx = (s->start_idx >= start) ? (s->start_idx - start) : 0;
- *end_idx = min(end, s->end_idx) - start;
+bool selection_dragging_start(struct selection *s)
+{
+ return s->drag_state == DRAG_START;
+}
- return true;
+void selection_drag_end(struct selection *s)
+{
+ s->drag_state = DRAG_NONE;
}
diff --git a/desktop/selection.h b/desktop/selection.h
index 2f3f6dcfe..8cd523fd8 100644
--- a/desktop/selection.h
+++ b/desktop/selection.h
@@ -20,86 +20,172 @@
* Text selection within browser windows (interface).
*/
-#ifndef _NETSURF_DESKTOP_SELECTION_H_
-#define _NETSURF_DESKTOP_SELECTION_H_
+#ifndef NETSURF_DESKTOP_SELECTION_H_
+#define NETSURF_DESKTOP_SELECTION_H_
#include <stdbool.h>
#include "netsurf/mouse.h"
-#include "content/handlers/css/utils.h"
struct box;
+struct browser_window;
+struct plot_font_style;
+struct selection_string;
+struct selection;
+struct content;
+
+/**
+ * determine if a selecion is active
+ */
+bool selection_active(struct selection *s);
-typedef enum {
- DRAG_NONE,
- DRAG_START,
- DRAG_END
-} seln_drag_state;
-
-
-/* this structure should be treated as opaque outside selection.c
- (it's defined here to accelerate selection_defined(s) for reduced
- impact on redraw code) */
-
-struct selection
-{
- struct content *c;
- struct box *root;
- nscss_len_ctx len_ctx;
-
- unsigned max_idx; /* total bytes in text representation */
-
- unsigned start_idx; /* offset in bytes within text representation */
- unsigned end_idx;
+bool selection_dragging(struct selection *s);
- bool defined;
- bool is_html;
+bool selection_dragging_start(struct selection *s);
- seln_drag_state drag_state;
-};
+/**
+ * Handles completion of a drag operation
+ */
+void selection_drag_end(struct selection *s);
+/**
+ * Creates a new selection object associated with a browser window.
+ *
+ * Used from text and html content handlers
+ *
+ * \return new selection context
+ */
+struct selection *selection_create(struct content *c);
-struct selection *selection_create(struct content *c, bool is_html);
-void selection_prepare(struct selection *s, struct content *c, bool is_html);
+/**
+ * Destroys a selection object clearing it if nesessary
+ *
+ * Used from content textsearch
+ *
+ * \param s selection object
+ */
void selection_destroy(struct selection *s);
-void selection_init(
- struct selection *s,
- struct box *root,
- const nscss_len_ctx *len_ctx);
-void selection_reinit(struct selection *s, struct box *root);
-
-/* struct box *selection_root(struct selection *s); */
-#define selection_root(s) ((s)->root)
-
-/* bool selection_defined(struct selection *s); */
-#define selection_defined(s) ((s)->defined)
+/**
+ * Initialise the selection object to use the given box subtree as its root,
+ * ie. selections are confined to that subtree.
+ *
+ * Used from text and html content handlers
+ *
+ * \param s selection object
+ */
+void selection_init(struct selection *s);
-/* bool selection_dragging(struct selection *s); */
-#define selection_dragging(s) ((s)->drag_state != DRAG_NONE)
+/**
+ * Initialise the selection object to use the given box subtree as its root,
+ * ie. selections are confined to that subtree, whilst maintaining the current
+ * selection whenever possible because, for example, it's just the page being
+ * resized causing the layout to change.
+ *
+ * Used from html content handler
+ *
+ * \param s selection object
+ */
+void selection_reinit(struct selection *s);
-/* bool selection_dragging_start(struct selection *s); */
-#define selection_dragging_start(s) ((s)->drag_state == DRAG_START)
+/**
+ * Clears the current selection, optionally causing the screen to be updated.
+ *
+ * Used from text and html content handlers
+ *
+ * \param s selection object
+ * \param redraw true iff the previously selected region of the browser
+ * window should be redrawn
+ * \return true if selection was cleared false if not
+ */
+bool selection_clear(struct selection *s, bool redraw);
-void selection_clear(struct selection *s, bool redraw);
+/**
+ * Selects all the text within the box subtree controlled by
+ * this selection object, updating the screen accordingly.
+ *
+ * Used from text and html content handlers
+ *
+ * \param s selection object
+ */
void selection_select_all(struct selection *s);
-void selection_set_start(struct selection *s, unsigned idx);
-void selection_set_end(struct selection *s, unsigned idx);
+/**
+ * Set the position of the current selection, updating the screen.
+ *
+ * Used from content textsearch
+ *
+ * \param s selection object
+ * \param start byte offset within textual representation
+ * \param end byte offset within textual representation
+ */
+void selection_set_position(struct selection *s, unsigned start, unsigned end);
-bool selection_click(struct selection *s, browser_mouse_state mouse,
- unsigned idx);
-void selection_track(struct selection *s, browser_mouse_state mouse,
- unsigned idx);
+/**
+ * Handles mouse clicks (including drag starts) in or near a selection
+ *
+ * Used from text and html content handlers
+ *
+ * \param s selection object
+ * \param mouse state of mouse buttons and modifier keys
+ * \param idx byte offset within textual representation
+ * \return true iff the click has been handled by the selection code
+ */
+bool selection_click(struct selection *s, struct browser_window *top, browser_mouse_state mouse, unsigned idx);
+/**
+ * Handles movements related to the selection, eg. dragging of start and
+ * end points.
+ *
+ * Used from text and html content handlers
+ *
+ * \param s selection object
+ * \param mouse state of mouse buttons and modifier keys
+ * \param idx byte offset within text representation
+ */
+void selection_track(struct selection *s, browser_mouse_state mouse, unsigned idx);
+
+/**
+ * Copy the selected contents to the clipboard
+ *
+ * Used from text and html content handlers
+ *
+ * \param s selection
+ * \return true iff successful
+ */
bool selection_copy_to_clipboard(struct selection *s);
-char * selection_get_copy(struct selection *s);
-/** Handles completion of a drag operation */
-/* void selection_drag_end(struct selection *s); */
-#define selection_drag_end(s) ((s)->drag_state = DRAG_NONE)
+/**
+ * Get copy of selection as string
+ *
+ * Used from text and html content handlers
+ *
+ * \param s selection
+ * \return string of selected text, or NULL. Ownership passed to caller.
+ */
+char *selection_get_copy(struct selection *s);
+
-bool selection_highlighted(const struct selection *s,
- unsigned start, unsigned end,
- unsigned *start_idx, unsigned *end_idx);
+/**
+ * Tests whether a text range lies partially within the selection, if there is
+ * a selection defined, returning the start and end indexes of the bytes
+ * that should be selected.
+ *
+ * Used from text and html content handlers, content textsearch
+ *
+ * \param s the selection object
+ * \param start byte offset of start of text
+ * \param end byte offset of end of text
+ * \param start_idx receives the start index (in bytes) of the highlighted portion
+ * \param end_idx receives the end index (in bytes)
+ * \return true iff part of the given box lies within the selection
+ */
+bool selection_highlighted(const struct selection *s, unsigned start, unsigned end, unsigned *start_idx, unsigned *end_idx);
+
+bool
+selection_string_append(const char *text,
+ size_t length,
+ bool space,
+ struct plot_font_style *style,
+ struct selection_string *sel_string);
#endif
diff --git a/desktop/sslcert_viewer.c b/desktop/sslcert_viewer.c
deleted file mode 100644
index f40af5968..000000000
--- a/desktop/sslcert_viewer.c
+++ /dev/null
@@ -1,572 +0,0 @@
-/*
- * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
- * Copyright 2013 Michael Drake <tlsa@netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- * SSL Certificate verification UI implementation
- */
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "content/fetch.h"
-#include "content/urldb.h"
-#include "content/hlcache.h"
-#include "desktop/sslcert_viewer.h"
-#include "desktop/treeview.h"
-#include "utils/messages.h"
-#include "utils/log.h"
-#include "utils/utils.h"
-
-/**
- * ssl certificate viewer data fields
- */
-enum sslcert_viewer_field {
- SSLCERT_V_SUBJECT,
- SSLCERT_V_SERIAL,
- SSLCERT_V_TYPE,
- SSLCERT_V_VALID_UNTIL,
- SSLCERT_V_VALID_FROM,
- SSLCERT_V_VERSION,
- SSLCERT_V_ISSUER,
- SSLCERT_V_CERTIFICATES,
- SSLCERT_V_N_FIELDS
-};
-
-
-/**
- * ssl certificate verification context.
- */
-struct sslcert_session_data {
- struct ssl_cert_info *certs; /**< Certificates */
- unsigned long num; /**< Number of certificates in chain */
- nsurl *url; /**< The url of the certificate */
- llcache_query_response cb; /**< Cert accept/reject callback */
- void *cbpw; /**< Context passed to callback */
-
- treeview *tree; /**< The treeview object */
- struct treeview_field_desc fields[SSLCERT_V_N_FIELDS];
-};
-
-
-/**
- * ssl certificate tree entry
- */
-struct sslcert_entry {
- treeview_node *entry;
- char version[24];
- char serial[24];
- char type[24];
- struct treeview_field_data data[SSLCERT_V_N_FIELDS - 1];
-};
-
-
-/**
- * Free a ssl certificate viewer entry's treeview field data.
- *
- * \param e Entry to free data from
- */
-static void sslcert_viewer_free_treeview_field_data(struct sslcert_entry *e)
-{
-}
-
-
-/**
- * Build a sslcert viewer treeview field from given text
- *
- * \param field SSL certificate treeview field to build
- * \param data SSL certificate entry field data to set
- * \param value Text to set in field, ownership yielded
- * \param ssl_d SSL certificate session data
- * \return NSERROR_OK on success, appropriate error otherwise
- */
-static inline nserror
-sslcert_viewer_field_builder(enum sslcert_viewer_field field,
- struct treeview_field_data *data,
- const char *value,
- struct sslcert_session_data *ssl_d)
-{
- data->field = ssl_d->fields[field].field;
- data->value = value;
- data->value_len = (value != NULL) ? strlen(value) : 0;
-
- return NSERROR_OK;
-}
-
-
-/**
- * Set a sslcert viewer entry's data from the certificate.
- *
- * \param e Entry to set up
- * \param cert Data associated with entry's certificate
- * \param ssl_d SSL certificate session data
- * \return NSERROR_OK on success, appropriate error otherwise
- */
-static nserror
-sslcert_viewer_set_treeview_field_data(struct sslcert_entry *e,
- const struct ssl_cert_info *cert,
- struct sslcert_session_data *ssl_d)
-{
- unsigned int written;
-
- assert(e != NULL);
- assert(cert != NULL);
- assert(ssl_d != NULL);
-
- /* Set the fields up */
- sslcert_viewer_field_builder(SSLCERT_V_SUBJECT,
- &e->data[SSLCERT_V_SUBJECT],
- cert->subject, ssl_d);
-
- written = snprintf(e->serial, sizeof(e->serial), "%li", cert->serial);
- assert(written < sizeof(e->serial));
- sslcert_viewer_field_builder(SSLCERT_V_SERIAL,
- &e->data[SSLCERT_V_SERIAL],
- e->serial, ssl_d);
-
- written = snprintf(e->type, sizeof(e->type), "%i", cert->cert_type);
- assert(written < sizeof(e->type));
- sslcert_viewer_field_builder(SSLCERT_V_TYPE,
- &e->data[SSLCERT_V_TYPE],
- e->type, ssl_d);
-
- sslcert_viewer_field_builder(SSLCERT_V_VALID_UNTIL,
- &e->data[SSLCERT_V_VALID_UNTIL],
- cert->not_after, ssl_d);
-
- sslcert_viewer_field_builder(SSLCERT_V_VALID_FROM,
- &e->data[SSLCERT_V_VALID_FROM],
- cert->not_before, ssl_d);
-
- written = snprintf(e->version, sizeof(e->version),
- "%li", cert->version);
- assert(written < sizeof(e->version));
- sslcert_viewer_field_builder(SSLCERT_V_VERSION,
- &e->data[SSLCERT_V_VERSION],
- e->version, ssl_d);
-
- sslcert_viewer_field_builder(SSLCERT_V_ISSUER,
- &e->data[SSLCERT_V_ISSUER],
- cert->issuer, ssl_d);
-
- return NSERROR_OK;
-}
-
-
-/**
- * Create a treeview node for a certificate
- *
- * \param ssl_d SSL certificate session data
- * \param n Number of SSL certificate in chain, to make node for
- * \return NSERROR_OK on success otherwise error code.
- */
-static nserror
-sslcert_viewer_create_node(struct sslcert_session_data *ssl_d, int n)
-{
- struct sslcert_entry *e;
- const struct ssl_cert_info *cert = &(ssl_d->certs[n]);
- nserror err;
-
- /* Create new certificate viewer entry */
- e = malloc(sizeof(struct sslcert_entry));
- if (e == NULL) {
- return NSERROR_NOMEM;
- }
-
- err = sslcert_viewer_set_treeview_field_data(e, cert, ssl_d);
- if (err != NSERROR_OK) {
- free(e);
- return err;
- }
-
- /* Create the new treeview node */
- err = treeview_create_node_entry(ssl_d->tree, &(e->entry),
- NULL, TREE_REL_FIRST_CHILD,
- e->data, e, TREE_OPTION_NONE);
- if (err != NSERROR_OK) {
- sslcert_viewer_free_treeview_field_data(e);
- free(e);
- return err;
- }
-
- return NSERROR_OK;
-}
-
-
-/**
- * Initialise the treeview entry fields
- *
- * \param ssl_d SSL certificate session data
- * \return NSERROR_OK on success otherwise error code.
- */
-static nserror sslcert_init_entry_fields(struct sslcert_session_data *ssl_d)
-{
- int i;
- const char *label;
-
- for (i = 0; i < SSLCERT_V_N_FIELDS; i++)
- ssl_d->fields[i].field = NULL;
-
- ssl_d->fields[SSLCERT_V_SUBJECT].flags = TREE_FLAG_DEFAULT;
- label = "TreeviewLabelSubject";
- label = messages_get(label);
- if (lwc_intern_string(label, strlen(label),
- &ssl_d->fields[SSLCERT_V_SUBJECT].field) !=
- lwc_error_ok) {
- goto error;
- }
-
- ssl_d->fields[SSLCERT_V_SERIAL].flags = TREE_FLAG_SHOW_NAME;
- label = "TreeviewLabelSerial";
- label = messages_get(label);
- if (lwc_intern_string(label, strlen(label),
- &ssl_d->fields[SSLCERT_V_SERIAL].field) !=
- lwc_error_ok) {
- goto error;
- }
-
- ssl_d->fields[SSLCERT_V_TYPE].flags = TREE_FLAG_SHOW_NAME;
- label = "TreeviewLabelType";
- label = messages_get(label);
- if (lwc_intern_string(label, strlen(label),
- &ssl_d->fields[SSLCERT_V_TYPE].field) !=
- lwc_error_ok) {
- goto error;
- }
-
- ssl_d->fields[SSLCERT_V_VALID_UNTIL].flags = TREE_FLAG_SHOW_NAME;
- label = "TreeviewLabelValidUntil";
- label = messages_get(label);
- if (lwc_intern_string(label, strlen(label),
- &ssl_d->fields[SSLCERT_V_VALID_UNTIL].field) !=
- lwc_error_ok) {
- goto error;
- }
-
- ssl_d->fields[SSLCERT_V_VALID_FROM].flags = TREE_FLAG_SHOW_NAME;
- label = "TreeviewLabelValidFrom";
- label = messages_get(label);
- if (lwc_intern_string(label, strlen(label),
- &ssl_d->fields[SSLCERT_V_VALID_FROM].field) !=
- lwc_error_ok) {
- goto error;
- }
-
- ssl_d->fields[SSLCERT_V_VERSION].flags = TREE_FLAG_SHOW_NAME;
- label = "TreeviewLabelVersion";
- label = messages_get(label);
- if (lwc_intern_string(label, strlen(label),
- &ssl_d->fields[SSLCERT_V_VERSION].field) !=
- lwc_error_ok) {
- goto error;
- }
-
- ssl_d->fields[SSLCERT_V_ISSUER].flags = TREE_FLAG_SHOW_NAME;
- label = "TreeviewLabelIssuer";
- label = messages_get(label);
- if (lwc_intern_string(label, strlen(label),
- &ssl_d->fields[SSLCERT_V_ISSUER].field) !=
- lwc_error_ok) {
- goto error;
- }
-
- ssl_d->fields[SSLCERT_V_CERTIFICATES].flags = TREE_FLAG_DEFAULT;
- label = "TreeviewLabelCertificates";
- label = messages_get(label);
- if (lwc_intern_string(label, strlen(label),
- &ssl_d->fields[SSLCERT_V_CERTIFICATES].field) !=
- lwc_error_ok) {
- return false;
- }
-
- return NSERROR_OK;
-
-error:
- for (i = 0; i < SSLCERT_V_N_FIELDS; i++)
- if (ssl_d->fields[i].field != NULL)
- lwc_string_unref(ssl_d->fields[i].field);
-
- return NSERROR_UNKNOWN;
-}
-
-
-/**
- * Delete ssl certificate viewer entries
- *
- * \param e Entry to delete.
- */
-static void sslcert_viewer_delete_entry(struct sslcert_entry *e)
-{
- sslcert_viewer_free_treeview_field_data(e);
- free(e);
-}
-
-
-/**
- * folder operation callback
- *
- * \param msg treeview message
- * \param data message context
- * \return NSERROR_OK on success
- */
-static nserror
-sslcert_viewer_tree_node_folder_cb(struct treeview_node_msg msg, void *data)
-{
- switch (msg.msg) {
- case TREE_MSG_NODE_DELETE:
- case TREE_MSG_NODE_EDIT:
- case TREE_MSG_NODE_LAUNCH:
- break;
- }
-
- return NSERROR_OK;
-}
-
-
-/**
- * node entry callback
- *
- * \param msg treeview message
- * \param data message context
- * \return NSERROR_OK on success
- */
-static nserror
-sslcert_viewer_tree_node_entry_cb(struct treeview_node_msg msg, void *data)
-{
- struct sslcert_entry *e = data;
-
- switch (msg.msg) {
- case TREE_MSG_NODE_DELETE:
- e->entry = NULL;
- sslcert_viewer_delete_entry(e);
- break;
-
- case TREE_MSG_NODE_EDIT:
- case TREE_MSG_NODE_LAUNCH:
- break;
- }
-
- return NSERROR_OK;
-}
-
-
-/**
- * ssl certificate treeview callbacks
- */
-struct treeview_callback_table sslv_tree_cb_t = {
- .folder = sslcert_viewer_tree_node_folder_cb,
- .entry = sslcert_viewer_tree_node_entry_cb
-};
-
-
-/* Exported interface, documented in sslcert_viewer.h */
-nserror
-sslcert_viewer_init(struct core_window_callback_table *cw_t,
- void *core_window_handle,
- struct sslcert_session_data *ssl_d)
-{
- nserror err;
- int cert_loop;
-
- assert(ssl_d != NULL);
-
- err = treeview_init();
- if (err != NSERROR_OK) {
- return err;
- }
-
- NSLOG(netsurf, INFO, "Building certificate viewer");
-
- /* Init. certificate chain treeview entry fields */
- err = sslcert_init_entry_fields(ssl_d);
- if (err != NSERROR_OK) {
- ssl_d->tree = NULL;
- return err;
- }
-
- /* Create the certificate treeview */
- err = treeview_create(&ssl_d->tree, &sslv_tree_cb_t,
- SSLCERT_V_N_FIELDS, ssl_d->fields,
- cw_t, core_window_handle, TREEVIEW_READ_ONLY);
- if (err != NSERROR_OK) {
- ssl_d->tree = NULL;
- return err;
- }
-
- /* Build treeview nodes from certificate chain */
- for (cert_loop = ssl_d->num - 1; cert_loop >= 0; cert_loop--) {
- err = sslcert_viewer_create_node(ssl_d, cert_loop);
- if (err != NSERROR_OK) {
- return err;
- }
- }
-
- NSLOG(netsurf, INFO, "Built certificate viewer");
-
- return NSERROR_OK;
-}
-
-
-/**
- * Free SSL certificate session data
- *
- * \param ssl_d SSL certificate session data
- */
-static void sslcert_cleanup_session(struct sslcert_session_data *ssl_d)
-{
- assert(ssl_d != NULL);
-
- if (ssl_d->url) {
- nsurl_unref(ssl_d->url);
- ssl_d->url = NULL;
- }
-
- if (ssl_d->certs) {
- free(ssl_d->certs);
- ssl_d->certs = NULL;
- }
-
- free(ssl_d);
-}
-
-
-/* Exported interface, documented in sslcert_viewer.h */
-nserror sslcert_viewer_fini(struct sslcert_session_data *ssl_d)
-{
- int i;
- nserror err;
-
- NSLOG(netsurf, INFO, "Finalising ssl certificate viewer");
-
- /* Destroy the treeview */
- err = treeview_destroy(ssl_d->tree);
-
- /* Free treeview entry fields */
- for (i = 0; i < SSLCERT_V_N_FIELDS; i++)
- if (ssl_d->fields[i].field != NULL)
- lwc_string_unref(ssl_d->fields[i].field);
-
- /* Destroy the sslcert_session_data */
- sslcert_cleanup_session(ssl_d);
-
- err = treeview_fini();
- if (err != NSERROR_OK) {
- return err;
- }
-
- NSLOG(netsurf, INFO, "Finalised ssl certificate viewer");
-
- return err;
-}
-
-
-/* Exported interface, documented in sslcert_viewer.h */
-nserror
-sslcert_viewer_create_session_data(unsigned long num,
- nsurl *url,
- llcache_query_response cb,
- void *cbpw,
- const struct ssl_cert_info *certs,
- struct sslcert_session_data **ssl_d)
-{
- struct sslcert_session_data *data;
-
- assert(url != NULL);
- assert(certs != NULL);
-
- data = malloc(sizeof(struct sslcert_session_data));
- if (data == NULL) {
- *ssl_d = NULL;
- return NSERROR_NOMEM;
- }
-
- /* copy certificate data */
- data->certs = malloc(num * sizeof(struct ssl_cert_info));
- if (data->certs == NULL) {
- free(data);
- *ssl_d = NULL;
- return NSERROR_NOMEM;
- }
- memcpy(data->certs, certs, num * sizeof(struct ssl_cert_info));
-
- data->url = nsurl_ref(url);
- data->num = num;
- data->cb = cb;
- data->cbpw = cbpw;
-
- data->tree = NULL;
-
- *ssl_d = data;
- return NSERROR_OK;
-}
-
-
-/* Exported interface, documented in sslcert_viewer.h */
-nserror sslcert_viewer_reject(struct sslcert_session_data *ssl_d)
-{
- assert(ssl_d != NULL);
-
- ssl_d->cb(false, ssl_d->cbpw);
-
- return NSERROR_OK;
-}
-
-
-/* Exported interface, documented in sslcert_viewer.h */
-nserror sslcert_viewer_accept(struct sslcert_session_data *ssl_d)
-{
- assert(ssl_d != NULL);
-
- urldb_set_cert_permissions(ssl_d->url, true);
-
- ssl_d->cb(true, ssl_d->cbpw);
-
- return NSERROR_OK;
-}
-
-
-/* Exported interface, documented in sslcert_viewer.h */
-void
-sslcert_viewer_redraw(struct sslcert_session_data *ssl_d,
- int x, int y,
- struct rect *clip,
- const struct redraw_context *ctx)
-{
- assert(ssl_d != NULL &&
- "sslcert_viewer_redraw() given bad session data");
-
- treeview_redraw(ssl_d->tree, x, y, clip, ctx);
-}
-
-
-/* Exported interface, documented in sslcert_viewer.h */
-void
-sslcert_viewer_mouse_action(struct sslcert_session_data *ssl_d,
- browser_mouse_state mouse,
- int x, int y)
-{
- treeview_mouse_action(ssl_d->tree, mouse, x, y);
-}
-
-
-/* Exported interface, documented in sslcert_viewer.h */
-bool sslcert_viewer_keypress(struct sslcert_session_data *ssl_d, uint32_t key)
-{
- return treeview_keypress(ssl_d->tree, key);
-}
diff --git a/desktop/sslcert_viewer.h b/desktop/sslcert_viewer.h
deleted file mode 100644
index 9a57b965c..000000000
--- a/desktop/sslcert_viewer.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
- * Copyright 2013 Michael Drake <tlsa@netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- * SSL Certificate verification UI interface
- */
-
-#ifndef NETSURF_DESKTOP_SSLCERT_VIEWER_H
-#define NETSURF_DESKTOP_SSLCERT_VIEWER_H
-
-#include "content/llcache.h"
-#include "netsurf/mouse.h"
-
-struct sslcert_session_data;
-struct redraw_context;
-struct core_window_callback_table;
-struct rect;
-
-/**
- * Create ssl certificate viewer session data.
- *
- * \param num The number of certificates in the chain
- * \param url Address of the page we're inspecting certificates of
- * \param cb Low level cache callback
- * \param cbpw Low level cache private data
- * \param certs The SSL certificates
- * \param ssl_d Updated to SSL certificate session data
- * \return NSERROR_OK on success, appropriate error otherwise
- *
- * Pass the session data to sslcert_viewer_init.
- * sslcert_viewer_fini destroys the session data.
- */
-nserror sslcert_viewer_create_session_data(
- unsigned long num, nsurl *url, llcache_query_response cb,
- void *cbpw, const struct ssl_cert_info *certs,
- struct sslcert_session_data **ssl_d);
-
-
-/**
- * Initialise a ssl certificate viewer from session data.
- *
- * This iterates through the certificates, building a treeview.
- *
- * \param cw_t Callback table for cert viewer's core_window
- * \param core_window_handle The core_window in which the cert viewer is shown
- * \param ssl_d SSL certificate session data
- * \return NSERROR_OK on success, appropriate error otherwise
- */
-nserror sslcert_viewer_init(struct core_window_callback_table *cw_t,
- void *core_window_handle, struct sslcert_session_data *ssl_d);
-
-
-/**
- * Finalise a ssl certificate viewer.
- *
- * This destroys the certificate treeview and the certificate viewer module's
- * session data.
- *
- * \param ssl_d SSL certificate session data
- * \return NSERROR_OK on success, appropriate error otherwise
- */
-nserror sslcert_viewer_fini(struct sslcert_session_data *ssl_d);
-
-
-/**
- * Reject a certificate chain.
- *
- * \param ssl_d SSL certificate session data
- * \return NSERROR_OK on success, appropriate error otherwise
- */
-nserror sslcert_viewer_reject(struct sslcert_session_data *ssl_d);
-
-
-/**
- * Accept a certificate chain.
- *
- * \param ssl_d SSL certificate session data
- * \return NSERROR_OK on success, appropriate error otherwise
- */
-nserror sslcert_viewer_accept(struct sslcert_session_data *ssl_d);
-
-
-/**
- * Redraw the ssl certificate viewer.
- *
- * \param ssl_d SSL certificate session data
- * \param x X coordinate to render treeview at
- * \param y Y coordinate to render treeview at
- * \param clip Current clip rectangle (wrt tree origin)
- * \param ctx Current redraw context
- */
-void sslcert_viewer_redraw(struct sslcert_session_data *ssl_d,
- int x, int y, struct rect *clip,
- const struct redraw_context *ctx);
-
-
-/**
- * Handles all kinds of mouse action
- *
- * \param ssl_d SSL certificate session data
- * \param mouse The current mouse state
- * \param x X coordinate
- * \param y Y coordinate
- */
-void sslcert_viewer_mouse_action(struct sslcert_session_data *ssl_d,
- browser_mouse_state mouse, int x, int y);
-
-
-/**
- * Key press handling.
- *
- * \param ssl_d SSL certificate session data
- * \param key The ucs4 character codepoint
- * \return true if the keypress is dealt with, false otherwise.
- */
-bool sslcert_viewer_keypress(struct sslcert_session_data *ssl_d, uint32_t key);
-
-#endif
diff --git a/desktop/textarea.c b/desktop/textarea.c
index 3fd4c9804..e0e87444c 100644
--- a/desktop/textarea.c
+++ b/desktop/textarea.c
@@ -45,9 +45,9 @@
#define TA_ALLOC_STEP 512
static plot_style_t pstyle_stroke_caret = {
- .stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_colour = CARET_COLOR,
- .stroke_width = 1,
+ .stroke_type = PLOT_OP_TYPE_SOLID,
+ .stroke_colour = CARET_COLOR,
+ .stroke_width = plot_style_int_to_fixed(1),
};
struct line_info {
@@ -58,7 +58,7 @@ struct line_info {
struct textarea_drag {
textarea_drag_type type;
union {
- struct scrollbar* scrollbar;
+ struct scrollbar *scrollbar;
} data;
};
@@ -625,7 +625,7 @@ static bool textarea_select(struct textarea *ta, int b_start, int b_end,
* \param ta Text area
* \return True on success, false otherwise
*/
-static bool textarea_select_fragment(struct textarea * ta)
+static bool textarea_select_fragment(struct textarea *ta)
{
int caret_pos;
size_t sel_start, sel_end;
@@ -676,7 +676,7 @@ static bool textarea_select_fragment(struct textarea * ta)
* \param ta textarea widget
* \return True on success, false otherwise
*/
-static bool textarea_select_paragraph(struct textarea * ta)
+static bool textarea_select_paragraph(struct textarea *ta)
{
int caret_pos;
size_t sel_start, sel_end;
@@ -1607,7 +1607,7 @@ static bool textarea_copy_to_undo_buffer(struct textarea *ta,
* \param b_end End byte index of replaced section (exclusive)
* \param rep Replacement UTF-8 text to insert
* \param rep_len Byte length of replacement UTF-8 text
- * \param add_to_clipboard True iff replaced text to be added to clipboard
+ * \param add_to_clipboard True if replaced text to be added to clipboard
* \param byte_delta Updated to change in byte count in textarea (ta->show)
* \param r Updated to area where redraw is required
* \return false on memory exhaustion, true otherwise
@@ -1805,7 +1805,7 @@ static void textarea_setup_text_offsets(struct textarea *ta)
ta->line_height = FIXTOINT(FMUL(FLTTOFIX(1.3), FDIV(FMUL(
nscss_screen_dpi, FDIV(INTTOFIX(ta->fstyle.size),
- INTTOFIX(FONT_SIZE_SCALE))), F_72)));
+ INTTOFIX(PLOT_STYLE_SCALE))), F_72)));
text_y_offset = text_y_offset_baseline = ta->border_width;
if (ta->flags & TEXTAREA_MULTILINE) {
@@ -1948,7 +1948,7 @@ struct textarea *textarea_create(const textarea_flags flags,
ret->line_height = FIXTOINT(FMUL(FLTTOFIX(1.3), FDIV(FMUL(
nscss_screen_dpi, FDIV(INTTOFIX(setup->text.size),
- INTTOFIX(FONT_SIZE_SCALE))), F_72)));
+ INTTOFIX(PLOT_STYLE_SCALE))), F_72)));
ret->caret_pos.line = ret->caret_pos.byte_off = -1;
ret->caret_x = 0;
@@ -2452,7 +2452,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
struct textarea_msg msg;
struct rect r; /**< Redraw rectangle */
char utf8[6];
- unsigned int caret, length, b_off, b_len;
+ unsigned int caret, caret_copy, length, b_off, b_len;
int h_extent = ta->h_extent;
int v_extent = ta->v_extent;
int line;
@@ -2466,7 +2466,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
/* Word separators */
static const char *sep = " .\n";
- caret = textarea_get_caret(ta);
+ caret = caret_copy = textarea_get_caret(ta);
line = ta->caret_pos.line;
readonly = (ta->flags & TEXTAREA_READONLY ? true : false);
@@ -2743,6 +2743,9 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
case NS_KEY_WORD_LEFT:
if (readonly)
break;
+ if (ta->sel_start != -1) {
+ textarea_clear_selection(ta);
+ }
if (caret == 0)
break;
caret--;
@@ -2756,13 +2759,59 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
break;
}
}
+ break;
+ case NS_KEY_DELETE_WORD_LEFT:
+ if (readonly)
+ break;
+
+ /* If there is a selection, remove the selected
+ * characters */
if (ta->sel_start != -1) {
+ if (!textarea_replace_text(ta, ta->sel_start,
+ ta->sel_end, "", 0, false,
+ &byte_delta, &r))
+ return false;
+ caret = ta->sel_start;
textarea_clear_selection(ta);
+ redraw = true;
+ break;
+ }
+
+ if (caret == 0)
+ break;
+
+ /* caret goes left until a non-separator is
+ * encountered */
+ caret--;
+ while (strchr(sep, ta->show->data[caret]) != NULL &&
+ caret > 0)
+ caret--;
+
+ /* caret goes left until a separator is encountered */
+ for (; caret > 0; caret--) {
+ if (strchr(sep, ta->show->data[caret]) !=
+ NULL) {
+ caret++;
+ break;
+ }
}
+
+ /* Remove the characters from new caret position to
+ * original caret position */
+ if (!textarea_replace_text(ta, caret, caret_copy,
+ "", 0, false, &byte_delta, &r))
+ return false;
+
+ redraw = true;
break;
case NS_KEY_WORD_RIGHT:
if (readonly)
break;
+ if (ta->sel_start != -1) {
+ textarea_clear_selection(ta);
+ }
+ if (caret == ta->show->len - 1)
+ break;
if (strchr(sep, ta->show->data[caret]) != NULL &&
caret < ta->show->len - 1) {
while (strchr(sep, ta->show->data[caret]) !=
@@ -2779,9 +2828,49 @@ bool textarea_keypress(struct textarea *ta, uint32_t key)
while (strchr(sep, ta->show->data[caret]) != NULL &&
caret < ta->show->len - 1)
caret++;
+ break;
+ case NS_KEY_DELETE_WORD_RIGHT:
+ if (readonly)
+ break;
+
+ /* If there is a selection, remove the selected
+ * characters */
if (ta->sel_start != -1) {
+ if (!textarea_replace_text(ta, ta->sel_start,
+ ta->sel_end, "", 0, false,
+ &byte_delta, &r))
+ return false;
+ caret = ta->sel_start;
textarea_clear_selection(ta);
+ redraw = true;
+ break;
}
+
+ if (caret == ta->show->len - 1)
+ break;
+
+ /* caret_copy goes right until a non-separator is
+ * encountered */
+ while (strchr(sep, ta->show->data[caret_copy]) != NULL
+ && caret_copy < ta->show->len - 1)
+ caret_copy++;
+
+ /* caret_copy goes right until a separator is
+ * encountered */
+ for (; caret_copy < ta->show->len - 1; caret_copy++) {
+ if (strchr(sep, ta->show->data[caret_copy]) !=
+ NULL) {
+ break;
+ }
+ }
+
+ /* Remove all the characters from original caret
+ * position to caret_copy */
+ if (!textarea_replace_text(ta, caret, caret_copy,
+ "", 0, false, &byte_delta, &r))
+ return false;
+
+ redraw = true;
break;
case NS_KEY_DELETE_LINE:
if (readonly)
diff --git a/desktop/textinput.c b/desktop/textinput.c
index c0e0ba8f7..b8dced689 100644
--- a/desktop/textinput.c
+++ b/desktop/textinput.c
@@ -33,13 +33,13 @@
#include "utils/talloc.h"
#include "utils/utf8.h"
#include "utils/utils.h"
+#include "netsurf/types.h"
#include "netsurf/mouse.h"
#include "netsurf/form.h"
#include "netsurf/window.h"
+#include "netsurf/browser_window.h"
#include "netsurf/keypress.h"
-#include "render/box.h"
-#include "render/html_internal.h"
-#include "render/layout.h"
+#include "content/content.h"
#include "desktop/browser_private.h"
#include "desktop/textinput.h"
@@ -92,13 +92,14 @@ void browser_window_remove_caret(struct browser_window *bw, bool only_hide)
root_bw = browser_window_get_root(bw);
assert(root_bw != NULL);
- if (only_hide)
+ if (only_hide) {
root_bw->can_edit = true;
- else
+ } else {
root_bw->can_edit = false;
+ }
if (root_bw->window) {
- guit->window->remove_caret(root_bw->window);
+ guit->window->event(root_bw->window, GW_EVENT_REMOVE_CARET);
}
}
diff --git a/desktop/treeview.c b/desktop/treeview.c
index 1651ff5ef..a65a37e72 100644
--- a/desktop/treeview.c
+++ b/desktop/treeview.c
@@ -22,13 +22,15 @@
* Treeview handling implementation.
*/
+#include "utils/config.h"
+
#include <string.h>
#include "utils/utils.h"
#include "utils/log.h"
#include "utils/nsurl.h"
+#include "utils/nscolour.h"
#include "utils/nsoption.h"
-#include "utils/config.h"
#include "netsurf/bitmap.h"
#include "netsurf/content.h"
#include "netsurf/plotters.h"
@@ -39,11 +41,13 @@
#include "content/hlcache.h"
#include "css/utils.h"
-#include "desktop/system_colour.h"
+#include "desktop/bitmap.h"
#include "desktop/knockout.h"
#include "desktop/textarea.h"
#include "desktop/treeview.h"
+#include "desktop/cw_helper.h"
#include "desktop/gui_internal.h"
+#include "desktop/system_colour.h"
/**
* The maximum horizontal size a treeview can possibly be.
@@ -333,7 +337,7 @@ static struct treeview_resource treeview_res[TREE_RES_LAST] = {
* \param[in] tree Treeview to get the height of.
* \return the display height in pixels.
*/
-static inline int treeview__get_display_height(treeview *tree)
+static inline int treeview__get_display_height(const treeview *tree)
{
return (tree->search.search == false) ?
tree->root->height :
@@ -358,6 +362,40 @@ static inline void treeview__cw_invalidate_area(
/**
+ * Corewindow callback wrapper: Request a full redraw of the window
+ *
+ * \param[in] tree The treeview to request redraw on.
+ */
+static inline void treeview__cw_full_redraw(
+ const struct treeview *tree)
+{
+ if (tree->cw_t != NULL) {
+ static const struct rect r = {
+ .x0 = 0,
+ .y0 = 0,
+ .x1 = REDRAW_MAX,
+ .y1 = REDRAW_MAX,
+ };
+ tree->cw_t->invalidate(tree->cw_h, &r);
+ }
+}
+
+
+/**
+ * Get height used by treeview's search bar (or 0 if not present).
+ *
+ * \param tree Treeview object to check.
+ * \return height used by search bar in pixels.
+ */
+static inline unsigned treeview__get_search_height(
+ const treeview *tree)
+{
+ return (tree->flags & TREEVIEW_SEARCHABLE) ?
+ tree_g.line_height : 0;
+}
+
+
+/**
* Corewindow callback wrapper: Update the limits of the window
*
* \param[in] tree The treeview to update size for.
@@ -368,12 +406,9 @@ static inline void treeview__cw_update_size(
const struct treeview *tree,
int width, int height)
{
- int search_height = (tree->flags & TREEVIEW_SEARCHABLE) ?
- tree_g.line_height : 0;
-
if (tree->cw_t != NULL) {
tree->cw_t->update_size(tree->cw_h, width,
- height + search_height);
+ height + treeview__get_search_height(tree));
}
}
@@ -393,9 +428,7 @@ static inline void treeview__cw_scroll_top(
.y1 = tree_g.line_height,
};
- if (tree->cw_t != NULL) {
- tree->cw_t->scroll_visible(tree->cw_h, &r);
- }
+ cw_helper_scroll_visible(tree->cw_t, tree->cw_h, &r);
}
@@ -501,9 +534,8 @@ static inline treeview_node * treeview_node_next(treeview_node *node, bool full)
*/
static treeview_node * treeview_y_node(treeview *tree, int target_y)
{
+ int y = treeview__get_search_height(tree);
treeview_node *n;
- int y = 0;
- int h;
assert(tree != NULL);
assert(tree->root != NULL);
@@ -511,7 +543,7 @@ static treeview_node * treeview_y_node(treeview *tree, int target_y)
n = treeview_node_next(tree->root, false);
while (n != NULL) {
- h = (n->type == TREE_NODE_ENTRY) ?
+ int h = (n->type == TREE_NODE_ENTRY) ?
n->height : tree_g.line_height;
if (target_y >= y && target_y < y + h)
return n;
@@ -531,10 +563,12 @@ static treeview_node * treeview_y_node(treeview *tree, int target_y)
* \param node Node to get position of
* \return node's y position
*/
-static int treeview_node_y(treeview *tree, treeview_node *node)
+static int treeview_node_y(
+ const treeview *tree,
+ const treeview_node *node)
{
treeview_node *n;
- int y = 0;
+ int y = treeview__get_search_height(tree);
assert(tree != NULL);
assert(tree->root != NULL);
@@ -553,6 +587,54 @@ static int treeview_node_y(treeview *tree, treeview_node *node)
/**
+ * Corewindow callback_wrapper: Scroll to make node visible
+ *
+ * \param[in] tree The treeview to scroll.
+ * \param[in] node The treeview node to scroll to visibility.
+ */
+static inline void treeview__cw_scroll_to_node(
+ const struct treeview *tree,
+ const struct treeview_node *node)
+{
+ struct rect r = {
+ .x0 = 0,
+ .y0 = treeview_node_y(tree, node),
+ .x1 = 1,
+ .y1 = ((node->type == TREE_NODE_ENTRY) ?
+ node->height : tree_g.line_height),
+ };
+
+ r.y1 += r.y0; /* Apply the Y offset to the second Y coordinate */
+
+ cw_helper_scroll_visible(tree->cw_t, tree->cw_h, &r);
+}
+
+
+/**
+ * Redraw tree from given node to the bottom.
+ *
+ * \param[in] tree Tree to redraw from node in.
+ * \param[in] node Node to redraw from.
+ */
+static void treeview__redraw_from_node(
+ const treeview *tree,
+ const treeview_node *node)
+{
+ struct rect r = {
+ .x0 = 0,
+ .y0 = treeview_node_y(tree, node),
+ .x1 = REDRAW_MAX,
+ .y1 = treeview__get_display_height(tree) +
+ treeview__get_search_height(tree),
+ };
+
+ assert(tree != NULL);
+
+ treeview__cw_invalidate_area(tree, &r);
+}
+
+
+/**
* The treeview walk mode. Controls which nodes are visited in a walk.
*/
enum treeview_walk_mode {
@@ -790,8 +872,7 @@ static nserror treeview__search(
nserror err;
uint32_t height;
uint32_t prev_height = treeview__get_display_height(tree);
- int search_height = (tree->flags & TREEVIEW_SEARCHABLE) ?
- tree_g.line_height : 0;
+ int search_height = treeview__get_search_height(tree);
struct treeview_search_walk_data sw = {
.len = len,
.text = text,
@@ -855,6 +936,12 @@ static void treeview__search_cancel(treeview *tree, bool drop_focus)
return;
}
+ if (textarea_get_text(tree->search.textarea, NULL, 0) == 1) {
+ // If there's no text in the search box, we drop focus on a
+ // cancel. Note '1' because it includes the trailing \0
+ drop_focus = true;
+ }
+
if (drop_focus) {
tree->search.active = false;
textarea_set_caret(tree->search.textarea, -1);
@@ -866,6 +953,34 @@ static void treeview__search_cancel(treeview *tree, bool drop_focus)
treeview__cw_invalidate_area(tree, &r);
}
+/**
+ * Convert from treeview drag to core window drag type.
+ *
+ * \param[in] tree A treeview.
+ * \return Core window drag type.
+ */
+static core_window_drag_status treeview__get_cw_drag_type(
+ const treeview *tree)
+{
+ assert(tree != NULL);
+
+ switch (tree->drag.type) {
+ case TV_DRAG_NONE:
+ return CORE_WINDOW_DRAG_NONE;
+
+ case TV_DRAG_SELECTION:
+ return CORE_WINDOW_DRAG_SELECTION;
+
+ case TV_DRAG_TEXTAREA: /* Fall through.*/
+ case TV_DRAG_SEARCH:
+ return CORE_WINDOW_DRAG_TEXT_SELECTION;
+
+ case TV_DRAG_MOVE:
+ return CORE_WINDOW_DRAG_MOVE;
+ }
+
+ return CORE_WINDOW_DRAG_NONE;
+}
/**
* Callback for textarea_create, in desktop/treeview.h
@@ -892,7 +1007,8 @@ static void treeview_textarea_search_callback(void *data,
/* Textarea drag started */
tree->drag.type = TV_DRAG_SEARCH;
}
- treeview__cw_drag_status(tree, tree->drag.type);
+ treeview__cw_drag_status(tree,
+ treeview__get_cw_drag_type(tree));
break;
case TEXTAREA_MSG_REDRAW_REQUEST:
@@ -1930,7 +2046,7 @@ treeview_create(treeview **tree,
(*tree)->fields = malloc(sizeof(struct treeview_field) * n_fields);
if ((*tree)->fields == NULL) {
- free(tree);
+ free(*tree);
return NSERROR_NOMEM;
}
@@ -1984,9 +2100,9 @@ treeview_create(treeview **tree,
if (flags & TREEVIEW_SEARCHABLE) {
(*tree)->search.textarea = treeview__create_textarea(
*tree, 600, tree_g.line_height,
- plot_style_even.text.background,
- plot_style_even.text.background,
- plot_style_even.text.foreground,
+ nscolours[NSCOLOUR_TEXT_INPUT_BG],
+ nscolours[NSCOLOUR_TEXT_INPUT_BG],
+ nscolours[NSCOLOUR_TEXT_INPUT_FG],
plot_style_odd.text,
treeview_textarea_search_callback);
if ((*tree)->search.textarea == NULL) {
@@ -2083,7 +2199,8 @@ treeview_node_expand_internal(treeview *tree, treeview_node *node)
{
treeview_node *child;
struct treeview_node_entry *e;
- int additional_height = 0;
+ int additional_height_folders = 0;
+ int additional_height_entries = 0;
int i;
assert(tree != NULL);
@@ -2111,7 +2228,7 @@ treeview_node_expand_internal(treeview *tree, treeview_node *node)
&(child->text.width));
}
- additional_height += child->height;
+ additional_height_folders += child->height;
child = child->next_sib;
} while (child != NULL);
@@ -2133,7 +2250,7 @@ treeview_node_expand_internal(treeview *tree, treeview_node *node)
}
/* Add height for field */
- additional_height += tree_g.line_height;
+ additional_height_entries += tree_g.line_height;
}
break;
@@ -2152,17 +2269,18 @@ treeview_node_expand_internal(treeview *tree, treeview_node *node)
for (struct treeview_node *n = node;
(n != NULL) && (n->flags & TV_NFLAGS_EXPANDED);
n = n->parent) {
- n->height += additional_height;
+ n->height += additional_height_entries +
+ additional_height_folders;
}
if (tree->search.search &&
node->type == TREE_NODE_ENTRY &&
node->flags & TV_NFLAGS_MATCHED) {
- tree->search.height += additional_height;
+ tree->search.height += additional_height_entries;
}
/* Inform front end of change in dimensions */
- if (additional_height != 0) {
+ if (additional_height_entries + additional_height_folders != 0) {
treeview__cw_update_size(tree, -1,
treeview__get_display_height(tree));
}
@@ -2175,17 +2293,13 @@ treeview_node_expand_internal(treeview *tree, treeview_node *node)
nserror treeview_node_expand(treeview *tree, treeview_node *node)
{
nserror res;
- struct rect r;
res = treeview_node_expand_internal(tree, node);
+ NSLOG(netsurf, INFO, "Expanding!");
if (res == NSERROR_OK) {
/* expansion was successful, attempt redraw */
- r.x0 = 0;
- r.y0 = treeview_node_y(tree, node);
- r.x1 = REDRAW_MAX;
- r.y1 = treeview__get_display_height(tree);
-
- treeview__cw_invalidate_area(tree, &r);
+ treeview__redraw_from_node(tree, node);
+ NSLOG(netsurf, INFO, "Expanded!");
}
return res;
@@ -2212,7 +2326,8 @@ struct treeview_contract_data {
static nserror treeview_node_contract_cb(treeview_node *n, void *ctx, bool *end)
{
struct treeview_contract_data *data = ctx;
- int h_reduction;
+ int h_reduction_folder = 0;
+ int h_reduction_entry = 0;
assert(n != NULL);
assert(n->type != TREE_NODE_ROOT);
@@ -2225,17 +2340,30 @@ static nserror treeview_node_contract_cb(treeview_node *n, void *ctx, bool *end)
return NSERROR_OK;
}
- h_reduction = n->height - tree_g.line_height;
- assert(h_reduction >= 0);
+ switch (n->type) {
+ case TREE_NODE_FOLDER:
+ h_reduction_folder = n->height - tree_g.line_height;
+ break;
+
+ case TREE_NODE_ENTRY:
+ h_reduction_entry = n->height - tree_g.line_height;
+ break;
+
+ default:
+ break;
+ }
+
+
+ assert(h_reduction_folder + h_reduction_entry >= 0);
for (struct treeview_node *node = n;
(node != NULL) && (node->flags & TV_NFLAGS_EXPANDED);
node = node->parent) {
- node->height -= h_reduction;
+ node->height -= h_reduction_folder + h_reduction_entry;
}
if (data->tree->search.search) {
- data->tree->search.height -= h_reduction;
+ data->tree->search.height -= h_reduction_entry;
}
n->flags ^= TV_NFLAGS_EXPANDED;
@@ -2289,19 +2417,15 @@ treeview_node_contract_internal(treeview *tree, treeview_node *node)
nserror treeview_node_contract(treeview *tree, treeview_node *node)
{
nserror res;
- struct rect r;
assert(tree != NULL);
res = treeview_node_contract_internal(tree, node);
+ NSLOG(netsurf, INFO, "Contracting!");
if (res == NSERROR_OK) {
/* successful contraction, request redraw */
- r.x0 = 0;
- r.y0 = treeview_node_y(tree, node);
- r.x1 = REDRAW_MAX;
- r.y1 = tree->root->height;
-
- treeview__cw_invalidate_area(tree, &r);
+ treeview__redraw_from_node(tree, node);
+ NSLOG(netsurf, INFO, "Contracted!");
}
return res;
@@ -2311,6 +2435,7 @@ nserror treeview_node_contract(treeview *tree, treeview_node *node)
/* Exported interface, documented in treeview.h */
nserror treeview_contract(treeview *tree, bool all)
{
+ int search_height = treeview__get_search_height(tree);
struct treeview_contract_data data;
bool selected;
treeview_node *n;
@@ -2322,7 +2447,7 @@ nserror treeview_contract(treeview *tree, bool all)
r.x0 = 0;
r.y0 = 0;
r.x1 = REDRAW_MAX;
- r.y1 = tree->root->height;
+ r.y1 = tree->root->height + search_height;
data.tree = tree;
data.only_entries = !all;
@@ -2444,7 +2569,7 @@ static void treeview_redraw_tree(
const int x,
const int y,
int *render_y_in_out,
- struct rect *r,
+ const struct rect *r,
struct content_redraw_data *data,
const struct redraw_context *ctx)
{
@@ -2663,7 +2788,7 @@ static void treeview_redraw_search(
const int x,
const int y,
int *render_y_in_out,
- struct rect *r,
+ const struct rect *r,
struct content_redraw_data *data,
const struct redraw_context *ctx)
{
@@ -3010,6 +3135,7 @@ struct treeview_selection_walk_data {
} drag;
struct {
treeview_node *prev;
+ treeview_node *fixed;
} yank;
struct {
treeview_node *n;
@@ -3112,6 +3238,10 @@ treeview_node_selection_walk_cb(treeview_node *n,
treeview_node *p = n->parent;
int h = 0;
+ if (n == sw->data.yank.fixed) {
+ break;
+ }
+
if (treeview_unlink_node(n))
h = n->height;
@@ -3270,8 +3400,7 @@ static bool treeview_clear_selection(treeview *tree, struct rect *rect)
sw.purpose = TREEVIEW_WALK_CLEAR_SELECTION;
sw.data.redraw.required = false;
sw.data.redraw.rect = rect;
- sw.current_y = (tree->flags & TREEVIEW_SEARCHABLE) ?
- tree_g.line_height : 0;
+ sw.current_y = treeview__get_search_height(tree);
treeview_walk_internal(tree, tree->root,
TREEVIEW_WALK_MODE_DISPLAY, NULL,
@@ -3300,8 +3429,7 @@ static bool treeview_select_all(treeview *tree, struct rect *rect)
sw.purpose = TREEVIEW_WALK_SELECT_ALL;
sw.data.redraw.required = false;
sw.data.redraw.rect = rect;
- sw.current_y = (tree->flags & TREEVIEW_SEARCHABLE) ?
- tree_g.line_height : 0;
+ sw.current_y = treeview__get_search_height(tree);
treeview_walk_internal(tree, tree->root,
TREEVIEW_WALK_MODE_DISPLAY, NULL,
@@ -3321,8 +3449,7 @@ static void treeview_commit_selection_drag(treeview *tree)
struct treeview_selection_walk_data sw;
sw.purpose = TREEVIEW_WALK_COMMIT_SELECT_DRAG;
- sw.current_y = (tree->flags & TREEVIEW_SEARCHABLE) ?
- tree_g.line_height : 0;
+ sw.current_y = treeview__get_search_height(tree);
if (tree->drag.start.y > tree->drag.prev.y) {
sw.data.drag.sel_min = tree->drag.prev.y;
@@ -3341,13 +3468,15 @@ static void treeview_commit_selection_drag(treeview *tree)
/**
* Yank a selection to the node move list.
*
- * \param tree Treeview object to yank selection from
+ * \param tree Treeview object to yank selection from
+ * \param fixed Treeview node that should not be yanked
*/
-static void treeview_move_yank_selection(treeview *tree)
+static void treeview_move_yank_selection(treeview *tree, treeview_node *fixed)
{
struct treeview_selection_walk_data sw;
sw.purpose = TREEVIEW_WALK_YANK_SELECTION;
+ sw.data.yank.fixed = fixed;
sw.data.yank.prev = NULL;
sw.tree = tree;
@@ -3404,12 +3533,12 @@ static bool treeview_delete_selection(treeview *tree, struct rect *rect)
rect->x0 = 0;
rect->y0 = 0;
rect->x1 = REDRAW_MAX;
- rect->y1 = tree->root->height;
+ rect->y1 = treeview__get_display_height(tree);
sw.purpose = TREEVIEW_WALK_DELETE_SELECTION;
sw.data.redraw.required = false;
sw.data.redraw.rect = rect;
- sw.current_y = 0;
+ sw.current_y = treeview__get_search_height(tree);
sw.tree = tree;
treeview_walk_internal(tree, tree->root,
@@ -3442,7 +3571,7 @@ static bool treeview_propagate_selection(treeview *tree, struct rect *rect)
sw.purpose = TREEVIEW_WALK_PROPAGATE_SELECTION;
sw.data.redraw.required = false;
sw.data.redraw.rect = rect;
- sw.current_y = 0;
+ sw.current_y = treeview__get_search_height(tree);
sw.tree = tree;
treeview_walk_internal(tree, tree->root,
@@ -3521,16 +3650,17 @@ static nserror treeview_move_selection(treeview *tree, struct rect *rect)
parent = relation->parent;
}
- /* The node that we're moving selection to can't itself be selected */
- assert(!(relation->flags & TV_NFLAGS_SELECTED));
-
/* Move all selected nodes from treeview to tree->move.root */
- treeview_move_yank_selection(tree);
+ treeview_move_yank_selection(tree, relation);
/* Move all nodes on tree->move.root to target location */
for (node = tree->move.root; node != NULL; node = next) {
next = node->next_sib;
+ if (node == relation) {
+ continue;
+ }
+
if (!(parent->flags & TV_NFLAGS_EXPANDED)) {
if (node->flags & TV_NFLAGS_EXPANDED)
treeview_node_contract_internal(tree, node);
@@ -3769,8 +3899,10 @@ treeview_keyboard_navigation(treeview *tree, uint32_t key, struct rect *rect)
.n_selected = 0,
.prev_n_selected = 0
};
- int h = tree->root->height;
+ int search_height = treeview__get_search_height(tree);
+ int h = treeview__get_display_height(tree) + search_height;
bool redraw = false;
+ struct treeview_node *scroll_to_node = NULL;
/* Fill out the nav. state struct, by examining the current selection
* state */
@@ -3778,6 +3910,8 @@ treeview_keyboard_navigation(treeview *tree, uint32_t key, struct rect *rect)
TREEVIEW_WALK_MODE_DISPLAY, NULL,
treeview_node_nav_cb, &ns);
+ scroll_to_node = ns.curr;
+
if (tree->search.search == false) {
if (ns.next == NULL)
ns.next = tree->root->children;
@@ -3798,10 +3932,12 @@ treeview_keyboard_navigation(treeview *tree, uint32_t key, struct rect *rect)
ns.curr->parent->type != TREE_NODE_ROOT) {
/* Step to parent */
ns.curr->parent->flags |= TV_NFLAGS_SELECTED;
+ scroll_to_node = ns.curr->parent;
} else if (ns.curr != NULL && tree->root->children != NULL) {
/* Select first node in tree */
tree->root->children->flags |= TV_NFLAGS_SELECTED;
+ scroll_to_node = tree->root->children;
}
break;
@@ -3814,6 +3950,7 @@ treeview_keyboard_navigation(treeview *tree, uint32_t key, struct rect *rect)
/* Step to first child */
ns.curr->children->flags |=
TV_NFLAGS_SELECTED;
+ scroll_to_node = ns.curr->children;
} else {
/* Retain current node selection */
ns.curr->flags |= TV_NFLAGS_SELECTED;
@@ -3835,6 +3972,7 @@ treeview_keyboard_navigation(treeview *tree, uint32_t key, struct rect *rect)
if (ns.prev != NULL) {
/* Step to previous node */
ns.prev->flags |= TV_NFLAGS_SELECTED;
+ scroll_to_node = ns.prev;
}
break;
@@ -3842,6 +3980,7 @@ treeview_keyboard_navigation(treeview *tree, uint32_t key, struct rect *rect)
if (ns.next != NULL) {
/* Step to next node */
ns.next->flags |= TV_NFLAGS_SELECTED;
+ scroll_to_node = ns.next;
}
break;
@@ -3849,12 +3988,14 @@ treeview_keyboard_navigation(treeview *tree, uint32_t key, struct rect *rect)
break;
}
+ treeview__cw_scroll_to_node(tree, scroll_to_node);
+
/* TODO: Deal with redraw area properly */
rect->x0 = 0;
rect->y0 = 0;
rect->x1 = REDRAW_MAX;
- if (tree->root->height > h)
- rect->y1 = tree->root->height;
+ if (treeview__get_display_height(tree) + search_height > h)
+ rect->y1 = treeview__get_display_height(tree) + search_height;
else
rect->y1 = h;
redraw = true;
@@ -4106,7 +4247,8 @@ static void treeview_textarea_callback(void *data, struct textarea_msg *msg)
/* Textarea drag started */
tree->drag.type = TV_DRAG_TEXTAREA;
}
- treeview__cw_drag_status(tree, tree->drag.type);
+ treeview__cw_drag_status(tree,
+ treeview__get_cw_drag_type(tree));
break;
case TEXTAREA_MSG_REDRAW_REQUEST:
@@ -4290,6 +4432,7 @@ struct treeview_mouse_action {
int x;
int y;
int current_y; /* Y coordinate value of top of current node */
+ int search_height;
};
@@ -4477,7 +4620,8 @@ treeview_node_mouse_action_cb(treeview_node *node,
if (((node->type == TREE_NODE_FOLDER) &&
(ma->mouse & BROWSER_MOUSE_DOUBLE_CLICK) && click) ||
(part == TV_NODE_PART_TOGGLE && click)) {
- int h = ma->tree->root->height;
+ int h = treeview__get_display_height(ma->tree) +
+ ma->search_height;
/* Clear any existing selection */
redraw |= treeview_clear_selection(ma->tree, &r);
@@ -4495,7 +4639,13 @@ treeview_node_mouse_action_cb(treeview_node *node,
/* Set up redraw */
if (!redraw || r.y0 > ma->current_y)
r.y0 = ma->current_y;
- r.y1 = h > ma->tree->root->height ? h : ma->tree->root->height;
+ if (h > treeview__get_display_height(ma->tree) +
+ ma->search_height) {
+ r.y1 = h;
+ } else {
+ r.y1 = treeview__get_display_height(ma->tree) +
+ ma->search_height;
+ }
redraw = true;
} else if ((node->type == TREE_NODE_ENTRY) &&
@@ -4576,8 +4726,7 @@ treeview_mouse_action(treeview *tree, browser_mouse_state mouse, int x, int y)
{
struct rect r;
bool redraw = false;
- int search_height = (tree->flags & TREEVIEW_SEARCHABLE) ?
- tree_g.line_height : 0;
+ int search_height = treeview__get_search_height(tree);
assert(tree != NULL);
assert(tree->root != NULL);
@@ -4592,9 +4741,7 @@ treeview_mouse_action(treeview *tree, browser_mouse_state mouse, int x, int y)
textarea_mouse_action(tree->edit.textarea, mouse,
x - tree->edit.x, y - tree->edit.y);
return;
- } else if (tree->drag.type == TV_DRAG_SEARCH ||
- (y < search_height &&
- tree->drag.type == TV_DRAG_NONE)) {
+ } else if (tree->drag.type == TV_DRAG_SEARCH) {
if (tree->search.active == false) {
tree->search.active = true;
if (treeview_clear_selection(tree, &r)) {
@@ -4606,6 +4753,16 @@ treeview_mouse_action(treeview *tree, browser_mouse_state mouse, int x, int y)
y);
return;
} else if (mouse & (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2) &&
+ y < search_height && tree->search.active == false) {
+ tree->search.active = true;
+ if (treeview_clear_selection(tree, &r)) {
+ treeview__cw_invalidate_area(tree, &r);
+ }
+ textarea_mouse_action(tree->search.textarea, mouse,
+ x - tree_g.window_padding - tree_g.icon_size,
+ y);
+ return;
+ } else if (mouse & (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2) &&
tree->search.active == true) {
tree->search.active = false;
@@ -4734,13 +4891,14 @@ treeview_mouse_action(treeview *tree, browser_mouse_state mouse, int x, int y)
} else {
/* On tree */
- struct treeview_mouse_action ma;
-
- ma.tree = tree;
- ma.mouse = mouse;
- ma.x = x;
- ma.y = y;
- ma.current_y = search_height;
+ struct treeview_mouse_action ma = {
+ .tree = tree,
+ .mouse = mouse,
+ .x = x,
+ .y = y,
+ .current_y = search_height,
+ .search_height = search_height,
+ };
treeview_walk_internal(tree, tree->root,
TREEVIEW_WALK_MODE_DISPLAY, NULL,
@@ -4748,12 +4906,10 @@ treeview_mouse_action(treeview *tree, browser_mouse_state mouse, int x, int y)
}
}
-
/* Exported interface, documented in treeview.h */
int treeview_get_height(treeview *tree)
{
- int search_height = (tree->flags & TREEVIEW_SEARCHABLE) ?
- tree_g.line_height : 0;
+ int search_height = treeview__get_search_height(tree);
int height = treeview__get_display_height(tree);
assert(tree != NULL);
@@ -4764,6 +4920,31 @@ int treeview_get_height(treeview *tree)
return height + search_height;
}
+/* Exported interface, documented in treeview.h */
+nserror treeview_set_search_string(
+ treeview *tree,
+ const char *string)
+{
+ if (!(tree->flags & TREEVIEW_SEARCHABLE)) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if (string == NULL || strlen(string) == 0) {
+ tree->search.active = false;
+ tree->search.search = false;
+ return treeview__search(tree, "", 0);
+ }
+
+ tree->search.active = true;
+ tree->search.search = true;
+ if (!textarea_set_text(tree->search.textarea, string)) {
+ return NSERROR_UNKNOWN;
+ }
+
+ treeview__cw_full_redraw(tree);
+
+ return NSERROR_OK;
+}
/**
* Initialise the plot styles from CSS system colour values.
@@ -4773,75 +4954,45 @@ int treeview_get_height(treeview *tree)
*/
static nserror treeview_init_plot_styles(int font_pt_size)
{
- nserror res;
-
/* Background colour */
plot_style_even.bg.stroke_type = PLOT_OP_TYPE_NONE;
plot_style_even.bg.stroke_width = 0;
plot_style_even.bg.stroke_colour = 0;
plot_style_even.bg.fill_type = PLOT_OP_TYPE_SOLID;
- res = ns_system_colour_char("Window", &plot_style_even.bg.fill_colour);
- if (res != NSERROR_OK) {
- return res;
- }
+ plot_style_even.bg.fill_colour = nscolours[NSCOLOUR_WIN_EVEN_BG];
/* Text colour */
plot_style_even.text.family = PLOT_FONT_FAMILY_SANS_SERIF;
plot_style_even.text.size = font_pt_size;
plot_style_even.text.weight = 400;
plot_style_even.text.flags = FONTF_NONE;
- res = ns_system_colour_char("WindowText", &plot_style_even.text.foreground);
- if (res != NSERROR_OK) {
- return res;
- }
- res = ns_system_colour_char("Window", &plot_style_even.text.background);
- if (res != NSERROR_OK) {
- return res;
- }
+ plot_style_even.text.foreground = nscolours[NSCOLOUR_WIN_EVEN_FG];
+ plot_style_even.text.background = nscolours[NSCOLOUR_WIN_EVEN_BG];
/* Entry field text colour */
plot_style_even.itext = plot_style_even.text;
- plot_style_even.itext.foreground = mix_colour(
- plot_style_even.text.foreground,
- plot_style_even.text.background,
- 255 * 10 / 16);
+ plot_style_even.itext.foreground = nscolours[NSCOLOUR_WIN_EVEN_FG_FADED];
/* Selected background colour */
plot_style_even.sbg = plot_style_even.bg;
- res = ns_system_colour_char("Highlight", &plot_style_even.sbg.fill_colour);
- if (res != NSERROR_OK) {
- return res;
- }
+ plot_style_even.sbg.fill_colour = nscolours[NSCOLOUR_SEL_BG];
/* Selected text colour */
plot_style_even.stext = plot_style_even.text;
- res = ns_system_colour_char("HighlightText", &plot_style_even.stext.foreground);
- if (res != NSERROR_OK) {
- return res;
- }
- res = ns_system_colour_char("Highlight", &plot_style_even.stext.background);
- if (res != NSERROR_OK) {
- return res;
- }
+ plot_style_even.stext.foreground = nscolours[NSCOLOUR_SEL_FG];
+ plot_style_even.stext.background = nscolours[NSCOLOUR_SEL_BG];
/* Selected entry field text colour */
plot_style_even.sitext = plot_style_even.stext;
- plot_style_even.sitext.foreground = mix_colour(
- plot_style_even.stext.foreground,
- plot_style_even.stext.background,
- 255 * 25 / 32);
+ plot_style_even.sitext.foreground = nscolours[NSCOLOUR_SEL_FG_SUBTLE];
/* Odd numbered node styles */
plot_style_odd.bg = plot_style_even.bg;
- plot_style_odd.bg.fill_colour = mix_colour(
- plot_style_even.bg.fill_colour,
- plot_style_even.text.foreground, 255 * 15 / 16);
+ plot_style_odd.bg.fill_colour = nscolours[NSCOLOUR_WIN_ODD_BG];
plot_style_odd.text = plot_style_even.text;
plot_style_odd.text.background = plot_style_odd.bg.fill_colour;
plot_style_odd.itext = plot_style_odd.text;
- plot_style_odd.itext.foreground = mix_colour(
- plot_style_odd.text.foreground,
- plot_style_odd.text.background, 255 * 10 / 16);
+ plot_style_odd.itext.foreground = nscolours[NSCOLOUR_WIN_EVEN_FG_FADED];
plot_style_odd.sbg = plot_style_even.sbg;
plot_style_odd.stext = plot_style_even.stext;
@@ -4927,7 +5078,7 @@ treeview_generate_triangle_bitmap(colour bg, colour fg, int size)
colour colour4 = fg;
/* Create the bitmap */
- b = guit->bitmap->create(size, size, BITMAP_NEW | BITMAP_OPAQUE);
+ b = guit->bitmap->create(size, size, BITMAP_OPAQUE);
if (b == NULL)
return NULL;
@@ -4941,58 +5092,68 @@ treeview_generate_triangle_bitmap(colour bg, colour fg, int size)
if (y < size / 2) {
/* Top half */
for (x = 0; x < y * 2; x++) {
- *(pos++) = red_from_colour(colour4);
- *(pos++) = green_from_colour(colour4);
- *(pos++) = blue_from_colour(colour4);
- *(pos++) = 0xff;
+ pos[bitmap_layout.r] = red_from_colour(colour4);
+ pos[bitmap_layout.g] = green_from_colour(colour4);
+ pos[bitmap_layout.b] = blue_from_colour(colour4);
+ pos[bitmap_layout.a] = 0xff;
+ pos += 4;
}
- *(pos++) = red_from_colour(colour3);
- *(pos++) = green_from_colour(colour3);
- *(pos++) = blue_from_colour(colour3);
- *(pos++) = 0xff;
- *(pos++) = red_from_colour(colour1);
- *(pos++) = green_from_colour(colour1);
- *(pos++) = blue_from_colour(colour1);
- *(pos++) = 0xff;
+ pos[bitmap_layout.r] = red_from_colour(colour3);
+ pos[bitmap_layout.g] = green_from_colour(colour3);
+ pos[bitmap_layout.b] = blue_from_colour(colour3);
+ pos[bitmap_layout.a] = 0xff;
+ pos += 4;
+ pos[bitmap_layout.r] = red_from_colour(colour1);
+ pos[bitmap_layout.g] = green_from_colour(colour1);
+ pos[bitmap_layout.b] = blue_from_colour(colour1);
+ pos[bitmap_layout.a] = 0xff;
+ pos += 4;
for (x = y * 2 + 2; x < size ; x++) {
- *(pos++) = red_from_colour(colour0);
- *(pos++) = green_from_colour(colour0);
- *(pos++) = blue_from_colour(colour0);
- *(pos++) = 0xff;
+ pos[bitmap_layout.r] = red_from_colour(colour0);
+ pos[bitmap_layout.g] = green_from_colour(colour0);
+ pos[bitmap_layout.b] = blue_from_colour(colour0);
+ pos[bitmap_layout.a] = 0xff;
+ pos += 4;
}
} else if ((y == size / 2) && (size & 0x1)) {
/* Middle row */
for (x = 0; x < size - 1; x++) {
- *(pos++) = red_from_colour(colour4);
- *(pos++) = green_from_colour(colour4);
- *(pos++) = blue_from_colour(colour4);
- *(pos++) = 0xff;
+ pos[bitmap_layout.r] = red_from_colour(colour4);
+ pos[bitmap_layout.g] = green_from_colour(colour4);
+ pos[bitmap_layout.b] = blue_from_colour(colour4);
+ pos[bitmap_layout.a] = 0xff;
+ pos += 4;
}
- *(pos++) = red_from_colour(colour2);
- *(pos++) = green_from_colour(colour2);
- *(pos++) = blue_from_colour(colour2);
- *(pos++) = 0xff;
+ pos[bitmap_layout.r] = red_from_colour(colour2);
+ pos[bitmap_layout.g] = green_from_colour(colour2);
+ pos[bitmap_layout.b] = blue_from_colour(colour2);
+ pos[bitmap_layout.a] = 0xff;
+ pos += 4;
} else {
/* Bottom half */
for (x = 0; x < (size - y - 1) * 2; x++) {
- *(pos++) = red_from_colour(colour4);
- *(pos++) = green_from_colour(colour4);
- *(pos++) = blue_from_colour(colour4);
- *(pos++) = 0xff;
+ pos[bitmap_layout.r] = red_from_colour(colour4);
+ pos[bitmap_layout.g] = green_from_colour(colour4);
+ pos[bitmap_layout.b] = blue_from_colour(colour4);
+ pos[bitmap_layout.a] = 0xff;
+ pos += 4;
}
- *(pos++) = red_from_colour(colour3);
- *(pos++) = green_from_colour(colour3);
- *(pos++) = blue_from_colour(colour3);
- *(pos++) = 0xff;
- *(pos++) = red_from_colour(colour1);
- *(pos++) = green_from_colour(colour1);
- *(pos++) = blue_from_colour(colour1);
- *(pos++) = 0xff;
+ pos[bitmap_layout.r] = red_from_colour(colour3);
+ pos[bitmap_layout.g] = green_from_colour(colour3);
+ pos[bitmap_layout.b] = blue_from_colour(colour3);
+ pos[bitmap_layout.a] = 0xff;
+ pos += 4;
+ pos[bitmap_layout.r] = red_from_colour(colour1);
+ pos[bitmap_layout.g] = green_from_colour(colour1);
+ pos[bitmap_layout.b] = blue_from_colour(colour1);
+ pos[bitmap_layout.a] = 0xff;
+ pos += 4;
for (x = (size - y) * 2; x < size ; x++) {
- *(pos++) = red_from_colour(colour0);
- *(pos++) = green_from_colour(colour0);
- *(pos++) = blue_from_colour(colour0);
- *(pos++) = 0xff;
+ pos[bitmap_layout.r] = red_from_colour(colour0);
+ pos[bitmap_layout.g] = green_from_colour(colour0);
+ pos[bitmap_layout.b] = blue_from_colour(colour0);
+ pos[bitmap_layout.a] = 0xff;
+ pos += 4;
}
}
@@ -5026,7 +5187,7 @@ treeview_generate_copy_bitmap(struct bitmap *orig, int size)
assert(size == guit->bitmap->get_height(orig));
/* Create the bitmap */
- b = guit->bitmap->create(size, size, BITMAP_NEW | BITMAP_OPAQUE);
+ b = guit->bitmap->create(size, size, BITMAP_OPAQUE);
if (b == NULL)
return NULL;
@@ -5074,7 +5235,7 @@ treeview_generate_rotate_bitmap(struct bitmap *orig, int size)
assert(size == guit->bitmap->get_height(orig));
/* Create the bitmap */
- b = guit->bitmap->create(size, size, BITMAP_NEW | BITMAP_OPAQUE);
+ b = guit->bitmap->create(size, size, BITMAP_OPAQUE);
if (b == NULL)
return NULL;
@@ -5195,7 +5356,7 @@ nserror treeview_init(void)
10 + 36) / 72;
tree_g.line_height = (font_px_size * 8 + 3) / 6;
- res = treeview_init_plot_styles(font_pt_size * FONT_SIZE_SCALE / 10);
+ res = treeview_init_plot_styles(font_pt_size * PLOT_STYLE_SCALE / 10);
if (res != NSERROR_OK) {
return res;
}
diff --git a/desktop/treeview.h b/desktop/treeview.h
index a8cf29ac5..df9b4fb26 100644
--- a/desktop/treeview.h
+++ b/desktop/treeview.h
@@ -495,4 +495,15 @@ void treeview_edit_selection(treeview *tree);
*/
int treeview_get_height(treeview *tree);
+
+/**
+ * Set the search string for a treeview with \ref TREEVIEW_SEARCHABLE
+ *
+ * \param tree Tree to set the search string for.
+ * \return NSERROR_OK on success, appropriate error otherwise
+ */
+nserror treeview_set_search_string(
+ treeview *tree,
+ const char *string);
+
#endif
diff --git a/desktop/version.c b/desktop/version.c
index bbe759f2e..91a7532f4 100644
--- a/desktop/version.c
+++ b/desktop/version.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Vincent Sanders <vince@netsurf-browser.org>
+ * Copyright 2019 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -20,11 +20,11 @@
#include "desktop/version.h"
-const char * const netsurf_version = "3.8 (Dev"
+const char * const netsurf_version = "3.12 (Dev"
#if defined(CI_BUILD)
" CI #" CI_BUILD
#endif
")"
;
const int netsurf_version_major = 3;
-const int netsurf_version_minor = 8;
+const int netsurf_version_minor = 12;
diff --git a/docs/Doxyfile b/docs/Doxyfile
index f10669316..974c5a728 100644
--- a/docs/Doxyfile
+++ b/docs/Doxyfile
@@ -1,4 +1,4 @@
-# Doxyfile 1.8.8
+# Doxyfile 1.8.13
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
@@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8
# title of most generated pages and in a few other places.
# The default value is: My Project.
-PROJECT_NAME = NetSurf
+PROJECT_NAME = "NetSurf"
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
@@ -46,10 +46,10 @@ PROJECT_NUMBER =
PROJECT_BRIEF =
-# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
-# the documentation. The maximum height of the logo should not exceed 55 pixels
-# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
-# to the output directory.
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
PROJECT_LOGO =
@@ -60,7 +60,7 @@ PROJECT_LOGO =
OUTPUT_DIRECTORY =
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
# will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where
@@ -93,14 +93,14 @@ ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
-# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES.
BRIEF_MEMBER_DESC = YES
-# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
# description of a member or function before the detailed description
#
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
@@ -118,7 +118,17 @@ REPEAT_BRIEF = YES
# the entity):The $name class, The $name widget, The $name file, is, provides,
# specifies, contains, represents, a, an and the.
-ABBREVIATE_BRIEF =
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# doxygen will generate a detailed section even if there is only a brief
@@ -135,7 +145,7 @@ ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
-# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
# before files name in the file list and in the header files. If set to NO the
# shortest path that makes the file name unique will be used
# The default value is: YES.
@@ -205,9 +215,9 @@ MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
-# new page for each member. If set to NO, the documentation of a member will be
-# part of the file/class/namespace that contains it.
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
# The default value is: NO.
SEPARATE_MEMBER_PAGES = NO
@@ -276,7 +286,7 @@ OPTIMIZE_OUTPUT_VHDL = NO
# instance to make doxygen treat .inc files as Fortran files (default is PHP),
# and .f files as C (default is Fortran), use: inc=Fortran f=C.
#
-# Note For files without extension you can use no_extension as a placeholder.
+# Note: For files without extension you can use no_extension as a placeholder.
#
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen.
@@ -293,10 +303,19 @@ EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 0.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 3
+
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
-# be prevented in individual cases by by putting a % sign in front of the word
-# or globally by setting AUTOLINK_SUPPORT to NO.
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
# The default value is: YES.
AUTOLINK_SUPPORT = YES
@@ -336,13 +355,20 @@ SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
+# tag is set to YES then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
# The default value is: NO.
DISTRIBUTE_GROUP_DOC = NO
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
# (for instance a group of public functions) to be put as a subgroup of that
# type (e.g. under the Public Functions section). Set it to NO to prevent
@@ -401,7 +427,7 @@ LOOKUP_CACHE_SIZE = 0
# Build related configuration options
#---------------------------------------------------------------------------
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
# documentation are documented, even if no documentation was available. Private
# class members and static file members will be hidden unless the
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
@@ -411,35 +437,35 @@ LOOKUP_CACHE_SIZE = 0
EXTRACT_ALL = YES
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
# The default value is: NO.
EXTRACT_PRIVATE = YES
-# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation.
# The default value is: NO.
EXTRACT_PACKAGE = NO
-# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
# included in the documentation.
# The default value is: NO.
EXTRACT_STATIC = YES
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
-# locally in source files will be included in the documentation. If set to NO
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
# only classes defined in header files are included. Does not have any effect
# for Java sources.
# The default value is: YES.
EXTRACT_LOCAL_CLASSES = YES
-# This flag is only useful for Objective-C code. When set to YES local methods,
+# This flag is only useful for Objective-C code. If set to YES, local methods,
# which are defined in the implementation section but not in the interface are
-# included in the documentation. If set to NO only methods in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
# included.
# The default value is: NO.
@@ -464,21 +490,21 @@ HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
-# to NO these classes will be included in the various overviews. This option has
-# no effect if EXTRACT_ALL is enabled.
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
-# (class|struct|union) declarations. If set to NO these declarations will be
+# (class|struct|union) declarations. If set to NO, these declarations will be
# included in the documentation.
# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = NO
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
-# documentation blocks found inside the body of a function. If set to NO these
+# documentation blocks found inside the body of a function. If set to NO, these
# blocks will be appended to the function's detailed documentation block.
# The default value is: NO.
@@ -492,7 +518,7 @@ HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
-# names in lower-case letters. If set to YES upper-case letters are also
+# names in lower-case letters. If set to YES, upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
@@ -501,12 +527,19 @@ INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
-# their full class and namespace scopes in the documentation. If set to YES the
+# their full class and namespace scopes in the documentation. If set to YES, the
# scope will be hidden.
# The default value is: NO.
HIDE_SCOPE_NAMES = NO
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
@@ -534,14 +567,14 @@ INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
# (detailed) documentation of file and class members alphabetically by member
-# name. If set to NO the members will appear in declaration order.
+# name. If set to NO, the members will appear in declaration order.
# The default value is: YES.
SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member
-# name. If set to NO the members will appear in declaration order. Note that
+# name. If set to NO, the members will appear in declaration order. Note that
# this will also influence the order of the classes in the class list.
# The default value is: NO.
@@ -586,27 +619,25 @@ SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
-# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
-# todo list. This list is created by putting \todo commands in the
-# documentation.
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
# The default value is: YES.
GENERATE_TODOLIST = YES
-# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
-# test list. This list is created by putting \test commands in the
-# documentation.
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
# The default value is: YES.
GENERATE_TESTLIST = YES
-# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
# list. This list is created by putting \bug commands in the documentation.
# The default value is: YES.
GENERATE_BUGLIST = YES
-# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
# the deprecated list. This list is created by putting \deprecated commands in
# the documentation.
# The default value is: YES.
@@ -631,8 +662,8 @@ ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
-# the bottom of the documentation of classes and structs. If set to YES the list
-# will mention the files that were used to generate the documentation.
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
# The default value is: YES.
SHOW_USED_FILES = YES
@@ -696,7 +727,7 @@ CITE_BIB_FILES =
QUIET = NO
# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
# this implies that the warnings are on.
#
# Tip: Turn warnings on while writing the documentation.
@@ -704,7 +735,7 @@ QUIET = NO
WARNINGS = YES
-# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: YES.
@@ -721,12 +752,18 @@ WARN_IF_DOC_ERROR = YES
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
-# value. If set to NO doxygen will only warn about wrong or incomplete parameter
-# documentation, but not about the absence of documentation.
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation.
# The default value is: NO.
WARN_NO_PARAMDOC = YES
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
# can produce. The string should contain the $file, $line, and $text tags, which
# will be replaced by the file and line number from which the warning originated
@@ -750,12 +787,12 @@ WARN_LOGFILE =
# The INPUT tag is used to specify the files and/or directories that contain
# documented source files. You may enter file names like myfile.cpp or
# directories like /usr/src/myproject. Separate the files or directories with
-# spaces.
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = docs \
docs/env.sh \
- docs/UnimplementedJavascript.txt \
+ docs/UnimplementedJavascript.md \
frontends/amiga \
frontends/amiga/stringview \
frontends/atari \
@@ -773,14 +810,16 @@ INPUT = docs \
frontends/riscos/scripts \
frontends/windows \
include/netsurf \
- render \
desktop \
content \
content/fetchers \
+ content/fetchers/file \
content/handlers/image \
content/handlers/css \
content/handlers/javascript \
content/handlers/javascript/duktape \
+ content/handlers/html \
+ content/handlers/text \
utils \
utils/http
@@ -795,20 +834,62 @@ INPUT_ENCODING = UTF-8
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
-# *.h) to filter out the source-files in the directories. If left blank the
-# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
-# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
-# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
-# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
-# *.qsf, *.as and *.js.
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
+# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf.
FILE_PATTERNS = *.c \
- *.h \
- *.y \
- *.l \
+ *.cc \
+ *.cxx \
*.cpp \
+ *.c++ \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.idl \
+ *.ddl \
+ *.odl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.cs \
+ *.d \
+ *.php \
+ *.php4 \
+ *.php5 \
+ *.phtml \
+ *.inc \
*.m \
- *.md
+ *.markdown \
+ *.md \
+ *.mm \
+ *.dox \
+ *.py \
+ *.pyw \
+ *.f90 \
+ *.f95 \
+ *.f03 \
+ *.f08 \
+ *.f \
+ *.for \
+ *.tcl \
+ *.vhd \
+ *.vhdl \
+ *.ucf \
+ *.qsf
# The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well.
@@ -863,7 +944,7 @@ EXAMPLE_PATH =
# *.h) to filter out the source-files in the directories. If left blank all
# files are included.
-EXAMPLE_PATTERNS =
+EXAMPLE_PATTERNS = *
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude commands
@@ -892,6 +973,10 @@ IMAGE_PATH =
# Note that the filter must not add or remove lines; it is applied before the
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
INPUT_FILTER =
@@ -901,11 +986,15 @@ INPUT_FILTER =
# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER ) will also be used to filter the input files that are used for
+# INPUT_FILTER) will also be used to filter the input files that are used for
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
# The default value is: NO.
@@ -965,7 +1054,7 @@ REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
-# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
# link to the documentation.
# The default value is: YES.
@@ -1012,13 +1101,13 @@ USE_HTAGS = NO
VERBATIM_HEADERS = YES
-# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
# cost of reduced performance. This can be particularly helpful with template
# rich C++ code for which doxygen's built-in parser lacks the necessary type
# information.
# Note: The availability of this option depends on whether or not doxygen was
-# compiled with the --with-libclang option.
+# generated with the -Duse-libclang=ON option for CMake.
# The default value is: NO.
CLANG_ASSISTED_PARSING = NO
@@ -1061,7 +1150,7 @@ IGNORE_PREFIX =
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
-# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
# The default value is: YES.
GENERATE_HTML = YES
@@ -1127,10 +1216,10 @@ HTML_STYLESHEET =
# cascading style sheets that are included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
-# standard style sheet and is therefor more robust against future updates.
+# standard style sheet and is therefore more robust against future updates.
# Doxygen will copy the style sheet files to the output directory.
-# Note: The order of the extra stylesheet files is of importance (e.g. the last
-# stylesheet in the list overrules the setting of the previous ones in the
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
@@ -1147,7 +1236,7 @@ HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
-# will adjust the colors in the stylesheet and background images according to
+# will adjust the colors in the style sheet and background images according to
# this color. Hue is specified as an angle on a colorwheel, see
# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
@@ -1178,8 +1267,9 @@ HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
-# to NO can help when comparing the output of multiple runs.
-# The default value is: YES.
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = YES
@@ -1275,28 +1365,28 @@ GENERATE_HTMLHELP = NO
CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
-# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
# doxygen will try to run the HTML help compiler on the generated index.hhp.
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION =
-# The GENERATE_CHI flag controls if a separate .chi index file is generated (
-# YES) or that it should be included in the master .chm file ( NO).
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
GENERATE_CHI = NO
-# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_INDEX_ENCODING =
-# The BINARY_TOC flag controls whether a binary table of contents is generated (
-# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
@@ -1410,7 +1500,7 @@ DISABLE_INDEX = NO
# index structure (just like the one that is generated for HTML Help). For this
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
-# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
# further fine-tune the look of the index. As an example, the default style
# sheet generated by doxygen has an example that shows how to put an image at
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
@@ -1438,7 +1528,7 @@ ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
-# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
# external symbols imported via tag files in a separate window.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
@@ -1467,7 +1557,7 @@ FORMULA_TRANSPARENT = YES
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
# http://www.mathjax.org) which uses client side Javascript for the rendering
-# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
# to it using the MATHJAX_RELPATH option.
@@ -1553,7 +1643,7 @@ SERVER_BASED_SEARCH = NO
# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
# search results.
#
-# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: http://xapian.org/).
#
@@ -1566,7 +1656,7 @@ EXTERNAL_SEARCH = NO
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
# which will return the search results when EXTERNAL_SEARCH is enabled.
#
-# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: http://xapian.org/). See the section "External Indexing and
# Searching" for details.
@@ -1604,7 +1694,7 @@ EXTRA_SEARCH_MAPPINGS =
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
-# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
# The default value is: YES.
GENERATE_LATEX = NO
@@ -1635,7 +1725,7 @@ LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
-# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
@@ -1650,12 +1740,15 @@ COMPACT_LATEX = NO
# The default value is: a4.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-PAPER_TYPE = a4wide
+PAPER_TYPE = a4
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
-# that should be included in the LaTeX output. To get the times font for
-# instance you can specify
-# EXTRA_PACKAGES=times
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
@@ -1670,9 +1763,9 @@ EXTRA_PACKAGES =
# Note: Only use a user-defined header if you know what you are doing! The
# following commands have a special meaning inside the header: $title,
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
-# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
-# for the replacement values of the other commands the user is refered to
-# HTML_HEADER.
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
@@ -1688,6 +1781,17 @@ LATEX_HEADER =
LATEX_FOOTER =
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output
# directory. Note that the files will be copied as-is; there are no commands or
@@ -1703,15 +1807,15 @@ LATEX_EXTRA_FILES =
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-PDF_HYPERLINKS = NO
+PDF_HYPERLINKS = YES
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
-# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
# higher quality PDF documentation.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-USE_PDFLATEX = NO
+USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
# command to the generated LaTeX files. This will instruct LaTeX to keep running
@@ -1747,11 +1851,19 @@ LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
-# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
# RTF output is optimized for Word 97 and may not look too pretty with other RTF
# readers/editors.
# The default value is: NO.
@@ -1766,7 +1878,7 @@ GENERATE_RTF = NO
RTF_OUTPUT = rtf
-# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
@@ -1803,11 +1915,21 @@ RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE = NO
+
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
-# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
# classes and files.
# The default value is: NO.
@@ -1851,7 +1973,7 @@ MAN_LINKS = NO
# Configuration options related to the XML output
#---------------------------------------------------------------------------
-# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
# captures the structure of the code including all documentation.
# The default value is: NO.
@@ -1865,7 +1987,7 @@ GENERATE_XML = NO
XML_OUTPUT = xml
-# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to
# the XML output. Note that enabling this will significantly increase the size
# of the XML output.
@@ -1878,7 +2000,7 @@ XML_PROGRAMLISTING = YES
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
-# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
# that can be used to generate PDF.
# The default value is: NO.
@@ -1892,7 +2014,7 @@ GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
-# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
# program listings (including syntax highlighting and cross-referencing
# information) to the DOCBOOK output. Note that enabling this will significantly
# increase the size of the DOCBOOK output.
@@ -1905,10 +2027,10 @@ DOCBOOK_PROGRAMLISTING = NO
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
-# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
-# Definitions (see http://autogen.sf.net) file that captures the structure of
-# the code including all documentation. Note that this feature is still
-# experimental and incomplete at the moment.
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sf.net) file that captures the
+# structure of the code including all documentation. Note that this feature is
+# still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_AUTOGEN_DEF = NO
@@ -1917,7 +2039,7 @@ GENERATE_AUTOGEN_DEF = NO
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
-# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
# file that captures the structure of the code including all documentation.
#
# Note that this feature is still experimental and incomplete at the moment.
@@ -1925,7 +2047,7 @@ GENERATE_AUTOGEN_DEF = NO
GENERATE_PERLMOD = NO
-# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
# output from the Perl module output.
# The default value is: NO.
@@ -1933,9 +2055,9 @@ GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
# formatted so it can be parsed by a human reader. This is useful if you want to
-# understand what is going on. On the other hand, if this tag is set to NO the
+# understand what is going on. On the other hand, if this tag is set to NO, the
# size of the Perl module output will be much smaller and Perl will parse it
# just the same.
# The default value is: YES.
@@ -1955,14 +2077,14 @@ PERLMOD_MAKEVAR_PREFIX =
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
-# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
# C-preprocessor directives found in the sources and include files.
# The default value is: YES.
ENABLE_PREPROCESSING = YES
-# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
-# in the source code. If set to NO only conditional compilation will be
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
# performed. Macro expansion can be done in a controlled way by setting
# EXPAND_ONLY_PREDEF to YES.
# The default value is: NO.
@@ -1978,7 +2100,7 @@ MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
-# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
# INCLUDE_PATH will be searched if a #include is found.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
@@ -2055,20 +2177,21 @@ TAGFILES =
GENERATE_TAGFILE =
-# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
-# class index. If set to NO only the inherited external classes will be listed.
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
# The default value is: NO.
ALLEXTERNALS = NO
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
-# the modules index. If set to NO, only the current project's groups will be
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
# listed.
# The default value is: YES.
EXTERNAL_GROUPS = YES
-# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
# the related pages index. If set to NO, only the current project's pages will
# be listed.
# The default value is: YES.
@@ -2085,7 +2208,7 @@ PERL_PATH = /usr/bin/perl
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
-# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
# disabled, but it is recommended to install and use dot, since it yields more
@@ -2110,7 +2233,7 @@ MSCGEN_PATH =
DIA_PATH =
-# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
# The default value is: YES.
@@ -2183,7 +2306,7 @@ COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
# The default value is: NO.
@@ -2235,7 +2358,8 @@ INCLUDED_BY_GRAPH = YES
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable call graphs for selected
-# functions only using the \callgraph command.
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
@@ -2246,7 +2370,8 @@ CALL_GRAPH = YES
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable caller graphs for selected
-# functions only using the \callergraph command.
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
@@ -2269,13 +2394,17 @@ GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot.
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement).
# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
-# gif:cairo:gd, gif:gd, gif:gd:gd and svg.
+# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
# The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES.
@@ -2323,10 +2452,19 @@ DIAFILE_DIRS =
# PlantUML is not used or called during a preprocessing step. Doxygen will
# generate a warning when it encounters a \startuml command in this case and
# will not generate output for the diagram.
-# This tag requires that the tag HAVE_DOT is set to YES.
PLANTUML_JAR_PATH =
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
# larger than this value, doxygen will truncate the graph, which is visualized
@@ -2363,7 +2501,7 @@ MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
# this, this feature is disabled by default.
@@ -2380,7 +2518,7 @@ DOT_MULTI_TARGETS = YES
GENERATE_LEGEND = YES
-# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
# files that are used to generate the various graphs.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
diff --git a/docs/PACKAGING-GTK b/docs/PACKAGING-GTK
index 7436f238e..b81bc6162 100644
--- a/docs/PACKAGING-GTK
+++ b/docs/PACKAGING-GTK
@@ -29,11 +29,8 @@
checkouts smaller and making sure changes to one set of resources updates
the other.
- The binary that the build system produces is called "nsgtk". There is also
- a shell script called "netsurf" that will set up the environment and launch
- the nsgtk binary. Do not ship this shell script with your package. It is
- included only as a convience for launching NetSurf from the build tree.
- Instead, you should move nsgtk to /usr/bin/netsurf (or wherever your
+ The binary that the build system produces is called "nsgtk3".
+ You should install nsgtk3 to `/usr/bin/netsurf` (or wherever your
distribution's packaging policy suggests) and copy the contents of
gtk/res/ (dereferencing the symlinks, obviously) to /usr/share/netsurf (or
wherever your packaging policy suggests).
@@ -67,18 +64,19 @@
===================
You may also want to change NetSurf's user agent string to include the
- name of your distribution. The user agent string is build by a function
+ name of your distribution. The user agent string is built by a function
kept in utils/useragent.c - you'll want to change the macro called
NETSURF_UA_FORMAT_STRING. It's processed via sprintf, so keep that in
- mind when changing it. The first two printf parameters are major and minor
- version numbers, the second two are OS name (uname -s) and architecture
- (uname -m). You might want change this to something like:
+ mind when changing it. The first format parameter is the OS name (uname -s)
+ and the remainder are major and minor version numbers. You might want
+ to change this to something like:
- "NetSurf/%d.%d (%s; %s; Debian GNU/Linux)"
+ "Mozilla/5.0 (%s; Debian GNU/Linux) NetSurf/%d.%d"
- or similar. Please don't be tempted to mention Mozilla or similar - let's
- let that lie die.
+ or similar.
+ Note that the "Mozilla/5.0" prefix is a requirement to enable modern
+ web standards on many websites. It should not be removed or modified.
Home page URL
===============
diff --git a/docs/UnimplementedJavascript.md b/docs/UnimplementedJavascript.md
new file mode 100644
index 000000000..0d21dc852
--- /dev/null
+++ b/docs/UnimplementedJavascript.md
@@ -0,0 +1,1549 @@
+Unimplemented javascript bindings {#unimplemented}
+=================================
+
+This is a list of all the binding methods, getters and setters without an implementation in a binding.
+
+Type | Unimplemented binding
+---- | ---------------------
+method | URLSearchParams::append();
+method | URLSearchParams::delete();
+method | URLSearchParams::get();
+method | URLSearchParams::getAll();
+method | URLSearchParams::has();
+method | URLSearchParams::set();
+method | URL::domainToASCII();
+method | URL::domainToUnicode();
+getter | URL::href(user);
+setter | URL::href(user);
+getter | URL::origin(user);
+getter | URL::protocol(user);
+setter | URL::protocol(user);
+getter | URL::username(user);
+setter | URL::username(user);
+getter | URL::password(user);
+setter | URL::password(user);
+getter | URL::host(user);
+setter | URL::host(user);
+getter | URL::hostname(user);
+setter | URL::hostname(user);
+getter | URL::port(user);
+setter | URL::port(user);
+getter | URL::pathname(user);
+setter | URL::pathname(user);
+getter | URL::search(user);
+setter | URL::search(user);
+getter | URL::hash(user);
+setter | URL::hash(user);
+getter | URL::searchParams(user);
+setter | URL::searchParams(user);
+getter | Event::timeStamp(user);
+method | MutationEvent::initMutationEvent();
+getter | MutationEvent::relatedNode(user);
+getter | MutationEvent::prevValue(string);
+getter | MutationEvent::newValue(string);
+getter | MutationEvent::attrName(string);
+getter | MutationEvent::attrChange(unsigned short);
+method | UIEvent::initUIEvent();
+getter | UIEvent::view(user);
+getter | UIEvent::detail(long);
+method | CompositionEvent::initCompositionEvent();
+getter | CompositionEvent::data(string);
+method | KeyboardEvent::initKeyboardEvent();
+getter | KeyboardEvent::repeat(boolean);
+getter | KeyboardEvent::isComposing(boolean);
+getter | KeyboardEvent::charCode(unsigned long);
+getter | KeyboardEvent::keyCode(unsigned long);
+getter | KeyboardEvent::which(unsigned long);
+method | MouseEvent::getModifierState();
+method | MouseEvent::initMouseEvent();
+getter | MouseEvent::region(string);
+getter | MouseEvent::screenX(long);
+getter | MouseEvent::screenY(long);
+getter | MouseEvent::clientX(long);
+getter | MouseEvent::clientY(long);
+getter | MouseEvent::ctrlKey(boolean);
+getter | MouseEvent::shiftKey(boolean);
+getter | MouseEvent::altKey(boolean);
+getter | MouseEvent::metaKey(boolean);
+getter | MouseEvent::button(short);
+getter | MouseEvent::relatedTarget(user);
+getter | MouseEvent::buttons(unsigned short);
+method | WheelEvent::initWheelEvent();
+getter | WheelEvent::deltaX(double);
+getter | WheelEvent::deltaY(double);
+getter | WheelEvent::deltaZ(double);
+getter | WheelEvent::deltaMode(unsigned long);
+method | FocusEvent::initFocusEvent();
+getter | FocusEvent::relatedTarget(user);
+method | CSS::escape();
+getter | PseudoElement::cascadedStyle(user);
+getter | PseudoElement::defaultStyle(user);
+getter | PseudoElement::rawComputedStyle(user);
+getter | PseudoElement::usedStyle(user);
+getter | SVGElement::style(user);
+method | CSSStyleDeclaration::item();
+method | CSSStyleDeclaration::getPropertyValue();
+method | CSSStyleDeclaration::getPropertyPriority();
+method | CSSStyleDeclaration::setProperty();
+method | CSSStyleDeclaration::setPropertyValue();
+method | CSSStyleDeclaration::setPropertyPriority();
+method | CSSStyleDeclaration::removeProperty();
+getter | CSSStyleDeclaration::cssText(string);
+setter | CSSStyleDeclaration::cssText(string);
+getter | CSSStyleDeclaration::length(unsigned long);
+getter | CSSStyleDeclaration::parentRule(user);
+getter | CSSStyleDeclaration::cssFloat(string);
+setter | CSSStyleDeclaration::cssFloat(string);
+getter | CSSStyleDeclaration::dashed_attribute(string);
+setter | CSSStyleDeclaration::dashed_attribute(string);
+getter | CSSRule::type(unsigned short);
+getter | CSSRule::cssText(string);
+setter | CSSRule::cssText(string);
+getter | CSSRule::parentRule(user);
+getter | CSSRule::parentStyleSheet(user);
+getter | CSSNamespaceRule::namespaceURI(string);
+getter | CSSNamespaceRule::prefix(string);
+getter | CSSMarginRule::name(string);
+getter | CSSMarginRule::style(user);
+method | CSSGroupingRule::insertRule();
+method | CSSGroupingRule::deleteRule();
+getter | CSSGroupingRule::cssRules(user);
+getter | CSSPageRule::selectorText(string);
+setter | CSSPageRule::selectorText(string);
+getter | CSSPageRule::style(user);
+getter | CSSMediaRule::media(user);
+getter | CSSImportRule::href(string);
+getter | CSSImportRule::media(user);
+getter | CSSImportRule::styleSheet(user);
+getter | CSSStyleRule::selectorText(string);
+setter | CSSStyleRule::selectorText(string);
+getter | CSSStyleRule::style(user);
+method | CSSRuleList::item();
+getter | CSSRuleList::length(unsigned long);
+method | StyleSheetList::item();
+getter | StyleSheetList::length(unsigned long);
+getter | StyleSheet::type(string);
+getter | StyleSheet::href(string);
+getter | StyleSheet::ownerNode(multiple);
+getter | StyleSheet::parentStyleSheet(user);
+getter | StyleSheet::title(string);
+getter | StyleSheet::media(user);
+getter | StyleSheet::disabled(boolean);
+setter | StyleSheet::disabled(boolean);
+method | CSSStyleSheet::insertRule();
+method | CSSStyleSheet::deleteRule();
+getter | CSSStyleSheet::ownerRule(user);
+getter | CSSStyleSheet::cssRules(user);
+method | MediaList::item();
+method | MediaList::appendMedium();
+method | MediaList::deleteMedium();
+getter | MediaList::mediaText(string);
+setter | MediaList::mediaText(string);
+getter | MediaList::length(unsigned long);
+method | Element::hasAttributes();
+method | Element::getAttributeNS();
+method | Element::setAttributeNS();
+method | Element::removeAttributeNS();
+method | Element::hasAttributeNS();
+method | Element::getAttributeNode();
+method | Element::getAttributeNodeNS();
+method | Element::setAttributeNode();
+method | Element::setAttributeNodeNS();
+method | Element::removeAttributeNode();
+method | Element::closest();
+method | Element::matches();
+method | Element::getElementsByTagNameNS();
+method | Element::getElementsByClassName();
+method | Element::insertAdjacentHTML();
+method | Element::pseudo();
+method | Element::prepend();
+method | Element::append();
+method | Element::query();
+method | Element::queryAll();
+method | Element::querySelector();
+method | Element::querySelectorAll();
+method | Element::before();
+method | Element::after();
+method | Element::replaceWith();
+method | Element::remove();
+getter | Element::namespaceURI(string);
+getter | Element::prefix(string);
+getter | Element::localName(string);
+getter | Element::tagName(string);
+getter | Element::outerHTML(string);
+setter | Element::outerHTML(string);
+getter | Element::children(user);
+getter | Element::cascadedStyle(user);
+getter | Element::defaultStyle(user);
+getter | Element::rawComputedStyle(user);
+getter | Element::usedStyle(user);
+method | HTMLElement::click();
+method | HTMLElement::focus();
+method | HTMLElement::blur();
+method | HTMLElement::forceSpellCheck();
+getter | HTMLElement::translate(boolean);
+setter | HTMLElement::translate(boolean);
+getter | HTMLElement::dataset(user);
+getter | HTMLElement::hidden(boolean);
+setter | HTMLElement::hidden(boolean);
+getter | HTMLElement::tabIndex(long);
+setter | HTMLElement::tabIndex(long);
+getter | HTMLElement::accessKey(string);
+setter | HTMLElement::accessKey(string);
+getter | HTMLElement::accessKeyLabel(string);
+getter | HTMLElement::draggable(boolean);
+setter | HTMLElement::draggable(boolean);
+getter | HTMLElement::dropzone(user);
+getter | HTMLElement::contextMenu(user);
+setter | HTMLElement::contextMenu(user);
+getter | HTMLElement::spellcheck(boolean);
+setter | HTMLElement::spellcheck(boolean);
+getter | HTMLElement::commandType(string);
+getter | HTMLElement::commandLabel(string);
+getter | HTMLElement::commandIcon(string);
+getter | HTMLElement::commandHidden(boolean);
+getter | HTMLElement::commandDisabled(boolean);
+getter | HTMLElement::commandChecked(boolean);
+getter | HTMLElement::onerror(user);
+setter | HTMLElement::onerror(user);
+getter | HTMLElement::contentEditable(string);
+setter | HTMLElement::contentEditable(string);
+getter | HTMLElement::isContentEditable(boolean);
+getter | HTMLDirectoryElement::compact(boolean);
+setter | HTMLDirectoryElement::compact(boolean);
+getter | HTMLFrameElement::contentDocument(user);
+getter | HTMLFrameElement::contentWindow(user);
+method | HTMLMarqueeElement::start();
+method | HTMLMarqueeElement::stop();
+getter | HTMLMarqueeElement::behavior(string);
+setter | HTMLMarqueeElement::behavior(string);
+getter | HTMLMarqueeElement::bgColor(string);
+setter | HTMLMarqueeElement::bgColor(string);
+getter | HTMLMarqueeElement::direction(string);
+setter | HTMLMarqueeElement::direction(string);
+getter | HTMLMarqueeElement::height(string);
+setter | HTMLMarqueeElement::height(string);
+getter | HTMLMarqueeElement::hspace(unsigned long);
+setter | HTMLMarqueeElement::hspace(unsigned long);
+getter | HTMLMarqueeElement::loop(long);
+setter | HTMLMarqueeElement::loop(long);
+getter | HTMLMarqueeElement::scrollAmount(unsigned long);
+setter | HTMLMarqueeElement::scrollAmount(unsigned long);
+getter | HTMLMarqueeElement::scrollDelay(unsigned long);
+setter | HTMLMarqueeElement::scrollDelay(unsigned long);
+getter | HTMLMarqueeElement::trueSpeed(boolean);
+setter | HTMLMarqueeElement::trueSpeed(boolean);
+getter | HTMLMarqueeElement::vspace(unsigned long);
+setter | HTMLMarqueeElement::vspace(unsigned long);
+getter | HTMLMarqueeElement::width(string);
+setter | HTMLMarqueeElement::width(string);
+getter | HTMLMarqueeElement::onbounce(user);
+setter | HTMLMarqueeElement::onbounce(user);
+getter | HTMLMarqueeElement::onfinish(user);
+setter | HTMLMarqueeElement::onfinish(user);
+getter | HTMLMarqueeElement::onstart(user);
+setter | HTMLMarqueeElement::onstart(user);
+getter | HTMLAppletElement::hspace(unsigned long);
+setter | HTMLAppletElement::hspace(unsigned long);
+getter | HTMLAppletElement::vspace(unsigned long);
+setter | HTMLAppletElement::vspace(unsigned long);
+getter | StorageEvent::key(string);
+getter | StorageEvent::oldValue(string);
+getter | StorageEvent::newValue(string);
+getter | StorageEvent::url(string);
+getter | StorageEvent::storageArea(user);
+method | Storage::key();
+method | Storage::getItem();
+method | Storage::setItem();
+method | Storage::removeItem();
+method | Storage::clear();
+getter | Storage::length(unsigned long);
+getter | WorkerLocation::href(user);
+getter | WorkerLocation::origin(user);
+getter | WorkerLocation::protocol(user);
+getter | WorkerLocation::host(user);
+getter | WorkerLocation::hostname(user);
+getter | WorkerLocation::port(user);
+getter | WorkerLocation::pathname(user);
+getter | WorkerLocation::search(user);
+getter | WorkerLocation::hash(user);
+method | WorkerNavigator::taintEnabled();
+getter | WorkerNavigator::appCodeName(string);
+getter | WorkerNavigator::appName(string);
+getter | WorkerNavigator::appVersion(string);
+getter | WorkerNavigator::platform(string);
+getter | WorkerNavigator::product(string);
+getter | WorkerNavigator::productSub(string);
+getter | WorkerNavigator::userAgent(string);
+getter | WorkerNavigator::vendor(string);
+getter | WorkerNavigator::vendorSub(string);
+getter | WorkerNavigator::language(string);
+getter | WorkerNavigator::languages(string);
+getter | WorkerNavigator::onLine(boolean);
+getter | SharedWorker::port(user);
+getter | SharedWorker::onerror(user);
+setter | SharedWorker::onerror(user);
+method | Worker::terminate();
+method | Worker::postMessage();
+getter | Worker::onmessage(user);
+setter | Worker::onmessage(user);
+getter | Worker::onerror(user);
+setter | Worker::onerror(user);
+method | WorkerGlobalScope::importScripts();
+method | WorkerGlobalScope::close();
+method | WorkerGlobalScope::btoa();
+method | WorkerGlobalScope::atob();
+method | WorkerGlobalScope::setTimeout();
+method | WorkerGlobalScope::clearTimeout();
+method | WorkerGlobalScope::setInterval();
+method | WorkerGlobalScope::clearInterval();
+method | WorkerGlobalScope::createImageBitmap();
+getter | WorkerGlobalScope::self(user);
+getter | WorkerGlobalScope::location(user);
+getter | WorkerGlobalScope::navigator(user);
+getter | WorkerGlobalScope::onerror(user);
+setter | WorkerGlobalScope::onerror(user);
+getter | WorkerGlobalScope::onlanguagechange(user);
+setter | WorkerGlobalScope::onlanguagechange(user);
+getter | WorkerGlobalScope::onoffline(user);
+setter | WorkerGlobalScope::onoffline(user);
+getter | WorkerGlobalScope::ononline(user);
+setter | WorkerGlobalScope::ononline(user);
+getter | SharedWorkerGlobalScope::name(string);
+getter | SharedWorkerGlobalScope::applicationCache(user);
+getter | SharedWorkerGlobalScope::onconnect(user);
+setter | SharedWorkerGlobalScope::onconnect(user);
+method | DedicatedWorkerGlobalScope::postMessage();
+getter | DedicatedWorkerGlobalScope::onmessage(user);
+setter | DedicatedWorkerGlobalScope::onmessage(user);
+method | BroadcastChannel::postMessage();
+method | BroadcastChannel::close();
+getter | BroadcastChannel::name(string);
+getter | BroadcastChannel::onmessage(user);
+setter | BroadcastChannel::onmessage(user);
+method | MessagePort::postMessage();
+method | MessagePort::start();
+method | MessagePort::close();
+getter | MessagePort::onmessage(user);
+setter | MessagePort::onmessage(user);
+getter | MessageChannel::port1(user);
+getter | MessageChannel::port2(user);
+getter | CloseEvent::wasClean(boolean);
+getter | CloseEvent::code(unsigned short);
+getter | CloseEvent::reason(string);
+method | WebSocket::close();
+method | WebSocket::send();
+getter | WebSocket::url(string);
+getter | WebSocket::readyState(unsigned short);
+getter | WebSocket::bufferedAmount(unsigned long);
+getter | WebSocket::onopen(user);
+setter | WebSocket::onopen(user);
+getter | WebSocket::onerror(user);
+setter | WebSocket::onerror(user);
+getter | WebSocket::onclose(user);
+setter | WebSocket::onclose(user);
+getter | WebSocket::extensions(string);
+getter | WebSocket::protocol(string);
+getter | WebSocket::onmessage(user);
+setter | WebSocket::onmessage(user);
+getter | WebSocket::binaryType(user);
+setter | WebSocket::binaryType(user);
+method | EventSource::close();
+getter | EventSource::url(string);
+getter | EventSource::withCredentials(boolean);
+getter | EventSource::readyState(unsigned short);
+getter | EventSource::onopen(user);
+setter | EventSource::onopen(user);
+getter | EventSource::onmessage(user);
+setter | EventSource::onmessage(user);
+getter | EventSource::onerror(user);
+setter | EventSource::onerror(user);
+method | MessageEvent::initMessageEvent();
+getter | MessageEvent::data(any);
+getter | MessageEvent::origin(string);
+getter | MessageEvent::lastEventId(string);
+getter | MessageEvent::source(multiple);
+getter | MessageEvent::ports(user);
+getter | ImageBitmap::width(unsigned long);
+getter | ImageBitmap::height(unsigned long);
+method | External::AddSearchProvider();
+method | External::IsSearchProviderInstalled();
+getter | MimeType::type(string);
+getter | MimeType::description(string);
+getter | MimeType::suffixes(string);
+getter | MimeType::enabledPlugin(user);
+method | Plugin::item();
+method | Plugin::namedItem();
+getter | Plugin::name(string);
+getter | Plugin::description(string);
+getter | Plugin::filename(string);
+getter | Plugin::length(unsigned long);
+method | MimeTypeArray::item();
+method | MimeTypeArray::namedItem();
+getter | MimeTypeArray::length(unsigned long);
+method | PluginArray::refresh();
+method | PluginArray::item();
+method | PluginArray::namedItem();
+getter | PluginArray::length(unsigned long);
+method | Navigator::registerProtocolHandler();
+method | Navigator::registerContentHandler();
+method | Navigator::isProtocolHandlerRegistered();
+method | Navigator::isContentHandlerRegistered();
+method | Navigator::unregisterProtocolHandler();
+method | Navigator::unregisterContentHandler();
+method | Navigator::yieldForStorageUpdates();
+getter | Navigator::language(string);
+getter | Navigator::languages(string);
+getter | Navigator::onLine(boolean);
+getter | Navigator::plugins(user);
+getter | Navigator::mimeTypes(user);
+getter | ErrorEvent::message(string);
+getter | ErrorEvent::filename(string);
+getter | ErrorEvent::lineno(unsigned long);
+getter | ErrorEvent::colno(unsigned long);
+getter | ErrorEvent::error(any);
+method | ApplicationCache::update();
+method | ApplicationCache::abort();
+method | ApplicationCache::swapCache();
+getter | ApplicationCache::status(unsigned short);
+getter | ApplicationCache::onchecking(user);
+setter | ApplicationCache::onchecking(user);
+getter | ApplicationCache::onerror(user);
+setter | ApplicationCache::onerror(user);
+getter | ApplicationCache::onnoupdate(user);
+setter | ApplicationCache::onnoupdate(user);
+getter | ApplicationCache::ondownloading(user);
+setter | ApplicationCache::ondownloading(user);
+getter | ApplicationCache::onprogress(user);
+setter | ApplicationCache::onprogress(user);
+getter | ApplicationCache::onupdateready(user);
+setter | ApplicationCache::onupdateready(user);
+getter | ApplicationCache::oncached(user);
+setter | ApplicationCache::oncached(user);
+getter | ApplicationCache::onobsolete(user);
+setter | ApplicationCache::onobsolete(user);
+getter | BeforeUnloadEvent::returnValue(string);
+setter | BeforeUnloadEvent::returnValue(string);
+getter | PageTransitionEvent::persisted(boolean);
+getter | HashChangeEvent::oldURL(string);
+getter | HashChangeEvent::newURL(string);
+getter | PopStateEvent::state(any);
+getter | Location::ancestorOrigins(string);
+setter | Location::protocol(user);
+setter | Location::username(user);
+setter | Location::password(user);
+setter | Location::host(user);
+setter | Location::hostname(user);
+setter | Location::port(user);
+setter | Location::pathname(user);
+setter | Location::search(user);
+setter | Location::hash(user);
+method | History::go();
+method | History::back();
+method | History::forward();
+method | History::pushState();
+method | History::replaceState();
+getter | History::length(unsigned long);
+getter | History::state(any);
+getter | BarProp::visible(boolean);
+method | Window::close();
+method | Window::stop();
+method | Window::focus();
+method | Window::blur();
+method | Window::open();
+method | Window::confirm();
+method | Window::prompt();
+method | Window::print();
+method | Window::showModalDialog();
+method | Window::requestAnimationFrame();
+method | Window::cancelAnimationFrame();
+method | Window::postMessage();
+method | Window::captureEvents();
+method | Window::releaseEvents();
+method | Window::getComputedStyle();
+method | Window::btoa();
+method | Window::atob();
+method | Window::createImageBitmap();
+getter | Window::self(user);
+getter | Window::history(user);
+getter | Window::locationbar(user);
+getter | Window::menubar(user);
+getter | Window::personalbar(user);
+getter | Window::scrollbars(user);
+getter | Window::statusbar(user);
+getter | Window::toolbar(user);
+getter | Window::status(string);
+setter | Window::status(string);
+getter | Window::closed(boolean);
+getter | Window::frames(user);
+getter | Window::length(unsigned long);
+getter | Window::top(user);
+getter | Window::opener(any);
+setter | Window::opener(any);
+getter | Window::parent(user);
+getter | Window::frameElement(user);
+getter | Window::external(user);
+getter | Window::applicationCache(user);
+getter | Window::sessionStorage(user);
+getter | Window::localStorage(user);
+getter | DragEvent::dataTransfer(user);
+method | DataTransferItem::getAsString();
+method | DataTransferItem::getAsFile();
+getter | DataTransferItem::kind(string);
+getter | DataTransferItem::type(string);
+method | DataTransferItemList::add();
+method | DataTransferItemList::remove();
+method | DataTransferItemList::clear();
+getter | DataTransferItemList::length(unsigned long);
+method | DataTransfer::setDragImage();
+method | DataTransfer::getData();
+method | DataTransfer::setData();
+method | DataTransfer::clearData();
+getter | DataTransfer::dropEffect(string);
+setter | DataTransfer::dropEffect(string);
+getter | DataTransfer::effectAllowed(string);
+setter | DataTransfer::effectAllowed(string);
+getter | DataTransfer::items(user);
+getter | DataTransfer::types(string);
+getter | DataTransfer::files(user);
+getter | Touch::region(string);
+method | Path2D::addPath();
+method | Path2D::addPathByStrokingPath();
+method | Path2D::addText();
+method | Path2D::addPathByStrokingText();
+method | Path2D::closePath();
+method | Path2D::moveTo();
+method | Path2D::lineTo();
+method | Path2D::quadraticCurveTo();
+method | Path2D::bezierCurveTo();
+method | Path2D::arcTo();
+method | Path2D::rect();
+method | Path2D::arc();
+method | Path2D::ellipse();
+method | DrawingStyle::setLineDash();
+method | DrawingStyle::getLineDash();
+getter | DrawingStyle::lineWidth(double);
+setter | DrawingStyle::lineWidth(double);
+getter | DrawingStyle::lineCap(string);
+setter | DrawingStyle::lineCap(string);
+getter | DrawingStyle::lineJoin(string);
+setter | DrawingStyle::lineJoin(string);
+getter | DrawingStyle::miterLimit(double);
+setter | DrawingStyle::miterLimit(double);
+getter | DrawingStyle::lineDashOffset(double);
+setter | DrawingStyle::lineDashOffset(double);
+getter | DrawingStyle::font(string);
+setter | DrawingStyle::font(string);
+getter | DrawingStyle::textAlign(string);
+setter | DrawingStyle::textAlign(string);
+getter | DrawingStyle::textBaseline(string);
+setter | DrawingStyle::textBaseline(string);
+getter | DrawingStyle::direction(string);
+setter | DrawingStyle::direction(string);
+getter | TextMetrics::width(double);
+getter | TextMetrics::actualBoundingBoxLeft(double);
+getter | TextMetrics::actualBoundingBoxRight(double);
+getter | TextMetrics::fontBoundingBoxAscent(double);
+getter | TextMetrics::fontBoundingBoxDescent(double);
+getter | TextMetrics::actualBoundingBoxAscent(double);
+getter | TextMetrics::actualBoundingBoxDescent(double);
+getter | TextMetrics::emHeightAscent(double);
+getter | TextMetrics::emHeightDescent(double);
+getter | TextMetrics::hangingBaseline(double);
+getter | TextMetrics::alphabeticBaseline(double);
+getter | TextMetrics::ideographicBaseline(double);
+method | CanvasPattern::setTransform();
+method | CanvasGradient::addColorStop();
+method | CanvasRenderingContext2D::commit();
+method | CanvasRenderingContext2D::save();
+method | CanvasRenderingContext2D::restore();
+method | CanvasRenderingContext2D::scale();
+method | CanvasRenderingContext2D::rotate();
+method | CanvasRenderingContext2D::translate();
+method | CanvasRenderingContext2D::transform();
+method | CanvasRenderingContext2D::setTransform();
+method | CanvasRenderingContext2D::resetTransform();
+method | CanvasRenderingContext2D::createLinearGradient();
+method | CanvasRenderingContext2D::createRadialGradient();
+method | CanvasRenderingContext2D::createPattern();
+method | CanvasRenderingContext2D::clearRect();
+method | CanvasRenderingContext2D::fillRect();
+method | CanvasRenderingContext2D::strokeRect();
+method | CanvasRenderingContext2D::beginPath();
+method | CanvasRenderingContext2D::fill();
+method | CanvasRenderingContext2D::stroke();
+method | CanvasRenderingContext2D::drawFocusIfNeeded();
+method | CanvasRenderingContext2D::scrollPathIntoView();
+method | CanvasRenderingContext2D::clip();
+method | CanvasRenderingContext2D::resetClip();
+method | CanvasRenderingContext2D::isPointInPath();
+method | CanvasRenderingContext2D::isPointInStroke();
+method | CanvasRenderingContext2D::fillText();
+method | CanvasRenderingContext2D::strokeText();
+method | CanvasRenderingContext2D::measureText();
+method | CanvasRenderingContext2D::drawImage();
+method | CanvasRenderingContext2D::addHitRegion();
+method | CanvasRenderingContext2D::removeHitRegion();
+method | CanvasRenderingContext2D::clearHitRegions();
+method | CanvasRenderingContext2D::setLineDash();
+method | CanvasRenderingContext2D::getLineDash();
+method | CanvasRenderingContext2D::closePath();
+method | CanvasRenderingContext2D::moveTo();
+method | CanvasRenderingContext2D::lineTo();
+method | CanvasRenderingContext2D::quadraticCurveTo();
+method | CanvasRenderingContext2D::bezierCurveTo();
+method | CanvasRenderingContext2D::arcTo();
+method | CanvasRenderingContext2D::rect();
+method | CanvasRenderingContext2D::arc();
+method | CanvasRenderingContext2D::ellipse();
+getter | CanvasRenderingContext2D::currentTransform(user);
+setter | CanvasRenderingContext2D::currentTransform(user);
+getter | CanvasRenderingContext2D::globalAlpha(double);
+setter | CanvasRenderingContext2D::globalAlpha(double);
+getter | CanvasRenderingContext2D::globalCompositeOperation(string);
+setter | CanvasRenderingContext2D::globalCompositeOperation(string);
+getter | CanvasRenderingContext2D::imageSmoothingEnabled(boolean);
+setter | CanvasRenderingContext2D::imageSmoothingEnabled(boolean);
+getter | CanvasRenderingContext2D::imageSmoothingQuality(user);
+setter | CanvasRenderingContext2D::imageSmoothingQuality(user);
+getter | CanvasRenderingContext2D::strokeStyle(multiple);
+setter | CanvasRenderingContext2D::strokeStyle(multiple);
+getter | CanvasRenderingContext2D::fillStyle(multiple);
+setter | CanvasRenderingContext2D::fillStyle(multiple);
+getter | CanvasRenderingContext2D::shadowOffsetX(double);
+setter | CanvasRenderingContext2D::shadowOffsetX(double);
+getter | CanvasRenderingContext2D::shadowOffsetY(double);
+setter | CanvasRenderingContext2D::shadowOffsetY(double);
+getter | CanvasRenderingContext2D::shadowBlur(double);
+setter | CanvasRenderingContext2D::shadowBlur(double);
+getter | CanvasRenderingContext2D::shadowColor(string);
+setter | CanvasRenderingContext2D::shadowColor(string);
+getter | CanvasRenderingContext2D::lineWidth(double);
+setter | CanvasRenderingContext2D::lineWidth(double);
+getter | CanvasRenderingContext2D::lineCap(string);
+setter | CanvasRenderingContext2D::lineCap(string);
+getter | CanvasRenderingContext2D::lineJoin(string);
+setter | CanvasRenderingContext2D::lineJoin(string);
+getter | CanvasRenderingContext2D::miterLimit(double);
+setter | CanvasRenderingContext2D::miterLimit(double);
+getter | CanvasRenderingContext2D::lineDashOffset(double);
+setter | CanvasRenderingContext2D::lineDashOffset(double);
+getter | CanvasRenderingContext2D::font(string);
+setter | CanvasRenderingContext2D::font(string);
+getter | CanvasRenderingContext2D::textAlign(string);
+setter | CanvasRenderingContext2D::textAlign(string);
+getter | CanvasRenderingContext2D::textBaseline(string);
+setter | CanvasRenderingContext2D::textBaseline(string);
+getter | CanvasRenderingContext2D::direction(string);
+setter | CanvasRenderingContext2D::direction(string);
+method | CanvasProxy::setContext();
+method | HTMLCanvasElement::probablySupportsContext();
+method | HTMLCanvasElement::setContext();
+method | HTMLCanvasElement::transferControlToProxy();
+method | HTMLCanvasElement::toDataURL();
+method | HTMLCanvasElement::toBlob();
+getter | HTMLTemplateElement::content(user);
+getter | HTMLScriptElement::async(boolean);
+setter | HTMLScriptElement::async(boolean);
+getter | HTMLScriptElement::crossOrigin(string);
+setter | HTMLScriptElement::crossOrigin(string);
+getter | HTMLScriptElement::nonce(string);
+setter | HTMLScriptElement::nonce(string);
+method | HTMLDialogElement::show();
+method | HTMLDialogElement::showModal();
+method | HTMLDialogElement::close();
+getter | HTMLDialogElement::open(boolean);
+setter | HTMLDialogElement::open(boolean);
+getter | HTMLDialogElement::returnValue(string);
+setter | HTMLDialogElement::returnValue(string);
+getter | RelatedEvent::relatedTarget(user);
+getter | HTMLMenuItemElement::type(string);
+setter | HTMLMenuItemElement::type(string);
+getter | HTMLMenuItemElement::label(string);
+setter | HTMLMenuItemElement::label(string);
+getter | HTMLMenuItemElement::icon(string);
+setter | HTMLMenuItemElement::icon(string);
+getter | HTMLMenuItemElement::disabled(boolean);
+setter | HTMLMenuItemElement::disabled(boolean);
+getter | HTMLMenuItemElement::checked(boolean);
+setter | HTMLMenuItemElement::checked(boolean);
+getter | HTMLMenuItemElement::radiogroup(string);
+setter | HTMLMenuItemElement::radiogroup(string);
+getter | HTMLMenuItemElement::default(boolean);
+setter | HTMLMenuItemElement::default(boolean);
+getter | HTMLMenuItemElement::command(user);
+getter | HTMLMenuElement::type(string);
+setter | HTMLMenuElement::type(string);
+getter | HTMLMenuElement::label(string);
+setter | HTMLMenuElement::label(string);
+getter | HTMLDetailsElement::open(boolean);
+setter | HTMLDetailsElement::open(boolean);
+getter | ValidityState::valueMissing(boolean);
+getter | ValidityState::typeMismatch(boolean);
+getter | ValidityState::patternMismatch(boolean);
+getter | ValidityState::tooLong(boolean);
+getter | ValidityState::tooShort(boolean);
+getter | ValidityState::rangeUnderflow(boolean);
+getter | ValidityState::rangeOverflow(boolean);
+getter | ValidityState::stepMismatch(boolean);
+getter | ValidityState::badInput(boolean);
+getter | ValidityState::customError(boolean);
+getter | ValidityState::valid(boolean);
+getter | AutocompleteErrorEvent::reason(user);
+getter | HTMLLegendElement::form(user);
+method | HTMLFieldSetElement::checkValidity();
+method | HTMLFieldSetElement::reportValidity();
+method | HTMLFieldSetElement::setCustomValidity();
+getter | HTMLFieldSetElement::disabled(boolean);
+setter | HTMLFieldSetElement::disabled(boolean);
+getter | HTMLFieldSetElement::form(user);
+getter | HTMLFieldSetElement::name(string);
+setter | HTMLFieldSetElement::name(string);
+getter | HTMLFieldSetElement::type(string);
+getter | HTMLFieldSetElement::elements(user);
+getter | HTMLFieldSetElement::willValidate(boolean);
+getter | HTMLFieldSetElement::validity(user);
+getter | HTMLFieldSetElement::validationMessage(string);
+getter | HTMLMeterElement::value(double);
+setter | HTMLMeterElement::value(double);
+getter | HTMLMeterElement::min(double);
+setter | HTMLMeterElement::min(double);
+getter | HTMLMeterElement::max(double);
+setter | HTMLMeterElement::max(double);
+getter | HTMLMeterElement::low(double);
+setter | HTMLMeterElement::low(double);
+getter | HTMLMeterElement::high(double);
+setter | HTMLMeterElement::high(double);
+getter | HTMLMeterElement::optimum(double);
+setter | HTMLMeterElement::optimum(double);
+getter | HTMLMeterElement::labels(user);
+getter | HTMLProgressElement::value(double);
+setter | HTMLProgressElement::value(double);
+getter | HTMLProgressElement::max(double);
+setter | HTMLProgressElement::max(double);
+getter | HTMLProgressElement::position(double);
+getter | HTMLProgressElement::labels(user);
+method | HTMLOutputElement::checkValidity();
+method | HTMLOutputElement::reportValidity();
+method | HTMLOutputElement::setCustomValidity();
+getter | HTMLOutputElement::htmlFor(user);
+getter | HTMLOutputElement::form(user);
+getter | HTMLOutputElement::name(string);
+setter | HTMLOutputElement::name(string);
+getter | HTMLOutputElement::type(string);
+getter | HTMLOutputElement::defaultValue(string);
+setter | HTMLOutputElement::defaultValue(string);
+getter | HTMLOutputElement::value(string);
+setter | HTMLOutputElement::value(string);
+getter | HTMLOutputElement::willValidate(boolean);
+getter | HTMLOutputElement::validity(user);
+getter | HTMLOutputElement::validationMessage(string);
+getter | HTMLOutputElement::labels(user);
+method | HTMLKeygenElement::checkValidity();
+method | HTMLKeygenElement::reportValidity();
+method | HTMLKeygenElement::setCustomValidity();
+getter | HTMLKeygenElement::autofocus(boolean);
+setter | HTMLKeygenElement::autofocus(boolean);
+getter | HTMLKeygenElement::challenge(string);
+setter | HTMLKeygenElement::challenge(string);
+getter | HTMLKeygenElement::disabled(boolean);
+setter | HTMLKeygenElement::disabled(boolean);
+getter | HTMLKeygenElement::form(user);
+getter | HTMLKeygenElement::keytype(string);
+setter | HTMLKeygenElement::keytype(string);
+getter | HTMLKeygenElement::name(string);
+setter | HTMLKeygenElement::name(string);
+getter | HTMLKeygenElement::type(string);
+getter | HTMLKeygenElement::willValidate(boolean);
+getter | HTMLKeygenElement::validity(user);
+getter | HTMLKeygenElement::validationMessage(string);
+getter | HTMLKeygenElement::labels(user);
+method | HTMLTextAreaElement::checkValidity();
+method | HTMLTextAreaElement::reportValidity();
+method | HTMLTextAreaElement::setCustomValidity();
+method | HTMLTextAreaElement::select();
+method | HTMLTextAreaElement::setRangeText();
+method | HTMLTextAreaElement::setSelectionRange();
+getter | HTMLTextAreaElement::autocomplete(string);
+setter | HTMLTextAreaElement::autocomplete(string);
+getter | HTMLTextAreaElement::autofocus(boolean);
+setter | HTMLTextAreaElement::autofocus(boolean);
+getter | HTMLTextAreaElement::cols(unsigned long);
+setter | HTMLTextAreaElement::cols(unsigned long);
+getter | HTMLTextAreaElement::dirName(string);
+setter | HTMLTextAreaElement::dirName(string);
+getter | HTMLTextAreaElement::form(user);
+getter | HTMLTextAreaElement::inputMode(string);
+setter | HTMLTextAreaElement::inputMode(string);
+getter | HTMLTextAreaElement::maxLength(long);
+setter | HTMLTextAreaElement::maxLength(long);
+getter | HTMLTextAreaElement::minLength(long);
+setter | HTMLTextAreaElement::minLength(long);
+getter | HTMLTextAreaElement::placeholder(string);
+setter | HTMLTextAreaElement::placeholder(string);
+getter | HTMLTextAreaElement::required(boolean);
+setter | HTMLTextAreaElement::required(boolean);
+getter | HTMLTextAreaElement::rows(unsigned long);
+setter | HTMLTextAreaElement::rows(unsigned long);
+getter | HTMLTextAreaElement::wrap(string);
+setter | HTMLTextAreaElement::wrap(string);
+getter | HTMLTextAreaElement::textLength(unsigned long);
+getter | HTMLTextAreaElement::willValidate(boolean);
+getter | HTMLTextAreaElement::validity(user);
+getter | HTMLTextAreaElement::validationMessage(string);
+getter | HTMLTextAreaElement::labels(user);
+getter | HTMLTextAreaElement::selectionStart(unsigned long);
+setter | HTMLTextAreaElement::selectionStart(unsigned long);
+getter | HTMLTextAreaElement::selectionEnd(unsigned long);
+setter | HTMLTextAreaElement::selectionEnd(unsigned long);
+getter | HTMLTextAreaElement::selectionDirection(string);
+setter | HTMLTextAreaElement::selectionDirection(string);
+getter | HTMLOptionElement::form(user);
+setter | HTMLOptionElement::text(string);
+getter | HTMLOptionElement::index(long);
+getter | HTMLOptGroupElement::disabled(boolean);
+setter | HTMLOptGroupElement::disabled(boolean);
+getter | HTMLOptGroupElement::label(string);
+setter | HTMLOptGroupElement::label(string);
+getter | HTMLDataListElement::options(user);
+method | HTMLSelectElement::item();
+method | HTMLSelectElement::namedItem();
+method | HTMLSelectElement::add();
+method | HTMLSelectElement::remove();
+method | HTMLSelectElement::checkValidity();
+method | HTMLSelectElement::reportValidity();
+method | HTMLSelectElement::setCustomValidity();
+getter | HTMLSelectElement::autocomplete(string);
+setter | HTMLSelectElement::autocomplete(string);
+getter | HTMLSelectElement::autofocus(boolean);
+setter | HTMLSelectElement::autofocus(boolean);
+getter | HTMLSelectElement::form(user);
+getter | HTMLSelectElement::required(boolean);
+setter | HTMLSelectElement::required(boolean);
+getter | HTMLSelectElement::size(unsigned long);
+setter | HTMLSelectElement::size(unsigned long);
+getter | HTMLSelectElement::options(user);
+getter | HTMLSelectElement::length(unsigned long);
+setter | HTMLSelectElement::length(unsigned long);
+getter | HTMLSelectElement::selectedOptions(user);
+getter | HTMLSelectElement::selectedIndex(long);
+setter | HTMLSelectElement::selectedIndex(long);
+getter | HTMLSelectElement::willValidate(boolean);
+getter | HTMLSelectElement::validity(user);
+getter | HTMLSelectElement::validationMessage(string);
+getter | HTMLSelectElement::labels(user);
+method | HTMLButtonElement::checkValidity();
+method | HTMLButtonElement::reportValidity();
+method | HTMLButtonElement::setCustomValidity();
+getter | HTMLButtonElement::autofocus(boolean);
+setter | HTMLButtonElement::autofocus(boolean);
+getter | HTMLButtonElement::form(user);
+getter | HTMLButtonElement::formAction(string);
+setter | HTMLButtonElement::formAction(string);
+getter | HTMLButtonElement::formEnctype(string);
+setter | HTMLButtonElement::formEnctype(string);
+getter | HTMLButtonElement::formMethod(string);
+setter | HTMLButtonElement::formMethod(string);
+getter | HTMLButtonElement::formNoValidate(boolean);
+setter | HTMLButtonElement::formNoValidate(boolean);
+getter | HTMLButtonElement::formTarget(string);
+setter | HTMLButtonElement::formTarget(string);
+getter | HTMLButtonElement::type(string);
+setter | HTMLButtonElement::type(string);
+getter | HTMLButtonElement::menu(user);
+setter | HTMLButtonElement::menu(user);
+getter | HTMLButtonElement::willValidate(boolean);
+getter | HTMLButtonElement::validity(user);
+getter | HTMLButtonElement::validationMessage(string);
+getter | HTMLButtonElement::labels(user);
+method | HTMLInputElement::stepUp();
+method | HTMLInputElement::stepDown();
+method | HTMLInputElement::checkValidity();
+method | HTMLInputElement::reportValidity();
+method | HTMLInputElement::setCustomValidity();
+method | HTMLInputElement::select();
+method | HTMLInputElement::setRangeText();
+method | HTMLInputElement::setSelectionRange();
+getter | HTMLInputElement::autocomplete(string);
+setter | HTMLInputElement::autocomplete(string);
+getter | HTMLInputElement::autofocus(boolean);
+setter | HTMLInputElement::autofocus(boolean);
+getter | HTMLInputElement::dirName(string);
+setter | HTMLInputElement::dirName(string);
+getter | HTMLInputElement::form(user);
+getter | HTMLInputElement::files(user);
+getter | HTMLInputElement::formAction(string);
+setter | HTMLInputElement::formAction(string);
+getter | HTMLInputElement::formEnctype(string);
+setter | HTMLInputElement::formEnctype(string);
+getter | HTMLInputElement::formMethod(string);
+setter | HTMLInputElement::formMethod(string);
+getter | HTMLInputElement::formNoValidate(boolean);
+setter | HTMLInputElement::formNoValidate(boolean);
+getter | HTMLInputElement::formTarget(string);
+setter | HTMLInputElement::formTarget(string);
+getter | HTMLInputElement::height(unsigned long);
+setter | HTMLInputElement::height(unsigned long);
+getter | HTMLInputElement::indeterminate(boolean);
+setter | HTMLInputElement::indeterminate(boolean);
+getter | HTMLInputElement::inputMode(string);
+setter | HTMLInputElement::inputMode(string);
+getter | HTMLInputElement::list(user);
+getter | HTMLInputElement::max(string);
+setter | HTMLInputElement::max(string);
+getter | HTMLInputElement::min(string);
+setter | HTMLInputElement::min(string);
+getter | HTMLInputElement::minLength(long);
+setter | HTMLInputElement::minLength(long);
+getter | HTMLInputElement::multiple(boolean);
+setter | HTMLInputElement::multiple(boolean);
+getter | HTMLInputElement::pattern(string);
+setter | HTMLInputElement::pattern(string);
+getter | HTMLInputElement::placeholder(string);
+setter | HTMLInputElement::placeholder(string);
+getter | HTMLInputElement::required(boolean);
+setter | HTMLInputElement::required(boolean);
+getter | HTMLInputElement::step(string);
+setter | HTMLInputElement::step(string);
+setter | HTMLInputElement::type(string);
+getter | HTMLInputElement::valueAsDate(date);
+setter | HTMLInputElement::valueAsDate(date);
+getter | HTMLInputElement::valueAsNumber(double);
+setter | HTMLInputElement::valueAsNumber(double);
+getter | HTMLInputElement::valueLow(double);
+setter | HTMLInputElement::valueLow(double);
+getter | HTMLInputElement::valueHigh(double);
+setter | HTMLInputElement::valueHigh(double);
+getter | HTMLInputElement::width(unsigned long);
+setter | HTMLInputElement::width(unsigned long);
+getter | HTMLInputElement::willValidate(boolean);
+getter | HTMLInputElement::validity(user);
+getter | HTMLInputElement::validationMessage(string);
+getter | HTMLInputElement::labels(user);
+getter | HTMLInputElement::selectionStart(unsigned long);
+setter | HTMLInputElement::selectionStart(unsigned long);
+getter | HTMLInputElement::selectionEnd(unsigned long);
+setter | HTMLInputElement::selectionEnd(unsigned long);
+getter | HTMLInputElement::selectionDirection(string);
+setter | HTMLInputElement::selectionDirection(string);
+getter | HTMLLabelElement::form(user);
+getter | HTMLLabelElement::control(user);
+method | HTMLFormElement::submit();
+method | HTMLFormElement::reset();
+method | HTMLFormElement::checkValidity();
+method | HTMLFormElement::reportValidity();
+method | HTMLFormElement::requestAutocomplete();
+getter | HTMLFormElement::autocomplete(string);
+setter | HTMLFormElement::autocomplete(string);
+getter | HTMLFormElement::encoding(string);
+setter | HTMLFormElement::encoding(string);
+getter | HTMLFormElement::name(string);
+setter | HTMLFormElement::name(string);
+getter | HTMLFormElement::noValidate(boolean);
+setter | HTMLFormElement::noValidate(boolean);
+getter | HTMLFormElement::elements(user);
+getter | HTMLFormElement::length(long);
+getter | HTMLTableCellElement::headers(user);
+method | HTMLTableHeaderCellElement::sort();
+getter | HTMLTableHeaderCellElement::scope(string);
+setter | HTMLTableHeaderCellElement::scope(string);
+getter | HTMLTableHeaderCellElement::abbr(string);
+setter | HTMLTableHeaderCellElement::abbr(string);
+getter | HTMLTableHeaderCellElement::sorted(string);
+setter | HTMLTableHeaderCellElement::sorted(string);
+getter | HTMLTableDataCellElement::abbr(string);
+setter | HTMLTableDataCellElement::abbr(string);
+method | HTMLTableRowElement::insertCell();
+method | HTMLTableRowElement::deleteCell();
+getter | HTMLTableRowElement::cells(user);
+method | HTMLTableSectionElement::insertRow();
+method | HTMLTableSectionElement::deleteRow();
+getter | HTMLTableSectionElement::rows(user);
+getter | HTMLTableColElement::span(unsigned long);
+setter | HTMLTableColElement::span(unsigned long);
+method | HTMLTableElement::createCaption();
+method | HTMLTableElement::deleteCaption();
+method | HTMLTableElement::createTHead();
+method | HTMLTableElement::deleteTHead();
+method | HTMLTableElement::createTFoot();
+method | HTMLTableElement::deleteTFoot();
+method | HTMLTableElement::createTBody();
+method | HTMLTableElement::insertRow();
+method | HTMLTableElement::deleteRow();
+method | HTMLTableElement::stopSorting();
+getter | HTMLTableElement::caption(user);
+setter | HTMLTableElement::caption(user);
+getter | HTMLTableElement::tHead(user);
+setter | HTMLTableElement::tHead(user);
+getter | HTMLTableElement::tFoot(user);
+setter | HTMLTableElement::tFoot(user);
+getter | HTMLTableElement::tBodies(user);
+getter | HTMLTableElement::rows(user);
+getter | HTMLTableElement::sortable(boolean);
+setter | HTMLTableElement::sortable(boolean);
+getter | HTMLAreaElement::download(string);
+setter | HTMLAreaElement::download(string);
+getter | HTMLAreaElement::ping(user);
+getter | HTMLAreaElement::rel(string);
+setter | HTMLAreaElement::rel(string);
+getter | HTMLAreaElement::relList(user);
+getter | HTMLAreaElement::hreflang(string);
+setter | HTMLAreaElement::hreflang(string);
+getter | HTMLAreaElement::type(string);
+setter | HTMLAreaElement::type(string);
+getter | HTMLAreaElement::href(user);
+setter | HTMLAreaElement::href(user);
+getter | HTMLAreaElement::origin(user);
+getter | HTMLAreaElement::protocol(user);
+setter | HTMLAreaElement::protocol(user);
+getter | HTMLAreaElement::username(user);
+setter | HTMLAreaElement::username(user);
+getter | HTMLAreaElement::password(user);
+setter | HTMLAreaElement::password(user);
+getter | HTMLAreaElement::host(user);
+setter | HTMLAreaElement::host(user);
+getter | HTMLAreaElement::hostname(user);
+setter | HTMLAreaElement::hostname(user);
+getter | HTMLAreaElement::port(user);
+setter | HTMLAreaElement::port(user);
+getter | HTMLAreaElement::pathname(user);
+setter | HTMLAreaElement::pathname(user);
+getter | HTMLAreaElement::search(user);
+setter | HTMLAreaElement::search(user);
+getter | HTMLAreaElement::hash(user);
+setter | HTMLAreaElement::hash(user);
+getter | HTMLMapElement::areas(user);
+getter | TrackEvent::track(multiple);
+method | TimeRanges::start();
+method | TimeRanges::end();
+getter | TimeRanges::length(unsigned long);
+getter | TextTrackCue::track(user);
+getter | TextTrackCue::id(string);
+setter | TextTrackCue::id(string);
+getter | TextTrackCue::startTime(double);
+setter | TextTrackCue::startTime(double);
+getter | TextTrackCue::endTime(double);
+setter | TextTrackCue::endTime(double);
+getter | TextTrackCue::pauseOnExit(boolean);
+setter | TextTrackCue::pauseOnExit(boolean);
+getter | TextTrackCue::onenter(user);
+setter | TextTrackCue::onenter(user);
+getter | TextTrackCue::onexit(user);
+setter | TextTrackCue::onexit(user);
+method | TextTrackCueList::getCueById();
+getter | TextTrackCueList::length(unsigned long);
+method | TextTrack::addCue();
+method | TextTrack::removeCue();
+getter | TextTrack::kind(user);
+getter | TextTrack::label(string);
+getter | TextTrack::language(string);
+getter | TextTrack::id(string);
+getter | TextTrack::inBandMetadataTrackDispatchType(string);
+getter | TextTrack::mode(user);
+setter | TextTrack::mode(user);
+getter | TextTrack::cues(user);
+getter | TextTrack::activeCues(user);
+getter | TextTrack::oncuechange(user);
+setter | TextTrack::oncuechange(user);
+method | TextTrackList::getTrackById();
+getter | TextTrackList::length(unsigned long);
+getter | TextTrackList::onchange(user);
+setter | TextTrackList::onchange(user);
+getter | TextTrackList::onaddtrack(user);
+setter | TextTrackList::onaddtrack(user);
+getter | TextTrackList::onremovetrack(user);
+setter | TextTrackList::onremovetrack(user);
+method | MediaController::pause();
+method | MediaController::unpause();
+method | MediaController::play();
+getter | MediaController::readyState(unsigned short);
+getter | MediaController::buffered(user);
+getter | MediaController::seekable(user);
+getter | MediaController::duration(double);
+getter | MediaController::currentTime(double);
+setter | MediaController::currentTime(double);
+getter | MediaController::paused(boolean);
+getter | MediaController::playbackState(user);
+getter | MediaController::played(user);
+getter | MediaController::defaultPlaybackRate(double);
+setter | MediaController::defaultPlaybackRate(double);
+getter | MediaController::playbackRate(double);
+setter | MediaController::playbackRate(double);
+getter | MediaController::volume(double);
+setter | MediaController::volume(double);
+getter | MediaController::muted(boolean);
+setter | MediaController::muted(boolean);
+getter | MediaController::onemptied(user);
+setter | MediaController::onemptied(user);
+getter | MediaController::onloadedmetadata(user);
+setter | MediaController::onloadedmetadata(user);
+getter | MediaController::onloadeddata(user);
+setter | MediaController::onloadeddata(user);
+getter | MediaController::oncanplay(user);
+setter | MediaController::oncanplay(user);
+getter | MediaController::oncanplaythrough(user);
+setter | MediaController::oncanplaythrough(user);
+getter | MediaController::onplaying(user);
+setter | MediaController::onplaying(user);
+getter | MediaController::onended(user);
+setter | MediaController::onended(user);
+getter | MediaController::onwaiting(user);
+setter | MediaController::onwaiting(user);
+getter | MediaController::ondurationchange(user);
+setter | MediaController::ondurationchange(user);
+getter | MediaController::ontimeupdate(user);
+setter | MediaController::ontimeupdate(user);
+getter | MediaController::onplay(user);
+setter | MediaController::onplay(user);
+getter | MediaController::onpause(user);
+setter | MediaController::onpause(user);
+getter | MediaController::onratechange(user);
+setter | MediaController::onratechange(user);
+getter | MediaController::onvolumechange(user);
+setter | MediaController::onvolumechange(user);
+getter | VideoTrack::id(string);
+getter | VideoTrack::kind(string);
+getter | VideoTrack::label(string);
+getter | VideoTrack::language(string);
+getter | VideoTrack::selected(boolean);
+setter | VideoTrack::selected(boolean);
+method | VideoTrackList::getTrackById();
+getter | VideoTrackList::length(unsigned long);
+getter | VideoTrackList::selectedIndex(long);
+getter | VideoTrackList::onchange(user);
+setter | VideoTrackList::onchange(user);
+getter | VideoTrackList::onaddtrack(user);
+setter | VideoTrackList::onaddtrack(user);
+getter | VideoTrackList::onremovetrack(user);
+setter | VideoTrackList::onremovetrack(user);
+getter | AudioTrack::id(string);
+getter | AudioTrack::kind(string);
+getter | AudioTrack::label(string);
+getter | AudioTrack::language(string);
+getter | AudioTrack::enabled(boolean);
+setter | AudioTrack::enabled(boolean);
+method | AudioTrackList::getTrackById();
+getter | AudioTrackList::length(unsigned long);
+getter | AudioTrackList::onchange(user);
+setter | AudioTrackList::onchange(user);
+getter | AudioTrackList::onaddtrack(user);
+setter | AudioTrackList::onaddtrack(user);
+getter | AudioTrackList::onremovetrack(user);
+setter | AudioTrackList::onremovetrack(user);
+getter | MediaError::code(unsigned short);
+method | HTMLMediaElement::load();
+method | HTMLMediaElement::canPlayType();
+method | HTMLMediaElement::fastSeek();
+method | HTMLMediaElement::getStartDate();
+method | HTMLMediaElement::play();
+method | HTMLMediaElement::pause();
+method | HTMLMediaElement::addTextTrack();
+getter | HTMLMediaElement::error(user);
+getter | HTMLMediaElement::src(string);
+setter | HTMLMediaElement::src(string);
+getter | HTMLMediaElement::srcObject(user);
+setter | HTMLMediaElement::srcObject(user);
+getter | HTMLMediaElement::currentSrc(string);
+getter | HTMLMediaElement::crossOrigin(string);
+setter | HTMLMediaElement::crossOrigin(string);
+getter | HTMLMediaElement::networkState(unsigned short);
+getter | HTMLMediaElement::preload(string);
+setter | HTMLMediaElement::preload(string);
+getter | HTMLMediaElement::buffered(user);
+getter | HTMLMediaElement::readyState(unsigned short);
+getter | HTMLMediaElement::seeking(boolean);
+getter | HTMLMediaElement::currentTime(double);
+setter | HTMLMediaElement::currentTime(double);
+getter | HTMLMediaElement::duration(double);
+getter | HTMLMediaElement::paused(boolean);
+getter | HTMLMediaElement::defaultPlaybackRate(double);
+setter | HTMLMediaElement::defaultPlaybackRate(double);
+getter | HTMLMediaElement::playbackRate(double);
+setter | HTMLMediaElement::playbackRate(double);
+getter | HTMLMediaElement::played(user);
+getter | HTMLMediaElement::seekable(user);
+getter | HTMLMediaElement::ended(boolean);
+getter | HTMLMediaElement::autoplay(boolean);
+setter | HTMLMediaElement::autoplay(boolean);
+getter | HTMLMediaElement::loop(boolean);
+setter | HTMLMediaElement::loop(boolean);
+getter | HTMLMediaElement::mediaGroup(string);
+setter | HTMLMediaElement::mediaGroup(string);
+getter | HTMLMediaElement::controller(user);
+setter | HTMLMediaElement::controller(user);
+getter | HTMLMediaElement::controls(boolean);
+setter | HTMLMediaElement::controls(boolean);
+getter | HTMLMediaElement::volume(double);
+setter | HTMLMediaElement::volume(double);
+getter | HTMLMediaElement::muted(boolean);
+setter | HTMLMediaElement::muted(boolean);
+getter | HTMLMediaElement::defaultMuted(boolean);
+setter | HTMLMediaElement::defaultMuted(boolean);
+getter | HTMLMediaElement::audioTracks(user);
+getter | HTMLMediaElement::videoTracks(user);
+getter | HTMLMediaElement::textTracks(user);
+getter | HTMLTrackElement::kind(string);
+setter | HTMLTrackElement::kind(string);
+getter | HTMLTrackElement::src(string);
+setter | HTMLTrackElement::src(string);
+getter | HTMLTrackElement::srclang(string);
+setter | HTMLTrackElement::srclang(string);
+getter | HTMLTrackElement::label(string);
+setter | HTMLTrackElement::label(string);
+getter | HTMLTrackElement::default(boolean);
+setter | HTMLTrackElement::default(boolean);
+getter | HTMLTrackElement::readyState(unsigned short);
+getter | HTMLTrackElement::track(user);
+getter | HTMLVideoElement::width(unsigned long);
+setter | HTMLVideoElement::width(unsigned long);
+getter | HTMLVideoElement::height(unsigned long);
+setter | HTMLVideoElement::height(unsigned long);
+getter | HTMLVideoElement::videoWidth(unsigned long);
+getter | HTMLVideoElement::videoHeight(unsigned long);
+getter | HTMLVideoElement::poster(string);
+setter | HTMLVideoElement::poster(string);
+method | HTMLObjectElement::getSVGDocument();
+method | HTMLObjectElement::checkValidity();
+method | HTMLObjectElement::reportValidity();
+method | HTMLObjectElement::setCustomValidity();
+getter | HTMLObjectElement::typeMustMatch(boolean);
+setter | HTMLObjectElement::typeMustMatch(boolean);
+getter | HTMLObjectElement::form(user);
+getter | HTMLObjectElement::contentDocument(user);
+getter | HTMLObjectElement::contentWindow(user);
+getter | HTMLObjectElement::willValidate(boolean);
+getter | HTMLObjectElement::validity(user);
+getter | HTMLObjectElement::validationMessage(string);
+getter | HTMLObjectElement::hspace(unsigned long);
+setter | HTMLObjectElement::hspace(unsigned long);
+getter | HTMLObjectElement::vspace(unsigned long);
+setter | HTMLObjectElement::vspace(unsigned long);
+method | HTMLEmbedElement::getSVGDocument();
+getter | HTMLEmbedElement::src(string);
+setter | HTMLEmbedElement::src(string);
+getter | HTMLEmbedElement::type(string);
+setter | HTMLEmbedElement::type(string);
+getter | HTMLEmbedElement::width(string);
+setter | HTMLEmbedElement::width(string);
+getter | HTMLEmbedElement::height(string);
+setter | HTMLEmbedElement::height(string);
+getter | HTMLEmbedElement::align(string);
+setter | HTMLEmbedElement::align(string);
+getter | HTMLEmbedElement::name(string);
+setter | HTMLEmbedElement::name(string);
+method | HTMLIFrameElement::getSVGDocument();
+getter | HTMLIFrameElement::srcdoc(string);
+setter | HTMLIFrameElement::srcdoc(string);
+getter | HTMLIFrameElement::sandbox(user);
+getter | HTMLIFrameElement::seamless(boolean);
+setter | HTMLIFrameElement::seamless(boolean);
+getter | HTMLIFrameElement::allowFullscreen(boolean);
+setter | HTMLIFrameElement::allowFullscreen(boolean);
+getter | HTMLIFrameElement::contentDocument(user);
+getter | HTMLIFrameElement::contentWindow(user);
+getter | HTMLImageElement::srcset(string);
+setter | HTMLImageElement::srcset(string);
+getter | HTMLImageElement::sizes(string);
+setter | HTMLImageElement::sizes(string);
+getter | HTMLImageElement::crossOrigin(string);
+setter | HTMLImageElement::crossOrigin(string);
+getter | HTMLImageElement::naturalWidth(unsigned long);
+getter | HTMLImageElement::naturalHeight(unsigned long);
+getter | HTMLImageElement::complete(boolean);
+getter | HTMLImageElement::currentSrc(string);
+getter | HTMLImageElement::lowsrc(string);
+setter | HTMLImageElement::lowsrc(string);
+getter | HTMLSourceElement::srcset(string);
+setter | HTMLSourceElement::srcset(string);
+getter | HTMLSourceElement::sizes(string);
+setter | HTMLSourceElement::sizes(string);
+getter | HTMLSourceElement::media(string);
+setter | HTMLSourceElement::media(string);
+getter | HTMLSourceElement::src(string);
+setter | HTMLSourceElement::src(string);
+getter | HTMLSourceElement::type(string);
+setter | HTMLSourceElement::type(string);
+getter | HTMLModElement::cite(string);
+setter | HTMLModElement::cite(string);
+getter | HTMLModElement::dateTime(string);
+setter | HTMLModElement::dateTime(string);
+getter | HTMLTimeElement::dateTime(string);
+setter | HTMLTimeElement::dateTime(string);
+getter | HTMLDataElement::value(string);
+setter | HTMLDataElement::value(string);
+getter | HTMLAnchorElement::download(string);
+setter | HTMLAnchorElement::download(string);
+getter | HTMLAnchorElement::ping(user);
+getter | HTMLAnchorElement::relList(user);
+getter | HTMLAnchorElement::type(string);
+setter | HTMLAnchorElement::type(string);
+getter | HTMLAnchorElement::text(string);
+setter | HTMLAnchorElement::text(string);
+getter | HTMLAnchorElement::href(user);
+setter | HTMLAnchorElement::href(user);
+getter | HTMLAnchorElement::origin(user);
+getter | HTMLAnchorElement::protocol(user);
+setter | HTMLAnchorElement::protocol(user);
+getter | HTMLAnchorElement::username(user);
+setter | HTMLAnchorElement::username(user);
+getter | HTMLAnchorElement::password(user);
+setter | HTMLAnchorElement::password(user);
+getter | HTMLAnchorElement::host(user);
+setter | HTMLAnchorElement::host(user);
+getter | HTMLAnchorElement::hostname(user);
+setter | HTMLAnchorElement::hostname(user);
+getter | HTMLAnchorElement::port(user);
+setter | HTMLAnchorElement::port(user);
+getter | HTMLAnchorElement::pathname(user);
+setter | HTMLAnchorElement::pathname(user);
+getter | HTMLAnchorElement::search(user);
+setter | HTMLAnchorElement::search(user);
+getter | HTMLAnchorElement::hash(user);
+setter | HTMLAnchorElement::hash(user);
+getter | HTMLDListElement::compact(boolean);
+setter | HTMLDListElement::compact(boolean);
+getter | HTMLUListElement::compact(boolean);
+setter | HTMLUListElement::compact(boolean);
+getter | HTMLUListElement::type(string);
+setter | HTMLUListElement::type(string);
+getter | HTMLOListElement::reversed(boolean);
+setter | HTMLOListElement::reversed(boolean);
+getter | HTMLHRElement::color(string);
+setter | HTMLHRElement::color(string);
+getter | HTMLStyleElement::nonce(string);
+setter | HTMLStyleElement::nonce(string);
+getter | HTMLStyleElement::scoped(boolean);
+setter | HTMLStyleElement::scoped(boolean);
+getter | HTMLStyleElement::sheet(user);
+getter | HTMLLinkElement::crossOrigin(string);
+setter | HTMLLinkElement::crossOrigin(string);
+getter | HTMLLinkElement::relList(user);
+getter | HTMLLinkElement::sizes(user);
+getter | HTMLLinkElement::sheet(user);
+method | HTMLCollection::item();
+method | HTMLCollection::namedItem();
+getter | HTMLCollection::length(unsigned long);
+method | HTMLOptionsCollection::add();
+method | HTMLOptionsCollection::remove();
+getter | HTMLOptionsCollection::length(unsigned long);
+setter | HTMLOptionsCollection::length(unsigned long);
+getter | HTMLOptionsCollection::selectedIndex(long);
+setter | HTMLOptionsCollection::selectedIndex(long);
+getter | RadioNodeList::value(string);
+setter | RadioNodeList::value(string);
+method | HTMLFormControlsCollection::namedItem();
+method | HTMLAllCollection::item();
+method | HTMLAllCollection::namedItem();
+getter | HTMLAllCollection::length(unsigned long);
+method | XMLSerializer::serializeToString();
+method | DOMParser::parseFromString();
+method | NodeFilter::acceptNode();
+method | TreeWalker::parentNode();
+method | TreeWalker::firstChild();
+method | TreeWalker::lastChild();
+method | TreeWalker::previousSibling();
+method | TreeWalker::nextSibling();
+method | TreeWalker::previousNode();
+method | TreeWalker::nextNode();
+getter | TreeWalker::root(user);
+getter | TreeWalker::whatToShow(unsigned long);
+getter | TreeWalker::filter(user);
+getter | TreeWalker::currentNode(user);
+setter | TreeWalker::currentNode(user);
+method | NodeIterator::nextNode();
+method | NodeIterator::previousNode();
+method | NodeIterator::detach();
+getter | NodeIterator::root(user);
+getter | NodeIterator::referenceNode(user);
+getter | NodeIterator::pointerBeforeReferenceNode(boolean);
+getter | NodeIterator::whatToShow(unsigned long);
+getter | NodeIterator::filter(user);
+method | Range::setStart();
+method | Range::setEnd();
+method | Range::setStartBefore();
+method | Range::setStartAfter();
+method | Range::setEndBefore();
+method | Range::setEndAfter();
+method | Range::collapse();
+method | Range::selectNode();
+method | Range::selectNodeContents();
+method | Range::compareBoundaryPoints();
+method | Range::deleteContents();
+method | Range::extractContents();
+method | Range::cloneContents();
+method | Range::insertNode();
+method | Range::surroundContents();
+method | Range::cloneRange();
+method | Range::detach();
+method | Range::isPointInRange();
+method | Range::comparePoint();
+method | Range::intersectsNode();
+method | Range::createContextualFragment();
+getter | Range::startContainer(user);
+getter | Range::startOffset(unsigned long);
+getter | Range::endContainer(user);
+getter | Range::endOffset(unsigned long);
+getter | Range::collapsed(boolean);
+getter | Range::commonAncestorContainer(user);
+method | CharacterData::substringData();
+method | CharacterData::appendData();
+method | CharacterData::insertData();
+method | CharacterData::deleteData();
+method | CharacterData::replaceData();
+method | CharacterData::before();
+method | CharacterData::after();
+method | CharacterData::replaceWith();
+method | CharacterData::remove();
+getter | CharacterData::data(string);
+setter | CharacterData::data(string);
+getter | CharacterData::length(unsigned long);
+getter | CharacterData::previousElementSibling(user);
+getter | CharacterData::nextElementSibling(user);
+getter | ProcessingInstruction::target(string);
+getter | ProcessingInstruction::sheet(user);
+method | Text::splitText();
+getter | Text::wholeText(string);
+getter | Attr::namespaceURI(string);
+getter | Attr::prefix(string);
+getter | Attr::localName(string);
+getter | Attr::name(string);
+getter | Attr::value(string);
+setter | Attr::value(string);
+getter | Attr::nodeValue(string);
+setter | Attr::nodeValue(string);
+getter | Attr::textContent(string);
+setter | Attr::textContent(string);
+getter | Attr::ownerElement(user);
+getter | Attr::specified(boolean);
+method | NamedNodeMap::getNamedItemNS();
+method | NamedNodeMap::setNamedItem();
+method | NamedNodeMap::setNamedItemNS();
+method | NamedNodeMap::removeNamedItem();
+method | NamedNodeMap::removeNamedItemNS();
+method | DOMImplementation::createDocumentType();
+method | DOMImplementation::createDocument();
+method | DOMImplementation::hasFeature();
+method | Document::getElementsByTagNameNS();
+method | Document::getElementsByClassName();
+method | Document::createComment();
+method | Document::createProcessingInstruction();
+method | Document::importNode();
+method | Document::adoptNode();
+method | Document::createAttribute();
+method | Document::createAttributeNS();
+method | Document::createRange();
+method | Document::createNodeIterator();
+method | Document::createTreeWalker();
+method | Document::getElementsByName();
+method | Document::open();
+method | Document::close();
+method | Document::hasFocus();
+method | Document::execCommand();
+method | Document::queryCommandEnabled();
+method | Document::queryCommandIndeterm();
+method | Document::queryCommandState();
+method | Document::queryCommandSupported();
+method | Document::queryCommandValue();
+method | Document::clear();
+method | Document::captureEvents();
+method | Document::releaseEvents();
+method | Document::enableStyleSheetsForSet();
+method | Document::prepend();
+method | Document::append();
+method | Document::query();
+method | Document::queryAll();
+method | Document::querySelector();
+method | Document::querySelectorAll();
+getter | Document::URL(string);
+getter | Document::documentURI(string);
+getter | Document::origin(string);
+getter | Document::compatMode(string);
+getter | Document::characterSet(string);
+getter | Document::inputEncoding(string);
+getter | Document::contentType(string);
+getter | Document::doctype(user);
+getter | Document::domain(string);
+setter | Document::domain(string);
+getter | Document::referrer(string);
+getter | Document::lastModified(string);
+getter | Document::readyState(user);
+getter | Document::title(string);
+setter | Document::title(string);
+getter | Document::dir(string);
+setter | Document::dir(string);
+setter | Document::body(user);
+getter | Document::images(user);
+getter | Document::embeds(user);
+getter | Document::plugins(user);
+getter | Document::links(user);
+getter | Document::forms(user);
+getter | Document::scripts(user);
+getter | Document::cssElementMap(user);
+getter | Document::currentScript(user);
+getter | Document::defaultView(user);
+getter | Document::activeElement(user);
+getter | Document::designMode(string);
+setter | Document::designMode(string);
+getter | Document::commands(user);
+getter | Document::fgColor(string);
+setter | Document::fgColor(string);
+getter | Document::linkColor(string);
+setter | Document::linkColor(string);
+getter | Document::vlinkColor(string);
+setter | Document::vlinkColor(string);
+getter | Document::alinkColor(string);
+setter | Document::alinkColor(string);
+getter | Document::bgColor(string);
+setter | Document::bgColor(string);
+getter | Document::anchors(user);
+getter | Document::applets(user);
+getter | Document::all(user);
+getter | Document::styleSheets(user);
+getter | Document::selectedStyleSheetSet(string);
+setter | Document::selectedStyleSheetSet(string);
+getter | Document::lastStyleSheetSet(string);
+getter | Document::preferredStyleSheetSet(string);
+getter | Document::styleSheetSets(string);
+getter | Document::children(user);
+getter | Document::firstElementChild(user);
+getter | Document::lastElementChild(user);
+getter | Document::childElementCount(unsigned long);
+getter | Document::onerror(user);
+setter | Document::onerror(user);
+method | XMLDocument::load();
+getter | MutationRecord::type(string);
+getter | MutationRecord::target(user);
+getter | MutationRecord::addedNodes(user);
+getter | MutationRecord::removedNodes(user);
+getter | MutationRecord::previousSibling(user);
+getter | MutationRecord::nextSibling(user);
+getter | MutationRecord::attributeName(string);
+getter | MutationRecord::attributeNamespace(string);
+getter | MutationRecord::oldValue(string);
+method | MutationObserver::observe();
+method | MutationObserver::disconnect();
+method | MutationObserver::takeRecords();
+method | DocumentType::before();
+method | DocumentType::after();
+method | DocumentType::replaceWith();
+method | DocumentType::remove();
+getter | DocumentType::name(string);
+getter | DocumentType::publicId(string);
+getter | DocumentType::systemId(string);
+method | DocumentFragment::getElementById();
+method | DocumentFragment::prepend();
+method | DocumentFragment::append();
+method | DocumentFragment::query();
+method | DocumentFragment::queryAll();
+method | DocumentFragment::querySelector();
+method | DocumentFragment::querySelectorAll();
+getter | DocumentFragment::children(user);
+getter | DocumentFragment::firstElementChild(user);
+getter | DocumentFragment::lastElementChild(user);
+getter | DocumentFragment::childElementCount(unsigned long);
+method | EventListener::handleEvent();
+method | CustomEvent::initCustomEvent();
+getter | CustomEvent::detail(any);
+
+ 1539 unimplemented bindings
+
diff --git a/docs/UnimplementedJavascript.txt b/docs/UnimplementedJavascript.txt
deleted file mode 100644
index 1b851b8bb..000000000
--- a/docs/UnimplementedJavascript.txt
+++ /dev/null
@@ -1,1798 +0,0 @@
-/** \page unimplemented Unimplemented javascript bindings
-This is a list of all the binding methods, getters and setters without an implementation in a binding.
-
-method ApplicationCache::abort();\n
-getter ApplicationCache::oncached(user);\n
-setter ApplicationCache::oncached(user);\n
-getter ApplicationCache::onchecking(user);\n
-setter ApplicationCache::onchecking(user);\n
-getter ApplicationCache::ondownloading(user);\n
-setter ApplicationCache::ondownloading(user);\n
-getter ApplicationCache::onerror(user);\n
-setter ApplicationCache::onerror(user);\n
-getter ApplicationCache::onnoupdate(user);\n
-setter ApplicationCache::onnoupdate(user);\n
-getter ApplicationCache::onobsolete(user);\n
-setter ApplicationCache::onobsolete(user);\n
-getter ApplicationCache::onprogress(user);\n
-setter ApplicationCache::onprogress(user);\n
-getter ApplicationCache::onupdateready(user);\n
-setter ApplicationCache::onupdateready(user);\n
-getter ApplicationCache::status(unsigned short);\n
-method ApplicationCache::swapCache();\n
-method ApplicationCache::update();\n
-getter Attr::localName(string);\n
-getter Attr::namespaceURI(string);\n
-getter Attr::name(string);\n
-getter Attr::nodeValue(string);\n
-setter Attr::nodeValue(string);\n
-getter Attr::ownerElement(user);\n
-getter Attr::prefix(string);\n
-getter Attr::specified(boolean);\n
-getter Attr::textContent(string);\n
-setter Attr::textContent(string);\n
-getter Attr::value(string);\n
-setter Attr::value(string);\n
-getter AudioTrack::enabled(boolean);\n
-setter AudioTrack::enabled(boolean);\n
-getter AudioTrack::id(string);\n
-getter AudioTrack::kind(string);\n
-getter AudioTrack::label(string);\n
-getter AudioTrack::language(string);\n
-method AudioTrackList::getTrackById();\n
-getter AudioTrackList::length(unsigned long);\n
-getter AudioTrackList::onaddtrack(user);\n
-setter AudioTrackList::onaddtrack(user);\n
-getter AudioTrackList::onchange(user);\n
-setter AudioTrackList::onchange(user);\n
-getter AudioTrackList::onremovetrack(user);\n
-setter AudioTrackList::onremovetrack(user);\n
-getter AutocompleteErrorEvent::reason(user);\n
-getter BarProp::visible(boolean);\n
-getter BeforeUnloadEvent::returnValue(string);\n
-setter BeforeUnloadEvent::returnValue(string);\n
-method BroadcastChannel::close();\n
-getter BroadcastChannel::name(string);\n
-getter BroadcastChannel::onmessage(user);\n
-setter BroadcastChannel::onmessage(user);\n
-method BroadcastChannel::postMessage();\n
-method CanvasGradient::addColorStop();\n
-method CanvasPattern::setTransform();\n
-method CanvasProxy::setContext();\n
-method CanvasRenderingContext2D::addHitRegion();\n
-method CanvasRenderingContext2D::arc();\n
-method CanvasRenderingContext2D::arcTo();\n
-method CanvasRenderingContext2D::beginPath();\n
-method CanvasRenderingContext2D::bezierCurveTo();\n
-getter CanvasRenderingContext2D::canvas(user);\n
-method CanvasRenderingContext2D::clearHitRegions();\n
-method CanvasRenderingContext2D::clearRect();\n
-method CanvasRenderingContext2D::clip();\n
-method CanvasRenderingContext2D::closePath();\n
-method CanvasRenderingContext2D::commit();\n
-method CanvasRenderingContext2D::createImageData();\n
-method CanvasRenderingContext2D::createLinearGradient();\n
-method CanvasRenderingContext2D::createPattern();\n
-method CanvasRenderingContext2D::createRadialGradient();\n
-getter CanvasRenderingContext2D::currentTransform(user);\n
-setter CanvasRenderingContext2D::currentTransform(user);\n
-getter CanvasRenderingContext2D::direction(string);\n
-setter CanvasRenderingContext2D::direction(string);\n
-method CanvasRenderingContext2D::drawFocusIfNeeded();\n
-method CanvasRenderingContext2D::drawImage();\n
-method CanvasRenderingContext2D::ellipse();\n
-method CanvasRenderingContext2D::fill();\n
-method CanvasRenderingContext2D::fillRect();\n
-getter CanvasRenderingContext2D::fillStyle(multiple);\n
-setter CanvasRenderingContext2D::fillStyle(multiple);\n
-method CanvasRenderingContext2D::fillText();\n
-getter CanvasRenderingContext2D::font(string);\n
-setter CanvasRenderingContext2D::font(string);\n
-method CanvasRenderingContext2D::getImageData();\n
-method CanvasRenderingContext2D::getLineDash();\n
-getter CanvasRenderingContext2D::globalAlpha(double);\n
-setter CanvasRenderingContext2D::globalAlpha(double);\n
-getter CanvasRenderingContext2D::globalCompositeOperation(string);\n
-setter CanvasRenderingContext2D::globalCompositeOperation(string);\n
-getter CanvasRenderingContext2D::height(unsigned long);\n
-setter CanvasRenderingContext2D::height(unsigned long);\n
-getter CanvasRenderingContext2D::imageSmoothingEnabled(boolean);\n
-setter CanvasRenderingContext2D::imageSmoothingEnabled(boolean);\n
-getter CanvasRenderingContext2D::imageSmoothingQuality(user);\n
-setter CanvasRenderingContext2D::imageSmoothingQuality(user);\n
-method CanvasRenderingContext2D::isPointInPath();\n
-method CanvasRenderingContext2D::isPointInStroke();\n
-getter CanvasRenderingContext2D::lineCap(string);\n
-setter CanvasRenderingContext2D::lineCap(string);\n
-getter CanvasRenderingContext2D::lineDashOffset(double);\n
-setter CanvasRenderingContext2D::lineDashOffset(double);\n
-getter CanvasRenderingContext2D::lineJoin(string);\n
-setter CanvasRenderingContext2D::lineJoin(string);\n
-method CanvasRenderingContext2D::lineTo();\n
-getter CanvasRenderingContext2D::lineWidth(double);\n
-setter CanvasRenderingContext2D::lineWidth(double);\n
-method CanvasRenderingContext2D::measureText();\n
-getter CanvasRenderingContext2D::miterLimit(double);\n
-setter CanvasRenderingContext2D::miterLimit(double);\n
-method CanvasRenderingContext2D::moveTo();\n
-method CanvasRenderingContext2D::putImageData();\n
-method CanvasRenderingContext2D::quadraticCurveTo();\n
-method CanvasRenderingContext2D::rect();\n
-method CanvasRenderingContext2D::removeHitRegion();\n
-method CanvasRenderingContext2D::resetClip();\n
-method CanvasRenderingContext2D::resetTransform();\n
-method CanvasRenderingContext2D::restore();\n
-method CanvasRenderingContext2D::rotate();\n
-method CanvasRenderingContext2D::save();\n
-method CanvasRenderingContext2D::scale();\n
-method CanvasRenderingContext2D::scrollPathIntoView();\n
-method CanvasRenderingContext2D::setLineDash();\n
-method CanvasRenderingContext2D::setTransform();\n
-getter CanvasRenderingContext2D::shadowBlur(double);\n
-setter CanvasRenderingContext2D::shadowBlur(double);\n
-getter CanvasRenderingContext2D::shadowColor(string);\n
-setter CanvasRenderingContext2D::shadowColor(string);\n
-getter CanvasRenderingContext2D::shadowOffsetX(double);\n
-setter CanvasRenderingContext2D::shadowOffsetX(double);\n
-getter CanvasRenderingContext2D::shadowOffsetY(double);\n
-setter CanvasRenderingContext2D::shadowOffsetY(double);\n
-method CanvasRenderingContext2D::stroke();\n
-method CanvasRenderingContext2D::strokeRect();\n
-getter CanvasRenderingContext2D::strokeStyle(multiple);\n
-setter CanvasRenderingContext2D::strokeStyle(multiple);\n
-method CanvasRenderingContext2D::strokeText();\n
-getter CanvasRenderingContext2D::textAlign(string);\n
-setter CanvasRenderingContext2D::textAlign(string);\n
-getter CanvasRenderingContext2D::textBaseline(string);\n
-setter CanvasRenderingContext2D::textBaseline(string);\n
-method CanvasRenderingContext2D::transform();\n
-method CanvasRenderingContext2D::translate();\n
-getter CanvasRenderingContext2D::width(unsigned long);\n
-setter CanvasRenderingContext2D::width(unsigned long);\n
-method CharacterData::after();\n
-method CharacterData::appendData();\n
-method CharacterData::before();\n
-getter CharacterData::data(string);\n
-setter CharacterData::data(string);\n
-method CharacterData::deleteData();\n
-method CharacterData::insertData();\n
-getter CharacterData::length(unsigned long);\n
-getter CharacterData::nextElementSibling(user);\n
-getter CharacterData::previousElementSibling(user);\n
-method CharacterData::remove();\n
-method CharacterData::replaceData();\n
-method CharacterData::replaceWith();\n
-method CharacterData::substringData();\n
-getter CloseEvent::code(unsigned short);\n
-getter CloseEvent::reason(string);\n
-getter CloseEvent::wasClean(boolean);\n
-getter CompositionEvent::data(string);\n
-method CompositionEvent::initCompositionEvent();\n
-method CSS::escape();\n
-getter CSSGroupingRule::cssRules(user);\n
-method CSSGroupingRule::deleteRule();\n
-method CSSGroupingRule::insertRule();\n
-getter CSSImportRule::href(string);\n
-getter CSSImportRule::media(user);\n
-getter CSSImportRule::styleSheet(user);\n
-getter CSSMarginRule::name(string);\n
-getter CSSMarginRule::style(user);\n
-getter CSSMediaRule::media(user);\n
-getter CSSNamespaceRule::namespaceURI(string);\n
-getter CSSNamespaceRule::prefix(string);\n
-getter CSSPageRule::selectorText(string);\n
-setter CSSPageRule::selectorText(string);\n
-getter CSSPageRule::style(user);\n
-getter CSSRule::cssText(string);\n
-setter CSSRule::cssText(string);\n
-method CSSRuleList::item();\n
-getter CSSRuleList::length(unsigned long);\n
-getter CSSRule::parentRule(user);\n
-getter CSSRule::parentStyleSheet(user);\n
-getter CSSRule::type(unsigned short);\n
-getter CSSStyleDeclaration::cssFloat(string);\n
-setter CSSStyleDeclaration::cssFloat(string);\n
-getter CSSStyleDeclaration::cssText(string);\n
-setter CSSStyleDeclaration::cssText(string);\n
-getter CSSStyleDeclaration::dashed_attribute(string);\n
-setter CSSStyleDeclaration::dashed_attribute(string);\n
-method CSSStyleDeclaration::getPropertyPriority();\n
-method CSSStyleDeclaration::getPropertyValue();\n
-method CSSStyleDeclaration::item();\n
-getter CSSStyleDeclaration::length(unsigned long);\n
-getter CSSStyleDeclaration::parentRule(user);\n
-method CSSStyleDeclaration::removeProperty();\n
-method CSSStyleDeclaration::setProperty();\n
-method CSSStyleDeclaration::setPropertyPriority();\n
-method CSSStyleDeclaration::setPropertyValue();\n
-getter CSSStyleRule::selectorText(string);\n
-setter CSSStyleRule::selectorText(string);\n
-getter CSSStyleRule::style(user);\n
-getter CSSStyleSheet::cssRules(user);\n
-method CSSStyleSheet::deleteRule();\n
-method CSSStyleSheet::insertRule();\n
-getter CSSStyleSheet::ownerRule(user);\n
-getter CustomEvent::detail(any);\n
-method CustomEvent::initCustomEvent();\n
-method DataTransfer::clearData();\n
-getter DataTransfer::dropEffect(string);\n
-setter DataTransfer::dropEffect(string);\n
-getter DataTransfer::effectAllowed(string);\n
-setter DataTransfer::effectAllowed(string);\n
-getter DataTransfer::files(user);\n
-method DataTransfer::getData();\n
-method DataTransferItem::getAsFile();\n
-method DataTransferItem::getAsString();\n
-getter DataTransferItem::kind(string);\n
-method DataTransferItemList::add();\n
-method DataTransferItemList::clear();\n
-getter DataTransferItemList::length(unsigned long);\n
-method DataTransferItemList::remove();\n
-getter DataTransfer::items(user);\n
-getter DataTransferItem::type(string);\n
-method DataTransfer::setData();\n
-method DataTransfer::setDragImage();\n
-getter DataTransfer::types(string);\n
-getter DedicatedWorkerGlobalScope::onmessage(user);\n
-setter DedicatedWorkerGlobalScope::onmessage(user);\n
-method DedicatedWorkerGlobalScope::postMessage();\n
-getter Document::activeElement(user);\n
-method Document::adoptNode();\n
-getter Document::alinkColor(string);\n
-setter Document::alinkColor(string);\n
-getter Document::all(user);\n
-getter Document::anchors(user);\n
-method Document::append();\n
-getter Document::applets(user);\n
-getter Document::bgColor(string);\n
-setter Document::bgColor(string);\n
-setter Document::body(user);\n
-method Document::captureEvents();\n
-getter Document::characterSet(string);\n
-getter Document::childElementCount(unsigned long);\n
-getter Document::children(user);\n
-method Document::clear();\n
-method Document::close();\n
-getter Document::commands(user);\n
-getter Document::compatMode(string);\n
-getter Document::contentType(string);\n
-setter Document::cookie(string);\n
-method Document::createAttribute();\n
-method Document::createAttributeNS();\n
-method Document::createComment();\n
-method Document::createDocumentFragment();\n
-method Document::createElementNS();\n
-method Document::createEvent();\n
-method Document::createNodeIterator();\n
-method Document::createProcessingInstruction();\n
-method Document::createRange();\n
-method Document::createTreeWalker();\n
-getter Document::cssElementMap(user);\n
-getter Document::currentScript(user);\n
-getter Document::defaultView(user);\n
-getter Document::designMode(string);\n
-setter Document::designMode(string);\n
-getter Document::dir(string);\n
-setter Document::dir(string);\n
-getter Document::doctype(user);\n
-getter Document::documentURI(string);\n
-getter Document::domain(string);\n
-setter Document::domain(string);\n
-getter Document::embeds(user);\n
-method Document::enableStyleSheetsForSet();\n
-method Document::execCommand();\n
-getter Document::fgColor(string);\n
-setter Document::fgColor(string);\n
-getter Document::firstElementChild(user);\n
-getter Document::forms(user);\n
-method DocumentFragment::append();\n
-getter DocumentFragment::childElementCount(unsigned long);\n
-getter DocumentFragment::children(user);\n
-getter DocumentFragment::firstElementChild(user);\n
-method DocumentFragment::getElementById();\n
-getter DocumentFragment::lastElementChild(user);\n
-method DocumentFragment::prepend();\n
-method DocumentFragment::query();\n
-method DocumentFragment::queryAll();\n
-method DocumentFragment::querySelector();\n
-method DocumentFragment::querySelectorAll();\n
-method Document::getElementsByClassName();\n
-method Document::getElementsByName();\n
-method Document::getElementsByTagNameNS();\n
-method Document::hasFocus();\n
-getter Document::images(user);\n
-getter Document::implementation(user);\n
-method Document::importNode();\n
-getter Document::inputEncoding(string);\n
-getter Document::lastElementChild(user);\n
-getter Document::lastModified(string);\n
-getter Document::lastStyleSheetSet(string);\n
-getter Document::linkColor(string);\n
-setter Document::linkColor(string);\n
-getter Document::links(user);\n
-getter Document::onerror(user);\n
-setter Document::onerror(user);\n
-method Document::open();\n
-getter Document::origin(string);\n
-getter Document::plugins(user);\n
-getter Document::preferredStyleSheetSet(string);\n
-method Document::prepend();\n
-method Document::query();\n
-method Document::queryAll();\n
-method Document::queryCommandEnabled();\n
-method Document::queryCommandIndeterm();\n
-method Document::queryCommandState();\n
-method Document::queryCommandSupported();\n
-method Document::queryCommandValue();\n
-method Document::querySelector();\n
-method Document::querySelectorAll();\n
-getter Document::readyState(user);\n
-getter Document::referrer(string);\n
-method Document::releaseEvents();\n
-getter Document::scripts(user);\n
-getter Document::selectedStyleSheetSet(string);\n
-setter Document::selectedStyleSheetSet(string);\n
-getter Document::styleSheetSets(string);\n
-getter Document::styleSheets(user);\n
-getter Document::title(string);\n
-setter Document::title(string);\n
-method DocumentType::after();\n
-method DocumentType::before();\n
-getter DocumentType::name(string);\n
-getter DocumentType::publicId(string);\n
-method DocumentType::remove();\n
-method DocumentType::replaceWith();\n
-getter DocumentType::systemId(string);\n
-getter Document::URL(string);\n
-getter Document::vlinkColor(string);\n
-setter Document::vlinkColor(string);\n
-method DOMImplementation::createDocument();\n
-method DOMImplementation::createDocumentType();\n
-method DOMImplementation::createHTMLDocument();\n
-method DOMImplementation::hasFeature();\n
-method DOMParser::parseFromString();\n
-getter DOMSettableTokenList::value(string);\n
-setter DOMSettableTokenList::value(string);\n
-method DOMTokenList::add();\n
-method DOMTokenList::contains();\n
-method DOMTokenList::item();\n
-getter DOMTokenList::length(unsigned long);\n
-method DOMTokenList::remove();\n
-method DOMTokenList::toggle();\n
-getter DragEvent::dataTransfer(user);\n
-getter DrawingStyle::direction(string);\n
-setter DrawingStyle::direction(string);\n
-getter DrawingStyle::font(string);\n
-setter DrawingStyle::font(string);\n
-method DrawingStyle::getLineDash();\n
-getter DrawingStyle::lineCap(string);\n
-setter DrawingStyle::lineCap(string);\n
-getter DrawingStyle::lineDashOffset(double);\n
-setter DrawingStyle::lineDashOffset(double);\n
-getter DrawingStyle::lineJoin(string);\n
-setter DrawingStyle::lineJoin(string);\n
-getter DrawingStyle::lineWidth(double);\n
-setter DrawingStyle::lineWidth(double);\n
-getter DrawingStyle::miterLimit(double);\n
-setter DrawingStyle::miterLimit(double);\n
-method DrawingStyle::setLineDash();\n
-getter DrawingStyle::textAlign(string);\n
-setter DrawingStyle::textAlign(string);\n
-getter DrawingStyle::textBaseline(string);\n
-setter DrawingStyle::textBaseline(string);\n
-method Element::after();\n
-method Element::append();\n
-getter Element::attributes(user);\n
-method Element::before();\n
-getter Element::cascadedStyle(user);\n
-getter Element::children(user);\n
-getter Element::classList(user);\n
-method Element::closest();\n
-getter Element::defaultStyle(user);\n
-method Element::getAttributeNode();\n
-method Element::getAttributeNodeNS();\n
-method Element::getAttributeNS();\n
-method Element::getElementsByClassName();\n
-method Element::getElementsByTagNameNS();\n
-method Element::hasAttributeNS();\n
-method Element::hasAttributes();\n
-getter Element::innerHTML(string);\n
-setter Element::innerHTML(string);\n
-method Element::insertAdjacentHTML();\n
-getter Element::localName(string);\n
-method Element::matches();\n
-getter Element::namespaceURI(string);\n
-getter Element::outerHTML(string);\n
-setter Element::outerHTML(string);\n
-getter Element::prefix(string);\n
-method Element::prepend();\n
-method Element::pseudo();\n
-method Element::query();\n
-method Element::queryAll();\n
-method Element::querySelector();\n
-method Element::querySelectorAll();\n
-getter Element::rawComputedStyle(user);\n
-method Element::remove();\n
-method Element::removeAttributeNode();\n
-method Element::removeAttributeNS();\n
-method Element::replaceWith();\n
-method Element::setAttributeNode();\n
-method Element::setAttributeNodeNS();\n
-method Element::setAttributeNS();\n
-getter Element::tagName(string);\n
-getter Element::usedStyle(user);\n
-getter ErrorEvent::colno(unsigned long);\n
-getter ErrorEvent::error(any);\n
-getter ErrorEvent::filename(string);\n
-getter ErrorEvent::lineno(unsigned long);\n
-getter ErrorEvent::message(string);\n
-method Event::initEvent();\n
-getter Event::isTrusted(boolean);\n
-method EventListener::handleEvent();\n
-method EventSource::close();\n
-getter EventSource::onerror(user);\n
-setter EventSource::onerror(user);\n
-getter EventSource::onmessage(user);\n
-setter EventSource::onmessage(user);\n
-getter EventSource::onopen(user);\n
-setter EventSource::onopen(user);\n
-getter EventSource::readyState(unsigned short);\n
-getter EventSource::url(string);\n
-getter EventSource::withCredentials(boolean);\n
-getter Event::timeStamp(user);\n
-method External::AddSearchProvider();\n
-method External::IsSearchProviderInstalled();\n
-method FocusEvent::initFocusEvent();\n
-getter FocusEvent::relatedTarget(user);\n
-getter HashChangeEvent::newURL(string);\n
-getter HashChangeEvent::oldURL(string);\n
-method History::back();\n
-method History::forward();\n
-method History::go();\n
-getter History::length(unsigned long);\n
-method History::pushState();\n
-method History::replaceState();\n
-getter History::state(any);\n
-method HTMLAllCollection::item();\n
-getter HTMLAllCollection::length(unsigned long);\n
-method HTMLAllCollection::namedItem();\n
-getter HTMLAnchorElement::download(string);\n
-setter HTMLAnchorElement::download(string);\n
-getter HTMLAnchorElement::hash(user);\n
-setter HTMLAnchorElement::hash(user);\n
-getter HTMLAnchorElement::hostname(user);\n
-setter HTMLAnchorElement::hostname(user);\n
-getter HTMLAnchorElement::host(user);\n
-setter HTMLAnchorElement::host(user);\n
-getter HTMLAnchorElement::href(user);\n
-setter HTMLAnchorElement::href(user);\n
-getter HTMLAnchorElement::origin(user);\n
-getter HTMLAnchorElement::password(user);\n
-setter HTMLAnchorElement::password(user);\n
-getter HTMLAnchorElement::pathname(user);\n
-setter HTMLAnchorElement::pathname(user);\n
-getter HTMLAnchorElement::ping(user);\n
-getter HTMLAnchorElement::port(user);\n
-setter HTMLAnchorElement::port(user);\n
-getter HTMLAnchorElement::protocol(user);\n
-setter HTMLAnchorElement::protocol(user);\n
-getter HTMLAnchorElement::relList(user);\n
-getter HTMLAnchorElement::search(user);\n
-setter HTMLAnchorElement::search(user);\n
-getter HTMLAnchorElement::text(string);\n
-setter HTMLAnchorElement::text(string);\n
-getter HTMLAnchorElement::type(string);\n
-setter HTMLAnchorElement::type(string);\n
-getter HTMLAnchorElement::username(user);\n
-setter HTMLAnchorElement::username(user);\n
-getter HTMLAppletElement::hspace(unsigned long);\n
-setter HTMLAppletElement::hspace(unsigned long);\n
-getter HTMLAppletElement::vspace(unsigned long);\n
-setter HTMLAppletElement::vspace(unsigned long);\n
-getter HTMLAreaElement::download(string);\n
-setter HTMLAreaElement::download(string);\n
-getter HTMLAreaElement::hash(user);\n
-setter HTMLAreaElement::hash(user);\n
-getter HTMLAreaElement::hostname(user);\n
-setter HTMLAreaElement::hostname(user);\n
-getter HTMLAreaElement::host(user);\n
-setter HTMLAreaElement::host(user);\n
-getter HTMLAreaElement::hreflang(string);\n
-setter HTMLAreaElement::hreflang(string);\n
-getter HTMLAreaElement::href(user);\n
-setter HTMLAreaElement::href(user);\n
-getter HTMLAreaElement::origin(user);\n
-getter HTMLAreaElement::password(user);\n
-setter HTMLAreaElement::password(user);\n
-getter HTMLAreaElement::pathname(user);\n
-setter HTMLAreaElement::pathname(user);\n
-getter HTMLAreaElement::ping(user);\n
-getter HTMLAreaElement::port(user);\n
-setter HTMLAreaElement::port(user);\n
-getter HTMLAreaElement::protocol(user);\n
-setter HTMLAreaElement::protocol(user);\n
-getter HTMLAreaElement::relList(user);\n
-getter HTMLAreaElement::rel(string);\n
-setter HTMLAreaElement::rel(string);\n
-getter HTMLAreaElement::search(user);\n
-setter HTMLAreaElement::search(user);\n
-getter HTMLAreaElement::type(string);\n
-setter HTMLAreaElement::type(string);\n
-getter HTMLAreaElement::username(user);\n
-setter HTMLAreaElement::username(user);\n
-getter HTMLBodyElement::onafterprint(user);\n
-setter HTMLBodyElement::onafterprint(user);\n
-getter HTMLBodyElement::onbeforeprint(user);\n
-setter HTMLBodyElement::onbeforeprint(user);\n
-getter HTMLBodyElement::onbeforeunload(user);\n
-setter HTMLBodyElement::onbeforeunload(user);\n
-getter HTMLBodyElement::onhashchange(user);\n
-setter HTMLBodyElement::onhashchange(user);\n
-getter HTMLBodyElement::onlanguagechange(user);\n
-setter HTMLBodyElement::onlanguagechange(user);\n
-getter HTMLBodyElement::onmessage(user);\n
-setter HTMLBodyElement::onmessage(user);\n
-getter HTMLBodyElement::onoffline(user);\n
-setter HTMLBodyElement::onoffline(user);\n
-getter HTMLBodyElement::ononline(user);\n
-setter HTMLBodyElement::ononline(user);\n
-getter HTMLBodyElement::onpagehide(user);\n
-setter HTMLBodyElement::onpagehide(user);\n
-getter HTMLBodyElement::onpageshow(user);\n
-setter HTMLBodyElement::onpageshow(user);\n
-getter HTMLBodyElement::onpopstate(user);\n
-setter HTMLBodyElement::onpopstate(user);\n
-getter HTMLBodyElement::onstorage(user);\n
-setter HTMLBodyElement::onstorage(user);\n
-getter HTMLBodyElement::onunload(user);\n
-setter HTMLBodyElement::onunload(user);\n
-getter HTMLButtonElement::autofocus(boolean);\n
-setter HTMLButtonElement::autofocus(boolean);\n
-method HTMLButtonElement::checkValidity();\n
-getter HTMLButtonElement::formAction(string);\n
-setter HTMLButtonElement::formAction(string);\n
-getter HTMLButtonElement::formEnctype(string);\n
-setter HTMLButtonElement::formEnctype(string);\n
-getter HTMLButtonElement::formMethod(string);\n
-setter HTMLButtonElement::formMethod(string);\n
-getter HTMLButtonElement::formNoValidate(boolean);\n
-setter HTMLButtonElement::formNoValidate(boolean);\n
-getter HTMLButtonElement::formTarget(string);\n
-setter HTMLButtonElement::formTarget(string);\n
-getter HTMLButtonElement::form(user);\n
-getter HTMLButtonElement::labels(user);\n
-getter HTMLButtonElement::menu(user);\n
-setter HTMLButtonElement::menu(user);\n
-method HTMLButtonElement::reportValidity();\n
-method HTMLButtonElement::setCustomValidity();\n
-getter HTMLButtonElement::type(string);\n
-setter HTMLButtonElement::type(string);\n
-getter HTMLButtonElement::validationMessage(string);\n
-getter HTMLButtonElement::validity(user);\n
-getter HTMLButtonElement::willValidate(boolean);\n
-method HTMLCanvasElement::getContext();\n
-getter HTMLCanvasElement::height(unsigned long);\n
-setter HTMLCanvasElement::height(unsigned long);\n
-method HTMLCanvasElement::probablySupportsContext();\n
-method HTMLCanvasElement::setContext();\n
-method HTMLCanvasElement::toBlob();\n
-method HTMLCanvasElement::toDataURL();\n
-method HTMLCanvasElement::transferControlToProxy();\n
-getter HTMLCanvasElement::width(unsigned long);\n
-setter HTMLCanvasElement::width(unsigned long);\n
-method HTMLCollection::item();\n
-getter HTMLCollection::length(unsigned long);\n
-method HTMLCollection::namedItem();\n
-getter HTMLDataElement::value(string);\n
-setter HTMLDataElement::value(string);\n
-getter HTMLDataListElement::options(user);\n
-getter HTMLDetailsElement::open(boolean);\n
-setter HTMLDetailsElement::open(boolean);\n
-method HTMLDialogElement::close();\n
-getter HTMLDialogElement::open(boolean);\n
-setter HTMLDialogElement::open(boolean);\n
-getter HTMLDialogElement::returnValue(string);\n
-setter HTMLDialogElement::returnValue(string);\n
-method HTMLDialogElement::show();\n
-method HTMLDialogElement::showModal();\n
-getter HTMLDirectoryElement::compact(boolean);\n
-setter HTMLDirectoryElement::compact(boolean);\n
-getter HTMLDListElement::compact(boolean);\n
-setter HTMLDListElement::compact(boolean);\n
-getter HTMLElement::accessKeyLabel(string);\n
-getter HTMLElement::accessKey(string);\n
-setter HTMLElement::accessKey(string);\n
-method HTMLElement::blur();\n
-method HTMLElement::click();\n
-getter HTMLElement::commandChecked(boolean);\n
-getter HTMLElement::commandDisabled(boolean);\n
-getter HTMLElement::commandHidden(boolean);\n
-getter HTMLElement::commandIcon(string);\n
-getter HTMLElement::commandLabel(string);\n
-getter HTMLElement::commandType(string);\n
-getter HTMLElement::contentEditable(string);\n
-setter HTMLElement::contentEditable(string);\n
-getter HTMLElement::contextMenu(user);\n
-setter HTMLElement::contextMenu(user);\n
-getter HTMLElement::dataset(user);\n
-getter HTMLElement::draggable(boolean);\n
-setter HTMLElement::draggable(boolean);\n
-getter HTMLElement::dropzone(user);\n
-method HTMLElement::focus();\n
-method HTMLElement::forceSpellCheck();\n
-getter HTMLElement::hidden(boolean);\n
-setter HTMLElement::hidden(boolean);\n
-getter HTMLElement::isContentEditable(boolean);\n
-getter HTMLElement::onerror(user);\n
-setter HTMLElement::onerror(user);\n
-getter HTMLElement::spellcheck(boolean);\n
-setter HTMLElement::spellcheck(boolean);\n
-getter HTMLElement::tabIndex(long);\n
-setter HTMLElement::tabIndex(long);\n
-getter HTMLElement::translate(boolean);\n
-setter HTMLElement::translate(boolean);\n
-getter HTMLEmbedElement::align(string);\n
-setter HTMLEmbedElement::align(string);\n
-method HTMLEmbedElement::getSVGDocument();\n
-getter HTMLEmbedElement::height(string);\n
-setter HTMLEmbedElement::height(string);\n
-getter HTMLEmbedElement::name(string);\n
-setter HTMLEmbedElement::name(string);\n
-getter HTMLEmbedElement::src(string);\n
-setter HTMLEmbedElement::src(string);\n
-getter HTMLEmbedElement::type(string);\n
-setter HTMLEmbedElement::type(string);\n
-getter HTMLEmbedElement::width(string);\n
-setter HTMLEmbedElement::width(string);\n
-method HTMLFieldSetElement::checkValidity();\n
-getter HTMLFieldSetElement::disabled(boolean);\n
-setter HTMLFieldSetElement::disabled(boolean);\n
-getter HTMLFieldSetElement::elements(user);\n
-getter HTMLFieldSetElement::form(user);\n
-getter HTMLFieldSetElement::name(string);\n
-setter HTMLFieldSetElement::name(string);\n
-method HTMLFieldSetElement::reportValidity();\n
-method HTMLFieldSetElement::setCustomValidity();\n
-getter HTMLFieldSetElement::type(string);\n
-getter HTMLFieldSetElement::validationMessage(string);\n
-getter HTMLFieldSetElement::validity(user);\n
-getter HTMLFieldSetElement::willValidate(boolean);\n
-method HTMLFormControlsCollection::namedItem();\n
-getter HTMLFormElement::autocomplete(string);\n
-setter HTMLFormElement::autocomplete(string);\n
-method HTMLFormElement::checkValidity();\n
-getter HTMLFormElement::elements(user);\n
-getter HTMLFormElement::encoding(string);\n
-setter HTMLFormElement::encoding(string);\n
-getter HTMLFormElement::length(long);\n
-getter HTMLFormElement::name(string);\n
-setter HTMLFormElement::name(string);\n
-getter HTMLFormElement::noValidate(boolean);\n
-setter HTMLFormElement::noValidate(boolean);\n
-method HTMLFormElement::reportValidity();\n
-method HTMLFormElement::requestAutocomplete();\n
-method HTMLFormElement::reset();\n
-method HTMLFormElement::submit();\n
-getter HTMLFrameElement::contentDocument(user);\n
-getter HTMLFrameElement::contentWindow(user);\n
-getter HTMLFrameSetElement::onafterprint(user);\n
-setter HTMLFrameSetElement::onafterprint(user);\n
-getter HTMLFrameSetElement::onbeforeprint(user);\n
-setter HTMLFrameSetElement::onbeforeprint(user);\n
-getter HTMLFrameSetElement::onbeforeunload(user);\n
-setter HTMLFrameSetElement::onbeforeunload(user);\n
-getter HTMLFrameSetElement::onhashchange(user);\n
-setter HTMLFrameSetElement::onhashchange(user);\n
-getter HTMLFrameSetElement::onlanguagechange(user);\n
-setter HTMLFrameSetElement::onlanguagechange(user);\n
-getter HTMLFrameSetElement::onmessage(user);\n
-setter HTMLFrameSetElement::onmessage(user);\n
-getter HTMLFrameSetElement::onoffline(user);\n
-setter HTMLFrameSetElement::onoffline(user);\n
-getter HTMLFrameSetElement::ononline(user);\n
-setter HTMLFrameSetElement::ononline(user);\n
-getter HTMLFrameSetElement::onpagehide(user);\n
-setter HTMLFrameSetElement::onpagehide(user);\n
-getter HTMLFrameSetElement::onpageshow(user);\n
-setter HTMLFrameSetElement::onpageshow(user);\n
-getter HTMLFrameSetElement::onpopstate(user);\n
-setter HTMLFrameSetElement::onpopstate(user);\n
-getter HTMLFrameSetElement::onstorage(user);\n
-setter HTMLFrameSetElement::onstorage(user);\n
-getter HTMLFrameSetElement::onunload(user);\n
-setter HTMLFrameSetElement::onunload(user);\n
-getter HTMLHRElement::color(string);\n
-setter HTMLHRElement::color(string);\n
-getter HTMLIFrameElement::allowFullscreen(boolean);\n
-setter HTMLIFrameElement::allowFullscreen(boolean);\n
-getter HTMLIFrameElement::contentDocument(user);\n
-getter HTMLIFrameElement::contentWindow(user);\n
-method HTMLIFrameElement::getSVGDocument();\n
-getter HTMLIFrameElement::sandbox(user);\n
-getter HTMLIFrameElement::seamless(boolean);\n
-setter HTMLIFrameElement::seamless(boolean);\n
-getter HTMLIFrameElement::srcdoc(string);\n
-setter HTMLIFrameElement::srcdoc(string);\n
-getter HTMLImageElement::complete(boolean);\n
-getter HTMLImageElement::crossOrigin(string);\n
-setter HTMLImageElement::crossOrigin(string);\n
-getter HTMLImageElement::currentSrc(string);\n
-getter HTMLImageElement::lowsrc(string);\n
-setter HTMLImageElement::lowsrc(string);\n
-getter HTMLImageElement::naturalHeight(unsigned long);\n
-getter HTMLImageElement::naturalWidth(unsigned long);\n
-getter HTMLImageElement::sizes(string);\n
-setter HTMLImageElement::sizes(string);\n
-getter HTMLImageElement::srcset(string);\n
-setter HTMLImageElement::srcset(string);\n
-getter HTMLInputElement::autocomplete(string);\n
-setter HTMLInputElement::autocomplete(string);\n
-getter HTMLInputElement::autofocus(boolean);\n
-setter HTMLInputElement::autofocus(boolean);\n
-method HTMLInputElement::checkValidity();\n
-getter HTMLInputElement::dirName(string);\n
-setter HTMLInputElement::dirName(string);\n
-getter HTMLInputElement::files(user);\n
-getter HTMLInputElement::formAction(string);\n
-setter HTMLInputElement::formAction(string);\n
-getter HTMLInputElement::formEnctype(string);\n
-setter HTMLInputElement::formEnctype(string);\n
-getter HTMLInputElement::formMethod(string);\n
-setter HTMLInputElement::formMethod(string);\n
-getter HTMLInputElement::formNoValidate(boolean);\n
-setter HTMLInputElement::formNoValidate(boolean);\n
-getter HTMLInputElement::formTarget(string);\n
-setter HTMLInputElement::formTarget(string);\n
-getter HTMLInputElement::form(user);\n
-getter HTMLInputElement::height(unsigned long);\n
-setter HTMLInputElement::height(unsigned long);\n
-getter HTMLInputElement::indeterminate(boolean);\n
-setter HTMLInputElement::indeterminate(boolean);\n
-getter HTMLInputElement::inputMode(string);\n
-setter HTMLInputElement::inputMode(string);\n
-getter HTMLInputElement::labels(user);\n
-getter HTMLInputElement::list(user);\n
-getter HTMLInputElement::max(string);\n
-setter HTMLInputElement::max(string);\n
-getter HTMLInputElement::minLength(long);\n
-setter HTMLInputElement::minLength(long);\n
-getter HTMLInputElement::min(string);\n
-setter HTMLInputElement::min(string);\n
-getter HTMLInputElement::multiple(boolean);\n
-setter HTMLInputElement::multiple(boolean);\n
-getter HTMLInputElement::pattern(string);\n
-setter HTMLInputElement::pattern(string);\n
-getter HTMLInputElement::placeholder(string);\n
-setter HTMLInputElement::placeholder(string);\n
-method HTMLInputElement::reportValidity();\n
-getter HTMLInputElement::required(boolean);\n
-setter HTMLInputElement::required(boolean);\n
-method HTMLInputElement::select();\n
-getter HTMLInputElement::selectionDirection(string);\n
-setter HTMLInputElement::selectionDirection(string);\n
-getter HTMLInputElement::selectionEnd(unsigned long);\n
-setter HTMLInputElement::selectionEnd(unsigned long);\n
-getter HTMLInputElement::selectionStart(unsigned long);\n
-setter HTMLInputElement::selectionStart(unsigned long);\n
-method HTMLInputElement::setCustomValidity();\n
-method HTMLInputElement::setRangeText();\n
-method HTMLInputElement::setSelectionRange();\n
-method HTMLInputElement::stepDown();\n
-getter HTMLInputElement::step(string);\n
-setter HTMLInputElement::step(string);\n
-method HTMLInputElement::stepUp();\n
-setter HTMLInputElement::type(string);\n
-getter HTMLInputElement::validationMessage(string);\n
-getter HTMLInputElement::validity(user);\n
-getter HTMLInputElement::valueAsDate(date);\n
-setter HTMLInputElement::valueAsDate(date);\n
-getter HTMLInputElement::valueAsNumber(double);\n
-setter HTMLInputElement::valueAsNumber(double);\n
-getter HTMLInputElement::valueHigh(double);\n
-setter HTMLInputElement::valueHigh(double);\n
-getter HTMLInputElement::valueLow(double);\n
-setter HTMLInputElement::valueLow(double);\n
-getter HTMLInputElement::width(unsigned long);\n
-setter HTMLInputElement::width(unsigned long);\n
-getter HTMLInputElement::willValidate(boolean);\n
-getter HTMLKeygenElement::autofocus(boolean);\n
-setter HTMLKeygenElement::autofocus(boolean);\n
-getter HTMLKeygenElement::challenge(string);\n
-setter HTMLKeygenElement::challenge(string);\n
-method HTMLKeygenElement::checkValidity();\n
-getter HTMLKeygenElement::disabled(boolean);\n
-setter HTMLKeygenElement::disabled(boolean);\n
-getter HTMLKeygenElement::form(user);\n
-getter HTMLKeygenElement::keytype(string);\n
-setter HTMLKeygenElement::keytype(string);\n
-getter HTMLKeygenElement::labels(user);\n
-getter HTMLKeygenElement::name(string);\n
-setter HTMLKeygenElement::name(string);\n
-method HTMLKeygenElement::reportValidity();\n
-method HTMLKeygenElement::setCustomValidity();\n
-getter HTMLKeygenElement::type(string);\n
-getter HTMLKeygenElement::validationMessage(string);\n
-getter HTMLKeygenElement::validity(user);\n
-getter HTMLKeygenElement::willValidate(boolean);\n
-getter HTMLLabelElement::control(user);\n
-getter HTMLLabelElement::form(user);\n
-getter HTMLLegendElement::form(user);\n
-getter HTMLLinkElement::crossOrigin(string);\n
-setter HTMLLinkElement::crossOrigin(string);\n
-getter HTMLLinkElement::relList(user);\n
-getter HTMLLinkElement::sheet(user);\n
-getter HTMLLinkElement::sizes(user);\n
-getter HTMLMapElement::areas(user);\n
-getter HTMLMarqueeElement::behavior(string);\n
-setter HTMLMarqueeElement::behavior(string);\n
-getter HTMLMarqueeElement::bgColor(string);\n
-setter HTMLMarqueeElement::bgColor(string);\n
-getter HTMLMarqueeElement::direction(string);\n
-setter HTMLMarqueeElement::direction(string);\n
-getter HTMLMarqueeElement::height(string);\n
-setter HTMLMarqueeElement::height(string);\n
-getter HTMLMarqueeElement::hspace(unsigned long);\n
-setter HTMLMarqueeElement::hspace(unsigned long);\n
-getter HTMLMarqueeElement::loop(long);\n
-setter HTMLMarqueeElement::loop(long);\n
-getter HTMLMarqueeElement::onbounce(user);\n
-setter HTMLMarqueeElement::onbounce(user);\n
-getter HTMLMarqueeElement::onfinish(user);\n
-setter HTMLMarqueeElement::onfinish(user);\n
-getter HTMLMarqueeElement::onstart(user);\n
-setter HTMLMarqueeElement::onstart(user);\n
-getter HTMLMarqueeElement::scrollAmount(unsigned long);\n
-setter HTMLMarqueeElement::scrollAmount(unsigned long);\n
-getter HTMLMarqueeElement::scrollDelay(unsigned long);\n
-setter HTMLMarqueeElement::scrollDelay(unsigned long);\n
-method HTMLMarqueeElement::start();\n
-method HTMLMarqueeElement::stop();\n
-getter HTMLMarqueeElement::trueSpeed(boolean);\n
-setter HTMLMarqueeElement::trueSpeed(boolean);\n
-getter HTMLMarqueeElement::vspace(unsigned long);\n
-setter HTMLMarqueeElement::vspace(unsigned long);\n
-getter HTMLMarqueeElement::width(string);\n
-setter HTMLMarqueeElement::width(string);\n
-method HTMLMediaElement::addTextTrack();\n
-getter HTMLMediaElement::audioTracks(user);\n
-getter HTMLMediaElement::autoplay(boolean);\n
-setter HTMLMediaElement::autoplay(boolean);\n
-getter HTMLMediaElement::buffered(user);\n
-method HTMLMediaElement::canPlayType();\n
-getter HTMLMediaElement::controller(user);\n
-setter HTMLMediaElement::controller(user);\n
-getter HTMLMediaElement::controls(boolean);\n
-setter HTMLMediaElement::controls(boolean);\n
-getter HTMLMediaElement::crossOrigin(string);\n
-setter HTMLMediaElement::crossOrigin(string);\n
-getter HTMLMediaElement::currentSrc(string);\n
-getter HTMLMediaElement::currentTime(double);\n
-setter HTMLMediaElement::currentTime(double);\n
-getter HTMLMediaElement::defaultMuted(boolean);\n
-setter HTMLMediaElement::defaultMuted(boolean);\n
-getter HTMLMediaElement::defaultPlaybackRate(double);\n
-setter HTMLMediaElement::defaultPlaybackRate(double);\n
-getter HTMLMediaElement::duration(double);\n
-getter HTMLMediaElement::ended(boolean);\n
-getter HTMLMediaElement::error(user);\n
-method HTMLMediaElement::fastSeek();\n
-method HTMLMediaElement::getStartDate();\n
-method HTMLMediaElement::load();\n
-getter HTMLMediaElement::loop(boolean);\n
-setter HTMLMediaElement::loop(boolean);\n
-getter HTMLMediaElement::mediaGroup(string);\n
-setter HTMLMediaElement::mediaGroup(string);\n
-getter HTMLMediaElement::muted(boolean);\n
-setter HTMLMediaElement::muted(boolean);\n
-getter HTMLMediaElement::networkState(unsigned short);\n
-method HTMLMediaElement::pause();\n
-getter HTMLMediaElement::paused(boolean);\n
-method HTMLMediaElement::play();\n
-getter HTMLMediaElement::playbackRate(double);\n
-setter HTMLMediaElement::playbackRate(double);\n
-getter HTMLMediaElement::played(user);\n
-getter HTMLMediaElement::preload(string);\n
-setter HTMLMediaElement::preload(string);\n
-getter HTMLMediaElement::readyState(unsigned short);\n
-getter HTMLMediaElement::seekable(user);\n
-getter HTMLMediaElement::seeking(boolean);\n
-getter HTMLMediaElement::srcObject(user);\n
-setter HTMLMediaElement::srcObject(user);\n
-getter HTMLMediaElement::src(string);\n
-setter HTMLMediaElement::src(string);\n
-getter HTMLMediaElement::textTracks(user);\n
-getter HTMLMediaElement::videoTracks(user);\n
-getter HTMLMediaElement::volume(double);\n
-setter HTMLMediaElement::volume(double);\n
-getter HTMLMenuElement::label(string);\n
-setter HTMLMenuElement::label(string);\n
-getter HTMLMenuElement::type(string);\n
-setter HTMLMenuElement::type(string);\n
-getter HTMLMenuItemElement::checked(boolean);\n
-setter HTMLMenuItemElement::checked(boolean);\n
-getter HTMLMenuItemElement::command(user);\n
-getter HTMLMenuItemElement::default(boolean);\n
-setter HTMLMenuItemElement::default(boolean);\n
-getter HTMLMenuItemElement::disabled(boolean);\n
-setter HTMLMenuItemElement::disabled(boolean);\n
-getter HTMLMenuItemElement::icon(string);\n
-setter HTMLMenuItemElement::icon(string);\n
-getter HTMLMenuItemElement::label(string);\n
-setter HTMLMenuItemElement::label(string);\n
-getter HTMLMenuItemElement::radiogroup(string);\n
-setter HTMLMenuItemElement::radiogroup(string);\n
-getter HTMLMenuItemElement::type(string);\n
-setter HTMLMenuItemElement::type(string);\n
-getter HTMLMeterElement::high(double);\n
-setter HTMLMeterElement::high(double);\n
-getter HTMLMeterElement::labels(user);\n
-getter HTMLMeterElement::low(double);\n
-setter HTMLMeterElement::low(double);\n
-getter HTMLMeterElement::max(double);\n
-setter HTMLMeterElement::max(double);\n
-getter HTMLMeterElement::min(double);\n
-setter HTMLMeterElement::min(double);\n
-getter HTMLMeterElement::optimum(double);\n
-setter HTMLMeterElement::optimum(double);\n
-getter HTMLMeterElement::value(double);\n
-setter HTMLMeterElement::value(double);\n
-getter HTMLModElement::cite(string);\n
-setter HTMLModElement::cite(string);\n
-getter HTMLModElement::dateTime(string);\n
-setter HTMLModElement::dateTime(string);\n
-method HTMLObjectElement::checkValidity();\n
-getter HTMLObjectElement::contentDocument(user);\n
-getter HTMLObjectElement::contentWindow(user);\n
-getter HTMLObjectElement::form(user);\n
-method HTMLObjectElement::getSVGDocument();\n
-getter HTMLObjectElement::hspace(unsigned long);\n
-setter HTMLObjectElement::hspace(unsigned long);\n
-method HTMLObjectElement::reportValidity();\n
-method HTMLObjectElement::setCustomValidity();\n
-getter HTMLObjectElement::typeMustMatch(boolean);\n
-setter HTMLObjectElement::typeMustMatch(boolean);\n
-getter HTMLObjectElement::validationMessage(string);\n
-getter HTMLObjectElement::validity(user);\n
-getter HTMLObjectElement::vspace(unsigned long);\n
-setter HTMLObjectElement::vspace(unsigned long);\n
-getter HTMLObjectElement::willValidate(boolean);\n
-getter HTMLOListElement::reversed(boolean);\n
-setter HTMLOListElement::reversed(boolean);\n
-getter HTMLOptGroupElement::disabled(boolean);\n
-setter HTMLOptGroupElement::disabled(boolean);\n
-getter HTMLOptGroupElement::label(string);\n
-setter HTMLOptGroupElement::label(string);\n
-getter HTMLOptionElement::form(user);\n
-getter HTMLOptionElement::index(long);\n
-setter HTMLOptionElement::text(string);\n
-method HTMLOptionsCollection::add();\n
-getter HTMLOptionsCollection::length(unsigned long);\n
-setter HTMLOptionsCollection::length(unsigned long);\n
-method HTMLOptionsCollection::remove();\n
-getter HTMLOptionsCollection::selectedIndex(long);\n
-setter HTMLOptionsCollection::selectedIndex(long);\n
-method HTMLOutputElement::checkValidity();\n
-getter HTMLOutputElement::defaultValue(string);\n
-setter HTMLOutputElement::defaultValue(string);\n
-getter HTMLOutputElement::form(user);\n
-getter HTMLOutputElement::htmlFor(user);\n
-getter HTMLOutputElement::labels(user);\n
-getter HTMLOutputElement::name(string);\n
-setter HTMLOutputElement::name(string);\n
-method HTMLOutputElement::reportValidity();\n
-method HTMLOutputElement::setCustomValidity();\n
-getter HTMLOutputElement::type(string);\n
-getter HTMLOutputElement::validationMessage(string);\n
-getter HTMLOutputElement::validity(user);\n
-getter HTMLOutputElement::value(string);\n
-setter HTMLOutputElement::value(string);\n
-getter HTMLOutputElement::willValidate(boolean);\n
-getter HTMLProgressElement::labels(user);\n
-getter HTMLProgressElement::max(double);\n
-setter HTMLProgressElement::max(double);\n
-getter HTMLProgressElement::position(double);\n
-getter HTMLProgressElement::value(double);\n
-setter HTMLProgressElement::value(double);\n
-getter HTMLScriptElement::async(boolean);\n
-setter HTMLScriptElement::async(boolean);\n
-getter HTMLScriptElement::crossOrigin(string);\n
-setter HTMLScriptElement::crossOrigin(string);\n
-getter HTMLScriptElement::nonce(string);\n
-setter HTMLScriptElement::nonce(string);\n
-method HTMLSelectElement::add();\n
-getter HTMLSelectElement::autocomplete(string);\n
-setter HTMLSelectElement::autocomplete(string);\n
-getter HTMLSelectElement::autofocus(boolean);\n
-setter HTMLSelectElement::autofocus(boolean);\n
-method HTMLSelectElement::checkValidity();\n
-getter HTMLSelectElement::form(user);\n
-method HTMLSelectElement::item();\n
-getter HTMLSelectElement::labels(user);\n
-getter HTMLSelectElement::length(unsigned long);\n
-setter HTMLSelectElement::length(unsigned long);\n
-method HTMLSelectElement::namedItem();\n
-getter HTMLSelectElement::options(user);\n
-method HTMLSelectElement::remove();\n
-method HTMLSelectElement::reportValidity();\n
-getter HTMLSelectElement::required(boolean);\n
-setter HTMLSelectElement::required(boolean);\n
-getter HTMLSelectElement::selectedIndex(long);\n
-setter HTMLSelectElement::selectedIndex(long);\n
-getter HTMLSelectElement::selectedOptions(user);\n
-method HTMLSelectElement::setCustomValidity();\n
-getter HTMLSelectElement::size(unsigned long);\n
-setter HTMLSelectElement::size(unsigned long);\n
-getter HTMLSelectElement::validationMessage(string);\n
-getter HTMLSelectElement::validity(user);\n
-getter HTMLSelectElement::willValidate(boolean);\n
-getter HTMLSourceElement::media(string);\n
-setter HTMLSourceElement::media(string);\n
-getter HTMLSourceElement::sizes(string);\n
-setter HTMLSourceElement::sizes(string);\n
-getter HTMLSourceElement::srcset(string);\n
-setter HTMLSourceElement::srcset(string);\n
-getter HTMLSourceElement::src(string);\n
-setter HTMLSourceElement::src(string);\n
-getter HTMLSourceElement::type(string);\n
-setter HTMLSourceElement::type(string);\n
-getter HTMLStyleElement::nonce(string);\n
-setter HTMLStyleElement::nonce(string);\n
-getter HTMLStyleElement::scoped(boolean);\n
-setter HTMLStyleElement::scoped(boolean);\n
-getter HTMLStyleElement::sheet(user);\n
-getter HTMLTableCellElement::headers(user);\n
-getter HTMLTableColElement::span(unsigned long);\n
-setter HTMLTableColElement::span(unsigned long);\n
-getter HTMLTableDataCellElement::abbr(string);\n
-setter HTMLTableDataCellElement::abbr(string);\n
-getter HTMLTableElement::caption(user);\n
-setter HTMLTableElement::caption(user);\n
-method HTMLTableElement::createCaption();\n
-method HTMLTableElement::createTBody();\n
-method HTMLTableElement::createTFoot();\n
-method HTMLTableElement::createTHead();\n
-method HTMLTableElement::deleteCaption();\n
-method HTMLTableElement::deleteRow();\n
-method HTMLTableElement::deleteTFoot();\n
-method HTMLTableElement::deleteTHead();\n
-method HTMLTableElement::insertRow();\n
-getter HTMLTableElement::rows(user);\n
-getter HTMLTableElement::sortable(boolean);\n
-setter HTMLTableElement::sortable(boolean);\n
-method HTMLTableElement::stopSorting();\n
-getter HTMLTableElement::tBodies(user);\n
-getter HTMLTableElement::tFoot(user);\n
-setter HTMLTableElement::tFoot(user);\n
-getter HTMLTableElement::tHead(user);\n
-setter HTMLTableElement::tHead(user);\n
-getter HTMLTableHeaderCellElement::abbr(string);\n
-setter HTMLTableHeaderCellElement::abbr(string);\n
-getter HTMLTableHeaderCellElement::scope(string);\n
-setter HTMLTableHeaderCellElement::scope(string);\n
-method HTMLTableHeaderCellElement::sort();\n
-getter HTMLTableHeaderCellElement::sorted(string);\n
-setter HTMLTableHeaderCellElement::sorted(string);\n
-getter HTMLTableRowElement::cells(user);\n
-method HTMLTableRowElement::deleteCell();\n
-method HTMLTableRowElement::insertCell();\n
-method HTMLTableSectionElement::deleteRow();\n
-method HTMLTableSectionElement::insertRow();\n
-getter HTMLTableSectionElement::rows(user);\n
-getter HTMLTemplateElement::content(user);\n
-getter HTMLTextAreaElement::autocomplete(string);\n
-setter HTMLTextAreaElement::autocomplete(string);\n
-getter HTMLTextAreaElement::autofocus(boolean);\n
-setter HTMLTextAreaElement::autofocus(boolean);\n
-method HTMLTextAreaElement::checkValidity();\n
-getter HTMLTextAreaElement::cols(unsigned long);\n
-setter HTMLTextAreaElement::cols(unsigned long);\n
-getter HTMLTextAreaElement::dirName(string);\n
-setter HTMLTextAreaElement::dirName(string);\n
-getter HTMLTextAreaElement::form(user);\n
-getter HTMLTextAreaElement::inputMode(string);\n
-setter HTMLTextAreaElement::inputMode(string);\n
-getter HTMLTextAreaElement::labels(user);\n
-getter HTMLTextAreaElement::maxLength(long);\n
-setter HTMLTextAreaElement::maxLength(long);\n
-getter HTMLTextAreaElement::minLength(long);\n
-setter HTMLTextAreaElement::minLength(long);\n
-getter HTMLTextAreaElement::placeholder(string);\n
-setter HTMLTextAreaElement::placeholder(string);\n
-method HTMLTextAreaElement::reportValidity();\n
-getter HTMLTextAreaElement::required(boolean);\n
-setter HTMLTextAreaElement::required(boolean);\n
-getter HTMLTextAreaElement::rows(unsigned long);\n
-setter HTMLTextAreaElement::rows(unsigned long);\n
-method HTMLTextAreaElement::select();\n
-getter HTMLTextAreaElement::selectionDirection(string);\n
-setter HTMLTextAreaElement::selectionDirection(string);\n
-getter HTMLTextAreaElement::selectionEnd(unsigned long);\n
-setter HTMLTextAreaElement::selectionEnd(unsigned long);\n
-getter HTMLTextAreaElement::selectionStart(unsigned long);\n
-setter HTMLTextAreaElement::selectionStart(unsigned long);\n
-method HTMLTextAreaElement::setCustomValidity();\n
-method HTMLTextAreaElement::setRangeText();\n
-method HTMLTextAreaElement::setSelectionRange();\n
-getter HTMLTextAreaElement::textLength(unsigned long);\n
-getter HTMLTextAreaElement::validationMessage(string);\n
-getter HTMLTextAreaElement::validity(user);\n
-getter HTMLTextAreaElement::willValidate(boolean);\n
-getter HTMLTextAreaElement::wrap(string);\n
-setter HTMLTextAreaElement::wrap(string);\n
-getter HTMLTimeElement::dateTime(string);\n
-setter HTMLTimeElement::dateTime(string);\n
-getter HTMLTrackElement::default(boolean);\n
-setter HTMLTrackElement::default(boolean);\n
-getter HTMLTrackElement::kind(string);\n
-setter HTMLTrackElement::kind(string);\n
-getter HTMLTrackElement::label(string);\n
-setter HTMLTrackElement::label(string);\n
-getter HTMLTrackElement::readyState(unsigned short);\n
-getter HTMLTrackElement::srclang(string);\n
-setter HTMLTrackElement::srclang(string);\n
-getter HTMLTrackElement::src(string);\n
-setter HTMLTrackElement::src(string);\n
-getter HTMLTrackElement::track(user);\n
-getter HTMLUListElement::compact(boolean);\n
-setter HTMLUListElement::compact(boolean);\n
-getter HTMLUListElement::type(string);\n
-setter HTMLUListElement::type(string);\n
-getter HTMLVideoElement::height(unsigned long);\n
-setter HTMLVideoElement::height(unsigned long);\n
-getter HTMLVideoElement::poster(string);\n
-setter HTMLVideoElement::poster(string);\n
-getter HTMLVideoElement::videoHeight(unsigned long);\n
-getter HTMLVideoElement::videoWidth(unsigned long);\n
-getter HTMLVideoElement::width(unsigned long);\n
-setter HTMLVideoElement::width(unsigned long);\n
-getter ImageBitmap::height(unsigned long);\n
-getter ImageBitmap::width(unsigned long);\n
-getter ImageData::data(user);\n
-getter ImageData::height(unsigned long);\n
-getter ImageData::width(unsigned long);\n
-getter KeyboardEvent::altKey(boolean);\n
-getter KeyboardEvent::charCode(unsigned long);\n
-getter KeyboardEvent::code(string);\n
-getter KeyboardEvent::ctrlKey(boolean);\n
-method KeyboardEvent::getModifierState();\n
-method KeyboardEvent::initKeyboardEvent();\n
-getter KeyboardEvent::isComposing(boolean);\n
-getter KeyboardEvent::keyCode(unsigned long);\n
-getter KeyboardEvent::key(string);\n
-getter KeyboardEvent::location(unsigned long);\n
-getter KeyboardEvent::metaKey(boolean);\n
-getter KeyboardEvent::repeat(boolean);\n
-getter KeyboardEvent::shiftKey(boolean);\n
-getter KeyboardEvent::which(unsigned long);\n
-getter Location::ancestorOrigins(string);\n
-setter Location::hash(user);\n
-setter Location::hostname(user);\n
-setter Location::host(user);\n
-setter Location::password(user);\n
-setter Location::pathname(user);\n
-setter Location::port(user);\n
-setter Location::protocol(user);\n
-setter Location::search(user);\n
-setter Location::username(user);\n
-getter MediaController::buffered(user);\n
-getter MediaController::currentTime(double);\n
-setter MediaController::currentTime(double);\n
-getter MediaController::defaultPlaybackRate(double);\n
-setter MediaController::defaultPlaybackRate(double);\n
-getter MediaController::duration(double);\n
-getter MediaController::muted(boolean);\n
-setter MediaController::muted(boolean);\n
-getter MediaController::oncanplaythrough(user);\n
-setter MediaController::oncanplaythrough(user);\n
-getter MediaController::oncanplay(user);\n
-setter MediaController::oncanplay(user);\n
-getter MediaController::ondurationchange(user);\n
-setter MediaController::ondurationchange(user);\n
-getter MediaController::onemptied(user);\n
-setter MediaController::onemptied(user);\n
-getter MediaController::onended(user);\n
-setter MediaController::onended(user);\n
-getter MediaController::onloadeddata(user);\n
-setter MediaController::onloadeddata(user);\n
-getter MediaController::onloadedmetadata(user);\n
-setter MediaController::onloadedmetadata(user);\n
-getter MediaController::onpause(user);\n
-setter MediaController::onpause(user);\n
-getter MediaController::onplaying(user);\n
-setter MediaController::onplaying(user);\n
-getter MediaController::onplay(user);\n
-setter MediaController::onplay(user);\n
-getter MediaController::onratechange(user);\n
-setter MediaController::onratechange(user);\n
-getter MediaController::ontimeupdate(user);\n
-setter MediaController::ontimeupdate(user);\n
-getter MediaController::onvolumechange(user);\n
-setter MediaController::onvolumechange(user);\n
-getter MediaController::onwaiting(user);\n
-setter MediaController::onwaiting(user);\n
-method MediaController::pause();\n
-getter MediaController::paused(boolean);\n
-method MediaController::play();\n
-getter MediaController::playbackRate(double);\n
-setter MediaController::playbackRate(double);\n
-getter MediaController::playbackState(user);\n
-getter MediaController::played(user);\n
-getter MediaController::readyState(unsigned short);\n
-getter MediaController::seekable(user);\n
-method MediaController::unpause();\n
-getter MediaController::volume(double);\n
-setter MediaController::volume(double);\n
-getter MediaError::code(unsigned short);\n
-method MediaList::appendMedium();\n
-method MediaList::deleteMedium();\n
-method MediaList::item();\n
-getter MediaList::length(unsigned long);\n
-getter MediaList::mediaText(string);\n
-setter MediaList::mediaText(string);\n
-getter MessageChannel::port1(user);\n
-getter MessageChannel::port2(user);\n
-getter MessageEvent::data(any);\n
-method MessageEvent::initMessageEvent();\n
-getter MessageEvent::lastEventId(string);\n
-getter MessageEvent::origin(string);\n
-getter MessageEvent::ports(user);\n
-getter MessageEvent::source(multiple);\n
-method MessagePort::close();\n
-getter MessagePort::onmessage(user);\n
-setter MessagePort::onmessage(user);\n
-method MessagePort::postMessage();\n
-method MessagePort::start();\n
-method MimeTypeArray::item();\n
-getter MimeTypeArray::length(unsigned long);\n
-method MimeTypeArray::namedItem();\n
-getter MimeType::description(string);\n
-getter MimeType::enabledPlugin(user);\n
-getter MimeType::suffixes(string);\n
-getter MimeType::type(string);\n
-getter MouseEvent::altKey(boolean);\n
-getter MouseEvent::button(short);\n
-getter MouseEvent::buttons(unsigned short);\n
-getter MouseEvent::clientX(long);\n
-getter MouseEvent::clientY(long);\n
-getter MouseEvent::ctrlKey(boolean);\n
-method MouseEvent::getModifierState();\n
-method MouseEvent::initMouseEvent();\n
-getter MouseEvent::metaKey(boolean);\n
-getter MouseEvent::region(string);\n
-getter MouseEvent::relatedTarget(user);\n
-getter MouseEvent::screenX(long);\n
-getter MouseEvent::screenY(long);\n
-getter MouseEvent::shiftKey(boolean);\n
-getter MutationEvent::attrChange(unsigned short);\n
-getter MutationEvent::attrName(string);\n
-method MutationEvent::initMutationEvent();\n
-getter MutationEvent::newValue(string);\n
-getter MutationEvent::prevValue(string);\n
-getter MutationEvent::relatedNode(user);\n
-method MutationObserver::disconnect();\n
-method MutationObserver::observe();\n
-method MutationObserver::takeRecords();\n
-getter MutationRecord::addedNodes(user);\n
-getter MutationRecord::attributeNamespace(string);\n
-getter MutationRecord::attributeName(string);\n
-getter MutationRecord::nextSibling(user);\n
-getter MutationRecord::oldValue(string);\n
-getter MutationRecord::previousSibling(user);\n
-getter MutationRecord::removedNodes(user);\n
-getter MutationRecord::target(user);\n
-getter MutationRecord::type(string);\n
-method NamedNodeMap::getNamedItem();\n
-method NamedNodeMap::getNamedItemNS();\n
-method NamedNodeMap::item();\n
-getter NamedNodeMap::length(unsigned long);\n
-method NamedNodeMap::removeNamedItem();\n
-method NamedNodeMap::removeNamedItemNS();\n
-method NamedNodeMap::setNamedItem();\n
-method NamedNodeMap::setNamedItemNS();\n
-method Navigator::isContentHandlerRegistered();\n
-method Navigator::isProtocolHandlerRegistered();\n
-getter Navigator::languages(string);\n
-getter Navigator::language(string);\n
-getter Navigator::mimeTypes(user);\n
-getter Navigator::onLine(boolean);\n
-getter Navigator::plugins(user);\n
-method Navigator::registerContentHandler();\n
-method Navigator::registerProtocolHandler();\n
-method Navigator::unregisterContentHandler();\n
-method Navigator::unregisterProtocolHandler();\n
-method Navigator::yieldForStorageUpdates();\n
-method NodeFilter::acceptNode();\n
-method NodeIterator::detach();\n
-getter NodeIterator::filter(user);\n
-method NodeIterator::nextNode();\n
-getter NodeIterator::pointerBeforeReferenceNode(boolean);\n
-method NodeIterator::previousNode();\n
-getter NodeIterator::referenceNode(user);\n
-getter NodeIterator::root(user);\n
-getter NodeIterator::whatToShow(unsigned long);\n
-getter PageTransitionEvent::persisted(boolean);\n
-method Path2D::addPath();\n
-method Path2D::addPathByStrokingPath();\n
-method Path2D::addPathByStrokingText();\n
-method Path2D::addText();\n
-method Path2D::arc();\n
-method Path2D::arcTo();\n
-method Path2D::bezierCurveTo();\n
-method Path2D::closePath();\n
-method Path2D::ellipse();\n
-method Path2D::lineTo();\n
-method Path2D::moveTo();\n
-method Path2D::quadraticCurveTo();\n
-method Path2D::rect();\n
-method PluginArray::item();\n
-getter PluginArray::length(unsigned long);\n
-method PluginArray::namedItem();\n
-method PluginArray::refresh();\n
-getter Plugin::description(string);\n
-getter Plugin::filename(string);\n
-method Plugin::item();\n
-getter Plugin::length(unsigned long);\n
-method Plugin::namedItem();\n
-getter Plugin::name(string);\n
-getter PopStateEvent::state(any);\n
-getter ProcessingInstruction::sheet(user);\n
-getter ProcessingInstruction::target(string);\n
-getter PseudoElement::cascadedStyle(user);\n
-getter PseudoElement::defaultStyle(user);\n
-getter PseudoElement::rawComputedStyle(user);\n
-getter PseudoElement::usedStyle(user);\n
-getter RadioNodeList::value(string);\n
-setter RadioNodeList::value(string);\n
-method Range::cloneContents();\n
-method Range::cloneRange();\n
-method Range::collapse();\n
-getter Range::collapsed(boolean);\n
-getter Range::commonAncestorContainer(user);\n
-method Range::compareBoundaryPoints();\n
-method Range::comparePoint();\n
-method Range::createContextualFragment();\n
-method Range::deleteContents();\n
-method Range::detach();\n
-getter Range::endContainer(user);\n
-getter Range::endOffset(unsigned long);\n
-method Range::extractContents();\n
-method Range::insertNode();\n
-method Range::intersectsNode();\n
-method Range::isPointInRange();\n
-method Range::selectNode();\n
-method Range::selectNodeContents();\n
-method Range::setEnd();\n
-method Range::setEndAfter();\n
-method Range::setEndBefore();\n
-method Range::setStart();\n
-method Range::setStartAfter();\n
-method Range::setStartBefore();\n
-getter Range::startContainer(user);\n
-getter Range::startOffset(unsigned long);\n
-method Range::surroundContents();\n
-getter RelatedEvent::relatedTarget(user);\n
-getter SharedWorkerGlobalScope::applicationCache(user);\n
-getter SharedWorkerGlobalScope::name(string);\n
-getter SharedWorkerGlobalScope::onconnect(user);\n
-setter SharedWorkerGlobalScope::onconnect(user);\n
-getter SharedWorker::onerror(user);\n
-setter SharedWorker::onerror(user);\n
-getter SharedWorker::port(user);\n
-method Storage::clear();\n
-getter StorageEvent::key(string);\n
-getter StorageEvent::newValue(string);\n
-getter StorageEvent::oldValue(string);\n
-getter StorageEvent::storageArea(user);\n
-getter StorageEvent::url(string);\n
-method Storage::getItem();\n
-method Storage::key();\n
-getter Storage::length(unsigned long);\n
-method Storage::removeItem();\n
-method Storage::setItem();\n
-getter StyleSheet::disabled(boolean);\n
-setter StyleSheet::disabled(boolean);\n
-getter StyleSheet::href(string);\n
-method StyleSheetList::item();\n
-getter StyleSheetList::length(unsigned long);\n
-getter StyleSheet::media(user);\n
-getter StyleSheet::ownerNode(multiple);\n
-getter StyleSheet::parentStyleSheet(user);\n
-getter StyleSheet::title(string);\n
-getter StyleSheet::type(string);\n
-getter SVGElement::style(user);\n
-getter TextMetrics::actualBoundingBoxAscent(double);\n
-getter TextMetrics::actualBoundingBoxDescent(double);\n
-getter TextMetrics::actualBoundingBoxLeft(double);\n
-getter TextMetrics::actualBoundingBoxRight(double);\n
-getter TextMetrics::alphabeticBaseline(double);\n
-getter TextMetrics::emHeightAscent(double);\n
-getter TextMetrics::emHeightDescent(double);\n
-getter TextMetrics::fontBoundingBoxAscent(double);\n
-getter TextMetrics::fontBoundingBoxDescent(double);\n
-getter TextMetrics::hangingBaseline(double);\n
-getter TextMetrics::ideographicBaseline(double);\n
-getter TextMetrics::width(double);\n
-method Text::splitText();\n
-getter TextTrack::activeCues(user);\n
-method TextTrack::addCue();\n
-getter TextTrackCue::endTime(double);\n
-setter TextTrackCue::endTime(double);\n
-getter TextTrackCue::id(string);\n
-setter TextTrackCue::id(string);\n
-method TextTrackCueList::getCueById();\n
-getter TextTrackCueList::length(unsigned long);\n
-getter TextTrackCue::onenter(user);\n
-setter TextTrackCue::onenter(user);\n
-getter TextTrackCue::onexit(user);\n
-setter TextTrackCue::onexit(user);\n
-getter TextTrackCue::pauseOnExit(boolean);\n
-setter TextTrackCue::pauseOnExit(boolean);\n
-getter TextTrackCue::startTime(double);\n
-setter TextTrackCue::startTime(double);\n
-getter TextTrack::cues(user);\n
-getter TextTrackCue::track(user);\n
-getter TextTrack::id(string);\n
-getter TextTrack::inBandMetadataTrackDispatchType(string);\n
-getter TextTrack::kind(user);\n
-getter TextTrack::label(string);\n
-getter TextTrack::language(string);\n
-method TextTrackList::getTrackById();\n
-getter TextTrackList::length(unsigned long);\n
-getter TextTrackList::onaddtrack(user);\n
-setter TextTrackList::onaddtrack(user);\n
-getter TextTrackList::onchange(user);\n
-setter TextTrackList::onchange(user);\n
-getter TextTrackList::onremovetrack(user);\n
-setter TextTrackList::onremovetrack(user);\n
-getter TextTrack::mode(user);\n
-setter TextTrack::mode(user);\n
-getter TextTrack::oncuechange(user);\n
-setter TextTrack::oncuechange(user);\n
-method TextTrack::removeCue();\n
-getter Text::wholeText(string);\n
-method TimeRanges::end();\n
-getter TimeRanges::length(unsigned long);\n
-method TimeRanges::start();\n
-getter Touch::region(string);\n
-getter TrackEvent::track(multiple);\n
-getter TreeWalker::currentNode(user);\n
-setter TreeWalker::currentNode(user);\n
-getter TreeWalker::filter(user);\n
-method TreeWalker::firstChild();\n
-method TreeWalker::lastChild();\n
-method TreeWalker::nextNode();\n
-method TreeWalker::nextSibling();\n
-method TreeWalker::parentNode();\n
-method TreeWalker::previousNode();\n
-method TreeWalker::previousSibling();\n
-getter TreeWalker::root(user);\n
-getter TreeWalker::whatToShow(unsigned long);\n
-getter UIEvent::detail(long);\n
-method UIEvent::initUIEvent();\n
-getter UIEvent::view(user);\n
-method URL::domainToASCII();\n
-method URL::domainToUnicode();\n
-getter URL::hash(user);\n
-setter URL::hash(user);\n
-getter URL::hostname(user);\n
-setter URL::hostname(user);\n
-getter URL::host(user);\n
-setter URL::host(user);\n
-getter URL::href(user);\n
-setter URL::href(user);\n
-getter URL::origin(user);\n
-getter URL::password(user);\n
-setter URL::password(user);\n
-getter URL::pathname(user);\n
-setter URL::pathname(user);\n
-getter URL::port(user);\n
-setter URL::port(user);\n
-getter URL::protocol(user);\n
-setter URL::protocol(user);\n
-method URLSearchParams::append();\n
-method URLSearchParams::delete();\n
-method URLSearchParams::get();\n
-method URLSearchParams::getAll();\n
-method URLSearchParams::has();\n
-method URLSearchParams::set();\n
-getter URL::searchParams(user);\n
-setter URL::searchParams(user);\n
-getter URL::search(user);\n
-setter URL::search(user);\n
-getter URL::username(user);\n
-setter URL::username(user);\n
-getter ValidityState::badInput(boolean);\n
-getter ValidityState::customError(boolean);\n
-getter ValidityState::patternMismatch(boolean);\n
-getter ValidityState::rangeOverflow(boolean);\n
-getter ValidityState::rangeUnderflow(boolean);\n
-getter ValidityState::stepMismatch(boolean);\n
-getter ValidityState::tooLong(boolean);\n
-getter ValidityState::tooShort(boolean);\n
-getter ValidityState::typeMismatch(boolean);\n
-getter ValidityState::valid(boolean);\n
-getter ValidityState::valueMissing(boolean);\n
-getter VideoTrack::id(string);\n
-getter VideoTrack::kind(string);\n
-getter VideoTrack::label(string);\n
-getter VideoTrack::language(string);\n
-method VideoTrackList::getTrackById();\n
-getter VideoTrackList::length(unsigned long);\n
-getter VideoTrackList::onaddtrack(user);\n
-setter VideoTrackList::onaddtrack(user);\n
-getter VideoTrackList::onchange(user);\n
-setter VideoTrackList::onchange(user);\n
-getter VideoTrackList::onremovetrack(user);\n
-setter VideoTrackList::onremovetrack(user);\n
-getter VideoTrackList::selectedIndex(long);\n
-getter VideoTrack::selected(boolean);\n
-setter VideoTrack::selected(boolean);\n
-getter WebSocket::binaryType(user);\n
-setter WebSocket::binaryType(user);\n
-getter WebSocket::bufferedAmount(unsigned long);\n
-method WebSocket::close();\n
-getter WebSocket::extensions(string);\n
-getter WebSocket::onclose(user);\n
-setter WebSocket::onclose(user);\n
-getter WebSocket::onerror(user);\n
-setter WebSocket::onerror(user);\n
-getter WebSocket::onmessage(user);\n
-setter WebSocket::onmessage(user);\n
-getter WebSocket::onopen(user);\n
-setter WebSocket::onopen(user);\n
-getter WebSocket::protocol(string);\n
-getter WebSocket::readyState(unsigned short);\n
-method WebSocket::send();\n
-getter WebSocket::url(string);\n
-getter WheelEvent::deltaMode(unsigned long);\n
-getter WheelEvent::deltaX(double);\n
-getter WheelEvent::deltaY(double);\n
-getter WheelEvent::deltaZ(double);\n
-method WheelEvent::initWheelEvent();\n
-getter Window::applicationCache(user);\n
-method Window::atob();\n
-method Window::blur();\n
-method Window::btoa();\n
-method Window::cancelAnimationFrame();\n
-method Window::captureEvents();\n
-method Window::clearInterval();\n
-method Window::clearTimeout();\n
-method Window::close();\n
-getter Window::closed(boolean);\n
-method Window::confirm();\n
-method Window::createImageBitmap();\n
-getter Window::external(user);\n
-method Window::focus();\n
-getter Window::frameElement(user);\n
-getter Window::frames(user);\n
-method Window::getComputedStyle();\n
-getter Window::history(user);\n
-getter Window::length(unsigned long);\n
-getter Window::localStorage(user);\n
-getter Window::locationbar(user);\n
-getter Window::menubar(user);\n
-getter Window::onabort(user);\n
-setter Window::onabort(user);\n
-getter Window::onafterprint(user);\n
-setter Window::onafterprint(user);\n
-getter Window::onautocompleteerror(user);\n
-setter Window::onautocompleteerror(user);\n
-getter Window::onautocomplete(user);\n
-setter Window::onautocomplete(user);\n
-getter Window::onbeforeprint(user);\n
-setter Window::onbeforeprint(user);\n
-getter Window::onbeforeunload(user);\n
-setter Window::onbeforeunload(user);\n
-getter Window::onblur(user);\n
-setter Window::onblur(user);\n
-getter Window::oncancel(user);\n
-setter Window::oncancel(user);\n
-getter Window::oncanplaythrough(user);\n
-setter Window::oncanplaythrough(user);\n
-getter Window::oncanplay(user);\n
-setter Window::oncanplay(user);\n
-getter Window::onchange(user);\n
-setter Window::onchange(user);\n
-getter Window::onclick(user);\n
-setter Window::onclick(user);\n
-getter Window::onclose(user);\n
-setter Window::onclose(user);\n
-getter Window::oncontextmenu(user);\n
-setter Window::oncontextmenu(user);\n
-getter Window::oncuechange(user);\n
-setter Window::oncuechange(user);\n
-getter Window::ondblclick(user);\n
-setter Window::ondblclick(user);\n
-getter Window::ondragend(user);\n
-setter Window::ondragend(user);\n
-getter Window::ondragenter(user);\n
-setter Window::ondragenter(user);\n
-getter Window::ondragexit(user);\n
-setter Window::ondragexit(user);\n
-getter Window::ondragleave(user);\n
-setter Window::ondragleave(user);\n
-getter Window::ondragover(user);\n
-setter Window::ondragover(user);\n
-getter Window::ondragstart(user);\n
-setter Window::ondragstart(user);\n
-getter Window::ondrag(user);\n
-setter Window::ondrag(user);\n
-getter Window::ondrop(user);\n
-setter Window::ondrop(user);\n
-getter Window::ondurationchange(user);\n
-setter Window::ondurationchange(user);\n
-getter Window::onemptied(user);\n
-setter Window::onemptied(user);\n
-getter Window::onended(user);\n
-setter Window::onended(user);\n
-getter Window::onerror(user);\n
-setter Window::onerror(user);\n
-getter Window::onfocus(user);\n
-setter Window::onfocus(user);\n
-getter Window::onhashchange(user);\n
-setter Window::onhashchange(user);\n
-getter Window::oninput(user);\n
-setter Window::oninput(user);\n
-getter Window::oninvalid(user);\n
-setter Window::oninvalid(user);\n
-getter Window::onkeydown(user);\n
-setter Window::onkeydown(user);\n
-getter Window::onkeypress(user);\n
-setter Window::onkeypress(user);\n
-getter Window::onkeyup(user);\n
-setter Window::onkeyup(user);\n
-getter Window::onlanguagechange(user);\n
-setter Window::onlanguagechange(user);\n
-getter Window::onloadeddata(user);\n
-setter Window::onloadeddata(user);\n
-getter Window::onloadedmetadata(user);\n
-setter Window::onloadedmetadata(user);\n
-getter Window::onloadstart(user);\n
-setter Window::onloadstart(user);\n
-getter Window::onload(user);\n
-setter Window::onload(user);\n
-getter Window::onmessage(user);\n
-setter Window::onmessage(user);\n
-getter Window::onmousedown(user);\n
-setter Window::onmousedown(user);\n
-getter Window::onmouseenter(user);\n
-setter Window::onmouseenter(user);\n
-getter Window::onmouseleave(user);\n
-setter Window::onmouseleave(user);\n
-getter Window::onmousemove(user);\n
-setter Window::onmousemove(user);\n
-getter Window::onmouseout(user);\n
-setter Window::onmouseout(user);\n
-getter Window::onmouseover(user);\n
-setter Window::onmouseover(user);\n
-getter Window::onmouseup(user);\n
-setter Window::onmouseup(user);\n
-getter Window::onoffline(user);\n
-setter Window::onoffline(user);\n
-getter Window::ononline(user);\n
-setter Window::ononline(user);\n
-getter Window::onpagehide(user);\n
-setter Window::onpagehide(user);\n
-getter Window::onpageshow(user);\n
-setter Window::onpageshow(user);\n
-getter Window::onpause(user);\n
-setter Window::onpause(user);\n
-getter Window::onplaying(user);\n
-setter Window::onplaying(user);\n
-getter Window::onplay(user);\n
-setter Window::onplay(user);\n
-getter Window::onpopstate(user);\n
-setter Window::onpopstate(user);\n
-getter Window::onprogress(user);\n
-setter Window::onprogress(user);\n
-getter Window::onratechange(user);\n
-setter Window::onratechange(user);\n
-getter Window::onreset(user);\n
-setter Window::onreset(user);\n
-getter Window::onresize(user);\n
-setter Window::onresize(user);\n
-getter Window::onscroll(user);\n
-setter Window::onscroll(user);\n
-getter Window::onseeked(user);\n
-setter Window::onseeked(user);\n
-getter Window::onseeking(user);\n
-setter Window::onseeking(user);\n
-getter Window::onselect(user);\n
-setter Window::onselect(user);\n
-getter Window::onshow(user);\n
-setter Window::onshow(user);\n
-getter Window::onsort(user);\n
-setter Window::onsort(user);\n
-getter Window::onstalled(user);\n
-setter Window::onstalled(user);\n
-getter Window::onstorage(user);\n
-setter Window::onstorage(user);\n
-getter Window::onsubmit(user);\n
-setter Window::onsubmit(user);\n
-getter Window::onsuspend(user);\n
-setter Window::onsuspend(user);\n
-getter Window::ontimeupdate(user);\n
-setter Window::ontimeupdate(user);\n
-getter Window::ontoggle(user);\n
-setter Window::ontoggle(user);\n
-getter Window::onunload(user);\n
-setter Window::onunload(user);\n
-getter Window::onvolumechange(user);\n
-setter Window::onvolumechange(user);\n
-getter Window::onwaiting(user);\n
-setter Window::onwaiting(user);\n
-getter Window::onwheel(user);\n
-setter Window::onwheel(user);\n
-method Window::open();\n
-getter Window::opener(any);\n
-setter Window::opener(any);\n
-getter Window::parent(user);\n
-getter Window::personalbar(user);\n
-method Window::postMessage();\n
-method Window::print();\n
-method Window::prompt();\n
-method Window::releaseEvents();\n
-method Window::requestAnimationFrame();\n
-getter Window::scrollbars(user);\n
-getter Window::self(user);\n
-getter Window::sessionStorage(user);\n
-method Window::setInterval();\n
-method Window::setTimeout();\n
-method Window::showModalDialog();\n
-getter Window::statusbar(user);\n
-getter Window::status(string);\n
-setter Window::status(string);\n
-method Window::stop();\n
-getter Window::toolbar(user);\n
-getter Window::top(user);\n
-method WorkerGlobalScope::atob();\n
-method WorkerGlobalScope::btoa();\n
-method WorkerGlobalScope::clearInterval();\n
-method WorkerGlobalScope::clearTimeout();\n
-method WorkerGlobalScope::close();\n
-method WorkerGlobalScope::createImageBitmap();\n
-method WorkerGlobalScope::importScripts();\n
-getter WorkerGlobalScope::location(user);\n
-getter WorkerGlobalScope::navigator(user);\n
-getter WorkerGlobalScope::onerror(user);\n
-setter WorkerGlobalScope::onerror(user);\n
-getter WorkerGlobalScope::onlanguagechange(user);\n
-setter WorkerGlobalScope::onlanguagechange(user);\n
-getter WorkerGlobalScope::onoffline(user);\n
-setter WorkerGlobalScope::onoffline(user);\n
-getter WorkerGlobalScope::ononline(user);\n
-setter WorkerGlobalScope::ononline(user);\n
-getter WorkerGlobalScope::self(user);\n
-method WorkerGlobalScope::setInterval();\n
-method WorkerGlobalScope::setTimeout();\n
-getter WorkerLocation::hash(user);\n
-getter WorkerLocation::hostname(user);\n
-getter WorkerLocation::host(user);\n
-getter WorkerLocation::href(user);\n
-getter WorkerLocation::origin(user);\n
-getter WorkerLocation::pathname(user);\n
-getter WorkerLocation::port(user);\n
-getter WorkerLocation::protocol(user);\n
-getter WorkerLocation::search(user);\n
-getter WorkerNavigator::appCodeName(string);\n
-getter WorkerNavigator::appName(string);\n
-getter WorkerNavigator::appVersion(string);\n
-getter WorkerNavigator::languages(string);\n
-getter WorkerNavigator::language(string);\n
-getter WorkerNavigator::onLine(boolean);\n
-getter WorkerNavigator::platform(string);\n
-getter WorkerNavigator::product(string);\n
-getter WorkerNavigator::productSub(string);\n
-method WorkerNavigator::taintEnabled();\n
-getter WorkerNavigator::userAgent(string);\n
-getter WorkerNavigator::vendor(string);\n
-getter WorkerNavigator::vendorSub(string);\n
-getter Worker::onerror(user);\n
-setter Worker::onerror(user);\n
-getter Worker::onmessage(user);\n
-setter Worker::onmessage(user);\n
-method Worker::postMessage();\n
-method Worker::terminate();\n
-method XMLDocument::load();\n
-method XMLSerializer::serializeToString();\n
-*/
diff --git a/docs/building-GTK.md b/docs/building-GTK.md
index 4ac0fc89e..aa898a04d 100644
--- a/docs/building-GTK.md
+++ b/docs/building-GTK.md
@@ -1,239 +1,214 @@
---------------------------------------------------------------------------------
- Build Instructions for GTK NetSurf 16 March 2014
---------------------------------------------------------------------------------
+Build Instructions for GTK NetSurf
+==================================
- This document provides instructions for building the GTK version of NetSurf
- and provides guidance on obtaining NetSurf's build dependencies.
+This document provides instructions for building the GTK version of NetSurf
+and provides guidance on obtaining NetSurf's build dependencies.
- GTK NetSurf has been tested on Debian, Ubuntu, Fedora 8, FreeBSD, NetBSD and
- Solaris 10. NetSurf requires at minimum GTK 2.12.
+GTK NetSurf has been tested on Debian, Ubuntu, Fedora 8, FreeBSD, NetBSD and
+Solaris 10. NetSurf requires at minimum GTK 2.12.
- Quick Start
-=============
+Quick Start
+-----------
- See the QUICK-START document, which provides a simple environment with
- which you can fetch, build and install NetSurf and its dependencies.
+See the QUICK-START document, which provides a simple environment with
+which you can fetch, build and install NetSurf and its dependencies.
- The QUICK-START is the recommended way to build NetSurf.
+The QUICK-START is the recommended way to build NetSurf.
- Manual building
-=================
+Manual building
+---------------
- If you can't follow the quick start instructions, you will have to build
- NetSurf manually. The instructions for doing this are given below.
+If you can't follow the quick start instructions, you will have to build
+NetSurf manually. The instructions for doing this are given below.
- Obtaining the build dependencies
-----------------------------------
-
- Many of NetSurf's dependencies are packaged on various operating systems.
- The remainder must be installed manually. Currently, some of the libraries
- developed as part of the NetSurf project have not had official releases.
- Hopefully they will soon be released with downloadable tarballs and packaged
- in common distros. For now, you'll have to make do with Git checkouts.
-
- Package installation
- --------------------
-
- Debian-like OS:
-
- $ apt-get install libgtk2.0-dev libcurl3-dev libpng-dev
- $ apt-get install librsvg2-dev libjpeg-dev
+Obtaining the build dependencies
+--------------------------------
- If you want to build with gtk 3 replace libgtk2.0-dev with libgtk-3-dev
+Many of NetSurf's dependencies are packaged on various operating systems.
+The remainder must be installed manually. Currently, some of the libraries
+developed as part of the NetSurf project have not had official releases.
+Hopefully they will soon be released with downloadable tarballs and packaged
+in common distros. For now, you'll have to make do with Git checkouts.
- Recent OS versions might need libcurl4-dev instead of libcurl3-dev but
- note that when it has not been built with OpenSSL, the SSL_CTX is not
- available and results that certification details won't be presented in case
- they are invalid. But as this is currently unimplemented in the GTK
- flavour of NetSurf, this won't make a difference at all.
+### Package installation
- For experimental javascript support the mozilla spiermonkey library
- is required:
+Debian-like OS:
- $ apt-get install libmozjs-dev
+ $ apt-get install libgtk2.0-dev libcurl3-dev libpng-dev
+ $ apt-get install librsvg2-dev libjpeg-dev
- Fedora:
+If you want to build with gtk 3 replace libgtk2.0-dev with libgtk-3-dev
- $ yum install curl-devel libpng-devel
- $ yum install librsvg2-devel expat-devel
+Recent OS versions might need libcurl4-dev instead of libcurl3-dev but
+note that when it has not been built with OpenSSL, the SSL_CTX is not
+available and results that certification details won't be presented in case
+they are invalid. But as this is currently unimplemented in the GTK
+flavour of NetSurf, this won't make a difference at all.
- Other:
+Fedora:
- You'll need to install the development resources for libglade2, libcurl3,
- libpng and librsvg.
+ $ yum install curl-devel libpng-devel
+ $ yum install librsvg2-devel expat-devel
- Libharu
- -------
+Other:
- NetSurf can use Haru PDF to enable PDF export. Haru PDF can be obtained
- from http://libharu.org/. We require libharu 2.2 or later.
+You'll need to install the development resources for libglade2, libcurl3,
+libpng and librsvg.
- | Note: libharu cannot be auto-detected by the Makefile. If you wish to
- | enable it, do so by creating a Makefile.config file.
+### Preparing your workspace
- Preparing your workspace
---------------------------
+NetSurf has a number of libraries which must be built in-order and
+installed into your workspace. Each library depends on a core build
+system which NetSurf projects use. This build system relies on the
+presence of things like pkg-config to find libraries and also certain
+environment variables in order to work correctly.
- NetSurf has a number of libraries which must be built in-order and
- installed into your workspace. Each library depends on a core build
- system which NetSurf projects use. This build system relies on the
- presence of things like pkg-config to find libraries and also certain
- environment variables in order to work correctly.
+Assuming you are preparing a workspace in /home/netsurf/workspace then
+the following steps will set you up:
- Assuming you are preparing a workspace in /home/netsurf/workspace then
- the following steps will set you up:
+### Make the workspace directory and change to it
- Make the workspace directory and change to it
- ---------------------------------------------
+ $ mkdir -p ${HOME}/netsurf/workspace
+ $ cd ${HOME}/netsurf/workspace
- $ mkdir -p ${HOME}/netsurf/workspace
- $ cd ${HOME}/netsurf/workspace
+### Make the temporary install space
- Make the temporary install space
- --------------------------------
+ $ mkdir inst
- $ mkdir inst
+### Make an environment script
- Make an environment script
- --------------------------
- $ cat > env.sh <<'EOF'
- export PKG_CONFIG_PATH=${HOME}/netsurf/workspace/inst/lib/pkgconfig::
- export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${HOME}/netsurf/workspace/inst/lib
- export PREFIX=${HOME}/netsurf/workspace/inst
- EOF
+ $ cat > env.sh <<'EOF'
+ export PKG_CONFIG_PATH=${HOME}/netsurf/workspace/inst/lib/pkgconfig::
+ export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${HOME}/netsurf/workspace/inst/lib
+ export PREFIX=${HOME}/netsurf/workspace/inst
+ EOF
- Change to workspace and source the environment
- ----------------------------------------------
+### Change to workspace and source the environment
- Whenever you wish to start development in a new shell, run the following:
+Whenever you wish to start development in a new shell, run the following:
- $ cd ${HOME}/netsurf/workspace
- $ source env.sh
+ $ cd ${HOME}/netsurf/workspace
+ $ source env.sh
- From here on, any commands in this document assume you have sourced your
- shell environment.
+From here on, any commands in this document assume you have sourced your
+shell environment.
- The NetSurf project's libraries
----------------------------------
+### The NetSurf project's libraries
- The NetSurf project has developed several libraries which are required by
- the browser. These are:
+The NetSurf project has developed several libraries which are required by
+the browser. These are:
- BuildSystem -- Shared build system, needed to build the other libraries
- LibParserUtils -- Parser building utility functions
- LibWapcaplet -- String internment
- Hubbub -- HTML5 compliant HTML parser
- LibCSS -- CSS parser and selection engine
- LibNSGIF -- GIF format image decoder
- LibNSBMP -- BMP and ICO format image decoder
- LibROSprite -- RISC OS Sprite format image decoder
+| BuildSystem | Shared build system, needed to build the other libraries |
+| LibParserUtils | Parser building utility functions |
+| LibWapcaplet | String internment |
+| Hubbub | HTML5 compliant HTML parser |
+| LibCSS | CSS parser and selection engine |
+| LibNSGIF | GIF format image decoder |
+| LibNSBMP | BMP and ICO format image decoder |
+| LibROSprite | RISC OS Sprite format image decoder |
- To fetch each of these libraries, run the appropriate commands from the
- Docs/LIBRARIES file, from within your workspace directory.
+To fetch each of these libraries, run the appropriate commands from the
+Docs/LIBRARIES file, from within your workspace directory.
- To build and install these libraries, simply enter each of their directories
- and run:
-
- $ make install
+To build and install these libraries, simply enter each of their directories
+and run:
- | Note: We advise enabling iconv() support in libparserutils, which vastly
- | increases the number of supported character sets. To do this,
- | create a file called Makefile.config.override in the libparserutils
- | directory, containing the following line:
- |
- | CFLAGS += -DWITH_ICONV_FILTER
- |
- | For more information, consult the libparserutils README file.
+ $ make install
- Now you should have all the NetSurf project libraries built and installed.
+> Note:
+>
+> We advise enabling iconv() support in libparserutils, which vastly
+> increases the number of supported character sets. To do this,
+> create a file called Makefile.config.override in the libparserutils
+> directory, containing the following line:
+>
+> CFLAGS += -DWITH_ICONV_FILTER
+>
+> For more information, consult the libparserutils README file.
+Now you should have all the NetSurf project libraries built and installed.
- Getting the NetSurf source
-----------------------------
- From your workspace directory, run the following command to get the NetSurf
- source:
+### Getting the NetSurf source
- $ git clone git://git.netsurf-browser.org/netsurf.git
+From your workspace directory, run the following command to get the NetSurf
+source:
- And change to the 'netsurf' directory:
+ $ git clone git://git.netsurf-browser.org/netsurf.git
- $ cd netsurf
+And change to the 'netsurf' directory:
- Building and executing NetSurf
---------------------------------
+ $ cd netsurf
- First of all, you should examine the options in Makefile.defaults
- and gtk/Makefile.defaults and enable and disable relevant features
- as you see fit by editing a Makefile.config file.
+Building and executing NetSurf
+------------------------------
- Some of these options can be automatically detected and used, and
- where this is the case they are set to such. Others cannot be
- automatically detected from the Makefile, so you will either need to
- install the dependencies, or set them to NO.
+First of all, you should examine the options in Makefile.defaults
+and gtk/Makefile.defaults and enable and disable relevant features
+as you see fit by editing a Makefile.config file.
- You should then obtain NetSurf's dependencies, keeping in mind which options
- you have enabled in the configuration file. See the next section for
- specifics.
+Some of these options can be automatically detected and used, and
+where this is the case they are set to such. Others cannot be
+automatically detected from the Makefile, so you will either need to
+install the dependencies, or set them to NO.
- Once done, to build GTK NetSurf on a UNIX-like platform, simply run:
+You should then obtain NetSurf's dependencies, keeping in mind which options
+you have enabled in the configuration file. See the next section for
+specifics.
- $ make
+Once done, to build GTK NetSurf on a UNIX-like platform, simply run:
- If that produces errors, you probably don't have some of NetSurf's
- build dependencies installed. See "Obtaining NetSurf's dependencies"
- below. Or turn off the complaining features in a Makefile.config
- file. You may need to "make clean" before attempting to build after
- installing the dependencies.
+ $ make
- Run NetSurf by executing the "test-nsgtk" shell script:
+If that produces errors, you probably don't have some of NetSurf's
+build dependencies installed. See "Obtaining NetSurf's dependencies"
+below. Or turn off the complaining features in a Makefile.config
+file. You may need to "make clean" before attempting to build after
+installing the dependencies.
- $ ./test-nsgtk
+Run NetSurf by executing "nsgtk3":
- This script makes it easy to run the nsgtk binary from the build tree. It
- sets up some environment variables which enable NetSurf to find its
- resources.
+ $ ./nsgtk3
- Builtin resources
--------------------
- There are numerous resources that accompany NetSurf, such as the
- image files for icons, cursors and the ui builder files that
- construct the browsers interface.
+### Builtin resources
- Some of these resources can be compiled into the browser executable
- removing the need to install these resources separately. The GLib
- library on which GTK is based provides this functionality to
- NetSurf.
+There are numerous resources that accompany NetSurf, such as the
+image files for icons, cursors and the ui builder files that
+construct the browsers interface.
- Up until GLib version 2.32 only the GDK pixbuf could be integrated
- in this way and is controlled with the NETSURF_USE_INLINE_PIXBUF
- variable (set in makefile.config).
+Some of these resources can be compiled into the browser executable
+removing the need to install these resources separately. The GLib
+library on which GTK is based provides this functionality to
+NetSurf.
- Glib version 2.32 and later integrated support for any file to be a
- resource while depreciating the old inline pixbuf interface. NetSurf
- gtk executables can integrate many resources using this interface,
- configuration is controlled with the NETSURF_USE_GRESOURCE variable.
+Up until GLib version 2.32 only the GDK pixbuf could be integrated
+in this way and is controlled with the NETSURF_USE_INLINE_PIXBUF
+variable (set in makefile.config).
- Loading from file is the fallback if a resource has not been
- compiled in, because of this if both of these features are
- unavailable (or disabled) NetSurf will automatically fall back to
- loading all its resources from files.
+Glib version 2.32 and later integrated support for any file to be a
+resource while depreciating the old inline pixbuf interface. NetSurf
+gtk executables can integrate many resources using this interface,
+configuration is controlled with the NETSURF_USE_GRESOURCE variable.
- The resource initialisation within the browser ensures it can access
- all the resources at start time, however it does not verify the
- resources are valid so failures could still occur subsequently. This
- is especially true for file based resources as they can become
- inaccessible after initialisation.
+Loading from file is the fallback if a resource has not been
+compiled in, because of this if both of these features are
+unavailable (or disabled) NetSurf will automatically fall back to
+loading all its resources from files.
+The resource initialisation within the browser ensures it can access
+all the resources at start time, however it does not verify the
+resources are valid so failures could still occur subsequently. This
+is especially true for file based resources as they can become
+inaccessible after initialisation.
- Note for packagers
-====================
- If you are packaging NetSurf, see the PACKAGING-GTK document.
+Note for packagers
+------------------
+If you are packaging NetSurf, see the PACKAGING-GTK document.
diff --git a/docs/core-window-interface.md b/docs/core-window-interface.md
index 8f6951f9f..1b389d916 100644
--- a/docs/core-window-interface.md
+++ b/docs/core-window-interface.md
@@ -10,7 +10,7 @@ The currently available user interfaces are:
- Cookies
- Global history
- Hotlist
- - SSL certificate view
+ - SSL certificate view (obsolete, but used as an example here)
- local history
Although not currently included in future additional user interfaces
diff --git a/docs/development.md b/docs/development.md
new file mode 100644
index 000000000..3f08b5496
--- /dev/null
+++ b/docs/development.md
@@ -0,0 +1,123 @@
+Development
+===========
+
+[TOC]
+
+# Working with the team
+
+Generally it is sensible to check with the other developers if you are
+planning to make a change to NetSurf intended to be merged.
+
+We are often about on the IRC channel but failing that the developer
+mailing list is a good place to try.
+
+All the project sources are held in [public git repositories](http://source.netsurf-browser.org/)
+
+# Compilation environment
+
+Compiling a development edition of NetSurf requires a POSIX style
+environment. Typically this means a Linux based system although Free
+BSD, Open BSD, Mac OS X and Haiku all known to work.
+
+## Toolchains
+
+Compilation for non POSIX toolkits/frontends (e.g. RISC OS) generally
+relies upon a cross compilation environment which is generated using
+the makefiles found in our
+[toolchains](http://source.netsurf-browser.org/toolchains.git/)
+repository. These toolchains are built by the Continuous Integration
+(CI) system and the
+[results of the system](http://ci.netsurf-browser.org/builds/toolchains/)
+are published as a convenience.
+
+## Quick setup
+
+The [quick start guide](docs/quick-start.md) can be used to get a
+development environment setup quickly and uses the
+[env.sh](env_8sh_source.html) script the core team utilises.
+
+## Manual setup
+
+The Manual environment setup and compilation method is covered by the
+details in the [netsurf libraries](docs/netsurf-libraries.md) document
+for the core libraries and then one of the building documents for the
+specific frontend.
+
+- [Amiga Os cross](docs/building-AmigaCross.md) and [Amiga OS](docs/building-AmigaOS.md)
+- [Framebuffer](docs/building-Framebuffer.md)
+- [GTK](docs/building-GTK.md)
+- [Haiku (BeOS)](docs/building-Haiku.md)
+- [Windows Win32](docs/building-Windows.md)
+
+These documents are sometimes not completely up to
+date and the env.sh script should be considered canonical.
+
+# Logging
+
+The [logging](docs/logging.md) interface controls debug and error
+messages not output through the GUI.
+
+# Unit testing
+
+NetSurf [unit tests](docs/unit-testing.md) provide basic test coverage
+of many core parts of the browser code such as url parsing and utility
+functions.
+
+# Integration testing
+
+NetSurf [integration tests](docs/integration-testing.md) use the
+monkey frontend to operate the browser as a whole. These tests open
+windows, navigate to websites and render contents as a user might.
+
+# New frontend development
+
+[Implementing a new frotend](docs/implementing-new-frontend.md) for a
+toolkit can be challenging and this guide provides an overview and
+worked example.
+
+# Documented API
+
+The NetSurf code makes use of Doxygen for code documentation.
+
+There are several documents which detail specific aspects of the
+codebase and APIs.
+
+## Core window
+
+The [core window API](docs/core-window-interface.md) allows frontends
+to use generic core code for user interface elements beyond the
+browser render.
+
+## Source object caching
+
+The [source object caching](docs/source-object-backing-store.md)
+provides a way for downloaded content to be kept on a persistent
+storage medium such as hard disc to make future retrieval of that
+content quickly.
+
+# Javascript
+
+Javascript provision is split into four parts:
+- An engine that takes source code and executes it.
+- Interfaces between the program and the web page.
+- Browser support to retrieve and manage the source code to be executed.
+- Browser support for the dispatch of events from user interface.
+
+## Library
+
+JavaScript is provided by integrating the duktape library. There are
+[instructions](docs/updating-duktape.md) on how to update the library.
+
+## Interface binding
+
+In order for javascript programs to to interact with the page contents
+it must use the Document Object Model (DOM) and Cascading Style Sheet
+Object Model (CSSOM) API.
+
+These interfaces are described using web Interface Description
+Language (IDL) within the relevant specifications
+(e.g. https://dom.spec.whatwg.org/).
+
+Each interface described by the webIDL must be bound (connected) to
+the browsers internal representation for the DOM or CSS, etc. The
+process of [writing bindings](docs/jsbinding.md) is ongoing.
diff --git a/docs/env.sh b/docs/env.sh
index b9adb92f9..4cb056ec1 100644
--- a/docs/env.sh
+++ b/docs/env.sh
@@ -1,4 +1,6 @@
-#!/bin/sh
+# This shell fragment is intended for use in `bash` or `zsh`. While it
+# may work in other shells it is not meant to, and any misbehaviour is not
+# considered a bug in that case.
#
# NetSurf Library, tool and browser development support script
#
@@ -36,7 +38,10 @@ fi
# apt get commandline to install necessary dev packages
ns-apt-get-install()
{
- if /usr/bin/apt-cache show libssl1.0-dev >/dev/null 2>&1; then
+ LIBCURL_OPENSSL_CONFLICTS="$(/usr/bin/apt-cache show libcurl4-openssl-dev | grep Conflicts | grep -o libssl1.0-dev)"
+ if [ "x${LIBCURL_OPENSSL_CONFLICTS}" != "x" ]; then
+ NS_DEV_DEB="${NS_DEV_DEB} libssl-dev"
+ elif /usr/bin/apt-cache show libssl1.0-dev >/dev/null 2>&1; then
NS_DEV_DEB="${NS_DEV_DEB} libssl1.0-dev"
else
NS_DEV_DEB="${NS_DEV_DEB} libssl-dev"
@@ -193,7 +198,7 @@ if [ "x${HOST}" = "x" ]; then
HOST=${TARGET_ABI}
fi
else
- HOST_CC_LIST="${HOST}-cc ${HOST}-gcc /opt/netsurf/${HOST}/cross/bin/${HOST}-cc /opt/netsurf/${HOST}/cross/bin/${HOST}-gcc"
+ HOST_CC_LIST="/opt/netsurf/${HOST}/cross/bin/${HOST}-cc /opt/netsurf/${HOST}/cross/bin/${HOST}-gcc ${HOST}-cc ${HOST}-gcc"
for HOST_CC_V in $(echo ${HOST_CC_LIST});do
HOST_CC=$(${WHICH_CMD} ${HOST_CC_V})
if [ "x${HOST_CC}" != "x" ];then
@@ -208,9 +213,13 @@ else
HOST_CC_MACHINE=$(${HOST_CC} -dumpmachine 2>/dev/null)
if [ "${HOST_CC_MACHINE}" != "${HOST}" ];then
- echo "Compiler dumpmachine differes from HOST setting"
+ echo "Compiler dumpmachine differs from HOST setting"
return 2
fi
+
+ NS_ENV_CC="${HOST_CC}"
+ export NS_ENV_CC
+
unset HOST_CC_LIST HOST_CC_V HOST_CC HOST_CC_MACHINE
fi
@@ -254,64 +263,81 @@ NS_GIT="git://git.netsurf-browser.org"
# Buildsystem: everything depends on this
NS_BUILDSYSTEM="buildsystem"
-# internal libraries all frontends require (order is important)
-NS_INTERNAL_LIBS="libwapcaplet libparserutils libhubbub libdom libcss libnsgif libnsbmp libutf8proc libnsutils libnspsl libnslog"
-
-# The browser itself
-NS_BROWSER="netsurf"
+NS_TOOLS=""
+NS_FRONTEND_LIBS=""
+BUILD_TARGET="${TARGET:-netsurf}"
-# add target specific libraries
-case "${HOST}" in
- i586-pc-haiku)
- # tools required to build the browser for haiku (beos)
- NS_TOOLS="nsgenbind"
- # libraries required for the haiku target abi
- NS_FRONTEND_LIBS="libsvgtiny"
- ;;
- *arwin*)
- # tools required to build the browser for OS X
- NS_TOOLS=""
- # libraries required for the Darwin target abi
- NS_FRONTEND_LIBS="libsvgtiny libnsfb"
- ;;
- arm-unknown-riscos)
- # tools required to build the browser for RISC OS
- NS_TOOLS="nsgenbind"
- # libraries required for the risc os target abi
- NS_FRONTEND_LIBS="libsvgtiny librufl libpencil librosprite"
- ;;
- *-atari-mint)
- # tools required to build the browser for atari
- NS_TOOLS=""
- # libraries required for the atari frontend
- NS_FRONTEND_LIBS=""
+case "$BUILD_TARGET" in
+ libhubbub)
+ NS_INTERNAL_LIBS="libparserutils"
;;
- ppc-amigaos)
- # default tools required to build the browser
- NS_TOOLS="nsgenbind"
- # default additional internal libraries
- NS_FRONTEND_LIBS="libsvgtiny"
- ;;
- m68k-unknown-amigaos)
- # default tools required to build the browser
- NS_TOOLS="nsgenbind"
- # default additional internal libraries
- NS_FRONTEND_LIBS="libsvgtiny"
+
+ libdom)
+ NS_INTERNAL_LIBS="libwapcaplet libparserutils libhubbub"
;;
- *-unknown-freebsd*)
- # tools required to build the browser for freebsd
- NS_TOOLS=""
- # libraries required for the freebsd frontend
- NS_FRONTEND_LIBS=""
- # select gnu make
- MAKE=gmake
+
+ libcss)
+ NS_INTERNAL_LIBS="libwapcaplet libparserutils"
;;
- *)
- # default tools required to build the browser
- NS_TOOLS="nsgenbind"
- # default additional internal libraries
- NS_FRONTEND_LIBS="libsvgtiny libnsfb"
+
+ netsurf)
+ # internal libraries all frontends require (order is important)
+ NS_INTERNAL_LIBS="libwapcaplet libparserutils libhubbub libdom libcss libnsgif libnsbmp libutf8proc libnsutils libnspsl libnslog"
+
+ # add target specific libraries
+ case "${HOST}" in
+ i586-pc-haiku)
+ # tools required to build the browser for haiku (beos)
+ NS_TOOLS="nsgenbind"
+ # libraries required for the haiku target abi
+ NS_FRONTEND_LIBS="libsvgtiny"
+ ;;
+ *arwin*)
+ # tools required to build the browser for OS X
+ NS_TOOLS=""
+ # libraries required for the Darwin target abi
+ NS_FRONTEND_LIBS="libsvgtiny libnsfb"
+ ;;
+ arm-unknown-riscos|arm-riscos-gnueabi*)
+ # tools required to build the browser for RISC OS
+ NS_TOOLS="nsgenbind"
+ # libraries required for the risc os target abi
+ NS_FRONTEND_LIBS="libsvgtiny librufl libpencil librosprite"
+ ;;
+ *-atari-mint)
+ # tools required to build the browser for atari
+ NS_TOOLS=""
+ # libraries required for the atari frontend
+ NS_FRONTEND_LIBS=""
+ ;;
+ ppc-amigaos)
+ # default tools required to build the browser
+ NS_TOOLS="nsgenbind"
+ # default additional internal libraries
+ NS_FRONTEND_LIBS="libsvgtiny"
+ ;;
+ m68k-unknown-amigaos)
+ # default tools required to build the browser
+ NS_TOOLS="nsgenbind"
+ # default additional internal libraries
+ NS_FRONTEND_LIBS="libsvgtiny"
+ ;;
+ *-unknown-freebsd*)
+ # tools required to build the browser for freebsd
+ NS_TOOLS=""
+ # libraries required for the freebsd frontend
+ NS_FRONTEND_LIBS=""
+ # select gnu make
+ MAKE=gmake
+ ;;
+ *)
+ # default tools required to build the browser
+ NS_TOOLS="nsgenbind"
+ # default additional internal libraries
+ NS_FRONTEND_LIBS="libsvgtiny libnsfb"
+ ;;
+ esac
;;
esac
@@ -322,7 +348,7 @@ export MAKE
# git pull in all repos parameters are passed to git pull
ns-pull()
{
- for REPO in $(echo ${NS_BUILDSYSTEM} ${NS_INTERNAL_LIBS} ${NS_FRONTEND_LIBS} ${NS_TOOLS} ${NS_BROWSER}) ; do
+ for REPO in $(echo ${NS_BUILDSYSTEM} ${NS_INTERNAL_LIBS} ${NS_FRONTEND_LIBS} ${NS_TOOLS} ${BUILD_TARGET}) ; do
echo -n " GIT: Pulling ${REPO}: "
if [ -f "${TARGET_WORKSPACE}/${REPO}/.git/config" ]; then
(cd ${TARGET_WORKSPACE}/${REPO} && git pull $*; )
@@ -335,19 +361,42 @@ ns-pull()
# clone all repositories
ns-clone()
{
+ SHALLOW=""
+ SKIP=""
+ while [ $# -gt 0 ]
+ do
+ case "$1" in
+ -d | --deps-only) SKIP="${BUILD_TARGET}"
+ shift
+ ;;
+ -s | --shallow) SHALLOW="--depth 1"
+ shift
+ ;;
+ -*) echo "Error: Unknown option: $1" >&2
+ exit 1
+ ;;
+ *) # No more options
+ break
+ ;;
+ esac
+ done
+
mkdir -p ${TARGET_WORKSPACE}
- for REPO in $(echo ${NS_BUILDSYSTEM} ${NS_INTERNAL_LIBS} ${NS_FRONTEND_LIBS} ${NS_RISCOS_LIBS} ${NS_TOOLS} ${NS_BROWSER}) ; do
+ for REPO in $(echo ${NS_BUILDSYSTEM} ${NS_INTERNAL_LIBS} ${NS_FRONTEND_LIBS} ${NS_RISCOS_LIBS} ${NS_TOOLS} ${BUILD_TARGET}) ; do
+ [ "x${REPO}" != "x${SKIP}" ] || continue
echo -n " GIT: Cloning ${REPO}: "
if [ -f ${TARGET_WORKSPACE}/${REPO}/.git/config ]; then
echo "Repository already present"
else
- (cd ${TARGET_WORKSPACE} && git clone ${NS_GIT}/${REPO}.git; )
+ (cd ${TARGET_WORKSPACE} && git clone ${SHALLOW} ${NS_GIT}/${REPO}.git; )
fi
done
# put current env.sh in place in workspace
- if [ ! -f "${TARGET_WORKSPACE}/env.sh" -a -f ${TARGET_WORKSPACE}/${NS_BROWSER}/docs/env.sh ]; then
- cp ${TARGET_WORKSPACE}/${NS_BROWSER}/docs/env.sh ${TARGET_WORKSPACE}/env.sh
+ if [ "x$NS_BROWSER" = "x" ]; then
+ if [ ! -f "${TARGET_WORKSPACE}/env.sh" -a -f ${TARGET_WORKSPACE}/${NS_BROWSER}/docs/env.sh ]; then
+ cp ${TARGET_WORKSPACE}/${NS_BROWSER}/docs/env.sh ${TARGET_WORKSPACE}/env.sh
+ fi
fi
}
diff --git a/docs/gource.sh b/docs/gource.sh
index a1fbcbe13..6f12b3ddb 100755
--- a/docs/gource.sh
+++ b/docs/gource.sh
@@ -23,7 +23,7 @@ OUTPUT_SIZE="1280x720"
# HD widescreen 1080p
#OUTPUT_SIZE="1280x1080"
-TMP_DIR=/net/holly/srv/video/Unsorted/
+TMP_DIR=/home/video/gource/
######################################################################
@@ -60,7 +60,7 @@ TMP_PPM=${TMP_DIR}/${TITLE}-gource-${TYPE}-${OUTPUT_SIZE}-${CMODE}.ppm
FILENAME=${TITLE}-gource-${TYPE}-${OUTPUT_SIZE}-${CMODE}.mp4
# filter some directories which are not interesting
-FILEFILTER="\!NetSurf/|riscos/distribution/|gtk/res/|framebuffer/res/|amiga/resources/|beos/res/|cocoa/res/|windows/res/|atari/res"
+FILEFILTER="\!NetSurf/|riscos/distribution/|gtk/res/|framebuffer/res/|amiga/resources/|beos/res/|cocoa/res/|windows/res/|atari/res|riscos/appdir/"
# generate
gource --title "NetSurf Development" -${OUTPUT_SIZE} ${QPARAM} --max-files 10000 --bloom-multiplier 0.10 --bloom-intensity 0.5 --title ${TITLE} --highlight-all-users --output-framerate 25 --hide filenames --stop-at-end --date-format "%d %B %Y" --bloom-intensity 0.2 --file-filter "${FILEFILTER}" --key --camera-mode ${CMODE} --output-ppm-stream - > ${TMP_PPM}
diff --git a/docs/implementing-new-frontend.md b/docs/implementing-new-frontend.md
new file mode 100644
index 000000000..4bda47af0
--- /dev/null
+++ b/docs/implementing-new-frontend.md
@@ -0,0 +1,413 @@
+Implementing a new frontend
+===========================
+
+[TOC]
+
+# Introduction
+
+NetSurf is divided into a series of frontends which provide a user
+interface around common core functionality.
+
+Each frontend is a distinct implementation for a specific GUI toolkit.
+
+The existing frontends are covered in the [user
+interface](docs/user-interface.md) documentation.
+
+Note implementing a new frontend implies using a toolkit distinct from
+one of those already implemented and is distinct from porting NetSurf
+to a new operating system platform.
+
+It is recommend, in the strongest terms, that if the prospective
+developer is porting to both a new platform and toolkit that they
+*start* by getting the [monkey](docs/using-monkey.md) frontend
+building and passing at least the basic integration tests on their
+platform.
+
+Experience has shown that attempting to port to a platform and
+implement a toolkit at the same time generally results in failure to
+achieve either goal.
+
+NetSurf is built using GNU make and frontends are expected to
+integrate with this buildsystem.
+
+Implementation languages have historically been limited to C, C++ and
+objective C. However any language that can call C functions and
+*importantly* be called back from C code ought to be usable. For
+example there have been experiments with JAVA using JNI but no current
+frontend is implemented using it.
+
+# Implementation complexity
+
+An absolutely minimal "proof of concept" frontend implementation (like
+the FLTK frontend that will be used as an example) is around 1,000
+lines of C code. Basic functionality like the windows frontend is
+around 7,000 lines. A complete fully functional frontend such as the
+one for GTK is closer to 15,000 lines.
+
+It should be noted the majority of the minimal implementation can
+simply be copied and the names changed as appropriate from an existing
+example. The actual amount of new code that needs to be provided is
+very small.
+
+NetSurf provides a great deal of generic functionality for things like
+cookie, bookmark, history windows which require only minimal frontend
+support with the [core window API](docs/core-window-interface.md).
+
+A frontend developer is free to implement any and all of this generic
+functionality thelselves in a manner more integrated into a toolkit.
+
+# Implementation
+
+A frontend is generally named for the toolkit it is implementing (i.e
+gtk for the GTK+ toolkit). It is advisable to be as specific as
+possible e.g. the frontend for the windows operating system should
+have been named win32 allowing for an impementation using a differnt
+toolkit (e.g mfc)
+
+All the files needed for the frontend are contained in a single
+sub-directory in the NetSurf source tree e.g. `frontends/fltk`
+
+The only file outside this directory that much be changed is the
+`frontends/Makefile.hts` where a new entry must be added to the valid
+targets list.
+
+## Build system
+
+A frontend must provide three GNU Makefile fragments (these will be
+included from the core Makefile):
+
+ - `Makefile` - This is used to extend CFLAGS, CXXFLAGS and LDFLAGS variables as required. The executable target is set with EXETARGET and the browser source files are listed in the SOURCES variable
+ - `Makefile.defaults` - allows setting frontend specific makefile variables and overriding of the default core build variables.
+ - `Makefile.tools` - allows setting up frontend specific build tooling (as a minimum a tool for the package configuration in PKG_CONFIG)
+
+Source code modules can be named as the devloper desires within the
+frontend directory and should be added to the SOURCES variable as
+desired.
+
+## Program entry
+
+Generally the entry point from the OS is the `main()` function and
+several frontends have a `main.cpp` where some have used `gui.c`.
+
+The usual shape for the `main()` function is a six step process:
+ 1. The frontends operation tables are registered with NetSurf
+ 2. The toolkit specific initialisation is performed (which may involve calling NetSurf provided utility functions for support operations like logging, message translations etc.)
+ 3. Initialise the NetSurf core. After this point all browser functionality is available and registered operations can be called.
+ 4. Perform toolkiit setup, usually opening the initial browsing window (perhaps according to user preferences)
+ 5. Run the toolkits main loop while ensuring the Netsurf scheduled operations are also run at teh apropriate time.
+ 6. Finalisation on completion.
+
+## NetSurf operations tables
+
+The frontend will generally call netsurf interfaces to get a desired
+behaviour e.g. `browser_window_create()` to create a new browsing
+context (the `browser_window_` prefix is historical and does not
+necessarily create a window e.g. on gtk it is more likely to open a
+tab in an existing window). To achive the desired operation some
+operations need to be performed by the frontend under control of
+NetSurf, these operations are listed in tables.
+
+The operation tables should be registered with the NetSurf core as one
+of the first operations of the frontend code. The functions in these
+tables (and the tables themselves) must remain valid until
+`netsurf_exit()` is called.
+
+There are (currently) twelve sets of operation tables held in separate
+structures. Only five of these are mandantory (misc, window, fetch,
+bitmap and layout).
+
+In this context mandantory means the tables must be non NULL and do
+not have a suitable default. Each of the mandantory sets contain
+function pointers to implement operations.
+
+### misc operation table
+
+The only mandantory operation in this table is schedule.
+
+When schedule is called the frontend must arrange for the passed
+callback to be called with the context parameter after a number of
+miliseconds.
+
+This callback is typicaly driven through the toolkits event loop and
+it is important such callbacks are not attempted from an operation.
+
+### window operation table
+
+The window operations (poorly named as already mentioned) are where
+the frontend is called to actually manipulate widgets in the
+toolkit. This is mediated through a `gui_window` context pointer which
+is typed as a structure.
+
+This context pointer is passed to all window operations and is
+generally assumed to contain at least a reference to the underlying
+`browser_window` which is provided in the initial create operation to
+allow subsequent use of various core functionality.
+
+The mandantory window operations are:
+ - create - create a new browsing context widget in the frontend toolkit
+ - destroy - destoy a previously created `gui_window`
+ - invalidate - mark an area of the browsing context viewport as requiring redraw (note no redraw should be attempted from here)
+ - get_scroll - get the scroll offsets from the toolkit drawing widget
+ - set_scroll - set the scroll offsets on the toolkit drawing widget
+ - get_dimensions - get the dimensions of the toolkit drawing widget
+ - event - deal with various window events from netsurf which have no additional parameters
+
+
+### fetch operation table
+
+The fetch operations allow the built in scheme fetchers (file, about, resource) to obtain additional information necessary to complete their operation.
+
+The two mandantory operations are:
+ - `filetype` - allows the file scheme to obtain a mime type from a file path e.g. `a.file.name.png` would result in `image/png`
+ - `get_resource_url` - maps resource scheme paths to URL e.g. `resource:default.css` to `file:///usr/share/netsurf/default.css`
+
+### bitmap operation table
+
+The bitmap table and all of its operations are mandantory only because
+the empty defaults have not been included as it is assumed a browser
+will want to display images.
+
+All operations may be provided by stubs that return the failure codes
+until full implementations are made.
+
+### layout operation table
+
+The layout table is used to layout text. All operations are given
+strings to manipulate encoded in UTF-8. There are three mandantory
+operations:
+ - `width` - Calculate the width of a string.
+ - `position` - Find the position in a string where an x coordinate falls.
+ - `split` - Find where to split a string to make it fit a width.
+
+# Worked Example
+
+Rather than attempt to describe every aspect of an implementation we
+will rather work from an actual minimal example for the FLTK toolkit.
+
+This is availble as a single commit (`git show 28ecbf82ed3024f51be4c87928fd91bacfc15cbc`) in the NetSurf source repository. Alternatively it can be [viewed in a web browser](https://git.netsurf-browser.org/netsurf.git/commit/?h=vince/fltk&id=28ecbf82ed3024f51be4c87928fd91bacfc15cbc).
+
+This represents the absolute minimum implementation to get a browser
+window on screen (and be able to click visible links). It is
+implemented in C++ as that is the FLTK implementation language but an
+equivalent implementation in other languages should be obvious.
+
+## Building
+
+The [frontends/Makefile.hts](https://git.netsurf-browser.org/netsurf.git/diff/frontends/Makefile.hts?h=vince/fltk&id=28ecbf82ed3024f51be4c87928fd91bacfc15cbc)
+had the fltk target added to the VLDTARGET variable. This allows
+NetSurf to be built for this frontend with `make TARGET=fltk`
+
+As previously described the three GNU Make files are added:
+
+[Makefile](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/Makefile?h=vince/fltk&id=28ecbf82ed3024f51be4c87928fd91bacfc15cbc)
+this shows how the flags are extended to add the fltk headers and
+library. Additionaly the list of sources are built here, as teh
+comment suggests it is important the SOURCES variable is not expanded
+here so the S_FRONTEND variable is used to allow expansion at teh
+correct time in the build process.
+
+[Makefile.defaults](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/Makefile.defaults?h=vince/fltk&id=28ecbf82ed3024f51be4c87928fd91bacfc15cbc)
+has the default setting to control the build parameters and file locations. These can be overriden by the `Makefile.config` at compile time.
+
+[Makefile.tools](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/Makefile.tools?h=vince/fltk&id=28ecbf82ed3024f51be4c87928fd91bacfc15cbc)
+allows the configuration of additional tools necessary to build for the target as a minimum pkg-config is usually required to find libraries.
+
+## Program entry
+
+In our example program entry is the classical `main()` in the [main.cpp](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/main.cpp?h=vince/fltk&id=28ecbf82ed3024f51be4c87928fd91bacfc15cbc) module.
+
+This implements the six stage process outlined previously.
+
+### Operations table registration
+
+The `netsurf_table` structure is initialised and passed to
+`netsurf_register()`. It should be noted that the approach taken here
+and in most frontends is to have a source module for each operation
+table. The header for each module exposes just the pointer to the
+indivial operation set, this allows for all the operation functions to
+be static to their module and hence helps reduce global symbol usage.
+
+### Frontend specific initialisation
+
+Her it is implemented in `nsfltk_init()` this function performs all
+the operations specific to the frontend which must be initialised
+before netsurf itself. In some toolkits this would require calling the
+toolkit initialisation (e.g. `gtk_init()`).
+
+It is nessesary to initialise netsurf logging and user options at this
+point. A more fully featured implementation would also initialise the
+message translation system here.
+
+### Netsurf initialisation
+
+This is simply the call to `netsurf_init()` from this point the
+browser is fully operational and operations can and will be called.
+
+### Frontend specific startup
+
+Although the browser is running it has not yet been told to open a
+window or navigate to a page. Here `nsfltk_start()` examines the
+command line and environment to determine the initial page to navigate
+to and calls `browser_window_create()` with the url, this will cause
+the browser to open a new browsing context and start the navigation.
+
+A frontend may choose to implement more complex logic here but the
+example here is a good start.
+
+### Toolkit run loop
+
+The function `nsfltk_run()` runs the toolkit event loop. In this case it is using the generic scheduleing in the [misc.cpp](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/misc.cpp?h=vince/fltk&id=28ecbf82ed3024f51be4c87928fd91bacfc15cbc) module to ensure callbacks get made at the apropriate time.
+
+There is a `nsfltk_done` boolean global checked here so when all the
+browser windows are closed the program will exit.
+
+A more fully featured port might use the toolkits scheduling rather
+than open coding a solution with a linked list as is done
+here.
+
+A futher optimisation would be to obtain the set of file descriptors
+being used (with `fetch_fdset()`) for active fetches allowing for
+activity based fetch progress instead of the fallback polling method.
+
+### finalisation
+
+This simply finalises the browser stopping all activity and cleaning
+up any resource usage. After the call to `netsurf_exit()` no more
+operation calls will be made and all caches used by the core will be
+flushed.
+
+If user option chnages are to be made persistant `nsoption_finalise()`
+should be called.
+
+The finalisation of logging will ensure that any output buffers are
+flushed.
+
+## The window operation table
+
+Amongst all the boilerplate of the default implementation the only novel code is in the window operation table in the [window.cpp](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/window.cpp?h=vince/fltk&id=28ecbf82ed3024f51be4c87928fd91bacfc15cbc) module.
+
+### `nsfltk_window_create`
+
+The create operation instansiates a new `NS_Window` object and
+references it in the gui_window structure which it returns to the
+caller. Technically we could simply return the `NS_Window` object as
+the gui_window pointer but this implementation is avoiding the cast.
+
+Secondly `Fl_Double_Window` is subclassed as `NS_Widget`. The sublass
+allows the close callback to be accessed so the global `nsfltk_done`
+boolean can be set during the destructor method.
+
+The NS_Window creates an instance of `NS_Widget` in its constructor, a
+more extensive implementation would add other window furniture here
+(scroll bars, url bar, navigation elements, etc.)
+
+The implementation subclasses `Fl_Widget` implementing the draw
+method to render the browsing context and the handle method to handle
+mouse events to allow teh user to click.
+
+The `NS_Widget::handle()` method simply translates the mouse press
+event from widget coordinates to netsurf canvas cooridinates and maps
+teh mouse button state. The core is informed of these events using
+`browser_window_mouse_click()`
+
+The `NS_Widget::draw` method similarly translates the fltk toolkits
+clip rectangle, builds a plotting context and calls
+`browser_window_redraw()` which will use the plotting operations in
+the plotting context to render the browsing context within the area
+specified. One thing to note here is the translation between the
+coordinates of the render area and the internal page canvas given as
+the second and third parameters to the draw call. When scrolling is
+required this is achived by altering these offsets.
+
+
+### `nsfltk_window_invalidate()`
+
+This simply calls the damage method on the `Fl_Widget` class with the
+appropriate coordinate translation.
+
+### `nsfltk_window_get_dimensions()`
+
+This obtains the fltk widget width and height and returns them.
+
+## The plotting interface
+
+When the `NS_Widget::draw` method was discussed it was noted that a
+plotting context is built containing an operation table. That table is
+implemented in [plotters.cpp](https://git.netsurf-browser.org/netsurf.git/diff/frontends/fltk/plotters.cpp?h=vince/fltk&id=28ecbf82ed3024f51be4c87928fd91bacfc15cbc)
+
+The implementation here is as minimal as can be, only line, rectangle
+and text have any implementation at all and even that simply sets a
+colour and performs the appropriate fltk draw function (`fl_line`,
+`fl_rect` and `fl_draw` respectively)
+
+# Worked Example next steps
+
+The previous section outlined the absolute minimum
+implementation. Here we can exmaine some next steps taken to extend
+the frontend.
+
+## Improving the user interface
+
+The example discussion is based on a commit (`git show bc546388ce428be5cfa37cecb174d549c7b30320`) in the NetSurf source repository. Alternatively it can be [viewed in a web browser](https://git.netsurf-browser.org/netsurf.git/commit/?h=vince/fltk&id=bc546388ce428be5cfa37cecb174d549c7b30320).
+
+This changes a single module `window.cpp` where the `NS_Window`,
+`NS_Widget` and `NS_URLBar` classes are used to create a basic
+browsing interface.
+
+The static window operation functions are moved inside the `NS_Window`
+class and the `gui_window` structure is used to obtain an instance
+allowing normal methods to be called to implement functionality. This
+is purely to make the C++ code more idiomatic and obviously would be
+handled differently in other languages.
+
+The `NS_Window` constructor builds additional widgets to just the
+browser drawing widget. It creates:
+ - a URL bar widget containing some navigation buttons and a widget to show the current url
+ - a vertical scrollbar
+ - a horizontal scrollbar
+ - a status text widget
+
+The scrollbar widgets fltk callbacks (called when user interacts with
+the scrollbar) call a method on the `NS_Widget` allowing it to track
+the current scroll offsets which are subsequently used in the drawing
+and user input handling methods.
+
+## Improving rendering
+
+Up to this point the rendering has been minimal and the text in a
+single face and size with incorrect width measurement. There was no
+proper handling of plotting styles and colours.
+
+## Implementing bitmap rendering
+
+There was no bitmap rendering so no pretty pictures.
+
+## Implementing the user messages API
+
+This immediately allows the browser to use the existing language
+translations for many internal strings.
+
+## Implementing a user settings dialog
+
+Implementing a way for the user to change configuration options
+without having to edit a configuration file greatly improves the
+perceived functionality.
+
+## Implementing corewindow
+
+The [core window interface](docs/core-window-interface.md) allows a
+frontend to use inbuilt rendering for several interfaces gaining a
+great deal of functionality for very litte code. This one interface
+set gives a cookie viewer,a local and global history viewer and a
+hotlist(bookmarks) viewer.
+
+# Conclusion
+
+Hopefully this breif overview and worked example should give the
+prospectinve frontend developer enough information to understand how
+to get started implementing a new frontend toolkit for NetSurf.
+
+As can be seen there is actualy very little novel code necessary to
+get started though I should mention that the move from "minimal" to
+"full" implementation is a large undertaking and it would be wise to
+talk with the NetSurf developers if undertaking such work.
diff --git a/docs/integration-testing.md b/docs/integration-testing.md
new file mode 100644
index 000000000..03b41308a
--- /dev/null
+++ b/docs/integration-testing.md
@@ -0,0 +1,542 @@
+NetSurf Integration Testing
+===========================
+
+[TOC]
+
+# Overview
+
+The monkey frontend is used to perform complex tests involving
+operating the browser as a user might (opening windows, navigating to
+websites and rendering the contents etc.)
+
+A test is written as a set of operations in a yaml file. These files
+are parsed and executed by the monkey driver script.
+
+There are very few tests within the NetSurf repository. The large
+majority of integration tests are instead held within the
+[netsurf-test](http://source.netsurf-browser.org/netsurf-test.git/)
+repository.
+
+To allow more effective use of these tests additional infrastructure
+has been constructed to allow groupings of tests to be run. This is
+used extensively by the CI system to perform integration testing on
+every commit.
+
+The infrastructure also provides for special CGI scripts which have
+known behaviours such as delays or returning specific content to
+extend test capabilities.
+
+
+# Running a test
+
+An individual test can be run using the monkey_driver.py python script
+from within the NetSurf repository
+
+ $ make TARGET=monkey
+ $ ./test/monkey_driver.py -m ./nsmonkey -t test/monkey-tests/start-stop.yaml
+
+The command actually executed can be augmented using the wrapper
+switch, this allows the test to be run under a debugger or profiler.
+
+For example to wrap execution under valgrind memory checker
+
+ $ ./test/monkey_driver.py -m ./nsmonkey -w 'valgrind -v --track-origins=yes' -t test/monkey-tests/start-stop.yaml
+
+
+# Running more than one test
+
+Each test is a member of a group and the tests within each group are
+run together. Groups are listed within division index files. A group
+of tests may occur within more than one division.
+
+To run the integration tests the monkey-see-monkey-do python script is
+used. It downloads the test plan for a division from the NetSurf test
+infrastructure and executes it.
+
+ $ ./test/monkey-see-monkey-do
+ Fetching tests...
+ Parsing tests...
+ Running tests...
+ Start group: initial
+ [ Basic checks that the browser can start and stop ]
+ => Run test: start-stop-no-js.yaml
+ => Run test: basic-navigation.yaml
+ => Run test: start-stop.yaml
+ Start group: no-networking
+ [ Tests that require no networking ]
+ => Run test: resource-scheme.yaml
+ Start group: ecmascript
+ [ ECMAScript tests ]
+ PASS
+
+If no division is specified on the command line the "default" division
+is used. Other divisions are specified with the d switch for example
+to specify the "short-internet" division:
+
+ $ ./test/monkey-see-monkey-do -d short-internet
+
+Additionally the g switch allows the limiting of tests within a single
+group to be executed.
+
+ $ ./test/monkey-see-monkey-do -g no-networking
+ Fetching tests...
+ Parsing tests...
+ Running tests...
+ Start group: no-networking
+ [ Tests that require no networking ]
+ => Run test: resource-scheme.yaml
+ PASS
+
+# Test files
+
+Each test is a individual [YAML](https://en.wikipedia.org/wiki/YAML)
+file and consists of associative arrays (key/value pairs), lists and
+comments.
+
+As a minimum a test must contain an associative array with keys for
+`title`, `group` and `steps`. The `steps` key must contain a list of
+test operations as a value.
+
+Each operation is an associative list and must, as a minimum, contain
+an action key with a suitable value.
+
+A minimal test that simply starts the browser without JavaScript and
+then quits it without ever opening a window to browse to a page
+
+ title: start and stop browser without JS
+ group: initial
+ steps:
+ - action: launch
+ options:
+ - enable_javascript=0
+ - action: quit
+
+
+# Actions
+
+## launch
+
+Start a browser instance. A test will generally have a single launch
+action paired with a quit action.
+
+Additional command line parameters may be set using the `launch-options`
+key the value of which must be a list of command line arguments to be
+passed to the browser (without their leading hyphens)
+
+The environment of the browser can be altered with the `environment` key
+the value is an associative array of environment variables which will
+be added to the browsers environment variables.
+
+User options may be set using the `options` key with a value containing
+a list of options to set. These options allow operation with differing
+user choices to be tested without a separate Choices file.
+
+The `language` key sets the LANGUAGE environment variable which controls
+the browsers user interface language. Note this is distinct from the
+language the browser requests from HTTP servers which is controlled
+with the `accept_language` user option.
+
+The following launch action would start a browser:
+ * Passing `--verbose` on the commandline
+ * The `NETSURFRES` environment variable set to `/home/netsurf/resources`
+ * The user options `enable_javascript` and `send_referer` set to false.
+ * The `LANGUAGE` environment variable set to `en`
+
+```
+- action: launch
+ launch-options:
+ - verbose
+ environment:
+ NETSURFRES: /home/netsurf/resources
+ options:
+ - enable_javascript=0
+ - send_referer=0
+ language: en
+```
+
+## window-new
+
+Open a new browser window. The test may open as many browser windows
+as necessary and they are usually paired with a `window-close` action
+
+The browser must have been previously launched or this action will
+assert the test with a failure.
+
+The `tag` key *must* also be present with a value (unique for all
+window-new actions). The value is used to identify subsequent
+operations in this window.
+
+As an example this will open a new window which can subsequently be
+referred to with the win1 identifier:
+
+ - action: window-new
+ tag: win1
+
+
+## window-close
+
+Closes a previously opened window. The window is identified with the
+`window` key, the value of this must be a previously created window
+identifier or an assert will occur.
+
+ - action: window-close
+ window: win1
+
+
+## navigate
+
+Cause a window to start navigating to a new URL.
+
+The window to be navigated is identified with the `window` key, the
+value of this must be a previously created window identifier or an
+assert will occur.
+
+The URL to navigate to navigate to is controlled either by the `url`
+or `repeaturl` key. The `url` value is directly used as the address to
+navigate to.
+
+ - action: navigate
+ window: win1
+ url: about:about
+
+The `repeaturl` value is used as a repeat action identifier allowing
+navigation in a loop with different values.
+
+ - action: repeat
+ values:
+ - https://www.google.com/
+ - https://apple.com/
+ - https://microsoft.com/
+ tag: urls
+ - action: navigate
+ window: win1
+ repeaturl: urls
+
+
+## reload
+
+Cause a window to (re)navigate to the current URL
+
+The window to be navigated is identified with the `window` key, the
+value of this must be a previously created window identifier or an
+assert will occur.
+
+ - action: reload
+ window: win1
+
+## stop
+
+Cause a window to immediately stop any navigation.
+
+The window to be navigated is identified with the `window` key, the
+value of this must be a previously created window identifier or an
+assert will occur.
+
+ - action: stop
+ window: win1
+
+## sleep-ms
+
+Wait for time to pass before continuing to next action.
+
+The value of the `time` key is either the duration to wait for in
+milliseconds or a `repeat` action identifier.
+
+The optional `conditions` key may contain a list of conditionals used
+to terminate the delay early. If a `repeat` action identifier is in
+use the loop is terminated if a condition is met.
+
+For example to wait 10 seconds:
+
+ - action: sleep-ms
+ time: 10000
+
+if a repeat action identifier is used the delay duration is the
+current iteration value and the delay is timed from when the current
+iteration started.
+
+The `sleep-ms` action here delays by 50 milliseconds more each
+iteration until the window navigation is complete when the `sleep-ms`
+action is delaying.
+
+ - action: repeat
+ min: 0
+ step: 50
+ tag: sleepytimer
+ steps:
+ - action: launch
+ - action: window-new
+ tag: win1
+ - action: navigate
+ window: win1
+ url: about:about
+ - action: sleep-ms
+ time: sleepytimer
+ conditions:
+ - window: win1
+ status: complete
+ - action: quit
+
+
+## block
+
+Wait for conditions to be met before continuing. This is similar to
+the `sleep-ms` action except that it will wait forever for the
+conditions to be met.
+
+The `conditions` key must contain a list of conditionals used to
+terminate the block.
+
+ - action: block
+ conditions:
+ - window: win1
+ status: complete
+
+valid `status` values are `complete` or `loading`.
+
+## repeat
+
+Repeat a set of actions.
+
+The identifier of the repeat action is set with the `tag` key and must
+be present and unique among `repeat` action identifiers.
+
+The actions to be repeated are placed in the `steps` list which may
+include any action and behaves just like the top level list.
+
+An iterator context is created for the repeat loop. The iterator can
+either be configured as a numeric value or as a list of values.
+
+The numeric iterator is controlled with the `min` ,`step` and `max`
+keys. All these keys are integer values and their presence is
+optional.
+
+The `min` value is the initial value of the iterator which defaults
+to 0.
+
+The `step` value controls how much the iterator is incremented
+on every loop with default value of 1.
+
+The loop terminates if the `max` value is exceeded. If no `max` value
+is specified the loop is infinite (i.e. no default) but may still be
+terminated by the `sleep-ms` action
+
+ - action: repeat
+ min: 0
+ step: 50
+ max: 100
+ tag: loopvar
+ steps:
+ - action: launch
+ - action: quit
+
+A value iterator has a `values` key containing a list. On each
+iteration of the loop a new value is available and can be used by the
+`navigate` action.
+
+Note that `min` ,`step` and `max` are ignored if there is a `values` key
+
+ - action: repeat
+ values:
+ - https://www.google.com/
+ - https://www.blogger.com/
+ - https://apple.com/
+ - https://microsoft.com/
+ tag: urls
+ steps:
+ - action: navigate
+ window: win1
+ repeaturl: urls
+ - action: block
+ conditions:
+ - window: win1
+ status: complete
+
+
+## timer-start
+
+Start a timer.
+
+The identifier for the timer is set with the `timer` key.
+
+ - action: timer-start
+ timer: timer1
+
+
+## timer-restart
+
+Re-start a timer
+
+The identifier for the timer is set with the `timer` key.
+
+ - action: timer-restart
+ timer: timer1
+
+
+## timer-stop
+
+Stop a timer
+
+The identifier for the timer is set with the `timer` key.
+
+ - action: timer-stop
+ timer: timer1
+
+
+## timer-check
+
+Check a timer meets a condition.
+
+The identifier for the timer is set with the `timer` key.
+
+The conditional is set with the `condition` key which must be present.
+
+
+## plot-check
+
+Perform a plot of a previously navigated window.
+
+The window to be rendered is identified with the `window` key, the
+value of this must be a previously created window identifier or an
+assert will occur.
+
+The `area` key allows control of the area to be redraw. The parameters are on two forms:
+
+ * A sequence of four numbers in the form `x0 y0 x1 y1`
+ * The keyword extent which attempt to plot the entire extent of the canvas
+
+An optional list of checks may be specified with the `checks` key. If
+any check is not satisfied an assert will occur and the test will
+fail. Multiple checks can be specified and all most pass successfully.
+
+The checks available are:
+
+ * The key `text-contains` where the text must occur somewhere in the
+ plotted output.
+ * The key `text-not-contains` where the text must not occur in the
+ plotted output.
+ * The key `bitmap-count` which specifies the number of images that
+ must be present.
+
+
+ - action: plot-check
+ window: win1
+ area: extent
+ checks:
+ - text-contains: NetSurf
+ - text-contains: Browser
+ - text-not-contains: Chrome
+ - bitmap-count: 1
+
+
+## click
+
+Perform a user mouse click on a specified window.
+
+The window to be clicked is identified with the `window` key, the
+value of this must be a previously created window identifier or an
+assert will occur.
+
+The `target` key contains an associative array which is used to select
+the location of the mouse operation in the window. The key `text` can
+be used to select text to be operated upon which matches the first
+occurrence of the text. The key `bitmap` has an integer value to
+select the index of the image to click.
+
+The optional `button` key selects which button is pressed it can take
+the value `left` or `right`. The default if not specified is `left`
+
+The optional `kind` key selects which button operation to be performed
+it can take the value `single`, `double` or `triple`. The default if
+not specified is `single`
+
+ - action: click
+ window: win1
+ target:
+ text: "about:Choices"
+
+
+## wait-loading
+
+Wait for the navigated page to start loading before moving to the next
+action.
+
+The window to be waited upon is identified with the `window` key, the
+value of this must be a previously created window identifier or an
+assert will occur.
+
+ - action: wait-loading
+ window: win1
+
+
+## add-auth
+
+Add basic authentication details for a navigation.
+
+The keys `url`, `realm`, `username` and `password` must be given. When
+a basic authentication challenge occurs that matches the url and
+realm parameters the associated username and password are returned to
+answer the challenge.
+
+ - action: add-auth
+ url: http://test.netsurf-browser.org/cgi-bin/auth.cgi?user=foo&pass=bar
+ realm: Fake Realm
+ username: foo
+ password: bar
+
+
+## remove-auth
+
+Remove a previously added authentication details.
+
+ - action: remove-auth
+ url: http://test.netsurf-browser.org/cgi-bin/auth.cgi?user=foo&pass=bar
+ realm: Fake Realm
+ username: foo
+ password: bar
+
+
+## clear-log
+
+Clear log for a window.
+
+The window to be cleared is identified with the `window` key, the
+value of this must be a previously created window identifier or an
+assert will occur.
+
+
+## wait-log
+
+Wait for string to appear in log output.
+
+The window to be waited upon is identified with the `window` key, the
+value of this must be a previously created window identifier or an
+assert will occur.
+
+The keys `source` `foldable` `level` and `substring` must be specified
+
+## js-exec
+
+Execute javascript in a window.
+
+The window to be execute within is identified with the `window` key, the
+value of this must be a previously created window identifier or an
+assert will occur.
+
+The `cmd` key contains the javascript to execute.
+
+
+## page-info-state
+
+Check the page information status matches an expected value.
+
+The window to be checked is identified with the `window` key, the
+value of this must be a previously created window identifier or an
+assert will occur.
+
+The value of the `match` key is compared to the windows page
+information status and an assert occurs if there is a mismatch.
+
+## quit
+
+This causes a previously launched browser instance to exit cleanly.
diff --git a/docs/jsbinding.md b/docs/jsbinding.md
new file mode 100644
index 000000000..8b24a80a5
--- /dev/null
+++ b/docs/jsbinding.md
@@ -0,0 +1,313 @@
+JavaScript bindings
+===================
+
+In order for JavaScript programs to to interact with the page contents
+it must use the Document Object Model (DOM) and Cascading Style Sheet
+Object Model (CSSOM) API.
+
+These interfaces are described using Web Interface Description
+Language (WebIDL) within the relevant specifications
+(e.g. https://dom.spec.whatwg.org/).
+
+Each interface described by the WebIDL must be bound (connected) to
+the browsers internal representation for the DOM or CSS, etc. These
+bindings descriptions are processed together with the WebIDL by the
+nsgenbind tool to generate source code.
+
+A list of [DOM and CSSOM methods](unimplemented.html) is available
+outlining the remaining unimplemented API bindings.
+
+WebIDL
+------
+
+The [WebIDL specification](http://www.w3.org/TR/WebIDL/) defines the
+interface description language used. The WebIDL is being updated and
+an [editors draft](https://heycam.github.io/webidl/) is available but
+use is inconsistent.
+
+These descriptions should be periodically updated to keep the browser
+interfaces current.
+
+There is a content/handlers/javascript/WebIDL/Makefile which attempts
+to automatically update the IDL files by scraping the web specs.
+
+This tool needs a great deal of hand holding, not least because many of the
+source documents list the IDL fragments multiple times, some even have
+appendices with the entire IDL repeated.
+
+The IDL uses some slightly different terms than other object orientated
+ systems.
+
+ WebIDL | JavaScript | Common OOP | Note
+ ------- | ---------- | ---------- | ----
+ interface | prototype | class | The data definition of the object
+ constants | read-only value property on the prototype | class variable | Belong to class, one copy
+ operation | method | method | functions that can be called
+ attribute | property | property | Variables set per instance
+
+JavaScript implementation
+-------------------------
+
+NetSurf consumes the Duktape JS engine in order to run the JS code which
+is used within the browser. Duktape is exceedingly well documented and
+its API docs at https://duktape.org/api.html are incredibly useful.
+
+It'll be worthwhile learning about how duktape stacks work in order to
+work on bindings in NetSurf
+
+Dukky
+-----
+
+Wrappering around and layering between duktape and the browser is a
+set of functionality we call `dukky`. This defines a variety of
+conventions and capabilities which are common to almost all bindings.
+The header `dukky.h` provides the interface to these functions.
+
+Normally these functions are used by automatically generated content,
+but if a binding needs to add DOM nodes back into the JavaScript
+environment (for example when returning them from a method
+implementation) `dukky_push_node()` should be used or when calling a
+function in a JS context `dukky_pcall()`
+
+Dukky automatically terminates any JS call which lasts for more than
+10 seconds. If you are calling a JS function from outside any of the
+"normal" means by which dukky might call code on your behalf
+(`js_exec()`, events, etc) then you should be sure to use
+`dukky_pcall()` and pass in `true` in `reset_timeout` otherwise your
+code may unexpectedly terminate early.
+
+Interface binding introduction
+------------------------------
+
+The binding files are processed by the nsgenbind tool to generate c
+source code which implements the interfaces within the JavaScript
+engine.
+
+The bindings are specific to a JavaScript engine, the DOM library, the
+CSS library and the browser. In this case that is the tuple of
+duktape, libdom, libcss and NetSurf.
+
+In principle other engines or libraries could be substituted
+(historically NetSurf unsuccessfully tried to use spidermonkey) but the
+engineering to do so is formidable.
+
+The bindings are kept the main [NetSurf source code
+repository](http://git.netsurf-browser.org/netsurf.git/) within the
+duktape JavaScript handler directory `content/handlers/javascript/duktape/`
+
+The root binding which contains all the interfaces introduced into
+the JavaScript programs initial execution context is nesurf.bnd this
+references all the WebIDL to be bound and includes all additional
+binding definitions to implement the interfaces.
+
+The bindings are a Domain Specific Language (DSL) which allows
+implementations to be added to each WebIDL method. nsgenbind
+documentation contains a [full description of the
+language](https://ci.netsurf-browser.org/jenkins/view/Categorized/job/docs-nsgenbind/doxygen/index.html).
+
+The main focus on creating binding is to implement the content within
+getter, setter and method stanzas. These correspond to implementations
+of the WebIDL operations on an interface.
+
+The binding implementations are in the form of C code fragments
+directly pasted into the generated code with generated setup code
+surrounding it.
+
+### Simple attribute example
+
+The Window interface (class) in the HTML specification has an
+attribute (property) called `name`.
+
+The full WebIDL for the Window interface is defined in the
+`content/handlers/javascript/WebIDL/html.idl` file but the
+fragment for our example is just:
+
+ interface Window : EventTarget {
+ attribute DOMString name;
+ };
+
+This indicates there is an attribute called `name` which is a string
+(technicaly a DOMString but the implementation does not differentiate
+between string types) which means it has both a setter and a getter.
+
+attributes can be marked readonly which would mean there is only a
+getter required for them. For example the Plugin interface has a
+'name' attribute defined as:
+
+ interface Plugin {
+ readonly attribute DOMString name;
+ };
+
+The getter and setter for the Window class attribute will be added to
+`Window.bnd`. The entries added will be of the form:
+
+ getter Window::name()
+ %{
+ %}
+
+ setter Window::name()
+ %{
+ %}
+
+The top level `netsurf.bnd` binding includes `Window.bnd` (using a
+`#include` directive) which contains the implementation of the Window
+class. This is purely to split the bindings up into logical units.
+
+The nsgenbind tool generates code that automatically allows acess to
+the classes private data structure elements through a variable called
+`priv` and the duktape stack in the variable `ctx`.
+
+The getter binding code must place the retrived value on the duktape
+stack and return 1 to indicate this or 0 if it failed.
+
+So for the name attribute case the complete getter binding is:
+
+ getter Window::name()
+ %{
+ const char *name;
+ browser_window_get_name(priv->win, &name);
+ duk_push_string(ctx, name);
+ return 1;
+ %}
+
+This uses the browser_window_get_name() interface to retrieve the name
+string for the window (identified using the private context) and then
+adds it to the duktape stack. The return value indicates the sucess of
+the operation.
+
+The setter must retrive the value to set from the duktap stack and
+update the internal private data structure with that value and return
+0 to indicate success.
+
+So for the name attribute case the complete setter binding is:
+
+ setter Window::name()
+ %{
+ const char *name;
+ name = duk_to_string(ctx, -1);
+ browser_window_set_name(priv->win, name);
+ return 0;
+ %}
+
+This uses browser_window_set_name() interface to set the name of the
+window. The return indicates the success of the operation.
+
+### Simple method example
+
+The Location interface (class) in the HTML specification has an
+operation (method) called `asign`. This method causes the browser to
+navigate to a new url.
+
+The full WebIDL for the Window interface is defined in the
+`content/handlers/javascript/WebIDL/html.idl` file but the
+fragment for our example is:
+
+ interface Location {
+ void assign(DOMString url);
+ }
+
+This shows there is an operation called assign in the Location
+interface which takes a single string parameter and returns nothing.
+
+The method binding will be added to `Location.bnd` similarly to how
+the attribute example used `Window.bnd`
+
+ method Location::assign()
+ %{
+ window_private_t *priv_win;
+ nsurl *joined;
+ duk_size_t slen;
+ const char *url;
+
+ /* retrieve the private data from the root object (window) */
+ duk_push_global_object(ctx);
+ duk_get_prop_string(ctx, -1, PRIVATE_MAGIC);
+ priv_win = duk_get_pointer(ctx, -1);
+ duk_pop(ctx);
+
+ if (priv_win == NULL || priv_win->win == NULL) {
+ NSLOG(netsurf, INFO, "failed to get browser context");
+ return 0;
+ }
+
+ url = duk_safe_to_lstring(ctx, 0, &slen);
+
+ nsurl_join(priv->url, url, &joined);
+ browser_window_navigate(priv_win->win,
+ joined,
+ NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(joined);
+ return 0;
+ %}
+
+The nsgenbind tool generates code that automatically allows acess to
+the classes private data structure elements through a variable called
+`priv` and the duktape stack in the variable `ctx`.
+
+In this case nsgenbind will generate code that will ensure there is at
+least one parameter and coerce it to a string on the duktape `ctx`
+stack returning a type error if it is unable to do so.
+
+The binding implementation shown here uses browser_window_navigate()
+to navigate to the new url. To do this it needs the browser window
+handle (pointer) which is obtained from the global object (the window)
+private structure.
+
+Note that the duk_safe_to_lstring() call used to obtain the url
+parameter needs no additional checking as nsgenbind emits this code
+automaticaly.
+
+### Overloaded method example
+
+The Window interface (class) in the HTML specification has an
+operation (method) called `alert`. This method is supposed to cause
+the user to be alerted about something on the page.
+
+The full WebIDL for the Window interface is defined in the
+`content/handlers/javascript/WebIDL/html.idl` file but the
+fragment for our example is:
+
+ interface Window : EventTarget {
+ void alert();
+ void alert(DOMString message);
+ };
+
+This indicates there is an operation called `alert`. It has two
+overloaded prototypes, one takes no parameters and one takes a string
+parameter (technicaly a DOMString but the implementation does not
+differentiate between string types)
+
+The method binding will be added to `Window.bnd` as the attribute example
+
+ method Window::alert()
+ %{
+ duk_idx_t dukky_argc = duk_get_top(ctx);
+ if (dukky_argc == 0) {
+ NSLOG(netsurf, INFO, "JS ALERT");
+ } else {
+ duk_size_t msg_len;
+ const char *msg;
+
+ if (!duk_is_string(ctx, 0)) {
+ duk_to_string(ctx, 0);
+ }
+ msg = duk_safe_to_lstring(ctx, 0, &msg_len);
+ NSLOG(netsurf, INFO, "JS ALERT: %*s", (int)msg_len, msg);
+ }
+ return 0;
+ %}
+
+The nsgenbind tool generates code that automatically allows acess to
+the classes private data structure elements through a variable called
+`priv` and the duktape stack in the variable `ctx`.
+
+For overloaded method calls nsgenbind does not emit code to do
+parameter verification and the binding code has to deal with all
+possible parameters itself.
+
+This binding checks the number of parameters and if one is present it
+coerces it to be a string and logs the result. \ No newline at end of file
diff --git a/docs/logging.md b/docs/logging.md
index 41c7ea1bd..abc852bca 100644
--- a/docs/logging.md
+++ b/docs/logging.md
@@ -62,12 +62,18 @@ The main command line switches that control logging are:
- -V <file>
Send the logging to a file instead of standard output
- - -log_filter=<filter>
+ - --log_filter=<filter>
Set the non verbose filter
- - -log_verbose_filter=<filter>
+ - --verbose_filter=<filter>
Set the verbose filter
+Examples:
+
+ ./nsgtk --log_filter="level:INFO"
+ ./nsgtk -v --verbose_filter="(cat:layout && level:DEBUG)"
+ ./nsgtk -v --verbose_filter="((cat:layout && level:DEBUG) || level:INFO)"
+
Options
-------
diff --git a/docs/mainpage.md b/docs/mainpage.md
index fa72d1464..afff4b65d 100644
--- a/docs/mainpage.md
+++ b/docs/mainpage.md
@@ -1,98 +1,13 @@
NetSurf web browser
===================
-![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1037/badge)[*](https://bestpractices.coreinfrastructure.org/projects/1037)
+![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1037/badge)
-The NetSurf code makes use of Doxygen for code documentation.
+[CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1037)
-User Interface
---------------
-There are some basic user guides for the
-[framebuffer](docs/using-framebuffer.md) and
-[monkey](docs/using-monkey.md) frontends.
+[Project](docs/project.md)
-The [core user options](docs/netsurf-options.md) of the browser are
-documented which are augmented by each frontend in a specific manner.
-
-### Logging
-
-The [logging](docs/logging.md) interface controls debug and error
-messages not output through the GUI.
-
-Documented API
---------------
-
-There are several documents which detail specific aspects of the
-codebase and APIs.
-
-### Core window
-
-The [core window API](docs/core-window-interface.md) allows frontends
-to use generic core code for user interface elements beyond the
-browser render.
-
-### Source object caching
-
-The [source object caching](docs/source-object-backing-store.md)
-provides a way for downloaded content to be kept on a persistent
-storage medium such as hard disc to make future retrieval of that
-content quickly.
-
-### Javascript
-
-JavaScript is provided by integrating the duktape library. There are [instructions](docs/updating-duktape.md) on how to update the library.
-
-A list of [unimplemented DOM and CSSOM methods](unimplemented.html)
-is available outlining the remaining API that have to be implemented.
-
-Development
------------
-
-Compiling a development edition of NetSurf requires a POSIX style
-environment. Typically this means a Linux based system although Free
-BSD, Open BSD, Mac OS X and Haiku all known to work.
-
-### Working with the team
-
-Generally it is sensible to check with the other developers if you are
-planning to make a change to NetSurf intended to be merged.
-
-We are often about on the IRC channel but failing that the developer
-mailing list is a good place to try.
-
-All the project sources are held in [public git repositories](http://source.netsurf-browser.org/)
-
-### Toolchains
-
-Compilation for non POSIX toolkits/frontends (e.g. RISC OS) generally
-relies upon a cross compilation environment which is generated using
-the makefiles found in our
-[toolchains](http://source.netsurf-browser.org/toolchains.git/)
-repository. These toolchains are built by the Continuous Integration
-(CI) system and the
-[results of the system](http://ci.netsurf-browser.org/builds/toolchains/)
-are published as a convenience.
-
-### Quick setup
-
-The [quick start guide](docs/quick-start.md) can be used to get a
-development environment setup quickly and uses the
-[env.sh](env_8sh_source.html) script the core team utilises.
-
-### Manual setup
-
-The Manual environment setup and compilation method is covered by the
-details in the [netsurf libraries](docs/netsurf-libraries.md) document
-for the core libraries and then one of the building documents for the
-specific frontend.
-
-- [Amiga Os cross](docs/building-AmigaCross.md) and [Amiga OS](docs/building-AmigaOS.md)
-- [Framebuffer](docs/building-Framebuffer.md)
-- [GTK](docs/building-GTK.md)
-- [Haiku (BeOS)](docs/building-Haiku.md)
-- [Windows Win32](docs/building-Windows.md)
-
-These documents are sometimes not completely up to
-date and the env.sh script should be considered canonical.
+[User Interface](docs/user-interface.md)
+[Development](docs/development.md) \ No newline at end of file
diff --git a/docs/netsurf-fb.1 b/docs/netsurf-fb.1
index e4c310075..045c1fe1a 100644
--- a/docs/netsurf-fb.1
+++ b/docs/netsurf-fb.1
@@ -95,9 +95,6 @@ Maximum disc cache size.
.B \-\-block_advertisements
Boolean to enable ad blocking.
.TP
-.B \-\-minimum_gif_delay
-Minimum time between gif frames
-.TP
.B \-\-send_referer
Boolean controlling whether referer data should be sent
.TP
@@ -146,12 +143,6 @@ The width of the initial window.
.B \-\-window_height
The height of the initial window.
.TP
-.B \-\-window_screen_width
-window screen width
-.TP
-.B \-\-window_screen_height
-window screen height
-.TP
.B \-\-toolbar_status_size
toolbar status size
.TP
@@ -308,9 +299,6 @@ Override CSS sys_colour_WindowFrame colour.
.B \-\-sys_colour_WindowText
Override CSS sys_colour_WindowText colour.
.TP
-.B \-\-render_resample
-render resample
-.TP
.B \-\-downloads_clear
downloads clear
.TP
@@ -332,9 +320,6 @@ button type
.B \-\-disable_popups
disable popups
.TP
-.B \-\-disable_plugins
-disable plugins
-.TP
.B \-\-history_age
history age
.TP
diff --git a/docs/netsurf-gtk.1 b/docs/netsurf-gtk.1
index 7b2f4f4f3..2ae61be84 100644
--- a/docs/netsurf-gtk.1
+++ b/docs/netsurf-gtk.1
@@ -67,8 +67,6 @@ Maximum memory cache size.
Maximum disc cache size.
.It Fl -block_advertisements
Boolean to enable ad blocking.
-.It Fl -minimum_gif_delay
-Minimum time between gif frames
.It Fl -send_referer
Boolean controlling whether referrer data should be sent
.It Fl -animate_images
@@ -101,10 +99,6 @@ The Y co-ordinate of the initial window.
The width of the initial window.
.It Fl -window_height
The height of the initial window.
-.It Fl -window_screen_width
-window screen width
-.It Fl -window_screen_height
-window screen height
.It Fl -toolbar_status_size
toolbar status size
.It Fl -scale
@@ -209,8 +203,6 @@ Override CSS sys_colour_Window colour.
Override CSS sys_colour_WindowFrame colour.
.It Fl -sys_colour_WindowText
Override CSS sys_colour_WindowText colour.
-.It Fl -render_resample
-render resample
.It Fl -downloads_clear
downloads clear
.It Fl -request_overwrite
@@ -225,8 +217,6 @@ Force tabs to always be show.
button type
.It Fl -disable_popups
disable popups
-.It Fl -disable_plugins
-disable plugins
.It Fl -history_age
history age
.It Fl -hover_urls
diff --git a/docs/netsurf-options.md b/docs/netsurf-options.md
index 553813842..5a723c76b 100644
--- a/docs/netsurf-options.md
+++ b/docs/netsurf-options.md
@@ -42,9 +42,9 @@ General Options
memory_cache_size | int | 12MiB | Preferred maximum size of memory cache in bytes.
disc_cache_size | uint | 1GiB | Preferred expiry size of disc cache in bytes.
disc_cache_age | int | 28 | Preferred expiry age of disc cache in days.
+ disc_cache_path | string | NULL | Path to disc cache, NULL means to use system path |
block_advertisements | bool | false | Whether to block advertisements
do_not_track | bool | false | Disable website tracking [1]
- minimum_gif_delay | int | 10 | Minimum GIF animation delay
send_referer | bool | true | Whether to send the referer HTTP header.
foreground_images | bool | true | Whether to fetch foreground images
background_images | bool | true | Whether to fetch background images
diff --git a/docs/project.md b/docs/project.md
new file mode 100644
index 000000000..7fa76d9ae
--- /dev/null
+++ b/docs/project.md
@@ -0,0 +1,17 @@
+NetSurf Project
+===============
+
+The NetSurf project is developing a document browser for the World
+Wide Web. It was started in 2002 on the RISC OS platform and has
+support for numerous operating systems and graphical toolkits.
+
+NetSurf is very modular and built from many component libraries which
+provide functionality from GIF image format decoding (libnsgif) to
+HTML document object model handling (libdom).
+
+NetSurf browser is open source and is licensed under the GPLv2 (with
+OpenSSL exception). Many of the supporting libraries are under a MIT
+licence.
+
+The [main website](http://www.netsurf-browser.org/) contains links to
+other resources and additional information.
diff --git a/docs/quick-start.md b/docs/quick-start.md
index 8bc90de81..449b956a3 100644
--- a/docs/quick-start.md
+++ b/docs/quick-start.md
@@ -1,15 +1,29 @@
Quick Build Steps for NetSurf
=============================
-Last Updated: 24 February 2015
+Last Updated: 21st January 2020
This document provides steps for building NetSurf.
+These instructions use a shell script to perform several operations.
+ This script has only been tested with the bash and zsh bourne style
+ shell interpreters. The latest version of this script should be
+ retrieved from the official NetSurf source repository.
+
+This shell script is used by the NetSurf Developers but you should
+ satisfy yourself that the script is not malicious. It should be noted
+ that building the browser will also be executing shell code and
+ requires a similar level of trust.
+
+
+Native build
+============
Grab a temporary env.sh
-----------------------
- $ wget http://git.netsurf-browser.org/netsurf.git/plain/docs/env.sh
+ $ wget https://git.netsurf-browser.org/netsurf.git/plain/docs/env.sh
+ $ unset HOST
$ source env.sh
@@ -28,6 +42,11 @@ If your package manager is not supported, you will have to install third
Get the NetSurf project source code from Git
--------------------------------------------
+All the sources for the browser and support libraries is available
+ from the public git server.
+
+Local copies may be easily obtained with the ns-clone command.
+
$ ns-clone
@@ -42,7 +61,7 @@ Updates NetSurf project library sources to latest, builds and installs them.
Switch to new NetSurf workspace
-------------------------------
-Remove the bootstrack script and use the newly installed one
+Remove the bootstrap script and use the newly installed one
$ rm env.sh
$ cd ~/dev-netsurf/workspace
@@ -54,39 +73,41 @@ Build and run NetSurf
$ cd netsurf
-To build the native front end (the GTK front end on Linux, BSDs, etc) you
-could do:
+To build the native front end (the GTK front end on Linux, BSDs, etc)
+ you could do:
$ make
- $ ./nsgtk
+ $ ./nsgtk3
To build the framebuffer front end, you could do:
$ make TARGET=framebuffer
$ ./nsfb
+More detailed documentation on using the [framebuffer](docs/using-framebuffer.md)
+ frontend are available.
Cross Compiling
===============
If you are cross compiling, you can follow the above steps, but when
-sourcing env.sh, you should set HOST environment variable to the
-appropriate triplet for your cross compiler. For example, to cross
-compile for RISC OS:
+ sourcing env.sh, you should set HOST environment variable to the
+ appropriate triplet for your cross compiler. For example, to cross
+ compile for RISC OS:
$ HOST=arm-unknown-riscos source env.sh
After that, the commands such as `ns-package-install` and
-`ns-pull-install` will do what is appropriate for the platform you
-are building for.
+ `ns-pull-install` will do what is appropriate for the platform you are
+ building for.
-To do the final build of NetSurf, pass the appropriate TARGET to make.
-For example, to cross compile for RISC OS:
+To do the final build of NetSurf, pass the appropriate TARGET to
+ make. For example, to cross compile for RISC OS:
$ make TARGET=riscos
Finally, you can package up your build to transfer to the system you
-are developing for. For example, to produce a package for RISC OS:
+ are developing for. For example, to produce a package for RISC OS:
$ make TARGET=riscos package
@@ -94,18 +115,19 @@ Getting a cross compiler set up
-------------------------------
We maintain cross compilation environments and an SDK for a number of
-platforms. These may be found in our toolchains repository.
+ platforms. These may be found in our toolchains repository.
$ git clone git://git.netsurf-browser.org/toolchains
-Pre-built versions of the toolchains for Debian systems are often available
-via our [automated build and test infrastructure](http://ci.netsurf-browser.org/builds/toolchains/)
+Pre-built versions of the toolchains for 64bit x86 Debian systems are
+ available via our [automated build and test
+ infrastructure](https://ci.netsurf-browser.org/builds/toolchains/)
Not working?
============
-If the above steps are inapplicable, or don't work, you can build manually.
-Follow the instructions in the BUILDING-* documents in the docs/ directory
-the NetSurf browser source tree.
+If the above steps are inapplicable, or don't work, you can build
+ manually. Follow the instructions in the BUILDING-* documents in the
+ docs/ directory the NetSurf browser source tree.
diff --git a/docs/source-object-backing-store.md b/docs/source-object-backing-store.md
index 0fb3614d4..4fb662087 100644
--- a/docs/source-object-backing-store.md
+++ b/docs/source-object-backing-store.md
@@ -1,26 +1,36 @@
Source Object (low level) cache backing store
=============================================
-Introduction
-------------
+[TOC]
-The source object cache provides a system to extend the life of source
-objects (HTML files, images etc.) after they are no longer immediately
-being used.
+# Introduction
-Only fetch types where we have well defined rules on caching are
-considered, in practice this limits us to HTTP(S). The section in
-RFC2616 [1] on caching specifies these rules.
+The source object (referred to as low level in the code) content cache
+provides a unified API for the rest of the browser to retrieve objects
+(HTML files, images etc.) from a URL.
+
+The cache initialy always fufuls these requsts by using the fetcher
+system to retrive data according to the URL scheme (network for HTTP,
+disc for file etc.) and storing the result in memory.
+
+The cache also provides a system to extend the life of source objects
+in memory when they are no longer immediately being used. Only fetch
+types where there are well defined rules on caching are considered, in
+practice this limits the cache to URLS with HTTP(S) schemes. The
+section in RFC2616 [1] on caching specifies these rules.
To further extend the objects lifetime they can be pushed into a
backing store where the objects are available for reuse less quickly
-than from RAM but faster than retrieving from the network again.
+than from memory but faster than retrieving from the network again.
The backing store implementation provides a key:value infrastructure
with a simple store, retrieve and invalidate interface.
-Generic filesystem backing store
---------------------------------
+The key is the object URL which by definition is unique for a source
+object. The value is the source object data *and* the associated
+metadata
+
+# Generic filesystem backing store
Although the backing store interface is fully pluggable a generic
implementation based on storing objects on the filesystem in a
@@ -34,13 +44,45 @@ As the backing store only holds cache data one should not expect a
great deal of effort to be expended converting formats (i.e. the cache
may simply be discarded).
-Layout version 1.1
-------------------
+## Layout version 2.02
+
+The version 2 layout stores cache entries in a hash map thus only uses
+memory proportional to the number of entries present removing the need
+for large fixed size indexes.
+
+The object identifier is generated from nsurl_hash() and data entries
+are stored in either a fixed size disc blocks or in separate files on disc.
+
+The file path if stored on disc must conform to the limitations of all
+the filesystems the cache can be placed upon.
+
+From http://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits the relevant subset is:
+ - path elements no longer than 8 characters
+ - acceptable characters are A-Z, 0-9
+ - short total path lengths (255 or less)
+ - no more than 77 entries per directory (6bits worth)
+
+The short total path lengths mean the encoding must represent as much
+data as possible in the least number of characters.
+
+To achieve all these goals we use RFC4648 base32 encoding which packs
+five bits into each character of the filename. By splitting the 32bit
+identifier using six bits per directory level only five levels of
+directory are required with a maximum of 64 entries per
+directory. This requires a total path length of 22 bytes (including
+directory separators) BA/BB/BC/BD/BE/ABCDEFG
+
+Files that are under 8KiB in size are stored in "small block files"
+these are pre allocated 8 Megabyte files on disc in which remove the
+need to have many, many small files stored on disc at the expensie of
+a some amount of wasted space for files that are smaller than the 8K
+block size.
-An object has an identifier value generated from the URL (NetSurf
-backing stores uses the URL as the unique key). The value used is
-obtained using nsurl_hash() which is currently a 32 bit FNV so is
-directly usable.
+## Layout version 1.1
+
+An object has an identifier value generated from the URL (the unique
+key). The value used is obtained using nsurl_hash() which is currently
+a 32 bit FNV so is directly usable.
This identifier is adequate to ensure the collision rate for the
hashed URL values (a collision for every 2^16 URLs added) is
@@ -83,26 +125,23 @@ resulting in the data being stored in a file path of
An address of 0x00040001 encodes to BAAB and a file path of
"/store/prefix/m/B/A/A/BAABAAA"
-Version 1.0
------------
+## Layout Version 1.0
-The version 1 layout was identical to the 1.1 except base64url
+The version 1.0 layout was identical to the 1.1 except base64url
encoding was used, this proved problematic as some systems filesystems
were case insensitive so upper and lower case letters collided.
There is no upgrade provision from the previous version simply delete
the cache directory.
-Control files
-~~~~~~~~~~~~~
+## Control files
+
+### control
-control
-+++++++
A control file is used to hold a list of values describing how the
other files in the backing store should be used.
-entries
-+++++++
+### entries
this file contains a table of entries describing the files held on the
filesystem.
@@ -110,26 +149,18 @@ filesystem.
Each control file table entry is 28 bytes and consists of
- signed 64 bit value for last use time
-
- 32bit full url hash allowing for index reconstruction and
additional collision detection. Also the possibility of increasing
the ADDRESS_LENGTH although this would require renaming all the
existing files in the cache and is not currently implemented.
-
- unsigned 32bit length for data
-
- unsigned 32bit length for metadata
-
- unsigned 16bit value for number of times used.
-
- unsigned 16bit value for flags
-
- unsigned 16bit value for data block index (unused)
-
- unsigned 16bit value for metatdata block index (unused)
-Address to entry index
-~~~~~~~~~~~~~~~~~~~~~~
+### Address to entry index
An entry index is held in RAM that allows looking up the address to
map to an entry in the control file.
@@ -137,14 +168,13 @@ map to an entry in the control file.
The index is the only data structure whose size is directly dependant
on the length of the hash specifically:
-(2 ^ (ADDRESS_BITS - 3)) * ENTRY_BITS) in bytes
+ (2 ^ (ADDRESS_BITS - 3)) * ENTRY_BITS) in bytes
where ADDRESS_BITS is how long the address is in bits and ENTRY_BITS
is how many entries the control file (and hence the while
cache) may hold.
-RISCOS values
-+++++++++++++
+## RISCOS values
By limiting the ENTRY_BITS size to 14 (16,384 entries) the entries
list is limited to 448kilobytes.
@@ -159,8 +189,7 @@ address) to happen roughly for every 2 ^ (ADDRESS_BITS / 2) = 2 ^ 9 =
512 objects stored. This roughly translates to a cache miss due to
collision every ten pages navigated to.
-Larger systems
-++++++++++++++
+## Larger systems
In general ENTRY_BITS set to 16 as this limits the store to 65536
objects which given the average size of an object at 8 kilobytes
@@ -170,11 +199,9 @@ For larger systems e.g. those using GTK frontend we would most likely
select ADDRESS_BITS as 22 resulting in a collision every 2048 objects
but the index using some 8 Megabytes
-Typical values
---------------
+## Typical values
-Example 1
-~~~~~~~~~
+### Example 1
For a store with 1034 objects generated from a random navigation of
pages linked from the about:welcome page.
@@ -185,8 +212,7 @@ majority of the storage is used to hold the URLs and headers.
Data total size is 9180475 bytes a mean of 8879 bytes 1648726 in the
largest 10 entries which if excluded gives 7355 bytes average size
-Example 2
-~~~~~~~~~
+### Example 2
355 pages navigated in 80 minutes from about:welcome page and a
handful of additional sites (google image search and reddit)
@@ -201,4 +227,4 @@ with one single 5,000,811 byte gif
data totals without gif is 28,127,020 mean 13,945
-[1] http://tools.ietf.org/html/rfc2616#section-13 \ No newline at end of file
+[1] http://tools.ietf.org/html/rfc2616#section-13
diff --git a/docs/unit-testing b/docs/unit-testing.md
index 49d82ed81..f7adc82c7 100644
--- a/docs/unit-testing
+++ b/docs/unit-testing.md
@@ -1,8 +1,9 @@
NetSurf Unit Testing
====================
-Overview
---------
+[TOC]
+
+# Overview
NetSurf has unit tests integrated in the test directory. These tests
use the check unit test framework for C [1].
@@ -13,8 +14,7 @@ programs although the framework does not madate this and some test
programs contain more than one suite.
-Execution
----------
+# Execution
The test programs are executed by using the standard "test" target
from the top level make invocation. The "coverage" target additionally
@@ -25,8 +25,7 @@ The check library must be installed to run the tests and the CI system
automatically executes all enabled tests and generates coverage
reports for each commit.
-Adding tests
-------------
+# Adding tests
The test/Makefile defines each indiviadual test program that should be
built and executed in the TESTS variable.
@@ -39,128 +38,128 @@ Each individual test program requires a main function which creates
one (or more) suites. The suites are added to a test runner and then
executed and the results reported.
-int main(int argc, char **argv)
-{
- int number_failed;
- SRunner *sr;
-
- sr = srunner_create(foo_suite_create());
- //srunner_add_suite(sr, bar_suite_create());
-
- srunner_run_all(sr, CK_ENV);
-
- number_failed = srunner_ntests_failed(sr);
- srunner_free(sr);
-
- return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
-}
+ int main(int argc, char **argv)
+ {
+ int number_failed;
+ SRunner *sr;
+
+ sr = srunner_create(foo_suite_create());
+ //srunner_add_suite(sr, bar_suite_create());
+
+ srunner_run_all(sr, CK_ENV);
+
+ number_failed = srunner_ntests_failed(sr);
+ srunner_free(sr);
+
+ return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
Suite creation is done with a sub function to logically split suite
code into sub modules. Each suite has test cases added to it.
-Suite *foo_suite_create(void)
-{
- Suite *s;
- s = suite_create("foo");
-
- suite_add_tcase(s, baz_case_create());
- suite_add_tcase(s, qux_case_create());
-
- return s;
-}
+ Suite *foo_suite_create(void)
+ {
+ Suite *s;
+ s = suite_create("foo");
+
+ suite_add_tcase(s, baz_case_create());
+ suite_add_tcase(s, qux_case_create());
+
+ return s;
+ }
Test cases include the actual tests to be performed within each case.
-TCase *baz_case_create(void)
-{
- TCase *tc;
- tc = tcase_create("Baz");
-
- tcase_add_test(tc, xxyz_test);
- tcase_add_test(tc, zzyx_test);
-
- return tc;
-}
+ TCase *baz_case_create(void)
+ {
+ TCase *tc;
+ tc = tcase_create("Baz");
+
+ tcase_add_test(tc, xxyz_test);
+ tcase_add_test(tc, zzyx_test);
+
+ return tc;
+ }
A test case may optionally have a fixture which is code that is
executed before and after each test case. Unchecked fixtures are
executed once before the test process forks for each test whereas
checked fixtures are executed for each and every test.
-static void fixture_setup(void)
-{
-}
-
-static void fixture_teardown(void)
-{
-}
-
-TCase *qux_case_create(void)
-{
- TCase *tc;
-
- /* Matching entry tests */
- tc = tcase_create("Match");
-
- tcase_add_checked_fixture(tc,
- fixture_setup,
- fixture_teardown);
-
- tcase_add_test(tc, zzz_test);
-
- return tc;
-}
+ static void fixture_setup(void)
+ {
+ }
+
+ static void fixture_teardown(void)
+ {
+ }
+
+ TCase *qux_case_create(void)
+ {
+ TCase *tc;
+
+ /* Matching entry tests */
+ tc = tcase_create("Match");
+
+ tcase_add_checked_fixture(tc,
+ fixture_setup,
+ fixture_teardown);
+
+ tcase_add_test(tc, zzz_test);
+
+ return tc;
+ }
Additionally test cases can contain tests executed in a loop. The test
recives a single integer as a parameter named _i which iterates
between values specified in the case setup.
-TCase *baz_case_create(void)
-{
- TCase *tc;
- tc = tcase_create("Baz");
-
- tcase_add_loop_test(tc, looping_test, 0, 5);
-
- return tc;
-}
+ TCase *baz_case_create(void)
+ {
+ TCase *tc;
+ tc = tcase_create("Baz");
+
+ tcase_add_loop_test(tc, looping_test, 0, 5);
+
+ return tc;
+ }
It is also possible to create tests which will generate a signal. The
most commonly used of these is to check asserts in API calls.
-TCase *baz_case_create(void)
-{
- TCase *tc;
- tc = tcase_create("Baz");
-
- tcase_add_test_raise_signal(tc, assert_test, 6);
-
- return tc;
-}
+ TCase *baz_case_create(void)
+ {
+ TCase *tc;
+ tc = tcase_create("Baz");
+
+ tcase_add_test_raise_signal(tc, assert_test, 6);
+
+ return tc;
+ }
Actual test code is self contained in a function which uses the
ck_assert macros to test results. The check framework requires each
test to use the START_TEST and END_TEST macros when definig them.
-/**
- * url access leaf test
- */
-START_TEST(nsurl_access_leaf_test)
-{
- nserror err;
- nsurl *res_url;
- const struct test_triplets *tst = &access_tests[_i];
-
- /* not testing create, this should always succeed */
- err = nsurl_create(tst->test1, &res_url);
- ck_assert(err == NSERROR_OK);
-
- ck_assert_str_eq(nsurl_access_leaf(res_url), tst->res);
-
- nsurl_unref(res_url);
-}
-END_TEST
+ /**
+ * url access leaf test
+ */
+ START_TEST(nsurl_access_leaf_test)
+ {
+ nserror err;
+ nsurl *res_url;
+ const struct test_triplets *tst = &access_tests[_i];
+
+ /* not testing create, this should always succeed */
+ err = nsurl_create(tst->test1, &res_url);
+ ck_assert(err == NSERROR_OK);
+
+ ck_assert_str_eq(nsurl_access_leaf(res_url), tst->res);
+
+ nsurl_unref(res_url);
+ }
+ END_TEST
[1] https://libcheck.github.io/check/
diff --git a/docs/user-interface.md b/docs/user-interface.md
new file mode 100644
index 000000000..49ca7a1ed
--- /dev/null
+++ b/docs/user-interface.md
@@ -0,0 +1,61 @@
+User Interface
+==============
+
+[TOC]
+
+Netsurf is divided into a series of frontends which provide a user
+interface around common core functionality. Each frontend is a
+distinct implementation for a specific GUI toolkit.
+
+Because of this the user interface has different features in
+each frontend allowing the browser to be a native application.
+
+# Frontends
+
+As GUI toolkits are often applicable to a single Operating
+System (OS) some frontends are named for their OS instead of the
+toolkit e.g. RISC OS WIMP frontend is named riscos and the Windows
+win32 frontend is named windows.
+
+## amiga
+
+Frontend specific to the amiga
+
+## atari
+
+Frontend specific to the atari
+
+## beos
+
+Frontend specific to the Haiku OS
+
+## framebuffer
+
+There is a basic user guide for the [framebuffer](docs/using-framebuffer.md)
+
+## gtk
+
+Frontend that uses the GTK+2 or GTK+3 toolkit
+
+## monkey
+
+This is the internal unit test frontend.
+
+There is a basic user guide [monkey](docs/using-monkey.md)
+
+## riscos
+
+Frontend for the RISC OS WIMP toolkit.
+
+## windows
+
+Frontend which uses the Microsodt win32 GDI toolkit.
+
+# User configuration
+
+The behaviour of the browser can be changed from the defaults with a
+configuration file. The [core user options](docs/netsurf-options.md)
+of the browser are common to all versions and are augmented by each
+frontend in a specific manner.
+
+
diff --git a/docs/using-framebuffer.md b/docs/using-framebuffer.md
index 3af8f983f..98a100a1f 100644
--- a/docs/using-framebuffer.md
+++ b/docs/using-framebuffer.md
@@ -62,6 +62,56 @@ Overview
the GTK frontend is a vastly superior choice. The framebuffer
frontend will appear exceptionally limited on such capable systems.
+Running
+=======
+
+ The framebuffer frontend is executed with the nsfb command. This
+ command takes parameters to control the operation of the
+ browser. The 'Configuring' section describes the available options
+ in detail.
+
+ The selection of the display surface is controlled with the -f
+ switch, the available display surfaces can be shown by passing '?'
+ as the parameter.
+
+ $ ./nsfb -f ?
+ ./nsfb: Valid surface names are:
+ ./nsfb: ram
+ ./nsfb: sdl
+ ./nsfb: x
+ ./nsfb: vnc
+ ./nsfb: wld
+
+ The avilable surfaces are dependant on what was compiled into the
+ nsfb library.
+
+ Common issues
+ -------------
+
+ - The browser appears to "hang" with no output
+
+ This is often cause by the unintentianal selection of the debug
+ "ram" surface. In this case the browser is in fact operating but
+ the output is being rendered to a memory buffer. the solution is
+ to explictly select the intended surface using the -f switch
+
+ - The displayed browser interface has no visible icons
+
+ This is generally because the necessary resources are not availale
+ on the resource search path.
+
+ - There is no displayed text.
+
+ The font configuration is incorrect either it has been compiled
+ wrongly or the configured freetype font is not available
+
+ - The browser messages are "bad"
+
+ If the browser messages are being emited as unrecognisable short
+ text symbols or in the wrong language it is likely the Messages
+ file could not be located. This can be confirmed by looking for
+ the text "Message translations failed to load" in the verbose log
+ output (run the browser with the -v switch)
Configuring
===========
@@ -72,11 +122,11 @@ Configuring
for details.
As with any NetSurf frontend run-time configuration is read from a
- "Choices" file. This file is a simple key:value list and is located
- in "${HOME}/.netsurf/Choices".
+ "Choices" file. This file is a simple key:value list and by default
+ is located in "${HOME}/.netsurf/Choices".
- The standard values supported by the NetSurf core are documented in
- the Options document. In addition to these there are a number of
+ The standard [core user options](docs/netsurf-options.md) are
+ available. In addition to the core options there are a number of
values to control specific aspects of the framebuffer version.
Toolkit Options
diff --git a/docs/using-monkey.md b/docs/using-monkey.md
index d6082bda9..d031a77bb 100644
--- a/docs/using-monkey.md
+++ b/docs/using-monkey.md
@@ -5,6 +5,13 @@ This document provides usage instructions for the Monkey version of NetSurf.
Monkey NetSurf has been tested on Ubuntu and Debian.
+Automated testing
+-----------------
+
+If you want to run the monkey_driver.py or monkey-see-monkey-do tools then
+you will need python3 and pyyaml installed. The latter also needs internet
+access to test.netsurf-browser.org to acquire test data.
+
Overview
--------
@@ -49,7 +56,7 @@ browser windows are prefixed by `WINDOW`.
* `WINDOW`: Anything about browser windows in general
-* `DOWNLOAD_WINDOW`: Anything about the download window.
+* `DOWNLOAD`: Anything about the download window.
* `SSLCERT`: Anything about SSL certificates
@@ -105,6 +112,11 @@ Commands
Cause the given browser window to visit the given URL.
Optionally you can give a referrer URL to also use (simulating
a click in the browser on a link).
+ Minimally you can expect throbber stop response.
+
+* `WINDOW STOP` _%id%_
+
+ Cause a browser window to stop any in progress navigatoipn.
Minimally you can expect throbber, url etc responses.
* `WINDOW REDRAW` _%id%_ [_%num% %num% %num% %num%_]
@@ -118,11 +130,65 @@ Commands
Minimally you can expect redraw start/stop messages and you
can likely expect some number of `PLOT` results.
-* `WINDOW RELOAD` _%id%_
+* `WINDOW RELOAD` _%id%_ [all]
Cause a browser window to reload its current content.
Expect responses similar to a GO command.
+* `WINDOW EXEC WIN` _%id%_ _%str%_
+
+ Cause a browser window to execute some javascript. It won't
+ work if the window doesn't have a *finished* HTML content.
+
+ This will send a `JS` message back.
+
+* `WINDOW CLICK WIN` _%id%_ `X` _%num%_ `Y` _%num%_ `BUTTON` _%str%_ `KIND` _%str%_
+
+ Cause a browser window to experience a mouse click. The coordinates should
+ be in plot coordinates, so you can use redraw plot commands to find things
+ and then click on them. The `BUTTON` value should be one of `LEFT`
+ or `RIGHT`, and the `KIND` is `SINGLE`, `DOUBLE`, or `TRIPLE`.
+
+ This command will not output anything itself, it's expected only to do things
+ as a result of the click (e.g. navigating when clicking a link).
+
+### Login commands
+
+* `LOGIN USERNAME` _%id%_ _%str%_
+
+ Set the username for the login
+
+* `LOGIN PASSWORD` _%id%_ _%str%_
+
+ Set the password for the login
+
+* `LOGIN GO` _%id%_
+
+ Cause a login to proceed using the set credentials
+
+ This will send a `DESTROY` message back.
+
+* `LOGIN DESTROY` _%id%_
+
+ Cause a login to fail
+
+ This will send a `DESTROY` message back.
+
+
+### SSL certificate commands
+
+* `SSLCERT GO` _%id%_
+
+ Cause a ssl certificate to be accepted and fetch to proceed.
+
+ This will send a `DESTROY` message back.
+
+* `SSLCERT DESTROY` _%id%_
+
+ Cause a ssl certificate to be rejected and fetch to fail
+
+ This will send a `DESTROY` message back.
+
Responses
---------
@@ -302,44 +368,82 @@ Responses
The core wraps redraws in these messages. Thus `PLOT` responses can
be allocated to the appropriate window.
+* `WINDOW JS WIN` _%id%_ `RET` `TRUE`/`FALSE`
+
+ Here `FALSE` indicates that some issue prevented the injection of
+ the script.
+
+* `WINDOW CONSOLE_LOG WIN` _%id%_ `SOURCE` _%source%_ _%foldable%_ _%level%_ _%str%_
+
+ Here, _%source%_ will be one of: `client-input`, `scripting-error`, or
+ `scripting-console`. _%foldable%_ will be one of `FOLDABLE` or
+ `NOT-FOLDABLE`. _%level%_ will be one of `LOG`, `INFO`, `WARN`, or
+ `ERROR`. The terminal string will be the log message.
+
### Download window messages
-* `DOWNLOAD_WINDOW CREATE DWIN` _%id%_ `WIN` _%id%_
+* `DOWNLOAD CREATE DWIN` _%id%_ `WIN` _%id%_
The core asked Monkey to create a download window owned by the
given browser window.
-* `DOWNLOAD_WINDOW DATA DWIN` _%id%_ `SIZE` _%n%_ `DATA` _%str%_
+* `DOWNLOAD DATA DWIN` _%id%_ `SIZE` _%n%_ `DATA` _%str%_
The core asked Monkey to update the named download window with
the given byte size and data string.
-* `DOWNLOAD_WINDOW ERROR DWIN` _%id%_ `ERROR` _%str%_
+* `DOWNLOAD ERROR DWIN` _%id%_ `ERROR` _%str%_
The core asked Monkey to update the named download window with
the given error message.
-* `DOWNLOAD_WINDOW DONE DWIN` _%id%_
+* `DOWNLOAD DONE DWIN` _%id%_
The core asked Monkey to destroy the named download window.
### SSL Certificate messages
-* `SSLCERT VERIFY CERT` _%id%_ `URL` _%url%_
+* `SSLCERT VERIFY CWIN` _%id%_ `URL` _%url%_
The core asked Monkey to say whether or not a given SSL
certificate is OK.
-> TODO: Implement the rest of the SSL certificat verification behaviour
+* `LOGIN DESTROY CWIN` _%id%_
+
+ The given certificate window has been destroyed and should no longer be sent
+ commands otherwise undefined behaviour may ensue.
### 401 Login messages
-* `401LOGIN OPEN M4` _%id%_ `URL` _%url%_ `REALM` _%str%_
+* `LOGIN OPEN LWIN` _%id%_ `URL` _%url%_
+
+ The core asked Monkey to ask for identification for the given URL.
+
+ This will be *immediately* followed by:
+
+* `LOGIN USER LWIN` _%id%_ `STR` _%str%_
+
+ The given login window has a default username of the given string
+
+ This will be *immediately* followed by:
+
+* `LOGIN PASS LWIN` _%id%_ `STR` _%str%_
+
+ The given login window has a default password of the given string
+
+ This will be *immediately* followed by:
+
+* `LOGIN REALM LWIN` _%id%_ `STR` _%str%_
+
+ The given login window has a realm of the given string
+
+ Subsequent to this message, the user of monkey is at liberty to issue
+ `LOGIN` commands to control the response of the `401LOGIN` process.
- The core asked Monkey to ask for identification for the named
- realm at the given URL.
+* `LOGIN DESTROY LWIN` _%id%_
-> TODO: Implement support to control the 401LOGIN process
+ The given login window has been destroyed and should no longer be sent
+ commands otherwise undefined behaviour may ensue.
### Plotter messages
diff --git a/frontends/Makefile.hts b/frontends/Makefile.hts
new file mode 100644
index 000000000..b5af240f1
--- /dev/null
+++ b/frontends/Makefile.hts
@@ -0,0 +1,122 @@
+# -*- mode: makefile-gmake -*-
+##
+## determine the HOST TARGET and SUBTARGET
+##
+
+# Determine host type
+# NOTE: HOST determination on RISC OS could fail because of missing bug fixes
+# in UnixLib which only got addressed in UnixLib 5 / GCCSDK 4.
+# When you don't have 'uname' available, you will see:
+# File 'uname' not found
+# When you do and using a 'uname' compiled with a buggy UnixLib, you
+# will see the following printed on screen:
+# RISC OS
+# In both cases HOST make variable is empty and we recover from that by
+# assuming we're building on RISC OS.
+# In case you don't see anything printed (including the warning), you
+# have an up-to-date RISC OS build system. ;-)
+HOST := $(shell uname -s)
+
+# Sanitise host
+# TODO: Ideally, we want the equivalent of s/[^A-Za-z0-9]/_/g here
+HOST := $(subst .,_,$(subst -,_,$(subst /,_,$(HOST))))
+
+ifeq ($(HOST),)
+ HOST := riscos
+ $(warning Build platform determination failed but that's a known problem for RISC OS so we're assuming a native RISC OS build.)
+else
+ ifeq ($(HOST),RISC OS)
+ # Fixup uname -s returning "RISC OS"
+ HOST := riscos
+ endif
+endif
+ifeq ($(HOST),riscos)
+ # Build happening on RO platform, default target is RO backend
+ ifeq ($(TARGET),)
+ TARGET := riscos
+ endif
+endif
+
+ifeq ($(HOST),BeOS)
+ HOST := beos
+endif
+ifeq ($(HOST),Haiku)
+ # Haiku implements the BeOS API
+ HOST := beos
+endif
+ifeq ($(HOST),beos)
+ # Build happening on BeOS platform, default target is BeOS backend
+ ifeq ($(TARGET),)
+ TARGET := beos
+ endif
+ ifeq ($(TARGET),haiku)
+ override TARGET := beos
+ endif
+endif
+
+ifeq ($(HOST),AmigaOS)
+ HOST := amiga
+ ifeq ($(TARGET),)
+ TARGET := amiga
+ endif
+endif
+
+ifeq ($(HOST),FreeMiNT)
+ HOST := mint
+endif
+ifeq ($(HOST),mint)
+ ifeq ($(TARGET),)
+ TARGET := atari
+ endif
+endif
+
+ifeq ($(findstring MINGW,$(HOST)),MINGW)
+ # MSYS' uname reports the likes of "MINGW32_NT-6.0"
+ HOST := windows
+endif
+ifeq ($(HOST),windows)
+ ifeq ($(TARGET),)
+ TARGET := windows
+ endif
+endif
+
+# Setup (sub)targets
+
+# empty default sub target
+SUBTARGET=
+
+# Default target is GTK 3 backend
+ifeq ($(TARGET),)
+ override TARGET := gtk
+ SUBTARGET = 3
+else
+ ifeq ($(TARGET),gtk)
+ # unspecified gtk is gtk3
+ SUBTARGET = 3
+ else
+ ifeq ($(TARGET),gtk3)
+ # gtk3 is gtk target with subtarget of 3
+ override TARGET := gtk
+ SUBTARGET = 3
+ else
+ ifeq ($(TARGET),gtk2)
+ # gtk2 is gtk target with subtarget of 2
+ override TARGET := gtk
+ SUBTARGET = 2
+ else
+ ifeq ($(TARGET),amigaos3)
+ override TARGET := amiga
+ SUBTARGET = os3
+ endif
+ endif
+ endif
+ endif
+endif
+
+# valid values for the TARGET
+VLDTARGET := amiga atari beos framebuffer gtk monkey riscos windows
+
+# Check for valid TARGET
+ifeq ($(filter $(VLDTARGET),$(TARGET)),)
+ $(error Unknown TARGET "$(TARGET)", Must be one of $(VLDTARGET))
+endif
diff --git a/frontends/amiga/Makefile b/frontends/amiga/Makefile
index ac05d1bf0..f537a1163 100644
--- a/frontends/amiga/Makefile
+++ b/frontends/amiga/Makefile
@@ -12,20 +12,27 @@ endif
$(eval $(call feature_enabled,AMIGA_ICON,-DWITH_AMIGA_ICON,,Amiga icon))
$(eval $(call feature_enabled,AMIGA_DATATYPES,-DWITH_AMIGA_DATATYPES,,DataTypes))
+$(eval $(call feature_enabled,AMISSL,-DWITH_AMISSL -DWITH_OPENSSL -D__NO_NET_API -D__NO_NETINCLUDE_ERRNO -I$(GCCSDK_INSTALL_ENV)/netinclude,-lamisslauto,AmiSSL))
CFLAGS += -I$(GCCSDK_INSTALL_ENV)/include
CFLAGS += $(shell $(PKG_CONFIG) --cflags tre)
-LDFLAGS += $(shell $(PKG_CONFIG) --static --libs libcurl openssl)
+LDFLAGS += $(shell $(PKG_CONFIG) --static --libs libcurl)
LDFLAGS += $(shell $(PKG_CONFIG) --libs tre)
LDFLAGS += -L$(GCCSDK_INSTALL_ENV)/lib
LDFLAGS += -lpbl -liconv
+ifeq ($(NETSURF_USE_OPENSSL),YES)
+ LDFLAGS += $(shell $(PKG_CONFIG) --static --libs openssl)
+endif
+
ifeq ($(SUBTARGET),os3)
LDFLAGS += -lamiga -lm
endif
+COMMON_WARNFLAGS += -Wno-cast-align
+
EXETARGET := NetSurf
# The filter and target for split messages
@@ -37,16 +44,16 @@ MESSAGES_FILTER=ami
# sources purely for the Amiga build
S_FRONTEND := gui.c history.c hotlist.c schedule.c file.c \
- misc.c bitmap.c font.c filetype.c utf8.c login.c memory.c \
+ misc.c bitmap.c font.c filetype.c utf8.c memory.c \
plotters.c object.c menu.c save_pdf.c arexx.c version.c \
cookies.c ctxmenu.c clipboard.c help.c font_scan.c \
launch.c search.c history_local.c download.c iff_dr2d.c \
- sslcert.c gui_options.c print.c theme.c drag.c icon.c libs.c \
+ gui_options.c print.c theme.c drag.c icon.c libs.c \
datatypes.c dt_picture.c dt_anim.c dt_sound.c plugin_hack.c \
stringview/stringview.c stringview/urlhistory.c rtg.c \
agclass/amigaguide_class.c os3support.c font_diskfont.c \
selectmenu.c hash/xxhash.c font_cache.c font_bullet.c \
- nsoption.c corewindow.c gui_menu.c
+ nsoption.c corewindow.c gui_menu.c pageinfo.c
# This is the final source build list
# Note this is deliberately *not* expanded here as common and image
@@ -73,7 +80,7 @@ AMIGA_DISTRIBUTION_FILES := $(FRONTEND_SOURCE_DIR)/dist/*
AMIGA_PKG_DIR := $(FRONTEND_SOURCE_DIR)/pkg
AMIGA_INSTALL_TARGET_DIR := NetSurf_Amiga
-netsurf.lha: $(EXETARGET)
+netsurf.lha: $(EXETARGET) $(POSTEXES)
$(VQ)echo Creating netsurf.lha
$(Q)rm -rf $(AMIGA_INSTALL_TARGET_DIR)
$(Q)$(MKDIR) -p $(AMIGA_INSTALL_TARGET_DIR)/NetSurf
@@ -98,5 +105,5 @@ netsurf.lha: $(EXETARGET)
$(Q)cp -p $(AMIGA_PKG_DIR)/netsurf.readme.info $(AMIGA_INSTALL_TARGET_DIR)/NetSurf
endif
$(Q)cd $(AMIGA_INSTALL_TARGET_DIR); \
- lha a netsurf.lha NetSurf NetSurf.info AutoInstall
+ lha ao6 netsurf.lha NetSurf NetSurf.info AutoInstall
diff --git a/frontends/amiga/Makefile.defaults b/frontends/amiga/Makefile.defaults
index f19d6e394..25e1f42e4 100644
--- a/frontends/amiga/Makefile.defaults
+++ b/frontends/amiga/Makefile.defaults
@@ -6,6 +6,12 @@
# Valid options: YES, NO
NETSURF_USE_LIBICONV_PLUG := NO
+# Use AmiSSL for secure connections.
+# Either this or NETSURF_USE_OPENSSL should be specified, not both.
+# libcurl must have been built against the same library.
+# Valid options: YES, NO
+NETSURF_USE_AMISSL := NO
+
# Enable NetSurf's use of librosprite for displaying RISC OS Sprites
# Valid options: YES, NO, AUTO
NETSURF_USE_ROSPRITE := NO
@@ -28,5 +34,14 @@ NETSURF_USE_NSSVG := YES
NETSURF_FS_BACKING_STORE := YES
# Optimisation levels
-CFLAGS += -fomit-frame-pointer -gstabs
+CFLAGS += -fomit-frame-pointer
+
+# Target-specific
+ifeq ($(SUBTARGET),os3)
+ NETSURF_USE_OPENSSL := NO
+ NETSURF_USE_AMISSL := YES
+ NETSURF_FS_BACKING_STORE := YES
+else
+ CFLAGS += -gstabs
+endif
diff --git a/frontends/amiga/Makefile.tools b/frontends/amiga/Makefile.tools
new file mode 100644
index 000000000..c16928783
--- /dev/null
+++ b/frontends/amiga/Makefile.tools
@@ -0,0 +1,21 @@
+# -*- mode: makefile-gmake -*-
+##
+## amiga target tool setup
+##
+
+ifeq ($(findstring amiga,$(HOST)),amiga)
+ # building for amiga on amiga
+ PKG_CONFIG := pkg-config
+else
+ ifeq ($(SUBTARGET),os3)
+ GCCSDK_INSTALL_ENV ?= /opt/netsurf/m68k-unknown-amigaos/env
+ GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/m68k-unknown-amigaos/cross/bin
+ else
+ GCCSDK_INSTALL_ENV ?= /opt/netsurf/ppc-amigaos/env
+ GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/ppc-amigaos/cross/bin
+ endif
+
+ CC := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc)
+
+ PKG_CONFIG := PKG_CONFIG_LIBDIR="$(GCCSDK_INSTALL_ENV)/lib/pkgconfig" pkg-config
+endif
diff --git a/frontends/amiga/arexx.c b/frontends/amiga/arexx.c
index 9484ee92b..243e927f8 100644
--- a/frontends/amiga/arexx.c
+++ b/frontends/amiga/arexx.c
@@ -69,7 +69,8 @@ enum
RX_ACTIVE,
RX_CLOSE,
RX_HOTLIST,
- RX_SLABSTATS
+ RX_SLABSTATS,
+ RX_EXEC
};
static Object *arexx_obj = NULL;
@@ -98,6 +99,7 @@ RXHOOKF(rx_active);
RXHOOKF(rx_close);
RXHOOKF(rx_hotlist);
RXHOOKF(rx_slabstats);
+RXHOOKF(rx_exec);
STATIC struct ARexxCmd Commands[] =
{
@@ -118,6 +120,7 @@ STATIC struct ARexxCmd Commands[] =
{"CLOSE", RX_CLOSE, rx_close, "W=WINDOW/K/N,T=TAB/K/N", 0, NULL, 0, 0, NULL },
{"HOTLIST", RX_HOTLIST, rx_hotlist, "A=ACTION/A", 0, NULL, 0, 0, NULL },
{"SLABSTATS", RX_SLABSTATS, rx_slabstats, "FILE", 0, NULL, 0, 0, NULL },
+ {"EXEC", RX_EXEC, rx_exec, "W=WINDOW/K/N,T=TAB/K/N,COMMAND/A/F", 0, NULL, 0, 0, NULL },
{ NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL }
};
@@ -191,9 +194,9 @@ static struct gui_window *ami_find_tab_gwin(struct gui_window_2 *gwin, int tab)
struct Node *ntab;
struct gui_window *gw;
- if((tab == 0) || (gwin->tabs == 0)) return gwin->gw;
+ if((tab == 0) || (ami_gui2_get_tabs(gwin) == 0)) return ami_gui2_get_gui_window(gwin);
- ctab = GetHead(&gwin->tab_list);
+ ctab = GetHead(ami_gui2_get_tab_list(gwin));
do
{
@@ -215,9 +218,9 @@ static int ami_find_tab_bw(struct gui_window_2 *gwin, struct browser_window *bw)
struct Node *ntab;
struct gui_window *tgw = NULL;
- if((bw == NULL) || (gwin->tabs == 0)) return 1;
+ if((bw == NULL) || (ami_gui2_get_tabs(gwin) == 0)) return 1;
- ctab = GetHead(&gwin->tab_list);
+ ctab = GetHead(ami_gui2_get_tab_list(gwin));
do
{
@@ -226,7 +229,7 @@ static int ami_find_tab_bw(struct gui_window_2 *gwin, struct browser_window *bw)
GetClickTabNodeAttrs(ctab,
TNA_UserData, &tgw,
TAG_DONE);
- if(tgw->bw == bw) return tabs;
+ if(ami_gui_get_browser_window(tgw) == bw) return tabs;
} while((ctab=ntab));
return 0;
@@ -235,6 +238,7 @@ static int ami_find_tab_bw(struct gui_window_2 *gwin, struct browser_window *bw)
static struct gui_window *ami_find_tab(int window, int tab)
{
struct nsObject *node, *nnode;
+ struct MinList *window_list = ami_gui_get_window_list();
if(!IsMinListEmpty(window_list))
{
@@ -260,7 +264,7 @@ static struct gui_window *ami_find_tab(int window, int tab)
RXHOOKF(rx_open)
{
struct dlnode *dln;
- struct gui_window *gw = cur_gw;
+ struct gui_window *gw = ami_gui_get_active_gw();
nsurl *url;
cmd->ac_RC = 0;
@@ -281,8 +285,8 @@ RXHOOKF(rx_open)
dln->filename = strdup((char *)cmd->ac_ArgList[3]);
dln->node.ln_Name = strdup((char *)cmd->ac_ArgList[0]);
dln->node.ln_Type = NT_USER;
- AddTail(&gw->dllist, (struct Node *)dln);
- browser_window_navigate(gw->bw,
+ AddTail(ami_gui_get_download_list(gw), (struct Node *)dln);
+ browser_window_navigate(ami_gui_get_browser_window(gw),
url,
NULL,
BW_NAVIGATE_DOWNLOAD,
@@ -303,11 +307,11 @@ RXHOOKF(rx_open)
BW_CREATE_TAB,
url,
NULL,
- gw->bw,
+ ami_gui_get_browser_window(gw),
NULL);
if(cmd->ac_ArgList[6]) {
- ami_gui_switch_to_new_tab(gw->shared);
+ ami_gui_switch_to_new_tab(ami_gui_get_gui_window_2(gw));
}
}
}
@@ -323,7 +327,7 @@ RXHOOKF(rx_open)
{
if(gw)
{
- browser_window_navigate(gw->bw,
+ browser_window_navigate(ami_gui_get_browser_window(gw),
url,
NULL,
BW_NAVIGATE_HISTORY,
@@ -346,9 +350,7 @@ RXHOOKF(rx_open)
RXHOOKF(rx_save)
{
BPTR fh = 0;
- ULONG source_size;
- const char *source_data;
- struct gui_window *gw = cur_gw;
+ struct gui_window *gw = ami_gui_get_active_gw();
cmd->ac_RC = 0;
@@ -357,19 +359,23 @@ RXHOOKF(rx_save)
if(!gw) return;
- ami_set_pointer(gw->shared, GUI_POINTER_WAIT, false);
+ ami_set_pointer(ami_gui_get_gui_window_2(gw), GUI_POINTER_WAIT, false);
if((fh = FOpen((char *)cmd->ac_ArgList[0], MODE_NEWFILE, 0)))
{
- struct hlcache_handle *h = browser_window_get_content(gw->bw);
- if((source_data = content_get_source_data(h, &source_size)))
+ const uint8_t *source_data;
+ size_t source_size;
+ struct hlcache_handle *h = browser_window_get_content(ami_gui_get_browser_window(gw));
+ source_data = content_get_source_data(h, &source_size);
+ if (source_data != NULL) {
FWrite(fh, source_data, 1, source_size);
+ }
FClose(fh);
- SetComment((char *)cmd->ac_ArgList[0], nsurl_access(browser_window_get_url(gw->bw)));
+ SetComment((char *)cmd->ac_ArgList[0], nsurl_access(browser_window_access_url(ami_gui_get_browser_window(gw))));
}
- ami_reset_pointer(gw->shared);
+ ami_reset_pointer(ami_gui_get_gui_window_2(gw));
}
RXHOOKF(rx_quit)
@@ -381,21 +387,21 @@ RXHOOKF(rx_quit)
RXHOOKF(rx_tofront)
{
cmd->ac_RC = 0;
- ScreenToFront(scrn);
+ ScreenToFront(ami_gui_get_screen());
}
RXHOOKF(rx_geturl)
{
- struct gui_window *gw = cur_gw;
+ struct gui_window *gw = ami_gui_get_active_gw();
cmd->ac_RC = 0;
if((cmd->ac_ArgList[0]) && (cmd->ac_ArgList[1]))
gw = ami_find_tab(*(ULONG *)cmd->ac_ArgList[0], *(ULONG *)cmd->ac_ArgList[1]);
- if(gw && gw->bw)
+ if(gw && ami_gui_get_browser_window(gw))
{
- strcpy(result, nsurl_access(browser_window_get_url(gw->bw)));
+ strcpy(result, nsurl_access(browser_window_access_url(ami_gui_get_browser_window(gw))));
}
else
{
@@ -407,7 +413,7 @@ RXHOOKF(rx_geturl)
RXHOOKF(rx_gettitle)
{
- struct gui_window *gw = cur_gw;
+ struct gui_window *gw = ami_gui_get_active_gw();
cmd->ac_RC = 0;
@@ -416,10 +422,10 @@ RXHOOKF(rx_gettitle)
if(gw)
{
- if(gw->shared->tabs > 1)
- strcpy(result, gw->tabtitle);
+ if(ami_gui2_get_tabs(ami_gui_get_gui_window_2(gw)) > 1)
+ strcpy(result, ami_gui_get_tab_title(gw));
else
- strcpy(result, gw->shared->wintitle);
+ strcpy(result, ami_gui_get_win_title(gw));
}
else
{
@@ -513,32 +519,32 @@ RXHOOKF(rx_pubscreen)
RXHOOKF(rx_back)
{
- struct gui_window *gw = cur_gw;
+ struct gui_window *gw = ami_gui_get_active_gw();
cmd->ac_RC = 0;
if((cmd->ac_ArgList[0]) && (cmd->ac_ArgList[1]))
gw = ami_find_tab(*(ULONG *)cmd->ac_ArgList[0], *(ULONG *)cmd->ac_ArgList[1]);
- if(gw) ami_gui_history(gw->shared, true);
+ if(gw) ami_gui_history(ami_gui_get_gui_window_2(gw), true);
}
RXHOOKF(rx_forward)
{
- struct gui_window *gw = cur_gw;
+ struct gui_window *gw = ami_gui_get_active_gw();
cmd->ac_RC = 0;
if((cmd->ac_ArgList[0]) && (cmd->ac_ArgList[1]))
gw = ami_find_tab(*(ULONG *)cmd->ac_ArgList[0], *(ULONG *)cmd->ac_ArgList[1]);
- if(gw) ami_gui_history(gw->shared, false);
+ if(gw) ami_gui_history(ami_gui_get_gui_window_2(gw), false);
}
RXHOOKF(rx_home)
{
- struct gui_window *gw = cur_gw;
+ struct gui_window *gw = ami_gui_get_active_gw();
nsurl *url;
cmd->ac_RC = 0;
@@ -551,7 +557,7 @@ RXHOOKF(rx_home)
if (nsurl_create(nsoption_charp(homepage_url), &url) != NSERROR_OK) {
amiga_warn_user("NoMemory", 0);
} else {
- browser_window_navigate(gw->bw,
+ browser_window_navigate(ami_gui_get_browser_window(gw),
url,
NULL,
BW_NAVIGATE_HISTORY,
@@ -564,7 +570,7 @@ RXHOOKF(rx_home)
RXHOOKF(rx_reload)
{
- struct gui_window *gw = cur_gw;
+ struct gui_window *gw = ami_gui_get_active_gw();
cmd->ac_RC = 0;
@@ -575,11 +581,11 @@ RXHOOKF(rx_reload)
{
if(cmd->ac_ArgList[0]) /* FORCE */
{
- browser_window_reload(gw->bw, true);
+ browser_window_reload(ami_gui_get_browser_window(gw), true);
}
else
{
- browser_window_reload(gw->bw, false);
+ browser_window_reload(ami_gui_get_browser_window(gw), false);
}
}
}
@@ -602,9 +608,10 @@ RXHOOKF(rx_windows)
RXHOOKF(rx_active)
{
int window = 0, tab = 0;
- struct gui_window *gw = cur_gw;
+ struct gui_window *gw = ami_gui_get_active_gw();
struct nsObject *node, *nnode;
struct gui_window_2 *gwin = NULL;
+ struct MinList *window_list = ami_gui_get_window_list();
cmd->ac_RC = 0;
@@ -623,7 +630,7 @@ RXHOOKF(rx_active)
if(node->Type == AMINS_WINDOW)
{
windows++;
- if(gwin->gw == gw)
+ if(IS_CURRENT_GW(gwin,gw))
{
window = windows;
break;
@@ -634,7 +641,7 @@ RXHOOKF(rx_active)
if(cmd->ac_ArgList[0])
{
- tab = ami_find_tab_bw(gwin, gw->bw);
+ tab = ami_find_tab_bw(gwin, ami_gui_get_browser_window(gw));
}
if(cmd->ac_ArgList[0]) sprintf(result, "%d", tab);
@@ -644,7 +651,7 @@ RXHOOKF(rx_active)
RXHOOKF(rx_close)
{
- struct gui_window *gw = cur_gw;
+ struct gui_window *gw = ami_gui_get_active_gw();
cmd->ac_RC = 0;
@@ -652,11 +659,11 @@ RXHOOKF(rx_close)
gw = ami_find_tab(*(ULONG *)cmd->ac_ArgList[0], *(ULONG *)cmd->ac_ArgList[1]);
else if(cmd->ac_ArgList[0])
{
- ami_gui_close_window(gw->shared);
+ ami_gui_close_window(ami_gui_get_gui_window_2(gw));
return;
}
- if(gw) browser_window_destroy(gw->bw);
+ if(gw) browser_window_destroy(ami_gui_get_browser_window(gw));
}
RXHOOKF(rx_hotlist)
@@ -670,6 +677,33 @@ RXHOOKF(rx_hotlist)
}
}
+RXHOOKF(rx_exec)
+{
+ struct gui_window *gw = ami_gui_get_active_gw();
+ bool res = false;
+
+ if(nsoption_bool(arexx_allow_exec) == false) {
+ cmd->ac_RC = RETURN_FAIL;
+ return;
+ }
+
+ if((cmd->ac_ArgList[0]) && (cmd->ac_ArgList[1]))
+ gw = ami_find_tab(*(ULONG *)cmd->ac_ArgList[0], *(ULONG *)cmd->ac_ArgList[1]);
+
+ if(gw) {
+ NSLOG(netsurf, WARNING, "Executing js: %s", (char *)cmd->ac_ArgList[2]);
+ res = browser_window_exec(ami_gui_get_browser_window(gw),
+ (char *)cmd->ac_ArgList[2], strlen((char *)cmd->ac_ArgList[2]));
+ }
+
+ if(res == false) {
+ cmd->ac_RC = RETURN_ERROR;
+ } else {
+ cmd->ac_RC = RETURN_OK;
+ }
+
+}
+
RXHOOKF(rx_slabstats)
{
#ifndef __amigaos4__
diff --git a/frontends/amiga/bitmap.c b/frontends/amiga/bitmap.c
index 0fde677ae..e8534a395 100644
--- a/frontends/amiga/bitmap.c
+++ b/frontends/amiga/bitmap.c
@@ -108,7 +108,7 @@ static APTR pool_bitmap = NULL;
static bool guigfx_warned = false;
/* exported function documented in amiga/bitmap.h */
-void *amiga_bitmap_create(int width, int height, unsigned int state)
+void *amiga_bitmap_create(int width, int height, enum gui_bitmap_flags flags)
{
struct bitmap *bitmap;
@@ -139,8 +139,7 @@ void *amiga_bitmap_create(int width, int height, unsigned int state)
bitmap->width = width;
bitmap->height = height;
- if(state & BITMAP_OPAQUE) bitmap->opaque = true;
- else bitmap->opaque = false;
+ bitmap->opaque = (flags & BITMAP_OPAQUE) == BITMAP_OPAQUE;
bitmap->nativebm = NULL;
bitmap->nativebmwidth = 0;
@@ -307,25 +306,6 @@ void amiga_bitmap_set_opaque(void *bitmap, bool opaque)
/* exported function documented in amiga/bitmap.h */
-bool amiga_bitmap_test_opaque(void *bitmap)
-{
- struct bitmap *bm = bitmap;
- uint32 p = bm->width * bm->height;
- uint32 a = 0;
- uint32 *bmi = (uint32 *)amiga_bitmap_get_buffer(bm);
-
- assert(bitmap);
-
- for(a=0;a<p;a+=4)
- {
- if ((*bmi & 0x000000ffU) != 0x000000ffU) return false;
- bmi++;
- }
- return true;
-}
-
-
-/* exported function documented in amiga/bitmap.h */
bool amiga_bitmap_get_opaque(void *bitmap)
{
struct bitmap *bm = bitmap;
@@ -367,40 +347,6 @@ int bitmap_get_height(void *bitmap)
}
}
-
-/**
- * Find the bytes per pixel of a bitmap
- *
- * \param vbitmap a bitmap, as returned by bitmap_create()
- * \return bytes per pixel
- */
-static size_t bitmap_get_bpp(void *vbitmap)
-{
- struct bitmap *bitmap = (struct bitmap *)vbitmap;
- assert(bitmap);
- return 4;
-}
-
-static void ami_bitmap_argb_to_rgba(struct bitmap *bm)
-{
- if(bm == NULL) return;
-
- ULONG *data = (ULONG *)amiga_bitmap_get_buffer(bm);
- for(int i = 0; i < (bm->width * bm->height); i++) {
- data[i] = (data[i] << 8) | (data[i] >> 24);
- }
-}
-
-static void ami_bitmap_rgba_to_argb(struct bitmap *bm)
-{
- if(bm == NULL) return;
-
- ULONG *data = (ULONG *)amiga_bitmap_get_buffer(bm);
- for(int i = 0; i < (bm->width * bm->height); i++) {
- data[i] = (data[ i] >> 8) | (data[i] << 24);
- }
-}
-
#ifdef BITMAP_DUMP
void bitmap_dump(struct bitmap *bitmap)
{
@@ -436,7 +382,7 @@ Object *ami_datatype_object_from_bitmap(struct bitmap *bitmap)
{
bmhd->bmh_Width = (UWORD)bitmap_get_width(bitmap);
bmhd->bmh_Height = (UWORD)bitmap_get_height(bitmap);
- bmhd->bmh_Depth = (UBYTE)bitmap_get_bpp(bitmap) * 8;
+ bmhd->bmh_Depth = (UBYTE)32;
if(!amiga_bitmap_get_opaque(bitmap)) bmhd->bmh_Masking = mskHasAlpha;
}
@@ -450,7 +396,7 @@ Object *ami_datatype_object_from_bitmap(struct bitmap *bitmap)
TAG_DONE);
IDoMethod(dto, PDTM_WRITEPIXELARRAY, amiga_bitmap_get_buffer(bitmap),
- PBPAFMT_RGBA, amiga_bitmap_get_rowstride(bitmap), 0, 0,
+ PBPAFMT_ARGB, amiga_bitmap_get_rowstride(bitmap), 0, 0,
bitmap_get_width(bitmap), bitmap_get_height(bitmap));
}
@@ -475,10 +421,10 @@ struct bitmap *ami_bitmap_from_datatype(char *filename)
bm = amiga_bitmap_create(bmh->bmh_Width, bmh->bmh_Height, 0);
IDoMethod(dto, PDTM_READPIXELARRAY, amiga_bitmap_get_buffer(bm),
- PBPAFMT_RGBA, amiga_bitmap_get_rowstride(bm), 0, 0,
+ PBPAFMT_ARGB, amiga_bitmap_get_rowstride(bm), 0, 0,
bmh->bmh_Width, bmh->bmh_Height);
- amiga_bitmap_set_opaque(bm, amiga_bitmap_test_opaque(bm));
+ amiga_bitmap_set_opaque(bm, bitmap_test_opaque(bm));
}
DisposeDTObject(dto);
}
@@ -490,6 +436,7 @@ static inline struct BitMap *ami_bitmap_get_generic(struct bitmap *bitmap,
int width, int height, struct BitMap *restrict friendbm, int type)
{
struct BitMap *restrict tbm = NULL;
+ struct Screen *scrn = ami_gui_get_screen();
if(bitmap->nativebm)
{
@@ -530,19 +477,22 @@ static inline struct BitMap *ami_bitmap_get_generic(struct bitmap *bitmap,
dithermode = DITHERMODE_FS;
}
- ami_bitmap_rgba_to_argb(bitmap);
- bitmap->drawhandle = ObtainDrawHandle(NULL,
- &rp, scrn->ViewPort.ColorMap,
- GGFX_DitherMode, dithermode,
- TAG_DONE);
-
- APTR ddh = CreateDirectDrawHandle(bitmap->drawhandle,
- bitmap->width, bitmap->height,
- width, height, NULL);
-
- DirectDrawTrueColor(ddh, (ULONG *)amiga_bitmap_get_buffer(bitmap), 0, 0, TAG_DONE);
- DeleteDirectDrawHandle(ddh);
- ami_bitmap_argb_to_rgba(bitmap);
+ bitmap->drawhandle = ObtainDrawHandle(
+ NULL,
+ &rp,
+ scrn->ViewPort.ColorMap,
+ GGFX_DitherMode, dithermode,
+ TAG_DONE);
+ if(bitmap->drawhandle) {
+ APTR ddh = CreateDirectDrawHandle(bitmap->drawhandle,
+ bitmap->width, bitmap->height,
+ width, height, NULL);
+
+ DirectDrawTrueColor(ddh, (ULONG *)amiga_bitmap_get_buffer(bitmap), 0, 0, TAG_DONE);
+ DeleteDirectDrawHandle(ddh);
+ ReleaseDrawHandle(bitmap->drawhandle);
+ bitmap->drawhandle = NULL;
+ }
} else {
if(guigfx_warned == false) {
amiga_warn_user("BMConvErr", NULL);
@@ -692,7 +642,7 @@ PLANEPTR ami_bitmap_get_mask(struct bitmap *bitmap, int width,
for(y=0; y<height; y++) {
for(x=0; x<width; x++) {
- if ((*bmi & 0x000000ffU) <= (ULONG)nsoption_int(mask_alpha)) maskbit = 0;
+ if ((*bmi & 0xff000000U) <= (ULONG)nsoption_int(mask_alpha)) maskbit = 0;
else maskbit = 1;
bmi++;
bitmap->native_mask[(y*bpr) + (x/8)] |=
@@ -769,8 +719,6 @@ static nserror bitmap_render(struct bitmap *bitmap, struct hlcache_handle *conte
BLITA_DestY, 0,
TAG_DONE);
- ami_bitmap_argb_to_rgba(bitmap);
-
/**\todo In theory we should be able to move the bitmap to our native area
to try to avoid re-conversion (at the expense of memory) */
@@ -818,13 +766,10 @@ static struct gui_bitmap_table bitmap_table = {
.destroy = amiga_bitmap_destroy,
.set_opaque = amiga_bitmap_set_opaque,
.get_opaque = amiga_bitmap_get_opaque,
- .test_opaque = amiga_bitmap_test_opaque,
.get_buffer = amiga_bitmap_get_buffer,
.get_rowstride = amiga_bitmap_get_rowstride,
.get_width = bitmap_get_width,
.get_height = bitmap_get_height,
- .get_bpp = bitmap_get_bpp,
- .save = amiga_bitmap_save,
.modified = amiga_bitmap_modified,
.render = bitmap_render,
};
diff --git a/frontends/amiga/bitmap.h b/frontends/amiga/bitmap.h
index aaec26ac2..a7dc9198f 100755
--- a/frontends/amiga/bitmap.h
+++ b/frontends/amiga/bitmap.h
@@ -25,7 +25,9 @@
#include <intuition/classusr.h>
#include <libraries/Picasso96.h>
-#define AMI_BITMAP_FORMAT RGBFB_R8G8B8A8
+#include "netsurf/bitmap.h"
+
+#define AMI_BITMAP_FORMAT RGBFB_A8R8G8B8
#define AMI_BITMAP_SCALE_ICON 0xFF
extern struct gui_bitmap_table *amiga_bitmap_table;
@@ -101,10 +103,10 @@ void ami_bitmap_fini(void);
*
* \param width width of image in pixels
* \param height width of image in pixels
- * \param state a flag word indicating the initial state
+ * \param flags flags for bitmap creation
* \return an opaque struct bitmap, or NULL on memory exhaustion
*/
-void *amiga_bitmap_create(int width, int height, unsigned int state);
+void *amiga_bitmap_create(int width, int height, enum gui_bitmap_flags flags);
/**
* Return a pointer to the pixel data in a bitmap.
@@ -174,14 +176,6 @@ void amiga_bitmap_modified(void *bitmap);
void amiga_bitmap_set_opaque(void *bitmap, bool opaque);
/**
- * Tests whether a bitmap has an opaque alpha channel
- *
- * \param bitmap a bitmap, as returned by bitmap_create()
- * \return whether the bitmap is opaque
- */
-bool amiga_bitmap_test_opaque(void *bitmap);
-
-/**
* Gets whether a bitmap should be plotted opaque
*
* \param bitmap a bitmap, as returned by bitmap_create()
diff --git a/frontends/amiga/clipboard.c b/frontends/amiga/clipboard.c
index 27b801540..05a83606e 100644
--- a/frontends/amiga/clipboard.c
+++ b/frontends/amiga/clipboard.c
@@ -17,6 +17,7 @@
*/
#include <stdlib.h>
+#include <string.h>
#include <proto/iffparse.h>
#include <proto/intuition.h>
#include <proto/exec.h>
@@ -86,14 +87,14 @@ void ami_clipboard_free(void)
void gui_start_selection(struct gui_window *g)
{
if(!g) return;
- if(!g->shared->win) return;
+ if(!ami_gui_get_window(g)) return;
if(nsoption_bool(kiosk_mode) == true) return;
- ami_gui_menu_set_disabled(g->shared->win, g->shared->imenu, M_COPY, false);
- ami_gui_menu_set_disabled(g->shared->win, g->shared->imenu, M_CLEAR, false);
+ ami_gui_menu_set_disabled(ami_gui_get_window(g), ami_gui_get_menu(g), M_COPY, false);
+ ami_gui_menu_set_disabled(ami_gui_get_window(g), ami_gui_get_menu(g), M_CLEAR, false);
- if (browser_window_get_editor_flags(g->bw) & BW_EDITOR_CAN_CUT)
- ami_gui_menu_set_disabled(g->shared->win, g->shared->imenu, M_CUT, false);
+ if (browser_window_get_editor_flags(ami_gui_get_browser_window(g)) & BW_EDITOR_CAN_CUT)
+ ami_gui_menu_set_disabled(ami_gui_get_window(g), ami_gui_get_menu(g), M_CUT, false);
}
static char *ami_clipboard_cat_collection(struct CollectionItem *ci, LONG codeset, size_t *text_length)
@@ -276,54 +277,54 @@ void ami_drag_selection(struct gui_window *g)
if(!gwin)
{
- DisplayBeep(scrn);
+ ami_gui_beep();
return;
}
- x = gwin->win->MouseX;
- y = gwin->win->MouseY;
+ x = ami_gui2_get_window(gwin)->MouseX;
+ y = ami_gui2_get_window(gwin)->MouseY;
if(ami_text_box_at_point(gwin, (ULONG *)&x, (ULONG *)&y))
{
iffh = ami_clipboard_init_internal(1);
- browser_window_key_press(g->bw, NS_KEY_COPY_SELECTION);
- browser_window_mouse_click(gwin->gw->bw, BROWSER_MOUSE_PRESS_1, x, y);
- browser_window_key_press(gwin->gw->bw, NS_KEY_PASTE);
+ browser_window_key_press(ami_gui_get_browser_window(g), NS_KEY_COPY_SELECTION);
+ browser_window_mouse_click(ami_gui2_get_browser_window(gwin), BROWSER_MOUSE_PRESS_1, x, y);
+ browser_window_key_press(ami_gui2_get_browser_window(gwin), NS_KEY_PASTE);
ami_clipboard_free_internal(iffh);
iffh = old_iffh;
}
else
{
- x = gwin->win->MouseX;
- y = gwin->win->MouseY;
+ x = ami_gui2_get_window(gwin)->MouseX;
+ y = ami_gui2_get_window(gwin)->MouseY;
- if(ami_gadget_hit(gwin->objects[GID_URL], x, y))
+ if(ami_gadget_hit(ami_gui2_get_object(gwin, AMI_GAD_URL), x, y))
{
- if((sel = browser_window_get_selection(g->bw)))
+ if((sel = browser_window_get_selection(ami_gui_get_browser_window(g))))
{
utf8text = ami_utf8_easy(sel);
- RefreshSetGadgetAttrs((struct Gadget *)gwin->objects[GID_URL],
- gwin->win, NULL, STRINGA_TextVal, utf8text, TAG_DONE);
+ RefreshSetGadgetAttrs((struct Gadget *)ami_gui2_get_object(gwin, AMI_GAD_URL),
+ ami_gui2_get_window(gwin), NULL, STRINGA_TextVal, utf8text, TAG_DONE);
free(sel);
ami_utf8_free(utf8text);
}
}
- else if(ami_gadget_hit(gwin->objects[GID_SEARCHSTRING], x, y))
+ else if(ami_gadget_hit(ami_gui2_get_object(gwin, AMI_GAD_SEARCH), x, y))
{
- if((sel = browser_window_get_selection(g->bw)))
+ if((sel = browser_window_get_selection(ami_gui_get_browser_window(g))))
{
utf8text = ami_utf8_easy(sel);
- RefreshSetGadgetAttrs((struct Gadget *)gwin->objects[GID_SEARCHSTRING],
- gwin->win, NULL, STRINGA_TextVal, utf8text, TAG_DONE);
+ RefreshSetGadgetAttrs((struct Gadget *)ami_gui2_get_object(gwin, AMI_GAD_SEARCH),
+ ami_gui2_get_window(gwin), NULL, STRINGA_TextVal, utf8text, TAG_DONE);
free(sel);
ami_utf8_free(utf8text);
}
}
else
{
- DisplayBeep(scrn);
+ ami_gui_beep();
}
}
}
@@ -349,15 +350,22 @@ bool ami_easy_clipboard_bitmap(struct bitmap *bitmap)
#ifdef WITH_NS_SVG
bool ami_easy_clipboard_svg(struct hlcache_handle *c)
{
- const char *source_data;
- ULONG source_size;
+ const uint8_t *source_data;
+ size_t source_size;
- if(ami_mime_compare(c, "svg") == false) return false;
- if((source_data = content_get_source_data(c, &source_size)) == NULL) return false;
+ if (ami_mime_compare(c, "svg") == false) {
+ return false;
+ }
+ source_data = content_get_source_data(c, &source_size);
+ if (source_data == NULL) {
+ return false;
+ }
- if(!(OpenIFF(iffh,IFFF_WRITE)))
- {
- ami_svg_to_dr2d(iffh, source_data, source_size, nsurl_access(hlcache_handle_get_url(c)));
+ if (!(OpenIFF(iffh,IFFF_WRITE))) {
+ ami_svg_to_dr2d(iffh,
+ (const char *)source_data,
+ source_size,
+ nsurl_access(hlcache_handle_get_url(c)));
CloseIFF(iffh);
}
diff --git a/frontends/amiga/cookies.c b/frontends/amiga/cookies.c
index 45e883fde..3cd32f37e 100644
--- a/frontends/amiga/cookies.c
+++ b/frontends/amiga/cookies.c
@@ -310,7 +310,7 @@ ami_cookies_create_window(struct ami_cookie_window *cookie_win)
WA_Left, nsoption_int(cookies_window_xpos),
WA_Width, nsoption_int(cookies_window_xsize),
WA_Height, nsoption_int(cookies_window_ysize),
- WA_PubScreen, scrn,
+ WA_PubScreen, ami_gui_get_screen(),
WA_ReportMouse, TRUE,
refresh_mode, TRUE,
WA_IDCMP, IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_NEWSIZE |
@@ -319,7 +319,7 @@ ami_cookies_create_window(struct ami_cookie_window *cookie_win)
WINDOW_IDCMPHook, &ami_cw->idcmp_hook,
WINDOW_IDCMPHookBits, IDCMP_IDCMPUPDATE | IDCMP_EXTENDEDMOUSE |
IDCMP_SIZEVERIFY | IDCMP_REFRESHWINDOW,
- WINDOW_SharedPort, sport,
+ WINDOW_SharedPort, ami_gui_get_shared_msgport(),
WINDOW_HorizProp, 1,
WINDOW_VertProp, 1,
WINDOW_UserData, cookie_win,
@@ -345,7 +345,7 @@ ami_cookies_create_window(struct ami_cookie_window *cookie_win)
}
/* exported interface documented in amiga/cookies.h */
-nserror ami_cookies_present(void)
+nserror ami_cookies_present(const char *search_term)
{
struct ami_cookie_window *ncwin;
nserror res;
@@ -395,6 +395,10 @@ nserror ami_cookies_present(void)
cookie_window = ncwin;
- return NSERROR_OK;
+ if (search_term != NULL) {
+ res = cookie_manager_set_search_string(search_term);
+ }
+
+ return res;
}
diff --git a/frontends/amiga/cookies.h b/frontends/amiga/cookies.h
index 6858e4cab..6eb525cbe 100644
--- a/frontends/amiga/cookies.h
+++ b/frontends/amiga/cookies.h
@@ -20,6 +20,6 @@
#define AMIGA_COOKIES_H
/** Open the cookie viewer */
-nserror ami_cookies_present(void);
+nserror ami_cookies_present(const char *search_term);
#endif
diff --git a/frontends/amiga/corewindow.c b/frontends/amiga/corewindow.c
index 42ee866ea..bfb0eb202 100644
--- a/frontends/amiga/corewindow.c
+++ b/frontends/amiga/corewindow.c
@@ -68,17 +68,19 @@
#include "amiga/utf8.h"
static void
-ami_cw_scroller_top(struct ami_corewindow *ami_cw, ULONG *restrict x, ULONG *restrict y)
+ami_cw_scroller_top(struct ami_corewindow *ami_cw,
+ ULONG *restrict x,
+ ULONG *restrict y)
{
ULONG xs = 0;
ULONG ys = 0;
if(ami_cw->scroll_x_visible == true) {
- GetAttr(SCROLLER_Top, ami_cw->objects[GID_CW_HSCROLL], (ULONG *)&xs);
+ GetAttr(SCROLLER_Top, ami_cw->objects[GID_CW_HSCROLL], &xs);
}
if(ami_cw->scroll_y_visible == true) {
- GetAttr(SCROLLER_Top, ami_cw->objects[GID_CW_VSCROLL], (ULONG *)&ys);
+ GetAttr(SCROLLER_Top, ami_cw->objects[GID_CW_VSCROLL], &ys);
}
*x = xs;
@@ -243,15 +245,15 @@ ami_cw_redraw_rect(struct ami_corewindow *ami_cw, struct rect *r)
ami_cw_scroller_top(ami_cw, &pos_x, &pos_y);
- if(x - pos_x + width > bbox->Width) width = bbox->Width - (x - pos_x);
- if(y - pos_y + height > bbox->Height) height = bbox->Height - (y - pos_y);
+ if(x - (LONG)pos_x + width > bbox->Width) width = bbox->Width - (x - pos_x);
+ if(y - (LONG)pos_y + height > bbox->Height) height = bbox->Height - (y - pos_y);
- if(x < pos_x) {
+ if(x < (LONG)pos_x) {
width -= pos_x - x;
x = pos_x;
}
- if(y < pos_y) {
+ if(y < (LONG)pos_y) {
height -= pos_y - y;
y = pos_y;
}
@@ -585,6 +587,7 @@ static void
ami_cw_drag_end(struct ami_corewindow *ami_cw, int x, int y)
{
if(ami_cw->dragging == false) return;
+ struct Screen *scrn = ami_gui_get_screen();
switch(ami_cw->drag_status) {
case CORE_WINDOW_DRAG_SELECTION:
@@ -822,16 +825,18 @@ ami_cw_invalidate_area(struct core_window *cw, const struct rect *r)
}
-static void
-ami_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
+static nserror
+ami_cw_get_window_dimensions(const struct core_window *cw,
+ int *width, int *height)
{
struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw;
ami_cw_window_size(ami_cw, width, height);
+ return NSERROR_OK;
}
-static void
+static nserror
ami_cw_update_size(struct core_window *cw, int width, int height)
{
struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw;
@@ -858,61 +863,61 @@ ami_cw_update_size(struct core_window *cw, int width, int height)
SCROLLER_Visible, win_h,
TAG_DONE);
}
+ return NSERROR_OK;
}
-static void
-ami_cw_scroll_visible(struct core_window *cw, const struct rect *r)
+static nserror
+ami_cw_get_scroll(const struct core_window *cw, int *x, int *y)
{
struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw;
-
- int scrollsetx;
- int scrollsety;
- int win_w = 0, win_h = 0;
ULONG win_x0, win_y0;
- int win_x1, win_y1;
-
- ami_cw_window_size(ami_cw, &win_w, &win_h);
ami_cw_scroller_top(ami_cw, &win_x0, &win_y0);
- win_x1 = win_x0 + win_w;
- win_y1 = win_y0 + win_h;
+ *x = win_x0;
+ *y = win_y0;
+ return NSERROR_OK;
+}
+
- if(r->y1 > win_y1) scrollsety = r->y1 - win_h;
- if(r->y0 < win_y0) scrollsety = r->y0;
- if(r->x1 > win_x1) scrollsetx = r->x1 - win_w;
- if(r->x0 < win_x0) scrollsetx = r->x0;
+static nserror
+ami_cw_set_scroll(struct core_window *cw, int x, int y)
+{
+ struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw;
if(ami_cw->scroll_y_visible == true) {
RefreshSetGadgetAttrs((APTR)ami_cw->objects[GID_CW_VSCROLL], ami_cw->win, NULL,
- SCROLLER_Top, scrollsety,
+ SCROLLER_Top, y,
TAG_DONE);
}
if(ami_cw->scroll_x_visible == true) {
RefreshSetGadgetAttrs((APTR)ami_cw->objects[GID_CW_HSCROLL], ami_cw->win, NULL,
- SCROLLER_Top, scrollsetx,
+ SCROLLER_Top, x,
TAG_DONE);
}
/* probably need to redraw here */
ami_cw_redraw(ami_cw, NULL);
+ return NSERROR_OK;
}
-static void
+static nserror
ami_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
{
struct ami_corewindow *ami_cw = (struct ami_corewindow *)cw;
ami_cw->drag_status = ds;
+ return NSERROR_OK;
}
struct core_window_callback_table ami_cw_cb_table = {
.invalidate = ami_cw_invalidate_area,
.update_size = ami_cw_update_size,
- .scroll_visible = ami_cw_scroll_visible,
+ .set_scroll = ami_cw_set_scroll,
+ .get_scroll = ami_cw_get_scroll,
.get_window_dimensions = ami_cw_get_window_dimensions,
.drag_status = ami_cw_drag_status
};
diff --git a/frontends/amiga/ctxmenu.c b/frontends/amiga/ctxmenu.c
index 717096f52..42826a3a5 100644
--- a/frontends/amiga/ctxmenu.c
+++ b/frontends/amiga/ctxmenu.c
@@ -107,8 +107,8 @@ HOOKF(void, ami_ctxmenu_item_selcopy, APTR, window, struct IntuiMessage *)
{
struct gui_window_2 *gwin = (struct gui_window_2 *)hook->h_Data;
- browser_window_key_press(gwin->gw->bw, NS_KEY_COPY_SELECTION);
- browser_window_key_press(gwin->gw->bw, NS_KEY_CLEAR_SELECTION);
+ browser_window_key_press(ami_gui2_get_browser_window(gwin), NS_KEY_COPY_SELECTION);
+ browser_window_key_press(ami_gui2_get_browser_window(gwin), NS_KEY_CLEAR_SELECTION);
}
HOOKF(void, ami_ctxmenu_item_websearch, APTR, window, struct IntuiMessage *)
@@ -117,11 +117,11 @@ HOOKF(void, ami_ctxmenu_item_websearch, APTR, window, struct IntuiMessage *)
nsurl *url;
struct gui_window_2 *gwin = (struct gui_window_2 *)hook->h_Data;
- char *sel = browser_window_get_selection(gwin->gw->bw);
+ char *sel = browser_window_get_selection(ami_gui2_get_browser_window(gwin));
ret = search_web_omni(sel, SEARCH_WEB_OMNI_SEARCHONLY, &url);
if (ret == NSERROR_OK) {
- browser_window_navigate(gwin->gw->bw,
+ browser_window_navigate(ami_gui2_get_browser_window(gwin),
url,
NULL,
BW_NAVIGATE_HISTORY,
@@ -146,8 +146,8 @@ HOOKF(void, ami_ctxmenu_item_urlopentab, APTR, window, struct IntuiMessage *)
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
nserror error = browser_window_create(BW_CREATE_CLONE | BW_CREATE_HISTORY | BW_CREATE_TAB,
url,
- browser_window_get_url(gwin->gw->bw),
- gwin->gw->bw,
+ browser_window_access_url(ami_gui2_get_browser_window(gwin)),
+ ami_gui2_get_browser_window(gwin),
&bw);
if (error != NSERROR_OK)
@@ -163,8 +163,8 @@ HOOKF(void, ami_ctxmenu_item_urlopenwin, APTR, window, struct IntuiMessage *)
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
nserror error = browser_window_create(BW_CREATE_CLONE | BW_CREATE_HISTORY,
url,
- browser_window_get_url(gwin->gw->bw),
- gwin->gw->bw,
+ browser_window_access_url(ami_gui2_get_browser_window(gwin)),
+ ami_gui2_get_browser_window(gwin),
&bw);
if (error != NSERROR_OK)
@@ -178,9 +178,9 @@ HOOKF(void, ami_ctxmenu_item_urldownload, APTR, window, struct IntuiMessage *)
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- browser_window_navigate(gwin->gw->bw,
+ browser_window_navigate(ami_gui2_get_browser_window(gwin),
url,
- browser_window_get_url(gwin->gw->bw),
+ browser_window_access_url(ami_gui2_get_browser_window(gwin)),
BW_NAVIGATE_DOWNLOAD,
NULL,
NULL,
@@ -198,9 +198,9 @@ HOOKF(void, ami_ctxmenu_item_objshow, APTR, window, struct IntuiMessage *)
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- browser_window_navigate(gwin->gw->bw,
+ browser_window_navigate(ami_gui2_get_browser_window(gwin),
hlcache_handle_get_url(hook->h_Data),
- browser_window_get_url(gwin->gw->bw),
+ browser_window_access_url(ami_gui2_get_browser_window(gwin)),
BW_NAVIGATE_HISTORY,
NULL,
NULL,
@@ -238,9 +238,9 @@ HOOKF(void, ami_ctxmenu_item_frameshow, APTR, window, struct IntuiMessage *)
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- browser_window_navigate(gwin->gw->bw,
+ browser_window_navigate(ami_gui2_get_browser_window(gwin),
hlcache_handle_get_url(hook->h_Data),
- browser_window_get_url(gwin->gw->bw),
+ browser_window_access_url(ami_gui2_get_browser_window(gwin)),
BW_NAVIGATE_HISTORY,
NULL,
NULL,
@@ -271,7 +271,8 @@ HOOKF(void, ami_ctxmenu_item_history, APTR, window, struct IntuiMessage *)
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- browser_window_history_go(gwin->gw->bw, (struct history_entry *)hook->h_Data, false);
+ browser_window_history_go(ami_gui2_get_browser_window(gwin),
+ (struct history_entry *)hook->h_Data, false);
}
@@ -300,7 +301,7 @@ static uint32 ami_ctxmenu_hook_func(struct Hook *hook, struct Window *window, st
Object *root_menu;
bool ctxmenu_has_content = false;
struct gui_window_2 *gwin = hook->h_Data;
- struct hlcache_handle *cc = browser_window_get_content(gwin->gw->bw);
+ struct hlcache_handle *cc = browser_window_get_content(ami_gui2_get_browser_window(gwin));
struct browser_window_features ccdata;
int mx = window->MouseX;
int my = window->MouseY;
@@ -328,11 +329,11 @@ static uint32 ami_ctxmenu_hook_func(struct Hook *hook, struct Window *window, st
return 0;
}
- browser_window_get_features(gwin->gw->bw, x, y, &ccdata);
+ browser_window_get_features(ami_gui2_get_browser_window(gwin), x, y, &ccdata);
- if((browser_window_can_select(gwin->gw->bw)) &&
- ((browser_window_get_editor_flags(gwin->gw->bw) & BW_EDITOR_CAN_COPY)) &&
- (sel = browser_window_get_selection(gwin->gw->bw))) {
+ if((browser_window_can_select(ami_gui2_get_browser_window(gwin))) &&
+ ((browser_window_get_editor_flags(ami_gui2_get_browser_window(gwin)) & BW_EDITOR_CAN_COPY)) &&
+ (sel = browser_window_get_selection(ami_gui2_get_browser_window(gwin)))) {
ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_SELCOPY, gwin);
ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_WEBSEARCH, gwin);
@@ -401,7 +402,7 @@ static void ami_ctxmenu_alloc_item(int id, const char *label, const char *key, c
if(image != NULL) {
ctxmenu_item_image[id] = BitMapObj,
- BITMAP_Screen, scrn,
+ BITMAP_Screen, ami_gui_get_screen(),
BITMAP_SourceFile, image,
BITMAP_Masking, TRUE,
BitMapEnd;
@@ -498,25 +499,26 @@ void ami_ctxmenu_init(void)
static bool ami_ctxmenu_history(int direction, struct gui_window_2 *gwin, const struct history_entry *entry)
{
Object *history_root;
- int id = AMI_CTX_ID_HISTORY0 + gwin->temp;
+ int id = AMI_CTX_ID_HISTORY0 + ami_gui2_get_ctxmenu_history_tmp(gwin);
if(direction == AMI_CTXMENU_HISTORY_FORWARD) id += 10;
- if(gwin->temp >= 10) return false;
+ if(ami_gui2_get_ctxmenu_history_tmp(gwin) >= 10) return false;
ctxmenu_item_hook[id].h_Entry = (HOOKFUNC)ami_ctxmenu_item_history;
ctxmenu_item_hook[id].h_Data = (APTR)entry;
- history_root = (Object *)IDoMethod(gwin->history_ctxmenu[direction], MM_FINDID, 0, AMI_CTX_ID_HISTORY);
+ history_root = (Object *)IDoMethod(ami_gui2_get_ctxmenu_history(gwin, direction), MM_FINDID, 0, AMI_CTX_ID_HISTORY);
IDoMethod(history_root, OM_ADDMEMBER, MStrip,
MA_Type, T_ITEM,
+ /* TODO: MA_Label should be in local charset */
MA_Label, browser_window_history_entry_get_title(entry),
MA_ID, id,
MA_Image, NULL,
MA_UserData, &ctxmenu_item_hook[id],
MEnd);
- gwin->temp++;
+ ami_gui2_set_ctxmenu_history_tmp(gwin, ami_gui2_get_ctxmenu_history_tmp(gwin) + 1);
return true;
}
@@ -542,11 +544,11 @@ struct Menu *ami_ctxmenu_history_create(int direction, struct gui_window_2 *gwin
{
Object *obj;
- if(gwin->history_ctxmenu[direction] == NULL) {
+ if(ami_gui2_get_ctxmenu_history(gwin, direction) == NULL) {
if(ctxmenu_item_label[AMI_CTX_ID_HISTORY] == NULL)
ctxmenu_item_label[AMI_CTX_ID_HISTORY] = ami_utf8_easy(messages_get("History"));
- gwin->history_ctxmenu[direction] = MStrip,
+ obj = MStrip,
MA_Type, T_ROOT,
MA_AddChild, MStrip,
MA_Type, T_MENU,
@@ -556,23 +558,26 @@ struct Menu *ami_ctxmenu_history_create(int direction, struct gui_window_2 *gwin
//MA_FreeImage, FALSE,
MEnd,
MEnd;
+
+ ami_gui2_set_ctxmenu_history(gwin, direction, obj);
+
} else {
for (int i = 0; i < 20; i++) {
- obj = (Object *)IDoMethod(gwin->history_ctxmenu[direction],
+ obj = (Object *)IDoMethod(ami_gui2_get_ctxmenu_history(gwin, direction),
MM_FINDID, 0, AMI_CTX_ID_HISTORY0 + i);
- if(obj != NULL) IDoMethod(gwin->history_ctxmenu[direction], OM_REMMEMBER, obj);
+ if(obj != NULL) IDoMethod(ami_gui2_get_ctxmenu_history(gwin, direction), OM_REMMEMBER, obj);
}
- gwin->temp = 0;
+ ami_gui2_set_ctxmenu_history_tmp(gwin, 0);
if(direction == AMI_CTXMENU_HISTORY_BACK) {
- browser_window_history_enumerate_back(gwin->gw->bw, ami_ctxmenu_history_back, gwin);
+ browser_window_history_enumerate_back(ami_gui2_get_browser_window(gwin), ami_ctxmenu_history_back, gwin);
} else {
- browser_window_history_enumerate_forward(gwin->gw->bw, ami_ctxmenu_history_forward, gwin);
+ browser_window_history_enumerate_forward(ami_gui2_get_browser_window(gwin), ami_ctxmenu_history_forward, gwin);
}
}
- return (struct Menu *)gwin->history_ctxmenu[direction];
+ return (struct Menu *)ami_gui2_get_ctxmenu_history(gwin, direction);
}
@@ -581,13 +586,16 @@ struct Menu *ami_ctxmenu_history_create(int direction, struct gui_window_2 *gwin
**************************/
/** Exported interface documented in ctxmenu.h **/
-struct Menu *ami_ctxmenu_clicktab_create(struct gui_window_2 *gwin)
+struct Menu *ami_ctxmenu_clicktab_create(struct gui_window_2 *gwin, Object **clicktab_obj)
{
Object *root_menu;
+ Object *clicktab;
- if(gwin->clicktab_ctxmenu != NULL) return (struct Menu *)gwin->clicktab_ctxmenu;
+ if(*clicktab_obj != NULL) {
+ return (struct Menu *)*clicktab_obj;
+ }
- gwin->clicktab_ctxmenu = MStrip,
+ clicktab = MStrip,
MA_Type, T_ROOT,
MA_AddChild, root_menu = MStrip,
MA_Type, T_MENU,
@@ -596,10 +604,12 @@ struct Menu *ami_ctxmenu_clicktab_create(struct gui_window_2 *gwin)
MEnd,
MEnd;
+ *clicktab_obj = clicktab;
+
ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_TABNEW, gwin);
ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_TABCLOSE_OTHER, gwin);
- return (struct Menu *)gwin->clicktab_ctxmenu;
+ return (struct Menu *)clicktab;
}
diff --git a/frontends/amiga/ctxmenu.h b/frontends/amiga/ctxmenu.h
index 08a5fe582..76beff5b0 100644
--- a/frontends/amiga/ctxmenu.h
+++ b/frontends/amiga/ctxmenu.h
@@ -75,10 +75,11 @@ struct Menu *ami_ctxmenu_history_create(int direction, struct gui_window_2 *gwin
* Create ClickTab context menu
*
* \param gwin struct gui_window_2 *
- * \returns pointer to menu (for convenience, is also stored in gwin structure)
+ * \param clicktab_obj ptr to memory to hold clicktab menu object
+ * \returns pointer to menu (for convenience)
* The returned pointer MUST be disposed of with DisposeObject before program exit.
*/
-struct Menu *ami_ctxmenu_clicktab_create(struct gui_window_2 *gwin);
+struct Menu *ami_ctxmenu_clicktab_create(struct gui_window_2 *gwin, Object **clicktab_obj);
#else //__amigaos4__
inline void ami_ctxmenu_init(void) {}
@@ -86,7 +87,7 @@ inline void ami_ctxmenu_free(void) {}
inline struct Hook *ami_ctxmenu_get_hook(APTR data) {return NULL;}
inline void ami_ctxmenu_release_hook(struct Hook *hook) {}
inline struct Menu *ami_ctxmenu_history_create(int direction, struct gui_window_2 *gwin) {return NULL;}
-inline struct Menu *ami_ctxmenu_clicktab_create(struct gui_window_2 *gwin) {return NULL;}
+inline struct Menu *ami_ctxmenu_clicktab_create(struct gui_window_2 *gwin, Object **clicktab_obj) {return NULL;}
#endif //__amigaos4__
#endif //AMIGA_CTXMENU_H
diff --git a/frontends/amiga/dist/Rexx/YT_download_page.nsrx b/frontends/amiga/dist/Rexx/YT_download_page.nsrx
new file mode 100644
index 000000000..fdc06923d
--- /dev/null
+++ b/frontends/amiga/dist/Rexx/YT_download_page.nsrx
@@ -0,0 +1,21 @@
+/* YT play.nsrx by Chris Handley
+ This script shows download links for a YouTube video using YT (OS4Depot:video/misc/yt.lha)
+*/
+
+options results
+
+if ~open('yt','AppDir:YT','R') then do
+ GETSCREENNAME
+ address command 'requestchoice >NIL: "NetSurf" "YT must be installed for this script to function.*n*nIt can be downloaded from OS4Depot:video/misc/yt" "OK" PubScreen='||result
+ OPEN 'http://os4depot.net/?function=showfile&file=video/misc/yt.lha' NEWTAB ACTIVE /* This doesn't work due to a NetSurf(?) bug */
+ exit
+end
+close('yt')
+
+GETURL
+/*address command 'requestchoice >NIL: "TEST" "'||result||'" "OK"'*/
+address command 'AppDir:YT <>CON:0/30/640/256/YT/AUTO/CLOSE "'||result||'" html silent'
+
+/* Hack to activate the newest tab */
+OPEN 'file:///RAM:' NEWTAB ACTIVE
+CLOSE
diff --git a/frontends/amiga/dist/Rexx/YT_open.nsrx b/frontends/amiga/dist/Rexx/YT_open.nsrx
new file mode 100644
index 000000000..4454f0c29
--- /dev/null
+++ b/frontends/amiga/dist/Rexx/YT_open.nsrx
@@ -0,0 +1,21 @@
+/* YT play.nsrx by Chris Handley
+ This script opens a YouTube video using YT (OS4Depot:video/misc/yt.lha)
+*/
+
+options results
+
+if ~open('yt','AppDir:YT','R') then do
+ GETSCREENNAME
+ address command 'requestchoice >NIL: "NetSurf" "YT must be installed for this script to function.*n*nIt can be downloaded from OS4Depot:video/misc/yt" "OK" PubScreen='||result
+ OPEN 'http://os4depot.net/?function=showfile&file=video/misc/yt.lha' NEWTAB ACTIVE /* This doesn't work due to a NetSurf(?) bug */
+ exit
+end
+close('yt')
+
+address COMMAND 'Run >NIL: RequestChoice Title="NetSurf" BODY="When finished with YT, click OK to return to NetSurf" GADGETS="OK" INACTIVE >NIL:' /* Hack to get Workbench to front */
+
+GETURL
+/*address command 'requestchoice >NIL: "TEST" "'||result||'" "OK"'*/
+address command 'AppDir:YT <>CON:0/30/640/256/YT/AUTO/CLOSE "'||result||'"'
+
+/*TOBACK*/ /* ideally we'd bring Workbench to front */
diff --git a/frontends/amiga/dist/Rexx/YT_play.nsrx b/frontends/amiga/dist/Rexx/YT_play.nsrx
new file mode 100644
index 000000000..a8e29162f
--- /dev/null
+++ b/frontends/amiga/dist/Rexx/YT_play.nsrx
@@ -0,0 +1,19 @@
+/* YT play.nsrx by Chris Handley
+ This script auto-plays a YouTube video using YT (OS4Depot:video/misc/yt.lha)
+*/
+
+options results
+
+if ~open('yt','AppDir:YT','R') then do
+ GETSCREENNAME
+ address command 'requestchoice >NIL: "NetSurf" "YT must be installed for this script to function.*n*nIt can be downloaded from OS4Depot:video/misc/yt" "OK" PubScreen='||result
+ OPEN 'http://os4depot.net/?function=showfile&file=video/misc/yt.lha' NEWTAB ACTIVE /* This doesn't work due to a NetSurf(?) bug */
+ exit
+end
+close('yt')
+
+GETURL
+/*address command 'requestchoice >NIL: "TEST" "'||result||'" "OK"'*/
+address command 'AppDir:YT <>CON:0/30/640/256/YT/AUTO/CLOSE "'||result||'" AutoPlay'
+
+/*TOBACK*/ /* ideally we'd bring Workbench to front */
diff --git a/frontends/amiga/download.c b/frontends/amiga/download.c
index 41ff6a689..cb9e99785 100644
--- a/frontends/amiga/download.c
+++ b/frontends/amiga/download.c
@@ -80,10 +80,18 @@
#define APPNOTIFY_StopBackMsg ( TAG_USER + 17 )
#endif
+enum {
+ OID_D_MAIN = 0,
+ GID_D_MAIN,
+ GID_D_STATUS,
+ GID_D_CANCEL,
+ GID_D_LAST
+};
+
struct gui_download_window {
struct ami_generic_window w;
struct Window *win;
- Object *objects[GID_LAST];
+ Object *objects[GID_D_LAST];
BPTR fh;
uint32 size;
uint32 downloaded;
@@ -124,8 +132,8 @@ static struct gui_download_window *gui_download_window_create(download_context *
dw = calloc(1, sizeof(struct gui_download_window));
- if(gui && (!IsListEmpty(&gui->dllist)) && (dw->dln = (struct dlnode *)FindName(&gui->dllist,url)))
- {
+ if(gui && (!IsListEmpty(ami_gui_get_download_list(gui)) &&
+ (dw->dln = (struct dlnode *)FindName(ami_gui_get_download_list(gui), url)))) {
strcpy(dw->fname, dw->dln->filename);
free(dw->dln->node.ln_Name);
dw->dln->node.ln_Name = NULL;
@@ -133,16 +141,16 @@ static struct gui_download_window *gui_download_window_create(download_context *
else
{
if(AslRequestTags(savereq,
- ASLFR_Window, gui->shared->win,
+ ASLFR_Window, ami_gui_get_window(gui),
ASLFR_SleepWindow, TRUE,
ASLFR_TitleText, messages_get("NetSurf"),
- ASLFR_Screen, scrn,
+ ASLFR_Screen, ami_gui_get_screen(),
ASLFR_InitialFile, dl_filename,
TAG_DONE))
{
strlcpy(dw->fname, savereq->fr_Drawer, 1024);
AddPart((STRPTR)&dw->fname,savereq->fr_File,1024);
- if(!ami_download_check_overwrite(dw->fname, gui->shared->win, total_size))
+ if(!ami_download_check_overwrite(dw->fname, ami_gui_get_window(gui), total_size))
{
free(dw);
return NULL;
@@ -158,7 +166,7 @@ static struct gui_download_window *gui_download_window_create(download_context *
if(dl_filename) ami_utf8_free(dl_filename);
dw->size = total_size;
dw->downloaded = 0;
- if(gui) dw->bw = gui->bw;
+ if(gui) dw->bw = ami_gui_get_browser_window(gui);
dw->url = url;
va[0] = (APTR)dw->downloaded;
@@ -183,7 +191,7 @@ static struct gui_download_window *gui_download_window_create(download_context *
APPNOTIFY_StopBackMsg, bkm,
TAG_DONE);
} else {
- dw->objects[OID_MAIN] = WindowObj,
+ dw->objects[OID_D_MAIN] = WindowObj,
WA_ScreenTitle, ami_gui_get_screen_title(),
WA_Title, dw->url,
WA_Activate, TRUE,
@@ -191,15 +199,15 @@ static struct gui_download_window *gui_download_window_create(download_context *
WA_DragBar, TRUE,
WA_CloseGadget, FALSE,
WA_SizeGadget, TRUE,
- WA_PubScreen,scrn,
- WINDOW_SharedPort,sport,
+ WA_PubScreen, ami_gui_get_screen(),
+ WINDOW_SharedPort, ami_gui_get_shared_msgport(),
WINDOW_UserData,dw,
WINDOW_IconifyGadget, FALSE,
WINDOW_LockHeight,TRUE,
WINDOW_Position, WPOS_CENTERSCREEN,
- WINDOW_ParentGroup, dw->objects[GID_MAIN] = LayoutVObj,
- LAYOUT_AddChild, dw->objects[GID_STATUS] = FuelGaugeObj,
- GA_ID,GID_STATUS,
+ WINDOW_ParentGroup, dw->objects[GID_D_MAIN] = LayoutVObj,
+ LAYOUT_AddChild, dw->objects[GID_D_STATUS] = FuelGaugeObj,
+ GA_ID,GID_D_STATUS,
GA_Text,messages_get("amiDownload"),
FUELGAUGE_Min,0,
FUELGAUGE_Max,total_size,
@@ -212,8 +220,8 @@ static struct gui_download_window *gui_download_window_create(download_context *
FuelGaugeEnd,
CHILD_NominalSize,TRUE,
CHILD_WeightedHeight,0,
- LAYOUT_AddChild, dw->objects[GID_CANCEL] = ButtonObj,
- GA_ID,GID_CANCEL,
+ LAYOUT_AddChild, dw->objects[GID_D_CANCEL] = ButtonObj,
+ GA_ID,GID_D_CANCEL,
GA_RelVerify,TRUE,
GA_Text,messages_get("Abort"),
GA_TabCycle,TRUE,
@@ -221,7 +229,7 @@ static struct gui_download_window *gui_download_window_create(download_context *
EndGroup,
EndWindow;
- dw->win = (struct Window *)RA_OpenWindow(dw->objects[OID_MAIN]);
+ dw->win = (struct Window *)RA_OpenWindow(dw->objects[OID_D_MAIN]);
}
dw->ctx = ctx;
@@ -256,7 +264,7 @@ static nserror gui_download_window_data(struct gui_download_window *dw,
APPNOTIFY_Percentage, dw->progress,
TAG_DONE);
} else {
- RefreshSetGadgetAttrs((struct Gadget *)dw->objects[GID_STATUS], dw->win, NULL,
+ RefreshSetGadgetAttrs((struct Gadget *)dw->objects[GID_D_STATUS], dw->win, NULL,
FUELGAUGE_Level, dw->downloaded,
GA_Text, messages_get("amiDownload"),
FUELGAUGE_VarArgs, va,
@@ -271,7 +279,7 @@ static nserror gui_download_window_data(struct gui_download_window *dw,
APPNOTIFY_Percentage, 100,
TAG_DONE);
} else {
- RefreshSetGadgetAttrs((struct Gadget *)dw->objects[GID_STATUS], dw->win, NULL,
+ RefreshSetGadgetAttrs((struct Gadget *)dw->objects[GID_D_STATUS], dw->win, NULL,
FUELGAUGE_Level, dw->downloaded,
GA_Text, messages_get("amiDownloadU"),
FUELGAUGE_VarArgs, va,
@@ -330,8 +338,8 @@ static void gui_download_window_done(struct gui_download_window *dw)
downloads_in_progress--;
- if(dw->objects[OID_MAIN] != NULL) {
- DisposeObject(dw->objects[OID_MAIN]);
+ if(dw->objects[OID_D_MAIN] != NULL) {
+ DisposeObject(dw->objects[OID_D_MAIN]);
}
ami_gui_win_list_remove(dw);
@@ -378,14 +386,14 @@ static BOOL ami_download_window_event(void *w)
if(dw == NULL) return FALSE; /* We may not have a real window */
- while((result = RA_HandleInput(dw->objects[OID_MAIN], &code)) != WMHI_LASTMSG)
+ while((result = RA_HandleInput(dw->objects[OID_D_MAIN], &code)) != WMHI_LASTMSG)
{
switch(result & WMHI_CLASSMASK) // class
{
case WMHI_GADGETUP:
switch(result & WMHI_GADGETMASK)
{
- case GID_CANCEL:
+ case GID_D_CANCEL:
ami_download_window_abort(dw);
return TRUE;
break;
@@ -426,19 +434,19 @@ gui_window_save_link(struct gui_window *g, nsurl *url, const char *title)
linkname = ASPrintf("Link_to_%s",FilePart(nsurl_access(url)));
if(AslRequestTags(savereq,
- ASLFR_Window, g->shared->win,
+ ASLFR_Window, ami_gui_get_window(g),
ASLFR_SleepWindow, TRUE,
ASLFR_TitleText,messages_get("NetSurf"),
- ASLFR_Screen,scrn,
- ASLFR_InitialFile,linkname,
+ ASLFR_Screen, ami_gui_get_screen(),
+ ASLFR_InitialFile, linkname,
TAG_DONE))
{
strlcpy(fname, savereq->fr_Drawer, 1024);
AddPart(fname,savereq->fr_File,1024);
- ami_set_pointer(g->shared, GUI_POINTER_WAIT, false);
+ ami_set_pointer(ami_gui_get_gui_window_2(g), GUI_POINTER_WAIT, false);
- if(ami_download_check_overwrite(fname, g->shared->win, 0))
+ if(ami_download_check_overwrite(fname, ami_gui_get_window(g), 0))
{
BPTR fh;
@@ -465,7 +473,7 @@ gui_window_save_link(struct gui_window *g, nsurl *url, const char *title)
}
FreeVec(linkname);
}
- ami_reset_pointer(g->shared);
+ ami_reset_pointer(ami_gui_get_gui_window_2(g));
}
return NSERROR_OK;
}
diff --git a/frontends/amiga/drag.c b/frontends/amiga/drag.c
index ec0ee3c6a..907d8f865 100644
--- a/frontends/amiga/drag.c
+++ b/frontends/amiga/drag.c
@@ -24,7 +24,6 @@
#include <proto/intuition.h>
#include <proto/utility.h>
#include <proto/icon.h>
-#include <proto/layers.h>
#include <graphics/blitattr.h>
#include <workbench/icon.h>
@@ -89,7 +88,7 @@ void gui_drag_save_object(struct gui_window *g, struct hlcache_handle *c,
break;
}
- ami_drag_icon_show(g->shared->win, filetype);
+ ami_drag_icon_show(ami_gui_get_window(g), filetype);
drag_save_data = c;
drag_save_gui = g;
@@ -98,7 +97,7 @@ void gui_drag_save_object(struct gui_window *g, struct hlcache_handle *c,
void gui_drag_save_selection(struct gui_window *g, const char *selection)
{
- ami_drag_icon_show(g->shared->win, "ascii");
+ ami_drag_icon_show(ami_gui_get_window(g), "ascii");
ami_autoscroll = true;
drag_save_data = g;
@@ -109,6 +108,7 @@ void ami_drag_save(struct Window *win)
{
ULONG which = WBO_NONE, type;
char path[1025], dpath[1025];
+ struct Screen *scrn = ami_gui_get_screen();
path[0] = 0; /* ensure path is terminated */
@@ -134,7 +134,7 @@ void ami_drag_save(struct Window *win)
{
if(drag_save == GUI_SAVE_TEXT_SELECTION)
ami_drag_selection((struct gui_window *)drag_save_data);
- else DisplayBeep(scrn);
+ else ami_gui_beep();
drag_save = 0;
drag_save_data = NULL;
@@ -143,7 +143,7 @@ void ami_drag_save(struct Window *win)
if(path[0] == '\0')
{
- DisplayBeep(scrn);
+ ami_gui_beep();
drag_save = 0;
drag_save_data = NULL;
return;
@@ -166,7 +166,7 @@ void ami_drag_save(struct Window *win)
case GUI_SAVE_TEXT_SELECTION: // selection
AddPart(path,"netsurf_text_selection",1024);
struct gui_window *g = (struct gui_window *) drag_save_data;
- ami_file_save(AMINS_SAVE_SELECTION, path, win, NULL, NULL, g->bw);
+ ami_file_save(AMINS_SAVE_SELECTION, path, win, NULL, NULL, ami_gui_get_browser_window(g));
break;
case GUI_SAVE_COMPLETE:
@@ -174,7 +174,7 @@ void ami_drag_save(struct Window *win)
struct hlcache_handle *c = drag_save_data;
AddPart(path, content_get_title(c), 1024);
- ami_file_save(AMINS_SAVE_COMPLETE, path, win, c, drag_save_gui->favicon, NULL);
+ ami_file_save(AMINS_SAVE_COMPLETE, path, win, c, ami_gui_get_favicon(drag_save_gui), NULL);
}
break;
@@ -204,7 +204,7 @@ void ami_drag_icon_show(struct Window *win, const char *type)
struct DiskObject *dobj = NULL;
ULONG width, height;
int deftype = WBPROJECT;
-
+ struct Screen *scrn = ami_gui_get_screen();
drag_in_progress = TRUE;
if(nsoption_bool(drag_save_icons) == false)
@@ -255,6 +255,7 @@ void ami_drag_icon_show(struct Window *win, const char *type)
bool ami_drag_icon_move(void)
{
if(drag_icon == NULL) return FALSE;
+ struct Screen *scrn = ami_gui_get_screen();
ChangeWindowBox(drag_icon, scrn->MouseX - (drag_icon_width / 2),
scrn->MouseY - (drag_icon_height / 2),
@@ -288,44 +289,9 @@ bool ami_drag_has_data(void)
else return false;
}
-static void *ami_find_gwin_by_id(struct Window *win, uint32 type)
-{
- struct nsObject *node, *nnode;
- struct gui_window_2 *gwin;
-
- if(!IsMinListEmpty(window_list))
- {
- node = (struct nsObject *)GetHead((struct List *)window_list);
-
- do
- {
- nnode=(struct nsObject *)GetSucc((struct Node *)node);
-
- if(node->Type == type)
- {
- gwin = node->objstruct;
- if(win == gwin->win) return gwin;
- }
- } while((node = nnode));
- }
- return NULL;
-}
-
-void *ami_window_at_pointer(int type)
-{
- struct Layer *layer;
-
- LockLayerInfo(&scrn->LayerInfo);
-
- layer = WhichLayer(&scrn->LayerInfo, scrn->MouseX, scrn->MouseY);
-
- UnlockLayerInfo(&scrn->LayerInfo);
-
- if(layer) return ami_find_gwin_by_id(layer->Window, type);
- else return NULL;
-}
-
#else
+#include <stddef.h>
+
#include "utils/errors.h"
#include "amiga/drag.h"
@@ -364,10 +330,5 @@ bool ami_drag_has_data(void)
{
return false;
}
-
-void *ami_window_at_pointer(int type)
-{
- return NULL;
-}
#endif
diff --git a/frontends/amiga/drag.h b/frontends/amiga/drag.h
index c0b040f72..1a546682c 100644
--- a/frontends/amiga/drag.h
+++ b/frontends/amiga/drag.h
@@ -35,8 +35,5 @@ void ami_drag_icon_close(struct Window *win);
bool ami_drag_icon_move(void);
BOOL ami_drag_in_progress(void);
bool ami_drag_has_data(void);
-
-void *ami_window_at_pointer(int type);
-
#endif
diff --git a/frontends/amiga/dt_anim.c b/frontends/amiga/dt_anim.c
index bd049206c..1162d7214 100644
--- a/frontends/amiga/dt_anim.c
+++ b/frontends/amiga/dt_anim.c
@@ -40,7 +40,9 @@
#include "netsurf/plotters.h"
#include "netsurf/bitmap.h"
#include "netsurf/content.h"
+#include "content/content.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
#include "content/llcache.h"
#include "amiga/bitmap.h"
@@ -72,9 +74,9 @@ static void amiga_dt_anim_destroy(struct content *c);
static bool amiga_dt_anim_redraw(struct content *c,
struct content_redraw_data *data, const struct rect *clip,
const struct redraw_context *ctx);
-static void amiga_dt_anim_open(struct content *c, struct browser_window *bw,
+static nserror amiga_dt_anim_open(struct content *c, struct browser_window *bw,
struct content *page, struct object_params *params);
-static void amiga_dt_anim_close(struct content *c);
+static nserror amiga_dt_anim_close(struct content *c);
static nserror amiga_dt_anim_clone(const struct content *old, struct content **newc);
static content_type amiga_dt_anim_content_type(void);
@@ -167,15 +169,15 @@ bool amiga_dt_anim_convert(struct content *c)
amiga_dt_anim_content *plugin = (amiga_dt_anim_content *) c;
union content_msg_data msg_data;
int width, height;
- const uint8 *data;
+ const uint8_t *data;
+ size_t size;
UBYTE *bm_buffer;
- ULONG size;
struct BitMapHeader *bmh;
- unsigned int bm_flags = BITMAP_NEW | BITMAP_OPAQUE;
+ unsigned int bm_flags = BITMAP_OPAQUE;
struct adtFrame adt_frame;
APTR clut;
- data = (uint8 *)content__get_source_data(c, &size);
+ data = content__get_source_data(c, &size);
if((plugin->dto = NewDTObject(NULL,
DTA_SourceType, DTST_MEMORY,
@@ -189,7 +191,8 @@ bool amiga_dt_anim_convert(struct content *c)
plugin->bitmap = amiga_bitmap_create(width, height, bm_flags);
if (!plugin->bitmap) {
- msg_data.error = messages_get("NoMemory");
+ msg_data.errordata.errorcode = NSERROR_NOMEM;
+ msg_data.errordata.errormsg = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
return false;
}
@@ -287,18 +290,18 @@ bool amiga_dt_anim_redraw(struct content *c,
* \param box box containing c, or 0 if not an object
* \param params object parameters, or 0 if not an object
*/
-void amiga_dt_anim_open(struct content *c, struct browser_window *bw,
+nserror amiga_dt_anim_open(struct content *c, struct browser_window *bw,
struct content *page, struct object_params *params)
{
NSLOG(netsurf, INFO, "amiga_dt_anim_open");
- return;
+ return NSERROR_OK;
}
-void amiga_dt_anim_close(struct content *c)
+nserror amiga_dt_anim_close(struct content *c)
{
NSLOG(netsurf, INFO, "amiga_dt_anim_close");
- return;
+ return NSERROR_OK;
}
void amiga_dt_anim_reformat(struct content *c, int width, int height)
diff --git a/frontends/amiga/dt_picture.c b/frontends/amiga/dt_picture.c
index 88ce1c834..e13790d5c 100644
--- a/frontends/amiga/dt_picture.c
+++ b/frontends/amiga/dt_picture.c
@@ -25,6 +25,7 @@
#include <stdbool.h>
#include <stdlib.h>
+#include <string.h>
#include <proto/datatypes.h>
#include <proto/dos.h>
#include <proto/intuition.h>
@@ -36,7 +37,9 @@
#include "netsurf/plotters.h"
#include "netsurf/bitmap.h"
#include "content/llcache.h"
+#include "content/content.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
#include "content/handlers/image/image_cache.h"
#include "amiga/bitmap.h"
@@ -131,11 +134,11 @@ nserror amiga_dt_picture_create(const content_handler *handler,
static Object *amiga_dt_picture_newdtobject(struct amiga_dt_picture_content *adt)
{
- const uint8 *data;
- ULONG size;
+ const uint8_t *data;
+ size_t size;
if(adt->dto == NULL) {
- data = (uint8 *)content__get_source_data((struct content *)adt, &size);
+ data = content__get_source_data((struct content *)adt, &size);
adt->dto = NewDTObject(NULL,
DTA_SourceType, DTST_MEMORY,
@@ -152,12 +155,12 @@ static Object *amiga_dt_picture_newdtobject(struct amiga_dt_picture_content *adt
static char *amiga_dt_picture_datatype(struct content *c)
{
- const uint8 *data;
- ULONG size;
+ const uint8_t *data;
+ size_t size;
struct DataType *dt;
char *filetype = NULL;
- data = (uint8 *)content__get_source_data(c, &size);
+ data = content__get_source_data(c, &size);
if((dt = ObtainDataType(DTST_MEMORY, NULL,
DTA_SourceAddress, data,
@@ -184,9 +187,10 @@ static struct bitmap *amiga_dt_picture_cache_convert(struct content *c)
if((dto = amiga_dt_picture_newdtobject(adt)))
{
- bitmap = amiga_bitmap_create(c->width, c->height, BITMAP_NEW);
+ bitmap = amiga_bitmap_create(c->width, c->height, BITMAP_NONE);
if (!bitmap) {
- msg_data.error = messages_get("NoMemory");
+ msg_data.errordata.errorcode = NSERROR_NOMEM;
+ msg_data.errordata.errormsg = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
return NULL;
}
@@ -198,7 +202,7 @@ static struct bitmap *amiga_dt_picture_cache_convert(struct content *c)
amiga_bitmap_get_rowstride(bitmap),
0, 0, c->width, c->height);
- amiga_bitmap_set_opaque(bitmap, amiga_bitmap_test_opaque(bitmap));
+ amiga_bitmap_set_opaque(bitmap, bitmap_test_opaque(bitmap));
DisposeDTObject(dto);
adt->dto = NULL;
diff --git a/frontends/amiga/dt_sound.c b/frontends/amiga/dt_sound.c
index e0f48da83..16b4f7c62 100644
--- a/frontends/amiga/dt_sound.c
+++ b/frontends/amiga/dt_sound.c
@@ -23,6 +23,8 @@
#ifdef WITH_AMIGA_DATATYPES
#include "amiga/os3support.h"
+#include <string.h>
+
#include <proto/datatypes.h>
#include <proto/dos.h>
#include <proto/intuition.h>
@@ -33,9 +35,10 @@
#include "utils/messages.h"
#include "netsurf/plotters.h"
#include "netsurf/content.h"
-#include "render/box.h"
+#include "html/box.h"
#include "content/llcache.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
#include "amiga/filetype.h"
#include "amiga/datatypes.h"
@@ -57,7 +60,7 @@ static void amiga_dt_sound_destroy(struct content *c);
static bool amiga_dt_sound_redraw(struct content *c,
struct content_redraw_data *data, const struct rect *clip,
const struct redraw_context *ctx);
-static void amiga_dt_sound_open(struct content *c, struct browser_window *bw,
+static nserror amiga_dt_sound_open(struct content *c, struct browser_window *bw,
struct content *page, struct object_params *params);
static nserror amiga_dt_sound_clone(const struct content *old, struct content **newc);
static content_type amiga_dt_sound_content_type(void);
@@ -150,10 +153,10 @@ bool amiga_dt_sound_convert(struct content *c)
amiga_dt_sound_content *plugin = (amiga_dt_sound_content *) c;
int width = 50, height = 50;
- const uint8 *data;
- ULONG size;
+ const uint8_t *data;
+ size_t size;
- data = (uint8 *)content__get_source_data(c, &size);
+ data = content__get_source_data(c, &size);
plugin->dto = NewDTObject(NULL,
DTA_SourceType, DTST_MEMORY,
@@ -195,7 +198,7 @@ bool amiga_dt_sound_redraw(struct content *c,
.fill_type = PLOT_OP_TYPE_SOLID,
.fill_colour = 0xffffff,
.stroke_colour = 0x000000,
- .stroke_width = 1,
+ .stroke_width = plot_style_int_to_fixed(1),
};
struct rect rect;
@@ -220,7 +223,7 @@ bool amiga_dt_sound_redraw(struct content *c,
}
-void amiga_dt_sound_open(struct content *c, struct browser_window *bw,
+nserror amiga_dt_sound_open(struct content *c, struct browser_window *bw,
struct content *page, struct object_params *params)
{
amiga_dt_sound_content *plugin = (amiga_dt_sound_content *) c;
@@ -247,7 +250,7 @@ void amiga_dt_sound_open(struct content *c, struct browser_window *bw,
if(plugin->dto && (plugin->immediate == true))
amiga_dt_sound_play(plugin->dto);
- return;
+ return NSERROR_OK;
}
diff --git a/frontends/amiga/file.c b/frontends/amiga/file.c
index 0fd43781d..79acb1a21 100644
--- a/frontends/amiga/file.c
+++ b/frontends/amiga/file.c
@@ -22,6 +22,8 @@
#include <proto/icon.h>
#include <workbench/icon.h>
+#include <string.h>
+
#include "utils/utils.h"
#include "utils/nsoption.h"
#include "utils/file.h"
@@ -29,6 +31,7 @@
#include "utils/nsurl.h"
#include "netsurf/browser_window.h"
#include "netsurf/content.h"
+#include "content/content_factory.h"
#include "desktop/save_complete.h"
#include "desktop/save_pdf.h"
#include "desktop/save_text.h"
@@ -84,9 +87,9 @@ void ami_file_open(struct gui_window_2 *gwin)
if(AslRequestTags(filereq,
ASLFR_TitleText, messages_get("NetSurf"),
- ASLFR_Window, gwin->win,
+ ASLFR_Window, ami_gui2_get_window(gwin),
ASLFR_SleepWindow, TRUE,
- ASLFR_Screen, scrn,
+ ASLFR_Screen, ami_gui_get_screen(),
ASLFR_DoSaveMode, FALSE,
ASLFR_RejectIcons, TRUE,
ASLFR_FilterFunc, &aslhookfunc,
@@ -100,7 +103,7 @@ void ami_file_open(struct gui_window_2 *gwin)
if (netsurf_path_to_nsurl(temp, &url) != NSERROR_OK) {
amiga_warn_user("NoMemory", 0);
} else {
- browser_window_navigate(gwin->gw->bw,
+ browser_window_navigate(ami_gui2_get_browser_window(gwin),
url,
NULL,
BW_NAVIGATE_HISTORY,
@@ -146,8 +149,9 @@ void ami_file_save(int type, char *fname, struct Window *win,
struct browser_window *bw)
{
BPTR lock, fh;
- const char *source_data;
- ULONG source_size;
+ const uint8_t *source_data;
+ char *selection;
+ size_t source_size;
struct bitmap *bm;
ami_update_pointer(win, GUI_POINTER_WAIT);
@@ -155,7 +159,8 @@ void ami_file_save(int type, char *fname, struct Window *win,
if(ami_download_check_overwrite(fname, win, 0)) {
switch(type) {
case AMINS_SAVE_SOURCE:
- if((source_data = content_get_source_data(object, &source_size))) {
+ source_data = content_get_source_data(object, &source_size);
+ if(source_data) {
BPTR fh;
if((fh = FOpen(fname, MODE_NEWFILE,0))) {
FWrite(fh, source_data, 1, source_size);
@@ -197,12 +202,17 @@ void ami_file_save(int type, char *fname, struct Window *win,
break;
case AMINS_SAVE_SELECTION:
- if((source_data = browser_window_get_selection(bw))) {
- if((fh = FOpen(fname, MODE_NEWFILE,0))) {
- FWrite(fh, source_data, 1, strlen(source_data));
+ selection = browser_window_get_selection(bw);
+ if(selection) {
+ fh = FOpen(fname, MODE_NEWFILE,0);
+ if (fh) {
+ FWrite(fh,
+ selection,
+ 1,
+ strlen(selection));
FClose(fh);
}
- free((void *)source_data);
+ free(selection);
}
break;
}
@@ -250,17 +260,18 @@ void ami_file_save_req(int type, struct gui_window_2 *gwin,
}
if(AslRequestTags(savereq,
- ASLFR_Window, gwin->win,
+ ASLFR_Window, ami_gui2_get_window(gwin),
ASLFR_SleepWindow, TRUE,
ASLFR_TitleText, messages_get("NetSurf"),
- ASLFR_Screen, scrn,
+ ASLFR_Screen, ami_gui_get_screen(),
ASLFR_InitialFile, fname_with_ext ? fname_with_ext : "",
TAG_DONE))
{
strlcpy(fname, savereq->fr_Drawer, 1024);
AddPart(fname, savereq->fr_File, 1024);
- ami_file_save(type, fname, gwin->win, object, gwin->gw->favicon, gwin->gw->bw);
+ ami_file_save(type, fname, ami_gui2_get_window(gwin), object,
+ ami_gui_get_favicon(ami_gui2_get_gui_window(gwin)), ami_gui2_get_browser_window(gwin));
}
if(fname) free(fname);
diff --git a/frontends/amiga/font.c b/frontends/amiga/font.c
index e69ff55f0..65e791416 100644
--- a/frontends/amiga/font.c
+++ b/frontends/amiga/font.c
@@ -24,7 +24,7 @@
#include "utils/log.h"
#include "utils/nsoption.h"
-#include "netsurf/browser_window.h"
+#include "netsurf/browser.h"
#include "netsurf/layout.h"
#include "amiga/font.h"
diff --git a/frontends/amiga/font_bullet.c b/frontends/amiga/font_bullet.c
index c8ad34c04..43f7b9488 100644
--- a/frontends/amiga/font_bullet.c
+++ b/frontends/amiga/font_bullet.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 - 2016 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ * Copyright 2008 - 2019 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -63,7 +63,7 @@
#define NSA_VALUE_SHEARSIN (1 << 14)
#define NSA_VALUE_SHEARCOS (1 << 16)
-#define NSA_FONT_EMWIDTH(s) (s / FONT_SIZE_SCALE) * (ami_font_dpi_get_xdpi() / 72.0)
+#define NSA_FONT_EMWIDTH(s) (s / PLOT_STYLE_SCALE) * (ami_font_dpi_get_xdpi() / 72.0)
const uint16 sc_table[] = {
0x0061, 0x1D00, /* a */
@@ -82,7 +82,7 @@ const uint16 sc_table[] = {
0x006E, 0x0274, /* n */
0x006F, 0x1D0F, /* o */
0x0070, 0x1D18, /* p */
- 0x0071, 0xA7EE, /* q (proposed) (Adobe codepoint 0xF771) */
+ 0x0071, 0xA7AF, /* q */
0x0072, 0x0280, /* r */
0x0073, 0xA731, /* s */
0x0074, 0x1D1B, /* t */
@@ -169,7 +169,9 @@ static nserror amiga_nsfont_width(const plot_font_style_t *fstyle,
{
*width = ami_font_unicode_width(string, length, fstyle, 0, 0, false);
- if(*width <= 0) *width == length; // fudge
+ if(*width <= 0) {
+ *width = length; /* fudge */
+ }
return NSERROR_OK;
}
@@ -347,6 +349,11 @@ static nserror amiga_nsfont_split(const plot_font_style_t *fstyle,
*/
static struct ami_font_cache_node *ami_font_open(const char *font, bool critical)
{
+ if(font == NULL) {
+ NSLOG(netsurf, INFO, "Requested NULL font");
+ return NULL;
+ }
+
struct ami_font_cache_node *nodedata = ami_font_cache_locate(font);
if(nodedata) return nodedata;
@@ -512,7 +519,7 @@ static struct OutlineFont *ami_open_outline_font(const plot_font_style_t *fstyle
}
/* Scale to 16.16 fixed point */
- ysize = fstyle->size * ((1 << 16) / FONT_SIZE_SCALE);
+ ysize = fstyle->size * ((1 << 16) / PLOT_STYLE_SCALE);
if(designed_node == NULL) {
ofont = node->font;
@@ -547,6 +554,7 @@ static inline int32 ami_font_plot_glyph(struct OutlineFont *ofont, struct RastPo
FIXED kern = 0;
ULONG glyphmaptag;
ULONG template_type;
+ bool skip_c2 = false;
uint32 long_char_1 = 0, long_char_2 = 0;
#ifndef __amigaos4__
struct BulletBase *BulletBase = ofont->BulletBase;
@@ -564,6 +572,8 @@ static inline int32 ami_font_plot_glyph(struct OutlineFont *ofont, struct RastPo
}
#endif
+ if (*char2 < 0x0020) skip_c2 = true;
+
#ifdef __amigaos4__
if(__builtin_expect(aa == true, 1)) {
glyphmaptag = OT_GlyphMap8Bit;
@@ -626,7 +636,7 @@ static inline int32 ami_font_plot_glyph(struct OutlineFont *ofont, struct RastPo
kern = 0;
- if(*char2) EObtainInfo(AMI_OFONT_ENGINE,
+ if((*char2) && (!skip_c2)) EObtainInfo(AMI_OFONT_ENGINE,
OT_TextKernPair, &kern,
TAG_END);
@@ -636,7 +646,7 @@ static inline int32 ami_font_plot_glyph(struct OutlineFont *ofont, struct RastPo
glyphmaptag, glyph,
TAG_END);
- if(*char2) EReleaseInfo(AMI_OFONT_ENGINE,
+ if((*char2) && (!skip_c2)) EReleaseInfo(AMI_OFONT_ENGINE,
OT_TextKernPair, kern,
TAG_END);
}
diff --git a/frontends/amiga/font_diskfont.c b/frontends/amiga/font_diskfont.c
index 2da3f0038..be1b89194 100644
--- a/frontends/amiga/font_diskfont.c
+++ b/frontends/amiga/font_diskfont.c
@@ -97,10 +97,13 @@ static struct TextFont *ami_font_bm_open(struct RastPort *rp, const plot_font_st
snprintf(font, MAX_FONT_NAME_SIZE, "%s.font", fontname);
tattr.ta_Name = font;
- tattr.ta_YSize = fstyle->size / FONT_SIZE_SCALE;
+ tattr.ta_YSize = fstyle->size / PLOT_STYLE_SCALE;
NSLOG(netsurf, INFO, "font: %s/%d", tattr.ta_Name, tattr.ta_YSize);
- if(prev_font != NULL) CloseFont(prev_font);
+ if(prev_font != NULL) {
+ CloseFont(prev_font);
+ prev_font = NULL;
+ }
if((bmfont = OpenDiskFont(&tattr))) {
SetRPAttrs(rp, RPTAG_Font, bmfont, TAG_DONE);
@@ -300,7 +303,14 @@ void ami_font_diskfont_init(void)
void ami_font_diskfont_fini(void)
{
- if(prev_font != NULL) CloseFont(prev_font);
- if(prev_fstyle != NULL) free(prev_fstyle);
+ if(prev_font != NULL) {
+ CloseFont(prev_font);
+ prev_font = NULL;
+ }
+
+ if(prev_fstyle != NULL) {
+ free(prev_fstyle);
+ prev_fstyle = NULL;
+ }
}
diff --git a/frontends/amiga/font_scan.c b/frontends/amiga/font_scan.c
index cb37f97fa..3fa71f737 100644
--- a/frontends/amiga/font_scan.c
+++ b/frontends/amiga/font_scan.c
@@ -114,7 +114,7 @@ static struct ami_font_scan_window *ami_font_scan_gui_open(int32 fonts)
WA_DragBar, TRUE,
WA_CloseGadget, FALSE,
WA_SizeGadget, TRUE,
- WA_PubScreen, scrn,
+ WA_PubScreen, ami_gui_get_screen(),
WA_BusyPointer, TRUE,
WA_Width, 400,
WINDOW_UserData, fsw,
diff --git a/frontends/amiga/gui.c b/frontends/amiga/gui.c
index e337ede0c..8eb34fb92 100644
--- a/frontends/amiga/gui.c
+++ b/frontends/amiga/gui.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2016 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ * Copyright 2008-2020 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -36,10 +36,17 @@
#include <proto/icon.h>
#include <proto/intuition.h>
#include <proto/keymap.h>
+#include <proto/layers.h>
#include <proto/locale.h>
#include <proto/utility.h>
#include <proto/wb.h>
+#ifdef WITH_AMISSL
+/* AmiSSL needs everything to use bsdsocket.library directly to avoid problems */
+#include <proto/bsdsocket.h>
+#define waitselect WaitSelect
+#endif
+
/* Other OS includes */
#include <datatypes/textclass.h>
#include <devices/inputevent.h>
@@ -65,6 +72,7 @@
#include <proto/clicktab.h>
#include <proto/label.h>
#include <proto/layout.h>
+#include <proto/listbrowser.h>
#include <proto/scroller.h>
#include <proto/space.h>
#include <proto/speedbar.h>
@@ -76,6 +84,7 @@
#include <gadgets/chooser.h>
#include <gadgets/clicktab.h>
#include <gadgets/layout.h>
+#include <gadgets/listbrowser.h>
#include <gadgets/scroller.h>
#include <gadgets/space.h>
#include <gadgets/speedbar.h>
@@ -139,11 +148,11 @@
#include "amiga/icon.h"
#include "amiga/launch.h"
#include "amiga/libs.h"
-#include "amiga/login.h"
#include "amiga/memory.h"
#include "amiga/menu.h"
#include "amiga/misc.h"
#include "amiga/nsoption.h"
+#include "amiga/pageinfo.h"
#include "amiga/plotters.h"
#include "amiga/plugin_hack.h"
#include "amiga/print.h"
@@ -152,7 +161,6 @@
#include "amiga/selectmenu.h"
#include "amiga/theme.h"
#include "amiga/utf8.h"
-#include "amiga/sslcert.h"
#define AMINS_SCROLLERPEN NUMDRIPENS
#define NSA_KBD_SCROLL_PX 10
@@ -187,16 +195,137 @@
extern struct gui_utf8_table *amiga_utf8_table;
+enum
+{
+ OID_MAIN = 0,
+ OID_VSCROLL,
+ OID_HSCROLL,
+ GID_MAIN,
+ GID_TABLAYOUT,
+ GID_BROWSER,
+ GID_STATUS,
+ GID_URL,
+ GID_ICON,
+ GID_STOP,
+ GID_RELOAD,
+ GID_HOME,
+ GID_BACK,
+ GID_FORWARD,
+ GID_THROBBER,
+ GID_SEARCH_ICON,
+ GID_PAGEINFO,
+ GID_PAGEINFO_INSECURE_BM,
+ GID_PAGEINFO_INTERNAL_BM,
+ GID_PAGEINFO_LOCAL_BM,
+ GID_PAGEINFO_SECURE_BM,
+ GID_PAGEINFO_WARNING_BM,
+ GID_FAVE,
+ GID_FAVE_ADD,
+ GID_FAVE_RMV,
+ GID_CLOSETAB,
+ GID_CLOSETAB_BM,
+ GID_ADDTAB,
+ GID_ADDTAB_BM,
+ GID_TABS,
+ GID_TABS_FLAG,
+ GID_SEARCHSTRING,
+ GID_TOOLBARLAYOUT,
+ GID_HOTLIST,
+ GID_HOTLISTLAYOUT,
+ GID_HOTLISTSEPBAR,
+ GID_HSCROLL,
+ GID_HSCROLLLAYOUT,
+ GID_VSCROLL,
+ GID_VSCROLLLAYOUT,
+ GID_LOGLAYOUT,
+ GID_LOG,
+ GID_LAST
+};
+
+struct gui_window_2 {
+ struct ami_generic_window w;
+ struct Window *win;
+ Object *restrict objects[GID_LAST];
+ struct gui_window *gw; /* currently-displayed gui_window */
+ bool redraw_required;
+ int throbber_frame;
+ struct List tab_list;
+ ULONG tabs;
+ ULONG next_tab;
+ struct Node *last_new_tab;
+ struct Hook scrollerhook;
+ browser_mouse_state mouse_state;
+ browser_mouse_state key_state;
+ ULONG throbber_update_count;
+ struct find_window *searchwin;
+ ULONG oldh;
+ ULONG oldv;
+ int temp;
+ bool redraw_scroll;
+ bool new_content;
+ struct ami_menu_data *menu_data[AMI_MENU_AREXX_MAX + 1]; /* only for GadTools menus */
+ ULONG hotlist_items;
+ Object *restrict hotlist_toolbar_lab[AMI_GUI_TOOLBAR_MAX];
+ struct List hotlist_toolbar_list;
+ struct List *web_search_list;
+ Object *search_bm;
+ char *restrict svbuffer;
+ char *restrict status;
+ char *restrict wintitle;
+ char *restrict helphints[GID_LAST];
+ browser_mouse_state prev_mouse_state;
+ struct timeval lastclick;
+ struct AppIcon *appicon; /* iconify appicon */
+ struct DiskObject *dobj; /* iconify appicon */
+ struct Hook favicon_hook;
+ struct Hook throbber_hook;
+ struct Hook browser_hook;
+ struct Hook *ctxmenu_hook;
+ Object *restrict history_ctxmenu[2];
+ Object *clicktab_ctxmenu;
+ gui_drag_type drag_op;
+ struct IBox *ptr_lock;
+ struct AppWindow *appwin;
+ struct MinList *shared_pens;
+ gui_pointer_shape mouse_pointer;
+ struct Menu *imenu; /* Intuition menu */
+ bool closed; /* Window has been closed (via menu) */
+};
+
+struct gui_window
+{
+ struct gui_window_2 *shared;
+ int tab;
+ struct Node *tab_node;
+ int c_x; /* Caret X posn */
+ int c_y; /* Caret Y posn */
+ int c_w; /* Caret width */
+ int c_h; /* Caret height */
+ int c_h_temp;
+ int scrollx;
+ int scrolly;
+ struct ami_history_local_window *hw;
+ struct List dllist;
+ struct hlcache_handle *favicon;
+ bool throbbing;
+ char *tabtitle;
+ APTR deferred_rects_pool;
+ struct MinList *deferred_rects;
+ struct browser_window *bw;
+ struct ColumnInfo *logcolumns;
+ struct List loglist;
+};
+
struct ami_gui_tb_userdata {
struct List *sblist;
struct gui_window_2 *gw;
int items;
};
-struct MinList *window_list = NULL;
-struct Screen *scrn = NULL;
-struct MsgPort *sport = NULL;
-struct gui_window *cur_gw = NULL;
+static struct MinList *window_list = NULL;
+static struct Screen *scrn = NULL;
+static struct MsgPort *sport = NULL;
+static struct gui_window *cur_gw = NULL;
static bool ami_quit = false;
@@ -231,17 +360,15 @@ static const __attribute__((used)) char *stack_cookie = "\0$STACK:196608\0";
const char * const versvn;
const char * const verdate;
-void ami_switch_tab(struct gui_window_2 *gwin, bool redraw);
-void ami_change_tab(struct gui_window_2 *gwin, int direction);
-void ami_get_hscroll_pos(struct gui_window_2 *gwin, ULONG *xs);
-void ami_get_vscroll_pos(struct gui_window_2 *gwin, ULONG *ys);
-void ami_quit_netsurf_delayed(void);
-Object *ami_gui_splash_open(void);
-void ami_gui_splash_close(Object *win_obj);
-HOOKF(uint32, ami_set_favicon_render_hook, APTR, space, struct gpRender *);
-HOOKF(uint32, ami_set_throbber_render_hook, APTR, space, struct gpRender *);
-bool ami_gui_map_filename(char **remapped, const char *restrict path, const char *restrict file,
- const char *restrict map);
+static void ami_switch_tab(struct gui_window_2 *gwin, bool redraw);
+static void ami_change_tab(struct gui_window_2 *gwin, int direction);
+static void ami_get_hscroll_pos(struct gui_window_2 *gwin, ULONG *xs);
+static void ami_get_vscroll_pos(struct gui_window_2 *gwin, ULONG *ys);
+static void ami_quit_netsurf_delayed(void);
+static Object *ami_gui_splash_open(void);
+static void ami_gui_splash_close(Object *win_obj);
+static bool ami_gui_map_filename(char **remapped, const char *restrict path,
+ const char *restrict file, const char *restrict map);
static void ami_gui_window_update_box_deferred(struct gui_window *g, bool draw);
static void ami_do_redraw(struct gui_window_2 *g);
static void ami_schedule_redraw_remove(struct gui_window_2 *gwin);
@@ -250,8 +377,10 @@ static bool gui_window_get_scroll(struct gui_window *g, int *restrict sx, int *r
static nserror gui_window_set_scroll(struct gui_window *g, const struct rect *rect);
static void gui_window_remove_caret(struct gui_window *g);
static void gui_window_place_caret(struct gui_window *g, int x, int y, int height, const struct rect *clip);
-//static void amiga_window_invalidate_area(struct gui_window *g, const struct rect *restrict rect);
+HOOKF(uint32, ami_set_favicon_render_hook, APTR, space, struct gpRender *);
+HOOKF(uint32, ami_set_throbber_render_hook, APTR, space, struct gpRender *);
+HOOKF(uint32, ami_gui_browser_render_hook, APTR, space, struct gpRender *);
/* accessors for default options - user option is updated if it is set as per default */
#define nsoption_default_set_int(OPTION, VALUE) \
@@ -259,6 +388,315 @@ static void gui_window_place_caret(struct gui_window *g, int x, int y, int heigh
nsoptions[NSOPTION_##OPTION].value.i = VALUE; \
nsoptions_default[NSOPTION_##OPTION].value.i = VALUE
+/* Functions documented in gui.h */
+struct MsgPort *ami_gui_get_shared_msgport(void)
+{
+ assert(sport != NULL);
+ return sport;
+}
+
+struct gui_window *ami_gui_get_active_gw(void)
+{
+ return cur_gw;
+}
+
+struct Screen *ami_gui_get_screen(void)
+{
+ return scrn;
+}
+
+struct MinList *ami_gui_get_window_list(void)
+{
+ assert(window_list != NULL);
+ return window_list;
+}
+
+void ami_gui_beep(void)
+{
+ DisplayBeep(scrn);
+}
+
+struct browser_window *ami_gui_get_browser_window(struct gui_window *gw)
+{
+ assert(gw != NULL);
+ return gw->bw;
+}
+
+struct browser_window *ami_gui2_get_browser_window(struct gui_window_2 *gwin)
+{
+ assert(gwin != NULL);
+ return ami_gui_get_browser_window(gwin->gw);
+}
+
+struct List *ami_gui_get_download_list(struct gui_window *gw)
+{
+ assert(gw != NULL);
+ return &gw->dllist;
+}
+
+struct gui_window_2 *ami_gui_get_gui_window_2(struct gui_window *gw)
+{
+ assert(gw != NULL);
+ return gw->shared;
+}
+
+struct gui_window *ami_gui2_get_gui_window(struct gui_window_2 *gwin)
+{
+ assert(gwin != NULL);
+ return gwin->gw;
+}
+
+const char *ami_gui_get_win_title(struct gui_window *gw)
+{
+ assert(gw != NULL);
+ assert(gw->shared != NULL);
+ return (const char *)gw->shared->wintitle;
+}
+
+const char *ami_gui_get_tab_title(struct gui_window *gw)
+{
+ assert(gw != NULL);
+ return (const char *)gw->tabtitle;
+}
+
+struct Node *ami_gui_get_tab_node(struct gui_window *gw)
+{
+ assert(gw != NULL);
+ return gw->tab_node;
+}
+
+ULONG ami_gui2_get_tabs(struct gui_window_2 *gwin)
+{
+ assert(gwin != NULL);
+ return gwin->tabs;
+}
+
+struct List *ami_gui2_get_tab_list(struct gui_window_2 *gwin)
+{
+ assert(gwin != NULL);
+ return &gwin->tab_list;
+}
+
+struct hlcache_handle *ami_gui_get_favicon(struct gui_window *gw)
+{
+ assert(gw != NULL);
+ return gw->favicon;
+}
+
+struct ami_history_local_window *ami_gui_get_history_window(struct gui_window *gw)
+{
+ assert(gw != NULL);
+ return gw->hw;
+}
+
+void ami_gui_set_history_window(struct gui_window *gw, struct ami_history_local_window *hw)
+{
+ assert(gw != NULL);
+ gw->hw = hw;
+}
+
+void ami_gui_set_find_window(struct gui_window *gw, struct find_window *fw)
+{
+ /* This needs to be in gui_window_2 as it is shared amongst tabs (I think),
+ * it just happens that the find code only knows of the gui_window
+ */
+ assert(gw != NULL);
+ assert(gw->shared != NULL);
+ gw->shared->searchwin = fw;
+}
+
+bool ami_gui_get_throbbing(struct gui_window *gw)
+{
+ assert(gw != NULL);
+ return gw->throbbing;
+}
+
+void ami_gui_set_throbbing(struct gui_window *gw, bool throbbing)
+{
+ assert(gw != NULL);
+ gw->throbbing = throbbing;
+}
+
+int ami_gui_get_throbber_frame(struct gui_window *gw)
+{
+ assert(gw != NULL);
+ assert(gw->shared != NULL);
+ return gw->shared->throbber_frame;
+}
+
+void ami_gui_set_throbber_frame(struct gui_window *gw, int frame)
+{
+ assert(gw != NULL);
+ assert(gw->shared != NULL);
+ gw->shared->throbber_frame = frame;
+}
+
+Object *ami_gui2_get_object(struct gui_window_2 *gwin, int object_type)
+{
+ ULONG obj = 0;
+
+ assert(gwin != NULL);
+
+ switch(object_type) {
+ case AMI_WIN_MAIN:
+ obj = OID_MAIN;
+ break;
+
+ case AMI_GAD_THROBBER:
+ obj = GID_THROBBER;
+ break;
+
+ case AMI_GAD_TABS:
+ obj = GID_TABS;
+ break;
+
+ case AMI_GAD_URL:
+ obj = GID_URL;
+ break;
+
+ case AMI_GAD_SEARCH:
+ obj = GID_SEARCHSTRING;
+ break;
+
+ default:
+ return NULL;
+ break;
+ }
+
+ return gwin->objects[obj];
+}
+
+
+struct Window *ami_gui2_get_window(struct gui_window_2 *gwin)
+{
+ assert(gwin != NULL);
+ return gwin->win;
+}
+
+struct Window *ami_gui_get_window(struct gui_window *gw)
+{
+ assert(gw != NULL);
+ return ami_gui2_get_window(gw->shared);
+}
+
+struct Menu *ami_gui_get_menu(struct gui_window *gw)
+{
+ assert(gw != NULL);
+ assert(gw->shared != NULL);
+ return gw->shared->imenu;
+}
+
+void ami_gui2_set_menu(struct gui_window_2 *gwin, struct Menu *menu)
+{
+ if(menu != NULL) {
+ gwin->imenu = menu;
+ } else {
+ ami_gui_menu_freemenus(gwin->imenu, gwin->menu_data);
+ }
+}
+
+struct ami_menu_data **ami_gui2_get_menu_data(struct gui_window_2 *gwin)
+{
+ assert(gwin != NULL);
+ return gwin->menu_data;
+}
+
+void ami_gui2_set_ctxmenu_history_tmp(struct gui_window_2 *gwin, int temp)
+{
+ assert(gwin != NULL);
+ gwin->temp = temp;
+}
+
+int ami_gui2_get_ctxmenu_history_tmp(struct gui_window_2 *gwin)
+{
+ assert(gwin != NULL);
+ return gwin->temp;
+}
+
+Object *ami_gui2_get_ctxmenu_history(struct gui_window_2 *gwin, ULONG direction)
+{
+ assert(gwin != NULL);
+ return gwin->history_ctxmenu[direction];
+}
+
+void ami_gui2_set_ctxmenu_history(struct gui_window_2 *gwin, ULONG direction, Object *ctx_hist)
+{
+ assert(gwin != NULL);
+ gwin->history_ctxmenu[direction] = ctx_hist;
+}
+
+void ami_gui2_set_closed(struct gui_window_2 *gwin, bool closed)
+{
+ assert(gwin != NULL);
+ gwin->closed = closed;
+}
+
+void ami_gui2_set_new_content(struct gui_window_2 *gwin, bool new_content)
+{
+ assert(gwin != NULL);
+ gwin->new_content = new_content;
+}
+
+/** undocumented, or internal, or documented elsewhere **/
+
+#ifdef __amigaos4__
+static void *ami_find_gwin_by_id(struct Window *win, uint32 type)
+{
+ struct nsObject *node, *nnode;
+ struct gui_window_2 *gwin;
+
+ if(!IsMinListEmpty(window_list))
+ {
+ node = (struct nsObject *)GetHead((struct List *)window_list);
+
+ do
+ {
+ nnode=(struct nsObject *)GetSucc((struct Node *)node);
+
+ if(node->Type == type)
+ {
+ gwin = node->objstruct;
+ if(win == ami_gui2_get_window(gwin)) return gwin;
+ }
+ } while((node = nnode));
+ }
+ return NULL;
+}
+
+void *ami_window_at_pointer(int type)
+{
+ struct Layer *layer;
+ struct Screen *scrn = ami_gui_get_screen();
+
+ LockLayerInfo(&scrn->LayerInfo);
+
+ layer = WhichLayer(&scrn->LayerInfo, scrn->MouseX, scrn->MouseY);
+
+ UnlockLayerInfo(&scrn->LayerInfo);
+
+ if(layer) return ami_find_gwin_by_id(layer->Window, type);
+ else return NULL;
+}
+#else
+/**\todo check if OS4 version of this function will build on OS3, even if it isn't called */
+void *ami_window_at_pointer(int type)
+{
+ return NULL;
+}
+#endif
+
+void ami_set_pointer(struct gui_window_2 *gwin, gui_pointer_shape shape, bool update)
+{
+ if(gwin->mouse_pointer == shape) return;
+ ami_update_pointer(ami_gui2_get_window(gwin), shape);
+ if(update == true) gwin->mouse_pointer = shape;
+}
+
+/* reset the mouse pointer back to what NetSurf last set it as */
+void ami_reset_pointer(struct gui_window_2 *gwin)
+{
+ ami_update_pointer(ami_gui2_get_window(gwin), gwin->mouse_pointer);
+}
STRPTR ami_locale_langs(int *codeset)
@@ -302,7 +740,7 @@ STRPTR ami_locale_langs(int *codeset)
return acceptlangs;
}
-bool ami_gui_map_filename(char **remapped, const char *restrict path,
+static bool ami_gui_map_filename(char **remapped, const char *restrict path,
const char *restrict file, const char *restrict map)
{
BPTR fh = 0;
@@ -657,6 +1095,7 @@ static nserror ami_set_options(struct nsoption_s *defaults)
const char *encname = (const char *)ObtainCharsetInfo(DFCS_NUMBER, codeset,
DFCS_MIMENAME);
nsoption_set_charp(local_charset, strdup(encname));
+ nsoption_set_int(local_codeset, codeset);
#else
nsoption_set_bool(download_notify, false);
nsoption_set_bool(font_antialiasing, false);
@@ -777,25 +1216,10 @@ static void ami_amiupdate(void)
static nsurl *gui_get_resource_url(const char *path)
{
char buf[1024];
- char path2[1024];
nsurl *url = NULL;
if(ami_locate_resource(buf, path) == false)
- {
- if((strncmp(path + strlen(path) - SLEN(".htm"), ".htm", SLEN(".htm")) == 0) ||
- (strncmp(path + strlen(path) - SLEN(".html"), ".html", SLEN(".html")) == 0))
- {
- /* Try with RISC OS HTML filetype, might work */
- strcpy(path2, path);
- strcat(path2, ",faf");
-
- if(ami_locate_resource(buf, path2) == false)
- {
- return NULL;
- }
- }
- else return NULL;
- }
+ return NULL;
netsurf_path_to_nsurl(buf, &url);
@@ -1037,6 +1461,10 @@ static void gui_init2(int argc, char** argv)
(nsoption_bool(startup_no_window) == false))
ami_openscreenfirst();
+ if(cli_force == true) {
+ notalreadyrunning = TRUE;
+ }
+
if(temp_homepage_url && notalreadyrunning) {
error = nsurl_create(temp_homepage_url, &url);
if (error == NSERROR_OK) {
@@ -1054,10 +1482,6 @@ static void gui_init2(int argc, char** argv)
temp_homepage_url = NULL;
}
- if(cli_force == true) {
- notalreadyrunning = TRUE;
- }
-
if(argc == 0) { // WB
struct WBStartup *WBenchMsg = (struct WBStartup *)argv;
struct WBArg *wbarg;
@@ -1359,6 +1783,7 @@ int ami_key_to_nskey(ULONG keycode, struct InputEvent *ie)
case RAWKEY_F8:
case RAWKEY_F9:
case RAWKEY_F10:
+ case RAWKEY_F12:
case RAWKEY_HELP:
// don't translate
nskey = keycode;
@@ -1461,9 +1886,6 @@ static bool ami_spacebox_to_ns_coords(struct gui_window_2 *gwin,
int ns_x = space_x;
int ns_y = space_y;
- ns_x /= gwin->gw->scale;
- ns_y /= gwin->gw->scale;
-
ns_x += gwin->gw->scrollx;
ns_y += gwin->gw->scrolly;
@@ -1506,8 +1928,7 @@ static void ami_gui_scroll_internal(struct gui_window_2 *gwin, int xs, int ys)
if(ami_mouse_to_ns_coords(gwin, &x, &y, -1, -1) == true)
{
- if(browser_window_scroll_at_point(gwin->gw->bw, x, y,
- xs, ys) == false)
+ if(browser_window_scroll_at_point(gwin->gw->bw, x, y, xs, ys) == false)
{
int width, height;
@@ -1589,11 +2010,11 @@ static struct IBox *ami_ns_rect_to_ibox(struct gui_window_2 *gwin, const struct
return NULL;
}
- ibox->Left = gwin->win->MouseX + (rect->x0 * gwin->gw->scale);
- ibox->Top = gwin->win->MouseY + (rect->y0 * gwin->gw->scale);
+ ibox->Left = gwin->win->MouseX + (rect->x0);
+ ibox->Top = gwin->win->MouseY + (rect->y0);
- ibox->Width = (rect->x1 - rect->x0) * gwin->gw->scale;
- ibox->Height = (rect->y1 - rect->y0) * gwin->gw->scale;
+ ibox->Width = (rect->x1 - rect->x0);
+ ibox->Height = (rect->y1 - rect->y0);
if(ibox->Left < bbox->Left) ibox->Left = bbox->Left;
if(ibox->Top < bbox->Top) ibox->Top = bbox->Top;
@@ -1659,18 +2080,20 @@ static void ami_gui_menu_update_all(void)
* \param gw The gui window to measure content area of.
* \param width receives width of window
* \param height receives height of window
- * \param scaled whether to return scaled values
* \return NSERROR_OK on sucess and width and height updated
* else error code.
*/
-static nserror gui_window_get_dimensions(struct gui_window *gw,
- int *restrict width, int *restrict height, bool scaled)
+static nserror
+gui_window_get_dimensions(struct gui_window *gw,
+ int *restrict width,
+ int *restrict height)
{
struct IBox *bbox;
nserror res;
- res = ami_gui_get_space_box((Object *)gw->shared->objects[GID_BROWSER], &bbox);
- if(res != NSERROR_OK) {
+ res = ami_gui_get_space_box((Object *)gw->shared->objects[GID_BROWSER],
+ &bbox);
+ if (res != NSERROR_OK) {
amiga_warn_user("NoMemory", "");
return res;
}
@@ -1680,11 +2103,6 @@ static nserror gui_window_get_dimensions(struct gui_window *gw,
ami_gui_free_space_box(bbox);
- if(scaled) {
- *width /= gw->scale;
- *height /= gw->scale;
- }
-
return NSERROR_OK;
}
@@ -1801,7 +2219,7 @@ static void ami_gui_scroller_update(struct gui_window_2 *gwin)
rethinkh = ami_gui_hscroll_remove(gwin);
} else {
if((browser_window_get_extents(gwin->gw->bw, false, &w, &h) == NSERROR_OK)) {
- gui_window_get_dimensions(gwin->gw, &ww, &wh, false);
+ gui_window_get_dimensions(gwin->gw, &ww, &wh);
}
if(vscroll == BW_SCROLLING_NO) {
@@ -1827,6 +2245,217 @@ static void ami_gui_scroller_update(struct gui_window_2 *gwin)
}
}
+/* For future use
+static void ami_gui_console_log_clear(struct gui_window *g)
+{
+ if(g->shared->objects[GID_LOG] != NULL) {
+ SetGadgetAttrs((struct Gadget *)g->shared->objects[GID_LOG], g->shared->win, NULL,
+ LISTBROWSER_Labels, NULL,
+ TAG_DONE);
+ }
+
+ FreeListBrowserList(&g->loglist);
+
+ NewList(&g->loglist);
+
+ if(g->shared->objects[GID_LOG] != NULL) {
+ SetGadgetAttrs((struct Gadget *)g->shared->objects[GID_LOG], g->shared->win, NULL,
+ LISTBROWSER_Labels, &g->loglist,
+ TAG_DONE);
+ }
+}
+*/
+
+static void ami_gui_console_log_add(struct gui_window *g)
+{
+ struct TagItem attrs[2];
+
+ if(g->shared->objects[GID_LOG] != NULL) return;
+
+ attrs[0].ti_Tag = CHILD_MinHeight;
+ attrs[0].ti_Data = 50;
+ attrs[1].ti_Tag = TAG_DONE;
+ attrs[1].ti_Data = 0;
+
+ g->shared->objects[GID_LOG] = ListBrowserObj,
+ GA_ID, GID_LOG,
+ LISTBROWSER_ColumnInfo, g->logcolumns,
+ LISTBROWSER_ColumnTitles, TRUE,
+ LISTBROWSER_Labels, &g->loglist,
+ LISTBROWSER_Striping, LBS_ROWS,
+ ListBrowserEnd;
+
+#ifdef __amigaos4__
+ IDoMethod(g->shared->objects[GID_LOGLAYOUT], LM_ADDCHILD,
+ g->shared->win, g->shared->objects[GID_LOG], NULL);
+#else
+ SetAttrs(g->shared->objects[GID_LOGLAYOUT],
+ LAYOUT_AddChild, g->shared->objects[GID_LOG], TAG_MORE, &attrs);
+#endif
+
+ FlushLayoutDomainCache((struct Gadget *)g->shared->objects[GID_MAIN]);
+
+ RethinkLayout((struct Gadget *)g->shared->objects[GID_MAIN],
+ g->shared->win, NULL, TRUE);
+
+ ami_schedule_redraw(g->shared, true);
+}
+
+static void ami_gui_console_log_remove(struct gui_window *g)
+{
+ if(g->shared->objects[GID_LOG] == NULL) return;
+
+#ifdef __amigaos4__
+ IDoMethod(g->shared->objects[GID_LOGLAYOUT], LM_REMOVECHILD,
+ g->shared->win, g->shared->objects[GID_LOG]);
+#else
+ SetAttrs(g->shared->objects[GID_LOGLAYOUT],
+ LAYOUT_RemoveChild, g->shared->objects[GID_LOG], TAG_DONE);
+#endif
+
+ g->shared->objects[GID_LOG] = NULL;
+
+ FlushLayoutDomainCache((struct Gadget *)g->shared->objects[GID_MAIN]);
+
+ RethinkLayout((struct Gadget *)g->shared->objects[GID_MAIN],
+ g->shared->win, NULL, TRUE);
+
+ ami_schedule_redraw(g->shared, true);
+}
+
+static bool ami_gui_console_log_toggle(struct gui_window *g)
+{
+ if(g->shared->objects[GID_LOG] == NULL) {
+ ami_gui_console_log_add(g);
+ return true;
+ } else {
+ ami_gui_console_log_remove(g);
+ return false;
+ }
+}
+
+static void ami_gui_console_log_switch(struct gui_window *g)
+{
+ if(g->shared->objects[GID_LOG] == NULL) return;
+
+ RefreshSetGadgetAttrs((struct Gadget *)g->shared->objects[GID_LOG], g->shared->win, NULL,
+ LISTBROWSER_ColumnInfo, g->logcolumns,
+ LISTBROWSER_Labels, &g->loglist,
+ TAG_DONE);
+}
+
+static void
+gui_window_console_log(struct gui_window *g,
+ browser_window_console_source src,
+ const char *msg,
+ size_t msglen,
+ browser_window_console_flags flags)
+{
+ bool foldable = !!(flags & BW_CS_FLAG_FOLDABLE);
+ const char *src_text;
+ const char *level_text;
+ struct Node *node;
+ ULONG style = 0;
+ ULONG fgpen = TEXTPEN;
+ ULONG lbflags = LBFLG_READONLY;
+ char timestamp[256];
+ time_t now = time(NULL);
+ struct tm *timedata = localtime(&now);
+
+ strftime(timestamp, 256, "%c", timedata);
+
+ if(foldable) lbflags |= LBFLG_HASCHILDREN;
+
+ switch (src) {
+ case BW_CS_INPUT:
+ src_text = "client-input";
+ break;
+ case BW_CS_SCRIPT_ERROR:
+ src_text = "scripting-error";
+ break;
+ case BW_CS_SCRIPT_CONSOLE:
+ src_text = "scripting-console";
+ break;
+ default:
+ assert(0 && "Unknown scripting source");
+ src_text = "unknown";
+ break;
+ }
+
+ switch (flags & BW_CS_FLAG_LEVEL_MASK) {
+ case BW_CS_FLAG_LEVEL_DEBUG:
+ level_text = "DEBUG";
+ fgpen = DISABLEDTEXTPEN;
+ lbflags |= LBFLG_CUSTOMPENS;
+ break;
+ case BW_CS_FLAG_LEVEL_LOG:
+ level_text = "LOG";
+ fgpen = DISABLEDTEXTPEN;
+ lbflags |= LBFLG_CUSTOMPENS;
+ break;
+ case BW_CS_FLAG_LEVEL_INFO:
+ level_text = "INFO";
+ break;
+ case BW_CS_FLAG_LEVEL_WARN:
+ level_text = "WARN";
+ break;
+ case BW_CS_FLAG_LEVEL_ERROR:
+ level_text = "ERROR";
+ style = FSF_BOLD;
+ break;
+ default:
+ assert(0 && "Unknown console logging level");
+ level_text = "unknown";
+ break;
+ }
+
+ if(g->shared->objects[GID_LOG] != NULL) {
+ SetGadgetAttrs((struct Gadget *)g->shared->objects[GID_LOG], g->shared->win, NULL,
+ LISTBROWSER_Labels, NULL,
+ TAG_DONE);
+ }
+
+ /* Add log entry to list irrespective of whether the log is open. */
+ if((node = AllocListBrowserNode(4,
+ LBNA_Flags, lbflags,
+ LBNA_Column, 0,
+ LBNCA_SoftStyle, style,
+ LBNCA_FGPen, fgpen,
+ LBNCA_CopyText, TRUE,
+ LBNCA_Text, timestamp,
+ LBNA_Column, 1,
+ LBNCA_SoftStyle, style,
+ LBNCA_FGPen, fgpen,
+ LBNCA_CopyText, TRUE,
+ LBNCA_Text, src_text,
+ LBNA_Column, 2,
+ LBNCA_SoftStyle, style,
+ LBNCA_FGPen, fgpen,
+ LBNCA_CopyText, TRUE,
+ LBNCA_Text, level_text,
+ LBNA_Column, 3,
+ LBNCA_SoftStyle, style,
+ LBNCA_FGPen, fgpen,
+ LBNCA_CopyText, TRUE,
+ LBNCA_Text, msg,
+ TAG_DONE))) {
+ AddTail(&g->loglist, node);
+ }
+
+ if(g->shared->objects[GID_LOG] != NULL) {
+ RefreshSetGadgetAttrs((struct Gadget *)g->shared->objects[GID_LOG], g->shared->win, NULL,
+ LISTBROWSER_Labels, &g->loglist,
+ TAG_DONE);
+ }
+
+#ifdef __amigaos4__
+ DebugPrintF("NETSURF: CONSOLE_LOG SOURCE %s %sFOLDABLE %s %.*s\n",
+ src_text, foldable ? "" : "NOT-", level_text,
+ (int)msglen, msg);
+#endif
+}
+
+
/**
* function to add retrieved favicon to gui
*/
@@ -2027,8 +2656,8 @@ static BOOL ami_gui_event(void *w)
break;
}
- x = (ULONG)((gwin->win->MouseX - bbox->Left) / gwin->gw->scale);
- y = (ULONG)((gwin->win->MouseY - bbox->Top) / gwin->gw->scale);
+ x = (ULONG)((gwin->win->MouseX - bbox->Left));
+ y = (ULONG)((gwin->win->MouseY - bbox->Top));
ami_get_hscroll_pos(gwin, (ULONG *)&xs);
ami_get_vscroll_pos(gwin, (ULONG *)&ys);
@@ -2088,8 +2717,8 @@ static BOOL ami_gui_event(void *w)
return FALSE;
}
- x = (ULONG)((gwin->win->MouseX - bbox->Left) / gwin->gw->scale);
- y = (ULONG)((gwin->win->MouseY - bbox->Top) / gwin->gw->scale);
+ x = (ULONG)(gwin->win->MouseX - bbox->Left);
+ y = (ULONG)(gwin->win->MouseY - bbox->Top);
ami_get_hscroll_pos(gwin, (ULONG *)&xs);
ami_get_vscroll_pos(gwin, (ULONG *)&ys);
@@ -2371,6 +3000,25 @@ static BOOL ami_gui_event(void *w)
ami_gui_history(gwin, false);
break;
+ case GID_PAGEINFO:
+ {
+ ULONG w_top, w_left;
+ ULONG g_top, g_left, g_height;
+
+ GetAttr(WA_Top, gwin->objects[OID_MAIN], &w_top);
+ GetAttr(WA_Left, gwin->objects[OID_MAIN], &w_left);
+ GetAttr(GA_Top, gwin->objects[GID_PAGEINFO], &g_top);
+ GetAttr(GA_Left, gwin->objects[GID_PAGEINFO], &g_left);
+ GetAttr(GA_Height, gwin->objects[GID_PAGEINFO], &g_height);
+
+ if(ami_pageinfo_open(gwin->gw->bw,
+ w_left + g_left,
+ w_top + g_top + g_height) != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to open page info window");
+ }
+ }
+ break;
+
case GID_FAVE:
GetAttr(STRINGA_TextVal,
(Object *)gwin->objects[GID_URL],
@@ -2493,13 +3141,17 @@ static BOOL ami_gui_event(void *w)
break;
case RAWKEY_F9: // decrease scale
- ami_gui_set_scale(gwin->gw, gwin->gw->scale - 0.1);
+ ami_gui_adjust_scale(gwin->gw, -0.1);
break;
case RAWKEY_F10: // increase scale
- ami_gui_set_scale(gwin->gw, gwin->gw->scale + 0.1);
+ ami_gui_adjust_scale(gwin->gw, +0.1);
break;
+ case RAWKEY_F12: // console log
+ ami_gui_console_log_toggle(gwin->gw);
+ break;
+
case RAWKEY_HELP: // help
ami_help_open(AMI_HELP_GUI, scrn);
break;
@@ -2602,6 +3254,56 @@ static void ami_gui_appicon_remove(struct gui_window_2 *gwin)
}
}
+static nserror gui_page_info_change(struct gui_window *gw)
+{
+ int bm_idx;
+ browser_window_page_info_state pistate;
+ struct gui_window_2 *gwin = ami_gui_get_gui_window_2(gw);
+ struct browser_window *bw = ami_gui_get_browser_window(gw);
+
+ /* if this isn't the visible tab, don't do anything */
+ if((gwin == NULL) || (gwin->gw != gw)) return NSERROR_OK;
+
+ pistate = browser_window_get_page_info_state(bw);
+
+ switch(pistate) {
+ case PAGE_STATE_INTERNAL:
+ bm_idx = GID_PAGEINFO_INTERNAL_BM;
+ break;
+
+ case PAGE_STATE_LOCAL:
+ bm_idx = GID_PAGEINFO_LOCAL_BM;
+ break;
+
+ case PAGE_STATE_INSECURE:
+ bm_idx = GID_PAGEINFO_INSECURE_BM;
+ break;
+
+ case PAGE_STATE_SECURE_OVERRIDE:
+ bm_idx = GID_PAGEINFO_WARNING_BM;
+ break;
+
+ case PAGE_STATE_SECURE_ISSUES:
+ bm_idx = GID_PAGEINFO_WARNING_BM;
+ break;
+
+ case PAGE_STATE_SECURE:
+ bm_idx = GID_PAGEINFO_SECURE_BM;
+ break;
+
+ default:
+ bm_idx = GID_PAGEINFO_INTERNAL_BM;
+ break;
+ }
+
+ RefreshSetGadgetAttrs((struct Gadget *)gwin->objects[GID_PAGEINFO], gwin->win, NULL,
+ BUTTON_RenderImage, gwin->objects[bm_idx],
+ GA_HintInfo, gwin->helphints[bm_idx],
+ TAG_DONE);
+
+ return NSERROR_OK;
+}
+
static void ami_handle_appmsg(void)
{
struct AppMessage *appmsg;
@@ -2873,7 +3575,7 @@ void ami_get_msg(void)
ami_quit_netsurf_delayed();
}
-void ami_change_tab(struct gui_window_2 *gwin, int direction)
+static void ami_change_tab(struct gui_window_2 *gwin, int direction)
{
struct Node *tab_node = gwin->gw->tab_node;
struct Node *ptab = NULL;
@@ -2895,7 +3597,136 @@ void ami_change_tab(struct gui_window_2 *gwin, int direction)
ami_switch_tab(gwin, true);
}
-void ami_switch_tab(struct gui_window_2 *gwin, bool redraw)
+
+static void gui_window_set_title(struct gui_window *g, const char *restrict title)
+{
+ struct Node *node;
+ char *restrict utf8title;
+
+ if(!g) return;
+ if(!title) return;
+
+ utf8title = ami_utf8_easy((char *)title);
+
+ if(g->tab_node) {
+ node = g->tab_node;
+
+ if((g->tabtitle == NULL) || (strcmp(utf8title, g->tabtitle)))
+ {
+ SetGadgetAttrs((struct Gadget *)g->shared->objects[GID_TABS],
+ g->shared->win, NULL,
+ CLICKTAB_Labels, ~0,
+ TAG_DONE);
+
+ if(g->tabtitle) free(g->tabtitle);
+ g->tabtitle = strdup(utf8title);
+
+ SetClickTabNodeAttrs(node, TNA_Text, g->tabtitle,
+ TNA_HintInfo, g->tabtitle,
+ TAG_DONE);
+
+ RefreshSetGadgetAttrs((struct Gadget *)g->shared->objects[GID_TABS],
+ g->shared->win, NULL,
+ CLICKTAB_Labels, &g->shared->tab_list,
+ TAG_DONE);
+
+ if(ClickTabBase->lib_Version < 53)
+ RethinkLayout((struct Gadget *)g->shared->objects[GID_TABLAYOUT],
+ g->shared->win, NULL, TRUE);
+ }
+ }
+
+ if(g == g->shared->gw) {
+ if((g->shared->wintitle == NULL) || (strcmp(utf8title, g->shared->wintitle)))
+ {
+ if(g->shared->wintitle) free(g->shared->wintitle);
+ g->shared->wintitle = strdup(utf8title);
+ SetWindowTitles(g->shared->win, g->shared->wintitle, ami_gui_get_screen_title());
+ }
+ }
+
+ ami_utf8_free(utf8title);
+}
+
+static void gui_window_update_extent(struct gui_window *g)
+{
+ struct IBox *bbox;
+
+ if(!g || !g->bw) return;
+ if(browser_window_has_content(g->bw) == false) return;
+
+ if(g == g->shared->gw) {
+ int width, height;
+ if(ami_gui_get_space_box((Object *)g->shared->objects[GID_BROWSER], &bbox) != NSERROR_OK) {
+ amiga_warn_user("NoMemory", "");
+ return;
+ }
+
+ if(g->shared->objects[GID_VSCROLL]) {
+ browser_window_get_extents(g->bw, true, &width, &height);
+ RefreshSetGadgetAttrs((struct Gadget *)(APTR)g->shared->objects[GID_VSCROLL],g->shared->win,NULL,
+ SCROLLER_Total, (ULONG)(height),
+ SCROLLER_Visible, bbox->Height,
+ TAG_DONE);
+ }
+
+ if(g->shared->objects[GID_HSCROLL])
+ {
+ browser_window_get_extents(g->bw, true, &width, &height);
+ RefreshSetGadgetAttrs((struct Gadget *)(APTR)g->shared->objects[GID_HSCROLL],
+ g->shared->win, NULL,
+ SCROLLER_Total, (ULONG)(width),
+ SCROLLER_Visible, bbox->Width,
+ TAG_DONE);
+ }
+
+ ami_gui_free_space_box(bbox);
+ }
+
+ ami_gui_scroller_update(g->shared);
+ g->shared->new_content = true;
+}
+
+
+/**
+ * Invalidates an area of an amiga browser window
+ *
+ * \param g gui_window
+ * \param rect area to redraw or NULL for the entire window area
+ * \return NSERROR_OK on success or appropriate error code
+ */
+static nserror amiga_window_invalidate_area(struct gui_window *g,
+ const struct rect *restrict rect)
+{
+ struct nsObject *nsobj;
+ struct rect *restrict deferred_rect;
+
+ if(!g) return NSERROR_BAD_PARAMETER;
+
+ if (rect == NULL) {
+ if (g != g->shared->gw) {
+ return NSERROR_OK;
+ }
+ } else {
+ if (ami_gui_window_update_box_deferred_check(g->deferred_rects, rect,
+ g->deferred_rects_pool)) {
+ deferred_rect = ami_memory_itempool_alloc(g->deferred_rects_pool,
+ sizeof(struct rect));
+ CopyMem(rect, deferred_rect, sizeof(struct rect));
+ nsobj = AddObject(g->deferred_rects, AMINS_RECT);
+ nsobj->objstruct = deferred_rect;
+ } else {
+ NSLOG(netsurf, INFO,
+ "Ignoring duplicate or subset of queued box redraw");
+ }
+ }
+ ami_schedule_redraw(g->shared, false);
+
+ return NSERROR_OK;
+}
+
+
+static void ami_switch_tab(struct gui_window_2 *gwin, bool redraw)
{
struct Node *tabnode;
struct IBox *bbox;
@@ -2915,6 +3746,8 @@ void ami_switch_tab(struct gui_window_2 *gwin, bool redraw)
TAG_DONE);
cur_gw = gwin->gw;
+ ami_gui_console_log_switch(gwin->gw);
+
if(ami_gui_get_space_box((Object *)gwin->objects[GID_BROWSER], &bbox) != NSERROR_OK) {
amiga_warn_user("NoMemory", "");
return;
@@ -2938,7 +3771,10 @@ void ami_switch_tab(struct gui_window_2 *gwin, bool redraw)
struct rect rect;
ami_plot_clear_bbox(gwin->win->RPort, bbox);
- browser_window_update(gwin->gw->bw, false);
+ gui_window_set_title(gwin->gw,
+ browser_window_get_title(gwin->gw->bw));
+ gui_window_update_extent(gwin->gw);
+ amiga_window_invalidate_area(gwin->gw, NULL);
rect.x0 = rect.x1 = gwin->gw->scrollx;
rect.y0 = rect.y1 = gwin->gw->scrolly;
@@ -2952,6 +3788,7 @@ void ami_switch_tab(struct gui_window_2 *gwin, bool redraw)
ami_throbber_redraw_schedule(0, gwin->gw);
gui_window_set_icon(gwin->gw, gwin->gw->favicon);
+ gui_page_info_change(gwin->gw);
}
ami_gui_free_space_box(bbox);
@@ -2991,7 +3828,7 @@ void ami_quit_netsurf(void)
}
}
-void ami_quit_netsurf_delayed(void)
+static void ami_quit_netsurf_delayed(void)
{
int res = -1;
#ifdef __amigaos4__
@@ -3395,7 +4232,7 @@ static void ami_toggletabbar(struct gui_window_2 *gwin, bool show)
GA_ID, GID_TABS,
GA_RelVerify, TRUE,
GA_Underscore, 13, // disable kb shortcuts
- GA_ContextMenu, ami_ctxmenu_clicktab_create(gwin),
+ GA_ContextMenu, ami_ctxmenu_clicktab_create(gwin, &gwin->clicktab_ctxmenu),
CLICKTAB_Labels, &gwin->tab_list,
CLICKTAB_LabelTruncate, TRUE,
CLICKTAB_CloseImage, gwin->objects[GID_CLOSETAB_BM],
@@ -3444,7 +4281,12 @@ static void ami_toggletabbar(struct gui_window_2 *gwin, bool show)
RethinkLayout((struct Gadget *)gwin->objects[GID_MAIN],
gwin->win, NULL, TRUE);
- if(gwin->gw && gwin->gw->bw) browser_window_update(gwin->gw->bw, false);
+ if (gwin->gw && gwin->gw->bw) {
+ gui_window_set_title(gwin->gw,
+ browser_window_get_title(gwin->gw->bw));
+ gui_window_update_extent(gwin->gw);
+ amiga_window_invalidate_area(gwin->gw, NULL);
+ }
}
void ami_gui_tabs_toggle_all(void)
@@ -3517,9 +4359,14 @@ int ami_gui_count_windows(int window, int *tabs)
*/
void ami_gui_set_scale(struct gui_window *gw, float scale)
{
- if(scale <= 0.0) return;
- gw->scale = scale;
browser_window_set_scale(gw->bw, scale, true);
+ ami_schedule_redraw(gw->shared, true);
+}
+
+void ami_gui_adjust_scale(struct gui_window *gw, float adjustment)
+{
+ browser_window_set_scale(gw->bw, adjustment, false);
+ ami_schedule_redraw(gw->shared, true);
}
void ami_gui_switch_to_new_tab(struct gui_window_2 *gwin)
@@ -3572,10 +4419,6 @@ static void ami_do_redraw_tiled(struct gui_window_2 *gwin, bool busy,
int tile_size_y;
ami_plot_ra_get_size(glob, &tile_size_x, &tile_size_y);
-
- int tile_x_scale = (int)(tile_size_x / gwin->gw->scale);
- int tile_y_scale = (int)(tile_size_y / gwin->gw->scale);
-
ami_plot_ra_set_pen_list(glob, gwin->shared_pens);
if(top < 0) {
@@ -3608,19 +4451,19 @@ static void ami_do_redraw_tiled(struct gui_window_2 *gwin, bool busy,
if(busy) ami_set_pointer(gwin, GUI_POINTER_WAIT, false);
- for(y = top; y < (top + height); y += tile_y_scale) {
+ for(y = top; y < (top + height); y += tile_size_y) {
clip.y0 = 0;
clip.y1 = tile_size_y;
if(clip.y1 > height) clip.y1 = height;
- if((((y - sy) * gwin->gw->scale) + clip.y1) > bbox->Height)
- clip.y1 = bbox->Height - ((y - sy) * gwin->gw->scale);
+ if(((y - sy) + clip.y1) > bbox->Height)
+ clip.y1 = bbox->Height - (y - sy);
- for(x = left; x < (left + width); x += tile_x_scale) {
+ for(x = left; x < (left + width); x += tile_size_x) {
clip.x0 = 0;
clip.x1 = tile_size_x;
if(clip.x1 > width) clip.x1 = width;
- if((((x - sx) * gwin->gw->scale) + clip.x1) > bbox->Width)
- clip.x1 = bbox->Width - ((x - sx) * gwin->gw->scale);
+ if(((x - sx) + clip.x1) > bbox->Width)
+ clip.x1 = bbox->Width - (x - sx);
if(browser_window_redraw(gwin->gw->bw,
clip.x0 - (int)x,
@@ -3635,15 +4478,15 @@ static void ami_do_redraw_tiled(struct gui_window_2 *gwin, bool busy,
BLITA_SrcY, 0,
BLITA_DestType, BLITT_RASTPORT,
BLITA_Dest, gwin->win->RPort,
- BLITA_DestX, bbox->Left + (int)((x - sx) * gwin->gw->scale),
- BLITA_DestY, bbox->Top + (int)((y - sy) * gwin->gw->scale),
+ BLITA_DestX, bbox->Left + (int)(x - sx),
+ BLITA_DestY, bbox->Top + (int)(y - sy),
BLITA_Width, (int)(clip.x1),
BLITA_Height, (int)(clip.y1),
TAG_DONE);
#else
BltBitMapRastPort(ami_plot_ra_get_bitmap(glob), 0, 0, gwin->win->RPort,
- bbox->Left + (int)((x - sx) * gwin->gw->scale),
- bbox->Top + (int)((y - sy) * gwin->gw->scale),
+ bbox->Left + (int)(x - sx),
+ bbox->Top + (int)(y - sy),
(int)(clip.x1), (int)(clip.y1), 0xC0);
#endif
}
@@ -3693,7 +4536,7 @@ static void ami_do_redraw_limits(struct gui_window *g, struct browser_window *bw
}
ami_do_redraw_tiled(g->shared, busy, x0, y0,
- (x1 - x0) * g->scale, (y1 - y0) * g->scale, sx, sy, bbox, &ctx);
+ x1 - x0, y1 - y0, sx, sy, bbox, &ctx);
ami_gui_free_space_box(bbox);
@@ -3701,44 +4544,6 @@ static void ami_do_redraw_limits(struct gui_window *g, struct browser_window *bw
}
-/**
- * Invalidates an area of an amiga browser window
- *
- * \param g gui_window
- * \param rect area to redraw or NULL for the entire window area
- * \return NSERROR_OK on success or appropriate error code
- */
-static nserror amiga_window_invalidate_area(struct gui_window *g,
- const struct rect *restrict rect)
-{
- struct nsObject *nsobj;
- struct rect *restrict deferred_rect;
-
- if(!g) return NSERROR_BAD_PARAMETER;
-
- if (rect == NULL) {
- if (g != g->shared->gw) {
- return NSERROR_OK;
- }
- } else {
- if (ami_gui_window_update_box_deferred_check(g->deferred_rects, rect,
- g->deferred_rects_pool)) {
- deferred_rect = ami_memory_itempool_alloc(g->deferred_rects_pool,
- sizeof(struct rect));
- CopyMem(rect, deferred_rect, sizeof(struct rect));
- nsobj = AddObject(g->deferred_rects, AMINS_RECT);
- nsobj->objstruct = deferred_rect;
- } else {
- NSLOG(netsurf, INFO,
- "Ignoring duplicate or subset of queued box redraw");
- }
- }
- ami_schedule_redraw(g->shared, false);
-
- return NSERROR_OK;
-}
-
-
static void ami_refresh_window(struct gui_window_2 *gwin)
{
/* simplerefresh only */
@@ -3760,14 +4565,10 @@ static void ami_refresh_window(struct gui_window_2 *gwin)
BeginRefresh(gwin->win);
- r.x0 = ((gwin->win->RPort->Layer->DamageList->bounds.MinX - bbox->Left) /
- browser_window_get_scale(gwin->gw->bw)) + sx - 1;
- r.x1 = ((gwin->win->RPort->Layer->DamageList->bounds.MaxX - bbox->Left) /
- browser_window_get_scale(gwin->gw->bw)) + sx + 2;
- r.y0 = ((gwin->win->RPort->Layer->DamageList->bounds.MinY - bbox->Top) /
- browser_window_get_scale(gwin->gw->bw)) + sy - 1;
- r.y1 = ((gwin->win->RPort->Layer->DamageList->bounds.MaxY - bbox->Top) /
- browser_window_get_scale(gwin->gw->bw)) + sy + 2;
+ r.x0 = (gwin->win->RPort->Layer->DamageList->bounds.MinX - bbox->Left) + sx - 1;
+ r.x1 = (gwin->win->RPort->Layer->DamageList->bounds.MaxX - bbox->Left) + sx + 2;
+ r.y0 = (gwin->win->RPort->Layer->DamageList->bounds.MinY - bbox->Top) + sy - 1;
+ r.y1 = (gwin->win->RPort->Layer->DamageList->bounds.MaxY - bbox->Top) + sy + 2;
regrect = gwin->win->RPort->Layer->DamageList->RegionRectangle;
@@ -3775,14 +4576,10 @@ static void ami_refresh_window(struct gui_window_2 *gwin)
while(regrect)
{
- r.x0 = ((regrect->bounds.MinX - bbox->Left) /
- browser_window_get_scale(gwin->gw->bw)) + sx - 1;
- r.x1 = ((regrect->bounds.MaxX - bbox->Left) /
- browser_window_get_scale(gwin->gw->bw)) + sx + 2;
- r.y0 = ((regrect->bounds.MinY - bbox->Top) /
- browser_window_get_scale(gwin->gw->bw)) + sy - 1;
- r.y1 = ((regrect->bounds.MaxY - bbox->Top) /
- browser_window_get_scale(gwin->gw->bw)) + sy + 2;
+ r.x0 = (regrect->bounds.MinX - bbox->Left) + sx - 1;
+ r.x1 = (regrect->bounds.MaxX - bbox->Left) + sx + 2;
+ r.y0 = (regrect->bounds.MinY - bbox->Top) + sy - 1;
+ r.y1 = (regrect->bounds.MaxY - bbox->Top) + sy + 2;
regrect = regrect->Next;
@@ -3915,6 +4712,7 @@ gui_window_create(struct browser_window *bw,
char closetab[100],closetab_s[100],closetab_g[100];
char addtab[100],addtab_s[100],addtab_g[100];
char fave[100], unfave[100];
+ char pi_insecure[100], pi_internal[100], pi_local[100], pi_secure[100], pi_warning[100];
char tabthrobber[100];
ULONG refresh_mode = WA_SmartRefresh;
ULONG defer_layout = TRUE;
@@ -3956,7 +4754,38 @@ gui_window_create(struct browser_window *bw,
g->deferred_rects = NewObjList();
g->deferred_rects_pool = ami_memory_itempool_create(sizeof(struct rect));
g->bw = bw;
- g->scale = browser_window_get_scale(bw);
+
+ NewList(&g->loglist);
+#ifdef __amigaos4__
+ g->logcolumns = AllocLBColumnInfo(4,
+ LBCIA_Column, 0,
+ // LBCIA_CopyTitle, TRUE,
+ LBCIA_Title, "time", /**\TODO: add these to Messages */
+ LBCIA_Weight, 10,
+ LBCIA_DraggableSeparator, TRUE,
+ LBCIA_Separator, TRUE,
+ LBCIA_Column, 1,
+ // LBCIA_CopyTitle, TRUE,
+ LBCIA_Title, "source", /**\TODO: add these to Messages */
+ LBCIA_Weight, 10,
+ LBCIA_DraggableSeparator, TRUE,
+ LBCIA_Separator, TRUE,
+ LBCIA_Column, 2,
+ // LBCIA_CopyTitle, TRUE,
+ LBCIA_Title, "level", /**\TODO: add these to Messages */
+ LBCIA_Weight, 5,
+ LBCIA_DraggableSeparator, TRUE,
+ LBCIA_Separator, TRUE,
+ LBCIA_Column, 3,
+ // LBCIA_CopyTitle, TRUE,
+ LBCIA_Title, "message", /**\TODO: add these to Messages */
+ LBCIA_Weight, 75,
+ LBCIA_DraggableSeparator, TRUE,
+ LBCIA_Separator, TRUE,
+ TAG_DONE);
+#else
+ /**\TODO write OS3-compatible version */
+#endif
if((flags & GW_CREATE_TAB) && existing)
{
@@ -4037,6 +4866,9 @@ gui_window_create(struct browser_window *bw,
g->shared->throbber_hook.h_Entry = (void *)ami_set_throbber_render_hook;
g->shared->throbber_hook.h_Data = g->shared;
+ g->shared->browser_hook.h_Entry = (void *)ami_gui_browser_render_hook;
+ g->shared->browser_hook.h_Data = g->shared;
+
newprefs_hook.h_Entry = (void *)ami_gui_newprefs_hook;
newprefs_hook.h_Data = 0;
@@ -4102,6 +4934,12 @@ gui_window_create(struct browser_window *bw,
g->shared->helphints[GID_ADDTAB] =
translate_escape_chars(messages_get("HelpToolbarAddTab"));
+ g->shared->helphints[GID_PAGEINFO_INSECURE_BM] = ami_utf8_easy(messages_get("PageInfoInsecure"));
+ g->shared->helphints[GID_PAGEINFO_LOCAL_BM] = ami_utf8_easy(messages_get("PageInfoLocal"));
+ g->shared->helphints[GID_PAGEINFO_SECURE_BM] = ami_utf8_easy(messages_get("PageInfoSecure"));
+ g->shared->helphints[GID_PAGEINFO_WARNING_BM] = ami_utf8_easy(messages_get("PageInfoWarning"));
+ g->shared->helphints[GID_PAGEINFO_INTERNAL_BM] = ami_utf8_easy(messages_get("PageInfoInternal"));
+
ami_get_theme_filename(nav_west, "theme_nav_west", false);
ami_get_theme_filename(nav_west_s, "theme_nav_west_s", false);
ami_get_theme_filename(nav_west_g, "theme_nav_west_g", false);
@@ -4126,6 +4964,11 @@ gui_window_create(struct browser_window *bw,
ami_get_theme_filename(tabthrobber, "theme_tab_loading", false);
ami_get_theme_filename(fave, "theme_fave", false);
ami_get_theme_filename(unfave, "theme_unfave", false);
+ ami_get_theme_filename(pi_insecure, "theme_pageinfo_insecure", false);
+ ami_get_theme_filename(pi_internal, "theme_pageinfo_internal", false);
+ ami_get_theme_filename(pi_local, "theme_pageinfo_local", false);
+ ami_get_theme_filename(pi_secure, "theme_pageinfo_secure", false);
+ ami_get_theme_filename(pi_warning, "theme_pageinfo_warning", false);
g->shared->objects[GID_FAVE_ADD] = BitMapObj,
BITMAP_SourceFile, fave,
@@ -4155,6 +4998,37 @@ gui_window_create(struct browser_window *bw,
BITMAP_Masking, TRUE,
BitMapEnd;
+ g->shared->objects[GID_PAGEINFO_INSECURE_BM] = BitMapObj,
+ BITMAP_SourceFile, pi_insecure,
+ BITMAP_Screen, scrn,
+ BITMAP_Masking, TRUE,
+ BitMapEnd;
+
+ g->shared->objects[GID_PAGEINFO_INTERNAL_BM] = BitMapObj,
+ BITMAP_SourceFile, pi_internal,
+ BITMAP_Screen, scrn,
+ BITMAP_Masking, TRUE,
+ BitMapEnd;
+
+ g->shared->objects[GID_PAGEINFO_LOCAL_BM] = BitMapObj,
+ BITMAP_SourceFile, pi_local,
+ BITMAP_Screen, scrn,
+ BITMAP_Masking, TRUE,
+ BitMapEnd;
+
+ g->shared->objects[GID_PAGEINFO_SECURE_BM] = BitMapObj,
+ BITMAP_SourceFile, pi_secure,
+ BITMAP_Screen, scrn,
+ BITMAP_Masking, TRUE,
+ BitMapEnd;
+
+ g->shared->objects[GID_PAGEINFO_WARNING_BM] = BitMapObj,
+ BITMAP_SourceFile, pi_warning,
+ BITMAP_Screen, scrn,
+ BITMAP_Masking, TRUE,
+ BitMapEnd;
+
+
if(ClickTabBase->lib_Version < 53)
{
addtabclosegadget = LAYOUT_AddChild;
@@ -4313,6 +5187,14 @@ gui_window_create(struct browser_window *bw,
SpaceEnd,
CHILD_WeightedWidth, 0,
CHILD_WeightedHeight, 0,
+ LAYOUT_AddChild, g->shared->objects[GID_PAGEINFO] = ButtonObj,
+ GA_ID, GID_PAGEINFO,
+ GA_RelVerify, TRUE,
+ GA_ReadOnly, FALSE,
+ BUTTON_RenderImage, g->shared->objects[GID_PAGEINFO_INTERNAL_BM],
+ ButtonEnd,
+ CHILD_WeightedWidth, 0,
+ CHILD_WeightedHeight, 0,
LAYOUT_AddChild, g->shared->objects[GID_URL] =
#ifdef __amigaos4__
NewObject(urlStringClass, NULL,
@@ -4401,10 +5283,15 @@ gui_window_create(struct browser_window *bw,
LAYOUT_AddChild, g->shared->objects[GID_BROWSER] = SpaceObj,
GA_ID,GID_BROWSER,
SPACE_Transparent,TRUE,
+ SPACE_RenderHook, &g->shared->browser_hook,
SpaceEnd,
EndGroup,
EndGroup,
EndGroup,
+// LAYOUT_WeightBar, TRUE,
+ LAYOUT_AddChild, g->shared->objects[GID_LOGLAYOUT] = LayoutVObj,
+ EndGroup,
+ CHILD_WeightedHeight, 0,
#ifndef __amigaos4__
LAYOUT_AddChild, g->shared->objects[GID_STATUS] = StringObj,
GA_ID, GID_STATUS,
@@ -4650,6 +5537,11 @@ static void gui_window_destroy(struct gui_window *g)
if((g->shared->tabs == 1) && (nsoption_bool(tab_always_show) == false))
ami_toggletabbar(g->shared, false);
+ FreeListBrowserList(&g->loglist);
+#ifdef __amigaos4__
+ FreeLBColumnInfo(g->logcolumns);
+#endif
+
if(g->tabtitle) free(g->tabtitle);
free(g);
return;
@@ -4672,6 +5564,11 @@ static void gui_window_destroy(struct gui_window *g)
DisposeObject(g->shared->objects[GID_TABS_FLAG]);
DisposeObject(g->shared->objects[GID_FAVE_ADD]);
DisposeObject(g->shared->objects[GID_FAVE_RMV]);
+ DisposeObject(g->shared->objects[GID_PAGEINFO_INSECURE_BM]);
+ DisposeObject(g->shared->objects[GID_PAGEINFO_INTERNAL_BM]);
+ DisposeObject(g->shared->objects[GID_PAGEINFO_LOCAL_BM]);
+ DisposeObject(g->shared->objects[GID_PAGEINFO_SECURE_BM]);
+ DisposeObject(g->shared->objects[GID_PAGEINFO_WARNING_BM]);
ami_gui_opts_websearch_free(g->shared->web_search_list);
if(g->shared->search_bm) DisposeObject(g->shared->search_bm);
@@ -4683,12 +5580,17 @@ static void gui_window_destroy(struct gui_window *g)
ami_ctxmenu_release_hook(g->shared->ctxmenu_hook);
ami_gui_menu_free(g->shared);
+ FreeListBrowserList(&g->loglist);
+#ifdef __amigaos4__
+ FreeLBColumnInfo(g->logcolumns);
+#endif
+
free(g->shared->wintitle);
ami_utf8_free(g->shared->status);
free(g->shared->svbuffer);
for(gid = 0; gid < GID_LAST; gid++)
- free(g->shared->helphints[gid]);
+ ami_utf8_free(g->shared->helphints[gid]);
ami_gui_win_list_remove(g->shared);
if(g->tab_node) {
@@ -4707,55 +5609,6 @@ static void gui_window_destroy(struct gui_window *g)
win_destroyed = true;
}
-static void gui_window_set_title(struct gui_window *g, const char *restrict title)
-{
- struct Node *node;
- char *restrict utf8title;
-
- if(!g) return;
- if(!title) return;
-
- utf8title = ami_utf8_easy((char *)title);
-
- if(g->tab_node) {
- node = g->tab_node;
-
- if((g->tabtitle == NULL) || (strcmp(utf8title, g->tabtitle)))
- {
- SetGadgetAttrs((struct Gadget *)g->shared->objects[GID_TABS],
- g->shared->win, NULL,
- CLICKTAB_Labels, ~0,
- TAG_DONE);
-
- if(g->tabtitle) free(g->tabtitle);
- g->tabtitle = strdup(utf8title);
-
- SetClickTabNodeAttrs(node, TNA_Text, g->tabtitle,
- TNA_HintInfo, g->tabtitle,
- TAG_DONE);
-
- RefreshSetGadgetAttrs((struct Gadget *)g->shared->objects[GID_TABS],
- g->shared->win, NULL,
- CLICKTAB_Labels, &g->shared->tab_list,
- TAG_DONE);
-
- if(ClickTabBase->lib_Version < 53)
- RethinkLayout((struct Gadget *)g->shared->objects[GID_TABLAYOUT],
- g->shared->win, NULL, TRUE);
- }
- }
-
- if(g == g->shared->gw) {
- if((g->shared->wintitle == NULL) || (strcmp(utf8title, g->shared->wintitle)))
- {
- if(g->shared->wintitle) free(g->shared->wintitle);
- g->shared->wintitle = strdup(utf8title);
- SetWindowTitles(g->shared->win, g->shared->wintitle, ami_gui_get_screen_title());
- }
- }
-
- ami_utf8_free(utf8title);
-}
static void ami_redraw_callback(void *p)
{
@@ -4893,7 +5746,6 @@ static void ami_do_redraw(struct gui_window_2 *gwin)
gwin->redraw_scroll = false;
if(gwin->new_content) gwin->redraw_scroll = false;
-// if(gwin->gw->scale != 1.0) gwin->redraw_scroll = false;
}
if(gwin->redraw_scroll)
@@ -4962,22 +5814,20 @@ static void ami_do_redraw(struct gui_window_2 *gwin)
}
-void ami_get_hscroll_pos(struct gui_window_2 *gwin, ULONG *xs)
+static void ami_get_hscroll_pos(struct gui_window_2 *gwin, ULONG *xs)
{
if(gwin->objects[GID_HSCROLL])
{
GetAttr(SCROLLER_Top, (Object *)gwin->objects[GID_HSCROLL], xs);
- *xs /= gwin->gw->scale;
} else {
*xs = 0;
}
}
-void ami_get_vscroll_pos(struct gui_window_2 *gwin, ULONG *ys)
+static void ami_get_vscroll_pos(struct gui_window_2 *gwin, ULONG *ys)
{
if(gwin->objects[GID_VSCROLL]) {
GetAttr(SCROLLER_Top, gwin->objects[GID_VSCROLL], ys);
- *ys /= gwin->gw->scale;
} else {
*ys = 0;
}
@@ -5046,7 +5896,7 @@ gui_window_set_scroll(struct gui_window *g, const struct rect *rect)
if(g->shared->objects[GID_VSCROLL]) {
RefreshSetGadgetAttrs((struct Gadget *)(APTR)g->shared->objects[GID_VSCROLL],
g->shared->win, NULL,
- SCROLLER_Top, (ULONG)(sy * g->scale),
+ SCROLLER_Top, (ULONG)(sy),
TAG_DONE);
}
@@ -5054,7 +5904,7 @@ gui_window_set_scroll(struct gui_window *g, const struct rect *rect)
{
RefreshSetGadgetAttrs((struct Gadget *)(APTR)g->shared->objects[GID_HSCROLL],
g->shared->win, NULL,
- SCROLLER_Top, (ULONG)(sx * g->scale),
+ SCROLLER_Top, (ULONG)(sx),
TAG_DONE);
}
@@ -5069,45 +5919,6 @@ gui_window_set_scroll(struct gui_window *g, const struct rect *rect)
return NSERROR_OK;
}
-static void gui_window_update_extent(struct gui_window *g)
-{
- struct IBox *bbox;
-
- if(!g || !g->bw) return;
- if(browser_window_has_content(g->bw) == false) return;
-
- if(g == g->shared->gw) {
- int width, height;
- if(ami_gui_get_space_box((Object *)g->shared->objects[GID_BROWSER], &bbox) != NSERROR_OK) {
- amiga_warn_user("NoMemory", "");
- return;
- }
-
- if(g->shared->objects[GID_VSCROLL]) {
- browser_window_get_extents(g->bw, true, &width, &height);
- RefreshSetGadgetAttrs((struct Gadget *)(APTR)g->shared->objects[GID_VSCROLL],g->shared->win,NULL,
- SCROLLER_Total, (ULONG)(height),
- SCROLLER_Visible, bbox->Height,
- TAG_DONE);
- }
-
- if(g->shared->objects[GID_HSCROLL])
- {
- browser_window_get_extents(g->bw, true, &width, &height);
- RefreshSetGadgetAttrs((struct Gadget *)(APTR)g->shared->objects[GID_HSCROLL],
- g->shared->win, NULL,
- SCROLLER_Total, (ULONG)(width),
- SCROLLER_Visible, bbox->Width,
- TAG_DONE);
- }
-
- ami_gui_free_space_box(bbox);
- }
-
- ami_gui_scroller_update(g->shared);
- g->shared->new_content = true;
-}
-
static void gui_window_set_status(struct gui_window *g, const char *text)
{
char *utf8text;
@@ -5248,6 +6059,19 @@ HOOKF(uint32, ami_set_throbber_render_hook, APTR, space, struct gpRender *)
return 0;
}
+HOOKF(uint32, ami_gui_browser_render_hook, APTR, space, struct gpRender *)
+{
+ struct gui_window_2 *gwin = hook->h_Data;
+
+ NSLOG(netsurf, DEBUG, "Render hook called with %ld (REDRAW=1)", msg->gpr_Redraw);
+
+ if(msg->gpr_Redraw != GREDRAW_REDRAW) return 0;
+
+ ami_schedule_redraw(gwin, true);
+
+ return 0;
+}
+
static void gui_window_place_caret(struct gui_window *g, int x, int y, int height,
const struct rect *clip)
{
@@ -5395,7 +6219,7 @@ BOOL ami_gadget_hit(Object *obj, int x, int y)
else return FALSE;
}
-Object *ami_gui_splash_open(void)
+static Object *ami_gui_splash_open(void)
{
Object *restrict win_obj, *restrict bm_obj;
struct Window *win;
@@ -5494,7 +6318,7 @@ Object *ami_gui_splash_open(void)
return win_obj;
}
-void ami_gui_splash_close(Object *win_obj)
+static void ami_gui_splash_close(Object *win_obj)
{
if(win_obj == NULL) return;
@@ -5605,6 +6429,53 @@ static char *ami_gui_get_user_dir(STRPTR current_user)
return current_user_dir;
}
+
+/**
+ * process miscellaneous window events
+ *
+ * \param gw The window receiving the event.
+ * \param event The event code.
+ * \return NSERROR_OK when processed ok
+ */
+static nserror
+gui_window_event(struct gui_window *gw, enum gui_window_event event)
+{
+ switch (event) {
+ case GW_EVENT_UPDATE_EXTENT:
+ gui_window_update_extent(gw);
+ break;
+
+ case GW_EVENT_REMOVE_CARET:
+ gui_window_remove_caret(gw);
+ break;
+
+ case GW_EVENT_NEW_CONTENT:
+ gui_window_new_content(gw);
+ break;
+
+ case GW_EVENT_START_SELECTION:
+ gui_start_selection(gw);
+ break;
+
+ case GW_EVENT_START_THROBBER:
+ gui_window_start_throbber(gw);
+ break;
+
+ case GW_EVENT_STOP_THROBBER:
+ gui_window_stop_throbber(gw);
+ break;
+
+ case GW_EVENT_PAGE_INFO_CHANGE:
+ gui_page_info_change(gw);
+ break;
+
+ default:
+ break;
+ }
+ return NSERROR_OK;
+}
+
+
static struct gui_window_table amiga_window_table = {
.create = gui_window_create,
.destroy = gui_window_destroy,
@@ -5612,26 +6483,23 @@ static struct gui_window_table amiga_window_table = {
.get_scroll = gui_window_get_scroll,
.set_scroll = gui_window_set_scroll,
.get_dimensions = gui_window_get_dimensions,
- .update_extent = gui_window_update_extent,
+ .event = gui_window_event,
.set_icon = gui_window_set_icon,
.set_title = gui_window_set_title,
.set_url = gui_window_set_url,
.set_status = gui_window_set_status,
.place_caret = gui_window_place_caret,
- .remove_caret = gui_window_remove_caret,
.drag_start = gui_window_drag_start,
- .new_content = gui_window_new_content,
.create_form_select_menu = gui_create_form_select_menu,
.file_gadget_open = gui_file_gadget_open,
.drag_save_object = gui_drag_save_object,
- .drag_save_selection =gui_drag_save_selection,
- .start_selection = gui_start_selection,
+ .drag_save_selection = gui_drag_save_selection,
+
+ .console_log = gui_window_console_log,
/* from theme */
.set_pointer = gui_window_set_pointer,
- .start_throbber = gui_window_start_throbber,
- .stop_throbber = gui_window_stop_throbber,
/* from download */
.save_link = gui_window_save_link,
@@ -5650,12 +6518,10 @@ static struct gui_search_web_table amiga_search_web_table = {
static struct gui_misc_table amiga_misc_table = {
.schedule = ami_schedule,
- .warning = amiga_warn_user,
.quit = gui_quit,
.launch_url = gui_launch_url,
- .cert_verify = ami_cert_verify,
- .login = gui_401login_open,
+ .present_cookies = ami_cookies_present,
};
/** Normal entry point from OS */
diff --git a/frontends/amiga/gui.h b/frontends/amiga/gui.h
index bf4ec9139..70f1c505e 100644
--- a/frontends/amiga/gui.h
+++ b/frontends/amiga/gui.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2017 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ * Copyright 2008-2019 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -38,57 +38,21 @@
#define HOOKF(ret,func,type,ptr,msgtype) static ASM ret func(REG(a0, struct Hook *hook),REG(a2, type ptr), REG(a1, msgtype msg))
#endif
-enum
-{
- OID_MAIN = 0,
- OID_VSCROLL,
- OID_HSCROLL,
- OID_LAST, /* for compatibility */
- GID_MAIN,
- GID_TABLAYOUT,
- GID_BROWSER,
- GID_STATUS,
- GID_URL,
- GID_ICON,
- GID_STOP,
- GID_RELOAD,
- GID_HOME,
- GID_BACK,
- GID_FORWARD,
- GID_THROBBER,
- GID_SEARCH_ICON,
- GID_FAVE,
- GID_FAVE_ADD,
- GID_FAVE_RMV,
- GID_CLOSETAB,
- GID_CLOSETAB_BM,
- GID_ADDTAB,
- GID_ADDTAB_BM,
- GID_TABS,
- GID_TABS_FLAG,
- GID_USER,
- GID_PASS,
- GID_LOGIN,
- GID_CANCEL,
- GID_NEXT,
- GID_PREV,
- GID_SEARCHSTRING,
- GID_SHOWALL,
- GID_CASE,
- GID_TOOLBARLAYOUT,
- GID_HOTLIST,
- GID_HOTLISTLAYOUT,
- GID_HOTLISTSEPBAR,
- GID_HSCROLL,
- GID_HSCROLLLAYOUT,
- GID_VSCROLL,
- GID_VSCROLLLAYOUT,
- GID_LAST
+/* valid options for ami_gui_get_object */
+enum {
+ AMI_GAD_THROBBER = 0,
+ AMI_GAD_TABS,
+ AMI_GAD_URL,
+ AMI_GAD_SEARCH,
+ AMI_WIN_MAIN
};
struct find_window;
struct ami_history_local_window;
struct ami_menu_data;
+struct gui_window;
+struct gui_window_2;
+struct IBox;
#define AMI_GUI_TOOLBAR_MAX 20
@@ -111,83 +75,7 @@ struct ami_generic_window {
const struct ami_win_event_table *tbl;
};
-struct gui_window_2 {
- struct ami_generic_window w;
- struct Window *win;
- Object *restrict objects[GID_LAST];
- struct gui_window *gw; /* currently-displayed gui_window */
- bool redraw_required;
- int throbber_frame;
- struct List tab_list;
- ULONG tabs;
- ULONG next_tab;
- struct Node *last_new_tab;
- struct Hook scrollerhook;
- struct form_control *control;
- browser_mouse_state mouse_state;
- browser_mouse_state key_state;
- ULONG throbber_update_count;
- struct find_window *searchwin;
- ULONG oldh;
- ULONG oldv;
- int temp;
- bool redraw_scroll;
- bool new_content;
- struct ami_menu_data *menu_data[AMI_MENU_AREXX_MAX + 1]; /* only for GadTools menus */
- ULONG hotlist_items;
- Object *restrict hotlist_toolbar_lab[AMI_GUI_TOOLBAR_MAX];
- struct List hotlist_toolbar_list;
- struct List *web_search_list;
- Object *search_bm;
- char *restrict svbuffer;
- char *restrict status;
- char *restrict wintitle;
- char *restrict helphints[GID_LAST];
- browser_mouse_state prev_mouse_state;
- struct timeval lastclick;
- struct AppIcon *appicon; /* iconify appicon */
- struct DiskObject *dobj; /* iconify appicon */
- struct Hook favicon_hook;
- struct Hook throbber_hook;
- struct Hook *ctxmenu_hook;
- Object *restrict history_ctxmenu[2];
- Object *restrict clicktab_ctxmenu;
- gui_drag_type drag_op;
- struct IBox *ptr_lock;
- struct AppWindow *appwin;
- struct MinList *shared_pens;
- gui_pointer_shape mouse_pointer;
- struct Menu *imenu; /* Intuition menu */
- bool closed; /* Window has been closed (via menu) */
-};
-
-struct gui_window
-{
- struct gui_window_2 *shared;
- int tab;
- struct Node *tab_node;
- int c_x; /* Caret X posn */
- int c_y; /* Caret Y posn */
- int c_w; /* Caret width */
- int c_h; /* Caret height */
- int c_h_temp;
- int scrollx;
- int scrolly;
- struct ami_history_local_window *hw;
- struct List dllist;
- struct hlcache_handle *favicon;
- bool throbbing;
- char *tabtitle;
- APTR deferred_rects_pool;
- struct MinList *deferred_rects;
- struct browser_window *bw;
- float scale;
-};
-
-extern struct MinList *window_list; /**\todo stop arexx.c poking about in here */
-extern struct Screen *scrn;
-extern struct MsgPort *sport;
-extern struct gui_window *cur_gw;
+#define IS_CURRENT_GW(GWIN,GW) (ami_gui2_get_gui_window(GWIN) == GW)
/* The return value for these functions must be deallocated using FreeVec() */
STRPTR ami_locale_langs(int *codeset);
@@ -211,7 +99,14 @@ void ami_gui_update_hotlist_button(struct gui_window_2 *gwin);
nserror ami_gui_new_blank_tab(struct gui_window_2 *gwin);
int ami_gui_count_windows(int window, int *tabs);
void ami_gui_set_scale(struct gui_window *gw, float scale);
+void ami_set_pointer(struct gui_window_2 *gwin, gui_pointer_shape shape, bool update);
+void ami_reset_pointer(struct gui_window_2 *gwin);
+void *ami_window_at_pointer(int type);
+/**
+ * Beep
+ */
+void ami_gui_beep(void);
/**
* Close a window and all tabs attached to it.
@@ -244,6 +139,13 @@ nserror ami_gui_get_space_box(Object *obj, struct IBox **bbox);
void ami_gui_free_space_box(struct IBox *bbox);
/**
+ * Get shared message port
+ *
+ * @return Pointer to an initialised MsgPort
+ */
+struct MsgPort *ami_gui_get_shared_msgport(void);
+
+/**
* Get the application.library ID NetSurf is registered as.
*
* @return App ID.
@@ -251,6 +153,13 @@ void ami_gui_free_space_box(struct IBox *bbox);
uint32 ami_gui_get_app_id(void);
/**
+ * Get a pointer to the screen NetSurf is running on.
+ *
+ * @return Pointer to struct Screen.
+ */
+struct Screen *ami_gui_get_screen(void);
+
+/**
* Get the string for NetSurf's screen titlebar.
*
* @return String to use as the screen's titlebar text.
@@ -273,6 +182,15 @@ nserror ami_gui_win_list_add(void *win, int type, const struct ami_win_event_tab
void ami_gui_win_list_remove(void *win);
/**
+ * Get the window list.
+ *
+ *\TODO: Nothing should be poking around in this list, but we aren't
+ * assigning unique IDs to windows (ARexx interface needs this)
+ * ami_find_gwin_by_id() is close but not ARexx-friendly
+ */
+struct MinList *ami_gui_get_window_list(void);
+
+/**
* Get which qualifier keys are being pressed
*/
int ami_gui_get_quals(Object *win_obj);
@@ -283,5 +201,167 @@ int ami_gui_get_quals(Object *win_obj);
bool ami_gui_window_update_box_deferred_check(struct MinList *deferred_rects,
const struct rect *restrict new_rect, APTR mempool);
+/**
+ * Adjust scale by specified amount
+ */
+void ami_gui_adjust_scale(struct gui_window *gw, float adjustment);
+
+/**
+ * Get a pointer to the gui_window which NetSurf considers
+ * to be the current/active one
+ */
+struct gui_window *ami_gui_get_active_gw(void);
+
+/**
+ * Get browser window from gui_window
+ */
+struct browser_window *ami_gui_get_browser_window(struct gui_window *gw);
+
+/**
+ * Get browser window from gui_window_2
+ */
+struct browser_window *ami_gui2_get_browser_window(struct gui_window_2 *gwin);
+
+/**
+ * Get gui_window_2 from gui_window
+ */
+struct gui_window_2 *ami_gui_get_gui_window_2(struct gui_window *gw);
+
+/**
+ * Get gui_window from gui_window_2
+ */
+struct gui_window *ami_gui2_get_gui_window(struct gui_window_2 *gwin);
+
+/**
+ * Get download list from gui_window
+ */
+struct List *ami_gui_get_download_list(struct gui_window *gw);
+
+/**
+ * Get tab title from gui_window
+ */
+const char *ami_gui_get_tab_title(struct gui_window *gw);
+
+/**
+ * Get window title from gui_window
+ */
+const char *ami_gui_get_win_title(struct gui_window *gw);
+
+/**
+ * Get tab node from gui_window
+ */
+struct Node *ami_gui_get_tab_node(struct gui_window *gw);
+
+/**
+ * Get tabs from gui_window_2
+ */
+ULONG ami_gui2_get_tabs(struct gui_window_2 *gwin);
+
+/**
+ * Get tab list from gui_window_2
+ */
+struct List *ami_gui2_get_tab_list(struct gui_window_2 *gwin);
+
+/**
+ * Get favicon from gui_window
+ */
+struct hlcache_handle *ami_gui_get_favicon(struct gui_window *gw);
+
+/**
+ * Get local history window from gui_window
+ */
+struct ami_history_local_window *ami_gui_get_history_window(struct gui_window *gw);
+
+/**
+ * Set local history window in gui_window
+ */
+void ami_gui_set_history_window(struct gui_window *gw, struct ami_history_local_window *hw);
+
+/**
+ * Set search window in gui_window
+ */
+void ami_gui_set_find_window(struct gui_window *gw, struct find_window *fw);
+
+/**
+ * Get throbbing status from gui_window
+ */
+bool ami_gui_get_throbbing(struct gui_window *gw);
+
+/**
+ * Get throbbing frame from gui_window
+ */
+int ami_gui_get_throbber_frame(struct gui_window *gw);
+
+/**
+ * Set throbbing frame in gui_window
+ */
+void ami_gui_set_throbber_frame(struct gui_window *gw, int frame);
+
+/**
+ * Set throbbing status in gui_window
+ */
+void ami_gui_set_throbbing(struct gui_window *gw, bool throbbing);
+
+/**
+ * Get object from gui_window
+ */
+Object *ami_gui2_get_object(struct gui_window_2 *gwin, int object_type);
+
+/**
+ * Get window from gui_window
+ */
+struct Window *ami_gui_get_window(struct gui_window *gw);
+
+/**
+ * Get window from gui_window_2
+ */
+struct Window *ami_gui2_get_window(struct gui_window_2 *gwin);
+
+/**
+ * Get imenu from gui_window
+ */
+struct Menu *ami_gui_get_menu(struct gui_window *gw);
+
+/**
+ * Set imenu to gui_window_2. A value of NULL will free the menu (and menu_data!)
+ */
+void ami_gui2_set_menu(struct gui_window_2 *gwin, struct Menu *menu);
+
+/**
+ * Get menu_data from gui_window_2
+ */
+struct ami_menu_data **ami_gui2_get_menu_data(struct gui_window_2 *gwin);
+
+/**
+ * Set ctxmenu history tmp in gui_window_2
+ */
+void ami_gui2_set_ctxmenu_history_tmp(struct gui_window_2 *gwin, int temp);
+
+/**
+ * Get ctxmenu history tmp from gui_window_2
+ */
+int ami_gui2_get_ctxmenu_history_tmp(struct gui_window_2 *gwin);
+
+/**
+ * Get ctxmenu history from gui_window_2
+ */
+Object *ami_gui2_get_ctxmenu_history(struct gui_window_2 *gwin, ULONG direction);
+
+/**
+ * Set ctxmenu history in gui_window_2
+ */
+void ami_gui2_set_ctxmenu_history(struct gui_window_2 *gwin, ULONG direction, Object *ctx_hist);
+
+/**
+ * Set closed in gui_window_2
+ */
+void ami_gui2_set_closed(struct gui_window_2 *gwin, bool closed);
+
+/**
+ * Set new_content in gui_window_2
+ * Indicates the window needs redrawing
+ */
+void ami_gui2_set_new_content(struct gui_window_2 *gwin, bool new_content);
+
#endif
diff --git a/frontends/amiga/gui_menu.c b/frontends/amiga/gui_menu.c
index 756f5e66c..dc1450fce 100644
--- a/frontends/amiga/gui_menu.c
+++ b/frontends/amiga/gui_menu.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ * Copyright 2017-2024 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -141,7 +141,7 @@ HOOKF(void, ami_menu_item_project_save, APTR, window, struct IntuiMessage *)
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- ami_file_save_req(type, gwin, browser_window_get_content(gwin->gw->bw));
+ ami_file_save_req(type, gwin, browser_window_get_content(ami_gui2_get_browser_window(gwin)));
}
HOOKF(void, ami_menu_item_project_closetab, APTR, window, struct IntuiMessage *)
@@ -149,7 +149,7 @@ HOOKF(void, ami_menu_item_project_closetab, APTR, window, struct IntuiMessage *)
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- browser_window_destroy(gwin->gw->bw);
+ browser_window_destroy(ami_gui2_get_browser_window(gwin));
}
HOOKF(void, ami_menu_item_project_closewin, APTR, window, struct IntuiMessage *)
@@ -157,7 +157,7 @@ HOOKF(void, ami_menu_item_project_closewin, APTR, window, struct IntuiMessage *)
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- gwin->closed = true;
+ ami_gui2_set_closed(gwin, true);
}
HOOKF(void, ami_menu_item_project_print, APTR, window, struct IntuiMessage *)
@@ -166,7 +166,7 @@ HOOKF(void, ami_menu_item_project_print, APTR, window, struct IntuiMessage *)
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
ami_set_pointer(gwin, GUI_POINTER_WAIT, false);
- ami_print_ui(browser_window_get_content(gwin->gw->bw));
+ ami_print_ui(browser_window_get_content(ami_gui2_get_browser_window(gwin)));
ami_reset_pointer(gwin);
}
@@ -191,7 +191,7 @@ HOOKF(void, ami_menu_item_project_about, APTR, window, struct IntuiMessage *)
#ifdef __amigaos4__
sel = TimedDosRequesterTags(TDR_ImageType,TDRIMAGE_INFO,
TDR_TitleString, messages_get("NetSurf"),
- TDR_Window, gwin->win,
+ TDR_Window, ami_gui2_get_window(gwin),
TDR_GadgetString, temp2,
TDR_FormatString,"NetSurf %s\nBuild date %s\n\nhttp://www.netsurf-browser.org",
TDR_Arg1,netsurf_version,
@@ -206,7 +206,7 @@ HOOKF(void, ami_menu_item_project_about, APTR, window, struct IntuiMessage *)
temp2,
};
- sel = EasyRequest(gwin->win, &about_req, NULL, netsurf_version, verdate);
+ sel = EasyRequest(ami_gui2_get_window(gwin), &about_req, NULL, netsurf_version, verdate);
#endif
free(temp2);
@@ -243,7 +243,7 @@ HOOKF(void, ami_menu_item_edit_cut, APTR, window, struct IntuiMessage *)
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- browser_window_key_press(gwin->gw->bw, NS_KEY_CUT_SELECTION);
+ browser_window_key_press(ami_gui2_get_browser_window(gwin), NS_KEY_CUT_SELECTION);
}
HOOKF(void, ami_menu_item_edit_copy, APTR, window, struct IntuiMessage *)
@@ -252,22 +252,22 @@ HOOKF(void, ami_menu_item_edit_copy, APTR, window, struct IntuiMessage *)
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- if(browser_window_can_select(gwin->gw->bw)) {
- browser_window_key_press(gwin->gw->bw, NS_KEY_COPY_SELECTION);
- browser_window_key_press(gwin->gw->bw, NS_KEY_CLEAR_SELECTION);
+ if(browser_window_can_select(ami_gui2_get_browser_window(gwin))) {
+ browser_window_key_press(ami_gui2_get_browser_window(gwin), NS_KEY_COPY_SELECTION);
+ browser_window_key_press(ami_gui2_get_browser_window(gwin), NS_KEY_CLEAR_SELECTION);
}
- else if((bm = content_get_bitmap(browser_window_get_content(gwin->gw->bw)))) {
+ else if((bm = content_get_bitmap(browser_window_get_content(ami_gui2_get_browser_window(gwin))))) {
/** @todo It should be checked that the lifetime of
* the objects containing the values returned (and the
* constness cast away) is safe.
*/
- ami_bitmap_set_url(bm, browser_window_get_url(gwin->gw->bw));
- ami_bitmap_set_title(bm, browser_window_get_title(gwin->gw->bw));
+ ami_bitmap_set_url(bm, browser_window_access_url(ami_gui2_get_browser_window(gwin)));
+ ami_bitmap_set_title(bm, browser_window_get_title(ami_gui2_get_browser_window(gwin)));
ami_easy_clipboard_bitmap(bm);
}
#ifdef WITH_NS_SVG
- else if(ami_mime_compare(browser_window_get_content(gwin->gw->bw), "svg") == true) {
- ami_easy_clipboard_svg(browser_window_get_content(gwin->gw->bw));
+ else if(ami_mime_compare(browser_window_get_content(ami_gui2_get_browser_window(gwin)), "svg") == true) {
+ ami_easy_clipboard_svg(browser_window_get_content(ami_gui2_get_browser_window(gwin)));
}
#endif
}
@@ -277,7 +277,7 @@ HOOKF(void, ami_menu_item_edit_paste, APTR, window, struct IntuiMessage *)
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- browser_window_key_press(gwin->gw->bw, NS_KEY_PASTE);
+ browser_window_key_press(ami_gui2_get_browser_window(gwin), NS_KEY_PASTE);
}
HOOKF(void, ami_menu_item_edit_selectall, APTR, window, struct IntuiMessage *)
@@ -285,8 +285,8 @@ HOOKF(void, ami_menu_item_edit_selectall, APTR, window, struct IntuiMessage *)
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- browser_window_key_press(gwin->gw->bw, NS_KEY_SELECT_ALL);
- gui_start_selection(gwin->gw);
+ browser_window_key_press(ami_gui2_get_browser_window(gwin), NS_KEY_SELECT_ALL);
+ gui_start_selection(ami_gui2_get_gui_window(gwin));
}
HOOKF(void, ami_menu_item_edit_clearsel, APTR, window, struct IntuiMessage *)
@@ -294,7 +294,7 @@ HOOKF(void, ami_menu_item_edit_clearsel, APTR, window, struct IntuiMessage *)
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- browser_window_key_press(gwin->gw->bw, NS_KEY_CLEAR_SELECTION);
+ browser_window_key_press(ami_gui2_get_browser_window(gwin), NS_KEY_CLEAR_SELECTION);
}
HOOKF(void, ami_menu_item_edit_undo, APTR, window, struct IntuiMessage *)
@@ -302,7 +302,7 @@ HOOKF(void, ami_menu_item_edit_undo, APTR, window, struct IntuiMessage *)
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- browser_window_key_press(gwin->gw->bw, NS_KEY_UNDO);
+ browser_window_key_press(ami_gui2_get_browser_window(gwin), NS_KEY_UNDO);
}
HOOKF(void, ami_menu_item_edit_redo, APTR, window, struct IntuiMessage *)
@@ -310,7 +310,7 @@ HOOKF(void, ami_menu_item_edit_redo, APTR, window, struct IntuiMessage *)
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- browser_window_key_press(gwin->gw->bw, NS_KEY_REDO);
+ browser_window_key_press(ami_gui2_get_browser_window(gwin), NS_KEY_REDO);
}
HOOKF(void, ami_menu_item_browser_find, APTR, window, struct IntuiMessage *)
@@ -318,7 +318,7 @@ HOOKF(void, ami_menu_item_browser_find, APTR, window, struct IntuiMessage *)
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- ami_search_open(gwin->gw);
+ ami_search_open(ami_gui2_get_gui_window(gwin));
}
HOOKF(void, ami_menu_item_browser_localhistory, APTR, window, struct IntuiMessage *)
@@ -326,7 +326,7 @@ HOOKF(void, ami_menu_item_browser_localhistory, APTR, window, struct IntuiMessag
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- ami_history_local_present(gwin->gw);
+ ami_history_local_present(ami_gui2_get_gui_window(gwin));
}
HOOKF(void, ami_menu_item_browser_globalhistory, APTR, window, struct IntuiMessage *)
@@ -336,7 +336,7 @@ HOOKF(void, ami_menu_item_browser_globalhistory, APTR, window, struct IntuiMessa
HOOKF(void, ami_menu_item_browser_cookies, APTR, window, struct IntuiMessage *)
{
- ami_cookies_present();
+ ami_cookies_present(NULL);
}
HOOKF(void, ami_menu_item_browser_foreimg, APTR, window, struct IntuiMessage *)
@@ -375,12 +375,24 @@ HOOKF(void, ami_menu_item_browser_enablejs, APTR, window, struct IntuiMessage *)
ami_gui_menu_set_check_toggled();
}
+HOOKF(void, ami_menu_item_browser_enablecss, APTR, window, struct IntuiMessage *)
+{
+ struct Menu *menustrip;
+ bool checked = false;
+
+ GetAttr(WINDOW_MenuStrip, (Object *)window, (ULONG *)&menustrip);
+ checked = ami_menu_get_selected(menustrip, msg);
+
+ nsoption_set_bool(author_level_css, checked);
+ ami_gui_menu_set_check_toggled();
+}
+
HOOKF(void, ami_menu_item_browser_scale_decrease, APTR, window, struct IntuiMessage *)
{
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- ami_gui_set_scale(gwin->gw, gwin->gw->scale - 0.1);
+ ami_gui_adjust_scale(ami_gui2_get_gui_window(gwin), -0.1);
}
HOOKF(void, ami_menu_item_browser_scale_normal, APTR, window, struct IntuiMessage *)
@@ -388,7 +400,7 @@ HOOKF(void, ami_menu_item_browser_scale_normal, APTR, window, struct IntuiMessag
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- ami_gui_set_scale(gwin->gw, 1.0);
+ ami_gui_set_scale(ami_gui2_get_gui_window(gwin), 1.0);
}
HOOKF(void, ami_menu_item_browser_scale_increase, APTR, window, struct IntuiMessage *)
@@ -396,7 +408,7 @@ HOOKF(void, ami_menu_item_browser_scale_increase, APTR, window, struct IntuiMess
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- ami_gui_set_scale(gwin->gw, gwin->gw->scale + 0.1);
+ ami_gui_adjust_scale(ami_gui2_get_gui_window(gwin), +0.1);
}
HOOKF(void, ami_menu_item_browser_redraw, APTR, window, struct IntuiMessage *)
@@ -405,7 +417,7 @@ HOOKF(void, ami_menu_item_browser_redraw, APTR, window, struct IntuiMessage *)
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
ami_schedule_redraw(gwin, true);
- gwin->new_content = true;
+ ami_gui2_set_new_content(gwin, true);
}
HOOKF(void, ami_menu_item_hotlist_add, APTR, window, struct IntuiMessage *)
@@ -414,12 +426,12 @@ HOOKF(void, ami_menu_item_hotlist_add, APTR, window, struct IntuiMessage *)
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- bw = gwin->gw->bw;
+ bw = ami_gui2_get_browser_window(gwin);
if (bw == NULL || browser_window_has_content(bw) == false)
return;
- hotlist_add_url(browser_window_get_url(bw));
+ hotlist_add_url(browser_window_access_url(bw));
ami_gui_update_hotlist_button(gwin);
}
@@ -436,7 +448,7 @@ HOOKF(void, ami_menu_item_hotlist_entries, APTR, window, struct IntuiMessage *)
if(url == NULL) return;
- browser_window_navigate(gwin->gw->bw,
+ browser_window_navigate(ami_gui2_get_browser_window(gwin),
url,
NULL,
BW_NAVIGATE_HISTORY,
@@ -455,10 +467,10 @@ HOOKF(void, ami_menu_item_settings_snapshot, APTR, window, struct IntuiMessage *
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- nsoption_set_int(window_x, gwin->win->LeftEdge);
- nsoption_set_int(window_y, gwin->win->TopEdge);
- nsoption_set_int(window_width, gwin->win->Width);
- nsoption_set_int(window_height, gwin->win->Height);
+ nsoption_set_int(window_x, ami_gui2_get_window(gwin)->LeftEdge);
+ nsoption_set_int(window_y, ami_gui2_get_window(gwin)->TopEdge);
+ nsoption_set_int(window_width, ami_gui2_get_window(gwin)->Width);
+ nsoption_set_int(window_height, ami_gui2_get_window(gwin)->Height);
}
HOOKF(void, ami_menu_item_settings_save, APTR, window, struct IntuiMessage *)
@@ -473,10 +485,10 @@ HOOKF(void, ami_menu_item_arexx_execute, APTR, window, struct IntuiMessage *)
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
if(AslRequestTags(filereq,
- ASLFR_Window, gwin->win,
+ ASLFR_Window, ami_gui2_get_window(gwin),
ASLFR_SleepWindow, TRUE,
ASLFR_TitleText, messages_get("NetSurf"),
- ASLFR_Screen, scrn,
+ ASLFR_Screen, ami_gui_get_screen(),
ASLFR_DoSaveMode, FALSE,
ASLFR_InitialDrawer, nsoption_charp(arexx_dir),
ASLFR_InitialPattern, "#?.nsrx",
@@ -582,6 +594,10 @@ ULONG ami_gui_menu_number(int item)
case M_JS:
menu_num = FULLMENUNUM(2,9,0);
break;
+
+ case M_CSS:
+ menu_num = FULLMENUNUM(2,10,0);
+ break;
default:
NSLOG(netsurf, INFO,
@@ -681,7 +697,7 @@ void ami_gui_menu_update_checked(struct gui_window_2 *gwin)
struct Menu *menustrip;
- GetAttr(WINDOW_MenuStrip, gwin->objects[OID_MAIN], (ULONG *)&menustrip);
+ GetAttr(WINDOW_MenuStrip, ami_gui2_get_object(gwin, AMI_WIN_MAIN), (ULONG *)&menustrip);
if(!menustrip) return;
if(nsoption_bool(enable_javascript) == true) {
if((ItemAddress(menustrip, ami_gui_menu_number(M_JS))->Flags & CHECKED) == 0)
@@ -690,6 +706,13 @@ void ami_gui_menu_update_checked(struct gui_window_2 *gwin)
if(ItemAddress(menustrip, ami_gui_menu_number(M_JS))->Flags & CHECKED)
ItemAddress(menustrip, ami_gui_menu_number(M_JS))->Flags ^= CHECKED;
}
+ if(nsoption_bool(author_level_css) == true) {
+ if((ItemAddress(menustrip, ami_gui_menu_number(M_CSS))->Flags & CHECKED) == 0)
+ ItemAddress(menustrip, ami_gui_menu_number(M_CSS))->Flags ^= CHECKED;
+ } else {
+ if(ItemAddress(menustrip, ami_gui_menu_number(M_CSS))->Flags & CHECKED)
+ ItemAddress(menustrip, ami_gui_menu_number(M_CSS))->Flags ^= CHECKED;
+ }
if(nsoption_bool(foreground_images) == true) {
if((ItemAddress(menustrip, ami_gui_menu_number(M_IMGFORE))->Flags & CHECKED) == 0)
ItemAddress(menustrip, ami_gui_menu_number(M_IMGFORE))->Flags ^= CHECKED;
@@ -706,24 +729,24 @@ void ami_gui_menu_update_checked(struct gui_window_2 *gwin)
ItemAddress(menustrip, ami_gui_menu_number(M_IMGBACK))->Flags ^= CHECKED;
}
- ResetMenuStrip(gwin->win, menustrip);
+ ResetMenuStrip(ami_gui2_get_window(gwin), menustrip);
}
void ami_gui_menu_update_disabled(struct gui_window *g, struct hlcache_handle *c)
{
- struct Window *win = g->shared->win;
+ struct Window *win = ami_gui_get_window(g);
if(nsoption_bool(kiosk_mode) == true) return;
if(content_get_type(c) <= CONTENT_CSS)
{
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_SAVETXT, false);
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_SAVECOMP, false);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_SAVETXT, false);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_SAVECOMP, false);
#ifdef WITH_PDF_EXPORT
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_SAVEPDF, false);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_SAVEPDF, false);
#endif
#if 0
- if(browser_window_get_editor_flags(g->bw) & BW_EDITOR_CAN_COPY) {
+ if(browser_window_get_editor_flags(ami_gui_get_browser_window(g)) & BW_EDITOR_CAN_COPY) {
OnMenu(win,AMI_MENU_COPY);
OnMenu(win,AMI_MENU_CLEAR);
} else {
@@ -731,39 +754,39 @@ void ami_gui_menu_update_disabled(struct gui_window *g, struct hlcache_handle *c
OffMenu(win,AMI_MENU_CLEAR);
}
- if(browser_window_get_editor_flags(g->bw) & BW_EDITOR_CAN_CUT)
+ if(browser_window_get_editor_flags(ami_gui_get_browser_window(g)) & BW_EDITOR_CAN_CUT)
OnMenu(win,AMI_MENU_CUT);
else
OffMenu(win,AMI_MENU_CUT);
- if(browser_window_get_editor_flags(g->bw) & BW_EDITOR_CAN_PASTE)
+ if(browser_window_get_editor_flags(ami_gui_get_browser_window(g)) & BW_EDITOR_CAN_PASTE)
OnMenu(win,AMI_MENU_PASTE);
else
OffMenu(win,AMI_MENU_PASTE);
#else
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_CUT, false);
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_COPY, false);
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_PASTE, false);
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_CLEAR, false);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_CUT, false);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_COPY, false);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_PASTE, false);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_CLEAR, false);
#endif
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_SELALL, false);
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_FIND, false);
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_SAVEIFF, true);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_SELALL, false);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_FIND, false);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_SAVEIFF, true);
}
else
{
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_CUT, true);
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_PASTE, true);
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_CLEAR, true);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_CUT, true);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_PASTE, true);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_CLEAR, true);
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_SAVETXT, true);
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_SAVECOMP, true);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_SAVETXT, true);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_SAVECOMP, true);
#ifdef WITH_PDF_EXPORT
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_SAVEPDF, true);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_SAVEPDF, true);
#endif
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_SELALL, true);
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_FIND, true);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_SELALL, true);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_FIND, true);
#ifdef WITH_NS_SVG
if(content_get_bitmap(c) || (ami_mime_compare(c, "svg") == true))
@@ -771,13 +794,13 @@ void ami_gui_menu_update_disabled(struct gui_window *g, struct hlcache_handle *c
if(content_get_bitmap(c))
#endif
{
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_COPY, false);
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_SAVEIFF, false);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_COPY, false);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_SAVEIFF, false);
}
else
{
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_COPY, true);
- ami_gui_menu_set_disabled(win, g->shared->imenu, M_SAVEIFF, true);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_COPY, true);
+ ami_gui_menu_set_disabled(win, ami_gui_get_menu(g), M_SAVEIFF, true);
}
}
}
@@ -919,6 +942,10 @@ static void ami_init_menulabs(struct ami_menu_data **md)
if(nsoption_bool(enable_javascript) == true)
js_flags |= CHECKED;
+ UWORD css_flags = CHECKIT | MENUTOGGLE;
+ if(nsoption_bool(author_level_css) == true)
+ css_flags |= CHECKED;
+
UWORD imgfore_flags = CHECKIT | MENUTOGGLE;
if(nsoption_bool(foreground_images) == true)
imgfore_flags |= CHECKED;
@@ -1007,6 +1034,8 @@ static void ami_init_menulabs(struct ami_menu_data **md)
ami_menu_item_browser_backimg, NULL, imgback_flags);
ami_menu_alloc_item(md, M_JS, NM_ITEM, "EnableJS", NULL, NULL,
ami_menu_item_browser_enablejs, NULL, js_flags);
+ ami_menu_alloc_item(md, M_CSS, NM_ITEM, "EnableCSS", NULL, NULL,
+ ami_menu_item_browser_enablecss, NULL, css_flags);
ami_menu_alloc_item(md, M_BAR_B4, NM_ITEM, NM_BARLABEL, NULL, NULL, NULL, NULL, 0);
ami_menu_alloc_item(md, M_REDRAW, NM_ITEM, "Redraw", NULL, "TBImages:list_wand",
ami_menu_item_browser_redraw, NULL, 0);
@@ -1035,26 +1064,32 @@ struct Menu *ami_gui_menu_create(struct gui_window_2 *gwin)
if(LIB_IS_AT_LEAST((struct Library *)IntuitionBase, 54, 6)) {
#ifdef __amigaos4__
if(gui_menu != NULL) {
- gwin->imenu = gui_menu;
+ ami_gui2_set_menu(gwin, gui_menu);
gui_menu_count++;
- return gwin->imenu;
+ return gui_menu;
}
ami_init_menulabs(gui_menu_data);
ami_menu_scan(gui_menu_data);
ami_menu_arexx_scan(gui_menu_data);
- gwin->imenu = ami_menu_layout(gui_menu_data, AMI_MENU_AREXX_MAX);
+ gui_menu = ami_menu_layout(gui_menu_data, AMI_MENU_AREXX_MAX);
- gui_menu = gwin->imenu;
+ ami_gui2_set_menu(gwin, gui_menu);
gui_menu_count++;
+ return gui_menu;
#endif
} else {
- ami_init_menulabs(gwin->menu_data);
- ami_menu_scan(gwin->menu_data);
- ami_menu_arexx_scan(gwin->menu_data);
- gwin->imenu = ami_menu_layout(gwin->menu_data, AMI_MENU_AREXX_MAX);
+ struct Menu *temp_menu;
+ struct ami_menu_data **md = ami_gui2_get_menu_data(gwin);
+
+ ami_init_menulabs(md);
+ ami_menu_scan(md);
+ ami_menu_arexx_scan(md);
+ temp_menu = ami_menu_layout(md, AMI_MENU_AREXX_MAX);
+ ami_gui2_set_menu(gwin, temp_menu);
+ return temp_menu;
}
- return gwin->imenu;
+ return NULL; // shouldn't get this far
}
static void ami_free_menulabs(struct ami_menu_data **md)
@@ -1089,13 +1124,24 @@ static void ami_free_menulabs(struct ami_menu_data **md)
}
}
+void ami_gui_menu_freemenus(struct Menu *menu, struct ami_menu_data **md)
+{
+ if(menu != NULL) {
+ FreeMenus(menu);
+ }
+
+ if(md != NULL) {
+ ami_free_menulabs(md);
+ }
+}
+
void ami_gui_menu_free(struct gui_window_2 *gwin)
{
if(LIB_IS_AT_LEAST((struct Library *)IntuitionBase, 54, 6)) {
#ifdef __amigaos4__
gui_menu_count--;
- SetAttrs(gwin->objects[OID_MAIN], WINDOW_MenuStrip, NULL, TAG_DONE);
+ SetAttrs(ami_gui2_get_object(gwin, AMI_WIN_MAIN), WINDOW_MenuStrip, NULL, TAG_DONE);
if(gui_menu_count == 0) {
ami_free_menulabs(gui_menu_data);
@@ -1105,8 +1151,7 @@ void ami_gui_menu_free(struct gui_window_2 *gwin)
}
#endif
} else {
- ami_free_menulabs(gwin->menu_data);
- FreeMenus(gwin->imenu);
+ ami_gui2_set_menu(gwin, NULL);
}
}
diff --git a/frontends/amiga/gui_menu.h b/frontends/amiga/gui_menu.h
index 3490fe9c1..ae36397c5 100644
--- a/frontends/amiga/gui_menu.h
+++ b/frontends/amiga/gui_menu.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2017 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ * Copyright 2008-2024 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -78,13 +78,14 @@ enum {
M_IMGFORE,
M_IMGBACK,
M_JS,
+ M_CSS,
M_BAR_B4,
M_REDRAW,
/* Hotlist menu */
M_HOTLIST,
M_HLADD,
M_HLSHOW,
- M_BAR_H1, // 47
+ M_BAR_H1, // 48
AMI_MENU_HOTLIST, /* Where the hotlist entries start */
AMI_MENU_HOTLIST_MAX = AMI_MENU_HOTLIST + AMI_HOTLIST_ITEMS,
/* Settings menu */
@@ -109,6 +110,7 @@ struct gui_window;
struct gui_window_2;
struct hlcache_handle;
struct Window;
+struct ami_menu_data;
ULONG ami_gui_menu_number(int item);
struct Menu *ami_gui_menu_create(struct gui_window_2 *gwin);
@@ -154,5 +156,10 @@ void ami_gui_menu_refresh_hotlist(void);
* \return true if NetSurf has been quit
*/
bool ami_gui_menu_quit_selected(void);
+
+/**
+ * Frees a menu. Only used on OS3 and old OS4.
+ */
+void ami_gui_menu_freemenus(struct Menu *menu, struct ami_menu_data **md);
#endif
diff --git a/frontends/amiga/gui_options.c b/frontends/amiga/gui_options.c
index cc3a915df..c8c51b012 100755
--- a/frontends/amiga/gui_options.c
+++ b/frontends/amiga/gui_options.c
@@ -83,7 +83,8 @@
enum
{
- GID_OPTS_MAIN = GID_MAIN,
+ OID_MAIN = 0,
+ GID_OPTS_MAIN,
GID_OPTS_HOMEPAGE,
GID_OPTS_HOMEPAGE_DEFAULT,
GID_OPTS_HOMEPAGE_CURRENT,
@@ -93,6 +94,7 @@ enum
GID_OPTS_FROMLOCALE,
GID_OPTS_HISTORY,
GID_OPTS_JAVASCRIPT,
+ GID_OPTS_ENABLECSS,
GID_OPTS_REFERRAL,
GID_OPTS_DONOTTRACK,
GID_OPTS_FASTSCROLL,
@@ -101,6 +103,9 @@ enum
GID_OPTS_SCREENNAME,
GID_OPTS_WIN_SIMPLE,
GID_OPTS_THEME,
+ GID_OPTS_THEMEPAGE,
+ GID_OPTS_DARK,
+ GID_OPTS_LIGHT,
GID_OPTS_PTRTRUE,
GID_OPTS_PTROS,
GID_OPTS_PROXY,
@@ -115,7 +120,6 @@ enum
GID_OPTS_NATIVEBM,
GID_OPTS_SCALEQ,
GID_OPTS_DITHERQ,
- GID_OPTS_ANIMSPEED,
GID_OPTS_ANIMDISABLE,
GID_OPTS_DPI_Y,
GID_OPTS_FONT_SANS,
@@ -210,6 +214,7 @@ enum
#define OPTS_LAST LAB_OPTS_LAST
#define OPTS_MAX_TABS 10
#define OPTS_MAX_SCREEN 4
+#define OPTS_MAX_THEMEPAGE 3
#define OPTS_MAX_PROXY 5
#define OPTS_MAX_NATIVEBM 4
#define OPTS_MAX_DITHER 4
@@ -227,6 +232,7 @@ struct ami_gui_opts_window {
#ifndef __amigaos4__
struct List clicktablist;
struct List screenoptslist;
+ struct List pagethemeoptslist;
struct List proxyoptslist;
struct List nativebmoptslist;
struct List ditheroptslist;
@@ -246,6 +252,7 @@ static struct ami_gui_opts_window *gow = NULL;
static CONST_STRPTR tabs[OPTS_MAX_TABS];
static STRPTR screenopts[OPTS_MAX_SCREEN];
+static CONST_STRPTR pagethemeopts[OPTS_MAX_THEMEPAGE];
static CONST_STRPTR proxyopts[OPTS_MAX_PROXY];
static CONST_STRPTR nativebmopts[OPTS_MAX_NATIVEBM];
static CONST_STRPTR ditheropts[OPTS_MAX_DITHER];
@@ -333,6 +340,10 @@ static void ami_gui_opts_setup(struct ami_gui_opts_window *gow)
screenopts[2] = (char *)ami_utf8_easy((char *)messages_get("ScreenPublic"));
screenopts[3] = NULL;
+ pagethemeopts[0] = (char *)ami_utf8_easy((char *)messages_get("Light"));
+ pagethemeopts[1] = (char *)ami_utf8_easy((char *)messages_get("Dark"));
+ pagethemeopts[2] = NULL;
+
proxyopts[0] = (char *)ami_utf8_easy((char *)messages_get("ProxyNone"));
proxyopts[1] = (char *)ami_utf8_easy((char *)messages_get("ProxyNoAuth"));
proxyopts[2] = (char *)ami_utf8_easy((char *)messages_get("ProxyBasic"));
@@ -359,10 +370,15 @@ static void ami_gui_opts_setup(struct ami_gui_opts_window *gow)
gadlab[GID_OPTS_FROMLOCALE] = (char *)ami_utf8_easy((char *)messages_get("LocaleLang"));
gadlab[GID_OPTS_HISTORY] = (char *)ami_utf8_easy((char *)messages_get("HistoryAge"));
gadlab[GID_OPTS_JAVASCRIPT] = (char *)ami_utf8_easy((char *)messages_get("EnableJS"));
+ gadlab[GID_OPTS_ENABLECSS] = (char *)ami_utf8_easy((char *)messages_get("EnableCSS"));
gadlab[GID_OPTS_REFERRAL] = (char *)ami_utf8_easy((char *)messages_get("SendReferer"));
gadlab[GID_OPTS_DONOTTRACK] = (char *)ami_utf8_easy((char *)messages_get("DoNotTrack"));
gadlab[GID_OPTS_FASTSCROLL] = (char *)ami_utf8_easy((char *)messages_get("FastScrolling"));
gadlab[GID_OPTS_WIN_SIMPLE] = (char *)ami_utf8_easy((char *)messages_get("SimpleRefresh"));
+ gadlab[GID_OPTS_THEME] = (char *)ami_utf8_easy((char *)messages_get("ThemeGUI"));
+ gadlab[GID_OPTS_THEMEPAGE] = (char *)ami_utf8_easy((char *)messages_get("ThemePage"));
+ gadlab[GID_OPTS_DARK] = (char *)ami_utf8_easy((char *)messages_get("Dark"));
+ gadlab[GID_OPTS_LIGHT] = (char *)ami_utf8_easy((char *)messages_get("Light"));
gadlab[GID_OPTS_PTRTRUE] = (char *)ami_utf8_easy((char *)messages_get("TrueColour"));
gadlab[GID_OPTS_PTROS] = (char *)ami_utf8_easy((char *)messages_get("OSPointers"));
gadlab[GID_OPTS_PROXY] = (char *)ami_utf8_easy((char *)messages_get("ProxyType"));
@@ -376,7 +392,6 @@ static void ami_gui_opts_setup(struct ami_gui_opts_window *gow)
gadlab[GID_OPTS_NATIVEBM] = (char *)ami_utf8_easy((char *)messages_get("CacheNative"));
gadlab[GID_OPTS_SCALEQ] = (char *)ami_utf8_easy((char *)messages_get("ScaleQuality"));
gadlab[GID_OPTS_DITHERQ] = (char *)ami_utf8_easy((char *)messages_get("DitherQuality"));
- gadlab[GID_OPTS_ANIMSPEED] = (char *)ami_utf8_easy((char *)messages_get("AnimSpeedLimit"));
gadlab[GID_OPTS_DPI_Y] = (char *)ami_utf8_easy((char *)messages_get("ResolutionY"));
gadlab[GID_OPTS_ANIMDISABLE] = (char *)ami_utf8_easy((char *)messages_get("AnimDisable"));
gadlab[GID_OPTS_FONT_SANS] = (char *)ami_utf8_easy((char *)messages_get("FontSans"));
@@ -422,7 +437,6 @@ static void ami_gui_opts_setup(struct ami_gui_opts_window *gow)
gadlab[LAB_OPTS_WINTITLE] = (char *)ami_utf8_easy((char *)messages_get("Preferences"));
gadlab[LAB_OPTS_RESTART] = (char *)ami_utf8_easy((char *)messages_get("NeedRestart"));
gadlab[LAB_OPTS_DAYS] = (char *)ami_utf8_easy((char *)messages_get("Days"));
- gadlab[LAB_OPTS_SECS] = (char *)ami_utf8_easy((char *)messages_get("AnimSpeedFrames"));
gadlab[LAB_OPTS_PT] = (char *)ami_utf8_easy((char *)messages_get("Pt"));
gadlab[LAB_OPTS_MM] = (char *)ami_utf8_easy((char *)messages_get("MM"));
gadlab[LAB_OPTS_MB] = (char *)ami_utf8_easy((char *)messages_get("MBytes"));
@@ -468,6 +482,7 @@ static void ami_gui_opts_setup(struct ami_gui_opts_window *gow)
#ifndef __amigaos4__
ami_gui_opts_array_to_list(&gow->clicktablist, tabs, NSA_LIST_CLICKTAB);
ami_gui_opts_array_to_list(&gow->screenoptslist, screenopts, NSA_LIST_RADIO);
+ ami_gui_opts_array_to_list(&gow->pagethemeoptslist, pagethemeopts, NSA_LIST_CHOOSER);
ami_gui_opts_array_to_list(&gow->proxyoptslist, proxyopts, NSA_LIST_CHOOSER);
ami_gui_opts_array_to_list(&gow->nativebmoptslist, nativebmopts, NSA_LIST_CHOOSER);
ami_gui_opts_array_to_list(&gow->ditheroptslist, ditheropts, NSA_LIST_CHOOSER);
@@ -499,6 +514,7 @@ static void ami_gui_opts_free(struct ami_gui_opts_window *gow)
#ifndef __amigaos4__
ami_gui_opts_free_list(&gow->clicktablist, NSA_LIST_CLICKTAB);
ami_gui_opts_free_list(&gow->screenoptslist, NSA_LIST_RADIO);
+ ami_gui_opts_free_list(&gow->pagethemeoptslist, NSA_LIST_CHOOSER);
ami_gui_opts_free_list(&gow->proxyoptslist, NSA_LIST_CHOOSER);
ami_gui_opts_free_list(&gow->nativebmoptslist, NSA_LIST_CHOOSER);
ami_gui_opts_free_list(&gow->ditheroptslist, NSA_LIST_CHOOSER);
@@ -513,12 +529,11 @@ void ami_gui_opts_open(void)
ULONG proxytype = 0;
BOOL screenmodedisabled = FALSE, screennamedisabled = FALSE;
BOOL proxyhostdisabled = TRUE, proxyauthdisabled = TRUE, proxybypassdisabled = FALSE;
- BOOL disableanims, animspeeddisabled = FALSE, acceptlangdisabled = FALSE;
+ BOOL disableanims, acceptlangdisabled = FALSE;
BOOL scaleselected = nsoption_bool(scale_quality), scaledisabled = FALSE;
BOOL ditherdisable = TRUE;
BOOL download_notify_disabled = FALSE, tab_always_show_disabled = FALSE;
BOOL ptr_disable = FALSE;
- char animspeed[10];
char *homepage_url_lc = ami_utf8_easy(nsoption_charp(homepage_url));
struct TextAttr fontsans, fontserif, fontmono, fontcursive, fontfantasy;
@@ -582,17 +597,13 @@ void ami_gui_opts_open(void)
proxybypassdisabled = TRUE;
}
- sprintf(animspeed,"%.2f",(float)(nsoption_int(minimum_gif_delay)/100.0));
-
if(nsoption_bool(animate_images))
{
disableanims = FALSE;
- animspeeddisabled = FALSE;
}
else
{
disableanims = TRUE;
- animspeeddisabled = TRUE;
}
if(nsoption_bool(accept_lang_locale))
@@ -656,8 +667,8 @@ void ami_gui_opts_open(void)
WA_DragBar, TRUE,
WA_CloseGadget, TRUE,
WA_SizeGadget, FALSE,
- WA_PubScreen,scrn,
- WINDOW_SharedPort,sport,
+ WA_PubScreen, ami_gui_get_screen(),
+ WINDOW_SharedPort, ami_gui_get_shared_msgport(),
WINDOW_UserData,gow,
WINDOW_IconifyGadget, FALSE,
WINDOW_Position, WPOS_CENTERSCREEN,
@@ -865,6 +876,23 @@ void ami_gui_opts_open(void)
GETFILE_ReadOnly, TRUE,
GETFILE_FullFileExpand, FALSE,
GetFileEnd,
+ CHILD_Label, LabelObj,
+ LABEL_Text, gadlab[GID_OPTS_THEME],
+ LabelEnd,
+ LAYOUT_AddChild, gow->objects[GID_OPTS_THEMEPAGE] = ChooserObj,
+ GA_ID, GID_OPTS_THEMEPAGE,
+ GA_RelVerify, TRUE,
+ CHOOSER_PopUp, TRUE,
+#ifdef __amigaos4__
+ CHOOSER_LabelArray, pagethemeopts,
+#else
+ CHOOSER_Labels, &gow->pagethemeoptslist,
+#endif
+ CHOOSER_Selected, nsoption_bool(prefer_dark_mode),
+ ChooserEnd,
+ CHILD_Label, LabelObj,
+ LABEL_Text, gadlab[GID_OPTS_THEMEPAGE],
+ LabelEnd,
LayoutEnd, // theme
CHILD_WeightedHeight, 0,
LAYOUT_AddChild, LayoutVObj,
@@ -1070,24 +1098,6 @@ void ami_gui_opts_open(void)
LAYOUT_SpaceOuter, TRUE,
LAYOUT_BevelStyle, BVS_GROUP,
LAYOUT_Label, gadlab[GRP_OPTS_ANIMS],
- LAYOUT_AddChild, LayoutHObj,
- LAYOUT_LabelColumn, PLACETEXT_RIGHT,
- LAYOUT_AddChild, gow->objects[GID_OPTS_ANIMSPEED] = StringObj,
- GA_ID, GID_OPTS_ANIMSPEED,
- GA_RelVerify, TRUE,
- GA_Disabled, animspeeddisabled,
- STRINGA_HookType, SHK_FLOAT,
- STRINGA_TextVal, animspeed,
- STRINGA_BufferPos,0,
- StringEnd,
- CHILD_WeightedWidth, 0,
- CHILD_Label, LabelObj,
- LABEL_Text, gadlab[LAB_OPTS_SECS],
- LabelEnd,
- LayoutEnd,
- CHILD_Label, LabelObj,
- LABEL_Text, gadlab[GID_OPTS_ANIMSPEED],
- LabelEnd,
LAYOUT_AddChild, gow->objects[GID_OPTS_ANIMDISABLE] = CheckBoxObj,
GA_ID, GID_OPTS_ANIMDISABLE,
GA_RelVerify, TRUE,
@@ -1491,6 +1501,12 @@ void ami_gui_opts_open(void)
GA_Selected, !nsoption_bool(core_select_menu),
GA_Disabled, !ami_selectmenu_is_safe(),
CheckBoxEnd,
+ LAYOUT_AddChild, gow->objects[GID_OPTS_ENABLECSS] = CheckBoxObj,
+ GA_ID, GID_OPTS_ENABLECSS,
+ GA_RelVerify, TRUE,
+ GA_Text, gadlab[GID_OPTS_ENABLECSS],
+ GA_Selected, nsoption_bool(author_level_css),
+ CheckBoxEnd,
LayoutEnd, // misc
CHILD_WeightedHeight, 0,
@@ -1683,7 +1699,6 @@ void ami_gui_opts_open(void)
static void ami_gui_opts_use(bool save)
{
ULONG data, id = 0;
- float animspeed;
struct TextAttr *tattr;
char *dot;
bool rescan_fonts = false;
@@ -1735,7 +1750,16 @@ static void ami_gui_opts_use(bool save)
} else {
nsoption_set_bool(do_not_track, false);
}
-
+
+ GetAttr(GA_Selected,gow->objects[GID_OPTS_ENABLECSS],(ULONG *)&data);
+ if (data) {
+ nsoption_set_bool(author_level_css, true);
+ } else {
+ nsoption_set_bool(author_level_css, false);
+ }
+
+ ami_gui_menu_set_checked(NULL, M_CSS, nsoption_bool(author_level_css));
+
GetAttr(GA_Selected,gow->objects[GID_OPTS_FASTSCROLL],(ULONG *)&data);
if (data) {
nsoption_set_bool(faster_scroll, true);
@@ -1780,6 +1804,13 @@ static void ami_gui_opts_use(bool save)
GetAttr(GETFILE_Drawer,gow->objects[GID_OPTS_THEME],(ULONG *)&data);
nsoption_set_charp(theme, (char *)strdup((char *)data));
+ GetAttr(CHOOSER_Selected,gow->objects[GID_OPTS_THEMEPAGE],(ULONG *)&data);
+ if(data) {
+ nsoption_set_bool(prefer_dark_mode, true);
+ } else {
+ nsoption_set_bool(prefer_dark_mode, false);
+ }
+
GetAttr(GA_Selected,gow->objects[GID_OPTS_PTRTRUE],(ULONG *)&data);
if (data) {
nsoption_set_bool(truecolour_mouse_pointers, true);
@@ -1834,10 +1865,6 @@ static void ami_gui_opts_use(bool save)
GetAttr(CHOOSER_Selected,gow->objects[GID_OPTS_DITHERQ],(ULONG *)&nsoption_int(dither_quality));
- GetAttr(STRINGA_TextVal,gow->objects[GID_OPTS_ANIMSPEED],(ULONG *)&data);
- animspeed = strtof((char *)data, NULL);
- nsoption_set_int(minimum_gif_delay, (int)(animspeed * 100));
-
GetAttr(GA_Selected,gow->objects[GID_OPTS_ANIMDISABLE],(ULONG *)&data);
if(data) {
nsoption_set_bool(animate_images, false);
@@ -2108,10 +2135,10 @@ static BOOL ami_gui_opts_event(void *w)
case WMHI_GADGETHELP:
if((result & WMHI_GADGETMASK) == 0) {
/* Pointer not over our window */
- ami_help_open(AMI_HELP_MAIN, scrn);
+ ami_help_open(AMI_HELP_MAIN, ami_gui_get_screen());
} else {
/* TODO: Make this sensitive to the tab the user is currently on */
- ami_help_open(AMI_HELP_PREFS, scrn);
+ ami_help_open(AMI_HELP_PREFS, ami_gui_get_screen());
}
break;
@@ -2140,9 +2167,9 @@ static BOOL ami_gui_opts_event(void *w)
break;
case GID_OPTS_HOMEPAGE_CURRENT:
- if(cur_gw) RefreshSetGadgetAttrs((struct Gadget *)gow->objects[GID_OPTS_HOMEPAGE],
+ if(ami_gui_get_active_gw()) RefreshSetGadgetAttrs((struct Gadget *)gow->objects[GID_OPTS_HOMEPAGE],
gow->win, NULL, STRINGA_TextVal,
- nsurl_access(browser_window_get_url(cur_gw->bw)), TAG_DONE);
+ nsurl_access(browser_window_access_url(ami_gui_get_browser_window(ami_gui_get_active_gw()))), TAG_DONE);
break;
case GID_OPTS_HOMEPAGE_BLANK:
@@ -2249,8 +2276,6 @@ static BOOL ami_gui_opts_event(void *w)
break;
case GID_OPTS_ANIMDISABLE:
- RefreshSetGadgetAttrs((struct Gadget *)gow->objects[GID_OPTS_ANIMSPEED],
- gow->win,NULL, GA_Disabled, code, TAG_DONE);
break;
case GID_OPTS_FONT_SANS:
diff --git a/frontends/amiga/history.c b/frontends/amiga/history.c
index e724f3e70..fd33a67f3 100644
--- a/frontends/amiga/history.c
+++ b/frontends/amiga/history.c
@@ -200,10 +200,10 @@ ami_history_global_drag_end(struct ami_corewindow *ami_cw, int x, int y)
}
if((ok == false) || (url == NULL)) {
- DisplayBeep(scrn);
+ ami_gui_beep();
} else if(url) {
if((gwin = ami_window_at_pointer(AMINS_WINDOW))) {
- browser_window_navigate(gwin->gw->bw,
+ browser_window_navigate(ami_gui2_get_browser_window(gwin),
url,
NULL,
BW_NAVIGATE_HISTORY,
@@ -233,7 +233,7 @@ HOOKF(void, ami_history_global_menu_item_project_export, APTR, window, struct In
ASLFR_Window, ami_cw->win,
ASLFR_SleepWindow, TRUE,
ASLFR_TitleText, messages_get("NetSurf"),
- ASLFR_Screen, scrn,
+ ASLFR_Screen, ami_gui_get_screen(),
ASLFR_InitialFile, "history.html",
TAG_DONE)) {
strlcpy(fname, savereq->fr_Drawer, 1024);
@@ -384,7 +384,7 @@ ami_history_global_create_window(struct ami_history_global_window *history_win)
WA_Left, nsoption_int(history_window_xpos),
WA_Width, nsoption_int(history_window_xsize),
WA_Height, nsoption_int(history_window_ysize),
- WA_PubScreen, scrn,
+ WA_PubScreen, ami_gui_get_screen(),
WA_ReportMouse, TRUE,
refresh_mode, TRUE,
WA_IDCMP, IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_NEWSIZE |
@@ -393,7 +393,7 @@ ami_history_global_create_window(struct ami_history_global_window *history_win)
WINDOW_IDCMPHook, &ami_cw->idcmp_hook,
WINDOW_IDCMPHookBits, IDCMP_IDCMPUPDATE | IDCMP_EXTENDEDMOUSE |
IDCMP_SIZEVERIFY | IDCMP_REFRESHWINDOW,
- WINDOW_SharedPort, sport,
+ WINDOW_SharedPort, ami_gui_get_shared_msgport(),
WINDOW_HorizProp, 1,
WINDOW_VertProp, 1,
WINDOW_UserData, history_win,
diff --git a/frontends/amiga/history_local.c b/frontends/amiga/history_local.c
index 0ae9cc040..5ad77ead7 100644
--- a/frontends/amiga/history_local.c
+++ b/frontends/amiga/history_local.c
@@ -81,13 +81,22 @@ ami_history_local_destroy(struct ami_history_local_window *history_local_win)
res = local_history_fini(history_local_win->session);
if (res == NSERROR_OK) {
- history_local_win->gw->hw = NULL;
+ ami_gui_set_history_window(history_local_win->gw, NULL);
res = ami_corewindow_fini(&history_local_win->core); /* closes the window for us */
history_local_window = NULL;
}
return res;
}
+static void ami_history_local_destroy_cw(struct ami_corewindow *ami_cw)
+{
+ struct ami_history_local_window *history_local_win;
+ /* technically degenerate container of */
+ history_local_win = (struct ami_history_local_window *)ami_cw;
+
+ ami_history_local_destroy(history_local_win);
+}
+
/**
* callback for mouse action for local history on core window
*
@@ -200,7 +209,7 @@ ami_history_local_create_window(struct ami_history_local_window *history_local_w
WA_SizeBRight, TRUE,
WA_Width, 100,
WA_Height, 100,
- WA_PubScreen, scrn,
+ WA_PubScreen, ami_gui_get_screen(),
WA_ReportMouse, TRUE,
refresh_mode, TRUE,
WA_IDCMP, IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_NEWSIZE |
@@ -209,7 +218,7 @@ ami_history_local_create_window(struct ami_history_local_window *history_local_w
WINDOW_IDCMPHook, &ami_cw->idcmp_hook,
WINDOW_IDCMPHookBits, IDCMP_IDCMPUPDATE | IDCMP_EXTENDEDMOUSE |
IDCMP_SIZEVERIFY | IDCMP_REFRESHWINDOW,
- WINDOW_SharedPort, sport,
+ WINDOW_SharedPort, ami_gui_get_shared_msgport(),
WINDOW_HorizProp, 1,
WINDOW_VertProp, 1,
WINDOW_UserData, history_local_win,
@@ -244,8 +253,8 @@ nserror ami_history_local_present(struct gui_window *gw)
if(history_local_window != NULL) {
//windowtofront()
- if (gw->hw != NULL) {
- res = local_history_set(gw->hw->session, gw->bw);
+ if (ami_gui_get_history_window(gw) != NULL) {
+ res = local_history_set(ami_gui_get_history_window(gw)->session, ami_gui_get_browser_window(gw));
return res;
}
@@ -271,7 +280,7 @@ nserror ami_history_local_present(struct gui_window *gw)
ncwin->core.draw = ami_history_local_draw;
ncwin->core.key = ami_history_local_key;
ncwin->core.mouse = ami_history_local_mouse;
- ncwin->core.close = ami_history_local_destroy;
+ ncwin->core.close = ami_history_local_destroy_cw;
ncwin->core.event = NULL;
ncwin->core.drag_end = NULL;
ncwin->core.icon_drop = NULL;
@@ -286,7 +295,7 @@ nserror ami_history_local_present(struct gui_window *gw)
res = local_history_init(ncwin->core.cb_table,
(struct core_window *)ncwin,
- gw->bw,
+ ami_gui_get_browser_window(gw),
&ncwin->session);
if (res != NSERROR_OK) {
ami_utf8_free(ncwin->core.wintitle);
@@ -308,7 +317,9 @@ nserror ami_history_local_present(struct gui_window *gw)
ncwin->gw = gw;
history_local_window = ncwin;
- gw->hw = ncwin;
+ ami_gui_set_history_window(gw, ncwin);
+
+ local_history_scroll_to_cursor(ncwin->session);
return NSERROR_OK;
}
diff --git a/frontends/amiga/history_local.h b/frontends/amiga/history_local.h
index 72ba7fa8b..0a265d821 100644
--- a/frontends/amiga/history_local.h
+++ b/frontends/amiga/history_local.h
@@ -16,8 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef AMIGA_HISTORY_GLOBAL_H
-#define AMIGA_HISTORY_GLOBAL_H
+#ifndef AMIGA_HISTORY_LOCAL_H
+#define AMIGA_HISTORY_LOCAL_H
struct gui_window;
struct ami_history_local_window;
diff --git a/frontends/amiga/hotlist.c b/frontends/amiga/hotlist.c
index c7efe9148..9a1d423bc 100644
--- a/frontends/amiga/hotlist.c
+++ b/frontends/amiga/hotlist.c
@@ -251,10 +251,10 @@ ami_hotlist_drag_end(struct ami_corewindow *ami_cw, int x, int y)
}
if((ok == false) || (url == NULL)) {
- DisplayBeep(scrn);
+ ami_gui_beep();
} else if(url) {
if((gwin = ami_window_at_pointer(AMINS_WINDOW))) {
- browser_window_navigate(gwin->gw->bw,
+ browser_window_navigate(ami_gui2_get_browser_window(gwin),
url,
NULL,
BW_NAVIGATE_HISTORY,
@@ -313,7 +313,7 @@ HOOKF(void, ami_hotlist_menu_item_project_export, APTR, window, struct IntuiMess
ASLFR_Window, ami_cw->win,
ASLFR_SleepWindow, TRUE,
ASLFR_TitleText, messages_get("NetSurf"),
- ASLFR_Screen, scrn,
+ ASLFR_Screen, ami_gui_get_screen(),
ASLFR_InitialFile, "hotlist.html",
TAG_DONE)) {
strlcpy(fname, savereq->fr_Drawer, 1024);
@@ -487,7 +487,7 @@ ami_hotlist_create_window(struct ami_hotlist_window *hotlist_win)
WA_Left, nsoption_int(hotlist_window_xpos),
WA_Width, nsoption_int(hotlist_window_xsize),
WA_Height, nsoption_int(hotlist_window_ysize),
- WA_PubScreen, scrn,
+ WA_PubScreen, ami_gui_get_screen(),
WA_ReportMouse, TRUE,
refresh_mode, TRUE,
WA_IDCMP, IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_NEWSIZE |
@@ -496,7 +496,7 @@ ami_hotlist_create_window(struct ami_hotlist_window *hotlist_win)
WINDOW_IDCMPHook, &ami_cw->idcmp_hook,
WINDOW_IDCMPHookBits, IDCMP_IDCMPUPDATE | IDCMP_EXTENDEDMOUSE |
IDCMP_SIZEVERIFY | IDCMP_REFRESHWINDOW,
- WINDOW_SharedPort, sport,
+ WINDOW_SharedPort, ami_gui_get_shared_msgport(),
WINDOW_HorizProp, 1,
WINDOW_VertProp, 1,
WINDOW_UserData, hotlist_win,
diff --git a/frontends/amiga/icon.c b/frontends/amiga/icon.c
index 582d355b6..2b7f61281 100644
--- a/frontends/amiga/icon.c
+++ b/frontends/amiga/icon.c
@@ -45,7 +45,10 @@
#include "netsurf/plotters.h"
#include "netsurf/bitmap.h"
#include "netsurf/content.h"
+#include "content/content.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
+#include "desktop/gui_internal.h"
#include "amiga/os3support.h"
#include "amiga/bitmap.h"
@@ -85,6 +88,17 @@ static void *amiga_icon_get_internal(const struct content *c, void *context)
return icon_c->bitmap;
}
+static bool amiga_icon_is_opaque(struct content *c)
+{
+ amiga_icon_content *icon_c = (amiga_icon_content *)c;
+
+ if (icon_c->bitmap != NULL) {
+ return guit->bitmap->get_opaque(icon_c->bitmap);
+ }
+
+ return false;
+}
+
static const content_handler amiga_icon_content_handler = {
.create = amiga_icon_create,
.data_complete = amiga_icon_convert,
@@ -93,6 +107,7 @@ static const content_handler amiga_icon_content_handler = {
.clone = amiga_icon_clone,
.get_internal = amiga_icon_get_internal,
.type = amiga_icon_content_type,
+ .is_opaque = amiga_icon_is_opaque,
.no_share = false,
};
@@ -154,7 +169,8 @@ bool amiga_icon_convert(struct content *c)
/* This loader will only work on local files, so fail if not a local path */
if(filename == NULL)
{
- msg_data.error = messages_get("NoMemory");
+ msg_data.errordata.errorcode = NSERROR_NOMEM;
+ msg_data.errordata.errormsg = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
return false;
}
@@ -166,7 +182,8 @@ bool amiga_icon_convert(struct content *c)
if(dobj == NULL)
{
- msg_data.error = messages_get("NoMemory");
+ msg_data.errordata.errorcode = NSERROR_NOMEM;
+ msg_data.errordata.errormsg = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
return false;
}
@@ -184,16 +201,18 @@ bool amiga_icon_convert(struct content *c)
return false;
}
- icon_c->bitmap = amiga_bitmap_create(width, height, BITMAP_NEW);
+ icon_c->bitmap = amiga_bitmap_create(width, height, BITMAP_NONE);
if (!icon_c->bitmap) {
- msg_data.error = messages_get("NoMemory");
+ msg_data.errordata.errorcode = NSERROR_NOMEM;
+ msg_data.errordata.errormsg = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
if(dobj) FreeDiskObject(dobj);
return false;
}
imagebuf = (ULONG *) amiga_bitmap_get_buffer(icon_c->bitmap);
if (!imagebuf) {
- msg_data.error = messages_get("NoMemory");
+ msg_data.errordata.errorcode = NSERROR_NOMEM;
+ msg_data.errordata.errormsg = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
if(dobj) FreeDiskObject(dobj);
return false;
diff --git a/frontends/amiga/iff_dr2d.c b/frontends/amiga/iff_dr2d.c
index a4c5855a1..624b501ff 100644
--- a/frontends/amiga/iff_dr2d.c
+++ b/frontends/amiga/iff_dr2d.c
@@ -120,6 +120,7 @@ bool ami_svg_to_dr2d(struct IFFHandle *iffh, const char *buffer,
if(!(PushChunk(iffh,0,ID_NAME,IFFSIZE_UNKNOWN)))
{
WriteChunkBytes(iffh,url,strlen(url));
+ WriteChunkBytes(iffh,"\0",1);
PopChunk(iffh);
}
@@ -185,6 +186,7 @@ bool ami_svg_to_dr2d(struct IFFHandle *iffh, const char *buffer,
attr->DashPattern = 1;
attr->EdgeValue = findcolour(diagram->shape[i].stroke);
}
+
attr->EdgeThick = (float) diagram->shape[i].stroke_width;
if(!(PushChunk(iffh,0,ID_ATTR,IFFSIZE_UNKNOWN)))
@@ -281,7 +283,7 @@ bool ami_svg_to_dr2d(struct IFFHandle *iffh, const char *buffer,
if(!(PushChunk(iffh, 0, ID_FONS, IFFSIZE_UNKNOWN)))
{
WriteChunkBytes(iffh, fons, sizeof(struct fons_struct));
- WriteChunkBytes(iffh, "Topaz\0", 6);
+ WriteChunkBytes(iffh, "Helvetica\0", 10);
PopChunk(iffh);
}
free(fons);
@@ -310,22 +312,27 @@ bool ami_svg_to_dr2d(struct IFFHandle *iffh, const char *buffer,
bool ami_save_svg(struct hlcache_handle *c,char *filename)
{
struct IFFHandle *iffh;
- const char *source_data;
- ULONG source_size;
+ const uint8_t *source_data;
+ size_t source_size;
- if(!ami_download_check_overwrite(filename, NULL, 0)) return false;
+ if (!ami_download_check_overwrite(filename, NULL, 0)) return false;
- if((iffh = AllocIFF())) {
- if((iffh->iff_Stream = Open(filename,MODE_NEWFILE))) {
+ if ((iffh = AllocIFF())) {
+ if ((iffh->iff_Stream = Open(filename,MODE_NEWFILE))) {
InitIFFasDOS(iffh);
}
else return false;
}
- if((OpenIFF(iffh,IFFF_WRITE))) return false;
+ if ((OpenIFF(iffh,IFFF_WRITE))) return false;
- if((source_data = content_get_source_data(c, &source_size)))
- ami_svg_to_dr2d(iffh, source_data, source_size, nsurl_access(hlcache_handle_get_url(c)));
+ source_data = content_get_source_data(c, &source_size);
+ if (source_data != NULL) {
+ ami_svg_to_dr2d(iffh,
+ (const char *)source_data,
+ source_size,
+ nsurl_access(hlcache_handle_get_url(c)));
+ }
if(iffh) CloseIFF(iffh);
if(iffh->iff_Stream) Close((BPTR)iffh->iff_Stream);
diff --git a/frontends/amiga/launch.c b/frontends/amiga/launch.c
index 10c32aeed..785f667ce 100755
--- a/frontends/amiga/launch.c
+++ b/frontends/amiga/launch.c
@@ -74,7 +74,7 @@ static void ami_openurl_free_list(struct MinList *list)
struct ami_protocol *node;
struct ami_protocol *nnode;
- if(IsMinListEmpty(list) == NULL) {
+ if(!IsMinListEmpty(list)) {
node = (struct ami_protocol *)GetHead((struct List *)list);
do
diff --git a/frontends/amiga/libs.c b/frontends/amiga/libs.c
index 305818076..eb1f21617 100644
--- a/frontends/amiga/libs.c
+++ b/frontends/amiga/libs.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ * Copyright 2014-2020 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -59,6 +59,7 @@
#define AMINS_LIB_OPEN(LIB, LIBVER, PREFIX, INTERFACE, INTVER, FAIL) \
NSLOG(netsurf, INFO, "Opening %s v%d", LIB, LIBVER); \
if((PREFIX##Base = (struct PREFIX##Base *)OpenLibrary(LIB, LIBVER))) { \
+ NSLOG(netsurf, INFO, " -> opened v%d.%d", ((struct Library *)PREFIX##Base)->lib_Version, ((struct Library *)PREFIX##Base)->lib_Revision); \
I##PREFIX = (struct PREFIX##IFace *)GetInterface((struct Library *)PREFIX##Base, INTERFACE, INTVER, NULL); \
if(I##PREFIX == NULL) { \
NSLOG(netsurf, INFO, "Failed to get %s interface v%d of %s", INTERFACE, INTVER, LIB); \
@@ -93,15 +94,17 @@
#define AMINS_CLASS_OPEN(CLASS, CLASSVER, PREFIX, CLASSGET, NEEDINTERFACE) \
NSLOG(netsurf, INFO, "Opening %s v%d", CLASS, CLASSVER); \
if((PREFIX##Base = OpenClass(CLASS, CLASSVER, &PREFIX##Class))) { \
+ NSLOG(netsurf, INFO, " -> opened v%d.%d", ((struct Library *)PREFIX##Base)->lib_Version, ((struct Library *)PREFIX##Base)->lib_Revision); \
if(NEEDINTERFACE == true) { \
NSLOG(netsurf, INFO, " + interface"); \
I##PREFIX = (struct PREFIX##IFace *)GetInterface((struct Library *)PREFIX##Base, "main", 1, NULL); \
if(I##PREFIX == NULL) { \
- NSLOG(netsurf, INFO, "Failed to get main interface v1 of %s", CLASS); \
+ NSLOG(netsurf, ERROR, "Failed to get main interface v1 of %s", CLASS); \
} \
} \
} \
if(PREFIX##Class == NULL) { \
+ NSLOG(netsurf, INFO, "Failed to open %s v%d", CLASS, CLASSVER); \
STRPTR error = ASPrintf("Unable to open %s v%d (fatal error)", CLASS, CLASSVER); \
ami_misc_fatal_error(error); \
FreeVec(error); \
@@ -110,7 +113,9 @@
#define AMINS_CLASS_CLOSE(PREFIX) \
if(I##PREFIX) DropInterface((struct Interface *)I##PREFIX); \
- if(PREFIX##Base) CloseClass(PREFIX##Base);
+ if(PREFIX##Base) CloseClass(PREFIX##Base); \
+ I##PREFIX = NULL; \
+ PREFIX##Base = NULL;
#define AMINS_CLASS_STRUCT(PREFIX) \
struct ClassLibrary *PREFIX##Base = NULL; \
@@ -121,6 +126,7 @@
#define AMINS_LIB_OPEN(LIB, LIBVER, PREFIX, INTERFACE, INTVER, FAIL) \
NSLOG(netsurf, INFO, "Opening %s v%d", LIB, LIBVER); \
if((PREFIX##Base = (struct PREFIX##Base *)OpenLibrary(LIB, LIBVER))) { \
+ NSLOG(netsurf, INFO, " -> opened v%d.%d", ((struct Library *)PREFIX##Base)->lib_Version, ((struct Library *)PREFIX##Base)->lib_Revision); \
} else { \
NSLOG(netsurf, INFO, "Failed to open %s v%d", LIB, LIBVER); \
if(FAIL == true) { \
@@ -132,7 +138,8 @@
}
#define AMINS_LIB_CLOSE(PREFIX) \
- if(PREFIX##Base) CloseLibrary((struct Library *)PREFIX##Base);
+ if(PREFIX##Base) CloseLibrary((struct Library *)PREFIX##Base); \
+ PREFIX##Base = NULL;
#define AMINS_LIB_STRUCT(PREFIX) \
struct PREFIX##Base *PREFIX##Base = NULL;
@@ -140,9 +147,11 @@
#define AMINS_CLASS_OPEN(CLASS, CLASSVER, PREFIX, CLASSGET, NEEDINTERFACE) \
NSLOG(netsurf, INFO, "Opening %s v%d", CLASS, CLASSVER); \
if((PREFIX##Base = OpenLibrary(CLASS, CLASSVER))) { \
+ NSLOG(netsurf, INFO, " -> opened v%d.%d", ((struct Library *)PREFIX##Base)->lib_Version, ((struct Library *)PREFIX##Base)->lib_Revision); \
PREFIX##Class = CLASSGET##_GetClass(); \
} \
if(PREFIX##Class == NULL) { \
+ NSLOG(netsurf, INFO, "Failed to open %s v%d", CLASS, CLASSVER); \
STRPTR error = ASPrintf("Unable to open %s v%d (fatal error)", CLASS, CLASSVER); \
ami_misc_fatal_error(error); \
FreeVec(error); \
@@ -150,7 +159,8 @@
}
#define AMINS_CLASS_CLOSE(PREFIX) \
- if(PREFIX##Base) CloseLibrary(PREFIX##Base);
+ if(PREFIX##Base) CloseLibrary(PREFIX##Base); \
+ PREFIX##Base = NULL;
#define AMINS_CLASS_STRUCT(PREFIX) \
struct Library *PREFIX##Base = NULL; \
@@ -179,6 +189,7 @@ AMINS_LIB_STRUCT(Locale);
AMINS_LIB_STRUCT(P96);
AMINS_LIB_STRUCT(Workbench);
+AMINS_LIB_STRUCT(Codesets);
AMINS_LIB_STRUCT(GuiGFX);
AMINS_CLASS_STRUCT(ARexx);
@@ -212,6 +223,7 @@ bool ami_libs_open(void)
#ifdef __amigaos4__
/* Libraries only needed on OS4 */
AMINS_LIB_OPEN("application.library", 53, Application, "application", 2, false)
+ AMINS_LIB_OPEN("dos.library", 37, DOS, "main", 1, true)
#else
/* Libraries we get automatically on OS4 but not OS3 */
AMINS_LIB_OPEN("utility.library", 37, Utility, "main", 1, true)
@@ -220,7 +232,6 @@ bool ami_libs_open(void)
AMINS_LIB_OPEN("asl.library", 37, Asl, "main", 1, true)
AMINS_LIB_OPEN("datatypes.library", 39, DataTypes, "main", 1, true)
AMINS_LIB_OPEN("diskfont.library", 40, Diskfont, "main", 1, true)
- AMINS_LIB_OPEN("dos.library", 37, DOS, "main", 1, true)
AMINS_LIB_OPEN("gadtools.library", 37, GadTools, "main", 1, true)
AMINS_LIB_OPEN("graphics.library", 40, Graphics, "main", 1, true)
AMINS_LIB_OPEN("icon.library", 44, Icon, "main", 1, true)
@@ -238,7 +249,8 @@ bool ami_libs_open(void)
AMINS_LIB_OPEN("Picasso96API.library", 0, P96, "main", 1, false)
/* Non-OS provided libraries */
- AMINS_LIB_OPEN("guigfx.library", 9, GuiGFX, "main", 1, false)
+ AMINS_LIB_OPEN("codesets.library", 6, Codesets, "main", 1, false)
+ AMINS_LIB_OPEN("guigfx.library", 9, GuiGFX, "main", 1, false)
/* NB: timer.device is opened in schedule.c (ultimately by the scheduler process).
* The library base and interface are obtained there, rather than here, due to
@@ -270,6 +282,7 @@ bool ami_libs_open(void)
AMINS_CLASS_OPEN("gadgets/integer.gadget", 41, Integer, INTEGER, false)
AMINS_CLASS_OPEN("images/label.image", 41, Label, LABEL, false)
AMINS_CLASS_OPEN("gadgets/layout.gadget", 43, Layout, LAYOUT, true)
+ AMINS_CLASS_OPEN("gadgets/listbrowser.gadget", 41, ListBrowser, LISTBROWSER, true)
AMINS_CLASS_OPEN("gadgets/radiobutton.gadget", 41, RadioButton, RADIOBUTTON, false)
AMINS_CLASS_OPEN("gadgets/scroller.gadget", 42, Scroller, SCROLLER, false)
AMINS_CLASS_OPEN("gadgets/space.gadget", 41, Space, SPACE, false)
@@ -277,10 +290,7 @@ bool ami_libs_open(void)
AMINS_CLASS_OPEN("gadgets/string.gadget", 41, String, STRING, false)
AMINS_CLASS_OPEN("window.class", 42, Window, WINDOW, false)
-#ifdef __amigaos4__
- /* BOOPSI classes only required on OS4 */
- AMINS_CLASS_OPEN("gadgets/listbrowser.gadget", 45, ListBrowser, LISTBROWSER, true)
-#else
+#ifndef __amigaos4__
/* BOOPSI classes only required prior to OS4 */
PageClass = PAGE_GetClass();
#endif
@@ -307,23 +317,21 @@ void ami_libs_close(void)
AMINS_CLASS_CLOSE(Integer)
AMINS_CLASS_CLOSE(Label)
AMINS_CLASS_CLOSE(Layout)
+ AMINS_CLASS_CLOSE(ListBrowser)
AMINS_CLASS_CLOSE(RadioButton)
AMINS_CLASS_CLOSE(Scroller)
AMINS_CLASS_CLOSE(Space)
AMINS_CLASS_CLOSE(SpeedBar)
AMINS_CLASS_CLOSE(String)
AMINS_CLASS_CLOSE(Window)
-#ifdef __amigaos4__
- AMINS_CLASS_CLOSE(ListBrowser)
-#endif
/* Libraries */
+ AMINS_LIB_CLOSE(Codesets)
AMINS_LIB_CLOSE(GuiGFX)
AMINS_LIB_CLOSE(Asl)
AMINS_LIB_CLOSE(DataTypes)
AMINS_LIB_CLOSE(Diskfont)
- AMINS_LIB_CLOSE(DOS)
AMINS_LIB_CLOSE(GadTools)
AMINS_LIB_CLOSE(Graphics)
AMINS_LIB_CLOSE(Icon)
@@ -336,6 +344,7 @@ void ami_libs_close(void)
AMINS_LIB_CLOSE(Workbench)
#ifdef __amigaos4__
AMINS_LIB_CLOSE(Application)
+ AMINS_LIB_CLOSE(DOS)
#else
AMINS_LIB_CLOSE(Utility)
#endif
diff --git a/frontends/amiga/libs.h b/frontends/amiga/libs.h
index aa3622af2..db5b65c75 100644
--- a/frontends/amiga/libs.h
+++ b/frontends/amiga/libs.h
@@ -63,6 +63,7 @@ extern Class *WindowClass;
#define LabelObj NewObject(LabelClass, NULL
#define LayoutHObj NewObject(LayoutClass, NULL, LAYOUT_Orientation, LAYOUT_ORIENT_HORIZ
#define LayoutVObj NewObject(LayoutClass, NULL, LAYOUT_Orientation, LAYOUT_ORIENT_VERT
+#define ListBrowserObj NewObject(ListBrowserClass, NULL
#ifdef __amigaos4__
#define PageObj NewObject(NULL, "page.gadget"
#else
diff --git a/frontends/amiga/login.c b/frontends/amiga/login.c
deleted file mode 100755
index 85324b0f1..000000000
--- a/frontends/amiga/login.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright 2008 Chris Young <chris@unsatisfactorysoftware.co.uk>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "amiga/os3support.h"
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <proto/exec.h>
-#include <proto/intuition.h>
-#include <proto/utility.h>
-
-#include <proto/window.h>
-#include <proto/layout.h>
-#include <proto/string.h>
-#include <proto/button.h>
-#include <proto/label.h>
-#include <classes/window.h>
-#include <gadgets/layout.h>
-#include <gadgets/string.h>
-#include <gadgets/button.h>
-#include <images/label.h>
-#include <reaction/reaction_macros.h>
-
-#include "utils/messages.h"
-#include "utils/nsurl.h"
-#include "netsurf/mouse.h"
-#include "netsurf/window.h"
-#include "netsurf/url_db.h"
-
-#include "amiga/gui.h"
-#include "amiga/libs.h"
-#include "amiga/object.h"
-#include "amiga/login.h"
-
-struct gui_login_window {
- struct ami_generic_window w;
- struct Window *win;
- Object *objects[GID_LAST];
- nserror (*cb)(bool proceed, void *pw);
- void *cbpw;
- nsurl *url;
- char *realm;
- lwc_string *host;
- char uname[256];
- char pwd[256];
-};
-
-static BOOL ami_401login_event(void *w);
-
-static const struct ami_win_event_table ami_login_table = {
- ami_401login_event,
- NULL, /* we don't explicitly close the login window at all.
- @todo check if this prevents us from quitting NetSurf */
-};
-
-void gui_401login_open(nsurl *url, const char *realm,
- nserror (*cb)(bool proceed, void *pw), void *cbpw)
-{
- const char *auth;
- struct gui_login_window *lw = calloc(1, sizeof(struct gui_login_window));
- lwc_string *host = nsurl_get_component(url, NSURL_HOST);
-
- assert(host != NULL);
-
- lw->host = host;
- lw->url = nsurl_ref(url);
- lw->realm = (char *)realm;
- lw->cb = cb;
- lw->cbpw = cbpw;
-
- auth = urldb_get_auth_details(lw->url, realm);
-
- if (auth == NULL) {
- lw->uname[0] = '\0';
- lw->pwd[0] = '\0';
- } else {
- const char *pwd;
- size_t pwd_len;
-
- pwd = strchr(auth, ':');
- assert(pwd && pwd < auth + sizeof(lw->uname));
- memcpy(lw->uname, auth, pwd - auth);
- lw->uname[pwd - auth] = '\0';
- ++pwd;
- pwd_len = strlen(pwd);
- assert(pwd_len < sizeof(lw->pwd));
- memcpy(lw->pwd, pwd, pwd_len);
- lw->pwd[pwd_len] = '\0';
- }
-
- lw->objects[OID_MAIN] = WindowObj,
- WA_ScreenTitle, ami_gui_get_screen_title(),
- WA_Title, nsurl_access(lw->url),
- WA_Activate, TRUE,
- WA_DepthGadget, TRUE,
- WA_DragBar, TRUE,
- WA_CloseGadget, FALSE,
- WA_SizeGadget, TRUE,
- WA_PubScreen,scrn,
- WINDOW_SharedPort,sport,
- WINDOW_UserData,lw,
- WINDOW_IconifyGadget, FALSE,
- WINDOW_LockHeight,TRUE,
- WINDOW_Position, WPOS_CENTERSCREEN,
- WINDOW_ParentGroup, lw->objects[GID_MAIN] = LayoutVObj,
- LAYOUT_AddChild, StringObj,
- STRINGA_TextVal,
- lwc_string_data(lw->host),
- GA_ReadOnly,TRUE,
- StringEnd,
- CHILD_Label, LabelObj,
- LABEL_Text,messages_get("Host"),
- LabelEnd,
- CHILD_WeightedHeight,0,
- LAYOUT_AddChild, StringObj,
- STRINGA_TextVal,lw->realm,
- GA_ReadOnly,TRUE,
- StringEnd,
- CHILD_Label, LabelObj,
- LABEL_Text,messages_get("Realm"),
- LabelEnd,
- CHILD_WeightedHeight,0,
- LAYOUT_AddChild, lw->objects[GID_USER] = StringObj,
- GA_ID,GID_USER,
- GA_TabCycle,TRUE,
- STRINGA_TextVal, lw->uname,
- StringEnd,
- CHILD_Label, LabelObj,
- LABEL_Text,messages_get("Username"),
- LabelEnd,
- CHILD_WeightedHeight,0,
- LAYOUT_AddChild, lw->objects[GID_PASS] = StringObj,
- GA_ID,GID_PASS,
- STRINGA_HookType,SHK_PASSWORD,
- GA_TabCycle,TRUE,
- STRINGA_TextVal, lw->pwd,
- StringEnd,
- CHILD_Label, LabelObj,
- LABEL_Text,messages_get("Password"),
- LabelEnd,
- CHILD_WeightedHeight,0,
- LAYOUT_AddChild, LayoutHObj,
- LAYOUT_AddChild, lw->objects[GID_LOGIN] = ButtonObj,
- GA_ID,GID_LOGIN,
- GA_RelVerify,TRUE,
- GA_Text,messages_get("Login"),
- GA_TabCycle,TRUE,
- ButtonEnd,
- CHILD_WeightedHeight,0,
- LAYOUT_AddChild, lw->objects[GID_CANCEL] = ButtonObj,
- GA_ID,GID_CANCEL,
- GA_RelVerify,TRUE,
- GA_Text,messages_get("Cancel"),
- GA_TabCycle,TRUE,
- ButtonEnd,
- LayoutEnd,
- CHILD_WeightedHeight,0,
- EndGroup,
- EndWindow;
-
- lw->win = (struct Window *)RA_OpenWindow(lw->objects[OID_MAIN]);
- ami_gui_win_list_add(lw, AMINS_LOGINWINDOW, &ami_login_table);
-}
-
-static void ami_401login_close(struct gui_login_window *lw)
-{
- /* If continuation exists, then forbid refetch */
- if (lw->cb != NULL)
- lw->cb(false, lw->cbpw);
-
- DisposeObject(lw->objects[OID_MAIN]);
- lwc_string_unref(lw->host);
- nsurl_unref(lw->url);
- ami_gui_win_list_remove(lw);
-}
-
-static void ami_401login_login(struct gui_login_window *lw)
-{
- ULONG *user,*pass;
- STRPTR userpass;
-
- GetAttr(STRINGA_TextVal,lw->objects[GID_USER],(ULONG *)&user);
- GetAttr(STRINGA_TextVal,lw->objects[GID_PASS],(ULONG *)&pass);
-
- userpass = ASPrintf("%s:%s",user,pass);
- urldb_set_auth_details(lw->url,lw->realm,userpass);
- FreeVec(userpass);
-
- lw->cb(true, lw->cbpw);
-
- /* Invalidate continuation */
- lw->cb = NULL;
- lw->cbpw = NULL;
-
- ami_401login_close(lw);
-}
-
-static BOOL ami_401login_event(void *w)
-{
- /* return TRUE if window destroyed */
- struct gui_login_window *lw = (struct gui_login_window *)w;
- ULONG result;
- uint16 code;
-
- while((result = RA_HandleInput(lw->objects[OID_MAIN], &code)) != WMHI_LASTMSG)
- {
- switch(result & WMHI_CLASSMASK) // class
- {
- case WMHI_GADGETUP:
- switch(result & WMHI_GADGETMASK)
- {
- case GID_LOGIN:
- ami_401login_login(lw);
- return TRUE;
- break;
-
- case GID_CANCEL:
- ami_401login_close(lw);
- return TRUE;
- break;
- }
- break;
- }
- }
- return FALSE;
-}
-
diff --git a/frontends/amiga/menu.c b/frontends/amiga/menu.c
index 1f3f981ea..85b2ec43f 100644
--- a/frontends/amiga/menu.c
+++ b/frontends/amiga/menu.c
@@ -251,7 +251,7 @@ static int ami_menu_layout_mc_recursive(Object *menu_parent, struct ami_menu_dat
MA_Image,
BitMapObj,
IA_Scalable, TRUE,
- BITMAP_Screen, scrn,
+ BITMAP_Screen, ami_gui_get_screen(),
BITMAP_SourceFile, md[j]->menuicon,
BITMAP_Masking, TRUE,
BitMapEnd,
@@ -298,6 +298,7 @@ static struct Menu *ami_menu_layout_gt(struct ami_menu_data **md, int max)
struct NewMenu *nm;
struct Menu *imenu = NULL;
struct VisualInfo *vi;
+ struct Screen *scrn = ami_gui_get_screen();
struct RastPort *rp = &scrn->RastPort;
struct DrawInfo *dri = GetScreenDrawInfo(scrn);
int space_width = TextLength(rp, " ", 1);
diff --git a/frontends/amiga/misc.c b/frontends/amiga/misc.c
index 532d2f182..57afbdd97 100755
--- a/frontends/amiga/misc.c
+++ b/frontends/amiga/misc.c
@@ -45,6 +45,7 @@
static LONG ami_misc_req(const char *message, uint32 type)
{
LONG ret = 0;
+ struct gui_window *cur_gw = ami_gui_get_active_gw();
NSLOG(netsurf, INFO, "%s", message);
#ifdef __amigaos4__
@@ -53,7 +54,7 @@ static LONG ami_misc_req(const char *message, uint32 type)
TDR_FormatString, message,
TDR_GadgetString, messages_get("OK"),
TDR_ImageType, type,
- TDR_Window, cur_gw ? cur_gw->shared->win : NULL,
+ TDR_Window, cur_gw ? ami_gui_get_window(cur_gw) : NULL,
TAG_DONE);
#else
struct EasyStruct easyreq = {
@@ -64,7 +65,7 @@ static LONG ami_misc_req(const char *message, uint32 type)
messages_get("OK"),
};
- ret = EasyRequest(cur_gw ? cur_gw->shared->win : NULL, &easyreq, NULL);
+ ret = EasyRequest(cur_gw ? ami_gui_get_window(cur_gw) : NULL, &easyreq, NULL);
#endif
return ret;
}
@@ -237,7 +238,8 @@ static nserror amiga_path_to_nsurl(const char *path, struct nsurl **url_out)
}
/**
- * returns a string with escape chars translated.
+ * returns a string with escape chars translated
+ * and string converted to local charset
* (based on remove_underscores from utils.c)
*/
@@ -245,6 +247,7 @@ char *translate_escape_chars(const char *s)
{
size_t i, ii, len;
char *ret;
+ char *outs;
len = strlen(s);
ret = malloc(len + 1);
if (ret == NULL)
@@ -259,7 +262,10 @@ char *translate_escape_chars(const char *s)
}
}
ret[ii] = '\0';
- return ret;
+
+ outs = ami_utf8_easy(ret);
+ free(ret);
+ return outs;
}
/**
diff --git a/frontends/amiga/options.h b/frontends/amiga/options.h
index a23435ca6..101558f6a 100644
--- a/frontends/amiga/options.h
+++ b/frontends/amiga/options.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 - 2012 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ * Copyright 2008 - 2020 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -47,6 +47,7 @@ NSOPTION_STRING(search_engines_file, "PROGDIR:Resources/SearchEngines")
NSOPTION_STRING(arexx_dir, "PROGDIR:Rexx")
NSOPTION_STRING(arexx_startup, "Startup.nsrx")
NSOPTION_STRING(arexx_shutdown, "Shutdown.nsrx")
+NSOPTION_BOOL(arexx_allow_exec, false)
NSOPTION_STRING(download_dir, NULL)
NSOPTION_BOOL(download_notify, true)
NSOPTION_BOOL(download_notify_progress, false)
@@ -80,7 +81,7 @@ NSOPTION_INTEGER(cookies_window_ypos, 0)
NSOPTION_INTEGER(cookies_window_xsize, 0)
NSOPTION_INTEGER(cookies_window_ysize, 0)
NSOPTION_INTEGER(web_search_width, 0)
-NSOPTION_BOOL(window_simple_refresh, false)
+NSOPTION_BOOL(window_simple_refresh, true)
NSOPTION_BOOL(resize_with_contents, false)
NSOPTION_INTEGER(reformat_delay, 0)
NSOPTION_INTEGER(redraw_tile_size_x, 0)
@@ -88,12 +89,22 @@ NSOPTION_INTEGER(redraw_tile_size_y, 0)
NSOPTION_INTEGER(monitor_aspect_x, 0)
NSOPTION_INTEGER(monitor_aspect_y, 0)
NSOPTION_BOOL(accept_lang_locale, true)
+
+/* Local charset when using iconv */
NSOPTION_STRING(local_charset, "ISO-8859-1")
+
#ifdef __amigaos4__
-/* Options relevant for OS4 only */
+/** Options relevant for OS4 only **/
+
+/* Local charset IANA number when using codesets */
+NSOPTION_INTEGER(local_codeset, 0)
+
+/* Use ExtMem */
NSOPTION_BOOL(use_extmem, true)
+
#else
-/* Options relevant for OS3 only */
+/** Options relevant for OS3 only **/
+
NSOPTION_BOOL(friend_bitmap, false)
#endif
diff --git a/frontends/amiga/os3support.c b/frontends/amiga/os3support.c
index 645496b73..98843c702 100644
--- a/frontends/amiga/os3support.c
+++ b/frontends/amiga/os3support.c
@@ -28,7 +28,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
-#include <dirent.h>
#include <proto/bullet.h>
#include <proto/exec.h>
@@ -182,6 +181,12 @@ char *strsep(char **s1, const char *s2)
return p1;
}
+int alphasort(const struct dirent **d1, const struct dirent **d2)
+{
+ /*\todo stub function, needs writing, preferably into clib2 */
+ return 0;
+}
+
int scandir(const char *dir, struct dirent ***namelist,
int (*filter)(const struct dirent *),
int (*compar)(const struct dirent **, const struct dirent **))
diff --git a/frontends/amiga/os3support.h b/frontends/amiga/os3support.h
index aa3027d36..dc4e06503 100644
--- a/frontends/amiga/os3support.h
+++ b/frontends/amiga/os3support.h
@@ -27,6 +27,7 @@
#ifndef __amigaos4__
#include <stdint.h>
+#include <dirent.h>
#include <proto/exec.h>
#include <proto/dos.h>
@@ -78,6 +79,8 @@
#define GAUGEIA_Level TAG_IGNORE
#define IA_InBorder TAG_IGNORE
#define IA_Label TAG_IGNORE
+#define LBNCA_SoftStyle TAG_IGNORE
+#define LISTBROWSER_Striping TAG_IGNORE
#define SA_Compositing TAG_IGNORE
#define SBNA_Text TAG_IGNORE
#define SBNA_HintInfo TAG_IGNORE
@@ -104,10 +107,15 @@
#define RAWKEY_F8 0x57
#define RAWKEY_F9 0x58
#define RAWKEY_F10 0x59
+#define RAWKEY_F12 0x6F
#define RAWKEY_HELP 0x5F
#define RAWKEY_HOME 0x70
#define RAWKEY_END 0x71
+/* New pens - these may not be equivalent */
+#define DISABLEDTEXTPEN HIGHLIGHTTEXTPEN
+#define TITLEPEN FILLPEN
+
/* Other constants */
#define BVS_DISPLAY BVS_NONE
#define IDCMP_EXTENDEDMOUSE 0
@@ -117,6 +125,7 @@
#define OFF_OPEN 0
#define AFF_OTAG 0
#define ML_SEPARATOR NM_BARLABEL
+#define LBS_ROWS 0
/* Renamed structures */
#define AnchorPathOld AnchorPath
@@ -249,6 +258,10 @@ char *ASPrintf(const char *fmt, ...);
/* C */
char *strlwr(char *str);
+int alphasort(const struct dirent **d1, const struct dirent **d2);
+int scandir(const char *dir, struct dirent ***namelist,
+ int (*filter)(const struct dirent *),
+ int (*compar)(const struct dirent **, const struct dirent **));
#endif
#endif
diff --git a/frontends/amiga/pageinfo.c b/frontends/amiga/pageinfo.c
new file mode 100644
index 000000000..54de0d008
--- /dev/null
+++ b/frontends/amiga/pageinfo.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2020 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Amiga implementation of page info using core windows.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <proto/intuition.h>
+
+#include <classes/window.h>
+#include <gadgets/layout.h>
+#include <gadgets/scroller.h>
+#include <gadgets/space.h>
+#include <images/label.h>
+
+#include <intuition/icclass.h>
+#include <reaction/reaction_macros.h>
+
+#include "utils/log.h"
+#include "netsurf/keypress.h"
+#include "netsurf/plotters.h"
+#include "desktop/page-info.h"
+#include "utils/messages.h"
+#include "utils/nsoption.h"
+
+#include "amiga/corewindow.h"
+#include "amiga/libs.h"
+#include "amiga/pageinfo.h"
+#include "amiga/schedule.h"
+#include "amiga/utf8.h"
+
+
+/**
+ * Amiga page info window context
+ */
+struct ami_pageinfo_window {
+ /** Amiga core window context */
+ struct ami_corewindow core;
+ /** core pageinfo */
+ struct page_info *pi;
+};
+
+/**
+ * destroy a previously created pageinfo window
+ */
+static void
+ami_pageinfo_destroy(struct ami_corewindow *ami_cw)
+{
+ nserror res;
+ struct ami_pageinfo_window *pageinfo_win = (struct ami_pageinfo_window *)ami_cw;
+ if(pageinfo_win->pi != NULL) {
+ res = page_info_destroy(pageinfo_win->pi);
+
+ if (res == NSERROR_OK) {
+ pageinfo_win->pi = NULL;
+ ami_corewindow_fini(&pageinfo_win->core); /* closes the window for us */
+ }
+ }
+}
+
+/**
+ * close pageinfo window (callback)
+ */
+static void
+ami_pageinfo_close_cb(void *p)
+{
+ ami_pageinfo_destroy((struct ami_corewindow *)p);
+}
+
+/**
+ * callback for unknown events on Amiga core window
+ * (result & WMHI_CLASSMASK) gives the class of event (eg. WMHI_GADGETUP)
+ * (result & WMHI_GADGETMASK) gives the gadget ID (eg. GID_SSLCERT_ACCEPT)
+ *
+ * \param ami_cw The Amiga core window structure.
+ * \param result event as returned by RA_HandleInput()
+ * \return TRUE if window closed during event processing
+ */
+static BOOL
+ami_pageinfo_event(struct ami_corewindow *ami_cw, ULONG result)
+{
+ if((result & WMHI_CLASSMASK) == WMHI_INACTIVE) {
+ /* Window went inactive, so schedule to close it */
+ ami_schedule(0, ami_pageinfo_close_cb, ami_cw);
+ /* NB: do not return TRUE here as we're still open for now */
+ }
+ return FALSE;
+}
+
+/**
+ * callback for mouse action for pageinfo on core window
+ *
+ * \param ami_cw The Amiga core window structure.
+ * \param mouse_state netsurf mouse state on event
+ * \param x location of event
+ * \param y location of event
+ * \return NSERROR_OK on success otherwise apropriate error code
+ */
+static nserror
+ami_pageinfo_mouse(struct ami_corewindow *ami_cw,
+ browser_mouse_state mouse_state,
+ int x, int y)
+{
+ bool did_something = false;
+ struct ami_pageinfo_window *pageinfo_win = (struct ami_pageinfo_window *)ami_cw;
+
+ if(page_info_mouse_action(pageinfo_win->pi, mouse_state, x, y, &did_something) == NSERROR_OK)
+ if (did_something == true) {
+ /* Something happened so we need to close ourselves */
+ ami_schedule(0, ami_pageinfo_close_cb, pageinfo_win);
+ }
+
+ return NSERROR_OK;
+}
+
+/**
+ * callback for keypress for pageinfo on core window
+ *
+ * \param ami_cw The Amiga core window structure.
+ * \param nskey The netsurf key code
+ * \return NSERROR_OK on success otherwise apropriate error code
+ */
+static nserror
+ami_pageinfo_key(struct ami_corewindow *ami_cw, uint32_t nskey)
+{
+ struct ami_pageinfo_window *pageinfo_win = (struct ami_pageinfo_window *)ami_cw;
+
+ if (page_info_keypress(pageinfo_win->pi, nskey)) {
+ return NSERROR_OK;
+ }
+ return NSERROR_NOT_IMPLEMENTED;
+}
+
+/**
+ * callback on draw event for pageinfo on core window
+ *
+ * \param ami_cw The Amiga core window structure.
+ * \param x the x coordinate to draw
+ * \param y the y coordinate to draw
+ * \param r The rectangle of the window that needs updating.
+ * \param ctx The drawing context
+ * \return NSERROR_OK on success otherwise apropriate error code
+ */
+static nserror
+ami_pageinfo_draw(struct ami_corewindow *ami_cw, int x, int y, struct rect *r, struct redraw_context *ctx)
+{
+ struct ami_pageinfo_window *pageinfo_win = (struct ami_pageinfo_window *)ami_cw;
+
+ page_info_redraw(pageinfo_win->pi, x, y, r, ctx);
+
+ return NSERROR_OK;
+}
+
+static nserror
+ami_pageinfo_create_window(struct ami_pageinfo_window *pageinfo_win, ULONG left, ULONG top)
+{
+ struct ami_corewindow *ami_cw = (struct ami_corewindow *)&pageinfo_win->core;
+ ULONG refresh_mode = WA_SmartRefresh;
+ struct Screen *scrn = ami_gui_get_screen();
+
+ if(nsoption_bool(window_simple_refresh) == true) {
+ refresh_mode = WA_SimpleRefresh;
+ }
+
+ ami_cw->objects[GID_CW_WIN] = WindowObj,
+ WA_ScreenTitle, ami_gui_get_screen_title(),
+ WA_Activate, TRUE,
+ WA_DepthGadget, FALSE,
+ WA_DragBar, FALSE,
+ WA_CloseGadget, FALSE,
+ WA_SizeGadget, FALSE,
+ WA_Borderless, TRUE,
+ WA_Left, left,
+ WA_Top, top,
+ WA_PubScreen, scrn,
+ WA_ReportMouse, TRUE,
+ refresh_mode, TRUE,
+ WA_IDCMP, IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_NEWSIZE |
+ IDCMP_RAWKEY | IDCMP_IDCMPUPDATE | IDCMP_INACTIVEWINDOW |
+ IDCMP_EXTENDEDMOUSE | IDCMP_SIZEVERIFY | IDCMP_REFRESHWINDOW,
+ WINDOW_IDCMPHook, &ami_cw->idcmp_hook,
+ WINDOW_IDCMPHookBits, IDCMP_IDCMPUPDATE | IDCMP_EXTENDEDMOUSE |
+ IDCMP_SIZEVERIFY | IDCMP_REFRESHWINDOW,
+ WINDOW_SharedPort, ami_gui_get_shared_msgport(),
+ WINDOW_UserData, pageinfo_win,
+ WINDOW_IconifyGadget, FALSE,
+ WINDOW_ParentGroup, ami_cw->objects[GID_CW_MAIN] = LayoutVObj,
+ LAYOUT_AddChild, ami_cw->objects[GID_CW_DRAW] = SpaceObj,
+ GA_ID, GID_CW_DRAW,
+ SPACE_Transparent, TRUE,
+ SPACE_BevelStyle, BVS_BOX,
+ GA_RelVerify, TRUE,
+ SpaceEnd,
+ EndGroup,
+ EndWindow;
+
+ if(ami_cw->objects[GID_CW_WIN] == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in amiga/pageinfo.h */
+nserror ami_pageinfo_open(struct browser_window *bw, ULONG left, ULONG top)
+{
+ struct ami_pageinfo_window *ncwin;
+ nserror res;
+ int width, height;
+
+ ncwin = calloc(1, sizeof(struct ami_pageinfo_window));
+ if (ncwin == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ ncwin->core.wintitle = ami_utf8_easy((char *)messages_get("PageInfo"));
+
+ res = ami_pageinfo_create_window(ncwin, left, top);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Page info init failed");
+ ami_utf8_free(ncwin->core.wintitle);
+ free(ncwin);
+ return res;
+ }
+
+ /* initialise Amiga core window */
+ ncwin->core.draw = ami_pageinfo_draw;
+ ncwin->core.key = ami_pageinfo_key;
+ ncwin->core.mouse = ami_pageinfo_mouse;
+ ncwin->core.close = ami_pageinfo_destroy;
+ ncwin->core.event = ami_pageinfo_event;
+
+ res = ami_corewindow_init(&ncwin->core);
+ if (res != NSERROR_OK) {
+ ami_utf8_free(ncwin->core.wintitle);
+ DisposeObject(ncwin->core.objects[GID_CW_WIN]);
+ free(ncwin);
+ return res;
+ }
+
+ res = page_info_create(ncwin->core.cb_table,
+ (struct core_window *)ncwin,
+ bw,
+ &ncwin->pi);
+
+ if (res != NSERROR_OK) {
+ ami_utf8_free(ncwin->core.wintitle);
+ DisposeObject(ncwin->core.objects[GID_CW_WIN]);
+ free(ncwin);
+ return res;
+ }
+
+ if(page_info_get_size(ncwin->pi, &width, &height) == NSERROR_OK) {
+ /* Set window to the correct size.
+ * TODO: this should really set the size of ncwin->core.objects[GID_CW_DRAW]
+ * and let the window adjust, here we've hardcoded to add 6x4px as that's
+ * what window.class does before v45.
+ */
+ SetAttrs(ncwin->core.objects[GID_CW_WIN], WA_InnerWidth, width + 6, WA_InnerHeight, height + 4, TAG_DONE);
+ }
+
+ return NSERROR_OK;
+}
+
diff --git a/frontends/gtk/login.h b/frontends/amiga/pageinfo.h
index 00c29000c..e48925e26 100644
--- a/frontends/gtk/login.h
+++ b/frontends/amiga/pageinfo.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Vincent Sanders <vince@netsurf-browser.org>
+ * Copyright 2020 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,16 +16,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Login interfaces.
- */
-
-#ifndef __NSGTK_LOGIN_H__
-#define __NSGTK_LOGIN_H__
+#ifndef AMIGA_PAGEINFO_H
+#define AMIGA_PAGEINFO_H
/**
- * login window request.
+ * Open the page info window
+ *
+ * \param bw the browser window
+ * \return NSERROR_OK or error code if window creation failed.
*/
-extern void gui_401login_open(struct nsurl *url, const char *realm, nserror (*cb)(bool proceed, void *pw), void *cbpw);
+nserror ami_pageinfo_open(struct browser_window *bw, ULONG left, ULONG top);
#endif
+
diff --git a/frontends/amiga/pkg/SearchEngines b/frontends/amiga/pkg/SearchEngines
index 3f4bdd95b..3095d43cf 100644
--- a/frontends/amiga/pkg/SearchEngines
+++ b/frontends/amiga/pkg/SearchEngines
@@ -1,2 +1,2 @@
-Aminet|www.aminet.net|http://aminet.net/search?query=%s|http://aminet.net/favicon.ico|
+Aminet|www.aminet.net|https://aminet.net/search?query=%s|https://aminet.net/favicon.ico|
OS4Depot|www.os4depot.net|http://www.os4depot.net/index.php?function=search&tool=simple&f_fields=%s|http://www.os4depot.net/favicon.ico|
diff --git a/frontends/amiga/pkg/netsurf.readme b/frontends/amiga/pkg/netsurf.readme
index 817e07435..d2d83ac56 100755
--- a/frontends/amiga/pkg/netsurf.readme
+++ b/frontends/amiga/pkg/netsurf.readme
@@ -2,11 +2,11 @@ Short: Fast CSS capable web browser
Uploader: chris@unsatisfactorysoftware.co.uk (Chris Young)
Author: NetSurf contributors (OS4 port by Chris Young)
Type: comm/www
-Version: 3.8
+Version: 3.11
Requires: dev/misc/guigfxlib.lha
Architecture: ppc-amigaos >= 4.0.0
-This is NetSurf 3.8 for AmigaOS 4 (native frontend).
+This is NetSurf 3.11 for AmigaOS 4 (native frontend).
For the latest version, visit http://www.netsurf-browser.org
*******************************************
diff --git a/frontends/amiga/pkg/netsurf_os3.readme b/frontends/amiga/pkg/netsurf_os3.readme
index 087e586f9..53514f8db 100644
--- a/frontends/amiga/pkg/netsurf_os3.readme
+++ b/frontends/amiga/pkg/netsurf_os3.readme
@@ -2,14 +2,14 @@ Short: Fast CSS capable web browser
Uploader: chris@unsatisfactorysoftware.co.uk (Chris Young)
Author: NetSurf contributors (OS4 port by Chris Young)
Type: comm/www
-Version: 3.8 BETA
-Requires: dev/misc/guigfxlib.lha
-Architecture: m68k-amigaos >= 3.5.0
+Version: 3.11 BETA
+Requires: dev/misc/guigfxlib.lha util/libs/AmiSSL-5.13-OS3.lha
+Architecture: m68k-amigaos >= 3.2.0
-This is NetSurf 3.8 BETA for AmigaOS 3.
+This is NetSurf 3.11 BETA for AmigaOS 3.
It is built off of the OS4 (Reaction) frontend.
-Requirements are AmigaOS 3.5 or 3.9, 32MB RAM.
+Requirements are AmigaOS 3.2, 3.5 or 3.9, 32MB RAM.
THIS IS EARLY BETA QUALITY SOFTWARE FOR TESTING ONLY.
ALL USE IS AT YOUR OWN RISK. IT *WILL* CRASH!
diff --git a/frontends/amiga/plotters.c b/frontends/amiga/plotters.c
index b8485430f..8bc1712dd 100644
--- a/frontends/amiga/plotters.c
+++ b/frontends/amiga/plotters.c
@@ -115,6 +115,7 @@ struct gui_globals *ami_plot_ra_alloc(ULONG width, ULONG height, bool force32bit
/* init shared bitmaps */
int depth = 32;
struct BitMap *friend = NULL;
+ struct Screen *scrn = ami_gui_get_screen();
struct gui_globals *gg = malloc(sizeof(struct gui_globals));
@@ -125,11 +126,34 @@ struct gui_globals *ami_plot_ra_alloc(ULONG width, ULONG height, bool force32bit
if(depth < 16) {
gg->palette_mapped = true;
if(force32bit == false) palette_mapped = true;
+
+ bitmap_set_format(&(bitmap_fmt_t) {
+ .layout = BITMAP_LAYOUT_ARGB8888,
+ .pma = true,
+ });
+
+ NSLOG(netsurf, INFO, "Set bitmap format to 0xAARRGGBB (native endian) (PMA)");
+
} else {
gg->palette_mapped = false;
- if(force32bit == false) palette_mapped = false;
+
+ bitmap_set_format(&(bitmap_fmt_t) {
+ .layout = BITMAP_LAYOUT_ARGB8888,
+ .pma = false,
+ });
+
+ NSLOG(netsurf, INFO, "Set bitmap format to 0xAARRGGBB (native endian)");
+
}
#else
+ bitmap_set_format(&(bitmap_fmt_t) {
+ .layout = BITMAP_LAYOUT_ARGB8888,
+ .pma = true,
+ });
+
+ NSLOG(netsurf, INFO, "Set bitmap format to 0xAARRGGBB (native endian) (PMA)");
+
+
/* Friend BitMaps are weird.
* For OS4, we shouldn't use a friend BitMap here (see below).
* For OS3 AGA, we get no display blitted if we use a friend BitMap,
@@ -143,16 +167,12 @@ struct gui_globals *ami_plot_ra_alloc(ULONG width, ULONG height, bool force32bit
if((depth > 8) && (force32bit == false)) friend = scrn->RastPort.BitMap;
}
- /* OS3 is locked to using palette-mapped display even on RTG.
- * To change this, comment out the below and build with the similar OS4 lines above.
- * Various bits of RTG code are OS4-only and OS3 versions will need to be written,
- * however a brief test reveals a negative performance benefit, so this lock to a
- * palette-mapped display is most likely permanent.
- */
-#warning OS3 locked to palette-mapped modes
- gg->palette_mapped = true;
- palette_mapped = true;
- if(depth > 8) depth = 8;
+ if(depth < 16) {
+ gg->palette_mapped = true;
+ if(force32bit == false) palette_mapped = true;
+ } else {
+ gg->palette_mapped = false;
+ }
#endif
/* Probably need to fix this next line */
@@ -256,11 +276,7 @@ void ami_plot_ra_free(struct gui_globals *gg)
ami_memory_chip_free(gg->tmprasbuf);
free(gg->areabuf);
DisposeLayerInfo(gg->layerinfo);
- if(gg->palette_mapped == false) {
- if(gg->bm) ami_rtg_freebitmap(gg->bm);
- } else {
- if(gg->bm) FreeBitMap(gg->bm);
- }
+ if(gg->bm) ami_rtg_freebitmap(gg->bm);
if(gg->managed_pen_list == true) {
ami_plot_release_pens(gg->shared_pens);
@@ -295,6 +311,7 @@ void ami_plot_ra_set_pen_list(struct gui_globals *gg, struct MinList *pen_list)
void ami_clearclipreg(struct gui_globals *gg)
{
struct Region *reg = NULL;
+ struct Screen *scrn = ami_gui_get_screen();
reg = InstallClipRegion(gg->rp->Layer,NULL);
if(reg) DisposeRegion(reg);
@@ -313,6 +330,8 @@ void ami_clearclipreg(struct gui_globals *gg)
static ULONG ami_plot_obtain_pen(struct MinList *shared_pens, ULONG colr)
{
struct ami_plot_pen *node;
+ struct Screen *scrn = ami_gui_get_screen();
+
LONG pen = ObtainBestPenA(scrn->ViewPort.ColorMap,
(colr & 0x000000ff) << 24,
(colr & 0x0000ff00) << 16,
@@ -336,6 +355,7 @@ static ULONG ami_plot_obtain_pen(struct MinList *shared_pens, ULONG colr)
void ami_plot_release_pens(struct MinList *shared_pens)
{
+ struct Screen *scrn = ami_gui_get_screen();
struct ami_plot_pen *node;
struct ami_plot_pen *nnode;
@@ -400,10 +420,10 @@ void ami_plot_clear_bbox(struct RastPort *rp, struct IBox *bbox)
static void ami_arc_gfxlib(struct RastPort *rp, int x, int y, int radius, int angle1, int angle2)
{
- double angle1_r = (double)(angle1) * (M_PI / 180.0);
- double angle2_r = (double)(angle2) * (M_PI / 180.0);
- double angle, b, c;
- double step = 0.1; //(angle2_r - angle1_r) / ((angle2_r - angle1_r) * (double)radius);
+ float angle1_r = (float)(angle1) * (M_PI / 180.0);
+ float angle2_r = (float)(angle2) * (M_PI / 180.0);
+ float angle, b, c;
+ float step = 0.1; //(angle2_r - angle1_r) / ((angle2_r - angle1_r) * (float)radius);
int x0, y0, x1, y1;
x0 = x;
@@ -412,13 +432,13 @@ static void ami_arc_gfxlib(struct RastPort *rp, int x, int y, int radius, int an
b = angle1_r;
c = angle2_r;
- x1 = (int)(cos(b) * (double)radius);
- y1 = (int)(sin(b) * (double)radius);
+ x1 = (int)(cos(b) * (float)radius);
+ y1 = (int)(sin(b) * (float)radius);
Move(rp, x0 + x1, y0 - y1);
for(angle = (b + step); angle <= c; angle += step) {
- x1 = (int)(cos(angle) * (double)radius);
- y1 = (int)(sin(angle) * (double)radius);
+ x1 = (int)(cos(angle) * (float)radius);
+ y1 = (int)(sin(angle) * (float)radius);
Draw(rp, x0 + x1, y0 - y1);
}
}
@@ -429,7 +449,7 @@ static nserror
ami_bitmap(struct gui_globals *glob, int x, int y, int width, int height, struct bitmap *bitmap)
{
NSLOG(plot, DEEPDEBUG, "[ami_plotter] Entered ami_bitmap()");
-
+ struct Screen *scrn = ami_gui_get_screen();
struct BitMap *tbm;
if (!width || !height) {
@@ -519,6 +539,7 @@ HOOKF(void, ami_bitmap_tile_hook, struct RastPort *, rp, struct BackFillMessage
{
int xf,yf;
struct bfbitmap *bfbm = (struct bfbitmap *)hook->h_Data;
+ struct Screen *scrn = ami_gui_get_screen();
/* tile down and across to extents (msg->Bounds.MinX)*/
for (xf = -bfbm->offsetx; xf < msg->Bounds.MaxX; xf += bfbm->width) {
@@ -580,7 +601,7 @@ HOOKF(void, ami_bitmap_tile_hook, struct RastPort *, rp, struct BackFillMessage
static void ami_bezier(struct bez_point *restrict a, struct bez_point *restrict b,
struct bez_point *restrict c, struct bez_point *restrict d,
- double t, struct bez_point *restrict p) {
+ float t, struct bez_point *restrict p) {
p->x = pow((1 - t), 3) * a->x + 3 * t * pow((1 -t), 2) * b->x + 3 * (1-t) * pow(t, 2)* c->x + pow (t, 3)* d->x;
p->y = pow((1 - t), 3) * a->y + 3 * t * pow((1 -t), 2) * b->y + 3 * (1-t) * pow(t, 2)* c->y + pow (t, 3)* d->y;
}
@@ -722,8 +743,8 @@ ami_line(const struct redraw_context *ctx,
struct gui_globals *glob = (struct gui_globals *)ctx->priv;
- glob->rp->PenWidth = style->stroke_width;
- glob->rp->PenHeight = style->stroke_width;
+ glob->rp->PenWidth = plot_style_fixed_to_int(style->stroke_width);
+ glob->rp->PenHeight = plot_style_fixed_to_int(style->stroke_width);
switch (style->stroke_type) {
case PLOT_OP_TYPE_SOLID: /**< Solid colour */
@@ -780,8 +801,8 @@ ami_rectangle(const struct redraw_context *ctx,
}
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
- glob->rp->PenWidth = style->stroke_width;
- glob->rp->PenHeight = style->stroke_width;
+ glob->rp->PenWidth = plot_style_fixed_to_int(style->stroke_width);
+ glob->rp->PenHeight = plot_style_fixed_to_int(style->stroke_width);
switch (style->stroke_type) {
case PLOT_OP_TYPE_SOLID: /**< Solid colour */
@@ -868,7 +889,6 @@ ami_polygon(const struct redraw_context *ctx,
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
- * \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
@@ -877,7 +897,6 @@ ami_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
- float width,
const float transform[6])
{
unsigned int i;
@@ -955,7 +974,7 @@ ami_path(const struct redraw_context *ctx,
p_c.x = p[i+5];
p_c.y = p[i+6];
- for (double t = 0.0; t <= 1.0; t += 0.1) {
+ for (float t = 0.0; t <= 1.0; t += 0.1) {
ami_bezier(&cur_p, &p_a, &p_b, &p_c, t, &p_r);
if (pstyle->fill_colour != NS_TRANSPARENT) {
if (AreaDraw(glob->rp, p_r.x, p_r.y) == -1) {
diff --git a/frontends/amiga/plugin_hack.c b/frontends/amiga/plugin_hack.c
index 4fd1f03f7..a775936bb 100644
--- a/frontends/amiga/plugin_hack.c
+++ b/frontends/amiga/plugin_hack.c
@@ -35,6 +35,7 @@
#include "amiga/filetype.h"
#include "amiga/plugin_hack.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
#include "content/llcache.h"
@@ -52,9 +53,9 @@ static void amiga_plugin_hack_destroy(struct content *c);
static bool amiga_plugin_hack_redraw(struct content *c,
struct content_redraw_data *data, const struct rect *clip,
const struct redraw_context *ctx);
-static void amiga_plugin_hack_open(struct content *c, struct browser_window *bw,
+static nserror amiga_plugin_hack_open(struct content *c, struct browser_window *bw,
struct content *page, struct object_params *params);
-static void amiga_plugin_hack_close(struct content *c);
+static nserror amiga_plugin_hack_close(struct content *c);
static nserror amiga_plugin_hack_clone(const struct content *old, struct content **newc);
static content_type amiga_plugin_hack_content_type(void);
@@ -151,7 +152,7 @@ bool amiga_plugin_hack_redraw(struct content *c,
.fill_type = PLOT_OP_TYPE_SOLID,
.fill_colour = 0xffffff,
.stroke_colour = 0x000000,
- .stroke_width = 1,
+ .stroke_width = plot_style_int_to_fixed(1),
};
struct rect rect;
nserror res;
@@ -185,7 +186,7 @@ bool amiga_plugin_hack_redraw(struct content *c,
* object within a page
* \param params object parameters, or 0 if not an object
*/
-void amiga_plugin_hack_open(struct content *c, struct browser_window *bw,
+nserror amiga_plugin_hack_open(struct content *c, struct browser_window *bw,
struct content *page, struct object_params *params)
{
NSLOG(netsurf, INFO, "amiga_plugin_hack_open %s",
@@ -198,13 +199,13 @@ void amiga_plugin_hack_open(struct content *c, struct browser_window *bw,
c->height = 0;
}
- return;
+ return NSERROR_OK;
}
-void amiga_plugin_hack_close(struct content *c)
+nserror amiga_plugin_hack_close(struct content *c)
{
NSLOG(netsurf, INFO, "amiga_plugin_hack_close");
- return;
+ return NSERROR_OK;
}
void amiga_plugin_hack_reformat(struct content *c, int width, int height)
diff --git a/frontends/amiga/print.c b/frontends/amiga/print.c
index 8c8565478..97c70b96c 100644
--- a/frontends/amiga/print.c
+++ b/frontends/amiga/print.c
@@ -73,6 +73,20 @@ bool ami_print_dump(void);
void ami_print_progress(void);
void ami_print_close_device(void);
+enum
+{
+ POID_MAIN = 0,
+ POID_LAST,
+ PGID_MAIN,
+ PGID_PRINTER,
+ PGID_SCALE,
+ PGID_COPIES,
+ PGID_PRINT,
+ PGID_CANCEL,
+ PGID_STATUS,
+ PGID_LAST
+};
+
const struct printer amiprinter = {
&amiplot,
ami_print_begin,
@@ -91,30 +105,19 @@ struct ami_printer_info
struct print_settings *ps;
int page;
int pages;
- Object *gadgets[GID_LAST];
- Object *objects[OID_LAST];
+ Object *gadgets[PGID_LAST];
+ Object *objects[POID_LAST];
struct Window *win;
};
struct ami_print_window {
struct ami_generic_window w;
struct Window *win;
- Object *objects[OID_LAST];
- Object *gadgets[GID_LAST];
+ Object *objects[POID_LAST];
+ Object *gadgets[PGID_LAST];
struct hlcache_handle *c;
};
-enum
-{
- PGID_MAIN=0,
- PGID_PRINTER,
- PGID_SCALE,
- PGID_COPIES,
- PGID_PRINT,
- PGID_CANCEL,
- PGID_LAST
-};
-
#define IFFPrefChunkCnt 2
static LONG IFFPrefChunks[] =
{
@@ -265,7 +268,7 @@ void ami_print_ui(struct hlcache_handle *c)
ami_print_ui_setup();
- pw->objects[OID_MAIN] = WindowObj,
+ pw->objects[POID_MAIN] = WindowObj,
WA_ScreenTitle, ami_gui_get_screen_title(),
WA_Title, gadlab[PGID_PRINT],
WA_Activate, TRUE,
@@ -273,8 +276,8 @@ void ami_print_ui(struct hlcache_handle *c)
WA_DragBar, TRUE,
WA_CloseGadget, TRUE,
WA_SizeGadget, FALSE,
- WA_PubScreen, scrn,
- WINDOW_SharedPort, sport,
+ WA_PubScreen, ami_gui_get_screen(),
+ WINDOW_SharedPort, ami_gui_get_shared_msgport(),
WINDOW_UserData, pw,
WINDOW_IconifyGadget, FALSE,
WINDOW_Position, WPOS_CENTERSCREEN,
@@ -328,7 +331,7 @@ void ami_print_ui(struct hlcache_handle *c)
GA_TabCycle,TRUE,
ButtonEnd,
CHILD_WeightedHeight,0,
- LAYOUT_AddChild, pw->gadgets[GID_CANCEL] = ButtonObj,
+ LAYOUT_AddChild, pw->gadgets[PGID_CANCEL] = ButtonObj,
GA_ID, PGID_CANCEL,
GA_RelVerify, TRUE,
GA_Text, gadlab[PGID_CANCEL],
@@ -339,13 +342,13 @@ void ami_print_ui(struct hlcache_handle *c)
EndGroup,
EndWindow;
- pw->win = (struct Window *)RA_OpenWindow(pw->objects[OID_MAIN]);
+ pw->win = (struct Window *)RA_OpenWindow(pw->objects[POID_MAIN]);
ami_gui_win_list_add(pw, AMINS_PRINTWINDOW, &ami_print_table);
}
static void ami_print_close(struct ami_print_window *pw)
{
- DisposeObject(pw->objects[OID_MAIN]);
+ DisposeObject(pw->objects[POID_MAIN]);
ami_gui_win_list_remove(pw);
ami_print_ui_free();
@@ -362,7 +365,7 @@ static BOOL ami_print_event(void *w)
int print_scale;
int printer_unit;
- while((result = RA_HandleInput(pw->objects[OID_MAIN],&code)) != WMHI_LASTMSG)
+ while((result = RA_HandleInput(pw->objects[POID_MAIN],&code)) != WMHI_LASTMSG)
{
switch(result & WMHI_CLASSMASK) // class
{
@@ -509,7 +512,7 @@ bool ami_print_next_page(void)
{
ami_print_info.page++;
- RefreshSetGadgetAttrs((struct Gadget *)ami_print_info.gadgets[GID_STATUS],
+ RefreshSetGadgetAttrs((struct Gadget *)ami_print_info.gadgets[PGID_STATUS],
ami_print_info.win, NULL,
FUELGAUGE_Level, ami_print_info.page,
TAG_DONE);
@@ -519,7 +522,7 @@ bool ami_print_next_page(void)
void ami_print_end(void)
{
ami_plot_ra_free(ami_print_info.gg);
- DisposeObject(ami_print_info.objects[OID_MAIN]);
+ DisposeObject(ami_print_info.objects[POID_MAIN]);
ami_print_close_device();
ami_print_free();
@@ -554,7 +557,7 @@ bool ami_print_dump(void)
void ami_print_progress(void)
{
- ami_print_info.objects[OID_MAIN] = WindowObj,
+ ami_print_info.objects[POID_MAIN] = WindowObj,
WA_ScreenTitle, ami_gui_get_screen_title(),
WA_Title, messages_get("Printing"),
WA_Activate, TRUE,
@@ -562,15 +565,15 @@ void ami_print_progress(void)
WA_DragBar, TRUE,
WA_CloseGadget, FALSE,
WA_SizeGadget, TRUE,
- WA_PubScreen,scrn,
+ WA_PubScreen, ami_gui_get_screen(),
//WINDOW_SharedPort,sport,
WINDOW_UserData, &ami_print_info,
WINDOW_IconifyGadget, FALSE,
WINDOW_LockHeight,TRUE,
WINDOW_Position, WPOS_CENTERSCREEN,
- WINDOW_ParentGroup, ami_print_info.gadgets[GID_MAIN] = LayoutVObj,
- LAYOUT_AddChild, ami_print_info.gadgets[GID_STATUS] = FuelGaugeObj,
- GA_ID,GID_STATUS,
+ WINDOW_ParentGroup, ami_print_info.gadgets[PGID_MAIN] = LayoutVObj,
+ LAYOUT_AddChild, ami_print_info.gadgets[PGID_STATUS] = FuelGaugeObj,
+ GA_ID,PGID_STATUS,
FUELGAUGE_Min,0,
FUELGAUGE_Max,ami_print_info.pages,
FUELGAUGE_Level,0,
@@ -582,8 +585,8 @@ void ami_print_progress(void)
CHILD_NominalSize,TRUE,
CHILD_WeightedHeight,0,
/*
- LAYOUT_AddChild, ami_print_info.gadgets[GID_CANCEL] = ButtonObj,
- GA_ID,GID_CANCEL,
+ LAYOUT_AddChild, ami_print_info.gadgets[PGID_CANCEL] = ButtonObj,
+ GA_ID,PGID_CANCEL,
GA_Disabled,TRUE,
GA_RelVerify,TRUE,
GA_Text,messages_get("Abort"),
@@ -593,6 +596,6 @@ void ami_print_progress(void)
EndGroup,
EndWindow;
- ami_print_info.win = (struct Window *)RA_OpenWindow(ami_print_info.objects[OID_MAIN]);
+ ami_print_info.win = (struct Window *)RA_OpenWindow(ami_print_info.objects[POID_MAIN]);
}
diff --git a/frontends/amiga/resources/Themes/AISS/Theme b/frontends/amiga/resources/Themes/AISS/Theme
index 8c5af103c..f8265bf73 100755
--- a/frontends/amiga/resources/Themes/AISS/Theme
+++ b/frontends/amiga/resources/Themes/AISS/Theme
@@ -31,6 +31,11 @@ theme_tab_loading:*TBImages:list_download
theme_search:*TBImages:list_search
theme_fave:*TBImages:list_favouriteadd
theme_unfave:*TBImages:list_favourite
+theme_pageinfo_insecure:*TBImages:list_warning
+theme_pageinfo_internal:*TBImages:list_info
+theme_pageinfo_local:*TBImages:list_info
+theme_pageinfo_secure:*TBImages:list_securezone
+theme_pageinfo_warning:*TBImages:list_warning
ptr_default:*PROGDIR:Resources/Pointers/Default
ptr_point:*PROGDIR:Resources/Pointers/Point
ptr_caret:*PROGDIR:Resources/Pointers/Caret
diff --git a/frontends/amiga/resources/Themes/Default/Theme b/frontends/amiga/resources/Themes/Default/Theme
index 141e84f54..7e8e9c8d6 100755
--- a/frontends/amiga/resources/Themes/Default/Theme
+++ b/frontends/amiga/resources/Themes/Default/Theme
@@ -44,6 +44,11 @@ theme_tab_loading:
theme_search:search.png
theme_fave:*PROGDIR:Resources/icons/hotlist-add.png
theme_unfave:*PROGDIR:Resources/icons/hotlist-rmv.png
+theme_pageinfo_insecure:*PROGDIR:Resources/icons/16x16/actions/page-info-insecure.png
+theme_pageinfo_internal:*PROGDIR:Resources/icons/16x16/actions/page-info-internal.png
+theme_pageinfo_local:*PROGDIR:Resources/icons/16x16/actions/page-info-local.png
+theme_pageinfo_secure:*PROGDIR:Resources/icons/16x16/actions/page-info-secure.png
+theme_pageinfo_warning:*PROGDIR:Resources/icons/16x16/actions/page-info-warning.png
ptr_default:*PROGDIR:Resources/Pointers/Default
ptr_point:*PROGDIR:Resources/Pointers/Point
ptr_caret:*PROGDIR:Resources/Pointers/Caret
diff --git a/frontends/amiga/rtg.c b/frontends/amiga/rtg.c
index 5e1cac290..8618c0a33 100644
--- a/frontends/amiga/rtg.c
+++ b/frontends/amiga/rtg.c
@@ -26,9 +26,6 @@ struct BitMap *ami_rtg_allocbitmap(ULONG width, ULONG height, ULONG depth,
ULONG flags, struct BitMap *friend, RGBFTYPE format)
{
if(P96Base == NULL) {
-#ifndef __amigaos4__
- if(depth > 8) depth = 8;
-#endif
return AllocBitMap(width, height, depth, flags, friend);
} else {
return p96AllocBitMap(width, height, depth, flags, friend, format);
diff --git a/frontends/amiga/schedule.c b/frontends/amiga/schedule.c
index 043edc7fe..307fff3e9 100644
--- a/frontends/amiga/schedule.c
+++ b/frontends/amiga/schedule.c
@@ -107,7 +107,8 @@ static nserror ami_schedule_add_timer_event(struct nscallback *nscb, int t)
* A scheduled callback matching both callback and p is returned, or NULL if none present.
*/
-static struct nscallback *ami_schedule_locate(void (*callback)(void *p), void *p, bool remove)
+static struct nscallback *
+ami_schedule_locate(void (*callback)(void *p), void *p, bool remove)
{
PblIterator *iterator;
struct nscallback *nscb;
@@ -119,7 +120,7 @@ static struct nscallback *ami_schedule_locate(void (*callback)(void *p), void *p
iterator = pblHeapIterator(schedule_list);
- while ((nscb = pblIteratorNext(iterator)) != -1) {
+ while ((nscb = pblIteratorNext(iterator)) != (void *)-1) {
if ((nscb->callback == callback) && (nscb->p == p)) {
if (remove == true) pblIteratorRemove(iterator);
found_cb = true;
@@ -170,7 +171,11 @@ static nserror schedule_remove(void (*callback)(void *p), void *p, bool abort)
if(nscb != NULL) {
if(abort == true) ami_schedule_remove_timer_event(nscb);
+#ifdef __amigaos4__
FreeSysObject(ASOT_IOREQUEST, nscb);
+#else
+ FreeVec(nscb);
+#endif
pblHeapConstruct(schedule_list);
}
@@ -186,11 +191,14 @@ static void schedule_remove_all(void)
iterator = pblHeapIterator(schedule_list);
- while ((nscb = pblIteratorNext(iterator)) != -1)
- {
+ while ((nscb = pblIteratorNext(iterator)) != (void *)-1) {
ami_schedule_remove_timer_event(nscb);
pblIteratorRemove(iterator);
+#ifdef __amigaos4__
FreeSysObject(ASOT_IOREQUEST, nscb);
+#else
+ FreeVec(nscb);
+#endif
};
pblIteratorFree(iterator);
@@ -218,18 +226,17 @@ static void ami_schedule_dump(void)
GetSysTime(&tv);
Amiga2Date(tv.Seconds, &clockdata);
- NSLOG(netsurf, INFO, "Current time = %d-%d-%d %d:%d:%d.%d",
+ NSLOG(netsurf, INFO, "Current time = %d-%d-%d %d:%d:%d.%lu",
clockdata.mday, clockdata.month, clockdata.year,
clockdata.hour, clockdata.min, clockdata.sec, tv.Microseconds);
NSLOG(netsurf, INFO, "Events remaining in queue:");
iterator = pblHeapIterator(schedule_list);
- while ((nscb = pblIteratorNext(iterator)) != -1)
- {
+ while ((nscb = pblIteratorNext(iterator)) != (void *)-1) {
Amiga2Date(nscb->tv.Seconds, &clockdata);
NSLOG(netsurf, INFO,
- "nscb: %p, at %d-%d-%d %d:%d:%d.%d, callback: %p, %p",
+ "nscb: %p, at %d-%d-%d %d:%d:%d.%lu, callback: %p, %p",
nscb, clockdata.mday, clockdata.month, clockdata.year,
clockdata.hour, clockdata.min, clockdata.sec,
nscb->tv.Microseconds, nscb->callback, nscb->p);
@@ -299,7 +306,10 @@ nserror ami_schedule_create(struct MsgPort *msgport)
schedule_msgport = msgport;
#endif
schedule_list = pblHeapNew();
- if(schedule_list == PBL_ERROR_OUT_OF_MEMORY) return NSERROR_NOMEM;
+
+ if (schedule_list == NULL) {
+ return NSERROR_NOMEM;
+ }
pblHeapSetCompareFunction(schedule_list, ami_schedule_compare);
@@ -335,11 +345,13 @@ nserror ami_schedule(int t, void (*callback)(void *p), void *p)
nscb = AllocSysObjectTags(ASOT_IOREQUEST,
ASOIOR_Duplicate, tioreq,
TAG_DONE);
+ if(nscb == NULL) return NSERROR_NOMEM;
#else
- nscb = (struct nscallback *)CreateIORequest(schedule_msgport, sizeof(struct nscallback));
+ if(schedule_msgport == NULL) return NSERROR_NOMEM;
+ nscb = AllocVec(sizeof(struct nscallback), MEMF_PUBLIC | MEMF_CLEAR);
+ if(nscb == NULL) return NSERROR_NOMEM;
*nscb = *tioreq;
#endif
- if(!nscb) return NSERROR_NOMEM;
if (ami_schedule_add_timer_event(nscb, t) != NSERROR_OK)
return NSERROR_NOMEM;
diff --git a/frontends/amiga/search.c b/frontends/amiga/search.c
index 99ee5b41e..853c06fef 100755
--- a/frontends/amiga/search.c
+++ b/frontends/amiga/search.c
@@ -61,6 +61,7 @@
#include "amiga/search.h"
#include "amiga/object.h"
#include "amiga/theme.h"
+#include "amiga/utf8.h"
#ifndef NOF_ELEMENTS
#define NOF_ELEMENTS(array) (sizeof(array)/sizeof(*(array)))
@@ -68,11 +69,33 @@
static bool search_insert;
+enum
+{
+ OID_S_MAIN = 0,
+ GID_S_MAIN,
+ GID_S_NEXT,
+ GID_S_PREV,
+ GID_S_SEARCHSTRING,
+ GID_S_SHOWALL,
+ GID_S_CASE,
+ GID_S_LAST
+};
+
+enum {
+ SSTR_TITLE = 0,
+ SSTR_CASE,
+ SSTR_SHOWALL,
+ SSTR_PREV,
+ SSTR_NEXT,
+ SSTR_LAST
+};
+
struct find_window {
struct ami_generic_window w;
struct Window *win;
- Object *objects[GID_LAST];
+ Object *objects[GID_S_LAST];
struct gui_window *gwin;
+ char *message[SSTR_LAST];
};
static struct find_window *fwin = NULL;
@@ -120,10 +143,10 @@ void ami_search_open(struct gui_window *gwin)
if(fwin)
{
- browser_window_search_clear(fwin->gwin->bw);
- fwin->gwin->shared->searchwin = NULL;
+ browser_window_search_clear(ami_gui_get_browser_window(fwin->gwin));
+ ami_gui_set_find_window(fwin->gwin, NULL);
fwin->gwin = gwin;
- gwin->shared->searchwin = fwin;
+ ami_gui_set_find_window(fwin->gwin, fwin);
WindowToFront(fwin->win);
ActivateWindow(fwin->win);
return;
@@ -131,77 +154,89 @@ void ami_search_open(struct gui_window *gwin)
fwin = calloc(1, sizeof(struct find_window));
- fwin->objects[OID_MAIN] = WindowObj,
+ /* Get local charset messages. If any of these are NULL it doesn't matter */
+ fwin->message[SSTR_TITLE] = ami_utf8_easy(messages_get("FindTextNS"));
+ fwin->message[SSTR_CASE] = ami_utf8_easy(messages_get("CaseSens"));
+ fwin->message[SSTR_SHOWALL] = ami_utf8_easy(messages_get("ShowAll"));
+ fwin->message[SSTR_PREV] = ami_utf8_easy(messages_get("Prev"));
+ fwin->message[SSTR_NEXT] = ami_utf8_easy(messages_get("Next"));
+
+ fwin->objects[OID_S_MAIN] = WindowObj,
WA_ScreenTitle, ami_gui_get_screen_title(),
- WA_Title,messages_get("FindTextNS"),
+ WA_Title, fwin->message[SSTR_TITLE],
WA_Activate, TRUE,
WA_DepthGadget, TRUE,
WA_DragBar, TRUE,
WA_CloseGadget, TRUE,
WA_SizeGadget, TRUE,
- WA_PubScreen,scrn,
- WINDOW_SharedPort,sport,
- WINDOW_UserData,fwin,
+ WA_PubScreen, ami_gui_get_screen(),
+ WINDOW_SharedPort, ami_gui_get_shared_msgport(),
+ WINDOW_UserData, fwin,
WINDOW_IconifyGadget, FALSE,
- WINDOW_LockHeight,TRUE,
+ WINDOW_LockHeight, TRUE,
WINDOW_Position, WPOS_CENTERSCREEN,
- WINDOW_ParentGroup, fwin->objects[GID_MAIN] = LayoutVObj,
- LAYOUT_AddChild, fwin->objects[GID_SEARCHSTRING] = StringObj,
- GA_ID,GID_SEARCHSTRING,
- GA_TabCycle,TRUE,
- GA_RelVerify,TRUE,
+ WINDOW_ParentGroup, fwin->objects[GID_S_MAIN] = LayoutVObj,
+ LAYOUT_AddChild, fwin->objects[GID_S_SEARCHSTRING] = StringObj,
+ GA_ID, GID_S_SEARCHSTRING,
+ GA_TabCycle, TRUE,
+ GA_RelVerify, TRUE,
StringEnd,
- CHILD_WeightedHeight,0,
- LAYOUT_AddChild, fwin->objects[GID_CASE] = CheckBoxObj,
- GA_ID,GID_CASE,
- GA_Text,messages_get("CaseSens"),
- GA_Selected,FALSE,
- GA_TabCycle,TRUE,
- GA_RelVerify,TRUE,
+ CHILD_WeightedHeight, 0,
+ LAYOUT_AddChild, fwin->objects[GID_S_CASE] = CheckBoxObj,
+ GA_ID, GID_S_CASE,
+ GA_Text, fwin->message[SSTR_CASE],
+ GA_Selected, FALSE,
+ GA_TabCycle, TRUE,
+ GA_RelVerify, TRUE,
CheckBoxEnd,
- LAYOUT_AddChild, fwin->objects[GID_SHOWALL] = CheckBoxObj,
- GA_ID,GID_SHOWALL,
- GA_Text,messages_get("ShowAll"),
- GA_Selected,FALSE,
- GA_TabCycle,TRUE,
- GA_RelVerify,TRUE,
+ LAYOUT_AddChild, fwin->objects[GID_S_SHOWALL] = CheckBoxObj,
+ GA_ID,GID_S_SHOWALL,
+ GA_Text, fwin->message[SSTR_SHOWALL],
+ GA_Selected, FALSE,
+ GA_TabCycle, TRUE,
+ GA_RelVerify, TRUE,
CheckBoxEnd,
-
LAYOUT_AddChild, LayoutHObj,
- LAYOUT_AddChild, fwin->objects[GID_PREV] = ButtonObj,
- GA_ID,GID_PREV,
- GA_RelVerify,TRUE,
- GA_Text,messages_get("Prev"),
- GA_TabCycle,TRUE,
- GA_Disabled,TRUE,
+ LAYOUT_AddChild, fwin->objects[GID_S_PREV] = ButtonObj,
+ GA_ID, GID_S_PREV,
+ GA_RelVerify, TRUE,
+ GA_Text, fwin->message[SSTR_PREV],
+ GA_TabCycle, TRUE,
+ GA_Disabled, TRUE,
ButtonEnd,
- CHILD_WeightedHeight,0,
- LAYOUT_AddChild, fwin->objects[GID_NEXT] = ButtonObj,
- GA_ID,GID_NEXT,
- GA_RelVerify,TRUE,
- GA_Text,messages_get("Next"),
- GA_TabCycle,TRUE,
- GA_Disabled,TRUE,
+ CHILD_WeightedHeight, 0,
+ LAYOUT_AddChild, fwin->objects[GID_S_NEXT] = ButtonObj,
+ GA_ID, GID_S_NEXT,
+ GA_RelVerify, TRUE,
+ GA_Text, fwin->message[SSTR_NEXT],
+ GA_TabCycle, TRUE,
+ GA_Disabled, TRUE,
ButtonEnd,
LayoutEnd,
CHILD_WeightedHeight,0,
EndGroup,
EndWindow;
- fwin->win = (struct Window *)RA_OpenWindow(fwin->objects[OID_MAIN]);
+ fwin->win = (struct Window *)RA_OpenWindow(fwin->objects[OID_S_MAIN]);
fwin->gwin = gwin;
ami_gui_win_list_add(fwin, AMINS_FINDWINDOW, &ami_search_table);
- gwin->shared->searchwin = fwin;
+ ami_gui_set_find_window(fwin->gwin, fwin);
- ActivateLayoutGadget((struct Gadget *)fwin->objects[GID_MAIN], fwin->win,
- NULL, (ULONG)fwin->objects[GID_SEARCHSTRING]);
+ ActivateLayoutGadget((struct Gadget *)fwin->objects[GID_S_MAIN], fwin->win,
+ NULL, (ULONG)fwin->objects[GID_S_SEARCHSTRING]);
}
void ami_search_close(void)
{
- browser_window_search_clear(fwin->gwin->bw);
- fwin->gwin->shared->searchwin = NULL;
- DisposeObject(fwin->objects[OID_MAIN]);
+ browser_window_search_clear(ami_gui_get_browser_window(fwin->gwin));
+ ami_gui_set_find_window(fwin->gwin, NULL);
+ DisposeObject(fwin->objects[OID_S_MAIN]);
+
+ /* Free local charset version of messages */
+ for(int i = 0; i < SSTR_LAST; i++) {
+ ami_utf8_free(fwin->message[i]);
+ }
+
ami_gui_win_list_remove(fwin);
fwin = NULL;
}
@@ -213,48 +248,48 @@ static BOOL ami_search_event(void *w)
uint16 code;
search_flags_t flags;
- while((result = RA_HandleInput(fwin->objects[OID_MAIN],&code)) != WMHI_LASTMSG)
+ while((result = RA_HandleInput(fwin->objects[OID_S_MAIN],&code)) != WMHI_LASTMSG)
{
switch(result & WMHI_CLASSMASK) // class
{
case WMHI_GADGETUP:
switch(result & WMHI_GADGETMASK)
{
- case GID_SEARCHSTRING:
- browser_window_search_clear(fwin->gwin->bw);
+ case GID_S_SEARCHSTRING:
+ browser_window_search_clear(ami_gui_get_browser_window(fwin->gwin));
- RefreshSetGadgetAttrs((struct Gadget *)fwin->objects[GID_PREV],
+ RefreshSetGadgetAttrs((struct Gadget *)fwin->objects[GID_S_PREV],
fwin->win, NULL,
GA_Disabled, FALSE,
TAG_DONE);
- RefreshSetGadgetAttrs((struct Gadget *)fwin->objects[GID_NEXT],
+ RefreshSetGadgetAttrs((struct Gadget *)fwin->objects[GID_S_NEXT],
fwin->win, NULL,
GA_Disabled, FALSE,
TAG_DONE);
/* fall through */
- case GID_NEXT:
+ case GID_S_NEXT:
search_insert = true;
flags = SEARCH_FLAG_FORWARDS |
ami_search_flags();
browser_window_search(
- fwin->gwin->bw,
+ ami_gui_get_browser_window(fwin->gwin),
NULL,
flags, ami_search_string());
- ActivateWindow(fwin->gwin->shared->win);
+ ActivateWindow(ami_gui_get_window(fwin->gwin));
break;
- case GID_PREV:
+ case GID_S_PREV:
search_insert = true;
flags = ~SEARCH_FLAG_FORWARDS &
ami_search_flags();
browser_window_search(
- fwin->gwin->bw,
+ ami_gui_get_browser_window(fwin->gwin),
NULL,
flags, ami_search_string());
- ActivateWindow(fwin->gwin->shared->win);
+ ActivateWindow(ami_gui_get_window(fwin->gwin));
break;
}
break;
@@ -299,7 +334,7 @@ void ami_search_set_hourglass(bool active, void *p)
char *ami_search_string(void)
{
char *text;
- GetAttr(STRINGA_TextVal,fwin->objects[GID_SEARCHSTRING],(ULONG *)&text);
+ GetAttr(STRINGA_TextVal,fwin->objects[GID_S_SEARCHSTRING],(ULONG *)&text);
return text;
}
@@ -325,7 +360,7 @@ void ami_search_add_recent(const char *string, void *p)
void ami_search_set_forward_state(bool active, void *p)
{
- RefreshSetGadgetAttrs((struct Gadget *)fwin->objects[GID_NEXT],
+ RefreshSetGadgetAttrs((struct Gadget *)fwin->objects[GID_S_NEXT],
fwin->win, NULL,
GA_Disabled, active ? FALSE : TRUE, TAG_DONE);
@@ -339,7 +374,7 @@ void ami_search_set_forward_state(bool active, void *p)
void ami_search_set_back_state(bool active, void *p)
{
- RefreshSetGadgetAttrs((struct Gadget *)fwin->objects[GID_PREV],
+ RefreshSetGadgetAttrs((struct Gadget *)fwin->objects[GID_S_PREV],
fwin->win, NULL,
GA_Disabled, active ? FALSE : TRUE, TAG_DONE);
}
@@ -352,8 +387,8 @@ search_flags_t ami_search_flags(void)
{
ULONG case_sensitive, showall;
search_flags_t flags;
- GetAttr(GA_Selected,fwin->objects[GID_CASE],(ULONG *)&case_sensitive);
- GetAttr(GA_Selected,fwin->objects[GID_SHOWALL],(ULONG *)&showall);
+ GetAttr(GA_Selected,fwin->objects[GID_S_CASE],(ULONG *)&case_sensitive);
+ GetAttr(GA_Selected,fwin->objects[GID_S_SHOWALL],(ULONG *)&showall);
flags = 0 | (case_sensitive ? SEARCH_FLAG_CASE_SENSITIVE : 0) |
(showall ? SEARCH_FLAG_SHOWALL : 0);
return flags;
diff --git a/frontends/amiga/search.h b/frontends/amiga/search.h
index f30352cd5..1815ef954 100755
--- a/frontends/amiga/search.h
+++ b/frontends/amiga/search.h
@@ -22,7 +22,7 @@
struct gui_search_table;
struct gui_window;
-struct gui_search_table *amiga_search_table;
+extern struct gui_search_table *amiga_search_table;
/**
* Change the displayed search status.
diff --git a/frontends/amiga/selectmenu.c b/frontends/amiga/selectmenu.c
index 8a8614136..873871d3d 100644
--- a/frontends/amiga/selectmenu.c
+++ b/frontends/amiga/selectmenu.c
@@ -71,10 +71,10 @@ BOOL ami_selectmenu_is_safe(void)
HOOKF(uint32, ami_popup_hook, Object *, item, APTR)
{
uint32 itemid = 0;
- struct gui_window *gwin = hook->h_Data;
+ struct form_control *control = hook->h_Data;
if(GetAttr(PMIA_ID, item, &itemid)) {
- form_select_process_selection(gwin->shared->control, itemid);
+ form_select_process_selection(control, itemid);
}
return itemid;
@@ -109,9 +109,7 @@ void gui_create_form_select_menu(struct gui_window *g,
selectmenuhook.h_Entry = ami_popup_hook;
selectmenuhook.h_SubEntry = NULL;
- selectmenuhook.h_Data = g;
-
- g->shared->control = control;
+ selectmenuhook.h_Data = control;
selectmenuobj = PMMENU(form_control_get_name(control)),
PMA_MenuHandler, &selectmenuhook, End;
@@ -166,9 +164,9 @@ void gui_create_form_select_menu(struct gui_window *g,
~0);
}
- ami_set_pointer(g->shared, GUI_POINTER_DEFAULT, false); // Clear the menu-style pointer
+ ami_set_pointer(ami_gui_get_gui_window_2(g), GUI_POINTER_DEFAULT, false); // Clear the menu-style pointer
- IDoMethod(selectmenuobj, PM_OPEN, g->shared->win);
+ IDoMethod(selectmenuobj, PM_OPEN, ami_gui_get_window(g));
/* PM_OPEN is blocking, so dispose menu immediately... */
if(selectmenuobj) DisposeObject(selectmenuobj);
diff --git a/frontends/amiga/sslcert.c b/frontends/amiga/sslcert.c
deleted file mode 100644
index 136b918fc..000000000
--- a/frontends/amiga/sslcert.c
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * Copyright 2017 Chris Young <chris@unsatisfactorysoftware.co.uk>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- * Implementation of Amiga certificate viewing using core windows.
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-
-#include <proto/intuition.h>
-
-#include <classes/window.h>
-#include <gadgets/button.h>
-#include <gadgets/layout.h>
-#include <gadgets/scroller.h>
-#include <gadgets/space.h>
-#include <images/label.h>
-
-#include <intuition/icclass.h>
-#include <reaction/reaction_macros.h>
-
-#include "utils/log.h"
-#include "netsurf/keypress.h"
-#include "netsurf/plotters.h"
-#include "desktop/sslcert_viewer.h"
-#include "utils/messages.h"
-#include "utils/nsoption.h"
-
-#include "amiga/corewindow.h"
-#include "amiga/libs.h"
-#include "amiga/sslcert.h"
-#include "amiga/utf8.h"
-
-
-/**
- * Amiga certificate viewing window context
- */
-enum {
- GID_SSLCERT_ACCEPT = GID_CW_LAST,
- GID_SSLCERT_REJECT,
- GID_SSLCERT_LAST
-};
-
-#define GID_SSLCERT_SIZE GID_SSLCERT_LAST - GID_CW_LAST
-
-struct ami_crtvrfy_window {
- /** Amiga core window context */
- struct ami_corewindow core;
-
- /** Amiga GUI stuff */
- Object *sslcert_objects[GID_SSLCERT_LAST]; // technically wasting a few bytes here
-
- char *sslerr;
- char *sslaccept;
- char *sslreject;
-
- /** SSL certificate viewer context data */
- struct sslcert_session_data *ssl_data;
-};
-
-/**
- * destroy a previously created certificate view
- */
-static nserror
-ami_crtvrfy_destroy(struct ami_crtvrfy_window *crtvrfy_win)
-{
- nserror res;
-
- res = sslcert_viewer_fini(crtvrfy_win->ssl_data);
- if (res == NSERROR_OK) {
- ami_utf8_free(crtvrfy_win->sslerr);
- ami_utf8_free(crtvrfy_win->sslaccept);
- ami_utf8_free(crtvrfy_win->sslreject);
- res = ami_corewindow_fini(&crtvrfy_win->core); /* closes the window for us */
- }
- return res;
-}
-
-static void
-ami_crtvrfy_accept(struct ami_corewindow *ami_cw)
-{
- struct ami_crtvrfy_window *crtvrfy_win;
- /* technically degenerate container of */
- crtvrfy_win = (struct ami_crtvrfy_window *)ami_cw;
-
- sslcert_viewer_accept(crtvrfy_win->ssl_data);
-
- ami_crtvrfy_destroy(crtvrfy_win);
-}
-
-static void
-ami_crtvrfy_reject(struct ami_corewindow *ami_cw)
-{
- struct ami_crtvrfy_window *crtvrfy_win;
- /* technically degenerate container of */
- crtvrfy_win = (struct ami_crtvrfy_window *)ami_cw;
-
- sslcert_viewer_reject(crtvrfy_win->ssl_data);
-
- ami_crtvrfy_destroy(crtvrfy_win);
-}
-
-/**
- * callback for unknown events on Amiga core window
- * eg. buttons in the ssl cert window
- * (result & WMHI_CLASSMASK) gives the class of event (eg. WMHI_GADGETUP)
- * (result & WMHI_GADGETMASK) gives the gadget ID (eg. GID_SSLCERT_ACCEPT)
- *
- * \param ami_cw The Amiga core window structure.
- * \param result event as returned by RA_HandleInput()
- * \return TRUE if window closed during event processing
- */
-static BOOL
-ami_crtvrfy_event(struct ami_corewindow *ami_cw, ULONG result)
-{
- if((result & WMHI_CLASSMASK) == WMHI_GADGETUP) {
- switch(result & WMHI_GADGETMASK) {
- case GID_SSLCERT_ACCEPT:
- ami_crtvrfy_accept(ami_cw);
- return TRUE;
- break;
-
- case GID_SSLCERT_REJECT:
- ami_crtvrfy_reject(ami_cw);
- return TRUE;
- break;
- }
- }
- return FALSE;
-}
-
-/**
- * callback for mouse action for certificate verify on core window
- *
- * \param ami_cw The Amiga core window structure.
- * \param mouse_state netsurf mouse state on event
- * \param x location of event
- * \param y location of event
- * \return NSERROR_OK on success otherwise apropriate error code
- */
-static nserror
-ami_crtvrfy_mouse(struct ami_corewindow *ami_cw,
- browser_mouse_state mouse_state,
- int x, int y)
-{
- struct ami_crtvrfy_window *crtvrfy_win;
- /* technically degenerate container of */
- crtvrfy_win = (struct ami_crtvrfy_window *)ami_cw;
-
- sslcert_viewer_mouse_action(crtvrfy_win->ssl_data, mouse_state, x, y);
-
- return NSERROR_OK;
-}
-
-/**
- * callback for keypress for certificate verify on core window
- *
- * \param ami_cw The Amiga core window structure.
- * \param nskey The netsurf key code
- * \return NSERROR_OK on success otherwise apropriate error code
- */
-static nserror
-ami_crtvrfy_key(struct ami_corewindow *ami_cw, uint32_t nskey)
-{
- struct ami_crtvrfy_window *crtvrfy_win;
-
- /* technically degenerate container of */
- crtvrfy_win = (struct ami_crtvrfy_window *)ami_cw;
-
- if (sslcert_viewer_keypress(crtvrfy_win->ssl_data, nskey)) {
- return NSERROR_OK;
- }
- return NSERROR_NOT_IMPLEMENTED;
-}
-
-/**
- * callback on draw event for certificate verify on core window
- *
- * \param ami_cw The Amiga core window structure.
- * \param x the x coordinate to draw
- * \param y the y coordinate to draw
- * \param r The rectangle of the window that needs updating.
- * \param ctx The drawing context
- * \return NSERROR_OK on success otherwise apropriate error code
- */
-static nserror
-ami_crtvrfy_draw(struct ami_corewindow *ami_cw, int x, int y, struct rect *r, struct redraw_context *ctx)
-{
- struct ami_crtvrfy_window *crtvrfy_win;
-
- /* technically degenerate container of */
- crtvrfy_win = (struct ami_crtvrfy_window *)ami_cw;
-
- sslcert_viewer_redraw(crtvrfy_win->ssl_data, x, y, r, ctx);
-
- return NSERROR_OK;
-}
-
-static nserror
-ami_crtvrfy_create_window(struct ami_crtvrfy_window *crtvrfy_win)
-{
- struct ami_corewindow *ami_cw = (struct ami_corewindow *)&crtvrfy_win->core;
- ULONG refresh_mode = WA_SmartRefresh;
-
- if(nsoption_bool(window_simple_refresh) == true) {
- refresh_mode = WA_SimpleRefresh;
- }
-
- ami_cw->objects[GID_CW_WIN] = WindowObj,
- WA_ScreenTitle, ami_gui_get_screen_title(),
- WA_Title, ami_cw->wintitle,
- WA_Activate, TRUE,
- WA_DepthGadget, TRUE,
- WA_DragBar, TRUE,
- WA_CloseGadget, FALSE,
- WA_SizeGadget, TRUE,
- WA_SizeBBottom, TRUE,
- WA_Height, scrn->Height / 2,
- WA_PubScreen, scrn,
- WA_ReportMouse, TRUE,
- refresh_mode, TRUE,
- WA_IDCMP, IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_NEWSIZE |
- IDCMP_RAWKEY | IDCMP_GADGETUP | IDCMP_IDCMPUPDATE |
- IDCMP_EXTENDEDMOUSE | IDCMP_SIZEVERIFY | IDCMP_REFRESHWINDOW,
- WINDOW_IDCMPHook, &ami_cw->idcmp_hook,
- WINDOW_IDCMPHookBits, IDCMP_IDCMPUPDATE | IDCMP_EXTENDEDMOUSE |
- IDCMP_SIZEVERIFY | IDCMP_REFRESHWINDOW,
- WINDOW_SharedPort, sport,
- WINDOW_UserData, crtvrfy_win,
- /* WINDOW_NewMenu, twin->menu, -> No menu for SSL Cert */
- WINDOW_IconifyGadget, FALSE,
- WINDOW_Position, WPOS_CENTERSCREEN,
- WINDOW_ParentGroup, ami_cw->objects[GID_CW_MAIN] = LayoutVObj,
- LAYOUT_AddImage, LabelObj,
- LABEL_Text, crtvrfy_win->sslerr,
- LabelEnd,
- LAYOUT_AddChild, ami_cw->objects[GID_CW_HSCROLLLAYOUT] = LayoutVObj,
- LAYOUT_AddChild, ami_cw->objects[GID_CW_VSCROLLLAYOUT] = LayoutHObj,
- LAYOUT_AddChild, ami_cw->objects[GID_CW_DRAW] = SpaceObj,
- GA_ID, GID_CW_DRAW,
- SPACE_Transparent, TRUE,
- SPACE_BevelStyle, BVS_DISPLAY,
- GA_RelVerify, TRUE,
- SpaceEnd,
- LAYOUT_AddChild, ami_cw->objects[GID_CW_VSCROLL] = ScrollerObj,
- GA_ID, GID_CW_VSCROLL,
- GA_RelVerify, TRUE,
- ICA_TARGET, ICTARGET_IDCMP,
- ScrollerEnd,
- LayoutEnd,
- LAYOUT_AddChild, ami_cw->objects[GID_CW_HSCROLL] = ScrollerObj,
- GA_ID, GID_CW_HSCROLL,
- GA_RelVerify, TRUE,
- ICA_TARGET, ICTARGET_IDCMP,
- SCROLLER_Orientation, SORIENT_HORIZ,
- ScrollerEnd,
- LayoutEnd,
- LAYOUT_AddChild, LayoutHObj,
- LAYOUT_AddChild, crtvrfy_win->sslcert_objects[GID_SSLCERT_ACCEPT] = ButtonObj,
- GA_ID, GID_SSLCERT_ACCEPT,
- GA_Text, crtvrfy_win->sslaccept,
- GA_RelVerify, TRUE,
- ButtonEnd,
- LAYOUT_AddChild, crtvrfy_win->sslcert_objects[GID_SSLCERT_REJECT] = ButtonObj,
- GA_ID, GID_SSLCERT_REJECT,
- GA_Text, crtvrfy_win->sslreject,
- GA_RelVerify, TRUE,
- ButtonEnd,
- EndGroup,
- CHILD_WeightedHeight, 0,
- EndGroup,
- EndWindow;
-
- if(ami_cw->objects[GID_CW_WIN] == NULL) {
- return NSERROR_NOMEM;
- }
-
- return NSERROR_OK;
-}
-
-/* exported interface documented in amiga/ssl_cert.h */
-nserror ami_cert_verify(struct nsurl *url,
- const struct ssl_cert_info *certs,
- unsigned long num,
- nserror (*cb)(bool proceed, void *pw),
- void *cbpw)
-{
- struct ami_crtvrfy_window *ncwin;
- nserror res;
-
- ncwin = calloc(1, sizeof(struct ami_crtvrfy_window));
- if (ncwin == NULL) {
- return NSERROR_NOMEM;
- }
-
- ncwin->core.wintitle = ami_utf8_easy((char *)messages_get("SSLCerts"));
- ncwin->sslerr = ami_utf8_easy((char *)messages_get("SSLError"));
- ncwin->sslaccept = ami_utf8_easy((char *)messages_get("SSL_Certificate_Accept"));
- ncwin->sslreject = ami_utf8_easy((char *)messages_get("SSL_Certificate_Reject"));
-
- res = ami_crtvrfy_create_window(ncwin);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "SSL UI builder init failed");
- ami_utf8_free(ncwin->core.wintitle);
- ami_utf8_free(ncwin->sslerr);
- ami_utf8_free(ncwin->sslaccept);
- ami_utf8_free(ncwin->sslreject);
- free(ncwin);
- return res;
- }
-
- /* initialise Amiga core window */
- ncwin->core.draw = ami_crtvrfy_draw;
- ncwin->core.key = ami_crtvrfy_key;
- ncwin->core.mouse = ami_crtvrfy_mouse;
- ncwin->core.close = ami_crtvrfy_reject;
- ncwin->core.event = ami_crtvrfy_event;
-
- res = ami_corewindow_init(&ncwin->core);
- if (res != NSERROR_OK) {
- ami_utf8_free(ncwin->core.wintitle);
- ami_utf8_free(ncwin->sslerr);
- ami_utf8_free(ncwin->sslaccept);
- ami_utf8_free(ncwin->sslreject);
- DisposeObject(ncwin->core.objects[GID_CW_WIN]);
- free(ncwin);
- return res;
- }
-
- /* initialise certificate viewing interface */
- res = sslcert_viewer_create_session_data(num, url, cb, cbpw, certs,
- &ncwin->ssl_data);
- if (res != NSERROR_OK) {
- ami_utf8_free(ncwin->core.wintitle);
- ami_utf8_free(ncwin->sslerr);
- ami_utf8_free(ncwin->sslaccept);
- ami_utf8_free(ncwin->sslreject);
- DisposeObject(ncwin->core.objects[GID_CW_WIN]);
- free(ncwin);
- return res;
- }
-
- res = sslcert_viewer_init(ncwin->core.cb_table,
- (struct core_window *)ncwin,
- ncwin->ssl_data);
- if (res != NSERROR_OK) {
- ami_utf8_free(ncwin->core.wintitle);
- ami_utf8_free(ncwin->sslerr);
- ami_utf8_free(ncwin->sslaccept);
- ami_utf8_free(ncwin->sslreject);
- DisposeObject(ncwin->core.objects[GID_CW_WIN]);
- free(ncwin);
- return res;
- }
-
- return NSERROR_OK;
-}
-
diff --git a/frontends/amiga/stringview/stringview.c b/frontends/amiga/stringview/stringview.c
index 245782b43..60c694a3c 100755
--- a/frontends/amiga/stringview/stringview.c
+++ b/frontends/amiga/stringview/stringview.c
@@ -161,7 +161,7 @@ static uint32 myStringSearch( Class *cl, Object *obj )
if(searchString)
{
searchString += 3;
- if (bufpos >= searchString - data->SearchBuffer)
+ if (bufpos >= (uint32)(searchString - data->SearchBuffer))
bufpos -= searchString - data->SearchBuffer;
}
else
@@ -848,7 +848,7 @@ Class *MakeStringClass( void )
if ( cl )
{
- cl->cl_Dispatcher.h_Entry = (uint32(*)())myStringClassDispatcher;
+ cl->cl_Dispatcher.h_Entry = (uint32(*)(void))myStringClassDispatcher;
}
URLHistory_Init();
diff --git a/frontends/amiga/stringview/stringview.h b/frontends/amiga/stringview/stringview.h
index 776705f0f..ecb53e802 100755
--- a/frontends/amiga/stringview/stringview.h
+++ b/frontends/amiga/stringview/stringview.h
@@ -41,8 +41,8 @@ struct myStringClassData
Object * WindowObject;
Object * ListviewObject;
struct List ListviewHeader;
- uint32 ListviewCount;
- uint32 ListviewSelected;
+ int32 ListviewCount;
+ int32 ListviewSelected;
struct List * SearchHeader;
STRPTR SearchBuffer;
};
diff --git a/frontends/amiga/theme.c b/frontends/amiga/theme.c
index 63982c879..3e6ed8647 100644
--- a/frontends/amiga/theme.c
+++ b/frontends/amiga/theme.c
@@ -215,20 +215,7 @@ void ami_get_theme_filename(char *filename, const char *themestring, bool protoc
void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape)
{
- ami_set_pointer(g->shared, shape, true);
-}
-
-void ami_set_pointer(struct gui_window_2 *gwin, gui_pointer_shape shape, bool update)
-{
- if(gwin->mouse_pointer == shape) return;
- ami_update_pointer(gwin->win, shape);
- if(update == true) gwin->mouse_pointer = shape;
-}
-
-/* reset the mouse pointer back to what NetSurf last set it as */
-void ami_reset_pointer(struct gui_window_2 *gwin)
-{
- ami_update_pointer(gwin->win, gwin->mouse_pointer);
+ ami_set_pointer(ami_gui_get_gui_window_2(g), shape, true);
}
void ami_update_pointer(struct Window *win, gui_pointer_shape shape)
@@ -429,16 +416,16 @@ void gui_window_start_throbber(struct gui_window *g)
if(nsoption_bool(kiosk_mode)) return;
#ifdef __amigaos4__
- if(g->tab_node && (g->shared->tabs > 1))
+ if(ami_gui_get_tab_node(g) && (ami_gui2_get_tabs(ami_gui_get_gui_window_2(g)) > 1))
{
- SetClickTabNodeAttrs(g->tab_node, TNA_Flagged, TRUE, TAG_DONE);
- RefreshGadgets((APTR)g->shared->objects[GID_TABS],
- g->shared->win, NULL);
+ SetClickTabNodeAttrs(ami_gui_get_tab_node(g), TNA_Flagged, TRUE, TAG_DONE);
+ RefreshGadgets((APTR)ami_gui2_get_object(ami_gui_get_gui_window_2(g), AMI_GAD_TABS),
+ ami_gui_get_window(g), NULL);
}
#endif
- g->throbbing = true;
- if(g->shared->throbber_frame == 0) g->shared->throbber_frame = 1;
+ ami_gui_set_throbbing(g, true);
+ if(ami_gui_get_throbber_frame(g) == 0) ami_gui_set_throbber_frame(g, 1);
ami_throbber_redraw_schedule(throbber_update_interval, g);
}
@@ -450,22 +437,22 @@ void gui_window_stop_throbber(struct gui_window *g)
if(nsoption_bool(kiosk_mode)) return;
#ifdef __amigaos4__
- if(g->tab_node && (g->shared->tabs > 1))
+ if(ami_gui_get_tab_node(g) && (ami_gui2_get_tabs(ami_gui_get_gui_window_2(g)) > 1))
{
- SetClickTabNodeAttrs(g->tab_node, TNA_Flagged, FALSE, TAG_DONE);
- RefreshGadgets((APTR)g->shared->objects[GID_TABS],
- g->shared->win, NULL);
+ SetClickTabNodeAttrs(ami_gui_get_tab_node(g), TNA_Flagged, FALSE, TAG_DONE);
+ RefreshGadgets((APTR)ami_gui2_get_object(ami_gui_get_gui_window_2(g), AMI_GAD_TABS),
+ ami_gui_get_window(g), NULL);
}
#endif
- if(g == g->shared->gw) {
- if(ami_gui_get_space_box(g->shared->objects[GID_THROBBER], &bbox) != NSERROR_OK) {
+ if(IS_CURRENT_GW(ami_gui_get_gui_window_2(g), g)) {
+ if(ami_gui_get_space_box(ami_gui2_get_object(ami_gui_get_gui_window_2(g), AMI_GAD_THROBBER), &bbox) != NSERROR_OK) {
amiga_warn_user("NoMemory", "");
return;
}
if(throbber != NULL) {
- BltBitMapRastPort(throbber, 0, 0, g->shared->win->RPort,
+ BltBitMapRastPort(throbber, 0, 0, ami_gui_get_window(g)->RPort,
bbox->Left, bbox->Top,
ami_theme_throbber_get_width(), ami_theme_throbber_get_height(),
0x0C0);
@@ -473,7 +460,7 @@ void gui_window_stop_throbber(struct gui_window *g)
ami_gui_free_space_box(bbox);
}
- g->throbbing = false;
+ ami_gui_set_throbbing(g, false);
ami_throbber_redraw_schedule(-1, g);
}
@@ -484,17 +471,17 @@ static void ami_throbber_update(void *p)
int frame = 0;
if(!g) return;
- if(!g->shared->objects[GID_THROBBER]) return;
+ if(!ami_gui2_get_object(ami_gui_get_gui_window_2(g), AMI_GAD_THROBBER)) return;
- if(g->throbbing == true) {
- frame = g->shared->throbber_frame;
- g->shared->throbber_frame++;
- if(g->shared->throbber_frame > (throbber_frames-1))
- g->shared->throbber_frame=1;
+ if(ami_gui_get_throbbing(g) == true) {
+ frame = ami_gui_get_throbber_frame(g);
+ ami_gui_set_throbber_frame(g, frame + 1);
+ if(ami_gui_get_throbber_frame(g) > (throbber_frames-1))
+ ami_gui_set_throbber_frame(g, 1);
}
- if(g->shared->gw == g) {
- if(ami_gui_get_space_box(g->shared->objects[GID_THROBBER], &bbox) != NSERROR_OK) {
+ if(IS_CURRENT_GW(ami_gui_get_gui_window_2(g),g)) {
+ if(ami_gui_get_space_box(ami_gui2_get_object(ami_gui_get_gui_window_2(g), AMI_GAD_THROBBER), &bbox) != NSERROR_OK) {
amiga_warn_user("NoMemory", "");
return;
}
@@ -508,14 +495,14 @@ static void ami_throbber_update(void *p)
BLITA_Width, ami_theme_throbber_get_width(),
BLITA_Height, ami_theme_throbber_get_height(),
BLITA_Source, throbber,
- BLITA_Dest, g->shared->win->RPort,
+ BLITA_Dest, ami_gui_get_window(g)->RPort,
BLITA_SrcType, BLITT_BITMAP,
BLITA_DestType, BLITT_RASTPORT,
// BLITA_UseSrcAlpha, TRUE,
TAG_DONE);
#else
BltBitMapRastPort(throbber, ami_theme_throbber_get_width() * frame,
- 0, g->shared->win->RPort,
+ 0, ami_gui_get_window(g)->RPort,
bbox->Left, bbox->Top,
ami_theme_throbber_get_width(), ami_theme_throbber_get_height(),
0xC0);
diff --git a/frontends/amiga/theme.h b/frontends/amiga/theme.h
index 6de7bc150..6ab3c0ea8 100644
--- a/frontends/amiga/theme.h
+++ b/frontends/amiga/theme.h
@@ -40,8 +40,6 @@ void ami_update_throbber(struct gui_window_2 *g,bool redraw);
void ami_init_mouse_pointers(void);
void ami_mouse_pointers_free(void);
-void ami_set_pointer(struct gui_window_2 *gwin, gui_pointer_shape shape, bool update);
-void ami_reset_pointer(struct gui_window_2 *gwin);
/* Use the following ONLY if nothing other than the Intuition window pointer is available,
* and ALWAYS in preference to SetWindowPointer(), as it features more pointers and uses
* the correct ones specified in user preferences. */
diff --git a/frontends/amiga/utf8.c b/frontends/amiga/utf8.c
index 5d05e9535..fabb1e24c 100755
--- a/frontends/amiga/utf8.c
+++ b/frontends/amiga/utf8.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ * Copyright 2008-2021 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -22,6 +22,7 @@
#include <string.h>
#include <sys/types.h>
+#include <proto/codesets.h>
#include <proto/exec.h>
#include <proto/utility.h>
@@ -31,20 +32,73 @@
#include "amiga/utf8.h"
+static nserror ami_utf8_codesets(const char *string, size_t len, char **result, bool to_local)
+{
+ char *out;
+ ULONG utf8_tag = CSA_SourceCodeset, local_tag = CSA_DestCodeset, len_tag = CSA_SourceLen;
+ static struct codeset *utf8_cs = NULL;
+ static struct codeset *local_cs = NULL;
+
+ if(local_cs == NULL) local_cs = CodesetsFind(NULL,
+#ifdef __amigaos4__
+ CSA_MIBenum, nsoption_int(local_codeset),
+#else
+ NULL,
+#endif
+ TAG_DONE);
+
+ if(utf8_cs == NULL) utf8_cs = CodesetsFind(NULL,
+ CSA_MIBenum, CS_MIBENUM_UTF_8,
+ TAG_DONE);
+
+ if(to_local == false) {
+ local_tag = CSA_SourceCodeset;
+ utf8_tag = CSA_DestCodeset;
+ }
+
+ if(len == 0) len_tag = TAG_IGNORE;
+
+ out = CodesetsConvertStr(CSA_Source, string,
+ len_tag, len,
+#ifdef __amigaos4__
+ local_tag, local_cs,
+#endif
+ utf8_tag, utf8_cs,
+ CSA_MapForeignChars, TRUE,
+ TAG_DONE);
+
+ if(out != NULL) {
+ *result = strdup(out);
+ CodesetsFreeA(out, NULL);
+ } else {
+ return NSERROR_BAD_ENCODING;
+ }
+
+ return NSERROR_OK;
+}
+
nserror utf8_from_local_encoding(const char *string, size_t len, char **result)
{
- return utf8_from_enc(string, nsoption_charp(local_charset), len, result, NULL);
+ if(__builtin_expect((CodesetsBase == NULL), 0)) {
+ return utf8_from_enc(string, nsoption_charp(local_charset), len, result, NULL);
+ } else {
+ return ami_utf8_codesets(string, len, result, false);
+ }
}
nserror utf8_to_local_encoding(const char *string, size_t len, char **result)
{
- nserror err = NSERROR_NOMEM;
- char *local_charset = ASPrintf("%s//IGNORE", nsoption_charp(local_charset));
- if(local_charset) {
- err = utf8_to_enc(string, local_charset, len, result);
- FreeVec(local_charset);
+ if(__builtin_expect((CodesetsBase == NULL), 0)) {
+ nserror err = NSERROR_NOMEM;
+ char *local_charset = ASPrintf("%s//IGNORE", nsoption_charp(local_charset));
+ if(local_charset) {
+ err = utf8_to_enc(string, local_charset, len, result);
+ FreeVec(local_charset);
+ }
+ return err;
+ } else {
+ return ami_utf8_codesets(string, len, result, true);
}
- return err;
}
void ami_utf8_free(char *ptr)
diff --git a/frontends/amiga/version.c b/frontends/amiga/version.c
index 61fbd7176..ae898cb83 100644
--- a/frontends/amiga/version.c
+++ b/frontends/amiga/version.c
@@ -25,7 +25,7 @@
* problems created by "0" not being a valid AmigaOS revision number.
*/
#define NETSURF_VERSION_MAJOR "3"
-#define NETSURF_VERSION_MINOR_EXTERNAL "8"
+#define NETSURF_VERSION_MINOR_EXTERNAL "12"
#if defined(CI_BUILD)
#define NETSURF_VERSION_MINOR CI_BUILD
#else
diff --git a/frontends/atari/Makefile b/frontends/atari/Makefile
index 585f0b217..2f6d7118b 100644
--- a/frontends/atari/Makefile
+++ b/frontends/atari/Makefile
@@ -8,7 +8,7 @@
# toolchain is located in /usr/bin and the wildcard matching
# fails then. So this wildcard matches only works for
# the netsurf environment!
-STRIP := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*strip)
+STRIP := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*-strip)
STACK := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*stack)
FT2CF := $(GCCSDK_INSTALL_ENV)/bin/freetype-config
@@ -33,10 +33,31 @@ endif
# non-pkgconfig components
-FREETYPE_FONT_CFLAGS := $(shell $(FT2CF) --cflags) -DWITH_FREETYPE_FONT_DRIVER
SPIDERMONKEY_CFLAGS := -DXP_UNIX -DJS_HAS_FILE_OBJECT=0 -DJSOPTION_JIT=0 -DPOSIX_SOURCE -D_BSD_SOURCE
-$(eval $(call feature_enabled,ATARI_FREETYPE_FONT,$(FREETYPE_FONT_CFLAGS),-lfreetype,(Freetype)))
+# freetype is optional but older versions do not use pkg-config
+ifeq ($(NETSURF_USE_ATARI_FREETYPE_FONT),YES)
+ NETSURF_USE_FREETYPE2 := AUTO
+ NETSURF_FEATURE_FREETYPE2_CFLAGS := -DWITH_FREETYPE_FONT_DRIVER
+
+ $(eval $(call pkg_config_find_and_add_enabled,FREETYPE2,freetype2,freetype2))
+
+ # try and use non pkg-config method
+ ifeq ($(NETSURF_USE_FREETYPE2),NO)
+ FREETYPE_CONFIG_EXISTS := $(shell $(FT2CF) --cflags >/dev/null && echo yes)
+ ifeq ($(FREETYPE_CONFIG_EXISTS),yes)
+ NETSURF_USE_FREETYPE2 := YES
+ CFLAGS += $(shell $(FT2CF) --cflags) $(NETSURF_FEATURE_FREETYPE2_CFLAGS)
+ LDFLAGS += $(shell $(FT2CF) --libs)
+ $(info FT2.CNFG: freetype2 (freetype2) enabled)
+ else
+ $(info FT2.CNFG: freetype2 (freetype2) failed)
+ $(error Unable to find library for: freetype2)
+ endif
+ endif
+endif
+
+
$(eval $(call feature_enabled,ATARI_NETSURF_FONT,-DWITH_INTERNAL_FONT_DRIVER,,(Internal Font)))
$(eval $(call feature_enabled,ATARI_VDI_FONT,-DWITH_VDI_FONT_DRIVER,,(VDI Font)))
$(eval $(call feature_enabled,ATARI_8BPP_SUPPORT,-DWITH_8BPP_SUPPORT,,(Indexed screen format support)))
@@ -64,7 +85,6 @@ S_FRONTEND := \
clipboard.c \
ctxmenu.c \
cookies.c \
- certview.c \
deskmenu.c \
download.c \
encoding.c \
@@ -75,7 +95,6 @@ S_FRONTEND := \
gui.c \
hotlist.c \
history.c \
- login.c \
misc.c \
osspec.c \
redrawslots.c \
@@ -104,8 +123,16 @@ S_FRONTEND := \
# Note this is deliberately *not* expanded here as common and image
# are not yet available
SOURCES = $(S_COMMON) $(S_IMAGE) $(S_BROWSER) $(S_FRONTEND)
+
+# ---------------------------------------------------------------------------
+# Target setup
+# ---------------------------------------------------------------------------
+
EXETARGET := ns$(SUBTARGET)$(PRGSUFFIX)
+# The filter and target for split messages
+MESSAGES_FILTER=atari
+
# ----------------------------------------------------------------------------
# Install target
# ----------------------------------------------------------------------------
@@ -121,10 +148,6 @@ ATARI_FONT_SOURCE_DIR := $(ATARI_FONT_TMP_DIR)$(ATARI_FONT_NAME)/
ATARI_GENERIC_RESOURCES := de en it ja nl
ATARI_RESOURCES := $(addprefix resources/,$(ATARI_GENERIC_RESOURCES))
-# ----------------------------------------------------------------------------
-# Install target
-# ----------------------------------------------------------------------------
-
install-atari:
# ----------------------------------------------------------------------------
@@ -138,7 +161,7 @@ $(ATARI_FONT_TMP_DIR)$(ATARI_FONT_NAME):
package-atari: $(ATARI_FONT_TMP_DIR)$(ATARI_FONT_NAME) $(PKGNAME)
$(VQ)echo Creating $(PKGNAME)
-$(PKGNAME): $(EXETARGET)
+$(PKGNAME): $(EXETARGET) $(POSTEXES)
ifneq ($(strip $(STRIP)),)
$(Q)echo Stripping symbols from $(EXETARGET) with $(STRIP)
$(Q)$(STRIP) $(EXETARGET)
@@ -177,10 +200,8 @@ endif
$(Q)cp resources/internal.css $(ATARI_TARGET_DIR)res/internal.css
$(Q)cp resources/SearchEngines $(ATARI_TARGET_DIR)res/search
$(Q)cp resources/ca-bundle $(ATARI_TARGET_DIR)res/cabundle
- $(Q)$(RM) $(ATARI_TARGET_DIR)res/messages
- $(Q)$(SPLIT_MESSAGES) -l en -p atari -f messages -o $(ATARI_TARGET_DIR)res/messages resources/FatMessages
+ $(Q)$(INSTALL) -m 644 -T $(MESSAGES_TARGET)/en/Messages $(ATARI_TARGET_DIR)res/messages
$(Q)cp resources/en/welcome.html $(ATARI_TARGET_DIR)res/welcome.html
- $(Q)cp resources/en/maps.html $(ATARI_TARGET_DIR)res/maps.html
$(Q)cp resources/en/licence.html $(ATARI_TARGET_DIR)res/licence.html
$(Q)cp resources/en/credits.html $(ATARI_TARGET_DIR)res/credits.html
diff --git a/frontends/atari/Makefile.tools b/frontends/atari/Makefile.tools
new file mode 100644
index 000000000..971ab21be
--- /dev/null
+++ b/frontends/atari/Makefile.tools
@@ -0,0 +1,19 @@
+# -*- mode: makefile-gmake -*-
+##
+## atari target tool setup
+##
+
+ifeq ($(HOST),atari)
+ PKG_CONFIG := pkg-config
+else
+ ifeq ($(HOST),mint)
+ PKG_CONFIG := pkg-config
+ else
+ GCCSDK_INSTALL_ENV ?= /opt/netsurf/m68k-atari-mint/env
+ GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/m68k-atari-mint/cross/bin
+
+ CC := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc)
+
+ PKG_CONFIG := PKG_CONFIG_LIBDIR="$(GCCSDK_INSTALL_ENV)/lib/pkgconfig" pkg-config
+ endif
+endif \ No newline at end of file
diff --git a/frontends/atari/bitmap.c b/frontends/atari/bitmap.c
index ae42da837..9b5a016a5 100644
--- a/frontends/atari/bitmap.c
+++ b/frontends/atari/bitmap.c
@@ -77,36 +77,36 @@ int init_mfdb(int bpp, int w, int h, uint32_t flags, MFDB * out )
* \param pixdata NULL or an memory address to use as the bitmap pixdata
* \return an opaque struct bitmap, or NULL on memory exhaustion
*/
-static void *atari_bitmap_create_ex( int w, int h, short bpp, int rowstride, unsigned int state, void * pixdata )
+static void *atari_bitmap_create_ex( int w, int h, short bpp, int rowstride, enum gui_bitmap_flags flags, void * pixdata )
{
- struct bitmap * bitmap;
+ struct bitmap * bitmap;
- NSLOG(netsurf, INFO,
- "width %d (rowstride: %d, bpp: %d), height %d, state %u", w,
- rowstride, bpp, h, state);
+ NSLOG(netsurf, INFO,
+ "width %d (rowstride: %d, bpp: %d), height %d, flags %u", w,
+ rowstride, bpp, h, (unsigned)flags);
if( rowstride == 0) {
rowstride = bpp * w;
}
assert( rowstride >= (w * bpp) );
- bitmap = calloc(1 , sizeof(struct bitmap) );
- if (bitmap) {
+ bitmap = calloc(1 , sizeof(struct bitmap) );
+ if (bitmap) {
if( pixdata == NULL) {
- bitmap->pixdata = calloc(1, (rowstride * h)+128);
+ bitmap->pixdata = calloc(1, (rowstride * h)+128);
}
else {
bitmap->pixdata = pixdata;
}
- if (bitmap->pixdata != NULL) {
+ if (bitmap->pixdata != NULL) {
bitmap->width = w;
bitmap->height = h;
- bitmap->opaque = (state & BITMAP_OPAQUE) ? true : false;
+ bitmap->opaque = (flags & BITMAP_OPAQUE) ? true : false;
bitmap->bpp = bpp;
bitmap->resized = NULL;
bitmap->rowstride = rowstride;
- } else {
+ } else {
free(bitmap);
bitmap=NULL;
NSLOG(netsurf, INFO, "Out of memory!");
@@ -118,9 +118,9 @@ static void *atari_bitmap_create_ex( int w, int h, short bpp, int rowstride, uns
/* exported interface documented in atari/bitmap.h */
-void *atari_bitmap_create(int w, int h, unsigned int state)
+void *atari_bitmap_create(int w, int h, enum gui_bitmap_flags flags)
{
- return atari_bitmap_create_ex( w, h, NS_BMP_DEFAULT_BPP, w * NS_BMP_DEFAULT_BPP, state, NULL );
+ return atari_bitmap_create_ex( w, h, NS_BMP_DEFAULT_BPP, w * NS_BMP_DEFAULT_BPP, flags, NULL );
}
/**
@@ -249,21 +249,6 @@ void atari_bitmap_destroy(void *bitmap)
/**
- * Save a bitmap in the platform's native format.
- *
- * \param bitmap a bitmap, as returned by bitmap_create()
- * \param path pathname for file
- * \param flags flags controlling how the bitmap is saved.
- * \return true on success, false on error and error reported
- */
-
-static bool bitmap_save(void *bitmap, const char *path, unsigned flags)
-{
- return true;
-}
-
-
-/**
* Sets whether a bitmap should be plotted opaque
*
* \param bitmap a bitmap, as returned by bitmap_create()
@@ -284,40 +269,6 @@ static void bitmap_set_opaque(void *bitmap, bool opaque)
}
-/**
- * Tests whether a bitmap has an opaque alpha channel
- *
- * \param bitmap a bitmap, as returned by bitmap_create()
- * \return whether the bitmap is opaque
- */
-static bool bitmap_test_opaque(void *bitmap)
-{
- int tst;
- struct bitmap *bm = bitmap;
-
- if (bitmap == NULL) {
- NSLOG(netsurf, INFO, "NULL bitmap!");
- return false;
- }
-
- if( nsoption_int(atari_transparency) == 0 ){
- return( true );
- }
-
- tst = bm->width * bm->height;
-
- while (tst-- > 0) {
- if (bm->pixdata[(tst << 2) + 3] != 0xff) {
- NSLOG(netsurf, INFO,
- "bitmap %p has transparency", bm);
- return false;
- }
- }
- NSLOG(netsurf, INFO, "bitmap %p is opaque", bm);
- return true;
-}
-
-
/* exported interface documented in atari/bitmap.h */
bool atari_bitmap_get_opaque(void *bitmap)
{
@@ -358,22 +309,12 @@ int atari_bitmap_get_height(void *bitmap)
return(bm->height);
}
-
-/**
- * Gets the number of BYTES per pixel.
- */
-static size_t bitmap_get_bpp(void *bitmap)
-{
- struct bitmap *bm = bitmap;
- return bm->bpp;
-}
-
/* exported interface documented in atari/bitmap.h */
bool atari_bitmap_resize(struct bitmap *img, HermesHandle hermes_h,
HermesFormat *fmt, int nw, int nh)
{
- unsigned int state = 0;
- short bpp = bitmap_get_bpp( img );
+ enum gui_bitmap_flags flags = 0;
+ short bpp = img->bpp;
int stride = atari_bitmap_get_rowstride( img );
int err;
@@ -389,9 +330,9 @@ bool atari_bitmap_resize(struct bitmap *img, HermesHandle hermes_h,
/* allocate the mem for resized bitmap */
if (img->opaque == true) {
- state |= BITMAP_OPAQUE;
+ flags |= BITMAP_OPAQUE;
}
- img->resized = atari_bitmap_create_ex( nw, nh, bpp, nw*bpp, state, NULL );
+ img->resized = atari_bitmap_create_ex( nw, nh, bpp, nw*bpp, flags, NULL );
if( img->resized == NULL ) {
printf("W: %d, H: %d, bpp: %d\n", nw, nh, bpp);
assert(img->resized);
@@ -439,13 +380,10 @@ static struct gui_bitmap_table bitmap_table = {
.destroy = atari_bitmap_destroy,
.set_opaque = bitmap_set_opaque,
.get_opaque = atari_bitmap_get_opaque,
- .test_opaque = bitmap_test_opaque,
.get_buffer = bitmap_get_buffer,
.get_rowstride = atari_bitmap_get_rowstride,
.get_width = atari_bitmap_get_width,
.get_height = atari_bitmap_get_height,
- .get_bpp = bitmap_get_bpp,
- .save = bitmap_save,
.modified = bitmap_modified,
.render = bitmap_render,
};
diff --git a/frontends/atari/bitmap.h b/frontends/atari/bitmap.h
index b0fa18069..88985ad3c 100644
--- a/frontends/atari/bitmap.h
+++ b/frontends/atari/bitmap.h
@@ -54,7 +54,7 @@
*/
#define MFDB_SIZE( bpp, stride, h ) ( ((stride >> 3) * h) * bpp )
-struct gui_bitmap_table *atari_bitmap_table;
+extern struct gui_bitmap_table *atari_bitmap_table;
struct bitmap {
int width;
@@ -90,7 +90,7 @@ int init_mfdb(int bpp, int w, int h, uint32_t flags, MFDB * out );
* \param state a flag word indicating the initial state
* \return an opaque struct bitmap, or NULL on memory exhaustion
*/
-void *atari_bitmap_create(int w, int h, unsigned int state);
+void *atari_bitmap_create(int w, int h, enum gui_bitmap_flags flags);
/**
* Find the width of a pixel row in bytes.
diff --git a/frontends/atari/certview.c b/frontends/atari/certview.c
deleted file mode 100644
index 80d18a059..000000000
--- a/frontends/atari/certview.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright 2013 Ole Loots <ole@monochrom.net>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <ctype.h>
-#include <string.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-
-#include "utils/nsoption.h"
-#include "utils/log.h"
-#include "utils/messages.h"
-#include "utils/utils.h"
-#include "desktop/sslcert_viewer.h"
-
-#include "atari/gui.h"
-#include "atari/misc.h"
-#include "atari/treeview.h"
-#include "atari/certview.h"
-#include "atari/findfile.h"
-#include "atari/gemtk/gemtk.h"
-#include "atari/res/netsurf.rsh"
-
-extern GRECT desk_area;
-
-
-/* Setup Atari Treeview Callbacks: */
-static nserror atari_sslcert_viewer_init_phase2(struct core_window *cw,
- struct core_window_callback_table * default_callbacks);
-static void atari_sslcert_viewer_finish(struct core_window *cw);
-static void atari_sslcert_viewer_keypress(struct core_window *cw,
- uint32_t ucs4);
-static void atari_sslcert_viewer_mouse_action(struct core_window *cw,
- browser_mouse_state mouse,
- int x, int y);
-static void atari_sslcert_viewer_draw(struct core_window *cw, int x,
- int y, struct rect *clip,
- const struct redraw_context *ctx);
-static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8]);
-
-static struct atari_treeview_callbacks atari_sslcert_viewer_treeview_callbacks = {
- .init_phase2 = atari_sslcert_viewer_init_phase2,
- .finish = atari_sslcert_viewer_finish,
- .draw = atari_sslcert_viewer_draw,
- .keypress = atari_sslcert_viewer_keypress,
- .mouse_action = atari_sslcert_viewer_mouse_action,
- .gemtk_user_func = handle_event
-};
-
-/* static functions */
-static void atari_sslcert_viewer_destroy(struct atari_sslcert_viewer_s * cvwin);
-
-
-static nserror atari_sslcert_viewer_init_phase2(struct core_window *cw,
- struct core_window_callback_table *cb_t)
-{
- struct atari_sslcert_viewer_s *cvwin;
- struct sslcert_session_data *ssl_d;
-
- cvwin = (struct atari_sslcert_viewer_s *)atari_treeview_get_user_data(cw);
-
- assert(cvwin);
-
- ssl_d = cvwin->ssl_session_data;
-
- assert(ssl_d);
-
- NSLOG(netsurf, INFO, "cw %p", cw);
-
- return(sslcert_viewer_init(cb_t, cw, ssl_d));
-}
-
-static void atari_sslcert_viewer_finish(struct core_window *cw)
-{
- struct atari_sslcert_viewer_s *cvwin;
-
- assert(cw);
-
- cvwin = (struct atari_sslcert_viewer_s *)atari_treeview_get_user_data(cw);
-
- /* This will also free the session data: */
- sslcert_viewer_fini(cvwin->ssl_session_data);
-
- NSLOG(netsurf, INFO, "cw %p", cw);
-}
-
-static void atari_sslcert_viewer_draw(struct core_window *cw, int x,
- int y, struct rect *clip,
- const struct redraw_context *ctx)
-{
- struct atari_sslcert_viewer_s *cvwin;
-
- assert(cw);
-
- cvwin = (struct atari_sslcert_viewer_s *)atari_treeview_get_user_data(cw);
-
- assert(cvwin);
-
- sslcert_viewer_redraw(cvwin->ssl_session_data, x, y, clip, ctx);
-}
-
-static void atari_sslcert_viewer_keypress(struct core_window *cw, uint32_t ucs4)
-{
- struct atari_sslcert_viewer_s *cvwin;
-
- assert(cw);
-
- cvwin = (struct atari_sslcert_viewer_s *)atari_treeview_get_user_data(cw);
-
- NSLOG(netsurf, INFO, "ucs4: %"PRIu32, ucs4);
- sslcert_viewer_keypress(cvwin->ssl_session_data, ucs4);
-}
-
-static void atari_sslcert_viewer_mouse_action(struct core_window *cw,
- browser_mouse_state mouse,
- int x, int y)
-{
- struct atari_sslcert_viewer_s *cvwin;
-
- assert(cw);
-
- cvwin = (struct atari_sslcert_viewer_s *)atari_treeview_get_user_data(cw);
-
- sslcert_viewer_mouse_action(cvwin->ssl_session_data, mouse, x, y);
-}
-
-
-static short handle_event(GUIWIN *win, EVMULT_OUT *ev_out, short msg[8])
-{
- struct core_window *tv=NULL;
- GRECT tb_area;
- GUIWIN * gemtk_win;
- struct atari_sslcert_viewer_s *cvwin = NULL;
- short retval = 0;
- OBJECT *toolbar;
-
- NSLOG(netsurf, INFO, "win %p", win);
-
- if(ev_out->emo_events & MU_MESAG){
- switch (msg[0]) {
-
- case WM_TOOLBAR:
- toolbar = gemtk_obj_get_tree(TOOLBAR_SSL_CERT);
- NSLOG(netsurf, INFO, "CERTVIEWER WM_TOOLBAR");
- tv = (struct core_window*) gemtk_wm_get_user_data(win);
- assert(tv);
- cvwin = (struct atari_sslcert_viewer_s *)
- atari_treeview_get_user_data(tv);
- switch (msg[4]) {
-
- case TOOLBAR_SSL_CERT_TRUSTED:
-
- if (toolbar[msg[4]].ob_state & OS_SELECTED) {
-
- } else {
-
- }
- break;
- }
-
-
- gemtk_win = atari_treeview_get_gemtk_window(tv);
- assert(gemtk_win);
- //gemtk_obj_get_tree(TOOLBAR_HOTLIST)[msg[4]].ob_state &= ~OS_SELECTED;
- atari_treeview_get_grect(tv, TREEVIEW_AREA_TOOLBAR, &tb_area);
- evnt_timer(150);
- gemtk_wm_exec_redraw(gemtk_win, &tb_area);
- retval = 1;
- break;
-
- case WM_CLOSED:
- // TODO set perrmissions
- toolbar = gemtk_obj_get_tree(TOOLBAR_SSL_CERT);
- tv = (struct core_window*) gemtk_wm_get_user_data(win);
- assert(tv);
- cvwin = (struct atari_sslcert_viewer_s *)
- atari_treeview_get_user_data(tv);
- if (toolbar[TOOLBAR_SSL_CERT_TRUSTED].ob_state & OS_SELECTED) {
- sslcert_viewer_accept(cvwin->ssl_session_data);
- } else {
- sslcert_viewer_reject(cvwin->ssl_session_data);
- }
- atari_sslcert_viewer_destroy(cvwin);
- retval = 1;
- break;
-
- default: break;
- }
- }
-
- return(retval);
-}
-
-static void atari_sslcert_viewer_init(struct atari_sslcert_viewer_s * cvwin,
- struct sslcert_session_data *ssl_d)
-{
- assert(cvwin->init == false);
- assert(cvwin->window == NULL);
- assert(cvwin->tv == NULL);
-
- int flags = ATARI_TREEVIEW_WIDGETS;
- short handle = -1;
- OBJECT * tree = gemtk_obj_get_tree(TOOLBAR_SSL_CERT);
- assert( tree );
-
- handle = wind_create(flags, 0, 0, desk_area.g_w, desk_area.g_h);
- cvwin->window = gemtk_wm_add(handle,
- GEMTK_WM_FLAG_DEFAULTS, NULL);
- if (cvwin->window == NULL ) {
- gemtk_msg_box_show(GEMTK_MSG_BOX_ALERT,
- "Failed to allocate Treeview:\nCertviewer");
- return;
- }
- wind_set_str(handle, WF_NAME, (char*)"SSL Certificate");
- gemtk_wm_set_toolbar(cvwin->window, tree, 0, 0);
- gemtk_wm_unlink(cvwin->window);
-
- cvwin->ssl_session_data = ssl_d;
- cvwin->tv = atari_treeview_create(cvwin->window,
- &atari_sslcert_viewer_treeview_callbacks,
- cvwin, flags);
-
- if (cvwin->tv == NULL) {
- /* handle it properly, clean up previous allocs */
- NSLOG(netsurf, INFO, "Failed to allocate treeview");
- return;
- }
-
- cvwin->init = true;
-}
-
-/*
- * documented in certview.h
- */
-void atari_sslcert_viewer_open(struct sslcert_session_data *ssl_d)
-{
- struct atari_sslcert_viewer_s * cvwin;
-
- cvwin = calloc(1, sizeof(struct atari_sslcert_viewer_s));
-
- assert(cvwin);
-
- atari_sslcert_viewer_init(cvwin, ssl_d);
-
- if (atari_treeview_is_open(cvwin->tv) == false) {
-
- GRECT pos;
- pos.g_x = desk_area.g_w - desk_area.g_w / 4;
- pos.g_y = desk_area.g_y;
- pos.g_w = desk_area.g_w / 4;
- pos.g_h = desk_area.g_h;
-
- atari_treeview_open(cvwin->tv, &pos);
- } else {
- wind_set(gemtk_wm_get_handle(cvwin->window), WF_TOP, 1, 0,
- 0, 0);
- }
-}
-
-
-static void atari_sslcert_viewer_destroy(struct atari_sslcert_viewer_s * cvwin)
-{
- assert(cvwin);
- assert(cvwin->init);
- assert(cvwin->window);
-
- NSLOG(netsurf, INFO, "cvwin %p", cvwin);
-
- if (atari_treeview_is_open(cvwin->tv))
- atari_treeview_close(cvwin->tv);
- wind_delete(gemtk_wm_get_handle(cvwin->window));
- gemtk_wm_remove(cvwin->window);
- cvwin->window = NULL;
- atari_treeview_delete(cvwin->tv);
- free(cvwin);
- NSLOG(netsurf, INFO, "done");
-}
diff --git a/frontends/atari/certview.h b/frontends/atari/certview.h
deleted file mode 100644
index ff15d8076..000000000
--- a/frontends/atari/certview.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2013 Ole Loots <ole@monochrom.net>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef CERTVIEW_H_INCLUDED
-#define CERTVIEW_H_INCLUDED
-
-#include <inttypes.h>
-#include <sys/types.h>
-#include <string.h>
-
-
-#include "assert.h"
-#include "utils/nsoption.h"
-#include "utils/log.h"
-#include "desktop/sslcert_viewer.h"
-
-struct core_window;
-
-struct atari_sslcert_viewer_s {
- GUIWIN * window;
- //struct atari_treeview_window *tv;/*< The hotlist treeview handle. */
- struct core_window *tv;
- struct sslcert_session_data *ssl_session_data;
- bool init;
-};
-
-/**
- * Initializes and opens an certificate inspector window
- * \param ssl_d ssl session data created by sslcert_viewer_create_session_data
- *
- * The window takes ownership of the session data and free's the memory on exit.
- */
-void atari_sslcert_viewer_open(struct sslcert_session_data *ssl_d);
-
-
-#endif // CERTVIEW_H_INCLUDED
diff --git a/frontends/atari/ctxmenu.c b/frontends/atari/ctxmenu.c
index ef4f01ae2..eb6cc1611 100644
--- a/frontends/atari/ctxmenu.c
+++ b/frontends/atari/ctxmenu.c
@@ -216,7 +216,7 @@ void context_popup(struct gui_window * gw, short x, short y)
browser_window_navigate(
gw->browser->bw,
hlcache_handle_get_url(ctx->ccdata.object),
- browser_window_get_url(gw->browser->bw),
+ browser_window_access_url(gw->browser->bw),
BW_NAVIGATE_DOWNLOAD,
NULL,
NULL,
@@ -232,7 +232,7 @@ void context_popup(struct gui_window * gw, short x, short y)
error = browser_window_navigate(
gw->browser->bw,
ctx->ccdata.link,
- browser_window_get_url(gw->browser->bw),
+ browser_window_access_url(gw->browser->bw),
BW_NAVIGATE_DOWNLOAD,
NULL,
NULL,
@@ -269,7 +269,7 @@ void context_popup(struct gui_window * gw, short x, short y)
error = browser_window_create(
BW_CREATE_HISTORY | BW_CREATE_CLONE,
ctx->ccdata.link,
- browser_window_get_url(gw->browser->bw),
+ browser_window_access_url(gw->browser->bw),
gw->browser->bw,
NULL);
if (error != NSERROR_OK) {
diff --git a/frontends/atari/deskmenu.c b/frontends/atari/deskmenu.c
index ded68ca5b..4426415bc 100644
--- a/frontends/atari/deskmenu.c
+++ b/frontends/atari/deskmenu.c
@@ -387,9 +387,7 @@ static void __CDECL menu_inc_scale(short item, short title, void *data)
if(input_window == NULL)
return;
- browser_window_set_scale(input_window->browser->bw,
- browser_window_get_scale(input_window->browser->bw) + 0.25,
- true);
+ browser_window_set_scale(input_window->browser->bw, +0.25, false);
}
@@ -398,9 +396,7 @@ static void __CDECL menu_dec_scale(short item, short title, void *data)
if(input_window == NULL)
return;
- browser_window_set_scale(input_window->browser->bw,
- browser_window_get_scale(input_window->browser->bw) - 0.25,
- true);
+ browser_window_set_scale(input_window->browser->bw, -0.25, false);
}
@@ -510,7 +506,7 @@ static void __CDECL menu_add_bookmark(short item, short title, void *data)
if (input_window) {
if( browser_window_has_content(input_window->browser->bw) ){
atari_hotlist_add_page(
- nsurl_access(browser_window_get_url(input_window->browser->bw)),
+ nsurl_access(browser_window_access_url(input_window->browser->bw)),
NULL
);
}
diff --git a/frontends/atari/encoding.h b/frontends/atari/encoding.h
index 784aa8273..53db7b78b 100644
--- a/frontends/atari/encoding.h
+++ b/frontends/atari/encoding.h
@@ -25,7 +25,7 @@
#include "utils/utf8.h"
-struct gui_utf8_table *atari_utf8_table;
+extern struct gui_utf8_table *atari_utf8_table;
nserror utf8_to_local_encoding(const char *string, size_t len, char **result);
nserror utf8_from_local_encoding(const char *string, size_t len, char **result);
diff --git a/frontends/atari/file.c b/frontends/atari/file.c
index 235d8240f..81b67e86c 100644
--- a/frontends/atari/file.c
+++ b/frontends/atari/file.c
@@ -234,7 +234,7 @@ static nserror atari_mkdir_all(const char *fname)
dname = strdup(fname);
- sep = strrchr(dname, '/');
+ sep = strrchr(dname, '\\');
if (sep == NULL) {
/* no directory separator path is just filename so its ok */
free(dname);
@@ -251,13 +251,13 @@ static nserror atari_mkdir_all(const char *fname)
}
return NSERROR_NOT_DIRECTORY;
}
- *sep = '/'; /* restore separator */
+ *sep = '\\'; /* restore separator */
sep = dname;
- while (*sep == '/') {
+ while (*sep == '\\') {
sep++;
}
- while ((sep = strchr(sep, '/')) != NULL) {
+ while ((sep = strchr(sep, '\\')) != NULL) {
*sep = 0;
if (stat(dname, &sb) != 0) {
if (nsmkdir(dname, S_IRWXU) != 0) {
@@ -272,9 +272,9 @@ static nserror atari_mkdir_all(const char *fname)
return NSERROR_NOT_DIRECTORY;
}
}
- *sep = '/'; /* restore separator */
+ *sep = '\\'; /* restore separator */
/* skip directory separators */
- while (*sep == '/') {
+ while (*sep == '\\') {
sep++;
}
}
diff --git a/frontends/atari/file.h b/frontends/atari/file.h
index b368567c7..3e568834b 100644
--- a/frontends/atari/file.h
+++ b/frontends/atari/file.h
@@ -21,7 +21,7 @@
#include "utils/file.h"
-struct gui_file_table *atari_file_table;
+extern struct gui_file_table *atari_file_table;
#endif /* FILE_C_INCLUDED */
diff --git a/frontends/atari/font.h b/frontends/atari/font.h
index a01d000c0..c0eb99dcd 100644
--- a/frontends/atari/font.h
+++ b/frontends/atari/font.h
@@ -19,7 +19,7 @@
#ifndef NS_ATARI_FONT_H
#define NS_ATARI_FONT_H
-struct gui_layout_table *atari_layout_table;
+extern struct gui_layout_table *atari_layout_table;
#endif /* NETSURF_FB_FONT_H */
diff --git a/frontends/atari/gui.c b/frontends/atari/gui.c
index 6ee63b301..3b324f507 100644
--- a/frontends/atari/gui.c
+++ b/frontends/atari/gui.c
@@ -29,6 +29,7 @@
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/corestrings.h"
+#include "utils/nsoption.h"
#include "netsurf/browser_window.h"
#include "netsurf/layout.h"
#include "netsurf/window.h"
@@ -52,9 +53,7 @@
#include "atari/toolbar.h"
#include "atari/hotlist.h"
#include "atari/cookies.h"
-#include "atari/certview.h"
#include "atari/history.h"
-#include "atari/login.h"
#include "atari/encoding.h"
#include "atari/res/netsurf.rsh"
#include "atari/plot/plot.h"
@@ -299,15 +298,11 @@ void gui_window_destroy(struct gui_window *gw)
* \param gw The gui window to measure content area of.
* \param width receives width of window
* \param height receives height of window
- * \param scaled whether to return scaled values
* \return NSERROR_OK on sucess and width and height updated
* else error code.
*/
static nserror
-gui_window_get_dimensions(struct gui_window *gw,
- int *width,
- int *height,
- bool scaled)
+gui_window_get_dimensions(struct gui_window *gw, int *width, int *height)
{
GRECT rect;
window_get_grect(gw->root, BROWSER_AREA_CONTENT, &rect);
@@ -766,53 +761,6 @@ static void gui_set_clipboard(const char *buffer, size_t length,
}
}
-static void gui_401login_open(nsurl *url, const char *realm,
- nserror (*cb)(bool proceed, void *pw), void *cbpw)
-{
- bool bres;
- char * out = NULL;
- bres = login_form_do( url, (char*)realm, &out);
- if (bres) {
- NSLOG(netsurf, INFO, "url: %s, realm: %s, auth: %s\n",
- nsurl_access(url), realm, out);
- urldb_set_auth_details(url, realm, out);
- }
- if (out != NULL) {
- free( out );
- }
- if (cb != NULL) {
- cb(bres, cbpw);
- }
-
-}
-
-static nserror
-gui_cert_verify(nsurl *url, const struct ssl_cert_info *certs,
- unsigned long num, nserror (*cb)(bool proceed, void *pw),
- void *cbpw)
-{
- struct sslcert_session_data *data;
- NSLOG(netsurf, INFO, "url %s", nsurl_access(url));
-
- // TODO: localize string
- int b = form_alert(1, "[2][SSL Verify failed, continue?][Continue|Abort|Details...]");
- if(b == 1){
- // Accept
- urldb_set_cert_permissions(url, true);
- cb(true, cbpw);
- } else if(b == 2) {
- // Reject
- urldb_set_cert_permissions(url, false);
- cb(false, cbpw);
- } else if(b == 3) {
- // Inspect
- sslcert_viewer_create_session_data(num, url, cb, cbpw, certs,
- &data);
- atari_sslcert_viewer_open(data);
- }
- return NSERROR_OK;
-}
-
void gui_set_input_gui_window(struct gui_window *gw)
{
NSLOG(netsurf, INFO, "Setting input window from: %p to %p\n",
@@ -1065,6 +1013,45 @@ static void gui_init(int argc, char** argv)
toolbar_init();
}
+
+/**
+ * process miscellaneous window events
+ *
+ * \param gw The window receiving the event.
+ * \param event The event code.
+ * \return NSERROR_OK when processed ok
+ */
+static nserror
+gui_window_event(struct gui_window *gw, enum gui_window_event event)
+{
+ switch (event) {
+ case GW_EVENT_UPDATE_EXTENT:
+ gui_window_update_extent(gw);
+ break;
+
+ case GW_EVENT_REMOVE_CARET:
+ gui_window_remove_caret(gw);
+ break;
+
+ case GW_EVENT_NEW_CONTENT:
+ gui_window_new_content(gw);
+ break;
+
+ case GW_EVENT_START_THROBBER:
+ gui_window_start_throbber(gw);
+ break;
+
+ case GW_EVENT_STOP_THROBBER:
+ gui_window_stop_throbber(gw);
+ break;
+
+ default:
+ break;
+ }
+ return NSERROR_OK;
+}
+
+
static struct gui_window_table atari_window_table = {
.create = gui_window_create,
.destroy = gui_window_destroy,
@@ -1072,7 +1059,7 @@ static struct gui_window_table atari_window_table = {
.get_scroll = gui_window_get_scroll,
.set_scroll = gui_window_set_scroll,
.get_dimensions = gui_window_get_dimensions,
- .update_extent = gui_window_update_extent,
+ .event = gui_window_event,
.set_title = gui_window_set_title,
.set_url = gui_window_set_url,
@@ -1080,10 +1067,6 @@ static struct gui_window_table atari_window_table = {
.set_status = atari_window_set_status,
.set_pointer = gui_window_set_pointer,
.place_caret = gui_window_place_caret,
- .remove_caret = gui_window_remove_caret,
- .new_content = gui_window_new_content,
- .start_throbber = gui_window_start_throbber,
- .stop_throbber = gui_window_stop_throbber,
};
static struct gui_clipboard_table atari_clipboard_table = {
@@ -1099,11 +1082,8 @@ static struct gui_fetch_table atari_fetch_table = {
static struct gui_misc_table atari_misc_table = {
.schedule = atari_schedule,
- .warning = atari_warn_user,
.quit = gui_quit,
- .cert_verify = gui_cert_verify,
- .login = gui_401login_open,
};
/* #define WITH_DBG_LOGFILE 1 */
diff --git a/frontends/atari/gui.h b/frontends/atari/gui.h
index 9c9aaaa58..b10aef798 100644
--- a/frontends/atari/gui.h
+++ b/frontends/atari/gui.h
@@ -122,7 +122,6 @@ struct s_gui_win_root
CMP_TOOLBAR toolbar;
CMP_STATUSBAR statusbar;
struct s_focus_info focus;
- float scale;
char * title;
struct bitmap * icon;
struct gui_window *active_gui_window;
diff --git a/frontends/atari/login.c b/frontends/atari/login.c
deleted file mode 100644
index 1b21c5d2a..000000000
--- a/frontends/atari/login.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2010 Ole Loots <ole@monochrom.net>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "utils/config.h"
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdbool.h>
-#include <cflib.h>
-
-#include "utils/errors.h"
-#include "utils/utils.h"
-#include "utils/messages.h"
-#include "utils/log.h"
-
-#include "atari/gui.h"
-#include "atari/misc.h"
-#include "atari/login.h"
-#include "atari/res/netsurf.rsh"
-
-
-bool login_form_do(nsurl * url, char * realm, char ** out)
-{
- char user[255];
- char pass[255];
- //const char * auth;
- short exit_obj = 0;
- OBJECT * tree;
-
- user[0] = 0;
- pass[0] = 0;
-
- // TODO: use auth details for predefined login data
- // auth = urldb_get_auth_details(url, realm);
- tree = gemtk_obj_get_tree(LOGIN);
-
- assert(tree != NULL);
-
- exit_obj = simple_mdial(tree, 0);
-
- if(exit_obj == LOGIN_BT_LOGIN) {
- get_string(tree, LOGIN_TB_USER, user);
- get_string(tree, LOGIN_TB_PASSWORD, pass);
- int size = strlen((char*)&user) + strlen((char*)&pass) + 2 ;
- *out = malloc(size);
- snprintf(*out, size, "%s:%s", user, pass);
- } else {
- *out = NULL;
- }
- return((exit_obj == LOGIN_BT_LOGIN));
-}
-
diff --git a/frontends/atari/plot/font_freetype.c b/frontends/atari/plot/font_freetype.c
index 1688e978b..3ff4ab115 100644
--- a/frontends/atari/plot/font_freetype.c
+++ b/frontends/atari/plot/font_freetype.c
@@ -25,6 +25,7 @@
#include "utils/log.h"
#include "utils/nsoption.h"
#include "netsurf/mouse.h"
+#include "netsurf/bitmap.h"
#include "netsurf/plot_style.h"
#include "atari/gui.h"
@@ -250,7 +251,7 @@ static void ft_fill_scalar(const plot_font_style_t *fstyle, FTC_Scaler srec)
srec->face_id = (FTC_FaceID)font_faces[selected_face];
- srec->width = srec->height = (fstyle->size * 64) / FONT_SIZE_SCALE;
+ srec->width = srec->height = (fstyle->size * 64) / PLOT_STYLE_SCALE;
srec->pixel = 0;
/* calculate x/y resolution, when browser_get_dpi() isn't available */
diff --git a/frontends/atari/plot/font_internal.c b/frontends/atari/plot/font_internal.c
index 709697f74..11732c5ea 100644
--- a/frontends/atari/plot/font_internal.c
+++ b/frontends/atari/plot/font_internal.c
@@ -25,6 +25,7 @@
#include "utils/utf8.h"
#include "utils/log.h"
#include "netsurf/mouse.h"
+#include "netsurf/bitmap.h"
#include "netsurf/plot_style.h"
#include "atari/gui.h"
diff --git a/frontends/atari/plot/font_vdi.c b/frontends/atari/plot/font_vdi.c
index 7cd82ddc9..556c08e82 100644
--- a/frontends/atari/plot/font_vdi.c
+++ b/frontends/atari/plot/font_vdi.c
@@ -106,9 +106,9 @@ static int str_width( FONT_PLOTTER self,const plot_font_style_t *fstyle, const c
fx |= 1;
vst_effects( self->vdi_handle, fx );
/* TODO: replace 90 with global dpi setting */
- //pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 );
+ //pxsize = ceil( (fstyle->size/PLOT_STYLE_SCALE) * 90 / 72 );
//vst_height( self->vdi_handle, pxsize ,&cw, &ch, &cellw, &cellh);
- pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 );
+ pxsize = ceil( (fstyle->size/PLOT_STYLE_SCALE) * 90 );
vst_point( self->vdi_handle, pxsize, &cw, &ch, &cellw, &cellh);
/*
if(slen != utf8_bounded_length(str, length)){
@@ -148,10 +148,10 @@ static int str_split( FONT_PLOTTER self, const plot_font_style_t * fstyle, const
if( fstyle->weight > 450 )
fx |= 1;
vst_effects( self->vdi_handle, fx );
- //pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 );
+ //pxsize = ceil( (fstyle->size/PLOT_STYLE_SCALE) * 90 / 72 );
//vst_height( self->vdi_handle, pxsize ,&cw, &ch, &cellw, &cellh);
- pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 );
+ pxsize = ceil( (fstyle->size/PLOT_STYLE_SCALE) * 90 );
vst_point( self->vdi_handle, pxsize, &cw, &ch, &cellw, &cellh);
*actual_x = 0;
//*char_offset = 0;
@@ -216,7 +216,7 @@ static int pixel_pos( FONT_PLOTTER self, const plot_font_style_t * fstyle,const
if( fstyle->weight > 450 )
fx |= 1;
vst_effects(self->vdi_handle, fx);
- pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 );
+ pxsize = ceil( (fstyle->size/PLOT_STYLE_SCALE) * 90 / 72 );
vst_height( self->vdi_handle, pxsize ,&cw, &ch, &cellw, &cellh);
*actual_x = 0;
*char_offset = 0;
@@ -283,8 +283,8 @@ static int text( FONT_PLOTTER self, int x, int y, const char *text, size_t leng
/* TODO: netsurf uses 90 as default dpi ( somewhere defined in libcss),
use that value or pass it as arg, to reduce netsurf dependency */
- //pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 );
- pxsize = ceil( (fstyle->size/FONT_SIZE_SCALE) * 90 / 72 );
+ //pxsize = ceil( (fstyle->size/PLOT_STYLE_SCALE) * 90 / 72 );
+ pxsize = ceil( (fstyle->size/PLOT_STYLE_SCALE) * 90 / 72 );
plot_get_dimensions(&canvas);
x += canvas.g_x;
diff --git a/frontends/atari/plot/plot.c b/frontends/atari/plot/plot.c
index 14c670352..4935b1776 100644
--- a/frontends/atari/plot/plot.c
+++ b/frontends/atari/plot/plot.c
@@ -2124,7 +2124,7 @@ plot_line(const struct redraw_context *ctx,
{
short pxy[4];
uint32_t lt;
- int sw = pstyle->stroke_width;
+ int sw = plot_style_fixed_to_int(pstyle->stroke_width);
if (((line->x0 < 0) && (line->x1 < 0)) ||
((line->y0 < 0) && (line->y1 < 0))) {
@@ -2183,7 +2183,7 @@ plot_rectangle(const struct redraw_context *ctx,
{
short pxy[4];
GRECT r, rclip, sclip;
- int sw = pstyle->stroke_width;
+ int sw = plot_style_fixed_to_int(pstyle->stroke_width);
uint32_t lt;
/* current canvas clip: */
@@ -2266,7 +2266,7 @@ plot_rectangle(const struct redraw_context *ctx,
if (pstyle->fill_type != PLOT_OP_TYPE_NONE ) {
short stroke_width = (short)(pstyle->stroke_type != PLOT_OP_TYPE_NONE) ?
- pstyle->stroke_width : 0;
+ plot_style_fixed_to_int(pstyle->stroke_width) : 0;
vsf_rgbcolor(atari_plot_vdi_handle, pstyle->fill_colour);
vsf_perimeter(atari_plot_vdi_handle, 0);
@@ -2343,7 +2343,6 @@ plot_polygon(const struct redraw_context *ctx,
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
- * \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
@@ -2352,7 +2351,6 @@ plot_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
- float width,
const float transform[6])
{
/** \todo Implement atari path plot */
diff --git a/frontends/atari/res/netsurf.rsh b/frontends/atari/res/netsurf.rsh
index c856501ae..be2bc949c 100755
--- a/frontends/atari/res/netsurf.rsh
+++ b/frontends/atari/res/netsurf.rsh
@@ -147,9 +147,6 @@
#define SETTINGS_EDIT_MIN_FONT_SIZE 28 /* FTEXT in tree SETTINGS */
#define SETTINGS_DEC_MIN_FONT_SIZE 29 /* BOXCHAR in tree SETTINGS */
#define SETTINGS_INC_MIN_FONT_SIZE 30 /* BOXCHAR in tree SETTINGS */
-#define SETTINGS_EDIT_MIN_GIF_DELAY 35 /* FTEXT in tree SETTINGS */
-#define SETTINGS_INC_GIF_DELAY 36 /* BOXCHAR in tree SETTINGS */
-#define SETTINGS_DEC_GIF_DELAY 37 /* BOXCHAR in tree SETTINGS */
#define SETTINGS_CB_ENABLE_ANIMATION 40 /* BUTTON in tree SETTINGS */
#define SETTINGS_CB_BG_IMAGES 42 /* BUTTON in tree SETTINGS */
#define SETTINGS_CB_FG_IMAGES 44 /* BUTTON in tree SETTINGS */
diff --git a/frontends/atari/res/netsurf.rsm b/frontends/atari/res/netsurf.rsm
index 6c240d371..3122791f7 100755
--- a/frontends/atari/res/netsurf.rsm
+++ b/frontends/atari/res/netsurf.rsm
@@ -132,9 +132,6 @@ ResourceMaster v3.651
#O 28@29@EDIT_MIN_FONT_SIZE@@
#O 29@27@DEC_MIN_FONT_SIZE@@
#O 30@27@INC_MIN_FONT_SIZE@@
-#O 35@29@EDIT_MIN_GIF_DELAY@@
-#O 36@27@INC_GIF_DELAY@@
-#O 37@27@DEC_GIF_DELAY@@
#O 40@26@CB_ENABLE_ANIMATION@@
#O 42@26@CB_BG_IMAGES@@
#O 44@26@CB_FG_IMAGES@@
diff --git a/frontends/atari/rootwin.c b/frontends/atari/rootwin.c
index 6576eac77..8fb3ec0f7 100644
--- a/frontends/atari/rootwin.c
+++ b/frontends/atari/rootwin.c
@@ -288,8 +288,6 @@ int window_create(struct gui_window * gw,
assert(gw->browser);
gw->browser->bw = bw;
- gw->scale = browser_window_get_scale(bw);
-
/* create statusbar component: */
if(sb) {
diff --git a/frontends/atari/search.h b/frontends/atari/search.h
index 04dfed4eb..adac62652 100644
--- a/frontends/atari/search.h
+++ b/frontends/atari/search.h
@@ -43,7 +43,7 @@ typedef struct s_search_form_session * SEARCH_FORM_SESSION;
struct s_search_form_session * nsatari_search_session_create(OBJECT * obj,
struct gui_window *gw);
-struct gui_search_table *atari_search_table;
+extern struct gui_search_table *atari_search_table;
void nsatari_search_session_destroy(struct s_search_form_session *s);
void nsatari_search_perform(struct s_search_form_session *s, OBJECT *obj,
diff --git a/frontends/atari/settings.c b/frontends/atari/settings.c
index 7084bacf7..d76468c17 100644
--- a/frontends/atari/settings.c
+++ b/frontends/atari/settings.c
@@ -48,7 +48,6 @@
extern char options[PATH_MAX];
extern GRECT desk_area;
-static float tmp_option_minimum_gif_delay;
static unsigned tmp_option_memory_cache_size;
static unsigned int tmp_option_disc_cache_size;
static unsigned int tmp_option_expire_url;
@@ -308,10 +307,6 @@ static void display_settings(void)
INPUT_MIN_REFLOW_PERIOD_MAX_LEN );
- tmp_option_minimum_gif_delay = (float)nsoption_int(minimum_gif_delay) / (float)100;
- snprintf( spare, 255, "%01.1f", tmp_option_minimum_gif_delay );
- set_text( SETTINGS_EDIT_MIN_GIF_DELAY, spare, 3 );
-
/* "Network" tab: */
set_text( SETTINGS_EDIT_PROXY_HOST, nsoption_charp(http_proxy_host),
INPUT_PROXY_HOST_MAX_LEN );
@@ -464,11 +459,6 @@ static void form_event(int index, int external)
break;
case SETTINGS_CB_ENABLE_ANIMATION:
- if( checked ) {
- ENABLE_OBJ( SETTINGS_EDIT_MIN_GIF_DELAY );
- } else {
- DISABLE_OBJ( SETTINGS_EDIT_MIN_GIF_DELAY );
- }
break;
case SETTINGS_BT_SEL_FONT_RENDERER:
@@ -697,23 +687,6 @@ static void form_event(int index, int external)
OBJ_REDRAW(SETTINGS_EDIT_HISTORY_AGE);
break;
- case SETTINGS_INC_GIF_DELAY:
- case SETTINGS_DEC_GIF_DELAY:
- if( index == SETTINGS_INC_GIF_DELAY )
- tmp_option_minimum_gif_delay += 0.1;
- else
- tmp_option_minimum_gif_delay -= 0.1;
-
- if( tmp_option_minimum_gif_delay < 0.1 )
- tmp_option_minimum_gif_delay = 0.1;
- if( tmp_option_minimum_gif_delay > 9.0 )
- tmp_option_minimum_gif_delay = 9.0;
- snprintf( spare, 255, "%01.1f", tmp_option_minimum_gif_delay );
- set_text( SETTINGS_EDIT_MIN_GIF_DELAY, spare, 3 );
- is_button = true;
- OBJ_REDRAW(SETTINGS_EDIT_MIN_GIF_DELAY);
- break;
-
case SETTINGS_INC_MIN_FONT_SIZE:
case SETTINGS_DEC_MIN_FONT_SIZE:
if( index == SETTINGS_INC_MIN_FONT_SIZE )
@@ -817,8 +790,6 @@ static void apply_settings(void)
OBJ_SELECTED(SETTINGS_CB_TRANSPARENCY));
nsoption_set_bool(animate_images,
OBJ_SELECTED(SETTINGS_CB_ENABLE_ANIMATION));
- nsoption_set_int(minimum_gif_delay,
- (int)(tmp_option_minimum_gif_delay*100+0.5));
/* nsoption_set_bool(incremental_reflow,
OBJ_SELECTED(SETTINGS_CB_INCREMENTAL_REFLOW));*/
nsoption_set_int(min_reflow_period, tmp_option_min_reflow_period);
diff --git a/frontends/atari/toolbar.c b/frontends/atari/toolbar.c
index fdfedcbee..b8f42267f 100644
--- a/frontends/atari/toolbar.c
+++ b/frontends/atari/toolbar.c
@@ -94,7 +94,7 @@ static float toolbar_url_scale = 1.0;
static plot_font_style_t font_style_url = {
.family = PLOT_FONT_FAMILY_SANS_SERIF,
- .size = 14*FONT_SIZE_SCALE,
+ .size = 14*PLOT_STYLE_SCALE,
.weight = 400,
.flags = FONTF_NONE,
.background = 0xffffff,
@@ -302,7 +302,7 @@ struct s_toolbar *toolbar_create(struct s_gui_win_root *owner)
/* create the url widget: */
font_style_url.size =
- toolbar_styles[t->style].font_height_pt * FONT_SIZE_SCALE;
+ toolbar_styles[t->style].font_height_pt * PLOT_STYLE_SCALE;
textarea_flags ta_flags = TEXTAREA_INTERNAL_CARET;
textarea_setup ta_setup;
diff --git a/frontends/atari/treeview.c b/frontends/atari/treeview.c
index 23db41309..6ab09991a 100644
--- a/frontends/atari/treeview.c
+++ b/frontends/atari/treeview.c
@@ -426,7 +426,7 @@ atari_treeview_invalidate_area(struct core_window *cw,
* \param width the width in px, or negative if don't care
* \param height the height in px, or negative if don't care
*/
-static void
+static nserror
atari_treeview_update_size(struct core_window *cw, int width, int height)
{
GRECT area;
@@ -436,7 +436,7 @@ atari_treeview_update_size(struct core_window *cw, int width, int height)
if (tv != NULL) {
if (tv->disposing)
- return;
+ return NSERROR_INVALID;
/* Get acces to the gemtk window slider settings: */
slid = gemtk_wm_get_scroll_info(tv->window);
@@ -465,6 +465,8 @@ atari_treeview_update_size(struct core_window *cw, int width, int height)
*/
gemtk_wm_update_slider(tv->window, GEMTK_WM_VH_SLIDER);
}
+
+ return NSERROR_OK;
}
@@ -474,11 +476,18 @@ atari_treeview_update_size(struct core_window *cw, int width, int height)
* \param cw the core window object
* \param r rectangle to make visible
*/
-static void
-atari_treeview_scroll_visible(struct core_window *cw, const struct rect *r)
+static nserror
+atari_treeview_set_scroll(struct core_window *cw, int x, int y)
{
- /* atari frontend doesn't support dragging outside the treeview */
- /* so there is no need to implement this? */
+ /* TODO */
+ return NSERROR_OK;
+}
+
+static nserror
+atari_treeview_get_scroll(const struct core_window *cw, int *x, int *y)
+{
+ /* TODO */
+ return NSERROR_NOT_IMPLEMENTED;
}
@@ -489,8 +498,8 @@ atari_treeview_scroll_visible(struct core_window *cw, const struct rect *r)
* \param width to be set to viewport width in px, if non NULL
* \param height to be set to viewport height in px, if non NULL
*/
-static void
-atari_treeview_get_window_dimensions(struct core_window *cw,
+static nserror
+atari_treeview_get_window_dimensions(const struct core_window *cw,
int *width,
int *height)
{
@@ -501,6 +510,8 @@ atari_treeview_get_window_dimensions(struct core_window *cw,
*width = work.g_w;
*height = work.g_h;
}
+
+ return NSERROR_OK;
}
@@ -510,10 +521,10 @@ atari_treeview_get_window_dimensions(struct core_window *cw,
* \param cw the core window object
* \param ds the current drag status
*/
-static void
+static nserror
atari_treeview_drag_status(struct core_window *cw, core_window_drag_status ds)
{
-
+ return NSERROR_NOT_IMPLEMENTED;
}
@@ -523,7 +534,8 @@ atari_treeview_drag_status(struct core_window *cw, core_window_drag_status ds)
static struct core_window_callback_table cw_t = {
.invalidate = atari_treeview_invalidate_area,
.update_size = atari_treeview_update_size,
- .scroll_visible = atari_treeview_scroll_visible,
+ .set_scroll = atari_treeview_set_scroll,
+ .get_scroll = atari_treeview_get_scroll,
.get_window_dimensions = atari_treeview_get_window_dimensions,
.drag_status = atari_treeview_drag_status
};
diff --git a/frontends/atari/verify_ssl.c b/frontends/atari/verify_ssl.c
deleted file mode 100644
index b099fe488..000000000
--- a/frontends/atari/verify_ssl.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright 2010 Ole Loots <ole@monochrom.net>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <windom.h>
-
-#include "utils/errors.h"
-#include "utils/utils.h"
-#include "utils/log.h"
-#include "utils/messages.h"
-
-#include "atari/res/netsurf.rsh"
-#include "atari/verify_ssl.h"
-
-/*
- todo: this file need to use the treeview api - complete rework,
- current implementation is not used in any way.
-*/
-
-extern void * h_gem_rsrc;
-extern short atari_plot_vdi_handle;
-
-
-#define CERT_INF_LINES 8
-
-static struct ssl_info_draw_param
-{
- struct ssl_cert_info * cert_infos_n;
- unsigned long num_certs;
- int current;
- int scrollx;
- int cols;
- int scrolly;
- int rows; /* assumed to be 8 */
- OBJECT * tree;
-} dp;
-
-
-static int cert_display_width( struct ssl_cert_info * cert_info )
-{
- int l1, l2;
- int add = 16; /* strlen("Issuer: "); */
-
- l1 = strlen(cert_info->issuer) + add;
- l2 = strlen(cert_info->subject) + add;
- return( MAX(l1, l2) );
-}
-
-
-static void __CDECL cert_info_draw( WINDOW * win, short buf[8], void * data)
-{
- struct ssl_info_draw_param * dp = (struct ssl_info_draw_param *)data;
- GRECT work;
- short pxy[4];
- int maxchars;
- short d, cbh, cbw;
- int i = 0;
- short x,y,w,h;
- int px_ypos;
- char * line = malloc(512);
- if( line == NULL )
- return;
-
- NSLOG(netsurf, INFO,
- "Cert info draw, win: %p, data: %p, scrollx: %d", win, data,
- dp->scrollx);
-
- WindGet( win, WF_WORKXYWH, &x, &y, &w, &h );
- /*using static values here, as RsrcUserDraw has mem leaks & a very small stack */
- pxy[0] = work.g_x = x + 8;
- pxy[1] = work.g_y = y + 80;
- pxy[2] = x + 8 + 272;
- pxy[3] = y + 80 + 176;
- work.g_w = 272;
- work.g_h = 176;
-
- maxchars = (work.g_w / 8)+1;
- vs_clip( atari_plot_vdi_handle, 1,(short*) &pxy );
- vswr_mode( atari_plot_vdi_handle, MD_REPLACE );
- vsf_interior( atari_plot_vdi_handle, 1 );
- vsf_color( atari_plot_vdi_handle, LWHITE );
- v_bar( atari_plot_vdi_handle, (short*)&pxy );
- vst_height( atari_plot_vdi_handle, 16, &d, &d, &cbw, &cbh );
- vst_alignment(atari_plot_vdi_handle, 0, 5, &d, &d );
- vst_color( atari_plot_vdi_handle, BLACK );
- vst_effects( atari_plot_vdi_handle, 0 );
- px_ypos = 0;
- for(i=0; i<CERT_INF_LINES; i++ ) {
- switch( i ) {
- case 0:
- sprintf(line, "Cert Version: %d", dp->cert_infos_n[dp->current].version );
- break;
-
- case 1:
- sprintf(line, "Invalid before: %s", &dp->cert_infos_n[dp->current].not_before );
- break;
-
- case 2:
- sprintf(line, "Invalid after: %s", &dp->cert_infos_n[dp->current].not_after );
- break;
-
- case 3:
- sprintf(line, "Signature type: %d", dp->cert_infos_n[dp->current].sig_type );
- break;
-
- case 4:
- sprintf(line, "Serial: %d", dp->cert_infos_n[dp->current].serial );
- break;
-
- case 5:
- sprintf(line, "Issuer: %s", &dp->cert_infos_n[dp->current].issuer );
- break;
-
- case 6:
- sprintf(line, "Subject: %s", &dp->cert_infos_n[dp->current].subject );
- break;
-
- case 7:
- sprintf(line, "Cert type: %d", dp->cert_infos_n[dp->current].cert_type );
- break;
-
- default:
- break;
- }
- if( (int)strlen(line) > dp->scrollx ) {
- if( dp->scrollx + maxchars < 511 && ( (signed int)strlen(line) - dp->scrollx) > maxchars )
- line[dp->scrollx + maxchars] = 0;
- v_gtext(atari_plot_vdi_handle, work.g_x + 1, work.g_y + px_ypos, &line[dp->scrollx]);
- }
- px_ypos += cbh;
- }
- vst_alignment(atari_plot_vdi_handle, 0, 0, &d, &d );
- vs_clip( atari_plot_vdi_handle, 0, (short*)&pxy );
- free( line );
-}
-
-
-static void do_popup( WINDOW *win, int index, int mode, void *data)
-{
- struct ssl_info_draw_param * dp = (struct ssl_info_draw_param *)data;
- char * items[dp->num_certs];
- short x, y;
- unsigned int i;
- NSLOG(netsurf, INFO, "do_popup: num certs: %d", dp->num_certs);
- for( i = 0; i<dp->num_certs; i++) {
- items[i] = malloc( 48 );
- strncpy(items[i], (char*)&dp->cert_infos_n[i].issuer, 46 );
- }
- objc_offset( FORM(win), index, &x, &y );
- dp->current = MenuPopUp( items, x, y,
- dp->num_certs, MIN( 3, dp->num_certs), 0,
- P_LIST + P_WNDW + P_CHCK );
- ObjcChange( OC_FORM, win, index, NORMAL, TRUE );
- dp->cols = cert_display_width( &dp->cert_infos_n[dp->current] );
- dp->rows = 8;
- dp->scrollx = 0;
- dp->scrolly = 0;
-
- /* Send (!) redraw ( OC_MSG ) */
- ObjcDrawParent( OC_FORM, FORM(win), VERIFY_BOX_DETAILS, 1, 7 | OC_MSG );
- for( i = 0; i<dp->num_certs; i++) {
- free( items[i] );
- }
-}
-
-
-
-bool
-verify_ssl_form_do(const char * url,
- const struct ssl_cert_info * cert_infos_n,
- unsigned long num_certs)
-{
- OBJECT *tree;
- WINDOW * form;
-
- bool bres = false;
- bool cont = true;
- int res = 0;
-
- RsrcGaddr (h_gem_rsrc , R_TREE, VERIFY, &tree);
- ObjcString( tree, VERIFY_LBL_HOST, (char*)url );
- ObjcChange( OC_OBJC, tree, VERIFY_BT_ACCEPT, 0, 0 );
- ObjcChange( OC_OBJC, tree, VERIFY_BT_REJECT, 0, 0 );
- form = FormWindBegin( tree, (char*)"SSL Verify failed" );
-
- dp.cert_infos_n = (struct ssl_cert_info *)cert_infos_n;
- dp.num_certs = num_certs;
- dp.scrollx = 0;
- dp.scrolly = 0;
- dp.current = 0;
- dp.cols = cert_display_width( &dp.cert_infos_n[dp.current] );
- dp.rows = 8;
- dp.tree = tree;
- EvntDataAdd( form, WM_REDRAW, cert_info_draw, (void*)&dp, EV_BOT );
- /* this results in some extended objects which can not be freed: :( */
- /* RsrcUserDraw( OC_FORM, tree, VERIFY_BOX_DETAILS, cert_info_draw,(void*)&dp ) ; */
- ObjcAttachFormFunc( form, VERIFY_BT_NEXT_CERT, do_popup, &dp );
- /*
- ObjcAttachFormFunc( form, VERIFY_BT_NEXT_CERT, do_popup, &dp );
- ObjcAttachFormFunc( form, VERIFY_BT_NEXT_CERT, do_popup, &dp );
- */
- while( cont ) {
- res = FormWindDo( MU_MESAG );
- cont = false;
- switch( res ){
- case VERIFY_BT_ACCEPT:
- bres = true;
- break;
-
- case VERIFY_BT_NEXT_CERT:
- /* select box clicked or dragged... */
- cont = true;
- break;
-
- case VERIFY_BT_REJECT:
- bres = false;
- break;
-
- case VERIFY_BT_SCROLL_D:
- cont = true;
- dp.scrolly += 1;
- ObjcDrawParent( OC_FORM, form, VERIFY_BOX_DETAILS, 1, 7 | OC_MSG );
- break;
-
- case VERIFY_BT_SCROLL_U:
- cont = true;
- dp.scrolly -= 1;
- ObjcDrawParent( OC_FORM, form, VERIFY_BOX_DETAILS, 1, 7 | OC_MSG );
- break;
-
- case VERIFY_BT_SCROLL_R:
- NSLOG(netsurf, INFO, "scroll r!");
- cont = true;
- dp.scrollx += 1;
- if( dp.scrollx > (dp.cols - (272 / 8 )) )
- dp.scrollx -= 1;
- ObjcDrawParent( OC_FORM, form, VERIFY_BOX_DETAILS, 1, 7 | OC_MSG);
- break;
-
- case VERIFY_BT_SCROLL_L:
- cont = true;
- dp.scrollx -= 1;
- if( dp.scrollx < 0 )
- dp.scrollx = 0;
- ObjcDrawParent( OC_FORM, form, VERIFY_BOX_DETAILS, 1, 7 | OC_MSG );
- break;
-
- default:
- break;
- }
- }
- FormWindEnd( );
- return( bres );
-}
diff --git a/frontends/beos/Makefile b/frontends/beos/Makefile
index 7693ac3f3..81c9326ee 100644
--- a/frontends/beos/Makefile
+++ b/frontends/beos/Makefile
@@ -33,6 +33,50 @@ VERSION_FULL := $(shell sed -n '/_version.*=.*"/{s/.*"\(.*\)".*/\1/;p;}' desktop
VERSION_MAJ := $(shell sed -n '/_major/{s/.* = \([0-9]*\).*/\1/;p;}' desktop/version.c)
VERSION_MIN := $(shell sed -n '/_minor/{s/.* = \([0-9]*\).*/\1/;p;}' desktop/version.c)
+
+HARCH := $(shell getarch)
+HPARCH := $(shell getarch -p)
+ifneq ($(HARCH),$(HPARCH))
+PKGSARCH := _$(HARCH)
+endif
+
+PKGNAME := netsurf$(PKGSARCH)-$(VERSION_MAJ).$(VERSION_MIN)-1-$(HPARCH).hpkg
+HAIKU_TARGET_DIR := netsurf_pkg
+
+# Identity of the packager
+PACKAGER := $(shell git config --get user.name) <$(shell git config --get user.email)>
+
+# package manifest file
+# TODO: remove requires hardcoding
+PKGINFO := \
+name netsurf$(PKGSARCH)\n\
+version $(VERSION_MAJ).$(VERSION_MIN)-1\n\
+architecture $(HPARCH)\n\
+summary "A multi-platform web browser"\n\
+description "Small as a mouse, fast as a cheetah and available for free. NetSurf is a multi-platform web browser for RISC OS, UNIX-like platforms (including Linux), Mac OS X, and more.Whether you want to check your webmail, read the news or post to discussion forums, NetSurf is your lightweight gateway to the world wide web. Actively developed, NetSurf is continually evolving and improving."\n\
+vendor "NetSurf"\n\
+packager "$(PACKAGER)"\n\
+copyrights {\n\t"2003-2018 The NetSurf Browser project"\n}\n\
+licenses {\n\t"GNU GPL v2"\n}\n\
+urls {\n\t"http://www.netsurf-browser.org/"\n}\n\
+source-urls {\n\t"http://download.netsurf-browser.org/netsurf/releases/source/netsurf-$(VERSION_MAJ).$(VERSION_MIN)-src.tar.gz"\n}\n\
+provides {\n\
+\tnetsurf$(PKGSARCH) = $(VERSION_MAJ).$(VERSION_MIN)\n\
+\tapp:netsurf = $(VERSION_MAJ).$(VERSION_MIN)\n\
+}\n\
+requires {\n\
+\thaiku_x86>=r1~alpha4_pm_hrev51655-1\n\
+\tlib:libcurl_x86>=4.4.0\n\
+\tlib:libexpat_x86>=1.6.7\n\
+\tlib:libiconv_x86>=2.5.0\n\
+\tlib:libpng16_x86>=16.34.0\n\
+\tlib:libjpeg_x86>=9.2.0\n\
+\tlib:libssl_x86>=1.0.0\n\
+\tlib:libutf8proc_x86>=1.3.1\n\
+\tlib:libz_x86>=1.2.11\n\
+}\n
+
+
# ----------------------------------------------------------------------------
# Source file setup
# ----------------------------------------------------------------------------
@@ -66,7 +110,7 @@ RDEF_IMP_BEOS := $(addprefix $(OBJROOT)/,$(subst /,_,$(RDEF_IMP_BEOS)))
RDEP_BEOS := \
adblock.css beosdefault.css default.css internal.css quirks.css \
netsurf.png favicon.png ca-bundle.txt \
- credits.html licence.html welcome.html maps.html SearchEngines
+ credits.html licence.html welcome.html SearchEngines
RDEP_BEOS := $(addprefix $(FRONTEND_RESOURCES_DIR)/,$(RDEP_BEOS)) \
$(wildcard $(FRONTEND_RESOURCES_DIR)/icons/*.png) \
@@ -104,4 +148,22 @@ install-beos:
# Package target
# ----------------------------------------------------------------------------
-package-beos:
+package-beos: $(PKGNAME)
+ $(VQ)echo Creating $(PKGNAME)
+
+$(PKGNAME): $(EXETARGET) $(POSTEXES)
+ $(Q)rm -rf $(HAIKU_TARGET_DIR)
+ $(Q)rm -rf $(PKGNAME)
+ $(Q)$(MKDIR) $(HAIKU_TARGET_DIR)
+ $(Q)echo -e '$(PKGINFO)' > $(HAIKU_TARGET_DIR)/.PackageInfo
+ $(Q)$(MKDIR) -p $(HAIKU_TARGET_DIR)/apps/netsurf/res
+ $(Q)$(MKDIR) -p $(HAIKU_TARGET_DIR)/data/deskbar/menu/Applications
+ $(Q)copyattr -d $(EXETARGET) $(HAIKU_TARGET_DIR)/apps/NetSurf
+ $(Q)cp -vRL $(FRONTEND_RESOURCES_DIR)/adblock.css $(HAIKU_TARGET_DIR)/apps/netsurf/res
+ $(Q)cp -vRL $(FRONTEND_RESOURCES_DIR)/ca-bundle.txt $(HAIKU_TARGET_DIR)/apps/netsurf/res
+ $(Q)cp -vRL $(FRONTEND_RESOURCES_DIR)/default.css $(HAIKU_TARGET_DIR)/apps/netsurf/res
+ $(Q)cp -vRL $(FRONTEND_RESOURCES_DIR)/beosdefault.css $(HAIKU_TARGET_DIR)/apps/netsurf/res
+ $(Q)cp -vRL $(FRONTEND_RESOURCES_DIR)/license $(HAIKU_TARGET_DIR)/apps/netsurf/res
+ $(Q)cp -vRL $(FRONTEND_RESOURCES_DIR)/SearchEngines $(HAIKU_TARGET_DIR)/apps/netsurf/res
+ $(Q)ln -s ../../../../apps/NetSurf $(HAIKU_TARGET_DIR)/data/deskbar/menu/Applications/
+ package create -v -C $(HAIKU_TARGET_DIR) $(PKGNAME)
diff --git a/frontends/beos/Makefile.tools b/frontends/beos/Makefile.tools
new file mode 100644
index 000000000..0324a2825
--- /dev/null
+++ b/frontends/beos/Makefile.tools
@@ -0,0 +1,14 @@
+# -*- mode: makefile-gmake -*-
+##
+## BeOS target tool setup
+##
+
+# Building for BeOS/Haiku
+#ifeq ($(HOST),beos)
+ # Build for BeOS on BeOS
+ GCCSDK_INSTALL_ENV := /boot/develop
+ CC := gcc
+ CXX := g++
+ EXEEXT :=
+ PKG_CONFIG := pkg-config
+#endif
diff --git a/frontends/beos/bitmap.cpp b/frontends/beos/bitmap.cpp
index c4b008755..f7e8fa032 100644
--- a/frontends/beos/bitmap.cpp
+++ b/frontends/beos/bitmap.cpp
@@ -114,28 +114,28 @@ static inline void nsbeos_rgba_to_bgra(void *src,
* Create a bitmap.
*
* \param width width of image in pixels
- * \param height width of image in pixels
- * \param state a flag word indicating the initial state
+ * \param height height of image in pixels
+ * \param bflags flags for bitmap creation
* \return an opaque struct bitmap, or NULL on memory exhaustion
*/
-static void *bitmap_create(int width, int height, unsigned int state)
+static void *bitmap_create(int width, int height, enum gui_bitmap_flags flags)
{
struct bitmap *bmp = (struct bitmap *)malloc(sizeof(struct bitmap));
if (bmp == NULL)
return NULL;
- int32 flags = 0;
- if (state & BITMAP_CLEAR_MEMORY)
- flags |= B_BITMAP_CLEAR_TO_WHITE;
+ int32 Bflags = 0;
+ if (flags & BITMAP_CLEAR)
+ Bflags |= B_BITMAP_CLEAR_TO_WHITE;
BRect frame(0, 0, width - 1, height - 1);
//XXX: bytes per row ?
- bmp->primary = new BBitmap(frame, flags, B_RGBA32);
- bmp->shadow = new BBitmap(frame, flags, B_RGBA32);
+ bmp->primary = new BBitmap(frame, Bflags, B_RGBA32);
+ bmp->shadow = new BBitmap(frame, Bflags, B_RGBA32);
bmp->pretile_x = bmp->pretile_y = bmp->pretile_xy = NULL;
- bmp->opaque = (state & BITMAP_OPAQUE) != 0;
+ bmp->opaque = (flags & BITMAP_OPAQUE) != 0;
return bmp;
}
@@ -156,21 +156,6 @@ static void bitmap_set_opaque(void *vbitmap, bool opaque)
/**
- * Tests whether a bitmap has an opaque alpha channel
- *
- * \param vbitmap a bitmap, as returned by bitmap_create()
- * \return whether the bitmap is opaque
- */
-static bool bitmap_test_opaque(void *vbitmap)
-{
- struct bitmap *bitmap = (struct bitmap *)vbitmap;
- assert(bitmap);
- /* todo: test if bitmap is opaque */
- return false;
-}
-
-
-/**
* Gets whether a bitmap should be plotted opaque
*
* \param vbitmap a bitmap, as returned by bitmap_create()
@@ -216,20 +201,6 @@ static size_t bitmap_get_rowstride(void *vbitmap)
/**
- * Find the bytes per pixels of a bitmap.
- *
- * \param vbitmap a bitmap, as returned by bitmap_create()
- * \return bytes per pixels of the bitmap
- */
-static size_t bitmap_get_bpp(void *vbitmap)
-{
- struct bitmap *bitmap = (struct bitmap *)vbitmap;
- assert(bitmap);
- return 4;
-}
-
-
-/**
* Free pretiles of a bitmap.
*
* \param bitmap The bitmap to free the pretiles of.
@@ -261,32 +232,6 @@ static void bitmap_destroy(void *vbitmap)
/**
- * Save a bitmap in the platform's native format.
- *
- * \param vbitmap a bitmap, as returned by bitmap_create()
- * \param path pathname for file
- * \param flags modify the behaviour of the save
- * \return true on success, false on error and error reported
- */
-static bool bitmap_save(void *vbitmap, const char *path, unsigned flags)
-{
- struct bitmap *bitmap = (struct bitmap *)vbitmap;
- BTranslatorRoster *roster = BTranslatorRoster::Default();
- BBitmapStream stream(bitmap->primary);
- BFile file(path, B_WRITE_ONLY | B_CREATE_FILE);
- uint32 type = B_PNG_FORMAT;
-
- if (file.InitCheck() < B_OK)
- return false;
-
- if (roster->Translate(&stream, NULL, NULL, &file, type) < B_OK)
- return false;
-
- return true;
-}
-
-
-/**
* The bitmap image has changed, so flush any persistant cache.
*
* \param vbitmap a bitmap, as returned by bitmap_create()
@@ -543,13 +488,10 @@ static struct gui_bitmap_table bitmap_table = {
/*.destroy =*/ bitmap_destroy,
/*.set_opaque =*/ bitmap_set_opaque,
/*.get_opaque =*/ bitmap_get_opaque,
- /*.test_opaque =*/ bitmap_test_opaque,
/*.get_buffer =*/ bitmap_get_buffer,
/*.get_rowstride =*/ bitmap_get_rowstride,
/*.get_width =*/ bitmap_get_width,
/*.get_height =*/ bitmap_get_height,
- /*.get_bpp =*/ bitmap_get_bpp,
- /*.save =*/ bitmap_save,
/*.modified =*/ bitmap_modified,
/*.render =*/ bitmap_render,
};
diff --git a/frontends/beos/font.cpp b/frontends/beos/font.cpp
index 81113032d..5e7e78228 100644
--- a/frontends/beos/font.cpp
+++ b/frontends/beos/font.cpp
@@ -130,7 +130,7 @@ void nsbeos_style_to_font(BFont &font, const struct plot_font_style *fstyle)
}
//fprintf(stderr, "nsbeos_style_to_font: value %f unit %d\n", style->font_size.value.length.value, style->font_size.value.length.unit);
- size = fstyle->size / FONT_SIZE_SCALE;
+ size = fstyle->size / PLOT_STYLE_SCALE;
//fprintf(stderr, "nsbeos_style_to_font: %f %d\n", size, style->font_size.value.length.unit);
diff --git a/frontends/beos/gui.cpp b/frontends/beos/gui.cpp
index 19f8eac49..cbfe352c8 100644
--- a/frontends/beos/gui.cpp
+++ b/frontends/beos/gui.cpp
@@ -42,6 +42,9 @@
#include <Roster.h>
#include <Screen.h>
#include <String.h>
+#ifdef __HAIKU__
+#include <LocaleRoster.h>
+#endif
extern "C" {
@@ -519,9 +522,18 @@ static BPath get_messages_path()
BPath p;
f.FindPath(B_FIND_PATH_APPS_DIRECTORY, "netsurf/res", p);
- // TODO: use Haiku's BLocale stuff
- BString lang(getenv("LC_MESSAGES"));
- lang.Truncate(2);
+ BString lang;
+#ifdef __HAIKU__
+ BMessage preferredLangs;
+ if (BLocaleRoster::Default()->GetPreferredLanguages(&preferredLangs) == B_OK) {
+ preferredLangs.FindString("language", 0, &lang);
+ lang.Truncate(2);
+ }
+#endif
+ if (lang.Length() < 1) {
+ lang.SetTo(getenv("LC_MESSAGES"));
+ lang.Truncate(2);
+ }
BDirectory d(p.Path());
if (!d.Contains(lang.String(), B_DIRECTORY_NODE))
lang = "en";
@@ -738,12 +750,12 @@ void nsbeos_gui_poll(void)
unsigned int fd_count = 0;
bigtime_t next_schedule = 0;
- /* get any active fetcher fd */
- fetch_fdset(&read_fd_set, &write_fd_set, &exc_fd_set, &max_fd);
-
/* run the scheduler */
schedule_run();
+ /* get any active fetcher fd */
+ fetch_fdset(&read_fd_set, &write_fd_set, &exc_fd_set, &max_fd);
+
// our own event pipe
FD_SET(sEventPipe[0], &read_fd_set);
@@ -778,7 +790,7 @@ void nsbeos_gui_poll(void)
if (len == sizeof(void *)) {
NSLOG(netsurf, DEEPDEBUG,
"gui_poll: BMessage.what %-4.4s\n",
- &(message->what));
+ (char *)&(message->what));
nsbeos_dispatch_event(message);
}
}
@@ -822,7 +834,9 @@ void nsbeos_gui_view_source(struct hlcache_handle *content)
BPath path;
status_t err;
size_t size;
- const char *source = content_get_source_data(content, &size);
+ const uint8_t *source;
+
+ source = content_get_source_data(content, &size);
if (!content || !source) {
beos_warn_user("MiscError", "No document source");
@@ -979,12 +993,11 @@ static struct gui_fetch_table beos_fetch_table = {
static struct gui_misc_table beos_misc_table = {
beos_schedule,
- beos_warn_user,
gui_quit,
gui_launch_url,
- NULL, //cert_verify
- gui_401login_open,
+ NULL, //401login
NULL, // pdf_password (if we have Haru support)
+ NULL, // present_cookies
};
@@ -1040,9 +1053,19 @@ int main(int argc, char** argv)
BResources resources;
resources.SetToImage((const void*)main);
size_t size = 0;
-
+
+ BString lang;
+#ifdef __HAIKU__
+ BMessage preferredLangs;
+ if (BLocaleRoster::Default()->GetPreferredLanguages(&preferredLangs) == B_OK) {
+ preferredLangs.FindString("language", 0, &lang);
+ }
+#endif
+ if (lang.Length() < 1)
+ lang.SetTo(getenv("LC_MESSAGES"));
+
char path[12];
- sprintf(path,"%.2s/Messages", getenv("LC_MESSAGES"));
+ sprintf(path,"%.2s/Messages", lang.String());
NSLOG(netsurf, INFO, "Loading messages from resource %s\n", path);
const uint8_t* res = (const uint8_t*)resources.LoadResource('data', path, &size);
diff --git a/frontends/beos/gui.h b/frontends/beos/gui.h
index debb5f339..f847a95fa 100644
--- a/frontends/beos/gui.h
+++ b/frontends/beos/gui.h
@@ -35,7 +35,12 @@ extern bool nsbeos_done;
extern bool replicated;
int gui_init_replicant(int argc, char** argv);
-extern "C" void gui_401login_open(struct nsurl *url, const char *realm, nserror (*cb)(bool proceed, void *pw), void *cbpw);
+extern "C" nserror gui_401login_open(struct nsurl *url, const char *realm,
+ const char *username, const char *password,
+ nserror (*cb)(const char *username,
+ const char *password,
+ void *pw),
+ void *cbpw);
extern "C" void nsbeos_gui_poll(void);
diff --git a/frontends/beos/login.cpp b/frontends/beos/login.cpp
index 85062987c..b7e20edf5 100644
--- a/frontends/beos/login.cpp
+++ b/frontends/beos/login.cpp
@@ -44,7 +44,9 @@ extern "C" {
class LoginAlert : public BAlert {
public:
- LoginAlert(nserror (*callback)(bool proceed, void *pw),
+ LoginAlert(nserror (*callback)(const char *username,
+ const char *password,
+ void *pw),
void *callbaclpw,
nsurl *url,
const char *host,
@@ -57,7 +59,9 @@ private:
nsurl* fUrl; /**< URL being fetched */
BString fHost; /**< Host for user display */
BString fRealm; /**< Authentication realm */
- nserror (*fCallback)(bool proceed, void *pw);
+ nserror (*fCallback)(const char *username,
+ const char *password,
+ void *pw);
void *fCallbackPw;
BTextControl *fUserControl;
@@ -66,13 +70,17 @@ private:
static void create_login_window(nsurl *host,
lwc_string *realm, const char *fetchurl,
- nserror (*cb)(bool proceed, void *pw), void *cbpw);
+ nserror (*cb)(const char *username,
+ const char *password,
+ void *pw), void *cbpw);
#define TC_H 25
#define TC_MARGIN 10
-LoginAlert::LoginAlert(nserror (*callback)(bool proceed, void *pw),
+LoginAlert::LoginAlert(nserror (*callback)(const char *username,
+ const char *password,
+ void *pw),
void *callbackpw,
nsurl *url,
const char *host,
@@ -164,8 +172,12 @@ LoginAlert::MessageReceived(BMessage *message)
}
-extern "C" void gui_401login_open(nsurl *url, const char *realm,
- nserror (*cb)(bool proceed, void *pw), void *cbpw)
+extern "C" nserror gui_401login_open(nsurl *url, const char *realm,
+ const char *username, const char *password,
+ nserror (*cb)(const char *username,
+ const char *password,
+ void *pw),
+ void *cbpw)
{
lwc_string *host;
@@ -174,12 +186,17 @@ extern "C" void gui_401login_open(nsurl *url, const char *realm,
create_login_window(url, host, realm, cb, cbpw);
free(host);
+
+ return NSERROR_OK;
}
//void create_login_window(struct browser_window *bw, const char *host,
// const char *realm, const char *fetchurl)
static void create_login_window(nsurl *url, lwc_string *host,
- const char *realm, nserror (*cb)(bool proceed, void *pw),
+ const char *realm, nserror (*cb)(
+ const char *username,
+ const char *password,
+ void *pw),
void *cbpw)
{
BString r("Secure Area");
diff --git a/frontends/beos/options.h b/frontends/beos/options.h
index 40d23a3bc..f959442f7 100644
--- a/frontends/beos/options.h
+++ b/frontends/beos/options.h
@@ -18,13 +18,12 @@
*/
-#ifndef _NETSURF_BEOS_OPTIONS_H_
-#define _NETSURF_BEOS_OPTIONS_H_
+#ifndef NETSURF_BEOS_OPTIONS_H_
+#define NETSURF_BEOS_OPTIONS_H_
/* currently nothing here */
#endif
-NSOPTION_BOOL(render_resample, false)
NSOPTION_STRING(url_file, NULL)
diff --git a/frontends/beos/plotters.cpp b/frontends/beos/plotters.cpp
index c4903e045..2c50f9497 100644
--- a/frontends/beos/plotters.cpp
+++ b/frontends/beos/plotters.cpp
@@ -370,7 +370,7 @@ nsbeos_plot_line(const struct redraw_context *ctx,
nsbeos_set_colour(style->stroke_colour);
float pensize = view->PenSize();
- view->SetPenSize(style->stroke_width);
+ view->SetPenSize(plot_style_fixed_to_float(style->stroke_width));
BPoint start(line->x0, line->y0);
BPoint end(line->x1, line->y1);
@@ -447,7 +447,7 @@ nsbeos_plot_rectangle(const struct redraw_context *ctx,
nsbeos_set_colour(style->stroke_colour);
float pensize = view->PenSize();
- view->SetPenSize(style->stroke_width);
+ view->SetPenSize(plot_style_fixed_to_float(style->stroke_width));
BRect rect(nsrect->x0, nsrect->y0, nsrect->x1, nsrect->y1);
view->StrokeRect(rect, pat);
@@ -518,7 +518,6 @@ nsbeos_plot_polygon(const struct redraw_context *ctx,
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
- * \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
@@ -527,7 +526,6 @@ nsbeos_plot_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
- float width,
const float transform[6])
{
unsigned int i;
@@ -578,7 +576,7 @@ nsbeos_plot_path(const struct redraw_context *ctx,
rgb_color old_high = view->HighColor();
float old_pen = view->PenSize();
- view->SetPenSize(width);
+ view->SetPenSize(plot_style_fixed_to_float(pstyle->stroke_width));
view->MovePenTo(0, 0);
if (pstyle->fill_colour != NS_TRANSPARENT) {
view->SetHighColor(nsbeos_rgb_colour(pstyle->fill_colour));
diff --git a/frontends/beos/res/en/maps.html b/frontends/beos/res/en/maps.html
deleted file mode 120000
index 507a4b248..000000000
--- a/frontends/beos/res/en/maps.html
+++ /dev/null
@@ -1 +0,0 @@
-../../../../resources/en/maps.html \ No newline at end of file
diff --git a/frontends/beos/res/maps.html b/frontends/beos/res/maps.html
deleted file mode 120000
index a32f725fb..000000000
--- a/frontends/beos/res/maps.html
+++ /dev/null
@@ -1 +0,0 @@
-en/maps.html \ No newline at end of file
diff --git a/frontends/beos/window.cpp b/frontends/beos/window.cpp
index f4229207b..b97be0f07 100644
--- a/frontends/beos/window.cpp
+++ b/frontends/beos/window.cpp
@@ -92,8 +92,6 @@ struct gui_window {
/* Keep gui_windows in a list for cleanup later */
struct gui_window *next, *prev;
-
- float scale;
};
@@ -336,11 +334,6 @@ struct browser_window *nsbeos_get_browser_for_gui(struct gui_window *g)
return g->bw;
}
-float nsbeos_get_scale_for_gui(struct gui_window *g)
-{
- return g->scale;
-}
-
/* Create a gui_window */
static struct gui_window *gui_window_create(struct browser_window *bw,
struct gui_window *existing,
@@ -360,7 +353,6 @@ static struct gui_window *gui_window_create(struct browser_window *bw,
g->bw = bw;
g->mouse.state = 0;
g->current_pointer = GUI_POINTER_DEFAULT;
- g->scale = browser_window_get_scale(bw);
g->careth = 0;
g->pending_resizes = 0;
@@ -518,9 +510,10 @@ void nsbeos_dispatch_event(BMessage *message)
if (gui->mouse.state & BROWSER_MOUSE_MOD_2 && !ctrl)
gui->mouse.state ^= BROWSER_MOUSE_MOD_2;
- browser_window_mouse_track(gui->bw, (browser_mouse_state)gui->mouse.state,
- (int)(where.x / gui->scale),
- (int)(where.y / gui->scale));
+ browser_window_mouse_track(gui->bw,
+ (browser_mouse_state)gui->mouse.state,
+ (int)(where.x),
+ (int)(where.y));
gui->last_x = (int)where.x;
gui->last_y = (int)where.y;
@@ -562,8 +555,8 @@ void nsbeos_dispatch_event(BMessage *message)
if (mods & B_CONTROL_KEY)
gui->mouse.state |= BROWSER_MOUSE_MOD_2;
- gui->mouse.pressed_x = where.x / gui->scale;
- gui->mouse.pressed_y = where.y / gui->scale;
+ gui->mouse.pressed_x = where.x;
+ gui->mouse.pressed_y = where.y;
// make sure the view is in focus
if (view && view->LockLooper()) {
@@ -624,8 +617,8 @@ void nsbeos_dispatch_event(BMessage *message)
if (gui->mouse.state & (BROWSER_MOUSE_CLICK_1|BROWSER_MOUSE_CLICK_2))
browser_window_mouse_click(gui->bw,
(browser_mouse_state)gui->mouse.state,
- where.x / gui->scale,
- where.y / gui->scale);
+ where.x,
+ where.y);
else
browser_window_mouse_track(gui->bw, (browser_mouse_state)0,
where.x, where.y);
@@ -655,23 +648,26 @@ void nsbeos_dispatch_event(BMessage *message)
{
nsurl* url;
BString realm;
- BString auth;
+ BString username;
+ BString password;
void* cbpw;
- nserror (*cb)(bool proceed, void* pw);
+ nserror (*cb)(const char *username,
+ const char *password,
+ void *pw);
if (message->FindPointer("URL", (void**)&url) < B_OK)
break;
if (message->FindString("Realm", &realm) < B_OK)
break;
- if (message->FindString("Auth", &auth) < B_OK)
+ if (message->FindString("User", &username) < B_OK)
+ break;
+ if (message->FindString("Pass", &password) < B_OK)
break;
if (message->FindPointer("callback", (void**)&cb) < B_OK)
break;
if (message->FindPointer("callback_pw", (void**)&cbpw) < B_OK)
break;
- //printf("login to '%s' with '%s'\n", url.String(), auth.String());
- urldb_set_auth_details(url, realm.String(), auth.String());
- cb(true, cbpw);
+ cb(username.String(), password.String(), cbpw);
break;
}
default:
@@ -683,7 +679,6 @@ void nsbeos_dispatch_event(BMessage *message)
void nsbeos_window_expose_event(BView *view, gui_window *g, BMessage *message)
{
BRect updateRect;
- //float scale = g->scale;
struct rect clip;
struct redraw_context ctx = { true, true, &nsbeos_plotters };
@@ -1113,93 +1108,79 @@ static void gui_window_update_extent(struct gui_window *g)
g->view->UnlockLooper();
}
-/* some cursors like those in Firefox */
-// XXX: move to separate file or resource ?
+static BCursorID gui_haiku_pointer(gui_pointer_shape shape)
+{
+ switch (shape) {
+ case GUI_POINTER_POINT: /* link */
+ return B_CURSOR_ID_FOLLOW_LINK;
-const uint8 kLinkCursorBits[] = {
- 16, /* cursor size */
- 1, /* bits per pixel */
- 2, /* vertical hot spot */
- 2, /* horizontal hot spot */
+ case GUI_POINTER_CARET: /* input */
+ return B_CURSOR_ID_I_BEAM;
- /* data */
- 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x24, 0x00, 0x24, 0x00, 0x13, 0xe0, 0x12, 0x5c, 0x09, 0x2a,
- 0x08, 0x01, 0x3c, 0x21, 0x4c, 0x71, 0x42, 0x71, 0x30, 0xf9, 0x0c, 0xf9, 0x02, 0x02, 0x01, 0x00,
+ case GUI_POINTER_MENU:
+ return B_CURSOR_ID_CONTEXT_MENU;
- /* mask */
- 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x1f, 0xe0, 0x1f, 0xfc, 0x0f, 0xfe,
- 0x0f, 0xff, 0x3f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x3f, 0xff, 0x0f, 0xff, 0x03, 0xfc, 0x01, 0xe0
-};
+ case GUI_POINTER_UP:
+ return B_CURSOR_ID_RESIZE_NORTH;
-const uint8 kWatchCursorBits[] = {
- 16, /* cursor size */
- 1, /* bits per pixel */
- 0, /* vertical hot spot */
- 1, /* horizontal hot spot */
+ case GUI_POINTER_DOWN:
+ return B_CURSOR_ID_RESIZE_SOUTH;
- /* data */
- 0x70, 0x00, 0x48, 0x00, 0x48, 0x00, 0x27, 0xc0, 0x24, 0xb8, 0x12, 0x54, 0x10, 0x02, 0x78, 0x02,
- 0x98, 0x02, 0x84, 0x02, 0x60, 0x3a, 0x18, 0x46, 0x04, 0x8a, 0x02, 0x92, 0x01, 0x82, 0x00, 0x45,
+ case GUI_POINTER_LEFT:
+ return B_CURSOR_ID_RESIZE_WEST;
- /* mask */
- 0x70, 0x00, 0x78, 0x00, 0x78, 0x00, 0x3f, 0xc0, 0x3f, 0xf8, 0x1f, 0xfc, 0x1f, 0xfe, 0x7f, 0xfe,
- 0xff, 0xfe, 0xff, 0xfe, 0x7f, 0xfe, 0x1f, 0xfe, 0x07, 0xfe, 0x03, 0xfe, 0x01, 0xfe, 0x00, 0x7f
-};
+ case GUI_POINTER_RIGHT:
+ return B_CURSOR_ID_RESIZE_EAST;
-const uint8 kWatch2CursorBits[] = {
- 16, /* cursor size */
- 1, /* bits per pixel */
- 0, /* vertical hot spot */
- 1, /* horizontal hot spot */
+ case GUI_POINTER_RU:
+ return B_CURSOR_ID_RESIZE_NORTH_EAST;
- /* data */
- 0x70, 0x00, 0x48, 0x00, 0x48, 0x00, 0x27, 0xc0, 0x24, 0xb8, 0x12, 0x54, 0x10, 0x02, 0x78, 0x02,
- 0x98, 0x02, 0x84, 0x02, 0x60, 0x3a, 0x18, 0x46, 0x04, 0xa2, 0x02, 0x92, 0x01, 0xa2, 0x00, 0x45,
+ case GUI_POINTER_LD:
+ return B_CURSOR_ID_RESIZE_SOUTH_WEST;
- /* mask */
- 0x70, 0x00, 0x78, 0x00, 0x78, 0x00, 0x3f, 0xc0, 0x3f, 0xf8, 0x1f, 0xfc, 0x1f, 0xfe, 0x7f, 0xfe,
- 0xff, 0xfe, 0xff, 0xfe, 0x7f, 0xfe, 0x1f, 0xfe, 0x07, 0xfe, 0x03, 0xfe, 0x01, 0xfe, 0x00, 0x7f
-};
+ case GUI_POINTER_LU:
+ return B_CURSOR_ID_RESIZE_NORTH_WEST;
+
+ case GUI_POINTER_RD:
+ return B_CURSOR_ID_RESIZE_SOUTH_EAST;
+
+ case GUI_POINTER_CROSS:
+ return B_CURSOR_ID_CROSS_HAIR;
+
+ case GUI_POINTER_MOVE:
+ return B_CURSOR_ID_MOVE;
+
+ case GUI_POINTER_WAIT:
+ case GUI_POINTER_PROGRESS:
+ return B_CURSOR_ID_PROGRESS;
+
+ case GUI_POINTER_NO_DROP:
+ case GUI_POINTER_NOT_ALLOWED:
+ return B_CURSOR_ID_NOT_ALLOWED;
+ case GUI_POINTER_HELP:
+ return B_CURSOR_ID_HELP;
+
+ case GUI_POINTER_DEFAULT:
+ default:
+ break;
+ }
+ return B_CURSOR_ID_SYSTEM_DEFAULT;
+}
static void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape)
{
- BCursor *cursor = NULL;
- bool allocated = false;
-
if (g->current_pointer == shape)
return;
g->current_pointer = shape;
- switch (shape) {
- case GUI_POINTER_POINT:
- cursor = new BCursor(kLinkCursorBits);
- allocated = true;
- break;
- case GUI_POINTER_CARET:
- cursor = (BCursor *)B_CURSOR_I_BEAM;
- break;
- case GUI_POINTER_WAIT:
- cursor = new BCursor(kWatchCursorBits);
- allocated = true;
- break;
- case GUI_POINTER_PROGRESS:
- cursor = new BCursor(kWatch2CursorBits);
- allocated = true;
- break;
- default:
- cursor = (BCursor *)B_CURSOR_SYSTEM_DEFAULT;
- allocated = false;
- }
+ BCursor cursor(gui_haiku_pointer(shape));
if (g->view && g->view->LockLooper()) {
- g->view->SetViewCursor(cursor);
+ g->view->SetViewCursor(&cursor);
g->view->UnlockLooper();
}
-
- if (allocated)
- delete cursor;
}
static void gui_window_place_caret(struct gui_window *g, int x, int y, int height,
@@ -1338,28 +1319,64 @@ struct gui_clipboard_table *beos_clipboard_table = &clipboard_table;
* \param g The gui window to measure content area of.
* \param width receives width of window
* \param height receives height of window
- * \param scaled whether to return scaled values
* \return NSERROR_OK on sucess and width and height updated
* else error code.
*/
static nserror
-gui_window_get_dimensions(struct gui_window *g, int *width, int *height,
- bool scaled)
+gui_window_get_dimensions(struct gui_window *g, int *width, int *height)
{
if (g->view &&
g->view->LockLooper()) {
*width = g->view->Bounds().Width() + 1;
*height = g->view->Bounds().Height() + 1;
g->view->UnlockLooper();
-
- if (scaled) {
- *width /= g->scale;
- *height /= g->scale;
- }
}
return NSERROR_OK;
}
+
+/**
+ * process miscellaneous window events
+ *
+ * \param gw The window receiving the event.
+ * \param event The event code.
+ * \return NSERROR_OK when processed ok
+ */
+static nserror
+gui_window_event(struct gui_window *gw, enum gui_window_event event)
+{
+ switch (event) {
+ case GW_EVENT_UPDATE_EXTENT:
+ gui_window_update_extent(gw);
+ break;
+
+ case GW_EVENT_REMOVE_CARET:
+ gui_window_remove_caret(gw);
+ break;
+
+ case GW_EVENT_NEW_CONTENT:
+ gui_window_new_content(gw);
+ break;
+
+ case GW_EVENT_START_SELECTION:
+ gui_start_selection(gw);
+ break;
+
+ case GW_EVENT_START_THROBBER:
+ gui_window_start_throbber(gw);
+ break;
+
+ case GW_EVENT_STOP_THROBBER:
+ gui_window_stop_throbber(gw);
+ break;
+
+ default:
+ break;
+ }
+ return NSERROR_OK;
+}
+
+
static struct gui_window_table window_table = {
gui_window_create,
gui_window_destroy,
@@ -1367,7 +1384,7 @@ static struct gui_window_table window_table = {
gui_window_get_scroll,
gui_window_set_scroll,
gui_window_get_dimensions,
- gui_window_update_extent,
+ gui_window_event,
/* from scaffold */
gui_window_set_title,
@@ -1376,18 +1393,13 @@ static struct gui_window_table window_table = {
gui_window_set_status,
gui_window_set_pointer,
gui_window_place_caret,
- gui_window_remove_caret,
- gui_window_start_throbber,
- gui_window_stop_throbber,
NULL, //drag_start
NULL, //save_link
- NULL, //scroll_start
- gui_window_new_content,
NULL, //create_form_select_menu
NULL, //file_gadget_open
NULL, //drag_save_object
NULL, //drag_save_selection
- gui_start_selection
+ NULL //console_log
};
struct gui_window_table *beos_window_table = &window_table;
diff --git a/frontends/beos/window.h b/frontends/beos/window.h
index 928acca22..f8726a887 100644
--- a/frontends/beos/window.h
+++ b/frontends/beos/window.h
@@ -72,8 +72,6 @@ struct beos_scaffolding *nsbeos_get_scaffold(struct gui_window *g);
struct browser_window *nsbeos_get_browser_for_gui(struct gui_window *g);
-float nsbeos_get_scale_for_gui(struct gui_window *g);
-
int nsbeos_gui_window_update_targets(struct gui_window *g);
void nsbeos_window_destroy_browser(struct gui_window *g);
diff --git a/frontends/framebuffer/Makefile b/frontends/framebuffer/Makefile
index 489eab97a..7408f0cbc 100644
--- a/frontends/framebuffer/Makefile
+++ b/frontends/framebuffer/Makefile
@@ -1,8 +1,14 @@
+#
+# Makefile for NetSurf Framebuffer frontend
+#
+# This file is part of NetSurf
+#
# ----------------------------------------------------------------------------
-# Framebuffer target setup
+# Framebuffer flag setup (using pkg-config)
# ----------------------------------------------------------------------------
-CFLAGS += -Dnsframebuffer
+CFLAGS += -std=c99 -g \
+ -Dnsframebuffer -Dsmall
#resource path
CFLAGS += '-DNETSURF_FB_RESPATH="$(NETSURF_FB_RESPATH)"'
@@ -20,26 +26,62 @@ CFLAGS += '-DNETSURF_FB_FONT_MONOSPACE_BOLD="$(NETSURF_FB_FONT_MONOSPACE_BOLD)"'
CFLAGS += '-DNETSURF_FB_FONT_CURSIVE="$(NETSURF_FB_FONT_CURSIVE)"'
CFLAGS += '-DNETSURF_FB_FONT_FANTASY="$(NETSURF_FB_FONT_FANTASY)"'
-CFLAGS += -std=c99 -g -Dsmall \
- -D_BSD_SOURCE \
- -D_DEFAULT_SOURCE \
- -D_XOPEN_SOURCE=600 \
- -D_POSIX_C_SOURCE=200809L
-
LDFLAGS += -lm
+# freetype is optional but older versions do not use pkg-config
+ifeq ($(NETSURF_FB_FONTLIB),freetype)
+ NETSURF_USE_FREETYPE2 := AUTO
+ NETSURF_FEATURE_FREETYPE2_CFLAGS := -DFB_USE_FREETYPE
+
+ $(eval $(call pkg_config_find_and_add_enabled,FREETYPE2,freetype2,freetype2))
+
+ # try and use non pkg-config method
+ ifeq ($(NETSURF_USE_FREETYPE2),NO)
+ FREETYPE_CONFIG_EXISTS := $(shell freetype-config --cflags >/dev/null && echo yes)
+ ifeq ($(FREETYPE_CONFIG_EXISTS),yes)
+ NETSURF_USE_FREETYPE2 := YES
+ CFLAGS += $(shell freetype-config --cflags) $(NETSURF_FEATURE_FREETYPE2_CFLAGS)
+ LDFLAGS += $(shell freetype-config --libs)
+ $(info FT2.CNFG: freetype2 (freetype2) enabled)
+ else
+ $(info FT2.CNFG: freetype2 (freetype2) failed)
+ $(error Unable to find library for: freetype2)
+ endif
+ endif
+endif
+
# non optional pkg-configed libs
LDFLAGS += -Wl,--whole-archive
$(eval $(call pkg_config_find_and_add,libnsfb,libnsfb))
LDFLAGS += -Wl,--no-whole-archive
-# freetype is optional but does not use pkg-config
-ifeq ($(NETSURF_FB_FONTLIB),freetype)
- CFLAGS += -DFB_USE_FREETYPE $(shell freetype-config --cflags)
- LDFLAGS += $(shell freetype-config --libs)
+# ---------------------------------------------------------------------------
+# Target setup
+# ---------------------------------------------------------------------------
+
+# The filter and target for split messages
+MESSAGES_FILTER=fb
+MESSAGES_TARGET=$(FRONTEND_RESOURCES_DIR)
+
+# ---------------------------------------------------------------------------
+# HOST specific feature flags
+# ---------------------------------------------------------------------------
+
+# enable POSIX and XSI feature flasg except:
+# - the default set on freebsd already has them enabled
+# - openbsd does not require the default source flags
+ifneq ($(HOST),FreeBSD)
+ ifneq ($(HOST),OpenBSD)
+ CFLAGS += -D_POSIX_C_SOURCE=200809L \
+ -D_XOPEN_SOURCE=700 \
+ -D_BSD_SOURCE \
+ -D_DEFAULT_SOURCE \
+ -D_NETBSD_SOURCE
+ else
+ CFLAGS += -D_POSIX_C_SOURCE=200809L
+ endif
endif
-
# ----------------------------------------------------------------------------
# built-in resource setup
# ----------------------------------------------------------------------------
@@ -80,22 +122,10 @@ FB_IMAGE_throbber6 := throbber/throbber6.png
FB_IMAGE_throbber7 := throbber/throbber7.png
FB_IMAGE_throbber8 := throbber/throbber8.png
-# local compiler flags
-ifeq ($(HOST),OpenBSD)
- HOST_CFLAGS += $(shell $(PKG_CONFIG) --cflags libpng)
- HOST_LDFLAGS += $(shell $(PKG_CONFIG) --libs libpng)
-else
- HOST_CFLAGS +=
- HOST_LDFLAGS += -lpng
-endif
-
-# Host tool to convert image bitmaps to source code.
-#
-# convert_image dependd on fb_bitmap.h so that if we change that
+# make convert_image depend on fbtk.h so that if we change that
# header, we get new images built.
-$(TOOLROOT)/convert_image: $(TOOLROOT)/created $(FRONTEND_SOURCE_DIR)/convert_image.c $(FRONTEND_SOURCE_DIR)/fbtk.h
- $(VQ)echo " HOST CC: $@"
- $(Q)$(HOST_CC) $(HOST_CFLAGS) -o $@ $(FRONTEND_SOURCE_DIR)/convert_image.c $(HOST_LDFLAGS)
+$(TOOLROOT)/convert_image: $(FRONTEND_SOURCE_DIR)/fbtk.h
+
# 1: input file
# 2: output file
@@ -117,11 +147,6 @@ $(eval $(foreach V,$(filter FB_IMAGE_%,$(.VARIABLES)),$(call convert_image,$(FRO
# Internal fonts to generate
FB_FONT_internal_ns-sans := fonts/glyph_data
-# Internal font conversion
-$(TOOLROOT)/convert_font: $(TOOLROOT)/created $(FRONTEND_SOURCE_DIR)/convert_font.c
- $(VQ)echo " HOST CC: $@"
- $(Q)$(HOST_CC) -o $@ $(FRONTEND_SOURCE_DIR)/convert_font.c
-
# 1: input file
# 2: output source code file
# 3: output header file
@@ -170,15 +195,15 @@ EXETARGET := nsfb
NETSURF_FRAMEBUFFER_RESOURCE_LIST := adblock.css credits.html \
default.css internal.css licence.html \
- netsurf.png quirks.css welcome.html maps.html Messages
+ netsurf.png quirks.css welcome.html
install-framebuffer:
- $(Q)$(MKDIR) -p $(DESTDIR)$(NETSURF_FRAMEBUFFER_BIN)
- $(Q)$(MKDIR) -p $(DESTDIR)$(NETSURF_FRAMEBUFFER_RESOURCES)
- $(Q)cp -v $(EXETARGET) $(DESTDIR)/$(NETSURF_FRAMEBUFFER_BIN)netsurf-fb
- $(Q)for F in $(NETSURF_FRAMEBUFFER_RESOURCE_LIST); do cp -vL $(FRONTEND_RESOURCES_DIR)/$$F $(DESTDIR)/$(NETSURF_FRAMEBUFFER_RESOURCES); done
- $(Q)$(RM) $(DESTDIR)$(NETSURF_FRAMEBUFFER_RESOURCES)messages
- $(Q)$(SPLIT_MESSAGES) -l en -p fb -f messages -o $(DESTDIR)$(NETSURF_FRAMEBUFFER_RESOURCES)messages -z resources/FatMessages
+ $(VQ)echo " INSTALL: $(DESTDIR)/$(PREFIX)"
+ $(Q)$(INSTALL) -d $(DESTDIR)/$(NETSURF_FRAMEBUFFER_BIN)
+ $(Q)$(INSTALL) -T $(EXETARGET) $(DESTDIR)/$(NETSURF_FRAMEBUFFER_BIN)/netsurf-fb
+ $(Q)$(INSTALL) -d $(DESTDIR)/$(NETSURF_FRAMEBUFFER_RESOURCES)
+ $(Q)for F in $(NETSURF_FRAMEBUFFER_RESOURCE_LIST); do $(INSTALL) -m 644 $(FRONTEND_RESOURCES_DIR)/$$F $(DESTDIR)/$(NETSURF_FRAMEBUFFER_RESOURCES); done
+ $(Q)$(INSTALL) -m 644 -T $(MESSAGES_TARGET)/en/Messages $(DESTDIR)/$(NETSURF_FRAMEBUFFER_RESOURCES)/Messages
# ----------------------------------------------------------------------------
# Package target
diff --git a/frontends/framebuffer/Makefile.defaults b/frontends/framebuffer/Makefile.defaults
index cc712e992..8def7d92a 100644
--- a/frontends/framebuffer/Makefile.defaults
+++ b/frontends/framebuffer/Makefile.defaults
@@ -38,10 +38,10 @@ NETSURF_FB_FONT_CURSIVE := Comic_Sans_MS.ttf
NETSURF_FB_FONT_FANTASY := Impact.ttf
# Default binary install path
-NETSURF_FRAMEBUFFER_BIN := $(PREFIX)/bin/
+NETSURF_FRAMEBUFFER_BIN := $(PREFIX)/bin
# Default resource install path
-NETSURF_FRAMEBUFFER_RESOURCES := $(PREFIX)/share/netsurf/
+NETSURF_FRAMEBUFFER_RESOURCES := $(PREFIX)/share/netsurf
# Default framebuffer search path
NETSURF_FB_RESPATH := $${HOME}/.netsurf/:$${NETSURFRES}:$(NETSURF_FRAMEBUFFER_RESOURCES):./frontends/framebuffer/res
diff --git a/frontends/framebuffer/Makefile.tools b/frontends/framebuffer/Makefile.tools
new file mode 100644
index 000000000..80623b164
--- /dev/null
+++ b/frontends/framebuffer/Makefile.tools
@@ -0,0 +1,15 @@
+# -*- mode: makefile-gmake -*-
+##
+## tool setup for the framebuffer target
+##
+
+ifeq ($(origin GCCSDK_INSTALL_ENV),undefined)
+ PKG_CONFIG := pkg-config
+else
+ PKG_CONFIG := PKG_CONFIG_LIBDIR="$(GCCSDK_INSTALL_ENV)/lib/pkgconfig" pkg-config
+endif
+
+ifneq ($(origin GCCSDK_INSTALL_CROSSBIN),undefined)
+ CC := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc)
+ CXX := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++)
+endif
diff --git a/frontends/framebuffer/bitmap.c b/frontends/framebuffer/bitmap.c
index 1fc9f46a2..c9b58541e 100644
--- a/frontends/framebuffer/bitmap.c
+++ b/frontends/framebuffer/bitmap.c
@@ -47,19 +47,16 @@
* \param state a flag word indicating the initial state
* \return an opaque struct bitmap, or NULL on memory exhaustion
*/
-static void *bitmap_create(int width, int height, unsigned int state)
+static void *bitmap_create(int width, int height, enum gui_bitmap_flags flags)
{
- nsfb_t *bm;
-
- NSLOG(netsurf, INFO, "width %d, height %d, state %u", width, height,
- state);
+ nsfb_t *bm;
bm = nsfb_new(NSFB_SURFACE_RAM);
if (bm == NULL) {
return NULL;
}
- if ((state & BITMAP_OPAQUE) == 0) {
+ if ((flags & BITMAP_OPAQUE) == 0) {
nsfb_set_geometry(bm, width, height, NSFB_FMT_ABGR8888);
} else {
nsfb_set_geometry(bm, width, height, NSFB_FMT_XBGR8888);
@@ -70,9 +67,7 @@ static void *bitmap_create(int width, int height, unsigned int state)
return NULL;
}
- NSLOG(netsurf, INFO, "bitmap %p", bm);
-
- return bm;
+ return bm;
}
@@ -133,20 +128,6 @@ static void bitmap_destroy(void *bitmap)
/**
- * Save a bitmap in the platform's native format.
- *
- * \param bitmap a bitmap, as returned by bitmap_create()
- * \param path pathname for file
- * \param flags flags controlling how the bitmap is saved.
- * \return true on success, false on error and error reported
- */
-static bool bitmap_save(void *bitmap, const char *path, unsigned flags)
-{
- return true;
-}
-
-
-/**
* The bitmap image has changed, so flush any persistant cache.
*
* \param bitmap a bitmap, as returned by bitmap_create()
@@ -175,39 +156,6 @@ static void bitmap_set_opaque(void *bitmap, bool opaque)
/**
- * Tests whether a bitmap has an opaque alpha channel
- *
- * \param bitmap a bitmap, as returned by bitmap_create()
- * \return whether the bitmap is opaque
- */
-static bool bitmap_test_opaque(void *bitmap)
-{
- int tst;
- nsfb_t *bm = bitmap;
- unsigned char *bmpptr;
- int width;
- int height;
-
- assert(bm != NULL);
-
- nsfb_get_buffer(bm, &bmpptr, NULL);
-
- nsfb_get_geometry(bm, &width, &height, NULL);
-
- tst = width * height;
-
- while (tst-- > 0) {
- if (bmpptr[(tst << 2) + 3] != 0xff) {
- NSLOG(netsurf, INFO, "bitmap %p has transparency", bm);
- return false;
- }
- }
- NSLOG(netsurf, INFO, "bitmap %p is opaque", bm);
- return true;
-}
-
-
-/**
* Gets weather a bitmap should be plotted opaque
*
* \param bitmap a bitmap, as returned by bitmap_create()
@@ -251,12 +199,6 @@ static int bitmap_get_height(void *bitmap)
return(height);
}
-/* get bytes per pixel */
-static size_t bitmap_get_bpp(void *bitmap)
-{
- return 4;
-}
-
/**
* Render content into a bitmap.
*
@@ -332,13 +274,10 @@ static struct gui_bitmap_table bitmap_table = {
.destroy = bitmap_destroy,
.set_opaque = bitmap_set_opaque,
.get_opaque = framebuffer_bitmap_get_opaque,
- .test_opaque = bitmap_test_opaque,
.get_buffer = bitmap_get_buffer,
.get_rowstride = bitmap_get_rowstride,
.get_width = bitmap_get_width,
.get_height = bitmap_get_height,
- .get_bpp = bitmap_get_bpp,
- .save = bitmap_save,
.modified = bitmap_modified,
.render = bitmap_render,
};
diff --git a/frontends/framebuffer/corewindow.c b/frontends/framebuffer/corewindow.c
index 93f88ff61..dbd8d013b 100644
--- a/frontends/framebuffer/corewindow.c
+++ b/frontends/framebuffer/corewindow.c
@@ -136,7 +136,7 @@ fb_cw_invalidate(struct core_window *cw, const struct rect *r)
}
-static void
+static nserror
fb_cw_update_size(struct core_window *cw, int width, int height)
{
/* struct fb_corewindow *fb_cw = (struct fb_corewindow *)cw;
@@ -144,41 +144,59 @@ fb_cw_update_size(struct core_window *cw, int width, int height)
toolkit_widget_set_size_request(FB_WIDGET(fb_cw->drawing_area),
width, height);
*/
+ return NSERROR_OK;
+}
+
+
+static nserror
+fb_cw_set_scroll(struct core_window *cw, int x, int y)
+{
+/* struct fb_corewindow *fb_cw = (struct fb_corewindow *)cw;
+
+ toolkit_scroll_widget(fb_cw->widget, r);
+*/
+ return NSERROR_OK;
}
-static void
-fb_cw_scroll_visible(struct core_window *cw, const struct rect *r)
+static nserror
+fb_cw_get_scroll(const struct core_window *cw, int *x, int *y)
{
/* struct fb_corewindow *fb_cw = (struct fb_corewindow *)cw;
toolkit_scroll_widget(fb_cw->widget, r);
*/
+ return NSERROR_NOT_IMPLEMENTED;
}
-static void
-fb_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
+static nserror
+fb_cw_get_window_dimensions(const struct core_window *cw,
+ int *width, int *height)
{
struct fb_corewindow *fb_cw = (struct fb_corewindow *)cw;
*width = fbtk_get_width(fb_cw->drawable);
*height = fbtk_get_height(fb_cw->drawable);
+ return NSERROR_OK;
}
-static void
+static nserror
fb_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
{
struct fb_corewindow *fb_cw = (struct fb_corewindow *)cw;
fb_cw->drag_status = ds;
+
+ return NSERROR_OK;
}
struct core_window_callback_table fb_cw_cb_table = {
.invalidate = fb_cw_invalidate,
.update_size = fb_cw_update_size,
- .scroll_visible = fb_cw_scroll_visible,
+ .set_scroll = fb_cw_set_scroll,
+ .get_scroll = fb_cw_get_scroll,
.get_window_dimensions = fb_cw_get_window_dimensions,
.drag_status = fb_cw_drag_status
};
diff --git a/frontends/framebuffer/fbtk/event.c b/frontends/framebuffer/fbtk/event.c
index 84c6c3791..7a580911b 100644
--- a/frontends/framebuffer/fbtk/event.c
+++ b/frontends/framebuffer/fbtk/event.c
@@ -84,7 +84,7 @@ fbtk_click(fbtk_widget_t *widget, nsfb_event_t *event)
x = fbtk_get_absx(clicked);
y = fbtk_get_absy(clicked);
- NSLOG(netsurf, INFO, "clicked %p at %d,%d", clicked, x, y);
+ NSLOG(netsurf, DEEPDEBUG, "clicked %p at %d,%d", clicked, x, y);
/* post the click */
fbtk_post_callback(clicked, FBTK_CBT_CLICK, event, cloc.x0 - x, cloc.y0 - y);
diff --git a/frontends/framebuffer/fbtk/text.c b/frontends/framebuffer/fbtk/text.c
index 4f3a2385d..9c96dcef4 100644
--- a/frontends/framebuffer/fbtk/text.c
+++ b/frontends/framebuffer/fbtk/text.c
@@ -71,7 +71,7 @@ fb_text_font_style(fbtk_widget_t *widget, int *font_height, int *padding,
#endif
font_style->family = PLOT_FONT_FAMILY_SANS_SERIF;
- font_style->size = px_to_pt(*font_height * FONT_SIZE_SCALE);
+ font_style->size = px_to_pt(*font_height * PLOT_STYLE_SCALE);
font_style->weight = 400;
font_style->flags = FONTF_NONE;
font_style->background = widget->bg;
diff --git a/frontends/framebuffer/fetch.h b/frontends/framebuffer/fetch.h
index 718b08300..d00f3aa21 100644
--- a/frontends/framebuffer/fetch.h
+++ b/frontends/framebuffer/fetch.h
@@ -20,6 +20,6 @@
#ifndef NETSURF_FB_FETCH_H
#define NETSURF_FB_FETCH_H
-struct gui_fetch_table *framebuffer_fetch_table;
+extern struct gui_fetch_table *framebuffer_fetch_table;
#endif
diff --git a/frontends/framebuffer/findfile.c b/frontends/framebuffer/findfile.c
index 67312f452..fffff4687 100644
--- a/frontends/framebuffer/findfile.c
+++ b/frontends/framebuffer/findfile.c
@@ -17,29 +17,130 @@
*/
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include "utils/filepath.h"
+#include "utils/log.h"
#include "framebuffer/findfile.h"
char **respaths; /** resource search path vector */
-/** Create an array of valid paths to search for resources.
+#define MAX_LANGV_SIZE 32
+
+/**
+ * goes through the environment in appropriate order to find configured language
+ *
+ * \return language to use or "C" if nothing appropriate is set
+ */
+static const char *get_language_env(void)
+{
+ const char *envstr;
+
+ envstr = getenv("LANGUAGE");
+ if ((envstr != NULL) && (envstr[0] != 0)) {
+ return envstr;
+ }
+
+ envstr = getenv("LC_ALL");
+ if ((envstr != NULL) && (envstr[0] != 0)) {
+ return envstr;
+ }
+
+ envstr = getenv("LC_MESSAGES");
+ if ((envstr != NULL) && (envstr[0] != 0)) {
+ return envstr;
+ }
+
+ envstr = getenv("LANG");
+ if ((envstr != NULL) && (envstr[0] != 0)) {
+ return envstr;
+ }
+
+ return "C";
+}
+
+/**
+ * build a string vector of language names
+ */
+static char **get_language_names(void)
+{
+ char **langv; /* output string vector of languages */
+ int langc; /* count of languages in vector */
+ const char *envlang; /* colon separated list of languages from environment */
+ int lstart = 0; /* offset to start of current language */
+ int lunder = 0; /* offset to underscore in current language */
+ int lend = 0; /* offset to end of current language */
+ char *nlang;
+
+ langv = calloc(MAX_LANGV_SIZE + 2, sizeof(char *));
+ if (langv == NULL) {
+ return NULL;
+ }
+
+ envlang = get_language_env();
+
+ for (langc = 0; langc < MAX_LANGV_SIZE; langc++) {
+ /* work through envlang splitting on : */
+ while ((envlang[lend] != 0) &&
+ (envlang[lend] != ':') &&
+ (envlang[lend] != '.')) {
+ if (envlang[lend] == '_') {
+ lunder = lend;
+ }
+ lend++;
+ }
+ /* place language in string vector */
+ nlang = malloc(lend - lstart + 1);
+ memcpy(nlang, envlang + lstart, lend - lstart);
+ nlang[lend - lstart] = 0;
+ langv[langc] = nlang;
+
+ /* add language without specialisation to vector */
+ if (lunder != lstart) {
+ nlang = malloc(lunder - lstart + 1);
+ memcpy(nlang, envlang + lstart, lunder - lstart);
+ nlang[lunder - lstart] = 0;
+ langv[++langc] = nlang;
+ }
+
+ /* if we stopped at the dot, move to the colon delimiter */
+ while ((envlang[lend] != 0) &&
+ (envlang[lend] != ':')) {
+ lend++;
+ }
+ if (envlang[lend] == 0) {
+ /* reached end of environment language list */
+ break;
+ }
+ lend++;
+ lstart = lunder = lend;
+ }
+ return langv;
+}
+
+/**
+ * Create an array of valid paths to search for resources.
*
* The idea is that all the complex path computation to find resources
* is performed here, once, rather than every time a resource is
* searched for.
*/
char **
-fb_init_resource(const char *resource_path)
+fb_init_resource_path(const char *resource_path)
{
char **pathv; /* resource path string vector */
char **respath; /* resource paths vector */
- const char *lang = NULL;
+ char **langv;
pathv = filepath_path_to_strvec(resource_path);
- respath = filepath_generate(pathv, &lang);
+ langv = get_language_names();
+
+ respath = filepath_generate(pathv, (const char * const *)langv);
+
+ filepath_free_strvec(langv);
filepath_free_strvec(pathv);
diff --git a/frontends/framebuffer/findfile.h b/frontends/framebuffer/findfile.h
index 1f3db6eb1..5e9e3186b 100644
--- a/frontends/framebuffer/findfile.h
+++ b/frontends/framebuffer/findfile.h
@@ -27,6 +27,6 @@ extern char **respaths;
* is performed here, once, rather than every time a resource is
* searched for.
*/
-char **fb_init_resource(const char *resource_path);
+char **fb_init_resource_path(const char *resource_path);
#endif /* NETSURF_FB_FINDFILE_H */
diff --git a/frontends/framebuffer/font_freetype.c b/frontends/framebuffer/font_freetype.c
index 9e47e4b99..3912821f7 100644
--- a/frontends/framebuffer/font_freetype.c
+++ b/frontends/framebuffer/font_freetype.c
@@ -29,7 +29,7 @@
#include "utils/nsoption.h"
#include "netsurf/utf8.h"
#include "netsurf/layout.h"
-#include "netsurf/browser_window.h"
+#include "netsurf/browser.h"
#include "netsurf/plot_style.h"
#include "framebuffer/gui.h"
@@ -392,7 +392,7 @@ static void fb_fill_scalar(const plot_font_style_t *fstyle, FTC_Scaler srec)
srec->face_id = (FTC_FaceID)fb_faces[selected_face];
- srec->width = srec->height = (fstyle->size * 64) / FONT_SIZE_SCALE;
+ srec->width = srec->height = (fstyle->size * 64) / PLOT_STYLE_SCALE;
srec->pixel = 0;
srec->x_res = srec->y_res = browser_get_dpi();
diff --git a/frontends/framebuffer/font_internal.c b/frontends/framebuffer/font_internal.c
index ff3471d1d..4d28c61ad 100644
--- a/frontends/framebuffer/font_internal.c
+++ b/frontends/framebuffer/font_internal.c
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include "utils/nsoption.h"
+#include "utils/utils.h"
#include "utils/utf8.h"
#include "netsurf/utf8.h"
#include "netsurf/layout.h"
@@ -212,7 +213,7 @@ fb_get_font_size(const plot_font_style_t *fstyle)
{
int size = fstyle->size * 10 /
(((nsoption_int(font_min_size) * 3 +
- nsoption_int(font_size)) / 4) * FONT_SIZE_SCALE);
+ nsoption_int(font_size)) / 4) * PLOT_STYLE_SCALE);
if (size > 2)
size = 2;
else if (size <= 0)
@@ -270,7 +271,8 @@ fb_get_glyph(uint32_t ucs4, enum fb_font_style style, int scale)
break;
}
}
- /* Fall through. */
+ fallthrough;
+
case FB_BOLD:
section = fb_bold_section_table[ucs4 / 256];
if (section != 0 || ucs4 / 256 == 0) {
@@ -281,7 +283,8 @@ fb_get_glyph(uint32_t ucs4, enum fb_font_style style, int scale)
break;
}
}
- /* Fall through. */
+ fallthrough;
+
case FB_ITALIC:
section = fb_italic_section_table[ucs4 / 256];
if (section != 0 || ucs4 / 256 == 0) {
@@ -292,7 +295,8 @@ fb_get_glyph(uint32_t ucs4, enum fb_font_style style, int scale)
break;
}
}
- /* Fall through. */
+ fallthrough;
+
case FB_REGULAR:
section = fb_regular_section_table[ucs4 / 256];
if (section != 0 || ucs4 / 256 == 0) {
@@ -303,7 +307,8 @@ fb_get_glyph(uint32_t ucs4, enum fb_font_style style, int scale)
break;
}
}
- /* Fall through. */
+ fallthrough;
+
default:
glyph_data = get_codepoint(ucs4, style & FB_ITALIC);
break;
diff --git a/frontends/framebuffer/framebuffer.c b/frontends/framebuffer/framebuffer.c
index 2ccc75062..52afdbf5d 100644
--- a/frontends/framebuffer/framebuffer.c
+++ b/frontends/framebuffer/framebuffer.c
@@ -168,7 +168,7 @@ framebuffer_plot_line(const struct redraw_context *ctx,
}
pen.stroke_colour = style->stroke_colour;
- pen.stroke_width = style->stroke_width;
+ pen.stroke_width = plot_style_fixed_to_int(style->stroke_width);
nsfb_plot_line(nsfb, &rect, &pen);
}
@@ -216,7 +216,9 @@ framebuffer_plot_rectangle(const struct redraw_context *ctx,
dashed = true;
}
- nsfb_plot_rectangle(nsfb, &rect, style->stroke_width, style->stroke_colour, dotted, dashed);
+ nsfb_plot_rectangle(nsfb, &rect,
+ plot_style_fixed_to_int(style->stroke_width),
+ style->stroke_colour, dotted, dashed);
}
return NSERROR_OK;
}
@@ -259,7 +261,6 @@ framebuffer_plot_polygon(const struct redraw_context *ctx,
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
- * \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
@@ -268,7 +269,6 @@ framebuffer_plot_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
- float width,
const float transform[6])
{
NSLOG(netsurf, INFO, "path unimplemented");
diff --git a/frontends/framebuffer/gui.c b/frontends/framebuffer/gui.c
index 1e27dafb6..689b63dc1 100644
--- a/frontends/framebuffer/gui.c
+++ b/frontends/framebuffer/gui.c
@@ -153,7 +153,7 @@ widget_scroll_y(struct gui_window *gw, int y, bool abs)
int content_width, content_height;
int height;
- NSLOG(netsurf, INFO, "window scroll");
+ NSLOG(netsurf, DEEPDEBUG, "window scroll");
if (abs) {
bwidget->pany = y - bwidget->scrolly;
} else {
@@ -237,7 +237,8 @@ fb_pan(fbtk_widget_t *widget,
height = fbtk_get_height(widget);
width = fbtk_get_width(widget);
- NSLOG(netsurf, INFO, "panning %d, %d", bwidget->panx, bwidget->pany);
+ NSLOG(netsurf, DEEPDEBUG, "panning %d, %d",
+ bwidget->panx, bwidget->pany);
x = fbtk_get_absx(widget);
y = fbtk_get_absy(widget);
@@ -357,7 +358,6 @@ fb_redraw(fbtk_widget_t *widget,
.plot = &fb_plotters
};
nsfb_t *nsfb = fbtk_get_nsfb(widget);
- float scale = browser_window_get_scale(bw);
x = fbtk_get_absx(widget);
y = fbtk_get_absy(widget);
@@ -377,8 +377,8 @@ fb_redraw(fbtk_widget_t *widget,
clip.y1 = bwidget->redraw_box.y1;
browser_window_redraw(bw,
- (x - bwidget->scrollx) / scale,
- (y - bwidget->scrolly) / scale,
+ x - bwidget->scrollx,
+ y - bwidget->scrolly,
&clip, &ctx);
if (fbtk_get_caret(widget, &caret_x, &caret_y, &caret_h)) {
@@ -450,13 +450,29 @@ static int fb_browser_window_destroy(fbtk_widget_t *widget,
return 0;
}
+static void
+framebuffer_surface_iterator(void *ctx, const char *name, enum nsfb_type_e type)
+{
+ const char *arg0 = ctx;
+ fprintf(stderr, "%s: %s\n", arg0, name);
+}
+
+static enum nsfb_type_e fetype = NSFB_SURFACE_COUNT;
static const char *fename;
static int febpp;
static int fewidth;
static int feheight;
static const char *feurl;
+static void
+framebuffer_pick_default_fename(void *ctx, const char *name, enum nsfb_type_e type)
+{
+ if (type < fetype) {
+ fename = name;
+ }
+}
+
static bool
process_cmdline(int argc, char** argv)
{
@@ -468,7 +484,8 @@ process_cmdline(int argc, char** argv)
NSLOG(netsurf, INFO, "argc %d, argv %p", argc, argv);
- fename = "sdl";
+ nsfb_enumerate_surface_types(framebuffer_pick_default_fename, NULL);
+
febpp = 32;
fewidth = nsoption_int(window_width);
@@ -508,7 +525,7 @@ process_cmdline(int argc, char** argv)
default:
fprintf(stderr,
- "Usage: %s [-f frontend] [-b bpp] url\n",
+ "Usage: %s [-f frontend] [-b bpp] [-w width] [-h height] <url>\n",
argv[0]);
return false;
}
@@ -518,6 +535,16 @@ process_cmdline(int argc, char** argv)
feurl = argv[optind];
}
+ if (nsfb_type_from_name(fename) == NSFB_SURFACE_NONE) {
+ if (strcmp(fename, "?") != 0) {
+ fprintf(stderr,
+ "%s: Unknown surface `%s`\n", argv[0], fename);
+ }
+ fprintf(stderr, "%s: Valid surface names are:\n", argv[0]);
+ nsfb_enumerate_surface_types(framebuffer_surface_iterator, argv[0]);
+ return false;
+ }
+
return true;
}
@@ -627,9 +654,8 @@ fb_browser_window_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
struct gui_window *gw = cbi->context;
struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
browser_mouse_state mouse;
- float scale = browser_window_get_scale(gw->bw);
- int x = (cbi->x + bwidget->scrollx) / scale;
- int y = (cbi->y + bwidget->scrolly) / scale;
+ int x = cbi->x + bwidget->scrollx;
+ int y = cbi->y + bwidget->scrolly;
uint64_t time_now;
static struct {
enum { CLICK_SINGLE, CLICK_DOUBLE, CLICK_TRIPLE } type;
@@ -640,8 +666,8 @@ fb_browser_window_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
cbi->event->type != NSFB_EVENT_KEY_UP)
return 0;
- NSLOG(netsurf, INFO, "browser window clicked at %d,%d", cbi->x,
- cbi->y);
+ NSLOG(netsurf, DEEPDEBUG, "browser window clicked at %d,%d",
+ cbi->x, cbi->y);
switch (cbi->event->type) {
case NSFB_EVENT_KEY_DOWN:
@@ -666,15 +692,17 @@ fb_browser_window_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
case NSFB_KEY_MOUSE_4:
/* scroll up */
- if (browser_window_scroll_at_point(gw->bw, x, y,
- 0, -100) == false)
+ if (browser_window_scroll_at_point(gw->bw,
+ x, y,
+ 0, -100) == false)
widget_scroll_y(gw, -100, false);
break;
case NSFB_KEY_MOUSE_5:
/* scroll down */
- if (browser_window_scroll_at_point(gw->bw, x, y,
- 0, 100) == false)
+ if (browser_window_scroll_at_point(gw->bw,
+ x, y,
+ 0, 100) == false)
widget_scroll_y(gw, 100, false);
break;
@@ -782,9 +810,8 @@ fb_browser_window_move(fbtk_widget_t *widget, fbtk_callback_info *cbi)
browser_mouse_state mouse = 0;
struct gui_window *gw = cbi->context;
struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
- float scale = browser_window_get_scale(gw->bw);
- int x = (cbi->x + bwidget->scrollx) / scale;
- int y = (cbi->y + bwidget->scrolly) / scale;
+ int x = cbi->x + bwidget->scrollx;
+ int y = cbi->y + bwidget->scrolly;
if (gui_drag.state == GUI_DRAG_PRESSED &&
(abs(x - gui_drag.x) > 5 ||
@@ -910,6 +937,27 @@ fb_browser_window_input(fbtk_widget_t *widget, fbtk_callback_info *cbi)
widget_scroll_y(gw, 100, false);
break;
+ case NSFB_KEY_MINUS:
+ if (modifier & FBTK_MOD_RCTRL ||
+ modifier & FBTK_MOD_LCTRL) {
+ browser_window_set_scale(gw->bw, -0.1, false);
+ }
+ break;
+
+ case NSFB_KEY_EQUALS: /* PLUS */
+ if (modifier & FBTK_MOD_RCTRL ||
+ modifier & FBTK_MOD_LCTRL) {
+ browser_window_set_scale(gw->bw, 0.1, false);
+ }
+ break;
+
+ case NSFB_KEY_0:
+ if (modifier & FBTK_MOD_RCTRL ||
+ modifier & FBTK_MOD_LCTRL) {
+ browser_window_set_scale(gw->bw, 1.0, true);
+ }
+ break;
+
case NSFB_KEY_RSHIFT:
modifier |= FBTK_MOD_RSHIFT;
break;
@@ -952,7 +1000,7 @@ fb_browser_window_input(fbtk_widget_t *widget, fbtk_callback_info *cbi)
break;
}
/* Z or Y pressed but not undo or redo; */
- /* Fall through */
+ fallthrough;
default:
ucs4 = fbtk_keycode_to_ucs4(cbi->event->value.keycode,
@@ -1121,7 +1169,7 @@ fb_url_enter(void *pw, char *text)
error = nsurl_create(text, &url);
if (error != NSERROR_OK) {
- fb_warn_user(messages_get_errorcode(error), 0);
+ fb_warn_user("Errorcode:", messages_get_errorcode(error));
} else {
browser_window_navigate(bw, url, NULL, BW_NAVIGATE_HISTORY,
NULL, NULL, NULL);
@@ -1841,10 +1889,9 @@ static bool
gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
{
struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser);
- float scale = browser_window_get_scale(g->bw);
- *sx = bwidget->scrollx / scale;
- *sy = bwidget->scrolly / scale;
+ *sx = bwidget->scrollx;
+ *sy = bwidget->scrolly;
return true;
}
@@ -1864,12 +1911,11 @@ static nserror
gui_window_set_scroll(struct gui_window *gw, const struct rect *rect)
{
struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser);
- float scale = browser_window_get_scale(gw->bw);
assert(bwidget);
- widget_scroll_x(gw, rect->x0 * scale, true);
- widget_scroll_y(gw, rect->y0 * scale, true);
+ widget_scroll_x(gw, rect->x0, true);
+ widget_scroll_y(gw, rect->y0, true);
return NSERROR_OK;
}
@@ -1881,23 +1927,14 @@ gui_window_set_scroll(struct gui_window *gw, const struct rect *rect)
* \param gw The gui window to measure content area of.
* \param width receives width of window
* \param height receives height of window
- * \param scaled whether to return scaled values
* \return NSERROR_OK on sucess and width and height updated.
*/
static nserror
-gui_window_get_dimensions(struct gui_window *gw,
- int *width,
- int *height,
- bool scaled)
+gui_window_get_dimensions(struct gui_window *gw, int *width, int *height)
{
*width = fbtk_get_width(gw->browser);
*height = fbtk_get_height(gw->browser);
- if (scaled) {
- float scale = browser_window_get_scale(gw->bw);
- *width /= scale;
- *height /= scale;
- }
return NSERROR_OK;
}
@@ -2077,6 +2114,38 @@ gui_window_remove_caret(struct gui_window *g)
}
}
+/**
+ * process miscellaneous window events
+ *
+ * \param gw The window receiving the event.
+ * \param event The event code.
+ * \return NSERROR_OK when processed ok
+ */
+static nserror
+gui_window_event(struct gui_window *gw, enum gui_window_event event)
+{
+ switch (event) {
+ case GW_EVENT_UPDATE_EXTENT:
+ gui_window_update_extent(gw);
+ break;
+
+ case GW_EVENT_REMOVE_CARET:
+ gui_window_remove_caret(gw);
+ break;
+
+ case GW_EVENT_START_THROBBER:
+ gui_window_start_throbber(gw);
+ break;
+
+ case GW_EVENT_STOP_THROBBER:
+ gui_window_stop_throbber(gw);
+ break;
+
+ default:
+ break;
+ }
+ return NSERROR_OK;
+}
static struct gui_window_table framebuffer_window_table = {
.create = gui_window_create,
@@ -2085,26 +2154,23 @@ static struct gui_window_table framebuffer_window_table = {
.get_scroll = gui_window_get_scroll,
.set_scroll = gui_window_set_scroll,
.get_dimensions = gui_window_get_dimensions,
- .update_extent = gui_window_update_extent,
+ .event = gui_window_event,
.set_url = gui_window_set_url,
.set_status = gui_window_set_status,
.set_pointer = gui_window_set_pointer,
.place_caret = gui_window_place_caret,
- .remove_caret = gui_window_remove_caret,
- .start_throbber = gui_window_start_throbber,
- .stop_throbber = gui_window_stop_throbber,
};
static struct gui_misc_table framebuffer_misc_table = {
.schedule = framebuffer_schedule,
- .warning = fb_warn_user,
.quit = gui_quit,
};
-/** Entry point from OS.
+/**
+ * Entry point from OS.
*
* /param argc The number of arguments in the string vector.
* /param argv The argument string vector.
@@ -2134,7 +2200,7 @@ main(int argc, char** argv)
die("NetSurf operation table failed registration");
}
- respaths = fb_init_resource(NETSURF_FB_RESPATH":"NETSURF_FB_FONTPATH);
+ respaths = fb_init_resource_path(NETSURF_FB_RESPATH":"NETSURF_FB_FONTPATH);
/* initialise logging. Not fatal if it fails but not much we
* can do about it either.
@@ -2200,7 +2266,7 @@ main(int argc, char** argv)
nsurl_unref(url);
}
if (ret != NSERROR_OK) {
- fb_warn_user(messages_get_errorcode(ret), 0);
+ fb_warn_user("Errorcode:", messages_get_errorcode(ret));
} else {
framebuffer_run();
diff --git a/frontends/framebuffer/local_history.c b/frontends/framebuffer/local_history.c
index cc45b1f29..c1963e2b1 100644
--- a/frontends/framebuffer/local_history.c
+++ b/frontends/framebuffer/local_history.c
@@ -205,6 +205,7 @@ nserror fb_local_history_present(fbtk_widget_t *parent,
fbtk_set_zorder(local_history_window->core.wnd, INT_MIN);
fbtk_set_mapping(local_history_window->core.wnd, true);
+ local_history_scroll_to_cursor(local_history_window->session);
}
return res;
diff --git a/frontends/framebuffer/res/Messages b/frontends/framebuffer/res/Messages
new file mode 120000
index 000000000..75bfdf53d
--- /dev/null
+++ b/frontends/framebuffer/res/Messages
@@ -0,0 +1 @@
+en/Messages \ No newline at end of file
diff --git a/frontends/framebuffer/res/de/welcome.html b/frontends/framebuffer/res/de/welcome.html
new file mode 120000
index 000000000..b77e23743
--- /dev/null
+++ b/frontends/framebuffer/res/de/welcome.html
@@ -0,0 +1 @@
+../../../../resources/de/welcome.html \ No newline at end of file
diff --git a/frontends/framebuffer/res/en/credits.html b/frontends/framebuffer/res/en/credits.html
new file mode 120000
index 000000000..f73ecd4aa
--- /dev/null
+++ b/frontends/framebuffer/res/en/credits.html
@@ -0,0 +1 @@
+../../../../resources/en/credits.html \ No newline at end of file
diff --git a/frontends/framebuffer/res/en/licence.html b/frontends/framebuffer/res/en/licence.html
new file mode 120000
index 000000000..0c3b430b7
--- /dev/null
+++ b/frontends/framebuffer/res/en/licence.html
@@ -0,0 +1 @@
+../../../../resources/en/licence.html \ No newline at end of file
diff --git a/frontends/framebuffer/res/en/welcome.html b/frontends/framebuffer/res/en/welcome.html
new file mode 120000
index 000000000..543f31ddd
--- /dev/null
+++ b/frontends/framebuffer/res/en/welcome.html
@@ -0,0 +1 @@
+../../../../resources/en/welcome.html \ No newline at end of file
diff --git a/frontends/framebuffer/res/fonts/glyph_data b/frontends/framebuffer/res/fonts/glyph_data
index e02756646..3658021b5 100644
--- a/frontends/framebuffer/res/fonts/glyph_data
+++ b/frontends/framebuffer/res/fonts/glyph_data
@@ -5022,6 +5022,25 @@ U+2014 - EM DASH
........ ........ ........ ........
........ ........ ........ ........
-----------------------------------------------------
+U+2015 - HORIZONTAL BAR
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ######## ######## ........ ........
+ ######## ######## ######## ########
+ ........ ........ ######## ########
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
U+2018 - LEFT SINGLE QUOTATION MARK
- - - - - - - - - - - - - - - - - - - - - - - - - - -
........ ........ ........ ........
@@ -5421,6 +5440,82 @@ U+2193 - DOWNWARDS ARROW
........ ........ ........ ........
........ ........ ........ ........
-----------------------------------------------------
+U+2196 - NORTH WEST ARROW
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ #######. .####### ........ ........
+ ######.. .######. #######. #######.
+ ####.... #####... ######.. #######.
+ ##.##... ##.##... #####... #####...
+ #..##... #..##... ##.###.. #####...
+ ...##... ....##.. ##.###.. ##.###..
+ ....##.. ....##.. ...###.. ...###..
+ .....##. .....##. ....###. ....###.
+ .....##. .....##. ....###. ....###.
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+2197 - NORTH EAST ARROW
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .######. ..###### ........ ........
+ ..#####. ...##### .######. ..######
+ ...####. ....#### ..#####. ....####
+ ..##.##. ...##.## ..#####. ..######
+ ..##..#. ..##...# .###.##. ..###.##
+ ..##.... ..##.... .###.... .###....
+ .##..... .##..... .###.... .###....
+ ##...... ##...... ###..... ###.....
+ ##...... ##...... ###..... ###.....
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+2198 - SOUTH EAST ARROW
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ##...... .##..... ###..... .###....
+ ##...... .##..... ###..... .###....
+ .##..... .##..... .###.... .###....
+ ..##.... .##..... .###.... .###....
+ ..##..#. ..##...# .###.##. ..###.##
+ ..##.##. ..##..## ..#####. ...#####
+ ...####. ...####. ..#####. ...####.
+ ..#####. ..#####. .######. .######.
+ .######. .######. ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
+U+2199 - SOUTH WEST ARROW
+- - - - - - - - - - - - - - - - - - - - - - - - - - -
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ .....##. .....##. ....###. .....###
+ .....##. .....##. ....###. .....###
+ ....##.. ....##.. ...###.. ....###.
+ ...##... ....##.. ##.###.. ##.###..
+ #..##... #..##... ##.###.. ##.###..
+ ##.##... ##.##... #####... #####...
+ ####.... #####... ######.. ######..
+ ######.. .######. #######. #######.
+ #######. .####### ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+ ........ ........ ........ ........
+-----------------------------------------------------
U+21E6 - LEFTWARDS WHITE ARROW
- - - - - - - - - - - - - - - - - - - - - - - - - - -
........ ........ ........ ........
diff --git a/frontends/framebuffer/res/it/credits.html b/frontends/framebuffer/res/it/credits.html
new file mode 120000
index 000000000..2b7c99542
--- /dev/null
+++ b/frontends/framebuffer/res/it/credits.html
@@ -0,0 +1 @@
+../../../../resources/it/credits.html \ No newline at end of file
diff --git a/frontends/framebuffer/res/it/licence.html b/frontends/framebuffer/res/it/licence.html
new file mode 120000
index 000000000..92afce85b
--- /dev/null
+++ b/frontends/framebuffer/res/it/licence.html
@@ -0,0 +1 @@
+../../../../resources/it/licence.html \ No newline at end of file
diff --git a/frontends/framebuffer/res/ja/welcome.html b/frontends/framebuffer/res/ja/welcome.html
new file mode 120000
index 000000000..8b603f3df
--- /dev/null
+++ b/frontends/framebuffer/res/ja/welcome.html
@@ -0,0 +1 @@
+../../../../resources/ja/welcome.html \ No newline at end of file
diff --git a/frontends/framebuffer/res/maps.html b/frontends/framebuffer/res/maps.html
deleted file mode 120000
index 05bcdc42e..000000000
--- a/frontends/framebuffer/res/maps.html
+++ /dev/null
@@ -1 +0,0 @@
-../../../resources/en/maps.html \ No newline at end of file
diff --git a/frontends/framebuffer/res/nl/credits.html b/frontends/framebuffer/res/nl/credits.html
new file mode 120000
index 000000000..71b27e40a
--- /dev/null
+++ b/frontends/framebuffer/res/nl/credits.html
@@ -0,0 +1 @@
+../../../../resources/nl/credits.html \ No newline at end of file
diff --git a/frontends/framebuffer/res/nl/licence.html b/frontends/framebuffer/res/nl/licence.html
new file mode 120000
index 000000000..5aaf1cb44
--- /dev/null
+++ b/frontends/framebuffer/res/nl/licence.html
@@ -0,0 +1 @@
+../../../../resources/nl/licence.html \ No newline at end of file
diff --git a/frontends/framebuffer/res/nl/welcome.html b/frontends/framebuffer/res/nl/welcome.html
new file mode 120000
index 000000000..ef7a97cc9
--- /dev/null
+++ b/frontends/framebuffer/res/nl/welcome.html
@@ -0,0 +1 @@
+../../../../resources/nl/welcome.html \ No newline at end of file
diff --git a/frontends/gtk/Makefile b/frontends/gtk/Makefile
index ec60ce70c..64a0872ba 100644
--- a/frontends/gtk/Makefile
+++ b/frontends/gtk/Makefile
@@ -11,6 +11,8 @@
NETSURF_FEATURE_RSVG_CFLAGS := -DWITH_RSVG
NETSURF_FEATURE_VIDEO_CFLAGS := -DWITH_VIDEO
+# determine if the rsvg library API version
+RSVG_API := $(shell $(PKG_CONFIG) --atleast-version=2.46 librsvg-2.0 && echo 246)
$(eval $(call pkg_config_find_and_add_enabled,RSVG,librsvg-2.0,SVG))
$(eval $(call pkg_config_find_and_add_enabled,VIDEO,gstreamer-0.10,Video))
@@ -32,13 +34,19 @@ ifeq ($(NETSURF_GTK_MAJOR),2)
GTKDEPFLAGS += -DGTK_DISABLE_DEPRECATED
endif
+# C library API control
+ifeq ($(HOST),FreeBSD)
+CAPIFLAGS :=
+else
+CAPIFLAGS := -D_XOPEN_SOURCE=700 \
+ -D_POSIX_C_SOURCE=200809L
+endif
GTKCFLAGS := -std=c99 -Dgtk -Dnsgtk -g \
$(GTKDEPFLAGS) \
+ $(CAPIFLAGS) \
-D_BSD_SOURCE \
-D_DEFAULT_SOURCE \
- -D_XOPEN_SOURCE=600 \
- -D_POSIX_C_SOURCE=200809L \
-D_NETBSD_SOURCE \
-DGTK_RESPATH=\"$(NETSURF_GTK_RES_PATH)\"
@@ -59,13 +67,7 @@ LDFLAGS += -lm
NSGTK_RESOURCES_DIR := $(FRONTEND_RESOURCES_DIR)
# The gtk binary target.
-ifeq ($(NETSURF_GTK_MAJOR),2)
- # gtk2 builds have no major suffix
- EXETARGET := nsgtk
-else
- # gtk3 and later builds use the major version suffix
- EXETARGET := nsgtk$(NETSURF_GTK_MAJOR)
-endif
+EXETARGET := nsgtk$(NETSURF_GTK_MAJOR)
# The filter and target for split messages
MESSAGES_FILTER=gtk
@@ -109,6 +111,7 @@ GLIB_COMPILE_RESOURCES := glib-compile-resources
CFLAGS += -DWITH_GRESOURCE
NETSURF_GRESOURCE_XML := $(NSGTK_RESOURCES_DIR)/netsurf.gresource.xml
+UI_GRESOURCE_XML := $(NSGTK_RESOURCES_DIR)/ui.gresource.xml
MESSAGES_GRESOURCE_XML := $(NSGTK_RESOURCES_DIR)/messages.gresource.xml
# generate the netsurf gresource source files
@@ -118,6 +121,13 @@ $(OBJROOT)/netsurf_gresource.c: $(NETSURF_GRESOURCE_XML) $(shell $(GLIB_COMPILE_
S_RESOURCE += $(OBJROOT)/netsurf_gresource.c
+# generate the ui gresource source files
+$(OBJROOT)/ui_gresource.c: $(UI_GRESOURCE_XML) $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir $(NSGTK_RESOURCES_DIR)/gtk$(NETSURF_GTK_MAJOR) --generate-dependencies $(UI_GRESOURCE_XML))
+ $(VQ)echo "GRESORCE: $<"
+ $(Q)$(GLIB_COMPILE_RESOURCES) --generate-source --sourcedir $(NSGTK_RESOURCES_DIR)/gtk$(NETSURF_GTK_MAJOR) --target=$@ $<
+
+S_RESOURCE += $(OBJROOT)/ui_gresource.c
+
# generate the messages gresource source file
$(OBJROOT)/messages_gresource.c: $(MESSAGES_GRESOURCE_XML) $(addsuffix /Messages,$(addprefix $(MESSAGES_TARGET)/,$(MESSAGES_LANGUAGES)))
$(VQ)echo "GRESORCE: $<"
@@ -164,12 +174,12 @@ endif
# ----------------------------------------------------------------------------
# S_FRONTEND are sources purely for the GTK frontend
-S_FRONTEND := gui.c schedule.c layout_pango.c bitmap.c plotters.c \
- scaffolding.c gdk.c completion.c login.c throbber.c accelerator.c \
- selection.c window.c fetch.c download.c menu.c print.c \
- search.c tabs.c toolbar.c gettext.c compat.c viewdata.c \
- viewsource.c preferences.c about.c resources.c corewindow.c \
- local_history.c global_history.c cookies.c hotlist.c ssl_cert.c
+S_FRONTEND := gui.c misc.c schedule.c layout_pango.c bitmap.c plotters.c \
+ scaffolding.c gdk.c completion.c throbber.c accelerator.c \
+ selection.c window.c fetch.c download.c menu.c print.c \
+ search.c tabs.c toolbar.c gettext.c compat.c viewdata.c \
+ viewsource.c preferences.c about.c resources.c corewindow.c \
+ local_history.c global_history.c cookies.c hotlist.c page_info.c
# This is the final source build list
# Note this is deliberately *not* expanded here as common and image
@@ -183,16 +193,15 @@ SOURCES = $(S_COMMON) $(S_IMAGE) $(S_BROWSER) $(S_RESOURCE) $(S_FRONTEND)
GTK_RESOURCES_LIST := \
languages SearchEngines ca-bundle.txt \
default.css adblock.css quirks.css internal.css \
- credits.html licence.html welcome.html maps.html Messages \
- default.ico favicon.png netsurf.png netsurf.xpm netsurf-16x16.xpm \
- arrow_down_8x32.png
+ credits.html licence.html welcome.html Messages \
+ default.ico favicon.png netsurf.png netsurf.xpm netsurf-16x16.xpm
GTK_RESOURCES_LIST := \
$(addprefix $(NSGTK_RESOURCES_DIR)/, $(GTK_RESOURCES_LIST)) \
- $(wildcard $(NSGTK_RESOURCES_DIR)/*.gtk$(NETSURF_GTK_MAJOR).ui)
+ $(wildcard $(NSGTK_RESOURCES_DIR)/gtk$(NETSURF_GTK_MAJOR)/*.ui)
# translations with more than just Messages files
-GTK_TRANSLATIONS_HTML := de en fr it ja nl
+GTK_TRANSLATIONS_HTML := de en fr it ja nl zh_CN
# destination for installed resources is the first entry in the gtk resource path
NSGTK_RESOURCES_DESTDIR := $(DESTDIR)$(word 1,$(subst :, ,$(NETSURF_GTK_RES_PATH)))
diff --git a/frontends/gtk/Makefile.tools b/frontends/gtk/Makefile.tools
new file mode 100644
index 000000000..5331dcc71
--- /dev/null
+++ b/frontends/gtk/Makefile.tools
@@ -0,0 +1,16 @@
+# -*- mode: makefile-gmake -*-
+##
+## tool setup for the gtk target
+##
+
+# use native package config
+PKG_CONFIG := pkg-config
+
+# gtk target processing
+ifeq ($(SUBTARGET),3)
+ override NETSURF_GTK_MAJOR := 3
+endif
+
+ifeq ($(SUBTARGET),2)
+ override NETSURF_GTK_MAJOR := 2
+endif
diff --git a/frontends/gtk/bitmap.c b/frontends/gtk/bitmap.c
index 36b614cf9..a995a9e28 100644
--- a/frontends/gtk/bitmap.c
+++ b/frontends/gtk/bitmap.c
@@ -45,22 +45,25 @@
* Create a bitmap.
*
* \param width width of image in pixels
- * \param height width of image in pixels
- * \param state a flag word indicating the initial state
+ * \param height height of image in pixels
+ * \param flags flags for bitmap creation
* \return an opaque struct bitmap, or NULL on memory exhaustion
*/
-static void *bitmap_create(int width, int height, unsigned int state)
+static void *bitmap_create(int width, int height, enum gui_bitmap_flags flags)
{
struct bitmap *gbitmap;
+ if (width == 0 || height == 0) {
+ return NULL;
+ }
+
gbitmap = calloc(1, sizeof(struct bitmap));
if (gbitmap != NULL) {
- if ((state & BITMAP_OPAQUE) != 0) {
- gbitmap->surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
- } else {
- gbitmap->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
+ if (flags & BITMAP_OPAQUE) {
+ gbitmap->opaque = true;
}
+ gbitmap->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
if (cairo_surface_status(gbitmap->surface) != CAIRO_STATUS_SUCCESS) {
cairo_surface_destroy(gbitmap->surface);
free(gbitmap);
@@ -81,76 +84,8 @@ static void *bitmap_create(int width, int height, unsigned int state)
static void bitmap_set_opaque(void *vbitmap, bool opaque)
{
struct bitmap *gbitmap = (struct bitmap *)vbitmap;
- cairo_format_t fmt;
- cairo_surface_t *nsurface = NULL;
-
- assert(gbitmap);
-
- fmt = cairo_image_surface_get_format(gbitmap->surface);
- if (fmt == CAIRO_FORMAT_RGB24) {
- if (opaque == false) {
- /* opaque to transparent */
- nsurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
- cairo_image_surface_get_width(gbitmap->surface),
- cairo_image_surface_get_height(gbitmap->surface));
-
- }
-
- } else {
- if (opaque == true) {
- /* transparent to opaque */
- nsurface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
- cairo_image_surface_get_width(gbitmap->surface),
- cairo_image_surface_get_height(gbitmap->surface));
-
- }
- }
-
- if (nsurface != NULL) {
- if (cairo_surface_status(nsurface) != CAIRO_STATUS_SUCCESS) {
- cairo_surface_destroy(nsurface);
- } else {
- memcpy(cairo_image_surface_get_data(nsurface),
- cairo_image_surface_get_data(gbitmap->surface),
- cairo_image_surface_get_stride(gbitmap->surface) * cairo_image_surface_get_height(gbitmap->surface));
- cairo_surface_destroy(gbitmap->surface);
- gbitmap->surface = nsurface;
-
- cairo_surface_mark_dirty(gbitmap->surface);
-
- }
-
- }
-}
-
-
-/**
- * Tests whether a bitmap has an opaque alpha channel
- *
- * \param vbitmap a bitmap, as returned by bitmap_create()
- * \return whether the bitmap is opaque
- */
-static bool bitmap_test_opaque(void *vbitmap)
-{
- struct bitmap *gbitmap = (struct bitmap *)vbitmap;
- unsigned char *pixels;
- int pcount;
- int ploop;
-
- assert(gbitmap);
-
- pixels = cairo_image_surface_get_data(gbitmap->surface);
-
- pcount = cairo_image_surface_get_stride(gbitmap->surface) *
- cairo_image_surface_get_height(gbitmap->surface);
-
- for (ploop = 3; ploop < pcount; ploop += 4) {
- if (pixels[ploop] != 0xff) {
- return false;
- }
- }
- return true;
+ gbitmap->opaque = opaque;
}
@@ -162,16 +97,8 @@ static bool bitmap_test_opaque(void *vbitmap)
static bool bitmap_get_opaque(void *vbitmap)
{
struct bitmap *gbitmap = (struct bitmap *)vbitmap;
- cairo_format_t fmt;
- assert(gbitmap);
-
- fmt = cairo_image_surface_get_format(gbitmap->surface);
- if (fmt == CAIRO_FORMAT_RGB24) {
- return true;
- }
-
- return false;
+ return gbitmap->opaque;
}
@@ -187,83 +114,13 @@ static bool bitmap_get_opaque(void *vbitmap)
static unsigned char *bitmap_get_buffer(void *vbitmap)
{
struct bitmap *gbitmap = (struct bitmap *)vbitmap;
- int pixel_loop;
- int pixel_count;
uint8_t *pixels;
- uint32_t t, r, g, b;
- cairo_format_t fmt;
assert(gbitmap);
cairo_surface_flush(gbitmap->surface);
pixels = cairo_image_surface_get_data(gbitmap->surface);
- if (!gbitmap->converted)
- return pixels;
-
- fmt = cairo_image_surface_get_format(gbitmap->surface);
- pixel_count = cairo_image_surface_get_width(gbitmap->surface) *
- cairo_image_surface_get_height(gbitmap->surface);
-
- if (fmt == CAIRO_FORMAT_RGB24) {
- /* Opaque image */
- for (pixel_loop=0; pixel_loop < pixel_count; pixel_loop++) {
- /* Cairo surface is ARGB, written in native endian */
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- b = pixels[4 * pixel_loop + 0];
- g = pixels[4 * pixel_loop + 1];
- r = pixels[4 * pixel_loop + 2];
- t = pixels[4 * pixel_loop + 3];
-#else
- t = pixels[4 * pixel_loop + 0];
- r = pixels[4 * pixel_loop + 1];
- g = pixels[4 * pixel_loop + 2];
- b = pixels[4 * pixel_loop + 3];
-#endif
-
- /* Core bitmaps always have a component order of rgba,
- * regardless of system endianness */
- pixels[4 * pixel_loop + 0] = r;
- pixels[4 * pixel_loop + 1] = g;
- pixels[4 * pixel_loop + 2] = b;
- pixels[4 * pixel_loop + 3] = t;
- }
- } else {
- /* Alpha image: de-multiply alpha */
- for (pixel_loop=0; pixel_loop < pixel_count; pixel_loop++) {
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- b = pixels[4 * pixel_loop + 0];
- g = pixels[4 * pixel_loop + 1];
- r = pixels[4 * pixel_loop + 2];
- t = pixels[4 * pixel_loop + 3];
-#else
- t = pixels[4 * pixel_loop + 0];
- r = pixels[4 * pixel_loop + 1];
- g = pixels[4 * pixel_loop + 2];
- b = pixels[4 * pixel_loop + 3];
-#endif
-
- if (t != 0) {
- r = (r << 8) / t;
- g = (g << 8) / t;
- b = (b << 8) / t;
-
- r = (r > 255) ? 255 : r;
- g = (g > 255) ? 255 : g;
- b = (b > 255) ? 255 : b;
- } else {
- r = g = b = 0;
- }
-
- pixels[4 * pixel_loop + 0] = r;
- pixels[4 * pixel_loop + 1] = g;
- pixels[4 * pixel_loop + 2] = b;
- pixels[4 * pixel_loop + 3] = t;
- }
- }
-
- gbitmap->converted = false;
-
return (unsigned char *) pixels;
}
@@ -284,22 +141,6 @@ static size_t bitmap_get_rowstride(void *vbitmap)
/**
- * Find the bytes per pixel of a bitmap
- *
- * \param vbitmap a bitmap, as returned by bitmap_create()
- * \return bytes per pixel
- */
-static size_t bitmap_get_bpp(void *vbitmap)
-{
- struct bitmap *gbitmap = (struct bitmap *)vbitmap;
- assert(gbitmap);
-
- return 4;
-}
-
-
-
-/**
* Free a bitmap.
*
* \param vbitmap a bitmap, as returned by bitmap_create()
@@ -320,23 +161,6 @@ static void bitmap_destroy(void *vbitmap)
/**
- * Save a bitmap in the platform's native format.
- *
- * \param vbitmap a bitmap, as returned by bitmap_create()
- * \param path pathname for file
- * \param flags modify the behaviour of the save
- * \return true on success, false on error and error reported
- */
-static bool bitmap_save(void *vbitmap, const char *path, unsigned flags)
-{
- struct bitmap *gbitmap = (struct bitmap *)vbitmap;
- assert(gbitmap);
-
- return false;
-}
-
-
-/**
* The bitmap image has changed, so flush any persistant cache.
*
* \param vbitmap a bitmap, as returned by bitmap_create()
@@ -344,81 +168,10 @@ static bool bitmap_save(void *vbitmap, const char *path, unsigned flags)
static void bitmap_modified(void *vbitmap)
{
struct bitmap *gbitmap = (struct bitmap *)vbitmap;
- int pixel_loop;
- int pixel_count;
- uint8_t *pixels;
- uint32_t t, r, g, b;
- cairo_format_t fmt;
assert(gbitmap);
- fmt = cairo_image_surface_get_format(gbitmap->surface);
-
- pixel_count = cairo_image_surface_get_width(gbitmap->surface) *
- cairo_image_surface_get_height(gbitmap->surface);
- pixels = cairo_image_surface_get_data(gbitmap->surface);
-
- if (gbitmap->converted) {
- cairo_surface_mark_dirty(gbitmap->surface);
- return;
- }
-
- if (fmt == CAIRO_FORMAT_RGB24) {
- /* Opaque image */
- for (pixel_loop=0; pixel_loop < pixel_count; pixel_loop++) {
- /* Core bitmaps always have a component order of rgba,
- * regardless of system endianness */
- r = pixels[4 * pixel_loop + 0];
- g = pixels[4 * pixel_loop + 1];
- b = pixels[4 * pixel_loop + 2];
- t = pixels[4 * pixel_loop + 3];
-
- /* Cairo surface is ARGB, written in native endian */
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- pixels[4 * pixel_loop + 0] = b;
- pixels[4 * pixel_loop + 1] = g;
- pixels[4 * pixel_loop + 2] = r;
- pixels[4 * pixel_loop + 3] = t;
-#else
- pixels[4 * pixel_loop + 0] = t;
- pixels[4 * pixel_loop + 1] = r;
- pixels[4 * pixel_loop + 2] = g;
- pixels[4 * pixel_loop + 3] = b;
-#endif
- }
- } else {
- /* Alpha image: pre-multiply alpha */
- for (pixel_loop=0; pixel_loop < pixel_count; pixel_loop++) {
- r = pixels[4 * pixel_loop + 0];
- g = pixels[4 * pixel_loop + 1];
- b = pixels[4 * pixel_loop + 2];
- t = pixels[4 * pixel_loop + 3];
-
- if (t != 0) {
- r = ((r * (t + 1)) >> 8) & 0xff;
- g = ((g * (t + 1)) >> 8) & 0xff;
- b = ((b * (t + 1)) >> 8) & 0xff;
- } else {
- r = g = b = 0;
- }
-
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- pixels[4 * pixel_loop + 0] = b;
- pixels[4 * pixel_loop + 1] = g;
- pixels[4 * pixel_loop + 2] = r;
- pixels[4 * pixel_loop + 3] = t;
-#else
- pixels[4 * pixel_loop + 0] = t;
- pixels[4 * pixel_loop + 1] = r;
- pixels[4 * pixel_loop + 2] = g;
- pixels[4 * pixel_loop + 3] = b;
-#endif
- }
- }
-
cairo_surface_mark_dirty(gbitmap->surface);
-
- gbitmap->converted = true;
}
/* exported interface documented in gtk/bitmap.h */
@@ -478,6 +231,10 @@ bitmap_render(struct bitmap *bitmap, struct hlcache_handle *content)
* aspect ratio of the required thumbnail. */
cheight = ((cwidth * dheight) + (dwidth / 2)) / dwidth;
+ /* At this point, we MUST have decided to render something non-zero sized */
+ assert(cwidth > 0);
+ assert(cheight > 0);
+
/* Create surface to render into */
surface = cairo_surface_create_similar(dsurface, CAIRO_CONTENT_COLOR_ALPHA, cwidth, cheight);
@@ -526,13 +283,10 @@ static struct gui_bitmap_table bitmap_table = {
.destroy = bitmap_destroy,
.set_opaque = bitmap_set_opaque,
.get_opaque = bitmap_get_opaque,
- .test_opaque = bitmap_test_opaque,
.get_buffer = bitmap_get_buffer,
.get_rowstride = bitmap_get_rowstride,
.get_width = nsgtk_bitmap_get_width,
.get_height = nsgtk_bitmap_get_height,
- .get_bpp = bitmap_get_bpp,
- .save = bitmap_save,
.modified = bitmap_modified,
.render = bitmap_render,
};
diff --git a/frontends/gtk/bitmap.h b/frontends/gtk/bitmap.h
index 0f46d19a8..80a0e7a3a 100644
--- a/frontends/gtk/bitmap.h
+++ b/frontends/gtk/bitmap.h
@@ -26,7 +26,7 @@ extern struct gui_bitmap_table *nsgtk_bitmap_table;
struct bitmap {
cairo_surface_t *surface; /* original cairo surface */
cairo_surface_t *scsurface; /* scaled surface */
- bool converted; /** set if the surface data has been converted */
+ bool opaque;
};
int nsgtk_bitmap_get_width(void *vbitmap);
diff --git a/frontends/gtk/compat.c b/frontends/gtk/compat.c
index 4c5524b0e..bd3f46ee5 100644
--- a/frontends/gtk/compat.c
+++ b/frontends/gtk/compat.c
@@ -170,18 +170,18 @@ void nsgtk_entry_set_icon_from_pixbuf(GtkWidget *entry,
/* exported interface documented in gtk/compat.h */
-void nsgtk_entry_set_icon_from_stock(GtkWidget *entry,
- GtkEntryIconPosition icon_pos,
- const gchar *id)
+void nsgtk_entry_set_icon_from_icon_name(GtkWidget *entry,
+ GtkEntryIconPosition icon_pos,
+ const gchar *id)
{
#ifdef NSGTK_USE_ICON_NAME
gtk_entry_set_icon_from_icon_name(GTK_ENTRY(entry), icon_pos, id);
#else
#if GTK_CHECK_VERSION(2,16,0)
- gtk_entry_set_icon_from_stock(GTK_ENTRY(entry), icon_pos, id);
+ gtk_entry_set_icon_from_icon_name(GTK_ENTRY(entry), icon_pos, id);
#else
- GtkImage *image = GTK_IMAGE(gtk_image_new_from_stock(id,
- GTK_ICON_SIZE_LARGE_TOOLBAR));
+ GtkImage *image;
+ image = GTK_IMAGE(gtk_image_new_from_stock(id, GTK_ICON_SIZE_LARGE_TOOLBAR));
if (image != NULL) {
sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(entry),
@@ -216,6 +216,17 @@ GtkWidget *nsgtk_button_new_from_stock(const gchar *stock_id)
}
/* exported interface documented in gtk/compat.h */
+void nsgtk_button_set_focus_on_click(GtkButton *button, gboolean focus_on_click)
+{
+#if GTK_CHECK_VERSION(3,20,0)
+ gtk_widget_set_focus_on_click(GTK_WIDGET(button), focus_on_click);
+#else
+ gtk_button_set_focus_on_click(button, focus_on_click);
+#endif
+}
+
+
+/* exported interface documented in gtk/compat.h */
gboolean nsgtk_stock_lookup(const gchar *stock_id, GtkStockItem *item)
{
#ifdef NSGTK_USE_ICON_NAME
@@ -234,12 +245,17 @@ void nsgtk_widget_override_background_color(GtkWidget *widget,
uint16_t b)
{
#if GTK_CHECK_VERSION(3,0,0)
+#if GTK_CHECK_VERSION(3,16,0)
+ /* do nothing - deprecated - must use css styling */
+ return;
+#else
GdkRGBA colour;
colour.alpha = (double)a / 0xffff;
colour.red = (double)r / 0xffff;
colour.green = (double)g / 0xffff;
colour.blue = (double)b / 0xffff;
gtk_widget_override_background_color(widget, state, &colour);
+#endif
#else
GdkColor colour;
colour.pixel = a;
@@ -403,15 +419,25 @@ GtkWidget *nsgtk_dialog_get_content_area(GtkDialog *dialog)
#endif
}
+#if GTK_CHECK_VERSION(3,22,0)
+#include "gtk/scaffolding.h"
+#endif
+
gboolean nsgtk_show_uri(GdkScreen *screen,
const gchar *uri,
guint32 timestamp,
GError **error)
{
#if GTK_CHECK_VERSION(2,14,0)
+#if GTK_CHECK_VERSION(3,22,0)
+ GtkWindow *parent;
+ parent = nsgtk_scaffolding_window(nsgtk_current_scaffolding());
+ return gtk_show_uri_on_window(parent, uri, timestamp,error);
+#else
return gtk_show_uri(screen, uri, timestamp, error);
+#endif
#else
- return FALSE; /* FIXME */
+ return FALSE; /** \todo add uri opening for before gtk 2.14 */
#endif
}
@@ -532,6 +558,17 @@ void nsgtk_image_menu_item_set_image(GtkWidget *image_menu_item, GtkWidget *imag
}
/* exported interface documented in gtk/compat.h */
+void nsgtk_menu_popup_at_pointer(GtkMenu *menu, const GdkEvent *trigger_event)
+{
+#if GTK_CHECK_VERSION(3,22,0)
+ gtk_menu_popup_at_pointer(menu, trigger_event);
+#else
+ gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 0,
+ gtk_get_current_event_time());
+#endif
+}
+
+/* exported interface documented in gtk/compat.h */
gboolean nsgtk_icon_size_lookup_for_settings(GtkSettings *settings,
GtkIconSize size,
gint *width,
@@ -598,7 +635,9 @@ void nsgtk_widget_set_margins(GtkWidget *widget, gint hmargin, gint vmargin)
gtk_widget_set_margin_top(widget, vmargin);
gtk_widget_set_margin_bottom(widget, vmargin);
#else
- gtk_misc_set_padding(GTK_MISC(widget), hmargin, vmargin);
+ if (GTK_IS_MISC(widget)) {
+ gtk_misc_set_padding(GTK_MISC(widget), hmargin, vmargin);
+ }
#endif
}
diff --git a/frontends/gtk/compat.h b/frontends/gtk/compat.h
index 9554b0cba..3b2f55094 100644
--- a/frontends/gtk/compat.h
+++ b/frontends/gtk/compat.h
@@ -16,7 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Compatibility functions for older GTK versions (interface)
*/
@@ -40,9 +41,6 @@
#define NSGTK_STOCK_CANCEL "_Cancel"
#define NSGTK_STOCK_CLEAR "edit-clear"
#define NSGTK_STOCK_CLOSE "window-close"
-#define NSGTK_STOCK_FIND "edit-find"
-#define NSGTK_STOCK_GO_BACK "go-previous"
-#define NSGTK_STOCK_GO_FORWARD "go-next"
#define NSGTK_STOCK_HOME "go-home"
#define NSGTK_STOCK_INFO "dialog-information"
#define NSGTK_STOCK_REFRESH "view-refresh"
@@ -51,14 +49,12 @@
#define NSGTK_STOCK_STOP "process-stop"
#define NSGTK_STOCK_OK "_OK"
#define NSGTK_STOCK_OPEN "_Open"
+#define NSGTK_STOCK_OPEN_MENU "open-menu"
#else
#define NSGTK_STOCK_ADD GTK_STOCK_ADD
#define NSGTK_STOCK_CANCEL GTK_STOCK_CANCEL
#define NSGTK_STOCK_CLEAR GTK_STOCK_CLEAR
#define NSGTK_STOCK_CLOSE GTK_STOCK_CLOSE
-#define NSGTK_STOCK_FIND GTK_STOCK_FIND
-#define NSGTK_STOCK_GO_BACK GTK_STOCK_GO_BACK
-#define NSGTK_STOCK_GO_FORWARD GTK_STOCK_GO_FORWARD
#define NSGTK_STOCK_HOME GTK_STOCK_HOME
#define NSGTK_STOCK_INFO GTK_STOCK_INFO
#define NSGTK_STOCK_REFRESH GTK_STOCK_REFRESH
@@ -67,6 +63,7 @@
#define NSGTK_STOCK_STOP GTK_STOCK_STOP
#define NSGTK_STOCK_OK GTK_STOCK_OK
#define NSGTK_STOCK_OPEN GTK_STOCK_OPEN
+#define NSGTK_STOCK_OPEN_MENU GTK_STOCK_JUSTIFY_FILL
#endif
/* widget alignment only available since 3.0 */
@@ -80,6 +77,12 @@ typedef enum {
} GtkAlign;
#endif
+/* value init since gtk 2.30 */
+#ifndef G_VALUE_INIT
+#define G_VALUE_INIT { 0, { { 0 } } }
+#endif
+
+
/**
* Set the alignment of a widget.
*
@@ -153,6 +156,9 @@ GtkStateType nsgtk_widget_get_state(GtkWidget *widget);
typedef GtkStateType GtkStateFlags;
typedef GtkStyle GtkStyleContext;
+/* gtk 3 changed the enum name for the state flags */
+#define GTK_STATE_FLAG_NORMAL GTK_STATE_NORMAL
+
#if GTK_CHECK_VERSION(2,22,0)
enum {
GTK_IN_DESTRUCTION = 1 << 0,
@@ -167,16 +173,16 @@ enum {
/**
- * Sets the icon shown in the entry at the specified position from a
- * stock image.
+ * Sets the icon shown in the entry at the specified position from an
+ * icon name.
*
- * Compatability interface for original deprecated in GTK 3.10
+ * Compatability interface for original introduced in 2.16
*
* \param entry The entry widget to set the icon on.
* \param icon_pos The position of the icon.
* \param stock_id the name of the stock item.
*/
-void nsgtk_entry_set_icon_from_stock(GtkWidget *entry, GtkEntryIconPosition icon_pos, const gchar *stock_id);
+void nsgtk_entry_set_icon_from_icon_name(GtkWidget *entry, GtkEntryIconPosition icon_pos, const gchar *stock_id);
/**
* Creates a GtkImage displaying a stock icon.
@@ -209,6 +215,16 @@ GtkWidget *nsgtk_button_new_from_stock(const gchar *stock_id);
*/
gboolean nsgtk_stock_lookup(const gchar *stock_id, GtkStockItem *item);
+/**
+ * Sets whether the button will grab focus when it is clicked with the mouse.
+ *
+ * Compatability interface for original deprecated in GTK 3.20
+ *
+ * \param button The button alter
+ * \param focus_on_click whether the button grabs focus when clicked with the mouse
+ */
+void nsgtk_button_set_focus_on_click(GtkButton *button, gboolean focus_on_click);
+
void nsgtk_window_set_opacity(GtkWindow *window, gdouble opacity);
void nsgtk_scrolled_window_add_with_viewport(GtkScrolledWindow *window, GtkWidget *child);
@@ -268,6 +284,15 @@ GtkWidget *nsgtk_image_menu_item_new_with_mnemonic(const gchar *label);
*/
void nsgtk_image_menu_item_set_image(GtkWidget *image_menu_item, GtkWidget *image);
+/**
+ * Displays menu and makes it available for selection
+ *
+ * Compatability interface for gtk_menu_popup deprecated in GTK 3.22.
+ *
+ * \param image_menu_item The image menu entry item.
+ * \param trigger_event the GdkEvent that initiated this request or NULL if it's the current event.
+ */
+void nsgtk_menu_popup_at_pointer(GtkMenu *menu, const GdkEvent *trigger_event);
/**
* Parses a resource file containing a GtkBuilder UI definition and
diff --git a/frontends/gtk/completion.c b/frontends/gtk/completion.c
index eea0a789f..585a9e511 100644
--- a/frontends/gtk/completion.c
+++ b/frontends/gtk/completion.c
@@ -21,7 +21,7 @@
* Implementation of url entry completion.
*/
-#include <gtk/gtk.h>
+#include <stdlib.h>
#include "utils/log.h"
#include "utils/messages.h"
@@ -31,13 +31,27 @@
#include "netsurf/browser_window.h"
#include "desktop/searchweb.h"
+#include "gtk/compat.h"
#include "gtk/warn.h"
#include "gtk/scaffolding.h"
+#include "gtk/toolbar_items.h"
#include "gtk/window.h"
#include "gtk/completion.h"
GtkListStore *nsgtk_completion_list;
+struct nsgtk_completion_ctx {
+ /**
+ * callback to obtain a browser window for navigation
+ */
+ struct browser_window *(*get_bw)(void *ctx);
+
+ /**
+ * context passed to get_bw function
+ */
+ void *get_bw_ctx;
+};
+
/**
* completion row matcher
*/
@@ -51,7 +65,6 @@ static gboolean nsgtk_completion_match(GtkEntryCompletion *completion,
* are in the list should be shown.
*/
return TRUE;
-
}
@@ -78,14 +91,17 @@ static gboolean
nsgtk_completion_match_select(GtkEntryCompletion *widget,
GtkTreeModel *model,
GtkTreeIter *iter,
- gpointer user_data)
+ gpointer data)
{
- GValue value = {0, };
- struct nsgtk_scaffolding *g = user_data;
- struct browser_window *bw = nsgtk_get_browser_window(nsgtk_scaffolding_top_level(g));
+ struct nsgtk_completion_ctx *cb_ctx;
+ GValue value = G_VALUE_INIT;
+ struct browser_window *bw;
nserror ret;
nsurl *url;
+ cb_ctx = data;
+ bw = cb_ctx->get_bw(cb_ctx->get_bw_ctx);
+
gtk_tree_model_get_value(model, iter, 0, &value);
ret = search_web_omni(g_value_get_string(&value),
@@ -128,11 +144,20 @@ gboolean nsgtk_completion_update(GtkEntry *entry)
}
/* exported interface documented in completion.h */
-GtkEntryCompletion *nsgtk_url_entry_completion_new(struct nsgtk_scaffolding *gs)
+nserror
+nsgtk_completion_connect_signals(GtkEntry *entry,
+ struct browser_window *(*get_bw)(void *ctx),
+ void *get_bw_ctx)
{
GtkEntryCompletion *completion;
+ struct nsgtk_completion_ctx *cb_ctx;
+
+ cb_ctx = calloc(1, sizeof(struct nsgtk_completion_ctx));
+ cb_ctx->get_bw = get_bw;
+ cb_ctx->get_bw_ctx = get_bw_ctx;
+
+ completion = gtk_entry_get_completion(entry);
- completion = gtk_entry_completion_new();
gtk_entry_completion_set_match_func(completion,
nsgtk_completion_match, NULL, NULL);
@@ -147,13 +172,15 @@ GtkEntryCompletion *nsgtk_url_entry_completion_new(struct nsgtk_scaffolding *gs)
gtk_entry_completion_set_popup_completion(completion, TRUE);
/* when selected callback */
- g_signal_connect(G_OBJECT(completion), "match-selected",
- G_CALLBACK(nsgtk_completion_match_select), gs);
+ g_signal_connect(G_OBJECT(completion),
+ "match-selected",
+ G_CALLBACK(nsgtk_completion_match_select),
+ cb_ctx);
g_object_set(G_OBJECT(completion),
- "popup-set-width", TRUE,
- "popup-single-match", TRUE,
- NULL);
+ "popup-set-width", TRUE,
+ "popup-single-match", TRUE,
+ NULL);
- return completion;
+ return NSERROR_OK;
}
diff --git a/frontends/gtk/completion.h b/frontends/gtk/completion.h
index 9a1db293d..a81f1301a 100644
--- a/frontends/gtk/completion.h
+++ b/frontends/gtk/completion.h
@@ -37,10 +37,11 @@ void nsgtk_completion_init(void);
gboolean nsgtk_completion_update(GtkEntry *entry);
/**
- * create a new entry completion on a scaffold.
- *
- * \param gs The scaffoliding which the url entry is in.
+ * connect signals on entry completion
*/
-GtkEntryCompletion *nsgtk_url_entry_completion_new(struct nsgtk_scaffolding *gs);
+nserror
+nsgtk_completion_connect_signals(GtkEntry *entry,
+ struct browser_window *(*get_bw)(void *ctx),
+ void *get_bw_ctx);
#endif
diff --git a/frontends/gtk/cookies.c b/frontends/gtk/cookies.c
index 1f7833cca..0df9719cb 100644
--- a/frontends/gtk/cookies.c
+++ b/frontends/gtk/cookies.c
@@ -98,6 +98,8 @@ MENUHANDLER(delete_selected)
MENUHANDLER(delete_all)
{
+ cookie_manager_keypress(NS_KEY_ESCAPE);
+ cookie_manager_keypress(NS_KEY_ESCAPE);
cookie_manager_keypress(NS_KEY_SELECT_ALL);
cookie_manager_keypress(NS_KEY_DELETE_LEFT);
return TRUE;
@@ -105,6 +107,8 @@ MENUHANDLER(delete_all)
MENUHANDLER(select_all)
{
+ cookie_manager_keypress(NS_KEY_ESCAPE);
+ cookie_manager_keypress(NS_KEY_ESCAPE);
cookie_manager_keypress(NS_KEY_SELECT_ALL);
return TRUE;
}
@@ -305,13 +309,14 @@ static nserror nsgtk_cookies_init(void)
/* exported function documented gtk/cookies.h */
-nserror nsgtk_cookies_present(void)
+nserror nsgtk_cookies_present(const char *search_term)
{
nserror res;
res = nsgtk_cookies_init();
if (res == NSERROR_OK) {
gtk_window_present(cookie_window->wnd);
+ res = cookie_manager_set_search_string(search_term);
}
return res;
}
diff --git a/frontends/gtk/cookies.h b/frontends/gtk/cookies.h
index c1a68b7f9..b8fc9aba2 100644
--- a/frontends/gtk/cookies.h
+++ b/frontends/gtk/cookies.h
@@ -28,7 +28,7 @@
*
* \return NSERROR_OK on success else appropriate error code on faliure.
*/
-nserror nsgtk_cookies_present(void);
+nserror nsgtk_cookies_present(const char *search_term);
/**
* Free any resources allocated for the cookie window.
diff --git a/frontends/gtk/corewindow.c b/frontends/gtk/corewindow.c
index 6ca5d228f..baa4cf155 100644
--- a/frontends/gtk/corewindow.c
+++ b/frontends/gtk/corewindow.c
@@ -87,6 +87,7 @@ static browser_mouse_state nsgtk_cw_gdkbutton_to_nsstate(GdkEventButton *event)
}
if (event->state & GDK_MOD1_MASK) {
+ /* usually alt */
ms |= BROWSER_MOUSE_MOD_3;
}
@@ -224,6 +225,10 @@ nsgtk_cw_motion_notify_event(GtkWidget *widget,
struct nsgtk_corewindow_mouse *mouse = &nsgtk_cw->mouse_state;
if (mouse->pressed == false) {
+ nsgtk_cw->mouse(nsgtk_cw,
+ BROWSER_MOUSE_HOVER,
+ event->x,
+ event->y);
return TRUE;
}
@@ -304,7 +309,7 @@ nsgtk_cw_motion_notify_event(GtkWidget *widget,
*/
static nserror nsgtk_cw_key(struct nsgtk_corewindow *nsgtk_cw, uint32_t nskey)
{
- double value;
+ double value = 0;
GtkAdjustment *vscroll;
GtkAdjustment *hscroll;
GtkAdjustment *scroll = NULL;
@@ -588,13 +593,15 @@ nsgtk_cw_invalidate_area(struct core_window *cw, const struct rect *rect)
* \param width New widget width.
* \param height New widget height.
*/
-static void
+static nserror
nsgtk_cw_update_size(struct core_window *cw, int width, int height)
{
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
gtk_widget_set_size_request(GTK_WIDGET(nsgtk_cw->drawing_area),
width, height);
+
+ return NSERROR_OK;
}
@@ -604,30 +611,56 @@ nsgtk_cw_update_size(struct core_window *cw, int width, int height)
* \param cw core window handle.
* \param r rectangle that needs scrolling.
*/
-static void
-nsgtk_cw_scroll_visible(struct core_window *cw, const struct rect *r)
+static nserror
+nsgtk_cw_set_scroll(struct core_window *cw, int x, int y)
{
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
- int y = 0, height = 0, y0, y1;
- gdouble page;
- GtkAdjustment *vadj;
- vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
+ if (nsgtk_cw->scrolled != NULL) {
+ GtkAdjustment *vadj;
+ GtkAdjustment *hadj;
+
+ vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
+ hadj = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
+
+ assert(vadj != NULL);
+ assert(hadj != NULL);
+
+ gtk_adjustment_set_value(vadj, y);
+ gtk_adjustment_set_value(hadj, x);
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * scroll window core window callback
+ *
+ * \param cw core window handle.
+ * \param r rectangle that needs scrolling.
+ */
+static nserror
+nsgtk_cw_get_scroll(const struct core_window *cw, int *x, int *y)
+{
+ struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
- assert(vadj);
+ if (nsgtk_cw->scrolled != NULL) {
+ GtkAdjustment *vadj;
+ GtkAdjustment *hadj;
- g_object_get(vadj, "page-size", &page, NULL);
+ vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
+ hadj = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
- y0 = (int)(gtk_adjustment_get_value(vadj));
- y1 = y0 + page;
+ assert(vadj != NULL);
+ assert(hadj != NULL);
- if ((y >= y0) && (y + height <= y1))
- return;
- if (y + height > y1)
- y0 = y0 + (y + height - y1);
- if (y < y0)
- y0 = y;
- gtk_adjustment_set_value(vadj, y0);
+ *y = (int)(gtk_adjustment_get_value(vadj));
+ *x = (int)(gtk_adjustment_get_value(hadj));
+ } else {
+ *x = 0;
+ *y = 0;
+ }
+ return NSERROR_OK;
}
@@ -638,21 +671,31 @@ nsgtk_cw_scroll_visible(struct core_window *cw, const struct rect *r)
* \param[out] width to be set to viewport width in px
* \param[out] height to be set to viewport height in px
*/
-static void
-nsgtk_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
+static nserror
+nsgtk_cw_get_window_dimensions(const struct core_window *cw,
+ int *width, int *height)
{
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
- GtkAdjustment *vadj;
- GtkAdjustment *hadj;
- gdouble page;
-
- hadj = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
- g_object_get(hadj, "page-size", &page, NULL);
- *width = page;
-
- vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
- g_object_get(vadj, "page-size", &page, NULL);
- *height = page;
+ if (nsgtk_cw->scrolled != NULL) {
+ GtkAdjustment *vadj;
+ GtkAdjustment *hadj;
+ gdouble page;
+
+ hadj = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
+ g_object_get(hadj, "page-size", &page, NULL);
+ *width = page;
+
+ vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
+ g_object_get(vadj, "page-size", &page, NULL);
+ *height = page;
+ } else {
+ GtkAllocation allocation;
+ gtk_widget_get_allocation(GTK_WIDGET(nsgtk_cw->drawing_area),
+ &allocation);
+ *width = allocation.width;
+ *height = allocation.height;
+ }
+ return NSERROR_OK;
}
@@ -662,11 +705,13 @@ nsgtk_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
* \param cw core window handle.
* \param ds The new drag status.
*/
-static void
+static nserror
nsgtk_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
{
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
nsgtk_cw->drag_status = ds;
+
+ return NSERROR_OK;
}
@@ -676,7 +721,8 @@ nsgtk_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
static struct core_window_callback_table nsgtk_cw_cb_table = {
.invalidate = nsgtk_cw_invalidate_area,
.update_size = nsgtk_cw_update_size,
- .scroll_visible = nsgtk_cw_scroll_visible,
+ .set_scroll = nsgtk_cw_set_scroll,
+ .get_scroll = nsgtk_cw_get_scroll,
.get_window_dimensions = nsgtk_cw_get_window_dimensions,
.drag_status = nsgtk_cw_drag_status
};
@@ -730,7 +776,7 @@ nserror nsgtk_corewindow_init(struct nsgtk_corewindow *nsgtk_cw)
nsgtk_widget_override_background_color(
GTK_WIDGET(nsgtk_cw->drawing_area),
- GTK_STATE_NORMAL,
+ GTK_STATE_FLAG_NORMAL,
0, 0xffff, 0xffff, 0xffff);
return NSERROR_OK;
diff --git a/frontends/gtk/download.c b/frontends/gtk/download.c
index d11036ea8..d1231634d 100644
--- a/frontends/gtk/download.c
+++ b/frontends/gtk/download.c
@@ -34,6 +34,7 @@
#include "gtk/warn.h"
#include "gtk/scaffolding.h"
+#include "gtk/toolbar_items.h"
#include "gtk/window.h"
#include "gtk/compat.h"
#include "gtk/resources.h"
@@ -64,12 +65,23 @@ typedef enum {
} nsgtk_download_status;
typedef enum {
- NSGTK_DOWNLOAD_PAUSE = 1 << 0,
+ NSGTK_DOWNLOAD_PAUSE = 1 << 0,
NSGTK_DOWNLOAD_RESUME = 1 << 1,
- NSGTK_DOWNLOAD_CANCEL = 1 << 2,
- NSGTK_DOWNLOAD_CLEAR = 1 << 3
+ NSGTK_DOWNLOAD_CANCEL = 1 << 2,
+ NSGTK_DOWNLOAD_CLEAR = 1 << 3
} nsgtk_download_actions;
+static const gchar* status_messages[] = {
+ NULL,
+ "gtkWorking",
+ "gtkError",
+ "gtkComplete",
+ "gtkCanceled"
+};
+
+/**
+ * context for each download.
+ */
struct gui_download_window {
struct download_context *ctx;
nsgtk_download_actions sensitivity;
@@ -77,8 +89,8 @@ struct gui_download_window {
GString *name;
GString *time_left;
- gint size_total;
- gint size_downloaded;
+ unsigned long long int size_total;
+ unsigned long long int size_downloaded;
gint progress;
gfloat time_remaining;
gfloat start_time;
@@ -89,26 +101,37 @@ struct gui_download_window {
GError *error;
};
-typedef void (*nsgtk_download_selection_action)(struct gui_download_window *dl);
+typedef void (*nsgtk_download_selection_action)(struct gui_download_window *dl,
+ void *user_data);
-static GtkWindow *nsgtk_download_window, *nsgtk_download_parent;
-static GtkProgressBar *nsgtk_download_progress_bar;
+/**
+ * context for a nsgtk download window.
+ */
+struct download_window_ctx {
+ GtkWindow *window;
+ GtkWindow *parent;
+
+ GtkProgressBar *progress;
+
+ GtkTreeView *tree;
+ GtkListStore *store;
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
-static GtkTreeView *nsgtk_download_tree;
-static GtkListStore *nsgtk_download_store;
-static GtkTreeSelection *nsgtk_download_selection;
-static GtkTreeIter nsgtk_download_iter;
+ GTimer *timer;
+ GList *list;
+ GtkButton *pause;
+ GtkButton *clear;
+ GtkButton *cancel;
+ GtkButton *resume;
-static GTimer *nsgtk_downloads_timer;
-static GList *nsgtk_downloads_list;
-static GtkButton *nsgtk_download_button_pause;
-static GtkButton *nsgtk_download_button_clear;
-static GtkButton *nsgtk_download_button_cancel;
-static GtkButton *nsgtk_download_button_resume;
-static gint nsgtk_downloads_num_active;
-static const gchar* status_messages[] = { NULL, "gtkWorking", "gtkError",
- "gtkComplete", "gtkCanceled" };
+ gint num_active;
+};
+/**
+ * global instance of the download window
+ */
+static struct download_window_ctx dl_ctx;
static GtkTreeView* nsgtk_download_tree_view_new(GtkBuilder *gladeFile)
@@ -116,40 +139,66 @@ static GtkTreeView* nsgtk_download_tree_view_new(GtkBuilder *gladeFile)
GtkTreeView *treeview;
GtkCellRenderer *renderer;
- treeview = GTK_TREE_VIEW(gtk_builder_get_object(gladeFile, "treeDownloads"));
+ treeview = GTK_TREE_VIEW(gtk_builder_get_object(gladeFile,
+ "treeDownloads"));
/* Progress column */
renderer = gtk_cell_renderer_progress_new();
- gtk_tree_view_insert_column_with_attributes (treeview, -1,
- messages_get("gtkProgress"), renderer, "value",
- NSGTK_DOWNLOAD_PROGRESS, "pulse", NSGTK_DOWNLOAD_PULSE,
- "text", NSGTK_DOWNLOAD_STATUS, NULL);
+ gtk_tree_view_insert_column_with_attributes(treeview,
+ -1,
+ messages_get("gtkProgress"),
+ renderer,
+ "value",
+ NSGTK_DOWNLOAD_PROGRESS,
+ "pulse",
+ NSGTK_DOWNLOAD_PULSE,
+ "text",
+ NSGTK_DOWNLOAD_STATUS,
+ NULL);
/* Information column */
renderer = gtk_cell_renderer_text_new();
- g_object_set(G_OBJECT(renderer), "wrap-mode", PANGO_WRAP_WORD_CHAR,
- "wrap-width", 300, NULL);
- gtk_tree_view_insert_column_with_attributes (treeview, -1,
- messages_get("gtkDetails"), renderer, "text",
- NSGTK_DOWNLOAD_INFO, NULL);
- gtk_tree_view_column_set_expand(gtk_tree_view_get_column(treeview,
- NSGTK_DOWNLOAD_INFO), TRUE);
+ g_object_set(G_OBJECT(renderer),
+ "wrap-mode",
+ PANGO_WRAP_WORD_CHAR,
+ "wrap-width",
+ 300,
+ NULL);
+ gtk_tree_view_insert_column_with_attributes(treeview,
+ -1,
+ messages_get("gtkDetails"),
+ renderer,
+ "text",
+ NSGTK_DOWNLOAD_INFO,
+ NULL);
+ gtk_tree_view_column_set_expand(
+ gtk_tree_view_get_column(treeview,
+ NSGTK_DOWNLOAD_INFO), TRUE);
/* Time remaining column */
renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes (treeview, -1,
- messages_get("gtkRemaining"), renderer, "text",
- NSGTK_DOWNLOAD_REMAINING, NULL);
+ gtk_tree_view_insert_column_with_attributes(treeview,
+ -1,
+ messages_get("gtkRemaining"),
+ renderer,
+ "text",
+ NSGTK_DOWNLOAD_REMAINING,
+ NULL);
/* Speed column */
renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes (treeview, -1,
- messages_get("gtkSpeed"), renderer, "text",
- NSGTK_DOWNLOAD_SPEED, NULL);
+ gtk_tree_view_insert_column_with_attributes(treeview,
+ -1,
+ messages_get("gtkSpeed"),
+ renderer,
+ "text",
+ NSGTK_DOWNLOAD_SPEED,
+ NULL);
return treeview;
}
+
static gint
nsgtk_download_sort(GtkTreeModel *model,
GtkTreeIter *a,
@@ -164,43 +213,52 @@ nsgtk_download_sort(GtkTreeModel *model,
return dl1->status - dl2->status;
}
+
static void
nsgtk_download_sensitivity_update_buttons(nsgtk_download_actions sensitivity)
{
/* Glade seems to pack the buttons in an arbitrary order */
enum { PAUSE_BUTTON, CLEAR_BUTTON, CANCEL_BUTTON, RESUME_BUTTON };
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_download_button_pause),
+ gtk_widget_set_sensitive(GTK_WIDGET(dl_ctx.pause),
sensitivity & NSGTK_DOWNLOAD_PAUSE);
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_download_button_clear),
+ gtk_widget_set_sensitive(GTK_WIDGET(dl_ctx.clear),
sensitivity & NSGTK_DOWNLOAD_CLEAR);
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_download_button_cancel),
+ gtk_widget_set_sensitive(GTK_WIDGET(dl_ctx.cancel),
sensitivity & NSGTK_DOWNLOAD_CANCEL);
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_download_button_resume),
+ gtk_widget_set_sensitive(GTK_WIDGET(dl_ctx.resume),
sensitivity & NSGTK_DOWNLOAD_RESUME);
}
+
static void nsgtk_download_sensitivity_evaluate(GtkTreeSelection *selection)
{
GtkTreeIter iter;
GList *rows;
- gboolean selected = gtk_tree_selection_count_selected_rows(selection);
- GtkTreeModel *model = GTK_TREE_MODEL(nsgtk_download_store);
+ gboolean selected;
+ GtkTreeModel *model;
nsgtk_download_actions sensitivity = 0;
struct gui_download_window *dl;
+ model = GTK_TREE_MODEL(dl_ctx.store);
+
+ selected = gtk_tree_selection_count_selected_rows(selection);
if (selected) {
rows = gtk_tree_selection_get_selected_rows(selection, &model);
while (rows != NULL) {
- gtk_tree_model_get_iter(model, &iter,
+ gtk_tree_model_get_iter(model,
+ &iter,
(GtkTreePath*)rows->data);
- gtk_tree_model_get(model, &iter, NSGTK_DOWNLOAD,
- &dl, -1);
+ gtk_tree_model_get(model,
+ &iter,
+ NSGTK_DOWNLOAD,
+ &dl,
+ -1);
sensitivity |= dl->sensitivity;
rows = rows->next;
}
} else {
- rows = nsgtk_downloads_list;
+ rows = dl_ctx.list;
while (rows != NULL) {
dl = rows->data;
sensitivity |= (dl->sensitivity & NSGTK_DOWNLOAD_CLEAR);
@@ -208,83 +266,121 @@ static void nsgtk_download_sensitivity_evaluate(GtkTreeSelection *selection)
}
}
-
nsgtk_download_sensitivity_update_buttons(sensitivity);
}
+
+/**
+ * Wrapper to GFunc-ify gtk_tree_path_free for g_list_foreach.
+ */
+static void
+nsgtk_download_gfunc__gtk_tree_path_free(gpointer data, gpointer user_data)
+{
+ gtk_tree_path_free(data);
+}
+
+
+/**
+ * Wrapper to GFunc-ify g_free for g_list_foreach.
+ */
+static void
+nsgtk_download_gfunc__g_free(gpointer data, gpointer user_data)
+{
+ g_free(data);
+}
+
+
static void nsgtk_download_do(nsgtk_download_selection_action action)
{
GList *rows, *dls = NULL;
- GtkTreeModel *model = GTK_TREE_MODEL(nsgtk_download_store);
- gboolean selection_exists = gtk_tree_selection_count_selected_rows(
- nsgtk_download_selection);
+ GtkTreeModel *model;
+
+ if (gtk_tree_selection_count_selected_rows(dl_ctx.selection)) {
+ model = GTK_TREE_MODEL(dl_ctx.store);
- if (selection_exists) {
- rows = gtk_tree_selection_get_selected_rows(
- nsgtk_download_selection, &model);
+ rows = gtk_tree_selection_get_selected_rows(dl_ctx.selection,
+ &model);
while (rows != NULL) {
struct gui_download_window *dl;
- gtk_tree_model_get_iter(GTK_TREE_MODEL(
- nsgtk_download_store),
- &nsgtk_download_iter,
+
+ gtk_tree_model_get_iter(GTK_TREE_MODEL(dl_ctx.store),
+ &dl_ctx.iter,
(GtkTreePath*)rows->data);
- gtk_tree_model_get(GTK_TREE_MODEL(nsgtk_download_store),
- &nsgtk_download_iter, NSGTK_DOWNLOAD,
- &dl, -1);
+
+ gtk_tree_model_get(GTK_TREE_MODEL(dl_ctx.store),
+ &dl_ctx.iter,
+ NSGTK_DOWNLOAD,
+ &dl,
+ -1);
+
dls = g_list_prepend(dls, dl);
rows = rows->next;
}
- g_list_foreach(rows, (GFunc)gtk_tree_path_free, NULL);
- g_list_foreach(rows, (GFunc)g_free, NULL);
+ g_list_foreach(rows,
+ nsgtk_download_gfunc__gtk_tree_path_free,
+ NULL);
+ g_list_foreach(rows,
+ nsgtk_download_gfunc__g_free,
+ NULL);
g_list_free(rows);
- } else
- dls = g_list_copy(nsgtk_downloads_list);
+ } else {
+ dls = g_list_copy(dl_ctx.list);
+ }
g_list_foreach(dls, (GFunc)action, NULL);
g_list_free(dls);
}
+
static gchar* nsgtk_download_info_to_string(struct gui_download_window *dl)
{
- gchar *size_info = g_strdup_printf(messages_get("gtkSizeInfo"),
- human_friendly_bytesize(dl->size_downloaded),
- dl->size_total == 0 ? messages_get("gtkUnknownSize") :
- human_friendly_bytesize(dl->size_total));
-
+ gchar *size_info;
gchar *r;
- if (dl->status != NSGTK_DOWNLOAD_ERROR)
+ size_info = g_strdup_printf(messages_get("gtkSizeInfo"),
+ human_friendly_bytesize(dl->size_downloaded),
+ dl->size_total == 0 ?
+ messages_get("gtkUnknownSize") :
+ human_friendly_bytesize(dl->size_total));
+
+ if (dl->status != NSGTK_DOWNLOAD_ERROR) {
r = g_strdup_printf("%s\n%s", dl->name->str, size_info);
- else
- r = g_strdup_printf("%s\n%s", dl->name->str,
- dl->error->message);
+ } else {
+ r = g_strdup_printf("%s\n%s", dl->name->str, dl->error->message);
+ }
g_free(size_info);
return r;
}
+
static gchar* nsgtk_download_time_to_string(gint seconds)
{
gint hours, minutes;
- if (seconds < 0)
+ if (seconds < 0) {
return g_strdup("-");
+ }
hours = seconds / 3600;
seconds -= hours * 3600;
minutes = seconds / 60;
seconds -= minutes * 60;
- if (hours > 0)
- return g_strdup_printf("%u:%02u:%02u", hours, minutes,
+ if (hours > 0) {
+ return g_strdup_printf("%u:%02u:%02u",
+ hours,
+ minutes,
seconds);
- else
+ } else {
return g_strdup_printf("%u:%02u", minutes, seconds);
+ }
}
-static void nsgtk_download_store_update_item (struct gui_download_window *dl)
+
+static void nsgtk_download_store_update_item(struct gui_download_window *dl)
{
gchar *info = nsgtk_download_info_to_string(dl);
char *human = human_friendly_bytesize(dl->speed);
@@ -294,11 +390,11 @@ static void nsgtk_download_store_update_item (struct gui_download_window *dl)
gboolean pulse = dl->status == NSGTK_DOWNLOAD_WORKING;
/* Updates iter (which is needed to set and get data) with the dl row */
- gtk_tree_model_get_iter(GTK_TREE_MODEL(nsgtk_download_store),
- &nsgtk_download_iter,
+ gtk_tree_model_get_iter(GTK_TREE_MODEL(dl_ctx.store),
+ &dl_ctx.iter,
gtk_tree_row_reference_get_path(dl->row));
- gtk_list_store_set(nsgtk_download_store, &nsgtk_download_iter,
+ gtk_list_store_set(dl_ctx.store, &dl_ctx.iter,
NSGTK_DOWNLOAD_PULSE, pulse ? dl->progress : -1,
NSGTK_DOWNLOAD_PROGRESS, pulse ? 0 : dl->progress,
NSGTK_DOWNLOAD_INFO, info,
@@ -311,27 +407,32 @@ static void nsgtk_download_store_update_item (struct gui_download_window *dl)
g_free(time);
}
+
static gboolean nsgtk_download_update(gboolean force_update)
{
/* Be sure we need to update */
- if (!nsgtk_widget_get_visible(GTK_WIDGET(nsgtk_download_window)))
+ if (!nsgtk_widget_get_visible(GTK_WIDGET(dl_ctx.window))) {
return TRUE;
+ }
GList *list;
gchar *text;
gboolean update, pulse_mode = FALSE;
- gint downloaded = 0, total = 0, dls = 0;
- gfloat percent, elapsed = g_timer_elapsed(nsgtk_downloads_timer, NULL);
- nsgtk_downloads_num_active = 0;
+ unsigned long long int downloaded = 0;
+ unsigned long long int total = 0;
+ gint dls = 0;
+ gfloat percent, elapsed = g_timer_elapsed(dl_ctx.timer, NULL);
- for (list = nsgtk_downloads_list; list != NULL; list = list->next) {
+ dl_ctx.num_active = 0;
+
+ for (list = dl_ctx.list; list != NULL; list = list->next) {
struct gui_download_window *dl = list->data;
update = force_update;
switch (dl->status) {
case NSGTK_DOWNLOAD_WORKING:
pulse_mode = TRUE;
- /* Fall through */
+ fallthrough;
case NSGTK_DOWNLOAD_NONE:
dl->speed = dl->size_downloaded /
@@ -340,77 +441,86 @@ static gboolean nsgtk_download_update(gboolean force_update)
dl->time_remaining = (dl->size_total -
dl->size_downloaded)/
dl->speed;
- dl->progress = (gfloat)
- dl->size_downloaded /
- dl->size_total * 100;
- } else
+ dl->progress = (double)dl->size_downloaded /
+ (double)dl->size_total * 100;
+ } else {
dl->progress++;
+ }
- nsgtk_downloads_num_active++;
+ dl_ctx.num_active++;
update = TRUE;
- /* Fall through */
+ fallthrough;
case NSGTK_DOWNLOAD_COMPLETE:
downloaded += dl->size_downloaded;
total += dl->size_total;
dls++;
+ fallthrough;
default:
;//Do nothing
}
- if (update)
+ if (update) {
nsgtk_download_store_update_item(dl);
+ }
}
if (pulse_mode) {
text = g_strdup_printf(
- messages_get(nsgtk_downloads_num_active > 1 ?
+ messages_get(dl_ctx.num_active > 1 ?
"gtkProgressBarPulse" :
"gtkProgressBarPulseSingle"),
- nsgtk_downloads_num_active);
- gtk_progress_bar_pulse(nsgtk_download_progress_bar);
- gtk_progress_bar_set_text(nsgtk_download_progress_bar, text);
+ dl_ctx.num_active);
+ gtk_progress_bar_pulse(dl_ctx.progress);
+ gtk_progress_bar_set_text(dl_ctx.progress, text);
} else {
- percent = total != 0 ? (gfloat)downloaded / total : 0;
+ percent = total != 0 ? (double)downloaded / (double)total : 0;
text = g_strdup_printf(messages_get("gtkProgressBar"),
- floor(percent*100), dls);
- gtk_progress_bar_set_fraction(nsgtk_download_progress_bar,
+ floor(percent * 100), dls);
+ gtk_progress_bar_set_fraction(dl_ctx.progress,
percent);
- gtk_progress_bar_set_text(nsgtk_download_progress_bar, text);
+ gtk_progress_bar_set_text(dl_ctx.progress, text);
}
g_free(text);
- if (nsgtk_downloads_num_active == 0)
+ if (dl_ctx.num_active == 0) {
return FALSE; /* Returning FALSE here cancels the g_timeout */
- else
+ } else {
return TRUE;
+ }
}
-static void nsgtk_download_store_clear_item(struct gui_download_window *dl)
+
+static void
+nsgtk_download_store_clear_item(struct gui_download_window *dl, void *user_data)
{
if (dl->sensitivity & NSGTK_DOWNLOAD_CLEAR) {
- nsgtk_downloads_list = g_list_remove(nsgtk_downloads_list, dl);
+ dl_ctx.list = g_list_remove(dl_ctx.list, dl);
- gtk_tree_model_get_iter(GTK_TREE_MODEL(nsgtk_download_store),
- &nsgtk_download_iter,
+ gtk_tree_model_get_iter(GTK_TREE_MODEL(dl_ctx.store),
+ &dl_ctx.iter,
gtk_tree_row_reference_get_path(dl->row));
- gtk_list_store_remove(nsgtk_download_store,
- &nsgtk_download_iter);
+ gtk_list_store_remove(dl_ctx.store,
+ &dl_ctx.iter);
download_context_destroy(dl->ctx);
g_string_free(dl->name, TRUE);
g_string_free(dl->time_left, TRUE);
g_free(dl);
- nsgtk_download_sensitivity_evaluate(nsgtk_download_selection);
+ nsgtk_download_sensitivity_evaluate(dl_ctx.selection);
nsgtk_download_update(FALSE);
}
}
-static void nsgtk_download_tree_view_row_activated(GtkTreeView *tree,
- GtkTreePath *path, GtkTreeViewColumn *column, gpointer data)
+
+static void
+nsgtk_download_tree_view_row_activated(GtkTreeView *tree,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ gpointer data)
{
GtkTreeModel *model;
GtkTreeIter iter;
@@ -423,29 +533,36 @@ static void nsgtk_download_tree_view_row_activated(GtkTreeView *tree,
}
}
-static void nsgtk_download_change_sensitivity(struct gui_download_window *dl,
- nsgtk_download_actions sensitivity)
+
+static void
+nsgtk_download_change_sensitivity(struct gui_download_window *dl,
+ nsgtk_download_actions sensitivity)
{
dl->sensitivity = sensitivity;
- nsgtk_download_sensitivity_evaluate(nsgtk_download_selection);
+ nsgtk_download_sensitivity_evaluate(dl_ctx.selection);
}
-static void nsgtk_download_change_status (
- struct gui_download_window *dl, nsgtk_download_status status)
+
+static void
+nsgtk_download_change_status(struct gui_download_window *dl,
+ nsgtk_download_status status)
{
dl->status = status;
if (status != NSGTK_DOWNLOAD_NONE) {
- gtk_tree_model_get_iter(GTK_TREE_MODEL(nsgtk_download_store),
- &nsgtk_download_iter,
+ gtk_tree_model_get_iter(GTK_TREE_MODEL(dl_ctx.store),
+ &dl_ctx.iter,
gtk_tree_row_reference_get_path(dl->row));
- gtk_list_store_set(nsgtk_download_store, &nsgtk_download_iter,
+ gtk_list_store_set(dl_ctx.store, &dl_ctx.iter,
NSGTK_DOWNLOAD_STATUS,
messages_get(status_messages[status]), -1);
}
}
-static void nsgtk_download_store_cancel_item (struct gui_download_window *dl)
+
+static void
+nsgtk_download_store_cancel_item(struct gui_download_window *dl,
+ void *user_data)
{
if (dl->sensitivity & NSGTK_DOWNLOAD_CANCEL) {
dl->speed = 0;
@@ -463,148 +580,49 @@ static void nsgtk_download_store_cancel_item (struct gui_download_window *dl)
}
}
+
static gboolean nsgtk_download_hide(GtkWidget *window)
{
gtk_widget_hide(window);
return TRUE;
}
-/* exported interface documented in gtk/download.h */
-nserror nsgtk_download_init(void)
-{
- GtkBuilder* builder;
- nserror res;
-
- res = nsgtk_builder_new_from_resname("downloads", &builder);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Download UI builder init failed");
- return res;
- }
-
- gtk_builder_connect_signals(builder, NULL);
-
- nsgtk_download_button_pause = GTK_BUTTON(gtk_builder_get_object(builder, "buttonPause"));
- nsgtk_download_button_clear = GTK_BUTTON(gtk_builder_get_object(builder, "buttonClear"));
- nsgtk_download_button_cancel = GTK_BUTTON(gtk_builder_get_object(builder, "buttonCancel"));
- nsgtk_download_button_resume = GTK_BUTTON(gtk_builder_get_object(builder, "buttonPlay"));
-
- nsgtk_download_progress_bar = GTK_PROGRESS_BAR(gtk_builder_get_object(builder, "progressBar"));
- nsgtk_download_window = GTK_WINDOW(gtk_builder_get_object(builder, "wndDownloads"));
- nsgtk_download_parent = NULL;
-
- gtk_window_set_transient_for(GTK_WINDOW(nsgtk_download_window),
- nsgtk_download_parent);
- gtk_window_set_destroy_with_parent(GTK_WINDOW(nsgtk_download_window),
- FALSE);
-
- nsgtk_downloads_timer = g_timer_new();
-
- nsgtk_download_tree = nsgtk_download_tree_view_new(builder);
-
- nsgtk_download_store = gtk_list_store_new(NSGTK_DOWNLOAD_N_COLUMNS,
- G_TYPE_INT, /* % complete */
- G_TYPE_STRING, /* Description */
- G_TYPE_STRING, /* Time remaining */
- G_TYPE_STRING, /* Speed */
- G_TYPE_INT, /* Pulse */
- G_TYPE_STRING, /* Status */
- G_TYPE_POINTER /* Download structure */
- );
-
-
- gtk_tree_view_set_model(nsgtk_download_tree,
- GTK_TREE_MODEL(nsgtk_download_store));
-
- gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(nsgtk_download_store),
- NSGTK_DOWNLOAD_STATUS,
- (GtkTreeIterCompareFunc) nsgtk_download_sort, NULL, NULL);
- gtk_tree_sortable_set_sort_column_id(
- GTK_TREE_SORTABLE(nsgtk_download_store),
- NSGTK_DOWNLOAD_STATUS, GTK_SORT_ASCENDING);
-
- g_object_unref(nsgtk_download_store);
-
- nsgtk_download_selection =
- gtk_tree_view_get_selection(nsgtk_download_tree);
- gtk_tree_selection_set_mode(nsgtk_download_selection,
- GTK_SELECTION_MULTIPLE);
-
- g_signal_connect(G_OBJECT(nsgtk_download_selection), "changed",
- G_CALLBACK(nsgtk_download_sensitivity_evaluate), NULL);
- g_signal_connect(nsgtk_download_tree, "row-activated",
- G_CALLBACK(nsgtk_download_tree_view_row_activated),
- NULL);
- g_signal_connect_swapped(gtk_builder_get_object(builder, "buttonClear"),
- "clicked",
- G_CALLBACK(nsgtk_download_do),
- nsgtk_download_store_clear_item);
- g_signal_connect_swapped(gtk_builder_get_object(builder, "buttonCancel"),
- "clicked",
- G_CALLBACK(nsgtk_download_do),
- nsgtk_download_store_cancel_item);
- g_signal_connect(G_OBJECT(nsgtk_download_window), "delete-event",
- G_CALLBACK(nsgtk_download_hide), NULL);
-
- return NSERROR_OK;
-}
-
-void nsgtk_download_destroy ()
-{
- nsgtk_download_do(nsgtk_download_store_cancel_item);
-}
-
-bool nsgtk_check_for_downloads (GtkWindow *parent)
-{
- if (nsgtk_downloads_num_active != 0) {
- GtkWidget *dialog;
- dialog = gtk_message_dialog_new_with_markup(parent,
- GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING,
- GTK_BUTTONS_NONE,
- "<big><b>%s</b></big>\n\n"
- "<small>%s</small>", messages_get("gtkQuit"),
- messages_get("gtkDownloadsRunning"));
- gtk_dialog_add_buttons(GTK_DIALOG(dialog), "gtk-cancel",
- GTK_RESPONSE_CANCEL, "gtk-quit",
- GTK_RESPONSE_CLOSE, NULL);
-
- gint response = gtk_dialog_run(GTK_DIALOG(dialog));
- gtk_widget_destroy(dialog);
-
- if (response == GTK_RESPONSE_CANCEL)
- return true;
- }
-
- return false;
-}
-
-void nsgtk_download_show(GtkWindow *parent)
-{
- gtk_window_set_transient_for(nsgtk_download_window,
- nsgtk_download_parent);
- gtk_window_present(nsgtk_download_window);
-}
-static gchar* nsgtk_download_dialog_show (const gchar *filename, const gchar *domain,
- const gchar *size)
+/**
+ * Prompt user for downloaded file name
+ *
+ * \param filename The original name of the file
+ * \param domain the domain the file is being downloaded from
+ * \param size The size of the file being downloaded
+ */
+static gchar*
+nsgtk_download_dialog_show(const gchar *filename,
+ const gchar *domain,
+ const gchar *size)
{
enum { GTK_RESPONSE_DOWNLOAD, GTK_RESPONSE_SAVE_AS };
GtkWidget *dialog;
char *destination = NULL;
- gchar *message = g_strdup(messages_get("gtkStartDownload"));
- gchar *info = g_strdup_printf(messages_get("gtkInfo"), filename,
- domain, size);
-
- dialog = gtk_message_dialog_new_with_markup(nsgtk_download_parent,
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
- "<span size=\"x-large\" weight=\"ultrabold\">%s</span>"
- "\n\n<small>%s</small>",
- message, info);
-
- gtk_dialog_add_buttons(GTK_DIALOG(dialog), NSGTK_STOCK_SAVE,
- GTK_RESPONSE_DOWNLOAD, NSGTK_STOCK_CANCEL,
- GTK_RESPONSE_CANCEL, NSGTK_STOCK_SAVE_AS,
- GTK_RESPONSE_SAVE_AS, NULL);
+ gchar *message;
+ gchar *info;
+
+ message = g_strdup(messages_get("gtkStartDownload"));
+ info = g_strdup_printf(messages_get("gtkInfo"), filename, domain, size);
+
+ dialog = gtk_message_dialog_new_with_markup(
+ dl_ctx.parent,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
+ "<span size=\"x-large\" weight=\"ultrabold\">%s</span>"
+ "\n\n<small>%s</small>",
+ message,
+ info);
+
+ gtk_dialog_add_buttons(GTK_DIALOG(dialog),
+ NSGTK_STOCK_SAVE, GTK_RESPONSE_DOWNLOAD,
+ NSGTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ NSGTK_STOCK_SAVE_AS, GTK_RESPONSE_SAVE_AS,
+ NULL);
gint result = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
@@ -613,13 +631,13 @@ static gchar* nsgtk_download_dialog_show (const gchar *filename, const gchar *do
switch (result) {
case GTK_RESPONSE_SAVE_AS: {
- dialog = gtk_file_chooser_dialog_new
- (messages_get("gtkSave"),
- nsgtk_download_parent,
- GTK_FILE_CHOOSER_ACTION_SAVE,
- NSGTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- NSGTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- NULL);
+ dialog = gtk_file_chooser_dialog_new(
+ messages_get("gtkSave"),
+ dl_ctx.parent,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ NSGTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ NSGTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+ NULL);
gtk_file_chooser_set_current_name
(GTK_FILE_CHOOSER(dialog), filename);
gtk_file_chooser_set_current_folder
@@ -649,30 +667,32 @@ static gchar* nsgtk_download_dialog_show (const gchar *filename, const gchar *do
* confirmation if needed */
if (g_file_test(destination, G_FILE_TEST_EXISTS) &&
nsoption_bool(request_overwrite)) {
- message = g_strdup_printf(messages_get(
- "gtkOverwrite"), filename);
- info = g_strdup_printf(messages_get(
- "gtkOverwriteInfo"),
+ GtkWidget *button;
+
+ message = g_strdup_printf(messages_get("gtkOverwrite"),
+ filename);
+ info = g_strdup_printf(messages_get("gtkOverwriteInfo"),
nsoption_charp(downloads_directory));
dialog = gtk_message_dialog_new_with_markup(
- nsgtk_download_parent,
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_CANCEL,
- "<b>%s</b>",message);
+ dl_ctx.parent,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_CANCEL,
+ "<b>%s</b>",
+ message);
gtk_message_dialog_format_secondary_markup(
- GTK_MESSAGE_DIALOG(dialog),
- "%s", info);
+ GTK_MESSAGE_DIALOG(dialog),
+ "%s",
+ info);
- GtkWidget *button = gtk_dialog_add_button(
- GTK_DIALOG(dialog),
- "_Replace",
- GTK_RESPONSE_DOWNLOAD);
+ button = gtk_dialog_add_button(GTK_DIALOG(dialog),
+ "_Replace",
+ GTK_RESPONSE_DOWNLOAD);
gtk_button_set_image(GTK_BUTTON(button),
nsgtk_image_new_from_stock(
- NSGTK_STOCK_SAVE,
- GTK_ICON_SIZE_BUTTON));
+ NSGTK_STOCK_SAVE,
+ GTK_ICON_SIZE_BUTTON));
gint result = gtk_dialog_run(GTK_DIALOG(dialog));
if (result == GTK_RESPONSE_CANCEL)
@@ -689,20 +709,24 @@ static gchar* nsgtk_download_dialog_show (const gchar *filename, const gchar *do
}
-static gboolean nsgtk_download_handle_error (GError *error)
+static gboolean nsgtk_download_handle_error(GError *error)
{
+ GtkWidget*dialog;
+ gchar *message;
+
if (error != NULL) {
- GtkWidget*dialog;
- gchar *message = g_strdup_printf(messages_get("gtkFileError"),
- error->message);
-
- dialog = gtk_message_dialog_new_with_markup
- (nsgtk_download_parent,
- GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
- GTK_BUTTONS_OK,
- "<big><b>%s</b></big>\n\n"
- "<small>%s</small>", messages_get("gtkFailed"),
- message);
+ message = g_strdup_printf(messages_get("gtkFileError"),
+ error->message);
+
+ dialog = gtk_message_dialog_new_with_markup(
+ dl_ctx.parent,
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ "<big><b>%s</b></big>\n\n"
+ "<small>%s</small>",
+ messages_get("gtkFailed"),
+ message);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
@@ -711,30 +735,53 @@ static gboolean nsgtk_download_handle_error (GError *error)
return FALSE;
}
-static void nsgtk_download_store_create_item (struct gui_download_window *dl)
+
+static void nsgtk_download_store_create_item(struct gui_download_window *dl)
{
nsgtk_download_store_update_item(dl);
/* The iter has already been updated to this row */
- gtk_list_store_set(nsgtk_download_store, &nsgtk_download_iter,
- NSGTK_DOWNLOAD, dl, -1);
+ gtk_list_store_set(dl_ctx.store,
+ &dl_ctx.iter,
+ NSGTK_DOWNLOAD,
+ dl,
+ -1);
}
+
+/**
+ * Wrapper to GSourceFunc-ify nsgtk_download_update.
+ */
+static gboolean
+nsgtk_download_gsourcefunc__nsgtk_download_update(gpointer user_data)
+{
+ return nsgtk_download_update(FALSE);
+}
+
+
+/**
+ * core callback on creating a new download
+ */
static struct gui_download_window *
gui_download_window_create(download_context *ctx, struct gui_window *gui)
{
- nsurl *url = download_context_get_url(ctx);
- unsigned long total_size = download_context_get_total_length(ctx);
+ nsurl *url;
+ unsigned long long int total_size;
gchar *domain;
gchar *destination;
- gboolean unknown_size = total_size == 0;
- const char *size = (total_size == 0 ?
- messages_get("gtkUnknownSize") :
- human_friendly_bytesize(total_size));
+ gboolean unknown_size;
+ struct gui_download_window *download;
+ const char *size;
+
+ url = download_context_get_url(ctx);
+ total_size = download_context_get_total_length(ctx);
+ unknown_size = total_size == 0;
+ size = (total_size == 0 ?
+ messages_get("gtkUnknownSize") :
+ human_friendly_bytesize(total_size));
- nsgtk_download_parent =
- nsgtk_scaffolding_window(nsgtk_get_scaffold(gui));
+ dl_ctx.parent = nsgtk_scaffolding_window(nsgtk_get_scaffold(gui));
- struct gui_download_window *download = malloc(sizeof *download);
+ download = malloc(sizeof *download);
if (download == NULL) {
return NULL;
}
@@ -761,12 +808,12 @@ gui_download_window_create(download_context *ctx, struct gui_window *gui)
/* Add the new row and store the reference to it (which keeps track of
* the tree changes) */
- gtk_list_store_prepend(nsgtk_download_store, &nsgtk_download_iter);
+ gtk_list_store_prepend(dl_ctx.store, &dl_ctx.iter);
download->row = gtk_tree_row_reference_new(
- GTK_TREE_MODEL(nsgtk_download_store),
- gtk_tree_model_get_path(
- GTK_TREE_MODEL(nsgtk_download_store),
- &nsgtk_download_iter));
+ GTK_TREE_MODEL(dl_ctx.store),
+ gtk_tree_model_get_path(
+ GTK_TREE_MODEL(dl_ctx.store),
+ &dl_ctx.iter));
download->ctx = ctx;
download->name = g_string_new(download_context_get_filename(ctx));
@@ -774,13 +821,14 @@ gui_download_window_create(download_context *ctx, struct gui_window *gui)
download->size_total = total_size;
download->size_downloaded = 0;
download->speed = 0;
- download->start_time = g_timer_elapsed(nsgtk_downloads_timer, NULL);
+ download->start_time = g_timer_elapsed(dl_ctx.timer, NULL);
download->time_remaining = -1;
download->status = NSGTK_DOWNLOAD_NONE;
download->progress = 0;
download->error = NULL;
- download->write =
- g_io_channel_new_file(destination, "w", &download->error);
+ download->write = g_io_channel_new_file(destination,
+ "w",
+ &download->error);
if (nsgtk_download_handle_error(download->error)) {
g_string_free(download->name, TRUE);
@@ -793,24 +841,32 @@ gui_download_window_create(download_context *ctx, struct gui_window *gui)
nsgtk_download_change_sensitivity(download, NSGTK_DOWNLOAD_CANCEL);
nsgtk_download_store_create_item(download);
- nsgtk_download_show(nsgtk_download_parent);
+ nsgtk_download_show(dl_ctx.parent);
- if (unknown_size)
+ if (unknown_size) {
nsgtk_download_change_status(download, NSGTK_DOWNLOAD_WORKING);
+ }
- if (nsgtk_downloads_num_active == 0) {
- g_timeout_add(UPDATE_RATE,
- (GSourceFunc) nsgtk_download_update, FALSE);
+ if (dl_ctx.num_active == 0) {
+ g_timeout_add(
+ UPDATE_RATE,
+ nsgtk_download_gsourcefunc__nsgtk_download_update,
+ NULL);
}
- nsgtk_downloads_list = g_list_prepend(nsgtk_downloads_list, download);
+ dl_ctx.list = g_list_prepend(dl_ctx.list, download);
return download;
}
-static nserror gui_download_window_data(struct gui_download_window *dw,
- const char *data, unsigned int size)
+/**
+ * core callback on receipt of data
+ */
+static nserror
+gui_download_window_data(struct gui_download_window *dw,
+ const char *data,
+ unsigned int size)
{
g_io_channel_write_chars(dw->write, data, size, NULL, &dw->error);
if (dw->error != NULL) {
@@ -822,7 +878,7 @@ static nserror gui_download_window_data(struct gui_download_window *dw,
nsgtk_download_update(TRUE);
- gtk_window_present(nsgtk_download_window);
+ gtk_window_present(dl_ctx.window);
return NSERROR_SAVE_FAILED;
}
@@ -832,12 +888,18 @@ static nserror gui_download_window_data(struct gui_download_window *dw,
}
-static void gui_download_window_error(struct gui_download_window *dw,
- const char *error_msg)
+/**
+ * core callback on error
+ */
+static void
+gui_download_window_error(struct gui_download_window *dw, const char *error_msg)
{
}
+/**
+ * core callback when core download is complete
+ */
static void gui_download_window_done(struct gui_download_window *dw)
{
g_io_channel_shutdown(dw->write, TRUE, &dw->error);
@@ -850,10 +912,11 @@ static void gui_download_window_done(struct gui_download_window *dw)
nsgtk_download_change_sensitivity(dw, NSGTK_DOWNLOAD_CLEAR);
nsgtk_download_change_status(dw, NSGTK_DOWNLOAD_COMPLETE);
- if (nsoption_bool(downloads_clear))
- nsgtk_download_store_clear_item(dw);
- else
+ if (nsoption_bool(downloads_clear)) {
+ nsgtk_download_store_clear_item(dw, NULL);
+ } else {
nsgtk_download_update(TRUE);
+ }
}
@@ -865,3 +928,146 @@ static struct gui_download_table download_table = {
};
struct gui_download_table *nsgtk_download_table = &download_table;
+
+
+/* exported interface documented in gtk/download.h */
+nserror nsgtk_download_init(void)
+{
+ GtkBuilder* builder;
+ nserror res;
+
+ res = nsgtk_builder_new_from_resname("downloads", &builder);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Download UI builder init failed");
+ return res;
+ }
+
+ gtk_builder_connect_signals(builder, NULL);
+
+ dl_ctx.pause = GTK_BUTTON(gtk_builder_get_object(builder,
+ "buttonPause"));
+ dl_ctx.clear = GTK_BUTTON(gtk_builder_get_object(builder,
+ "buttonClear"));
+ dl_ctx.cancel = GTK_BUTTON(gtk_builder_get_object(builder,
+ "buttonCancel"));
+ dl_ctx.resume = GTK_BUTTON(gtk_builder_get_object(builder,
+ "buttonPlay"));
+
+ dl_ctx.progress = GTK_PROGRESS_BAR(gtk_builder_get_object(builder,
+ "progressBar"));
+ dl_ctx.window = GTK_WINDOW(gtk_builder_get_object(builder,
+ "wndDownloads"));
+ dl_ctx.parent = NULL;
+
+ gtk_window_set_transient_for(GTK_WINDOW(dl_ctx.window),
+ dl_ctx.parent);
+ gtk_window_set_destroy_with_parent(GTK_WINDOW(dl_ctx.window),
+ FALSE);
+
+ dl_ctx.timer = g_timer_new();
+
+ dl_ctx.tree = nsgtk_download_tree_view_new(builder);
+
+ dl_ctx.store = gtk_list_store_new(NSGTK_DOWNLOAD_N_COLUMNS,
+ G_TYPE_INT, /* % complete */
+ G_TYPE_STRING, /* Description */
+ G_TYPE_STRING, /* Time remaining */
+ G_TYPE_STRING, /* Speed */
+ G_TYPE_INT, /* Pulse */
+ G_TYPE_STRING, /* Status */
+ G_TYPE_POINTER /* Download structure */
+ );
+
+
+ gtk_tree_view_set_model(dl_ctx.tree, GTK_TREE_MODEL(dl_ctx.store));
+
+ gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(dl_ctx.store),
+ NSGTK_DOWNLOAD_STATUS,
+ (GtkTreeIterCompareFunc)nsgtk_download_sort, NULL, NULL);
+ gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dl_ctx.store),
+ NSGTK_DOWNLOAD_STATUS,
+ GTK_SORT_ASCENDING);
+
+ g_object_unref(dl_ctx.store);
+
+ dl_ctx.selection = gtk_tree_view_get_selection(dl_ctx.tree);
+ gtk_tree_selection_set_mode(dl_ctx.selection, GTK_SELECTION_MULTIPLE);
+
+ g_signal_connect(G_OBJECT(dl_ctx.selection),
+ "changed",
+ G_CALLBACK(nsgtk_download_sensitivity_evaluate),
+ NULL);
+
+ g_signal_connect(dl_ctx.tree,
+ "row-activated",
+ G_CALLBACK(nsgtk_download_tree_view_row_activated),
+ NULL);
+
+ g_signal_connect_swapped(gtk_builder_get_object(builder, "buttonClear"),
+ "clicked",
+ G_CALLBACK(nsgtk_download_do),
+ nsgtk_download_store_clear_item);
+
+ g_signal_connect_swapped(gtk_builder_get_object(builder, "buttonCancel"),
+ "clicked",
+ G_CALLBACK(nsgtk_download_do),
+ nsgtk_download_store_cancel_item);
+
+ g_signal_connect(G_OBJECT(dl_ctx.window),
+ "delete-event",
+ G_CALLBACK(nsgtk_download_hide),
+ NULL);
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in gtk/download.h */
+void nsgtk_download_destroy(void)
+{
+ nsgtk_download_do(nsgtk_download_store_cancel_item);
+}
+
+
+/* exported interface documented in gtk/download.h */
+bool nsgtk_check_for_downloads(GtkWindow *parent)
+{
+ GtkWidget *dialog;
+ gint response;
+
+ if (dl_ctx.num_active == 0) {
+ return false;
+ }
+
+ dialog = gtk_message_dialog_new_with_markup(
+ parent,
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ "<big><b>%s</b></big>\n\n"
+ "<small>%s</small>",
+ messages_get("gtkQuit"),
+ messages_get("gtkDownloadsRunning"));
+
+ gtk_dialog_add_buttons(GTK_DIALOG(dialog),
+ "gtk-cancel", GTK_RESPONSE_CANCEL,
+ "gtk-quit", GTK_RESPONSE_CLOSE,
+ NULL);
+
+ response = gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+
+ if (response == GTK_RESPONSE_CANCEL) {
+ return true;
+ }
+
+ return false;
+}
+
+
+/* exported interface documented in gtk/download.h */
+void nsgtk_download_show(GtkWindow *parent)
+{
+ gtk_window_set_transient_for(dl_ctx.window, dl_ctx.parent);
+ gtk_window_present(dl_ctx.window);
+}
diff --git a/frontends/gtk/download.h b/frontends/gtk/download.h
index 0b1097655..c6dc187e7 100644
--- a/frontends/gtk/download.h
+++ b/frontends/gtk/download.h
@@ -19,12 +19,11 @@
#ifndef GTK_DOWNLOAD_H
#define GTK_DOWNLOAD_H
-#include <gtk/gtk.h>
-
/**
* download operation table for gtk
*/
-struct gui_download_table *nsgtk_download_table;
+extern struct gui_download_table *nsgtk_download_table;
+
/**
* Initialise download window ready for use.
@@ -33,9 +32,27 @@ struct gui_download_table *nsgtk_download_table;
*/
nserror nsgtk_download_init(void);
-void nsgtk_download_destroy (void);
+
+/**
+ * Destroy download window
+ */
+void nsgtk_download_destroy(void);
+
+
+/**
+ * Check with user if download is in progress they want to complete
+ *
+ * \param parent The parent window for the prompt dialog.
+ * \return true if the user wants to continue else false.
+ */
bool nsgtk_check_for_downloads(GtkWindow *parent);
+
+
+/**
+ * Show the download window
+ *
+ * \param parent The parent window to use for the shown window
+ */
void nsgtk_download_show(GtkWindow *parent);
-void nsgtk_download_add(gchar *url, gchar *destination);
#endif
diff --git a/frontends/gtk/fetch.c b/frontends/gtk/fetch.c
index b05c1bd95..d77073a63 100644
--- a/frontends/gtk/fetch.c
+++ b/frontends/gtk/fetch.c
@@ -75,6 +75,7 @@ void gtk_fetch_filetype_init(const char *mimefile)
hash_add(mime_hash, "html", "text/html");
hash_add(mime_hash, "jpg", "image/jpeg");
hash_add(mime_hash, "jpeg", "image/jpeg");
+ hash_add(mime_hash, "jxl", "image/jxl");
hash_add(mime_hash, "gif", "image/gif");
hash_add(mime_hash, "png", "image/png");
hash_add(mime_hash, "jng", "image/jng");
@@ -117,11 +118,9 @@ void gtk_fetch_filetype_init(const char *mimefile)
type = ptr;
- /* search for the first non-whitespace char or NUL or
+ /* search for the first whitespace char or NUL or
* NL */
- while (*ptr &&
- (!ascii_is_space(*ptr)) &&
- *ptr != '\n') {
+ while (*ptr && (!ascii_is_space(*ptr))) {
ptr++;
}
@@ -146,9 +145,7 @@ void gtk_fetch_filetype_init(const char *mimefile)
/* search for the first whitespace char or
* NUL or NL which is the end of the ext.
*/
- while (*ptr &&
- (!ascii_is_space(*ptr)) &&
- *ptr != '\n') {
+ while (*ptr && (!ascii_is_space(*ptr))) {
ptr++;
}
diff --git a/frontends/gtk/fetch.h b/frontends/gtk/fetch.h
index a095adbf9..9175ccdf2 100644
--- a/frontends/gtk/fetch.h
+++ b/frontends/gtk/fetch.h
@@ -19,7 +19,7 @@
#ifndef NETSURF_GTK_FETCH_H
#define NETSURF_GTK_FETCH_H
-struct gui_fetch_table *nsgtk_fetch_table;
+extern struct gui_fetch_table *nsgtk_fetch_table;
void gtk_fetch_filetype_init(const char *mimefile);
void gtk_fetch_filetype_fin(void);
diff --git a/frontends/gtk/gdk.c b/frontends/gtk/gdk.c
index fd82af5b2..fe9a0791c 100644
--- a/frontends/gtk/gdk.c
+++ b/frontends/gtk/gdk.c
@@ -33,7 +33,8 @@ convert_alpha(guchar *dest_data,
int x, y;
for (y = 0; y < height; y++) {
- guint32 *src = (guint32 *) src_data;
+ /* this cast is safe, the buffer is appropriately aligned */
+ guint32 *src = (void *) src_data;
for (x = 0; x < width; x++) {
guint alpha = src[x] >> 24;
@@ -72,7 +73,7 @@ nsgdk_pixbuf_get_from_surface(cairo_surface_t *surface, int scwidth, int scheigh
memset(gdk_pixbuf_get_pixels(pixbuf),
0xff,
- gdk_pixbuf_get_rowstride(pixbuf) * scheight);
+ gdk_pixbuf_get_rowstride(pixbuf) * (size_t)scheight);
/* scale cairo surface into new surface the target size */
cairo_surface_flush(surface); /* ensure source surface is ready */
diff --git a/frontends/gtk/global_history.c b/frontends/gtk/global_history.c
index f204168d0..33032e567 100644
--- a/frontends/gtk/global_history.c
+++ b/frontends/gtk/global_history.c
@@ -107,6 +107,8 @@ MENUHANDLER(delete_selected)
MENUHANDLER(delete_all)
{
+ global_history_keypress(NS_KEY_ESCAPE);
+ global_history_keypress(NS_KEY_ESCAPE);
global_history_keypress(NS_KEY_SELECT_ALL);
global_history_keypress(NS_KEY_DELETE_LEFT);
return TRUE;
@@ -114,12 +116,16 @@ MENUHANDLER(delete_all)
MENUHANDLER(select_all)
{
+ global_history_keypress(NS_KEY_ESCAPE);
+ global_history_keypress(NS_KEY_ESCAPE);
global_history_keypress(NS_KEY_SELECT_ALL);
return TRUE;
}
MENUHANDLER(clear_selection)
{
+ global_history_keypress(NS_KEY_ESCAPE);
+ global_history_keypress(NS_KEY_ESCAPE);
global_history_keypress(NS_KEY_CLEAR_SELECTION);
return TRUE;
}
diff --git a/frontends/gtk/gui.c b/frontends/gtk/gui.c
index 3163be16d..661176ded 100644
--- a/frontends/gtk/gui.c
+++ b/frontends/gtk/gui.c
@@ -41,13 +41,13 @@
#include "netsurf/keypress.h"
#include "netsurf/url_db.h"
#include "netsurf/cookie_db.h"
+#include "netsurf/browser.h"
#include "netsurf/browser_window.h"
-#include "netsurf/misc.h"
#include "netsurf/netsurf.h"
+#include "netsurf/bitmap.h"
#include "content/fetch.h"
#include "content/backing_store.h"
#include "desktop/save_complete.h"
-#include "desktop/save_pdf.h"
#include "desktop/searchweb.h"
#include "desktop/hotlist.h"
@@ -62,446 +62,34 @@
#include "gtk/global_history.h"
#include "gtk/hotlist.h"
#include "gtk/throbber.h"
+#include "gtk/toolbar_items.h"
#include "gtk/scaffolding.h"
#include "gtk/window.h"
#include "gtk/schedule.h"
#include "gtk/selection.h"
#include "gtk/search.h"
-#include "gtk/ssl_cert.h"
#include "gtk/bitmap.h"
+#include "gtk/misc.h"
#include "gtk/resources.h"
-#include "gtk/login.h"
#include "gtk/layout_pango.h"
#include "gtk/accelerator.h"
bool nsgtk_complete = false;
-char *nsgtk_config_home; /* exported global defined in gtk/gui.h */
+/* exported global defined in gtk/gui.h */
+char *nsgtk_config_home;
-GdkPixbuf *favicon_pixbuf; /** favicon default pixbuf */
-GdkPixbuf *win_default_icon_pixbuf; /** default window icon pixbuf */
-GdkPixbuf *arrow_down_pixbuf; /** arrow down pixbuf */
+/** favicon default pixbuf */
+GdkPixbuf *favicon_pixbuf;
-GtkBuilder *warning_builder;
-
-char **respaths; /** resource search path vector */
-
-/**
- * Cause an abnormal program termination.
- *
- * \note This never returns and is intended to terminate without any cleanup.
- *
- * \param error The message to display to the user.
- */
-static void die(const char * const error)
-{
- fprintf(stderr, "%s", error);
- exit(EXIT_FAILURE);
-}
-
-/**
- * Create an array of valid paths to search for resources.
- *
- * The idea is that all the complex path computation to find resources
- * is performed here, once, rather than every time a resource is
- * searched for.
- */
-static char **
-nsgtk_init_resource_path(const char *config_home)
-{
- char *resource_path;
- int resource_path_len;
- const gchar * const *langv;
- char **pathv; /* resource path string vector */
- char **respath; /* resource paths vector */
-
- if (config_home != NULL) {
- resource_path_len = snprintf(NULL, 0,
- "%s:${NETSURFRES}:%s",
- config_home,
- GTK_RESPATH);
- resource_path = malloc(resource_path_len + 1);
- if (resource_path == NULL) {
- return NULL;
- }
- snprintf(resource_path, resource_path_len + 1,
- "%s:${NETSURFRES}:%s",
- config_home,
- GTK_RESPATH);
- } else {
- resource_path_len = snprintf(NULL, 0,
- "${NETSURFRES}:%s",
- GTK_RESPATH);
- resource_path = malloc(resource_path_len + 1);
- if (resource_path == NULL) {
- return NULL;
- }
- snprintf(resource_path,
- resource_path_len + 1,
- "${NETSURFRES}:%s",
- GTK_RESPATH);
- }
-
- pathv = filepath_path_to_strvec(resource_path);
-
- langv = g_get_language_names();
-
- respath = filepath_generate(pathv, langv);
-
- filepath_free_strvec(pathv);
-
- free(resource_path);
-
- return respath;
-}
-
-
-/**
- * Set option defaults for gtk frontend.
- *
- * @param defaults The option table to update.
- * @return error status.
- */
-static nserror set_defaults(struct nsoption_s *defaults)
-{
- char *fname;
-
- /* cookie file default */
- fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Cookies");
- if (fname != NULL) {
- nsoption_setnull_charp(cookie_file, fname);
- }
-
- /* cookie jar default */
- fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Cookies");
- if (fname != NULL) {
- nsoption_setnull_charp(cookie_jar, fname);
- }
-
- /* url database default */
- fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "URLs");
- if (fname != NULL) {
- nsoption_setnull_charp(url_file, fname);
- }
-
- /* bookmark database default */
- fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Hotlist");
- if (fname != NULL) {
- nsoption_setnull_charp(hotlist_path, fname);
- }
-
- /* download directory default */
- fname = getenv("HOME");
- if (fname != NULL) {
- nsoption_setnull_charp(downloads_directory, strdup(fname));
- }
-
- /* default path to certificates */
- nsoption_setnull_charp(ca_path, strdup("/etc/ssl/certs"));
-
- if ((nsoption_charp(cookie_file) == NULL) ||
- (nsoption_charp(cookie_jar) == NULL) ||
- (nsoption_charp(url_file) == NULL) ||
- (nsoption_charp(hotlist_path) == NULL) ||
- (nsoption_charp(downloads_directory) == NULL) ||
- (nsoption_charp(ca_path) == NULL)) {
- NSLOG(netsurf, INFO,
- "Failed initialising default resource paths");
- return NSERROR_BAD_PARAMETER;
- }
-
- /* set default font names */
- nsoption_set_charp(font_sans, strdup("Sans"));
- nsoption_set_charp(font_serif, strdup("Serif"));
- nsoption_set_charp(font_mono, strdup("Monospace"));
- nsoption_set_charp(font_cursive, strdup("Serif"));
- nsoption_set_charp(font_fantasy, strdup("Serif"));
-
- return NSERROR_OK;
-}
-
-
-
-
-/**
- * Initialize GTK specific parts of the browser.
- *
- * \param argc The number of arguments on the command line
- * \param argv A string vector of command line arguments.
- * \respath A string vector of the path elements of resources
- */
-static nserror nsgtk_init(int argc, char** argv, char **respath)
-{
- char buf[PATH_MAX];
- char *resource_filename;
- char *addr = NULL;
- nsurl *url;
- nserror res;
-
- /* Initialise gtk accelerator table */
- res = nsgtk_accelerator_init(respaths);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Unable to load gtk accelerator configuration");
- /* not fatal if this does not load */
- }
-
- /* initialise warning dialog */
- res = nsgtk_builder_new_from_resname("warning", &warning_builder);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to initialise warning dialog");
- return res;
- }
-
- gtk_builder_connect_signals(warning_builder, NULL);
-
- /* set default icon if its available */
- res = nsgdk_pixbuf_new_from_resname("netsurf.xpm",
- &win_default_icon_pixbuf);
- if (res == NSERROR_OK) {
- NSLOG(netsurf, INFO, "Seting default window icon");
- gtk_window_set_default_icon(win_default_icon_pixbuf);
- }
-
- /* Search engine sources */
- resource_filename = filepath_find(respath, "SearchEngines");
- search_web_init(resource_filename);
- if (resource_filename != NULL) {
- NSLOG(netsurf, INFO, "Using '%s' as Search Engines file",
- resource_filename);
- free(resource_filename);
- }
-
- /* Default favicon */
- res = nsgdk_pixbuf_new_from_resname("favicon.png", &favicon_pixbuf);
- if (res != NSERROR_OK) {
- favicon_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
- false, 8, 16, 16);
- }
-
- /* arrow down icon */
- res = nsgdk_pixbuf_new_from_resname("arrow_down_8x32.png",
- &arrow_down_pixbuf);
- if (res != NSERROR_OK) {
- arrow_down_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
- false, 8, 8, 32);
- }
-
- /* initialise throbber */
- res = nsgtk_throbber_init();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to initialise throbber.");
- return res;
- }
-
- /* Initialise completions - cannot fail */
- nsgtk_completion_init();
-
- /* The tree view system needs to know the screen's DPI, so we
- * find that out here, rather than when we create a first browser
- * window.
- */
- browser_set_dpi(gdk_screen_get_resolution(gdk_screen_get_default()));
- NSLOG(netsurf, INFO, "Set CSS DPI to %d", browser_get_dpi());
-
- filepath_sfinddef(respath, buf, "mime.types", "/etc/");
- gtk_fetch_filetype_init(buf);
-
- save_complete_init();
-
- urldb_load(nsoption_charp(url_file));
- urldb_load_cookies(nsoption_charp(cookie_file));
- hotlist_init(nsoption_charp(hotlist_path),
- nsoption_charp(hotlist_path));
-
- /* Initialise top level UI elements */
- res = nsgtk_download_init();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to initialise download window.");
- return res;
- }
-
- /* If there is a url specified on the command line use it */
- if (argc > 1) {
- struct stat fs;
- if (stat(argv[1], &fs) == 0) {
- size_t addrlen;
- char *rp = realpath(argv[1], NULL);
- assert(rp != NULL);
-
- /* calculate file url length including terminator */
- addrlen = SLEN("file://") + strlen(rp) + 1;
- addr = malloc(addrlen);
- assert(addr != NULL);
- snprintf(addr, addrlen, "file://%s", rp);
- free(rp);
- } else {
- addr = strdup(argv[1]);
- }
- }
- if (addr != NULL) {
- /* managed to set up based on local launch */
- } else if (nsoption_charp(homepage_url) != NULL) {
- addr = strdup(nsoption_charp(homepage_url));
- } else {
- addr = strdup(NETSURF_HOMEPAGE);
- }
-
- /* create an initial browser window */
- res = nsurl_create(addr, &url);
- if (res == NSERROR_OK) {
- res = browser_window_create(BW_CREATE_HISTORY,
- url,
- NULL,
- NULL,
- NULL);
- nsurl_unref(url);
- }
-
- free(addr);
-
- return res;
-}
-
-
-
-/**
- * Ensures output logging stream is correctly configured
- */
-static bool nslog_stream_configure(FILE *fptr)
-{
- /* set log stream to be non-buffering */
- setbuf(fptr, NULL);
-
- return true;
-}
-
-
-/**
- * Run the gtk event loop.
- *
- * The same as the standard gtk_main loop except this ensures active
- * FD are added to the gtk poll event set.
- */
-static void nsgtk_main(void)
-{
- fd_set read_fd_set, write_fd_set, exc_fd_set;
- int max_fd;
- GPollFD *fd_list[1000];
- unsigned int fd_count;
-
- while (!nsgtk_complete) {
- max_fd = -1;
- fd_count = 0;
- FD_ZERO(&read_fd_set);
- FD_ZERO(&write_fd_set);
- FD_ZERO(&exc_fd_set);
-
- fetch_fdset(&read_fd_set, &write_fd_set, &exc_fd_set, &max_fd);
- for (int i = 0; i <= max_fd; i++) {
- if (FD_ISSET(i, &read_fd_set)) {
- GPollFD *fd = malloc(sizeof *fd);
- fd->fd = i;
- fd->events = G_IO_IN | G_IO_HUP | G_IO_ERR;
- g_main_context_add_poll(0, fd, 0);
- fd_list[fd_count++] = fd;
- }
- if (FD_ISSET(i, &write_fd_set)) {
- GPollFD *fd = malloc(sizeof *fd);
- fd->fd = i;
- fd->events = G_IO_OUT | G_IO_ERR;
- g_main_context_add_poll(0, fd, 0);
- fd_list[fd_count++] = fd;
- }
- if (FD_ISSET(i, &exc_fd_set)) {
- GPollFD *fd = malloc(sizeof *fd);
- fd->fd = i;
- fd->events = G_IO_ERR;
- g_main_context_add_poll(0, fd, 0);
- fd_list[fd_count++] = fd;
- }
- }
-
- schedule_run();
+/** default window icon pixbuf */
+GdkPixbuf *win_default_icon_pixbuf;
- gtk_main_iteration();
-
- for (unsigned int i = 0; i != fd_count; i++) {
- g_main_context_remove_poll(0, fd_list[i]);
- free(fd_list[i]);
- }
- }
-}
-
-
-static void gui_quit(void)
-{
- nserror res;
-
- NSLOG(netsurf, INFO, "Quitting GUI");
-
- /* Ensure all scaffoldings are destroyed before we go into exit */
- nsgtk_download_destroy();
- urldb_save_cookies(nsoption_charp(cookie_jar));
- urldb_save(nsoption_charp(url_file));
-
- res = nsgtk_cookies_destroy();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Error finalising cookie viewer: %s",
- messages_get_errorcode(res));
- }
-
- res = nsgtk_local_history_destroy();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Error finalising local history viewer: %s",
- messages_get_errorcode(res));
- }
-
- res = nsgtk_global_history_destroy();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Error finalising global history viewer: %s",
- messages_get_errorcode(res));
- }
-
- res = nsgtk_hotlist_destroy();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Error finalising hotlist viewer: %s",
- messages_get_errorcode(res));
- }
-
- res = hotlist_fini();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Error finalising hotlist: %s",
- messages_get_errorcode(res));
- }
-
- free(nsgtk_config_home);
-
- gtk_fetch_filetype_fin();
-}
-
-static nserror gui_launch_url(struct nsurl *url)
-{
- gboolean ok;
- GError *error = NULL;
+GtkBuilder *warning_builder;
- ok = nsgtk_show_uri(NULL, nsurl_access(url), GDK_CURRENT_TIME, &error);
- if (ok == TRUE) {
- return NSERROR_OK;
- }
+/** resource search path vector */
+char **respaths;
- if (error) {
- nsgtk_warning(messages_get("URIOpenError"), error->message);
- g_error_free(error);
- }
- return NSERROR_NO_FETCH_HANDLER;
-}
/* exported function documented in gtk/warn.h */
nserror nsgtk_warning(const char *warning, const char *detail)
@@ -518,7 +106,7 @@ nserror nsgtk_warning(const char *warning, const char *detail)
"labelWarning"));
snprintf(buf, sizeof(buf), "%s %s", messages_get(warning),
- detail ? detail : "");
+ detail ? detail : "");
buf[sizeof(buf) - 1] = 0;
gtk_label_set_text(WarningLabel, buf);
@@ -529,129 +117,7 @@ nserror nsgtk_warning(const char *warning, const char *detail)
}
-static void nsgtk_PDF_set_pass(GtkButton *w, gpointer data)
-{
- char **owner_pass = ((void **)data)[0];
- char **user_pass = ((void **)data)[1];
- GtkWindow *wnd = ((void **)data)[2];
- GtkBuilder *password_builder = ((void **)data)[3];
- char *path = ((void **)data)[4];
-
- char *op, *op1;
- char *up, *up1;
-
- op = strdup(gtk_entry_get_text(
- GTK_ENTRY(gtk_builder_get_object(password_builder,
- "entryPDFOwnerPassword"))));
- op1 = strdup(gtk_entry_get_text(
- GTK_ENTRY(gtk_builder_get_object(password_builder,
- "entryPDFOwnerPassword1"))));
- up = strdup(gtk_entry_get_text(
- GTK_ENTRY(gtk_builder_get_object(password_builder,
- "entryPDFUserPassword"))));
- up1 = strdup(gtk_entry_get_text(
- GTK_ENTRY(gtk_builder_get_object(password_builder,
- "entryPDFUserPassword1"))));
-
-
- if (op[0] == '\0') {
- gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
- "labelInfo")),
- "Owner password must be at least 1 character long:");
- free(op);
- free(up);
- } else if (!strcmp(op, up)) {
- gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
- "labelInfo")),
- "User and owner passwords must be different:");
- free(op);
- free(up);
- } else if (!strcmp(op, op1) && !strcmp(up, up1)) {
-
- *owner_pass = op;
- if (up[0] == '\0')
- free(up);
- else
- *user_pass = up;
-
- free(data);
- gtk_widget_destroy(GTK_WIDGET(wnd));
- g_object_unref(G_OBJECT(password_builder));
-
- save_pdf(path);
-
- free(path);
- } else {
- gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
- "labelInfo")), "Passwords not confirmed:");
- free(op);
- free(up);
- }
-
- free(op1);
- free(up1);
-}
-
-static void nsgtk_PDF_no_pass(GtkButton *w, gpointer data)
-{
- GtkWindow *wnd = ((void **)data)[2];
- GtkBuilder *password_builder = ((void **)data)[3];
- char *path = ((void **)data)[4];
-
- free(data);
-
- gtk_widget_destroy(GTK_WIDGET(wnd));
- g_object_unref(G_OBJECT(password_builder));
-
- save_pdf(path);
-
- free(path);
-}
-
-static void nsgtk_pdf_password(char **owner_pass, char **user_pass, char *path)
-{
- GtkButton *ok, *no;
- GtkWindow *wnd;
- void **data;
- GtkBuilder *password_builder;
- nserror res;
-
- res = nsgtk_builder_new_from_resname("password", &password_builder);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Password UI builder init failed");
- return;
- }
-
- gtk_builder_connect_signals(password_builder, NULL);
-
- wnd = GTK_WINDOW(gtk_builder_get_object(password_builder,
- "wndPDFPassword"));
-
- data = malloc(5 * sizeof(void *));
-
- *owner_pass = NULL;
- *user_pass = NULL;
-
- data[0] = owner_pass;
- data[1] = user_pass;
- data[2] = wnd;
- data[3] = password_builder;
- data[4] = path;
-
- ok = GTK_BUTTON(gtk_builder_get_object(password_builder,
- "buttonPDFSetPassword"));
- no = GTK_BUTTON(gtk_builder_get_object(password_builder,
- "buttonPDFNoPassword"));
-
- g_signal_connect(G_OBJECT(ok), "clicked",
- G_CALLBACK(nsgtk_PDF_set_pass), (gpointer)data);
- g_signal_connect(G_OBJECT(no), "clicked",
- G_CALLBACK(nsgtk_PDF_no_pass), (gpointer)data);
-
- gtk_widget_show(GTK_WIDGET(wnd));
-}
-
-
+/* exported interface documented in gtk/gui.h */
uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
{
/* this function will need to become much more complex to support
@@ -666,12 +132,16 @@ uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
case GDK_KEY(BackSpace):
if (key->state & GDK_SHIFT_MASK)
return NS_KEY_DELETE_LINE_START;
+ else if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_DELETE_WORD_LEFT;
else
return NS_KEY_DELETE_LEFT;
case GDK_KEY(Delete):
if (key->state & GDK_SHIFT_MASK)
return NS_KEY_DELETE_LINE_END;
+ else if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_DELETE_WORD_RIGHT;
else
return NS_KEY_DELETE_RIGHT;
@@ -683,10 +153,14 @@ uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
case GDK_KEY(Left):
case GDK_KEY(KP_Left):
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_WORD_LEFT;
return NS_KEY_LEFT;
case GDK_KEY(Right):
case GDK_KEY(KP_Right):
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_WORD_RIGHT;
return NS_KEY_RIGHT;
case GDK_KEY(Up):
@@ -781,6 +255,63 @@ uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
/**
+ * Create an array of valid paths to search for resources.
+ *
+ * The idea is that all the complex path computation to find resources
+ * is performed here, once, rather than every time a resource is
+ * searched for.
+ */
+static char **
+nsgtk_init_resource_path(const char *config_home)
+{
+ char *resource_path;
+ int resource_path_len;
+ const gchar * const *langv;
+ char **pathv; /* resource path string vector */
+ char **respath; /* resource paths vector */
+
+ if (config_home != NULL) {
+ resource_path_len = snprintf(NULL, 0,
+ "%s:${NETSURFRES}:%s",
+ config_home,
+ GTK_RESPATH);
+ resource_path = malloc(resource_path_len + 1);
+ if (resource_path == NULL) {
+ return NULL;
+ }
+ snprintf(resource_path, resource_path_len + 1,
+ "%s:${NETSURFRES}:%s",
+ config_home,
+ GTK_RESPATH);
+ } else {
+ resource_path_len = snprintf(NULL, 0,
+ "${NETSURFRES}:%s",
+ GTK_RESPATH);
+ resource_path = malloc(resource_path_len + 1);
+ if (resource_path == NULL) {
+ return NULL;
+ }
+ snprintf(resource_path,
+ resource_path_len + 1,
+ "${NETSURFRES}:%s",
+ GTK_RESPATH);
+ }
+
+ pathv = filepath_path_to_strvec(resource_path);
+
+ langv = g_get_language_names();
+
+ respath = filepath_generate(pathv, langv);
+
+ filepath_free_strvec(pathv);
+
+ free(resource_path);
+
+ return respath;
+}
+
+
+/**
* create directory name and check it is acessible and a directory.
*/
static nserror
@@ -818,6 +349,7 @@ check_dirname(const char *path, const char *leaf, char **dirname_out)
return ret;
}
+
/**
* Get the path to the config directory.
*
@@ -885,6 +417,7 @@ static nserror get_config_home(char **config_home_out)
return NSERROR_OK;
}
+
static nserror create_config_home(char **config_home_out)
{
char *config_home = NULL;
@@ -935,6 +468,192 @@ static nserror create_config_home(char **config_home_out)
return NSERROR_OK;
}
+
+/**
+ * Ensures output logging stream is correctly configured
+ */
+static bool nslog_stream_configure(FILE *fptr)
+{
+ /* set log stream to be non-buffering */
+ setbuf(fptr, NULL);
+
+ return true;
+}
+
+
+/**
+ * Set option defaults for gtk frontend.
+ *
+ * \param defaults The option table to update.
+ * \return error status.
+ */
+static nserror set_defaults(struct nsoption_s *defaults)
+{
+ char *fname;
+ GtkSettings *settings;
+ GtkIconSize tooliconsize;
+ GtkToolbarStyle toolbarstyle;
+
+ /* cookie file default */
+ fname = NULL;
+ netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Cookies");
+ if (fname != NULL) {
+ nsoption_setnull_charp(cookie_file, fname);
+ }
+
+ /* cookie jar default */
+ fname = NULL;
+ netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Cookies");
+ if (fname != NULL) {
+ nsoption_setnull_charp(cookie_jar, fname);
+ }
+
+ /* url database default */
+ fname = NULL;
+ netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "URLs");
+ if (fname != NULL) {
+ nsoption_setnull_charp(url_file, fname);
+ }
+
+ /* bookmark database default */
+ fname = NULL;
+ netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Hotlist");
+ if (fname != NULL) {
+ nsoption_setnull_charp(hotlist_path, fname);
+ }
+
+ /* download directory default */
+ fname = getenv("HOME");
+ if (fname != NULL) {
+ nsoption_setnull_charp(downloads_directory, strdup(fname));
+ }
+
+ if ((nsoption_charp(cookie_file) == NULL) ||
+ (nsoption_charp(cookie_jar) == NULL) ||
+ (nsoption_charp(url_file) == NULL) ||
+ (nsoption_charp(hotlist_path) == NULL) ||
+ (nsoption_charp(downloads_directory) == NULL)) {
+ NSLOG(netsurf, INFO,
+ "Failed initialising default resource paths");
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* set default font names */
+ nsoption_set_charp(font_sans, strdup("Sans"));
+ nsoption_set_charp(font_serif, strdup("Serif"));
+ nsoption_set_charp(font_mono, strdup("Monospace"));
+ nsoption_set_charp(font_cursive, strdup("Serif"));
+ nsoption_set_charp(font_fantasy, strdup("Serif"));
+
+ /* Default toolbar button type to system defaults */
+
+ settings = gtk_settings_get_default();
+ g_object_get(settings,
+ "gtk-toolbar-icon-size", &tooliconsize,
+ "gtk-toolbar-style", &toolbarstyle, NULL);
+
+ switch (toolbarstyle) {
+ case GTK_TOOLBAR_ICONS:
+ if (tooliconsize == GTK_ICON_SIZE_SMALL_TOOLBAR) {
+ nsoption_set_int(button_type, 1);
+ } else {
+ nsoption_set_int(button_type, 2);
+ }
+ break;
+
+ case GTK_TOOLBAR_TEXT:
+ nsoption_set_int(button_type, 4);
+ break;
+
+ case GTK_TOOLBAR_BOTH:
+ case GTK_TOOLBAR_BOTH_HORIZ:
+ /* no labels in default configuration */
+ default:
+ /* No system default, so use large icons */
+ nsoption_set_int(button_type, 2);
+ break;
+ }
+
+ /* set default items in toolbar */
+ nsoption_set_charp(toolbar_items,
+ strdup("back/history/forward/reloadstop/url_bar/websearch/openmenu"));
+
+ /* set default for menu and tool bar visibility */
+ nsoption_set_charp(bar_show, strdup("tool"));
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Initialise user options
+ *
+ * Initialise the browser configuration options. These are set by:
+ * - set generic defaults suitable for the gtk frontend
+ * - user choices loaded from Choices file
+ * - command line parameters
+ */
+static nserror nsgtk_option_init(int *pargc, char** argv)
+{
+ nserror ret;
+ char *choices = NULL;
+
+ /* user options setup */
+ ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ /* Attempt to load the user choices */
+ ret = netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices");
+ if (ret == NSERROR_OK) {
+ nsoption_read(choices, nsoptions);
+ free(choices);
+ }
+
+ /* overide loaded options with those from commandline */
+ nsoption_commandline(pargc, argv, nsoptions);
+
+ /* ensure all options fall within sensible bounds */
+
+ /* Attempt to handle nonsense status bar widths. These may exist
+ * in people's Choices as the GTK front end used to abuse the
+ * status bar width option by using it for an absolute value in px.
+ * The GTK front end now correctly uses it as a proportion of window
+ * width. Here we assume that a value of less than 15% is wrong
+ * and set to the default two thirds. */
+ if (nsoption_int(toolbar_status_size) < 1500) {
+ nsoption_set_int(toolbar_status_size, 6667);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * initialise message translation
+ */
+static nserror nsgtk_messages_init(char **respaths)
+{
+ const char *messages;
+ nserror ret;
+ const uint8_t *data;
+ size_t data_size;
+
+ ret = nsgtk_data_from_resname("Messages", &data, &data_size);
+ if (ret == NSERROR_OK) {
+ ret = messages_add_from_inline(data, data_size);
+ } else {
+ /* Obtain path to messages */
+ ret = nsgtk_path_from_resname("Messages", &messages);
+ if (ret == NSERROR_OK) {
+ ret = messages_add_from_file(messages);
+ }
+ }
+ return ret;
+}
+
+
/**
* Get the path to the cache directory.
*
@@ -983,6 +702,10 @@ static nserror get_cache_home(char **cache_home_out)
return NSERROR_OK;
}
+
+/**
+ * create a cache directory
+ */
static nserror create_cache_home(char **cache_home_out)
{
char *cache_home = NULL;
@@ -990,7 +713,7 @@ static nserror create_cache_home(char **cache_home_out)
char *xdg_cache_dir;
nserror ret;
- NSLOG(netsurf, INFO, "Attempting to create configuration directory");
+ NSLOG(netsurf, INFO, "Attempting to create cache directory");
/* $XDG_CACHE_HOME defines the base directory
* relative to which user specific cache files
@@ -1033,98 +756,13 @@ static nserror create_cache_home(char **cache_home_out)
return NSERROR_OK;
}
-static nserror nsgtk_option_init(int *pargc, char** argv)
-{
- nserror ret;
- char *choices = NULL;
-
- /* user options setup */
- ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
- if (ret != NSERROR_OK) {
- return ret;
- }
-
- /* Attempt to load the user choices */
- ret = netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices");
- if (ret == NSERROR_OK) {
- nsoption_read(choices, nsoptions);
- free(choices);
- }
-
- /* overide loaded options with those from commandline */
- nsoption_commandline(pargc, argv, nsoptions);
-
- /* ensure all options fall within sensible bounds */
-
- /* Attempt to handle nonsense status bar widths. These may exist
- * in people's Choices as the GTK front end used to abuse the
- * status bar width option by using it for an absolute value in px.
- * The GTK front end now correctly uses it as a proportion of window
- * width. Here we assume that a value of less than 15% is wrong
- * and set to the default two thirds. */
- if (nsoption_int(toolbar_status_size) < 1500) {
- nsoption_set_int(toolbar_status_size, 6667);
- }
-
- return NSERROR_OK;
-}
-
-static struct gui_misc_table nsgtk_misc_table = {
- .schedule = nsgtk_schedule,
- .warning = nsgtk_warning,
-
- .quit = gui_quit,
- .launch_url = gui_launch_url,
- .cert_verify = gtk_cert_verify,
- .login = gui_401login_open,
- .pdf_password = nsgtk_pdf_password,
-};
-
-
-static nserror nsgtk_messages_init(char **respaths)
-{
- const char *messages;
- nserror ret;
- const uint8_t *data;
- size_t data_size;
-
- ret = nsgtk_data_from_resname("Messages", &data, &data_size);
- if (ret == NSERROR_OK) {
- ret = messages_add_from_inline(data, data_size);
- } else {
- /* Obtain path to messages */
- ret = nsgtk_path_from_resname("Messages", &messages);
- if (ret == NSERROR_OK) {
- ret = messages_add_from_file(messages);
- }
- }
- return ret;
-}
/**
- * Main entry point from OS.
+ * GTK specific initialisation
*/
-int main(int argc, char** argv)
+static nserror nsgtk_init(int *pargc, char ***pargv, char **cache_home)
{
- char *cache_home = NULL;
nserror ret;
- struct netsurf_table nsgtk_table = {
- .misc = &nsgtk_misc_table,
- .window = nsgtk_window_table,
- .clipboard = nsgtk_clipboard_table,
- .download = nsgtk_download_table,
- .fetch = nsgtk_fetch_table,
- .llcache = filesystem_llcache_table,
- .search = nsgtk_search_table,
- .search_web = nsgtk_search_web_table,
- .bitmap = nsgtk_bitmap_table,
- .layout = nsgtk_layout_table,
- };
-
- ret = netsurf_register(&nsgtk_table);
- if (ret != NSERROR_OK) {
- die("NetSurf operation table failed registration\n");
- }
/* Locate the correct user configuration directory path */
ret = get_config_home(&nsgtk_config_home);
@@ -1139,12 +777,12 @@ int main(int argc, char** argv)
}
/* Initialise gtk */
- gtk_init(&argc, &argv);
+ gtk_init(pargc, pargv);
/* initialise logging. Not fatal if it fails but not much we
* can do about it either.
*/
- nslog_init(nslog_stream_configure, &argc, argv);
+ nslog_init(nslog_stream_configure, pargc, *pargv);
/* build the common resource path list */
respaths = nsgtk_init_resource_path(nsgtk_config_home);
@@ -1158,15 +796,15 @@ int main(int argc, char** argv)
if (ret != NSERROR_OK) {
fprintf(stderr, "GTK resources failed to initialise (%s)\n",
messages_get_errorcode(ret));
- return 1;
+ return ret;
}
/* Initialise user options */
- ret = nsgtk_option_init(&argc, argv);
+ ret = nsgtk_option_init(pargc, *pargv);
if (ret != NSERROR_OK) {
fprintf(stderr, "Options failed to initialise (%s)\n",
messages_get_errorcode(ret));
- return 1;
+ return ret;
}
/* Initialise translated messages */
@@ -1177,35 +815,353 @@ int main(int argc, char** argv)
NSLOG(netsurf, INFO, "Unable to load translated messages");
/** \todo decide if message load faliure should be fatal */
}
-
+
/* Locate the correct user cache directory path */
- ret = get_cache_home(&cache_home);
+ ret = get_cache_home(cache_home);
if (ret == NSERROR_NOT_FOUND) {
/* no cache directory exists yet so try to create one */
- ret = create_cache_home(&cache_home);
+ ret = create_cache_home(cache_home);
}
if (ret != NSERROR_OK) {
NSLOG(netsurf, INFO, "Unable to locate a cache directory.");
}
- /* core initialisation */
- ret = netsurf_init(cache_home);
- free(cache_home);
- if (ret != NSERROR_OK) {
- fprintf(stderr, "NetSurf core failed to initialise (%s)\n",
- messages_get_errorcode(ret));
- return 1;
+
+ return NSERROR_OK;
+}
+
+
+#if GTK_CHECK_VERSION(3,14,0)
+
+/**
+ * adds named icons into gtk theme
+ */
+static nserror nsgtk_add_named_icons_to_theme(void)
+{
+ gtk_icon_theme_add_resource_path(gtk_icon_theme_get_default(),
+ "/org/netsurf/icons");
+ return NSERROR_OK;
+}
+
+#else
+
+static nserror
+add_builtin_icon(const char *prefix, const char *name, int x, int y)
+{
+ GdkPixbuf *pixbuf;
+ nserror res;
+ char *resname;
+ int resnamelen;
+
+ /* resource name string length allowing for / .png and termination */
+ resnamelen = strlen(prefix) + strlen(name) + 5 + 1 + 4 + 1;
+ resname = malloc(resnamelen);
+ if (resname == NULL) {
+ return NSERROR_NOMEM;
}
+ snprintf(resname, resnamelen, "icons%s/%s.png", prefix, name);
- /* gtk specific initalisation and main run loop */
- ret = nsgtk_init(argc, argv, respaths);
- if (ret != NSERROR_OK) {
- fprintf(stderr, "NetSurf gtk initialise failed (%s)\n",
- messages_get_errorcode(ret));
+ res = nsgdk_pixbuf_new_from_resname(resname, &pixbuf);
+ NSLOG(netsurf, DEEPDEBUG, "%d %s", res, resname);
+ free(resname);
+ if (res != NSERROR_OK) {
+ pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8, x, y);
+ }
+ gtk_icon_theme_add_builtin_icon(name, y, pixbuf);
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * adds named icons into gtk theme
+ */
+static nserror nsgtk_add_named_icons_to_theme(void)
+{
+ /* these must also be in gtk/resources.c pixbuf_resource *and*
+ * gtk/res/netsurf.gresource.xml
+ */
+ add_builtin_icon("", "local-history", 8, 32);
+ add_builtin_icon("", "show-cookie", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-insecure", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-internal", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-local", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-secure", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-warning", 24, 24);
+ add_builtin_icon("/48x48/actions", "page-info-insecure", 48, 48);
+ add_builtin_icon("/48x48/actions", "page-info-internal", 48, 48);
+ add_builtin_icon("/48x48/actions", "page-info-local", 48, 48);
+ add_builtin_icon("/48x48/actions", "page-info-secure", 48, 48);
+ add_builtin_icon("/48x48/actions", "page-info-warning", 48, 48);
+
+ return NSERROR_OK;
+}
+
+#endif
+
+
+/**
+ * setup GTK specific parts of the browser.
+ *
+ * \param argc The number of arguments on the command line
+ * \param argv A string vector of command line arguments.
+ * \respath A string vector of the path elements of resources
+ */
+static nserror nsgtk_setup(int argc, char** argv, char **respath)
+{
+ char buf[PATH_MAX];
+ char *resource_filename;
+ char *addr = NULL;
+ nsurl *url;
+ nserror res;
+
+ /* Initialise gtk accelerator table */
+ res = nsgtk_accelerator_init(respaths);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Unable to load gtk accelerator configuration");
+ /* not fatal if this does not load */
+ }
+
+ /* initialise warning dialog */
+ res = nsgtk_builder_new_from_resname("warning", &warning_builder);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to initialise warning dialog");
+ return res;
+ }
+
+ gtk_builder_connect_signals(warning_builder, NULL);
+
+ /* set default icon if its available */
+ res = nsgdk_pixbuf_new_from_resname("netsurf.xpm",
+ &win_default_icon_pixbuf);
+ if (res == NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Seting default window icon");
+ gtk_window_set_default_icon(win_default_icon_pixbuf);
+ }
+
+ /* Search engine sources */
+ resource_filename = filepath_find(respath, "SearchEngines");
+ search_web_init(resource_filename);
+ if (resource_filename != NULL) {
+ NSLOG(netsurf, INFO, "Using '%s' as Search Engines file",
+ resource_filename);
+ free(resource_filename);
+ }
+ search_web_select_provider(nsoption_int(search_provider));
+
+ /* Default favicon */
+ res = nsgdk_pixbuf_new_from_resname("favicon.png", &favicon_pixbuf);
+ if (res != NSERROR_OK) {
+ favicon_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
+ false, 8, 16, 16);
+ }
+
+ /* add named icons to gtk theme */
+ res = nsgtk_add_named_icons_to_theme();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to add named icons to GTK theme.");
+ return res;
+ }
+
+ /* initialise throbber */
+ res = nsgtk_throbber_init();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to initialise throbber.");
+ return res;
+ }
+
+ /* Initialise completions - cannot fail */
+ nsgtk_completion_init();
+
+ /* The tree view system needs to know the screen's DPI, so we
+ * find that out here, rather than when we create a first browser
+ * window.
+ */
+ browser_set_dpi(gdk_screen_get_resolution(gdk_screen_get_default()));
+ NSLOG(netsurf, INFO, "Set CSS DPI to %d", browser_get_dpi());
+
+ bitmap_set_format(&(bitmap_fmt_t) {
+ .layout = BITMAP_LAYOUT_ARGB8888,
+ .pma = true,
+ });
+
+ filepath_sfinddef(respath, buf, "mime.types", "/etc/");
+ gtk_fetch_filetype_init(buf);
+
+ save_complete_init();
+
+ urldb_load(nsoption_charp(url_file));
+ urldb_load_cookies(nsoption_charp(cookie_file));
+ hotlist_init(nsoption_charp(hotlist_path),
+ nsoption_charp(hotlist_path));
+
+ /* Initialise top level UI elements */
+ res = nsgtk_download_init();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to initialise download window.");
+ return res;
+ }
+
+ /* If there is a url specified on the command line use it */
+ if (argc > 1) {
+ struct stat fs;
+ if (stat(argv[1], &fs) == 0) {
+ size_t addrlen;
+ char *rp = realpath(argv[1], NULL);
+ assert(rp != NULL);
+
+ /* calculate file url length including terminator */
+ addrlen = SLEN("file://") + strlen(rp) + 1;
+ addr = malloc(addrlen);
+ assert(addr != NULL);
+ snprintf(addr, addrlen, "file://%s", rp);
+ free(rp);
+ } else {
+ addr = strdup(argv[1]);
+ }
+ }
+ if (addr != NULL) {
+ /* managed to set up based on local launch */
+ } else if (nsoption_charp(homepage_url) != NULL) {
+ addr = strdup(nsoption_charp(homepage_url));
} else {
- nsgtk_main();
+ addr = strdup(NETSURF_HOMEPAGE);
+ }
+
+ /* create an initial browser window */
+ res = nsurl_create(addr, &url);
+ if (res == NSERROR_OK) {
+ res = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+
+ free(addr);
+
+ return res;
+}
+
+
+/**
+ * Run the gtk event loop.
+ *
+ * The same as the standard gtk_main loop except this ensures active
+ * FD are added to the gtk poll event set.
+ */
+static void nsgtk_main(void)
+{
+ fd_set read_fd_set, write_fd_set, exc_fd_set;
+ int max_fd;
+ GPollFD *fd_list[1000];
+ unsigned int fd_count;
+
+ while (!nsgtk_complete) {
+ max_fd = -1;
+ fd_count = 0;
+ FD_ZERO(&read_fd_set);
+ FD_ZERO(&write_fd_set);
+ FD_ZERO(&exc_fd_set);
+
+ while (gtk_events_pending())
+ gtk_main_iteration_do(TRUE);
+
+ schedule_run();
+
+ fetch_fdset(&read_fd_set, &write_fd_set, &exc_fd_set, &max_fd);
+ for (int i = 0; i <= max_fd; i++) {
+ if (FD_ISSET(i, &read_fd_set)) {
+ GPollFD *fd = malloc(sizeof *fd);
+ fd->fd = i;
+ fd->events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+ g_main_context_add_poll(0, fd, 0);
+ fd_list[fd_count++] = fd;
+ }
+ if (FD_ISSET(i, &write_fd_set)) {
+ GPollFD *fd = malloc(sizeof *fd);
+ fd->fd = i;
+ fd->events = G_IO_OUT | G_IO_ERR;
+ g_main_context_add_poll(0, fd, 0);
+ fd_list[fd_count++] = fd;
+ }
+ if (FD_ISSET(i, &exc_fd_set)) {
+ GPollFD *fd = malloc(sizeof *fd);
+ fd->fd = i;
+ fd->events = G_IO_ERR;
+ g_main_context_add_poll(0, fd, 0);
+ fd_list[fd_count++] = fd;
+ }
+ }
+
+ gtk_main_iteration();
+
+ for (unsigned int i = 0; i != fd_count; i++) {
+ g_main_context_remove_poll(0, fd_list[i]);
+ free(fd_list[i]);
+ }
+ }
+}
+
+
+/**
+ * finalise the browser
+ */
+static void nsgtk_finalise(void)
+{
+ nserror res;
+
+ NSLOG(netsurf, INFO, "Quitting GUI");
+
+ /* Ensure all scaffoldings are destroyed before we go into exit */
+ nsgtk_download_destroy();
+ urldb_save_cookies(nsoption_charp(cookie_jar));
+ urldb_save(nsoption_charp(url_file));
+
+ res = nsgtk_cookies_destroy();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Error finalising cookie viewer: %s",
+ messages_get_errorcode(res));
+ }
+
+ res = nsgtk_local_history_destroy();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Error finalising local history viewer: %s",
+ messages_get_errorcode(res));
}
+ res = nsgtk_global_history_destroy();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Error finalising global history viewer: %s",
+ messages_get_errorcode(res));
+ }
+
+ res = nsgtk_hotlist_destroy();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Error finalising hotlist viewer: %s",
+ messages_get_errorcode(res));
+ }
+
+ res = hotlist_fini();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Error finalising hotlist: %s",
+ messages_get_errorcode(res));
+ }
+
+ res = save_complete_finalise();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Error finalising save complete: %s",
+ messages_get_errorcode(res));
+ }
+
+ free(nsgtk_config_home);
+
+ gtk_fetch_filetype_fin();
+
/* common finalisation */
netsurf_exit();
@@ -1215,5 +1171,66 @@ int main(int argc, char** argv)
/* finalise logging */
nslog_finalise();
+}
+
+
+/**
+ * Main entry point from OS.
+ */
+int main(int argc, char** argv)
+{
+ nserror res;
+ char *cache_home = NULL;
+ struct netsurf_table nsgtk_table = {
+ .misc = nsgtk_misc_table,
+ .window = nsgtk_window_table,
+ .clipboard = nsgtk_clipboard_table,
+ .download = nsgtk_download_table,
+ .fetch = nsgtk_fetch_table,
+ .llcache = filesystem_llcache_table,
+ .search = nsgtk_search_table,
+ .search_web = nsgtk_search_web_table,
+ .bitmap = nsgtk_bitmap_table,
+ .layout = nsgtk_layout_table,
+ };
+
+ res = netsurf_register(&nsgtk_table);
+ if (res != NSERROR_OK) {
+ fprintf(stderr,
+ "NetSurf operation table failed registration (%s)\n",
+ messages_get_errorcode(res));
+ return 1;
+ }
+
+ /* gtk specific initialisation */
+ res = nsgtk_init(&argc, &argv, &cache_home);
+ if (res != NSERROR_OK) {
+ fprintf(stderr, "NetSurf gtk failed to initialise (%s)\n",
+ messages_get_errorcode(res));
+ return 2;
+ }
+
+ /* core initialisation */
+ res = netsurf_init(cache_home);
+ free(cache_home);
+ if (res != NSERROR_OK) {
+ fprintf(stderr, "NetSurf core failed to initialise (%s)\n",
+ messages_get_errorcode(res));
+ return 3;
+ }
+
+ /* gtk specific initalisation and main run loop */
+ res = nsgtk_setup(argc, argv, respaths);
+ if (res != NSERROR_OK) {
+ nsgtk_finalise();
+ fprintf(stderr, "NetSurf gtk setup failed (%s)\n",
+ messages_get_errorcode(res));
+ return 4;
+ }
+
+ nsgtk_main();
+
+ nsgtk_finalise();
+
return 0;
}
diff --git a/frontends/gtk/gui.h b/frontends/gtk/gui.h
index 53e732437..ee82e7a6f 100644
--- a/frontends/gtk/gui.h
+++ b/frontends/gtk/gui.h
@@ -27,9 +27,6 @@ extern char *nsgtk_config_home;
/** favicon default pixbuf */
extern GdkPixbuf *favicon_pixbuf;
-/** arrow down pixbuf */
-extern GdkPixbuf *arrow_down_pixbuf;
-
/** resource search path vector */
extern char **respaths;
diff --git a/frontends/gtk/hotlist.c b/frontends/gtk/hotlist.c
index 843e47736..b047dc65f 100644
--- a/frontends/gtk/hotlist.c
+++ b/frontends/gtk/hotlist.c
@@ -170,6 +170,8 @@ MENUHANDLER(delete_selected)
MENUHANDLER(select_all)
{
+ hotlist_keypress(NS_KEY_ESCAPE);
+ hotlist_keypress(NS_KEY_ESCAPE);
hotlist_keypress(NS_KEY_SELECT_ALL);
return TRUE;
}
diff --git a/frontends/gtk/layout_pango.c b/frontends/gtk/layout_pango.c
index a5964eb37..9e8e94d48 100644
--- a/frontends/gtk/layout_pango.c
+++ b/frontends/gtk/layout_pango.c
@@ -277,7 +277,7 @@ nsfont_style_to_description(const plot_font_style_t *fstyle)
break;
}
- size = (fstyle->size * PANGO_SCALE) / FONT_SIZE_SCALE;
+ size = (fstyle->size * PANGO_SCALE) / PLOT_STYLE_SCALE;
if (fstyle->flags & FONTF_ITALIC)
style = PANGO_STYLE_ITALIC;
diff --git a/frontends/gtk/local_history.c b/frontends/gtk/local_history.c
index 35b7a4ad6..0d59c468a 100644
--- a/frontends/gtk/local_history.c
+++ b/frontends/gtk/local_history.c
@@ -35,6 +35,7 @@
#include "gtk/resources.h"
#include "gtk/corewindow.h"
#include "gtk/local_history.h"
+#include "gtk/scaffolding.h"
struct nsgtk_local_history_window {
struct nsgtk_corewindow core;
@@ -158,6 +159,12 @@ nsgtk_local_history_init(struct browser_window *bw,
ncwin->wnd = GTK_WINDOW(gtk_builder_get_object(ncwin->builder,
"wndHistory"));
+ /* Configure for transient behaviour */
+ gtk_window_set_type_hint(GTK_WINDOW(ncwin->wnd),
+ GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU);
+ gtk_window_set_modal(GTK_WINDOW(ncwin->wnd), TRUE);
+
+
ncwin->core.scrolled = GTK_SCROLLED_WINDOW(
gtk_builder_get_object(ncwin->builder,
"HistoryScrolled"));
@@ -171,6 +178,16 @@ nsgtk_local_history_init(struct browser_window *bw,
"delete_event",
G_CALLBACK(gtk_widget_hide_on_delete),
NULL);
+ /* Ditto if we lose the grab */
+ g_signal_connect(G_OBJECT(ncwin->wnd),
+ "grab-broken-event",
+ G_CALLBACK(gtk_widget_hide_on_delete),
+ ncwin);
+ /* Handle button press events */
+ g_signal_connect(G_OBJECT(ncwin->wnd),
+ "button-press-event",
+ G_CALLBACK(gtk_widget_hide_on_delete),
+ ncwin);
ncwin->core.draw = nsgtk_local_history_draw;
ncwin->core.key = nsgtk_local_history_key;
@@ -206,7 +223,11 @@ nserror nsgtk_local_history_present(GtkWindow *parent,
int width, height;
res = nsgtk_local_history_init(bw, &local_history_window);
if (res == NSERROR_OK) {
+ gtk_window_group_add_window(gtk_window_get_group(parent),
+ local_history_window->wnd);
gtk_window_set_transient_for(local_history_window->wnd, parent);
+ gtk_window_set_screen(local_history_window->wnd,
+ gtk_widget_get_screen(GTK_WIDGET(parent)));
gtk_window_get_size(parent, &prnt_width, &prnt_height);
@@ -224,7 +245,13 @@ nserror nsgtk_local_history_present(GtkWindow *parent,
}
gtk_window_resize(local_history_window->wnd, width, height);
- gtk_window_present(local_history_window->wnd);
+ /* Attempt to place the window in the right place */
+ nsgtk_scaffolding_position_local_history(nsgtk_current_scaffolding());
+
+ gtk_widget_show(GTK_WIDGET(local_history_window->wnd));
+ gtk_widget_grab_focus(GTK_WIDGET(local_history_window->wnd));
+
+ local_history_scroll_to_cursor(local_history_window->session);
}
return res;
@@ -267,3 +294,11 @@ nserror nsgtk_local_history_destroy(void)
return res;
}
+
+/* exported function documented gtk/history.h */
+void nsgtk_local_history_set_position(int x, int y)
+{
+ NSLOG(netsurf, INFO, "x=%d y=%d", x, y);
+
+ gtk_window_move(local_history_window->wnd, x, y);
+}
diff --git a/frontends/gtk/local_history.h b/frontends/gtk/local_history.h
index 605405ddf..c5b447194 100644
--- a/frontends/gtk/local_history.h
+++ b/frontends/gtk/local_history.h
@@ -34,6 +34,11 @@ struct browser_window;
nserror nsgtk_local_history_present(GtkWindow *parent, struct browser_window *bw);
/**
+ * set the local history window position.
+ */
+void nsgtk_local_history_set_position(int x, int y);
+
+/**
* hide the local history window from being visible.
*
* \return NSERROR_OK on success else appropriate error code on faliure.
diff --git a/frontends/gtk/login.c b/frontends/gtk/login.c
deleted file mode 100644
index 91d8b37f0..000000000
--- a/frontends/gtk/login.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright 2006 Rob Kendrick <rjek@rjek.com>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <gtk/gtk.h>
-
-#include "utils/log.h"
-#include "utils/nsurl.h"
-#include "netsurf/url_db.h"
-
-#include "gtk/resources.h"
-#include "gtk/login.h"
-
-/** login window session data */
-struct session_401 {
- nsurl *url; /**< URL being fetched */
- lwc_string *host; /**< Host for user display */
- char *realm; /**< Authentication realm */
- nserror (*cb)(bool proceed, void *pw); /**< Continuation callback */
- void *cbpw; /**< Continuation data */
- GtkBuilder *x; /**< Our builder windows */
- GtkWindow *wnd; /**< The login window itself */
- GtkEntry *user; /**< Widget with username */
- GtkEntry *pass; /**< Widget with password */
-};
-
-/**
- * Destroy login window and free all associated resources
- *
- * \param session The login window session to destroy.
- */
-static void destroy_login_window(struct session_401 *session)
-{
- nsurl_unref(session->url);
- lwc_string_unref(session->host);
- free(session->realm);
- gtk_widget_destroy(GTK_WIDGET(session->wnd));
- g_object_unref(G_OBJECT(session->x));
- free(session);
-}
-
-
-/**
- * process next signal in entry widgets.
- *
- * \param w current widget
- * \param data next widget
- */
-static void nsgtk_login_next(GtkWidget *w, gpointer data)
-{
- gtk_widget_grab_focus(GTK_WIDGET(data));
-}
-
-
-/**
- * handler called when navigation is continued
- *
- * \param w current widget
- * \param data login window session
- */
-static void nsgtk_login_ok_clicked(GtkButton *w, gpointer data)
-{
- /* close the window and destroy it, having continued the fetch
- * assoicated with it.
- */
-
- struct session_401 *session = (struct session_401 *)data;
- const gchar *user = gtk_entry_get_text(session->user);
- const gchar *pass = gtk_entry_get_text(session->pass);
- char *auth;
-
- auth = malloc(strlen(user) + strlen(pass) + 2);
- sprintf(auth, "%s:%s", user, pass);
- urldb_set_auth_details(session->url, session->realm, auth);
- free(auth);
-
- session->cb(true, session->cbpw);
-
- destroy_login_window(session);
-}
-
-
-/**
- * handler called when navigation is cancelled
- *
- * \param w widget
- * \param data login window session
- */
-static void nsgtk_login_cancel_clicked(GtkButton *w, gpointer data)
-{
- struct session_401 *session = (struct session_401 *) data;
-
- session->cb(false, session->cbpw);
-
- /* close and destroy the window */
- destroy_login_window(session);
-}
-
-
-/**
- * create a new instance of the login window
- *
- * creates login window and handles to all the widgets we're
- * interested in.
- *
- * \param url The url causing the login.
- * \param host the host being logged into
- * \param realm realmm the login relates to
- * \param cb callback when complete
- * \param cbpw data to pass to callback
- * \return NSERROR_OK on sucessful window creation or error code on faliure.
- */
-static nserror
-create_login_window(nsurl *url,
- lwc_string *host,
- const char *realm,
- nserror (*cb)(bool proceed, void *pw),
- void *cbpw)
-{
- struct session_401 *session;
- GtkWindow *wnd;
- GtkLabel *lhost, *lrealm;
- GtkEntry *euser, *epass;
- GtkButton *bok, *bcan;
- GtkBuilder* builder;
- nserror res;
-
- session = calloc(1, sizeof(struct session_401));
- if (session == NULL) {
- return NSERROR_NOMEM;
- }
-
- res = nsgtk_builder_new_from_resname("login", &builder);
- if (res != NSERROR_OK) {
- free(session);
- return res;
- }
-
- gtk_builder_connect_signals(builder, NULL);
-
- wnd = GTK_WINDOW(gtk_builder_get_object(builder, "wndLogin"));
- lhost = GTK_LABEL(gtk_builder_get_object(builder, "labelLoginHost"));
- lrealm = GTK_LABEL(gtk_builder_get_object(builder, "labelLoginRealm"));
- euser = GTK_ENTRY(gtk_builder_get_object(builder, "entryLoginUser"));
- epass = GTK_ENTRY(gtk_builder_get_object(builder, "entryLoginPass"));
- bok = GTK_BUTTON(gtk_builder_get_object(builder, "buttonLoginOK"));
- bcan = GTK_BUTTON(gtk_builder_get_object(builder, "buttonLoginCan"));
-
- /* create and fill in our session structure */
- session->url = nsurl_ref(url);
- session->host = lwc_string_ref(host);
- session->realm = strdup(realm ? realm : "Secure Area");
- session->cb = cb;
- session->cbpw = cbpw;
- session->x = builder;
- session->wnd = wnd;
- session->user = euser;
- session->pass = epass;
-
- /* fill in our new login window */
-
- gtk_label_set_text(GTK_LABEL(lhost), lwc_string_data(host));
- gtk_label_set_text(lrealm, realm);
- gtk_entry_set_text(euser, "");
- gtk_entry_set_text(epass, "");
-
- /* attach signal handlers to the Login and Cancel buttons in our new
- * window to call functions in this file to process the login
- */
- g_signal_connect(G_OBJECT(bok), "clicked",
- G_CALLBACK(nsgtk_login_ok_clicked), (gpointer)session);
- g_signal_connect(G_OBJECT(bcan), "clicked",
- G_CALLBACK(nsgtk_login_cancel_clicked),
- (gpointer)session);
-
- /* attach signal handlers to the entry boxes such that pressing
- * enter in one progresses the focus onto the next widget.
- */
-
- g_signal_connect(G_OBJECT(euser), "activate",
- G_CALLBACK(nsgtk_login_next), (gpointer)epass);
- g_signal_connect(G_OBJECT(epass), "activate",
- G_CALLBACK(nsgtk_login_next), (gpointer)bok);
-
- /* make sure the username entry box currently has the focus */
- gtk_widget_grab_focus(GTK_WIDGET(euser));
-
- /* finally, show the window */
- gtk_widget_show(GTK_WIDGET(wnd));
-
- return NSERROR_OK;
-}
-
-
-/* exported function documented in gtk/login.h */
-void gui_401login_open(nsurl *url,
- const char *realm,
- nserror (*cb)(bool proceed, void *pw),
- void *cbpw)
-{
- lwc_string *host;
- nserror res;
-
- host = nsurl_get_component(url, NSURL_HOST);
- assert(host != NULL);
-
- res = create_login_window(url, host, realm, cb, cbpw);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Login init failed");
-
- /* creating login failed so cancel navigation */
- cb(false, cbpw);
- }
-
- lwc_string_unref(host);
-}
diff --git a/frontends/gtk/menu.c b/frontends/gtk/menu.c
index 6a6033231..03056d2a8 100644
--- a/frontends/gtk/menu.c
+++ b/frontends/gtk/menu.c
@@ -49,12 +49,12 @@ nsgtk_menu_add_image_item(GtkMenu *menu,
GdkModifierType mod;
GtkWidget *item;
const char *accelerator_desc; /* accelerator key description */
-
+
item = nsgtk_image_menu_item_new_with_mnemonic(messages_get(message));
if (item == NULL) {
return false;
}
-
+
accelerator_desc = nsgtk_accelerator_get_desc(message);
if (accelerator_desc != NULL) {
gtk_accelerator_parse(accelerator_desc, &key, &mod);
@@ -85,15 +85,17 @@ nsgtk_menu_add_image_item(GtkMenu *menu,
#define IMAGE_ITEM(p, q, r, s, t)\
nsgtk_menu_add_image_item(s->p##_menu, &(s->q##_menuitem), #r, t)
-#define CHECK_ITEM(p, q, r, s)\
- s->q##_menuitem = GTK_CHECK_MENU_ITEM(\
+#define CHECK_ITEM(p, q, r, s) \
+ do { \
+ s->q##_menuitem = GTK_CHECK_MENU_ITEM( \
gtk_check_menu_item_new_with_mnemonic(\
messages_get(#r)));\
- if ((s->q##_menuitem != NULL) && (s->p##_menu != NULL)) {\
- gtk_menu_shell_append(GTK_MENU_SHELL(s->p##_menu),\
- GTK_WIDGET(s->q##_menuitem));\
- gtk_widget_show(GTK_WIDGET(s->q##_menuitem));\
- }
+ if ((s->q##_menuitem != NULL) && (s->p##_menu != NULL)) { \
+ gtk_menu_shell_append(GTK_MENU_SHELL(s->p##_menu), \
+ GTK_WIDGET(s->q##_menuitem)); \
+ gtk_widget_show(GTK_WIDGET(s->q##_menuitem)); \
+ } \
+ } while(0)
#define SET_SUBMENU(q, r) \
do { \
@@ -142,21 +144,23 @@ nsgtk_menu_add_image_item(GtkMenu *menu,
static struct nsgtk_export_submenu *
nsgtk_menu_export_submenu(GtkAccelGroup *group)
{
- struct nsgtk_export_submenu *ret = malloc(sizeof(struct
- nsgtk_export_submenu));
+ struct nsgtk_export_submenu *ret;
+ ret = malloc(sizeof(struct nsgtk_export_submenu));
+
if (ret == NULL) {
nsgtk_warning(messages_get("NoMemory"), 0);
return NULL;
}
+
ret->export_menu = GTK_MENU(gtk_menu_new());
if (ret->export_menu == NULL) {
nsgtk_warning(messages_get("NoMemory"), 0);
free(ret);
return NULL;
}
+
+ IMAGE_ITEM(export, savepage, gtkSavePage, ret, group);
IMAGE_ITEM(export, plaintext, gtkPlainText, ret, group);
- IMAGE_ITEM(export, drawfile, gtkDrawFile, ret, group);
- IMAGE_ITEM(export, postscript, gtkPostScript, ret, group);
IMAGE_ITEM(export, pdf, gtkPDF, ret, group);
return ret;
}
@@ -213,57 +217,45 @@ static struct nsgtk_tabs_submenu *nsgtk_menu_tabs_submenu(GtkAccelGroup *group)
return ret;
}
-/**
-* creates an images submenu
-* \param group the 'global' in a gtk sense accelerator reference
-*/
-static struct nsgtk_images_submenu *nsgtk_menu_images_submenu(GtkAccelGroup *group)
+/**
+ * creates a toolbars submenu
+ *
+ * \param group the 'global' in a gtk sense accelerator reference
+ */
+static struct nsgtk_toolbars_submenu *
+nsgtk_menu_toolbars_submenu(GtkAccelGroup *group)
{
- struct nsgtk_images_submenu *ret =
- malloc(sizeof(struct nsgtk_images_submenu));
- if (ret == NULL) {
+ struct nsgtk_toolbars_submenu *tmenu;
+
+ tmenu = malloc(sizeof(struct nsgtk_toolbars_submenu));
+ if (tmenu == NULL) {
nsgtk_warning(messages_get("NoMemory"), 0);
return NULL;
}
- ret->images_menu = GTK_MENU(gtk_menu_new());
- if (ret->images_menu == NULL) {
+
+ tmenu->toolbars_menu = GTK_MENU(gtk_menu_new());
+ if (tmenu->toolbars_menu == NULL) {
nsgtk_warning(messages_get("NoMemory"), 0);
- free(ret);
+ free(tmenu);
return NULL;
}
- CHECK_ITEM(images, foregroundimages, gtkForegroundImages, ret)
- CHECK_ITEM(images, backgroundimages, gtkBackgroundImages, ret)
- return ret;
-}
-
-/**
-* creates a toolbars submenu
-* \param group the 'global' in a gtk sense accelerator reference
-*/
-static struct nsgtk_toolbars_submenu *nsgtk_menu_toolbars_submenu(
- GtkAccelGroup *group)
-{
- struct nsgtk_toolbars_submenu *ret =
- malloc(sizeof(struct nsgtk_toolbars_submenu));
- if (ret == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- return NULL;
+ CHECK_ITEM(toolbars, menubar, gtkMenuBar, tmenu);
+ if (tmenu->menubar_menuitem != NULL) {
+ gtk_check_menu_item_set_active(tmenu->menubar_menuitem, TRUE);
}
- ret->toolbars_menu = GTK_MENU(gtk_menu_new());
- if (ret->toolbars_menu == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- free(ret);
- return NULL;
+
+ CHECK_ITEM(toolbars, toolbar, gtkToolBar, tmenu);
+ if (tmenu->toolbar_menuitem != NULL) {
+ gtk_check_menu_item_set_active(tmenu->toolbar_menuitem, TRUE);
}
- CHECK_ITEM(toolbars, menubar, gtkMenuBar, ret)
- if (ret->menubar_menuitem != NULL)
- gtk_check_menu_item_set_active(ret->menubar_menuitem, TRUE);
- CHECK_ITEM(toolbars, toolbar, gtkToolBar, ret)
- if (ret->toolbar_menuitem != NULL)
- gtk_check_menu_item_set_active(ret->toolbar_menuitem, TRUE);
- return ret;
+
+ ADD_SEP(toolbars, tmenu);
+
+ IMAGE_ITEM(toolbars, customize, gtkCustomize, tmenu, group);
+
+ return tmenu;
}
/**
@@ -271,8 +263,8 @@ static struct nsgtk_toolbars_submenu *nsgtk_menu_toolbars_submenu(
* \param group the 'global' in a gtk sense accelerator reference
*/
-static struct nsgtk_developer_submenu *nsgtk_menu_developer_submenu(
- GtkAccelGroup *group)
+static struct nsgtk_developer_submenu *
+nsgtk_menu_developer_submenu(GtkAccelGroup *group)
{
struct nsgtk_developer_submenu *dmenu =
malloc(sizeof(struct nsgtk_developer_submenu));
@@ -323,7 +315,6 @@ static struct nsgtk_file_menu *nsgtk_menu_file_submenu(GtkAccelGroup *group)
IMAGE_ITEM(file, openfile, gtkOpenFile, fmenu, group);
IMAGE_ITEM(file, closewindow, gtkCloseWindow, fmenu, group);
ADD_SEP(file, fmenu);
- IMAGE_ITEM(file, savepage, gtkSavePage, fmenu, group);
IMAGE_ITEM(file, export, gtkExport, fmenu, group);
ADD_SEP(file, fmenu);
IMAGE_ITEM(file, printpreview, gtkPrintPreview, fmenu, group);
@@ -385,22 +376,16 @@ static struct nsgtk_view_menu *nsgtk_menu_view_submenu(GtkAccelGroup *group)
free(ret);
return NULL;
}
- IMAGE_ITEM(view, stop, gtkStop, ret, group);
- IMAGE_ITEM(view, reload, gtkReload, ret, group);
- ADD_SEP(view, ret);
IMAGE_ITEM(view, scaleview, gtkScaleView, ret, group);
+ SET_SUBMENU(scaleview, ret);
IMAGE_ITEM(view, fullscreen, gtkFullScreen, ret, group);
ADD_SEP(view, ret);
- IMAGE_ITEM(view, images, gtkImages, ret, group);
IMAGE_ITEM(view, toolbars, gtkToolbars, ret, group);
+ SET_SUBMENU(toolbars, ret);
IMAGE_ITEM(view, tabs, gtkTabs, ret, group);
+ SET_SUBMENU(tabs, ret);
ADD_SEP(view, ret);
IMAGE_ITEM(view, savewindowsize, gtkSaveWindowSize, ret, group);
- SET_SUBMENU(scaleview, ret);
- SET_SUBMENU(images, ret);
- SET_SUBMENU(toolbars, ret);
- SET_SUBMENU(tabs, ret);
-
return ret;
}
@@ -426,6 +411,8 @@ static struct nsgtk_nav_menu *nsgtk_menu_nav_submenu(GtkAccelGroup *group)
IMAGE_ITEM(nav, back, gtkBack, ret, group);
IMAGE_ITEM(nav, forward, gtkForward, ret, group);
+ IMAGE_ITEM(nav, stop, gtkStop, ret, group);
+ IMAGE_ITEM(nav, reload, gtkReload, ret, group);
IMAGE_ITEM(nav, home, gtkHome, ret, group);
ADD_SEP(nav, ret);
IMAGE_ITEM(nav, localhistory, gtkLocalHistory, ret, group);
@@ -436,7 +423,6 @@ static struct nsgtk_nav_menu *nsgtk_menu_nav_submenu(GtkAccelGroup *group)
ADD_SEP(nav, ret);
IMAGE_ITEM(nav, openlocation, gtkOpenLocation, ret, group);
-
return ret;
}
@@ -531,44 +517,61 @@ nsgtk_menu_bar_create(GtkMenuShell *menubar, GtkAccelGroup *group)
return nmenu;
}
+
/* exported function documented in gtk/menu.h */
-struct nsgtk_popup_menu *nsgtk_popup_menu_create(GtkAccelGroup *group)
+struct nsgtk_burger_menu *nsgtk_burger_menu_create(GtkAccelGroup *group)
{
- struct nsgtk_popup_menu *nmenu;
+ struct nsgtk_burger_menu *nmenu;
- NEW_MENU(nmenu, popup);
+ NEW_MENU(nmenu, burger);
- IMAGE_ITEM(popup, file, gtkFile, nmenu, group);
+ IMAGE_ITEM(burger, file, gtkFile, nmenu, group);
SET_SUBMENU(file, nmenu);
- IMAGE_ITEM(popup, edit, gtkEdit, nmenu, group);
+ IMAGE_ITEM(burger, edit, gtkEdit, nmenu, group);
SET_SUBMENU(edit, nmenu);
- IMAGE_ITEM(popup, view, gtkView, nmenu, group);
+ IMAGE_ITEM(burger, view, gtkView, nmenu, group);
SET_SUBMENU(view, nmenu);
- IMAGE_ITEM(popup, nav, gtkNavigate, nmenu, group);
+ IMAGE_ITEM(burger, nav, gtkNavigate, nmenu, group);
SET_SUBMENU(nav, nmenu);
- IMAGE_ITEM(popup, tools, gtkTools, nmenu, group);
+ IMAGE_ITEM(burger, tools, gtkTools, nmenu, group);
SET_SUBMENU(tools, nmenu);
- IMAGE_ITEM(popup, help, gtkHelp, nmenu, group);
+ IMAGE_ITEM(burger, help, gtkHelp, nmenu, group);
SET_SUBMENU(help, nmenu);
- ADD_NAMED_SEP(popup, first, nmenu);
+ return nmenu;
+}
- IMAGE_ITEM(popup, back, gtkBack, nmenu, group);
- IMAGE_ITEM(popup, forward, gtkForward, nmenu, group);
- ADD_NAMED_SEP(popup, third, nmenu);
+/* exported function documented in gtk/menu.h */
+struct nsgtk_popup_menu *nsgtk_popup_menu_create(GtkAccelGroup *group)
+{
+ struct nsgtk_popup_menu *nmenu;
+
+ NEW_MENU(nmenu, popup);
+ IMAGE_ITEM(popup, back, gtkBack, nmenu, group);
+ IMAGE_ITEM(popup, forward, gtkForward, nmenu, group);
IMAGE_ITEM(popup, stop, gtkStop, nmenu, group);
IMAGE_ITEM(popup, reload, gtkReload, nmenu, group);
+
+ ADD_NAMED_SEP(popup, first, nmenu);
+
IMAGE_ITEM(popup, cut, gtkCut, nmenu, group);
IMAGE_ITEM(popup, copy, gtkCopy, nmenu, group);
IMAGE_ITEM(popup, paste, gtkPaste, nmenu, group);
- IMAGE_ITEM(popup, customize, gtkCustomize, nmenu, group);
+
+ ADD_NAMED_SEP(popup, second, nmenu);
+
+ IMAGE_ITEM(popup, toolbars, gtkToolbars, nmenu, group);
+ SET_SUBMENU(toolbars, nmenu);
+
+ IMAGE_ITEM(popup, tools, gtkTools, nmenu, group);
+ SET_SUBMENU(tools, nmenu);
return nmenu;
}
@@ -593,3 +596,71 @@ nsgtk_link_menu_create(GtkAccelGroup *group)
return nmenu;
}
+
+
+/* exported function documented in gtk/menu.h */
+nserror nsgtk_menu_bar_destroy(struct nsgtk_bar_submenu *menu)
+{
+ gtk_widget_destroy(GTK_WIDGET(menu->bar_menu));
+
+ free(menu->file_submenu->export_submenu);
+ free(menu->file_submenu);
+ free(menu->edit_submenu);
+ free(menu->view_submenu->tabs_submenu);
+ free(menu->view_submenu->toolbars_submenu);
+ free(menu->view_submenu->scaleview_submenu);
+ free(menu->view_submenu);
+ free(menu->nav_submenu);
+ free(menu->tools_submenu->developer_submenu);
+ free(menu->tools_submenu);
+ free(menu->help_submenu);
+ free(menu);
+
+ return NSERROR_OK;
+}
+
+/* exported function documented in gtk/menu.h */
+nserror nsgtk_burger_menu_destroy(struct nsgtk_burger_menu *menu)
+{
+ gtk_widget_destroy(GTK_WIDGET(menu->burger_menu));
+
+ free(menu->file_submenu->export_submenu);
+ free(menu->file_submenu);
+ free(menu->edit_submenu);
+ free(menu->view_submenu->tabs_submenu);
+ free(menu->view_submenu->toolbars_submenu);
+ free(menu->view_submenu->scaleview_submenu);
+ free(menu->view_submenu);
+ free(menu->nav_submenu);
+ free(menu->tools_submenu->developer_submenu);
+ free(menu->tools_submenu);
+ free(menu->help_submenu);
+ free(menu);
+
+ return NSERROR_OK;
+}
+
+
+/* exported function documented in gtk/menu.h */
+nserror nsgtk_popup_menu_destroy(struct nsgtk_popup_menu *menu)
+{
+ gtk_widget_destroy(GTK_WIDGET(menu->popup_menu));
+
+ free(menu->toolbars_submenu);
+ free(menu->tools_submenu->developer_submenu);
+ free(menu->tools_submenu);
+ free(menu);
+
+ return NSERROR_OK;
+}
+
+
+/* exported function documented in gtk/menu.h */
+nserror nsgtk_link_menu_destroy(struct nsgtk_link_menu *menu)
+{
+ gtk_widget_destroy(GTK_WIDGET(menu->link_menu));
+
+ free(menu);
+
+ return NSERROR_OK;
+}
diff --git a/frontends/gtk/menu.h b/frontends/gtk/menu.h
index 5da5cb1b2..cf63b334a 100644
--- a/frontends/gtk/menu.h
+++ b/frontends/gtk/menu.h
@@ -15,66 +15,68 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_GTK_MENU_H_
-#define _NETSURF_GTK_MENU_H_
+#ifndef NETSURF_GTK_MENU_H_
+#define NETSURF_GTK_MENU_H_
#include <gtk/gtk.h>
+/**
+ * File menu item on menubar
+ */
struct nsgtk_file_menu {
- GtkMenuItem *file; /* File menu item on menubar */
- GtkMenu *file_menu;
- GtkWidget *newwindow_menuitem;
- GtkWidget *newtab_menuitem;
- GtkWidget *openfile_menuitem;
- GtkWidget *closewindow_menuitem;
- GtkWidget *savepage_menuitem;
- GtkWidget *export_menuitem;
- struct nsgtk_export_submenu *export_submenu;
- GtkWidget *printpreview_menuitem;
- GtkWidget *print_menuitem;
- GtkWidget *quit_menuitem;
+ GtkMenuItem *file;
+ GtkMenu *file_menu;
+ GtkWidget *newwindow_menuitem;
+ GtkWidget *newtab_menuitem;
+ GtkWidget *openfile_menuitem;
+ GtkWidget *closewindow_menuitem;
+ GtkWidget *export_menuitem;
+ struct nsgtk_export_submenu *export_submenu;
+ GtkWidget *printpreview_menuitem;
+ GtkWidget *print_menuitem;
+ GtkWidget *quit_menuitem;
};
struct nsgtk_edit_menu {
- GtkMenuItem *edit; /* Edit menu item on menubar */
- GtkMenu *edit_menu;
- GtkWidget *cut_menuitem;
- GtkWidget *copy_menuitem;
- GtkWidget *paste_menuitem;
- GtkWidget *delete_menuitem;
- GtkWidget *selectall_menuitem;
- GtkWidget *find_menuitem;
- GtkWidget *preferences_menuitem;
+ GtkMenuItem *edit; /* Edit menu item on menubar */
+ GtkMenu *edit_menu;
+ GtkWidget *cut_menuitem;
+ GtkWidget *copy_menuitem;
+ GtkWidget *paste_menuitem;
+ GtkWidget *delete_menuitem;
+ GtkWidget *selectall_menuitem;
+ GtkWidget *find_menuitem;
+ GtkWidget *preferences_menuitem;
};
struct nsgtk_view_menu {
- GtkMenuItem *view; /* View menu item on menubar */
- GtkMenu *view_menu; /* gtk menu attached to menu item */
- GtkWidget *stop_menuitem;
- GtkWidget *reload_menuitem;
- GtkWidget *scaleview_menuitem;
+ GtkMenuItem *view; /* View menu item on menubar */
+ GtkMenu *view_menu; /* gtk menu attached to menu item */
+
+ GtkWidget *scaleview_menuitem;
struct nsgtk_scaleview_submenu *scaleview_submenu;
- GtkWidget *fullscreen_menuitem;
- GtkWidget *images_menuitem;
- struct nsgtk_images_submenu *images_submenu;
- GtkWidget *toolbars_menuitem;
- struct nsgtk_toolbars_submenu *toolbars_submenu;
- GtkWidget *tabs_menuitem;
- struct nsgtk_tabs_submenu *tabs_submenu;
- GtkWidget *savewindowsize_menuitem;
+ GtkWidget *fullscreen_menuitem;
+ GtkWidget *toolbars_menuitem;
+ struct nsgtk_toolbars_submenu *toolbars_submenu;
+ GtkWidget *tabs_menuitem;
+ struct nsgtk_tabs_submenu *tabs_submenu;
+ GtkWidget *savewindowsize_menuitem;
};
struct nsgtk_nav_menu {
- GtkMenuItem *nav; /* Nav menu item on menubar */
- GtkMenu *nav_menu;
- GtkWidget *back_menuitem;
- GtkWidget *forward_menuitem;
- GtkWidget *home_menuitem;
- GtkWidget *localhistory_menuitem;
- GtkWidget *globalhistory_menuitem;
- GtkWidget *addbookmarks_menuitem;
- GtkWidget *showbookmarks_menuitem;
- GtkWidget *openlocation_menuitem;
+ GtkMenuItem *nav; /* Nav menu item on menubar */
+ GtkMenu *nav_menu;
+
+ GtkWidget *back_menuitem;
+ GtkWidget *forward_menuitem;
+ GtkWidget *stop_menuitem;
+ GtkWidget *reload_menuitem;
+ GtkWidget *home_menuitem;
+ GtkWidget *localhistory_menuitem;
+ GtkWidget *globalhistory_menuitem;
+ GtkWidget *addbookmarks_menuitem;
+ GtkWidget *showbookmarks_menuitem;
+ GtkWidget *openlocation_menuitem;
};
struct nsgtk_tools_menu {
@@ -88,47 +90,41 @@ struct nsgtk_tools_menu {
};
struct nsgtk_help_menu {
- GtkMenuItem *help; /* Help menu item on menubar */
- GtkMenu *help_menu;
- GtkWidget *contents_menuitem;
- GtkWidget *guide_menuitem;
- GtkWidget *info_menuitem;
- GtkWidget *about_menuitem;
+ GtkMenuItem *help; /* Help menu item on menubar */
+ GtkMenu *help_menu;
+ GtkWidget *contents_menuitem;
+ GtkWidget *guide_menuitem;
+ GtkWidget *info_menuitem;
+ GtkWidget *about_menuitem;
};
struct nsgtk_export_submenu {
- GtkMenu *export_menu;
- GtkWidget *plaintext_menuitem;
- GtkWidget *drawfile_menuitem;
- GtkWidget *postscript_menuitem;
- GtkWidget *pdf_menuitem;
+ GtkMenu *export_menu;
+ GtkWidget *savepage_menuitem;
+ GtkWidget *plaintext_menuitem;
+ GtkWidget *pdf_menuitem;
};
struct nsgtk_scaleview_submenu {
- GtkMenu *scaleview_menu;
- GtkWidget *zoomplus_menuitem;
- GtkWidget *zoomminus_menuitem;
- GtkWidget *zoomnormal_menuitem;
+ GtkMenu *scaleview_menu;
+ GtkWidget *zoomplus_menuitem;
+ GtkWidget *zoomminus_menuitem;
+ GtkWidget *zoomnormal_menuitem;
};
struct nsgtk_tabs_submenu {
- GtkMenu *tabs_menu;
- GtkWidget *nexttab_menuitem;
- GtkWidget *prevtab_menuitem;
- GtkWidget *closetab_menuitem;
-};
-
-struct nsgtk_images_submenu {
- GtkMenu *images_menu;
- GtkCheckMenuItem *foregroundimages_menuitem;
- GtkCheckMenuItem *backgroundimages_menuitem;
+ GtkMenu *tabs_menu;
+ GtkWidget *nexttab_menuitem;
+ GtkWidget *prevtab_menuitem;
+ GtkWidget *closetab_menuitem;
};
struct nsgtk_toolbars_submenu {
- GtkMenu *toolbars_menu;
- GtkCheckMenuItem *menubar_menuitem;
- GtkCheckMenuItem *toolbar_menuitem;
+ GtkMenu *toolbars_menu;
+ GtkCheckMenuItem *menubar_menuitem;
+ GtkCheckMenuItem *toolbar_menuitem;
+ GtkWidget *customize_menuitem;
};
struct nsgtk_developer_submenu {
@@ -140,20 +136,21 @@ struct nsgtk_developer_submenu {
GtkWidget *debugdomtree_menuitem;
};
-
+/**
+ * main menubar
+ */
struct nsgtk_bar_submenu {
GtkMenuBar *bar_menu;
struct nsgtk_file_menu *file_submenu;
struct nsgtk_edit_menu *edit_submenu;
struct nsgtk_view_menu *view_submenu;
struct nsgtk_nav_menu *nav_submenu;
- struct nsgtk_tabs_submenu *tabs_submenu;
struct nsgtk_tools_menu *tools_submenu;
struct nsgtk_help_menu *help_submenu;
};
-struct nsgtk_popup_menu {
- GtkMenu *popup_menu;
+struct nsgtk_burger_menu {
+ GtkMenu *burger_menu;
GtkWidget *file_menuitem;
struct nsgtk_file_menu *file_submenu;
@@ -167,32 +164,35 @@ struct nsgtk_popup_menu {
GtkWidget *nav_menuitem;
struct nsgtk_nav_menu *nav_submenu;
- GtkWidget *tabs_menuitem;
- struct nsgtk_tabs_submenu *tabs_submenu;
-
GtkWidget *tools_menuitem;
struct nsgtk_tools_menu *tools_submenu;
GtkWidget *help_menuitem;
struct nsgtk_help_menu *help_submenu;
+};
- GtkWidget *first_separator;
+struct nsgtk_popup_menu {
+ GtkMenu *popup_menu;
/* navigation entries */
GtkWidget *back_menuitem;
GtkWidget *forward_menuitem;
-
- GtkWidget *third_separator;
-
- /* view entries */
GtkWidget *stop_menuitem;
GtkWidget *reload_menuitem;
+ GtkWidget *first_separator;
+
+ /* edit entries */
GtkWidget *cut_menuitem;
GtkWidget *copy_menuitem;
GtkWidget *paste_menuitem;
- GtkWidget *customize_menuitem;
+ GtkWidget *second_separator;
+
+ GtkWidget *toolbars_menuitem;
+ struct nsgtk_toolbars_submenu *toolbars_submenu;
+ GtkWidget *tools_menuitem;
+ struct nsgtk_tools_menu *tools_submenu;
};
struct nsgtk_link_menu {
@@ -206,22 +206,82 @@ struct nsgtk_link_menu {
GtkWidget *copy_menuitem;
};
+
/**
- * Create main menu bar.
+ * Create main menubar menu.
*/
struct nsgtk_bar_submenu *nsgtk_menu_bar_create(GtkMenuShell *menubar, GtkAccelGroup *group);
+
+/**
+ * Generate burger menu.
+ *
+ * \param accelerator group to use with menu
+ * \return new menu structure or NULL on error
+ */
+struct nsgtk_burger_menu *nsgtk_burger_menu_create(GtkAccelGroup *group);
+
+
/**
- * Generate right click menu menu.
+ * Generate right click popup menu.
*
+ * \param accelerator group to use with menu
+ * \return new menu structure or NULL on error
*/
struct nsgtk_popup_menu *nsgtk_popup_menu_create(GtkAccelGroup *group);
+
/**
- * Generate context sensitive popup menu for link.
+ * Generate context sensitive link popup menu.
*
+ * \param accelerator group to use with menu
+ * \return new menu structure or NULL on error
*/
struct nsgtk_link_menu *nsgtk_link_menu_create(GtkAccelGroup *group);
+/**
+ * destroy bar menu
+ *
+ * destroys the gtk widgets associated with menu and frees all storage.
+ *
+ * \param menu menu to destroy
+ * \return NSERROR_OK and menu destroyed on success else error code
+ */
+nserror nsgtk_menu_bar_destroy(struct nsgtk_bar_submenu *menu);
+
+
+/**
+ * destroy burger menu
+ *
+ * destroys the gtk widgets associated with menu and frees all storage.
+ *
+ * \param menu menu to destroy
+ * \return NSERROR_OK and menu destroyed on success else error code
+ */
+nserror nsgtk_burger_menu_destroy(struct nsgtk_burger_menu *menu);
+
+
+/**
+ * destroy popup menu
+ *
+ * destroys the gtk widgets associated with menu and frees all storage.
+ *
+ * \param menu menu to destroy
+ * \return NSERROR_OK and menu destroyed on success else error code
+ */
+nserror nsgtk_popup_menu_destroy(struct nsgtk_popup_menu *menu);
+
+
+/**
+ * destroy link menu
+ *
+ * destroys the gtk widgets associated with menu and frees all storage.
+ *
+ * \param menu menu to destroy
+ * \return NSERROR_OK and menu destroyed on success else error code
+ */
+nserror nsgtk_link_menu_destroy(struct nsgtk_link_menu *menu);
+
+
#endif
diff --git a/frontends/gtk/misc.c b/frontends/gtk/misc.c
new file mode 100644
index 000000000..8ab1d914c
--- /dev/null
+++ b/frontends/gtk/misc.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2021 Vincemt Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of netsurf miscellaneous operations table
+ */
+
+#include <string.h>
+#include <stdbool.h>
+#include <gtk/gtk.h>
+
+#include "utils/config.h"
+#include "utils/errors.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/nsurl.h"
+#include "netsurf/misc.h"
+#include "desktop/save_pdf.h"
+
+#include "gtk/compat.h"
+#include "gtk/warn.h"
+#include "gtk/schedule.h"
+#include "gtk/resources.h"
+#include "gtk/cookies.h"
+#include "gtk/misc.h"
+
+
+static nserror gui_launch_url(struct nsurl *url)
+{
+ gboolean ok;
+ GError *error = NULL;
+
+ ok = nsgtk_show_uri(NULL, nsurl_access(url), GDK_CURRENT_TIME, &error);
+ if (ok == TRUE) {
+ return NSERROR_OK;
+ }
+
+ if (error) {
+ nsgtk_warning(messages_get("URIOpenError"), error->message);
+ g_error_free(error);
+ }
+ return NSERROR_NO_FETCH_HANDLER;
+}
+
+static void nsgtk_PDF_set_pass(GtkButton *w, gpointer data)
+{
+ char **owner_pass = ((void **)data)[0];
+ char **user_pass = ((void **)data)[1];
+ GtkWindow *wnd = ((void **)data)[2];
+ GtkBuilder *password_builder = ((void **)data)[3];
+ char *path = ((void **)data)[4];
+
+ char *op, *op1;
+ char *up, *up1;
+
+ op = strdup(gtk_entry_get_text(
+ GTK_ENTRY(gtk_builder_get_object(password_builder,
+ "entryPDFOwnerPassword"))));
+ op1 = strdup(gtk_entry_get_text(
+ GTK_ENTRY(gtk_builder_get_object(password_builder,
+ "entryPDFOwnerPassword1"))));
+ up = strdup(gtk_entry_get_text(
+ GTK_ENTRY(gtk_builder_get_object(password_builder,
+ "entryPDFUserPassword"))));
+ up1 = strdup(gtk_entry_get_text(
+ GTK_ENTRY(gtk_builder_get_object(password_builder,
+ "entryPDFUserPassword1"))));
+
+
+ if (op[0] == '\0') {
+ gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
+ "labelInfo")),
+ "Owner password must be at least 1 character long:");
+ free(op);
+ free(up);
+ } else if (!strcmp(op, up)) {
+ gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
+ "labelInfo")),
+ "User and owner passwords must be different:");
+ free(op);
+ free(up);
+ } else if (!strcmp(op, op1) && !strcmp(up, up1)) {
+
+ *owner_pass = op;
+ if (up[0] == '\0')
+ free(up);
+ else
+ *user_pass = up;
+
+ free(data);
+ gtk_widget_destroy(GTK_WIDGET(wnd));
+ g_object_unref(G_OBJECT(password_builder));
+
+ save_pdf(path);
+
+ free(path);
+ } else {
+ gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
+ "labelInfo")), "Passwords not confirmed:");
+ free(op);
+ free(up);
+ }
+
+ free(op1);
+ free(up1);
+}
+
+static void nsgtk_PDF_no_pass(GtkButton *w, gpointer data)
+{
+ GtkWindow *wnd = ((void **)data)[2];
+ GtkBuilder *password_builder = ((void **)data)[3];
+ char *path = ((void **)data)[4];
+
+ free(data);
+
+ gtk_widget_destroy(GTK_WIDGET(wnd));
+ g_object_unref(G_OBJECT(password_builder));
+
+ save_pdf(path);
+
+ free(path);
+}
+
+static void nsgtk_pdf_password(char **owner_pass, char **user_pass, char *path)
+{
+ GtkButton *ok, *no;
+ GtkWindow *wnd;
+ void **data;
+ GtkBuilder *password_builder;
+ nserror res;
+
+ res = nsgtk_builder_new_from_resname("password", &password_builder);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Password UI builder init failed");
+ return;
+ }
+
+ gtk_builder_connect_signals(password_builder, NULL);
+
+ wnd = GTK_WINDOW(gtk_builder_get_object(password_builder,
+ "wndPDFPassword"));
+
+ data = malloc(5 * sizeof(void *));
+
+ *owner_pass = NULL;
+ *user_pass = NULL;
+
+ data[0] = owner_pass;
+ data[1] = user_pass;
+ data[2] = wnd;
+ data[3] = password_builder;
+ data[4] = path;
+
+ ok = GTK_BUTTON(gtk_builder_get_object(password_builder,
+ "buttonPDFSetPassword"));
+ no = GTK_BUTTON(gtk_builder_get_object(password_builder,
+ "buttonPDFNoPassword"));
+
+ g_signal_connect(G_OBJECT(ok), "clicked",
+ G_CALLBACK(nsgtk_PDF_set_pass), (gpointer)data);
+ g_signal_connect(G_OBJECT(no), "clicked",
+ G_CALLBACK(nsgtk_PDF_no_pass), (gpointer)data);
+
+ gtk_widget_show(GTK_WIDGET(wnd));
+}
+
+
+static struct gui_misc_table misc_table = {
+ .schedule = nsgtk_schedule,
+
+ .launch_url = gui_launch_url,
+ .pdf_password = nsgtk_pdf_password,
+ .present_cookies = nsgtk_cookies_present,
+};
+
+struct gui_misc_table *nsgtk_misc_table = &misc_table;
diff --git a/frontends/windows/filetype.h b/frontends/gtk/misc.h
index f71a0b2da..3a02c2254 100644
--- a/frontends/windows/filetype.h
+++ b/frontends/gtk/misc.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Vincent Sanders <vince@netsurf-browser.org>
+ * Copyright 2021 Vincemt Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,9 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_WINDOWS_FILETYPE_H_
-#define _NETSURF_WINDOWS_FILETYPE_H_
+#ifndef NETSURF_GTK_MISC_H
+#define NETSURF_GTK_MISC_H 1
-struct gui_fetch_table *win32_fetch_table;
+extern struct gui_misc_table *nsgtk_misc_table;
#endif
diff --git a/frontends/gtk/options.h b/frontends/gtk/options.h
index 018a448be..7fd79d7c5 100644
--- a/frontends/gtk/options.h
+++ b/frontends/gtk/options.h
@@ -16,16 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_GTK_OPTIONS_H_
-#define _NETSURF_GTK_OPTIONS_H_
+#ifndef NETSURF_GTK_OPTIONS_H_
+#define NETSURF_GTK_OPTIONS_H_
/* currently nothing here */
#endif
-/* High quality image scaling */
-NSOPTION_BOOL(render_resample, true)
-
/* clear downloads */
NSOPTION_BOOL(downloads_clear, false)
@@ -47,9 +44,6 @@ NSOPTION_INTEGER(button_type, 0)
/* disallow popup windows */
NSOPTION_BOOL(disable_popups, false)
-/* disable content plugins */
-NSOPTION_BOOL(disable_plugins, false)
-
/* number of days to keep history data */
NSOPTION_INTEGER(history_age, 0)
@@ -72,4 +66,7 @@ NSOPTION_INTEGER(developer_view, 0)
NSOPTION_INTEGER(position_tab, 0)
/* Toolbar customisation */
-NSOPTION_STRING(toolbar_order, NULL)
+NSOPTION_STRING(toolbar_items, NULL)
+
+/* The menu and tool bars that are shown */
+NSOPTION_STRING(bar_show, NULL)
diff --git a/frontends/gtk/page_info.c b/frontends/gtk/page_info.c
new file mode 100644
index 000000000..0d76a2f71
--- /dev/null
+++ b/frontends/gtk/page_info.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2015 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of gtk certificate viewing using gtk core windows.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <gtk/gtk.h>
+
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "netsurf/keypress.h"
+#include "netsurf/plotters.h"
+#include "netsurf/misc.h"
+#include "netsurf/browser_window.h"
+#include "desktop/page-info.h"
+#include "desktop/gui_internal.h"
+
+#include "gtk/plotters.h"
+#include "gtk/scaffolding.h"
+#include "gtk/resources.h"
+#include "gtk/page_info.h"
+#include "gtk/corewindow.h"
+
+
+/**
+ * GTK certificate viewing window context
+ */
+struct nsgtk_pi_window {
+ /** GTK core window context */
+ struct nsgtk_corewindow core;
+ /** GTK builder for window */
+ GtkBuilder *builder;
+ /** GTK window being shown */
+ GtkWindow *dlg;
+ /** Core page-info window */
+ struct page_info *pi;
+};
+
+
+/**
+ * destroy a previously created page information window
+ */
+static gboolean
+nsgtk_pi_delete_event(GtkWidget *w, GdkEvent *event, gpointer data)
+{
+ struct nsgtk_pi_window *pi_win;
+ pi_win = (struct nsgtk_pi_window *)data;
+
+ page_info_destroy(pi_win->pi);
+
+ nsgtk_corewindow_fini(&pi_win->core);
+ gtk_widget_destroy(GTK_WIDGET(pi_win->dlg));
+ g_object_unref(G_OBJECT(pi_win->builder));
+ free(pi_win);
+
+ return FALSE;
+}
+
+/**
+ * Called to cause the page-info window to close cleanly
+ */
+static void
+nsgtk_pi_close_callback(void *pw)
+{
+ nsgtk_pi_delete_event(NULL, NULL, pw);
+}
+
+/**
+ * callback for mouse action for certificate verify on core window
+ *
+ * \param nsgtk_cw The nsgtk core window structure.
+ * \param mouse_state netsurf mouse state on event
+ * \param x location of event
+ * \param y location of event
+ * \return NSERROR_OK on success otherwise appropriate error code
+ */
+static nserror
+nsgtk_pi_mouse(struct nsgtk_corewindow *nsgtk_cw,
+ browser_mouse_state mouse_state,
+ int x, int y)
+{
+ struct nsgtk_pi_window *pi_win;
+ bool did_something = false;
+ /* technically degenerate container of */
+ pi_win = (struct nsgtk_pi_window *)nsgtk_cw;
+
+ if (page_info_mouse_action(pi_win->pi, mouse_state, x, y, &did_something) == NSERROR_OK) {
+ if (did_something == true) {
+ /* Something happened so we need to close ourselves */
+ guit->misc->schedule(0, nsgtk_pi_close_callback, pi_win);
+ }
+ }
+
+ return NSERROR_OK;
+}
+
+/**
+ * callback for keypress for certificate verify on core window
+ *
+ * \param nsgtk_cw The nsgtk core window structure.
+ * \param nskey The netsurf key code
+ * \return NSERROR_OK on success otherwise appropriate error code
+ */
+static nserror
+nsgtk_pi_key(struct nsgtk_corewindow *nsgtk_cw, uint32_t nskey)
+{
+ struct nsgtk_pi_window *pi_win;
+
+ /* technically degenerate container of */
+ pi_win = (struct nsgtk_pi_window *)nsgtk_cw;
+
+ if (page_info_keypress(pi_win->pi, nskey)) {
+ return NSERROR_OK;
+ }
+ return NSERROR_NOT_IMPLEMENTED;
+}
+
+/**
+ * callback on draw event for certificate verify on core window
+ *
+ * \param nsgtk_cw The nsgtk core window structure.
+ * \param r The rectangle of the window that needs updating.
+ * \return NSERROR_OK on success otherwise appropriate error code
+ */
+static nserror
+nsgtk_pi_draw(struct nsgtk_corewindow *nsgtk_cw, struct rect *r)
+{
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &nsgtk_plotters
+ };
+ struct nsgtk_pi_window *pi_win;
+
+ /* technically degenerate container of */
+ pi_win = (struct nsgtk_pi_window *)nsgtk_cw;
+
+ page_info_redraw(pi_win->pi, 0, 0, r, &ctx);
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in gtk/page_info.h */
+nserror nsgtk_page_info(struct browser_window *bw)
+{
+ struct nsgtk_pi_window *ncwin;
+ nserror res;
+ GtkWindow *scaffwin = nsgtk_scaffolding_window(nsgtk_current_scaffolding());
+
+ ncwin = calloc(1, sizeof(struct nsgtk_pi_window));
+ if (ncwin == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ res = nsgtk_builder_new_from_resname("pageinfo", &ncwin->builder);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, CRITICAL, "Page Info UI builder init failed %s", messages_get_errorcode(res));
+ free(ncwin);
+ return res;
+ }
+
+ gtk_builder_connect_signals(ncwin->builder, NULL);
+
+ ncwin->dlg = GTK_WINDOW(gtk_builder_get_object(ncwin->builder,
+ "PGIWindow"));
+
+ /* Configure for transient behaviour */
+ gtk_window_set_type_hint(GTK_WINDOW(ncwin->dlg),
+ GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU);
+
+ gtk_window_set_modal(GTK_WINDOW(ncwin->dlg), TRUE);
+
+ gtk_window_group_add_window(gtk_window_get_group(scaffwin),
+ GTK_WINDOW(ncwin->dlg));
+
+ gtk_window_set_transient_for(GTK_WINDOW(ncwin->dlg), scaffwin);
+
+ gtk_window_set_screen(GTK_WINDOW(ncwin->dlg),
+ gtk_widget_get_screen(GTK_WIDGET(scaffwin)));
+
+ /* Attempt to place the window in the right place */
+ nsgtk_scaffolding_position_page_info(nsgtk_current_scaffolding(),
+ ncwin);
+
+ ncwin->core.drawing_area = GTK_DRAWING_AREA(
+ gtk_builder_get_object(ncwin->builder, "PGIDrawingArea"));
+
+ /* make the delete event call our destructor */
+ g_signal_connect(G_OBJECT(ncwin->dlg),
+ "delete_event",
+ G_CALLBACK(nsgtk_pi_delete_event),
+ ncwin);
+ /* Ditto if we lose the grab */
+ g_signal_connect(G_OBJECT(ncwin->dlg),
+ "grab-broken-event",
+ G_CALLBACK(nsgtk_pi_delete_event),
+ ncwin);
+ /* Handle button press events */
+ g_signal_connect(G_OBJECT(ncwin->dlg),
+ "button-press-event",
+ G_CALLBACK(nsgtk_pi_delete_event),
+ ncwin);
+
+ /* initialise GTK core window */
+ ncwin->core.draw = nsgtk_pi_draw;
+ ncwin->core.key = nsgtk_pi_key;
+ ncwin->core.mouse = nsgtk_pi_mouse;
+
+ res = nsgtk_corewindow_init(&ncwin->core);
+ if (res != NSERROR_OK) {
+ g_object_unref(G_OBJECT(ncwin->dlg));
+ free(ncwin);
+ return res;
+ }
+
+ res = page_info_create(ncwin->core.cb_table,
+ (struct core_window *)ncwin,
+ bw, &ncwin->pi);
+ if (res != NSERROR_OK) {
+ g_object_unref(G_OBJECT(ncwin->dlg));
+ free(ncwin);
+ return res;
+ }
+
+ gtk_widget_show(GTK_WIDGET(ncwin->dlg));
+
+ gtk_widget_grab_focus(GTK_WIDGET(ncwin->dlg));
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in gtk/page_info.h */
+void
+nsgtk_page_info_set_position(struct nsgtk_pi_window *win, int x, int y)
+{
+ NSLOG(netsurf, INFO, "win=%p x=%d y=%d", win, x, y);
+
+ gtk_window_move(GTK_WINDOW(win->dlg), x, y);
+}
diff --git a/frontends/gtk/ssl_cert.h b/frontends/gtk/page_info.h
index 1712756e9..23e1e348c 100644
--- a/frontends/gtk/ssl_cert.h
+++ b/frontends/gtk/page_info.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2019 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,22 +16,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef NETSURF_GTK_SSL_CERT_H
-#define NETSURF_GTK_SSL_CERT_H 1
-
-struct nsurl;
-struct ssl_cert_info;
+#ifndef NETSURF_GTK_PAGE_INFO_H
+#define NETSURF_GTK_PAGE_INFO_H 1
/**
- * Prompt the user to verify a certificate with issuse.
+ * Page information window
*
- * \param url The URL being verified.
- * \param certs The certificate to be verified
- * \param num The number of certificates to be verified.
- * \param cb Callback upon user decision.
- * \param cbpw Context pointer passed to cb
+ * \param bw the browser window to get page information for
* \return NSERROR_OK or error code if prompt creation failed.
*/
-nserror gtk_cert_verify(struct nsurl *url, const struct ssl_cert_info *certs, unsigned long num, nserror (*cb)(bool proceed, void *pw), void *cbpw);
+nserror nsgtk_page_info(struct browser_window *bw);
+
+/**
+ * Position the given page information window at the given
+ * coordinates.
+ *
+ * \param pi the page info window to position
+ * \param x the X coordinate for the top left of the window
+ * \param y the Y coordinate for the top left of the window
+ */
+void nsgtk_page_info_set_position(struct nsgtk_pi_window *pi, int x, int y);
#endif
diff --git a/frontends/gtk/plotters.c b/frontends/gtk/plotters.c
index 88e7760c6..110dcffc5 100644
--- a/frontends/gtk/plotters.c
+++ b/frontends/gtk/plotters.c
@@ -89,6 +89,20 @@ static inline void nsgtk_set_dashed(void)
/**
+ * Set cairo context line width.
+ */
+static inline void nsgtk_set_line_width(plot_style_fixed width)
+{
+ if (width == 0) {
+ cairo_set_line_width(current_cr, 1);
+ } else {
+ cairo_set_line_width(current_cr,
+ plot_style_fixed_to_double(width));
+ }
+}
+
+
+/**
* \brief Sets a clip rectangle for subsequent plot operations.
*
* \param ctx The current redraw context.
@@ -191,10 +205,7 @@ nsgtk_plot_disc(const struct redraw_context *ctx,
break;
}
- if (style->stroke_width == 0)
- cairo_set_line_width(current_cr, 1);
- else
- cairo_set_line_width(current_cr, style->stroke_width);
+ nsgtk_set_line_width(style->stroke_width);
cairo_arc(current_cr, x, y, radius, 0, M_PI * 2);
@@ -242,10 +253,7 @@ nsgtk_plot_line(const struct redraw_context *ctx,
nsgtk_set_colour(style->stroke_colour);
}
- if (style->stroke_width == 0)
- cairo_set_line_width(current_cr, 1);
- else
- cairo_set_line_width(current_cr, style->stroke_width);
+ nsgtk_set_line_width(style->stroke_width);
/* core expects horizontal and vertical lines to be on pixels, not
* between pixels
@@ -331,10 +339,7 @@ nsgtk_plot_rectangle(const struct redraw_context *ctx,
break;
}
- if (style->stroke_width == 0)
- cairo_set_line_width(current_cr, 1);
- else
- cairo_set_line_width(current_cr, style->stroke_width);
+ nsgtk_set_line_width(style->stroke_width);
cairo_rectangle(current_cr,
rect->x0 + 0.5,
@@ -394,7 +399,6 @@ nsgtk_plot_polygon(const struct redraw_context *ctx,
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
- * \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
@@ -403,7 +407,6 @@ nsgtk_plot_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
- float width,
const float transform[6])
{
unsigned int i;
@@ -421,7 +424,7 @@ nsgtk_plot_path(const struct redraw_context *ctx,
cairo_get_matrix(current_cr, &old_ctm);
/* Set up line style and width */
- cairo_set_line_width(current_cr, 1);
+ nsgtk_set_line_width(pstyle->stroke_width);
nsgtk_set_solid();
/* Load new CTM */
@@ -429,8 +432,8 @@ nsgtk_plot_path(const struct redraw_context *ctx,
n_ctm.yx = transform[1];
n_ctm.xy = transform[2];
n_ctm.yy = transform[3];
- n_ctm.x0 = transform[4];
- n_ctm.y0 = transform[5];
+ n_ctm.x0 = transform[4] + old_ctm.x0;
+ n_ctm.y0 = transform[5] + old_ctm.y0;
cairo_set_matrix(current_cr, &n_ctm);
diff --git a/frontends/gtk/preferences.c b/frontends/gtk/preferences.c
index 65f41ed27..a44e7241e 100644
--- a/frontends/gtk/preferences.c
+++ b/frontends/gtk/preferences.c
@@ -30,6 +30,7 @@
#include "desktop/searchweb.h"
#include "gtk/compat.h"
+#include "gtk/toolbar_items.h"
#include "gtk/window.h"
#include "gtk/gui.h"
#include "gtk/scaffolding.h"
@@ -411,12 +412,6 @@ TOGGLEBUTTON_SIGNALS(checkHideAdverts, block_advertisements)
/* enable javascript */
TOGGLEBUTTON_SIGNALS(checkEnableJavascript, enable_javascript)
-/* disable plugins */
-TOGGLEBUTTON_SIGNALS(checkDisablePlugins, disable_plugins)
-
-/* high quality image scaling */
-TOGGLEBUTTON_SIGNALS(checkResampleImages, render_resample)
-
/* load and display of images */
G_MODULE_EXPORT void
nsgtk_preferences_comboboxLoadImages_changed(GtkComboBox *combo,
@@ -480,9 +475,6 @@ nsgtk_preferences_comboboxLoadImages_realize(GtkWidget *widget,
/* enable animation */
TOGGLEBUTTON_SIGNALS(checkEnableAnimations, animate_images)
-/* frame time */
-SPINBUTTON_SIGNALS(spinAnimationSpeed, minimum_gif_delay, 100.0)
-
/* Fonts */
/* default font */
@@ -511,7 +503,7 @@ SPINBUTTON_SIGNALS(spinDefaultSize, font_size, 10.0)
G_MODULE_EXPORT void
nsgtk_preferences_fontPreview_clicked(GtkButton *button, struct ppref *priv)
{
- nsgtk_reflow_all_windows();
+ nsgtk_window_update_all();
}
@@ -713,7 +705,7 @@ nsgtk_preferences_checkShowSingleTab_toggled(GtkToggleButton *togglebutton,
{
nsoption_set_bool(show_single_tab,
gtk_toggle_button_get_active(togglebutton));
- nsgtk_reflow_all_windows();
+ nsgtk_window_update_all();
}
G_MODULE_EXPORT void
@@ -735,20 +727,11 @@ G_MODULE_EXPORT void
nsgtk_preferences_comboTabPosition_changed(GtkComboBox *widget,
struct ppref *priv)
{
- struct nsgtk_scaffolding *current;
-
/* set the option */
nsoption_set_int(position_tab, gtk_combo_box_get_active(widget));
- /* update all notebooks in all scaffolds */
- current = nsgtk_scaffolding_iterate(NULL);
- while (current) {
- nsgtk_scaffolding_reset_offset(current);
-
- nsgtk_reflow_all_windows();
-
- current = nsgtk_scaffolding_iterate(current);
- }
+ /* update all windows */
+ nsgtk_window_update_all();
}
G_MODULE_EXPORT void
@@ -791,18 +774,10 @@ G_MODULE_EXPORT void
nsgtk_preferences_comboButtonType_changed(GtkComboBox *widget,
struct ppref *priv)
{
- struct nsgtk_scaffolding *current;
-
nsoption_set_int(button_type, gtk_combo_box_get_active(widget) + 1);
- current = nsgtk_scaffolding_iterate(NULL);
- while (current != NULL) {
- nsgtk_scaffolding_reset_offset(current);
-
- nsgtk_scaffolding_toolbars(current, nsoption_int(button_type));
-
- current = nsgtk_scaffolding_iterate(current);
- }
+ /* update all windows to adopt change */
+ nsgtk_window_update_all();
}
G_MODULE_EXPORT void
@@ -826,7 +801,7 @@ ENTRY_SIGNALS(entryHomePageURL, homepage_url)
G_MODULE_EXPORT void
nsgtk_preferences_setCurrentPage_clicked(GtkButton *button, struct ppref *priv)
{
- const gchar *url = nsurl_access(browser_window_get_url(priv->bw));
+ const gchar *url = nsurl_access(browser_window_access_url(priv->bw));
if (priv->entryHomePageURL != NULL) {
gtk_entry_set_text(GTK_ENTRY(priv->entryHomePageURL), url);
diff --git a/frontends/gtk/print.c b/frontends/gtk/print.c
index 8f71230a6..c4f1b0f7a 100644
--- a/frontends/gtk/print.c
+++ b/frontends/gtk/print.c
@@ -133,6 +133,17 @@ static inline void nsgtk_print_set_dashed(void)
cairo_set_dash(gtk_print_current_cr, cdashes, 1, 0);
}
+/** Set cairo context line width. */
+static inline void nsgtk_set_line_width(plot_style_fixed width)
+{
+ if (width == 0) {
+ cairo_set_line_width(gtk_print_current_cr, 1);
+ } else {
+ cairo_set_line_width(gtk_print_current_cr,
+ plot_style_fixed_to_double(width));
+ }
+}
+
/**
* \brief Sets a clip rectangle for subsequent plot operations.
@@ -248,10 +259,7 @@ nsgtk_print_plot_disc(const struct redraw_context *ctx,
break;
}
- if (style->stroke_width == 0)
- cairo_set_line_width(gtk_print_current_cr, 1);
- else
- cairo_set_line_width(gtk_print_current_cr, style->stroke_width);
+ nsgtk_set_line_width(style->stroke_width);
cairo_arc(gtk_print_current_cr, x, y, radius, 0, M_PI * 2);
@@ -294,10 +302,7 @@ nsgtk_print_plot_line(const struct redraw_context *ctx,
break;
}
- if (style->stroke_width == 0)
- cairo_set_line_width(gtk_print_current_cr, 1);
- else
- cairo_set_line_width(gtk_print_current_cr, style->stroke_width);
+ nsgtk_set_line_width(style->stroke_width);
cairo_move_to(gtk_print_current_cr, line->x0 + 0.5, line->y0 + 0.5);
cairo_line_to(gtk_print_current_cr, line->x1 + 0.5, line->y1 + 0.5);
@@ -350,13 +355,6 @@ nsgtk_print_plot_rectangle(const struct redraw_context *ctx,
}
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
- int stroke_width;
-
- /* ensure minimum stroke width */
- stroke_width = style->stroke_width;
- if (stroke_width == 0) {
- stroke_width = 1;
- }
nsgtk_print_set_colour(style->stroke_colour);
@@ -375,7 +373,7 @@ nsgtk_print_plot_rectangle(const struct redraw_context *ctx,
break;
}
- cairo_set_line_width(gtk_print_current_cr, stroke_width);
+ nsgtk_set_line_width(style->stroke_width);
cairo_rectangle(gtk_print_current_cr,
rect->x0, rect->y0,
@@ -429,7 +427,6 @@ nsgtk_print_plot_polygon(const struct redraw_context *ctx,
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
- * \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
@@ -438,7 +435,6 @@ nsgtk_print_plot_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
- float width,
const float transform[6])
{
/* Only the internal SVG renderer uses this plot call currently,
diff --git a/frontends/gtk/res/en/maps.html b/frontends/gtk/res/en/maps.html
deleted file mode 120000
index 507a4b248..000000000
--- a/frontends/gtk/res/en/maps.html
+++ /dev/null
@@ -1 +0,0 @@
-../../../../resources/en/maps.html \ No newline at end of file
diff --git a/frontends/gtk/res/fr/credits.html b/frontends/gtk/res/fr/credits.html
new file mode 120000
index 000000000..47da488e8
--- /dev/null
+++ b/frontends/gtk/res/fr/credits.html
@@ -0,0 +1 @@
+../../../../resources/fr/credits.html \ No newline at end of file
diff --git a/frontends/gtk/res/fr/licence.html b/frontends/gtk/res/fr/licence.html
new file mode 120000
index 000000000..2fd247ba8
--- /dev/null
+++ b/frontends/gtk/res/fr/licence.html
@@ -0,0 +1 @@
+../../../../resources/fr/licence.html \ No newline at end of file
diff --git a/frontends/gtk/res/fr/welcome.html b/frontends/gtk/res/fr/welcome.html
new file mode 120000
index 000000000..a7a2023ea
--- /dev/null
+++ b/frontends/gtk/res/fr/welcome.html
@@ -0,0 +1 @@
+../../../../resources/fr/welcome.html \ No newline at end of file
diff --git a/frontends/gtk/res/cookies.gtk2.ui b/frontends/gtk/res/gtk2/cookies.ui
index 86f15c765..86f15c765 100644
--- a/frontends/gtk/res/cookies.gtk2.ui
+++ b/frontends/gtk/res/gtk2/cookies.ui
diff --git a/frontends/gtk/res/downloads.gtk2.ui b/frontends/gtk/res/gtk2/downloads.ui
index 1e71328a4..1e71328a4 100644
--- a/frontends/gtk/res/downloads.gtk2.ui
+++ b/frontends/gtk/res/gtk2/downloads.ui
diff --git a/frontends/gtk/res/globalhistory.gtk2.ui b/frontends/gtk/res/gtk2/globalhistory.ui
index 2b89ecb4b..2b89ecb4b 100644
--- a/frontends/gtk/res/globalhistory.gtk2.ui
+++ b/frontends/gtk/res/gtk2/globalhistory.ui
diff --git a/frontends/gtk/res/hotlist.gtk2.ui b/frontends/gtk/res/gtk2/hotlist.ui
index af0fd5696..af0fd5696 100644
--- a/frontends/gtk/res/hotlist.gtk2.ui
+++ b/frontends/gtk/res/gtk2/hotlist.ui
diff --git a/frontends/gtk/res/localhistory.gtk2.ui b/frontends/gtk/res/gtk2/localhistory.ui
index 9512b6289..2003ed69a 100644
--- a/frontends/gtk/res/localhistory.gtk2.ui
+++ b/frontends/gtk/res/gtk2/localhistory.ui
@@ -2,6 +2,7 @@
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkWindow" id="wndHistory">
+ <property name="type">GTK_WINDOW_POPUP</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">NetSurf Local History</property>
<property name="window_position">center</property>
diff --git a/frontends/gtk/res/gtk2/netsurf.ui b/frontends/gtk/res/gtk2/netsurf.ui
new file mode 100644
index 000000000..adca54001
--- /dev/null
+++ b/frontends/gtk/res/gtk2/netsurf.ui
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 2.12 -->
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="upper">100</property>
+ <property name="value">0.5357142857142857</property>
+ <property name="step_increment">26</property>
+ <property name="page_increment">10</property>
+ <property name="page_size">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment2">
+ <property name="upper">100</property>
+ <property name="step_increment">26</property>
+ <property name="page_increment">10</property>
+ <property name="page_size">10</property>
+ </object>
+ <object class="GtkWindow" id="wndBrowser">
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes">NetSurf</property>
+ <property name="window_position">center</property>
+ <child>
+ <object class="GtkVBox" id="vbox14">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkMenuBar" id="menubar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_tabs">False</property>
+ <property name="show_border">False</property>
+ <property name="scrollable">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="tab">
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="tab">
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="tab">
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="tab">
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="tab">
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="tab">
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/frontends/gtk/res/options.gtk2.ui b/frontends/gtk/res/gtk2/options.ui
index a1162585d..907d0b511 100644
--- a/frontends/gtk/res/options.gtk2.ui
+++ b/frontends/gtk/res/gtk2/options.ui
@@ -1143,38 +1143,6 @@
</packing>
</child>
<child>
- <object class="GtkCheckButton" id="checkDisablePlugins">
- <property name="label" translatable="yes">preferencesControlDisable</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="nsgtk_preferences_checkDisablePlugins_toggled" swapped="no"/>
- <signal name="realize" handler="nsgtk_preferences_checkDisablePlugins_realize" swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">3</property>
- </packing>
- </child>
- <child>
- <object class="GtkCheckButton" id="checkResampleImages">
- <property name="label" translatable="yes">preferencesControlHigh</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="nsgtk_preferences_checkResampleImages_toggled" swapped="no"/>
- <signal name="realize" handler="nsgtk_preferences_checkResampleImages_realize" swapped="no"/>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">4</property>
- </packing>
- </child>
- <child>
<object class="GtkHBox" id="hbox8">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -1215,7 +1183,7 @@
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
- <property name="position">5</property>
+ <property name="position">3</property>
</packing>
</child>
</object>
@@ -1272,55 +1240,6 @@
<property name="position">0</property>
</packing>
</child>
- <child>
- <object class="GtkHBox" id="hbox9">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkLabel" id="label19">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">preferencesAnimationMinimum</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkSpinButton" id="spinAnimationSpeed">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="has_tooltip">True</property>
- <property name="tooltip_text" translatable="yes">preferencesAnimationMinimumTooltip</property>
- <property name="invisible_char">â—</property>
- <property name="primary_icon_activatable">False</property>
- <property name="secondary_icon_activatable">False</property>
- <property name="primary_icon_sensitive">True</property>
- <property name="secondary_icon_sensitive">True</property>
- <property name="adjustment">adjustment_animation_time</property>
- <property name="climb_rate">1</property>
- <property name="digits">1</property>
- <property name="numeric">True</property>
- <property name="update_policy">if-valid</property>
- <signal name="value-changed" handler="nsgtk_preferences_spinAnimationSpeed_valuechanged" swapped="no"/>
- <signal name="realize" handler="nsgtk_preferences_spinAnimationSpeed_realize" swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
</object>
</child>
</object>
diff --git a/frontends/gtk/res/gtk2/pageinfo.ui b/frontends/gtk/res/gtk2/pageinfo.ui
new file mode 100644
index 000000000..3d541d653
--- /dev/null
+++ b/frontends/gtk/res/gtk2/pageinfo.ui
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="2.24"/>
+ <!-- interface-naming-policy project-wide -->
+ <object class="GtkWindow" id="PGIWindow">
+ <property name="type">GTK_WINDOW_POPUP</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkDrawingArea" id="PGIDrawingArea">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/frontends/gtk/res/password.gtk2.ui b/frontends/gtk/res/gtk2/password.ui
index eb51e4f8f..eb51e4f8f 100644
--- a/frontends/gtk/res/password.gtk2.ui
+++ b/frontends/gtk/res/gtk2/password.ui
diff --git a/frontends/gtk/res/gtk2/tabcontents.ui b/frontends/gtk/res/gtk2/tabcontents.ui
new file mode 100644
index 000000000..c47e6a2ef
--- /dev/null
+++ b/frontends/gtk/res/gtk2/tabcontents.ui
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 2.12 -->
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkAdjustment" id="layouthadjustment">
+ <property name="upper">100</property>
+ <property name="step_increment">30</property>
+ <property name="page_increment">10</property>
+ <property name="page_size">10</property>
+ </object>
+ <object class="GtkAdjustment" id="layoutvadjustment">
+ <property name="upper">100</property>
+ <property name="step_increment">30</property>
+ <property name="page_increment">10</property>
+ <property name="page_size">10</property>
+ </object>
+ <object class="GtkVBox" id="tabBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkToolbar" id="toolbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="toolbar_style">both-horiz</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolbar" id="findbar">
+ <property name="can_focus">False</property>
+ <property name="toolbar_style">both</property>
+ <child>
+ <object class="GtkToolItem" id="toolitemFind">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkEntry" id="Find">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="FindBack">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">gtkFindBack</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">go-up</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="FindForward">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">gtkFindForward</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">go-down</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolItem" id="toolitemFindHighlightAll">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkCheckButton" id="FindHighlightAll">
+ <property name="label" translatable="yes">gtkFindHighlightAll</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">show all matches</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolItem" id="toolitemFindMatchCase">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkCheckButton" id="FindMatchCase">
+ <property name="label" translatable="yes">gtkFindMatchCase</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Match case when searching</property>
+ <property name="relief">none</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="FindClose">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">gtkFindClose</property>
+ <property name="icon_name">window-close</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkTable" id="tabContents">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <child>
+ <object class="GtkLayout" id="layout">
+ <property name="visible">True</property>
+ <property name="app_paintable">True</property>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK | GDK_SCROLL_MASK</property>
+ <property name="hadjustment">layouthadjustment</property>
+ <property name="vadjustment">layoutvadjustment</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStatusbar" id="resizer">
+ <property name="height_request">1</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">2</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHPaned" id="hpaned1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkLabel" id="status_bar">
+ <property name="width_request">1</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="xpad">4</property>
+ <property name="label" translatable="yes">Status</property>
+ </object>
+ <packing>
+ <property name="resize">False</property>
+ <property name="shrink">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHScrollbar" id="hscrollbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="adjustment">layouthadjustment</property>
+ </object>
+ <packing>
+ <property name="resize">True</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVScrollbar" id="vscrollbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="adjustment">layoutvadjustment</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="x_options"/>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/frontends/gtk/res/gtk2/toolbar.ui b/frontends/gtk/res/gtk2/toolbar.ui
new file mode 100644
index 000000000..61723065b
--- /dev/null
+++ b/frontends/gtk/res/gtk2/toolbar.ui
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 2.12 -->
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkVBox" id="customisation">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkToolbar" id="toolbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="xpad">6</property>
+ <property name="label" translatable="yes">gtkCustomizeToolbarInstructions</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">6</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <child>
+ <object class="GtkViewport" id="viewport1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkVBox" id="toolbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHButtonBox" id="hbuttonbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="reset">
+ <property name="label" translatable="yes">Reset to defaults</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="discard">
+ <property name="label">gtk-discard</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="apply">
+ <property name="label">gtk-apply</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">6</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/frontends/gtk/res/viewdata.gtk2.ui b/frontends/gtk/res/gtk2/viewdata.ui
index 7589022ca..7589022ca 100644
--- a/frontends/gtk/res/viewdata.gtk2.ui
+++ b/frontends/gtk/res/gtk2/viewdata.ui
diff --git a/frontends/gtk/res/warning.gtk2.ui b/frontends/gtk/res/gtk2/warning.ui
index e4fb4e662..e4fb4e662 100644
--- a/frontends/gtk/res/warning.gtk2.ui
+++ b/frontends/gtk/res/gtk2/warning.ui
diff --git a/frontends/gtk/res/cookies.gtk3.ui b/frontends/gtk/res/gtk3/cookies.ui
index 44dcb80b8..85f9aae76 100644
--- a/frontends/gtk/res/cookies.gtk3.ui
+++ b/frontends/gtk/res/gtk3/cookies.ui
@@ -187,7 +187,7 @@
<object class="GtkDrawingArea" id="cookiesDrawingArea">
<property name="visible">True</property>
<property name="app_paintable">True</property>
- <property name="can_focus">False</property>
+ <property name="can_focus">True</property>
<property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
</object>
</child>
diff --git a/frontends/gtk/res/downloads.gtk3.ui b/frontends/gtk/res/gtk3/downloads.ui
index 1e71328a4..1e71328a4 100644
--- a/frontends/gtk/res/downloads.gtk3.ui
+++ b/frontends/gtk/res/gtk3/downloads.ui
diff --git a/frontends/gtk/res/globalhistory.gtk3.ui b/frontends/gtk/res/gtk3/globalhistory.ui
index 7fa598f1e..c0496964f 100644
--- a/frontends/gtk/res/globalhistory.gtk3.ui
+++ b/frontends/gtk/res/gtk3/globalhistory.ui
@@ -219,7 +219,7 @@
<child>
<object class="GtkDrawingArea" id="globalHistoryDrawingArea">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can_focus">True</property>
<property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
</object>
</child>
diff --git a/frontends/gtk/res/hotlist.gtk3.ui b/frontends/gtk/res/gtk3/hotlist.ui
index b0e075c4b..ccd193637 100644
--- a/frontends/gtk/res/hotlist.gtk3.ui
+++ b/frontends/gtk/res/gtk3/hotlist.ui
@@ -236,7 +236,7 @@
<child>
<object class="GtkDrawingArea" id="hotlistDrawingArea">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can_focus">True</property>
<property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
</object>
</child>
diff --git a/frontends/gtk/res/localhistory.gtk3.ui b/frontends/gtk/res/gtk3/localhistory.ui
index 1a4b9004d..9a36a91a7 100644
--- a/frontends/gtk/res/localhistory.gtk3.ui
+++ b/frontends/gtk/res/gtk3/localhistory.ui
@@ -2,6 +2,7 @@
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkWindow" id="wndHistory">
+ <property name="type">GTK_WINDOW_POPUP</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">NetSurf Local History</property>
<property name="window_position">center</property>
@@ -26,7 +27,7 @@
<child>
<object class="GtkDrawingArea" id="HistoryDrawingArea">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can_focus">True</property>
<property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
</object>
</child>
diff --git a/frontends/gtk/res/gtk3/netsurf.ui b/frontends/gtk/res/gtk3/netsurf.ui
new file mode 100644
index 000000000..6ea8f07a7
--- /dev/null
+++ b/frontends/gtk/res/gtk3/netsurf.ui
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.0"/>
+ <object class="GtkWindow" id="wndBrowser">
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkMenuBar" id="menubar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="show_tabs">False</property>
+ <property name="show_border">False</property>
+ <property name="scrollable">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="tab">
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="tab">
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="tab">
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/frontends/gtk/res/options.gtk3.ui b/frontends/gtk/res/gtk3/options.ui
index 2a3516f09..82a3e175a 100644
--- a/frontends/gtk/res/options.gtk3.ui
+++ b/frontends/gtk/res/gtk3/options.ui
@@ -143,9 +143,10 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
- <object class="GtkVBox" id="vbox_main">
+ <object class="GtkBox" id="vbox_main">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="valign">start</property>
<property name="spacing">6</property>
<child>
@@ -162,14 +163,16 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox2">
+ <object class="GtkBox" id="vbox2">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
- <object class="GtkHBox" id="hbox1">
+ <object class="GtkBox" id="hbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label_startup_page">
@@ -207,9 +210,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox2">
+ <object class="GtkBox" id="hbox2">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<placeholder/>
@@ -289,9 +293,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox3">
+ <object class="GtkBox" id="vbox3">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkUrlSearch">
@@ -314,9 +319,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox3">
+ <object class="GtkBox" id="hbox3">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label5">
@@ -393,9 +399,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox4">
+ <object class="GtkBox" id="vbox4">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkClearDownloads">
@@ -438,9 +445,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox4">
+ <object class="GtkBox" id="hbox4">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label8">
@@ -510,9 +518,10 @@
</packing>
</child>
<child>
- <object class="GtkVBox" id="vbox_appearance">
+ <object class="GtkBox" id="vbox_appearance">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="valign">start</property>
<property name="spacing">6</property>
<child>
@@ -529,9 +538,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox5">
+ <object class="GtkBox" id="vbox5">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkShowSingleTab">
@@ -594,9 +604,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox5">
+ <object class="GtkBox" id="hbox5">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label9">
@@ -672,14 +683,16 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox1">
+ <object class="GtkBox" id="vbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
- <object class="GtkHBox" id="hbox6">
+ <object class="GtkBox" id="hbox6">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label13">
@@ -755,9 +768,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox7">
+ <object class="GtkBox" id="vbox7">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkDisplayRecentURLs">
@@ -813,14 +827,16 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox8">
+ <object class="GtkBox" id="vbox8">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
- <object class="GtkHBox" id="hbox7">
+ <object class="GtkBox" id="hbox7">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label16">
@@ -899,10 +915,11 @@
</packing>
</child>
<child>
- <object class="GtkVBox" id="vbox_content">
+ <object class="GtkBox" id="vbox_content">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkFrame" id="frame_content_control">
@@ -918,9 +935,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox6">
+ <object class="GtkBox" id="vbox6">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkDisablePopups">
@@ -983,49 +1001,10 @@
</packing>
</child>
<child>
- <object class="GtkCheckButton" id="checkDisablePlugins">
- <property name="label" translatable="yes">preferencesControlDisable</property>
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="halign">start</property>
- <property name="use_action_appearance">False</property>
- <property name="xalign">0.5</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="nsgtk_preferences_checkDisablePlugins_toggled" swapped="no"/>
- <signal name="realize" handler="nsgtk_preferences_checkDisablePlugins_realize" swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">3</property>
- </packing>
- </child>
- <child>
- <object class="GtkCheckButton" id="checkResampleImages">
- <property name="label" translatable="yes">preferencesControlHigh</property>
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="halign">start</property>
- <property name="use_action_appearance">False</property>
- <property name="xalign">0.5</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="nsgtk_preferences_checkResampleImages_toggled" swapped="no"/>
- <signal name="realize" handler="nsgtk_preferences_checkResampleImages_realize" swapped="no"/>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">4</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox8">
+ <object class="GtkBox" id="hbox8">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label17">
@@ -1064,7 +1043,7 @@
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
- <property name="position">5</property>
+ <property name="position">3</property>
</packing>
</child>
</object>
@@ -1101,9 +1080,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox9">
+ <object class="GtkBox" id="vbox9">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkEnableAnimations">
@@ -1125,51 +1105,6 @@
<property name="position">0</property>
</packing>
</child>
- <child>
- <object class="GtkHBox" id="hbox9">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkLabel" id="label19">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">preferencesAnimationMinimum</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkSpinButton" id="spinAnimationSpeed">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="has_tooltip">True</property>
- <property name="tooltip_text" translatable="yes">preferencesAnimationMinimumTooltip</property>
- <property name="invisible_char">â—</property>
- <property name="adjustment">adjustment_animation_time</property>
- <property name="climb_rate">1</property>
- <property name="digits">1</property>
- <property name="numeric">True</property>
- <property name="update_policy">if-valid</property>
- <signal name="value-changed" handler="nsgtk_preferences_spinAnimationSpeed_valuechanged" swapped="no"/>
- <signal name="realize" handler="nsgtk_preferences_spinAnimationSpeed_realize" swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
</object>
</child>
</object>
@@ -1204,14 +1139,16 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkHBox" id="hbox11">
+ <object class="GtkBox" id="hbox11">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">12</property>
<child>
- <object class="GtkHBox" id="hbox12">
+ <object class="GtkBox" id="hbox12">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label26">
@@ -1253,9 +1190,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox13">
+ <object class="GtkBox" id="hbox13">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label27">
@@ -1349,14 +1287,16 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox10">
+ <object class="GtkBox" id="vbox10">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
- <object class="GtkHBox" id="hbox10">
+ <object class="GtkBox" id="hbox10">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label21">
@@ -1446,10 +1386,11 @@
</packing>
</child>
<child>
- <object class="GtkVBox" id="vbox_privacy">
+ <object class="GtkBox" id="vbox_privacy">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkFrame" id="frame_privacy_general">
@@ -1465,9 +1406,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox15">
+ <object class="GtkBox" id="vbox15">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkSendReferer">
@@ -1543,9 +1485,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox11">
+ <object class="GtkBox" id="vbox11">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkHoverURLs">
@@ -1568,9 +1511,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox14">
+ <object class="GtkBox" id="hbox14">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label28">
@@ -1657,9 +1601,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox12">
+ <object class="GtkBox" id="vbox12">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkTable" id="table3">
@@ -1815,9 +1760,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox17">
+ <object class="GtkBox" id="hbox17">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<child>
<placeholder/>
</child>
@@ -1881,10 +1827,11 @@
</packing>
</child>
<child>
- <object class="GtkVBox" id="vbox_network">
+ <object class="GtkBox" id="vbox_network">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkFrame" id="frame_network_proxy">
@@ -1979,9 +1926,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox19">
+ <object class="GtkBox" id="hbox19">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkEntry" id="entryProxyHost">
@@ -2285,10 +2233,11 @@
</packing>
</child>
<child>
- <object class="GtkVBox" id="vbox_pdfexport">
+ <object class="GtkBox" id="vbox_pdfexport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkFrame" id="frame_pdfexport_appearance">
@@ -2304,9 +2253,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox13">
+ <object class="GtkBox" id="vbox13">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkSuppressImages">
@@ -2369,9 +2319,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox15">
+ <object class="GtkBox" id="hbox15">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label59">
@@ -2458,14 +2409,16 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox16">
+ <object class="GtkBox" id="vbox16">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
- <object class="GtkHBox" id="hbox22">
+ <object class="GtkBox" id="hbox22">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<child>
<object class="GtkLabel" id="label62">
<property name="visible">True</property>
@@ -2504,9 +2457,10 @@
<placeholder/>
</child>
<child>
- <object class="GtkHBox" id="hbox16">
+ <object class="GtkBox" id="hbox16">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label51">
@@ -2548,9 +2502,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox18">
+ <object class="GtkBox" id="hbox18">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label52">
@@ -2593,9 +2548,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox20">
+ <object class="GtkBox" id="hbox20">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label53">
@@ -2639,9 +2595,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox21">
+ <object class="GtkBox" id="hbox21">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label54">
@@ -2746,9 +2703,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox14">
+ <object class="GtkBox" id="vbox14">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">7</property>
<child>
<object class="GtkCheckButton" id="checkCompressPDF">
diff --git a/frontends/gtk/res/gtk3/pageinfo.ui b/frontends/gtk/res/gtk3/pageinfo.ui
new file mode 100644
index 000000000..fdee5ac8d
--- /dev/null
+++ b/frontends/gtk/res/gtk3/pageinfo.ui
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkWindow" id="PGIWindow">
+ <property name="type">GTK_WINDOW_POPUP</property>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_STRUCTURE_MASK</property>
+ <property name="resizable">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkDrawingArea" id="PGIDrawingArea">
+ <property name="name">PGIDrawingArea</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/frontends/gtk/res/password.gtk3.ui b/frontends/gtk/res/gtk3/password.ui
index eb51e4f8f..eb51e4f8f 100644
--- a/frontends/gtk/res/password.gtk3.ui
+++ b/frontends/gtk/res/gtk3/password.ui
diff --git a/frontends/gtk/res/gtk3/tabcontents.ui b/frontends/gtk/res/gtk3/tabcontents.ui
new file mode 100644
index 000000000..b07cf92e0
--- /dev/null
+++ b/frontends/gtk/res/gtk3/tabcontents.ui
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.0"/>
+ <object class="GtkAdjustment" id="layouthadjustment">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="layoutvadjustment">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkBox" id="tabBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkToolbar" id="toolbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="toolbar_style">both</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolbar" id="findbar">
+ <property name="can_focus">False</property>
+ <property name="toolbar_style">both</property>
+ <child>
+ <object class="GtkToolItem">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkEntry" id="Find">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">â—</property>
+ <property name="placeholder_text" translatable="yes">gtkFindPlaceholder</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="homogeneous">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="FindBack">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">gtkFindBack</property>
+ <property name="label" translatable="yes">gtkFindBack</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-go-up</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="FindForward">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">gtkFindForward</property>
+ <property name="label" translatable="yes">gtkFindForward</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-go-down</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolItem">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkCheckButton" id="FindHighlightAll">
+ <property name="label" translatable="yes">gtkFindHighlightAll</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolItem">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkCheckButton" id="FindMatchCase">
+ <property name="label" translatable="yes">gtkFindMatchCase</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="FindClose">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">gtkFindClose</property>
+ <property name="label" translatable="yes">gtkFindClose</property>
+ <property name="stock_id">gtk-close</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="tabContents">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">2</property>
+ <property name="column_spacing">2</property>
+ <child>
+ <object class="GtkLayout" id="layout">
+ <property name="visible">True</property>
+ <property name="app_paintable">True</property>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK | GDK_SCROLL_MASK</property>
+ <property name="hadjustment">layouthadjustment</property>
+ <property name="vadjustment">layoutvadjustment</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrollbar" id="vscrollbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="adjustment">layoutvadjustment</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkPaned" id="hpaned1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <child>
+ <object class="GtkLabel" id="status_bar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xpad">4</property>
+ <property name="label" translatable="yes">Status</property>
+ <property name="single_line_mode">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="resize">False</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrollbar" id="hscrollbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="adjustment">layouthadjustment</property>
+ </object>
+ <packing>
+ <property name="resize">True</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/frontends/gtk/res/gtk3/toolbar.ui b/frontends/gtk/res/gtk3/toolbar.ui
new file mode 100644
index 000000000..60452f472
--- /dev/null
+++ b/frontends/gtk/res/gtk3/toolbar.ui
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<!--*- mode: xml -*-->
+<interface>
+ <requires lib="gtk+" version="3.0"/>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-refresh</property>
+ </object>
+ <object class="GtkBox" id="customisation">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkToolbar" id="toolbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xpad">6</property>
+ <property name="label" translatable="yes">gtkCustomizeToolbarInstructions</property>
+ <property name="wrap">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">6</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="toolbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButtonBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="reset">
+ <property name="label" translatable="yes">Reset</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image2</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="discard">
+ <property name="label">gtk-discard</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="apply">
+ <property name="label">gtk-apply</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">6</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/frontends/gtk/res/viewdata.gtk3.ui b/frontends/gtk/res/gtk3/viewdata.ui
index b742d5f6b..b742d5f6b 100644
--- a/frontends/gtk/res/viewdata.gtk3.ui
+++ b/frontends/gtk/res/gtk3/viewdata.ui
diff --git a/frontends/gtk/res/warning.gtk3.ui b/frontends/gtk/res/gtk3/warning.ui
index e4fb4e662..e4fb4e662 100644
--- a/frontends/gtk/res/warning.gtk3.ui
+++ b/frontends/gtk/res/gtk3/warning.ui
diff --git a/frontends/gtk/res/login.gtk2.ui b/frontends/gtk/res/login.gtk2.ui
deleted file mode 100644
index 552b173ed..000000000
--- a/frontends/gtk/res/login.gtk2.ui
+++ /dev/null
@@ -1,223 +0,0 @@
-<?xml version="1.0"?>
-<!--*- mode: xml -*-->
-<interface>
- <object class="GtkDialog" id="wndLogin">
- <property name="title" translatable="yes">Site Authentication</property>
- <property name="window_position">GTK_WIN_POS_CENTER_ALWAYS</property>
- <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
- <child internal-child="vbox">
- <object class="GtkVBox" id="dialog-vbox2">
- <property name="visible">True</property>
- <child>
- <object class="GtkHBox" id="hbox12">
- <property name="visible">True</property>
- <property name="border_width">3</property>
- <child>
- <object class="GtkImage" id="image3">
- <property name="visible">True</property>
- <property name="yalign">0.10000000149011612</property>
- <property name="xpad">12</property>
- <property name="icon_size">6</property>
- <property name="icon_name">gtk-dialog-authentication</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkTable" id="table5">
- <property name="visible">True</property>
- <property name="border_width">1</property>
- <property name="n_rows">4</property>
- <property name="n_columns">2</property>
- <property name="column_spacing">11</property>
- <property name="row_spacing">10</property>
- <child>
- <object class="GtkLabel" id="labelLoginHost">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">moo.yoo.com</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label57">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Password</property>
- </object>
- <packing>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label56">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Username</property>
- </object>
- <packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label54">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Host</property>
- </object>
- <packing>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label55">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Realm</property>
- </object>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="labelLoginRealm">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">my sekr3t area</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="entryLoginPass">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="visibility">False</property>
- <property name="activates_default">True</property>
- <property name="text" translatable="yes">opensesame</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="y_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="entryLoginUser">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="has_focus">True</property>
- <property name="text" translatable="yes">sesame</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="y_options"/>
- </packing>
- </child>
- </object>
- <packing>
- <property name="padding">1</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">2</property>
- </packing>
- </child>
- <child internal-child="action_area">
- <object class="GtkHButtonBox" id="dialog-action_area2">
- <property name="visible">True</property>
- <property name="layout_style">GTK_BUTTONBOX_END</property>
- <child>
- <object class="GtkButton" id="buttonLoginCan">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label">gtk-cancel</property>
- <property name="use_stock">True</property>
- </object>
- </child>
- <child>
- <object class="GtkButton" id="buttonLoginOK">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="has_default">True</property>
- <child>
- <object class="GtkAlignment" id="alignment14">
- <property name="visible">True</property>
- <property name="can_default">True</property>
- <property name="has_default">True</property>
- <property name="xscale">0</property>
- <property name="yscale">0</property>
- <child>
- <object class="GtkHBox" id="hbox11">
- <property name="visible">True</property>
- <property name="spacing">2</property>
- <child>
- <object class="GtkImage" id="image2">
- <property name="visible">True</property>
- <property name="stock">gtk-ok</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label49">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Login</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">GTK_PACK_END</property>
- </packing>
- </child>
- </object>
- </child>
- <action-widgets>
- <action-widget response="-6">buttonLoginCan</action-widget>
- <action-widget response="-5">buttonLoginOK</action-widget>
- </action-widgets>
- </object>
-</interface>
diff --git a/frontends/gtk/res/login.gtk3.ui b/frontends/gtk/res/login.gtk3.ui
deleted file mode 100644
index 552b173ed..000000000
--- a/frontends/gtk/res/login.gtk3.ui
+++ /dev/null
@@ -1,223 +0,0 @@
-<?xml version="1.0"?>
-<!--*- mode: xml -*-->
-<interface>
- <object class="GtkDialog" id="wndLogin">
- <property name="title" translatable="yes">Site Authentication</property>
- <property name="window_position">GTK_WIN_POS_CENTER_ALWAYS</property>
- <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
- <child internal-child="vbox">
- <object class="GtkVBox" id="dialog-vbox2">
- <property name="visible">True</property>
- <child>
- <object class="GtkHBox" id="hbox12">
- <property name="visible">True</property>
- <property name="border_width">3</property>
- <child>
- <object class="GtkImage" id="image3">
- <property name="visible">True</property>
- <property name="yalign">0.10000000149011612</property>
- <property name="xpad">12</property>
- <property name="icon_size">6</property>
- <property name="icon_name">gtk-dialog-authentication</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkTable" id="table5">
- <property name="visible">True</property>
- <property name="border_width">1</property>
- <property name="n_rows">4</property>
- <property name="n_columns">2</property>
- <property name="column_spacing">11</property>
- <property name="row_spacing">10</property>
- <child>
- <object class="GtkLabel" id="labelLoginHost">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">moo.yoo.com</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label57">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Password</property>
- </object>
- <packing>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label56">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Username</property>
- </object>
- <packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label54">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Host</property>
- </object>
- <packing>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label55">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Realm</property>
- </object>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="labelLoginRealm">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">my sekr3t area</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="entryLoginPass">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="visibility">False</property>
- <property name="activates_default">True</property>
- <property name="text" translatable="yes">opensesame</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="y_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="entryLoginUser">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="has_focus">True</property>
- <property name="text" translatable="yes">sesame</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="y_options"/>
- </packing>
- </child>
- </object>
- <packing>
- <property name="padding">1</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">2</property>
- </packing>
- </child>
- <child internal-child="action_area">
- <object class="GtkHButtonBox" id="dialog-action_area2">
- <property name="visible">True</property>
- <property name="layout_style">GTK_BUTTONBOX_END</property>
- <child>
- <object class="GtkButton" id="buttonLoginCan">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label">gtk-cancel</property>
- <property name="use_stock">True</property>
- </object>
- </child>
- <child>
- <object class="GtkButton" id="buttonLoginOK">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="has_default">True</property>
- <child>
- <object class="GtkAlignment" id="alignment14">
- <property name="visible">True</property>
- <property name="can_default">True</property>
- <property name="has_default">True</property>
- <property name="xscale">0</property>
- <property name="yscale">0</property>
- <child>
- <object class="GtkHBox" id="hbox11">
- <property name="visible">True</property>
- <property name="spacing">2</property>
- <child>
- <object class="GtkImage" id="image2">
- <property name="visible">True</property>
- <property name="stock">gtk-ok</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label49">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Login</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">GTK_PACK_END</property>
- </packing>
- </child>
- </object>
- </child>
- <action-widgets>
- <action-widget response="-6">buttonLoginCan</action-widget>
- <action-widget response="-5">buttonLoginOK</action-widget>
- </action-widgets>
- </object>
-</interface>
diff --git a/frontends/gtk/res/maps.html b/frontends/gtk/res/maps.html
deleted file mode 120000
index a32f725fb..000000000
--- a/frontends/gtk/res/maps.html
+++ /dev/null
@@ -1 +0,0 @@
-en/maps.html \ No newline at end of file
diff --git a/frontends/gtk/res/messages.gresource.xml b/frontends/gtk/res/messages.gresource.xml
index 684a10862..6da406245 100644
--- a/frontends/gtk/res/messages.gresource.xml
+++ b/frontends/gtk/res/messages.gresource.xml
@@ -6,5 +6,6 @@
<file>de/Messages</file>
<file>fr/Messages</file>
<file>it/Messages</file>
+ <file>zh_CN/Messages</file>
</gresource>
</gresources>
diff --git a/frontends/gtk/res/netsurf.gresource.xml b/frontends/gtk/res/netsurf.gresource.xml
index e8243254a..21a2e7723 100644
--- a/frontends/gtk/res/netsurf.gresource.xml
+++ b/frontends/gtk/res/netsurf.gresource.xml
@@ -1,34 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/netsurf">
- <file>cookies.gtk2.ui</file>
- <file>globalhistory.gtk3.ui</file>
- <file>localhistory.gtk3.ui</file>
- <file>netsurf.gtk2.ui</file>
- <file>password.gtk3.ui</file>
- <file>toolbar.gtk2.ui</file>
- <file>warning.gtk3.ui</file>
- <file>cookies.gtk3.ui</file>
- <file>hotlist.gtk2.ui</file>
- <file>netsurf.gtk3.ui</file>
- <file>ssl.gtk2.ui</file>
- <file>toolbar.gtk3.ui</file>
- <file>downloads.gtk2.ui</file>
- <file>hotlist.gtk3.ui</file>
- <file>options.gtk2.ui</file>
- <file>ssl.gtk3.ui</file>
- <file>viewdata.gtk2.ui</file>
- <file>downloads.gtk3.ui</file>
- <file>login.gtk2.ui</file>
- <file>options.gtk3.ui</file>
- <file>tabcontents.gtk2.ui</file>
- <file>viewdata.gtk3.ui</file>
- <file>localhistory.gtk2.ui</file>
- <file>globalhistory.gtk2.ui</file>
- <file>login.gtk3.ui</file>
- <file>password.gtk2.ui</file>
- <file>tabcontents.gtk3.ui</file>
- <file>warning.gtk2.ui</file>
<file preprocess="to-pixdata">favicon.png</file>
<file preprocess="to-pixdata">netsurf.xpm</file>
<file preprocess="to-pixdata">menu_cursor.png</file>
@@ -42,24 +14,30 @@
<file preprocess="to-pixdata">throbber/throbber7.png</file>
<file preprocess="to-pixdata">throbber/throbber8.png</file>
<file>credits.html</file>
+ <file>fr/credits.html</file>
<file>it/credits.html</file>
<file>nl/credits.html</file>
+ <file>zh_CN/credits.html</file>
<file>licence.html</file>
+ <file>fr/licence.html</file>
<file>it/licence.html</file>
<file>nl/licence.html</file>
+ <file>zh_CN/licence.html</file>
<file>welcome.html</file>
<file>de/welcome.html</file>
+ <file>fr/welcome.html</file>
<file>it/welcome.html</file>
<file>ja/welcome.html</file>
<file>nl/welcome.html</file>
- <file>maps.html</file>
+ <file>zh_CN/welcome.html</file>
<file>adblock.css</file>
<file>default.css</file>
<file>internal.css</file>
<file>quirks.css</file>
<file>netsurf.png</file>
<file>default.ico</file>
- <file>arrow_down_8x32.png</file>
+ <file>icons/show-cookie.png</file>
+ <file>icons/local-history.png</file>
<file>icons/arrow-l.png</file>
<file>icons/content.png</file>
<file>icons/directory2.png</file>
@@ -67,6 +45,16 @@
<file>icons/hotlist-add.png</file>
<file>icons/hotlist-rmv.png</file>
<file>icons/search.png</file>
+ <file>icons/24x24/actions/page-info-insecure.png</file>
+ <file>icons/24x24/actions/page-info-internal.png</file>
+ <file>icons/24x24/actions/page-info-local.png</file>
+ <file>icons/24x24/actions/page-info-secure.png</file>
+ <file>icons/24x24/actions/page-info-warning.png</file>
+ <file>icons/48x48/actions/page-info-insecure.png</file>
+ <file>icons/48x48/actions/page-info-internal.png</file>
+ <file>icons/48x48/actions/page-info-local.png</file>
+ <file>icons/48x48/actions/page-info-secure.png</file>
+ <file>icons/48x48/actions/page-info-warning.png</file>
<file>languages</file>
<file>accelerators</file>
</gresource>
diff --git a/frontends/gtk/res/netsurf.gtk2.ui b/frontends/gtk/res/netsurf.gtk2.ui
deleted file mode 100644
index 68812b364..000000000
--- a/frontends/gtk/res/netsurf.gtk2.ui
+++ /dev/null
@@ -1,212 +0,0 @@
-<?xml version="1.0"?>
-<!--Generated with glade3 3.4.5 on Wed Apr 7 17:10:28 2010 -->
-<interface>
- <object class="GtkAdjustment" id="adjustment1">
- <property name="upper">100</property>
- <property name="lower">0</property>
- <property name="page_increment">10</property>
- <property name="step_increment">26</property>
- <property name="page_size">10</property>
- <property name="value">0.5357142857142857</property>
- </object>
- <object class="GtkAdjustment" id="adjustment2">
- <property name="upper">100</property>
- <property name="lower">0</property>
- <property name="page_increment">10</property>
- <property name="step_increment">26</property>
- <property name="page_size">10</property>
- <property name="value">0</property>
- </object>
- <object class="GtkUIManager" id="uimanager1">
- <ui>
- <menubar name="menubar"/>
- </ui>
- </object>
- <object class="GtkWindow" id="wndBrowser">
- <property name="title" translatable="yes">NetSurf</property>
- <property name="window_position">GTK_WIN_POS_CENTER</property>
- <child>
- <object class="GtkVBox" id="vbox14">
- <property name="visible">True</property>
- <child>
- <object class="GtkMenuBar" constructor="uimanager1" id="menubar">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolbar" id="toolbar">
- <property name="visible">True</property>
- <property name="toolbar_style">GTK_TOOLBAR_BOTH_HORIZ</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolbar" id="searchbar">
- <property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
- <child>
- <object class="GtkToolButton" id="closeSearchButton">
- <property name="visible">True</property>
- <property name="stock_id">gtk-close</property>
- </object>
- <packing>
- <property name="expand">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolItem" id="searchLabelItem">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="searchlabel">
- <property name="visible">True</property>
- <property name="xpad">4</property>
- <property name="label" translatable="yes">Match</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolItem" id="toolSearch">
- <property name="visible">True</property>
- <child>
- <object class="GtkEntry" id="searchEntry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolButton" id="searchBackButton">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Search _Back</property>
- <property name="use_underline">True</property>
- <property name="stock_id">gtk-go-back</property>
- </object>
- <packing>
- <property name="expand">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolButton" id="searchForwardButton">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Search _Forward</property>
- <property name="use_underline">True</property>
- <property name="stock_id">gtk-go-forward</property>
- </object>
- <packing>
- <property name="expand">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolItem" id="checkAllSearchItem">
- <property name="visible">True</property>
- <child>
- <object class="GtkCheckButton" id="checkAllSearch">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="tooltip-text" translatable="yes">show all matches</property>
- <property name="label" translatable="yes">All </property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolItem" id="caseSensItem">
- <property name="visible">True</property>
- <child>
- <object class="GtkCheckButton" id="caseSensButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="tooltip-text" translatable="yes">Match case when searching</property>
- <property name="label" translatable="yes">Case</property>
- <property name="relief">GTK_RELIEF_NONE</property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">False</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkNotebook" id="notebook">
- <property name="visible">True</property>
- <property name="show_tabs">False</property>
- <property name="show_border">False</property>
- <property name="scrollable">True</property>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- </object>
- <packing>
- <property name="position">3</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
-</interface>
diff --git a/frontends/gtk/res/netsurf.gtk3.ui b/frontends/gtk/res/netsurf.gtk3.ui
deleted file mode 100644
index ce47c6370..000000000
--- a/frontends/gtk/res/netsurf.gtk3.ui
+++ /dev/null
@@ -1,207 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<interface>
- <!-- interface-requires gtk+ 3.0 -->
- <object class="GtkWindow" id="wndBrowser">
- <property name="can_focus">False</property>
- <child>
- <object class="GtkBox" id="box1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkMenuBar" id="menubar">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolbar" id="toolbar">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="toolbar_style">both</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolbar" id="searchbar">
- <property name="can_focus">False</property>
- <property name="toolbar_style">both</property>
- <child>
- <object class="GtkToolButton" id="closeSearchButton">
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_action_appearance">False</property>
- <property name="label" translatable="yes">gtk-close</property>
- <property name="stock_id">gtk-close</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolItem" id="searchLabelItem">
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_action_appearance">False</property>
- <child>
- <object class="GtkLabel" id="searchlabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="xpad">4</property>
- <property name="label" translatable="yes">Match</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolItem" id="toolSearch">
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_action_appearance">False</property>
- <child>
- <object class="GtkEntry" id="searchEntry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="invisible_char">â—</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolButton" id="searchBackButton">
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_action_appearance">False</property>
- <property name="label" translatable="yes">Search _Back</property>
- <property name="use_underline">True</property>
- <property name="stock_id">gtk-go-back</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolButton" id="searchForwardButton">
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_action_appearance">False</property>
- <property name="label" translatable="yes">Search _Forward</property>
- <property name="use_underline">True</property>
- <property name="stock_id">gtk-go-forward</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolItem" id="checkAllSearchItem">
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_action_appearance">False</property>
- <child>
- <object class="GtkCheckButton" id="checkAllSearch">
- <property name="label" translatable="yes">All</property>
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_action_appearance">False</property>
- <property name="xalign">0</property>
- <property name="draw_indicator">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolItem" id="caseSensItem">
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_action_appearance">False</property>
- <child>
- <object class="GtkCheckButton" id="caseSensButton">
- <property name="label" translatable="yes">Case</property>
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_action_appearance">False</property>
- <property name="xalign">0</property>
- <property name="draw_indicator">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkNotebook" id="notebook">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="show_tabs">False</property>
- <property name="show_border">False</property>
- <property name="scrollable">True</property>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">3</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
-</interface>
diff --git a/frontends/gtk/res/ssl.gtk2.ui b/frontends/gtk/res/ssl.gtk2.ui
deleted file mode 100644
index 90f449ddd..000000000
--- a/frontends/gtk/res/ssl.gtk2.ui
+++ /dev/null
@@ -1,202 +0,0 @@
-<?xml version="1.0"?>
-<!--*- mode: xml -*-->
-<interface>
- <object class="GtkDialog" id="wndSSLProblem">
- <property name="border_width">1</property>
- <property name="title" translatable="yes">SSL certificate problem</property>
- <property name="modal">True</property>
- <property name="default_width">500</property>
- <property name="default_height">250</property>
- <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
- <child internal-child="vbox">
- <object class="GtkVBox" id="dialog-vbox3">
- <property name="visible">True</property>
- <child>
- <object class="GtkHBox" id="hbox15">
- <property name="visible">True</property>
- <child>
- <object class="GtkImage" id="image6">
- <property name="visible">True</property>
- <property name="yalign">0</property>
- <property name="icon_size">6</property>
- <property name="icon_name">gtk-dialog-warning</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkVBox" id="vbox13">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label62">
- <property name="visible">True</property>
- <property name="label" translatable="yes">NetSurf failed to verify the authenticity of an SSL certificate. Please verify the details presented below.</property>
- <property name="justify">GTK_JUSTIFY_CENTER</property>
- <property name="wrap">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkFrame" id="frame13">
- <property name="visible">True</property>
- <property name="border_width">5</property>
- <property name="label_xalign">0</property>
- <child>
- <object class="GtkAlignment" id="alignment17">
- <property name="visible">True</property>
- <property name="left_padding">12</property>
- <child>
- <object class="GtkScrolledWindow" id="SSLScrolled">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="shadow_type">GTK_SHADOW_IN</property>
- <child>
- <object class="GtkViewport" id="SSLViewport">
- <property name="visible">True</property>
- <property name="resize_mode">GTK_RESIZE_QUEUE</property>
- <child>
- <object class="GtkDrawingArea" id="SSLDrawingArea">
- <property name="visible">True</property>
- <property name="app_paintable">True</property>
- <property name="can_focus">True</property>
- <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel" id="label63">
- <property name="visible">True</property>
- <property name="label" translatable="yes">&lt;b&gt;Certificate chain&lt;/b&gt;</property>
- <property name="use_markup">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">2</property>
- </packing>
- </child>
- <child internal-child="action_area">
- <object class="GtkHButtonBox" id="dialog-action_area3">
- <property name="visible">True</property>
- <property name="layout_style">GTK_BUTTONBOX_END</property>
- <child>
- <object class="GtkButton" id="sslreject">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <child>
- <object class="GtkAlignment" id="alignment16">
- <property name="visible">True</property>
- <property name="xscale">0</property>
- <property name="yscale">0</property>
- <child>
- <object class="GtkHBox" id="hbox14">
- <property name="visible">True</property>
- <property name="spacing">2</property>
- <child>
- <object class="GtkImage" id="image5">
- <property name="visible">True</property>
- <property name="stock">gtk-cancel</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label61">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Reject</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkButton" id="sslaccept">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <child>
- <object class="GtkAlignment" id="alignment15">
- <property name="visible">True</property>
- <property name="xscale">0</property>
- <property name="yscale">0</property>
- <child>
- <object class="GtkHBox" id="hbox13">
- <property name="visible">True</property>
- <property name="spacing">2</property>
- <child>
- <object class="GtkImage" id="image4">
- <property name="visible">True</property>
- <property name="stock">gtk-apply</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label60">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Accept</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">GTK_PACK_END</property>
- </packing>
- </child>
- </object>
- </child>
- <action-widgets>
- <action-widget response="-6">sslreject</action-widget>
- <action-widget response="-5">sslaccept</action-widget>
- </action-widgets>
- </object>
-</interface>
diff --git a/frontends/gtk/res/ssl.gtk3.ui b/frontends/gtk/res/ssl.gtk3.ui
deleted file mode 100644
index dace2a49e..000000000
--- a/frontends/gtk/res/ssl.gtk3.ui
+++ /dev/null
@@ -1,181 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<interface>
- <!-- interface-requires gtk+ 3.0 -->
- <object class="GtkImage" id="image2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="stock">gtk-apply</property>
- </object>
- <object class="GtkImage" id="image3">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="stock">gtk-cancel</property>
- </object>
- <object class="GtkDialog" id="wndSSLProblem">
- <property name="can_focus">False</property>
- <property name="border_width">5</property>
- <property name="default_width">440</property>
- <property name="default_height">260</property>
- <property name="destroy_with_parent">True</property>
- <property name="type_hint">dialog</property>
- <child internal-child="vbox">
- <object class="GtkBox" id="dialog-vbox1">
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <property name="spacing">2</property>
- <child internal-child="action_area">
- <object class="GtkButtonBox" id="dialog-action_area1">
- <property name="can_focus">False</property>
- <property name="layout_style">end</property>
- <child>
- <object class="GtkButton" id="sslreject">
- <property name="label" translatable="yes">_Reject</property>
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_action_appearance">False</property>
- <property name="image">image3</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="sslaccept">
- <property name="label" translatable="yes">_Accept</property>
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_action_appearance">False</property>
- <property name="image">image2</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox" id="box1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkBox" id="box2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkImage" id="image1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_right">8</property>
- <property name="stock">gtk-dialog-warning</property>
- <property name="icon-size">6</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">NetSurf failed to verify the authenticity of an SSL certificate. Please verify the details presented below.</property>
- <property name="wrap">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkFrame" id="frame1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- <child>
- <object class="GtkAlignment" id="alignment1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="left_padding">12</property>
- <child>
- <object class="GtkScrolledWindow" id="SSLScrolled">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="shadow_type">in</property>
- <child>
- <object class="GtkViewport" id="SSLViewport">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkDrawingArea" id="SSLDrawingArea">
- <property name="visible">True</property>
- <property name="app_paintable">True</property>
- <property name="can_focus">True</property>
- <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
- <property name="valign">start</property>
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel" id="label1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">&lt;b&gt;Certificate Chain&lt;/b&gt;</property>
- <property name="use_markup">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- <action-widgets>
- <action-widget response="-6">sslreject</action-widget>
- <action-widget response="-5">sslaccept</action-widget>
- </action-widgets>
- </object>
-</interface>
diff --git a/frontends/gtk/res/tabcontents.gtk2.ui b/frontends/gtk/res/tabcontents.gtk2.ui
deleted file mode 100644
index 63e290e8b..000000000
--- a/frontends/gtk/res/tabcontents.gtk2.ui
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0"?>
-<interface>
- <!-- interface-requires gtk+ 2.12 -->
- <!-- interface-naming-policy toplevel-contextual -->
- <object class="GtkTable" id="tabContents">
- <property name="visible">True</property>
- <property name="n_rows">2</property>
- <property name="n_columns">2</property>
- <child>
- <object class="GtkLayout" id="layout">
- <property name="visible">True</property>
- <property name="app_paintable">True</property>
- <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK | GDK_SCROLL_MASK</property>
- <property name="hadjustment">layouthadjustment</property>
- <property name="vadjustment">layoutvadjustment</property>
- </object>
- </child>
- <child>
- <object class="GtkStatusbar" id="resizer">
- <property name="height_request">1</property>
- <property name="visible">True</property>
- <property name="spacing">2</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <object class="GtkHPaned" id="hpaned1">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <child>
- <object class="GtkLabel" id="status_bar">
- <property name="width_request">1</property>
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">4</property>
- <property name="label" translatable="yes">Status</property>
- </object>
- <packing>
- <property name="resize">False</property>
- <property name="shrink">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkHScrollbar" id="hscrollbar">
- <property name="visible">True</property>
- <property name="adjustment">layouthadjustment</property>
- </object>
- <packing>
- <property name="resize">True</property>
- <property name="shrink">True</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <object class="GtkVScrollbar" id="vscrollbar">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <property name="adjustment">layoutvadjustment</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="x_options"></property>
- </packing>
- </child>
- </object>
- <object class="GtkAdjustment" id="layouthadjustment">
- <property name="upper">100</property>
- <property name="step_increment">30</property>
- <property name="page_increment">10</property>
- <property name="page_size">10</property>
- </object>
- <object class="GtkAdjustment" id="layoutvadjustment">
- <property name="upper">100</property>
- <property name="step_increment">30</property>
- <property name="page_increment">10</property>
- <property name="page_size">10</property>
- </object>
-</interface>
diff --git a/frontends/gtk/res/tabcontents.gtk3.ui b/frontends/gtk/res/tabcontents.gtk3.ui
deleted file mode 100644
index 23328b3b7..000000000
--- a/frontends/gtk/res/tabcontents.gtk3.ui
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<interface>
- <!-- interface-requires gtk+ 3.0 -->
- <object class="GtkAdjustment" id="layouthadjustment">
- <property name="upper">100</property>
- <property name="step_increment">1</property>
- <property name="page_increment">10</property>
- </object>
- <object class="GtkAdjustment" id="layoutvadjustment">
- <property name="upper">100</property>
- <property name="step_increment">1</property>
- <property name="page_increment">10</property>
- </object>
- <object class="GtkGrid" id="tabContents">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="row_spacing">2</property>
- <property name="column_spacing">2</property>
- <child>
- <object class="GtkLayout" id="layout">
- <property name="visible">True</property>
- <property name="app_paintable">True</property>
- <property name="can_focus">False</property>
- <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK | GDK_SCROLL_MASK</property>
- <property name="hadjustment">layouthadjustment</property>
- <property name="vadjustment">layoutvadjustment</property>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkScrollbar" id="vscrollbar">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="vexpand">True</property>
- <property name="orientation">vertical</property>
- <property name="adjustment">layoutvadjustment</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkPaned" id="hpaned1">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hexpand">True</property>
- <child>
- <object class="GtkLabel" id="status_bar">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="xalign">0</property>
- <property name="xpad">4</property>
- <property name="label" translatable="yes">Status</property>
- <property name="single_line_mode">True</property>
- </object>
- <packing>
- <property name="resize">False</property>
- <property name="shrink">True</property>
- </packing>
- </child>
- <child>
- <object class="GtkScrollbar" id="hscrollbar">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="adjustment">layouthadjustment</property>
- </object>
- <packing>
- <property name="resize">True</property>
- <property name="shrink">True</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <placeholder/>
- </child>
- </object>
-</interface>
diff --git a/frontends/gtk/res/toolbar.gtk2.ui b/frontends/gtk/res/toolbar.gtk2.ui
deleted file mode 100644
index 4e8805a6f..000000000
--- a/frontends/gtk/res/toolbar.gtk2.ui
+++ /dev/null
@@ -1,172 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<interface>
- <!-- interface-requires gtk+ 2.12 -->
- <!-- interface-naming-policy toplevel-contextual -->
- <object class="GtkDialog" id="dialogToolbar">
- <property name="width_request">700</property>
- <property name="height_request">450</property>
- <property name="can_focus">False</property>
- <property name="border_width">5</property>
- <property name="title" translatable="yes">gtkToolBarTitle</property>
- <property name="window_position">center-on-parent</property>
- <property name="destroy_with_parent">True</property>
- <property name="type_hint">dialog</property>
- <child internal-child="vbox">
- <object class="GtkVBox" id="dialog-vbox1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">2</property>
- <child>
- <object class="GtkHBox" id="hbox1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="homogeneous">True</property>
- <child>
- <object class="GtkLabel" id="label1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Move items from store to toolbar</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Rearrange items in toolbar</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label3">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Move items from toolbar to store</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">2</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkScrolledWindow" id="scrolledwindow1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</property>
- <child>
- <object class="GtkViewport" id="viewport1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkVBox" id="widgetvbox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <placeholder/>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child internal-child="action_area">
- <object class="GtkHButtonBox" id="dialog-action_area1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="layout_style">end</property>
- <child>
- <object class="GtkButton" id="reset">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <child>
- <object class="GtkHBox" id="button1hbox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkImage" id="image1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="stock">gtk-refresh</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="refreshbuttonlabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Reset to defaults</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">10</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="close">
- <property name="label">gtk-close</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- </child>
- <action-widgets>
- <action-widget response="0">reset</action-widget>
- <action-widget response="0">close</action-widget>
- </action-widgets>
- </object>
-</interface>
diff --git a/frontends/gtk/res/toolbar.gtk3.ui b/frontends/gtk/res/toolbar.gtk3.ui
deleted file mode 100644
index 1f1148703..000000000
--- a/frontends/gtk/res/toolbar.gtk3.ui
+++ /dev/null
@@ -1,137 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.18.3 -->
-<!--*- mode: xml -*-->
-<interface>
- <requires lib="gtk+" version="3.0"/>
- <object class="GtkImage" id="image2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="stock">gtk-refresh</property>
- </object>
- <object class="GtkDialog" id="dialogToolbar">
- <property name="width_request">700</property>
- <property name="height_request">450</property>
- <property name="can_focus">False</property>
- <property name="title" translatable="yes">gtkToolBarTitle</property>
- <property name="type_hint">dialog</property>
- <child internal-child="vbox">
- <object class="GtkBox" id="dialog-vbox1">
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <property name="spacing">2</property>
- <child internal-child="action_area">
- <object class="GtkButtonBox" id="dialog-action_area1">
- <property name="can_focus">False</property>
- <property name="layout_style">end</property>
- <child>
- <object class="GtkButton" id="reset">
- <property name="label" translatable="yes">Reset To Defaults</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="image">image2</property>
- <property name="yalign">0.52999997138977051</property>
- <property name="always_show_image">True</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="close">
- <property name="label">gtk-close</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkGrid" id="grid1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="column_homogeneous">True</property>
- <child>
- <object class="GtkLabel" id="label1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Move items from store to toolbar</property>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Rearrange items in toolbar</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label3">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Move items from toolbar to store</property>
- </object>
- <packing>
- <property name="left_attach">2</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkScrolledWindow" id="scrolledwindow1">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <child>
- <object class="GtkViewport" id="viewport1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkVBox" id="widgetvbox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <placeholder/>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
-</interface>
diff --git a/frontends/gtk/res/ui.gresource.xml b/frontends/gtk/res/ui.gresource.xml
new file mode 100644
index 000000000..dd43ddf59
--- /dev/null
+++ b/frontends/gtk/res/ui.gresource.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/netsurf">
+ <file>cookies.ui</file>
+ <file>downloads.ui</file>
+ <file>globalhistory.ui</file>
+ <file>hotlist.ui</file>
+ <file>localhistory.ui</file>
+ <file>netsurf.ui</file>
+ <file>options.ui</file>
+ <file>pageinfo.ui</file>
+ <file>password.ui</file>
+ <file>tabcontents.ui</file>
+ <file>toolbar.ui</file>
+ <file>viewdata.ui</file>
+ <file>warning.ui</file>
+ </gresource>
+</gresources>
diff --git a/frontends/gtk/res/zh_CN/credits.html b/frontends/gtk/res/zh_CN/credits.html
new file mode 120000
index 000000000..6fd96ea63
--- /dev/null
+++ b/frontends/gtk/res/zh_CN/credits.html
@@ -0,0 +1 @@
+../../../../resources/zh_CN/credits.html \ No newline at end of file
diff --git a/frontends/gtk/res/zh_CN/licence.html b/frontends/gtk/res/zh_CN/licence.html
new file mode 120000
index 000000000..d757031d5
--- /dev/null
+++ b/frontends/gtk/res/zh_CN/licence.html
@@ -0,0 +1 @@
+../../../../resources/zh_CN/licence.html \ No newline at end of file
diff --git a/frontends/gtk/res/zh_CN/welcome.html b/frontends/gtk/res/zh_CN/welcome.html
new file mode 120000
index 000000000..fa10c2a20
--- /dev/null
+++ b/frontends/gtk/res/zh_CN/welcome.html
@@ -0,0 +1 @@
+../../../../resources/zh_CN/welcome.html \ No newline at end of file
diff --git a/frontends/gtk/resources.c b/frontends/gtk/resources.c
index fc3ac6ff3..fc17f7418 100644
--- a/frontends/gtk/resources.c
+++ b/frontends/gtk/resources.c
@@ -77,8 +77,6 @@ static struct nsgtk_resource_s ui_resource[] = {
RES_ENTRY("netsurf"),
RES_ENTRY("tabcontents"),
RES_ENTRY("password"),
- RES_ENTRY("login"),
- RES_ENTRY("ssl"),
RES_ENTRY("toolbar"),
RES_ENTRY("downloads"),
RES_ENTRY("globalhistory"),
@@ -88,6 +86,7 @@ static struct nsgtk_resource_s ui_resource[] = {
RES_ENTRY("cookies"),
RES_ENTRY("viewdata"),
RES_ENTRY("warning"),
+ RES_ENTRY("pageinfo"),
{ NULL, 0, NSGTK_RESOURCE_FILE, NULL },
};
@@ -96,7 +95,18 @@ static struct nsgtk_resource_s pixbuf_resource[] = {
RES_ENTRY("favicon.png"),
RES_ENTRY("netsurf.xpm"),
RES_ENTRY("menu_cursor.png"),
- RES_ENTRY("arrow_down_8x32.png"),
+ RES_ENTRY("icons/local-history.png"),
+ RES_ENTRY("icons/show-cookie.png"),
+ RES_ENTRY("icons/24x24/actions/page-info-insecure.png"),
+ RES_ENTRY("icons/24x24/actions/page-info-internal.png"),
+ RES_ENTRY("icons/24x24/actions/page-info-local.png"),
+ RES_ENTRY("icons/24x24/actions/page-info-secure.png"),
+ RES_ENTRY("icons/24x24/actions/page-info-warning.png"),
+ RES_ENTRY("icons/48x48/actions/page-info-insecure.png"),
+ RES_ENTRY("icons/48x48/actions/page-info-internal.png"),
+ RES_ENTRY("icons/48x48/actions/page-info-local.png"),
+ RES_ENTRY("icons/48x48/actions/page-info-secure.png"),
+ RES_ENTRY("icons/48x48/actions/page-info-warning.png"),
RES_ENTRY("throbber/throbber0.png"),
RES_ENTRY("throbber/throbber1.png"),
RES_ENTRY("throbber/throbber2.png"),
@@ -114,7 +124,6 @@ static struct nsgtk_resource_s direct_resource[] = {
RES_ENTRY("welcome.html"),
RES_ENTRY("credits.html"),
RES_ENTRY("licence.html"),
- RES_ENTRY("maps.html"),
RES_ENTRY("default.css"),
RES_ENTRY("adblock.css"),
RES_ENTRY("internal.css"),
@@ -336,11 +345,6 @@ init_pixbuf_resource(char **respath, struct nsgtk_resource_s *resource)
*/
static nserror init_ui_resource(char **respath, struct nsgtk_resource_s *ui_res)
{
-#if GTK_CHECK_VERSION(3,0,0)
- int gtkv = 3;
-#else
- int gtkv = 2;
-#endif
int resnamelen;
char *resname;
struct nsgtk_resource_s resource;
@@ -352,7 +356,7 @@ static nserror init_ui_resource(char **respath, struct nsgtk_resource_s *ui_res)
if (resname == NULL) {
return NSERROR_NOMEM;
}
- snprintf(resname, resnamelen, "%s.gtk%d.ui", ui_res->name, gtkv);
+ snprintf(resname, resnamelen, "%s.ui", ui_res->name);
resource.name = resname;
resource.len = ui_res->len;
resource.path = NULL;
diff --git a/frontends/gtk/scaffolding.c b/frontends/gtk/scaffolding.c
index 6f81e91db..f9d4f6d67 100644
--- a/frontends/gtk/scaffolding.c
+++ b/frontends/gtk/scaffolding.c
@@ -1,6 +1,5 @@
/*
- * Copyright 2006 Rob Kendrick <rjek@rjek.com>
- * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ * Copyright 2019 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -17,92 +16,51 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <assert.h>
+#include <gtk/gtk.h>
#include <stdbool.h>
-#include <stdio.h>
-#include <errno.h>
#include <stdlib.h>
-#include <unistd.h>
#include <string.h>
-#include <gtk/gtk.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
#include "utils/utils.h"
-#include "utils/dirent.h"
-#include "utils/messages.h"
-#include "utils/corestrings.h"
#include "utils/log.h"
-#include "utils/nsoption.h"
-#include "utils/file.h"
+#include "utils/messages.h"
#include "utils/nsurl.h"
-#include "netsurf/content.h"
-#include "netsurf/keypress.h"
+#include "utils/nsoption.h"
#include "netsurf/browser_window.h"
-#include "netsurf/plotters.h"
#include "desktop/browser_history.h"
#include "desktop/hotlist.h"
-#include "desktop/print.h"
-#include "desktop/save_complete.h"
-#ifdef WITH_PDF_EXPORT
-#include "desktop/font_haru.h"
-#include "desktop/save_pdf.h"
-#endif
-#include "desktop/save_text.h"
-#include "desktop/searchweb.h"
-#include "desktop/search.h"
#include "gtk/compat.h"
-#include "gtk/warn.h"
-#include "gtk/cookies.h"
-#include "gtk/completion.h"
-#include "gtk/preferences.h"
-#include "gtk/about.h"
-#include "gtk/viewsource.h"
-#include "gtk/bitmap.h"
-#include "gtk/gui.h"
-#include "gtk/global_history.h"
+#include "gtk/toolbar_items.h"
+#include "gtk/menu.h"
#include "gtk/local_history.h"
-#include "gtk/hotlist.h"
+#include "gtk/gui.h"
#include "gtk/download.h"
-#include "gtk/menu.h"
-#include "gtk/plotters.h"
-#include "gtk/print.h"
-#include "gtk/search.h"
-#include "gtk/throbber.h"
-#include "gtk/toolbar.h"
#include "gtk/window.h"
-#include "gtk/gdk.h"
-#include "gtk/scaffolding.h"
+#include "gtk/warn.h"
#include "gtk/tabs.h"
-#include "gtk/schedule.h"
-#include "gtk/viewdata.h"
#include "gtk/resources.h"
-#include "gtk/layout_pango.h"
-
-/** Macro to define a handler for menu, button and activate events. */
-#define MULTIHANDLER(q)\
-static gboolean nsgtk_on_##q##_activate(struct nsgtk_scaffolding *g);\
-static gboolean nsgtk_on_##q##_activate_menu(GtkMenuItem *widget, gpointer data)\
-{\
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;\
- return nsgtk_on_##q##_activate(g);\
-}\
-static gboolean nsgtk_on_##q##_activate_button(GtkButton *widget, gpointer data)\
-{\
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;\
- return nsgtk_on_##q##_activate(g);\
-}\
-static gboolean nsgtk_on_##q##_activate(struct nsgtk_scaffolding *g)
-
-/** Macro to define a handler for menu events. */
-#define MENUHANDLER(q)\
-static gboolean nsgtk_on_##q##_activate_menu(GtkMenuItem *widget, gpointer data)
-
-/** Macro to define a handler for button events. */
-#define BUTTONHANDLER(q)\
-static gboolean nsgtk_on_##q##_activate(GtkButton *widget, gpointer data)
-
-/** Core scaffolding structure. */
+#include "gtk/scaffolding.h"
+
+
+/**
+ * menu entry context
+ */
+struct nsgtk_menu {
+ GtkWidget *main; /* main menu entry */
+ GtkWidget *burger; /* right click menu */
+ GtkWidget *popup; /* popup menu entry */
+ /**
+ * menu item handler
+ */
+ gboolean (*mhandler)(GtkMenuItem *widget, gpointer data);
+ const char *iconname; /* name of the icon to use */
+ bool sensitivity; /* menu item is sensitive */
+};
+
+/**
+ * Core scaffolding structure.
+ */
struct nsgtk_scaffolding {
/** global linked list of scaffolding for gui interface adjustments */
struct nsgtk_scaffolding *next, *prev;
@@ -115,45 +73,37 @@ struct nsgtk_scaffolding {
/** scaffold container window */
GtkWindow *window;
- bool fullscreen; /**< flag for the scaffold window fullscreen status */
/** tab widget holding displayed pages */
GtkNotebook *notebook;
- /** entry widget holding the url of the current displayed page */
- GtkWidget *url_bar;
- GtkEntryCompletion *url_bar_completion; /**< Completions for url_bar */
-
- /** Activity throbber */
- GtkImage *throbber;
- int throb_frame; /**< Current frame of throbber animation */
-
- struct gtk_search *search;
- /** Web search widget */
- GtkWidget *webSearchEntry;
-
- /** controls toolbar */
- GtkToolbar *tool_bar;
- struct nsgtk_button_connect *buttons[PLACEHOLDER_BUTTON];
- int offset;
- int toolbarmem;
- int toolbarbase;
- int historybase;
+ /** handler id for tabs remove callback */
+ gulong tabs_remove_handler_id;
/** menu bar hierarchy */
struct nsgtk_bar_submenu *menu_bar;
+ /** burger menu hierarchy */
+ struct nsgtk_burger_menu *burger_menu;
+
/** right click popup menu hierarchy */
- struct nsgtk_popup_menu *menu_popup;
+ struct nsgtk_popup_menu *popup_menu;
/** link popup menu */
struct nsgtk_link_menu *link_menu;
+
+ /** menu entries widgets for sensitivity adjustment */
+ struct nsgtk_menu menus[PLACEHOLDER_BUTTON];
};
-/** current scaffold for model dialogue use */
+/**
+ * current scaffold for model dialogue use
+ */
static struct nsgtk_scaffolding *scaf_current;
-/** global list for interface changes */
+/**
+ * global list for interface changes
+ */
static struct nsgtk_scaffolding *scaf_list = NULL;
/**
@@ -167,45 +117,31 @@ static struct browser_window_features current_menu_features;
* Helper to hide popup menu entries by grouping.
*
* \param menu The popup menu to modify.
- * \param submenu flag to indicate if submenus should be hidden.
* \param nav flag to indicate if navigation entries should be hidden.
* \param cnp flag to indicate if cut and paste entries should be hidden.
* \param custom flag to indicate if menu customisation is hidden.
*/
static void
-popup_menu_hide(struct nsgtk_popup_menu *menu,
- bool submenu,
- bool nav,
- bool cnp,
- bool custom)
+popup_menu_hide(struct nsgtk_popup_menu *menu, bool nav, bool cnp)
{
- if (submenu) {
- gtk_widget_hide(GTK_WIDGET(menu->file_menuitem));
- gtk_widget_hide(GTK_WIDGET(menu->edit_menuitem));
- gtk_widget_hide(GTK_WIDGET(menu->view_menuitem));
- gtk_widget_hide(GTK_WIDGET(menu->nav_menuitem));
- gtk_widget_hide(GTK_WIDGET(menu->help_menuitem));
-
- gtk_widget_hide(menu->first_separator);
- }
-
if (nav) {
gtk_widget_hide(GTK_WIDGET(menu->back_menuitem));
gtk_widget_hide(GTK_WIDGET(menu->forward_menuitem));
gtk_widget_hide(GTK_WIDGET(menu->stop_menuitem));
gtk_widget_hide(GTK_WIDGET(menu->reload_menuitem));
+
+ gtk_widget_hide(menu->first_separator);
}
if (cnp) {
gtk_widget_hide(GTK_WIDGET(menu->cut_menuitem));
gtk_widget_hide(GTK_WIDGET(menu->copy_menuitem));
gtk_widget_hide(GTK_WIDGET(menu->paste_menuitem));
- }
- if (custom) {
- gtk_widget_hide(GTK_WIDGET(menu->customize_menuitem));
+ gtk_widget_hide(menu->second_separator);
}
+
}
@@ -213,48 +149,32 @@ popup_menu_hide(struct nsgtk_popup_menu *menu,
* Helper to show popup menu entries by grouping.
*
* \param menu The popup menu to modify.
- * \param submenu flag to indicate if submenus should be visible.
* \param nav flag to indicate if navigation entries should be visible.
* \param cnp flag to indicate if cut and paste entries should be visible.
* \param custom flag to indicate if menu customisation is visible.
*/
static void
-popup_menu_show(struct nsgtk_popup_menu *menu,
- bool submenu,
- bool nav,
- bool cnp,
- bool custom)
+popup_menu_show(struct nsgtk_popup_menu *menu, bool nav, bool cnp)
{
- if (submenu) {
- gtk_widget_show(GTK_WIDGET(menu->file_menuitem));
- gtk_widget_show(GTK_WIDGET(menu->edit_menuitem));
- gtk_widget_show(GTK_WIDGET(menu->view_menuitem));
- gtk_widget_show(GTK_WIDGET(menu->nav_menuitem));
- gtk_widget_show(GTK_WIDGET(menu->help_menuitem));
-
- gtk_widget_show(menu->first_separator);
- }
-
if (nav) {
gtk_widget_show(GTK_WIDGET(menu->back_menuitem));
gtk_widget_show(GTK_WIDGET(menu->forward_menuitem));
gtk_widget_show(GTK_WIDGET(menu->stop_menuitem));
gtk_widget_show(GTK_WIDGET(menu->reload_menuitem));
+
+ gtk_widget_show(menu->first_separator);
}
if (cnp) {
gtk_widget_show(GTK_WIDGET(menu->cut_menuitem));
gtk_widget_show(GTK_WIDGET(menu->copy_menuitem));
gtk_widget_show(GTK_WIDGET(menu->paste_menuitem));
- }
- if (custom) {
- gtk_widget_show(GTK_WIDGET(menu->customize_menuitem));
+ gtk_widget_show(menu->second_separator);
}
-}
+}
-/* event handlers and support functions for them */
/**
* resource cleanup function for window destruction.
@@ -273,6 +193,18 @@ static void scaffolding_window_destroy(GtkWidget *widget, gpointer data)
nsgtk_local_history_hide();
+ /* ensure scaffolding being destroyed is not current */
+ if (scaf_current == gs) {
+ scaf_current = NULL;
+ /* attempt to select nearest scaffold instead of just selecting the first */
+ if (gs->prev != NULL) {
+ scaf_current = gs->prev;
+ } else if (gs->next != NULL) {
+ scaf_current = gs->next;
+ }
+ }
+
+ /* remove scaffolding from list */
if (gs->prev != NULL) {
gs->prev->next = gs->next;
} else {
@@ -284,6 +216,16 @@ static void scaffolding_window_destroy(GtkWidget *widget, gpointer data)
NSLOG(netsurf, INFO, "scaffold list head: %p", scaf_list);
+ /* ensure menu resources are freed */
+ nsgtk_menu_bar_destroy(gs->menu_bar);
+ nsgtk_burger_menu_destroy(gs->burger_menu);
+ nsgtk_popup_menu_destroy(gs->popup_menu);
+ nsgtk_link_menu_destroy(gs->link_menu);
+
+ g_signal_handler_disconnect(gs->notebook, gs->tabs_remove_handler_id);
+
+ free(gs);
+
if (scaf_list == NULL) {
/* no more open windows - stop the browser */
nsgtk_complete = true;
@@ -326,100 +268,74 @@ static void scaffolding_update_context(struct nsgtk_scaffolding *g)
{
struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- g->buttons[BACK_BUTTON]->sensitivity =
- browser_window_history_back_available(bw);
- g->buttons[FORWARD_BUTTON]->sensitivity =
- browser_window_history_forward_available(bw);
+ g->menus[BACK_BUTTON].sensitivity =
+ browser_window_history_back_available(bw);
+ g->menus[FORWARD_BUTTON].sensitivity =
+ browser_window_history_forward_available(bw);
nsgtk_scaffolding_set_sensitivity(g);
- /* update the url bar, particularly necessary when tabbing */
- browser_window_refresh_url_bar(bw);
-
nsgtk_local_history_hide();
}
/**
- * Make the throbber run.
- *
- * scheduled callback to update the throbber
- *
- * \param p The context passed when scheduled.
- */
-static void nsgtk_throb(void *p)
-{
- struct nsgtk_scaffolding *g = p;
-
- if (g->throb_frame >= (nsgtk_throbber->nframes - 1)) {
- g->throb_frame = 1;
- } else {
- g->throb_frame++;
- }
-
- gtk_image_set_from_pixbuf(g->throbber,
- nsgtk_throbber->framedata[g->throb_frame]);
-
- nsgtk_schedule(100, nsgtk_throb, p);
-}
-
-
-/**
* edit the sensitivity of focused widget
*
+ * \todo this needs to update toolbar sensitivity
+ *
* \param g The scaffolding context.
*/
static guint
-nsgtk_scaffolding_update_edit_actions_sensitivity(
- struct nsgtk_scaffolding *g)
+nsgtk_scaffolding_update_edit_actions_sensitivity(struct nsgtk_scaffolding *g)
{
GtkWidget *widget = gtk_window_get_focus(g->window);
- gboolean has_selection;
if (GTK_IS_EDITABLE(widget)) {
+ gboolean has_selection;
has_selection = gtk_editable_get_selection_bounds(
- GTK_EDITABLE (widget), NULL, NULL);
-
- g->buttons[COPY_BUTTON]->sensitivity = has_selection;
- g->buttons[CUT_BUTTON]->sensitivity = has_selection;
- g->buttons[PASTE_BUTTON]->sensitivity = true;
+ GTK_EDITABLE(widget), NULL, NULL);
+ g->menus[COPY_BUTTON].sensitivity = has_selection;
+ g->menus[CUT_BUTTON].sensitivity = has_selection;
+ g->menus[PASTE_BUTTON].sensitivity = true;
} else {
struct browser_window *bw =
- nsgtk_get_browser_window(g->top_level);
+ nsgtk_get_browser_window(g->top_level);
browser_editor_flags edit_f =
- browser_window_get_editor_flags(bw);
-
- g->buttons[COPY_BUTTON]->sensitivity =
- edit_f & BW_EDITOR_CAN_COPY;
- g->buttons[CUT_BUTTON]->sensitivity =
- edit_f & BW_EDITOR_CAN_CUT;
- g->buttons[PASTE_BUTTON]->sensitivity =
- edit_f & BW_EDITOR_CAN_PASTE;
+ browser_window_get_editor_flags(bw);
+
+ g->menus[COPY_BUTTON].sensitivity =
+ edit_f & BW_EDITOR_CAN_COPY;
+ g->menus[CUT_BUTTON].sensitivity =
+ edit_f & BW_EDITOR_CAN_CUT;
+ g->menus[PASTE_BUTTON].sensitivity =
+ edit_f & BW_EDITOR_CAN_PASTE;
}
nsgtk_scaffolding_set_sensitivity(g);
- return ((g->buttons[COPY_BUTTON]->sensitivity) |
- (g->buttons[CUT_BUTTON]->sensitivity) |
- (g->buttons[PASTE_BUTTON]->sensitivity));
+
+ return ((g->menus[COPY_BUTTON].sensitivity) |
+ (g->menus[CUT_BUTTON].sensitivity) |
+ (g->menus[PASTE_BUTTON].sensitivity));
}
/**
* make edit actions sensitive
*
+ * \todo toolbar sensitivity
+ *
* \param g The scaffolding context.
*/
static void
-nsgtk_scaffolding_enable_edit_actions_sensitivity(
- struct nsgtk_scaffolding *g)
+nsgtk_scaffolding_enable_edit_actions_sensitivity(struct nsgtk_scaffolding *g)
{
-
- g->buttons[PASTE_BUTTON]->sensitivity = true;
- g->buttons[COPY_BUTTON]->sensitivity = true;
- g->buttons[CUT_BUTTON]->sensitivity = true;
+ g->menus[PASTE_BUTTON].sensitivity = true;
+ g->menus[COPY_BUTTON].sensitivity = true;
+ g->menus[CUT_BUTTON].sensitivity = true;
nsgtk_scaffolding_set_sensitivity(g);
- popup_menu_show(g->menu_popup, false, false, true, false);
+ popup_menu_show(g->popup_menu, false, true);
}
/* signal handling functions for the toolbar, URL bar, and menu bar */
@@ -456,6 +372,7 @@ nsgtk_window_edit_menu_hidden(GtkWidget *widget,
return TRUE;
}
+
/**
* gtk event handler for popup menu being hidden.
*
@@ -463,80 +380,10 @@ nsgtk_window_edit_menu_hidden(GtkWidget *widget,
* \param g scaffolding handle
* \return TRUE to indicate event handled
*/
-static gboolean nsgtk_window_popup_menu_hidden(GtkWidget *widget,
- struct nsgtk_scaffolding *g)
-{
- nsgtk_scaffolding_enable_edit_actions_sensitivity(g);
- return TRUE;
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-gboolean nsgtk_window_url_activate_event(GtkWidget *widget, gpointer data)
-{
- struct nsgtk_scaffolding *g = data;
- nserror ret;
- nsurl *url;
-
- ret = search_web_omni(gtk_entry_get_text(GTK_ENTRY(g->url_bar)),
- SEARCH_WEB_OMNI_NONE,
- &url);
- if (ret == NSERROR_OK) {
- ret = browser_window_navigate(nsgtk_get_browser_window(g->top_level),
- url, NULL, BW_NAVIGATE_HISTORY,
- NULL, NULL, NULL);
- nsurl_unref(url);
- }
- if (ret != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(ret), 0);
- }
-
- return TRUE;
-}
-
-
-/**
- * update handler for URL entry widget
- *
- * \param widget The widget receiving the delete event
- * \param event The event
- * \param data The context pointer passed when the connection was made.
- * \return TRUE to indicate signal handled.
- */
-gboolean
-nsgtk_window_url_changed(GtkWidget *widget,
- GdkEventKey *event,
- gpointer data)
-{
- return nsgtk_completion_update(GTK_ENTRY(widget));
-}
-
-
-/**
- * Event handler for popup menu on toolbar.
- *
- * \param toolbar The toolbar being clicked
- * \param x The x coordinate where the click happened
- * \param y The x coordinate where the click happened
- * \param button the buttons being pressed
- * \param data The context pointer passed when the connection was made.
- * \return TRUE to indicate event handled.
- */
static gboolean
-nsgtk_window_tool_bar_clicked(GtkToolbar *toolbar,
- gint x,
- gint y,
- gint button,
- gpointer data)
+nsgtk_window_popup_menu_hidden(GtkWidget *widget, struct nsgtk_scaffolding *g)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
-
- /* set visibility for right-click popup menu */
- popup_menu_hide(g->menu_popup, true, false, true, false);
- popup_menu_show(g->menu_popup, false, false, false, true);
-
- gtk_menu_popup(g->menu_popup->popup_menu, NULL, NULL, NULL, NULL, 0,
- gtk_get_current_event_time());
-
+ nsgtk_scaffolding_enable_edit_actions_sensitivity(g);
return TRUE;
}
@@ -544,6 +391,9 @@ nsgtk_window_tool_bar_clicked(GtkToolbar *toolbar,
/**
* Update the menus when the number of tabs changes.
*
+ * \todo toolbar sensitivity
+ * \todo next/previous tab ought to only be visible if there is such a tab
+ *
* \param notebook The notebook all the tabs are in
* \param page The newly added page container widget
* \param page_num The index of the newly added page
@@ -557,12 +407,18 @@ nsgtk_window_tabs_add(GtkNotebook *notebook,
{
gboolean visible = gtk_notebook_get_show_tabs(g->notebook);
g_object_set(g->menu_bar->view_submenu->tabs_menuitem,
- "visible", visible, NULL);
- g_object_set(g->menu_popup->view_submenu->tabs_menuitem,
- "visible", visible, NULL);
- g->buttons[NEXTTAB_BUTTON]->sensitivity = visible;
- g->buttons[PREVTAB_BUTTON]->sensitivity = visible;
- g->buttons[CLOSETAB_BUTTON]->sensitivity = visible;
+ "visible",
+ visible,
+ NULL);
+ g_object_set(g->burger_menu->view_submenu->tabs_menuitem,
+ "visible",
+ visible,
+ NULL);
+
+ g->menus[NEXTTAB_BUTTON].sensitivity = visible;
+ g->menus[PREVTAB_BUTTON].sensitivity = visible;
+ g->menus[CLOSETAB_BUTTON].sensitivity = visible;
+
nsgtk_scaffolding_set_sensitivity(g);
}
@@ -570,6 +426,8 @@ nsgtk_window_tabs_add(GtkNotebook *notebook,
/**
* Update the menus when the number of tabs changes.
*
+ * \todo toolbar sensitivity
+ *
* \param notebook The notebook all the tabs are in
* \param page The page container widget being removed
* \param page_num The index of the removed page
@@ -581,6 +439,8 @@ nsgtk_window_tabs_remove(GtkNotebook *notebook,
guint page_num,
struct nsgtk_scaffolding *gs)
{
+ gboolean visible;
+
/* if the scaffold is being destroyed it is not useful to
* update the state, further many of the widgets may have
* already been destroyed.
@@ -595,472 +455,46 @@ nsgtk_window_tabs_remove(GtkNotebook *notebook,
return;
}
- gboolean visible = gtk_notebook_get_show_tabs(gs->notebook);
- g_object_set(gs->menu_bar->view_submenu->tabs_menuitem, "visible", visible, NULL);
- g_object_set(gs->menu_popup->view_submenu->tabs_menuitem, "visible", visible, NULL);
- gs->buttons[NEXTTAB_BUTTON]->sensitivity = visible;
- gs->buttons[PREVTAB_BUTTON]->sensitivity = visible;
- gs->buttons[CLOSETAB_BUTTON]->sensitivity = visible;
- nsgtk_scaffolding_set_sensitivity(gs);
-}
-
-/**
- * Handle opening a file path.
- *
- * \param filename The filename to open.
- */
-static void nsgtk_openfile_open(const char *filename)
-{
- struct browser_window *bw;
- char *urltxt;
- nsurl *url;
- nserror error;
-
- bw = nsgtk_get_browser_window(scaf_current->top_level);
-
- urltxt = malloc(strlen(filename) + FILE_SCHEME_PREFIX_LEN + 1);
-
- if (urltxt != NULL) {
- sprintf(urltxt, FILE_SCHEME_PREFIX"%s", filename);
-
- error = nsurl_create(urltxt, &url);
- if (error != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(error), 0);
- } else {
- browser_window_navigate(bw,
- url,
- NULL,
- BW_NAVIGATE_HISTORY,
- NULL,
- NULL,
- NULL);
- nsurl_unref(url);
- }
- free(urltxt);
- }
-}
-
-/* signal handlers for menu entries */
-
-MULTIHANDLER(newwindow)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- const char *addr;
- nsurl *url;
- nserror error;
-
- if (nsoption_charp(homepage_url) != NULL) {
- addr = nsoption_charp(homepage_url);
- } else {
- addr = NETSURF_HOMEPAGE;
- }
-
- error = nsurl_create(addr, &url);
- if (error == NSERROR_OK) {
- error = browser_window_create(BW_CREATE_HISTORY,
- url,
- NULL,
- bw,
- NULL);
- nsurl_unref(url);
- }
- if (error != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(error), 0);
- }
-
- return TRUE;
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-nserror nsgtk_scaffolding_new_tab(struct gui_window *gw)
-{
- struct browser_window *bw = nsgtk_get_browser_window(gw);
- nsurl *url = NULL;
- nserror error;
-
- if (!nsoption_bool(new_blank)) {
- const char *addr;
- if (nsoption_charp(homepage_url) != NULL) {
- addr = nsoption_charp(homepage_url);
- } else {
- addr = NETSURF_HOMEPAGE;
- }
- error = nsurl_create(addr, &url);
- if (error != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(error), 0);
- }
- }
-
- error = browser_window_create(BW_CREATE_HISTORY |
- BW_CREATE_TAB,
- url,
- NULL,
- bw,
- NULL);
- if (url != NULL) {
- nsurl_unref(url);
- }
- return error;
-}
+ visible = gtk_notebook_get_show_tabs(gs->notebook);
+ g_object_set(gs->menu_bar->view_submenu->tabs_menuitem,
+ "visible", visible, NULL);
+ g_object_set(gs->burger_menu->view_submenu->tabs_menuitem,
+ "visible", visible, NULL);
-MULTIHANDLER(newtab)
-{
- nserror error;
+ gs->menus[NEXTTAB_BUTTON].sensitivity = visible;
+ gs->menus[PREVTAB_BUTTON].sensitivity = visible;
+ gs->menus[CLOSETAB_BUTTON].sensitivity = visible;
- error = nsgtk_scaffolding_new_tab(g->top_level);
- if (error != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(error), 0);
- }
- return TRUE;
+ nsgtk_scaffolding_set_sensitivity(gs);
}
-MULTIHANDLER(openfile)
-{
- GtkWidget *dlgOpen;
- gint response;
-
- scaf_current = g;
- dlgOpen = gtk_file_chooser_dialog_new("Open File",
- scaf_current->window,
- GTK_FILE_CHOOSER_ACTION_OPEN,
- NSGTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- NSGTK_STOCK_OPEN, GTK_RESPONSE_OK,
- NULL, NULL);
-
- response = gtk_dialog_run(GTK_DIALOG(dlgOpen));
- if (response == GTK_RESPONSE_OK) {
- gchar *filename;
- filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlgOpen));
-
- nsgtk_openfile_open((const char *)filename);
-
- g_free(filename);
- }
- gtk_widget_destroy(dlgOpen);
- return TRUE;
-}
+/* signal handlers for menu entries */
/**
- * callback to determine if a path is a directory.
- *
- * \param info The path information
- * \param data context pointer set to NULL
- * \return TRUE if path is a directory else false
+ * handle menu activate signals by calling toolbar item activation
*/
-static gboolean
-nsgtk_filter_directory(const GtkFileFilterInfo *info,
- gpointer data)
-{
- DIR *d = opendir(info->filename);
- if (d == NULL)
- return FALSE;
- closedir(d);
- return TRUE;
-}
-
-MULTIHANDLER(savepage)
-{
- if (!browser_window_has_content(nsgtk_get_browser_window(g->top_level)))
- return FALSE;
-
- GtkWidget *fc = gtk_file_chooser_dialog_new(
- messages_get("gtkcompleteSave"), g->window,
- GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER,
- NSGTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- NSGTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- NULL);
- DIR *d;
- char *path;
- nserror res;
- GtkFileFilter *filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "Directories");
- gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME,
- nsgtk_filter_directory, NULL, NULL);
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fc), filter);
- gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(fc), filter);
-
- res = nsurl_nice(browser_window_get_url(
- nsgtk_get_browser_window(g->top_level)), &path, false);
- if (res != NSERROR_OK) {
- path = strdup(messages_get("SaveText"));
- if (path == NULL) {
- nsgtk_warning("NoMemory", 0);
- return FALSE;
- }
- }
-
- if (access(path, F_OK) != 0)
- gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(fc), path);
- free(path);
-
- gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(fc),
- TRUE);
-
- if (gtk_dialog_run(GTK_DIALOG(fc)) != GTK_RESPONSE_ACCEPT) {
- gtk_widget_destroy(fc);
- return TRUE;
- }
-
- path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fc));
- d = opendir(path);
- if (d == NULL) {
- NSLOG(netsurf, INFO,
- "Unable to open directory %s for complete save: %s",
- path,
- strerror(errno));
- if (errno == ENOTDIR)
- nsgtk_warning("NoDirError", path);
- else
- nsgtk_warning("gtkFileError", path);
- gtk_widget_destroy(fc);
- g_free(path);
- return TRUE;
- }
- closedir(d);
- save_complete(browser_window_get_content(nsgtk_get_browser_window(
- g->top_level)), path, NULL);
- g_free(path);
-
- gtk_widget_destroy(fc);
-
- return TRUE;
-}
-
-
-MULTIHANDLER(pdf)
-{
-#ifdef WITH_PDF_EXPORT
-
- GtkWidget *save_dialog;
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- struct print_settings *settings;
- char filename[PATH_MAX];
- char dirname[PATH_MAX];
- char *url_name;
- nserror res;
-
- NSLOG(netsurf, INFO, "Print preview (generating PDF) started.");
-
- res = nsurl_nice(browser_window_get_url(bw), &url_name, true);
- if (res != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(res), 0);
- return TRUE;
- }
-
- strncpy(filename, url_name, PATH_MAX);
- strncat(filename, ".pdf", PATH_MAX - strlen(filename));
- filename[PATH_MAX - 1] = '\0';
-
- free(url_name);
-
- strncpy(dirname, option_downloads_directory, PATH_MAX);
- strncat(dirname, "/", PATH_MAX - strlen(dirname));
- dirname[PATH_MAX - 1] = '\0';
-
- /* this way the scale used by PDF functions is synchronised with that
- * used by the all-purpose print interface
- */
- haru_nsfont_set_scale((float)option_export_scale / 100);
-
- save_dialog = gtk_file_chooser_dialog_new("Export to PDF", g->window,
- GTK_FILE_CHOOSER_ACTION_SAVE,
- NSGTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- NSGTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- NULL);
-
- gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(save_dialog),
- dirname);
-
- gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(save_dialog),
- filename);
-
- if (gtk_dialog_run(GTK_DIALOG(save_dialog)) == GTK_RESPONSE_ACCEPT) {
- gchar *filename = gtk_file_chooser_get_filename(
- GTK_FILE_CHOOSER(save_dialog));
-
- settings = print_make_settings(PRINT_OPTIONS,
- (const char *) filename, &haru_nsfont);
- g_free(filename);
-
- if (settings == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- gtk_widget_destroy(save_dialog);
- return TRUE;
- }
-
- /* This will clean up the print_settings object for us */
- print_basic_run(browser_window_get_content(bw),
- &pdf_printer, settings);
- }
-
- gtk_widget_destroy(save_dialog);
-
-#endif /* WITH_PDF_EXPORT */
-
- return TRUE;
-}
-
-MULTIHANDLER(plaintext)
-{
- if (!browser_window_has_content(nsgtk_get_browser_window(g->top_level)))
- return FALSE;
-
- GtkWidget *fc = gtk_file_chooser_dialog_new(
- messages_get("gtkplainSave"), g->window,
- GTK_FILE_CHOOSER_ACTION_SAVE,
- NSGTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- NSGTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- NULL);
- char *filename;
- nserror res;
-
- res = nsurl_nice(browser_window_get_url(
- nsgtk_get_browser_window(g->top_level)),
- &filename, false);
- if (res != NSERROR_OK) {
- filename = strdup(messages_get("SaveText"));
- if (filename == NULL) {
- nsgtk_warning("NoMemory", 0);
- return FALSE;
- }
- }
-
- gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(fc), filename);
- gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(fc),
- TRUE);
+#define TOOLBAR_ITEM_p(identifier, name) \
+ static gboolean \
+nsgtk_on_##name##_activate_menu(GtkMenuItem *widget, gpointer data) \
+{ \
+ struct nsgtk_scaffolding *gs = (struct nsgtk_scaffolding *)data;\
+ nsgtk_window_item_activate(gs->top_level, identifier); \
+ return TRUE; \
+}
+#define TOOLBAR_ITEM_y(identifier, name)
+#define TOOLBAR_ITEM_n(identifier, name)
+#define TOOLBAR_ITEM(identifier, name, sensitivity, clicked, activate, label, iconame) \
+ TOOLBAR_ITEM_ ## activate(identifier, name)
+#include "gtk/toolbar_items.h"
+#undef TOOLBAR_ITEM_y
+#undef TOOLBAR_ITEM_n
+#undef TOOLBAR_ITEM_p
+#undef TOOLBAR_ITEM
- free(filename);
- if (gtk_dialog_run(GTK_DIALOG(fc)) == GTK_RESPONSE_ACCEPT) {
- filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fc));
- save_as_text(browser_window_get_content(
- nsgtk_get_browser_window(
- g->top_level)), filename);
- g_free(filename);
- }
-
- gtk_widget_destroy(fc);
- return TRUE;
-}
-
-MULTIHANDLER(drawfile)
-{
- return TRUE;
-}
-
-MULTIHANDLER(postscript)
-{
- return TRUE;
-}
-
-MULTIHANDLER(printpreview)
-{
- return TRUE;
-}
-
-
-MULTIHANDLER(print)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
-
- GtkPrintOperation *print_op;
- GtkPageSetup *page_setup;
- GtkPrintSettings *print_settings;
- GtkPrintOperationResult res = GTK_PRINT_OPERATION_RESULT_ERROR;
- struct print_settings *nssettings;
- char *settings_fname = NULL;
-
- print_op = gtk_print_operation_new();
- if (print_op == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- return TRUE;
- }
-
- /* use previously saved settings if any */
- netsurf_mkpath(&settings_fname, NULL, 2, nsgtk_config_home, "Print");
- if (settings_fname != NULL) {
- print_settings = gtk_print_settings_new_from_file(settings_fname, NULL);
- if (print_settings != NULL) {
- gtk_print_operation_set_print_settings(print_op,
- print_settings);
-
- /* We're not interested in the settings any more */
- g_object_unref(print_settings);
- }
- }
-
- content_to_print = browser_window_get_content(bw);
-
- page_setup = gtk_print_run_page_setup_dialog(g->window, NULL, NULL);
- if (page_setup == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- free(settings_fname);
- g_object_unref(print_op);
- return TRUE;
- }
- gtk_print_operation_set_default_page_setup(print_op, page_setup);
-
- nssettings = print_make_settings(PRINT_DEFAULT, NULL, nsgtk_layout_table);
-
- g_signal_connect(print_op, "begin_print",
- G_CALLBACK(gtk_print_signal_begin_print), nssettings);
- g_signal_connect(print_op, "draw_page",
- G_CALLBACK(gtk_print_signal_draw_page), NULL);
- g_signal_connect(print_op, "end_print",
- G_CALLBACK(gtk_print_signal_end_print), nssettings);
-
- if (content_get_type(browser_window_get_content(bw)) !=
- CONTENT_TEXTPLAIN) {
- res = gtk_print_operation_run(print_op,
- GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
- g->window,
- NULL);
- }
-
- /* if the settings were used save them for future use */
- if (settings_fname != NULL) {
- if (res == GTK_PRINT_OPERATION_RESULT_APPLY) {
- /* Do not increment the settings reference */
- print_settings =
- gtk_print_operation_get_print_settings(print_op);
-
- gtk_print_settings_to_file(print_settings,
- settings_fname,
- NULL);
- }
- free(settings_fname);
- }
-
- /* Our print_settings object is destroyed by the end print handler */
- g_object_unref(page_setup);
- g_object_unref(print_op);
-
- return TRUE;
-}
-
-MULTIHANDLER(closewindow)
-{
- gtk_widget_destroy(GTK_WIDGET(g->window));
- return TRUE;
-}
-
-MULTIHANDLER(quit)
-{
- struct nsgtk_scaffolding *gs;
-
- if (nsgtk_check_for_downloads(g->window) == false) {
- gs = scaf_list;
- while (gs != NULL) {
- gtk_widget_destroy(GTK_WIDGET(gs->window));
- gs = gs->next;
- }
- }
-
- return TRUE;
-}
-
-MENUHANDLER(savelink)
+static gboolean
+nsgtk_on_savelink_activate_menu(GtkMenuItem *widget, gpointer data)
{
struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *) data;
struct gui_window *gui = g->top_level;
@@ -1084,10 +518,12 @@ MENUHANDLER(savelink)
return TRUE;
}
+
/**
* Handler for opening new window from a link. attached to the popup menu.
*/
-MENUHANDLER(link_openwin)
+static gboolean
+nsgtk_on_link_openwin_activate_menu(GtkMenuItem *widget, gpointer data)
{
struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *) data;
struct gui_window *gui = g->top_level;
@@ -1106,10 +542,12 @@ MENUHANDLER(link_openwin)
return TRUE;
}
+
/**
* Handler for opening new tab from a link. attached to the popup menu.
*/
-MENUHANDLER(link_opentab)
+static gboolean
+nsgtk_on_link_opentab_activate_menu(GtkMenuItem *widget, gpointer data)
{
struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *) data;
struct gui_window *gui = g->top_level;
@@ -1119,8 +557,6 @@ MENUHANDLER(link_opentab)
if (current_menu_features.link == NULL)
return FALSE;
- temp_open_background = 1;
-
err = browser_window_create(BW_CREATE_CLONE |
BW_CREATE_HISTORY |
BW_CREATE_TAB,
@@ -1129,15 +565,15 @@ MENUHANDLER(link_opentab)
nsgtk_warning(messages_get_errorcode(err), 0);
}
- temp_open_background = -1;
-
return TRUE;
}
+
/**
* Handler for bookmarking a link. attached to the popup menu.
*/
-MENUHANDLER(link_bookmark)
+static gboolean
+nsgtk_on_link_bookmark_activate_menu(GtkMenuItem *widget, gpointer data)
{
if (current_menu_features.link == NULL)
return FALSE;
@@ -1147,10 +583,12 @@ MENUHANDLER(link_bookmark)
return TRUE;
}
+
/**
* Handler for copying a link. attached to the popup menu.
*/
-MENUHANDLER(link_copy)
+static gboolean
+nsgtk_on_link_copy_activate_menu(GtkMenuItem *widget, gpointer data)
{
GtkClipboard *clipboard;
@@ -1165,624 +603,346 @@ MENUHANDLER(link_copy)
}
-MULTIHANDLER(cut)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- GtkWidget *focused = gtk_window_get_focus(g->window);
-
- /* If the url bar has focus, let gtk handle it */
- if (GTK_IS_EDITABLE (focused))
- gtk_editable_cut_clipboard (GTK_EDITABLE(g->url_bar));
- else
- browser_window_key_press(bw, NS_KEY_CUT_SELECTION);
-
- return TRUE;
-}
-
-MULTIHANDLER(copy)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- GtkWidget *focused = gtk_window_get_focus(g->window);
-
- /* If the url bar has focus, let gtk handle it */
- if (GTK_IS_EDITABLE (focused))
- gtk_editable_copy_clipboard(GTK_EDITABLE(g->url_bar));
- else
- browser_window_key_press(bw, NS_KEY_COPY_SELECTION);
-
- return TRUE;
-}
-
-MULTIHANDLER(paste)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- GtkWidget *focused = gtk_window_get_focus(g->window);
-
- /* If the url bar has focus, let gtk handle it */
- if (GTK_IS_EDITABLE (focused))
- gtk_editable_paste_clipboard (GTK_EDITABLE (focused));
- else
- browser_window_key_press(bw, NS_KEY_PASTE);
-
- return TRUE;
-}
-
-MULTIHANDLER(delete)
-{
- return TRUE;
-}
-
-MENUHANDLER(customize)
+static gboolean nsgtk_on_find_activate_menu(GtkMenuItem *widget, gpointer data)
{
struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- nsgtk_toolbar_customization_init(g);
- return TRUE;
-}
-
-MULTIHANDLER(selectall)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- if (nsgtk_widget_has_focus(GTK_WIDGET(g->url_bar))) {
- NSLOG(netsurf, INFO, "Selecting all URL bar text");
- gtk_editable_select_region(GTK_EDITABLE(g->url_bar), 0, -1);
- } else {
- NSLOG(netsurf, INFO, "Selecting all document text");
- browser_window_key_press(bw, NS_KEY_SELECT_ALL);
- }
+ nsgtk_window_search_toggle(g->top_level);
return TRUE;
}
-MULTIHANDLER(find)
+static nserror get_bar_show(bool *menu, bool *tool)
{
- nsgtk_scaffolding_toggle_search_bar_visibility(g);
- return TRUE;
-}
+ const char *cur_bar_show;
-MULTIHANDLER(preferences)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- GtkWidget* wndpreferences;
+ *menu = false;
+ *tool = false;
- wndpreferences = nsgtk_preferences(bw, g->window);
- if (wndpreferences != NULL) {
- gtk_widget_show(GTK_WIDGET(wndpreferences));
+ cur_bar_show = nsoption_charp(bar_show);
+ if (cur_bar_show != NULL) {
+ if (strcmp(cur_bar_show, "menu/tool") == 0) {
+ *menu = true;
+ *tool = true;
+ } else if (strcmp(cur_bar_show, "menu") == 0) {
+ *menu = true;
+ } else if (strcmp(cur_bar_show, "tool") == 0) {
+ *tool = true;
+ }
}
- return TRUE;
-}
-
-MULTIHANDLER(zoomplus)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- float old_scale = nsgtk_get_scale_for_gui(g->top_level);
-
- browser_window_set_scale(bw, old_scale + 0.05, true);
-
- return TRUE;
-}
-
-MULTIHANDLER(zoomnormal)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
-
- browser_window_set_scale(bw, 1.0, true);
-
- return TRUE;
+ return NSERROR_OK;
}
-MULTIHANDLER(zoomminus)
+static nserror set_bar_show(const char *bar, bool show)
{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- float old_scale = nsgtk_get_scale_for_gui(g->top_level);
+ bool menu;
+ bool tool;
+ const char *new_bar_show;
- browser_window_set_scale(bw, old_scale - 0.05, true);
+ get_bar_show(&menu, &tool);
- return TRUE;
-}
+ if (strcmp(bar, "menu") == 0) {
+ menu = show;
+ } else if (strcmp(bar, "tool") == 0) {
+ tool = show;
+ }
-MULTIHANDLER(fullscreen)
-{
- if (g->fullscreen) {
- gtk_window_unfullscreen(g->window);
+ if ((menu == true) && (tool == true)) {
+ new_bar_show = "menu/tool";
+ } else if (menu == true) {
+ new_bar_show = "menu";
+ } else if (tool == true) {
+ new_bar_show = "tool";
} else {
- gtk_window_fullscreen(g->window);
+ new_bar_show = "none";
}
+ nsoption_set_charp(bar_show, strdup(new_bar_show));
- g->fullscreen = !g->fullscreen;
-
- return TRUE;
+ return NSERROR_OK;
}
-MULTIHANDLER(viewsource)
+static gboolean
+nsgtk_on_menubar_activate_menu(GtkMenuItem *widget, gpointer data)
{
- nserror ret;
+ struct nsgtk_scaffolding *gs = (struct nsgtk_scaffolding *)data;
+ GtkCheckMenuItem *bmcmi; /* burger menu check */
+ GtkCheckMenuItem *mbcmi; /* menu bar check */
+ GtkCheckMenuItem *tbcmi; /* popup menu check */
- ret = nsgtk_viewsource(g->window, nsgtk_get_browser_window(g->top_level));
- if (ret != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(ret), 0);
- }
-
- return TRUE;
-}
-
-MENUHANDLER(menubar)
-{
- GtkWidget *w;
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
+ bmcmi = GTK_CHECK_MENU_ITEM(gs->burger_menu->view_submenu->toolbars_submenu->menubar_menuitem);
+ mbcmi = GTK_CHECK_MENU_ITEM(gs->menu_bar->view_submenu->toolbars_submenu->menubar_menuitem);
+ tbcmi = GTK_CHECK_MENU_ITEM(gs->popup_menu->toolbars_submenu->menubar_menuitem);
- /* if the menubar is not being shown the popup menu shows the
- * menubar entries instead.
- */
+ /* ensure menubar and burger menu checkboxes are both updated */
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
- /* need to synchronise menus as gtk grumbles when one menu
- * is attached to both headers */
- w = GTK_WIDGET(g->menu_popup->view_submenu->toolbars_submenu->menubar_menuitem);
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))
- == FALSE)
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
- TRUE);
-
- w = GTK_WIDGET(g->menu_bar->view_submenu->toolbars_submenu->menubar_menuitem);
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))
- == FALSE)
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
- TRUE);
-
- gtk_widget_show(GTK_WIDGET(g->menu_bar->bar_menu));
-
- popup_menu_show(g->menu_popup, false, true, true, true);
- popup_menu_hide(g->menu_popup, true, false, false, false);
- } else {
- w = GTK_WIDGET(g->menu_popup->view_submenu->toolbars_submenu->menubar_menuitem);
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
- FALSE);
-
- w = GTK_WIDGET(g->menu_bar->view_submenu->toolbars_submenu->menubar_menuitem);
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
- FALSE);
-
- gtk_widget_hide(GTK_WIDGET(g->menu_bar->bar_menu));
-
- popup_menu_show(g->menu_popup, true, true, true, true);
+ if (gtk_check_menu_item_get_active(bmcmi) == FALSE) {
+ gtk_check_menu_item_set_active(bmcmi, TRUE);
+ }
- }
- return TRUE;
-}
+ if (gtk_check_menu_item_get_active(mbcmi) == FALSE) {
+ gtk_check_menu_item_set_active(mbcmi, TRUE);
+ }
-MENUHANDLER(toolbar)
-{
- GtkWidget *w;
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
+ if (gtk_check_menu_item_get_active(tbcmi) == FALSE) {
+ gtk_check_menu_item_set_active(tbcmi, TRUE);
+ }
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
- w = GTK_WIDGET(g->menu_popup->view_submenu->toolbars_submenu->toolbar_menuitem);
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))
- == FALSE)
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
- TRUE);
-
- w = GTK_WIDGET(g->menu_bar->view_submenu->toolbars_submenu->toolbar_menuitem);
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))
- == FALSE)
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
- TRUE);
- gtk_widget_show(GTK_WIDGET(g->tool_bar));
+ gtk_widget_show(GTK_WIDGET(gs->menu_bar->bar_menu));
+ set_bar_show("menu", true);
} else {
- w = GTK_WIDGET(g->menu_popup->view_submenu->toolbars_submenu->toolbar_menuitem);
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
- FALSE);
- w = GTK_WIDGET(g->menu_bar->view_submenu->toolbars_submenu->toolbar_menuitem);
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
- FALSE);
- gtk_widget_hide(GTK_WIDGET(g->tool_bar));
- }
-
- return TRUE;
-}
-
-MULTIHANDLER(downloads)
-{
- nsgtk_download_show(g->window);
-
- return TRUE;
-}
-
-MULTIHANDLER(savewindowsize)
-{
- int x,y,w,h;
- char *choices = NULL;
+ if (gtk_check_menu_item_get_active(bmcmi) == TRUE) {
+ gtk_check_menu_item_set_active(bmcmi, FALSE);
+ }
- gtk_window_get_position(g->window, &x, &y);
- gtk_window_get_size(g->window, &w, &h);
+ if (gtk_check_menu_item_get_active(mbcmi) == TRUE) {
+ gtk_check_menu_item_set_active(mbcmi, FALSE);
+ }
- nsoption_set_int(window_width, w);
- nsoption_set_int(window_height, h);
- nsoption_set_int(window_x, x);
- nsoption_set_int(window_y, y);
+ if (gtk_check_menu_item_get_active(tbcmi) == TRUE) {
+ gtk_check_menu_item_set_active(tbcmi, FALSE);
+ }
- netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices");
- if (choices != NULL) {
- nsoption_write(choices, NULL, NULL);
- free(choices);
+ gtk_widget_hide(GTK_WIDGET(gs->menu_bar->bar_menu));
+ set_bar_show("menu", false);
}
-
return TRUE;
}
-MULTIHANDLER(toggledebugging)
-{
- struct browser_window *bw;
-
- bw = nsgtk_get_browser_window(g->top_level);
-
- browser_window_debug(bw, CONTENT_DEBUG_REDRAW);
-
- nsgtk_reflow_all_windows();
-
- return TRUE;
-}
-MULTIHANDLER(debugboxtree)
+static gboolean
+nsgtk_on_toolbar_activate_menu(GtkMenuItem *widget, gpointer data)
{
- gchar *fname;
- gint handle;
- FILE *f;
- struct browser_window *bw;
+ struct nsgtk_scaffolding *gs = (struct nsgtk_scaffolding *)data;
+ GtkCheckMenuItem *bmcmi; /* burger menu check */
+ GtkCheckMenuItem *mbcmi; /* menu bar check */
+ GtkCheckMenuItem *tbcmi; /* popup menu check */
- handle = g_file_open_tmp("nsgtkboxtreeXXXXXX", &fname, NULL);
- if ((handle == -1) || (fname == NULL)) {
- return TRUE;
- }
- close(handle); /* in case it was binary mode */
-
- /* save data to temporary file */
- f = fopen(fname, "w");
- if (f == NULL) {
- nsgtk_warning("Error saving box tree dump.",
- "Unable to open file for writing.");
- unlink(fname);
- return TRUE;
- }
-
- bw = nsgtk_get_browser_window(g->top_level);
+ bmcmi = GTK_CHECK_MENU_ITEM(gs->burger_menu->view_submenu->toolbars_submenu->toolbar_menuitem);
+ mbcmi = GTK_CHECK_MENU_ITEM(gs->menu_bar->view_submenu->toolbars_submenu->toolbar_menuitem);
+ tbcmi = GTK_CHECK_MENU_ITEM(gs->popup_menu->toolbars_submenu->toolbar_menuitem);
- browser_window_debug_dump(bw, f, CONTENT_DEBUG_RENDER);
+ /* ensure menubar and burger menu checkboxes are both updated */
+ if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
+ if (gtk_check_menu_item_get_active(bmcmi) == FALSE) {
+ gtk_check_menu_item_set_active(bmcmi, TRUE);
+ }
- fclose(f);
+ if (gtk_check_menu_item_get_active(mbcmi) == FALSE) {
+ gtk_check_menu_item_set_active(mbcmi, TRUE);
+ }
- nsgtk_viewfile("Box Tree Debug", "boxtree", fname);
+ if (gtk_check_menu_item_get_active(tbcmi) == FALSE) {
+ gtk_check_menu_item_set_active(tbcmi, TRUE);
+ }
- g_free(fname);
+ nsgtk_window_toolbar_show(gs, true);
+ set_bar_show("tool", true);
+ } else {
+ if (gtk_check_menu_item_get_active(bmcmi) == TRUE) {
+ gtk_check_menu_item_set_active(bmcmi, FALSE);
+ }
- return TRUE;
-}
+ if (gtk_check_menu_item_get_active(mbcmi) == TRUE) {
+ gtk_check_menu_item_set_active(mbcmi, FALSE);
+ }
-MULTIHANDLER(debugdomtree)
-{
- gchar *fname;
- gint handle;
- FILE *f;
- struct browser_window *bw;
+ if (gtk_check_menu_item_get_active(tbcmi) == TRUE) {
+ gtk_check_menu_item_set_active(tbcmi, FALSE);
+ }
- handle = g_file_open_tmp("nsgtkdomtreeXXXXXX", &fname, NULL);
- if ((handle == -1) || (fname == NULL)) {
- return TRUE;
+ nsgtk_window_toolbar_show(gs, false);
+ set_bar_show("tool", false);
}
- close(handle); /* in case it was binary mode */
-
- /* save data to temporary file */
- f = fopen(fname, "w");
- if (f == NULL) {
- nsgtk_warning("Error saving box tree dump.",
- "Unable to open file for writing.");
- unlink(fname);
- return TRUE;
- }
-
- bw = nsgtk_get_browser_window(g->top_level);
-
- browser_window_debug_dump(bw, f, CONTENT_DEBUG_DOM);
-
- fclose(f);
-
- nsgtk_viewfile("DOM Tree Debug", "domtree", fname);
-
- g_free(fname);
-
return TRUE;
}
-MULTIHANDLER(stop)
+static gboolean
+nsgtk_on_nexttab_activate_menu(GtkMenuItem *widget, gpointer data)
{
- struct browser_window *bw =
- nsgtk_get_browser_window(g->top_level);
+ struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- browser_window_stop(bw);
+ nsgtk_tab_next(g->notebook);
return TRUE;
}
-MULTIHANDLER(reload)
-{
- struct browser_window *bw =
- nsgtk_get_browser_window(g->top_level);
- if (bw == NULL)
- return TRUE;
-
- /* clear potential search effects */
- browser_window_search_clear(bw);
- browser_window_reload(bw, true);
-
- return TRUE;
-}
-
-MULTIHANDLER(back)
+static gboolean
+nsgtk_on_prevtab_activate_menu(GtkMenuItem *widget, gpointer data)
{
- struct browser_window *bw =
- nsgtk_get_browser_window(g->top_level);
-
- if ((bw == NULL) || (!browser_window_history_back_available(bw)))
- return TRUE;
-
- /* clear potential search effects */
- browser_window_search_clear(bw);
+ struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- browser_window_history_back(bw, false);
- scaffolding_update_context(g);
+ nsgtk_tab_prev(g->notebook);
return TRUE;
}
-MULTIHANDLER(forward)
-{
- struct browser_window *bw =
- nsgtk_get_browser_window(g->top_level);
-
- if ((bw == NULL) || (!browser_window_history_forward_available(bw)))
- return TRUE;
-
- /* clear potential search effects */
- browser_window_search_clear(bw);
-
- browser_window_history_forward(bw, false);
- scaffolding_update_context(g);
-
- return TRUE;
-}
-MULTIHANDLER(home)
+/**
+ * menu signal handler for activation on close tab item
+ */
+static gboolean
+nsgtk_on_closetab_activate_menu(GtkMenuItem *widget, gpointer data)
{
- static const char *addr = NETSURF_HOMEPAGE;
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- nsurl *url;
- nserror error;
-
- if (nsoption_charp(homepage_url) != NULL) {
- addr = nsoption_charp(homepage_url);
- }
+ struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- error = nsurl_create(addr, &url);
- if (error != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(error), 0);
- } else {
- browser_window_navigate(bw,
- url,
- NULL,
- BW_NAVIGATE_HISTORY,
- NULL,
- NULL,
- NULL);
- nsurl_unref(url);
- }
+ nsgtk_tab_close_current(g->notebook);
return TRUE;
}
-MULTIHANDLER(localhistory)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- nserror res;
+/* end of menu callback handlers */
- res = nsgtk_local_history_present(g->window, bw);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Unable to initialise local history window.");
+/**
+ * attach gtk signal handlers for menus
+ */
+static void nsgtk_menu_connect_signals(struct nsgtk_scaffolding *g)
+{
+ int idx; /* item index */
+ for (idx = BACK_BUTTON; idx < PLACEHOLDER_BUTTON; idx++) {
+ if (g->menus[idx].main != NULL) {
+ g_signal_connect(g->menus[idx].main,
+ "activate",
+ G_CALLBACK(g->menus[idx].mhandler),
+ g);
+ }
+ if (g->menus[idx].burger != NULL) {
+ g_signal_connect(g->menus[idx].burger,
+ "activate",
+ G_CALLBACK(g->menus[idx].mhandler),
+ g);
+ }
+ if (g->menus[idx].popup != NULL) {
+ g_signal_connect(g->menus[idx].popup,
+ "activate",
+ G_CALLBACK(g->menus[idx].mhandler),
+ g);
+ }
}
- return TRUE;
}
-MULTIHANDLER(globalhistory)
-{
- nserror res;
- res = nsgtk_global_history_present();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Unable to initialise global history window.");
- }
- return TRUE;
-}
-MULTIHANDLER(addbookmarks)
+/**
+ * Create and connect handlers to bar menu.
+ *
+ * \param gs scaffolding to attach popup menu to.
+ * \param group The accelerator group to use for the popup.
+ * \param showmenu if the bar menu should be shown
+ * \param showtool if the toolabar should be shown
+ * \return menu structure on success or NULL on error.
+ */
+static struct nsgtk_bar_submenu *
+create_scaffolding_bar_menu(struct nsgtk_scaffolding *gs,
+ GtkAccelGroup *group,
+ bool showmenu,
+ bool showtool)
{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
+ GtkMenuShell *menushell;
+ struct nsgtk_bar_submenu *nmenu;
- if (bw == NULL || !browser_window_has_content(bw))
- return TRUE;
- hotlist_add_url(browser_window_get_url(bw));
- return TRUE;
-}
+ menushell = GTK_MENU_SHELL(gtk_builder_get_object(gs->builder,
+ "menubar"));
-MULTIHANDLER(showbookmarks)
-{
- nserror res;
- res = nsgtk_hotlist_present();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to initialise bookmark window.");
+ nmenu = nsgtk_menu_bar_create(menushell, group);
+ if (nmenu == NULL) {
+ return NULL;
}
- return TRUE;
-}
-MULTIHANDLER(showcookies)
-{
- nserror res;
- res = nsgtk_cookies_present();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to initialise cookies window.");
+ /* set menu bar visibility */
+ if (showmenu) {
+ gtk_widget_show(GTK_WIDGET(nmenu->bar_menu));
+ } else {
+ gtk_widget_hide(GTK_WIDGET(nmenu->bar_menu));
}
- return TRUE;
-}
-MULTIHANDLER(openlocation)
-{
- gtk_widget_grab_focus(GTK_WIDGET(g->url_bar));
- return TRUE;
-}
+ /* set checks correct way on toolbar submenu */
+ gtk_check_menu_item_set_active(nmenu->view_submenu->toolbars_submenu->menubar_menuitem, showmenu);
+ gtk_check_menu_item_set_active(nmenu->view_submenu->toolbars_submenu->toolbar_menuitem, showtool);
-MULTIHANDLER(nexttab)
-{
- nsgtk_tab_next(g->notebook);
+ /* bar menu signal handlers for edit controls */
+ g_signal_connect(nmenu->edit_submenu->edit,
+ "show",
+ G_CALLBACK(nsgtk_window_edit_menu_shown),
+ gs);
- return TRUE;
-}
+ g_signal_connect(nmenu->edit_submenu->edit,
+ "hide",
+ G_CALLBACK(nsgtk_window_edit_menu_hidden),
+ gs);
-MULTIHANDLER(prevtab)
-{
+ /*
+ * attach signal handlers for menubar and toolbar visibility toggling
+ */
+ g_signal_connect(nmenu->view_submenu->toolbars_submenu->menubar_menuitem,
+ "toggled",
+ G_CALLBACK(nsgtk_on_menubar_activate_menu),
+ gs);
- nsgtk_tab_prev(g->notebook);
+ g_signal_connect(nmenu->view_submenu->toolbars_submenu->toolbar_menuitem,
+ "toggled",
+ G_CALLBACK(nsgtk_on_toolbar_activate_menu),
+ gs);
- return TRUE;
-}
-MULTIHANDLER(closetab)
-{
- nsgtk_tab_close_current(g->notebook);
-
- return TRUE;
+ return nmenu;
}
-MULTIHANDLER(contents)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- nsurl *url;
- nserror error;
-
- error = nsurl_create("http://www.netsurf-browser.org/documentation/", &url);
- if (error != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(error), 0);
- } else {
- browser_window_navigate(bw,
- url,
- NULL,
- BW_NAVIGATE_HISTORY,
- NULL,
- NULL,
- NULL);
- nsurl_unref(url);
- }
- return TRUE;
-}
-
-MULTIHANDLER(guide)
+/**
+ * Create and connect handlers to burger menu.
+ *
+ * \param g scaffolding to attach popup menu to.
+ * \param group The accelerator group to use for the popup.
+ * \param showbar if the bar menu should be shown
+ * \param showtool if the toolabar should be shown
+ * \return menu structure on success or NULL on error.
+ */
+static struct nsgtk_burger_menu *
+create_scaffolding_burger_menu(struct nsgtk_scaffolding *gs,
+ GtkAccelGroup *group,
+ bool showbar,
+ bool showtool)
{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- nsurl *url;
+ struct nsgtk_burger_menu *nmenu;
- if (nsurl_create("http://www.netsurf-browser.org/documentation/guide", &url) != NSERROR_OK) {
- nsgtk_warning("NoMemory", 0);
- } else {
- browser_window_navigate(bw,
- url,
- NULL,
- BW_NAVIGATE_HISTORY,
- NULL,
- NULL,
- NULL);
- nsurl_unref(url);
- }
+ nmenu = nsgtk_burger_menu_create(group);
- return TRUE;
-}
-
-MULTIHANDLER(info)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- nsurl *url;
-
- if (nsurl_create("http://www.netsurf-browser.org/documentation/info", &url) != NSERROR_OK) {
- nsgtk_warning("NoMemory", 0);
- } else {
- browser_window_navigate(bw,
- url,
- NULL,
- BW_NAVIGATE_HISTORY,
- NULL,
- NULL,
- NULL);
- nsurl_unref(url);
+ if (nmenu == NULL) {
+ return NULL;
}
- return TRUE;
-}
-
-MULTIHANDLER(about)
-{
- nsgtk_about_dialog_init(g->window);
- return TRUE;
-}
+ /* set checks correct way on toolbar submenu */
+ gtk_check_menu_item_set_active(nmenu->view_submenu->toolbars_submenu->menubar_menuitem, showbar);
+ gtk_check_menu_item_set_active(nmenu->view_submenu->toolbars_submenu->toolbar_menuitem, showtool);
-BUTTONHANDLER(history)
-{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- return nsgtk_on_localhistory_activate(g);
+ g_signal_connect(nmenu->view_submenu->toolbars_submenu->menubar_menuitem,
+ "toggled",
+ G_CALLBACK(nsgtk_on_menubar_activate_menu),
+ gs);
+ g_signal_connect(nmenu->view_submenu->toolbars_submenu->toolbar_menuitem,
+ "toggled",
+ G_CALLBACK(nsgtk_on_toolbar_activate_menu),
+ gs);
+ return nmenu;
}
-#undef MULTIHANDLER
-#undef CHECKHANDLER
-#undef BUTTONHANDLER
-
-static void nsgtk_attach_menu_handlers(struct nsgtk_scaffolding *g)
-{
- for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- if (g->buttons[i]->main != NULL) {
- g_signal_connect(g->buttons[i]->main, "activate",
- G_CALLBACK(g->buttons[i]->mhandler), g);
- }
- if (g->buttons[i]->rclick != NULL) {
- g_signal_connect(g->buttons[i]->rclick, "activate",
- G_CALLBACK(g->buttons[i]->mhandler), g);
- }
- if (g->buttons[i]->popup != NULL) {
- g_signal_connect(g->buttons[i]->popup, "activate",
- G_CALLBACK(g->buttons[i]->mhandler), g);
- }
- }
-#define CONNECT_CHECK(q)\
- g_signal_connect(g->menu_bar->view_submenu->toolbars_submenu->q##_menuitem, "toggled", G_CALLBACK(nsgtk_on_##q##_activate_menu), g);\
- g_signal_connect(g->menu_popup->view_submenu->toolbars_submenu->q##_menuitem, "toggled", G_CALLBACK(nsgtk_on_##q##_activate_menu), g)
- CONNECT_CHECK(menubar);
- CONNECT_CHECK(toolbar);
-#undef CONNECT_CHECK
-
-}
/**
* Create and connect handlers to popup menu.
*
- * \param g scaffolding to attach popup menu to.
+ * \param gs scaffolding to attach popup menu to.
* \param group The accelerator group to use for the popup.
+ * \param showbar if the bar menu should be shown
+ * \param showtool if the toolabar should be shown
* \return menu structure on success or NULL on error.
*/
static struct nsgtk_popup_menu *
-nsgtk_new_scaffolding_popup(struct nsgtk_scaffolding *g, GtkAccelGroup *group)
+create_scaffolding_popup_menu(struct nsgtk_scaffolding *gs,
+ GtkAccelGroup *group,
+ bool showbar,
+ bool showtool)
{
struct nsgtk_popup_menu *nmenu;
@@ -1791,28 +951,31 @@ nsgtk_new_scaffolding_popup(struct nsgtk_scaffolding *g, GtkAccelGroup *group)
if (nmenu == NULL) {
return NULL;
}
+ /* set checks correct way on toolbar submenu */
+ gtk_check_menu_item_set_active(nmenu->toolbars_submenu->menubar_menuitem, showbar);
+ gtk_check_menu_item_set_active(nmenu->toolbars_submenu->toolbar_menuitem, showtool);
- g_signal_connect(nmenu->popup_menu, "hide",
- G_CALLBACK(nsgtk_window_popup_menu_hidden), g);
-
- g_signal_connect(nmenu->cut_menuitem, "activate",
- G_CALLBACK(nsgtk_on_cut_activate_menu), g);
-
- g_signal_connect(nmenu->copy_menuitem, "activate",
- G_CALLBACK(nsgtk_on_copy_activate_menu), g);
+ g_signal_connect(nmenu->popup_menu,
+ "hide",
+ G_CALLBACK(nsgtk_window_popup_menu_hidden),
+ gs);
- g_signal_connect(nmenu->paste_menuitem, "activate",
- G_CALLBACK(nsgtk_on_paste_activate_menu), g);
-
- g_signal_connect(nmenu->customize_menuitem, "activate",
- G_CALLBACK(nsgtk_on_customize_activate_menu), g);
+ g_signal_connect(nmenu->toolbars_submenu->menubar_menuitem,
+ "toggled",
+ G_CALLBACK(nsgtk_on_menubar_activate_menu),
+ gs);
+ g_signal_connect(nmenu->toolbars_submenu->toolbar_menuitem,
+ "toggled",
+ G_CALLBACK(nsgtk_on_toolbar_activate_menu),
+ gs);
/* set initial popup menu visibility */
- popup_menu_hide(nmenu, true, false, false, true);
+ popup_menu_hide(nmenu, false, false);
return nmenu;
}
+
/**
* Create and connect handlers to link popup menu.
*
@@ -1821,7 +984,7 @@ nsgtk_new_scaffolding_popup(struct nsgtk_scaffolding *g, GtkAccelGroup *group)
* \return true on success or false on error.
*/
static struct nsgtk_link_menu *
-nsgtk_new_scaffolding_link_popup(struct nsgtk_scaffolding *g, GtkAccelGroup *group)
+create_scaffolding_link_menu(struct nsgtk_scaffolding *g, GtkAccelGroup *group)
{
struct nsgtk_link_menu *nmenu;
@@ -1831,482 +994,261 @@ nsgtk_new_scaffolding_link_popup(struct nsgtk_scaffolding *g, GtkAccelGroup *gro
return NULL;
}
- g_signal_connect(nmenu->save_menuitem, "activate",
- G_CALLBACK(nsgtk_on_savelink_activate_menu), g);
+ g_signal_connect(nmenu->save_menuitem,
+ "activate",
+ G_CALLBACK(nsgtk_on_savelink_activate_menu),
+ g);
- g_signal_connect(nmenu->opentab_menuitem, "activate",
- G_CALLBACK(nsgtk_on_link_opentab_activate_menu), g);
+ g_signal_connect(nmenu->opentab_menuitem,
+ "activate",
+ G_CALLBACK(nsgtk_on_link_opentab_activate_menu),
+ g);
- g_signal_connect(nmenu->openwin_menuitem, "activate",
- G_CALLBACK(nsgtk_on_link_openwin_activate_menu), g);
+ g_signal_connect(nmenu->openwin_menuitem,
+ "activate",
+ G_CALLBACK(nsgtk_on_link_openwin_activate_menu),
+ g);
- g_signal_connect(nmenu->bookmark_menuitem, "activate",
- G_CALLBACK(nsgtk_on_link_bookmark_activate_menu), g);
+ g_signal_connect(nmenu->bookmark_menuitem,
+ "activate",
+ G_CALLBACK(nsgtk_on_link_bookmark_activate_menu),
+ g);
- g_signal_connect(nmenu->copy_menuitem, "activate",
- G_CALLBACK(nsgtk_on_link_copy_activate_menu), g);
+ g_signal_connect(nmenu->copy_menuitem,
+ "activate",
+ G_CALLBACK(nsgtk_on_link_copy_activate_menu),
+ g);
return nmenu;
}
-/* exported interface documented in gtk/scaffolding.h */
-struct nsgtk_scaffolding *nsgtk_current_scaffolding(void)
-{
- if (scaf_current == NULL) {
- scaf_current = scaf_list;
- }
- return scaf_current;
-}
/**
- * init the array g->buttons[]
+ * initialiase the menu signal handlers ready for connection
*/
-static void nsgtk_scaffolding_toolbar_init(struct nsgtk_scaffolding *g)
-{
-#define ITEM_MAIN(p, q, r)\
- g->buttons[p##_BUTTON]->main = g->menu_bar->q->r##_menuitem;\
- g->buttons[p##_BUTTON]->rclick = g->menu_popup->q->r##_menuitem;\
- g->buttons[p##_BUTTON]->mhandler = nsgtk_on_##r##_activate_menu;\
- g->buttons[p##_BUTTON]->bhandler = nsgtk_on_##r##_activate_button;\
- g->buttons[p##_BUTTON]->dataplus = nsgtk_toolbar_##r##_button_data;\
- g->buttons[p##_BUTTON]->dataminus = nsgtk_toolbar_##r##_toolbar_button_data
-
-#define ITEM_SUB(p, q, r, s)\
- g->buttons[p##_BUTTON]->main =\
- g->menu_bar->q->r##_submenu->s##_menuitem;\
- g->buttons[p##_BUTTON]->rclick =\
- g->menu_popup->q->r##_submenu->s##_menuitem;\
- g->buttons[p##_BUTTON]->mhandler =\
- nsgtk_on_##s##_activate_menu;\
- g->buttons[p##_BUTTON]->bhandler =\
- nsgtk_on_##s##_activate_button;\
- g->buttons[p##_BUTTON]->dataplus =\
- nsgtk_toolbar_##s##_button_data;\
- g->buttons[p##_BUTTON]->dataminus =\
- nsgtk_toolbar_##s##_toolbar_button_data
-
-#define ITEM_BUTTON(p, q)\
- g->buttons[p##_BUTTON]->bhandler =\
- nsgtk_on_##q##_activate;\
- g->buttons[p##_BUTTON]->dataplus =\
- nsgtk_toolbar_##q##_button_data;\
- g->buttons[p##_BUTTON]->dataminus =\
- nsgtk_toolbar_##q##_toolbar_button_data
-
-#define ITEM_POP(p, q) \
- g->buttons[p##_BUTTON]->popup = g->menu_popup->q##_menuitem
-
-#define SENSITIVITY(q) \
- g->buttons[q##_BUTTON]->sensitivity = false
-
-#define ITEM_ITEM(p, q)\
- g->buttons[p##_ITEM]->dataplus =\
- nsgtk_toolbar_##q##_button_data;\
- g->buttons[p##_ITEM]->dataminus =\
- nsgtk_toolbar_##q##_toolbar_button_data
-
- ITEM_ITEM(WEBSEARCH, websearch);
- ITEM_ITEM(THROBBER, throbber);
- ITEM_MAIN(NEWWINDOW, file_submenu, newwindow);
- ITEM_MAIN(NEWTAB, file_submenu, newtab);
- ITEM_MAIN(OPENFILE, file_submenu, openfile);
- ITEM_MAIN(PRINT, file_submenu, print);
- ITEM_MAIN(CLOSEWINDOW, file_submenu, closewindow);
- ITEM_MAIN(SAVEPAGE, file_submenu, savepage);
- ITEM_MAIN(PRINTPREVIEW, file_submenu, printpreview);
- ITEM_MAIN(PRINT, file_submenu, print);
- ITEM_MAIN(QUIT, file_submenu, quit);
- ITEM_MAIN(CUT, edit_submenu, cut);
- ITEM_MAIN(COPY, edit_submenu, copy);
- ITEM_MAIN(PASTE, edit_submenu, paste);
- ITEM_MAIN(DELETE, edit_submenu, delete);
- ITEM_MAIN(SELECTALL, edit_submenu, selectall);
- ITEM_MAIN(FIND, edit_submenu, find);
- ITEM_MAIN(PREFERENCES, edit_submenu, preferences);
- ITEM_MAIN(STOP, view_submenu, stop);
- ITEM_POP(STOP, stop);
- ITEM_MAIN(RELOAD, view_submenu, reload);
- ITEM_POP(RELOAD, reload);
- ITEM_MAIN(FULLSCREEN, view_submenu, fullscreen);
- ITEM_MAIN(DOWNLOADS, tools_submenu, downloads);
- ITEM_MAIN(SAVEWINDOWSIZE, view_submenu, savewindowsize);
- ITEM_MAIN(BACK, nav_submenu, back);
- ITEM_POP(BACK, back);
- ITEM_MAIN(FORWARD, nav_submenu, forward);
- ITEM_POP(FORWARD, forward);
- ITEM_MAIN(HOME, nav_submenu, home);
- ITEM_MAIN(LOCALHISTORY, nav_submenu, localhistory);
- ITEM_MAIN(GLOBALHISTORY, nav_submenu, globalhistory);
- ITEM_MAIN(ADDBOOKMARKS, nav_submenu, addbookmarks);
- ITEM_MAIN(SHOWBOOKMARKS, nav_submenu, showbookmarks);
- ITEM_MAIN(SHOWCOOKIES, tools_submenu, showcookies);
- ITEM_MAIN(OPENLOCATION, nav_submenu, openlocation);
- ITEM_MAIN(CONTENTS, help_submenu, contents);
- ITEM_MAIN(INFO, help_submenu, info);
- ITEM_MAIN(GUIDE, help_submenu, guide);
- ITEM_MAIN(ABOUT, help_submenu, about);
- ITEM_SUB(PLAINTEXT, file_submenu, export, plaintext);
- ITEM_SUB(PDF, file_submenu, export, pdf);
- ITEM_SUB(DRAWFILE, file_submenu, export, drawfile);
- ITEM_SUB(POSTSCRIPT, file_submenu, export, postscript);
- ITEM_SUB(ZOOMPLUS, view_submenu, scaleview, zoomplus);
- ITEM_SUB(ZOOMMINUS, view_submenu, scaleview, zoomminus);
- ITEM_SUB(ZOOMNORMAL, view_submenu, scaleview, zoomnormal);
- ITEM_SUB(NEXTTAB, view_submenu, tabs, nexttab);
- ITEM_SUB(PREVTAB, view_submenu, tabs, prevtab);
- ITEM_SUB(CLOSETAB, view_submenu, tabs, closetab);
-
- /* development submenu */
- ITEM_SUB(VIEWSOURCE, tools_submenu, developer, viewsource);
- ITEM_SUB(TOGGLEDEBUGGING, tools_submenu, developer, toggledebugging);
- ITEM_SUB(SAVEBOXTREE, tools_submenu, developer, debugboxtree);
- ITEM_SUB(SAVEDOMTREE, tools_submenu, developer, debugdomtree);
- ITEM_BUTTON(HISTORY, history);
-
- /* disable items that make no sense initially, as well as
- * as-yet-unimplemented items */
- SENSITIVITY(BACK);
- SENSITIVITY(FORWARD);
- SENSITIVITY(STOP);
- SENSITIVITY(PRINTPREVIEW);
- SENSITIVITY(DELETE);
- SENSITIVITY(DRAWFILE);
- SENSITIVITY(POSTSCRIPT);
- SENSITIVITY(NEXTTAB);
- SENSITIVITY(PREVTAB);
- SENSITIVITY(CLOSETAB);
-#ifndef WITH_PDF_EXPORT
- SENSITIVITY(PDF);
-#endif
-
-#undef ITEM_MAIN
-#undef ITEM_SUB
-#undef ITEM_BUTTON
-#undef ITEM_POP
-#undef SENSITIVITY
+static nserror nsgtk_menu_initialise(struct nsgtk_scaffolding *g)
+{
+#define TOOLBAR_ITEM_p(identifier, name, iconame) \
+ g->menus[identifier].mhandler = nsgtk_on_##name##_activate_menu; \
+ g->menus[identifier].iconname = iconame;
+#define TOOLBAR_ITEM_y(identifier, name, iconame) \
+ g->menus[identifier].mhandler = nsgtk_on_##name##_activate_menu; \
+ g->menus[identifier].iconname = iconame;
+#define TOOLBAR_ITEM_n(identifier, name, iconame) \
+ g->menus[identifier].mhandler = NULL; \
+ g->menus[identifier].iconname = iconame;
+#define TOOLBAR_ITEM(identifier, name, snstvty, clicked, activate, label, iconame) \
+ g->menus[identifier].sensitivity = snstvty; \
+ TOOLBAR_ITEM_ ## activate(identifier, name, iconame)
+#include "gtk/toolbar_items.h"
+#undef TOOLBAR_ITEM_y
+#undef TOOLBAR_ITEM_n
+#undef TOOLBAR_ITEM
+
+ /* items on menubar, burger */
+#define ITEM_MB(p, q, r) \
+ g->menus[p##_BUTTON].main = g->menu_bar->r##_submenu->q##_menuitem; \
+ g->menus[p##_BUTTON].burger = g->burger_menu->r##_submenu->q##_menuitem
+
+ /* items on menubar, burger and context popup submenu */
+#define ITEM_MBP(p, q, r) \
+ g->menus[p##_BUTTON].main = g->menu_bar->r##_submenu->q##_menuitem; \
+ g->menus[p##_BUTTON].burger = g->burger_menu->r##_submenu->q##_menuitem; \
+ g->menus[p##_BUTTON].popup = g->popup_menu->r##_submenu->q##_menuitem
+
+ /* items on menubar, burger and context popup */
+#define ITEM_MBp(p, q, r) \
+ g->menus[p##_BUTTON].main = g->menu_bar->r##_submenu->q##_menuitem; \
+ g->menus[p##_BUTTON].burger = g->burger_menu->r##_submenu->q##_menuitem; \
+ g->menus[p##_BUTTON].popup = g->popup_menu->q##_menuitem
+
+
+ /* file menu */
+ ITEM_MB(NEWWINDOW, newwindow, file);
+ ITEM_MB(NEWTAB, newtab, file);
+ ITEM_MB(OPENFILE, openfile, file);
+ ITEM_MB(CLOSEWINDOW, closewindow, file);
+ ITEM_MB(PRINTPREVIEW, printpreview, file);
+ ITEM_MB(PRINT, print, file);
+ ITEM_MB(QUIT, quit, file);
+ /* file - export submenu */
+ ITEM_MB(SAVEPAGE, savepage, file_submenu->export);
+ ITEM_MB(PLAINTEXT, plaintext, file_submenu->export);
+ ITEM_MB(PDF, pdf, file_submenu->export);
+
+ /* edit menu */
+ ITEM_MBp(CUT, cut, edit);
+ ITEM_MBp(COPY, copy, edit);
+ ITEM_MBp(PASTE, paste, edit);
+ ITEM_MB(DELETE, delete, edit);
+ ITEM_MB(SELECTALL, selectall, edit);
+ ITEM_MB(FIND, find, edit);
+ ITEM_MB(PREFERENCES, preferences, edit);
+
+ /* view menu */
+ ITEM_MB(FULLSCREEN, fullscreen, view);
+ ITEM_MB(SAVEWINDOWSIZE, savewindowsize, view);
+ /* view - scale submenu */
+ ITEM_MB(ZOOMPLUS, zoomplus, view_submenu->scaleview);
+ ITEM_MB(ZOOMMINUS, zoomminus, view_submenu->scaleview);
+ ITEM_MB(ZOOMNORMAL, zoomnormal, view_submenu->scaleview);
+ /* view - tabs submenu */
+ ITEM_MB(NEXTTAB, nexttab, view_submenu->tabs);
+ ITEM_MB(PREVTAB, prevtab, view_submenu->tabs);
+ ITEM_MB(CLOSETAB, closetab, view_submenu->tabs);
+ /* view - toolbars submenu */
+ ITEM_MB(CUSTOMIZE, customize, view_submenu->toolbars);
+ g->menus[CUSTOMIZE_BUTTON].popup = g->popup_menu->toolbars_submenu->customize_menuitem;
+
+ /* navigation menu */
+ ITEM_MBp(BACK, back, nav);
+ ITEM_MBp(FORWARD, forward, nav);
+ ITEM_MBp(STOP, stop, nav);
+ ITEM_MBp(RELOAD, reload, nav);
+ ITEM_MB(HOME, home, nav);
+ ITEM_MB(LOCALHISTORY, localhistory, nav);
+ ITEM_MB(GLOBALHISTORY, globalhistory, nav);
+ ITEM_MB(ADDBOOKMARKS, addbookmarks, nav);
+ ITEM_MB(SHOWBOOKMARKS, showbookmarks, nav);
+ ITEM_MB(OPENLOCATION, openlocation, nav);
+
+ /* tools menu */
+ ITEM_MBP(DOWNLOADS, downloads, tools);
+ ITEM_MBP(SHOWCOOKIES, showcookies, tools);
+ /* tools > developer submenu */
+ ITEM_MBP(VIEWSOURCE, viewsource, tools_submenu->developer);
+ ITEM_MBP(TOGGLEDEBUGGING, toggledebugging, tools_submenu->developer);
+ ITEM_MBP(SAVEBOXTREE, debugboxtree, tools_submenu->developer);
+ ITEM_MBP(SAVEDOMTREE, debugdomtree, tools_submenu->developer);
+
+ /* help menu */
+ ITEM_MB(CONTENTS, contents, help);
+ ITEM_MB(GUIDE, guide, help);
+ ITEM_MB(INFO, info, help);
+ ITEM_MB(ABOUT, about, help);
+
+
+#undef ITEM_MB
+#undef ITEM_MBp
+#undef ITEM_MBP
+ return NSERROR_OK;
}
-static void nsgtk_scaffolding_initial_sensitivity(struct nsgtk_scaffolding *g)
+
+static void nsgtk_menu_set_sensitivity(struct nsgtk_scaffolding *g)
{
+
for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- if (g->buttons[i]->main != NULL)
- gtk_widget_set_sensitive(GTK_WIDGET(
- g->buttons[i]->main),
- g->buttons[i]->sensitivity);
- if (g->buttons[i]->rclick != NULL)
+ if (g->menus[i].main != NULL) {
gtk_widget_set_sensitive(GTK_WIDGET(
- g->buttons[i]->rclick),
- g->buttons[i]->sensitivity);
- if ((g->buttons[i]->location != -1) &&
- (g->buttons[i]->button != NULL))
+ g->menus[i].main),
+ g->menus[i].sensitivity);
+ }
+ if (g->menus[i].burger != NULL) {
gtk_widget_set_sensitive(GTK_WIDGET(
- g->buttons[i]->button),
- g->buttons[i]->sensitivity);
- if (g->buttons[i]->popup != NULL)
+ g->menus[i].burger),
+ g->menus[i].sensitivity);
+ }
+ if (g->menus[i].popup != NULL) {
gtk_widget_set_sensitive(GTK_WIDGET(
- g->buttons[i]->popup),
- g->buttons[i]->sensitivity);
+ g->menus[i].popup),
+ g->menus[i].sensitivity);
+ }
}
- gtk_widget_set_sensitive(GTK_WIDGET(g->menu_bar->view_submenu->images_menuitem), FALSE);
}
-void nsgtk_scaffolding_toolbars(struct nsgtk_scaffolding *g, int tbi)
-{
- switch (tbi) {
- /* case 0 is 'unset' [from fresh install / clearing options]
- * see above */
-
- case 1: /* Small icons */
- /* main toolbar */
- gtk_toolbar_set_style(GTK_TOOLBAR(g->tool_bar),
- GTK_TOOLBAR_ICONS);
- gtk_toolbar_set_icon_size(GTK_TOOLBAR(g->tool_bar),
- GTK_ICON_SIZE_SMALL_TOOLBAR);
- /* search toolbar */
- gtk_toolbar_set_style(GTK_TOOLBAR(g->search->bar),
- GTK_TOOLBAR_ICONS);
- gtk_toolbar_set_icon_size(GTK_TOOLBAR(g->search->bar),
- GTK_ICON_SIZE_SMALL_TOOLBAR);
- break;
-
- case 2: /* Large icons */
- gtk_toolbar_set_style(GTK_TOOLBAR(g->tool_bar),
- GTK_TOOLBAR_ICONS);
- gtk_toolbar_set_icon_size(GTK_TOOLBAR(g->tool_bar),
- GTK_ICON_SIZE_LARGE_TOOLBAR);
- /* search toolbar */
- gtk_toolbar_set_style(GTK_TOOLBAR(g->search->bar),
- GTK_TOOLBAR_ICONS);
- gtk_toolbar_set_icon_size(GTK_TOOLBAR(g->search->bar),
- GTK_ICON_SIZE_LARGE_TOOLBAR);
- break;
-
- case 3: /* Large icons with text */
- gtk_toolbar_set_style(GTK_TOOLBAR(g->tool_bar),
- GTK_TOOLBAR_BOTH);
- gtk_toolbar_set_icon_size(GTK_TOOLBAR(g->tool_bar),
- GTK_ICON_SIZE_LARGE_TOOLBAR);
- /* search toolbar */
- gtk_toolbar_set_style(GTK_TOOLBAR(g->search->bar),
- GTK_TOOLBAR_BOTH);
- gtk_toolbar_set_icon_size(GTK_TOOLBAR(g->search->bar),
- GTK_ICON_SIZE_LARGE_TOOLBAR);
- break;
-
- case 4: /* Text icons only */
- gtk_toolbar_set_style(GTK_TOOLBAR(g->tool_bar),
- GTK_TOOLBAR_TEXT);
- /* search toolbar */
- gtk_toolbar_set_style(GTK_TOOLBAR(g->search->bar),
- GTK_TOOLBAR_TEXT);
- default:
- break;
- }
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-struct nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel)
+/* set menu items to have icons */
+static void nsgtk_menu_set_icons(struct nsgtk_scaffolding *g)
{
- struct nsgtk_scaffolding *gs;
- int i;
- GtkAccelGroup *group;
-
- gs = calloc(1, sizeof(*gs));
- if (gs == NULL) {
- return NULL;
- }
-
- NSLOG(netsurf, INFO,
- "Constructing a scaffold of %p for gui_window %p", gs, toplevel);
-
- gs->top_level = toplevel;
-
- /* Construct UI widgets */
- if (nsgtk_builder_new_from_resname("netsurf", &gs->builder) != NSERROR_OK) {
- free(gs);
- return NULL;
- }
-
- gtk_builder_connect_signals(gs->builder, NULL);
-
-/** Obtain a GTK widget handle from UI builder object */
-#define GET_WIDGET(x) GTK_WIDGET (gtk_builder_get_object(gs->builder, (x)))
-
- gs->window = GTK_WINDOW(GET_WIDGET("wndBrowser"));
- gs->notebook = GTK_NOTEBOOK(GET_WIDGET("notebook"));
- gs->tool_bar = GTK_TOOLBAR(GET_WIDGET("toolbar"));
-
- gs->search = malloc(sizeof(struct gtk_search));
- if (gs->search == NULL) {
- free(gs);
- return NULL;
- }
-
- gs->search->bar = GTK_TOOLBAR(GET_WIDGET("searchbar"));
- gs->search->entry = GTK_ENTRY(GET_WIDGET("searchEntry"));
-
- gs->search->buttons[0] = GTK_TOOL_BUTTON(GET_WIDGET("searchBackButton"));
- gs->search->buttons[1] = GTK_TOOL_BUTTON(GET_WIDGET("searchForwardButton"));
- gs->search->buttons[2] = GTK_TOOL_BUTTON(GET_WIDGET("closeSearchButton"));
- gs->search->checkAll = GTK_CHECK_BUTTON(GET_WIDGET("checkAllSearch"));
- gs->search->caseSens = GTK_CHECK_BUTTON(GET_WIDGET("caseSensButton"));
-
-#undef GET_WIDGET
-
- /* allocate buttons */
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- gs->buttons[i] = calloc(1, sizeof(struct nsgtk_button_connect));
- if (gs->buttons[i] == NULL) {
- for (i-- ; i >= BACK_BUTTON; i--) {
- free(gs->buttons[i]);
- }
- free(gs);
- return NULL;
+ GtkWidget *img;
+ for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
+ /* ensure there is an icon name */
+ if (g->menus[i].iconname == NULL) {
+ continue;
}
- gs->buttons[i]->location = -1;
- gs->buttons[i]->sensitivity = true;
- }
-
- /* here custom toolbutton adding code */
- gs->offset = 0;
- gs->toolbarmem = 0;
- gs->toolbarbase = 0;
- gs->historybase = 0;
- nsgtk_toolbar_customization_load(gs);
- nsgtk_toolbar_set_physical(gs);
-
- group = gtk_accel_group_new();
- gtk_window_add_accel_group(gs->window, group);
-
- gs->menu_bar = nsgtk_menu_bar_create(GTK_MENU_SHELL(gtk_builder_get_object(gs->builder, "menubar")), group);
-
-
- /* set this window's size and position to what's in the options, or
- * or some sensible default if they're not set yet.
- */
- if (nsoption_int(window_width) > 0) {
- gtk_window_move(gs->window,
- nsoption_int(window_x),
- nsoption_int(window_y));
- gtk_window_resize(gs->window,
- nsoption_int(window_width),
- nsoption_int(window_height));
- } else {
- /* Set to 1000x700, so we're very likely to fit even on
- * 1024x768 displays, not being able to take into account
- * window furniture or panels.
- */
- gtk_window_set_default_size(gs->window, 1000, 700);
- }
-
- /* Default toolbar button type uses system defaults */
- if (nsoption_int(button_type) == 0) {
- GtkSettings *settings = gtk_settings_get_default();
- GtkIconSize tooliconsize;
- GtkToolbarStyle toolbarstyle;
-
- g_object_get(settings,
- "gtk-toolbar-icon-size", &tooliconsize,
- "gtk-toolbar-style", &toolbarstyle, NULL);
-
- switch (toolbarstyle) {
- case GTK_TOOLBAR_ICONS:
- if (tooliconsize == GTK_ICON_SIZE_SMALL_TOOLBAR) {
- nsoption_set_int(button_type, 1);
- } else {
- nsoption_set_int(button_type, 2);
- }
- break;
- case GTK_TOOLBAR_TEXT:
- nsoption_set_int(button_type, 4);
- break;
-
- case GTK_TOOLBAR_BOTH:
- case GTK_TOOLBAR_BOTH_HORIZ:
- /* no labels in default configuration */
- default:
- /* No system default, so use large icons */
- nsoption_set_int(button_type, 2);
- break;
+ if (g->menus[i].main != NULL) {
+ img = gtk_image_new_from_icon_name(g->menus[i].iconname,
+ GTK_ICON_SIZE_MENU);
+ nsgtk_image_menu_item_set_image(GTK_WIDGET(g->menus[i].main), img);
+ }
+ if (g->menus[i].burger != NULL) {
+ img = gtk_image_new_from_icon_name(g->menus[i].iconname,
+ GTK_ICON_SIZE_MENU);
+ nsgtk_image_menu_item_set_image(GTK_WIDGET(g->menus[i].burger), img);
+ }
+ if (g->menus[i].popup != NULL) {
+ img = gtk_image_new_from_icon_name(g->menus[i].iconname,
+ GTK_ICON_SIZE_MENU);
+ nsgtk_image_menu_item_set_image(GTK_WIDGET(g->menus[i].popup), img);
}
}
+}
- nsgtk_scaffolding_toolbars(gs, nsoption_int(button_type));
-
- gtk_toolbar_set_show_arrow(gs->tool_bar, TRUE);
- gtk_widget_show_all(GTK_WIDGET(gs->tool_bar));
- nsgtk_tab_init(gs);
-
- gtk_widget_set_size_request(GTK_WIDGET(
- gs->buttons[HISTORY_BUTTON]->button), 20, -1);
-
-
- /* set up URL bar completion */
- gs->url_bar_completion = nsgtk_url_entry_completion_new(gs);
-
- /* set up the throbber. */
- gs->throb_frame = 0;
-
-
-#define CONNECT(obj, sig, callback, ptr) \
- g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr))
-
- g_signal_connect_after(gs->notebook, "page-added",
- G_CALLBACK(nsgtk_window_tabs_add), gs);
- g_signal_connect_after(gs->notebook, "page-removed",
- G_CALLBACK(nsgtk_window_tabs_remove), gs);
-
- /* connect main window signals to their handlers. */
- CONNECT(gs->window, "delete-event",
- scaffolding_window_delete_event, gs);
-
- CONNECT(gs->window, "destroy", scaffolding_window_destroy, gs);
-
- /* toolbar URL bar menu bar search bar signal handlers */
- CONNECT(gs->menu_bar->edit_submenu->edit, "show",
- nsgtk_window_edit_menu_shown, gs);
- CONNECT(gs->menu_bar->edit_submenu->edit, "hide",
- nsgtk_window_edit_menu_hidden, gs);
-
- CONNECT(gs->search->buttons[1], "clicked",
- nsgtk_search_forward_button_clicked, gs);
-
- CONNECT(gs->search->buttons[0], "clicked",
- nsgtk_search_back_button_clicked, gs);
-
- CONNECT(gs->search->entry, "changed", nsgtk_search_entry_changed, gs);
-
- CONNECT(gs->search->entry, "activate", nsgtk_search_entry_activate, gs);
-
- CONNECT(gs->search->entry, "key-press-event",
- nsgtk_search_entry_key, gs);
- CONNECT(gs->search->buttons[2], "clicked",
- nsgtk_search_close_button_clicked, gs);
+/**
+ * create and initialise menus
+ *
+ * There are four menus held by the scaffolding:
+ *
+ * 1. Main menubar menu.
+ * This can be hidden which causes the right click popup context menu
+ * to use the burger menu.
+ * 2. Burger menu.
+ * This can be opened from a burger icon on the toolbar.
+ * 3. popup context menu.
+ * This is opened by right mouse clicking on the toolbar or browser area
+ * 4. link context menu
+ * Opened like the other popup menu when the mouse is over a link in the
+ * browser area
+ *
+ * The cut, copy, paste, delete and back, forwards, stop, reload groups of
+ * menu entries are context sensitive and must be updated as appropriate
+ * when a menu is opened which contains those groups.
+ */
+static nserror nsgtk_menus_create(struct nsgtk_scaffolding *gs)
+{
+ GtkAccelGroup *group;
+ bool showmenu; /* show menubar */
+ bool showtool; /* show toolbar */
- CONNECT(gs->search->caseSens, "toggled",
- nsgtk_search_entry_changed, gs);
+ get_bar_show(&showmenu, &showtool);
- CONNECT(gs->tool_bar, "popup-context-menu",
- nsgtk_window_tool_bar_clicked, gs);
+ group = gtk_accel_group_new();
- /* create popup menu */
- gs->menu_popup = nsgtk_new_scaffolding_popup(gs, group);
+ gtk_window_add_accel_group(gs->window, group);
- gs->link_menu = nsgtk_new_scaffolding_link_popup(gs, group);
+ gs->menu_bar = create_scaffolding_bar_menu(gs, group, showmenu, showtool);
+ gs->burger_menu = create_scaffolding_burger_menu(gs, group, showmenu, showtool);
+ gs->popup_menu = create_scaffolding_popup_menu(gs, group, showmenu, showtool);
+ gs->link_menu = create_scaffolding_link_menu(gs, group);
/* set up the menu signal handlers */
- nsgtk_scaffolding_toolbar_init(gs);
- nsgtk_toolbar_connect_all(gs);
- nsgtk_attach_menu_handlers(gs);
-
- nsgtk_scaffolding_initial_sensitivity(gs);
+ nsgtk_menu_initialise(gs);
+ nsgtk_menu_set_icons(gs);
+ nsgtk_menu_connect_signals(gs);
+ nsgtk_menu_set_sensitivity(gs);
- gs->fullscreen = false;
-
- /* attach to the list */
- if (scaf_list) {
- scaf_list->prev = gs;
- }
- gs->next = scaf_list;
- gs->prev = NULL;
- scaf_list = gs;
-
- /* set icon images */
- nsgtk_theme_implement(gs);
-
- /* set web search provider */
- search_web_select_provider(nsoption_int(search_provider));
-
- /* finally, show the window. */
- gtk_widget_show(GTK_WIDGET(gs->window));
-
- NSLOG(netsurf, INFO, "creation complete");
-
- return gs;
+ return NSERROR_OK;
}
+
/* exported function documented in gtk/scaffolding.h */
-void nsgtk_window_set_title(struct gui_window *gw, const char *title)
+void nsgtk_scaffolding_set_title(struct gui_window *gw, const char *title)
{
struct nsgtk_scaffolding *gs = nsgtk_get_scaffold(gw);
int title_len;
char *newtitle;
- if ((title == NULL) || (title[0] == '\0')) {
- if (gs->top_level != gw) {
- gtk_window_set_title(gs->window, "NetSurf");
- }
+ /* only set window title if top level window */
+ if (gs->top_level != gw) {
return;
}
- nsgtk_tab_set_title(gw, title);
-
- if (gs->top_level != gw) {
- /* not top level window so do not set window title */
+ if (title == NULL || title[0] == '\0') {
+ gtk_window_set_title(gs->window, "NetSurf");
return;
}
@@ -2321,213 +1263,48 @@ void nsgtk_window_set_title(struct gui_window *gw, const char *title)
gtk_window_set_title(gs->window, newtitle);
free(newtitle);
-}
-
-nserror gui_window_set_url(struct gui_window *gw, nsurl *url)
-{
- struct nsgtk_scaffolding *g;
- size_t idn_url_l;
- char *idn_url_s = NULL;
-
- g = nsgtk_get_scaffold(gw);
- if (g->top_level == gw) {
- if (nsoption_bool(display_decoded_idn) == true) {
- if (nsurl_get_utf8(url, &idn_url_s, &idn_url_l) != NSERROR_OK)
- idn_url_s = NULL;
- }
-
- gtk_entry_set_text(GTK_ENTRY(g->url_bar), idn_url_s ? idn_url_s : nsurl_access(url));
-
- if(idn_url_s)
- free(idn_url_s);
-
- gtk_editable_set_position(GTK_EDITABLE(g->url_bar), -1);
- }
- return NSERROR_OK;
-}
-
-void gui_window_start_throbber(struct gui_window* _g)
-{
- struct nsgtk_scaffolding *g = nsgtk_get_scaffold(_g);
- g->buttons[STOP_BUTTON]->sensitivity = true;
- g->buttons[RELOAD_BUTTON]->sensitivity = false;
- nsgtk_scaffolding_set_sensitivity(g);
-
- scaffolding_update_context(g);
-
- nsgtk_schedule(100, nsgtk_throb, g);
-}
-
-void gui_window_stop_throbber(struct gui_window* _g)
-{
- struct nsgtk_scaffolding *g = nsgtk_get_scaffold(_g);
- if (g == NULL)
- return;
- scaffolding_update_context(g);
- nsgtk_schedule(-1, nsgtk_throb, g);
- if (g->buttons[STOP_BUTTON] != NULL)
- g->buttons[STOP_BUTTON]->sensitivity = false;
- if (g->buttons[RELOAD_BUTTON] != NULL)
- g->buttons[RELOAD_BUTTON]->sensitivity = true;
-
- nsgtk_scaffolding_set_sensitivity(g);
-
- if ((g->throbber == NULL) || (nsgtk_throbber == NULL) ||
- (nsgtk_throbber->framedata == NULL) ||
- (nsgtk_throbber->framedata[0] == NULL))
- return;
- gtk_image_set_from_pixbuf(g->throbber, nsgtk_throbber->framedata[0]);
}
-/**
- * set favicon
- */
-void
-nsgtk_scaffolding_set_icon(struct gui_window *gw)
+/* exported interface documented in scaffolding.h */
+nserror nsgtk_scaffolding_throbber(struct gui_window* gw, bool active)
{
- struct nsgtk_scaffolding *sc = nsgtk_get_scaffold(gw);
- GdkPixbuf *icon_pixbuf = nsgtk_get_icon(gw);
-
- /* check icon needs to be shown */
- if ((icon_pixbuf == NULL) ||
- (sc->top_level != gw)) {
- return;
+ struct nsgtk_scaffolding *gs = nsgtk_get_scaffold(gw);
+ if (active) {
+ gs->menus[STOP_BUTTON].sensitivity = true;
+ gs->menus[RELOAD_BUTTON].sensitivity = false;
+ } else {
+ gs->menus[STOP_BUTTON].sensitivity = false;
+ gs->menus[RELOAD_BUTTON].sensitivity = true;
}
+ scaffolding_update_context(gs);
- nsgtk_entry_set_icon_from_pixbuf(sc->url_bar,
- GTK_ENTRY_ICON_PRIMARY,
- icon_pixbuf);
-
- gtk_widget_show_all(GTK_WIDGET(sc->buttons[URL_BAR_ITEM]->button));
+ return NSERROR_OK;
}
-static void
-nsgtk_scaffolding_set_websearch(struct nsgtk_scaffolding *g, const char *content)
-{
- /** \todo this code appears technically correct, though
- * currently has no effect at all.
- */
- PangoLayout *lo = gtk_entry_get_layout(GTK_ENTRY(g->webSearchEntry));
- if (lo != NULL) {
- pango_layout_set_font_description(lo, NULL);
- PangoFontDescription *desc = pango_font_description_new();
- if (desc != NULL) {
- pango_font_description_set_style(desc,
- PANGO_STYLE_ITALIC);
- pango_font_description_set_family(desc, "Arial");
- pango_font_description_set_weight(desc,
- PANGO_WEIGHT_ULTRALIGHT);
- pango_font_description_set_size(desc,
- 10 * PANGO_SCALE);
- pango_layout_set_font_description(lo, desc);
- }
-
- PangoAttrList *list = pango_attr_list_new();
- if (list != NULL) {
- PangoAttribute *italic = pango_attr_style_new(
- PANGO_STYLE_ITALIC);
- if (italic != NULL) {
- italic->start_index = 0;
- italic->end_index = strlen(content);
- }
- PangoAttribute *grey = pango_attr_foreground_new(
- 0x7777, 0x7777, 0x7777);
- if (grey != NULL) {
- grey->start_index = 0;
- grey->end_index = strlen(content);
- }
- pango_attr_list_insert(list, italic);
- pango_attr_list_insert(list, grey);
- pango_layout_set_attributes(lo, list);
- pango_attr_list_unref(list);
- }
- pango_layout_set_text(lo, content, -1);
- }
-/* an alternative method */
-/* char *parse = malloc(strlen(content) + 1);
- PangoAttrList *list = pango_layout_get_attributes(lo);
- char *markup = g_strconcat("<span foreground='#777777'><i>", content,
- "</i></span>", NULL);
- pango_parse_markup(markup, -1, 0, &list, &parse, NULL, NULL);
- gtk_widget_show_all(g->webSearchEntry);
-*/
- gtk_entry_set_visibility(GTK_ENTRY(g->webSearchEntry), TRUE);
- gtk_entry_set_text(GTK_ENTRY(g->webSearchEntry), content);
-}
-/**
- * GTK UI callback when search provider details are updated.
- *
- * \param provider_name The providers name.
- * \param provider_bitmap The bitmap representing the provider.
- * \return NSERROR_OK on success else error code.
- */
-static nserror
-gui_search_web_provider_update(const char *provider_name,
- struct bitmap *provider_bitmap)
+/* exported interface documented in gtk/scaffolding.h */
+nserror nsgtk_scaffolding_destroy_all(void)
{
- struct nsgtk_scaffolding *current;
- GdkPixbuf *srch_pixbuf = NULL;
- char *searchcontent;
-
- NSLOG(netsurf, INFO, "name:%s bitmap %p", provider_name,
- provider_bitmap);
-
- if (provider_bitmap != NULL) {
- srch_pixbuf = nsgdk_pixbuf_get_from_surface(provider_bitmap->surface, 16, 16);
-
- if (srch_pixbuf == NULL) {
- return NSERROR_NOMEM;
- }
- }
-
- /* setup the search content name */
- searchcontent = malloc(strlen(provider_name) + SLEN("Search ") + 1);
- if (searchcontent != NULL) {
- sprintf(searchcontent, "Search %s", provider_name);
- }
-
- /* set the search provider parameters up in each scaffold */
- for (current = scaf_list; current != NULL; current = current->next) {
- if (current->webSearchEntry == NULL) {
- continue;
- }
+ struct nsgtk_scaffolding *gs;
- /* add ico to each window's toolbar */
- if (srch_pixbuf != NULL) {
- nsgtk_entry_set_icon_from_pixbuf(current->webSearchEntry,
- GTK_ENTRY_ICON_PRIMARY,
- srch_pixbuf);
- } else {
- nsgtk_entry_set_icon_from_stock(current->webSearchEntry,
- GTK_ENTRY_ICON_PRIMARY,
- NSGTK_STOCK_FIND);
- }
+ gs = scaf_list;
+ assert(gs != NULL);
- /* set search entry text */
- if (searchcontent != NULL) {
- nsgtk_scaffolding_set_websearch(current, searchcontent);
- } else {
- nsgtk_scaffolding_set_websearch(current, provider_name);
- }
+ if (nsgtk_check_for_downloads(gs->window) == true) {
+ return NSERROR_INVALID;
}
- free(searchcontent);
-
- if (srch_pixbuf != NULL) {
- g_object_unref(srch_pixbuf);
+ /* iterate all scaffolding windows and destroy them */
+ while (gs != NULL) {
+ struct nsgtk_scaffolding *next = gs->next;
+ gtk_widget_destroy(GTK_WIDGET(gs->window));
+ gs = next;
}
-
return NSERROR_OK;
}
-static struct gui_search_web_table search_web_table = {
- .provider_update = gui_search_web_provider_update,
-};
-
-struct gui_search_web_table *nsgtk_search_web_table = &search_web_table;
/* exported interface documented in gtk/scaffolding.h */
GtkWindow* nsgtk_scaffolding_window(struct nsgtk_scaffolding *g)
@@ -2541,41 +1318,14 @@ GtkNotebook* nsgtk_scaffolding_notebook(struct nsgtk_scaffolding *g)
return g->notebook;
}
-/* exported interface documented in gtk/scaffolding.h */
-GtkWidget *nsgtk_scaffolding_urlbar(struct nsgtk_scaffolding *g)
-{
- return g->url_bar;
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-GtkWidget *nsgtk_scaffolding_websearch(struct nsgtk_scaffolding *g)
-{
- return g->webSearchEntry;
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-GtkToolbar *nsgtk_scaffolding_toolbar(struct nsgtk_scaffolding *g)
-{
- return g->tool_bar;
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-struct nsgtk_button_connect *
-nsgtk_scaffolding_button(struct nsgtk_scaffolding *g, int i)
-{
- return g->buttons[i];
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-struct gtk_search *nsgtk_scaffolding_search(struct nsgtk_scaffolding *g)
-{
- return g->search;
-}
/* exported interface documented in gtk/scaffolding.h */
-GtkMenuBar *nsgtk_scaffolding_menu_bar(struct nsgtk_scaffolding *g)
+GtkMenuBar *nsgtk_scaffolding_menu_bar(struct nsgtk_scaffolding *gs)
{
- return g->menu_bar->bar_menu;
+ if (gs == NULL) {
+ return NULL;
+ }
+ return gs->menu_bar->bar_menu;
}
/* exported interface documented in gtk/scaffolding.h */
@@ -2587,54 +1337,6 @@ struct nsgtk_scaffolding *nsgtk_scaffolding_iterate(struct nsgtk_scaffolding *g)
return g->next;
}
-/* exported interface documented in gtk/scaffolding.h */
-void nsgtk_scaffolding_reset_offset(struct nsgtk_scaffolding *g)
-{
- g->offset = 0;
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-void nsgtk_scaffolding_update_url_bar_ref(struct nsgtk_scaffolding *g)
-{
- g->url_bar = GTK_WIDGET(gtk_bin_get_child(GTK_BIN(
- nsgtk_scaffolding_button(g, URL_BAR_ITEM)->button)));
-
- gtk_entry_set_completion(GTK_ENTRY(g->url_bar),
- g->url_bar_completion);
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-void nsgtk_scaffolding_update_throbber_ref(struct nsgtk_scaffolding *g)
-{
- g->throbber = GTK_IMAGE(gtk_bin_get_child(
- GTK_BIN(g->buttons[THROBBER_ITEM]->button)));
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-void nsgtk_scaffolding_update_websearch_ref(struct nsgtk_scaffolding *g)
-{
- g->webSearchEntry = gtk_bin_get_child(GTK_BIN(
- g->buttons[WEBSEARCH_ITEM]->button));
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-void nsgtk_scaffolding_toggle_search_bar_visibility(struct nsgtk_scaffolding *g)
-{
- gboolean vis;
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
-
- g_object_get(G_OBJECT(g->search->bar), "visible", &vis, NULL);
- if (vis) {
- if (bw != NULL) {
- browser_window_search_clear(bw);
- }
-
- gtk_widget_hide(GTK_WIDGET(g->search->bar));
- } else {
- gtk_widget_show(GTK_WIDGET(g->search->bar));
- gtk_widget_grab_focus(GTK_WIDGET(g->search->entry));
- }
-}
/* exported interface documented in gtk/scaffolding.h */
struct gui_window *nsgtk_scaffolding_top_level(struct nsgtk_scaffolding *g)
@@ -2642,6 +1344,7 @@ struct gui_window *nsgtk_scaffolding_top_level(struct nsgtk_scaffolding *g)
return g->top_level;
}
+
/* exported interface documented in gtk/scaffolding.h */
void nsgtk_scaffolding_set_top_level(struct gui_window *gw)
{
@@ -2657,44 +1360,33 @@ void nsgtk_scaffolding_set_top_level(struct gui_window *gw)
sc = nsgtk_get_scaffold(gw);
assert(sc != NULL);
+ scaf_current = sc;
+
sc->top_level = gw;
- /* Synchronise the history (will also update the URL bar) */
+ /* Synchronise the history */
scaffolding_update_context(sc);
- /* clear effects of potential searches */
- browser_window_search_clear(bw);
-
- nsgtk_scaffolding_set_icon(gw);
-
/* Ensure the window's title bar is updated */
- nsgtk_window_set_title(gw, browser_window_get_title(bw));
-
+ nsgtk_scaffolding_set_title(gw, browser_window_get_title(bw));
}
+
/* exported interface documented in scaffolding.h */
void nsgtk_scaffolding_set_sensitivity(struct nsgtk_scaffolding *g)
{
int i;
-#define SENSITIVITY(q)\
- i = q##_BUTTON;\
- if (g->buttons[i]->main != NULL)\
- gtk_widget_set_sensitive(GTK_WIDGET(\
- g->buttons[i]->main),\
- g->buttons[i]->sensitivity);\
- if (g->buttons[i]->rclick != NULL)\
- gtk_widget_set_sensitive(GTK_WIDGET(\
- g->buttons[i]->rclick),\
- g->buttons[i]->sensitivity);\
- if ((g->buttons[i]->location != -1) && \
- (g->buttons[i]->button != NULL))\
- gtk_widget_set_sensitive(GTK_WIDGET(\
- g->buttons[i]->button),\
- g->buttons[i]->sensitivity);\
- if (g->buttons[i]->popup != NULL)\
- gtk_widget_set_sensitive(GTK_WIDGET(\
- g->buttons[i]->popup),\
- g->buttons[i]->sensitivity);
+#define SENSITIVITY(q) \
+ i = q##_BUTTON; \
+ if (g->menus[i].main != NULL) \
+ gtk_widget_set_sensitive(GTK_WIDGET(g->menus[i].main), \
+ g->menus[i].sensitivity); \
+ if (g->menus[i].burger != NULL) \
+ gtk_widget_set_sensitive(GTK_WIDGET(g->menus[i].burger), \
+ g->menus[i].sensitivity); \
+ if (g->menus[i].popup != NULL) \
+ gtk_widget_set_sensitive(GTK_WIDGET(g->menus[i].popup), \
+ g->menus[i].sensitivity);
SENSITIVITY(STOP)
SENSITIVITY(RELOAD)
@@ -2707,86 +1399,205 @@ void nsgtk_scaffolding_set_sensitivity(struct nsgtk_scaffolding *g)
SENSITIVITY(PREVTAB)
SENSITIVITY(CLOSETAB)
#undef SENSITIVITY
+
}
/* exported interface documented in gtk/scaffolding.h */
-void nsgtk_scaffolding_context_menu(struct nsgtk_scaffolding *g,
- gdouble x,
- gdouble y)
+nserror nsgtk_scaffolding_toolbar_context_menu(struct nsgtk_scaffolding *gs)
+{
+ /* set visibility for right-click popup menu */
+ popup_menu_hide(gs->popup_menu, false, true);
+
+ nsgtk_menu_popup_at_pointer(gs->popup_menu->popup_menu, NULL);
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in gtk/scaffolding.h */
+nserror nsgtk_scaffolding_burger_menu(struct nsgtk_scaffolding *gs)
+{
+ nsgtk_menu_popup_at_pointer(gs->burger_menu->burger_menu, NULL);
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in gtk/scaffolding.h */
+void
+nsgtk_scaffolding_context_menu(struct nsgtk_scaffolding *g,
+ gdouble x,
+ gdouble y)
{
GtkMenu *gtkmenu;
+ struct browser_window *bw;
+
+ bw = nsgtk_get_browser_window(g->top_level);
/* update the global context menu features */
- browser_window_get_features(nsgtk_get_browser_window(g->top_level),
- x, y, &current_menu_features);
+ browser_window_get_features(bw, x, y, &current_menu_features);
if (current_menu_features.link != NULL) {
/* menu is opening over a link */
gtkmenu = g->link_menu->link_menu;
} else {
- gtkmenu = g->menu_popup->popup_menu;
+ gtkmenu = g->popup_menu->popup_menu;
nsgtk_scaffolding_update_edit_actions_sensitivity(g);
- if (!(g->buttons[COPY_BUTTON]->sensitivity)) {
- gtk_widget_hide(GTK_WIDGET(g->menu_popup->copy_menuitem));
+ if (!(g->menus[COPY_BUTTON].sensitivity)) {
+ gtk_widget_hide(GTK_WIDGET(g->popup_menu->copy_menuitem));
} else {
- gtk_widget_show(GTK_WIDGET(g->menu_popup->copy_menuitem));
+ gtk_widget_show(GTK_WIDGET(g->popup_menu->copy_menuitem));
}
- if (!(g->buttons[CUT_BUTTON]->sensitivity)) {
- gtk_widget_hide(GTK_WIDGET(g->menu_popup->cut_menuitem));
+ if (!(g->menus[CUT_BUTTON].sensitivity)) {
+ gtk_widget_hide(GTK_WIDGET(g->popup_menu->cut_menuitem));
} else {
- gtk_widget_show(GTK_WIDGET(g->menu_popup->cut_menuitem));
+ gtk_widget_show(GTK_WIDGET(g->popup_menu->cut_menuitem));
}
- if (!(g->buttons[PASTE_BUTTON]->sensitivity)) {
- gtk_widget_hide(GTK_WIDGET(g->menu_popup->paste_menuitem));
+ if (!(g->menus[PASTE_BUTTON].sensitivity)) {
+ gtk_widget_hide(GTK_WIDGET(g->popup_menu->paste_menuitem));
} else {
- gtk_widget_show(GTK_WIDGET(g->menu_popup->paste_menuitem));
+ gtk_widget_show(GTK_WIDGET(g->popup_menu->paste_menuitem));
}
- /* hide customise */
- popup_menu_hide(g->menu_popup, false, false, false, true);
}
- gtk_menu_popup(gtkmenu, NULL, NULL, NULL, NULL, 0,
- gtk_get_current_event_time());
+ nsgtk_menu_popup_at_pointer(gtkmenu, NULL);
}
-/**
- * reallocate width for history button, reallocate buttons right of history;
- * memorise base of history button / toolbar
- */
-void nsgtk_scaffolding_toolbar_size_allocate(GtkWidget *widget,
- GtkAllocation *alloc, gpointer data)
+/* exported interface documented in gtk/scaffolding.h */
+struct nsgtk_scaffolding *nsgtk_current_scaffolding(void)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- int i = nsgtk_toolbar_get_id_from_widget(widget, g);
- if (i == -1)
- return;
- if ((g->toolbarmem == alloc->x) ||
- (g->buttons[i]->location <
- g->buttons[HISTORY_BUTTON]->location))
- /* no reallocation after first adjustment, no reallocation for buttons
- * left of history button */
- return;
- if (widget == GTK_WIDGET(g->buttons[HISTORY_BUTTON]->button)) {
- if (alloc->width == 20)
- return;
-
- g->toolbarbase = alloc->y + alloc->height;
- g->historybase = alloc->x + 20;
- if (g->offset == 0)
- g->offset = alloc->width - 20;
- alloc->width = 20;
- } else if (g->buttons[i]->location <=
- g->buttons[URL_BAR_ITEM]->location) {
- alloc->x -= g->offset;
- if (i == URL_BAR_ITEM)
- alloc->width += g->offset;
+ if (scaf_current == NULL) {
+ scaf_current = scaf_list;
}
- g->toolbarmem = alloc->x;
- gtk_widget_size_allocate(widget, alloc);
+ return scaf_current;
+}
+
+/* exported interface documented in gtk/scaffolding.h */
+struct nsgtk_scaffolding *nsgtk_scaffolding_from_notebook(GtkNotebook *notebook)
+{
+ struct nsgtk_scaffolding *gs;
+ gs = scaf_list;
+ while (gs != NULL) {
+ if (gs->notebook == notebook) {
+ break;
+ }
+ gs = gs->next;
+ }
+ return gs;
+}
+
+/* exported interface documented in gtk/scaffolding.h */
+struct nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel)
+{
+ nserror res;
+ struct nsgtk_scaffolding *gs;
+
+ gs = calloc(1, sizeof(*gs));
+ if (gs == NULL) {
+ return NULL;
+ }
+
+ NSLOG(netsurf, INFO,
+ "Constructing a scaffold of %p for gui_window %p", gs, toplevel);
+
+ gs->top_level = toplevel;
+
+ /* Construct UI widgets */
+ if (nsgtk_builder_new_from_resname("netsurf", &gs->builder) != NSERROR_OK) {
+ free(gs);
+ return NULL;
+ }
+
+ gtk_builder_connect_signals(gs->builder, NULL);
+
+ /* containing window setup */
+ gs->window = GTK_WINDOW(gtk_builder_get_object(gs->builder,
+ "wndBrowser"));
+
+ /**
+ * set this window's size and position to what's in the options, or
+ * some sensible default if they are not set yet.
+ */
+ if (nsoption_int(window_width) > 0) {
+ gtk_window_move(gs->window,
+ nsoption_int(window_x),
+ nsoption_int(window_y));
+ gtk_window_resize(gs->window,
+ nsoption_int(window_width),
+ nsoption_int(window_height));
+ } else {
+ /* Set to 1000x700, so we're very likely to fit even on
+ * 1024x768 displays, not being able to take into account
+ * window furniture or panels.
+ */
+ gtk_window_set_default_size(gs->window, 1000, 700);
+ }
+
+ g_signal_connect(gs->window,
+ "delete-event",
+ G_CALLBACK(scaffolding_window_delete_event),
+ gs);
+
+ g_signal_connect(gs->window,
+ "destroy",
+ G_CALLBACK(scaffolding_window_destroy),
+ gs);
+
+
+ /* notebook */
+ res = nsgtk_notebook_create(gs->builder, &gs->notebook);
+ if (res != NSERROR_OK) {
+ free(gs);
+ return NULL;
+ }
+
+ g_signal_connect_after(gs->notebook,
+ "page-added",
+ G_CALLBACK(nsgtk_window_tabs_add),
+ gs);
+ gs->tabs_remove_handler_id = g_signal_connect_after(gs->notebook,
+ "page-removed",
+ G_CALLBACK(nsgtk_window_tabs_remove),
+ gs);
+
+
+ res = nsgtk_menus_create(gs);
+ if (res != NSERROR_OK) {
+ free(gs);
+ return NULL;
+ }
+
+ /* attach to the list */
+ if (scaf_list) {
+ scaf_list->prev = gs;
+ }
+ gs->next = scaf_list;
+ gs->prev = NULL;
+ scaf_list = gs;
+
+ /* finally, show the window. */
+ gtk_widget_show(GTK_WIDGET(gs->window));
+
+ NSLOG(netsurf, INFO, "creation complete");
+
+ return gs;
+}
+
+/* exported interface documented in gtk/scaffolding.h */
+nserror nsgtk_scaffolding_position_page_info(struct nsgtk_scaffolding *gs,
+ struct nsgtk_pi_window *win)
+{
+ return nsgtk_window_position_page_info(gs->top_level, win);
+}
+
+/* exported interface documented in gtk/scaffolding.h */
+nserror nsgtk_scaffolding_position_local_history(struct nsgtk_scaffolding *gs)
+{
+ return nsgtk_window_position_local_history(gs->top_level);
}
diff --git a/frontends/gtk/scaffolding.h b/frontends/gtk/scaffolding.h
index e1fd9bf2a..87d4f3bd6 100644
--- a/frontends/gtk/scaffolding.h
+++ b/frontends/gtk/scaffolding.h
@@ -27,91 +27,8 @@ struct hlcache_handle;
struct gui_window;
struct gui_search_web_table;
struct nsurl;
+struct nsgtk_pi_window;
-extern struct gui_search_web_table *nsgtk_search_web_table;
-
-typedef enum {
- BACK_BUTTON = 0,
- HISTORY_BUTTON,
- FORWARD_BUTTON,
- STOP_BUTTON,
- RELOAD_BUTTON,
- HOME_BUTTON,
- URL_BAR_ITEM,
- WEBSEARCH_ITEM,
- THROBBER_ITEM,
- NEWWINDOW_BUTTON,
- NEWTAB_BUTTON,
- OPENFILE_BUTTON,
- CLOSETAB_BUTTON,
- CLOSEWINDOW_BUTTON,
- SAVEPAGE_BUTTON,
- PDF_BUTTON,
- PLAINTEXT_BUTTON,
- DRAWFILE_BUTTON,
- POSTSCRIPT_BUTTON,
- PRINTPREVIEW_BUTTON,
- PRINT_BUTTON,
- QUIT_BUTTON,
- CUT_BUTTON,
- COPY_BUTTON,
- PASTE_BUTTON,
- DELETE_BUTTON,
- SELECTALL_BUTTON,
- FIND_BUTTON,
- PREFERENCES_BUTTON,
- ZOOMPLUS_BUTTON,
- ZOOMMINUS_BUTTON,
- ZOOMNORMAL_BUTTON,
- FULLSCREEN_BUTTON,
- VIEWSOURCE_BUTTON,
- DOWNLOADS_BUTTON,
- SAVEWINDOWSIZE_BUTTON,
- TOGGLEDEBUGGING_BUTTON,
- SAVEBOXTREE_BUTTON,
- SAVEDOMTREE_BUTTON,
- LOCALHISTORY_BUTTON,
- GLOBALHISTORY_BUTTON,
- ADDBOOKMARKS_BUTTON,
- SHOWBOOKMARKS_BUTTON,
- SHOWCOOKIES_BUTTON,
- OPENLOCATION_BUTTON,
- NEXTTAB_BUTTON,
- PREVTAB_BUTTON,
- CONTENTS_BUTTON,
- GUIDE_BUTTON,
- INFO_BUTTON,
- ABOUT_BUTTON,
- PLACEHOLDER_BUTTON /* size indicator; array maximum indices */
-} nsgtk_toolbar_button; /* PLACEHOLDER_BUTTON - 1 */
-
-struct gtk_history_window {
- struct nsgtk_scaffolding *g;
- GtkWindow *window;
- GtkScrolledWindow *scrolled;
- GtkDrawingArea *drawing_area;
-};
-
-struct gtk_search {
- GtkToolbar *bar;
- GtkEntry *entry;
- GtkToolButton *buttons[3]; /* back, forward, */
- GtkCheckButton *checkAll; /* close */
- GtkCheckButton *caseSens;
-};
-
-struct nsgtk_button_connect {
- GtkToolItem *button;
- int location; /* in toolbar */
- bool sensitivity;
- GtkWidget *main; /* left click menu entry */
- GtkWidget *rclick; /* right click menu */
- GtkWidget *popup; /* popup menu entry */
- void *mhandler; /* menu item clicked */
- void *bhandler; /* button clicked */
- void *dataplus; /* customization -> toolbar */
- void *dataminus; /* customization -> store */
-};
/**
* create a new scaffolding for a window.
@@ -122,69 +39,75 @@ struct nsgtk_button_connect {
struct nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *gw);
/**
- * Obtain the most recently used scaffolding element.
+ * causes all scaffolding windows to be destroyed.
*
- * This allows tabs to be opened in the most recently used window
+ * \return NSERROR_OK and all scaffolding windows destroyed else
+ * NSERROR_INVALID if download in progress and user continued.
*/
-struct nsgtk_scaffolding *nsgtk_current_scaffolding(void);
+nserror nsgtk_scaffolding_destroy_all(void);
-/* acessors for gtk elements within a scaffold */
+/**
+ * Update scaffolding window when throbber state changes
+ */
+nserror nsgtk_scaffolding_throbber(struct gui_window* gw, bool active);
/**
- * Get the gtk window for a scaffolding.
+ * open the toolbar context menu
*/
-GtkWindow *nsgtk_scaffolding_window(struct nsgtk_scaffolding *g);
+nserror nsgtk_scaffolding_toolbar_context_menu(struct nsgtk_scaffolding *gs);
/**
- * Get the gtk notebook from a scaffold.
+ * Position the page-info popup in the right place
+ *
+ * \param gs The scaffolding to position relative to
+ * \param win The page-info window to position
*/
-GtkNotebook *nsgtk_scaffolding_notebook(struct nsgtk_scaffolding *g);
+nserror nsgtk_scaffolding_position_page_info(struct nsgtk_scaffolding *gs,
+ struct nsgtk_pi_window *win);
/**
- * Get the gtk url bar from a scaffold.
+ * Position the local-history popup in the right place
+ *
+ * \param gs The scaffolding to position relative to
*/
-GtkWidget *nsgtk_scaffolding_urlbar(struct nsgtk_scaffolding *g);
+nserror nsgtk_scaffolding_position_local_history(struct nsgtk_scaffolding *gs);
/**
- * Get the gtk web search entry from a scaffold.
+ * open the burger menu
*/
-GtkWidget *nsgtk_scaffolding_websearch(struct nsgtk_scaffolding *g);
+nserror nsgtk_scaffolding_burger_menu(struct nsgtk_scaffolding *gs);
/**
- * Get the gtk toolbar from a scaffold.
+ * Obtain the most recently used scaffolding element.
+ *
+ * This allows tabs to be opened in the most recently used window
*/
-GtkToolbar *nsgtk_scaffolding_toolbar(struct nsgtk_scaffolding *g);
+struct nsgtk_scaffolding *nsgtk_current_scaffolding(void);
+/* acessors for gtk elements within a scaffold */
-struct nsgtk_button_connect *nsgtk_scaffolding_button(struct nsgtk_scaffolding *g, int i);
+/**
+ * Get the gtk window for a scaffolding.
+ */
+GtkWindow *nsgtk_scaffolding_window(struct nsgtk_scaffolding *g);
+
+/**
+ * Get the gtk notebook from a scaffold.
+ */
+GtkNotebook *nsgtk_scaffolding_notebook(struct nsgtk_scaffolding *g);
struct gtk_search *nsgtk_scaffolding_search(struct nsgtk_scaffolding *g);
GtkMenuBar *nsgtk_scaffolding_menu_bar(struct nsgtk_scaffolding *g);
-struct gtk_history_window *nsgtk_scaffolding_history_window(struct nsgtk_scaffolding *g);
-
struct gui_window *nsgtk_scaffolding_top_level(struct nsgtk_scaffolding *g);
-/**
- * reset the scaffold offset value to 0.
- *
- * \todo The value is only ever altered in
- * nsgtk_scaffolding_toolbar_size_allocate and is something to do with
- * the history button either clarify or remove!
- */
-void nsgtk_scaffolding_reset_offset(struct nsgtk_scaffolding *g);
/**
* Iterate through available scaffolding.
*/
struct nsgtk_scaffolding *nsgtk_scaffolding_iterate(struct nsgtk_scaffolding *g);
-void nsgtk_scaffolding_update_url_bar_ref(struct nsgtk_scaffolding *g);
-
-void nsgtk_scaffolding_update_throbber_ref(struct nsgtk_scaffolding *g);
-
-void nsgtk_scaffolding_update_websearch_ref(struct nsgtk_scaffolding *g);
void nsgtk_scaffolding_toggle_search_bar_visibility(struct nsgtk_scaffolding *g);
@@ -224,29 +147,20 @@ void nsgtk_scaffolding_set_sensitivity(struct nsgtk_scaffolding *g);
*/
void nsgtk_scaffolding_context_menu(struct nsgtk_scaffolding *g, gdouble x, gdouble y);
-void nsgtk_scaffolding_toolbar_size_allocate(GtkWidget *widget, GtkAllocation *alloc, gpointer data);
-
-void nsgtk_scaffolding_set_icon(struct gui_window *gw);
-
-gboolean nsgtk_window_url_activate_event(GtkWidget *, gpointer);
-
-gboolean nsgtk_window_url_changed(GtkWidget *, GdkEventKey *, gpointer);
-
-nserror nsgtk_scaffolding_new_tab(struct gui_window *gw);
-
-/* core acessors */
/**
* set the title in the window
*
* \param gw The gui window to set title on
* \param title The title to set which may be NULL
*/
-void nsgtk_window_set_title(struct gui_window *gw, const char *title);
-
-nserror gui_window_set_url(struct gui_window *g, struct nsurl *url);
-void gui_window_start_throbber(struct gui_window *g);
-void gui_window_stop_throbber(struct gui_window *g);
+void nsgtk_scaffolding_set_title(struct gui_window *gw, const char *title);
-void nsgtk_scaffolding_toolbars(struct nsgtk_scaffolding *g, int tbi);
+/**
+ * find which scaffolding contains a gtk notebook
+ *
+ * \param notebook The notebook to search for.
+ * \return The scaffolding containing the notebook or NULL if not found
+ */
+struct nsgtk_scaffolding *nsgtk_scaffolding_from_notebook(GtkNotebook *notebook);
#endif /* NETSURF_GTK_SCAFFOLDING_H */
diff --git a/frontends/gtk/schedule.c b/frontends/gtk/schedule.c
index d5b45674b..69678924d 100644
--- a/frontends/gtk/schedule.c
+++ b/frontends/gtk/schedule.c
@@ -28,9 +28,9 @@
/** Killable callback closure embodiment. */
typedef struct {
- void (*callback)(void *); /**< The callback function. */
- void *context; /**< The context for the callback. */
- bool callback_killed; /**< Whether or not this was killed. */
+ void (*callback)(void *); /**< The callback function. */
+ void *context; /**< The context for the callback. */
+ bool callback_killed; /**< Whether or not this was killed. */
} _nsgtk_callback_t;
/** List of callbacks which have occurred and are pending running. */
@@ -61,20 +61,29 @@ nsgtk_schedule_kill_callback(void *_target, void *_match)
if ((target->callback == match->callback) &&
(target->context == match->context)) {
NSLOG(schedule, DEBUG,
- "Found match for %p(%p), killing.",
+ "Found match for %p(%p), killing.",
target->callback, target->context);
target->callback = NULL;
target->context = NULL;
target->callback_killed = true;
+ match->callback_killed = true;
}
}
-static void
-schedule_remove(void (*callback)(void *p), void *p)
+/**
+ * remove a matching callback and context tuple from all lists
+ *
+ * \param callback The callback to match
+ * \param cbctx The callback context to match
+ * \return NSERROR_OK if the tuple was removed from at least one list else NSERROR_NOT_FOUND
+ */
+static nserror
+schedule_remove(void (*callback)(void *p), void *cbctx)
{
_nsgtk_callback_t cb_match = {
.callback = callback,
- .context = p,
+ .context = cbctx,
+ .callback_killed = false,
};
g_list_foreach(queued_callbacks,
@@ -83,29 +92,36 @@ schedule_remove(void (*callback)(void *p), void *p)
nsgtk_schedule_kill_callback, &cb_match);
g_list_foreach(this_run,
nsgtk_schedule_kill_callback, &cb_match);
+
+ if (cb_match.callback_killed == false) {
+ return NSERROR_NOT_FOUND;
+ }
+ return NSERROR_OK;
}
/* exported interface documented in gtk/schedule.h */
-nserror nsgtk_schedule(int t, void (*callback)(void *p), void *p)
+nserror nsgtk_schedule(int t, void (*callback)(void *p), void *cbctx)
{
- _nsgtk_callback_t *cb;
+ _nsgtk_callback_t *cb;
+ nserror res;
/* Kill any pending schedule of this kind. */
- schedule_remove(callback, p);
+ res = schedule_remove(callback, cbctx);
- if (t < 0) {
- return NSERROR_OK;
- }
+ /* only removal */
+ if (t < 0) {
+ return res;
+ }
- cb = malloc(sizeof(_nsgtk_callback_t));
+ cb = malloc(sizeof(_nsgtk_callback_t));
cb->callback = callback;
- cb->context = p;
+ cb->context = cbctx;
cb->callback_killed = false;
/* Prepend is faster right now. */
queued_callbacks = g_list_prepend(queued_callbacks, cb);
g_timeout_add(t, nsgtk_schedule_generic_callback, cb);
- return NSERROR_OK;
+ return NSERROR_OK;
}
bool
@@ -121,7 +137,7 @@ schedule_run(void)
pending_callbacks = NULL;
NSLOG(schedule, DEBUG,
- "Captured a run of %d callbacks to fire.",
+ "Captured a run of %d callbacks to fire.",
g_list_length(this_run));
/* Run all the callbacks which made it this far. */
@@ -132,5 +148,5 @@ schedule_run(void)
cb->callback(cb->context);
free(cb);
}
- return true;
+ return true;
}
diff --git a/frontends/gtk/search.c b/frontends/gtk/search.c
index 298309679..f9a509f6e 100644
--- a/frontends/gtk/search.c
+++ b/frontends/gtk/search.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ * Copyright 2019 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -17,228 +17,340 @@
*/
- /** \file
- * Free text search (front component)
+/**
+ * \file
+ * find in page gtk frontend implementation
+ *
+ * \todo this whole thing should be named find rather than search as
+ * that generally means web search and is confusing.
*/
-#include <stdint.h>
-#include <ctype.h>
-#include <string.h>
-#include <gdk/gdkkeysyms.h>
-
-#include "utils/config.h"
-#include "utils/log.h"
-#include "utils/messages.h"
-#include "utils/nsurl.h"
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <gtk/gtk.h>
+
+#include "utils/nsoption.h"
#include "netsurf/search.h"
-#include "netsurf/browser_window.h"
#include "desktop/search.h"
-#include "desktop/searchweb.h"
-#include "gtk/warn.h"
#include "gtk/compat.h"
-#include "gtk/search.h"
-#include "gtk/scaffolding.h"
+#include "gtk/toolbar_items.h"
#include "gtk/window.h"
+#include "gtk/search.h"
+
+
+struct gtk_search {
+ GtkToolbar *bar;
+ GtkEntry *entry;
+ GtkToolButton *back;
+ GtkToolButton *forward;
+ GtkToolButton *close;
+ GtkCheckButton *checkAll;
+ GtkCheckButton *caseSens;
+
+ struct browser_window *bw;
+};
/**
* activate search forwards button in gui.
*
* \param active activate/inactivate
- * \param gw The gui window in which to activite the search button in.
+ * \param search the gtk search context
*/
-static void nsgtk_search_set_forward_state(bool active, struct gui_window *gw)
+static void nsgtk_search_set_forward_state(bool active, struct gtk_search *search)
{
- if (gw != NULL && nsgtk_get_browser_window(gw) != NULL) {
- struct nsgtk_scaffolding *g = nsgtk_get_scaffold(gw);
- gtk_widget_set_sensitive(
- GTK_WIDGET(nsgtk_scaffolding_search(g)->buttons[1]),
- active);
- }
+ gtk_widget_set_sensitive(GTK_WIDGET(search->forward), active);
}
+
/**
* activate search back button in gui.
*
* \param active activate/inactivate
- * \param gw The gui window in which to activite the search button in.
+ * \param search the gtk search context
*/
-static void nsgtk_search_set_back_state(bool active, struct gui_window *gw)
+static void nsgtk_search_set_back_state(bool active, struct gtk_search *search)
{
- if (gw != NULL && nsgtk_get_browser_window(gw) != NULL) {
- struct nsgtk_scaffolding *g = nsgtk_get_scaffold(gw);
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_search(
- g)->buttons[0]), active);
- }
+ gtk_widget_set_sensitive(GTK_WIDGET(search->back), active);
}
-/** connected to the search forward button */
-gboolean nsgtk_search_forward_button_clicked(GtkWidget *widget, gpointer data)
+/**
+ * connected to the search forward button
+ */
+static gboolean
+nsgtk_search_forward_button_clicked(GtkWidget *widget, gpointer data)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- struct gui_window *gw = nsgtk_scaffolding_top_level(g);
- struct browser_window *bw = nsgtk_get_browser_window(gw);
-
- assert(bw);
-
- search_flags_t flags = SEARCH_FLAG_FORWARDS |
- (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
- nsgtk_scaffolding_search(g)->caseSens)) ?
- SEARCH_FLAG_CASE_SENSITIVE : 0) |
- (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
- nsgtk_scaffolding_search(g)->checkAll)) ?
- SEARCH_FLAG_SHOWALL : 0);
-
- browser_window_search(bw, gw, flags,
- gtk_entry_get_text(nsgtk_scaffolding_search(g)->entry));
+ struct gtk_search *search;
+ search_flags_t flags;
+
+ search = (struct gtk_search *)data;
+
+ flags = SEARCH_FLAG_FORWARDS;
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(search->caseSens))) {
+ flags |= SEARCH_FLAG_CASE_SENSITIVE;
+ }
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(search->checkAll))) {
+ flags |= SEARCH_FLAG_SHOWALL;
+ }
+
+ browser_window_search(search->bw, search, flags,
+ gtk_entry_get_text(search->entry));
+
return TRUE;
}
-/** connected to the search back button */
-
-gboolean nsgtk_search_back_button_clicked(GtkWidget *widget, gpointer data)
+/**
+ * connected to the search back button
+ */
+static gboolean
+nsgtk_search_back_button_clicked(GtkWidget *widget, gpointer data)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- struct gui_window *gw = nsgtk_scaffolding_top_level(g);
- struct browser_window *bw = nsgtk_get_browser_window(gw);
-
- assert(bw);
-
- search_flags_t flags = 0 |(gtk_toggle_button_get_active(
- GTK_TOGGLE_BUTTON(
- nsgtk_scaffolding_search(g)->caseSens)) ?
- SEARCH_FLAG_CASE_SENSITIVE : 0) |
- (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
- nsgtk_scaffolding_search(g)->checkAll)) ?
- SEARCH_FLAG_SHOWALL : 0);
-
- browser_window_search(bw, gw, flags,
- gtk_entry_get_text(nsgtk_scaffolding_search(g)->entry));
+ struct gtk_search *search;
+ search_flags_t flags;
+
+ search = (struct gtk_search *)data;
+
+ flags = 0;
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(search->caseSens))) {
+ flags |= SEARCH_FLAG_CASE_SENSITIVE;
+ }
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(search->checkAll))) {
+ flags |= SEARCH_FLAG_SHOWALL;
+ }
+
+ browser_window_search(search->bw, search, flags,
+ gtk_entry_get_text(search->entry));
+
return TRUE;
}
-/** connected to the search close button */
-
-gboolean nsgtk_search_close_button_clicked(GtkWidget *widget, gpointer data)
+/**
+ * connected to the search close button
+ */
+static gboolean
+nsgtk_search_close_button_clicked(GtkWidget *widget, gpointer data)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- nsgtk_scaffolding_toggle_search_bar_visibility(g);
- return TRUE;
+ struct gtk_search *search;
+
+ search = (struct gtk_search *)data;
+
+ nsgtk_search_toggle_visibility(search);
+
+ return TRUE;
}
-/** connected to the search entry [typing] */
-gboolean nsgtk_search_entry_changed(GtkWidget *widget, gpointer data)
+/**
+ * connected to the search entry [typing]
+ */
+static gboolean nsgtk_search_entry_changed(GtkWidget *widget, gpointer data)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- struct gui_window *gw = nsgtk_scaffolding_top_level(g);
- struct browser_window *bw = nsgtk_get_browser_window(gw);
+ struct gtk_search *search;
search_flags_t flags;
- assert(bw != NULL);
+ search = (struct gtk_search *)data;
+
+ flags = 0;
- nsgtk_search_set_forward_state(true, gw);
- nsgtk_search_set_back_state(true, gw);
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(search->caseSens))) {
+ flags |= SEARCH_FLAG_CASE_SENSITIVE;
+ }
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(search->checkAll))) {
+ flags |= SEARCH_FLAG_SHOWALL;
+ }
- flags = SEARCH_FLAG_FORWARDS |
- (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
- nsgtk_scaffolding_search(g)->caseSens)) ?
- SEARCH_FLAG_CASE_SENSITIVE : 0) |
- (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
- nsgtk_scaffolding_search(g)->checkAll)) ?
- SEARCH_FLAG_SHOWALL : 0);
+ browser_window_search(search->bw, search, flags,
+ gtk_entry_get_text(search->entry));
- browser_window_search(bw, gw, flags,
- gtk_entry_get_text(nsgtk_scaffolding_search(g)->entry));
return TRUE;
}
-/** connected to the search entry [return key] */
-
-gboolean nsgtk_search_entry_activate(GtkWidget *widget, gpointer data)
+/**
+ * connected to the search entry [return key]
+ */
+static gboolean nsgtk_search_entry_activate(GtkWidget *widget, gpointer data)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- struct gui_window *gw = nsgtk_scaffolding_top_level(g);
- struct browser_window *bw = nsgtk_get_browser_window(gw);
+ struct gtk_search *search;
search_flags_t flags;
- assert(bw);
+ search = (struct gtk_search *)data;
- flags = SEARCH_FLAG_FORWARDS |
- (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
- nsgtk_scaffolding_search(g)->caseSens)) ?
- SEARCH_FLAG_CASE_SENSITIVE : 0) |
- (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
- nsgtk_scaffolding_search(g)->checkAll)) ?
- SEARCH_FLAG_SHOWALL : 0);
+ flags = SEARCH_FLAG_FORWARDS;
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(search->caseSens))) {
+ flags |= SEARCH_FLAG_CASE_SENSITIVE;
+ }
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(search->checkAll))) {
+ flags |= SEARCH_FLAG_SHOWALL;
+ }
+
+ browser_window_search(search->bw, search, flags,
+ gtk_entry_get_text(search->entry));
- browser_window_search(bw, gw, flags,
- gtk_entry_get_text(nsgtk_scaffolding_search(g)->entry));
return FALSE;
}
-/** allows escape key to close search bar too */
-
-gboolean
+/**
+ * allows escape key to close search bar too
+ */
+static gboolean
nsgtk_search_entry_key(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
if (event->keyval == GDK_KEY(Escape)) {
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- nsgtk_scaffolding_toggle_search_bar_visibility(g);
+ struct gtk_search *search;
+ search = (struct gtk_search *)data;
+
+ nsgtk_search_toggle_visibility(search);
}
return FALSE;
}
-/** connected to the websearch entry [return key] */
-gboolean nsgtk_websearch_activate(GtkWidget *widget, gpointer data)
+static struct gui_search_table search_table = {
+ .forward_state = (void *)nsgtk_search_set_forward_state,
+ .back_state = (void *)nsgtk_search_set_back_state,
+};
+
+struct gui_search_table *nsgtk_search_table = &search_table;
+
+
+/* exported interface documented in gtk/scaffolding.h */
+nserror nsgtk_search_toggle_visibility(struct gtk_search *search)
{
- struct nsgtk_scaffolding *g = data;
- nserror ret;
- nsurl *url;
-
- ret = search_web_omni(
- gtk_entry_get_text(GTK_ENTRY(nsgtk_scaffolding_websearch(g))),
- SEARCH_WEB_OMNI_SEARCHONLY,
- &url);
- if (ret == NSERROR_OK) {
- temp_open_background = 0;
- ret = browser_window_create(
- BW_CREATE_HISTORY | BW_CREATE_TAB,
- url,
- NULL,
- nsgtk_get_browser_window(nsgtk_scaffolding_top_level(g)),
- NULL);
- temp_open_background = -1;
- nsurl_unref(url);
- }
- if (ret != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(ret), 0);
+ gboolean vis;
+
+ browser_window_search_clear(search->bw);
+
+ g_object_get(G_OBJECT(search->bar), "visible", &vis, NULL);
+ if (vis) {
+ gtk_widget_hide(GTK_WIDGET(search->bar));
+ } else {
+ gtk_widget_show(GTK_WIDGET(search->bar));
+ gtk_widget_grab_focus(GTK_WIDGET(search->entry));
+ nsgtk_search_entry_changed(GTK_WIDGET(search->entry), search);
}
- return TRUE;
+ return NSERROR_OK;
}
-/**
- * allows a click in the websearch entry field to clear the name of the
- * provider
- */
-gboolean nsgtk_websearch_clear(GtkWidget *widget, GdkEventFocus *f,
- gpointer data)
+/* exported interface documented in gtk/search.h */
+nserror nsgtk_search_restyle(struct gtk_search *search)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- gtk_editable_select_region(GTK_EDITABLE(
- nsgtk_scaffolding_websearch(g)), 0, -1);
- gtk_widget_grab_focus(GTK_WIDGET(nsgtk_scaffolding_websearch(g)));
- return TRUE;
+ switch (nsoption_int(button_type)) {
+
+ case 1: /* Small icons */
+ gtk_toolbar_set_style(GTK_TOOLBAR(search->bar),
+ GTK_TOOLBAR_ICONS);
+ gtk_toolbar_set_icon_size(GTK_TOOLBAR(search->bar),
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
+ break;
+
+ case 2: /* Large icons */
+ gtk_toolbar_set_style(GTK_TOOLBAR(search->bar),
+ GTK_TOOLBAR_ICONS);
+ gtk_toolbar_set_icon_size(GTK_TOOLBAR(search->bar),
+ GTK_ICON_SIZE_LARGE_TOOLBAR);
+ break;
+
+ case 3: /* Large icons with text */
+ gtk_toolbar_set_style(GTK_TOOLBAR(search->bar),
+ GTK_TOOLBAR_BOTH);
+ gtk_toolbar_set_icon_size(GTK_TOOLBAR(search->bar),
+ GTK_ICON_SIZE_LARGE_TOOLBAR);
+ break;
+
+ case 4: /* Text icons only */
+ gtk_toolbar_set_style(GTK_TOOLBAR(search->bar),
+ GTK_TOOLBAR_TEXT);
+ break;
+
+ default:
+ break;
+ }
+ return NSERROR_OK;
}
+/* exported interface documented in gtk/search.h */
+nserror
+nsgtk_search_create(GtkBuilder *builder,
+ struct browser_window *bw,
+ struct gtk_search **search_out)
+{
+ struct gtk_search *search;
-static struct gui_search_table search_table = {
- .forward_state = (void *)nsgtk_search_set_forward_state,
- .back_state = (void *)nsgtk_search_set_back_state,
-};
+ search = malloc(sizeof(struct gtk_search));
+ if (search == NULL) {
+ return NSERROR_NOMEM;
+ }
-struct gui_search_table *nsgtk_search_table = &search_table;
+ search->bw = bw;
+
+ search->bar = GTK_TOOLBAR(gtk_builder_get_object(builder, "findbar"));
+ search->entry = GTK_ENTRY(gtk_builder_get_object(builder, "Find"));
+ search->back = GTK_TOOL_BUTTON(gtk_builder_get_object(builder,
+ "FindBack"));
+ search->forward = GTK_TOOL_BUTTON(gtk_builder_get_object(builder,
+ "FindForward"));
+ search->close = GTK_TOOL_BUTTON(gtk_builder_get_object(builder,
+ "FindClose"));
+ search->checkAll = GTK_CHECK_BUTTON(gtk_builder_get_object(builder,
+ "FindHighlightAll"));
+ search->caseSens = GTK_CHECK_BUTTON(gtk_builder_get_object(builder,
+ "FindMatchCase"));
+
+ g_signal_connect(search->forward,
+ "clicked",
+ G_CALLBACK(nsgtk_search_forward_button_clicked),
+ search);
+
+ g_signal_connect(search->back,
+ "clicked",
+ G_CALLBACK(nsgtk_search_back_button_clicked),
+ search);
+
+ g_signal_connect(search->entry,
+ "changed",
+ G_CALLBACK(nsgtk_search_entry_changed),
+ search);
+
+ g_signal_connect(search->entry,
+ "activate",
+ G_CALLBACK(nsgtk_search_entry_activate),
+ search);
+
+ g_signal_connect(search->entry,
+ "key-press-event",
+ G_CALLBACK(nsgtk_search_entry_key),
+ search);
+
+ g_signal_connect(search->close,
+ "clicked",
+ G_CALLBACK(nsgtk_search_close_button_clicked),
+ search);
+
+ g_signal_connect(search->caseSens,
+ "toggled",
+ G_CALLBACK(nsgtk_search_entry_changed),
+ search);
+
+ g_signal_connect(search->checkAll,
+ "toggled",
+ G_CALLBACK(nsgtk_search_entry_changed),
+ search);
+
+ nsgtk_search_restyle(search);
+
+
+ *search_out = search;
+
+ return NSERROR_OK;
+}
diff --git a/frontends/gtk/search.h b/frontends/gtk/search.h
index dd8c60d0f..5eb0b35cc 100644
--- a/frontends/gtk/search.h
+++ b/frontends/gtk/search.h
@@ -16,21 +16,36 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_GTK_SEARCH_H_
-#define _NETSURF_GTK_SEARCH_H_
-
-struct gui_search_table *nsgtk_search_table;
-
-struct nsgtk_scaffolding;
-
-void nsgtk_search_bar_toggle_visibility(struct nsgtk_scaffolding * g);
-gboolean nsgtk_search_entry_changed(GtkWidget *widget, gpointer data);
-gboolean nsgtk_search_entry_activate(GtkWidget *widget, gpointer data);
-gboolean nsgtk_search_entry_key(GtkWidget *widget, GdkEventKey *event, gpointer data);
-gboolean nsgtk_search_forward_button_clicked(GtkWidget *widget, gpointer data);
-gboolean nsgtk_search_back_button_clicked(GtkWidget *widget, gpointer data);
-gboolean nsgtk_search_close_button_clicked(GtkWidget *widget, gpointer data);
-gboolean nsgtk_websearch_activate(GtkWidget *widget, gpointer data);
-gboolean nsgtk_websearch_clear(GtkWidget *widget, GdkEventFocus *f, gpointer data);
-
+/**
+ * \file
+ * free text page search for gtk interface
+ */
+
+#ifndef NETSURF_GTK_SEARCH_H_
+#define NETSURF_GTK_SEARCH_H_
+
+extern struct gui_search_table *nsgtk_search_table;
+
+struct gtk_search;
+
+/**
+ * create text search context
+ *
+ * \param builder the gtk builder containing the search toolbar
+ * \param bw The browsing context to run the find operations against
+ * \param search search context result
+ * \return NSERROR_OK and search_out updated
+ */
+nserror nsgtk_search_create(GtkBuilder *builder, struct browser_window *bw, struct gtk_search **search);
+
+/**
+ * update search toolbar size and style
+ */
+nserror nsgtk_search_restyle(struct gtk_search *search);
+
+/**
+ * toggle search bar visibility
+ */
+nserror nsgtk_search_toggle_visibility(struct gtk_search *search);
+
#endif
diff --git a/frontends/gtk/selection.c b/frontends/gtk/selection.c
index 228d65dbe..871526047 100644
--- a/frontends/gtk/selection.c
+++ b/frontends/gtk/selection.c
@@ -24,6 +24,7 @@
#include "netsurf/browser_window.h"
#include "netsurf/clipboard.h"
+#include "gtk/toolbar_items.h"
#include "gtk/window.h"
static GString *current_selection = NULL;
diff --git a/frontends/gtk/selection.h b/frontends/gtk/selection.h
index 6463692cf..07716a0d9 100644
--- a/frontends/gtk/selection.h
+++ b/frontends/gtk/selection.h
@@ -19,6 +19,6 @@
#ifndef GTK_SELECTION_H
#define GTK_SELECTION_H
-struct gui_clipboard_table *nsgtk_clipboard_table;
+extern struct gui_clipboard_table *nsgtk_clipboard_table;
#endif
diff --git a/frontends/gtk/ssl_cert.c b/frontends/gtk/ssl_cert.c
deleted file mode 100644
index 9d98db1f6..000000000
--- a/frontends/gtk/ssl_cert.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright 2015 Vincent Sanders <vince@netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- * Implementation of gtk certificate viewing using gtk core windows.
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <gtk/gtk.h>
-
-#include "utils/log.h"
-#include "netsurf/keypress.h"
-#include "netsurf/plotters.h"
-#include "desktop/sslcert_viewer.h"
-
-#include "gtk/plotters.h"
-#include "gtk/scaffolding.h"
-#include "gtk/resources.h"
-#include "gtk/ssl_cert.h"
-#include "gtk/corewindow.h"
-
-
-/**
- * GTK certificate viewing window context
- */
-struct nsgtk_crtvrfy_window {
- /** GTK core window context */
- struct nsgtk_corewindow core;
- /** GTK builder for window */
- GtkBuilder *builder;
- /** GTK dialog window being shown */
- GtkDialog *dlg;
- /** SSL certificate viewer context data */
- struct sslcert_session_data *ssl_data;
-};
-
-/**
- * destroy a previously created certificate view
- */
-static nserror nsgtk_crtvrfy_destroy(struct nsgtk_crtvrfy_window *crtvrfy_win)
-{
- nserror res;
-
- res = sslcert_viewer_fini(crtvrfy_win->ssl_data);
- if (res == NSERROR_OK) {
- res = nsgtk_corewindow_fini(&crtvrfy_win->core);
- gtk_widget_destroy(GTK_WIDGET(crtvrfy_win->dlg));
- g_object_unref(G_OBJECT(crtvrfy_win->builder));
- free(crtvrfy_win);
- }
- return res;
-}
-
-static void
-nsgtk_crtvrfy_accept(GtkButton *w, gpointer data)
-{
- struct nsgtk_crtvrfy_window *crtvrfy_win;
- crtvrfy_win = (struct nsgtk_crtvrfy_window *)data;
-
- sslcert_viewer_accept(crtvrfy_win->ssl_data);
-
- nsgtk_crtvrfy_destroy(crtvrfy_win);
-}
-
-static void
-nsgtk_crtvrfy_reject(GtkWidget *w, gpointer data)
-{
- struct nsgtk_crtvrfy_window *crtvrfy_win;
- crtvrfy_win = (struct nsgtk_crtvrfy_window *)data;
-
- sslcert_viewer_reject(crtvrfy_win->ssl_data);
-
- nsgtk_crtvrfy_destroy(crtvrfy_win);
-}
-
-static gboolean
-nsgtk_crtvrfy_delete_event(GtkWidget *w, GdkEvent *event, gpointer data)
-{
- nsgtk_crtvrfy_reject(w, data);
- return FALSE;
-}
-
-/**
- * callback for mouse action for certificate verify on core window
- *
- * \param nsgtk_cw The nsgtk core window structure.
- * \param mouse_state netsurf mouse state on event
- * \param x location of event
- * \param y location of event
- * \return NSERROR_OK on success otherwise appropriate error code
- */
-static nserror
-nsgtk_crtvrfy_mouse(struct nsgtk_corewindow *nsgtk_cw,
- browser_mouse_state mouse_state,
- int x, int y)
-{
- struct nsgtk_crtvrfy_window *crtvrfy_win;
- /* technically degenerate container of */
- crtvrfy_win = (struct nsgtk_crtvrfy_window *)nsgtk_cw;
-
- sslcert_viewer_mouse_action(crtvrfy_win->ssl_data, mouse_state, x, y);
-
- return NSERROR_OK;
-}
-
-/**
- * callback for keypress for certificate verify on core window
- *
- * \param nsgtk_cw The nsgtk core window structure.
- * \param nskey The netsurf key code
- * \return NSERROR_OK on success otherwise appropriate error code
- */
-static nserror
-nsgtk_crtvrfy_key(struct nsgtk_corewindow *nsgtk_cw, uint32_t nskey)
-{
- struct nsgtk_crtvrfy_window *crtvrfy_win;
-
- /* technically degenerate container of */
- crtvrfy_win = (struct nsgtk_crtvrfy_window *)nsgtk_cw;
-
- if (sslcert_viewer_keypress(crtvrfy_win->ssl_data, nskey)) {
- return NSERROR_OK;
- }
- return NSERROR_NOT_IMPLEMENTED;
-}
-
-/**
- * callback on draw event for certificate verify on core window
- *
- * \param nsgtk_cw The nsgtk core window structure.
- * \param r The rectangle of the window that needs updating.
- * \return NSERROR_OK on success otherwise appropriate error code
- */
-static nserror
-nsgtk_crtvrfy_draw(struct nsgtk_corewindow *nsgtk_cw, struct rect *r)
-{
- struct redraw_context ctx = {
- .interactive = true,
- .background_images = true,
- .plot = &nsgtk_plotters
- };
- struct nsgtk_crtvrfy_window *crtvrfy_win;
-
- /* technically degenerate container of */
- crtvrfy_win = (struct nsgtk_crtvrfy_window *)nsgtk_cw;
-
- sslcert_viewer_redraw(crtvrfy_win->ssl_data, 0, 0, r, &ctx);
-
- return NSERROR_OK;
-}
-
-/* exported interface documented in gtk/ssl_cert.h */
-nserror gtk_cert_verify(struct nsurl *url,
- const struct ssl_cert_info *certs,
- unsigned long num,
- nserror (*cb)(bool proceed, void *pw),
- void *cbpw)
-{
- struct nsgtk_crtvrfy_window *ncwin;
- nserror res;
-
- ncwin = malloc(sizeof(struct nsgtk_crtvrfy_window));
- if (ncwin == NULL) {
- return NSERROR_NOMEM;
- }
-
- res = nsgtk_builder_new_from_resname("ssl", &ncwin->builder);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "SSL UI builder init failed");
- free(ncwin);
- return res;
- }
-
- gtk_builder_connect_signals(ncwin->builder, NULL);
-
- ncwin->dlg = GTK_DIALOG(gtk_builder_get_object(ncwin->builder,
- "wndSSLProblem"));
-
- /* set parent for transient dialog */
- gtk_window_set_transient_for(GTK_WINDOW(ncwin->dlg),
- nsgtk_scaffolding_window(nsgtk_current_scaffolding()));
-
- ncwin->core.scrolled = GTK_SCROLLED_WINDOW(
- gtk_builder_get_object(ncwin->builder, "SSLScrolled"));
-
- ncwin->core.drawing_area = GTK_DRAWING_AREA(
- gtk_builder_get_object(ncwin->builder, "SSLDrawingArea"));
-
- /* make the delete event call our destructor */
- g_signal_connect(G_OBJECT(ncwin->dlg),
- "delete_event",
- G_CALLBACK(nsgtk_crtvrfy_delete_event),
- ncwin);
-
- /* accept button */
- g_signal_connect(G_OBJECT(gtk_builder_get_object(ncwin->builder,
- "sslaccept")),
- "clicked",
- G_CALLBACK(nsgtk_crtvrfy_accept),
- ncwin);
-
- /* reject button */
- g_signal_connect(G_OBJECT(gtk_builder_get_object(ncwin->builder,
- "sslreject")),
- "clicked",
- G_CALLBACK(nsgtk_crtvrfy_reject),
- ncwin);
-
- /* initialise GTK core window */
- ncwin->core.draw = nsgtk_crtvrfy_draw;
- ncwin->core.key = nsgtk_crtvrfy_key;
- ncwin->core.mouse = nsgtk_crtvrfy_mouse;
-
- res = nsgtk_corewindow_init(&ncwin->core);
- if (res != NSERROR_OK) {
- g_object_unref(G_OBJECT(ncwin->dlg));
- free(ncwin);
- return res;
- }
-
- /* initialise certificate viewing interface */
- res = sslcert_viewer_create_session_data(num, url, cb, cbpw, certs,
- &ncwin->ssl_data);
- if (res != NSERROR_OK) {
- g_object_unref(G_OBJECT(ncwin->dlg));
- free(ncwin);
- return res;
- }
-
- res = sslcert_viewer_init(ncwin->core.cb_table,
- (struct core_window *)ncwin,
- ncwin->ssl_data);
- if (res != NSERROR_OK) {
- g_object_unref(G_OBJECT(ncwin->dlg));
- free(ncwin);
- return res;
- }
-
- gtk_widget_show(GTK_WIDGET(ncwin->dlg));
-
- return NSERROR_OK;
-}
diff --git a/frontends/gtk/tabs.c b/frontends/gtk/tabs.c
index dbe9d405b..4fa109b70 100644
--- a/frontends/gtk/tabs.c
+++ b/frontends/gtk/tabs.c
@@ -20,11 +20,12 @@
#include <string.h>
#include "utils/nsoption.h"
-#include "utils/messages.h"
+#include "utils/log.h"
#include "netsurf/browser_window.h"
#include "desktop/search.h"
#include "gtk/compat.h"
+#include "gtk/toolbar_items.h"
#include "gtk/scaffolding.h"
#include "gtk/window.h"
#include "gtk/search.h"
@@ -32,9 +33,15 @@
#define TAB_WIDTH_N_CHARS 15
-/** callback to update sizes when style-set gtk signal */
-static void nsgtk_tab_update_size(GtkWidget *hbox, GtkStyle *previous_style,
- GtkWidget *close_button)
+static gint srcpagenum;
+
+/**
+ * callback to update sizes when style-set gtk signal
+ */
+static void
+nsgtk_tab_update_size(GtkWidget *hbox,
+ GtkStyle *previous_style,
+ GtkWidget *close_button)
{
PangoFontMetrics *metrics;
PangoContext *context;
@@ -63,63 +70,114 @@ static void nsgtk_tab_update_size(GtkWidget *hbox, GtkStyle *previous_style,
gtk_widget_set_size_request(close_button, w + 4, h + 4);
}
-/** Create a notebook tab label */
-static GtkWidget *nsgtk_tab_label_setup(struct gui_window *window)
+
+/**
+ * gtk event handler for button release on tab hbox
+ */
+static gboolean
+nsgtk_tab_button_release(GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ GtkWidget *page;
+
+ if ((event->type == GDK_BUTTON_RELEASE) && (event->button == 2)) {
+ page = (GtkWidget *)user_data;
+ gtk_widget_destroy(page);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/**
+ * Create a notebook tab label
+ *
+ * \param page The page content widget
+ * \param title The title of the page
+ * \param icon_pixbuf The icon of the page
+ */
+static GtkWidget *
+nsgtk_tab_label_setup(GtkWidget *page,
+ const char *title,
+ GdkPixbuf *icon_pixbuf)
{
- GtkWidget *hbox, *label, *button, *close;
+ GtkWidget *ebox, *hbox, *favicon, *label, *button, *close;
+
+ /* horizontal box */
+ hbox = nsgtk_hbox_new(FALSE, 3);
- hbox = nsgtk_hbox_new(FALSE, 2);
+ /* event box */
+ ebox = gtk_event_box_new();
+ gtk_widget_set_events(ebox, GDK_BUTTON_PRESS_MASK);
+ gtk_container_add(GTK_CONTAINER(ebox), hbox);
- label = gtk_label_new(messages_get("NewTab"));
+ /* construct a favicon */
+ favicon = gtk_image_new();
+ if (icon_pixbuf != NULL) {
+ gtk_image_set_from_pixbuf(GTK_IMAGE(favicon), icon_pixbuf);
+ }
+
+ /* construct a label */
+ label = gtk_label_new(title);
gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
gtk_label_set_single_line_mode(GTK_LABEL(label), TRUE);
nsgtk_widget_set_alignment(label, GTK_ALIGN_START, GTK_ALIGN_CENTER);
nsgtk_widget_set_margins(label, 0, 0);
gtk_widget_show(label);
+ /* construct a close button */
button = gtk_button_new();
close = nsgtk_image_new_from_stock(NSGTK_STOCK_CLOSE,
- GTK_ICON_SIZE_MENU);
+ GTK_ICON_SIZE_LARGE_TOOLBAR);
gtk_container_add(GTK_CONTAINER(button), close);
- gtk_button_set_focus_on_click(GTK_BUTTON(button), FALSE);
+ nsgtk_button_set_focus_on_click(GTK_BUTTON(button), FALSE);
gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
gtk_widget_set_tooltip_text(button, "Close this tab.");
-#ifdef FIXME
- GtkRcStyle *rcstyle;
- rcstyle = gtk_rc_style_new();
- rcstyle->xthickness = rcstyle->ythickness = 0;
- gtk_widget_modify_style(button, rcstyle);
- g_object_unref(rcstyle);
-#endif
-
- g_signal_connect_swapped(button, "clicked",
- G_CALLBACK(nsgtk_window_destroy_browser), window);
- g_signal_connect(hbox, "style-set",
- G_CALLBACK(nsgtk_tab_update_size), button);
-
+ /* pack the widgets into the label box */
+ gtk_box_pack_start(GTK_BOX(hbox), favicon, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
- g_object_set_data(G_OBJECT(hbox), "label", label);
- g_object_set_data(G_OBJECT(hbox), "close-button", button);
+ /* make the icon and label widgets findable by name */
+ g_object_set_data(G_OBJECT(ebox), "favicon", favicon);
+ g_object_set_data(G_OBJECT(ebox), "label", label);
+ /* attach signal handlers */
+ g_signal_connect_swapped(button,
+ "clicked",
+ G_CALLBACK(gtk_widget_destroy), page);
- gtk_widget_show_all(hbox);
- return hbox;
-}
-#include "utils/log.h"
+ g_signal_connect(hbox,
+ "style-set",
+ G_CALLBACK(nsgtk_tab_update_size),
+ button);
-/** callback when page is switched */
+ g_signal_connect(ebox,
+ "button-release-event",
+ G_CALLBACK(nsgtk_tab_button_release),
+ page);
-static gint srcpagenum;
-/** The switch-page signal handler
+ gtk_widget_show_all(ebox);
+
+ return ebox;
+}
+
+
+/**
+ * The before switch-page gtk signal handler
*
* This signal is handled both before and after delivery to work round
* issue that setting the selected tab during the switch-page signal
* fails
+ *
+ * \param notebook The notebook being changed
+ * \param page The notebook page being switched to
+ * \param selpagenum The currently selected page number
+ * \param user_data Unused
*/
static void
nsgtk_tab_switch_page(GtkNotebook *notebook,
@@ -130,6 +188,15 @@ nsgtk_tab_switch_page(GtkNotebook *notebook,
srcpagenum = gtk_notebook_get_current_page(notebook);
}
+
+/**
+ * The after switch-page gtk signal handler
+ *
+ * \param notebook The notebook being changed
+ * \param selpage The notebook page selected
+ * \param selpagenum The currently selected page number
+ * \param user_data Unused
+ */
static void
nsgtk_tab_switch_page_after(GtkNotebook *notebook,
GtkWidget *selpage,
@@ -138,41 +205,62 @@ nsgtk_tab_switch_page_after(GtkNotebook *notebook,
{
GtkWidget *srcpage;
GtkWidget *addpage;
- struct gui_window *gw;
- nserror error;
+ GtkMenuBar *menubar;
+ struct gui_window *gw = NULL;
+ nserror res = NSERROR_INVALID;
addpage = g_object_get_data(G_OBJECT(notebook), "addtab");
- if (selpage == addpage) {
- if ((srcpagenum != -1) &&
- (srcpagenum != (gint)selpagenum)) {
- /* ensure the add tab is not actually selected */
- NSLOG(netsurf, INFO, "src %d sel %d", srcpagenum,
- selpagenum);
- srcpage = gtk_notebook_get_nth_page(notebook, srcpagenum);
- gw = g_object_get_data(G_OBJECT(srcpage), "gui_window");
- if ((gw != NULL) && (nsgtk_get_scaffold(gw) != NULL)) {
- error = nsgtk_scaffolding_new_tab(gw);
- if (error != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Failed to open new tab.");
- }
- }
- }
- } else {
+ /* check if trying to select the "add page" tab */
+ if (selpage != addpage) {
NSLOG(netsurf, INFO, "sel %d", selpagenum);
- /* tab with page in it */
+ menubar = nsgtk_scaffolding_menu_bar(nsgtk_scaffolding_from_notebook(notebook));
gw = g_object_get_data(G_OBJECT(selpage), "gui_window");
if (gw != NULL) {
+ /* tab with web page in it */
nsgtk_scaffolding_set_top_level(gw);
+ gtk_widget_show(GTK_WIDGET(addpage));
+ gtk_widget_set_sensitive(GTK_WIDGET(menubar), true);
+ } else {
+ /* tab with non browser content (e.g. tb customize) */
+ gtk_widget_hide(GTK_WIDGET(addpage));
+ gtk_widget_set_sensitive(GTK_WIDGET(menubar), false);
}
+ return;
+ }
+
+ NSLOG(netsurf, INFO, "src %d sel %d", srcpagenum, selpagenum);
+
+ /* ensure the add tab is not already selected */
+ if ((srcpagenum == -1) || (srcpagenum == (gint)selpagenum)) {
+ return;
+ }
+
+ srcpage = gtk_notebook_get_nth_page(notebook, srcpagenum);
+
+ gw = g_object_get_data(G_OBJECT(srcpage), "gui_window");
+
+ if (gw != NULL) {
+ res = nsgtk_window_item_activate(gw, NEWTAB_BUTTON);
+ }
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Failed to open new tab.");
}
}
-static void nsgtk_tab_page_reordered(GtkNotebook *notebook,
- GtkWidget *child,
- guint page_num,
- gpointer user_data)
+
+/**
+ * The tab reordered gtk signal handler
+ *
+ * \param notebook The notebook being changed
+ * \param page_num The currently selected page number
+ * \param user_data Unused
+ */
+static void
+nsgtk_tab_page_reordered(GtkNotebook *notebook,
+ GtkWidget *child,
+ guint page_num,
+ gpointer user_data)
{
gint pages;
GtkWidget *addpage;
@@ -187,6 +275,13 @@ static void nsgtk_tab_page_reordered(GtkNotebook *notebook,
}
}
+/**
+ * The tab orientation signal handler
+ *
+ * \param notebook The notebook being changed
+ * \param page_num The currently selected page number
+ * \param user_data Unused
+ */
static void
nsgtk_tab_orientation(GtkNotebook *notebook)
{
@@ -210,7 +305,9 @@ nsgtk_tab_orientation(GtkNotebook *notebook)
}
}
-/** adds a "new tab" tab */
+/**
+ * adds a "new tab" tab
+ */
static GtkWidget *
nsgtk_tab_add_newtab(GtkNotebook *notebook)
{
@@ -221,7 +318,9 @@ nsgtk_tab_add_newtab(GtkNotebook *notebook)
tablabel = nsgtk_hbox_new(FALSE, 1);
tabcontents = nsgtk_hbox_new(FALSE, 1);
- add = nsgtk_image_new_from_stock(NSGTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
+ add = gtk_image_new_from_icon_name(NSGTK_STOCK_ADD,
+ GTK_ICON_SIZE_LARGE_TOOLBAR);
+ gtk_widget_set_tooltip_text(add, "New Tab");
gtk_box_pack_start(GTK_BOX(tablabel), add, FALSE, FALSE, 0);
@@ -238,18 +337,26 @@ nsgtk_tab_add_newtab(GtkNotebook *notebook)
return tablabel;
}
-/** callback to alter tab visibility when pages are added or removed */
+
+/**
+ * callback to alter tab visibility when pages are added or removed
+ */
static void
nsgtk_tab_visibility_update(GtkNotebook *notebook, GtkWidget *child, guint page)
{
- gint pagec = gtk_notebook_get_n_pages(notebook);
- GtkWidget *addpage = g_object_get_data(G_OBJECT(notebook), "addtab");
-
- if (addpage != NULL) {
- pagec--; /* skip the add tab */
- if ((gint)page == pagec) {
- /* ensure the add new tab cannot be current */
- gtk_notebook_set_current_page(notebook, page - 1);
+ gint pagec;
+ GtkWidget *addpage;
+
+ pagec = gtk_notebook_get_n_pages(notebook);
+ if (pagec > 1) {
+ addpage = g_object_get_data(G_OBJECT(notebook), "addtab");
+ if (addpage != NULL) {
+ pagec--; /* skip the add tab */
+ if ((gint)page == pagec) {
+ /* ensure the add new tab cannot be current */
+ gtk_notebook_set_current_page(notebook,
+ page - 1);
+ }
}
}
@@ -260,6 +367,7 @@ nsgtk_tab_visibility_update(GtkNotebook *notebook, GtkWidget *child, guint page)
}
}
+
/* exported interface documented in gtk/tabs.h */
void nsgtk_tab_options_changed(GtkNotebook *notebook)
{
@@ -269,48 +377,56 @@ void nsgtk_tab_options_changed(GtkNotebook *notebook)
/* exported interface documented in gtk/tabs.h */
-void nsgtk_tab_init(struct nsgtk_scaffolding *gs)
+nserror nsgtk_notebook_create(GtkBuilder *builder, GtkNotebook **notebook_out)
{
GtkNotebook *notebook;
- notebook = nsgtk_scaffolding_notebook(gs);
+ notebook = GTK_NOTEBOOK(gtk_builder_get_object(builder, "notebook"));
nsgtk_tab_add_newtab(notebook);
- g_signal_connect(notebook, "switch-page",
- G_CALLBACK(nsgtk_tab_switch_page), NULL);
- g_signal_connect_after(notebook, "switch-page",
- G_CALLBACK(nsgtk_tab_switch_page_after), NULL);
+ g_signal_connect(notebook,
+ "switch-page",
+ G_CALLBACK(nsgtk_tab_switch_page),
+ NULL);
+ g_signal_connect_after(notebook,
+ "switch-page",
+ G_CALLBACK(nsgtk_tab_switch_page_after),
+ NULL);
+ g_signal_connect(notebook,
+ "page-removed",
+ G_CALLBACK(nsgtk_tab_visibility_update),
+ NULL);
+ g_signal_connect(notebook,
+ "page-added",
+ G_CALLBACK(nsgtk_tab_visibility_update),
+ NULL);
+ g_signal_connect(notebook,
+ "page-reordered",
+ G_CALLBACK(nsgtk_tab_page_reordered),
+ NULL);
- g_signal_connect(notebook, "page-removed",
- G_CALLBACK(nsgtk_tab_visibility_update), NULL);
- g_signal_connect(notebook, "page-added",
- G_CALLBACK(nsgtk_tab_visibility_update), NULL);
- g_signal_connect(notebook, "page-reordered",
- G_CALLBACK(nsgtk_tab_page_reordered), NULL);
+ nsgtk_tab_options_changed(notebook);
+ *notebook_out = notebook;
- nsgtk_tab_options_changed(notebook);
+ return NSERROR_OK;
}
/* exported interface documented in gtk/tabs.h */
-void nsgtk_tab_add(struct gui_window *gw,
+nserror
+nsgtk_tab_add_page(GtkNotebook *notebook,
GtkWidget *tab_contents,
- bool background)
+ bool background,
+ const char *title,
+ GdkPixbuf *icon_pixbuf)
{
- GtkNotebook *notebook;
GtkWidget *tabBox;
gint remember;
gint pages;
gint newpage;
- g_object_set_data(G_OBJECT(tab_contents), "gui_window", gw);
-
- notebook = nsgtk_scaffolding_notebook(nsgtk_get_scaffold(gw));
-
- tabBox = nsgtk_tab_label_setup(gw);
-
- nsgtk_window_set_tab(gw, tabBox);
+ tabBox = nsgtk_tab_label_setup(tab_contents, title, icon_pixbuf);
remember = gtk_notebook_get_current_page(notebook);
@@ -328,24 +444,83 @@ void nsgtk_tab_add(struct gui_window *gw,
gtk_notebook_set_current_page(notebook, newpage);
}
- gtk_widget_grab_focus(GTK_WIDGET(nsgtk_scaffolding_urlbar(
- nsgtk_get_scaffold(gw))));
+ return NSERROR_OK;
}
+
/* exported interface documented in gtk/tabs.h */
-void nsgtk_tab_set_title(struct gui_window *g, const char *title)
+void nsgtk_tab_add(struct gui_window *gw,
+ GtkWidget *tab_contents,
+ bool background,
+ const char *title,
+ GdkPixbuf *icon_pixbuf)
{
- GtkWidget *label;
- GtkWidget *tab;
+ GtkNotebook *notebook;
- tab = nsgtk_window_get_tab(g);
- if (tab == NULL) {
- return;
+ g_object_set_data(G_OBJECT(tab_contents), "gui_window", gw);
+
+ notebook = nsgtk_scaffolding_notebook(nsgtk_get_scaffold(gw));
+
+ nsgtk_tab_add_page(notebook, tab_contents, background, title, icon_pixbuf);
+
+}
+
+
+/* exported interface documented in gtk/tabs.h */
+nserror nsgtk_tab_set_icon(GtkWidget *page, GdkPixbuf *pixbuf)
+{
+ GtkImage *favicon;
+ GtkWidget *tab_label;
+ GtkNotebook *notebook;
+
+ if (pixbuf == NULL) {
+ return NSERROR_INVALID;
+ }
+ notebook = GTK_NOTEBOOK(gtk_widget_get_ancestor(page, GTK_TYPE_NOTEBOOK));
+ if (notebook == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ tab_label = gtk_notebook_get_tab_label(notebook, page);
+ if (tab_label == NULL) {
+ return NSERROR_INVALID;
}
- label = g_object_get_data(G_OBJECT(tab), "label");
- gtk_label_set_text(GTK_LABEL(label), title);
- gtk_widget_set_tooltip_text(tab, title);
+ favicon = GTK_IMAGE(g_object_get_data(G_OBJECT(tab_label), "favicon"));
+
+ gtk_image_set_from_pixbuf(favicon, pixbuf);
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in gtk/tabs.h */
+nserror nsgtk_tab_set_title(GtkWidget *page, const char *title)
+{
+ GtkLabel *label;
+ GtkWidget *tab_label;
+ GtkNotebook *notebook;
+
+ if (title == NULL) {
+ return NSERROR_INVALID;
+ }
+
+ notebook = GTK_NOTEBOOK(gtk_widget_get_ancestor(page, GTK_TYPE_NOTEBOOK));
+ if (notebook == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ tab_label = gtk_notebook_get_tab_label(notebook, page);
+ if (tab_label == NULL) {
+ return NSERROR_INVALID;
+ }
+
+ label = GTK_LABEL(g_object_get_data(G_OBJECT(tab_label), "label"));
+
+ gtk_label_set_text(label, title);
+ gtk_widget_set_tooltip_text(tab_label, title);
+
+ return NSERROR_OK;
}
/* exported interface documented in gtk/tabs.h */
diff --git a/frontends/gtk/tabs.h b/frontends/gtk/tabs.h
index 440d61336..63edae3cc 100644
--- a/frontends/gtk/tabs.h
+++ b/frontends/gtk/tabs.h
@@ -16,24 +16,58 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_GTK_TABS_H_
-#define _NETSURF_GTK_TABS_H_
+#ifndef NETSURF_GTK_TABS_H_
+#define NETSURF_GTK_TABS_H_
struct gui_window;
-void nsgtk_tab_init(struct nsgtk_scaffolding *gs);
-void nsgtk_tab_add(struct gui_window *window, GtkWidget *tab_contents, bool background);
+/**
+ * create notebook
+ *
+ * creates a notebook for use inside a window, creates the special add
+ * page(tab) and attaches all signals.
+ *
+ * \param builder the gtk builder object to create notbook from
+ * \param notebook_out reciveds the created notebook
+ * \return NSERROR_OK and notebook_out updated else error code
+ */
+nserror nsgtk_notebook_create(GtkBuilder *builder, GtkNotebook **notebook_out);
+
+/**
+ * Add new gui window page to notebook.
+ */
+void nsgtk_tab_add(struct gui_window *window, GtkWidget *tab_contents, bool background, const char *title, GdkPixbuf *icon_pixbuf);
+
+/**
+ * Add new page to a notebook
+ */
+nserror nsgtk_tab_add_page(GtkNotebook *notebook, GtkWidget *tab_contents, bool background, const char *title, GdkPixbuf *icon_pixbuf);
-/** set the tab title
+
+/**
+ * set the tab title
*
* The tab title will be set to the parameter
*
* \note currently only called from nsgtk_window_set_title()
*
- * \param g the gui window to set tab title for.
+ * \param page The page widget that was added to the notebook
* \param title The title text which may not be NULL.
+ * \return NSERROR_OK on sucess else appropriate code.
+ */
+nserror nsgtk_tab_set_title(GtkWidget *page, const char *title);
+
+/**
+ * set the tab icon
+ *
+ * The tab icon will be set to the \a pixbuf parameter
+ *
+ * \param page The page widget that was added to the notebook
+ * \param pixbuf The pixbuf to set the icon to.
+ * \return NSERROR_OK on sucess else appropriate code.
*/
-void nsgtk_tab_set_title(struct gui_window *g, const char *title);
+nserror nsgtk_tab_set_icon(GtkWidget *page, GdkPixbuf *pixbuf);
+
void nsgtk_tab_options_changed(GtkNotebook *notebook);
nserror nsgtk_tab_close_current(GtkNotebook *notebook);
nserror nsgtk_tab_prev(GtkNotebook *notebook);
diff --git a/frontends/gtk/throbber.c b/frontends/gtk/throbber.c
index b8efceca1..f94893bef 100644
--- a/frontends/gtk/throbber.c
+++ b/frontends/gtk/throbber.c
@@ -28,7 +28,16 @@
#include "gtk/resources.h"
#include "gtk/throbber.h"
-struct nsgtk_throbber *nsgtk_throbber = NULL;
+/**
+ * Throbber images context
+ */
+struct nsgtk_throbber
+{
+ int nframes; /**< Number of frames in the throbber */
+ GdkPixbuf **framedata; /* pixbuf data for the frames */
+};
+
+static struct nsgtk_throbber *nsgtk_throbber = NULL;
#define THROBBER_FRAMES 9
#define THROBBER_FMT "throbber/throbber%d.png"
@@ -36,10 +45,10 @@ struct nsgtk_throbber *nsgtk_throbber = NULL;
/* exported interface documented in gtk/throbber.h */
nserror nsgtk_throbber_init(void)
{
- struct nsgtk_throbber *throb; /**< structure we generate */
+ nserror res = NSERROR_OK;
+ struct nsgtk_throbber *throb;
int frame;
char resname[] = THROBBER_FMT;
- nserror res = NSERROR_OK;
throb = malloc(sizeof(*throb));
if (throb == NULL) {
@@ -49,7 +58,7 @@ nserror nsgtk_throbber_init(void)
throb->framedata = malloc(sizeof(GdkPixbuf *) * THROBBER_FRAMES);
if (throb->framedata == NULL) {
free(throb);
- return false;
+ return NSERROR_NOMEM;
}
for (frame = 0; frame < THROBBER_FRAMES; frame++) {
@@ -73,11 +82,9 @@ nserror nsgtk_throbber_init(void)
throb->nframes = frame;
nsgtk_throbber = throb;
return res;
-
-
}
-
+/* exported interface documented in gtk/throbber.h */
void nsgtk_throbber_finalise(void)
{
int i;
@@ -91,3 +98,30 @@ void nsgtk_throbber_finalise(void)
nsgtk_throbber = NULL;
}
+
+/* exported interface documented in gtk/throbber.h */
+nserror nsgtk_throbber_get_frame(int frame, GdkPixbuf **pixbuf)
+{
+ nserror res = NSERROR_OK;
+
+ /* ensure initialisation */
+ if (nsgtk_throbber == NULL) {
+ res = nsgtk_throbber_init();
+ }
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* ensure frame in range */
+ if ((frame < 0) || (frame >= nsgtk_throbber->nframes)) {
+ return NSERROR_BAD_SIZE;
+ }
+
+ /* ensure there is frame data */
+ if (nsgtk_throbber->framedata[frame] == NULL) {
+ return NSERROR_INVALID;
+ }
+
+ *pixbuf = nsgtk_throbber->framedata[frame];
+ return NSERROR_OK;
+}
diff --git a/frontends/gtk/throbber.h b/frontends/gtk/throbber.h
index e0b47e15c..c8529d2e2 100644
--- a/frontends/gtk/throbber.h
+++ b/frontends/gtk/throbber.h
@@ -16,20 +16,27 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef __GTK_THROBBER_H__
-#define __GTK_THROBBER_H__
-
-#include <gtk/gtk.h>
-
-struct nsgtk_throbber
-{
- int nframes; /**< Number of frames in the throbber */
- GdkPixbuf **framedata;
-};
-
-extern struct nsgtk_throbber *nsgtk_throbber;
+#ifndef NETSURF_GTK_THROBBER_H
+#define NETSURF_GTK_THROBBER_H
+/**
+ * Initialise global throbber context
+ */
nserror nsgtk_throbber_init(void);
+
+/**
+ * release global throbber context
+ */
void nsgtk_throbber_finalise(void);
-#endif /* __GTK_THROBBER_H__ */
+/**
+ * get the pixbuf of a given frame of the throbber
+ *
+ * \param frame The frame number starting at 0 for stopped frame
+ * \param pixbuf updated on success
+ * \return NSERROR_OK and pixbuf updated on success, NSERROR_BAD_SIZE if frame
+ * is out of range else error code.
+ */
+nserror nsgtk_throbber_get_frame(int frame, GdkPixbuf **pixbuf);
+
+#endif /* NETSURF_GTK_THROBBER_H */
diff --git a/frontends/gtk/toolbar.c b/frontends/gtk/toolbar.c
index e93bd49f9..6ec41cc1d 100644
--- a/frontends/gtk/toolbar.c
+++ b/frontends/gtk/toolbar.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ * Copyright 2019 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,18 +16,36 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+/**
+ * \file
+ * implementation of toolbar to control browsing context
+ */
+
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <errno.h>
#include <gtk/gtk.h>
-#include "netsurf/browser_window.h"
-#include "desktop/searchweb.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/nsoption.h"
#include "utils/file.h"
+#include "utils/nsurl.h"
+#include "utils/corestrings.h"
+#include "desktop/browser_history.h"
+#include "desktop/searchweb.h"
+#include "desktop/search.h"
+#include "desktop/save_complete.h"
+#include "desktop/save_text.h"
+#include "desktop/print.h"
+#include "desktop/hotlist.h"
+#include "netsurf/content.h"
+#include "netsurf/browser_window.h"
+#include "netsurf/keypress.h"
+#include "gtk/toolbar_items.h"
+#include "gtk/completion.h"
#include "gtk/gui.h"
#include "gtk/warn.h"
#include "gtk/search.h"
@@ -36,63 +54,203 @@
#include "gtk/window.h"
#include "gtk/compat.h"
#include "gtk/resources.h"
+#include "gtk/schedule.h"
+#include "gtk/local_history.h"
+#include "gtk/global_history.h"
+#include "gtk/viewsource.h"
+#include "gtk/download.h"
+#include "gtk/viewdata.h"
+#include "gtk/tabs.h"
+#include "gtk/print.h"
+#include "gtk/layout_pango.h"
+#include "gtk/preferences.h"
+#include "gtk/hotlist.h"
+#include "gtk/cookies.h"
+#include "gtk/about.h"
+#include "gtk/gdk.h"
+#include "gtk/bitmap.h"
+#include "gtk/page_info.h"
#include "gtk/toolbar.h"
-static GtkTargetEntry entry = {(char *)"nsgtk_button_data",
- GTK_TARGET_SAME_APP, 0};
-
-static bool edit_mode = false;
-
-struct nsgtk_toolbar_custom_store {
- GtkWidget *window;
- GtkWidget *store_buttons[PLACEHOLDER_BUTTON];
- GtkWidget *widgetvbox;
- GtkWidget *currentbar;
- char numberh; /* current horizontal location while adding */
- GtkBuilder *builder; /* button widgets to store */
- int buttonlocations[PLACEHOLDER_BUTTON];
- int currentbutton;
- bool fromstore;
-};
-/* the number of buttons that fit in the width of the store window */
-#define NSGTK_STORE_WIDTH 6
+/**
+ * button location indicating button is not to be shown
+ */
+#define INACTIVE_LOCATION (-1)
-/* the 'standard' width of a button that makes sufficient of its label
-visible */
-#define NSGTK_BUTTON_WIDTH 111
+/**
+ * time (in ms) between throbber animation frame updates
+ */
+#define THROBBER_FRAME_TIME (100)
-/* the 'standard' height of a button that fits as many toolbars as
-possible into the store */
+/**
+ * the minimum number of columns in the tool store
+ */
+#define NSGTK_MIN_STORE_COLUMNS 4
+
+/**
+ * the 'standard' width of a button that makes sufficient of its label visible
+ */
+#define NSGTK_BUTTON_WIDTH 120
+
+/**
+ * the 'standard' height of a button that fits as many toolbars as
+ * possible into the store
+ */
#define NSGTK_BUTTON_HEIGHT 70
-/* the 'normal' width of the websearch bar */
+/**
+ * the 'normal' width of the websearch bar
+ */
#define NSGTK_WEBSEARCH_WIDTH 150
-static struct nsgtk_toolbar_custom_store store;
-static struct nsgtk_toolbar_custom_store *window = &store;
+/**
+ * toolbar item context
+ */
+struct nsgtk_toolbar_item {
+
+ /**
+ * GTK widget in the toolbar
+ */
+ GtkToolItem *button;
+
+ /**
+ * location index in toolbar
+ */
+ int location;
+
+ /**
+ * if the item is currently sensitive in the toolbar
+ */
+ bool sensitivity;
+
+ /**
+ * textural name used in serialising items
+ */
+ const char *name;
+
+ /**
+ * button clicked on toolbar handler
+ */
+ gboolean (*clicked)(GtkWidget *widget, gpointer data);
+
+ /**
+ * handler when dragging from customisation toolbox to toolbar
+ */
+ void *dataplus;
+
+ /**
+ * handler when dragging from toolbar to customisation toolbox
+ */
+ void *dataminus;
+};
+/**
+ * Location focus state machine
+ *
+ * 1. If we don't care, we're in LFS_IDLE
+ * 2. When we create a new toolbar, we can put it into
+ * LFS_WANT which means that we want the url bar to focus
+ * 3. When we start throbbing if we're in LFS_WANT we move to LFS_THROB
+ * 4. When we stop throbbing, if we're in LFS_THROB we move to LFS_LAST
+ *
+ * While not in LFS_IDLE, if the url bar is updated and we previously had it
+ * fully selected then we reselect it all. If we're in LFS_LAST we move to
+ * LFS_IDLE at that point.
+ */
+typedef enum {
+ LFS_IDLE, /**< Nothing to do */
+ LFS_WANT, /**< Want focus, will apply */
+ LFS_THROB, /**< Want focus, we have started throbbing */
+ LFS_LAST, /**< Last chance for a focus update */
+} nsgtk_toolbar_location_focus_state;
-enum image_sets {
- IMAGE_SET_MAIN_MENU = 0,
- IMAGE_SET_RCLICK_MENU,
- IMAGE_SET_POPUP_MENU,
- IMAGE_SET_BUTTONS,
- IMAGE_SET_COUNT
+/**
+ * control toolbar context
+ */
+struct nsgtk_toolbar {
+ /** gtk toolbar widget */
+ GtkToolbar *widget;
+
+ /* toolbar size allocation context */
+ int offset;
+ int toolbarmem;
+ int toolbarbase;
+ int historybase;
+
+ /**
+ * Toolbar item contexts
+ */
+ struct nsgtk_toolbar_item items[PLACEHOLDER_BUTTON];
+
+ /**
+ * Current frame of throbber animation
+ */
+ int throb_frame;
+
+ /**
+ * Web search widget
+ */
+ GtkWidget *webSearchEntry;
+
+ /**
+ * callback to obtain a browser window for navigation
+ */
+ struct browser_window *(*get_bw)(void *ctx);
+
+ /**
+ * context passed to get_bw function
+ */
+ void *get_ctx;
+
+ /**
+ * Location focus state machine, current state
+ */
+ nsgtk_toolbar_location_focus_state loc_focus;
};
-typedef enum search_buttons {
- SEARCH_BACK_BUTTON = 0,
- SEARCH_FORWARD_BUTTON,
- SEARCH_CLOSE_BUTTON,
- SEARCH_BUTTONS_COUNT
-} nsgtk_search_buttons;
-
-struct nsgtk_theme {
- GtkImage *image[PLACEHOLDER_BUTTON];
- GtkImage *searchimage[SEARCH_BUTTONS_COUNT];
- /* apng throbber element */
+
+/**
+ * toolbar cusomisation context
+ */
+struct nsgtk_toolbar_customisation {
+ /**
+ * first entry is a toolbar widget so a customisation widget
+ * can be cast to toolbar and back.
+ */
+ struct nsgtk_toolbar toolbar;
+
+ /**
+ * The top level container (tabBox)
+ */
+ GtkWidget *container;
+
+ /**
+ * The vertical box into which the available tools are shown
+ */
+ GtkBox *toolbox;
+
+ /**
+ * widget handles for items in the customisation toolbox area
+ */
+ GtkToolItem *items[PLACEHOLDER_BUTTON];
+
+ /**
+ * which item is being dragged
+ */
+ int dragitem; /* currentbutton */
+ /**
+ * true if item being dragged onto toolbar, false if from toolbar
+ */
+ bool dragfrom; /*fromstore */
+
};
+
+/* forward declaration */
+static nserror toolbar_item_create(nsgtk_toolbar_button id,
+ struct nsgtk_toolbar_item *item_out);
+
+
/**
* returns a string without its underscores
*
@@ -122,1372 +280,3608 @@ static char *remove_underscores(const char *s, bool replacespace)
/**
- * get default image for buttons / menu items from gtk stock items.
- *
- * \param tbbutton button reference
- * \param iconsize The size of icons to select.
- * \param usedef Use the default image if not found.
- * \return default images.
- */
-static GtkImage *
-nsgtk_theme_image_default(nsgtk_toolbar_button tbbutton,
- GtkIconSize iconsize,
- bool usedef)
-{
- GtkImage *image; /* The GTK image to return */
-
- switch(tbbutton) {
-
-#define BUTTON_IMAGE(p, q) \
- case p##_BUTTON: \
- image = GTK_IMAGE(nsgtk_image_new_from_stock(q, iconsize)); \
- break
-
- BUTTON_IMAGE(BACK, NSGTK_STOCK_GO_BACK);
- BUTTON_IMAGE(FORWARD, NSGTK_STOCK_GO_FORWARD);
- BUTTON_IMAGE(STOP, NSGTK_STOCK_STOP);
- BUTTON_IMAGE(RELOAD, NSGTK_STOCK_REFRESH);
- BUTTON_IMAGE(HOME, NSGTK_STOCK_HOME);
- BUTTON_IMAGE(NEWWINDOW, "gtk-new");
- BUTTON_IMAGE(NEWTAB, "gtk-new");
- BUTTON_IMAGE(OPENFILE, NSGTK_STOCK_OPEN);
- BUTTON_IMAGE(CLOSETAB, NSGTK_STOCK_CLOSE);
- BUTTON_IMAGE(CLOSEWINDOW, NSGTK_STOCK_CLOSE);
- BUTTON_IMAGE(SAVEPAGE, NSGTK_STOCK_SAVE_AS);
- BUTTON_IMAGE(PRINTPREVIEW, "gtk-print-preview");
- BUTTON_IMAGE(PRINT, "gtk-print");
- BUTTON_IMAGE(QUIT, "gtk-quit");
- BUTTON_IMAGE(CUT, "gtk-cut");
- BUTTON_IMAGE(COPY, "gtk-copy");
- BUTTON_IMAGE(PASTE, "gtk-paste");
- BUTTON_IMAGE(DELETE, "gtk-delete");
- BUTTON_IMAGE(SELECTALL, "gtk-select-all");
- BUTTON_IMAGE(FIND, NSGTK_STOCK_FIND);
- BUTTON_IMAGE(PREFERENCES, "gtk-preferences");
- BUTTON_IMAGE(ZOOMPLUS, "gtk-zoom-in");
- BUTTON_IMAGE(ZOOMMINUS, "gtk-zoom-out");
- BUTTON_IMAGE(ZOOMNORMAL, "gtk-zoom-100");
- BUTTON_IMAGE(FULLSCREEN, "gtk-fullscreen");
- BUTTON_IMAGE(VIEWSOURCE, "gtk-index");
- BUTTON_IMAGE(CONTENTS, "gtk-help");
- BUTTON_IMAGE(ABOUT, "gtk-about");
-#undef BUTTON_IMAGE
+ * create throbber toolbar item widget
+ *
+ * create a gtk entry widget with a completion attached
+ */
+static GtkToolItem *
+make_toolbar_item_throbber(bool sensitivity, bool edit)
+{
+ nserror res;
+ GtkToolItem *item;
+ GdkPixbuf *pixbuf;
+ GtkWidget *image;
- case HISTORY_BUTTON:
- image = GTK_IMAGE(gtk_image_new_from_pixbuf(arrow_down_pixbuf));
- break;
+ res = nsgtk_throbber_get_frame(0, &pixbuf);
+ if (res != NSERROR_OK) {
+ return NULL;
+ }
- default:
- image = NULL;
- break;
+ if (edit) {
+ const char *msg;
+ msg = messages_get("ToolThrob");
+ item = gtk_tool_button_new(
+ GTK_WIDGET(gtk_image_new_from_pixbuf(pixbuf)),
+ msg);
+ } else {
+ item = gtk_tool_item_new();
+
+ image = gtk_image_new_from_pixbuf(pixbuf);
+ if (image != NULL) {
+ nsgtk_widget_set_alignment(image,
+ GTK_ALIGN_CENTER,
+ GTK_ALIGN_CENTER);
+ nsgtk_widget_set_margins(image, 3, 0);
+
+ gtk_container_add(GTK_CONTAINER(item), image);
+ }
+ }
+ gtk_widget_set_sensitive(GTK_WIDGET(item), sensitivity);
+
+ return item;
+}
+
+
+/**
+ * create url bar toolbar item widget
+ *
+ * create a gtk entry widget with a completion attached
+ *
+ * \param sensitivity if the entry should be created sensitive to input
+ * \param edit if the entry should be editable
+ */
+static GtkToolItem *
+make_toolbar_item_url_bar(bool sensitivity, bool edit)
+{
+ GtkToolItem *item;
+ GtkWidget *entry;
+ GtkEntryCompletion *completion;
+
+ entry = nsgtk_entry_new();
+ if (entry == NULL) {
+ return NULL;
}
+ nsgtk_entry_set_icon_from_icon_name(entry,
+ GTK_ENTRY_ICON_PRIMARY,
+ "page-info-internal");
+
+ if (edit) {
+ gtk_entry_set_width_chars(GTK_ENTRY(entry), 9);
+
+ item = gtk_tool_button_new(NULL, "URL");
+ gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(item), entry);
+ } else {
+ completion = gtk_entry_completion_new();
+ if (completion != NULL) {
+ gtk_entry_set_completion(GTK_ENTRY(entry), completion);
+ }
+
+ item = gtk_tool_item_new();
+ if (item == NULL) {
+ return NULL;
+ }
+
+ gtk_container_add(GTK_CONTAINER(item), entry);
+ gtk_tool_item_set_expand(item, TRUE);
- if (usedef && (image == NULL)) {
- image = GTK_IMAGE(nsgtk_image_new_from_stock("gtk-missing-image", iconsize));
}
+ gtk_widget_set_sensitive(GTK_WIDGET(item), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(entry), sensitivity);
- return image;
+ return item;
}
+
/**
- * Get default image for search buttons / menu items from gtk stock items
+ * create web search toolbar item widget
+ */
+static GtkToolItem *
+make_toolbar_item_websearch(bool sensitivity, bool edit)
+{
+ GtkToolItem *item;
+ nserror res;
+ GtkWidget *entry;
+ struct bitmap *bitmap;
+ GdkPixbuf *pixbuf = NULL;
+
+ res = search_web_get_provider_bitmap(&bitmap);
+ if ((res == NSERROR_OK) && (bitmap != NULL)) {
+ pixbuf = nsgdk_pixbuf_get_from_surface(bitmap->surface, 32, 32);
+ }
+
+ entry = nsgtk_entry_new();
+
+ if (entry == NULL) {
+ return NULL;
+ }
+
+ if (pixbuf != NULL) {
+ nsgtk_entry_set_icon_from_pixbuf(entry,
+ GTK_ENTRY_ICON_PRIMARY,
+ pixbuf);
+ g_object_unref(pixbuf);
+ } else {
+ nsgtk_entry_set_icon_from_icon_name(entry,
+ GTK_ENTRY_ICON_PRIMARY,
+ NSGTK_STOCK_INFO);
+ }
+
+ if (edit) {
+ gtk_entry_set_width_chars(GTK_ENTRY(entry), 9);
+
+ item = gtk_tool_button_new(NULL, "Web Search");
+ gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(item),
+ entry);
+ } else {
+ gtk_widget_set_size_request(entry, NSGTK_WEBSEARCH_WIDTH, -1);
+
+ item = gtk_tool_item_new();
+ if (item == NULL) {
+ return NULL;
+ }
+
+ gtk_container_add(GTK_CONTAINER(item), entry);
+ }
+ gtk_widget_set_sensitive(GTK_WIDGET(item), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(entry), sensitivity);
+
+ return item;
+}
+
+
+/**
+ * create local history toolbar item widget
+ */
+static GtkToolItem *
+make_toolbar_item_history(bool sensitivity, bool edit)
+{
+ GtkToolItem *item;
+ const char *msg = "H";
+ char *label = NULL;
+
+ if (edit) {
+ msg = messages_get("gtkLocalHistory");
+ }
+ label = remove_underscores(msg, false);
+ item = gtk_tool_button_new(NULL, label);
+ if (label != NULL) {
+ free(label);
+ }
+ gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(item), "local-history");
+
+ /* set history widget minimum width */
+ gtk_widget_set_size_request(GTK_WIDGET(item), 20, -1);
+ gtk_widget_set_sensitive(GTK_WIDGET(item), sensitivity);
+
+ return item;
+}
+
+
+/**
+ * create generic button toolbar item widget
+ */
+static GtkToolItem *
+make_toolbar_item_button(const char *labelmsg,
+ const char *iconname,
+ bool sensitivity,
+ bool edit)
+{
+ GtkToolItem *item;
+ char *label = NULL;
+
+ label = remove_underscores(messages_get(labelmsg), false);
+
+ item = gtk_tool_button_new(NULL, label);
+ if (label != NULL) {
+ free(label);
+ }
+
+ if (item != NULL) {
+ gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(item), iconname);
+
+ gtk_widget_set_sensitive(GTK_WIDGET(item), sensitivity);
+ if (edit) {
+ nsgtk_widget_set_margins(GTK_WIDGET(item), 0, 0);
+ }
+ }
+
+ return item;
+}
+
+
+/**
+ * widget factory for creation of toolbar item widgets
*
- * \param tbbutton search button reference
- * \param iconsize The size of icons to select.
- * \param usedef Use the default image if not found.
- * \return default search image.
+ * \param i the id of the widget
+ * \param theme the theme to make the widgets from
+ * \return gtk widget
*/
+static GtkToolItem *
+make_toolbar_item(nsgtk_toolbar_button itemid, bool sensitivity)
+{
+ GtkToolItem *toolitem = NULL;
+
+ switch(itemid) {
+#define TOOLBAR_ITEM_y(identifier, label, iconame)
+#define TOOLBAR_ITEM_n(identifier, label, iconame)
+#define TOOLBAR_ITEM_t(identifier, label, iconame) \
+ case identifier: \
+ toolitem = make_toolbar_item_button(#label, iconame, sensitivity, false); \
+ break;
+#define TOOLBAR_ITEM_b(identifier, label, iconame) \
+ case identifier: \
+ toolitem = make_toolbar_item_button(#label, iconame, sensitivity, false); \
+ break;
+#define TOOLBAR_ITEM(identifier, name, snstvty, clicked, activate, label, iconame) \
+ TOOLBAR_ITEM_ ## clicked(identifier, label, iconame)
+
+#include "gtk/toolbar_items.h"
+
+#undef TOOLBAR_ITEM_t
+#undef TOOLBAR_ITEM_b
+#undef TOOLBAR_ITEM_n
+#undef TOOLBAR_ITEM_y
+#undef TOOLBAR_ITEM
+
+ case HISTORY_BUTTON:
+ toolitem = make_toolbar_item_history(sensitivity, false);
+ break;
+
+ case URL_BAR_ITEM:
+ toolitem = make_toolbar_item_url_bar(sensitivity, false);
+ break;
-static GtkImage *
-nsgtk_theme_searchimage_default(nsgtk_search_buttons tbbutton,
- GtkIconSize iconsize,
- bool usedef)
+ case THROBBER_ITEM:
+ toolitem = make_toolbar_item_throbber(sensitivity, false);
+ break;
+
+ case WEBSEARCH_ITEM:
+ toolitem = make_toolbar_item_websearch(sensitivity, false);
+ break;
+
+ default:
+ break;
+
+ }
+ return toolitem;
+}
+
+
+/**
+ * widget factory for creation of toolbar item widgets for the toolbox
+ *
+ * \param itemid the id of the widget
+ * \return gtk tool item widget
+ */
+static GtkToolItem *
+make_toolbox_item(nsgtk_toolbar_button itemid, bool bar)
{
- GtkImage *image;
+ GtkToolItem *toolitem = NULL;
+
+ switch(itemid) {
+#define TOOLBAR_ITEM_y(identifier, label, iconame)
+#define TOOLBAR_ITEM_n(identifier, label, iconame)
+#define TOOLBAR_ITEM_t(identifier, label, iconame) \
+ case identifier: \
+ if (bar) { \
+ toolitem = make_toolbar_item_button(#label, iconame, true, true); \
+ } \
+ break;
+#define TOOLBAR_ITEM_b(identifier, label, iconame) \
+ case identifier: \
+ toolitem = make_toolbar_item_button(#label, iconame, true, true); \
+ break;
+#define TOOLBAR_ITEM(identifier, name, snstvty, clicked, activate, label, iconame) \
+ TOOLBAR_ITEM_ ## clicked(identifier, label, iconame)
+
+#include "gtk/toolbar_items.h"
- switch (tbbutton) {
+#undef TOOLBAR_ITEM_t
+#undef TOOLBAR_ITEM_b
+#undef TOOLBAR_ITEM_n
+#undef TOOLBAR_ITEM_y
+#undef TOOLBAR_ITEM
+
+ case HISTORY_BUTTON:
+ toolitem = make_toolbar_item_history(true, true);
+ break;
- case (SEARCH_BACK_BUTTON):
- image = GTK_IMAGE(nsgtk_image_new_from_stock(
- NSGTK_STOCK_GO_BACK, iconsize));
+ case URL_BAR_ITEM:
+ toolitem = make_toolbar_item_url_bar(false, true);
break;
- case (SEARCH_FORWARD_BUTTON):
- image = GTK_IMAGE(nsgtk_image_new_from_stock(
- NSGTK_STOCK_GO_FORWARD, iconsize));
+ case THROBBER_ITEM:
+ toolitem = make_toolbar_item_throbber(true, true);
break;
- case (SEARCH_CLOSE_BUTTON):
- image = GTK_IMAGE(nsgtk_image_new_from_stock(
- NSGTK_STOCK_CLOSE, iconsize));
+ case WEBSEARCH_ITEM:
+ toolitem = make_toolbar_item_websearch(false, true);
break;
default:
- image = NULL;
+ break;
+
}
+ return toolitem;
+}
+
+
+/**
+ * target entry for drag source
+ */
+static GtkTargetEntry target_entry = {
+ (char *)"nsgtk_button_data",
+ GTK_TARGET_SAME_APP,
+ 0
+};
+
- if (usedef && (image == NULL)) {
- image = GTK_IMAGE(nsgtk_image_new_from_stock(
- "gtk-missing-image", iconsize));
+/**
+ * find the toolbar item with a given location.
+ *
+ * \param tb the toolbar instance
+ * \param locaction the location to search for
+ * \return the item id for a location
+ */
+static nsgtk_toolbar_button
+itemid_from_location(struct nsgtk_toolbar *tb, int location)
+{
+ int iidx;
+ for (iidx = BACK_BUTTON; iidx < PLACEHOLDER_BUTTON; iidx++) {
+ if (tb->items[iidx].location == location) {
+ break;
+ }
}
+ return iidx;
+}
+
- return image;
+/**
+ * save toolbar settings to file
+ */
+static nserror
+nsgtk_toolbar_customisation_save(struct nsgtk_toolbar *tb)
+{
+ int iidx; /* item index */
+ char *order; /* item ordering */
+ char *start; /* start of next item name to be output */
+ int orderlen = 0; /* length of item ordering */
+ nsgtk_toolbar_button itemid;
+ int location;
+ char *choices = NULL;
+
+ for (iidx = BACK_BUTTON; iidx < PLACEHOLDER_BUTTON; iidx++) {
+ if (tb->items[iidx].location != INACTIVE_LOCATION) {
+ orderlen += strlen(tb->items[iidx].name);
+ orderlen++; /* allow for separator */
+ }
+ }
+
+ /* ensure there are some items to store */
+ if (orderlen == 0) {
+ return NSERROR_INVALID;
+ }
+
+ order = malloc(orderlen);
+ if (order == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ start = order;
+
+ for (location = BACK_BUTTON;
+ location < PLACEHOLDER_BUTTON;
+ location++) {
+ int written;
+ itemid = itemid_from_location(tb, location);
+ if (itemid == PLACEHOLDER_BUTTON) {
+ /* no more filled locations */
+ break;
+ }
+ written = snprintf(start,
+ orderlen - (start - order),
+ "%s/",
+ tb->items[itemid].name);
+ if ((written < 0) ||
+ (written >= orderlen - (start - order))) {
+ free(order);
+ return NSERROR_UNKNOWN;
+ }
+ start += written;
+
+ if ((start - order) >= orderlen) {
+ break;
+ }
+ }
+
+ order[orderlen - 1] = 0;
+
+ nsoption_set_charp(toolbar_items, order);
+
+ /* ensure choices are saved */
+ netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices");
+ if (choices != NULL) {
+ nsoption_write(choices, NULL, NULL);
+ free(choices);
+ }
+
+ return NSERROR_OK;
}
+
/**
- * initialise a theme structure with gtk images
+ * connect signals to a toolbar item in a customisation toolbar
*
- * \param iconsize The size of icon to load
- * \param usedef use the default gtk icon if unset
+ * \param tb The toolbar
+ * \param itemid The item id within to toolbar to connect
+ * \param NSERROR_OK on success
*/
-static struct nsgtk_theme *nsgtk_theme_load(GtkIconSize iconsize, bool usedef)
+static nserror
+toolbar_item_connect_signals(struct nsgtk_toolbar *tb, int itemid)
{
- struct nsgtk_theme *theme;
- int btnloop;
+ /* set toolbar items to be a drag source */
+ gtk_tool_item_set_use_drag_window(tb->items[itemid].button, TRUE);
+ gtk_drag_source_set(GTK_WIDGET(tb->items[itemid].button),
+ GDK_BUTTON1_MASK,
+ &target_entry,
+ 1,
+ GDK_ACTION_COPY);
+ g_signal_connect(tb->items[itemid].button,
+ "drag-data-get",
+ G_CALLBACK(tb->items[itemid].dataminus),
+ tb);
+ return NSERROR_OK;
+}
- theme = malloc(sizeof(struct nsgtk_theme));
- if (theme == NULL) {
- return NULL;
+
+/**
+ * customisation container handler for drag drop signal
+ *
+ * called when a widget is dropped onto the store window
+ */
+static gboolean
+customisation_container_drag_drop_cb(GtkWidget *widget,
+ GdkDragContext *gdc,
+ gint x, gint y,
+ guint time,
+ gpointer data)
+{
+ struct nsgtk_toolbar_customisation *tbc;
+ tbc = (struct nsgtk_toolbar_customisation *)data;
+ int location;
+ int itemid;
+
+ if ((tbc->dragfrom) || (tbc->dragitem == -1)) {
+ tbc->dragitem = -1;
+ return FALSE;
}
- for (btnloop = BACK_BUTTON;
- btnloop < PLACEHOLDER_BUTTON ;
- btnloop++) {
- theme->image[btnloop] = nsgtk_theme_image_default(btnloop,
- iconsize,
- usedef);
+ if (tbc->toolbar.items[tbc->dragitem].location == INACTIVE_LOCATION) {
+ tbc->dragitem = -1;
+ gtk_drag_finish(gdc, TRUE, TRUE, time);
+ return FALSE;
+
}
- for (btnloop = SEARCH_BACK_BUTTON;
- btnloop < SEARCH_BUTTONS_COUNT;
- btnloop++) {
- theme->searchimage[btnloop] =
- nsgtk_theme_searchimage_default(btnloop,
- iconsize,
- usedef);
+ /* update the locations for all the subsequent toolbar items */
+ for (location = tbc->toolbar.items[tbc->dragitem].location;
+ location < PLACEHOLDER_BUTTON;
+ location++) {
+ itemid = itemid_from_location(&tbc->toolbar, location);
+ if (itemid == PLACEHOLDER_BUTTON) {
+ break;
+ }
+ tbc->toolbar.items[itemid].location--;
}
- return theme;
-}
+ /* remove existing item */
+ tbc->toolbar.items[tbc->dragitem].location = -1;
+ gtk_container_remove(GTK_CONTAINER(tbc->toolbar.widget),
+ GTK_WIDGET(tbc->toolbar.items[tbc->dragitem].button));
+
+ tbc->dragitem = -1;
+ gtk_drag_finish(gdc, TRUE, TRUE, time);
+ return FALSE;
+}
-/* exported function documented in gtk/toolbar.h */
-void nsgtk_theme_implement(struct nsgtk_scaffolding *g)
+/**
+ * customisation container handler for drag motion signal
+ *
+ * called when hovering above the store
+ */
+static gboolean
+customisation_container_drag_motion_cb(GtkWidget *widget,
+ GdkDragContext *gdc,
+ gint x, gint y,
+ guint time,
+ gpointer data)
{
- struct nsgtk_theme *theme[IMAGE_SET_COUNT];
- int i;
- struct nsgtk_button_connect *button;
- struct gtk_search *search;
+ return FALSE;
+}
- theme[IMAGE_SET_MAIN_MENU] = nsgtk_theme_load(GTK_ICON_SIZE_MENU, false);
- theme[IMAGE_SET_RCLICK_MENU] = nsgtk_theme_load(GTK_ICON_SIZE_MENU, false);
- theme[IMAGE_SET_POPUP_MENU] = nsgtk_theme_load(GTK_ICON_SIZE_MENU, false);
- theme[IMAGE_SET_BUTTONS] = nsgtk_theme_load(GTK_ICON_SIZE_LARGE_TOOLBAR, false);
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- if ((i == URL_BAR_ITEM) || (i == THROBBER_ITEM) ||
- (i == WEBSEARCH_ITEM))
- continue;
+/**
+ * customisation toolbar handler for drag drop signal
+ *
+ * called when a widget is dropped onto the toolbar
+ */
+static gboolean
+customisation_toolbar_drag_drop_cb(GtkWidget *widget,
+ GdkDragContext *gdc,
+ gint x,
+ gint y,
+ guint time,
+ gpointer data)
+{
+ struct nsgtk_toolbar_customisation *tbc;
+ tbc = (struct nsgtk_toolbar_customisation *)data;
+ gint position; /* drop position in toolbar */
+ int location;
+ int itemid;
+ struct nsgtk_toolbar_item *dragitem; /* toolbar item being dragged */
+
+ position = gtk_toolbar_get_drop_index(tbc->toolbar.widget, x, y);
+ if (tbc->dragitem == -1) {
+ return TRUE;
+ }
- button = nsgtk_scaffolding_button(g, i);
- if (button == NULL)
- continue;
+ /* pure conveiance variable */
+ dragitem = &tbc->toolbar.items[tbc->dragitem];
- /* gtk_image_menu_item_set_image accepts NULL image */
- if ((button->main != NULL) &&
- (theme[IMAGE_SET_MAIN_MENU] != NULL)) {
- nsgtk_image_menu_item_set_image(
- GTK_WIDGET(button->main),
- GTK_WIDGET(theme[IMAGE_SET_MAIN_MENU]->image[i]));
- gtk_widget_show_all(GTK_WIDGET(button->main));
+ /* deal with replacing existing item in toolbar */
+ if (dragitem->location != INACTIVE_LOCATION) {
+ if (dragitem->location < position) {
+ position--;
}
- if ((button->rclick != NULL) &&
- (theme[IMAGE_SET_RCLICK_MENU] != NULL)) {
- nsgtk_image_menu_item_set_image(GTK_WIDGET(button->rclick),
- GTK_WIDGET(
- theme[IMAGE_SET_RCLICK_MENU]->
- image[i]));
- gtk_widget_show_all(GTK_WIDGET(button->rclick));
+
+ /* update the locations for all the subsequent toolbar items */
+ for (location = dragitem->location;
+ location < PLACEHOLDER_BUTTON;
+ location++) {
+ itemid = itemid_from_location(&tbc->toolbar, location);
+ if (itemid == PLACEHOLDER_BUTTON) {
+ break;
+ }
+ tbc->toolbar.items[itemid].location--;
}
- if ((button->popup != NULL) &&
- (theme[IMAGE_SET_POPUP_MENU] != NULL)) {
- nsgtk_image_menu_item_set_image(GTK_WIDGET(button->popup),
- GTK_WIDGET(
- theme[IMAGE_SET_POPUP_MENU]->
- image[i]));
- gtk_widget_show_all(GTK_WIDGET(button->popup));
+
+ /* remove existing item */
+ dragitem->location = INACTIVE_LOCATION;
+ gtk_container_remove(GTK_CONTAINER(tbc->toolbar.widget),
+ GTK_WIDGET(dragitem->button));
+ }
+
+
+ dragitem->button = make_toolbox_item(tbc->dragitem, true);
+
+ if (dragitem->button == NULL) {
+ nsgtk_warning("NoMemory", 0);
+ return TRUE;
+ }
+
+ /* update locations */
+ for (location = PLACEHOLDER_BUTTON; location >= position; location--) {
+ itemid = itemid_from_location(&tbc->toolbar, location);
+ if (itemid != PLACEHOLDER_BUTTON) {
+ tbc->toolbar.items[itemid].location++;
}
- if ((button->location != -1) && (button->button != NULL) &&
- (theme[IMAGE_SET_BUTTONS] != NULL)) {
- gtk_tool_button_set_icon_widget(
- GTK_TOOL_BUTTON(button->button),
- GTK_WIDGET(
- theme[IMAGE_SET_BUTTONS]->
- image[i]));
- gtk_widget_show_all(GTK_WIDGET(button->button));
+ }
+ dragitem->location = position;
+
+ gtk_toolbar_insert(tbc->toolbar.widget,
+ dragitem->button,
+ dragitem->location);
+
+ toolbar_item_connect_signals(&tbc->toolbar, tbc->dragitem);
+ gtk_widget_show_all(GTK_WIDGET(dragitem->button));
+ tbc->dragitem = -1;
+ return TRUE;
+}
+
+
+/**
+ * customisation toolbar handler for drag data received signal
+ *
+ * connected to toolbutton drop; perhaps one day it'll work properly
+ * so it may replace the global current_button
+ */
+static gboolean
+customisation_toolbar_drag_data_received_cb(GtkWidget *widget,
+ GdkDragContext *gdc,
+ gint x,
+ gint y,
+ GtkSelectionData *selection,
+ guint info,
+ guint time,
+ gpointer data)
+{
+ return FALSE;
+}
+
+
+/**
+ * customisation toolbar handler for drag motion signal
+ *
+ * called when hovering an item above the toolbar
+ */
+static gboolean
+customisation_toolbar_drag_motion_cb(GtkWidget *widget,
+ GdkDragContext *gdc,
+ gint x,
+ gint y,
+ guint time,
+ gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ GtkToolItem *item;
+ gint position; /* position in toolbar */
+
+ item = gtk_tool_button_new(NULL, NULL);
+ position = gtk_toolbar_get_drop_index(tb->widget, x, y);
+
+ gtk_toolbar_set_drop_highlight_item(tb->widget, item, position);
+
+ return FALSE; /* drag not in drop zone */
+}
+
+
+/**
+ * customisation toolbar handler for drag leave signal
+ *
+ * called when hovering stops
+ */
+static void
+customisation_toolbar_drag_leave_cb(GtkWidget *widget,
+ GdkDragContext *gdc,
+ guint time,
+ gpointer data)
+{
+ gtk_toolbar_set_drop_highlight_item(GTK_TOOLBAR(widget), NULL, 0);
+}
+
+
+/**
+ * create a new browser window
+ *
+ * creates a browser window with default url depending on user choices.
+ *
+ * \param bw The browser window to pass for existing window/
+ * \param intab true if the new window should be in a tab else false
+ * for new window.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsgtk_browser_window_create(struct browser_window *bw, bool intab)
+{
+ nserror res = NSERROR_OK;
+ nsurl *url = NULL;
+ int flags = BW_CREATE_HISTORY | BW_CREATE_FOREGROUND | BW_CREATE_FOCUS_LOCATION;
+
+ if (intab) {
+ flags |= BW_CREATE_TAB;
+ }
+
+ if (!nsoption_bool(new_blank)) {
+ const char *addr;
+ if (nsoption_charp(homepage_url) != NULL) {
+ addr = nsoption_charp(homepage_url);
+ } else {
+ addr = NETSURF_HOMEPAGE;
}
+ res = nsurl_create(addr, &url);
+ }
+
+ if (res == NSERROR_OK) {
+ res = browser_window_create(flags, url, NULL, bw, NULL);
+ }
+
+ if (url != NULL) {
+ nsurl_unref(url);
+ }
+
+ return res;
+}
+
+
+/**
+ * Apply the user toolbar button settings from configuration
+ *
+ * GTK specific user option string is a set of fields arranged as
+ * [itemreference];[itemlocation]|[itemreference];[itemlocation]| etc
+ *
+ * \param tb The toolbar to apply customisation to
+ * \param NSERROR_OK on success else error code.
+ */
+static nserror
+apply_user_button_customisation(struct nsgtk_toolbar *tb)
+{
+ const char *tbitems; /* item order user config */
+ const char *start;
+ const char *end;
+ int iidx; /* item index */
+ int location = 0; /* location index */
+
+ /* set all button locations to inactive */
+ for (iidx = BACK_BUTTON; iidx < PLACEHOLDER_BUTTON; iidx++) {
+ tb->items[iidx].location = INACTIVE_LOCATION;
}
- /* set search bar images */
- search = nsgtk_scaffolding_search(g);
- if ((search != NULL) && (theme[IMAGE_SET_MAIN_MENU] != NULL)) {
- /* gtk_tool_button_set_icon_widget accepts NULL image */
- if (search->buttons[SEARCH_BACK_BUTTON] != NULL) {
- gtk_tool_button_set_icon_widget(
- search->buttons[SEARCH_BACK_BUTTON],
- GTK_WIDGET(theme[IMAGE_SET_MAIN_MENU]->
- searchimage[SEARCH_BACK_BUTTON]));
- gtk_widget_show_all(GTK_WIDGET(
- search->buttons[SEARCH_BACK_BUTTON]));
+ tbitems = nsoption_charp(toolbar_items);
+ if (tbitems == NULL) {
+ tbitems = "";
+ }
+
+ end = tbitems;
+ while (*end != 0) {
+ start = end;
+ while ((*end != 0) && (*end !='/')) {
+ end++;
}
- if (search->buttons[SEARCH_FORWARD_BUTTON] != NULL) {
- gtk_tool_button_set_icon_widget(
- search->buttons[SEARCH_FORWARD_BUTTON],
- GTK_WIDGET(theme[IMAGE_SET_MAIN_MENU]->
- searchimage[SEARCH_FORWARD_BUTTON]));
- gtk_widget_show_all(GTK_WIDGET(
- search->buttons[
- SEARCH_FORWARD_BUTTON]));
+
+ for (iidx = BACK_BUTTON; iidx < PLACEHOLDER_BUTTON; iidx++) {
+ if (((ssize_t)strlen(tb->items[iidx].name) == (end - start)) &&
+ (strncmp(tb->items[iidx].name, start, end - start) == 0)) {
+ tb->items[iidx].location = location++;
+ break;
+ }
}
- if (search->buttons[SEARCH_CLOSE_BUTTON] != NULL) {
- gtk_tool_button_set_icon_widget(
- search->buttons[SEARCH_CLOSE_BUTTON],
- GTK_WIDGET(theme[IMAGE_SET_MAIN_MENU]->
- searchimage[SEARCH_CLOSE_BUTTON]));
- gtk_widget_show_all(GTK_WIDGET(
- search->buttons[SEARCH_CLOSE_BUTTON]));
+
+ if (*end == '/') {
+ end++;
}
}
- for (i = 0; i < IMAGE_SET_COUNT; i++) {
- if (theme[i] != NULL) {
- free(theme[i]);
- }
+ if (location == 0) {
+ /* completely failed to create any buttons so use defaults */
+ tb->items[BACK_BUTTON].location = location++;
+ tb->items[HISTORY_BUTTON].location = location++;
+ tb->items[FORWARD_BUTTON].location = location++;
+ tb->items[RELOADSTOP_BUTTON].location = location++;
+ tb->items[URL_BAR_ITEM].location = location++;
+ tb->items[WEBSEARCH_ITEM].location = location++;
+ tb->items[OPENMENU_BUTTON].location = location++;
+ tb->items[THROBBER_ITEM].location = location++;
}
+
+
+ return NSERROR_OK;
}
/**
- * callback function to iterate toolbar's widgets
+ * callback function to remove a widget from a container
*/
-static void nsgtk_toolbar_clear_toolbar(GtkWidget *widget, gpointer data)
+static void container_remove_widget(GtkWidget *widget, gpointer data)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- gtk_container_remove(GTK_CONTAINER(nsgtk_scaffolding_toolbar(g)),
- widget);
+ GtkContainer *container = GTK_CONTAINER(data);
+ gtk_container_remove(container, widget);
}
+
/**
- * connect temporary handler for toolbar edit events
+ * populates a toolbar with widgets in correct order
*
- * \param g The scaffolding
- * \param bi The button index
+ * \param tb toolbar
+ * \return NSERROR_OK on success else error code.
*/
-static void nsgtk_toolbar_temp_connect(struct nsgtk_scaffolding *g,
- nsgtk_toolbar_button bi)
+static nserror populate_gtk_toolbar_widget(struct nsgtk_toolbar *tb)
{
- struct nsgtk_button_connect *bc;
+ int location; /* location index */
+ int itemid;
+
+ /* clear the toolbar container of all widgets */
+ gtk_container_foreach(GTK_CONTAINER(tb->widget),
+ container_remove_widget,
+ tb->widget);
+
+ /* add widgets to toolbar */
+ for (location = 0; location < PLACEHOLDER_BUTTON; location++) {
+ itemid = itemid_from_location(tb, location);
+ if (itemid == PLACEHOLDER_BUTTON) {
+ break;
+ }
+ tb->items[itemid].button =
+ make_toolbar_item(itemid,
+ tb->items[itemid].sensitivity);
+
+ gtk_toolbar_insert(tb->widget,
+ tb->items[itemid].button,
+ location);
+ }
- if (bi != URL_BAR_ITEM) {
- bc = nsgtk_scaffolding_button(g, bi);
- if ((bc->button != NULL) && (bc->dataminus != NULL)) {
- g_signal_connect(bc->button,
- "drag-data-get",
- G_CALLBACK(bc->dataminus),
- g);
+ gtk_widget_show_all(GTK_WIDGET(tb->widget));
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * populates the customization toolbar with widgets in correct order
+ *
+ * \param tb toolbar
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror customisation_toolbar_populate(struct nsgtk_toolbar *tb)
+{
+ int location; /* location index */
+ int itemid;
+
+ /* clear the toolbar container of all widgets */
+ gtk_container_foreach(GTK_CONTAINER(tb->widget),
+ container_remove_widget,
+ tb->widget);
+
+ /* add widgets to toolbar */
+ for (location = 0; location < PLACEHOLDER_BUTTON; location++) {
+ itemid = itemid_from_location(tb, location);
+ if (itemid == PLACEHOLDER_BUTTON) {
+ break;
}
+ tb->items[itemid].button = make_toolbox_item(itemid, true);
+
+ gtk_toolbar_insert(tb->widget,
+ tb->items[itemid].button,
+ location);
}
+
+ gtk_widget_show_all(GTK_WIDGET(tb->widget));
+
+ return NSERROR_OK;
}
+
/**
- * get scaffolding button index of button at location
+ * find the toolbar item with a given gtk widget.
*
- * \return toolbar item id from location when there is an item at that logical
- * location; else -1
+ * \param tb the toolbar instance
+ * \param toolitem the tool item widget to search for
+ * \return the item id matching the widget
*/
static nsgtk_toolbar_button
-nsgtk_toolbar_get_id_at_location(struct nsgtk_scaffolding *g, int i)
+itemid_from_gtktoolitem(struct nsgtk_toolbar *tb, GtkToolItem *toolitem)
{
- int q;
- for (q = BACK_BUTTON; q < PLACEHOLDER_BUTTON; q++) {
- if (nsgtk_scaffolding_button(g, q)->location == i) {
- return q;
+ int iidx;
+ for (iidx = BACK_BUTTON; iidx < PLACEHOLDER_BUTTON; iidx++) {
+ if ((tb->items[iidx].location != INACTIVE_LOCATION) &&
+ (tb->items[iidx].button == toolitem)) {
+ break;
}
}
- return -1;
+ return iidx;
}
+
/**
- * widget factory for creation of toolbar item widgets
- * \param g the reference scaffolding
- * \param i the id of the widget
- * \param theme the theme to make the widgets from
+ * set a toolbar items sensitivity
+ *
+ * note this does not set menu items sensitivity
*/
-static GtkWidget *
-nsgtk_toolbar_make_widget(struct nsgtk_scaffolding *g,
- nsgtk_toolbar_button i,
- struct nsgtk_theme *theme)
-{
- GtkWidget *w = NULL;
-
- switch(i) {
-
-/* gtk_tool_button_new() accepts NULL args */
-#define MAKE_STOCKBUTTON(p, q) \
- case p##_BUTTON: { \
- GtkStockItem item; \
- char *label = NULL; \
- if (nsgtk_stock_lookup(q, &item) && \
- (item.label != NULL) && \
- ((label = remove_underscores(item.label, false)) != NULL)) { \
- w = GTK_WIDGET(gtk_tool_button_new(GTK_WIDGET( \
- theme->image[p##_BUTTON]), label)); \
- free(label); \
- } else { \
- w = GTK_WIDGET(gtk_tool_button_new(GTK_WIDGET( \
- theme->image[p##_BUTTON]), q)); \
- } \
- break; \
+static nserror
+set_item_sensitivity(struct nsgtk_toolbar_item *item, bool sensitivity)
+{
+ if (item->sensitivity != sensitivity) {
+ /* item requires sensitivity changing */
+ item->sensitivity = sensitivity;
+
+ if ((item->location != -1) && (item->button != NULL)) {
+ gtk_widget_set_sensitive(GTK_WIDGET(item->button),
+ item->sensitivity);
+ }
}
- MAKE_STOCKBUTTON(HOME, NSGTK_STOCK_HOME)
- MAKE_STOCKBUTTON(BACK, NSGTK_STOCK_GO_BACK)
- MAKE_STOCKBUTTON(FORWARD, NSGTK_STOCK_GO_FORWARD)
- MAKE_STOCKBUTTON(STOP, NSGTK_STOCK_STOP)
- MAKE_STOCKBUTTON(RELOAD, NSGTK_STOCK_REFRESH)
-#undef MAKE_STOCKBUTTON
+ return NSERROR_OK;
+}
- case HISTORY_BUTTON:
- w = GTK_WIDGET(gtk_tool_button_new(GTK_WIDGET(
- theme->image[HISTORY_BUTTON]), "H"));
- break;
- case URL_BAR_ITEM: {
- GtkWidget *entry = nsgtk_entry_new();
- w = GTK_WIDGET(gtk_tool_item_new());
+/**
+ * set an item to its alternative action
+ *
+ * this is currently only used for the stop/reload button where we
+ * also reuse the item sensitivity for the state indicator.
+ *
+ * \param tb the toolbar instance
+ */
+static nserror set_item_action(struct nsgtk_toolbar *tb, int itemid, bool alt)
+{
+ const char *iconname;
+ char *label = NULL;
+
+ if (itemid != RELOADSTOP_BUTTON) {
+ return NSERROR_INVALID;
+ }
+ if (tb->items[itemid].location == -1) {
+ return NSERROR_OK;
+ }
+ tb->items[itemid].sensitivity = alt;
- if ((entry == NULL) || (w == NULL)) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- return NULL;
- }
+ if (tb->items[itemid].button == NULL) {
+ return NSERROR_INVALID;
+ }
- nsgtk_entry_set_icon_from_pixbuf(entry,
- GTK_ENTRY_ICON_PRIMARY,
- favicon_pixbuf);
+ if (tb->items[itemid].sensitivity) {
+ iconname = NSGTK_STOCK_REFRESH;
+ label = remove_underscores(messages_get("Reload"), false);
+
+ } else {
+ iconname = NSGTK_STOCK_STOP;
+ label = remove_underscores(messages_get("gtkStop"), false);
- gtk_container_add(GTK_CONTAINER(w), entry);
- gtk_tool_item_set_expand(GTK_TOOL_ITEM(w), TRUE);
- break;
}
+ gtk_tool_button_set_label(GTK_TOOL_BUTTON(tb->items[itemid].button),
+ label);
- case THROBBER_ITEM: {
- if ((nsgtk_throbber == NULL) ||
- (nsgtk_throbber->framedata == NULL) ||
- (nsgtk_throbber->framedata[0] == NULL)) {
- return NULL;
+ gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(tb->items[itemid].button),
+ iconname);
+
+ gtk_widget_set_sensitive(GTK_WIDGET(tb->items[itemid].button), TRUE);
+
+ if (label != NULL) {
+ free(label);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * cause the toolbar browsing context to navigate to a new url.
+ *
+ * \param tb the toolbar context.
+ * \param urltxt The url string.
+ * \return NSERROR_OK on success else appropriate error code.
+ */
+static nserror
+toolbar_navigate_to_url(struct nsgtk_toolbar *tb, const char *urltxt)
+{
+ struct browser_window *bw;
+ nsurl *url;
+ nserror res;
+
+ res = nsurl_create(urltxt, &url);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ res = browser_window_navigate(bw,
+ url,
+ NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+
+ return res;
+}
+
+
+/**
+ * run a gtk file chooser as a save dialog to obtain a path
+ */
+static nserror
+nsgtk_saveas_dialog(struct browser_window *bw,
+ const char *title,
+ GtkWindow *parent,
+ bool folder,
+ gchar **path_out)
+{
+ nserror res;
+ GtkWidget *fc; /* file chooser widget */
+ GtkFileChooserAction action;
+ char *path; /* proposed path */
+
+ if (!browser_window_has_content(bw)) {
+ /* cannot save a page with no content */
+ return NSERROR_INVALID;
+ }
+
+ if (folder) {
+ action = GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER;
+ } else {
+ action = GTK_FILE_CHOOSER_ACTION_SAVE;
+ }
+
+ fc = gtk_file_chooser_dialog_new(title,
+ parent,
+ action,
+ NSGTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ NSGTK_STOCK_SAVE,
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ /* set a default file name */
+ res = nsurl_nice(browser_window_access_url(bw), &path, false);
+ if (res != NSERROR_OK) {
+ path = strdup(messages_get("SaveText"));
+ if (path == NULL) {
+ gtk_widget_destroy(fc);
+ return NSERROR_NOMEM;
}
+ }
- if (edit_mode) {
- w = GTK_WIDGET(gtk_tool_button_new(GTK_WIDGET(
- gtk_image_new_from_pixbuf(
- nsgtk_throbber->framedata[0])),
- "[throbber]"));
- } else {
- GtkWidget *image;
+ if ((!folder) || (access(path, F_OK) != 0)) {
+ gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(fc), path);
+ }
+ free(path);
- w = GTK_WIDGET(gtk_tool_item_new());
+ /* confirm overwriting */
+ gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(fc), TRUE);
- image = gtk_image_new_from_pixbuf(nsgtk_throbber->framedata[0]);
- if (image != NULL) {
- nsgtk_widget_set_alignment(image,
- GTK_ALIGN_CENTER,
- GTK_ALIGN_CENTER);
- nsgtk_widget_set_margins(image, 3, 0);
+ /* run the dialog to let user select path */
+ if (gtk_dialog_run(GTK_DIALOG(fc)) != GTK_RESPONSE_ACCEPT) {
+ gtk_widget_destroy(fc);
+ return NSERROR_NOT_FOUND;
+ }
- gtk_container_add(GTK_CONTAINER(w), image);
- }
+ *path_out = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fc));
+
+ gtk_widget_destroy(fc);
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * connect all signals to widgets in a customisation
+ */
+static nserror
+toolbar_customisation_connect_signals(struct nsgtk_toolbar *tb)
+{
+ int iidx;
+
+ for (iidx = BACK_BUTTON; iidx < PLACEHOLDER_BUTTON; iidx++) {
+ /* skip inactive items in toolbar */
+ if (tb->items[iidx].location != INACTIVE_LOCATION) {
+ toolbar_item_connect_signals(tb, iidx);
}
- break;
}
- case WEBSEARCH_ITEM: {
- if (edit_mode)
- return GTK_WIDGET(gtk_tool_button_new(GTK_WIDGET(
- nsgtk_image_new_from_stock(NSGTK_STOCK_FIND,
- GTK_ICON_SIZE_LARGE_TOOLBAR)),
- "[websearch]"));
+ /* add move button listeners */
+ g_signal_connect(tb->widget,
+ "drag-drop",
+ G_CALLBACK(customisation_toolbar_drag_drop_cb),
+ tb);
+ g_signal_connect(tb->widget,
+ "drag-data-received",
+ G_CALLBACK(customisation_toolbar_drag_data_received_cb),
+ tb);
+ g_signal_connect(tb->widget,
+ "drag-motion",
+ G_CALLBACK(customisation_toolbar_drag_motion_cb),
+ tb);
+ g_signal_connect(tb->widget,
+ "drag-leave",
+ G_CALLBACK(customisation_toolbar_drag_leave_cb),
+ tb);
+
+ /* set data types */
+ gtk_drag_dest_set(GTK_WIDGET(tb->widget),
+ GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
+ &target_entry,
+ 1,
+ GDK_ACTION_COPY);
+
+ return NSERROR_OK;
+}
+
+
+static void
+item_size_allocate_cb(GtkWidget *widget,
+ GdkRectangle *alloc,
+ gpointer user_data)
+{
+ if (alloc->width > NSGTK_BUTTON_WIDTH) {
+ alloc->width = NSGTK_BUTTON_WIDTH;
+ }
+ if (alloc->height > NSGTK_BUTTON_HEIGHT) {
+ alloc->height = NSGTK_BUTTON_HEIGHT;
+ }
+ gtk_widget_set_allocation(widget, alloc);
+}
+
- GtkWidget *entry = nsgtk_entry_new();
+/**
+ * add a row to a toolbar customisation toolbox
+ *
+ * \param tbc The toolbar customisation context
+ * \param startitem The item index of the beginning of the row
+ * \param enditem The item index of the beginning of the next row
+ * \return NSERROR_OK on successs else error
+ */
+static nserror
+add_toolbox_row(struct nsgtk_toolbar_customisation *tbc,
+ int startitem,
+ int enditem)
+{
+ GtkToolbar *rowbar;
+ int iidx;
- w = GTK_WIDGET(gtk_tool_item_new());
+ rowbar = GTK_TOOLBAR(gtk_toolbar_new());
+ if (rowbar == NULL) {
+ return NSERROR_NOMEM;
+ }
- if ((entry == NULL) || (w == NULL)) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- return NULL;
+ gtk_toolbar_set_style(rowbar, GTK_TOOLBAR_BOTH);
+ gtk_toolbar_set_icon_size(rowbar, GTK_ICON_SIZE_LARGE_TOOLBAR);
+ gtk_box_pack_start(tbc->toolbox, GTK_WIDGET(rowbar), FALSE, FALSE, 0);
+
+ for (iidx = startitem; iidx < enditem; iidx++) {
+ if (tbc->items[iidx] == NULL) {
+ /* skip any widgets that failed to initialise */
+ continue;
}
+ gtk_widget_set_size_request(GTK_WIDGET(tbc->items[iidx]),
+ NSGTK_BUTTON_WIDTH,
+ NSGTK_BUTTON_HEIGHT);
+ gtk_tool_item_set_use_drag_window(tbc->items[iidx], TRUE);
+ gtk_drag_source_set(GTK_WIDGET(tbc->items[iidx]),
+ GDK_BUTTON1_MASK,
+ &target_entry,
+ 1,
+ GDK_ACTION_COPY);
+ g_signal_connect(tbc->items[iidx],
+ "drag-data-get",
+ G_CALLBACK(tbc->toolbar.items[iidx].dataplus),
+ &tbc->toolbar);
+ g_signal_connect(tbc->items[iidx],
+ "size-allocate",
+ G_CALLBACK(item_size_allocate_cb),
+ NULL);
+ gtk_toolbar_insert(rowbar, tbc->items[iidx], -1);
+ }
+ return NSERROR_OK;
+}
- gtk_widget_set_size_request(entry, NSGTK_WEBSEARCH_WIDTH, -1);
- nsgtk_entry_set_icon_from_stock(entry, GTK_ENTRY_ICON_PRIMARY,
- NSGTK_STOCK_INFO);
+/**
+ * creates widgets in customisation toolbox
+ *
+ * \param tbc The toolbar customisation context
+ * \param width The width to layout the toolbox to
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+toolbar_customisation_create_toolbox(struct nsgtk_toolbar_customisation *tbc,
+ int width)
+{
+ int columns; /* number of items in a single row */
+ int curcol; /* current column in creation */
+ int iidx; /* item index */
+ int startidx; /* index of item at start of row */
+
+ /* ensure there are a minimum number of items per row */
+ columns = width / NSGTK_BUTTON_WIDTH;
+ if (columns < NSGTK_MIN_STORE_COLUMNS) {
+ columns = NSGTK_MIN_STORE_COLUMNS;
+ }
- gtk_container_add(GTK_CONTAINER(w), entry);
- break;
+ curcol = 0;
+ for (iidx = startidx = BACK_BUTTON; iidx < PLACEHOLDER_BUTTON; iidx++) {
+ if (curcol >= columns) {
+ add_toolbox_row(tbc, startidx, iidx);
+ curcol = 0;
+ startidx = iidx;
+ }
+ tbc->items[iidx] = make_toolbox_item(iidx, false);
+ if (tbc->items[iidx] != NULL) {
+ curcol++;
+ }
+ }
+ if (curcol > 0) {
+ add_toolbox_row(tbc, startidx, iidx);
}
-/* gtk_tool_button_new accepts NULL args */
-#define MAKE_MENUBUTTON(p, q) \
- case p##_BUTTON: { \
- char *label = NULL; \
- label = remove_underscores(messages_get(#q), false); \
- w = GTK_WIDGET(gtk_tool_button_new(GTK_WIDGET( \
- theme->image[p##_BUTTON]), label)); \
- if (label != NULL) \
- free(label); \
- break; \
- }
-
- MAKE_MENUBUTTON(NEWWINDOW, gtkNewWindow)
- MAKE_MENUBUTTON(NEWTAB, gtkNewTab)
- MAKE_MENUBUTTON(OPENFILE, gtkOpenFile)
- MAKE_MENUBUTTON(CLOSETAB, gtkCloseTab)
- MAKE_MENUBUTTON(CLOSEWINDOW, gtkCloseWindow)
- MAKE_MENUBUTTON(SAVEPAGE, gtkSavePage)
- MAKE_MENUBUTTON(PRINTPREVIEW, gtkPrintPreview)
- MAKE_MENUBUTTON(PRINT, gtkPrint)
- MAKE_MENUBUTTON(QUIT, gtkQuitMenu)
- MAKE_MENUBUTTON(CUT, gtkCut)
- MAKE_MENUBUTTON(COPY, gtkCopy)
- MAKE_MENUBUTTON(PASTE, gtkPaste)
- MAKE_MENUBUTTON(DELETE, gtkDelete)
- MAKE_MENUBUTTON(SELECTALL, gtkSelectAll)
- MAKE_MENUBUTTON(PREFERENCES, gtkPreferences)
- MAKE_MENUBUTTON(ZOOMPLUS, gtkZoomPlus)
- MAKE_MENUBUTTON(ZOOMMINUS, gtkZoomMinus)
- MAKE_MENUBUTTON(ZOOMNORMAL, gtkZoomNormal)
- MAKE_MENUBUTTON(FULLSCREEN, gtkFullScreen)
- MAKE_MENUBUTTON(VIEWSOURCE, gtkViewSource)
- MAKE_MENUBUTTON(CONTENTS, gtkContents)
- MAKE_MENUBUTTON(ABOUT, gtkAbout)
- MAKE_MENUBUTTON(PDF, gtkPDF)
- MAKE_MENUBUTTON(PLAINTEXT, gtkPlainText)
- MAKE_MENUBUTTON(DRAWFILE, gtkDrawFile)
- MAKE_MENUBUTTON(POSTSCRIPT, gtkPostScript)
- MAKE_MENUBUTTON(FIND, gtkFind)
- MAKE_MENUBUTTON(DOWNLOADS, gtkDownloads)
- MAKE_MENUBUTTON(SAVEWINDOWSIZE, gtkSaveWindowSize)
- MAKE_MENUBUTTON(TOGGLEDEBUGGING, gtkToggleDebugging)
- MAKE_MENUBUTTON(SAVEBOXTREE, gtkDebugBoxTree)
- MAKE_MENUBUTTON(SAVEDOMTREE, gtkDebugDomTree)
- MAKE_MENUBUTTON(LOCALHISTORY, gtkLocalHistory)
- MAKE_MENUBUTTON(GLOBALHISTORY, gtkGlobalHistory)
- MAKE_MENUBUTTON(ADDBOOKMARKS, gtkAddBookMarks)
- MAKE_MENUBUTTON(SHOWBOOKMARKS, gtkShowBookMarks)
- MAKE_MENUBUTTON(SHOWCOOKIES, gtkShowCookies)
- MAKE_MENUBUTTON(OPENLOCATION, gtkOpenLocation)
- MAKE_MENUBUTTON(NEXTTAB, gtkNextTab)
- MAKE_MENUBUTTON(PREVTAB, gtkPrevTab)
- MAKE_MENUBUTTON(GUIDE, gtkGuide)
- MAKE_MENUBUTTON(INFO, gtkUserInformation)
-#undef MAKE_MENUBUTTON
+ return NSERROR_OK;
+}
- default:
- break;
+/**
+ * update toolbar in customisation to user settings
+ */
+static nserror
+customisation_toolbar_update(struct nsgtk_toolbar_customisation *tbc)
+{
+ nserror res;
+
+ res = apply_user_button_customisation(&tbc->toolbar);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* populate toolbar widget */
+ res = customisation_toolbar_populate(&tbc->toolbar);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* ensure icon sizes and text labels on toolbar are set */
+ res = nsgtk_toolbar_restyle(&tbc->toolbar);
+ if (res != NSERROR_OK) {
+ return res;
}
- return w;
+
+ /* attach handlers to toolbar widgets */
+ res = toolbar_customisation_connect_signals(&tbc->toolbar);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ return NSERROR_OK;
}
+
/**
- * called when a widget is dropped onto the toolbar
+ * customisation apply handler for clicked signal
+ *
+ * when 'save settings' button is clicked
+ */
+static gboolean
+customisation_apply_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar_customisation *tbc;
+ tbc = (struct nsgtk_toolbar_customisation *)data;
+
+ /* save state to file, update toolbars for all windows */
+ nsgtk_toolbar_customisation_save(&tbc->toolbar);
+ nsgtk_window_toolbar_update();
+ gtk_widget_destroy(tbc->container);
+
+ return TRUE;
+}
+
+
+/**
+ * customisation reset handler for clicked signal
+ *
+ * when 'reload defaults' button is clicked
*/
static gboolean
-nsgtk_toolbar_data(GtkWidget *widget,
- GdkDragContext *gdc,
- gint x,
- gint y,
- guint time,
- gpointer data)
-{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- int ind = gtk_toolbar_get_drop_index(nsgtk_scaffolding_toolbar(g),
- x, y);
- int q, i;
- if (window->currentbutton == -1)
+customisation_reset_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar_customisation *tbc;
+ tbc = (struct nsgtk_toolbar_customisation *)data;
+
+ customisation_toolbar_update(tbc);
+
+ return TRUE;
+}
+
+
+/**
+ * customisation container destroy handler
+ */
+static void customisation_container_destroy_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar_customisation *tbc;
+ tbc = (struct nsgtk_toolbar_customisation *)data;
+
+ free(tbc);
+}
+
+/*
+ * Toolbar button clicked handlers
+ */
+
+/**
+ * create a toolbar customisation tab
+ *
+ * this is completely different approach to previous implementation. it
+ * is not modal and the toolbar configuration is performed completely
+ * within the tab. once the user is happy they can apply the change or
+ * cancel as they see fit while continuing to use the browser as usual.
+ */
+static gboolean cutomize_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar_customisation *tbc;
+ nserror res;
+ GtkBuilder *builder;
+ GtkNotebook *notebook; /* notebook containing widget */
+ GtkAllocation notebook_alloc; /* notebook size allocation */
+ int iidx; /* item index */
+
+ /* obtain the notebook being added to */
+ notebook = GTK_NOTEBOOK(gtk_widget_get_ancestor(widget,
+ GTK_TYPE_NOTEBOOK));
+ if (notebook == NULL) {
return TRUE;
- struct nsgtk_theme *theme =
- nsgtk_theme_load(GTK_ICON_SIZE_LARGE_TOOLBAR, false);
- if (theme == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
+ }
+
+ /* create builder */
+ res = nsgtk_builder_new_from_resname("toolbar", &builder);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Toolbar UI builder init failed");
return TRUE;
}
- if (nsgtk_scaffolding_button(g, window->currentbutton)->location
- != -1) {
- /* widget was already in the toolbar; so replace */
- if (nsgtk_scaffolding_button(g, window->currentbutton)->
- location < ind)
- ind--;
- gtk_container_remove(GTK_CONTAINER(
- nsgtk_scaffolding_toolbar(g)), GTK_WIDGET(
- nsgtk_scaffolding_button(g,
- window->currentbutton)->button));
- /* 'move' all widgets further right than the original location,
- * one place to the left in logical schema */
- for (i = nsgtk_scaffolding_button(g, window->currentbutton)->
- location + 1; i < PLACEHOLDER_BUTTON; i++) {
- q = nsgtk_toolbar_get_id_at_location(g, i);
- if (q == -1)
- continue;
- nsgtk_scaffolding_button(g, q)->location--;
- }
- nsgtk_scaffolding_button(g, window->currentbutton)->
- location = -1;
- }
- nsgtk_scaffolding_button(g, window->currentbutton)->button =
- GTK_TOOL_ITEM(nsgtk_toolbar_make_widget(g,
- window->currentbutton, theme));
- free(theme);
- if (nsgtk_scaffolding_button(g, window->currentbutton)->button
- == NULL) {
- nsgtk_warning("NoMemory", 0);
+ gtk_builder_connect_signals(builder, NULL);
+
+ /* create nsgtk_toolbar_customisation which has nsgtk_toolbar
+ * at the front so we can reuse functions that take
+ * nsgtk_toolbar
+ */
+ tbc = calloc(1, sizeof(struct nsgtk_toolbar_customisation));
+ if (tbc == NULL) {
+ g_object_unref(builder);
return TRUE;
}
- /* update logical schema */
- nsgtk_scaffolding_reset_offset(g);
- /* 'move' all widgets further right than the new location, one place to
- * the right in logical schema */
- for (i = PLACEHOLDER_BUTTON - 1; i >= ind; i--) {
- q = nsgtk_toolbar_get_id_at_location(g, i);
- if (q == -1)
- continue;
- nsgtk_scaffolding_button(g, q)->location++;
+
+ /* get container box widget which forms a page of the tabs */
+ tbc->container = GTK_WIDGET(gtk_builder_get_object(builder, "customisation"));
+ if (tbc->container == NULL) {
+ goto cutomize_button_clicked_cb_error;
}
- nsgtk_scaffolding_button(g, window->currentbutton)->location = ind;
- /* complete action */
- GtkToolItem *current_button;
+ /* vertical box for the toolbox to drag items into and out of */
+ tbc->toolbox = GTK_BOX(gtk_builder_get_object(builder, "toolbox"));
+ if (tbc->toolbox == NULL) {
+ goto cutomize_button_clicked_cb_error;
+ }
- current_button = GTK_TOOL_ITEM(nsgtk_scaffolding_button(g, window->currentbutton)->button);
+ /* customisation toolbar container */
+ tbc->toolbar.widget = GTK_TOOLBAR(gtk_builder_get_object(builder, "toolbar"));
+ if (tbc->toolbar.widget == NULL) {
+ goto cutomize_button_clicked_cb_error;
+ }
- gtk_toolbar_insert(nsgtk_scaffolding_toolbar(g), current_button, ind);
+ /* build customisation toolbar */
+ gtk_toolbar_set_show_arrow(tbc->toolbar.widget, TRUE);
- gtk_tool_item_set_use_drag_window(current_button, TRUE);
- gtk_drag_source_set(GTK_WIDGET(current_button),
- GDK_BUTTON1_MASK, &entry, 1,
- GDK_ACTION_COPY);
- nsgtk_toolbar_temp_connect(g, window->currentbutton);
- gtk_widget_show_all(GTK_WIDGET(current_button));
+ for (iidx = BACK_BUTTON; iidx < PLACEHOLDER_BUTTON; iidx++) {
+ res = toolbar_item_create(iidx, &tbc->toolbar.items[iidx]);
+ if (res != NSERROR_OK) {
+ goto cutomize_button_clicked_cb_error;
+ }
+ }
+
+ res = customisation_toolbar_update(tbc);
+ if (res != NSERROR_OK) {
+ goto cutomize_button_clicked_cb_error;
+ }
+
+ /* use toolbox for widgets to drag to/from */
+ gtk_widget_get_allocation(GTK_WIDGET(notebook), &notebook_alloc);
+
+ res = toolbar_customisation_create_toolbox(tbc, notebook_alloc.width);
+ if (res != NSERROR_OK) {
+ goto cutomize_button_clicked_cb_error;
+ }
+
+ /* configure the container */
+ gtk_drag_dest_set(GTK_WIDGET(tbc->container),
+ GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
+ &target_entry,
+ 1,
+ GDK_ACTION_COPY);
+
+ /* discard button calls destroy */
+ g_signal_connect_swapped(GTK_WIDGET(gtk_builder_get_object(builder,
+ "discard")),
+ "clicked",
+ G_CALLBACK(gtk_widget_destroy),
+ tbc->container);
+
+ /* save and update on apply button */
+ g_signal_connect(GTK_WIDGET(gtk_builder_get_object(builder, "apply")),
+ "clicked",
+ G_CALLBACK(customisation_apply_clicked_cb),
+ tbc);
+
+ g_signal_connect(GTK_WIDGET(gtk_builder_get_object(builder, "reset")),
+ "clicked",
+ G_CALLBACK(customisation_reset_clicked_cb),
+ tbc);
+
+ /* close and cleanup on delete signal */
+ g_signal_connect(tbc->container,
+ "destroy",
+ G_CALLBACK(customisation_container_destroy_cb),
+ tbc);
+
+
+ g_signal_connect(tbc->container,
+ "drag-drop",
+ G_CALLBACK(customisation_container_drag_drop_cb),
+ tbc);
+
+ g_signal_connect(tbc->container,
+ "drag-motion",
+ G_CALLBACK(customisation_container_drag_motion_cb),
+ tbc);
- window->currentbutton = -1;
+ nsgtk_tab_add_page(notebook,
+ tbc->container,
+ false,
+ messages_get("gtkCustomizeToolbarTitle"),
+ favicon_pixbuf);
+
+ /* safe to drop the reference to the builder as the container is
+ * referenced by the notebook now.
+ */
+ g_object_unref(builder);
+
+ return TRUE;
+
+ cutomize_button_clicked_cb_error:
+ free(tbc);
+ g_object_unref(builder);
return TRUE;
+
+}
+
+
+/**
+ * callback for all toolbar items widget size allocation
+ *
+ * handler connected to all toolbar items for the size-allocate signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param alloc The size allocation being set.
+ * \param data The toolbar context passed when the signal was connected
+ */
+static void
+toolbar_item_size_allocate_cb(GtkWidget *widget,
+ GtkAllocation *alloc,
+ gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ nsgtk_toolbar_button itemid;
+
+ itemid = itemid_from_gtktoolitem(tb, GTK_TOOL_ITEM(widget));
+
+ if ((tb->toolbarmem == alloc->x) ||
+ (tb->items[itemid].location < tb->items[HISTORY_BUTTON].location)) {
+ /*
+ * no reallocation after first adjustment,
+ * no reallocation for buttons left of history button
+ */
+ return;
+ }
+
+ if (itemid == HISTORY_BUTTON) {
+ if (alloc->width == 20) {
+ return;
+ }
+
+ tb->toolbarbase = alloc->y + alloc->height;
+ tb->historybase = alloc->x + 20;
+ if (tb->offset == 0) {
+ tb->offset = alloc->width - 20;
+ }
+ alloc->width = 20;
+ } else if (tb->items[itemid].location <= tb->items[URL_BAR_ITEM].location) {
+ alloc->x -= tb->offset;
+ if (itemid == URL_BAR_ITEM) {
+ alloc->width += tb->offset;
+ }
+ }
+ tb->toolbarmem = alloc->x;
+
+ gtk_widget_size_allocate(widget, alloc);
}
+
/**
- * connected to toolbutton drop; perhaps one day it'll work properly so it may
- * replace the global current_button
+ * handler for back tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
static gboolean
-nsgtk_toolbar_move_complete(GtkWidget *widget,
- GdkDragContext *gdc,
- gint x,
- gint y,
- GtkSelectionData *selection,
- guint info,
- guint time,
- gpointer data)
+back_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- return FALSE;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ if ((bw != NULL) && browser_window_history_back_available(bw)) {
+ /* clear potential search effects */
+ browser_window_search_clear(bw);
+
+ browser_window_history_back(bw, false);
+
+ set_item_sensitivity(&tb->items[BACK_BUTTON],
+ browser_window_history_back_available(bw));
+ set_item_sensitivity(&tb->items[FORWARD_BUTTON],
+ browser_window_history_forward_available(bw));
+
+ nsgtk_local_history_hide();
+ }
+ return TRUE;
}
+
/**
- * called when hovering an item above the toolbar
+ * handler for forward tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
static gboolean
-nsgtk_toolbar_action(GtkWidget *widget, GdkDragContext *gdc, gint x,
- gint y, guint time, gpointer data)
-{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- GtkToolItem *item = gtk_tool_button_new(NULL, NULL);
- if (item != NULL)
- gtk_toolbar_set_drop_highlight_item(
- nsgtk_scaffolding_toolbar(g),
- GTK_TOOL_ITEM(item),
- gtk_toolbar_get_drop_index(
- nsgtk_scaffolding_toolbar(g), x, y));
- return FALSE;
+forward_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ if ((bw != NULL) && browser_window_history_forward_available(bw)) {
+ /* clear potential search effects */
+ browser_window_search_clear(bw);
+
+ browser_window_history_forward(bw, false);
+
+ set_item_sensitivity(&tb->items[BACK_BUTTON],
+ browser_window_history_back_available(bw));
+ set_item_sensitivity(&tb->items[FORWARD_BUTTON],
+ browser_window_history_forward_available(bw));
+ nsgtk_local_history_hide();
+ }
+ return TRUE;
}
+
/**
- * called when hovering stops
+ * handler for stop tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-static void
-nsgtk_toolbar_clear(GtkWidget *widget, GdkDragContext *gdc, guint time,
- gpointer data)
+static gboolean
+stop_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- gtk_toolbar_set_drop_highlight_item(GTK_TOOLBAR(widget), NULL, 0);
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+
+ browser_window_stop(tb->get_bw(tb->get_ctx));
+
+ return TRUE;
+}
+
+
+/**
+ * handler for reload tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+reload_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ /* clear potential search effects */
+ browser_window_search_clear(bw);
+
+ browser_window_reload(bw, true);
+
+ return TRUE;
+}
+
+
+/**
+ * handler for reload/stop tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+reloadstop_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ /* clear potential search effects */
+ browser_window_search_clear(bw);
+
+ if (tb->items[RELOADSTOP_BUTTON].sensitivity) {
+ browser_window_reload(bw, true);
+ } else {
+ browser_window_stop(tb->get_bw(tb->get_ctx));
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * handler for home tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+home_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ nserror res;
+ const char *addr;
+
+ if (nsoption_charp(homepage_url) != NULL) {
+ addr = nsoption_charp(homepage_url);
+ } else {
+ addr = NETSURF_HOMEPAGE;
+ }
+
+ res = toolbar_navigate_to_url(tb, addr);
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * callback for url entry widget activation
+ *
+ * handler connected to url entry widget for the activate signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE to allow activation.
+ */
+static gboolean url_entry_activate_cb(GtkWidget *widget, gpointer data)
+{
+ nserror res;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ nsurl *url;
+
+ res = search_web_omni(gtk_entry_get_text(GTK_ENTRY(widget)),
+ SEARCH_WEB_OMNI_NONE,
+ &url);
+ if (res == NSERROR_OK) {
+ bw = tb->get_bw(tb->get_ctx);
+ res = browser_window_navigate(
+ bw, url, NULL, BW_NAVIGATE_HISTORY, NULL, NULL, NULL);
+ nsurl_unref(url);
+ }
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * callback for url entry widget changing
+ *
+ * handler connected to url entry widget for the change signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param event The key change event that changed the entry.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE to allow activation.
+ */
+static gboolean
+url_entry_changed_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+ return nsgtk_completion_update(GTK_ENTRY(widget));
}
+
/**
- * add item to toolbar.
+ * callback for url entry widget icon button release
*
- * the function should be called, when multiple items are being added,
- * in ascending order.
+ * handler connected to url entry widget for the icon release signal
*
- * \param g the scaffolding whose toolbar an item is added to.
- * \param i the location in the toolbar.
- * \param theme The theme in use.
+ * \param widget The widget the signal is being delivered to.
+ * \param event The key change event that changed the entry.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE to allow activation.
*/
static void
-nsgtk_toolbar_add_item_to_toolbar(struct nsgtk_scaffolding *g, int i,
- struct nsgtk_theme *theme)
-{
- int q;
- for (q = BACK_BUTTON; q < PLACEHOLDER_BUTTON; q++)
- if (nsgtk_scaffolding_button(g, q)->location == i) {
- nsgtk_scaffolding_button(g, q)->button = GTK_TOOL_ITEM(
- nsgtk_toolbar_make_widget(g, q,
- theme));
- gtk_toolbar_insert(nsgtk_scaffolding_toolbar(g),
- nsgtk_scaffolding_button(g, q)->button,
- i);
- break;
- }
+url_entry_icon_release_cb(GtkEntry *entry,
+ GtkEntryIconPosition icon_pos,
+ GdkEvent *event,
+ gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ nsgtk_page_info(bw);
+}
+
+
+/**
+ * handler for web search tool bar entry item activate signal
+ *
+ * handler connected to web search entry widget for the activate signal
+ *
+ * \todo make this user selectable to switch between opening in new
+ * and navigating current window. Possibly improve core search_web interfaces
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean websearch_entry_activate_cb(GtkWidget *widget, gpointer data)
+{
+ nserror res;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ nsurl *url;
+
+ res = search_web_omni(gtk_entry_get_text(GTK_ENTRY(widget)),
+ SEARCH_WEB_OMNI_SEARCHONLY,
+ &url);
+ if (res == NSERROR_OK) {
+ bw = tb->get_bw(tb->get_ctx);
+
+ res = browser_window_create(
+ BW_CREATE_HISTORY | BW_CREATE_TAB | BW_CREATE_FOREGROUND,
+ url,
+ NULL,
+ bw,
+ NULL);
+ nsurl_unref(url);
+ }
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
+ }
+
+ return TRUE;
}
/**
- * cleanup code physical update of all toolbars; resensitize
- * \param g the 'front' scaffolding that called customize
+ * handler for web search tool bar item button press signal
+ *
+ * allows a click in the websearch entry field to clear the name of the
+ * provider.
+ *
+ * \todo this does not work well, different behaviour wanted perhaps?
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-static void nsgtk_toolbar_close(struct nsgtk_scaffolding *g)
+static gboolean
+websearch_entry_button_press_cb(GtkWidget *widget,
+ GdkEventFocus *f,
+ gpointer data)
{
- int i;
+ gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1);
+ gtk_widget_grab_focus(GTK_WIDGET(widget));
- struct nsgtk_scaffolding *list;
- struct nsgtk_theme *theme;
+ return TRUE;
+}
- list = nsgtk_scaffolding_iterate(NULL);
- while (list) {
- theme = nsgtk_theme_load(GTK_ICON_SIZE_LARGE_TOOLBAR, false);
- if (theme == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- continue;
- }
- /* clear toolbar */
- gtk_container_foreach(GTK_CONTAINER(nsgtk_scaffolding_toolbar(
- list)), nsgtk_toolbar_clear_toolbar, list);
- /* then add items */
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- nsgtk_toolbar_add_item_to_toolbar(list, i, theme);
+
+/**
+ * handler for new window tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+newwindow_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ nserror res;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+
+ res = nsgtk_browser_window_create(tb->get_bw(tb->get_ctx), false);
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * handler for new tab tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+newtab_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ nserror res;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+
+ res = nsgtk_browser_window_create(tb->get_bw(tb->get_ctx), true);
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
+ }
+ return TRUE;
+}
+
+
+/**
+ * handler for open file tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+openfile_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ GtkWidget *dlgOpen;
+ gint response;
+ GtkWidget *toplevel;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ dlgOpen = gtk_file_chooser_dialog_new("Open File",
+ GTK_WINDOW(toplevel),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ NSGTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ NSGTK_STOCK_OPEN, GTK_RESPONSE_OK,
+ NULL, NULL);
+
+ response = gtk_dialog_run(GTK_DIALOG(dlgOpen));
+ if (response == GTK_RESPONSE_OK) {
+ char *urltxt;
+ gchar *filename;
+ nserror res;
+ nsurl *url;
+
+ filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlgOpen));
+
+ urltxt = malloc(strlen(filename) + FILE_SCHEME_PREFIX_LEN + 1);
+ if (urltxt != NULL) {
+ sprintf(urltxt, FILE_SCHEME_PREFIX"%s", filename);
+
+ res = nsurl_create(urltxt, &url);
+ if (res == NSERROR_OK) {
+ bw = tb->get_bw(tb->get_ctx);
+ res = browser_window_navigate(bw,
+ url,
+ NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
+ }
+ free(urltxt);
}
- nsgtk_toolbar_connect_all(list);
- gtk_widget_show_all(GTK_WIDGET(nsgtk_scaffolding_toolbar(
- list)));
- nsgtk_scaffolding_set_sensitivity(list);
- nsgtk_widget_override_background_color(GTK_WIDGET(nsgtk_window_get_layout(nsgtk_scaffolding_top_level(list))), GTK_STATE_NORMAL, 0, 0xFFFF, 0xFFFF, 0xFFFF);
- g_signal_handler_unblock(GTK_WIDGET(
- nsgtk_window_get_layout(
- nsgtk_scaffolding_top_level(list))),
- nsgtk_window_get_signalhandler(
- nsgtk_scaffolding_top_level(list),
- NSGTK_WINDOW_SIGNAL_CLICK));
- g_signal_handler_unblock(GTK_WIDGET(
- nsgtk_window_get_layout(
- nsgtk_scaffolding_top_level(list))),
- nsgtk_window_get_signalhandler(
- nsgtk_scaffolding_top_level(list),
- NSGTK_WINDOW_SIGNAL_REDRAW));
- browser_window_refresh_url_bar(
- nsgtk_get_browser_window(
- nsgtk_scaffolding_top_level(list)));
-
- if (list != g)
- gtk_widget_set_sensitive(GTK_WIDGET(
- nsgtk_scaffolding_window(list)), TRUE);
- free(theme);
- list = nsgtk_scaffolding_iterate(list);
- }
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_notebook(g)),
- TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_menu_bar(g)),
- TRUE);
- /* update favicon etc */
- nsgtk_scaffolding_set_top_level(nsgtk_scaffolding_top_level(g));
-
- search_web_select_provider(-1);
-}
-
-/**
- * when cancel button is clicked
- */
-static gboolean nsgtk_toolbar_cancel_clicked(GtkWidget *widget, gpointer data)
-{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
-
- edit_mode = false;
- /* reset g->buttons->location */
- for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- nsgtk_scaffolding_button(g, i)->location =
- window->buttonlocations[i];
- }
- nsgtk_toolbar_set_physical(g);
- nsgtk_toolbar_connect_all(g);
- nsgtk_toolbar_close(g);
- nsgtk_scaffolding_set_sensitivity(g);
- gtk_widget_destroy(window->window);
+
+
+ g_free(filename);
+ }
+
+ gtk_widget_destroy(dlgOpen);
+
+ return TRUE;
+}
+
+
+/**
+ * handler for close window tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+closewindow_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ GtkWidget *toplevel;
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+ gtk_widget_destroy(toplevel);
return TRUE;
}
+
/**
- * physically add widgets to store window
+ * handler for full save export tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-static bool nsgtk_toolbar_add_store_widget(GtkWidget *widget)
+static gboolean
+savepage_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- if (window->numberh >= NSGTK_STORE_WIDTH) {
- window->currentbar = gtk_toolbar_new();
- if (window->currentbar == NULL) {
- nsgtk_warning("NoMemory", 0);
- return false;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ DIR *d;
+ gchar *path;
+ nserror res;
+ GtkWidget *toplevel;
+
+ bw = tb->get_bw(tb->get_ctx);
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ res = nsgtk_saveas_dialog(bw,
+ messages_get("gtkcompleteSave"),
+ GTK_WINDOW(toplevel),
+ true,
+ &path);
+ if (res != NSERROR_OK) {
+ return FALSE;
+ }
+
+ d = opendir(path);
+ if (d == NULL) {
+ NSLOG(netsurf, INFO,
+ "Unable to open directory %s for complete save: %s",
+ path,
+ strerror(errno));
+ if (errno == ENOTDIR) {
+ nsgtk_warning("NoDirError", path);
+ } else {
+ nsgtk_warning("gtkFileError", path);
}
- gtk_toolbar_set_style(GTK_TOOLBAR(window->currentbar),
- GTK_TOOLBAR_BOTH);
- gtk_toolbar_set_icon_size(GTK_TOOLBAR(window->currentbar),
- GTK_ICON_SIZE_LARGE_TOOLBAR);
- gtk_box_pack_start(GTK_BOX(window->widgetvbox),
- window->currentbar, FALSE, FALSE, 0);
- window->numberh = 0;
+ g_free(path);
+ return TRUE;
}
- gtk_widget_set_size_request(widget, NSGTK_BUTTON_WIDTH,
- NSGTK_BUTTON_HEIGHT);
- gtk_toolbar_insert(GTK_TOOLBAR(window->currentbar), GTK_TOOL_ITEM(
- widget), window->numberh++);
- gtk_tool_item_set_use_drag_window(GTK_TOOL_ITEM(widget), TRUE);
- gtk_drag_source_set(widget, GDK_BUTTON1_MASK, &entry, 1,
- GDK_ACTION_COPY);
- gtk_widget_show_all(window->window);
- return true;
+ closedir(d);
+
+ save_complete(browser_window_get_content(bw), path, NULL);
+ g_free(path);
+
+ return TRUE;
}
/**
- * cast toolbar settings to all scaffoldings referenced from the global linked
- * list of gui_windows
+ * handler for pdf export tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-static void nsgtk_toolbar_cast(struct nsgtk_scaffolding *g)
+static gboolean
+pdf_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- int i;
- struct nsgtk_scaffolding *list;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWidget *toplevel;
+ gchar *filename;
+ nserror res;
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- window->buttonlocations[i] =
- ((nsgtk_scaffolding_button(g, i)->location
- >= -1) &&
- (nsgtk_scaffolding_button(g, i)->location
- < PLACEHOLDER_BUTTON)) ?
- nsgtk_scaffolding_button(g, i)->location : -1;
+ bw = tb->get_bw(tb->get_ctx);
+
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ res = nsgtk_saveas_dialog(bw,
+ "Export to PDF",
+ GTK_WINDOW(toplevel),
+ false,
+ &filename);
+ if (res != NSERROR_OK) {
+ return FALSE;
}
- list = nsgtk_scaffolding_iterate(NULL);
- while (list) {
- if (list != g)
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++)
- nsgtk_scaffolding_button(list, i)->location =
- window->buttonlocations[i];
- list = nsgtk_scaffolding_iterate(list);
+#ifdef WITH_PDF_EXPORT
+ struct print_settings *settings;
+
+ /* this way the scale used by PDF functions is synchronised with that
+ * used by the all-purpose print interface
+ */
+ haru_nsfont_set_scale((float)option_export_scale / 100);
+
+ settings = print_make_settings(PRINT_OPTIONS,
+ (const char *) filename,
+ &haru_nsfont);
+ g_free(filename);
+ if (settings == NULL) {
+ return TRUE;
}
+ /* This will clean up the print_settings object for us */
+ print_basic_run(browser_window_get_content(bw), &pdf_printer, settings);
+#endif
+ return TRUE;
+
}
/**
- * load toolbar settings from file; file is a set of fields arranged as
- * [itemreference];[itemlocation]|[itemreference];[itemlocation]| etc
+ * handler for plain text export tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-void nsgtk_toolbar_customization_load(struct nsgtk_scaffolding *g)
+static gboolean
+plaintext_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- int i, ii;
- char *buffer;
- char *buffer1, *subbuffer, *ptr = NULL, *pter = NULL;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWidget *toplevel;
+ gchar *filename;
+ nserror res;
+
+ bw = tb->get_bw(tb->get_ctx);
- /* default toolbar button order */
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- nsgtk_scaffolding_button(g, i)->location =
- (i <= THROBBER_ITEM) ? i : -1;
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ res = nsgtk_saveas_dialog(bw,
+ messages_get("gtkplainSave"),
+ GTK_WINDOW(toplevel),
+ false,
+ &filename);
+ if (res != NSERROR_OK) {
+ return FALSE;
}
- /* ensure the option is actually set */
- if (nsoption_charp(toolbar_order) == NULL) {
- return;
+
+ save_as_text(browser_window_get_content(bw), filename);
+ g_free(filename);
+
+ return TRUE;
+}
+
+
+/**
+ * handler for print tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+print_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkPrintOperation *print_op;
+ GtkPageSetup *page_setup;
+ GtkPrintSettings *print_settings;
+ GtkPrintOperationResult res = GTK_PRINT_OPERATION_RESULT_ERROR;
+ struct print_settings *nssettings;
+ char *settings_fname = NULL;
+ GtkWidget *toplevel;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ print_op = gtk_print_operation_new();
+ if (print_op == NULL) {
+ nsgtk_warning(messages_get("NoMemory"), 0);
+ return TRUE;
}
- buffer = strdup(nsoption_charp(toolbar_order));
-
- i = BACK_BUTTON;
- ii = BACK_BUTTON;
- buffer1 = strtok_r(buffer, "|", &ptr);
- while (buffer1 != NULL) {
- subbuffer = strtok_r(buffer1, ";", &pter);
- if (subbuffer != NULL) {
- i = atoi(subbuffer);
- subbuffer = strtok_r(NULL, ";", &pter);
- if (subbuffer != NULL) {
- ii = atoi(subbuffer);
- if ((i >= BACK_BUTTON) &&
- (i < PLACEHOLDER_BUTTON) &&
- (ii >= -1) &&
- (ii < PLACEHOLDER_BUTTON)) {
- nsgtk_scaffolding_button(g, i)->location = ii;
- }
- }
+
+ /* use previously saved settings if any */
+ netsurf_mkpath(&settings_fname, NULL, 2, nsgtk_config_home, "Print");
+ if (settings_fname != NULL) {
+ print_settings = gtk_print_settings_new_from_file(settings_fname, NULL);
+ if (print_settings != NULL) {
+ gtk_print_operation_set_print_settings(print_op,
+ print_settings);
+
+ /* We're not interested in the settings any more */
+ g_object_unref(print_settings);
+ }
+ }
+
+ content_to_print = browser_window_get_content(bw);
+
+ page_setup = gtk_print_run_page_setup_dialog(GTK_WINDOW(toplevel),
+ NULL,
+ NULL);
+ if (page_setup == NULL) {
+ nsgtk_warning(messages_get("NoMemory"), 0);
+ free(settings_fname);
+ g_object_unref(print_op);
+ return TRUE;
+ }
+ gtk_print_operation_set_default_page_setup(print_op, page_setup);
+
+ nssettings = print_make_settings(PRINT_DEFAULT,
+ NULL,
+ nsgtk_layout_table);
+
+ g_signal_connect(print_op,
+ "begin_print",
+ G_CALLBACK(gtk_print_signal_begin_print),
+ nssettings);
+ g_signal_connect(print_op,
+ "draw_page",
+ G_CALLBACK(gtk_print_signal_draw_page),
+ NULL);
+ g_signal_connect(print_op,
+ "end_print",
+ G_CALLBACK(gtk_print_signal_end_print),
+ nssettings);
+
+ if (content_get_type(browser_window_get_content(bw)) != CONTENT_TEXTPLAIN) {
+ res = gtk_print_operation_run(print_op,
+ GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+ GTK_WINDOW(toplevel),
+ NULL);
+ }
+
+ /* if the settings were used save them for future use */
+ if (settings_fname != NULL) {
+ if (res == GTK_PRINT_OPERATION_RESULT_APPLY) {
+ /* Do not increment the settings reference */
+ print_settings = gtk_print_operation_get_print_settings(print_op);
+
+ gtk_print_settings_to_file(print_settings,
+ settings_fname,
+ NULL);
}
- buffer1 = strtok_r(NULL, "|", &ptr);
+ free(settings_fname);
+ }
+
+ /* Our print_settings object is destroyed by the end print handler */
+ g_object_unref(page_setup);
+ g_object_unref(print_op);
+
+ return TRUE;
+}
+
+/**
+ * handler for quit tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+quit_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ nsgtk_scaffolding_destroy_all();
+ return TRUE;
+}
+
+
+/**
+ * handler for cut tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+cut_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWidget *focused;
+ GtkWidget *toplevel;
+
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ focused = gtk_window_get_focus(GTK_WINDOW(toplevel));
+
+ /* let gtk handle it if focused widget is an editable */
+ if (GTK_IS_EDITABLE(focused)) {
+ gtk_editable_cut_clipboard(GTK_EDITABLE(focused));
+ } else {
+ bw = tb->get_bw(tb->get_ctx);
+ browser_window_key_press(bw, NS_KEY_CUT_SELECTION);
}
- free(buffer);
+ return TRUE;
}
/**
- * save toolbar settings to file
+ * handler for copy tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-static nserror nsgtk_toolbar_customization_save(struct nsgtk_scaffolding *g)
+static gboolean
+copy_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- char *choices = NULL;
- char *order;
- int order_len = PLACEHOLDER_BUTTON * 12; /* length of order buffer */
- int tbidx;
- char *cur;
- int plen;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWidget *focused;
+ GtkWidget *toplevel;
- order = malloc(order_len);
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
- if (order == NULL) {
- return NSERROR_NOMEM;
+ focused = gtk_window_get_focus(GTK_WINDOW(toplevel));
+
+ /* let gtk handle it if focused widget is an editable */
+ if (GTK_IS_EDITABLE(focused)) {
+ gtk_editable_copy_clipboard(GTK_EDITABLE(focused));
+ } else {
+ bw = tb->get_bw(tb->get_ctx);
+ browser_window_key_press(bw, NS_KEY_COPY_SELECTION);
}
- cur = order;
- for (tbidx = BACK_BUTTON; tbidx < PLACEHOLDER_BUTTON; tbidx++) {
- plen = snprintf(cur,
- order_len,
- "%d;%d|",
- tbidx,
- nsgtk_scaffolding_button(g, tbidx)->location);
- if (plen == order_len) {
- /* ran out of space, bail early */
- NSLOG(netsurf, INFO,
- "toolbar ordering exceeded available space");
- break;
- }
- cur += plen;
- order_len -= plen;
+ return TRUE;
+}
+
+
+/**
+ * handler for paste tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+paste_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWidget *focused;
+ GtkWidget *toplevel;
+
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ focused = gtk_window_get_focus(GTK_WINDOW(toplevel));
+
+ /* let gtk handle it if focused widget is an editable */
+ if (GTK_IS_EDITABLE(focused)) {
+ gtk_editable_paste_clipboard(GTK_EDITABLE(focused));
+ } else {
+ bw = tb->get_bw(tb->get_ctx);
+ browser_window_key_press(bw, NS_KEY_PASTE);
}
- nsoption_set_charp(toolbar_order, order);
+ return TRUE;
+}
+
+
+/**
+ * handler for delete tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+delete_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWidget *focused;
+ GtkWidget *toplevel;
+
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ focused = gtk_window_get_focus(GTK_WINDOW(toplevel));
+
+ /* let gtk handle it if focused widget is an editable */
+ if (GTK_IS_EDITABLE(focused)) {
+ gtk_editable_delete_selection(GTK_EDITABLE(focused));
+ } else {
+ bw = tb->get_bw(tb->get_ctx);
+ browser_window_key_press(bw, NS_KEY_CLEAR_SELECTION);
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * handler for select all tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+selectall_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWidget *focused;
+ GtkWidget *toplevel;
+
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ focused = gtk_window_get_focus(GTK_WINDOW(toplevel));
+
+ /* let gtk handle it if focused widget is an editable */
+ if (GTK_IS_EDITABLE(focused)) {
+ gtk_editable_select_region(GTK_EDITABLE(focused), 0, -1);
+ } else {
+ bw = tb->get_bw(tb->get_ctx);
+ browser_window_key_press(bw, NS_KEY_SELECT_ALL);
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * handler for preferences tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+preferences_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWidget *toplevel;
+ GtkWidget *wndpreferences;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ wndpreferences = nsgtk_preferences(bw, GTK_WINDOW(toplevel));
+ if (wndpreferences != NULL) {
+ gtk_widget_show(wndpreferences);
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * handler for zoom plus tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+zoomplus_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ browser_window_set_scale(bw, 0.05, false);
+
+ return TRUE;
+}
+
+
+/**
+ * handler for zoom minus tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+zoomminus_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ browser_window_set_scale(bw, -0.05, false);
+
+ return TRUE;
+
+}
+
+
+/**
+ * handler for zoom normal tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+zoomnormal_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ browser_window_set_scale(bw, 1.0, true);
+
+ return TRUE;
+}
+
+
+/**
+ * handler for full screen tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+fullscreen_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ GtkWindow *gtkwindow; /* gtk window widget is in */
+ GdkWindow *gdkwindow;
+ GdkWindowState state;
+
+ gtkwindow = GTK_WINDOW(gtk_widget_get_ancestor(widget,GTK_TYPE_WINDOW));
+ gdkwindow = gtk_widget_get_window(GTK_WIDGET(gtkwindow));
+ state = gdk_window_get_state(gdkwindow);
+
+ if (state & GDK_WINDOW_STATE_FULLSCREEN) {
+ gtk_window_unfullscreen(gtkwindow);
+ } else {
+ gtk_window_fullscreen(gtkwindow);
+ }
+ return TRUE;
+}
+
+
+/**
+ * handler for view source tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+viewsource_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ nserror res;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWindow *gtkwindow; /* gtk window widget is in */
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ gtkwindow = GTK_WINDOW(gtk_widget_get_ancestor(widget,GTK_TYPE_WINDOW));
+
+ res = nsgtk_viewsource(gtkwindow, bw);
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * handler for show downloads tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+downloads_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ GtkWindow *gtkwindow; /* gtk window widget is in */
+ gtkwindow = GTK_WINDOW(gtk_widget_get_ancestor(widget,GTK_TYPE_WINDOW));
+ nsgtk_download_show(gtkwindow);
+ return TRUE;
+}
+
+
+/**
+ * handler for show downloads tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+savewindowsize_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ GtkWindow *gtkwindow; /* gtk window widget is in */
+ int x,y,w,h;
+ char *choices = NULL;
+
+ gtkwindow = GTK_WINDOW(gtk_widget_get_ancestor(widget,GTK_TYPE_WINDOW));
+
+ gtk_window_get_position(gtkwindow, &x, &y);
+ gtk_window_get_size(gtkwindow, &w, &h);
+
+ nsoption_set_int(window_width, w);
+ nsoption_set_int(window_height, h);
+ nsoption_set_int(window_x, x);
+ nsoption_set_int(window_y, y);
- /* ensure choices are saved */
netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices");
if (choices != NULL) {
nsoption_write(choices, NULL, NULL);
free(choices);
}
- return NSERROR_OK;
+ return TRUE;
}
/**
- * when 'save settings' button is clicked
+ * handler for show downloads tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-static gboolean nsgtk_toolbar_persist(GtkWidget *widget, gpointer data)
+static gboolean
+toggledebugging_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ browser_window_debug(bw, CONTENT_DEBUG_REDRAW);
+
+ nsgtk_window_update_all();
- edit_mode = false;
- /* save state to file, update toolbars for all windows */
- nsgtk_toolbar_customization_save(g);
- nsgtk_toolbar_cast(g);
- nsgtk_toolbar_set_physical(g);
- nsgtk_toolbar_close(g);
- gtk_widget_destroy(window->window);
return TRUE;
}
+
/**
- * when 'reload defaults' button is clicked
+ * handler for debug box tree tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-static gboolean nsgtk_toolbar_reset(GtkWidget *widget, gpointer data)
+static gboolean
+debugboxtree_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- int i;
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++)
- nsgtk_scaffolding_button(g, i)->location =
- (i <= THROBBER_ITEM) ? i : -1;
- nsgtk_toolbar_set_physical(g);
- for (i = BACK_BUTTON; i <= THROBBER_ITEM; i++) {
- if (i == URL_BAR_ITEM)
- continue;
- gtk_tool_item_set_use_drag_window(GTK_TOOL_ITEM(
- nsgtk_scaffolding_button(g, i)->button), TRUE);
- gtk_drag_source_set(GTK_WIDGET(
- nsgtk_scaffolding_button(g, i)->button),
- GDK_BUTTON1_MASK, &entry, 1, GDK_ACTION_COPY);
- nsgtk_toolbar_temp_connect(g, i);
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ gchar *fname;
+ gint handle;
+ FILE *f;
+
+ handle = g_file_open_tmp("nsgtkboxtreeXXXXXX", &fname, NULL);
+ if ((handle == -1) || (fname == NULL)) {
+ return TRUE;
}
+ close(handle); /* in case it was binary mode */
+
+ /* save data to temporary file */
+ f = fopen(fname, "w");
+ if (f == NULL) {
+ nsgtk_warning("Error saving box tree dump.",
+ "Unable to open file for writing.");
+ unlink(fname);
+ return TRUE;
+ }
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ browser_window_debug_dump(bw, f, CONTENT_DEBUG_RENDER);
+
+ fclose(f);
+
+ nsgtk_viewfile("Box Tree Debug", "boxtree", fname);
+
+ g_free(fname);
+
return TRUE;
}
+
/**
- * when titlebar / alt-F4 window close event happens
+ * handler for debug dom tree tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-static gboolean nsgtk_toolbar_delete(GtkWidget *widget, GdkEvent *event,
- gpointer data)
+static gboolean
+debugdomtree_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- edit_mode = false;
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- /* reset g->buttons->location */
- for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- nsgtk_scaffolding_button(g, i)->location =
- window->buttonlocations[i];
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ gchar *fname;
+ gint handle;
+ FILE *f;
+
+ handle = g_file_open_tmp("nsgtkdomtreeXXXXXX", &fname, NULL);
+ if ((handle == -1) || (fname == NULL)) {
+ return TRUE;
}
- nsgtk_toolbar_set_physical(g);
- nsgtk_toolbar_connect_all(g);
- nsgtk_toolbar_close(g);
- nsgtk_scaffolding_set_sensitivity(g);
- gtk_widget_destroy(window->window);
+ close(handle); /* in case it was binary mode */
+
+ /* save data to temporary file */
+ f = fopen(fname, "w");
+ if (f == NULL) {
+ nsgtk_warning("Error saving box tree dump.",
+ "Unable to open file for writing.");
+ unlink(fname);
+ return TRUE;
+ }
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ browser_window_debug_dump(bw, f, CONTENT_DEBUG_DOM);
+
+ fclose(f);
+
+ nsgtk_viewfile("DOM Tree Debug", "domtree", fname);
+
+ g_free(fname);
+
return TRUE;
+
}
+
/**
- * called when a widget is dropped onto the store window
+ * handler for local history tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
static gboolean
-nsgtk_toolbar_store_return(GtkWidget *widget, GdkDragContext *gdc,
- gint x, gint y, guint time, gpointer data)
+localhistory_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- int q, i;
+ nserror res;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWidget *toplevel;
- if ((window->fromstore) || (window->currentbutton == -1)) {
- window->currentbutton = -1;
- return FALSE;
- }
- if (nsgtk_scaffolding_button(g, window->currentbutton)->location
- != -1) {
- /* 'move' all widgets further right, one place to the left
- * in logical schema */
- for (i = nsgtk_scaffolding_button(g, window->currentbutton)->
- location + 1; i < PLACEHOLDER_BUTTON; i++) {
- q = nsgtk_toolbar_get_id_at_location(g, i);
- if (q == -1)
- continue;
- nsgtk_scaffolding_button(g, q)->location--;
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+ if (toplevel != NULL) {
+ bw = tb->get_bw(tb->get_ctx);
+
+ res = nsgtk_local_history_present(GTK_WINDOW(toplevel), bw);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Unable to present local history window.");
}
- gtk_container_remove(GTK_CONTAINER(
- nsgtk_scaffolding_toolbar(g)), GTK_WIDGET(
- nsgtk_scaffolding_button(g,
- window->currentbutton)->button));
- nsgtk_scaffolding_button(g, window->currentbutton)->location
- = -1;
- }
- window->currentbutton = -1;
- gtk_drag_finish(gdc, TRUE, TRUE, time);
- return FALSE;
+ }
+ return TRUE;
}
/**
- * called when hovering above the store
+ * handler for history tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
static gboolean
-nsgtk_toolbar_store_action(GtkWidget *widget, GdkDragContext *gdc,
- gint x, gint y, guint time, gpointer data)
+history_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- return FALSE;
+ return localhistory_button_clicked_cb(widget, data);
}
+
/**
- * create store window
+ * handler for global history tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-static void nsgtk_toolbar_window_open(struct nsgtk_scaffolding *g)
+static gboolean
+globalhistory_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- struct nsgtk_theme *theme;
nserror res;
+ res = nsgtk_global_history_present();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Unable to initialise global history window.");
+ }
+ return TRUE;
+}
- theme = nsgtk_theme_load(GTK_ICON_SIZE_LARGE_TOOLBAR, true);
- if (theme == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- nsgtk_toolbar_cancel_clicked(NULL, g);
- return;
+
+/**
+ * handler for add bookmark tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+addbookmarks_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+ if (browser_window_has_content(bw)) {
+ hotlist_add_url(browser_window_access_url(bw));
}
+ return TRUE;
+}
+
- res = nsgtk_builder_new_from_resname("toolbar", &window->builder);
+/**
+ * handler for show bookmark tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+showbookmarks_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ nserror res;
+ res = nsgtk_hotlist_present();
if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Toolbar UI builder init failed");
- nsgtk_warning("Toolbar UI builder init failed", 0);
- nsgtk_toolbar_cancel_clicked(NULL, g);
- free(theme);
- return;
+ NSLOG(netsurf, INFO, "Unable to initialise bookmark window.");
}
+ return TRUE;
+}
- gtk_builder_connect_signals(window->builder, NULL);
- window->window = GTK_WIDGET(gtk_builder_get_object(
- window->builder, "dialogToolbar"));
- if (window->window == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- nsgtk_toolbar_cancel_clicked(NULL, g);
- free(theme);
- return;
+/**
+ * handler for show cookies tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+showcookies_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ nserror res;
+ res = nsgtk_cookies_present(NULL);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to initialise cookies window.");
}
+ return TRUE;
+}
- gtk_window_set_transient_for(GTK_WINDOW(window->window),
- nsgtk_scaffolding_window(g));
- window->widgetvbox = GTK_WIDGET(gtk_builder_get_object(
- window->builder, "widgetvbox"));
- if (window->widgetvbox == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- nsgtk_toolbar_cancel_clicked(NULL, g);
- free(theme);
- return;
+/**
+ * handler for open location tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+openlocation_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ GtkToolItem *urltitem;
+
+ urltitem = tb->items[URL_BAR_ITEM].button;
+ if (urltitem != NULL) {
+ GtkEntry *entry;
+ entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(urltitem)));
+ gtk_widget_grab_focus(GTK_WIDGET(entry));
}
+ return TRUE;
+}
- /* preset to width [in buttons] of */
- window->numberh = NSGTK_STORE_WIDTH;
- /* store to cause creation of a new toolbar */
- window->currentbutton = -1;
+/**
+ * handler for contents tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+contents_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ nserror res;
- /* load toolbuttons */
- /* add toolbuttons to window */
- /* set event handlers */
- for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- if (i == URL_BAR_ITEM)
- continue;
- window->store_buttons[i] =
- nsgtk_toolbar_make_widget(g, i, theme);
- if (window->store_buttons[i] == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- continue;
- }
- nsgtk_toolbar_add_store_widget(window->store_buttons[i]);
- g_signal_connect(window->store_buttons[i], "drag-data-get",
- G_CALLBACK(
- nsgtk_scaffolding_button(g, i)->dataplus), g);
+ res = toolbar_navigate_to_url(tb, "https://www.netsurf-browser.org/documentation/");
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
+ }
+
+ return TRUE;
+}
+
+/**
+ * handler for contents tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+guide_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ nserror res;
+
+ res = toolbar_navigate_to_url(tb, "https://www.netsurf-browser.org/documentation/guide");
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
}
- free(theme);
+ return TRUE;
+}
+
+
+/**
+ * handler for contents tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+info_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ nserror res;
- gtk_window_set_accept_focus(GTK_WINDOW(window->window), FALSE);
+ res = toolbar_navigate_to_url(tb, "https://www.netsurf-browser.org/documentation/info");
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
+ }
- gtk_drag_dest_set(GTK_WIDGET(window->window), GTK_DEST_DEFAULT_MOTION |
- GTK_DEST_DEFAULT_DROP, &entry, 1, GDK_ACTION_COPY);
+ return TRUE;
+}
- g_signal_connect(GTK_WIDGET(gtk_builder_get_object(
- window->builder, "close")),
- "clicked",
- G_CALLBACK(nsgtk_toolbar_persist),
- g);
- g_signal_connect(GTK_WIDGET(gtk_builder_get_object(
- window->builder, "reset")),
- "clicked",
- G_CALLBACK(nsgtk_toolbar_reset),
- g);
+/**
+ * handler for contents tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean about_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ GtkWindow *parent; /* gtk window widget is in */
+
+ parent = GTK_WINDOW(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW));
+
+ nsgtk_about_dialog_init(parent);
+ return TRUE;
+}
+
+/**
+ * handler for openmenu tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE to indicate signal handled.
+ */
+static gboolean openmenu_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct gui_window *gw;
+ struct nsgtk_scaffolding *gs;
+
+ gw = tb->get_ctx; /** \todo stop assuming the context is a gui window */
- g_signal_connect(window->window, "delete-event",
- G_CALLBACK(nsgtk_toolbar_delete), g);
+ gs = nsgtk_get_scaffold(gw);
- g_signal_connect(window->window, "drag-drop",
- G_CALLBACK(nsgtk_toolbar_store_return), g);
+ nsgtk_scaffolding_burger_menu(gs);
+
+ return TRUE;
+}
- g_signal_connect(window->window, "drag-motion",
- G_CALLBACK(nsgtk_toolbar_store_action), g);
- gtk_widget_show_all(window->window);
+/* define data plus and data minus handlers */
+#define TOOLBAR_ITEM(identifier, name, snstvty, clicked, activate, label, iconame) \
+static gboolean \
+nsgtk_toolbar_##name##_data_plus(GtkWidget *widget, \
+ GdkDragContext *cont, \
+ GtkSelectionData *selection, \
+ guint info, \
+ guint time, \
+ gpointer data) \
+{ \
+ struct nsgtk_toolbar_customisation *tbc; \
+ tbc = (struct nsgtk_toolbar_customisation *)data; \
+ tbc->dragitem = identifier; \
+ tbc->dragfrom = true; \
+ return TRUE; \
+} \
+static gboolean \
+nsgtk_toolbar_##name##_data_minus(GtkWidget *widget, \
+ GdkDragContext *cont, \
+ GtkSelectionData *selection, \
+ guint info, \
+ guint time, \
+ gpointer data) \
+{ \
+ struct nsgtk_toolbar_customisation *tbc; \
+ tbc = (struct nsgtk_toolbar_customisation *)data; \
+ tbc->dragitem = identifier; \
+ tbc->dragfrom = false; \
+ return TRUE; \
}
+#include "gtk/toolbar_items.h"
+
+#undef TOOLBAR_ITEM
+
+
/**
- * change behaviour of scaffoldings while editing toolbar
+ * create a toolbar item
*
- * All buttons as well as window clicks are desensitized; then buttons
- * in the front window are changed to movable buttons
+ * create a toolbar item and set up its default handlers
*/
-void nsgtk_toolbar_customization_init(struct nsgtk_scaffolding *g)
+static nserror
+toolbar_item_create(nsgtk_toolbar_button id, struct nsgtk_toolbar_item *item)
{
- int i;
- struct nsgtk_scaffolding *list;
- edit_mode = true;
+ item->location = INACTIVE_LOCATION;
+
+ /* set item defaults from macro */
+ switch (id) {
+#define TOOLBAR_ITEM_t(name) \
+ item->clicked = name##_button_clicked_cb;
+#define TOOLBAR_ITEM_b(name) \
+ item->clicked = name##_button_clicked_cb;
+#define TOOLBAR_ITEM_y(name) \
+ item->clicked = name##_button_clicked_cb;
+#define TOOLBAR_ITEM_n(name) \
+ item->clicked = NULL;
+#define TOOLBAR_ITEM(identifier, iname, snstvty, clicked, activate, label, iconame) \
+ case identifier: \
+ item->name = #iname; \
+ item->sensitivity = snstvty; \
+ item->dataplus = nsgtk_toolbar_##iname##_data_plus; \
+ item->dataminus = nsgtk_toolbar_##iname##_data_minus; \
+ TOOLBAR_ITEM_ ## clicked(iname) \
+ break;
- list = nsgtk_scaffolding_iterate(NULL);
- while (list) {
- g_signal_handler_block(GTK_WIDGET(
- nsgtk_window_get_layout(
- nsgtk_scaffolding_top_level(list))),
- nsgtk_window_get_signalhandler(
- nsgtk_scaffolding_top_level(list),
- NSGTK_WINDOW_SIGNAL_CLICK));
- g_signal_handler_block(GTK_WIDGET(
- nsgtk_window_get_layout(
- nsgtk_scaffolding_top_level(list))),
- nsgtk_window_get_signalhandler(
- nsgtk_scaffolding_top_level(list),
- NSGTK_WINDOW_SIGNAL_REDRAW));
- nsgtk_widget_override_background_color(
- GTK_WIDGET(nsgtk_window_get_layout(
- nsgtk_scaffolding_top_level(list))),
- GTK_STATE_NORMAL, 0, 0xEEEE, 0xEEEE, 0xEEEE);
+#include "gtk/toolbar_items.h"
- if (list == g) {
- list = nsgtk_scaffolding_iterate(list);
- continue;
- }
- /* set sensitive for all gui_windows save g */
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_window(
- list)), FALSE);
- list = nsgtk_scaffolding_iterate(list);
- }
- /* set sensitive for all of g save toolbar */
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_menu_bar(g)),
- FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_notebook(g)),
- FALSE);
-
- /* set editable aspect for toolbar */
- gtk_container_foreach(GTK_CONTAINER(nsgtk_scaffolding_toolbar(g)),
- nsgtk_toolbar_clear_toolbar, g);
- nsgtk_toolbar_set_physical(g);
- /* memorize button locations, set editable */
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- window->buttonlocations[i] = nsgtk_scaffolding_button(g, i)
- ->location;
- if ((window->buttonlocations[i] == -1) || (i == URL_BAR_ITEM))
- continue;
- gtk_tool_item_set_use_drag_window(GTK_TOOL_ITEM(
- nsgtk_scaffolding_button(g, i)->button), TRUE);
- gtk_drag_source_set(GTK_WIDGET(nsgtk_scaffolding_button(
- g, i)->button), GDK_BUTTON1_MASK, &entry, 1,
- GDK_ACTION_COPY);
- nsgtk_toolbar_temp_connect(g, i);
+#undef TOOLBAR_ITEM_t
+#undef TOOLBAR_ITEM_y
+#undef TOOLBAR_ITEM_n
+#undef TOOLBAR_ITEM
+
+ case PLACEHOLDER_BUTTON:
+ return NSERROR_INVALID;
}
- /* add move button listeners */
- g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_toolbar(g)),
- "drag-drop", G_CALLBACK(nsgtk_toolbar_data), g);
- g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_toolbar(g)),
- "drag-data-received", G_CALLBACK(
- nsgtk_toolbar_move_complete), g);
- g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_toolbar(g)),
- "drag-motion", G_CALLBACK(nsgtk_toolbar_action), g);
- g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_toolbar(g)),
- "drag-leave", G_CALLBACK(
- nsgtk_toolbar_clear), g);
+ return NSERROR_OK;
+}
- /* set data types */
- gtk_drag_dest_set(GTK_WIDGET(nsgtk_scaffolding_toolbar(g)),
- GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
- &entry, 1, GDK_ACTION_COPY);
- /* open toolbar window */
- nsgtk_toolbar_window_open(g);
+/**
+ * set a toolbar item to a throbber frame number
+ *
+ * \param toolbar_item The toolbar item to update
+ * \param frame The animation frame number to update to
+ * \return NSERROR_OK on success,
+ * NSERROR_INVALID if the toolbar item does not contain an image,
+ * NSERROR_BAD_SIZE if the frame is out of range.
+ */
+static nserror set_throbber_frame(GtkToolItem *toolbar_item, int frame)
+{
+ nserror res;
+ GdkPixbuf *pixbuf;
+ GtkImage *throbber;
+
+ if (toolbar_item == NULL) {
+ /* no toolbar item */
+ return NSERROR_INVALID;
+ }
+
+ res = nsgtk_throbber_get_frame(frame, &pixbuf);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ throbber = GTK_IMAGE(gtk_bin_get_child(GTK_BIN(toolbar_item)));
+
+ gtk_image_set_from_pixbuf(throbber, pixbuf);
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Make the throbber run.
+ *
+ * scheduled callback to update the throbber
+ *
+ * \param p The context passed when scheduled.
+ */
+static void next_throbber_frame(void *p)
+{
+ struct nsgtk_toolbar *tb = p;
+ nserror res;
+
+ tb->throb_frame++; /* advance to next frame */
+
+ res = set_throbber_frame(tb->items[THROBBER_ITEM].button,
+ tb->throb_frame);
+ if (res == NSERROR_BAD_SIZE) {
+ tb->throb_frame = 1;
+ res = set_throbber_frame(tb->items[THROBBER_ITEM].button,
+ tb->throb_frame);
+ }
+
+ /* only schedule next frame if there are no errors */
+ if (res == NSERROR_OK) {
+ nsgtk_schedule(THROBBER_FRAME_TIME, next_throbber_frame, p);
+ }
}
+
/**
- * set toolbar logical -> physical; physically visible toolbar buttons are made
- * to correspond to the logically stored schema in terms of location
- * visibility etc
+ * connect signal handlers to a gtk toolbar item
*/
-void nsgtk_toolbar_set_physical(struct nsgtk_scaffolding *g)
+static nserror
+toolbar_connect_signal(struct nsgtk_toolbar *tb, nsgtk_toolbar_button itemid)
{
- int i;
- struct nsgtk_theme *theme;
+ struct nsgtk_toolbar_item *item;
+ GtkEntry *entry;
- theme = nsgtk_theme_load(GTK_ICON_SIZE_LARGE_TOOLBAR, false);
- if (theme == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- return;
+ item = &tb->items[itemid];
+
+ if (item->button != NULL) {
+ g_signal_connect(item->button,
+ "size-allocate",
+ G_CALLBACK(toolbar_item_size_allocate_cb),
+ tb);
}
- /* simplest is to clear the toolbar then reload it from memory */
- gtk_container_foreach(GTK_CONTAINER(nsgtk_scaffolding_toolbar(g)),
- nsgtk_toolbar_clear_toolbar, g);
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- nsgtk_toolbar_add_item_to_toolbar(g, i, theme);
+
+ switch (itemid) {
+ case URL_BAR_ITEM:
+ entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(item->button)));
+
+ g_signal_connect(GTK_WIDGET(entry),
+ "activate",
+ G_CALLBACK(url_entry_activate_cb),
+ tb);
+ g_signal_connect(GTK_WIDGET(entry),
+ "changed",
+ G_CALLBACK(url_entry_changed_cb),
+ tb);
+ g_signal_connect(GTK_WIDGET(entry),
+ "icon-release",
+ G_CALLBACK(url_entry_icon_release_cb),
+ tb);
+
+ nsgtk_completion_connect_signals(entry,
+ tb->get_bw,
+ tb->get_ctx);
+ break;
+
+
+ case WEBSEARCH_ITEM:
+ entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(item->button)));
+
+ g_signal_connect(GTK_WIDGET(entry),
+ "activate",
+ G_CALLBACK(websearch_entry_activate_cb),
+ tb);
+ g_signal_connect(GTK_WIDGET(entry),
+ "button-press-event",
+ G_CALLBACK(websearch_entry_button_press_cb),
+ tb);
+ break;
+
+ default:
+ if ((item->clicked != NULL) && (item->button != NULL)) {
+ g_signal_connect(item->button,
+ "clicked",
+ G_CALLBACK(item->clicked),
+ tb);
+ }
+ break;
+
}
- gtk_widget_show_all(GTK_WIDGET(nsgtk_scaffolding_toolbar(g)));
- free(theme);
+
+ return NSERROR_OK;
}
/**
- * \return toolbar item id when a widget is an element of the scaffolding
- * else -1
+ * connect all signals to widgets in a toolbar
*/
-int nsgtk_toolbar_get_id_from_widget(GtkWidget *widget,
- struct nsgtk_scaffolding *g)
+static nserror toolbar_connect_signals(struct nsgtk_toolbar *tb)
{
- int i;
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- if ((nsgtk_scaffolding_button(g, i)->location != -1)
- && (widget == GTK_WIDGET(
- nsgtk_scaffolding_button(g, i)->button))) {
- return i;
+ int location; /* location index */
+ nsgtk_toolbar_button itemid; /* item id */
+
+ for (location = BACK_BUTTON; location < PLACEHOLDER_BUTTON; location++) {
+ itemid = itemid_from_location(tb, location);
+ if (itemid == PLACEHOLDER_BUTTON) {
+ /* no more filled locations */
+ break;
}
+ toolbar_connect_signal(tb, itemid);
}
- return -1;
+
+ return NSERROR_OK;
}
/**
- * add handlers to factory widgets
- * \param g the scaffolding to attach handlers to
- * \param i the toolbar item id
+ * signal handler for toolbar context menu
+ *
+ * \param toolbar The toolbar event is being delivered to
+ * \param x The x coordinate where the click happened
+ * \param y The x coordinate where the click happened
+ * \param button the buttons being pressed
+ * \param data The context pointer passed when the connection was made.
+ * \return TRUE to indicate signal handled.
*/
-static void
-nsgtk_toolbar_set_handler(struct nsgtk_scaffolding *g, nsgtk_toolbar_button i)
+static gboolean
+toolbar_popup_context_menu_cb(GtkToolbar *toolbar,
+ gint x,
+ gint y,
+ gint button,
+ gpointer data)
{
- switch(i){
- case URL_BAR_ITEM:
- nsgtk_scaffolding_update_url_bar_ref(g);
- g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_urlbar(g)),
- "activate", G_CALLBACK(
- nsgtk_window_url_activate_event), g);
- g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_urlbar(g)),
- "changed", G_CALLBACK(
- nsgtk_window_url_changed), g);
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct gui_window *gw;
+ struct nsgtk_scaffolding *gs;
+
+ gw = tb->get_ctx; /** \todo stop assuming the context is a gui window */
+
+ gs = nsgtk_get_scaffold(gw);
+
+ nsgtk_scaffolding_toolbar_context_menu(gs);
+
+ return TRUE;
+}
+
+
+/**
+ * toolbar delete signal handler
+ */
+static void toolbar_destroy_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb;
+ tb = (struct nsgtk_toolbar *)data;
+
+ /* ensure any throbber scheduled is stopped */
+ nsgtk_schedule(-1, next_throbber_frame, tb);
+
+ free(tb);
+}
+
+
+/* exported interface documented in toolbar.h */
+nserror
+nsgtk_toolbar_create(GtkBuilder *builder,
+ struct browser_window *(*get_bw)(void *ctx),
+ void *get_ctx,
+ bool want_location_focus,
+ struct nsgtk_toolbar **tb_out)
+{
+ nserror res;
+ struct nsgtk_toolbar *tb;
+ int bidx; /* button index */
+
+ tb = calloc(1, sizeof(struct nsgtk_toolbar));
+ if (tb == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ tb->get_bw = get_bw;
+ tb->get_ctx = get_ctx;
+ /* set the throbber start frame. */
+ tb->throb_frame = 0;
+ if (want_location_focus) {
+ tb->loc_focus = LFS_WANT;
+ } else {
+ tb->loc_focus = LFS_IDLE;
+ }
+
+ tb->widget = GTK_TOOLBAR(gtk_builder_get_object(builder, "toolbar"));
+ gtk_toolbar_set_show_arrow(tb->widget, TRUE);
+
+ g_signal_connect(tb->widget,
+ "popup-context-menu",
+ G_CALLBACK(toolbar_popup_context_menu_cb),
+ tb);
+
+ /* close and cleanup on delete signal */
+ g_signal_connect(tb->widget,
+ "destroy",
+ G_CALLBACK(toolbar_destroy_cb),
+ tb);
+
+ /* allocate button contexts */
+ for (bidx = BACK_BUTTON; bidx < PLACEHOLDER_BUTTON; bidx++) {
+ res = toolbar_item_create(bidx, &tb->items[bidx]);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ res = nsgtk_toolbar_update(tb);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ *tb_out = tb;
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in toolbar.h */
+nserror nsgtk_toolbar_restyle(struct nsgtk_toolbar *tb)
+{
+ /*
+ * reset toolbar size allocation so icon size change affects
+ * allocated widths.
+ */
+ tb->offset = 0;
+
+ switch (nsoption_int(button_type)) {
+
+ case 1: /* Small icons */
+ gtk_toolbar_set_style(GTK_TOOLBAR(tb->widget),
+ GTK_TOOLBAR_ICONS);
+ gtk_toolbar_set_icon_size(GTK_TOOLBAR(tb->widget),
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
break;
- case THROBBER_ITEM:
- nsgtk_scaffolding_update_throbber_ref(g);
+ case 2: /* Large icons */
+ gtk_toolbar_set_style(GTK_TOOLBAR(tb->widget),
+ GTK_TOOLBAR_ICONS);
+ gtk_toolbar_set_icon_size(GTK_TOOLBAR(tb->widget),
+ GTK_ICON_SIZE_LARGE_TOOLBAR);
break;
- case WEBSEARCH_ITEM:
- nsgtk_scaffolding_update_websearch_ref(g);
- g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_websearch(g)),
- "activate", G_CALLBACK(
- nsgtk_websearch_activate), g);
- g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_websearch(g)),
- "button-press-event", G_CALLBACK(
- nsgtk_websearch_clear), g);
+ case 3: /* Large icons with text */
+ gtk_toolbar_set_style(GTK_TOOLBAR(tb->widget),
+ GTK_TOOLBAR_BOTH);
+ gtk_toolbar_set_icon_size(GTK_TOOLBAR(tb->widget),
+ GTK_ICON_SIZE_LARGE_TOOLBAR);
+ break;
+
+ case 4: /* Text icons only */
+ gtk_toolbar_set_style(GTK_TOOLBAR(tb->widget),
+ GTK_TOOLBAR_TEXT);
break;
default:
- if ((nsgtk_scaffolding_button(g, i)->bhandler != NULL) &&
- (nsgtk_scaffolding_button(g, i)->button != NULL)) {
- g_signal_connect(
- nsgtk_scaffolding_button(g, i)->button,
- "clicked",
- G_CALLBACK(nsgtk_scaffolding_button(
- g, i)->bhandler), g);
+ break;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in toolbar.h */
+nserror nsgtk_toolbar_throbber(struct nsgtk_toolbar *tb, bool active)
+{
+ nserror res;
+ struct browser_window *bw;
+
+ /* Manage the location focus state */
+ switch (tb->loc_focus) {
+ case LFS_IDLE:
+ break;
+ case LFS_WANT:
+ if (active) {
+ tb->loc_focus = LFS_THROB;
+ }
+ break;
+ case LFS_THROB:
+ if (!active) {
+ tb->loc_focus = LFS_LAST;
}
break;
+ case LFS_LAST:
+ break;
+ }
+
+ /* when activating the throbber simply schedule the next frame update */
+ if (active) {
+ nsgtk_schedule(THROBBER_FRAME_TIME, next_throbber_frame, tb);
+
+ set_item_sensitivity(&tb->items[STOP_BUTTON], true);
+ set_item_sensitivity(&tb->items[RELOAD_BUTTON], false);
+ set_item_action(tb, RELOADSTOP_BUTTON, false);
+
+ return NSERROR_OK;
+ }
+
+ /* stopping the throbber */
+ nsgtk_schedule(-1, next_throbber_frame, tb);
+ tb->throb_frame = 0;
+ res = set_throbber_frame(tb->items[THROBBER_ITEM].button,
+ tb->throb_frame);
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ /* adjust sensitivity of other items */
+ set_item_sensitivity(&tb->items[STOP_BUTTON], false);
+ set_item_sensitivity(&tb->items[RELOAD_BUTTON], true);
+ set_item_action(tb, RELOADSTOP_BUTTON, true);
+ set_item_sensitivity(&tb->items[BACK_BUTTON],
+ browser_window_history_back_available(bw));
+ set_item_sensitivity(&tb->items[FORWARD_BUTTON],
+ browser_window_history_forward_available(bw));
+ nsgtk_local_history_hide();
+
+ return res;
+}
+
+
+/* exported interface documented in toolbar.h */
+nserror nsgtk_toolbar_page_info_change(struct nsgtk_toolbar *tb)
+{
+ GtkEntry *url_entry;
+ browser_window_page_info_state pistate;
+ struct browser_window *bw;
+ const char *icon_name;
+
+ if (tb->items[URL_BAR_ITEM].button == NULL) {
+ /* no toolbar item */
+ return NSERROR_INVALID;
+ }
+ url_entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(tb->items[URL_BAR_ITEM].button)));
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ pistate = browser_window_get_page_info_state(bw);
+
+ switch (pistate) {
+ case PAGE_STATE_INTERNAL:
+ icon_name = "page-info-internal";
+ break;
+
+ case PAGE_STATE_LOCAL:
+ icon_name = "page-info-local";
+ break;
+
+ case PAGE_STATE_INSECURE:
+ icon_name = "page-info-insecure";
+ break;
+
+ case PAGE_STATE_SECURE_OVERRIDE:
+ icon_name = "page-info-warning";
+ break;
+
+ case PAGE_STATE_SECURE_ISSUES:
+ icon_name = "page-info-warning";
+ break;
+
+ case PAGE_STATE_SECURE:
+ icon_name = "page-info-secure";
+ break;
+
+ default:
+ icon_name = "page-info-internal";
+ break;
+ }
+
+ nsgtk_entry_set_icon_from_icon_name(GTK_WIDGET(url_entry),
+ GTK_ENTRY_ICON_PRIMARY,
+ icon_name);
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in toolbar.h */
+nserror nsgtk_toolbar_set_url(struct nsgtk_toolbar *tb, nsurl *url)
+{
+ size_t idn_url_l;
+ char *idn_url_s = NULL;
+ const char *url_text = NULL;
+ GtkEntry *url_entry;
+
+ if (tb->items[URL_BAR_ITEM].button == NULL) {
+ /* no toolbar item */
+ return NSERROR_INVALID;
+ }
+ url_entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(tb->items[URL_BAR_ITEM].button)));
+
+ if (nsoption_bool(display_decoded_idn) == true) {
+ if (nsurl_get_utf8(url, &idn_url_s, &idn_url_l) != NSERROR_OK) {
+ idn_url_s = NULL;
+ }
+ url_text = idn_url_s;
+ }
+ if (url_text == NULL) {
+ url_text = nsurl_access(url);
+ }
+
+ if (strcmp(url_text, gtk_entry_get_text(url_entry)) != 0) {
+ /* The URL bar content has changed, we need to update it */
+ gint startpos, endpos;
+ bool was_selected;
+ gtk_editable_get_selection_bounds(GTK_EDITABLE(url_entry),
+ &startpos, &endpos);
+ was_selected = gtk_widget_is_focus(GTK_WIDGET(url_entry)) &&
+ startpos == 0 &&
+ endpos == gtk_entry_get_text_length(url_entry);
+ gtk_entry_set_text(url_entry, url_text);
+ if (was_selected && tb->loc_focus != LFS_IDLE) {
+ gtk_widget_grab_focus(GTK_WIDGET(url_entry));
+ if (tb->loc_focus == LFS_LAST) {
+ tb->loc_focus = LFS_IDLE;
+ }
+ }
}
+
+ if (idn_url_s != NULL) {
+ free(idn_url_s);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in toolbar.h */
+nserror
+nsgtk_toolbar_set_websearch_image(struct nsgtk_toolbar *tb, GdkPixbuf *pixbuf)
+{
+ GtkWidget *entry;
+
+ if (tb->items[WEBSEARCH_ITEM].button == NULL) {
+ /* no toolbar item */
+ return NSERROR_INVALID;
+ }
+
+ entry = gtk_bin_get_child(GTK_BIN(tb->items[WEBSEARCH_ITEM].button));
+
+ if (pixbuf != NULL) {
+ nsgtk_entry_set_icon_from_pixbuf(entry,
+ GTK_ENTRY_ICON_PRIMARY,
+ pixbuf);
+ } else {
+ nsgtk_entry_set_icon_from_icon_name(entry,
+ GTK_ENTRY_ICON_PRIMARY,
+ NSGTK_STOCK_INFO);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in toolbar.h */
+nserror
+nsgtk_toolbar_item_activate(struct nsgtk_toolbar *tb,
+ nsgtk_toolbar_button itemid)
+{
+ GtkWidget *widget;
+
+ /* ensure item id in range */
+ if ((itemid < BACK_BUTTON) || (itemid >= PLACEHOLDER_BUTTON)) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if (tb->items[itemid].clicked == NULL) {
+ return NSERROR_INVALID;
+ }
+
+ /*
+ * if item has a widget in the current toolbar use that as the
+ * signal source otherwise use the toolbar widget itself.
+ */
+ if (tb->items[itemid].button != NULL) {
+ widget = GTK_WIDGET(tb->items[itemid].button);
+ } else {
+ widget = GTK_WIDGET(tb->widget);
+ }
+
+ tb->items[itemid].clicked(widget, tb);
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in toolbar.h */
+nserror nsgtk_toolbar_show(struct nsgtk_toolbar *tb, bool show)
+{
+ if (show) {
+ gtk_widget_show(GTK_WIDGET(tb->widget));
+ } else {
+ gtk_widget_hide(GTK_WIDGET(tb->widget));
+ }
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in toolbar.h */
+nserror nsgtk_toolbar_update(struct nsgtk_toolbar *tb)
+{
+ nserror res;
+
+ /* setup item locations based on user config */
+ res = apply_user_button_customisation(tb);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* populate toolbar widget */
+ res = populate_gtk_toolbar_widget(tb);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* ensure icon sizes and text labels on toolbar are set */
+ res = nsgtk_toolbar_restyle(tb);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = toolbar_connect_signals(tb);
+
+ return res;
}
/**
- * connect 'normal' handlers to toolbar buttons
+ * Find the correct location for popping up a window for the chosen item.
+ *
+ * \param tb The toolbar to select from
+ * \param item_idx The toolbar item to select from
+ * \param out_x Filled with an appropriate X coordinate
+ * \param out_y Filled with an appropriate Y coordinate
*/
-void nsgtk_toolbar_connect_all(struct nsgtk_scaffolding *g)
+static nserror
+nsgtk_toolbar_get_icon_window_position(struct nsgtk_toolbar *tb,
+ int item_idx,
+ int *out_x,
+ int *out_y)
{
- int q, i;
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- q = nsgtk_toolbar_get_id_at_location(g, i);
- if (q == -1)
- continue;
- if (nsgtk_scaffolding_button(g, q)->button != NULL)
- g_signal_connect(
- nsgtk_scaffolding_button(g, q)->button,
- "size-allocate", G_CALLBACK(
- nsgtk_scaffolding_toolbar_size_allocate
- ), g);
- nsgtk_toolbar_set_handler(g, q);
- }
-}
-
-
-#define DATAHANDLER(p, q, r)\
-gboolean nsgtk_toolbar_##p##_button_data(GtkWidget *widget, GdkDragContext\
- *cont, GtkSelectionData *selection, guint info, guint time,\
- gpointer data)\
-{\
- r->currentbutton = q##_BUTTON;\
- r->fromstore = true;\
- return TRUE;\
-}\
-gboolean nsgtk_toolbar_##p##_toolbar_button_data(GtkWidget *widget,\
- GdkDragContext *cont, GtkSelectionData *selection, guint info,\
- guint time, gpointer data)\
-{\
- r->currentbutton = q##_BUTTON;\
- r->fromstore = false;\
- return TRUE;\
-}
-
-DATAHANDLER(home, HOME, window)
-DATAHANDLER(forward, FORWARD, window)
-DATAHANDLER(back, BACK, window)
-DATAHANDLER(stop, STOP, window)
-DATAHANDLER(reload, RELOAD, window)
-DATAHANDLER(history, HISTORY, window)
-DATAHANDLER(newwindow, NEWWINDOW, window)
-DATAHANDLER(newtab, NEWTAB, window)
-DATAHANDLER(openfile, OPENFILE, window)
-DATAHANDLER(closetab, CLOSETAB, window)
-DATAHANDLER(closewindow, CLOSEWINDOW, window)
-DATAHANDLER(savepage, SAVEPAGE, window)
-DATAHANDLER(printpreview, PRINTPREVIEW, window)
-DATAHANDLER(print, PRINT, window)
-DATAHANDLER(quit, QUIT, window)
-DATAHANDLER(cut, CUT, window)
-DATAHANDLER(copy, COPY, window)
-DATAHANDLER(paste, PASTE, window)
-DATAHANDLER(delete, DELETE, window)
-DATAHANDLER(selectall, SELECTALL, window)
-DATAHANDLER(preferences, PREFERENCES, window)
-DATAHANDLER(zoomplus, ZOOMPLUS, window)
-DATAHANDLER(zoomminus, ZOOMMINUS, window)
-DATAHANDLER(zoomnormal, ZOOMNORMAL, window)
-DATAHANDLER(fullscreen, FULLSCREEN, window)
-DATAHANDLER(viewsource, VIEWSOURCE, window)
-DATAHANDLER(contents, CONTENTS, window)
-DATAHANDLER(about, ABOUT, window)
-DATAHANDLER(pdf, PDF, window)
-DATAHANDLER(plaintext, PLAINTEXT, window)
-DATAHANDLER(drawfile, DRAWFILE, window)
-DATAHANDLER(postscript, POSTSCRIPT, window)
-DATAHANDLER(find, FIND, window)
-DATAHANDLER(downloads, DOWNLOADS, window)
-DATAHANDLER(savewindowsize, SAVEWINDOWSIZE, window)
-DATAHANDLER(toggledebugging, TOGGLEDEBUGGING, window)
-DATAHANDLER(debugboxtree, SAVEBOXTREE, window)
-DATAHANDLER(debugdomtree, SAVEDOMTREE, window)
-DATAHANDLER(localhistory, LOCALHISTORY, window)
-DATAHANDLER(globalhistory, GLOBALHISTORY, window)
-DATAHANDLER(addbookmarks, ADDBOOKMARKS, window)
-DATAHANDLER(showbookmarks, SHOWBOOKMARKS, window)
-DATAHANDLER(showcookies, SHOWCOOKIES, window)
-DATAHANDLER(openlocation, OPENLOCATION, window)
-DATAHANDLER(nexttab, NEXTTAB, window)
-DATAHANDLER(prevtab, PREVTAB, window)
-DATAHANDLER(guide, GUIDE, window)
-DATAHANDLER(info, INFO, window)
-#undef DATAHANDLER
-
-#define DATAHANDLER(p, q, r) \
-gboolean nsgtk_toolbar_##p##_button_data(GtkWidget *widget, GdkDragContext\
- *cont, GtkSelectionData *selection, guint info, guint time,\
- gpointer data)\
-{\
- r->currentbutton = q##_ITEM;\
- r->fromstore = true;\
- return TRUE;\
-}\
-gboolean nsgtk_toolbar_##p##_toolbar_button_data(GtkWidget *widget,\
- GdkDragContext *cont, GtkSelectionData *selection, guint info,\
- guint time, gpointer data)\
-{\
- r->currentbutton = q##_ITEM;\
- r->fromstore = false;\
- return TRUE;\
-}
-
-DATAHANDLER(throbber, THROBBER, window)
-DATAHANDLER(websearch, WEBSEARCH, window)
-#undef DATAHANDLER
+ struct nsgtk_toolbar_item *item = &tb->items[item_idx];
+ GtkWidget *widget = GTK_WIDGET(item->button);
+ GtkAllocation alloc;
+ gint rootx, rooty, x, y;
+
+ switch (item_idx) {
+ case URL_BAR_ITEM:
+ widget = GTK_WIDGET(gtk_bin_get_child(GTK_BIN(item->button)));
+ break;
+ default:
+ /* Nothing to do here */
+ break;
+ }
+
+ nsgtk_widget_get_allocation(widget, &alloc);
+
+ if (gtk_widget_translate_coordinates(widget,
+ gtk_widget_get_toplevel(widget),
+ 0,
+ alloc.height - 1,
+ &x, &y) != TRUE) {
+ return NSERROR_UNKNOWN;
+ }
+
+ gtk_window_get_position(GTK_WINDOW(gtk_widget_get_toplevel(widget)),
+ &rootx, &rooty);
+
+ *out_x = rootx + x + 4;
+ *out_y = rooty + y + 4;
+
+ return NSERROR_OK;
+}
+
+nserror nsgtk_toolbar_position_page_info(struct nsgtk_toolbar *tb,
+ struct nsgtk_pi_window *win)
+{
+ nserror res;
+ int x, y;
+
+ res = nsgtk_toolbar_get_icon_window_position(tb, URL_BAR_ITEM, &x, &y);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ nsgtk_page_info_set_position(win, x, y);
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in toolbar.h */
+nserror nsgtk_toolbar_position_local_history(struct nsgtk_toolbar *tb)
+{
+ nserror res;
+ int x, y;
+
+ res = nsgtk_toolbar_get_icon_window_position(tb, HISTORY_BUTTON, &x, &y);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ nsgtk_local_history_set_position(x, y);
+
+ return NSERROR_OK;
+}
diff --git a/frontends/gtk/toolbar.h b/frontends/gtk/toolbar.h
index 4286fe3f0..4ecca9f02 100644
--- a/frontends/gtk/toolbar.h
+++ b/frontends/gtk/toolbar.h
@@ -16,77 +16,127 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_GTK_TOOLBAR_H_
-#define _NETSURF_GTK_TOOLBAR_H_
+#ifndef NETSURF_GTK_TOOLBAR_H_
+#define NETSURF_GTK_TOOLBAR_H_
/**
- * sets up the images for scaffolding.
+ * control toolbar context
*/
-void nsgtk_theme_implement(struct nsgtk_scaffolding *g);
+struct nsgtk_toolbar;
+struct nsgtk_scaffolding;
+/**
+ * create a control toolbar
+ *
+ * \param[in] builder The gtk builder object the toolbar is being created from
+ * \param[out] toolbar a pointer to receive the result.
+ * \return NSERROR_OK and toolbar updated on success else error code
+ */
+nserror nsgtk_toolbar_create(GtkBuilder *builder,
+ struct browser_window *(*get_bw)(void *ctx),
+ void *get_bw_ctx,
+ bool want_location_focus,
+ struct nsgtk_toolbar **toolbar);
+
+
+/**
+ * Update the toolbar items being shown based on current settings
+ *
+ * \param toolbar A toolbar returned from a creation
+ * \return NSERROR_OK on success
+ */
+nserror nsgtk_toolbar_update(struct nsgtk_toolbar *tb);
+
+
+/**
+ * Update toolbar style and size based on current settings
+ *
+ * \param toolbar A toolbar returned from a creation
+ * \return NSERROR_OK on success
+ */
+nserror nsgtk_toolbar_restyle(struct nsgtk_toolbar *tb);
+
+
+/**
+ * Start or stop a throbber in a toolbar
+ *
+ * \param toolbar A toolbar returned from a creation
+ * \param active True if the throbber animation should play.
+ * \return NSERROR_OK on success
+ */
+nserror nsgtk_toolbar_throbber(struct nsgtk_toolbar *tb, bool active);
+
+
+/**
+ * Page info has changed state
+ *
+ * \param toolbar A toolbar returned from a creation
+ * \return NSERROR_OK on success
+ */
+nserror nsgtk_toolbar_page_info_change(struct nsgtk_toolbar *tb);
+
+
+/**
+ * Update the toolbar url entry
+ *
+ * \param toolbar A toolbar returned from a creation
+ * \param url The URL to set
+ * \return NSERROR_OK on success
+ */
+nserror nsgtk_toolbar_set_url(struct nsgtk_toolbar *tb, nsurl *url);
+
+
+/**
+ * set the websearch image
+ *
+ * \param toolbar A toolbar returned from a creation
+ * \param pixbuf The pixel buffer data to use to set the web search icon
+ * \return NSERROR_OK on success
+ */
+nserror nsgtk_toolbar_set_websearch_image(struct nsgtk_toolbar *tb, GdkPixbuf *pixbuf);
+
+
+/**
+ * activate the handler for a toolbar item
+ *
+ * This allows the same action to be performed for menu enties as if
+ * the user had clicked the toolbar widget.
+ *
+ * \param toolbar A toolbar returned from a creation
+ * \param itemid the id of the item to activate
+ * \return NSERROR_OK on success
+ */
+nserror nsgtk_toolbar_item_activate(struct nsgtk_toolbar *tb, nsgtk_toolbar_button itemid);
+
+/**
+ * set the toolbar to be shown or hidden
+ *
+ * \param toolbar A toolbar returned from a creation
+ * \param show true to show the toolbar and false to hide it.
+ * \return NSERROR_OK on success
+ */
+nserror nsgtk_toolbar_show(struct nsgtk_toolbar *tb, bool show);
+
+/**
+ * position the page info window appropriately
+ *
+ * \param tb The toolbar to position relative to
+ * \param win The page-info window to position
+ */
+nserror nsgtk_toolbar_position_page_info(struct nsgtk_toolbar *tb,
+ struct nsgtk_pi_window *win);
+
+/**
+ * position the local history window appropriately
+ *
+ * \param tb The toolbar to position relative to
+ */
+nserror nsgtk_toolbar_position_local_history(struct nsgtk_toolbar *tb);
+
+/**
+ * Initialise customization of toolbar entries
+ */
void nsgtk_toolbar_customization_init(struct nsgtk_scaffolding *g);
-void nsgtk_toolbar_init(struct nsgtk_scaffolding *g);
-void nsgtk_toolbar_customization_load(struct nsgtk_scaffolding *g);
-void nsgtk_toolbar_set_physical(struct nsgtk_scaffolding *g);
-void nsgtk_toolbar_connect_all(struct nsgtk_scaffolding *g);
-int nsgtk_toolbar_get_id_from_widget(GtkWidget *widget, struct nsgtk_scaffolding *g);
-
-#define TOOLPROTO(q) gboolean nsgtk_toolbar_##q##_button_data(\
- GtkWidget *widget, GdkDragContext *cont, GtkSelectionData\
- *selection, guint info, guint time, gpointer data);\
-gboolean nsgtk_toolbar_##q##_toolbar_button_data(GtkWidget *widget,\
- GdkDragContext *cont, GtkSelectionData *selection, guint info,\
- guint time, gpointer data)
-TOOLPROTO(home);
-TOOLPROTO(back);
-TOOLPROTO(forward);
-TOOLPROTO(reload);
-TOOLPROTO(stop);
-TOOLPROTO(throbber);
-TOOLPROTO(websearch);
-TOOLPROTO(history);
-TOOLPROTO(newwindow);
-TOOLPROTO(newtab);
-TOOLPROTO(openfile);
-TOOLPROTO(closetab);
-TOOLPROTO(closewindow);
-TOOLPROTO(savepage);
-TOOLPROTO(pdf);
-TOOLPROTO(plaintext);
-TOOLPROTO(drawfile);
-TOOLPROTO(postscript);
-TOOLPROTO(printpreview);
-TOOLPROTO(print);
-TOOLPROTO(quit);
-TOOLPROTO(cut);
-TOOLPROTO(copy);
-TOOLPROTO(paste);
-TOOLPROTO(delete);
-TOOLPROTO(selectall);
-TOOLPROTO(find);
-TOOLPROTO(preferences);
-TOOLPROTO(zoomplus);
-TOOLPROTO(zoomminus);
-TOOLPROTO(zoomnormal);
-TOOLPROTO(fullscreen);
-TOOLPROTO(viewsource);
-TOOLPROTO(downloads);
-TOOLPROTO(localhistory);
-TOOLPROTO(globalhistory);
-TOOLPROTO(addbookmarks);
-TOOLPROTO(showbookmarks);
-TOOLPROTO(showcookies);
-TOOLPROTO(openlocation);
-TOOLPROTO(nexttab);
-TOOLPROTO(prevtab);
-TOOLPROTO(savewindowsize);
-TOOLPROTO(toggledebugging);
-TOOLPROTO(debugboxtree);
-TOOLPROTO(debugdomtree);
-TOOLPROTO(contents);
-TOOLPROTO(guide);
-TOOLPROTO(info);
-TOOLPROTO(about);
-#undef TOOLPROTO
+
#endif
diff --git a/frontends/gtk/toolbar_items.h b/frontends/gtk/toolbar_items.h
new file mode 100644
index 000000000..b4bed371f
--- /dev/null
+++ b/frontends/gtk/toolbar_items.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETSURF_GTK_TOOLBAR_ITEMS_H
+#define NETSURF_GTK_TOOLBAR_ITEMS_H
+
+typedef enum {
+ BACK_BUTTON = 0,
+ HISTORY_BUTTON,
+ FORWARD_BUTTON,
+ RELOADSTOP_BUTTON,
+ URL_BAR_ITEM,
+ WEBSEARCH_ITEM,
+ OPENMENU_BUTTON,
+ STOP_BUTTON,
+ RELOAD_BUTTON,
+ HOME_BUTTON,
+ THROBBER_ITEM,
+ NEWWINDOW_BUTTON,
+ NEWTAB_BUTTON,
+ OPENFILE_BUTTON,
+ CLOSETAB_BUTTON,
+ CLOSEWINDOW_BUTTON,
+ SAVEPAGE_BUTTON,
+ PDF_BUTTON,
+ PLAINTEXT_BUTTON,
+ DRAWFILE_BUTTON,
+ POSTSCRIPT_BUTTON,
+ PRINTPREVIEW_BUTTON,
+ PRINT_BUTTON,
+ QUIT_BUTTON,
+ CUT_BUTTON,
+ COPY_BUTTON,
+ PASTE_BUTTON,
+ DELETE_BUTTON,
+ SELECTALL_BUTTON,
+ FIND_BUTTON,
+ PREFERENCES_BUTTON,
+ ZOOMPLUS_BUTTON,
+ ZOOMMINUS_BUTTON,
+ ZOOMNORMAL_BUTTON,
+ FULLSCREEN_BUTTON,
+ VIEWSOURCE_BUTTON,
+ DOWNLOADS_BUTTON,
+ SAVEWINDOWSIZE_BUTTON,
+ TOGGLEDEBUGGING_BUTTON,
+ SAVEBOXTREE_BUTTON,
+ SAVEDOMTREE_BUTTON,
+ LOCALHISTORY_BUTTON,
+ GLOBALHISTORY_BUTTON,
+ ADDBOOKMARKS_BUTTON,
+ SHOWBOOKMARKS_BUTTON,
+ SHOWCOOKIES_BUTTON,
+ OPENLOCATION_BUTTON,
+ NEXTTAB_BUTTON,
+ PREVTAB_BUTTON,
+ CONTENTS_BUTTON,
+ GUIDE_BUTTON,
+ INFO_BUTTON,
+ ABOUT_BUTTON,
+ CUSTOMIZE_BUTTON,
+ PLACEHOLDER_BUTTON /* size indicator; array maximum indices */
+} nsgtk_toolbar_button; /* PLACEHOLDER_BUTTON - 1 */
+
+#endif
+
+/*
+ * Item fields are:
+ * - item identifier (enum value)
+ * - name (identifier)
+ * - initial sensitivity (true/false)
+ * - if there is a toolbar click signal handler (y/n) and it is available in
+ * the toolbar and toolbox as a button (b, implies y) if the item is
+ * available as a button but not placed in the toolbox (t, implies y)
+ * - if there is a menu activate signal handler (y/n) and it calls the
+ * toolbar click handler directly. (p, implies y)
+ * - item label as a netsurf message (identifier)
+ * - icon image name ("string")
+ */
+
+#ifndef TOOLBAR_ITEM
+#define TOOLBAR_ITEM(a, b, c, d, e, f, g)
+#define TOOLBAR_ITEM_SET
+#endif
+
+TOOLBAR_ITEM(BACK_BUTTON, back, false, b, p, gtkBack, "go-previous")
+TOOLBAR_ITEM(HISTORY_BUTTON, history, true, y, n, , "local-history")
+TOOLBAR_ITEM(FORWARD_BUTTON, forward, false, b, p, gtkForward, "go-next")
+TOOLBAR_ITEM(STOP_BUTTON, stop, false, t, p, gtkStop, NSGTK_STOCK_STOP)
+TOOLBAR_ITEM(RELOAD_BUTTON, reload, true, t, p, Reload, NSGTK_STOCK_REFRESH)
+TOOLBAR_ITEM(HOME_BUTTON, home, true, b, p, gtkHome, NSGTK_STOCK_HOME)
+TOOLBAR_ITEM(URL_BAR_ITEM, url_bar, true, n, n, , NULL)
+TOOLBAR_ITEM(WEBSEARCH_ITEM, websearch, true, n, n, , NULL)
+TOOLBAR_ITEM(THROBBER_ITEM, throbber, true, n, n, , NULL)
+TOOLBAR_ITEM(NEWWINDOW_BUTTON, newwindow, true, b, p, gtkNewWindow, "document-new")
+TOOLBAR_ITEM(NEWTAB_BUTTON, newtab, true, b, p, gtkNewTab, NSGTK_STOCK_ADD)
+TOOLBAR_ITEM(OPENFILE_BUTTON, openfile, true, b, p, gtkOpenFile, "document-open")
+TOOLBAR_ITEM(CLOSETAB_BUTTON, closetab, false, n, y, , "window-close")
+TOOLBAR_ITEM(CLOSEWINDOW_BUTTON, closewindow, true, y, p, , "window-close")
+TOOLBAR_ITEM(SAVEPAGE_BUTTON, savepage, true, b, p, gtkSavePage, "text-html")
+TOOLBAR_ITEM(PDF_BUTTON, pdf, false, y, p, , "x-office-document")
+TOOLBAR_ITEM(PLAINTEXT_BUTTON, plaintext, true, b, p, gtkPlainText, "text-x-generic")
+TOOLBAR_ITEM(DRAWFILE_BUTTON, drawfile, false, n, n, , NULL)
+TOOLBAR_ITEM(POSTSCRIPT_BUTTON, postscript, false, n, n, , NULL)
+TOOLBAR_ITEM(PRINTPREVIEW_BUTTON, printpreview, false, n, p, gtkPrintPreview, "gtk-print-preview")
+TOOLBAR_ITEM(PRINT_BUTTON, print, true, b, p, gtkPrint, "document-print")
+TOOLBAR_ITEM(QUIT_BUTTON, quit, true, b, p, gtkQuitMenu, "application-exit")
+TOOLBAR_ITEM(CUT_BUTTON, cut, true, b, p, gtkCut, "edit-cut")
+TOOLBAR_ITEM(COPY_BUTTON, copy, true, b, p, gtkCopy, "edit-copy")
+TOOLBAR_ITEM(PASTE_BUTTON, paste, true, b, p, gtkPaste, "edit-paste")
+TOOLBAR_ITEM(DELETE_BUTTON, delete, false, b, p, gtkDelete, "edit-delete")
+TOOLBAR_ITEM(SELECTALL_BUTTON, selectall, true, b, p, gtkSelectAll, "edit-select-all")
+TOOLBAR_ITEM(FIND_BUTTON, find, true, n, y, gtkFind, "edit-find")
+TOOLBAR_ITEM(PREFERENCES_BUTTON, preferences, true, b, p, gtkPreferences, "preferences-system")
+TOOLBAR_ITEM(ZOOMPLUS_BUTTON, zoomplus, true, b, p, gtkZoomPlus, "gtk-zoom-in")
+TOOLBAR_ITEM(ZOOMMINUS_BUTTON, zoomminus, true, b, p, gtkZoomMinus, "gtk-zoom-out")
+TOOLBAR_ITEM(ZOOMNORMAL_BUTTON, zoomnormal, true, b, p, gtkZoomNormal, "gtk-zoom-100")
+TOOLBAR_ITEM(FULLSCREEN_BUTTON, fullscreen, true, b, p, gtkFullScreen, "gtk-fullscreen")
+TOOLBAR_ITEM(VIEWSOURCE_BUTTON, viewsource, true, b, p, gtkPageSource, "gtk-index")
+TOOLBAR_ITEM(DOWNLOADS_BUTTON, downloads, true, b, p, gtkDownloads, NSGTK_STOCK_SAVE_AS)
+TOOLBAR_ITEM(SAVEWINDOWSIZE_BUTTON, savewindowsize, true, y, p, gtkSaveWindowSize, NULL)
+TOOLBAR_ITEM(TOGGLEDEBUGGING_BUTTON, toggledebugging, true, y, p, gtkToggleDebugging, NULL)
+TOOLBAR_ITEM(SAVEBOXTREE_BUTTON, debugboxtree, true, y, p, gtkDebugBoxTree, NULL)
+TOOLBAR_ITEM(SAVEDOMTREE_BUTTON, debugdomtree, true, y, p, gtkDebugDomTree, NULL)
+TOOLBAR_ITEM(LOCALHISTORY_BUTTON, localhistory, true, y, p, , NULL)
+TOOLBAR_ITEM(GLOBALHISTORY_BUTTON, globalhistory, true, y, p, gtkGlobalHistory, NULL)
+TOOLBAR_ITEM(ADDBOOKMARKS_BUTTON, addbookmarks, true, y, p, gtkAddBookMarks, NULL)
+TOOLBAR_ITEM(SHOWBOOKMARKS_BUTTON, showbookmarks, true, b, p, gtkShowBookMarks, "user-bookmarks")
+TOOLBAR_ITEM(SHOWCOOKIES_BUTTON, showcookies, true, b, p, gtkShowCookies, "show-cookie")
+TOOLBAR_ITEM(OPENLOCATION_BUTTON, openlocation, true, y, p, gtkOpenLocation, NULL)
+TOOLBAR_ITEM(NEXTTAB_BUTTON, nexttab, false, n, y, gtkNextTab, "media-skip-forward")
+TOOLBAR_ITEM(PREVTAB_BUTTON, prevtab, false, n, y, gtkPrevTab, "media-skip-backward")
+TOOLBAR_ITEM(CONTENTS_BUTTON, contents, true, y, p, gtkContents, "gtk-help")
+TOOLBAR_ITEM(GUIDE_BUTTON, guide, true, y, p, gtkGuide, "gtk-help")
+TOOLBAR_ITEM(INFO_BUTTON, info, true, y, p, gtkUserInformation, "dialog-information")
+TOOLBAR_ITEM(ABOUT_BUTTON, about, true, b, p, gtkAbout, "help-about")
+TOOLBAR_ITEM(OPENMENU_BUTTON, openmenu, true, b, n, gtkOpenMenu, NSGTK_STOCK_OPEN_MENU)
+TOOLBAR_ITEM(CUSTOMIZE_BUTTON, cutomize, true, y, p, , NULL)
+TOOLBAR_ITEM(RELOADSTOP_BUTTON, reloadstop, true, b, n, Reload, NSGTK_STOCK_REFRESH)
+
+#ifdef TOOLBAR_ITEM_SET
+#undef TOOLBAR_ITEM
+#undef TOOLBAR_ITEM_SET
+#endif
diff --git a/frontends/gtk/viewsource.c b/frontends/gtk/viewsource.c
index acf81018d..7c11862c6 100644
--- a/frontends/gtk/viewsource.c
+++ b/frontends/gtk/viewsource.c
@@ -34,8 +34,8 @@ nserror nsgtk_viewsource(GtkWindow *parent, struct browser_window *bw)
{
nserror ret;
struct hlcache_handle *hlcontent;
- const char *source_data;
- unsigned long source_size;
+ const uint8_t *source_data;
+ size_t source_size;
char *ndata = NULL;
size_t ndata_len;
char *filename;
@@ -52,7 +52,7 @@ nserror nsgtk_viewsource(GtkWindow *parent, struct browser_window *bw)
source_data = content_get_source_data(hlcontent, &source_size);
- ret = nsurl_nice(browser_window_get_url(bw), &filename, false);
+ ret = nsurl_nice(browser_window_access_url(bw), &filename, false);
if (ret != NSERROR_OK) {
filename = strdup(messages_get("SaveSource"));
if (filename == NULL) {
@@ -60,15 +60,16 @@ nserror nsgtk_viewsource(GtkWindow *parent, struct browser_window *bw)
}
}
- title = malloc(strlen(nsurl_access(browser_window_get_url(bw))) + SLEN("Source of - NetSurf") + 1);
+ title = malloc(strlen(nsurl_access(browser_window_access_url(bw))) + SLEN("Source of - NetSurf") + 1);
if (title == NULL) {
free(filename);
return NSERROR_NOMEM;
}
- sprintf(title, "Source of %s - NetSurf", nsurl_access(browser_window_get_url(bw)));
+ sprintf(title, "Source of %s - NetSurf", nsurl_access(browser_window_access_url(bw)));
- ret = utf8_from_enc(source_data,
- content_get_encoding(hlcontent, CONTENT_ENCODING_NORMAL),
+ ret = utf8_from_enc((const char *)source_data,
+ content_get_encoding(hlcontent,
+ CONTENT_ENCODING_NORMAL),
source_size,
&ndata,
&ndata_len);
diff --git a/frontends/gtk/window.c b/frontends/gtk/window.c
index 7f24d40ac..f5c87ef87 100644
--- a/frontends/gtk/window.c
+++ b/frontends/gtk/window.c
@@ -31,10 +31,13 @@
#include <gdk/gdkkeysyms.h>
#include <gdk-pixbuf/gdk-pixdata.h>
-#include "netsurf/inttypes.h"
+#include "utils/utils.h"
#include "utils/log.h"
#include "utils/utf8.h"
#include "utils/nsoption.h"
+#include "utils/messages.h"
+#include "utils/nsurl.h"
+#include "netsurf/inttypes.h"
#include "netsurf/content.h"
#include "netsurf/browser_window.h"
#include "netsurf/mouse.h"
@@ -45,12 +48,13 @@
#include "desktop/searchweb.h"
#include "desktop/textinput.h"
-#include "gtk/window.h"
#include "gtk/selection.h"
#include "gtk/warn.h"
#include "gtk/compat.h"
#include "gtk/gui.h"
#include "gtk/scaffolding.h"
+#include "gtk/toolbar_items.h"
+#include "gtk/toolbar.h"
#include "gtk/local_history.h"
#include "gtk/plotters.h"
#include "gtk/schedule.h"
@@ -58,13 +62,18 @@
#include "gtk/bitmap.h"
#include "gtk/gdk.h"
#include "gtk/resources.h"
+#include "gtk/search.h"
+#include "gtk/throbber.h"
+#include "gtk/window.h"
+
+/**
+ * time (in ms) between throbber animation frame updates
+ */
+#define THROBBER_FRAME_TIME (100)
static GtkWidget *select_menu;
static struct form_control *select_menu_control;
-static void nsgtk_select_menu_clicked(GtkCheckMenuItem *checkmenuitem,
- gpointer user_data);
-
struct gui_window {
/**
* The gtk scaffold object containing menu, buttons, url bar, [tabs],
@@ -94,12 +103,21 @@ struct gui_window {
/** previous event location */
int last_x, last_y;
- /** The top level container (tabContents) */
+ /** controls toolbar context */
+ struct nsgtk_toolbar *toolbar;
+
+ /** search toolbar context */
+ struct gtk_search *search;
+
+ /** The top level container (tabBox) */
GtkWidget *container;
/** display widget for this page or frame */
GtkLayout *layout;
+ /** The container for the layout etc */
+ GtkWidget *grid;
+
/** handle to the the visible tab */
GtkWidget *tab;
@@ -112,15 +130,15 @@ struct gui_window {
/** has the status pane had its first size operation yet? */
bool paned_sized;
- /** to allow disactivation / resume of normal window behaviour */
- gulong signalhandler[NSGTK_WINDOW_SIGNAL_COUNT];
-
/** The icon this window should have */
GdkPixbuf *icon;
/** The input method to use with this window */
GtkIMContext *input_method;
+ /** current frame of throbber */
+ int throb_frame;
+
/** list for cleanup */
struct gui_window *next, *prev;
};
@@ -128,60 +146,12 @@ struct gui_window {
/**< first entry in window list */
struct gui_window *window_list = NULL;
-/** flag controlling opening of tabs in teh background */
-int temp_open_background = -1;
-
-struct nsgtk_scaffolding *nsgtk_get_scaffold(struct gui_window *g)
-{
- return g->scaffold;
-}
-
-GdkPixbuf *nsgtk_get_icon(struct gui_window *gw)
-{
- return gw->icon;
-}
-
-struct browser_window *nsgtk_get_browser_window(struct gui_window *g)
-{
- return g->bw;
-}
-
-unsigned long nsgtk_window_get_signalhandler(struct gui_window *g, int i)
-{
- return g->signalhandler[i];
-}
-
-GtkLayout *nsgtk_window_get_layout(struct gui_window *g)
-{
- return g->layout;
-}
-
-GtkWidget *nsgtk_window_get_tab(struct gui_window *g)
-{
- return g->tab;
-}
-
-void nsgtk_window_set_tab(struct gui_window *g, GtkWidget *w)
-{
- g->tab = w;
-}
-
-
-struct gui_window *nsgtk_window_iterate(struct gui_window *g)
-{
- return g->next;
-}
-
-float nsgtk_get_scale_for_gui(struct gui_window *g)
-{
- return browser_window_get_scale(g->bw);
-}
-
-static void nsgtk_select_menu_clicked(GtkCheckMenuItem *checkmenuitem,
- gpointer user_data)
+static void
+nsgtk_select_menu_clicked(GtkCheckMenuItem *checkmenuitem,
+ gpointer user_data)
{
form_select_process_selection(select_menu_control,
- (intptr_t)user_data);
+ (intptr_t)user_data);
}
#if GTK_CHECK_VERSION(3,0,0)
@@ -278,8 +248,10 @@ nsgtk_window_draw_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
#endif
-static gboolean nsgtk_window_motion_notify_event(GtkWidget *widget,
- GdkEventMotion *event, gpointer data)
+static gboolean
+nsgtk_window_motion_notify_event(GtkWidget *widget,
+ GdkEventMotion *event,
+ gpointer data)
{
struct gui_window *g = data;
bool shift = event->state & GDK_SHIFT_MASK;
@@ -325,15 +297,34 @@ static gboolean nsgtk_window_motion_notify_event(GtkWidget *widget,
if (g->mouse.state & BROWSER_MOUSE_MOD_2 && !ctrl)
g->mouse.state ^= BROWSER_MOUSE_MOD_2;
- browser_window_mouse_track(g->bw, g->mouse.state,
- event->x / browser_window_get_scale(g->bw),
- event->y / browser_window_get_scale(g->bw));
+ browser_window_mouse_track(g->bw, g->mouse.state, event->x, event->y);
return TRUE;
}
-static gboolean nsgtk_window_button_press_event(GtkWidget *widget,
- GdkEventButton *event, gpointer data)
+/**
+ * GTK signal handler for focus-out-event on layout
+ *
+ * when focus leaves the layout widget ensure the caret is cleared
+ */
+static gboolean
+nsgtk_window_focus_out_event(GtkWidget *widget,
+ GdkEvent *event,
+ gpointer data)
+{
+ struct gui_window *g = data;
+
+ browser_window_remove_caret(g->bw, true);
+ return FALSE;
+}
+
+/**
+ * GTK signal handler for button-press-event on layout
+ */
+static gboolean
+nsgtk_window_button_press_event(GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data)
{
struct gui_window *g = data;
@@ -341,8 +332,8 @@ static gboolean nsgtk_window_button_press_event(GtkWidget *widget,
gtk_widget_grab_focus(GTK_WIDGET(g->layout));
nsgtk_local_history_hide();
- g->mouse.pressed_x = event->x / browser_window_get_scale(g->bw);
- g->mouse.pressed_y = event->y / browser_window_get_scale(g->bw);
+ g->mouse.pressed_x = event->x;
+ g->mouse.pressed_y = event->y;
switch (event->button) {
case 1: /* Left button, usually. Pass to core as BUTTON 1. */
@@ -382,25 +373,43 @@ static gboolean nsgtk_window_button_press_event(GtkWidget *widget,
g->last_x = event->x;
g->last_y = event->y;
- browser_window_mouse_click(g->bw, g->mouse.state, g->mouse.pressed_x,
- g->mouse.pressed_y);
+ browser_window_mouse_click(g->bw,
+ g->mouse.state,
+ g->mouse.pressed_x,
+ g->mouse.pressed_y);
return TRUE;
}
-static gboolean nsgtk_window_button_release_event(GtkWidget *widget,
- GdkEventButton *event, gpointer data)
+
+static gboolean
+nsgtk_window_button_release_event(GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data)
{
struct gui_window *g = data;
bool shift = event->state & GDK_SHIFT_MASK;
bool ctrl = event->state & GDK_CONTROL_MASK;
+ switch (event->button) {
+ case 8:
+ nsgtk_toolbar_item_activate(g->toolbar, BACK_BUTTON);
+ break;
+ case 9:
+ nsgtk_toolbar_item_activate(g->toolbar, FORWARD_BUTTON);
+ break;
+ default:
+ NSLOG(netsurf, DEBUG, "event button %d", event->button);
+ break;
+ }
+
/* If the mouse state is PRESS then we are waiting for a release to emit
* a click event, otherwise just reset the state to nothing */
- if (g->mouse.state & BROWSER_MOUSE_PRESS_1)
+ if (g->mouse.state & BROWSER_MOUSE_PRESS_1) {
g->mouse.state ^= (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1);
- else if (g->mouse.state & BROWSER_MOUSE_PRESS_2)
+ } else if (g->mouse.state & BROWSER_MOUSE_PRESS_2) {
g->mouse.state ^= (BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_2);
+ }
/* Handle modifiers being removed */
if (g->mouse.state & BROWSER_MOUSE_MOD_1 && !shift)
@@ -409,19 +418,16 @@ static gboolean nsgtk_window_button_release_event(GtkWidget *widget,
g->mouse.state ^= BROWSER_MOUSE_MOD_2;
if (g->mouse.state & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2)) {
- browser_window_mouse_click(g->bw, g->mouse.state,
- event->x / browser_window_get_scale(g->bw),
- event->y / browser_window_get_scale(g->bw));
+ browser_window_mouse_click(g->bw, g->mouse.state, event->x, event->y);
} else {
- browser_window_mouse_track(g->bw, 0,
- event->x / browser_window_get_scale(g->bw),
- event->y / browser_window_get_scale(g->bw));
+ browser_window_mouse_track(g->bw, 0, event->x, event->y);
}
g->mouse.state = 0;
return TRUE;
}
+
static gboolean
nsgtk_window_scroll_event(GtkWidget *widget,
GdkEventScroll *event,
@@ -466,9 +472,8 @@ nsgtk_window_scroll_event(GtkWidget *widget,
deltay *= nsgtk_adjustment_get_step_increment(vscroll);
if (browser_window_scroll_at_point(g->bw,
- event->x / browser_window_get_scale(g->bw),
- event->y / browser_window_get_scale(g->bw),
- deltax, deltay) != true) {
+ event->x, event->y,
+ deltax, deltay) != true) {
/* core did not handle event so change adjustments */
@@ -510,12 +515,15 @@ nsgtk_window_scroll_event(GtkWidget *widget,
return TRUE;
}
-static gboolean nsgtk_window_keypress_event(GtkWidget *widget,
- GdkEventKey *event, gpointer data)
+
+static gboolean
+nsgtk_window_keypress_event(GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer data)
{
struct gui_window *g = data;
uint32_t nskey;
-
+
if (gtk_im_context_filter_keypress(g->input_method, event))
return TRUE;
@@ -627,17 +635,22 @@ static gboolean nsgtk_window_keypress_event(GtkWidget *widget,
return TRUE;
}
-static gboolean nsgtk_window_keyrelease_event(GtkWidget *widget,
- GdkEventKey *event, gpointer data)
+
+static gboolean
+nsgtk_window_keyrelease_event(GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer data)
{
struct gui_window *g = data;
-
+
return gtk_im_context_filter_keypress(g->input_method, event);
}
-static void nsgtk_window_input_method_commit(GtkIMContext *ctx,
- const gchar *str, gpointer data)
+static void
+nsgtk_window_input_method_commit(GtkIMContext *ctx,
+ const gchar *str,
+ gpointer data)
{
struct gui_window *g = data;
size_t len = strlen(str), offset = 0;
@@ -652,8 +665,10 @@ static void nsgtk_window_input_method_commit(GtkIMContext *ctx,
}
-static gboolean nsgtk_window_size_allocate_event(GtkWidget *widget,
- GtkAllocation *allocation, gpointer data)
+static gboolean
+nsgtk_window_size_allocate_event(GtkWidget *widget,
+ GtkAllocation *allocation,
+ gpointer data)
{
struct gui_window *g = data;
@@ -663,7 +678,8 @@ static gboolean nsgtk_window_size_allocate_event(GtkWidget *widget,
}
-/** when the pane position is changed update the user option
+/**
+ * when the pane position is changed update the user option
*
* The slightly awkward implementation with the first allocation flag
* is necessary because the initial window creation does not cause an
@@ -692,11 +708,15 @@ nsgtk_paned_notify__position(GObject *gobject, GParamSpec *pspec, gpointer data)
((gtk_paned_get_position(g->paned) * 10000) / (pane_alloc.width - 1)));
}
-/** Set status bar / scroll bar proportion according to user option
- * when pane is resized.
+
+/**
+ * Set status bar / scroll bar proportion according to user option
+ * when pane is resized.
*/
-static gboolean nsgtk_paned_size_allocate_event(GtkWidget *widget,
- GtkAllocation *allocation, gpointer data)
+static gboolean
+nsgtk_paned_size_allocate_event(GtkWidget *widget,
+ GtkAllocation *allocation,
+ gpointer data)
{
gtk_paned_set_position(GTK_PANED(widget),
(nsoption_int(toolbar_status_size) * allocation->width) / 10000);
@@ -704,7 +724,12 @@ static gboolean nsgtk_paned_size_allocate_event(GtkWidget *widget,
return TRUE;
}
-/* destroy the browsing context as there is nothing to display it now */
+
+/**
+ * handler for gtk destroy signal on window container
+ *
+ * destroy the browsing context as there is will be nothing to display it now
+ */
static void window_destroy(GtkWidget *widget, gpointer data)
{
struct gui_window *gw = data;
@@ -712,6 +737,66 @@ static void window_destroy(GtkWidget *widget, gpointer data)
browser_window_destroy(gw->bw);
g_object_unref(gw->input_method);
+
+ /* free any existing icon */
+ if (gw->icon != NULL) {
+ g_object_unref(gw->icon);
+ gw->icon = NULL;
+ }
+
+ free(gw);
+}
+
+
+static struct browser_window *bw_from_gw(void *data)
+{
+ struct gui_window *gw = data;
+ return gw->bw;
+}
+
+
+static bool get_tool_bar_show(void)
+{
+ const char *cur_bar_show;
+
+ cur_bar_show = nsoption_charp(bar_show);
+ if (cur_bar_show != NULL) {
+ if (strcmp(cur_bar_show, "menu/tool") == 0) {
+ return true;
+ } else if (strcmp(cur_bar_show, "tool") == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/**
+ * Make the throbber advance to next frame.
+ *
+ * scheduled callback to update the throbber
+ *
+ * \param p The context passed when scheduled.
+ */
+static void next_throbber_frame(void *p)
+{
+ struct gui_window *gw = p;
+ nserror res;
+ GdkPixbuf *pixbuf;
+
+ gw->throb_frame++; /* advance to next frame */
+
+ res = nsgtk_throbber_get_frame(gw->throb_frame, &pixbuf);
+ if (res == NSERROR_BAD_SIZE) {
+ gw->throb_frame = 1;
+ res = nsgtk_throbber_get_frame(gw->throb_frame, &pixbuf);
+ }
+
+ if (res == NSERROR_OK) {
+ nsgtk_tab_set_icon(gw->container, pixbuf);
+ /* only schedule next frame if there are no errors */
+ nsgtk_schedule(THROBBER_FRAME_TIME, next_throbber_frame, p);
+ }
}
@@ -730,13 +815,17 @@ static void window_destroy(GtkWidget *widget, gpointer data)
*/
static struct gui_window *
gui_window_create(struct browser_window *bw,
- struct gui_window *existing,
- gui_window_create_flags flags)
+ struct gui_window *existing,
+ gui_window_create_flags flags)
{
struct gui_window *g; /* what is being created to return */
- bool tempback;
+ bool open_in_background = !(nsoption_bool(focus_new));
GtkBuilder* tab_builder;
+ /* If there is a foreground request, override user preference */
+ if (flags & GW_CREATE_FOREGROUND)
+ open_in_background = false;
+
nserror res;
res = nsgtk_builder_new_from_resname("tabcontents", &tab_builder);
@@ -781,12 +870,32 @@ gui_window_create(struct browser_window *bw,
}
/* Construct our primary elements */
- g->container = GTK_WIDGET(gtk_builder_get_object(tab_builder, "tabContents"));
+ g->container = GTK_WIDGET(gtk_builder_get_object(tab_builder, "tabBox"));
g->layout = GTK_LAYOUT(gtk_builder_get_object(tab_builder, "layout"));
+ g->grid = GTK_WIDGET(gtk_builder_get_object(tab_builder, "tabContents"));
g->status_bar = GTK_LABEL(gtk_builder_get_object(tab_builder, "status_bar"));
g->paned = GTK_PANED(gtk_builder_get_object(tab_builder, "hpaned1"));
g->input_method = gtk_im_multicontext_new();
+
+ /* create toolbar */
+ res = nsgtk_toolbar_create(tab_builder, bw_from_gw, g,
+ !!(flags & GW_CREATE_FOCUS_LOCATION),
+ &g->toolbar);
+ if (res != NSERROR_OK) {
+ free(g);
+ g_object_unref(tab_builder);
+ return NULL;
+ }
+
+ /* local page text search toolbar */
+ res = nsgtk_search_create(tab_builder, g->bw, &g->search);
+ if (res != NSERROR_OK) {
+ free(g);
+ g_object_unref(tab_builder);
+ return NULL;
+ }
+
/* set a default favicon */
g_object_ref(favicon_pixbuf);
g->icon = favicon_pixbuf;
@@ -816,11 +925,10 @@ gui_window_create(struct browser_window *bw,
/* set the default background colour of the drawing area to white. */
nsgtk_widget_override_background_color(GTK_WIDGET(g->layout),
- GTK_STATE_NORMAL,
+ GTK_STATE_FLAG_NORMAL,
0, 0xffff, 0xffff, 0xffff);
- g->signalhandler[NSGTK_WINDOW_SIGNAL_REDRAW] =
- nsgtk_connect_draw_event(GTK_WIDGET(g->layout),
+ nsgtk_connect_draw_event(GTK_WIDGET(g->layout),
G_CALLBACK(nsgtk_window_draw_event), g);
/* helper macro to conect signals to callbacks */
@@ -830,8 +938,7 @@ gui_window_create(struct browser_window *bw,
/* layout signals */
CONNECT(g->layout, "motion-notify-event",
nsgtk_window_motion_notify_event, g);
- g->signalhandler[NSGTK_WINDOW_SIGNAL_CLICK] =
- CONNECT(g->layout, "button-press-event",
+ CONNECT(g->layout, "button-press-event",
nsgtk_window_button_press_event, g);
CONNECT(g->layout, "button-release-event",
nsgtk_window_button_release_event, g);
@@ -843,6 +950,8 @@ gui_window_create(struct browser_window *bw,
nsgtk_window_size_allocate_event, g);
CONNECT(g->layout, "scroll-event",
nsgtk_window_scroll_event, g);
+ CONNECT(g->layout, "focus-out-event",
+ nsgtk_window_focus_out_event, g);
/* status pane signals */
CONNECT(g->paned, "size-allocate",
@@ -864,71 +973,65 @@ gui_window_create(struct browser_window *bw,
nsgtk_window_input_method_commit, g);
/* add the tab container to the scaffold notebook */
- switch (temp_open_background) {
- case -1:
- tempback = !(nsoption_bool(focus_new));
- break;
- case 0:
- tempback = false;
- break;
- default:
- tempback = true;
- break;
- }
- nsgtk_tab_add(g, g->container, tempback);
+ nsgtk_tab_add(g, g->container,
+ open_in_background,
+ messages_get("NewTab"), g->icon);
+
+ /* initialy should not be visible */
+ nsgtk_search_toggle_visibility(g->search);
+
+ /* set toolbar visibility from user option */
+ nsgtk_toolbar_show(g->toolbar, get_tool_bar_show());
/* safe to drop the reference to the tab_builder as the container is
* referenced by the notebook now.
*/
g_object_unref(tab_builder);
- return g;
-}
-
-
-
-void nsgtk_reflow_all_windows(void)
-{
- for (struct gui_window *g = window_list; g; g = g->next) {
- nsgtk_tab_options_changed(nsgtk_scaffolding_notebook(g->scaffold));
- browser_window_schedule_reformat(g->bw);
+ /* Finally we need to focus the location bar if requested */
+ if (flags & GW_CREATE_FOCUS_LOCATION) {
+ if (nsgtk_window_item_activate(g, OPENLOCATION_BUTTON) != NSERROR_OK) {
+ NSLOG(netsurf, WARNING, "Unable to focus location input");
+ }
}
+
+ return g;
}
-void nsgtk_window_destroy_browser(struct gui_window *gw)
+static void gui_window_destroy(struct gui_window *gw)
{
- /* remove tab */
- gtk_widget_destroy(gw->container);
-}
+ NSLOG(netsurf, INFO, "gui_window: %p", gw);
+ assert(gw != NULL);
+ assert(gw->bw != NULL);
+ NSLOG(netsurf, INFO, "scaffolding: %p", gw->scaffold);
-static void gui_window_destroy(struct gui_window *g)
-{
- NSLOG(netsurf, INFO, "gui_window: %p", g);
- assert(g != NULL);
- assert(g->bw != NULL);
- NSLOG(netsurf, INFO, "scaffolding: %p", g->scaffold);
+ /* kill off any throbber that might be running */
+ nsgtk_schedule(-1, next_throbber_frame, gw);
- if (g->prev) {
- g->prev->next = g->next;
+ /* remove from window list */
+ if (gw->prev) {
+ gw->prev->next = gw->next;
} else {
- window_list = g->next;
+ window_list = gw->next;
}
- if (g->next) {
- g->next->prev = g->prev;
+ if (gw->next) {
+ gw->next->prev = gw->prev;
}
NSLOG(netsurf, INFO, "window list head: %p", window_list);
}
+
/**
* favicon setting for gtk gui window.
*
* \param gw gtk gui window to set favicon on.
* \param icon A handle to the new favicon content.
*/
-static void gui_window_set_icon(struct gui_window *gw, struct hlcache_handle *icon)
+static void
+gui_window_set_icon(struct gui_window *gw, struct hlcache_handle *icon)
{
struct bitmap *icon_bitmap = NULL;
@@ -952,9 +1055,13 @@ static void gui_window_set_icon(struct gui_window *gw, struct hlcache_handle *ic
gw->icon = favicon_pixbuf;
}
- nsgtk_scaffolding_set_icon(gw);
+ /* only set icon if throbber not running */
+ if (gw->throb_frame == 0) {
+ nsgtk_tab_set_icon(gw->container, gw->icon);
+ }
}
+
static bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
{
GtkAdjustment *vadj = nsgtk_layout_get_vadjustment(g->layout);
@@ -969,6 +1076,7 @@ static bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
return true;
}
+
static void nsgtk_redraw_caret(struct gui_window *g)
{
int sx, sy;
@@ -983,6 +1091,7 @@ static void nsgtk_redraw_caret(struct gui_window *g)
}
+
static void gui_window_remove_caret(struct gui_window *g)
{
int sx, sy;
@@ -1000,6 +1109,7 @@ static void gui_window_remove_caret(struct gui_window *g)
}
+
/**
* Invalidates an area of a GTK browser window
*
@@ -1011,7 +1121,6 @@ static nserror
nsgtk_window_invalidate_area(struct gui_window *g, const struct rect *rect)
{
int sx, sy;
- float scale;
if (rect == NULL) {
gtk_widget_queue_draw(GTK_WIDGET(g->layout));
@@ -1023,17 +1132,17 @@ nsgtk_window_invalidate_area(struct gui_window *g, const struct rect *rect)
}
gui_window_get_scroll(g, &sx, &sy);
- scale = browser_window_get_scale(g->bw);
gtk_widget_queue_draw_area(GTK_WIDGET(g->layout),
- rect->x0 * scale - sx,
- rect->y0 * scale - sy,
- (rect->x1 - rect->x0) * scale,
- (rect->y1 - rect->y0) * scale);
+ rect->x0 - sx,
+ rect->y0 - sy,
+ rect->x1 - rect->x0,
+ rect->y1 - rect->y0);
return NSERROR_OK;
}
+
static void gui_window_set_status(struct gui_window *g, const char *text)
{
assert(g);
@@ -1087,17 +1196,20 @@ gui_window_set_scroll(struct gui_window *g, const struct rect *rect)
return NSERROR_OK;
}
+
static void gui_window_update_extent(struct gui_window *g)
{
int w, h;
if (browser_window_get_extents(g->bw, true, &w, &h) == NSERROR_OK) {
gtk_layout_set_size(g->layout, w, h);
+ gtk_widget_queue_resize(g->grid);
}
}
-static void gui_window_set_pointer(struct gui_window *g,
- gui_pointer_shape shape)
+
+static void
+gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape)
{
GdkCursor *cursor = NULL;
GdkCursorType cursortype;
@@ -1182,8 +1294,10 @@ static void gui_window_set_pointer(struct gui_window *g,
}
-static void gui_window_place_caret(struct gui_window *g, int x, int y, int height,
- const struct rect *clip)
+static void
+gui_window_place_caret(struct gui_window *g,
+ int x, int y, int height,
+ const struct rect *clip)
{
nsgtk_redraw_caret(g);
@@ -1215,14 +1329,11 @@ static void gui_window_place_caret(struct gui_window *g, int x, int y, int heigh
* \param gw The gui window to measure content area of.
* \param width receives width of window
* \param height receives height of window
- * \param scaled whether to return scaled values
* \return NSERROR_OK on sucess and width and height updated
* else error code.
*/
static nserror
-gui_window_get_dimensions(struct gui_window *gw,
- int *width, int *height,
- bool scaled)
+gui_window_get_dimensions(struct gui_window *gw, int *width, int *height)
{
GtkAllocation alloc;
@@ -1232,23 +1343,19 @@ gui_window_get_dimensions(struct gui_window *gw,
*width = alloc.width;
*height = alloc.height;
- if (scaled) {
- float scale = browser_window_get_scale(gw->bw);
- *width /= scale;
- *height /= scale;
- }
- NSLOG(netsurf, INFO, "gw:%p width:%i height:%i", gw, *width, *height);
-
return NSERROR_OK;
}
+
static void gui_window_start_selection(struct gui_window *g)
{
gtk_widget_grab_focus(GTK_WIDGET(g->layout));
}
-static void gui_window_create_form_select_menu(struct gui_window *g,
- struct form_control *control)
+
+static void
+gui_window_create_form_select_menu(struct gui_window *g,
+ struct form_control *control)
{
intptr_t item;
struct form_option *option;
@@ -1295,11 +1402,15 @@ static void gui_window_create_form_select_menu(struct gui_window *g,
gtk_widget_show_all(select_menu);
- gtk_menu_popup(GTK_MENU(select_menu), NULL, NULL, NULL,
- NULL /* data */, 0, gtk_get_current_event_time());
-
+ nsgtk_menu_popup_at_pointer(GTK_MENU(select_menu), NULL);
}
+
+/**
+ * GTK window UI callback when core needs a file selection gadget
+ *
+ * \param g The gui window on which the gadget has been requested
+ */
static void
gui_window_file_gadget_open(struct gui_window *g,
struct hlcache_handle *hl,
@@ -1315,7 +1426,7 @@ gui_window_file_gadget_open(struct gui_window *g,
NULL);
NSLOG(netsurf, INFO, "*** open dialog: %p", dialog);
-
+
int ret = gtk_dialog_run(GTK_DIALOG(dialog));
NSLOG(netsurf, INFO, "*** return value: %d", ret);
if (ret == GTK_RESPONSE_ACCEPT) {
@@ -1323,7 +1434,7 @@ gui_window_file_gadget_open(struct gui_window *g,
filename = gtk_file_chooser_get_filename(
GTK_FILE_CHOOSER(dialog));
-
+
browser_window_set_gadget_filename(g->bw, gadget, filename);
g_free(filename);
@@ -1332,6 +1443,147 @@ gui_window_file_gadget_open(struct gui_window *g,
gtk_widget_destroy(dialog);
}
+
+/**
+ * handle throbber changing state
+ */
+static nserror throbber(struct gui_window *gw, bool active)
+{
+ nsgtk_toolbar_throbber(gw->toolbar, active);
+ nsgtk_scaffolding_throbber(gw, active);
+ if (active) {
+ nsgtk_schedule(THROBBER_FRAME_TIME, next_throbber_frame, gw);
+ } else {
+ nsgtk_schedule(-1, next_throbber_frame, gw);
+ gw->throb_frame = 0;
+ /* set tab back to favicon */
+ nsgtk_tab_set_icon(gw->container, gw->icon);
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * handle page info changing
+ */
+static nserror page_info_change(struct gui_window *gw)
+{
+ nsgtk_toolbar_page_info_change(gw->toolbar);
+ return NSERROR_OK;
+}
+
+/**
+ * GTK window UI callback to process miscellaneous events
+ *
+ * \param gw The window receiving the event.
+ * \param event The event code.
+ * \return NSERROR_OK when processed ok
+ */
+static nserror
+gui_window_event(struct gui_window *gw, enum gui_window_event event)
+{
+ switch (event) {
+ case GW_EVENT_UPDATE_EXTENT:
+ gui_window_update_extent(gw);
+ break;
+
+ case GW_EVENT_REMOVE_CARET:
+ gui_window_remove_caret(gw);
+ break;
+
+ case GW_EVENT_START_SELECTION:
+ gui_window_start_selection(gw);
+ break;
+
+ case GW_EVENT_START_THROBBER:
+ throbber(gw, true);
+ break;
+
+ case GW_EVENT_STOP_THROBBER:
+ throbber(gw, false);
+ break;
+
+ case GW_EVENT_PAGE_INFO_CHANGE:
+ page_info_change(gw);
+ break;
+
+ default:
+ break;
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * GTK window UI callback when core changes the current url
+ *
+ * \param gw The gui window on which the url has been set.
+ * \param url The new url.
+ */
+static nserror gui_window_set_url(struct gui_window *gw, nsurl *url)
+{
+ return nsgtk_toolbar_set_url(gw->toolbar, url);
+}
+
+
+/**
+ * GTK window UI callback when core changes the current title
+ *
+ * \param gw The gui window on which the url has been set.
+ * \param url The new url.
+ */
+static void gui_window_set_title(struct gui_window *gw, const char *title)
+{
+
+ if ((title != NULL) && (title[0] != '\0')) {
+ nsgtk_tab_set_title(gw->container, title);
+ }
+ nsgtk_scaffolding_set_title(gw, title);
+}
+
+
+/**
+ * GTK UI callback when search provider details are updated.
+ *
+ * \param name The providers name.
+ * \param bitmap The bitmap representing the provider.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+gui_search_web_provider_update(const char *name, struct bitmap *bitmap)
+{
+ struct gui_window *gw;
+ GdkPixbuf *pixbuf = NULL;
+
+ if (bitmap != NULL) {
+ pixbuf = nsgdk_pixbuf_get_from_surface(bitmap->surface, 32, 32);
+ }
+
+ for (gw = window_list; gw != NULL; gw = gw->next) {
+ nsgtk_toolbar_set_websearch_image(gw->toolbar, pixbuf);
+ }
+
+ if (pixbuf != NULL) {
+ g_object_unref(pixbuf);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * GTK frontend web search operation table
+ */
+static struct gui_search_web_table search_web_table = {
+ .provider_update = gui_search_web_provider_update,
+};
+
+struct gui_search_web_table *nsgtk_search_web_table = &search_web_table;
+
+
+/**
+ * GTK frontend browser window operation table
+ */
static struct gui_window_table window_table = {
.create = gui_window_create,
.destroy = gui_window_destroy,
@@ -1339,22 +1591,115 @@ static struct gui_window_table window_table = {
.get_scroll = gui_window_get_scroll,
.set_scroll = gui_window_set_scroll,
.get_dimensions = gui_window_get_dimensions,
- .update_extent = gui_window_update_extent,
+ .event = gui_window_event,
.set_icon = gui_window_set_icon,
+ .set_title = gui_window_set_title,
.set_status = gui_window_set_status,
.set_pointer = gui_window_set_pointer,
.place_caret = gui_window_place_caret,
- .remove_caret = gui_window_remove_caret,
.create_form_select_menu = gui_window_create_form_select_menu,
.file_gadget_open = gui_window_file_gadget_open,
- .start_selection = gui_window_start_selection,
-
- /* from scaffold */
- .set_title = nsgtk_window_set_title,
.set_url = gui_window_set_url,
- .start_throbber = gui_window_start_throbber,
- .stop_throbber = gui_window_stop_throbber,
+
+
};
struct gui_window_table *nsgtk_window_table = &window_table;
+
+
+/* exported interface documented in window.h */
+struct nsgtk_scaffolding *nsgtk_get_scaffold(struct gui_window *g)
+{
+ return g->scaffold;
+}
+
+
+/* exported interface documented in window.h */
+struct browser_window *nsgtk_get_browser_window(struct gui_window *g)
+{
+ return g->bw;
+}
+
+
+/* exported interface documented in window.h */
+GtkLayout *nsgtk_window_get_layout(struct gui_window *g)
+{
+ return g->layout;
+}
+
+
+/* exported interface documented in window.h */
+nserror
+nsgtk_window_search_toggle(struct gui_window *gw)
+{
+ return nsgtk_search_toggle_visibility(gw->search);
+}
+
+
+/* exported interface documented in window.h */
+nserror
+nsgtk_window_item_activate(struct gui_window *gw, nsgtk_toolbar_button itemid)
+{
+ return nsgtk_toolbar_item_activate(gw->toolbar, itemid);
+}
+
+
+/* exported interface documented in window.h */
+void nsgtk_window_destroy_browser(struct gui_window *gw)
+{
+ /* remove tab */
+ gtk_widget_destroy(gw->container);
+}
+
+
+/* exported interface documented in window.h */
+nserror nsgtk_window_update_all(void)
+{
+ struct gui_window *gw;
+ for (gw = window_list; gw != NULL; gw = gw->next) {
+ nsgtk_tab_options_changed(nsgtk_scaffolding_notebook(gw->scaffold));
+ nsgtk_toolbar_restyle(gw->toolbar);
+ nsgtk_search_restyle(gw->search);
+ browser_window_schedule_reformat(gw->bw);
+ }
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in window.h */
+nserror nsgtk_window_toolbar_show(struct nsgtk_scaffolding *gs, bool show)
+{
+ struct gui_window *gw;
+ for (gw = window_list; gw != NULL; gw = gw->next) {
+ if (gw->scaffold == gs) {
+ nsgtk_toolbar_show(gw->toolbar, show);
+ }
+ }
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in window.h */
+nserror nsgtk_window_toolbar_update(void)
+{
+ struct gui_window *gw;
+ for (gw = window_list; gw != NULL; gw = gw->next) {
+ nsgtk_toolbar_update(gw->toolbar);
+
+ }
+ return NSERROR_OK;
+}
+
+/* exported interface documented in window.h */
+nserror nsgtk_window_position_page_info(struct gui_window *gw,
+ struct nsgtk_pi_window *win)
+{
+ return nsgtk_toolbar_position_page_info(gw->toolbar, win);
+}
+
+/* exported interface documented in window.h */
+nserror nsgtk_window_position_local_history(struct gui_window *gw)
+{
+ return nsgtk_toolbar_position_local_history(gw->toolbar);
+}
diff --git a/frontends/gtk/window.h b/frontends/gtk/window.h
index 7e46a7c60..a43e0b197 100644
--- a/frontends/gtk/window.h
+++ b/frontends/gtk/window.h
@@ -19,28 +19,98 @@
#ifndef NETSURF_GTK_WINDOW_H
#define NETSURF_GTK_WINDOW_H 1
-extern struct gui_window_table *nsgtk_window_table;
+struct nsgtk_pi_window;
-typedef enum nsgtk_window_signals {
- NSGTK_WINDOW_SIGNAL_CLICK,
- NSGTK_WINDOW_SIGNAL_REDRAW,
- NSGTK_WINDOW_SIGNAL_COUNT
-} nsgtk_window_signal;
+extern struct gui_window_table *nsgtk_window_table;
+extern struct gui_search_web_table *nsgtk_search_web_table;
extern struct gui_window *window_list;
-extern int temp_open_background;
-
-struct browser_window *nsgtk_get_browser_window(struct gui_window *g);
-struct nsgtk_scaffolding *nsgtk_get_scaffold(struct gui_window *g);
-GdkPixbuf *nsgtk_get_icon(struct gui_window *gw);
-void nsgtk_reflow_all_windows(void);
-float nsgtk_get_scale_for_gui(struct gui_window *g);
-int nsgtk_gui_window_update_targets(struct gui_window *g);
-void nsgtk_window_destroy_browser(struct gui_window *g);
-unsigned long nsgtk_window_get_signalhandler(struct gui_window *g, int i);
-GtkLayout *nsgtk_window_get_layout(struct gui_window *g);
-struct gui_window *nsgtk_window_iterate(struct gui_window *g);
-GtkWidget *nsgtk_window_get_tab(struct gui_window *g);
-void nsgtk_window_set_tab(struct gui_window *g, GtkWidget *w);
+
+/**
+ * get core browsing context from gui window handle
+ *
+ * \param gw gui window handle
+ */
+struct browser_window *nsgtk_get_browser_window(struct gui_window *gw);
+
+/**
+ * get containing nsgtk scaffolding handle from gui window handle
+ *
+ * \param gw gui window handle
+ */
+struct nsgtk_scaffolding *nsgtk_get_scaffold(struct gui_window *gw);
+
+/**
+ * Every window will have its tab, toolbar and drawing area updated
+ *
+ * The update will ensure the correct tab options are used, the
+ * toolbar size and style is changed and the browser window contents
+ * redrawn.
+ */
+nserror nsgtk_window_update_all(void);
+
+/**
+ * every window will have its toolbar updated to reflect user settings
+ */
+nserror nsgtk_window_toolbar_update(void);
+
+/**
+ * Windows associated with a scaffold will have their toolbar show state set
+ */
+nserror nsgtk_window_toolbar_show(struct nsgtk_scaffolding *gs, bool show);
+
+/**
+ * update targets
+ *
+ * \param gw gui window handle
+ */
+int nsgtk_gui_window_update_targets(struct gui_window *gw);
+
+/**
+ * destroy browsing context
+ *
+ * \param gw gui window handle
+ */
+void nsgtk_window_destroy_browser(struct gui_window *gw);
+
+
+/**
+ * toggle search visibility
+ *
+ * \param gw gui window handle
+ */
+nserror nsgtk_window_search_toggle(struct gui_window *gw);
+
+/**
+ * get gtk layout from gui handle
+ *
+ * \param gw gui window handle
+ */
+GtkLayout *nsgtk_window_get_layout(struct gui_window *gw);
+
+
+/**
+ * activate the handler for a item in a toolbar of a gui window
+ *
+ * \param gw The gui window handle
+ * \param itemid The id of the item to activate
+ */
+nserror nsgtk_window_item_activate(struct gui_window *gw, nsgtk_toolbar_button itemid);
+
+/**
+ * position page_info appropriately
+ *
+ * \param gw The gui window handle to position relative to
+ * \param win The page-info window to position
+ */
+nserror nsgtk_window_position_page_info(struct gui_window *gw,
+ struct nsgtk_pi_window *win);
+
+/**
+ * position local_history appropriately
+ *
+ * \param gw The gui window handle to position relative to
+ */
+nserror nsgtk_window_position_local_history(struct gui_window *gw);
#endif /* NETSURF_GTK_WINDOW_H */
diff --git a/frontends/monkey/401login.c b/frontends/monkey/401login.c
index 090f18984..1629425f6 100644
--- a/frontends/monkey/401login.c
+++ b/frontends/monkey/401login.c
@@ -16,40 +16,208 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "utils/ring.h"
-
#include <stdlib.h>
#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include "utils/ring.h"
+#include "utils/nsurl.h"
+
+#include "monkey/output.h"
#include "monkey/401login.h"
-typedef struct monkey401 {
+struct monkey401 {
struct monkey401 *r_next, *r_prev;
uint32_t num;
- lwc_string *host; /* Ignore */
- nserror (*cb)(bool,void*);
- void *pw;
-} monkey401_t;
+ nserror (*cb)(struct nsurl*, const char *, const char *, const char *, void *);
+ void *cbpw;
+ char *username;
+ char *password;
+ char *realm;
+ struct nsurl *url;
+};
+
+static struct monkey401 *m401_ring = NULL;
+static uint32_t m401_ctr = 0;
+
+
+nserror
+gui_401login_open(struct nsurl *url,
+ const char *realm,
+ const char *username,
+ const char *password,
+ nserror (*cb)(struct nsurl *url,
+ const char *realm,
+ const char *username,
+ const char *password,
+ void *pw),
+ void *cbpw)
+{
+ struct monkey401 *m401_ctx;
+
+ m401_ctx = calloc(sizeof(*m401_ctx), 1);
+ if (m401_ctx == NULL) {
+ return NSERROR_NOMEM;
+ }
+ m401_ctx->realm = strdup(realm);
+ if (m401_ctx->realm == NULL) {
+ free(m401_ctx);
+ return NSERROR_NOMEM;
+ }
+ m401_ctx->url = nsurl_ref(url);
+ m401_ctx->cb = cb;
+ m401_ctx->cbpw = cbpw;
+ m401_ctx->num = m401_ctr++;
+
+ RING_INSERT(m401_ring, m401_ctx);
+
+ if (username == NULL) {
+ username = "";
+ }
+
+ if (password == NULL) {
+ password = "";
+ }
+
+ moutf(MOUT_LOGIN, "OPEN LWIN %u URL %s", m401_ctx->num, nsurl_access(url));
+ moutf(MOUT_LOGIN, "USER LWIN %u STR %s", m401_ctx->num, username);
+ moutf(MOUT_LOGIN, "PASS LWIN %u STR %s", m401_ctx->num, password);
+ moutf(MOUT_LOGIN, "REALM LWIN %u STR %s", m401_ctx->num, realm);
+
+ return NSERROR_OK;
+}
+
+static struct monkey401 *
+monkey_find_login_by_num(uint32_t login_num)
+{
+ struct monkey401 *ret = NULL;
+
+ RING_ITERATE_START(struct monkey401, m401_ring, c_ring) {
+ if (c_ring->num == login_num) {
+ ret = c_ring;
+ RING_ITERATE_STOP(m401_ring, c_ring);
+ }
+ } RING_ITERATE_END(m401_ring, c_ring);
+
+ return ret;
+}
+
+static void free_login_context(struct monkey401 *m401_ctx) {
+ moutf(MOUT_LOGIN, "DESTROY LWIN %u", m401_ctx->num);
+ RING_REMOVE(m401_ring, m401_ctx);
+ if (m401_ctx->username != NULL) {
+ free(m401_ctx->username);
+ }
+ if (m401_ctx->password != NULL) {
+ free(m401_ctx->password);
+ }
+ free(m401_ctx->realm);
+ nsurl_unref(m401_ctx->url);
+ free(m401_ctx);
+}
+
+static void
+monkey_login_handle_go(int argc, char **argv)
+{
+ struct monkey401 *m401_ctx;
+
+ if (argc != 3) {
+ moutf(MOUT_ERROR, "LOGIN GO ARGS BAD");
+ return;
+ }
+
+ m401_ctx = monkey_find_login_by_num(atoi(argv[2]));
+ if (m401_ctx == NULL) {
+ moutf(MOUT_ERROR, "LOGIN NUM BAD");
+ return;
+ }
-static monkey401_t *m4_ring = NULL;
-static uint32_t m4_ctr = 0;
+ m401_ctx->cb(m401_ctx->url, m401_ctx->realm, m401_ctx->username, m401_ctx->password, m401_ctx->cbpw);
+
+ free_login_context(m401_ctx);
+}
-void gui_401login_open(nsurl *url, const char *realm,
- nserror (*cb)(bool proceed, void *pw), void *cbpw)
+static void
+monkey_login_handle_destroy(int argc, char **argv)
{
- monkey401_t *m4t = calloc(sizeof(*m4t), 1);
- if (m4t == NULL) {
- cb(false, cbpw);
+ struct monkey401 *m401_ctx;
+
+ if (argc != 3) {
+ moutf(MOUT_ERROR, "LOGIN DESTROY ARGS BAD");
return;
}
- m4t->cb = cb;
- m4t->pw = cbpw;
- m4t->num = m4_ctr++;
-
- RING_INSERT(m4_ring, m4t);
-
- fprintf(stdout, "401LOGIN OPEN M4 %u URL %s REALM %s\n",
- m4t->num, nsurl_access(url), realm);
+
+ m401_ctx = monkey_find_login_by_num(atoi(argv[2]));
+ if (m401_ctx == NULL) {
+ moutf(MOUT_ERROR, "LOGIN NUM BAD");
+ return;
+ }
+
+ free_login_context(m401_ctx);
}
+static void
+monkey_login_handle_username(int argc, char **argv)
+{
+ struct monkey401 *m401_ctx;
+
+ if (argc != 4) {
+ moutf(MOUT_ERROR, "LOGIN USERNAME ARGS BAD");
+ return;
+ }
+
+ m401_ctx = monkey_find_login_by_num(atoi(argv[2]));
+ if (m401_ctx == NULL) {
+ moutf(MOUT_ERROR, "LOGIN NUM BAD");
+ return;
+ }
+
+ if (m401_ctx->username != NULL) {
+ free(m401_ctx->username);
+ }
+
+ m401_ctx->username = strdup(argv[3]);
+}
+static void
+monkey_login_handle_password(int argc, char **argv)
+{
+ struct monkey401 *m401_ctx;
+
+ if (argc != 4) {
+ moutf(MOUT_ERROR, "LOGIN PASSWORD ARGS BAD");
+ return;
+ }
+
+ m401_ctx = monkey_find_login_by_num(atoi(argv[2]));
+ if (m401_ctx == NULL) {
+ moutf(MOUT_ERROR, "LOGIN NUM BAD");
+ return;
+ }
+
+ if (m401_ctx->password != NULL) {
+ free(m401_ctx->password);
+ }
+
+ m401_ctx->password = strdup(argv[3]);
+}
+
+void
+monkey_login_handle_command(int argc, char **argv)
+{
+ if (argc == 1)
+ return;
+
+ if (strcmp(argv[1], "USERNAME") == 0) {
+ monkey_login_handle_username(argc, argv);
+ } else if (strcmp(argv[1], "PASSWORD") == 0) {
+ monkey_login_handle_password(argc, argv);
+ } else if (strcmp(argv[1], "DESTROY") == 0) {
+ monkey_login_handle_destroy(argc, argv);
+ } else if (strcmp(argv[1], "GO") == 0) {
+ monkey_login_handle_go(argc, argv);
+ } else {
+ moutf(MOUT_ERROR, "LOGIN COMMAND UNKNOWN %s\n", argv[1]);
+ }
+}
diff --git a/frontends/monkey/401login.h b/frontends/monkey/401login.h
index e78355ea2..45a2a1b52 100644
--- a/frontends/monkey/401login.h
+++ b/frontends/monkey/401login.h
@@ -1,9 +1,39 @@
+/*
+ * Copyright 2018 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
-#include <stdbool.h>
+#ifndef NS_MONKEY_401LOGIN_H
+#define NS_MONKEY_401LOGIN_H
-#include "utils/nsurl.h"
#include "utils/errors.h"
+struct nsurl;
-void gui_401login_open(nsurl *url, const char *realm,
- nserror (*cb)(bool proceed, void *pw), void *cbpw);
+nserror gui_401login_open(struct nsurl *url,
+ const char *realm,
+ const char *username,
+ const char *password,
+ nserror (*cb)(struct nsurl *url,
+ const char *realm,
+ const char *username,
+ const char *password,
+ void *pw),
+ void *cbpw);
+
+void monkey_login_handle_command(int argc, char **argv);
+
+#endif
diff --git a/frontends/monkey/Makefile b/frontends/monkey/Makefile
index 86f1d912e..d2dae3e16 100644
--- a/frontends/monkey/Makefile
+++ b/frontends/monkey/Makefile
@@ -9,20 +9,38 @@
CWARNFLAGS += -Werror
-CFLAGS += -std=c99 -Dmonkey -Dnsmonkey -g \
- -D_BSD_SOURCE \
- -D_DEFAULT_SOURCE \
- -D_XOPEN_SOURCE=700 \
- -D_POSIX_C_SOURCE=200809L \
- -D_NETBSD_SOURCE \
+CFLAGS += -std=c99 \
+ -Dmonkey -Dnsmonkey -g \
-DMONKEY_RESPATH=\"$(NETSURF_MONKEY_RESOURCES)\"
LDFLAGS += -lm
# ---------------------------------------------------------------------------
-# Windows flag setup
+# Target setup
# ---------------------------------------------------------------------------
+# Path to monkey resources
+MONKEY_RESOURCES_DIR := $(FRONTEND_RESOURCES_DIR)
+
+# The filter and target for split messages
+MESSAGES_FILTER=monkey
+MESSAGES_TARGET=$(MONKEY_RESOURCES_DIR)
+
+# ---------------------------------------------------------------------------
+# HOST specific feature flags
+# ---------------------------------------------------------------------------
+
+# enable POSIX and XSI features.
+# everywhere but freebsd where the default set already has them enabled
+ifneq ($(HOST),FreeBSD)
+ CFLAGS += -D_POSIX_C_SOURCE=200809L \
+ -D_XOPEN_SOURCE=700 \
+ -D_BSD_SOURCE \
+ -D_DEFAULT_SOURCE \
+ -D_NETBSD_SOURCE
+endif
+
+# Windows flag setup
ifeq ($(HOST),Windows_NT)
CFLAGS += -U__STRICT_ANSI__
endif
@@ -32,8 +50,8 @@ endif
# ----------------------------------------------------------------------------
# S_MONKEY are sources purely for the MONKEY build
-S_FRONTEND := main.c filetype.c schedule.c bitmap.c plot.c browser.c \
- download.c 401login.c cert.c layout.c dispatch.c fetch.c
+S_FRONTEND := main.c output.c filetype.c schedule.c bitmap.c plot.c browser.c \
+ download.c 401login.c layout.c dispatch.c fetch.c
# This is the final source build list
diff --git a/frontends/monkey/Makefile.defaults b/frontends/monkey/Makefile.defaults
index d6a90a3dc..87b6f3ac4 100644
--- a/frontends/monkey/Makefile.defaults
+++ b/frontends/monkey/Makefile.defaults
@@ -9,5 +9,6 @@ NETSURF_USE_RSVG := NO
NETSURF_USE_NSSVG := NO
NETSURF_USE_ROSPRITE := NO
NETSURF_USE_HARU_PDF := NO
+NETSURF_FS_BACKING_STORE := YES
CFLAGS += -O2
diff --git a/frontends/monkey/Makefile.tools b/frontends/monkey/Makefile.tools
new file mode 100644
index 000000000..7546506ff
--- /dev/null
+++ b/frontends/monkey/Makefile.tools
@@ -0,0 +1,15 @@
+# -*- mode: makefile-gmake -*-
+##
+## monkey target tool setup
+##
+
+ifeq ($(origin GCCSDK_INSTALL_ENV),undefined)
+ PKG_CONFIG := pkg-config
+else
+ PKG_CONFIG := PKG_CONFIG_LIBDIR="$(GCCSDK_INSTALL_ENV)/lib/pkgconfig" pkg-config
+endif
+
+ifneq ($(origin GCCSDK_INSTALL_CROSSBIN),undefined)
+ CC := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc)
+ CXX := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++)
+endif
diff --git a/frontends/monkey/bitmap.c b/frontends/monkey/bitmap.c
index 83b8566b6..900dbca72 100644
--- a/frontends/monkey/bitmap.c
+++ b/frontends/monkey/bitmap.c
@@ -23,6 +23,7 @@
#include "utils/errors.h"
#include "netsurf/bitmap.h"
+#include "monkey/output.h"
#include "monkey/bitmap.h"
struct bitmap {
@@ -30,26 +31,26 @@ struct bitmap {
size_t rowstride;
int width;
int height;
- unsigned int state;
+ bool opaque;
};
-static void *bitmap_create(int width, int height, unsigned int state)
+static void *bitmap_create(int width, int height, enum gui_bitmap_flags flags)
{
struct bitmap *ret = calloc(sizeof(*ret), 1);
if (ret == NULL)
return NULL;
-
+
ret->width = width;
ret->height = height;
- ret->state = state;
-
+ ret->opaque = (flags & BITMAP_OPAQUE) == BITMAP_OPAQUE;
+
ret->ptr = calloc(width, height * 4);
-
+
if (ret->ptr == NULL) {
free(ret);
return NULL;
}
-
+
return ret;
}
@@ -63,23 +64,15 @@ static void bitmap_destroy(void *bitmap)
static void bitmap_set_opaque(void *bitmap, bool opaque)
{
struct bitmap *bmap = bitmap;
-
- if (opaque)
- bmap->state |= (BITMAP_OPAQUE);
- else
- bmap->state &= ~(BITMAP_OPAQUE);
-}
-static bool bitmap_test_opaque(void *bitmap)
-{
- return false;
+ bmap->opaque = opaque;
}
static bool bitmap_get_opaque(void *bitmap)
{
struct bitmap *bmap = bitmap;
-
- return (bmap->state & BITMAP_OPAQUE) == BITMAP_OPAQUE;
+
+ return bmap->opaque;
}
static unsigned char *bitmap_get_buffer(void *bitmap)
@@ -95,21 +88,9 @@ static size_t bitmap_get_rowstride(void *bitmap)
return bmap->width * 4;
}
-static size_t bitmap_get_bpp(void *bitmap)
-{
- /* OMG?! */
- return 4;
-}
-
-static bool bitmap_save(void *bitmap, const char *path, unsigned flags)
-{
- return true;
-}
-
static void bitmap_modified(void *bitmap)
{
- struct bitmap *bmap = bitmap;
- bmap->state |= BITMAP_MODIFIED;
+ return;
}
static int bitmap_get_width(void *bitmap)
@@ -127,7 +108,7 @@ static int bitmap_get_height(void *bitmap)
static nserror bitmap_render(struct bitmap *bitmap,
struct hlcache_handle *content)
{
- fprintf(stdout, "GENERIC BITMAP RENDER\n");
+ moutf(MOUT_GENERIC, "BITMAP RENDER");
return NSERROR_OK;
}
@@ -136,13 +117,10 @@ static struct gui_bitmap_table bitmap_table = {
.destroy = bitmap_destroy,
.set_opaque = bitmap_set_opaque,
.get_opaque = bitmap_get_opaque,
- .test_opaque = bitmap_test_opaque,
.get_buffer = bitmap_get_buffer,
.get_rowstride = bitmap_get_rowstride,
.get_width = bitmap_get_width,
.get_height = bitmap_get_height,
- .get_bpp = bitmap_get_bpp,
- .save = bitmap_save,
.modified = bitmap_modified,
.render = bitmap_render,
};
diff --git a/frontends/monkey/browser.c b/frontends/monkey/browser.c
index 1fbbbf0b1..49cc63c3b 100644
--- a/frontends/monkey/browser.c
+++ b/frontends/monkey/browser.c
@@ -32,6 +32,7 @@
#include "netsurf/browser_window.h"
#include "netsurf/plotters.h"
+#include "monkey/output.h"
#include "monkey/browser.h"
#include "monkey/plot.h"
@@ -42,7 +43,7 @@ static struct gui_window *gw_ring = NULL;
/* exported function documented in monkey/browser.h */
nserror monkey_warn_user(const char *warning, const char *detail)
{
- fprintf(stderr, "WARN %s %s\n", warning, detail);
+ moutf(MOUT_WARNING, "%s %s", warning, detail);
return NSERROR_OK;
}
@@ -50,14 +51,14 @@ struct gui_window *
monkey_find_window_by_num(uint32_t win_num)
{
struct gui_window *ret = NULL;
-
+
RING_ITERATE_START(struct gui_window, gw_ring, c_ring) {
if (c_ring->win_num == win_num) {
ret = c_ring;
RING_ITERATE_STOP(gw_ring, c_ring);
}
} RING_ITERATE_END(gw_ring, c_ring);
-
+
return ret;
}
@@ -77,28 +78,31 @@ gui_window_create(struct browser_window *bw,
struct gui_window *ret = calloc(sizeof(*ret), 1);
if (ret == NULL)
return NULL;
-
+
ret->win_num = win_ctr++;
ret->bw = bw;
-
+
ret->width = 800;
ret->height = 600;
-
- fprintf(stdout, "WINDOW NEW WIN %u FOR %p EXISTING %p NEWTAB %s CLONE %s\n",
- ret->win_num, bw, existing, flags & GW_CREATE_TAB ? "TRUE" : "FALSE",
- flags & GW_CREATE_CLONE ? "TRUE" : "FALSE");
- fprintf(stdout, "WINDOW SIZE WIN %u WIDTH %d HEIGHT %d\n",
- ret->win_num, ret->width, ret->height);
-
+
+ moutf(MOUT_WINDOW,
+ "NEW WIN %u FOR %p EXISTING %p NEWTAB %s CLONE %s",
+ ret->win_num, bw, existing,
+ flags & GW_CREATE_TAB ? "TRUE" : "FALSE",
+ flags & GW_CREATE_CLONE ? "TRUE" : "FALSE");
+ moutf(MOUT_WINDOW,
+ "SIZE WIN %u WIDTH %d HEIGHT %d",
+ ret->win_num, ret->width, ret->height);
+
RING_INSERT(gw_ring, ret);
-
+
return ret;
}
static void
gui_window_destroy(struct gui_window *g)
{
- fprintf(stdout, "WINDOW DESTROY WIN %u\n", g->win_num);
+ moutf(MOUT_WINDOW, "DESTROY WIN %u", g->win_num);
RING_REMOVE(gw_ring, g);
free(g);
}
@@ -106,7 +110,7 @@ gui_window_destroy(struct gui_window *g)
static void
gui_window_set_title(struct gui_window *g, const char *title)
{
- fprintf(stdout, "WINDOW TITLE WIN %u STR %s\n", g->win_num, title);
+ moutf(MOUT_WINDOW, "TITLE WIN %u STR %s", g->win_num, title);
}
/**
@@ -115,43 +119,43 @@ gui_window_set_title(struct gui_window *g, const char *title)
* \param g The gui window to measure content area of.
* \param width receives width of window
* \param height receives height of window
- * \param scaled whether to return scaled values
* \return NSERROR_OK on sucess and width and height updated.
*/
static nserror
-gui_window_get_dimensions(struct gui_window *g, int *width, int *height,
- bool scaled)
+gui_window_get_dimensions(struct gui_window *g, int *width, int *height)
{
- fprintf(stdout, "WINDOW GET_DIMENSIONS WIN %u WIDTH %d HEIGHT %d\n",
- g->win_num, g->width, g->height);
*width = g->width;
*height = g->height;
+ moutf(MOUT_WINDOW,
+ "GET_DIMENSIONS WIN %u WIDTH %d HEIGHT %d",
+ g->win_num, *width, *height);
+
return NSERROR_OK;
}
static void
gui_window_new_content(struct gui_window *g)
{
- fprintf(stdout, "WINDOW NEW_CONTENT WIN %u\n", g->win_num);
+ moutf(MOUT_WINDOW, "NEW_CONTENT WIN %u", g->win_num);
}
static void
gui_window_set_icon(struct gui_window *g, struct hlcache_handle *icon)
{
- fprintf(stdout, "WINDOW NEW_ICON WIN %u\n", g->win_num);
+ moutf(MOUT_WINDOW, "NEW_ICON WIN %u", g->win_num);
}
static void
gui_window_start_throbber(struct gui_window *g)
{
- fprintf(stdout, "WINDOW START_THROBBER WIN %u\n", g->win_num);
+ moutf(MOUT_WINDOW, "START_THROBBER WIN %u", g->win_num);
}
static void
gui_window_stop_throbber(struct gui_window *g)
{
- fprintf(stdout, "WINDOW STOP_THROBBER WIN %u\n", g->win_num);
+ moutf(MOUT_WINDOW, "STOP_THROBBER WIN %u", g->win_num);
}
@@ -171,7 +175,7 @@ gui_window_set_scroll(struct gui_window *gw, const struct rect *rect)
gw->scrollx = rect->x0;
gw->scrolly = rect->y0;
- fprintf(stdout, "WINDOW SET_SCROLL WIN %u X %d Y %d\n",
+ moutf(MOUT_WINDOW, "SET_SCROLL WIN %u X %d Y %d",
gw->win_num, rect->x0, rect->y0);
return NSERROR_OK;
}
@@ -187,15 +191,14 @@ gui_window_set_scroll(struct gui_window *gw, const struct rect *rect)
static nserror
monkey_window_invalidate_area(struct gui_window *gw, const struct rect *rect)
{
- fprintf(stdout, "WINDOW INVALIDATE_AREA WIN %u", gw->win_num);
-
if (rect != NULL) {
- fprintf(stdout,
- " X %d Y %d WIDTH %d HEIGHT %d\n",
- rect->x0, rect->y0,
- (rect->x1 - rect->x0), (rect->y1 - rect->y0));
+ moutf(MOUT_WINDOW,
+ "INVALIDATE_AREA WIN %u X %d Y %d WIDTH %d HEIGHT %d",
+ gw->win_num,
+ rect->x0, rect->y0,
+ (rect->x1 - rect->x0), (rect->y1 - rect->y0));
} else {
- fprintf(stdout," ALL\n");
+ moutf(MOUT_WINDOW, "INVALIDATE_AREA WIN %u ALL", gw->win_num);
}
return NSERROR_OK;
@@ -209,21 +212,21 @@ gui_window_update_extent(struct gui_window *g)
if (browser_window_get_extents(g->bw, false, &width, &height) != NSERROR_OK)
return;
- fprintf(stdout, "WINDOW UPDATE_EXTENT WIN %u WIDTH %d HEIGHT %d\n",
- g->win_num, width, height);
+ moutf(MOUT_WINDOW, "UPDATE_EXTENT WIN %u WIDTH %d HEIGHT %d",
+ g->win_num, width, height);
}
static void
gui_window_set_status(struct gui_window *g, const char *text)
{
- fprintf(stdout, "WINDOW SET_STATUS WIN %u STR %s\n", g->win_num, text);
+ moutf(MOUT_WINDOW, "SET_STATUS WIN %u STR %s", g->win_num, text);
}
static void
gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape)
{
const char *ptr_name = "UNKNOWN";
-
+
switch (shape) {
case GUI_POINTER_POINT:
ptr_name = "POINT";
@@ -285,21 +288,24 @@ gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape)
default:
break;
}
- fprintf(stdout, "WINDOW SET_POINTER WIN %u POINTER %s\n", g->win_num, ptr_name);
+
+ moutf(MOUT_WINDOW, "SET_POINTER WIN %u POINTER %s",
+ g->win_num, ptr_name);
}
static nserror
gui_window_set_url(struct gui_window *g, nsurl *url)
{
- fprintf(stdout, "WINDOW SET_URL WIN %u URL %s\n", g->win_num, nsurl_access(url));
+ moutf(MOUT_WINDOW, "SET_URL WIN %u URL %s",
+ g->win_num, nsurl_access(url));
return NSERROR_OK;
}
static bool
gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
{
- fprintf(stdout, "WINDOW GET_SCROLL WIN %u X %d Y %d\n",
- g->win_num, g->scrollx, g->scrolly);
+ moutf(MOUT_WINDOW, "GET_SCROLL WIN %u X %d Y %d",
+ g->win_num, g->scrollx, g->scrolly);
*sx = g->scrollx;
*sy = g->scrolly;
return true;
@@ -308,7 +314,7 @@ gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
static bool
gui_window_scroll_start(struct gui_window *g)
{
- fprintf(stdout, "WINDOW SCROLL_START WIN %u\n", g->win_num);
+ moutf(MOUT_WINDOW, "SCROLL_START WIN %u", g->win_num);
g->scrollx = g->scrolly = 0;
return true;
}
@@ -318,33 +324,127 @@ static void
gui_window_place_caret(struct gui_window *g, int x, int y, int height,
const struct rect *clip)
{
- fprintf(stdout, "WINDOW PLACE_CARET WIN %u X %d Y %d HEIGHT %d\n",
- g->win_num, x, y, height);
+ moutf(MOUT_WINDOW, "PLACE_CARET WIN %u X %d Y %d HEIGHT %d",
+ g->win_num, x, y, height);
}
static void
gui_window_remove_caret(struct gui_window *g)
{
- fprintf(stdout, "WINDOW REMOVE_CARET WIN %u\n", g->win_num);
+ moutf(MOUT_WINDOW, "REMOVE_CARET WIN %u", g->win_num);
}
static bool
gui_window_drag_start(struct gui_window *g, gui_drag_type type,
- const struct rect *rect)
+ const struct rect *rect)
{
- fprintf(stdout, "WINDOW SCROLL_START WIN %u TYPE %i\n", g->win_num, type);
+ moutf(MOUT_WINDOW, "SCROLL_START WIN %u TYPE %i", g->win_num, type);
return false;
}
static nserror
gui_window_save_link(struct gui_window *g, nsurl *url, const char *title)
{
- fprintf(stdout, "WINDOW SAVE_LINK WIN %u URL %s TITLE %s\n",
+ moutf(MOUT_WINDOW, "SAVE_LINK WIN %u URL %s TITLE %s",
g->win_num, nsurl_access(url), title);
return NSERROR_OK;
}
+static void
+gui_window_console_log(struct gui_window *g,
+ browser_window_console_source src,
+ const char *msg,
+ size_t msglen,
+ browser_window_console_flags flags)
+{
+ bool foldable = !!(flags & BW_CS_FLAG_FOLDABLE);
+ const char *src_text;
+ const char *level_text;
+
+ switch (src) {
+ case BW_CS_INPUT:
+ src_text = "client-input";
+ break;
+ case BW_CS_SCRIPT_ERROR:
+ src_text = "scripting-error";
+ break;
+ case BW_CS_SCRIPT_CONSOLE:
+ src_text = "scripting-console";
+ break;
+ default:
+ assert(0 && "Unknown scripting source");
+ src_text = "unknown";
+ break;
+ }
+
+ switch (flags & BW_CS_FLAG_LEVEL_MASK) {
+ case BW_CS_FLAG_LEVEL_DEBUG:
+ level_text = "DEBUG";
+ break;
+ case BW_CS_FLAG_LEVEL_LOG:
+ level_text = "LOG";
+ break;
+ case BW_CS_FLAG_LEVEL_INFO:
+ level_text = "INFO";
+ break;
+ case BW_CS_FLAG_LEVEL_WARN:
+ level_text = "WARN";
+ break;
+ case BW_CS_FLAG_LEVEL_ERROR:
+ level_text = "ERROR";
+ break;
+ default:
+ assert(0 && "Unknown console logging level");
+ level_text = "unknown";
+ break;
+ }
+
+ moutf(MOUT_WINDOW, "CONSOLE_LOG WIN %u SOURCE %s %sFOLDABLE %s %.*s",
+ g->win_num, src_text, foldable ? "" : "NOT-", level_text,
+ (int)msglen, msg);
+}
+
+static void
+gui_window_report_page_info(struct gui_window *g)
+{
+ const char *state = "***WAH***";
+
+ switch (browser_window_get_page_info_state(g->bw)) {
+ case PAGE_STATE_UNKNOWN:
+ state = "UNKNOWN";
+ break;
+
+ case PAGE_STATE_INTERNAL:
+ state = "INTERNAL";
+ break;
+
+ case PAGE_STATE_LOCAL:
+ state = "LOCAL";
+ break;
+
+ case PAGE_STATE_INSECURE:
+ state = "INSECURE";
+ break;
+
+ case PAGE_STATE_SECURE_OVERRIDE:
+ state = "SECURE_OVERRIDE";
+ break;
+ case PAGE_STATE_SECURE_ISSUES:
+ state = "SECURE_ISSUES";
+ break;
+
+ case PAGE_STATE_SECURE:
+ state = "SECURE";
+ break;
+
+ default:
+ assert(0 && "Monkey needs some lovin' here");
+ break;
+ }
+ moutf(MOUT_WINDOW, "PAGE_STATUS WIN %u STATUS %s",
+ g->win_num, state);
+}
/**** Handlers ****/
@@ -380,11 +480,11 @@ monkey_window_handle_destroy(int argc, char **argv)
{
struct gui_window *gw;
uint32_t nr = atoi((argc > 2) ? argv[2] : "-1");
-
+
gw = monkey_find_window_by_num(nr);
-
+
if (gw == NULL) {
- fprintf(stdout, "ERROR WINDOW NUM BAD\n");
+ moutf(MOUT_ERROR, "WINDOW NUM BAD");
} else {
browser_window_destroy(gw->bw);
}
@@ -397,16 +497,16 @@ monkey_window_handle_go(int argc, char **argv)
nsurl *url;
nsurl *ref_url = NULL;
nserror error;
-
+
if (argc < 4 || argc > 5) {
- fprintf(stdout, "ERROR WINDOW GO ARGS BAD\n");
+ moutf(MOUT_ERROR, "WINDOW GO ARGS BAD");
return;
}
-
+
gw = monkey_find_window_by_num(atoi(argv[2]));
-
+
if (gw == NULL) {
- fprintf(stdout, "ERROR WINDOW NUM BAD\n");
+ moutf(MOUT_ERROR, "WINDOW NUM BAD");
return;
}
@@ -436,6 +536,28 @@ monkey_window_handle_go(int argc, char **argv)
}
}
+/**
+ * handle WINDOW STOP command
+ */
+static void
+monkey_window_handle_stop(int argc, char **argv)
+{
+ struct gui_window *gw;
+ if (argc != 3) {
+ moutf(MOUT_ERROR, "WINDOW STOP ARGS BAD\n");
+ return;
+ }
+
+ gw = monkey_find_window_by_num(atoi(argv[2]));
+
+ if (gw == NULL) {
+ moutf(MOUT_ERROR, "WINDOW NUM BAD");
+ } else {
+ browser_window_stop(gw->bw);
+ }
+}
+
+
static void
monkey_window_handle_redraw(int argc, char **argv)
{
@@ -446,35 +568,35 @@ monkey_window_handle_redraw(int argc, char **argv)
.background_images = true,
.plot = monkey_plotters
};
-
+
if (argc != 3 && argc != 7) {
- fprintf(stdout, "ERROR WINDOW REDRAW ARGS BAD\n");
+ moutf(MOUT_ERROR, "WINDOW REDRAW ARGS BAD");
return;
}
gw = monkey_find_window_by_num(atoi(argv[2]));
-
+
if (gw == NULL) {
- fprintf(stdout, "ERROR WINDOW NUM BAD\n");
+ moutf(MOUT_ERROR, "WINDOW NUM BAD");
return;
}
-
+
clip.x0 = 0;
clip.y0 = 0;
clip.x1 = gw->width;
clip.y1 = gw->height;
-
+
if (argc == 7) {
clip.x0 = atoi(argv[3]);
clip.y0 = atoi(argv[4]);
clip.x1 = atoi(argv[5]);
clip.y1 = atoi(argv[6]);
}
-
+
NSLOG(netsurf, INFO, "Issue redraw");
- fprintf(stdout, "WINDOW REDRAW WIN %d START\n", atoi(argv[2]));
- browser_window_redraw(gw->bw, gw->scrollx, gw->scrolly, &clip, &ctx);
- fprintf(stdout, "WINDOW REDRAW WIN %d STOP\n", atoi(argv[2]));
+ moutf(MOUT_WINDOW, "REDRAW WIN %d START", atoi(argv[2]));
+ browser_window_redraw(gw->bw, gw->scrollx, gw->scrolly, &clip, &ctx);
+ moutf(MOUT_WINDOW, "REDRAW WIN %d STOP", atoi(argv[2]));
}
static void
@@ -482,39 +604,170 @@ monkey_window_handle_reload(int argc, char **argv)
{
struct gui_window *gw;
if (argc != 3 && argc != 4) {
- fprintf(stdout, "ERROR WINDOW RELOAD ARGS BAD\n");
+ moutf(MOUT_ERROR, "WINDOW RELOAD ARGS BAD\n");
+ return;
}
-
+
gw = monkey_find_window_by_num(atoi(argv[2]));
-
+
if (gw == NULL) {
- fprintf(stdout, "ERROR WINDOW NUM BAD\n");
+ moutf(MOUT_ERROR, "WINDOW NUM BAD");
} else {
browser_window_reload(gw->bw, argc == 4);
}
}
+static void
+monkey_window_handle_exec(int argc, char **argv)
+{
+ struct gui_window *gw;
+ if (argc < 5) {
+ moutf(MOUT_ERROR, "WINDOW EXEC ARGS BAD\n");
+ }
+
+ gw = monkey_find_window_by_num(atoi(argv[2]));
+
+ if (gw == NULL) {
+ moutf(MOUT_ERROR, "WINDOW NUM BAD");
+ } else {
+ /* Gather argv[4] onward into a string to pass to js_exec */
+ int total = 0;
+ for (int i = 4; i < argc; ++i) {
+ total += strlen(argv[i]) + 1;
+ }
+ char *cmd = calloc(total, 1);
+ if (cmd == NULL) {
+ moutf(MOUT_ERROR, "JS WIN %d RET ENOMEM", atoi(argv[2]));
+ return;
+ }
+ strcpy(cmd, argv[4]);
+ for (int i = 5; i < argc; ++i) {
+ strcat(cmd, " ");
+ strcat(cmd, argv[i]);
+ }
+ /* Now execute the JS */
+
+ moutf(MOUT_WINDOW, "JS WIN %d RET %s", atoi(argv[2]),
+ browser_window_exec(gw->bw, cmd, total - 1) ? "TRUE" : "FALSE");
+
+ free(cmd);
+ }
+}
+
+
+static void
+monkey_window_handle_click(int argc, char **argv)
+{
+ /* `WINDOW CLICK WIN` _%id%_ `X` _%num%_ `Y` _%num%_ `BUTTON` _%str%_ `KIND` _%str%_ */
+ /* 0 1 2 3 4 5 6 7 8 9 10 11 */
+ struct gui_window *gw;
+ if (argc != 12) {
+ moutf(MOUT_ERROR, "WINDOW CLICK ARGS BAD\n");
+ }
+
+ gw = monkey_find_window_by_num(atoi(argv[2]));
+
+ if (gw == NULL) {
+ moutf(MOUT_ERROR, "WINDOW NUM BAD");
+ } else {
+ int x = atoi(argv[5]);
+ int y = atoi(argv[7]);
+ browser_mouse_state mouse;
+ const char *button = argv[9];
+ const char *kind = argv[11];
+ if (strcmp(button, "LEFT") == 0) {
+ mouse = BROWSER_MOUSE_CLICK_1;
+ } else if (strcmp(button, "RIGHT") == 0) {
+ mouse = BROWSER_MOUSE_CLICK_2;
+ } else {
+ moutf(MOUT_ERROR, "WINDOW BUTTON BAD");
+ return;
+ }
+ if (strcmp(kind, "SINGLE") == 0) {
+ /* Nothing */
+ } else if (strcmp(kind, "DOUBLE") == 0) {
+ mouse |= BROWSER_MOUSE_DOUBLE_CLICK;
+ } else if (strcmp(kind, "TRIPLE") == 0) {
+ mouse |= BROWSER_MOUSE_TRIPLE_CLICK;
+ } else {
+ moutf(MOUT_ERROR, "WINDOW KIND BAD");
+ return;
+ }
+ browser_window_mouse_click(gw->bw, mouse, x, y);
+ }
+}
void
monkey_window_handle_command(int argc, char **argv)
{
if (argc == 1)
return;
-
+
if (strcmp(argv[1], "NEW") == 0) {
monkey_window_handle_new(argc, argv);
} else if (strcmp(argv[1], "DESTROY") == 0) {
monkey_window_handle_destroy(argc, argv);
} else if (strcmp(argv[1], "GO") == 0) {
monkey_window_handle_go(argc, argv);
+ } else if (strcmp(argv[1], "STOP") == 0) {
+ monkey_window_handle_stop(argc, argv);
} else if (strcmp(argv[1], "REDRAW") == 0) {
monkey_window_handle_redraw(argc, argv);
} else if (strcmp(argv[1], "RELOAD") == 0) {
monkey_window_handle_reload(argc, argv);
+ } else if (strcmp(argv[1], "EXEC") == 0) {
+ monkey_window_handle_exec(argc, argv);
+ } else if (strcmp(argv[1], "CLICK") == 0) {
+ monkey_window_handle_click(argc, argv);
} else {
- fprintf(stdout, "ERROR WINDOW COMMAND UNKNOWN %s\n", argv[1]);
+ moutf(MOUT_ERROR, "WINDOW COMMAND UNKNOWN %s\n", argv[1]);
}
-
+
+}
+
+/**
+ * process miscellaneous window events
+ *
+ * \param gw The window receiving the event.
+ * \param event The event code.
+ * \return NSERROR_OK when processed ok
+ */
+static nserror
+gui_window_event(struct gui_window *gw, enum gui_window_event event)
+{
+ switch (event) {
+ case GW_EVENT_UPDATE_EXTENT:
+ gui_window_update_extent(gw);
+ break;
+
+ case GW_EVENT_REMOVE_CARET:
+ gui_window_remove_caret(gw);
+ break;
+
+ case GW_EVENT_SCROLL_START:
+ gui_window_scroll_start(gw);
+ break;
+
+ case GW_EVENT_NEW_CONTENT:
+ gui_window_new_content(gw);
+ break;
+
+ case GW_EVENT_START_THROBBER:
+ gui_window_start_throbber(gw);
+ break;
+
+ case GW_EVENT_STOP_THROBBER:
+ gui_window_stop_throbber(gw);
+ break;
+
+ case GW_EVENT_PAGE_INFO_CHANGE:
+ gui_window_report_page_info(gw);
+ break;
+
+ default:
+ break;
+ }
+ return NSERROR_OK;
}
static struct gui_window_table window_table = {
@@ -524,7 +777,7 @@ static struct gui_window_table window_table = {
.get_scroll = gui_window_get_scroll,
.set_scroll = gui_window_set_scroll,
.get_dimensions = gui_window_get_dimensions,
- .update_extent = gui_window_update_extent,
+ .event = gui_window_event,
.set_title = gui_window_set_title,
.set_url = gui_window_set_url,
@@ -532,13 +785,10 @@ static struct gui_window_table window_table = {
.set_status = gui_window_set_status,
.set_pointer = gui_window_set_pointer,
.place_caret = gui_window_place_caret,
- .remove_caret = gui_window_remove_caret,
.drag_start = gui_window_drag_start,
.save_link = gui_window_save_link,
- .scroll_start = gui_window_scroll_start,
- .new_content = gui_window_new_content,
- .start_throbber = gui_window_start_throbber,
- .stop_throbber = gui_window_stop_throbber,
+
+ .console_log = gui_window_console_log,
};
struct gui_window_table *monkey_window_table = &window_table;
diff --git a/frontends/monkey/cert.c b/frontends/monkey/cert.c
deleted file mode 100644
index a19975527..000000000
--- a/frontends/monkey/cert.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2011 Daniel Silverstone <dsilvers@digital-scurf.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "utils/ring.h"
-#include "utils/nsurl.h"
-
-#include "monkey/cert.h"
-
-typedef struct monkey_cert {
- struct monkey_cert *r_next, *r_prev;
- uint32_t num;
- char *host; /* Ignore */
- nserror (*cb)(bool,void*);
- void *pw;
-} monkey_cert_t;
-
-static monkey_cert_t *cert_ring = NULL;
-static uint32_t cert_ctr = 0;
-
-nserror
-gui_cert_verify(nsurl *url, const struct ssl_cert_info *certs,
- unsigned long num, nserror (*cb)(bool proceed, void *pw),
- void *cbpw)
-{
- monkey_cert_t *m4t = calloc(sizeof(*m4t), 1);
- if (m4t == NULL) {
- return NSERROR_NOMEM;
- }
- m4t->cb = cb;
- m4t->pw = cbpw;
- m4t->num = cert_ctr++;
-
- RING_INSERT(cert_ring, m4t);
-
- fprintf(stdout, "SSLCERT VERIFY CERT %u URL %s\n",
- m4t->num, nsurl_access(url));
-
- return NSERROR_OK;
-}
-
-
diff --git a/frontends/monkey/dispatch.c b/frontends/monkey/dispatch.c
index e60325cf1..08bd352d5 100644
--- a/frontends/monkey/dispatch.c
+++ b/frontends/monkey/dispatch.c
@@ -29,7 +29,7 @@
typedef struct cmdhandler {
struct cmdhandler *r_next, *r_prev;
- const char *cmd;
+ char *cmd;
handle_command_fn fn;
} monkey_cmdhandler_t;
@@ -50,6 +50,17 @@ monkey_register_handler(const char *cmd, handle_command_fn fn)
}
void
+monkey_free_handlers(void)
+{
+ while (handler_ring != NULL) {
+ monkey_cmdhandler_t *handler = handler_ring;
+ RING_REMOVE(handler_ring, handler);
+ free(handler->cmd);
+ free(handler);
+ }
+}
+
+void
monkey_process_command(void)
{
char buffer[PATH_MAX];
diff --git a/frontends/monkey/dispatch.h b/frontends/monkey/dispatch.h
index dc6e50a0b..11b1c0239 100644
--- a/frontends/monkey/dispatch.h
+++ b/frontends/monkey/dispatch.h
@@ -25,4 +25,6 @@ nserror monkey_register_handler(const char *cmd, handle_command_fn fn);
void monkey_process_command(void);
+void monkey_free_handlers(void);
+
#endif /* NETSURF_MONKEY_DISPATCH_H */
diff --git a/frontends/monkey/download.c b/frontends/monkey/download.c
index 5c9ce1b53..b9ca1746f 100644
--- a/frontends/monkey/download.c
+++ b/frontends/monkey/download.c
@@ -25,6 +25,7 @@
#include "netsurf/download.h"
#include "desktop/download.h"
+#include "monkey/output.h"
#include "monkey/browser.h"
static uint32_t dwin_ctr = 0;
@@ -33,6 +34,7 @@ struct gui_download_window {
struct gui_download_window *r_next;
struct gui_download_window *r_prev;
struct gui_window *g;
+ download_context *dlctx;
uint32_t dwin_num;
char *host; /* ignore */
};
@@ -48,11 +50,12 @@ gui_download_window_create(download_context *ctx,
return NULL;
ret->g = parent;
ret->dwin_num = dwin_ctr++;
+ ret->dlctx = ctx;
RING_INSERT(dw_ring, ret);
- fprintf(stdout, "DOWNLOAD_WINDOW CREATE DWIN %u WIN %u\n",
- ret->dwin_num, parent->win_num);
+ moutf(MOUT_DOWNLOAD, "CREATE DWIN %u WIN %u",
+ ret->dwin_num, parent->win_num);
return ret;
}
@@ -61,7 +64,7 @@ static nserror
gui_download_window_data(struct gui_download_window *dw,
const char *data, unsigned int size)
{
- fprintf(stdout, "DOWNLOAD_WINDOW DATA DWIN %u SIZE %u DATA %s\n",
+ moutf(MOUT_DOWNLOAD, "DATA DWIN %u SIZE %u DATA %s",
dw->dwin_num, size, data);
return NSERROR_OK;
}
@@ -70,16 +73,15 @@ static void
gui_download_window_error(struct gui_download_window *dw,
const char *error_msg)
{
- fprintf(stdout, "DOWNLOAD_WINDOW ERROR DWIN %u ERROR %s\n",
- dw->dwin_num, error_msg);
+ moutf(MOUT_DOWNLOAD, "ERROR DWIN %u ERROR %s", dw->dwin_num, error_msg);
}
static void
gui_download_window_done(struct gui_download_window *dw)
{
- fprintf(stdout, "DOWNLOAD_WINDOW DONE DWIN %u\n",
- dw->dwin_num);
+ moutf(MOUT_DOWNLOAD, "DONE DWIN %u", dw->dwin_num);
RING_REMOVE(dw_ring, dw);
+ download_context_destroy(dw->dlctx);
free(dw);
}
diff --git a/frontends/monkey/farmer.py b/frontends/monkey/farmer.py
deleted file mode 100644
index d4b4b1e21..000000000
--- a/frontends/monkey/farmer.py
+++ /dev/null
@@ -1,363 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2017 Daniel Silverstone <dsilvers@digital-scurf.org>
-#
-# This file is part of NetSurf, http://www.netsurf-browser.org/
-#
-# NetSurf is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# NetSurf is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-"""
-Monkey Farmer
-
-The monkey farmer is a wrapper around `nsmonkey` which can be used to simplify
-access to the monkey behaviours and ultimately to write useful tests in an
-expressive but not overcomplicated DSLish way. Tests are, ultimately, still
-Python code.
-
-"""
-
-import asyncore
-import os
-import socket
-import subprocess
-import time
-
-#monkey_cmd = ['./nsmonkey', '--accept_language=fr']
-monkey_cmd = ['./nsmonkey']
-
-class MonkeyFarmer(asyncore.dispatcher):
- def __init__(self, online, quiet=False):
- (mine, monkeys) = socket.socketpair()
-
- asyncore.dispatcher.__init__(self, sock=mine)
-
- self.monkey = subprocess.Popen(
- monkey_cmd,
- stdin=monkeys,
- stdout=monkeys,
- close_fds=[mine])
-
- monkeys.close()
-
- self.buffer = ""
- self.incoming = ""
- self.lines = []
- self.scheduled = []
- self.deadmonkey = False
- self.online = online
- self.quiet = quiet
-
- def handle_connect(self):
- pass
-
- def handle_read(self):
- got = self.recv(8192)
- if got == "" or got is None:
- self.deadmonkey = True
- return
- self.incoming += got
- if "\n" in self.incoming:
- lines = self.incoming.split("\n")
- self.incoming = lines.pop()
- self.lines = lines
-
- def writable(self):
- return (len(self.buffer) > 0)
-
- def handle_write(self):
- sent = self.send(self.buffer)
- self.buffer = self.buffer[sent:]
-
- def tell_monkey(self, *args):
- cmd = (" ".join(args))
- if not self.quiet:
- print ">>> %s" % cmd
- self.buffer += "%s\n" % cmd
-
- def monkey_says(self, line):
- if not self.quiet:
- print "<<< %s" % line
- self.online(line)
-
- def schedule_event(self, event, secs=None, when=None):
- assert(secs is not None or when is not None)
- if when is None:
- when = time.time() + secs
- self.scheduled.append((when, event))
- self.scheduled.sort(lambda a,b: cmp(a[0],b[0]))
-
- def unschedule_event(self, event):
- self.scheduled = [x for x in self.scheduled if x[1] != event]
-
- def loop(self, once=False):
- if len(self.lines) > 0:
- self.monkey_says(self.lines.pop(0))
- if once:
- return
- while not self.deadmonkey:
- now = time.time()
- while len(self.scheduled) > 0 and now >= self.scheduled[0][0]:
- func = self.scheduled[0][1]
- self.scheduled.pop(0)
- func(self)
- now = time.time()
- if len(self.scheduled) > 0:
- next = self.scheduled[0][0]
- asyncore.loop(timeout=next-now, count=1)
- else:
- asyncore.loop(count=1)
- if len(self.lines) > 0:
- self.monkey_says(self.lines.pop(0))
- if once:
- break
-
-class Browser:
- def __init__(self, quiet=False):
- self.farmer = MonkeyFarmer(online=self.on_monkey_line, quiet=quiet)
- self.windows = {}
- self.current_draw_target = None
-
- def pass_options(self, *opts):
- if len(opts) > 0:
- self.farmer.tell_monkey("OPTIONS " + (" ".join(opts)))
-
- def on_monkey_line(self, line):
- parts = line.split(" ")
- handler = getattr(self, "handle_" + parts[0], None)
- if handler is not None:
- handler(*parts[1:])
-
- def quit(self):
- self.farmer.tell_monkey("QUIT")
-
- def quit_and_wait(self):
- self.quit()
- self.farmer.loop()
-
- def handle_GENERIC(self, what, *args):
- pass
-
- def handle_WINDOW(self, action, _win, winid, *args):
- if action == "NEW":
- new_win = BrowserWindow(self, winid, *args)
- self.windows[winid] = new_win
- else:
- win = self.windows.get(winid, None)
- if win is None:
- print " Unknown window id %s" % winid
- else:
- win.handle(action, *args)
-
- def handle_PLOT(self, *args):
- if self.current_draw_target is not None:
- self.current_draw_target.handle_plot(*args)
-
- def new_window(self, url=None):
- if url is None:
- self.farmer.tell_monkey("WINDOW NEW")
- else:
- self.farmer.tell_monkey("WINDOW NEW %s" % url)
- wins_known = set(self.windows.keys())
- while len(set(self.windows.keys()).difference(wins_known)) == 0:
- self.farmer.loop(once=True)
- poss_wins = set(self.windows.keys()).difference(wins_known)
- return self.windows[poss_wins.pop()]
-
-
-class BrowserWindow:
- def __init__(self, browser, winid, _for, coreid, _existing, otherid, _newtab, newtab, _clone, clone):
- self.alive = True
- self.browser = browser
- self.winid = winid
- self.coreid = coreid
- self.existing = browser.windows.get(otherid, None)
- self.newtab = newtab == "TRUE"
- self.clone = clone == "TRUE"
- self.width = 0
- self.height = 0
- self.title = ""
- self.throbbing = False
- self.scrollx = 0
- self.scrolly = 0
- self.content_width = 0
- self.content_height = 0
- self.status = ""
- self.pointer = ""
- self.scale = 1.0
- self.url = ""
- self.plotted = []
- self.plotting = False
-
- def kill(self):
- self.browser.farmer.tell_monkey("WINDOW DESTROY %s" % self.winid)
-
- def go(self, url, referer = None):
- if referer is None:
- self.browser.farmer.tell_monkey("WINDOW GO %s %s" % (
- self.winid, url))
- else:
- self.browser.farmer.tell_monkey("WINDOW GO %s %s %s" % (
- self.winid, url, referer))
-
- def reload(self):
- self.browser.farmer.tell_monkey("WINDOW RELOAD %s" % self.winid)
-
- def redraw(self, coords=None):
- if coords is None:
- self.browser.farmer.tell_monkey("WINDOW REDRAW %s" % self.winid)
- else:
- self.browser.farmer.tell_monkey("WINDOW REDRAW %s %s" % (
- self.winid, (" ".join(coords))))
-
- def handle(self, action, *args):
- handler = getattr(self, "handle_window_" + action, None)
- if handler is not None:
- handler(*args)
-
- def handle_window_SIZE(self, _width, width, _height, height):
- self.width = int(width)
- self.height = int(height)
-
- def handle_window_DESTROY(self):
- self.alive = False
-
- def handle_window_TITLE(self, _str, *title):
- self.title = " ".join(title)
-
- def handle_window_REDRAW(self):
- pass
-
- def handle_window_GET_DIMENSIONS(self, _width, width, _height, height):
- self.width = width
- self.height = height
-
- def handle_window_NEW_CONTENT(self):
- pass
-
- def handle_window_NEW_ICON(self):
- pass
-
- def handle_window_START_THROBBER(self):
- self.throbbing = True
-
- def handle_window_STOP_THROBBER(self):
- self.throbbing = False
-
- def handle_window_SET_SCROLL(self, _x, x, _y, y):
- self.scrollx = int(x)
- self.scrolly = int(y)
-
- def handle_window_UPDATE_BOX(self, _x, x, _y, y, _width, width, _height, height):
- x = int(x)
- y = int(y)
- width = int(width)
- height = int(height)
- pass
-
- def handle_window_UPDATE_EXTENT(self, _width, width, _height, height):
- self.content_width = int(width)
- self.content_height = int(height)
-
- def handle_window_SET_STATUS(self, _str, *status):
- self.status = (" ".join(status))
-
- def handle_window_SET_POINTER(self, _ptr, ptr):
- self.pointer = ptr
-
- def handle_window_SET_SCALE(self, _scale, scale):
- self.scale = float(scale)
-
- def handle_window_SET_URL(self, _url, url):
- self.url = url
-
- def handle_window_GET_SCROLL(self, _x, x, _y, y):
- self.scrollx = int(x)
- self.scrolly = int(y)
-
- def handle_window_SCROLL_START(self):
- self.scrollx = 0
- self.scrolly = 0
-
- def handle_window_REDRAW(self, act):
- if act == "START":
- self.browser.current_draw_target = self
- self.plotted = []
- self.plotting = True
- else:
- self.browser.current_draw_target = None
- self.plotting = False
-
- def load_page(self, url=None, referer=None):
- if url is not None:
- self.go(url, referer)
- self.wait_loaded()
-
- def reload(self):
- self.browser.farmer.tell_monkey("WINDOW RELOAD %s" % self.winid)
- self.wait_loaded()
-
- def wait_loaded(self):
- while not self.throbbing:
- self.browser.farmer.loop(once=True)
- while self.throbbing:
- self.browser.farmer.loop(once=True)
-
- def handle_plot(self, *args):
- self.plotted.append(args)
-
- def redraw(self, coords=None):
- if coords is None:
- self.browser.farmer.tell_monkey("WINDOW REDRAW %s" % self.winid)
- else:
- self.browser.farmer.tell_monkey("WINDOW REDRAW %s %s" % (
- self.winid, (" ".join(coords))))
- while not self.plotting:
- self.browser.farmer.loop(once=True)
- while self.plotting:
- self.browser.farmer.loop(once=True)
- return self.plotted
-
-
-# Simple test is as follows...
-
-browser = Browser(quiet=True)
-
-win = browser.new_window()
-
-fname = "test/js/inline-doc-write-simple.html"
-full_fname = os.path.join(os.getcwd(), fname)
-
-browser.pass_options("--enable_javascript=0")
-win.load_page("file://" + full_fname)
-
-print("Loaded, URL is %s" % win.url)
-
-cmds = win.redraw()
-print("Received %d plot commands" % len(cmds))
-for cmd in cmds:
- if cmd[0] == "TEXT":
- print "%s %s -> %s" % (cmd[2], cmd[4], (" ".join(cmd[6:])))
-
-
-browser.pass_options("--enable_javascript=1")
-win.load_page("file://" + full_fname)
-
-print("Loaded, URL is %s" % win.url)
-
-cmds = win.redraw()
-print("Received %d plot commands" % len(cmds))
-for cmd in cmds:
- if cmd[0] == "TEXT":
- print "%s %s -> %s" % (cmd[2], cmd[4], (" ".join(cmd[6:])))
-
-browser.quit_and_wait()
diff --git a/frontends/monkey/fetch.h b/frontends/monkey/fetch.h
index f146e2ef8..2881e92c5 100644
--- a/frontends/monkey/fetch.h
+++ b/frontends/monkey/fetch.h
@@ -19,6 +19,6 @@
#ifndef NS_MONKEY_FETCH_H
#define NS_MONKEY_FETCH_H
-struct gui_fetch_table *monkey_fetch_table;
+extern struct gui_fetch_table *monkey_fetch_table;
#endif /* NS_MONKEY_FETCH_H */
diff --git a/frontends/monkey/filetype.c b/frontends/monkey/filetype.c
index 65c84f9bd..37853a63d 100644
--- a/frontends/monkey/filetype.c
+++ b/frontends/monkey/filetype.c
@@ -69,8 +69,10 @@ void monkey_fetch_filetype_init(const char *mimefile)
hash_add(mime_hash, "html", "text/html");
hash_add(mime_hash, "jpg", "image/jpeg");
hash_add(mime_hash, "jpeg", "image/jpeg");
+ hash_add(mime_hash, "bmp", "image/bmp");
hash_add(mime_hash, "gif", "image/gif");
hash_add(mime_hash, "png", "image/png");
+ hash_add(mime_hash, "ico", "image/ico");
hash_add(mime_hash, "jng", "image/jng");
hash_add(mime_hash, "mng", "image/mng");
hash_add(mime_hash, "webp", "image/webp");
@@ -108,9 +110,9 @@ void monkey_fetch_filetype_init(const char *mimefile)
type = ptr;
- /* search for the first non-whitespace char or NUL or
+ /* search for the first whitespace char or NUL or
* NL */
- while (*ptr && (!ascii_is_space(*ptr)) && *ptr != '\n')
+ while (*ptr && (!ascii_is_space(*ptr)))
ptr++;
if (*ptr == '\0' || *ptr == '\n') {
@@ -133,8 +135,7 @@ void monkey_fetch_filetype_init(const char *mimefile)
/* search for the first whitespace char or
* NUL or NL which is the end of the ext.
*/
- while (*ptr && (!ascii_is_space(*ptr)) &&
- *ptr != '\n')
+ while (*ptr && (!ascii_is_space(*ptr)))
ptr++;
if (*ptr == '\0' || *ptr == '\n') {
diff --git a/frontends/monkey/layout.c b/frontends/monkey/layout.c
index 7b7223144..0d6a3b4dc 100644
--- a/frontends/monkey/layout.c
+++ b/frontends/monkey/layout.c
@@ -33,7 +33,7 @@ static nserror nsfont_width(const plot_font_style_t *fstyle,
const char *string, size_t length,
int *width)
{
- *width = (fstyle->size * utf8_bounded_length(string, length)) / FONT_SIZE_SCALE;
+ *width = (fstyle->size * utf8_bounded_length(string, length)) / PLOT_STYLE_SCALE;
return NSERROR_OK;
}
@@ -53,10 +53,10 @@ static nserror nsfont_position_in_string(const plot_font_style_t *fstyle,
const char *string, size_t length,
int x, size_t *char_offset, int *actual_x)
{
- *char_offset = x / (fstyle->size / FONT_SIZE_SCALE);
+ *char_offset = x / (fstyle->size / PLOT_STYLE_SCALE);
if (*char_offset > length)
*char_offset = length;
- *actual_x = *char_offset * (fstyle->size / FONT_SIZE_SCALE);
+ *actual_x = *char_offset * (fstyle->size / PLOT_STYLE_SCALE);
return NSERROR_OK;
}
@@ -88,7 +88,7 @@ static nserror nsfont_split(const plot_font_style_t *fstyle,
const char *string, size_t length,
int x, size_t *char_offset, int *actual_x)
{
- int c_off = *char_offset = x / (fstyle->size / FONT_SIZE_SCALE);
+ int c_off = *char_offset = x / (fstyle->size / PLOT_STYLE_SCALE);
if (*char_offset > length) {
*char_offset = length;
} else {
@@ -104,7 +104,7 @@ static nserror nsfont_split(const plot_font_style_t *fstyle,
}
}
}
- *actual_x = *char_offset * (fstyle->size / FONT_SIZE_SCALE);
+ *actual_x = *char_offset * (fstyle->size / PLOT_STYLE_SCALE);
return NSERROR_OK;
}
diff --git a/frontends/monkey/main.c b/frontends/monkey/main.c
index 53cde5a72..463f0bea6 100644
--- a/frontends/monkey/main.c
+++ b/frontends/monkey/main.c
@@ -23,6 +23,8 @@
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
+#include <errno.h>
+#include <signal.h>
#include "utils/config.h"
#include "utils/sys_time.h"
@@ -36,10 +38,11 @@
#include "netsurf/url_db.h"
#include "netsurf/cookie_db.h"
#include "content/fetch.h"
+#include "content/backing_store.h"
+#include "monkey/output.h"
#include "monkey/dispatch.h"
#include "monkey/browser.h"
-#include "monkey/cert.h"
#include "monkey/401login.h"
#include "monkey/filetype.h"
#include "monkey/fetch.h"
@@ -66,11 +69,12 @@ static bool monkey_done = false;
*/
static void die(const char * const error)
{
- fprintf(stderr, "DIE %s\n", error);
+ moutf(MOUT_DIE, "%s", error);
exit(EXIT_FAILURE);
}
-/** obtain language from environment
+/**
+ * obtain language from environment
*
* start with GNU extension LANGUAGE environment variable and then try
* POSIX variables LC_ALL, LC_MESSAGES and LANG
@@ -104,7 +108,8 @@ static const char *get_language(void)
}
-/** provide a string vector of languages in preference order
+/**
+ * provide a string vector of languages in preference order
*
* environment variables are processed to aquire a colon separated
* list of languages which are converted into a string vector. The
@@ -171,7 +176,16 @@ static const char * const *get_languagev(void)
return &langv[0];
}
-/* Stolen from gtk/gui.c */
+/**
+ * Create an array of valid paths to search for resources.
+ *
+ * The idea is that all the complex path computation to find resources
+ * is performed here, once, rather than every time a resource is
+ * searched for.
+ *
+ * \param resource_path A shell style colon separated path list
+ * \return A string vector of valid paths where resources can be found
+ */
static char **
nsmonkey_init_resource(const char *resource_path)
{
@@ -199,7 +213,17 @@ static void monkey_quit(void)
static nserror gui_launch_url(struct nsurl *url)
{
- fprintf(stdout, "GENERIC LAUNCH URL %s\n", nsurl_access(url));
+ moutf(MOUT_GENERIC, "LAUNCH URL %s", nsurl_access(url));
+ return NSERROR_OK;
+}
+
+static nserror gui_present_cookies(const char *search_term)
+{
+ if (search_term != NULL) {
+ moutf(MOUT_GENERIC, "PRESENT_COOKIES %s", search_term);
+ } else {
+ moutf(MOUT_GENERIC, "PRESENT_COOKIES");
+ }
return NSERROR_OK;
}
@@ -243,12 +267,11 @@ static bool nslog_stream_configure(FILE *fptr)
static struct gui_misc_table monkey_misc_table = {
.schedule = monkey_schedule,
- .warning = monkey_warn_user,
.quit = monkey_quit,
.launch_url = gui_launch_url,
- .cert_verify = gui_cert_verify,
.login = gui_401login_open,
+ .present_cookies = gui_present_cookies,
};
static void monkey_run(void)
@@ -262,6 +285,9 @@ static void monkey_run(void)
while (!monkey_done) {
+ /* discover the next scheduled event time */
+ schedtm = monkey_schedule_run();
+
/* clears fdset */
fetch_fdset(&read_fd_set, &write_fd_set, &exc_fd_set, &max_fd);
@@ -272,14 +298,11 @@ static void monkey_run(void)
FD_SET(0, &read_fd_set);
FD_SET(0, &exc_fd_set);
- /* discover the next scheduled event time */
- schedtm = monkey_schedule_run();
-
/* setup timeout */
switch (schedtm) {
case -1:
NSLOG(netsurf, INFO, "Iterate blocking");
- fprintf(stdout, "GENERIC POLL BLOCKING\n");
+ moutf(MOUT_GENERIC, "POLL BLOCKING");
timeout = NULL;
break;
@@ -292,7 +315,7 @@ static void monkey_run(void)
default:
NSLOG(netsurf, INFO, "Iterate non-blocking");
- fprintf(stdout, "GENERIC POLL TIMED %d\n", schedtm);
+ moutf(MOUT_GENERIC, "POLL TIMED %d", schedtm);
tv.tv_sec = schedtm / 1000; /* miliseconds to seconds */
tv.tv_usec = (schedtm % 1000) * 1000; /* remainder to microseconds */
timeout = &tv;
@@ -305,6 +328,7 @@ static void monkey_run(void)
&exc_fd_set,
timeout);
if (rdy_fd < 0) {
+ NSLOG(netsurf, CRITICAL, "Unable to select: %s", strerror(errno));
monkey_done = true;
} else if (rdy_fd > 0) {
if (FD_ISSET(0, &read_fd_set)) {
@@ -314,6 +338,53 @@ static void monkey_run(void)
}
}
+#if (!defined(NDEBUG) && defined(HAVE_EXECINFO))
+#include <execinfo.h>
+static void *backtrace_buffer[4096];
+
+void
+__assert_fail(const char *__assertion, const char *__file,
+ unsigned int __line, const char *__function)
+{
+ int frames;
+ fprintf(stderr,
+ "MONKEY: Assertion failure!\n"
+ "%s:%d: %s: Assertion `%s` failed.\n",
+ __file, __line, __function, __assertion);
+
+ frames = backtrace(&backtrace_buffer[0], 4096);
+ if (frames > 0 && frames < 4096) {
+ fprintf(stderr, "Backtrace:\n");
+ fflush(stderr);
+ backtrace_symbols_fd(&backtrace_buffer[0], frames, 2);
+ }
+
+ abort();
+}
+
+static void
+signal_handler(int sig)
+{
+ int frames;
+ fprintf(stderr, "Caught signal %s (%d)\n",
+ ((sig == SIGSEGV) ? "SIGSEGV" :
+ ((sig == SIGILL) ? "SIGILL" :
+ ((sig == SIGFPE) ? "SIGFPE" :
+ ((sig == SIGBUS) ? "SIGBUS" :
+ "unknown signal")))),
+ sig);
+ frames = backtrace(&backtrace_buffer[0], 4096);
+ if (frames > 0 && frames < 4096) {
+ fprintf(stderr, "Backtrace:\n");
+ fflush(stderr);
+ backtrace_symbols_fd(&backtrace_buffer[0], frames, 2);
+ }
+
+ abort();
+}
+
+#endif
+
int
main(int argc, char **argv)
{
@@ -328,8 +399,18 @@ main(int argc, char **argv)
.fetch = monkey_fetch_table,
.bitmap = monkey_bitmap_table,
.layout = monkey_layout_table,
+ .llcache = filesystem_llcache_table,
};
+#if (!defined(NDEBUG) && defined(HAVE_EXECINFO))
+ /* Catch segfault, illegal instructions and fp exceptions */
+ signal(SIGSEGV, signal_handler);
+ signal(SIGILL, signal_handler);
+ signal(SIGFPE, signal_handler);
+ /* It's unlikely, but SIGBUS could happen on some platforms */
+ signal(SIGBUS, signal_handler);
+#endif
+
ret = netsurf_register(&monkey_table);
if (ret != NSERROR_OK) {
die("NetSurf operation table failed registration");
@@ -377,6 +458,12 @@ main(int argc, char **argv)
urldb_load(nsoption_charp(url_file));
urldb_load_cookies(nsoption_charp(cookie_file));
+ /* Free resource paths now we're done finding resources */
+ for (char **s = respaths; *s != NULL; s++) {
+ free(*s);
+ }
+ free(respaths);
+
ret = monkey_register_handler("QUIT", quit_handler);
if (ret != NSERROR_OK) {
die("quit handler failed to register");
@@ -392,14 +479,20 @@ main(int argc, char **argv)
die("options handler failed to register");
}
- fprintf(stdout, "GENERIC STARTED\n");
+ ret = monkey_register_handler("LOGIN", monkey_login_handle_command);
+ if (ret != NSERROR_OK) {
+ die("login handler failed to register");
+ }
+
+
+ moutf(MOUT_GENERIC, "STARTED");
monkey_run();
- fprintf(stdout, "GENERIC CLOSING_DOWN\n");
+ moutf(MOUT_GENERIC, "CLOSING_DOWN");
monkey_kill_browser_windows();
netsurf_exit();
- fprintf(stdout, "GENERIC FINISHED\n");
+ moutf(MOUT_GENERIC, "FINISHED");
/* finalise options */
nsoption_finalise(nsoptions, nsoptions_default);
@@ -407,5 +500,8 @@ main(int argc, char **argv)
/* finalise logging */
nslog_finalise();
+ /* And free any monkey-specific bits */
+ monkey_free_handlers();
+
return 0;
}
diff --git a/frontends/monkey/options.h b/frontends/monkey/options.h
index 57cce7e1f..8f6dd8b42 100644
--- a/frontends/monkey/options.h
+++ b/frontends/monkey/options.h
@@ -16,14 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_MONKEY_OPTIONS_H_
-#define _NETSURF_MONKEY_OPTIONS_H_
+#ifndef NETSURF_MONKEY_OPTIONS_H_
+#define NETSURF_MONKEY_OPTIONS_H_
/* currently nothing here */
#endif
-NSOPTION_BOOL(render_resample, true)
NSOPTION_BOOL(downloads_clear, false)
NSOPTION_BOOL(request_overwrite, true)
NSOPTION_STRING(downloads_directory, NULL)
@@ -31,7 +30,6 @@ NSOPTION_STRING(url_file, NULL)
NSOPTION_BOOL(show_single_tab, false)
NSOPTION_INTEGER(button_type, 0)
NSOPTION_BOOL(disable_popups, false)
-NSOPTION_BOOL(disable_plugins, false)
NSOPTION_INTEGER(history_age, 0)
NSOPTION_BOOL(hover_urls, false)
NSOPTION_BOOL(focus_new, false)
diff --git a/frontends/monkey/output.c b/frontends/monkey/output.c
new file mode 100644
index 000000000..d7eb7cdb6
--- /dev/null
+++ b/frontends/monkey/output.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2018 Vincent Sanders <vince@nexturf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "monkey/output.h"
+
+/**
+ * output type prefixes
+ */
+static const char *type_text[]={
+ "DIE",
+ "ERROR",
+ "WARN",
+ "GENERIC",
+ "WINDOW",
+ "LOGIN",
+ "DOWNLOAD",
+ "PLOT",
+};
+
+/* exported interface documented in monkey/output.h */
+int moutf(enum monkey_output_type mout_type, const char *fmt, ...)
+{
+ va_list ap;
+ int res;
+
+ res = fprintf(stdout, "%s ", type_text[mout_type]);
+
+ va_start(ap, fmt);
+ res += vfprintf(stdout, fmt, ap);
+ va_end(ap);
+
+ fputc('\n', stdout);
+
+ return res + 1;
+}
diff --git a/frontends/monkey/cert.h b/frontends/monkey/output.h
index 4470e2e72..8e6a0abd6 100644
--- a/frontends/monkey/cert.h
+++ b/frontends/monkey/output.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
+ * Copyright 2018 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,13 +16,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_MONKEY_CERT_H_
-#define _NETSURF_MONKEY_CERT_H_
+#ifndef NS_MONKEY_OUTPUT_H
+#define NS_MONKEY_OUTPUT_H
-struct ssl_cert_info;
+enum monkey_output_type {
+ MOUT_DIE,
+ MOUT_ERROR,
+ MOUT_WARNING,
+ MOUT_GENERIC,
+ MOUT_WINDOW,
+ MOUT_LOGIN,
+ MOUT_DOWNLOAD,
+ MOUT_PLOT,
+};
-nserror gui_cert_verify(nsurl *url, const struct ssl_cert_info *certs,
- unsigned long num, nserror (*cb)(bool proceed, void *pw),
- void *cbpw);
+int moutf(enum monkey_output_type mout_type, const char *fmt, ...);
#endif
diff --git a/frontends/monkey/plot.c b/frontends/monkey/plot.c
index d00dca754..a8f0d61b6 100644
--- a/frontends/monkey/plot.c
+++ b/frontends/monkey/plot.c
@@ -22,6 +22,8 @@
#include "utils/errors.h"
#include "netsurf/plotters.h"
+#include "monkey/output.h"
+
/**
* \brief Sets a clip rectangle for subsequent plot operations.
*
@@ -33,8 +35,7 @@
static nserror
monkey_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
{
- fprintf(stdout,
- "PLOT CLIP X0 %d Y0 %d X1 %d Y1 %d\n",
+ moutf(MOUT_PLOT, "CLIP X0 %d Y0 %d X1 %d Y1 %d",
clip->x0, clip->y0, clip->x1, clip->y1);
return NSERROR_OK;
}
@@ -61,9 +62,8 @@ monkey_plot_arc(const struct redraw_context *ctx,
const plot_style_t *style,
int x, int y, int radius, int angle1, int angle2)
{
- fprintf(stdout,
- "PLOT ARC X %d Y %d RADIUS %d ANGLE1 %d ANGLE2 %d\n",
- x, y, radius, angle1, angle2);
+ moutf(MOUT_PLOT, "ARC X %d Y %d RADIUS %d ANGLE1 %d ANGLE2 %d",
+ x, y, radius, angle1, angle2);
return NSERROR_OK;
}
@@ -85,9 +85,7 @@ monkey_plot_disc(const struct redraw_context *ctx,
const plot_style_t *style,
int x, int y, int radius)
{
- fprintf(stdout,
- "PLOT DISC X %d Y %d RADIUS %d\n",
- x, y, radius);
+ moutf(MOUT_PLOT, "DISC X %d Y %d RADIUS %d", x, y, radius);
return NSERROR_OK;
}
@@ -108,8 +106,7 @@ monkey_plot_line(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *line)
{
- fprintf(stdout,
- "PLOT LINE X0 %d Y0 %d X1 %d Y1 %d\n",
+ moutf(MOUT_PLOT, "LINE X0 %d Y0 %d X1 %d Y1 %d",
line->x0, line->y0, line->x1, line->y1);
return NSERROR_OK;
}
@@ -133,8 +130,7 @@ monkey_plot_rectangle(const struct redraw_context *ctx,
const plot_style_t *style,
const struct rect *rect)
{
- fprintf(stdout,
- "PLOT RECT X0 %d Y0 %d X1 %d Y1 %d\n",
+ moutf(MOUT_PLOT, "RECT X0 %d Y0 %d X1 %d Y1 %d",
rect->x0, rect->y0, rect->x1, rect->y1);
return NSERROR_OK;
}
@@ -160,9 +156,7 @@ monkey_plot_polygon(const struct redraw_context *ctx,
const int *p,
unsigned int n)
{
- fprintf(stdout,
- "PLOT POLYGON VERTICIES %d\n",
- n);
+ moutf(MOUT_PLOT, "POLYGON VERTICIES %d", n);
return NSERROR_OK;
}
@@ -177,7 +171,6 @@ monkey_plot_polygon(const struct redraw_context *ctx,
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
- * \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
@@ -186,12 +179,10 @@ monkey_plot_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
- float width,
const float transform[6])
{
- fprintf(stdout,
- "PLOT PATH VERTICIES %d WIDTH %f\n",
- n, width);
+ moutf(MOUT_PLOT, "PATH VERTICIES %d WIDTH %f",
+ n, plot_style_fixed_to_float(pstyle->stroke_width));
return NSERROR_OK;
}
@@ -229,9 +220,8 @@ monkey_plot_bitmap(const struct redraw_context *ctx,
colour bg,
bitmap_flags_t flags)
{
- fprintf(stdout,
- "PLOT BITMAP X %d Y %d WIDTH %d HEIGHT %d\n",
- x, y, width, height);
+ moutf(MOUT_PLOT, "BITMAP X %d Y %d WIDTH %d HEIGHT %d",
+ x, y, width, height);
return NSERROR_OK;
}
@@ -255,9 +245,7 @@ monkey_plot_text(const struct redraw_context *ctx,
const char *text,
size_t length)
{
- fprintf(stdout,
- "PLOT TEXT X %d Y %d STR %*s\n",
- x, y, (int)length, text);
+ moutf(MOUT_PLOT, "TEXT X %d Y %d STR %.*s", x, y, (int)length, text);
return NSERROR_OK;
}
@@ -273,7 +261,7 @@ static const struct plotter_table plotters = {
.path = monkey_plot_path,
.bitmap = monkey_plot_bitmap,
.text = monkey_plot_text,
- .option_knockout = true,
+ .option_knockout = true,
};
const struct plotter_table* monkey_plotters = &plotters;
diff --git a/frontends/monkey/schedule.c b/frontends/monkey/schedule.c
index 3d76997f4..9d3ab7af8 100644
--- a/frontends/monkey/schedule.c
+++ b/frontends/monkey/schedule.c
@@ -43,6 +43,7 @@ struct nscallback
*
* \param callback callback function
* \param p user parameter, passed to callback function
+ * \return NSERROR_OK if callback found and removed else NSERROR_NOT_FOUND
*
* All scheduled callbacks matching both callback and p are removed.
*/
@@ -51,10 +52,11 @@ static nserror schedule_remove(void (*callback)(void *p), void *p)
struct nscallback *cur_nscb;
struct nscallback *prev_nscb;
struct nscallback *unlnk_nscb;
+ bool removed = false;
/* check there is something on the list to remove */
if (schedule_list == NULL) {
- return NSERROR_OK;
+ return NSERROR_NOT_FOUND;
}
NSLOG(schedule, DEBUG, "removing %p, %p", callback, p);
@@ -80,6 +82,7 @@ static nserror schedule_remove(void (*callback)(void *p), void *p)
prev_nscb->next = cur_nscb;
}
free (unlnk_nscb);
+ removed = true;
} else {
/* move to next element */
prev_nscb = cur_nscb;
@@ -87,6 +90,9 @@ static nserror schedule_remove(void (*callback)(void *p), void *p)
}
}
+ if (removed == false) {
+ return NSERROR_NOT_FOUND;
+ }
return NSERROR_OK;
}
@@ -99,7 +105,7 @@ nserror monkey_schedule(int tival, void (*callback)(void *p), void *p)
/* ensure uniqueness of the callback and context */
ret = schedule_remove(callback, p);
- if ((tival < 0) || (ret != NSERROR_OK)) {
+ if (tival < 0) {
return ret;
}
diff --git a/frontends/riscos/401login.c b/frontends/riscos/401login.c
deleted file mode 100644
index 4b2deb16b..000000000
--- a/frontends/riscos/401login.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "utils/config.h"
-
-#include <assert.h>
-#include <stdbool.h>
-#include <string.h>
-#include <oslib/wimp.h>
-
-#include "utils/log.h"
-#include "utils/messages.h"
-#include "utils/nsurl.h"
-#include "netsurf/url_db.h"
-
-#include "riscos/gui.h"
-#include "riscos/dialog.h"
-#include "riscos/wimp_event.h"
-
-#define ICON_401LOGIN_LOGIN 0
-#define ICON_401LOGIN_CANCEL 1
-#define ICON_401LOGIN_HOST 2
-#define ICON_401LOGIN_REALM 3
-#define ICON_401LOGIN_USERNAME 4
-#define ICON_401LOGIN_PASSWORD 5
-
-static void ro_gui_401login_close(wimp_w w);
-static bool ro_gui_401login_apply(wimp_w w);
-static void ro_gui_401login_open(nsurl *url, lwc_string *host,
- const char *realm,
- nserror (*cb)(bool proceed, void *pw), void *cbpw);
-
-static wimp_window *dialog_401_template;
-
-struct session_401 {
- lwc_string *host; /**< Host for user display */
- char *realm; /**< Authentication realm */
- char uname[256]; /**< Buffer for username */
- nsurl *url; /**< URL being fetched */
- char pwd[256]; /**< Buffer for password */
- nserror (*cb)(bool proceed, void *pw); /**< Continuation callback */
- void *cbpw; /**< Continuation callback data */
-};
-
-
-/**
- * Load the 401 login window template.
- */
-
-void ro_gui_401login_init(void)
-{
- dialog_401_template = ro_gui_dialog_load_template("login");
-}
-
-
-/**
- * Open the login dialog
- */
-void gui_401login_open(nsurl *url, const char *realm,
- nserror (*cb)(bool proceed, void *pw), void *cbpw)
-{
- lwc_string *host = nsurl_get_component(url, NSURL_HOST);
- assert(host != NULL);
-
- ro_gui_401login_open(url, host, realm, cb, cbpw);
-
- lwc_string_unref(host);
-}
-
-
-/**
- * Open a 401 login window.
- */
-
-void ro_gui_401login_open(nsurl *url, lwc_string *host, const char *realm,
- nserror (*cb)(bool proceed, void *pw), void *cbpw)
-{
- struct session_401 *session;
- wimp_w w;
- const char *auth;
-
- session = calloc(1, sizeof(struct session_401));
- if (!session) {
- ro_warn_user("NoMemory", 0);
- return;
- }
-
- session->url = nsurl_ref(url);
- if (realm == NULL)
- realm = "Secure Area";
- auth = urldb_get_auth_details(session->url, realm);
- if (auth == NULL) {
- session->uname[0] = '\0';
- session->pwd[0] = '\0';
- } else {
- const char *pwd;
- size_t pwd_len;
-
- pwd = strchr(auth, ':');
- assert(pwd && pwd < auth + sizeof(session->uname));
- memcpy(session->uname, auth, pwd - auth);
- session->uname[pwd - auth] = '\0';
- ++pwd;
- pwd_len = strlen(pwd);
- assert(pwd_len < sizeof(session->pwd));
- memcpy(session->pwd, pwd, pwd_len);
- session->pwd[pwd_len] = '\0';
- }
- session->host = lwc_string_ref(host);
- session->realm = strdup(realm);
- session->cb = cb;
- session->cbpw = cbpw;
-
- if (!session->realm) {
- nsurl_unref(session->url);
- lwc_string_unref(session->host);
- free(session);
- ro_warn_user("NoMemory", 0);
- return;
- }
-
- /* fill in download window icons */
- dialog_401_template->icons[ICON_401LOGIN_HOST].data.
- indirected_text.text =
- (char *)lwc_string_data(session->host);
- dialog_401_template->icons[ICON_401LOGIN_HOST].data.
- indirected_text.size =
- lwc_string_length(session->host) + 1;
- dialog_401_template->icons[ICON_401LOGIN_REALM].data.
- indirected_text.text = session->realm;
- dialog_401_template->icons[ICON_401LOGIN_REALM].data.
- indirected_text.size = strlen(session->realm) + 1;
- dialog_401_template->icons[ICON_401LOGIN_USERNAME].data.
- indirected_text.text = session->uname;
- dialog_401_template->icons[ICON_401LOGIN_USERNAME].data.
- indirected_text.size = sizeof(session->uname);
- dialog_401_template->icons[ICON_401LOGIN_PASSWORD].data.
- indirected_text.text = session->pwd;
- dialog_401_template->icons[ICON_401LOGIN_PASSWORD].data.
- indirected_text.size = sizeof(session->pwd);
-
- /* create and open the window */
- w = wimp_create_window(dialog_401_template);
-
- ro_gui_wimp_event_register_text_field(w, ICON_401LOGIN_USERNAME);
- ro_gui_wimp_event_register_text_field(w, ICON_401LOGIN_PASSWORD);
- ro_gui_wimp_event_register_cancel(w, ICON_401LOGIN_CANCEL);
- ro_gui_wimp_event_register_ok(w, ICON_401LOGIN_LOGIN,
- ro_gui_401login_apply);
- ro_gui_wimp_event_register_close_window(w, ro_gui_401login_close);
- ro_gui_wimp_event_set_user_data(w, session);
-
- ro_gui_dialog_open_persistent(NULL, w, false);
-}
-
-/**
- * Handle closing of login dialog
- */
-void ro_gui_401login_close(wimp_w w)
-{
- os_error *error;
- struct session_401 *session;
-
- session = (struct session_401 *)ro_gui_wimp_event_get_user_data(w);
-
- assert(session);
-
- /* If ok didn't happen, send failure response */
- if (session->cb != NULL)
- session->cb(false, session->cbpw);
-
- nsurl_unref(session->url);
- lwc_string_unref(session->host);
- free(session->realm);
- free(session);
-
- error = xwimp_delete_window(w);
- if (error) {
- NSLOG(netsurf, INFO, "xwimp_delete_window: 0x%x:%s",
- error->errnum, error->errmess);
- ro_warn_user("WimpError", error->errmess);
- }
- ro_gui_wimp_event_finalise(w);
-}
-
-
-/* Login Clicked -> create a new fetch request, specifying uname & pwd
- * CURLOPT_USERPWD takes a string "username:password"
- */
-bool ro_gui_401login_apply(wimp_w w)
-{
- struct session_401 *session;
- char *auth;
-
- session = (struct session_401 *)ro_gui_wimp_event_get_user_data(w);
-
- assert(session);
-
- auth = malloc(strlen(session->uname) + strlen(session->pwd) + 2);
- if (!auth) {
- NSLOG(netsurf, INFO, "calloc failed");
- ro_warn_user("NoMemory", 0);
- return false;
- }
-
- sprintf(auth, "%s:%s", session->uname, session->pwd);
-
- urldb_set_auth_details(session->url, session->realm, auth);
-
- free(auth);
-
- session->cb(true, session->cbpw);
-
- /* Flag that we sent response by invalidating callback details */
- session->cb = NULL;
- session->cbpw = NULL;
-
- return true;
-}
-
diff --git a/frontends/riscos/Makefile b/frontends/riscos/Makefile
index f531b6b5b..265f9289d 100644
--- a/frontends/riscos/Makefile
+++ b/frontends/riscos/Makefile
@@ -22,6 +22,9 @@ RESOURCES = $(TPD_RISCOS)
CFLAGS += -Driscos -std=c99 -D_BSD_SOURCE -D_POSIX_C_SOURCE \
-mpoke-function-name -fno-strict-aliasing
+ifeq ($(findstring -elfeabi,$(SUBTARGET)),-elfeabi)
+ CFLAGS += -funwind-tables
+endif
CFLAGS += -I$(GCCSDK_INSTALL_ENV)/include
ifeq ($(HOST),riscos)
@@ -33,7 +36,7 @@ ifeq ($(HOST),riscos)
LDFLAGS += -LOSLib: -lOSLib32
else
LDFLAGS += -lOSLib32
- ifeq ($(SUBTARGET),-elf)
+ ifeq ($(findstring -elf,$(SUBTARGET)),-elf)
# Go for static builds & AIF binary at the moment:
CFLAGS += -static
LDFLAGS += -static
@@ -46,17 +49,52 @@ endif
# ----------------------------------------------------------------------------
# S_RISCOS are sources purely for the RISC OS build
-S_FRONTEND := 401login.c assert.c bitmap.c buffer.c configure.c gui.c \
- dialog.c download.c filetype.c font.c help.c image.c \
- iconbar.c menus.c message.c mouse.c palettes.c plotters.c \
- print.c query.c save.c save_draw.c save_pdf.c schedule.c \
- search.c searchweb.c textarea.c textselection.c theme.c \
- theme_install.c toolbar.c url_suggest.c wimp.c wimp_event.c \
- ucstables.c uri.c url_complete.c url_protocol.c window.c \
- corewindow.c cookies.c sslcert.c hotlist.c \
- local_history.c global_history.c \
- $(addprefix content-handlers/,artworks.c awrender.s draw.c \
- sprite.c) \
+S_FRONTEND := \
+ assert.c \
+ bitmap.c \
+ buffer.c \
+ configure.c \
+ cookies.c \
+ corewindow.c \
+ dialog.c \
+ download.c \
+ filetype.c \
+ font.c \
+ global_history.c \
+ gui.c \
+ help.c \
+ hotlist.c \
+ image.c \
+ iconbar.c \
+ local_history.c \
+ menus.c \
+ message.c \
+ mouse.c \
+ pageinfo.c \
+ palettes.c \
+ plotters.c \
+ print.c \
+ query.c \
+ save.c \
+ save_draw.c \
+ save_pdf.c \
+ schedule.c \
+ search.c \
+ searchweb.c \
+ textarea.c \
+ textselection.c \
+ theme.c \
+ theme_install.c \
+ toolbar.c \
+ url_suggest.c \
+ ucstables.c \
+ uri.c \
+ url_complete.c \
+ url_protocol.c \
+ window.c \
+ wimp.c \
+ wimp_event.c \
+ $(addprefix content-handlers/,artworks.c awrender.s draw.c sprite.c) \
$(addprefix gui/,button_bar.c progress_bar.c status_bar.c \
throbber.c url_bar.c) \
$(addprefix configure/,con_cache.c con_connect.c con_content.c \
@@ -76,6 +114,9 @@ MESSAGES_FILTER=ro
$(FRONTEND_SOURCE_DIR)/appdir/!Run$(RUNEXT): $(FRONTEND_SOURCE_DIR)/scripts/Run $(EXETARGET)
$(VQ)echo " MAKERUN: $@"
$(Q)$(MAKERUN) $(EXETARGET) $< $@
+ifeq ($(findstring -elfeabi,$(SUBTARGET)),-elfeabi)
+ $(Q)$(SED) -i -e 's/^|\(RMEnsure ARMEABISupport\)/\1/' -e 's/SharedUnixLibrary 1\.07/SharedUnixLibrary 1.16/g' $@
+endif
$(FRONTEND_SOURCE_DIR)/appdir/!Help$(RUNEXT): $(FRONTEND_SOURCE_DIR)/scripts/Help
$(VQ)echo " CP: $@"
@@ -139,15 +180,15 @@ install-riscos:
package-riscos: netsurf.zip
-netsurf.zip: $(EXETARGET)
+netsurf.zip: $(EXETARGET) $(POSTEXES)
$(eval $@_TMPDIR := $(shell mktemp -d))
$(Q) $(RM) $@
$(Q) cp -rLvp $(FRONTEND_SOURCE_DIR)/appdir $($@_TMPDIR)/!NetSurf
- $(Q) $(CURDIR)/utils/git-date.sh $(FRONTEND_SOURCE_DIR)/distribution
+ $(Q) $(CURDIR)/tools/git-date.sh $(FRONTEND_SOURCE_DIR)/distribution
$(Q) rsync --archive --verbose $(FRONTEND_SOURCE_DIR)/distribution/!Boot $($@_TMPDIR)
$(Q) rsync --archive --verbose $(FRONTEND_SOURCE_DIR)/distribution/!System $($@_TMPDIR)
$(Q) rsync --archive --verbose $(FRONTEND_SOURCE_DIR)/distribution/3rdParty $($@_TMPDIR)
$(Q) cp $(FRONTEND_SOURCE_DIR)/distribution/ReadMe $($@_TMPDIR)
$(Q) cp $(FRONTEND_SOURCE_DIR)/distribution/LeesMij $($@_TMPDIR)
- $(Q) cd $($@_TMPDIR) && /opt/netsurf/arm-unknown-riscos/env/bin/zip -9vr\, $(CURDIR)/$@ *
+ $(Q) cd $($@_TMPDIR) && $(ZIP) -9vr\, $(CURDIR)/$@ *
$(Q) $(RM) -rf $($@_TMPDIR)
diff --git a/frontends/riscos/Makefile.tools b/frontends/riscos/Makefile.tools
new file mode 100644
index 000000000..a5b5cca1e
--- /dev/null
+++ b/frontends/riscos/Makefile.tools
@@ -0,0 +1,100 @@
+# -*- mode: makefile-gmake -*-
+##
+## RISC OS target tool setup
+##
+
+ifeq ($(HOST),riscos)
+ # Build for RO on RO
+ GCCSDK_INSTALL_ENV := <NSLibs$$Dir>
+ CCRES := ccres
+ TPLEXT :=
+ MAKERUN := makerun
+ SQUEEZE := squeeze
+ RUNEXT :=
+ CC := gcc
+ CXX := g++
+ EXEEXT :=
+ PKG_CONFIG :=
+ ZIP := zip
+ SED :=
+else
+ # Cross-build for RO
+ # Four options are available:
+ # a. GCCSDK 3.4.6 - AOF (machine: arm-unknown-riscos)
+ # b. GCCSDK 4 - ELF (machine: arm-unknown-riscos)
+ # c. GCCSDK 8+ - ELF, using soft-float EABI (machine: arm-riscos-gnueabi)
+ # d. GCCSDK 8+ - ELF, using hard-float EABI (machine: arm-riscos-gnueabihf)
+ # GCCSDK 3.4.6 and 4 are distinguished by GCCSDK 3.4.6 binary names
+ # not having the machine prefix (e.g. gcc), whereas GCCSDK 4 binaries
+ # do (e.g. arm-unknown-riscos-gcc).
+
+ # Search for the toolchain install locations if we haven't been told
+ # The search order prefers GCCSDK 3.4.6/4 over 8+ and soft-float over hard.
+ ifeq ($(origin GCCSDK_INSTALL_ENV),undefined)
+ ifneq ($(realpath /opt/netsurf/arm-unknown-riscos/env),)
+ GCCSDK_INSTALL_ENV := /opt/netsurf/arm-unknown-riscos/env
+ else
+ ifneq ($(realpath /opt/netsurf/arm-riscos-gnueabi/env),)
+ GCCSDK_INSTALL_ENV := /opt/netsurf/arm-riscos-gnueabi/env
+ else
+ ifneq ($(realpath /opt/netsurf/arm-riscos-gnueabihf/env),)
+ GCCSDK_INSTALL_ENV := /opt/netsurf/arm-riscos-gnueabihf/env
+ else
+ # No NetSurf-specific toolchain found: try the "normal" GCCSDK path
+ GCCSDK_INSTALL_ENV := /home/riscos/env
+ endif
+ endif
+ endif
+ endif
+
+ ifeq ($(origin GCCSDK_INSTALL_CROSSBIN),undefined)
+ ifneq ($(realpath /opt/netsurf/arm-unknown-riscos/cross/bin),)
+ GCCSDK_INSTALL_CROSSBIN := /opt/netsurf/arm-unknown-riscos/cross/bin
+ else
+ ifneq ($(realpath /opt/netsurf/arm-riscos-gnueabi/cross/bin),)
+ GCCSDK_INSTALL_CROSSBIN := /opt/netsurf/arm-riscos-gnueabi/cross/bin
+ else
+ ifneq ($(realpath /opt/netsurf/arm-riscos-gnueabihf/cross/bin),)
+ GCCSDK_INSTALL_CROSSBIN := /opt/netsurf/arm-riscos-gnueabihf/cross/bin
+ else
+ # No NetSurf-specific toolchain found: try the "normal" GCCSDK path
+ GCCSDK_INSTALL_CROSSBIN := /home/riscos/cross/bin
+ endif
+ endif
+ endif
+ endif
+
+ CCRES := $(GCCSDK_INSTALL_CROSSBIN)/ccres
+ TPLEXT := ,fec
+ MAKERUN := $(GCCSDK_INSTALL_CROSSBIN)/makerun
+ SQUEEZE := $(GCCSDK_INSTALL_CROSSBIN)/squeeze
+ RUNEXT := ,feb
+ CC := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc)
+
+ # Work out what kind of toolchain we're dealing with
+ ifneq (,$(findstring arm-unknown-riscos-gcc,$(CC)))
+ # GCCSDK 4
+ SUBTARGET := -elf
+ EXEEXT := ,e1f
+ ELF2AIF := $(GCCSDK_INSTALL_CROSSBIN)/elf2aif
+ else
+ ifneq (,$(findstring arm-riscos-gnueabi,$(CC)))
+ # GCCSDK 8+
+ SUBTARGET := -elfeabi
+ ifneq (,$(findstring gnueabihf,$(CC)))
+ SUBTARGET := -elfeabihf
+ endif
+ EXEEXT := ,e1f
+ ELF2AIF := $(GCCSDK_INSTALL_CROSSBIN)/elf2aif -e
+ else
+ # GCCSDK 3.4.6
+ SUBTARGET := -aof
+ EXEEXT := ,ff8
+ endif
+ endif
+
+ CXX := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++)
+ PKG_CONFIG = PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(GCCSDK_INSTALL_ENV)/lib/pkgconfig:$(GCCSDK_INSTALL_ENV)/share/pkgconfig" pkg-config
+ ZIP := $(GCCSDK_INSTALL_CROSSBIN)/zip
+ SED := sed
+endif
diff --git a/frontends/riscos/appdir/!Boot,feb b/frontends/riscos/appdir/!Boot,feb
index ca7a3feec..acaad8192 100644
--- a/frontends/riscos/appdir/!Boot,feb
+++ b/frontends/riscos/appdir/!Boot,feb
@@ -35,10 +35,8 @@ Set File$Type_F91 URI
Set File$Type_FAF HTML
| Application system variables
-|
-| See http://www.iyonix.com/32bit/help.shtml for more details.
If (("<NetSurf$Help>" = "") OR ("<NetSurf$ForceVars>" = "1")) Then Set NetSurf$Help <NetSurf$Dir>.Docs.docs_en
-If (("<NetSurf$Web>" = "") OR ("<NetSurf$ForceVars>" = "1")) Then Set NetSurf$Web "http://www.netsurf-browser.org/"
+If (("<NetSurf$Web>" = "") OR ("<NetSurf$ForceVars>" = "1")) Then Set NetSurf$Web "https://www.netsurf-browser.org/"
If (("<NetSurf$Title>" = "") OR ("<NetSurf$ForceVars>" = "1")) Then Set NetSurf$Title "NetSurf"
If (("<NetSurf$Publisher>" = "") OR ("<NetSurf$ForceVars>" = "1")) Then Set NetSurf$Publisher "The NetSurf Developers"
If (("<NetSurf$Description>" = "") OR ("<NetSurf$ForceVars>" = "1")) Then Set NetSurf$Description "Web browser"
diff --git a/frontends/riscos/appdir/Resources/Aletheia,ffd b/frontends/riscos/appdir/Resources/Aletheia,ffd
index 9af7ea129..8eb1773da 100644
--- a/frontends/riscos/appdir/Resources/Aletheia,ffd
+++ b/frontends/riscos/appdir/Resources/Aletheia,ffd
Binary files differ
diff --git a/frontends/riscos/appdir/Resources/SearchEngines b/frontends/riscos/appdir/Resources/SearchEngines
index e7fd7cb65..1e4530f06 100644
--- a/frontends/riscos/appdir/Resources/SearchEngines
+++ b/frontends/riscos/appdir/Resources/SearchEngines
@@ -1,22 +1,21 @@
-Google|www.google.com|http://www.google.com/search?q=%s|http://www.google.com/favicon.ico|
-Yahoo|search.yahoo.com|http://search.yahoo.com/search?p=%s|http://www.yahoo.com/favicon.ico|
-Bing|www.bing.com|http://www.bing.com/search?q=%s|http://www.bing.com/favicon.ico|
-Business.com|www.business.com|http://www.business.com/search/rslt_default.asp?query=%s|http://www.business.com/favicon.ico|
-Omgili|www.omgili.com|http://www.omgili.com/AAAAA/%s.html|http://www.omgili.com/favicon.ico|
-BBC News|search.bbc.co.uk|http://search.bbc.co.uk/search?q=%s&tab=ns|http://news.bbc.co.uk/favicon.ico|
-Ubuntu Packages|packages.ubuntu.com|http://packages.ubuntu.com/search?keywords=%s|http://packages.ubuntu.com/favicon.ico|
-Creative Commons|creativecommons.org|http://creativecommons.org/?s=%s|http://creativecommons.org/favicon.ico|
-Ask.com|www.ask.com|http://www.ask.com/web?q=%s|http://www.ask.com/favicon.ico|
-Answers.com|www.answers.com|http://www.answers.com/%s|http://www.answers.com/favicon.ico|
-Dictionary.com|dictionary.reference.com|http://dictionary.reference.com/browse/%s?jss=0|http://dictionary.reference.com/favicon.ico|
-Youtube|www.youtube.com|http://www.youtube.com/results?search_query=%s|http://www.youtube.com/favicon.ico|
-AeroMp3|www.aeromp3.com|http://www.aeromp3.com/search?q=%s|http://www.aeromp3.com/favicon.ico|
-AOL|search.aol.com|http://search.aol.com/aol/search?query=%s|http://www.aol.com/favicon.ico|
-Baidu|www.baidu.com|http://www.baidu.com/s?wd=%s|http://www.baidu.com/favicon.ico|
-Amazon|www.amazon.com|http://www.amazon.com/s/ref=nb_ss_gw?field-keywords=%s|http://www.amazon.com/favicon.ico|
-Ebay|shop.ebay.com|http://shop.ebay.com/items/%s|http://www.ebay.com/favicon.ico|
-IMDB|www.imdb.com|http://www.imdb.com/find?q=%s|http://www.imdb.com/favicon.ico|
-ESPN|search.espn.go.com|http://search.espn.go.com/%s/|http://www.espn.go.com/favicon.ico|
-Wikipedia|en.wikipedia.org|http://en.wikipedia.org/w/index.php?title=Special%%3ASearch&search=%s|http://en.wikipedia.org/favicon.ico|
-DuckDuckGo|www.duckduckgo.com|http://www.duckduckgo.com/?q=%s|http://www.duckduckgo.com/favicon.ico|
-Seeks|www.seeks-project.info|https://www.seeks-project.info/search.php/search?q=%s|http://www.seeks-project.info/search.php/public/images/seek_icon_32x32_transparent.png|
+Google|www.google.com|https://www.google.com/search?q=%s|https://www.google.com/favicon.ico|
+Yahoo|search.yahoo.com|https://search.yahoo.com/search?p=%s|https://www.yahoo.com/favicon.ico|
+Bing|www.bing.com|https://www.bing.com/search?q=%s|https://www.bing.com/favicon.ico|
+Business.com|www.business.com|https://www.business.com/search/rslt_default.asp?query=%s|https://www.business.com/favicon.ico|
+Omgili|www.omgili.com|https://www.omgili.com/AAAAA/%s.html|https://www.omgili.com/favicon.ico|
+BBC News|search.bbc.co.uk|https://search.bbc.co.uk/search?q=%s&tab=ns|https://news.bbc.co.uk/favicon.ico|
+Ubuntu Packages|packages.ubuntu.com|https://packages.ubuntu.com/search?keywords=%s|https://packages.ubuntu.com/favicon.ico|
+Creative Commons|creativecommons.org|https://creativecommons.org/?s=%s|https://creativecommons.org/favicon.ico|
+Ask.com|www.ask.com|https://www.ask.com/web?q=%s|https://www.ask.com/favicon.ico|
+Answers.com|www.answers.com|https://www.answers.com/%s|https://www.answers.com/favicon.ico|
+Dictionary.com|dictionary.reference.com|https://dictionary.reference.com/browse/%s?jss=0|https://dictionary.reference.com/favicon.ico|
+Youtube|www.youtube.com|https://www.youtube.com/results?search_query=%s|https://www.youtube.com/favicon.ico|
+AeroMp3|www.aeromp3.com|https://www.aeromp3.com/search?q=%s|https://www.aeromp3.com/favicon.ico|
+AOL|search.aol.com|https://search.aol.com/aol/search?query=%s|https://www.aol.com/favicon.ico|
+Baidu|www.baidu.com|https://www.baidu.com/s?wd=%s|https://www.baidu.com/favicon.ico|
+Amazon|www.amazon.com|https://www.amazon.com/s/ref=nb_ss_gw?field-keywords=%s|https://www.amazon.com/favicon.ico|
+Ebay|shop.ebay.com|https://shop.ebay.com/items/%s|https://www.ebay.com/favicon.ico|
+IMDB|www.imdb.com|https://www.imdb.com/find?q=%s|https://www.imdb.com/favicon.ico|
+ESPN|search.espn.go.com|https://search.espn.go.com/%s/|https://www.espn.go.com/favicon.ico|
+Wikipedia|en.wikipedia.org|https://en.wikipedia.org/w/index.php?title=Special%%3ASearch&search=%s|https://en.wikipedia.org/favicon.ico|
+DuckDuckGo|www.duckduckgo.com|https://www.duckduckgo.com/?q=%s|https://www.duckduckgo.com/favicon.ico|
diff --git a/frontends/riscos/appdir/Resources/en/!Help b/frontends/riscos/appdir/Resources/en/!Help
index 977f069d8..bba2b2a72 100644
--- a/frontends/riscos/appdir/Resources/en/!Help
+++ b/frontends/riscos/appdir/Resources/en/!Help
@@ -1,14 +1,14 @@
-NetSurf - Open Source web browser - http://www.netsurf-browser.org/
+NetSurf - Open Source web browser - https://www.netsurf-browser.org/
To view the full documentation, start NetSurf and choose "Help..." from the
icon bar menu.
This is a development build of NetSurf. In case of problems, please check
-for a newer development build at http://www.netsurf-browser.org/
+for a newer development build at https://www.netsurf-browser.org/
Please report any unexpected behaviour on the NetSurf bug tracker.
-This may be found at http://bugs.netsurf-browser.org/
+This may be found at https://bugs.netsurf-browser.org/
-Alternatively, the developers are often available on Freenode in the
+Alternatively, the developers are often available on libera.chat in the
channel #netsurf.
diff --git a/frontends/riscos/appdir/Resources/en/maps.html,faf b/frontends/riscos/appdir/Resources/en/maps.html,faf
deleted file mode 120000
index 4ae4f6c42..000000000
--- a/frontends/riscos/appdir/Resources/en/maps.html,faf
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../resources/en/maps.html \ No newline at end of file
diff --git a/frontends/riscos/appdir/Resources/nl/!Help b/frontends/riscos/appdir/Resources/nl/!Help
index 4eca563bc..8a68e94f9 100644
--- a/frontends/riscos/appdir/Resources/nl/!Help
+++ b/frontends/riscos/appdir/Resources/nl/!Help
@@ -1,15 +1,15 @@
-NetSurf - Webbrowser (met open broncode) - http://www.netsurf-browser.org/
+NetSurf - Webbrowser (met open broncode) - https://www.netsurf-browser.org/
Om alle documentatie te kunnen raadplegen: start NetSurf en kies "Help..."
vanuit het symbolenbalkmenu.
Dit is een ontwikkelversie van NetSurf. Bij problemen: kijk eerst of er een
-nieuwere versie is op http://www.netsurf-browser.org/
+nieuwere versie is op https://www.netsurf-browser.org/
Gelieve ook elk onverwacht gedrag van NetSurf, in het Engels te melden via
-onze 'bug tracker' op http://bugs.netsurf-browser.org/
+onze 'bug tracker' op https://bugs.netsurf-browser.org/
-Een alternatief is Freenode op het kanaal #netsurf waar de ontwikkelaars
+Een alternatief is libera.chat op het kanaal #netsurf waar de ontwikkelaars
vaak bereikbaar zijn.
diff --git a/frontends/riscos/bitmap.c b/frontends/riscos/bitmap.c
index d554d54b4..97dce6acc 100644
--- a/frontends/riscos/bitmap.c
+++ b/frontends/riscos/bitmap.c
@@ -44,7 +44,6 @@
#include "utils/log.h"
#include "utils/messages.h"
#include "netsurf/plotters.h"
-#include "netsurf/bitmap.h"
#include "netsurf/content.h"
#include "riscos/gui.h"
@@ -91,7 +90,7 @@ static bool bitmap_initialise(struct bitmap *bitmap)
assert(!bitmap->sprite_area);
area_size = 16 + 44 + bitmap->width * bitmap->height * 4;
- if (bitmap->state & BITMAP_CLEAR_MEMORY)
+ if (bitmap->clear)
bitmap->sprite_area = calloc(1, area_size);
else
bitmap->sprite_area = malloc(area_size);
@@ -123,7 +122,7 @@ static bool bitmap_initialise(struct bitmap *bitmap)
/* exported interface documented in riscos/bitmap.h */
-void *riscos_bitmap_create(int width, int height, unsigned int state)
+void *riscos_bitmap_create(int width, int height, enum gui_bitmap_flags flags)
{
struct bitmap *bitmap;
@@ -135,7 +134,8 @@ void *riscos_bitmap_create(int width, int height, unsigned int state)
return NULL;
bitmap->width = width;
bitmap->height = height;
- bitmap->state = state;
+ bitmap->opaque = (flags & BITMAP_OPAQUE) == BITMAP_OPAQUE;
+ bitmap->clear = (flags & BITMAP_CLEAR) == BITMAP_CLEAR;
return bitmap;
}
@@ -172,10 +172,7 @@ static void bitmap_set_opaque(void *vbitmap, bool opaque)
struct bitmap *bitmap = (struct bitmap *) vbitmap;
assert(bitmap);
- if (opaque)
- bitmap->state |= BITMAP_OPAQUE;
- else
- bitmap->state &= ~BITMAP_OPAQUE;
+ bitmap->opaque = opaque;
}
@@ -192,61 +189,12 @@ static size_t bitmap_get_rowstride(void *vbitmap)
}
-/**
- * Tests whether a bitmap has an opaque alpha channel
- *
- * \param vbitmap a bitmap, as returned by bitmap_create()
- * \return whether the bitmap is opaque
- */
-static bool bitmap_test_opaque(void *vbitmap)
-{
- struct bitmap *bitmap = (struct bitmap *) vbitmap;
- unsigned char *sprite;
- unsigned int width, height, size;
- osspriteop_header *sprite_header;
- unsigned *p, *ep;
-
- assert(bitmap);
-
- sprite = riscos_bitmap_get_buffer(bitmap);
- if (!sprite)
- return false;
-
- width = bitmap_get_rowstride(bitmap);
-
- sprite_header = (osspriteop_header *) (bitmap->sprite_area + 1);
-
- height = (sprite_header->height + 1);
-
- size = width * height;
-
- p = (void *) sprite;
-
- ep = (void *) (sprite + (size & ~31));
- while (p < ep) {
- /* \todo prefetch(p, 128)? */
- if (((p[0] & p[1] & p[2] & p[3] & p[4] & p[5] & p[6] & p[7])
- & 0xff000000U) != 0xff000000U)
- return false;
- p += 8;
- }
-
- ep = (void *) (sprite + size);
- while (p < ep) {
- if ((*p & 0xff000000U) != 0xff000000U) return false;
- p++;
- }
-
- return true;
-}
-
-
/* exported interface documented in riscos/bitmap.h */
bool riscos_bitmap_get_opaque(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
assert(bitmap);
- return (bitmap->state & BITMAP_OPAQUE);
+ return bitmap->opaque;
}
@@ -449,8 +397,7 @@ bool riscos_bitmap_save(void *vbitmap, const char *path, unsigned flags)
*/
static void bitmap_modified(void *vbitmap)
{
- struct bitmap *bitmap = (struct bitmap *) vbitmap;
- bitmap->state |= BITMAP_MODIFIED;
+ (void)(vbitmap);
}
@@ -480,20 +427,6 @@ static int bitmap_get_height(void *vbitmap)
}
-/**
- * Find the bytes per pixel of a bitmap
- *
- * \param vbitmap a bitmap, as returned by bitmap_create()
- * \return bytes per pixel
- */
-static size_t bitmap_get_bpp(void *vbitmap)
-{
- struct bitmap *bitmap = (struct bitmap *)vbitmap;
- assert(bitmap);
- return 4;
-}
-
-
/* exported interface documented in riscos/bitmap.h */
void riscos_bitmap_overlay_sprite(struct bitmap *bitmap,
const osspriteop_header *s)
@@ -874,13 +807,10 @@ static struct gui_bitmap_table bitmap_table = {
.destroy = riscos_bitmap_destroy,
.set_opaque = bitmap_set_opaque,
.get_opaque = riscos_bitmap_get_opaque,
- .test_opaque = bitmap_test_opaque,
.get_buffer = riscos_bitmap_get_buffer,
.get_rowstride = bitmap_get_rowstride,
.get_width = bitmap_get_width,
.get_height = bitmap_get_height,
- .get_bpp = bitmap_get_bpp,
- .save = riscos_bitmap_save,
.modified = bitmap_modified,
.render = riscos_bitmap_render,
};
diff --git a/frontends/riscos/bitmap.h b/frontends/riscos/bitmap.h
index 3aca30de6..628ec4b7a 100644
--- a/frontends/riscos/bitmap.h
+++ b/frontends/riscos/bitmap.h
@@ -19,13 +19,15 @@
#ifndef _NETSURF_RISCOS_BITMAP_H_
#define _NETSURF_RISCOS_BITMAP_H_
+#include "netsurf/bitmap.h"
+
struct osspriteop_area;
struct osspriteop_header;
struct hlcache_handle;
struct bitmap;
/** bitmap operations table */
-struct gui_bitmap_table *riscos_bitmap_table;
+extern struct gui_bitmap_table *riscos_bitmap_table;
/** save with full alpha channel (if not opaque) */
#define BITMAP_SAVE_FULL_ALPHA (1 << 0)
@@ -37,7 +39,8 @@ struct bitmap {
int width; /**< width of bitmap */
int height; /**< height of bitmap */
- unsigned int state; /**< The bitmap attributes (opaque/dirty etc.) */
+ bool opaque; /**< Whether the bitmap is opaque. */
+ bool clear; /**< Whether the bitmap should be initialised to zeros. */
struct osspriteop_area *sprite_area; /**< Uncompressed data, or NULL */
};
@@ -71,11 +74,11 @@ void riscos_bitmap_overlay_sprite(struct bitmap *bitmap, const struct osspriteop
* Create a bitmap.
*
* \param width width of image in pixels
- * \param height width of image in pixels
- * \param state the state to create the bitmap in.
+ * \param height height of image in pixels
+ * \param flags flags for bitmap creation.
* \return an opaque struct bitmap, or NULL on memory exhaustion
*/
-void *riscos_bitmap_create(int width, int height, unsigned int state);
+void *riscos_bitmap_create(int width, int height, enum gui_bitmap_flags flags);
/**
* Free a bitmap.
diff --git a/frontends/riscos/buffer.c b/frontends/riscos/buffer.c
index c63a270db..9c8f8fe11 100644
--- a/frontends/riscos/buffer.c
+++ b/frontends/riscos/buffer.c
@@ -81,7 +81,7 @@ static os_mode mode;
*
* \param redraw the current WIMP redraw area to buffer
*/
-void ro_gui_buffer_open(wimp_draw *redraw)
+void ro_gui_buffer_open(const wimp_draw *redraw)
{
int size;
int total_size;
diff --git a/frontends/riscos/buffer.h b/frontends/riscos/buffer.h
index a683c324c..7de0ecdc6 100644
--- a/frontends/riscos/buffer.h
+++ b/frontends/riscos/buffer.h
@@ -25,7 +25,7 @@
#include "oslib/wimp.h"
-void ro_gui_buffer_open(wimp_draw *redraw);
+void ro_gui_buffer_open(const wimp_draw *redraw);
void ro_gui_buffer_close(void);
#endif
diff --git a/frontends/riscos/configure/con_content.c b/frontends/riscos/configure/con_content.c
index 50bbd15ef..bdf147bd4 100644
--- a/frontends/riscos/configure/con_content.c
+++ b/frontends/riscos/configure/con_content.c
@@ -30,7 +30,7 @@
#define CONTENT_BLOCK_ADVERTISEMENTS 2
#define CONTENT_BLOCK_POPUPS 3
-#define CONTENT_NO_PLUGINS 4
+#define CONTENT_BLOCK_CSS 4
#define CONTENT_TARGET_BLANK 7
#define CONTENT_DEFAULT_BUTTON 8
#define CONTENT_CANCEL_BUTTON 9
@@ -47,8 +47,8 @@ bool ro_gui_options_content_initialise(wimp_w w)
nsoption_bool(block_advertisements));
ro_gui_set_icon_selected_state(w, CONTENT_BLOCK_POPUPS,
nsoption_bool(block_popups));
- ro_gui_set_icon_selected_state(w, CONTENT_NO_PLUGINS,
- nsoption_bool(no_plugins));
+ ro_gui_set_icon_selected_state(w, CONTENT_BLOCK_CSS,
+ !nsoption_bool(author_level_css));
ro_gui_set_icon_selected_state(w, CONTENT_TARGET_BLANK,
nsoption_bool(target_blank));
ro_gui_set_icon_selected_state(w, CONTENT_NO_JAVASCRIPT,
@@ -57,7 +57,7 @@ bool ro_gui_options_content_initialise(wimp_w w)
/* initialise all functions for a newly created window */
ro_gui_wimp_event_register_checkbox(w, CONTENT_BLOCK_ADVERTISEMENTS);
ro_gui_wimp_event_register_checkbox(w, CONTENT_BLOCK_POPUPS);
- ro_gui_wimp_event_register_checkbox(w, CONTENT_NO_PLUGINS);
+ ro_gui_wimp_event_register_checkbox(w, CONTENT_BLOCK_CSS);
ro_gui_wimp_event_register_checkbox(w, CONTENT_TARGET_BLANK);
ro_gui_wimp_event_register_checkbox(w, CONTENT_NO_JAVASCRIPT);
ro_gui_wimp_event_register_button(w, CONTENT_DEFAULT_BUTTON,
@@ -78,7 +78,7 @@ void ro_gui_options_content_default(wimp_pointer *pointer)
false);
ro_gui_set_icon_selected_state(pointer->w, CONTENT_BLOCK_POPUPS,
false);
- ro_gui_set_icon_selected_state(pointer->w, CONTENT_NO_PLUGINS,
+ ro_gui_set_icon_selected_state(pointer->w, CONTENT_BLOCK_CSS,
false);
ro_gui_set_icon_selected_state(pointer->w, CONTENT_TARGET_BLANK,
true);
@@ -93,8 +93,8 @@ bool ro_gui_options_content_ok(wimp_w w)
nsoption_set_bool(block_popups,
ro_gui_get_icon_selected_state(w, CONTENT_BLOCK_POPUPS));
- nsoption_set_bool(no_plugins,
- ro_gui_get_icon_selected_state(w, CONTENT_NO_PLUGINS));
+ nsoption_set_bool(author_level_css,
+ !ro_gui_get_icon_selected_state(w, CONTENT_BLOCK_CSS));
nsoption_set_bool(target_blank,
ro_gui_get_icon_selected_state(w, CONTENT_TARGET_BLANK));
diff --git a/frontends/riscos/configure/con_image.c b/frontends/riscos/configure/con_image.c
index c7fc7f314..d81dc5c3b 100644
--- a/frontends/riscos/configure/con_image.c
+++ b/frontends/riscos/configure/con_image.c
@@ -23,6 +23,7 @@
#include "utils/nsoption.h"
#include "utils/log.h"
+#include "utils/utils.h"
#include "riscos/gui.h"
#include "riscos/configure/configure.h"
@@ -38,15 +39,10 @@
#define IMAGE_BACKGROUND_FIELD 6
#define IMAGE_BACKGROUND_MENU 7
#define IMAGE_CURRENT_DISPLAY 8
-#define IMAGE_SPEED_TEXT 11
-#define IMAGE_SPEED_FIELD 12
-#define IMAGE_SPEED_DEC 13
-#define IMAGE_SPEED_INC 14
-#define IMAGE_SPEED_CS 15
-#define IMAGE_DISABLE_ANIMATION 16
-#define IMAGE_DEFAULT_BUTTON 17
-#define IMAGE_CANCEL_BUTTON 18
-#define IMAGE_OK_BUTTON 19
+#define IMAGE_DISABLE_ANIMATION 11
+#define IMAGE_DEFAULT_BUTTON 12
+#define IMAGE_CANCEL_BUTTON 13
+#define IMAGE_OK_BUTTON 14
static bool ro_gui_options_image_click(wimp_pointer *pointer);
static bool ro_gui_options_image_ok(wimp_w w);
@@ -88,8 +84,6 @@ bool ro_gui_options_image_initialise(wimp_w w)
image_quality_menu->entries[i].
data.indirected_text.text, true);
}
- ro_gui_set_icon_decimal(w, IMAGE_SPEED_FIELD,
- nsoption_int(minimum_gif_delay), 2);
ro_gui_set_icon_selected_state(w, IMAGE_DISABLE_ANIMATION,
!nsoption_bool(animate_images));
ro_gui_options_update_shading(w);
@@ -99,11 +93,7 @@ bool ro_gui_options_image_initialise(wimp_w w)
IMAGE_FOREGROUND_MENU, image_quality_menu);
ro_gui_wimp_event_register_menu_gright(w, IMAGE_BACKGROUND_FIELD,
IMAGE_BACKGROUND_MENU, image_quality_menu);
- ro_gui_wimp_event_register_text_field(w, IMAGE_SPEED_TEXT);
- ro_gui_wimp_event_register_numeric_field(w, IMAGE_SPEED_FIELD,
- IMAGE_SPEED_INC, IMAGE_SPEED_DEC, 0, 6000, 10, 2);
ro_gui_wimp_event_register_checkbox(w, IMAGE_DISABLE_ANIMATION);
- ro_gui_wimp_event_register_text_field(w, IMAGE_SPEED_CS);
ro_gui_wimp_event_register_redraw_window(w,
ro_gui_options_image_redraw);
ro_gui_wimp_event_register_mouse_click(w,
@@ -218,10 +208,9 @@ bool ro_gui_options_image_click(wimp_pointer *pointer)
IMAGE_BACKGROUND_FIELD,
image_quality_menu->entries[2].
data.indirected_text.text, true);
- ro_gui_set_icon_decimal(pointer->w, IMAGE_SPEED_FIELD,
- 10, 2);
ro_gui_set_icon_selected_state(pointer->w,
IMAGE_DISABLE_ANIMATION, false);
+ fallthrough;
case IMAGE_DISABLE_ANIMATION:
ro_gui_options_update_shading(pointer->w);
break;
@@ -245,11 +234,6 @@ void ro_gui_options_update_shading(wimp_w w)
bool shaded;
shaded = ro_gui_get_icon_selected_state(w, IMAGE_DISABLE_ANIMATION);
- ro_gui_set_icon_shaded_state(w, IMAGE_SPEED_TEXT, shaded);
- ro_gui_set_icon_shaded_state(w, IMAGE_SPEED_FIELD, shaded);
- ro_gui_set_icon_shaded_state(w, IMAGE_SPEED_DEC, shaded);
- ro_gui_set_icon_shaded_state(w, IMAGE_SPEED_INC, shaded);
- ro_gui_set_icon_shaded_state(w, IMAGE_SPEED_CS, shaded);
}
bool ro_gui_options_image_ok(wimp_w w)
@@ -258,9 +242,6 @@ bool ro_gui_options_image_ok(wimp_w w)
(unsigned int *)&nsoption_int(plot_bg_quality),
(unsigned int *)&nsoption_int(plot_fg_quality));
- nsoption_set_int(minimum_gif_delay,
- ro_gui_get_icon_decimal(w, IMAGE_SPEED_FIELD, 2));
-
nsoption_set_bool(animate_images,
!ro_gui_get_icon_selected_state(w,
IMAGE_DISABLE_ANIMATION));
diff --git a/frontends/riscos/content-handlers/artworks.c b/frontends/riscos/content-handlers/artworks.c
index 8ec4edcae..c107ec6b4 100644
--- a/frontends/riscos/content-handlers/artworks.c
+++ b/frontends/riscos/content-handlers/artworks.c
@@ -38,7 +38,9 @@
#include "utils/utils.h"
#include "netsurf/plotters.h"
#include "netsurf/content.h"
+#include "content/content.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
#include "content/llcache.h"
#include "riscos/content-handlers/artworks.h"
@@ -91,7 +93,7 @@ struct awinfo_block {
/* Assembler routines for interfacing with the ArtworksRenderer module */
extern os_error *awrender_init(const char **doc,
- unsigned long *doc_size,
+ size_t *doc_size,
void *routine,
void *workspace);
@@ -170,8 +172,8 @@ bool artworks_convert(struct content *c)
{
artworks_content *aw = (artworks_content *) c;
union content_msg_data msg_data;
- const char *source_data;
- unsigned long source_size;
+ const uint8_t *source_data;
+ size_t source_size;
void *init_workspace;
void *init_routine;
os_error *error;
@@ -184,7 +186,8 @@ bool artworks_convert(struct content *c)
&used, NULL, NULL);
if (used >= 0) {
NSLOG(netsurf, INFO, "Alias$LoadArtWorksModules not defined");
- msg_data.error = messages_get("AWNotSeen");
+ msg_data.errordata.errorcode = NSERROR_UNKNOWN;
+ msg_data.errordata.errormsg = messages_get("AWNotSeen");
content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
return false;
}
@@ -194,7 +197,8 @@ bool artworks_convert(struct content *c)
if (error) {
NSLOG(netsurf, INFO, "xos_cli: 0x%x: %s", error->errnum,
error->errmess);
- msg_data.error = error->errmess;
+ msg_data.errordata.errorcode = NSERROR_UNKNOWN;
+ msg_data.errordata.errormsg = error->errmess;
content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
return false;
}
@@ -205,7 +209,8 @@ bool artworks_convert(struct content *c)
if (error) {
NSLOG(netsurf, INFO, "AWRender_FileInitAddress: 0x%x: %s",
error->errnum, error->errmess);
- msg_data.error = error->errmess;
+ msg_data.errordata.errorcode = NSERROR_UNKNOWN;
+ msg_data.errordata.errormsg = error->errmess;
content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
return false;
}
@@ -216,7 +221,8 @@ bool artworks_convert(struct content *c)
if (error) {
NSLOG(netsurf, INFO, "AWRender_RenderAddress: 0x%x: %s",
error->errnum, error->errmess);
- msg_data.error = error->errmess;
+ msg_data.errordata.errorcode = NSERROR_UNKNOWN;
+ msg_data.errordata.errormsg = error->errmess;
content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
return false;
}
@@ -224,12 +230,13 @@ bool artworks_convert(struct content *c)
source_data = content__get_source_data(c, &source_size);
/* initialise (convert file to new format if required) */
- error = awrender_init(&source_data, &source_size,
+ error = awrender_init((const char **)&source_data, &source_size,
init_routine, init_workspace);
if (error) {
NSLOG(netsurf, INFO, "awrender_init: 0x%x : %s",
error->errnum, error->errmess);
- msg_data.error = error->errmess;
+ msg_data.errordata.errorcode = NSERROR_UNKNOWN;
+ msg_data.errordata.errormsg = error->errmess;
content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
return false;
}
@@ -245,7 +252,8 @@ bool artworks_convert(struct content *c)
if (error) {
NSLOG(netsurf, INFO, "AWRender_DocBounds: 0x%x: %s",
error->errnum, error->errmess);
- msg_data.error = error->errmess;
+ msg_data.errordata.errorcode = NSERROR_UNKNOWN;
+ msg_data.errordata.errormsg = error->errmess;
content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
return false;
}
@@ -261,7 +269,8 @@ bool artworks_convert(struct content *c)
if (!aw->block) {
NSLOG(netsurf, INFO,
"failed to create block for ArtworksRenderer");
- msg_data.error = messages_get("NoMemory");
+ msg_data.errordata.errorcode = NSERROR_NOMEM;
+ msg_data.errordata.errormsg = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
return false;
}
@@ -313,8 +322,8 @@ bool artworks_redraw(struct content *c, struct content_redraw_data *data,
};
artworks_content *aw = (artworks_content *) c;
struct awinfo_block info;
- const char *source_data;
- unsigned long source_size;
+ const uint8_t *source_data;
+ size_t source_size;
os_error *error;
os_trfm matrix;
int vals[24];
@@ -389,17 +398,17 @@ bool artworks_redraw(struct content *c, struct content_redraw_data *data,
source_data = content__get_source_data(c, &source_size);
- error = awrender_render(source_data,
- &info,
- &matrix,
- vals,
- &aw->block,
- &aw->size,
- 110, /* fully anti-aliased */
- 0,
- source_size,
- aw->render_routine,
- aw->render_workspace);
+ error = awrender_render((const char *)source_data,
+ &info,
+ &matrix,
+ vals,
+ &aw->block,
+ &aw->size,
+ 110, /* fully anti-aliased */
+ 0,
+ source_size,
+ aw->render_routine,
+ aw->render_workspace);
if (error) {
NSLOG(netsurf, INFO, "awrender_render: 0x%x: %s",
diff --git a/frontends/riscos/content-handlers/awrender.s b/frontends/riscos/content-handlers/awrender.s
index 5bcafe520..fe37f66fb 100644
--- a/frontends/riscos/content-handlers/awrender.s
+++ b/frontends/riscos/content-handlers/awrender.s
@@ -209,12 +209,18 @@ errblk % 256
@ os_error *awrender_init(byte **doc, size_t *doc_size, void *init_routine, void *init_workspace);
.global awrender_init
-awrender_init: MOV ip,sp
+awrender_init:
+#ifndef __ARM_EABI__
+ MOV ip,sp
STMFD sp!,{a1,a2,v1,v2,fp,ip,lr,pc}
SUB fp,ip,#4
SUB ip,sp,#512
CMP ip,sl
BLMI __rt_stkovf_split_big
+#else
+ STMFD sp!,{a1,a2,v1,v2,fp,lr}
+ ADD fp,sp,#4*4
+#endif
LDR v2,=aw_temp
LDR a1,[a1]
@@ -235,14 +241,18 @@ awrender_init: MOV ip,sp
@ return updated block ptr & size to caller
- LDR a2,[fp,#-28]
- LDR a3,[fp,#-24]
+ LDR a2,[sp],#4
+ LDR a3,[sp],#4
LDR ip,[v2,#aw_rsz_block]
LDR lr,[v2,#aw_rsz_size]
STR ip,[a2]
STR lr,[a3]
- LDMEA fp,{v1,v2,fp,sp,pc}
+#ifndef __ARM_EABI__
+ LDMDB fp,{v1,v2,fp,sp,pc}
+#else
+ LDMIA sp!,{v1,v2,fp,pc}
+#endif
@ os_error *awrender_render(const char *doc,
@@ -258,37 +268,46 @@ awrender_init: MOV ip,sp
@ void *workspace);
.global awrender_render
-awrender_render: MOV ip,sp
- STMFD sp!,{v1-v4,fp,ip,lr,pc}
+awrender_render:
+#ifndef __ARM_EABI__
+ MOV ip,sp
+ STMFD sp!,{v1-v6,fp,ip,lr,pc}
SUB fp,ip,#4
SUB ip,sp,#512
CMP ip,sl
BLMI __rt_stkovf_split_big
+ ADD ip,fp,#4 @ ip -> stacked args
+#else
+ MOV ip,sp @ ip -> stacked args
+ STMFD sp!,{v1-v6,fp,lr}
+ ADD fp,sp,#6*4
+#endif
- LDR R12,[fp,#20]
LDR R14,=aw_temp
- LDR R5,[fp,#4]
- LDR R6,[fp,#12]
+ LDR R5,[ip,#0] @ rsz_block
+ LDR R6,[ip,#8] @ wysiwyg_setting
LDR R4,[R5] @ resizable block
- LDR R7,[fp,#16]
+ LDR R7,[ip,#12] @ output_dest
+ LDR R8,[ip,#16] @ doc_size
+ LDR R9,[ip,#4] @ rsz_size
STR R4,[R14,#aw_rsz_block]
STR R0,[R14,#aw_fixed_block] @ document ptr
- STR R12,[R14,#aw_fixed_size] @ document size
- LDR R12,[fp,#8]
+ STR R8,[R14,#aw_fixed_size] @ document size
STR R5,[sp,#-4]! @ ptr to receive block
- STR R12,[sp,#-4]! @ ptr to receive size
+ STR R9,[sp,#-4]! @ ptr to receive size
- LDR R12,[R12]
+ LDR R9,[R9]
ADR R5,aw_callback
- STR R12,[R14,#aw_rsz_size]
+ STR R9,[R14,#aw_rsz_size]
STR sl,[R14,#aw_sl]
STR fp,[R14,#aw_fp]
- LDR R12,[fp,#28]
+ LDR R8,[ip,#20] @ routine
+ LDR R12,[ip,#24] @ workspace
MOV lr,pc
- LDR pc,[fp,#24]
+ MOV pc,R8
MOVVC a1,#0
@ return updated block ptr & size to caller
@@ -301,7 +320,11 @@ awrender_render: MOV ip,sp
STR R5,[R12]
STR R6,[R4]
- LDMEA fp,{v1-v4,fp,sp,pc}
+#ifndef __ARM_EABI__
+ LDMDB fp,{v1-v6,fp,sp,pc}
+#else
+ LDMIA sp!,{v1-v6,fp,pc}
+#endif
@ Callback routine for block resizing
@@ -340,11 +363,18 @@ aw_callback: TEQ R11,#3
CMP R1,R2
BLS aw_read
- STMFD R13!,{R1,R10-R12,R14}
+ STMFD R13!,{R1,R4,R10-R12,R14}
+#ifdef __ARM_EABI__
+ MOV R4,R13 @ save original sp
+ BIC R13,R13,#7 @ align to multiple of 8
+#endif
LDR sl,[R11,#aw_sl]
LDR fp,[R11,#aw_fp]
BL realloc
- LDMFD R13!,{R1,R10-R12,R14}
+#ifdef __ARM_EABI__
+ MOV R13,R4 @ restore unaligned sp
+#endif
+ LDMFD R13!,{R1,R4,R10-R12,R14}
CMP R0,#0 @ did it work?
BEQ aw_nomem
@@ -359,7 +389,11 @@ aw_read: @ return details of fixed block
SUBS R11,R11,R11 @ clear V
MOV PC,R14
-aw_nomem: STMFD R13!,{R10,R12,R14}
+aw_nomem: STMFD R13!,{R4,R10,R12,R14}
+#ifdef __ARM_EABI__
+ MOV R4,R13 @ save original sp
+ BIC R13,R13,#7 @ align to multiple of 8
+#endif
LDR sl,[R11,#aw_sl]
LDR fp,[R11,#aw_fp]
ADR R0,tok_nomem
@@ -370,13 +404,17 @@ aw_nomem: STMFD R13!,{R10,R12,R14}
SUB R0,R0,#4 @ error number already 0
MOV R11,#0 @ restore reason code
CMP PC,#1<<31 @ set V
- LDMFD R13!,{R10,R12,PC}
+#ifdef __ARM_EABI__
+ MOV R13,R4 @ restore original sp
+#endif
+ LDMFD R13!,{R4,R10,R12,PC}
tok_nomem: .asciz "NoMemory"
.align
.bss
+ .align
aw_temp: .space sizeof_aw
.type aw_temp, %object
.size aw_temp, . - aw_temp
diff --git a/frontends/riscos/content-handlers/draw.c b/frontends/riscos/content-handlers/draw.c
index bb66f9dbb..522d5d3fe 100644
--- a/frontends/riscos/content-handlers/draw.c
+++ b/frontends/riscos/content-handlers/draw.c
@@ -35,7 +35,9 @@
#include "utils/utils.h"
#include "netsurf/plotters.h"
#include "netsurf/content.h"
+#include "content/content.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
#include "content/llcache.h"
#include "riscos/content-handlers/draw.h"
@@ -112,8 +114,8 @@ bool draw_convert(struct content *c)
{
draw_content *draw = (draw_content *) c;
union content_msg_data msg_data;
- const char *source_data;
- unsigned long source_size;
+ const uint8_t *source_data;
+ size_t source_size;
const void *data;
os_box bbox;
os_error *error;
@@ -128,7 +130,8 @@ bool draw_convert(struct content *c)
if (error) {
NSLOG(netsurf, INFO, "xdrawfile_bbox: 0x%x: %s",
error->errnum, error->errmess);
- msg_data.error = error->errmess;
+ msg_data.errordata.errorcode = NSERROR_UNKNOWN;
+ msg_data.errordata.errormsg = error->errmess;
content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
return false;
}
@@ -180,8 +183,8 @@ bool draw_redraw(struct content *c, struct content_redraw_data *data,
{
draw_content *draw = (draw_content *) c;
os_trfm matrix;
- const char *source_data;
- unsigned long source_size;
+ const uint8_t *source_data;
+ size_t source_size;
const void *src_data;
os_error *error;
diff --git a/frontends/riscos/content-handlers/sprite.c b/frontends/riscos/content-handlers/sprite.c
index 3556aa555..f6ab68451 100644
--- a/frontends/riscos/content-handlers/sprite.c
+++ b/frontends/riscos/content-handlers/sprite.c
@@ -16,7 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Content for image/x-riscos-sprite (RISC OS implementation).
*
* No conversion is necessary: we can render RISC OS sprites directly under
@@ -35,7 +36,9 @@
#include "netsurf/plotters.h"
#include "netsurf/content.h"
#include "content/llcache.h"
+#include "content/content.h"
#include "content/content_protected.h"
+#include "content/content_factory.h"
#include "riscos/gui.h"
#include "riscos/image.h"
@@ -112,8 +115,8 @@ bool sprite_convert(struct content *c)
os_error *error;
int w, h;
union content_msg_data msg_data;
- const char *source_data;
- unsigned long source_size;
+ const uint8_t *source_data;
+ size_t source_size;
const void *sprite_data;
char *title;
@@ -125,7 +128,8 @@ bool sprite_convert(struct content *c)
/* check for bad data */
if ((int)source_size + 4 != area->used) {
- msg_data.error = messages_get("BadSprite");
+ msg_data.errordata.errorcode = NSERROR_UNKNOWN;
+ msg_data.errordata.errormsg = messages_get("BadSprite");
content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
return false;
}
@@ -139,7 +143,8 @@ bool sprite_convert(struct content *c)
"xosspriteop_read_sprite_info: 0x%x: %s",
error->errnum,
error->errmess);
- msg_data.error = error->errmess;
+ msg_data.errordata.errorcode = NSERROR_UNKNOWN;
+ msg_data.errordata.errormsg = error->errmess;
content_broadcast(c, CONTENT_MSG_ERROR, &msg_data);
return false;
}
diff --git a/frontends/riscos/cookies.c b/frontends/riscos/cookies.c
index 125d04356..199699dba 100644
--- a/frontends/riscos/cookies.c
+++ b/frontends/riscos/cookies.c
@@ -342,6 +342,7 @@ cookie_menu_select(wimp_w w,
*/
static nserror ro_cookie_init(void)
{
+ os_error *error;
struct ro_cookie_window *ncwin;
nserror res;
static const struct ns_menu cookie_menu_def = {
@@ -383,7 +384,14 @@ static nserror ro_cookie_init(void)
}
/* create window from template */
- ncwin->core.wh = wimp_create_window(dialog_cookie_template);
+ error = xwimp_create_window(dialog_cookie_template, &ncwin->core.wh);
+ if (error) {
+ NSLOG(netsurf, INFO, "xwimp_create_window: 0x%x: %s",
+ error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ free(ncwin);
+ return NSERROR_NOMEM;
+ }
ro_gui_set_window_title(ncwin->core.wh, messages_get("Cookies"));
@@ -439,7 +447,7 @@ static nserror ro_cookie_init(void)
/* exported interface documented in riscos/cookies.h */
-nserror ro_gui_cookies_present(void)
+nserror ro_gui_cookies_present(const char *search_term)
{
nserror res;
@@ -449,6 +457,9 @@ nserror ro_gui_cookies_present(void)
ro_gui_dialog_open_top(cookie_window->core.wh,
cookie_window->core.toolbar,
600, 800);
+ if (search_term != NULL) {
+ res = cookie_manager_set_search_string(search_term);
+ }
} else {
NSLOG(netsurf, INFO, "Failed presenting code %d", res);
}
diff --git a/frontends/riscos/cookies.h b/frontends/riscos/cookies.h
index 1b07d2122..6a217903e 100644
--- a/frontends/riscos/cookies.h
+++ b/frontends/riscos/cookies.h
@@ -41,7 +41,7 @@ void ro_gui_cookies_initialise(void);
*
* \return NSERROR_OK on success else appropriate error code on faliure.
*/
-nserror ro_gui_cookies_present(void);
+nserror ro_gui_cookies_present(const char *search_term);
/**
* Free any resources allocated for the cookie window.
diff --git a/frontends/riscos/corewindow.c b/frontends/riscos/corewindow.c
index 84177aa90..88bb5c3ef 100644
--- a/frontends/riscos/corewindow.c
+++ b/frontends/riscos/corewindow.c
@@ -45,12 +45,15 @@
#include "riscos/window.h"
#include "riscos/toolbar.h"
#include "riscos/mouse.h"
+#include "riscos/wimputils.h"
#include "riscos/corewindow.h"
#ifndef wimp_KEY_END
#define wimp_KEY_END wimp_KEY_COPY
#endif
+static struct ro_corewindow *ro_cw_drag_cw;
+
/**
* Update a windows scrollbars.
*
@@ -119,10 +122,15 @@ static void ro_cw_redraw(wimp_draw *redraw)
origin_x = redraw->box.x0 - redraw->xscroll;
origin_y = redraw->box.y1 + ro_cw->origin_y - redraw->yscroll;
- r.x0 = (redraw->clip.x0 - origin_x) / 2;
- r.y0 = (origin_y - redraw->clip.y1) / 2;
- r.x1 = r.x0 + ((redraw->clip.x1 - redraw->clip.x0) / 2);
- r.y1 = r.y0 + ((redraw->clip.y1 - redraw->clip.y0) / 2);
+ ro_plot_clip_rect.x0 = redraw->clip.x0 - origin_x;
+ ro_plot_clip_rect.y0 = origin_y - redraw->clip.y0;
+ ro_plot_clip_rect.x1 = redraw->clip.x1 - origin_x;
+ ro_plot_clip_rect.y1 = origin_y - redraw->clip.y1;
+
+ r.x0 = (ro_plot_clip_rect.x0 ) / 2; /* left */
+ r.y0 = (ro_plot_clip_rect.y1 ) / 2; /* top */
+ r.x1 = (ro_plot_clip_rect.x1 + 1) / 2; /* right */
+ r.y1 = (ro_plot_clip_rect.y0 + 1) / 2; /* bottom */
/* call the draw callback */
ro_cw->draw(ro_cw, origin_x, origin_y, &r);
@@ -143,10 +151,24 @@ static void ro_cw_scroll(wimp_scroll *scroll)
int page_y;
struct ro_corewindow *ro_cw;
wimp_open open;
+ wimp_window_state state;
ro_cw = (struct ro_corewindow *)ro_gui_wimp_event_get_user_data(scroll->w);
NSLOG(netsurf, INFO, "RO corewindow context %p", ro_cw);
+ state.w = ro_cw->wh;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ NSLOG(netsurf, INFO, "xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess);
+ return;
+ }
+
+ /* Don't try to update window if it's closed */
+ if (!(state.flags & wimp_WINDOW_OPEN)) {
+ return;
+ }
+
page_x = scroll->visible.x1 - scroll->visible.x0 - 32;
page_y = scroll->visible.y1 - scroll->visible.y0 - 32;
@@ -235,6 +257,11 @@ static void ro_cw_mouse_at(wimp_pointer *pointer, void *data)
(unsigned int)pointer->w);
return;
}
+ if (ro_cw != ro_cw_drag_cw) {
+ NSLOG(netsurf, DEEPDEBUG, "Called without drag window: %p",
+ ro_cw);
+ return;
+ }
NSLOG(netsurf, INFO, "RO corewindow context %p", ro_cw);
/* Not a Menu click. */
@@ -371,6 +398,7 @@ ro_cw_drag_start(struct ro_corewindow *ro_cw,
ro_warn_user("WimpError", error->errmess);
}
+ ro_cw_drag_cw = ro_cw;
ro_mouse_drag_start(ro_cw_drag_end, ro_cw_mouse_at, NULL, NULL);
}
}
@@ -791,7 +819,7 @@ ro_cw_invalidate(struct core_window *cw, const struct rect *r)
/**
* Callback from the core to update the content area size.
*/
-static void
+static nserror
ro_cw_update_size(struct core_window *cw, int width, int height)
{
struct ro_corewindow *ro_cw = (struct ro_corewindow *)cw;
@@ -810,7 +838,7 @@ ro_cw_update_size(struct core_window *cw, int width, int height)
if (error) {
NSLOG(netsurf, INFO, "xwimp_get_window_state: 0x%x: %s",
error->errnum, error->errmess);
- return;
+ return NSERROR_INVALID;
}
/* only update the window if it is open */
@@ -823,16 +851,63 @@ ro_cw_update_size(struct core_window *cw, int width, int height)
update_scrollbars(ro_cw, &open);
}
+ return NSERROR_OK;
}
/**
* Callback from the core to scroll the visible content.
*/
-static void
-ro_cw_scroll_visible(struct core_window *cw, const struct rect *r)
+static nserror
+ro_cw_get_scroll(const struct core_window *cw, int *x, int *y)
{
- //struct ro_corewindow *ro_cw = (struct ro_corewindow *)cw;
+ struct ro_corewindow *ro_cw = (struct ro_corewindow *)cw;
+ wimp_window_state state = {
+ .w = ro_cw->wh,
+ };
+ os_error *error;
+
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ NSLOG(netsurf, ERROR, "xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess);
+ return NSERROR_INVALID;
+ }
+
+ *x = state.xscroll / 2;
+ *y = -state.yscroll / 2;
+ return NSERROR_OK;
+}
+
+
+/**
+ * Callback from the core to scroll the visible content.
+ */
+static nserror
+ro_cw_set_scroll(struct core_window *cw, int x, int y)
+{
+ struct ro_corewindow *ro_cw = (struct ro_corewindow *)cw;
+ wimp_window_state state = {
+ .w = ro_cw->wh,
+ };
+ os_error *error;
+
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ NSLOG(netsurf, ERROR, "xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess);
+ return NSERROR_INVALID;
+ }
+
+ state.xscroll = x * 2;
+ state.yscroll = -y * 2;
+
+ /* only update the window if it is open */
+ if (state.flags & wimp_WINDOW_OPEN) {
+ update_scrollbars(ro_cw, PTR_WIMP_OPEN(&state));
+ }
+
+ return NSERROR_OK;
}
@@ -843,8 +918,9 @@ ro_cw_scroll_visible(struct core_window *cw, const struct rect *r)
* \param[out] width to be set to viewport width in px
* \param[out] height to be set to viewport height in px
*/
-static void
-ro_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
+static nserror
+ro_cw_get_window_dimensions(const struct core_window *cw,
+ int *width, int *height)
{
struct ro_corewindow *ro_cw = (struct ro_corewindow *)cw;
os_error *error;
@@ -855,29 +931,42 @@ ro_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
if (error) {
NSLOG(netsurf, INFO, "xwimp_get_window_state: 0x%x: %s",
error->errnum, error->errmess);
- return;
+ return NSERROR_INVALID;
}
*width = (state.visible.x1 - state.visible.x0) / 2;
*height = (state.visible.y1 - state.visible.y0) / 2;
+
+ /* Account for toolbar height, if present */
+ if (ro_cw->toolbar != NULL) {
+ *height -= ro_toolbar_full_height(ro_cw->toolbar) / 2;
+ }
+ if (*height < 0) {
+ *height = 0;
+ }
+
+ return NSERROR_OK;
}
/**
* Callback from the core to update the drag status.
*/
-static void
+static nserror
ro_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
{
struct ro_corewindow *ro_cw = (struct ro_corewindow *)cw;
ro_cw->drag_status = ds;
+
+ return NSERROR_OK;
}
struct core_window_callback_table ro_cw_cb_table = {
.invalidate = ro_cw_invalidate,
.update_size = ro_cw_update_size,
- .scroll_visible = ro_cw_scroll_visible,
+ .set_scroll = ro_cw_set_scroll,
+ .get_scroll = ro_cw_get_scroll,
.get_window_dimensions = ro_cw_get_window_dimensions,
.drag_status = ro_cw_drag_status
};
@@ -965,6 +1054,8 @@ ro_corewindow_init(struct ro_corewindow *ro_cw,
}
/* setup context for event handlers */
+ NSLOG(netsurf, INFO, "Setting corewindow %p for window handle %p",
+ ro_cw, ro_cw->wh);
ro_gui_wimp_event_set_user_data(ro_cw->wh, ro_cw);
/* register wimp events. */
diff --git a/frontends/riscos/dialog.c b/frontends/riscos/dialog.c
index a50d1289b..67019c4ff 100644
--- a/frontends/riscos/dialog.c
+++ b/frontends/riscos/dialog.c
@@ -39,6 +39,7 @@
#include "utils/messages.h"
#include "utils/nsurl.h"
#include "desktop/version.h"
+#include "desktop/searchweb.h"
#include "netsurf/browser_window.h"
#include "riscos/configure.h"
@@ -49,9 +50,9 @@
#include "riscos/gui.h"
#include "riscos/window.h"
#include "riscos/hotlist.h"
+#include "riscos/pageinfo.h"
#include "riscos/menus.h"
#include "riscos/save.h"
-#include "riscos/sslcert.h"
#include "riscos/toolbar.h"
#include "riscos/url_complete.h"
#include "riscos/url_suggest.h"
@@ -72,7 +73,6 @@
wimp_w dialog_info, dialog_saveas,
- dialog_401li,
dialog_zoom, dialog_pageinfo, dialog_objinfo, dialog_tooltip,
dialog_warning,
dialog_folder, dialog_entry, dialog_search, dialog_print,
@@ -114,9 +114,6 @@ void ro_gui_dialog_init(void)
/* configure window */
ro_gui_configure_initialise();
- /* 401 login window */
- ro_gui_401login_init();
-
/* theme installation */
dialog_theme_install = ro_gui_dialog_create("theme_inst");
ro_gui_wimp_event_register_cancel(dialog_theme_install,
@@ -182,9 +179,6 @@ void ro_gui_dialog_init(void)
* associated dialogues to be set up first.
*/
- /* certificate verification window */
- ro_gui_cert_initialise();
-
/* hotlist window */
ro_gui_hotlist_initialise();
@@ -196,6 +190,9 @@ void ro_gui_dialog_init(void)
/* cookies window */
ro_gui_cookies_initialise();
+
+ /* page info window */
+ ro_gui_pageinfo_initialise();
}
@@ -339,12 +336,16 @@ void ro_gui_dialog_close(wimp_w close)
{
int i;
wimp_caret caret;
+ wimp_w parent = (wimp_w)-1;
os_error *error;
/* Check if we're a persistent window */
for (i = 0; i < MAX_PERSISTENT; i++) {
if (persistent_dialog[i].dialog == close) {
/* We are => invalidate record */
+ if (persistent_dialog[i].parent != NULL) {
+ parent = persistent_dialog[i].parent;
+ }
persistent_dialog[i].parent = NULL;
persistent_dialog[i].dialog = NULL;
break;
@@ -367,7 +368,7 @@ void ro_gui_dialog_close(wimp_w close)
/* Check if we are a persistent window */
if (i < MAX_PERSISTENT) {
error = xwimp_set_caret_position(
- persistent_dialog[i].parent,
+ parent,
wimp_ICON_WINDOW, -100, -100,
32, -1);
/* parent may have been closed first */
@@ -429,9 +430,9 @@ bool ro_gui_dialog_open_top(wimp_w w, struct toolbar *toolbar,
if (!open) {
int dimension;
int scroll_width;
- /* cancel any editing */
- if (ro_toolbar_get_editing(toolbar))
- ro_toolbar_toggle_edit(toolbar);
+ /* cancel any editing */
+ if (ro_toolbar_get_editing(toolbar))
+ ro_toolbar_toggle_edit(toolbar);
/* move to the centre */
ro_gui_screen_size(&screen_width, &screen_height);
@@ -605,7 +606,7 @@ void ro_gui_dialog_open_persistent(wimp_w parent, wimp_w w, bool pointer) {
void ro_gui_dialog_add_persistent(wimp_w parent, wimp_w w) {
- int i;
+ int i;
/* all persistant windows have a back icon */
ro_gui_wimp_update_window_furniture(w, wimp_WINDOW_BACK_ICON,
@@ -754,9 +755,9 @@ static bool ro_gui_dialog_open_url_init(void)
xwimp_close_template();
die(error->errmess);
}
-
+
free(definition);
-
+
ro_gui_wimp_event_register_menu_gright(dialog_openurl, ICON_OPENURL_URL,
ICON_OPENURL_MENU, ro_gui_url_suggest_menu);
ro_gui_wimp_event_register_cancel(dialog_openurl, ICON_OPENURL_CANCEL);
@@ -771,35 +772,31 @@ static bool ro_gui_dialog_open_url_init(void)
-bool ro_gui_dialog_openurl_apply(wimp_w w) {
- const char *urltxt;
- char *url2;
+bool ro_gui_dialog_openurl_apply(wimp_w w)
+{
+ nserror res;
+ const char *url_s;
nsurl *url;
- nserror error;
- urltxt = ro_gui_get_icon_string(w, ICON_OPENURL_URL);
- url2 = strdup(urltxt); /** @todo why is this copied */
- if (url2 == NULL) {
- return false;
- }
+ url_s = ro_gui_get_icon_string(w, ICON_OPENURL_URL);
+
+ res = search_web_omni(url_s, SEARCH_WEB_OMNI_NONE, &url);
- error = nsurl_create(url2, &url);
- free(url2);
- if (error == NSERROR_OK) {
- error = browser_window_create(BW_CREATE_HISTORY,
- url,
- NULL,
- NULL,
- NULL);
+ if (res == NSERROR_OK) {
+ res = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
nsurl_unref(url);
}
- if (error != NSERROR_OK) {
- ro_warn_user(messages_get_errorcode(error), 0);
+
+ if (res != NSERROR_OK) {
+ ro_warn_user(messages_get_errorcode(res), 0);
return false;
}
return true;
-
}
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Boot,feb b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Boot,feb
index 7c0c46241..b2cdbf102 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Boot,feb
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Boot,feb
@@ -2,4 +2,4 @@
|
Set Unicode$Dir <Obey$Dir>
SetMacro Unicode$Path <Unicode$Dir>.,Resources:$.Resources.Unicode.
-IconSprites Unicode:!Sprites
+IconSprites Unicode:Themes.!Sprites
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Help b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Help
index 8c0488185..a24701e02 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Help
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Help
@@ -1 +1,5 @@
-This application contains resources for Unicode support in applications.
+ !Unicode
+ ========
+
+This application contains resources for Unicode support in
+applications.
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Run,feb b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Run,feb
index bd70e96ac..40999ded5 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Run,feb
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Run,feb
@@ -2,4 +2,4 @@
|
Set Unicode$Dir <Obey$Dir>
SetMacro Unicode$Path <Unicode$Dir>.,Resources:$.Resources.Unicode.
-IconSprites Unicode:!Sprites
+IconSprites Unicode:Themes.!Sprites
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Acorn/Latin1 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Acorn/Latin1,ffd
index bdf5d3b67..bdf5d3b67 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Acorn/Latin1
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Acorn/Latin1,ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/CentEuro b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/CentEuro,ffd
index 5ab69ff2e..5ab69ff2e 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/CentEuro
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/CentEuro,ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Cyrillic b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Cyrillic,ffd
index 670fd6cdc..670fd6cdc 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Cyrillic
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Cyrillic,ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Roman b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Roman,ffd
index 254579e2c..254579e2c 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Roman
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Roman,ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Ukrainian b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Ukrainian,ffd
index a220587ba..a220587ba 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Ukrainian
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Ukrainian,ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/BigFive b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/BigFive,ffd
index c659cef19..c659cef19 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/BigFive
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/BigFive,ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C0/40[ISO646] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C0/40[ISO646],ffd
index cd92b5486..cd92b5486 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C0/40[ISO646]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C0/40[ISO646],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C1/43[IS6429] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C1/43[IS6429],ffd
index 74002a168..74002a168 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C1/43[IS6429]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C1/43[IS6429],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/40[646old] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/40[646old],ffd
index 00e2d1096..00e2d1096 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/40[646old]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/40[646old],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/41[646-GB] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/41[646-GB],ffd
index c293f93d6..c293f93d6 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/41[646-GB]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/41[646-GB],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/42[646IRV] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/42[646IRV],ffd
index e0b4bcadb..e0b4bcadb 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/42[646IRV]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/42[646IRV],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/43[FinSwe] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/43[FinSwe],ffd
index 7d4646905..7d4646905 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/43[FinSwe]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/43[FinSwe],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/47[646-SE] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/47[646-SE],ffd
index a6b091a22..a6b091a22 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/47[646-SE]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/47[646-SE],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/48[646-SE] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/48[646-SE],ffd
index 9bd24ab29..9bd24ab29 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/48[646-SE]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/48[646-SE],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/49[JS201K] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/49[JS201K],ffd
index 20ce8d498..20ce8d498 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/49[JS201K]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/49[JS201K],ffd
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4A[JS201R] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4A[JS201R],ffd
index 21d2a479b..21d2a479b 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4A[JS201R]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4A[JS201R],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4B[646-DE] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4B[646-DE],ffd
index a2e284e1b..a2e284e1b 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4B[646-DE]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4B[646-DE],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4C[646-PT] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4C[646-PT],ffd
index e076e2517..e076e2517 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4C[646-PT]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4C[646-PT],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/54[GB1988] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/54[GB1988],ffd
index 3b43719ce..3b43719ce 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/54[GB1988]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/54[GB1988],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/56[Teltxt] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/56[Teltxt],ffd
index 73ce49e17..73ce49e17 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/56[Teltxt]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/56[Teltxt],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/59[646-IT] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/59[646-IT],ffd
index f1ae81962..f1ae81962 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/59[646-IT]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/59[646-IT],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/5A[646-ES] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/5A[646-ES],ffd
index 674fc2d70..674fc2d70 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/5A[646-ES]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/5A[646-ES],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/60[646-NO] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/60[646-NO],ffd
index fc92892ee..fc92892ee 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/60[646-NO]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/60[646-NO],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/66[646-FR] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/66[646-FR],ffd
index 8dd604679..8dd604679 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/66[646-FR]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/66[646-FR],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/69[646-HU] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/69[646-HU],ffd
index 65300b2c5..65300b2c5 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/69[646-HU]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/69[646-HU],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6B[Arabic] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6B[Arabic],ffd
index c47689914..c47689914 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6B[Arabic]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6B[Arabic],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6C[IS6937] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6C[IS6937],ffd
index 93453f5de..93453f5de 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6C[IS6937]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6C[IS6937],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/7A[SerbCr] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/7A[SerbCr],ffd
index 9740e784e..9740e784e 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/7A[SerbCr]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/7A[SerbCr],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/40[JS6226] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/40[JS6226],ffd
index a677dfc3d..a677dfc3d 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/40[JS6226]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/40[JS6226],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/41[GB2312] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/41[GB2312],ffd
index 679608ad2..679608ad2 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/41[GB2312]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/41[GB2312],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/42[JIS208] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/42[JIS208],ffd
index 532b1f4f3..532b1f4f3 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/42[JIS208]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/42[JIS208],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/43[KS1001] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/43[KS1001],ffd
index 36186c864..36186c864 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/43[KS1001]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/43[KS1001],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/44[JIS212] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/44[JIS212],ffd
index f5343a30e..f5343a30e 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/44[JIS212]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/44[JIS212],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/47[CNS1] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/47[CNS1],ffd
index da07f45d3..da07f45d3 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/47[CNS1]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/47[CNS1],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/48[CNS2] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/48[CNS2],ffd
index 44ee24c91..44ee24c91 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/48[CNS2]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/48[CNS2],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/49[CNS3] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/49[CNS3],ffd
index a8464e5aa..a8464e5aa 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/49[CNS3]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/49[CNS3],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4A[CNS4] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4A[CNS4],ffd
index a8f3e3270..a8f3e3270 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4A[CNS4]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4A[CNS4],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4B[CNS5] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4B[CNS5],ffd
index 535b0f4b5..535b0f4b5 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4B[CNS5]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4B[CNS5],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4C[CNS6] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4C[CNS6],ffd
index 7bfb2b1d4..7bfb2b1d4 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4C[CNS6]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4C[CNS6],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4D[CNS7] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4D[CNS7],ffd
index be14c7279..be14c7279 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4D[CNS7]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4D[CNS7],ffd
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/41[Lat1] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/41[Lat1],ffd
index 97e6b1106..97e6b1106 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/41[Lat1]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/41[Lat1],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/42[Lat2] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/42[Lat2],ffd
index b753c40fe..b753c40fe 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/42[Lat2]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/42[Lat2],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/43[Lat3] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/43[Lat3],ffd
index 88d477886..88d477886 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/43[Lat3]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/43[Lat3],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/44[Lat4] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/44[Lat4],ffd
index a40662d45..a40662d45 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/44[Lat4]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/44[Lat4],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/46[Greek] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/46[Greek],ffd
index c42397388..c42397388 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/46[Greek]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/46[Greek],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/47[Arabic] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/47[Arabic],ffd
index 4507f467a..4507f467a 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/47[Arabic]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/47[Arabic],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/48[Hebrew] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/48[Hebrew],ffd
index 70f39cca6..70f39cca6 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/48[Hebrew]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/48[Hebrew],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4C[Cyrill] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4C[Cyrill],ffd
index 8ff0115e4..8ff0115e4 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4C[Cyrill]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4C[Cyrill],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4D[Lat5] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4D[Lat5],ffd
index 6381e607e..6381e607e 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4D[Lat5]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4D[Lat5],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/50[LatSup] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/50[LatSup],ffd
index a320c7fe8..a320c7fe8 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/50[LatSup]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/50[LatSup],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/52[IS6937] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/52[IS6937],ffd
index dff6ccba4..dff6ccba4 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/52[IS6937]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/52[IS6937],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/54[Thai] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/54[Thai],ffd
index d74377759..d74377759 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/54[Thai]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/54[Thai],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/56[Lat6] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/56[Lat6],ffd
index 4e3e4f313..4e3e4f313 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/56[Lat6]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/56[Lat6],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/58[L6Sami] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/58[L6Sami],ffd
index 4dfd9188c..4dfd9188c 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/58[L6Sami]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/58[L6Sami],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/59[Lat7] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/59[Lat7],ffd
index 256a88e76..256a88e76 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/59[Lat7]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/59[Lat7],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5C[Welsh] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5C[Welsh],ffd
index b5e00509f..b5e00509f 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5C[Welsh]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5C[Welsh],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5D[Sami] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5D[Sami],ffd
index 15734c036..15734c036 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5D[Sami]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5D[Sami],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5E[Hebrew] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5E[Hebrew],ffd
index a6593b071..a6593b071 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5E[Hebrew]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5E[Hebrew],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5F[Lat8] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5F[Lat8],ffd
index c15713e82..c15713e82 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5F[Lat8]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5F[Lat8],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/62[Lat9] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/62[Lat9],ffd
index 5bf449d58..5bf449d58 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/62[Lat9]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/62[Lat9],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/66[Lat10] b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/66[Lat10],ffd
index e8ba925d3..e8ba925d3 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/66[Lat10]
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/66[Lat10],ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/KOI8-R b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/KOI8-R,ffd
index 8063cd4bc..8063cd4bc 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/KOI8-R
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/KOI8-R,ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1250 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1250,ffd
index 7a0d35ceb..7a0d35ceb 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1250
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1250,ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1251 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1251,ffd
index 3d6009cab..3d6009cab 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1251
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1251,ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1252 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1252,ffd
index 6d3bf293d..6d3bf293d 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1252
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1252,ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1253 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1253,ffd
index 50a48be13..50a48be13 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1253
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1253,ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1254 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1254,ffd
index 45ecfe907..45ecfe907 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1254
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1254,ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1256 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1256,ffd
index 7fc95a92f..7fc95a92f 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1256
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1256,ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP866 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP866,ffd
index cd214d24b..cd214d24b 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP866
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP866,ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP874 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP874,ffd
index 26a6fc8c3..26a6fc8c3 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP874
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP874,ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP932 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP932,ffd
index 2c0c111f9..2c0c111f9 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP932
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP932,ffd
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Files/CharNames b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Files/CharNames
new file mode 100644
index 000000000..3600913be
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Files/CharNames
@@ -0,0 +1,14016 @@
+# > Unicode:Files.CharNames
+# Mapping of code points to character names
+#
+# Lines starting with a '#' are comments, blank lines are ignored.
+#
+# Copyright (c) 2002 Unicode, Inc. All rights reserved.
+# Based on http://www.unicode.org/Public/3.2-Update/UnicodeData-3.2.0.txt
+#
+0000-001F:\ê
+0020:SPACE
+0021:EXCLAM\”\¥
+0022:QUOT\”\¥
+0023:\­SIGN
+0024:DOLLAR\‚
+0025:PERCENT\‚
+0026:AMPERSAND
+0027:APOSTROPHE
+0028:\‰ \ÑS
+0029:\ù\ÑS
+002A:ASTERISK
+002B:PLUS\‚
+002C:COMMA
+002D:HYPHEN-MINUS
+002E:FULL STOP
+002F:SOLIDUS
+0030:DIGIT ZERO
+0031:DIGIT ONE
+0032:DIGIT TWO
+0033:DIGIT THREE
+0034:DIGIT FOUR
+0035:DIGIT FIVE
+0036:DIGIT SIX
+0037:DIGIT SEVEN
+0038:DIGIT E\¼
+0039:DIGIT NINE
+003A:COLON
+003B:SEMICOLON
+003C:\µ\‚
+003D:EQUALS\‚
+003E:\’\‚
+003F:QUESTION\¥
+0040:COMMERCIAL AT
+0041:\PA
+0042:\PB
+0043:\PC
+0044:\PD
+0045:\PE
+0046:\PF
+0047:\PG
+0048:\PH
+0049:\PI
+004A:\PJ
+004B:\PK
+004C:\PL
+004D:\PM
+004E:\PN
+004F:\PO
+0050:\PP
+0051:\PQ
+0052:\PR
+0053:\PS
+0054:\PT
+0055:\PU
+0056:\PV
+0057:\PW
+0058:\PX
+0059:\PY
+005A:\PZ
+005B:\‰ \r\–
+005C:REVERSE SOLIDUS
+005D:\ù\r\–
+005E:CIRCUMFLEX\×
+005F:LOW \ä
+0060:GRAVE\×
+0061:\LA
+0062:\LB
+0063:\LC
+0064:\LD
+0065:\LE
+0066:\LF
+0067:\LG
+0068:\LH
+0069:\LI
+006A:\LJ
+006B:\LK
+006C:\LL
+006D:\LM
+006E:\LN
+006F:\LO
+0070:\LP
+0071:\LQ
+0072:\LR
+0073:\LS
+0074:\LT
+0075:\LU
+0076:\LV
+0077:\LW
+0078:\LX
+0079:\LY
+007A:\LZ
+007B:\‰ CURLY \–
+007C:\€ \ä
+007D:\ùCURLY \–
+007E:\æ
+007F:\ê
+0080:\ê
+0081:\ê
+0082:\ê
+0083:\ê
+0084:\ê
+0085:\ê
+0086:\ê
+0087:\ê
+0088:\ê
+0089:\ê
+008A:\ê
+008B:\ê
+008C:\ê
+008D:\ê
+008E:\ê
+008F:\ê
+0090:\ê
+0091:\ê
+0092:\ê
+0093:\ê
+0094:\ê
+0095:\ê
+0096:\ê
+0097:\ê
+0098:\ê
+0099:\ê
+009A:\ê
+009B:\ê
+009C:\ê
+009D:\ê
+009E:\ê
+009F:\ê
+00A0:NO-BREAK SPACE
+00A1:INVERT\ÂEXCLAM\”\¥
+00A2:CENT\‚
+00A3:POUND\‚
+00A4:CURRENCY\‚
+00A5:YEN\‚
+00A6:BROKEN\ì
+00A7:SECTION\‚
+00A8:DIAERESIS
+00A9:COPY\ùSIGN
+00AA:FEMININE ORDINAL INDICATOR
+00AB:\‰-\Ä\0 ANGLE QUOT\”\¥
+00AC:NOT\‚
+00AD:SOFT HYPHEN
+00AE:REGISTERED\‚
+00AF:\å
+00B0:DEGREE\‚
+00B1:PLUS-MINUS\‚
+00B2:SUPER\Ž TWO
+00B3:SUPER\Ž THREE
+00B4:\Ü\×
+00B5:MICRO\‚
+00B6:PILCROW\‚
+00B7:MIDDLE DOT
+00B8:CEDILLA
+00B9:SUPER\Ž ONE
+00BA:MASCU\ä ORDINAL INDICATOR
+00BB:\q-\Ä\0 ANGLE QUOT\”\¥
+00BC:\úONE QUARTER
+00BD:\úONE HALF
+00BE:\úTHREE QUARTERS
+00BF:INVERT\ÂQUESTION\¥
+00C0:\PA\HGRAVE
+00C1:\PA\H\Ü
+00C2:\PA\ˆ
+00C3:\PA\H\æ
+00C4:\PA\ž
+00C5:\PA\HR\ô\p
+00C6:\PAE
+00C7:\PC\HCEDILLA
+00C8:\PE\HGRAVE
+00C9:\PE\H\Ü
+00CA:\PE\ˆ
+00CB:\PE\ž
+00CC:\PI\HGRAVE
+00CD:\PI\H\Ü
+00CE:\PI\ˆ
+00CF:\PI\ž
+00D0:\PETH
+00D1:\PN\H\æ
+00D2:\PO\HGRAVE
+00D3:\PO\H\Ü
+00D4:\PO\ˆ
+00D5:\PO\H\æ
+00D6:\PO\ž
+00D7:MULTIPLIC\”\‚
+00D8:\PO\H\Á
+00D9:\PU\HGRAVE
+00DA:\PU\H\Ü
+00DB:\PU\ˆ
+00DC:\PU\ž
+00DD:\PY\H\Ü
+00DE:\PTHORN
+00DF:\LSHARP S
+00E0:\LA\HGRAVE
+00E1:\LA\H\Ü
+00E2:\LA\ˆ
+00E3:\LA\H\æ
+00E4:\LA\ž
+00E5:\LA\HR\ô\p
+00E6:\LAE
+00E7:\LC\HCEDILLA
+00E8:\LE\HGRAVE
+00E9:\LE\H\Ü
+00EA:\LE\ˆ
+00EB:\LE\ž
+00EC:\LI\HGRAVE
+00ED:\LI\H\Ü
+00EE:\LI\ˆ
+00EF:\LI\ž
+00F0:\LETH
+00F1:\LN\H\æ
+00F2:\LO\HGRAVE
+00F3:\LO\H\Ü
+00F4:\LO\ˆ
+00F5:\LO\H\æ
+00F6:\LO\ž
+00F7:DIVISION\‚
+00F8:\LO\H\Á
+00F9:\LU\HGRAVE
+00FA:\LU\H\Ü
+00FB:\LU\ˆ
+00FC:\LU\ž
+00FD:\LY\H\Ü
+00FE:\LTHORN
+00FF:\LY\ž
+0100:\PA\H\å
+0101:\LA\H\å
+0102:\PA\HBREVE
+0103:\LA\HBREVE
+0104:\PA\HOGONEK
+0105:\LA\HOGONEK
+0106:\PC\H\Ü
+0107:\LC\H\Ü
+0108:\PC\ˆ
+0109:\LC\ˆ
+010A:\PC\³\p
+010B:\LC\³\p
+010C:\PC\û
+010D:\LC\û
+010E:\PD\û
+010F:\LD\û
+0110:\PD\H\Á
+0111:\LD\H\Á
+0112:\PE\H\å
+0113:\LE\H\å
+0114:\PE\HBREVE
+0115:\LE\HBREVE
+0116:\PE\³\p
+0117:\LE\³\p
+0118:\PE\HOGONEK
+0119:\LE\HOGONEK
+011A:\PE\û
+011B:\LE\û
+011C:\PG\ˆ
+011D:\LG\ˆ
+011E:\PG\HBREVE
+011F:\LG\HBREVE
+0120:\PG\³\p
+0121:\LG\³\p
+0122:\PG\HCEDILLA
+0123:\LG\HCEDILLA
+0124:\PH\ˆ
+0125:\LH\ˆ
+0126:\PH\H\Á
+0127:\LH\H\Á
+0128:\PI\H\æ
+0129:\LI\H\æ
+012A:\PI\H\å
+012B:\LI\H\å
+012C:\PI\HBREVE
+012D:\LI\HBREVE
+012E:\PI\HOGONEK
+012F:\LI\HOGONEK
+0130:\PI\³\p
+0131:\LDOTLESS I
+0132:LATIN\Ò\òIJ
+0133:LATIN\Ç\òIJ
+0134:\PJ\ˆ
+0135:\LJ\ˆ
+0136:\PK\HCEDILLA
+0137:\LK\HCEDILLA
+0138:\LKRA
+0139:\PL\H\Ü
+013A:\LL\H\Ü
+013B:\PL\HCEDILLA
+013C:\LL\HCEDILLA
+013D:\PL\û
+013E:\LL\û
+013F:\PL\HMIDDLE DOT
+0140:\LL\HMIDDLE DOT
+0141:\PL\H\Á
+0142:\LL\H\Á
+0143:\PN\H\Ü
+0144:\LN\H\Ü
+0145:\PN\HCEDILLA
+0146:\LN\HCEDILLA
+0147:\PN\û
+0148:\LN\û
+0149:\LN PRECED\ÂBY APOSTROPHE
+014A:\PENG
+014B:\LENG
+014C:\PO\H\å
+014D:\LO\H\å
+014E:\PO\HBREVE
+014F:\LO\HBREVE
+0150:\PO\H\0 \Ü
+0151:\LO\H\0 \Ü
+0152:LATIN\Ò\òOE
+0153:LATIN\Ç\òOE
+0154:\PR\H\Ü
+0155:\LR\H\Ü
+0156:\PR\HCEDILLA
+0157:\LR\HCEDILLA
+0158:\PR\û
+0159:\LR\û
+015A:\PS\H\Ü
+015B:\LS\H\Ü
+015C:\PS\ˆ
+015D:\LS\ˆ
+015E:\PS\HCEDILLA
+015F:\LS\HCEDILLA
+0160:\PS\û
+0161:\LS\û
+0162:\PT\HCEDILLA
+0163:\LT\HCEDILLA
+0164:\PT\û
+0165:\LT\û
+0166:\PT\H\Á
+0167:\LT\H\Á
+0168:\PU\H\æ
+0169:\LU\H\æ
+016A:\PU\H\å
+016B:\LU\H\å
+016C:\PU\HBREVE
+016D:\LU\HBREVE
+016E:\PU\HR\ô\p
+016F:\LU\HR\ô\p
+0170:\PU\H\0 \Ü
+0171:\LU\H\0 \Ü
+0172:\PU\HOGONEK
+0173:\LU\HOGONEK
+0174:\PW\ˆ
+0175:\LW\ˆ
+0176:\PY\ˆ
+0177:\LY\ˆ
+0178:\PY\ž
+0179:\PZ\H\Ü
+017A:\LZ\H\Ü
+017B:\PZ\³\p
+017C:\LZ\³\p
+017D:\PZ\û
+017E:\LZ\û
+017F:\LLONG S
+0180:\LB\H\Á
+0181:\PB\í
+0182:\PB\HTOPBAR
+0183:\LB\HTOPBAR
+0184:\PTONE SIX
+0185:\LTONE SIX
+0186:\POPEN O
+0187:\PC\í
+0188:\LC\í
+0189:\PAFRICAN D
+018A:\PD\í
+018B:\PD\HTOPBAR
+018C:\LD\HTOPBAR
+018D:\LTURN\ÂDELTA
+018E:\P\öE
+018F:\PSCHWA
+0190:\POPEN E
+0191:\PF\í
+0192:\LF\í
+0193:\PG\í
+0194:\PGAMMA
+0195:\LHV
+0196:\PIOTA
+0197:\PI\H\Á
+0198:\PK\í
+0199:\LK\í
+019A:\LL\HBAR
+019B:\LLAMBDA\H\Á
+019C:\PTURN\ÂM
+019D:\PN\H\‰ HOOK
+019E:\LN\HLONG \ùLEG
+019F:\PO\HMIDDLE \æ
+01A0:\PO\HHORN
+01A1:\LO\HHORN
+01A2:\POI
+01A3:\LOI
+01A4:\PP\í
+01A5:\LP\í
+01A6:LATIN\@YR
+01A7:\PTONE TWO
+01A8:\LTONE TWO
+01A9:\PESH
+01AA:LATIN\@\öESH LOOP
+01AB:\LT\HPALATAL HOOK
+01AC:\PT\í
+01AD:\LT\í
+01AE:\PT\HRETROFLEX HOOK
+01AF:\PU\HHORN
+01B0:\LU\HHORN
+01B1:\PU\É
+01B2:\PV\í
+01B3:\PY\í
+01B4:\LY\í
+01B5:\PZ\H\Á
+01B6:\LZ\H\Á
+01B7:\PEZH
+01B8:\PEZH REVERSED
+01B9:\LEZH REVERSED
+01BA:\LEZH\HTAIL
+01BB:LATIN\@TWO\H\Á
+01BC:\PTONE FIVE
+01BD:\LTONE FIVE
+01BE:LATIN\@INVERT\ÂGLOTTAL STOP\H\Á
+01BF:LATIN\@WYNN
+01C0:LATIN\@DENTAL CLICK
+01C1:LATIN\@LATERAL CLICK
+01C2:LATIN\@ALVEOLAR CLICK
+01C3:LATIN\@RETROFLEX CLICK
+01C4:\PDZ\û
+01C5:\PD\HSMALL\@Z\û
+01C6:\LDZ\û
+01C7:\PLJ
+01C8:\PL\HSMALL\@J
+01C9:\LLJ
+01CA:\PNJ
+01CB:\PN\HSMALL\@J
+01CC:\LNJ
+01CD:\PA\û
+01CE:\LA\û
+01CF:\PI\û
+01D0:\LI\û
+01D1:\PO\û
+01D2:\LO\û
+01D3:\PU\û
+01D4:\LU\û
+01D5:\PU\ž\i\å
+01D6:\LU\ž\i\å
+01D7:\PU\ž\i\Ü
+01D8:\LU\ž\i\Ü
+01D9:\PU\ž\iCARON
+01DA:\LU\ž\iCARON
+01DB:\PU\ž\iGRAVE
+01DC:\LU\ž\iGRAVE
+01DD:\LTURN\ÂE
+01DE:\PA\ž\i\å
+01DF:\LA\ž\i\å
+01E0:\PA\³\p\i\å
+01E1:\LA\³\p\i\å
+01E2:\PAE\H\å
+01E3:\LAE\H\å
+01E4:\PG\H\Á
+01E5:\LG\H\Á
+01E6:\PG\û
+01E7:\LG\û
+01E8:\PK\û
+01E9:\LK\û
+01EA:\PO\HOGONEK
+01EB:\LO\HOGONEK
+01EC:\PO\HOGONEK\i\å
+01ED:\LO\HOGONEK\i\å
+01EE:\PEZH\û
+01EF:\LEZH\û
+01F0:\LJ\û
+01F1:\PDZ
+01F2:\PD\HSMALL\@Z
+01F3:\LDZ
+01F4:\PG\H\Ü
+01F5:\LG\H\Ü
+01F6:\PHWAIR
+01F7:\PWYNN
+01F8:\PN\HGRAVE
+01F9:\LN\HGRAVE
+01FA:\PA\HR\ô\p\i\Ü
+01FB:\LA\HR\ô\p\i\Ü
+01FC:\PAE\H\Ü
+01FD:\LAE\H\Ü
+01FE:\PO\H\Á\i\Ü
+01FF:\LO\H\Á\i\Ü
+0200:\PA\H\0 GRAVE
+0201:\LA\H\0 GRAVE
+0202:\PA\HINVERT\ÂBREVE
+0203:\LA\HINVERT\ÂBREVE
+0204:\PE\H\0 GRAVE
+0205:\LE\H\0 GRAVE
+0206:\PE\HINVERT\ÂBREVE
+0207:\LE\HINVERT\ÂBREVE
+0208:\PI\H\0 GRAVE
+0209:\LI\H\0 GRAVE
+020A:\PI\HINVERT\ÂBREVE
+020B:\LI\HINVERT\ÂBREVE
+020C:\PO\H\0 GRAVE
+020D:\LO\H\0 GRAVE
+020E:\PO\HINVERT\ÂBREVE
+020F:\LO\HINVERT\ÂBREVE
+0210:\PR\H\0 GRAVE
+0211:\LR\H\0 GRAVE
+0212:\PR\HINVERT\ÂBREVE
+0213:\LR\HINVERT\ÂBREVE
+0214:\PU\H\0 GRAVE
+0215:\LU\H\0 GRAVE
+0216:\PU\HINVERT\ÂBREVE
+0217:\LU\HINVERT\ÂBREVE
+0218:\PS\HCOMMA\…
+0219:\LS\HCOMMA\…
+021A:\PT\HCOMMA\…
+021B:\LT\HCOMMA\…
+021C:\PYOGH
+021D:\LYOGH
+021E:\PH\û
+021F:\LH\û
+0220:\PN\HLONG \ùLEG
+0222:\POU
+0223:\LOU
+0224:\PZ\í
+0225:\LZ\í
+0226:\PA\³\p
+0227:\LA\³\p
+0228:\PE\HCEDILLA
+0229:\LE\HCEDILLA
+022A:\PO\ž\i\å
+022B:\LO\ž\i\å
+022C:\PO\H\æ\i\å
+022D:\LO\H\æ\i\å
+022E:\PO\³\p
+022F:\LO\³\p
+0230:\PO\³\p\i\å
+0231:\LO\³\p\i\å
+0232:\PY\H\å
+0233:\LY\H\å
+0250:\LTURN\ÂA
+0251:\L\þ
+0252:\LTURN\Â\þ
+0253:\LB\í
+0254:\LOPEN O
+0255:\LC\HCURL
+0256:\LD\HTAIL
+0257:\LD\í
+0258:\L\öE
+0259:\LSCHWA
+025A:\LSCHWA\í
+025B:\LOPEN E
+025C:\L\öOPEN E
+025D:\L\öOPEN E\í
+025E:\LCLOS\Â\öOPEN E
+025F:\LDOTLESS J\H\Á
+0260:\LG\í
+0261:\L\Ž G
+0262:LATIN\@SMALL\ÒG
+0263:\LGAMMA
+0264:\LRAMS HORN
+0265:\LTURN\ÂH
+0266:\LH\í
+0267:\LHENG\í
+0268:\LI\H\Á
+0269:\LIOTA
+026A:LATIN\@SMALL\ÒI
+026B:\LL\HMIDDLE \æ
+026C:\LL\HBELT
+026D:\LL\HRETROFLEX HOOK
+026E:\LLEZH
+026F:\LTURN\ÂM
+0270:\LTURN\ÂM\HLONG LEG
+0271:\LM\í
+0272:\LN\H\‰ HOOK
+0273:\LN\HRETROFLEX HOOK
+0274:LATIN\@SMALL\ÒN
+0275:\LBARR\ÂO
+0276:LATIN\@SMALL\ÒOE
+0277:\LCLOS\Â\ü
+0278:\LPHI
+0279:\LTURN\ÂR
+027A:\LTURN\ÂR\HLONG LEG
+027B:\LTURN\ÂR\í
+027C:\LR\HLONG LEG
+027D:\LR\HTAIL
+027E:\LR\HFISHHOOK
+027F:\L\öR\HFISHHOOK
+0280:LATIN\@SMALL\ÒR
+0281:LATIN\@SMALL\ÒINVERT\ÂR
+0282:\LS\í
+0283:\LESH
+0284:\LDOTLESS J\H\Á\iHOOK
+0285:\LSQUAT \öESH
+0286:\LESH\HCURL
+0287:\LTURN\ÂT
+0288:\LT\HRETROFLEX HOOK
+0289:\LU\ì
+028A:\LU\É
+028B:\LV\í
+028C:\LTURN\ÂV
+028D:\LTURN\ÂW
+028E:\LTURN\ÂY
+028F:LATIN\@SMALL\ÒY
+0290:\LZ\HRETROFLEX HOOK
+0291:\LZ\HCURL
+0292:\LEZH
+0293:\LEZH\HCURL
+0294:LATIN\@GLOTTAL STOP
+0295:LATIN\@PHARYNGEAL VOIC\ÂFRICATIVE
+0296:LATIN\@INVERT\ÂGLOTTAL STOP
+0297:LATIN\@STRETCH\ÂC
+0298:LATIN\@BILABIAL CLICK
+0299:LATIN\@SMALL\ÒB
+029A:\LCLOS\ÂOPEN E
+029B:LATIN\@SMALL\ÒG\í
+029C:LATIN\@SMALL\ÒH
+029D:\LJ\HCROSSED-TAIL
+029E:\LTURN\ÂK
+029F:LATIN\@SMALL\ÒL
+02A0:\LQ\í
+02A1:LATIN\@GLOTTAL STOP\H\Á
+02A2:LATIN\@\öGLOTTAL STOP\H\Á
+02A3:\LDZ DIGRAPH
+02A4:\LDEZH DIGRAPH
+02A5:\LDZ DIGRAPH\HCURL
+02A6:\LTS DIGRAPH
+02A7:\LTESH DIGRAPH
+02A8:\LTC DIGRAPH\HCURL
+02A9:\LFENG DIGRAPH
+02AA:\LLS DIGRAPH
+02AB:\LLZ DIGRAPH
+02AC:LATIN\@BILABIAL PERCUSSIVE
+02AD:LATIN\@BIDENTAL PERCUSSIVE
+02B0:\®\§H
+02B1:\®\§H\í
+02B2:\®\§J
+02B3:\®\§R
+02B4:\®\§TURN\ÂR
+02B5:\®\§TURN\ÂR\í
+02B6:\®SMALL\ÒINVERT\ÂR
+02B7:\®\§W
+02B8:\®\§Y
+02B9:\®PRIME
+02BA:\®\0 PRIME
+02BB:\®TURN\ÂCOMMA
+02BC:\®APOSTROPHE
+02BD:\®\öCOMMA
+02BE:\®\ùHALF R\ô
+02BF:\®\‰ HALF R\ô
+02C0:\®GLOTTAL STOP
+02C1:\®\öGLOTTAL STOP
+02C2:\®\‰\uHEAD
+02C3:\®\q\uHEAD
+02C4:\®UP\uHEAD
+02C5:\®\Ë\uHEAD
+02C6:\®CIRCUMFLEX\×
+02C7:CARON
+02C8:\®\€ \ä
+02C9:\®\å
+02CA:\®\Ü\×
+02CB:\®GRAVE\×
+02CC:\®LOW \€ \ä
+02CD:\®LOW \å
+02CE:\®LOW GRAVE\×
+02CF:\®LOW \Ü\×
+02D0:\®TRIANGULAR COLON
+02D1:\®HALF TRIANGULAR COLON
+02D2:\®CENTR\Â\ùHALF R\ô
+02D3:\®CENTR\Â\‰ HALF R\ô
+02D4:\®UP TACK
+02D5:\®\Ë TACK
+02D6:\®PLUS\‚
+02D7:\®MINUS\‚
+02D8:BREVE
+02D9:DOT\p
+02DA:R\ô\p
+02DB:OGONEK
+02DC:\§\æ
+02DD:\0 \Ü\×
+02DE:\®RHOTIC HOOK
+02DF:\®CROSS\×
+02E0:\®\§GAMMA
+02E1:\®\§L
+02E2:\®\§S
+02E3:\®\§X
+02E4:\®\§\öGLOTTAL STOP
+02E5:\®EXTRA-HIGH TONE\ì
+02E6:\®HIGH TONE\ì
+02E7:\®MID TONE\ì
+02E8:\®LOW TONE\ì
+02E9:\®EXTRA-LOW TONE\ì
+02EA:\®YIN DEPART\ô TONE\¥
+02EB:\®YANG DEPART\ô TONE\¥
+02EC:\®VOIC\ô
+02ED:\®UNASPIRATED
+02EE:\®\0 APOSTROPHE
+0300:\oGRAVE\×
+0301:\o\Ü\×
+0302:\oCIRCUMFLEX\×
+0303:\o\æ
+0304:\o\å
+0305:\oOVER\ä
+0306:\oBREVE
+0307:\oDOT\p
+0308:\oDIAERESIS
+0309:\oHOOK\p
+030A:\oR\ô\p
+030B:\o\0 \Ü\×
+030C:\oCARON
+030D:\o\€ \ä\p
+030E:\o\0 \€ \ä\p
+030F:\o\0 GRAVE\×
+0310:\oCANDRABINDU
+0311:\oINVERT\ÂBREVE
+0312:\oTURN\ÂCOMMA\p
+0313:\oCOMMA\p
+0314:\o\öCOMMA\p
+0315:\oCOMMA\p \q
+0316:\oGRAVE\×\…
+0317:\o\Ü\×\…
+0318:\o\‰ TACK\…
+0319:\o\ùTACK\…
+031A:\o\‰ ANGLE\p
+031B:\oHORN
+031C:\o\‰ HALF R\ô\…
+031D:\oUP TACK\…
+031E:\o\Ë TACK\…
+031F:\oPLUS\‚\…
+0320:\oMINUS\‚\…
+0321:\oPALATALIZ\ÂHOOK\…
+0322:\oRETROFLEX HOOK\…
+0323:\oDOT\…
+0324:\oDIAERESIS\…
+0325:\oR\ô\…
+0326:\oCOMMA\…
+0327:\oCEDILLA
+0328:\oOGONEK
+0329:\o\€ \ä\…
+032A:\oBRIDGE\…
+032B:\oINVERT\Â\0 ARCH\…
+032C:\oCARON\…
+032D:\oCIRCUMFLEX\×\…
+032E:\oBREVE\…
+032F:\oINVERT\ÂBREVE\…
+0330:\o\æ\…
+0331:\o\å\…
+0332:\oLOW \ä
+0333:\o\0 LOW \ä
+0334:\o\æ OVERLAY
+0335:\oSHORT \Á OVERLAY
+0336:\oLONG \Á OVERLAY
+0337:\oSHORT SOLIDUS OVERLAY
+0338:\oLONG SOLIDUS OVERLAY
+0339:\o\ùHALF R\ô\…
+033A:\oINVERT\ÂBRIDGE\…
+033B:\o\rBELOW
+033C:\oSEAGULL\…
+033D:\oX\p
+033E:\o\€ \æ
+033F:\o\0 OVER\ä
+0340:\oGRAVE TONE\¥
+0341:\o\Ü TONE\¥
+0342:\oGREEK \´
+0343:\oGREEK KORONIS
+0344:\oGREEK DIALYTIKA TONOS
+0345:\oGREEK YPO\œ
+0346:\oBRIDGE\p
+0347:\oEQUALS\‚\…
+0348:\o\0 \€ \ä\…
+0349:\o\‰ ANGLE\…
+034A:\oNOT \æ\p
+034B:\oHOMOTHETIC\p
+034C:\oALMOST\‘\p
+034D:\o\‰ \q\u\…
+034E:\oUP\Š\u\…
+034F:\oGRAPHEME JOINER
+0360:\o\0 \æ
+0361:\o\0 INVERT\ÂBREVE
+0362:\o\0 \Ù\…
+0363:\o\LA
+0364:\o\LE
+0365:\o\LI
+0366:\o\LO
+0367:\o\LU
+0368:\o\LC
+0369:\o\LD
+036A:\o\LH
+036B:\o\LM
+036C:\o\LR
+036D:\o\LT
+036E:\o\LV
+036F:\o\LX
+0374:GREEK NUMERAL\‚
+0375:GREEK \ïNUMERAL\‚
+037A:GREEK YPO\œ
+037E:GREEK QUESTION\¥
+0384:GREEK TONOS
+0385:GREEK DIALYTIKA TONOS
+0386:\9\þ\HTONOS
+0387:GREEK ANO TELEIA
+0388:\9E\É\HTONOS
+0389:\9ETA\HTONOS
+038A:\9IOTA\HTONOS
+038C:\9OMICRON\HTONOS
+038E:\9U\É\HTONOS
+038F:\9\ü\HTONOS
+0390:\yIOTA\HDIALYTIKA\iTONOS
+0391:\9\þ
+0392:\9BETA
+0393:\9GAMMA
+0394:\9DELTA
+0395:\9E\É
+0396:\9ZETA
+0397:\9ETA
+0398:\9THETA
+0399:\9IOTA
+039A:\9KAPPA
+039B:\9LAMDA
+039C:\9MU
+039D:\9NU
+039E:\9XI
+039F:\9OMICRON
+03A0:\9PI
+03A1:\9RHO
+03A3:\9SIGMA
+03A4:\9TAU
+03A5:\9U\É
+03A6:\9PHI
+03A7:\9CHI
+03A8:\9PSI
+03A9:\9\ü
+03AA:\9IOTA\HDIALYTIKA
+03AB:\9U\É\HDIALYTIKA
+03AC:\y\þ\HTONOS
+03AD:\yE\É\HTONOS
+03AE:\yETA\HTONOS
+03AF:\yIOTA\HTONOS
+03B0:\yU\É\HDIALYTIKA\iTONOS
+03B1:\y\þ
+03B2:\yBETA
+03B3:\yGAMMA
+03B4:\yDELTA
+03B5:\yE\É
+03B6:\yZETA
+03B7:\yETA
+03B8:\yTHETA
+03B9:\yIOTA
+03BA:\yKAPPA
+03BB:\yLAMDA
+03BC:\yMU
+03BD:\yNU
+03BE:\yXI
+03BF:\yOMICRON
+03C0:\yPI
+03C1:\yRHO
+03C2:\yFINAL SIGMA
+03C3:\ySIGMA
+03C4:\yTAU
+03C5:\yU\É
+03C6:\yPHI
+03C7:\yCHI
+03C8:\yPSI
+03C9:\y\ü
+03CA:\yIOTA\HDIALYTIKA
+03CB:\yU\É\HDIALYTIKA
+03CC:\yOMICRON\HTONOS
+03CD:\yU\É\HTONOS
+03CE:\y\ü\HTONOS
+03D0:GREEK BETA \
+03D1:GREEK THETA \
+03D2:GREEK U\É\í \
+03D3:GREEK U\É\H\Ü\iHOOK \
+03D4:GREEK U\É\ž\iHOOK \
+03D5:GREEK PHI \
+03D6:GREEK PI \
+03D7:GREEK KAI \
+03D8:GREEK\@ARCHAIC KOPPA
+03D9:\yARCHAIC KOPPA
+03DA:GREEK\@STIGMA
+03DB:\ySTIGMA
+03DC:GREEK\@DIGAMMA
+03DD:\yDIGAMMA
+03DE:GREEK\@KOPPA
+03DF:\yKOPPA
+03E0:GREEK\@SAMPI
+03E1:\ySAMPI
+03E2:COPTIC\ãSHEI
+03E3:COPTIC\N\@SHEI
+03E4:COPTIC\ãFEI
+03E5:COPTIC\N\@FEI
+03E6:COPTIC\ãKHEI
+03E7:COPTIC\N\@KHEI
+03E8:COPTIC\ãHORI
+03E9:COPTIC\N\@HORI
+03EA:COPTIC\ãGANGIA
+03EB:COPTIC\N\@GANGIA
+03EC:COPTIC\ãSHIMA
+03ED:COPTIC\N\@SHIMA
+03EE:COPTIC\ãDEI
+03EF:COPTIC\N\@DEI
+03F0:GREEK KAPPA \
+03F1:GREEK RHO \
+03F2:GREEK LUNATE SIGMA \
+03F3:GREEK\@YOT
+03F4:GREEK\ÒTHETA \
+03F5:GREEK LUNATE E\É \
+03F6:GREEK \öLUNATE E\É \
+0400:\¡IE\HGRAVE
+0401:\¡IO
+0402:\¡DJE
+0403:\¡GJE
+0404:\¡UKRAINIAN IE
+0405:\¡DZE
+0406:\¡BYELORUSSIAN-UKRAINIAN I
+0407:\¡YI
+0408:\¡JE
+0409:\¡LJE
+040A:\¡NJE
+040B:\¡TSHE
+040C:\¡KJE
+040D:\¡I\HGRAVE
+040E:\¡SHORT U
+040F:\¡DZHE
+0410:\¡A
+0411:\¡BE
+0412:\¡VE
+0413:\¡GHE
+0414:\¡DE
+0415:\¡IE
+0416:\¡ZHE
+0417:\¡ZE
+0418:\¡I
+0419:\¡SHORT I
+041A:\¡KA
+041B:\¡EL
+041C:\¡EM
+041D:\¡EN
+041E:\¡O
+041F:\¡PE
+0420:\¡ER
+0421:\¡ES
+0422:\¡TE
+0423:\¡U
+0424:\¡EF
+0425:\¡HA
+0426:\¡TSE
+0427:\¡CHE
+0428:\¡SHA
+0429:\¡SHCHA
+042A:\¡HARD\‚
+042B:\¡YERU
+042C:\¡SOFT\‚
+042D:\¡E
+042E:\¡YU
+042F:\¡YA
+0430:\¢A
+0431:\¢BE
+0432:\¢VE
+0433:\¢GHE
+0434:\¢DE
+0435:\¢IE
+0436:\¢ZHE
+0437:\¢ZE
+0438:\¢I
+0439:\¢SHORT I
+043A:\¢KA
+043B:\¢EL
+043C:\¢EM
+043D:\¢EN
+043E:\¢O
+043F:\¢PE
+0440:\¢ER
+0441:\¢ES
+0442:\¢TE
+0443:\¢U
+0444:\¢EF
+0445:\¢HA
+0446:\¢TSE
+0447:\¢CHE
+0448:\¢SHA
+0449:\¢SHCHA
+044A:\¢HARD\‚
+044B:\¢YERU
+044C:\¢SOFT\‚
+044D:\¢E
+044E:\¢YU
+044F:\¢YA
+0450:\¢IE\HGRAVE
+0451:\¢IO
+0452:\¢DJE
+0453:\¢GJE
+0454:\¢UKRAINIAN IE
+0455:\¢DZE
+0456:\¢BYELORUSSIAN-UKRAINIAN I
+0457:\¢YI
+0458:\¢JE
+0459:\¢LJE
+045A:\¢NJE
+045B:\¢TSHE
+045C:\¢KJE
+045D:\¢I\HGRAVE
+045E:\¢SHORT U
+045F:\¢DZHE
+0460:\¡\ü
+0461:\¢\ü
+0462:\¡YAT
+0463:\¢YAT
+0464:\¡IOTIFI\ÂE
+0465:\¢IOTIFI\ÂE
+0466:\¡LITTLE YUS
+0467:\¢LITTLE YUS
+0468:\¡IOTIFI\ÂLITTLE YUS
+0469:\¢IOTIFI\ÂLITTLE YUS
+046A:\¡BIG YUS
+046B:\¢BIG YUS
+046C:\¡IOTIFI\ÂBIG YUS
+046D:\¢IOTIFI\ÂBIG YUS
+046E:\¡KSI
+046F:\¢KSI
+0470:\¡PSI
+0471:\¢PSI
+0472:\¡FITA
+0473:\¢FITA
+0474:\¡IZHITSA
+0475:\¢IZHITSA
+0476:\¡IZHITSA\H\0 GRAVE\×
+0477:\¢IZHITSA\H\0 GRAVE\×
+0478:\¡UK
+0479:\¢UK
+047A:\¡ROUND \ü
+047B:\¢ROUND \ü
+047C:\¡\ü\HTITLO
+047D:\¢\ü\HTITLO
+047E:\¡OT
+047F:\¢OT
+0480:\¡KOPPA
+0481:\¢KOPPA
+0482:\g THOUSANDS\‚
+0483:\o\g TITLO
+0484:\o\g PALATALIZ\”
+0485:\o\g DASIA PNEUMATA
+0486:\o\g PSILI PNEUMATA
+0488:\o\g HUNDR\ÂTHOUSANDS\‚
+0489:\o\g MILLIONS\‚
+048A:\¡SHORT I\HTAIL
+048B:\¢SHORT I\HTAIL
+048C:\¡SEMISOFT\‚
+048D:\¢SEMISOFT\‚
+048E:\¡ER\HTICK
+048F:\¢ER\HTICK
+0490:\¡GHE\HUPTURN
+0491:\¢GHE\HUPTURN
+0492:\¡GHE\H\Á
+0493:\¢GHE\H\Á
+0494:\¡GHE\HMIDDLE HOOK
+0495:\¢GHE\HMIDDLE HOOK
+0496:\¡ZHE\HDESCENDER
+0497:\¢ZHE\HDESCENDER
+0498:\¡ZE\HDESCENDER
+0499:\¢ZE\HDESCENDER
+049A:\¡KA\HDESCENDER
+049B:\¢KA\HDESCENDER
+049C:\¡KA\H\€ \Á
+049D:\¢KA\H\€ \Á
+049E:\¡KA\H\Á
+049F:\¢KA\H\Á
+04A0:\¡BASHKIR KA
+04A1:\¢BASHKIR KA
+04A2:\¡EN\HDESCENDER
+04A3:\¢EN\HDESCENDER
+04A4:\g\Ò\òEN GHE
+04A5:\g\Ç\òEN GHE
+04A6:\¡PE\HMIDDLE HOOK
+04A7:\¢PE\HMIDDLE HOOK
+04A8:\¡ABKHASIAN HA
+04A9:\¢ABKHASIAN HA
+04AA:\¡ES\HDESCENDER
+04AB:\¢ES\HDESCENDER
+04AC:\¡TE\HDESCENDER
+04AD:\¢TE\HDESCENDER
+04AE:\¡STRA\¼ U
+04AF:\¢STRA\¼ U
+04B0:\¡STRA\¼ U\H\Á
+04B1:\¢STRA\¼ U\H\Á
+04B2:\¡HA\HDESCENDER
+04B3:\¢HA\HDESCENDER
+04B4:\g\Ò\òTE TSE
+04B5:\g\Ç\òTE TSE
+04B6:\¡CHE\HDESCENDER
+04B7:\¢CHE\HDESCENDER
+04B8:\¡CHE\H\€ \Á
+04B9:\¢CHE\H\€ \Á
+04BA:\¡SHHA
+04BB:\¢SHHA
+04BC:\¡ABKHASIAN CHE
+04BD:\¢ABKHASIAN CHE
+04BE:\¡ABKHASIAN CHE\HDESCENDER
+04BF:\¢ABKHASIAN CHE\HDESCENDER
+04C0:\g\@PALOCHKA
+04C1:\¡ZHE\HBREVE
+04C2:\¢ZHE\HBREVE
+04C3:\¡KA\í
+04C4:\¢KA\í
+04C5:\¡EL\HTAIL
+04C6:\¢EL\HTAIL
+04C7:\¡EN\í
+04C8:\¢EN\í
+04C9:\¡EN\HTAIL
+04CA:\¢EN\HTAIL
+04CB:\¡KHAKASSIAN CHE
+04CC:\¢KHAKASSIAN CHE
+04CD:\¡EM\HTAIL
+04CE:\¢EM\HTAIL
+04D0:\¡A\HBREVE
+04D1:\¢A\HBREVE
+04D2:\¡A\ž
+04D3:\¢A\ž
+04D4:\g\Ò\òA IE
+04D5:\g\Ç\òA IE
+04D6:\¡IE\HBREVE
+04D7:\¢IE\HBREVE
+04D8:\¡SCHWA
+04D9:\¢SCHWA
+04DA:\¡SCHWA\ž
+04DB:\¢SCHWA\ž
+04DC:\¡ZHE\ž
+04DD:\¢ZHE\ž
+04DE:\¡ZE\ž
+04DF:\¢ZE\ž
+04E0:\¡ABKHASIAN DZE
+04E1:\¢ABKHASIAN DZE
+04E2:\¡I\H\å
+04E3:\¢I\H\å
+04E4:\¡I\ž
+04E5:\¢I\ž
+04E6:\¡O\ž
+04E7:\¢O\ž
+04E8:\¡BARR\ÂO
+04E9:\¢BARR\ÂO
+04EA:\¡BARR\ÂO\ž
+04EB:\¢BARR\ÂO\ž
+04EC:\¡E\ž
+04ED:\¢E\ž
+04EE:\¡U\H\å
+04EF:\¢U\H\å
+04F0:\¡U\ž
+04F1:\¢U\ž
+04F2:\¡U\H\0 \Ü
+04F3:\¢U\H\0 \Ü
+04F4:\¡CHE\ž
+04F5:\¢CHE\ž
+04F8:\¡YERU\ž
+04F9:\¢YERU\ž
+0500:\¡KOMI DE
+0501:\¢KOMI DE
+0502:\¡KOMI DJE
+0503:\¢KOMI DJE
+0504:\¡KOMI ZJE
+0505:\¢KOMI ZJE
+0506:\¡KOMI DZJE
+0507:\¢KOMI DZJE
+0508:\¡KOMI LJE
+0509:\¢KOMI LJE
+050A:\¡KOMI NJE
+050B:\¢KOMI NJE
+050C:\¡KOMI SJE
+050D:\¢KOMI SJE
+050E:\¡KOMI TJE
+050F:\¢KOMI TJE
+0531:ARMENIAN\ãAYB
+0532:ARMENIAN\ãBEN
+0533:ARMENIAN\ãGIM
+0534:ARMENIAN\ãDA
+0535:ARMENIAN\ãECH
+0536:ARMENIAN\ãZA
+0537:ARMENIAN\ãEH
+0538:ARMENIAN\ãET
+0539:ARMENIAN\ãTO
+053A:ARMENIAN\ãZHE
+053B:ARMENIAN\ãINI
+053C:ARMENIAN\ãLIWN
+053D:ARMENIAN\ãXEH
+053E:ARMENIAN\ãCA
+053F:ARMENIAN\ãKEN
+0540:ARMENIAN\ãHO
+0541:ARMENIAN\ãJA
+0542:ARMENIAN\ãGHAD
+0543:ARMENIAN\ãCHEH
+0544:ARMENIAN\ãMEN
+0545:ARMENIAN\ãYI
+0546:ARMENIAN\ãNOW
+0547:ARMENIAN\ãSHA
+0548:ARMENIAN\ãVO
+0549:ARMENIAN\ãCHA
+054A:ARMENIAN\ãPEH
+054B:ARMENIAN\ãJHEH
+054C:ARMENIAN\ãRA
+054D:ARMENIAN\ãSEH
+054E:ARMENIAN\ãVEW
+054F:ARMENIAN\ãTIWN
+0550:ARMENIAN\ãREH
+0551:ARMENIAN\ãCO
+0552:ARMENIAN\ãYIWN
+0553:ARMENIAN\ãPIWR
+0554:ARMENIAN\ãKEH
+0555:ARMENIAN\ãOH
+0556:ARMENIAN\ãFEH
+0559:ARMENIAN \®\‰ HALF R\ô
+055A:ARMENIAN APOSTROPHE
+055B:ARMENIAN EMPHASIS\¥
+055C:ARMENIAN EXCLAM\”\¥
+055D:ARMENIAN COMMA
+055E:ARMENIAN QUESTION\¥
+055F:ARMENIAN ABBREVI\”\¥
+0561:ARMENIAN\N\@AYB
+0562:ARMENIAN\N\@BEN
+0563:ARMENIAN\N\@GIM
+0564:ARMENIAN\N\@DA
+0565:ARMENIAN\N\@ECH
+0566:ARMENIAN\N\@ZA
+0567:ARMENIAN\N\@EH
+0568:ARMENIAN\N\@ET
+0569:ARMENIAN\N\@TO
+056A:ARMENIAN\N\@ZHE
+056B:ARMENIAN\N\@INI
+056C:ARMENIAN\N\@LIWN
+056D:ARMENIAN\N\@XEH
+056E:ARMENIAN\N\@CA
+056F:ARMENIAN\N\@KEN
+0570:ARMENIAN\N\@HO
+0571:ARMENIAN\N\@JA
+0572:ARMENIAN\N\@GHAD
+0573:ARMENIAN\N\@CHEH
+0574:ARMENIAN\N\@MEN
+0575:ARMENIAN\N\@YI
+0576:ARMENIAN\N\@NOW
+0577:ARMENIAN\N\@SHA
+0578:ARMENIAN\N\@VO
+0579:ARMENIAN\N\@CHA
+057A:ARMENIAN\N\@PEH
+057B:ARMENIAN\N\@JHEH
+057C:ARMENIAN\N\@RA
+057D:ARMENIAN\N\@SEH
+057E:ARMENIAN\N\@VEW
+057F:ARMENIAN\N\@TIWN
+0580:ARMENIAN\N\@REH
+0581:ARMENIAN\N\@CO
+0582:ARMENIAN\N\@YIWN
+0583:ARMENIAN\N\@PIWR
+0584:ARMENIAN\N\@KEH
+0585:ARMENIAN\N\@OH
+0586:ARMENIAN\N\@FEH
+0587:ARMENIAN\Ç\òECH YIWN
+0589:ARMENIAN\é
+058A:ARMENIAN HYPHEN
+0591:\Ÿ\× ETNAHTA
+0592:\Ÿ\× SEGOL
+0593:\Ÿ\× SHALSHELET
+0594:\Ÿ\× ZAQEF QATAN
+0595:\Ÿ\× ZAQEF GADOL
+0596:\Ÿ\× TIPEHA
+0597:\Ÿ\× REVIA
+0598:\Ÿ\× ZARQA
+0599:\Ÿ\× PASHTA
+059A:\Ÿ\× YETIV
+059B:\Ÿ\× TEVIR
+059C:\Ÿ\× GERESH
+059D:\Ÿ\× GERESH MUQDAM
+059E:\Ÿ\× GERSHAYIM
+059F:\Ÿ\× QARNEY PARA
+05A0:\Ÿ\× TELISHA GEDOLA
+05A1:\Ÿ\× PAZER
+05A3:\Ÿ\× MUNAH
+05A4:\Ÿ\× MAHAPAKH
+05A5:\Ÿ\× MERKHA
+05A6:\Ÿ\× MERKHA KEFULA
+05A7:\Ÿ\× DARGA
+05A8:\Ÿ\× QADMA
+05A9:\Ÿ\× TELISHA QETANA
+05AA:\Ÿ\× YERAH BEN YOMO
+05AB:\Ÿ\× OLE
+05AC:\Ÿ\× ILUY
+05AD:\Ÿ\× DEHI
+05AE:\Ÿ\× ZINOR
+05AF:\Ÿ\¥ MASORA \Ð
+05B0:\Ÿ POINT SHEVA
+05B1:\Ÿ POINT HATAF SEGOL
+05B2:\Ÿ POINT HATAF PATAH
+05B3:\Ÿ POINT HATAF QAMATS
+05B4:\Ÿ POINT HIRIQ
+05B5:\Ÿ POINT TSERE
+05B6:\Ÿ POINT SEGOL
+05B7:\Ÿ POINT PATAH
+05B8:\Ÿ POINT QAMATS
+05B9:\Ÿ POINT HOLAM
+05BB:\Ÿ POINT QUBUTS
+05BC:\Ÿ POINT DAGESH OR MAPIQ
+05BD:\Ÿ POINT METEG
+05BE:\Ÿ PUNCTU\” MAQAF
+05BF:\Ÿ POINT RAFE
+05C0:\Ÿ PUNCTU\” PASEQ
+05C1:\Ÿ POINT SHIN DOT
+05C2:\Ÿ POINT SIN DOT
+05C3:\Ÿ PUNCTU\” SOF PASUQ
+05C4:\Ÿ\¥ \÷DOT
+05D0:\Ÿ\@ALEF
+05D1:\Ÿ\@BET
+05D2:\Ÿ\@GIMEL
+05D3:\Ÿ\@DALET
+05D4:\Ÿ\@HE
+05D5:\Ÿ\@VAV
+05D6:\Ÿ\@ZAYIN
+05D7:\Ÿ\@HET
+05D8:\Ÿ\@TET
+05D9:\Ÿ\@YOD
+05DA:\Ÿ\@FINAL KAF
+05DB:\Ÿ\@KAF
+05DC:\Ÿ\@LAMED
+05DD:\Ÿ\@FINAL MEM
+05DE:\Ÿ\@MEM
+05DF:\Ÿ\@FINAL NUN
+05E0:\Ÿ\@NUN
+05E1:\Ÿ\@SAMEKH
+05E2:\Ÿ\@AYIN
+05E3:\Ÿ\@FINAL PE
+05E4:\Ÿ\@PE
+05E5:\Ÿ\@FINAL TSADI
+05E6:\Ÿ\@TSADI
+05E7:\Ÿ\@QOF
+05E8:\Ÿ\@RESH
+05E9:\Ÿ\@SHIN
+05EA:\Ÿ\@TAV
+05F0:\Ÿ \òYIDDISH \0 VAV
+05F1:\Ÿ \òYIDDISH VAV YOD
+05F2:\Ÿ \òYIDDISH \0 YOD
+05F3:\Ÿ PUNCTU\” GERESH
+05F4:\Ÿ PUNCTU\” GERSHAYIM
+060C:\Ê COMMA
+061B:\Ê SEMICOLON
+061F:\Ê QUESTION\¥
+0621:\^HAMZA
+0622:\^ALEF\HMADDA\p
+0623:\^ALEF\HHAMZA\p
+0624:\^WAW\HHAMZA\p
+0625:\^ALEF\HHAMZA\…
+0626:\^\º
+0627:\^ALEF
+0628:\^BEH
+0629:\^TEH MARBUTA
+062A:\^TEH
+062B:\^THEH
+062C:\^JEEM
+062D:\^HAH
+062E:\^KHAH
+062F:\^DAL
+0630:\^THAL
+0631:\^REH
+0632:\^ZAIN
+0633:\^SEEN
+0634:\^SHEEN
+0635:\^SAD
+0636:\^DAD
+0637:\^TAH
+0638:\^ZAH
+0639:\^AIN
+063A:\^GHAIN
+0640:\Ê TATWEEL
+0641:\^FEH
+0642:\^QAF
+0643:\^KAF
+0644:\^LAM
+0645:\^MEEM
+0646:\^NOON
+0647:\^HEH
+0648:\^WAW
+0649:\^ALEF MAKSURA
+064A:\^YEH
+064B:\Ê FATHATAN
+064C:\Ê DAMMATAN
+064D:\Ê KASRATAN
+064E:\Ê FATHA
+064F:\Ê DAMMA
+0650:\Ê KASRA
+0651:\Ê SHADDA
+0652:\Ê SUKUN
+0653:\Ê MADDAH\p
+0654:\Ê HAMZA\p
+0655:\Ê HAMZA\…
+0660:\Ê-INDIC\hZERO
+0661:\Ê-INDIC\hONE
+0662:\Ê-INDIC\hTWO
+0663:\Ê-INDIC\hTHREE
+0664:\Ê-INDIC\hFOUR
+0665:\Ê-INDIC\hFIVE
+0666:\Ê-INDIC\hSIX
+0667:\Ê-INDIC\hSEVEN
+0668:\Ê-INDIC\hE\¼
+0669:\Ê-INDIC\hNINE
+066A:\Ê PERCENT\‚
+066B:\Ê DECIMAL SEPARATOR
+066C:\Ê THOUSANDS SEPARATOR
+066D:\Ê FIVE POINT\ÂSTAR
+066E:\^DOTLESS BEH
+066F:\^DOTLESS QAF
+0670:\^SUPER\Ž ALEF
+0671:\^ALEF WASLA
+0672:\^ALEF\HWAVY HAMZA\p
+0673:\^ALEF\HWAVY HAMZA\…
+0674:\^HIGH HAMZA
+0675:\^HIGH HAMZA ALEF
+0676:\^HIGH HAMZA WAW
+0677:\^U\HHAMZA\p
+0678:\^HIGH HAMZA YEH
+0679:\^TTEH
+067A:\^TTEHEH
+067B:\^BEEH
+067C:\^TEH\HR\ô
+067D:\^TEH\HTHREE DOTS\p \Ë\Š
+067E:\^PEH
+067F:\^TEHEH
+0680:\^BEHEH
+0681:\^HAH\HHAMZA\p
+0682:\^HAH\HTWO DOTS \€\p
+0683:\^NYEH
+0684:\^DYEH
+0685:\^HAH\HTHREE DOTS\p
+0686:\^TCHEH
+0687:\^TCHEHEH
+0688:\^DDAL
+0689:\^DAL\HR\ô
+068A:\^DAL\³\…
+068B:\^DAL\³\… AND\ÇTAH
+068C:\^DAHAL
+068D:\^DDAHAL
+068E:\^DUL
+068F:\^DAL\HTHREE DOTS\p \Ë\Š
+0690:\^DAL\HFOUR DOTS\p
+0691:\^RREH
+0692:\^REH WITH\ÇV
+0693:\^REH\HR\ô
+0694:\^REH\³\…
+0695:\^REH WITH\ÇV\…
+0696:\^REH\³\…\iDOT\p
+0697:\^REH\HTWO DOTS\p
+0698:\^JEH
+0699:\^REH\HFOUR DOTS\p
+069A:\^SEEN\³\…\iDOT\p
+069B:\^SEEN\HTHREE DOTS\…
+069C:\^SEEN\HTHREE DOTS\…\iTHREE DOTS\p
+069D:\^SAD\HTWO DOTS\…
+069E:\^SAD\HTHREE DOTS\p
+069F:\^TAH\HTHREE DOTS\p
+06A0:\^AIN\HTHREE DOTS\p
+06A1:\^DOTLESS FEH
+06A2:\^FEH\³ MOVED\…
+06A3:\^FEH\³\…
+06A4:\^VEH
+06A5:\^FEH\HTHREE DOTS\…
+06A6:\^PEHEH
+06A7:\^QAF\³\p
+06A8:\^QAF\HTHREE DOTS\p
+06A9:\^KEHEH
+06AA:\^SWASH KAF
+06AB:\^KAF\HR\ô
+06AC:\^KAF\³\p
+06AD:\^NG
+06AE:\^KAF\HTHREE DOTS\…
+06AF:\^GAF
+06B0:\^GAF\HR\ô
+06B1:\^NGOEH
+06B2:\^GAF\HTWO DOTS\…
+06B3:\^GUEH
+06B4:\^GAF\HTHREE DOTS\p
+06B5:\^LAM WITH\ÇV
+06B6:\^LAM\³\p
+06B7:\^LAM\HTHREE DOTS\p
+06B8:\^LAM\HTHREE DOTS\…
+06B9:\^NOON\³\…
+06BA:\^NOON GHUNNA
+06BB:\^RNOON
+06BC:\^NOON\HR\ô
+06BD:\^NOON\HTHREE DOTS\p
+06BE:\^HEH DOACHASHMEE
+06BF:\^TCHEH\³\p
+06C0:\^HEH\HYEH\p
+06C1:\^HEH GOAL
+06C2:\^HEH GOAL\HHAMZA\p
+06C3:\^TEH MARBUTA GOAL
+06C4:\^WAW\HR\ô
+06C5:\^KIRGHIZ OE
+06C6:\^OE
+06C7:\^U
+06C8:\^YU
+06C9:\^KIRGHIZ YU
+06CA:\^WAW\HTWO DOTS\p
+06CB:\^VE
+06CC:\^FARSI YEH
+06CD:\^YEH\HTAIL
+06CE:\^YEH WITH\ÇV
+06CF:\^WAW\³\p
+06D0:\^E
+06D1:\^YEH\HTHREE DOTS\…
+06D2:\^YEH\ìREE
+06D3:\^YEH\ìREE\HHAMZA\p
+06D4:\Ê\é
+06D5:\^AE
+06D6:\Ê\ÇHIGH \òSAD\HLAM\‡
+06D7:\Ê\ÇHIGH \òQAF\HLAM\‡
+06D8:\Ê\ÇHIGH MEEM\2
+06D9:\Ê\ÇHIGH LAM ALEF
+06DA:\Ê\ÇHIGH JEEM
+06DB:\Ê\ÇHIGH THREE DOTS
+06DC:\Ê\ÇHIGH SEEN
+06DD:\Ê END OF AYAH
+06DE:\Ê START OF RUB EL HIZB
+06DF:\Ê\ÇHIGH ROUND\ÂZERO
+06E0:\Ê\ÇHIGH UP\ùRECTANGULAR ZERO
+06E1:\Ê\ÇHIGH DOTLESS HEAD OF KHAH
+06E2:\Ê\ÇHIGH MEEM\Q
+06E3:\Ê\ÇLOW SEEN
+06E4:\Ê\ÇHIGH MADDA
+06E5:\Ê\ÇWAW
+06E6:\Ê\ÇYEH
+06E7:\Ê\ÇHIGH YEH
+06E8:\Ê\ÇHIGH NOON
+06E9:\Ê PLACE OF SAJDAH
+06EA:\Ê EMPTY CENTRE LOW STOP
+06EB:\Ê EMPTY CENTRE HIGH STOP
+06EC:\Ê ROUND\ÂHIGH STOP\HFILL\ÂCENTRE
+06ED:\Ê\ÇLOW MEEM
+06F0:EXTEND\Â\Ê-INDIC\hZERO
+06F1:EXTEND\Â\Ê-INDIC\hONE
+06F2:EXTEND\Â\Ê-INDIC\hTWO
+06F3:EXTEND\Â\Ê-INDIC\hTHREE
+06F4:EXTEND\Â\Ê-INDIC\hFOUR
+06F5:EXTEND\Â\Ê-INDIC\hFIVE
+06F6:EXTEND\Â\Ê-INDIC\hSIX
+06F7:EXTEND\Â\Ê-INDIC\hSEVEN
+06F8:EXTEND\Â\Ê-INDIC\hE\¼
+06F9:EXTEND\Â\Ê-INDIC\hNINE
+06FA:\^SHEEN\³\…
+06FB:\^DAD\³\…
+06FC:\^GHAIN\³\…
+06FD:\Ê\‚ SINDHI AMPERSAND
+06FE:\Ê\‚ SINDHI POSTPOSITION MEN
+0700:\Ó END OF PARAGRAPH
+0701:\Ó SUPRA\äAR\é
+0702:\Ó SUB\äAR\é
+0703:\Ó SUPRA\äAR COLON
+0704:\Ó SUB\äAR COLON
+0705:\Ó \ COLON
+0706:\Ó COLON SKEW\Â\‰
+0707:\Ó COLON SKEW\Â\q
+0708:\Ó SUPRA\äAR COLON SKEW\Â\‰
+0709:\Ó SUB\äAR COLON SKEW\Â\q
+070A:\Ó CONTRACTION
+070B:\Ó HARKLEAN OBELUS
+070C:\Ó HARKLEAN METOBELUS
+070D:\Ó HARKLEAN ASTERISCUS
+070F:\Ó ABBREVI\”\¥
+0710:\Ó\@ALAPH
+0711:\Ó\@SUPER\Ž ALAPH
+0712:\Ó\@BETH
+0713:\Ó\@GAMAL
+0714:\Ó\@GAMAL GARSHUNI
+0715:\Ó\@DALATH
+0716:\Ó\@DOTLESS DALATH RISH
+0717:\Ó\@HE
+0718:\Ó\@WAW
+0719:\Ó\@ZAIN
+071A:\Ó\@HETH
+071B:\Ó\@TETH
+071C:\Ó\@TETH GARSHUNI
+071D:\Ó\@YUDH
+071E:\Ó\@YUDH HE
+071F:\Ó\@KAPH
+0720:\Ó\@LAMADH
+0721:\Ó\@MIM
+0722:\Ó\@NUN
+0723:\Ó\@SEMKATH
+0724:\Ó\@FINAL SEMKATH
+0725:\Ó\@E
+0726:\Ó\@PE
+0727:\Ó\@\öPE
+0728:\Ó\@SADHE
+0729:\Ó\@QAPH
+072A:\Ó\@RISH
+072B:\Ó\@SHIN
+072C:\Ó\@TAW
+0730:\Ó PTHAHA\p
+0731:\Ó PTHAHA\…
+0732:\Ó PTHAHA DOTTED
+0733:\Ó ZQAPHA\p
+0734:\Ó ZQAPHA\…
+0735:\Ó ZQAPHA DOTTED
+0736:\Ó RBASA\p
+0737:\Ó RBASA\…
+0738:\Ó DOTT\ÂZLAMA \
+0739:\Ó DOTT\ÂZLAMA ANGULAR
+073A:\Ó HBASA\p
+073B:\Ó HBASA\…
+073C:\Ó HBASA-ESASA DOTTED
+073D:\Ó ESASA\p
+073E:\Ó ESASA\…
+073F:\Ó RWAHA
+0740:\Ó FEMININE DOT
+0741:\Ó QUSHSHAYA
+0742:\Ó RUKKAKHA
+0743:\Ó TWO \€ DOTS\p
+0744:\Ó TWO \€ DOTS\…
+0745:\Ó THREE DOTS\p
+0746:\Ó THREE DOTS\…
+0747:\Ó OBLIQUE \ä\p
+0748:\Ó OBLIQUE \ä\…
+0749:\Ó MUSIC
+074A:\Ó\ìREKH
+0780:\ëHAA
+0781:\ëSHAVIYANI
+0782:\ëNOONU
+0783:\ëRAA
+0784:\ëBAA
+0785:\ëLHAVIYANI
+0786:\ëKAAFU
+0787:\ëALIFU
+0788:\ëVAAVU
+0789:\ëMEEMU
+078A:\ëFAAFU
+078B:\ëDHAALU
+078C:\ëTHAA
+078D:\ëLAAMU
+078E:\ëGAAFU
+078F:\ëGNAVIYANI
+0790:\ëSEENU
+0791:\ëDAVIYANI
+0792:\ëZAVIYANI
+0793:\ëTAVIYANI
+0794:\ëYAA
+0795:\ëPAVIYANI
+0796:\ëJAVIYANI
+0797:\ëCHAVIYANI
+0798:\ëTTAA
+0799:\ëHHAA
+079A:\ëKHAA
+079B:\ëTHAALU
+079C:\ëZAA
+079D:\ëSHEENU
+079E:\ëSAADHU
+079F:\ëDAADHU
+07A0:\ëTO
+07A1:\ëZO
+07A2:\ëAINU
+07A3:\ëGHAINU
+07A4:\ëQAAFU
+07A5:\ëWAAVU
+07A6:THAANA ABAFILI
+07A7:THAANA AABAAFILI
+07A8:THAANA IBIFILI
+07A9:THAANA EEBEEFILI
+07AA:THAANA UBUFILI
+07AB:THAANA OOBOOFILI
+07AC:THAANA EBEFILI
+07AD:THAANA EYBEYFILI
+07AE:THAANA OBOFILI
+07AF:THAANA OABOAFILI
+07B0:THAANA SUKUN
+07B1:\ëNAA
+0901:\„\‚ CANDRABINDU
+0902:\„\‚ ANUSVARA
+0903:\„\‚ VISARGA
+0905:\„\@A
+0906:\„\@AA
+0907:\„\@I
+0908:\„\@II
+0909:\„\@U
+090A:\„\@UU
+090B:\„\@\ÎR
+090C:\„\@\ÎL
+090D:\„\@CANDRA E
+090E:\„\@SHORT E
+090F:\„\@E
+0910:\„\@AI
+0911:\„\@CANDRA O
+0912:\„\@SHORT O
+0913:\„\@O
+0914:\„\@AU
+0915:\„\@KA
+0916:\„\@KHA
+0917:\„\@GA
+0918:\„\@GHA
+0919:\„\@NGA
+091A:\„\@CA
+091B:\„\@CHA
+091C:\„\@JA
+091D:\„\@JHA
+091E:\„\@NYA
+091F:\„\@TTA
+0920:\„\@TTHA
+0921:\„\@DDA
+0922:\„\@DDHA
+0923:\„\@NNA
+0924:\„\@TA
+0925:\„\@THA
+0926:\„\@DA
+0927:\„\@DHA
+0928:\„\@NA
+0929:\„\@NNNA
+092A:\„\@PA
+092B:\„\@PHA
+092C:\„\@BA
+092D:\„\@BHA
+092E:\„\@MA
+092F:\„\@YA
+0930:\„\@RA
+0931:\„\@RRA
+0932:\„\@LA
+0933:\„\@LLA
+0934:\„\@LLLA
+0935:\„\@VA
+0936:\„\@SHA
+0937:\„\@SSA
+0938:\„\@SA
+0939:\„\@HA
+093C:\„\‚ NUKTA
+093D:\„\‚ AVAGRAHA
+093E:\„\bAA
+093F:\„\bI
+0940:\„\bII
+0941:\„\bU
+0942:\„\bUU
+0943:\„\b\ÎR
+0944:\„\b\ÎRR
+0945:\„\bCANDRA E
+0946:\„\bSHORT E
+0947:\„\bE
+0948:\„\bAI
+0949:\„\bCANDRA O
+094A:\„\bSHORT O
+094B:\„\bO
+094C:\„\bAU
+094D:\„\‚ VIRAMA
+0950:\„ OM
+0951:\„ STRESS\‚ UDATTA
+0952:\„ STRESS\‚ ANUDATTA
+0953:\„ GRAVE\×
+0954:\„ \Ü\×
+0958:\„\@QA
+0959:\„\@KHHA
+095A:\„\@GHHA
+095B:\„\@ZA
+095C:\„\@DDDHA
+095D:\„\@RHA
+095E:\„\@FA
+095F:\„\@YYA
+0960:\„\@\ÎRR
+0961:\„\@\ÎLL
+0962:\„\b\ÎL
+0963:\„\b\ÎLL
+0964:\„ DANDA
+0965:\„ \0 DANDA
+0966:\„\hZERO
+0967:\„\hONE
+0968:\„\hTWO
+0969:\„\hTHREE
+096A:\„\hFOUR
+096B:\„\hFIVE
+096C:\„\hSIX
+096D:\„\hSEVEN
+096E:\„\hE\¼
+096F:\„\hNINE
+0970:\„ ABBREVI\”\‚
+0981:\°\‚ CANDRABINDU
+0982:\°\‚ ANUSVARA
+0983:\°\‚ VISARGA
+0985:\°\@A
+0986:\°\@AA
+0987:\°\@I
+0988:\°\@II
+0989:\°\@U
+098A:\°\@UU
+098B:\°\@\ÎR
+098C:\°\@\ÎL
+098F:\°\@E
+0990:\°\@AI
+0993:\°\@O
+0994:\°\@AU
+0995:\°\@KA
+0996:\°\@KHA
+0997:\°\@GA
+0998:\°\@GHA
+0999:\°\@NGA
+099A:\°\@CA
+099B:\°\@CHA
+099C:\°\@JA
+099D:\°\@JHA
+099E:\°\@NYA
+099F:\°\@TTA
+09A0:\°\@TTHA
+09A1:\°\@DDA
+09A2:\°\@DDHA
+09A3:\°\@NNA
+09A4:\°\@TA
+09A5:\°\@THA
+09A6:\°\@DA
+09A7:\°\@DHA
+09A8:\°\@NA
+09AA:\°\@PA
+09AB:\°\@PHA
+09AC:\°\@BA
+09AD:\°\@BHA
+09AE:\°\@MA
+09AF:\°\@YA
+09B0:\°\@RA
+09B2:\°\@LA
+09B6:\°\@SHA
+09B7:\°\@SSA
+09B8:\°\@SA
+09B9:\°\@HA
+09BC:\°\‚ NUKTA
+09BE:\°\bAA
+09BF:\°\bI
+09C0:\°\bII
+09C1:\°\bU
+09C2:\°\bUU
+09C3:\°\b\ÎR
+09C4:\°\b\ÎRR
+09C7:\°\bE
+09C8:\°\bAI
+09CB:\°\bO
+09CC:\°\bAU
+09CD:\°\‚ VIRAMA
+09D7:\° AU LENGTH\¥
+09DC:\°\@RRA
+09DD:\°\@RHA
+09DF:\°\@YYA
+09E0:\°\@\ÎRR
+09E1:\°\@\ÎLL
+09E2:\°\b\ÎL
+09E3:\°\b\ÎLL
+09E6:\°\hZERO
+09E7:\°\hONE
+09E8:\°\hTWO
+09E9:\°\hTHREE
+09EA:\°\hFOUR
+09EB:\°\hFIVE
+09EC:\°\hSIX
+09ED:\°\hSEVEN
+09EE:\°\hE\¼
+09EF:\°\hNINE
+09F0:\°\@RA\HMIDDLE DIAGONAL
+09F1:\°\@RA\H\ïDIAGONAL
+09F2:\° RUPEE\¥
+09F3:\° RUPEE\‚
+09F4:\° CURRENCY NUMERATOR ONE
+09F5:\° CURRENCY NUMERATOR TWO
+09F6:\° CURRENCY NUMERATOR THREE
+09F7:\° CURRENCY NUMERATOR FOUR
+09F8:\° CURRENCY NUMERATOR ONE LESS THAN THE DENOMINATOR
+09F9:\° CURRENCY DENOMINATOR SIXTEEN
+09FA:\° ISSHAR
+0A02:\¯\‚ BINDI
+0A05:\¯\@A
+0A06:\¯\@AA
+0A07:\¯\@I
+0A08:\¯\@II
+0A09:\¯\@U
+0A0A:\¯\@UU
+0A0F:\¯\@EE
+0A10:\¯\@AI
+0A13:\¯\@OO
+0A14:\¯\@AU
+0A15:\¯\@KA
+0A16:\¯\@KHA
+0A17:\¯\@GA
+0A18:\¯\@GHA
+0A19:\¯\@NGA
+0A1A:\¯\@CA
+0A1B:\¯\@CHA
+0A1C:\¯\@JA
+0A1D:\¯\@JHA
+0A1E:\¯\@NYA
+0A1F:\¯\@TTA
+0A20:\¯\@TTHA
+0A21:\¯\@DDA
+0A22:\¯\@DDHA
+0A23:\¯\@NNA
+0A24:\¯\@TA
+0A25:\¯\@THA
+0A26:\¯\@DA
+0A27:\¯\@DHA
+0A28:\¯\@NA
+0A2A:\¯\@PA
+0A2B:\¯\@PHA
+0A2C:\¯\@BA
+0A2D:\¯\@BHA
+0A2E:\¯\@MA
+0A2F:\¯\@YA
+0A30:\¯\@RA
+0A32:\¯\@LA
+0A33:\¯\@LLA
+0A35:\¯\@VA
+0A36:\¯\@SHA
+0A38:\¯\@SA
+0A39:\¯\@HA
+0A3C:\¯\‚ NUKTA
+0A3E:\¯\bAA
+0A3F:\¯\bI
+0A40:\¯\bII
+0A41:\¯\bU
+0A42:\¯\bUU
+0A47:\¯\bEE
+0A48:\¯\bAI
+0A4B:\¯\bOO
+0A4C:\¯\bAU
+0A4D:\¯\‚ VIRAMA
+0A59:\¯\@KHHA
+0A5A:\¯\@GHHA
+0A5B:\¯\@ZA
+0A5C:\¯\@RRA
+0A5E:\¯\@FA
+0A66:\¯\hZERO
+0A67:\¯\hONE
+0A68:\¯\hTWO
+0A69:\¯\hTHREE
+0A6A:\¯\hFOUR
+0A6B:\¯\hFIVE
+0A6C:\¯\hSIX
+0A6D:\¯\hSEVEN
+0A6E:\¯\hE\¼
+0A6F:\¯\hNINE
+0A70:\¯ TIPPI
+0A71:\¯ ADDAK
+0A72:\¯ IRI
+0A73:\¯ URA
+0A74:\¯ EK ONKAR
+0A81:\ª\‚ CANDRABINDU
+0A82:\ª\‚ ANUSVARA
+0A83:\ª\‚ VISARGA
+0A85:\ª\@A
+0A86:\ª\@AA
+0A87:\ª\@I
+0A88:\ª\@II
+0A89:\ª\@U
+0A8A:\ª\@UU
+0A8B:\ª\@\ÎR
+0A8D:\ª VOWEL CANDRA E
+0A8F:\ª\@E
+0A90:\ª\@AI
+0A91:\ª VOWEL CANDRA O
+0A93:\ª\@O
+0A94:\ª\@AU
+0A95:\ª\@KA
+0A96:\ª\@KHA
+0A97:\ª\@GA
+0A98:\ª\@GHA
+0A99:\ª\@NGA
+0A9A:\ª\@CA
+0A9B:\ª\@CHA
+0A9C:\ª\@JA
+0A9D:\ª\@JHA
+0A9E:\ª\@NYA
+0A9F:\ª\@TTA
+0AA0:\ª\@TTHA
+0AA1:\ª\@DDA
+0AA2:\ª\@DDHA
+0AA3:\ª\@NNA
+0AA4:\ª\@TA
+0AA5:\ª\@THA
+0AA6:\ª\@DA
+0AA7:\ª\@DHA
+0AA8:\ª\@NA
+0AAA:\ª\@PA
+0AAB:\ª\@PHA
+0AAC:\ª\@BA
+0AAD:\ª\@BHA
+0AAE:\ª\@MA
+0AAF:\ª\@YA
+0AB0:\ª\@RA
+0AB2:\ª\@LA
+0AB3:\ª\@LLA
+0AB5:\ª\@VA
+0AB6:\ª\@SHA
+0AB7:\ª\@SSA
+0AB8:\ª\@SA
+0AB9:\ª\@HA
+0ABC:\ª\‚ NUKTA
+0ABD:\ª\‚ AVAGRAHA
+0ABE:\ª\bAA
+0ABF:\ª\bI
+0AC0:\ª\bII
+0AC1:\ª\bU
+0AC2:\ª\bUU
+0AC3:\ª\b\ÎR
+0AC4:\ª\b\ÎRR
+0AC5:\ª\bCANDRA E
+0AC7:\ª\bE
+0AC8:\ª\bAI
+0AC9:\ª\bCANDRA O
+0ACB:\ª\bO
+0ACC:\ª\bAU
+0ACD:\ª\‚ VIRAMA
+0AD0:\ª OM
+0AE0:\ª\@\ÎRR
+0AE6:\ª\hZERO
+0AE7:\ª\hONE
+0AE8:\ª\hTWO
+0AE9:\ª\hTHREE
+0AEA:\ª\hFOUR
+0AEB:\ª\hFIVE
+0AEC:\ª\hSIX
+0AED:\ª\hSEVEN
+0AEE:\ª\hE\¼
+0AEF:\ª\hNINE
+0B01:ORIYA\‚ CANDRABINDU
+0B02:ORIYA\‚ ANUSVARA
+0B03:ORIYA\‚ VISARGA
+0B05:\âA
+0B06:\âAA
+0B07:\âI
+0B08:\âII
+0B09:\âU
+0B0A:\âUU
+0B0B:\â\ÎR
+0B0C:\â\ÎL
+0B0F:\âE
+0B10:\âAI
+0B13:\âO
+0B14:\âAU
+0B15:\âKA
+0B16:\âKHA
+0B17:\âGA
+0B18:\âGHA
+0B19:\âNGA
+0B1A:\âCA
+0B1B:\âCHA
+0B1C:\âJA
+0B1D:\âJHA
+0B1E:\âNYA
+0B1F:\âTTA
+0B20:\âTTHA
+0B21:\âDDA
+0B22:\âDDHA
+0B23:\âNNA
+0B24:\âTA
+0B25:\âTHA
+0B26:\âDA
+0B27:\âDHA
+0B28:\âNA
+0B2A:\âPA
+0B2B:\âPHA
+0B2C:\âBA
+0B2D:\âBHA
+0B2E:\âMA
+0B2F:\âYA
+0B30:\âRA
+0B32:\âLA
+0B33:\âLLA
+0B36:\âSHA
+0B37:\âSSA
+0B38:\âSA
+0B39:\âHA
+0B3C:ORIYA\‚ NUKTA
+0B3D:ORIYA\‚ AVAGRAHA
+0B3E:ORIYA\bAA
+0B3F:ORIYA\bI
+0B40:ORIYA\bII
+0B41:ORIYA\bU
+0B42:ORIYA\bUU
+0B43:ORIYA\b\ÎR
+0B47:ORIYA\bE
+0B48:ORIYA\bAI
+0B4B:ORIYA\bO
+0B4C:ORIYA\bAU
+0B4D:ORIYA\‚ VIRAMA
+0B56:ORIYA AI LENGTH\¥
+0B57:ORIYA AU LENGTH\¥
+0B5C:\âRRA
+0B5D:\âRHA
+0B5F:\âYYA
+0B60:\â\ÎRR
+0B61:\â\ÎLL
+0B66:ORIYA\hZERO
+0B67:ORIYA\hONE
+0B68:ORIYA\hTWO
+0B69:ORIYA\hTHREE
+0B6A:ORIYA\hFOUR
+0B6B:ORIYA\hFIVE
+0B6C:ORIYA\hSIX
+0B6D:ORIYA\hSEVEN
+0B6E:ORIYA\hE\¼
+0B6F:ORIYA\hNINE
+0B70:ORIYA ISSHAR
+0B82:TAMIL\‚ ANUSVARA
+0B83:TAMIL\‚ VISARGA
+0B85:TAMIL\@A
+0B86:TAMIL\@AA
+0B87:TAMIL\@I
+0B88:TAMIL\@II
+0B89:TAMIL\@U
+0B8A:TAMIL\@UU
+0B8E:TAMIL\@E
+0B8F:TAMIL\@EE
+0B90:TAMIL\@AI
+0B92:TAMIL\@O
+0B93:TAMIL\@OO
+0B94:TAMIL\@AU
+0B95:TAMIL\@KA
+0B99:TAMIL\@NGA
+0B9A:TAMIL\@CA
+0B9C:TAMIL\@JA
+0B9E:TAMIL\@NYA
+0B9F:TAMIL\@TTA
+0BA3:TAMIL\@NNA
+0BA4:TAMIL\@TA
+0BA8:TAMIL\@NA
+0BA9:TAMIL\@NNNA
+0BAA:TAMIL\@PA
+0BAE:TAMIL\@MA
+0BAF:TAMIL\@YA
+0BB0:TAMIL\@RA
+0BB1:TAMIL\@RRA
+0BB2:TAMIL\@LA
+0BB3:TAMIL\@LLA
+0BB4:TAMIL\@LLLA
+0BB5:TAMIL\@VA
+0BB7:TAMIL\@SSA
+0BB8:TAMIL\@SA
+0BB9:TAMIL\@HA
+0BBE:TAMIL\bAA
+0BBF:TAMIL\bI
+0BC0:TAMIL\bII
+0BC1:TAMIL\bU
+0BC2:TAMIL\bUU
+0BC6:TAMIL\bE
+0BC7:TAMIL\bEE
+0BC8:TAMIL\bAI
+0BCA:TAMIL\bO
+0BCB:TAMIL\bOO
+0BCC:TAMIL\bAU
+0BCD:TAMIL\‚ VIRAMA
+0BD7:TAMIL AU LENGTH\¥
+0BE7:TAMIL\hONE
+0BE8:TAMIL\hTWO
+0BE9:TAMIL\hTHREE
+0BEA:TAMIL\hFOUR
+0BEB:TAMIL\hFIVE
+0BEC:TAMIL\hSIX
+0BED:TAMIL\hSEVEN
+0BEE:TAMIL\hE\¼
+0BEF:TAMIL\hNINE
+0BF0:TAMIL \­TEN
+0BF1:TAMIL \­ONE HUNDRED
+0BF2:TAMIL \­ONE THOUSAND
+0C01:\Ï\‚ CANDRABINDU
+0C02:\Ï\‚ ANUSVARA
+0C03:\Ï\‚ VISARGA
+0C05:\Ï\@A
+0C06:\Ï\@AA
+0C07:\Ï\@I
+0C08:\Ï\@II
+0C09:\Ï\@U
+0C0A:\Ï\@UU
+0C0B:\Ï\@\ÎR
+0C0C:\Ï\@\ÎL
+0C0E:\Ï\@E
+0C0F:\Ï\@EE
+0C10:\Ï\@AI
+0C12:\Ï\@O
+0C13:\Ï\@OO
+0C14:\Ï\@AU
+0C15:\Ï\@KA
+0C16:\Ï\@KHA
+0C17:\Ï\@GA
+0C18:\Ï\@GHA
+0C19:\Ï\@NGA
+0C1A:\Ï\@CA
+0C1B:\Ï\@CHA
+0C1C:\Ï\@JA
+0C1D:\Ï\@JHA
+0C1E:\Ï\@NYA
+0C1F:\Ï\@TTA
+0C20:\Ï\@TTHA
+0C21:\Ï\@DDA
+0C22:\Ï\@DDHA
+0C23:\Ï\@NNA
+0C24:\Ï\@TA
+0C25:\Ï\@THA
+0C26:\Ï\@DA
+0C27:\Ï\@DHA
+0C28:\Ï\@NA
+0C2A:\Ï\@PA
+0C2B:\Ï\@PHA
+0C2C:\Ï\@BA
+0C2D:\Ï\@BHA
+0C2E:\Ï\@MA
+0C2F:\Ï\@YA
+0C30:\Ï\@RA
+0C31:\Ï\@RRA
+0C32:\Ï\@LA
+0C33:\Ï\@LLA
+0C35:\Ï\@VA
+0C36:\Ï\@SHA
+0C37:\Ï\@SSA
+0C38:\Ï\@SA
+0C39:\Ï\@HA
+0C3E:\Ï\bAA
+0C3F:\Ï\bI
+0C40:\Ï\bII
+0C41:\Ï\bU
+0C42:\Ï\bUU
+0C43:\Ï\b\ÎR
+0C44:\Ï\b\ÎRR
+0C46:\Ï\bE
+0C47:\Ï\bEE
+0C48:\Ï\bAI
+0C4A:\Ï\bO
+0C4B:\Ï\bOO
+0C4C:\Ï\bAU
+0C4D:\Ï\‚ VIRAMA
+0C55:\Ï LENGTH\¥
+0C56:\Ï AI LENGTH\¥
+0C60:\Ï\@\ÎRR
+0C61:\Ï\@\ÎLL
+0C66:\Ï\hZERO
+0C67:\Ï\hONE
+0C68:\Ï\hTWO
+0C69:\Ï\hTHREE
+0C6A:\Ï\hFOUR
+0C6B:\Ï\hFIVE
+0C6C:\Ï\hSIX
+0C6D:\Ï\hSEVEN
+0C6E:\Ï\hE\¼
+0C6F:\Ï\hNINE
+0C82:\»\‚ ANUSVARA
+0C83:\»\‚ VISARGA
+0C85:\»\@A
+0C86:\»\@AA
+0C87:\»\@I
+0C88:\»\@II
+0C89:\»\@U
+0C8A:\»\@UU
+0C8B:\»\@\ÎR
+0C8C:\»\@\ÎL
+0C8E:\»\@E
+0C8F:\»\@EE
+0C90:\»\@AI
+0C92:\»\@O
+0C93:\»\@OO
+0C94:\»\@AU
+0C95:\»\@KA
+0C96:\»\@KHA
+0C97:\»\@GA
+0C98:\»\@GHA
+0C99:\»\@NGA
+0C9A:\»\@CA
+0C9B:\»\@CHA
+0C9C:\»\@JA
+0C9D:\»\@JHA
+0C9E:\»\@NYA
+0C9F:\»\@TTA
+0CA0:\»\@TTHA
+0CA1:\»\@DDA
+0CA2:\»\@DDHA
+0CA3:\»\@NNA
+0CA4:\»\@TA
+0CA5:\»\@THA
+0CA6:\»\@DA
+0CA7:\»\@DHA
+0CA8:\»\@NA
+0CAA:\»\@PA
+0CAB:\»\@PHA
+0CAC:\»\@BA
+0CAD:\»\@BHA
+0CAE:\»\@MA
+0CAF:\»\@YA
+0CB0:\»\@RA
+0CB1:\»\@RRA
+0CB2:\»\@LA
+0CB3:\»\@LLA
+0CB5:\»\@VA
+0CB6:\»\@SHA
+0CB7:\»\@SSA
+0CB8:\»\@SA
+0CB9:\»\@HA
+0CBE:\»\bAA
+0CBF:\»\bI
+0CC0:\»\bII
+0CC1:\»\bU
+0CC2:\»\bUU
+0CC3:\»\b\ÎR
+0CC4:\»\b\ÎRR
+0CC6:\»\bE
+0CC7:\»\bEE
+0CC8:\»\bAI
+0CCA:\»\bO
+0CCB:\»\bOO
+0CCC:\»\bAU
+0CCD:\»\‚ VIRAMA
+0CD5:\» LENGTH\¥
+0CD6:\» AI LENGTH\¥
+0CDE:\»\@FA
+0CE0:\»\@\ÎRR
+0CE1:\»\@\ÎLL
+0CE6:\»\hZERO
+0CE7:\»\hONE
+0CE8:\»\hTWO
+0CE9:\»\hTHREE
+0CEA:\»\hFOUR
+0CEB:\»\hFIVE
+0CEC:\»\hSIX
+0CED:\»\hSEVEN
+0CEE:\»\hE\¼
+0CEF:\»\hNINE
+0D02:\š\‚ ANUSVARA
+0D03:\š\‚ VISARGA
+0D05:\š\@A
+0D06:\š\@AA
+0D07:\š\@I
+0D08:\š\@II
+0D09:\š\@U
+0D0A:\š\@UU
+0D0B:\š\@\ÎR
+0D0C:\š\@\ÎL
+0D0E:\š\@E
+0D0F:\š\@EE
+0D10:\š\@AI
+0D12:\š\@O
+0D13:\š\@OO
+0D14:\š\@AU
+0D15:\š\@KA
+0D16:\š\@KHA
+0D17:\š\@GA
+0D18:\š\@GHA
+0D19:\š\@NGA
+0D1A:\š\@CA
+0D1B:\š\@CHA
+0D1C:\š\@JA
+0D1D:\š\@JHA
+0D1E:\š\@NYA
+0D1F:\š\@TTA
+0D20:\š\@TTHA
+0D21:\š\@DDA
+0D22:\š\@DDHA
+0D23:\š\@NNA
+0D24:\š\@TA
+0D25:\š\@THA
+0D26:\š\@DA
+0D27:\š\@DHA
+0D28:\š\@NA
+0D2A:\š\@PA
+0D2B:\š\@PHA
+0D2C:\š\@BA
+0D2D:\š\@BHA
+0D2E:\š\@MA
+0D2F:\š\@YA
+0D30:\š\@RA
+0D31:\š\@RRA
+0D32:\š\@LA
+0D33:\š\@LLA
+0D34:\š\@LLLA
+0D35:\š\@VA
+0D36:\š\@SHA
+0D37:\š\@SSA
+0D38:\š\@SA
+0D39:\š\@HA
+0D3E:\š\bAA
+0D3F:\š\bI
+0D40:\š\bII
+0D41:\š\bU
+0D42:\š\bUU
+0D43:\š\b\ÎR
+0D46:\š\bE
+0D47:\š\bEE
+0D48:\š\bAI
+0D4A:\š\bO
+0D4B:\š\bOO
+0D4C:\š\bAU
+0D4D:\š\‚ VIRAMA
+0D57:\š AU LENGTH\¥
+0D60:\š\@\ÎRR
+0D61:\š\@\ÎLL
+0D66:\š\hZERO
+0D67:\š\hONE
+0D68:\š\hTWO
+0D69:\š\hTHREE
+0D6A:\š\hFOUR
+0D6B:\š\hFIVE
+0D6C:\š\hSIX
+0D6D:\š\hSEVEN
+0D6E:\š\hE\¼
+0D6F:\š\hNINE
+0D82:SINHALA\‚ ANUSVARAYA
+0D83:SINHALA\‚ VISARGAYA
+0D85:\¶AYANNA
+0D86:\¶AAYANNA
+0D87:\¶AEYANNA
+0D88:\¶AEEYANNA
+0D89:\¶IYANNA
+0D8A:\¶IIYANNA
+0D8B:\¶UYANNA
+0D8C:\¶UUYANNA
+0D8D:\¶IRUYANNA
+0D8E:\¶IRUUYANNA
+0D8F:\¶ILUYANNA
+0D90:\¶ILUUYANNA
+0D91:\¶EYANNA
+0D92:\¶EEYANNA
+0D93:\¶AIYANNA
+0D94:\¶OYANNA
+0D95:\¶OOYANNA
+0D96:\¶AUYANNA
+0D9A:\¶ALPAPRAANA KAYANNA
+0D9B:\¶MAHAAPRAANA KAYANNA
+0D9C:\¶ALPAPRAANA GAYANNA
+0D9D:\¶MAHAAPRAANA GAYANNA
+0D9E:\¶KANTAJA NAASIKYAYA
+0D9F:\¶SANYAKA GAYANNA
+0DA0:\¶ALPAPRAANA CAYANNA
+0DA1:\¶MAHAAPRAANA CAYANNA
+0DA2:\¶ALPAPRAANA JAYANNA
+0DA3:\¶MAHAAPRAANA JAYANNA
+0DA4:\¶TAALUJA NAASIKYAYA
+0DA5:\¶TAALUJA SANYOOGA NAAKSIKYAYA
+0DA6:\¶SANYAKA JAYANNA
+0DA7:\¶ALPAPRAANA TTAYANNA
+0DA8:\¶MAHAAPRAANA TTAYANNA
+0DA9:\¶ALPAPRAANA DDAYANNA
+0DAA:\¶MAHAAPRAANA DDAYANNA
+0DAB:\¶MUURDHAJA NAYANNA
+0DAC:\¶SANYAKA DDAYANNA
+0DAD:\¶ALPAPRAANA TAYANNA
+0DAE:\¶MAHAAPRAANA TAYANNA
+0DAF:\¶ALPAPRAANA DAYANNA
+0DB0:\¶MAHAAPRAANA DAYANNA
+0DB1:\¶DANTAJA NAYANNA
+0DB3:\¶SANYAKA DAYANNA
+0DB4:\¶ALPAPRAANA PAYANNA
+0DB5:\¶MAHAAPRAANA PAYANNA
+0DB6:\¶ALPAPRAANA BAYANNA
+0DB7:\¶MAHAAPRAANA BAYANNA
+0DB8:\¶MAYANNA
+0DB9:\¶AMBA BAYANNA
+0DBA:\¶YAYANNA
+0DBB:\¶RAYANNA
+0DBD:\¶DANTAJA LAYANNA
+0DC0:\¶VAYANNA
+0DC1:\¶TAALUJA SAYANNA
+0DC2:\¶MUURDHAJA SAYANNA
+0DC3:\¶DANTAJA SAYANNA
+0DC4:\¶HAYANNA
+0DC5:\¶MUURDHAJA LAYANNA
+0DC6:\¶FAYANNA
+0DCA:SINHALA\‚ AL-LAKUNA
+0DCF:SINHALA\bAELA-PILLA
+0DD0:SINHALA\bKETTI AEDA-PILLA
+0DD1:SINHALA\bDIGA AEDA-PILLA
+0DD2:SINHALA\bKETTI IS-PILLA
+0DD3:SINHALA\bDIGA IS-PILLA
+0DD4:SINHALA\bKETTI PAA-PILLA
+0DD6:SINHALA\bDIGA PAA-PILLA
+0DD8:SINHALA\bGAETTA-PILLA
+0DD9:SINHALA\bKOMBUVA
+0DDA:SINHALA\bDIGA KOMBUVA
+0DDB:SINHALA\bKOMBU DEKA
+0DDC:SINHALA\bKOMBUVA HAA AELA-PILLA
+0DDD:SINHALA\bKOMBUVA HAA DIGA AELA-PILLA
+0DDE:SINHALA\bKOMBUVA HAA GAYANUKITTA
+0DDF:SINHALA\bGAYANUKITTA
+0DF2:SINHALA\bDIGA GAETTA-PILLA
+0DF3:SINHALA\bDIGA GAYANUKITTA
+0DF4:SINHALA PUNCTU\” KUNDDALIYA
+0E01:\3KO KAI
+0E02:\3KHO KHAI
+0E03:\3KHO KHUAT
+0E04:\3KHO KHWAI
+0E05:\3KHO KHON
+0E06:\3KHO RAKHANG
+0E07:\3NGO NGU
+0E08:\3CHO CHAN
+0E09:\3CHO CH\ô
+0E0A:\3CHO CHANG
+0E0B:\3SO SO
+0E0C:\3CHO CHOE
+0E0D:\3YO Y\ô
+0E0E:\3DO CHADA
+0E0F:\3TO PATAK
+0E10:\3THO THAN
+0E11:\3THO NANGMONTHO
+0E12:\3THO PHUTHAO
+0E13:\3NO NEN
+0E14:\3DO DEK
+0E15:\3TO TAO
+0E16:\3THO THUNG
+0E17:\3THO THAHAN
+0E18:\3THO THONG
+0E19:\3NO NU
+0E1A:\3BO BAIMAI
+0E1B:\3PO PLA
+0E1C:\3PHO PHUNG
+0E1D:\3FO FA
+0E1E:\3PHO PHAN
+0E1F:\3FO FAN
+0E20:\3PHO SAMPHAO
+0E21:\3MO MA
+0E22:\3YO YAK
+0E23:\3RO RUA
+0E24:\3RU
+0E25:\3LO L\ô
+0E26:\3LU
+0E27:\3WO WAEN
+0E28:\3SO SALA
+0E29:\3SO RUSI
+0E2A:\3SO SUA
+0E2B:\3HO HIP
+0E2C:\3LO CHULA
+0E2D:\3O ANG
+0E2E:\3HO NOKHUK
+0E2F:\3PAIYANNOI
+0E30:\3SARA A
+0E31:\3MAI HAN-AKAT
+0E32:\3SARA AA
+0E33:\3SARA AM
+0E34:\3SARA I
+0E35:\3SARA II
+0E36:\3SARA UE
+0E37:\3SARA UEE
+0E38:\3SARA U
+0E39:\3SARA UU
+0E3A:\3PHINTHU
+0E3F:THAI CURRENCY \ BAHT
+0E40:\3SARA E
+0E41:\3SARA AE
+0E42:\3SARA O
+0E43:\3SARA AI MAIMUAN
+0E44:\3SARA AI MAIMALAI
+0E45:\3LAKKHANGYAO
+0E46:\3MAIYAMOK
+0E47:\3MAITAIKHU
+0E48:\3MAI EK
+0E49:\3MAI THO
+0E4A:\3MAI TRI
+0E4B:\3MAI CHATTAWA
+0E4C:\3THANTHAKHAT
+0E4D:\3NIKHAHIT
+0E4E:\3YAMAKKAN
+0E4F:\3FONGMAN
+0E50:THAI\hZERO
+0E51:THAI\hONE
+0E52:THAI\hTWO
+0E53:THAI\hTHREE
+0E54:THAI\hFOUR
+0E55:THAI\hFIVE
+0E56:THAI\hSIX
+0E57:THAI\hSEVEN
+0E58:THAI\hE\¼
+0E59:THAI\hNINE
+0E5A:\3ANGKHANKHU
+0E5B:\3KHOMUT
+0E81:LAO\@KO
+0E82:LAO\@KHO SUNG
+0E84:LAO\@KHO TAM
+0E87:LAO\@NGO
+0E88:LAO\@CO
+0E8A:LAO\@SO TAM
+0E8D:LAO\@NYO
+0E94:LAO\@DO
+0E95:LAO\@TO
+0E96:LAO\@THO SUNG
+0E97:LAO\@THO TAM
+0E99:LAO\@NO
+0E9A:LAO\@BO
+0E9B:LAO\@PO
+0E9C:LAO\@PHO SUNG
+0E9D:LAO\@FO TAM
+0E9E:LAO\@PHO TAM
+0E9F:LAO\@FO SUNG
+0EA1:LAO\@MO
+0EA2:LAO\@YO
+0EA3:LAO\@LO L\ô
+0EA5:LAO\@LO LOOT
+0EA7:LAO\@WO
+0EAA:LAO\@SO SUNG
+0EAB:LAO\@HO SUNG
+0EAD:LAO\@O
+0EAE:LAO\@HO TAM
+0EAF:LAO ELLIPSIS
+0EB0:LAO\bA
+0EB1:LAO\bMAI KAN
+0EB2:LAO\bAA
+0EB3:LAO\bAM
+0EB4:LAO\bI
+0EB5:LAO\bII
+0EB6:LAO\bY
+0EB7:LAO\bYY
+0EB8:LAO\bU
+0EB9:LAO\bUU
+0EBB:LAO\bMAI KON
+0EBC:LAO SEMIVOWEL\‚ LO
+0EBD:LAO SEMIVOWEL\‚ NYO
+0EC0:LAO\bE
+0EC1:LAO\bEI
+0EC2:LAO\bO
+0EC3:LAO\bAY
+0EC4:LAO\bAI
+0EC6:LAO KO LA
+0EC8:LAO TONE MAI EK
+0EC9:LAO TONE MAI THO
+0ECA:LAO TONE MAI TI
+0ECB:LAO TONE MAI CATAWA
+0ECC:LAO CANCELL\”\¥
+0ECD:LAO NIGGAHITA
+0ED0:LAO\hZERO
+0ED1:LAO\hONE
+0ED2:LAO\hTWO
+0ED3:LAO\hTHREE
+0ED4:LAO\hFOUR
+0ED5:LAO\hFIVE
+0ED6:LAO\hSIX
+0ED7:LAO\hSEVEN
+0ED8:LAO\hE\¼
+0ED9:LAO\hNINE
+0EDC:LAO HO NO
+0EDD:LAO HO MO
+0F00:\5\COM
+0F01:\5\¥ GTER YIG MGO TRUNCAT\ÂA
+0F02:\5\¥ GTER YIG MGO -UM RNAM BCAD MA
+0F03:\5\¥ GTER YIG MGO -UM GTER TSHEG MA
+0F04:\5\¥ INITIAL YIG MGO MDUN MA
+0F05:\5\¥ CLOS\ô YIG MGO SGAB MA
+0F06:\5\¥ CARET YIG MGO PHUR SHAD MA
+0F07:\5\¥ YIG MGO TSHEG SHAD MA
+0F08:\5\¥ SBRUL SHAD
+0F09:\5\¥ BSKUR YIG MGO
+0F0A:\5\¥ BKA- SHOG YIG MGO
+0F0B:\5\¥ INTERSYLLABIC TSHEG
+0F0C:\5\¥ DELIMITER TSHEG BSTAR
+0F0D:\5\¥ SHAD
+0F0E:\5\¥ NYIS SHAD
+0F0F:\5\¥ TSHEG SHAD
+0F10:\5\¥ NYIS TSHEG SHAD
+0F11:\5\¥ RIN CHEN SPUNGS SHAD
+0F12:\5\¥ RGYA GRAM SHAD
+0F13:\5\¥ CARET -DZUD RTAGS ME LONG CAN
+0F14:\5\¥ GTER TSHEG
+0F15:\5 LOGOTYPE\‚ CHAD RTAGS
+0F16:\5 LOGOTYPE\‚ LHAG RTAGS
+0F17:\5 ASTROLOGICAL\‚ SGRA GCAN -CHAR RTAGS
+0F18:\5 ASTROLOGICAL\‚ -KHYUD PA
+0F19:\5 ASTROLOGICAL\‚ SDONG TSHUGS
+0F1A:\5\‚ RDEL DKAR GCIG
+0F1B:\5\‚ RDEL DKAR GNYIS
+0F1C:\5\‚ RDEL DKAR GSUM
+0F1D:\5\‚ RDEL NAG GCIG
+0F1E:\5\‚ RDEL NAG GNYIS
+0F1F:\5\‚ RDEL DKAR RDEL NAG
+0F20:\5\hZERO
+0F21:\5\hONE
+0F22:\5\hTWO
+0F23:\5\hTHREE
+0F24:\5\hFOUR
+0F25:\5\hFIVE
+0F26:\5\hSIX
+0F27:\5\hSEVEN
+0F28:\5\hE\¼
+0F29:\5\hNINE
+0F2A:\5\hHALF ONE
+0F2B:\5\hHALF TWO
+0F2C:\5\hHALF THREE
+0F2D:\5\hHALF FOUR
+0F2E:\5\hHALF FIVE
+0F2F:\5\hHALF SIX
+0F30:\5\hHALF SEVEN
+0F31:\5\hHALF E\¼
+0F32:\5\hHALF NINE
+0F33:\5\hHALF ZERO
+0F34:\5\¥ BSDUS RTAGS
+0F35:\5\¥ NGAS BZUNG NYI ZLA
+0F36:\5\¥ CARET -DZUD RTAGS BZHI MIG CAN
+0F37:\5\¥ NGAS BZUNG SGOR RTAGS
+0F38:\5\¥ CHE MGO
+0F39:\5\¥ TSA -PHRU
+0F3A:\5\¥ GUG RTAGS GYON
+0F3B:\5\¥ GUG RTAGS GYAS
+0F3C:\5\¥ ANG KHANG GYON
+0F3D:\5\¥ ANG KHANG GYAS
+0F3E:\5\‚ YAR TSHES
+0F3F:\5\‚ MAR TSHES
+0F40:\5\@KA
+0F41:\5\@KHA
+0F42:\5\@GA
+0F43:\5\@GHA
+0F44:\5\@NGA
+0F45:\5\@CA
+0F46:\5\@CHA
+0F47:\5\@JA
+0F49:\5\@NYA
+0F4A:\5\@TTA
+0F4B:\5\@TTHA
+0F4C:\5\@DDA
+0F4D:\5\@DDHA
+0F4E:\5\@NNA
+0F4F:\5\@TA
+0F50:\5\@THA
+0F51:\5\@DA
+0F52:\5\@DHA
+0F53:\5\@NA
+0F54:\5\@PA
+0F55:\5\@PHA
+0F56:\5\@BA
+0F57:\5\@BHA
+0F58:\5\@MA
+0F59:\5\@TSA
+0F5A:\5\@TSHA
+0F5B:\5\@DZA
+0F5C:\5\@DZHA
+0F5D:\5\@WA
+0F5E:\5\@ZHA
+0F5F:\5\@ZA
+0F60:\5\@-A
+0F61:\5\@YA
+0F62:\5\@RA
+0F63:\5\@LA
+0F64:\5\@SHA
+0F65:\5\@SSA
+0F66:\5\@SA
+0F67:\5\@HA
+0F68:\5\@A
+0F69:\5\@KSSA
+0F6A:\5\@FIXED-FORM RA
+0F71:\5\bAA
+0F72:\5\bI
+0F73:\5\bII
+0F74:\5\bU
+0F75:\5\bUU
+0F76:\5\b\ÎR
+0F77:\5\b\ÎRR
+0F78:\5\b\ÎL
+0F79:\5\b\ÎLL
+0F7A:\5\bE
+0F7B:\5\bEE
+0F7C:\5\bO
+0F7D:\5\bOO
+0F7E:\5\‚ RJES SU NGA RO
+0F7F:\5\‚ RNAM BCAD
+0F80:\5\b\öI
+0F81:\5\b\öII
+0F82:\5\‚ NYI ZLA NAA DA
+0F83:\5\‚ SNA LDAN
+0F84:\5\¥ HALANTA
+0F85:\5\¥ PALUTA
+0F86:\5\‚ LCI RTAGS
+0F87:\5\‚ YANG RTAGS
+0F88:\5\‚ LCE TSA CAN
+0F89:\5\‚ MCHU CAN
+0F8A:\5\‚ GRU CAN RGY\ôS
+0F8B:\5\‚ GRU M\ÂRGY\ôS
+0F90:\KA
+0F91:\KHA
+0F92:\GA
+0F93:\GHA
+0F94:\NGA
+0F95:\CA
+0F96:\CHA
+0F97:\JA
+0F99:\NYA
+0F9A:\TTA
+0F9B:\TTHA
+0F9C:\DDA
+0F9D:\DDHA
+0F9E:\NNA
+0F9F:\TA
+0FA0:\THA
+0FA1:\DA
+0FA2:\DHA
+0FA3:\NA
+0FA4:\PA
+0FA5:\PHA
+0FA6:\BA
+0FA7:\BHA
+0FA8:\MA
+0FA9:\TSA
+0FAA:\TSHA
+0FAB:\DZA
+0FAC:\DZHA
+0FAD:\WA
+0FAE:\ZHA
+0FAF:\ZA
+0FB0:\-A
+0FB1:\YA
+0FB2:\RA
+0FB3:\LA
+0FB4:\SHA
+0FB5:\SSA
+0FB6:\SA
+0FB7:\HA
+0FB8:\A
+0FB9:\KSSA
+0FBA:\FIXED-FORM WA
+0FBB:\FIXED-FORM YA
+0FBC:\FIXED-FORM RA
+0FBE:\5 KU RU KHA
+0FBF:\5 KU RU KHA BZHI MIG CAN
+0FC0:\5 CANTILL\”\‚ \Å BEAT
+0FC1:\5 CANTILL\”\‚ L\¼ BEAT
+0FC2:\5 CANTILL\”\‚ CANG TE-U
+0FC3:\5 CANTILL\”\‚ SBUB -CHAL
+0FC4:\5 \ DRIL BU
+0FC5:\5 \ RDO RJE
+0FC6:\5 \ PADMA GDAN
+0FC7:\5 \ RDO RJE RGYA GRAM
+0FC8:\5 \ PHUR PA
+0FC9:\5 \ NOR BU
+0FCA:\5 \ NOR BU NYIS -KHYIL
+0FCB:\5 \ NOR BU GSUM -KHYIL
+0FCC:\5 \ NOR BU BZHI -KHYIL
+0FCF:\5\‚ RDEL NAG GSUM
+1000:\½\@KA
+1001:\½\@KHA
+1002:\½\@GA
+1003:\½\@GHA
+1004:\½\@NGA
+1005:\½\@CA
+1006:\½\@CHA
+1007:\½\@JA
+1008:\½\@JHA
+1009:\½\@NYA
+100A:\½\@NNYA
+100B:\½\@TTA
+100C:\½\@TTHA
+100D:\½\@DDA
+100E:\½\@DDHA
+100F:\½\@NNA
+1010:\½\@TA
+1011:\½\@THA
+1012:\½\@DA
+1013:\½\@DHA
+1014:\½\@NA
+1015:\½\@PA
+1016:\½\@PHA
+1017:\½\@BA
+1018:\½\@BHA
+1019:\½\@MA
+101A:\½\@YA
+101B:\½\@RA
+101C:\½\@LA
+101D:\½\@WA
+101E:\½\@SA
+101F:\½\@HA
+1020:\½\@LLA
+1021:\½\@A
+1023:\½\@I
+1024:\½\@II
+1025:\½\@U
+1026:\½\@UU
+1027:\½\@E
+1029:\½\@O
+102A:\½\@AU
+102C:\½\bAA
+102D:\½\bI
+102E:\½\bII
+102F:\½\bU
+1030:\½\bUU
+1031:\½\bE
+1032:\½\bAI
+1036:\½\‚ ANUSVARA
+1037:\½\‚ DOT\…
+1038:\½\‚ VISARGA
+1039:\½\‚ VIRAMA
+1040:\½\hZERO
+1041:\½\hONE
+1042:\½\hTWO
+1043:\½\hTHREE
+1044:\½\hFOUR
+1045:\½\hFIVE
+1046:\½\hSIX
+1047:\½\hSEVEN
+1048:\½\hE\¼
+1049:\½\hNINE
+104A:\½\‚ LITTLE SECTION
+104B:\½\‚ SECTION
+104C:\½ \ LOCATIVE
+104D:\½ \ COMPLETED
+104E:\½ \ AFOREMENTIONED
+104F:\½ \ GENITIVE
+1050:\½\@SHA
+1051:\½\@SSA
+1052:\½\@\ÎR
+1053:\½\@\ÎRR
+1054:\½\@\ÎL
+1055:\½\@\ÎLL
+1056:\½\b\ÎR
+1057:\½\b\ÎRR
+1058:\½\b\ÎL
+1059:\½\b\ÎLL
+10A0:GEORGIAN\ãAN
+10A1:GEORGIAN\ãBAN
+10A2:GEORGIAN\ãGAN
+10A3:GEORGIAN\ãDON
+10A4:GEORGIAN\ãEN
+10A5:GEORGIAN\ãVIN
+10A6:GEORGIAN\ãZEN
+10A7:GEORGIAN\ãTAN
+10A8:GEORGIAN\ãIN
+10A9:GEORGIAN\ãKAN
+10AA:GEORGIAN\ãLAS
+10AB:GEORGIAN\ãMAN
+10AC:GEORGIAN\ãNAR
+10AD:GEORGIAN\ãON
+10AE:GEORGIAN\ãPAR
+10AF:GEORGIAN\ãZHAR
+10B0:GEORGIAN\ãRAE
+10B1:GEORGIAN\ãSAN
+10B2:GEORGIAN\ãTAR
+10B3:GEORGIAN\ãUN
+10B4:GEORGIAN\ãPHAR
+10B5:GEORGIAN\ãKHAR
+10B6:GEORGIAN\ãGHAN
+10B7:GEORGIAN\ãQAR
+10B8:GEORGIAN\ãSHIN
+10B9:GEORGIAN\ãCHIN
+10BA:GEORGIAN\ãCAN
+10BB:GEORGIAN\ãJIL
+10BC:GEORGIAN\ãCIL
+10BD:GEORGIAN\ãCHAR
+10BE:GEORGIAN\ãXAN
+10BF:GEORGIAN\ãJHAN
+10C0:GEORGIAN\ãHAE
+10C1:GEORGIAN\ãHE
+10C2:GEORGIAN\ãHIE
+10C3:GEORGIAN\ãWE
+10C4:GEORGIAN\ãHAR
+10C5:GEORGIAN\ãHOE
+10D0:GEORGIAN\@AN
+10D1:GEORGIAN\@BAN
+10D2:GEORGIAN\@GAN
+10D3:GEORGIAN\@DON
+10D4:GEORGIAN\@EN
+10D5:GEORGIAN\@VIN
+10D6:GEORGIAN\@ZEN
+10D7:GEORGIAN\@TAN
+10D8:GEORGIAN\@IN
+10D9:GEORGIAN\@KAN
+10DA:GEORGIAN\@LAS
+10DB:GEORGIAN\@MAN
+10DC:GEORGIAN\@NAR
+10DD:GEORGIAN\@ON
+10DE:GEORGIAN\@PAR
+10DF:GEORGIAN\@ZHAR
+10E0:GEORGIAN\@RAE
+10E1:GEORGIAN\@SAN
+10E2:GEORGIAN\@TAR
+10E3:GEORGIAN\@UN
+10E4:GEORGIAN\@PHAR
+10E5:GEORGIAN\@KHAR
+10E6:GEORGIAN\@GHAN
+10E7:GEORGIAN\@QAR
+10E8:GEORGIAN\@SHIN
+10E9:GEORGIAN\@CHIN
+10EA:GEORGIAN\@CAN
+10EB:GEORGIAN\@JIL
+10EC:GEORGIAN\@CIL
+10ED:GEORGIAN\@CHAR
+10EE:GEORGIAN\@XAN
+10EF:GEORGIAN\@JHAN
+10F0:GEORGIAN\@HAE
+10F1:GEORGIAN\@HE
+10F2:GEORGIAN\@HIE
+10F3:GEORGIAN\@WE
+10F4:GEORGIAN\@HAR
+10F5:GEORGIAN\@HOE
+10F6:GEORGIAN\@FI
+10F7:GEORGIAN\@YN
+10F8:GEORGIAN\@ELIFI
+10FB:GEORGIAN PARAGRAPH SEPARATOR
+1100:\™KIYEOK
+1101:\™SSANGKIYEOK
+1102:\™N\ÆN
+1103:\™TIKEUT
+1104:\™SSANGTIKEUT
+1105:\™R\ÆL
+1106:\™M\ÆM
+1107:\™P\ÆP
+1108:\™SSANGP\ÆP
+1109:\™SIOS
+110A:\™SSANGSIOS
+110B:\™\ÆNG
+110C:\™C\ÆC
+110D:\™SSANGC\ÆC
+110E:\™CH\ÆCH
+110F:\™KH\ÆKH
+1110:\™TH\ÆTH
+1111:\™PH\ÆPH
+1112:\™H\ÆH
+1113:\™N\ÆN-KIYEOK
+1114:\™SSANGN\ÆN
+1115:\™N\ÆN-TIKEUT
+1116:\™N\ÆN-P\ÆP
+1117:\™TIKEUT-KIYEOK
+1118:\™R\ÆL-N\ÆN
+1119:\™SSANGR\ÆL
+111A:\™R\ÆL-H\ÆH
+111B:\™KAPYEOUNR\ÆL
+111C:\™M\ÆM-P\ÆP
+111D:\™KAPYEOUNM\ÆM
+111E:\™P\ÆP-KIYEOK
+111F:\™P\ÆP-N\ÆN
+1120:\™P\ÆP-TIKEUT
+1121:\™P\ÆP-SIOS
+1122:\™P\ÆP-SIOS-KIYEOK
+1123:\™P\ÆP-SIOS-TIKEUT
+1124:\™P\ÆP-SIOS-P\ÆP
+1125:\™P\ÆP-SSANGSIOS
+1126:\™P\ÆP-SIOS-C\ÆC
+1127:\™P\ÆP-C\ÆC
+1128:\™P\ÆP-CH\ÆCH
+1129:\™P\ÆP-TH\ÆTH
+112A:\™P\ÆP-PH\ÆPH
+112B:\™KAPYEOUNP\ÆP
+112C:\™KAPYEOUNSSANGP\ÆP
+112D:\™SIOS-KIYEOK
+112E:\™SIOS-N\ÆN
+112F:\™SIOS-TIKEUT
+1130:\™SIOS-R\ÆL
+1131:\™SIOS-M\ÆM
+1132:\™SIOS-P\ÆP
+1133:\™SIOS-P\ÆP-KIYEOK
+1134:\™SIOS-SSANGSIOS
+1135:\™SIOS-\ÆNG
+1136:\™SIOS-C\ÆC
+1137:\™SIOS-CH\ÆCH
+1138:\™SIOS-KH\ÆKH
+1139:\™SIOS-TH\ÆTH
+113A:\™SIOS-PH\ÆPH
+113B:\™SIOS-H\ÆH
+113C:\™CHITUEUMSIOS
+113D:\™CHITUEUMSSANGSIOS
+113E:\™CEONGCH\ÆMSIOS
+113F:\™CEONGCH\ÆMSSANGSIOS
+1140:\™PANSIOS
+1141:\™\ÆNG-KIYEOK
+1142:\™\ÆNG-TIKEUT
+1143:\™\ÆNG-M\ÆM
+1144:\™\ÆNG-P\ÆP
+1145:\™\ÆNG-SIOS
+1146:\™\ÆNG-PANSIOS
+1147:\™SSANG\ÆNG
+1148:\™\ÆNG-C\ÆC
+1149:\™\ÆNG-CH\ÆCH
+114A:\™\ÆNG-TH\ÆTH
+114B:\™\ÆNG-PH\ÆPH
+114C:\™YES\ÆNG
+114D:\™C\ÆC-\ÆNG
+114E:\™CHITUEUMC\ÆC
+114F:\™CHITUEUMSSANGC\ÆC
+1150:\™CEONGCH\ÆMC\ÆC
+1151:\™CEONGCH\ÆMSSANGC\ÆC
+1152:\™CH\ÆCH-KH\ÆKH
+1153:\™CH\ÆCH-H\ÆH
+1154:\™CHITUEUMCH\ÆCH
+1155:\™CEONGCH\ÆMCH\ÆCH
+1156:\™PH\ÆPH-P\ÆP
+1157:\™KAPYEOUNPH\ÆPH
+1158:\™SSANGH\ÆH
+1159:\™YEORINH\ÆH
+115F:\™FILLER
+1160:\«FILLER
+1161:\«A
+1162:\«AE
+1163:\«YA
+1164:\«YAE
+1165:\«EO
+1166:\«E
+1167:\«YEO
+1168:\«YE
+1169:\«O
+116A:\«WA
+116B:\«WAE
+116C:\«OE
+116D:\«YO
+116E:\«U
+116F:\«WEO
+1170:\«WE
+1171:\«WI
+1172:\«YU
+1173:\«EU
+1174:\«YI
+1175:\«I
+1176:\«A-O
+1177:\«A-U
+1178:\«YA-O
+1179:\«YA-YO
+117A:\«EO-O
+117B:\«EO-U
+117C:\«EO-EU
+117D:\«YEO-O
+117E:\«YEO-U
+117F:\«O-EO
+1180:\«O-E
+1181:\«O-YE
+1182:\«O-O
+1183:\«O-U
+1184:\«YO-YA
+1185:\«YO-YAE
+1186:\«YO-YEO
+1187:\«YO-O
+1188:\«YO-I
+1189:\«U-A
+118A:\«U-AE
+118B:\«U-EO-EU
+118C:\«U-YE
+118D:\«U-U
+118E:\«YU-A
+118F:\«YU-EO
+1190:\«YU-E
+1191:\«YU-YEO
+1192:\«YU-YE
+1193:\«YU-U
+1194:\«YU-I
+1195:\«EU-U
+1196:\«EU-EU
+1197:\«YI-U
+1198:\«I-A
+1199:\«I-YA
+119A:\«I-O
+119B:\«I-U
+119C:\«I-EU
+119D:\«I-ARAEA
+119E:\«ARAEA
+119F:\«ARAEA-EO
+11A0:\«ARAEA-U
+11A1:\«ARAEA-I
+11A2:\«SSANGARAEA
+11A8:\“KIYEOK
+11A9:\“SSANGKIYEOK
+11AA:\“KIYEOK-SIOS
+11AB:\“N\ÆN
+11AC:\“N\ÆN-C\ÆC
+11AD:\“N\ÆN-H\ÆH
+11AE:\“TIKEUT
+11AF:\“R\ÆL
+11B0:\“R\ÆL-KIYEOK
+11B1:\“R\ÆL-M\ÆM
+11B2:\“R\ÆL-P\ÆP
+11B3:\“R\ÆL-SIOS
+11B4:\“R\ÆL-TH\ÆTH
+11B5:\“R\ÆL-PH\ÆPH
+11B6:\“R\ÆL-H\ÆH
+11B7:\“M\ÆM
+11B8:\“P\ÆP
+11B9:\“P\ÆP-SIOS
+11BA:\“SIOS
+11BB:\“SSANGSIOS
+11BC:\“\ÆNG
+11BD:\“C\ÆC
+11BE:\“CH\ÆCH
+11BF:\“KH\ÆKH
+11C0:\“TH\ÆTH
+11C1:\“PH\ÆPH
+11C2:\“H\ÆH
+11C3:\“KIYEOK-R\ÆL
+11C4:\“KIYEOK-SIOS-KIYEOK
+11C5:\“N\ÆN-KIYEOK
+11C6:\“N\ÆN-TIKEUT
+11C7:\“N\ÆN-SIOS
+11C8:\“N\ÆN-PANSIOS
+11C9:\“N\ÆN-TH\ÆTH
+11CA:\“TIKEUT-KIYEOK
+11CB:\“TIKEUT-R\ÆL
+11CC:\“R\ÆL-KIYEOK-SIOS
+11CD:\“R\ÆL-N\ÆN
+11CE:\“R\ÆL-TIKEUT
+11CF:\“R\ÆL-TIKEUT-H\ÆH
+11D0:\“SSANGR\ÆL
+11D1:\“R\ÆL-M\ÆM-KIYEOK
+11D2:\“R\ÆL-M\ÆM-SIOS
+11D3:\“R\ÆL-P\ÆP-SIOS
+11D4:\“R\ÆL-P\ÆP-H\ÆH
+11D5:\“R\ÆL-KAPYEOUNP\ÆP
+11D6:\“R\ÆL-SSANGSIOS
+11D7:\“R\ÆL-PANSIOS
+11D8:\“R\ÆL-KH\ÆKH
+11D9:\“R\ÆL-YEORINH\ÆH
+11DA:\“M\ÆM-KIYEOK
+11DB:\“M\ÆM-R\ÆL
+11DC:\“M\ÆM-P\ÆP
+11DD:\“M\ÆM-SIOS
+11DE:\“M\ÆM-SSANGSIOS
+11DF:\“M\ÆM-PANSIOS
+11E0:\“M\ÆM-CH\ÆCH
+11E1:\“M\ÆM-H\ÆH
+11E2:\“KAPYEOUNM\ÆM
+11E3:\“P\ÆP-R\ÆL
+11E4:\“P\ÆP-PH\ÆPH
+11E5:\“P\ÆP-H\ÆH
+11E6:\“KAPYEOUNP\ÆP
+11E7:\“SIOS-KIYEOK
+11E8:\“SIOS-TIKEUT
+11E9:\“SIOS-R\ÆL
+11EA:\“SIOS-P\ÆP
+11EB:\“PANSIOS
+11EC:\“\ÆNG-KIYEOK
+11ED:\“\ÆNG-SSANGKIYEOK
+11EE:\“SSANG\ÆNG
+11EF:\“\ÆNG-KH\ÆKH
+11F0:\“YES\ÆNG
+11F1:\“YES\ÆNG-SIOS
+11F2:\“YES\ÆNG-PANSIOS
+11F3:\“PH\ÆPH-P\ÆP
+11F4:\“KAPYEOUNPH\ÆPH
+11F5:\“H\ÆH-N\ÆN
+11F6:\“H\ÆH-R\ÆL
+11F7:\“H\ÆH-M\ÆM
+11F8:\“H\ÆH-P\ÆP
+11F9:\“YEORINH\ÆH
+1200:\VHA
+1201:\VHU
+1202:\VHI
+1203:\VHAA
+1204:\VHEE
+1205:\VHE
+1206:\VHO
+1208:\VLA
+1209:\VLU
+120A:\VLI
+120B:\VLAA
+120C:\VLEE
+120D:\VLE
+120E:\VLO
+120F:\VLWA
+1210:\VHHA
+1211:\VHHU
+1212:\VHHI
+1213:\VHHAA
+1214:\VHHEE
+1215:\VHHE
+1216:\VHHO
+1217:\VHHWA
+1218:\VMA
+1219:\VMU
+121A:\VMI
+121B:\VMAA
+121C:\VMEE
+121D:\VME
+121E:\VMO
+121F:\VMWA
+1220:\VSZA
+1221:\VSZU
+1222:\VSZI
+1223:\VSZAA
+1224:\VSZEE
+1225:\VSZE
+1226:\VSZO
+1227:\VSZWA
+1228:\VRA
+1229:\VRU
+122A:\VRI
+122B:\VRAA
+122C:\VREE
+122D:\VRE
+122E:\VRO
+122F:\VRWA
+1230:\VSA
+1231:\VSU
+1232:\VSI
+1233:\VSAA
+1234:\VSEE
+1235:\VSE
+1236:\VSO
+1237:\VSWA
+1238:\VSHA
+1239:\VSHU
+123A:\VSHI
+123B:\VSHAA
+123C:\VSHEE
+123D:\VSHE
+123E:\VSHO
+123F:\VSHWA
+1240:\VQA
+1241:\VQU
+1242:\VQI
+1243:\VQAA
+1244:\VQEE
+1245:\VQE
+1246:\VQO
+1248:\VQWA
+124A:\VQWI
+124B:\VQWAA
+124C:\VQWEE
+124D:\VQWE
+1250:\VQHA
+1251:\VQHU
+1252:\VQHI
+1253:\VQHAA
+1254:\VQHEE
+1255:\VQHE
+1256:\VQHO
+1258:\VQHWA
+125A:\VQHWI
+125B:\VQHWAA
+125C:\VQHWEE
+125D:\VQHWE
+1260:\VBA
+1261:\VBU
+1262:\VBI
+1263:\VBAA
+1264:\VBEE
+1265:\VBE
+1266:\VBO
+1267:\VBWA
+1268:\VVA
+1269:\VVU
+126A:\VVI
+126B:\VVAA
+126C:\VVEE
+126D:\VVE
+126E:\VVO
+126F:\VVWA
+1270:\VTA
+1271:\VTU
+1272:\VTI
+1273:\VTAA
+1274:\VTEE
+1275:\VTE
+1276:\VTO
+1277:\VTWA
+1278:\VCA
+1279:\VCU
+127A:\VCI
+127B:\VCAA
+127C:\VCEE
+127D:\VCE
+127E:\VCO
+127F:\VCWA
+1280:\VXA
+1281:\VXU
+1282:\VXI
+1283:\VXAA
+1284:\VXEE
+1285:\VXE
+1286:\VXO
+1288:\VXWA
+128A:\VXWI
+128B:\VXWAA
+128C:\VXWEE
+128D:\VXWE
+1290:\VNA
+1291:\VNU
+1292:\VNI
+1293:\VNAA
+1294:\VNEE
+1295:\VNE
+1296:\VNO
+1297:\VNWA
+1298:\VNYA
+1299:\VNYU
+129A:\VNYI
+129B:\VNYAA
+129C:\VNYEE
+129D:\VNYE
+129E:\VNYO
+129F:\VNYWA
+12A0:\VGLOTTAL A
+12A1:\VGLOTTAL U
+12A2:\VGLOTTAL I
+12A3:\VGLOTTAL AA
+12A4:\VGLOTTAL EE
+12A5:\VGLOTTAL E
+12A6:\VGLOTTAL O
+12A7:\VGLOTTAL WA
+12A8:\VKA
+12A9:\VKU
+12AA:\VKI
+12AB:\VKAA
+12AC:\VKEE
+12AD:\VKE
+12AE:\VKO
+12B0:\VKWA
+12B2:\VKWI
+12B3:\VKWAA
+12B4:\VKWEE
+12B5:\VKWE
+12B8:\VKXA
+12B9:\VKXU
+12BA:\VKXI
+12BB:\VKXAA
+12BC:\VKXEE
+12BD:\VKXE
+12BE:\VKXO
+12C0:\VKXWA
+12C2:\VKXWI
+12C3:\VKXWAA
+12C4:\VKXWEE
+12C5:\VKXWE
+12C8:\VWA
+12C9:\VWU
+12CA:\VWI
+12CB:\VWAA
+12CC:\VWEE
+12CD:\VWE
+12CE:\VWO
+12D0:\VPHARYNGEAL A
+12D1:\VPHARYNGEAL U
+12D2:\VPHARYNGEAL I
+12D3:\VPHARYNGEAL AA
+12D4:\VPHARYNGEAL EE
+12D5:\VPHARYNGEAL E
+12D6:\VPHARYNGEAL O
+12D8:\VZA
+12D9:\VZU
+12DA:\VZI
+12DB:\VZAA
+12DC:\VZEE
+12DD:\VZE
+12DE:\VZO
+12DF:\VZWA
+12E0:\VZHA
+12E1:\VZHU
+12E2:\VZHI
+12E3:\VZHAA
+12E4:\VZHEE
+12E5:\VZHE
+12E6:\VZHO
+12E7:\VZHWA
+12E8:\VYA
+12E9:\VYU
+12EA:\VYI
+12EB:\VYAA
+12EC:\VYEE
+12ED:\VYE
+12EE:\VYO
+12F0:\VDA
+12F1:\VDU
+12F2:\VDI
+12F3:\VDAA
+12F4:\VDEE
+12F5:\VDE
+12F6:\VDO
+12F7:\VDWA
+12F8:\VDDA
+12F9:\VDDU
+12FA:\VDDI
+12FB:\VDDAA
+12FC:\VDDEE
+12FD:\VDDE
+12FE:\VDDO
+12FF:\VDDWA
+1300:\VJA
+1301:\VJU
+1302:\VJI
+1303:\VJAA
+1304:\VJEE
+1305:\VJE
+1306:\VJO
+1307:\VJWA
+1308:\VGA
+1309:\VGU
+130A:\VGI
+130B:\VGAA
+130C:\VGEE
+130D:\VGE
+130E:\VGO
+1310:\VGWA
+1312:\VGWI
+1313:\VGWAA
+1314:\VGWEE
+1315:\VGWE
+1318:\VGGA
+1319:\VGGU
+131A:\VGGI
+131B:\VGGAA
+131C:\VGGEE
+131D:\VGGE
+131E:\VGGO
+1320:\VTHA
+1321:\VTHU
+1322:\VTHI
+1323:\VTHAA
+1324:\VTHEE
+1325:\VTHE
+1326:\VTHO
+1327:\VTHWA
+1328:\VCHA
+1329:\VCHU
+132A:\VCHI
+132B:\VCHAA
+132C:\VCHEE
+132D:\VCHE
+132E:\VCHO
+132F:\VCHWA
+1330:\VPHA
+1331:\VPHU
+1332:\VPHI
+1333:\VPHAA
+1334:\VPHEE
+1335:\VPHE
+1336:\VPHO
+1337:\VPHWA
+1338:\VTSA
+1339:\VTSU
+133A:\VTSI
+133B:\VTSAA
+133C:\VTSEE
+133D:\VTSE
+133E:\VTSO
+133F:\VTSWA
+1340:\VTZA
+1341:\VTZU
+1342:\VTZI
+1343:\VTZAA
+1344:\VTZEE
+1345:\VTZE
+1346:\VTZO
+1348:\VFA
+1349:\VFU
+134A:\VFI
+134B:\VFAA
+134C:\VFEE
+134D:\VFE
+134E:\VFO
+134F:\VFWA
+1350:\VPA
+1351:\VPU
+1352:\VPI
+1353:\VPAA
+1354:\VPEE
+1355:\VPE
+1356:\VPO
+1357:\VPWA
+1358:\VRYA
+1359:\VMYA
+135A:\VFYA
+1361:ETHIOPIC WORDSPACE
+1362:ETHIOPIC\é
+1363:ETHIOPIC COMMA
+1364:ETHIOPIC SEMICOLON
+1365:ETHIOPIC COLON
+1366:ETHIOPIC PREFACE COLON
+1367:ETHIOPIC QUESTION\¥
+1368:ETHIOPIC PARAGRAPH SEPARATOR
+1369:ETHIOPIC\hONE
+136A:ETHIOPIC\hTWO
+136B:ETHIOPIC\hTHREE
+136C:ETHIOPIC\hFOUR
+136D:ETHIOPIC\hFIVE
+136E:ETHIOPIC\hSIX
+136F:ETHIOPIC\hSEVEN
+1370:ETHIOPIC\hE\¼
+1371:ETHIOPIC\hNINE
+1372:ETHIOPIC \­TEN
+1373:ETHIOPIC \­TWENTY
+1374:ETHIOPIC \­THIRTY
+1375:ETHIOPIC \­FORTY
+1376:ETHIOPIC \­FIFTY
+1377:ETHIOPIC \­SIXTY
+1378:ETHIOPIC \­SEVENTY
+1379:ETHIOPIC \­E\¼Y
+137A:ETHIOPIC \­NINETY
+137B:ETHIOPIC \­HUNDRED
+137C:ETHIOPIC \­TEN THOUSAND
+13A0:\ŒA
+13A1:\ŒE
+13A2:\ŒI
+13A3:\ŒO
+13A4:\ŒU
+13A5:\ŒV
+13A6:\ŒGA
+13A7:\ŒKA
+13A8:\ŒGE
+13A9:\ŒGI
+13AA:\ŒGO
+13AB:\ŒGU
+13AC:\ŒGV
+13AD:\ŒHA
+13AE:\ŒHE
+13AF:\ŒHI
+13B0:\ŒHO
+13B1:\ŒHU
+13B2:\ŒHV
+13B3:\ŒLA
+13B4:\ŒLE
+13B5:\ŒLI
+13B6:\ŒLO
+13B7:\ŒLU
+13B8:\ŒLV
+13B9:\ŒMA
+13BA:\ŒME
+13BB:\ŒMI
+13BC:\ŒMO
+13BD:\ŒMU
+13BE:\ŒNA
+13BF:\ŒHNA
+13C0:\ŒNAH
+13C1:\ŒNE
+13C2:\ŒNI
+13C3:\ŒNO
+13C4:\ŒNU
+13C5:\ŒNV
+13C6:\ŒQUA
+13C7:\ŒQUE
+13C8:\ŒQUI
+13C9:\ŒQUO
+13CA:\ŒQUU
+13CB:\ŒQUV
+13CC:\ŒSA
+13CD:\ŒS
+13CE:\ŒSE
+13CF:\ŒSI
+13D0:\ŒSO
+13D1:\ŒSU
+13D2:\ŒSV
+13D3:\ŒDA
+13D4:\ŒTA
+13D5:\ŒDE
+13D6:\ŒTE
+13D7:\ŒDI
+13D8:\ŒTI
+13D9:\ŒDO
+13DA:\ŒDU
+13DB:\ŒDV
+13DC:\ŒDLA
+13DD:\ŒTLA
+13DE:\ŒTLE
+13DF:\ŒTLI
+13E0:\ŒTLO
+13E1:\ŒTLU
+13E2:\ŒTLV
+13E3:\ŒTSA
+13E4:\ŒTSE
+13E5:\ŒTSI
+13E6:\ŒTSO
+13E7:\ŒTSU
+13E8:\ŒTSV
+13E9:\ŒWA
+13EA:\ŒWE
+13EB:\ŒWI
+13EC:\ŒWO
+13ED:\ŒWU
+13EE:\ŒWV
+13EF:\ŒYA
+13F0:\ŒYE
+13F1:\ŒYI
+13F2:\ŒYO
+13F3:\ŒYU
+13F4:\ŒYV
+1401:\FE
+1402:\FAAI
+1403:\FI
+1404:\FII
+1405:\FO
+1406:\FOO
+1407:\FY-CREE OO
+1408:\kEE
+1409:\kI
+140A:\FA
+140B:\FAA
+140C:\FWE
+140D:\WE
+140E:\FWI
+140F:\WI
+1410:\FWII
+1411:\WII
+1412:\FWO
+1413:\WO
+1414:\FWOO
+1415:\WOO
+1416:\FNASKAPI WOO
+1417:\FWA
+1418:\WA
+1419:\FWAA
+141A:\WAA
+141B:\FNASKAPI WAA
+141C:\FAI
+141D:\FY-CREE W
+141E:\FGLOTTAL STOP
+141F:\FFINAL \Ü
+1420:\FFINAL GRAVE
+1421:\FFINAL BOTTOM HALF R\ô
+1422:\FFINAL TOP HALF R\ô
+1423:\FFINAL \ùHALF R\ô
+1424:\FFINAL R\ô
+1425:\FFINAL \0 \Ü
+1426:\FFINAL \0 SHORT \€ \ÁS
+1427:\FFINAL MIDDLE DOT
+1428:\FFINAL SHORT \ \Á
+1429:\FFINAL PLUS
+142A:\FFINAL \Ë TACK
+142B:\FEN
+142C:\FIN
+142D:\FON
+142E:\FAN
+142F:\FPE
+1430:\FPAAI
+1431:\FPI
+1432:\FPII
+1433:\FPO
+1434:\FPOO
+1435:\FY-CREE POO
+1436:\kHEE
+1437:\kHI
+1438:\FPA
+1439:\FPAA
+143A:\FPWE
+143B:\PWE
+143C:\FPWI
+143D:\PWI
+143E:\FPWII
+143F:\PWII
+1440:\FPWO
+1441:\PWO
+1442:\FPWOO
+1443:\PWOO
+1444:\FPWA
+1445:\PWA
+1446:\FPWAA
+1447:\PWAA
+1448:\FY-CREE PWAA
+1449:\FP
+144A:\P
+144B:\kH
+144C:\FTE
+144D:\FTAAI
+144E:\FTI
+144F:\FTII
+1450:\FTO
+1451:\FTOO
+1452:\FY-CREE TOO
+1453:\kDEE
+1454:\kDI
+1455:\FTA
+1456:\FTAA
+1457:\FTWE
+1458:\TWE
+1459:\FTWI
+145A:\TWI
+145B:\FTWII
+145C:\TWII
+145D:\FTWO
+145E:\TWO
+145F:\FTWOO
+1460:\TWOO
+1461:\FTWA
+1462:\TWA
+1463:\FTWAA
+1464:\TWAA
+1465:\FNASKAPI TWAA
+1466:\FT
+1467:\FTTE
+1468:\FTTI
+1469:\FTTO
+146A:\FTTA
+146B:\FKE
+146C:\FKAAI
+146D:\FKI
+146E:\FKII
+146F:\FKO
+1470:\FKOO
+1471:\FY-CREE KOO
+1472:\FKA
+1473:\FKAA
+1474:\FKWE
+1475:\KWE
+1476:\FKWI
+1477:\KWI
+1478:\FKWII
+1479:\KWII
+147A:\FKWO
+147B:\KWO
+147C:\FKWOO
+147D:\KWOO
+147E:\FKWA
+147F:\KWA
+1480:\FKWAA
+1481:\KWAA
+1482:\FNASKAPI KWAA
+1483:\FK
+1484:\FKW
+1485:\FSOUTH-SLAVEY KEH
+1486:\FSOUTH-SLAVEY KIH
+1487:\FSOUTH-SLAVEY KOH
+1488:\FSOUTH-SLAVEY KAH
+1489:\FCE
+148A:\FCAAI
+148B:\FCI
+148C:\FCII
+148D:\FCO
+148E:\FCOO
+148F:\FY-CREE COO
+1490:\FCA
+1491:\FCAA
+1492:\FCWE
+1493:\CWE
+1494:\FCWI
+1495:\CWI
+1496:\FCWII
+1497:\CWII
+1498:\FCWO
+1499:\CWO
+149A:\FCWOO
+149B:\CWOO
+149C:\FCWA
+149D:\CWA
+149E:\FCWAA
+149F:\CWAA
+14A0:\FNASKAPI CWAA
+14A1:\FC
+14A2:\FSAYISI TH
+14A3:\FME
+14A4:\FMAAI
+14A5:\FMI
+14A6:\FMII
+14A7:\FMO
+14A8:\FMOO
+14A9:\FY-CREE MOO
+14AA:\FMA
+14AB:\FMAA
+14AC:\FMWE
+14AD:\MWE
+14AE:\FMWI
+14AF:\MWI
+14B0:\FMWII
+14B1:\MWII
+14B2:\FMWO
+14B3:\MWO
+14B4:\FMWOO
+14B5:\MWOO
+14B6:\FMWA
+14B7:\MWA
+14B8:\FMWAA
+14B9:\MWAA
+14BA:\FNASKAPI MWAA
+14BB:\FM
+14BC:\M
+14BD:\FMH
+14BE:\FATHAPASCAN M
+14BF:\FSAYISI M
+14C0:\FNE
+14C1:\FNAAI
+14C2:\FNI
+14C3:\FNII
+14C4:\FNO
+14C5:\FNOO
+14C6:\FY-CREE NOO
+14C7:\FNA
+14C8:\FNAA
+14C9:\FNWE
+14CA:\NWE
+14CB:\FNWA
+14CC:\NWA
+14CD:\FNWAA
+14CE:\NWAA
+14CF:\FNASKAPI NWAA
+14D0:\FN
+14D1:\kNG
+14D2:\FNH
+14D3:\FLE
+14D4:\FLAAI
+14D5:\FLI
+14D6:\FLII
+14D7:\FLO
+14D8:\FLOO
+14D9:\FY-CREE LOO
+14DA:\FLA
+14DB:\FLAA
+14DC:\FLWE
+14DD:\LWE
+14DE:\FLWI
+14DF:\LWI
+14E0:\FLWII
+14E1:\LWII
+14E2:\FLWO
+14E3:\LWO
+14E4:\FLWOO
+14E5:\LWOO
+14E6:\FLWA
+14E7:\LWA
+14E8:\FLWAA
+14E9:\LWAA
+14EA:\FL
+14EB:\L
+14EC:\FMEDIAL L
+14ED:\FSE
+14EE:\FSAAI
+14EF:\FSI
+14F0:\FSII
+14F1:\FSO
+14F2:\FSOO
+14F3:\FY-CREE SOO
+14F4:\FSA
+14F5:\FSAA
+14F6:\FSWE
+14F7:\SWE
+14F8:\FSWI
+14F9:\SWI
+14FA:\FSWII
+14FB:\SWII
+14FC:\FSWO
+14FD:\SWO
+14FE:\FSWOO
+14FF:\SWOO
+1500:\FSWA
+1501:\SWA
+1502:\FSWAA
+1503:\SWAA
+1504:\FNASKAPI SWAA
+1505:\FS
+1506:\FATHAPASCAN S
+1507:\FSW
+1508:\F\¬FOOT S
+1509:\FMOOSE-CREE SK
+150A:\FNASKAPI SKW
+150B:\FNASKAPI S-W
+150C:\FNASKAPI SPWA
+150D:\FNASKAPI STWA
+150E:\FNASKAPI SKWA
+150F:\FNASKAPI SCWA
+1510:\FSHE
+1511:\FSHI
+1512:\FSHII
+1513:\FSHO
+1514:\FSHOO
+1515:\FSHA
+1516:\FSHAA
+1517:\FSHWE
+1518:\SHWE
+1519:\FSHWI
+151A:\SHWI
+151B:\FSHWII
+151C:\SHWII
+151D:\FSHWO
+151E:\SHWO
+151F:\FSHWOO
+1520:\SHWOO
+1521:\FSHWA
+1522:\SHWA
+1523:\FSHWAA
+1524:\SHWAA
+1525:\FSH
+1526:\FYE
+1527:\FYAAI
+1528:\FYI
+1529:\FYII
+152A:\FYO
+152B:\FYOO
+152C:\FY-CREE YOO
+152D:\FYA
+152E:\FYAA
+152F:\FYWE
+1530:\YWE
+1531:\FYWI
+1532:\YWI
+1533:\FYWII
+1534:\YWII
+1535:\FYWO
+1536:\YWO
+1537:\FYWOO
+1538:\YWOO
+1539:\FYWA
+153A:\YWA
+153B:\FYWAA
+153C:\YWAA
+153D:\FNASKAPI YWAA
+153E:\FY
+153F:\FBIBLE-CREE Y
+1540:\Y
+1541:\FSAYISI YI
+1542:\FRE
+1543:\FR-CREE RE
+1544:\LE
+1545:\FRAAI
+1546:\FRI
+1547:\FRII
+1548:\FRO
+1549:\FROO
+154A:\LO
+154B:\FRA
+154C:\FRAA
+154D:\LA
+154E:\FRWAA
+154F:\RWAA
+1550:\FR
+1551:\R
+1552:\FMEDIAL R
+1553:\FFE
+1554:\FFAAI
+1555:\FFI
+1556:\FFII
+1557:\FFO
+1558:\FFOO
+1559:\FFA
+155A:\FFAA
+155B:\FFWAA
+155C:\FWAA
+155D:\FF
+155E:\FTHE
+155F:\FN-CREE THE
+1560:\FTHI
+1561:\FN-CREE THI
+1562:\FTHII
+1563:\FN-CREE THII
+1564:\FTHO
+1565:\FTHOO
+1566:\FTHA
+1567:\FTHAA
+1568:\FTHWAA
+1569:\THWAA
+156A:\FTH
+156B:\FTTHE
+156C:\FTTHI
+156D:\FTTHO
+156E:\FTTHA
+156F:\FTTH
+1570:\FTYE
+1571:\FTYI
+1572:\FTYO
+1573:\FTYA
+1574:\FNUNAVIK HE
+1575:\FNUNAVIK HI
+1576:\FNUNAVIK HII
+1577:\FNUNAVIK HO
+1578:\FNUNAVIK HOO
+1579:\FNUNAVIK HA
+157A:\FNUNAVIK HAA
+157B:\FNUNAVIK H
+157C:\FNUNAVUT H
+157D:\FHK
+157E:\FQAAI
+157F:\FQI
+1580:\FQII
+1581:\FQO
+1582:\FQOO
+1583:\FQA
+1584:\FQAA
+1585:\FQ
+1586:\FTLHE
+1587:\FTLHI
+1588:\FTLHO
+1589:\FTLHA
+158A:\RE
+158B:\RI
+158C:\RO
+158D:\RA
+158E:\FNGAAI
+158F:\FNGI
+1590:\FNGII
+1591:\FNGO
+1592:\FNGOO
+1593:\FNGA
+1594:\FNGAA
+1595:\FNG
+1596:\FNNG
+1597:\FSAYISI SHE
+1598:\FSAYISI SHI
+1599:\FSAYISI SHO
+159A:\FSAYISI SHA
+159B:\FWOODS-CREE THE
+159C:\FWOODS-CREE THI
+159D:\FWOODS-CREE THO
+159E:\FWOODS-CREE THA
+159F:\FWOODS-CREE TH
+15A0:\FLHI
+15A1:\FLHII
+15A2:\FLHO
+15A3:\FLHOO
+15A4:\FLHA
+15A5:\FLHAA
+15A6:\FLH
+15A7:\FTH-CREE THE
+15A8:\FTH-CREE THI
+15A9:\FTH-CREE THII
+15AA:\FTH-CREE THO
+15AB:\FTH-CREE THOO
+15AC:\FTH-CREE THA
+15AD:\FTH-CREE THAA
+15AE:\FTH-CREE TH
+15AF:\FAIVILIK B
+15B0:\F\¬FOOT E
+15B1:\F\¬FOOT I
+15B2:\F\¬FOOT O
+15B3:\F\¬FOOT A
+15B4:\F\¬FOOT WE
+15B5:\F\¬FOOT WI
+15B6:\F\¬FOOT WO
+15B7:\F\¬FOOT WA
+15B8:\F\¬FOOT NE
+15B9:\F\¬FOOT NI
+15BA:\F\¬FOOT NO
+15BB:\F\¬FOOT NA
+15BC:\F\¬FOOT KE
+15BD:\F\¬FOOT KI
+15BE:\F\¬FOOT KO
+15BF:\F\¬FOOT KA
+15C0:\FSAYISI HE
+15C1:\FSAYISI HI
+15C2:\FSAYISI HO
+15C3:\FSAYISI HA
+15C4:\kGHU
+15C5:\kGHO
+15C6:\kGHE
+15C7:\kGHEE
+15C8:\kGHI
+15C9:\kGHA
+15CA:\kRU
+15CB:\kRO
+15CC:\kRE
+15CD:\kREE
+15CE:\kRI
+15CF:\kRA
+15D0:\kWU
+15D1:\kWO
+15D2:\kWE
+15D3:\kWEE
+15D4:\kWI
+15D5:\kWA
+15D6:\kHWU
+15D7:\kHWO
+15D8:\kHWE
+15D9:\kHWEE
+15DA:\kHWI
+15DB:\kHWA
+15DC:\kTHU
+15DD:\kTHO
+15DE:\kTHE
+15DF:\kTHEE
+15E0:\kTHI
+15E1:\kTHA
+15E2:\kTTU
+15E3:\kTTO
+15E4:\kTTE
+15E5:\kTTEE
+15E6:\kTTI
+15E7:\kTTA
+15E8:\kPU
+15E9:\kPO
+15EA:\kPE
+15EB:\kPEE
+15EC:\kPI
+15ED:\kPA
+15EE:\kP
+15EF:\kGU
+15F0:\kGO
+15F1:\kGE
+15F2:\kGEE
+15F3:\kGI
+15F4:\kGA
+15F5:\kKHU
+15F6:\kKHO
+15F7:\kKHE
+15F8:\kKHEE
+15F9:\kKHI
+15FA:\kKHA
+15FB:\kKKU
+15FC:\kKKO
+15FD:\kKKE
+15FE:\kKKEE
+15FF:\kKKI
+1600:\kKKA
+1601:\kKK
+1602:\kNU
+1603:\kNO
+1604:\kNE
+1605:\kNEE
+1606:\kNI
+1607:\kNA
+1608:\kMU
+1609:\kMO
+160A:\kME
+160B:\kMEE
+160C:\kMI
+160D:\kMA
+160E:\kYU
+160F:\kYO
+1610:\kYE
+1611:\kYEE
+1612:\kYI
+1613:\kYA
+1614:\kJU
+1615:\FSAYISI JU
+1616:\kJO
+1617:\kJE
+1618:\kJEE
+1619:\kJI
+161A:\FSAYISI JI
+161B:\kJA
+161C:\kJJU
+161D:\kJJO
+161E:\kJJE
+161F:\kJJEE
+1620:\kJJI
+1621:\kJJA
+1622:\kLU
+1623:\kLO
+1624:\kLE
+1625:\kLEE
+1626:\kLI
+1627:\kLA
+1628:\kDLU
+1629:\kDLO
+162A:\kDLE
+162B:\kDLEE
+162C:\kDLI
+162D:\kDLA
+162E:\kLHU
+162F:\kLHO
+1630:\kLHE
+1631:\kLHEE
+1632:\kLHI
+1633:\kLHA
+1634:\kTLHU
+1635:\kTLHO
+1636:\kTLHE
+1637:\kTLHEE
+1638:\kTLHI
+1639:\kTLHA
+163A:\kTLU
+163B:\kTLO
+163C:\kTLE
+163D:\kTLEE
+163E:\kTLI
+163F:\kTLA
+1640:\kZU
+1641:\kZO
+1642:\kZE
+1643:\kZEE
+1644:\kZI
+1645:\kZA
+1646:\kZ
+1647:\kINITIAL Z
+1648:\kDZU
+1649:\kDZO
+164A:\kDZE
+164B:\kDZEE
+164C:\kDZI
+164D:\kDZA
+164E:\kSU
+164F:\kSO
+1650:\kSE
+1651:\kSEE
+1652:\kSI
+1653:\kSA
+1654:\kSHU
+1655:\kSHO
+1656:\kSHE
+1657:\kSHEE
+1658:\kSHI
+1659:\kSHA
+165A:\kSH
+165B:\kTSU
+165C:\kTSO
+165D:\kTSE
+165E:\kTSEE
+165F:\kTSI
+1660:\kTSA
+1661:\kCHU
+1662:\kCHO
+1663:\kCHE
+1664:\kCHEE
+1665:\kCHI
+1666:\kCHA
+1667:\kTTSU
+1668:\kTTSO
+1669:\kTTSE
+166A:\kTTSEE
+166B:\kTTSI
+166C:\kTTSA
+166D:\FCHI\‚
+166E:\FFULL STOP
+166F:\FQAI
+1670:\FNGAI
+1671:\FNNGI
+1672:\FNNGII
+1673:\FNNGO
+1674:\FNNGOO
+1675:\FNNGA
+1676:\FNNGAA
+1680:OGHAM SPACE\¥
+1681:OGHAM\@BEITH
+1682:OGHAM\@LUIS
+1683:OGHAM\@FEARN
+1684:OGHAM\@SAIL
+1685:OGHAM\@NION
+1686:OGHAM\@UATH
+1687:OGHAM\@DAIR
+1688:OGHAM\@TINNE
+1689:OGHAM\@COLL
+168A:OGHAM\@CEIRT
+168B:OGHAM\@MUIN
+168C:OGHAM\@GORT
+168D:OGHAM\@NGEADAL
+168E:OGHAM\@STRAIF
+168F:OGHAM\@RUIS
+1690:OGHAM\@AILM
+1691:OGHAM\@ONN
+1692:OGHAM\@UR
+1693:OGHAM\@EADHADH
+1694:OGHAM\@IODHADH
+1695:OGHAM\@EABHADH
+1696:OGHAM\@OR
+1697:OGHAM\@UILLEANN
+1698:OGHAM\@IFIN
+1699:OGHAM\@EAMHANCHOLL
+169A:OGHAM\@PEITH
+169B:OGHAM FEATHER\¥
+169C:OGHAM \öFEATHER\¥
+16A0:\ÀFEHU FEOH FE F
+16A1:\ÀV
+16A2:\ÀURUZ UR U
+16A3:\ÀYR
+16A4:\ÀY
+16A5:\ÀW
+16A6:\ÀTHURISAZ THURS THORN
+16A7:\ÀETH
+16A8:\ÀANSUZ A
+16A9:\ÀOS O
+16AA:\ÀAC A
+16AB:\ÀAESC
+16AC:\ÀLONG-BRANCH-OSS O
+16AD:\ÀSHORT-TWIG-OSS O
+16AE:\ÀO
+16AF:\ÀOE
+16B0:\ÀON
+16B1:\ÀRAIDO RAD REID R
+16B2:\ÀKAUNA
+16B3:\ÀCEN
+16B4:\ÀKAUN K
+16B5:\ÀG
+16B6:\ÀENG
+16B7:\ÀGEBO GYFU G
+16B8:\ÀGAR
+16B9:\ÀWUNJO WYNN W
+16BA:\ÀHAGLAZ H
+16BB:\ÀHAEGL H
+16BC:\ÀLONG-BRANCH-HAGALL H
+16BD:\ÀSHORT-TWIG-HAGALL H
+16BE:\ÀNAUDIZ NYD NAUD N
+16BF:\ÀSHORT-TWIG-NAUD N
+16C0:\ÀDOTTED-N
+16C1:\ÀISAZ IS ISS I
+16C2:\ÀE
+16C3:\ÀJERAN J
+16C4:\ÀGER
+16C5:\ÀLONG-BRANCH-AR AE
+16C6:\ÀSHORT-TWIG-AR A
+16C7:\ÀIWAZ EOH
+16C8:\ÀPERTHO PEORTH P
+16C9:\ÀALGIZ EOLHX
+16CA:\ÀSOWILO S
+16CB:\ÀSIGEL LONG-BRANCH-SOL S
+16CC:\ÀSHORT-TWIG-SOL S
+16CD:\ÀC
+16CE:\ÀZ
+16CF:\ÀTIWAZ TIR TYR T
+16D0:\ÀSHORT-TWIG-TYR T
+16D1:\ÀD
+16D2:\ÀBERKANAN BEORC BJARKAN B
+16D3:\ÀSHORT-TWIG-BJARKAN B
+16D4:\ÀDOTTED-P
+16D5:\ÀOPEN-P
+16D6:\ÀEHWAZ EH E
+16D7:\ÀMANNAZ MAN M
+16D8:\ÀLONG-BRANCH-MADR M
+16D9:\ÀSHORT-TWIG-MADR M
+16DA:\ÀLAUKAZ LAGU LOGR L
+16DB:\ÀDOTTED-L
+16DC:\À\ôWAZ
+16DD:\À\ô
+16DE:\ÀDAGAZ DAEG D
+16DF:\ÀOTHALAN ETHEL O
+16E0:\ÀEAR
+16E1:\ÀIOR
+16E2:\ÀCWEORTH
+16E3:\ÀCALC
+16E4:\ÀCEALC
+16E5:\ÀSTAN
+16E6:\ÀLONG-BRANCH-YR
+16E7:\ÀSHORT-TWIG-YR
+16E8:\ÀICELANDIC-YR
+16E9:\ÀQ
+16EA:\ÀX
+16EB:RUNIC S\ôLE PUNCTU\”
+16EC:RUNIC MULTIPLE PUNCTU\”
+16ED:RUNIC CROSS PUNCTU\”
+16EE:RUNIC ARLAUG \
+16EF:RUNIC TVIMADUR \
+16F0:RUNIC BELGTHOR \
+1700:TAGALOG\@A
+1701:TAGALOG\@I
+1702:TAGALOG\@U
+1703:TAGALOG\@KA
+1704:TAGALOG\@GA
+1705:TAGALOG\@NGA
+1706:TAGALOG\@TA
+1707:TAGALOG\@DA
+1708:TAGALOG\@NA
+1709:TAGALOG\@PA
+170A:TAGALOG\@BA
+170B:TAGALOG\@MA
+170C:TAGALOG\@YA
+170E:TAGALOG\@LA
+170F:TAGALOG\@WA
+1710:TAGALOG\@SA
+1711:TAGALOG\@HA
+1712:TAGALOG\bI
+1713:TAGALOG\bU
+1714:TAGALOG\‚ VIRAMA
+1720:HANUNOO\@A
+1721:HANUNOO\@I
+1722:HANUNOO\@U
+1723:HANUNOO\@KA
+1724:HANUNOO\@GA
+1725:HANUNOO\@NGA
+1726:HANUNOO\@TA
+1727:HANUNOO\@DA
+1728:HANUNOO\@NA
+1729:HANUNOO\@PA
+172A:HANUNOO\@BA
+172B:HANUNOO\@MA
+172C:HANUNOO\@YA
+172D:HANUNOO\@RA
+172E:HANUNOO\@LA
+172F:HANUNOO\@WA
+1730:HANUNOO\@SA
+1731:HANUNOO\@HA
+1732:HANUNOO\bI
+1733:HANUNOO\bU
+1734:HANUNOO\‚ PAMUDPOD
+1735:PHILIPPINE S\ôLE PUNCTU\”
+1736:PHILIPPINE \0 PUNCTU\”
+1740:BUHID\@A
+1741:BUHID\@I
+1742:BUHID\@U
+1743:BUHID\@KA
+1744:BUHID\@GA
+1745:BUHID\@NGA
+1746:BUHID\@TA
+1747:BUHID\@DA
+1748:BUHID\@NA
+1749:BUHID\@PA
+174A:BUHID\@BA
+174B:BUHID\@MA
+174C:BUHID\@YA
+174D:BUHID\@RA
+174E:BUHID\@LA
+174F:BUHID\@WA
+1750:BUHID\@SA
+1751:BUHID\@HA
+1752:BUHID\bI
+1753:BUHID\bU
+1760:TAGBANWA\@A
+1761:TAGBANWA\@I
+1762:TAGBANWA\@U
+1763:TAGBANWA\@KA
+1764:TAGBANWA\@GA
+1765:TAGBANWA\@NGA
+1766:TAGBANWA\@TA
+1767:TAGBANWA\@DA
+1768:TAGBANWA\@NA
+1769:TAGBANWA\@PA
+176A:TAGBANWA\@BA
+176B:TAGBANWA\@MA
+176C:TAGBANWA\@YA
+176E:TAGBANWA\@LA
+176F:TAGBANWA\@WA
+1770:TAGBANWA\@SA
+1772:TAGBANWA\bI
+1773:TAGBANWA\bU
+1780:\Ý\@KA
+1781:\Ý\@KHA
+1782:\Ý\@KO
+1783:\Ý\@KHO
+1784:\Ý\@NGO
+1785:\Ý\@CA
+1786:\Ý\@CHA
+1787:\Ý\@CO
+1788:\Ý\@CHO
+1789:\Ý\@NYO
+178A:\Ý\@DA
+178B:\Ý\@TTHA
+178C:\Ý\@DO
+178D:\Ý\@TTHO
+178E:\Ý\@NNO
+178F:\Ý\@TA
+1790:\Ý\@THA
+1791:\Ý\@TO
+1792:\Ý\@THO
+1793:\Ý\@NO
+1794:\Ý\@BA
+1795:\Ý\@PHA
+1796:\Ý\@PO
+1797:\Ý\@PHO
+1798:\Ý\@MO
+1799:\Ý\@YO
+179A:\Ý\@RO
+179B:\Ý\@LO
+179C:\Ý\@VO
+179D:\Ý\@SHA
+179E:\Ý\@SSO
+179F:\Ý\@SA
+17A0:\Ý\@HA
+17A1:\Ý\@LA
+17A2:\Ý\@QA
+17A3:\ÃQAQ
+17A4:\ÃQAA
+17A5:\ÃQI
+17A6:\ÃQII
+17A7:\ÃQU
+17A8:\ÃQUK
+17A9:\ÃQUU
+17AA:\ÃQUUV
+17AB:\ÃRY
+17AC:\ÃRYY
+17AD:\ÃLY
+17AE:\ÃLYY
+17AF:\ÃQE
+17B0:\ÃQAI
+17B1:\ÃQOO TYPE ONE
+17B2:\ÃQOO TYPE TWO
+17B3:\ÃQAU
+17B4:\Ý VOWEL INHERENT AQ
+17B5:\Ý VOWEL INHERENT AA
+17B6:\Ý\bAA
+17B7:\Ý\bI
+17B8:\Ý\bII
+17B9:\Ý\bY
+17BA:\Ý\bYY
+17BB:\Ý\bU
+17BC:\Ý\bUU
+17BD:\Ý\bUA
+17BE:\Ý\bOE
+17BF:\Ý\bYA
+17C0:\Ý\bIE
+17C1:\Ý\bE
+17C2:\Ý\bAE
+17C3:\Ý\bAI
+17C4:\Ý\bOO
+17C5:\Ý\bAU
+17C6:\Ý\‚ NIKAHIT
+17C7:\Ý\‚ REAHMUK
+17C8:\Ý\‚ YUUKALEAPINTU
+17C9:\Ý\‚ MUUSIKATOAN
+17CA:\Ý\‚ TRIISAP
+17CB:\Ý\‚ BANTOC
+17CC:\Ý\‚ ROBAT
+17CD:\Ý\‚ TOANDAKHIAT
+17CE:\Ý\‚ KAKABAT
+17CF:\Ý\‚ AHSDA
+17D0:\Ý\‚ SAMYOK SANNYA
+17D1:\Ý\‚ VIRIAM
+17D2:\Ý\‚ COENG
+17D3:\Ý\‚ BATHAMASAT
+17D4:\Ý\‚ KHAN
+17D5:\Ý\‚\ìIYOOSAN
+17D6:\Ý\‚ CAMNUC PII KUUH
+17D7:\Ý\‚ LEK TOO
+17D8:\Ý\‚ BEYYAL
+17D9:\Ý\‚ PHNAEK MUAN
+17DA:\Ý\‚ KOOMUUT
+17DB:\Ý CURRENCY \ RIEL
+17DC:\Ý\‚ AVAKRAHASANYA
+17E0:\Ý\hZERO
+17E1:\Ý\hONE
+17E2:\Ý\hTWO
+17E3:\Ý\hTHREE
+17E4:\Ý\hFOUR
+17E5:\Ý\hFIVE
+17E6:\Ý\hSIX
+17E7:\Ý\hSEVEN
+17E8:\Ý\hE\¼
+17E9:\Ý\hNINE
+1800:MONGOLIAN BIRGA
+1801:MONGOLIAN ELLIPSIS
+1802:MONGOLIAN COMMA
+1803:MONGOLIAN\é
+1804:MONGOLIAN COLON
+1805:MONGOLIAN FOUR DOTS
+1806:MONGOLIAN TODO SOFT HYPHEN
+1807:MONGOLIAN SIBE\CBOUNDARY\¥ER
+1808:MONGOLIAN MANCHU COMMA
+1809:MONGOLIAN MANCHU\é
+180A:MONGOLIAN NIRUGU
+180B:MONGOLIAN FREE \ç ONE
+180C:MONGOLIAN FREE \ç TWO
+180D:MONGOLIAN FREE \ç THREE
+180E:MONGOLIAN VOWEL SEPARATOR
+1810:MONGOLIAN\hZERO
+1811:MONGOLIAN\hONE
+1812:MONGOLIAN\hTWO
+1813:MONGOLIAN\hTHREE
+1814:MONGOLIAN\hFOUR
+1815:MONGOLIAN\hFIVE
+1816:MONGOLIAN\hSIX
+1817:MONGOLIAN\hSEVEN
+1818:MONGOLIAN\hE\¼
+1819:MONGOLIAN\hNINE
+1820:\xA
+1821:\xE
+1822:\xI
+1823:\xO
+1824:\xU
+1825:\xOE
+1826:\xUE
+1827:\xEE
+1828:\xNA
+1829:\xANG
+182A:\xBA
+182B:\xPA
+182C:\xQA
+182D:\xGA
+182E:\xMA
+182F:\xLA
+1830:\xSA
+1831:\xSHA
+1832:\xTA
+1833:\xDA
+1834:\xCHA
+1835:\xJA
+1836:\xYA
+1837:\xRA
+1838:\xWA
+1839:\xFA
+183A:\xKA
+183B:\xKHA
+183C:\xTSA
+183D:\xZA
+183E:\xHAA
+183F:\xZRA
+1840:\xLHA
+1841:\xZHI
+1842:\xCHI
+1843:\xTODO LONG VOWEL\‚
+1844:\xTODO E
+1845:\xTODO I
+1846:\xTODO O
+1847:\xTODO U
+1848:\xTODO OE
+1849:\xTODO UE
+184A:\xTODO ANG
+184B:\xTODO BA
+184C:\xTODO PA
+184D:\xTODO QA
+184E:\xTODO GA
+184F:\xTODO MA
+1850:\xTODO TA
+1851:\xTODO DA
+1852:\xTODO CHA
+1853:\xTODO JA
+1854:\xTODO TSA
+1855:\xTODO YA
+1856:\xTODO WA
+1857:\xTODO KA
+1858:\xTODO GAA
+1859:\xTODO HAA
+185A:\xTODO JIA
+185B:\xTODO NIA
+185C:\xTODO DZA
+185D:\xSIBE E
+185E:\xSIBE I
+185F:\xSIBE IY
+1860:\xSIBE UE
+1861:\xSIBE U
+1862:\xSIBE ANG
+1863:\xSIBE KA
+1864:\xSIBE GA
+1865:\xSIBE HA
+1866:\xSIBE PA
+1867:\xSIBE SHA
+1868:\xSIBE TA
+1869:\xSIBE DA
+186A:\xSIBE JA
+186B:\xSIBE FA
+186C:\xSIBE GAA
+186D:\xSIBE HAA
+186E:\xSIBE TSA
+186F:\xSIBE ZA
+1870:\xSIBE RAA
+1871:\xSIBE CHA
+1872:\xSIBE ZHA
+1873:\xMANCHU I
+1874:\xMANCHU KA
+1875:\xMANCHU RA
+1876:\xMANCHU FA
+1877:\xMANCHU ZHA
+1880:\x\ÕANUSVARA ONE
+1881:\x\ÕVISARGA ONE
+1882:\x\ÕDAMARU
+1883:\x\ÕUBADAMA
+1884:\x\ÕINVERT\ÂUBADAMA
+1885:\x\ÕBALUDA
+1886:\x\ÕTHREE BALUDA
+1887:\x\ÕA
+1888:\x\ÕI
+1889:\x\ÕKA
+188A:\x\ÕNGA
+188B:\x\ÕCA
+188C:\x\ÕTTA
+188D:\x\ÕTTHA
+188E:\x\ÕDDA
+188F:\x\ÕNNA
+1890:\x\ÕTA
+1891:\x\ÕDA
+1892:\x\ÕPA
+1893:\x\ÕPHA
+1894:\x\ÕSSA
+1895:\x\ÕZHA
+1896:\x\ÕZA
+1897:\x\ÕAH
+1898:\xTODO \ÕTA
+1899:\xTODO \ÕZHA
+189A:\xMANCHU \ÕGHA
+189B:\xMANCHU \ÕNGA
+189C:\xMANCHU \ÕCA
+189D:\xMANCHU \ÕJHA
+189E:\xMANCHU \ÕTTA
+189F:\xMANCHU \ÕDDHA
+18A0:\xMANCHU \ÕTA
+18A1:\xMANCHU \ÕDHA
+18A2:\xMANCHU \ÕSSA
+18A3:\xMANCHU \ÕCYA
+18A4:\xMANCHU \ÕZHA
+18A5:\xMANCHU \ÕZA
+18A6:\x\ÕHALF U
+18A7:\x\ÕHALF YA
+18A8:\xMANCHU \ÕBHA
+18A9:\x\ÕDAGALGA
+1E00:\PA\HR\ô\…
+1E01:\LA\HR\ô\…
+1E02:\PB\³\p
+1E03:\LB\³\p
+1E04:\PB\³\…
+1E05:\LB\³\…
+1E06:\PB\H\ä\…
+1E07:\LB\H\ä\…
+1E08:\PC\HCEDILLA\i\Ü
+1E09:\LC\HCEDILLA\i\Ü
+1E0A:\PD\³\p
+1E0B:\LD\³\p
+1E0C:\PD\³\…
+1E0D:\LD\³\…
+1E0E:\PD\H\ä\…
+1E0F:\LD\H\ä\…
+1E10:\PD\HCEDILLA
+1E11:\LD\HCEDILLA
+1E12:\PD\ˆ\…
+1E13:\LD\ˆ\…
+1E14:\PE\H\å\iGRAVE
+1E15:\LE\H\å\iGRAVE
+1E16:\PE\H\å\i\Ü
+1E17:\LE\H\å\i\Ü
+1E18:\PE\ˆ\…
+1E19:\LE\ˆ\…
+1E1A:\PE\H\æ\…
+1E1B:\LE\H\æ\…
+1E1C:\PE\HCEDILLA\iBREVE
+1E1D:\LE\HCEDILLA\iBREVE
+1E1E:\PF\³\p
+1E1F:\LF\³\p
+1E20:\PG\H\å
+1E21:\LG\H\å
+1E22:\PH\³\p
+1E23:\LH\³\p
+1E24:\PH\³\…
+1E25:\LH\³\…
+1E26:\PH\ž
+1E27:\LH\ž
+1E28:\PH\HCEDILLA
+1E29:\LH\HCEDILLA
+1E2A:\PH\HBREVE\…
+1E2B:\LH\HBREVE\…
+1E2C:\PI\H\æ\…
+1E2D:\LI\H\æ\…
+1E2E:\PI\ž\i\Ü
+1E2F:\LI\ž\i\Ü
+1E30:\PK\H\Ü
+1E31:\LK\H\Ü
+1E32:\PK\³\…
+1E33:\LK\³\…
+1E34:\PK\H\ä\…
+1E35:\LK\H\ä\…
+1E36:\PL\³\…
+1E37:\LL\³\…
+1E38:\PL\³\…\i\å
+1E39:\LL\³\…\i\å
+1E3A:\PL\H\ä\…
+1E3B:\LL\H\ä\…
+1E3C:\PL\ˆ\…
+1E3D:\LL\ˆ\…
+1E3E:\PM\H\Ü
+1E3F:\LM\H\Ü
+1E40:\PM\³\p
+1E41:\LM\³\p
+1E42:\PM\³\…
+1E43:\LM\³\…
+1E44:\PN\³\p
+1E45:\LN\³\p
+1E46:\PN\³\…
+1E47:\LN\³\…
+1E48:\PN\H\ä\…
+1E49:\LN\H\ä\…
+1E4A:\PN\ˆ\…
+1E4B:\LN\ˆ\…
+1E4C:\PO\H\æ\i\Ü
+1E4D:\LO\H\æ\i\Ü
+1E4E:\PO\H\æ\iDIAERESIS
+1E4F:\LO\H\æ\iDIAERESIS
+1E50:\PO\H\å\iGRAVE
+1E51:\LO\H\å\iGRAVE
+1E52:\PO\H\å\i\Ü
+1E53:\LO\H\å\i\Ü
+1E54:\PP\H\Ü
+1E55:\LP\H\Ü
+1E56:\PP\³\p
+1E57:\LP\³\p
+1E58:\PR\³\p
+1E59:\LR\³\p
+1E5A:\PR\³\…
+1E5B:\LR\³\…
+1E5C:\PR\³\…\i\å
+1E5D:\LR\³\…\i\å
+1E5E:\PR\H\ä\…
+1E5F:\LR\H\ä\…
+1E60:\PS\³\p
+1E61:\LS\³\p
+1E62:\PS\³\…
+1E63:\LS\³\…
+1E64:\PS\H\Ü\iDOT\p
+1E65:\LS\H\Ü\iDOT\p
+1E66:\PS\û\iDOT\p
+1E67:\LS\û\iDOT\p
+1E68:\PS\³\…\iDOT\p
+1E69:\LS\³\…\iDOT\p
+1E6A:\PT\³\p
+1E6B:\LT\³\p
+1E6C:\PT\³\…
+1E6D:\LT\³\…
+1E6E:\PT\H\ä\…
+1E6F:\LT\H\ä\…
+1E70:\PT\ˆ\…
+1E71:\LT\ˆ\…
+1E72:\PU\ž\…
+1E73:\LU\ž\…
+1E74:\PU\H\æ\…
+1E75:\LU\H\æ\…
+1E76:\PU\ˆ\…
+1E77:\LU\ˆ\…
+1E78:\PU\H\æ\i\Ü
+1E79:\LU\H\æ\i\Ü
+1E7A:\PU\H\å\iDIAERESIS
+1E7B:\LU\H\å\iDIAERESIS
+1E7C:\PV\H\æ
+1E7D:\LV\H\æ
+1E7E:\PV\³\…
+1E7F:\LV\³\…
+1E80:\PW\HGRAVE
+1E81:\LW\HGRAVE
+1E82:\PW\H\Ü
+1E83:\LW\H\Ü
+1E84:\PW\ž
+1E85:\LW\ž
+1E86:\PW\³\p
+1E87:\LW\³\p
+1E88:\PW\³\…
+1E89:\LW\³\…
+1E8A:\PX\³\p
+1E8B:\LX\³\p
+1E8C:\PX\ž
+1E8D:\LX\ž
+1E8E:\PY\³\p
+1E8F:\LY\³\p
+1E90:\PZ\ˆ
+1E91:\LZ\ˆ
+1E92:\PZ\³\…
+1E93:\LZ\³\…
+1E94:\PZ\H\ä\…
+1E95:\LZ\H\ä\…
+1E96:\LH\H\ä\…
+1E97:\LT\ž
+1E98:\LW\HR\ô\p
+1E99:\LY\HR\ô\p
+1E9A:\LA\H\ùHALF R\ô
+1E9B:\LLONG S\³\p
+1EA0:\PA\³\…
+1EA1:\LA\³\…
+1EA2:\PA\í\p
+1EA3:\LA\í\p
+1EA4:\PA\ˆ\i\Ü
+1EA5:\LA\ˆ\i\Ü
+1EA6:\PA\ˆ\iGRAVE
+1EA7:\LA\ˆ\iGRAVE
+1EA8:\PA\ˆ\iHOOK\p
+1EA9:\LA\ˆ\iHOOK\p
+1EAA:\PA\ˆ\i\æ
+1EAB:\LA\ˆ\i\æ
+1EAC:\PA\ˆ\iDOT\…
+1EAD:\LA\ˆ\iDOT\…
+1EAE:\PA\HBREVE\i\Ü
+1EAF:\LA\HBREVE\i\Ü
+1EB0:\PA\HBREVE\iGRAVE
+1EB1:\LA\HBREVE\iGRAVE
+1EB2:\PA\HBREVE\iHOOK\p
+1EB3:\LA\HBREVE\iHOOK\p
+1EB4:\PA\HBREVE\i\æ
+1EB5:\LA\HBREVE\i\æ
+1EB6:\PA\HBREVE\iDOT\…
+1EB7:\LA\HBREVE\iDOT\…
+1EB8:\PE\³\…
+1EB9:\LE\³\…
+1EBA:\PE\í\p
+1EBB:\LE\í\p
+1EBC:\PE\H\æ
+1EBD:\LE\H\æ
+1EBE:\PE\ˆ\i\Ü
+1EBF:\LE\ˆ\i\Ü
+1EC0:\PE\ˆ\iGRAVE
+1EC1:\LE\ˆ\iGRAVE
+1EC2:\PE\ˆ\iHOOK\p
+1EC3:\LE\ˆ\iHOOK\p
+1EC4:\PE\ˆ\i\æ
+1EC5:\LE\ˆ\i\æ
+1EC6:\PE\ˆ\iDOT\…
+1EC7:\LE\ˆ\iDOT\…
+1EC8:\PI\í\p
+1EC9:\LI\í\p
+1ECA:\PI\³\…
+1ECB:\LI\³\…
+1ECC:\PO\³\…
+1ECD:\LO\³\…
+1ECE:\PO\í\p
+1ECF:\LO\í\p
+1ED0:\PO\ˆ\i\Ü
+1ED1:\LO\ˆ\i\Ü
+1ED2:\PO\ˆ\iGRAVE
+1ED3:\LO\ˆ\iGRAVE
+1ED4:\PO\ˆ\iHOOK\p
+1ED5:\LO\ˆ\iHOOK\p
+1ED6:\PO\ˆ\i\æ
+1ED7:\LO\ˆ\i\æ
+1ED8:\PO\ˆ\iDOT\…
+1ED9:\LO\ˆ\iDOT\…
+1EDA:\PO\HHORN\i\Ü
+1EDB:\LO\HHORN\i\Ü
+1EDC:\PO\HHORN\iGRAVE
+1EDD:\LO\HHORN\iGRAVE
+1EDE:\PO\HHORN\iHOOK\p
+1EDF:\LO\HHORN\iHOOK\p
+1EE0:\PO\HHORN\i\æ
+1EE1:\LO\HHORN\i\æ
+1EE2:\PO\HHORN\iDOT\…
+1EE3:\LO\HHORN\iDOT\…
+1EE4:\PU\³\…
+1EE5:\LU\³\…
+1EE6:\PU\í\p
+1EE7:\LU\í\p
+1EE8:\PU\HHORN\i\Ü
+1EE9:\LU\HHORN\i\Ü
+1EEA:\PU\HHORN\iGRAVE
+1EEB:\LU\HHORN\iGRAVE
+1EEC:\PU\HHORN\iHOOK\p
+1EED:\LU\HHORN\iHOOK\p
+1EEE:\PU\HHORN\i\æ
+1EEF:\LU\HHORN\i\æ
+1EF0:\PU\HHORN\iDOT\…
+1EF1:\LU\HHORN\iDOT\…
+1EF2:\PY\HGRAVE
+1EF3:\LY\HGRAVE
+1EF4:\PY\³\…
+1EF5:\LY\³\…
+1EF6:\PY\í\p
+1EF7:\LY\í\p
+1EF8:\PY\H\æ
+1EF9:\LY\H\æ
+1F00:\y\þ\HPSILI
+1F01:\y\þ\HDASIA
+1F02:\y\þ\·VARIA
+1F03:\y\þ\±VARIA
+1F04:\y\þ\·OXIA
+1F05:\y\þ\±OXIA
+1F06:\y\þ\·\´
+1F07:\y\þ\±\´
+1F08:\9\þ\HPSILI
+1F09:\9\þ\HDASIA
+1F0A:\9\þ\·VARIA
+1F0B:\9\þ\±VARIA
+1F0C:\9\þ\·OXIA
+1F0D:\9\þ\±OXIA
+1F0E:\9\þ\·\´
+1F0F:\9\þ\±\´
+1F10:\yE\É\HPSILI
+1F11:\yE\É\HDASIA
+1F12:\yE\É\·VARIA
+1F13:\yE\É\±VARIA
+1F14:\yE\É\·OXIA
+1F15:\yE\É\±OXIA
+1F18:\9E\É\HPSILI
+1F19:\9E\É\HDASIA
+1F1A:\9E\É\·VARIA
+1F1B:\9E\É\±VARIA
+1F1C:\9E\É\·OXIA
+1F1D:\9E\É\±OXIA
+1F20:\yETA\HPSILI
+1F21:\yETA\HDASIA
+1F22:\yETA\·VARIA
+1F23:\yETA\±VARIA
+1F24:\yETA\·OXIA
+1F25:\yETA\±OXIA
+1F26:\yETA\·\´
+1F27:\yETA\±\´
+1F28:\9ETA\HPSILI
+1F29:\9ETA\HDASIA
+1F2A:\9ETA\·VARIA
+1F2B:\9ETA\±VARIA
+1F2C:\9ETA\·OXIA
+1F2D:\9ETA\±OXIA
+1F2E:\9ETA\·\´
+1F2F:\9ETA\±\´
+1F30:\yIOTA\HPSILI
+1F31:\yIOTA\HDASIA
+1F32:\yIOTA\·VARIA
+1F33:\yIOTA\±VARIA
+1F34:\yIOTA\·OXIA
+1F35:\yIOTA\±OXIA
+1F36:\yIOTA\·\´
+1F37:\yIOTA\±\´
+1F38:\9IOTA\HPSILI
+1F39:\9IOTA\HDASIA
+1F3A:\9IOTA\·VARIA
+1F3B:\9IOTA\±VARIA
+1F3C:\9IOTA\·OXIA
+1F3D:\9IOTA\±OXIA
+1F3E:\9IOTA\·\´
+1F3F:\9IOTA\±\´
+1F40:\yOMICRON\HPSILI
+1F41:\yOMICRON\HDASIA
+1F42:\yOMICRON\·VARIA
+1F43:\yOMICRON\±VARIA
+1F44:\yOMICRON\·OXIA
+1F45:\yOMICRON\±OXIA
+1F48:\9OMICRON\HPSILI
+1F49:\9OMICRON\HDASIA
+1F4A:\9OMICRON\·VARIA
+1F4B:\9OMICRON\±VARIA
+1F4C:\9OMICRON\·OXIA
+1F4D:\9OMICRON\±OXIA
+1F50:\yU\É\HPSILI
+1F51:\yU\É\HDASIA
+1F52:\yU\É\·VARIA
+1F53:\yU\É\±VARIA
+1F54:\yU\É\·OXIA
+1F55:\yU\É\±OXIA
+1F56:\yU\É\·\´
+1F57:\yU\É\±\´
+1F59:\9U\É\HDASIA
+1F5B:\9U\É\±VARIA
+1F5D:\9U\É\±OXIA
+1F5F:\9U\É\±\´
+1F60:\y\ü\HPSILI
+1F61:\y\ü\HDASIA
+1F62:\y\ü\·VARIA
+1F63:\y\ü\±VARIA
+1F64:\y\ü\·OXIA
+1F65:\y\ü\±OXIA
+1F66:\y\ü\·\´
+1F67:\y\ü\±\´
+1F68:\9\ü\HPSILI
+1F69:\9\ü\HDASIA
+1F6A:\9\ü\·VARIA
+1F6B:\9\ü\±VARIA
+1F6C:\9\ü\·OXIA
+1F6D:\9\ü\±OXIA
+1F6E:\9\ü\·\´
+1F6F:\9\ü\±\´
+1F70:\y\þ\HVARIA
+1F71:\y\þ\HOXIA
+1F72:\yE\É\HVARIA
+1F73:\yE\É\HOXIA
+1F74:\yETA\HVARIA
+1F75:\yETA\HOXIA
+1F76:\yIOTA\HVARIA
+1F77:\yIOTA\HOXIA
+1F78:\yOMICRON\HVARIA
+1F79:\yOMICRON\HOXIA
+1F7A:\yU\É\HVARIA
+1F7B:\yU\É\HOXIA
+1F7C:\y\ü\HVARIA
+1F7D:\y\ü\HOXIA
+1F80:\y\þ\·YPO\œ
+1F81:\y\þ\±YPO\œ
+1F82:\y\þ\·VARIA\iYPO\œ
+1F83:\y\þ\±VARIA\iYPO\œ
+1F84:\y\þ\·OXIA\iYPO\œ
+1F85:\y\þ\±OXIA\iYPO\œ
+1F86:\y\þ\·\´\iYPO\œ
+1F87:\y\þ\±\´\iYPO\œ
+1F88:\9\þ\·PROS\œ
+1F89:\9\þ\±PROS\œ
+1F8A:\9\þ\·VARIA\iPROS\œ
+1F8B:\9\þ\±VARIA\iPROS\œ
+1F8C:\9\þ\·OXIA\iPROS\œ
+1F8D:\9\þ\±OXIA\iPROS\œ
+1F8E:\9\þ\·\´\iPROS\œ
+1F8F:\9\þ\±\´\iPROS\œ
+1F90:\yETA\·YPO\œ
+1F91:\yETA\±YPO\œ
+1F92:\yETA\·VARIA\iYPO\œ
+1F93:\yETA\±VARIA\iYPO\œ
+1F94:\yETA\·OXIA\iYPO\œ
+1F95:\yETA\±OXIA\iYPO\œ
+1F96:\yETA\·\´\iYPO\œ
+1F97:\yETA\±\´\iYPO\œ
+1F98:\9ETA\·PROS\œ
+1F99:\9ETA\±PROS\œ
+1F9A:\9ETA\·VARIA\iPROS\œ
+1F9B:\9ETA\±VARIA\iPROS\œ
+1F9C:\9ETA\·OXIA\iPROS\œ
+1F9D:\9ETA\±OXIA\iPROS\œ
+1F9E:\9ETA\·\´\iPROS\œ
+1F9F:\9ETA\±\´\iPROS\œ
+1FA0:\y\ü\·YPO\œ
+1FA1:\y\ü\±YPO\œ
+1FA2:\y\ü\·VARIA\iYPO\œ
+1FA3:\y\ü\±VARIA\iYPO\œ
+1FA4:\y\ü\·OXIA\iYPO\œ
+1FA5:\y\ü\±OXIA\iYPO\œ
+1FA6:\y\ü\·\´\iYPO\œ
+1FA7:\y\ü\±\´\iYPO\œ
+1FA8:\9\ü\·PROS\œ
+1FA9:\9\ü\±PROS\œ
+1FAA:\9\ü\·VARIA\iPROS\œ
+1FAB:\9\ü\±VARIA\iPROS\œ
+1FAC:\9\ü\·OXIA\iPROS\œ
+1FAD:\9\ü\±OXIA\iPROS\œ
+1FAE:\9\ü\·\´\iPROS\œ
+1FAF:\9\ü\±\´\iPROS\œ
+1FB0:\y\þ\HVRACHY
+1FB1:\y\þ\H\å
+1FB2:\y\þ\HVARIA\iYPO\œ
+1FB3:\y\þ\HYPO\œ
+1FB4:\y\þ\HOXIA\iYPO\œ
+1FB6:\y\þ\H\´
+1FB7:\y\þ\H\´\iYPO\œ
+1FB8:\9\þ\HVRACHY
+1FB9:\9\þ\H\å
+1FBA:\9\þ\HVARIA
+1FBB:\9\þ\HOXIA
+1FBC:\9\þ\HPROS\œ
+1FBD:GREEK KORONIS
+1FBE:GREEK PROS\œ
+1FBF:GREEK PSILI
+1FC0:GREEK \´
+1FC1:GREEK DIALYTIKA\i\´
+1FC2:\yETA\HVARIA\iYPO\œ
+1FC3:\yETA\HYPO\œ
+1FC4:\yETA\HOXIA\iYPO\œ
+1FC6:\yETA\H\´
+1FC7:\yETA\H\´\iYPO\œ
+1FC8:\9E\É\HVARIA
+1FC9:\9E\É\HOXIA
+1FCA:\9ETA\HVARIA
+1FCB:\9ETA\HOXIA
+1FCC:\9ETA\HPROS\œ
+1FCD:GREEK PSILI\iVARIA
+1FCE:GREEK PSILI\iOXIA
+1FCF:GREEK PSILI\i\´
+1FD0:\yIOTA\HVRACHY
+1FD1:\yIOTA\H\å
+1FD2:\yIOTA\HDIALYTIKA\iVARIA
+1FD3:\yIOTA\HDIALYTIKA\iOXIA
+1FD6:\yIOTA\H\´
+1FD7:\yIOTA\HDIALYTIKA\i\´
+1FD8:\9IOTA\HVRACHY
+1FD9:\9IOTA\H\å
+1FDA:\9IOTA\HVARIA
+1FDB:\9IOTA\HOXIA
+1FDD:GREEK DASIA\iVARIA
+1FDE:GREEK DASIA\iOXIA
+1FDF:GREEK DASIA\i\´
+1FE0:\yU\É\HVRACHY
+1FE1:\yU\É\H\å
+1FE2:\yU\É\HDIALYTIKA\iVARIA
+1FE3:\yU\É\HDIALYTIKA\iOXIA
+1FE4:\yRHO\HPSILI
+1FE5:\yRHO\HDASIA
+1FE6:\yU\É\H\´
+1FE7:\yU\É\HDIALYTIKA\i\´
+1FE8:\9U\É\HVRACHY
+1FE9:\9U\É\H\å
+1FEA:\9U\É\HVARIA
+1FEB:\9U\É\HOXIA
+1FEC:\9RHO\HDASIA
+1FED:GREEK DIALYTIKA\iVARIA
+1FEE:GREEK DIALYTIKA\iOXIA
+1FEF:GREEK VARIA
+1FF2:\y\ü\HVARIA\iYPO\œ
+1FF3:\y\ü\HYPO\œ
+1FF4:\y\ü\HOXIA\iYPO\œ
+1FF6:\y\ü\H\´
+1FF7:\y\ü\H\´\iYPO\œ
+1FF8:\9OMICRON\HVARIA
+1FF9:\9OMICRON\HOXIA
+1FFA:\9\ü\HVARIA
+1FFB:\9\ü\HOXIA
+1FFC:\9\ü\HPROS\œ
+1FFD:GREEK OXIA
+1FFE:GREEK DASIA
+2000:EN QUAD
+2001:EM QUAD
+2002:EN SPACE
+2003:EM SPACE
+2004:THREE-PER-EM SPACE
+2005:FOUR-PER-EM SPACE
+2006:SIX-PER-EM SPACE
+2007:FIGURE SPACE
+2008:PUNCTU\” SPACE
+2009:THIN SPACE
+200A:HAIR SPACE
+200B:ZERO WIDTH SPACE
+200C:ZERO WIDTH NON-JOINER
+200D:ZERO WIDTH JOINER
+200E:\‰-TO-\ùMARK
+200F:\q-TO-\‰\¥
+2010:HYPHEN
+2011:NON-BREAK\ô HYPHEN
+2012:FIGURE DASH
+2013:EN DASH
+2014:EM DASH
+2015:\\ì
+2016:\0 \€ \ä
+2017:\0 LOW \ä
+2018:\‰ S\ôLE QUOT\”\¥
+2019:\ùS\ôLE QUOT\”\¥
+201A:S\ôLE LOW-9 QUOT\”\¥
+201B:S\ôLE HIGH-REVERSED-9 QUOT\”\¥
+201C:\‰ \0 QUOT\”\¥
+201D:\ù\0 QUOT\”\¥
+201E:\0 LOW-9 QUOT\”\¥
+201F:\0 HIGH-REVERSED-9 QUOT\”\¥
+2020:DAGGER
+2021:\0 DAGGER
+2022:BULLET
+2023:TRIANGULAR BULLET
+2024:ONE DOT LEADER
+2025:TWO DOT LEADER
+2026:\ ELLIPSIS
+2027:HYPHEN\” POINT
+2028:\ä SEPARATOR
+2029:PARAGRAPH SEPARATOR
+202A:\‰-TO-\ùEMBEDD\ô
+202B:\q-TO-\‰ EMBEDD\ô
+202C:POP DIRECTION\XATT\ô
+202D:\‰-TO-\ùOVERRIDE
+202E:\q-TO-\‰ OVERRIDE
+202F:NARROW NO-BREAK SPACE
+2030:PER MILLE\‚
+2031:PER TEN THOUSAND\‚
+2032:PRIME
+2033:\0 PRIME
+2034:TRIPLE PRIME
+2035:\öPRIME
+2036:\ö\0 PRIME
+2037:\öTRIPLE PRIME
+2038:CARET
+2039:S\ôLE \‰-\ÄANGLE QUOT\”\¥
+203A:S\ôLE \q-\ÄANGLE QUOT\”\¥
+203B:REFERENCE\¥
+203C:\0 EXCLAM\”\¥
+203D:INTERROBANG
+203E:OVER\ä
+203F:UNDERTIE
+2040:CHARACTER TIE
+2041:CARET INSERTION POINT
+2042:ASTERISM
+2043:HYPHEN BULLET
+2044:FRACTION SLASH
+2045:\‰ \r\–\HQUILL
+2046:\ù\r\–\HQUILL
+2047:\0 QUESTION\¥
+2048:QUESTION EXCLAM\”\¥
+2049:EXCLAM\” QUESTION\¥
+204A:TIRONIAN\‚ ET
+204B:\öPILCROW\‚
+204C:\¬ \‰\Š BULLET
+204D:\¬ \q\Š BULLET
+204E:LOW ASTERISK
+204F:\öSEMICOLON
+2050:CLOSE UP
+2051:TWO ASTERISKS ALIGN\Â\€LY
+2052:COMMERCIAL MINUS\‚
+2057:QUADRUPLE PRIME
+205F:MEDIUM \ESPACE
+2060:WORD JOINER
+2061:FUNCTION APPLIC\”
+2062:INVISIBLE TIMES
+2063:INVISIBLE SEPARATOR
+206A:INHIBIT SYMMETRIC SWAPP\ô
+206B:ACTIVATE SYMMETRIC SWAPP\ô
+206C:INHIBIT \Ê FORM SHAP\ô
+206D:ACTIVATE \Ê FORM SHAP\ô
+206E:N\”AL\hSHAPES
+206F:NOMINAL\hSHAPES
+2070:SUPER\Ž ZERO
+2071:SUPER\Ž \LI
+2074:SUPER\Ž FOUR
+2075:SUPER\Ž FIVE
+2076:SUPER\Ž SIX
+2077:SUPER\Ž SEVEN
+2078:SUPER\Ž E\¼
+2079:SUPER\Ž NINE
+207A:SUPER\Ž PLUS\‚
+207B:SUPER\Ž MINUS
+207C:SUPER\Ž EQUALS\‚
+207D:SUPER\Ž \‰ \ÑS
+207E:SUPER\Ž \ù\ÑS
+207F:SUPER\Ž \LN
+2080:SUB\Ž ZERO
+2081:SUB\Ž ONE
+2082:SUB\Ž TWO
+2083:SUB\Ž THREE
+2084:SUB\Ž FOUR
+2085:SUB\Ž FIVE
+2086:SUB\Ž SIX
+2087:SUB\Ž SEVEN
+2088:SUB\Ž E\¼
+2089:SUB\Ž NINE
+208A:SUB\Ž PLUS\‚
+208B:SUB\Ž MINUS
+208C:SUB\Ž EQUALS\‚
+208D:SUB\Ž \‰ \ÑS
+208E:SUB\Ž \ù\ÑS
+20A0:EURO-CURRENCY\‚
+20A1:COLON\‚
+20A2:CRUZEIRO\‚
+20A3:FRENCH FRANC\‚
+20A4:LIRA\‚
+20A5:MILL\‚
+20A6:NAIRA\‚
+20A7:PESETA\‚
+20A8:RUPEE\‚
+20A9:WON\‚
+20AA:NEW SHEQEL\‚
+20AB:DONG\‚
+20AC:EURO\‚
+20AD:KIP\‚
+20AE:TUGRIK\‚
+20AF:DRACHMA\‚
+20B0:GERMAN PENNY\‚
+20B1:PESO\‚
+20D0:\o\‰ HARPOON\p
+20D1:\o\ùHARPOON\p
+20D2:\oLONG \€ \ä OVERLAY
+20D3:\oSHORT \€ \ä OVERLAY
+20D4:\oANTICLOCKWISE\u\p
+20D5:\oCLOCKWISE\u\p
+20D6:\o\‰\u\p
+20D7:\o\q\u\p
+20D8:\oR\ô OVERLAY
+20D9:\oCLOCKWISE R\ô OVERLAY
+20DA:\oANTICLOCKWISE R\ô OVERLAY
+20DB:\oTHREE DOTS\p
+20DC:\oFOUR DOTS\p
+20DD:\oENCLOS\ô \Ð
+20DE:\oENCLOS\ô \ý
+20DF:\oENCLOS\ô DIAMOND
+20E0:\oENCLOS\ô \Ð BACKSLASH
+20E1:\o\‰ \q\u\p
+20E2:\oENCLOS\ô SCREEN
+20E3:\oENCLOS\ô KEYCAP
+20E4:\oENCLOS\ô UPWARD \Ä\¾
+20E5:\oREVERSE SOLIDUS OVERLAY
+20E6:\o\0 \€ \Á OVERLAY
+20E7:\oANNUITY \
+20E8:\oTRIPLE UNDERDOT
+20E9:\oWIDE BRIDGE\p
+20EA:\o\‰\Š\u OVERLAY
+2100:ACCOUNT OF
+2101:ADDRESS\ÂTO THE SUBJECT
+2102:\¤\ÒC
+2103:DEGREE CELSIUS
+2104:CENTRE \ä \
+2105:CARE OF
+2106:CADA UNA
+2107:EULER CONSTANT
+2108:SCRUPLE
+2109:DEGREE FAHRENHEIT
+210A:\Ž\ÇG
+210B:\Ž\ÒH
+210C:\¬-LETTER\ÒH
+210D:\¤\ÒH
+210E:PLANCK CONSTANT
+210F:PLANCK CONSTANT OVER TWO PI
+2110:\Ž\ÒI
+2111:\¬-LETTER\ÒI
+2112:\Ž\ÒL
+2113:\Ž\ÇL
+2114:L B\ì \
+2115:\¤\ÒN
+2116:NUMERO\‚
+2117:SOUND RECORD\ô COPY\q
+2118:\Ž\ÒP
+2119:\¤\ÒP
+211A:\¤\ÒQ
+211B:\Ž\ÒR
+211C:\¬-LETTER\ÒR
+211D:\¤\ÒR
+211E:PRE\ŽION TAKE
+211F:RESPONSE
+2120:SERVICE\¥
+2121:TELEPHONE\‚
+2122:TRADE\¥\‚
+2123:VERSICLE
+2124:\¤\ÒZ
+2125:OUNCE\‚
+2126:OHM\‚
+2127:INVERT\ÂOHM\‚
+2128:\¬-LETTER\ÒZ
+2129:TURN\Â\yIOTA
+212A:KELVIN\‚
+212B:ANGSTROM\‚
+212C:\Ž\ÒB
+212D:\¬-LETTER\ÒC
+212E:ESTIMAT\Â\
+212F:\Ž\ÇE
+2130:\Ž\ÒE
+2131:\Ž\ÒF
+2132:TURNED\ÒF
+2133:\Ž\ÒM
+2134:\Ž\ÇO
+2135:ALEF \
+2136:BET \
+2137:GIMEL \
+2138:DALET \
+2139:INFORM\” SOURCE
+213A:ROTATED\ÒQ
+213D:\¤\ÇGAMMA
+213E:\¤\ÒGAMMA
+213F:\¤\ÒPI
+2140:\¤ N-ARY SUMM\”
+2141:TURN\ÂSANS-SERIF\ÒG
+2142:TURN\ÂSANS-SERIF\ÒL
+2143:\öSANS-SERIF\ÒL
+2144:TURN\ÂSANS-SERIF\ÒY
+2145:\¤ \›D
+2146:\¤ \—D
+2147:\¤ \—E
+2148:\¤ \—I
+2149:\¤ \—J
+214A:PROPERTY \ä
+214B:TURN\ÂAMPERSAND
+2153:\úONE THIRD
+2154:\úTWO THIRDS
+2155:\úONE FIFTH
+2156:\úTWO FIFTHS
+2157:\úTHREE FIFTHS
+2158:\úFOUR FIFTHS
+2159:\úONE SIXTH
+215A:\úFIVE SIXTHS
+215B:\úONE E\¼H
+215C:\úTHREE E\¼HS
+215D:\úFIVE E\¼HS
+215E:\úSEVEN E\¼HS
+215F:FRACTION NUMERATOR ONE
+2160:\²ONE
+2161:\²TWO
+2162:\²THREE
+2163:\²FOUR
+2164:\²FIVE
+2165:\²SIX
+2166:\²SEVEN
+2167:\²E\¼
+2168:\²NINE
+2169:\²TEN
+216A:\²ELEVEN
+216B:\²TWELVE
+216C:\²FIFTY
+216D:\²ONE HUNDRED
+216E:\²FIVE HUNDRED
+216F:\²ONE THOUSAND
+2170:\§\²ONE
+2171:\§\²TWO
+2172:\§\²THREE
+2173:\§\²FOUR
+2174:\§\²FIVE
+2175:\§\²SIX
+2176:\§\²SEVEN
+2177:\§\²E\¼
+2178:\§\²NINE
+2179:\§\²TEN
+217A:\§\²ELEVEN
+217B:\§\²TWELVE
+217C:\§\²FIFTY
+217D:\§\²ONE HUNDRED
+217E:\§\²FIVE HUNDRED
+217F:\§\²ONE THOUSAND
+2180:\²ONE THOUSAND C D
+2181:\²FIVE THOUSAND
+2182:\²TEN THOUSAND
+2183:\²\öONE HUNDRED
+2190:\‰\Š\u
+2191:UP\Š\u
+2192:\Ù
+2193:\Ë\Š\u
+2194:\‰ \q\u
+2195:UP \Ë\u
+2196:NORTH WEST\u
+2197:NORTH EAST\u
+2198:SOUTH EAST\u
+2199:SOUTH WEST\u
+219A:\‰\Š\u\H\Á
+219B:\Ù\H\Á
+219C:\‰\Š WAVE\u
+219D:\q\Š WAVE\u
+219E:\‰\Š TWO HEADED\u
+219F:UP\Š TWO HEADED\u
+21A0:\q\Š TWO HEADED\u
+21A1:\Ë\Š TWO HEADED\u
+21A2:\‰\Š\u\HTAIL
+21A3:\Ù\HTAIL
+21A4:\‰\Š\u FROM\ì
+21A5:UP\Š\u FROM\ì
+21A6:\Ù FROM\ì
+21A7:\Ë\Š\u FROM\ì
+21A8:UP \Ë\u\HBASE
+21A9:\‰\Š\u\í
+21AA:\Ù\í
+21AB:\‰\Š\u\HLOOP
+21AC:\Ù\HLOOP
+21AD:\‰ \ùWAVE\u
+21AE:\‰ \q\u\H\Á
+21AF:\Ë\Š ZIGZAG\u
+21B0:UP\Š\u\HTIP \‰\Š
+21B1:UP\Š\u\HTIP \q\Š
+21B2:\Ë\Š\u\HTIP \‰\Š
+21B3:\Ë\Š\u\HTIP \q\Š
+21B4:\Ù\HCORNER \Ë\Š
+21B5:\Ë\Š\u\HCORNER \‰\Š
+21B6:ANTICLOCKWISE TOP SEMI\Ð\u
+21B7:CLOCKWISE TOP SEMI\Ð\u
+21B8:NORTH WEST\u TO LONG\ì
+21B9:\‰\Š\u TO\ì OVER \Ù TO\ì
+21BA:ANTICLOCKWISE OPEN \Ð\u
+21BB:CLOCKWISE OPEN \Ð\u
+21BC:\‰\ƒUP\Š
+21BD:\‰\ƒ\Ë\Š
+21BE:UP\ƒ\q\Š
+21BF:UP\ƒ\‰\Š
+21C0:\q\ƒUP\Š
+21C1:\q\ƒ\Ë\Š
+21C2:\Ë\ƒ\q\Š
+21C3:\Ë\ƒ\‰\Š
+21C4:\Ù OVER \‰\Š\u
+21C5:UP\Š\u \‰\Š OF \Ë\Š\u
+21C6:\‰\Š\u OVER \Ù
+21C7:\‰\Š PAIRED\uS
+21C8:UP\Š PAIRED\uS
+21C9:\q\Š PAIRED\uS
+21CA:\Ë\Š PAIRED\uS
+21CB:\‰\Š HARPOON OVER \q\Š HARPOON
+21CC:\q\Š HARPOON OVER \‰\Š HARPOON
+21CD:\‰\Š \0\u\H\Á
+21CE:\‰ \ù\0\u\H\Á
+21CF:\q\Š \0\u\H\Á
+21D0:\‰\Š \0\u
+21D1:UP\Š \0\u
+21D2:\q\Š \0\u
+21D3:\Ë\Š \0\u
+21D4:\‰ \ù\0\u
+21D5:UP \Ë \0\u
+21D6:NORTH WEST \0\u
+21D7:NORTH EAST \0\u
+21D8:SOUTH EAST \0\u
+21D9:SOUTH WEST \0\u
+21DA:\‰\Š TRIPLE\u
+21DB:\q\Š TRIPLE\u
+21DC:\‰\Š SQUIGGLE\u
+21DD:\q\Š SQUIGGLE\u
+21DE:UP\Š\u\H\0 \Á
+21DF:\Ë\Š\u\H\0 \Á
+21E0:\‰\Š DASHED\u
+21E1:UP\Š DASHED\u
+21E2:\q\Š DASHED\u
+21E3:\Ë\Š DASHED\u
+21E4:\‰\Š\u TO\ì
+21E5:\Ù TO\ì
+21E6:\‰\Š WHITE\u
+21E7:UP\Š WHITE\u
+21E8:\q\Š WHITE\u
+21E9:\Ë\Š WHITE\u
+21EA:UP\Š WHITE\u FROM\ì
+21EB:UP\Š WHITE\u ON PEDESTAL
+21EC:UP\Š WHITE\u ON PEDESTAL\H\\ì
+21ED:UP\Š WHITE\u ON PEDESTAL\H\€\ì
+21EE:UP\Š \¦\0\u
+21EF:UP\Š \¦\0\u ON PEDESTAL
+21F0:\q\Š WHITE\u FROM WALL
+21F1:NORTH WEST\u TO CORNER
+21F2:SOUTH EAST\u TO CORNER
+21F3:UP \Ë WHITE\u
+21F4:\q\u WITH\Ç\Ð
+21F5:\Ë\Š\u \‰\Š OF UP\Š\u
+21F6:THREE \ÙS
+21F7:\‰\Š\u\H\€ \Á
+21F8:\Ù\H\€ \Á
+21F9:\‰ \q\u\H\€ \Á
+21FA:\‰\Š\u\H\0 \€ \Á
+21FB:\Ù\H\0 \€ \Á
+21FC:\‰ \q\u\H\0 \€ \Á
+21FD:\‰\Š OPEN-HEADED\u
+21FE:\q\Š OPEN-HEADED\u
+21FF:\‰ \ùOPEN-HEADED\u
+2200:FOR ALL
+2201:COMPLEMENT
+2202:PARTIAL DIFFERENTIAL
+2203:THERE EXISTS
+2204:THERE DOES NOT EXIST
+2205:EMPTY SET
+2206:INCREMENT
+2207:NABLA
+2208:ELEMENT OF
+2209:NOT AN ELEMENT OF
+220A:\§ELEMENT OF
+220B:CONTAINS AS MEMBER
+220C:DOES NOT CONTAIN AS MEMBER
+220D:\§CONTAINS AS MEMBER
+220E:END OF PROOF
+220F:N-ARY PRODUCT
+2210:N-ARY COPRODUCT
+2211:N-ARY SUMM\”
+2212:MINUS\‚
+2213:MINUS-OR-PLUS\‚
+2214:DOT PLUS
+2215:DIVISION SLASH
+2216:SET MINUS
+2217:ASTERISK\Ú
+2218:R\ô\Ú
+2219:BULLET\Ú
+221A:\rROOT
+221B:CUBE ROOT
+221C:FOURTH ROOT
+221D:PROPORTIONAL TO
+221E:INFINITY
+221F:\ùANGLE
+2220:ANGLE
+2221:MEASUR\ÂANGLE
+2222:SPHERICAL ANGLE
+2223:DIVIDES
+2224:DOES NOT DIVIDE
+2225:PARALLEL TO
+2226:NOT PARALLEL TO
+2227:LOGICAL AND
+2228:LOGICAL OR
+2229:INTERSECTION
+222A:UNION
+222B:INTEGRAL
+222C:\0 INTEGRAL
+222D:TRIPLE INTEGRAL
+222E:CONTOUR INTEGRAL
+222F:SURFACE INTEGRAL
+2230:VOLUME INTEGRAL
+2231:CLOCKWISE INTEGRAL
+2232:CLOCKWISE CONTOUR INTEGRAL
+2233:ANTICLOCKWISE CONTOUR INTEGRAL
+2234:THEREFORE
+2235:BECAUSE
+2236:RATIO
+2237:PROPORTION
+2238:DOT MINUS
+2239:EXCESS
+223A:GEOMETRIC PROPORTION
+223B:HOMOTHETIC
+223C:\æ\Ú
+223D:\ö\æ
+223E:INVERT\ÂLAZY S
+223F:SINE WAVE
+2240:WREATH PRODUCT
+2241:NOT \æ
+2242:MINUS \æ
+2243:ASYMPTOTICALLY\‘
+2244:NOT ASYMPTOTICALLY\‘
+2245:APPROXIMATELY\‘
+2246:APPROXIMATELY BUT NOT ACTUALLY\‘
+2247:NEITHER APPROXIMATELY NOR ACTUALLY\‘
+2248:ALMOST\‘
+2249:NOT ALMOST\‘
+224A:ALMOST EQUAL OR\‘
+224B:TRIPLE \æ
+224C:ALL\‘
+224D:EQUIVALENT TO
+224E:GEOMETRICALLY EQUIVALENT TO
+224F:DIFFERENCE BETWEEN
+2250:APPROACHES THE LIMIT
+2251:GEOMETRICALLY\‘
+2252:APPROXIMATELY\‘ OR THE IMAGE OF
+2253:IMAGE OF OR APPROXIMATELY\‘
+2254:COLON EQUALS
+2255:EQUALS COLON
+2256:R\ô IN\‘
+2257:R\ô\‘
+2258:CORRESPONDS TO
+2259:ESTIMATES
+225A:EQUIANGULAR TO
+225B:STAR EQUALS
+225C:DELTA\‘
+225D:EQUAL TO BY DEFINITION
+225E:MEASUR\ÂBY
+225F:QUESTIONED\‘
+2260:NOT\‘
+2261:IDENTICAL TO
+2262:NOT IDENTICAL TO
+2263:STRICTLY EQUIVALENT TO
+2264:\µ OR\‘
+2265:\’ OR\‘
+2266:\µ OVER\‘
+2267:\’ OVER\‘
+2268:\µ BUT NOT\‘
+2269:\’ BUT NOT\‘
+226A:MUCH \µ
+226B:MUCH \’
+226C:BETWEEN
+226D:NOT EQUIVALENT TO
+226E:NOT \µ
+226F:NOT \’
+2270:NEITHER \µ NOR\‘
+2271:NEITHER \’ NOR\‘
+2272:\µ OR EQUIVALENT TO
+2273:\’ OR EQUIVALENT TO
+2274:NEITHER \µ NOR EQUIVALENT TO
+2275:NEITHER \’ NOR EQUIVALENT TO
+2276:\µ OR \’
+2277:\’ OR \µ
+2278:NEITHER \µ NOR \’
+2279:NEITHER \’ NOR \µ
+227A:PRECEDES
+227B:SUCCEEDS
+227C:PRECEDES OR\‘
+227D:SUCCEEDS OR\‘
+227E:PRECEDES OR EQUIVALENT TO
+227F:SUCCEEDS OR EQUIVALENT TO
+2280:DOES NOT PRECEDE
+2281:DOES NOT SUCCEED
+2282:SUBSET OF
+2283:SUPERSET OF
+2284:NOT A SUBSET OF
+2285:NOT A SUPERSET OF
+2286:SUBSET OF OR\‘
+2287:SUPERSET OF OR\‘
+2288:NEITHER A SUBSET OF NOR\‘
+2289:NEITHER A SUPERSET OF NOR\‘
+228A:SUBSET OF\HNOT\‘
+228B:SUPERSET OF\HNOT\‘
+228C:MULTISET
+228D:MULTISET MULTIPLIC\”
+228E:MULTISET UNION
+228F:\rIMAGE OF
+2290:\rORIGINAL OF
+2291:\rIMAGE OF OR\‘
+2292:\rORIGINAL OF OR\‘
+2293:\rCAP
+2294:\rCUP
+2295:\cPLUS
+2296:\cMINUS
+2297:\cTIMES
+2298:\cDIVISION SLASH
+2299:\cDOT\Ú
+229A:\cR\ô\Ú
+229B:\cASTERISK\Ú
+229C:\cEQUALS
+229D:\cDASH
+229E:\ýD PLUS
+229F:\ýD MINUS
+22A0:\ýD TIMES
+22A1:\ýD DOT\Ú
+22A2:\ùTACK
+22A3:\‰ TACK
+22A4:\Ë TACK
+22A5:UP TACK
+22A6:ASSERTION
+22A7:MODELS
+22A8:TRUE
+22A9:FORCES
+22AA:TRIPLE \€\ì \ùTURNSTILE
+22AB:\0 \€\ì \0 \ùTURNSTILE
+22AC:DOES NOT PROVE
+22AD:NOT TRUE
+22AE:DOES NOT FORCE
+22AF:NEGAT\Â\0 \€\ì \0 \ùTURNSTILE
+22B0:PRECEDES UNDER REL\”
+22B1:SUCCEEDS UNDER REL\”
+22B2:NORMAL SUBGROUP OF
+22B3:CONTAINS AS NORMAL SUBGROUP
+22B4:NORMAL SUBGROUP OF OR\‘
+22B5:CONTAINS AS NORMAL SUBGROUP OR\‘
+22B6:ORIGINAL OF
+22B7:IMAGE OF
+22B8:MULTIMAP
+22B9:HERMITIAN CONJUGATE MATRIX
+22BA:INTERCALATE
+22BB:XOR
+22BC:NAND
+22BD:NOR
+22BE:\ùANGLE\HARC
+22BF:\ù\¾
+22C0:N-ARY LOGICAL AND
+22C1:N-ARY LOGICAL OR
+22C2:N-ARY INTERSECTION
+22C3:N-ARY UNION
+22C4:DIAMOND\Ú
+22C5:DOT\Ú
+22C6:STAR\Ú
+22C7:DIVISION TIMES
+22C8:BOWTIE
+22C9:\‰ NORMAL FACTOR SEMIDIRECT PRODUCT
+22CA:\ùNORMAL FACTOR SEMIDIRECT PRODUCT
+22CB:\‰ SEMIDIRECT PRODUCT
+22CC:\ùSEMIDIRECT PRODUCT
+22CD:\ö\æ EQUALS
+22CE:CURLY LOGICAL OR
+22CF:CURLY LOGICAL AND
+22D0:\0 SUBSET
+22D1:\0 SUPERSET
+22D2:\0 INTERSECTION
+22D3:\0 UNION
+22D4:PITCHFORK
+22D5:EQUAL\iPARALLEL TO
+22D6:\µ\³
+22D7:\’\³
+22D8:VERY MUCH \µ
+22D9:VERY MUCH \’
+22DA:\µ\‘ OR \’
+22DB:\’\‘ OR \µ
+22DC:EQUAL TO OR \µ
+22DD:EQUAL TO OR \’
+22DE:EQUAL TO OR PRECEDES
+22DF:EQUAL TO OR SUCCEEDS
+22E0:DOES NOT PRECEDE OR EQUAL
+22E1:DOES NOT SUCCE\ÂOR EQUAL
+22E2:NOT \rIMAGE OF OR\‘
+22E3:NOT \rORIGINAL OF OR\‘
+22E4:\rIMAGE OF OR NOT\‘
+22E5:\rORIGINAL OF OR NOT\‘
+22E6:\µ BUT NOT EQUIVALENT TO
+22E7:\’ BUT NOT EQUIVALENT TO
+22E8:PRECEDES BUT NOT EQUIVALENT TO
+22E9:SUCCEEDS BUT NOT EQUIVALENT TO
+22EA:NOT NORMAL SUBGROUP OF
+22EB:DOES NOT CONTAIN AS NORMAL SUBGROUP
+22EC:NOT NORMAL SUBGROUP OF OR\‘
+22ED:DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
+22EE:\€ ELLIPSIS
+22EF:MID\ä \ ELLIPSIS
+22F0:UP \ùDIAGONAL ELLIPSIS
+22F1:\Ë \ùDIAGONAL ELLIPSIS
+22F2:ELEMENT OF\HLONG \ \Á
+22F3:ELEMENT OF\H\€\ì AT END OF \ \Á
+22F4:\§ELEMENT OF\H\€\ì AT END OF \ \Á
+22F5:ELEMENT OF\³\p
+22F6:ELEMENT OF\HOVERBAR
+22F7:\§ELEMENT OF\HOVERBAR
+22F8:ELEMENT OF\HUNDERBAR
+22F9:ELEMENT OF\HTWO \ \ÁS
+22FA:CONTAINS\HLONG \ \Á
+22FB:CONTAINS\H\€\ì AT END OF \ \Á
+22FC:\§CONTAINS\H\€\ì AT END OF \ \Á
+22FD:CONTAINS\HOVERBAR
+22FE:\§CONTAINS\HOVERBAR
+22FF:Z NOT\” BAG MEMBERSHIP
+2300:DIAMETER\‚
+2301:ELECTRIC\u
+2302:HOUSE
+2303:UP\uHEAD
+2304:\Ë\uHEAD
+2305:PROJECTIVE
+2306:PERSPECTIVE
+2307:WAVY \ä
+2308:\‰ CEIL\ô
+2309:\ùCEIL\ô
+230A:\‰ FLOOR
+230B:\ùFLOOR
+230C:BOTTOM \ùCROP
+230D:BOTTOM \‰ CROP
+230E:TOP \ùCROP
+230F:TOP \‰ CROP
+2310:\öNOT\‚
+2311:\rLOZENGE
+2312:ARC
+2313:SEGMENT
+2314:SECTOR
+2315:TELEPHONE RECORDER
+2316:POSITION INDICATOR
+2317:VIEWDATA \ý
+2318:PLACE OF INTEREST\‚
+2319:TURN\ÂNOT\‚
+231A:WATCH
+231B:HOURGLASS
+231C:TOP \‰ CORNER
+231D:TOP \ùCORNER
+231E:BOTTOM \‰ CORNER
+231F:BOTTOM \ùCORNER
+2320:TOP HALF INTEGRAL
+2321:BOTTOM HALF INTEGRAL
+2322:FROWN
+2323:SMILE
+2324:UP\uHEAD BETWEEN TWO \\ìS
+2325:OPTION KEY
+2326:ERASE TO THE \q
+2327:X IN A RECTANGLE BOX
+2328:KEYBOARD
+2329:\‰-\ÄANGLE \–
+232A:\q-\ÄANGLE \–
+232B:ERASE TO THE \‰
+232C:BENZENE R\ô
+232D:CYLINDRICITY
+232E:ALL AROUND-PROFILE
+232F:SYMMETRY
+2330:TOTAL RUNOUT
+2331:DIMENSION ORIGIN
+2332:CONICAL TAPER
+2333:SLOPE
+2334:COUNTERBORE
+2335:COUNTERSINK
+2336:\lI-BEAM
+2337:\lSQUISH QUAD
+2338:\lQUAD EQUAL
+2339:\lQUAD DIVIDE
+233A:\lQUAD DIAMOND
+233B:\lQUAD JOT
+233C:\lQUAD \Ð
+233D:\l\Ð STILE
+233E:\l\Ð JOT
+233F:\lSLASH\ì
+2340:\lBACKSLASH\ì
+2341:\lQUAD SLASH
+2342:\lQUAD BACKSLASH
+2343:\lQUAD \µ
+2344:\lQUAD \’
+2345:\l\‰\Š VANE
+2346:\l\q\Š VANE
+2347:\lQUAD \‰\Š\u
+2348:\lQUAD \Ù
+2349:\l\Ð BACKSLASH
+234A:\l\Ë TACK UNDERBAR
+234B:\lDELTA STILE
+234C:\lQUAD \Ë CARET
+234D:\lQUAD DELTA
+234E:\l\Ë TACK JOT
+234F:\lUP\Š VANE
+2350:\lQUAD UP\Š\u
+2351:\lUP TACK OVERBAR
+2352:\lDEL STILE
+2353:\lQUAD UP CARET
+2354:\lQUAD DEL
+2355:\lUP TACK JOT
+2356:\l\Ë\Š VANE
+2357:\lQUAD \Ë\Š\u
+2358:\lQUOTE UNDERBAR
+2359:\lDELTA UNDERBAR
+235A:\lDIAMOND UNDERBAR
+235B:\lJOT UNDERBAR
+235C:\l\Ð UNDERBAR
+235D:\lUP SHOE JOT
+235E:\lQUOTE QUAD
+235F:\l\Ð STAR
+2360:\lQUAD COLON
+2361:\lUP TACK DIAERESIS
+2362:\lDEL DIAERESIS
+2363:\lSTAR DIAERESIS
+2364:\lJOT DIAERESIS
+2365:\l\Ð DIAERESIS
+2366:\l\Ë SHOE STILE
+2367:\l\‰ SHOE STILE
+2368:\l\æ DIAERESIS
+2369:\l\’ DIAERESIS
+236A:\lCOMMA\ì
+236B:\lDEL \æ
+236C:\lZILDE
+236D:\lSTILE \æ
+236E:\lSEMICOLON UNDERBAR
+236F:\lQUAD NOT EQUAL
+2370:\lQUAD QUESTION
+2371:\l\Ë CARET \æ
+2372:\lUP CARET \æ
+2373:\lIOTA
+2374:\lRHO
+2375:\l\ü
+2376:\l\þ UNDERBAR
+2377:\lE\É UNDERBAR
+2378:\lIOTA UNDERBAR
+2379:\l\ü UNDERBAR
+237A:\l\þ
+237B:NOT CHECK\¥
+237C:\ùANGLE\H\Ë\Š ZIGZAG\u
+237D:SHOULDER\ÂOPEN BOX
+237E:BELL \
+237F:\€ \ä\HMIDDLE DOT
+2380:INSERTION \
+2381:CONTINUOUS UNDER\ä \
+2382:DISCONTINUOUS UNDER\ä \
+2383:EMPHASIS \
+2384:COMPOSITION \
+2385:\¦\rWITH CENTRE \€ \ä
+2386:ENTER \
+2387:ALTERNATIVE KEY \
+2388:HELM \
+2389:\c\\ì\HNOTCH
+238A:\c\¾ \Ë
+238B:BROKEN \Ð\HNORTHWEST\u
+238C:UNDO \
+238D:MONOSTABLE \
+238E:HYSTERESIS \
+238F:OPEN-CIRCUIT-OUTPUT H-TYPE \
+2390:OPEN-CIRCUIT-OUTPUT L-TYPE \
+2391:PASSIVE-PULL-\Ë-OUTPUT \
+2392:PASSIVE-PULL-UP-OUTPUT \
+2393:DIRECT CURRENT \ FORM TWO
+2394:SOFTWARE-FUNCTION \
+2395:\lQUAD
+2396:DECIMAL SEPARATOR KEY \
+2397:PREVIOUS PAGE
+2398:NEXT PAGE
+2399:PRINT SCREEN \
+239A:CLEAR SCREEN \
+239B:\‰ \ÑS \÷HOOK
+239C:\‰ \ÑS EXTENSION
+239D:\‰ \ÑS \ïHOOK
+239E:\ù\ÑS \÷HOOK
+239F:\ù\ÑS EXTENSION
+23A0:\ù\ÑS \ïHOOK
+23A1:\‰ \r\– \÷CORNER
+23A2:\‰ \r\– EXTENSION
+23A3:\‰ \r\– \ïCORNER
+23A4:\ù\r\– \÷CORNER
+23A5:\ù\r\– EXTENSION
+23A6:\ù\r\– \ïCORNER
+23A7:\‰ CURLY \– \÷HOOK
+23A8:\‰ CURLY \– MIDDLE PIECE
+23A9:\‰ CURLY \– \ïHOOK
+23AA:CURLY \– EXTENSION
+23AB:\ùCURLY \– \÷HOOK
+23AC:\ùCURLY \– MIDDLE PIECE
+23AD:\ùCURLY \– \ïHOOK
+23AE:INTEGRAL EXTENSION
+23AF:\ \ä EXTENSION
+23B0:\÷\‰ OR \ï\ùCURLY \– SECTION
+23B1:\÷\ùOR \ï\‰ CURLY \– SECTION
+23B2:SUMM\” TOP
+23B3:SUMM\” BOTTOM
+23B4:TOP \r\–
+23B5:BOTTOM \r\–
+23B6:BOTTOM \r\– OVER TOP \r\–
+23B7:RADICAL \ BOTTOM
+23B8:\‰ \€ BOX \ä
+23B9:\ù\€ BOX \ä
+23BA:\ SCAN \ä-1
+23BB:\ SCAN \ä-3
+23BC:\ SCAN \ä-7
+23BD:\ SCAN \ä-9
+23BE:\ó\€\iTOP \q
+23BF:\ó\€\iBOTTOM \q
+23C0:\ó\€\H\Ð
+23C1:\ó\Ë\i\\H\Ð
+23C2:\óUP\i\\H\Ð
+23C3:\ó\€\H\¾
+23C4:\ó\Ë\i\\H\¾
+23C5:\óUP\i\\H\¾
+23C6:\ó\€\iWAVE
+23C7:\ó\Ë\i\\HWAVE
+23C8:\óUP\i\\HWAVE
+23C9:\ó\Ë\i\
+23CA:\óUP\i\
+23CB:\ó\€\iTOP \‰
+23CC:\ó\€\iBOTTOM \‰
+23CD:\rFOOT
+23CE:RETURN \
+2400:\ñNULL
+2401:\ñSTART OF HEAD\ô
+2402:\ñSTART OF TEXT
+2403:\ñEND OF TEXT
+2404:\ñEND OF TRANSMISSION
+2405:\ñENQUIRY
+2406:\ñACKNOWLEDGE
+2407:\ñBELL
+2408:\ñBACKSPACE
+2409:\ñ\ TABUL\”
+240A:\ñ\ä FEED
+240B:\ñ\€ TABUL\”
+240C:\ñFORM FEED
+240D:\ñCARRIAGE RETURN
+240E:\ñSHIFT OUT
+240F:\ñSHIFT IN
+2410:\ñDATA LINK ESCAPE
+2411:\ñDEVICE CONTROL ONE
+2412:\ñDEVICE CONTROL TWO
+2413:\ñDEVICE CONTROL THREE
+2414:\ñDEVICE CONTROL FOUR
+2415:\ñNEGATIVE ACKNOWLEDGE
+2416:\ñSYNCHRONOUS IDLE
+2417:\ñEND OF TRANSMISSION BLOCK
+2418:\ñCANCEL
+2419:\ñEND OF MEDIUM
+241A:\ñSUBSTITUTE
+241B:\ñESCAPE
+241C:\ñFILE SEPARATOR
+241D:\ñGROUP SEPARATOR
+241E:\ñRECORD SEPARATOR
+241F:\ñUNIT SEPARATOR
+2420:\ñSPACE
+2421:\ñDELETE
+2422:BLANK \
+2423:OPEN BOX
+2424:\ñNEW\ä
+2425:\ñDELETE FORM TWO
+2426:\ñSUBSTITUTE FORM TWO
+2440:OCR HOOK
+2441:OCR CHAIR
+2442:OCR FORK
+2443:OCR INVERT\ÂFORK
+2444:OCR BELT BUCKLE
+2445:OCR BOW TIE
+2446:OCR BRANCH BANK IDENTIFIC\”
+2447:OCR AMOUNT OF CHECK
+2448:OCR DASH
+2449:OCR CUSTOMER ACCOUNT NUMBER
+244A:OCR \0 BACKSLASH
+2460:\cDIGIT ONE
+2461:\cDIGIT TWO
+2462:\cDIGIT THREE
+2463:\cDIGIT FOUR
+2464:\cDIGIT FIVE
+2465:\cDIGIT SIX
+2466:\cDIGIT SEVEN
+2467:\cDIGIT E\¼
+2468:\cDIGIT NINE
+2469:\c\­TEN
+246A:\c\­ELEVEN
+246B:\c\­TWELVE
+246C:\c\­THIRTEEN
+246D:\c\­FOURTEEN
+246E:\c\­FIFTEEN
+246F:\c\­SIXTEEN
+2470:\c\­SEVENTEEN
+2471:\c\­E\¼EEN
+2472:\c\­NINETEEN
+2473:\c\­TWENTY
+2474:\tDIGIT ONE
+2475:\tDIGIT TWO
+2476:\tDIGIT THREE
+2477:\tDIGIT FOUR
+2478:\tDIGIT FIVE
+2479:\tDIGIT SIX
+247A:\tDIGIT SEVEN
+247B:\tDIGIT E\¼
+247C:\tDIGIT NINE
+247D:\t\­TEN
+247E:\t\­ELEVEN
+247F:\t\­TWELVE
+2480:\t\­THIRTEEN
+2481:\t\­FOURTEEN
+2482:\t\­FIFTEEN
+2483:\t\­SIXTEEN
+2484:\t\­SEVENTEEN
+2485:\t\­E\¼EEN
+2486:\t\­NINETEEN
+2487:\t\­TWENTY
+2488:DIGIT ONE\é
+2489:DIGIT TWO\é
+248A:DIGIT THREE\é
+248B:DIGIT FOUR\é
+248C:DIGIT FIVE\é
+248D:DIGIT SIX\é
+248E:DIGIT SEVEN\é
+248F:DIGIT E\¼\é
+2490:DIGIT NINE\é
+2491:\­TEN\é
+2492:\­ELEVEN\é
+2493:\­TWELVE\é
+2494:\­THIRTEEN\é
+2495:\­FOURTEEN\é
+2496:\­FIFTEEN\é
+2497:\­SIXTEEN\é
+2498:\­SEVENTEEN\é
+2499:\­E\¼EEN\é
+249A:\­NINETEEN\é
+249B:\­TWENTY\é
+249C:\t\LA
+249D:\t\LB
+249E:\t\LC
+249F:\t\LD
+24A0:\t\LE
+24A1:\t\LF
+24A2:\t\LG
+24A3:\t\LH
+24A4:\t\LI
+24A5:\t\LJ
+24A6:\t\LK
+24A7:\t\LL
+24A8:\t\LM
+24A9:\t\LN
+24AA:\t\LO
+24AB:\t\LP
+24AC:\t\LQ
+24AD:\t\LR
+24AE:\t\LS
+24AF:\t\LT
+24B0:\t\LU
+24B1:\t\LV
+24B2:\t\LW
+24B3:\t\LX
+24B4:\t\LY
+24B5:\t\LZ
+24B6:\c\PA
+24B7:\c\PB
+24B8:\c\PC
+24B9:\c\PD
+24BA:\c\PE
+24BB:\c\PF
+24BC:\c\PG
+24BD:\c\PH
+24BE:\c\PI
+24BF:\c\PJ
+24C0:\c\PK
+24C1:\c\PL
+24C2:\c\PM
+24C3:\c\PN
+24C4:\c\PO
+24C5:\c\PP
+24C6:\c\PQ
+24C7:\c\PR
+24C8:\c\PS
+24C9:\c\PT
+24CA:\c\PU
+24CB:\c\PV
+24CC:\c\PW
+24CD:\c\PX
+24CE:\c\PY
+24CF:\c\PZ
+24D0:\c\LA
+24D1:\c\LB
+24D2:\c\LC
+24D3:\c\LD
+24D4:\c\LE
+24D5:\c\LF
+24D6:\c\LG
+24D7:\c\LH
+24D8:\c\LI
+24D9:\c\LJ
+24DA:\c\LK
+24DB:\c\LL
+24DC:\c\LM
+24DD:\c\LN
+24DE:\c\LO
+24DF:\c\LP
+24E0:\c\LQ
+24E1:\c\LR
+24E2:\c\LS
+24E3:\c\LT
+24E4:\c\LU
+24E5:\c\LV
+24E6:\c\LW
+24E7:\c\LX
+24E8:\c\LY
+24E9:\c\LZ
+24EA:\cDIGIT ZERO
+24EB:NEGATIVE \c\­ELEVEN
+24EC:NEGATIVE \c\­TWELVE
+24ED:NEGATIVE \c\­THIRTEEN
+24EE:NEGATIVE \c\­FOURTEEN
+24EF:NEGATIVE \c\­FIFTEEN
+24F0:NEGATIVE \c\­SIXTEEN
+24F1:NEGATIVE \c\­SEVENTEEN
+24F2:NEGATIVE \c\­E\¼EEN
+24F3:NEGATIVE \c\­NINETEEN
+24F4:NEGATIVE \c\­TWENTY
+24F5:\0 \cDIGIT ONE
+24F6:\0 \cDIGIT TWO
+24F7:\0 \cDIGIT THREE
+24F8:\0 \cDIGIT FOUR
+24F9:\0 \cDIGIT FIVE
+24FA:\0 \cDIGIT SIX
+24FB:\0 \cDIGIT SEVEN
+24FC:\0 \cDIGIT E\¼
+24FD:\0 \cDIGIT NINE
+24FE:\0 \c\­TEN
+2500:\jL\¼ \
+2501:\j\Å \
+2502:\jL\¼ \€
+2503:\j\Å \€
+2504:\jL\¼ TRIPLE DASH \
+2505:\j\Å TRIPLE DASH \
+2506:\jL\¼ TRIPLE DASH \€
+2507:\j\Å TRIPLE DASH \€
+2508:\jL\¼ QUADRUPLE DASH \
+2509:\j\Å QUADRUPLE DASH \
+250A:\jL\¼ QUADRUPLE DASH \€
+250B:\j\Å QUADRUPLE DASH \€
+250C:\jL\¼ \Ë\i\q
+250D:\j\Ë L\¼\i\ù\Å
+250E:\j\Ë \Å\i\ùL\¼
+250F:\j\Å \Ë\i\q
+2510:\jL\¼ \Ë\i\‰
+2511:\j\Ë L\¼\i\‰ \Å
+2512:\j\Ë \Å\i\‰ L\¼
+2513:\j\Å \Ë\i\‰
+2514:\jL\¼ UP\i\q
+2515:\jUP L\¼\i\ù\Å
+2516:\jUP \Å\i\ùL\¼
+2517:\j\Å UP\i\q
+2518:\jL\¼ UP\i\‰
+2519:\jUP L\¼\i\‰ \Å
+251A:\jUP \Å\i\‰ L\¼
+251B:\j\Å UP\i\‰
+251C:\jL\¼ \€\i\q
+251D:\j\€ L\¼\i\ù\Å
+251E:\jUP \Å\i\ù\Ë L\¼
+251F:\j\Ë \Å\i\ùUP L\¼
+2520:\j\€ \Å\i\ùL\¼
+2521:\j\Ë L\¼\i\ùUP \Å
+2522:\jUP L\¼\i\ù\Ë \Å
+2523:\j\Å \€\i\q
+2524:\jL\¼ \€\i\‰
+2525:\j\€ L\¼\i\‰ \Å
+2526:\jUP \Å\i\‰ \Ë L\¼
+2527:\j\Ë \Å\i\‰ UP L\¼
+2528:\j\€ \Å\i\‰ L\¼
+2529:\j\Ë L\¼\i\‰ UP \Å
+252A:\jUP L\¼\i\‰ \Ë \Å
+252B:\j\Å \€\i\‰
+252C:\jL\¼ \Ë\i\
+252D:\j\‰ \Å\i\ù\Ë L\¼
+252E:\j\ù\Å\i\‰ \Ë L\¼
+252F:\j\Ë L\¼\i\ \Å
+2530:\j\Ë \Å\i\ L\¼
+2531:\j\ùL\¼\i\‰ \Ë \Å
+2532:\j\‰ L\¼\i\ù\Ë \Å
+2533:\j\Å \Ë\i\
+2534:\jL\¼ UP\i\
+2535:\j\‰ \Å\i\ùUP L\¼
+2536:\j\ù\Å\i\‰ UP L\¼
+2537:\jUP L\¼\i\ \Å
+2538:\jUP \Å\i\ L\¼
+2539:\j\ùL\¼\i\‰ UP \Å
+253A:\j\‰ L\¼\i\ùUP \Å
+253B:\j\Å UP\i\
+253C:\jL\¼ \€\i\
+253D:\j\‰ \Å\i\ù\€ L\¼
+253E:\j\ù\Å\i\‰ \€ L\¼
+253F:\j\€ L\¼\i\ \Å
+2540:\jUP \Å\i\Ë \ L\¼
+2541:\j\Ë \Å\iUP \ L\¼
+2542:\j\€ \Å\i\ L\¼
+2543:\j\‰ UP \Å\i\ù\Ë L\¼
+2544:\j\ùUP \Å\i\‰ \Ë L\¼
+2545:\j\‰ \Ë \Å\i\ùUP L\¼
+2546:\j\ù\Ë \Å\i\‰ UP L\¼
+2547:\j\Ë L\¼\iUP \ \Å
+2548:\jUP L\¼\i\Ë \ \Å
+2549:\j\ùL\¼\i\‰ \€ \Å
+254A:\j\‰ L\¼\i\ù\€ \Å
+254B:\j\Å \€\i\
+254C:\jL\¼ \0 DASH \
+254D:\j\Å \0 DASH \
+254E:\jL\¼ \0 DASH \€
+254F:\j\Å \0 DASH \€
+2550:\j\0 \
+2551:\j\0 \€
+2552:\j\Ë S\ôLE\i\ù\0
+2553:\j\Ë \0\i\ùS\ôLE
+2554:\j\0 \Ë\i\q
+2555:\j\Ë S\ôLE\i\‰ \0
+2556:\j\Ë \0\i\‰ S\ôLE
+2557:\j\0 \Ë\i\‰
+2558:\jUP S\ôLE\i\ù\0
+2559:\jUP \0\i\ùS\ôLE
+255A:\j\0 UP\i\q
+255B:\jUP S\ôLE\i\‰ \0
+255C:\jUP \0\i\‰ S\ôLE
+255D:\j\0 UP\i\‰
+255E:\j\€ S\ôLE\i\ù\0
+255F:\j\€ \0\i\ùS\ôLE
+2560:\j\0 \€\i\q
+2561:\j\€ S\ôLE\i\‰ \0
+2562:\j\€ \0\i\‰ S\ôLE
+2563:\j\0 \€\i\‰
+2564:\j\Ë S\ôLE\i\ \0
+2565:\j\Ë \0\i\ S\ôLE
+2566:\j\0 \Ë\i\
+2567:\jUP S\ôLE\i\ \0
+2568:\jUP \0\i\ S\ôLE
+2569:\j\0 UP\i\
+256A:\j\€ S\ôLE\i\ \0
+256B:\j\€ \0\i\ S\ôLE
+256C:\j\0 \€\i\
+256D:\jL\¼ ARC \Ë\i\q
+256E:\jL\¼ ARC \Ë\i\‰
+256F:\jL\¼ ARC UP\i\‰
+2570:\jL\¼ ARC UP\i\q
+2571:\jL\¼ DIAGONAL \÷\ùTO \ï\‰
+2572:\jL\¼ DIAGONAL \÷\‰ TO \ï\q
+2573:\jL\¼ DIAGONAL CROSS
+2574:\jL\¼ \‰
+2575:\jL\¼ UP
+2576:\jL\¼ \q
+2577:\jL\¼ \Ë
+2578:\j\Å \‰
+2579:\j\Å UP
+257A:\j\Å \q
+257B:\j\Å \Ë
+257C:\jL\¼ \‰\i\Å \q
+257D:\jL\¼ UP\i\Å \Ë
+257E:\j\Å \‰\iL\¼ \q
+257F:\j\Å UP\iL\¼ \Ë
+2580:\÷HALF BLOCK
+2581:\ïONE E\¼H BLOCK
+2582:\ïONE QUARTER BLOCK
+2583:\ïTHREE E\¼HS BLOCK
+2584:\ïHALF BLOCK
+2585:\ïFIVE E\¼HS BLOCK
+2586:\ïTHREE QUARTERS BLOCK
+2587:\ïSEVEN E\¼HS BLOCK
+2588:FULL BLOCK
+2589:\‰ SEVEN E\¼HS BLOCK
+258A:\‰ THREE QUARTERS BLOCK
+258B:\‰ FIVE E\¼HS BLOCK
+258C:\‰ HALF BLOCK
+258D:\‰ THREE E\¼HS BLOCK
+258E:\‰ ONE QUARTER BLOCK
+258F:\‰ ONE E\¼H BLOCK
+2590:\ùHALF BLOCK
+2591:L\¼ SHADE
+2592:MEDIUM SHADE
+2593:DARK SHADE
+2594:\÷ONE E\¼H BLOCK
+2595:\ùONE E\¼H BLOCK
+2596:QUADRANT \ï\‰
+2597:QUADRANT \ï\q
+2598:QUADRANT \÷\‰
+2599:QUADRANT \÷\‰\i\ï\‰\i\ï\q
+259A:QUADRANT \÷\‰\i\ï\q
+259B:QUADRANT \÷\‰\i\÷\ùAND \ï\‰
+259C:QUADRANT \÷\‰\i\÷\ùAND \ï\q
+259D:QUADRANT \÷\q
+259E:QUADRANT \÷\ùAND \ï\‰
+259F:QUADRANT \÷\ùAND \ï\‰\i\ï\q
+25A0:\¬ \ý
+25A1:\¦\ý
+25A2:\¦\rWITH ROUND\ÂCORNERS
+25A3:\¦\rCONTAIN\ô \¬\Ç\ý
+25A4:\rWITH \ FILL
+25A5:\rWITH \€ FILL
+25A6:\rWITH ORTHOGONAL CROSSHATCH FILL
+25A7:\rWITH \÷\‰ TO \ï\ùFILL
+25A8:\rWITH \÷\ùTO \ï\‰ FILL
+25A9:\rWITH DIAGONAL CROSSHATCH FILL
+25AA:\¬\Ç\ý
+25AB:WHITE\Ç\ý
+25AC:\¬ RECTANGLE
+25AD:\¦RECTANGLE
+25AE:\¬ \€ RECTANGLE
+25AF:\¦\€ RECTANGLE
+25B0:\¬ PARALLELOGRAM
+25B1:\¦PARALLELOGRAM
+25B2:\¬ UP-\Ä\¾
+25B3:\¦UP-\Ä\¾
+25B4:\¬ UP-\Ä\§\¾
+25B5:\¦UP-\Ä\§\¾
+25B6:\¬ \q-\Ä\¾
+25B7:\¦\q-\Ä\¾
+25B8:\¬ \q-\Ä\§\¾
+25B9:\¦\q-\Ä\§\¾
+25BA:\¬ \q-\ÄPOINTER
+25BB:\¦\q-\ÄPOINTER
+25BC:\¬ \Ë-\Ä\¾
+25BD:\¦\Ë-\Ä\¾
+25BE:\¬ \Ë-\Ä\§\¾
+25BF:\¦\Ë-\Ä\§\¾
+25C0:\¬ \‰-\Ä\¾
+25C1:\¦\‰-\Ä\¾
+25C2:\¬ \‰-\Ä\§\¾
+25C3:\¦\‰-\Ä\§\¾
+25C4:\¬ \‰-\ÄPOINTER
+25C5:\¦\‰-\ÄPOINTER
+25C6:\¬ DIAMOND
+25C7:\¦DIAMOND
+25C8:\¦DIAMOND CONTAIN\ô \¬\ÇDIAMOND
+25C9:FISHEYE
+25CA:LOZENGE
+25CB:\¦\Ð
+25CC:DOTT\Â\Ð
+25CD:\Ð\H\€ FILL
+25CE:BULLSEYE
+25CF:\¬ \Ð
+25D0:\Ð\H\‰ HALF \¬
+25D1:\Ð\H\ùHALF \¬
+25D2:\Ð\H\ïHALF \¬
+25D3:\Ð\H\÷HALF \¬
+25D4:\Ð\H\÷\ùQUADRANT \¬
+25D5:\Ð\HALL BUT \÷\‰ QUADRANT \¬
+25D6:\‰ HALF \¬ \Ð
+25D7:\ùHALF \¬ \Ð
+25D8:INVERSE BULLET
+25D9:INVERSE \¦\Ð
+25DA:\÷HALF INVERSE \¦\Ð
+25DB:\ïHALF INVERSE \¦\Ð
+25DC:\÷\‰ QUADRANT CIRCULAR ARC
+25DD:\÷\ùQUADRANT CIRCULAR ARC
+25DE:\ï\ùQUADRANT CIRCULAR ARC
+25DF:\ï\‰ QUADRANT CIRCULAR ARC
+25E0:\÷HALF \Ð
+25E1:\ïHALF \Ð
+25E2:\¬ \ï\ù\¾
+25E3:\¬ \ï\‰ \¾
+25E4:\¬ \÷\‰ \¾
+25E5:\¬ \÷\ù\¾
+25E6:\¦BULLET
+25E7:\rWITH \‰ HALF \¬
+25E8:\rWITH \ùHALF \¬
+25E9:\rWITH \÷\‰ DIAGONAL HALF \¬
+25EA:\rWITH \ï\ùDIAGONAL HALF \¬
+25EB:\¦\rWITH \€ BISECT\ô \ä
+25EC:\¦UP-\Ä\¾\³
+25ED:UP-\Ä\¾\H\‰ HALF \¬
+25EE:UP-\Ä\¾\H\ùHALF \¬
+25EF:LARGE \Ð
+25F0:\¦\rWITH \÷\‰ QUADRANT
+25F1:\¦\rWITH \ï\‰ QUADRANT
+25F2:\¦\rWITH \ï\ùQUADRANT
+25F3:\¦\rWITH \÷\ùQUADRANT
+25F4:\¦\Ð\H\÷\‰ QUADRANT
+25F5:\¦\Ð\H\ï\‰ QUADRANT
+25F6:\¦\Ð\H\ï\ùQUADRANT
+25F7:\¦\Ð\H\÷\ùQUADRANT
+25F8:\÷\‰ \¾
+25F9:\÷\ù\¾
+25FA:\ï\‰ \¾
+25FB:\¦MEDIUM \ý
+25FC:\¬ MEDIUM \ý
+25FD:\¦MEDIUM\Ç\ý
+25FE:\¬ MEDIUM\Ç\ý
+25FF:\ï\ù\¾
+2600:\¬ SUN\HRAYS
+2601:CLOUD
+2602:UMBRELLA
+2603:SNOWMAN
+2604:COMET
+2605:\¬ STAR
+2606:\¦STAR
+2607:L\¼N\ô
+2608:THUNDERSTORM
+2609:SUN
+260A:ASCEND\ô NODE
+260B:DESCEND\ô NODE
+260C:CONJUNCTION
+260D:OPPOSITION
+260E:\¬ TELEPHONE
+260F:\¦TELEPHONE
+2610:BALLOT BOX
+2611:BALLOT BOX\HCHECK
+2612:BALLOT BOX\HX
+2613:SALTIRE
+2616:\¦SHOGI PIECE
+2617:\¬ SHOGI PIECE
+2619:\öROTAT\ÂFLORAL HEART BULLET
+261A:\¬ \‰ \ÄINDEX
+261B:\¬ \ù\ÄINDEX
+261C:\¦\‰ \ÄINDEX
+261D:\¦UP \ÄINDEX
+261E:\¦\ù\ÄINDEX
+261F:\¦\Ë \ÄINDEX
+2620:SKULL\iCROSSBONES
+2621:CAUTION\‚
+2622:RADIOACTIVE\‚
+2623:BIOHAZARD\‚
+2624:CADUCEUS
+2625:ANKH
+2626:ORTHODOX CROSS
+2627:CHI RHO
+2628:CROSS OF LORRAINE
+2629:CROSS OF JERUSALEM
+262A:STAR\iCRESCENT
+262B:FARSI \
+262C:ADI SHAKTI
+262D:HAMMER\iSICKLE
+262E:PEACE \
+262F:YIN YANG
+2630:TRIGRAM FOR HEAVEN
+2631:TRIGRAM FOR LAKE
+2632:TRIGRAM FOR FIRE
+2633:TRIGRAM FOR THUNDER
+2634:TRIGRAM FOR WIND
+2635:TRIGRAM FOR WATER
+2636:TRIGRAM FOR MOUNTAIN
+2637:TRIGRAM FOR EARTH
+2638:WHEEL OF DHARMA
+2639:\¦FROWN\ô FACE
+263A:\¦SMIL\ô FACE
+263B:\¬ SMIL\ô FACE
+263C:\¦SUN\HRAYS
+263D:FIRST QUARTER MOON
+263E:LAST QUARTER MOON
+263F:MERCURY
+2640:FEMALE\‚
+2641:EARTH
+2642:MALE\‚
+2643:JUPITER
+2644:SATURN
+2645:URANUS
+2646:NEPTUNE
+2647:PLUTO
+2648:ARIES
+2649:TAURUS
+264A:GEMINI
+264B:CANCER
+264C:LEO
+264D:VIRGO
+264E:LIBRA
+264F:SCORPIUS
+2650:SAGITTARIUS
+2651:CAPRICORN
+2652:AQUARIUS
+2653:PISCES
+2654:\¦CHESS K\ô
+2655:\¦CHESS QUEEN
+2656:\¦CHESS ROOK
+2657:\¦CHESS BISHOP
+2658:\¦CHESS KN\¼
+2659:\¦CHESS PAWN
+265A:\¬ CHESS K\ô
+265B:\¬ CHESS QUEEN
+265C:\¬ CHESS ROOK
+265D:\¬ CHESS BISHOP
+265E:\¬ CHESS KN\¼
+265F:\¬ CHESS PAWN
+2660:\¬ SPADE SUIT
+2661:\¦HEART SUIT
+2662:\¦DIAMOND SUIT
+2663:\¬ CLUB SUIT
+2664:\¦SPADE SUIT
+2665:\¬ HEART SUIT
+2666:\¬ DIAMOND SUIT
+2667:\¦CLUB SUIT
+2668:HOT SPR\ôS
+2669:QUARTER NOTE
+266A:E\¼H NOTE
+266B:BEAM\ÂE\¼H NOTES
+266C:BEAM\ÂSIXTEENTH NOTES
+266D:MUSIC FLAT\‚
+266E:MUSIC NATURAL\‚
+266F:MUSIC SHARP\‚
+2670:WEST \Ó CROSS
+2671:EAST \Ó CROSS
+2672:UNIVERSAL RECYCL\ô \
+2673:RECYCL\ô \ñTYPE-1 PLASTICS
+2674:RECYCL\ô \ñTYPE-2 PLASTICS
+2675:RECYCL\ô \ñTYPE-3 PLASTICS
+2676:RECYCL\ô \ñTYPE-4 PLASTICS
+2677:RECYCL\ô \ñTYPE-5 PLASTICS
+2678:RECYCL\ô \ñTYPE-6 PLASTICS
+2679:RECYCL\ô \ñTYPE-7 PLASTICS
+267A:RECYCL\ô \ñGENERIC MATERIALS
+267B:\¬ UNIVERSAL RECYCL\ô \
+267C:RECYCL\ÂPAPER \
+267D:PARTIALLY-RECYCL\ÂPAPER \
+2680:DIE FACE-1
+2681:DIE FACE-2
+2682:DIE FACE-3
+2683:DIE FACE-4
+2684:DIE FACE-5
+2685:DIE FACE-6
+2686:\¦\Ð\³ \q
+2687:\¦\Ð\HTWO DOTS
+2688:\¬ \Ð\H\¦DOT \q
+2689:\¬ \Ð\HTWO \¦DOTS
+2701:\÷BLADE SCISSORS
+2702:\¬ SCISSORS
+2703:\ïBLADE SCISSORS
+2704:\¦SCISSORS
+2706:TELEPHONE LOC\”\‚
+2707:TAPE DRIVE
+2708:AIRPLANE
+2709:ENVELOPE
+270C:VICTORY HAND
+270D:WRIT\ô HAND
+270E:\ï\ùPENCIL
+270F:PENCIL
+2710:\÷\ùPENCIL
+2711:\¦NIB
+2712:\¬ NIB
+2713:CHECK\¥
+2714:\Å CHECK\¥
+2715:MULTIPLIC\” X
+2716:\Å MULTIPLIC\” X
+2717:BALLOT X
+2718:\Å BALLOT X
+2719:OUT\äD GREEK CROSS
+271A:\Å GREEK CROSS
+271B:OPEN CENTRE CROSS
+271C:\Å OPEN CENTRE CROSS
+271D:LATIN CROSS
+271E:SHADOW\Â\¦LATIN CROSS
+271F:OUT\äD LATIN CROSS
+2720:MALTESE CROSS
+2721:STAR OF DAVID
+2722:FOUR TEARDROP-SPOK\ÂASTERISK
+2723:FOUR BALLOON-SPOK\ÂASTERISK
+2724:\Å FOUR BALLOON-SPOK\ÂASTERISK
+2725:FOUR CLUB-SPOK\ÂASTERISK
+2726:\¬ FOUR POINT\ÂSTAR
+2727:\¦FOUR POINT\ÂSTAR
+2729:STRESS OUT\äD \¦STAR
+272A:\c\¦STAR
+272B:OPEN CENTRE \¬ STAR
+272C:\¬ CENTRE \¦STAR
+272D:OUT\äD \¬ STAR
+272E:\Å OUT\äD \¬ STAR
+272F:PINWHEEL STAR
+2730:SHADOW\Â\¦STAR
+2731:\Å ASTERISK
+2732:OPEN CENTRE ASTERISK
+2733:E\¼ SPOK\ÂASTERISK
+2734:E\¼ POINT\Â\¬ STAR
+2735:E\¼ POINT\ÂPINWHEEL STAR
+2736:SIX POINT\Â\¬ STAR
+2737:E\¼ POINT\ÂRECTI\äAR \¬ STAR
+2738:\Å E\¼ POINT\ÂRECTI\äAR \¬ STAR
+2739:TWELVE POINT\Â\¬ STAR
+273A:SIXTEEN POINT\ÂASTERISK
+273B:TEARDROP-SPOK\ÂASTERISK
+273C:OPEN CENTRE TEARDROP-SPOK\ÂASTERISK
+273D:\Å TEARDROP-SPOK\ÂASTERISK
+273E:SIX PETALL\Â\¬\i\¦FLORETTE
+273F:\¬ FLORETTE
+2740:\¦FLORETTE
+2741:E\¼ PETALL\ÂOUT\äD \¬ FLORETTE
+2742:\cOPEN CENTRE E\¼ POINT\ÂSTAR
+2743:\Å TEARDROP-SPOK\ÂPINWHEEL ASTERISK
+2744:SNOWFLAKE
+2745:T\¼ TRIFOLIATE SNOWFLAKE
+2746:\Å CHEVRON SNOWFLAKE
+2747:SPARKLE
+2748:\Å SPARKLE
+2749:BALLOON-SPOK\ÂASTERISK
+274A:E\¼ TEARDROP-SPOK\ÂPROPELLER ASTERISK
+274B:\Å E\¼ TEARDROP-SPOK\ÂPROPELLER ASTERISK
+274D:SHADOW\Â\¦\Ð
+274F:\ï\ùDROP-SHADOW\Â\¦\ý
+2750:\÷\ùDROP-SHADOW\Â\¦\ý
+2751:\ï\ùSHADOW\Â\¦\ý
+2752:\÷\ùSHADOW\Â\¦\ý
+2756:\¬ DIAMOND MINUS \¦X
+2758:L\¼ \€\ì
+2759:MEDIUM \€\ì
+275A:\Å \€\ì
+275B:\Å S\ôLE TURN\ÂCOMMA QUOT\”\¥ ORNAMENT
+275C:\Å S\ôLE COMMA QUOT\”\¥ ORNAMENT
+275D:\Å \0 TURN\ÂCOMMA QUOT\”\¥ ORNAMENT
+275E:\Å \0 COMMA QUOT\”\¥ ORNAMENT
+2761:CURV\ÂSTEM PARAGRAPH\‚ ORNAMENT
+2762:\Å EXCLAM\”\¥ ORNAMENT
+2763:\Å HEART EXCLAM\”\¥ ORNAMENT
+2764:\Å \¬ HEART
+2765:ROTAT\Â\Å \¬ HEART BULLET
+2766:FLORAL HEART
+2767:ROTAT\ÂFLORAL HEART BULLET
+2768:MEDIUM \‰ \ÑS ORNAMENT
+2769:MEDIUM \ù\ÑS ORNAMENT
+276A:MEDIUM FLATTEN\Â\‰ \ÑS ORNAMENT
+276B:MEDIUM FLATTEN\Â\ù\ÑS ORNAMENT
+276C:MEDIUM \‰-\ÄANGLE \– ORNAMENT
+276D:MEDIUM \q-\ÄANGLE \– ORNAMENT
+276E:\Å \‰-\ÄANGLE QUOT\”\¥ ORNAMENT
+276F:\Å \q-\ÄANGLE QUOT\”\¥ ORNAMENT
+2770:\Å \‰-\ÄANGLE \– ORNAMENT
+2771:\Å \q-\ÄANGLE \– ORNAMENT
+2772:L\¼ \‰ TORTOISE SHELL \– ORNAMENT
+2773:L\¼ \ùTORTOISE SHELL \– ORNAMENT
+2774:MEDIUM \‰ CURLY \– ORNAMENT
+2775:MEDIUM \ùCURLY \– ORNAMENT
+2776:\ÌDIGIT ONE
+2777:\ÌDIGIT TWO
+2778:\ÌDIGIT THREE
+2779:\ÌDIGIT FOUR
+277A:\ÌDIGIT FIVE
+277B:\ÌDIGIT SIX
+277C:\ÌDIGIT SEVEN
+277D:\ÌDIGIT E\¼
+277E:\ÌDIGIT NINE
+277F:\Ì\­TEN
+2780:D\ôBAT \cSANS-SERIF\hONE
+2781:D\ôBAT \cSANS-SERIF\hTWO
+2782:D\ôBAT \cSANS-SERIF\hTHREE
+2783:D\ôBAT \cSANS-SERIF\hFOUR
+2784:D\ôBAT \cSANS-SERIF\hFIVE
+2785:D\ôBAT \cSANS-SERIF\hSIX
+2786:D\ôBAT \cSANS-SERIF\hSEVEN
+2787:D\ôBAT \cSANS-SERIF\hE\¼
+2788:D\ôBAT \cSANS-SERIF\hNINE
+2789:D\ôBAT \cSANS-SERIF \­TEN
+278A:\ÌSANS-SERIF\hONE
+278B:\ÌSANS-SERIF\hTWO
+278C:\ÌSANS-SERIF\hTHREE
+278D:\ÌSANS-SERIF\hFOUR
+278E:\ÌSANS-SERIF\hFIVE
+278F:\ÌSANS-SERIF\hSIX
+2790:\ÌSANS-SERIF\hSEVEN
+2791:\ÌSANS-SERIF\hE\¼
+2792:\ÌSANS-SERIF\hNINE
+2793:\ÌSANS-SERIF \­TEN
+2794:\Å WIDE-HEAD\Â\Ù
+2798:\Å SOUTH EAST\u
+2799:\Å \Ù
+279A:\Å NORTH EAST\u
+279B:DRAFT\ô POINT \Ù
+279C:\Å ROUND-TIPP\Â\Ù
+279D:\¾-HEAD\Â\Ù
+279E:\Å \¾-HEAD\Â\Ù
+279F:DASH\Â\¾-HEAD\Â\Ù
+27A0:\Å DASH\Â\¾-HEAD\Â\Ù
+27A1:\¬ \Ù
+27A2:THREE-D TOP-L\¼\Â\ÙHEAD
+27A3:THREE-D BOTTOM-L\¼\Â\ÙHEAD
+27A4:\¬ \ÙHEAD
+27A5:\Å \¬ CURV\Â\Ë\Š\i\Ù
+27A6:\Å \¬ CURV\ÂUP\Š\i\Ù
+27A7:SQUAT \¬ \Ù
+27A8:\Å CONCAVE-POINT\Â\¬ \Ù
+27A9:\q-SHAD\Â\¦\Ù
+27AA:\‰-SHAD\Â\¦\Ù
+27AB:BACK-TILT\ÂSHADOW\Â\¦\Ù
+27AC:FRONT-TILT\ÂSHADOW\Â\¦\Ù
+27AD:\Å \ï\q-SHADOW\Â\¦\Ù
+27AE:\Å \÷\q-SHADOW\Â\¦\Ù
+27AF:NOTCH\Â\ï\q-SHADOW\Â\¦\Ù
+27B1:NOTCH\Â\÷\q-SHADOW\Â\¦\Ù
+27B2:\c\Å \¦\Ù
+27B3:WHITE-FEATHER\Â\Ù
+27B4:\¬-FEATHER\ÂSOUTH EAST\u
+27B5:\¬-FEATHER\Â\Ù
+27B6:\¬-FEATHER\ÂNORTH EAST\u
+27B7:\Å \¬-FEATHER\ÂSOUTH EAST\u
+27B8:\Å \¬-FEATHER\Â\Ù
+27B9:\Å \¬-FEATHER\ÂNORTH EAST\u
+27BA:TEARDROP-BARB\Â\Ù
+27BB:\Å TEARDROP-SHANK\Â\Ù
+27BC:WEDGE-TAIL\Â\Ù
+27BD:\Å WEDGE-TAIL\Â\Ù
+27BE:OPEN-OUT\äD \Ù
+27D0:\¦DIAMOND\HCENTR\ÂDOT
+27D1:AND\³
+27D2:ELEMENT OF OPEN\ô UP\Š
+27D3:\ï\ùCORNER\³
+27D4:\÷\‰ CORNER\³
+27D5:\‰ OUTER JOIN
+27D6:\ùOUTER JOIN
+27D7:FULL OUTER JOIN
+27D8:LARGE UP TACK
+27D9:LARGE \Ë TACK
+27DA:\‰\i\ù\0 TURNSTILE
+27DB:\‰\i\ùTACK
+27DC:\‰ MULTIMAP
+27DD:LONG \ùTACK
+27DE:LONG \‰ TACK
+27DF:UP TACK\H\Ð\p
+27E0:LOZENGE DIVID\ÂBY \ RULE
+27E1:\¦CONCAVE-SID\ÂDIAMOND
+27E2:\¦CONCAVE-SID\ÂDIAMOND\H\‰\Š TICK
+27E3:\¦CONCAVE-SID\ÂDIAMOND\H\q\Š TICK
+27E4:\¦\rWITH \‰\Š TICK
+27E5:\¦\rWITH \q\Š TICK
+27E6:\E\‰ \¦\r\–
+27E7:\E\ù\¦\r\–
+27E8:\E\‰ ANGLE \–
+27E9:\E\ùANGLE \–
+27EA:\E\‰ \0 ANGLE \–
+27EB:\E\ù\0 ANGLE \–
+27F0:UP\Š QUADRUPLE\u
+27F1:\Ë\Š QUADRUPLE\u
+27F2:ANTICLOCKWISE GAPP\Â\Ð\u
+27F3:CLOCKWISE GAPP\Â\Ð\u
+27F4:\q\u\H\cPLUS
+27F5:LONG \‰\Š\u
+27F6:LONG \Ù
+27F7:LONG \‰ \q\u
+27F8:LONG \‰\Š \0\u
+27F9:LONG \q\Š \0\u
+27FA:LONG \‰ \ù\0\u
+27FB:LONG \‰\Š\u FROM\ì
+27FC:LONG \Ù FROM\ì
+27FD:LONG \‰\Š \0\u FROM\ì
+27FE:LONG \q\Š \0\u FROM\ì
+27FF:LONG \q\Š SQUIGGLE\u
+2800:BRAILLE PATTERN BLANK
+2801:\M1
+2802:\M2
+2803:\M12
+2804:\M3
+2805:\M13
+2806:\M23
+2807:\M123
+2808:\M4
+2809:\M14
+280A:\M24
+280B:\M124
+280C:\M34
+280D:\M134
+280E:\M234
+280F:\M1234
+2810:\M5
+2811:\M15
+2812:\M25
+2813:\M125
+2814:\M35
+2815:\M135
+2816:\M235
+2817:\M1235
+2818:\M45
+2819:\M145
+281A:\M245
+281B:\M1245
+281C:\M345
+281D:\M1345
+281E:\M2345
+281F:\M12345
+2820:\M6
+2821:\M16
+2822:\M26
+2823:\M126
+2824:\M36
+2825:\M136
+2826:\M236
+2827:\M1236
+2828:\M46
+2829:\M146
+282A:\M246
+282B:\M1246
+282C:\M346
+282D:\M1346
+282E:\M2346
+282F:\M12346
+2830:\M56
+2831:\M156
+2832:\M256
+2833:\M1256
+2834:\M356
+2835:\M1356
+2836:\M2356
+2837:\M12356
+2838:\M456
+2839:\M1456
+283A:\M2456
+283B:\M12456
+283C:\M3456
+283D:\M13456
+283E:\M23456
+283F:\M123456
+2840:\M7
+2841:\M17
+2842:\M27
+2843:\M127
+2844:\M37
+2845:\M137
+2846:\M237
+2847:\M1237
+2848:\M47
+2849:\M147
+284A:\M247
+284B:\M1247
+284C:\M347
+284D:\M1347
+284E:\M2347
+284F:\M12347
+2850:\M57
+2851:\M157
+2852:\M257
+2853:\M1257
+2854:\M357
+2855:\M1357
+2856:\M2357
+2857:\M12357
+2858:\M457
+2859:\M1457
+285A:\M2457
+285B:\M12457
+285C:\M3457
+285D:\M13457
+285E:\M23457
+285F:\M123457
+2860:\M67
+2861:\M167
+2862:\M267
+2863:\M1267
+2864:\M367
+2865:\M1367
+2866:\M2367
+2867:\M12367
+2868:\M467
+2869:\M1467
+286A:\M2467
+286B:\M12467
+286C:\M3467
+286D:\M13467
+286E:\M23467
+286F:\M123467
+2870:\M567
+2871:\M1567
+2872:\M2567
+2873:\M12567
+2874:\M3567
+2875:\M13567
+2876:\M23567
+2877:\M123567
+2878:\M4567
+2879:\M14567
+287A:\M24567
+287B:\M124567
+287C:\M34567
+287D:\M134567
+287E:\M234567
+287F:\M1234567
+2880:\M8
+2881:\M18
+2882:\M28
+2883:\M128
+2884:\M38
+2885:\M138
+2886:\M238
+2887:\M1238
+2888:\M48
+2889:\M148
+288A:\M248
+288B:\M1248
+288C:\M348
+288D:\M1348
+288E:\M2348
+288F:\M12348
+2890:\M58
+2891:\M158
+2892:\M258
+2893:\M1258
+2894:\M358
+2895:\M1358
+2896:\M2358
+2897:\M12358
+2898:\M458
+2899:\M1458
+289A:\M2458
+289B:\M12458
+289C:\M3458
+289D:\M13458
+289E:\M23458
+289F:\M123458
+28A0:\M68
+28A1:\M168
+28A2:\M268
+28A3:\M1268
+28A4:\M368
+28A5:\M1368
+28A6:\M2368
+28A7:\M12368
+28A8:\M468
+28A9:\M1468
+28AA:\M2468
+28AB:\M12468
+28AC:\M3468
+28AD:\M13468
+28AE:\M23468
+28AF:\M123468
+28B0:\M568
+28B1:\M1568
+28B2:\M2568
+28B3:\M12568
+28B4:\M3568
+28B5:\M13568
+28B6:\M23568
+28B7:\M123568
+28B8:\M4568
+28B9:\M14568
+28BA:\M24568
+28BB:\M124568
+28BC:\M34568
+28BD:\M134568
+28BE:\M234568
+28BF:\M1234568
+28C0:\M78
+28C1:\M178
+28C2:\M278
+28C3:\M1278
+28C4:\M378
+28C5:\M1378
+28C6:\M2378
+28C7:\M12378
+28C8:\M478
+28C9:\M1478
+28CA:\M2478
+28CB:\M12478
+28CC:\M3478
+28CD:\M13478
+28CE:\M23478
+28CF:\M123478
+28D0:\M578
+28D1:\M1578
+28D2:\M2578
+28D3:\M12578
+28D4:\M3578
+28D5:\M13578
+28D6:\M23578
+28D7:\M123578
+28D8:\M4578
+28D9:\M14578
+28DA:\M24578
+28DB:\M124578
+28DC:\M34578
+28DD:\M134578
+28DE:\M234578
+28DF:\M1234578
+28E0:\M678
+28E1:\M1678
+28E2:\M2678
+28E3:\M12678
+28E4:\M3678
+28E5:\M13678
+28E6:\M23678
+28E7:\M123678
+28E8:\M4678
+28E9:\M14678
+28EA:\M24678
+28EB:\M124678
+28EC:\M34678
+28ED:\M134678
+28EE:\M234678
+28EF:\M1234678
+28F0:\M5678
+28F1:\M15678
+28F2:\M25678
+28F3:\M125678
+28F4:\M35678
+28F5:\M135678
+28F6:\M235678
+28F7:\M1235678
+28F8:\M45678
+28F9:\M145678
+28FA:\M245678
+28FB:\M1245678
+28FC:\M345678
+28FD:\M1345678
+28FE:\M2345678
+28FF:\M12345678
+2900:\q\Š TWO-HEADED\u\H\€ \Á
+2901:\q\Š TWO-HEADED\u\H\0 \€ \Á
+2902:\‰\Š \0\u\H\€ \Á
+2903:\q\Š \0\u\H\€ \Á
+2904:\‰ \ù\0\u\H\€ \Á
+2905:\q\Š TWO-HEADED\u FROM\ì
+2906:\‰\Š \0\u FROM\ì
+2907:\q\Š \0\u FROM\ì
+2908:\Ë\Š\u\H\ \Á
+2909:UP\Š\u\H\ \Á
+290A:UP\Š TRIPLE\u
+290B:\Ë\Š TRIPLE\u
+290C:\‰\Š \0 DASH\u
+290D:\q\Š \0 DASH\u
+290E:\‰\Š TRIPLE DASH\u
+290F:\q\Š TRIPLE DASH\u
+2910:\q\Š TWO-HEAD\ÂTRIPLE DASH\u
+2911:\Ù\³T\ÂSTEM
+2912:UP\Š\u TO\ì
+2913:\Ë\Š\u TO\ì
+2914:\Ù\HTAIL\H\€ \Á
+2915:\Ù\HTAIL\H\0 \€ \Á
+2916:\q\Š TWO-HEADED\u\HTAIL
+2917:\q\Š TWO-HEADED\u\HTAIL\H\€ \Á
+2918:\q\Š TWO-HEADED\u\HTAIL\H\0 \€ \Á
+2919:\‰\Š\u-TAIL
+291A:\Ù-TAIL
+291B:\‰\Š \0\u-TAIL
+291C:\q\Š \0\u-TAIL
+291D:\‰\Š\u TO \¬ DIAMOND
+291E:\Ù TO \¬ DIAMOND
+291F:\‰\Š\u FROM\ì TO \¬ DIAMOND
+2920:\Ù FROM\ì TO \¬ DIAMOND
+2921:NORTH WEST\iSOUTH EAST\u
+2922:NORTH EAST\iSOUTH WEST\u
+2923:NORTH WEST\u\í
+2924:NORTH EAST\u\í
+2925:SOUTH EAST\u\í
+2926:SOUTH WEST\u\í
+2927:NORTH WEST\u\iNORTH EAST\u
+2928:NORTH EAST\u\iSOUTH EAST\u
+2929:SOUTH EAST\u\iSOUTH WEST\u
+292A:SOUTH WEST\u\iNORTH WEST\u
+292B:RIS\ô DIAGONAL CROSS\ô FALL\ô DIAGONAL
+292C:FALL\ô DIAGONAL CROSS\ô RIS\ô DIAGONAL
+292D:SOUTH EAST\u CROSS\ô NORTH EAST\u
+292E:NORTH EAST\u CROSS\ô SOUTH EAST\u
+292F:FALL\ô DIAGONAL CROSS\ô NORTH EAST\u
+2930:RIS\ô DIAGONAL CROSS\ô SOUTH EAST\u
+2931:NORTH EAST\u CROSS\ô NORTH WEST\u
+2932:NORTH WEST\u CROSS\ô NORTH EAST\u
+2933:WAVE\u \ÄDIRECTLY \q
+2934:ARROW \Ä\q\Š THEN CURV\ô UP\Š
+2935:ARROW \Ä\q\Š THEN CURV\ô \Ë\Š
+2936:ARROW \Ä\Ë\Š THEN CURV\ô \‰\Š
+2937:ARROW \Ä\Ë\Š THEN CURV\ô \q\Š
+2938:\q-SIDE ARC CLOCKWISE\u
+2939:\‰-SIDE ARC ANTICLOCKWISE\u
+293A:TOP ARC ANTICLOCKWISE\u
+293B:BOTTOM ARC ANTICLOCKWISE\u
+293C:TOP ARC CLOCKWISE\u\HMINUS
+293D:TOP ARC ANTICLOCKWISE\u\HPLUS
+293E:\ï\ùSEMICIRCULAR CLOCKWISE\u
+293F:\ï\‰ SEMICIRCULAR ANTICLOCKWISE\u
+2940:ANTICLOCKWISE CLOS\Â\Ð\u
+2941:CLOCKWISE CLOS\Â\Ð\u
+2942:\Ù\p SHORT \‰\Š\u
+2943:\‰\Š\u\p SHORT \Ù
+2944:SHORT \Ù\p \‰\Š\u
+2945:\Ù\HPLUS\…
+2946:\‰\Š\u\HPLUS\…
+2947:\Ù THROUGH X
+2948:\‰ \q\u THROUGH\Ç\Ð
+2949:UP\Š TWO-HEADED\u FROM\Ç\Ð
+294A:\‰\ìB UP \ùBARB \Ë HARPOON
+294B:\‰\ìB \Ë \ùBARB UP HARPOON
+294C:UP\ìB \ù\Ë\ìB \‰ HARPOON
+294D:UP\ìB \‰ \Ë\ìB \ùHARPOON
+294E:\‰\ìB UP \ùBARB UP HARPOON
+294F:UP\ìB \ù\Ë\ìB \ùHARPOON
+2950:\‰\ìB \Ë \ùBARB \Ë HARPOON
+2951:UP\ìB \‰ \Ë\ìB \‰ HARPOON
+2952:\‰\ƒUP TO\ì
+2953:\q\ƒUP TO\ì
+2954:UP\ƒ\ùTO\ì
+2955:\Ë\ƒ\ùTO\ì
+2956:\‰\ƒ\Ë TO\ì
+2957:\q\ƒ\Ë TO\ì
+2958:UP\ƒ\‰ TO\ì
+2959:\Ë\ƒ\‰ TO\ì
+295A:\‰\ƒUP FROM\ì
+295B:\q\ƒUP FROM\ì
+295C:UP\ƒ\ùFROM\ì
+295D:\Ë\ƒ\ùFROM\ì
+295E:\‰\ƒ\Ë FROM\ì
+295F:\q\ƒ\Ë FROM\ì
+2960:UP\ƒ\‰ FROM\ì
+2961:\Ë\ƒ\‰ FROM\ì
+2962:\‰\ƒUP\p \‰\ƒ\Ë
+2963:UP\ƒ\‰ BESIDE UP\ƒ\q
+2964:\q\ƒUP\p \q\ƒ\Ë
+2965:\Ë\ƒ\‰ BESIDE \Ë\ƒ\q
+2966:\‰\ƒUP\p \q\ƒUP
+2967:\‰\ƒ\Ë\p \q\ƒ\Ë
+2968:\q\ƒUP\p \‰\ƒUP
+2969:\q\ƒ\Ë\p \‰\ƒ\Ë
+296A:\‰\ƒUP\p LONG DASH
+296B:\‰\ƒ\Ë\… LONG DASH
+296C:\q\ƒUP\p LONG DASH
+296D:\q\ƒ\Ë\… LONG DASH
+296E:UP\ƒ\‰ BESIDE \Ë\ƒ\q
+296F:\Ë\ƒ\‰ BESIDE UP\ƒ\q
+2970:\ù\0\u\HROUND\ÂHEAD
+2971:EQUALS\‚\p \Ù
+2972:\æ\Ú\p \Ù
+2973:\‰\Š\u\p \æ\Ú
+2974:\Ù\p \æ\Ú
+2975:\Ù\p ALMOST\‘
+2976:\µ\p \‰\Š\u
+2977:\‰\Š\u THROUGH \µ
+2978:\’\p \Ù
+2979:SUBSET\p \Ù
+297A:\‰\Š\u THROUGH SUBSET
+297B:SUPERSET\p \‰\Š\u
+297C:\‰ FISH TAIL
+297D:\ùFISH TAIL
+297E:UP FISH TAIL
+297F:\Ë FISH TAIL
+2980:TRIPLE \€\ì DELIMITER
+2981:Z NOT\” SPOT
+2982:Z NOT\” TYPE COLON
+2983:\‰ \¦CURLY \–
+2984:\ù\¦CURLY \–
+2985:\‰ \¦\ÑS
+2986:\ù\¦\ÑS
+2987:Z NOT\” \‰ IMAGE \–
+2988:Z NOT\” \ùIMAGE \–
+2989:Z NOT\” \‰ BIND\ô \–
+298A:Z NOT\” \ùBIND\ô \–
+298B:\‰ \r\–\HUNDERBAR
+298C:\ù\r\–\HUNDERBAR
+298D:\‰ \r\–\HTICK IN TOP CORNER
+298E:\ù\r\–\HTICK IN BOTTOM CORNER
+298F:\‰ \r\–\HTICK IN BOTTOM CORNER
+2990:\ù\r\–\HTICK IN TOP CORNER
+2991:\‰ ANGLE \–\³
+2992:\ùANGLE \–\³
+2993:\‰ ARC \µ \–
+2994:\ùARC \’ \–
+2995:\0 \‰ ARC \’ \–
+2996:\0 \ùARC \µ \–
+2997:\‰ \¬ TORTOISE SHELL \–
+2998:\ù\¬ TORTOISE SHELL \–
+2999:DOTT\ÂFENCE
+299A:\€ ZIGZAG \ä
+299B:MEASUR\ÂANGLE OPEN\ô \‰
+299C:\ùANGLE VARIANT\H\ý
+299D:MEASUR\Â\ùANGLE\³
+299E:ANGLE\HS INSIDE
+299F:\Ü ANGLE
+29A0:SPHERICAL ANGLE OPEN\ô \‰
+29A1:SPHERICAL ANGLE OPEN\ô UP
+29A2:TURN\ÂANGLE
+29A3:\öANGLE
+29A4:ANGLE\HUNDERBAR
+29A5:\öANGLE\HUNDERBAR
+29A6:OBLIQUE ANGLE OPEN\ô UP
+29A7:OBLIQUE ANGLE OPEN\ô \Ë
+29A8:\àUP\i\q
+29A9:\àUP\i\‰
+29AA:\à\Ë\i\q
+29AB:\à\Ë\i\‰
+29AC:\à\ùAND UP
+29AD:\à\‰\iUP
+29AE:\à\ùAND \Ë
+29AF:\à\‰\i\Ë
+29B0:\öEMPTY SET
+29B1:EMPTY SET\HOVERBAR
+29B2:EMPTY SET WITH\Ç\Ð\p
+29B3:EMPTY SET\H\q\u\p
+29B4:EMPTY SET\H\‰\u\p
+29B5:\Ð\H\\ì
+29B6:\c\€\ì
+29B7:\cPARALLEL
+29B8:\cREVERSE SOLIDUS
+29B9:\cPERPENDICULAR
+29BA:\Ð DIVID\ÂBY \\ì\iTOP HALF DIVID\ÂBY \€\ì
+29BB:\Ð\HSUPERIMPOS\ÂX
+29BC:\cANTICLOCKWISE-ROTAT\ÂDIVISION\‚
+29BD:UP\u THROUGH \Ð
+29BE:\c\¦BULLET
+29BF:\cBULLET
+29C0:\c\µ
+29C1:\c\’
+29C2:\Ð WITH\Ç\Ð TO THE \q
+29C3:\Ð\HTWO \ \ÁS TO THE \q
+29C4:\ýD RIS\ô DIAGONAL SLASH
+29C5:\ýD FALL\ô DIAGONAL SLASH
+29C6:\ýD ASTERISK
+29C7:\ýD\Ç\Ð
+29C8:\ýD \ý
+29C9:TWO JOIN\Â\ýS
+29CA:\¾\³\p
+29CB:\¾\HUNDERBAR
+29CC:S IN \¾
+29CD:\¾\HSERIFS AT BOTTOM
+29CE:\ù\¾\p \‰ \¾
+29CF:\‰ \¾ BESIDE \€\ì
+29D0:\€\ì BESIDE \ù\¾
+29D1:BOWTIE\H\‰ HALF \¬
+29D2:BOWTIE\H\ùHALF \¬
+29D3:\¬ BOWTIE
+29D4:TIMES\H\‰ HALF \¬
+29D5:TIMES\H\ùHALF \¬
+29D6:\¦HOURGLASS
+29D7:\¬ HOURGLASS
+29D8:\‰ WIGGLY FENCE
+29D9:\ùWIGGLY FENCE
+29DA:\‰ \0 WIGGLY FENCE
+29DB:\ù\0 WIGGLY FENCE
+29DC:INCOMPLETE INFINITY
+29DD:TIE OVER INFINITY
+29DE:INFINITY NEGATED\H\€\ì
+29DF:\0-END\ÂMULTIMAP
+29E0:\rWITH CONTOUR\ÂOUT\ä
+29E1:INCREASES AS
+29E2:SHUFFLE PRODUCT
+29E3:EQUALS\‚\iSLANT\ÂPARALLEL
+29E4:EQUALS\‚\iSLANT\ÂPARALLEL\H\æ\p
+29E5:IDENTICAL TO\iSLANT\ÂPARALLEL
+29E6:GLEICH STARK
+29E7:THERMODYNAMIC
+29E8:\Ë-\Ä\¾\H\‰ HALF \¬
+29E9:\Ë-\Ä\¾\H\ùHALF \¬
+29EA:\¬ DIAMOND\H\Ë\u
+29EB:\¬ LOZENGE
+29EC:\¦\Ð\H\Ë\u
+29ED:\¬ \Ð\H\Ë\u
+29EE:ERROR-BARR\Â\¦\ý
+29EF:ERROR-BARR\Â\¬ \ý
+29F0:ERROR-BARR\Â\¦DIAMOND
+29F1:ERROR-BARR\Â\¬ DIAMOND
+29F2:ERROR-BARR\Â\¦\Ð
+29F3:ERROR-BARR\Â\¬ \Ð
+29F4:RULE-DELAYED
+29F5:REVERSE SOLIDUS\Ú
+29F6:SOLIDUS\HOVERBAR
+29F7:REVERSE SOLIDUS\H\ \Á
+29F8:BIG SOLIDUS
+29F9:BIG REVERSE SOLIDUS
+29FA:\0 PLUS
+29FB:TRIPLE PLUS
+29FC:\‰-\ÄCURV\ÂANGLE \–
+29FD:\q-\ÄCURV\ÂANGLE \–
+29FE:TINY
+29FF:MINY
+2A00:N-ARY \cDOT\Ú
+2A01:N-ARY \cPLUS\Ú
+2A02:N-ARY \cTIMES\Ú
+2A03:N-ARY UNION\Ú\³
+2A04:N-ARY UNION\Ú\HPLUS
+2A05:N-ARY \rINTERSECTION\Ú
+2A06:N-ARY \rUNION\Ú
+2A07:TWO LOGICAL AND\Ú
+2A08:TWO LOGICAL OR\Ú
+2A09:N-ARY TIMES\Ú
+2A0A:MODULO TWO SUM
+2A0B:SUMM\”\HINTEGRAL
+2A0C:QUADRUPLE INTEGRAL\Ú
+2A0D:FINITE PART INTEGRAL
+2A0E:INTEGRAL\H\0 \Á
+2A0F:INTEGRAL AVERAGE\HSLASH
+2A10:CIRCUL\” FUNCTION
+2A11:ANTICLOCKWISE INTEGR\”
+2A12:\ä INTEGR\”\HRECTANGULAR PATH AROUND POLE
+2A13:\ä INTEGR\”\HSEMICIRCULAR PATH AROUND POLE
+2A14:\ä INTEGR\” NOT INCLUD\ô THE POLE
+2A15:INTEGRAL AROUND A POINT\Ú
+2A16:QUATERNION INTEGRAL\Ú
+2A17:INTEGRAL\H\‰\Š\u\í
+2A18:INTEGRAL\HTIMES\‚
+2A19:INTEGRAL\HINTERSECTION
+2A1A:INTEGRAL\HUNION
+2A1B:INTEGRAL\HOVERBAR
+2A1C:INTEGRAL\HUNDERBAR
+2A1D:JOIN
+2A1E:LARGE \‰ \¾\Ú
+2A1F:Z NOT\” SCHEMA COMPOSITION
+2A20:Z NOT\” SCHEMA PIP\ô
+2A21:Z NOT\” SCHEMA PROJECTION
+2A22:PLUS\‚ WITH\Ç\Ð\p
+2A23:PLUS\‚\ˆ\×\p
+2A24:PLUS\‚\H\æ\p
+2A25:PLUS\‚\³\…
+2A26:PLUS\‚\H\æ\…
+2A27:PLUS\‚\HSUB\Ž TWO
+2A28:PLUS\‚\H\¬ \¾
+2A29:MINUS\‚\HCOMMA\p
+2A2A:MINUS\‚\³\…
+2A2B:MINUS\‚\HFALL\ô DOTS
+2A2C:MINUS\‚\HRIS\ô DOTS
+2A2D:PLUS\‚ IN \‰ HALF \Ð
+2A2E:PLUS\‚ IN \ùHALF \Ð
+2A2F:VECTOR OR CROSS PRODUCT
+2A30:MULTIPLIC\”\‚\³\p
+2A31:MULTIPLIC\”\‚\HUNDERBAR
+2A32:SEMIDIRECT PRODUCT\HBOTTOM CLOSED
+2A33:SMASH PRODUCT
+2A34:MULTIPLIC\”\‚ IN \‰ HALF \Ð
+2A35:MULTIPLIC\”\‚ IN \ùHALF \Ð
+2A36:\cMULTIPLIC\”\‚\ˆ\×
+2A37:MULTIPLIC\”\‚ IN \0 \Ð
+2A38:\cDIVISION\‚
+2A39:PLUS\‚ IN \¾
+2A3A:MINUS\‚ IN \¾
+2A3B:MULTIPLIC\”\‚ IN \¾
+2A3C:INTERIOR PRODUCT
+2A3D:\qHAND INTERIOR PRODUCT
+2A3E:Z NOT\” REL\”AL COMPOSITION
+2A3F:AMALGAM\” OR COPRODUCT
+2A40:INTERSECTION\³
+2A41:UNION\HMINUS\‚
+2A42:UNION\HOVERBAR
+2A43:INTERSECTION\HOVERBAR
+2A44:INTERSECTION\HLOGICAL AND
+2A45:UNION\HLOGICAL OR
+2A46:UNION\p INTERSECTION
+2A47:INTERSECTION\p UNION
+2A48:UNION\p\ì\p INTERSECTION
+2A49:INTERSECTION\p\ì\p UNION
+2A4A:UNION BESIDE\iJOINED\HUNION
+2A4B:INTERSECTION BESIDE\iJOINED\HINTERSECTION
+2A4C:CLOS\ÂUNION\HSERIFS
+2A4D:CLOS\ÂINTERSECTION\HSERIFS
+2A4E:\0 \rINTERSECTION
+2A4F:\0 \rUNION
+2A50:CLOS\ÂUNION\HSERIFS\iSMASH PRODUCT
+2A51:LOGICAL AND\³\p
+2A52:LOGICAL OR\³\p
+2A53:\0 LOGICAL AND
+2A54:\0 LOGICAL OR
+2A55:TWO INTERSECT\ô LOGICAL AND
+2A56:TWO INTERSECT\ô LOGICAL OR
+2A57:SLOP\ô LARGE OR
+2A58:SLOP\ô LARGE AND
+2A59:LOGICAL OR OVERLAPP\ô LOGICAL AND
+2A5A:LOGICAL AND\HMIDDLE STEM
+2A5B:LOGICAL OR\HMIDDLE STEM
+2A5C:LOGICAL AND\H\ DASH
+2A5D:LOGICAL OR\H\ DASH
+2A5E:LOGICAL AND\H\0 OVERBAR
+2A5F:LOGICAL AND\HUNDERBAR
+2A60:LOGICAL AND\H\0 UNDERBAR
+2A61:\§VEE\HUNDERBAR
+2A62:LOGICAL OR\H\0 OVERBAR
+2A63:LOGICAL OR\H\0 UNDERBAR
+2A64:Z NOT\” DOMAIN ANTIRESTRICTION
+2A65:Z NOT\” RANGE ANTIRESTRICTION
+2A66:EQUALS\‚\³\…
+2A67:IDENTICAL\³\p
+2A68:TRIPLE \\ì\H\0 \€ \Á
+2A69:TRIPLE \\ì\HTRIPLE \€ \Á
+2A6A:\æ\Ú\³\p
+2A6B:\æ\Ú\HRIS\ô DOTS
+2A6C:SIMILAR MINUS SIMILAR
+2A6D:CONGRUENT\³\p
+2A6E:EQUALS\HASTERISK
+2A6F:ALMOST\‘\ˆ\×
+2A70:APPROXIMATELY EQUAL OR\‘
+2A71:EQUALS\‚\p PLUS\‚
+2A72:PLUS\‚\p EQUALS\‚
+2A73:EQUALS\‚\p \æ\Ú
+2A74:\0 COLON EQUAL
+2A75:TWO CONSECUTIVE EQUALS\‚S
+2A76:THREE CONSECUTIVE EQUALS\‚S
+2A77:EQUALS\‚\HTWO DOTS\p\iTWO DOTS\…
+2A78:EQUIVALENT\HFOUR DOTS\p
+2A79:\µ\H\Ð INSIDE
+2A7A:\’\H\Ð INSIDE
+2A7B:\µ\HQUESTION\¥\p
+2A7C:\’\HQUESTION\¥\p
+2A7D:\µ OR SLANTED\‘
+2A7E:\’ OR SLANTED\‘
+2A7F:\µ OR SLANTED\‘\³ INSIDE
+2A80:\’ OR SLANTED\‘\³ INSIDE
+2A81:\µ OR SLANTED\‘\³\p
+2A82:\’ OR SLANTED\‘\³\p
+2A83:\µ OR SLANTED\‘\³\p \q
+2A84:\’ OR SLANTED\‘\³\p \‰
+2A85:\µ OR APPROXIMATE
+2A86:\’ OR APPROXIMATE
+2A87:\µ\iS\ôLE-\ä NOT\‘
+2A88:\’\iS\ôLE-\ä NOT\‘
+2A89:\µ\iNOT APPROXIMATE
+2A8A:\’\iNOT APPROXIMATE
+2A8B:\µ\p \0-\ä EQUAL\p \’
+2A8C:\’\p \0-\ä EQUAL\p \µ
+2A8D:\µ\p SIMILAR OR EQUAL
+2A8E:\’\p SIMILAR OR EQUAL
+2A8F:\µ\p SIMILAR\p \’
+2A90:\’\p SIMILAR\p \µ
+2A91:\µ\p \’\p \0-\ä EQUAL
+2A92:\’\p \µ\p \0-\ä EQUAL
+2A93:\µ\p SLANT\ÂEQUAL\p \’\p SLANT\ÂEQUAL
+2A94:\’\p SLANT\ÂEQUAL\p \µ\p SLANT\ÂEQUAL
+2A95:SLANTED\‘ OR \µ
+2A96:SLANTED\‘ OR \’
+2A97:SLANTED\‘ OR \µ\³ INSIDE
+2A98:SLANTED\‘ OR \’\³ INSIDE
+2A99:\0-\ä\‘ OR \µ
+2A9A:\0-\ä\‘ OR \’
+2A9B:\0-\ä SLANTED\‘ OR \µ
+2A9C:\0-\ä SLANTED\‘ OR \’
+2A9D:SIMILAR OR \µ
+2A9E:SIMILAR OR \’
+2A9F:SIMILAR\p \µ\p EQUALS\‚
+2AA0:SIMILAR\p \’\p EQUALS\‚
+2AA1:\0 NEST\Â\µ
+2AA2:\0 NEST\Â\’
+2AA3:\0 NEST\Â\µ\HUNDERBAR
+2AA4:\’ OVERLAPP\ô \µ
+2AA5:\’ BESIDE \µ
+2AA6:\µ CLOS\ÂBY CURVE
+2AA7:\’ CLOS\ÂBY CURVE
+2AA8:\µ CLOS\ÂBY CURVE\p SLANT\ÂEQUAL
+2AA9:\’ CLOS\ÂBY CURVE\p SLANT\ÂEQUAL
+2AAA:SMALLER THAN
+2AAB:LARGER THAN
+2AAC:SMALLER THAN OR\‘
+2AAD:LARGER THAN OR\‘
+2AAE:EQUALS\‚\HBUMPY\p
+2AAF:PRECEDES\p S\ôLE-\ä EQUALS\‚
+2AB0:SUCCEEDS\p S\ôLE-\ä EQUALS\‚
+2AB1:PRECEDES\p S\ôLE-\ä NOT\‘
+2AB2:SUCCEEDS\p S\ôLE-\ä NOT\‘
+2AB3:PRECEDES\p EQUALS\‚
+2AB4:SUCCEEDS\p EQUALS\‚
+2AB5:PRECEDES\p NOT\‘
+2AB6:SUCCEEDS\p NOT\‘
+2AB7:PRECEDES\p ALMOST\‘
+2AB8:SUCCEEDS\p ALMOST\‘
+2AB9:PRECEDES\p NOT ALMOST\‘
+2ABA:SUCCEEDS\p NOT ALMOST\‘
+2ABB:\0 PRECEDES
+2ABC:\0 SUCCEEDS
+2ABD:SUBSET\³
+2ABE:SUPERSET\³
+2ABF:SUBSET\HPLUS\‚\…
+2AC0:SUPERSET\HPLUS\‚\…
+2AC1:SUBSET\HMULTIPLIC\”\‚\…
+2AC2:SUPERSET\HMULTIPLIC\”\‚\…
+2AC3:SUBSET OF OR\‘\³\p
+2AC4:SUPERSET OF OR\‘\³\p
+2AC5:SUBSET OF\p EQUALS\‚
+2AC6:SUPERSET OF\p EQUALS\‚
+2AC7:SUBSET OF\p \æ\Ú
+2AC8:SUPERSET OF\p \æ\Ú
+2AC9:SUBSET OF\p ALMOST\‘
+2ACA:SUPERSET OF\p ALMOST\‘
+2ACB:SUBSET OF\p NOT\‘
+2ACC:SUPERSET OF\p NOT\‘
+2ACD:\r\‰ OPEN BOX\Ú
+2ACE:\r\ùOPEN BOX\Ú
+2ACF:CLOS\ÂSUBSET
+2AD0:CLOS\ÂSUPERSET
+2AD1:CLOS\ÂSUBSET OR\‘
+2AD2:CLOS\ÂSUPERSET OR\‘
+2AD3:SUBSET\p SUPERSET
+2AD4:SUPERSET\p SUBSET
+2AD5:SUBSET\p SUBSET
+2AD6:SUPERSET\p SUPERSET
+2AD7:SUPERSET BESIDE SUBSET
+2AD8:SUPERSET BESIDE\iJOIN\ÂBY DASH\HSUBSET
+2AD9:ELEMENT OF OPEN\ô \Ë\Š
+2ADA:PITCHFORK\HTEE TOP
+2ADB:TRANSVERSAL INTERSECTION
+2ADC:FORK\ô
+2ADD:NONFORK\ô
+2ADE:SHORT \‰ TACK
+2ADF:SHORT \Ë TACK
+2AE0:SHORT UP TACK
+2AE1:PERPENDICULAR\HS
+2AE2:\€\ì TRIPLE \ùTURNSTILE
+2AE3:\0 \€\ì \‰ TURNSTILE
+2AE4:\€\ì \0 \‰ TURNSTILE
+2AE5:\0 \€\ì \0 \‰ TURNSTILE
+2AE6:LONG DASH FROM \‰ MEMBER OF \0 \€
+2AE7:SHORT \Ë TACK\HOVERBAR
+2AE8:SHORT UP TACK\HUNDERBAR
+2AE9:SHORT UP TACK\p SHORT \Ë TACK
+2AEA:\0 \Ë TACK
+2AEB:\0 UP TACK
+2AEC:\0 \Á NOT\‚
+2AED:\ö\0 \Á NOT\‚
+2AEE:DOES NOT DIVIDE\H\öNEG\” SLASH
+2AEF:\€ \ä\H\Ð\p
+2AF0:\€ \ä\H\Ð\…
+2AF1:\Ë TACK\H\Ð\…
+2AF2:PARALLEL\H\ \Á
+2AF3:PARALLEL\H\æ\Ú
+2AF4:TRIPLE \€\ì BINARY REL\”
+2AF5:TRIPLE \€\ì\H\ \Á
+2AF6:TRIPLE COLON\Ú
+2AF7:TRIPLE NEST\Â\µ
+2AF8:TRIPLE NEST\Â\’
+2AF9:\0-\ä SLANT\Â\µ OR\‘
+2AFA:\0-\ä SLANT\Â\’ OR\‘
+2AFB:TRIPLE SOLIDUS BINARY REL\”
+2AFC:LARGE TRIPLE \€\ì\Ú
+2AFD:\0 SOLIDUS\Ú
+2AFE:\¦\€\ì
+2AFF:N-ARY \¦\€\ì
+2E80:CJK\vREPEAT
+2E81:CJK\vCLIFF
+2E82:CJK\vSECOND ONE
+2E83:CJK\vSECOND TWO
+2E84:CJK\vSECOND THREE
+2E85:CJK\vPERSON
+2E86:CJK\vBOX
+2E87:CJK\vTABLE
+2E88:CJK\vKNIFE ONE
+2E89:CJK\vKNIFE TWO
+2E8A:CJK\vDIVIN\”
+2E8B:CJK\vSEAL
+2E8C:CJK\v\§ONE
+2E8D:CJK\v\§TWO
+2E8E:CJK\vLAME ONE
+2E8F:CJK\vLAME TWO
+2E90:CJK\vLAME THREE
+2E91:CJK\vLAME FOUR
+2E92:CJK\vSNAKE
+2E93:CJK\vTHREAD
+2E94:CJK\vSNOUT ONE
+2E95:CJK\vSNOUT TWO
+2E96:CJK\vHEART ONE
+2E97:CJK\vHEART TWO
+2E98:CJK\vHAND
+2E99:CJK\vRAP
+2E9B:CJK\vCHOKE
+2E9C:CJK\vSUN
+2E9D:CJK\vMOON
+2E9E:CJK\vDEATH
+2E9F:CJK\vMOTHER
+2EA0:CJK\vCIVILIAN
+2EA1:CJK\vWATER ONE
+2EA2:CJK\vWATER TWO
+2EA3:CJK\vFIRE
+2EA4:CJK\vPAW ONE
+2EA5:CJK\vPAW TWO
+2EA6:CJK\vSIMPLIFI\ÂHALF TREE TRUNK
+2EA7:CJK\vCOW
+2EA8:CJK\vDOG
+2EA9:CJK\vJADE
+2EAA:CJK\vBOLT OF CLOTH
+2EAB:CJK\vEYE
+2EAC:CJK\vSPIRIT ONE
+2EAD:CJK\vSPIRIT TWO
+2EAE:CJK\vBAMBOO
+2EAF:CJK\vSILK
+2EB0:CJK\vC-SIMPLIFI\ÂSILK
+2EB1:CJK\vNET ONE
+2EB2:CJK\vNET TWO
+2EB3:CJK\vNET THREE
+2EB4:CJK\vNET FOUR
+2EB5:CJK\vMESH
+2EB6:CJK\vSHEEP
+2EB7:CJK\vRAM
+2EB8:CJK\vEWE
+2EB9:CJK\vOLD
+2EBA:CJK\vBRUSH ONE
+2EBB:CJK\vBRUSH TWO
+2EBC:CJK\vMEAT
+2EBD:CJK\vMORTAR
+2EBE:CJK\vGRASS ONE
+2EBF:CJK\vGRASS TWO
+2EC0:CJK\vGRASS THREE
+2EC1:CJK\vTIGER
+2EC2:CJK\vCLOTHES
+2EC3:CJK\vWEST ONE
+2EC4:CJK\vWEST TWO
+2EC5:CJK\vC-SIMPLIFI\ÂSEE
+2EC6:CJK\vSIMPLIFI\ÂHORN
+2EC7:CJK\vHORN
+2EC8:CJK\vC-SIMPLIFI\ÂSPEECH
+2EC9:CJK\vC-SIMPLIFI\ÂSHELL
+2ECA:CJK\vFOOT
+2ECB:CJK\vC-SIMPLIFI\ÂCART
+2ECC:CJK\vSIMPLIFI\ÂWALK
+2ECD:CJK\vWALK ONE
+2ECE:CJK\vWALK TWO
+2ECF:CJK\vCITY
+2ED0:CJK\vC-SIMPLIFI\ÂGOLD
+2ED1:CJK\vLONG ONE
+2ED2:CJK\vLONG TWO
+2ED3:CJK\vC-SIMPLIFI\ÂLONG
+2ED4:CJK\vC-SIMPLIFI\ÂGATE
+2ED5:CJK\vMOUND ONE
+2ED6:CJK\vMOUND TWO
+2ED7:CJK\vRAIN
+2ED8:CJK\vBLUE
+2ED9:CJK\vC-SIMPLIFI\ÂTANN\ÂLEATHER
+2EDA:CJK\vC-SIMPLIFI\ÂLEAF
+2EDB:CJK\vC-SIMPLIFI\ÂWIND
+2EDC:CJK\vC-SIMPLIFI\ÂFLY
+2EDD:CJK\vEAT ONE
+2EDE:CJK\vEAT TWO
+2EDF:CJK\vEAT THREE
+2EE0:CJK\vC-SIMPLIFI\ÂEAT
+2EE1:CJK\vHEAD
+2EE2:CJK\vC-SIMPLIFI\ÂHORSE
+2EE3:CJK\vBONE
+2EE4:CJK\vGHOST
+2EE5:CJK\vC-SIMPLIFI\ÂFISH
+2EE6:CJK\vC-SIMPLIFI\ÂBIRD
+2EE7:CJK\vC-SIMPLIFI\ÂSALT
+2EE8:CJK\vSIMPLIFI\ÂWHEAT
+2EE9:CJK\vSIMPLIFI\ÂYELLOW
+2EEA:CJK\vC-SIMPLIFI\ÂFROG
+2EEB:CJK\vJ-SIMPLIFI\ÂEVEN
+2EEC:CJK\vC-SIMPLIFI\ÂEVEN
+2EED:CJK\vJ-SIMPLIFI\ÂTOOTH
+2EEE:CJK\vC-SIMPLIFI\ÂTOOTH
+2EEF:CJK\vJ-SIMPLIFI\ÂDRAGON
+2EF0:CJK\vC-SIMPLIFI\ÂDRAGON
+2EF1:CJK\vTURTLE
+2EF2:CJK\vJ-SIMPLIFI\ÂTURTLE
+2EF3:CJK\vC-SIMPLIFI\ÂTURTLE
+2F00:\UONE
+2F01:\U\ä
+2F02:\UDOT
+2F03:\USLASH
+2F04:\USECOND
+2F05:\UHOOK
+2F06:\UTWO
+2F07:\ULID
+2F08:\UMAN
+2F09:\ULEGS
+2F0A:\UENTER
+2F0B:\UE\¼
+2F0C:\U\Ë BOX
+2F0D:\UCOVER
+2F0E:\UICE
+2F0F:\UTABLE
+2F10:\UOPEN BOX
+2F11:\UKNIFE
+2F12:\UPOWER
+2F13:\UWRAP
+2F14:\USPOON
+2F15:\U\ùOPEN BOX
+2F16:\UHID\ô ENCLOSURE
+2F17:\UTEN
+2F18:\UDIVIN\”
+2F19:\USEAL
+2F1A:\UCLIFF
+2F1B:\UPRIVATE
+2F1C:\UAGAIN
+2F1D:\UMOUTH
+2F1E:\UENCLOSURE
+2F1F:\UEARTH
+2F20:\USCHOLAR
+2F21:\UGO
+2F22:\UGO SLOWLY
+2F23:\UEVEN\ô
+2F24:\UBIG
+2F25:\UWOMAN
+2F26:\UCHILD
+2F27:\UROOF
+2F28:\UINCH
+2F29:\USMALL
+2F2A:\ULAME
+2F2B:\UCORPSE
+2F2C:\USPROUT
+2F2D:\UMOUNTAIN
+2F2E:\URIVER
+2F2F:\UWORK
+2F30:\UONESELF
+2F31:\UTURBAN
+2F32:\UDRY
+2F33:\USHORT THREAD
+2F34:\UDOTT\ÂCLIFF
+2F35:\ULONG STRIDE
+2F36:\UTWO HANDS
+2F37:\USHOOT
+2F38:\UBOW
+2F39:\USNOUT
+2F3A:\UBRISTLE
+2F3B:\USTEP
+2F3C:\UHEART
+2F3D:\UHALBERD
+2F3E:\UDOOR
+2F3F:\UHAND
+2F40:\UBRANCH
+2F41:\URAP
+2F42:\U\Ž
+2F43:\UDIPPER
+2F44:\UAXE
+2F45:\U\ý
+2F46:\UNOT
+2F47:\USUN
+2F48:\USAY
+2F49:\UMOON
+2F4A:\UTREE
+2F4B:\ULACK
+2F4C:\USTOP
+2F4D:\UDEATH
+2F4E:\UWEAPON
+2F4F:\UDO NOT
+2F50:\UCOMPARE
+2F51:\UFUR
+2F52:\UCLAN
+2F53:\USTEAM
+2F54:\UWATER
+2F55:\UFIRE
+2F56:\UCLAW
+2F57:\UFATHER
+2F58:\U\0 X
+2F59:\UHALF TREE TRUNK
+2F5A:\USLICE
+2F5B:\UFANG
+2F5C:\UCOW
+2F5D:\UDOG
+2F5E:\UPROFOUND
+2F5F:\UJADE
+2F60:\UMELON
+2F61:\UTILE
+2F62:\USWEET
+2F63:\ULIFE
+2F64:\UUSE
+2F65:\UFIELD
+2F66:\UBOLT OF CLOTH
+2F67:\USICKNESS
+2F68:\UDOTT\ÂTENT
+2F69:\UWHITE
+2F6A:\USKIN
+2F6B:\UDISH
+2F6C:\UEYE
+2F6D:\USPEAR
+2F6E:\UARROW
+2F6F:\USTONE
+2F70:\USPIRIT
+2F71:\UTRACK
+2F72:\UGRAIN
+2F73:\UCAVE
+2F74:\USTAND
+2F75:\UBAMBOO
+2F76:\URICE
+2F77:\USILK
+2F78:\UJAR
+2F79:\UNET
+2F7A:\USHEEP
+2F7B:\UFEATHER
+2F7C:\UOLD
+2F7D:\UAND
+2F7E:\UPLOW
+2F7F:\UEAR
+2F80:\UBRUSH
+2F81:\UMEAT
+2F82:\UMINISTER
+2F83:\USELF
+2F84:\UARRIVE
+2F85:\UMORTAR
+2F86:\UTONGUE
+2F87:\UOPPOSE
+2F88:\UBOAT
+2F89:\USTOPP\ô
+2F8A:\UCOLOR
+2F8B:\UGRASS
+2F8C:\UTIGER
+2F8D:\UINSECT
+2F8E:\UBLOOD
+2F8F:\UWALK ENCLOSURE
+2F90:\UCLOTHES
+2F91:\UWEST
+2F92:\USEE
+2F93:\UHORN
+2F94:\USPEECH
+2F95:\UVALLEY
+2F96:\UBEAN
+2F97:\UPIG
+2F98:\UBADGER
+2F99:\USHELL
+2F9A:\URED
+2F9B:\URUN
+2F9C:\UFOOT
+2F9D:\UBODY
+2F9E:\UCART
+2F9F:\UBITTER
+2FA0:\UMORN\ô
+2FA1:\UWALK
+2FA2:\UCITY
+2FA3:\UWINE
+2FA4:\UDIST\ôUISH
+2FA5:\UVILLAGE
+2FA6:\UGOLD
+2FA7:\ULONG
+2FA8:\UGATE
+2FA9:\UMOUND
+2FAA:\USLAVE
+2FAB:\USHORT TAIL\ÂBIRD
+2FAC:\URAIN
+2FAD:\UBLUE
+2FAE:\UWRONG
+2FAF:\UFACE
+2FB0:\ULEATHER
+2FB1:\UTANN\ÂLEATHER
+2FB2:\ULEEK
+2FB3:\USOUND
+2FB4:\ULEAF
+2FB5:\UWIND
+2FB6:\UFLY
+2FB7:\UEAT
+2FB8:\UHEAD
+2FB9:\UFRAGRANT
+2FBA:\UHORSE
+2FBB:\UBONE
+2FBC:\UTALL
+2FBD:\UHAIR
+2FBE:\UF\¼
+2FBF:\USACRIFICIAL WINE
+2FC0:\UCAULDRON
+2FC1:\UGHOST
+2FC2:\UFISH
+2FC3:\UBIRD
+2FC4:\USALT
+2FC5:\UDEER
+2FC6:\UWHEAT
+2FC7:\UHEMP
+2FC8:\UYELLOW
+2FC9:\UMILLET
+2FCA:\U\¬
+2FCB:\UEMBROIDERY
+2FCC:\UFROG
+2FCD:\UTRIPOD
+2FCE:\UDRUM
+2FCF:\URAT
+2FD0:\UNOSE
+2FD1:\UEVEN
+2FD2:\UTOOTH
+2FD3:\UDRAGON
+2FD4:\UTURTLE
+2FD5:\UFLUTE
+2FF0:\ð \‰ TO \q
+2FF1:\ð\p TO\…
+2FF2:\ð \‰ TO MIDDLE\i\q
+2FF3:\ð\p TO MIDDLE AND\…
+2FF4:\ð FULL SURROUND
+2FF5:\ð SURROUND FROM\p
+2FF6:\ð SURROUND FROM\…
+2FF7:\ð SURROUND FROM \‰
+2FF8:\ð SURROUND FROM \÷\‰
+2FF9:\ð SURROUND FROM \÷\q
+2FFA:\ð SURROUND FROM \ï\‰
+2FFB:\ð OVERLAID
+3000:\8IC SPACE
+3001:\8IC COMMA
+3002:\8IC\é
+3003:DITTO\¥
+3004:JAPANESE INDUSTRIAL STANDARD \
+3005:\8IC ITER\”\¥
+3006:\8IC CLOS\ô\¥
+3007:\8IC \­ZERO
+3008:\‰ ANGLE \–
+3009:\ùANGLE \–
+300A:\‰ \0 ANGLE \–
+300B:\ù\0 ANGLE \–
+300C:\‰ CORNER \–
+300D:\ùCORNER \–
+300E:\‰ \¦CORNER \–
+300F:\ù\¦CORNER \–
+3010:\‰ \¬ LENTICULAR \–
+3011:\ù\¬ LENTICULAR \–
+3012:POSTAL\¥
+3013:GETA\¥
+3014:\‰ TORTOISE SHELL \–
+3015:\ùTORTOISE SHELL \–
+3016:\‰ \¦LENTICULAR \–
+3017:\ù\¦LENTICULAR \–
+3018:\‰ \¦TORTOISE SHELL \–
+3019:\ù\¦TORTOISE SHELL \–
+301A:\‰ \¦\r\–
+301B:\ù\¦\r\–
+301C:WAVE DASH
+301D:\ö\0 PRIME QUOT\”\¥
+301E:\0 PRIME QUOT\”\¥
+301F:LOW \0 PRIME QUOT\”\¥
+3020:POSTAL\¥ FACE
+3021:HANGZHOU NUMERAL ONE
+3022:HANGZHOU NUMERAL TWO
+3023:HANGZHOU NUMERAL THREE
+3024:HANGZHOU NUMERAL FOUR
+3025:HANGZHOU NUMERAL FIVE
+3026:HANGZHOU NUMERAL SIX
+3027:HANGZHOU NUMERAL SEVEN
+3028:HANGZHOU NUMERAL E\¼
+3029:HANGZHOU NUMERAL NINE
+302A:\8IC LEVEL TONE\¥
+302B:\8IC RIS\ô TONE\¥
+302C:\8IC DEPART\ô TONE\¥
+302D:\8IC ENTER\ô TONE\¥
+302E:\e S\ôLE DOT TONE\¥
+302F:\e \0 DOT TONE\¥
+3030:WAVY DASH
+3031:\€ KANA REPEAT\¥
+3032:\€ KANA REPEAT\HVOIC\ÂSOUND\¥
+3033:\€ KANA REPEAT\¥ \÷HALF
+3034:\€ KANA REPEAT\HVOIC\ÂSOUND\¥ \÷HALF
+3035:\€ KANA REPEAT\¥ \ïHALF
+3036:\cPOSTAL\¥
+3037:\8IC TELEGRAPH \ä FE\ÂSEPARATOR \
+3038:HANGZHOU NUMERAL TEN
+3039:HANGZHOU NUMERAL TWENTY
+303A:HANGZHOU NUMERAL THIRTY
+303B:\€ \8IC ITER\”\¥
+303C:MASU\¥
+303D:PART ALTERN\”\¥
+303E:\8IC VARI\” INDICATOR
+303F:\8IC HALF FILL SPACE
+3041:\‹\§A
+3042:\‹A
+3043:\‹\§I
+3044:\‹I
+3045:\‹\§U
+3046:\‹U
+3047:\‹\§E
+3048:\‹E
+3049:\‹\§O
+304A:\‹O
+304B:\‹KA
+304C:\‹GA
+304D:\‹KI
+304E:\‹GI
+304F:\‹KU
+3050:\‹GU
+3051:\‹KE
+3052:\‹GE
+3053:\‹KO
+3054:\‹GO
+3055:\‹SA
+3056:\‹ZA
+3057:\‹SI
+3058:\‹ZI
+3059:\‹SU
+305A:\‹ZU
+305B:\‹SE
+305C:\‹ZE
+305D:\‹SO
+305E:\‹ZO
+305F:\‹TA
+3060:\‹DA
+3061:\‹TI
+3062:\‹DI
+3063:\‹\§TU
+3064:\‹TU
+3065:\‹DU
+3066:\‹TE
+3067:\‹DE
+3068:\‹TO
+3069:\‹DO
+306A:\‹NA
+306B:\‹NI
+306C:\‹NU
+306D:\‹NE
+306E:\‹NO
+306F:\‹HA
+3070:\‹BA
+3071:\‹PA
+3072:\‹HI
+3073:\‹BI
+3074:\‹PI
+3075:\‹HU
+3076:\‹BU
+3077:\‹PU
+3078:\‹HE
+3079:\‹BE
+307A:\‹PE
+307B:\‹HO
+307C:\‹BO
+307D:\‹PO
+307E:\‹MA
+307F:\‹MI
+3080:\‹MU
+3081:\‹ME
+3082:\‹MO
+3083:\‹\§YA
+3084:\‹YA
+3085:\‹\§YU
+3086:\‹YU
+3087:\‹\§YO
+3088:\‹YO
+3089:\‹RA
+308A:\‹RI
+308B:\‹RU
+308C:\‹RE
+308D:\‹RO
+308E:\‹\§WA
+308F:\‹WA
+3090:\‹WI
+3091:\‹WE
+3092:\‹WO
+3093:\‹N
+3094:\‹VU
+3095:\‹\§KA
+3096:\‹\§KE
+3099:\o\n-HIRAGANA VOIC\ÂSOUND\¥
+309A:\o\n-HIRAGANA SEMI-VOIC\ÂSOUND\¥
+309B:\n-HIRAGANA VOIC\ÂSOUND\¥
+309C:\n-HIRAGANA SEMI-VOIC\ÂSOUND\¥
+309D:HIRAGANA ITER\”\¥
+309E:HIRAGANA VOIC\ÂITER\”\¥
+309F:HIRAGANA DIGRAPH YORI
+30A0:\n-HIRAGANA \0 HYPHEN
+30A1:\Í\§A
+30A2:\ÍA
+30A3:\Í\§I
+30A4:\ÍI
+30A5:\Í\§U
+30A6:\ÍU
+30A7:\Í\§E
+30A8:\ÍE
+30A9:\Í\§O
+30AA:\ÍO
+30AB:\ÍKA
+30AC:\ÍGA
+30AD:\ÍKI
+30AE:\ÍGI
+30AF:\ÍKU
+30B0:\ÍGU
+30B1:\ÍKE
+30B2:\ÍGE
+30B3:\ÍKO
+30B4:\ÍGO
+30B5:\ÍSA
+30B6:\ÍZA
+30B7:\ÍSI
+30B8:\ÍZI
+30B9:\ÍSU
+30BA:\ÍZU
+30BB:\ÍSE
+30BC:\ÍZE
+30BD:\ÍSO
+30BE:\ÍZO
+30BF:\ÍTA
+30C0:\ÍDA
+30C1:\ÍTI
+30C2:\ÍDI
+30C3:\Í\§TU
+30C4:\ÍTU
+30C5:\ÍDU
+30C6:\ÍTE
+30C7:\ÍDE
+30C8:\ÍTO
+30C9:\ÍDO
+30CA:\ÍNA
+30CB:\ÍNI
+30CC:\ÍNU
+30CD:\ÍNE
+30CE:\ÍNO
+30CF:\ÍHA
+30D0:\ÍBA
+30D1:\ÍPA
+30D2:\ÍHI
+30D3:\ÍBI
+30D4:\ÍPI
+30D5:\ÍHU
+30D6:\ÍBU
+30D7:\ÍPU
+30D8:\ÍHE
+30D9:\ÍBE
+30DA:\ÍPE
+30DB:\ÍHO
+30DC:\ÍBO
+30DD:\ÍPO
+30DE:\ÍMA
+30DF:\ÍMI
+30E0:\ÍMU
+30E1:\ÍME
+30E2:\ÍMO
+30E3:\Í\§YA
+30E4:\ÍYA
+30E5:\Í\§YU
+30E6:\ÍYU
+30E7:\Í\§YO
+30E8:\ÍYO
+30E9:\ÍRA
+30EA:\ÍRI
+30EB:\ÍRU
+30EC:\ÍRE
+30ED:\ÍRO
+30EE:\Í\§WA
+30EF:\ÍWA
+30F0:\ÍWI
+30F1:\ÍWE
+30F2:\ÍWO
+30F3:\ÍN
+30F4:\ÍVU
+30F5:\Í\§KA
+30F6:\Í\§KE
+30F7:\ÍVA
+30F8:\ÍVI
+30F9:\ÍVE
+30FA:\ÍVO
+30FB:\n MIDDLE DOT
+30FC:\n-HIRAGANA PROLONG\ÂSOUND\¥
+30FD:\n ITER\”\¥
+30FE:\n VOIC\ÂITER\”\¥
+30FF:\n DIGRAPH KOTO
+3105:\©B
+3106:\©P
+3107:\©M
+3108:\©F
+3109:\©D
+310A:\©T
+310B:\©N
+310C:\©L
+310D:\©G
+310E:\©K
+310F:\©H
+3110:\©J
+3111:\©Q
+3112:\©X
+3113:\©ZH
+3114:\©CH
+3115:\©SH
+3116:\©R
+3117:\©Z
+3118:\©C
+3119:\©S
+311A:\©A
+311B:\©O
+311C:\©E
+311D:\©EH
+311E:\©AI
+311F:\©EI
+3120:\©AU
+3121:\©OU
+3122:\©AN
+3123:\©EN
+3124:\©ANG
+3125:\©ENG
+3126:\©ER
+3127:\©I
+3128:\©U
+3129:\©IU
+312A:\©V
+312B:\©NG
+312C:\©GN
+3131:\ÖKIYEOK
+3132:\ÖSSANGKIYEOK
+3133:\ÖKIYEOK-SIOS
+3134:\ÖN\ÆN
+3135:\ÖN\ÆN-C\ÆC
+3136:\ÖN\ÆN-H\ÆH
+3137:\ÖTIKEUT
+3138:\ÖSSANGTIKEUT
+3139:\ÖR\ÆL
+313A:\ÖR\ÆL-KIYEOK
+313B:\ÖR\ÆL-M\ÆM
+313C:\ÖR\ÆL-P\ÆP
+313D:\ÖR\ÆL-SIOS
+313E:\ÖR\ÆL-TH\ÆTH
+313F:\ÖR\ÆL-PH\ÆPH
+3140:\ÖR\ÆL-H\ÆH
+3141:\ÖM\ÆM
+3142:\ÖP\ÆP
+3143:\ÖSSANGP\ÆP
+3144:\ÖP\ÆP-SIOS
+3145:\ÖSIOS
+3146:\ÖSSANGSIOS
+3147:\Ö\ÆNG
+3148:\ÖC\ÆC
+3149:\ÖSSANGC\ÆC
+314A:\ÖCH\ÆCH
+314B:\ÖKH\ÆKH
+314C:\ÖTH\ÆTH
+314D:\ÖPH\ÆPH
+314E:\ÖH\ÆH
+314F:\ÖA
+3150:\ÖAE
+3151:\ÖYA
+3152:\ÖYAE
+3153:\ÖEO
+3154:\ÖE
+3155:\ÖYEO
+3156:\ÖYE
+3157:\ÖO
+3158:\ÖWA
+3159:\ÖWAE
+315A:\ÖOE
+315B:\ÖYO
+315C:\ÖU
+315D:\ÖWEO
+315E:\ÖWE
+315F:\ÖWI
+3160:\ÖYU
+3161:\ÖEU
+3162:\ÖYI
+3163:\ÖI
+3164:\e FILLER
+3165:\ÖSSANGN\ÆN
+3166:\ÖN\ÆN-TIKEUT
+3167:\ÖN\ÆN-SIOS
+3168:\ÖN\ÆN-PANSIOS
+3169:\ÖR\ÆL-KIYEOK-SIOS
+316A:\ÖR\ÆL-TIKEUT
+316B:\ÖR\ÆL-P\ÆP-SIOS
+316C:\ÖR\ÆL-PANSIOS
+316D:\ÖR\ÆL-YEORINH\ÆH
+316E:\ÖM\ÆM-P\ÆP
+316F:\ÖM\ÆM-SIOS
+3170:\ÖM\ÆM-PANSIOS
+3171:\ÖKAPYEOUNM\ÆM
+3172:\ÖP\ÆP-KIYEOK
+3173:\ÖP\ÆP-TIKEUT
+3174:\ÖP\ÆP-SIOS-KIYEOK
+3175:\ÖP\ÆP-SIOS-TIKEUT
+3176:\ÖP\ÆP-C\ÆC
+3177:\ÖP\ÆP-TH\ÆTH
+3178:\ÖKAPYEOUNP\ÆP
+3179:\ÖKAPYEOUNSSANGP\ÆP
+317A:\ÖSIOS-KIYEOK
+317B:\ÖSIOS-N\ÆN
+317C:\ÖSIOS-TIKEUT
+317D:\ÖSIOS-P\ÆP
+317E:\ÖSIOS-C\ÆC
+317F:\ÖPANSIOS
+3180:\ÖSSANG\ÆNG
+3181:\ÖYES\ÆNG
+3182:\ÖYES\ÆNG-SIOS
+3183:\ÖYES\ÆNG-PANSIOS
+3184:\ÖKAPYEOUNPH\ÆPH
+3185:\ÖSSANGH\ÆH
+3186:\ÖYEORINH\ÆH
+3187:\ÖYO-YA
+3188:\ÖYO-YAE
+3189:\ÖYO-I
+318A:\ÖYU-YEO
+318B:\ÖYU-YE
+318C:\ÖYU-I
+318D:\ÖARAEA
+318E:\ÖARAEAE
+3190:\8IC ANNOT\” LINK\ô\¥
+3191:\8IC ANNOT\” REVERSE\¥
+3192:\8IC ANNOT\” ONE\¥
+3193:\8IC ANNOT\” TWO\¥
+3194:\8IC ANNOT\” THREE\¥
+3195:\8IC ANNOT\” FOUR\¥
+3196:\8IC ANNOT\” TOP\¥
+3197:\8IC ANNOT\” MIDDLE\¥
+3198:\8IC ANNOT\” BOTTOM\¥
+3199:\8IC ANNOT\” FIRST\¥
+319A:\8IC ANNOT\” SECOND\¥
+319B:\8IC ANNOT\” THIRD\¥
+319C:\8IC ANNOT\” FOURTH\¥
+319D:\8IC ANNOT\” HEAVEN\¥
+319E:\8IC ANNOT\” EARTH\¥
+319F:\8IC ANNOT\” MAN\¥
+31A0:\©BU
+31A1:\©ZI
+31A2:\©JI
+31A3:\©GU
+31A4:\©EE
+31A5:\©ENN
+31A6:\©OO
+31A7:\©ONN
+31A8:\©IR
+31A9:\©ANN
+31AA:\©INN
+31AB:\©UNN
+31AC:\©IM
+31AD:\©NGG
+31AE:\©AINN
+31AF:\©AUNN
+31B0:\©AM
+31B1:\©OM
+31B2:\©ONG
+31B3:\©INNN
+31B4:BOPOMOFO FINAL\@P
+31B5:BOPOMOFO FINAL\@T
+31B6:BOPOMOFO FINAL\@K
+31B7:BOPOMOFO FINAL\@H
+31F0:\Í\§KU
+31F1:\Í\§SI
+31F2:\Í\§SU
+31F3:\Í\§TO
+31F4:\Í\§NU
+31F5:\Í\§HA
+31F6:\Í\§HI
+31F7:\Í\§HU
+31F8:\Í\§HE
+31F9:\Í\§HO
+31FA:\Í\§MU
+31FB:\Í\§RA
+31FC:\Í\§RI
+31FD:\Í\§RU
+31FE:\Í\§RE
+31FF:\Í\§RO
+3200:\t\e KIYEOK
+3201:\t\e N\ÆN
+3202:\t\e TIKEUT
+3203:\t\e R\ÆL
+3204:\t\e M\ÆM
+3205:\t\e P\ÆP
+3206:\t\e SIOS
+3207:\t\e \ÆNG
+3208:\t\e C\ÆC
+3209:\t\e CH\ÆCH
+320A:\t\e KH\ÆKH
+320B:\t\e TH\ÆTH
+320C:\t\e PH\ÆPH
+320D:\t\e H\ÆH
+320E:\t\e KIYEOK A
+320F:\t\e N\ÆN A
+3210:\t\e TIKEUT A
+3211:\t\e R\ÆL A
+3212:\t\e M\ÆM A
+3213:\t\e P\ÆP A
+3214:\t\e SIOS A
+3215:\t\e \ÆNG A
+3216:\t\e C\ÆC A
+3217:\t\e CH\ÆCH A
+3218:\t\e KH\ÆKH A
+3219:\t\e TH\ÆTH A
+321A:\t\e PH\ÆPH A
+321B:\t\e H\ÆH A
+321C:\t\e C\ÆC U
+3220:\t\8 ONE
+3221:\t\8 TWO
+3222:\t\8 THREE
+3223:\t\8 FOUR
+3224:\t\8 FIVE
+3225:\t\8 SIX
+3226:\t\8 SEVEN
+3227:\t\8 E\¼
+3228:\t\8 NINE
+3229:\t\8 TEN
+322A:\t\8 MOON
+322B:\t\8 FIRE
+322C:\t\8 WATER
+322D:\t\8 WOOD
+322E:\t\8 METAL
+322F:\t\8 EARTH
+3230:\t\8 SUN
+3231:\t\8 STOCK
+3232:\t\8 HAVE
+3233:\t\8 SOCIETY
+3234:\t\8 NAME
+3235:\t\8 SPECIAL
+3236:\t\8 FINANCIAL
+3237:\t\8 CONGRATUL\”
+3238:\t\8 LABOR
+3239:\t\8 REPRESENT
+323A:\t\8 CALL
+323B:\t\8 STUDY
+323C:\t\8 SUPERVISE
+323D:\t\8 ENTERPRISE
+323E:\t\8 RESOURCE
+323F:\t\8 ALLIANCE
+3240:\t\8 FESTIVAL
+3241:\t\8 REST
+3242:\t\8 SELF
+3243:\t\8 REACH
+3251:\c\­TWENTY ONE
+3252:\c\­TWENTY TWO
+3253:\c\­TWENTY THREE
+3254:\c\­TWENTY FOUR
+3255:\c\­TWENTY FIVE
+3256:\c\­TWENTY SIX
+3257:\c\­TWENTY SEVEN
+3258:\c\­TWENTY E\¼
+3259:\c\­TWENTY NINE
+325A:\c\­THIRTY
+325B:\c\­THIRTY ONE
+325C:\c\­THIRTY TWO
+325D:\c\­THIRTY THREE
+325E:\c\­THIRTY FOUR
+325F:\c\­THIRTY FIVE
+3260:\c\e KIYEOK
+3261:\c\e N\ÆN
+3262:\c\e TIKEUT
+3263:\c\e R\ÆL
+3264:\c\e M\ÆM
+3265:\c\e P\ÆP
+3266:\c\e SIOS
+3267:\c\e \ÆNG
+3268:\c\e C\ÆC
+3269:\c\e CH\ÆCH
+326A:\c\e KH\ÆKH
+326B:\c\e TH\ÆTH
+326C:\c\e PH\ÆPH
+326D:\c\e H\ÆH
+326E:\c\e KIYEOK A
+326F:\c\e N\ÆN A
+3270:\c\e TIKEUT A
+3271:\c\e R\ÆL A
+3272:\c\e M\ÆM A
+3273:\c\e P\ÆP A
+3274:\c\e SIOS A
+3275:\c\e \ÆNG A
+3276:\c\e C\ÆC A
+3277:\c\e CH\ÆCH A
+3278:\c\e KH\ÆKH A
+3279:\c\e TH\ÆTH A
+327A:\c\e PH\ÆPH A
+327B:\c\e H\ÆH A
+327F:KOREAN STANDARD \
+3280:\c\8 ONE
+3281:\c\8 TWO
+3282:\c\8 THREE
+3283:\c\8 FOUR
+3284:\c\8 FIVE
+3285:\c\8 SIX
+3286:\c\8 SEVEN
+3287:\c\8 E\¼
+3288:\c\8 NINE
+3289:\c\8 TEN
+328A:\c\8 MOON
+328B:\c\8 FIRE
+328C:\c\8 WATER
+328D:\c\8 WOOD
+328E:\c\8 METAL
+328F:\c\8 EARTH
+3290:\c\8 SUN
+3291:\c\8 STOCK
+3292:\c\8 HAVE
+3293:\c\8 SOCIETY
+3294:\c\8 NAME
+3295:\c\8 SPECIAL
+3296:\c\8 FINANCIAL
+3297:\c\8 CONGRATUL\”
+3298:\c\8 LABOR
+3299:\c\8 SECRET
+329A:\c\8 MALE
+329B:\c\8 FEMALE
+329C:\c\8 SUITABLE
+329D:\c\8 EXCELLENT
+329E:\c\8 PRINT
+329F:\c\8 ATTENTION
+32A0:\c\8 ITEM
+32A1:\c\8 REST
+32A2:\c\8 COPY
+32A3:\c\8 CORRECT
+32A4:\c\8 HIGH
+32A5:\c\8 CENTRE
+32A6:\c\8 LOW
+32A7:\c\8 \‰
+32A8:\c\8 \q
+32A9:\c\8 MEDICINE
+32AA:\c\8 RELIGION
+32AB:\c\8 STUDY
+32AC:\c\8 SUPERVISE
+32AD:\c\8 ENTERPRISE
+32AE:\c\8 RESOURCE
+32AF:\c\8 ALLIANCE
+32B0:\c\8 N\¼
+32B1:\c\­THIRTY SIX
+32B2:\c\­THIRTY SEVEN
+32B3:\c\­THIRTY E\¼
+32B4:\c\­THIRTY NINE
+32B5:\c\­FORTY
+32B6:\c\­FORTY ONE
+32B7:\c\­FORTY TWO
+32B8:\c\­FORTY THREE
+32B9:\c\­FORTY FOUR
+32BA:\c\­FORTY FIVE
+32BB:\c\­FORTY SIX
+32BC:\c\­FORTY SEVEN
+32BD:\c\­FORTY E\¼
+32BE:\c\­FORTY NINE
+32BF:\c\­FIFTY
+32C0:\_JANUARY
+32C1:\_FEBRUARY
+32C2:\_MARCH
+32C3:\_APRIL
+32C4:\_MAY
+32C5:\_JUNE
+32C6:\_JULY
+32C7:\_AUGUST
+32C8:\_SEPTEMBER
+32C9:\_OCTOBER
+32CA:\_NOVEMBER
+32CB:\_DECEMBER
+32D0:\c\n A
+32D1:\c\n I
+32D2:\c\n U
+32D3:\c\n E
+32D4:\c\n O
+32D5:\c\n KA
+32D6:\c\n KI
+32D7:\c\n KU
+32D8:\c\n KE
+32D9:\c\n KO
+32DA:\c\n SA
+32DB:\c\n SI
+32DC:\c\n SU
+32DD:\c\n SE
+32DE:\c\n SO
+32DF:\c\n TA
+32E0:\c\n TI
+32E1:\c\n TU
+32E2:\c\n TE
+32E3:\c\n TO
+32E4:\c\n NA
+32E5:\c\n NI
+32E6:\c\n NU
+32E7:\c\n NE
+32E8:\c\n NO
+32E9:\c\n HA
+32EA:\c\n HI
+32EB:\c\n HU
+32EC:\c\n HE
+32ED:\c\n HO
+32EE:\c\n MA
+32EF:\c\n MI
+32F0:\c\n MU
+32F1:\c\n ME
+32F2:\c\n MO
+32F3:\c\n YA
+32F4:\c\n YU
+32F5:\c\n YO
+32F6:\c\n RA
+32F7:\c\n RI
+32F8:\c\n RU
+32F9:\c\n RE
+32FA:\c\n RO
+32FB:\c\n WA
+32FC:\c\n WI
+32FD:\c\n WE
+32FE:\c\n WO
+3300:\rAPAATO
+3301:\rARUHUA
+3302:\rANPEA
+3303:\rAARU
+3304:\rIN\ôU
+3305:\rINTI
+3306:\rUON
+3307:\rESUKUUDO
+3308:\rEEKAA
+3309:\rONSU
+330A:\rOOMU
+330B:\rKAIRI
+330C:\rKARATTO
+330D:\rKARORII
+330E:\rGARON
+330F:\rGANMA
+3310:\rGIGA
+3311:\rGINII
+3312:\rKYURII
+3313:\rGIRUDAA
+3314:\rKIRO
+3315:\rKIROGURAMU
+3316:\rKIROMEETORU
+3317:\rKIROWATTO
+3318:\rGURAMU
+3319:\rGURAMUTON
+331A:\rKURUZEIRO
+331B:\rKUROONE
+331C:\rKEESU
+331D:\rKORUNA
+331E:\rKOOPO
+331F:\rSAIKURU
+3320:\rSANTIIMU
+3321:\rSIR\ôU
+3322:\rSENTI
+3323:\rSENTO
+3324:\rDAASU
+3325:\rDESI
+3326:\rDORU
+3327:\rTON
+3328:\rNANO
+3329:\rNOTTO
+332A:\rHAITU
+332B:\rPAASENTO
+332C:\rPAATU
+332D:\rBAARERU
+332E:\rPIASUTORU
+332F:\rPIKURU
+3330:\rPIKO
+3331:\rBIRU
+3332:\rHUARADDO
+3333:\rHUIITO
+3334:\rBUSSYERU
+3335:\rHURAN
+3336:\rHEKUTAARU
+3337:\rPESO
+3338:\rPENIHI
+3339:\rHERUTU
+333A:\rPENSU
+333B:\rPEEZI
+333C:\rBEETA
+333D:\rPOINTO
+333E:\rBORUTO
+333F:\rHON
+3340:\rPONDO
+3341:\rHOORU
+3342:\rHOON
+3343:\rMAIKURO
+3344:\rMAIRU
+3345:\rMAHHA
+3346:\rMARUKU
+3347:\rMANSYON
+3348:\rMIKURON
+3349:\rMIRI
+334A:\rMIRIBAARU
+334B:\rMEGA
+334C:\rMEGATON
+334D:\rMEETORU
+334E:\rYAADO
+334F:\rYAARU
+3350:\rYUAN
+3351:\rRITTORU
+3352:\rRIRA
+3353:\rRUPII
+3354:\rRUUBURU
+3355:\rREMU
+3356:\rRENTOGEN
+3357:\rWATTO
+3358:\_HOUR ZERO
+3359:\_HOUR ONE
+335A:\_HOUR TWO
+335B:\_HOUR THREE
+335C:\_HOUR FOUR
+335D:\_HOUR FIVE
+335E:\_HOUR SIX
+335F:\_HOUR SEVEN
+3360:\_HOUR E\¼
+3361:\_HOUR NINE
+3362:\_HOUR TEN
+3363:\_HOUR ELEVEN
+3364:\_HOUR TWELVE
+3365:\_HOUR THIRTEEN
+3366:\_HOUR FOURTEEN
+3367:\_HOUR FIFTEEN
+3368:\_HOUR SIXTEEN
+3369:\_HOUR SEVENTEEN
+336A:\_HOUR E\¼EEN
+336B:\_HOUR NINETEEN
+336C:\_HOUR TWENTY
+336D:\_HOUR TWENTY-ONE
+336E:\_HOUR TWENTY-TWO
+336F:\_HOUR TWENTY-THREE
+3370:\_HOUR TWENTY-FOUR
+3371:\rHPA
+3372:\rDA
+3373:\rAU
+3374:\rBAR
+3375:\rOV
+3376:\rPC
+337B:\rERA NAME HEISEI
+337C:\rERA NAME SYOUWA
+337D:\rERA NAME TAISYOU
+337E:\rERA NAME MEIZI
+337F:\rCORPOR\”
+3380:\rPA AMPS
+3381:\rNA
+3382:\rMU A
+3383:\rMA
+3384:\rKA
+3385:\rKB
+3386:\rMB
+3387:\rGB
+3388:\rCAL
+3389:\rKCAL
+338A:\rPF
+338B:\rNF
+338C:\rMU F
+338D:\rMU G
+338E:\rMG
+338F:\rKG
+3390:\rHZ
+3391:\rKHZ
+3392:\rMHZ
+3393:\rGHZ
+3394:\rTHZ
+3395:\rMU L
+3396:\rML
+3397:\rDL
+3398:\rKL
+3399:\rFM
+339A:\rNM
+339B:\rMU M
+339C:\rMM
+339D:\rCM
+339E:\rKM
+339F:\rMM \ýD
+33A0:\rCM \ýD
+33A1:\rM \ýD
+33A2:\rKM \ýD
+33A3:\rMM CUBED
+33A4:\rCM CUBED
+33A5:\rM CUBED
+33A6:\rKM CUBED
+33A7:\rM OVER S
+33A8:\rM OVER S \ýD
+33A9:\rPA
+33AA:\rKPA
+33AB:\rMPA
+33AC:\rGPA
+33AD:\rRAD
+33AE:\rRAD OVER S
+33AF:\rRAD OVER S \ýD
+33B0:\rPS
+33B1:\rNS
+33B2:\rMU S
+33B3:\rMS
+33B4:\rPV
+33B5:\rNV
+33B6:\rMU V
+33B7:\rMV
+33B8:\rKV
+33B9:\rMV MEGA
+33BA:\rPW
+33BB:\rNW
+33BC:\rMU W
+33BD:\rMW
+33BE:\rKW
+33BF:\rMW MEGA
+33C0:\rK OHM
+33C1:\rM OHM
+33C2:\rAM
+33C3:\rBQ
+33C4:\rCC
+33C5:\rCD
+33C6:\rC OVER KG
+33C7:\rCO
+33C8:\rDB
+33C9:\rGY
+33CA:\rHA
+33CB:\rHP
+33CC:\rIN
+33CD:\rKK
+33CE:\rKM\I
+33CF:\rKT
+33D0:\rLM
+33D1:\rLN
+33D2:\rLOG
+33D3:\rLX
+33D4:\rMB\N
+33D5:\rMIL
+33D6:\rMOL
+33D7:\rPH
+33D8:\rPM
+33D9:\rPPM
+33DA:\rPR
+33DB:\rSR
+33DC:\rSV
+33DD:\rWB
+33E0:\_DAY ONE
+33E1:\_DAY TWO
+33E2:\_DAY THREE
+33E3:\_DAY FOUR
+33E4:\_DAY FIVE
+33E5:\_DAY SIX
+33E6:\_DAY SEVEN
+33E7:\_DAY E\¼
+33E8:\_DAY NINE
+33E9:\_DAY TEN
+33EA:\_DAY ELEVEN
+33EB:\_DAY TWELVE
+33EC:\_DAY THIRTEEN
+33ED:\_DAY FOURTEEN
+33EE:\_DAY FIFTEEN
+33EF:\_DAY SIXTEEN
+33F0:\_DAY SEVENTEEN
+33F1:\_DAY E\¼EEN
+33F2:\_DAY NINETEEN
+33F3:\_DAY TWENTY
+33F4:\_DAY TWENTY-ONE
+33F5:\_DAY TWENTY-TWO
+33F6:\_DAY TWENTY-THREE
+33F7:\_DAY TWENTY-FOUR
+33F8:\_DAY TWENTY-FIVE
+33F9:\_DAY TWENTY-SIX
+33FA:\_DAY TWENTY-SEVEN
+33FB:\_DAY TWENTY-E\¼
+33FC:\_DAY TWENTY-NINE
+33FD:\_DAY THIRTY
+33FE:\_DAY THIRTY-ONE
+3400-4DB5:<CJK Ideograph Extension A>
+4E00-9FA5:<CJK Ideograph>
+A000:\ZIT
+A001:\ZIX
+A002:\ZI
+A003:\ZIP
+A004:\ZIET
+A005:\ZIEX
+A006:\ZIE
+A007:\ZIEP
+A008:\ZAT
+A009:\ZAX
+A00A:\ZA
+A00B:\ZAP
+A00C:\ZUOX
+A00D:\ZUO
+A00E:\ZUOP
+A00F:\ZOT
+A010:\ZOX
+A011:\ZO
+A012:\ZOP
+A013:\ZEX
+A014:\ZE
+A015:\ZWU
+A016:\ZBIT
+A017:\ZBIX
+A018:\ZBI
+A019:\ZBIP
+A01A:\ZBIET
+A01B:\ZBIEX
+A01C:\ZBIE
+A01D:\ZBIEP
+A01E:\ZBAT
+A01F:\ZBAX
+A020:\ZBA
+A021:\ZBAP
+A022:\ZBUOX
+A023:\ZBUO
+A024:\ZBUOP
+A025:\ZBOT
+A026:\ZBOX
+A027:\ZBO
+A028:\ZBOP
+A029:\ZBEX
+A02A:\ZBE
+A02B:\ZBEP
+A02C:\ZBUT
+A02D:\ZBUX
+A02E:\ZBU
+A02F:\ZBUP
+A030:\ZBURX
+A031:\ZBUR
+A032:\ZBYT
+A033:\ZBYX
+A034:\ZBY
+A035:\ZBYP
+A036:\ZBYRX
+A037:\ZBYR
+A038:\ZPIT
+A039:\ZPIX
+A03A:\ZPI
+A03B:\ZPIP
+A03C:\ZPIEX
+A03D:\ZPIE
+A03E:\ZPIEP
+A03F:\ZPAT
+A040:\ZPAX
+A041:\ZPA
+A042:\ZPAP
+A043:\ZPUOX
+A044:\ZPUO
+A045:\ZPUOP
+A046:\ZPOT
+A047:\ZPOX
+A048:\ZPO
+A049:\ZPOP
+A04A:\ZPUT
+A04B:\ZPUX
+A04C:\ZPU
+A04D:\ZPUP
+A04E:\ZPURX
+A04F:\ZPUR
+A050:\ZPYT
+A051:\ZPYX
+A052:\ZPY
+A053:\ZPYP
+A054:\ZPYRX
+A055:\ZPYR
+A056:\ZBBIT
+A057:\ZBBIX
+A058:\ZBBI
+A059:\ZBBIP
+A05A:\ZBBIET
+A05B:\ZBBIEX
+A05C:\ZBBIE
+A05D:\ZBBIEP
+A05E:\ZBBAT
+A05F:\ZBBAX
+A060:\ZBBA
+A061:\ZBBAP
+A062:\ZBBUOX
+A063:\ZBBUO
+A064:\ZBBUOP
+A065:\ZBBOT
+A066:\ZBBOX
+A067:\ZBBO
+A068:\ZBBOP
+A069:\ZBBEX
+A06A:\ZBBE
+A06B:\ZBBEP
+A06C:\ZBBUT
+A06D:\ZBBUX
+A06E:\ZBBU
+A06F:\ZBBUP
+A070:\ZBBURX
+A071:\ZBBUR
+A072:\ZBBYT
+A073:\ZBBYX
+A074:\ZBBY
+A075:\ZBBYP
+A076:\ÿBIT
+A077:\ÿBIX
+A078:\ÿBI
+A079:\ÿBIP
+A07A:\ÿBIEX
+A07B:\ÿBIE
+A07C:\ÿBIEP
+A07D:\ÿBAT
+A07E:\ÿBAX
+A07F:\ÿBA
+A080:\ÿBAP
+A081:\ÿBOT
+A082:\ÿBOX
+A083:\ÿBO
+A084:\ÿBOP
+A085:\ÿBUT
+A086:\ÿBUX
+A087:\ÿBU
+A088:\ÿBUP
+A089:\ÿBURX
+A08A:\ÿBUR
+A08B:\ÿBYT
+A08C:\ÿBYX
+A08D:\ÿBY
+A08E:\ÿBYP
+A08F:\ÿBYRX
+A090:\ÿBYR
+A091:\ZHMIT
+A092:\ZHMIX
+A093:\ZHMI
+A094:\ZHMIP
+A095:\ZHMIEX
+A096:\ZHMIE
+A097:\ZHMIEP
+A098:\ZHMAT
+A099:\ZHMAX
+A09A:\ZHMA
+A09B:\ZHMAP
+A09C:\ZHMUOX
+A09D:\ZHMUO
+A09E:\ZHMUOP
+A09F:\ZHMOT
+A0A0:\ZHMOX
+A0A1:\ZHMO
+A0A2:\ZHMOP
+A0A3:\ZHMUT
+A0A4:\ZHMUX
+A0A5:\ZHMU
+A0A6:\ZHMUP
+A0A7:\ZHMURX
+A0A8:\ZHMUR
+A0A9:\ZHMYX
+A0AA:\ZHMY
+A0AB:\ZHMYP
+A0AC:\ZHMYRX
+A0AD:\ZHMYR
+A0AE:\ZMIT
+A0AF:\ZMIX
+A0B0:\ZMI
+A0B1:\ZMIP
+A0B2:\ZMIEX
+A0B3:\ZMIE
+A0B4:\ZMIEP
+A0B5:\ZMAT
+A0B6:\ZMAX
+A0B7:\ZMA
+A0B8:\ZMAP
+A0B9:\ZMUOT
+A0BA:\ZMUOX
+A0BB:\ZMUO
+A0BC:\ZMUOP
+A0BD:\ZMOT
+A0BE:\ZMOX
+A0BF:\ZMO
+A0C0:\ZMOP
+A0C1:\ZMEX
+A0C2:\ZME
+A0C3:\ZMUT
+A0C4:\ZMUX
+A0C5:\ZMU
+A0C6:\ZMUP
+A0C7:\ZMURX
+A0C8:\ZMUR
+A0C9:\ZMYT
+A0CA:\ZMYX
+A0CB:\ZMY
+A0CC:\ZMYP
+A0CD:\ZFIT
+A0CE:\ZFIX
+A0CF:\ZFI
+A0D0:\ZFIP
+A0D1:\ZFAT
+A0D2:\ZFAX
+A0D3:\ZFA
+A0D4:\ZFAP
+A0D5:\ZFOX
+A0D6:\ZFO
+A0D7:\ZFOP
+A0D8:\ZFUT
+A0D9:\ZFUX
+A0DA:\ZFU
+A0DB:\ZFUP
+A0DC:\ZFURX
+A0DD:\ZFUR
+A0DE:\ZFYT
+A0DF:\ZFYX
+A0E0:\ZFY
+A0E1:\ZFYP
+A0E2:\ZVIT
+A0E3:\ZVIX
+A0E4:\ZVI
+A0E5:\ZVIP
+A0E6:\ZVIET
+A0E7:\ZVIEX
+A0E8:\ZVIE
+A0E9:\ZVIEP
+A0EA:\ZVAT
+A0EB:\ZVAX
+A0EC:\ZVA
+A0ED:\ZVAP
+A0EE:\ZVOT
+A0EF:\ZVOX
+A0F0:\ZVO
+A0F1:\ZVOP
+A0F2:\ZVEX
+A0F3:\ZVEP
+A0F4:\ZVUT
+A0F5:\ZVUX
+A0F6:\ZVU
+A0F7:\ZVUP
+A0F8:\ZVURX
+A0F9:\ZVUR
+A0FA:\ZVYT
+A0FB:\ZVYX
+A0FC:\ZVY
+A0FD:\ZVYP
+A0FE:\ZVYRX
+A0FF:\ZVYR
+A100:\ZDIT
+A101:\ZDIX
+A102:\ZDI
+A103:\ZDIP
+A104:\ZDIEX
+A105:\ZDIE
+A106:\ZDIEP
+A107:\ZDAT
+A108:\ZDAX
+A109:\ZDA
+A10A:\ZDAP
+A10B:\ZDUOX
+A10C:\ZDUO
+A10D:\ZDOT
+A10E:\ZDOX
+A10F:\ZDO
+A110:\ZDOP
+A111:\ZDEX
+A112:\ZDE
+A113:\ZDEP
+A114:\ZDUT
+A115:\ZDUX
+A116:\ZDU
+A117:\ZDUP
+A118:\ZDURX
+A119:\ZDUR
+A11A:\ZTIT
+A11B:\ZTIX
+A11C:\ZTI
+A11D:\ZTIP
+A11E:\ZTIEX
+A11F:\ZTIE
+A120:\ZTIEP
+A121:\ZTAT
+A122:\ZTAX
+A123:\ZTA
+A124:\ZTAP
+A125:\ZTUOT
+A126:\ZTUOX
+A127:\ZTUO
+A128:\ZTUOP
+A129:\ZTOT
+A12A:\ZTOX
+A12B:\ZTO
+A12C:\ZTOP
+A12D:\ZTEX
+A12E:\ZTE
+A12F:\ZTEP
+A130:\ZTUT
+A131:\ZTUX
+A132:\ZTU
+A133:\ZTUP
+A134:\ZTURX
+A135:\ZTUR
+A136:\ZDDIT
+A137:\ZDDIX
+A138:\ZDDI
+A139:\ZDDIP
+A13A:\ZDDIEX
+A13B:\ZDDIE
+A13C:\ZDDIEP
+A13D:\ZDDAT
+A13E:\ZDDAX
+A13F:\ZDDA
+A140:\ZDDAP
+A141:\ZDDUOX
+A142:\ZDDUO
+A143:\ZDDUOP
+A144:\ZDDOT
+A145:\ZDDOX
+A146:\ZDDO
+A147:\ZDDOP
+A148:\ZDDEX
+A149:\ZDDE
+A14A:\ZDDEP
+A14B:\ZDDUT
+A14C:\ZDDUX
+A14D:\ZDDU
+A14E:\ZDDUP
+A14F:\ZDDURX
+A150:\ZDDUR
+A151:\ÿDIT
+A152:\ÿDIX
+A153:\ÿDI
+A154:\ÿDIP
+A155:\ÿDIEX
+A156:\ÿDIE
+A157:\ÿDAT
+A158:\ÿDAX
+A159:\ÿDA
+A15A:\ÿDAP
+A15B:\ÿDOT
+A15C:\ÿDOX
+A15D:\ÿDO
+A15E:\ÿDOP
+A15F:\ÿDEX
+A160:\ÿDE
+A161:\ÿDEP
+A162:\ÿDUT
+A163:\ÿDUX
+A164:\ÿDU
+A165:\ÿDUP
+A166:\ÿDURX
+A167:\ÿDUR
+A168:\ZHNIT
+A169:\ZHNIX
+A16A:\ZHNI
+A16B:\ZHNIP
+A16C:\ZHNIET
+A16D:\ZHNIEX
+A16E:\ZHNIE
+A16F:\ZHNIEP
+A170:\ZHNAT
+A171:\ZHNAX
+A172:\ZHNA
+A173:\ZHNAP
+A174:\ZHNUOX
+A175:\ZHNUO
+A176:\ZHNOT
+A177:\ZHNOX
+A178:\ZHNOP
+A179:\ZHNEX
+A17A:\ZHNE
+A17B:\ZHNEP
+A17C:\ZHNUT
+A17D:\ÿIT
+A17E:\ÿIX
+A17F:\ÿI
+A180:\ÿIP
+A181:\ÿIEX
+A182:\ÿIE
+A183:\ÿIEP
+A184:\ÿAX
+A185:\ÿA
+A186:\ÿAP
+A187:\ÿUOX
+A188:\ÿUO
+A189:\ÿUOP
+A18A:\ÿOT
+A18B:\ÿOX
+A18C:\ÿO
+A18D:\ÿOP
+A18E:\ÿEX
+A18F:\ÿE
+A190:\ÿEP
+A191:\ÿUT
+A192:\ÿUX
+A193:\ÿU
+A194:\ÿUP
+A195:\ÿURX
+A196:\ÿUR
+A197:\ZHLIT
+A198:\ZHLIX
+A199:\ZHLI
+A19A:\ZHLIP
+A19B:\ZHLIEX
+A19C:\ZHLIE
+A19D:\ZHLIEP
+A19E:\ZHLAT
+A19F:\ZHLAX
+A1A0:\ZHLA
+A1A1:\ZHLAP
+A1A2:\ZHLUOX
+A1A3:\ZHLUO
+A1A4:\ZHLUOP
+A1A5:\ZHLOX
+A1A6:\ZHLO
+A1A7:\ZHLOP
+A1A8:\ZHLEX
+A1A9:\ZHLE
+A1AA:\ZHLEP
+A1AB:\ZHLUT
+A1AC:\ZHLUX
+A1AD:\ZHLU
+A1AE:\ZHLUP
+A1AF:\ZHLURX
+A1B0:\ZHLUR
+A1B1:\ZHLYT
+A1B2:\ZHLYX
+A1B3:\ZHLY
+A1B4:\ZHLYP
+A1B5:\ZHLYRX
+A1B6:\ZHLYR
+A1B7:\ZLIT
+A1B8:\ZLIX
+A1B9:\ZLI
+A1BA:\ZLIP
+A1BB:\ZLIET
+A1BC:\ZLIEX
+A1BD:\ZLIE
+A1BE:\ZLIEP
+A1BF:\ZLAT
+A1C0:\ZLAX
+A1C1:\ZLA
+A1C2:\ZLAP
+A1C3:\ZLUOT
+A1C4:\ZLUOX
+A1C5:\ZLUO
+A1C6:\ZLUOP
+A1C7:\ZLOT
+A1C8:\ZLOX
+A1C9:\ZLO
+A1CA:\ZLOP
+A1CB:\ZLEX
+A1CC:\ZLE
+A1CD:\ZLEP
+A1CE:\ZLUT
+A1CF:\ZLUX
+A1D0:\ZLU
+A1D1:\ZLUP
+A1D2:\ZLURX
+A1D3:\ZLUR
+A1D4:\ZLYT
+A1D5:\ZLYX
+A1D6:\ZLY
+A1D7:\ZLYP
+A1D8:\ZLYRX
+A1D9:\ZLYR
+A1DA:\ZGIT
+A1DB:\ZGIX
+A1DC:\ZGI
+A1DD:\ZGIP
+A1DE:\ZGIET
+A1DF:\ZGIEX
+A1E0:\ZGIE
+A1E1:\ZGIEP
+A1E2:\ZGAT
+A1E3:\ZGAX
+A1E4:\ZGA
+A1E5:\ZGAP
+A1E6:\ZGUOT
+A1E7:\ZGUOX
+A1E8:\ZGUO
+A1E9:\ZGUOP
+A1EA:\ZGOT
+A1EB:\ZGOX
+A1EC:\ZGO
+A1ED:\ZGOP
+A1EE:\ZGET
+A1EF:\ZGEX
+A1F0:\ZGE
+A1F1:\ZGEP
+A1F2:\ZGUT
+A1F3:\ZGUX
+A1F4:\ZGU
+A1F5:\ZGUP
+A1F6:\ZGURX
+A1F7:\ZGUR
+A1F8:\ZKIT
+A1F9:\ZKIX
+A1FA:\ZKI
+A1FB:\ZKIP
+A1FC:\ZKIEX
+A1FD:\ZKIE
+A1FE:\ZKIEP
+A1FF:\ZKAT
+A200:\ZKAX
+A201:\ZKA
+A202:\ZKAP
+A203:\ZKUOX
+A204:\ZKUO
+A205:\ZKUOP
+A206:\ZKOT
+A207:\ZKOX
+A208:\ZKO
+A209:\ZKOP
+A20A:\ZKET
+A20B:\ZKEX
+A20C:\ZKE
+A20D:\ZKEP
+A20E:\ZKUT
+A20F:\ZKUX
+A210:\ZKU
+A211:\ZKUP
+A212:\ZKURX
+A213:\ZKUR
+A214:\ZGGIT
+A215:\ZGGIX
+A216:\ZGGI
+A217:\ZGGIEX
+A218:\ZGGIE
+A219:\ZGGIEP
+A21A:\ZGGAT
+A21B:\ZGGAX
+A21C:\ZGGA
+A21D:\ZGGAP
+A21E:\ZGGUOT
+A21F:\ZGGUOX
+A220:\ZGGUO
+A221:\ZGGUOP
+A222:\ZGGOT
+A223:\ZGGOX
+A224:\ZGGO
+A225:\ZGGOP
+A226:\ZGGET
+A227:\ZGGEX
+A228:\ZGGE
+A229:\ZGGEP
+A22A:\ZGGUT
+A22B:\ZGGUX
+A22C:\ZGGU
+A22D:\ZGGUP
+A22E:\ZGGURX
+A22F:\ZGGUR
+A230:\ZMGIEX
+A231:\ZMGIE
+A232:\ZMGAT
+A233:\ZMGAX
+A234:\ZMGA
+A235:\ZMGAP
+A236:\ZMGUOX
+A237:\ZMGUO
+A238:\ZMGUOP
+A239:\ZMGOT
+A23A:\ZMGOX
+A23B:\ZMGO
+A23C:\ZMGOP
+A23D:\ZMGEX
+A23E:\ZMGE
+A23F:\ZMGEP
+A240:\ZMGUT
+A241:\ZMGUX
+A242:\ZMGU
+A243:\ZMGUP
+A244:\ZMGURX
+A245:\ZMGUR
+A246:\ZHXIT
+A247:\ZHXIX
+A248:\ZHXI
+A249:\ZHXIP
+A24A:\ZHXIET
+A24B:\ZHXIEX
+A24C:\ZHXIE
+A24D:\ZHXIEP
+A24E:\ZHXAT
+A24F:\ZHXAX
+A250:\ZHXA
+A251:\ZHXAP
+A252:\ZHXUOT
+A253:\ZHXUOX
+A254:\ZHXUO
+A255:\ZHXUOP
+A256:\ZHXOT
+A257:\ZHXOX
+A258:\ZHXO
+A259:\ZHXOP
+A25A:\ZHXEX
+A25B:\ZHXE
+A25C:\ZHXEP
+A25D:\ÿGIEX
+A25E:\ÿGIE
+A25F:\ÿGIEP
+A260:\ÿGAT
+A261:\ÿGAX
+A262:\ÿGA
+A263:\ÿGAP
+A264:\ÿGUOT
+A265:\ÿGUOX
+A266:\ÿGUO
+A267:\ÿGOT
+A268:\ÿGOX
+A269:\ÿGO
+A26A:\ÿGOP
+A26B:\ÿGEX
+A26C:\ÿGE
+A26D:\ÿGEP
+A26E:\ZHIT
+A26F:\ZHIEX
+A270:\ZHIE
+A271:\ZHAT
+A272:\ZHAX
+A273:\ZHA
+A274:\ZHAP
+A275:\ZHUOT
+A276:\ZHUOX
+A277:\ZHUO
+A278:\ZHUOP
+A279:\ZHOT
+A27A:\ZHOX
+A27B:\ZHO
+A27C:\ZHOP
+A27D:\ZHEX
+A27E:\ZHE
+A27F:\ZHEP
+A280:\ZWAT
+A281:\ZWAX
+A282:\ZWA
+A283:\ZWAP
+A284:\ZWUOX
+A285:\ZWUO
+A286:\ZWUOP
+A287:\ZWOX
+A288:\ZWO
+A289:\ZWOP
+A28A:\ZWEX
+A28B:\ZWE
+A28C:\ZWEP
+A28D:\ZZIT
+A28E:\ZZIX
+A28F:\ZZI
+A290:\ZZIP
+A291:\ZZIEX
+A292:\ZZIE
+A293:\ZZIEP
+A294:\ZZAT
+A295:\ZZAX
+A296:\ZZA
+A297:\ZZAP
+A298:\ZZUOX
+A299:\ZZUO
+A29A:\ZZUOP
+A29B:\ZZOT
+A29C:\ZZOX
+A29D:\ZZO
+A29E:\ZZOP
+A29F:\ZZEX
+A2A0:\ZZE
+A2A1:\ZZEP
+A2A2:\ZZUT
+A2A3:\ZZUX
+A2A4:\ZZU
+A2A5:\ZZUP
+A2A6:\ZZURX
+A2A7:\ZZUR
+A2A8:\ZZYT
+A2A9:\ZZYX
+A2AA:\ZZY
+A2AB:\ZZYP
+A2AC:\ZZYRX
+A2AD:\ZZYR
+A2AE:\ZCIT
+A2AF:\ZCIX
+A2B0:\ZCI
+A2B1:\ZCIP
+A2B2:\ZCIET
+A2B3:\ZCIEX
+A2B4:\ZCIE
+A2B5:\ZCIEP
+A2B6:\ZCAT
+A2B7:\ZCAX
+A2B8:\ZCA
+A2B9:\ZCAP
+A2BA:\ZCUOX
+A2BB:\ZCUO
+A2BC:\ZCUOP
+A2BD:\ZCOT
+A2BE:\ZCOX
+A2BF:\ZCO
+A2C0:\ZCOP
+A2C1:\ZCEX
+A2C2:\ZCE
+A2C3:\ZCEP
+A2C4:\ZCUT
+A2C5:\ZCUX
+A2C6:\ZCU
+A2C7:\ZCUP
+A2C8:\ZCURX
+A2C9:\ZCUR
+A2CA:\ZCYT
+A2CB:\ZCYX
+A2CC:\ZCY
+A2CD:\ZCYP
+A2CE:\ZCYRX
+A2CF:\ZCYR
+A2D0:\ZZZIT
+A2D1:\ZZZIX
+A2D2:\ZZZI
+A2D3:\ZZZIP
+A2D4:\ZZZIET
+A2D5:\ZZZIEX
+A2D6:\ZZZIE
+A2D7:\ZZZIEP
+A2D8:\ZZZAT
+A2D9:\ZZZAX
+A2DA:\ZZZA
+A2DB:\ZZZAP
+A2DC:\ZZZOX
+A2DD:\ZZZO
+A2DE:\ZZZOP
+A2DF:\ZZZEX
+A2E0:\ZZZE
+A2E1:\ZZZEP
+A2E2:\ZZZUX
+A2E3:\ZZZU
+A2E4:\ZZZUP
+A2E5:\ZZZURX
+A2E6:\ZZZUR
+A2E7:\ZZZYT
+A2E8:\ZZZYX
+A2E9:\ZZZY
+A2EA:\ZZZYP
+A2EB:\ZZZYRX
+A2EC:\ZZZYR
+A2ED:\ÿZIT
+A2EE:\ÿZIX
+A2EF:\ÿZI
+A2F0:\ÿZIP
+A2F1:\ÿZIEX
+A2F2:\ÿZIE
+A2F3:\ÿZIEP
+A2F4:\ÿZAT
+A2F5:\ÿZAX
+A2F6:\ÿZA
+A2F7:\ÿZAP
+A2F8:\ÿZUOX
+A2F9:\ÿZUO
+A2FA:\ÿZOX
+A2FB:\ÿZOP
+A2FC:\ÿZEX
+A2FD:\ÿZE
+A2FE:\ÿZUX
+A2FF:\ÿZU
+A300:\ÿZUP
+A301:\ÿZURX
+A302:\ÿZUR
+A303:\ÿZYT
+A304:\ÿZYX
+A305:\ÿZY
+A306:\ÿZYP
+A307:\ÿZYRX
+A308:\ÿZYR
+A309:\ZSIT
+A30A:\ZSIX
+A30B:\ZSI
+A30C:\ZSIP
+A30D:\ZSIEX
+A30E:\ZSIE
+A30F:\ZSIEP
+A310:\ZSAT
+A311:\ZSAX
+A312:\ZSA
+A313:\ZSAP
+A314:\ZSUOX
+A315:\ZSUO
+A316:\ZSUOP
+A317:\ZSOT
+A318:\ZSOX
+A319:\ZSO
+A31A:\ZSOP
+A31B:\ZSEX
+A31C:\ZSE
+A31D:\ZSEP
+A31E:\ZSUT
+A31F:\ZSUX
+A320:\ZSU
+A321:\ZSUP
+A322:\ZSURX
+A323:\ZSUR
+A324:\ZSYT
+A325:\ZSYX
+A326:\ZSY
+A327:\ZSYP
+A328:\ZSYRX
+A329:\ZSYR
+A32A:\ZSSIT
+A32B:\ZSSIX
+A32C:\ZSSI
+A32D:\ZSSIP
+A32E:\ZSSIEX
+A32F:\ZSSIE
+A330:\ZSSIEP
+A331:\ZSSAT
+A332:\ZSSAX
+A333:\ZSSA
+A334:\ZSSAP
+A335:\ZSSOT
+A336:\ZSSOX
+A337:\ZSSO
+A338:\ZSSOP
+A339:\ZSSEX
+A33A:\ZSSE
+A33B:\ZSSEP
+A33C:\ZSSUT
+A33D:\ZSSUX
+A33E:\ZSSU
+A33F:\ZSSUP
+A340:\ZSSYT
+A341:\ZSSYX
+A342:\ZSSY
+A343:\ZSSYP
+A344:\ZSSYRX
+A345:\ZSSYR
+A346:\ZZHAT
+A347:\ZZHAX
+A348:\ZZHA
+A349:\ZZHAP
+A34A:\ZZHUOX
+A34B:\ZZHUO
+A34C:\ZZHUOP
+A34D:\ZZHOT
+A34E:\ZZHOX
+A34F:\ZZHO
+A350:\ZZHOP
+A351:\ZZHET
+A352:\ZZHEX
+A353:\ZZHE
+A354:\ZZHEP
+A355:\ZZHUT
+A356:\ZZHUX
+A357:\ZZHU
+A358:\ZZHUP
+A359:\ZZHURX
+A35A:\ZZHUR
+A35B:\ZZHYT
+A35C:\ZZHYX
+A35D:\ZZHY
+A35E:\ZZHYP
+A35F:\ZZHYRX
+A360:\ZZHYR
+A361:\ZCHAT
+A362:\ZCHAX
+A363:\ZCHA
+A364:\ZCHAP
+A365:\ZCHUOT
+A366:\ZCHUOX
+A367:\ZCHUO
+A368:\ZCHUOP
+A369:\ZCHOT
+A36A:\ZCHOX
+A36B:\ZCHO
+A36C:\ZCHOP
+A36D:\ZCHET
+A36E:\ZCHEX
+A36F:\ZCHE
+A370:\ZCHEP
+A371:\ZCHUX
+A372:\ZCHU
+A373:\ZCHUP
+A374:\ZCHURX
+A375:\ZCHUR
+A376:\ZCHYT
+A377:\ZCHYX
+A378:\ZCHY
+A379:\ZCHYP
+A37A:\ZCHYRX
+A37B:\ZCHYR
+A37C:\ZRRAX
+A37D:\ZRRA
+A37E:\ZRRUOX
+A37F:\ZRRUO
+A380:\ZRROT
+A381:\ZRROX
+A382:\ZRRO
+A383:\ZRROP
+A384:\ZRRET
+A385:\ZRREX
+A386:\ZRRE
+A387:\ZRREP
+A388:\ZRRUT
+A389:\ZRRUX
+A38A:\ZRRU
+A38B:\ZRRUP
+A38C:\ZRRURX
+A38D:\ZRRUR
+A38E:\ZRRYT
+A38F:\ZRRYX
+A390:\ZRRY
+A391:\ZRRYP
+A392:\ZRRYRX
+A393:\ZRRYR
+A394:\ÿRAT
+A395:\ÿRAX
+A396:\ÿRA
+A397:\ÿRAP
+A398:\ÿROX
+A399:\ÿRO
+A39A:\ÿROP
+A39B:\ÿRET
+A39C:\ÿREX
+A39D:\ÿRE
+A39E:\ÿREP
+A39F:\ÿRUT
+A3A0:\ÿRUX
+A3A1:\ÿRU
+A3A2:\ÿRUP
+A3A3:\ÿRURX
+A3A4:\ÿRUR
+A3A5:\ÿRYT
+A3A6:\ÿRYX
+A3A7:\ÿRY
+A3A8:\ÿRYP
+A3A9:\ÿRYRX
+A3AA:\ÿRYR
+A3AB:\ZSHAT
+A3AC:\ZSHAX
+A3AD:\ZSHA
+A3AE:\ZSHAP
+A3AF:\ZSHUOX
+A3B0:\ZSHUO
+A3B1:\ZSHUOP
+A3B2:\ZSHOT
+A3B3:\ZSHOX
+A3B4:\ZSHO
+A3B5:\ZSHOP
+A3B6:\ZSHET
+A3B7:\ZSHEX
+A3B8:\ZSHE
+A3B9:\ZSHEP
+A3BA:\ZSHUT
+A3BB:\ZSHUX
+A3BC:\ZSHU
+A3BD:\ZSHUP
+A3BE:\ZSHURX
+A3BF:\ZSHUR
+A3C0:\ZSHYT
+A3C1:\ZSHYX
+A3C2:\ZSHY
+A3C3:\ZSHYP
+A3C4:\ZSHYRX
+A3C5:\ZSHYR
+A3C6:\ZRAT
+A3C7:\ZRAX
+A3C8:\ZRA
+A3C9:\ZRAP
+A3CA:\ZRUOX
+A3CB:\ZRUO
+A3CC:\ZRUOP
+A3CD:\ZROT
+A3CE:\ZROX
+A3CF:\ZRO
+A3D0:\ZROP
+A3D1:\ZREX
+A3D2:\ZRE
+A3D3:\ZREP
+A3D4:\ZRUT
+A3D5:\ZRUX
+A3D6:\ZRU
+A3D7:\ZRUP
+A3D8:\ZRURX
+A3D9:\ZRUR
+A3DA:\ZRYT
+A3DB:\ZRYX
+A3DC:\ZRY
+A3DD:\ZRYP
+A3DE:\ZRYRX
+A3DF:\ZRYR
+A3E0:\ZJIT
+A3E1:\ZJIX
+A3E2:\ZJI
+A3E3:\ZJIP
+A3E4:\ZJIET
+A3E5:\ZJIEX
+A3E6:\ZJIE
+A3E7:\ZJIEP
+A3E8:\ZJUOT
+A3E9:\ZJUOX
+A3EA:\ZJUO
+A3EB:\ZJUOP
+A3EC:\ZJOT
+A3ED:\ZJOX
+A3EE:\ZJO
+A3EF:\ZJOP
+A3F0:\ZJUT
+A3F1:\ZJUX
+A3F2:\ZJU
+A3F3:\ZJUP
+A3F4:\ZJURX
+A3F5:\ZJUR
+A3F6:\ZJYT
+A3F7:\ZJYX
+A3F8:\ZJY
+A3F9:\ZJYP
+A3FA:\ZJYRX
+A3FB:\ZJYR
+A3FC:\ZQIT
+A3FD:\ZQIX
+A3FE:\ZQI
+A3FF:\ZQIP
+A400:\ZQIET
+A401:\ZQIEX
+A402:\ZQIE
+A403:\ZQIEP
+A404:\ZQUOT
+A405:\ZQUOX
+A406:\ZQUO
+A407:\ZQUOP
+A408:\ZQOT
+A409:\ZQOX
+A40A:\ZQO
+A40B:\ZQOP
+A40C:\ZQUT
+A40D:\ZQUX
+A40E:\ZQU
+A40F:\ZQUP
+A410:\ZQURX
+A411:\ZQUR
+A412:\ZQYT
+A413:\ZQYX
+A414:\ZQY
+A415:\ZQYP
+A416:\ZQYRX
+A417:\ZQYR
+A418:\ZJJIT
+A419:\ZJJIX
+A41A:\ZJJI
+A41B:\ZJJIP
+A41C:\ZJJIET
+A41D:\ZJJIEX
+A41E:\ZJJIE
+A41F:\ZJJIEP
+A420:\ZJJUOX
+A421:\ZJJUO
+A422:\ZJJUOP
+A423:\ZJJOT
+A424:\ZJJOX
+A425:\ZJJO
+A426:\ZJJOP
+A427:\ZJJUT
+A428:\ZJJUX
+A429:\ZJJU
+A42A:\ZJJUP
+A42B:\ZJJURX
+A42C:\ZJJUR
+A42D:\ZJJYT
+A42E:\ZJJYX
+A42F:\ZJJY
+A430:\ZJJYP
+A431:\ÿJIT
+A432:\ÿJIX
+A433:\ÿJI
+A434:\ÿJIP
+A435:\ÿJIET
+A436:\ÿJIEX
+A437:\ÿJIE
+A438:\ÿJIEP
+A439:\ÿJUOX
+A43A:\ÿJUO
+A43B:\ÿJOT
+A43C:\ÿJOX
+A43D:\ÿJO
+A43E:\ÿJOP
+A43F:\ÿJUX
+A440:\ÿJU
+A441:\ÿJUP
+A442:\ÿJURX
+A443:\ÿJUR
+A444:\ÿJYT
+A445:\ÿJYX
+A446:\ÿJY
+A447:\ÿJYP
+A448:\ÿJYRX
+A449:\ÿJYR
+A44A:\ÿYIT
+A44B:\ÿYIX
+A44C:\ÿYI
+A44D:\ÿYIP
+A44E:\ÿYIET
+A44F:\ÿYIEX
+A450:\ÿYIE
+A451:\ÿYIEP
+A452:\ÿYUOX
+A453:\ÿYUO
+A454:\ÿYUOP
+A455:\ÿYOT
+A456:\ÿYOX
+A457:\ÿYO
+A458:\ÿYOP
+A459:\ÿYUT
+A45A:\ÿYUX
+A45B:\ÿYU
+A45C:\ÿYUP
+A45D:\ZXIT
+A45E:\ZXIX
+A45F:\ZXI
+A460:\ZXIP
+A461:\ZXIET
+A462:\ZXIEX
+A463:\ZXIE
+A464:\ZXIEP
+A465:\ZXUOX
+A466:\ZXUO
+A467:\ZXOT
+A468:\ZXOX
+A469:\ZXO
+A46A:\ZXOP
+A46B:\ZXYT
+A46C:\ZXYX
+A46D:\ZXY
+A46E:\ZXYP
+A46F:\ZXYRX
+A470:\ZXYR
+A471:\ZYIT
+A472:\ZYIX
+A473:\ZYI
+A474:\ZYIP
+A475:\ZYIET
+A476:\ZYIEX
+A477:\ZYIE
+A478:\ZYIEP
+A479:\ZYUOT
+A47A:\ZYUOX
+A47B:\ZYUO
+A47C:\ZYUOP
+A47D:\ZYOT
+A47E:\ZYOX
+A47F:\ZYO
+A480:\ZYOP
+A481:\ZYUT
+A482:\ZYUX
+A483:\ZYU
+A484:\ZYUP
+A485:\ZYURX
+A486:\ZYUR
+A487:\ZYYT
+A488:\ZYYX
+A489:\ZYY
+A48A:\ZYYP
+A48B:\ZYYRX
+A48C:\ZYYR
+A490:YI\vQOT
+A491:YI\vLI
+A492:YI\vKIT
+A493:YI\vNYIP
+A494:YI\vCYP
+A495:YI\vSSI
+A496:YI\vGGOP
+A497:YI\vGEP
+A498:YI\vMI
+A499:YI\vHXIT
+A49A:YI\vLYR
+A49B:YI\vBBUT
+A49C:YI\vMOP
+A49D:YI\vYO
+A49E:YI\vPUT
+A49F:YI\vHXUO
+A4A0:YI\vTAT
+A4A1:YI\vGA
+A4A2:YI\vZUP
+A4A3:YI\vCYT
+A4A4:YI\vDDUR
+A4A5:YI\vBUR
+A4A6:YI\vGGUO
+A4A7:YI\vNYOP
+A4A8:YI\vTU
+A4A9:YI\vOP
+A4AA:YI\vJJUT
+A4AB:YI\vZOT
+A4AC:YI\vPYT
+A4AD:YI\vHMO
+A4AE:YI\vYIT
+A4AF:YI\vVUR
+A4B0:YI\vSHY
+A4B1:YI\vVEP
+A4B2:YI\vZA
+A4B3:YI\vJO
+A4B4:YI\vNZUP
+A4B5:YI\vJJY
+A4B6:YI\vGOT
+A4B7:YI\vJJIE
+A4B8:YI\vWO
+A4B9:YI\vDU
+A4BA:YI\vSHUR
+A4BB:YI\vLIE
+A4BC:YI\vCY
+A4BD:YI\vCUOP
+A4BE:YI\vCIP
+A4BF:YI\vHXOP
+A4C0:YI\vSHAT
+A4C1:YI\vZUR
+A4C2:YI\vSHOP
+A4C3:YI\vCHE
+A4C4:YI\vZZIET
+A4C5:YI\vNBIE
+A4C6:YI\vKE
+AC00-D7A3:<Hangul Syllable>
+D800-DB7F:<Non Private Use High Surrogate>
+DB80-DBFF:<Private Use High Surrogate>
+DC00-DFFF:<Low Surrogate>
+E000-F8FF:<Private Use>
+F900:\ 00
+F901:\ 01
+F902:\ 02
+F903:\ 03
+F904:\ 04
+F905:\ 05
+F906:\ 06
+F907:\ 07
+F908:\ 08
+F909:\ 09
+F90A:\ 0A
+F90B:\ 0B
+F90C:\ 0C
+F90D:\ 0D
+F90E:\ 0E
+F90F:\ 0F
+F910:\ 10
+F911:\ 11
+F912:\ 12
+F913:\ 13
+F914:\ 14
+F915:\ 15
+F916:\ 16
+F917:\ 17
+F918:\ 18
+F919:\ 19
+F91A:\ 1A
+F91B:\ 1B
+F91C:\ 1C
+F91D:\ 1D
+F91E:\ 1E
+F91F:\ 1F
+F920:\ 20
+F921:\ 21
+F922:\ 22
+F923:\ 23
+F924:\ 24
+F925:\ 25
+F926:\ 26
+F927:\ 27
+F928:\ 28
+F929:\ 29
+F92A:\ 2A
+F92B:\ 2B
+F92C:\ 2C
+F92D:\ 2D
+F92E:\ 2E
+F92F:\ 2F
+F930:\ 30
+F931:\ 31
+F932:\ 32
+F933:\ 33
+F934:\ 34
+F935:\ 35
+F936:\ 36
+F937:\ 37
+F938:\ 38
+F939:\ 39
+F93A:\ 3A
+F93B:\ 3B
+F93C:\ 3C
+F93D:\ 3D
+F93E:\ 3E
+F93F:\ 3F
+F940:\ 40
+F941:\ 41
+F942:\ 42
+F943:\ 43
+F944:\ 44
+F945:\ 45
+F946:\ 46
+F947:\ 47
+F948:\ 48
+F949:\ 49
+F94A:\ 4A
+F94B:\ 4B
+F94C:\ 4C
+F94D:\ 4D
+F94E:\ 4E
+F94F:\ 4F
+F950:\ 50
+F951:\ 51
+F952:\ 52
+F953:\ 53
+F954:\ 54
+F955:\ 55
+F956:\ 56
+F957:\ 57
+F958:\ 58
+F959:\ 59
+F95A:\ 5A
+F95B:\ 5B
+F95C:\ 5C
+F95D:\ 5D
+F95E:\ 5E
+F95F:\ 5F
+F960:\ 60
+F961:\ 61
+F962:\ 62
+F963:\ 63
+F964:\ 64
+F965:\ 65
+F966:\ 66
+F967:\ 67
+F968:\ 68
+F969:\ 69
+F96A:\ 6A
+F96B:\ 6B
+F96C:\ 6C
+F96D:\ 6D
+F96E:\ 6E
+F96F:\ 6F
+F970:\ 70
+F971:\ 71
+F972:\ 72
+F973:\ 73
+F974:\ 74
+F975:\ 75
+F976:\ 76
+F977:\ 77
+F978:\ 78
+F979:\ 79
+F97A:\ 7A
+F97B:\ 7B
+F97C:\ 7C
+F97D:\ 7D
+F97E:\ 7E
+F97F:\ 7F
+F980:\ 80
+F981:\ 81
+F982:\ 82
+F983:\ 83
+F984:\ 84
+F985:\ 85
+F986:\ 86
+F987:\ 87
+F988:\ 88
+F989:\ 89
+F98A:\ 8A
+F98B:\ 8B
+F98C:\ 8C
+F98D:\ 8D
+F98E:\ 8E
+F98F:\ 8F
+F990:\ 90
+F991:\ 91
+F992:\ 92
+F993:\ 93
+F994:\ 94
+F995:\ 95
+F996:\ 96
+F997:\ 97
+F998:\ 98
+F999:\ 99
+F99A:\ 9A
+F99B:\ 9B
+F99C:\ 9C
+F99D:\ 9D
+F99E:\ 9E
+F99F:\ 9F
+F9A0:\ A0
+F9A1:\ A1
+F9A2:\ A2
+F9A3:\ A3
+F9A4:\ A4
+F9A5:\ A5
+F9A6:\ A6
+F9A7:\ A7
+F9A8:\ A8
+F9A9:\ A9
+F9AA:\ AA
+F9AB:\ AB
+F9AC:\ AC
+F9AD:\ AD
+F9AE:\ AE
+F9AF:\ AF
+F9B0:\ B0
+F9B1:\ B1
+F9B2:\ B2
+F9B3:\ B3
+F9B4:\ B4
+F9B5:\ B5
+F9B6:\ B6
+F9B7:\ B7
+F9B8:\ B8
+F9B9:\ B9
+F9BA:\ BA
+F9BB:\ BB
+F9BC:\ BC
+F9BD:\ BD
+F9BE:\ BE
+F9BF:\ BF
+F9C0:\ C0
+F9C1:\ C1
+F9C2:\ C2
+F9C3:\ C3
+F9C4:\ C4
+F9C5:\ C5
+F9C6:\ C6
+F9C7:\ C7
+F9C8:\ C8
+F9C9:\ C9
+F9CA:\ CA
+F9CB:\ CB
+F9CC:\ CC
+F9CD:\ CD
+F9CE:\ CE
+F9CF:\ CF
+F9D0:\ D0
+F9D1:\ D1
+F9D2:\ D2
+F9D3:\ D3
+F9D4:\ D4
+F9D5:\ D5
+F9D6:\ D6
+F9D7:\ D7
+F9D8:\ D8
+F9D9:\ D9
+F9DA:\ DA
+F9DB:\ DB
+F9DC:\ DC
+F9DD:\ DD
+F9DE:\ DE
+F9DF:\ DF
+F9E0:\ E0
+F9E1:\ E1
+F9E2:\ E2
+F9E3:\ E3
+F9E4:\ E4
+F9E5:\ E5
+F9E6:\ E6
+F9E7:\ E7
+F9E8:\ E8
+F9E9:\ E9
+F9EA:\ EA
+F9EB:\ EB
+F9EC:\ EC
+F9ED:\ ED
+F9EE:\ EE
+F9EF:\ EF
+F9F0:\ F0
+F9F1:\ F1
+F9F2:\ F2
+F9F3:\ F3
+F9F4:\ F4
+F9F5:\ F5
+F9F6:\ F6
+F9F7:\ F7
+F9F8:\ F8
+F9F9:\ F9
+F9FA:\ FA
+F9FB:\ FB
+F9FC:\ FC
+F9FD:\ FD
+F9FE:\ FE
+F9FF:\ FF
+FA00:\õ00
+FA01:\õ01
+FA02:\õ02
+FA03:\õ03
+FA04:\õ04
+FA05:\õ05
+FA06:\õ06
+FA07:\õ07
+FA08:\õ08
+FA09:\õ09
+FA0A:\õ0A
+FA0B:\õ0B
+FA0C:\õ0C
+FA0D:\õ0D
+FA0E:\õ0E
+FA0F:\õ0F
+FA10:\õ10
+FA11:\õ11
+FA12:\õ12
+FA13:\õ13
+FA14:\õ14
+FA15:\õ15
+FA16:\õ16
+FA17:\õ17
+FA18:\õ18
+FA19:\õ19
+FA1A:\õ1A
+FA1B:\õ1B
+FA1C:\õ1C
+FA1D:\õ1D
+FA1E:\õ1E
+FA1F:\õ1F
+FA20:\õ20
+FA21:\õ21
+FA22:\õ22
+FA23:\õ23
+FA24:\õ24
+FA25:\õ25
+FA26:\õ26
+FA27:\õ27
+FA28:\õ28
+FA29:\õ29
+FA2A:\õ2A
+FA2B:\õ2B
+FA2C:\õ2C
+FA2D:\õ2D
+FA30:\õ30
+FA31:\õ31
+FA32:\õ32
+FA33:\õ33
+FA34:\õ34
+FA35:\õ35
+FA36:\õ36
+FA37:\õ37
+FA38:\õ38
+FA39:\õ39
+FA3A:\õ3A
+FA3B:\õ3B
+FA3C:\õ3C
+FA3D:\õ3D
+FA3E:\õ3E
+FA3F:\õ3F
+FA40:\õ40
+FA41:\õ41
+FA42:\õ42
+FA43:\õ43
+FA44:\õ44
+FA45:\õ45
+FA46:\õ46
+FA47:\õ47
+FA48:\õ48
+FA49:\õ49
+FA4A:\õ4A
+FA4B:\õ4B
+FA4C:\õ4C
+FA4D:\õ4D
+FA4E:\õ4E
+FA4F:\õ4F
+FA50:\õ50
+FA51:\õ51
+FA52:\õ52
+FA53:\õ53
+FA54:\õ54
+FA55:\õ55
+FA56:\õ56
+FA57:\õ57
+FA58:\õ58
+FA59:\õ59
+FA5A:\õ5A
+FA5B:\õ5B
+FA5C:\õ5C
+FA5D:\õ5D
+FA5E:\õ5E
+FA5F:\õ5F
+FA60:\õ60
+FA61:\õ61
+FA62:\õ62
+FA63:\õ63
+FA64:\õ64
+FA65:\õ65
+FA66:\õ66
+FA67:\õ67
+FA68:\õ68
+FA69:\õ69
+FA6A:\õ6A
+FB00:LATIN\Ç\òFF
+FB01:LATIN\Ç\òFI
+FB02:LATIN\Ç\òFL
+FB03:LATIN\Ç\òFFI
+FB04:LATIN\Ç\òFFL
+FB05:LATIN\Ç\òLONG S T
+FB06:LATIN\Ç\òST
+FB13:ARMENIAN\Ç\òMEN NOW
+FB14:ARMENIAN\Ç\òMEN ECH
+FB15:ARMENIAN\Ç\òMEN INI
+FB16:ARMENIAN\Ç\òVEW NOW
+FB17:ARMENIAN\Ç\òMEN XEH
+FB1D:\Ÿ\@YOD\HHIRIQ
+FB1E:\Ÿ POINT JUDEO-SPANISH VARIKA
+FB1F:\Ÿ \òYIDDISH YOD YOD PATAH
+FB20:\Ÿ\@ALTERNATIVE AYIN
+FB21:\Ÿ\@WIDE ALEF
+FB22:\Ÿ\@WIDE DALET
+FB23:\Ÿ\@WIDE HE
+FB24:\Ÿ\@WIDE KAF
+FB25:\Ÿ\@WIDE LAMED
+FB26:\Ÿ\@WIDE FINAL MEM
+FB27:\Ÿ\@WIDE RESH
+FB28:\Ÿ\@WIDE TAV
+FB29:\Ÿ\@ALTERNATIVE PLUS\‚
+FB2A:\Ÿ\@SHIN\HSHIN DOT
+FB2B:\Ÿ\@SHIN\HSIN DOT
+FB2C:\Ÿ\@SHIN\HDAGESH\iSHIN DOT
+FB2D:\Ÿ\@SHIN\HDAGESH\iSIN DOT
+FB2E:\Ÿ\@ALEF\HPATAH
+FB2F:\Ÿ\@ALEF\HQAMATS
+FB30:\Ÿ\@ALEF\HMAPIQ
+FB31:\Ÿ\@BET\HDAGESH
+FB32:\Ÿ\@GIMEL\HDAGESH
+FB33:\Ÿ\@DALET\HDAGESH
+FB34:\Ÿ\@HE\HMAPIQ
+FB35:\Ÿ\@VAV\HDAGESH
+FB36:\Ÿ\@ZAYIN\HDAGESH
+FB38:\Ÿ\@TET\HDAGESH
+FB39:\Ÿ\@YOD\HDAGESH
+FB3A:\Ÿ\@FINAL KAF\HDAGESH
+FB3B:\Ÿ\@KAF\HDAGESH
+FB3C:\Ÿ\@LAMED\HDAGESH
+FB3E:\Ÿ\@MEM\HDAGESH
+FB40:\Ÿ\@NUN\HDAGESH
+FB41:\Ÿ\@SAMEKH\HDAGESH
+FB43:\Ÿ\@FINAL PE\HDAGESH
+FB44:\Ÿ\@PE\HDAGESH
+FB46:\Ÿ\@TSADI\HDAGESH
+FB47:\Ÿ\@QOF\HDAGESH
+FB48:\Ÿ\@RESH\HDAGESH
+FB49:\Ÿ\@SHIN\HDAGESH
+FB4A:\Ÿ\@TAV\HDAGESH
+FB4B:\Ÿ\@VAV\HHOLAM
+FB4C:\Ÿ\@BET\HRAFE
+FB4D:\Ÿ\@KAF\HRAFE
+FB4E:\Ÿ\@PE\HRAFE
+FB4F:\Ÿ \òALEF LAMED
+FB50:\^ALEF WASLA\Q
+FB51:\^ALEF WASLA\6
+FB52:\^BEEH\Q
+FB53:\^BEEH\6
+FB54:\^BEEH\2
+FB55:\^BEEH MEDI\X
+FB56:\^PEH\Q
+FB57:\^PEH\6
+FB58:\^PEH\2
+FB59:\^PEH MEDI\X
+FB5A:\^BEHEH\Q
+FB5B:\^BEHEH\6
+FB5C:\^BEHEH\2
+FB5D:\^BEHEH MEDI\X
+FB5E:\^TTEHEH\Q
+FB5F:\^TTEHEH\6
+FB60:\^TTEHEH\2
+FB61:\^TTEHEH MEDI\X
+FB62:\^TEHEH\Q
+FB63:\^TEHEH\6
+FB64:\^TEHEH\2
+FB65:\^TEHEH MEDI\X
+FB66:\^TTEH\Q
+FB67:\^TTEH\6
+FB68:\^TTEH\2
+FB69:\^TTEH MEDI\X
+FB6A:\^VEH\Q
+FB6B:\^VEH\6
+FB6C:\^VEH\2
+FB6D:\^VEH MEDI\X
+FB6E:\^PEHEH\Q
+FB6F:\^PEHEH\6
+FB70:\^PEHEH\2
+FB71:\^PEHEH MEDI\X
+FB72:\^DYEH\Q
+FB73:\^DYEH\6
+FB74:\^DYEH\2
+FB75:\^DYEH MEDI\X
+FB76:\^NYEH\Q
+FB77:\^NYEH\6
+FB78:\^NYEH\2
+FB79:\^NYEH MEDI\X
+FB7A:\^TCHEH\Q
+FB7B:\^TCHEH\6
+FB7C:\^TCHEH\2
+FB7D:\^TCHEH MEDI\X
+FB7E:\^TCHEHEH\Q
+FB7F:\^TCHEHEH\6
+FB80:\^TCHEHEH\2
+FB81:\^TCHEHEH MEDI\X
+FB82:\^DDAHAL\Q
+FB83:\^DDAHAL\6
+FB84:\^DAHAL\Q
+FB85:\^DAHAL\6
+FB86:\^DUL\Q
+FB87:\^DUL\6
+FB88:\^DDAL\Q
+FB89:\^DDAL\6
+FB8A:\^JEH\Q
+FB8B:\^JEH\6
+FB8C:\^RREH\Q
+FB8D:\^RREH\6
+FB8E:\^KEHEH\Q
+FB8F:\^KEHEH\6
+FB90:\^KEHEH\2
+FB91:\^KEHEH MEDI\X
+FB92:\^GAF\Q
+FB93:\^GAF\6
+FB94:\^GAF\2
+FB95:\^GAF MEDI\X
+FB96:\^GUEH\Q
+FB97:\^GUEH\6
+FB98:\^GUEH\2
+FB99:\^GUEH MEDI\X
+FB9A:\^NGOEH\Q
+FB9B:\^NGOEH\6
+FB9C:\^NGOEH\2
+FB9D:\^NGOEH MEDI\X
+FB9E:\^NOON GHUNNA\Q
+FB9F:\^NOON GHUNNA\6
+FBA0:\^RNOON\Q
+FBA1:\^RNOON\6
+FBA2:\^RNOON\2
+FBA3:\^RNOON MEDI\X
+FBA4:\^HEH\HYEH\p\Q
+FBA5:\^HEH\HYEH\p\6
+FBA6:\^HEH GOAL\Q
+FBA7:\^HEH GOAL\6
+FBA8:\^HEH GOAL\2
+FBA9:\^HEH GOAL MEDI\X
+FBAA:\^HEH DOACHASHMEE\Q
+FBAB:\^HEH DOACHASHMEE\6
+FBAC:\^HEH DOACHASHMEE\2
+FBAD:\^HEH DOACHASHMEE MEDI\X
+FBAE:\^YEH\ìREE\Q
+FBAF:\^YEH\ìREE\6
+FBB0:\^YEH\ìREE\HHAMZA\p\Q
+FBB1:\^YEH\ìREE\HHAMZA\p\6
+FBD3:\^NG\Q
+FBD4:\^NG\6
+FBD5:\^NG\2
+FBD6:\^NG MEDI\X
+FBD7:\^U\Q
+FBD8:\^U\6
+FBD9:\^OE\Q
+FBDA:\^OE\6
+FBDB:\^YU\Q
+FBDC:\^YU\6
+FBDD:\^U\HHAMZA\p\Q
+FBDE:\^VE\Q
+FBDF:\^VE\6
+FBE0:\^KIRGHIZ OE\Q
+FBE1:\^KIRGHIZ OE\6
+FBE2:\^KIRGHIZ YU\Q
+FBE3:\^KIRGHIZ YU\6
+FBE4:\^E\Q
+FBE5:\^E\6
+FBE6:\^E\2
+FBE7:\^E MEDI\X
+FBE8:\^UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA\2
+FBE9:\^UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA MEDI\X
+FBEA:\J\º\HALEF\Q
+FBEB:\J\º\HALEF\6
+FBEC:\J\º\HAE\Q
+FBED:\J\º\HAE\6
+FBEE:\J\º\HWAW\Q
+FBEF:\J\º\HWAW\6
+FBF0:\J\º\HU\Q
+FBF1:\J\º\HU\6
+FBF2:\J\º\HOE\Q
+FBF3:\J\º\HOE\6
+FBF4:\J\º\HYU\Q
+FBF5:\J\º\HYU\6
+FBF6:\J\º\HE\Q
+FBF7:\J\º\HE\6
+FBF8:\J\º\HE\2
+FBF9:\JUIGHUR KIRGHIZ \º\‡\Q
+FBFA:\JUIGHUR KIRGHIZ \º\‡\6
+FBFB:\JUIGHUR KIRGHIZ \º\‡\2
+FBFC:\^FARSI YEH\Q
+FBFD:\^FARSI YEH\6
+FBFE:\^FARSI YEH\2
+FBFF:\^FARSI YEH MEDI\X
+FC00:\J\º\Ô\Q
+FC01:\J\º\HHAH\Q
+FC02:\J\º\\Q
+FC03:\J\º\‡\Q
+FC04:\J\º\HYEH\Q
+FC05:\JBEH\Ô\Q
+FC06:\JBEH\HHAH\Q
+FC07:\JBEH\HKHAH\Q
+FC08:\JBEH\\Q
+FC09:\JBEH\‡\Q
+FC0A:\JBEH\HYEH\Q
+FC0B:\JTEH\Ô\Q
+FC0C:\JTEH\HHAH\Q
+FC0D:\JTEH\HKHAH\Q
+FC0E:\JTEH\\Q
+FC0F:\JTEH\‡\Q
+FC10:\JTEH\HYEH\Q
+FC11:\JTHEH\Ô\Q
+FC12:\JTHEH\\Q
+FC13:\JTHEH\‡\Q
+FC14:\JTHEH\HYEH\Q
+FC15:\JJEEM\HHAH\Q
+FC16:\JJEEM\\Q
+FC17:\JHAH\Ô\Q
+FC18:\JHAH\\Q
+FC19:\JKHAH\Ô\Q
+FC1A:\JKHAH\HHAH\Q
+FC1B:\JKHAH\\Q
+FC1C:\JSEEN\Ô\Q
+FC1D:\JSEEN\HHAH\Q
+FC1E:\JSEEN\HKHAH\Q
+FC1F:\JSEEN\\Q
+FC20:\JSAD\HHAH\Q
+FC21:\JSAD\\Q
+FC22:\JDAD\Ô\Q
+FC23:\JDAD\HHAH\Q
+FC24:\JDAD\HKHAH\Q
+FC25:\JDAD\\Q
+FC26:\JTAH\HHAH\Q
+FC27:\JTAH\\Q
+FC28:\JZAH\\Q
+FC29:\JAIN\Ô\Q
+FC2A:\JAIN\\Q
+FC2B:\JGHAIN\Ô\Q
+FC2C:\JGHAIN\\Q
+FC2D:\JFEH\Ô\Q
+FC2E:\JFEH\HHAH\Q
+FC2F:\JFEH\HKHAH\Q
+FC30:\JFEH\\Q
+FC31:\JFEH\‡\Q
+FC32:\JFEH\HYEH\Q
+FC33:\JQAF\HHAH\Q
+FC34:\JQAF\\Q
+FC35:\JQAF\‡\Q
+FC36:\JQAF\HYEH\Q
+FC37:\JKAF\HALEF\Q
+FC38:\JKAF\Ô\Q
+FC39:\JKAF\HHAH\Q
+FC3A:\JKAF\HKHAH\Q
+FC3B:\JKAF\HLAM\Q
+FC3C:\JKAF\\Q
+FC3D:\JKAF\‡\Q
+FC3E:\JKAF\HYEH\Q
+FC3F:\JLAM\Ô\Q
+FC40:\JLAM\HHAH\Q
+FC41:\JLAM\HKHAH\Q
+FC42:\JLAM\\Q
+FC43:\JLAM\‡\Q
+FC44:\JLAM\HYEH\Q
+FC45:\JMEEM\Ô\Q
+FC46:\JMEEM\HHAH\Q
+FC47:\JMEEM\HKHAH\Q
+FC48:\JMEEM\\Q
+FC49:\JMEEM\‡\Q
+FC4A:\JMEEM\HYEH\Q
+FC4B:\JNOON\Ô\Q
+FC4C:\JNOON\HHAH\Q
+FC4D:\JNOON\HKHAH\Q
+FC4E:\JNOON\\Q
+FC4F:\JNOON\‡\Q
+FC50:\JNOON\HYEH\Q
+FC51:\JHEH\Ô\Q
+FC52:\JHEH\\Q
+FC53:\JHEH\‡\Q
+FC54:\JHEH\HYEH\Q
+FC55:\JYEH\Ô\Q
+FC56:\JYEH\HHAH\Q
+FC57:\JYEH\HKHAH\Q
+FC58:\JYEH\\Q
+FC59:\JYEH\‡\Q
+FC5A:\JYEH\HYEH\Q
+FC5B:\JTHAL\HSUPER\Ž ALEF\Q
+FC5C:\JREH\HSUPER\Ž ALEF\Q
+FC5D:\JALEF MAKSURA\HSUPER\Ž ALEF\Q
+FC5E:\JSHADDA\HDAMMATAN\Q
+FC5F:\JSHADDA\HKASRATAN\Q
+FC60:\JSHADDA\HFATHA\Q
+FC61:\JSHADDA\HDAMMA\Q
+FC62:\JSHADDA\HKASRA\Q
+FC63:\JSHADDA\HSUPER\Ž ALEF\Q
+FC64:\J\º\HREH\6
+FC65:\J\º\HZAIN\6
+FC66:\J\º\\6
+FC67:\J\º\HNOON\6
+FC68:\J\º\‡\6
+FC69:\J\º\Û
+FC6A:\JBEH\HREH\6
+FC6B:\JBEH\HZAIN\6
+FC6C:\JBEH\\6
+FC6D:\JBEH\HNOON\6
+FC6E:\JBEH\‡\6
+FC6F:\JBEH\Û
+FC70:\JTEH\HREH\6
+FC71:\JTEH\HZAIN\6
+FC72:\JTEH\\6
+FC73:\JTEH\HNOON\6
+FC74:\JTEH\‡\6
+FC75:\JTEH\Û
+FC76:\JTHEH\HREH\6
+FC77:\JTHEH\HZAIN\6
+FC78:\JTHEH\\6
+FC79:\JTHEH\HNOON\6
+FC7A:\JTHEH\‡\6
+FC7B:\JTHEH\Û
+FC7C:\JFEH\‡\6
+FC7D:\JFEH\Û
+FC7E:\JQAF\‡\6
+FC7F:\JQAF\Û
+FC80:\JKAF\HALEF\6
+FC81:\JKAF\HLAM\6
+FC82:\JKAF\\6
+FC83:\JKAF\‡\6
+FC84:\JKAF\Û
+FC85:\JLAM\\6
+FC86:\JLAM\‡\6
+FC87:\JLAM\Û
+FC88:\JMEEM\HALEF\6
+FC89:\JMEEM\\6
+FC8A:\JNOON\HREH\6
+FC8B:\JNOON\HZAIN\6
+FC8C:\JNOON\\6
+FC8D:\JNOON\HNOON\6
+FC8E:\JNOON\‡\6
+FC8F:\JNOON\Û
+FC90:\JALEF MAKSURA\HSUPER\Ž ALEF\6
+FC91:\JYEH\HREH\6
+FC92:\JYEH\HZAIN\6
+FC93:\JYEH\\6
+FC94:\JYEH\HNOON\6
+FC95:\JYEH\‡\6
+FC96:\JYEH\Û
+FC97:\J\º\Ô\2
+FC98:\J\º\HHAH\2
+FC99:\J\º\HKHAH\2
+FC9A:\J\º\\2
+FC9B:\J\º\HHEH\2
+FC9C:\JBEH\Ô\2
+FC9D:\JBEH\HHAH\2
+FC9E:\JBEH\HKHAH\2
+FC9F:\JBEH\\2
+FCA0:\JBEH\HHEH\2
+FCA1:\JTEH\Ô\2
+FCA2:\JTEH\HHAH\2
+FCA3:\JTEH\HKHAH\2
+FCA4:\JTEH\\2
+FCA5:\JTEH\HHEH\2
+FCA6:\JTHEH\\2
+FCA7:\JJEEM\HHAH\2
+FCA8:\JJEEM\\2
+FCA9:\JHAH\Ô\2
+FCAA:\JHAH\\2
+FCAB:\JKHAH\Ô\2
+FCAC:\JKHAH\\2
+FCAD:\JSEEN\Ô\2
+FCAE:\JSEEN\HHAH\2
+FCAF:\JSEEN\HKHAH\2
+FCB0:\JSEEN\\2
+FCB1:\JSAD\HHAH\2
+FCB2:\JSAD\HKHAH\2
+FCB3:\JSAD\\2
+FCB4:\JDAD\Ô\2
+FCB5:\JDAD\HHAH\2
+FCB6:\JDAD\HKHAH\2
+FCB7:\JDAD\\2
+FCB8:\JTAH\HHAH\2
+FCB9:\JZAH\\2
+FCBA:\JAIN\Ô\2
+FCBB:\JAIN\\2
+FCBC:\JGHAIN\Ô\2
+FCBD:\JGHAIN\\2
+FCBE:\JFEH\Ô\2
+FCBF:\JFEH\HHAH\2
+FCC0:\JFEH\HKHAH\2
+FCC1:\JFEH\\2
+FCC2:\JQAF\HHAH\2
+FCC3:\JQAF\\2
+FCC4:\JKAF\Ô\2
+FCC5:\JKAF\HHAH\2
+FCC6:\JKAF\HKHAH\2
+FCC7:\JKAF\HLAM\2
+FCC8:\JKAF\\2
+FCC9:\JLAM\Ô\2
+FCCA:\JLAM\HHAH\2
+FCCB:\JLAM\HKHAH\2
+FCCC:\JLAM\\2
+FCCD:\JLAM\HHEH\2
+FCCE:\JMEEM\Ô\2
+FCCF:\JMEEM\HHAH\2
+FCD0:\JMEEM\HKHAH\2
+FCD1:\JMEEM\\2
+FCD2:\JNOON\Ô\2
+FCD3:\JNOON\HHAH\2
+FCD4:\JNOON\HKHAH\2
+FCD5:\JNOON\\2
+FCD6:\JNOON\HHEH\2
+FCD7:\JHEH\Ô\2
+FCD8:\JHEH\\2
+FCD9:\JHEH\HSUPER\Ž ALEF\2
+FCDA:\JYEH\Ô\2
+FCDB:\JYEH\HHAH\2
+FCDC:\JYEH\HKHAH\2
+FCDD:\JYEH\\2
+FCDE:\JYEH\HHEH\2
+FCDF:\J\º\ MEDI\X
+FCE0:\J\º\HHEH MEDI\X
+FCE1:\JBEH\ MEDI\X
+FCE2:\JBEH\HHEH MEDI\X
+FCE3:\JTEH\ MEDI\X
+FCE4:\JTEH\HHEH MEDI\X
+FCE5:\JTHEH\ MEDI\X
+FCE6:\JTHEH\HHEH MEDI\X
+FCE7:\JSEEN\ MEDI\X
+FCE8:\JSEEN\HHEH MEDI\X
+FCE9:\JSHEEN\ MEDI\X
+FCEA:\JSHEEN\HHEH MEDI\X
+FCEB:\JKAF\HLAM MEDI\X
+FCEC:\JKAF\ MEDI\X
+FCED:\JLAM\ MEDI\X
+FCEE:\JNOON\ MEDI\X
+FCEF:\JNOON\HHEH MEDI\X
+FCF0:\JYEH\ MEDI\X
+FCF1:\JYEH\HHEH MEDI\X
+FCF2:\JSHADDA\HFATHA MEDI\X
+FCF3:\JSHADDA\HDAMMA MEDI\X
+FCF4:\JSHADDA\HKASRA MEDI\X
+FCF5:\JTAH\‡\Q
+FCF6:\JTAH\HYEH\Q
+FCF7:\JAIN\‡\Q
+FCF8:\JAIN\HYEH\Q
+FCF9:\JGHAIN\‡\Q
+FCFA:\JGHAIN\HYEH\Q
+FCFB:\JSEEN\‡\Q
+FCFC:\JSEEN\HYEH\Q
+FCFD:\JSHEEN\‡\Q
+FCFE:\JSHEEN\HYEH\Q
+FCFF:\JHAH\‡\Q
+FD00:\JHAH\HYEH\Q
+FD01:\JJEEM\‡\Q
+FD02:\JJEEM\HYEH\Q
+FD03:\JKHAH\‡\Q
+FD04:\JKHAH\HYEH\Q
+FD05:\JSAD\‡\Q
+FD06:\JSAD\HYEH\Q
+FD07:\JDAD\‡\Q
+FD08:\JDAD\HYEH\Q
+FD09:\JSHEEN\Ô\Q
+FD0A:\JSHEEN\HHAH\Q
+FD0B:\JSHEEN\HKHAH\Q
+FD0C:\JSHEEN\\Q
+FD0D:\JSHEEN\HREH\Q
+FD0E:\JSEEN\HREH\Q
+FD0F:\JSAD\HREH\Q
+FD10:\JDAD\HREH\Q
+FD11:\JTAH\‡\6
+FD12:\JTAH\Û
+FD13:\JAIN\‡\6
+FD14:\JAIN\Û
+FD15:\JGHAIN\‡\6
+FD16:\JGHAIN\Û
+FD17:\JSEEN\‡\6
+FD18:\JSEEN\Û
+FD19:\JSHEEN\‡\6
+FD1A:\JSHEEN\Û
+FD1B:\JHAH\‡\6
+FD1C:\JHAH\Û
+FD1D:\JJEEM\‡\6
+FD1E:\JJEEM\Û
+FD1F:\JKHAH\‡\6
+FD20:\JKHAH\Û
+FD21:\JSAD\‡\6
+FD22:\JSAD\Û
+FD23:\JDAD\‡\6
+FD24:\JDAD\Û
+FD25:\JSHEEN\Ô\6
+FD26:\JSHEEN\HHAH\6
+FD27:\JSHEEN\HKHAH\6
+FD28:\JSHEEN\\6
+FD29:\JSHEEN\HREH\6
+FD2A:\JSEEN\HREH\6
+FD2B:\JSAD\HREH\6
+FD2C:\JDAD\HREH\6
+FD2D:\JSHEEN\Ô\2
+FD2E:\JSHEEN\HHAH\2
+FD2F:\JSHEEN\HKHAH\2
+FD30:\JSHEEN\\2
+FD31:\JSEEN\HHEH\2
+FD32:\JSHEEN\HHEH\2
+FD33:\JTAH\\2
+FD34:\JSEEN\Ô MEDI\X
+FD35:\JSEEN\HHAH MEDI\X
+FD36:\JSEEN\HKHAH MEDI\X
+FD37:\JSHEEN\Ô MEDI\X
+FD38:\JSHEEN\HHAH MEDI\X
+FD39:\JSHEEN\HKHAH MEDI\X
+FD3A:\JTAH\ MEDI\X
+FD3B:\JZAH\ MEDI\X
+FD3C:\JALEF\HFATHATAN\6
+FD3D:\JALEF\HFATHATAN\Q
+FD3E:ORNATE \‰ \ÑS
+FD3F:ORNATE \ù\ÑS
+FD50:\JTEH\Ô\\2
+FD51:\JTEH\HHAH\Ô\6
+FD52:\JTEH\HHAH\Ô\2
+FD53:\JTEH\HHAH\\2
+FD54:\JTEH\HKHAH\\2
+FD55:\JTEH\\Ô\2
+FD56:\JTEH\\HHAH\2
+FD57:\JTEH\\HKHAH\2
+FD58:\JJEEM\\HHAH\6
+FD59:\JJEEM\\HHAH\2
+FD5A:\JHAH\\Û
+FD5B:\JHAH\\‡\6
+FD5C:\JSEEN\HHAH\Ô\2
+FD5D:\JSEEN\Ô\HHAH\2
+FD5E:\JSEEN\Ô\‡\6
+FD5F:\JSEEN\\HHAH\6
+FD60:\JSEEN\\HHAH\2
+FD61:\JSEEN\\Ô\2
+FD62:\JSEEN\\\6
+FD63:\JSEEN\\\2
+FD64:\JSAD\HHAH\HHAH\6
+FD65:\JSAD\HHAH\HHAH\2
+FD66:\JSAD\\\6
+FD67:\JSHEEN\HHAH\\6
+FD68:\JSHEEN\HHAH\\2
+FD69:\JSHEEN\Ô\Û
+FD6A:\JSHEEN\\HKHAH\6
+FD6B:\JSHEEN\\HKHAH\2
+FD6C:\JSHEEN\\\6
+FD6D:\JSHEEN\\\2
+FD6E:\JDAD\HHAH\‡\6
+FD6F:\JDAD\HKHAH\\6
+FD70:\JDAD\HKHAH\\2
+FD71:\JTAH\\HHAH\6
+FD72:\JTAH\\HHAH\2
+FD73:\JTAH\\\2
+FD74:\JTAH\\Û
+FD75:\JAIN\Ô\\6
+FD76:\JAIN\\\6
+FD77:\JAIN\\\2
+FD78:\JAIN\\‡\6
+FD79:\JGHAIN\\\6
+FD7A:\JGHAIN\\Û
+FD7B:\JGHAIN\\‡\6
+FD7C:\JFEH\HKHAH\\6
+FD7D:\JFEH\HKHAH\\2
+FD7E:\JQAF\\HHAH\6
+FD7F:\JQAF\\\6
+FD80:\JLAM\HHAH\\6
+FD81:\JLAM\HHAH\Û
+FD82:\JLAM\HHAH\‡\6
+FD83:\JLAM\Ô\Ô\2
+FD84:\JLAM\Ô\Ô\6
+FD85:\JLAM\HKHAH\\6
+FD86:\JLAM\HKHAH\\2
+FD87:\JLAM\\HHAH\6
+FD88:\JLAM\\HHAH\2
+FD89:\JMEEM\HHAH\Ô\2
+FD8A:\JMEEM\HHAH\\2
+FD8B:\JMEEM\HHAH\Û
+FD8C:\JMEEM\Ô\HHAH\2
+FD8D:\JMEEM\Ô\\2
+FD8E:\JMEEM\HKHAH\Ô\2
+FD8F:\JMEEM\HKHAH\\2
+FD92:\JMEEM\Ô\HKHAH\2
+FD93:\JHEH\\Ô\2
+FD94:\JHEH\\\2
+FD95:\JNOON\HHAH\\2
+FD96:\JNOON\HHAH\‡\6
+FD97:\JNOON\Ô\\6
+FD98:\JNOON\Ô\\2
+FD99:\JNOON\Ô\‡\6
+FD9A:\JNOON\\Û
+FD9B:\JNOON\\‡\6
+FD9C:\JYEH\\\6
+FD9D:\JYEH\\\2
+FD9E:\JBEH\HKHAH\Û
+FD9F:\JTEH\Ô\Û
+FDA0:\JTEH\Ô\‡\6
+FDA1:\JTEH\HKHAH\Û
+FDA2:\JTEH\HKHAH\‡\6
+FDA3:\JTEH\\Û
+FDA4:\JTEH\\‡\6
+FDA5:\JJEEM\\Û
+FDA6:\JJEEM\HHAH\‡\6
+FDA7:\JJEEM\\‡\6
+FDA8:\JSEEN\HKHAH\‡\6
+FDA9:\JSAD\HHAH\Û
+FDAA:\JSHEEN\HHAH\Û
+FDAB:\JDAD\HHAH\Û
+FDAC:\JLAM\Ô\Û
+FDAD:\JLAM\\Û
+FDAE:\JYEH\HHAH\Û
+FDAF:\JYEH\Ô\Û
+FDB0:\JYEH\\Û
+FDB1:\JMEEM\\Û
+FDB2:\JQAF\\Û
+FDB3:\JNOON\HHAH\Û
+FDB4:\JQAF\\HHAH\2
+FDB5:\JLAM\HHAH\\2
+FDB6:\JAIN\\Û
+FDB7:\JKAF\\Û
+FDB8:\JNOON\Ô\HHAH\2
+FDB9:\JMEEM\HKHAH\Û
+FDBA:\JLAM\Ô\\2
+FDBB:\JKAF\\\6
+FDBC:\JLAM\Ô\\6
+FDBD:\JNOON\Ô\HHAH\6
+FDBE:\JJEEM\HHAH\Û
+FDBF:\JHAH\Ô\Û
+FDC0:\JMEEM\Ô\Û
+FDC1:\JFEH\\Û
+FDC2:\JBEH\HHAH\Û
+FDC3:\JKAF\\\2
+FDC4:\JAIN\Ô\\2
+FDC5:\JSAD\\\2
+FDC6:\JSEEN\HKHAH\Û
+FDC7:\JNOON\Ô\Û
+FDF0:\JSALLA US\ÂAS KORANIC STOP\‚\Q
+FDF1:\JQALA US\ÂAS KORANIC STOP\‚\Q
+FDF2:\JALLAH\Q
+FDF3:\JAKBAR\Q
+FDF4:\JMOHAMMAD\Q
+FDF5:\JSALAM\Q
+FDF6:\JRASOUL\Q
+FDF7:\JALAYHE\Q
+FDF8:\JWASALLAM\Q
+FDF9:\JSALLA\Q
+FDFA:\JSALLALLAHOU ALAYHE WASALLAM
+FDFB:\JJALLAJALALOUHOU
+FDFC:RIAL\‚
+FE00:\ç-1
+FE01:\ç-2
+FE02:\ç-3
+FE03:\ç-4
+FE04:\ç-5
+FE05:\ç-6
+FE06:\ç-7
+FE07:\ç-8
+FE08:\ç-9
+FE09:\ç-10
+FE0A:\ç-11
+FE0B:\ç-12
+FE0C:\ç-13
+FE0D:\ç-14
+FE0E:\ç-15
+FE0F:\ç-16
+FE20:\o\ò\‰ HALF
+FE21:\o\ò\ùHALF
+FE22:\o\0 \æ \‰ HALF
+FE23:\o\0 \æ \ùHALF
+FE30:\¹TWO DOT LEADER
+FE31:\¹EM DASH
+FE32:\¹EN DASH
+FE33:\¹LOW \ä
+FE34:\¹WAVY LOW \ä
+FE35:\¹\‰ \ÑS
+FE36:\¹\ù\ÑS
+FE37:\¹\‰ CURLY \–
+FE38:\¹\ùCURLY \–
+FE39:\¹\‰ TORTOISE SHELL \–
+FE3A:\¹\ùTORTOISE SHELL \–
+FE3B:\¹\‰ \¬ LENTICULAR \–
+FE3C:\¹\ù\¬ LENTICULAR \–
+FE3D:\¹\‰ \0 ANGLE \–
+FE3E:\¹\ù\0 ANGLE \–
+FE3F:\¹\‰ ANGLE \–
+FE40:\¹\ùANGLE \–
+FE41:\¹\‰ CORNER \–
+FE42:\¹\ùCORNER \–
+FE43:\¹\‰ \¦CORNER \–
+FE44:\¹\ù\¦CORNER \–
+FE45:SESAME DOT
+FE46:\¦SESAME DOT
+FE49:DASH\ÂOVER\ä
+FE4A:CENTRE\ä OVER\ä
+FE4B:WAVY OVER\ä
+FE4C:\0 WAVY OVER\ä
+FE4D:DASH\ÂLOW \ä
+FE4E:CENTRE\ä LOW \ä
+FE4F:WAVY LOW \ä
+FE50:\§COMMA
+FE51:\§\8IC COMMA
+FE52:SMALL\é
+FE54:\§SEMICOLON
+FE55:\§COLON
+FE56:\§QUESTION\¥
+FE57:\§EXCLAM\”\¥
+FE58:\§EM DASH
+FE59:\§\‰ \ÑS
+FE5A:\§\ù\ÑS
+FE5B:\§\‰ CURLY \–
+FE5C:\§\ùCURLY \–
+FE5D:\§\‰ TORTOISE SHELL \–
+FE5E:\§\ùTORTOISE SHELL \–
+FE5F:\§\­SIGN
+FE60:\§AMPERSAND
+FE61:\§ASTERISK
+FE62:\§PLUS\‚
+FE63:\§HYPHEN-MINUS
+FE64:\§\µ\‚
+FE65:\§\’\‚
+FE66:\§EQUALS\‚
+FE68:\§REVERSE SOLIDUS
+FE69:\§DOLLAR\‚
+FE6A:\§PERCENT\‚
+FE6B:\§COMMERCIAL AT
+FE70:\Ê FATHATAN\Q
+FE71:\Ê TATWEEL\HFATHATAN\p
+FE72:\Ê DAMMATAN\Q
+FE73:\Ê TAIL FRAGMENT
+FE74:\Ê KASRATAN\Q
+FE76:\Ê FATHA\Q
+FE77:\Ê FATHA MEDI\X
+FE78:\Ê DAMMA\Q
+FE79:\Ê DAMMA MEDI\X
+FE7A:\Ê KASRA\Q
+FE7B:\Ê KASRA MEDI\X
+FE7C:\Ê SHADDA\Q
+FE7D:\Ê SHADDA MEDI\X
+FE7E:\Ê SUKUN\Q
+FE7F:\Ê SUKUN MEDI\X
+FE80:\^HAMZA\Q
+FE81:\^ALEF\HMADDA\p\Q
+FE82:\^ALEF\HMADDA\p\6
+FE83:\^ALEF\HHAMZA\p\Q
+FE84:\^ALEF\HHAMZA\p\6
+FE85:\^WAW\HHAMZA\p\Q
+FE86:\^WAW\HHAMZA\p\6
+FE87:\^ALEF\HHAMZA\…\Q
+FE88:\^ALEF\HHAMZA\…\6
+FE89:\^\º\Q
+FE8A:\^\º\6
+FE8B:\^\º\2
+FE8C:\^\º MEDI\X
+FE8D:\^ALEF\Q
+FE8E:\^ALEF\6
+FE8F:\^BEH\Q
+FE90:\^BEH\6
+FE91:\^BEH\2
+FE92:\^BEH MEDI\X
+FE93:\^TEH MARBUTA\Q
+FE94:\^TEH MARBUTA\6
+FE95:\^TEH\Q
+FE96:\^TEH\6
+FE97:\^TEH\2
+FE98:\^TEH MEDI\X
+FE99:\^THEH\Q
+FE9A:\^THEH\6
+FE9B:\^THEH\2
+FE9C:\^THEH MEDI\X
+FE9D:\^JEEM\Q
+FE9E:\^JEEM\6
+FE9F:\^JEEM\2
+FEA0:\^JEEM MEDI\X
+FEA1:\^HAH\Q
+FEA2:\^HAH\6
+FEA3:\^HAH\2
+FEA4:\^HAH MEDI\X
+FEA5:\^KHAH\Q
+FEA6:\^KHAH\6
+FEA7:\^KHAH\2
+FEA8:\^KHAH MEDI\X
+FEA9:\^DAL\Q
+FEAA:\^DAL\6
+FEAB:\^THAL\Q
+FEAC:\^THAL\6
+FEAD:\^REH\Q
+FEAE:\^REH\6
+FEAF:\^ZAIN\Q
+FEB0:\^ZAIN\6
+FEB1:\^SEEN\Q
+FEB2:\^SEEN\6
+FEB3:\^SEEN\2
+FEB4:\^SEEN MEDI\X
+FEB5:\^SHEEN\Q
+FEB6:\^SHEEN\6
+FEB7:\^SHEEN\2
+FEB8:\^SHEEN MEDI\X
+FEB9:\^SAD\Q
+FEBA:\^SAD\6
+FEBB:\^SAD\2
+FEBC:\^SAD MEDI\X
+FEBD:\^DAD\Q
+FEBE:\^DAD\6
+FEBF:\^DAD\2
+FEC0:\^DAD MEDI\X
+FEC1:\^TAH\Q
+FEC2:\^TAH\6
+FEC3:\^TAH\2
+FEC4:\^TAH MEDI\X
+FEC5:\^ZAH\Q
+FEC6:\^ZAH\6
+FEC7:\^ZAH\2
+FEC8:\^ZAH MEDI\X
+FEC9:\^AIN\Q
+FECA:\^AIN\6
+FECB:\^AIN\2
+FECC:\^AIN MEDI\X
+FECD:\^GHAIN\Q
+FECE:\^GHAIN\6
+FECF:\^GHAIN\2
+FED0:\^GHAIN MEDI\X
+FED1:\^FEH\Q
+FED2:\^FEH\6
+FED3:\^FEH\2
+FED4:\^FEH MEDI\X
+FED5:\^QAF\Q
+FED6:\^QAF\6
+FED7:\^QAF\2
+FED8:\^QAF MEDI\X
+FED9:\^KAF\Q
+FEDA:\^KAF\6
+FEDB:\^KAF\2
+FEDC:\^KAF MEDI\X
+FEDD:\^LAM\Q
+FEDE:\^LAM\6
+FEDF:\^LAM\2
+FEE0:\^LAM MEDI\X
+FEE1:\^MEEM\Q
+FEE2:\^MEEM\6
+FEE3:\^MEEM\2
+FEE4:\^MEEM MEDI\X
+FEE5:\^NOON\Q
+FEE6:\^NOON\6
+FEE7:\^NOON\2
+FEE8:\^NOON MEDI\X
+FEE9:\^HEH\Q
+FEEA:\^HEH\6
+FEEB:\^HEH\2
+FEEC:\^HEH MEDI\X
+FEED:\^WAW\Q
+FEEE:\^WAW\6
+FEEF:\^ALEF MAKSURA\Q
+FEF0:\^ALEF MAKSURA\6
+FEF1:\^YEH\Q
+FEF2:\^YEH\6
+FEF3:\^YEH\2
+FEF4:\^YEH MEDI\X
+FEF5:\JLAM\HALEF\HMADDA\p\Q
+FEF6:\JLAM\HALEF\HMADDA\p\6
+FEF7:\JLAM\HALEF\HHAMZA\p\Q
+FEF8:\JLAM\HALEF\HHAMZA\p\6
+FEF9:\JLAM\HALEF\HHAMZA\…\Q
+FEFA:\JLAM\HALEF\HHAMZA\…\6
+FEFB:\JLAM\HALEF\Q
+FEFC:\JLAM\HALEF\6
+FEFF:ZERO WIDTH NO-BREAK SPACE
+FF01:\†EXCLAM\”\¥
+FF02:\†QUOT\”\¥
+FF03:\†\­SIGN
+FF04:\†DOLLAR\‚
+FF05:\†PERCENT\‚
+FF06:\†AMPERSAND
+FF07:\†APOSTROPHE
+FF08:\†\‰ \ÑS
+FF09:\†\ù\ÑS
+FF0A:\†ASTERISK
+FF0B:\†PLUS\‚
+FF0C:\†COMMA
+FF0D:\†HYPHEN-MINUS
+FF0E:\†FULL STOP
+FF0F:\†SOLIDUS
+FF10:\†DIGIT ZERO
+FF11:\†DIGIT ONE
+FF12:\†DIGIT TWO
+FF13:\†DIGIT THREE
+FF14:\†DIGIT FOUR
+FF15:\†DIGIT FIVE
+FF16:\†DIGIT SIX
+FF17:\†DIGIT SEVEN
+FF18:\†DIGIT E\¼
+FF19:\†DIGIT NINE
+FF1A:\†COLON
+FF1B:\†SEMICOLON
+FF1C:\†\µ\‚
+FF1D:\†EQUALS\‚
+FF1E:\†\’\‚
+FF1F:\†QUESTION\¥
+FF20:\†COMMERCIAL AT
+FF21:\†\PA
+FF22:\†\PB
+FF23:\†\PC
+FF24:\†\PD
+FF25:\†\PE
+FF26:\†\PF
+FF27:\†\PG
+FF28:\†\PH
+FF29:\†\PI
+FF2A:\†\PJ
+FF2B:\†\PK
+FF2C:\†\PL
+FF2D:\†\PM
+FF2E:\†\PN
+FF2F:\†\PO
+FF30:\†\PP
+FF31:\†\PQ
+FF32:\†\PR
+FF33:\†\PS
+FF34:\†\PT
+FF35:\†\PU
+FF36:\†\PV
+FF37:\†\PW
+FF38:\†\PX
+FF39:\†\PY
+FF3A:\†\PZ
+FF3B:\†\‰ \r\–
+FF3C:\†REVERSE SOLIDUS
+FF3D:\†\ù\r\–
+FF3E:\†CIRCUMFLEX\×
+FF3F:\†LOW \ä
+FF40:\†GRAVE\×
+FF41:\†\LA
+FF42:\†\LB
+FF43:\†\LC
+FF44:\†\LD
+FF45:\†\LE
+FF46:\†\LF
+FF47:\†\LG
+FF48:\†\LH
+FF49:\†\LI
+FF4A:\†\LJ
+FF4B:\†\LK
+FF4C:\†\LL
+FF4D:\†\LM
+FF4E:\†\LN
+FF4F:\†\LO
+FF50:\†\LP
+FF51:\†\LQ
+FF52:\†\LR
+FF53:\†\LS
+FF54:\†\LT
+FF55:\†\LU
+FF56:\†\LV
+FF57:\†\LW
+FF58:\†\LX
+FF59:\†\LY
+FF5A:\†\LZ
+FF5B:\†\‰ CURLY \–
+FF5C:\†\€ \ä
+FF5D:\†\ùCURLY \–
+FF5E:\†\æ
+FF5F:\†\‰ \¦\ÑS
+FF60:\†\ù\¦\ÑS
+FF61:\4\8IC\é
+FF62:\4\‰ CORNER \–
+FF63:\4\ùCORNER \–
+FF64:\4\8IC COMMA
+FF65:\4\n MIDDLE DOT
+FF66:\4\ÍWO
+FF67:\4\Í\§A
+FF68:\4\Í\§I
+FF69:\4\Í\§U
+FF6A:\4\Í\§E
+FF6B:\4\Í\§O
+FF6C:\4\Í\§YA
+FF6D:\4\Í\§YU
+FF6E:\4\Í\§YO
+FF6F:\4\Í\§TU
+FF70:\4\n-HIRAGANA PROLONG\ÂSOUND\¥
+FF71:\4\ÍA
+FF72:\4\ÍI
+FF73:\4\ÍU
+FF74:\4\ÍE
+FF75:\4\ÍO
+FF76:\4\ÍKA
+FF77:\4\ÍKI
+FF78:\4\ÍKU
+FF79:\4\ÍKE
+FF7A:\4\ÍKO
+FF7B:\4\ÍSA
+FF7C:\4\ÍSI
+FF7D:\4\ÍSU
+FF7E:\4\ÍSE
+FF7F:\4\ÍSO
+FF80:\4\ÍTA
+FF81:\4\ÍTI
+FF82:\4\ÍTU
+FF83:\4\ÍTE
+FF84:\4\ÍTO
+FF85:\4\ÍNA
+FF86:\4\ÍNI
+FF87:\4\ÍNU
+FF88:\4\ÍNE
+FF89:\4\ÍNO
+FF8A:\4\ÍHA
+FF8B:\4\ÍHI
+FF8C:\4\ÍHU
+FF8D:\4\ÍHE
+FF8E:\4\ÍHO
+FF8F:\4\ÍMA
+FF90:\4\ÍMI
+FF91:\4\ÍMU
+FF92:\4\ÍME
+FF93:\4\ÍMO
+FF94:\4\ÍYA
+FF95:\4\ÍYU
+FF96:\4\ÍYO
+FF97:\4\ÍRA
+FF98:\4\ÍRI
+FF99:\4\ÍRU
+FF9A:\4\ÍRE
+FF9B:\4\ÍRO
+FF9C:\4\ÍWA
+FF9D:\4\ÍN
+FF9E:\4\n VOIC\ÂSOUND\¥
+FF9F:\4\n SEMI-VOIC\ÂSOUND\¥
+FFA0:\4\e FILLER
+FFA1:\4\ÖKIYEOK
+FFA2:\4\ÖSSANGKIYEOK
+FFA3:\4\ÖKIYEOK-SIOS
+FFA4:\4\ÖN\ÆN
+FFA5:\4\ÖN\ÆN-C\ÆC
+FFA6:\4\ÖN\ÆN-H\ÆH
+FFA7:\4\ÖTIKEUT
+FFA8:\4\ÖSSANGTIKEUT
+FFA9:\4\ÖR\ÆL
+FFAA:\4\ÖR\ÆL-KIYEOK
+FFAB:\4\ÖR\ÆL-M\ÆM
+FFAC:\4\ÖR\ÆL-P\ÆP
+FFAD:\4\ÖR\ÆL-SIOS
+FFAE:\4\ÖR\ÆL-TH\ÆTH
+FFAF:\4\ÖR\ÆL-PH\ÆPH
+FFB0:\4\ÖR\ÆL-H\ÆH
+FFB1:\4\ÖM\ÆM
+FFB2:\4\ÖP\ÆP
+FFB3:\4\ÖSSANGP\ÆP
+FFB4:\4\ÖP\ÆP-SIOS
+FFB5:\4\ÖSIOS
+FFB6:\4\ÖSSANGSIOS
+FFB7:\4\Ö\ÆNG
+FFB8:\4\ÖC\ÆC
+FFB9:\4\ÖSSANGC\ÆC
+FFBA:\4\ÖCH\ÆCH
+FFBB:\4\ÖKH\ÆKH
+FFBC:\4\ÖTH\ÆTH
+FFBD:\4\ÖPH\ÆPH
+FFBE:\4\ÖH\ÆH
+FFC2:\4\ÖA
+FFC3:\4\ÖAE
+FFC4:\4\ÖYA
+FFC5:\4\ÖYAE
+FFC6:\4\ÖEO
+FFC7:\4\ÖE
+FFCA:\4\ÖYEO
+FFCB:\4\ÖYE
+FFCC:\4\ÖO
+FFCD:\4\ÖWA
+FFCE:\4\ÖWAE
+FFCF:\4\ÖOE
+FFD2:\4\ÖYO
+FFD3:\4\ÖU
+FFD4:\4\ÖWEO
+FFD5:\4\ÖWE
+FFD6:\4\ÖWI
+FFD7:\4\ÖYU
+FFDA:\4\ÖEU
+FFDB:\4\ÖYI
+FFDC:\4\ÖI
+FFE0:\†CENT\‚
+FFE1:\†POUND\‚
+FFE2:\†NOT\‚
+FFE3:\†\å
+FFE4:\†BROKEN\ì
+FFE5:\†YEN\‚
+FFE6:\†WON\‚
+FFE8:\4FORMS L\¼ \€
+FFE9:\4\‰\Š\u
+FFEA:\4UP\Š\u
+FFEB:\4\Ù
+FFEC:\4\Ë\Š\u
+FFED:\4\¬ \ý
+FFEE:\4\¦\Ð
+FFF9:INTER\äAR ANNOT\” ANCHOR
+FFFA:INTER\äAR ANNOT\” SEPARATOR
+FFFB:INTER\äAR ANNOT\” TERMINATOR
+FFFC:OBJECT REPLACEMENT CHARACTER
+FFFD:REPLACEMENT CHARACTER
+10300:OLD \f\@A
+10301:OLD \f\@BE
+10302:OLD \f\@KE
+10303:OLD \f\@DE
+10304:OLD \f\@E
+10305:OLD \f\@VE
+10306:OLD \f\@ZE
+10307:OLD \f\@HE
+10308:OLD \f\@THE
+10309:OLD \f\@I
+1030A:OLD \f\@KA
+1030B:OLD \f\@EL
+1030C:OLD \f\@EM
+1030D:OLD \f\@EN
+1030E:OLD \f\@ESH
+1030F:OLD \f\@O
+10310:OLD \f\@PE
+10311:OLD \f\@SHE
+10312:OLD \f\@KU
+10313:OLD \f\@ER
+10314:OLD \f\@ES
+10315:OLD \f\@TE
+10316:OLD \f\@U
+10317:OLD \f\@EKS
+10318:OLD \f\@PHE
+10319:OLD \f\@KHE
+1031A:OLD \f\@EF
+1031B:OLD \f\@ERS
+1031C:OLD \f\@CHE
+1031D:OLD \f\@II
+1031E:OLD \f\@UU
+10320:OLD \f NUMERAL ONE
+10321:OLD \f NUMERAL FIVE
+10322:OLD \f NUMERAL TEN
+10323:OLD \f NUMERAL FIFTY
+10330:GOTHIC\@AHSA
+10331:GOTHIC\@BAIRKAN
+10332:GOTHIC\@GIBA
+10333:GOTHIC\@DAGS
+10334:GOTHIC\@AIHVUS
+10335:GOTHIC\@QAIRTHRA
+10336:GOTHIC\@IUJA
+10337:GOTHIC\@HAGL
+10338:GOTHIC\@THIUTH
+10339:GOTHIC\@EIS
+1033A:GOTHIC\@KUSMA
+1033B:GOTHIC\@LAGUS
+1033C:GOTHIC\@MANNA
+1033D:GOTHIC\@NAUTHS
+1033E:GOTHIC\@JER
+1033F:GOTHIC\@URUS
+10340:GOTHIC\@PAIRTHRA
+10341:GOTHIC\@NINETY
+10342:GOTHIC\@RAIDA
+10343:GOTHIC\@SAUIL
+10344:GOTHIC\@TEIWS
+10345:GOTHIC\@WINJA
+10346:GOTHIC\@FAIHU
+10347:GOTHIC\@IGGWS
+10348:GOTHIC\@HWAIR
+10349:GOTHIC\@OTHAL
+1034A:GOTHIC\@NINE HUNDRED
+10400:\¿\ãLONG I
+10401:\¿\ãLONG E
+10402:\¿\ãLONG A
+10403:\¿\ãLONG AH
+10404:\¿\ãLONG O
+10405:\¿\ãLONG OO
+10406:\¿\ãSHORT I
+10407:\¿\ãSHORT E
+10408:\¿\ãSHORT A
+10409:\¿\ãSHORT AH
+1040A:\¿\ãSHORT O
+1040B:\¿\ãSHORT OO
+1040C:\¿\ãAY
+1040D:\¿\ãOW
+1040E:\¿\ãWU
+1040F:\¿\ãYEE
+10410:\¿\ãH
+10411:\¿\ãPEE
+10412:\¿\ãBEE
+10413:\¿\ãTEE
+10414:\¿\ãDEE
+10415:\¿\ãCHEE
+10416:\¿\ãJEE
+10417:\¿\ãKAY
+10418:\¿\ãGAY
+10419:\¿\ãEF
+1041A:\¿\ãVEE
+1041B:\¿\ãETH
+1041C:\¿\ãTHEE
+1041D:\¿\ãES
+1041E:\¿\ãZEE
+1041F:\¿\ãESH
+10420:\¿\ãZHEE
+10421:\¿\ãER
+10422:\¿\ãEL
+10423:\¿\ãEM
+10424:\¿\ãEN
+10425:\¿\ãENG
+10428:\¿\N\@LONG I
+10429:\¿\N\@LONG E
+1042A:\¿\N\@LONG A
+1042B:\¿\N\@LONG AH
+1042C:\¿\N\@LONG O
+1042D:\¿\N\@LONG OO
+1042E:\¿\N\@SHORT I
+1042F:\¿\N\@SHORT E
+10430:\¿\N\@SHORT A
+10431:\¿\N\@SHORT AH
+10432:\¿\N\@SHORT O
+10433:\¿\N\@SHORT OO
+10434:\¿\N\@AY
+10435:\¿\N\@OW
+10436:\¿\N\@WU
+10437:\¿\N\@YEE
+10438:\¿\N\@H
+10439:\¿\N\@PEE
+1043A:\¿\N\@BEE
+1043B:\¿\N\@TEE
+1043C:\¿\N\@DEE
+1043D:\¿\N\@CHEE
+1043E:\¿\N\@JEE
+1043F:\¿\N\@KAY
+10440:\¿\N\@GAY
+10441:\¿\N\@EF
+10442:\¿\N\@VEE
+10443:\¿\N\@ETH
+10444:\¿\N\@THEE
+10445:\¿\N\@ES
+10446:\¿\N\@ZEE
+10447:\¿\N\@ESH
+10448:\¿\N\@ZHEE
+10449:\¿\N\@ER
+1044A:\¿\N\@EL
+1044B:\¿\N\@EM
+1044C:\¿\N\@EN
+1044D:\¿\N\@ENG
+1D000:\YPSILI
+1D001:\YDASEIA
+1D002:\Y\´
+1D003:\YOXEIA EKFONITIKON
+1D004:\YOXEIA DIPLI
+1D005:\YVAREIA EKFONITIKON
+1D006:\YVAREIA DIPLI
+1D007:\YKATHISTI
+1D008:\YSYRMATIKI
+1D009:\YPARAKLITIKI
+1D00A:\YYPOKRISIS
+1D00B:\YYPOKRISIS DIPLI
+1D00C:\YKREMASTI
+1D00D:\YAPESO EKFONITIKON
+1D00E:\YEXO EKFONITIKON
+1D00F:\YTELEIA
+1D010:\YKENTIMATA
+1D011:\YAPOSTROFOS
+1D012:\YAPOSTROFOS DIPLI
+1D013:\YSYNEVMA
+1D014:\YTHITA
+1D015:\YOLIGON ARCHAION
+1D016:\YGORGON ARCHAION
+1D017:\Y\É
+1D018:\YCHAMILON
+1D019:\YVATHY
+1D01A:\YISON ARCHAION
+1D01B:\YKENTIMA ARCHAION
+1D01C:\YKENTIMATA ARCHAION
+1D01D:\YSAXIMATA
+1D01E:\YPARICHON
+1D01F:\YSTAVROS APODEXIA
+1D020:\YOXEIAI ARCHAION
+1D021:\YVAREIAI ARCHAION
+1D022:\YAPODERMA ARCHAION
+1D023:\YAPOTHEMA
+1D024:\YKLASMA
+1D025:\YREVMA
+1D026:\YPIASMA ARCHAION
+1D027:\YTINAGMA
+1D028:\YANATRICHISMA
+1D029:\YSEISMA
+1D02A:\YSYNAGMA ARCHAION
+1D02B:\YSYNAGMA META STAVROU
+1D02C:\YOYRANISMA ARCHAION
+1D02D:\YTHEMA
+1D02E:\YLEMOI
+1D02F:\YDYO
+1D030:\YTRIA
+1D031:\YTESSERA
+1D032:\YKRATIMATA
+1D033:\YAPESO EXO NEO
+1D034:\YFTHORA ARCHAION
+1D035:\YIMIFTHORA
+1D036:\YTROMIKON ARCHAION
+1D037:\YKATAVA TROMIKON
+1D038:\YPELASTON
+1D039:\YPSIFISTON
+1D03A:\YKONTEVMA
+1D03B:\YCHOREVMA ARCHAION
+1D03C:\YRAPISMA
+1D03D:\YPARAKALESMA ARCHAION
+1D03E:\YPARAKLITIKI ARCHAION
+1D03F:\YICHADIN
+1D040:\YNANA
+1D041:\YPETASMA
+1D042:\YKONTEVMA ALLO
+1D043:\YTROMIKON ALLO
+1D044:\YSTRAGGISMATA
+1D045:\YGRONTHISMATA
+1D046:\YISON NEO
+1D047:\YOLIGON NEO
+1D048:\YOXEIA NEO
+1D049:\YPETASTI
+1D04A:\YKOUFISMA
+1D04B:\YPETASTOKOUFISMA
+1D04C:\YKRATIMOKOUFISMA
+1D04D:\YPELASTON NEO
+1D04E:\YKENTIMATA NEO ANO
+1D04F:\YKENTIMA NEO ANO
+1D050:\YYPSILI
+1D051:\YAPOSTROFOS NEO
+1D052:\YAPOSTROFOI SYNDESMOS NEO
+1D053:\YYPORROI
+1D054:\YKRATIMOYPORROON
+1D055:\YELAFRON
+1D056:\YCHAMILI
+1D057:\YMIKRON ISON
+1D058:\YVAREIA NEO
+1D059:\YPIASMA NEO
+1D05A:\YPSIFISTON NEO
+1D05B:\YOMALON
+1D05C:\YANTIKENOMA
+1D05D:\YLYGISMA
+1D05E:\YPARAKLITIKI NEO
+1D05F:\YPARAKALESMA NEO
+1D060:\YETERON PARAKALESMA
+1D061:\YKYLISMA
+1D062:\YANTIKENOKYLISMA
+1D063:\YTROMIKON NEO
+1D064:\YEKSTREPTON
+1D065:\YSYNAGMA NEO
+1D066:\YSYRMA
+1D067:\YCHOREVMA NEO
+1D068:\YEPEGERMA
+1D069:\YSEISMA NEO
+1D06A:\YXIRON KLASMA
+1D06B:\YTROMIKOPSIFISTON
+1D06C:\YPSIFISTOLYGISMA
+1D06D:\YTROMIKOLYGISMA
+1D06E:\YTROMIKOPARAKALESMA
+1D06F:\YPSIFISTOPARAKALESMA
+1D070:\YTROMIKOSYNAGMA
+1D071:\YPSIFISTOSYNAGMA
+1D072:\YGORGOSYNTHETON
+1D073:\YARGOSYNTHETON
+1D074:\YETERON ARGOSYNTHETON
+1D075:\YOYRANISMA NEO
+1D076:\YTHEMATISMOS ESO
+1D077:\YTHEMATISMOS EXO
+1D078:\YTHEMA APLOUN
+1D079:\YTHES KAI APOTHES
+1D07A:\YKATAVASMA
+1D07B:\YENDOFONON
+1D07C:\YYFEN KATO
+1D07D:\YYFEN ANO
+1D07E:\YSTAVROS
+1D07F:\YKLASMA ANO
+1D080:\YDIPLI ARCHAION
+1D081:\YKRATIMA ARCHAION
+1D082:\YKRATIMA ALLO
+1D083:\YKRATIMA NEO
+1D084:\YAPODERMA NEO
+1D085:\YAPLI
+1D086:\YDIPLI
+1D087:\YTRIPLI
+1D088:\YTETRAPLI
+1D089:\YKORONIS
+1D08A:\YLEIMMA ENOS CHRONOU
+1D08B:\YLEIMMA DYO CHRONON
+1D08C:\YLEIMMA TRION CHRONON
+1D08D:\YLEIMMA TESSARON CHRONON
+1D08E:\YLEIMMA IMISEOS CHRONOU
+1D08F:\YGORGON NEO ANO
+1D090:\YGORGON PARESTIGMENON ARISTERA
+1D091:\YGORGON PARESTIGMENON DEXIA
+1D092:\YDIGORGON
+1D093:\YDIGORGON PARESTIGMENON ARISTERA KATO
+1D094:\YDIGORGON PARESTIGMENON ARISTERA ANO
+1D095:\YDIGORGON PARESTIGMENON DEXIA
+1D096:\YTRIGORGON
+1D097:\YARGON
+1D098:\YIMIDIARGON
+1D099:\YDIARGON
+1D09A:\YAGOGI POLI ARGI
+1D09B:\YAGOGI ARGOTERI
+1D09C:\YAGOGI ARGI
+1D09D:\YAGOGI METRIA
+1D09E:\YAGOGI MESI
+1D09F:\YAGOGI GORGI
+1D0A0:\YAGOGI GORGOTERI
+1D0A1:\YAGOGI POLI GORGI
+1D0A2:\YMARTYRIA PROTOS ICHOS
+1D0A3:\YMARTYRIA ALLI PROTOS ICHOS
+1D0A4:\YMARTYRIA DEYTEROS ICHOS
+1D0A5:\YMARTYRIA ALLI DEYTEROS ICHOS
+1D0A6:\YMARTYRIA TRITOS ICHOS
+1D0A7:\YMARTYRIA TRIFONIAS
+1D0A8:\YMARTYRIA TETARTOS ICHOS
+1D0A9:\YMARTYRIA TETARTOS LEGETOS ICHOS
+1D0AA:\YMARTYRIA LEGETOS ICHOS
+1D0AB:\YMARTYRIA PLAGIOS ICHOS
+1D0AC:\YISAKIA TELOUS ICHIMATOS
+1D0AD:\YAPOSTROFOI TELOUS ICHIMATOS
+1D0AE:\YFANEROSIS TETRAFONIAS
+1D0AF:\YFANEROSIS MONOFONIAS
+1D0B0:\YFANEROSIS DIFONIAS
+1D0B1:\YMARTYRIA VARYS ICHOS
+1D0B2:\YMARTYRIA PROTOVARYS ICHOS
+1D0B3:\YMARTYRIA PLAGIOS TETARTOS ICHOS
+1D0B4:\YGORTHMIKON N APLOUN
+1D0B5:\YGORTHMIKON N DIPLOUN
+1D0B6:\YENARXIS KAI FTHORA VOU
+1D0B7:\YIMIFONON
+1D0B8:\YIMIFTHORON
+1D0B9:\YFTHORA ARCHAION DEYTEROU ICHOU
+1D0BA:\YFTHORA DIATONIKI PA
+1D0BB:\YFTHORA DIATONIKI NANA
+1D0BC:\YFTHORA NAOS ICHOS
+1D0BD:\YFTHORA DIATONIKI DI
+1D0BE:\YFTHORA SKLIRON DIATONON DI
+1D0BF:\YFTHORA DIATONIKI KE
+1D0C0:\YFTHORA DIATONIKI ZO
+1D0C1:\YFTHORA DIATONIKI NI KATO
+1D0C2:\YFTHORA DIATONIKI NI ANO
+1D0C3:\YFTHORA MALAKON CHROMA DIFONIAS
+1D0C4:\YFTHORA MALAKON CHROMA MONOFONIAS
+1D0C5:\YFHTORA SKLIRON CHROMA VASIS
+1D0C6:\YFTHORA SKLIRON CHROMA SYNAFI
+1D0C7:\YFTHORA NENANO
+1D0C8:\YCHROA ZYGOS
+1D0C9:\YCHROA KLITON
+1D0CA:\YCHROA SPATHI
+1D0CB:\YFTHORA I YFESIS TETARTIMORION
+1D0CC:\YFTHORA ENARMONIOS ANTIFONIA
+1D0CD:\YYFESIS TRITIMORION
+1D0CE:\YDIESIS TRITIMORION
+1D0CF:\YDIESIS TETARTIMORION
+1D0D0:\YDIESIS APLI DYO DODEKATA
+1D0D1:\YDIESIS MONOGRAMMOS TESSERA DODEKATA
+1D0D2:\YDIESIS DIGRAMMOS EX DODEKATA
+1D0D3:\YDIESIS TRIGRAMMOS OKTO DODEKATA
+1D0D4:\YYFESIS APLI DYO DODEKATA
+1D0D5:\YYFESIS MONOGRAMMOS TESSERA DODEKATA
+1D0D6:\YYFESIS DIGRAMMOS EX DODEKATA
+1D0D7:\YYFESIS TRIGRAMMOS OKTO DODEKATA
+1D0D8:\YGENIKI DIESIS
+1D0D9:\YGENIKI YFESIS
+1D0DA:\YDIASTOLI APLI MIKRI
+1D0DB:\YDIASTOLI APLI MEGALI
+1D0DC:\YDIASTOLI DIPLI
+1D0DD:\YDIASTOLI THESEOS
+1D0DE:\YSIMANSIS THESEOS
+1D0DF:\YSIMANSIS THESEOS DISIMOU
+1D0E0:\YSIMANSIS THESEOS TRISIMOU
+1D0E1:\YSIMANSIS THESEOS TETRASIMOU
+1D0E2:\YSIMANSIS ARSEOS
+1D0E3:\YSIMANSIS ARSEOS DISIMOU
+1D0E4:\YSIMANSIS ARSEOS TRISIMOU
+1D0E5:\YSIMANSIS ARSEOS TETRASIMOU
+1D0E6:\YDIGRAMMA GG
+1D0E7:\YDIFTOGGOS OU
+1D0E8:\YSTIGMA
+1D0E9:\YARKTIKO PA
+1D0EA:\YARKTIKO VOU
+1D0EB:\YARKTIKO GA
+1D0EC:\YARKTIKO DI
+1D0ED:\YARKTIKO KE
+1D0EE:\YARKTIKO ZO
+1D0EF:\YARKTIKO NI
+1D0F0:\YKENTIMATA NEO MESO
+1D0F1:\YKENTIMA NEO MESO
+1D0F2:\YKENTIMATA NEO KATO
+1D0F3:\YKENTIMA NEO KATO
+1D0F4:\YKLASMA KATO
+1D0F5:\YGORGON NEO KATO
+1D100:\KS\ôLE\ì\ä
+1D101:\K\0\ì\ä
+1D102:\KFINAL\ì\ä
+1D103:\KREVERSE FINAL\ì\ä
+1D104:\KDASHED\ì\ä
+1D105:\KSHORT\ì\ä
+1D106:\K\‰ REPEAT\‚
+1D107:\K\ùREPEAT\‚
+1D108:\KREPEAT DOTS
+1D109:\KDAL SEGNO
+1D10A:\KDA CAPO
+1D10B:\KSEGNO
+1D10C:\KCODA
+1D10D:\KREPEAT\ÂFIGURE-1
+1D10E:\KREPEAT\ÂFIGURE-2
+1D10F:\KREPEAT\ÂFIGURE-3
+1D110:\KFERMATA
+1D111:\KFERMATA\…
+1D112:\KBREATH\¥
+1D113:\KCAESURA
+1D114:\KBRACE
+1D115:\K\–
+1D116:\KONE-\ä STAFF
+1D117:\KTWO-\ä STAFF
+1D118:\KTHREE-\ä STAFF
+1D119:\KFOUR-\ä STAFF
+1D11A:\KFIVE-\ä STAFF
+1D11B:\KSIX-\ä STAFF
+1D11C:\KSIX-STR\ô FRETBOARD
+1D11D:\KFOUR-STR\ô FRETBOARD
+1D11E:\KG CLEF
+1D11F:\KG CLEF OTTAVA ALTA
+1D120:\KG CLEF OTTAVA BASSA
+1D121:\KC CLEF
+1D122:\KF CLEF
+1D123:\KF CLEF OTTAVA ALTA
+1D124:\KF CLEF OTTAVA BASSA
+1D125:\KDRUM CLEF-1
+1D126:\KDRUM CLEF-2
+1D12A:\K\0 SHARP
+1D12B:\K\0 FLAT
+1D12C:\KFLAT UP
+1D12D:\KFLAT \Ë
+1D12E:\KNATURAL UP
+1D12F:\KNATURAL \Ë
+1D130:\KSHARP UP
+1D131:\KSHARP \Ë
+1D132:\KQUARTER TONE SHARP
+1D133:\KQUARTER TONE FLAT
+1D134:\KCOMMON TIME
+1D135:\KCUT TIME
+1D136:\KOTTAVA ALTA
+1D137:\KOTTAVA BASSA
+1D138:\KQUINDICESIMA ALTA
+1D139:\KQUINDICESIMA BASSA
+1D13A:\KMULTI REST
+1D13B:\KWHOLE REST
+1D13C:\KHALF REST
+1D13D:\KQUARTER REST
+1D13E:\KE\¼H REST
+1D13F:\KSIXTEENTH REST
+1D140:\KTHIRTY-SECOND REST
+1D141:\KSIXTY-FOURTH REST
+1D142:\KONE HUNDR\ÂTWENTY-E\¼H REST
+1D143:\KX NOTEHEAD
+1D144:\KPLUS NOTEHEAD
+1D145:\K\Ð X NOTEHEAD
+1D146:\K\rNOTEHEAD WHITE
+1D147:\K\rNOTEHEAD \¬
+1D148:\K\¾ NOTEHEAD UP WHITE
+1D149:\K\¾ NOTEHEAD UP \¬
+1D14A:\K\¾ NOTEHEAD \‰ WHITE
+1D14B:\K\¾ NOTEHEAD \‰ \¬
+1D14C:\K\¾ NOTEHEAD \ùWHITE
+1D14D:\K\¾ NOTEHEAD \ù\¬
+1D14E:\K\¾ NOTEHEAD \Ë WHITE
+1D14F:\K\¾ NOTEHEAD \Ë \¬
+1D150:\K\¾ NOTEHEAD UP \ùWHITE
+1D151:\K\¾ NOTEHEAD UP \ù\¬
+1D152:\KMOON NOTEHEAD WHITE
+1D153:\KMOON NOTEHEAD \¬
+1D154:\K\¾-ROUND NOTEHEAD \Ë WHITE
+1D155:\K\¾-ROUND NOTEHEAD \Ë \¬
+1D156:\K\ÑS NOTEHEAD
+1D157:\KVOID NOTEHEAD
+1D158:\KNOTEHEAD \¬
+1D159:\KNULL NOTEHEAD
+1D15A:\KCLUSTER NOTEHEAD WHITE
+1D15B:\KCLUSTER NOTEHEAD \¬
+1D15C:\KBREVE
+1D15D:\KWHOLE NOTE
+1D15E:\KHALF NOTE
+1D15F:\KQUARTER NOTE
+1D160:\KE\¼H NOTE
+1D161:\KSIXTEENTH NOTE
+1D162:\KTHIRTY-SECOND NOTE
+1D163:\KSIXTY-FOURTH NOTE
+1D164:\KONE HUNDR\ÂTWENTY-E\¼H NOTE
+1D165:\K\oSTEM
+1D166:\K\oSPRECHGESANG STEM
+1D167:\K\oTREMOLO-1
+1D168:\K\oTREMOLO-2
+1D169:\K\oTREMOLO-3
+1D16A:\KF\ôER\ÂTREMOLO-1
+1D16B:\KF\ôER\ÂTREMOLO-2
+1D16C:\KF\ôER\ÂTREMOLO-3
+1D16D:\K\oAUGMENT\” DOT
+1D16E:\K\oFLAG-1
+1D16F:\K\oFLAG-2
+1D170:\K\oFLAG-3
+1D171:\K\oFLAG-4
+1D172:\K\oFLAG-5
+1D173:\KBEGIN BEAM
+1D174:\KEND BEAM
+1D175:\KBEGIN TIE
+1D176:\KEND TIE
+1D177:\KBEGIN SLUR
+1D178:\KEND SLUR
+1D179:\KBEGIN PHRASE
+1D17A:\KEND PHRASE
+1D17B:\K\oACCENT
+1D17C:\K\oSTACCATO
+1D17D:\K\oTENUTO
+1D17E:\K\oSTACCATISSIMO
+1D17F:\K\oMARCATO
+1D180:\K\oMARCATO-STACCATO
+1D181:\K\oACCENT-STACCATO
+1D182:\K\oLOURE
+1D183:\KARPEGGIATO UP
+1D184:\KARPEGGIATO \Ë
+1D185:\K\oDOIT
+1D186:\K\oRIP
+1D187:\K\oFLIP
+1D188:\K\oSMEAR
+1D189:\K\oBEND
+1D18A:\K\o\0 TONGUE
+1D18B:\K\oTRIPLE TONGUE
+1D18C:\KRINFORZANDO
+1D18D:\KSUBITO
+1D18E:\KZ
+1D18F:\KPIANO
+1D190:\KMEZZO
+1D191:\KFORTE
+1D192:\KCRESCENDO
+1D193:\KDECRESCENDO
+1D194:\KGRACE NOTE SLASH
+1D195:\KGRACE NOTE NO SLASH
+1D196:\KTR
+1D197:\KTURN
+1D198:\KINVERT\ÂTURN
+1D199:\KTURN SLASH
+1D19A:\KTURN UP
+1D19B:\KORNAMENT \Á-1
+1D19C:\KORNAMENT \Á-2
+1D19D:\KORNAMENT \Á-3
+1D19E:\KORNAMENT \Á-4
+1D19F:\KORNAMENT \Á-5
+1D1A0:\KORNAMENT \Á-6
+1D1A1:\KORNAMENT \Á-7
+1D1A2:\KORNAMENT \Á-8
+1D1A3:\KORNAMENT \Á-9
+1D1A4:\KORNAMENT \Á-10
+1D1A5:\KORNAMENT \Á-11
+1D1A6:\KHAUPTSTIMME
+1D1A7:\KNEBENSTIMME
+1D1A8:\KEND OF STIMME
+1D1A9:\KDEGREE SLASH
+1D1AA:\K\o\Ë BOW
+1D1AB:\K\oUP BOW
+1D1AC:\K\oHARMONIC
+1D1AD:\K\oSNAP PIZZICATO
+1D1AE:\KPEDAL\¥
+1D1AF:\KPEDAL UP\¥
+1D1B0:\KHALF PEDAL\¥
+1D1B1:\KGLISSANDO UP
+1D1B2:\KGLISSANDO \Ë
+1D1B3:\KWITH F\ôERNAILS
+1D1B4:\KDAMP
+1D1B5:\KDAMP ALL
+1D1B6:\KMAXIMA
+1D1B7:\KLONGA
+1D1B8:\KBREVIS
+1D1B9:\KSEMIBREVIS WHITE
+1D1BA:\KSEMIBREVIS \¬
+1D1BB:\KMINIMA
+1D1BC:\KMINIMA \¬
+1D1BD:\KSEMIMINIMA WHITE
+1D1BE:\KSEMIMINIMA \¬
+1D1BF:\KFUSA WHITE
+1D1C0:\KFUSA \¬
+1D1C1:\KLONGA PERFECTA REST
+1D1C2:\KLONGA IMPERFECTA REST
+1D1C3:\KBREVIS REST
+1D1C4:\KSEMIBREVIS REST
+1D1C5:\KMINIMA REST
+1D1C6:\KSEMIMINIMA REST
+1D1C7:\KTEMPUS PERFECTUM CUM PROL\”E PERFECTA
+1D1C8:\KTEMPUS PERFECTUM CUM PROL\”E IMPERFECTA
+1D1C9:\KTEMPUS PERFECTUM CUM PROL\”E PERFECTA DIMINUTION-1
+1D1CA:\KTEMPUS IMPERFECTUM CUM PROL\”E PERFECTA
+1D1CB:\KTEMPUS IMPERFECTUM CUM PROL\”E IMPERFECTA
+1D1CC:\KTEMPUS IMPERFECTUM CUM PROL\”E IMPERFECTA DIMINUTION-1
+1D1CD:\KTEMPUS IMPERFECTUM CUM PROL\”E IMPERFECTA DIMINUTION-2
+1D1CE:\KTEMPUS IMPERFECTUM CUM PROL\”E IMPERFECTA DIMINUTION-3
+1D1CF:\KCROIX
+1D1D0:\KGREGORIAN C CLEF
+1D1D1:\KGREGORIAN F CLEF
+1D1D2:\K\rB
+1D1D3:\KVIRGA
+1D1D4:\KPODATUS
+1D1D5:\KCLIVIS
+1D1D6:\KSCANDICUS
+1D1D7:\KCLIMACUS
+1D1D8:\KTORCULUS
+1D1D9:\KPORRECTUS
+1D1DA:\KPORRECTUS FLEXUS
+1D1DB:\KSCANDICUS FLEXUS
+1D1DC:\KTORCULUS RESUPINUS
+1D1DD:\KPES SUBPUNCTIS
+1D400:\îCAPITAL A
+1D401:\îCAPITAL B
+1D402:\îCAPITAL C
+1D403:\îCAPITAL D
+1D404:\îCAPITAL E
+1D405:\îCAPITAL F
+1D406:\îCAPITAL G
+1D407:\îCAPITAL H
+1D408:\îCAPITAL I
+1D409:\îCAPITAL J
+1D40A:\îCAPITAL K
+1D40B:\îCAPITAL L
+1D40C:\îCAPITAL M
+1D40D:\îCAPITAL N
+1D40E:\îCAPITAL O
+1D40F:\îCAPITAL P
+1D410:\îCAPITAL Q
+1D411:\îCAPITAL R
+1D412:\îCAPITAL S
+1D413:\îCAPITAL T
+1D414:\îCAPITAL U
+1D415:\îCAPITAL V
+1D416:\îCAPITAL W
+1D417:\îCAPITAL X
+1D418:\îCAPITAL Y
+1D419:\îCAPITAL Z
+1D41A:\î\§A
+1D41B:\î\§B
+1D41C:\î\§C
+1D41D:\î\§D
+1D41E:\î\§E
+1D41F:\î\§F
+1D420:\î\§G
+1D421:\î\§H
+1D422:\î\§I
+1D423:\î\§J
+1D424:\î\§K
+1D425:\î\§L
+1D426:\î\§M
+1D427:\î\§N
+1D428:\î\§O
+1D429:\î\§P
+1D42A:\î\§Q
+1D42B:\î\§R
+1D42C:\î\§S
+1D42D:\î\§T
+1D42E:\î\§U
+1D42F:\î\§V
+1D430:\î\§W
+1D431:\î\§X
+1D432:\î\§Y
+1D433:\î\§Z
+1D434:\E\›A
+1D435:\E\›B
+1D436:\E\›C
+1D437:\E\›D
+1D438:\E\›E
+1D439:\E\›F
+1D43A:\E\›G
+1D43B:\E\›H
+1D43C:\E\›I
+1D43D:\E\›J
+1D43E:\E\›K
+1D43F:\E\›L
+1D440:\E\›M
+1D441:\E\›N
+1D442:\E\›O
+1D443:\E\›P
+1D444:\E\›Q
+1D445:\E\›R
+1D446:\E\›S
+1D447:\E\›T
+1D448:\E\›U
+1D449:\E\›V
+1D44A:\E\›W
+1D44B:\E\›X
+1D44C:\E\›Y
+1D44D:\E\›Z
+1D44E:\E\—A
+1D44F:\E\—B
+1D450:\E\—C
+1D451:\E\—D
+1D452:\E\—E
+1D453:\E\—F
+1D454:\E\—G
+1D456:\E\—I
+1D457:\E\—J
+1D458:\E\—K
+1D459:\E\—L
+1D45A:\E\—M
+1D45B:\E\—N
+1D45C:\E\—O
+1D45D:\E\—P
+1D45E:\E\—Q
+1D45F:\E\—R
+1D460:\E\—S
+1D461:\E\—T
+1D462:\E\—U
+1D463:\E\—V
+1D464:\E\—W
+1D465:\E\—X
+1D466:\E\—Y
+1D467:\E\—Z
+1D468:\î\›A
+1D469:\î\›B
+1D46A:\î\›C
+1D46B:\î\›D
+1D46C:\î\›E
+1D46D:\î\›F
+1D46E:\î\›G
+1D46F:\î\›H
+1D470:\î\›I
+1D471:\î\›J
+1D472:\î\›K
+1D473:\î\›L
+1D474:\î\›M
+1D475:\î\›N
+1D476:\î\›O
+1D477:\î\›P
+1D478:\î\›Q
+1D479:\î\›R
+1D47A:\î\›S
+1D47B:\î\›T
+1D47C:\î\›U
+1D47D:\î\›V
+1D47E:\î\›W
+1D47F:\î\›X
+1D480:\î\›Y
+1D481:\î\›Z
+1D482:\î\—A
+1D483:\î\—B
+1D484:\î\—C
+1D485:\î\—D
+1D486:\î\—E
+1D487:\î\—F
+1D488:\î\—G
+1D489:\î\—H
+1D48A:\î\—I
+1D48B:\î\—J
+1D48C:\î\—K
+1D48D:\î\—L
+1D48E:\î\—M
+1D48F:\î\—N
+1D490:\î\—O
+1D491:\î\—P
+1D492:\î\—Q
+1D493:\î\—R
+1D494:\î\—S
+1D495:\î\—T
+1D496:\î\—U
+1D497:\î\—V
+1D498:\î\—W
+1D499:\î\—X
+1D49A:\î\—Y
+1D49B:\î\—Z
+1D49C:\E\Ž\ÒA
+1D49E:\E\Ž\ÒC
+1D49F:\E\Ž\ÒD
+1D4A2:\E\Ž\ÒG
+1D4A5:\E\Ž\ÒJ
+1D4A6:\E\Ž\ÒK
+1D4A9:\E\Ž\ÒN
+1D4AA:\E\Ž\ÒO
+1D4AB:\E\Ž\ÒP
+1D4AC:\E\Ž\ÒQ
+1D4AE:\E\Ž\ÒS
+1D4AF:\E\Ž\ÒT
+1D4B0:\E\Ž\ÒU
+1D4B1:\E\Ž\ÒV
+1D4B2:\E\Ž\ÒW
+1D4B3:\E\Ž\ÒX
+1D4B4:\E\Ž\ÒY
+1D4B5:\E\Ž\ÒZ
+1D4B6:\E\Ž\ÇA
+1D4B7:\E\Ž\ÇB
+1D4B8:\E\Ž\ÇC
+1D4B9:\E\Ž\ÇD
+1D4BB:\E\Ž\ÇF
+1D4BD:\E\Ž\ÇH
+1D4BE:\E\Ž\ÇI
+1D4BF:\E\Ž\ÇJ
+1D4C0:\E\Ž\ÇK
+1D4C2:\E\Ž\ÇM
+1D4C3:\E\Ž\ÇN
+1D4C5:\E\Ž\ÇP
+1D4C6:\E\Ž\ÇQ
+1D4C7:\E\Ž\ÇR
+1D4C8:\E\Ž\ÇS
+1D4C9:\E\Ž\ÇT
+1D4CA:\E\Ž\ÇU
+1D4CB:\E\Ž\ÇV
+1D4CC:\E\Ž\ÇW
+1D4CD:\E\Ž\ÇX
+1D4CE:\E\Ž\ÇY
+1D4CF:\E\Ž\ÇZ
+1D4D0:\î\Ž\ÒA
+1D4D1:\î\Ž\ÒB
+1D4D2:\î\Ž\ÒC
+1D4D3:\î\Ž\ÒD
+1D4D4:\î\Ž\ÒE
+1D4D5:\î\Ž\ÒF
+1D4D6:\î\Ž\ÒG
+1D4D7:\î\Ž\ÒH
+1D4D8:\î\Ž\ÒI
+1D4D9:\î\Ž\ÒJ
+1D4DA:\î\Ž\ÒK
+1D4DB:\î\Ž\ÒL
+1D4DC:\î\Ž\ÒM
+1D4DD:\î\Ž\ÒN
+1D4DE:\î\Ž\ÒO
+1D4DF:\î\Ž\ÒP
+1D4E0:\î\Ž\ÒQ
+1D4E1:\î\Ž\ÒR
+1D4E2:\î\Ž\ÒS
+1D4E3:\î\Ž\ÒT
+1D4E4:\î\Ž\ÒU
+1D4E5:\î\Ž\ÒV
+1D4E6:\î\Ž\ÒW
+1D4E7:\î\Ž\ÒX
+1D4E8:\î\Ž\ÒY
+1D4E9:\î\Ž\ÒZ
+1D4EA:\î\Ž\ÇA
+1D4EB:\î\Ž\ÇB
+1D4EC:\î\Ž\ÇC
+1D4ED:\î\Ž\ÇD
+1D4EE:\î\Ž\ÇE
+1D4EF:\î\Ž\ÇF
+1D4F0:\î\Ž\ÇG
+1D4F1:\î\Ž\ÇH
+1D4F2:\î\Ž\ÇI
+1D4F3:\î\Ž\ÇJ
+1D4F4:\î\Ž\ÇK
+1D4F5:\î\Ž\ÇL
+1D4F6:\î\Ž\ÇM
+1D4F7:\î\Ž\ÇN
+1D4F8:\î\Ž\ÇO
+1D4F9:\î\Ž\ÇP
+1D4FA:\î\Ž\ÇQ
+1D4FB:\î\Ž\ÇR
+1D4FC:\î\Ž\ÇS
+1D4FD:\î\Ž\ÇT
+1D4FE:\î\Ž\ÇU
+1D4FF:\î\Ž\ÇV
+1D500:\î\Ž\ÇW
+1D501:\î\Ž\ÇX
+1D502:\î\Ž\ÇY
+1D503:\î\Ž\ÇZ
+1D504:\E\£\ÒA
+1D505:\E\£\ÒB
+1D507:\E\£\ÒD
+1D508:\E\£\ÒE
+1D509:\E\£\ÒF
+1D50A:\E\£\ÒG
+1D50D:\E\£\ÒJ
+1D50E:\E\£\ÒK
+1D50F:\E\£\ÒL
+1D510:\E\£\ÒM
+1D511:\E\£\ÒN
+1D512:\E\£\ÒO
+1D513:\E\£\ÒP
+1D514:\E\£\ÒQ
+1D516:\E\£\ÒS
+1D517:\E\£\ÒT
+1D518:\E\£\ÒU
+1D519:\E\£\ÒV
+1D51A:\E\£\ÒW
+1D51B:\E\£\ÒX
+1D51C:\E\£\ÒY
+1D51E:\E\£\ÇA
+1D51F:\E\£\ÇB
+1D520:\E\£\ÇC
+1D521:\E\£\ÇD
+1D522:\E\£\ÇE
+1D523:\E\£\ÇF
+1D524:\E\£\ÇG
+1D525:\E\£\ÇH
+1D526:\E\£\ÇI
+1D527:\E\£\ÇJ
+1D528:\E\£\ÇK
+1D529:\E\£\ÇL
+1D52A:\E\£\ÇM
+1D52B:\E\£\ÇN
+1D52C:\E\£\ÇO
+1D52D:\E\£\ÇP
+1D52E:\E\£\ÇQ
+1D52F:\E\£\ÇR
+1D530:\E\£\ÇS
+1D531:\E\£\ÇT
+1D532:\E\£\ÇU
+1D533:\E\£\ÇV
+1D534:\E\£\ÇW
+1D535:\E\£\ÇX
+1D536:\E\£\ÇY
+1D537:\E\£\ÇZ
+1D538:\E\¤\ÒA
+1D539:\E\¤\ÒB
+1D53B:\E\¤\ÒD
+1D53C:\E\¤\ÒE
+1D53D:\E\¤\ÒF
+1D53E:\E\¤\ÒG
+1D540:\E\¤\ÒI
+1D541:\E\¤\ÒJ
+1D542:\E\¤\ÒK
+1D543:\E\¤\ÒL
+1D544:\E\¤\ÒM
+1D546:\E\¤\ÒO
+1D54A:\E\¤\ÒS
+1D54B:\E\¤\ÒT
+1D54C:\E\¤\ÒU
+1D54D:\E\¤\ÒV
+1D54E:\E\¤\ÒW
+1D54F:\E\¤\ÒX
+1D550:\E\¤\ÒY
+1D552:\E\¤\ÇA
+1D553:\E\¤\ÇB
+1D554:\E\¤\ÇC
+1D555:\E\¤\ÇD
+1D556:\E\¤\ÇE
+1D557:\E\¤\ÇF
+1D558:\E\¤\ÇG
+1D559:\E\¤\ÇH
+1D55A:\E\¤\ÇI
+1D55B:\E\¤\ÇJ
+1D55C:\E\¤\ÇK
+1D55D:\E\¤\ÇL
+1D55E:\E\¤\ÇM
+1D55F:\E\¤\ÇN
+1D560:\E\¤\ÇO
+1D561:\E\¤\ÇP
+1D562:\E\¤\ÇQ
+1D563:\E\¤\ÇR
+1D564:\E\¤\ÇS
+1D565:\E\¤\ÇT
+1D566:\E\¤\ÇU
+1D567:\E\¤\ÇV
+1D568:\E\¤\ÇW
+1D569:\E\¤\ÇX
+1D56A:\E\¤\ÇY
+1D56B:\E\¤\ÇZ
+1D56C:\î\£\ÒA
+1D56D:\î\£\ÒB
+1D56E:\î\£\ÒC
+1D56F:\î\£\ÒD
+1D570:\î\£\ÒE
+1D571:\î\£\ÒF
+1D572:\î\£\ÒG
+1D573:\î\£\ÒH
+1D574:\î\£\ÒI
+1D575:\î\£\ÒJ
+1D576:\î\£\ÒK
+1D577:\î\£\ÒL
+1D578:\î\£\ÒM
+1D579:\î\£\ÒN
+1D57A:\î\£\ÒO
+1D57B:\î\£\ÒP
+1D57C:\î\£\ÒQ
+1D57D:\î\£\ÒR
+1D57E:\î\£\ÒS
+1D57F:\î\£\ÒT
+1D580:\î\£\ÒU
+1D581:\î\£\ÒV
+1D582:\î\£\ÒW
+1D583:\î\£\ÒX
+1D584:\î\£\ÒY
+1D585:\î\£\ÒZ
+1D586:\î\£\ÇA
+1D587:\î\£\ÇB
+1D588:\î\£\ÇC
+1D589:\î\£\ÇD
+1D58A:\î\£\ÇE
+1D58B:\î\£\ÇF
+1D58C:\î\£\ÇG
+1D58D:\î\£\ÇH
+1D58E:\î\£\ÇI
+1D58F:\î\£\ÇJ
+1D590:\î\£\ÇK
+1D591:\î\£\ÇL
+1D592:\î\£\ÇM
+1D593:\î\£\ÇN
+1D594:\î\£\ÇO
+1D595:\î\£\ÇP
+1D596:\î\£\ÇQ
+1D597:\î\£\ÇR
+1D598:\î\£\ÇS
+1D599:\î\£\ÇT
+1D59A:\î\£\ÇU
+1D59B:\î\£\ÇV
+1D59C:\î\£\ÇW
+1D59D:\î\£\ÇX
+1D59E:\î\£\ÇY
+1D59F:\î\£\ÇZ
+1D5A0:\z\ÒA
+1D5A1:\z\ÒB
+1D5A2:\z\ÒC
+1D5A3:\z\ÒD
+1D5A4:\z\ÒE
+1D5A5:\z\ÒF
+1D5A6:\z\ÒG
+1D5A7:\z\ÒH
+1D5A8:\z\ÒI
+1D5A9:\z\ÒJ
+1D5AA:\z\ÒK
+1D5AB:\z\ÒL
+1D5AC:\z\ÒM
+1D5AD:\z\ÒN
+1D5AE:\z\ÒO
+1D5AF:\z\ÒP
+1D5B0:\z\ÒQ
+1D5B1:\z\ÒR
+1D5B2:\z\ÒS
+1D5B3:\z\ÒT
+1D5B4:\z\ÒU
+1D5B5:\z\ÒV
+1D5B6:\z\ÒW
+1D5B7:\z\ÒX
+1D5B8:\z\ÒY
+1D5B9:\z\ÒZ
+1D5BA:\z\ÇA
+1D5BB:\z\ÇB
+1D5BC:\z\ÇC
+1D5BD:\z\ÇD
+1D5BE:\z\ÇE
+1D5BF:\z\ÇF
+1D5C0:\z\ÇG
+1D5C1:\z\ÇH
+1D5C2:\z\ÇI
+1D5C3:\z\ÇJ
+1D5C4:\z\ÇK
+1D5C5:\z\ÇL
+1D5C6:\z\ÇM
+1D5C7:\z\ÇN
+1D5C8:\z\ÇO
+1D5C9:\z\ÇP
+1D5CA:\z\ÇQ
+1D5CB:\z\ÇR
+1D5CC:\z\ÇS
+1D5CD:\z\ÇT
+1D5CE:\z\ÇU
+1D5CF:\z\ÇV
+1D5D0:\z\ÇW
+1D5D1:\z\ÇX
+1D5D2:\z\ÇY
+1D5D3:\z\ÇZ
+1D5D4:\O\ÒA
+1D5D5:\O\ÒB
+1D5D6:\O\ÒC
+1D5D7:\O\ÒD
+1D5D8:\O\ÒE
+1D5D9:\O\ÒF
+1D5DA:\O\ÒG
+1D5DB:\O\ÒH
+1D5DC:\O\ÒI
+1D5DD:\O\ÒJ
+1D5DE:\O\ÒK
+1D5DF:\O\ÒL
+1D5E0:\O\ÒM
+1D5E1:\O\ÒN
+1D5E2:\O\ÒO
+1D5E3:\O\ÒP
+1D5E4:\O\ÒQ
+1D5E5:\O\ÒR
+1D5E6:\O\ÒS
+1D5E7:\O\ÒT
+1D5E8:\O\ÒU
+1D5E9:\O\ÒV
+1D5EA:\O\ÒW
+1D5EB:\O\ÒX
+1D5EC:\O\ÒY
+1D5ED:\O\ÒZ
+1D5EE:\O\ÇA
+1D5EF:\O\ÇB
+1D5F0:\O\ÇC
+1D5F1:\O\ÇD
+1D5F2:\O\ÇE
+1D5F3:\O\ÇF
+1D5F4:\O\ÇG
+1D5F5:\O\ÇH
+1D5F6:\O\ÇI
+1D5F7:\O\ÇJ
+1D5F8:\O\ÇK
+1D5F9:\O\ÇL
+1D5FA:\O\ÇM
+1D5FB:\O\ÇN
+1D5FC:\O\ÇO
+1D5FD:\O\ÇP
+1D5FE:\O\ÇQ
+1D5FF:\O\ÇR
+1D600:\O\ÇS
+1D601:\O\ÇT
+1D602:\O\ÇU
+1D603:\O\ÇV
+1D604:\O\ÇW
+1D605:\O\ÇX
+1D606:\O\ÇY
+1D607:\O\ÇZ
+1D608:\z \›A
+1D609:\z \›B
+1D60A:\z \›C
+1D60B:\z \›D
+1D60C:\z \›E
+1D60D:\z \›F
+1D60E:\z \›G
+1D60F:\z \›H
+1D610:\z \›I
+1D611:\z \›J
+1D612:\z \›K
+1D613:\z \›L
+1D614:\z \›M
+1D615:\z \›N
+1D616:\z \›O
+1D617:\z \›P
+1D618:\z \›Q
+1D619:\z \›R
+1D61A:\z \›S
+1D61B:\z \›T
+1D61C:\z \›U
+1D61D:\z \›V
+1D61E:\z \›W
+1D61F:\z \›X
+1D620:\z \›Y
+1D621:\z \›Z
+1D622:\z \—A
+1D623:\z \—B
+1D624:\z \—C
+1D625:\z \—D
+1D626:\z \—E
+1D627:\z \—F
+1D628:\z \—G
+1D629:\z \—H
+1D62A:\z \—I
+1D62B:\z \—J
+1D62C:\z \—K
+1D62D:\z \—L
+1D62E:\z \—M
+1D62F:\z \—N
+1D630:\z \—O
+1D631:\z \—P
+1D632:\z \—Q
+1D633:\z \—R
+1D634:\z \—S
+1D635:\z \—T
+1D636:\z \—U
+1D637:\z \—V
+1D638:\z \—W
+1D639:\z \—X
+1D63A:\z \—Y
+1D63B:\z \—Z
+1D63C:\O \›A
+1D63D:\O \›B
+1D63E:\O \›C
+1D63F:\O \›D
+1D640:\O \›E
+1D641:\O \›F
+1D642:\O \›G
+1D643:\O \›H
+1D644:\O \›I
+1D645:\O \›J
+1D646:\O \›K
+1D647:\O \›L
+1D648:\O \›M
+1D649:\O \›N
+1D64A:\O \›O
+1D64B:\O \›P
+1D64C:\O \›Q
+1D64D:\O \›R
+1D64E:\O \›S
+1D64F:\O \›T
+1D650:\O \›U
+1D651:\O \›V
+1D652:\O \›W
+1D653:\O \›X
+1D654:\O \›Y
+1D655:\O \›Z
+1D656:\O \—A
+1D657:\O \—B
+1D658:\O \—C
+1D659:\O \—D
+1D65A:\O \—E
+1D65B:\O \—F
+1D65C:\O \—G
+1D65D:\O \—H
+1D65E:\O \—I
+1D65F:\O \—J
+1D660:\O \—K
+1D661:\O \—L
+1D662:\O \—M
+1D663:\O \—N
+1D664:\O \—O
+1D665:\O \—P
+1D666:\O \—Q
+1D667:\O \—R
+1D668:\O \—S
+1D669:\O \—T
+1D66A:\O \—U
+1D66B:\O \—V
+1D66C:\O \—W
+1D66D:\O \—X
+1D66E:\O \—Y
+1D66F:\O \—Z
+1D670:\•\ÒA
+1D671:\•\ÒB
+1D672:\•\ÒC
+1D673:\•\ÒD
+1D674:\•\ÒE
+1D675:\•\ÒF
+1D676:\•\ÒG
+1D677:\•\ÒH
+1D678:\•\ÒI
+1D679:\•\ÒJ
+1D67A:\•\ÒK
+1D67B:\•\ÒL
+1D67C:\•\ÒM
+1D67D:\•\ÒN
+1D67E:\•\ÒO
+1D67F:\•\ÒP
+1D680:\•\ÒQ
+1D681:\•\ÒR
+1D682:\•\ÒS
+1D683:\•\ÒT
+1D684:\•\ÒU
+1D685:\•\ÒV
+1D686:\•\ÒW
+1D687:\•\ÒX
+1D688:\•\ÒY
+1D689:\•\ÒZ
+1D68A:\•\ÇA
+1D68B:\•\ÇB
+1D68C:\•\ÇC
+1D68D:\•\ÇD
+1D68E:\•\ÇE
+1D68F:\•\ÇF
+1D690:\•\ÇG
+1D691:\•\ÇH
+1D692:\•\ÇI
+1D693:\•\ÇJ
+1D694:\•\ÇK
+1D695:\•\ÇL
+1D696:\•\ÇM
+1D697:\•\ÇN
+1D698:\•\ÇO
+1D699:\•\ÇP
+1D69A:\•\ÇQ
+1D69B:\•\ÇR
+1D69C:\•\ÇS
+1D69D:\•\ÇT
+1D69E:\•\ÇU
+1D69F:\•\ÇV
+1D6A0:\•\ÇW
+1D6A1:\•\ÇX
+1D6A2:\•\ÇY
+1D6A3:\•\ÇZ
+1D6A8:\îCAPITAL \þ
+1D6A9:\îCAPITAL BETA
+1D6AA:\îCAPITAL GAMMA
+1D6AB:\îCAPITAL DELTA
+1D6AC:\îCAPITAL E\É
+1D6AD:\îCAPITAL ZETA
+1D6AE:\îCAPITAL ETA
+1D6AF:\îCAPITAL THETA
+1D6B0:\îCAPITAL IOTA
+1D6B1:\îCAPITAL KAPPA
+1D6B2:\îCAPITAL LAMDA
+1D6B3:\îCAPITAL MU
+1D6B4:\îCAPITAL NU
+1D6B5:\îCAPITAL XI
+1D6B6:\îCAPITAL OMICRON
+1D6B7:\îCAPITAL PI
+1D6B8:\îCAPITAL RHO
+1D6B9:\îCAPITAL THETA \
+1D6BA:\îCAPITAL SIGMA
+1D6BB:\îCAPITAL TAU
+1D6BC:\îCAPITAL U\É
+1D6BD:\îCAPITAL PHI
+1D6BE:\îCAPITAL CHI
+1D6BF:\îCAPITAL PSI
+1D6C0:\îCAPITAL \ü
+1D6C1:\îNABLA
+1D6C2:\î\§\þ
+1D6C3:\î\§BETA
+1D6C4:\î\§GAMMA
+1D6C5:\î\§DELTA
+1D6C6:\î\§E\É
+1D6C7:\î\§ZETA
+1D6C8:\î\§ETA
+1D6C9:\î\§THETA
+1D6CA:\î\§IOTA
+1D6CB:\î\§KAPPA
+1D6CC:\î\§LAMDA
+1D6CD:\î\§MU
+1D6CE:\î\§NU
+1D6CF:\î\§XI
+1D6D0:\î\§OMICRON
+1D6D1:\î\§PI
+1D6D2:\î\§RHO
+1D6D3:\î\§FINAL SIGMA
+1D6D4:\î\§SIGMA
+1D6D5:\î\§TAU
+1D6D6:\î\§U\É
+1D6D7:\î\§PHI
+1D6D8:\î\§CHI
+1D6D9:\î\§PSI
+1D6DA:\î\§\ü
+1D6DB:\îPARTIAL DIFFERENTIAL
+1D6DC:\îE\É \
+1D6DD:\îTHETA \
+1D6DE:\îKAPPA \
+1D6DF:\îPHI \
+1D6E0:\îRHO \
+1D6E1:\îPI \
+1D6E2:\E\›\þ
+1D6E3:\E\›BETA
+1D6E4:\E\›GAMMA
+1D6E5:\E\›DELTA
+1D6E6:\E\›E\É
+1D6E7:\E\›ZETA
+1D6E8:\E\›ETA
+1D6E9:\E\›THETA
+1D6EA:\E\›IOTA
+1D6EB:\E\›KAPPA
+1D6EC:\E\›LAMDA
+1D6ED:\E\›MU
+1D6EE:\E\›NU
+1D6EF:\E\›XI
+1D6F0:\E\›OMICRON
+1D6F1:\E\›PI
+1D6F2:\E\›RHO
+1D6F3:\E\›THETA \
+1D6F4:\E\›SIGMA
+1D6F5:\E\›TAU
+1D6F6:\E\›U\É
+1D6F7:\E\›PHI
+1D6F8:\E\›CHI
+1D6F9:\E\›PSI
+1D6FA:\E\›\ü
+1D6FB:\E\f NABLA
+1D6FC:\E\—\þ
+1D6FD:\E\—BETA
+1D6FE:\E\—GAMMA
+1D6FF:\E\—DELTA
+1D700:\E\—E\É
+1D701:\E\—ZETA
+1D702:\E\—ETA
+1D703:\E\—THETA
+1D704:\E\—IOTA
+1D705:\E\—KAPPA
+1D706:\E\—LAMDA
+1D707:\E\—MU
+1D708:\E\—NU
+1D709:\E\—XI
+1D70A:\E\—OMICRON
+1D70B:\E\—PI
+1D70C:\E\—RHO
+1D70D:\E\—FINAL SIGMA
+1D70E:\E\—SIGMA
+1D70F:\E\—TAU
+1D710:\E\—U\É
+1D711:\E\—PHI
+1D712:\E\—CHI
+1D713:\E\—PSI
+1D714:\E\—\ü
+1D715:\E\f PARTIAL DIFFERENTIAL
+1D716:\E\f E\É \
+1D717:\E\f THETA \
+1D718:\E\f KAPPA \
+1D719:\E\f PHI \
+1D71A:\E\f RHO \
+1D71B:\E\f PI \
+1D71C:\î\›\þ
+1D71D:\î\›BETA
+1D71E:\î\›GAMMA
+1D71F:\î\›DELTA
+1D720:\î\›E\É
+1D721:\î\›ZETA
+1D722:\î\›ETA
+1D723:\î\›THETA
+1D724:\î\›IOTA
+1D725:\î\›KAPPA
+1D726:\î\›LAMDA
+1D727:\î\›MU
+1D728:\î\›NU
+1D729:\î\›XI
+1D72A:\î\›OMICRON
+1D72B:\î\›PI
+1D72C:\î\›RHO
+1D72D:\î\›THETA \
+1D72E:\î\›SIGMA
+1D72F:\î\›TAU
+1D730:\î\›U\É
+1D731:\î\›PHI
+1D732:\î\›CHI
+1D733:\î\›PSI
+1D734:\î\›\ü
+1D735:\î\f NABLA
+1D736:\î\—\þ
+1D737:\î\—BETA
+1D738:\î\—GAMMA
+1D739:\î\—DELTA
+1D73A:\î\—E\É
+1D73B:\î\—ZETA
+1D73C:\î\—ETA
+1D73D:\î\—THETA
+1D73E:\î\—IOTA
+1D73F:\î\—KAPPA
+1D740:\î\—LAMDA
+1D741:\î\—MU
+1D742:\î\—NU
+1D743:\î\—XI
+1D744:\î\—OMICRON
+1D745:\î\—PI
+1D746:\î\—RHO
+1D747:\î\—FINAL SIGMA
+1D748:\î\—SIGMA
+1D749:\î\—TAU
+1D74A:\î\—U\É
+1D74B:\î\—PHI
+1D74C:\î\—CHI
+1D74D:\î\—PSI
+1D74E:\î\—\ü
+1D74F:\î\f PARTIAL DIFFERENTIAL
+1D750:\î\f E\É \
+1D751:\î\f THETA \
+1D752:\î\f KAPPA \
+1D753:\î\f PHI \
+1D754:\î\f RHO \
+1D755:\î\f PI \
+1D756:\O\Ò\þ
+1D757:\O\ÒBETA
+1D758:\O\ÒGAMMA
+1D759:\O\ÒDELTA
+1D75A:\O\ÒE\É
+1D75B:\O\ÒZETA
+1D75C:\O\ÒETA
+1D75D:\O\ÒTHETA
+1D75E:\O\ÒIOTA
+1D75F:\O\ÒKAPPA
+1D760:\O\ÒLAMDA
+1D761:\O\ÒMU
+1D762:\O\ÒNU
+1D763:\O\ÒXI
+1D764:\O\ÒOMICRON
+1D765:\O\ÒPI
+1D766:\O\ÒRHO
+1D767:\O\ÒTHETA \
+1D768:\O\ÒSIGMA
+1D769:\O\ÒTAU
+1D76A:\O\ÒU\É
+1D76B:\O\ÒPHI
+1D76C:\O\ÒCHI
+1D76D:\O\ÒPSI
+1D76E:\O\Ò\ü
+1D76F:\O NABLA
+1D770:\O\Ç\þ
+1D771:\O\ÇBETA
+1D772:\O\ÇGAMMA
+1D773:\O\ÇDELTA
+1D774:\O\ÇE\É
+1D775:\O\ÇZETA
+1D776:\O\ÇETA
+1D777:\O\ÇTHETA
+1D778:\O\ÇIOTA
+1D779:\O\ÇKAPPA
+1D77A:\O\ÇLAMDA
+1D77B:\O\ÇMU
+1D77C:\O\ÇNU
+1D77D:\O\ÇXI
+1D77E:\O\ÇOMICRON
+1D77F:\O\ÇPI
+1D780:\O\ÇRHO
+1D781:\O\ÇFINAL SIGMA
+1D782:\O\ÇSIGMA
+1D783:\O\ÇTAU
+1D784:\O\ÇU\É
+1D785:\O\ÇPHI
+1D786:\O\ÇCHI
+1D787:\O\ÇPSI
+1D788:\O\Ç\ü
+1D789:\O PARTIAL DIFFERENTIAL
+1D78A:\O E\É \
+1D78B:\O THETA \
+1D78C:\O KAPPA \
+1D78D:\O PHI \
+1D78E:\O RHO \
+1D78F:\O PI \
+1D790:\O \›\þ
+1D791:\O \›BETA
+1D792:\O \›GAMMA
+1D793:\O \›DELTA
+1D794:\O \›E\É
+1D795:\O \›ZETA
+1D796:\O \›ETA
+1D797:\O \›THETA
+1D798:\O \›IOTA
+1D799:\O \›KAPPA
+1D79A:\O \›LAMDA
+1D79B:\O \›MU
+1D79C:\O \›NU
+1D79D:\O \›XI
+1D79E:\O \›OMICRON
+1D79F:\O \›PI
+1D7A0:\O \›RHO
+1D7A1:\O \›THETA \
+1D7A2:\O \›SIGMA
+1D7A3:\O \›TAU
+1D7A4:\O \›U\É
+1D7A5:\O \›PHI
+1D7A6:\O \›CHI
+1D7A7:\O \›PSI
+1D7A8:\O \›\ü
+1D7A9:\O \f NABLA
+1D7AA:\O \—\þ
+1D7AB:\O \—BETA
+1D7AC:\O \—GAMMA
+1D7AD:\O \—DELTA
+1D7AE:\O \—E\É
+1D7AF:\O \—ZETA
+1D7B0:\O \—ETA
+1D7B1:\O \—THETA
+1D7B2:\O \—IOTA
+1D7B3:\O \—KAPPA
+1D7B4:\O \—LAMDA
+1D7B5:\O \—MU
+1D7B6:\O \—NU
+1D7B7:\O \—XI
+1D7B8:\O \—OMICRON
+1D7B9:\O \—PI
+1D7BA:\O \—RHO
+1D7BB:\O \—FINAL SIGMA
+1D7BC:\O \—SIGMA
+1D7BD:\O \—TAU
+1D7BE:\O \—U\É
+1D7BF:\O \—PHI
+1D7C0:\O \—CHI
+1D7C1:\O \—PSI
+1D7C2:\O \—\ü
+1D7C3:\O \f PARTIAL DIFFERENTIAL
+1D7C4:\O \f E\É \
+1D7C5:\O \f THETA \
+1D7C6:\O \f KAPPA \
+1D7C7:\O \f PHI \
+1D7C8:\O \f RHO \
+1D7C9:\O \f PI \
+1D7CE:\îDIGIT ZERO
+1D7CF:\îDIGIT ONE
+1D7D0:\îDIGIT TWO
+1D7D1:\îDIGIT THREE
+1D7D2:\îDIGIT FOUR
+1D7D3:\îDIGIT FIVE
+1D7D4:\îDIGIT SIX
+1D7D5:\îDIGIT SEVEN
+1D7D6:\îDIGIT E\¼
+1D7D7:\îDIGIT NINE
+1D7D8:\E\¤\hZERO
+1D7D9:\E\¤\hONE
+1D7DA:\E\¤\hTWO
+1D7DB:\E\¤\hTHREE
+1D7DC:\E\¤\hFOUR
+1D7DD:\E\¤\hFIVE
+1D7DE:\E\¤\hSIX
+1D7DF:\E\¤\hSEVEN
+1D7E0:\E\¤\hE\¼
+1D7E1:\E\¤\hNINE
+1D7E2:\z\hZERO
+1D7E3:\z\hONE
+1D7E4:\z\hTWO
+1D7E5:\z\hTHREE
+1D7E6:\z\hFOUR
+1D7E7:\z\hFIVE
+1D7E8:\z\hSIX
+1D7E9:\z\hSEVEN
+1D7EA:\z\hE\¼
+1D7EB:\z\hNINE
+1D7EC:\O\hZERO
+1D7ED:\O\hONE
+1D7EE:\O\hTWO
+1D7EF:\O\hTHREE
+1D7F0:\O\hFOUR
+1D7F1:\O\hFIVE
+1D7F2:\O\hSIX
+1D7F3:\O\hSEVEN
+1D7F4:\O\hE\¼
+1D7F5:\O\hNINE
+1D7F6:\•\hZERO
+1D7F7:\•\hONE
+1D7F8:\•\hTWO
+1D7F9:\•\hTHREE
+1D7FA:\•\hFOUR
+1D7FB:\•\hFIVE
+1D7FC:\•\hSIX
+1D7FD:\•\hSEVEN
+1D7FE:\•\hE\¼
+1D7FF:\•\hNINE
+20000-2A6D6:<CJK Ideograph Extension B>
+2F800:\Þ00
+2F801:\Þ01
+2F802:\Þ02
+2F803:\Þ03
+2F804:\Þ04
+2F805:\Þ05
+2F806:\Þ06
+2F807:\Þ07
+2F808:\Þ08
+2F809:\Þ09
+2F80A:\Þ0A
+2F80B:\Þ0B
+2F80C:\Þ0C
+2F80D:\Þ0D
+2F80E:\Þ0E
+2F80F:\Þ0F
+2F810:\Þ10
+2F811:\Þ11
+2F812:\Þ12
+2F813:\Þ13
+2F814:\Þ14
+2F815:\Þ15
+2F816:\Þ16
+2F817:\Þ17
+2F818:\Þ18
+2F819:\Þ19
+2F81A:\Þ1A
+2F81B:\Þ1B
+2F81C:\Þ1C
+2F81D:\Þ1D
+2F81E:\Þ1E
+2F81F:\Þ1F
+2F820:\Þ20
+2F821:\Þ21
+2F822:\Þ22
+2F823:\Þ23
+2F824:\Þ24
+2F825:\Þ25
+2F826:\Þ26
+2F827:\Þ27
+2F828:\Þ28
+2F829:\Þ29
+2F82A:\Þ2A
+2F82B:\Þ2B
+2F82C:\Þ2C
+2F82D:\Þ2D
+2F82E:\Þ2E
+2F82F:\Þ2F
+2F830:\Þ30
+2F831:\Þ31
+2F832:\Þ32
+2F833:\Þ33
+2F834:\Þ34
+2F835:\Þ35
+2F836:\Þ36
+2F837:\Þ37
+2F838:\Þ38
+2F839:\Þ39
+2F83A:\Þ3A
+2F83B:\Þ3B
+2F83C:\Þ3C
+2F83D:\Þ3D
+2F83E:\Þ3E
+2F83F:\Þ3F
+2F840:\Þ40
+2F841:\Þ41
+2F842:\Þ42
+2F843:\Þ43
+2F844:\Þ44
+2F845:\Þ45
+2F846:\Þ46
+2F847:\Þ47
+2F848:\Þ48
+2F849:\Þ49
+2F84A:\Þ4A
+2F84B:\Þ4B
+2F84C:\Þ4C
+2F84D:\Þ4D
+2F84E:\Þ4E
+2F84F:\Þ4F
+2F850:\Þ50
+2F851:\Þ51
+2F852:\Þ52
+2F853:\Þ53
+2F854:\Þ54
+2F855:\Þ55
+2F856:\Þ56
+2F857:\Þ57
+2F858:\Þ58
+2F859:\Þ59
+2F85A:\Þ5A
+2F85B:\Þ5B
+2F85C:\Þ5C
+2F85D:\Þ5D
+2F85E:\Þ5E
+2F85F:\Þ5F
+2F860:\Þ60
+2F861:\Þ61
+2F862:\Þ62
+2F863:\Þ63
+2F864:\Þ64
+2F865:\Þ65
+2F866:\Þ66
+2F867:\Þ67
+2F868:\Þ68
+2F869:\Þ69
+2F86A:\Þ6A
+2F86B:\Þ6B
+2F86C:\Þ6C
+2F86D:\Þ6D
+2F86E:\Þ6E
+2F86F:\Þ6F
+2F870:\Þ70
+2F871:\Þ71
+2F872:\Þ72
+2F873:\Þ73
+2F874:\Þ74
+2F875:\Þ75
+2F876:\Þ76
+2F877:\Þ77
+2F878:\Þ78
+2F879:\Þ79
+2F87A:\Þ7A
+2F87B:\Þ7B
+2F87C:\Þ7C
+2F87D:\Þ7D
+2F87E:\Þ7E
+2F87F:\Þ7F
+2F880:\Þ80
+2F881:\Þ81
+2F882:\Þ82
+2F883:\Þ83
+2F884:\Þ84
+2F885:\Þ85
+2F886:\Þ86
+2F887:\Þ87
+2F888:\Þ88
+2F889:\Þ89
+2F88A:\Þ8A
+2F88B:\Þ8B
+2F88C:\Þ8C
+2F88D:\Þ8D
+2F88E:\Þ8E
+2F88F:\Þ8F
+2F890:\Þ90
+2F891:\Þ91
+2F892:\Þ92
+2F893:\Þ93
+2F894:\Þ94
+2F895:\Þ95
+2F896:\Þ96
+2F897:\Þ97
+2F898:\Þ98
+2F899:\Þ99
+2F89A:\Þ9A
+2F89B:\Þ9B
+2F89C:\Þ9C
+2F89D:\Þ9D
+2F89E:\Þ9E
+2F89F:\Þ9F
+2F8A0:\ÞA0
+2F8A1:\ÞA1
+2F8A2:\ÞA2
+2F8A3:\ÞA3
+2F8A4:\ÞA4
+2F8A5:\ÞA5
+2F8A6:\ÞA6
+2F8A7:\ÞA7
+2F8A8:\ÞA8
+2F8A9:\ÞA9
+2F8AA:\ÞAA
+2F8AB:\ÞAB
+2F8AC:\ÞAC
+2F8AD:\ÞAD
+2F8AE:\ÞAE
+2F8AF:\ÞAF
+2F8B0:\ÞB0
+2F8B1:\ÞB1
+2F8B2:\ÞB2
+2F8B3:\ÞB3
+2F8B4:\ÞB4
+2F8B5:\ÞB5
+2F8B6:\ÞB6
+2F8B7:\ÞB7
+2F8B8:\ÞB8
+2F8B9:\ÞB9
+2F8BA:\ÞBA
+2F8BB:\ÞBB
+2F8BC:\ÞBC
+2F8BD:\ÞBD
+2F8BE:\ÞBE
+2F8BF:\ÞBF
+2F8C0:\ÞC0
+2F8C1:\ÞC1
+2F8C2:\ÞC2
+2F8C3:\ÞC3
+2F8C4:\ÞC4
+2F8C5:\ÞC5
+2F8C6:\ÞC6
+2F8C7:\ÞC7
+2F8C8:\ÞC8
+2F8C9:\ÞC9
+2F8CA:\ÞCA
+2F8CB:\ÞCB
+2F8CC:\ÞCC
+2F8CD:\ÞCD
+2F8CE:\ÞCE
+2F8CF:\ÞCF
+2F8D0:\ÞD0
+2F8D1:\ÞD1
+2F8D2:\ÞD2
+2F8D3:\ÞD3
+2F8D4:\ÞD4
+2F8D5:\ÞD5
+2F8D6:\ÞD6
+2F8D7:\ÞD7
+2F8D8:\ÞD8
+2F8D9:\ÞD9
+2F8DA:\ÞDA
+2F8DB:\ÞDB
+2F8DC:\ÞDC
+2F8DD:\ÞDD
+2F8DE:\ÞDE
+2F8DF:\ÞDF
+2F8E0:\ÞE0
+2F8E1:\ÞE1
+2F8E2:\ÞE2
+2F8E3:\ÞE3
+2F8E4:\ÞE4
+2F8E5:\ÞE5
+2F8E6:\ÞE6
+2F8E7:\ÞE7
+2F8E8:\ÞE8
+2F8E9:\ÞE9
+2F8EA:\ÞEA
+2F8EB:\ÞEB
+2F8EC:\ÞEC
+2F8ED:\ÞED
+2F8EE:\ÞEE
+2F8EF:\ÞEF
+2F8F0:\ÞF0
+2F8F1:\ÞF1
+2F8F2:\ÞF2
+2F8F3:\ÞF3
+2F8F4:\ÞF4
+2F8F5:\ÞF5
+2F8F6:\ÞF6
+2F8F7:\ÞF7
+2F8F8:\ÞF8
+2F8F9:\ÞF9
+2F8FA:\ÞFA
+2F8FB:\ÞFB
+2F8FC:\ÞFC
+2F8FD:\ÞFD
+2F8FE:\ÞFE
+2F8FF:\ÞFF
+2F900:\ß00
+2F901:\ß01
+2F902:\ß02
+2F903:\ß03
+2F904:\ß04
+2F905:\ß05
+2F906:\ß06
+2F907:\ß07
+2F908:\ß08
+2F909:\ß09
+2F90A:\ß0A
+2F90B:\ß0B
+2F90C:\ß0C
+2F90D:\ß0D
+2F90E:\ß0E
+2F90F:\ß0F
+2F910:\ß10
+2F911:\ß11
+2F912:\ß12
+2F913:\ß13
+2F914:\ß14
+2F915:\ß15
+2F916:\ß16
+2F917:\ß17
+2F918:\ß18
+2F919:\ß19
+2F91A:\ß1A
+2F91B:\ß1B
+2F91C:\ß1C
+2F91D:\ß1D
+2F91E:\ß1E
+2F91F:\ß1F
+2F920:\ß20
+2F921:\ß21
+2F922:\ß22
+2F923:\ß23
+2F924:\ß24
+2F925:\ß25
+2F926:\ß26
+2F927:\ß27
+2F928:\ß28
+2F929:\ß29
+2F92A:\ß2A
+2F92B:\ß2B
+2F92C:\ß2C
+2F92D:\ß2D
+2F92E:\ß2E
+2F92F:\ß2F
+2F930:\ß30
+2F931:\ß31
+2F932:\ß32
+2F933:\ß33
+2F934:\ß34
+2F935:\ß35
+2F936:\ß36
+2F937:\ß37
+2F938:\ß38
+2F939:\ß39
+2F93A:\ß3A
+2F93B:\ß3B
+2F93C:\ß3C
+2F93D:\ß3D
+2F93E:\ß3E
+2F93F:\ß3F
+2F940:\ß40
+2F941:\ß41
+2F942:\ß42
+2F943:\ß43
+2F944:\ß44
+2F945:\ß45
+2F946:\ß46
+2F947:\ß47
+2F948:\ß48
+2F949:\ß49
+2F94A:\ß4A
+2F94B:\ß4B
+2F94C:\ß4C
+2F94D:\ß4D
+2F94E:\ß4E
+2F94F:\ß4F
+2F950:\ß50
+2F951:\ß51
+2F952:\ß52
+2F953:\ß53
+2F954:\ß54
+2F955:\ß55
+2F956:\ß56
+2F957:\ß57
+2F958:\ß58
+2F959:\ß59
+2F95A:\ß5A
+2F95B:\ß5B
+2F95C:\ß5C
+2F95D:\ß5D
+2F95E:\ß5E
+2F95F:\ß5F
+2F960:\ß60
+2F961:\ß61
+2F962:\ß62
+2F963:\ß63
+2F964:\ß64
+2F965:\ß65
+2F966:\ß66
+2F967:\ß67
+2F968:\ß68
+2F969:\ß69
+2F96A:\ß6A
+2F96B:\ß6B
+2F96C:\ß6C
+2F96D:\ß6D
+2F96E:\ß6E
+2F96F:\ß6F
+2F970:\ß70
+2F971:\ß71
+2F972:\ß72
+2F973:\ß73
+2F974:\ß74
+2F975:\ß75
+2F976:\ß76
+2F977:\ß77
+2F978:\ß78
+2F979:\ß79
+2F97A:\ß7A
+2F97B:\ß7B
+2F97C:\ß7C
+2F97D:\ß7D
+2F97E:\ß7E
+2F97F:\ß7F
+2F980:\ß80
+2F981:\ß81
+2F982:\ß82
+2F983:\ß83
+2F984:\ß84
+2F985:\ß85
+2F986:\ß86
+2F987:\ß87
+2F988:\ß88
+2F989:\ß89
+2F98A:\ß8A
+2F98B:\ß8B
+2F98C:\ß8C
+2F98D:\ß8D
+2F98E:\ß8E
+2F98F:\ß8F
+2F990:\ß90
+2F991:\ß91
+2F992:\ß92
+2F993:\ß93
+2F994:\ß94
+2F995:\ß95
+2F996:\ß96
+2F997:\ß97
+2F998:\ß98
+2F999:\ß99
+2F99A:\ß9A
+2F99B:\ß9B
+2F99C:\ß9C
+2F99D:\ß9D
+2F99E:\ß9E
+2F99F:\ß9F
+2F9A0:\ßA0
+2F9A1:\ßA1
+2F9A2:\ßA2
+2F9A3:\ßA3
+2F9A4:\ßA4
+2F9A5:\ßA5
+2F9A6:\ßA6
+2F9A7:\ßA7
+2F9A8:\ßA8
+2F9A9:\ßA9
+2F9AA:\ßAA
+2F9AB:\ßAB
+2F9AC:\ßAC
+2F9AD:\ßAD
+2F9AE:\ßAE
+2F9AF:\ßAF
+2F9B0:\ßB0
+2F9B1:\ßB1
+2F9B2:\ßB2
+2F9B3:\ßB3
+2F9B4:\ßB4
+2F9B5:\ßB5
+2F9B6:\ßB6
+2F9B7:\ßB7
+2F9B8:\ßB8
+2F9B9:\ßB9
+2F9BA:\ßBA
+2F9BB:\ßBB
+2F9BC:\ßBC
+2F9BD:\ßBD
+2F9BE:\ßBE
+2F9BF:\ßBF
+2F9C0:\ßC0
+2F9C1:\ßC1
+2F9C2:\ßC2
+2F9C3:\ßC3
+2F9C4:\ßC4
+2F9C5:\ßC5
+2F9C6:\ßC6
+2F9C7:\ßC7
+2F9C8:\ßC8
+2F9C9:\ßC9
+2F9CA:\ßCA
+2F9CB:\ßCB
+2F9CC:\ßCC
+2F9CD:\ßCD
+2F9CE:\ßCE
+2F9CF:\ßCF
+2F9D0:\ßD0
+2F9D1:\ßD1
+2F9D2:\ßD2
+2F9D3:\ßD3
+2F9D4:\ßD4
+2F9D5:\ßD5
+2F9D6:\ßD6
+2F9D7:\ßD7
+2F9D8:\ßD8
+2F9D9:\ßD9
+2F9DA:\ßDA
+2F9DB:\ßDB
+2F9DC:\ßDC
+2F9DD:\ßDD
+2F9DE:\ßDE
+2F9DF:\ßDF
+2F9E0:\ßE0
+2F9E1:\ßE1
+2F9E2:\ßE2
+2F9E3:\ßE3
+2F9E4:\ßE4
+2F9E5:\ßE5
+2F9E6:\ßE6
+2F9E7:\ßE7
+2F9E8:\ßE8
+2F9E9:\ßE9
+2F9EA:\ßEA
+2F9EB:\ßEB
+2F9EC:\ßEC
+2F9ED:\ßED
+2F9EE:\ßEE
+2F9EF:\ßEF
+2F9F0:\ßF0
+2F9F1:\ßF1
+2F9F2:\ßF2
+2F9F3:\ßF3
+2F9F4:\ßF4
+2F9F5:\ßF5
+2F9F6:\ßF6
+2F9F7:\ßF7
+2F9F8:\ßF8
+2F9F9:\ßF9
+2F9FA:\ßFA
+2F9FB:\ßFB
+2F9FC:\ßFC
+2F9FD:\ßFD
+2F9FE:\ßFE
+2F9FF:\ßFF
+2FA00:\1A00
+2FA01:\1A01
+2FA02:\1A02
+2FA03:\1A03
+2FA04:\1A04
+2FA05:\1A05
+2FA06:\1A06
+2FA07:\1A07
+2FA08:\1A08
+2FA09:\1A09
+2FA0A:\1A0A
+2FA0B:\1A0B
+2FA0C:\1A0C
+2FA0D:\1A0D
+2FA0E:\1A0E
+2FA0F:\1A0F
+2FA10:\1A10
+2FA11:\1A11
+2FA12:\1A12
+2FA13:\1A13
+2FA14:\1A14
+2FA15:\1A15
+2FA16:\1A16
+2FA17:\1A17
+2FA18:\1A18
+2FA19:\1A19
+2FA1A:\1A1A
+2FA1B:\1A1B
+2FA1C:\1A1C
+2FA1D:\1A1D
+E0001:LANGUAGE TAG
+E0020:TAG SPACE
+E0021:TAG EXCLAM\”\¥
+E0022:TAG QUOT\”\¥
+E0023:TAG \­SIGN
+E0024:TAG DOLLAR\‚
+E0025:TAG PERCENT\‚
+E0026:TAG AMPERSAND
+E0027:TAG APOSTROPHE
+E0028:TAG \‰ \ÑS
+E0029:TAG \ù\ÑS
+E002A:TAG ASTERISK
+E002B:TAG PLUS\‚
+E002C:TAG COMMA
+E002D:TAG HYPHEN-MINUS
+E002E:TAG\é
+E002F:TAG SOLIDUS
+E0030:TAG\hZERO
+E0031:TAG\hONE
+E0032:TAG\hTWO
+E0033:TAG\hTHREE
+E0034:TAG\hFOUR
+E0035:TAG\hFIVE
+E0036:TAG\hSIX
+E0037:TAG\hSEVEN
+E0038:TAG\hE\¼
+E0039:TAG\hNINE
+E003A:TAG COLON
+E003B:TAG SEMICOLON
+E003C:TAG \µ\‚
+E003D:TAG EQUALS\‚
+E003E:TAG \’\‚
+E003F:TAG QUESTION\¥
+E0040:TAG COMMERCIAL AT
+E0041:TAG \PA
+E0042:TAG \PB
+E0043:TAG \PC
+E0044:TAG \PD
+E0045:TAG \PE
+E0046:TAG \PF
+E0047:TAG \PG
+E0048:TAG \PH
+E0049:TAG \PI
+E004A:TAG \PJ
+E004B:TAG \PK
+E004C:TAG \PL
+E004D:TAG \PM
+E004E:TAG \PN
+E004F:TAG \PO
+E0050:TAG \PP
+E0051:TAG \PQ
+E0052:TAG \PR
+E0053:TAG \PS
+E0054:TAG \PT
+E0055:TAG \PU
+E0056:TAG \PV
+E0057:TAG \PW
+E0058:TAG \PX
+E0059:TAG \PY
+E005A:TAG \PZ
+E005B:TAG \‰ \r\–
+E005C:TAG REVERSE SOLIDUS
+E005D:TAG \ù\r\–
+E005E:TAG CIRCUMFLEX\×
+E005F:TAG LOW \ä
+E0060:TAG GRAVE\×
+E0061:TAG \LA
+E0062:TAG \LB
+E0063:TAG \LC
+E0064:TAG \LD
+E0065:TAG \LE
+E0066:TAG \LF
+E0067:TAG \LG
+E0068:TAG \LH
+E0069:TAG \LI
+E006A:TAG \LJ
+E006B:TAG \LK
+E006C:TAG \LL
+E006D:TAG \LM
+E006E:TAG \LN
+E006F:TAG \LO
+E0070:TAG \LP
+E0071:TAG \LQ
+E0072:TAG \LR
+E0073:TAG \LS
+E0074:TAG \LT
+E0075:TAG \LU
+E0076:TAG \LV
+E0077:TAG \LW
+E0078:TAG \LX
+E0079:TAG \LY
+E007A:TAG \LZ
+E007B:TAG \‰ CURLY \–
+E007C:TAG \€ \ä
+E007D:TAG \ùCURLY \–
+E007E:TAG \æ
+E007F:CANCEL TAG
+F0000-FFFFD:<Plane 15 Private Use>
+100000-10FFFD:<Plane 16 Private Use>
+T0:DOUBLE
+T1:CJK COMPATIBILITY IDEOGRAPH-2F
+T2: INITIAL FORM
+T3:THAI CHARACTER
+T4:HALFWIDTH
+T5:TIBETAN
+T6: FINAL FORM
+T7:SEONG
+T8:IDEOGRAPH
+T9:GREEK CAPITAL LETTER
+T@: LETTER
+TB:CJK COMPATIBILITY IDEOGRAPH-
+TC: SYLLABLE
+TE:MATHEMATICAL
+TF:CANADIAN SYLLABICS
+TH: WITH
+TI: CAPITAL
+TJ:ARABIC LIGATURE
+TK:MUSICAL SYMBOL
+TL:LATIN SMALL LETTER
+TM:BRAILLE PATTERN DOTS-
+TN: SMALL
+TO:MATHEMATICAL SANS-SERIF BOLD
+TP:LATIN CAPITAL LETTER
+TQ: ISOLATED FORM
+TU:KANGXI RADICAL
+TV:ETHIOPIC SYLLABLE
+TX:AL FORM
+TY:BYZANTINE MUSICAL SYMBOL
+TZ:YI SYLLABLE
+T^:ARABIC LETTER
+T_:IDEOGRAPHIC TELEGRAPH SYMBOL FOR
+Tb: VOWEL SIGN
+Tc:CIRCLED
+Te:HANGUL
+Tf:ITALIC
+Tg:CYRILLIC
+Th: DIGIT
+Ti: AND
+Tj:BOX DRAWINGS
+Tk:CANADIAN SYLLABICS CARRIER
+Tl:APL FUNCTIONAL SYMBOL
+Tm:MATHEMATICAL BOLD
+Tn:KATAKANA
+To:COMBINING
+Tp: ABOVE
+Tq:RIGHT
+Tr:SQUARE
+Tt:PARENTHESIZED
+Tu: ARROW
+Tv: RADICAL
+Tx:MONGOLIAN LETTER
+Ty:GREEK SMALL LETTER
+Tz:MATHEMATICAL SANS-SERIF
+T€:VERTICAL
+T:CANADIAN SYLLABICS WEST-CREE
+T‚: SIGN
+Tƒ:WARDS HARPOON WITH BARB
+T„:DEVANAGARI
+T…: BELOW
+T†:FULLWIDTH
+T‡: WITH ALEF MAKSURA
+Tˆ: WITH CIRCUMFLEX
+T‰:LEFT
+TŠ:WARDS
+T‹:HIRAGANA LETTER
+TŒ:CHEROKEE LETTER
+T:SYMBOL
+TŽ:SCRIPT
+T: WITH MEEM
+T:HORIZONTAL
+T‘: EQUAL TO
+T’:GREATER-THAN
+T“:HANGUL JONGSEONG
+T”:ATION
+T•:MATHEMATICAL MONOSPACE
+T–:BRACKET
+T—:ITALIC SMALL
+T™:HANGUL CHOSEONG
+Tš:MALAYALAM
+T›:ITALIC CAPITAL
+Tœ:GEGRAMMENI
+T:TIBETAN SUBJOINED LETTER
+Tž: WITH DIAERESIS
+TŸ:HEBREW
+T :CJK COMPATIBILITY IDEOGRAPH-F9
+T¡:CYRILLIC CAPITAL LETTER
+T¢:CYRILLIC SMALL LETTER
+T£:FRAKTUR
+T¤:DOUBLE-STRUCK
+T¥: MARK
+T¦:WHITE
+T§:SMALL
+T©:BOPOMOFO LETTER
+Tª:GUJARATI
+T«:HANGUL JUNGSEONG
+T¬:BLACK
+T­:NUMBER
+T®:MODIFIER LETTER
+T¯:GURMUKHI
+T°:BENGALI
+T±: WITH DASIA AND
+T²:ROMAN NUMERAL
+T³: WITH DOT
+T´:PERISPOMENI
+Tµ:LESS-THAN
+T¶:SINHALA LETTER
+T·: WITH PSILI AND
+T¹:PRESENTATION FORM FOR VERTICAL
+Tº:YEH WITH HAMZA ABOVE
+T»:KANNADA
+T¼:IGHT
+T½:MYANMAR
+T¾:TRIANGLE
+T¿:DESERET
+TÀ:RUNIC LETTER
+TÁ:STROKE
+TÂ:ED
+TÃ:KHMER INDEPENDENT VOWEL
+TÄ:POINTING
+TÅ:HEAVY
+TÆ:IEU
+TÇ: SMALL
+TÉ:PSILON
+TÊ:ARABIC
+TË:DOWN
+TÌ:DINGBAT NEGATIVE CIRCLED
+TÍ:KATAKANA LETTER
+TÎ:VOCALIC
+TÏ:TELUGU
+TÐ:CIRCLE
+TÑ:PARENTHESI
+TÒ: CAPITAL
+TÓ:SYRIAC
+TÔ: WITH JEEM
+TÕ:ALI GALI
+TÖ:HANGUL LETTER
+T×: ACCENT
+TÙ:RIGHTWARDS ARROW
+TÚ: OPERATOR
+TÛ: WITH YEH FINAL FORM
+TÜ:ACUTE
+TÝ:KHMER
+TÞ:CJK COMPATIBILITY IDEOGRAPH-2F8
+Tß:CJK COMPATIBILITY IDEOGRAPH-2F9
+Tà:MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING
+Tá:DINGBAT NEGATIVE CIRCLED C-SIMPLIFIED
+Tâ:ORIYA LETTER
+Tã: CAPITAL LETTER
+Tä:LINE
+Tå:MACRON
+Tæ:TILDE
+Tç:VARIATION SELECTOR
+Té: FULL STOP
+Tê:<control>
+Të:THAANA LETTER
+Tì: BAR
+Tí: WITH HOOK
+Tî:MATHEMATICAL BOLD
+Tï:LOWER
+Tð:IDEOGRAPHIC DESCRIPTION CHARACTER
+Tñ:SYMBOL FOR
+Tò:LIGATURE
+Tó:DENTISTRY SYMBOL LIGHT
+Tô:ING
+Tõ:CJK COMPATIBILITY IDEOGRAPH-FA
+Tö:REVERSED
+T÷:UPPER
+Tù:RIGHT
+Tú:VULGAR FRACTION
+Tû: WITH CARON
+Tü:OMEGA
+Tý:SQUARE
+Tþ:ALPHA
+Tÿ:YI SYLLABLE N
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites,ff9 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/!Sprites,ff9
index 3eb5b44b7..3eb5b44b7 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites,ff9
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/!Sprites,ff9
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites11,ff9 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/!Sprites11,ff9
index 48986b41e..48986b41e 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites11,ff9
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/!Sprites11,ff9
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites22,ff9 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/!Sprites22,ff9
index 63a6e6122..63a6e6122 100644
--- a/frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites22,ff9
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/!Sprites22,ff9
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/Morris4/!Sprites,ff9 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/Morris4/!Sprites,ff9
new file mode 100644
index 000000000..096f2f22a
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/Morris4/!Sprites,ff9
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/Morris4/!Sprites22,ff9 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/Morris4/!Sprites22,ff9
new file mode 100644
index 000000000..3bf5d53b4
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/Morris4/!Sprites22,ff9
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/Ursula/!Sprites,ff9 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/Ursula/!Sprites,ff9
new file mode 100644
index 000000000..29a67dd3c
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/Ursula/!Sprites,ff9
Binary files differ
diff --git a/frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/Ursula/!Sprites22,ff9 b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/Ursula/!Sprites22,ff9
new file mode 100644
index 000000000..0c866df39
--- /dev/null
+++ b/frontends/riscos/distribution/!Boot/Resources/!Unicode/Themes/Ursula/!Sprites22,ff9
Binary files differ
diff --git a/frontends/riscos/distribution/!System/310/Modules/Network/URI,ffa b/frontends/riscos/distribution/!System/310/Modules/Network/URI,ffa
index 431535e21..d6dafd212 100644
--- a/frontends/riscos/distribution/!System/310/Modules/Network/URI,ffa
+++ b/frontends/riscos/distribution/!System/310/Modules/Network/URI,ffa
Binary files differ
diff --git a/frontends/riscos/distribution/!System/310/Modules/SharedULib,ffa b/frontends/riscos/distribution/!System/310/Modules/SharedULib,ffa
index 8dd0dd2c9..045d6a3af 100755..100644
--- a/frontends/riscos/distribution/!System/310/Modules/SharedULib,ffa
+++ b/frontends/riscos/distribution/!System/310/Modules/SharedULib,ffa
Binary files differ
diff --git a/frontends/riscos/distribution/!System/400/Modules/ARMEABISupport,ffa b/frontends/riscos/distribution/!System/400/Modules/ARMEABISupport,ffa
new file mode 100644
index 000000000..bfcc3ef63
--- /dev/null
+++ b/frontends/riscos/distribution/!System/400/Modules/ARMEABISupport,ffa
Binary files differ
diff --git a/frontends/riscos/distribution/3rdParty/ARMEABISupport/Copyright b/frontends/riscos/distribution/3rdParty/ARMEABISupport/Copyright
new file mode 100644
index 000000000..8bb7d7eb0
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/ARMEABISupport/Copyright
@@ -0,0 +1,20 @@
+Copyright (c) 2019-2022 Lee Noar
+Copyright (c) 2019-2022 GCCSDK Developers
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/frontends/riscos/distribution/3rdParty/ARMEABISupport/Origin,b28 b/frontends/riscos/distribution/3rdParty/ARMEABISupport/Origin,b28
new file mode 100644
index 000000000..246443e2c
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/ARMEABISupport/Origin,b28
@@ -0,0 +1 @@
+https://www.riscos.info/downloads/gccsdk/sharedunixlib/
diff --git a/frontends/riscos/distribution/3rdParty/AcornURI/!ReadMe b/frontends/riscos/distribution/3rdParty/AcornURI/!ReadMe
deleted file mode 100644
index 4f4ca1e24..000000000
--- a/frontends/riscos/distribution/3rdParty/AcornURI/!ReadMe
+++ /dev/null
@@ -1,34 +0,0 @@
-AcornURI 1.04
--------------
-
-Hi. This is a complete reimplementation of Acorn's URI module such that it
-works on Iyonix. This allows simple URI / URL launching from applications.
-Merge this !System with your own, then (re)launch your favourite browser to
-ensure it's running.
-
-This has a few advantages over the official offering: it's smaller,
-compatible with more browsers and more tolerant of errors.
-
-This is released under the terms of the LGPL, which is included in this
-archive as the file Copying. Previous versions of this module were released
-under the GPL, and are still available from sudden.recoil.org.
-
-Source is available from the same place you downloaded this archive, ie
-<http://sudden.recoil.org/others/acornuri/acornuri104src.zip>
-
-
-Changelog
----------
-
-v1.04 20-May-06 Relicensed under the LGPL (rather than GPL)
-
-v1.03 11-May-04 Changed the order of things to try, so it now
- always prefers browsers which are already loaded
-
-v1.02 19-Feb-04 Fixed claiming of URIs where I'd misread the spec
- Added automatic fall-back to the ANT protocol
- Removed some service calls to improve reliability
-
---
-Christian Ludlam
-chris@recoil.org \ No newline at end of file
diff --git a/frontends/riscos/distribution/3rdParty/AcornURI/Apache-2.0 b/frontends/riscos/distribution/3rdParty/AcornURI/Apache-2.0
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/AcornURI/Apache-2.0
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/frontends/riscos/distribution/3rdParty/AcornURI/Copying b/frontends/riscos/distribution/3rdParty/AcornURI/Copying
index 5ab7695ab..4c1b077bf 100644
--- a/frontends/riscos/distribution/3rdParty/AcornURI/Copying
+++ b/frontends/riscos/distribution/3rdParty/AcornURI/Copying
@@ -1,504 +1,22 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
+Files: URI
+Copyright:
+ 1995, 1998 Acorn Computers Ltd
+ 2000 Pace Micro Technology plc
+ 2007, 2008, 2013 Castle Technology Ltd
+License: Apache-2.0
+
+License: Apache-2.0
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ .
+ http://www.apache.org/licenses/LICENSE-2.0
+ .
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ .
+ The complete text of the Apache License Version 2.0 can be found in
+ in the file 'Apache-2.0'.
diff --git a/frontends/riscos/distribution/3rdParty/AcornURI/Origin,b28 b/frontends/riscos/distribution/3rdParty/AcornURI/Origin,b28
new file mode 100644
index 000000000..573a74db2
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/AcornURI/Origin,b28
@@ -0,0 +1 @@
+https://www.riscosopen.org/
diff --git a/frontends/riscos/distribution/3rdParty/Cache/Copyright b/frontends/riscos/distribution/3rdParty/Cache/Copyright
new file mode 100644
index 000000000..61d82856d
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/Cache/Copyright
@@ -0,0 +1,20 @@
+Copyright 2007 Adam Richardson
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/frontends/riscos/distribution/3rdParty/Cache/Origin,b28 b/frontends/riscos/distribution/3rdParty/Cache/Origin,b28
new file mode 100644
index 000000000..ad677d3c9
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/Cache/Origin,b28
@@ -0,0 +1 @@
+https://www.snowstone.org.uk/riscos/
diff --git a/frontends/riscos/distribution/3rdParty/CryptRand/Origin,b28 b/frontends/riscos/distribution/3rdParty/CryptRand/Origin,b28
new file mode 100644
index 000000000..f56f9d600
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/CryptRand/Origin,b28
@@ -0,0 +1 @@
+https://www.riscos.info/packages/arm/System
diff --git a/frontends/riscos/distribution/3rdParty/Iconv/COPYING b/frontends/riscos/distribution/3rdParty/Iconv/COPYING
new file mode 100644
index 000000000..266d65eb1
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/Iconv/COPYING
@@ -0,0 +1,140 @@
+Files: *
+Copyright: 2004-13 J-M Bell
+License: MIT-like
+
+Files: src/transtab
+Copyright: 2000 Markus Kuhn
+License: transtab
+
+Files: test/GNU/*
+Copyright: 2000-2002, 2004-2005 Free Software Foundation, Inc.
+License: LGPL-2+
+
+Files: unicode/Unicode/*
+Copyright:
+ 1997 Acorn Computers Ltd
+ 1999, 2001 Pace Micro Technology plc
+License: Apache-2.0
+
+Files: unicode/Unicode/c/makealiases
+Copyright: 2008 John-Mark Bell
+License: MIT-like
+
+Files: unicode/Unicode/data/CharNames
+Copyright: 2002 Unicode, Inc
+License: Unicode
+
+Files: unicode/UnicodeLib/*
+Copyright:
+ 1997, 1998 Acorn Computers Ltd
+ 1997-2000 Pace Micro Technology PLC.
+ 1999 Element 14 Ltd
+ 2005, 2009, 2015 Castle Technology Ltd
+License: Apache-2.0
+
+Files: unicode/UnicodeLib/data/*
+Copyright:
+ 1991-2002 Unicode, Inc.
+License: Unicode
+
+License: Apache-2.0
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ .
+ http://www.apache.org/licenses/LICENSE-2.0
+ .
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ .
+ The complete text of the Apache License Version 2.0 can be found in
+ in the file 'licenses/Apache-2.0'.
+
+License: LGPL-2+
+ The GNU LIBICONV Library is free software; you can redistribute it
+ and/or modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+ .
+ The GNU LIBICONV Library is distributed in the hope that it will be
+ useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+ .
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU LIBICONV Library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation, Inc., 51 Franklin Street,
+ Fifth Floor, Boston, MA 02110-1301, USA.
+ .
+ The full text of the GNU Library General Public License version 2 can be
+ found in the file 'licenses/LGPL-2'.
+
+License: MIT-like
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ .
+ * The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ .
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
+License: transtab
+ This package contains a table for transliterating ISO 10646 texts into
+ best-effort representations using smaller coded character sets (ASCII,
+ ISO 8859, etc.). It is primarily intended for inclusion into the GNU C
+ library, but might be of use for other applications as well. The table
+ is freely available to anyone.
+
+License: Unicode
+ UNICODE LICENSE V3
+ .
+ COPYRIGHT AND PERMISSION NOTICE
+ .
+ Copyright © 1991-2023 Unicode, Inc.
+ .
+ NOTICE TO USER: Carefully read the following legal agreement. BY
+ DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR
+ SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
+ TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT
+ DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
+ .
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of data files and any associated documentation (the "Data Files") or
+ software and any associated documentation (the "Software") to deal in the
+ Data Files or Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, and/or sell
+ copies of the Data Files or Software, and to permit persons to whom the
+ Data Files or Software are furnished to do so, provided that either (a)
+ this copyright and permission notice appear with all copies of the Data
+ Files or Software, or (b) this copyright and permission notice appear in
+ associated Documentation.
+ .
+ THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
+ THIRD PARTY RIGHTS.
+ .
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
+ BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
+ OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA
+ FILES OR SOFTWARE.
+ .
+ Except as contained in this notice, the name of a copyright holder shall
+ not be used in advertising or otherwise to promote the sale, use or other
+ dealings in these Data Files or Software without prior written
+ authorization of the copyright holder.
diff --git a/frontends/riscos/distribution/3rdParty/Iconv/Origin,b28 b/frontends/riscos/distribution/3rdParty/Iconv/Origin,b28
new file mode 100644
index 000000000..547a62896
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/Iconv/Origin,b28
@@ -0,0 +1 @@
+https://www.netsurf-browser.org/iconv/
diff --git a/frontends/riscos/distribution/3rdParty/Iconv/ReadMe b/frontends/riscos/distribution/3rdParty/Iconv/ReadMe
index 907c2c7c8..f49a1b0b2 100644
--- a/frontends/riscos/distribution/3rdParty/Iconv/ReadMe
+++ b/frontends/riscos/distribution/3rdParty/Iconv/ReadMe
@@ -24,22 +24,5 @@ See the ReadMe file in that directory for further information.
Licence
=======
-Iconv is Copyright © 2004-13 J-M Bell
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
- * The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
+Please see the COPYING file for full licensing information. No part of the
+test suite is included in this binary distribution.
diff --git a/frontends/riscos/distribution/3rdParty/Iconv/licenses/Apache-2.0 b/frontends/riscos/distribution/3rdParty/Iconv/licenses/Apache-2.0
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/Iconv/licenses/Apache-2.0
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/frontends/riscos/distribution/3rdParty/Iconv/licenses/LGPL-2 b/frontends/riscos/distribution/3rdParty/Iconv/licenses/LGPL-2
new file mode 100644
index 000000000..5bc8fb2c8
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/Iconv/licenses/LGPL-2
@@ -0,0 +1,481 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/frontends/riscos/distribution/3rdParty/SharedULib/Copyright b/frontends/riscos/distribution/3rdParty/SharedULib/Copyright
index b6784ed06..4939ec36e 100644
--- a/frontends/riscos/distribution/3rdParty/SharedULib/Copyright
+++ b/frontends/riscos/distribution/3rdParty/SharedULib/Copyright
@@ -7,9 +7,9 @@ Nicholas Clark and Peter Burwood.
These contributors have expressed "no interest" in any further licensing or
copyright in regards to UnixLib.
-Other sections are (c) 1999-2006 Nick Burrett, John Tytgat, Peter Naulls,
-Peter Teichmann, Alex Waugh, Christian Ludlam, Theo Markettos, Graham Shaw,
-James Bursa and John-Mark Bell.
+Other sections are (c) 1999-2011 Nick Burrett, John Tytgat, Peter Naulls,
+Lee Noar, Peter Teichmann, Alex Waugh, Christian Ludlam, Theo Markettos,
+Graham Shaw, James Bursa and John-Mark Bell.
In January 2005, permission was obtained from all relevant contributors
by Peter Naulls to license all past and present contributions to UnixLib
@@ -86,7 +86,7 @@ http://www.fsf.org/licenses/why-not-lgpl.html
===========================================================================
- Copyright (c) 1995-2005 UnixLib Developers
+ Copyright (c) 1995-2009 UnixLib Developers
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -280,7 +280,6 @@ works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
-
GNU LIBRARY GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
@@ -631,8 +630,8 @@ safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -658,7 +657,7 @@ necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
- <signature of Ty Coon>, 1 April 1990
+ <signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
diff --git a/frontends/riscos/distribution/3rdParty/SharedULib/Origin,b28 b/frontends/riscos/distribution/3rdParty/SharedULib/Origin,b28
new file mode 100644
index 000000000..246443e2c
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/SharedULib/Origin,b28
@@ -0,0 +1 @@
+https://www.riscos.info/downloads/gccsdk/sharedunixlib/
diff --git a/frontends/riscos/distribution/3rdParty/Tinct/Origin,b28 b/frontends/riscos/distribution/3rdParty/Tinct/Origin,b28
new file mode 100644
index 000000000..3081d9159
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/Tinct/Origin,b28
@@ -0,0 +1 @@
+http://www.tinct.net/tinct.asp
diff --git a/frontends/riscos/distribution/3rdParty/Unicode/Apache-2.0 b/frontends/riscos/distribution/3rdParty/Unicode/Apache-2.0
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/Unicode/Apache-2.0
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/frontends/riscos/distribution/3rdParty/Unicode/Copyright b/frontends/riscos/distribution/3rdParty/Unicode/Copyright
new file mode 100644
index 000000000..f1a33a5d0
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/Unicode/Copyright
@@ -0,0 +1,66 @@
+Files: !Unicode.*
+Copyright:
+ 1997 Acorn Computers Ltd
+ 1999, 2001 Pace Micro Technology plc
+License: Apache-2.0
+
+Files: !Unicode.Files.CharNames
+Copyright: 2002 Unicode, Inc
+License: Unicode
+
+License: Apache-2.0
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ .
+ http://www.apache.org/licenses/LICENSE-2.0
+ .
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ .
+ The complete text of the Apache License Version 2.0 can be found in
+ in the file 'Apache-2.0'.
+
+License: Unicode
+ UNICODE LICENSE V3
+ .
+ COPYRIGHT AND PERMISSION NOTICE
+ .
+ Copyright © 1991-2023 Unicode, Inc.
+ .
+ NOTICE TO USER: Carefully read the following legal agreement. BY
+ DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR
+ SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
+ TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT
+ DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
+ .
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of data files and any associated documentation (the "Data Files") or
+ software and any associated documentation (the "Software") to deal in the
+ Data Files or Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, and/or sell
+ copies of the Data Files or Software, and to permit persons to whom the
+ Data Files or Software are furnished to do so, provided that either (a)
+ this copyright and permission notice appear with all copies of the Data
+ Files or Software, or (b) this copyright and permission notice appear in
+ associated Documentation.
+ .
+ THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
+ THIRD PARTY RIGHTS.
+ .
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
+ BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
+ OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA
+ FILES OR SOFTWARE.
+ .
+ Except as contained in this notice, the name of a copyright holder shall
+ not be used in advertising or otherwise to promote the sale, use or other
+ dealings in these Data Files or Software without prior written
+ authorization of the copyright holder.
diff --git a/frontends/riscos/distribution/3rdParty/Unicode/Origin,b28 b/frontends/riscos/distribution/3rdParty/Unicode/Origin,b28
new file mode 100644
index 000000000..573a74db2
--- /dev/null
+++ b/frontends/riscos/distribution/3rdParty/Unicode/Origin,b28
@@ -0,0 +1 @@
+https://www.riscosopen.org/
diff --git a/frontends/riscos/distribution/LeesMij b/frontends/riscos/distribution/LeesMij
index a0d3ff41f..3a48b77ec 100644
--- a/frontends/riscos/distribution/LeesMij
+++ b/frontends/riscos/distribution/LeesMij
@@ -6,7 +6,7 @@ broncode.
De nieuwste versie van NetSurf is verkrijgbaar via:
- http://www.netsurf-browser.org/
+ https://www.netsurf-browser.org/
Installatie
@@ -59,15 +59,3 @@ voor meer informatie.
De meegeleverde !Boot- en !System-mappen bevatten items die door
derden zijn geproduceerd. De bijbehorende licenties zijn meegeleverd
in de map '3rdParty'.
-
-AcornURI
- http://sudden.recoil.org/others/
-
-Iconv
- http://www.netsurf-browser.org/iconv/
-
-SharedUnixLibrary
- http://www.riscos.info/downloads/gccsdk/sharedunixlib/system.zip
-
-Tinct
- http://www.tinct.net/tinct.asp
diff --git a/frontends/riscos/distribution/ReadMe b/frontends/riscos/distribution/ReadMe
index eec39d6ab..6a4429b12 100644
--- a/frontends/riscos/distribution/ReadMe
+++ b/frontends/riscos/distribution/ReadMe
@@ -5,7 +5,7 @@ This is a development build of NetSurf, an open source web browser.
The latest version of NetSurf is available from:
- http://www.netsurf-browser.org/
+ https://www.netsurf-browser.org/
Installation
@@ -31,7 +31,10 @@ Double click on !NetSurf in your chosen location to launch NetSurf.
Note NetSurf requires WindowManager 3.80 or later. This comes
with RISC OS 4 and above. RISC OS 3 users should install
the Universal Boot Sequence from:
- http://acorn.riscos.com/riscos/releases/UniBoot/
+ http://www.riscos.com/ftp_space/generic/uniboot/ or,
+ alternatively, use the HardDisc4 and associated System
+ resources provided by RISC OS Open:
+ https://www.riscosopen.org/content/downloads/common
Note RISC OS 3.1 and earlier are not supported.
@@ -45,17 +48,5 @@ for details.
The !Boot and !System directories contain items provided produced
-by third parties. Their licences are provided in the 3rd Party
-directory.
-
-AcornURI
- http://sudden.recoil.org/others/
-
-Iconv
- http://www.netsurf-browser.org/iconv/
-
-SharedUnixLibrary
- http://www.riscos.info/downloads/gccsdk/sharedunixlib/system.zip
-
-Tinct
- http://www.tinct.net/tinct.asp
+by third parties. Their licences, associated documentation, and
+origin are provided in the 3rd Party directory.
diff --git a/frontends/riscos/download.c b/frontends/riscos/download.c
index bdc705426..216f5750c 100644
--- a/frontends/riscos/download.c
+++ b/frontends/riscos/download.c
@@ -313,8 +313,8 @@ gui_download_window_create(download_context *ctx, struct gui_window *gui)
/** @todo change this to take a reference to the nsurl and use
* that value directly rather than using a fixed buffer.
*/
- strncpy(dw->url, nsurl_access(url), sizeof dw->url);
- dw->url[sizeof dw->url - 1] = 0;
+ strncpy(dw->url, nsurl_access(url), sizeof(dw->url) - 1);
+ dw->url[sizeof(dw->url) - 1] = 0;
dw->status[0] = 0;
gettimeofday(&dw->start_time, 0);
@@ -414,7 +414,8 @@ gui_download_window_create(download_context *ctx, struct gui_window *gui)
return 0;
}
else {
- strncpy(dw->path, local_path, sizeof dw->path);
+ strncpy(dw->path, local_path, sizeof(dw->path) - 1);
+ dw->path[sizeof(dw->path)-1] = 0;
free(local_path);
}
@@ -484,7 +485,8 @@ static void gui_download_window_error(struct gui_download_window *dw,
riscos_schedule(-1, ro_gui_download_update_status_wrapper, dw);
/* place error message in status icon in red */
- strncpy(dw->status, error_msg, sizeof dw->status);
+ strncpy(dw->status, error_msg, sizeof(dw->status) - 1);
+ dw->status[sizeof(dw->status)-1] = 0;
error = xwimp_set_icon_state(dw->window,
ICON_DOWNLOAD_STATUS,
wimp_COLOUR_RED << wimp_ICON_FG_COLOUR_SHIFT,
@@ -872,11 +874,11 @@ bool ro_gui_download_click(wimp_pointer *pointer)
ro_gui_drag_icon(x, y, sprite);
} else if (pointer->i == ICON_DOWNLOAD_DESTINATION) {
- char command[256] = "Filer_OpenDir ";
+ char command[sizeof(dw->path) + 14 + 1] = "Filer_OpenDir ";
char *dot;
- strncpy(command + 14, dw->path, 242);
- command[255] = 0;
+ strncpy(command + 14, dw->path, sizeof(command) - 14 - 1);
+ command[sizeof(command) - 1] = 0;
dot = strrchr(command, '.');
if (dot) {
os_error *error;
@@ -1384,7 +1386,8 @@ bool ro_gui_download_save(struct gui_download_window *dw,
}
dw->saved = true;
- strncpy(dw->path, file_name, sizeof dw->path);
+ strncpy(dw->path, file_name, sizeof(dw->path) - 1);
+ dw->path[sizeof(dw->path)-1] = 0;
if (!dw->send_dataload || dw->save_message.data.data_xfer.est_size != -1)
ro_gui_download_remember_dir(file_name);
diff --git a/frontends/riscos/filetype.c b/frontends/riscos/filetype.c
index 73651cd63..b0dc949f8 100644
--- a/frontends/riscos/filetype.c
+++ b/frontends/riscos/filetype.c
@@ -39,6 +39,7 @@ static const struct type_entry type_map[] = {
{0x188, "application/x-shockwave-flash"},
{0x695, "image/gif"},
{0x69c, "image/x-ms-bmp"},
+ {0xa66, "image/webp"},
{0xaad, "image/svg+xml"},
{0xaff, "image/x-drawfile"},
{0xb60, "image/png"},
@@ -269,6 +270,7 @@ int ro_content_native_type(struct hlcache_handle *c)
case FILETYPE_BMP: /* bmp */
case FILETYPE_ICO: /* ico */
case FILETYPE_PNG: /* png */
+ case FILETYPE_WEBP: /* webp */
case 0xff9: /* sprite */
return osfile_TYPE_SPRITE;
case FILETYPE_SVG: /* svg */
diff --git a/frontends/riscos/filetype.h b/frontends/riscos/filetype.h
index 4c45e7bd0..b9fca4d49 100644
--- a/frontends/riscos/filetype.h
+++ b/frontends/riscos/filetype.h
@@ -67,6 +67,9 @@
#ifndef FILETYPE_SVG
#define FILETYPE_SVG 0xaad
#endif
+#ifndef FILETYPE_WEBP
+#define FILETYPE_WEBP 0xa66
+#endif
/**
* Determine the MIME type of a local file.
diff --git a/frontends/riscos/font.c b/frontends/riscos/font.c
index 8913efeeb..2ff309043 100644
--- a/frontends/riscos/font.c
+++ b/frontends/riscos/font.c
@@ -469,7 +469,7 @@ void nsfont_read_style(const plot_font_style_t *fstyle,
rufl_WEIGHT_900
};
- *font_size = (fstyle->size * 16) / FONT_SIZE_SCALE;
+ *font_size = (fstyle->size * 16) / PLOT_STYLE_SCALE;
if (1600 < *font_size)
*font_size = 1600;
diff --git a/frontends/riscos/font.h b/frontends/riscos/font.h
index a29bad83a..5a82f63ee 100644
--- a/frontends/riscos/font.h
+++ b/frontends/riscos/font.h
@@ -26,7 +26,7 @@
#include <rufl.h>
struct plot_font_style;
-struct gui_layout_table *riscos_layout_table;
+extern struct gui_layout_table *riscos_layout_table;
/** desktop font, size and style being used */
extern char ro_gui_desktop_font_family[];
diff --git a/frontends/riscos/global_history.c b/frontends/riscos/global_history.c
index 7dfc58317..51f5390cb 100644
--- a/frontends/riscos/global_history.c
+++ b/frontends/riscos/global_history.c
@@ -367,6 +367,7 @@ global_history_menu_select(wimp_w w,
*/
static nserror ro_global_history_init(void)
{
+ os_error *error;
struct ro_global_history_window *ncwin;
nserror res;
static const struct ns_menu global_history_menu_def = {
@@ -411,7 +412,15 @@ static nserror ro_global_history_init(void)
}
/* create window from template */
- ncwin->core.wh = wimp_create_window(dialog_global_history_template);
+ error = xwimp_create_window(dialog_global_history_template,
+ &ncwin->core.wh);
+ if (error) {
+ NSLOG(netsurf, INFO, "xwimp_create_window: 0x%x: %s",
+ error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ free(ncwin);
+ return NSERROR_NOMEM;
+ }
ro_gui_set_window_title(ncwin->core.wh, messages_get("GlobalHistory"));
@@ -435,6 +444,9 @@ static nserror ro_global_history_init(void)
return res;
}
+ NSLOG(netsurf, INFO, "Created global history corewindow: %p",
+ &ncwin->core);
+
res = global_history_init(ncwin->core.cb_table,
(struct core_window *)ncwin);
if (res != NSERROR_OK) {
diff --git a/frontends/riscos/gui.c b/frontends/riscos/gui.c
index be1bc8d9a..1a2b944a8 100644
--- a/frontends/riscos/gui.c
+++ b/frontends/riscos/gui.c
@@ -73,10 +73,10 @@
#include "riscos/query.h"
#include "riscos/window.h"
#include "riscos/iconbar.h"
-#include "riscos/sslcert.h"
#include "riscos/local_history.h"
#include "riscos/global_history.h"
#include "riscos/cookies.h"
+#include "riscos/pageinfo.h"
#include "riscos/wimp_event.h"
#include "riscos/uri.h"
#include "riscos/url_protocol.h"
@@ -94,6 +94,7 @@ bool riscos_done = false;
extern bool ro_plot_patterned_lines;
int os_version = 0;
+bool os_alpha_sprite_supported = false;
const char * const __dynamic_da_name = "NetSurf"; /**< For UnixLib. */
int __dynamic_da_max_size = 128 * 1024 * 1024; /**< For UnixLib. */
@@ -143,27 +144,6 @@ static ns_wimp_message_list task_messages = {
message_URI_PROCESS,
message_URI_RETURN_RESULT,
message_INET_SUITE_OPEN_URL,
-#ifdef WITH_PLUGIN
- message_PLUG_IN_OPENING,
- message_PLUG_IN_CLOSED,
- message_PLUG_IN_RESHAPE_REQUEST,
- message_PLUG_IN_FOCUS,
- message_PLUG_IN_URL_ACCESS,
- message_PLUG_IN_STATUS,
- message_PLUG_IN_BUSY,
- message_PLUG_IN_STREAM_NEW,
- message_PLUG_IN_STREAM_WRITE,
- message_PLUG_IN_STREAM_WRITTEN,
- message_PLUG_IN_STREAM_DESTROY,
- message_PLUG_IN_OPEN,
- message_PLUG_IN_CLOSE,
- message_PLUG_IN_RESHAPE,
- message_PLUG_IN_STREAM_AS_FILE,
- message_PLUG_IN_NOTIFY,
- message_PLUG_IN_ABORT,
- message_PLUG_IN_ACTION,
- /* message_PLUG_IN_INFORMED, (not provided by oslib) */
-#endif
message_PRINT_SAVE,
message_PRINT_ERROR,
message_PRINT_TYPE_ODD,
@@ -305,7 +285,7 @@ set_colour_from_wimp(struct nsoption_s *opts,
static nserror set_defaults(struct nsoption_s *defaults)
{
/* Set defaults for absent option strings */
- nsoption_setnull_charp(ca_bundle, strdup("NetSurf:Resources.ca-bundle"));
+ nsoption_setnull_charp(ca_bundle, strdup("<NetSurf$CABundle>"));
nsoption_setnull_charp(cookie_file, strdup("NetSurf:Cookies"));
nsoption_setnull_charp(cookie_jar, strdup(CHOICES_PREFIX "Cookies"));
@@ -827,6 +807,7 @@ static void ro_msg_dataload(wimp_message *message)
case osfile_TYPE_TEXT:
case FILETYPE_ARTWORKS:
case FILETYPE_SVG:
+ case FILETYPE_WEBP:
/* display the actual file */
error = netsurf_path_to_nsurl(message->data.data_xfer.file_name, &url);
break;
@@ -929,7 +910,8 @@ static void ro_msg_datasave(wimp_message *message)
case osfile_TYPE_SPRITE:
case osfile_TYPE_TEXT:
case FILETYPE_ARTWORKS:
- case FILETYPE_SVG: {
+ case FILETYPE_SVG:
+ case FILETYPE_WEBP: {
os_error *error;
dataxfer->your_ref = dataxfer->my_ref;
@@ -1108,6 +1090,28 @@ static void ro_gui_check_resolvers(void)
}
}
+/**
+ * Determine whether the OS version supports alpha channels.
+ *
+ * \return true iff alpha channels are supported, false otherwise.
+ */
+static bool ro_gui__os_alpha_sprites_supported(void)
+{
+ os_error *error;
+ int var_val;
+ bits psr;
+
+ psr = 0;
+ error = xos_read_mode_variable(alpha_SPRITE_MODE,
+ os_MODEVAR_MODE_FLAGS, &var_val, &psr);
+ if (error) {
+ NSLOG(netsurf, ERROR, "xos_read_mode_variable: 0x%x: %s",
+ error->errnum, error->errmess);
+ return false;
+ }
+
+ return (var_val == (1 << 15));
+}
/**
* Initialise the RISC OS specific GUI.
@@ -1150,6 +1154,10 @@ static nserror gui_init(int argc, char** argv)
* being present) */
xos_byte(osbyte_IN_KEY, 0, 0xff, &os_version, NULL);
+ os_alpha_sprite_supported = ro_gui__os_alpha_sprites_supported();
+ NSLOG(netsurf, INFO, "OS supports alpha sprites: %s",
+ os_alpha_sprite_supported ? "yes" : "no");
+
/* the first release version of the A9home OS is incapable of
plotting patterned lines (presumably a fault in the hw acceleration) */
if (!xosmodule_lookup("VideoHWSMI", NULL, NULL, &base, NULL, NULL)) {
@@ -1202,16 +1210,9 @@ static nserror gui_init(int argc, char** argv)
/* Initialise save complete functionality */
save_complete_init();
- /* Initialise the font subsystem */
- nsfont_init();
-
- /* Load in visited URLs, Cookies, and hostlist */
+ /* Load in visited URLs and Cookies */
urldb_load(nsoption_charp(url_path));
urldb_load_cookies(nsoption_charp(cookie_file));
- hotlist_init(nsoption_charp(hotlist_path),
- nsoption_bool(external_hotlists) ?
- NULL :
- nsoption_charp(hotlist_save));
/* Initialise with the wimp */
error = xwimp_initialise(wimp_VERSION_RO38, task_name,
@@ -1242,6 +1243,15 @@ static nserror gui_init(int argc, char** argv)
ro_message_register_route(message_WINDOW_INFO,
ro_msg_window_info);
+ /* Initialise the font subsystem (must be after Wimp_Initialise) */
+ nsfont_init();
+
+ /* Initialise the hotlist (must be after fonts) */
+ hotlist_init(nsoption_charp(hotlist_path),
+ nsoption_bool(external_hotlists) ?
+ NULL :
+ nsoption_charp(hotlist_save));
+
/* Initialise global information */
ro_gui_get_screen_properties();
ro_gui_wimp_get_desktop_font();
@@ -1593,6 +1603,7 @@ static void gui_quit(void)
ro_gui_window_quit();
ro_gui_local_history_finalise();
ro_gui_global_history_finalise();
+ ro_gui_pageinfo_finalise();
ro_gui_hotlist_finalise();
ro_gui_cookies_finalise();
ro_gui_saveas_quit();
@@ -1747,51 +1758,6 @@ static void ro_gui_user_message(wimp_event_no event, wimp_message *message)
ro_url_message_received(message);
}
break;
-#ifdef WITH_PLUGIN
- case message_PLUG_IN_OPENING:
- plugin_opening(message);
- break;
- case message_PLUG_IN_CLOSED:
- plugin_closed(message);
- break;
- case message_PLUG_IN_RESHAPE_REQUEST:
- plugin_reshape_request(message);
- break;
- case message_PLUG_IN_FOCUS:
- break;
- case message_PLUG_IN_URL_ACCESS:
- plugin_url_access(message);
- break;
- case message_PLUG_IN_STATUS:
- plugin_status(message);
- break;
- case message_PLUG_IN_BUSY:
- break;
- case message_PLUG_IN_STREAM_NEW:
- plugin_stream_new(message);
- break;
- case message_PLUG_IN_STREAM_WRITE:
- break;
- case message_PLUG_IN_STREAM_WRITTEN:
- plugin_stream_written(message);
- break;
- case message_PLUG_IN_STREAM_DESTROY:
- break;
- case message_PLUG_IN_OPEN:
- if (event == wimp_USER_MESSAGE_ACKNOWLEDGE)
- plugin_open_msg(message);
- break;
- case message_PLUG_IN_CLOSE:
- if (event == wimp_USER_MESSAGE_ACKNOWLEDGE)
- plugin_close_msg(message);
- break;
- case message_PLUG_IN_RESHAPE:
- case message_PLUG_IN_STREAM_AS_FILE:
- case message_PLUG_IN_NOTIFY:
- case message_PLUG_IN_ABORT:
- case message_PLUG_IN_ACTION:
- break;
-#endif
case message_PRINT_SAVE:
if (event == wimp_USER_MESSAGE_ACKNOWLEDGE)
ro_print_save_bounce(message);
@@ -1980,8 +1946,8 @@ void ro_gui_view_source(struct hlcache_handle *c)
int objtype;
bool done = false;
- const char *source_data;
- unsigned long source_size;
+ const uint8_t *source_data;
+ size_t source_size;
if (!c) {
ro_warn_user("MiscError", "No document source");
@@ -2427,12 +2393,10 @@ static struct gui_fetch_table riscos_fetch_table = {
static struct gui_misc_table riscos_misc_table = {
.schedule = riscos_schedule,
- .warning = ro_warn_user,
.quit = gui_quit,
.launch_url = gui_launch_url,
- .cert_verify = gui_cert_verify,
- .login = gui_401login_open,
+ .present_cookies = ro_gui_cookies_present,
};
diff --git a/frontends/riscos/gui.h b/frontends/riscos/gui.h
index 49a8ba417..03989ae20 100644
--- a/frontends/riscos/gui.h
+++ b/frontends/riscos/gui.h
@@ -34,6 +34,8 @@
extern int os_version;
+extern bool os_alpha_sprite_supported;
+
extern const char * NETSURF_DIR;
struct toolbar;
@@ -44,7 +46,6 @@ struct tree;
struct node;
struct history;
struct css_style;
-struct ssl_cert_info;
struct nsurl;
struct hlcache_handle;
@@ -93,8 +94,6 @@ struct gui_window {
char validation[12]; /**< Validation string for colours */
- float scale; /**< Browser window scale */
-
/** Options. */
struct {
bool buffer_animations; /**< Use screen buffering for animations. */
@@ -134,11 +133,6 @@ void ro_gui_download_datasave_ack(wimp_message *message);
bool ro_gui_download_prequit(void);
extern struct gui_download_table *riscos_download_table;
-/* in 401login.c */
-void ro_gui_401login_init(void);
-void gui_401login_open(struct nsurl *url, const char *realm,
- nserror (*cb)(bool proceed, void *pw), void *cbpw);
-
/* in schedule.c */
extern bool sched_active;
extern os_t sched_time;
@@ -163,7 +157,7 @@ nserror riscos_schedule(int t, void (*callback)(void *p), void *p);
/* in search.c */
void ro_gui_search_init(void);
void ro_gui_search_prepare(struct browser_window *g);
-struct gui_search_table *riscos_search_table;
+extern struct gui_search_table *riscos_search_table;
/* in print.c */
void ro_gui_print_init(void);
@@ -173,6 +167,7 @@ void ro_gui_print_prepare(struct gui_window *g);
extern const struct plotter_table ro_plotters;
extern int ro_plot_origin_x;
extern int ro_plot_origin_y;
+extern struct rect ro_plot_clip_rect;
/* in theme_install.c */
bool ro_gui_theme_install_apply(wimp_w w);
diff --git a/frontends/riscos/gui/button_bar.c b/frontends/riscos/gui/button_bar.c
index 34ae39ae5..50e1de3c1 100644
--- a/frontends/riscos/gui/button_bar.c
+++ b/frontends/riscos/gui/button_bar.c
@@ -189,7 +189,8 @@ struct button_bar *ro_gui_button_bar_create(struct theme_descriptor *theme,
icon->bar_next = NULL;
strncpy(icon->sprite, buttons[def].icon,
- BUTTONBAR_SPRITE_NAME_LENGTH);
+ BUTTONBAR_SPRITE_NAME_LENGTH - 1);
+ icon->sprite[BUTTONBAR_SPRITE_NAME_LENGTH-1] = 0;
snprintf(icon->validation, BUTTONBAR_VALIDATION_LENGTH,
"R5;S%s,p%s", icon->sprite, icon->sprite);
diff --git a/frontends/riscos/gui/throbber.c b/frontends/riscos/gui/throbber.c
index f3b79a68e..e3e4106cc 100644
--- a/frontends/riscos/gui/throbber.c
+++ b/frontends/riscos/gui/throbber.c
@@ -32,6 +32,7 @@
#include "oslib/wimp.h"
#include "utils/log.h"
+#include "utils/utils.h"
#include "riscos/gui.h"
#include "riscos/gui/throbber.h"
@@ -385,7 +386,8 @@ bool ro_gui_throbber_animate(struct throbber *throbber)
throbber->current_frame = 1;
snprintf(sprite_name, THROBBER_SPRITE_NAME_LENGTH,
- "throbber%i", throbber->current_frame);
+ "throbber%i",
+ min(max(throbber->current_frame, 0), 999));
ro_gui_set_icon_string(throbber->window, throbber->icon,
sprite_name, true);
diff --git a/frontends/riscos/gui/url_bar.c b/frontends/riscos/gui/url_bar.c
index ee5c689df..99a90f58a 100644
--- a/frontends/riscos/gui/url_bar.c
+++ b/frontends/riscos/gui/url_bar.c
@@ -25,20 +25,11 @@
* the use of the hlcache content interface.
*/
-#include <alloca.h>
-#include <assert.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include "oslib/os.h"
-#include "oslib/osspriteop.h"
+#include <stddef.h>
#include "oslib/wimp.h"
#include "utils/log.h"
#include "utils/messages.h"
-#include "utils/utf8.h"
-#include "utils/nsurl.h"
#include "netsurf/browser_window.h"
#include "netsurf/plotters.h"
#include "netsurf/content.h"
@@ -46,21 +37,25 @@
#include "riscos/gui.h"
#include "riscos/hotlist.h"
-#include "riscos/gui/url_bar.h"
#include "riscos/url_suggest.h"
#include "riscos/wimp.h"
#include "riscos/wimp_event.h"
+#include "riscos/wimputils.h"
#include "riscos/window.h"
#include "riscos/ucstables.h"
#include "riscos/filetype.h"
+#include "riscos/gui/url_bar.h"
#define URLBAR_HEIGHT 52
#define URLBAR_FAVICON_SIZE 16
#define URLBAR_HOTLIST_SIZE 17
+#define URLBAR_PGINFO_WIDTH ((26) * 2)
#define URLBAR_FAVICON_WIDTH ((5 + URLBAR_FAVICON_SIZE + 5) * 2)
#define URLBAR_HOTLIST_WIDTH ((5 + URLBAR_HOTLIST_SIZE + 5) * 2)
#define URLBAR_MIN_WIDTH 52
#define URLBAR_GRIGHT_GUTTER 8
+
+#define URLBAR_PGINFO_NAME_LENGTH 12
#define URLBAR_FAVICON_NAME_LENGTH 12
struct url_bar {
@@ -73,29 +68,43 @@ struct url_bar {
/** The window and icon details. */
wimp_w window;
os_box extent;
+ osspriteop_area *sprites;
wimp_i container_icon;
- char favicon_sprite[URLBAR_FAVICON_NAME_LENGTH];
- int favicon_type;
- struct hlcache_handle *favicon_content;
- os_box favicon_extent;
- os_coord favicon_offset;
- int favicon_width, favicon_height;
-
- wimp_i text_icon;
- char *text_buffer;
- size_t text_size;
- char *text_buffer_utf8;
-
- wimp_i suggest_icon;
- int suggest_x, suggest_y;
-
bool hidden;
bool display;
bool shaded;
struct {
+ char sprite[URLBAR_PGINFO_NAME_LENGTH];
+ os_box extent;
+ } pginfo;
+
+ struct {
+ char sprite[URLBAR_FAVICON_NAME_LENGTH];
+ int type;
+ struct hlcache_handle *content;
+ os_box extent;
+ os_coord offset;
+ int width;
+ int height;
+ } favicon;
+
+ struct {
+ wimp_i icon;
+ char *buffer;
+ size_t size;
+ char *buffer_utf8;
+ } text;
+
+ struct {
+ wimp_i icon;
+ int x;
+ int y;
+ } suggest;
+
+ struct {
bool set;
os_box extent;
os_coord offset;
@@ -128,119 +137,50 @@ static struct url_bar_resource url_bar_res[URLBAR_RES_LAST] = {
};
-static void ro_gui_url_bar_set_hotlist(struct url_bar *url_bar, bool set);
-
-
-/* This is an exported interface documented in url_bar.h */
-struct url_bar *ro_gui_url_bar_create(struct theme_descriptor *theme)
-{
- struct url_bar *url_bar;
-
- /* Allocate memory. */
-
- url_bar = malloc(sizeof(struct url_bar));
- if (url_bar == NULL) {
- NSLOG(netsurf, INFO, "No memory for malloc()");
- return NULL;
- }
-
- /* Set up default parameters. */
-
- url_bar->theme = theme;
-
- url_bar->display = false;
- url_bar->shaded = false;
-
- url_bar->x_min = URLBAR_FAVICON_WIDTH + URLBAR_MIN_WIDTH +
- URLBAR_HOTLIST_WIDTH;
- url_bar->y_min = URLBAR_HEIGHT;
-
- url_bar->extent.x0 = 0;
- url_bar->extent.y0 = 0;
- url_bar->extent.x1 = 0;
- url_bar->extent.y1 = 0;
-
- url_bar->window = NULL;
- url_bar->container_icon = -1;
- url_bar->text_icon = -1;
- url_bar->suggest_icon = -1;
-
- url_bar->favicon_extent.x0 = 0;
- url_bar->favicon_extent.y0 = 0;
- url_bar->favicon_extent.x1 = 0;
- url_bar->favicon_extent.y1 = 0;
- url_bar->favicon_width = 0;
- url_bar->favicon_height = 0;
- url_bar->favicon_content = NULL;
- url_bar->favicon_type = 0;
- strncpy(url_bar->favicon_sprite, "Ssmall_xxx",
- URLBAR_FAVICON_NAME_LENGTH);
-
- url_bar->hotlist.set = false;
- url_bar->hotlist.extent.x0 = 0;
- url_bar->hotlist.extent.y0 = 0;
- url_bar->hotlist.extent.x1 = 0;
- url_bar->hotlist.extent.y1 = 0;
-
- url_bar->text_size = RO_GUI_MAX_URL_SIZE;
- url_bar->text_buffer = malloc(url_bar->text_size);
- if (url_bar->text_buffer == NULL) {
- free(url_bar);
- return NULL;
- }
- url_bar->text_buffer[0] = 0;
- url_bar->text_buffer_utf8 = NULL;
-
- url_bar->hidden = false;
-
- return url_bar;
-}
-
-
/**
* Position the icons in the URL bar to take account of the currently
* configured extent.
*
- * \param *url_bar The URL bar to update.
- * \param full true to resize everything; false to move only
- * the right-hand end of the bar.
- * \return true if successful; else false.
+ * \param *url_bar The URL bar to update.
+ * \param full true to resize everything;
+ * false to move only the right-hand end of the bar.
+ * \return true if successful; else false.
*/
-
static bool ro_gui_url_bar_icon_resize(struct url_bar *url_bar, bool full)
{
- int x0, y0, x1, y1;
- int centre;
- os_error *error;
- os_coord eig = {1, 1};
- wimp_caret caret;
-
- if (url_bar == NULL || url_bar->window == NULL)
+ int x0, y0, x1, y1;
+ int centre;
+ os_error *error;
+ os_coord eig = {1, 1};
+ wimp_caret caret;
+
+ if ((url_bar == NULL) ||
+ (url_bar->window == NULL)) {
return false;
+ }
/* calculate 1px in OS units */
ro_convert_pixels_to_os_units(&eig, (os_mode) -1);
/* The vertical centre line of the widget's extent. */
-
centre = url_bar->extent.y0 +
- (url_bar->extent.y1 - url_bar->extent.y0) / 2;
+ (url_bar->extent.y1 - url_bar->extent.y0) / 2;
/* Position the container icon. */
-
if (url_bar->container_icon != -1) {
x0 = url_bar->extent.x0;
x1 = url_bar->extent.x1 -
- url_bar->suggest_x - URLBAR_GRIGHT_GUTTER;
+ url_bar->suggest.x - URLBAR_GRIGHT_GUTTER;
y0 = centre - (URLBAR_HEIGHT / 2);
y1 = y0 + URLBAR_HEIGHT;
error = xwimp_resize_icon(url_bar->window,
- url_bar->container_icon,
- x0, y0, x1, y1);
+ url_bar->container_icon,
+ x0, y0, x1, y1);
if (error != NULL) {
- NSLOG(netsurf, INFO, "xwimp_resize_icon: 0x%x: %s",
+ NSLOG(netsurf, INFO,
+ "xwimp_resize_icon: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
url_bar->container_icon = -1;
@@ -249,82 +189,90 @@ static bool ro_gui_url_bar_icon_resize(struct url_bar *url_bar, bool full)
}
/* Position the URL Suggest icon. */
-
- if (url_bar->suggest_icon != -1) {
- x0 = url_bar->extent.x1 - url_bar->suggest_x;
+ if (url_bar->suggest.icon != -1) {
+ x0 = url_bar->extent.x1 - url_bar->suggest.x;
x1 = url_bar->extent.x1;
- y0 = centre - (url_bar->suggest_y / 2);
- y1 = y0 + url_bar->suggest_y;
+ y0 = centre - (url_bar->suggest.y / 2);
+ y1 = y0 + url_bar->suggest.y;
error = xwimp_resize_icon(url_bar->window,
- url_bar->suggest_icon,
- x0, y0, x1, y1);
+ url_bar->suggest.icon,
+ x0, y0, x1, y1);
if (error != NULL) {
- NSLOG(netsurf, INFO, "xwimp_resize_icon: 0x%x: %s",
+ NSLOG(netsurf, INFO,
+ "xwimp_resize_icon: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
- url_bar->suggest_icon = -1;
+ url_bar->suggest.icon = -1;
return false;
}
}
/* Position the Text icon. */
-
- if (url_bar->text_icon != -1) {
- x0 = url_bar->extent.x0 + URLBAR_FAVICON_WIDTH;
+ if (url_bar->text.icon != -1) {
+ x0 = url_bar->extent.x0 + URLBAR_PGINFO_WIDTH + URLBAR_FAVICON_WIDTH;
x1 = url_bar->extent.x1 - eig.x - URLBAR_HOTLIST_WIDTH -
- url_bar->suggest_x - URLBAR_GRIGHT_GUTTER;
+ url_bar->suggest.x - URLBAR_GRIGHT_GUTTER;
y0 = centre - (URLBAR_HEIGHT / 2) + eig.y;
y1 = y0 + URLBAR_HEIGHT - 2 * eig.y;
error = xwimp_resize_icon(url_bar->window,
- url_bar->text_icon,
- x0, y0, x1, y1);
+ url_bar->text.icon,
+ x0, y0, x1, y1);
if (error != NULL) {
- NSLOG(netsurf, INFO, "xwimp_resize_icon: 0x%x: %s",
+ NSLOG(netsurf, INFO,
+ "xwimp_resize_icon: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
- url_bar->text_icon = -1;
+ url_bar->text.icon = -1;
return false;
}
if (xwimp_get_caret_position(&caret) == NULL) {
if ((caret.w == url_bar->window) &&
- (caret.i == url_bar->text_icon)) {
+ (caret.i == url_bar->text.icon)) {
xwimp_set_caret_position(url_bar->window,
- url_bar->text_icon, caret.pos.x,
- caret.pos.y, -1, caret.index);
+ url_bar->text.icon,
+ caret.pos.x,
+ caret.pos.y,
+ -1,
+ caret.index);
}
}
}
- /* Position the Favicon icon. */
+ /* Position the page info icon. */
+ url_bar->pginfo.extent.x0 = url_bar->extent.x0 + eig.x;
+ url_bar->pginfo.extent.x1 = url_bar->extent.x0 + URLBAR_PGINFO_WIDTH;
+ url_bar->pginfo.extent.y0 = centre - (URLBAR_HEIGHT / 2) + eig.y;
+ url_bar->pginfo.extent.y1 = url_bar->pginfo.extent.y0 + URLBAR_HEIGHT
+ - 2 * eig.y;
- url_bar->favicon_extent.x0 = url_bar->extent.x0 + eig.x;
- url_bar->favicon_extent.x1 = url_bar->extent.x0 + URLBAR_FAVICON_WIDTH;
- url_bar->favicon_extent.y0 = centre - (URLBAR_HEIGHT / 2) + eig.y;
- url_bar->favicon_extent.y1 = url_bar->favicon_extent.y0 + URLBAR_HEIGHT
- - 2 * eig.y;
+ /* Position the Favicon icon. */
+ url_bar->favicon.extent.x0 = url_bar->extent.x0 + URLBAR_PGINFO_WIDTH ;
+ url_bar->favicon.extent.x1 = url_bar->extent.x0 + URLBAR_PGINFO_WIDTH + URLBAR_FAVICON_WIDTH;
+ url_bar->favicon.extent.y0 = centre - (URLBAR_HEIGHT / 2) + eig.y;
+ url_bar->favicon.extent.y1 = url_bar->favicon.extent.y0 + URLBAR_HEIGHT
+ - 2 * eig.y;
/* Position the Hotlist icon. */
-
url_bar->hotlist.extent.x0 = url_bar->extent.x1 - eig.x -
- URLBAR_HOTLIST_WIDTH - url_bar->suggest_x -
- URLBAR_GRIGHT_GUTTER;
+ URLBAR_HOTLIST_WIDTH - url_bar->suggest.x -
+ URLBAR_GRIGHT_GUTTER;
url_bar->hotlist.extent.x1 = url_bar->hotlist.extent.x0 +
- URLBAR_HOTLIST_WIDTH;
+ URLBAR_HOTLIST_WIDTH;
url_bar->hotlist.extent.y0 = centre - (URLBAR_HEIGHT / 2) + eig.y;
url_bar->hotlist.extent.y1 = url_bar->hotlist.extent.y0 + URLBAR_HEIGHT
- - 2 * eig.y;
+ - 2 * eig.y;
url_bar->hotlist.offset.x = ((url_bar->hotlist.extent.x1 -
- url_bar->hotlist.extent.x0) -
- (URLBAR_HOTLIST_SIZE * 2)) / 2;
+ url_bar->hotlist.extent.x0) -
+ (URLBAR_HOTLIST_SIZE * 2)) / 2;
url_bar->hotlist.offset.y = ((url_bar->hotlist.extent.y1 -
- url_bar->hotlist.extent.y0) -
- (URLBAR_HOTLIST_SIZE * 2)) / 2 - 1;
+ url_bar->hotlist.extent.y0) -
+ (URLBAR_HOTLIST_SIZE * 2)) / 2 - 1;
return true;
}
@@ -334,18 +282,19 @@ static bool ro_gui_url_bar_icon_resize(struct url_bar *url_bar, bool full)
* Create or delete a URL bar's icons if required to bring it into sync with
* the current hidden setting.
*
- * \param *url_bar The URL bar to update.
- * \return true if successful; else false.
+ * \param *url_bar The URL bar to update.
+ * \return true if successful; else false.
*/
-
static bool ro_gui_url_bar_icon_update(struct url_bar *url_bar)
{
- wimp_icon_create icon;
- os_error *error;
- bool resize;
+ wimp_icon_create icon;
+ os_error *error;
+ bool resize;
- if (url_bar == NULL || url_bar->window == NULL)
+ if ((url_bar == NULL) ||
+ (url_bar->window == NULL)) {
return false;
+ }
icon.w = url_bar->window;
icon.icon.extent.x0 = 0;
@@ -359,13 +308,12 @@ static bool ro_gui_url_bar_icon_update(struct url_bar *url_bar)
if (!url_bar->hidden && url_bar->container_icon == -1) {
icon.icon.flags = wimp_ICON_BORDER |
- (wimp_COLOUR_BLACK <<
- wimp_ICON_FG_COLOUR_SHIFT) |
- (wimp_BUTTON_DOUBLE_CLICK_DRAG <<
- wimp_ICON_BUTTON_TYPE_SHIFT);
+ (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
+ (wimp_BUTTON_DOUBLE_CLICK_DRAG << wimp_ICON_BUTTON_TYPE_SHIFT);
error = xwimp_create_icon(&icon, &url_bar->container_icon);
if (error != NULL) {
- NSLOG(netsurf, INFO, "xwimp_create_icon: 0x%x: %s",
+ NSLOG(netsurf, INFO,
+ "xwimp_create_icon: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
url_bar->container_icon = -1;
@@ -373,11 +321,13 @@ static bool ro_gui_url_bar_icon_update(struct url_bar *url_bar)
}
resize = true;
- } else if (url_bar->hidden && url_bar->container_icon != -1){
+ } else if ((url_bar->hidden) &&
+ (url_bar->container_icon != -1)) {
error = xwimp_delete_icon(url_bar->window,
- url_bar->container_icon);
+ url_bar->container_icon);
if (error != NULL) {
- NSLOG(netsurf, INFO, "xwimp_delete_icon: 0x%x: %s",
+ NSLOG(netsurf, INFO,
+ "xwimp_delete_icon: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
return false;
@@ -387,55 +337,68 @@ static bool ro_gui_url_bar_icon_update(struct url_bar *url_bar)
}
/* Create or delete the text icon. */
-
- if (!url_bar->hidden && url_bar->text_icon == -1) {
- icon.icon.data.indirected_text.text = url_bar->text_buffer;
+ if (!url_bar->hidden &&
+ url_bar->text.icon == -1) {
+ icon.icon.data.indirected_text.text = url_bar->text.buffer;
icon.icon.data.indirected_text.validation = text_validation;
- icon.icon.data.indirected_text.size = url_bar->text_size;
- icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED |
- wimp_ICON_VCENTRED | wimp_ICON_FILLED |
- (wimp_COLOUR_BLACK <<
- wimp_ICON_FG_COLOUR_SHIFT);
- if (url_bar->display)
+ icon.icon.data.indirected_text.size = url_bar->text.size;
+ icon.icon.flags = wimp_ICON_TEXT |
+ wimp_ICON_INDIRECTED |
+ wimp_ICON_VCENTRED |
+ wimp_ICON_FILLED |
+ (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT);
+
+ if (url_bar->display) {
icon.icon.flags |= (wimp_BUTTON_NEVER <<
- wimp_ICON_BUTTON_TYPE_SHIFT);
- else
+ wimp_ICON_BUTTON_TYPE_SHIFT);
+ } else if (!ns_wimp_has_text_selection()) {
icon.icon.flags |= (wimp_BUTTON_WRITE_CLICK_DRAG <<
- wimp_ICON_BUTTON_TYPE_SHIFT);
- error = xwimp_create_icon(&icon, &url_bar->text_icon);
+ wimp_ICON_BUTTON_TYPE_SHIFT);
+ } else {
+ icon.icon.flags |= (wimp_BUTTON_WRITABLE <<
+ wimp_ICON_BUTTON_TYPE_SHIFT);
+ }
+ error = xwimp_create_icon(&icon, &url_bar->text.icon);
if (error) {
- NSLOG(netsurf, INFO, "xwimp_create_icon: 0x%x: %s",
+ NSLOG(netsurf, INFO,
+ "xwimp_create_icon: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
- url_bar->text_icon = -1;
+ url_bar->text.icon = -1;
return false;
}
resize = true;
- } else if (url_bar->hidden && url_bar->text_icon != -1) {
+
+ } else if (url_bar->hidden &&
+ url_bar->text.icon != -1) {
error = xwimp_delete_icon(url_bar->window,
- url_bar->text_icon);
+ url_bar->text.icon);
if (error != NULL) {
- NSLOG(netsurf, INFO, "xwimp_delete_icon: 0x%x: %s",
+ NSLOG(netsurf, INFO,
+ "xwimp_delete_icon: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
return false;
}
- url_bar->text_icon = -1;
+ url_bar->text.icon = -1;
}
/* Create or delete the suggest icon. */
-
- if (!url_bar->hidden && url_bar->suggest_icon == -1) {
+ if (!url_bar->hidden &&
+ url_bar->suggest.icon == -1) {
icon.icon.data.indirected_text.text = null_text_string;
icon.icon.data.indirected_text.size = 1;
icon.icon.data.indirected_text.validation = suggest_validation;
- icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE |
- wimp_ICON_INDIRECTED | wimp_ICON_HCENTRED |
- wimp_ICON_VCENTRED | (wimp_BUTTON_CLICK <<
- wimp_ICON_BUTTON_TYPE_SHIFT);
- error = xwimp_create_icon(&icon, &url_bar->suggest_icon);
+ icon.icon.flags = wimp_ICON_TEXT |
+ wimp_ICON_SPRITE |
+ wimp_ICON_INDIRECTED |
+ wimp_ICON_HCENTRED |
+ wimp_ICON_VCENTRED |
+ (wimp_BUTTON_CLICK << wimp_ICON_BUTTON_TYPE_SHIFT);
+
+ error = xwimp_create_icon(&icon, &url_bar->suggest.icon);
if (error) {
NSLOG(netsurf, INFO, "xwimp_create_icon: 0x%x: %s",
error->errnum, error->errmess);
@@ -445,59 +408,198 @@ static bool ro_gui_url_bar_icon_update(struct url_bar *url_bar)
if (!url_bar->display)
ro_gui_wimp_event_register_menu_gright(url_bar->window,
- wimp_ICON_WINDOW, url_bar->suggest_icon,
- ro_gui_url_suggest_menu);
+ wimp_ICON_WINDOW,
+ url_bar->suggest.icon,
+ ro_gui_url_suggest_menu);
- if (!ro_gui_url_bar_update_urlsuggest(url_bar))
+ if (!ro_gui_url_bar_update_urlsuggest(url_bar)) {
return false;
+ }
resize = true;
- } else if (url_bar->hidden && url_bar->suggest_icon != -1) {
+
+ } else if (url_bar->hidden &&
+ url_bar->suggest.icon != -1) {
ro_gui_wimp_event_deregister(url_bar->window,
- url_bar->suggest_icon);
+ url_bar->suggest.icon);
error = xwimp_delete_icon(url_bar->window,
- url_bar->suggest_icon);
+ url_bar->suggest.icon);
if (error != NULL) {
- NSLOG(netsurf, INFO, "xwimp_delete_icon: 0x%x: %s",
+ NSLOG(netsurf, INFO,
+ "xwimp_delete_icon: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
return false;
}
- url_bar->suggest_icon = -1;
+ url_bar->suggest.icon = -1;
}
/* If any icons were created, resize the bar. */
-
- if (resize && !ro_gui_url_bar_icon_resize(url_bar, true))
+ if (resize && !ro_gui_url_bar_icon_resize(url_bar, true)) {
return false;
+ }
/* If there are any icons, apply shading as necessary. */
-
- if (url_bar->container_icon != -1)
+ if (url_bar->container_icon != -1) {
ro_gui_set_icon_shaded_state(url_bar->window,
- url_bar->container_icon, url_bar->shaded);
+ url_bar->container_icon,
+ url_bar->shaded);
+ }
- if (url_bar->text_icon != -1)
+ if (url_bar->text.icon != -1) {
ro_gui_set_icon_shaded_state(url_bar->window,
- url_bar->text_icon, url_bar->shaded);
+ url_bar->text.icon,
+ url_bar->shaded);
+ }
- if (url_bar->suggest_icon != -1)
+ if (url_bar->suggest.icon != -1) {
ro_gui_set_icon_shaded_state(url_bar->window,
- url_bar->suggest_icon, url_bar->shaded);
+ url_bar->suggest.icon,
+ url_bar->shaded);
+ }
return true;
}
+/**
+ * Set the state of a URL Bar's hotlist icon.
+ *
+ * \param *url_bar The URL Bar to update.
+ * \param set TRUE to set the hotlist icon; FALSE to clear it.
+ */
+static void ro_gui_url_bar_set_hotlist(struct url_bar *url_bar, bool set)
+{
+ if (url_bar == NULL ||
+ set == url_bar->hotlist.set) {
+ return;
+ }
+
+ url_bar->hotlist.set = set;
+
+ if (!url_bar->hidden) {
+ xwimp_force_redraw(url_bar->window,
+ url_bar->hotlist.extent.x0,
+ url_bar->hotlist.extent.y0,
+ url_bar->hotlist.extent.x1,
+ url_bar->hotlist.extent.y1);
+ }
+}
+
+
+/**
+ * Callback for hlcache.
+ */
+static nserror
+ro_gui_url_bar_res_cb(hlcache_handle *handle,
+ const hlcache_event *event, void *pw)
+{
+ struct url_bar_resource *r = pw;
+
+ switch (event->type) {
+ case CONTENT_MSG_READY:
+ case CONTENT_MSG_DONE:
+ r->ready = true;
+ r->height = content_get_height(handle);
+ break;
+
+ default:
+ break;
+ }
+
+ return NSERROR_OK;
+}
+
+
/* This is an exported interface documented in url_bar.h */
+struct url_bar *ro_gui_url_bar_create(struct theme_descriptor *theme)
+{
+ struct url_bar *url_bar;
-bool ro_gui_url_bar_rebuild(struct url_bar *url_bar,
- struct theme_descriptor *theme, theme_style style,
- wimp_w window, bool display, bool shaded)
+ /* Allocate memory. */
+
+ url_bar = malloc(sizeof(struct url_bar));
+ if (url_bar == NULL) {
+ NSLOG(netsurf, INFO, "No memory for malloc()");
+ return NULL;
+ }
+
+ /* Set up default parameters. */
+
+ url_bar->theme = theme;
+ url_bar->sprites = ro_gui_theme_get_sprites(theme);
+
+ url_bar->display = false;
+ url_bar->shaded = false;
+
+ url_bar->x_min = URLBAR_FAVICON_WIDTH + URLBAR_MIN_WIDTH +
+ URLBAR_HOTLIST_WIDTH;
+ url_bar->y_min = URLBAR_HEIGHT;
+
+ url_bar->extent.x0 = 0;
+ url_bar->extent.y0 = 0;
+ url_bar->extent.x1 = 0;
+ url_bar->extent.y1 = 0;
+
+ url_bar->window = NULL;
+ url_bar->container_icon = -1;
+ url_bar->text.icon = -1;
+ url_bar->suggest.icon = -1;
+
+ url_bar->pginfo.extent.x0 = 0;
+ url_bar->pginfo.extent.y0 = 0;
+ url_bar->pginfo.extent.x1 = 0;
+ url_bar->pginfo.extent.y1 = 0;
+ strncpy(url_bar->pginfo.sprite,
+ "pgiinternal",
+ URLBAR_PGINFO_NAME_LENGTH);
+
+ url_bar->favicon.extent.x0 = 0;
+ url_bar->favicon.extent.y0 = 0;
+ url_bar->favicon.extent.x1 = 0;
+ url_bar->favicon.extent.y1 = 0;
+ url_bar->favicon.width = 0;
+ url_bar->favicon.height = 0;
+ url_bar->favicon.content = NULL;
+ url_bar->favicon.type = 0;
+ strncpy(url_bar->favicon.sprite,
+ "Ssmall_xxx",
+ URLBAR_FAVICON_NAME_LENGTH);
+
+ url_bar->hotlist.set = false;
+ url_bar->hotlist.extent.x0 = 0;
+ url_bar->hotlist.extent.y0 = 0;
+ url_bar->hotlist.extent.x1 = 0;
+ url_bar->hotlist.extent.y1 = 0;
+
+ url_bar->text.size = RO_GUI_MAX_URL_SIZE;
+ url_bar->text.buffer = malloc(url_bar->text.size);
+ if (url_bar->text.buffer == NULL) {
+ free(url_bar);
+ return NULL;
+ }
+ url_bar->text.buffer[0] = 0;
+ url_bar->text.buffer_utf8 = NULL;
+
+ url_bar->hidden = false;
+
+ return url_bar;
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+bool
+ro_gui_url_bar_rebuild(struct url_bar *url_bar,
+ struct theme_descriptor *theme,
+ theme_style style,
+ wimp_w window,
+ bool display,
+ bool shaded)
{
- if (url_bar == NULL)
+ if (url_bar == NULL) {
return false;
+ }
url_bar->theme = theme;
url_bar->window = window;
@@ -506,52 +608,62 @@ bool ro_gui_url_bar_rebuild(struct url_bar *url_bar,
url_bar->shaded = shaded;
url_bar->container_icon = -1;
- url_bar->text_icon = -1;
- url_bar->suggest_icon = -1;
+ url_bar->text.icon = -1;
+ url_bar->suggest.icon = -1;
ro_gui_wimp_get_sprite_dimensions((osspriteop_area *) -1,
- suggest_icon, &url_bar->suggest_x, &url_bar->suggest_y);
+ suggest_icon,
+ &url_bar->suggest.x,
+ &url_bar->suggest.y);
- url_bar->x_min = URLBAR_FAVICON_WIDTH + URLBAR_MIN_WIDTH +
- URLBAR_HOTLIST_WIDTH + URLBAR_GRIGHT_GUTTER +
- url_bar->suggest_x;
- url_bar->y_min = (url_bar->suggest_y > URLBAR_HEIGHT) ?
- url_bar->suggest_y : URLBAR_HEIGHT;
+ url_bar->x_min = URLBAR_PGINFO_WIDTH +
+ URLBAR_FAVICON_WIDTH +
+ URLBAR_MIN_WIDTH +
+ URLBAR_HOTLIST_WIDTH +
+ URLBAR_GRIGHT_GUTTER +
+ url_bar->suggest.x;
+
+ url_bar->y_min = (url_bar->suggest.y > URLBAR_HEIGHT) ?
+ url_bar->suggest.y : URLBAR_HEIGHT;
return ro_gui_url_bar_icon_update(url_bar);
}
/* This is an exported interface documented in url_bar.h */
-
void ro_gui_url_bar_destroy(struct url_bar *url_bar)
{
- if (url_bar == NULL)
+ if (url_bar == NULL) {
return;
+ }
- if (url_bar->text_buffer_utf8 != NULL)
- free(url_bar->text_buffer_utf8);
+ if (url_bar->text.buffer_utf8 != NULL) {
+ free(url_bar->text.buffer_utf8);
+ }
- if (url_bar->text_buffer != NULL)
- free(url_bar->text_buffer);
+ if (url_bar->text.buffer != NULL) {
+ free(url_bar->text.buffer);
+ }
free(url_bar);
}
/* This is an exported interface documented in url_bar.h */
-
-bool ro_gui_url_bar_get_dims(struct url_bar *url_bar,
- int *width, int *height)
+bool ro_gui_url_bar_get_dims(struct url_bar *url_bar, int *width, int *height)
{
- if (url_bar == NULL)
+ if (url_bar == NULL) {
return false;
+ }
- if (url_bar->x_min != -1 && url_bar->y_min != -1) {
- if (width != NULL)
+ if (url_bar->x_min != -1 &&
+ url_bar->y_min != -1) {
+ if (width != NULL) {
*width = url_bar->x_min;
- if (height != NULL)
+ }
+ if (height != NULL) {
*height = url_bar->y_min;
+ }
return true;
}
@@ -561,46 +673,52 @@ bool ro_gui_url_bar_get_dims(struct url_bar *url_bar,
/* This is an exported interface documented in url_bar.h */
-
-bool ro_gui_url_bar_set_extent(struct url_bar *url_bar,
- int x0, int y0, int x1, int y1)
+bool
+ro_gui_url_bar_set_extent(struct url_bar *url_bar,
+ int x0, int y0, int x1, int y1)
{
- bool stretch;
+ bool stretch;
- if (url_bar == NULL)
+ if (url_bar == NULL) {
return false;
+ }
- if ((x1 - x0) < url_bar->x_min || (y1 - y0) < url_bar->y_min)
+ if ((x1 - x0) < url_bar->x_min ||
+ (y1 - y0) < url_bar->y_min) {
return false;
+ }
- if (url_bar->extent.x0 == x0 && url_bar->extent.y0 == y0 &&
- url_bar->extent.x1 == x1 &&
- url_bar->extent.y1 == y1)
+ if (url_bar->extent.x0 == x0 &&
+ url_bar->extent.y0 == y0 &&
+ url_bar->extent.x1 == x1 &&
+ url_bar->extent.y1 == y1) {
return true;
+ }
/* If it's only the length that changes, less needs to be updated. */
-
- stretch = (url_bar->extent.x0 == x0 && url_bar->extent.y0 == y0 &&
- url_bar->extent.y1 == y1) ? true : false;
+ stretch = (url_bar->extent.x0 == x0 &&
+ url_bar->extent.y0 == y0 &&
+ url_bar->extent.y1 == y1) ? true : false;
/* Redraw the relevant bits of the toolbar. */
-
- if (url_bar->window != NULL && !url_bar->hidden) {
+ if (url_bar->window != NULL &&
+ !url_bar->hidden) {
if (stretch) {
xwimp_force_redraw(url_bar->window,
- x0 + URLBAR_FAVICON_WIDTH, y0,
- (x1 > url_bar->extent.x1) ?
- x1 : url_bar->extent.x1, y1);
+ x0 + URLBAR_PGINFO_WIDTH + URLBAR_FAVICON_WIDTH, y0,
+ (x1 > url_bar->extent.x1) ?
+ x1 : url_bar->extent.x1, y1);
} else {
xwimp_force_redraw(url_bar->window,
- url_bar->extent.x0, url_bar->extent.y0,
- url_bar->extent.x1, url_bar->extent.y1);
+ url_bar->extent.x0,
+ url_bar->extent.y0,
+ url_bar->extent.x1,
+ url_bar->extent.y1);
xwimp_force_redraw(url_bar->window, x0, y0, x1, y1);
}
}
/* Reposition the URL bar icons. */
-
url_bar->extent.x0 = x0;
url_bar->extent.y0 = y0;
url_bar->extent.x1 = x1;
@@ -611,7 +729,6 @@ bool ro_gui_url_bar_set_extent(struct url_bar *url_bar,
/* This is an exported interface documented in url_bar.h */
-
bool ro_gui_url_bar_hide(struct url_bar *url_bar, bool hide)
{
if (url_bar == NULL || url_bar->hidden == hide)
@@ -624,11 +741,11 @@ bool ro_gui_url_bar_hide(struct url_bar *url_bar, bool hide)
/* This is an exported interface documented in url_bar.h */
-
void ro_gui_url_bar_redraw(struct url_bar *url_bar, wimp_draw *redraw)
{
wimp_icon icon;
struct rect clip;
+ bool draw_pginfo = true;
bool draw_favicon = true;
bool draw_hotlist = true;
@@ -637,44 +754,75 @@ void ro_gui_url_bar_redraw(struct url_bar *url_bar, wimp_draw *redraw)
return;
if ((redraw->clip.x0 - (redraw->box.x0 - redraw->xscroll)) >
- (url_bar->favicon_extent.x1) ||
- (redraw->clip.y0 - (redraw->box.y1 - redraw->yscroll)) >
- (url_bar->favicon_extent.y1) ||
- (redraw->clip.x1 - (redraw->box.x0 - redraw->xscroll)) <
- (url_bar->favicon_extent.x0) ||
- (redraw->clip.y1 - (redraw->box.y1 - redraw->yscroll)) <
- (url_bar->favicon_extent.y0)) {
+ (url_bar->pginfo.extent.x1) ||
+ (redraw->clip.y0 - (redraw->box.y1 - redraw->yscroll)) >
+ (url_bar->pginfo.extent.y1) ||
+ (redraw->clip.x1 - (redraw->box.x0 - redraw->xscroll)) <
+ (url_bar->pginfo.extent.x0) ||
+ (redraw->clip.y1 - (redraw->box.y1 - redraw->yscroll)) <
+ (url_bar->pginfo.extent.y0)) {
+ /* page info not in redraw area */
+ draw_pginfo = false;
+ }
+
+ if ((redraw->clip.x0 - (redraw->box.x0 - redraw->xscroll)) >
+ (url_bar->favicon.extent.x1) ||
+ (redraw->clip.y0 - (redraw->box.y1 - redraw->yscroll)) >
+ (url_bar->favicon.extent.y1) ||
+ (redraw->clip.x1 - (redraw->box.x0 - redraw->xscroll)) <
+ (url_bar->favicon.extent.x0) ||
+ (redraw->clip.y1 - (redraw->box.y1 - redraw->yscroll)) <
+ (url_bar->favicon.extent.y0)) {
/* Favicon not in redraw area */
draw_favicon = false;
}
if ((redraw->clip.x0 - (redraw->box.x0 - redraw->xscroll)) >
- (url_bar->hotlist.extent.x1) ||
- (redraw->clip.y0 - (redraw->box.y1 - redraw->yscroll)) >
- (url_bar->hotlist.extent.y1) ||
- (redraw->clip.x1 - (redraw->box.x0 - redraw->xscroll)) <
- (url_bar->hotlist.extent.x0) ||
- (redraw->clip.y1 - (redraw->box.y1 - redraw->yscroll)) <
- (url_bar->hotlist.extent.y0)) {
+ (url_bar->hotlist.extent.x1) ||
+ (redraw->clip.y0 - (redraw->box.y1 - redraw->yscroll)) >
+ (url_bar->hotlist.extent.y1) ||
+ (redraw->clip.x1 - (redraw->box.x0 - redraw->xscroll)) <
+ (url_bar->hotlist.extent.x0) ||
+ (redraw->clip.y1 - (redraw->box.y1 - redraw->yscroll)) <
+ (url_bar->hotlist.extent.y0)) {
/* Hotlist icon not in redraw area */
draw_hotlist = false;
}
+ if (draw_pginfo) {
+ icon.flags = wimp_ICON_SPRITE |
+ wimp_ICON_INDIRECTED |
+ wimp_ICON_FILLED |
+ wimp_ICON_HCENTRED |
+ wimp_ICON_VCENTRED |
+ (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT);
+ icon.data.indirected_sprite.id = (osspriteop_id)url_bar->pginfo.sprite;
+ icon.data.indirected_sprite.area = url_bar->sprites;
+ icon.data.indirected_sprite.size = 12;
+
+ icon.extent.x0 = url_bar->pginfo.extent.x0;
+ icon.extent.x1 = url_bar->pginfo.extent.x1;
+ icon.extent.y0 = url_bar->pginfo.extent.y0;
+ icon.extent.y1 = url_bar->pginfo.extent.y1;
+
+ xwimp_plot_icon(&icon);
+ }
+
if (draw_favicon) {
- if (url_bar->favicon_content == NULL) {
+ if (url_bar->favicon.content == NULL) {
icon.data.indirected_text.text = null_text_string;
icon.data.indirected_text.validation =
- url_bar->favicon_sprite;
+ url_bar->favicon.sprite;
icon.data.indirected_text.size = 1;
icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE |
- wimp_ICON_INDIRECTED |
- wimp_ICON_FILLED |
- wimp_ICON_HCENTRED |
- wimp_ICON_VCENTRED;
- icon.extent.x0 = url_bar->favicon_extent.x0;
- icon.extent.x1 = url_bar->favicon_extent.x1;
- icon.extent.y0 = url_bar->favicon_extent.y0;
- icon.extent.y1 = url_bar->favicon_extent.y1;
+ wimp_ICON_INDIRECTED |
+ wimp_ICON_FILLED |
+ wimp_ICON_HCENTRED |
+ wimp_ICON_VCENTRED;
+ icon.extent.x0 = url_bar->favicon.extent.x0;
+ icon.extent.x1 = url_bar->favicon.extent.x1;
+ icon.extent.y0 = url_bar->favicon.extent.y0;
+ icon.extent.y1 = url_bar->favicon.extent.y1;
xwimp_plot_icon(&icon);
} else {
@@ -687,34 +835,34 @@ void ro_gui_url_bar_redraw(struct url_bar *url_bar, wimp_draw *redraw)
xwimp_set_colour(wimp_COLOUR_WHITE);
xos_plot(os_MOVE_TO,
- (redraw->box.x0 - redraw->xscroll) +
- url_bar->favicon_extent.x0,
- (redraw->box.y1 - redraw->yscroll) +
- url_bar->favicon_extent.y0);
+ (redraw->box.x0 - redraw->xscroll) +
+ url_bar->favicon.extent.x0,
+ (redraw->box.y1 - redraw->yscroll) +
+ url_bar->favicon.extent.y0);
xos_plot(os_PLOT_TO | os_PLOT_RECTANGLE,
- (redraw->box.x0 - redraw->xscroll) +
- url_bar->favicon_extent.x1,
- (redraw->box.y1 - redraw->yscroll) +
- url_bar->favicon_extent.y1);
+ (redraw->box.x0 - redraw->xscroll) +
+ url_bar->favicon.extent.x1,
+ (redraw->box.y1 - redraw->yscroll) +
+ url_bar->favicon.extent.y1);
clip.x0 = (redraw->clip.x0 - ro_plot_origin_x) / 2;
clip.y0 = (ro_plot_origin_y - redraw->clip.y0) / 2;
clip.x1 = (redraw->clip.x1 - ro_plot_origin_x) / 2;
clip.y1 = (ro_plot_origin_y - redraw->clip.y1) / 2;
- data.x = (url_bar->favicon_extent.x0 +
- url_bar->favicon_offset.x) / 2;
- data.y = (url_bar->favicon_offset.y -
- url_bar->favicon_extent.y1) / 2;
- data.width = url_bar->favicon_width;
- data.height = url_bar->favicon_height;
+ data.x = (url_bar->favicon.extent.x0 +
+ url_bar->favicon.offset.x) / 2;
+ data.y = (url_bar->favicon.offset.y -
+ url_bar->favicon.extent.y1) / 2;
+ data.width = url_bar->favicon.width;
+ data.height = url_bar->favicon.height;
data.background_colour = 0xFFFFFF;
data.scale = 1;
data.repeat_x = false;
data.repeat_y = false;
- content_redraw(url_bar->favicon_content,
- &data, &clip, &ctx);
+ content_redraw(url_bar->favicon.content,
+ &data, &clip, &ctx);
}
}
@@ -726,20 +874,20 @@ void ro_gui_url_bar_redraw(struct url_bar *url_bar, wimp_draw *redraw)
.plot = &ro_plotters
};
struct url_bar_resource *hotlist_icon = url_bar->hotlist.set ?
- &(url_bar_res[URLBAR_RES_HOTLIST_REMOVE]) :
- &(url_bar_res[URLBAR_RES_HOTLIST_ADD]);
+ &(url_bar_res[URLBAR_RES_HOTLIST_REMOVE]) :
+ &(url_bar_res[URLBAR_RES_HOTLIST_ADD]);
xwimp_set_colour(wimp_COLOUR_WHITE);
xos_plot(os_MOVE_TO,
- (redraw->box.x0 - redraw->xscroll) +
- url_bar->hotlist.extent.x0,
- (redraw->box.y1 - redraw->yscroll) +
- url_bar->hotlist.extent.y0);
+ (redraw->box.x0 - redraw->xscroll) +
+ url_bar->hotlist.extent.x0,
+ (redraw->box.y1 - redraw->yscroll) +
+ url_bar->hotlist.extent.y0);
xos_plot(os_PLOT_TO | os_PLOT_RECTANGLE,
- (redraw->box.x0 - redraw->xscroll) +
- url_bar->hotlist.extent.x1,
- (redraw->box.y1 - redraw->yscroll) +
- url_bar->hotlist.extent.y1);
+ (redraw->box.x0 - redraw->xscroll) +
+ url_bar->hotlist.extent.x1,
+ (redraw->box.y1 - redraw->yscroll) +
+ url_bar->hotlist.extent.y1);
if (hotlist_icon->ready == false) {
return;
@@ -751,9 +899,9 @@ void ro_gui_url_bar_redraw(struct url_bar *url_bar, wimp_draw *redraw)
clip.y1 = (ro_plot_origin_y - redraw->clip.y1) / 2;
data.x = (url_bar->hotlist.extent.x0 +
- url_bar->hotlist.offset.x) / 2;
+ url_bar->hotlist.offset.x) / 2;
data.y = (url_bar->hotlist.offset.y -
- url_bar->hotlist.extent.y1) / 2;
+ url_bar->hotlist.extent.y1) / 2;
data.width = URLBAR_HOTLIST_SIZE;
data.height = URLBAR_HOTLIST_SIZE;
data.background_colour = 0xFFFFFF;
@@ -765,67 +913,93 @@ void ro_gui_url_bar_redraw(struct url_bar *url_bar, wimp_draw *redraw)
}
}
+/**
+ * check if os point is inside an os box
+ *
+ * \param pos The coordinate of the point
+ * \param box The box to check against
+ * \return true if point is inside the box else false
+ */
+static inline bool is_point_in_box(os_coord *pos, os_box *box)
+{
+ if (pos->x < box->x0 ||
+ pos->x > box->x1 ||
+ pos->y < box->y0 ||
+ pos->y > box->y1) {
+ return false;
+ }
+ return true;
+}
/* This is an exported interface documented in url_bar.h */
-
-bool ro_gui_url_bar_click(struct url_bar *url_bar,
- wimp_pointer *pointer, wimp_window_state *state,
- url_bar_action *action)
+bool
+ro_gui_url_bar_click(struct url_bar *url_bar,
+ wimp_pointer *pointer,
+ wimp_window_state *state,
+ url_bar_action *action)
{
os_coord pos;
if (url_bar == NULL || url_bar->hidden ||
- url_bar->display || url_bar->shaded)
+ url_bar->display || url_bar->shaded) {
return false;
+ }
/* Check that the click was within our part of the window. */
-
pos.x = pointer->pos.x - state->visible.x0 + state->xscroll;
pos.y = pointer->pos.y - state->visible.y1 + state->yscroll;
- if (pos.x < url_bar->extent.x0 || pos.x > url_bar->extent.x1 ||
- pos.y < url_bar->extent.y0 ||
- pos.y > url_bar->extent.y1)
+ if (!is_point_in_box(&pos, &url_bar->extent)) {
return false;
+ }
/* If we have a Select or Adjust click, check if it originated on the
* hotlist icon; if it did, return an event.
*/
-
if (pointer->buttons == wimp_SINGLE_SELECT ||
- pointer->buttons == wimp_SINGLE_ADJUST) {
- if (pos.x >= url_bar->hotlist.extent.x0 &&
- pos.x <= url_bar->hotlist.extent.x1 &&
- pos.y >= url_bar->hotlist.extent.y0 &&
- pos.y <= url_bar->hotlist.extent.y1) {
+ pointer->buttons == wimp_SINGLE_ADJUST) {
+ if (is_point_in_box(&pos, &url_bar->hotlist.extent)) {
if (pointer->buttons == wimp_SINGLE_SELECT &&
- action != NULL)
+ action != NULL) {
*action = TOOLBAR_URL_SELECT_HOTLIST;
- else if (pointer->buttons == wimp_SINGLE_ADJUST &&
- action != NULL)
+ } else if (pointer->buttons == wimp_SINGLE_ADJUST &&
+ action != NULL) {
*action = TOOLBAR_URL_ADJUST_HOTLIST;
+ }
+ return true;
+ }
+
+ if (is_point_in_box(&pos, &url_bar->pginfo.extent)) {
+ if (pointer->buttons == wimp_SINGLE_SELECT &&
+ action != NULL) {
+ *action = TOOLBAR_URL_SELECT_PGINFO;
+ } else if (pointer->buttons == wimp_SINGLE_ADJUST &&
+ action != NULL) {
+ *action = TOOLBAR_URL_ADJUST_PGINFO;
+ }
return true;
}
+
}
/* If we find a Select or Adjust drag, check if it originated on the
* URL bar or over the favicon. If either, then return an event.
*/
-
if (pointer->buttons == wimp_DRAG_SELECT ||
- pointer->buttons == wimp_DRAG_ADJUST) {
- if (pointer->i == url_bar->text_icon) {
- if (action != NULL)
- *action = TOOLBAR_URL_DRAG_URL;
- return true;
+ pointer->buttons == wimp_DRAG_ADJUST) {
+ if (!ns_wimp_has_text_selection()) {
+ if (pointer->i == url_bar->text.icon) {
+ if (action != NULL) {
+ *action = TOOLBAR_URL_DRAG_URL;
+ }
+ return true;
+ }
}
- if (pos.x >= url_bar->favicon_extent.x0 &&
- pos.x <= url_bar->favicon_extent.x1 &&
- pos.y >= url_bar->favicon_extent.y0 &&
- pos.y <= url_bar->favicon_extent.y1) {
- if (action != NULL)
+ if (is_point_in_box(&pos, &url_bar->favicon.extent)) {
+ if (action != NULL) {
*action = TOOLBAR_URL_DRAG_FAVICON;
+ }
return true;
}
}
@@ -835,37 +1009,49 @@ bool ro_gui_url_bar_click(struct url_bar *url_bar,
/* This is an exported interface documented in url_bar.h */
-
-bool ro_gui_url_bar_menu_prepare(struct url_bar *url_bar, wimp_i i,
- wimp_menu *menu, wimp_pointer *pointer)
+bool
+ro_gui_url_bar_menu_prepare(struct url_bar *url_bar,
+ wimp_i i,
+ wimp_menu *menu,
+ wimp_pointer *pointer)
{
- if (url_bar == NULL || url_bar->suggest_icon != i ||
- menu != ro_gui_url_suggest_menu)
+ if (url_bar == NULL ||
+ url_bar->suggest.icon != i ||
+ menu != ro_gui_url_suggest_menu) {
return false;
+ }
- if (pointer != NULL)
+ if (pointer != NULL) {
return ro_gui_url_suggest_prepare_menu();
+ }
return true;
}
/* This is an exported interface documented in url_bar.h */
-
-bool ro_gui_url_bar_menu_select(struct url_bar *url_bar, wimp_i i,
- wimp_menu *menu, wimp_selection *selection, menu_action action)
+bool
+ro_gui_url_bar_menu_select(struct url_bar *url_bar,
+ wimp_i i,
+ wimp_menu *menu,
+ wimp_selection *selection,
+ menu_action action)
{
const char *urltxt;
struct gui_window *g;
- if (url_bar == NULL || url_bar->suggest_icon != i ||
- menu != ro_gui_url_suggest_menu)
+ if (url_bar == NULL ||
+ url_bar->suggest.icon != i ||
+ menu != ro_gui_url_suggest_menu) {
return false;
+ }
urltxt = ro_gui_url_suggest_get_selection(selection);
g = ro_gui_toolbar_lookup(url_bar->window);
- if (urltxt != NULL && g != NULL && g->bw != NULL) {
+ if (urltxt != NULL &&
+ g != NULL &&
+ g->bw != NULL) {
nsurl *url;
nserror error;
@@ -876,12 +1062,12 @@ bool ro_gui_url_bar_menu_select(struct url_bar *url_bar, wimp_i i,
ro_gui_window_set_url(g, url);
browser_window_navigate(g->bw,
- url,
- NULL,
- BW_NAVIGATE_HISTORY,
- NULL,
- NULL,
- NULL);
+ url,
+ NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
nsurl_unref(url);
}
}
@@ -891,65 +1077,74 @@ bool ro_gui_url_bar_menu_select(struct url_bar *url_bar, wimp_i i,
/* This is an exported interface documented in url_bar.h */
-
-bool ro_gui_url_bar_help_suffix(struct url_bar *url_bar, wimp_i i,
- os_coord *mouse, wimp_window_state *state,
- wimp_mouse_state buttons, const char **suffix)
+bool
+ro_gui_url_bar_help_suffix(struct url_bar *url_bar,
+ wimp_i i,
+ os_coord *mouse,
+ wimp_window_state *state,
+ wimp_mouse_state buttons,
+ const char **suffix)
{
- os_coord pos;
+ os_coord pos;
- if (url_bar == NULL || url_bar->hidden)
+ if (url_bar == NULL || url_bar->hidden) {
return false;
+ }
/* Check that the click was within our part of the window. */
pos.x = mouse->x - state->visible.x0 + state->xscroll;
pos.y = mouse->y - state->visible.y1 + state->yscroll;
- if (pos.x < url_bar->extent.x0 || pos.x > url_bar->extent.x1 ||
- pos.y < url_bar->extent.y0 ||
- pos.y > url_bar->extent.y1)
+ if (pos.x < url_bar->extent.x0 ||
+ pos.x > url_bar->extent.x1 ||
+ pos.y < url_bar->extent.y0 ||
+ pos.y > url_bar->extent.y1) {
return false;
+ }
/* Return hard-coded icon numbers that match the ones that were
* always allocated to the URL bar in a previous implementation.
* If Messages can be updated, this could be changed.
*/
- if (i == url_bar->text_icon)
+ if (i == url_bar->text.icon) {
*suffix = "14";
- else if (i == url_bar->suggest_icon)
+ } else if (i == url_bar->suggest.icon) {
*suffix = "15";
- else if (pos.x >= url_bar->hotlist.extent.x0 &&
- pos.x <= url_bar->hotlist.extent.x1 &&
- pos.y >= url_bar->hotlist.extent.y0 &&
- pos.y <= url_bar->hotlist.extent.y1)
+ } else if (pos.x >= url_bar->hotlist.extent.x0 &&
+ pos.x <= url_bar->hotlist.extent.x1 &&
+ pos.y >= url_bar->hotlist.extent.y0 &&
+ pos.y <= url_bar->hotlist.extent.y1) {
*suffix = "Hot";
- else if (pos.x >= url_bar->favicon_extent.x0 &&
- pos.x <= url_bar->favicon_extent.x1 &&
- pos.y >= url_bar->favicon_extent.y0 &&
- pos.y <= url_bar->favicon_extent.y1)
+ } else if (pos.x >= url_bar->favicon.extent.x0 &&
+ pos.x <= url_bar->favicon.extent.x1 &&
+ pos.y >= url_bar->favicon.extent.y0 &&
+ pos.y <= url_bar->favicon.extent.y1) {
*suffix = "Fav";
- else
+ } else {
*suffix = "";
+ }
return true;
}
/* This is an exported interface documented in url_bar.h */
-
bool ro_gui_url_bar_take_caret(struct url_bar *url_bar)
{
- os_error *error;
+ os_error *error;
- if (url_bar == NULL || url_bar->hidden)
+ if (url_bar == NULL || url_bar->hidden) {
return false;
+ }
- error = xwimp_set_caret_position(url_bar->window, url_bar->text_icon,
- -1, -1, -1, 0);
+ error = xwimp_set_caret_position(url_bar->window,
+ url_bar->text.icon,
+ -1, -1, -1, 0);
if (error) {
- NSLOG(netsurf, INFO, "xwimp_set_caret_position: 0x%x: %s",
+ NSLOG(netsurf, INFO,
+ "xwimp_set_caret_position: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
@@ -961,18 +1156,23 @@ bool ro_gui_url_bar_take_caret(struct url_bar *url_bar)
/* This is an exported interface documented in url_bar.h */
-
-void ro_gui_url_bar_set_url(struct url_bar *url_bar, const char *url,
- bool is_utf8, bool set_caret)
+void
+ro_gui_url_bar_set_url(struct url_bar *url_bar,
+ const char *url,
+ bool is_utf8,
+ bool set_caret)
{
- wimp_caret caret;
- os_error *error;
- char *local_text = NULL;
- const char *local_url;
+ wimp_caret caret;
+ os_error *error;
+ char *local_text = NULL;
+ const char *local_url;
nsurl *n;
- if (url_bar == NULL || url_bar->text_buffer == NULL || url == NULL)
+ if (url_bar == NULL ||
+ url_bar->text.buffer == NULL ||
+ url == NULL) {
return;
+ }
/* Before we do anything with the URL, get it into local encoding so
* that behaviour is consistent with the rest of the URL Bar module
@@ -996,55 +1196,56 @@ void ro_gui_url_bar_set_url(struct url_bar *url_bar, const char *url,
local_url = url;
}
- /* Copy the text into the icon buffer. If the text is too long, blank
- * the buffer and warn the user.
+ /* Copy the text into the icon buffer. If the text is too long, truncate
+ * for URL bar and log the full URL.
*/
-
- if (strlen(local_url) >= url_bar->text_size) {
- url_bar->text_buffer[0] = '\0';
- ro_warn_user("LongURL", NULL);
- NSLOG(netsurf, INFO, "Long URL (%zu chars): %s", strlen(url),
- url);
- } else {
- strncpy(url_bar->text_buffer, local_url,
- url_bar->text_size - 1);
- url_bar->text_buffer[url_bar->text_size - 1] = '\0';
+ if (strlen(local_url) >= url_bar->text.size) {
+ NSLOG(netsurf, WARNING,
+ "URL too long to show in URL bar (%zu chars): %s",
+ strlen(url), url);
}
- if (local_text != NULL)
+ strncpy(url_bar->text.buffer, local_url, url_bar->text.size - 1);
+ url_bar->text.buffer[url_bar->text.size - 1] = '\0';
+
+ if (local_text != NULL) {
free(local_text);
+ }
/* Set the hotlist flag. */
-
- if (nsurl_create(url_bar->text_buffer, &n) == NSERROR_OK) {
+ if (nsurl_create(url, &n) == NSERROR_OK) {
ro_gui_url_bar_set_hotlist(url_bar, ro_gui_hotlist_has_page(n));
nsurl_unref(n);
}
/* If there's no icon, then there's nothing else to do... */
-
- if (url_bar->text_icon == -1)
+ if (url_bar->text.icon == -1) {
return;
+ }
/* ...if there is, redraw the icon and fix the caret's position. */
-
- ro_gui_redraw_icon(url_bar->window, url_bar->text_icon);
+ ro_gui_redraw_icon(url_bar->window, url_bar->text.icon);
error = xwimp_get_caret_position(&caret);
if (error) {
- NSLOG(netsurf, INFO, "xwimp_get_caret_position: 0x%x: %s",
+ NSLOG(netsurf, INFO,
+ "xwimp_get_caret_position: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
return;
}
- if (set_caret || (caret.w == url_bar->window &&
- caret.i == url_bar->text_icon)) {
- const char *set_url = ro_gui_get_icon_string(url_bar->window,
- url_bar->text_icon);
+ if (set_caret ||
+ (caret.w == url_bar->window &&
+ caret.i == url_bar->text.icon)) {
+ const char *set_url;
+ set_url = ro_gui_get_icon_string(url_bar->window,
+ url_bar->text.icon);
error = xwimp_set_caret_position(url_bar->window,
- url_bar->text_icon, 0, 0, -1, strlen(set_url));
+ url_bar->text.icon,
+ 0, 0, -1,
+ strlen(set_url));
if (error) {
NSLOG(netsurf, INFO,
"xwimp_set_caret_position: 0x%x: %s",
@@ -1057,88 +1258,73 @@ void ro_gui_url_bar_set_url(struct url_bar *url_bar, const char *url,
/* This is an exported interface documented in url_bar.h */
-
void ro_gui_url_bar_update_hotlist(struct url_bar *url_bar)
{
const char *url;
nsurl *n;
- if (url_bar == NULL)
+ if (url_bar == NULL) {
return;
+ }
- url = (const char *) url_bar->text_buffer;
- if (url != NULL && nsurl_create(url, &n) == NSERROR_OK) {
+ url = (const char *) url_bar->text.buffer;
+ if (url != NULL &&
+ nsurl_create(url, &n) == NSERROR_OK) {
ro_gui_url_bar_set_hotlist(url_bar, ro_gui_hotlist_has_page(n));
nsurl_unref(n);
}
}
-/**
- * Set the state of a URL Bar's hotlist icon.
- *
- * \param *url_bar The URL Bar to update.
- * \param set TRUE to set the hotlist icon; FALSE to clear it.
- */
-
-static void ro_gui_url_bar_set_hotlist(struct url_bar *url_bar, bool set)
-{
- if (url_bar == NULL || set == url_bar->hotlist.set)
- return;
-
- url_bar->hotlist.set = set;
-
- if (!url_bar->hidden) {
- xwimp_force_redraw(url_bar->window,
- url_bar->hotlist.extent.x0,
- url_bar->hotlist.extent.y0,
- url_bar->hotlist.extent.x1,
- url_bar->hotlist.extent.y1);
- }
-}
-
-
/* This is an exported interface documented in url_bar.h */
-
const char *ro_gui_url_bar_get_url(struct url_bar *url_bar)
{
- if ((url_bar == NULL) || (url_bar->text_buffer == NULL))
+ nserror res;
+
+ if ((url_bar == NULL) ||
+ (url_bar->text.buffer == NULL)) {
return NULL;
+ }
- if (url_bar->text_buffer_utf8 != NULL) {
- free(url_bar->text_buffer_utf8);
- url_bar->text_buffer_utf8 = NULL;
+ if (url_bar->text.buffer_utf8 != NULL) {
+ free(url_bar->text.buffer_utf8);
+ url_bar->text.buffer_utf8 = NULL;
}
- if (url_bar->text_buffer[0] == '\0')
- return (const char *) url_bar->text_buffer;
+ if (url_bar->text.buffer[0] == '\0') {
+ return (const char *) url_bar->text.buffer;
+ }
- if (utf8_from_local_encoding(url_bar->text_buffer, 0, &url_bar->text_buffer_utf8) == NSERROR_OK) {
- return (const char *) url_bar->text_buffer_utf8;
+ res = utf8_from_local_encoding(url_bar->text.buffer, 0,
+ &url_bar->text.buffer_utf8);
+ if (res == NSERROR_OK) {
+ return (const char *)url_bar->text.buffer_utf8;
}
- return (const char *) url_bar->text_buffer;
+ return (const char *) url_bar->text.buffer;
}
/* This is an exported interface documented in url_bar.h */
-
bool ro_gui_url_bar_get_url_extent(struct url_bar *url_bar, os_box *extent)
{
- wimp_icon_state state;
- os_error *error;
+ wimp_icon_state state;
+ os_error *error;
- if (url_bar == NULL || url_bar->hidden)
+ if (url_bar == NULL || url_bar->hidden) {
return false;
+ }
- if (extent == NULL)
+ if (extent == NULL) {
return true;
+ }
state.w = url_bar->window;
state.i = url_bar->container_icon;
error = xwimp_get_icon_state(&state);
if (error) {
- NSLOG(netsurf, INFO, "xwimp_get_icon_state: 0x%x: %s",
+ NSLOG(netsurf, INFO,
+ "xwimp_get_icon_state: 0x%x: %s",
error->errnum, error->errmess);
ro_warn_user("WimpError", error->errmess);
return false;
@@ -1154,36 +1340,45 @@ bool ro_gui_url_bar_get_url_extent(struct url_bar *url_bar, os_box *extent)
/* This is an exported interface documented in url_bar.h */
-
-bool ro_gui_url_bar_test_for_text_field_click(struct url_bar *url_bar,
- wimp_pointer *pointer)
+bool
+ro_gui_url_bar_test_for_text_field_click(struct url_bar *url_bar,
+ wimp_pointer *pointer)
{
- if (url_bar == NULL || url_bar->hidden || pointer == NULL)
+ if (url_bar == NULL ||
+ url_bar->hidden ||
+ pointer == NULL) {
return false;
+ }
return (pointer->w == url_bar->window &&
- pointer->i == url_bar->text_icon) ? true : false;
+ pointer->i == url_bar->text.icon) ? true : false;
}
/* This is an exported interface documented in url_bar.h */
-
-bool ro_gui_url_bar_test_for_text_field_keypress(struct url_bar *url_bar,
- wimp_key *key)
+bool
+ro_gui_url_bar_test_for_text_field_keypress(struct url_bar *url_bar,
+ wimp_key *key)
{
const char *url;
nsurl *n;
- if (url_bar == NULL || url_bar->hidden || key == NULL)
+ if (url_bar == NULL ||
+ url_bar->hidden ||
+ key == NULL) {
return false;
+ }
- if (key->w != url_bar->window || key->i != url_bar->text_icon)
+ if (key->w != url_bar->window ||
+ key->i != url_bar->text.icon) {
return false;
+ }
/* Update hotlist indicator */
- url = (const char *) url_bar->text_buffer;
- if (url != NULL && nsurl_create(url, &n) == NSERROR_OK) {
+ url = (const char *) url_bar->text.buffer;
+ if (url != NULL &&
+ nsurl_create(url, &n) == NSERROR_OK) {
ro_gui_url_bar_set_hotlist(url_bar, ro_gui_hotlist_has_page(n));
nsurl_unref(n);
} else if (url_bar->hotlist.set) {
@@ -1195,101 +1390,165 @@ bool ro_gui_url_bar_test_for_text_field_keypress(struct url_bar *url_bar,
/* This is an exported interface documented in url_bar.h */
-
-bool ro_gui_url_bar_set_site_favicon(struct url_bar *url_bar,
- struct hlcache_handle *h)
+bool
+ro_gui_url_bar_set_site_favicon(struct url_bar *url_bar,
+ struct hlcache_handle *h)
{
- content_type type = CONTENT_NONE;
+ content_type type = CONTENT_NONE;
- if (url_bar == NULL)
+ if (url_bar == NULL) {
return false;
+ }
- if (h != NULL)
+ if (h != NULL) {
type = content_get_type(h);
+ }
// \TODO -- Maybe test for CONTENT_ICO ???
if (type == CONTENT_IMAGE) {
- url_bar->favicon_content = h;
- url_bar->favicon_width = content_get_width(h);
- url_bar->favicon_height = content_get_height(h);
-
- if (url_bar->favicon_width > URLBAR_FAVICON_SIZE)
- url_bar->favicon_width = URLBAR_FAVICON_SIZE;
-
- if (url_bar->favicon_height > URLBAR_FAVICON_SIZE)
- url_bar->favicon_height = URLBAR_FAVICON_SIZE;
-
- url_bar->favicon_offset.x = ((url_bar->favicon_extent.x1 -
- url_bar->favicon_extent.x0) -
- (url_bar->favicon_width * 2)) / 2;
- url_bar->favicon_offset.y = ((url_bar->favicon_extent.y1 -
- url_bar->favicon_extent.y0) -
- (url_bar->favicon_height * 2)) / 2;
+ url_bar->favicon.content = h;
+ url_bar->favicon.width = content_get_width(h);
+ url_bar->favicon.height = content_get_height(h);
+
+ if (url_bar->favicon.width > URLBAR_FAVICON_SIZE) {
+ url_bar->favicon.width = URLBAR_FAVICON_SIZE;
+ }
+
+ if (url_bar->favicon.height > URLBAR_FAVICON_SIZE) {
+ url_bar->favicon.height = URLBAR_FAVICON_SIZE;
+ }
+
+ url_bar->favicon.offset.x = ((url_bar->favicon.extent.x1 -
+ url_bar->favicon.extent.x0) -
+ (url_bar->favicon.width * 2)) / 2;
+ url_bar->favicon.offset.y = ((url_bar->favicon.extent.y1 -
+ url_bar->favicon.extent.y0) -
+ (url_bar->favicon.height * 2)) / 2;
} else {
- url_bar->favicon_content = NULL;
+ url_bar->favicon.content = NULL;
- if (url_bar->favicon_type != 0)
- snprintf(url_bar->favicon_sprite,
- URLBAR_FAVICON_NAME_LENGTH,
- "Ssmall_%.3x", url_bar->favicon_type);
- else
- snprintf(url_bar->favicon_sprite,
- URLBAR_FAVICON_NAME_LENGTH,
- "Ssmall_xxx");
+ if (url_bar->favicon.type != 0) {
+ snprintf(url_bar->favicon.sprite,
+ URLBAR_FAVICON_NAME_LENGTH,
+ "Ssmall_%.3x", url_bar->favicon.type);
+ } else {
+ snprintf(url_bar->favicon.sprite,
+ URLBAR_FAVICON_NAME_LENGTH,
+ "Ssmall_xxx");
+ }
}
- if (!url_bar->hidden)
+ if (!url_bar->hidden) {
xwimp_force_redraw(url_bar->window,
- url_bar->favicon_extent.x0,
- url_bar->favicon_extent.y0,
- url_bar->favicon_extent.x1,
- url_bar->favicon_extent.y1);
+ url_bar->favicon.extent.x0,
+ url_bar->favicon.extent.y0,
+ url_bar->favicon.extent.x1,
+ url_bar->favicon.extent.y1);
+ }
return true;
}
/* This is an exported interface documented in url_bar.h */
+bool ro_gui_url_bar_page_info_change(struct url_bar *url_bar)
+{
+ browser_window_page_info_state pistate;
+ const char *icon_name;
+ struct gui_window *g;
+
+ g = ro_gui_toolbar_lookup(url_bar->window);
+
+ pistate = browser_window_get_page_info_state(g->bw);
+
+ switch (pistate) {
+ case PAGE_STATE_LOCAL:
+ icon_name = "pgilocal";
+ break;
+
+ case PAGE_STATE_INSECURE:
+ icon_name = "pgiinsecure";
+ break;
+
+ case PAGE_STATE_SECURE_OVERRIDE:
+ icon_name = "pgiwarning";
+ break;
+
+ case PAGE_STATE_SECURE_ISSUES:
+ icon_name = "pgiwarning";
+ break;
+
+ case PAGE_STATE_SECURE:
+ icon_name = "pgisecure";
+ break;
-bool ro_gui_url_bar_set_content_favicon(struct url_bar *url_bar,
- struct gui_window *g)
+ case PAGE_STATE_INTERNAL:
+ default:
+ icon_name = "pgiinternal";
+ break;
+ }
+
+ strncpy(url_bar->pginfo.sprite, icon_name, URLBAR_PGINFO_NAME_LENGTH);
+
+ if (!url_bar->hidden) {
+ xwimp_force_redraw(url_bar->window,
+ url_bar->pginfo.extent.x0,
+ url_bar->pginfo.extent.y0,
+ url_bar->pginfo.extent.x1,
+ url_bar->pginfo.extent.y1);
+ }
+
+ return true;
+}
+
+
+/* This is an exported interface documented in url_bar.h */
+bool
+ro_gui_url_bar_set_content_favicon(struct url_bar *url_bar,
+ struct gui_window *g)
{
int type = 0;
- char sprite[URLBAR_FAVICON_NAME_LENGTH];
+ char sprite[URLBAR_FAVICON_NAME_LENGTH-1];
struct hlcache_handle *h;
- if (url_bar == NULL || g == NULL)
+ if (url_bar == NULL ||
+ g == NULL) {
return false;
+ }
h = browser_window_get_content(g->bw);
- if (h != NULL)
+ if (h != NULL) {
type = ro_content_filetype(h);
+ }
if (type != 0) {
snprintf(sprite, URLBAR_FAVICON_NAME_LENGTH,
- "small_%.3x", type);
+ "small_%.3x", type);
- if (!ro_gui_wimp_sprite_exists(sprite))
+ if (!ro_gui_wimp_sprite_exists(sprite)) {
type = 0;
+ }
}
- url_bar->favicon_type = type;
+ url_bar->favicon.type = type;
- if (url_bar->favicon_content == NULL) {
- if (type == 0)
- snprintf(url_bar->favicon_sprite,
- URLBAR_FAVICON_NAME_LENGTH, "Ssmall_xxx");
- else
- snprintf(url_bar->favicon_sprite,
- URLBAR_FAVICON_NAME_LENGTH, "S%s", sprite);
+ if (url_bar->favicon.content == NULL) {
+ if (type == 0) {
+ snprintf(url_bar->favicon.sprite,
+ URLBAR_FAVICON_NAME_LENGTH, "Ssmall_xxx");
+ } else {
+ snprintf(url_bar->favicon.sprite,
+ URLBAR_FAVICON_NAME_LENGTH, "S%s", sprite);
+ }
- if (!url_bar->hidden)
+ if (!url_bar->hidden) {
xwimp_force_redraw(url_bar->window,
- url_bar->favicon_extent.x0,
- url_bar->favicon_extent.y0,
- url_bar->favicon_extent.x1,
- url_bar->favicon_extent.y1);
+ url_bar->favicon.extent.x0,
+ url_bar->favicon.extent.y0,
+ url_bar->favicon.extent.x1,
+ url_bar->favicon.extent.y1);
+ }
}
return true;
@@ -1297,41 +1556,21 @@ bool ro_gui_url_bar_set_content_favicon(struct url_bar *url_bar,
/* This is an exported interface documented in url_bar.h */
-
bool ro_gui_url_bar_update_urlsuggest(struct url_bar *url_bar)
{
- if (url_bar == NULL || url_bar->hidden)
+ if (url_bar == NULL ||
+ url_bar->hidden) {
return (url_bar == NULL) ? false : true;
+ }
- if (url_bar->window != NULL && url_bar->suggest_icon != -1)
+ if (url_bar->window != NULL &&
+ url_bar->suggest.icon != -1) {
ro_gui_set_icon_shaded_state(url_bar->window,
- url_bar->suggest_icon,
- !ro_gui_url_suggest_get_menu_available());
-
- return true;
-}
-
-
-/**
- * Callback for hlcache.
- */
-static nserror ro_gui_url_bar_res_cb(hlcache_handle *handle,
- const hlcache_event *event, void *pw)
-{
- struct url_bar_resource *r = pw;
-
- switch (event->type) {
- case CONTENT_MSG_READY:
- case CONTENT_MSG_DONE:
- r->ready = true;
- r->height = content_get_height(handle);
- break;
-
- default:
- break;
+ url_bar->suggest.icon,
+ !ro_gui_url_suggest_get_menu_available());
}
- return NSERROR_OK;
+ return true;
}
@@ -1343,10 +1582,15 @@ bool ro_gui_url_bar_init(void)
for (i = 0; i < URLBAR_RES_LAST; i++) {
nsurl *url;
if (nsurl_create(url_bar_res[i].url, &url) == NSERROR_OK) {
- hlcache_handle_retrieve(url, 0, NULL, NULL,
- ro_gui_url_bar_res_cb,
- &(url_bar_res[i]), NULL,
- CONTENT_IMAGE, &(url_bar_res[i].c));
+ hlcache_handle_retrieve(url,
+ 0,
+ NULL,
+ NULL,
+ ro_gui_url_bar_res_cb,
+ &(url_bar_res[i]),
+ NULL,
+ CONTENT_IMAGE,
+ &(url_bar_res[i].c));
nsurl_unref(url);
}
}
diff --git a/frontends/riscos/gui/url_bar.h b/frontends/riscos/gui/url_bar.h
index 9486e214d..fc210f503 100644
--- a/frontends/riscos/gui/url_bar.h
+++ b/frontends/riscos/gui/url_bar.h
@@ -35,7 +35,9 @@ typedef enum {
TOOLBAR_URL_DRAG_URL,
TOOLBAR_URL_DRAG_FAVICON,
TOOLBAR_URL_SELECT_HOTLIST,
- TOOLBAR_URL_ADJUST_HOTLIST
+ TOOLBAR_URL_ADJUST_HOTLIST,
+ TOOLBAR_URL_SELECT_PGINFO,
+ TOOLBAR_URL_ADJUST_PGINFO
} url_bar_action;
struct url_bar;
@@ -323,8 +325,17 @@ bool ro_gui_url_bar_set_content_favicon(struct url_bar *url_bar,
* \param *url_bar The URL bar to update.
* \return true if successful; else false.
*/
-
bool ro_gui_url_bar_update_urlsuggest(struct url_bar *url_bar);
+
+/**
+ * Update the page info icon
+ *
+ * \param url_bar The URL bar to update.
+ * \return true if successful; else false.
+ */
+bool ro_gui_url_bar_page_info_change(struct url_bar *url_bar);
+
+
#endif
diff --git a/frontends/riscos/hotlist.c b/frontends/riscos/hotlist.c
index b0ed1e2f4..7e18ce88e 100644
--- a/frontends/riscos/hotlist.c
+++ b/frontends/riscos/hotlist.c
@@ -423,6 +423,7 @@ hotlist_menu_select(wimp_w w,
*/
static nserror ro_hotlist_init(void)
{
+ os_error *error;
struct ro_hotlist_window *ncwin;
nserror res;
static const struct ns_menu hotlist_menu_def = {
@@ -472,7 +473,14 @@ static nserror ro_hotlist_init(void)
}
/* create window from template */
- ncwin->core.wh = wimp_create_window(dialog_hotlist_template);
+ error = xwimp_create_window(dialog_hotlist_template, &ncwin->core.wh);
+ if (error) {
+ NSLOG(netsurf, INFO, "xwimp_create_window: 0x%x: %s",
+ error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ free(ncwin);
+ return NSERROR_NOMEM;
+ }
ro_gui_set_window_title(ncwin->core.wh, messages_get("Hotlist"));
diff --git a/frontends/riscos/iconbar.c b/frontends/riscos/iconbar.c
index 23f97258b..c85827030 100644
--- a/frontends/riscos/iconbar.c
+++ b/frontends/riscos/iconbar.c
@@ -207,7 +207,7 @@ bool ro_gui_iconbar_menu_select(wimp_w w, wimp_i i, wimp_menu *menu,
switch (action) {
case HELP_OPEN_CONTENTS:
- error = nsurl_create("http://www.netsurf-browser.org/documentation/", &url);
+ error = nsurl_create("https://www.netsurf-browser.org/documentation/", &url);
if (error == NSERROR_OK) {
error = browser_window_create(BW_CREATE_HISTORY,
url,
@@ -232,7 +232,7 @@ bool ro_gui_iconbar_menu_select(wimp_w w, wimp_i i, wimp_menu *menu,
ro_gui_global_history_present();
return true;
case COOKIES_SHOW:
- ro_gui_cookies_present();
+ ro_gui_cookies_present(NULL);
return true;
case CHOICES_SHOW:
ro_gui_configure_show();
diff --git a/frontends/riscos/image.c b/frontends/riscos/image.c
index 30cb30096..5c90b05ba 100644
--- a/frontends/riscos/image.c
+++ b/frontends/riscos/image.c
@@ -27,76 +27,9 @@
#include "riscos/image.h"
#include "riscos/gui.h"
+#include "riscos/wimp.h"
#include "riscos/tinct.h"
-static bool image_redraw_tinct(osspriteop_id header, int x, int y,
- int req_width, int req_height, int width, int height,
- colour background_colour, bool repeatx, bool repeaty,
- bool alpha, unsigned int tinct_options);
-static bool image_redraw_os(osspriteop_id header, int x, int y,
- int req_width, int req_height, int width, int height);
-
-/**
- * Plot an image at the given coordinates using the method specified
- *
- * \param area The sprite area containing the sprite
- * \param x Left edge of sprite
- * \param y Top edge of sprite
- * \param req_width The requested width of the sprite
- * \param req_height The requested height of the sprite
- * \param width The actual width of the sprite
- * \param height The actual height of the sprite
- * \param background_colour The background colour to blend to
- * \param repeatx Repeat the image in the x direction
- * \param repeaty Repeat the image in the y direction
- * \param background Use background image settings (otherwise foreground)
- * \param type The plot method to use
- * \return true on success, false otherwise
- */
-bool image_redraw(osspriteop_area *area, int x, int y, int req_width,
- int req_height, int width, int height,
- colour background_colour,
- bool repeatx, bool repeaty, bool background, image_type type)
-{
- unsigned int tinct_options;
-
- /* failed decompression/loading can result in no image being present */
- if (!area)
- return false;
-
- osspriteop_id header = (osspriteop_id)
- ((char*) area + area->first);
- req_width *= 2;
- req_height *= 2;
- width *= 2;
- height *= 2;
- tinct_options = background ? nsoption_int(plot_bg_quality) :
- nsoption_int(plot_fg_quality);
- switch (type) {
- case IMAGE_PLOT_TINCT_ALPHA:
- return image_redraw_tinct(header, x, y,
- req_width, req_height,
- width, height,
- background_colour,
- repeatx, repeaty, true,
- tinct_options);
- case IMAGE_PLOT_TINCT_OPAQUE:
- return image_redraw_tinct(header, x, y,
- req_width, req_height,
- width, height,
- background_colour,
- repeatx, repeaty, false,
- tinct_options);
- case IMAGE_PLOT_OS:
- return image_redraw_os(header, x, y, req_width,
- req_height, width, height);
- default:
- break;
- }
-
- return false;
-}
-
/**
* Plot an image at the given coordinates using tinct
*
@@ -114,7 +47,7 @@ bool image_redraw(osspriteop_area *area, int x, int y, int req_width,
* \param tinct_options The base option set to use
* \return true on success, false otherwise
*/
-bool image_redraw_tinct(osspriteop_id header, int x, int y,
+static bool image_redraw_tinct(osspriteop_id header, int x, int y,
int req_width, int req_height, int width, int height,
colour background_colour, bool repeatx, bool repeaty,
bool alpha, unsigned int tinct_options)
@@ -133,11 +66,11 @@ bool image_redraw_tinct(osspriteop_id header, int x, int y,
if (alpha) {
error = _swix(Tinct_PlotScaledAlpha, _INR(2,7),
- header, x, y - req_height,
+ header, x, y,
req_width, req_height, tinct_options);
} else {
error = _swix(Tinct_PlotScaled, _INR(2,7),
- header, x, y - req_height,
+ header, x, y,
req_width, req_height, tinct_options);
}
@@ -150,7 +83,6 @@ bool image_redraw_tinct(osspriteop_id header, int x, int y,
return true;
}
-
/**
* Plot an image at the given coordinates using os_spriteop
*
@@ -161,10 +93,11 @@ bool image_redraw_tinct(osspriteop_id header, int x, int y,
* \param req_height The requested height of the sprite
* \param width The actual width of the sprite
* \param height The actual height of the sprite
+ * \param tile Whether to tile the sprite
* \return true on success, false otherwise
*/
-bool image_redraw_os(osspriteop_id header, int x, int y, int req_width,
- int req_height, int width, int height)
+static bool image_redraw_os(osspriteop_id header, int x, int y, int req_width,
+ int req_height, int width, int height, bool tile)
{
int size;
os_factors f;
@@ -172,7 +105,7 @@ bool image_redraw_os(osspriteop_id header, int x, int y, int req_width,
os_error *error;
error = xcolourtrans_generate_table_for_sprite(
- (osspriteop_area *)0x100, header,
+ osspriteop_UNSPECIFIED, header,
os_CURRENT_MODE,
colourtrans_CURRENT_PALETTE,
0, colourtrans_GIVEN_SPRITE, 0, 0, &size);
@@ -192,7 +125,7 @@ bool image_redraw_os(osspriteop_id header, int x, int y, int req_width,
}
error = xcolourtrans_generate_table_for_sprite(
- (osspriteop_area *)0x100, header,
+ osspriteop_UNSPECIFIED, header,
os_CURRENT_MODE,
colourtrans_CURRENT_PALETTE,
table, colourtrans_GIVEN_SPRITE, 0, 0, 0);
@@ -210,10 +143,15 @@ bool image_redraw_os(osspriteop_id header, int x, int y, int req_width,
f.xdiv = width;
f.ydiv = height;
- error = xosspriteop_put_sprite_scaled(osspriteop_PTR,
- (osspriteop_area *)0x100, header,
- x, (int)(y - req_height),
- 8, &f, table);
+ if (tile) {
+ error = xosspriteop_plot_tiled_sprite(osspriteop_PTR,
+ osspriteop_UNSPECIFIED, header, x, y,
+ osspriteop_USE_MASK, &f, table);
+ } else {
+ error = xosspriteop_put_sprite_scaled(osspriteop_PTR,
+ osspriteop_UNSPECIFIED, header, x, y,
+ osspriteop_USE_MASK, &f, table);
+ }
if (error) {
NSLOG(netsurf, INFO,
"xosspriteop_put_sprite_scaled: 0x%x: %s",
@@ -227,3 +165,135 @@ bool image_redraw_os(osspriteop_id header, int x, int y, int req_width,
return true;
}
+
+/**
+ * Override a sprite's mode.
+ *
+ * Only replaces mode if existing mode matches \ref old.
+ *
+ * \param[in] area The sprite area containing the sprite.
+ * \param[in] type Requested plot mode.
+ * \param[in] old Existing sprite mode to check for.
+ * \param[in] new Sprite mode to set if existing mode is expected.
+ */
+static inline void image__override_sprite_mode(
+ osspriteop_area *area,
+ image_type type,
+ os_mode old,
+ os_mode new)
+{
+ osspriteop_header *sprite = (osspriteop_header *)(area + 1);
+
+ if (sprite->mode == old && type == IMAGE_PLOT_TINCT_ALPHA) {
+ sprite->mode = new;
+ }
+}
+
+/**
+ * Plot an image at the given coordinates using the method specified
+ *
+ * \param area The sprite area containing the sprite
+ * \param x Left edge of sprite
+ * \param y Top edge of sprite
+ * \param req_width The requested width of the sprite
+ * \param req_height The requested height of the sprite
+ * \param width The actual width of the sprite
+ * \param height The actual height of the sprite
+ * \param background_colour The background colour to blend to
+ * \param repeatx Repeat the image in the x direction
+ * \param repeaty Repeat the image in the y direction
+ * \param background Use background image settings (otherwise foreground)
+ * \param type The plot method to use
+ * \return true on success, false otherwise
+ */
+bool image_redraw(osspriteop_area *area, int x, int y, int req_width,
+ int req_height, int width, int height,
+ colour background_colour,
+ bool repeatx, bool repeaty, bool background, image_type type)
+{
+ image_type used_type = type;
+ unsigned int tinct_options;
+ bool tinct_avoid = false;
+ bool res = false;
+
+ /* failed decompression/loading can result in no image being present */
+ if (!area)
+ return false;
+
+ osspriteop_id header = (osspriteop_id)
+ ((char*) area + area->first);
+
+ req_width *= 2;
+ req_height *= 2;
+ width *= 2;
+ height *= 2;
+ y -= req_height;
+
+ tinct_options = background ? nsoption_int(plot_bg_quality) :
+ nsoption_int(plot_fg_quality);
+
+ if (os_alpha_sprite_supported) {
+ /* Ideally Tinct would be updated to understand that modern OS
+ * versions can cope with alpha channels, and we could continue
+ * to pass to Tinct. The main drawback of fully avoiding Tinct
+ * is that we lose the optimisation for tiling tiny bitmaps.
+ */
+ if (tinct_options & tinct_USE_OS_SPRITE_OP) {
+ used_type = IMAGE_PLOT_OS;
+ tinct_avoid = true;
+ }
+ }
+
+ if (tinct_avoid) {
+ int xeig;
+ int yeig;
+
+ if (ro_gui_wimp_read_eig_factors(os_CURRENT_MODE,
+ &xeig, &yeig)) {
+
+ req_width = (req_width / 2) * (4 >> xeig);
+ req_height = (req_height / 2) * (4 >> yeig);
+ }
+ }
+
+ switch (used_type) {
+ case IMAGE_PLOT_TINCT_ALPHA:
+ res = image_redraw_tinct(header, x, y,
+ req_width, req_height,
+ width, height,
+ background_colour,
+ repeatx, repeaty, true,
+ tinct_options);
+ break;
+
+ case IMAGE_PLOT_TINCT_OPAQUE:
+ res = image_redraw_tinct(header, x, y,
+ req_width, req_height,
+ width, height,
+ background_colour,
+ repeatx, repeaty, false,
+ tinct_options);
+ break;
+
+ case IMAGE_PLOT_OS:
+ if (tinct_avoid) {
+ image__override_sprite_mode(area, type,
+ tinct_SPRITE_MODE,
+ alpha_SPRITE_MODE);
+ }
+ res = image_redraw_os(header, x, y, req_width,
+ req_height, width, height,
+ repeatx | repeaty);
+ if (tinct_avoid) {
+ image__override_sprite_mode(area, type,
+ alpha_SPRITE_MODE,
+ tinct_SPRITE_MODE);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return res;
+}
diff --git a/frontends/riscos/local_history.c b/frontends/riscos/local_history.c
index bbe6a1d12..03f1d8657 100644
--- a/frontends/riscos/local_history.c
+++ b/frontends/riscos/local_history.c
@@ -289,6 +289,7 @@ static nserror
ro_local_history_init(struct browser_window *bw,
struct ro_local_history_window **win_out)
{
+ os_error *error;
struct ro_local_history_window *ncwin;
nserror res;
@@ -306,7 +307,15 @@ ro_local_history_init(struct browser_window *bw,
}
/* create window from template */
- ncwin->core.wh = wimp_create_window(dialog_local_history_template);
+ error = xwimp_create_window(dialog_local_history_template,
+ &ncwin->core.wh);
+ if (error) {
+ NSLOG(netsurf, INFO, "xwimp_create_window: 0x%x: %s",
+ error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ free(ncwin);
+ return NSERROR_NOMEM;
+ }
/* initialise callbacks */
ncwin->core.draw = ro_local_history_draw;
@@ -394,6 +403,17 @@ ro_local_history_open(struct ro_local_history_window *lhw, wimp_w parent)
ro_gui_dialog_open_persistent(parent, lhw->core.wh, true);
+ /* Give the window focus. */
+ error = xwimp_set_caret_position(lhw->core.wh, -1, 0, 0, -1, 0);
+ if (error) {
+ NSLOG(netsurf, INFO,
+ "xwimp_set_caret_position: 0x%x : %s",
+ error->errnum,
+ error->errmess);
+ }
+
+ local_history_scroll_to_cursor(lhw->session);
+
return NSERROR_OK;
}
diff --git a/frontends/riscos/options.h b/frontends/riscos/options.h
index cb2b78bd8..bf85f07c2 100644
--- a/frontends/riscos/options.h
+++ b/frontends/riscos/options.h
@@ -16,12 +16,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * RISC OS specific options.
+/**
+ * \file
+ * Option specific to RISC OS
+ *
+ * Platform specific options for RISC OS can be added by editing this file
+ *
+ * Global optionsshould be added in the desktop options.h.
+ *
+ * This header is specificaly intented to be included multiple times
+ * with different macro definitions so there is no guard
*/
-#ifndef _NETSURF_RISCOS_OPTIONS_H_
-#define _NETSURF_RISCOS_OPTIONS_H_
+#ifndef NETSURF_RISCOS_OPTIONS_H_
+#define NETSURF_RISCOS_OPTIONS_H_
#include "riscos/tinct.h"
@@ -66,3 +74,13 @@ NSOPTION_BOOL(thumbnail_iconise, true)
NSOPTION_BOOL(interactive_help, true)
NSOPTION_BOOL(external_hotlists, false)
NSOPTION_STRING(external_hotlist_app, NULL)
+
+/**
+ * width of screen when window_width option was saved
+ */
+NSOPTION_INTEGER(window_screen_width, 0)
+
+/**
+ * height of screen when window_heigh option was saved
+ */
+NSOPTION_INTEGER(window_screen_height, 0)
diff --git a/frontends/riscos/pageinfo.c b/frontends/riscos/pageinfo.c
new file mode 100644
index 000000000..7ce09591b
--- /dev/null
+++ b/frontends/riscos/pageinfo.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of RISC OS page info core window.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <oslib/wimp.h>
+
+#include "utils/log.h"
+#include "netsurf/mouse.h"
+#include "netsurf/plotters.h"
+#include "desktop/page-info.h"
+
+#include "riscos/gui.h"
+#include "riscos/dialog.h"
+#include "riscos/toolbar.h"
+#include "riscos/wimputils.h"
+#include "riscos/corewindow.h"
+#include "riscos/pageinfo.h"
+
+
+/**
+ * Page info window container for RISC OS.
+ */
+struct ro_pageinfo_window {
+ struct ro_corewindow core;
+ /** Core page-info window */
+ struct page_info *pgi;
+};
+
+/** page info window is a singleton */
+static struct ro_pageinfo_window *pageinfo_window = NULL;
+
+/** riscos template for pageinfo window */
+static wimp_window *dialog_pageinfo_template;
+
+/**
+ * callback to draw on drawable area of ro page info window
+ *
+ * \param ro_cw The riscos core window structure.
+ * \param r The rectangle of the window that needs updating.
+ * \param originx The risc os plotter x origin.
+ * \param originy The risc os plotter y origin.
+ * \return NSERROR_OK on success otherwise apropriate error code
+ */
+static nserror
+ro_pageinfo_draw(struct ro_corewindow *ro_cw,
+ int originx,
+ int originy,
+ struct rect *r)
+{
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &ro_plotters
+ };
+ struct ro_pageinfo_window *lhw;
+
+ lhw = (struct ro_pageinfo_window *)ro_cw;
+
+ ro_plot_origin_x = originx;
+ ro_plot_origin_y = originy;
+ no_font_blending = true;
+ page_info_redraw(lhw->pgi, 0, 0, r, &ctx);
+ no_font_blending = false;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * callback for keypress on ro coookie window
+ *
+ * \param ro_cw The ro core window structure.
+ * \param nskey The netsurf key code.
+ * \return NSERROR_OK if key processed,
+ * NSERROR_NOT_IMPLEMENTED if key not processed
+ * otherwise apropriate error code
+ */
+static nserror
+ro_pageinfo_key(struct ro_corewindow *ro_cw, uint32_t nskey)
+{
+ struct ro_pageinfo_window *lhw;
+
+ lhw = (struct ro_pageinfo_window *)ro_cw;
+
+ if (page_info_keypress(lhw->pgi, nskey)) {
+ return NSERROR_OK;
+ }
+ return NSERROR_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * callback for mouse event on ro page info window
+ *
+ * \param ro_cw The ro core window structure.
+ * \param mouse_state mouse state
+ * \param x location of event
+ * \param y location of event
+ * \return NSERROR_OK on sucess otherwise apropriate error code.
+ */
+static nserror
+ro_pageinfo_mouse(struct ro_corewindow *ro_cw,
+ browser_mouse_state mouse_state,
+ int x, int y)
+{
+ struct ro_pageinfo_window *pgiw;
+
+ pgiw = (struct ro_pageinfo_window *)ro_cw;
+ bool did_something = false;
+
+ if (page_info_mouse_action(pgiw->pgi, mouse_state, x, y, &did_something) == NSERROR_OK) {
+ if (did_something == true) {
+ /* Something happened so we need to close ourselves */
+ ro_gui_dialog_close(ro_cw->wh);
+ }
+ }
+
+ if ((mouse_state & BROWSER_MOUSE_LEAVE) != 0) {
+ ro_gui_dialog_close(ro_cw->wh);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Creates the window for the page info tree.
+ *
+ * \return NSERROR_OK on success else appropriate error code on faliure.
+ */
+static nserror
+ro_pageinfo_init(struct browser_window *bw,
+ struct ro_pageinfo_window **win_out)
+{
+ os_error *error;
+ struct ro_pageinfo_window *ncwin;
+ nserror res;
+
+ /* memoise window so it can be represented when necessary
+ * instead of recreating every time.
+ */
+ if ((*win_out) != NULL) {
+ res = page_info_set((*win_out)->pgi, bw);
+ return res;
+ }
+
+ ncwin = calloc(1, sizeof(*ncwin));
+ if (ncwin == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ /* create window from template */
+ error = xwimp_create_window(dialog_pageinfo_template,
+ &ncwin->core.wh);
+ if (error) {
+ NSLOG(netsurf, INFO, "xwimp_create_window: 0x%x: %s",
+ error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ free(ncwin);
+ return NSERROR_NOMEM;
+ }
+
+ /* initialise callbacks */
+ ncwin->core.draw = ro_pageinfo_draw;
+ ncwin->core.key = ro_pageinfo_key;
+ ncwin->core.mouse = ro_pageinfo_mouse;
+
+ /* initialise core window */
+ res = ro_corewindow_init(&ncwin->core,
+ NULL,
+ NULL,
+ 0,
+ NULL);
+ if (res != NSERROR_OK) {
+ free(ncwin);
+ return res;
+ }
+
+ res = page_info_create(ncwin->core.cb_table,
+ (struct core_window *)ncwin,
+ bw,
+ &ncwin->pgi);
+ if (res != NSERROR_OK) {
+ free(ncwin);
+ return res;
+ }
+
+ *win_out = ncwin;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * open RISC OS page info window at the correct size
+ */
+static nserror
+ro_pageinfo_open(struct ro_pageinfo_window *lhw, wimp_w parent)
+{
+ nserror res;
+ int width, height;
+ os_box box = {0, 0, 0, 0};
+ wimp_window_state state;
+ os_error *error;
+
+ res = page_info_get_size(lhw->pgi, &width, &height);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ width *= 2;
+ height *= 2;
+
+ /* set extent */
+ box.x1 = width;
+ box.y0 = -height;
+ error = xwimp_set_extent(lhw->core.wh, &box);
+ if (error) {
+ NSLOG(netsurf, INFO, "xwimp_set_extent: 0x%x: %s",
+ error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return NSERROR_NOMEM;
+ }
+
+ /* open full size */
+ state.w = lhw->core.wh;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ NSLOG(netsurf, INFO, "xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return NSERROR_NOMEM;
+ }
+ state.visible.x0 = 0;
+ state.visible.y0 = 0;
+ state.visible.x1 = width;
+ state.visible.y1 = height;
+ state.next = wimp_HIDDEN;
+ error = xwimp_open_window(PTR_WIMP_OPEN(&state));
+ if (error) {
+ NSLOG(netsurf, INFO, "xwimp_open_window: 0x%x: %s",
+ error->errnum, error->errmess);
+ ro_warn_user("WimpError", error->errmess);
+ return NSERROR_NOMEM;
+ }
+
+ ro_gui_dialog_open_persistent(parent, lhw->core.wh, true);
+
+ /* Give the window focus. */
+ error = xwimp_set_caret_position(lhw->core.wh, -1, 0, 0, -1, 0);
+ if (error) {
+ NSLOG(netsurf, INFO,
+ "xwimp_set_caret_position: 0x%x : %s",
+ error->errnum,
+ error->errmess);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in riscos/pageinfo.h */
+nserror ro_gui_pageinfo_initialise(void)
+{
+ dialog_pageinfo_template = ro_gui_dialog_load_template("corepginfo");
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in riscos/pageinfo.h */
+nserror ro_gui_pageinfo_present(struct gui_window *gw)
+{
+ nserror res;
+
+ res = ro_pageinfo_init(gw->bw, &pageinfo_window);
+ if (res == NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Presenting");
+ res = ro_pageinfo_open(pageinfo_window, gw->window);
+ } else {
+ NSLOG(netsurf, INFO, "Failed presenting error code %d", res);
+ }
+
+ return res;
+}
+
+/* exported interface documented in riscos/pageinfo.h */
+nserror ro_gui_pageinfo_finalise(void)
+{
+ nserror res;
+
+ if (pageinfo_window == NULL) {
+ return NSERROR_OK;
+ }
+
+ res = page_info_destroy(pageinfo_window->pgi);
+ if (res == NSERROR_OK) {
+ res = ro_corewindow_fini(&pageinfo_window->core);
+
+ free(pageinfo_window);
+ pageinfo_window = NULL;
+ }
+
+ return res;
+}
diff --git a/frontends/riscos/pageinfo.h b/frontends/riscos/pageinfo.h
new file mode 100644
index 000000000..e5581c27e
--- /dev/null
+++ b/frontends/riscos/pageinfo.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@nesurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Interface to page info core window for RISC OS
+ */
+
+#ifndef NETSURF_RISCOS_PAGEINFO_H_
+#define NETSURF_RISCOS_PAGEINFO_H_
+
+struct gui_window;
+
+/**
+ * initialise the pageinfo window template ready for subsequent use.
+ */
+nserror ro_gui_pageinfo_initialise(void);
+
+/**
+ * make the pageinfo window visible.
+ *
+ * \return NSERROR_OK on success else appropriate error code on faliure.
+ */
+nserror ro_gui_pageinfo_present(struct gui_window *gw);
+
+/**
+ * Free any resources allocated for the page info window.
+ *
+ * \return NSERROR_OK on success else appropriate error code on faliure.
+ */
+nserror ro_gui_pageinfo_finalise(void);
+
+#endif
diff --git a/frontends/riscos/plotters.c b/frontends/riscos/plotters.c
index 2fbd12aeb..e38e746cd 100644
--- a/frontends/riscos/plotters.c
+++ b/frontends/riscos/plotters.c
@@ -39,6 +39,7 @@
int ro_plot_origin_x = 0;
int ro_plot_origin_y = 0;
+struct rect ro_plot_clip_rect;
/** One version of the A9home OS is incapable of drawing patterned lines */
bool ro_plot_patterned_lines = true;
@@ -110,12 +111,25 @@ ro_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
os_error *error;
char buf[12];
- int clip_x0 = ro_plot_origin_x + clip->x0 * 2;
- int clip_y0 = ro_plot_origin_y - clip->y0 * 2 - 1;
- int clip_x1 = ro_plot_origin_x + clip->x1 * 2 - 1;
- int clip_y1 = ro_plot_origin_y - clip->y1 * 2;
-
- if (clip_x1 < clip_x0 || clip_y0 < clip_y1) {
+ int clip_x0 = clip->x0 * 2;
+ int clip_y0 = clip->y1 * 2;
+ int clip_x1 = clip->x1 * 2;
+ int clip_y1 = clip->y0 * 2;
+
+ /* Avoid artefacts due to clip rectangle offsetting in EX0 EY0 modes.
+ * The area the WIMP asked us to draw might have dimensions that are
+ * not a multiple of 2. */
+ if (clip_x0 < ro_plot_clip_rect.x0) clip_x0 = ro_plot_clip_rect.x0;
+ if (clip_x1 > ro_plot_clip_rect.x1) clip_x1 = ro_plot_clip_rect.x1;
+ if (clip_y0 > ro_plot_clip_rect.y0) clip_y0 = ro_plot_clip_rect.y0;
+ if (clip_y1 < ro_plot_clip_rect.y1) clip_y1 = ro_plot_clip_rect.y1;
+
+ clip_x0 = ro_plot_origin_x + clip_x0;
+ clip_y0 = ro_plot_origin_y - clip_y0;
+ clip_x1 = ro_plot_origin_x + clip_x1 - 1;
+ clip_y1 = ro_plot_origin_y - clip_y1 - 1;
+
+ if (clip_x1 < clip_x0 || clip_y1 < clip_y0) {
NSLOG(netsurf, INFO, "bad clip rectangle %i %i %i %i",
clip_x0, clip_y0, clip_x1, clip_y1);
return NSERROR_BAD_SIZE;
@@ -124,12 +138,12 @@ ro_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
buf[0] = os_VDU_SET_GRAPHICS_WINDOW;
buf[1] = clip_x0;
buf[2] = clip_x0 >> 8;
- buf[3] = clip_y1;
- buf[4] = clip_y1 >> 8;
+ buf[3] = clip_y0;
+ buf[4] = clip_y0 >> 8;
buf[5] = clip_x1;
buf[6] = clip_x1 >> 8;
- buf[7] = clip_y0;
- buf[8] = clip_y0 >> 8;
+ buf[7] = clip_y1;
+ buf[8] = clip_y1 >> 8;
error = xos_writen(buf, 9);
if (error) {
@@ -324,9 +338,9 @@ ro_plot_line(const struct redraw_context *ctx,
dashed = true;
return ro_plot_draw_path((const draw_path *)path,
- style->stroke_width,
- style->stroke_colour,
- dotted, dashed);
+ plot_style_fixed_to_int(style->stroke_width),
+ style->stroke_colour,
+ dotted, dashed);
}
return NSERROR_OK;
}
@@ -365,7 +379,7 @@ ro_plot_rectangle(const struct redraw_context *ctx,
error = xos_plot(os_MOVE_TO,
ro_plot_origin_x + rect->x0 * 2,
- ro_plot_origin_y - rect->y0 * 2 - 1);
+ ro_plot_origin_y - rect->y1 * 2);
if (error) {
NSLOG(netsurf, INFO, "xos_plot: 0x%x: %s",
error->errnum, error->errmess);
@@ -374,7 +388,7 @@ ro_plot_rectangle(const struct redraw_context *ctx,
error = xos_plot(os_PLOT_RECTANGLE | os_PLOT_TO,
ro_plot_origin_x + rect->x1 * 2 - 1,
- ro_plot_origin_y - rect->y1 * 2);
+ ro_plot_origin_y - rect->y0 * 2 - 1);
if (error) {
NSLOG(netsurf, INFO, "xos_plot: 0x%x: %s",
error->errnum, error->errmess);
@@ -412,10 +426,10 @@ ro_plot_rectangle(const struct redraw_context *ctx,
dashed = true;
ro_plot_draw_path((const draw_path *)path,
- style->stroke_width,
- style->stroke_colour,
- dotted,
- dashed);
+ plot_style_fixed_to_int(style->stroke_width),
+ style->stroke_colour,
+ dotted,
+ dashed);
}
return NSERROR_OK;
@@ -483,7 +497,6 @@ ro_plot_polygon(const struct redraw_context *ctx,
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
- * \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
@@ -492,7 +505,6 @@ ro_plot_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
- float width,
const float transform[6])
{
static const draw_line_style line_style = {
@@ -591,7 +603,9 @@ ro_plot_path(const struct redraw_context *ctx,
}
error = xdraw_stroke((draw_path *) path, 0, &trfm, 0,
- width * 2 * 256, &line_style, 0);
+ plot_style_fixed_to_int(
+ pstyle->stroke_width) * 2 * 256,
+ &line_style, 0);
if (error) {
NSLOG(netsurf, INFO, "xdraw_stroke: 0x%x: %s",
error->errnum, error->errmess);
diff --git a/frontends/riscos/print.c b/frontends/riscos/print.c
index d965baff4..e87f47857 100644
--- a/frontends/riscos/print.c
+++ b/frontends/riscos/print.c
@@ -106,7 +106,7 @@ static bool print_document(struct gui_window *g, const char *filename);
static const char *print_declare_fonts(struct hlcache_handle *h);
static void print_fonts_callback(void *context,
const char *font_name, unsigned int font_size,
- const char *s8, unsigned short *s16, unsigned int n,
+ const uint8_t *s8, const uint32_t *s32, unsigned int n,
int x, int y);
@@ -831,7 +831,6 @@ print_fonts_plot_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
- float width,
const float transform[6])
{
return NSERROR_OK;
@@ -999,7 +998,7 @@ end:
void print_fonts_callback(void *context,
const char *font_name, unsigned int font_size,
- const char *s8, unsigned short *s16, unsigned int n,
+ const uint8_t *s8, const uint32_t *s32, unsigned int n,
int x, int y)
{
unsigned int i;
@@ -1010,7 +1009,7 @@ void print_fonts_callback(void *context,
(void) x; /* unused */
(void) y; /* unused */
- assert(s8 || s16);
+ assert(s8 || s32);
/* check if the font name is new */
for (i = 0; i != print_fonts_count &&
diff --git a/frontends/riscos/save.c b/frontends/riscos/save.c
index 76ce6d3e5..b435787b0 100644
--- a/frontends/riscos/save.c
+++ b/frontends/riscos/save.c
@@ -40,8 +40,10 @@
#include "utils/config.h"
#include "utils/log.h"
#include "utils/messages.h"
-#include "utils/utf8.h"
+#include "utils/nsoption.h"
#include "utils/nsurl.h"
+#include "utils/utf8.h"
+#include "utils/utils.h"
#include "netsurf/browser_window.h"
#include "netsurf/window.h"
#include "netsurf/bitmap.h"
@@ -60,7 +62,6 @@
#include "riscos/menus.h"
#include "riscos/message.h"
#include "riscos/mouse.h"
-#include "utils/nsoption.h"
#include "riscos/query.h"
#include "riscos/save.h"
#include "riscos/save_draw.h"
@@ -243,7 +244,7 @@ ro_gui_save_create_thumbnail(struct hlcache_handle *h, const char *name)
struct bitmap *bitmap;
osspriteop_area *area;
- bitmap = riscos_bitmap_create(34, 34, BITMAP_NEW | BITMAP_OPAQUE | BITMAP_CLEAR_MEMORY);
+ bitmap = riscos_bitmap_create(34, 34, BITMAP_OPAQUE | BITMAP_CLEAR);
if (!bitmap) {
NSLOG(netsurf, INFO, "Thumbnail initialisation failed.");
return false;
@@ -257,7 +258,8 @@ ro_gui_save_create_thumbnail(struct hlcache_handle *h, const char *name)
}
sprite_header = (osspriteop_header *)(area + 1);
- strncpy(sprite_header->name, name, 12);
+ memset(sprite_header->name, 0, 12);
+ memcpy(sprite_header->name, name, min(strlen(name), 12));
/* we can't resize the saveas sprite area because it may move
@@ -908,8 +910,8 @@ static bool ro_gui_save_object_native(struct hlcache_handle *h, char *path)
if (file_type == osfile_TYPE_SPRITE || file_type == osfile_TYPE_DRAW) {
/* Native sprite or drawfile */
- const char *source_data;
- unsigned long source_size;
+ const uint8_t *source_data;
+ size_t source_size;
os_error *error;
source_data = content_get_source_data(h, &source_size);
@@ -960,8 +962,8 @@ static bool
ro_gui_save_content(struct hlcache_handle *h, char *path, bool force_overwrite)
{
os_error *error;
- const char *source_data;
- unsigned long source_size;
+ const uint8_t *source_data;
+ size_t source_size;
/* does the user want to check for collisions when saving? */
if (!force_overwrite) {
@@ -1018,7 +1020,7 @@ ro_gui_save_content(struct hlcache_handle *h, char *path, bool force_overwrite)
}
else
gui_save_current_type = GUI_SAVE_OBJECT_ORIG; /** \todo do this earlier? */
- /* no break */
+ fallthrough;
case GUI_SAVE_SOURCE:
case GUI_SAVE_OBJECT_ORIG:
source_data = content_get_source_data(h, &source_size);
diff --git a/frontends/riscos/save_draw.c b/frontends/riscos/save_draw.c
index 9ee730434..1e67d2d8d 100644
--- a/frontends/riscos/save_draw.c
+++ b/frontends/riscos/save_draw.c
@@ -168,7 +168,7 @@ ro_save_draw_line(const struct redraw_context *ctx,
sizeof path / sizeof path[0],
pencil_TRANSPARENT,
style->stroke_colour << 8,
- style->stroke_width,
+ plot_style_fixed_to_int(style->stroke_width),
pencil_JOIN_MITRED,
pencil_CAP_BUTT,
pencil_CAP_BUTT,
@@ -235,7 +235,7 @@ ro_save_draw_rectangle(const struct redraw_context *ctx,
sizeof path / sizeof path[0],
pencil_TRANSPARENT,
style->stroke_colour << 8,
- style->stroke_width,
+ plot_style_fixed_to_int(style->stroke_width),
pencil_JOIN_MITRED,
pencil_CAP_BUTT,
pencil_CAP_BUTT,
@@ -312,7 +312,6 @@ ro_save_draw_polygon(const struct redraw_context *ctx,
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
- * \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
@@ -321,7 +320,6 @@ ro_save_draw_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
- float width,
const float transform[6])
{
pencil_code code;
@@ -409,7 +407,8 @@ ro_save_draw_path(const struct redraw_context *ctx,
pstyle->stroke_colour == NS_TRANSPARENT ?
pencil_TRANSPARENT :
pstyle->stroke_colour << 8,
- width, pencil_JOIN_MITRED,
+ plot_style_fixed_to_int(pstyle->stroke_width),
+ pencil_JOIN_MITRED,
pencil_CAP_BUTT,
pencil_CAP_BUTT,
0,
diff --git a/frontends/riscos/scripts/Run b/frontends/riscos/scripts/Run
index 4a51d7838..3368140d2 100644
--- a/frontends/riscos/scripts/Run
+++ b/frontends/riscos/scripts/Run
@@ -33,16 +33,19 @@ SetMacro NetSurf$ChoicesSave <Choices$Write>.WWW.NetSurf.Choices
RMEnsure UtilityModule 3.00 Error NetSurf needs RISC OS 3 or later
| Ensure Nested WIMP is installed
-| http://acorn.riscos.com/ (in the universal boot archive)
-RMEnsure WindowManager 3.80 Error NetSurf requires the Nested Window Manager. This can be obtained by downloading the Universal Boot sequence from http://acorn.riscos.com/
+| http://www.riscos.com/ftp_space/generic/uniboot/ (i.e. install universal boot)
+RMEnsure WindowManager 3.80 Error NetSurf requires the Nested Window Manager. This can be obtained by downloading the Universal Boot sequence from http://www.riscos.com/ftp_space/generic/uniboot/
| Check for various key resources - can't do much if they don't exist
If "<System$Path>" = "" Then Set System$Path_Message System resources not found.
If "<Wimp$ScrapDir>" = "" Then Error Scrap resource not found.
If "<InetDBase$Path>" = "" Then Error Internet resources can not be found
-If "<Unicode$Path>" = "" Then Error NetSurf requires the !Unicode resource. This can be found, along with the Iconv module, at http://www.netsurf-browser.org/projects/iconv/
+If "<Unicode$Path>" = "" Then Error NetSurf requires the !Unicode resource. This can be found, along with the Iconv module, at https://www.netsurf-browser.org/projects/iconv/
If "<Inet$MimeMappings>" = "" Then Set Inet$MimeMappings InetDBase:MimeMap
+| Use OS copy of root CA bundle, if present
+IfThere InetDBase:CertData Then Set NetSurf$CABundle InetDBase:CertData Else Set NetSurf$CABundle NetSurf:Resources.ca-bundle
+
| Define this alias for clarity
| Syntax: NetSurfRMLoad <Path to module>
Set Alias$NetSurfRMLoad IfThere %%*0 Then RMLoad %%*0
@@ -65,6 +68,10 @@ RMEnsure DrawFile 1.30 Error NetSurf requires the DrawFile module. This can be d
RMEnsure SharedUnixLibrary 1.07 NetSurfRMLoad System:Modules.SharedULib
RMEnsure SharedUnixLibrary 1.07 Error NetSurf requires SharedUnixLibrary 1.07 or later. Please use the RISC OS Configure app to update the computer's !System directory from the NetSurf archive.
+| Ensure ARMEABISupport is installed
+|RMEnsure ARMEABISupport 1.04 NetSurfRMLoad System:Modules.ARMEABISupport
+|RMEnsure ARMEABISupport 1.04 Error NetSurf requires ARMEABISupport 1.04 or later. Please use the RISC OS Configure app to update the computer's !System directory from the NetSurf archive.
+
| Load AcornURI if it isn't already
Unset NetSurf$Start_URI_Handler
RMEnsure AcornURI 0.12 Set NetSurf$Start_URI_Handler 1
diff --git a/frontends/riscos/sslcert.c b/frontends/riscos/sslcert.c
deleted file mode 100644
index 4d81268f4..000000000
--- a/frontends/riscos/sslcert.c
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * Copyright 2006 John M Bell <jmb202@ecs.soton.ac.uk>
- * Copyright 2016 Vincent Sanders <vince@netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- * Implementation of RISC OS certificate verification UI.
- */
-
-#include <oslib/wimp.h>
-
-#include "utils/log.h"
-#include "netsurf/plotters.h"
-#include "desktop/sslcert_viewer.h"
-
-#include "riscos/dialog.h"
-#include "riscos/wimp.h"
-#include "riscos/wimp_event.h"
-#include "riscos/wimputils.h"
-#include "riscos/gui.h"
-#include "riscos/toolbar.h"
-#include "riscos/corewindow.h"
-#include "riscos/sslcert.h"
-
-/* widget ID */
-#define ICON_SSL_PANE 1
-#define ICON_SSL_REJECT 3
-#define ICON_SSL_ACCEPT 4
-
-/**
- * RISC OS certificate viewer context.
- */
-struct ro_cert_window {
- struct ro_corewindow core;
-
- /** certificate view window handle */
- wimp_w wh;
-
- /** SSL certificate viewer context data */
- struct sslcert_session_data *ssl_data;
-
-};
-
-/** riscos dialog template for certificate viewer window. */
-static wimp_window *dialog_cert_template;
-
-/** riscos template for certificate tree pane. */
-static wimp_window *cert_tree_template;
-
-
-/**
- * Handle closing of the RISC OS certificate verification dialog
- *
- * Deleting wimp windows, freeing up the core window and ssl data block.
- *
- * \param certw The context associated with the dialogue.
- */
-static void ro_gui_cert_release_window(struct ro_cert_window *certw)
-{
- os_error *error;
-
- ro_gui_wimp_event_finalise(certw->wh);
-
- sslcert_viewer_fini(certw->ssl_data);
-
- ro_corewindow_fini(&certw->core);
-
- error = xwimp_delete_window(certw->wh);
- if (error) {
- NSLOG(netsurf, INFO, "xwimp_delete_window: 0x%x:%s",
- error->errnum, error->errmess);
- }
-
- error = xwimp_delete_window(certw->core.wh);
- if (error) {
- NSLOG(netsurf, INFO, "xwimp_delete_window: 0x%x:%s",
- error->errnum, error->errmess);
- }
-
- free(certw);
-}
-
-/**
- * Handle acceptance of certificate via event callback.
- *
- * \param pointer The wimp pointer event.
- */
-static void ro_gui_cert_accept(wimp_pointer *pointer)
-{
- struct ro_cert_window *certw;
- certw = (struct ro_cert_window *)ro_gui_wimp_event_get_user_data(pointer->w);
-
- sslcert_viewer_accept(certw->ssl_data);
- ro_gui_dialog_close(certw->wh);
- ro_gui_cert_release_window(certw);
-}
-
-
-/**
- * Handle rejection of certificate via event callback.
- *
- * \param pointer The wimp pointer block.
- */
-static void ro_gui_cert_reject(wimp_pointer *pointer)
-{
- struct ro_cert_window *certw;
- certw = (struct ro_cert_window *)ro_gui_wimp_event_get_user_data(pointer->w);
-
- sslcert_viewer_reject(certw->ssl_data);
- ro_gui_dialog_close(certw->wh);
- ro_gui_cert_release_window(certw);
-}
-
-
-/**
- * Callback to handle the closure of the SSL dialogue by other means.
- *
- * \param w The window handle being closed.
- */
-static void ro_gui_cert_close_window(wimp_w w)
-{
- struct ro_cert_window *certw;
- certw = (struct ro_cert_window *)ro_gui_wimp_event_get_user_data(w);
-
- ro_gui_cert_release_window(certw);
-}
-
-
-/**
- * Attach tree window as a pane to ssl window.
- *
- * Nest the tree window inside the pane window. To do this, we:
- * - Get the current pane extent,
- * - Get the parent window position and the location of the pane-
- * locating icon inside it,
- * - Set the visible area of the pane to suit,
- * - Check that the pane extents are OK for this visible area, and
- * increase them if necessary,
- * - Before finally opening the pane as a nested part of the parent.
- *
- */
-static nserror cert_attach_pane(wimp_w parent, wimp_w pane)
-{
- os_error *error;
- wimp_window_state wstate;
- wimp_window_info winfo;
- wimp_icon_state istate;
- bool set_extent;
-
- winfo.w = pane;
- error = xwimp_get_window_info_header_only(&winfo);
- if (error) {
- NSLOG(netsurf, INFO, "xwimp_get_window_info: 0x%x: %s",
- error->errnum, error->errmess);
- return NSERROR_INIT_FAILED;
- }
-
- wstate.w = parent;
- error = xwimp_get_window_state(&wstate);
- if (error) {
- NSLOG(netsurf, INFO, "xwimp_get_window_state: 0x%x: %s",
- error->errnum, error->errmess);
- return NSERROR_INIT_FAILED;
- }
-
- istate.w = parent;
- istate.i = ICON_SSL_PANE;
- error = xwimp_get_icon_state(&istate);
- if (error) {
- NSLOG(netsurf, INFO, "xwimp_get_icon_state: 0x%x: %s",
- error->errnum, error->errmess);
- return NSERROR_INIT_FAILED;
- }
-
- wstate.w = pane;
- wstate.visible.x1 = wstate.visible.x0 + istate.icon.extent.x1 - 20 - ro_get_vscroll_width(pane);
- wstate.visible.x0 += istate.icon.extent.x0 + 20;
- wstate.visible.y0 = wstate.visible.y1 + istate.icon.extent.y0 + 20 + ro_get_hscroll_height(pane);
- wstate.visible.y1 += istate.icon.extent.y1 - 32;
-
- set_extent = false;
-
- if ((winfo.extent.x1 - winfo.extent.x0) <
- (wstate.visible.x1 - wstate.visible.x0)) {
- winfo.extent.x0 = 0;
- winfo.extent.x1 = wstate.visible.x1 - wstate.visible.x0;
- set_extent = true;
- }
- if ((winfo.extent.y1 - winfo.extent.y0) <
- (wstate.visible.y1 - wstate.visible.y0)) {
- winfo.extent.y1 = 0;
- winfo.extent.x1 = wstate.visible.y0 - wstate.visible.y1;
- set_extent = true;
- }
-
- if (set_extent) {
- error = xwimp_set_extent(pane, &(winfo.extent));
- if (error) {
- NSLOG(netsurf, INFO, "xwimp_set_extent: 0x%x: %s",
- error->errnum, error->errmess);
- return NSERROR_INIT_FAILED;
- }
- }
-
- error = xwimp_open_window_nested(
- PTR_WIMP_OPEN(&wstate),
- parent,
- wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT << wimp_CHILD_XORIGIN_SHIFT |
- wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT << wimp_CHILD_YORIGIN_SHIFT |
- wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT << wimp_CHILD_LS_EDGE_SHIFT |
- wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT << wimp_CHILD_RS_EDGE_SHIFT);
- if (error) {
- NSLOG(netsurf, INFO, "xwimp_open_window_nested: 0x%x: %s",
- error->errnum, error->errmess);
- return NSERROR_INIT_FAILED;
- }
-
- return NSERROR_OK;
-}
-
-
-/**
- * Callback to draw on drawable area of ro certificate viewer window.
- *
- * \param ro_cw The riscos core window structure.
- * \param originx The risc os plotter x origin.
- * \param originy The risc os plotter y origin.
- * \param r The rectangle of the window that needs updating.
- * \return NSERROR_OK on success otherwise apropriate error code
- */
-static nserror
-cert_draw(struct ro_corewindow *ro_cw, int originx, int originy, struct rect *r)
-{
- struct ro_cert_window *certw;
- struct redraw_context ctx = {
- .interactive = true,
- .background_images = true,
- .plot = &ro_plotters
- };
-
- certw = (struct ro_cert_window *)ro_cw;
-
- ro_plot_origin_x = originx;
- ro_plot_origin_y = originy;
- no_font_blending = true;
- sslcert_viewer_redraw(certw->ssl_data, 0, 0, r, &ctx);
- no_font_blending = false;
-
- return NSERROR_OK;
-}
-
-
-/**
- * callback for keypress on ro certificate viewer window
- *
- * \param ro_cw The ro core window structure.
- * \param nskey The netsurf key code.
- * \return NSERROR_OK if key processed,
- * NSERROR_NOT_IMPLEMENTED if key not processed
- * otherwise apropriate error code
- */
-static nserror cert_key(struct ro_corewindow *ro_cw, uint32_t nskey)
-{
- struct ro_cert_window *certw;
- certw = (struct ro_cert_window *)ro_cw;
-
- if (sslcert_viewer_keypress(certw->ssl_data, nskey)) {
- return NSERROR_OK;
- }
- return NSERROR_NOT_IMPLEMENTED;
-}
-
-
-/**
- * callback for mouse event on ro certificate viewer window
- *
- * \param ro_cw The ro core window structure.
- * \param mouse_state mouse state
- * \param x location of event
- * \param y location of event
- * \return NSERROR_OK on sucess otherwise apropriate error code.
- */
-static nserror
-cert_mouse(struct ro_corewindow *ro_cw,
- browser_mouse_state mouse_state,
- int x, int y)
-{
- struct ro_cert_window *certw;
- certw = (struct ro_cert_window *)ro_cw;
-
- sslcert_viewer_mouse_action(certw->ssl_data, mouse_state, x, y);
-
- return NSERROR_OK;
-}
-
-/* exported interface documented in riscos/sslcert.h */
-nserror
-gui_cert_verify(nsurl *url,
- const struct ssl_cert_info *certs,
- unsigned long num,
- nserror (*cb)(bool proceed, void *pw),
- void *cbpw)
-{
- os_error *error;
- struct ro_cert_window *ncwin; /* new certificate window */
- nserror res;
-
- ncwin = malloc(sizeof(struct ro_cert_window));
- if (ncwin == NULL) {
- return NSERROR_NOMEM;
- }
-
- /* initialise certificate viewing interface */
- res = sslcert_viewer_create_session_data(num, url, cb, cbpw, certs,
- &ncwin->ssl_data);
- if (res != NSERROR_OK) {
- free(ncwin);
- return res;
- }
-
- /* Create the SSL window */
- error = xwimp_create_window(dialog_cert_template, &ncwin->wh);
- if (error) {
- NSLOG(netsurf, INFO, "xwimp_create_window: 0x%x: %s",
- error->errnum, error->errmess);
- free(ncwin);
- return NSERROR_INIT_FAILED;
- }
-
- /* create ssl viewer pane window */
- error = xwimp_create_window(cert_tree_template, &ncwin->core.wh);
- if (error) {
- NSLOG(netsurf, INFO, "xwimp_create_window: 0x%x: %s",
- error->errnum, error->errmess);
- free(ncwin);
- return NSERROR_INIT_FAILED;
- }
-
- /* setup callbacks */
- ncwin->core.draw = cert_draw;
- ncwin->core.key = cert_key;
- ncwin->core.mouse = cert_mouse;
-
- /* initialise core window */
- res = ro_corewindow_init(&ncwin->core, NULL, NULL, 0, NULL);
- if (res != NSERROR_OK) {
- free(ncwin);
- return res;
- }
-
- res = sslcert_viewer_init(ncwin->core.cb_table,
- (struct core_window *)ncwin,
- ncwin->ssl_data);
- if (res != NSERROR_OK) {
- free(ncwin);
- return res;
- }
-
- /* Set up the certificate window event handling.
- *
- * (The action buttons are registered as button events, not OK and
- * Cancel, as both need to carry out actions.)
- */
- ro_gui_wimp_event_set_user_data(ncwin->wh, ncwin);
- ro_gui_wimp_event_register_close_window(ncwin->wh,
- ro_gui_cert_close_window);
- ro_gui_wimp_event_register_button(ncwin->wh,
- ICON_SSL_REJECT,
- ro_gui_cert_reject);
- ro_gui_wimp_event_register_button(ncwin->wh,
- ICON_SSL_ACCEPT,
- ro_gui_cert_accept);
-
- ro_gui_dialog_open_persistent(NULL, ncwin->wh, false);
-
- res = cert_attach_pane(ncwin->wh, ncwin->core.wh);
- if (res != NSERROR_OK) {
- ro_gui_cert_release_window(ncwin);
- }
-
- return res;
-}
-
-
-/* exported interface documented in riscos/sslcert.h */
-void ro_gui_cert_initialise(void)
-{
- /* Load template for the SSL certificate window */
- dialog_cert_template = ro_gui_dialog_load_template("sslcert");
-
- /* load template for ssl treeview pane and adjust the window flags. */
- cert_tree_template = ro_gui_dialog_load_template("tree");
-
- cert_tree_template->flags &= ~(wimp_WINDOW_MOVEABLE |
- wimp_WINDOW_BACK_ICON |
- wimp_WINDOW_CLOSE_ICON |
- wimp_WINDOW_TITLE_ICON |
- wimp_WINDOW_SIZE_ICON |
- wimp_WINDOW_TOGGLE_ICON);
-}
diff --git a/frontends/riscos/sslcert.h b/frontends/riscos/sslcert.h
deleted file mode 100644
index 09607f04c..000000000
--- a/frontends/riscos/sslcert.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2006 Richard Wilson <info@tinct.net>
- * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- * RISC OS SSL certificate viewer interface.
- */
-
-#ifndef NETSURF_RISCOS_SSLCERT_H
-#define NETSURF_RISCOS_SSLCERT_H
-
-struct node;
-
-/**
- * Load and initialise the certificate window template.
- */
-void ro_gui_cert_initialise(void);
-
-/**
- * Prompt the user to verify a certificate with issuse.
- *
- * \param url The URL being verified.
- * \param certs The certificate to be verified
- * \param num The number of certificates to be verified.
- * \param cb Callback upon user decision.
- * \param cbpw Context pointer passed to cb
- */
-nserror gui_cert_verify(struct nsurl *url, const struct ssl_cert_info *certs, unsigned long num, nserror (*cb)(bool proceed, void *pw), void *cbpw);
-
-#endif
-
diff --git a/frontends/riscos/templates/de b/frontends/riscos/templates/de
index a4ec1f4ad..b5710d467 100644
--- a/frontends/riscos/templates/de
+++ b/frontends/riscos/templates/de
@@ -858,56 +858,6 @@ wimp_window {
text_and_sprite.validation:""
}
wimp_icon {
- extent:20,-404,208,-360
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Speedlimit"
- text.size:12
- text.validation:""
- }
- wimp_icon {
- extent:212,-408,380,-356
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_WHITE
- text.text:"12.34"
- text.size:*
- text.validation:"Pptr_write;Kta"
- }
- wimp_icon {
- extent:396,-400,428,-368
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:""
- text_and_sprite.size:*
- text_and_sprite.validation:"r5;sdown,pdown"
- }
- wimp_icon {
- extent:428,-400,460,-368
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:""
- text_and_sprite.size:*
- text_and_sprite.validation:"r5;sup,pup"
- }
- wimp_icon {
- extent:468,-404,612,-360
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Sekunden"
- text.size:*
- text.validation:""
- }
- wimp_icon {
extent:212,-460,640,-416
icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
icon_esg:0
@@ -1195,7 +1145,7 @@ wimp_window {
icon_esg:0
icon_fg:wimp_COLOUR_BLACK
icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"http://netsurf.sourceforge.net/netsurf.zip"
+ text.text:"https://netsurf.sourceforge.net/netsurf.zip"
text.size:*
text.validation:"R2"
}
@@ -1291,6 +1241,32 @@ wimp_window {
}
wimp_window {
+ template_name:"corepginfo"
+ visible:252,388,1152,808
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_SCROLL_REPEAT | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_WHITE
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-880,1236,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Page Info"
+ text.size:*
+ text.validation:""
+}
+
+wimp_window {
template_name:"info"
visible:268,838,888,1086
xscroll:0
@@ -1397,124 +1373,6 @@ wimp_window {
}
wimp_window {
- template_name:"login"
- visible:710,422,1386,758
- xscroll:0
- yscroll:-8
- next:wimp_TOP
- window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
- title_fg:wimp_COLOUR_BLACK
- title_bg:wimp_COLOUR_LIGHT_GREY
- work_fg:wimp_COLOUR_BLACK
- work_bg:wimp_COLOUR_VERY_LIGHT_GREY
- scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
- scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
- highlight_bg:wimp_COLOUR_CREAM
- extra_flags:
- extent:0,-344,676,-8
- title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
- work_flags:
- sprite_area:&1
- xmin:676
- ymin:336
- text.text:"Authentifizierung"
- text.size:20
- text.validation:""
- wimp_icon {
- extent:532,-332,664,-264
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Login"
- text.size:8
- text.validation:"R6,3;Nok"
- }
- wimp_icon {
- extent:376,-324,508,-272
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Abbruch"
- text.size:*
- text.validation:"R5,3;Ncancel"
- }
- wimp_icon {
- extent:168,-68,668,-16
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"moo.yoo.com"
- text.size:255
- text.validation:"R2"
- }
- wimp_icon {
- extent:168,-128,668,-76
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"my sekr3t area"
- text.size:255
- text.validation:"R2"
- }
- wimp_icon {
- extent:168,-188,668,-136
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_WHITE
- text.text:""
- text.size:255
- text.validation:"Pptr_write;Kta;N401username"
- }
- wimp_icon {
- extent:168,-248,668,-196
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_WHITE
- text.text:""
- text.size:255
- text.validation:"Pptr_write;Kta;D*"
- }
- wimp_icon {
- extent:88,-64,164,-20
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Host"
- }
- wimp_icon {
- extent:16,-184,164,-140
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Username"
- }
- wimp_icon {
- extent:24,-244,164,-200
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Passwort"
- }
- wimp_icon {
- extent:68,-124,164,-80
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Realm"
- }
-}
-
-wimp_window {
template_name:"new_entry"
visible:1120,590,1720,810
xscroll:0
@@ -3449,254 +3307,6 @@ wimp_window {
}
wimp_window {
- template_name:"ssldisplay"
- visible:212,142,1172,682
- xscroll:0
- yscroll:0
- next:wimp_TOP
- window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
- title_fg:wimp_COLOUR_BLACK
- title_bg:wimp_COLOUR_LIGHT_GREY
- work_fg:wimp_COLOUR_BLACK
- work_bg:wimp_COLOUR_VERY_LIGHT_GREY
- scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
- scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
- highlight_bg:wimp_COLOUR_CREAM
- extra_flags:
- extent:0,-540,960,0
- title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
- work_flags:
- sprite_area:&1
- xmin:960
- ymin:76
- text.text:"SSL Zertifikat"
- text.size:16
- text.validation:""
- wimp_icon {
- extent:432,-168,928,-116
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2"
- }
- wimp_icon {
- extent:16,-520,944,-24
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R4"
- }
- wimp_icon {
- extent:24,-108,148,-64
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Version"
- }
- wimp_icon {
- extent:152,-108,264,-56
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2"
- }
- wimp_icon {
- extent:260,-104,432,-60
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"gültig von"
- }
- wimp_icon {
- extent:432,-108,928,-56
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2"
- }
- wimp_icon {
- extent:68,-168,148,-124
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Typ"
- }
- wimp_icon {
- extent:152,-168,264,-116
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2"
- }
- wimp_icon {
- extent:244,-164,432,-120
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"gültig bis"
- }
- wimp_icon {
- extent:32,-52,380,-8
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:" Certificate details "
- text_and_sprite.size:*
- text_and_sprite.validation:""
- }
- wimp_icon {
- extent:40,-228,148,-184
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Serial"
- }
- wimp_icon {
- extent:152,-228,928,-176
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2"
- }
- wimp_icon {
- extent:40,-288,148,-244
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Issuer"
- }
- wimp_icon {
- extent:152,-376,928,-236
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2;L"
- }
- wimp_icon {
- extent:24,-432,148,-388
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Subject"
- }
- wimp_icon {
- extent:152,-504,928,-384
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2;L"
- }
-}
-
-wimp_window {
- template_name:"sslcert"
- visible:348,306,1136,898
- xscroll:0
- yscroll:0
- next:wimp_TOP
- window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FULL_SIZE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
- title_fg:wimp_COLOUR_BLACK
- title_bg:wimp_COLOUR_LIGHT_GREY
- work_fg:wimp_COLOUR_BLACK
- work_bg:wimp_COLOUR_VERY_LIGHT_GREY
- scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
- scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
- highlight_bg:wimp_COLOUR_CREAM
- extra_flags:
- extent:0,-592,788,0
- title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
- work_flags:
- sprite_area:&1
- xmin:788
- ymin:592
- text.text:"SSL Zertifizierungsproblem"
- text.size:*
- text.validation:""
- wimp_icon {
- extent:16,-108,772,-16
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"NetSurf konnte ein SSL Zertifikat nicht prüfen. Bitte die Details unten beachten."
- text.size:150
- text.validation:"R2;L"
- }
- wimp_icon {
- extent:16,-484,772,-136
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R4"
- }
- wimp_icon {
- extent:32,-164,380,-120
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:" Certificate chain "
- text_and_sprite.size:22
- text_and_sprite.validation:""
- }
- wimp_icon {
- extent:404,-564,568,-512
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Ablehnen"
- text.size:*
- text.validation:"R5,3"
- }
- wimp_icon {
- extent:588,-572,772,-504
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Annehmen"
- text.size:12
- text.validation:"R6,3"
- }
-}
-
-wimp_window {
template_name:"con_content"
visible:1404,424,2044,924
xscroll:0
@@ -3760,15 +3370,11 @@ wimp_window {
}
wimp_icon {
extent:32,-256,496,-212
-#ifdef WITH_PLUGIN
icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
-#else
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_DELETED | wimp_BUTTON_RADIO
-#endif
icon_esg:0
icon_fg:wimp_COLOUR_BLACK
icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:"Plugins nicht benutzen"
+ text_and_sprite.text:"CSS nicht benutzen"
text_and_sprite.size:42
text_and_sprite.validation:"Soptoff,opton"
}
diff --git a/frontends/riscos/templates/en b/frontends/riscos/templates/en
index 25be55f5a..6ea18a859 100644
--- a/frontends/riscos/templates/en
+++ b/frontends/riscos/templates/en
@@ -856,56 +856,6 @@ wimp_window {
text_and_sprite.validation:""
}
wimp_icon {
- extent:20,-404,208,-360
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Speed limit"
- text.size:*
- text.validation:""
- }
- wimp_icon {
- extent:212,-408,380,-356
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_WHITE
- text.text:"12.34"
- text.size:*
- text.validation:"Pptr_write;Kta;A0-9."
- }
- wimp_icon {
- extent:396,-400,428,-368
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:""
- text_and_sprite.size:*
- text_and_sprite.validation:"r5;sdown,pdown"
- }
- wimp_icon {
- extent:428,-400,460,-368
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:""
- text_and_sprite.size:*
- text_and_sprite.validation:"r5;sup,pup"
- }
- wimp_icon {
- extent:468,-404,592,-360
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"seconds"
- text.size:*
- text.validation:""
- }
- wimp_icon {
extent:212,-460,556,-416
icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
icon_esg:0
@@ -1405,7 +1355,7 @@ wimp_window {
icon_esg:0
icon_fg:wimp_COLOUR_BLACK
icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"http://netsurf.sourceforge.net/netsurf.zip"
+ text.text:"https://netsurf.sourceforge.net/netsurf.zip"
text.size:*
text.validation:"R2"
}
@@ -1501,6 +1451,32 @@ wimp_window {
}
wimp_window {
+ template_name:"corepginfo"
+ visible:252,388,1152,808
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_SCROLL_REPEAT | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_WHITE
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-880,1236,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Page Info"
+ text.size:*
+ text.validation:""
+}
+
+wimp_window {
template_name:"info"
visible:752,452,1372,700
xscroll:0
@@ -1607,124 +1583,6 @@ wimp_window {
}
wimp_window {
- template_name:"login"
- visible:582,400,1258,736
- xscroll:0
- yscroll:0
- next:wimp_TOP
- window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
- title_fg:wimp_COLOUR_BLACK
- title_bg:wimp_COLOUR_LIGHT_GREY
- work_fg:wimp_COLOUR_BLACK
- work_bg:wimp_COLOUR_VERY_LIGHT_GREY
- scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
- scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
- highlight_bg:wimp_COLOUR_CREAM
- extra_flags:
- extent:0,-336,676,0
- title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
- work_flags:
- sprite_area:&1
- xmin:676
- ymin:336
- text.text:"Site Authentication"
- text.size:*
- text.validation:""
- wimp_icon {
- extent:532,-324,664,-256
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Login"
- text.size:8
- text.validation:"R6,3;Nok"
- }
- wimp_icon {
- extent:380,-316,508,-264
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Cancel"
- text.size:*
- text.validation:"R5,3;Ncancel"
- }
- wimp_icon {
- extent:168,-60,668,-8
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"moo.yoo.com"
- text.size:255
- text.validation:"R2"
- }
- wimp_icon {
- extent:168,-120,668,-68
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"my sekr3t area"
- text.size:255
- text.validation:"R2"
- }
- wimp_icon {
- extent:168,-180,668,-128
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_WHITE
- text.text:""
- text.size:255
- text.validation:"Pptr_write;Kta;N401username"
- }
- wimp_icon {
- extent:168,-240,668,-188
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_WHITE
- text.text:""
- text.size:255
- text.validation:"Pptr_write;Kta;D*"
- }
- wimp_icon {
- extent:84,-56,164,-12
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Host"
- }
- wimp_icon {
- extent:8,-176,164,-132
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Username"
- }
- wimp_icon {
- extent:20,-236,164,-192
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Password"
- }
- wimp_icon {
- extent:64,-116,164,-72
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Realm"
- }
-}
-
-wimp_window {
template_name:"new_entry"
visible:480,660,1080,880
xscroll:0
@@ -2969,178 +2827,6 @@ wimp_window {
}
wimp_window {
- template_name:"ssldisplay"
- visible:862,768,1822,1308
- xscroll:0
- yscroll:0
- next:wimp_TOP
- window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
- title_fg:wimp_COLOUR_BLACK
- title_bg:wimp_COLOUR_LIGHT_GREY
- work_fg:wimp_COLOUR_BLACK
- work_bg:wimp_COLOUR_VERY_LIGHT_GREY
- scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
- scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
- highlight_bg:wimp_COLOUR_CREAM
- extra_flags:
- extent:0,-540,960,0
- title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
- work_flags:
- sprite_area:&1
- xmin:960
- ymin:76
- text.text:"SSL certificate"
- text.size:*
- text.validation:""
- wimp_icon {
- extent:16,-520,944,-24
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R4"
- }
- wimp_icon {
- extent:32,-52,380,-8
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:" Certificate details "
- text_and_sprite.size:*
- text_and_sprite.validation:""
- }
- wimp_icon {
- extent:24,-108,148,-64
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Version"
- }
- wimp_icon {
- extent:152,-108,264,-56
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2"
- }
- wimp_icon {
- extent:284,-104,456,-60
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Valid from"
- }
- wimp_icon {
- extent:460,-108,928,-56
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2"
- }
- wimp_icon {
- extent:68,-168,148,-124
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Type"
- }
- wimp_icon {
- extent:152,-168,264,-116
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2"
- }
- wimp_icon {
- extent:268,-164,456,-120
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Valid until"
- }
- wimp_icon {
- extent:460,-168,928,-116
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2"
- }
- wimp_icon {
- extent:40,-228,148,-184
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Serial"
- }
- wimp_icon {
- extent:152,-228,928,-176
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2"
- }
- wimp_icon {
- extent:40,-288,148,-244
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Issuer"
- }
- wimp_icon {
- extent:152,-376,928,-236
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2;L"
- }
- wimp_icon {
- extent:24,-432,148,-388
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Subject"
- }
- wimp_icon {
- extent:152,-504,928,-384
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2;L"
- }
-}
-
-wimp_window {
template_name:"con_secure"
visible:1590,788,2182,1152
xscroll:0
@@ -3354,15 +3040,11 @@ wimp_window {
}
wimp_icon {
extent:32,-256,344,-212
-#ifdef WITH_PLUGIN
icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
-#else
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_DELETED | wimp_BUTTON_RADIO
-#endif
icon_esg:0
icon_fg:wimp_COLOUR_BLACK
icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:"Disable plug-ins"
+ text_and_sprite.text:"Disable CSS"
text_and_sprite.size:42
text_and_sprite.validation:"Soptoff,opton"
}
@@ -3760,78 +3442,3 @@ wimp_window {
}
}
-wimp_window {
- template_name:"sslcert"
- visible:348,306,1136,898
- xscroll:0
- yscroll:0
- next:wimp_TOP
- window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
- title_fg:wimp_COLOUR_BLACK
- title_bg:wimp_COLOUR_LIGHT_GREY
- work_fg:wimp_COLOUR_BLACK
- work_bg:wimp_COLOUR_VERY_LIGHT_GREY
- scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
- scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
- highlight_bg:wimp_COLOUR_CREAM
- extra_flags:
- extent:0,-592,788,0
- title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
- work_flags:
- sprite_area:&1
- xmin:788
- ymin:592
- text.text:"SSL certificate problem"
- text.size:*
- text.validation:""
- wimp_icon {
- extent:16,-108,772,-16
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"NetSurf failed to verify the authenticity of an SSL certificate. Please verify the details presented below."
- text.size:150
- text.validation:"R2;L"
- }
- wimp_icon {
- extent:16,-484,772,-136
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R4"
- }
- wimp_icon {
- extent:32,-164,380,-120
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:" Certificate chain "
- text_and_sprite.size:22
- text_and_sprite.validation:""
- }
- wimp_icon {
- extent:404,-564,568,-512
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Reject"
- text.size:*
- text.validation:"R5,3"
- }
- wimp_icon {
- extent:588,-572,772,-504
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Accept"
- text.size:8
- text.validation:"R6,3"
- }
-}
diff --git a/frontends/riscos/templates/fr b/frontends/riscos/templates/fr
index fafe0cec1..e2741df4a 100644
--- a/frontends/riscos/templates/fr
+++ b/frontends/riscos/templates/fr
@@ -860,56 +860,6 @@ wimp_window {
text_and_sprite.validation:""
}
wimp_icon {
- extent:20,-404,208,-360
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Vitesse limite"
- text.size:*
- text.validation:""
- }
- wimp_icon {
- extent:212,-408,380,-356
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_WHITE
- text.text:"12.34"
- text.size:*
- text.validation:"Pptr_write;Kta"
- }
- wimp_icon {
- extent:396,-400,428,-368
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:""
- text_and_sprite.size:*
- text_and_sprite.validation:"r5;sdown,pdown"
- }
- wimp_icon {
- extent:428,-400,460,-368
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:""
- text_and_sprite.size:*
- text_and_sprite.validation:"r5;sup,pup"
- }
- wimp_icon {
- extent:468,-404,592,-360
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"secondes"
- text.size:*
- text.validation:""
- }
- wimp_icon {
extent:212,-460,628,-416
icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
icon_esg:0
@@ -1195,7 +1145,7 @@ wimp_window {
icon_esg:0
icon_fg:wimp_COLOUR_BLACK
icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"http://netsurf.sourceforge.net/netsurf.zip"
+ text.text:"https://netsurf.sourceforge.net/netsurf.zip"
text.size:*
text.validation:"R2"
}
@@ -1291,6 +1241,32 @@ wimp_window {
}
wimp_window {
+ template_name:"corepginfo"
+ visible:252,388,1152,808
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_SCROLL_REPEAT | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_WHITE
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-880,1236,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Page Info"
+ text.size:*
+ text.validation:""
+}
+
+wimp_window {
template_name:"info"
visible:506,58,1126,306
xscroll:0
@@ -1405,128 +1381,6 @@ wimp_window {
}
wimp_window {
- template_name:"login"
- visible:566,258,1242,594
- xscroll:0
- yscroll:0
- next:wimp_TOP
- window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
- title_fg:wimp_COLOUR_BLACK
- title_bg:wimp_COLOUR_LIGHT_GREY
- work_fg:wimp_COLOUR_BLACK
- work_bg:wimp_COLOUR_VERY_LIGHT_GREY
- scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
- scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
- highlight_bg:wimp_COLOUR_CREAM
- extra_flags:
- extent:0,-336,676,0
- title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
- work_flags:
- sprite_area:&1
- xmin:676
- ymin:336
- text.text:"Authentification du Site"
- text.size:*
- text.validation:""
- wimp_icon {
- extent:532,-324,664,-256
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Entrer"
- text.size:8
- text.validation:"R6,3;Nok"
- }
- wimp_icon {
- extent:376,-316,508,-264
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Annuler"
- text.size:*
- text.validation:"R5,3;Ncancel"
- }
- wimp_icon {
- extent:200,-60,668,-8
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"moo.yoo.com"
- text.size:255
- text.validation:"R2"
- }
- wimp_icon {
- extent:200,-120,668,-68
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"my sekr3t area"
- text.size:255
- text.validation:"R2"
- }
- wimp_icon {
- extent:200,-180,668,-128
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_WHITE
- text.text:""
- text.size:255
- text.validation:"Pptr_write;Kta;N401username"
- }
- wimp_icon {
- extent:200,-240,668,-188
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_WHITE
- text.text:""
- text.size:255
- text.validation:"Pptr_write;Kta;D*"
- }
- wimp_icon {
- extent:120,-56,196,-12
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Hôte"
- }
- wimp_icon {
- extent:8,-176,196,-132
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Identifiant"
- text.size:*
- text.validation:""
- }
- wimp_icon {
- extent:8,-236,196,-192
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Code secret"
- text.size:*
- text.validation:""
- }
- wimp_icon {
- extent:68,-116,196,-72
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Domaine"
- }
-}
-
-wimp_window {
template_name:"new_entry"
visible:1120,590,1720,810
xscroll:0
@@ -2988,15 +2842,11 @@ wimp_window {
}
wimp_icon {
extent:32,-256,404,-212
-#ifdef WITH_PLUGIN
icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
-#else
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_DELETED | wimp_BUTTON_RADIO
-#endif
icon_esg:0
icon_fg:wimp_COLOUR_BLACK
icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:"Désactiver les plug-ins"
+ text_and_sprite.text:"Désactiver les CSS"
text_and_sprite.size:42
text_and_sprite.validation:"Soptoff,opton"
}
@@ -3610,253 +3460,3 @@ wimp_window {
}
}
-
-wimp_window {
- template_name:"ssldisplay"
- visible:282,178,1242,718
- xscroll:0
- yscroll:0
- next:wimp_TOP
- window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
- title_fg:wimp_COLOUR_BLACK
- title_bg:wimp_COLOUR_LIGHT_GREY
- work_fg:wimp_COLOUR_BLACK
- work_bg:wimp_COLOUR_VERY_LIGHT_GREY
- scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
- scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
- highlight_bg:wimp_COLOUR_CREAM
- extra_flags:
- extent:0,-540,960,0
- title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
- work_flags:
- sprite_area:&1
- xmin:960
- ymin:76
- text.text:"Certificat SSL"
- text.size:16
- text.validation:""
- wimp_icon {
- extent:16,-520,944,-24
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R4"
- }
- wimp_icon {
- extent:32,-52,412,-8
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:" Détails de certificat "
- text_and_sprite.size:*
- text_and_sprite.validation:""
- }
- wimp_icon {
- extent:68,-108,192,-64
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Version"
- }
- wimp_icon {
- extent:200,-108,312,-56
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2"
- }
- wimp_icon {
- extent:384,-104,524,-60
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Valide de"
- }
- wimp_icon {
- extent:524,-108,928,-56
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2"
- }
- wimp_icon {
- extent:112,-168,192,-124
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Type"
- }
- wimp_icon {
- extent:200,-168,312,-116
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2"
- }
- wimp_icon {
- extent:328,-164,524,-120
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Valide jusqu'à"
- text.size:*
- text.validation:""
- }
- wimp_icon {
- extent:524,-168,928,-116
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2"
- }
- wimp_icon {
- extent:84,-228,192,-184
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Série"
- }
- wimp_icon {
- extent:200,-228,928,-176
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2"
- }
- wimp_icon {
- extent:32,-288,200,-244
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Fournisseur"
- }
- wimp_icon {
- extent:200,-376,928,-236
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2;L"
- }
- wimp_icon {
- extent:68,-432,192,-388
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Sujet"
- }
- wimp_icon {
- extent:200,-504,928,-384
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R2;L"
- }
-}
-
-wimp_window {
- template_name:"sslcert"
- visible:348,306,1136,898
- xscroll:0
- yscroll:0
- next:wimp_TOP
- window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
- title_fg:wimp_COLOUR_BLACK
- title_bg:wimp_COLOUR_LIGHT_GREY
- work_fg:wimp_COLOUR_BLACK
- work_bg:wimp_COLOUR_VERY_LIGHT_GREY
- scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
- scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
- highlight_bg:wimp_COLOUR_CREAM
- extra_flags:
- extent:0,-592,788,0
- title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
- work_flags:
- sprite_area:&1
- xmin:788
- ymin:592
- text.text:"Problème de certificat SSL"
- text.size:*
- text.validation:""
- wimp_icon {
- extent:16,-108,772,-16
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"NetSurf n'a pas pu vérifier l'authenticité d'un certificat SSL. Vérifiez SVP les détails présentés ci-dessous."
- text.size:150
- text.validation:"R2;L"
- }
- wimp_icon {
- extent:16,-484,772,-136
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:*
- text.validation:"R4"
- }
- wimp_icon {
- extent:32,-164,380,-120
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:"Chaîne de certificat "
- text_and_sprite.size:*
- text_and_sprite.validation:""
- }
- wimp_icon {
- extent:404,-564,568,-512
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Rejeter"
- text.size:*
- text.validation:"R5,3"
- }
- wimp_icon {
- extent:588,-572,772,-504
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Accepter"
- text.size:*
- text.validation:"R6,3"
- }
-}
diff --git a/frontends/riscos/templates/nl b/frontends/riscos/templates/nl
index 5ed9cac1b..24b176891 100644
--- a/frontends/riscos/templates/nl
+++ b/frontends/riscos/templates/nl
@@ -858,56 +858,6 @@ wimp_window {
text_and_sprite.validation:""
}
wimp_icon {
- extent:20,-404,232,-360
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Animatietijd"
- text.size:15
- text.validation:""
- }
- wimp_icon {
- extent:236,-408,404,-356
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_WHITE
- text.text:"12.34"
- text.size:6
- text.validation:"Pptr_write;Kta;A0-9."
- }
- wimp_icon {
- extent:420,-400,452,-368
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:""
- text_and_sprite.size:1
- text_and_sprite.validation:"r5;sdown,pdown"
- }
- wimp_icon {
- extent:452,-400,484,-368
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_REPEAT
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:""
- text_and_sprite.size:1
- text_and_sprite.validation:"r5;sup,pup"
- }
- wimp_icon {
- extent:492,-404,644,-360
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"seconden"
- text.size:9
- text.validation:""
- }
- wimp_icon {
extent:236,-460,616,-416
icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
icon_esg:0
@@ -1409,8 +1359,8 @@ wimp_window {
icon_esg:0
icon_fg:wimp_COLOUR_BLACK
icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"http://netsurf.sourceforge.net/netsurf.zip"
- text.size:43
+ text.text:"https://netsurf.sourceforge.net/netsurf.zip"
+ text.size:*
text.validation:"R2"
}
wimp_icon {
@@ -1505,6 +1455,32 @@ wimp_window {
}
wimp_window {
+ template_name:"corepginfo"
+ visible:252,388,1152,808
+ xscroll:0
+ yscroll:0
+ next:wimp_TOP
+ window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_SCROLL_REPEAT | wimp_WINDOW_NEW_FORMAT
+ title_fg:wimp_COLOUR_BLACK
+ title_bg:wimp_COLOUR_LIGHT_GREY
+ work_fg:wimp_COLOUR_BLACK
+ work_bg:wimp_COLOUR_WHITE
+ scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
+ scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
+ highlight_bg:wimp_COLOUR_CREAM
+ extra_flags:
+ extent:0,-880,1236,0
+ title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
+ work_flags:wimp_BUTTON_CLICK
+ sprite_area:&1
+ xmin:0
+ ymin:0
+ text.text:"Page Info"
+ text.size:*
+ text.validation:""
+}
+
+wimp_window {
template_name:"info"
visible:752,332,1412,700
xscroll:0
@@ -1649,126 +1625,6 @@ wimp_window {
}
wimp_window {
- template_name:"login"
- visible:582,400,1322,736
- xscroll:0
- yscroll:0
- next:wimp_TOP
- window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
- title_fg:wimp_COLOUR_BLACK
- title_bg:wimp_COLOUR_LIGHT_GREY
- work_fg:wimp_COLOUR_BLACK
- work_bg:wimp_COLOUR_VERY_LIGHT_GREY
- scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
- scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
- highlight_bg:wimp_COLOUR_CREAM
- extra_flags:
- extent:0,-336,740,0
- title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
- work_flags:
- sprite_area:&1
- xmin:740
- ymin:336
- text.text:"Website-authenticatie"
- text.size:22
- text.validation:""
- wimp_icon {
- extent:596,-324,728,-256
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Login"
- text.size:8
- text.validation:"R6,3;Nok"
- }
- wimp_icon {
- extent:408,-316,572,-264
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Annuleer"
- text.size:9
- text.validation:"R5,3;Ncancel"
- }
- wimp_icon {
- extent:252,-60,732,-8
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"moo.yoo.com"
- text.size:255
- text.validation:"R2"
- }
- wimp_icon {
- extent:252,-120,732,-68
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"my sekr3t area"
- text.size:255
- text.validation:"R2"
- }
- wimp_icon {
- extent:252,-180,732,-128
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_WHITE
- text.text:""
- text.size:255
- text.validation:"Pptr_write;Kta;N401username"
- }
- wimp_icon {
- extent:252,-240,732,-188
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_WRITABLE
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_WHITE
- text.text:""
- text.size:255
- text.validation:"Pptr_write;Kta;D*"
- }
- wimp_icon {
- extent:100,-56,248,-12
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Website"
- }
- wimp_icon {
- extent:4,-176,248,-132
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Gebruikersnaam"
- text.size:15
- text.validation:""
- }
- wimp_icon {
- extent:16,-236,248,-192
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Wachtwoord"
- }
- wimp_icon {
- extent:108,-116,248,-72
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Gebied"
- }
-}
-
-wimp_window {
template_name:"new_entry"
visible:480,660,1080,880
xscroll:0
@@ -3017,180 +2873,6 @@ wimp_window {
}
wimp_window {
- template_name:"ssldisplay"
- visible:862,768,1870,1308
- xscroll:0
- yscroll:0
- next:wimp_TOP
- window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
- title_fg:wimp_COLOUR_BLACK
- title_bg:wimp_COLOUR_LIGHT_GREY
- work_fg:wimp_COLOUR_BLACK
- work_bg:wimp_COLOUR_VERY_LIGHT_GREY
- scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
- scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
- highlight_bg:wimp_COLOUR_CREAM
- extra_flags:
- extent:0,-540,1008,0
- title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
- work_flags:
- sprite_area:&1
- xmin:1008
- ymin:76
- text.text:"SSL-certificaat"
- text.size:16
- text.validation:""
- wimp_icon {
- extent:16,-520,992,-24
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:1
- text.validation:"R4"
- }
- wimp_icon {
- extent:32,-52,380,-8
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:" Certificaatedetails "
- text_and_sprite.size:22
- text_and_sprite.validation:""
- }
- wimp_icon {
- extent:72,-108,196,-64
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Versie"
- }
- wimp_icon {
- extent:200,-108,312,-56
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:1
- text.validation:"R2"
- }
- wimp_icon {
- extent:320,-104,528,-60
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Geldig vanaf"
- text.size:13
- text.validation:""
- }
- wimp_icon {
- extent:532,-108,976,-56
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:1
- text.validation:"R2"
- }
- wimp_icon {
- extent:116,-168,196,-124
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Type"
- }
- wimp_icon {
- extent:200,-168,312,-116
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:1
- text.validation:"R2"
- }
- wimp_icon {
- extent:340,-164,528,-120
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Geldig tot"
- }
- wimp_icon {
- extent:532,-168,976,-116
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:1
- text.validation:"R2"
- }
- wimp_icon {
- extent:68,-228,196,-184
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Serienr"
- }
- wimp_icon {
- extent:200,-228,976,-176
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:1
- text.validation:"R2"
- }
- wimp_icon {
- extent:56,-288,196,-244
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Uitgever"
- }
- wimp_icon {
- extent:200,-376,976,-236
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:1
- text.validation:"R2;L"
- }
- wimp_icon {
- extent:24,-432,196,-388
- icon_flags:wimp_ICON_TEXT | wimp_ICON_VCENTRED | wimp_ICON_RJUSTIFIED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_only:"Onderwerp"
- }
- wimp_icon {
- extent:200,-504,976,-384
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:1
- text.validation:"R2;L"
- }
-}
-
-wimp_window {
template_name:"con_secure"
visible:1590,788,2206,1152
xscroll:0
@@ -3408,11 +3090,11 @@ wimp_window {
}
wimp_icon {
extent:32,-256,540,-212
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_ICON_DELETED | wimp_BUTTON_RADIO
+ icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_BUTTON_RADIO
icon_esg:0
icon_fg:wimp_COLOUR_BLACK
icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:"Plug-ins uitschakelen"
+ text_and_sprite.text:"CSS uitschakelen"
text_and_sprite.size:42
text_and_sprite.validation:"Soptoff,opton"
}
@@ -3810,78 +3492,3 @@ wimp_window {
}
}
-wimp_window {
- template_name:"sslcert"
- visible:348,250,1136,898
- xscroll:0
- yscroll:0
- next:wimp_TOP
- window_flags:wimp_WINDOW_MOVEABLE | wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_BOUNDED_ONCE | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_NEW_FORMAT
- title_fg:wimp_COLOUR_BLACK
- title_bg:wimp_COLOUR_LIGHT_GREY
- work_fg:wimp_COLOUR_BLACK
- work_bg:wimp_COLOUR_VERY_LIGHT_GREY
- scroll_outer:wimp_COLOUR_MID_LIGHT_GREY
- scroll_inner:wimp_COLOUR_VERY_LIGHT_GREY
- highlight_bg:wimp_COLOUR_CREAM
- extra_flags:
- extent:0,-648,788,0
- title_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | 0x27000000
- work_flags:
- sprite_area:&1
- xmin:788
- ymin:648
- text.text:"SSL-certificaatprobleem"
- text.size:24
- text.validation:""
- wimp_icon {
- extent:16,-148,772,-16
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"NetSurf kan de rechtmatigheid van een SSL-certificaat niet verifiëren. Verifieer de details hieronder."
- text.size:150
- text.validation:"R2;L"
- }
- wimp_icon {
- extent:16,-548,772,-176
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:""
- text.size:1
- text.validation:"R4"
- }
- wimp_icon {
- extent:32,-204,380,-160
- icon_flags:wimp_ICON_TEXT | wimp_ICON_SPRITE | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text_and_sprite.text:" Certificaatketen "
- text_and_sprite.size:22
- text_and_sprite.validation:""
- }
- wimp_icon {
- extent:404,-624,568,-572
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Verwerp"
- text.size:8
- text.validation:"R5,3"
- }
- wimp_icon {
- extent:588,-632,772,-564
- icon_flags:wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_BUTTON_CLICK
- icon_esg:0
- icon_fg:wimp_COLOUR_BLACK
- icon_bg:wimp_COLOUR_VERY_LIGHT_GREY
- text.text:"Accepteer"
- text.size:10
- text.validation:"R6,3"
- }
-}
diff --git a/frontends/riscos/textarea.c b/frontends/riscos/textarea.c
index 6f41c640b..69b7eede1 100644
--- a/frontends/riscos/textarea.c
+++ b/frontends/riscos/textarea.c
@@ -33,6 +33,7 @@
#include "utils/log.h"
#include "utils/utf8.h"
+#include "utils/utils.h"
#include "riscos/gui.h"
#include "riscos/oslib_pre7.h"
@@ -1023,7 +1024,7 @@ bool ro_textarea_key_press(wimp_key *key)
break;
}
- /* fall through */
+ fallthrough;
case wimp_KEY_ESCAPE:
keypress = *key;
keypress.w = ta->parent;
diff --git a/frontends/riscos/textselection.c b/frontends/riscos/textselection.c
index e5be27791..2300330db 100644
--- a/frontends/riscos/textselection.c
+++ b/frontends/riscos/textselection.c
@@ -188,8 +188,9 @@ static void ro_gui_selection_drag_end(wimp_dragged *drag, void *data)
return;
}
- if (ro_gui_window_to_window_pos(g, drag->final.x0, drag->final.y0, &pos))
+ if (ro_gui_window_to_window_pos(g, drag->final.x0, drag->final.y0, &pos)) {
browser_window_mouse_track(g->bw, 0, pos.x, pos.y);
+ }
}
/**
diff --git a/frontends/riscos/textselection.h b/frontends/riscos/textselection.h
index 400e3dd26..0d7cc169b 100644
--- a/frontends/riscos/textselection.h
+++ b/frontends/riscos/textselection.h
@@ -25,7 +25,7 @@
#include "oslib/wimp.h"
-struct gui_clipboard_table *riscos_clipboard_table;
+extern struct gui_clipboard_table *riscos_clipboard_table;
void gui_start_selection(struct gui_window *g);
diff --git a/frontends/riscos/theme_install.c b/frontends/riscos/theme_install.c
index fbca9e4fa..1e1af6c9a 100644
--- a/frontends/riscos/theme_install.c
+++ b/frontends/riscos/theme_install.c
@@ -47,8 +47,6 @@ wimp_w dialog_theme_install;
static void theme_install_close(wimp_w w);
static nserror theme_install_callback(struct hlcache_handle *handle,
const hlcache_event *event, void *pw);
-static bool theme_install_read(const char *source_data,
- unsigned long source_size);
/**
@@ -80,6 +78,33 @@ void theme_install_start(struct hlcache_handle *c)
/**
+ * Fill in theme_install_descriptor from received theme data.
+ *
+ * \param source_data received data
+ * \param source_size size of data
+ * \return true if data is a correct theme, false on error
+ *
+ * If the data is a correct theme, theme_install_descriptor is filled in.
+ */
+
+static bool
+theme_install_read(const uint8_t *source_data, size_t source_size)
+{
+ const void *data = source_data;
+
+ if (source_size < sizeof(struct theme_file_header))
+ return false;
+ if (!ro_gui_theme_read_file_header(&theme_install_descriptor,
+ (struct theme_file_header *) data))
+ return false;
+ if (source_size - sizeof(struct theme_file_header) !=
+ theme_install_descriptor.compressed_size)
+ return false;
+ return true;
+}
+
+
+/**
* Callback for fetchcache() for theme install fetches.
*/
@@ -90,8 +115,8 @@ nserror theme_install_callback(struct hlcache_handle *handle,
case CONTENT_MSG_DONE:
{
- const char *source_data;
- unsigned long source_size;
+ const uint8_t *source_data;
+ size_t source_size;
int author_indent = 0;
char buffer[256];
@@ -124,7 +149,7 @@ nserror theme_install_callback(struct hlcache_handle *handle,
case CONTENT_MSG_ERROR:
theme_install_close(dialog_theme_install);
- ro_warn_user(event->data.error, 0);
+ ro_warn_user(event->data.errordata.errormsg, 0);
break;
default:
@@ -135,30 +160,6 @@ nserror theme_install_callback(struct hlcache_handle *handle,
}
-/**
- * Fill in theme_install_descriptor from received theme data.
- *
- * \param source_data received data
- * \param source_size size of data
- * \return true if data is a correct theme, false on error
- *
- * If the data is a correct theme, theme_install_descriptor is filled in.
- */
-
-bool theme_install_read(const char *source_data, unsigned long source_size)
-{
- const void *data = source_data;
-
- if (source_size < sizeof(struct theme_file_header))
- return false;
- if (!ro_gui_theme_read_file_header(&theme_install_descriptor,
- (struct theme_file_header *) data))
- return false;
- if (source_size - sizeof(struct theme_file_header) !=
- theme_install_descriptor.compressed_size)
- return false;
- return true;
-}
/**
@@ -174,8 +175,8 @@ bool ro_gui_theme_install_apply(wimp_w w)
struct theme_descriptor *theme_install;
os_error *error;
char *fix;
- const char *source_data;
- unsigned long source_size;
+ const uint8_t *source_data;
+ size_t source_size;
assert(theme_install_content);
diff --git a/frontends/riscos/tinct.h b/frontends/riscos/tinct.h
index e02dcdece..29313724e 100644
--- a/frontends/riscos/tinct.h
+++ b/frontends/riscos/tinct.h
@@ -148,7 +148,16 @@
*/
#define tinct_BACKGROUND_SHIFT 0x08
-/* Sprite mode
-*/
+/* Sprite mode tinct
+ *
+ * Mode is: 32bpp 8:8:8:8 XXBBGGRR mode (a RISC OS 3.5+ type)
+ * We put alpha in the unused XX channel and Tinct treats it as alpha.
+ */
#define tinct_SPRITE_MODE (os_mode)0x301680b5
+
+/* Sprite mode alpha
+ *
+ * Mode is: 32bpp 8:8:8:8 AABBGGRR mode (a RISC OS 5 type)
+ */
+#define alpha_SPRITE_MODE (os_mode)0x78608051
#endif
diff --git a/frontends/riscos/toolbar.c b/frontends/riscos/toolbar.c
index 758c90cc2..c6a882ab6 100644
--- a/frontends/riscos/toolbar.c
+++ b/frontends/riscos/toolbar.c
@@ -420,7 +420,7 @@ bool ro_toolbar_rebuild(struct toolbar *toolbar)
ro_gui_wimp_event_transfer(old_window, toolbar->toolbar_handle);
}
- /* The help prefix changes from edit to non-edit more. */
+ /* The help prefix changes from edit to non-edit mode. */
ro_gui_wimp_event_set_help_prefix(toolbar->toolbar_handle,
(toolbar->editing) ?
@@ -1115,18 +1115,20 @@ bool ro_toolbar_click(wimp_pointer *pointer)
return true;
}
- /* Nothing else has handled this, so try passing it to the
- * URL Complete module.
- *
- * \TODO -- This should really move into the URL Bar module, as
- * URL Complete is really an extension to that.
- */
-
- if (toolbar->url != NULL && toolbar->url_display &&
- ro_gui_url_bar_test_for_text_field_click(toolbar->url,
- pointer)) {
- ro_gui_url_complete_start(toolbar);
- return true;
+ if (pointer->buttons != wimp_DRAG_SELECT &&
+ pointer->buttons != wimp_DRAG_ADJUST) {
+ /* Nothing else has handled this click, so try passing it to
+ * the URL Complete module.
+ *
+ * \TODO -- This should really move into the URL Bar module, as
+ * URL Complete is really an extension to that.
+ */
+ if (toolbar->url != NULL && toolbar->url_display &&
+ ro_gui_url_bar_test_for_text_field_click(
+ toolbar->url, pointer)) {
+ ro_gui_url_complete_start(toolbar);
+ return true;
+ }
}
return false;
@@ -1538,7 +1540,6 @@ void ro_toolbar_start_throbbing(struct toolbar *toolbar)
/* This is an exported interface documented in toolbar.h */
-
void ro_toolbar_stop_throbbing(struct toolbar *toolbar)
{
if (toolbar != NULL && toolbar->throbber != NULL)
@@ -1547,7 +1548,16 @@ void ro_toolbar_stop_throbbing(struct toolbar *toolbar)
/* This is an exported interface documented in toolbar.h */
+void ro_toolbar_page_info_change(struct toolbar *toolbar)
+{
+ if (toolbar == NULL || toolbar->url == NULL)
+ return;
+
+ ro_gui_url_bar_page_info_change(toolbar->url);
+}
+
+/* This is an exported interface documented in toolbar.h */
void ro_toolbar_throb(struct toolbar *toolbar)
{
if (toolbar != NULL && toolbar->throbber != NULL)
@@ -1656,7 +1666,6 @@ bool ro_toolbar_get_url_field_extent(struct toolbar *toolbar, os_box *extent)
/* This is an exported interface documented in toolbar.h */
-
void ro_toolbar_set_site_favicon(struct toolbar *toolbar,
struct hlcache_handle *h)
{
@@ -1668,7 +1677,6 @@ void ro_toolbar_set_site_favicon(struct toolbar *toolbar,
/* This is an exported interface documented in toolbar.h */
-
void ro_toolbar_set_content_favicon(struct toolbar *toolbar,
struct gui_window *g)
{
diff --git a/frontends/riscos/toolbar.h b/frontends/riscos/toolbar.h
index 41f1af728..9bca44525 100644
--- a/frontends/riscos/toolbar.h
+++ b/frontends/riscos/toolbar.h
@@ -304,7 +304,6 @@ int ro_toolbar_full_height(struct toolbar *toolbar);
*
* \param *toolbar the toolbar to start throbbing.
*/
-
void ro_toolbar_start_throbbing(struct toolbar *toolbar);
@@ -538,5 +537,14 @@ bool ro_toolbar_get_editing(struct toolbar *toolbar);
bool ro_toolbar_toggle_edit(struct toolbar *toolbar);
+
+/**
+ * Update the page information indicator.
+ *
+ * \param toolbar the toolbar to update the page info in.
+ */
+void ro_toolbar_page_info_change(struct toolbar *toolbar);
+
+
#endif
diff --git a/frontends/riscos/ucstables.c b/frontends/riscos/ucstables.c
index 3e31c992e..a94e4348c 100644
--- a/frontends/riscos/ucstables.c
+++ b/frontends/riscos/ucstables.c
@@ -398,49 +398,47 @@ static const char *localencodings[] = {
"ISO-8859-10//TRANSLIT",
"ISO-8859-13//TRANSLIT",
"ISO-8859-14//TRANSLIT",
- "ISO-8859-16//TRANSLIT",
-#define CONT_ENC_END 116 /* RISC OS alphabet numbers lie in a
- * contiguous range [100,CONT_ENC_END]
- * _except_ for Cyrillic2, which doesn't.
- */
- "CP866//TRANSLIT" /* Cyrillic2 - 120 */
+ "ISO-8859-16//TRANSLIT", /* Latin10 - 116 */
+ NULL, /* UTF-16, if you believe HdrSrc (Unused) */
+ NULL, /* Unused */
+ NULL, /* Unused */
+ "CP866//TRANSLIT" /* Cyrillic2 - 120 */
};
-static const struct special {
- char local; /**< Local 8bit representation */
- char len; /**< Length (in bytes) of UTF-8 character */
- const char *utf; /**< UTF-8 representation */
-} special_chars[] = {
- { 0x80, 3, "\xE2\x82\xAC" }, /* EURO SIGN */
- { 0x81, 2, "\xC5\xB4" }, /* LATIN CAPITAL LETTER W WITH CIRCUMFLEX */
- { 0x82, 2, "\xC5\xB5" }, /* LATIN SMALL LETTER W WITH CIRCUMFLEX */
- { 0x84, 3, "\xE2\x9C\x98" }, /* HEAVY BALLOT X */
- { 0x85, 2, "\xC5\xB6" }, /* LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */
- { 0x86, 2, "\xC5\xB7" }, /* LATIN SMALL LETTER Y WITH CIRCUMFLEX */
- { 0x88, 3, "\xE2\x87\x90" }, /* LEFTWARDS DOUBLE ARROW */
- { 0x89, 3, "\xE2\x87\x92" }, /* RIGHTWARDS DOUBLE ARROW */
- { 0x8a, 3, "\xE2\x87\x93" }, /* DOWNWARDS DOUBLE ARROW */
- { 0x8b, 3, "\xE2\x87\x91" }, /* UPWARDS DOUBLE ARROW */
- { 0x8c, 3, "\xE2\x80\xA6" }, /* HORIZONTAL ELLIPSIS */
- { 0x8d, 3, "\xE2\x84\xA2" }, /* TRADE MARK SIGN */
- { 0x8e, 3, "\xE2\x80\xB0" }, /* PER MILLE SIGN */
- { 0x8f, 3, "\xE2\x80\xA2" }, /* BULLET */
- { 0x90, 3, "\xE2\x80\x98" }, /* LEFT SINGLE QUOTATION MARK */
- { 0x91, 3, "\xE2\x80\x99" }, /* RIGHT SINGLE QUOTATION MARK */
- { 0x92, 3, "\xE2\x80\xB9" }, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
- { 0x93, 3, "\xE2\x80\xBA" }, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
- { 0x94, 3, "\xE2\x80\x9C" }, /* LEFT DOUBLE QUOTATION MARK */
- { 0x95, 3, "\xE2\x80\x9D" }, /* RIGHT DOUBLE QUOTATION MARK */
- { 0x96, 3, "\xE2\x80\x9E" }, /* DOUBLE LOW-9 QUOTATION MARK */
- { 0x97, 3, "\xE2\x80\x93" }, /* EN DASH */
- { 0x98, 3, "\xE2\x80\x94" }, /* EM DASH */
- { 0x99, 3, "\xE2\x88\x92" }, /* MINUS SIGN */
- { 0x9a, 2, "\xC5\x92" }, /* LATIN CAPITAL LIGATURE OE */
- { 0x9b, 2, "\xC5\x93" }, /* LATIN SMALL LIGATURE OE */
- { 0x9c, 3, "\xE2\x80\xA0" }, /* DAGGER */
- { 0x9d, 3, "\xE2\x80\xA1" }, /* DOUBLE DAGGER */
- { 0x9e, 3, "\xEF\xAC\x81" }, /* LATIN SMALL LIGATURE FI */
- { 0x9f, 3, "\xEF\xAC\x82" } /* LATIN SMALL LIGATURE FL */
+/* These are the Acorn Latin1 C1 block between [0x80,0x9f] */
+static const char *special_chars[] = {
+ "\xE2\x82\xAC", /* EURO SIGN */
+ "\xC5\xB4", /* LATIN CAPITAL LETTER W WITH CIRCUMFLEX */
+ "\xC5\xB5", /* LATIN SMALL LETTER W WITH CIRCUMFLEX */
+ NULL, /* unused */
+ "\xE2\x9C\x98", /* HEAVY BALLOT X */
+ "\xC5\xB6", /* LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */
+ "\xC5\xB7", /* LATIN SMALL LETTER Y WITH CIRCUMFLEX */
+ NULL, /* unused */
+ "\xE2\x87\x90", /* LEFTWARDS DOUBLE ARROW */
+ "\xE2\x87\x92", /* RIGHTWARDS DOUBLE ARROW */
+ "\xE2\x87\x93", /* DOWNWARDS DOUBLE ARROW */
+ "\xE2\x87\x91", /* UPWARDS DOUBLE ARROW */
+ "\xE2\x80\xA6", /* HORIZONTAL ELLIPSIS */
+ "\xE2\x84\xA2", /* TRADE MARK SIGN */
+ "\xE2\x80\xB0", /* PER MILLE SIGN */
+ "\xE2\x80\xA2", /* BULLET */
+ "\xE2\x80\x98", /* LEFT SINGLE QUOTATION MARK */
+ "\xE2\x80\x99", /* RIGHT SINGLE QUOTATION MARK */
+ "\xE2\x80\xB9", /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
+ "\xE2\x80\xBA", /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
+ "\xE2\x80\x9C", /* LEFT DOUBLE QUOTATION MARK */
+ "\xE2\x80\x9D", /* RIGHT DOUBLE QUOTATION MARK */
+ "\xE2\x80\x9E", /* DOUBLE LOW-9 QUOTATION MARK */
+ "\xE2\x80\x93", /* EN DASH */
+ "\xE2\x80\x94", /* EM DASH */
+ "\xE2\x88\x92", /* MINUS SIGN */
+ "\xC5\x92", /* LATIN CAPITAL LIGATURE OE */
+ "\xC5\x93", /* LATIN SMALL LIGATURE OE */
+ "\xE2\x80\xA0", /* DAGGER */
+ "\xE2\x80\xA1", /* DOUBLE DAGGER */
+ "\xEF\xAC\x81", /* LATIN SMALL LIGATURE FI */
+ "\xEF\xAC\x82" /* LATIN SMALL LIGATURE FL */
};
@@ -470,20 +468,22 @@ nserror utf8_to_local_encoding(const char *string, size_t len, char **result)
/* read system alphabet */
error = xosbyte1(osbyte_ALPHABET_NUMBER, 127, 0, &alphabet);
- if (error)
+ /* Assume Latin1 for anything we know nothing about */
+ if (error || alphabet < territory_ALPHABET_BFONT ||
+ alphabet > territory_ALPHABET_CYRILLIC2)
alphabet = territory_ALPHABET_LATIN1;
/* UTF-8 -> simply copy string */
- if (alphabet == 111 /* UTF-8 */) {
+ if (alphabet == territory_ALPHABET_UTF8) {
*result = strndup(string, len);
return NSERROR_OK;
}
/* get encoding name */
- enc = (alphabet <= CONT_ENC_END ? localencodings[alphabet - 100]
- : (alphabet == 120 ?
- localencodings[CONT_ENC_END - 100 + 1]
- : localencodings[0]));
+ enc = localencodings[alphabet - territory_ALPHABET_BFONT];
+ /* Assume Latin1 for any that are unused */
+ if (enc == NULL)
+ enc = localencodings[0];
/* create output buffer */
*(result) = malloc(len + 1);
@@ -498,13 +498,32 @@ nserror utf8_to_local_encoding(const char *string, size_t len, char **result)
* characters and inserting appropriate output for characters
* that iconv can't handle. */
for (off = 0; off < len; off = utf8_next(string, len, off)) {
- if (string[off] != 0xE2 &&
- string[off] != 0xC5 && string[off] != 0xEF)
+ /* Specials only start with C5/E2/EF */
+ if (string[off] != 0xC5 &&
+ string[off] != 0xE2 && string[off] != 0xEF)
continue;
+ /* Ignore truncated input */
+ if (off + 2 + (string[off] == 0xC5 ? 0 : 1) >= len)
+ continue;
+
+ /* Search to see if this character is special */
for (i = 0; i != NOF_ELEMENTS(special_chars); i++) {
- if (strncmp(string + off, special_chars[i].utf,
- special_chars[i].len) != 0)
+ /* Skip unused special char */
+ if (special_chars[i] == NULL)
+ continue;
+
+ /* Skip 2-byte non-match */
+ if (string[off] == 0xC5 &&
+ (string[off] != special_chars[i][0] ||
+ string[off+1] != special_chars[i][1]))
+ continue;
+
+ /* Skip 3-byte non-match */
+ if (string[off] != 0xC5 &&
+ (string[off] != special_chars[i][0] ||
+ string[off+1] != special_chars[i][1] ||
+ string[off+2] != special_chars[i][2]))
continue;
/* 0 length has a special meaning to utf8_to_enc */
@@ -524,9 +543,13 @@ nserror utf8_to_local_encoding(const char *string, size_t len, char **result)
free(temp);
}
- *cur_pos = special_chars[i].local;
+ /* Emit conversion for this special character */
+ *cur_pos = 0x80 + i;
*(++cur_pos) = '\0';
- prev_off = off + special_chars[i].len;
+ prev_off = off + 2 + (string[off] == 0xC5 ? 0 : 1);
+
+ /* Return to outer loop to process remaining input */
+ break;
}
}
@@ -561,7 +584,7 @@ nserror utf8_to_local_encoding(const char *string, size_t len, char **result)
nserror utf8_from_local_encoding(const char *string, size_t len, char **result)
{
os_error *error;
- int alphabet, i, num_specials = 0, result_alloc;
+ int alphabet, num_specials = 0, result_alloc;
#define SPECIAL_CHUNK_SIZE 255
size_t off, prev_off, cur_off;
char *temp;
@@ -576,11 +599,13 @@ nserror utf8_from_local_encoding(const char *string, size_t len, char **result)
/* read system alphabet */
error = xosbyte1(osbyte_ALPHABET_NUMBER, 127, 0, &alphabet);
- if (error)
+ /* Assume Latin1 for anything we know nothing about */
+ if (error || alphabet < territory_ALPHABET_BFONT ||
+ alphabet > territory_ALPHABET_CYRILLIC2)
alphabet = territory_ALPHABET_LATIN1;
/* UTF-8 -> simply copy string */
- if (alphabet == 111 /* UTF-8 */) {
+ if (alphabet == territory_ALPHABET_UTF8) {
temp = strndup(string, len);
if (!temp)
return NSERROR_NOMEM;
@@ -590,10 +615,10 @@ nserror utf8_from_local_encoding(const char *string, size_t len, char **result)
}
/* get encoding name */
- enc = (alphabet <= CONT_ENC_END ? localencodings[alphabet - 100]
- : (alphabet == 120 ?
- localencodings[CONT_ENC_END - 100 + 1]
- : localencodings[0]));
+ enc = localencodings[alphabet - territory_ALPHABET_BFONT];
+ /* Assume Latin1 for any that are unused */
+ if (enc == NULL)
+ enc = localencodings[0];
/* create output buffer (oversized) */
result_alloc = (len * 4) + (3 * SPECIAL_CHUNK_SIZE) + 1;
@@ -610,52 +635,54 @@ nserror utf8_from_local_encoding(const char *string, size_t len, char **result)
* characters and inserting appropriate output for characters
* that iconv can't handle. */
for (off = 0; off < len; off++) {
+ /* Skip non-special characters */
if (string[off] < 0x80 || string[off] > 0x9f)
continue;
- for (i = 0; i != NOF_ELEMENTS(special_chars); i++) {
- if (string[off] != special_chars[i].local)
- continue;
-
- /* 0 length has a special meaning to utf8_from_enc */
- if (off - prev_off > 0) {
- err = utf8_from_enc(string + prev_off, enc,
- off - prev_off, &temp, NULL);
- if (err != NSERROR_OK) {
- assert(err != NSERROR_BAD_ENCODING);
- NSLOG(netsurf, INFO,
- "utf8_from_enc failed");
- free(*result);
- return NSERROR_NOMEM;
- }
-
- strcat((*result) + cur_off, temp);
-
- cur_off += strlen(temp);
-
- free(temp);
+ /* 0 length has a special meaning to utf8_from_enc */
+ if (off - prev_off > 0) {
+ err = utf8_from_enc(string + prev_off, enc,
+ off - prev_off, &temp, NULL);
+ if (err != NSERROR_OK) {
+ assert(err != NSERROR_BAD_ENCODING);
+ NSLOG(netsurf, INFO, "utf8_from_enc failed");
+ free(*result);
+ return NSERROR_NOMEM;
}
- strcat((*result) + cur_off, special_chars[i].utf);
+ strcat((*result) + cur_off, temp);
- cur_off += special_chars[i].len;
+ cur_off += strlen(temp);
- prev_off = off + 1;
+ free(temp);
+ }
- num_specials++;
- if (num_specials % SPECIAL_CHUNK_SIZE ==
- SPECIAL_CHUNK_SIZE - 1) {
- char *temp = realloc((*result),
- result_alloc +
- (3 * SPECIAL_CHUNK_SIZE));
- if (!temp) {
- free(*result);
- return NSERROR_NOMEM;
- }
+ /* Append UTF-8 encoded special character or U+FFFD if none */
+ if (special_chars[string[off]-0x80] != NULL) {
+ const char *special = special_chars[string[off]-0x80];
+ strcat((*result) + cur_off, special);
+ cur_off += 2 + (special[0] == 0xC5 ? 0 : 1);
+ } else {
+ strcat((*result) + cur_off, "\xef\xbf\xbd");
+ cur_off += 3;
+ }
- *result = temp;
- result_alloc += (3 * SPECIAL_CHUNK_SIZE);
+ prev_off = off + 1;
+
+ /* Resize output buffer if necessary */
+ num_specials++;
+ if (num_specials % SPECIAL_CHUNK_SIZE ==
+ SPECIAL_CHUNK_SIZE - 1) {
+ char *temp = realloc((*result),
+ result_alloc +
+ (3 * SPECIAL_CHUNK_SIZE));
+ if (!temp) {
+ free(*result);
+ return NSERROR_NOMEM;
}
+
+ *result = temp;
+ result_alloc += (3 * SPECIAL_CHUNK_SIZE);
}
}
diff --git a/frontends/riscos/ucstables.h b/frontends/riscos/ucstables.h
index e5d838249..31db5d882 100644
--- a/frontends/riscos/ucstables.h
+++ b/frontends/riscos/ucstables.h
@@ -21,7 +21,7 @@
* This is only used if nothing claims Service_International,8
*/
-struct gui_utf8_table *riscos_utf8_table;
+extern struct gui_utf8_table *riscos_utf8_table;
nserror utf8_to_local_encoding(const char *string, size_t len, char **result);
nserror utf8_from_local_encoding(const char *string, size_t len, char **result);
diff --git a/frontends/riscos/wimputils.h b/frontends/riscos/wimputils.h
index 5225a720e..b1bd88045 100644
--- a/frontends/riscos/wimputils.h
+++ b/frontends/riscos/wimputils.h
@@ -24,6 +24,9 @@
#define riscos_wimputils_h_
#include <oslib/wimp.h>
+#include <oslib/wimpreadsysinfo.h>
+
+#include "utils/log.h"
/* Magical union to permit aliasing of wimp_window_state and wimp_open
* Do not use this directly. Use the macros, instead. */
@@ -62,4 +65,27 @@ typedef union vdu_var_list {
#define PTR_OS_VDU_VAR_LIST(l) ((os_vdu_var_list *) (vdu_var_list *) (l))
+/**
+ * Check whether the OS supports text selection in writiable icons.
+ *
+ * \return true if text-selection is supported, false otherwise.
+ */
+static inline bool ns_wimp_has_text_selection(void)
+{
+ wimp_colour bg;
+ wimp_colour fg;
+ os_error *error;
+ wimpreadsysinfotextselection_flags flags;
+
+ error = xwimpreadsysinfo_text_selection(&bg, &fg, &flags);
+ if (error) {
+ NSLOG(netsurf, WARNING,
+ "xwimpreadsysinfo_text_selection: 0x%x: %s",
+ error->errnum, error->errmess);
+ return false;
+ }
+
+ return (flags & wimpreadsysinfotextselectionflags_ENABLED);
+}
+
#endif
diff --git a/frontends/riscos/window.c b/frontends/riscos/window.c
index 986e5c55d..4dcdcd734 100644
--- a/frontends/riscos/window.c
+++ b/frontends/riscos/window.c
@@ -64,6 +64,7 @@
#include "netsurf/keypress.h"
#include "desktop/browser_history.h"
#include "desktop/cookie_manager.h"
+#include "desktop/searchweb.h"
#include "riscos/bitmap.h"
#include "riscos/buffer.h"
@@ -71,6 +72,7 @@
#include "riscos/dialog.h"
#include "riscos/local_history.h"
#include "riscos/global_history.h"
+#include "riscos/pageinfo.h"
#include "riscos/gui.h"
#include "riscos/gui/status_bar.h"
#include "riscos/help.h"
@@ -390,15 +392,18 @@ static void ro_gui_window_open(wimp_open *open)
/* reformat or change extent if necessary */
if (have_content &&
- (g->old_width != width || g->old_height != height)) {
+ (g->old_width != width || g->old_height != height)) {
/* Ctrl-resize of a top-level window scales the content size */
- if ((g->old_width > 0) && (g->old_width != width) &&
- (ro_gui_ctrl_pressed()))
- new_scale = (g->scale * width) / g->old_width;
+ if ((g->old_width > 0) &&
+ (g->old_width != width) &&
+ (ro_gui_ctrl_pressed())) {
+ new_scale = (browser_window_get_scale(g->bw) * width) / g->old_width;
+ }
browser_window_schedule_reformat(g->bw);
}
- if (g->update_extent || g->old_width != width ||
- g->old_height != height) {
+ if (g->update_extent ||
+ g->old_width != width ||
+ g->old_height != height) {
g->old_width = width;
g->old_height = height;
g->update_extent = false;
@@ -583,7 +588,7 @@ static void ro_gui_window_action_add_bookmark(struct gui_window *g)
browser_window_has_content(g->bw) == false)
return;
- url = browser_window_get_url(g->bw);
+ url = browser_window_access_url(g->bw);
ro_gui_hotlist_add_page(url);
ro_toolbar_update_hotlist(g->toolbar);
@@ -603,7 +608,7 @@ static void ro_gui_window_action_remove_bookmark(struct gui_window *g)
browser_window_has_content(g->bw) == false)
return;
- url = browser_window_get_url(g->bw);
+ url = browser_window_access_url(g->bw);
ro_gui_hotlist_remove_page(url);
}
@@ -828,8 +833,11 @@ ro_gui_window_toolbar_click(void *data,
if (action_type == TOOLBAR_ACTION_URL) {
switch (action.url) {
case TOOLBAR_URL_DRAG_URL:
+ case TOOLBAR_URL_DRAG_FAVICON:
{
gui_save_type save_type;
+ nserror err;
+ nsurl *url;
if (!browser_window_has_content(g->bw))
break;
@@ -839,9 +847,17 @@ ro_gui_window_toolbar_click(void *data,
else
save_type = GUI_SAVE_LINK_TEXT;
- ro_gui_drag_save_link(save_type,
- browser_window_get_url(g->bw),
+ err = browser_window_get_url(g->bw, true, &url);
+ if (err != NSERROR_OK) {
+ /* Fall back to access (won't get fragment). */
+ url = nsurl_ref(
+ browser_window_access_url(g->bw));
+ }
+
+ ro_gui_drag_save_link(save_type, url,
browser_window_get_title(g->bw), g);
+
+ nsurl_unref(url);
}
break;
@@ -853,6 +869,10 @@ ro_gui_window_toolbar_click(void *data,
ro_gui_window_action_remove_bookmark(g);
break;
+ case TOOLBAR_URL_SELECT_PGINFO:
+ case TOOLBAR_URL_ADJUST_PGINFO:
+ ro_gui_pageinfo_present(g);
+
default:
break;
}
@@ -972,17 +992,18 @@ ro_gui_window_toolbar_click(void *data,
* \param g gui_window to update
* \param url1 url to be launched
*/
-static void ro_gui_window_launch_url(struct gui_window *g, const char *url1)
+static void ro_gui_window_launch_url(struct gui_window *g, const char *url_s)
{
nserror error;
nsurl *url;
- if (url1 == NULL)
+ if (url_s == NULL) {
return;
+ }
ro_gui_url_complete_close();
- error = nsurl_create(url1, &url);
+ error = search_web_omni(url_s, SEARCH_WEB_OMNI_NONE, &url);
if (error != NSERROR_OK) {
ro_warn_user(messages_get_errorcode(error), 0);
} else {
@@ -1009,7 +1030,7 @@ static void ro_gui_window_action_new_window(struct gui_window *g)
return;
error = browser_window_create(BW_CREATE_CLONE,
- browser_window_get_url(g->bw),
+ browser_window_access_url(g->bw),
NULL, g->bw, NULL);
if (error != NSERROR_OK) {
@@ -1102,7 +1123,7 @@ ro_gui_window_scroll_action(struct gui_window *g,
step_x = SCROLL_TOP;
break;
default:
- step_x = (visible_x * (scroll_x>>2)) >> 2;
+ step_x = (32 * (scroll_x / 4));
break;
}
@@ -1128,7 +1149,7 @@ ro_gui_window_scroll_action(struct gui_window *g,
step_y = SCROLL_TOP;
break;
default:
- step_y = -((visible_y * (scroll_y>>2)) >> 2);
+ step_y = -(32 * (scroll_y / 4));
break;
}
@@ -1142,10 +1163,12 @@ ro_gui_window_scroll_action(struct gui_window *g,
*/
if (pointer.w == g->window &&
- ro_gui_window_to_window_pos(g,
- pointer.pos.x, pointer.pos.y, &pos))
- handled = browser_window_scroll_at_point(g->bw, pos.x, pos.y,
- step_x, step_y);
+ ro_gui_window_to_window_pos(g, pointer.pos.x, pointer.pos.y, &pos))
+ handled = browser_window_scroll_at_point(g->bw,
+ pos.x,
+ pos.y,
+ step_x,
+ step_y);
/* If the core didn't do the scrolling, handle it via the Wimp.
* Windows which contain frames can only be scrolled by the core,
@@ -1197,6 +1220,52 @@ ro_gui_window_scroll_action(struct gui_window *g,
}
}
+/**
+ * handle scale kepresses within RISC OS
+ */
+static bool handle_local_keypress_scale(struct gui_window *gw, uint32_t c)
+{
+ float cscale; /* current scale */
+ float scale; /* new scale */
+
+ cscale = browser_window_get_scale(gw->bw);
+
+ scale = cscale;
+
+ if (ro_gui_shift_pressed() && c == 17) {
+ scale = cscale - 0.1;
+ } else if (ro_gui_shift_pressed() && c == 23) {
+ scale = cscale + 0.1;
+ } else if (c == 17) {
+ for (int i = SCALE_SNAP_TO_SIZE - 1; i >= 0; i--) {
+ if (scale_snap_to[i] < cscale) {
+ scale = scale_snap_to[i];
+ break;
+ }
+ }
+ } else {
+ for (unsigned int i = 0; i < SCALE_SNAP_TO_SIZE; i++) {
+ if (scale_snap_to[i] > cscale) {
+ scale = scale_snap_to[i];
+ break;
+ }
+ }
+ }
+
+ if (scale < scale_snap_to[0]) {
+ scale = scale_snap_to[0];
+ }
+
+ if (scale > scale_snap_to[SCALE_SNAP_TO_SIZE - 1]) {
+ scale = scale_snap_to[SCALE_SNAP_TO_SIZE - 1];
+ }
+
+ if (cscale != scale) {
+ ro_gui_window_set_scale(gw, scale);
+ }
+
+ return true;
+}
/**
* Handle keypresses within the RISC OS GUI
@@ -1219,7 +1288,6 @@ ro_gui_window_handle_local_keypress(struct gui_window *g,
os_error *ro_error;
wimp_pointer pointer;
os_coord pos;
- float scale;
uint32_t c = (uint32_t) key->c;
wimp_scroll_direction xscroll = wimp_SCROLL_NONE;
wimp_scroll_direction yscroll = wimp_SCROLL_NONE;
@@ -1245,7 +1313,7 @@ ro_gui_window_handle_local_keypress(struct gui_window *g,
case IS_WIMP_KEY + wimp_KEY_F1: /* Help. */
{
nserror error = nsurl_create(
- "http://www.netsurf-browser.org/documentation/",
+ "https://www.netsurf-browser.org/documentation/",
&url);
if (error == NSERROR_OK) {
error = browser_window_create(BW_CREATE_HISTORY,
@@ -1359,8 +1427,7 @@ ro_gui_window_handle_local_keypress(struct gui_window *g,
if (is_toolbar) {
const char *toolbar_url;
toolbar_url = ro_toolbar_get_url(g->toolbar);
- if (toolbar_url != NULL)
- ro_gui_window_launch_url(g, toolbar_url);
+ ro_gui_window_launch_url(g, toolbar_url);
}
return true;
@@ -1380,34 +1447,10 @@ ro_gui_window_handle_local_keypress(struct gui_window *g,
case 17: /* CTRL+Q (Zoom out) */
case 23: /* CTRL+W (Zoom in) */
- if (browser_window_has_content(g->bw) == false)
- break;
- scale = g->scale;
- if (ro_gui_shift_pressed() && c == 17)
- scale = g->scale - 0.1;
- else if (ro_gui_shift_pressed() && c == 23)
- scale = g->scale + 0.1;
- else if (c == 17) {
- for (int i = SCALE_SNAP_TO_SIZE - 1; i >= 0; i--)
- if (scale_snap_to[i] < g->scale) {
- scale = scale_snap_to[i];
- break;
- }
- } else {
- for (unsigned int i = 0; i < SCALE_SNAP_TO_SIZE; i++)
- if (scale_snap_to[i] > g->scale) {
- scale = scale_snap_to[i];
- break;
- }
- }
- if (scale < scale_snap_to[0])
- scale = scale_snap_to[0];
- if (scale > scale_snap_to[SCALE_SNAP_TO_SIZE - 1])
- scale = scale_snap_to[SCALE_SNAP_TO_SIZE - 1];
- if (g->scale != scale) {
- ro_gui_window_set_scale(g, scale);
+ if (browser_window_has_content(g->bw) == true) {
+ return handle_local_keypress_scale(g, c);
}
- return true;
+ break;
case IS_WIMP_KEY + wimp_KEY_PRINT:
ro_gui_window_action_print(g);
@@ -1552,7 +1595,7 @@ static void ro_gui_window_close(wimp_w w)
if (pointer.buttons & wimp_CLICK_ADJUST) {
destroy = !ro_gui_shift_pressed();
- url = browser_window_get_url(g->bw);
+ url = browser_window_access_url(g->bw);
if (url != NULL) {
netsurf_nsurl_to_path(url, &filename);
}
@@ -1597,6 +1640,57 @@ static void ro_gui_window_close(wimp_w w)
}
}
+/**
+ * Wrapper for calls to browser_window_redraw for a wimp_draw rectangle.
+ *
+ * \param[in] gui_win Window to render.
+ * \param[in] wimp_rect The area of gui_win to render into.
+ * \param[in] use_buffer Whether to use buffered rendering.
+ */
+static inline void ro_gui_window__redraw_rect(
+ const struct gui_window *gui_win,
+ const wimp_draw *wimp_rect,
+ bool use_buffer)
+{
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &ro_plotters
+ };
+ struct rect clip;
+
+ /* OS's redraw request coordinates are in screen coordinates,
+ * with an origin at the bottom left of the screen.
+ * Find the coordinate of the top left of the document in terms
+ * of OS screen coordinates.
+ * NOTE: OS units are 2 per px. */
+ ro_plot_origin_x = wimp_rect->box.x0 - wimp_rect->xscroll;
+ ro_plot_origin_y = wimp_rect->box.y1 - wimp_rect->yscroll;
+
+ /* Adjust clip rect for origin. */
+ ro_plot_clip_rect.x0 = wimp_rect->clip.x0 - ro_plot_origin_x;
+ ro_plot_clip_rect.y0 = ro_plot_origin_y - wimp_rect->clip.y0;
+ ro_plot_clip_rect.x1 = wimp_rect->clip.x1 - ro_plot_origin_x;
+ ro_plot_clip_rect.y1 = ro_plot_origin_y - wimp_rect->clip.y1;
+
+ /* Convert OS redraw rectangle request coordinates into NetSurf
+ * coordinates. NetSurf coordinates have origin at top left of
+ * document and units are in px. */
+ clip.x0 = (ro_plot_clip_rect.x0 ) / 2; /* left */
+ clip.y0 = (ro_plot_clip_rect.y1 ) / 2; /* top */
+ clip.x1 = (ro_plot_clip_rect.x1 + 1) / 2; /* right */
+ clip.y1 = (ro_plot_clip_rect.y0 + 1) / 2; /* bottom */
+
+ if (use_buffer) {
+ ro_gui_buffer_open(wimp_rect);
+ }
+
+ browser_window_redraw(gui_win->bw, 0, 0, &clip, &ctx);
+
+ if (use_buffer) {
+ ro_gui_buffer_close();
+ }
+}
/**
* Handle a Redraw_Window_Request for a browser window.
@@ -1608,11 +1702,6 @@ static void ro_gui_window_redraw(wimp_draw *redraw)
osbool more;
struct gui_window *g;
os_error *error;
- struct redraw_context ctx = {
- .interactive = true,
- .background_images = true,
- .plot = &ro_plotters
- };
g = (struct gui_window *)ro_gui_wimp_event_get_user_data(redraw->w);
@@ -1633,31 +1722,8 @@ static void ro_gui_window_redraw(wimp_draw *redraw)
return;
}
while (more) {
- struct rect clip;
-
- /* OS's redraw request coordinates are in screen coordinates,
- * with an origin at the bottom left of the screen.
- * Find the coordinate of the top left of the document in terms
- * of OS screen coordinates.
- * NOTE: OS units are 2 per px. */
- ro_plot_origin_x = redraw->box.x0 - redraw->xscroll;
- ro_plot_origin_y = redraw->box.y1 - redraw->yscroll;
-
- /* Convert OS redraw rectangle request coordinates into NetSurf
- * coordinates. NetSurf coordinates have origin at top left of
- * document and units are in px. */
- clip.x0 = (redraw->clip.x0 - ro_plot_origin_x) / 2; /* left */
- clip.y0 = (ro_plot_origin_y - redraw->clip.y1) / 2; /* top */
- clip.x1 = (redraw->clip.x1 - ro_plot_origin_x) / 2; /* right */
- clip.y1 = (ro_plot_origin_y - redraw->clip.y0) / 2; /* bottom */
-
- if (ro_gui_current_redraw_gui->option.buffer_everything)
- ro_gui_buffer_open(redraw);
-
- browser_window_redraw(g->bw, 0, 0, &clip, &ctx);
-
- if (ro_gui_current_redraw_gui->option.buffer_everything)
- ro_gui_buffer_close();
+ ro_gui_window__redraw_rect(g, redraw,
+ ro_gui_current_redraw_gui->option.buffer_everything);
/* Check to see if there are more rectangles to draw and
* get next one */
@@ -1688,37 +1754,48 @@ static void ro_gui_window_redraw(wimp_draw *redraw)
*/
static void ro_gui_window_scroll(wimp_scroll *scroll)
{
- struct gui_window *g = ro_gui_window_lookup(scroll->w);
-
- if (g && browser_window_has_content(g->bw) && ro_gui_shift_pressed()) {
- /* extended scroll request with shift held down; change zoom */
- float scale, inc;
-
- if (scroll->ymin & 3)
- inc = 0.02; /* RO5 sends the msg 5 times;
- * don't ask me why
- *
- * @todo this is liable to break if
- * HID is configured optimally for
- * frame scrolling. *5 appears to be
- * an artifact of non-HID mode scrolling.
- */
- else
- inc = (1 << (ABS(scroll->ymin)>>2)) / 20.0F;
-
- if (scroll->ymin > 0) {
- scale = g->scale + inc;
- if (scale > scale_snap_to[SCALE_SNAP_TO_SIZE - 1])
- scale = scale_snap_to[SCALE_SNAP_TO_SIZE - 1];
- } else {
- scale = g->scale - inc;
- if (scale < scale_snap_to[0])
- scale = scale_snap_to[0];
- }
- if (g->scale != scale)
- ro_gui_window_set_scale(g, scale);
- } else if (g != NULL) {
+ float cscale, scale, inc;
+ struct gui_window *g = ro_gui_window_lookup(scroll->w);
+
+ if (g == NULL) {
+ return;
+ }
+
+ if ((browser_window_has_content(g->bw) == false) ||
+ (ro_gui_shift_pressed() == false)) {
ro_gui_window_scroll_action(g, scroll->xmin, scroll->ymin);
+ return;
+ }
+
+ /* extended scroll request with shift held down; change zoom */
+ cscale = browser_window_get_scale(g->bw);
+
+ if (scroll->ymin & 3) {
+ inc = 0.02; /* RO5 sends the msg 5 times;
+ * don't ask me why
+ *
+ * @todo this is liable to break if
+ * HID is configured optimally for
+ * frame scrolling. *5 appears to be
+ * an artifact of non-HID mode scrolling.
+ */
+ } else {
+ inc = (1 << (ABS(scroll->ymin)>>2)) / 20.0F;
+ }
+
+ if (scroll->ymin > 0) {
+ scale = cscale + inc;
+ if (scale > scale_snap_to[SCALE_SNAP_TO_SIZE - 1]) {
+ scale = scale_snap_to[SCALE_SNAP_TO_SIZE - 1];
+ }
+ } else {
+ scale = cscale - inc;
+ if (scale < scale_snap_to[0]) {
+ scale = scale_snap_to[0];
+ }
+ }
+ if (scale != cscale) {
+ ro_gui_window_set_scale(g, scale);
}
}
@@ -2498,7 +2575,7 @@ ro_gui_window_menu_select(wimp_w w,
/* help actions */
case HELP_OPEN_CONTENTS:
- error = nsurl_create("http://www.netsurf-browser.org/documentation/", &url);
+ error = nsurl_create("https://www.netsurf-browser.org/documentation/", &url);
if (error == NSERROR_OK) {
error = browser_window_create(BW_CREATE_HISTORY,
url,
@@ -2510,7 +2587,7 @@ ro_gui_window_menu_select(wimp_w w,
break;
case HELP_OPEN_GUIDE:
- error = nsurl_create("http://www.netsurf-browser.org/documentation/guide", &url);
+ error = nsurl_create("https://www.netsurf-browser.org/documentation/guide", &url);
if (error == NSERROR_OK) {
error = browser_window_create(BW_CREATE_HISTORY,
url,
@@ -2522,7 +2599,7 @@ ro_gui_window_menu_select(wimp_w w,
break;
case HELP_OPEN_INFORMATION:
- error = nsurl_create("http://www.netsurf-browser.org/documentation/info", &url);
+ error = nsurl_create("https://www.netsurf-browser.org/documentation/info", &url);
if (error == NSERROR_OK) {
error = browser_window_create(BW_CREATE_HISTORY,
url,
@@ -2585,7 +2662,7 @@ ro_gui_window_menu_select(wimp_w w,
/* cookies actions */
case COOKIES_SHOW:
- ro_gui_cookies_present();
+ ro_gui_cookies_present(NULL);
break;
case COOKIES_DELETE:
@@ -2671,7 +2748,7 @@ ro_gui_window_menu_select(wimp_w w,
error = browser_window_navigate(
bw,
current_menu_url,
- browser_window_get_url(bw),
+ browser_window_access_url(bw),
BW_NAVIGATE_DOWNLOAD,
NULL,
NULL,
@@ -2684,7 +2761,7 @@ ro_gui_window_menu_select(wimp_w w,
error = browser_window_create(
BW_CREATE_HISTORY | BW_CREATE_CLONE,
current_menu_url,
- browser_window_get_url(bw),
+ browser_window_access_url(bw),
bw,
NULL);
}
@@ -3221,7 +3298,6 @@ static struct gui_window *gui_window_create(struct browser_window *bw,
g->active = false;
strcpy(g->title, "NetSurf");
g->iconise_icon = -1;
- g->scale = browser_window_get_scale(bw);
/* Set the window position */
if (existing != NULL &&
@@ -3502,20 +3578,25 @@ static void gui_window_destroy(struct gui_window *g)
*/
static void gui_window_set_title(struct gui_window *g, const char *title)
{
+ float scale;
assert(g);
assert(title);
- if (g->scale != 1.0) {
- int scale_disp = g->scale * 100;
+ scale = browser_window_get_scale(g->bw);
+
+ if (scale != 1.0) {
+ int scale_disp = scale * 100;
- if (ABS((float)scale_disp - g->scale * 100) >= 0.05)
+ if (ABS((float)scale_disp - scale * 100) >= 0.05) {
snprintf(g->title, sizeof g->title, "%s (%.1f%%)",
- title, g->scale * 100);
- else
+ title, scale * 100);
+ } else {
snprintf(g->title, sizeof g->title, "%s (%i%%)",
title, scale_disp);
+ }
} else {
- strncpy(g->title, title, sizeof g->title);
+ strncpy(g->title, title, sizeof(g->title) - 1);
+ g->title[sizeof(g->title)-1] = 0;
}
ro_gui_set_window_title(g->window, g->title);
@@ -3547,10 +3628,11 @@ static bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
return false;
}
- if (g->toolbar)
+ if (g->toolbar) {
toolbar_height = ro_toolbar_full_height(g->toolbar);
- *sx = state.xscroll / (2 * g->scale);
- *sy = -(state.yscroll - toolbar_height) / (2 * g->scale);
+ }
+ *sx = state.xscroll / 2;
+ *sy = -(state.yscroll - toolbar_height) / 2;
return true;
}
@@ -3589,8 +3671,8 @@ gui_window_set_scroll(struct gui_window *g, const struct rect *rect)
if ((rect->x0 == rect->x1) && (rect->y0 == rect->y1)) {
/* scroll to top */
- state.xscroll = rect->x0 * 2 * g->scale;
- state.yscroll = (-rect->y0 * 2 * g->scale) + toolbar_height;
+ state.xscroll = rect->x0 * 2;
+ state.yscroll = (-rect->y0 * 2) + toolbar_height;
} else {
/* scroll area into view with padding */
int x0, y0, x1, y1;
@@ -3598,10 +3680,10 @@ gui_window_set_scroll(struct gui_window *g, const struct rect *rect)
int padding_available;
int correction;
- x0 = rect->x0 * 2 * g->scale;
- y0 = rect->y0 * 2 * g->scale;
- x1 = rect->x1 * 2 * g->scale;
- y1 = rect->y1 * 2 * g->scale;
+ x0 = rect->x0 * 2 ;
+ y0 = rect->y0 * 2 ;
+ x1 = rect->x1 * 2 ;
+ y1 = rect->y1 * 2 ;
cx0 = state.xscroll;
cy0 = -state.yscroll + toolbar_height;
@@ -3669,21 +3751,15 @@ gui_window_set_scroll(struct gui_window *g, const struct rect *rect)
* \param gw gui window to measure
* \param width receives width of window
* \param height receives height of window
- * \param scaled whether to return scaled values
+ * \return NSERROR_OK and width and height updated
*/
static nserror
-gui_window_get_dimensions(struct gui_window *gw,
- int *width, int *height,
- bool scaled)
+gui_window_get_dimensions(struct gui_window *gw, int *width, int *height)
{
/* use the cached window sizes */
*width = gw->old_width / 2;
*height = gw->old_height / 2;
- if (scaled) {
- *width /= gw->scale;
- *height /= gw->scale;
- }
return NSERROR_OK;
}
@@ -3717,7 +3793,6 @@ static void gui_window_start_throbber(struct gui_window *g)
}
-
/**
* Update the interface to reflect page loading stopped.
*
@@ -3732,6 +3807,20 @@ static void gui_window_stop_throbber(struct gui_window *g)
g->active = false;
}
+
+/**
+ * Update the interface to reflect change in page info status
+ *
+ * \param gw window with start of load
+ */
+static void gui_window_page_info_change(struct gui_window *gw)
+{
+ if (gw->toolbar != NULL) {
+ ro_toolbar_page_info_change(gw->toolbar);
+ }
+}
+
+
/**
* set favicon
*/
@@ -3745,7 +3834,6 @@ gui_window_set_icon(struct gui_window *g, struct hlcache_handle *icon)
}
-
/**
* Remove the caret, if present.
*
@@ -3825,8 +3913,9 @@ static void ro_gui_window_scroll_end(wimp_dragged *drag, void *data)
ro_warn_user("WimpError", error->errmess);
}
- if (ro_gui_window_to_window_pos(g, drag->final.x0, drag->final.y0, &pos))
+ if (ro_gui_window_to_window_pos(g, drag->final.x0, drag->final.y0, &pos)) {
browser_window_mouse_track(g->bw, 0, pos.x, pos.y);
+ }
}
@@ -3905,6 +3994,7 @@ gui_window_drag_start(struct gui_window *g,
{
wimp_pointer pointer;
wimp_drag drag;
+ float scale = browser_window_get_scale(g->bw);
if (rect != NULL) {
/* We have a box to constrain the pointer to, for the drag
@@ -3921,13 +4011,13 @@ gui_window_drag_start(struct gui_window *g,
drag.type = wimp_DRAG_USER_POINT;
drag.bbox.x0 = pointer.pos.x +
- (int)(rect->x0 * 2 * g->scale);
+ (int)(rect->x0 * 2 * scale);
drag.bbox.y0 = pointer.pos.y +
- (int)(rect->y0 * 2 * g->scale);
+ (int)(rect->y0 * 2 * scale);
drag.bbox.x1 = pointer.pos.x +
- (int)(rect->x1 * 2 * g->scale);
+ (int)(rect->x1 * 2 * scale);
drag.bbox.y1 = pointer.pos.y +
- (int)(rect->y1 * 2 * g->scale);
+ (int)(rect->y1 * 2 * scale);
error = xwimp_drag_box(&drag);
if (error) {
@@ -3941,8 +4031,9 @@ gui_window_drag_start(struct gui_window *g,
switch (type) {
case GDRAGGING_SCROLLBAR:
/* Dragging a core scrollbar */
- ro_mouse_drag_start(ro_gui_window_scroll_end, ro_gui_window_mouse_at,
- NULL, g);
+ ro_mouse_drag_start(ro_gui_window_scroll_end,
+ ro_gui_window_mouse_at,
+ NULL, g);
break;
default:
@@ -4087,6 +4178,57 @@ ro_gui_window_import_text(struct gui_window *g, const char *filename)
/**
+ * process miscellaneous window events
+ *
+ * \param gw The window receiving the event.
+ * \param event The event code.
+ * \return NSERROR_OK when processed ok
+ */
+static nserror
+ro_gui_window_event(struct gui_window *gw, enum gui_window_event event)
+{
+ switch (event) {
+ case GW_EVENT_UPDATE_EXTENT:
+ gui_window_update_extent(gw);
+ break;
+
+ case GW_EVENT_REMOVE_CARET:
+ gui_window_remove_caret(gw);
+ break;
+
+ case GW_EVENT_SCROLL_START:
+ gui_window_scroll_start(gw);
+ break;
+
+ case GW_EVENT_NEW_CONTENT:
+ gui_window_new_content(gw);
+ break;
+
+ case GW_EVENT_START_THROBBER:
+ gui_window_start_throbber(gw);
+ break;
+
+ case GW_EVENT_STOP_THROBBER:
+ gui_window_stop_throbber(gw);
+ break;
+
+ case GW_EVENT_START_SELECTION:
+ /* from textselection */
+ gui_start_selection(gw);
+ break;
+
+ case GW_EVENT_PAGE_INFO_CHANGE:
+ gui_window_page_info_change(gw);
+ break;
+
+ default:
+ break;
+ }
+ return NSERROR_OK;
+}
+
+
+/**
* RISC OS browser window operation table
*/
static struct gui_window_table window_table = {
@@ -4096,7 +4238,7 @@ static struct gui_window_table window_table = {
.get_scroll = gui_window_get_scroll,
.set_scroll = gui_window_set_scroll,
.get_dimensions = gui_window_get_dimensions,
- .update_extent = gui_window_update_extent,
+ .event = ro_gui_window_event,
.set_title = gui_window_set_title,
.set_url = ro_gui_window_set_url,
@@ -4104,21 +4246,13 @@ static struct gui_window_table window_table = {
.set_status = riscos_window_set_status,
.set_pointer = gui_window_set_pointer,
.place_caret = gui_window_place_caret,
- .remove_caret = gui_window_remove_caret,
.save_link = gui_window_save_link,
.drag_start = gui_window_drag_start,
- .scroll_start = gui_window_scroll_start,
- .new_content = gui_window_new_content,
- .start_throbber = gui_window_start_throbber,
- .stop_throbber = gui_window_stop_throbber,
.create_form_select_menu = gui_window_create_form_select_menu,
/* from save */
.drag_save_object = gui_drag_save_object,
.drag_save_selection =gui_drag_save_selection,
-
- /* from textselection */
- .start_selection = gui_start_selection,
};
struct gui_window_table *riscos_window_table = &window_table;
@@ -4268,10 +4402,10 @@ ro_gui_window_invalidate_area(struct gui_window *g, const struct rect *rect)
return NSERROR_OK;
}
- x0 = floorf(rect->x0 * 2 * g->scale);
- y0 = -ceilf(rect->y1 * 2 * g->scale);
- x1 = ceilf(rect->x1 * 2 * g->scale) + 1;
- y1 = -floorf(rect->y0 * 2 * g->scale) + 1;
+ x0 = floorf(rect->x0 * 2 );
+ y0 = -ceilf(rect->y1 * 2 );
+ x1 = ceilf(rect->x1 * 2 ) + 1;
+ y1 = -floorf(rect->y0 * 2 ) + 1;
use_buffer =
(g->option.buffer_everything || g->option.buffer_animations);
@@ -4339,7 +4473,6 @@ nserror ro_gui_window_set_url(struct gui_window *g, nsurl *url)
/* exported interface documented in riscos/window.h */
void ro_gui_window_set_scale(struct gui_window *g, float scale)
{
- g->scale = scale;
browser_window_set_scale(g->bw, scale, true);
}
@@ -4382,11 +4515,14 @@ void ro_gui_window_mouse_at(wimp_pointer *pointer, void *data)
os_coord pos;
struct gui_window *g = (struct gui_window *) data;
- if (ro_gui_window_to_window_pos(g, pointer->pos.x, pointer->pos.y, &pos))
- browser_window_mouse_track(g->bw,
- ro_gui_mouse_drag_state(pointer->buttons,
+ if (ro_gui_window_to_window_pos(g, pointer->pos.x, pointer->pos.y, &pos)) {
+ browser_window_mouse_track(
+ g->bw,
+ ro_gui_mouse_drag_state(pointer->buttons,
wimp_BUTTON_DOUBLE_CLICK_DRAG),
- pos.x, pos.y);
+ pos.x,
+ pos.y);
+ }
}
@@ -4434,7 +4570,7 @@ ro_gui_window_iconise(struct gui_window *g, wimp_full_message_window_info *wi)
/* create the thumbnail sprite */
bitmap = riscos_bitmap_create(width, height,
- BITMAP_NEW | BITMAP_OPAQUE | BITMAP_CLEAR_MEMORY);
+ BITMAP_OPAQUE | BITMAP_CLEAR);
if (!bitmap) {
NSLOG(netsurf, INFO, "Thumbnail initialisation failed.");
return;
@@ -4559,22 +4695,15 @@ void ro_gui_window_redraw_all(void)
}
}
-
/* exported interface documented in riscos/window.h */
void ro_gui_window_update_boxes(void)
{
osbool more;
bool use_buffer;
wimp_draw update;
- struct rect clip;
os_error *error;
struct update_box *cur;
struct gui_window *g;
- struct redraw_context ctx = {
- .interactive = true,
- .background_images = true,
- .plot = &ro_plotters
- };
for (cur = pending_updates; cur != NULL; cur = cur->next) {
g = cur->g;
@@ -4600,22 +4729,8 @@ void ro_gui_window_update_boxes(void)
/* Set the current redraw gui_window to get options from */
ro_gui_current_redraw_gui = g;
- ro_plot_origin_x = update.box.x0 - update.xscroll;
- ro_plot_origin_y = update.box.y1 - update.yscroll;
-
while (more) {
- clip.x0 = (update.clip.x0 - ro_plot_origin_x) / 2;
- clip.y0 = (ro_plot_origin_y - update.clip.y1) / 2;
- clip.x1 = (update.clip.x1 - ro_plot_origin_x) / 2;
- clip.y1 = (ro_plot_origin_y - update.clip.y0) / 2;
-
- if (use_buffer)
- ro_gui_buffer_open(&update);
-
- browser_window_redraw(g->bw, 0, 0, &clip, &ctx);
-
- if (use_buffer)
- ro_gui_buffer_close();
+ ro_gui_window__redraw_rect(g, &update, use_buffer);
error = xwimp_get_rectangle(&update, &more);
/* RISC OS 3.7 returns an error here if enough buffer
@@ -4676,17 +4791,19 @@ void ro_gui_throb(void)
/* exported interface documented in riscos/window.h */
void ro_gui_window_default_options(struct gui_window *gui)
{
+ float cscale;
+
if (gui == NULL)
return;
- /* Save the basic options
- */
- nsoption_set_int(scale, gui->scale * 100);
+ cscale = browser_window_get_scale(gui->bw);
+
+ /* Save the basic options */
+ nsoption_set_int(scale, cscale * 100);
nsoption_set_bool(buffer_animations, gui->option.buffer_animations);
nsoption_set_bool(buffer_everything, gui->option.buffer_everything);
- /* Set up the toolbar
- */
+ /* Set up the toolbar */
if (gui->toolbar != NULL) {
nsoption_set_bool(toolbar_show_buttons,
ro_toolbar_get_display_buttons(gui->toolbar));
@@ -4695,9 +4812,10 @@ void ro_gui_window_default_options(struct gui_window *gui)
nsoption_set_bool(toolbar_show_throbber,
ro_toolbar_get_display_throbber(gui->toolbar));
}
- if (gui->status_bar != NULL)
+ if (gui->status_bar != NULL) {
nsoption_set_int(toolbar_status_size,
ro_gui_status_bar_get_width(gui->status_bar));
+ }
}
@@ -4749,33 +4867,8 @@ ro_gui_window_to_window_pos(struct gui_window *g, int x, int y, os_coord *pos)
ro_warn_user("WimpError", error->errmess);
return false;
}
- pos->x = (x - (state.visible.x0 - state.xscroll)) / 2 / g->scale;
- pos->y = ((state.visible.y1 - state.yscroll) - y) / 2 / g->scale;
- return true;
-}
-
-
-/* exported interface documented in riscos/window.h */
-bool ro_gui_window_to_screen_pos(struct gui_window *g,
- int x,
- int y,
- os_coord *pos)
-{
- wimp_window_state state;
- os_error *error;
-
- assert(g);
-
- state.w = g->window;
- error = xwimp_get_window_state(&state);
- if (error) {
- NSLOG(netsurf, INFO, "xwimp_get_window_state: 0x%x:%s",
- error->errnum, error->errmess);
- ro_warn_user("WimpError", error->errmess);
- return false;
- }
- pos->x = (x * 2 * g->scale) + (state.visible.x0 - state.xscroll);
- pos->y = (state.visible.y1 - state.yscroll) - (y * 2 * g->scale);
+ pos->x = (x - (state.visible.x0 - state.xscroll)) / 2 ;
+ pos->y = ((state.visible.y1 - state.yscroll) - y) / 2 ;
return true;
}
diff --git a/frontends/riscos/window.h b/frontends/riscos/window.h
index 0a5bd43c2..c3325a7a4 100644
--- a/frontends/riscos/window.h
+++ b/frontends/riscos/window.h
@@ -192,17 +192,6 @@ bool ro_gui_window_to_window_pos(struct gui_window *g, int x, int y, os_coord *p
/**
- * Convert x,y window co-ordinates into screen co-ordinates.
- *
- * \param g gui window
- * \param x x ordinate
- * \param y y ordinate
- * \param pos receives position in screen co-ordinatates
- * \return true iff conversion successful
- */
-bool ro_gui_window_to_screen_pos(struct gui_window *g, int x, int y, os_coord *pos);
-
-/**
* Returns the state of the mouse buttons and modifiers keys for a
* mouse action, suitable for passing to the OS-independent
* browser window/ treeview/ etc code.
diff --git a/frontends/windows/Makefile b/frontends/windows/Makefile
index de01ce33a..524f716fe 100644
--- a/frontends/windows/Makefile
+++ b/frontends/windows/Makefile
@@ -33,11 +33,15 @@ WSCFLAGS := -std=c99 -Dnswin32 -DCURL_STATICLIB -DCARES_STATICLIB -g
CFLAGS += $(WSCFLAGS)
LDFLAGS += $(WSCFLAGS)
+# The filter and target for split messages
+MESSAGES_FILTER=win
+MESSAGES_TARGET=$(FRONTEND_RESOURCES_DIR)
+
# ----------------------------------------------------------------------------
# built-in resource setup
# ----------------------------------------------------------------------------
-$(OBJROOT)/windows_resource.o: $(FRONTEND_RESOURCES_DIR)/resource.rc
+$(OBJROOT)/windows_resource.o: $(FRONTEND_RESOURCES_DIR)/resource.rc $(addsuffix /Messages,$(addprefix $(MESSAGES_TARGET)/,$(MESSAGES_LANGUAGES)))
$(VQ)echo " WINDRES: compiling windows resources"
${Q}$(WINDRES) $< -O coff -o $@
@@ -48,10 +52,10 @@ S_RESOURCES := windows_resource.o
# ----------------------------------------------------------------------------
# sources purely for the windows build
-S_FRONTEND := main.c window.c gui.c drawable.c plot.c findfile.c \
- font.c bitmap.c about.c prefs.c download.c filetype.c file.c \
+S_FRONTEND := main.c window.c gui.c clipboard.c drawable.c plot.c findfile.c \
+ font.c bitmap.c about.c prefs.c download.c fetch.c file.c \
local_history.c schedule.c windbg.c pointers.c \
- corewindow.c hotlist.c cookies.c global_history.c ssl_cert.c
+ corewindow.c hotlist.c cookies.c global_history.c
# This is the final source build list
# Note this is deliberately *not* expanded here as common and image
@@ -82,12 +86,11 @@ NSIS_VERBOSE := 0
endif
# installer messages generation
-$(OBJROOT)/messages-en: resources/FatMessages
- $(VQ)echo "MSGSPLIT: Language: en Filter: win"
- $(Q)$(RM) $@
- $(Q)$(SPLIT_MESSAGES) -l en -p win -f messages -o $@ $<
+$(OBJROOT)/messages-en: $(MESSAGES_TARGET)/en/Messages
+ $(VQ)echo " MSGCP: $< $@"
+ $(Q)$(INSTALL) -m 644 -T $< $@
-netsurf-installer.exe: $(EXETARGET) $(WIN_RES_INS_OBJ)
+netsurf-installer.exe: $(EXETARGET) $(POSTEXES) $(WIN_RES_INS_OBJ)
$(VQ)echo "MAKENSIS: $@"
$(Q)makensis -V$(NSIS_VERBOSE) -NOCD -DOBJROOT=$(OBJROOT) -DRESDIR=$(FRONTEND_RESOURCES_DIR) -DVERSIONMAJOR=$(VERSION_MAJ) -DVERSIONMINOR=$(VERSION_MIN) -DOUTFNAME=$@ $(FRONTEND_RESOURCES_DIR)/installer.nsi
diff --git a/frontends/windows/Makefile.defaults b/frontends/windows/Makefile.defaults
index 1d844f112..51e71accb 100644
--- a/frontends/windows/Makefile.defaults
+++ b/frontends/windows/Makefile.defaults
@@ -3,8 +3,8 @@
# ----------------------------------------------------------------------------
# Where to search for NetSurf's resources after looking in ~/.netsurf and
-# $NETSURFRES. It must have a trailing backslash
-NETSURF_WINDOWS_RESPATH :=
+# ${APPDATA}\NetSurf. It must have a trailing backslash
+NETSURF_WINDOWS_RESPATH := $${NETSURFRES}
# Enable NetSurf's use of librosprite for displaying RISC OS Sprites
# Valid options: YES, NO, AUTO
diff --git a/frontends/windows/Makefile.tools b/frontends/windows/Makefile.tools
new file mode 100644
index 000000000..24f0f7fbd
--- /dev/null
+++ b/frontends/windows/Makefile.tools
@@ -0,0 +1,19 @@
+# -*- mode: makefile-gmake -*-
+##
+## windows (win32) target tool setup
+##
+
+ifneq ($(HOST),windows)
+ # Set Mingw defaults
+ GCCSDK_INSTALL_ENV ?= /opt/netsurf/i686-w64-mingw32/env
+ GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/i686-w64-mingw32/cross/bin
+
+ CC := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc)
+ WINDRES := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*windres)
+
+ PKG_CONFIG := PKG_CONFIG_LIBDIR="$(GCCSDK_INSTALL_ENV)/lib/pkgconfig" pkg-config
+else
+ # Building on Windows
+ CC := gcc
+ PKG_CONFIG := pkg-config
+endif
diff --git a/frontends/windows/about.c b/frontends/windows/about.c
index 2cd855b55..325587d8a 100644
--- a/frontends/windows/about.c
+++ b/frontends/windows/about.c
@@ -139,9 +139,9 @@ nsws_about_event_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
return FALSE;
}
-void nsws_about_dialog_init(HINSTANCE hinst, HWND parent)
+void nsw32_about_dialog_init(HINSTANCE hinst, HWND parent)
{
- int ret = DialogBox(hinst, MAKEINTRESOURCE(IDD_DLG_ABOUT), parent,
+ int ret = DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUT), parent,
nsws_about_event_callback);
if (ret == -1) {
win32_warning(messages_get("NoMemory"), 0);
diff --git a/frontends/windows/about.h b/frontends/windows/about.h
index e0315b507..807c7b900 100644
--- a/frontends/windows/about.h
+++ b/frontends/windows/about.h
@@ -16,9 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_WINDOWS_ABOUT_H_
-#define _NETSURF_WINDOWS_ABOUT_H_
+#ifndef NETSURF_WINDOWS_ABOUT_H
+#define NETSURF_WINDOWS_ABOUT_H
-void nsws_about_dialog_init(HINSTANCE hinst, HWND parent);
+void nsw32_about_dialog_init(HINSTANCE hinst, HWND parent);
#endif
diff --git a/frontends/windows/bitmap.c b/frontends/windows/bitmap.c
index eed3d3a15..a52f29ad9 100644
--- a/frontends/windows/bitmap.c
+++ b/frontends/windows/bitmap.c
@@ -41,19 +41,19 @@
* Create a bitmap.
*
* \param width width of image in pixels
- * \param height width of image in pixels
- * \param state a flag word indicating the initial state
+ * \param height height of image in pixels
+ * \param state flags flags for bitmap creation
* \return an opaque struct bitmap, or NULL on memory exhaustion
*/
-void *win32_bitmap_create(int width, int height, unsigned int state)
+static void *win32_bitmap_create(int width, int height, enum gui_bitmap_flags flags)
{
struct bitmap *bitmap;
BITMAPV5HEADER *pbmi;
HBITMAP windib;
uint8_t *pixdata;
- NSLOG(netsurf, INFO, "width %d, height %d, state %u", width, height,
- state);
+ NSLOG(netsurf, INFO, "width %d, height %d, flags %u", width, height,
+ (unsigned)flags);
pbmi = calloc(1, sizeof(BITMAPV5HEADER));
if (pbmi == NULL) {
@@ -91,7 +91,7 @@ void *win32_bitmap_create(int width, int height, unsigned int state)
bitmap->windib = windib;
bitmap->pbmi = pbmi;
bitmap->pixdata = pixdata;
- if ((state & BITMAP_OPAQUE) != 0) {
+ if ((flags & BITMAP_OPAQUE) != 0) {
bitmap->opaque = true;
} else {
bitmap->opaque = false;
@@ -164,20 +164,6 @@ void win32_bitmap_destroy(void *bitmap)
/**
- * Save a bitmap in the platform's native format.
- *
- * \param bitmap a bitmap, as returned by bitmap_create()
- * \param path pathname for file
- * \param flags flags controlling how the bitmap is saved.
- * \return true on success, false on error and error reported
- */
-static bool bitmap_save(void *bitmap, const char *path, unsigned flags)
-{
- return true;
-}
-
-
-/**
* The bitmap image has changed, so flush any persistant cache.
*
* \param bitmap a bitmap, as returned by bitmap_create()
@@ -207,35 +193,6 @@ static void bitmap_set_opaque(void *bitmap, bool opaque)
/**
- * Tests whether a bitmap has an opaque alpha channel
- *
- * \param bitmap a bitmap, as returned by bitmap_create()
- * \return whether the bitmap is opaque
- */
-static bool bitmap_test_opaque(void *bitmap)
-{
- int tst;
- struct bitmap *bm = bitmap;
-
- if (bitmap == NULL) {
- NSLOG(netsurf, INFO, "NULL bitmap!");
- return false;
- }
-
- tst = bm->width * bm->height;
-
- while (tst-- > 0) {
- if (bm->pixdata[(tst << 2) + 3] != 0xff) {
- NSLOG(netsurf, INFO, "bitmap %p has transparency", bm);
- return false;
- }
- }
- NSLOG(netsurf, INFO, "bitmap %p is opaque", bm);
- return true;
-}
-
-
-/**
* Gets whether a bitmap should be plotted opaque
*
* \param bitmap a bitmap, as returned by bitmap_create()
@@ -276,11 +233,6 @@ static int bitmap_get_height(void *bitmap)
return(bm->height);
}
-static size_t bitmap_get_bpp(void *bitmap)
-{
- return 4;
-}
-
struct bitmap *bitmap_scale(struct bitmap *prescale, int width, int height)
{
struct bitmap *ret = malloc(sizeof(struct bitmap));
@@ -346,7 +298,7 @@ bitmap_render(struct bitmap *bitmap, struct hlcache_handle *content)
}
/* create a full size bitmap and plot into it */
- fsbitmap = win32_bitmap_create(width, height, BITMAP_NEW | BITMAP_CLEAR_MEMORY | BITMAP_OPAQUE);
+ fsbitmap = win32_bitmap_create(width, height, BITMAP_CLEAR | BITMAP_OPAQUE);
SelectObject(bufferdc, fsbitmap->windib);
@@ -375,13 +327,10 @@ static struct gui_bitmap_table bitmap_table = {
.destroy = win32_bitmap_destroy,
.set_opaque = bitmap_set_opaque,
.get_opaque = bitmap_get_opaque,
- .test_opaque = bitmap_test_opaque,
.get_buffer = bitmap_get_buffer,
.get_rowstride = bitmap_get_rowstride,
.get_width = bitmap_get_width,
.get_height = bitmap_get_height,
- .get_bpp = bitmap_get_bpp,
- .save = bitmap_save,
.modified = bitmap_modified,
.render = bitmap_render,
};
diff --git a/frontends/windows/bitmap.h b/frontends/windows/bitmap.h
index c723159e1..a370dd619 100644
--- a/frontends/windows/bitmap.h
+++ b/frontends/windows/bitmap.h
@@ -20,7 +20,7 @@
#ifndef _NETSURF_WINDOWS_BITMAP_H_
#define _NETSURF_WINDOWS_BITMAP_H_
-struct gui_bitmap_table *win32_bitmap_table;
+extern struct gui_bitmap_table *win32_bitmap_table;
struct bitmap {
HBITMAP windib;
@@ -33,8 +33,6 @@ struct bitmap {
struct bitmap *bitmap_scale(struct bitmap *prescale, int width, int height);
-void *win32_bitmap_create(int width, int height, unsigned int state);
-
void win32_bitmap_destroy(void *bitmap);
#endif
diff --git a/frontends/windows/clipboard.c b/frontends/windows/clipboard.c
new file mode 100644
index 000000000..bc52a4594
--- /dev/null
+++ b/frontends/windows/clipboard.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2019 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * win32 clipboard implementation.
+ */
+
+#include <windows.h>
+
+#include "utils/log.h"
+#include "netsurf/clipboard.h"
+
+#include "windows/clipboard.h"
+
+/**
+ * Core asks front end for clipboard contents.
+ *
+ * \param buffer UTF-8 text, allocated by front end, ownership yeilded to core
+ * \param length Byte length of UTF-8 text in buffer
+ */
+static void gui_get_clipboard(char **buffer, size_t *length)
+{
+ HANDLE clipboard_handle;
+ wchar_t *content;
+
+ if (OpenClipboard(NULL)) {
+ clipboard_handle = GetClipboardData(CF_UNICODETEXT);
+ if (clipboard_handle != NULL) {
+ content = GlobalLock(clipboard_handle);
+ if (content != NULL) {
+ int required_len;
+ size_t content_len;
+
+ content_len = wcslen(content);
+
+ /* compute length */
+ required_len = WideCharToMultiByte(
+ CP_UTF8,
+ WC_NO_BEST_FIT_CHARS,
+ content,
+ content_len,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ /* allocate buffer and do conversion */
+ *buffer = malloc(required_len);
+ *length = WideCharToMultiByte(
+ CP_UTF8,
+ WC_NO_BEST_FIT_CHARS,
+ content,
+ content_len,
+ *buffer,
+ required_len,
+ NULL,
+ NULL);
+
+ GlobalUnlock(clipboard_handle);
+ }
+ }
+ CloseClipboard();
+ }
+}
+
+
+/**
+ * Core tells front end to put given text in clipboard
+ *
+ * \param buffer UTF-8 text, owned by core
+ * \param length Byte length of UTF-8 text in buffer
+ * \param styles Array of styles given to text runs, owned by core, or NULL
+ * \param n_styles Number of text run styles in array
+ */
+static void
+gui_set_clipboard(const char *buffer,
+ size_t length,
+ nsclipboard_styles styles[],
+ int n_styles)
+{
+ HGLOBAL hglbCopy;
+ wchar_t *content; /* clipboard content */
+ int content_len; /* characters in content */
+
+ if (OpenClipboard(NULL)) {
+ EmptyClipboard();
+ content_len = MultiByteToWideChar(CP_UTF8,
+ MB_PRECOMPOSED,
+ buffer, length,
+ NULL, 0);
+
+ hglbCopy = GlobalAlloc(GMEM_MOVEABLE,
+ ((content_len + 1) * sizeof(wchar_t)));
+ if (hglbCopy != NULL) {
+ content = GlobalLock(hglbCopy);
+ MultiByteToWideChar(CP_UTF8,
+ MB_PRECOMPOSED,
+ buffer, length,
+ content, content_len);
+ content[content_len] = 0; /* null terminate */
+
+ GlobalUnlock(hglbCopy);
+ SetClipboardData(CF_UNICODETEXT, hglbCopy);
+ }
+ CloseClipboard();
+ }
+}
+
+
+
+static struct gui_clipboard_table clipboard_table = {
+ .get = gui_get_clipboard,
+ .set = gui_set_clipboard,
+};
+
+struct gui_clipboard_table *win32_clipboard_table = &clipboard_table;
diff --git a/frontends/amiga/login.h b/frontends/windows/clipboard.h
index 058fa5948..92f096b8e 100755..100644
--- a/frontends/amiga/login.h
+++ b/frontends/windows/clipboard.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ * Copyright 2019 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,14 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef AMIGA_LOGIN_H
-#define AMIGA_LOGIN_H
+#ifndef NETSURF_WINDOWS_CLIPBOARD_H
+#define NETSURF_WINDOWS_CLIPBOARD_H
-#include <stdbool.h>
-
-struct gui_login_window;
+/**
+ * The clipboard operation function table for win32
+ */
+extern struct gui_clipboard_table *win32_clipboard_table;
-void gui_401login_open(nsurl *url, const char *realm,
- nserror (*cb)(bool proceed, void *pw), void *cbpw);
#endif
-
diff --git a/frontends/windows/cookies.c b/frontends/windows/cookies.c
index b3c56da8c..ee754bc3f 100644
--- a/frontends/windows/cookies.c
+++ b/frontends/windows/cookies.c
@@ -34,6 +34,7 @@
#include "windows/plot.h"
#include "windows/corewindow.h"
#include "windows/cookies.h"
+#include "windows/gui.h"
struct nsw32_cookie_window {
@@ -170,13 +171,16 @@ static nserror nsw32_cookie_init(HINSTANCE hInstance)
/* exported interface documented in windows/cookie.h */
-nserror nsw32_cookies_present(HINSTANCE hInstance)
+nserror nsw32_cookies_present(const char *search_term)
{
nserror res;
- res = nsw32_cookie_init(hInstance);
+ res = nsw32_cookie_init(hinst);
if (res == NSERROR_OK) {
ShowWindow(cookie_window->core.hWnd, SW_SHOWNORMAL);
+ if (search_term != NULL) {
+ res = cookie_manager_set_search_string(search_term);
+ }
}
return res;
}
diff --git a/frontends/windows/cookies.h b/frontends/windows/cookies.h
index 8500c7821..dd7ae4279 100644
--- a/frontends/windows/cookies.h
+++ b/frontends/windows/cookies.h
@@ -35,7 +35,7 @@
*
* \return NSERROR_OK on success else appropriate error code on faliure.
*/
-nserror nsw32_cookies_present(HINSTANCE hinstance);
+nserror nsw32_cookies_present(const char *search_term);
/**
* Free any resources allocated for the cookie window.
diff --git a/frontends/windows/corewindow.c b/frontends/windows/corewindow.c
index 7d88ce7c4..7d6dc69b0 100644
--- a/frontends/windows/corewindow.c
+++ b/frontends/windows/corewindow.c
@@ -443,7 +443,7 @@ nsw32_cw_invalidate_area(struct core_window *cw, const struct rect *rect)
/**
* Callback from the core to update the content area size
*/
-static void
+static nserror
nsw32_cw_update_size(struct core_window *cw, int width, int height)
{
struct nsw32_corewindow *nsw32_cw = (struct nsw32_corewindow *)cw;
@@ -453,13 +453,23 @@ nsw32_cw_update_size(struct core_window *cw, int width, int height)
NSLOG(netsurf, INFO, "new content size w:%d h:%d", width, height);
update_scrollbars(nsw32_cw);
+ return NSERROR_OK;
}
-static void
-nsw32_cw_scroll_visible(struct core_window *cw, const struct rect *r)
+static nserror
+nsw32_cw_set_scroll(struct core_window *cw, int x, int y)
{
/** /todo call setscroll apropriately */
+ return NSERROR_OK;
+}
+
+
+static nserror
+nsw32_cw_get_scroll(const struct core_window *cw, int *x, int *y)
+{
+ /** /todo call getscroll apropriately */
+ return NSERROR_NOT_IMPLEMENTED;
}
@@ -470,8 +480,9 @@ nsw32_cw_scroll_visible(struct core_window *cw, const struct rect *r)
* \param[out] width to be set to viewport width in px
* \param[out] height to be set to viewport height in px
*/
-static void
-nsw32_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
+static nserror
+nsw32_cw_get_window_dimensions(const struct core_window *cw,
+ int *width, int *height)
{
struct nsw32_corewindow *nsw32_cw = (struct nsw32_corewindow *)cw;
@@ -479,21 +490,24 @@ nsw32_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
GetClientRect(nsw32_cw->hWnd, &rc);
*width = rc.right;
*height = rc.bottom;
+ return NSERROR_OK;
}
-static void
+static nserror
nsw32_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
{
struct nsw32_corewindow *nsw32_cw = (struct nsw32_corewindow *)cw;
nsw32_cw->drag_status = ds;
+ return NSERROR_OK;
}
struct core_window_callback_table nsw32_cw_cb_table = {
.invalidate = nsw32_cw_invalidate_area,
.update_size = nsw32_cw_update_size,
- .scroll_visible = nsw32_cw_scroll_visible,
+ .set_scroll = nsw32_cw_set_scroll,
+ .get_scroll = nsw32_cw_get_scroll,
.get_window_dimensions = nsw32_cw_get_window_dimensions,
.drag_status = nsw32_cw_drag_status
};
diff --git a/frontends/windows/download.c b/frontends/windows/download.c
index dfcd2b5a4..cfd2bbbb7 100644
--- a/frontends/windows/download.c
+++ b/frontends/windows/download.c
@@ -169,6 +169,7 @@ nsws_download_event_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
case IDOK:
if (download1->downloaded != download1->size)
return TRUE;
+ fallthrough;
case IDCANCEL:
nsws_download_clear_data(download1);
@@ -185,7 +186,7 @@ nsws_download_event_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
static bool nsws_download_window_up(struct gui_download_window *w)
{
w->hwnd = CreateDialog(hinst,
- MAKEINTRESOURCE(IDD_DLG_DOWNLOAD),
+ MAKEINTRESOURCE(IDD_DOWNLOAD),
gui_window_main_window(w->window),
nsws_download_event_callback);
if (w->hwnd == NULL) {
diff --git a/frontends/windows/drawable.c b/frontends/windows/drawable.c
index f491e0a2a..84b11ed78 100644
--- a/frontends/windows/drawable.c
+++ b/frontends/windows/drawable.c
@@ -41,7 +41,7 @@
#include "windows/local_history.h"
#include "windows/drawable.h"
-static const char windowclassname_drawable[] = "nswsdrawablewindow";
+static const wchar_t *windowclassname_drawable = L"nswsdrawablewindow";
/**
@@ -223,19 +223,71 @@ nsws_drawable_resize(struct gui_window *gw)
return 0;
}
+/**
+ * Handle unicode character messages.
+ */
+static LRESULT
+nsws_drawable_unichar(struct gui_window *gw, HWND hwnd, WPARAM wparam)
+{
+ uint32_t nskey;
+
+ if (wparam == UNICODE_NOCHAR) {
+ return 1;
+ }
+
+ nskey = wparam;
+ browser_window_key_press(gw->bw, nskey);
+ return 0;
+}
/**
- * Handle key press messages.
+ * Handle character messages.
+ *
+ * WM_CHAR is generated when WM_KEYDOWN message are passed to
+ * TranslateMessage; wParam is UTF-16. If the codepoint is 4
+ * bytes, there are 2 WM_CHAR message, one with the high
+ * surrogate and one with the low surrogate.
*/
static LRESULT
-nsws_drawable_key(struct gui_window *gw, HWND hwnd, WPARAM wparam)
+nsws_drawable_char(struct gui_window *gw, HWND hwnd, WPARAM wparam)
{
- if (GetFocus() != hwnd)
- return 0 ;
+ uint32_t nskey;
+
+ nskey = wparam;
+
+ const uint32_t utf16_hi_surrogate_start = 0xD800;
+ const uint32_t utf16_lo_surrogate_start = 0xDC00;
+ const uint32_t utf16_surrogate_end = 0xDFFF;
+ static uint32_t highSurrogate = 0;
+
+ if ((nskey >= utf16_hi_surrogate_start) &&
+ (nskey < utf16_lo_surrogate_start) ) {
+ highSurrogate = nskey;
+ } else {
+ if ((nskey >= utf16_lo_surrogate_start) &&
+ (nskey <= utf16_surrogate_end)) {
+ uint32_t lowSurrogate = nskey;
+ nskey = (highSurrogate - utf16_hi_surrogate_start) << 10;
+ nskey |= ( lowSurrogate - utf16_lo_surrogate_start );
+ nskey += 0x10000;
+ }
+ highSurrogate = 0;
+
+ browser_window_key_press(gw->bw, nskey);
+ }
+
+ return 0;
+}
+
+/**
+ * Handle keydown messages.
+ */
+static LRESULT
+nsws_drawable_keydown(struct gui_window *gw, HWND hwnd, WPARAM wparam)
+{
uint32_t i;
bool shift = ((GetKeyState(VK_SHIFT) & 0x8000) == 0x8000);
- bool capslock = ((GetKeyState(VK_CAPITAL) & 1) == 1);
switch(wparam) {
case VK_LEFT:
@@ -285,30 +337,18 @@ nsws_drawable_key(struct gui_window *gw, HWND hwnd, WPARAM wparam)
break;
case VK_NEXT:
- i = wparam;
- SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0),
- 0);
- break;
+ SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0);
+ return 1;
case VK_PRIOR:
- i = wparam;
- SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0),
- 0);
- break;
+ SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0);
+ return 1;
default:
- i = wparam;
- break;
+ return 1;
}
- if ((i >= 'A') &&
- (i <= 'Z') &&
- (((!capslock) && (!shift)) || ((capslock) && (shift)))) {
- i += 'a' - 'A';
- }
-
- if (gw != NULL)
- browser_window_key_press(gw->bw, i);
+ browser_window_key_press(gw->bw, i);
return 0;
}
@@ -338,10 +378,15 @@ nsws_drawable_paint(struct gui_window *gw, HWND hwnd)
clip.x1 = ps.rcPaint.right;
clip.y1 = ps.rcPaint.bottom;
+ /**
+ * \todo work out why the heck scroll needs scaling
+ */
+
browser_window_redraw(gw->bw,
- -gw->scrollx / gw->scale,
- -gw->scrolly / gw->scale,
- &clip, &ctx);
+ -gw->scrollx,
+ -gw->scrolly,
+ &clip,
+ &ctx);
}
EndPaint(hwnd, &ps);
@@ -385,19 +430,21 @@ nsws_drawable_mouseup(struct gui_window *gw,
if ((gw->mouse->state & click) != 0) {
NSLOG(netsurf, INFO,
- "mouse click bw %p, state 0x%x, x %f, y %f", gw->bw,
- gw->mouse->state, (x + gw->scrollx) / gw->scale,
- (y + gw->scrolly) / gw->scale);
+ "mouse click bw %p, state 0x%x, x %d, y %d",
+ gw->bw,
+ gw->mouse->state,
+ x + gw->scrollx,
+ y + gw->scrolly);
browser_window_mouse_click(gw->bw,
gw->mouse->state,
- (x + gw->scrollx) / gw->scale,
- (y + gw->scrolly) / gw->scale);
+ x + gw->scrollx,
+ y + gw->scrolly);
} else {
browser_window_mouse_track(gw->bw,
0,
- (x + gw->scrollx) / gw->scale,
- (y + gw->scrolly) / gw->scale);
+ x + gw->scrollx,
+ y + gw->scrolly);
}
gw->mouse->state = 0;
@@ -428,16 +475,19 @@ nsws_drawable_mousedown(struct gui_window *gw,
if ((GetKeyState(VK_MENU) & 0x8000) == 0x8000)
gw->mouse->state |= BROWSER_MOUSE_MOD_3;
- gw->mouse->pressed_x = (x + gw->scrollx) / gw->scale;
- gw->mouse->pressed_y = (y + gw->scrolly) / gw->scale;
+ gw->mouse->pressed_x = x + gw->scrollx;
+ gw->mouse->pressed_y = y + gw->scrolly;
- NSLOG(netsurf, INFO, "mouse click bw %p, state %x, x %f, y %f",
- gw->bw, gw->mouse->state, (x + gw->scrollx) / gw->scale,
- (y + gw->scrolly) / gw->scale);
+ NSLOG(netsurf, INFO, "mouse click bw %p, state %x, x %d, y %d",
+ gw->bw,
+ gw->mouse->state,
+ x + gw->scrollx,
+ y + gw->scrolly);
- browser_window_mouse_click(gw->bw, gw->mouse->state,
- (x + gw->scrollx) / gw->scale,
- (y + gw->scrolly) / gw->scale);
+ browser_window_mouse_click(gw->bw,
+ gw->mouse->state,
+ x + gw->scrollx,
+ y + gw->scrolly);
return 0;
}
@@ -456,9 +506,9 @@ nsws_drawable_mousemove(struct gui_window *gw, int x, int y)
if ((gw == NULL) || (gw->mouse == NULL) || (gw->bw == NULL))
return 0;
- /* scale co-ordinates */
- x = (x + gw->scrollx) / gw->scale;
- y = (y + gw->scrolly) / gw->scale;
+ /* add scroll offsets */
+ x = x + gw->scrollx;
+ y = y + gw->scrolly;
/* if mouse button held down and pointer moved more than
* minimum distance drag is happening */
@@ -544,7 +594,6 @@ nsws_window_drawable_event_callback(HWND hwnd,
BROWSER_MOUSE_PRESS_2);
SetFocus(hwnd);
return 0;
- break;
case WM_LBUTTONUP:
return nsws_drawable_mouseup(gw,
@@ -567,7 +616,16 @@ nsws_window_drawable_event_callback(HWND hwnd,
return nsws_drawable_paint(gw, hwnd);
case WM_KEYDOWN:
- return nsws_drawable_key(gw, hwnd, wparam);
+ if (nsws_drawable_keydown(gw, hwnd, wparam) == 0) {
+ return 0;
+ }
+ break;
+
+ case WM_CHAR:
+ return nsws_drawable_char(gw, hwnd, wparam);
+
+ case WM_UNICHAR:
+ return nsws_drawable_unichar(gw, hwnd, wparam);
case WM_SIZE:
return nsws_drawable_resize(gw);
@@ -581,6 +639,29 @@ nsws_window_drawable_event_callback(HWND hwnd,
case WM_MOUSEWHEEL:
return nsws_drawable_wheel(gw, hwnd, wparam);
+ case WM_PASTE:
+ browser_window_key_press(gw->bw, NS_KEY_PASTE);
+ return 0;
+
+ case WM_COPY:
+ browser_window_key_press(gw->bw, NS_KEY_COPY_SELECTION);
+ return 0;
+
+ case WM_CUT:
+ browser_window_key_press(gw->bw, NS_KEY_CUT_SELECTION);
+ return 0;
+
+ case WM_CLEAR:
+ /**
+ * \todo win32 clear operation deletes the contents of
+ * the selection but ns clear selection only
+ * removes the highlight.
+ */
+ browser_window_key_press(gw->bw, NS_KEY_CLEAR_SELECTION);
+ return 0;
+
+
+
}
return DefWindowProc(hwnd, msg, wparam, lparam);
}
@@ -595,14 +676,16 @@ nsws_window_create_drawable(HINSTANCE hinstance,
struct gui_window *gw)
{
HWND hwnd;
- hwnd = CreateWindow(windowclassname_drawable,
- NULL,
- WS_VISIBLE | WS_CHILD,
- 0, 0, 0, 0,
- hparent,
- NULL,
- hinstance,
- NULL);
+ hwnd = CreateWindowExW(0,
+ windowclassname_drawable,
+ NULL,
+ WS_VISIBLE | WS_CHILD,
+ 0, 0,
+ 0, 0,
+ hparent,
+ NULL,
+ hinstance,
+ NULL);
if (hwnd == NULL) {
win_perror("WindowCreateDrawable");
@@ -623,7 +706,7 @@ nsws_window_create_drawable(HINSTANCE hinstance,
nserror
nsws_create_drawable_class(HINSTANCE hinstance) {
nserror ret = NSERROR_OK;
- WNDCLASSEX w;
+ WNDCLASSEXW w;
/* drawable area */
w.cbSize = sizeof(WNDCLASSEX);
@@ -639,7 +722,7 @@ nsws_create_drawable_class(HINSTANCE hinstance) {
w.lpszClassName = windowclassname_drawable;
w.hIconSm = NULL;
- if (RegisterClassEx(&w) == 0) {
+ if (RegisterClassExW(&w) == 0) {
win_perror("DrawableClass");
ret = NSERROR_INIT_FAILED;
}
diff --git a/frontends/windows/filetype.c b/frontends/windows/fetch.c
index a5fd9e95e..287f20f6c 100644
--- a/frontends/windows/filetype.c
+++ b/frontends/windows/fetch.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2003 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2018 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -25,10 +25,13 @@
#include <string.h>
#include "utils/log.h"
+#include "utils/file.h"
+#include "utils/filepath.h"
#include "content/fetch.h"
#include "netsurf/fetch.h"
-#include "windows/filetype.h"
+#include "windows/fetch.h"
+#include "windows/gui.h"
/**
* determine the MIME type of a local file.
@@ -60,9 +63,71 @@ static const char *fetch_filetype(const char *unix_path)
return "text/html";
}
+/**
+ * Translate resource to full win32 url.
+ *
+ * Transforms a resource: path into a full URL. The returned URL
+ * is used as the target for a redirect. The caller takes ownership of
+ * the returned nsurl including unrefing it when finished with it.
+ *
+ * \param path The path of the resource to locate.
+ * \return A string containing the full URL of the target object or
+ * NULL if no suitable resource can be found.
+ */
+static nsurl *nsw32_get_resource_url(const char *path)
+{
+ char buf[PATH_MAX];
+ nsurl *url = NULL;
+
+ netsurf_path_to_nsurl(filepath_sfind(G_resource_pathv, buf, path), &url);
+
+ return url;
+}
+
+
+/* exported interface documented in windows/fetch.h */
+nserror
+nsw32_get_resource_data(const char *path,
+ const uint8_t **data_out,
+ size_t *data_len_out)
+{
+ HRSRC reshandle;
+ HGLOBAL datahandle;
+ uint8_t *data;
+ DWORD data_len;
+
+ reshandle = FindResource(NULL, path, "USER");
+ if (reshandle == NULL) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ data_len = SizeofResource(NULL, reshandle);
+ if (data_len == 0) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ datahandle = LoadResource(NULL, reshandle);
+ if (datahandle == NULL) {
+ return NSERROR_NOT_FOUND;
+ }
+ data = LockResource(datahandle);
+ if (data == NULL) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ *data_out = data;
+ *data_len_out = data_len;
+
+ return NSERROR_OK;
+}
+
+
/** win32 fetch operation table */
static struct gui_fetch_table fetch_table = {
.filetype = fetch_filetype,
+
+ .get_resource_url = nsw32_get_resource_url,
+ .get_resource_data = nsw32_get_resource_data,
};
struct gui_fetch_table *win32_fetch_table = &fetch_table;
diff --git a/frontends/amiga/sslcert.h b/frontends/windows/fetch.h
index 392989f02..e85402ac3 100644
--- a/frontends/amiga/sslcert.h
+++ b/frontends/windows/fetch.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ * Copyright 2014 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,23 +16,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef AMIGA_SSLCERT_H
-#define AMIGA_SSLCERT_H
-struct nsurl;
-struct ssl_cert_info;
+#ifndef _NETSURF_WINDOWS_FILETYPE_H_
+#define _NETSURF_WINDOWS_FILETYPE_H_
/**
- * Prompt the user to verify a certificate with issues.
+ * win32 API fetch operation table
+ */
+extern struct gui_fetch_table *win32_fetch_table;
+
+/**
+ * Translate resource to win32 resource data.
*
- * \param url The URL being verified.
- * \param certs The certificate to be verified
- * \param num The number of certificates to be verified.
- * \param cb Callback upon user decision.
- * \param cbpw Context pointer passed to cb
- * \return NSERROR_OK or error code if prompt creation failed.
+ * Obtains the data for a resource directly
+ *
+ * \param path The path of the resource to locate.
+ * \param data Pointer to recive data into
+ * \param data_len Pointer to length of returned data
+ * \return NSERROR_OK and the data and length values updated
+ * else appropriate error code.
*/
-nserror ami_cert_verify(struct nsurl *url,
- const struct ssl_cert_info *certs, unsigned long num,
- nserror (*cb)(bool proceed, void *pw), void *cbpw);
-#endif
+nserror nsw32_get_resource_data(const char *path, const uint8_t **data_out, size_t *data_len_out);
+#endif
diff --git a/frontends/windows/file.h b/frontends/windows/file.h
index 5262dde2c..19dfba3b1 100644
--- a/frontends/windows/file.h
+++ b/frontends/windows/file.h
@@ -24,6 +24,6 @@
#ifndef _NETSURF_WINDOWS_FILE_H_
#define _NETSURF_WINDOWS_FILE_H_
-struct gui_file_table *win32_file_table;
+extern struct gui_file_table *win32_file_table;
#endif
diff --git a/frontends/windows/font.c b/frontends/windows/font.c
index 37ccf23fe..3e81a80a1 100644
--- a/frontends/windows/font.c
+++ b/frontends/windows/font.c
@@ -93,23 +93,31 @@ HFONT get_font(const plot_font_style_t *style)
{
char *face = NULL;
DWORD family;
+ int nHeight;
+ HDC hdc;
+ HFONT font;
+
switch(style->family) {
case PLOT_FONT_FAMILY_SERIF:
face = strdup(nsoption_charp(font_serif));
family = FF_ROMAN | DEFAULT_PITCH;
break;
+
case PLOT_FONT_FAMILY_MONOSPACE:
face = strdup(nsoption_charp(font_mono));
family = FF_MODERN | DEFAULT_PITCH;
break;
+
case PLOT_FONT_FAMILY_CURSIVE:
face = strdup(nsoption_charp(font_cursive));
family = FF_SCRIPT | DEFAULT_PITCH;
break;
+
case PLOT_FONT_FAMILY_FANTASY:
face = strdup(nsoption_charp(font_fantasy));
family = FF_DECORATIVE | DEFAULT_PITCH;
break;
+
case PLOT_FONT_FAMILY_SANS_SERIF:
default:
face = strdup(nsoption_charp(font_sans));
@@ -117,30 +125,30 @@ HFONT get_font(const plot_font_style_t *style)
break;
}
- int nHeight = -10;
+ nHeight = -10;
- HDC hdc = GetDC(font_hwnd);
- nHeight = -MulDiv(style->size, GetDeviceCaps(hdc, LOGPIXELSY), 72 * FONT_SIZE_SCALE);
+ hdc = GetDC(font_hwnd);
+ nHeight = -MulDiv(style->size, GetDeviceCaps(hdc, LOGPIXELSY), 72 * PLOT_STYLE_SCALE);
ReleaseDC(font_hwnd, hdc);
- HFONT font = CreateFont(
- nHeight, /* height */
- 0, /* width */
- 0, /* escapement*/
- 0, /* orientation */
- style->weight,
- (style->flags & FONTF_ITALIC) ? TRUE : FALSE,
- FALSE, /* underline */
- FALSE, /* strike */
- DEFAULT_CHARSET, /* for locale */
- OUT_DEFAULT_PRECIS, /* general 'best match' */
- CLIP_DEFAULT_PRECIS,
- DEFAULT_QUALITY,
- family,
- face /* name of font face */
- );
- if (face != NULL)
+ font = CreateFont(nHeight, /* height */
+ 0, /* width */
+ 0, /* escapement*/
+ 0, /* orientation */
+ style->weight,
+ (style->flags & FONTF_ITALIC) ? TRUE : FALSE,
+ FALSE, /* underline */
+ FALSE, /* strike */
+ DEFAULT_CHARSET, /* for locale */
+ OUT_DEFAULT_PRECIS, /* general 'best match' */
+ CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,
+ family,
+ face); /* name of font face */
+
+ if (face != NULL) {
free(face);
+ }
if (font == NULL) {
if (style->family == PLOT_FONT_FAMILY_MONOSPACE) {
@@ -149,50 +157,67 @@ HFONT get_font(const plot_font_style_t *style)
font = (HFONT) GetStockObject(ANSI_VAR_FONT);
}
}
- if (font == NULL)
+
+ if (font == NULL) {
font = (HFONT) GetStockObject(SYSTEM_FONT);
+ }
+
return font;
}
+/* size of temporary wide character string for computing string width */
+#define WSTRLEN 4096
+
/**
* Measure the width of a string.
*
* \param[in] style plot style for this text
- * \param[in] string UTF-8 string to measure
- * \param[in] length length of string, in bytes
+ * \param[in] utf8str string encoded in UTF-8 to measure
+ * \param[in] utf8len length of string, in bytes
* \param[out] width updated to width of string[0..length)
* \return NSERROR_OK on success otherwise appropriate error code
*/
static nserror
win32_font_width(const plot_font_style_t *style,
- const char *string,
- size_t length,
+ const char *utf8str,
+ size_t utf8len,
int *width)
{
+ nserror ret = NSERROR_OK;
HDC hdc;
HFONT font;
HFONT fontbak;
- SIZE s;
- nserror ret = NSERROR_OK;
+ SIZE sizl; /* size in logical units */
+ BOOL wres;
+ int wclen; /* wide char length */
+ static WCHAR wstr[WSTRLEN]; /* temporary wide char string */
- if (length == 0) {
+ if (utf8len == 0) {
*width = 0;
- } else {
- hdc = GetDC(NULL);
- font = get_font(style);
- fontbak = SelectObject(hdc, font);
+ return ret;
+ }
- /* may well need to convert utf-8 to lpctstr */
- if (GetTextExtentPoint32A(hdc, string, length, &s) != 0) {
- *width = s.cx;
+ hdc = GetDC(NULL);
+ font = get_font(style);
+ fontbak = SelectObject(hdc, font);
+
+ wclen = MultiByteToWideChar(CP_UTF8, 0, utf8str, utf8len, wstr, WSTRLEN);
+ if (wclen != 0) {
+ wres = GetTextExtentPoint32W(hdc, wstr, wclen, &sizl);
+ if (wres == FALSE) {
+ ret = NSERROR_INVALID;
} else {
- ret = NSERROR_UNKNOWN;
+ *width = sizl.cx;
}
- font = SelectObject(hdc, fontbak);
- DeleteObject(font);
- ReleaseDC(NULL, hdc);
+ } else {
+ ret = NSERROR_NOSPACE;
}
+
+ font = SelectObject(hdc, fontbak);
+ DeleteObject(font);
+ ReleaseDC(NULL, hdc);
+
return ret;
}
@@ -200,19 +225,19 @@ win32_font_width(const plot_font_style_t *style,
/**
* Find the position in a string where an x coordinate falls.
*
- * \param style css_style for this text, with style->font_size.size ==
+ * \param style css_style for this text, with style->font_size.size ==
* CSS_FONT_SIZE_LENGTH
- * \param string UTF-8 string to measure
- * \param length length of string
- * \param x x coordinate to search for
- * \param char_offset updated to offset in string of actual_x, [0..length]
- * \param actual_x updated to x coordinate of character closest to x
+ * \param utf8str string to measure encoded in UTF-8
+ * \param utf8len length of string
+ * \param x coordinate to search for
+ * \param char_offset updated to offset in string of actual_x, [0..length]
+ * \param actual_x updated to x coordinate of character closest to x
* \return NSERROR_OK on success otherwise appropriate error code
*/
static nserror
win32_font_position(const plot_font_style_t *style,
- const char *string,
- size_t length,
+ const char *utf8str,
+ size_t utf8len,
int x,
size_t *char_offset,
int *actual_x)
@@ -224,26 +249,29 @@ win32_font_position(const plot_font_style_t *style,
int offset;
nserror ret = NSERROR_OK;
- if ((length == 0) || (x < 1)) {
+ /* deal with zero length input or invalid search co-ordiate */
+ if ((utf8len == 0) || (x < 1)) {
*char_offset = 0;
*actual_x = 0;
+ return ret;
+ }
+
+ hdc = GetDC(NULL);
+ font = get_font(style);
+ fontbak = SelectObject(hdc, font);
+
+ if ((GetTextExtentExPointA(hdc, utf8str, utf8len, x, &offset, NULL, &s) != 0) &&
+ (GetTextExtentPoint32A(hdc, utf8str, offset, &s) != 0)) {
+ *char_offset = (size_t)offset;
+ *actual_x = s.cx;
} else {
- hdc = GetDC(NULL);
- font = get_font(style);
- fontbak = SelectObject(hdc, font);
-
- if ((GetTextExtentExPointA(hdc, string, length, x, &offset, NULL,&s) != 0) &&
- (GetTextExtentPoint32A(hdc, string, offset, &s) != 0)) {
- *char_offset = (size_t)offset;
- *actual_x = s.cx;
- } else {
- ret = NSERROR_UNKNOWN;
- }
- font = SelectObject(hdc, fontbak);
- DeleteObject(font);
- ReleaseDC(NULL, hdc);
+ ret = NSERROR_UNKNOWN;
}
+ font = SelectObject(hdc, fontbak);
+ DeleteObject(font);
+ ReleaseDC(NULL, hdc);
+
return ret;
}
@@ -256,7 +284,7 @@ win32_font_position(const plot_font_style_t *style,
* \param string UTF-8 string to measure
* \param length length of string
* \param x width available
- * \param char_offset updated to offset in string of actual_x, [0..length]
+ * \param[out] offset updated to offset in string of actual_x, [0..length]
* \param actual_x updated to x coordinate of character closest to x
* \return NSERROR_OK on success otherwise appropriate error code
*
@@ -269,52 +297,48 @@ win32_font_split(const plot_font_style_t *style,
const char *string,
size_t length,
int x,
- size_t *char_offset,
+ size_t *offset,
int *actual_x)
{
+ nserror res;
int c_off;
- nserror ret = NSERROR_UNKNOWN;
-
- if (win32_font_position(style,
- string,
- length,
- x,
- char_offset,
- actual_x) == NSERROR_OK) {
- c_off = *char_offset;
- if (*char_offset == length) {
- ret = NSERROR_OK;
- } else {
- bool success;
- while ((string[*char_offset] != ' ') &&
- (*char_offset > 0)) {
- (*char_offset)--;
- }
-
- if (*char_offset == 0) {
- *char_offset = c_off;
- while ((*char_offset < length) &&
- (string[*char_offset] != ' ')) {
- (*char_offset)++;
- }
- }
-
- success = win32_font_width(style,
- string,
- *char_offset,
- actual_x);
- if (success) {
- ret = NSERROR_OK;
- }
+
+ /* get the offset into teh string on the proposed position */
+ res = win32_font_position(style, string, length, x, offset, actual_x);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* return the whole string fits in the proposed length */
+ if (*offset == length) {
+ return NSERROR_OK;
+ }
+
+ c_off = *offset;
+
+ /* walk backwards through string looking for space to break on */
+ while ((string[*offset] != ' ') &&
+ (*offset > 0)) {
+ (*offset)--;
+ }
+
+ /* walk forwards through string looking for space if back failed */
+ if (*offset == 0) {
+ *offset = c_off;
+ while ((*offset < length) &&
+ (string[*offset] != ' ')) {
+ (*offset)++;
}
}
+ /* find the actual string width of the break */
+ res = win32_font_width(style, string, *offset, actual_x);
NSLOG(netsurf, DEEPDEBUG,
"ret %d Split %u chars at %ipx: Split at char %i (%ipx) - %.*s",
- ret, length, x, *char_offset, *actual_x, *char_offset, string);
+ res, length, x, *offset, *actual_x, *offset, string);
- return ret;
+ return res;
}
diff --git a/frontends/windows/font.h b/frontends/windows/font.h
index ec2c262ff..8219e4c76 100644
--- a/frontends/windows/font.h
+++ b/frontends/windows/font.h
@@ -35,8 +35,8 @@ struct font_desc {
const char *encoding;
};
-struct gui_layout_table *win32_layout_table;
-struct gui_utf8_table *win32_utf8_table;
+extern struct gui_layout_table *win32_layout_table;
+extern struct gui_utf8_table *win32_utf8_table;
/**
* convert from utf-8 to win32 font encoding.
diff --git a/frontends/windows/gui.c b/frontends/windows/gui.c
index 890bfae42..9a2c13b23 100644
--- a/frontends/windows/gui.c
+++ b/frontends/windows/gui.c
@@ -36,22 +36,90 @@
#include "utils/file.h"
#include "utils/messages.h"
#include "netsurf/browser_window.h"
-#include "netsurf/clipboard.h"
#include "windows/schedule.h"
#include "windows/window.h"
-#include "windows/filetype.h"
#include "windows/gui.h"
-/**
- * win32 application instance handle.
- *
- * This handle is set in the main windows entry point.
- */
+/* exported global defined in windows/gui.h */
HINSTANCE hinst;
+/* exported global defined in windows/gui.h */
+char **G_resource_pathv;
+
+/* exported global defined in windows/gui.h */
+char *G_config_path;
+
static bool win32_quit = false;
+struct dialog_list_entry {
+ struct dialog_list_entry *next;
+ HWND hwnd;
+};
+
+static struct dialog_list_entry *dlglist = NULL;
+
+/* exported interface documented in gui.h */
+nserror nsw32_add_dialog(HWND hwndDlg)
+{
+ struct dialog_list_entry *nentry;
+ nentry = malloc(sizeof(struct dialog_list_entry));
+ if (nentry == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ nentry->hwnd = hwndDlg;
+ nentry->next = dlglist;
+ dlglist = nentry;
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in gui.h */
+nserror nsw32_del_dialog(HWND hwndDlg)
+{
+ struct dialog_list_entry **prev;
+ struct dialog_list_entry *cur;
+
+ prev = &dlglist;
+ cur = *prev;
+
+ while (cur != NULL) {
+ if (cur->hwnd == hwndDlg) {
+ /* found match */
+ *prev = cur->next;
+ NSLOG(netsurf, DEBUG,
+ "removed hwnd %p entry %p", cur->hwnd, cur);
+ free(cur);
+ return NSERROR_OK;
+ }
+ prev = &cur->next;
+ cur = *prev;
+ }
+ NSLOG(netsurf, INFO, "did not find hwnd %p", hwndDlg);
+
+ return NSERROR_NOT_FOUND;
+}
+
+/**
+ * walks dialog list and attempts to process any messages for them
+ */
+static nserror handle_dialog_message(LPMSG lpMsg)
+{
+ struct dialog_list_entry *cur;
+ cur = dlglist;
+ while (cur != NULL) {
+ if (IsDialogMessage(cur->hwnd, lpMsg)) {
+ NSLOG(netsurf, DEBUG,
+ "dispatched dialog hwnd %p", cur->hwnd);
+ return NSERROR_OK;
+ }
+ cur = cur->next;
+ }
+
+ return NSERROR_NOT_FOUND;
+}
+
/* exported interface documented in gui.h */
void win32_set_quit(bool q)
{
@@ -92,7 +160,8 @@ void win32_run(void)
}
}
- if (bRet > 0) {
+ if ((bRet > 0) &&
+ (handle_dialog_message(&Msg) != NSERROR_OK)) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
@@ -113,65 +182,17 @@ nserror win32_warning(const char *warning, const char *detail)
}
-/**
- * Core asks front end for clipboard contents.
- *
- * \param buffer UTF-8 text, allocated by front end, ownership yeilded to core
- * \param length Byte length of UTF-8 text in buffer
- */
-static void gui_get_clipboard(char **buffer, size_t *length)
+/* exported function documented in windows/gui.h */
+nserror
+win32_report_nserror(nserror error, const char *detail)
{
- /* TODO: Implement this */
- HANDLE clipboard_handle;
- char *content;
-
- clipboard_handle = GetClipboardData(CF_TEXT);
- if (clipboard_handle != NULL) {
- content = GlobalLock(clipboard_handle);
- NSLOG(netsurf, INFO, "pasting %s", content);
- GlobalUnlock(clipboard_handle);
- }
-}
-
+ size_t len = 1 +
+ strlen(messages_get_errorcode(error)) +
+ ((detail != 0) ? strlen(detail) : 0);
+ char message[len];
+ snprintf(message, len, messages_get_errorcode(error), detail);
+ MessageBox(NULL, message, "Warning", MB_ICONWARNING);
-/**
- * Core tells front end to put given text in clipboard
- *
- * \param buffer UTF-8 text, owned by core
- * \param length Byte length of UTF-8 text in buffer
- * \param styles Array of styles given to text runs, owned by core, or NULL
- * \param n_styles Number of text run styles in array
- */
-static void gui_set_clipboard(const char *buffer, size_t length,
- nsclipboard_styles styles[], int n_styles)
-{
- /* TODO: Implement this */
- HANDLE hnew;
- char *new, *original;
- HANDLE h = GetClipboardData(CF_TEXT);
- if (h == NULL)
- original = (char *)"";
- else
- original = GlobalLock(h);
-
- size_t len = strlen(original) + 1;
- hnew = GlobalAlloc(GHND, length + len);
- new = (char *)GlobalLock(hnew);
- snprintf(new, length + len, "%s%s", original, buffer);
-
- if (h != NULL) {
- GlobalUnlock(h);
- EmptyClipboard();
- }
- GlobalUnlock(hnew);
- SetClipboardData(CF_TEXT, hnew);
+ return NSERROR_OK;
}
-
-
-static struct gui_clipboard_table clipboard_table = {
- .get = gui_get_clipboard,
- .set = gui_set_clipboard,
-};
-
-struct gui_clipboard_table *win32_clipboard_table = &clipboard_table;
diff --git a/frontends/windows/gui.h b/frontends/windows/gui.h
index efbf02924..957280ae4 100644
--- a/frontends/windows/gui.h
+++ b/frontends/windows/gui.h
@@ -17,16 +17,27 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_WINDOWS_GUI_H_
-#define _NETSURF_WINDOWS_GUI_H_
+#ifndef NETSURF_WINDOWS_GUI_H
+#define NETSURF_WINDOWS_GUI_H
struct gui_window;
-struct gui_clipboard_table *win32_clipboard_table;
+/**
+ * win32 application instance handle.
+ *
+ * This handle is set in the main windows entry point.
+ */
extern HINSTANCE hinst;
-/** Directory where all configuration files are held. */
-extern char *nsw32_config_home;
+/**
+ * path to where all user config files are held.
+ */
+extern char *G_config_path;
+
+/**
+ * resource search path vector.
+ */
+extern char **G_resource_pathv;
/* bounding box */
typedef struct bbox_s {
@@ -56,4 +67,25 @@ void win32_set_quit(bool q);
*/
nserror win32_warning(const char *warning, const char *detail);
+/**
+ * Warn the user of an unexpected nserror.
+ *
+ * \param[in] error The nserror to report
+ * \param[in] detail Additional text to be displayed or NULL.
+ * \return NSERROR_OK on success or error code if there was a
+ * faliure displaying the message to the user.
+ */
+nserror win32_report_nserror(nserror error, const char *detail);
+
+/**
+ * add a modeless dialog to the special handling list
+ */
+nserror nsw32_add_dialog(HWND hwndDlg);
+
+/**
+ * remove a modeless dialog from the special handling list
+ */
+nserror nsw32_del_dialog(HWND hwndDlg);
+
+
#endif
diff --git a/frontends/windows/local_history.c b/frontends/windows/local_history.c
index 722d365e7..823901b69 100644
--- a/frontends/windows/local_history.c
+++ b/frontends/windows/local_history.c
@@ -215,6 +215,7 @@ nsw32_local_history_present(HWND hWndParent, struct browser_window *bw)
width,
height,
SWP_SHOWWINDOW);
+ local_history_scroll_to_cursor(local_history_window->session);
}
return res;
}
diff --git a/frontends/windows/main.c b/frontends/windows/main.c
index a3a7c2b39..c051f446c 100644
--- a/frontends/windows/main.c
+++ b/frontends/windows/main.c
@@ -34,6 +34,7 @@
#include "utils/nsoption.h"
#include "netsurf/url_db.h"
#include "netsurf/cookie_db.h"
+#include "netsurf/browser.h"
#include "netsurf/browser_window.h"
#include "netsurf/fetch.h"
#include "netsurf/misc.h"
@@ -42,22 +43,40 @@
#include "windows/findfile.h"
#include "windows/file.h"
+#include "windows/cookies.h"
#include "windows/drawable.h"
#include "windows/corewindow.h"
-#include "windows/ssl_cert.h"
#include "windows/download.h"
#include "windows/local_history.h"
#include "windows/window.h"
#include "windows/schedule.h"
#include "windows/font.h"
-#include "windows/filetype.h"
+#include "windows/fetch.h"
#include "windows/pointers.h"
#include "windows/bitmap.h"
+#include "windows/clipboard.h"
#include "windows/gui.h"
-static char **respaths; /** resource search path vector. */
-char *nsw32_config_home; /* exported global defined in windows/gui.h */
+/**
+ * Obtain the DPI of the display.
+ *
+ * \return The DPI of the device the window is displayed on.
+ */
+static int get_screen_dpi(void)
+{
+ HDC screendc = GetDC(0);
+ int dpi = GetDeviceCaps(screendc, LOGPIXELSY);
+ ReleaseDC(0, screendc);
+
+ if (dpi <= 10) {
+ dpi = 96; /* 96DPI is the default */
+ }
+
+ NSLOG(netsurf, INFO, "FIX DPI %d", dpi);
+
+ return dpi;
+}
/**
* Get the path to the config directory.
@@ -118,15 +137,6 @@ static void die(const char *error)
}
-static nsurl *gui_get_resource_url(const char *path)
-{
- char buf[PATH_MAX];
- nsurl *url = NULL;
-
- netsurf_path_to_nsurl(filepath_sfind(respaths, buf, path), &url);
-
- return url;
-}
/**
* Ensures output logging stream is available
@@ -134,7 +144,7 @@ static nsurl *gui_get_resource_url(const char *path)
static bool nslog_ensure(FILE *fptr)
{
/* mwindows compile flag normally invalidates standard io unless
- * already redirected
+ * already redirected
*/
if (_get_osfhandle(fileno(fptr)) == -1) {
AllocConsole();
@@ -180,6 +190,11 @@ static nserror set_defaults(struct nsoption_s *defaults)
&ptr);
if (res_len > 0) {
nsoption_setnull_charp(ca_bundle, strdup(buf));
+ } else {
+ ptr = filepath_sfind(G_resource_pathv, buf, "ca-bundle.crt");
+ if (ptr != NULL) {
+ nsoption_setnull_charp(ca_bundle, strdup(buf));
+ }
}
@@ -205,34 +220,34 @@ static nserror set_defaults(struct nsoption_s *defaults)
}
free(buf);
-
+
/* ensure homepage option has a default */
nsoption_setnull_charp(homepage_url, strdup(NETSURF_HOMEPAGE));
/* cookie file default */
fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsw32_config_home, "Cookies");
+ netsurf_mkpath(&fname, NULL, 2, G_config_path, "Cookies");
if (fname != NULL) {
nsoption_setnull_charp(cookie_file, fname);
}
/* cookie jar default */
fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsw32_config_home, "Cookies");
+ netsurf_mkpath(&fname, NULL, 2, G_config_path, "Cookies");
if (fname != NULL) {
nsoption_setnull_charp(cookie_jar, fname);
}
/* url database default */
fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsw32_config_home, "URLs");
+ netsurf_mkpath(&fname, NULL, 2, G_config_path, "URLs");
if (fname != NULL) {
nsoption_setnull_charp(url_file, fname);
}
/* bookmark database default */
fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsw32_config_home, "Hotlist");
+ netsurf_mkpath(&fname, NULL, 2, G_config_path, "Hotlist");
if (fname != NULL) {
nsoption_setnull_charp(hotlist_path, fname);
}
@@ -244,11 +259,16 @@ static nserror set_defaults(struct nsoption_s *defaults)
/**
* Initialise user options location and contents
*/
-static nserror nsw32_option_init(int *pargc, char** argv)
+static nserror
+nsw32_option_init(int *pargc, char** argv, char **respaths, char *config_path)
{
nserror ret;
char *choices = NULL;
+ /* set the globals that will be used in the set_defaults() callback */
+ G_resource_pathv = respaths;
+ G_config_path = config_path;
+
/* user options setup */
ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
if (ret != NSERROR_OK) {
@@ -256,7 +276,7 @@ static nserror nsw32_option_init(int *pargc, char** argv)
}
/* Attempt to load the user choices */
- ret = netsurf_mkpath(&choices, NULL, 2, nsw32_config_home, "Choices");
+ ret = netsurf_mkpath(&choices, NULL, 2, config_path, "Choices");
if (ret == NSERROR_OK) {
nsoption_read(choices, nsoptions);
free(choices);
@@ -268,11 +288,90 @@ static nserror nsw32_option_init(int *pargc, char** argv)
return NSERROR_OK;
}
+/**
+ * Initialise messages
+ */
+static nserror nsw32_messages_init(char **respaths)
+{
+ char *messages;
+ nserror res;
+ const uint8_t *data;
+ size_t data_size;
+
+ res = nsw32_get_resource_data("messages", &data, &data_size);
+ if (res == NSERROR_OK) {
+ res = messages_add_from_inline(data, data_size);
+ } else {
+ /* Obtain path to messages */
+ messages = filepath_find(respaths, "messages");
+ if (messages == NULL) {
+ res = NSERROR_NOT_FOUND;
+ } else {
+ res = messages_add_from_file(messages);
+ free(messages);
+ }
+ }
+
+ return res;
+}
+
+
+/**
+ * Construct a unix style argc/argv
+ *
+ * \param argc_out number of commandline arguments
+ * \param argv_out string vector of command line arguments
+ * \return NSERROR_OK on success else error code
+ */
+static nserror win32_to_unix_commandline(int *argc_out, char ***argv_out)
+{
+ int argc = 0;
+ char **argv;
+ int cura;
+ LPWSTR *argvw;
+ size_t len;
+
+ argvw = CommandLineToArgvW(GetCommandLineW(), &argc);
+ if (argvw == NULL) {
+ return NSERROR_INVALID;
+ }
+
+ argv = malloc(sizeof(char *) * argc);
+ if (argv == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ for (cura = 0; cura < argc; cura++) {
+
+ len = wcstombs(NULL, argvw[cura], 0) + 1;
+ if (len > 0) {
+ argv[cura] = malloc(len);
+ if (argv[cura] == NULL) {
+ free(argv);
+ return NSERROR_NOMEM;
+ }
+ } else {
+ free(argv);
+ return NSERROR_INVALID;
+ }
+
+ wcstombs(argv[cura], argvw[cura], len);
+ /* alter windows-style forward slash flags to hyphen flags. */
+ if (argv[cura][0] == '/') {
+ argv[cura][0] = '-';
+ }
+ }
+
+ *argc_out = argc;
+ *argv_out = argv;
+
+ return NSERROR_OK;
+}
+
static struct gui_misc_table win32_misc_table = {
.schedule = win32_schedule,
- .warning = win32_warning,
- .cert_verify = nsw32_cert_verify,
+ .present_cookies = nsw32_cookies_present,
};
/**
@@ -281,11 +380,10 @@ static struct gui_misc_table win32_misc_table = {
int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hLastInstance, LPSTR lpcli, int ncmd)
{
- char **argv = NULL;
- int argc = 0, argctemp = 0;
- size_t len;
- LPWSTR *argvw;
- char *messages;
+ int argc;
+ char **argv;
+ char **respaths;
+ char *nsw32_config_home = NULL;
nserror ret;
const char *addr;
nsurl *url;
@@ -300,7 +398,6 @@ WinMain(HINSTANCE hInstance, HINSTANCE hLastInstance, LPSTR lpcli, int ncmd)
.bitmap = win32_bitmap_table,
.layout = win32_layout_table,
};
- win32_fetch_table->get_resource_url = gui_get_resource_url;
ret = netsurf_register(&win32_table);
if (ret != NSERROR_OK) {
@@ -312,56 +409,43 @@ WinMain(HINSTANCE hInstance, HINSTANCE hLastInstance, LPSTR lpcli, int ncmd)
setbuf(stderr, NULL);
- /* Construct a unix style argc/argv */
- if (SLEN(lpcli) > 0) {
- argvw = CommandLineToArgvW(GetCommandLineW(), &argc);
- }
-
- argv = malloc(sizeof(char *) * argc);
- while (argctemp < argc) {
- len = wcstombs(NULL, argvw[argctemp], 0) + 1;
- if (len > 0) {
- argv[argctemp] = malloc(len);
- }
-
- if (argv[argctemp] != NULL) {
- wcstombs(argv[argctemp], argvw[argctemp], len);
- /* alter windows-style forward slash flags to
- * hyphen flags.
- */
- if (argv[argctemp][0] == '/')
- argv[argctemp][0] = '-';
- }
- argctemp++;
+ ret = win32_to_unix_commandline(&argc, &argv);
+ if (ret != NSERROR_OK) {
+ /* no log as logging requires this for initialisation */
+ return 1;
}
/* initialise logging - not fatal if it fails but not much we
- * can do about it
+ * can do about it
*/
nslog_init(nslog_ensure, &argc, argv);
+ /* build resource path string vector */
+ respaths = nsws_init_resource("${APPDATA}\\NetSurf:${PROGRAMFILES}\\NetSurf\\NetSurf\\:"NETSURF_WINDOWS_RESPATH);
+
/* Locate the correct user configuration directory path */
ret = get_config_home(&nsw32_config_home);
if (ret != NSERROR_OK) {
NSLOG(netsurf, INFO,
"Unable to locate a configuration directory.");
- nsw32_config_home = NULL;
}
/* Initialise user options */
- ret = nsw32_option_init(&argc, argv);
+ ret = nsw32_option_init(&argc, argv, respaths, nsw32_config_home);
if (ret != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Options failed to initialise (%s)\n",
+ NSLOG(netsurf, ERROR, "Options failed to initialise (%s)\n",
messages_get_errorcode(ret));
return 1;
}
- respaths = nsws_init_resource("${APPDATA}\\NetSurf:${HOME}\\.netsurf:${NETSURFRES}:${PROGRAMFILES}\\NetSurf\\NetSurf\\:"NETSURF_WINDOWS_RESPATH);
-
- /* message init */
- messages = filepath_find(respaths, "messages");
- messages_add_from_file(messages);
- free(messages);
+ /* Initialise translated messages */
+ ret = nsw32_messages_init(respaths);
+ if (ret != NSERROR_OK) {
+ fprintf(stderr, "Unable to load translated messages (%s)\n",
+ messages_get_errorcode(ret));
+ NSLOG(netsurf, INFO, "Unable to load translated messages");
+ /** \todo decide if message load faliure should be fatal */
+ }
/* common initialisation */
ret = netsurf_init(NULL);
@@ -370,6 +454,8 @@ WinMain(HINSTANCE hInstance, HINSTANCE hLastInstance, LPSTR lpcli, int ncmd)
return 1;
}
+ browser_set_dpi(get_screen_dpi());
+
urldb_load(nsoption_charp(url_file));
urldb_load_cookies(nsoption_charp(cookie_file));
hotlist_init(nsoption_charp(hotlist_path),
@@ -378,7 +464,6 @@ WinMain(HINSTANCE hInstance, HINSTANCE hLastInstance, LPSTR lpcli, int ncmd)
ret = nsws_create_main_class(hInstance);
ret = nsws_create_drawable_class(hInstance);
ret = nsw32_create_corewindow_class(hInstance);
- ret = nsws_create_cert_verify_class(hInstance);
nsoption_set_bool(target_blank, false);
diff --git a/frontends/windows/plot.c b/frontends/windows/plot.c
index 3668e4bb6..4d9096d75 100644
--- a/frontends/windows/plot.c
+++ b/frontends/windows/plot.c
@@ -601,7 +601,9 @@ line(const struct redraw_context *ctx,
(style->stroke_type == PLOT_OP_TYPE_DASH) ? PS_DASH:
0);
LOGBRUSH lb = {BS_SOLID, col, 0};
- HPEN pen = ExtCreatePen(penstyle, style->stroke_width, &lb, 0, NULL);
+ HPEN pen = ExtCreatePen(penstyle,
+ plot_style_fixed_to_int(style->stroke_width),
+ &lb, 0, NULL);
if (pen == NULL) {
DeleteObject(clipregion);
return NSERROR_INVALID;
@@ -672,7 +674,9 @@ rectangle(const struct redraw_context *ctx,
if (style->fill_type == PLOT_OP_TYPE_NONE)
lb1.lbStyle = BS_HOLLOW;
- HPEN pen = ExtCreatePen(penstyle, style->stroke_width, &lb, 0, NULL);
+ HPEN pen = ExtCreatePen(penstyle,
+ plot_style_fixed_to_int(style->stroke_width),
+ &lb, 0, NULL);
if (pen == NULL) {
return NSERROR_INVALID;
}
@@ -810,7 +814,6 @@ polygon(const struct redraw_context *ctx,
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
- * \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
@@ -819,7 +822,6 @@ path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
- float width,
const float transform[6])
{
NSLOG(plot, DEEPDEBUG, "path unimplemented");
diff --git a/frontends/windows/pointers.c b/frontends/windows/pointers.c
index a730e4bd2..333ef1a9a 100644
--- a/frontends/windows/pointers.c
+++ b/frontends/windows/pointers.c
@@ -33,7 +33,6 @@
#include "windows/schedule.h"
#include "windows/window.h"
-#include "windows/filetype.h"
#include "windows/pointers.h"
struct nsws_pointers {
diff --git a/frontends/windows/prefs.c b/frontends/windows/prefs.c
index 591b57426..d6855f5da 100644
--- a/frontends/windows/prefs.c
+++ b/frontends/windows/prefs.c
@@ -230,13 +230,6 @@ static BOOL CALLBACK options_appearance_dialog_handler(HWND hwnd,
sub = GetDlgItem(hwnd, IDC_PREFS_NOANIMATION);
SendMessage(sub, BM_SETCHECK, (WPARAM)((nsoption_bool(animate_images))
? BST_UNCHECKED : BST_CHECKED), 0);
-
- if (nsoption_int(minimum_gif_delay) != 0) {
- sub = GetDlgItem(hwnd, IDC_PREFS_ANIMATIONDELAY);
- snprintf(number, 6, "%.1f", nsoption_int(minimum_gif_delay) /
- 100.0);
- SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number);
- }
break;
case WM_NOTIFY:
@@ -268,18 +261,6 @@ static BOOL CALLBACK options_appearance_dialog_handler(HWND hwnd,
nsoption_set_bool(animate_images,
(IsDlgButtonChecked(hwnd, IDC_PREFS_NOANIMATION) == BST_CHECKED) ? true : false);
-
- sub = GetDlgItem(hwnd, IDC_PREFS_ANIMATIONDELAY);
- len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0);
- temp = malloc(len + 1);
- if (temp != NULL) {
- SendMessage(sub, WM_GETTEXT, (WPARAM)
- (len + 1), (LPARAM) temp);
- nsoption_set_int(minimum_gif_delay,
- (int)(100 * strtod(temp, NULL)));
- free(temp);
- }
-
break;
case UDN_DELTAPOS: {
@@ -292,15 +273,11 @@ static BOOL CALLBACK options_appearance_dialog_handler(HWND hwnd,
case IDC_PREFS_FONT_MINSIZE_SPIN:
change_spinner(GetDlgItem(hwnd, IDC_PREFS_FONT_MINSIZE), 0.1 * ud->iDelta, 1.0, 50.0);
return TRUE;
-
- case IDC_PREFS_ANIMATIONDELAY_SPIN:
- change_spinner(GetDlgItem(hwnd, IDC_PREFS_ANIMATIONDELAY), 0.1 * ud->iDelta, 0.1, 100.0);
- return TRUE;
-
}
}
break;
}
+ break;
case WM_COMMAND:
@@ -699,7 +676,7 @@ nserror nsws_prefs_save(void)
char *choices = NULL;
nserror res;
- res = netsurf_mkpath(&choices, NULL, 2, nsw32_config_home, "Choices");
+ res = netsurf_mkpath(&choices, NULL, 2, G_config_path, "Choices");
if (res == NSERROR_OK) {
nsoption_write(choices, NULL, NULL);
free(choices);
@@ -718,7 +695,7 @@ void nsws_prefs_dialog_init(HINSTANCE hinst, HWND parent)
psp[0].dwSize = sizeof(PROPSHEETPAGE);
psp[0].dwFlags = 0;/*PSP_USEICONID*/
psp[0].hInstance = hinst;
- psp[0].pszTemplate = MAKEINTRESOURCE(IDD_DLG_OPTIONS_GENERAL);
+ psp[0].pszTemplate = MAKEINTRESOURCE(IDD_OPTIONS_GENERAL);
psp[0].pfnDlgProc = options_general_dialog_handler;
psp[0].lParam = 0;
psp[0].pfnCallback = NULL;
@@ -726,7 +703,7 @@ void nsws_prefs_dialog_init(HINSTANCE hinst, HWND parent)
psp[1].dwSize = sizeof(PROPSHEETPAGE);
psp[1].dwFlags = 0;/*PSP_USEICONID*/
psp[1].hInstance = hinst;
- psp[1].pszTemplate = MAKEINTRESOURCE(IDD_DLG_OPTIONS_CONNECTIONS);
+ psp[1].pszTemplate = MAKEINTRESOURCE(IDD_OPTIONS_CONNECTIONS);
psp[1].pfnDlgProc = options_connections_dialog_handler;
psp[1].lParam = 0;
psp[1].pfnCallback = NULL;
@@ -734,7 +711,7 @@ void nsws_prefs_dialog_init(HINSTANCE hinst, HWND parent)
psp[2].dwSize = sizeof(PROPSHEETPAGE);
psp[2].dwFlags = 0;/*PSP_USEICONID*/
psp[2].hInstance = hinst;
- psp[2].pszTemplate = MAKEINTRESOURCE(IDD_DLG_OPTIONS_APPERANCE);
+ psp[2].pszTemplate = MAKEINTRESOURCE(IDD_OPTIONS_APPERANCE);
psp[2].pfnDlgProc = options_appearance_dialog_handler;
psp[2].lParam = 0;
psp[2].pfnCallback = NULL;
diff --git a/frontends/windows/res/icons/arrow-l.png b/frontends/windows/res/icons/arrow-l.png
new file mode 120000
index 000000000..6e580c561
--- /dev/null
+++ b/frontends/windows/res/icons/arrow-l.png
@@ -0,0 +1 @@
+../../../../resources/icons/arrow-l.png \ No newline at end of file
diff --git a/frontends/windows/res/icons/content.png b/frontends/windows/res/icons/content.png
new file mode 120000
index 000000000..dd71532dc
--- /dev/null
+++ b/frontends/windows/res/icons/content.png
@@ -0,0 +1 @@
+../../../../resources/icons/content.png \ No newline at end of file
diff --git a/frontends/windows/res/icons/directory.png b/frontends/windows/res/icons/directory.png
new file mode 120000
index 000000000..71aee69d5
--- /dev/null
+++ b/frontends/windows/res/icons/directory.png
@@ -0,0 +1 @@
+../../../../resources/icons/directory.png \ No newline at end of file
diff --git a/frontends/windows/res/icons/directory2.png b/frontends/windows/res/icons/directory2.png
new file mode 120000
index 000000000..4daa093d0
--- /dev/null
+++ b/frontends/windows/res/icons/directory2.png
@@ -0,0 +1 @@
+../../../../resources/icons/directory2.png \ No newline at end of file
diff --git a/frontends/windows/res/icons/hotlist-add.png b/frontends/windows/res/icons/hotlist-add.png
new file mode 120000
index 000000000..5039509fc
--- /dev/null
+++ b/frontends/windows/res/icons/hotlist-add.png
@@ -0,0 +1 @@
+../../../../resources/icons/hotlist-add.png \ No newline at end of file
diff --git a/frontends/windows/res/icons/hotlist-rmv.png b/frontends/windows/res/icons/hotlist-rmv.png
new file mode 120000
index 000000000..2b592cd13
--- /dev/null
+++ b/frontends/windows/res/icons/hotlist-rmv.png
@@ -0,0 +1 @@
+../../../../resources/icons/hotlist-rmv.png \ No newline at end of file
diff --git a/frontends/windows/res/icons/search.png b/frontends/windows/res/icons/search.png
new file mode 120000
index 000000000..e30f7bee8
--- /dev/null
+++ b/frontends/windows/res/icons/search.png
@@ -0,0 +1 @@
+../../../../resources/icons/search.png \ No newline at end of file
diff --git a/frontends/windows/res/installer.nsi b/frontends/windows/res/installer.nsi
index 17afee26d..2f8b757d8 100644
--- a/frontends/windows/res/installer.nsi
+++ b/frontends/windows/res/installer.nsi
@@ -13,16 +13,16 @@
!define VERSIONMAJOR 3
!endif
!ifndef VERSIONMINOR
- !define VERSIONMINOR 7
+ !define VERSIONMINOR 11
!endif
!ifndef VERSIONBUILD
!define VERSIONBUILD 0
!endif
# These will be displayed by the "Click here for support information" link in "Add/Remove Programs"
-!define HELPURL "http://www.netsurf-browser.org/" # "Support Information" link
-!define UPDATEURL "http://www.netsurf-browser.org/" # "Product Updates" link
-!define ABOUTURL "http://www.netsurf-browser.org/" # "Publisher" link
+!define HELPURL "https://www.netsurf-browser.org/" # "Support Information" link
+!define UPDATEURL "https://www.netsurf-browser.org/" # "Product Updates" link
+!define ABOUTURL "https://www.netsurf-browser.org/" # "Publisher" link
# This is the size (in kB) of all the files copied into "Program Files"
!define INSTALLSIZE 9000
diff --git a/frontends/windows/res/page-info-insecure.bmp b/frontends/windows/res/page-info-insecure.bmp
new file mode 100644
index 000000000..d8e15c318
--- /dev/null
+++ b/frontends/windows/res/page-info-insecure.bmp
Binary files differ
diff --git a/frontends/windows/res/page-info-internal.bmp b/frontends/windows/res/page-info-internal.bmp
new file mode 100644
index 000000000..b9b4eabd5
--- /dev/null
+++ b/frontends/windows/res/page-info-internal.bmp
Binary files differ
diff --git a/frontends/windows/res/page-info-local.bmp b/frontends/windows/res/page-info-local.bmp
new file mode 100644
index 000000000..51cd5964b
--- /dev/null
+++ b/frontends/windows/res/page-info-local.bmp
Binary files differ
diff --git a/frontends/windows/res/page-info-secure.bmp b/frontends/windows/res/page-info-secure.bmp
new file mode 100644
index 000000000..b08809c66
--- /dev/null
+++ b/frontends/windows/res/page-info-secure.bmp
Binary files differ
diff --git a/frontends/windows/res/page-info-warning.bmp b/frontends/windows/res/page-info-warning.bmp
new file mode 100644
index 000000000..8e6b3afeb
--- /dev/null
+++ b/frontends/windows/res/page-info-warning.bmp
Binary files differ
diff --git a/frontends/windows/res/resource.rc b/frontends/windows/res/resource.rc
index 192cd57c7..9e9927b0c 100644
--- a/frontends/windows/res/resource.rc
+++ b/frontends/windows/res/resource.rc
@@ -1,269 +1,345 @@
+// Generated by ResEdit 1.6.6
+
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include "../resourceid.h"
+//
+// Bitmap resources
+//
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDR_HOME_BITMAP BITMAP "home.bmp"
-IDR_NETSURF_ICON ICON DISCARDABLE "NetSurf.ico"
-IDR_TOOLBAR_BITMAP BITMAP DISCARDABLE "toolbar.bmp"
-IDR_TOOLBAR_BITMAP_GREY BITMAP DISCARDABLE "toolbarg.bmp"
-IDR_TOOLBAR_BITMAP_HOT BITMAP DISCARDABLE "toolbarh.bmp"
-IDR_NETSURF_BANNER BITMAP DISCARDABLE "banner.bmp"
-IDR_HOME_BITMAP BITMAP DISCARDABLE "home.bmp"
-
-IDR_THROBBER_FRAME0_BITMAP BITMAP DISCARDABLE "throbber/throbber0.bmp"
-IDR_THROBBER_FRAME1_BITMAP BITMAP DISCARDABLE "throbber/throbber1.bmp"
-IDR_THROBBER_FRAME2_BITMAP BITMAP DISCARDABLE "throbber/throbber2.bmp"
-IDR_THROBBER_FRAME3_BITMAP BITMAP DISCARDABLE "throbber/throbber3.bmp"
-IDR_THROBBER_FRAME4_BITMAP BITMAP DISCARDABLE "throbber/throbber4.bmp"
-IDR_THROBBER_FRAME5_BITMAP BITMAP DISCARDABLE "throbber/throbber5.bmp"
-IDR_THROBBER_FRAME6_BITMAP BITMAP DISCARDABLE "throbber/throbber6.bmp"
-IDR_THROBBER_FRAME7_BITMAP BITMAP DISCARDABLE "throbber/throbber7.bmp"
-
-IDR_MENU_MAIN MENU
-BEGIN
- POPUP "&File"
- BEGIN
- MENUITEM "&New Window",IDM_FILE_OPEN_WINDOW
- MENUITEM "Open &Location",IDM_FILE_OPEN_LOCATION
- MENUITEM "&Close",IDM_FILE_CLOSE_WINDOW
- MENUITEM SEPARATOR
- MENUITEM "&Save Page",IDM_FILE_SAVE_PAGE,GRAYED,HELP
- POPUP "Save Page &As"
- BEGIN
- MENUITEM "Text",IDM_FILE_SAVEAS_TEXT,GRAYED
- MENUITEM "PDF",IDM_FILE_SAVEAS_PDF,GRAYED
- MENUITEM "Postscript",IDM_FILE_SAVEAS_POSTSCRIPT,GRAYED
- END
- MENUITEM SEPARATOR
- MENUITEM "Print Pre&view",IDM_FILE_PRINT_PREVIEW
- MENUITEM "&Print",IDM_FILE_PRINT
- MENUITEM SEPARATOR
- MENUITEM "E&xit",IDM_FILE_QUIT
- END
- POPUP "&Edit"
- BEGIN
- MENUITEM "Cu&t",IDM_EDIT_CUT
- MENUITEM "&Copy",IDM_EDIT_COPY
- MENUITEM "&Paste",IDM_EDIT_PASTE
- MENUITEM "&Delete",IDM_EDIT_DELETE
- MENUITEM SEPARATOR
- MENUITEM "Select &All",IDM_EDIT_SELECT_ALL
- MENUITEM SEPARATOR
- MENUITEM "&Find",IDM_EDIT_SEARCH
- END
- POPUP "&View"
- BEGIN
- MENUITEM "Stop",IDM_NAV_STOP
- MENUITEM "Reload",IDM_NAV_RELOAD
- MENUITEM SEPARATOR
- POPUP "&Zoom"
- BEGIN
- MENUITEM "Zoom &In",IDM_VIEW_ZOOMPLUS
- MENUITEM "Zoom &Out",IDM_VIEW_ZOOMMINUS
- MENUITEM "&Reset",IDM_VIEW_ZOOMNORMAL
- END
- MENUITEM SEPARATOR
- MENUITEM "Page S&ource",IDM_VIEW_SOURCE
- MENUITEM "&Full Screen",IDM_VIEW_FULLSCREEN
- MENUITEM SEPARATOR
- MENUITEM "Save size and location",IDM_VIEW_SAVE_WIN_METRICS
- END
- POPUP "&Navigate"
- BEGIN
- MENUITEM "Back",IDM_NAV_BACK
- MENUITEM "Forward",IDM_NAV_FORWARD
- MENUITEM "Home",IDM_NAV_HOME
- MENUITEM SEPARATOR
- MENUITEM "Local History",IDM_NAV_LOCALHISTORY
- MENUITEM "Global History",IDM_NAV_GLOBALHISTORY
- MENUITEM SEPARATOR
- MENUITEM "Show Bookmarks",IDM_NAV_BOOKMARKS
- END
- POPUP "&Tools"
- BEGIN
- MENUITEM "&Downloads",IDM_TOOLS_DOWNLOADS
- MENUITEM "&Show Cookies",IDM_TOOLS_COOKIES
- POPUP "Debugging"
- BEGIN
- MENUITEM "Debug rendering",IDM_VIEW_TOGGLE_DEBUG_RENDERING
- MENUITEM "Save Box Tree",IDM_VIEW_DEBUGGING_SAVE_BOXTREE,GRAYED
- MENUITEM "Save DOM Tree",IDM_VIEW_DEBUGGING_SAVE_DOMTREE,GRAYED
- END
- MENUITEM SEPARATOR
- MENUITEM "Options...",IDM_EDIT_PREFERENCES
- END
- POPUP "&Help"
- BEGIN
- MENUITEM "&Contents",IDM_HELP_CONTENTS
- MENUITEM "G&uide",IDM_HELP_GUIDE
- MENUITEM "&Info",IDM_HELP_INFO
- MENUITEM SEPARATOR
- MENUITEM "&About NetSurf",IDM_HELP_ABOUT
- END
-END
-
-IDR_MENU_CONTEXT MENU
-BEGIN
- POPUP "Context"
- BEGIN
- MENUITEM "&Back",IDM_NAV_BACK
- MENUITEM "F&orward",IDM_NAV_FORWARD
- MENUITEM "&Home",IDM_NAV_HOME
- MENUITEM "&Stop",IDM_NAV_STOP
- MENUITEM "&Reload",IDM_NAV_RELOAD
- MENUITEM SEPARATOR
- MENUITEM "C&ut",IDM_EDIT_CUT,GRAYED
- MENUITEM "&Copy",IDM_EDIT_COPY,GRAYED
- MENUITEM "&Paste",IDM_EDIT_PASTE,GRAYED
- MENUITEM "&Delete",IDM_EDIT_DELETE,GRAYED
- END
-END
-
-IDD_DLG_ABOUT DIALOGEX 10,10,206,133
-CAPTION "About NetSurf"
-FONT 8,"MS Sans Serif",0,0,0
-STYLE WS_VISIBLE|WS_CAPTION|WS_SYSMENU
-EXSTYLE WS_EX_DLGMODALFRAME
-BEGIN
- CONTROL IDR_NETSURF_BANNER,IDC_IMG1,"Static",SS_BITMAP|0x40L /*SS_REALSIZECONTROL*/,0,0,205,53
- CONTROL "NetSurf",IDC_ABOUT_VERSION,"Static",SS_LEFT,10,60,185,16
- CONTROL "NetSurf is a small fast browser",IDC_ABOUT_TEXT,"Static",SS_LEFT,10,83,185,8
- CONTROL "Copyright 2003-2011 The NetSurf Developers",IDC_ABOUT_COPYRIGHT,"Static",SS_LEFT,10,96,185,8
- CONTROL "&OK",IDOK,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,143,111,54,15
- CONTROL "&Credits",IDC_BTN_CREDITS,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,10,111,54,15
- CONTROL "&Licence",IDC_BTN_LICENCE,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,70,111,54,15
-END
-
-IDD_DLG_DOWNLOAD DIALOGEX 0,0,201,84
-CAPTION "Download"
-FONT 8,"MS Sans Serif",0,0,0
-STYLE WS_POPUP|WS_VISIBLE|WS_CAPTION|WS_SYSMENU|DS_MODALFRAME|DS_SETFONT
-EXSTYLE WS_EX_DLGMODALFRAME
-BEGIN
- CONTROL "downloading [file] [size] from [domain] to [destination]",IDC_DOWNLOAD_LABEL,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_CENTER,6,6,189,35
- CONTROL "progress",IDC_DOWNLOAD_PROGRESS,PROGRESS_CLASS,WS_VISIBLE,6,50,189,10
- CONTROL "&OK",IDOK,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,141,66,54,15
- CONTROL "&Cancel",IDCANCEL,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,81,66,54,15
-END
-
-
-IDD_DLG_OPTIONS_GENERAL DIALOGEX 0,0,220,200
-CAPTION "General"
-FONT 8,"MS Shell Dlg"
-STYLE DS_CONTROL|DS_SHELLFONT
-BEGIN
- /* home page entry */
- CONTROL "Home Page",IDC_STATIC,"Static",SS_LEFT,7,7,40,8
- CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,47,11,166,1
- CONTROL IDR_HOME_BITMAP,IDC_STATIC,"Static",SS_BITMAP,15,19,24,24
- CONTROL "",IDC_PREFS_HOMEPAGE,"Edit",WS_TABSTOP|ES_OEMCONVERT|ES_AUTOHSCROLL,43,19,170,14,WS_EX_CLIENTEDGE
-
-
- /* Content control */
- CONTROL "Content Control",IDC_STATIC,"Static",SS_LEFT,7,40,60,8
- CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,67,44,146,1
-
- CONTROL "Hide Images",IDC_PREFS_IMAGES,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,43,52,67,10
- CONTROL "Hide Advertisements",IDC_PREFS_ADVERTS,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,43,66,81,10
- CONTROL "Send referer",IDC_PREFS_REFERER,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,43,80,55,10
-
-END
-
-IDD_DLG_OPTIONS_CONNECTIONS DIALOGEX 0,0,220,200
-CAPTION "Connections"
-FONT 8,"MS Shell Dlg"
-STYLE DS_CONTROL|DS_SHELLFONT
-BEGIN
- /* proxy divider */
- CONTROL "Proxy",IDC_STATIC,"Static",SS_LEFT,7,7,30,8
- CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,37,11,176,1
-
- /* proxy controls */
- CONTROL "Type:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,22,40,8
- CONTROL "",IDC_PREFS_PROXYTYPE,"ComboBox",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|CBS_DROPDOWNLIST,80,19,60,60
-
- CONTROL "Server:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,39,28,8
- CONTROL "",IDC_PREFS_PROXYHOST,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|ES_OEMCONVERT|ES_AUTOHSCROLL,80,36,80,14,WS_EX_CLIENTEDGE
-
- CONTROL "Port:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,164,39,16,8
- CONTROL "",IDC_PREFS_PROXYPORT,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|ES_OEMCONVERT|ES_AUTOHSCROLL,182,36,24,14,WS_EX_CLIENTEDGE
- CONTROL "Username:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,60,35,8
- CONTROL "",IDC_PREFS_PROXYNAME,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|ES_OEMCONVERT|ES_AUTOHSCROLL,80,57,45,14,WS_EX_CLIENTEDGE
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDR_NETSURF_BANNER BITMAP "banner.bmp"
- CONTROL "Password:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,132,60,34,8
- CONTROL "",IDC_PREFS_PROXYPASS,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|ES_OEMCONVERT|ES_AUTOHSCROLL|ES_PASSWORD,168,57,45,14,WS_EX_CLIENTEDGE
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDR_TOOLBAR_BITMAP BITMAP "toolbar.bmp"
- /* fetcher divider */
- CONTROL "Fetchers",IDC_STATIC,"Static",SS_LEFT,7,78,40,8
- CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,42,82,171,1
- /* max fetchers */
- CONTROL "Max Fetchers:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP,43,96,64,8
- CONTROL "",IDC_PREFS_FETCHERS,"Edit",ES_NUMBER|ES_RIGHT|WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|WS_BORDER,111,93,30,14
- CONTROL "Max Fetchers",IDC_PREFS_FETCHERS_SPIN,UPDOWN_CLASS,UDS_AUTOBUDDY|UDS_ALIGNRIGHT|WS_VISIBLE,341,122,11,15
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDR_TOOLBAR_BITMAP_GREY BITMAP "toolbarg.bmp"
- /* fetchers per host */
- CONTROL "Fetches per host:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP,43,118,64,8
- CONTROL "",IDC_PREFS_FETCH_HOST,"Edit",ES_NUMBER|ES_RIGHT|WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|WS_BORDER,111,114,30,14
- CONTROL "Fetches per host",IDC_PREFS_FETCH_HOST_SPIN,UPDOWN_CLASS,UDS_AUTOBUDDY|UDS_ALIGNRIGHT|WS_VISIBLE,341,140,11,15
- /* cached fetchers */
- CONTROL "Cached Fetches:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP,43,138,64,8
- CONTROL "",IDC_PREFS_FETCH_HANDLES,"Edit",ES_NUMBER|ES_RIGHT|WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|WS_BORDER,111,135,30,14
- CONTROL "Cached Fetches",IDC_PREFS_FETCH_HANDLES_SPIN,UPDOWN_CLASS,UDS_AUTOBUDDY|UDS_ALIGNRIGHT|WS_VISIBLE,341,158,11,15
-
-END
-
-IDD_DLG_OPTIONS_APPERANCE DIALOGEX 10,10,220,200
-CAPTION "Apperance"
-FONT 8,"MS Shell Dlg"
-STYLE DS_CONTROL|DS_SHELLFONT
-BEGIN
- /* proxy separator */
- CONTROL "Fonts",IDC_STATIC,"Static",SS_LEFT,7,7,20,8
- CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,27,11,186,1
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDR_TOOLBAR_BITMAP_HOT BITMAP "toolbarh.bmp"
- /* font controls */
- CONTROL "Sans-serif:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,22,44,8
- CONTROL "Sans-serif",IDC_PREFS_SANS,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,89,19,50,14
- CONTROL "Serif:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,40,24,8
- CONTROL "Serif",IDC_PREFS_SERIF,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,89,37,50,14
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDR_THROBBER_AVI AVI "throbber.avi"
- CONTROL "Monospace:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,58,40,8
- CONTROL "Monospace",IDC_PREFS_MONO,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,89,55,50,14
- CONTROL "Cursive:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,76,32,8
- CONTROL "Cursive",IDC_PREFS_CURSIVE,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,89,73,50,14
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDB_PAGEINFO_INSECURE BITMAP "page-info-insecure.bmp"
- CONTROL "Fantasy:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,94,32,8
- CONTROL "Fantasy",IDC_PREFS_FANTASY,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,89,91,50,14
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDB_PAGEINFO_SECURE BITMAP "page-info-secure.bmp"
- CONTROL "Default:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,112,38,8
- CONTROL "",IDC_PREFS_FONTDEF,"ComboBox",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|CBS_DROPDOWNLIST,89,109,50,60
- CONTROL "Size:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,147,112,16,8
- CONTROL "",IDC_PREFS_FONT_SIZE,"Edit",ES_NUMBER|WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,165,109,35,14,WS_EX_CLIENTEDGE
- CONTROL "Font Size",IDC_PREFS_FONT_SIZE_SPIN,UPDOWN_CLASS,UDS_AUTOBUDDY|UDS_ALIGNRIGHT|WS_VISIBLE,75,137,11,15
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDB_PAGEINFO_INTERNAL BITMAP "page-info-internal.bmp"
- CONTROL "Minimum Size:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,130,52,8
- CONTROL "",IDC_PREFS_FONT_MINSIZE,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,97,127,35,14,WS_EX_CLIENTEDGE
- CONTROL "Minimum Font Size",IDC_PREFS_FONT_MINSIZE_SPIN,UPDOWN_CLASS,UDS_AUTOBUDDY|UDS_ALIGNRIGHT|WS_VISIBLE,76,159,11,15
- /* animation separator */
- CONTROL "Animation",IDC_STATIC,"Static",SS_LEFT,7,148,36,8
- CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,43,152,170,1
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDB_PAGEINFO_WARNING BITMAP "page-info-warning.bmp"
- CONTROL "Disable",IDC_PREFS_NOANIMATION,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,43,163,39,10
- CONTROL "Minimum delay:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,55,180,56,8
- CONTROL "",IDC_PREFS_ANIMATIONDELAY,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,113,177,35,14,WS_EX_CLIENTEDGE
- CONTROL "Min delay",IDC_PREFS_ANIMATIONDELAY_SPIN,UPDOWN_CLASS,UDS_AUTOBUDDY|UDS_ALIGNRIGHT|WS_VISIBLE,43,210,11,15
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDB_PAGEINFO_LOCAL BITMAP "page-info-local.bmp"
-END
+//
+// Menu resources
+//
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDR_MENU_CONTEXT MENU
+{
+ POPUP "Context"
+ {
+ MENUITEM "&Back", IDM_NAV_BACK
+ MENUITEM "F&orward", IDM_NAV_FORWARD
+ MENUITEM "&Home", IDM_NAV_HOME
+ MENUITEM "&Stop", IDM_NAV_STOP
+ MENUITEM "&Reload", IDM_NAV_RELOAD
+ MENUITEM SEPARATOR
+ MENUITEM "C&ut", IDM_EDIT_CUT, GRAYED
+ MENUITEM "&Copy", IDM_EDIT_COPY, GRAYED
+ MENUITEM "&Paste", IDM_EDIT_PASTE, GRAYED
+ MENUITEM "&Delete", IDM_EDIT_DELETE, GRAYED
+ }
+}
+
+
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDR_MENU_MAIN MENU
+{
+ POPUP "&File"
+ {
+ MENUITEM "&New Window", IDM_FILE_OPEN_WINDOW
+ MENUITEM "Open &Location", IDM_FILE_OPEN_LOCATION
+ MENUITEM "&Close", IDM_FILE_CLOSE_WINDOW
+ MENUITEM SEPARATOR
+ MENUITEM "&Save Page", IDM_FILE_SAVE_PAGE, HELP, GRAYED
+ POPUP "Save Page &As"
+ {
+ MENUITEM "Text", IDM_FILE_SAVEAS_TEXT, GRAYED
+ MENUITEM "PDF", IDM_FILE_SAVEAS_PDF, GRAYED
+ MENUITEM "Postscript", IDM_FILE_SAVEAS_POSTSCRIPT, GRAYED
+ }
+ MENUITEM SEPARATOR
+ MENUITEM "Print Pre&view", IDM_FILE_PRINT_PREVIEW
+ MENUITEM "&Print", IDM_FILE_PRINT
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", IDM_FILE_QUIT
+ }
+ POPUP "&Edit"
+ {
+ MENUITEM "Cu&t", IDM_EDIT_CUT
+ MENUITEM "&Copy", IDM_EDIT_COPY
+ MENUITEM "&Paste", IDM_EDIT_PASTE
+ MENUITEM "&Delete", IDM_EDIT_DELETE
+ MENUITEM SEPARATOR
+ MENUITEM "Select &All", IDM_EDIT_SELECT_ALL
+ MENUITEM SEPARATOR
+ MENUITEM "&Find", IDM_EDIT_SEARCH
+ }
+ POPUP "&View"
+ {
+ MENUITEM "Stop", IDM_NAV_STOP
+ MENUITEM "Reload", IDM_NAV_RELOAD
+ MENUITEM SEPARATOR
+ POPUP "&Zoom"
+ {
+ MENUITEM "Zoom &In", IDM_VIEW_ZOOMPLUS
+ MENUITEM "Zoom &Out", IDM_VIEW_ZOOMMINUS
+ MENUITEM "&Reset", IDM_VIEW_ZOOMNORMAL
+ }
+ MENUITEM SEPARATOR
+ MENUITEM "Page S&ource", IDM_VIEW_SOURCE
+ MENUITEM "&Full Screen", IDM_VIEW_FULLSCREEN
+ MENUITEM SEPARATOR
+ MENUITEM "Save size and location", IDM_VIEW_SAVE_WIN_METRICS
+ }
+ POPUP "&Navigate"
+ {
+ MENUITEM "Back", IDM_NAV_BACK
+ MENUITEM "Forward", IDM_NAV_FORWARD
+ MENUITEM "Home", IDM_NAV_HOME
+ MENUITEM SEPARATOR
+ MENUITEM "Local History", IDM_NAV_LOCALHISTORY
+ MENUITEM "Global History", IDM_NAV_GLOBALHISTORY
+ MENUITEM SEPARATOR
+ MENUITEM "Show Bookmarks", IDM_NAV_BOOKMARKS
+ }
+ POPUP "&Tools"
+ {
+ MENUITEM "&Downloads", IDM_TOOLS_DOWNLOADS
+ MENUITEM "&Show Cookies", IDM_TOOLS_COOKIES
+ POPUP "Debugging"
+ {
+ MENUITEM "Debug rendering", IDM_VIEW_TOGGLE_DEBUG_RENDERING
+ MENUITEM "Save Box Tree", IDM_VIEW_DEBUGGING_SAVE_BOXTREE, GRAYED
+ MENUITEM "Save DOM Tree", IDM_VIEW_DEBUGGING_SAVE_DOMTREE, GRAYED
+ }
+ MENUITEM SEPARATOR
+ MENUITEM "Options...", IDM_EDIT_PREFERENCES
+ }
+ POPUP "&Help"
+ {
+ MENUITEM "&Contents", IDM_HELP_CONTENTS
+ MENUITEM "G&uide", IDM_HELP_GUIDE
+ MENUITEM "&Info", IDM_HELP_INFO
+ MENUITEM SEPARATOR
+ MENUITEM "&About NetSurf", IDM_HELP_ABOUT
+ }
+}
+
+
+
+//
+// Dialog resources
+//
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDD_ABOUT DIALOGEX 10, 10, 206, 133
+STYLE DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_SYSMENU
+CAPTION "About NetSurf"
+FONT 8, "Ms Shell Dlg"
+{
+ CONTROL IDR_NETSURF_BANNER, IDC_IMG1, WC_STATIC, SS_BITMAP | SS_REALSIZECONTROL, 0, 0, 205, 53, WS_EX_LEFT
+ LTEXT "NetSurf", IDC_ABOUT_VERSION, 10, 60, 185, 16, NOT WS_GROUP | SS_LEFT, WS_EX_LEFT
+ LTEXT "NetSurf is a small fast browser", IDC_ABOUT_TEXT, 10, 83, 185, 8, NOT WS_GROUP | SS_LEFT, WS_EX_LEFT
+ LTEXT "Copyright 2003-2011 The NetSurf Developers", IDC_ABOUT_COPYRIGHT, 10, 96, 185, 8, NOT WS_GROUP | SS_LEFT, WS_EX_LEFT
+ PUSHBUTTON "&OK", IDOK, 143, 111, 54, 15, 0, WS_EX_LEFT
+ PUSHBUTTON "&Credits", IDC_BTN_CREDITS, 10, 111, 54, 15, 0, WS_EX_LEFT
+ PUSHBUTTON "&Licence", IDC_BTN_LICENCE, 70, 111, 54, 15, 0, WS_EX_LEFT
+}
+
+
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDD_DOWNLOAD DIALOGEX 0, 0, 201, 84
+STYLE DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
+CAPTION "Download"
+FONT 8, "Ms Shell Dlg"
+{
+ CTEXT "downloading [file] [size] from [domain] to [destination]", IDC_DOWNLOAD_LABEL, 6, 6, 189, 35, SS_CENTER, WS_EX_LEFT
+ CONTROL "progress", IDC_DOWNLOAD_PROGRESS, PROGRESS_CLASS, 0, 6, 50, 189, 10, WS_EX_LEFT
+ PUSHBUTTON "&OK", IDOK, 141, 66, 54, 15, 0, WS_EX_LEFT
+ PUSHBUTTON "&Cancel", IDCANCEL, 81, 66, 54, 15, 0, WS_EX_LEFT
+}
+
+
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDD_LOGIN DIALOGEX 0, 0, 280, 93
+STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
+CAPTION "Log In"
+FONT 8, "Ms Shell Dlg"
+{
+ LTEXT "Password:", 0, 7, 53, 35, 9, SS_LEFT, WS_EX_LEFT
+ LTEXT "User name:", 0, 7, 35, 40, 9, SS_LEFT, WS_EX_LEFT
+ LTEXT "The site foo.bar requires authorization for a realm", IDC_LOGIN_DESCRIPTION, 49, 7, 224, 18, SS_LEFT, WS_EX_LEFT
+ EDITTEXT IDC_LOGIN_USERNAME, 49, 32, 224, 14, ES_AUTOHSCROLL, WS_EX_LEFT
+ EDITTEXT IDC_LOGIN_PASSWORD, 49, 50, 224, 14, ES_AUTOHSCROLL | ES_PASSWORD, WS_EX_LEFT
+ DEFPUSHBUTTON "Log in", IDOK, 169, 71, 50, 14, 0, WS_EX_LEFT
+ PUSHBUTTON "Cancel", IDCANCEL, 223, 71, 50, 14, 0, WS_EX_LEFT
+}
+
+
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDD_OPTIONS_APPERANCE DIALOGEX 10, 10, 220, 200
+STYLE DS_CONTROL | DS_SHELLFONT
+CAPTION "Apperance"
+FONT 8, "MS Shell Dlg", 0, 0, 1
+{
+ LTEXT "Fonts", IDC_STATIC, 7, 7, 20, 8, NOT WS_GROUP | SS_LEFT, WS_EX_LEFT
+ CONTROL "", IDC_STATIC, WC_STATIC, SS_ETCHEDFRAME, 27, 11, 186, 1, WS_EX_LEFT
+ LTEXT "Sans-serif:", IDC_STATIC, 43, 22, 44, 8, SS_LEFT, WS_EX_LEFT
+ PUSHBUTTON "Sans-serif", IDC_PREFS_SANS, 89, 19, 50, 14, 0, WS_EX_LEFT
+ LTEXT "Serif:", IDC_STATIC, 43, 40, 24, 8, SS_LEFT, WS_EX_LEFT
+ PUSHBUTTON "Serif", IDC_PREFS_SERIF, 89, 37, 50, 14, 0, WS_EX_LEFT
+ LTEXT "Monospace:", IDC_STATIC, 43, 58, 40, 8, SS_LEFT, WS_EX_LEFT
+ PUSHBUTTON "Monospace", IDC_PREFS_MONO, 89, 55, 50, 14, 0, WS_EX_LEFT
+ LTEXT "Cursive:", IDC_STATIC, 43, 76, 32, 8, SS_LEFT, WS_EX_LEFT
+ PUSHBUTTON "Cursive", IDC_PREFS_CURSIVE, 89, 73, 50, 14, 0, WS_EX_LEFT
+ LTEXT "Fantasy:", IDC_STATIC, 43, 94, 32, 8, SS_LEFT, WS_EX_LEFT
+ PUSHBUTTON "Fantasy", IDC_PREFS_FANTASY, 89, 91, 50, 14, 0, WS_EX_LEFT
+ LTEXT "Default:", IDC_STATIC, 43, 112, 38, 8, SS_LEFT, WS_EX_LEFT
+ COMBOBOX IDC_PREFS_FONTDEF, 89, 109, 50, 60, WS_TABSTOP | CBS_DROPDOWNLIST, WS_EX_LEFT
+ LTEXT "Size:", IDC_STATIC, 147, 112, 16, 8, SS_LEFT, WS_EX_LEFT
+ EDITTEXT IDC_PREFS_FONT_SIZE, 165, 109, 35, 14, NOT WS_BORDER | ES_NUMBER, WS_EX_CLIENTEDGE
+ CONTROL "Font Size", IDC_PREFS_FONT_SIZE_SPIN, UPDOWN_CLASS, UDS_ALIGNRIGHT | UDS_AUTOBUDDY, 75, 137, 11, 15, WS_EX_LEFT
+ LTEXT "Minimum Size:", IDC_STATIC, 43, 130, 52, 8, SS_LEFT, WS_EX_LEFT
+ EDITTEXT IDC_PREFS_FONT_MINSIZE, 97, 127, 35, 14, NOT WS_BORDER, WS_EX_CLIENTEDGE
+ CONTROL "Minimum Font Size", IDC_PREFS_FONT_MINSIZE_SPIN, UPDOWN_CLASS, UDS_ALIGNRIGHT | UDS_AUTOBUDDY, 76, 159, 11, 15, WS_EX_LEFT
+ LTEXT "Animation", IDC_STATIC, 7, 148, 36, 8, NOT WS_GROUP | SS_LEFT, WS_EX_LEFT
+ CONTROL "", IDC_STATIC, WC_STATIC, SS_ETCHEDFRAME, 43, 152, 170, 1, WS_EX_LEFT
+ AUTOCHECKBOX "Disable", IDC_PREFS_NOANIMATION, 43, 163, 39, 10, 0, WS_EX_LEFT
+}
+
+
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDD_OPTIONS_CONNECTIONS DIALOGEX 0, 0, 220, 200
+STYLE DS_CONTROL | DS_SHELLFONT
+CAPTION "Connections"
+FONT 8, "MS Shell Dlg", 0, 0, 1
+{
+ LTEXT "Proxy", IDC_STATIC, 7, 7, 30, 8, NOT WS_GROUP | SS_LEFT, WS_EX_LEFT
+ CONTROL "", IDC_STATIC, WC_STATIC, SS_ETCHEDFRAME, 37, 11, 176, 1, WS_EX_LEFT
+ LTEXT "Type:", IDC_STATIC, 43, 22, 40, 8, SS_LEFT, WS_EX_LEFT
+ COMBOBOX IDC_PREFS_PROXYTYPE, 80, 19, 60, 60, WS_TABSTOP | CBS_DROPDOWNLIST, WS_EX_LEFT
+ LTEXT "Server:", IDC_STATIC, 43, 39, 28, 8, SS_LEFT, WS_EX_LEFT
+ EDITTEXT IDC_PREFS_PROXYHOST, 80, 36, 80, 14, NOT WS_BORDER | ES_AUTOHSCROLL | ES_OEMCONVERT, WS_EX_CLIENTEDGE
+ LTEXT "Port:", IDC_STATIC, 164, 39, 16, 8, SS_LEFT, WS_EX_LEFT
+ EDITTEXT IDC_PREFS_PROXYPORT, 182, 36, 24, 14, NOT WS_BORDER | ES_AUTOHSCROLL | ES_OEMCONVERT, WS_EX_CLIENTEDGE
+ LTEXT "Username:", IDC_STATIC, 43, 60, 35, 8, SS_LEFT, WS_EX_LEFT
+ EDITTEXT IDC_PREFS_PROXYNAME, 80, 57, 45, 14, NOT WS_BORDER | ES_AUTOHSCROLL | ES_OEMCONVERT, WS_EX_CLIENTEDGE
+ LTEXT "Password:", IDC_STATIC, 132, 60, 34, 8, SS_LEFT, WS_EX_LEFT
+ EDITTEXT IDC_PREFS_PROXYPASS, 168, 57, 45, 14, NOT WS_BORDER | ES_AUTOHSCROLL | ES_OEMCONVERT | ES_PASSWORD, WS_EX_CLIENTEDGE
+ LTEXT "Fetchers", IDC_STATIC, 7, 78, 40, 8, NOT WS_GROUP | SS_LEFT, WS_EX_LEFT
+ CONTROL "", IDC_STATIC, WC_STATIC, SS_ETCHEDFRAME, 42, 82, 171, 1, WS_EX_LEFT
+ LTEXT "Max Fetchers:", IDC_STATIC, 43, 96, 64, 8, SS_LEFT, WS_EX_LEFT
+ EDITTEXT IDC_PREFS_FETCHERS, 111, 93, 30, 14, ES_RIGHT | ES_NUMBER, WS_EX_LEFT
+ CONTROL "Max Fetchers", IDC_PREFS_FETCHERS_SPIN, UPDOWN_CLASS, UDS_ALIGNRIGHT | UDS_AUTOBUDDY, 341, 122, 11, 15, WS_EX_LEFT
+ LTEXT "Fetches per host:", IDC_STATIC, 43, 118, 64, 8, SS_LEFT, WS_EX_LEFT
+ EDITTEXT IDC_PREFS_FETCH_HOST, 111, 114, 30, 14, ES_RIGHT | ES_NUMBER, WS_EX_LEFT
+ CONTROL "Fetches per host", IDC_PREFS_FETCH_HOST_SPIN, UPDOWN_CLASS, UDS_ALIGNRIGHT | UDS_AUTOBUDDY, 341, 140, 11, 15, WS_EX_LEFT
+ LTEXT "Cached Fetches:", IDC_STATIC, 43, 138, 64, 8, SS_LEFT, WS_EX_LEFT
+ EDITTEXT IDC_PREFS_FETCH_HANDLES, 111, 135, 30, 14, ES_RIGHT | ES_NUMBER, WS_EX_LEFT
+ CONTROL "Cached Fetches", IDC_PREFS_FETCH_HANDLES_SPIN, UPDOWN_CLASS, UDS_ALIGNRIGHT | UDS_AUTOBUDDY, 341, 158, 11, 15, WS_EX_LEFT
+}
+
+
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDD_OPTIONS_GENERAL DIALOGEX 0, 0, 220, 200
+STYLE DS_CONTROL | DS_SHELLFONT
+CAPTION "General"
+FONT 8, "MS Shell Dlg", 0, 0, 1
+{
+ LTEXT "Home Page", IDC_STATIC, 7, 7, 40, 8, NOT WS_GROUP | SS_LEFT, WS_EX_LEFT
+ CONTROL "", IDC_STATIC, WC_STATIC, SS_ETCHEDFRAME, 47, 11, 166, 1, WS_EX_LEFT
+ CONTROL IDR_HOME_BITMAP, IDC_STATIC, WC_STATIC, SS_BITMAP, 15, 19, 24, 24, WS_EX_LEFT
+ EDITTEXT IDC_PREFS_HOMEPAGE, 43, 19, 170, 14, NOT WS_BORDER | ES_AUTOHSCROLL | ES_OEMCONVERT, WS_EX_CLIENTEDGE
+ LTEXT "Content Control", IDC_STATIC, 7, 40, 60, 8, NOT WS_GROUP | SS_LEFT, WS_EX_LEFT
+ CONTROL "", IDC_STATIC, WC_STATIC, SS_ETCHEDFRAME, 67, 44, 146, 1, WS_EX_LEFT
+ AUTOCHECKBOX "Hide Images", IDC_PREFS_IMAGES, 43, 52, 67, 10, 0, WS_EX_LEFT
+ AUTOCHECKBOX "Hide Advertisements", IDC_PREFS_ADVERTS, 43, 66, 81, 10, 0, WS_EX_LEFT
+ AUTOCHECKBOX "Send referer", IDC_PREFS_REFERER, 43, 80, 55, 10, 0, WS_EX_LEFT
+}
+
+
+
+//
+// Icon resources
+//
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDR_NETSURF_ICON ICON "NetSurf.ico"
+
+
+//
+// User resources
+//
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+default.css USER "default.css"
+adblock.css USER "adblock.css"
+internal.css USER "internal.css"
+quirks.css USER "quirks.css"
+welcome.html USER "welcome.html"
+licence.html USER "licence.html"
+credits.html USER "credits.html"
+netsurf.png USER "netsurf.png"
+icons/arrow-l.png USER "icons/arrow-l.png"
+icons/content.png USER "icons/content.png"
+icons/directory.png USER "icons/directory.png"
+icons/directory2.png USER "icons/directory2.png"
+icons/hotlist-add.png USER "icons/hotlist-add.png"
+icons/hotlist-rmv.png USER "icons/hotlist-rmv.png"
+icons/search.png USER "icons/search.png"
+
+/* translated messages */
+
+/* english is the fallback */
+LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
+messages USER "en/Messages"
+
+LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT
+messages USER "fr/Messages"
+
+LANGUAGE LANG_GERMAN, SUBLANG_DEFAULT
+messages USER "de/Messages"
+
+LANGUAGE LANG_ITALIAN, SUBLANG_DEFAULT
+messages USER "it/Messages"
+
+LANGUAGE LANG_DUTCH, SUBLANG_DEFAULT
+messages USER "nl/Messages"
diff --git a/frontends/windows/resourceid.h b/frontends/windows/resourceid.h
index 605a77cb1..db275913b 100644
--- a/frontends/windows/resourceid.h
+++ b/frontends/windows/resourceid.h
@@ -16,30 +16,28 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_WINDOWS_RESOURCEID_H_
-#define _NETSURF_WINDOWS_RESOURCEID_H_
+#ifndef NETSURF_WINDOWS_RESOURCEID_H
+#define NETSURF_WINDOWS_RESOURCEID_H
#ifndef IDC_STATIC
#define IDC_STATIC (-1)
#endif
#define IDR_NETSURF_ICON 100
+#define IDR_THROBBER_AVI 101
#define IDR_TOOLBAR_BITMAP 102
#define IDR_TOOLBAR_BITMAP_GREY 103
#define IDR_TOOLBAR_BITMAP_HOT 104
#define IDR_NETSURF_BANNER 105
-#define IDR_HOME_BITMAP 114
+#define IDR_HOME_BITMAP 106
+#define IDC_PAGEINFO 107
+#define IDB_PAGEINFO_INSECURE 108
+#define IDB_PAGEINFO_SECURE 109
+#define IDB_PAGEINFO_INTERNAL 110
+#define IDB_PAGEINFO_WARNING 111
+#define IDB_PAGEINFO_LOCAL 112
-#define IDR_THROBBER_FRAME0_BITMAP 106
-#define IDR_THROBBER_FRAME1_BITMAP 107
-#define IDR_THROBBER_FRAME2_BITMAP 108
-#define IDR_THROBBER_FRAME3_BITMAP 109
-#define IDR_THROBBER_FRAME4_BITMAP 110
-#define IDR_THROBBER_FRAME5_BITMAP 111
-#define IDR_THROBBER_FRAME6_BITMAP 112
-#define IDR_THROBBER_FRAME7_BITMAP 113
-
-#define IDD_DLG_ABOUT 1000
+#define IDD_ABOUT 1000
#define IDC_IMG1 1001
#define IDC_ABOUT_VERSION 1002
#define IDC_ABOUT_TEXT 1003
@@ -47,11 +45,11 @@
#define IDC_BTN_CREDITS 1005
#define IDC_BTN_LICENCE 1006
-#define IDD_DLG_DOWNLOAD 1100
+#define IDD_DOWNLOAD 1100
#define IDC_DOWNLOAD_LABEL 1101
#define IDC_DOWNLOAD_PROGRESS 1102
-#define IDD_DLG_MAIN 1300
+#define IDD_MAIN 1300
#define IDC_MAIN_TOOLBAR 1301
#define IDC_MAIN_URLBAR 1302
#define IDC_MAIN_THROBBER 1303
@@ -59,13 +57,13 @@
#define IDC_MAIN_STATUSBAR 1305
#define IDC_MAIN_LAUNCH_URL 1306
-#define IDD_DLG_OPTIONS_GENERAL 1400
+#define IDD_OPTIONS_GENERAL 1400
#define IDC_PREFS_HOMEPAGE 1401
#define IDC_PREFS_IMAGES 1402
#define IDC_PREFS_ADVERTS 1403
#define IDC_PREFS_REFERER 1404
-#define IDD_DLG_OPTIONS_CONNECTIONS 1500
+#define IDD_OPTIONS_CONNECTIONS 1500
#define IDC_PREFS_FETCHERS 1501
#define IDC_PREFS_FETCHERS_SPIN 1502
#define IDC_PREFS_FETCH_HOST 1503
@@ -73,7 +71,7 @@
#define IDC_PREFS_FETCH_HANDLES 1505
#define IDC_PREFS_FETCH_HANDLES_SPIN 1506
-#define IDD_DLG_OPTIONS_APPERANCE 1200
+#define IDD_OPTIONS_APPERANCE 1200
#define IDC_PREFS_PROXYTYPE 1206
#define IDC_PREFS_PROXYHOST 1207
#define IDC_PREFS_PROXYPORT 1208
@@ -90,14 +88,11 @@
#define IDC_PREFS_FANTASY 1219
#define IDC_PREFS_FONTDEF 1220
#define IDC_PREFS_NOANIMATION 1227
-#define IDC_PREFS_ANIMATIONDELAY 1228
-#define IDC_PREFS_ANIMATIONDELAY_SPIN 1229
-
-#define IDD_DLG_SSLCERT 1600
-#define IDC_SSLCERT_IMG1 1601
-#define IDC_SSLCERT_BTN_ACCEPT 1602
-#define IDC_SSLCERT_BTN_REJECT 1603
+#define IDD_LOGIN 1700
+#define IDC_LOGIN_USERNAME 1701
+#define IDC_LOGIN_PASSWORD 1702
+#define IDC_LOGIN_DESCRIPTION 1703
#define IDR_MENU_MAIN 10000
#define IDM_FILE_OPEN_WINDOW 10101
diff --git a/frontends/windows/ssl_cert.c b/frontends/windows/ssl_cert.c
deleted file mode 100644
index 4db061626..000000000
--- a/frontends/windows/ssl_cert.c
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * Copyright 2016 Vincent Sanders <vince@netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- * Implementation of win32 certificate viewing using nsw32 core windows.
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <windows.h>
-
-#include "utils/log.h"
-#include "utils/nsoption.h"
-#include "netsurf/keypress.h"
-#include "netsurf/plotters.h"
-#include "desktop/sslcert_viewer.h"
-
-#include "windows/windbg.h"
-#include "windows/plot.h"
-#include "windows/corewindow.h"
-#include "windows/gui.h"
-#include "windows/resourceid.h"
-#include "windows/ssl_cert.h"
-
-/* spacing and sizes for dialog elements from
- * https://msdn.microsoft.com/en-us/library/windows/desktop/dn742486(v=vs.85).aspx#sizingandspacing
- */
-/** dialog margin */
-#define DLG_MRGN 11
-/** warning icon height */
-#define WRN_ICO_H 32
-/** comand button width */
-#define CMD_BTN_W 75
-/** command button height */
-#define CMD_BTN_H 23
-
-static const char windowclassname_sslcert[] = "nswssslcertwindow";
-
-/** win32 ssl certificate view context */
-struct nsw32_sslcert_window {
- struct nsw32_corewindow core;
-
- /** SSL certificate viewer context data */
- struct sslcert_session_data *ssl_data;
-
- /** dialog window handle */
- HWND hWnd;
-
- /** accept button handle */
- HWND hAccept;
-
- /** reject button handle */
- HWND hReject;
-
- /** warning text handle */
- HWND hTxt;
-};
-
-
-/**
- * callback for keypress on ssl certificate window
- *
- * \param nsw32_cw The nsw32 core window structure.
- * \param nskey The netsurf key code
- * \return NSERROR_OK on success otherwise appropriate error code
- */
-static nserror
-nsw32_sslcert_viewer_key(struct nsw32_corewindow *nsw32_cw, uint32_t nskey)
-{
- struct nsw32_sslcert_window *crtvrfy_win;
-
- /* technically degenerate container of */
- crtvrfy_win = (struct nsw32_sslcert_window *)nsw32_cw;
-
- if (sslcert_viewer_keypress(crtvrfy_win->ssl_data, nskey)) {
- return NSERROR_OK;
- }
- return NSERROR_NOT_IMPLEMENTED;
-}
-
-
-/**
- * callback for mouse action on ssl certificate window
- *
- * \param nsw32_cw The nsw32 core window structure.
- * \param mouse_state netsurf mouse state on event
- * \param x location of event
- * \param y location of event
- * \return NSERROR_OK on success otherwise appropriate error code
- */
-static nserror
-nsw32_sslcert_viewer_mouse(struct nsw32_corewindow *nsw32_cw,
- browser_mouse_state mouse_state,
- int x, int y)
-{
- struct nsw32_sslcert_window *crtvrfy_win;
-
- /* technically degenerate container of */
- crtvrfy_win = (struct nsw32_sslcert_window *)nsw32_cw;
-
- sslcert_viewer_mouse_action(crtvrfy_win->ssl_data, mouse_state, x, y);
-
- return NSERROR_OK;
-}
-
-
-/**
- * callback on draw event for ssl certificate window
- *
- * \param nsw32_cw The nsw32 core window structure.
- * \param scrollx The horizontal scroll offset.
- * \param scrolly The vertical scroll offset.
- * \param r The rectangle of the window that needs updating.
- * \return NSERROR_OK on success otherwise appropriate error code
- */
-static nserror
-nsw32_sslcert_viewer_draw(struct nsw32_corewindow *nsw32_cw,
- int scrollx,
- int scrolly,
- struct rect *r)
-{
- struct nsw32_sslcert_window *crtvrfy_win;
- struct redraw_context ctx = {
- .interactive = true,
- .background_images = true,
- .plot = &win_plotters
- };
-
- /* technically degenerate container of */
- crtvrfy_win = (struct nsw32_sslcert_window *)nsw32_cw;
-
- sslcert_viewer_redraw(crtvrfy_win->ssl_data,
- -scrollx, -scrolly,
- r, &ctx);
-
- return NSERROR_OK;
-}
-
-
-/**
- * callback on close event for ssl certificate window
- *
- * \param nsw32_cw The nsw32 core window structure.
- * \return NSERROR_OK on success otherwise appropriate error code
- */
-static nserror
-nsw32_sslcert_viewer_close(struct nsw32_corewindow *nsw32_cw)
-{
- DestroyWindow(nsw32_cw->hWnd);
-
- return NSERROR_OK;
-}
-
-
-/* exported interface documented in nsw32/ssl_cert.h */
-nserror nsw32_cert_verify(struct nsurl *url,
- const struct ssl_cert_info *certs,
- unsigned long num,
- nserror (*cb)(bool proceed, void *pw),
- void *cbpw)
-{
- struct nsw32_sslcert_window *ncwin;
- nserror res;
-
- ncwin = malloc(sizeof(struct nsw32_sslcert_window));
- if (ncwin == NULL) {
- return NSERROR_NOMEM;
- }
-
- /* initialise certificate viewing interface */
- res = sslcert_viewer_create_session_data(num, url, cb, cbpw, certs,
- &ncwin->ssl_data);
- if (res != NSERROR_OK) {
- free(ncwin);
- return res;
- }
-
- NSLOG(netsurf, INFO, "creating hInstance %p SSL window", hinst);
- ncwin->hWnd = CreateWindowEx(0,
- windowclassname_sslcert,
- "SSL Certificate viewer",
- WS_OVERLAPPEDWINDOW |
- WS_CLIPSIBLINGS |
- WS_CLIPCHILDREN |
- CS_DBLCLKS,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- 500,
- 400,
- NULL,
- NULL,
- hinst,
- NULL);
- if (ncwin->hWnd == NULL) {
- NSLOG(netsurf, INFO, "Window create failed");
- return NSERROR_NOMEM;
- }
-
- ncwin->core.title = NULL;
- ncwin->core.draw = nsw32_sslcert_viewer_draw;
- ncwin->core.key = nsw32_sslcert_viewer_key;
- ncwin->core.mouse = nsw32_sslcert_viewer_mouse;
- ncwin->core.close = nsw32_sslcert_viewer_close;
-
- res = nsw32_corewindow_init(hinst, ncwin->hWnd, &ncwin->core);
- if (res != NSERROR_OK) {
- free(ncwin);
- return res;
- }
-
- res = sslcert_viewer_init(ncwin->core.cb_table,
- (struct core_window *)ncwin,
- ncwin->ssl_data);
- if (res != NSERROR_OK) {
- free(ncwin);
- return res;
- }
-
- ncwin->hAccept = CreateWindowEx(0,
- "BUTTON",
- "Accept",
- WS_TABSTOP|WS_VISIBLE|
- WS_CHILD|BS_DEFPUSHBUTTON,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CMD_BTN_W,
- CMD_BTN_H,
- ncwin->hWnd,
- (HMENU)IDC_SSLCERT_BTN_ACCEPT,
- hinst,
- NULL);
- HGDIOBJ hfDefault=GetStockObject(DEFAULT_GUI_FONT);
- SendMessage(ncwin->hAccept, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE,0));
- ncwin->hReject = CreateWindowEx(0,
- "BUTTON",
- "Reject",
- WS_TABSTOP|WS_VISIBLE|
- WS_CHILD|BS_DEFPUSHBUTTON,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CMD_BTN_W,
- CMD_BTN_H,
- ncwin->hWnd,
- (HMENU)IDC_SSLCERT_BTN_REJECT,
- hinst,
- NULL);
- SendMessage(ncwin->hReject, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE,0));
-
- CreateWindowEx(0,
- "STATIC",
- IDI_WARNING,
- WS_VISIBLE | WS_CHILD | SS_ICON,
- DLG_MRGN,
- DLG_MRGN,
- CMD_BTN_W,
- CMD_BTN_H,
- ncwin->hWnd,
- NULL,
- NULL,
- NULL);
- ncwin->hTxt = CreateWindowEx(0,
- "STATIC",
- "NetSurf failed to verify the authenticity of an SSL certificate. Verify the certificate details",
- WS_VISIBLE | WS_CHILD | SS_LEFT,
- DLG_MRGN + WRN_ICO_H + DLG_MRGN,
- DLG_MRGN + 5,
- 400,
- WRN_ICO_H - 5,
- ncwin->hWnd,
- NULL,
- NULL,
- NULL);
- SendMessage(ncwin->hTxt, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE,0));
-
- SetProp(ncwin->hWnd, TEXT("CertWnd"), (HANDLE)ncwin);
-
- ShowWindow(ncwin->hWnd, SW_SHOWNORMAL);
-
- return NSERROR_OK;
-}
-
-
-/**
- * position and size ssl cert window widgets.
- *
- * \param hwnd The win32 handle of the window
- * \param certwin The certificate viewer context
- */
-static void
-nsw32_window_ssl_cert_size(HWND hwnd, struct nsw32_sslcert_window *certwin)
-{
- RECT rc;
- GetClientRect(hwnd, &rc);
- /* position certificate drawable */
- MoveWindow(certwin->core.hWnd,
- DLG_MRGN,
- DLG_MRGN + WRN_ICO_H + DLG_MRGN,
- rc.right - (DLG_MRGN + DLG_MRGN),
- rc.bottom - (DLG_MRGN + WRN_ICO_H + DLG_MRGN + DLG_MRGN + CMD_BTN_H + DLG_MRGN),
- TRUE);
- /* position accept button */
- MoveWindow(certwin->hAccept,
- rc.right - (DLG_MRGN + CMD_BTN_W),
- rc.bottom - (DLG_MRGN + CMD_BTN_H),
- CMD_BTN_W,
- CMD_BTN_H,
- TRUE);
- /* position reject button */
- MoveWindow(certwin->hReject,
- rc.right - (DLG_MRGN + CMD_BTN_W + 7 + CMD_BTN_W),
- rc.bottom - (DLG_MRGN + CMD_BTN_H),
- CMD_BTN_W,
- CMD_BTN_H,
- TRUE);
- /* position text */
- MoveWindow(certwin->hTxt,
- DLG_MRGN + WRN_ICO_H + DLG_MRGN,
- DLG_MRGN + 5,
- rc.right - (DLG_MRGN + WRN_ICO_H + DLG_MRGN + DLG_MRGN),
- WRN_ICO_H - 5,
- TRUE);
-}
-
-
-/**
- * Destroy a certificate viewing window
- *
- * \param crtwin The certificate viewer context
- * \return NSERROR_OK on success otherwise appropriate error code
- */
-static nserror nsw32_crtvrfy_destroy(struct nsw32_sslcert_window *crtwin)
-{
- nserror res;
-
- res = sslcert_viewer_fini(crtwin->ssl_data);
- if (res == NSERROR_OK) {
- res = nsw32_corewindow_fini(&crtwin->core);
- DestroyWindow(crtwin->hWnd);
- free(crtwin);
- }
- return res;
-}
-
-
-/**
- * handle command message on ssl certificate viewing window.
- *
- * \param hwnd The win32 window handle.
- * \param crtwin certificate window context.
- * \param notification_code notifiction code
- * \param identifier notification identifier
- * \param ctrl_window The win32 control window handle
- * \return appropriate response for command
- */
-static LRESULT
-nsw32_window_ssl_cert_command(HWND hwnd,
- struct nsw32_sslcert_window *crtwin,
- int notification_code,
- int identifier,
- HWND ctrl_window)
-{
- NSLOG(netsurf, INFO,
- "notification_code %x identifier %x ctrl_window %p",
- notification_code,
- identifier,
- ctrl_window);
-
- switch(identifier) {
- case IDC_SSLCERT_BTN_ACCEPT:
- sslcert_viewer_accept(crtwin->ssl_data);
- nsw32_crtvrfy_destroy(crtwin);
- break;
-
- case IDC_SSLCERT_BTN_REJECT:
- sslcert_viewer_reject(crtwin->ssl_data);
- nsw32_crtvrfy_destroy(crtwin);
- break;
-
- default:
- return 1; /* unhandled */
- }
- return 0; /* control message handled */
-}
-
-
-/**
- * callback for SSL certificate window win32 events
- *
- * \param hwnd The win32 window handle
- * \param msg The win32 message identifier
- * \param wparam The w win32 parameter
- * \param lparam The l win32 parameter
- */
-static LRESULT CALLBACK
-nsw32_window_ssl_cert_event_callback(HWND hwnd,
- UINT msg,
- WPARAM wparam,
- LPARAM lparam)
-{
- struct nsw32_sslcert_window *crtwin;
- crtwin = GetProp(hwnd, TEXT("CertWnd"));
- if (crtwin != NULL) {
- switch (msg) {
- case WM_SIZE:
- nsw32_window_ssl_cert_size(hwnd, crtwin);
- break;
-
- case WM_COMMAND:
- if (nsw32_window_ssl_cert_command(hwnd,
- crtwin,
- HIWORD(wparam),
- LOWORD(wparam),
- (HWND)lparam) == 0) {
- return 0;
- }
- break;
-
- case WM_CLOSE:
- sslcert_viewer_reject(crtwin->ssl_data);
- nsw32_crtvrfy_destroy(crtwin);
- return 0;
- }
- }
-
- return DefWindowProc(hwnd, msg, wparam, lparam);
-}
-
-
-/* exported interface documented in nsw32/ssl_cert.h */
-nserror nsws_create_cert_verify_class(HINSTANCE hInstance)
-{
- nserror ret = NSERROR_OK;
- WNDCLASSEX wc;
-
- /* drawable area */
- wc.cbSize = sizeof(WNDCLASSEX);
- wc.style = 0;
- wc.lpfnWndProc = nsw32_window_ssl_cert_event_callback;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = hInstance;
- wc.hIcon = NULL;
- wc.hCursor = NULL;
- wc.hbrBackground = (HBRUSH)(COLOR_MENU + 1);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = windowclassname_sslcert;
- wc.hIconSm = NULL;
-
- if (RegisterClassEx(&wc) == 0) {
- win_perror("CertVerifyClass");
- ret = NSERROR_INIT_FAILED;
- }
-
- return ret;
-}
diff --git a/frontends/windows/ssl_cert.h b/frontends/windows/ssl_cert.h
deleted file mode 100644
index 6c1f0415a..000000000
--- a/frontends/windows/ssl_cert.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2016 Vincent Sanders <vince@netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- * Interface to win32 certificate viewing using nsw32 core windows.
- */
-
-#ifndef NETSURF_WINDOWS_SSL_CERT_H
-#define NETSURF_WINDOWS_SSL_CERT_H 1
-
-struct nsurl;
-struct ssl_cert_info;
-
-/**
- * Prompt the user to verify a certificate with issuse.
- *
- * \param url The URL being verified.
- * \param certs The certificate to be verified
- * \param num The number of certificates to be verified.
- * \param cb Callback upon user decision.
- * \param cbpw Context pointer passed to cb
- * \return NSERROR_OK or error code if prompt creation failed.
- */
-nserror nsw32_cert_verify(struct nsurl *url, const struct ssl_cert_info *certs, unsigned long num, nserror (*cb)(bool proceed, void *pw), void *cbpw);
-
-/**
- * Create the ssl viewer window class.
- *
- * \param hinstance The application instance
- * \return NSERROR_OK on success or NSERROR_INIT_FAILED if the class
- * creation failed.
- */
-nserror nsws_create_cert_verify_class(HINSTANCE hinstance);
-
-#endif
diff --git a/frontends/windows/windbg.h b/frontends/windows/windbg.h
index 6cd9f97f8..f09cea9e6 100644
--- a/frontends/windows/windbg.h
+++ b/frontends/windows/windbg.h
@@ -16,20 +16,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_WINDOWS_WINDBG_H_
-#define _NETSURF_WINDOWS_WINDBG_H_
+#ifndef NETSURF_WINDOWS_WINDBG_H
+#define NETSURF_WINDOWS_WINDBG_H
#include "utils/log.h"
const char *msg_num_to_name(int msg);
void win_perror(const char *lpszFunction);
+/**
+ * log windows message
+ *
+ * log a windows message with symbols converted to human redable
+ */
#define LOG_WIN_MSG(h, m, w, l) \
if (((m) != WM_SETCURSOR) && \
((m) != WM_MOUSEMOVE) && \
((m) != WM_NCHITTEST) && \
((m) != WM_ENTERIDLE)) \
- NSLOG(netsurf, INFO, \
+ NSLOG(netsurf, DEBUG, \
"%s, hwnd %p, w 0x%x, l 0x%Ix", \
msg_num_to_name(m), h, w, l)
diff --git a/frontends/windows/window.c b/frontends/windows/window.c
index 90d076812..00e5a7e05 100644
--- a/frontends/windows/window.c
+++ b/frontends/windows/window.c
@@ -55,43 +55,35 @@
#include "windows/global_history.h"
#include "windows/window.h"
-/** List of all our gui windows */
+/**
+ * List of all gui windows
+ */
static struct gui_window *window_list = NULL;
-/** The main window class name */
-static const char windowclassname_main[] = "nswsmainwindow";
+/**
+ * The main window class name
+ */
+static const LPCWSTR windowclassname_main = L"nswsmainwindow";
-/** width of the throbber element */
+/**
+ * width of the throbber element
+ */
#define NSWS_THROBBER_WIDTH 24
-/** height of the url entry box */
+/**
+ * height of the url entry box
+ */
#define NSWS_URLBAR_HEIGHT 23
-/** Number of open windows */
-static int open_windows = 0;
-
-
/**
- * Obtain the DPI of the display.
- *
- * \param hwnd A win32 window handle to get the DPI for
- * \return The DPI of the device the window is displayed on.
+ * height of the Page Information bitmap button
*/
-static int get_window_dpi(HWND hwnd)
-{
- HDC hdc = GetDC(hwnd);
- int dpi = GetDeviceCaps(hdc, LOGPIXELSY);
-
- if (dpi <= 10) {
- dpi = 96; /* 96DPI is the default */
- }
+#define NSW32_PGIBUTTON_HEIGHT 16
- ReleaseDC(hwnd, hdc);
-
- NSLOG(netsurf, INFO, "FIX DPI %d", dpi);
-
- return dpi;
-}
+/**
+ * Number of open windows
+ */
+static int open_windows = 0;
/**
@@ -152,6 +144,23 @@ static HWND nsws_window_create(HINSTANCE hInstance, struct gui_window *gw)
{
HWND hwnd;
INITCOMMONCONTROLSEX icc;
+ int xpos = CW_USEDEFAULT;
+ int ypos = CW_USEDEFAULT;
+ int width = CW_USEDEFAULT;
+ int height = CW_USEDEFAULT;
+
+ if ((nsoption_int(window_width) >= 100) &&
+ (nsoption_int(window_height) >= 100) &&
+ (nsoption_int(window_x) >= 0) &&
+ (nsoption_int(window_y) >= 0)) {
+ xpos = nsoption_int(window_x);
+ ypos = nsoption_int(window_y);
+ width = nsoption_int(window_width);
+ height = nsoption_int(window_height);
+
+ NSLOG(netsurf, DEBUG, "Setting Window position %d,%d %d,%d",
+ xpos, ypos, width, height);
+ }
icc.dwSize = sizeof(icc);
icc.dwICC = ICC_BAR_CLASSES | ICC_WIN95_CLASSES;
@@ -163,53 +172,28 @@ static HWND nsws_window_create(HINSTANCE hInstance, struct gui_window *gw)
gw->mainmenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU_MAIN));
gw->rclick = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU_CONTEXT));
- NSLOG(netsurf, INFO,
- "creating hInstance %p GUI window %p",
- hInstance, gw);
- hwnd = CreateWindowEx(0,
- windowclassname_main,
- "NetSurf Browser",
- WS_OVERLAPPEDWINDOW |
- WS_CLIPCHILDREN |
- WS_CLIPSIBLINGS |
- CS_DBLCLKS,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- gw->width,
- gw->height,
- NULL,
- gw->mainmenu,
- hInstance,
- NULL);
+ hwnd = CreateWindowExW(0,
+ windowclassname_main,
+ L"NetSurf Browser",
+ WS_OVERLAPPEDWINDOW |
+ WS_CLIPCHILDREN |
+ WS_CLIPSIBLINGS |
+ CS_DBLCLKS,
+ xpos,
+ ypos,
+ width,
+ height,
+ NULL,
+ gw->mainmenu,
+ hInstance,
+ (LPVOID)gw);
if (hwnd == NULL) {
NSLOG(netsurf, INFO, "Window create failed");
- return NULL;
- }
-
- /* set the gui window associated with this browser */
- SetProp(hwnd, TEXT("GuiWnd"), (HANDLE)gw);
-
- browser_set_dpi(get_window_dpi(hwnd));
-
- if ((nsoption_int(window_width) >= 100) &&
- (nsoption_int(window_height) >= 100) &&
- (nsoption_int(window_x) >= 0) &&
- (nsoption_int(window_y) >= 0)) {
- NSLOG(netsurf, INFO,
- "Setting Window position %d,%d %d,%d",
- nsoption_int(window_x), nsoption_int(window_y),
- nsoption_int(window_width), nsoption_int(window_height));
- SetWindowPos(hwnd, HWND_TOP,
- nsoption_int(window_x),
- nsoption_int(window_y),
- nsoption_int(window_width),
- nsoption_int(window_height),
- SWP_SHOWWINDOW);
+ } else {
+ nsws_window_set_accels(gw);
}
- nsws_window_set_accels(gw);
-
return hwnd;
}
@@ -230,7 +214,7 @@ nsws_window_toolbar_command(struct gui_window *gw,
int identifier,
HWND ctrl_window)
{
- NSLOG(netsurf, INFO,
+ NSLOG(netsurf, DEBUG,
"notification_code %d identifier %d ctrl_window %p",
notification_code,
identifier,
@@ -241,39 +225,39 @@ nsws_window_toolbar_command(struct gui_window *gw,
case IDC_MAIN_URLBAR:
switch (notification_code) {
case EN_CHANGE:
- NSLOG(netsurf, INFO, "EN_CHANGE");
+ NSLOG(netsurf, DEBUG, "EN_CHANGE");
break;
case EN_ERRSPACE:
- NSLOG(netsurf, INFO, "EN_ERRSPACE");
+ NSLOG(netsurf, DEBUG, "EN_ERRSPACE");
break;
case EN_HSCROLL:
- NSLOG(netsurf, INFO, "EN_HSCROLL");
+ NSLOG(netsurf, DEBUG, "EN_HSCROLL");
break;
case EN_KILLFOCUS:
- NSLOG(netsurf, INFO, "EN_KILLFOCUS");
+ NSLOG(netsurf, DEBUG, "EN_KILLFOCUS");
break;
case EN_MAXTEXT:
- NSLOG(netsurf, INFO, "EN_MAXTEXT");
+ NSLOG(netsurf, DEBUG, "EN_MAXTEXT");
break;
case EN_SETFOCUS:
- NSLOG(netsurf, INFO, "EN_SETFOCUS");
+ NSLOG(netsurf, DEBUG, "EN_SETFOCUS");
break;
case EN_UPDATE:
- NSLOG(netsurf, INFO, "EN_UPDATE");
+ NSLOG(netsurf, DEBUG, "EN_UPDATE");
break;
case EN_VSCROLL:
- NSLOG(netsurf, INFO, "EN_VSCROLL");
+ NSLOG(netsurf, DEBUG, "EN_VSCROLL");
break;
default:
- NSLOG(netsurf, INFO, "Unknown notification_code");
+ NSLOG(netsurf, DEBUG, "Unknown notification_code");
break;
}
break;
@@ -320,7 +304,7 @@ urlbar_dimensions(HWND hWndParent,
/**
* callback for toolbar events
*
- * message handler for toolbar window
+ * subclass message handler for toolbar window
*
* \param hwnd win32 window handle message arrived for
* \param msg The message ID
@@ -336,7 +320,11 @@ nsws_window_toolbar_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
LOG_WIN_MSG(hwnd, msg, wparam, lparam);
+ toolproc = (WNDPROC)GetProp(hwnd, TEXT("OrigMsgProc"));
+ assert(toolproc != NULL);
+
gw = nsws_get_gui_window(hwnd);
+ assert(gw != NULL);
switch (msg) {
case WM_SIZE:
@@ -372,19 +360,15 @@ nsws_window_toolbar_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
return 0;
}
break;
- }
- /* remove properties if window is being destroyed */
- if (msg == WM_NCDESTROY) {
+ case WM_NCDESTROY:
+ /* remove properties if window is being destroyed */
RemoveProp(hwnd, TEXT("GuiWnd"));
- toolproc = (WNDPROC)RemoveProp(hwnd, TEXT("OrigMsgProc"));
- } else {
- toolproc = (WNDPROC)GetProp(hwnd, TEXT("OrigMsgProc"));
- }
+ RemoveProp(hwnd, TEXT("OrigMsgProc"));
+ /* put the original message handler back */
+ SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)toolproc);
+ break;
- if (toolproc == NULL) {
- /* the original toolbar procedure is not available */
- return DefWindowProc(hwnd, msg, wparam, lparam);
}
/* chain to the next handler */
@@ -392,10 +376,21 @@ nsws_window_toolbar_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
}
+static void set_urlbar_edit_size(HWND hwnd)
+{
+ RECT rc;
+ GetClientRect(hwnd, &rc);
+ rc.left += NSW32_PGIBUTTON_HEIGHT;
+ SendMessage(hwnd, EM_SETRECT, 0, (LPARAM)&rc);
+ NSLOG(netsurf, DEBUG, "left:%ld right:%ld top:%ld bot:%ld",
+ rc.left,rc.right,rc.top,rc.bottom);
+}
+
+
/**
* callback for url bar events
*
- * message handler for urlbar window
+ * subclass message handler for urlbar window
*
* \param hwnd win32 window handle message arrived for
* \param msg The message ID
@@ -408,17 +403,24 @@ nsws_window_urlbar_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
struct gui_window *gw;
WNDPROC urlproc;
HFONT hFont;
+ LRESULT result;
LOG_WIN_MSG(hwnd, msg, wparam, lparam);
- gw = nsws_get_gui_window(hwnd);
-
urlproc = (WNDPROC)GetProp(hwnd, TEXT("OrigMsgProc"));
+ assert(urlproc != NULL);
+
+ gw = nsws_get_gui_window(hwnd);
+ assert(gw != NULL);
/* override messages */
switch (msg) {
case WM_CHAR:
- if (wparam == 13) {
+ if (wparam == 1) {
+ /* handle ^A */
+ SendMessage(hwnd, EM_SETSEL, 0, -1);
+ return 1;
+ } else if (wparam == 13) {
SendMessage(gw->main, WM_COMMAND, IDC_MAIN_LAUNCH_URL, 0);
return 0;
}
@@ -430,25 +432,27 @@ nsws_window_urlbar_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
NSLOG(netsurf, INFO, "Destroyed font object");
DeleteObject(hFont);
}
-
+ fallthrough;
case WM_NCDESTROY:
/* remove properties if window is being destroyed */
RemoveProp(hwnd, TEXT("GuiWnd"));
RemoveProp(hwnd, TEXT("OrigMsgProc"));
+ /* put the original message handler back */
+ SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)urlproc);
break;
- }
- if (urlproc == NULL) {
- /* the original toolbar procedure is not available */
- return DefWindowProc(hwnd, msg, wparam, lparam);
+ case WM_SIZE:
+ result = CallWindowProc(urlproc, hwnd, msg, wparam, lparam);
+ set_urlbar_edit_size(hwnd);
+ return result;
+
}
/* chain to the next handler */
return CallWindowProc(urlproc, hwnd, msg, wparam, lparam);
}
-
/**
* create a urlbar and message handler
*
@@ -466,6 +470,7 @@ nsws_window_urlbar_create(HINSTANCE hInstance,
{
int urlx, urly, urlwidth, urlheight;
HWND hwnd;
+ HWND hbutton;
WNDPROC urlproc;
HFONT hFont;
@@ -478,7 +483,8 @@ nsws_window_urlbar_create(HINSTANCE hInstance,
hwnd = CreateWindowEx(0L,
TEXT("Edit"),
NULL,
- WS_CHILD | WS_BORDER | WS_VISIBLE | ES_LEFT | ES_AUTOHSCROLL,
+ WS_CHILD | WS_BORDER | WS_VISIBLE |
+ ES_LEFT | ES_AUTOHSCROLL | ES_MULTILINE,
urlx,
urly,
urlwidth,
@@ -486,7 +492,7 @@ nsws_window_urlbar_create(HINSTANCE hInstance,
hWndParent,
(HMENU)IDC_MAIN_URLBAR,
hInstance,
- 0);
+ NULL);
if (hwnd == NULL) {
return NULL;
@@ -512,6 +518,28 @@ nsws_window_urlbar_create(HINSTANCE hInstance,
SendMessage(hwnd, WM_SETFONT, (WPARAM)hFont, 0);
}
+
+ /* Create the page info button */
+ hbutton = CreateWindowEx(0L,
+ TEXT("BUTTON"),
+ NULL,
+ WS_CHILD | WS_VISIBLE | BS_BITMAP | BS_FLAT,
+ (NSWS_URLBAR_HEIGHT - NSW32_PGIBUTTON_HEIGHT) /2,
+ (NSWS_URLBAR_HEIGHT - NSW32_PGIBUTTON_HEIGHT) /2,
+ NSW32_PGIBUTTON_HEIGHT,
+ NSW32_PGIBUTTON_HEIGHT,
+ hwnd,
+ (HMENU)IDC_PAGEINFO,
+ hInstance,
+ NULL);
+
+ /* put a property on the parent toolbar so it can set the page info */
+ SetProp(hWndParent, TEXT("hPGIbutton"), (HANDLE)hbutton);
+
+ SendMessageW(hbutton, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)gw->hPageInfo[PAGE_STATE_UNKNOWN]);
+
+ set_urlbar_edit_size(hwnd);
+
NSLOG(netsurf, INFO,
"Created url bar hwnd:%p, x:%d, y:%d, w:%d, h:%d", hwnd, urlx,
urly, urlwidth, urlheight);
@@ -534,7 +562,6 @@ nsws_window_throbber_create(HINSTANCE hInstance,
struct gui_window *gw)
{
HWND hwnd;
- char avi[PATH_MAX];
int urlx, urly, urlwidth, urlheight;
urlbar_dimensions(hWndParent,
@@ -554,9 +581,8 @@ nsws_window_throbber_create(HINSTANCE hInstance,
hInstance,
NULL);
- nsws_find_resource(avi, "throbber.avi", "windows/res/throbber.avi");
- NSLOG(netsurf, INFO, "setting throbber avi as %s", avi);
- Animate_Open(hwnd, avi);
+ Animate_Open(hwnd, MAKEINTRESOURCE(IDR_THROBBER_AVI));
+
if (gw->throbbing) {
Animate_Play(hwnd, 0, -1, -1);
} else {
@@ -647,7 +673,7 @@ nsws_window_create_toolbar(HINSTANCE hInstance,
hWndToolbar = CreateWindowEx(0,
TOOLBARCLASSNAME,
"Toolbar",
- WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT,
+ WS_CHILD | TBSTYLE_FLAT,
0, 0, 0, 0,
hWndParent,
NULL,
@@ -712,15 +738,21 @@ nsws_window_create_toolbar(HINSTANCE hInstance,
TB_BUTTONSTRUCTSIZE,
(WPARAM)sizeof(TBBUTTON),
0);
+
SendMessage(hWndToolbar,
TB_ADDBUTTONS,
(WPARAM)gw->toolbuttonc,
(LPARAM)&tbButtons);
+ /* create url widget */
gw->urlbar = nsws_window_urlbar_create(hInstance, hWndToolbar, gw);
+ /* create throbber widget */
gw->throbber = nsws_window_throbber_create(hInstance, hWndToolbar, gw);
+ SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0);
+ ShowWindow(hWndToolbar, TRUE);
+
return hWndToolbar;
}
@@ -909,8 +941,8 @@ win32_window_invalidate_area(struct gui_window *gw, const struct rect *rect)
if (rect != NULL) {
redrawrectp = &redrawrect;
- redrawrect.left = (long)rect->x0 - (gw->scrollx / gw->scale);
- redrawrect.top = (long)rect->y0 - (gw->scrolly / gw->scale);
+ redrawrect.left = (long)rect->x0 - gw->scrollx;
+ redrawrect.top = (long)rect->y0 - gw->scrolly;
redrawrect.right =(long)rect->x1;
redrawrect.bottom = (long)rect->y1;
@@ -925,36 +957,6 @@ win32_window_invalidate_area(struct gui_window *gw, const struct rect *rect)
/**
- * Set scale of a win32 browser window
- *
- * \param gw win32 frontend window context
- * \param scale The new scale
- */
-static void nsws_set_scale(struct gui_window *gw, float scale)
-{
- struct rect rect;
-
- assert(gw != NULL);
-
- if (gw->scale == scale) {
- return;
- }
-
- rect.x0 = rect.x1 = gw->scrollx;
- rect.y0 = rect.y1 = gw->scrolly;
-
- gw->scale = scale;
-
- if (gw->bw != NULL) {
- browser_window_set_scale(gw->bw, scale, true);
- }
-
- win32_window_invalidate_area(gw, NULL);
- win32_window_set_scroll(gw, &rect);
-}
-
-
-/**
* Create a new window due to menu selection
*
* \param gw frontends graphical window.
@@ -1058,48 +1060,35 @@ nsws_window_command(HWND hwnd,
break;
case IDM_EDIT_CUT:
- OpenClipboard(gw->main);
- EmptyClipboard();
- CloseClipboard();
if (GetFocus() == gw->urlbar) {
SendMessage(gw->urlbar, WM_CUT, 0, 0);
- } else if (gw->bw != NULL) {
- browser_window_key_press(gw->bw, NS_KEY_CUT_SELECTION);
+ } else {
+ SendMessage(gw->drawingarea, WM_CUT, 0, 0);
}
break;
case IDM_EDIT_COPY:
- OpenClipboard(gw->main);
- EmptyClipboard();
- CloseClipboard();
if (GetFocus() == gw->urlbar) {
SendMessage(gw->urlbar, WM_COPY, 0, 0);
- } else if (gw->bw != NULL) {
- browser_window_key_press(gw->bw, NS_KEY_COPY_SELECTION);
+ } else {
+ SendMessage(gw->drawingarea, WM_COPY, 0, 0);
}
break;
case IDM_EDIT_PASTE: {
- OpenClipboard(gw->main);
- HANDLE h = GetClipboardData(CF_TEXT);
- if (h != NULL) {
- char *content = GlobalLock(h);
- NSLOG(netsurf, INFO, "pasting %s\n", content);
- GlobalUnlock(h);
- }
- CloseClipboard();
- if (GetFocus() == gw->urlbar)
+ if (GetFocus() == gw->urlbar) {
SendMessage(gw->urlbar, WM_PASTE, 0, 0);
- else
- browser_window_key_press(gw->bw, NS_KEY_PASTE);
+ } else {
+ SendMessage(gw->drawingarea, WM_PASTE, 0, 0);
+ }
break;
}
case IDM_EDIT_DELETE:
if (GetFocus() == gw->urlbar)
- SendMessage(gw->urlbar, WM_CUT, 0, 0);
+ SendMessage(gw->urlbar, WM_CLEAR, 0, 0);
else
- browser_window_key_press(gw->bw, NS_KEY_DELETE_RIGHT);
+ SendMessage(gw->drawingarea, WM_CLEAR, 0, 0);
break;
case IDM_EDIT_SELECT_ALL:
@@ -1135,9 +1124,10 @@ nsws_window_command(HWND hwnd,
case IDM_NAV_HOME:
{
nsurl *url;
+ ret = nsurl_create(nsoption_charp(homepage_url), &url);
- if (nsurl_create(nsoption_charp(homepage_url), &url) != NSERROR_OK) {
- win32_warning("NoMemory", 0);
+ if (ret != NSERROR_OK) {
+ win32_report_nserror(ret, 0);
} else {
browser_window_navigate(gw->bw,
url,
@@ -1168,7 +1158,7 @@ nsws_window_command(HWND hwnd,
break;
case IDM_TOOLS_COOKIES:
- nsw32_cookies_present(hinst);
+ nsw32_cookies_present(NULL);
break;
case IDM_NAV_BOOKMARKS:
@@ -1176,15 +1166,15 @@ nsws_window_command(HWND hwnd,
break;
case IDM_VIEW_ZOOMPLUS:
- nsws_set_scale(gw, gw->scale * 1.1);
+ browser_window_set_scale(gw->bw, 0.1, false);
break;
case IDM_VIEW_ZOOMMINUS:
- nsws_set_scale(gw, gw->scale * 0.9);
+ browser_window_set_scale(gw->bw, -0.1, false);
break;
case IDM_VIEW_ZOOMNORMAL:
- nsws_set_scale(gw, 1.0);
+ browser_window_set_scale(gw->bw, 1.0, true);
break;
case IDM_VIEW_SOURCE:
@@ -1260,26 +1250,27 @@ nsws_window_command(HWND hwnd,
case IDM_HELP_CONTENTS:
nsws_window_go(hwnd,
- "http://www.netsurf-browser.org/documentation/");
+ "https://www.netsurf-browser.org/documentation/");
break;
case IDM_HELP_GUIDE:
nsws_window_go(hwnd,
- "http://www.netsurf-browser.org/documentation/guide");
+ "https://www.netsurf-browser.org/documentation/guide");
break;
case IDM_HELP_INFO:
nsws_window_go(hwnd,
- "http://www.netsurf-browser.org/documentation/info");
+ "https://www.netsurf-browser.org/documentation/info");
break;
case IDM_HELP_ABOUT:
- nsws_about_dialog_init(hinst, gw->main);
+ nsw32_about_dialog_init(hinst, gw->main);
break;
case IDC_MAIN_LAUNCH_URL:
{
nsurl *url;
+ nserror err;
if (GetFocus() != gw->urlbar)
break;
@@ -1289,8 +1280,10 @@ nsws_window_command(HWND hwnd,
SendMessage(gw->urlbar, WM_GETTEXT, (WPARAM)(len + 1), (LPARAM)addr);
NSLOG(netsurf, INFO, "launching %s\n", addr);
- if (nsurl_create(addr, &url) != NSERROR_OK) {
- win32_warning("NoMemory", 0);
+ err = nsurl_create(addr, &url);
+
+ if (err != NSERROR_OK) {
+ win32_report_nserror(err, 0);
} else {
browser_window_navigate(gw->bw,
url,
@@ -1375,8 +1368,6 @@ nsws_window_resize(struct gui_window *gw,
}
nsws_window_update_forward_back(gw);
- browser_window_update(gw->bw, false);
-
if (gw->toolbar != NULL) {
SendMessage(gw->toolbar, TB_SETSTATE,
(WPARAM) IDM_NAV_STOP,
@@ -1400,12 +1391,30 @@ nsws_window_event_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
struct gui_window *gw;
RECT rmain;
+ LPCREATESTRUCTW createstruct;
LOG_WIN_MSG(hwnd, msg, wparam, lparam);
- /* deal with window creation as a special case */
- if (msg == WM_CREATE) {
- /* To cause all the component child windows to be
+ gw = nsws_get_gui_window(hwnd);
+
+ switch (msg) {
+ case WM_NCCREATE: /* non client area create */
+ /* gw is passed as the lpParam from createwindowex() */
+ createstruct = (LPCREATESTRUCTW)lparam;
+ gw = (struct gui_window *)createstruct->lpCreateParams;
+
+ /* set the gui window associated with this window handle */
+ SetProp(hwnd, TEXT("GuiWnd"), (HANDLE)gw);
+
+ NSLOG(netsurf, INFO,
+ "created hWnd:%p hInstance %p GUI window %p",
+ hwnd, createstruct->hInstance, gw);
+
+ break;
+
+ case WM_CREATE:
+ /*
+ * To cause all the component child windows to be
* re-sized correctly a WM_SIZE message of the actual
* created size must be sent.
*
@@ -1414,19 +1423,9 @@ nsws_window_event_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
* until after the WM_CREATE message is dispatched.
*/
GetClientRect(hwnd, &rmain);
- PostMessage(hwnd, WM_SIZE, 0, MAKELPARAM(rmain.right, rmain.bottom));
- return DefWindowProc(hwnd, msg, wparam, lparam);
- }
-
-
- gw = nsws_get_gui_window(hwnd);
- if (gw == NULL) {
- NSLOG(netsurf, INFO,
- "Unable to find gui window structure for hwnd %p", hwnd);
- return DefWindowProc(hwnd, msg, wparam, lparam);
- }
-
- switch (msg) {
+ PostMessage(hwnd, WM_SIZE, 0,
+ MAKELPARAM(rmain.right, rmain.bottom));
+ break;
case WM_CONTEXTMENU:
if (nsws_ctx_menu(gw, hwnd, GET_X_LPARAM(lparam),
@@ -1456,7 +1455,64 @@ nsws_window_event_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
}
- return DefWindowProc(hwnd, msg, wparam, lparam);
+ return DefWindowProcW(hwnd, msg, wparam, lparam);
+}
+
+static void destroy_page_info_bitmaps(struct gui_window *gw)
+{
+ DeleteObject(gw->hPageInfo[PAGE_STATE_UNKNOWN]);
+ DeleteObject(gw->hPageInfo[PAGE_STATE_INTERNAL]);
+ DeleteObject(gw->hPageInfo[PAGE_STATE_LOCAL]);
+ DeleteObject(gw->hPageInfo[PAGE_STATE_INSECURE]);
+ DeleteObject(gw->hPageInfo[PAGE_STATE_SECURE_OVERRIDE]);
+ DeleteObject(gw->hPageInfo[PAGE_STATE_SECURE_ISSUES]);
+ DeleteObject(gw->hPageInfo[PAGE_STATE_SECURE]);
+}
+
+static void load_page_info_bitmaps(HINSTANCE hInstance, struct gui_window *gw)
+{
+ gw->hPageInfo[PAGE_STATE_UNKNOWN] = LoadImage(hInstance,
+ MAKEINTRESOURCE(IDB_PAGEINFO_INTERNAL),
+ IMAGE_BITMAP,
+ 0,
+ 0,
+ LR_DEFAULTCOLOR);
+ gw->hPageInfo[PAGE_STATE_INTERNAL] = LoadImage(hInstance,
+ MAKEINTRESOURCE(IDB_PAGEINFO_INTERNAL),
+ IMAGE_BITMAP,
+ 0,
+ 0,
+ LR_DEFAULTCOLOR);
+ gw->hPageInfo[PAGE_STATE_LOCAL] = LoadImage(hInstance,
+ MAKEINTRESOURCE(IDB_PAGEINFO_LOCAL),
+ IMAGE_BITMAP,
+ 0,
+ 0,
+ LR_DEFAULTCOLOR);
+ gw->hPageInfo[PAGE_STATE_INSECURE] = LoadImage(hInstance,
+ MAKEINTRESOURCE(IDB_PAGEINFO_INSECURE),
+ IMAGE_BITMAP,
+ 0,
+ 0,
+ LR_DEFAULTCOLOR);
+ gw->hPageInfo[PAGE_STATE_SECURE_OVERRIDE] = LoadImage(hInstance,
+ MAKEINTRESOURCE(IDB_PAGEINFO_WARNING),
+ IMAGE_BITMAP,
+ 0,
+ 0,
+ LR_DEFAULTCOLOR);
+ gw->hPageInfo[PAGE_STATE_SECURE_ISSUES] = LoadImage(hInstance,
+ MAKEINTRESOURCE(IDB_PAGEINFO_WARNING),
+ IMAGE_BITMAP,
+ 0,
+ 0,
+ LR_DEFAULTCOLOR);
+ gw->hPageInfo[PAGE_STATE_SECURE] = LoadImage(hInstance,
+ MAKEINTRESOURCE(IDB_PAGEINFO_SECURE),
+ IMAGE_BITMAP,
+ 0,
+ 0,
+ LR_DEFAULTCOLOR);
}
@@ -1487,12 +1543,13 @@ win32_window_create(struct browser_window *bw,
gw->width = 800;
gw->height = 600;
- gw->scale = 1.0;
gw->toolbuttonsize = 24;
gw->requestscrollx = 0;
gw->requestscrolly = 0;
gw->localhistory = NULL;
+ load_page_info_bitmaps(hinst, gw);
+
gw->mouse = malloc(sizeof(struct browser_mouse));
if (gw->mouse == NULL) {
free(gw);
@@ -1551,6 +1608,8 @@ static void win32_window_destroy(struct gui_window *w)
DestroyAcceleratorTable(w->acceltable);
+ destroy_page_info_bitmaps(w);
+
free(w);
w = NULL;
}
@@ -1562,12 +1621,10 @@ static void win32_window_destroy(struct gui_window *w)
* \param gw gui_window to measure
* \param width receives width of window
* \param height receives height of window
- * \param scaled whether to return scaled values
+ * \return NSERROR_OK and width and height updated
*/
static nserror
-win32_window_get_dimensions(struct gui_window *gw,
- int *width, int *height,
- bool scaled)
+win32_window_get_dimensions(struct gui_window *gw, int *width, int *height)
{
*width = gw->width;
*height = gw->height;
@@ -1584,9 +1641,12 @@ win32_window_get_dimensions(struct gui_window *gw,
*
* \param w gui_window to update the extent of
*/
-static void win32_window_update_extent(struct gui_window *w)
+static void win32_window_update_extent(struct gui_window *gw)
{
-
+ struct rect rect;
+ rect.x0 = rect.x1 = gw->scrollx;
+ rect.y0 = rect.y1 = gw->scrolly;
+ win32_window_set_scroll(gw, &rect);
}
@@ -1599,6 +1659,8 @@ static void win32_window_update_extent(struct gui_window *w)
static void win32_window_set_title(struct gui_window *w, const char *title)
{
char *fulltitle;
+ int wlen;
+ LPWSTR enctitle;
if (w == NULL) {
return;
@@ -1607,14 +1669,32 @@ static void win32_window_set_title(struct gui_window *w, const char *title)
NSLOG(netsurf, INFO, "%p, title %s", w, title);
fulltitle = malloc(strlen(title) + SLEN(" - NetSurf") + 1);
if (fulltitle == NULL) {
- win32_warning("NoMemory", 0);
+ NSLOG(netsurf, ERROR, "%s",
+ messages_get_errorcode(NSERROR_NOMEM));
return;
}
strcpy(fulltitle, title);
strcat(fulltitle, " - NetSurf");
- SendMessage(w->main, WM_SETTEXT, 0, (LPARAM)fulltitle);
+ wlen = MultiByteToWideChar(CP_UTF8, 0, fulltitle, -1, NULL, 0);
+ if (wlen == 0) {
+ NSLOG(netsurf, ERROR, "failed encoding \"%s\"", fulltitle);
+ free(fulltitle);
+ return;
+ }
+
+ enctitle = malloc(2 * (wlen + 1));
+ if (enctitle == NULL) {
+ NSLOG(netsurf, ERROR, "%s encoding \"%s\" len %d",
+ messages_get_errorcode(NSERROR_NOMEM), fulltitle, wlen);
+ free(fulltitle);
+ return;
+ }
+
+ MultiByteToWideChar(CP_UTF8, 0, fulltitle, -1, enctitle, wlen);
+ SetWindowTextW(w->main, enctitle);
+ free(enctitle);
free(fulltitle);
}
@@ -1678,9 +1758,8 @@ win32_window_place_caret(struct gui_window *w, int x, int y,
return;
}
- CreateCaret(w->drawingarea, (HBITMAP)NULL, 1, height * w->scale);
- SetCaretPos(x * w->scale - w->scrollx,
- y * w->scale - w->scrolly);
+ CreateCaret(w->drawingarea, (HBITMAP)NULL, 1, height );
+ SetCaretPos(x - w->scrollx, y - w->scrolly);
ShowCaret(w->drawingarea);
}
@@ -1765,6 +1844,62 @@ static void win32_window_stop_throbber(struct gui_window *w)
/**
+ * win32 page info change.
+ *
+ * \param gw window to chnage info on
+ */
+static void win32_window_page_info_change(struct gui_window *gw)
+{
+ HWND hbutton;
+ browser_window_page_info_state pistate;
+
+ hbutton = GetProp(gw->toolbar, TEXT("hPGIbutton"));
+
+ pistate = browser_window_get_page_info_state(gw->bw);
+
+ SendMessageW(hbutton, BM_SETIMAGE, IMAGE_BITMAP,
+ (LPARAM)gw->hPageInfo[pistate]);
+}
+
+
+/**
+ * process miscellaneous window events
+ *
+ * \param gw The window receiving the event.
+ * \param event The event code.
+ * \return NSERROR_OK when processed ok
+ */
+static nserror
+win32_window_event(struct gui_window *gw, enum gui_window_event event)
+{
+ switch (event) {
+ case GW_EVENT_UPDATE_EXTENT:
+ win32_window_update_extent(gw);
+ break;
+
+ case GW_EVENT_REMOVE_CARET:
+ win32_window_remove_caret(gw);
+ break;
+
+ case GW_EVENT_START_THROBBER:
+ win32_window_start_throbber(gw);
+ break;
+
+ case GW_EVENT_STOP_THROBBER:
+ win32_window_stop_throbber(gw);
+ break;
+
+ case GW_EVENT_PAGE_INFO_CHANGE:
+ win32_window_page_info_change(gw);
+ break;
+
+ default:
+ break;
+ }
+ return NSERROR_OK;
+}
+
+/**
* win32 frontend browser window handling operation table
*/
static struct gui_window_table window_table = {
@@ -1774,16 +1909,13 @@ static struct gui_window_table window_table = {
.get_scroll = win32_window_get_scroll,
.set_scroll = win32_window_set_scroll,
.get_dimensions = win32_window_get_dimensions,
- .update_extent = win32_window_update_extent,
+ .event = win32_window_event,
.set_title = win32_window_set_title,
.set_url = win32_window_set_url,
.set_status = win32_window_set_status,
.set_pointer = win32_window_set_pointer,
.place_caret = win32_window_place_caret,
- .remove_caret = win32_window_remove_caret,
- .start_throbber = win32_window_start_throbber,
- .stop_throbber = win32_window_stop_throbber,
};
struct gui_window_table *win32_window_table = &window_table;
@@ -1823,13 +1955,15 @@ bool nsws_window_go(HWND hwnd, const char *urltxt)
{
struct gui_window *gw;
nsurl *url;
+ nserror ret;
gw = nsws_get_gui_window(hwnd);
if (gw == NULL)
return false;
+ ret = nsurl_create(urltxt, &url);
- if (nsurl_create(urltxt, &url) != NSERROR_OK) {
- win32_warning("NoMemory", 0);
+ if (ret != NSERROR_OK) {
+ win32_report_nserror(ret, 0);
} else {
browser_window_navigate(gw->bw,
url,
@@ -1949,7 +2083,7 @@ nserror
nsws_create_main_class(HINSTANCE hinstance)
{
nserror ret = NSERROR_OK;
- WNDCLASSEX wc;
+ WNDCLASSEXW wc;
/* main window */
wc.cbSize = sizeof(WNDCLASSEX);
@@ -1965,7 +2099,7 @@ nsws_create_main_class(HINSTANCE hinstance)
wc.lpszClassName = windowclassname_main;
wc.hIconSm = LoadIcon(hinstance, MAKEINTRESOURCE(IDR_NETSURF_ICON));
- if (RegisterClassEx(&wc) == 0) {
+ if (RegisterClassExW(&wc) == 0) {
win_perror("MainWindowClass");
ret = NSERROR_INIT_FAILED;
}
diff --git a/frontends/windows/window.h b/frontends/windows/window.h
index 3cdb9aefe..97be710f3 100644
--- a/frontends/windows/window.h
+++ b/frontends/windows/window.h
@@ -16,8 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_WINDOWS_WINDOW_H_
-#define _NETSURF_WINDOWS_WINDOW_H_
+#ifndef NETSURF_WINDOWS_WINDOW_H_
+#define NETSURF_WINDOWS_WINDOW_H_
/** The window operation function table for win32 */
extern struct gui_window_table *win32_window_table;
@@ -26,8 +26,7 @@ extern struct gui_window_table *win32_window_table;
struct browser_mouse {
struct gui_window *gui;
- struct box *box;
-
+
double pressed_x;
double pressed_y;
bool waiting;
@@ -62,7 +61,7 @@ struct gui_window {
HACCEL acceltable; /**< accelerators */
- float scale; /**< scale of content */
+ HBITMAP hPageInfo[8]; /**< page info handles */
int scrollx; /**< current scroll location */
int scrolly; /**< current scroll location */
diff --git a/include/netsurf/bitmap.h b/include/netsurf/bitmap.h
index a85efce99..10e9a07fb 100644
--- a/include/netsurf/bitmap.h
+++ b/include/netsurf/bitmap.h
@@ -20,64 +20,120 @@
* \file
* Generic bitmap handling interface.
*
- * This interface wraps the native platform-specific image format, so that
- * portable image convertors can be written.
+ * This interface wraps the native platform-specific image format.
*
- * Bitmaps are required to be 32bpp with components in the order RR GG BB AA.
+ * Bitmaps are required to be 32bpp with 8-bit components. The components are
+ * red, green, blue, and alpha, in client specified order.
*
- * For example, an opaque 1x1 pixel image would yield the following bitmap
- * data:
- *
- * > Red : 0xff 0x00 0x00 0x00
- * > Green: 0x00 0xff 0x00 0x00
- * > Blue : 0x00 0x00 0xff 0x00
- *
- * Any attempt to read pixels by casting bitmap data to uint32_t or similar
- * will need to cater for the order of bytes in a word being different on
- * big and little endian systems. To avoid confusion, it is recommended
- * that pixel data is loaded as follows:
- *
- * uint32_t read_pixel(const uint8_t *bmp)
- * {
- * // red green blue alpha
- * return bmp[0] | (bmp[1] << 8) | (bmp[2] << 16) | (bmp[3] << 24);
- * }
- *
- * and *not* as follows:
- *
- * uint32_t read_pixel(const uint8_t *bmp)
- * {
- * return *((uint32_t *) bmp);
- * }
+ * The component order may be set in the front ends by calling
+ * \ref bitmap_set_format().
*/
#ifndef _NETSURF_BITMAP_H_
#define _NETSURF_BITMAP_H_
-#define BITMAP_NEW 0
-#define BITMAP_OPAQUE (1 << 0) /**< image is opaque */
-#define BITMAP_MODIFIED (1 << 1) /**< buffer has been modified */
-#define BITMAP_CLEAR_MEMORY (1 << 2) /**< memory should be wiped */
+/** Bitmap creation flags. */
+enum gui_bitmap_flags {
+ BITMAP_NONE = 0,
+ BITMAP_OPAQUE = (1 << 0), /**< image is opaque */
+ BITMAP_CLEAR = (1 << 1), /**< memory should be wiped to 0 */
+};
+
+/**
+ * NetSurf bitmap pixel layout.
+ *
+ * All pixels are 32 bits per pixel (bpp). The different layouts allow control
+ * over the ordering of colour channels. All colour channels are 8 bits wide.
+ */
+enum bitmap_layout {
+ /** Bite-wise RGBA: Byte order: 0xRR, 0xGG, 0xBB, 0xAA. */
+ BITMAP_LAYOUT_R8G8B8A8,
+
+ /** Bite-wise BGRA: Byte order: 0xBB, 0xGG, 0xRR, 0xAA. */
+ BITMAP_LAYOUT_B8G8R8A8,
+
+ /** Bite-wise ARGB: Byte order: 0xAA, 0xRR, 0xGG, 0xBB. */
+ BITMAP_LAYOUT_A8R8G8B8,
+
+ /** Bite-wise ABGR: Byte order: 0xAA, 0xBB, 0xGG, 0xRR. */
+ BITMAP_LAYOUT_A8B8G8R8,
+
+ /**
+ * 32-bit RGBA (0xRRGGBBAA).
+ *
+ * * On little endian host, same as \ref BITMAP_LAYOUT_A8B8G8R8.
+ * * On big endian host, same as \ref BITMAP_LAYOUT_R8G8B8A8.
+ */
+ BITMAP_LAYOUT_RGBA8888,
+
+ /**
+ * 32-bit BGRA (0xBBGGRRAA).
+ *
+ * * On little endian host, same as \ref BITMAP_LAYOUT_A8R8G8B8.
+ * * On big endian host, same as \ref BITMAP_LAYOUT_B8G8R8A8.
+ */
+ BITMAP_LAYOUT_BGRA8888,
+
+ /**
+ * 32-bit ARGB (0xAARRGGBB).
+ *
+ * * On little endian host, same as \ref BITMAP_LAYOUT_B8G8R8A8.
+ * * On big endian host, same as \ref BITMAP_LAYOUT_A8R8G8B8.
+ */
+ BITMAP_LAYOUT_ARGB8888,
+
+ /**
+ * 32-bit BGRA (0xAABBGGRR).
+ *
+ * * On little endian host, same as \ref BITMAP_LAYOUT_R8G8B8A8.
+ * * On big endian host, same as \ref BITMAP_LAYOUT_A8B8G8R8.
+ */
+ BITMAP_LAYOUT_ABGR8888,
+};
+
+/** Bitmap format specifier. */
+typedef struct bitmap_fmt {
+ enum bitmap_layout layout; /**< Colour component layout. */
+ bool pma; /**< Premultiplied alpha. */
+} bitmap_fmt_t;
struct content;
struct bitmap;
struct hlcache_handle;
/**
+ * Set client bitmap format.
+ *
+ * Set this to ensure that the bitmaps decoded by the core are in the
+ * correct format for the front end.
+ *
+ * \param[in] bitmap_format The bitmap format specification to set.
+ */
+void bitmap_set_format(const bitmap_fmt_t *bitmap_format);
+
+/**
+ * Test whether a bitmap is completely opaque (no transparency).
+ *
+ * \param[in] bitmap The bitmap to test.
+ * \return Returns true if the bitmap is opaque, false otherwise.
+ */
+bool bitmap_test_opaque(void *bitmap);
+
+/**
* Bitmap operations.
*/
struct gui_bitmap_table {
- /* Mandantory entries */
+ /* Mandatory entries */
/**
* Create a new bitmap.
*
- * \param width width of image in pixels
- * \param height width of image in pixels
- * \param state The state to create the bitmap in.
+ * \param width width of image in pixels
+ * \param height height of image in pixels
+ * \param flags flags for bitmap creation
* \return A bitmap structure or NULL on error.
*/
- void *(*create)(int width, int height, unsigned int state);
+ void *(*create)(int width, int height, enum gui_bitmap_flags flags);
/**
* Destroy a bitmap.
@@ -103,16 +159,10 @@ struct gui_bitmap_table {
bool (*get_opaque)(void *bitmap);
/**
- * Test if a bitmap is opaque.
- *
- * \param bitmap The bitmap to examine.
- * \return The bitmap opacity.
- */
- bool (*test_opaque)(void *bitmap);
-
- /**
* Get the image buffer from a bitmap
*
+ * Note that all pixels must be 4-byte aligned.
+ *
* \param bitmap The bitmap to get the buffer from.
* \return The image buffer or NULL if there is none.
*/
@@ -143,22 +193,6 @@ struct gui_bitmap_table {
int (*get_height)(void *bitmap);
/**
- * The the *bytes* per pixel.
- *
- * \param bitmap The bitmap
- */
- size_t (*get_bpp)(void *bitmap);
-
- /**
- * Savde a bitmap to disc.
- *
- * \param bitmap The bitmap to save
- * \param path The path to save the bitmap to.
- * \param flags Flags affecting the save.
- */
- bool (*save)(void *bitmap, const char *path, unsigned flags);
-
- /**
* Marks a bitmap as modified.
*
* \param bitmap The bitmap set as modified.
diff --git a/include/netsurf/browser.h b/include/netsurf/browser.h
new file mode 100644
index 000000000..dfe8eb3df
--- /dev/null
+++ b/include/netsurf/browser.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
+ * Copyright 2006 James Bursa <bursa@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Browser interfaces.
+ */
+
+#ifndef NETSURF_BROWSER_H_
+#define NETSURF_BROWSER_H_
+
+/**
+ * Set the DPI of the browser.
+ *
+ * \param dpi The DPI to set.
+ */
+nserror browser_set_dpi(int dpi);
+
+/**
+ * Get the browser DPI.
+ *
+ * \return The DPI in use.
+ */
+int browser_get_dpi(void);
+
+#endif
diff --git a/include/netsurf/browser_window.h b/include/netsurf/browser_window.h
index 6c44e161f..521340a82 100644
--- a/include/netsurf/browser_window.h
+++ b/include/netsurf/browser_window.h
@@ -22,14 +22,15 @@
* Browser window creation and manipulation interface.
*/
-#ifndef _NETSURF_BROWSER_WINDOW_H_
-#define _NETSURF_BROWSER_WINDOW_H_
+#ifndef NETSURF_BROWSER_WINDOW_H_
+#define NETSURF_BROWSER_WINDOW_H_
#include <stdbool.h>
#include <stdio.h>
#include "utils/errors.h"
#include "netsurf/mouse.h"
+#include "netsurf/console.h"
struct browser_window;
struct hlcache_handle;
@@ -41,6 +42,7 @@ struct form_control;
struct nsurl;
struct rect;
struct redraw_context;
+struct cert_chain;
enum content_debug;
/**
@@ -57,6 +59,20 @@ typedef enum {
DRAGGING_OTHER
} browser_drag_type;
+/**
+ * Browser window page information states
+ */
+typedef enum {
+ PAGE_STATE_UNKNOWN, /**< Unable to determine */
+ PAGE_STATE_INTERNAL, /**< Page loaded from internal handler */
+ PAGE_STATE_LOCAL, /**< Page loaded from file:/// etc */
+ PAGE_STATE_INSECURE, /**< Insecure page load */
+ PAGE_STATE_SECURE_OVERRIDE, /**< Secure load, but had to override */
+ PAGE_STATE_SECURE_ISSUES, /**< Secure load, but has insecure elements */
+ PAGE_STATE_SECURE, /**< Secure load */
+ PAGE_STATE__COUNT, /**< Count of number of valid page states */
+} browser_window_page_info_state;
+
typedef enum {
BW_EDITOR_NONE = 0, /**< No selection, no editing */
BW_EDITOR_CAN_COPY = (1 << 0), /**< Have selection */
@@ -94,6 +110,12 @@ enum browser_window_create_flags {
* have that option.
*/
BW_CREATE_UNVERIFIABLE = (1 << 3),
+
+ /** Request foreground opening. */
+ BW_CREATE_FOREGROUND = (1 << 4),
+
+ /** Request location bar focus. */
+ BW_CREATE_FOCUS_LOCATION = (1 << 5),
};
/** flags to browser_window_navigate */
@@ -119,7 +141,10 @@ enum browser_window_nav_flags {
BW_NAVIGATE_UNVERIFIABLE = (1 << 2),
/** suppress initial history updates (used by back/fwd/etc) */
- BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE = (1 << 3)
+ BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE = (1 << 3),
+
+ /** Internal navigation (set only by core features using such) */
+ BW_NAVIGATE_INTERNAL = (1 << 4)
};
/**
@@ -200,14 +225,27 @@ bool browser_window_up_available(struct browser_window *bw);
nserror browser_window_navigate_up(struct browser_window *bw, bool new_window);
/**
- * Get a browser window's URL.
+ * Access a browser window's URL. This URL is always without any fragment.
*
* \param bw browser window
* \return pointer to nsurl. Doesn't create a ref for caller.
*
* \note guaranteed to return a valid nsurl ptr, never returns NULL.
*/
-struct nsurl* browser_window_get_url(struct browser_window *bw);
+struct nsurl* browser_window_access_url(const struct browser_window *bw);
+
+/**
+ * Access a browser window's URL.
+ *
+ * \param[in] bw browser window
+ * \param[in] fragment Whether to include any URL fragment.
+ * \param[out] url_out Returns a ref to the URL on success.
+ * \return NSERROR_OK, or appropriate error otherwise.
+ */
+nserror browser_window_get_url(
+ struct browser_window *bw,
+ bool fragment,
+ struct nsurl** url_out);
/**
* Get the title of a browser_window.
@@ -251,6 +289,7 @@ bool browser_window_has_content(struct browser_window *bw);
*/
struct hlcache_handle *browser_window_get_content(struct browser_window *bw);
+
/**
* Set the dimensions of the area a browser window occupies
*
@@ -261,21 +300,6 @@ struct hlcache_handle *browser_window_get_content(struct browser_window *bw);
void browser_window_set_dimensions(struct browser_window *bw,
int width, int height);
-/**
- * Redraw browser window, set extent to content, and update title.
- *
- * \param bw browser_window
- * \param scroll_to_top move view to top of page
- */
-void browser_window_update(struct browser_window *bw, bool scroll_to_top);
-
-/**
- * update an area of a browser window.
- *
- * \param bw The browser window to update.
- * \param rect The area to redraw
- */
-void browser_window_update_box(struct browser_window *bw, struct rect *rect);
/**
* Stop all fetching activity in a browser window.
@@ -284,13 +308,16 @@ void browser_window_update_box(struct browser_window *bw, struct rect *rect);
*/
void browser_window_stop(struct browser_window *bw);
+
/**
* Reload the page in a browser window.
*
- * \param bw browser window
- * \param all whether to reload all objects associated with the page
+ * \param bw browser window
+ * \param all whether to reload all objects associated with the page
+ * \return NSERROR_OK on success else error code.
*/
-void browser_window_reload(struct browser_window *bw, bool all);
+nserror browser_window_reload(struct browser_window *bw, bool all);
+
/**
* Close and destroy a browser window.
@@ -323,9 +350,10 @@ void browser_window_reformat(struct browser_window *bw, bool background, int wid
*
* \param bw The browser window to scale.
* \param scale The new scale.
- * \param all Scale all windows in the tree (ie work up as well as down)
+ * \param absolute If the scale value is absolute or relative to current value
+ * \return NSERROR_OK and scale applied else other error code caused by reflow etc.
*/
-void browser_window_set_scale(struct browser_window *bw, float scale, bool all);
+nserror browser_window_set_scale(struct browser_window *bw, float scale, bool absolute);
/**
@@ -336,6 +364,7 @@ void browser_window_set_scale(struct browser_window *bw, float scale, bool all);
*/
float browser_window_get_scale(struct browser_window *bw);
+
/**
* Get access to any page features at the given coordinates.
*
@@ -354,6 +383,7 @@ float browser_window_get_scale(struct browser_window *bw);
nserror browser_window_get_features(struct browser_window *bw,
int x, int y, struct browser_window_features *data);
+
/**
* Send a scroll request to a browser window at a particular point. The
* 'deepest' scrollable object which can be scrolled in the requested
@@ -369,6 +399,7 @@ nserror browser_window_get_features(struct browser_window *bw,
bool browser_window_scroll_at_point(struct browser_window *bw,
int x, int y, int scrx, int scry);
+
/**
* Drop a file onto a browser window at a particular point, or determine if a
* file may be dropped onto the content at given point.
@@ -382,6 +413,7 @@ bool browser_window_scroll_at_point(struct browser_window *bw,
bool browser_window_drop_file_at_point(struct browser_window *bw,
int x, int y, char *file);
+
/**
* set filename on form control.
*
@@ -392,6 +424,7 @@ bool browser_window_drop_file_at_point(struct browser_window *bw,
void browser_window_set_gadget_filename(struct browser_window *bw,
struct form_control *gadget, const char *fn);
+
/**
* Update URL bar for a given browser window to bw's content's URL
*
@@ -399,6 +432,7 @@ void browser_window_set_gadget_filename(struct browser_window *bw,
*/
nserror browser_window_refresh_url_bar(struct browser_window *bw);
+
/**
* Handle mouse clicks in a browser window.
*
@@ -410,6 +444,7 @@ nserror browser_window_refresh_url_bar(struct browser_window *bw);
void browser_window_mouse_click(struct browser_window *bw,
browser_mouse_state mouse, int x, int y);
+
/**
* Handle non-click mouse action in a browser window. (drag ends, movements)
*
@@ -452,26 +487,6 @@ nserror browser_window_schedule_reformat(struct browser_window *bw);
/**
- * callback for select menu widget
- *
- * \todo This API needs investigating
- */
-void browser_select_menu_callback(void *client_data,
- int x, int y, int width, int height);
-
-/**
- * Redraw a rectangular region of a browser window.
- *
- * \param bw browser window to be redrawn
- * \param x x co-ord of top-left
- * \param y y co-ord of top-left
- * \param width width of rectangle
- * \param height height of rectangle
- */
-void browser_window_redraw_rect(struct browser_window *bw, int x, int y,
- int width, int height);
-
-/**
* Change the shape of the mouse pointer
*
* \param bw Browser window to set shape in
@@ -480,6 +495,7 @@ void browser_window_redraw_rect(struct browser_window *bw, int x, int y,
void browser_window_set_pointer(struct browser_window *bw,
browser_pointer_shape shape);
+
/**
* Start drag scrolling the contents of the browser window
*
@@ -489,6 +505,7 @@ void browser_window_set_pointer(struct browser_window *bw,
*/
void browser_window_page_drag_start(struct browser_window *bw, int x, int y);
+
/**
* Check availability of Back action for a given browser window
*
@@ -497,6 +514,7 @@ void browser_window_page_drag_start(struct browser_window *bw, int x, int y);
*/
bool browser_window_back_available(struct browser_window *bw);
+
/**
* Check availability of Forward action for a given browser window
*
@@ -505,6 +523,7 @@ bool browser_window_back_available(struct browser_window *bw);
*/
bool browser_window_forward_available(struct browser_window *bw);
+
/**
* Check availability of Reload action for a given browser window
*
@@ -513,6 +532,7 @@ bool browser_window_forward_available(struct browser_window *bw);
*/
bool browser_window_reload_available(struct browser_window *bw);
+
/**
* Check availability of Stop action for a given browser window
*
@@ -521,6 +541,7 @@ bool browser_window_reload_available(struct browser_window *bw);
*/
bool browser_window_stop_available(struct browser_window *bw);
+
/**
* Redraw an area of a window.
*
@@ -545,6 +566,7 @@ bool browser_window_stop_available(struct browser_window *bw);
bool browser_window_redraw(struct browser_window *bw, int x, int y,
const struct rect *clip, const struct redraw_context *ctx);
+
/**
* Check whether browser window is ready for redraw
*
@@ -652,19 +674,6 @@ bool browser_window_is_frameset(struct browser_window *bw);
nserror browser_window_get_scrollbar_type(struct browser_window *bw,
browser_scrolling *h, browser_scrolling *v);
-/**
- * Set the DPI of the browser.
- *
- * \param dpi The DPI to set.
- */
-nserror browser_set_dpi(int dpi);
-
-/**
- * Get the browser DPI.
- *
- * \return The DPI in use.
- */
-int browser_get_dpi(void);
/**
* Dump debug info concerning the browser window's contents to file
@@ -712,4 +721,93 @@ nserror browser_window_get_name(struct browser_window *bw, const char **name);
*/
nserror browser_window_set_name(struct browser_window *bw, const char *name);
+/**
+ * Execute some JavaScript code in a browsing context.
+ *
+ * Runs the passed in JavaScript code in the browsing context.
+ *
+ * \param bw The browser window
+ * \param src The JavaScript source code
+ * \param srclen The length of the source code
+ * \return Whether the JS function was successfully injected into the content
+ */
+bool browser_window_exec(struct browser_window *bw, const char *src, size_t srclen);
+
+/**
+ * Log a console message into the browser window console.
+ *
+ * If the targetted browser window is a frame, the message will be bubbled
+ * to the outermost window to be logged.
+ *
+ * \param bw The browser window
+ * \param src The source of the message
+ * \param msg The text of the message
+ * \param msglen The length of the text of the message
+ * \param flags Flags for the message
+ * \return Whether or not the logged message succeeded in being stored
+ */
+nserror browser_window_console_log(struct browser_window *bw,
+ browser_window_console_source src,
+ const char *msg,
+ size_t msglen,
+ browser_window_console_flags flags);
+
+/**
+ * Request the current browser window page info state.
+ *
+ * The page information state is an indicator enumeration to be used by
+ * frontends to indicate to the user if the page they are viewing is able
+ * to be trusted. This is often shown as a padlock of some kind.
+ *
+ * This is also used by the internal page information corewindow to render
+ * to the user what the situation is.
+ *
+ * \param bw The browser window
+ * \return The state of the browser window
+ */
+browser_window_page_info_state browser_window_get_page_info_state(
+ const struct browser_window *bw);
+
+/**
+ * Request the current browser window SSL certificate chain.
+ *
+ * When the page has SSL information, this will retrieve the certificate chain.
+ *
+ * If there is no chain available, this will return NSERROR_NOT_FOUND
+ *
+ * \param bw The browser window
+ * \param chain Pointer to be filled out with certificate chain
+ * \return Whether or not the chain is available
+ */
+nserror browser_window_get_ssl_chain(struct browser_window *bw, struct cert_chain **chain);
+
+/**
+ * Get the number of cookies in use for the current page.
+ *
+ * \param bw A browser window.
+ * \return Number of cookies in use, or 0 on error.
+ */
+int browser_window_get_cookie_count(
+ const struct browser_window *bw);
+
+/**
+ * Open cookie viewer for the current page.
+ *
+ * \param bw A browser window.
+ * \return NSERROR_OK, or appropriate error otherwise.
+ */
+nserror browser_window_show_cookies(
+ const struct browser_window *bw);
+
+/**
+ * Show the certificate page for the current page.
+ *
+ * Does nothing for a page without certificates.
+ *
+ * \param bw A browser window.
+ * \return NSERROR_OK, or appropriate error otherwise.
+ */
+nserror browser_window_show_certificates(
+ struct browser_window *bw);
+
#endif
diff --git a/include/netsurf/console.h b/include/netsurf/console.h
new file mode 100644
index 000000000..dead3fd2e
--- /dev/null
+++ b/include/netsurf/console.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2019 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Browser window console stuff
+ */
+
+#ifndef _NETSURF_CONSOLE_H_
+#define _NETSURF_CONSOLE_H_
+
+/**
+ * Sources of messages which end up in the browser window console
+ */
+typedef enum {
+ BW_CS_INPUT, /**< Input from the client */
+ BW_CS_SCRIPT_ERROR, /**< Error from some running script */
+ BW_CS_SCRIPT_CONSOLE, /**< Logging from some running script */
+} browser_window_console_source;
+
+/**
+ * Flags for browser window console logging.
+ *
+ * It is valid to bitwise-or some of these flags together where indicated.
+ */
+typedef enum {
+ /**
+ * The log entry is foldable.
+ *
+ * Set this to indicate that the text should be folded on the first
+ * newline on display. If this is set but there are no newlines in
+ * the logged text, the core will unset it before passing on to
+ * callbacks or storing the log entry.
+ */
+ BW_CS_FLAG_FOLDABLE = 1 << 0,
+
+ /** Logged at the 'debug' level, please use only one of the LEVEL flags */
+ BW_CS_FLAG_LEVEL_DEBUG = 0 << 1,
+ /** Logged at the 'log' level, please only use one of the LEVEL flags */
+ BW_CS_FLAG_LEVEL_LOG = 1 << 1,
+ /** Logged at the 'info' level, please use only one of the LEVEL flags */
+ BW_CS_FLAG_LEVEL_INFO = 2 << 1,
+ /** Logged at the 'warn' level, please use only one of the LEVEL flags */
+ BW_CS_FLAG_LEVEL_WARN = 3 << 1,
+ /** Logged at the 'error' level, please use only one of the LEVEL flags */
+ BW_CS_FLAG_LEVEL_ERROR = 4 << 1,
+ /* Levels 5, 6, 7 unused as yet */
+ /** Mask for the error level to allow easy comparison using the above */
+ BW_CS_FLAG_LEVEL_MASK = 7 << 1,
+} browser_window_console_flags;
+
+#endif /* _NETSURF_CONSOLE_H_ */
+
diff --git a/include/netsurf/content.h b/include/netsurf/content.h
index 5eee59acd..d8adca040 100644
--- a/include/netsurf/content.h
+++ b/include/netsurf/content.h
@@ -94,7 +94,7 @@ lwc_string *content_get_mime_type(struct hlcache_handle *h);
* \param size Pointer to location to receive byte size of source
* \return Pointer to source data
*/
-const char *content_get_source_data(struct hlcache_handle *h, unsigned long *size);
+const uint8_t *content_get_source_data(struct hlcache_handle *h, size_t *size);
/**
diff --git a/include/netsurf/content_type.h b/include/netsurf/content_type.h
index ef654cd70..0a6b83009 100644
--- a/include/netsurf/content_type.h
+++ b/include/netsurf/content_type.h
@@ -18,7 +18,7 @@
/**
* \file
- * Declaration of content type enumerations.
+ * Declaration of content enumerations.
*
* The content enumerations are defined here.
*/
@@ -28,17 +28,27 @@
/** Debugging dump operations */
enum content_debug {
- CONTENT_DEBUG_RENDER, /** Debug the contents rendering. */
- CONTENT_DEBUG_DOM, /** Debug the contents Document Object. */
- CONTENT_DEBUG_REDRAW /** Debug redraw operations. */
+ /** Debug the contents rendering. */
+ CONTENT_DEBUG_RENDER,
+
+ /** Debug the contents Document Object. */
+ CONTENT_DEBUG_DOM,
+
+ /** Debug redraw operations. */
+ CONTENT_DEBUG_REDRAW
};
+
/** Content encoding information types */
enum content_encoding_type {
- CONTENT_ENCODING_NORMAL, /** The content encoding */
- CONTENT_ENCODING_SOURCE /** The content encoding source */
+ /** The content encoding */
+ CONTENT_ENCODING_NORMAL,
+
+ /** The content encoding source */
+ CONTENT_ENCODING_SOURCE
};
+
/** The type of a content. */
typedef enum {
/** no type for content */
@@ -73,4 +83,101 @@ typedef enum {
} content_type;
+/** Status of a content */
+typedef enum {
+ /** Content is being fetched or converted and is not safe to display. */
+ CONTENT_STATUS_LOADING,
+
+ /** Some parts of content still being loaded, but can be displayed. */
+ CONTENT_STATUS_READY,
+
+ /** Content has completed all processing. */
+ CONTENT_STATUS_DONE,
+
+ /** Error occurred, content will be destroyed imminently. */
+ CONTENT_STATUS_ERROR
+} content_status;
+
+
+/**
+ * Used in callbacks to indicate what has occurred.
+ */
+typedef enum {
+ /** Content wishes to log something */
+ CONTENT_MSG_LOG,
+
+ /** Content is from SSL and this is its chain */
+ CONTENT_MSG_SSL_CERTS,
+
+ /** fetching or converting */
+ CONTENT_MSG_LOADING,
+
+ /** may be displayed */
+ CONTENT_MSG_READY,
+
+ /** content has finished processing */
+ CONTENT_MSG_DONE,
+
+ /** error occurred */
+ CONTENT_MSG_ERROR,
+
+ /** fetch url redirect occured */
+ CONTENT_MSG_REDIRECT,
+
+ /** new status string */
+ CONTENT_MSG_STATUS,
+
+ /** content_reformat done */
+ CONTENT_MSG_REFORMAT,
+
+ /** needs redraw (eg. new animation frame) */
+ CONTENT_MSG_REDRAW,
+
+ /** wants refresh */
+ CONTENT_MSG_REFRESH,
+
+ /** download, not for display */
+ CONTENT_MSG_DOWNLOAD,
+
+ /** RFC5988 link */
+ CONTENT_MSG_LINK,
+
+ /** Javascript thread */
+ CONTENT_MSG_GETTHREAD,
+
+ /** Get viewport dimensions. */
+ CONTENT_MSG_GETDIMS,
+
+ /** Request to scroll content */
+ CONTENT_MSG_SCROLL,
+
+ /** Allow drag saving of content */
+ CONTENT_MSG_DRAGSAVE,
+
+ /** Allow URL to be saved */
+ CONTENT_MSG_SAVELINK,
+
+ /** Wants a specific mouse pointer set */
+ CONTENT_MSG_POINTER,
+
+ /** A selection made or cleared */
+ CONTENT_MSG_SELECTION,
+
+ /** Caret movement / hiding */
+ CONTENT_MSG_CARET,
+
+ /** A drag started or ended */
+ CONTENT_MSG_DRAG,
+
+ /** Create a select menu */
+ CONTENT_MSG_SELECTMENU,
+
+ /** A gadget has been clicked on (mainly for file) */
+ CONTENT_MSG_GADGETCLICK,
+
+ /** A free text search action has occurred */
+ CONTENT_MSG_TEXTSEARCH
+} content_msg;
+
+
#endif
diff --git a/include/netsurf/core_window.h b/include/netsurf/core_window.h
index 77d220b9c..8cbd8efbf 100644
--- a/include/netsurf/core_window.h
+++ b/include/netsurf/core_window.h
@@ -74,16 +74,33 @@ struct core_window_callback_table {
* \param[in] cw the core window object
* \param[in] width the width in px, or negative if don't care
* \param[in] height the height in px, or negative if don't care
+ * \return NSERROR_OK on success or appropriate error code
*/
- void (*update_size)(struct core_window *cw, int width, int height);
+ nserror (*update_size)(struct core_window *cw, int width, int height);
/**
- * Scroll the window to make area visible
+ * Scroll the window to given scroll offsets
+ *
+ * Note: Core callers of this may want to look at calling
+ * the `cw_helper_scroll_visible()`, rather than calling
+ * this directly.
*
* \param[in] cw the core window object
- * \param[in] r rectangle to make visible
+ * \param[in] x x-scroll value to set
+ * \param[in] y y-scroll value to set
+ * \return NSERROR_OK on success or appropriate error code
*/
- void (*scroll_visible)(struct core_window *cw, const struct rect *r);
+ nserror (*set_scroll)(struct core_window *cw, int x, int y);
+
+ /**
+ * Get the current scroll offsets
+ *
+ * \param[in] cw the core window object
+ * \param[out] returns horizontal scroll in px
+ * \param[out] returns vertical scroll in px
+ * \return NSERROR_OK on success or appropriate error code
+ */
+ nserror (*get_scroll)(const struct core_window *cw, int *x, int *y);
/**
* Get window viewport dimensions
@@ -91,8 +108,9 @@ struct core_window_callback_table {
* \param[in] cw the core window object
* \param[out] width to be set to viewport width in px
* \param[out] height to be set to viewport height in px
+ * \return NSERROR_OK on success or appropriate error code
*/
- void (*get_window_dimensions)(struct core_window *cw,
+ nserror (*get_window_dimensions)(const struct core_window *cw,
int *width, int *height);
/**
@@ -100,8 +118,9 @@ struct core_window_callback_table {
*
* \param[in] cw the core window object
* \param[in] ds the current drag status
+ * \return NSERROR_OK on success or appropriate error code
*/
- void (*drag_status)(struct core_window *cw,
+ nserror (*drag_status)(struct core_window *cw,
core_window_drag_status ds);
};
diff --git a/include/netsurf/fetch.h b/include/netsurf/fetch.h
index 6e6d653ee..156f4d1ef 100644
--- a/include/netsurf/fetch.h
+++ b/include/netsurf/fetch.h
@@ -49,15 +49,15 @@ struct gui_fetch_table {
/**
* Translate resource to full url.
*
- * @note Only used in resource fetcher
+ * @note Only used in resource protocol fetcher
*
- * Transforms a resource: path into a full URL. The returned URL
+ * Transforms a resource protocol path into a full URL. The returned URL
* is used as the target for a redirect. The caller takes ownership of
* the returned nsurl including unrefing it when finished with it.
*
* \param path The path of the resource to locate.
- * \return A string containing the full URL of the target object or
- * NULL if no suitable resource can be found.
+ * \return A netsurf url object containing the full URL of the resource
+ * path or NULL if a suitable resource URL can not be generated.
*/
struct nsurl* (*get_resource_url)(const char *path);
@@ -99,6 +99,23 @@ struct gui_fetch_table {
*/
char *(*mimetype)(const char *ro_path);
+ /**
+ * Open a socket
+ *
+ * \param domain Communication domain
+ * \param type Socket type
+ * \param protocol Protocol
+ * \return Socket descriptor on success, -1 on error and errno set
+ */
+ int (*socket_open)(int domain, int type, int protocol);
+
+ /**
+ * Close a socket
+ *
+ * \param socket Socket descriptor
+ * \return 0 on success, -1 on error and errno set
+ */
+ int (*socket_close)(int socket);
};
#endif
diff --git a/include/netsurf/inttypes.h b/include/netsurf/inttypes.h
index 874d83f3d..e2229085a 100644
--- a/include/netsurf/inttypes.h
+++ b/include/netsurf/inttypes.h
@@ -34,6 +34,10 @@
#define PRId64 "lld"
#endif
+#ifndef PRIu64
+#define PRIu64 "llu"
+#endif
+
/* Windows does not have sizet formating codes */
#if defined(_WIN32)
@@ -48,8 +52,13 @@
/** c99 standard printf formatting for size_t type */
#define PRIsizet "zu"
+#if defined(__riscos__)
+/** riscos/unixlib defines ssize_t as a long int */
+#define PRIssizet "ld"
+#else
/** c99 standard printf formatting for ssize_t type */
#define PRIssizet "zd"
+#endif
#endif
diff --git a/include/netsurf/keypress.h b/include/netsurf/keypress.h
index 604d2dd9b..84d9d41c8 100644
--- a/include/netsurf/keypress.h
+++ b/include/netsurf/keypress.h
@@ -59,7 +59,9 @@ enum input_key {
NS_KEY_TEXT_START,
NS_KEY_TEXT_END,
NS_KEY_WORD_LEFT,
+ NS_KEY_DELETE_WORD_LEFT,
NS_KEY_WORD_RIGHT,
+ NS_KEY_DELETE_WORD_RIGHT,
NS_KEY_PAGE_UP,
NS_KEY_PAGE_DOWN,
NS_KEY_DELETE_LINE_END,
diff --git a/include/netsurf/misc.h b/include/netsurf/misc.h
index 2647b9a1c..00ac705cc 100644
--- a/include/netsurf/misc.h
+++ b/include/netsurf/misc.h
@@ -22,12 +22,12 @@
* Interface to platform-specific miscellaneous browser operation table.
*/
-#ifndef _NETSURF_MISC_H_
-#define _NETSURF_MISC_H_
+#ifndef NETSURF_MISC_H_
+#define NETSURF_MISC_H_
struct form_control;
struct gui_window;
-struct ssl_cert_info;
+struct cert_chain;
struct nsurl;
/**
@@ -57,17 +57,6 @@ struct gui_misc_table {
*/
nserror (*schedule)(int t, void (*callback)(void *p), void *p);
- /**
- * Warn the user of an event.
- *
- * \param[in] message A warning looked up in the message
- * translation table
- * \param[in] detail Additional text to be displayed or NULL.
- * \return NSERROR_OK on success or error code if there was a
- * faliure displaying the message to the user.
- */
- nserror (*warning)(const char *message, const char *detail);
-
/* Optional entries */
@@ -82,28 +71,59 @@ struct gui_misc_table {
nserror (*launch_url)(struct nsurl *url);
/**
- * Prompt the user to verify a certificate with issuse.
+ * Retrieve username/password for a given url+realm if there is one
+ * stored in a frontend-specific way (e.g. gnome-keyring)
+ *
+ * To respond, call the callback with the url, realm, username,
+ * and password. Pass "" if the empty string
+ * is required.
+ *
+ * To keep hold of the url, remember to nsurl_ref() it, and to keep
+ * the realm, you will need to strdup() it.
+ *
+ * If the front end returns NSERROR_OK for this function, they may,
+ * at some future time, call the `cb` with `cbpw` callback exactly once.
+ *
+ * If the front end returns other than NSERROR_OK, they should not
+ * call the `cb` callback.
+ *
+ * The callback should not be called immediately upon receipt of this
+ * call as the browser window may not be reentered.
*
- * \param url The URL being verified.
- * \param certs The certificate to be verified
- * \param num The number of certificates to be verified.
- * \param cb Callback upon user decision.
- * \param cbpw Context pointer passed to cb
+ * **NOTE** The lifetime of the cbpw is not well defined. In general
+ * do not use the cb if *any* browser window has navigated or been
+ * destroyed.
+ *
+ * \param url The URL being verified.
+ * \param realm The authorization realm.
+ * \param username Any current username (or empty string).
+ * \param password Any current password (or empty string).
+ * \param cb Callback upon user decision.
+ * \param cbpw Context pointer passed to cb
* \return NSERROR_OK on sucess else error and cb never called
*/
- nserror (*cert_verify)(struct nsurl *url, const struct ssl_cert_info *certs, unsigned long num, nserror (*cb)(bool proceed, void *pw), void *cbpw);
-
- /**
- * Prompt user for login
- */
- void (*login)(struct nsurl *url, const char *realm,
- nserror (*cb)(bool proceed, void *pw), void *cbpw);
+ nserror (*login)(struct nsurl *url, const char *realm,
+ const char *username, const char *password,
+ nserror (*cb)(struct nsurl *url,
+ const char *realm,
+ const char *username,
+ const char *password,
+ void *pw),
+ void *cbpw);
/**
* Prompt the user for a password for a PDF.
*/
void (*pdf_password)(char **owner_pass, char **user_pass, char *path);
+ /**
+ * Request that the cookie manager be displayed
+ *
+ * \param search_term The search term to be set (NULL if no search)
+ *
+ * \return NSERROR_OK on success
+ */
+ nserror (*present_cookies)(const char *search_term);
};
#endif
diff --git a/include/netsurf/plot_style.h b/include/netsurf/plot_style.h
index 30db3663e..875020cd8 100644
--- a/include/netsurf/plot_style.h
+++ b/include/netsurf/plot_style.h
@@ -25,6 +25,8 @@
#define NETSURF_PLOT_STYLE_H
#include <stdint.h>
+#include <stdint.h>
+#include <libwapcaplet/libwapcaplet.h>
#include "netsurf/types.h"
/** light grey widget base colour */
@@ -36,8 +38,26 @@
/** Transparent colour value. */
#define NS_TRANSPARENT 0x01000000
-/** Scaling factor for font sizes */
-#define FONT_SIZE_SCALE 1024
+/** 22:10 fixed point */
+#define PLOT_STYLE_RADIX (10)
+
+/** Scaling factor for plot styles */
+#define PLOT_STYLE_SCALE (1 << PLOT_STYLE_RADIX)
+
+/* type for fixed point numbers */
+typedef int32_t plot_style_fixed;
+
+/* Convert an int to fixed point */
+#define plot_style_int_to_fixed(v) ((v) << PLOT_STYLE_RADIX)
+
+/* Convert fixed point to int */
+#define plot_style_fixed_to_int(v) ((v) >> PLOT_STYLE_RADIX)
+
+/* Convert fixed point to float */
+#define plot_style_fixed_to_float(v) (((float)v) / PLOT_STYLE_SCALE)
+
+/* Convert fixed point to double */
+#define plot_style_fixed_to_double(v) (((double)v) / PLOT_STYLE_SCALE)
/**
* Type of plot operation
@@ -55,7 +75,7 @@ typedef enum {
*/
typedef struct plot_style_s {
plot_operation_type_t stroke_type; /**< Stroke plot type */
- int stroke_width; /**< Width of stroke, in pixels */
+ plot_style_fixed stroke_width; /**< Width of stroke, in pixels */
colour stroke_colour; /**< Colour of stroke */
plot_operation_type_t fill_type; /**< Fill plot type */
colour fill_colour; /**< Colour of fill */
@@ -89,8 +109,14 @@ typedef enum {
* Font style for plotting
*/
typedef struct plot_font_style {
+ /**
+ * Array of pointers to font families.
+ *
+ * May be NULL. Array is NULL terminated.
+ */
+ lwc_string * const * families;
plot_font_generic_family_t family; /**< Generic family to plot with */
- int size; /**< Font size, in points * FONT_SIZE_SCALE */
+ plot_style_fixed size; /**< Font size, in pt */
int weight; /**< Font weight: value in range [100,900] as per CSS */
plot_font_flags_t flags; /**< Font flags */
colour background; /**< Background colour to blend to, if appropriate */
@@ -98,8 +124,13 @@ typedef struct plot_font_style {
} plot_font_style_t;
+/* Darken a colour by taking seven eighths of each channel's intensity */
+#define half_darken_colour(c1) \
+ ((((7 * (c1 & 0xff00ff)) >> 3) & 0xff00ff) | \
+ (((7 * (c1 & 0x00ff00)) >> 3) & 0x00ff00))
+
/* Darken a colour by taking three quarters of each channel's intensity */
-#define darken_colour(c1) \
+#define darken_colour(c1) \
((((3 * (c1 & 0xff00ff)) >> 2) & 0xff00ff) | \
(((3 * (c1 & 0x00ff00)) >> 2) & 0x00ff00))
@@ -108,6 +139,12 @@ typedef struct plot_font_style {
((((9 * (c1 & 0xff00ff)) >> 4) & 0xff00ff) | \
(((9 * (c1 & 0x00ff00)) >> 4) & 0x00ff00))
+/* Lighten a colour by taking seven eighths of each channel's intensity
+ * and adding a full one eighth intensity */
+#define half_lighten_colour(c1) \
+ (((((7 * (c1 & 0xff00ff)) >> 3) + 0x200020) & 0xff00ff) | \
+ ((((7 * (c1 & 0x00ff00)) >> 3) + 0x002000) & 0x00ff00))
+
/* Lighten a colour by taking 12/16ths of each channel's intensity
* and adding a full 4/16ths intensity */
#define lighten_colour(c1) \
@@ -127,13 +164,34 @@ typedef struct plot_font_style {
(((((c0 & 0xff00ff) + (c1 & 0xff00ff)) >> 1) & 0xff00ff) | \
((((c0 & 0x00ff00) + (c1 & 0x00ff00)) >> 1) & 0x00ff00))
+/**
+ * Obtain the luminance of a colour according to ITU BT.601
+ *
+ * ITU BT.601 formula is
+ * Y = 0.299 R + 0.587 G + 0.114 B
+ * actual values are
+ * Y = 76/255 R + 150/255 G + 29/255 B
+ * Y = 0.298 R + 0.588 G + 0.113 B
+ *
+ * @note if additional performance is required this could be altered to
+ * Y = 0.375 R + 0.5 G + 0.125 B
+ * with
+ * Y = (R << 1 + R + G << 2 + B) >> 3
+ */
+#define colour_lightness(c0) \
+ ((((c0 & 0x0000ff) * 77) >> 8) + \
+ (((c0 & 0x00ff00) * 151) >> 16) + \
+ (((c0 & 0xff0000) * 30) >> 24))
+
+/* Choose either black or white, depending on which is nearest to the
+ * percieved lightness of the supplied colour, c0. */
+#define colour_to_bw_nearest(c0) \
+ ((colour_lightness(c0) > (0xff / 2)) ? 0xffffff : 0x000000)
+
/* Choose either black or white, depending on which is furthest from the
* percieved lightness of the supplied colour, c0. */
#define colour_to_bw_furthest(c0) \
- ((((((c0 & 0x0000ff) * 77) >> 8) + \
- (((c0 & 0x00ff00) * 151) >> 16) + \
- (((c0 & 0xff0000) * 28) >> 24)) > \
- (0xff / 2)) ? 0x000000 : 0xffffff)
+ ((colour_lightness(c0) > (0xff / 2)) ? 0x000000 : 0xffffff)
/* Mix two colours according to the proportion given by p, where 0 <= p <= 255
* p = 0 gives result ==> c1, p = 255 gives result ==> c0 */
@@ -143,10 +201,6 @@ typedef struct plot_font_style {
(((((c1 & 0x00ff00) * (255 - p)) + \
((c0 & 0x00ff00) * ( p)) ) >> 8) & 0x00ff00))
-/* get a bitmap pixel (image/bitmap.h) into a plot colour */
-#define pixel_to_colour(b) \
- b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)
-
/* Get the red channel from a colour */
#define red_from_colour(c) \
((c ) & 0xff)
@@ -159,6 +213,45 @@ typedef struct plot_font_style {
#define blue_from_colour(c) \
((c >> 16) & 0xff)
+/* Swap red and blue channels in a colour */
+#define colour_rb_swap(c) \
+ (((0x000000ff & c) << 16) | \
+ ((0x0000ff00 & c) ) | \
+ ((0x00ff0000 & c) >> 16))
+
+/** Colour components */
+enum plot_colour_component {
+ PLOT_COLOUR_COMPONENT_RED,
+ PLOT_COLOUR_COMPONENT_GREEN,
+ PLOT_COLOUR_COMPONENT_BLUE,
+ PLOT_COLOUR_COMPONENT_ALPHA,
+};
+
+/**
+ * Engorge a particular colour channel.
+ *
+ * \param[in] col The colour to engorge a component of.
+ * \param[in] dark Whether col is a dark colour.
+ * \param[in] comp Colour component to engorge.
+ */
+static inline colour colour_engorge_component(
+ colour col,
+ bool dark,
+ enum plot_colour_component comp)
+{
+ static const colour msk[PLOT_COLOUR_COMPONENT_ALPHA] = {
+ [PLOT_COLOUR_COMPONENT_RED] = 0x0000ff,
+ [PLOT_COLOUR_COMPONENT_GREEN] = 0x00ff00,
+ [PLOT_COLOUR_COMPONENT_BLUE] = 0xff0000,
+ };
+ colour d = dark ? darken_colour(col) : double_darken_colour(col);
+ colour l = dark ? double_lighten_colour(col) : lighten_colour(col);
+
+ assert(comp < PLOT_COLOUR_COMPONENT_ALPHA);
+
+ return (msk[comp] & l) | (~msk[comp] & d);
+}
+
/* global fill styles */
extern plot_style_t *plot_style_fill_white;
diff --git a/include/netsurf/plotters.h b/include/netsurf/plotters.h
index 87fbd9a74..2fd507aa5 100644
--- a/include/netsurf/plotters.h
+++ b/include/netsurf/plotters.h
@@ -108,7 +108,9 @@ struct plotter_table {
* operations within.
* \return NSERROR_OK on success else error code.
*/
- nserror (*clip)(const struct redraw_context *ctx, const struct rect *clip);
+ nserror (*clip)(
+ const struct redraw_context *ctx,
+ const struct rect *clip);
/**
* Plots an arc
@@ -126,7 +128,14 @@ struct plotter_table {
* \param angle2 The finish angle of the arc.
* \return NSERROR_OK on success else error code.
*/
- nserror (*arc)(const struct redraw_context *ctx, const plot_style_t *pstyle, int x, int y, int radius, int angle1, int angle2);
+ nserror (*arc)(
+ const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ int x,
+ int y,
+ int radius,
+ int angle1,
+ int angle2);
/**
* Plots a circle
@@ -140,7 +149,12 @@ struct plotter_table {
* \param radius The radius of the circle.
* \return NSERROR_OK on success else error code.
*/
- nserror (*disc)(const struct redraw_context *ctx, const plot_style_t *pstyle, int x, int y, int radius);
+ nserror (*disc)(
+ const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ int x,
+ int y,
+ int radius);
/**
* Plots a line
@@ -153,7 +167,10 @@ struct plotter_table {
* \param line A rectangle defining the line to be drawn
* \return NSERROR_OK on success else error code.
*/
- nserror (*line)(const struct redraw_context *ctx, const plot_style_t *pstyle, const struct rect *line);
+ nserror (*line)(
+ const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const struct rect *line);
/**
* Plots a rectangle.
@@ -168,7 +185,10 @@ struct plotter_table {
* \param rect A rectangle defining the line to be drawn
* \return NSERROR_OK on success else error code.
*/
- nserror (*rectangle)(const struct redraw_context *ctx, const plot_style_t *pstyle, const struct rect *rectangle);
+ nserror (*rectangle)(
+ const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const struct rect *rectangle);
/**
* Plot a polygon
@@ -184,7 +204,11 @@ struct plotter_table {
* \param n number of verticies.
* \return NSERROR_OK on success else error code.
*/
- nserror (*polygon)(const struct redraw_context *ctx, const plot_style_t *pstyle, const int *p, unsigned int n);
+ nserror (*polygon)(
+ const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const int *p,
+ unsigned int n);
/**
* Plots a path.
@@ -196,11 +220,15 @@ struct plotter_table {
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
- * \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
- nserror (*path)(const struct redraw_context *ctx, const plot_style_t *pstyle, const float *p, unsigned int n, float width, const float transform[6]);
+ nserror (*path)(
+ const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const float *p,
+ unsigned int n,
+ const float transform[6]);
/**
* Plot a bitmap
@@ -226,7 +254,15 @@ struct plotter_table {
* \param flags the flags controlling the type of plot operation
* \return NSERROR_OK on success else error code.
*/
- nserror (*bitmap)(const struct redraw_context *ctx, struct bitmap *bitmap, int x, int y, int width, int height, colour bg, bitmap_flags_t flags);
+ nserror (*bitmap)(
+ const struct redraw_context *ctx,
+ struct bitmap *bitmap,
+ int x,
+ int y,
+ int width,
+ int height,
+ colour bg,
+ bitmap_flags_t flags);
/**
* Text plotting.
@@ -239,7 +275,13 @@ struct plotter_table {
* \param length length of string, in bytes
* \return NSERROR_OK on success else error code.
*/
- nserror (*text)(const struct redraw_context *ctx, const plot_font_style_t *fstyle, int x, int y, const char *text, size_t length);
+ nserror (*text)(
+ const struct redraw_context *ctx,
+ const plot_font_style_t *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length);
/**
* Start of a group of objects.
@@ -250,7 +292,9 @@ struct plotter_table {
* \param ctx The current redraw context.
* \return NSERROR_OK on success else error code.
*/
- nserror (*group_start)(const struct redraw_context *ctx, const char *name);
+ nserror (*group_start)(
+ const struct redraw_context *ctx,
+ const char *name);
/**
* End of the most recently started group.
@@ -260,7 +304,8 @@ struct plotter_table {
* \param ctx The current redraw context.
* \return NSERROR_OK on success else error code.
*/
- nserror (*group_end)(const struct redraw_context *ctx);
+ nserror (*group_end)(
+ const struct redraw_context *ctx);
/**
* Only used internally by the knockout code. Must be NULL in
@@ -269,7 +314,8 @@ struct plotter_table {
* \param ctx The current redraw context.
* \return NSERROR_OK on success else error code.
*/
- nserror (*flush)(const struct redraw_context *ctx);
+ nserror (*flush)(
+ const struct redraw_context *ctx);
/* flags */
/**
diff --git a/include/netsurf/ssl_certs.h b/include/netsurf/ssl_certs.h
new file mode 100644
index 000000000..05ff13161
--- /dev/null
+++ b/include/netsurf/ssl_certs.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2019 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ *
+ * SSL related types and values
+ */
+
+#ifndef NETSURF_SSL_CERTS_H_
+#define NETSURF_SSL_CERTS_H_
+
+struct nsurl;
+
+/**
+ * ssl certificate error status
+ *
+ * Do not reorder / remove entries because these may be persisted to the disk
+ * cache as simple ints.
+ */
+typedef enum {
+ SSL_CERT_ERR_OK, /**< Nothing wrong with this certificate */
+ SSL_CERT_ERR_UNKNOWN, /**< Unknown error */
+ SSL_CERT_ERR_BAD_ISSUER, /**< Bad issuer */
+ SSL_CERT_ERR_BAD_SIG, /**< Bad signature on this certificate */
+ SSL_CERT_ERR_TOO_YOUNG, /**< This certificate is not yet valid */
+ SSL_CERT_ERR_TOO_OLD, /**< This certificate is no longer valid */
+ SSL_CERT_ERR_SELF_SIGNED, /**< This certificate (or the chain) is self signed */
+ SSL_CERT_ERR_CHAIN_SELF_SIGNED, /**< This certificate chain is self signed */
+ SSL_CERT_ERR_REVOKED, /**< This certificate has been revoked */
+ SSL_CERT_ERR_HOSTNAME_MISMATCH, /**< This certificate host did not match the server */
+ SSL_CERT_ERR_CERT_MISSING, /**< This certificate was missing from the chain, its data is useless */
+} ssl_cert_err;
+
+/** Always the max known ssl certificate error type */
+#define SSL_CERT_ERR_MAX_KNOWN SSL_CERT_ERR_HOSTNAME_MISMATCH
+
+/** maximum number of X509 certificates in chain for TLS connection */
+#define MAX_CERT_DEPTH 10
+
+/**
+ * X509 certificate chain
+ */
+struct cert_chain {
+ /**
+ * the number of certificates in the chain
+ * */
+ size_t depth;
+ struct {
+ /**
+ * Whatever is wrong with this certificate
+ */
+ ssl_cert_err err;
+
+ /**
+ * data in Distinguished Encoding Rules (DER) format
+ */
+ uint8_t *der;
+
+ /**
+ * DER length
+ */
+ size_t der_length;
+ } certs[MAX_CERT_DEPTH];
+};
+
+/**
+ * create new certificate chain
+ *
+ * \param dpth the depth to set in the new chain.
+ * \param chain_out A pointer to recive the new chain.
+ * \return NSERROR_OK on success or NSERROR_NOMEM on memory exhaustion
+ */
+nserror cert_chain_alloc(size_t depth, struct cert_chain **chain_out);
+
+/**
+ * duplicate a certificate chain into an existing chain
+ *
+ * \param src The certificate chain to copy from
+ * \param dst The chain to overwrite with a copy of src
+ * \return NSERROR_OK on success or NSERROR_NOMEM on memory exhaustion
+ *
+ * NOTE: if this returns NSERROR_NOMEM then the destination chain will have
+ * some amount of content and should be cleaned up with cert_chain_free.
+ */
+nserror cert_chain_dup_into(const struct cert_chain *src, struct cert_chain *dst);
+
+/**
+ * duplicate a certificate chain
+ *
+ * \param src The certificate chain to copy from
+ * \param dst_out A pointer to recive the duplicated chain
+ * \return NSERROR_OK on success or NSERROR_NOMEM on memory exhaustion
+ */
+nserror cert_chain_dup(const struct cert_chain *src, struct cert_chain **dst_out);
+
+/**
+ * create a certificate chain from a fetch query string
+ *
+ * \param url The url to convert the query from
+ * \param dst_out A pointer to recive the duplicated chain
+ * \return NSERROR_OK on success or NSERROR_NOMEM on memory exhaustion
+ */
+nserror cert_chain_from_query(struct nsurl *url, struct cert_chain **chain_out);
+
+/**
+ * create a fetch query string from a certificate chain
+ *
+ *
+ * \return NSERROR_OK on success or NSERROR_NOMEM on memory exhaustion
+ */
+nserror cert_chain_to_query(struct cert_chain *chain, struct nsurl **url_out);
+
+/**
+ * free a certificate chain
+ *
+ * \param chain The certificate chain to free
+ * \return NSERROR_OK on success
+ */
+nserror cert_chain_free(struct cert_chain *chain);
+
+/**
+ * total number of data bytes in a chain
+ *
+ * \param chain The chain to size
+ * \return the number of bytes used by the chain
+ */
+size_t cert_chain_size(const struct cert_chain *chain);
+
+#endif /* NETSURF_SSL_CERTS_H_ */
diff --git a/include/netsurf/url_db.h b/include/netsurf/url_db.h
index 217cf8fcd..071675652 100644
--- a/include/netsurf/url_db.h
+++ b/include/netsurf/url_db.h
@@ -58,27 +58,6 @@ nserror urldb_save(const char *filename);
/**
- * Set authentication data for an URL
- *
- * \param url The URL to consider
- * \param realm The authentication realm
- * \param auth The authentication details (in form username:password)
- */
-void urldb_set_auth_details(struct nsurl *url, const char *realm, const char *auth);
-
-
-/**
- * Look up authentication details in database
- *
- * \param url Absolute URL to search for
- * \param realm When non-NULL, it is realm which can be used to determine
- * the protection space when that's not been done before for given URL.
- * \return Pointer to authentication details, or NULL if not found
- */
-const char *urldb_get_auth_details(struct nsurl *url, const char *realm);
-
-
-/**
* Iterate over entries in the database which match the given prefix
*
* \param prefix Prefix to match
diff --git a/include/netsurf/window.h b/include/netsurf/window.h
index 53d9b30f2..16fd95e30 100644
--- a/include/netsurf/window.h
+++ b/include/netsurf/window.h
@@ -26,6 +26,16 @@
#ifndef NETSURF_WINDOW_H
#define NETSURF_WINDOW_H
+#include "netsurf/console.h"
+
+struct browser_window;
+struct form_control;
+struct rect;
+struct hlcache_handle;
+struct nsurl;
+
+enum gui_pointer_shape;
+
typedef enum gui_save_type {
GUI_SAVE_SOURCE,
GUI_SAVE_DRAW,
@@ -56,16 +66,68 @@ typedef enum {
typedef enum {
GW_CREATE_NONE = 0, /**< New window */
GW_CREATE_CLONE = (1 << 0), /**< Clone existing window */
- GW_CREATE_TAB = (1 << 1) /**< Create tab in same window as existing */
+ GW_CREATE_TAB = (1 << 1), /**< Create tab in same window as existing */
+ GW_CREATE_FOREGROUND = (1 << 2), /**< Request this window/tab is foregrounded */
+ GW_CREATE_FOCUS_LOCATION = (1 << 3) , /** Request this window/tab focusses the URL input */
} gui_window_create_flags;
-struct browser_window;
-struct form_control;
-struct rect;
-struct hlcache_handle;
-struct nsurl;
+/**
+ * Window events
+ *
+ * these are events delivered to a gui window which have no additional
+ * parameters and hence do not require separate callbacks.
+ */
+enum gui_window_event {
+ /**
+ * An empty event should never occur
+ */
+ GW_EVENT_NONE = 0,
-enum gui_pointer_shape;
+ /**
+ * Update the extent of the inside of a browser window to that of the
+ * current content.
+ *
+ * @todo this is used to update scroll bars does it need
+ * renaming? some frontends (windows) do not even implement it.
+ */
+ GW_EVENT_UPDATE_EXTENT,
+
+ /**
+ * Remove the caret, if present.
+ */
+ GW_EVENT_REMOVE_CARET,
+
+ /**
+ * start the navigation throbber.
+ */
+ GW_EVENT_START_THROBBER,
+
+ /**
+ * stop the navigation throbber.
+ */
+ GW_EVENT_STOP_THROBBER,
+
+ /**
+ * Starts drag scrolling of a browser window
+ */
+ GW_EVENT_SCROLL_START,
+
+ /**
+ * Called when the gui_window has new content.
+ */
+ GW_EVENT_NEW_CONTENT,
+
+ /**
+ * selection started
+ */
+ GW_EVENT_START_SELECTION,
+
+ /**
+ * Page status has changed and so the padlock should be
+ * updated.
+ */
+ GW_EVENT_PAGE_INFO_CHANGE,
+};
/**
* Graphical user interface window function table.
@@ -173,24 +235,23 @@ struct gui_window_table {
* \param gw The gui window to measure content area of.
* \param width receives width of window
* \param height receives height of window
- * \param scaled whether to return scaled values
* \return NSERROR_OK on success and width and height updated
* else error code.
*/
- nserror (*get_dimensions)(struct gui_window *gw, int *width, int *height, bool scaled);
+ nserror (*get_dimensions)(struct gui_window *gw, int *width, int *height);
/**
- * Update the extent of the inside of a browser window to that of the
- * current content.
+ * Miscellaneous event occurred for a window
*
- * @todo this is used to update scroll bars does it need
- * renaming? some frontends (windows) do not even implement it.
+ * This is used to inform the frontend of window events which
+ * require no additional parameters.
*
- * \param gw The gui window to update the extent of.
+ * \param gw The gui window the event occurred for
+ * \param event Which event has occurred.
+ * \return NSERROR_OK if the event was processed else error code.
*/
- void (*update_extent)(struct gui_window *gw);
-
+ nserror (*event)(struct gui_window *gw, enum gui_window_event event);
/* Optional entries */
@@ -246,27 +307,6 @@ struct gui_window_table {
void (*place_caret)(struct gui_window *g, int x, int y, int height, const struct rect *clip);
/**
- * Remove the caret, if present.
- *
- * \param g window with caret
- */
- void (*remove_caret)(struct gui_window *g);
-
- /**
- * start the navigation throbber.
- *
- * \param g window in which to start throbber.
- */
- void (*start_throbber)(struct gui_window *g);
-
- /**
- * stop the navigation throbber.
- *
- * \param g window with throbber to stop
- */
- void (*stop_throbber)(struct gui_window *g);
-
- /**
* start a drag operation within a window
*
* \param g window to start drag from.
@@ -286,21 +326,6 @@ struct gui_window_table {
*/
nserror (*save_link)(struct gui_window *g, struct nsurl *url, const char *title);
-
- /**
- * Starts drag scrolling of a browser window
- *
- * \param g the window to scroll
- */
- bool (*scroll_start)(struct gui_window *g);
-
- /**
- * Called when the gui_window has new content.
- *
- * \param gw The gui window that has new content
- */
- void (*new_content)(struct gui_window *gw);
-
/**
* create a form select menu
*
@@ -336,11 +361,21 @@ struct gui_window_table {
void (*drag_save_selection)(struct gui_window *gw, const char *selection);
/**
- * selection started
+ * console logging happening.
+ *
+ * See \ref browser_window_console_log
*
- * \param gw The gui window to start selection in.
+ * \param gw The gui window receiving the logging.
+ * \param src The source of the logging message
+ * \param msg The text of the logging message
+ * \param msglen The length of the text of the logging message
+ * \param flags Flags associated with the logging.
*/
- void (*start_selection)(struct gui_window *gw);
+ void (*console_log)(struct gui_window *gw,
+ browser_window_console_source src,
+ const char *msg,
+ size_t msglen,
+ browser_window_console_flags flags);
};
#endif
diff --git a/render/Makefile b/render/Makefile
deleted file mode 100644
index dc2e31c9e..000000000
--- a/render/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# Render sources
-
-S_RENDER := box.c box_construct.c box_normalise.c box_textarea.c \
- font.c form.c imagemap.c layout.c search.c table.c textplain.c \
- html.c html_css.c html_css_fetcher.c html_script.c \
- html_interaction.c html_redraw.c html_redraw_border.c \
- html_forms.c html_object.c
-
-
-S_RENDER := $(addprefix render/,$(S_RENDER))
diff --git a/render/box.c b/render/box.c
deleted file mode 100644
index c97e8982b..000000000
--- a/render/box.c
+++ /dev/null
@@ -1,1242 +0,0 @@
-/*
- * Copyright 2005-2007 James Bursa <bursa@users.sourceforge.net>
- * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
- * Copyright 2005 John M Bell <jmb202@ecs.soton.ac.uk>
- * Copyright 2008 Michael Drake <tlsa@netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- * implementation of box tree manipulation.
- */
-
-#include <assert.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-#include <dom/dom.h>
-
-#include "utils/nsoption.h"
-#include "utils/log.h"
-#include "utils/talloc.h"
-#include "netsurf/misc.h"
-#include "netsurf/content.h"
-#include "netsurf/mouse.h"
-#include "css/utils.h"
-#include "css/dump.h"
-#include "desktop/scrollbar.h"
-#include "desktop/gui_internal.h"
-
-#include "render/box.h"
-#include "render/form_internal.h"
-#include "render/html_internal.h"
-
-#define box_is_float(box) (box->type == BOX_FLOAT_LEFT || \
- box->type == BOX_FLOAT_RIGHT)
-
-/**
- * Destructor for box nodes which own styles
- *
- * \param b The box being destroyed.
- * \return 0 to allow talloc to continue destroying the tree.
- */
-static int box_talloc_destructor(struct box *b)
-{
- struct html_scrollbar_data *data;
-
- if ((b->flags & STYLE_OWNED) && b->style != NULL) {
- css_computed_style_destroy(b->style);
- b->style = NULL;
- }
-
- if (b->styles != NULL) {
- css_select_results_destroy(b->styles);
- b->styles = NULL;
- }
-
- if (b->href != NULL)
- nsurl_unref(b->href);
-
- if (b->id != NULL) {
- lwc_string_unref(b->id);
- }
-
- if (b->node != NULL) {
- dom_node_unref(b->node);
- }
-
- if (b->scroll_x != NULL) {
- data = scrollbar_get_data(b->scroll_x);
- scrollbar_destroy(b->scroll_x);
- free(data);
- }
-
- if (b->scroll_y != NULL) {
- data = scrollbar_get_data(b->scroll_y);
- scrollbar_destroy(b->scroll_y);
- free(data);
- }
-
- return 0;
-}
-
-/**
- * Create a box tree node.
- *
- * \param styles selection results for the box, or NULL
- * \param style computed style for the box (not copied), or 0
- * \param style_owned whether style is owned by this box
- * \param href href for the box (copied), or 0
- * \param target target for the box (not copied), or 0
- * \param title title for the box (not copied), or 0
- * \param id id for the box (not copied), or 0
- * \param context context for allocations
- * \return allocated and initialised box, or 0 on memory exhaustion
- *
- * styles is always owned by the box, if it is set.
- * style is only owned by the box in the case of implied boxes.
- */
-
-struct box * box_create(css_select_results *styles, css_computed_style *style,
- bool style_owned, nsurl *href, const char *target,
- const char *title, lwc_string *id, void *context)
-{
- unsigned int i;
- struct box *box;
-
- box = talloc(context, struct box);
- if (!box) {
- return 0;
- }
-
- talloc_set_destructor(box, box_talloc_destructor);
-
- box->type = BOX_INLINE;
- box->flags = 0;
- box->flags = style_owned ? (box->flags | STYLE_OWNED) : box->flags;
- box->styles = styles;
- box->style = style;
- box->x = box->y = 0;
- box->width = UNKNOWN_WIDTH;
- box->height = 0;
- box->descendant_x0 = box->descendant_y0 = 0;
- box->descendant_x1 = box->descendant_y1 = 0;
- for (i = 0; i != 4; i++)
- box->margin[i] = box->padding[i] = box->border[i].width = 0;
- box->scroll_x = box->scroll_y = NULL;
- box->min_width = 0;
- box->max_width = UNKNOWN_MAX_WIDTH;
- box->byte_offset = 0;
- box->text = NULL;
- box->length = 0;
- box->space = 0;
- box->href = (href == NULL) ? NULL : nsurl_ref(href);
- box->target = target;
- box->title = title;
- box->columns = 1;
- box->rows = 1;
- box->start_column = 0;
- box->next = NULL;
- box->prev = NULL;
- box->children = NULL;
- box->last = NULL;
- box->parent = NULL;
- box->inline_end = NULL;
- box->float_children = NULL;
- box->float_container = NULL;
- box->next_float = NULL;
- box->cached_place_below_level = 0;
- box->list_marker = NULL;
- box->col = NULL;
- box->gadget = NULL;
- box->usemap = NULL;
- box->id = id;
- box->background = NULL;
- box->object = NULL;
- box->object_params = NULL;
- box->iframe = NULL;
- box->node = NULL;
-
- return box;
-}
-
-/**
- * Add a child to a box tree node.
- *
- * \param parent box giving birth
- * \param child box to link as last child of parent
- */
-
-void box_add_child(struct box *parent, struct box *child)
-{
- assert(parent);
- assert(child);
-
- if (parent->children != 0) { /* has children already */
- parent->last->next = child;
- child->prev = parent->last;
- } else { /* this is the first child */
- parent->children = child;
- child->prev = 0;
- }
-
- parent->last = child;
- child->parent = parent;
-}
-
-
-/**
- * Insert a new box as a sibling to a box in a tree.
- *
- * \param box box already in tree
- * \param new_box box to link into tree as next sibling
- */
-
-void box_insert_sibling(struct box *box, struct box *new_box)
-{
- new_box->parent = box->parent;
- new_box->prev = box;
- new_box->next = box->next;
- box->next = new_box;
- if (new_box->next)
- new_box->next->prev = new_box;
- else if (new_box->parent)
- new_box->parent->last = new_box;
-}
-
-
-/**
- * Unlink a box from the box tree and then free it recursively.
- *
- * \param box box to unlink and free recursively.
- */
-
-void box_unlink_and_free(struct box *box)
-{
- struct box *parent = box->parent;
- struct box *next = box->next;
- struct box *prev = box->prev;
-
- if (parent) {
- if (parent->children == box)
- parent->children = next;
- if (parent->last == box)
- parent->last = next ? next : prev;
- }
-
- if (prev)
- prev->next = next;
- if (next)
- next->prev = prev;
-
- box_free(box);
-}
-
-
-/**
- * Free a box tree recursively.
- *
- * \param box box to free recursively
- *
- * The box and all its children is freed.
- */
-
-void box_free(struct box *box)
-{
- struct box *child, *next;
-
- /* free children first */
- for (child = box->children; child; child = next) {
- next = child->next;
- box_free(child);
- }
-
- /* last this box */
- box_free_box(box);
-}
-
-
-/**
- * Free the data in a single box structure.
- *
- * \param box box to free
- */
-
-void box_free_box(struct box *box)
-{
- if (!(box->flags & CLONE)) {
- if (box->gadget)
- form_free_control(box->gadget);
- if (box->scroll_x != NULL)
- scrollbar_destroy(box->scroll_x);
- if (box->scroll_y != NULL)
- scrollbar_destroy(box->scroll_y);
- if (box->styles != NULL)
- css_select_results_destroy(box->styles);
- }
-
- talloc_free(box);
-}
-
-
-/**
- * Find the absolute coordinates of a box.
- *
- * \param box the box to calculate coordinates of
- * \param x updated to x coordinate
- * \param y updated to y coordinate
- */
-
-void box_coords(struct box *box, int *x, int *y)
-{
- *x = box->x;
- *y = box->y;
- while (box->parent) {
- if (box_is_float(box)) {
- do {
- box = box->parent;
- } while (!box->float_children);
- } else
- box = box->parent;
- *x += box->x - scrollbar_get_offset(box->scroll_x);
- *y += box->y - scrollbar_get_offset(box->scroll_y);
- }
-}
-
-
-/**
- * Find the bounds of a box.
- *
- * \param box the box to calculate bounds of
- * \param r receives bounds
- */
-
-void box_bounds(struct box *box, struct rect *r)
-{
- int width, height;
-
- box_coords(box, &r->x0, &r->y0);
-
- width = box->padding[LEFT] + box->width + box->padding[RIGHT];
- height = box->padding[TOP] + box->height + box->padding[BOTTOM];
-
- r->x1 = r->x0 + width;
- r->y1 = r->y0 + height;
-}
-
-
-/**
- * Determine if a point lies within a box.
- *
- * \param[in] len_ctx CSS length conversion context to use.
- * \param[in] box Box to consider
- * \param[in] x Coordinate relative to box
- * \param[in] y Coordinate relative to box
- * \param[out] physically If function returning true, physically is set true
- * iff point is within the box's physical dimensions and
- * false if the point is not within the box's physical
- * dimensions but is in the area defined by the box's
- * descendants. If function returns false, physically
- * is undefined.
- * \return true if the point is within the box or a descendant box
- *
- * This is a helper function for box_at_point().
- */
-
-static bool box_contains_point(
- const nscss_len_ctx *len_ctx,
- const struct box *box,
- int x,
- int y,
- bool *physically)
-{
- css_computed_clip_rect css_rect;
-
- if (box->style != NULL &&
- css_computed_position(box->style) ==
- CSS_POSITION_ABSOLUTE &&
- css_computed_clip(box->style, &css_rect) ==
- CSS_CLIP_RECT) {
- /* We have an absolutly positioned box with a clip rect */
- struct rect r = {
- .x0 = box->border[LEFT].width,
- .y0 = box->border[TOP].width,
- .x1 = box->padding[LEFT] + box->width +
- box->border[RIGHT].width +
- box->padding[RIGHT],
- .y1 = box->padding[TOP] + box->height +
- box->border[BOTTOM].width +
- box->padding[BOTTOM]
- };
- if (x >= r.x0 && x < r.x1 && y >= r.y0 && y < r.y1)
- *physically = true;
- else
- *physically = false;
-
- /* Adjust rect to css clip region */
- if (css_rect.left_auto == false) {
- r.x0 += FIXTOINT(nscss_len2px(len_ctx,
- css_rect.left, css_rect.lunit,
- box->style));
- }
- if (css_rect.top_auto == false) {
- r.y0 += FIXTOINT(nscss_len2px(len_ctx,
- css_rect.top, css_rect.tunit,
- box->style));
- }
- if (css_rect.right_auto == false) {
- r.x1 = box->border[LEFT].width +
- FIXTOINT(nscss_len2px(len_ctx,
- css_rect.right,
- css_rect.runit,
- box->style));
- }
- if (css_rect.bottom_auto == false) {
- r.y1 = box->border[TOP].width +
- FIXTOINT(nscss_len2px(len_ctx,
- css_rect.bottom,
- css_rect.bunit,
- box->style));
- }
-
- /* Test if point is in clipped box */
- if (x >= r.x0 && x < r.x1 && y >= r.y0 && y < r.y1) {
- /* inside clip area */
- return true;
- }
-
- /* Not inside clip area */
- return false;
- }
- if (x >= -box->border[LEFT].width &&
- x < box->padding[LEFT] + box->width +
- box->padding[RIGHT] + box->border[RIGHT].width &&
- y >= -box->border[TOP].width &&
- y < box->padding[TOP] + box->height +
- box->padding[BOTTOM] + box->border[BOTTOM].width) {
- *physically = true;
- return true;
- }
- if (box->list_marker && box->list_marker->x - box->x <= x +
- box->list_marker->border[LEFT].width &&
- x < box->list_marker->x - box->x +
- box->list_marker->padding[LEFT] +
- box->list_marker->width +
- box->list_marker->border[RIGHT].width +
- box->list_marker->padding[RIGHT] &&
- box->list_marker->y - box->y <= y +
- box->list_marker->border[TOP].width &&
- y < box->list_marker->y - box->y +
- box->list_marker->padding[TOP] +
- box->list_marker->height +
- box->list_marker->border[BOTTOM].width +
- box->list_marker->padding[BOTTOM]) {
- *physically = true;
- return true;
- }
- if ((box->style && css_computed_overflow_x(box->style) ==
- CSS_OVERFLOW_VISIBLE) || !box->style) {
- if (box->descendant_x0 <= x &&
- x < box->descendant_x1) {
- *physically = false;
- return true;
- }
- }
- if ((box->style && css_computed_overflow_y(box->style) ==
- CSS_OVERFLOW_VISIBLE) || !box->style) {
- if (box->descendant_y0 <= y &&
- y < box->descendant_y1) {
- *physically = false;
- return true;
- }
- }
- return false;
-}
-
-
-/** Direction to move in a box-tree walk */
-enum box_walk_dir {
- BOX_WALK_CHILDREN,
- BOX_WALK_PARENT,
- BOX_WALK_NEXT_SIBLING,
- BOX_WALK_FLOAT_CHILDREN,
- BOX_WALK_NEXT_FLOAT_SIBLING,
- BOX_WALK_FLOAT_CONTAINER
-};
-
-
-/**
- * Move from box to next box in given direction, adjusting for box coord change
- *
- * \param b box to move from from
- * \param dir direction to move in
- * \param x box's global x-coord, updated to position of next box
- * \param y box's global y-coord, updated to position of next box
- *
- * If no box can be found in given direction, NULL is returned.
- */
-static inline struct box *box_move_xy(struct box *b, enum box_walk_dir dir,
- int *x, int *y)
-{
- struct box *rb = NULL;
-
- switch (dir) {
- case BOX_WALK_CHILDREN:
- b = b->children;
- if (b == NULL)
- break;
- *x += b->x;
- *y += b->y;
- if (!box_is_float(b)) {
- rb = b;
- break;
- }
- /* Fall through */
-
- case BOX_WALK_NEXT_SIBLING:
- do {
- *x -= b->x;
- *y -= b->y;
- b = b->next;
- if (b == NULL)
- break;
- *x += b->x;
- *y += b->y;
- } while (box_is_float(b));
- rb = b;
- break;
-
- case BOX_WALK_PARENT:
- *x -= b->x;
- *y -= b->y;
- rb = b->parent;
- break;
-
- case BOX_WALK_FLOAT_CHILDREN:
- b = b->float_children;
- if (b == NULL)
- break;
- *x += b->x;
- *y += b->y;
- rb = b;
- break;
-
- case BOX_WALK_NEXT_FLOAT_SIBLING:
- *x -= b->x;
- *y -= b->y;
- b = b->next_float;
- if (b == NULL)
- break;
- *x += b->x;
- *y += b->y;
- rb = b;
- break;
-
- case BOX_WALK_FLOAT_CONTAINER:
- *x -= b->x;
- *y -= b->y;
- rb = b->float_container;
- break;
-
- default:
- assert(0 && "Bad box walk type.");
- }
-
- return rb;
-}
-
-
-/**
- * Itterator for walking to next box in interaction order
- *
- * \param b box to find next box from
- * \param x box's global x-coord, updated to position of next box
- * \param y box's global y-coord, updated to position of next box
- * \param skip_children whether to skip box's children
- *
- * This walks to a boxes float children before its children. When walking
- * children, floating boxes are skipped.
- */
-static inline struct box *box_next_xy(struct box *b, int *x, int *y,
- bool skip_children)
-{
- struct box *n;
- int tx, ty;
-
- assert(b != NULL);
-
- if (skip_children) {
- /* Caller is not interested in any kind of children */
- goto skip_children;
- }
-
- tx = *x; ty = *y;
- n = box_move_xy(b, BOX_WALK_FLOAT_CHILDREN, &tx, &ty);
- if (n) {
- /* Next node is float child */
- *x = tx;
- *y = ty;
- return n;
- }
-done_float_children:
-
- tx = *x; ty = *y;
- n = box_move_xy(b, BOX_WALK_CHILDREN, &tx, &ty);
- if (n) {
- /* Next node is child */
- *x = tx;
- *y = ty;
- return n;
- }
-
-skip_children:
- tx = *x; ty = *y;
- n = box_move_xy(b, BOX_WALK_NEXT_FLOAT_SIBLING, &tx, &ty);
- if (n) {
- /* Go to next float sibling */
- *x = tx;
- *y = ty;
- return n;
- }
-
- if (box_is_float(b)) {
- /* Done floats, but the float container may have children,
- * or siblings, or ansestors with siblings. Change to
- * float container and move past handling its float children.
- */
- b = box_move_xy(b, BOX_WALK_FLOAT_CONTAINER, x, y);
- goto done_float_children;
- }
-
- /* Go to next sibling, or nearest ancestor with next sibling. */
- while (b) {
- while (!b->next && b->parent) {
- b = box_move_xy(b, BOX_WALK_PARENT, x, y);
- if (box_is_float(b)) {
- /* Go on to next float, if there is one */
- goto skip_children;
- }
- }
- if (!b->next) {
- /* No more boxes */
- return NULL;
- }
-
- tx = *x; ty = *y;
- n = box_move_xy(b, BOX_WALK_NEXT_SIBLING, &tx, &ty);
- if (n) {
- /* Go to non-float (ancestor) sibling */
- *x = tx;
- *y = ty;
- return n;
-
- } else if (b->parent) {
- b = box_move_xy(b, BOX_WALK_PARENT, x, y);
- if (box_is_float(b)) {
- /* Go on to next float, if there is one */
- goto skip_children;
- }
-
- } else {
- /* No more boxes */
- return NULL;
- }
- }
-
- assert(b != NULL);
- return NULL;
-}
-
-
-
-/**
- * Find the boxes at a point.
- *
- * \param len_ctx CSS length conversion context for document.
- * \param box box to search children of
- * \param x point to find, in global document coordinates
- * \param y point to find, in global document coordinates
- * \param box_x position of box, in global document coordinates, updated
- * to position of returned box, if any
- * \param box_y position of box, in global document coordinates, updated
- * to position of returned box, if any
- * \return box at given point, or 0 if none found
- *
- * To find all the boxes in the hierarchy at a certain point, use code like
- * this:
- * \code
- * struct box *box = top_of_document_to_search;
- * int box_x = 0, box_y = 0;
- *
- * while ((box = box_at_point(len_ctx, box, x, y, &box_x, &box_y))) {
- * // process box
- * }
- * \endcode
- */
-
-struct box *box_at_point(const nscss_len_ctx *len_ctx,
- struct box *box, const int x, const int y,
- int *box_x, int *box_y)
-{
- bool skip_children;
- bool physically;
-
- assert(box);
-
- skip_children = false;
- while ((box = box_next_xy(box, box_x, box_y, skip_children))) {
- if (box_contains_point(len_ctx, box, x - *box_x, y - *box_y,
- &physically)) {
- *box_x -= scrollbar_get_offset(box->scroll_x);
- *box_y -= scrollbar_get_offset(box->scroll_y);
-
- if (physically)
- return box;
-
- skip_children = false;
- } else {
- skip_children = true;
- }
- }
-
- return NULL;
-}
-
-
-/**
- * Check whether box is nearer mouse coordinates than current nearest box
- *
- * \param box box to test
- * \param bx position of box, in global document coordinates
- * \param by position of box, in global document coordinates
- * \param x mouse point, in global document coordinates
- * \param y mouse point, in global document coordinates
- * \param dir direction in which to search (-1 = above-left,
- * +1 = below-right)
- * \param nearest nearest text box found, or NULL if none
- * updated if box is nearer than existing nearest
- * \param tx position of text_box, in global document coordinates
- * updated if box is nearer than existing nearest
- * \param ty position of text_box, in global document coordinates
- * updated if box is nearer than existing nearest
- * \param nr_xd distance to nearest text box found
- * updated if box is nearer than existing nearest
- * \param nr_yd distance to nearest text box found
- * updated if box is nearer than existing nearest
- * \return true if mouse point is inside box
- */
-
-static bool box_nearer_text_box(struct box *box, int bx, int by,
- int x, int y, int dir, struct box **nearest, int *tx, int *ty,
- int *nr_xd, int *nr_yd)
-{
- int w = box->padding[LEFT] + box->width + box->padding[RIGHT];
- int h = box->padding[TOP] + box->height + box->padding[BOTTOM];
- int y1 = by + h;
- int x1 = bx + w;
- int yd = INT_MAX;
- int xd = INT_MAX;
-
- if (x >= bx && x1 > x && y >= by && y1 > y) {
- *nearest = box;
- *tx = bx;
- *ty = by;
- return true;
- }
-
- if (box->parent->list_marker != box) {
- if (dir < 0) {
- /* consider only those children (partly) above-left */
- if (by <= y && bx < x) {
- yd = y <= y1 ? 0 : y - y1;
- xd = x <= x1 ? 0 : x - x1;
- }
- } else {
- /* consider only those children (partly) below-right */
- if (y1 > y && x1 > x) {
- yd = y > by ? 0 : by - y;
- xd = x > bx ? 0 : bx - x;
- }
- }
-
- /* give y displacement precedence over x */
- if (yd < *nr_yd || (yd == *nr_yd && xd <= *nr_xd)) {
- *nr_yd = yd;
- *nr_xd = xd;
- *nearest = box;
- *tx = bx;
- *ty = by;
- }
- }
- return false;
-}
-
-
-/**
- * Pick the text box child of 'box' that is closest to and above-left
- * (dir -ve) or below-right (dir +ve) of the point 'x,y'
- *
- * \param box parent box
- * \param bx position of box, in global document coordinates
- * \param by position of box, in global document coordinates
- * \param fx position of float parent, in global document coordinates
- * \param fy position of float parent, in global document coordinates
- * \param x mouse point, in global document coordinates
- * \param y mouse point, in global document coordinates
- * \param dir direction in which to search (-1 = above-left,
- * +1 = below-right)
- * \param nearest nearest text box found, or NULL if none
- * updated if a descendant of box is nearer than old nearest
- * \param tx position of nearest, in global document coordinates
- * updated if a descendant of box is nearer than old nearest
- * \param ty position of nearest, in global document coordinates
- * updated if a descendant of box is nearer than old nearest
- * \param nr_xd distance to nearest text box found
- * updated if a descendant of box is nearer than old nearest
- * \param nr_yd distance to nearest text box found
- * updated if a descendant of box is nearer than old nearest
- * \return true if mouse point is inside text_box
- */
-
-static bool box_nearest_text_box(struct box *box, int bx, int by,
- int fx, int fy, int x, int y, int dir, struct box **nearest,
- int *tx, int *ty, int *nr_xd, int *nr_yd)
-{
- struct box *child = box->children;
- int c_bx, c_by;
- int c_fx, c_fy;
- bool in_box = false;
-
- if (*nearest == NULL) {
- *nr_xd = INT_MAX / 2; /* displacement of 'nearest so far' */
- *nr_yd = INT_MAX / 2;
- }
- if (box->type == BOX_INLINE_CONTAINER) {
- int bw = box->padding[LEFT] + box->width + box->padding[RIGHT];
- int bh = box->padding[TOP] + box->height + box->padding[BOTTOM];
- int b_y1 = by + bh;
- int b_x1 = bx + bw;
- if (x >= bx && b_x1 > x && y >= by && b_y1 > y) {
- in_box = true;
- }
- }
-
- while (child) {
- if (child->type == BOX_FLOAT_LEFT ||
- child->type == BOX_FLOAT_RIGHT) {
- c_bx = fx + child->x -
- scrollbar_get_offset(child->scroll_x);
- c_by = fy + child->y -
- scrollbar_get_offset(child->scroll_y);
- } else {
- c_bx = bx + child->x -
- scrollbar_get_offset(child->scroll_x);
- c_by = by + child->y -
- scrollbar_get_offset(child->scroll_y);
- }
- if (child->float_children) {
- c_fx = c_bx;
- c_fy = c_by;
- } else {
- c_fx = fx;
- c_fy = fy;
- }
- if (in_box && child->text && !child->object) {
- if (box_nearer_text_box(child,
- c_bx, c_by, x, y, dir, nearest,
- tx, ty, nr_xd, nr_yd))
- return true;
- } else {
- if (child->list_marker) {
- if (box_nearer_text_box(
- child->list_marker,
- c_bx + child->list_marker->x,
- c_by + child->list_marker->y,
- x, y, dir, nearest,
- tx, ty, nr_xd, nr_yd))
- return true;
- }
- if (box_nearest_text_box(child, c_bx, c_by,
- c_fx, c_fy, x, y, dir, nearest, tx, ty,
- nr_xd, nr_yd))
- return true;
- }
- child = child->next;
- }
-
- return false;
-}
-
-
-/**
- * Peform pick text on browser window contents to locate the box under
- * the mouse pointer, or nearest in the given direction if the pointer is
- * not over a text box.
- *
- * \param html an HTML content
- * \param x coordinate of mouse
- * \param y coordinate of mouse
- * \param dir direction to search (-1 = above-left, +1 = below-right)
- * \param dx receives x ordinate of mouse relative to text box
- * \param dy receives y ordinate of mouse relative to text box
- */
-
-struct box *box_pick_text_box(struct html_content *html,
- int x, int y, int dir, int *dx, int *dy)
-{
- struct box *text_box = NULL;
- struct box *box;
- int nr_xd, nr_yd;
- int bx, by;
- int fx, fy;
- int tx, ty;
-
- if (html == NULL)
- return NULL;
-
- box = html->layout;
- bx = box->margin[LEFT];
- by = box->margin[TOP];
- fx = bx;
- fy = by;
-
- if (!box_nearest_text_box(box, bx, by, fx, fy, x, y,
- dir, &text_box, &tx, &ty, &nr_xd, &nr_yd)) {
- if (text_box && text_box->text && !text_box->object) {
- int w = (text_box->padding[LEFT] +
- text_box->width +
- text_box->padding[RIGHT]);
- int h = (text_box->padding[TOP] +
- text_box->height +
- text_box->padding[BOTTOM]);
- int x1, y1;
-
- y1 = ty + h;
- x1 = tx + w;
-
- /* ensure point lies within the text box */
- if (x < tx) x = tx;
- if (y < ty) y = ty;
- if (y > y1) y = y1;
- if (x > x1) x = x1;
- }
- }
-
- /* return coordinates relative to box */
- *dx = x - tx;
- *dy = y - ty;
-
- return text_box;
-}
-
-
-/**
- * Find a box based upon its id attribute.
- *
- * \param box box tree to search
- * \param id id to look for
- * \return the box or 0 if not found
- */
-
-struct box *box_find_by_id(struct box *box, lwc_string *id)
-{
- struct box *a, *b;
- bool m;
-
- if (box->id != NULL &&
- lwc_string_isequal(id, box->id, &m) == lwc_error_ok &&
- m == true)
- return box;
-
- for (a = box->children; a; a = a->next) {
- if ((b = box_find_by_id(a, id)) != NULL)
- return b;
- }
-
- return NULL;
-}
-
-
-/**
- * Determine if a box is visible when the tree is rendered.
- *
- * \param box box to check
- * \return true iff the box is rendered
- */
-
-bool box_visible(struct box *box)
-{
- /* visibility: hidden */
- if (box->style && css_computed_visibility(box->style) ==
- CSS_VISIBILITY_HIDDEN)
- return false;
-
- return true;
-}
-
-
-/**
- * Print a box tree to a file.
- */
-
-void box_dump(FILE *stream, struct box *box, unsigned int depth, bool style)
-{
- unsigned int i;
- struct box *c, *prev;
-
- for (i = 0; i != depth; i++)
- fprintf(stream, " ");
-
- fprintf(stream, "%p ", box);
- fprintf(stream, "x%i y%i w%i h%i ", box->x, box->y,
- box->width, box->height);
- if (box->max_width != UNKNOWN_MAX_WIDTH)
- fprintf(stream, "min%i max%i ", box->min_width, box->max_width);
- fprintf(stream, "(%i %i %i %i) ",
- box->descendant_x0, box->descendant_y0,
- box->descendant_x1, box->descendant_y1);
-
- fprintf(stream, "m(%i %i %i %i) ",
- box->margin[TOP], box->margin[LEFT],
- box->margin[BOTTOM], box->margin[RIGHT]);
-
- switch (box->type) {
- case BOX_BLOCK: fprintf(stream, "BLOCK "); break;
- case BOX_INLINE_CONTAINER: fprintf(stream, "INLINE_CONTAINER "); break;
- case BOX_INLINE: fprintf(stream, "INLINE "); break;
- case BOX_INLINE_END: fprintf(stream, "INLINE_END "); break;
- case BOX_INLINE_BLOCK: fprintf(stream, "INLINE_BLOCK "); break;
- case BOX_TABLE: fprintf(stream, "TABLE [columns %i] ",
- box->columns); break;
- case BOX_TABLE_ROW: fprintf(stream, "TABLE_ROW "); break;
- case BOX_TABLE_CELL: fprintf(stream, "TABLE_CELL [columns %i, "
- "start %i, rows %i] ", box->columns,
- box->start_column, box->rows); break;
- case BOX_TABLE_ROW_GROUP: fprintf(stream, "TABLE_ROW_GROUP "); break;
- case BOX_FLOAT_LEFT: fprintf(stream, "FLOAT_LEFT "); break;
- case BOX_FLOAT_RIGHT: fprintf(stream, "FLOAT_RIGHT "); break;
- case BOX_BR: fprintf(stream, "BR "); break;
- case BOX_TEXT: fprintf(stream, "TEXT "); break;
- default: fprintf(stream, "Unknown box type ");
- }
-
- if (box->text)
- fprintf(stream, "%li '%.*s' ", (unsigned long) box->byte_offset,
- (int) box->length, box->text);
- if (box->space)
- fprintf(stream, "space ");
- if (box->object) {
- fprintf(stream, "(object '%s') ",
- nsurl_access(hlcache_handle_get_url(box->object)));
- }
- if (box->iframe) {
- fprintf(stream, "(iframe) ");
- }
- if (box->gadget)
- fprintf(stream, "(gadget) ");
- if (style && box->style)
- nscss_dump_computed_style(stream, box->style);
- if (box->href)
- fprintf(stream, " -> '%s'", nsurl_access(box->href));
- if (box->target)
- fprintf(stream, " |%s|", box->target);
- if (box->title)
- fprintf(stream, " [%s]", box->title);
- if (box->id)
- fprintf(stream, " ID:%s", lwc_string_data(box->id));
- if (box->type == BOX_INLINE || box->type == BOX_INLINE_END)
- fprintf(stream, " inline_end %p", box->inline_end);
- if (box->float_children)
- fprintf(stream, " float_children %p", box->float_children);
- if (box->next_float)
- fprintf(stream, " next_float %p", box->next_float);
- if (box->float_container)
- fprintf(stream, " float_container %p", box->float_container);
- if (box->col) {
- fprintf(stream, " (columns");
- for (i = 0; i != box->columns; i++)
- fprintf(stream, " (%s %s %i %i %i)",
- ((const char *[]) {"UNKNOWN", "FIXED",
- "AUTO", "PERCENT", "RELATIVE"})
- [box->col[i].type],
- ((const char *[]) {"normal",
- "positioned"})
- [box->col[i].positioned],
- box->col[i].width,
- box->col[i].min, box->col[i].max);
- fprintf(stream, ")");
- }
- if (box->node != NULL) {
- dom_string *name;
- if (dom_node_get_node_name(box->node, &name) == DOM_NO_ERR) {
- fprintf(stream, " <%s>", dom_string_data(name));
- dom_string_unref(name);
- }
- }
- fprintf(stream, "\n");
-
- if (box->list_marker) {
- for (i = 0; i != depth; i++)
- fprintf(stream, " ");
- fprintf(stream, "list_marker:\n");
- box_dump(stream, box->list_marker, depth + 1, style);
- }
-
- for (c = box->children; c && c->next; c = c->next)
- ;
- if (box->last != c)
- fprintf(stream, "warning: box->last %p (should be %p) "
- "(box %p)\n", box->last, c, box);
- for (prev = 0, c = box->children; c; prev = c, c = c->next) {
- if (c->parent != box)
- fprintf(stream, "warning: box->parent %p (should be "
- "%p) (box on next line)\n",
- c->parent, box);
- if (c->prev != prev)
- fprintf(stream, "warning: box->prev %p (should be "
- "%p) (box on next line)\n",
- c->prev, prev);
- box_dump(stream, c, depth + 1, style);
- }
-}
-
-/**
- * Applies the given scroll setup to a box. This includes scroll
- * creation/deletion as well as scroll dimension updates.
- *
- * \param c content in which the box is located
- * \param box the box to handle the scrolls for
- * \param bottom whether the horizontal scrollbar should be present
- * \param right whether the vertical scrollbar should be present
- * \return true on success false otherwise
- */
-bool box_handle_scrollbars(struct content *c, struct box *box,
- bool bottom, bool right)
-{
- struct html_scrollbar_data *data;
- int visible_width, visible_height;
- int full_width, full_height;
-
- if (!bottom && box->scroll_x != NULL) {
- data = scrollbar_get_data(box->scroll_x);
- scrollbar_destroy(box->scroll_x);
- free(data);
- box->scroll_x = NULL;
- }
-
- if (!right && box->scroll_y != NULL) {
- data = scrollbar_get_data(box->scroll_y);
- scrollbar_destroy(box->scroll_y);
- free(data);
- box->scroll_y = NULL;
- }
-
- if (!bottom && !right)
- return true;
-
- visible_width = box->width + box->padding[RIGHT] + box->padding[LEFT];
- visible_height = box->height + box->padding[TOP] + box->padding[BOTTOM];
-
- full_width = ((box->descendant_x1 - box->border[RIGHT].width) >
- visible_width) ?
- box->descendant_x1 + box->padding[RIGHT] :
- visible_width;
- full_height = ((box->descendant_y1 - box->border[BOTTOM].width) >
- visible_height) ?
- box->descendant_y1 + box->padding[BOTTOM] :
- visible_height;
-
- if (right) {
- if (box->scroll_y == NULL) {
- data = malloc(sizeof(struct html_scrollbar_data));
- if (data == NULL) {
- NSLOG(netsurf, INFO, "malloc failed");
- guit->misc->warning("NoMemory", 0);
- return false;
- }
- data->c = c;
- data->box = box;
- if (scrollbar_create(false, visible_height,
- full_height, visible_height,
- data, html_overflow_scroll_callback,
- &(box->scroll_y)) != NSERROR_OK) {
- return false;
- }
- } else {
- scrollbar_set_extents(box->scroll_y, visible_height,
- visible_height, full_height);
- }
- }
- if (bottom) {
- if (box->scroll_x == NULL) {
- data = malloc(sizeof(struct html_scrollbar_data));
- if (data == NULL) {
- NSLOG(netsurf, INFO, "malloc failed");
- guit->misc->warning("NoMemory", 0);
- return false;
- }
- data->c = c;
- data->box = box;
- if (scrollbar_create(true,
- visible_width -
- (right ? SCROLLBAR_WIDTH : 0),
- full_width, visible_width,
- data, html_overflow_scroll_callback,
- &box->scroll_x) != NSERROR_OK) {
- return false;
- }
- } else {
- scrollbar_set_extents(box->scroll_x,
- visible_width -
- (right ? SCROLLBAR_WIDTH : 0),
- visible_width, full_width);
- }
- }
-
- if (right && bottom)
- scrollbar_make_pair(box->scroll_x, box->scroll_y);
-
- return true;
-}
-
-/**
- * Determine if a box has a vertical scrollbar.
- *
- * \param box scrolling box
- * \return the box has a vertical scrollbar
- */
-
-bool box_vscrollbar_present(const struct box * const box)
-{
- return box->padding[TOP] + box->height + box->padding[BOTTOM] +
- box->border[BOTTOM].width < box->descendant_y1;
-}
-
-
-/**
- * Determine if a box has a horizontal scrollbar.
- *
- * \param box scrolling box
- * \return the box has a horizontal scrollbar
- */
-
-bool box_hscrollbar_present(const struct box * const box)
-{
- return box->padding[LEFT] + box->width + box->padding[RIGHT] +
- box->border[RIGHT].width < box->descendant_x1;
-}
-
diff --git a/render/box.h b/render/box.h
deleted file mode 100644
index 1af0a8b73..000000000
--- a/render/box.h
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
- * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/** \file
- * Box tree construction and manipulation (interface).
- *
- * This stage of rendering converts a tree of dom_nodes (produced by libdom)
- * to a tree of struct box. The box tree represents the structure of the
- * document as given by the CSS display and float properties.
- *
- * For example, consider the following HTML:
- * \code
- * <h1>Example Heading</h1>
- * <p>Example paragraph <em>with emphasised text</em> etc.</p> \endcode
- *
- * This would produce approximately the following box tree with default CSS
- * rules:
- * \code
- * BOX_BLOCK (corresponds to h1)
- * BOX_INLINE_CONTAINER
- * BOX_INLINE "Example Heading"
- * BOX_BLOCK (p)
- * BOX_INLINE_CONTAINER
- * BOX_INLINE "Example paragraph "
- * BOX_INLINE "with emphasised text" (em)
- * BOX_INLINE "etc." \endcode
- *
- * Note that the em has been collapsed into the INLINE_CONTAINER.
- *
- * If these CSS rules were applied:
- * \code
- * h1 { display: table-cell }
- * p { display: table-cell }
- * em { float: left; width: 5em } \endcode
- *
- * then the box tree would instead look like this:
- * \code
- * BOX_TABLE
- * BOX_TABLE_ROW_GROUP
- * BOX_TABLE_ROW
- * BOX_TABLE_CELL (h1)
- * BOX_INLINE_CONTAINER
- * BOX_INLINE "Example Heading"
- * BOX_TABLE_CELL (p)
- * BOX_INLINE_CONTAINER
- * BOX_INLINE "Example paragraph "
- * BOX_FLOAT_LEFT (em)
- * BOX_BLOCK
- * BOX_INLINE_CONTAINER
- * BOX_INLINE "with emphasised text"
- * BOX_INLINE "etc." \endcode
- *
- * Here implied boxes have been added and a float is present.
- *
- * A box tree is "normalized" if the following is satisfied:
- * \code
- * parent permitted child nodes
- * BLOCK, INLINE_BLOCK BLOCK, INLINE_CONTAINER, TABLE
- * INLINE_CONTAINER INLINE, INLINE_BLOCK, FLOAT_LEFT, FLOAT_RIGHT, BR, TEXT,
- * INLINE_END
- * INLINE none
- * TABLE at least 1 TABLE_ROW_GROUP
- * TABLE_ROW_GROUP at least 1 TABLE_ROW
- * TABLE_ROW at least 1 TABLE_CELL
- * TABLE_CELL BLOCK, INLINE_CONTAINER, TABLE (same as BLOCK)
- * FLOAT_(LEFT|RIGHT) exactly 1 BLOCK or TABLE
- * \endcode
- */
-
-#ifndef _NETSURF_RENDER_BOX_H_
-#define _NETSURF_RENDER_BOX_H_
-
-#include <limits.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <libcss/libcss.h>
-
-#include "content/handlers/css/utils.h"
-
-struct content;
-struct box;
-struct browser_window;
-struct column;
-struct object_params;
-struct object_param;
-struct html_content;
-struct nsurl;
-struct dom_node;
-struct dom_string;
-struct rect;
-
-#define UNKNOWN_WIDTH INT_MAX
-#define UNKNOWN_MAX_WIDTH INT_MAX
-
-typedef void (*box_construct_complete_cb)(struct html_content *c, bool success);
-
-/** Type of a struct box. */
-typedef enum {
- BOX_BLOCK, BOX_INLINE_CONTAINER, BOX_INLINE,
- BOX_TABLE, BOX_TABLE_ROW, BOX_TABLE_CELL,
- BOX_TABLE_ROW_GROUP,
- BOX_FLOAT_LEFT, BOX_FLOAT_RIGHT,
- BOX_INLINE_BLOCK, BOX_BR, BOX_TEXT,
- BOX_INLINE_END, BOX_NONE
-} box_type;
-
-
-/** Flags for a struct box. */
-typedef enum {
- NEW_LINE = 1 << 0, /* first inline on a new line */
- STYLE_OWNED = 1 << 1, /* style is owned by this box */
- PRINTED = 1 << 2, /* box has already been printed */
- PRE_STRIP = 1 << 3, /* PRE tag needing leading newline stripped */
- CLONE = 1 << 4, /* continuation of previous box from wrapping */
- MEASURED = 1 << 5, /* text box width has been measured */
- HAS_HEIGHT = 1 << 6, /* box has height (perhaps due to children) */
- MAKE_HEIGHT = 1 << 7, /* box causes its own height */
- NEED_MIN = 1 << 8, /* minimum width is required for layout */
- REPLACE_DIM = 1 << 9, /* replaced element has given dimensions */
- IFRAME = 1 << 10, /* box contains an iframe */
- CONVERT_CHILDREN = 1 << 11, /* wanted children converting */
- IS_REPLACED = 1 << 12 /* box is a replaced element */
-} box_flags;
-
-/* Sides of a box */
-enum box_side { TOP, RIGHT, BOTTOM, LEFT };
-
-/**
- * Container for box border details
- */
-struct box_border {
- enum css_border_style_e style; /**< border-style */
- css_color c; /**< border-color value */
- int width; /**< border-width (pixels) */
-};
-
-/** Node in box tree. All dimensions are in pixels. */
-struct box {
- /** Type of box. */
- box_type type;
-
- /** Box flags */
- box_flags flags;
-
- /** Computed styles for elements and their pseudo elements. NULL on
- * non-element boxes. */
- css_select_results *styles;
-
- /** Style for this box. 0 for INLINE_CONTAINER and FLOAT_*. Pointer into
- * a box's 'styles' select results, except for implied boxes, where it
- * is a pointer to an owned computed style. */
- css_computed_style *style;
-
- /** Coordinate of left padding edge relative to parent box, or relative
- * to ancestor that contains this box in float_children for FLOAT_. */
- int x;
- /** Coordinate of top padding edge, relative as for x. */
- int y;
-
- int width; /**< Width of content box (excluding padding etc.). */
- int height; /**< Height of content box (excluding padding etc.). */
-
- /* These four variables determine the maximum extent of a box's
- * descendants. They are relative to the x,y coordinates of the box.
- *
- * Their use depends on the overflow CSS property:
- *
- * Overflow: Usage:
- * visible The content of the box is displayed within these
- * dimensions.
- * hidden These are ignored. Content is plotted within the box
- * dimensions.
- * scroll These are used to determine the extent of the
- * scrollable area.
- * auto As "scroll".
- */
- int descendant_x0; /**< left edge of descendants */
- int descendant_y0; /**< top edge of descendants */
- int descendant_x1; /**< right edge of descendants */
- int descendant_y1; /**< bottom edge of descendants */
-
- int margin[4]; /**< Margin: TOP, RIGHT, BOTTOM, LEFT. */
- int padding[4]; /**< Padding: TOP, RIGHT, BOTTOM, LEFT. */
- struct box_border border[4]; /**< Border: TOP, RIGHT, BOTTOM, LEFT. */
-
- struct scrollbar *scroll_x; /**< Horizontal scroll. */
- struct scrollbar *scroll_y; /**< Vertical scroll. */
-
- /** Width of box taking all line breaks (including margins etc). Must
- * be non-negative. */
- int min_width;
- /** Width that would be taken with no line breaks. Must be
- * non-negative. */
- int max_width;
-
- /**< Byte offset within a textual representation of this content. */
- size_t byte_offset;
-
- char *text; /**< Text, or 0 if none. Unterminated. */
- size_t length; /**< Length of text. */
-
- /** Width of space after current text (depends on font and size). */
- int space;
-
- struct nsurl *href; /**< Link, or 0. */
- const char *target; /**< Link target, or 0. */
- const char *title; /**< Title, or 0. */
-
- unsigned int columns; /**< Number of columns for TABLE / TABLE_CELL. */
- unsigned int rows; /**< Number of rows for TABLE only. */
- unsigned int start_column; /**< Start column for TABLE_CELL only. */
-
- struct box *next; /**< Next sibling box, or 0. */
- struct box *prev; /**< Previous sibling box, or 0. */
- struct box *children; /**< First child box, or 0. */
- struct box *last; /**< Last child box, or 0. */
- struct box *parent; /**< Parent box, or 0. */
- /** INLINE_END box corresponding to this INLINE box, or INLINE box
- * corresponding to this INLINE_END box. */
- struct box *inline_end;
-
- /** First float child box, or 0. Float boxes are in the tree twice, in
- * this list for the block box which defines the area for floats, and
- * also in the standard tree given by children, next, prev, etc. */
- struct box *float_children;
- /** Next sibling float box. */
- struct box *next_float;
- /** If box is a float, points to box's containing block */
- struct box *float_container;
- /** Level below which subsequent floats must be cleared.
- * This is used only for boxes with float_children */
- int clear_level;
-
- /* Level below which floats have been placed. */
- int cached_place_below_level;
-
- /** List marker box if this is a list-item, or 0. */
- struct box *list_marker;
-
- struct column *col; /**< Array of table column data for TABLE only. */
-
- /** Form control data, or 0 if not a form control. */
- struct form_control* gadget;
-
- char *usemap; /** (Image)map to use with this object, or 0 if none */
- lwc_string *id; /**< value of id attribute (or name for anchors) */
-
- /** Background image for this box, or 0 if none */
- struct hlcache_handle *background;
-
- /** Object in this box (usually an image), or 0 if none. */
- struct hlcache_handle* object;
- /** Parameters for the object, or 0. */
- struct object_params *object_params;
-
- /** Iframe's browser_window, or NULL if none */
- struct browser_window *iframe;
-
- struct dom_node *node; /**< DOM node that generated this box or NULL */
-};
-
-/** Table column data. */
-struct column {
- /** Type of column. */
- enum { COLUMN_WIDTH_UNKNOWN, COLUMN_WIDTH_FIXED,
- COLUMN_WIDTH_AUTO, COLUMN_WIDTH_PERCENT,
- COLUMN_WIDTH_RELATIVE } type;
- /** Preferred width of column. Pixels for FIXED, percentage for PERCENT,
- * relative units for RELATIVE, unused for AUTO. */
- int width;
- /** Minimum width of content. */
- int min;
- /** Maximum width of content. */
- int max;
- /** Whether all of column's cells are css positioned. */
- bool positioned;
-};
-
-/** Parameters for object element and similar elements. */
-struct object_params {
- struct nsurl *data;
- char *type;
- char *codetype;
- struct nsurl *codebase;
- struct nsurl *classid;
- struct object_param *params;
-};
-
-/** Linked list of object element parameters. */
-struct object_param {
- char *name;
- char *value;
- char *type;
- char *valuetype;
- struct object_param *next;
-};
-
-/** Frame target names (constant pointers to save duplicating the strings many
- * times). We convert _blank to _top for user-friendliness. */
-extern const char *TARGET_SELF;
-extern const char *TARGET_PARENT;
-extern const char *TARGET_TOP;
-extern const char *TARGET_BLANK;
-
-
-
-struct box * box_create(css_select_results *styles, css_computed_style *style,
- bool style_owned, struct nsurl *href, const char *target,
- const char *title, lwc_string *id, void *context);
-void box_add_child(struct box *parent, struct box *child);
-void box_insert_sibling(struct box *box, struct box *new_box);
-void box_unlink_and_free(struct box *box);
-void box_free(struct box *box);
-void box_free_box(struct box *box);
-void box_bounds(struct box *box, struct rect *r);
-void box_coords(struct box *box, int *x, int *y);
-struct box *box_at_point(
- const nscss_len_ctx *len_ctx,
- struct box *box, const int x, const int y,
- int *box_x, int *box_y);
-struct box *box_pick_text_box(struct html_content *html,
- int x, int y, int dir, int *dx, int *dy);
-struct box *box_find_by_id(struct box *box, lwc_string *id);
-bool box_visible(struct box *box);
-void box_dump(FILE *stream, struct box *box, unsigned int depth, bool style);
-
-/**
- * Extract a URL from a relative link, handling junk like whitespace and
- * attempting to read a real URL from "javascript:" links.
- *
- * \param content html content
- * \param dsrel relative URL text taken from page
- * \param base base for relative URLs
- * \param result updated to target URL on heap, unchanged if extract failed
- * \return true on success, false on memory exhaustion
- */
-bool box_extract_link(const struct html_content *content, const struct dom_string *dsrel, struct nsurl *base, struct nsurl **result);
-
-bool box_handle_scrollbars(struct content *c, struct box *box,
- bool bottom, bool right);
-bool box_vscrollbar_present(const struct box *box);
-bool box_hscrollbar_present(const struct box *box);
-
-nserror dom_to_box(struct dom_node *n, struct html_content *c,
- box_construct_complete_cb cb);
-
-bool box_normalise_block(
- struct box *block,
- const struct box *root,
- struct html_content *c);
-
-#endif
diff --git a/render/box_construct.c b/render/box_construct.c
deleted file mode 100644
index 1aa99e2d1..000000000
--- a/render/box_construct.c
+++ /dev/null
@@ -1,3137 +0,0 @@
-/*
- * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
- * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
- * Copyright 2005 John M Bell <jmb202@ecs.soton.ac.uk>
- * Copyright 2006 Richard Wilson <info@tinct.net>
- * Copyright 2008 Michael Drake <tlsa@netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- * Implementation of conversion from DOM tree to box tree.
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-
-#include "utils/config.h"
-#include "utils/nsoption.h"
-#include "utils/corestrings.h"
-#include "utils/log.h"
-#include "utils/messages.h"
-#include "utils/talloc.h"
-#include "utils/string.h"
-#include "utils/ascii.h"
-#include "netsurf/css.h"
-#include "netsurf/misc.h"
-#include "netsurf/plot_style.h"
-#include "content/content_protected.h"
-#include "css/hints.h"
-#include "css/select.h"
-#include "css/utils.h"
-#include "desktop/gui_internal.h"
-
-#include "render/box.h"
-#include "render/box_textarea.h"
-#include "render/form_internal.h"
-#include "render/html_internal.h"
-
-/**
- * Context for box tree construction
- */
-struct box_construct_ctx {
- html_content *content; /**< Content we're constructing for */
-
- dom_node *n; /**< Current node to process */
-
- struct box *root_box; /**< Root box in the tree */
-
- box_construct_complete_cb cb; /**< Callback to invoke on completion */
-
- int *bctx; /**< talloc context */
-};
-
-/**
- * Transient properties for construction of current node
- */
-struct box_construct_props {
- /** Style from which to inherit, or NULL if none */
- const css_computed_style *parent_style;
- /** Current link target, or NULL if none */
- nsurl *href;
- /** Current frame target, or NULL if none */
- const char *target;
- /** Current title attribute, or NULL if none */
- const char *title;
- /** Identity of the current block-level container */
- struct box *containing_block;
- /** Current container for inlines, or NULL if none
- * \note If non-NULL, will be the last child of containing_block */
- struct box *inline_container;
- /** Whether the current node is the root of the DOM tree */
- bool node_is_root;
-};
-
-static const content_type image_types = CONTENT_IMAGE;
-
-/* the strings are not important, since we just compare the pointers */
-const char *TARGET_SELF = "_self";
-const char *TARGET_PARENT = "_parent";
-const char *TARGET_TOP = "_top";
-const char *TARGET_BLANK = "_blank";
-
-static void convert_xml_to_box(struct box_construct_ctx *ctx);
-static bool box_construct_element(struct box_construct_ctx *ctx,
- bool *convert_children);
-static void box_construct_element_after(dom_node *n, html_content *content);
-static bool box_construct_text(struct box_construct_ctx *ctx);
-static css_select_results * box_get_style(html_content *c,
- const css_computed_style *parent_style,
- const css_computed_style *root_style, dom_node *n);
-static void box_text_transform(char *s, unsigned int len,
- enum css_text_transform_e tt);
-#define BOX_SPECIAL_PARAMS dom_node *n, html_content *content, \
- struct box *box, bool *convert_children
-static bool box_a(BOX_SPECIAL_PARAMS);
-static bool box_body(BOX_SPECIAL_PARAMS);
-static bool box_br(BOX_SPECIAL_PARAMS);
-static bool box_image(BOX_SPECIAL_PARAMS);
-static bool box_textarea(BOX_SPECIAL_PARAMS);
-static bool box_select(BOX_SPECIAL_PARAMS);
-static bool box_input(BOX_SPECIAL_PARAMS);
-static bool box_button(BOX_SPECIAL_PARAMS);
-static bool box_frameset(BOX_SPECIAL_PARAMS);
-static bool box_create_frameset(struct content_html_frames *f, dom_node *n,
- html_content *content);
-static bool box_select_add_option(struct form_control *control, dom_node *n);
-static bool box_noscript(BOX_SPECIAL_PARAMS);
-static bool box_object(BOX_SPECIAL_PARAMS);
-static bool box_embed(BOX_SPECIAL_PARAMS);
-static bool box_pre(BOX_SPECIAL_PARAMS);
-static bool box_iframe(BOX_SPECIAL_PARAMS);
-static bool box_get_attribute(dom_node *n, const char *attribute,
- void *context, char **value);
-
-/* element_table must be sorted by name */
-struct element_entry {
- char name[10]; /* element type */
- bool (*convert)(BOX_SPECIAL_PARAMS);
-};
-static const struct element_entry element_table[] = {
- {"a", box_a},
- {"body", box_body},
- {"br", box_br},
- {"button", box_button},
- {"embed", box_embed},
- {"frameset", box_frameset},
- {"iframe", box_iframe},
- {"image", box_image},
- {"img", box_image},
- {"input", box_input},
- {"noscript", box_noscript},
- {"object", box_object},
- {"pre", box_pre},
- {"select", box_select},
- {"textarea", box_textarea}
-};
-#define ELEMENT_TABLE_COUNT (sizeof(element_table) / sizeof(element_table[0]))
-
-/**
- * Construct a box tree from an xml tree and stylesheets.
- *
- * \param n xml tree
- * \param c content of type CONTENT_HTML to construct box tree in
- * \param cb callback to report conversion completion
- * \return netsurf error code indicating status of call
- */
-
-nserror dom_to_box(dom_node *n, html_content *c, box_construct_complete_cb cb)
-{
- struct box_construct_ctx *ctx;
-
- if (c->bctx == NULL) {
- /* create a context allocation for this box tree */
- c->bctx = talloc_zero(0, int);
- if (c->bctx == NULL) {
- return NSERROR_NOMEM;
- }
- }
-
- ctx = malloc(sizeof(*ctx));
- if (ctx == NULL) {
- return NSERROR_NOMEM;
- }
-
- ctx->content = c;
- ctx->n = dom_node_ref(n);
- ctx->root_box = NULL;
- ctx->cb = cb;
- ctx->bctx = c->bctx;
-
- return guit->misc->schedule(0, (void *)convert_xml_to_box, ctx);
-}
-
-/* mapping from CSS display to box type
- * this table must be in sync with libcss' css_display enum */
-static const box_type box_map[] = {
- 0, /*CSS_DISPLAY_INHERIT,*/
- BOX_INLINE, /*CSS_DISPLAY_INLINE,*/
- BOX_BLOCK, /*CSS_DISPLAY_BLOCK,*/
- BOX_BLOCK, /*CSS_DISPLAY_LIST_ITEM,*/
- BOX_INLINE, /*CSS_DISPLAY_RUN_IN,*/
- BOX_INLINE_BLOCK, /*CSS_DISPLAY_INLINE_BLOCK,*/
- BOX_TABLE, /*CSS_DISPLAY_TABLE,*/
- BOX_TABLE, /*CSS_DISPLAY_INLINE_TABLE,*/
- BOX_TABLE_ROW_GROUP, /*CSS_DISPLAY_TABLE_ROW_GROUP,*/
- BOX_TABLE_ROW_GROUP, /*CSS_DISPLAY_TABLE_HEADER_GROUP,*/
- BOX_TABLE_ROW_GROUP, /*CSS_DISPLAY_TABLE_FOOTER_GROUP,*/
- BOX_TABLE_ROW, /*CSS_DISPLAY_TABLE_ROW,*/
- BOX_NONE, /*CSS_DISPLAY_TABLE_COLUMN_GROUP,*/
- BOX_NONE, /*CSS_DISPLAY_TABLE_COLUMN,*/
- BOX_TABLE_CELL, /*CSS_DISPLAY_TABLE_CELL,*/
- BOX_INLINE, /*CSS_DISPLAY_TABLE_CAPTION,*/
- BOX_NONE /*CSS_DISPLAY_NONE*/
-};
-
-static inline struct box *box_for_node(dom_node *n)
-{
- struct box *box = NULL;
- dom_exception err;
-
- err = dom_node_get_user_data(n, corestring_dom___ns_key_box_node_data,
- (void *) &box);
- if (err != DOM_NO_ERR)
- return NULL;
-
- return box;
-}
-
-static inline bool box_is_root(dom_node *n)
-{
- dom_node *parent;
- dom_node_type type;
- dom_exception err;
-
- err = dom_node_get_parent_node(n, &parent);
- if (err != DOM_NO_ERR)
- return false;
-
- if (parent != NULL) {
- err = dom_node_get_node_type(parent, &type);
-
- dom_node_unref(parent);
-
- if (err != DOM_NO_ERR)
- return false;
-
- if (type != DOM_DOCUMENT_NODE)
- return false;
- }
-
- return true;
-}
-
-/**
- * Find the next node in the DOM tree, completing
- * element construction where appropriate.
- *
- * \param n Current node
- * \param content Containing content
- * \param convert_children Whether to consider children of \a n
- * \return Next node to process, or NULL if complete
- *
- * \note \a n will be unreferenced
- */
-static dom_node *next_node(dom_node *n, html_content *content,
- bool convert_children)
-{
- dom_node *next = NULL;
- bool has_children;
- dom_exception err;
-
- err = dom_node_has_child_nodes(n, &has_children);
- if (err != DOM_NO_ERR) {
- dom_node_unref(n);
- return NULL;
- }
-
- if (convert_children && has_children) {
- err = dom_node_get_first_child(n, &next);
- if (err != DOM_NO_ERR) {
- dom_node_unref(n);
- return NULL;
- }
- dom_node_unref(n);
- } else {
- err = dom_node_get_next_sibling(n, &next);
- if (err != DOM_NO_ERR) {
- dom_node_unref(n);
- return NULL;
- }
-
- if (next != NULL) {
- if (box_for_node(n) != NULL)
- box_construct_element_after(n, content);
- dom_node_unref(n);
- } else {
- if (box_for_node(n) != NULL)
- box_construct_element_after(n, content);
-
- while (box_is_root(n) == false) {
- dom_node *parent = NULL;
- dom_node *parent_next = NULL;
-
- err = dom_node_get_parent_node(n, &parent);
- if (err != DOM_NO_ERR) {
- dom_node_unref(n);
- return NULL;
- }
-
- assert(parent != NULL);
-
- err = dom_node_get_next_sibling(parent,
- &parent_next);
- if (err != DOM_NO_ERR) {
- dom_node_unref(parent);
- dom_node_unref(n);
- return NULL;
- }
-
- if (parent_next != NULL) {
- dom_node_unref(parent_next);
- dom_node_unref(parent);
- break;
- }
-
- dom_node_unref(n);
- n = parent;
- parent = NULL;
-
- if (box_for_node(n) != NULL) {
- box_construct_element_after(
- n, content);
- }
- }
-
- if (box_is_root(n) == false) {
- dom_node *parent = NULL;
-
- err = dom_node_get_parent_node(n, &parent);
- if (err != DOM_NO_ERR) {
- dom_node_unref(n);
- return NULL;
- }
-
- assert(parent != NULL);
-
- err = dom_node_get_next_sibling(parent, &next);
- if (err != DOM_NO_ERR) {
- dom_node_unref(parent);
- dom_node_unref(n);
- return NULL;
- }
-
- if (box_for_node(parent) != NULL) {
- box_construct_element_after(parent,
- content);
- }
-
- dom_node_unref(parent);
- }
-
- dom_node_unref(n);
- }
- }
-
- return next;
-}
-
-/**
- * Convert an ELEMENT node to a box tree fragment,
- * then schedule conversion of the next ELEMENT node
- */
-void convert_xml_to_box(struct box_construct_ctx *ctx)
-{
- dom_node *next;
- bool convert_children;
- uint32_t num_processed = 0;
- const uint32_t max_processed_before_yield = 10;
-
- do {
- convert_children = true;
-
- assert(ctx->n != NULL);
-
- if (box_construct_element(ctx, &convert_children) == false) {
- ctx->cb(ctx->content, false);
- dom_node_unref(ctx->n);
- free(ctx);
- return;
- }
-
- /* Find next element to process, converting text nodes as we go */
- next = next_node(ctx->n, ctx->content, convert_children);
- while (next != NULL) {
- dom_node_type type;
- dom_exception err;
-
- err = dom_node_get_node_type(next, &type);
- if (err != DOM_NO_ERR) {
- ctx->cb(ctx->content, false);
- dom_node_unref(next);
- free(ctx);
- return;
- }
-
- if (type == DOM_ELEMENT_NODE)
- break;
-
- if (type == DOM_TEXT_NODE) {
- ctx->n = next;
- if (box_construct_text(ctx) == false) {
- ctx->cb(ctx->content, false);
- dom_node_unref(ctx->n);
- free(ctx);
- return;
- }
- }
-
- next = next_node(next, ctx->content, true);
- }
-
- ctx->n = next;
-
- if (next == NULL) {
- /* Conversion complete */
- struct box root;
-
- memset(&root, 0, sizeof(root));
-
- root.type = BOX_BLOCK;
- root.children = root.last = ctx->root_box;
- root.children->parent = &root;
-
- /** \todo Remove box_normalise_block */
- if (box_normalise_block(&root, ctx->root_box,
- ctx->content) == false) {
- ctx->cb(ctx->content, false);
- } else {
- ctx->content->layout = root.children;
- ctx->content->layout->parent = NULL;
-
- ctx->cb(ctx->content, true);
- }
-
- assert(ctx->n == NULL);
-
- free(ctx);
- return;
- }
- } while (++num_processed < max_processed_before_yield);
-
- /* More work to do: schedule a continuation */
- guit->misc->schedule(0, (void *)convert_xml_to_box, ctx);
-}
-
-/**
- * Construct a list marker box
- *
- * \param box Box to attach marker to
- * \param title Current title attribute
- * \param ctx Box construction context
- * \param parent Current block-level container
- * \return true on success, false on memory exhaustion
- */
-static bool box_construct_marker(struct box *box, const char *title,
- struct box_construct_ctx *ctx, struct box *parent)
-{
- lwc_string *image_uri;
- struct box *marker;
-
- marker = box_create(NULL, box->style, false, NULL, NULL, title,
- NULL, ctx->bctx);
- if (marker == false)
- return false;
-
- marker->type = BOX_BLOCK;
-
- /** \todo marker content (list-style-type) */
- switch (css_computed_list_style_type(box->style)) {
- case CSS_LIST_STYLE_TYPE_DISC:
- /* 2022 BULLET */
- marker->text = (char *) "\342\200\242";
- marker->length = 3;
- break;
- case CSS_LIST_STYLE_TYPE_CIRCLE:
- /* 25CB WHITE CIRCLE */
- marker->text = (char *) "\342\227\213";
- marker->length = 3;
- break;
- case CSS_LIST_STYLE_TYPE_SQUARE:
- /* 25AA BLACK SMALL SQUARE */
- marker->text = (char *) "\342\226\252";
- marker->length = 3;
- break;
- case CSS_LIST_STYLE_TYPE_DECIMAL:
- case CSS_LIST_STYLE_TYPE_LOWER_ALPHA:
- case CSS_LIST_STYLE_TYPE_LOWER_ROMAN:
- case CSS_LIST_STYLE_TYPE_UPPER_ALPHA:
- case CSS_LIST_STYLE_TYPE_UPPER_ROMAN:
- default:
- if (parent->last) {
- struct box *last = parent->last;
-
- /* Drill down into last child of parent
- * to find the list marker (if any)
- *
- * Floated list boxes end up as:
- *
- * parent
- * BOX_INLINE_CONTAINER
- * BOX_FLOAT_{LEFT,RIGHT}
- * BOX_BLOCK <-- list box
- * ...
- */
- while (last != NULL && last->list_marker == NULL) {
- struct box *last_inner = last;
-
- while (last_inner != NULL) {
- if (last_inner->list_marker != NULL)
- break;
- if (last_inner->type ==
- BOX_INLINE_CONTAINER ||
- last_inner->type ==
- BOX_FLOAT_LEFT ||
- last_inner->type ==
- BOX_FLOAT_RIGHT) {
- last_inner = last_inner->last;
- } else {
- last_inner = NULL;
- }
- }
- if (last_inner != NULL) {
- last = last_inner;
- } else {
- last = last->prev;
- }
- }
-
- if (last && last->list_marker) {
- marker->rows = last->list_marker->rows + 1;
- }
- }
-
- marker->text = talloc_array(ctx->bctx, char, 20);
- if (marker->text == NULL)
- return false;
-
- snprintf(marker->text, 20, "%u.", marker->rows);
- marker->length = strlen(marker->text);
- break;
- case CSS_LIST_STYLE_TYPE_NONE:
- marker->text = 0;
- marker->length = 0;
- break;
- }
-
- if (css_computed_list_style_image(box->style, &image_uri) == CSS_LIST_STYLE_IMAGE_URI &&
- (image_uri != NULL) &&
- (nsoption_bool(foreground_images) == true)) {
- nsurl *url;
- nserror error;
-
- /* TODO: we get a url out of libcss as a lwc string, but
- * earlier we already had it as a nsurl after we
- * nsurl_joined it. Can this be improved?
- * For now, just making another nsurl. */
- error = nsurl_create(lwc_string_data(image_uri), &url);
- if (error != NSERROR_OK)
- return false;
-
- if (html_fetch_object(ctx->content, url, marker, image_types,
- ctx->content->base.available_width, 1000, false) ==
- false) {
- nsurl_unref(url);
- return false;
- }
- nsurl_unref(url);
- }
-
- box->list_marker = marker;
- marker->parent = box;
-
- return true;
-}
-
-/**
- * Construct the box required for a generated element.
- *
- * \param n XML node of type XML_ELEMENT_NODE
- * \param content Content of type CONTENT_HTML that is being processed
- * \param box Box which may have generated content
- * \param style Complete computed style for pseudo element, or NULL
- *
- * TODO:
- * This is currently incomplete. It just does enough to support the clearfix
- * hack. ( http://www.positioniseverything.net/easyclearing.html )
- */
-static void box_construct_generate(dom_node *n, html_content *content,
- struct box *box, const css_computed_style *style)
-{
- struct box *gen = NULL;
- enum css_display_e computed_display;
- const css_computed_content_item *c_item;
-
- /* Nothing to generate if the parent box is not a block */
- if (box->type != BOX_BLOCK)
- return;
-
- /* To determine if an element has a pseudo element, we select
- * for it and test to see if the returned style's content
- * property is set to normal. */
- if (style == NULL ||
- css_computed_content(style, &c_item) ==
- CSS_CONTENT_NORMAL) {
- /* No pseudo element */
- return;
- }
-
- /* create box for this element */
- computed_display = ns_computed_display(style, box_is_root(n));
- if (computed_display == CSS_DISPLAY_BLOCK ||
- computed_display == CSS_DISPLAY_TABLE) {
- /* currently only support block level boxes */
-
- /** \todo Not wise to drop const from the computed style */
- gen = box_create(NULL, (css_computed_style *) style,
- false, NULL, NULL, NULL, NULL, content->bctx);
- if (gen == NULL) {
- return;
- }
-
- /* set box type from computed display */
- gen->type = box_map[ns_computed_display(
- style, box_is_root(n))];
-
- box_add_child(box, gen);
- }
-}
-
-/**
- * Extract transient construction properties
- *
- * \param n Current DOM node to convert
- * \param props Property object to populate
- */
-static void box_extract_properties(dom_node *n,
- struct box_construct_props *props)
-{
- memset(props, 0, sizeof(*props));
-
- props->node_is_root = box_is_root(n);
-
- /* Extract properties from containing DOM node */
- if (props->node_is_root == false) {
- dom_node *current_node = n;
- dom_node *parent_node = NULL;
- struct box *parent_box;
- dom_exception err;
-
- /* Find ancestor node containing parent box */
- while (true) {
- err = dom_node_get_parent_node(current_node,
- &parent_node);
- if (err != DOM_NO_ERR || parent_node == NULL)
- break;
-
- parent_box = box_for_node(parent_node);
-
- if (parent_box != NULL) {
- props->parent_style = parent_box->style;
- props->href = parent_box->href;
- props->target = parent_box->target;
- props->title = parent_box->title;
-
- dom_node_unref(parent_node);
- break;
- } else {
- if (current_node != n)
- dom_node_unref(current_node);
- current_node = parent_node;
- parent_node = NULL;
- }
- }
-
- /* Find containing block (may be parent) */
- while (true) {
- struct box *b;
-
- err = dom_node_get_parent_node(current_node,
- &parent_node);
- if (err != DOM_NO_ERR || parent_node == NULL) {
- if (current_node != n)
- dom_node_unref(current_node);
- break;
- }
-
- if (current_node != n)
- dom_node_unref(current_node);
-
- b = box_for_node(parent_node);
-
- /* Children of nodes that created an inline box
- * will generate boxes which are attached as
- * _siblings_ of the box generated for their
- * parent node. Note, however, that we'll still
- * use the parent node's styling as the parent
- * style, above. */
- if (b != NULL && b->type != BOX_INLINE &&
- b->type != BOX_BR) {
- props->containing_block = b;
-
- dom_node_unref(parent_node);
- break;
- } else {
- current_node = parent_node;
- parent_node = NULL;
- }
- }
- }
-
- /* Compute current inline container, if any */
- if (props->containing_block != NULL &&
- props->containing_block->last != NULL &&
- props->containing_block->last->type ==
- BOX_INLINE_CONTAINER)
- props->inline_container = props->containing_block->last;
-}
-
-/**
- * Construct the box tree for an XML element.
- *
- * \param ctx Tree construction context
- * \param convert_children Whether to convert children
- * \return true on success, false on memory exhaustion
- */
-
-bool box_construct_element(struct box_construct_ctx *ctx,
- bool *convert_children)
-{
- dom_string *title0, *s;
- lwc_string *id = NULL;
- struct box *box = NULL, *old_box;
- css_select_results *styles = NULL;
- struct element_entry *element;
- lwc_string *bgimage_uri;
- dom_exception err;
- struct box_construct_props props;
- const css_computed_style *root_style = NULL;
-
- assert(ctx->n != NULL);
-
- box_extract_properties(ctx->n, &props);
-
- if (props.containing_block != NULL) {
- /* In case the containing block is a pre block, we clear
- * the PRE_STRIP flag since it is not used if we follow
- * the pre with a tag */
- props.containing_block->flags &= ~PRE_STRIP;
- }
-
- if (props.node_is_root == false) {
- root_style = ctx->root_box->style;
- }
-
- styles = box_get_style(ctx->content, props.parent_style, root_style,
- ctx->n);
- if (styles == NULL)
- return false;
-
- /* Extract title attribute, if present */
- err = dom_element_get_attribute(ctx->n, corestring_dom_title, &title0);
- if (err != DOM_NO_ERR)
- return false;
-
- if (title0 != NULL) {
- char *t = squash_whitespace(dom_string_data(title0));
-
- dom_string_unref(title0);
-
- if (t == NULL)
- return false;
-
- props.title = talloc_strdup(ctx->bctx, t);
-
- free(t);
-
- if (props.title == NULL)
- return false;
- }
-
- /* Extract id attribute, if present */
- err = dom_element_get_attribute(ctx->n, corestring_dom_id, &s);
- if (err != DOM_NO_ERR)
- return false;
-
- if (s != NULL) {
- err = dom_string_intern(s, &id);
- if (err != DOM_NO_ERR)
- id = NULL;
-
- dom_string_unref(s);
- }
-
- box = box_create(styles, styles->styles[CSS_PSEUDO_ELEMENT_NONE], false,
- props.href, props.target, props.title, id,
- ctx->bctx);
- if (box == NULL)
- return false;
-
- /* If this is the root box, add it to the context */
- if (props.node_is_root)
- ctx->root_box = box;
-
- /* Deal with colspan/rowspan */
- err = dom_element_get_attribute(ctx->n, corestring_dom_colspan, &s);
- if (err != DOM_NO_ERR)
- return false;
-
- if (s != NULL) {
- const char *val = dom_string_data(s);
-
- if ('0' <= val[0] && val[0] <= '9')
- box->columns = strtol(val, NULL, 10);
-
- dom_string_unref(s);
- }
-
- err = dom_element_get_attribute(ctx->n, corestring_dom_rowspan, &s);
- if (err != DOM_NO_ERR)
- return false;
-
- if (s != NULL) {
- const char *val = dom_string_data(s);
-
- if ('0' <= val[0] && val[0] <= '9')
- box->rows = strtol(val, NULL, 10);
-
- dom_string_unref(s);
- }
-
- /* Set box type from computed display */
- if ((css_computed_position(box->style) == CSS_POSITION_ABSOLUTE ||
- css_computed_position(box->style) ==
- CSS_POSITION_FIXED) &&
- (ns_computed_display_static(box->style) ==
- CSS_DISPLAY_INLINE ||
- ns_computed_display_static(box->style) ==
- CSS_DISPLAY_INLINE_BLOCK ||
- ns_computed_display_static(box->style) ==
- CSS_DISPLAY_INLINE_TABLE)) {
- /* Special case for absolute positioning: make absolute inlines
- * into inline block so that the boxes are constructed in an
- * inline container as if they were not absolutely positioned.
- * Layout expects and handles this. */
- box->type = box_map[CSS_DISPLAY_INLINE_BLOCK];
- } else if (props.node_is_root) {
- /* Special case for root element: force it to BLOCK, or the
- * rest of the layout will break. */
- box->type = BOX_BLOCK;
- } else {
- /* Normal mapping */
- box->type = box_map[ns_computed_display(box->style,
- props.node_is_root)];
- }
-
- err = dom_node_get_node_name(ctx->n, &s);
- if (err != DOM_NO_ERR || s == NULL)
- return false;
-
- /* Special elements */
- element = bsearch(dom_string_data(s), element_table,
- ELEMENT_TABLE_COUNT, sizeof(element_table[0]),
- (int (*)(const void *, const void *)) strcasecmp);
-
- dom_string_unref(s);
-
- if (element != NULL) {
- /* A special convert function exists for this element */
- if (element->convert(ctx->n, ctx->content, box,
- convert_children) == false)
- return false;
- }
-
- /* Handle the :before pseudo element */
- if (!(box->flags & IS_REPLACED)) {
- box_construct_generate(ctx->n, ctx->content, box,
- box->styles->styles[CSS_PSEUDO_ELEMENT_BEFORE]);
- }
-
- if (box->type == BOX_NONE || (ns_computed_display(box->style,
- props.node_is_root) == CSS_DISPLAY_NONE &&
- props.node_is_root == false)) {
- css_select_results_destroy(styles);
- box->styles = NULL;
- box->style = NULL;
-
- /* Invalidate associated gadget, if any */
- if (box->gadget != NULL) {
- box->gadget->box = NULL;
- box->gadget = NULL;
- }
-
- /* Can't do this, because the lifetimes of boxes and gadgets
- * are inextricably linked. Fortunately, talloc will save us
- * (for now) */
- /* box_free_box(box); */
-
- *convert_children = false;
-
- return true;
- }
-
- /* Attach DOM node to box */
- err = dom_node_set_user_data(ctx->n,
- corestring_dom___ns_key_box_node_data, box, NULL,
- (void *) &old_box);
- if (err != DOM_NO_ERR)
- return false;
-
- /* Attach box to DOM node */
- box->node = dom_node_ref(ctx->n);
-
- if (props.inline_container == NULL &&
- (box->type == BOX_INLINE ||
- box->type == BOX_BR ||
- box->type == BOX_INLINE_BLOCK ||
- css_computed_float(box->style) == CSS_FLOAT_LEFT ||
- css_computed_float(box->style) == CSS_FLOAT_RIGHT) &&
- props.node_is_root == false) {
- /* Found an inline child of a block without a current container
- * (i.e. this box is the first child of its parent, or was
- * preceded by block-level siblings) */
- assert(props.containing_block != NULL &&
- "Box must have containing block.");
-
- props.inline_container = box_create(NULL, NULL, false, NULL,
- NULL, NULL, NULL, ctx->bctx);
- if (props.inline_container == NULL)
- return false;
-
- props.inline_container->type = BOX_INLINE_CONTAINER;
-
- box_add_child(props.containing_block, props.inline_container);
- }
-
- /* Kick off fetch for any background image */
- if (css_computed_background_image(box->style, &bgimage_uri) ==
- CSS_BACKGROUND_IMAGE_IMAGE && bgimage_uri != NULL &&
- nsoption_bool(background_images) == true) {
- nsurl *url;
- nserror error;
-
- /* TODO: we get a url out of libcss as a lwc string, but
- * earlier we already had it as a nsurl after we
- * nsurl_joined it. Can this be improved?
- * For now, just making another nsurl. */
- error = nsurl_create(lwc_string_data(bgimage_uri), &url);
- if (error == NSERROR_OK) {
- /* Fetch image if we got a valid URL */
- if (html_fetch_object(ctx->content, url, box,
- image_types,
- ctx->content->base.available_width,
- 1000, true) == false) {
- nsurl_unref(url);
- return false;
- }
- nsurl_unref(url);
- }
- }
-
- if (*convert_children)
- box->flags |= CONVERT_CHILDREN;
-
- if (box->type == BOX_INLINE || box->type == BOX_BR ||
- box->type == BOX_INLINE_BLOCK) {
- /* Inline container must exist, as we'll have
- * created it above if it didn't */
- assert(props.inline_container != NULL);
-
- box_add_child(props.inline_container, box);
- } else {
- if (ns_computed_display(box->style, props.node_is_root) ==
- CSS_DISPLAY_LIST_ITEM) {
- /* List item: compute marker */
- if (box_construct_marker(box, props.title, ctx,
- props.containing_block) == false)
- return false;
- }
-
- if (props.node_is_root == false &&
- (css_computed_float(box->style) ==
- CSS_FLOAT_LEFT ||
- css_computed_float(box->style) ==
- CSS_FLOAT_RIGHT)) {
- /* Float: insert a float between the parent and box. */
- struct box *flt = box_create(NULL, NULL, false,
- props.href, props.target, props.title,
- NULL, ctx->bctx);
- if (flt == NULL)
- return false;
-
- if (css_computed_float(box->style) == CSS_FLOAT_LEFT)
- flt->type = BOX_FLOAT_LEFT;
- else
- flt->type = BOX_FLOAT_RIGHT;
-
- box_add_child(props.inline_container, flt);
- box_add_child(flt, box);
- } else {
- /* Non-floated block-level box: add to containing block
- * if there is one. If we're the root box, then there
- * won't be. */
- if (props.containing_block != NULL)
- box_add_child(props.containing_block, box);
- }
- }
-
- return true;
-}
-
-/**
- * Complete construction of the box tree for an element.
- *
- * \param n DOM node to construct for
- * \param content Containing document
- *
- * This will be called after all children of an element have been processed
- */
-void box_construct_element_after(dom_node *n, html_content *content)
-{
- struct box_construct_props props;
- struct box *box = box_for_node(n);
-
- assert(box != NULL);
-
- box_extract_properties(n, &props);
-
- if (box->type == BOX_INLINE || box->type == BOX_BR) {
- /* Insert INLINE_END into containing block */
- struct box *inline_end;
- bool has_children;
- dom_exception err;
-
- err = dom_node_has_child_nodes(n, &has_children);
- if (err != DOM_NO_ERR)
- return;
-
- if (has_children == false ||
- (box->flags & CONVERT_CHILDREN) == 0) {
- /* No children, or didn't want children converted */
- return;
- }
-
- if (props.inline_container == NULL) {
- /* Create inline container if we don't have one */
- props.inline_container = box_create(NULL, NULL, false,
- NULL, NULL, NULL, NULL, content->bctx);
- if (props.inline_container == NULL)
- return;
-
- props.inline_container->type = BOX_INLINE_CONTAINER;
-
- box_add_child(props.containing_block,
- props.inline_container);
- }
-
- inline_end = box_create(NULL, box->style, false,
- box->href, box->target, box->title,
- box->id == NULL ? NULL :
- lwc_string_ref(box->id), content->bctx);
- if (inline_end != NULL) {
- inline_end->type = BOX_INLINE_END;
-
- assert(props.inline_container != NULL);
-
- box_add_child(props.inline_container, inline_end);
-
- box->inline_end = inline_end;
- inline_end->inline_end = box;
- }
- } else if (!(box->flags & IS_REPLACED)) {
- /* Handle the :after pseudo element */
- box_construct_generate(n, content, box,
- box->styles->styles[CSS_PSEUDO_ELEMENT_AFTER]);
- }
-}
-
-/**
- * Construct the box tree for an XML text node.
- *
- * \param ctx Tree construction context
- * \return true on success, false on memory exhaustion
- */
-
-bool box_construct_text(struct box_construct_ctx *ctx)
-{
- struct box_construct_props props;
- struct box *box = NULL;
- dom_string *content;
- dom_exception err;
-
- assert(ctx->n != NULL);
-
- box_extract_properties(ctx->n, &props);
-
- assert(props.containing_block != NULL);
-
- err = dom_characterdata_get_data(ctx->n, &content);
- if (err != DOM_NO_ERR || content == NULL)
- return false;
-
- if (css_computed_white_space(props.parent_style) ==
- CSS_WHITE_SPACE_NORMAL ||
- css_computed_white_space(props.parent_style) ==
- CSS_WHITE_SPACE_NOWRAP) {
- char *text;
-
- text = squash_whitespace(dom_string_data(content));
-
- dom_string_unref(content);
-
- if (text == NULL)
- return false;
-
- /* if the text is just a space, combine it with the preceding
- * text node, if any */
- if (text[0] == ' ' && text[1] == 0) {
- if (props.inline_container != NULL) {
- assert(props.inline_container->last != NULL);
-
- props.inline_container->last->space =
- UNKNOWN_WIDTH;
- }
-
- free(text);
-
- return true;
- }
-
- if (props.inline_container == NULL) {
- /* Child of a block without a current container
- * (i.e. this box is the first child of its parent, or
- * was preceded by block-level siblings) */
- props.inline_container = box_create(NULL, NULL, false,
- NULL, NULL, NULL, NULL, ctx->bctx);
- if (props.inline_container == NULL) {
- free(text);
- return false;
- }
-
- props.inline_container->type = BOX_INLINE_CONTAINER;
-
- box_add_child(props.containing_block,
- props.inline_container);
- }
-
- /** \todo Dropping const here is not clever */
- box = box_create(NULL,
- (css_computed_style *) props.parent_style,
- false, props.href, props.target, props.title,
- NULL, ctx->bctx);
- if (box == NULL) {
- free(text);
- return false;
- }
-
- box->type = BOX_TEXT;
-
- box->text = talloc_strdup(ctx->bctx, text);
- free(text);
- if (box->text == NULL)
- return false;
-
- box->length = strlen(box->text);
-
- /* strip ending space char off */
- if (box->length > 1 && box->text[box->length - 1] == ' ') {
- box->space = UNKNOWN_WIDTH;
- box->length--;
- }
-
- if (css_computed_text_transform(props.parent_style) !=
- CSS_TEXT_TRANSFORM_NONE)
- box_text_transform(box->text, box->length,
- css_computed_text_transform(
- props.parent_style));
-
- box_add_child(props.inline_container, box);
-
- if (box->text[0] == ' ') {
- box->length--;
-
- memmove(box->text, &box->text[1], box->length);
-
- if (box->prev != NULL)
- box->prev->space = UNKNOWN_WIDTH;
- }
- } else {
- /* white-space: pre */
- char *text;
- size_t text_len = dom_string_byte_length(content);
- size_t i;
- char *current;
- enum css_white_space_e white_space =
- css_computed_white_space(props.parent_style);
-
- /* note: pre-wrap/pre-line are unimplemented */
- assert(white_space == CSS_WHITE_SPACE_PRE ||
- white_space == CSS_WHITE_SPACE_PRE_LINE ||
- white_space == CSS_WHITE_SPACE_PRE_WRAP);
-
- text = malloc(text_len + 1);
- dom_string_unref(content);
-
- if (text == NULL)
- return false;
-
- memcpy(text, dom_string_data(content), text_len);
- text[text_len] = '\0';
-
- /* TODO: Handle tabs properly */
- for (i = 0; i < text_len; i++)
- if (text[i] == '\t')
- text[i] = ' ';
-
- if (css_computed_text_transform(props.parent_style) !=
- CSS_TEXT_TRANSFORM_NONE)
- box_text_transform(text, strlen(text),
- css_computed_text_transform(
- props.parent_style));
-
- current = text;
-
- /* swallow a single leading new line */
- if (props.containing_block->flags & PRE_STRIP) {
- switch (*current) {
- case '\n':
- current++;
- break;
- case '\r':
- current++;
- if (*current == '\n')
- current++;
- break;
- }
- props.containing_block->flags &= ~PRE_STRIP;
- }
-
- do {
- size_t len = strcspn(current, "\r\n");
-
- char old = current[len];
-
- current[len] = 0;
-
- if (props.inline_container == NULL) {
- /* Child of a block without a current container
- * (i.e. this box is the first child of its
- * parent, or was preceded by block-level
- * siblings) */
- props.inline_container = box_create(NULL, NULL,
- false, NULL, NULL, NULL, NULL,
- ctx->bctx);
- if (props.inline_container == NULL) {
- free(text);
- return false;
- }
-
- props.inline_container->type =
- BOX_INLINE_CONTAINER;
-
- box_add_child(props.containing_block,
- props.inline_container);
- }
-
- /** \todo Dropping const isn't clever */
- box = box_create(NULL,
- (css_computed_style *) props.parent_style,
- false, props.href, props.target, props.title,
- NULL, ctx->bctx);
- if (box == NULL) {
- free(text);
- return false;
- }
-
- box->type = BOX_TEXT;
-
- box->text = talloc_strdup(ctx->bctx, current);
- if (box->text == NULL) {
- free(text);
- return false;
- }
-
- box->length = strlen(box->text);
-
- box_add_child(props.inline_container, box);
-
- current[len] = old;
-
- current += len;
-
- if (current[0] != '\0') {
- /* Linebreak: create new inline container */
- props.inline_container = box_create(NULL, NULL,
- false, NULL, NULL, NULL, NULL,
- ctx->bctx);
- if (props.inline_container == NULL) {
- free(text);
- return false;
- }
-
- props.inline_container->type =
- BOX_INLINE_CONTAINER;
-
- box_add_child(props.containing_block,
- props.inline_container);
-
- if (current[0] == '\r' && current[1] == '\n')
- current += 2;
- else
- current++;
- }
- } while (*current);
-
- free(text);
- }
-
- return true;
-}
-
-/**
- * Get the style for an element.
- *
- * \param c content of type CONTENT_HTML that is being processed
- * \param parent_style style at this point in xml tree, or NULL for root
- * \param root_style root node's style, or NULL for root
- * \param n node in xml tree
- * \return the new style, or NULL on memory exhaustion
- */
-css_select_results *box_get_style(html_content *c,
- const css_computed_style *parent_style,
- const css_computed_style *root_style, dom_node *n)
-{
- dom_string *s;
- dom_exception err;
- css_stylesheet *inline_style = NULL;
- css_select_results *styles;
- nscss_select_ctx ctx;
-
- /* Firstly, construct inline stylesheet, if any */
- err = dom_element_get_attribute(n, corestring_dom_style, &s);
- if (err != DOM_NO_ERR)
- return NULL;
-
- if (s != NULL) {
- inline_style = nscss_create_inline_style(
- (const uint8_t *) dom_string_data(s),
- dom_string_byte_length(s),
- c->encoding,
- nsurl_access(c->base_url),
- c->quirks != DOM_DOCUMENT_QUIRKS_MODE_NONE);
-
- dom_string_unref(s);
-
- if (inline_style == NULL)
- return NULL;
- }
-
- /* Populate selection context */
- ctx.ctx = c->select_ctx;
- ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
- ctx.base_url = c->base_url;
- ctx.universal = c->universal;
- ctx.root_style = root_style;
- ctx.parent_style = parent_style;
-
- /* Select style for element */
- styles = nscss_get_style(&ctx, n, CSS_MEDIA_SCREEN, inline_style);
-
- /* No longer need inline style */
- if (inline_style != NULL)
- css_stylesheet_destroy(inline_style);
-
- return styles;
-}
-
-
-/**
- * Apply the CSS text-transform property to given text for its ASCII chars.
- *
- * \param s string to transform
- * \param len length of s
- * \param tt transform type
- */
-
-void box_text_transform(char *s, unsigned int len, enum css_text_transform_e tt)
-{
- unsigned int i;
- if (len == 0)
- return;
- switch (tt) {
- case CSS_TEXT_TRANSFORM_UPPERCASE:
- for (i = 0; i < len; ++i)
- if ((unsigned char) s[i] < 0x80)
- s[i] = toupper(s[i]);
- break;
- case CSS_TEXT_TRANSFORM_LOWERCASE:
- for (i = 0; i < len; ++i)
- if ((unsigned char) s[i] < 0x80)
- s[i] = tolower(s[i]);
- break;
- case CSS_TEXT_TRANSFORM_CAPITALIZE:
- if ((unsigned char) s[0] < 0x80)
- s[0] = toupper(s[0]);
- for (i = 1; i < len; ++i)
- if ((unsigned char) s[i] < 0x80 &&
- isspace(s[i - 1]))
- s[i] = toupper(s[i]);
- break;
- default:
- break;
- }
-}
-
-
-/**
- * \name Special case element handlers
- *
- * These functions are called by box_construct_element() when an element is
- * being converted, according to the entries in element_table.
- *
- * The parameters are the xmlNode, the content for the document, and a partly
- * filled in box structure for the element.
- *
- * Return true on success, false on memory exhaustion. Set *convert_children
- * to false if children of this element in the XML tree should be skipped (for
- * example, if they have been processed in some special way already).
- *
- * Elements ordered as in the HTML 4.01 specification. Section numbers in
- * brackets [] refer to the spec.
- *
- * \{
- */
-
-/**
- * Document body [7.5.1].
- */
-
-bool box_body(BOX_SPECIAL_PARAMS)
-{
- css_color color;
-
- css_computed_background_color(box->style, &color);
- if (nscss_color_is_transparent(color))
- content->background_colour = NS_TRANSPARENT;
- else
- content->background_colour = nscss_color_to_ns(color);
-
- return true;
-}
-
-
-/**
- * Forced line break [9.3.2].
- */
-
-bool box_br(BOX_SPECIAL_PARAMS)
-{
- box->type = BOX_BR;
- return true;
-}
-
-/**
- * Preformatted text [9.3.4].
- */
-
-bool box_pre(BOX_SPECIAL_PARAMS)
-{
- box->flags |= PRE_STRIP;
- return true;
-}
-
-/**
- * Anchor [12.2].
- */
-
-bool box_a(BOX_SPECIAL_PARAMS)
-{
- bool ok;
- nsurl *url;
- dom_string *s;
- dom_exception err;
-
- err = dom_element_get_attribute(n, corestring_dom_href, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- ok = box_extract_link(content, s, content->base_url, &url);
- dom_string_unref(s);
- if (!ok)
- return false;
- if (url) {
- if (box->href != NULL)
- nsurl_unref(box->href);
- box->href = url;
- }
- }
-
- /* name and id share the same namespace */
- err = dom_element_get_attribute(n, corestring_dom_name, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- lwc_string *lwc_name;
-
- err = dom_string_intern(s, &lwc_name);
-
- dom_string_unref(s);
-
- if (err == DOM_NO_ERR) {
- /* name replaces existing id
- * TODO: really? */
- if (box->id != NULL)
- lwc_string_unref(box->id);
-
- box->id = lwc_name;
- }
- }
-
- /* target frame [16.3] */
- err = dom_element_get_attribute(n, corestring_dom_target, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- if (dom_string_caseless_lwc_isequal(s,
- corestring_lwc__blank))
- box->target = TARGET_BLANK;
- else if (dom_string_caseless_lwc_isequal(s,
- corestring_lwc__top))
- box->target = TARGET_TOP;
- else if (dom_string_caseless_lwc_isequal(s,
- corestring_lwc__parent))
- box->target = TARGET_PARENT;
- else if (dom_string_caseless_lwc_isequal(s,
- corestring_lwc__self))
- /* the default may have been overridden by a
- * <base target=...>, so this is different to 0 */
- box->target = TARGET_SELF;
- else {
- /* 6.16 says that frame names must begin with [a-zA-Z]
- * This doesn't match reality, so just take anything */
- box->target = talloc_strdup(content->bctx,
- dom_string_data(s));
- if (!box->target) {
- dom_string_unref(s);
- return false;
- }
- }
- dom_string_unref(s);
- }
-
- return true;
-}
-
-
-/**
- * Embedded image [13.2].
- */
-
-bool box_image(BOX_SPECIAL_PARAMS)
-{
- bool ok;
- dom_string *s;
- dom_exception err;
- nsurl *url;
- enum css_width_e wtype;
- enum css_height_e htype;
- css_fixed value = 0;
- css_unit wunit = CSS_UNIT_PX;
- css_unit hunit = CSS_UNIT_PX;
-
- if (box->style && ns_computed_display(box->style,
- box_is_root(n)) == CSS_DISPLAY_NONE)
- return true;
-
- /* handle alt text */
- err = dom_element_get_attribute(n, corestring_dom_alt, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- char *alt = squash_whitespace(dom_string_data(s));
- dom_string_unref(s);
- if (alt == NULL)
- return false;
- box->text = talloc_strdup(content->bctx, alt);
- free(alt);
- if (box->text == NULL)
- return false;
- box->length = strlen(box->text);
- }
-
- if (nsoption_bool(foreground_images) == false) {
- return true;
- }
-
- /* imagemap associated with this image */
- if (!box_get_attribute(n, "usemap", content->bctx, &box->usemap))
- return false;
- if (box->usemap && box->usemap[0] == '#')
- box->usemap++;
-
- /* get image URL */
- err = dom_element_get_attribute(n, corestring_dom_src, &s);
- if (err != DOM_NO_ERR || s == NULL)
- return true;
-
- if (box_extract_link(content, s, content->base_url, &url) == false) {
- dom_string_unref(s);
- return false;
- }
-
- dom_string_unref(s);
-
- if (url == NULL)
- return true;
-
- /* start fetch */
- box->flags |= IS_REPLACED;
- ok = html_fetch_object(content, url, box, image_types,
- content->base.available_width, 1000, false);
- nsurl_unref(url);
-
- wtype = css_computed_width(box->style, &value, &wunit);
- htype = css_computed_height(box->style, &value, &hunit);
-
- if (wtype == CSS_WIDTH_SET && wunit != CSS_UNIT_PCT &&
- htype == CSS_HEIGHT_SET && hunit != CSS_UNIT_PCT) {
- /* We know the dimensions the image will be shown at before it's
- * fetched. */
- box->flags |= REPLACE_DIM;
- }
-
- return ok;
-}
-
-
-/**
- * Noscript element
- */
-
-bool box_noscript(BOX_SPECIAL_PARAMS)
-{
- /* If scripting is enabled, do not display the contents of noscript */
- if (content->enable_scripting)
- *convert_children = false;
-
- return true;
-}
-
-
-/**
- * Destructor for object_params, for &lt;object&gt; elements
- *
- * \param o The object params being destroyed.
- * \return 0 to allow talloc to continue destroying the tree.
- */
-static int box_object_talloc_destructor(struct object_params *o)
-{
- if (o->codebase != NULL)
- nsurl_unref(o->codebase);
- if (o->classid != NULL)
- nsurl_unref(o->classid);
- if (o->data != NULL)
- nsurl_unref(o->data);
-
- return 0;
-}
-
-/**
- * Generic embedded object [13.3].
- */
-
-bool box_object(BOX_SPECIAL_PARAMS)
-{
- struct object_params *params;
- struct object_param *param;
- dom_string *codebase, *classid, *data;
- dom_node *c;
- dom_exception err;
-
- if (box->style && ns_computed_display(box->style,
- box_is_root(n)) == CSS_DISPLAY_NONE)
- return true;
-
- if (box_get_attribute(n, "usemap", content->bctx, &box->usemap) ==
- false)
- return false;
- if (box->usemap && box->usemap[0] == '#')
- box->usemap++;
-
- params = talloc(content->bctx, struct object_params);
- if (params == NULL)
- return false;
-
- talloc_set_destructor(params, box_object_talloc_destructor);
-
- params->data = NULL;
- params->type = NULL;
- params->codetype = NULL;
- params->codebase = NULL;
- params->classid = NULL;
- params->params = NULL;
-
- /* codebase, classid, and data are URLs
- * (codebase is the base for the other two) */
- err = dom_element_get_attribute(n, corestring_dom_codebase, &codebase);
- if (err == DOM_NO_ERR && codebase != NULL) {
- if (box_extract_link(content, codebase, content->base_url,
- &params->codebase) == false) {
- dom_string_unref(codebase);
- return false;
- }
- dom_string_unref(codebase);
- }
- if (params->codebase == NULL)
- params->codebase = nsurl_ref(content->base_url);
-
- err = dom_element_get_attribute(n, corestring_dom_classid, &classid);
- if (err == DOM_NO_ERR && classid != NULL) {
- if (box_extract_link(content, classid,
- params->codebase, &params->classid) == false) {
- dom_string_unref(classid);
- return false;
- }
- dom_string_unref(classid);
- }
-
- err = dom_element_get_attribute(n, corestring_dom_data, &data);
- if (err == DOM_NO_ERR && data != NULL) {
- if (box_extract_link(content, data,
- params->codebase, &params->data) == false) {
- dom_string_unref(data);
- return false;
- }
- dom_string_unref(data);
- }
-
- if (params->classid == NULL && params->data == NULL)
- /* nothing to embed; ignore */
- return true;
-
- /* Don't include ourself */
- if (params->classid != NULL && nsurl_compare(content->base_url,
- params->classid, NSURL_COMPLETE))
- return true;
-
- if (params->data != NULL && nsurl_compare(content->base_url,
- params->data, NSURL_COMPLETE))
- return true;
-
- /* codetype and type are MIME types */
- if (box_get_attribute(n, "codetype", params,
- &params->codetype) == false)
- return false;
- if (box_get_attribute(n, "type", params, &params->type) == false)
- return false;
-
- /* classid && !data => classid is used (consult codetype)
- * (classid || !classid) && data => data is used (consult type)
- * !classid && !data => invalid; ignored */
-
- if (params->classid != NULL && params->data == NULL &&
- params->codetype != NULL) {
- lwc_string *icodetype;
- lwc_error lerror;
-
- lerror = lwc_intern_string(params->codetype,
- strlen(params->codetype), &icodetype);
- if (lerror != lwc_error_ok)
- return false;
-
- if (content_factory_type_from_mime_type(icodetype) ==
- CONTENT_NONE) {
- /* can't handle this MIME type */
- lwc_string_unref(icodetype);
- return true;
- }
-
- lwc_string_unref(icodetype);
- }
-
- if (params->data != NULL && params->type != NULL) {
- lwc_string *itype;
- lwc_error lerror;
-
- lerror = lwc_intern_string(params->type, strlen(params->type),
- &itype);
- if (lerror != lwc_error_ok)
- return false;
-
- if (content_factory_type_from_mime_type(itype) ==
- CONTENT_NONE) {
- /* can't handle this MIME type */
- lwc_string_unref(itype);
- return true;
- }
-
- lwc_string_unref(itype);
- }
-
- /* add parameters to linked list */
- err = dom_node_get_first_child(n, &c);
- if (err != DOM_NO_ERR)
- return false;
-
- while (c != NULL) {
- dom_node *next;
- dom_node_type type;
-
- err = dom_node_get_node_type(c, &type);
- if (err != DOM_NO_ERR) {
- dom_node_unref(c);
- return false;
- }
-
- if (type == DOM_ELEMENT_NODE) {
- dom_string *name;
-
- err = dom_node_get_node_name(c, &name);
- if (err != DOM_NO_ERR) {
- dom_node_unref(c);
- return false;
- }
-
- if (!dom_string_caseless_lwc_isequal(name,
- corestring_lwc_param)) {
- /* The first non-param child is the start of
- * the alt html. Therefore, we should break
- * out of this loop. */
- dom_node_unref(c);
- break;
- }
-
- param = talloc(params, struct object_param);
- if (param == NULL) {
- dom_node_unref(c);
- return false;
- }
- param->name = NULL;
- param->value = NULL;
- param->type = NULL;
- param->valuetype = NULL;
- param->next = NULL;
-
- if (box_get_attribute(c, "name", param,
- &param->name) == false) {
- dom_node_unref(c);
- return false;
- }
-
- if (box_get_attribute(c, "value", param,
- &param->value) == false) {
- dom_node_unref(c);
- return false;
- }
-
- if (box_get_attribute(c, "type", param,
- &param->type) == false) {
- dom_node_unref(c);
- return false;
- }
-
- if (box_get_attribute(c, "valuetype", param,
- &param->valuetype) == false) {
- dom_node_unref(c);
- return false;
- }
-
- if (param->valuetype == NULL) {
- param->valuetype = talloc_strdup(param, "data");
- if (param->valuetype == NULL) {
- dom_node_unref(c);
- return false;
- }
- }
-
- param->next = params->params;
- params->params = param;
- }
-
- err = dom_node_get_next_sibling(c, &next);
- if (err != DOM_NO_ERR) {
- dom_node_unref(c);
- return false;
- }
-
- dom_node_unref(c);
- c = next;
- }
-
- box->object_params = params;
-
- /* start fetch (MIME type is ok or not specified) */
- box->flags |= IS_REPLACED;
- if (!html_fetch_object(content,
- params->data ? params->data : params->classid,
- box, CONTENT_ANY, content->base.available_width, 1000,
- false))
- return false;
-
- *convert_children = false;
- return true;
-}
-
-
-/**
- * Window subdivision [16.2.1].
- */
-
-bool box_frameset(BOX_SPECIAL_PARAMS)
-{
- bool ok;
-
- if (content->frameset) {
- NSLOG(netsurf, INFO, "Error: multiple framesets in document.");
- /* Don't convert children */
- if (convert_children)
- *convert_children = false;
- /* And ignore this spurious frameset */
- box->type = BOX_NONE;
- return true;
- }
-
- content->frameset = talloc_zero(content->bctx, struct content_html_frames);
- if (!content->frameset)
- return false;
-
- ok = box_create_frameset(content->frameset, n, content);
- if (ok)
- box->type = BOX_NONE;
-
- if (convert_children)
- *convert_children = false;
- return ok;
-}
-
-
-/**
- * Destructor for content_html_frames, for frame elements
- *
- * \param f The frame params being destroyed.
- * \return 0 to allow talloc to continue destroying the tree.
- */
-static int box_frames_talloc_destructor(struct content_html_frames *f)
-{
- if (f->url != NULL) {
- nsurl_unref(f->url);
- f->url = NULL;
- }
-
- return 0;
-}
-
-
-/**
- * Parse a multi-length-list, as defined by HTML 4.01.
- *
- * \param ds dom string to parse
- * \param count updated to number of entries
- * \return array of struct box_multi_length, or 0 on memory exhaustion
- */
-static struct frame_dimension *
-box_parse_multi_lengths(const dom_string *ds, unsigned int *count)
-{
- char *end;
- unsigned int i, n;
- struct frame_dimension *length;
- const char *s;
-
- s = dom_string_data(ds);
-
- for (i = 0, n = 1; s[i]; i++)
- if (s[i] == ',')
- n++;
-
- length = calloc(n, sizeof(struct frame_dimension));
- if (!length)
- return NULL;
-
- for (i = 0; i != n; i++) {
- while (ascii_is_space(*s)) {
- s++;
- }
- length[i].value = strtof(s, &end);
- if (length[i].value <= 0) {
- length[i].value = 1;
- }
- s = end;
- switch (*s) {
- case '%':
- length[i].unit = FRAME_DIMENSION_PERCENT;
- break;
- case '*':
- length[i].unit = FRAME_DIMENSION_RELATIVE;
- break;
- default:
- length[i].unit = FRAME_DIMENSION_PIXELS;
- break;
- }
- while (*s && *s != ',') {
- s++;
- }
- if (*s == ',') {
- s++;
- }
- }
-
- *count = n;
- return length;
-}
-
-
-bool box_create_frameset(struct content_html_frames *f, dom_node *n,
- html_content *content) {
- unsigned int row, col, index, i;
- unsigned int rows = 1, cols = 1;
- dom_string *s;
- dom_exception err;
- nsurl *url;
- struct frame_dimension *row_height = 0, *col_width = 0;
- dom_node *c, *next;
- struct content_html_frames *frame;
- bool default_border = true;
- colour default_border_colour = 0x000000;
-
- /* parse rows and columns */
- err = dom_element_get_attribute(n, corestring_dom_rows, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- row_height = box_parse_multi_lengths(s, &rows);
- dom_string_unref(s);
- if (row_height == NULL)
- return false;
- } else {
- row_height = calloc(1, sizeof(struct frame_dimension));
- if (row_height == NULL)
- return false;
- row_height->value = 100;
- row_height->unit = FRAME_DIMENSION_PERCENT;
- }
-
- err = dom_element_get_attribute(n, corestring_dom_cols, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- col_width = box_parse_multi_lengths(s, &cols);
- dom_string_unref(s);
- if (col_width == NULL) {
- free(row_height);
- return false;
- }
- } else {
- col_width = calloc(1, sizeof(struct frame_dimension));
- if (col_width == NULL) {
- free(row_height);
- return false;
- }
- col_width->value = 100;
- col_width->unit = FRAME_DIMENSION_PERCENT;
- }
-
- /* common extension: border="0|1" to control all children */
- err = dom_element_get_attribute(n, corestring_dom_border, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- if ((dom_string_data(s)[0] == '0') &&
- (dom_string_data(s)[1] == '\0'))
- default_border = false;
- dom_string_unref(s);
- }
-
- /* common extension: frameborder="yes|no" to control all children */
- err = dom_element_get_attribute(n, corestring_dom_frameborder, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- if (dom_string_caseless_lwc_isequal(s,
- corestring_lwc_no) == 0)
- default_border = false;
- dom_string_unref(s);
- }
-
- /* common extension: bordercolor="#RRGGBB|<named colour>" to control
- *all children */
- err = dom_element_get_attribute(n, corestring_dom_bordercolor, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- css_color color;
-
- if (nscss_parse_colour(dom_string_data(s), &color))
- default_border_colour = nscss_color_to_ns(color);
-
- dom_string_unref(s);
- }
-
- /* update frameset and create default children */
- f->cols = cols;
- f->rows = rows;
- f->scrolling = BW_SCROLLING_NO;
- f->children = talloc_array(content->bctx, struct content_html_frames,
- (rows * cols));
-
- talloc_set_destructor(f->children, box_frames_talloc_destructor);
-
- for (row = 0; row < rows; row++) {
- for (col = 0; col < cols; col++) {
- index = (row * cols) + col;
- frame = &f->children[index];
- frame->cols = 0;
- frame->rows = 0;
- frame->width = col_width[col];
- frame->height = row_height[row];
- frame->margin_width = 0;
- frame->margin_height = 0;
- frame->name = NULL;
- frame->url = NULL;
- frame->no_resize = false;
- frame->scrolling = BW_SCROLLING_AUTO;
- frame->border = default_border;
- frame->border_colour = default_border_colour;
- frame->children = NULL;
- }
- }
- free(col_width);
- free(row_height);
-
- /* create the frameset windows */
- err = dom_node_get_first_child(n, &c);
- if (err != DOM_NO_ERR)
- return false;
-
- for (row = 0; c != NULL && row < rows; row++) {
- for (col = 0; c != NULL && col < cols; col++) {
- while (c != NULL) {
- dom_node_type type;
- dom_string *name;
-
- err = dom_node_get_node_type(c, &type);
- if (err != DOM_NO_ERR) {
- dom_node_unref(c);
- return false;
- }
-
- err = dom_node_get_node_name(c, &name);
- if (err != DOM_NO_ERR) {
- dom_node_unref(c);
- return false;
- }
-
- if (type != DOM_ELEMENT_NODE ||
- (!dom_string_caseless_lwc_isequal(
- name,
- corestring_lwc_frame) &&
- !dom_string_caseless_lwc_isequal(
- name,
- corestring_lwc_frameset
- ))) {
- err = dom_node_get_next_sibling(c,
- &next);
- if (err != DOM_NO_ERR) {
- dom_string_unref(name);
- dom_node_unref(c);
- return false;
- }
-
- dom_string_unref(name);
- dom_node_unref(c);
- c = next;
- } else {
- /* Got a FRAME or FRAMESET element */
- dom_string_unref(name);
- break;
- }
- }
-
- if (c == NULL)
- break;
-
- /* get current frame */
- index = (row * cols) + col;
- frame = &f->children[index];
-
- /* nest framesets */
- err = dom_node_get_node_name(c, &s);
- if (err != DOM_NO_ERR) {
- dom_node_unref(c);
- return false;
- }
-
- if (dom_string_caseless_lwc_isequal(s,
- corestring_lwc_frameset)) {
- dom_string_unref(s);
- frame->border = 0;
- if (box_create_frameset(frame, c,
- content) == false) {
- dom_node_unref(c);
- return false;
- }
-
- err = dom_node_get_next_sibling(c, &next);
- if (err != DOM_NO_ERR) {
- dom_node_unref(c);
- return false;
- }
-
- dom_node_unref(c);
- c = next;
- continue;
- }
-
- dom_string_unref(s);
-
- /* get frame URL (not required) */
- url = NULL;
- err = dom_element_get_attribute(c, corestring_dom_src, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- box_extract_link(content, s, content->base_url,
- &url);
- dom_string_unref(s);
- }
-
- /* copy url */
- if (url != NULL) {
- /* no self-references */
- if (nsurl_compare(content->base_url, url,
- NSURL_COMPLETE) == false)
- frame->url = url;
- url = NULL;
- }
-
- /* fill in specified values */
- err = dom_element_get_attribute(c, corestring_dom_name, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- frame->name = talloc_strdup(content->bctx,
- dom_string_data(s));
- dom_string_unref(s);
- }
-
- dom_element_has_attribute(c, corestring_dom_noresize,
- &frame->no_resize);
-
- err = dom_element_get_attribute(c, corestring_dom_frameborder,
- &s);
- if (err == DOM_NO_ERR && s != NULL) {
- i = atoi(dom_string_data(s));
- frame->border = (i != 0);
- dom_string_unref(s);
- }
-
- err = dom_element_get_attribute(c, corestring_dom_scrolling, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- if (dom_string_caseless_lwc_isequal(s,
- corestring_lwc_yes))
- frame->scrolling = BW_SCROLLING_YES;
- else if (dom_string_caseless_lwc_isequal(s,
- corestring_lwc_no))
- frame->scrolling = BW_SCROLLING_NO;
- dom_string_unref(s);
- }
-
- err = dom_element_get_attribute(c, corestring_dom_marginwidth,
- &s);
- if (err == DOM_NO_ERR && s != NULL) {
- frame->margin_width = atoi(dom_string_data(s));
- dom_string_unref(s);
- }
-
- err = dom_element_get_attribute(c, corestring_dom_marginheight,
- &s);
- if (err == DOM_NO_ERR && s != NULL) {
- frame->margin_height = atoi(dom_string_data(s));
- dom_string_unref(s);
- }
-
- err = dom_element_get_attribute(c, corestring_dom_bordercolor,
- &s);
- if (err == DOM_NO_ERR && s != NULL) {
- css_color color;
-
- if (nscss_parse_colour(dom_string_data(s),
- &color))
- frame->border_colour =
- nscss_color_to_ns(color);
-
- dom_string_unref(s);
- }
-
- /* advance */
- err = dom_node_get_next_sibling(c, &next);
- if (err != DOM_NO_ERR) {
- dom_node_unref(c);
- return false;
- }
-
- dom_node_unref(c);
- c = next;
- }
- }
-
- /* If the last child wasn't a frame, we still need to unref it */
- if (c != NULL) {
- dom_node_unref(c);
- }
-
- return true;
-}
-
-
-/**
- * Destructor for content_html_iframe, for &lt;iframe&gt; elements
- *
- * \param f The iframe params being destroyed.
- * \return 0 to allow talloc to continue destroying the tree.
- */
-static int box_iframes_talloc_destructor(struct content_html_iframe *f)
-{
- if (f->url != NULL) {
- nsurl_unref(f->url);
- f->url = NULL;
- }
-
- return 0;
-}
-
-
-/**
- * Inline subwindow [16.5].
- */
-
-bool box_iframe(BOX_SPECIAL_PARAMS)
-{
- nsurl *url;
- dom_string *s;
- dom_exception err;
- struct content_html_iframe *iframe;
- int i;
-
- if (box->style && ns_computed_display(box->style,
- box_is_root(n)) == CSS_DISPLAY_NONE)
- return true;
-
- if (box->style && css_computed_visibility(box->style) ==
- CSS_VISIBILITY_HIDDEN)
- /* Don't create iframe discriptors for invisible iframes
- * TODO: handle hidden iframes at browser_window generation
- * time instead? */
- return true;
-
- /* get frame URL */
- err = dom_element_get_attribute(n, corestring_dom_src, &s);
- if (err != DOM_NO_ERR || s == NULL)
- return true;
- if (box_extract_link(content, s, content->base_url, &url) == false) {
- dom_string_unref(s);
- return false;
- }
- dom_string_unref(s);
- if (url == NULL)
- return true;
-
- /* don't include ourself */
- if (nsurl_compare(content->base_url, url, NSURL_COMPLETE)) {
- nsurl_unref(url);
- return true;
- }
-
- /* create a new iframe */
- iframe = talloc(content->bctx, struct content_html_iframe);
- if (iframe == NULL) {
- nsurl_unref(url);
- return false;
- }
-
- talloc_set_destructor(iframe, box_iframes_talloc_destructor);
-
- iframe->box = box;
- iframe->margin_width = 0;
- iframe->margin_height = 0;
- iframe->name = NULL;
- iframe->url = url;
- iframe->scrolling = BW_SCROLLING_AUTO;
- iframe->border = true;
-
- /* Add this iframe to the linked list of iframes */
- iframe->next = content->iframe;
- content->iframe = iframe;
-
- /* fill in specified values */
- err = dom_element_get_attribute(n, corestring_dom_name, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- iframe->name = talloc_strdup(content->bctx, dom_string_data(s));
- dom_string_unref(s);
- }
-
- err = dom_element_get_attribute(n, corestring_dom_frameborder, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- i = atoi(dom_string_data(s));
- iframe->border = (i != 0);
- dom_string_unref(s);
- }
-
- err = dom_element_get_attribute(n, corestring_dom_bordercolor, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- css_color color;
-
- if (nscss_parse_colour(dom_string_data(s), &color))
- iframe->border_colour = nscss_color_to_ns(color);
-
- dom_string_unref(s);
- }
-
- err = dom_element_get_attribute(n, corestring_dom_scrolling, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- if (dom_string_caseless_lwc_isequal(s,
- corestring_lwc_yes))
- iframe->scrolling = BW_SCROLLING_YES;
- else if (dom_string_caseless_lwc_isequal(s,
- corestring_lwc_no))
- iframe->scrolling = BW_SCROLLING_NO;
- dom_string_unref(s);
- }
-
- err = dom_element_get_attribute(n, corestring_dom_marginwidth, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- iframe->margin_width = atoi(dom_string_data(s));
- dom_string_unref(s);
- }
-
- err = dom_element_get_attribute(n, corestring_dom_marginheight, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- iframe->margin_height = atoi(dom_string_data(s));
- dom_string_unref(s);
- }
-
- /* box */
- assert(box->style);
- box->flags |= IFRAME;
- box->flags |= IS_REPLACED;
-
- /* Showing iframe, so don't show alternate content */
- if (convert_children)
- *convert_children = false;
- return true;
-}
-
-
-/**
- * Helper function for adding textarea widget to box.
- *
- * This is a load of hacks to ensure boxes replaced with textareas
- * can be handled by the layout code.
- */
-
-static bool box_input_text(html_content *html, struct box *box,
- struct dom_node *node)
-{
- struct box *inline_container, *inline_box;
-
- box->type = BOX_INLINE_BLOCK;
-
- inline_container = box_create(NULL, 0, false, 0, 0, 0, 0, html->bctx);
- if (!inline_container)
- return false;
- inline_container->type = BOX_INLINE_CONTAINER;
- inline_box = box_create(NULL, box->style, false, 0, 0, box->title, 0,
- html->bctx);
- if (!inline_box)
- return false;
- inline_box->type = BOX_TEXT;
- inline_box->text = talloc_strdup(html->bctx, "");
-
- box_add_child(inline_container, inline_box);
- box_add_child(box, inline_container);
-
- return box_textarea_create_textarea(html, box, node);
-}
-
-
-/**
- * Form control [17.4].
- */
-
-bool box_input(BOX_SPECIAL_PARAMS)
-{
- struct form_control *gadget = NULL;
- dom_string *type = NULL;
- dom_exception err;
- nsurl *url;
- nserror error;
-
- dom_element_get_attribute(n, corestring_dom_type, &type);
-
- gadget = html_forms_get_control_for_node(content->forms, n);
- if (gadget == NULL)
- goto no_memory;
- box->gadget = gadget;
- box->flags |= IS_REPLACED;
- gadget->box = box;
- gadget->html = content;
-
- if (type && dom_string_caseless_lwc_isequal(type,
- corestring_lwc_password)) {
- if (box_input_text(content, box, n) == false)
- goto no_memory;
-
- } else if (type && dom_string_caseless_lwc_isequal(type,
- corestring_lwc_file)) {
- box->type = BOX_INLINE_BLOCK;
-
- } else if (type && dom_string_caseless_lwc_isequal(type,
- corestring_lwc_hidden)) {
- /* no box for hidden inputs */
- box->type = BOX_NONE;
-
- } else if (type &&
- (dom_string_caseless_lwc_isequal(type,
- corestring_lwc_checkbox) ||
- dom_string_caseless_lwc_isequal(type,
- corestring_lwc_radio))) {
-
- } else if (type &&
- (dom_string_caseless_lwc_isequal(type,
- corestring_lwc_submit) ||
- dom_string_caseless_lwc_isequal(type,
- corestring_lwc_reset) ||
- dom_string_caseless_lwc_isequal(type,
- corestring_lwc_button))) {
- struct box *inline_container, *inline_box;
-
- if (box_button(n, content, box, 0) == false)
- goto no_memory;
-
- inline_container = box_create(NULL, 0, false, 0, 0, 0, 0,
- content->bctx);
- if (inline_container == NULL)
- goto no_memory;
-
- inline_container->type = BOX_INLINE_CONTAINER;
-
- inline_box = box_create(NULL, box->style, false, 0, 0,
- box->title, 0, content->bctx);
- if (inline_box == NULL)
- goto no_memory;
-
- inline_box->type = BOX_TEXT;
-
- if (box->gadget->value != NULL)
- inline_box->text = talloc_strdup(content->bctx,
- box->gadget->value);
- else if (box->gadget->type == GADGET_SUBMIT)
- inline_box->text = talloc_strdup(content->bctx,
- messages_get("Form_Submit"));
- else if (box->gadget->type == GADGET_RESET)
- inline_box->text = talloc_strdup(content->bctx,
- messages_get("Form_Reset"));
- else
- inline_box->text = talloc_strdup(content->bctx,
- "Button");
-
- if (inline_box->text == NULL)
- goto no_memory;
-
- inline_box->length = strlen(inline_box->text);
-
- box_add_child(inline_container, inline_box);
-
- box_add_child(box, inline_container);
-
- } else if (type && dom_string_caseless_lwc_isequal(type,
- corestring_lwc_image)) {
- gadget->type = GADGET_IMAGE;
-
- if (box->style && ns_computed_display(box->style,
- box_is_root(n)) != CSS_DISPLAY_NONE &&
- nsoption_bool(foreground_images) == true) {
- dom_string *s;
-
- err = dom_element_get_attribute(n, corestring_dom_src, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- error = nsurl_join(content->base_url,
- dom_string_data(s), &url);
- dom_string_unref(s);
- if (error != NSERROR_OK)
- goto no_memory;
-
- /* if url is equivalent to the parent's url,
- * we've got infinite inclusion. stop it here
- */
- if (nsurl_compare(url, content->base_url,
- NSURL_COMPLETE) == false) {
- if (!html_fetch_object(content, url,
- box, image_types,
- content->base.
- available_width,
- 1000, false)) {
- nsurl_unref(url);
- goto no_memory;
- }
- }
- nsurl_unref(url);
- }
- }
- } else {
- /* the default type is "text" */
- if (box_input_text(content, box, n) == false)
- goto no_memory;
- }
-
- if (type)
- dom_string_unref(type);
-
- *convert_children = false;
- return true;
-
-no_memory:
- if (type)
- dom_string_unref(type);
-
- return false;
-}
-
-
-/**
- * Push button [17.5].
- */
-
-bool box_button(BOX_SPECIAL_PARAMS)
-{
- struct form_control *gadget;
-
- gadget = html_forms_get_control_for_node(content->forms, n);
- if (!gadget)
- return false;
-
- gadget->html = content;
- box->gadget = gadget;
- box->flags |= IS_REPLACED;
- gadget->box = box;
-
- box->type = BOX_INLINE_BLOCK;
-
- /* Just render the contents */
-
- return true;
-}
-
-
-/**
- * Option selector [17.6].
- */
-
-bool box_select(BOX_SPECIAL_PARAMS)
-{
- struct box *inline_container;
- struct box *inline_box;
- struct form_control *gadget;
- dom_node *c, *c2;
- dom_node *next, *next2;
- dom_exception err;
-
- gadget = html_forms_get_control_for_node(content->forms, n);
- if (gadget == NULL)
- return false;
-
- gadget->html = content;
- err = dom_node_get_first_child(n, &c);
- if (err != DOM_NO_ERR) {
- form_free_control(gadget);
- return false;
- }
-
- while (c != NULL) {
- dom_string *name;
-
- err = dom_node_get_node_name(c, &name);
- if (err != DOM_NO_ERR) {
- dom_node_unref(c);
- form_free_control(gadget);
- return false;
- }
-
- if (dom_string_caseless_lwc_isequal(name,
- corestring_lwc_option)) {
- dom_string_unref(name);
-
- if (box_select_add_option(gadget, c) == false) {
- dom_node_unref(c);
- form_free_control(gadget);
- return false;
- }
- } else if (dom_string_caseless_lwc_isequal(name,
- corestring_lwc_optgroup)) {
- dom_string_unref(name);
-
- err = dom_node_get_first_child(c, &c2);
- if (err != DOM_NO_ERR) {
- dom_node_unref(c);
- form_free_control(gadget);
- return false;
- }
-
- while (c2 != NULL) {
- dom_string *c2_name;
-
- err = dom_node_get_node_name(c2, &c2_name);
- if (err != DOM_NO_ERR) {
- dom_node_unref(c2);
- dom_node_unref(c);
- form_free_control(gadget);
- return false;
- }
-
- if (dom_string_caseless_lwc_isequal(c2_name,
- corestring_lwc_option)) {
- dom_string_unref(c2_name);
-
- if (box_select_add_option(gadget,
- c2) == false) {
- dom_node_unref(c2);
- dom_node_unref(c);
- return false;
- }
- } else {
- dom_string_unref(c2_name);
- }
-
- err = dom_node_get_next_sibling(c2, &next2);
- if (err != DOM_NO_ERR) {
- dom_node_unref(c2);
- dom_node_unref(c);
- return false;
- }
-
- dom_node_unref(c2);
- c2 = next2;
- }
- } else {
- dom_string_unref(name);
- }
-
- err = dom_node_get_next_sibling(c, &next);
- if (err != DOM_NO_ERR) {
- dom_node_unref(c);
- form_free_control(gadget);
- return false;
- }
-
- dom_node_unref(c);
- c = next;
- }
-
- if (gadget->data.select.num_items == 0) {
- /* no options: ignore entire select */
- form_free_control(gadget);
- return true;
- }
-
- box->type = BOX_INLINE_BLOCK;
- box->gadget = gadget;
- box->flags |= IS_REPLACED;
- gadget->box = box;
-
- inline_container = box_create(NULL, 0, false, 0, 0, 0, 0, content->bctx);
- if (inline_container == NULL)
- goto no_memory;
- inline_container->type = BOX_INLINE_CONTAINER;
- inline_box = box_create(NULL, box->style, false, 0, 0, box->title, 0,
- content->bctx);
- if (inline_box == NULL)
- goto no_memory;
- inline_box->type = BOX_TEXT;
- box_add_child(inline_container, inline_box);
- box_add_child(box, inline_container);
-
- if (gadget->data.select.multiple == false &&
- gadget->data.select.num_selected == 0) {
- gadget->data.select.current = gadget->data.select.items;
- gadget->data.select.current->initial_selected =
- gadget->data.select.current->selected = true;
- gadget->data.select.num_selected = 1;
- dom_html_option_element_set_selected(
- gadget->data.select.current->node, true);
- }
-
- if (gadget->data.select.num_selected == 0)
- inline_box->text = talloc_strdup(content->bctx,
- messages_get("Form_None"));
- else if (gadget->data.select.num_selected == 1)
- inline_box->text = talloc_strdup(content->bctx,
- gadget->data.select.current->text);
- else
- inline_box->text = talloc_strdup(content->bctx,
- messages_get("Form_Many"));
- if (inline_box->text == NULL)
- goto no_memory;
-
- inline_box->length = strlen(inline_box->text);
-
- *convert_children = false;
- return true;
-
-no_memory:
- return false;
-}
-
-
-/**
- * Add an option to a form select control (helper function for box_select()).
- *
- * \param control select containing the &lt;option&gt;
- * \param n xml element node for &lt;option&gt;
- * \return true on success, false on memory exhaustion
- */
-
-bool box_select_add_option(struct form_control *control, dom_node *n)
-{
- char *value = NULL;
- char *text = NULL;
- char *text_nowrap = NULL;
- bool selected;
- dom_string *content, *s;
- dom_exception err;
-
- err = dom_node_get_text_content(n, &content);
- if (err != DOM_NO_ERR)
- return false;
-
- if (content != NULL) {
- text = squash_whitespace(dom_string_data(content));
- dom_string_unref(content);
- } else {
- text = strdup("");
- }
-
- if (text == NULL)
- goto no_memory;
-
- err = dom_element_get_attribute(n, corestring_dom_value, &s);
- if (err == DOM_NO_ERR && s != NULL) {
- value = strdup(dom_string_data(s));
- dom_string_unref(s);
- } else {
- value = strdup(text);
- }
-
- if (value == NULL)
- goto no_memory;
-
- dom_element_has_attribute(n, corestring_dom_selected, &selected);
-
- /* replace spaces/TABs with hard spaces to prevent line wrapping */
- text_nowrap = cnv_space2nbsp(text);
- if (text_nowrap == NULL)
- goto no_memory;
-
- if (form_add_option(control, value, text_nowrap, selected, n) == false)
- goto no_memory;
-
- free(text);
-
- return true;
-
-no_memory:
- free(value);
- free(text);
- free(text_nowrap);
- return false;
-}
-
-
-/**
- * Multi-line text field [17.7].
- */
-
-bool box_textarea(BOX_SPECIAL_PARAMS)
-{
- /* Get the form_control for the DOM node */
- box->gadget = html_forms_get_control_for_node(content->forms, n);
- if (box->gadget == NULL)
- return false;
-
- box->flags |= IS_REPLACED;
- box->gadget->html = content;
- box->gadget->box = box;
-
- if (!box_input_text(content, box, n))
- return false;
-
- *convert_children = false;
- return true;
-}
-
-
-/**
- * Embedded object (not in any HTML specification:
- * see http://wp.netscape.com/assist/net_sites/new_html3_prop.html )
- */
-
-bool box_embed(BOX_SPECIAL_PARAMS)
-{
- struct object_params *params;
- struct object_param *param;
- dom_namednodemap *attrs;
- unsigned long idx;
- uint32_t num_attrs;
- dom_string *src;
- dom_exception err;
-
- if (box->style && ns_computed_display(box->style,
- box_is_root(n)) == CSS_DISPLAY_NONE)
- return true;
-
- params = talloc(content->bctx, struct object_params);
- if (params == NULL)
- return false;
-
- talloc_set_destructor(params, box_object_talloc_destructor);
-
- params->data = NULL;
- params->type = NULL;
- params->codetype = NULL;
- params->codebase = NULL;
- params->classid = NULL;
- params->params = NULL;
-
- /* src is a URL */
- err = dom_element_get_attribute(n, corestring_dom_src, &src);
- if (err != DOM_NO_ERR || src == NULL)
- return true;
- if (box_extract_link(content, src, content->base_url,
- &params->data) == false) {
- dom_string_unref(src);
- return false;
- }
-
- dom_string_unref(src);
-
- if (params->data == NULL)
- return true;
-
- /* Don't include ourself */
- if (nsurl_compare(content->base_url, params->data, NSURL_COMPLETE))
- return true;
-
- /* add attributes as parameters to linked list */
- err = dom_node_get_attributes(n, &attrs);
- if (err != DOM_NO_ERR)
- return false;
-
- err = dom_namednodemap_get_length(attrs, &num_attrs);
- if (err != DOM_NO_ERR) {
- dom_namednodemap_unref(attrs);
- return false;
- }
-
- for (idx = 0; idx < num_attrs; idx++) {
- dom_attr *attr;
- dom_string *name, *value;
-
- err = dom_namednodemap_item(attrs, idx, (void *) &attr);
- if (err != DOM_NO_ERR) {
- dom_namednodemap_unref(attrs);
- return false;
- }
-
- err = dom_attr_get_name(attr, &name);
- if (err != DOM_NO_ERR) {
- dom_namednodemap_unref(attrs);
- return false;
- }
-
- if (dom_string_caseless_lwc_isequal(name, corestring_lwc_src)) {
- dom_string_unref(name);
- continue;
- }
-
- err = dom_attr_get_value(attr, &value);
- if (err != DOM_NO_ERR) {
- dom_string_unref(name);
- dom_namednodemap_unref(attrs);
- return false;
- }
-
- param = talloc(content->bctx, struct object_param);
- if (param == NULL) {
- dom_string_unref(value);
- dom_string_unref(name);
- dom_namednodemap_unref(attrs);
- return false;
- }
-
- param->name = talloc_strdup(content->bctx, dom_string_data(name));
- param->value = talloc_strdup(content->bctx, dom_string_data(value));
- param->type = NULL;
- param->valuetype = talloc_strdup(content->bctx, "data");
- param->next = NULL;
-
- dom_string_unref(value);
- dom_string_unref(name);
-
- if (param->name == NULL || param->value == NULL ||
- param->valuetype == NULL) {
- dom_namednodemap_unref(attrs);
- return false;
- }
-
- param->next = params->params;
- params->params = param;
- }
-
- dom_namednodemap_unref(attrs);
-
- box->object_params = params;
-
- /* start fetch */
- box->flags |= IS_REPLACED;
- return html_fetch_object(content, params->data, box, CONTENT_ANY,
- content->base.available_width, 1000, false);
-}
-
-/**
- * \}
- */
-
-
-/**
- * Get the value of an XML element's attribute.
- *
- * \param n xmlNode, of type XML_ELEMENT_NODE
- * \param attribute name of attribute
- * \param context talloc context for result buffer
- * \param value updated to value, if the attribute is present
- * \return true on success, false if attribute present but memory exhausted
- *
- * Note that returning true does not imply that the attribute was found. If the
- * attribute was not found, *value will be unchanged.
- */
-
-bool box_get_attribute(dom_node *n, const char *attribute,
- void *context, char **value)
-{
- char *result;
- dom_string *attr, *attr_name;
- dom_exception err;
-
- err = dom_string_create_interned((const uint8_t *) attribute,
- strlen(attribute), &attr_name);
- if (err != DOM_NO_ERR)
- return false;
-
- err = dom_element_get_attribute(n, attr_name, &attr);
- if (err != DOM_NO_ERR) {
- dom_string_unref(attr_name);
- return false;
- }
-
- dom_string_unref(attr_name);
-
- if (attr != NULL) {
- result = talloc_strdup(context, dom_string_data(attr));
-
- dom_string_unref(attr);
-
- if (result == NULL)
- return false;
-
- *value = result;
- }
-
- return true;
-}
-
-
-/* exported function documented in render/box.h */
-bool
-box_extract_link(const html_content *content,
- const dom_string *dsrel,
- nsurl *base,
- nsurl **result)
-{
- char *s, *s1, *apos0 = 0, *apos1 = 0, *quot0 = 0, *quot1 = 0;
- unsigned int i, j, end;
- nserror error;
- const char *rel;
-
- rel = dom_string_data(dsrel);
-
- s1 = s = malloc(3 * strlen(rel) + 1);
- if (!s)
- return false;
-
- /* copy to s, removing white space and control characters */
- for (i = 0; rel[i] && ascii_is_space(rel[i]); i++)
- ;
- for (end = strlen(rel);
- (end != i) && ascii_is_space(rel[end - 1]);
- end--)
- ;
- for (j = 0; i != end; i++) {
- if ((unsigned char) rel[i] < 0x20) {
- ; /* skip control characters */
- } else if (rel[i] == ' ') {
- s[j++] = '%';
- s[j++] = '2';
- s[j++] = '0';
- } else {
- s[j++] = rel[i];
- }
- }
- s[j] = 0;
-
- if (content->enable_scripting == false) {
- /* extract first quoted string out of "javascript:" link */
- if (strncmp(s, "javascript:", 11) == 0) {
- apos0 = strchr(s, '\'');
- if (apos0)
- apos1 = strchr(apos0 + 1, '\'');
- quot0 = strchr(s, '"');
- if (quot0)
- quot1 = strchr(quot0 + 1, '"');
- if (apos0 && apos1 &&
- (!quot0 || !quot1 || apos0 < quot0)) {
- *apos1 = 0;
- s1 = apos0 + 1;
- } else if (quot0 && quot1) {
- *quot1 = 0;
- s1 = quot0 + 1;
- }
- }
- }
-
- /* construct absolute URL */
- error = nsurl_join(base, s1, result);
- free(s);
- if (error != NSERROR_OK) {
- *result = NULL;
- return false;
- }
-
- return true;
-}
-
-
-
diff --git a/render/form.c b/render/form.c
deleted file mode 100644
index 432002564..000000000
--- a/render/form.c
+++ /dev/null
@@ -1,1895 +0,0 @@
-/*
- * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
- * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
- * Copyright 2004 John Tytgat <joty@netsurf-browser.org>
- * Copyright 2005-9 John-Mark Bell <jmb@netsurf-browser.org>
- * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
- * Copyright 2010 Michael Drake <tlsa@netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- * Form handling functions (implementation).
- */
-
-#include <assert.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-#include <dom/dom.h>
-
-#include "utils/corestrings.h"
-#include "utils/log.h"
-#include "utils/messages.h"
-#include "utils/talloc.h"
-#include "utils/url.h"
-#include "utils/utf8.h"
-#include "utils/ascii.h"
-#include "netsurf/browser_window.h"
-#include "netsurf/mouse.h"
-#include "netsurf/plotters.h"
-#include "netsurf/misc.h"
-#include "content/fetch.h"
-#include "content/hlcache.h"
-#include "css/utils.h"
-#include "desktop/knockout.h"
-#include "desktop/scrollbar.h"
-#include "desktop/textarea.h"
-#include "desktop/gui_internal.h"
-
-#include "render/box.h"
-#include "render/font.h"
-#include "render/form_internal.h"
-#include "render/html.h"
-#include "render/html_internal.h"
-#include "render/layout.h"
-
-#define MAX_SELECT_HEIGHT 210
-#define SELECT_LINE_SPACING 0.2
-#define SELECT_BORDER_WIDTH 1
-#define SELECT_SELECTED_COLOUR 0xDB9370
-
-struct form_select_menu {
- int line_height;
- int width, height;
- struct scrollbar *scrollbar;
- int f_size;
- bool scroll_capture;
- select_menu_redraw_callback callback;
- void *client_data;
- struct content *c;
-};
-
-static plot_style_t plot_style_fill_selected = {
- .fill_type = PLOT_OP_TYPE_SOLID,
- .fill_colour = SELECT_SELECTED_COLOUR,
-};
-
-static plot_font_style_t plot_fstyle_entry = {
- .family = PLOT_FONT_FAMILY_SANS_SERIF,
- .weight = 400,
- .flags = FONTF_NONE,
- .background = 0xffffff,
- .foreground = 0x000000,
-};
-
-static char *form_acceptable_charset(struct form *form);
-static char *form_encode_item(const char *item, uint32_t len, const char *charset,
- const char *fallback);
-static void form_select_menu_clicked(struct form_control *control,
- int x, int y);
-static void form_select_menu_scroll_callback(void *client_data,
- struct scrollbar_msg_data *scrollbar_data);
-
-/* exported interface documented in render/form_internal.h */
-struct form *form_new(void *node, const char *action, const char *target,
- form_method method, const char *charset,
- const char *doc_charset)
-{
- struct form *form;
-
- form = calloc(1, sizeof *form);
- if (!form)
- return NULL;
-
- form->action = strdup(action != NULL ? action : "");
- if (form->action == NULL) {
- free(form);
- return NULL;
- }
-
- form->target = target != NULL ? strdup(target) : NULL;
- if (target != NULL && form->target == NULL) {
- free(form->action);
- free(form);
- return NULL;
- }
-
- form->method = method;
-
- form->accept_charsets = charset != NULL ? strdup(charset) : NULL;
- if (charset != NULL && form->accept_charsets == NULL) {
- free(form->target);
- free(form->action);
- free(form);
- return NULL;
- }
-
- form->document_charset = doc_charset != NULL ? strdup(doc_charset)
- : NULL;
- if (doc_charset && form->document_charset == NULL) {
- free(form->accept_charsets);
- free(form->target);
- free(form->action);
- free(form);
- return NULL;
- }
-
- form->node = node;
-
- return form;
-}
-
-
-/* exported interface documented in render/form_internal.h */
-void form_free(struct form *form)
-{
- struct form_control *c, *d;
-
- for (c = form->controls; c != NULL; c = d) {
- d = c->next;
-
- form_free_control(c);
- }
-
- free(form->action);
- free(form->target);
- free(form->accept_charsets);
- free(form->document_charset);
-
- free(form);
-}
-
-/* exported interface documented in render/form_internal.h */
-struct form_control *form_new_control(void *node, form_control_type type)
-{
- struct form_control *control;
-
- control = calloc(1, sizeof *control);
- if (control == NULL)
- return NULL;
-
- control->node = node;
- control->type = type;
-
- return control;
-}
-
-
-/**
- * Add a control to the list of controls in a form.
- *
- * \param form The form to add the control to
- * \param control The control to add
- */
-void form_add_control(struct form *form, struct form_control *control)
-{
- if (form == NULL) {
- return;
- }
-
- control->form = form;
-
- if (form->controls != NULL) {
- assert(form->last_control);
-
- form->last_control->next = control;
- control->prev = form->last_control;
- control->next = NULL;
- form->last_control = control;
- } else {
- form->controls = form->last_control = control;
- }
-}
-
-
-/**
- * Free a struct form_control.
- *
- * \param control structure to free
- */
-void form_free_control(struct form_control *control)
-{
- struct form_control *c;
- assert(control != NULL);
-
- NSLOG(netsurf, INFO, "Control:%p name:%p value:%p initial:%p",
- control, control->name, control->value, control->initial_value);
- free(control->name);
- free(control->value);
- free(control->initial_value);
-
- if (control->type == GADGET_SELECT) {
- struct form_option *option, *next;
-
- for (option = control->data.select.items; option;
- option = next) {
- next = option->next;
- NSLOG(netsurf, INFO,
- "select option:%p text:%p value:%p", option,
- option->text, option->value);
- free(option->text);
- free(option->value);
- free(option);
- }
- if (control->data.select.menu != NULL) {
- form_free_select_menu(control);
- }
- }
-
- if (control->type == GADGET_TEXTAREA ||
- control->type == GADGET_TEXTBOX ||
- control->type == GADGET_PASSWORD) {
-
- if (control->data.text.initial != NULL) {
- dom_string_unref(control->data.text.initial);
- }
-
- if (control->data.text.ta != NULL) {
- textarea_destroy(control->data.text.ta);
- }
- }
-
- /* unlink the control from the form */
- if (control->form != NULL) {
- for (c = control->form->controls; c != NULL; c = c->next) {
- if (c->next == control) {
- c->next = control->next;
- if (control->form->last_control == control)
- control->form->last_control = c;
- break;
- }
- if (c == control) {
- /* can only happen if control was first control */
- control->form->controls = control->next;
- if (control->form->last_control == control)
- control->form->controls =
- control->form->last_control = NULL;
- break;
- }
- }
- }
-
- free(control);
-}
-
-
-/**
- * Add an option to a form select control.
- *
- * \param control form control of type GADGET_SELECT
- * \param value value of option, used directly (not copied)
- * \param text text for option, used directly (not copied)
- * \param selected this option is selected
- * \param node the DOM node this option is associated with
- * \return true on success, false on memory exhaustion
- */
-bool form_add_option(struct form_control *control, char *value, char *text,
- bool selected, void *node)
-{
- struct form_option *option;
-
- assert(control);
- assert(control->type == GADGET_SELECT);
-
- option = calloc(1, sizeof *option);
- if (!option)
- return false;
-
- option->value = value;
- option->text = text;
-
- /* add to linked list */
- if (control->data.select.items == 0)
- control->data.select.items = option;
- else
- control->data.select.last_item->next = option;
- control->data.select.last_item = option;
-
- /* set selected */
- if (selected && (control->data.select.num_selected == 0 ||
- control->data.select.multiple)) {
- option->selected = option->initial_selected = true;
- control->data.select.num_selected++;
- control->data.select.current = option;
- }
-
- control->data.select.num_items++;
-
- option->node = node;
-
- return true;
-}
-
-
-/* exported interface documented in render/form_internal.h */
-bool form_successful_controls_dom(struct form *_form,
- struct form_control *_submit_button,
- struct fetch_multipart_data **successful_controls)
-{
- dom_html_form_element *form = _form->node;
- dom_html_element *submit_button = (_submit_button != NULL) ? _submit_button->node : NULL;
- dom_html_collection *form_elements = NULL;
- dom_html_options_collection *options = NULL;
- dom_node *form_element = NULL, *option_element = NULL;
- dom_exception err;
- dom_string *nodename = NULL, *inputname = NULL, *inputvalue = NULL, *inputtype = NULL;
- struct fetch_multipart_data sentinel, *last_success, *success_new;
- bool had_submit = false, element_disabled, checked;
- char *charset, *rawfile_temp = NULL, *basename;
- uint32_t index, element_count;
- struct image_input_coords *coords;
-
- last_success = &sentinel;
- sentinel.next = NULL;
-
- /** \todo Replace this call with something DOMish */
- charset = form_acceptable_charset(_form);
- if (charset == NULL) {
- NSLOG(netsurf, INFO, "failed to find charset");
- return false;
- }
-
-#define ENCODE_ITEM(i) (((i) == NULL) ? ( \
- form_encode_item("", 0, charset, _form->document_charset) \
- ):( \
- form_encode_item(dom_string_data(i), dom_string_byte_length(i), \
- charset, _form->document_charset) \
- ))
-
- err = dom_html_form_element_get_elements(form, &form_elements);
-
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO, "Could not get form elements");
- goto dom_no_memory;
- }
-
-
- err = dom_html_collection_get_length(form_elements, &element_count);
-
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO, "Could not get form element count");
- goto dom_no_memory;
- }
-
- for (index = 0; index < element_count; index++) {
- if (form_element != NULL) {
- dom_node_unref(form_element);
- form_element = NULL;
- }
- if (nodename != NULL) {
- dom_string_unref(nodename);
- nodename = NULL;
- }
- if (inputname != NULL) {
- dom_string_unref(inputname);
- inputname = NULL;
- }
- if (inputvalue != NULL) {
- dom_string_unref(inputvalue);
- inputvalue = NULL;
- }
- if (inputtype != NULL) {
- dom_string_unref(inputtype);
- inputtype = NULL;
- }
- if (options != NULL) {
- dom_html_options_collection_unref(options);
- options = NULL;
- }
- err = dom_html_collection_item(form_elements,
- index, &form_element);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not retrieve form element %d", index);
- goto dom_no_memory;
- }
-
- /* Form elements are one of:
- * HTMLButtonElement
- * HTMLInputElement
- * HTMLTextAreaElement
- * HTMLSelectElement
- */
- err = dom_node_get_node_name(form_element, &nodename);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO, "Could not get node name");
- goto dom_no_memory;
- }
-
- if (dom_string_isequal(nodename, corestring_dom_TEXTAREA)) {
- err = dom_html_text_area_element_get_disabled(
- (dom_html_text_area_element *)form_element,
- &element_disabled);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get text area disabled property");
- goto dom_no_memory;
- }
- err = dom_html_text_area_element_get_name(
- (dom_html_text_area_element *)form_element,
- &inputname);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get text area name property");
- goto dom_no_memory;
- }
- } else if (dom_string_isequal(nodename, corestring_dom_SELECT)) {
- err = dom_html_select_element_get_disabled(
- (dom_html_select_element *)form_element,
- &element_disabled);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get select disabled property");
- goto dom_no_memory;
- }
- err = dom_html_select_element_get_name(
- (dom_html_select_element *)form_element,
- &inputname);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get select name property");
- goto dom_no_memory;
- }
- } else if (dom_string_isequal(nodename, corestring_dom_INPUT)) {
- err = dom_html_input_element_get_disabled(
- (dom_html_input_element *)form_element,
- &element_disabled);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get input disabled property");
- goto dom_no_memory;
- }
- err = dom_html_input_element_get_name(
- (dom_html_input_element *)form_element,
- &inputname);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get input name property");
- goto dom_no_memory;
- }
- } else if (dom_string_isequal(nodename, corestring_dom_BUTTON)) {
- err = dom_html_button_element_get_disabled(
- (dom_html_button_element *)form_element,
- &element_disabled);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get button disabled property");
- goto dom_no_memory;
- }
- err = dom_html_button_element_get_name(
- (dom_html_button_element *)form_element,
- &inputname);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get button name property");
- goto dom_no_memory;
- }
- } else {
- /* Unknown element type came through! */
- NSLOG(netsurf, INFO, "Unknown element type: %*s",
- (int)dom_string_byte_length(nodename),
- dom_string_data(nodename));
- goto dom_no_memory;
- }
- if (element_disabled)
- continue;
- if (inputname == NULL)
- continue;
-
- if (dom_string_isequal(nodename, corestring_dom_TEXTAREA)) {
- err = dom_html_text_area_element_get_value(
- (dom_html_text_area_element *)form_element,
- &inputvalue);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get text area content");
- goto dom_no_memory;
- }
- } else if (dom_string_isequal(nodename, corestring_dom_SELECT)) {
- uint32_t options_count, option_index;
- err = dom_html_select_element_get_options(
- (dom_html_select_element *)form_element,
- &options);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get select options collection");
- goto dom_no_memory;
- }
- err = dom_html_options_collection_get_length(
- options, &options_count);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get select options collection length");
- goto dom_no_memory;
- }
- for(option_index = 0; option_index < options_count;
- ++option_index) {
- bool selected;
- if (option_element != NULL) {
- dom_node_unref(option_element);
- option_element = NULL;
- }
- if (inputvalue != NULL) {
- dom_string_unref(inputvalue);
- inputvalue = NULL;
- }
- err = dom_html_options_collection_item(
- options, option_index, &option_element);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get options item %d",
- option_index);
- goto dom_no_memory;
- }
- err = dom_html_option_element_get_selected(
- (dom_html_option_element *)option_element,
- &selected);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get option selected property");
- goto dom_no_memory;
- }
- if (!selected)
- continue;
- err = dom_html_option_element_get_value(
- (dom_html_option_element *)option_element,
- &inputvalue);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get option value");
- goto dom_no_memory;
- }
-
- success_new = calloc(1, sizeof(*success_new));
- if (success_new == NULL) {
- NSLOG(netsurf, INFO,
- "Could not allocate data for option");
- goto dom_no_memory;
- }
-
- last_success->next = success_new;
- last_success = success_new;
-
- success_new->name = ENCODE_ITEM(inputname);
- if (success_new->name == NULL) {
- NSLOG(netsurf, INFO,
- "Could not encode name for option");
- goto dom_no_memory;
- }
- success_new->value = ENCODE_ITEM(inputvalue);
- if (success_new->value == NULL) {
- NSLOG(netsurf, INFO,
- "Could not encode value for option");
- goto dom_no_memory;
- }
- }
- continue;
- } else if (dom_string_isequal(nodename, corestring_dom_BUTTON)) {
- err = dom_html_button_element_get_type(
- (dom_html_button_element *) form_element,
- &inputtype);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get button element type");
- goto dom_no_memory;
- }
- if (dom_string_caseless_isequal(
- inputtype, corestring_dom_submit)) {
-
- if (submit_button == NULL && !had_submit) {
- /* no button used, and first submit
- * node found, so use it
- */
- had_submit = true;
- } else if ((dom_node *)submit_button !=
- (dom_node *)form_element) {
- continue;
- }
-
- err = dom_html_button_element_get_value(
- (dom_html_button_element *)form_element,
- &inputvalue);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get submit button value");
- goto dom_no_memory;
- }
- /* Drop through to report successful button */
- } else {
- continue;
- }
- } else if (dom_string_isequal(nodename, corestring_dom_INPUT)) {
- /* Things to consider here */
- /* Buttons -- only if the successful control */
- /* radio and checkbox -- only if selected */
- /* file -- also get the rawfile */
- /* everything else -- just value */
- err = dom_html_input_element_get_type(
- (dom_html_input_element *) form_element,
- &inputtype);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get input element type");
- goto dom_no_memory;
- }
- if (dom_string_caseless_isequal(
- inputtype, corestring_dom_submit)) {
-
- if (submit_button == NULL && !had_submit) {
- /* no button used, and first submit
- * node found, so use it
- */
- had_submit = true;
- } else if ((dom_node *)submit_button !=
- (dom_node *)form_element) {
- continue;
- }
-
- err = dom_html_input_element_get_value(
- (dom_html_input_element *)form_element,
- &inputvalue);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get submit button value");
- goto dom_no_memory;
- }
- /* Drop through to report the successful button */
- } else if (dom_string_caseless_isequal(
- inputtype, corestring_dom_image)) {
- /* We *ONLY* use an image input if it was the
- * thing which activated us
- */
- if ((dom_node *)submit_button !=
- (dom_node *)form_element)
- continue;
-
- err = dom_node_get_user_data(
- form_element,
- corestring_dom___ns_key_image_coords_node_data,
- &coords);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get image XY data");
- goto dom_no_memory;
- }
- if (coords == NULL) {
- NSLOG(netsurf, INFO,
- "No XY data on the image input");
- goto dom_no_memory;
- }
-
- basename = ENCODE_ITEM(inputname);
-
- success_new = calloc(1, sizeof(*success_new));
- if (success_new == NULL) {
- free(basename);
- NSLOG(netsurf, INFO,
- "Could not allocate data for image.x");
- goto dom_no_memory;
- }
-
- last_success->next = success_new;
- last_success = success_new;
-
- success_new->name = malloc(strlen(basename) + 3);
- if (success_new->name == NULL) {
- free(basename);
- NSLOG(netsurf, INFO,
- "Could not allocate name for image.x");
- goto dom_no_memory;
- }
- success_new->value = malloc(20);
- if (success_new->value == NULL) {
- free(basename);
- NSLOG(netsurf, INFO,
- "Could not allocate value for image.x");
- goto dom_no_memory;
- }
- sprintf(success_new->name, "%s.x", basename);
- sprintf(success_new->value, "%d", coords->x);
-
- success_new = calloc(1, sizeof(*success_new));
- if (success_new == NULL) {
- free(basename);
- NSLOG(netsurf, INFO,
- "Could not allocate data for image.y");
- goto dom_no_memory;
- }
-
- last_success->next = success_new;
- last_success = success_new;
-
- success_new->name = malloc(strlen(basename) + 3);
- if (success_new->name == NULL) {
- free(basename);
- NSLOG(netsurf, INFO,
- "Could not allocate name for image.y");
- goto dom_no_memory;
- }
- success_new->value = malloc(20);
- if (success_new->value == NULL) {
- free(basename);
- NSLOG(netsurf, INFO,
- "Could not allocate value for image.y");
- goto dom_no_memory;
- }
- sprintf(success_new->name, "%s.y", basename);
- sprintf(success_new->value, "%d", coords->y);
- free(basename);
- continue;
- } else if (dom_string_caseless_isequal(
- inputtype, corestring_dom_radio) ||
- dom_string_caseless_isequal(
- inputtype, corestring_dom_checkbox)) {
- err = dom_html_input_element_get_checked(
- (dom_html_input_element *)form_element,
- &checked);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get input element checked");
- goto dom_no_memory;
- }
- if (!checked)
- continue;
- err = dom_html_input_element_get_value(
- (dom_html_input_element *)form_element,
- &inputvalue);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get input element value");
- goto dom_no_memory;
- }
- if (inputvalue == NULL) {
- inputvalue = dom_string_ref(
- corestring_dom_on);
- }
- /* Fall through to simple allocation */
- } else if (dom_string_caseless_isequal(
- inputtype, corestring_dom_file)) {
-
- err = dom_html_input_element_get_value(
- (dom_html_input_element *)form_element,
- &inputvalue);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get file value");
- goto dom_no_memory;
- }
- err = dom_node_get_user_data(
- form_element,
- corestring_dom___ns_key_file_name_node_data,
- &rawfile_temp);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get file rawname");
- goto dom_no_memory;
- }
- rawfile_temp = strdup(rawfile_temp != NULL ?
- rawfile_temp :
- "");
- if (rawfile_temp == NULL) {
- NSLOG(netsurf, INFO,
- "Could not copy file rawname");
- goto dom_no_memory;
- }
- /* Fall out to the allocation */
- } else if (dom_string_caseless_isequal(
- inputtype, corestring_dom_reset) ||
- dom_string_caseless_isequal(
- inputtype, corestring_dom_button)) {
- /* Skip these */
- NSLOG(netsurf, INFO,
- "Skipping RESET and BUTTON");
- continue;
- } else {
- /* Everything else is treated as text values */
- err = dom_html_input_element_get_value(
- (dom_html_input_element *)form_element,
- &inputvalue);
- if (err != DOM_NO_ERR) {
- NSLOG(netsurf, INFO,
- "Could not get input value");
- goto dom_no_memory;
- }
- /* Fall out to the allocation */
- }
- }
-
- success_new = calloc(1, sizeof(*success_new));
- if (success_new == NULL) {
- NSLOG(netsurf, INFO,
- "Could not allocate data for generic");
- goto dom_no_memory;
- }
-
- last_success->next = success_new;
- last_success = success_new;
-
- success_new->name = ENCODE_ITEM(inputname);
- if (success_new->name == NULL) {
- NSLOG(netsurf, INFO,
- "Could not encode name for generic");
- goto dom_no_memory;
- }
- success_new->value = ENCODE_ITEM(inputvalue);
- if (success_new->value == NULL) {
- NSLOG(netsurf, INFO,
- "Could not encode value for generic");
- goto dom_no_memory;
- }
- if (rawfile_temp != NULL) {
- success_new->file = true;
- success_new->rawfile = rawfile_temp;
- rawfile_temp = NULL;
- }
- }
-
- free(charset);
-
- if (form_element != NULL) {
- dom_node_unref(form_element);
- }
-
- if (form_elements != NULL) {
- dom_html_collection_unref(form_elements);
- }
-
- if (nodename != NULL) {
- dom_string_unref(nodename);
- }
-
- if (inputname != NULL) {
- dom_string_unref(inputname);
- }
-
- if (inputvalue != NULL) {
- dom_string_unref(inputvalue);
- }
-
- if (options != NULL) {
- dom_html_options_collection_unref(options);
- }
-
- if (option_element != NULL) {
- dom_node_unref(option_element);
- }
-
- if (inputtype != NULL) {
- dom_string_unref(inputtype);
- }
-
- if (rawfile_temp != NULL) {
- free(rawfile_temp);
- }
-
- *successful_controls = sentinel.next;
-
- return true;
-
-dom_no_memory:
- free(charset);
- fetch_multipart_data_destroy(sentinel.next);
-
- if (form_elements != NULL)
- dom_html_collection_unref(form_elements);
- if (form_element != NULL)
- dom_node_unref(form_element);
- if (nodename != NULL)
- dom_string_unref(nodename);
- if (inputname != NULL)
- dom_string_unref(inputname);
- if (inputvalue != NULL)
- dom_string_unref(inputvalue);
- if (options != NULL)
- dom_html_options_collection_unref(options);
- if (option_element != NULL)
- dom_node_unref(option_element);
- if (inputtype != NULL)
- dom_string_unref(inputtype);
- if (rawfile_temp != NULL)
- free(rawfile_temp);
-
- return false;
-}
-#undef ENCODE_ITEM
-
-/**
- * Encode controls using application/x-www-form-urlencoded.
- *
- * \param form form to which successful controls relate
- * \param control linked list of fetch_multipart_data
- * \param query_string iff true add '?' to the start of returned data
- * \return URL-encoded form, or 0 on memory exhaustion
- */
-
-static char *form_url_encode(struct form *form,
- struct fetch_multipart_data *control,
- bool query_string)
-{
- char *name, *value;
- char *s, *s2;
- unsigned int len, len1, len_init;
- nserror url_err;
-
- if (query_string)
- s = malloc(2);
- else
- s = malloc(1);
-
- if (s == NULL)
- return NULL;
-
- if (query_string) {
- s[0] = '?';
- s[1] = '\0';
- len_init = len = 1;
- } else {
- s[0] = '\0';
- len_init = len = 0;
- }
-
- for (; control; control = control->next) {
- url_err = url_escape(control->name, true, NULL, &name);
- if (url_err == NSERROR_NOMEM) {
- free(s);
- return NULL;
- }
-
- assert(url_err == NSERROR_OK);
-
- url_err = url_escape(control->value, true, NULL, &value);
- if (url_err == NSERROR_NOMEM) {
- free(name);
- free(s);
- return NULL;
- }
-
- assert(url_err == NSERROR_OK);
-
- len1 = len + strlen(name) + strlen(value) + 2;
- s2 = realloc(s, len1 + 1);
- if (!s2) {
- free(value);
- free(name);
- free(s);
- return NULL;
- }
- s = s2;
- sprintf(s + len, "%s=%s&", name, value);
- len = len1;
- free(name);
- free(value);
- }
-
- if (len > len_init) {
- /* Replace trailing '&' */
- s[len - 1] = '\0';
- }
- return s;
-}
-
-/**
- * Find an acceptable character set encoding with which to submit the form
- *
- * \param form The form
- * \return Pointer to charset name (on heap, caller should free) or NULL
- */
-char *form_acceptable_charset(struct form *form)
-{
- char *temp, *c;
-
- if (!form)
- return NULL;
-
- if (!form->accept_charsets) {
- /* no accept-charsets attribute for this form */
- if (form->document_charset)
- /* document charset present, so use it */
- return strdup(form->document_charset);
- else
- /* no document charset, so default to 8859-1 */
- return strdup("ISO-8859-1");
- }
-
- /* make temporary copy of accept-charsets attribute */
- temp = strdup(form->accept_charsets);
- if (!temp)
- return NULL;
-
- /* make it upper case */
- for (c = temp; *c; c++) {
- *c = ascii_to_upper(*c);
- }
-
- /* is UTF-8 specified? */
- c = strstr(temp, "UTF-8");
- if (c) {
- free(temp);
- return strdup("UTF-8");
- }
-
- /* dispense with temporary copy */
- free(temp);
-
- /* according to RFC2070, the accept-charsets attribute of the
- * form element contains a space and/or comma separated list */
- c = form->accept_charsets;
-
- /** \todo an improvement would be to choose an encoding
- * acceptable to the server which covers as much of the input
- * values as possible. Additionally, we need to handle the
- * case where none of the acceptable encodings cover all the
- * textual input values. For now, we just extract the first
- * element of the charset list
- */
- while (*c && !ascii_is_space(*c)) {
- if (*c == ',')
- break;
- c++;
- }
-
- return strndup(form->accept_charsets, c - form->accept_charsets);
-}
-
-/**
- * Convert a string from UTF-8 to the specified charset
- * As a final fallback, this will attempt to convert to ISO-8859-1.
- *
- * \todo Return charset used?
- *
- * \param item String to convert
- * \param len Length of string to convert
- * \param charset Destination charset
- * \param fallback Fallback charset (may be NULL),
- * used iff converting to charset fails
- * \return Pointer to converted string (on heap, caller frees), or NULL
- */
-char *form_encode_item(const char *item, uint32_t len, const char *charset,
- const char *fallback)
-{
- nserror err;
- char *ret = NULL;
- char cset[256];
-
- if (!item || !charset)
- return NULL;
-
- snprintf(cset, sizeof cset, "%s//TRANSLIT", charset);
-
- err = utf8_to_enc(item, cset, 0, &ret);
- if (err == NSERROR_BAD_ENCODING) {
- /* charset not understood, try without transliteration */
- snprintf(cset, sizeof cset, "%s", charset);
- err = utf8_to_enc(item, cset, len, &ret);
-
- if (err == NSERROR_BAD_ENCODING) {
- /* nope, try fallback charset (if any) */
- if (fallback) {
- snprintf(cset, sizeof cset,
- "%s//TRANSLIT", fallback);
- err = utf8_to_enc(item, cset, 0, &ret);
-
- if (err == NSERROR_BAD_ENCODING) {
- /* and without transliteration */
- snprintf(cset, sizeof cset,
- "%s", fallback);
- err = utf8_to_enc(item, cset, 0, &ret);
- }
- }
-
- if (err == NSERROR_BAD_ENCODING) {
- /* that also failed, use 8859-1 */
- err = utf8_to_enc(item, "ISO-8859-1//TRANSLIT",
- 0, &ret);
- if (err == NSERROR_BAD_ENCODING) {
- /* and without transliteration */
- err = utf8_to_enc(item, "ISO-8859-1",
- 0, &ret);
- }
- }
- }
- }
- if (err == NSERROR_NOMEM) {
- return NULL;
- }
-
- return ret;
-}
-
-/* exported interface documented in render/form_internal.h */
-bool form_open_select_menu(void *client_data,
- struct form_control *control,
- select_menu_redraw_callback callback,
- struct content *c)
-{
- int line_height_with_spacing;
- struct box *box;
- plot_font_style_t fstyle;
- int total_height;
- struct form_select_menu *menu;
- html_content *html = (html_content *)c;
-
-
- /* if the menu is opened for the first time */
- if (control->data.select.menu == NULL) {
-
- menu = calloc(1, sizeof (struct form_select_menu));
- if (menu == NULL) {
- guit->misc->warning("NoMemory", 0);
- return false;
- }
-
- control->data.select.menu = menu;
-
- box = control->box;
-
- menu->width = box->width +
- box->border[RIGHT].width +
- box->border[LEFT].width +
- box->padding[RIGHT] + box->padding[LEFT];
-
- font_plot_style_from_css(&html->len_ctx, control->box->style,
- &fstyle);
- menu->f_size = fstyle.size;
-
- menu->line_height = FIXTOINT(FDIV((FMUL(FLTTOFIX(1.2),
- FMUL(nscss_screen_dpi,
- INTTOFIX(fstyle.size / FONT_SIZE_SCALE)))),
- F_72));
-
- line_height_with_spacing = menu->line_height +
- menu->line_height *
- SELECT_LINE_SPACING;
-
- total_height = control->data.select.num_items *
- line_height_with_spacing;
- menu->height = total_height;
-
- if (menu->height > MAX_SELECT_HEIGHT) {
-
- menu->height = MAX_SELECT_HEIGHT;
- }
- menu->client_data = client_data;
- menu->callback = callback;
- if (scrollbar_create(false,
- menu->height,
- total_height,
- menu->height,
- control,
- form_select_menu_scroll_callback,
- &(menu->scrollbar)) != NSERROR_OK) {
- free(menu);
- return false;
- }
- menu->c = c;
- }
- else menu = control->data.select.menu;
-
- menu->callback(client_data, 0, 0, menu->width, menu->height);
-
- return true;
-}
-
-
-/* exported interface documented in render/form_internal.h */
-void form_free_select_menu(struct form_control *control)
-{
- if (control->data.select.menu->scrollbar != NULL)
- scrollbar_destroy(control->data.select.menu->scrollbar);
- free(control->data.select.menu);
- control->data.select.menu = NULL;
-}
-
-
-/* exported interface documented in render/form_internal.h */
-bool form_redraw_select_menu(struct form_control *control, int x, int y,
- float scale, const struct rect *clip,
- const struct redraw_context *ctx)
-{
- struct box *box;
- struct form_select_menu *menu = control->data.select.menu;
- struct form_option *option;
- int line_height, line_height_with_spacing;
- int width, height;
- int x0, y0, x1, scrollbar_x, y1, y2, y3;
- int item_y;
- int text_pos_offset, text_x;
- int scrollbar_width = SCROLLBAR_WIDTH;
- int i;
- int scroll;
- int x_cp, y_cp;
- struct rect r;
- struct rect rect;
- nserror res;
-
- box = control->box;
-
- x_cp = x;
- y_cp = y;
- width = menu->width;
- height = menu->height;
- line_height = menu->line_height;
-
- line_height_with_spacing = line_height +
- line_height * SELECT_LINE_SPACING;
- scroll = scrollbar_get_offset(menu->scrollbar);
-
- if (scale != 1.0) {
- x *= scale;
- y *= scale;
- width *= scale;
- height *= scale;
- scrollbar_width *= scale;
-
- i = scroll / line_height_with_spacing;
- scroll -= i * line_height_with_spacing;
- line_height *= scale;
- line_height_with_spacing *= scale;
- scroll *= scale;
- scroll += i * line_height_with_spacing;
- }
-
-
- x0 = x;
- y0 = y;
- x1 = x + width - 1;
- y1 = y + height - 1;
- scrollbar_x = x1 - scrollbar_width;
-
- r.x0 = x0;
- r.y0 = y0;
- r.x1 = x1 + 1;
- r.y1 = y1 + 1;
- res = ctx->plot->clip(ctx, &r);
- if (res != NSERROR_OK) {
- return false;
- }
-
- rect.x0 = x0;
- rect.y0 = y0;
- rect.x1 = x1;
- rect.y1 = y1;
- res = ctx->plot->rectangle(ctx, plot_style_stroke_darkwbasec, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
-
- x0 = x0 + SELECT_BORDER_WIDTH;
- y0 = y0 + SELECT_BORDER_WIDTH;
- x1 = x1 - SELECT_BORDER_WIDTH;
- y1 = y1 - SELECT_BORDER_WIDTH;
- height = height - 2 * SELECT_BORDER_WIDTH;
-
- r.x0 = x0;
- r.y0 = y0;
- r.x1 = x1 + 1;
- r.y1 = y1 + 1;
- res = ctx->plot->clip(ctx, &r);
- if (res != NSERROR_OK) {
- return false;
- }
-
- res = ctx->plot->rectangle(ctx, plot_style_fill_lightwbasec, &r);
- if (res != NSERROR_OK) {
- return false;
- }
-
- option = control->data.select.items;
- item_y = line_height_with_spacing;
-
- while (item_y < scroll) {
- option = option->next;
- item_y += line_height_with_spacing;
- }
- item_y -= line_height_with_spacing;
- text_pos_offset = y - scroll +
- (int) (line_height * (0.75 + SELECT_LINE_SPACING));
- text_x = x + (box->border[LEFT].width + box->padding[LEFT]) * scale;
-
- plot_fstyle_entry.size = menu->f_size;
-
- while (option && item_y - scroll < height) {
-
- if (option->selected) {
- y2 = y + item_y - scroll;
- y3 = y + item_y + line_height_with_spacing - scroll;
-
- rect.x0 = x0;
- rect.y0 = y0 > y2 ? y0 : y2;
- rect.x1 = scrollbar_x + 1;
- rect.y1 = y3 < y1 + 1 ? y3 : y1 + 1;
- res = ctx->plot->rectangle(ctx, &plot_style_fill_selected, &rect);
- if (res != NSERROR_OK) {
- return false;
- }
- }
-
- y2 = text_pos_offset + item_y;
- res = ctx->plot->text(ctx,
- &plot_fstyle_entry,
- text_x, y2,
- option->text, strlen(option->text));
- if (res != NSERROR_OK) {
- return false;
- }
-
- item_y += line_height_with_spacing;
- option = option->next;
- }
-
- res = scrollbar_redraw(menu->scrollbar,
- x_cp + menu->width - SCROLLBAR_WIDTH,
- y_cp,
- clip, scale, ctx);
- if (res != NSERROR_OK) {
- return false;
- }
-
- return true;
-}
-
-/**
- * Check whether a clipping rectangle is completely contained in the
- * select menu.
- *
- * \param control the select menu to check the clipping rectangle for
- * \param scale the current browser window scale
- * \param clip the clipping rectangle
- * \return true if inside false otherwise
- */
-bool form_clip_inside_select_menu(struct form_control *control, float scale,
- const struct rect *clip)
-{
- struct form_select_menu *menu = control->data.select.menu;
- int width, height;
-
-
- width = menu->width;
- height = menu->height;
-
- if (scale != 1.0) {
- width *= scale;
- height *= scale;
- }
-
- if (clip->x0 >= 0 && clip->x1 <= width &&
- clip->y0 >= 0 && clip->y1 <= height)
- return true;
-
- return false;
-}
-
-
-/**
- * Process a selection from a form select menu.
- *
- * \param html The html content handle for the form
- * \param control form control with menu
- * \param item index of item selected from the menu
- * \return NSERROR_OK or appropriate error code.
- */
-static nserror form__select_process_selection(html_content *html,
- struct form_control *control, int item)
-{
- struct box *inline_box;
- struct form_option *o;
- int count;
- nserror ret = NSERROR_OK;
-
- assert(control != NULL);
- assert(html != NULL);
-
- /** \todo Even though the form code is effectively part of the html
- * content handler, poking around inside contents is not good
- */
-
- inline_box = control->box->children->children;
-
- for (count = 0, o = control->data.select.items;
- o != NULL;
- count++, o = o->next) {
- if (!control->data.select.multiple && o->selected) {
- o->selected = false;
- dom_html_option_element_set_selected(o->node, false);
- }
-
- if (count == item) {
- if (control->data.select.multiple) {
- if (o->selected) {
- o->selected = false;
- dom_html_option_element_set_selected(
- o->node, false);
- control->data.select.num_selected--;
- } else {
- o->selected = true;
- dom_html_option_element_set_selected(
- o->node, true);
- control->data.select.num_selected++;
- }
- } else {
- dom_html_option_element_set_selected(
- o->node, true);
- o->selected = true;
- }
- }
-
- if (o->selected) {
- control->data.select.current = o;
- }
- }
-
- talloc_free(inline_box->text);
- inline_box->text = 0;
-
- if (control->data.select.num_selected == 0) {
- inline_box->text = talloc_strdup(html->bctx,
- messages_get("Form_None"));
- } else if (control->data.select.num_selected == 1) {
- inline_box->text = talloc_strdup(html->bctx,
- control->data.select.current->text);
- } else {
- inline_box->text = talloc_strdup(html->bctx,
- messages_get("Form_Many"));
- }
-
- if (!inline_box->text) {
- ret = NSERROR_NOMEM;
- inline_box->length = 0;
- } else {
- inline_box->length = strlen(inline_box->text);
- }
- inline_box->width = control->box->width;
-
- html__redraw_a_box(html, control->box);
-
- return ret;
-}
-
-/* exported interface documented in netsurf/form.h */
-nserror form_select_process_selection(struct form_control *control, int item)
-{
- assert(control != NULL);
-
- return form__select_process_selection(control->html, control, item);
-}
-
-/* exported interface documented in netsurf/form.h */
-struct form_option *
-form_select_get_option(struct form_control *control, int item)
-{
- struct form_option *opt;
-
- opt = control->data.select.items;
- while ((opt != NULL) && (item > 0)) {
- opt = opt->next;
- item--;
- }
- return opt;
-}
-
-/* exported interface documented in netsurf/form.h */
-char *form_control_get_name(struct form_control *control)
-{
- return control->name;
-}
-
-/* exported interface documented in netsurf/form.h */
-nserror form_control_bounding_rect(struct form_control *control, struct rect *r)
-{
- box_bounds( control->box, r );
- return NSERROR_OK;
-}
-
-
-/**
- * Handle a click on the area of the currently opened select menu.
- *
- * \param control the select menu which received the click
- * \param x X coordinate of click
- * \param y Y coordinate of click
- */
-void form_select_menu_clicked(struct form_control *control, int x, int y)
-{
- struct form_select_menu *menu = control->data.select.menu;
- struct form_option *option;
- html_content *html = (html_content *)menu->c;
- int line_height, line_height_with_spacing;
- int item_bottom_y;
- int scroll, i;
-
- scroll = scrollbar_get_offset(menu->scrollbar);
-
- line_height = menu->line_height;
- line_height_with_spacing = line_height +
- line_height * SELECT_LINE_SPACING;
-
- option = control->data.select.items;
- item_bottom_y = line_height_with_spacing;
- i = 0;
- while (option && item_bottom_y < scroll + y) {
- item_bottom_y += line_height_with_spacing;
- option = option->next;
- i++;
- }
-
- if (option != NULL) {
- form__select_process_selection(html, control, i);
- }
-
- menu->callback(menu->client_data, 0, 0, menu->width, menu->height);
-}
-
-/**
- * Handle mouse action for the currently opened select menu.
- *
- * \param control the select menu which received the mouse action
- * \param mouse current mouse state
- * \param x X coordinate of click
- * \param y Y coordinate of click
- * \return text for the browser status bar or NULL if the menu has
- * to be closed
- */
-const char *form_select_mouse_action(struct form_control *control,
- browser_mouse_state mouse, int x, int y)
-{
- struct form_select_menu *menu = control->data.select.menu;
- int x0, y0, x1, y1, scrollbar_x;
- const char *status = NULL;
- bool multiple = control->data.select.multiple;
-
- x0 = 0;
- y0 = 0;
- x1 = menu->width;
- y1 = menu->height;
- scrollbar_x = x1 - SCROLLBAR_WIDTH;
-
- if (menu->scroll_capture ||
- (x > scrollbar_x && x < x1 && y > y0 && y < y1)) {
- /* The scroll is currently capturing all events or the mouse
- * event is taking place on the scrollbar widget area
- */
- x -= scrollbar_x;
- return scrollbar_mouse_status_to_message(
- scrollbar_mouse_action(menu->scrollbar,
- mouse, x, y));
- }
-
-
- if (x > x0 && x < scrollbar_x && y > y0 && y < y1) {
- /* over option area */
-
- if (mouse & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2))
- /* button 1 or 2 click */
- form_select_menu_clicked(control, x, y);
-
- if (!(mouse & BROWSER_MOUSE_CLICK_1 && !multiple))
- /* anything but a button 1 click over a single select
- menu */
- status = messages_get(control->data.select.multiple ?
- "SelectMClick" : "SelectClick");
-
- } else if (!(mouse & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2)))
- /* if not a button 1 or 2 click*/
- status = messages_get("SelectClose");
-
- return status;
-}
-
-/**
- * Handle mouse drag end for the currently opened select menu.
- *
- * \param control the select menu which received the mouse drag end
- * \param mouse current mouse state
- * \param x X coordinate of drag end
- * \param y Y coordinate of drag end
- */
-void form_select_mouse_drag_end(struct form_control *control,
- browser_mouse_state mouse, int x, int y)
-{
- int x0, y0, x1, y1;
- int box_x, box_y;
- struct box *box;
- struct form_select_menu *menu = control->data.select.menu;
-
- box = control->box;
-
- /* Get global coords of scrollbar */
- box_coords(box, &box_x, &box_y);
- box_x -= box->border[LEFT].width;
- box_y += box->height + box->border[BOTTOM].width +
- box->padding[BOTTOM] + box->padding[TOP];
-
- /* Get drag end coords relative to scrollbar */
- x = x - box_x;
- y = y - box_y;
-
- if (menu->scroll_capture) {
- x -= menu->width - SCROLLBAR_WIDTH;
- scrollbar_mouse_drag_end(menu->scrollbar, mouse, x, y);
- return;
- }
-
- x0 = 0;
- y0 = 0;
- x1 = menu->width;
- y1 = menu->height;
-
-
- if (x > x0 && x < x1 - SCROLLBAR_WIDTH && y > y0 && y < y1)
- /* handle drag end above the option area like a regular click */
- form_select_menu_clicked(control, x, y);
-}
-
-/**
- * Callback for the select menus scroll
- */
-void form_select_menu_scroll_callback(void *client_data,
- struct scrollbar_msg_data *scrollbar_data)
-{
- struct form_control *control = client_data;
- struct form_select_menu *menu = control->data.select.menu;
- html_content *html = (html_content *)menu->c;
-
- switch (scrollbar_data->msg) {
- case SCROLLBAR_MSG_MOVED:
- menu->callback(menu->client_data,
- 0, 0,
- menu->width,
- menu->height);
- break;
- case SCROLLBAR_MSG_SCROLL_START:
- {
- struct rect rect = {
- .x0 = scrollbar_data->x0,
- .y0 = scrollbar_data->y0,
- .x1 = scrollbar_data->x1,
- .y1 = scrollbar_data->y1
- };
-
- browser_window_set_drag_type(html->bw,
- DRAGGING_CONTENT_SCROLLBAR, &rect);
-
- menu->scroll_capture = true;
- }
- break;
- case SCROLLBAR_MSG_SCROLL_FINISHED:
- menu->scroll_capture = false;
-
- browser_window_set_drag_type(html->bw,
- DRAGGING_NONE, NULL);
- break;
- default:
- break;
- }
-}
-
-/**
- * Get the dimensions of a select menu.
- *
- * \param control the select menu to get the dimensions of
- * \param width gets updated to menu width
- * \param height gets updated to menu height
- */
-void form_select_get_dimensions(struct form_control *control,
- int *width, int *height)
-{
- *width = control->data.select.menu->width;
- *height = control->data.select.menu->height;
-}
-
-/**
- * Callback for the core select menu.
- */
-void form_select_menu_callback(void *client_data,
- int x, int y, int width, int height)
-{
- html_content *html = client_data;
- int menu_x, menu_y;
- struct box *box;
-
- box = html->visible_select_menu->box;
- box_coords(box, &menu_x, &menu_y);
-
- menu_x -= box->border[LEFT].width;
- menu_y += box->height + box->border[BOTTOM].width +
- box->padding[BOTTOM] +
- box->padding[TOP];
- content__request_redraw((struct content *)html, menu_x + x, menu_y + y,
- width, height);
-}
-
-
-/**
- * Set a radio form control and clear the others in the group.
- *
- * \param radio form control of type GADGET_RADIO
- */
-
-void form_radio_set(struct form_control *radio)
-{
- struct form_control *control;
-
- assert(radio);
- if (!radio->form)
- return;
-
- if (radio->selected)
- return;
-
- for (control = radio->form->controls; control;
- control = control->next) {
- if (control->type != GADGET_RADIO)
- continue;
- if (control == radio)
- continue;
- if (strcmp(control->name, radio->name) != 0)
- continue;
-
- if (control->selected) {
- control->selected = false;
- dom_html_input_element_set_checked(control->node, false);
- html__redraw_a_box(radio->html, control->box);
- }
- }
-
- radio->selected = true;
- dom_html_input_element_set_checked(radio->node, true);
- html__redraw_a_box(radio->html, radio->box);
-}
-
-
-/**
- * Collect controls and submit a form.
- */
-
-void form_submit(nsurl *page_url, struct browser_window *target,
- struct form *form, struct form_control *submit_button)
-{
- char *data = NULL;
- struct fetch_multipart_data *success;
- nsurl *action_url;
- nsurl *action_query;
- nserror error;
-
- assert(form != NULL);
-
- if (form_successful_controls_dom(form, submit_button, &success) == false) {
- guit->misc->warning("NoMemory", 0);
- return;
- }
-
- /* Decompose action */
- if (nsurl_create(form->action, &action_url) != NSERROR_OK) {
- free(data);
- fetch_multipart_data_destroy(success);
- guit->misc->warning("NoMemory", 0);
- return;
- }
-
- switch (form->method) {
- case method_GET:
- data = form_url_encode(form, success, true);
- if (data == NULL) {
- fetch_multipart_data_destroy(success);
- guit->misc->warning("NoMemory", 0);
- return;
- }
-
- /* Replace query segment */
- error = nsurl_replace_query(action_url, data, &action_query);
- if (error != NSERROR_OK) {
- nsurl_unref(action_query);
- free(data);
- fetch_multipart_data_destroy(success);
- guit->misc->warning(messages_get_errorcode(error), 0);
- return;
- }
-
- /* Construct submit url */
- browser_window_navigate(target,
- action_query,
- page_url,
- BW_NAVIGATE_HISTORY,
- NULL,
- NULL,
- NULL);
-
- nsurl_unref(action_query);
- break;
-
- case method_POST_URLENC:
- data = form_url_encode(form, success, false);
- if (data == NULL) {
- fetch_multipart_data_destroy(success);
- guit->misc->warning("NoMemory", 0);
- nsurl_unref(action_url);
- return;
- }
-
- browser_window_navigate(target,
- action_url,
- page_url,
- BW_NAVIGATE_HISTORY,
- data,
- NULL,
- NULL);
- break;
-
- case method_POST_MULTIPART:
- browser_window_navigate(target,
- action_url,
- page_url,
- BW_NAVIGATE_HISTORY,
- NULL,
- success,
- NULL);
-
- break;
- }
-
- nsurl_unref(action_url);
- fetch_multipart_data_destroy(success);
- free(data);
-}
-
-void form_gadget_update_value(struct form_control *control, char *value)
-{
- switch (control->type) {
- case GADGET_HIDDEN:
- case GADGET_TEXTBOX:
- case GADGET_TEXTAREA:
- case GADGET_PASSWORD:
- case GADGET_FILE:
- if (control->value != NULL) {
- free(control->value);
- }
- control->value = value;
- if (control->node != NULL) {
- dom_exception err;
- dom_string *str;
- err = dom_string_create((uint8_t *)value,
- strlen(value), &str);
- if (err == DOM_NO_ERR) {
- if (control->type == GADGET_TEXTAREA)
- err = dom_html_text_area_element_set_value(
- (dom_html_text_area_element *)(control->node),
- str);
- else
- err = dom_html_input_element_set_value(
- (dom_html_input_element *)(control->node),
- str);
- dom_string_unref(str);
- }
- }
- break;
- default:
- /* Do nothing */
- break;
- }
-}
diff --git a/render/html_interaction.c b/render/html_interaction.c
deleted file mode 100644
index 2d14ed2ae..000000000
--- a/render/html_interaction.c
+++ /dev/null
@@ -1,1434 +0,0 @@
-/*
- * Copyright 2006 James Bursa <bursa@users.sourceforge.net>
- * Copyright 2006 Richard Wilson <info@tinct.net>
- * Copyright 2008 Michael Drake <tlsa@netsurf-browser.org>
- * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- * User interaction with a CONTENT_HTML (implementation).
- */
-
-#include <assert.h>
-#include <stdbool.h>
-
-#include <dom/dom.h>
-
-#include "utils/corestrings.h"
-#include "utils/messages.h"
-#include "utils/utils.h"
-#include "utils/log.h"
-#include "utils/nsoption.h"
-#include "netsurf/content.h"
-#include "netsurf/browser_window.h"
-#include "netsurf/mouse.h"
-#include "netsurf/misc.h"
-#include "netsurf/layout.h"
-#include "netsurf/keypress.h"
-#include "content/hlcache.h"
-#include "desktop/frames.h"
-#include "desktop/scrollbar.h"
-#include "desktop/selection.h"
-#include "desktop/textarea.h"
-#include "javascript/js.h"
-#include "desktop/gui_internal.h"
-
-#include "render/box.h"
-#include "render/box_textarea.h"
-#include "render/font.h"
-#include "render/form_internal.h"
-#include "render/html_internal.h"
-#include "render/imagemap.h"
-#include "render/search.h"
-
-/**
- * Get pointer shape for given box
- *
- * \param box box in question
- * \param imagemap whether an imagemap applies to the box
- */
-
-static browser_pointer_shape get_pointer_shape(struct box *box, bool imagemap)
-{
- browser_pointer_shape pointer;
- css_computed_style *style;
- enum css_cursor_e cursor;
- lwc_string **cursor_uris;
-
- if (box->type == BOX_FLOAT_LEFT || box->type == BOX_FLOAT_RIGHT)
- style = box->children->style;
- else
- style = box->style;
-
- if (style == NULL)
- return BROWSER_POINTER_DEFAULT;
-
- cursor = css_computed_cursor(style, &cursor_uris);
-
- switch (cursor) {
- case CSS_CURSOR_AUTO:
- if (box->href || (box->gadget &&
- (box->gadget->type == GADGET_IMAGE ||
- box->gadget->type == GADGET_SUBMIT)) ||
- imagemap) {
- /* link */
- pointer = BROWSER_POINTER_POINT;
- } else if (box->gadget &&
- (box->gadget->type == GADGET_TEXTBOX ||
- box->gadget->type == GADGET_PASSWORD ||
- box->gadget->type == GADGET_TEXTAREA)) {
- /* text input */
- pointer = BROWSER_POINTER_CARET;
- } else {
- /* html content doesn't mind */
- pointer = BROWSER_POINTER_AUTO;
- }
- break;
- case CSS_CURSOR_CROSSHAIR:
- pointer = BROWSER_POINTER_CROSS;
- break;
- case CSS_CURSOR_POINTER:
- pointer = BROWSER_POINTER_POINT;
- break;
- case CSS_CURSOR_MOVE:
- pointer = BROWSER_POINTER_MOVE;
- break;
- case CSS_CURSOR_E_RESIZE:
- pointer = BROWSER_POINTER_RIGHT;
- break;
- case CSS_CURSOR_W_RESIZE:
- pointer = BROWSER_POINTER_LEFT;
- break;
- case CSS_CURSOR_N_RESIZE:
- pointer = BROWSER_POINTER_UP;
- break;
- case CSS_CURSOR_S_RESIZE:
- pointer = BROWSER_POINTER_DOWN;
- break;
- case CSS_CURSOR_NE_RESIZE:
- pointer = BROWSER_POINTER_RU;
- break;
- case CSS_CURSOR_SW_RESIZE:
- pointer = BROWSER_POINTER_LD;
- break;
- case CSS_CURSOR_SE_RESIZE:
- pointer = BROWSER_POINTER_RD;
- break;
- case CSS_CURSOR_NW_RESIZE:
- pointer = BROWSER_POINTER_LU;
- break;
- case CSS_CURSOR_TEXT:
- pointer = BROWSER_POINTER_CARET;
- break;
- case CSS_CURSOR_WAIT:
- pointer = BROWSER_POINTER_WAIT;
- break;
- case CSS_CURSOR_PROGRESS:
- pointer = BROWSER_POINTER_PROGRESS;
- break;
- case CSS_CURSOR_HELP:
- pointer = BROWSER_POINTER_HELP;
- break;
- default:
- pointer = BROWSER_POINTER_DEFAULT;
- break;
- }
-
- return pointer;
-}
-
-
-/**
- * Start drag scrolling the contents of a box
- *
- * \param box the box to be scrolled
- * \param x x ordinate of initial mouse position
- * \param y y ordinate
- */
-
-static void html_box_drag_start(struct box *box, int x, int y)
-{
- int box_x, box_y;
- int scroll_mouse_x, scroll_mouse_y;
-
- box_coords(box, &box_x, &box_y);
-
- if (box->scroll_x != NULL) {
- scroll_mouse_x = x - box_x ;
- scroll_mouse_y = y - (box_y + box->padding[TOP] +
- box->height + box->padding[BOTTOM] -
- SCROLLBAR_WIDTH);
- scrollbar_start_content_drag(box->scroll_x,
- scroll_mouse_x, scroll_mouse_y);
- } else if (box->scroll_y != NULL) {
- scroll_mouse_x = x - (box_x + box->padding[LEFT] +
- box->width + box->padding[RIGHT] -
- SCROLLBAR_WIDTH);
- scroll_mouse_y = y - box_y;
-
- scrollbar_start_content_drag(box->scroll_y,
- scroll_mouse_x, scroll_mouse_y);
- }
-}
-
-
-/**
- * End overflow scroll scrollbar drags
- *
- * \param html html content
- * \param mouse state of mouse buttons and modifier keys
- * \param x coordinate of mouse
- * \param y coordinate of mouse
- * \param dir Direction of drag
- */
-static size_t html_selection_drag_end(struct html_content *html,
- browser_mouse_state mouse, int x, int y, int dir)
-{
- int pixel_offset;
- struct box *box;
- int dx, dy;
- size_t idx = 0;
-
- box = box_pick_text_box(html, x, y, dir, &dx, &dy);
- if (box) {
- plot_font_style_t fstyle;
-
- font_plot_style_from_css(&html->len_ctx, box->style, &fstyle);
-
- guit->layout->position(&fstyle, box->text, box->length,
- dx, &idx, &pixel_offset);
-
- idx += box->byte_offset;
- }
-
- return idx;
-}
-
-
-/**
- * Handle mouse tracking (including drags) in an HTML content window.
- *
- * \param c content of type html
- * \param bw browser window
- * \param mouse state of mouse buttons and modifier keys
- * \param x coordinate of mouse
- * \param y coordinate of mouse
- */
-
-void html_mouse_track(struct content *c, struct browser_window *bw,
- browser_mouse_state mouse, int x, int y)
-{
- html_mouse_action(c, bw, mouse, x, y);
-}
-
-/**
- * Helper for file gadgets to store their filename.
- *
- * Stores the filename unencoded on the dom node associated with the
- * gadget.
- *
- * \todo Get rid of this crap eventually
- *
- * \param operation DOM operation
- * \param key DOM node key being considerd
- * \param _data The data assocated with the key
- * \param src The source DOM node.
- * \param dst The destination DOM node.
- */
-static void
-html__image_coords_dom_user_data_handler(dom_node_operation operation,
- dom_string *key,
- void *_data,
- struct dom_node *src,
- struct dom_node *dst)
-{
- struct image_input_coords *oldcoords, *coords = _data, *newcoords;
-
- if (!dom_string_isequal(corestring_dom___ns_key_image_coords_node_data,
- key) || coords == NULL) {
- return;
- }
-
- switch (operation) {
- case DOM_NODE_CLONED:
- newcoords = calloc(1, sizeof(*newcoords));
- if (newcoords != NULL) {
- *newcoords = *coords;
- if (dom_node_set_user_data(dst,
- corestring_dom___ns_key_image_coords_node_data,
- newcoords,
- html__image_coords_dom_user_data_handler,
- &oldcoords) == DOM_NO_ERR) {
- free(oldcoords);
- }
- }
- break;
-
- case DOM_NODE_DELETED:
- free(coords);
- break;
-
- case DOM_NODE_RENAMED:
- case DOM_NODE_IMPORTED:
- case DOM_NODE_ADOPTED:
- break;
-
- default:
- NSLOG(netsurf, INFO, "User data operation not handled.");
- assert(0);
- }
-}
-
-/**
- * Handle mouse clicks and movements in an HTML content window.
- *
- * \param c content of type html
- * \param bw browser window
- * \param mouse state of mouse buttons and modifier keys
- * \param x coordinate of mouse
- * \param y coordinate of mouse
- *
- * This function handles both hovering and clicking. It is important that the
- * code path is identical (except that hovering doesn't carry out the action),
- * so that the status bar reflects exactly what will happen. Having separate
- * code paths opens the possibility that an attacker will make the status bar
- * show some harmless action where clicking will be harmful.
- */
-
-void html_mouse_action(struct content *c, struct browser_window *bw,
- browser_mouse_state mouse, int x, int y)
-{
- html_content *html = (html_content *) c;
- enum { ACTION_NONE, ACTION_SUBMIT, ACTION_GO } action = ACTION_NONE;
- const char *title = 0;
- nsurl *url = 0;
- char *url_s = NULL;
- size_t url_l = 0;
- const char *target = 0;
- char status_buffer[200];
- const char *status = 0;
- browser_pointer_shape pointer = BROWSER_POINTER_DEFAULT;
- bool imagemap = false;
- int box_x = 0, box_y = 0;
- int gadget_box_x = 0, gadget_box_y = 0;
- int html_object_pos_x = 0, html_object_pos_y = 0;
- int text_box_x = 0;
- struct box *url_box = 0;
- struct box *gadget_box = 0;
- struct box *text_box = 0;
- struct box *box;
- struct form_control *gadget = 0;
- hlcache_handle *object = NULL;
- struct box *html_object_box = NULL;
- struct browser_window *iframe = NULL;
- struct box *drag_candidate = NULL;
- struct scrollbar *scrollbar = NULL;
- plot_font_style_t fstyle;
- int scroll_mouse_x = 0, scroll_mouse_y = 0;
- int padding_left, padding_right, padding_top, padding_bottom;
- browser_drag_type drag_type = browser_window_get_drag_type(bw);
- union content_msg_data msg_data;
- struct dom_node *node = NULL;
- union html_drag_owner drag_owner;
- union html_selection_owner sel_owner;
- bool click = mouse & (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2 |
- BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2 |
- BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2);
-
- if (drag_type != DRAGGING_NONE && !mouse &&
- html->visible_select_menu != NULL) {
- /* drag end: select menu */
- form_select_mouse_drag_end(html->visible_select_menu,
- mouse, x, y);
- }
-
- if (html->visible_select_menu != NULL) {
- box = html->visible_select_menu->box;
- box_coords(box, &box_x, &box_y);
-
- box_x -= box->border[LEFT].width;
- box_y += box->height + box->border[BOTTOM].width +
- box->padding[BOTTOM] + box->padding[TOP];
- status = form_select_mouse_action(html->visible_select_menu,
- mouse, x - box_x, y - box_y);
- if (status != NULL) {
- msg_data.explicit_status_text = status;
- content_broadcast(c, CONTENT_MSG_STATUS, &msg_data);
- } else {
- int width, height;
- form_select_get_dimensions(html->visible_select_menu,
- &width, &height);
- html->visible_select_menu = NULL;
- browser_window_redraw_rect(bw, box_x, box_y,
- width, height);
- }
- return;
- }
-
- if (html->drag_type == HTML_DRAG_SELECTION) {
- /* Selection drag */
- struct box *box;
- int dir = -1;
- int dx, dy;
-
- if (!mouse) {
- /* End of selection drag */
- int dir = -1;
- size_t idx;
-
- if (selection_dragging_start(&html->sel))
- dir = 1;
-
- idx = html_selection_drag_end(html, mouse, x, y, dir);
-
- if (idx != 0)
- selection_track(&html->sel, mouse, idx);
-
- drag_owner.no_owner = true;
- html_set_drag_type(html, HTML_DRAG_NONE,
- drag_owner, NULL);
- return;
- }
-
- if (selection_dragging_start(&html->sel))
- dir = 1;
-
- box = box_pick_text_box(html, x, y, dir, &dx, &dy);
-
- if (box != NULL) {
- int pixel_offset;
- size_t idx;
- plot_font_style_t fstyle;
-
- font_plot_style_from_css(&html->len_ctx,
- box->style, &fstyle);
-
- guit->layout->position(&fstyle,
- box->text, box->length,
- dx, &idx, &pixel_offset);
-
- selection_track(&html->sel, mouse,
- box->byte_offset + idx);
- }
- return;
- }
-
- if (html->drag_type == HTML_DRAG_SCROLLBAR) {
- struct scrollbar *scr = html->drag_owner.scrollbar;
- struct html_scrollbar_data *data = scrollbar_get_data(scr);
-
- if (!mouse) {
- /* drag end: scrollbar */
- html_overflow_scroll_drag_end(scr, mouse, x, y);
- }
-
- box = data->box;
- box_coords(box, &box_x, &box_y);
- if (scrollbar_is_horizontal(scr)) {
- scroll_mouse_x = x - box_x ;
- scroll_mouse_y = y - (box_y + box->padding[TOP] +
- box->height + box->padding[BOTTOM] -
- SCROLLBAR_WIDTH);
- status = scrollbar_mouse_status_to_message(
- scrollbar_mouse_action(scr, mouse,
- scroll_mouse_x,
- scroll_mouse_y));
- } else {
- scroll_mouse_x = x - (box_x + box->padding[LEFT] +
- box->width + box->padding[RIGHT] -
- SCROLLBAR_WIDTH);
- scroll_mouse_y = y - box_y;
- status = scrollbar_mouse_status_to_message(
- scrollbar_mouse_action(scr, mouse,
- scroll_mouse_x,
- scroll_mouse_y));
- }
-
- msg_data.explicit_status_text = status;
- content_broadcast(c, CONTENT_MSG_STATUS, &msg_data);
- return;
- }
-
- if (html->drag_type == HTML_DRAG_TEXTAREA_SELECTION ||
- html->drag_type == HTML_DRAG_TEXTAREA_SCROLLBAR) {
- box = html->drag_owner.textarea;
- assert(box->gadget != NULL);
- assert(box->gadget->type == GADGET_TEXTAREA ||
- box->gadget->type == GADGET_PASSWORD ||
- box->gadget->type == GADGET_TEXTBOX);
-
- box_coords(box, &box_x, &box_y);
- textarea_mouse_action(box->gadget->data.text.ta, mouse,
- x - box_x, y - box_y);
-
- /* TODO: Set appropriate statusbar message */
- return;
- }
-
- if (html->drag_type == HTML_DRAG_CONTENT_SELECTION ||
- html->drag_type == HTML_DRAG_CONTENT_SCROLL) {
- box = html->drag_owner.content;
- assert(box->object != NULL);
-
- box_coords(box, &box_x, &box_y);
- content_mouse_track(box->object, bw, mouse,
- x - box_x, y - box_y);
- return;
- }
-
- if (html->drag_type == HTML_DRAG_CONTENT_SELECTION) {
- box = html->drag_owner.content;
- assert(box->object != NULL);
-
- box_coords(box, &box_x, &box_y);
- content_mouse_track(box->object, bw, mouse,
- x - box_x, y - box_y);
- return;
- }
-
- /* Content related drags handled by now */
- assert(html->drag_type == HTML_DRAG_NONE);
-
- /* search the box tree for a link, imagemap, form control, or
- * box with scrollbars
- */
-
- box = html->layout;
-
- /* Consider the margins of the html page now */
- box_x = box->margin[LEFT];
- box_y = box->margin[TOP];
-
- /* descend through visible boxes setting more specific values for:
- * box - deepest box at point
- * html_object_box - html object
- * html_object_pos_x - html object
- * html_object_pos_y - html object
- * object - non html object
- * iframe - iframe
- * url - href or imagemap
- * target - href or imagemap or gadget
- * url_box - href or imagemap
- * imagemap - imagemap
- * gadget - gadget
- * gadget_box - gadget
- * gadget_box_x - gadget
- * gadget_box_y - gadget
- * title - title
- * pointer
- *
- * drag_candidate - first box with scroll
- * padding_left - box with scroll
- * padding_right
- * padding_top
- * padding_bottom
- * scrollbar - inside padding box stops decent
- * scroll_mouse_x - inside padding box stops decent
- * scroll_mouse_y - inside padding box stops decent
- *
- * text_box - text box
- * text_box_x - text_box
- */
- do {
- if ((box->style != NULL) &&
- (css_computed_visibility(box->style) ==
- CSS_VISIBILITY_HIDDEN)) {
- continue;
- }
-
- if (box->node != NULL) {
- node = box->node;
- }
-
- if (box->object) {
- if (content_get_type(box->object) == CONTENT_HTML) {
- html_object_box = box;
- html_object_pos_x = box_x;
- html_object_pos_y = box_y;
- } else {
- object = box->object;
- }
- }
-
- if (box->iframe) {
- iframe = box->iframe;
- }
-
- if (box->href) {
- url = box->href;
- target = box->target;
- url_box = box;
- }
-
- if (box->usemap) {
- url = imagemap_get(html, box->usemap,
- box_x, box_y, x, y, &target);
- if (url) {
- imagemap = true;
- url_box = box;
- }
- }
-
- if (box->gadget) {
- gadget = box->gadget;
- gadget_box = box;
- gadget_box_x = box_x;
- gadget_box_y = box_y;
- if (gadget->form)
- target = gadget->form->target;
- }
-
- if (box->title) {
- title = box->title;
- }
-
- pointer = get_pointer_shape(box, false);
-
- if ((box->scroll_x != NULL) ||
- (box->scroll_y != NULL)) {
-
- if (drag_candidate == NULL) {
- drag_candidate = box;
- }
-
- padding_left = box_x +
- scrollbar_get_offset(box->scroll_x);
- padding_right = padding_left + box->padding[LEFT] +
- box->width + box->padding[RIGHT];
- padding_top = box_y +
- scrollbar_get_offset(box->scroll_y);
- padding_bottom = padding_top + box->padding[TOP] +
- box->height + box->padding[BOTTOM];
-
- if ((x > padding_left) &&
- (x < padding_right) &&
- (y > padding_top) &&
- (y < padding_bottom)) {
- /* mouse inside padding box */
-
- if ((box->scroll_y != NULL) &&
- (x > (padding_right -
- SCROLLBAR_WIDTH))) {
- /* mouse above vertical box scroll */
-
- scrollbar = box->scroll_y;
- scroll_mouse_x = x - (padding_right -
- SCROLLBAR_WIDTH);
- scroll_mouse_y = y - padding_top;
- break;
-
- } else if ((box->scroll_x != NULL) &&
- (y > (padding_bottom -
- SCROLLBAR_WIDTH))) {
- /* mouse above horizontal box scroll */
-
- scrollbar = box->scroll_x;
- scroll_mouse_x = x - padding_left;
- scroll_mouse_y = y - (padding_bottom -
- SCROLLBAR_WIDTH);
- break;
- }
- }
- }
-
- if (box->text && !box->object) {
- text_box = box;
- text_box_x = box_x;
- }
- } while ((box = box_at_point(&html->len_ctx, box, x, y,
- &box_x, &box_y)) != NULL);
-
- /* use of box_x, box_y, or content below this point is probably a
- * mistake; they will refer to the last box returned by box_at_point */
- assert(node != NULL);
-
- if (scrollbar) {
- status = scrollbar_mouse_status_to_message(
- scrollbar_mouse_action(scrollbar, mouse,
- scroll_mouse_x,
- scroll_mouse_y));
- pointer = BROWSER_POINTER_DEFAULT;
- } else if (gadget) {
- textarea_mouse_status ta_status;
-
- switch (gadget->type) {
- case GADGET_SELECT:
- status = messages_get("FormSelect");
- pointer = BROWSER_POINTER_MENU;
- if (mouse & BROWSER_MOUSE_CLICK_1 &&
- nsoption_bool(core_select_menu)) {
- html->visible_select_menu = gadget;
- form_open_select_menu(c, gadget,
- form_select_menu_callback,
- c);
- pointer = BROWSER_POINTER_DEFAULT;
- } else if (mouse & BROWSER_MOUSE_CLICK_1) {
- msg_data.select_menu.gadget = gadget;
- content_broadcast(c, CONTENT_MSG_SELECTMENU,
- &msg_data);
- }
- break;
- case GADGET_CHECKBOX:
- status = messages_get("FormCheckbox");
- if (mouse & BROWSER_MOUSE_CLICK_1) {
- gadget->selected = !gadget->selected;
- dom_html_input_element_set_checked(
- (dom_html_input_element *)(gadget->node),
- gadget->selected);
- html__redraw_a_box(html, gadget_box);
- }
- break;
- case GADGET_RADIO:
- status = messages_get("FormRadio");
- if (mouse & BROWSER_MOUSE_CLICK_1)
- form_radio_set(gadget);
- break;
- case GADGET_IMAGE:
- /* This falls through to SUBMIT */
- if (mouse & BROWSER_MOUSE_CLICK_1) {
- struct image_input_coords *coords, *oldcoords;
- /** \todo Find a way to not ignore errors */
- coords = calloc(1, sizeof(*coords));
- if (coords == NULL) {
- return;
- }
- coords->x = x - gadget_box_x;
- coords->y = y - gadget_box_y;
- if (dom_node_set_user_data(
- gadget->node,
- corestring_dom___ns_key_image_coords_node_data,
- coords, html__image_coords_dom_user_data_handler,
- &oldcoords) != DOM_NO_ERR)
- return;
- free(oldcoords);
- }
- /* Fall through */
- case GADGET_SUBMIT:
- if (gadget->form) {
- snprintf(status_buffer, sizeof status_buffer,
- messages_get("FormSubmit"),
- gadget->form->action);
- status = status_buffer;
- pointer = get_pointer_shape(gadget_box, false);
- if (mouse & (BROWSER_MOUSE_CLICK_1 |
- BROWSER_MOUSE_CLICK_2))
- action = ACTION_SUBMIT;
- } else {
- status = messages_get("FormBadSubmit");
- }
- break;
- case GADGET_TEXTBOX:
- case GADGET_PASSWORD:
- case GADGET_TEXTAREA:
- if (gadget->type == GADGET_TEXTAREA)
- status = messages_get("FormTextarea");
- else
- status = messages_get("FormTextbox");
-
- if (click && (html->selection_type !=
- HTML_SELECTION_TEXTAREA ||
- html->selection_owner.textarea !=
- gadget_box)) {
- sel_owner.none = true;
- html_set_selection(html, HTML_SELECTION_NONE,
- sel_owner, true);
- }
-
- ta_status = textarea_mouse_action(gadget->data.text.ta,
- mouse, x - gadget_box_x,
- y - gadget_box_y);
-
- if (ta_status & TEXTAREA_MOUSE_EDITOR) {
- pointer = get_pointer_shape(gadget_box, false);
- } else {
- pointer = BROWSER_POINTER_DEFAULT;
- status = scrollbar_mouse_status_to_message(
- ta_status >> 3);
- }
- break;
- case GADGET_HIDDEN:
- /* not possible: no box generated */
- break;
- case GADGET_RESET:
- status = messages_get("FormReset");
- break;
- case GADGET_FILE:
- status = messages_get("FormFile");
- if (mouse & BROWSER_MOUSE_CLICK_1) {
- msg_data.gadget_click.gadget = gadget;
- content_broadcast(c, CONTENT_MSG_GADGETCLICK,
- &msg_data);
- }
- break;
- case GADGET_BUTTON:
- /* This gadget cannot be activated */
- status = messages_get("FormButton");
- break;
- }
-
- } else if (object && (mouse & BROWSER_MOUSE_MOD_2)) {
-
- if (mouse & BROWSER_MOUSE_DRAG_2) {
- msg_data.dragsave.type = CONTENT_SAVE_NATIVE;
- msg_data.dragsave.content = object;
- content_broadcast(c, CONTENT_MSG_DRAGSAVE, &msg_data);
-
- } else if (mouse & BROWSER_MOUSE_DRAG_1) {
- msg_data.dragsave.type = CONTENT_SAVE_ORIG;
- msg_data.dragsave.content = object;
- content_broadcast(c, CONTENT_MSG_DRAGSAVE, &msg_data);
- }
-
- /* \todo should have a drag-saving object msg */
-
- } else if (iframe) {
- int pos_x, pos_y;
- float scale = browser_window_get_scale(bw);
-
- browser_window_get_position(iframe, false, &pos_x, &pos_y);
-
- pos_x /= scale;
- pos_y /= scale;
-
- if (mouse & BROWSER_MOUSE_CLICK_1 ||
- mouse & BROWSER_MOUSE_CLICK_2) {
- browser_window_mouse_click(iframe, mouse,
- x - pos_x, y - pos_y);
- } else {
- browser_window_mouse_track(iframe, mouse,
- x - pos_x, y - pos_y);
- }
- } else if (html_object_box) {
-
- if (click && (html->selection_type != HTML_SELECTION_CONTENT ||
- html->selection_owner.content !=
- html_object_box)) {
- sel_owner.none = true;
- html_set_selection(html, HTML_SELECTION_NONE,
- sel_owner, true);
- }
- if (mouse & BROWSER_MOUSE_CLICK_1 ||
- mouse & BROWSER_MOUSE_CLICK_2) {
- content_mouse_action(html_object_box->object,
- bw, mouse,
- x - html_object_pos_x,
- y - html_object_pos_y);
- } else {
- content_mouse_track(html_object_box->object,
- bw, mouse,
- x - html_object_pos_x,
- y - html_object_pos_y);
- }
- } else if (url) {
- if (nsoption_bool(display_decoded_idn) == true) {
- if (nsurl_get_utf8(url, &url_s, &url_l) != NSERROR_OK) {
- /* Unable to obtain a decoded IDN. This is not a fatal error.
- * Ensure the string pointer is NULL so we use the encoded version. */
- url_s = NULL;
- }
- }
-
- if (title) {
- snprintf(status_buffer, sizeof status_buffer, "%s: %s",
- url_s ? url_s : nsurl_access(url), title);
- } else {
- snprintf(status_buffer, sizeof status_buffer, "%s",
- url_s ? url_s : nsurl_access(url));
- }
-
- status = status_buffer;
-
- if (url_s != NULL)
- free(url_s);
-
- pointer = get_pointer_shape(url_box, imagemap);
-
- if (mouse & BROWSER_MOUSE_CLICK_1 &&
- mouse & BROWSER_MOUSE_MOD_1) {
- /* force download of link */
- browser_window_navigate(bw,
- url,
- content_get_url(c),
- BW_NAVIGATE_DOWNLOAD,
- NULL,
- NULL,
- NULL);
-
- } else if (mouse & BROWSER_MOUSE_CLICK_2 &&
- mouse & BROWSER_MOUSE_MOD_1) {
- msg_data.savelink.url = url;
- msg_data.savelink.title = title;
- content_broadcast(c, CONTENT_MSG_SAVELINK, &msg_data);
-
- } else if (mouse & (BROWSER_MOUSE_CLICK_1 |
- BROWSER_MOUSE_CLICK_2))
- action = ACTION_GO;
- } else {
- bool done = false;
-
- /* frame resizing */
- if (browser_window_frame_resize_start(bw, mouse, x, y,
- &pointer)) {
- if (mouse & (BROWSER_MOUSE_DRAG_1 |
- BROWSER_MOUSE_DRAG_2)) {
- status = messages_get("FrameDrag");
- }
- done = true;
- }
-
- /* if clicking in the main page, remove the selection from any
- * text areas */
- if (!done) {
-
- if (click && html->focus_type != HTML_FOCUS_SELF) {
- union html_focus_owner fo;
- fo.self = true;
- html_set_focus(html, HTML_FOCUS_SELF, fo,
- true, 0, 0, 0, NULL);
- }
- if (click && html->selection_type !=
- HTML_SELECTION_SELF) {
- sel_owner.none = true;
- html_set_selection(html, HTML_SELECTION_NONE,
- sel_owner, true);
- }
-
- if (text_box) {
- int pixel_offset;
- size_t idx;
-
- font_plot_style_from_css(&html->len_ctx,
- text_box->style, &fstyle);
-
- guit->layout->position(&fstyle,
- text_box->text,
- text_box->length,
- x - text_box_x,
- &idx,
- &pixel_offset);
-
- if (selection_click(&html->sel, mouse,
- text_box->byte_offset + idx)) {
- /* key presses must be directed at the
- * main browser window, paste text
- * operations ignored */
- html_drag_type drag_type;
- union html_drag_owner drag_owner;
-
- if (selection_dragging(&html->sel)) {
- drag_type = HTML_DRAG_SELECTION;
- drag_owner.no_owner = true;
- html_set_drag_type(html,
- drag_type,
- drag_owner,
- NULL);
- status = messages_get(
- "Selecting");
- }
-
- done = true;
- }
-
- } else if (mouse & BROWSER_MOUSE_PRESS_1) {
- sel_owner.none = true;
- selection_clear(&html->sel, true);
- }
-
- if (selection_defined(&html->sel)) {
- sel_owner.none = false;
- html_set_selection(html, HTML_SELECTION_SELF,
- sel_owner, true);
- } else if (click && html->selection_type !=
- HTML_SELECTION_NONE) {
- sel_owner.none = true;
- html_set_selection(html, HTML_SELECTION_NONE,
- sel_owner, true);
- }
- }
-
- if (!done) {
- if (title)
- status = title;
-
- if (mouse & BROWSER_MOUSE_DRAG_1) {
- if (mouse & BROWSER_MOUSE_MOD_2) {
- msg_data.dragsave.type =
- CONTENT_SAVE_COMPLETE;
- msg_data.dragsave.content = NULL;
- content_broadcast(c,
- CONTENT_MSG_DRAGSAVE,
- &msg_data);
- } else {
- if (drag_candidate == NULL) {
- browser_window_page_drag_start(
- bw, x, y);
- } else {
- html_box_drag_start(
- drag_candidate,
- x, y);
- }
- pointer = BROWSER_POINTER_MOVE;
- }
- }
- else if (mouse & BROWSER_MOUSE_DRAG_2) {
- if (mouse & BROWSER_MOUSE_MOD_2) {
- msg_data.dragsave.type =
- CONTENT_SAVE_SOURCE;
- msg_data.dragsave.content = NULL;
- content_broadcast(c,
- CONTENT_MSG_DRAGSAVE,
- &msg_data);
- } else {
- if (drag_candidate == NULL) {
- browser_window_page_drag_start(
- bw, x, y);
- } else {
- html_box_drag_start(
- drag_candidate,
- x, y);
- }
- pointer = BROWSER_POINTER_MOVE;
- }
- }
- }
- if (mouse && mouse < BROWSER_MOUSE_MOD_1) {
- /* ensure key presses still act on the browser window */
- union html_focus_owner fo;
- fo.self = true;
- html_set_focus(html, HTML_FOCUS_SELF, fo,
- true, 0, 0, 0, NULL);
- }
- }
-
- if (!iframe && !html_object_box) {
- msg_data.explicit_status_text = status;
- content_broadcast(c, CONTENT_MSG_STATUS, &msg_data);
-
- msg_data.pointer = pointer;
- content_broadcast(c, CONTENT_MSG_POINTER, &msg_data);
- }
-
- /* fire dom click event */
- if (mouse & BROWSER_MOUSE_CLICK_1) {
- fire_dom_event(corestring_dom_click, node, true, true);
- }
-
- /* deferred actions that can cause this browser_window to be destroyed
- * and must therefore be done after set_status/pointer
- */
- switch (action) {
- case ACTION_SUBMIT:
- form_submit(content_get_url(c),
- browser_window_find_target(bw, target, mouse),
- gadget->form, gadget);
- break;
- case ACTION_GO:
- browser_window_navigate(browser_window_find_target(bw, target, mouse),
- url,
- content_get_url(c),
- BW_NAVIGATE_HISTORY,
- NULL,
- NULL,
- NULL);
- break;
- case ACTION_NONE:
- break;
- }
-}
-
-
-/**
- * Handle keypresses.
- *
- * \param c content of type HTML
- * \param key The UCS4 character codepoint
- * \return true if key handled, false otherwise
- */
-
-bool html_keypress(struct content *c, uint32_t key)
-{
- html_content *html = (html_content *) c;
- struct selection *sel = &html->sel;
- struct box *box;
-
- switch (html->focus_type) {
- case HTML_FOCUS_CONTENT:
- box = html->focus_owner.content;
- return content_keypress(box->object, key);
-
- case HTML_FOCUS_TEXTAREA:
- box = html->focus_owner.textarea;
- return box_textarea_keypress(html, box, key);
-
- default:
- /* Deal with it below */
- break;
- }
-
- switch (key) {
- case NS_KEY_COPY_SELECTION:
- selection_copy_to_clipboard(sel);
- return true;
-
- case NS_KEY_CLEAR_SELECTION:
- selection_clear(sel, true);
- return true;
-
- case NS_KEY_SELECT_ALL:
- selection_select_all(sel);
- return true;
-
- case NS_KEY_ESCAPE:
- if (selection_defined(sel)) {
- selection_clear(sel, true);
- return true;
- }
-
- /* if there's no selection, leave Escape for the caller */
- return false;
- }
-
- return false;
-}
-
-
-/**
- * Handle search.
- *
- * \param c content of type HTML
- * \param context front end private data
- * \param flags search flags
- * \param string search string
- */
-void html_search(struct content *c, void *context,
- search_flags_t flags, const char *string)
-{
- html_content *html = (html_content *)c;
-
- assert(c != NULL);
-
- if (string != NULL && html->search_string != NULL &&
- strcmp(string, html->search_string) == 0 &&
- html->search != NULL) {
- /* Continue prev. search */
- search_step(html->search, flags, string);
-
- } else if (string != NULL) {
- /* New search */
- free(html->search_string);
- html->search_string = strdup(string);
- if (html->search_string == NULL)
- return;
-
- if (html->search != NULL) {
- search_destroy_context(html->search);
- html->search = NULL;
- }
-
- html->search = search_create_context(c, CONTENT_HTML, context);
-
- if (html->search == NULL)
- return;
-
- search_step(html->search, flags, string);
-
- } else {
- /* Clear search */
- html_search_clear(c);
-
- free(html->search_string);
- html->search_string = NULL;
- }
-}
-
-
-/**
- * Terminate a search.
- *
- * \param c content of type HTML
- */
-void html_search_clear(struct content *c)
-{
- html_content *html = (html_content *)c;
-
- assert(c != NULL);
-
- free(html->search_string);
- html->search_string = NULL;
-
- if (html->search != NULL) {
- search_destroy_context(html->search);
- }
- html->search = NULL;
-}
-
-
-/**
- * Callback for in-page scrollbars.
- */
-void html_overflow_scroll_callback(void *client_data,
- struct scrollbar_msg_data *scrollbar_data)
-{
- struct html_scrollbar_data *data = client_data;
- html_content *html = (html_content *)data->c;
- struct box *box = data->box;
- union content_msg_data msg_data;
- html_drag_type drag_type;
- union html_drag_owner drag_owner;
-
- switch(scrollbar_data->msg) {
- case SCROLLBAR_MSG_MOVED:
-
- if (html->reflowing == true) {
- /* Can't redraw during layout, and it will
- * be redrawn after layout anyway. */
- break;
- }
-
- html__redraw_a_box(html, box);
- break;
- case SCROLLBAR_MSG_SCROLL_START:
- {
- struct rect rect = {
- .x0 = scrollbar_data->x0,
- .y0 = scrollbar_data->y0,
- .x1 = scrollbar_data->x1,
- .y1 = scrollbar_data->y1
- };
- drag_type = HTML_DRAG_SCROLLBAR;
- drag_owner.scrollbar = scrollbar_data->scrollbar;
- html_set_drag_type(html, drag_type, drag_owner, &rect);
- }
- break;
- case SCROLLBAR_MSG_SCROLL_FINISHED:
- drag_type = HTML_DRAG_NONE;
- drag_owner.no_owner = true;
- html_set_drag_type(html, drag_type, drag_owner, NULL);
-
- msg_data.pointer = BROWSER_POINTER_AUTO;
- content_broadcast(data->c, CONTENT_MSG_POINTER, &msg_data);
- break;
- }
-}
-
-
-/**
- * End overflow scroll scrollbar drags
- *
- * \param scrollbar scrollbar widget
- * \param mouse state of mouse buttons and modifier keys
- * \param x coordinate of mouse
- * \param y coordinate of mouse
- */
-void html_overflow_scroll_drag_end(struct scrollbar *scrollbar,
- browser_mouse_state mouse, int x, int y)
-{
- int scroll_mouse_x, scroll_mouse_y, box_x, box_y;
- struct html_scrollbar_data *data = scrollbar_get_data(scrollbar);
- struct box *box;
-
- box = data->box;
- box_coords(box, &box_x, &box_y);
-
- if (scrollbar_is_horizontal(scrollbar)) {
- scroll_mouse_x = x - box_x;
- scroll_mouse_y = y - (box_y + box->padding[TOP] +
- box->height + box->padding[BOTTOM] -
- SCROLLBAR_WIDTH);
- scrollbar_mouse_drag_end(scrollbar, mouse,
- scroll_mouse_x, scroll_mouse_y);
- } else {
- scroll_mouse_x = x - (box_x + box->padding[LEFT] +
- box->width + box->padding[RIGHT] -
- SCROLLBAR_WIDTH);
- scroll_mouse_y = y - box_y;
- scrollbar_mouse_drag_end(scrollbar, mouse,
- scroll_mouse_x, scroll_mouse_y);
- }
-}
-
-/* Documented in html_internal.h */
-void html_set_drag_type(html_content *html, html_drag_type drag_type,
- union html_drag_owner drag_owner, const struct rect *rect)
-{
- union content_msg_data msg_data;
-
- assert(html != NULL);
-
- html->drag_type = drag_type;
- html->drag_owner = drag_owner;
-
- switch (drag_type) {
- case HTML_DRAG_NONE:
- assert(drag_owner.no_owner == true);
- msg_data.drag.type = CONTENT_DRAG_NONE;
- break;
-
- case HTML_DRAG_SCROLLBAR:
- case HTML_DRAG_TEXTAREA_SCROLLBAR:
- case HTML_DRAG_CONTENT_SCROLL:
- msg_data.drag.type = CONTENT_DRAG_SCROLL;
- break;
-
- case HTML_DRAG_SELECTION:
- assert(drag_owner.no_owner == true);
- /* Fall through */
- case HTML_DRAG_TEXTAREA_SELECTION:
- case HTML_DRAG_CONTENT_SELECTION:
- msg_data.drag.type = CONTENT_DRAG_SELECTION;
- break;
- }
- msg_data.drag.rect = rect;
-
- /* Inform of the content's drag status change */
- content_broadcast((struct content *)html, CONTENT_MSG_DRAG, &msg_data);
-}
-
-/* Documented in html_internal.h */
-void html_set_focus(html_content *html, html_focus_type focus_type,
- union html_focus_owner focus_owner, bool hide_caret,
- int x, int y, int height, const struct rect *clip)
-{
- union content_msg_data msg_data;
- int x_off = 0;
- int y_off = 0;
- struct rect cr;
- bool textarea_lost_focus = html->focus_type == HTML_FOCUS_TEXTAREA &&
- focus_type != HTML_FOCUS_TEXTAREA;
-
- assert(html != NULL);
-
- switch (focus_type) {
- case HTML_FOCUS_SELF:
- assert(focus_owner.self == true);
- if (html->focus_type == HTML_FOCUS_SELF)
- /* Don't need to tell anyone anything */
- return;
- break;
-
- case HTML_FOCUS_CONTENT:
- box_coords(focus_owner.content, &x_off, &y_off);
- break;
-
- case HTML_FOCUS_TEXTAREA:
- box_coords(focus_owner.textarea, &x_off, &y_off);
- break;
- }
-
- html->focus_type = focus_type;
- html->focus_owner = focus_owner;
-
- if (textarea_lost_focus) {
- msg_data.caret.type = CONTENT_CARET_REMOVE;
- } else if (focus_type != HTML_FOCUS_SELF && hide_caret) {
- msg_data.caret.type = CONTENT_CARET_HIDE;
- } else {
- if (clip != NULL) {
- cr = *clip;
- cr.x0 += x_off;
- cr.y0 += y_off;
- cr.x1 += x_off;
- cr.y1 += y_off;
- }
-
- msg_data.caret.type = CONTENT_CARET_SET_POS;
- msg_data.caret.pos.x = x + x_off;
- msg_data.caret.pos.y = y + y_off;
- msg_data.caret.pos.height = height;
- msg_data.caret.pos.clip = (clip == NULL) ? NULL : &cr;
- }
-
- /* Inform of the content's drag status change */
- content_broadcast((struct content *)html, CONTENT_MSG_CARET, &msg_data);
-}
-
-/* Documented in html_internal.h */
-void html_set_selection(html_content *html, html_selection_type selection_type,
- union html_selection_owner selection_owner, bool read_only)
-{
- union content_msg_data msg_data;
- struct box *box;
- bool changed = false;
- bool same_type = html->selection_type == selection_type;
-
- assert(html != NULL);
-
- if ((selection_type == HTML_SELECTION_NONE &&
- html->selection_type != HTML_SELECTION_NONE) ||
- (selection_type != HTML_SELECTION_NONE &&
- html->selection_type == HTML_SELECTION_NONE))
- /* Existance of selection has changed, and we'll need to
- * inform our owner */
- changed = true;
-
- /* Clear any existing selection */
- if (html->selection_type != HTML_SELECTION_NONE) {
- switch (html->selection_type) {
- case HTML_SELECTION_SELF:
- if (same_type)
- break;
- selection_clear(&html->sel, true);
- break;
- case HTML_SELECTION_TEXTAREA:
- if (same_type && html->selection_owner.textarea ==
- selection_owner.textarea)
- break;
- box = html->selection_owner.textarea;
- textarea_clear_selection(box->gadget->data.text.ta);
- break;
- case HTML_SELECTION_CONTENT:
- if (same_type && html->selection_owner.content ==
- selection_owner.content)
- break;
- box = html->selection_owner.content;
- content_clear_selection(box->object);
- break;
- default:
- break;
- }
- }
-
- html->selection_type = selection_type;
- html->selection_owner = selection_owner;
-
- if (!changed)
- /* Don't need to report lack of change to owner */
- return;
-
- /* Prepare msg */
- switch (selection_type) {
- case HTML_SELECTION_NONE:
- assert(selection_owner.none == true);
- msg_data.selection.selection = false;
- break;
- case HTML_SELECTION_SELF:
- assert(selection_owner.none == false);
- /* fall through */
- case HTML_SELECTION_TEXTAREA:
- case HTML_SELECTION_CONTENT:
- msg_data.selection.selection = true;
- break;
- default:
- break;
- }
- msg_data.selection.read_only = read_only;
-
- /* Inform of the content's selection status change */
- content_broadcast((struct content *)html, CONTENT_MSG_SELECTION,
- &msg_data);
-}
diff --git a/render/search.c b/render/search.c
deleted file mode 100644
index ca9520165..000000000
--- a/render/search.c
+++ /dev/null
@@ -1,656 +0,0 @@
-/*
- * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
- * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net>
- * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- * Free text search (core)
- */
-
-#include <ctype.h>
-#include <string.h>
-#include <dom/dom.h>
-
-#include "utils/config.h"
-#include "utils/log.h"
-#include "utils/messages.h"
-#include "utils/utils.h"
-#include "content/content.h"
-#include "content/hlcache.h"
-#include "desktop/selection.h"
-#include "netsurf/search.h"
-#include "netsurf/misc.h"
-#include "desktop/gui_internal.h"
-
-#include "render/box.h"
-#include "render/html.h"
-#include "render/html_internal.h"
-#include "render/search.h"
-#include "render/textplain.h"
-
-#ifndef NOF_ELEMENTS
-#define NOF_ELEMENTS(array) (sizeof(array)/sizeof(*(array)))
-#endif
-
-
-struct list_entry {
- unsigned start_idx; /* start position of match */
- unsigned end_idx; /* end of match */
-
- struct box *start_box; /* used only for html contents */
- struct box *end_box;
-
- struct selection *sel;
-
- struct list_entry *prev;
- struct list_entry *next;
-};
-
-struct search_context {
- void *gui_p;
- struct content *c;
- struct list_entry *found;
- struct list_entry *current; /* first for select all */
- char *string;
- bool prev_case_sens;
- bool newsearch;
- bool is_html;
-};
-
-
-/* Exported function documented in search.h */
-struct search_context * search_create_context(struct content *c,
- content_type type, void *gui_data)
-{
- struct search_context *context;
- struct list_entry *search_head;
-
- if (type != CONTENT_HTML && type != CONTENT_TEXTPLAIN) {
- return NULL;
- }
-
- context = malloc(sizeof(struct search_context));
- if (context == NULL) {
- guit->misc->warning("NoMemory", 0);
- return NULL;
- }
-
- search_head = malloc(sizeof(struct list_entry));
- if (search_head == NULL) {
- guit->misc->warning("NoMemory", 0);
- free(context);
- return NULL;
- }
-
- search_head->start_idx = 0;
- search_head->end_idx = 0;
- search_head->start_box = NULL;
- search_head->end_box = NULL;
- search_head->sel = NULL;
- search_head->prev = NULL;
- search_head->next = NULL;
-
- context->found = search_head;
- context->current = NULL;
- context->string = NULL;
- context->prev_case_sens = false;
- context->newsearch = true;
- context->c = c;
- context->is_html = (type == CONTENT_HTML) ? true : false;
- context->gui_p = gui_data;
-
- return context;
-}
-
-
-/**
- * Release the memory used by the list of matches,
- * deleting selection objects too
- */
-
-static void free_matches(struct search_context *context)
-{
- struct list_entry *a;
- struct list_entry *b;
-
- a = context->found->next;
-
- /* empty the list before clearing and deleting the
- * selections because the the clearing updates the
- * screen immediately, causing nested accesses to the list */
-
- context->found->prev = NULL;
- context->found->next = NULL;
-
- for (; a; a = b) {
- b = a->next;
- if (a->sel) {
- selection_clear(a->sel, true);
- selection_destroy(a->sel);
- }
- free(a);
- }
-}
-
-
-/**
- * Find the first occurrence of 'match' in 'string' and return its index
- *
- * \param string the string to be searched (unterminated)
- * \param s_len length of the string to be searched
- * \param pattern the pattern for which we are searching (unterminated)
- * \param p_len length of pattern
- * \param case_sens true iff case sensitive match required
- * \param m_len accepts length of match in bytes
- * \return pointer to first match, NULL if none
- */
-
-static const char *find_pattern(const char *string, int s_len,
- const char *pattern, int p_len, bool case_sens,
- unsigned int *m_len)
-{
- struct { const char *ss, *s, *p; bool first; } context[16];
- const char *ep = pattern + p_len;
- const char *es = string + s_len;
- const char *p = pattern - 1; /* a virtual '*' before the pattern */
- const char *ss = string;
- const char *s = string;
- bool first = true;
- int top = 0;
-
- while (p < ep) {
- bool matches;
- if (p < pattern || *p == '*') {
- char ch;
-
- /* skip any further asterisks; one is the same as many
- */
- do p++; while (p < ep && *p == '*');
-
- /* if we're at the end of the pattern, yes, it matches
- */
- if (p >= ep) break;
-
- /* anything matches a # so continue matching from
- here, and stack a context that will try to match
- the wildcard against the next character */
-
- ch = *p;
- if (ch != '#') {
- /* scan forwards until we find a match for
- this char */
- if (!case_sens) ch = toupper(ch);
- while (s < es) {
- if (case_sens) {
- if (*s == ch) break;
- } else if (toupper(*s) == ch)
- break;
- s++;
- }
- }
-
- if (s < es) {
- /* remember where we are in case the match
- fails; we may then resume */
- if (top < (int)NOF_ELEMENTS(context)) {
- context[top].ss = ss;
- context[top].s = s + 1;
- context[top].p = p - 1;
- /* ptr to last asterisk */
- context[top].first = first;
- top++;
- }
-
- if (first) {
- ss = s;
- /* remember first non-'*' char */
- first = false;
- }
-
- matches = true;
- } else {
- matches = false;
- }
-
- } else if (s < es) {
- char ch = *p;
- if (ch == '#')
- matches = true;
- else {
- if (case_sens)
- matches = (*s == ch);
- else
- matches = (toupper(*s) == toupper(ch));
- }
- if (matches && first) {
- ss = s; /* remember first non-'*' char */
- first = false;
- }
- } else {
- matches = false;
- }
-
- if (matches) {
- p++; s++;
- } else {
- /* doesn't match,
- * resume with stacked context if we have one */
- if (--top < 0)
- return NULL; /* no match, give up */
-
- ss = context[top].ss;
- s = context[top].s;
- p = context[top].p;
- first = context[top].first;
- }
- }
-
- /* end of pattern reached */
- *m_len = max(s - ss, 1);
- return ss;
-}
-
-
-/**
- * Add a new entry to the list of matches
- *
- * \param start_idx Offset of match start within textual representation
- * \param end_idx Offset of match end
- * \param context The search context to add the entry to.
- * \return Pointer to added entry, NULL iff failed.
- */
-
-static struct list_entry *add_entry(unsigned start_idx, unsigned end_idx,
- struct search_context *context)
-{
- struct list_entry *entry;
-
- /* found string in box => add to list */
- entry = calloc(1, sizeof(*entry));
- if (!entry) {
- guit->misc->warning("NoMemory", 0);
- return NULL;
- }
-
- entry->start_idx = start_idx;
- entry->end_idx = end_idx;
- entry->sel = NULL;
-
- entry->next = 0;
- entry->prev = context->found->prev;
-
- if (context->found->prev == NULL)
- context->found->next = entry;
- else
- context->found->prev->next = entry;
-
- context->found->prev = entry;
-
- return entry;
-}
-
-
-/**
- * Finds all occurrences of a given string in the html box tree
- *
- * \param pattern the string pattern to search for
- * \param p_len pattern length
- * \param cur pointer to the current box
- * \param case_sens whether to perform a case sensitive search
- * \param context The search context to add the entry to.
- * \return true on success, false on memory allocation failure
- */
-static bool find_occurrences_html(const char *pattern, int p_len,
- struct box *cur, bool case_sens,
- struct search_context *context)
-{
- struct box *a;
-
- /* ignore this box, if there's no visible text */
- if (!cur->object && cur->text) {
- const char *text = cur->text;
- unsigned length = cur->length;
-
- while (length > 0) {
- struct list_entry *entry;
- unsigned match_length;
- unsigned match_offset;
- const char *new_text;
- const char *pos = find_pattern(text, length,
- pattern, p_len, case_sens,
- &match_length);
- if (!pos)
- break;
-
- /* found string in box => add to list */
- match_offset = pos - cur->text;
-
- entry = add_entry(cur->byte_offset + match_offset,
- cur->byte_offset +
- match_offset +
- match_length, context);
- if (!entry)
- return false;
-
- entry->start_box = cur;
- entry->end_box = cur;
-
- new_text = pos + match_length;
- length -= (new_text - text);
- text = new_text;
- }
- }
-
- /* and recurse */
- for (a = cur->children; a; a = a->next) {
- if (!find_occurrences_html(pattern, p_len, a, case_sens,
- context))
- return false;
- }
-
- return true;
-}
-
-
-/**
- * Finds all occurrences of a given string in a textplain content
- *
- * \param pattern the string pattern to search for
- * \param p_len pattern length
- * \param c the content to be searched
- * \param case_sens whether to perform a case sensitive search
- * \param context The search context to add the entry to.
- * \return true on success, false on memory allocation failure
- */
-
-static bool find_occurrences_text(const char *pattern, int p_len,
- struct content *c, bool case_sens,
- struct search_context *context)
-{
- int nlines = textplain_line_count(c);
- int line;
-
- for(line = 0; line < nlines; line++) {
- size_t offset, length;
- const char *text = textplain_get_line(c, line,
- &offset, &length);
- if (text) {
- while (length > 0) {
- struct list_entry *entry;
- unsigned match_length;
- size_t start_idx;
- const char *new_text;
- const char *pos = find_pattern(text, length,
- pattern, p_len, case_sens,
- &match_length);
- if (!pos)
- break;
-
- /* found string in line => add to list */
- start_idx = offset + (pos - text);
- entry = add_entry(start_idx, start_idx +
- match_length, context);
- if (!entry)
- return false;
-
- new_text = pos + match_length;
- offset += (new_text - text);
- length -= (new_text - text);
- text = new_text;
- }
- }
- }
-
- return true;
-}
-
-
-/**
- * Search for a string in the box tree
- *
- * \param string the string to search for
- * \param string_len length of search string
- * \param context The search context to add the entry to.
- * \param flags flags to control the search.
- */
-static void search_text(const char *string, int string_len,
- struct search_context *context, search_flags_t flags)
-{
- struct rect bounds;
- struct box *box = NULL;
- union content_msg_data msg_data;
- bool case_sensitive, forwards, showall;
-
- case_sensitive = ((flags & SEARCH_FLAG_CASE_SENSITIVE) != 0) ?
- true : false;
- forwards = ((flags & SEARCH_FLAG_FORWARDS) != 0) ? true : false;
- showall = ((flags & SEARCH_FLAG_SHOWALL) != 0) ? true : false;
-
- if (context->c == NULL)
- return;
-
- if (context->is_html == true) {
- html_content *html = (html_content *)context->c;
-
- box = html->layout;
-
- if (!box)
- return;
- }
-
-
- /* check if we need to start a new search or continue an old one */
- if (context->newsearch) {
- bool res;
-
- if (context->string != NULL)
- free(context->string);
-
- context->current = NULL;
- free_matches(context);
-
- context->string = malloc(string_len + 1);
- if (context->string != NULL) {
- memcpy(context->string, string, string_len);
- context->string[string_len] = '\0';
- }
-
- guit->search->hourglass(true, context->gui_p);
-
- if (context->is_html == true) {
- res = find_occurrences_html(string, string_len,
- box, case_sensitive, context);
- } else {
- res = find_occurrences_text(string, string_len,
- context->c, case_sensitive, context);
- }
-
- if (!res) {
- free_matches(context);
- guit->search->hourglass(false, context->gui_p);
- return;
- }
- guit->search->hourglass(false, context->gui_p);
-
- context->prev_case_sens = case_sensitive;
-
- /* new search, beginning at the top of the page */
- context->current = context->found->next;
- context->newsearch = false;
-
- } else if (context->current != NULL) {
- /* continued search in the direction specified */
- if (forwards) {
- if (context->current->next)
- context->current = context->current->next;
- } else {
- if (context->current->prev)
- context->current = context->current->prev;
- }
- }
-
- guit->search->status((context->current != NULL), context->gui_p);
-
- search_show_all(showall, context);
-
- guit->search->back_state((context->current != NULL) &&
- (context->current->prev != NULL),
- context->gui_p);
- guit->search->forward_state((context->current != NULL) &&
- (context->current->next != NULL),
- context->gui_p);
-
- if (context->current == NULL)
- return;
-
- if (context->is_html == true) {
- /* get box position and jump to it */
- box_coords(context->current->start_box, &bounds.x0, &bounds.y0);
- /* \todo: move x0 in by correct idx */
- box_coords(context->current->end_box, &bounds.x1, &bounds.y1);
- /* \todo: move x1 in by correct idx */
- bounds.x1 += context->current->end_box->width;
- bounds.y1 += context->current->end_box->height;
- } else {
- textplain_coords_from_range(context->c,
- context->current->start_idx,
- context->current->end_idx, &bounds);
- }
-
- msg_data.scroll.area = true;
- msg_data.scroll.x0 = bounds.x0;
- msg_data.scroll.y0 = bounds.y0;
- msg_data.scroll.x1 = bounds.x1;
- msg_data.scroll.y1 = bounds.y1;
- content_broadcast(context->c, CONTENT_MSG_SCROLL, &msg_data);
-}
-
-
-/* Exported function documented in search.h */
-void search_step(struct search_context *context, search_flags_t flags,
- const char *string)
-{
- int string_len;
- int i = 0;
-
- if (context == NULL) {
- guit->misc->warning("SearchError", 0);
- return;
- }
-
- guit->search->add_recent(string, context->gui_p);
-
- string_len = strlen(string);
- for (i = 0; i < string_len; i++)
- if (string[i] != '#' && string[i] != '*')
- break;
- if (i >= string_len) {
- union content_msg_data msg_data;
- free_matches(context);
-
- guit->search->status(true, context->gui_p);
- guit->search->back_state(false, context->gui_p);
- guit->search->forward_state(false, context->gui_p);
-
- msg_data.scroll.area = false;
- msg_data.scroll.x0 = 0;
- msg_data.scroll.y0 = 0;
- content_broadcast(context->c, CONTENT_MSG_SCROLL, &msg_data);
- return;
- }
- search_text(string, string_len, context, flags);
-}
-
-
-/* Exported function documented in search.h */
-bool search_term_highlighted(struct content *c,
- unsigned start_offset, unsigned end_offset,
- unsigned *start_idx, unsigned *end_idx,
- struct search_context *context)
-{
- if (c == context->c) {
- struct list_entry *a;
- for (a = context->found->next; a; a = a->next)
- if (a->sel && selection_defined(a->sel) &&
- selection_highlighted(a->sel,
- start_offset, end_offset,
- start_idx, end_idx))
- return true;
- }
-
- return false;
-}
-
-
-/* Exported function documented in search.h */
-void search_show_all(bool all, struct search_context *context)
-{
- struct list_entry *a;
-
- for (a = context->found->next; a; a = a->next) {
- bool add = true;
- if (!all && a != context->current) {
- add = false;
- if (a->sel) {
- selection_clear(a->sel, true);
- selection_destroy(a->sel);
- a->sel = NULL;
- }
- }
- if (add && !a->sel) {
-
- if (context->is_html == true) {
- html_content *html = (html_content *)context->c;
- a->sel = selection_create(context->c, true);
- if (!a->sel)
- continue;
-
- selection_init(a->sel, html->layout,
- &html->len_ctx);
- } else {
- a->sel = selection_create(context->c, false);
- if (!a->sel)
- continue;
-
- selection_init(a->sel, NULL, NULL);
- }
-
- selection_set_start(a->sel, a->start_idx);
- selection_set_end(a->sel, a->end_idx);
- }
- }
-}
-
-
-/* Exported function documented in search.h */
-void search_destroy_context(struct search_context *context)
-{
- assert(context != NULL);
-
- if (context->string != NULL) {
- guit->search->add_recent(context->string, context->gui_p);
- free(context->string);
- }
-
- guit->search->forward_state(true, context->gui_p);
- guit->search->back_state(true, context->gui_p);
-
- free_matches(context);
- free(context);
-}
diff --git a/render/search.h b/render/search.h
deleted file mode 100644
index 79d1ee3d3..000000000
--- a/render/search.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _NETSURF_RENDER_SEARCH_H_
-#define _NETSURF_RENDER_SEARCH_H_
-
-#include <ctype.h>
-#include <string.h>
-
-#include "desktop/search.h"
-
-struct search_context;
-
-/**
- * create a search_context
- *
- * \param c The content the search_context is connected to
- * \param type The content type of c
- * \param context A context pointer passed to the provider routines.
- * \return A new search context or NULL on error.
- */
-struct search_context *search_create_context(struct content *c,
- content_type type, void *context);
-
-/**
- * Ends the search process, invalidating all state
- * freeing the list of found boxes
- */
-void search_destroy_context(struct search_context *context);
-
-/**
- * Begins/continues the search process
- *
- * \note that this may be called many times for a single search.
- *
- * \param context The search context in use.
- * \param flags The flags forward/back etc
- * \param string The string to match
- */
-void search_step(struct search_context *context, search_flags_t flags,
- const char * string);
-
-/**
- * Specifies whether all matches or just the current match should
- * be highlighted in the search text.
- */
-void search_show_all(bool all, struct search_context *context);
-
-/**
- * Determines whether any portion of the given text box should be
- * selected because it matches the current search string.
- *
- * \param c The content to hilight within.
- * \param start_offset byte offset within text of string to be checked
- * \param end_offset byte offset within text
- * \param start_idx byte offset within string of highlight start
- * \param end_idx byte offset of highlight end
- * \param context The search context to hilight entries from.
- * \return true iff part of the box should be highlighted
- */
-bool search_term_highlighted(struct content *c,
- unsigned start_offset, unsigned end_offset,
- unsigned *start_idx, unsigned *end_idx,
- struct search_context *context);
-
-#endif
diff --git a/render/textplain.h b/render/textplain.h
deleted file mode 100644
index 0f0128e56..000000000
--- a/render/textplain.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright 2006 James Bursa <bursa@users.sourceforge.net>
- * Copyright 2006 Adrian Lees <adrianl@users.sourceforge.net>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- *
- * Interface to content handler for plain text.
- */
-
-#ifndef NETSURF_RENDER_TEXTPLAIN_H
-#define NETSURF_RENDER_TEXTPLAIN_H
-
-#include <stddef.h>
-#include "netsurf/mouse.h"
-
-struct content;
-struct hlcache_handle;
-struct http_parameter;
-struct rect;
-
-/**
- * Initialise the text content handler
- *
- * \return NSERROR_OK on success else appropriate error code.
- */
-nserror textplain_init(void);
-
-
-/**
- * Retrieve number of lines in content
- *
- * \param[in] c Content to retrieve line count from
- * \return Number of lines
- */
-unsigned long textplain_line_count(struct content *c);
-
-
-/**
- * Retrieve the size (in bytes) of text data
- *
- * \param[in] c Content to retrieve size of
- * \return Size, in bytes, of data
- */
-size_t textplain_size(struct content *c);
-
-
-/**
- * Return byte offset within UTF8 textplain content.
- *
- * given the co-ordinates of a point within a textplain content. 'dir'
- * specifies the direction in which to search (-1 = above-left, +1 =
- * below-right) if the co-ordinates are not contained within a line.
- *
- * \param[in] c content of type CONTENT_TEXTPLAIN
- * \param[in] x x ordinate of point
- * \param[in] y y ordinate of point
- * \param[in] dir direction of search if not within line
- * \return byte offset of character containing (or nearest to) point
- */
-size_t textplain_offset_from_coords(struct content *c, int x, int y, int dir);
-
-
-/**
- * Given a range of byte offsets within a UTF8 textplain content,
- * return a box that fully encloses the text
- *
- * \param[in] c content of type CONTENT_TEXTPLAIN
- * \param[in] start byte offset of start of text range
- * \param[in] end byte offset of end
- * \param[out] r rectangle to be completed
- */
-void textplain_coords_from_range(struct content *c,
- unsigned start, unsigned end, struct rect *r);
-
-/**
- * Return a pointer to the requested line of text.
- *
- * \param[in] c content of type CONTENT_TEXTPLAIN
- * \param[in] lineno line number
- * \param[out] poffset receives byte offset of line start within text
- * \param[out] plen receives length of returned line
- * \return pointer to text, or NULL if invalid line number
- */
-char *textplain_get_line(struct content *c, unsigned lineno,
- size_t *poffset, size_t *plen);
-
-
-/**
- * Find line number of byte in text
- *
- * Given a byte offset within the text, return the line number
- * of the line containing that offset.
- *
- * \param[in] c content of type CONTENT_TEXTPLAIN
- * \param[in] offset byte offset within textual representation
- * \return line number, or -1 if offset invalid (larger than size)
- */
-int textplain_find_line(struct content *c, unsigned offset);
-
-
-/**
- * Return a pointer to the raw UTF-8 data, as opposed to the reformatted
- * text to fit the window width. Thus only hard newlines are preserved
- * in the saved/copied text of a selection.
- *
- * \param[in] c content of type CONTENT_TEXTPLAIN
- * \param[in] start starting byte offset within UTF-8 text
- * \param[in] end ending byte offset
- * \param[out] plen receives validated length
- * \return pointer to text, or NULL if no text
- */
-char *textplain_get_raw_data(struct content *c, unsigned start, unsigned end, size_t *plen);
-
-
-/**
- * Get the browser window containing a textplain content
- *
- * \param[in] c text/plain content
- * \return the browser window
- */
-struct browser_window *textplain_get_browser_window(struct content *c);
-
-#endif
diff --git a/resources/FatMessages b/resources/FatMessages
index de8eed6ad..bda91910a 100644
--- a/resources/FatMessages
+++ b/resources/FatMessages
@@ -25,7 +25,7 @@
#
# The split-messages tool requires keys for all languages to be
# grouped together but language order is not important. If a key for a
-# specific language is ommited the default language value will be used
+# specific language is omitted the default language value will be used
# instead (currently en)
#
# If you find something tagged 'all', but it is only relevant to a specific
@@ -34,12 +34,2334 @@
#
# Globals
+# =======
+#
en.all.NetSurf:NetSurf
+zh_CN.all.NetSurf:NetSurf
+
+en.all.NetSurfCopyright:© 2003-2023 The NetSurf Developers
+de.all.NetSurfCopyright:© 2003-2023 die NetSurf Entwickler
+fr.all.NetSurfCopyright:© 2003-2023 Les développeurs de NetSurf
+nl.all.NetSurfCopyright:© 2003-2023 De NetSurf-ontwikkelaars
+it.all.NetSurfCopyright:© 2003-2023 A cura degli sviluppatori di NetSurf
+zh_CN.all.NetSurfCopyright:© 2003-2023 NetSurf å¼€å‘人员
+
+
+# General
+# =======
+#
+# Some general purpose words and phrases
+#
+en.all.Yes:Yes
+de.all.Yes:Ja
+fr.all.Yes:Oui
+it.all.Yes:Si
+nl.all.Yes:Ja
+zh_CN.all.Yes:是
+
+en.all.No:No
+de.all.No:Nein
+fr.all.No:Non
+it.all.No:No
+nl.all.No:Nee
+zh_CN.all.No:å¦
+
+en.all.Replace:Replace file
+de.all.Replace:Ãœberschreiben
+fr.all.Replace:Remplacer le fichier
+it.all.Replace:Sostituisci il file
+nl.all.Replace:Vervang bestand
+zh_CN.all.Replace:替æ¢æ–‡ä»¶
+
+en.all.DontReplace:Don't replace
+de.all.DontReplace:Abbrechen
+fr.all.DontReplace:Ne pas remplacer
+it.all.DontReplace:Non sostituire
+nl.all.DontReplace:Annuleer bewaaractie
+zh_CN.all.DontReplace:ä¸è¦æ›¿æ¢
+
+en.all.Remove:Remove address
+de.all.Remove:Adresse entfernen
+fr.all.Remove:Retirer l’adresse
+it.all.Remove:Rimuovi indirizzo
+nl.all.Remove:Verwijder adres
+zh_CN.all.Remove:删除地å€
+
+en.all.DontRemove:Don't remove
+de.all.DontRemove:Behalten
+fr.all.DontRemove:Ne pas retirer
+it.all.DontRemove:Non rimuovere
+nl.all.DontRemove:Niet verwijderen
+zh_CN.all.DontRemove:ä¸è¦åˆ é™¤
+
+en.all.obj:object
+de.all.obj:Objekt
+fr.all.obj:objet
+it.all.obj:oggetto
+nl.all.obj:object
+zh_CN.all.obj:对象
+
+en.all.objs:objects
+de.all.objs:Objekte
+fr.all.objs:objets
+it.all.objs:oggetti
+nl.all.objs:objecten
+zh_CN.all.objs:对象
+
+en.all.styl:stylesheet
+de.all.styl:Formatvorlage
+fr.all.styl:feuille de styles
+it.all.styl:foglio di stile
+nl.all.styl:stijlblad
+zh_CN.all.styl:æ ·å¼è¡¨
+
+en.all.styls:stylesheets
+de.all.styls:Formatvorlagen
+fr.all.styls:feuilles de styles
+it.all.styls:fogli di stile
+nl.all.styls:stijlbladen
+zh_CN.all.styls:æ ·å¼è¡¨
+
+en.all.OK:OK
+de.all.OK:OK
+fr.all.OK:OK
+it.all.OK:OK
+nl.all.OK:OK
+zh_CN.all.OK:好的
+
+en.all.Selecting:Selecting
+de.all.Selecting:Auswählen
+fr.all.Selecting:Sélection
+it.all.Selecting:Selezione
+nl.all.Selecting:selecteren
+zh_CN.all.Selecting:正在选择
+
+en.all.FrameDrag:Resizing frames
+de.all.FrameDrag:Frames ändern
+fr.all.FrameDrag:Redimensionnement des cadres
+it.all.FrameDrag:Ridimensione dei frame
+nl.all.FrameDrag:frames aan het aanpassen
+zh_CN.all.FrameDrag:正在调整框架大å°
+
+
+# Units
+# =====
+#
+# Decimal prefix
+en.all.Bytes: B
+de.all.Bytes: B
+fr.all.Bytes: o
+it.all.Bytes: Byte
+nl.all.Bytes: B
+zh_CN.all.Bytes: B
+
+en.all.kBytes: kB
+de.all.kBytes: kB
+fr.all.kBytes: ko
+it.all.kBytes: KB
+nl.all.kBytes: KB
+zh_CN.all.kBytes: kB
+
+en.all.MBytes: MB
+de.all.MBytes: MB
+fr.all.MBytes: Mo
+it.all.MBytes: MB
+nl.all.MBytes: MB
+zh_CN.all.MBytes: MB
+
+en.all.GBytes: GB
+de.all.GBytes: GB
+fr.all.GBytes: Go
+it.all.GBytes: GB
+nl.all.GBytes: GB
+zh_CN.all.GBytes: GB
+
+# Binary prefix
+en.all.KiBytes: KiB
+fr.all.KiBytes: Kio
+zh_CN.all.KiBytes: KiB
+
+en.all.MiBytes: MiB
+fr.all.MiBytes: Mio
+zh_CN.all.MiBytes: MiB
+
+en.all.GiBytes: GiB
+fr.all.GiBytes: Gio
+zh_CN.all.GiBytes: GiB
+
+en.all.TiBytes: TiB
+fr.all.TiBytes: Tio
+zh_CN.all.TiBytes: TiB
+
+en.all.PiBytes: PiB
+fr.all.PiBytes: Pio
+zh_CN.all.PiBytes: PiB
+
+en.all.EiBytes: EiB
+fr.all.EiBytes: Eio
+zh_CN.all.EiBytes: EiB
+
+# Content Forms
+# =============
+#
+# This section contains tokens used by forms
+#
+en.all.Form_Submit:Submit
+de.all.Form_Submit:Ãœbertragen
+fr.all.Form_Submit:Envoyer
+it.all.Form_Submit:Invia
+nl.all.Form_Submit:Versturen
+zh_CN.all.Form_Submit:æ交
+
+en.all.Form_Reset:Reset
+de.all.Form_Reset:Zurücksetzen
+fr.all.Form_Reset:Effacer
+it.all.Form_Reset:Resetta
+nl.all.Form_Reset:Opnieuw
+zh_CN.all.Form_Reset:é‡ç½®
+
+en.all.Form_None:
+de.all.Form_None:
+fr.all.Form_None:
+it.all.Form_None:
+nl.all.Form_None:
+zh_CN.all.Form_None:空
+
+en.all.Form_Many:(Many)
+de.all.Form_Many:(Viele)
+fr.all.Form_Many:(Plusieurs)
+it.all.Form_Many:(Molti)
+nl.all.Form_Many:(Veel)
+zh_CN.all.Form_Many:(多个表)
+
+en.all.Form_Drop:Drop file here
+it.all.Form_Drop:Sposta il file qui
+de.all.Form_Drop:Datei hier hinziehen
+fr.all.Form_Drop:Déposer ici votre fichier
+it.all.Form_Drop:Inserisci un file qui
+nl.all.Form_Drop:Bestand hier plaatsen
+zh_CN.all.Form_Drop:å•å‡»ä»¥é€‰æ‹©æ–‡ä»¶
+en.gtk.Form_Drop:Click to select file
+fr.gtk.Form_Drop:Cliquer pour sélectionner un fichier
+it.gtk.Form_Drop:Clicca per selezionare il file
+nl.gtk.Form_Drop:Klik om bestand te selecteren
+en.ro.Form_Drop:Drop file here
+fr.ro.Form_Drop:Déposer ici votre fichier
+it.ro.Form_Drop:Sposta il file qui
+en.ami.Form_Drop:Click or drop file here
+fr.ami.Form_Drop:Cliquer ou déposer un fichier ici
+it.ami.Form_Drop:Clicca o sposta il file qui
+nl.ami.Form_Drop:Sleep bestand hierheen
+en.beos.Form_Drop:Drop file here
+fr.beos.Form_Drop:Déposer ici votre fichier
+it.beos.Form_Drop:Sposta il file qui
+nl.beos.Form_Drop:Sleep bestand hierheen
+en.fb.Form_Drop:Click to select file
+fr.fb.Form_Drop:Cliquer pour sélectionner un fichier
+it.fb.Form_Drop:Clicca per selezionare il file
+nl.fb.Form_Drop:Klik om bestand te selecteren
+en.osx.Form_Drop:Click to select file
+fr.osx.Form_Drop:Cliquer pour sélectionner un fichier
+it.osx.Form_Drop:Clicca per selezionare il file
+
+en.all.FormSelect:Click to choose a form item
+de.all.FormSelect:Anklicken öffnet Auswahlmenü
+fr.all.FormSelect:Cliquer pour choisir un élément du formulaire
+it.all.FormSelect:Clicca per scegliere un oggetto del form
+nl.all.FormSelect:Klikken selecteert een formulieritem
+zh_CN.all.FormSelect:å•å‡»ä»¥é€‰æ‹©è¡¨å•é¡¹
+
+en.all.FormCheckbox:Click to check this option
+de.all.FormCheckbox:Anklicken um die Option an/abzuschalten
+fr.all.FormCheckbox:Cliquer pour cocher cette option
+it.all.FormCheckbox:Clicca per scegliere questa opzione
+nl.all.FormCheckbox:Klikken selecteert deze optie
+zh_CN.all.FormCheckbox:å•å‡»ä»¥é€‰ä¸­æ­¤é€‰é¡¹
+
+en.all.FormRadio:Click to choose this option
+de.all.FormRadio:Anklicken wählt diese Option
+fr.all.FormRadio:Cliquer pour choisir cette option
+it.all.FormRadio:Clicca per selezionare questa opzione
+nl.all.FormRadio:Klikken kiest deze optie
+zh_CN.all.FormRadio:å•å‡»ä»¥é€‰æ‹©æ­¤é€‰é¡¹
+
+en.all.FormSubmit:Send form to %s
+de.all.FormSubmit:Daten übertragen an %s
+fr.all.FormSubmit:Envoyer le formulaire à %s
+it.all.FormSubmit:Invia il risultato del form a: %s
+nl.all.FormSubmit:Informatie versturen naar %s
+zh_CN.all.FormSubmit:å‘é€è¡¨æ ¼åˆ° %s
+
+en.all.FormBadSubmit:Warning: form can not be submitted
+de.all.FormBadSubmit:Achtung: Daten können nicht gesendet werden
+fr.all.FormBadSubmit:Attention : le formulaire n’a pas pu être envoyé
+it.all.FormBadSubmit:Attenzione: Il form non può essere inviato
+nl.all.FormBadSubmit:Waarschuwing: informatie kan niet verzonden worden
+zh_CN.all.FormBadSubmit:警告:无法æ交表格
+
+en.all.FormButton:Warning: button can not be activated
+de.all.FormButton:Achtung: Schaltknopf kann nicht aktiviert werden
+fr.all.FormButton:Attention : le bouton n’a pas pu être activé
+it.all.FormButton:Attenzione: il pulsante non può essere attivato
+nl.all.FormButton:Waarschuwing: knop kan niet geactiveerd worden
+zh_CN.all.FormButton:警告:无法激活按钮
+
+en.all.FormTextarea:Click to edit the text
+de.all.FormTextarea:Anklicken zum Editieren
+fr.all.FormTextarea:Cliquer pour éditer ce texte
+it.all.FormTextarea:Clicca per editare il testo
+nl.all.FormTextarea:Klikken om tekst te bewerken
+zh_CN.all.FormTextarea:å•å‡»ä»¥ç¼–辑文本
+
+en.all.FormTextbox:Click to edit this field
+de.all.FormTextbox:Anklicken zum Bearbeiten des Feldes
+fr.all.FormTextbox:Cliquer pour éditer ce champ
+it.all.FormTextbox:Clicca per editare il campo di testo
+nl.all.FormTextbox:Klikken om dit veld te bewerken
+zh_CN.all.FormTextbox:å•å‡»ä»¥ç¼–辑此字段
+
+en.all.FormReset:Reset form (not implemented)
+de.all.FormReset:Zurücksetzen (nicht implementiert)
+fr.all.FormReset:Effacer le formulaire (non implémenté)
+it.all.FormReset:Resetta il form
+nl.all.FormReset:Formulier opnieuw instellen (niet geïmplemented)
+zh_CN.all.FormReset:é‡ç½®è¡¨æ ¼ï¼ˆæœªå®žçŽ°ï¼‰
+
+en.all.FormFile:Drop a file here to upload it
+de.all.FormFile:Zum Upload Datei hierhin ziehen und fallenlassen
+fr.all.FormFile:Déposer un fichier ici pour le téléverser
+it.all.FormFile:Inserisci un file da inviare qui
+nl.all.FormFile:Het bestand hier plaatsen voor verzenden
+zh_CN.all.FormFile:将文件拖放到在此处上传
+
+en.all.SelectMenu:Select
+de.all.SelectMenu:Auswahl
+fr.all.SelectMenu:Sélectionner
+it.all.SelectMenu:Seleziona
+nl.all.SelectMenu:Selecteer
+zh_CN.all.SelectMenu:选择
+
+
+# Content titles
+# ==============
+#
+en.all.BMPTitle:%s (BMP image %lux%lu pixels)
+de.all.BMPTitle:%s (BMP Bild %lux%lu pixels)
+fr.all.BMPTitle:%s (Image BMP %lux%lu pixels)
+it.all.BMPTitle:%s (Immagine BMP %lux%lu pixel)
+nl.all.BMPTitle:%s (BMP-afbeelding %lux%lu punten)
+zh_CN.all.BMPTitle:%s(BMP å›¾åƒ ï¼…luxï¼…lu åƒç´ ï¼‰
+
+en.all.GIFTitle:%s (GIF image %lux%lu pixels)
+de.all.GIFTitle:%s (GIF Bild %lux%lu pixels)
+fr.all.GIFTitle:%s (Image GIF %lux%lu pixels)
+it.all.GIFTitle:%s (Immagine GIF %lux%lu pixel)
+nl.all.GIFTitle:%s (GIF-afbeelding %lux%lu punten)
+zh_CN.all.GIFTitle:%s(GIF å›¾åƒ ï¼…luxï¼…lu åƒç´ ï¼‰
+
+en.all.ICOTitle:%s (ICO image %lux%lu pixels)
+de.all.ICOTitle:%s (ICO Bild %lux%lu pixels)
+fr.all.ICOTitle:%s (Image BMP %lux%lu pixels)
+it.all.ICOTitle:%s (Immagine ICO %lux%lu pixel)
+nl.all.ICOTitle:%s (ICO-afbeelding %lux%lu punten)
+zh_CN.all.ICOTitle:%s(ICO å›¾åƒ ï¼…luxï¼…lu åƒç´ ï¼‰
+
+en.all.JPEGTitle:%s (JPEG image %lux%lu pixels)
+de.all.JPEGTitle:%s (JPEG Bild %lux%lu pixels)
+fr.all.JPEGTitle:%s (Image JPEG %lux%lu pixels)
+it.all.JPEGTitle:%s (Immagine JPEG %lux%lu pixel)
+nl.all.JPEGTitle:%s (JPEG-afbeelding %lux%lu punten)
+zh_CN.all.JPEGTitle:%s(JPEG å›¾åƒ ï¼…luxï¼…lu åƒç´ ï¼‰
+
+en.all.PNGTitle:%s (PNG image %lux%lu pixels)
+de.all.PNGTitle:%s (PNG Bild %lux%lu pixels)
+fr.all.PNGTitle:%s (Image PNG %lux%lu pixels)
+it.all.PNGTitle:%s (Immagine PNG %lux%lu pixel)
+nl.all.PNGTitle:%s (PNG-afbeelding %lux%lu punten)
+zh_CN.all.PNGTitle:%s(PNG å›¾åƒ ï¼…luxï¼…lu åƒç´ ï¼‰
+
+en.all.SpriteTitle:%s (Sprite image %lux%lu pixels)
+de.all.SpriteTitle:%s (Sprite Bild %lux%lu pixels)
+fr.all.SpriteTitle:%s (Image « sprite » %lux%lu pixels)
+it.all.SpriteTitle:%s (Immagine Sprite %lux%lu pixel)
+nl.all.SpriteTitle:%s (Sprite-afbeelding %lux%lu punten)
+zh_CN.all.SpriteTitle:%s(Sprite å›¾åƒ ï¼…luxï¼…lu åƒç´ ï¼‰
+
+en.all.WebPTitle:%s (WebP image %lux%lu pixels)
+de.all.WebPTitle:%s (WebP Bild %lux%lu pixels)
+fr.all.WebPTitle:%s (Image WebP %lux%lu pixels)
+it.all.WebPTitle:%s (Immagine WebP %lux%lu pixel)
+nl.all.WebPTitle:%s (WebP-afbeelding %lux%lu punten)
+zh_CN.all.WebPTitle:%s(WebP å›¾åƒ ï¼…luxï¼…lu åƒç´ ï¼‰
+
+en.ro.ArtWorksTitle:%s (ArtWorks image %lux%lu pixels)
+de.ro.ArtWorksTitle:%s (ArtWorks Bild %lux%lu pixels)
+fr.ro.ArtWorksTitle:%s (Image ArtWorks %lux%lu pixels)
+it.ro.ArtWorksTitle:%s (Immagine ArtWorks %lux%lu pixel)
+nl.ro.ArtWorksTitle:%s (ArtWorks-afbeelding %lux%lu punten)
+zh_CN.ro.ArtWorksTitle:%s(Artworks å›¾åƒ ï¼…luxï¼…lu åƒç´ ï¼‰
+
+en.ro.DrawTitle:%s (Draw image %lux%lu pixels)
+de.ro.DrawTitle:%s (Draw Bild %lux%lu pixels)
+fr.ro.DrawTitle:%s (Image Draw %lux%lu pixels)
+it.ro.DrawTitle:%s (Immagine Draw %lux%lu pixel)
+nl.ro.DrawTitle:%s (Draw-afbeelding %lux%lu punten)
+zh_CN.ro.DrawTitle:%s(Draw å›¾åƒ ï¼…luxï¼…lu åƒç´ ï¼‰
+
+en.ami.DataTypesTitle:%s (%s image %lux%lu pixels)
+de.ami.DataTypesTitle:%s (%s Bild %lux%lu pixels)
+fr.ami.DataTypesTitle:%s (Image %s %lux%lu pixels)
+it.ami.DataTypesTitle:%s (Immagine %s %lux%lu pixel)
+nl.ami.DataTypesTitle:%s (%s afbeelding %lux%lu punten)
+zh_CN.ami.DataTypesTitle:%s(%s å›¾åƒ ï¼…luxï¼…lu åƒç´ ï¼‰
+
+
+# HTML page character encoding source
+# ===================================
+#
+en.all.Encoding0:from HTTP headers
+de.all.Encoding0:aus HTTP Kopfzeilen
+fr.all.Encoding0:dans les entêtes HTTP
+it.all.Encoding0:da intestazioni HTTP
+nl.all.Encoding0:van HTTP-koppen
+zh_CN.all.Encoding0:从 HTTP 报头
+
+en.all.Encoding1:detected
+de.all.Encoding1:ermittelt
+fr.all.Encoding1:détecté
+it.all.Encoding1:rilevato
+nl.all.Encoding1:gedetecteerd
+zh_CN.all.Encoding1:检测到
+
+en.all.Encoding2:from <meta>
+de.all.Encoding2:aus <meta>
+fr.all.Encoding2:de <meta>
+it.all.Encoding2:da <meta>
+nl.all.Encoding2:van <meta>
+zh_CN.all.Encoding2:从 <meta>
+
+en.all.EncodingUnk:Unknown
+de.all.EncodingUnk:Unbekannt
+fr.all.EncodingUnk:Inconnu
+it.all.EncodingUnk:Sconosciuto
+nl.all.EncodingUnk:Onbekend
+zh_CN.all.EncodingUnk:未知编ç 
+
+
+# Fetching errors
+# ===============
+#
+# Error displayed as an HTML page
+#
+# This section contains error and warning messages which
+# are displayed to the user.
+#
+en.all.Not2xx:Server returned an error
+de.all.Not2xx:Server meldet Fehler zurück
+fr.all.Not2xx:Le serveur a renvoyé une erreur
+it.all.Not2xx:Il server ha riportato un errore
+nl.all.Not2xx:Server meldt een fout
+zh_CN.all.Not2xx:æœåŠ¡å™¨è¿”回错误
+
+en.all.InvalidURL:The address <em>%s</em> could not be understood.
+de.all.InvalidURL:Die Adresse <em>%s</em> konnte nicht ausgewertet werden.
+fr.all.InvalidURL:L’adresse <em>%s</em> n’a pas pu être reconnue.
+it.all.InvalidURL:L'indirizzo <em>%s</em> non è stato riconosciuto.
+nl.all.InvalidURL:Het adres <em>%s</em> klopt niet.
+zh_CN.all.InvalidURL:无法ç†è§£åœ°å€ <em>%s</em>。
+
+
+# HTML error page
+# ===============
+#
+en.all.ErrorPage:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Page error</title></head><body><h1>Sorry, NetSurf was unable to display this page</h1><p><strong>%s</strong></p></body></html>
+de.all.ErrorPage:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Seitenfehler</title></head><body><h1>NetSurf konnte diese Seite leider nicht darstellen.</h1><p><strong>%s</strong></p></body></html>
+fr.all.ErrorPage:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Erreur</title></head><body><h1>Désolé, NetSurf n’a pas pu afficher cette page</h1><p><strong>%s</strong></p></body></html>
+it.all.ErrorPage:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Errore nella pagina</title></head><body><h1>Spiacente, NetSurf non è in grado di visualizzare questa pagina.</h1><p><strong>%s</strong></p></body></html>
+nl.all.ErrorPage:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Pagina fout</title></head><body><h1>Sorry, NetSurf kan deze pagina</h1><p><strong>%s</strong></p>niet tonen.</body></html>
+zh_CN.all.ErrorPage:<!DOCTYPE HTML PUBLIC“-// W3C // DTD HTML 4.01 // zh_CNâ€â€œ http://www.w3.org/TR/html4/strict.dtd“><html><head><meta http-equiv =“ Content-Type†content =“ text / html; charset = UTF-8â€> <title>页é¢é”™è¯¯</title> </head> <body> <h1>抱歉, NetSurf 无法显示此页é¢</ h1> <p> <strong>%s </strong> </p> </body> </html>
+
+
+# General errors
+# ==============
+#
+# Messages shown in dialog box
+#
+# These may be augmented with further relevant information, which
+# is displayed after the contents of the relevant token.
+#
+en.all.NoMemory:NetSurf is running out of memory. Please free some memory and try again.
+de.all.NoMemory:Zu wenig Speicher. Bitte mehr Speicher zur Verfügung stellen und erneut versuchen.
+fr.all.NoMemory:NetSurf a besoin de plus de mémoire. Veuillez libérer de la mémoire et réessayer.
+it.all.NoMemory:Memoria insufficiente per l'esecuzione di NetSurf. Per favore liberane un pò e riprova nuovamente.
+nl.all.NoMemory:NetSurf heeft gebrek aan voldoende geheugen. Maak wat geheugen vrij en probeer het dan nog eens.
+zh_CN.all.NoMemory:NetSurf 内存ä¸è¶³ã€‚请释放一些内存,然åŽé‡è¯•ã€‚
+
+en.all.SaveError:The file could not be saved due to an error:
+de.all.SaveError:Die Datei konnte wegen eines Fehlers nicht gespeichert werden:
+fr.all.SaveError:Le fichier n’a pas pu être sauvé à cause d’une erreur :
+it.all.SaveError:Il file non può essere salvato a causa di un errore:
+nl.all.SaveError:Wegens een fout kan dit bestand niet opgeslagen worden:
+zh_CN.all.SaveError:由于出现错误,无法ä¿å­˜æ­¤æ–‡ä»¶ï¼š
+
+en.all.LoadError:The file could not be loaded due to an error:
+de.all.LoadError:Die Datei konnte wegen eines Fehlers nicht geladen werden:
+fr.all.LoadError:Le fichier n’a pas pu être chargé à cause d’une erreur :
+it.all.LoadError:Il file non può essere caricato a causa di un errore:
+nl.all.LoadError:Wegens een fout kan dit bestand niet geladen worden:
+zh_CN.all.LoadError:由于出现错误,无法加载此文件:
+
+en.all.MiscError:An unexpected error occurred:
+de.all.MiscError:Unerwarteter Fehler:
+fr.all.MiscError:Une erreur inattendue s’est produite :
+it.all.MiscError:Si è verificato un errore inatteso:
+nl.all.MiscError:Er trad een onverwachte fout op:
+zh_CN.all.MiscError:出现错误:
+
+en.all.FileError:File does not exist:
+de.all.FileError:Datei existiert nicht:
+fr.all.FileError:Le fichier n’existe pas :
+it.all.FileError:Il file è inesistente:
+nl.all.FileError:Bestand lijkt niet te bestaan:
+zh_CN.all.FileError:文件ä¸å­˜åœ¨ï¼š
+
+en.all.PrintError:An error occurred when printing:
+de.all.PrintError:Ein Fehler trat während des Druckens auf:
+fr.all.PrintError:Une erreur s’est produite lors de l’impression :
+it.all.PrintError:Si è verificato un errore durante la stampa:
+nl.all.PrintError:Fout tijdens afdrukken:
+zh_CN.all.PrintError:打å°æ—¶å‡ºçŽ°é”™è¯¯ï¼š
+
+en.all.NoDiscSpace:Not enough space available on disc.
+de.all.NoDiscSpace:Nicht genug Speicherplatz auf dem Medium vorhanden.
+fr.all.NoDiscSpace:Pas assez d’espace disque disponible.
+it.all.NoDiscSpace:Spazio insufficiente nel disco.
+nl.all.NoDiscSpace:Onvoldoende ruimte beschikbaar op schijf.
+zh_CN.all.NoDiscSpace:ç£ç›˜ä¸Šæ²¡æœ‰è¶³å¤Ÿçš„å¯ç”¨ç©ºé—´ã€‚
+
+en.all.HotlistSaveError:The hotlist was unable to be correctly saved.
+de.all.HotlistSaveError:Hotlist konnte nicht korrekt gespeichert werden.
+fr.all.HotlistSaveError:Les marque-pages n’ont pas pu être correctement sauvés.
+it.all.HotlistSaveError:Non è stato possibile salvare correttamente i segnalibri.
+nl.all.HotlistSaveError:De favorietenlijst kon niet correct worden bewaard.
+zh_CN.all.HotlistSaveError:无法正确ä¿å­˜æ­¤å¸¸ç”¨åˆ—表。
+
+en.all.TreeLoadError:The tree was unable to be correctly loaded.
+de.all.TreeLoadError:The tree was unable to be correctly loaded.
+fr.all.TreeLoadError:L’arbre n’a pas pu être correctement chargé.
+it.all.TreeLoadError:L'albero della directory non è stato caricato correttamente.
+nl.all.TreeLoadError:De gegevensstructuur kon niet correct worden geladen.
+zh_CN.all.TreeLoadError:无法正确加载此树。
+
+en.all.NoDirError:%s is not a directory
+de.all.NoDirError:%s ist kein Verzeichnis.
+fr.all.NoDirError:%s n’est pas un dossier
+it.all.NoDirError:%s non è una directory
+nl.all.NoDirError:%s is geen map
+zh_CN.all.NoDirError:%s ä¸æ˜¯ç›®å½•
+
+en.all.NoNameError:Please enter a name
+de.all.NoNameError:Bitte einen Namen eingeben.
+fr.all.NoNameError:Merci d’entrer un nom
+it.all.NoNameError:Inserisci un nome
+nl.all.NoNameError:Geef een naam op
+zh_CN.all.NoNameError:请输入å称
+
+en.all.NoURLError:Please enter a URL
+de.all.NoURLError:Bitte eine URL Adresse eingeben.
+fr.all.NoURLError:Merci d’entrer une URL
+it.all.NoURLError:Inserisci un URL
+nl.all.NoURLError:Geef een adres op
+zh_CN.all.NoURLError:请输入 URL
+
+en.all.URIError:NetSurf was unable to parse this URI file due to a syntax error.
+de.all.URIError:NetSurf konnte die URI Datei nicht lesen. Syntax Fehler.
+fr.all.URIError:NetSurf est incapable de traiter ce fichier URI à cause d’une erreur de syntaxe.
+it.all.URIError:NetSurf non è stato in grado di processare questo file URI a causa di un errore di sintassi.
+nl.all.URIError:NetSurf kon dit URI-bestand niet verwerken vanwege een syntaxisfout.
+zh_CN.all.URIError:由于语法错误,NetSurf 无法解æžæ­¤ URI 文件。
+
+en.all.EmptyError:file is empty.
+de.all.EmptyError:Die Datei ist leer.
+fr.all.EmptyError:Le fichier est vide.
+it.all.EmptyError:Il file è vuoto.
+nl.all.EmptyError:bestand is leeg.
+zh_CN.all.EmptyError:文件为空。
+
+en.all.SearchError:Invalid Search.
+de.all.SearchError:Suche fehlerhaft.
+fr.all.SearchError:La recherche n’est pas valide.
+it.all.SearchError:Ricerca non valida.
+nl.all.SearchError:Ongeldige zoekopdracht.
+zh_CN.all.SearchError:无效æœç´¢ã€‚
+
+en.all.EncNotRec:Encoding type not recognised.
+de.all.EncNotRec:Encodierung nicht erkannt.
+fr.all.EncNotRec:Le type d’encodage n’est pas reconnu.
+it.all.EncNotRec:Tipo di codifica sconosciuta.
+nl.all.EncNotRec:Codeertype is niet herkend.
+zh_CN.all.EncNotRec:无法识别编ç ç±»åž‹ã€‚
+
+en.all.FileOpenError:could not open file '%s'
+de.all.FileOpenError:Datei ist nicht zu öffnen: '%s'
+fr.all.FileOpenError:ne parvient pas à ouvrir le fichier « %s »
+it.all.FileOpenError:Impossibile aprire il file '%s'
+nl.all.FileOpenError:kan bestand '%s' niet openen
+zh_CN.all.FileOpenError:无法打开文件“%sâ€
+
+en.all.DirectoryError:directory '%s' already exists
+de.all.DirectoryError:Verzeichnis '%s' existiert bereits.
+fr.all.DirectoryError:le dossier « %s » existe déjà
+it.all.DirectoryError:La directory '%s' è già esistente
+nl.all.DirectoryError:map '%s' bestaat reeds
+zh_CN.all.DirectoryError:目录“%sâ€å·²ç»å­˜åœ¨
+
+en.all.Timeout:This site took too long to respond
+fr.all.Timeout:Ce site met trop de temps à répondre
+it.all.Timeout:Questo sito sta impiegando troppo a rispondere
+zh_CN.all.Timeout:此网站å“应时间过长
+
+en.all.BadURL:The given URL was not able to be parsed
+fr.all.BadURL:L’URL entrée n’a pas pu être parsée
+zh_CN.all.BadURL:给定的 URL 无法解æž
+
+# error messages for RISC OS
+#
+en.ro.PathToURL:An error occurred converting the file path to an URL:
+de.ro.PathToURL:Fehler beim Konvertieren des Dateipfades in eine URL Adresse:
+fr.ro.PathToURL:Une erreur s’est produite en convertissant le chemin du fichier en une URL :
+it.ro.PathToURL:Si è verificato un errore durante la conversione del percorso file nell'URL:
+nl.ro.PathToURL:Fout tijdens het omzetten van het bestandspad naar een adres:
+zh_CN.ro.PathToURL:将文件路径转æ¢ä¸º URL æ—¶å‘生错误:
+
+en.ro.WimpError:An unexpected Window Manager error occurred:
+de.ro.WimpError:Unerwarteter Fehler im Window Manager:
+fr.ro.WimpError:Une erreur inattendue du gestionnaire de fenêtres s’est produite :
+it.ro.WimpError:Si è verificato un errore inatteso nella finestra principale:
+nl.ro.WimpError:Er trad een onverwachte fout op in de Vensterbeheerder:
+zh_CN.ro.WimpError:å‘生窗å£ç®¡ç†å™¨é”™è¯¯ï¼š
+
+en.ro.DragError:An error occurred when dragging the icon:
+de.ro.DragError:Fehler beim Ziehen des Symboles:
+fr.ro.DragError:Une erreur s’est produite lors du déplacement de l’icône :
+it.ro.DragError:Si è verificato un errore durante il trascinamento dell'icona:
+nl.ro.DragError:Fout bij het slepen van het symbool:
+zh_CN.ro.DragError:拖动图标时å‘生错误:
+
+en.ro.MenuError:An error occurred when opening the menu:
+de.ro.MenuError:Fehler beim Öffnen des Menüs:
+fr.ro.MenuError:Une erreur s’est produite lors de l’ouverture du menu :
+it.ro.MenuError:Si è verificato un errore durante l'apertura del menu:
+nl.ro.MenuError:Fout bij het openen van het menu:
+zh_CN.ro.MenuError:打开èœå•æ—¶å‘生错误:
+
+en.ro.DownloadWarn:This download may not complete:
+de.ro.DownloadWarn:Der Download ist wahrscheinlich unvollständig:
+fr.ro.DownloadWarn:Ce téléchargement ne peut pas se terminer :
+it.ro.DownloadWarn:Questo trasferimento potrebbe essere incompleto:
+nl.ro.DownloadWarn:Dit bestand is misschien niet compleet opgehaald:
+zh_CN.ro.DownloadWarn:此下载å¯èƒ½æ— æ³•å®Œæˆï¼š
+
+en.ro.LongURL:The URL for this page is too long for NetSurf to display.
+de.ro.LongURL:The URL for this page is too long for NetSurf to display.
+fr.ro.LongURL:L’URL de cette page est trop longue pour pouvoir être affichée par NetSurf.
+it.ro.LongURL:L'URL di questa pagina è troppo lungo per essere visualizzato su NetSurf.
+nl.ro.LongURL:Het adres van deze pagina is te lang voor NetSurf om te kunnen tonen.
+zh_CN.ro.LongURL:该页é¢çš„ URL 过长, NetSurf 无法显示。
+
+en.ro.FontBadInst:An error occurred when initialising fonts due to the presence of obsolete copies of the ROM fonts on disc. NetSurf will exit and launch a program which will attempt to fix this.
+de.ro.FontBadInst:Font-Initialisierung fehlerhaft. Obsolete Kopien von ROM Fonts auf dem lokalem Speichermedium. Fehlerbehebung startet.
+fr.ro.FontBadInst:Une erreur s’est produite lors de l’initialisation des polices de caractères à cause de la présence de copies obsolètes de polices ROM sur le disque. NetSurf va s’arrêter et lancer un programme pour tenter de réparer ça.
+it.ro.FontBadInst:Si è verificato un errore durante l'inizializzazione dei font a causa della presenza di una copia obsoleta dei font "ROM" nel disco. NetSurf verrà chiuso e si cercherà di lanciare un programma in grado di risolvere questo problema.
+nl.ro.FontBadInst:Probleem ontstaan bij het initialiseren van de lettertypen. Een schijf bevat een map met geactiveerde ROM-lettertypes die overbodig zijn. NetSurf wordt gestopt en activeert een programma die dit probleem probeert te verhelpen.
+zh_CN.ro.FontBadInst:因为ç£ç›˜ä¸Šå­˜åœ¨ ROM 字体的过时副本,åˆå§‹åŒ–字体时出现错误。NetSurf 将退出并å¯åŠ¨ä¸€ä¸ªç”¨äºŽå°è¯•ä¿®å¤æ­¤é—®é¢˜çš„程åºã€‚
+
+en.ro.FontError:Failed to open font "Homerton.Medium" (%s).
+de.ro.FontError:Fehler beim öffnen des Fonts "Homerton.Medium" (%s).
+fr.ro.FontError:Échec d’ouverture de la police « Homerton.Medium » (%s).
+it.ro.FontError:Impossibile aprire il font "Homerton.Medium" (%s).
+nl.ro.FontError:Het lettertypebestand "Homerton.Medium" kan niet worden geopend (%s).
+zh_CN.ro.FontError:无法打开字体“Homerton.Mediumâ€(%s)。
+
+en.ro.Resolvers:No domain name servers are configured, so only browsing local files will be possible. Use Configure to set your name server(s).
+de.ro.Resolvers:Keine Domain Name Servers (DNS) konfiguriert. Nur lokale Dateien sind ladbar. Bitte DNS unter !Boot eintragen.
+fr.ro.Resolvers:Aucun serveur de résolution de nom de domaine n’étant configuré, seul la consultation de fichiers locaux est possible. Utilisez Configure pour définir les serveurs de noms.
+it.ro.Resolvers:Non è stato configurato nessun nome per i domini dei server, perciò sarà possibile effettuare la navigazione dei file solo in modalità locale. Usa "Configura" per impostare il nome (o i nomi) del/dei server.
+nl.ro.Resolvers:Er zijn geen DNS-servers ingesteld, dus kunnen alleen lokale bestanden worden bekeken. Ga naar de netwerkinstellingen via !Boot om de DNS-server(s) in te stellen.
+zh_CN.ro.Resolvers:没有é…置域åæœåŠ¡å™¨ï¼Œå› æ­¤åªèƒ½æµè§ˆæœ¬åœ°æ–‡ä»¶ã€‚ 使用é…ç½®æ¥è®¾ç½®æ‚¨çš„域åæœåŠ¡å™¨ã€‚
+
+en.ro.Template:A window template is missing from the Templates file. Please reinstall NetSurf.
+de.ro.Template:Ein Template für ein Fenster fehlt in der Datei Templates. Bitte NetSurf neu installieren.
+fr.ro.Template:Un modèle de fenêtre est absent du fichier des modèles. Merci de réinstaller NetSurf.
+it.ro.Template:Una finestra di template risulta mancante. Per favore reinstalla NetSurf.
+nl.ro.Template:Er ontbreekt een vensterdefinitie in het Templates-bestand. Installeer NetSurf opnieuw.
+zh_CN.ro.Template:Templates 文件中缺少窗å£æ¨¡æ¿ã€‚请é‡æ–°å®‰è£… NetSurf。
+
+en.ro.NoPathError:To save, drag the icon to a directory display
+de.ro.NoPathError:Symbol in ein Verzeichnisfenster ziehen um zu Speichern.
+fr.ro.NoPathError:Pour enregistrer, déposez cette icône dans la fenêtre d’un dossier
+it.ro.NoPathError:Per salvare, trascina l'icona in una directory di visualizzazione.
+nl.ro.NoPathError:Het symbool naar een geopende mapvenster slepen om te bewaren.
+zh_CN.ro.NoPathError:è‹¥è¦ä¿å­˜ï¼Œè¯·å°†å›¾æ ‡æ‹–动到显示的目录中
+
+en.ro.AWNotSeen:Please locate the AWViewer application and try again.
+de.ro.AWNotSeen:Das Programm AWViewer wurde nicht gefunden.
+fr.ro.AWNotSeen:Merci de définir l’emplacement de l’application AWViewer avant de réessayez.
+it.ro.AWNotSeen:Per favore fornisci l'applicativo AWViewer e riprova nuovamente.
+nl.ro.AWNotSeen:Initialiseer het AWViewer-programma door het op te zoeken en probeer het dan nog eens.
+zh_CN.ro.AWNotSeen:è¯·å®šä½ AWViewer 应用程åºï¼Œç„¶åŽé‡è¯•ã€‚
+
+en.ro.PrintErrorRO2:It appears that the printer is busy.
+de.ro.PrintErrorRO2:Der Drucker scheint beschäftigt zu sein.
+fr.ro.PrintErrorRO2:Il semble que l’imprimante soit occupée.
+it.ro.PrintErrorRO2:La stampante sembra essere occupata.
+nl.ro.PrintErrorRO2:De printer lijkt al bezig te zijn.
+zh_CN.ro.PrintErrorRO2:打å°æœºä¼¼ä¹Žæ­£å¿™ã€‚
+
+en.ro.SprIsNull:Unable to convert image to sprite
+de.ro.SprIsNull:Bild nicht in Sprite konvertierbar
+fr.ro.SprIsNull:Impossible de convertir l’image en « sprite »
+it.ro.SprIsNull:Impossibile convertire l'immagine in sprite.
+nl.ro.SprIsNull:Afbeelding kan niet worden omgezet in een sprite.
+zh_CN.ro.SprIsNull:无法将图åƒè½¬æ¢ä¸ºè´´å›¾
+
+# Error messages for Amiga
+#
+en.ami.CompError:Unable to open
+de.ami.CompError:Nicht zu öffnen
+fr.ami.CompError:Ouverture impossible
+it.ami.CompError:Impossibile aprire
+nl.ami.CompError:Niet te openen
+zh_CN.ami.CompError:无法打开
+
+en.ami.BMConvErr:NetSurf requires guigfx.library to display images in this mode
+de.ami.BMConvErr:NetSurf benötigt die guigfx.library für Bilder in diesem Mode
+fr.ami.BMConvErr:NetSurf requiert guigfx.library pour afficher les images dans ce mode
+it.ami.BMConvErr:NetSurf richiede la guigfx.library per visualizzare le immagini in questa modalità
+nl.ami.BMConvErr:NetSurf requires guigfx.library to display images in this mode
+zh_CN.ami.BMConvErr:在这ç§æ¨¡å¼ä¸‹ï¼ŒNetSurf éœ€è¦ guigfx.library æ¥æ˜¾ç¤ºå›¾åƒ
+
+en.ami.MultiTabClose:Are you sure you want to close multiple tabs?
+de.ami.MultiTabClose:Wirklich mehrere Tabs schließen?
+fr.ami.MultiTabClose:Êtes-vous sûr de vouloir fermer plusieurs onglets en même temps ?
+it.ami.MultiTabClose:Sono rimaste aperte più schede, sei sicuro di voler chiudere NetSurf?
+nl.ami.MultiTabClose:Er zijn meerdere tabbladen geopend. Tabbladen allemaal sluiten?
+zh_CN.ami.MultiTabClose:您确定è¦å…³é—­å¤šä¸ªæ ‡ç­¾é¡µå—?
+
+en.ami.TCPIPShutdown:The TCP/IP stack has signalled that it is about to shutdown and NetSurf must exit. NetSurf will quit in 5 seconds unless this shutdown is aborted.
+de.ami.TCPIPShutdown:Der TCP/IP Stack geht grad' zur Hölle und reißt Netsurf mit sich. In genau 5 Sekunden - es sei denn, der Shutdown wird abgebrochen.
+fr.ami.TCPIPShutdown:La pile TCP/IP a signalé son arrêt et NetSurf doit donc être fermé. NetSurf va s’arrêter dans 5 secondes à moins que cet arrêt soit annulé.
+it.ami.TCPIPShutdown:Lo stack TCP/IP ha dato segnale di essere in procinto di arresto, NetSurf verrà chiuso. NetSurf si chiuderà entro 5 secondi a meno che lo shutdown non venga interrotto.
+nl.ami.TCPIPShutdown:De TCP/IP-stack meldt dat deze wordt afgesloten waardoor NetSurf gestopt moet worden. NetSurf zal stoppen in 5 seconden, tenzij het afsluiten wordt afgebroken.
+zh_CN.ami.TCPIPShutdown:TCP/IP 堆栈已å‘出å³å°†å…³é—­çš„ä¿¡å·ï¼Œå¹¶ä¸” NetSurf 必须退出。除éžä¸­æ­¢å…³æœºï¼Œå¦åˆ™ NetSurf 将在 5 秒钟内退出。
+
+en.ami.AbortShutdown:Abort shutdown
+de.ami.AbortShutdown:Shutdown abbrechen
+fr.ami.AbortShutdown:Annuler l’arrêt
+it.ami.AbortShutdown:Interrompi lo shutdown
+nl.ami.AbortShutdown:Afsluiten afbreken
+zh_CN.ami.AbortShutdown:中止关机
+
+
+# Queries
+# =======
+#
+# This section contains queries which are displayed to the user
+#
+en.all.AbortDownload:Are you sure you wish to abort this download?
+de.all.AbortDownload:Soll das Herunterladen der Datei wirklich abgebrochen werden ?
+fr.all.AbortDownload:Étes-vous sûr de vouloir interrompre ce téléchargement ?
+it.all.AbortDownload:Sei sicuro di voler annullare questo trasferimento?
+nl.all.AbortDownload:Zeker weten dat deze ophaalopdracht afgebroken moet worden?
+zh_CN.all.AbortDownload:您确定è¦ä¸­æ­¢æ­¤ä¸‹è½½ä»»åŠ¡å—?
+
+en.all.QuitDownload:One or more downloads are still in progress. Are you sure you wish to quit?
+de.all.QuitDownload:Das Herunterladen ein oder mehrerer Dateien wurde noch nicht abgeschlossen. Soll NetSurf trotzdem beendet werden ?
+fr.all.QuitDownload:Un ou plusieurs téléchargements sont en cours. Êtes-vous sûr de vouloir quitter ?
+it.all.QuitDownload:Uno o più file si trovano in fase di scaricamento, sei sicuro di voler chiudere NetSurf?
+nl.all.QuitDownload:Eén of meer ophaalopdrachten zijn nog in uitvoering. Toch afbreken?
+zh_CN.all.QuitDownload:一或多个下载任务ä»åœ¨è¿›è¡Œä¸­ã€‚您确定è¦é€€å‡ºå—?
+
+en.all.OverwriteFile:A file with that name already exists and would be lost.
+de.all.OverwriteFile:Eine Datei mit diesem Namen existiert bereits und würde überschrieben werden.
+fr.all.OverwriteFile:Un fichier portant ce nom existe déjà et serait perdu.
+it.all.OverwriteFile:Un file con questo nome è già esistente, continuare comporterà la sovrascrittura del file originale.
+nl.all.OverwriteFile:Een bestand met deze naam bestaat al en zal door deze actie overschreven worden.
+zh_CN.all.OverwriteFile:å·²ç»å­˜åœ¨å…·æœ‰è¯¥å称的文件,原文件将会丢失。
+
+en.all.RemoveHotlist:Are you sure you wish to remove this address from the hotlist?
+de.all.RemoveHotlist:Adresse wirklich aus der Hotlist entfernen?
+fr.all.RemoveHotlist:Êtes-vous sûr de vouloir supprimer cette adresse des marque-pages ?
+it.all.RemoveHotlist:Sei sicuro di voler rimuovere questo indirizzo dai segnalibri?
+nl.all.RemoveHotlist:Zeker weten dat dit adres uit de favorietenlijst verwijderd moet worden?
+zh_CN.all.RemoveHotlist:您确定è¦ä»Žå¸¸ç”¨é¡¹åˆ—表中删除此地å€å—?
+
+
+# Page fetching
+# =============
+#
+# This section contains messages which may be displayed whilst
+# fetching a page or other content
+#
+
+# Fetch status messages - displayed in status bar
+#
+en.all.Progress:%s of %s
+de.all.Progress:%s von %s
+fr.all.Progress:%s reçus de %s
+it.all.Progress:%s di %s
+nl.all.Progress:%s van %s
+zh_CN.all.Progress:第 %s 个,共 %s 个
+
+en.all.ProgressU:%s
+de.all.ProgressU:%s
+fr.all.ProgressU:%s
+it.all.ProgressU:%s
+nl.all.ProgressU:%s
+zh_CN.all.ProgressU:%s
+
+en.all.RecPercent:Received %s (%u%%)
+de.all.RecPercent:Empfangen %s (%u%%)
+fr.all.RecPercent:%s reçus (%u%%)
+it.all.RecPercent:ricevuti %s (%u%%)
+nl.all.RecPercent:ontvangen %s (%u%%)
+zh_CN.all.RecPercent:已收到 %s (%u%%)
+
+en.all.Received:Received %s
+de.all.Received:Empfangen %s
+fr.all.Received:%s reçus
+it.all.Received:ricevuti %s
+nl.all.Received:ontvangen %s
+zh_CN.all.Received:已收到 %s
+
+en.all.Redirecting:Redirecting...
+de.all.Redirecting:Umleiten...
+fr.all.Redirecting:Redirection en cours…
+it.all.Redirecting:redirezione in corso...
+nl.all.Redirecting:doorverwijzen...
+zh_CN.all.Redirecting:正在é‡å®šå‘…
+
+en.all.Loading:Loading
+de.all.Loading:Laden
+fr.all.Loading:Chargement
+it.all.Loading:Caricamento della pagina...
+nl.all.Loading:laden
+zh_CN.all.Loading:正在加载
+
+en.all.Fetching:Fetching data
+de.all.Fetching:Daten holen
+fr.all.Fetching:Récupération des données
+it.all.Fetching:Ricezione
+nl.all.Fetching:ophalen
+zh_CN.all.Fetching:正在æå–æ•°æ®
+
+en.all.Processing:Processing
+de.all.Processing:Auswerten
+fr.all.Processing:Traitement
+it.all.Processing:elaborazione del documento in corso...
+nl.all.Processing:verwerking
+zh_CN.all.Processing:正在处ç†
+
+en.all.Formatting:Formatting
+de.all.Formatting:Formatieren
+fr.all.Formatting:Formatage
+it.all.Formatting:formattazione del documento in corso...
+nl.all.Formatting:opmaken
+zh_CN.all.Formatting:正在排版
+
+en.all.Done:Done
+de.all.Done:Fertiggestellt
+fr.all.Done:Terminé
+it.all.Done:Completato
+nl.all.Done:klaar
+zh_CN.all.Done:已完æˆ
+
+en.all.Stopped:Stopped
+de.all.Stopped:Angehalten
+fr.all.Stopped:Arrêté
+it.all.Stopped:Interrotto
+nl.all.Stopped:gestopt
+zh_CN.all.Stopped:å·²åœæ­¢
+
+# Fetch warning/error messages - displayed in status bar
+#
+en.all.BadRedirect:Bad redirect URL
+de.all.BadRedirect:Falsche URL für Redirect
+fr.all.BadRedirect:Mauvaise URL de redirection
+it.all.BadRedirect:Errata redirezione dell'URL
+nl.all.BadRedirect:foutief doorverwijzen naar adres
+zh_CN.all.BadRedirect:错误的é‡å®šå‘地å€
+
+en.all.FetchFailed:Unable to fetch document
+de.all.FetchFailed:Kann Dokument nicht fetchen
+fr.all.FetchFailed:Récupération du fichier impossible
+it.all.FetchFailed:Impossibile ottenere il documento
+nl.all.FetchFailed:Dit document kan niet worden opgehaald.
+zh_CN.all.FetchFailed:无法获å–文件
+
+en.all.NotCSS:Warning: stylesheet is not CSS
+de.all.NotCSS:Warnung:Stylesheet ist kein CSS
+fr.all.NotCSS:Attention : la feuille de style n’est pas du CSS
+it.all.NotCSS:Attenzione: La dicitura "Foglio di stile" non ha nulla a che vedere con i CSS
+nl.all.NotCSS:melding: stijlblad is geen CSS
+zh_CN.all.NotCSS:警告:样å¼è¡¨ä¸æ˜¯ CSS æ ·å¼
+
+en.all.NotFavIco:Favicon not supported
+de.all.NotFavIco:Favicon wird nicht unterstützt
+fr.all.NotFavIco:Favicon non reconnu
+it.all.NotFavIco:Favicon non supportata
+nl.all.NotFavIco:websitesymbool wordt niet ondersteund
+zh_CN.all.NotFavIco:ä¸æ”¯æŒçš„网站图标
+
+en.all.BadObject:Warning: bad object type
+de.all.BadObject:Warnung: falscher Objekttyp
+fr.all.BadObject:Attention : mauvais type d’objet
+it.all.BadObject:Errore nell'analisi del tipo di oggetto
+nl.all.BadObject:melding: fout objecttype
+zh_CN.all.BadObject:警告:对象类型错误
+
+en.all.ObjError:Error loading object: %s
+de.all.ObjError:Fehler beim Laden des Objektes: %s
+fr.all.ObjError:Erreur lors du chargement de : %s
+it.all.ObjError:Errore nel caricamento dell'oggetto: %s
+nl.all.ObjError:fout bij het laden object: %s
+zh_CN.all.ObjError:加载对象时出错:%s
+
+en.all.ParsingFail:Parsing the document failed.
+de.all.ParsingFail:Dokumentparsing ist fehlgeschlagen.
+fr.all.ParsingFail:L’analyse syntaxique du document a échoué.
+it.all.ParsingFail:Analisi del documento fallita.
+nl.all.ParsingFail:fout bij ontleden van dit document.
+zh_CN.all.ParsingFail:无法解æžæ–‡æ¡£ã€‚
+
+en.all.CSSGeneric:Error processing CSS
+de.all.CSSGeneric:CSS Auswertung klappt nicht
+fr.all.CSSGeneric:Erreur lors du traitement CSS
+nl.all.CSSGeneric:fout bij het verwerken van de CSS
+it.all.CSSGeneric:Errore nell'elaborazione del CSS
+zh_CN.all.CSSGeneric:å¤„ç† CSS 时出错
+
+en.all.CSSBase:Base stylesheet failed to load
+fr.all.CSSBase:Échec de chargement de la feuille de style de base
+nl.all.CSSBase:basisstijlblad kan niet worden geladen
+it.all.CSSBase:Impossibile caricare il foglio di stile base
+zh_CN.all.CSSBase:无法加载基本样å¼è¡¨
+
+en.all.BadGIF:Reading GIF failed.
+de.all.BadGIF:Lesen einer GIF Datei fehlgeschlagen.
+fr.all.BadGIF:Erreur de lecture GIF.
+it.all.BadGIF:Lettura del file GIF fallita.
+nl.all.BadGIF:fout bij lezen GIF.
+zh_CN.all.BadGIF:æ— æ³•èŽ·å– GIF 图åƒã€‚
+
+en.all.BadBMP:Reading BMP failed.
+de.all.BadBMP:Lesen einer BMP Datei fehlgeschlagen.
+fr.all.BadBMP:Erreur de lecture BMP.
+it.all.BadBMP:Lettura del file BMP fallita.
+nl.all.BadBMP:fout bij lezen BMP.
+zh_CN.all.BadBMP:æ— æ³•èŽ·å– BMP 图åƒã€‚
+
+en.all.BadICO:Reading ICO failed.
+de.all.BadICO:Lesen einer ICO Datei fehlgeschlagen.
+fr.all.BadICO:Erreur de lecture ICO.
+it.all.BadICO:Lettura del file ICO fallita.
+nl.all.BadICO:fout bij lezen ICO.
+zh_CN.all.BadICO:æ— æ³•èŽ·å– ICO 图åƒã€‚
+
+en.all.PNGError:Error converting PNG.
+de.all.PNGError:Fehler beim PNG konvertieren.
+fr.all.PNGError:Erreur de conversion PNG.
+it.all.PNGError:Errore durante la conversione PNG.
+nl.all.PNGError:fout bij omzetting PNG.
+zh_CN.all.PNGError:æ— æ³•è½¬æ¢ PNG 图åƒã€‚
+
+en.all.MNGError:Error converting MNG/PNG/JNG: %i
+de.all.MNGError:MNG Library Fehler: %i
+fr.all.MNGError:Erreur dans la bibliothèque MNG/PNG/JNG : %i
+it.all.MNGError:Errore durante la conversione MNG/PNG/JNG: %i
+nl.all.MNGError:MNG-bibliotheekfout: %i
+zh_CN.all.MNGError:æ— æ³•è½¬æ¢ MNG/PNG/JNG 图åƒï¼š%i
+
+en.all.BadSprite:Invalid or corrupt Sprite data.
+de.all.BadSprite:Ungültiges oder beschädigtes Sprite.
+fr.all.BadSprite:Les données du « sprite » sont invalides ou corrompues.
+it.all.BadSprite:Dati del file Sprite invalidi o corrotti.
+nl.all.BadSprite:foutief sprite-bestand.
+zh_CN.all.BadSprite:无效或已æŸå的贴图数æ®ã€‚
+
+
+# HTTP status codes
+# =================
+#
+en.all.HTTP0:OK
+de.all.HTTP0:OK
+fr.all.HTTP0:OK
+it.all.HTTP0:OK
+nl.all.HTTP0:OK
+zh_CN.all.HTTP0:好的
+
+en.all.HTTP200:OK
+de.all.HTTP200:OK
+fr.all.HTTP200:OK
+it.all.HTTP200:OK
+nl.all.HTTP200:OK
+zh_CN.all.HTTP200:好的
+
+en.all.HTTP201:Created
+de.all.HTTP201:Created
+fr.all.HTTP201:Créé
+it.all.HTTP201:Creato
+nl.all.HTTP201:Aangemaakt
+zh_CN.all.HTTP201:已创建
+
+en.all.HTTP202:Accepted
+de.all.HTTP202:Accepted
+fr.all.HTTP202:Accepté
+it.all.HTTP202:Accettato
+nl.all.HTTP202:Aanvaard
+zh_CN.all.HTTP202:已接å—
+
+en.all.HTTP203:Non-authoritative information
+de.all.HTTP203:Non-authoritative information
+fr.all.HTTP203:Information ne faisant pas autorité
+it.all.HTTP203:Informazione non autorevole
+nl.all.HTTP203:Niet-gemachtigde informatie
+zh_CN.all.HTTP203:éžæƒå¨ä¿¡æ¯
+
+en.all.HTTP204:No content
+de.all.HTTP204:No content
+fr.all.HTTP204:Aucun contenu
+it.all.HTTP204:Nessun contenuto
+nl.all.HTTP204:Geen inhoud
+zh_CN.all.HTTP204:无内容
+
+en.all.HTTP205:Reset content
+de.all.HTTP205:Reset content
+fr.all.HTTP205:Réinitialisation du contenu
+it.all.HTTP205:Resetta contenuto
+nl.all.HTTP205:Inhoud opnieuw instellen
+zh_CN.all.HTTP205:é‡è®¾å†…容
+
+en.all.HTTP206:Partial content
+de.all.HTTP206:Partial content
+fr.all.HTTP206:Contenu partiel
+it.all.HTTP206:Contenuto parziale
+nl.all.HTTP206:Gedeeltelijke inhoud
+zh_CN.all.HTTP206:部分内容
+
+en.all.HTTP300:Multiple choices
+de.all.HTTP300:Multiple choices
+fr.all.HTTP300:Choix multiples
+it.all.HTTP300:Scelte multiple
+nl.all.HTTP300:Meerkeuze
+zh_CN.all.HTTP300:多é‡é€‰æ‹©
+
+en.all.HTTP301:Moved permanently
+de.all.HTTP301:Moved permanently
+fr.all.HTTP301:A changé d’adresse définitivement
+it.all.HTTP301:Rimosso permanentemente
+nl.all.HTTP301:Definitief verplaatst
+zh_CN.all.HTTP301:永久移动
+
+en.all.HTTP302:Found
+de.all.HTTP302:Found
+fr.all.HTTP302:Trouvé
+it.all.HTTP302:Trovato
+nl.all.HTTP302:Gevonden
+zh_CN.all.HTTP302:已找到
+
+en.all.HTTP303:See other
+de.all.HTTP303:See other
+fr.all.HTTP303:Voir autre
+it.all.HTTP303:Mostra altro
+nl.all.HTTP303:Zie andere
+zh_CN.all.HTTP303:查看其他
+
+en.all.HTTP304:Not modified
+de.all.HTTP304:Not modified
+fr.all.HTTP304:Non modifié
+it.all.HTTP304:Non modificato
+nl.all.HTTP304:Niet gewijzigd
+zh_CN.all.HTTP304:未修改
+
+en.all.HTTP305:Use proxy
+de.all.HTTP305:Use proxy
+fr.all.HTTP305:Utilisez un proxy
+it.all.HTTP305:Usa Proxy
+nl.all.HTTP305:Gebruik Proxy
+zh_CN.all.HTTP305:使用代ç†æœåŠ¡å™¨
+
+en.all.HTTP307:Temporary redirect
+de.all.HTTP307:Temporary redirect
+fr.all.HTTP307:Redirection temporaire
+it.all.HTTP307:Redirezione temporanea
+nl.all.HTTP307:Tijdelijke omleiding
+zh_CN.all.HTTP307:临时é‡å®šå‘
+
+en.all.HTTP400:Bad request
+de.all.HTTP400:Bad request
+fr.all.HTTP400:Mauvaise requête
+it.all.HTTP400:Richiesta errata
+nl.all.HTTP400:Foute aanvraag
+zh_CN.all.HTTP400:错误请求
+
+en.all.HTTP401:Unauthorized
+de.all.HTTP401:Unauthorized
+fr.all.HTTP401:Non autorisé
+it.all.HTTP401:Autorizzazione negata
+nl.all.HTTP401:Niet geautoriseerd
+zh_CN.all.HTTP401:未ç»æŽˆæƒ
+
+en.all.HTTP402:Payment required
+de.all.HTTP402:Payment required
+fr.all.HTTP402:Paiment nécessaire
+it.all.HTTP402:Richiesta di pagamento
+nl.all.HTTP402:Betalende toegang
+zh_CN.all.HTTP402:需è¦æ”¯ä»˜
+
+en.all.HTTP403:Forbidden
+de.all.HTTP403:Forbidden
+fr.all.HTTP403:Interdit
+it.all.HTTP403:Vietato
+nl.all.HTTP403:Verboden toegang
+zh_CN.all.HTTP403:å·²ç¦æ­¢
+
+en.all.HTTP404:Not found
+de.all.HTTP404:Not found
+fr.all.HTTP404:Non trouvé
+it.all.HTTP404:Non trovato
+nl.all.HTTP404:Niet gevonden
+zh_CN.all.HTTP404:未找到
+
+en.all.HTTP405:Method not allowed
+de.all.HTTP405:Method not allowed
+fr.all.HTTP405:Méthode non autorisée
+it.all.HTTP405:Metodo non permesso
+nl.all.HTTP405:Methode niet toegestaan
+zh_CN.all.HTTP405:方法ä¸å…许
+
+en.all.HTTP406:Not acceptable
+de.all.HTTP406:Not acceptable
+fr.all.HTTP406:Non acceptable
+it.all.HTTP406:Non accettabile
+nl.all.HTTP406:Niet aanvaardbaar
+zh_CN.all.HTTP406:ä¸æŽ¥å—
+
+en.all.HTTP407:Proxy authentication required
+de.all.HTTP407:Proxy authentication required
+fr.all.HTTP407:Authentification via proxy nécessaire
+it.all.HTTP407:Autentificazione Proxy necessaria
+nl.all.HTTP407:Authenticatie op de proxy-server verplicht
+zh_CN.all.HTTP407:需è¦ä»£ç†èº«ä»½éªŒè¯
+
+en.all.HTTP408:Request timeout
+de.all.HTTP408:Request timeout
+fr.all.HTTP408:Délai de requête trop long
+it.all.HTTP408:Timeout della richiesta
+nl.all.HTTP408:Aanvraagtijd verstreken
+zh_CN.all.HTTP408:请求超时
+
+en.all.HTTP409:Conflict
+de.all.HTTP409:Conflict
+fr.all.HTTP409:Conflit
+it.all.HTTP409:Conflitto
+nl.all.HTTP409:Conflict
+zh_CN.all.HTTP409:冲çª
+
+en.all.HTTP410:Gone
+de.all.HTTP410:Gone
+fr.all.HTTP410:Parti
+it.all.HTTP410:Irraggiungibile
+nl.all.HTTP410:Verdwenen
+zh_CN.all.HTTP410:已丢失
+
+en.all.HTTP411:Length required
+de.all.HTTP411:Length required
+fr.all.HTTP411:Taille nécessaire
+it.all.HTTP411:Lunghezza richiesta
+nl.all.HTTP411:Lengte benodigd
+zh_CN.all.HTTP411:长度å—é™
+
+en.all.HTTP412:Precondition failed
+de.all.HTTP412:Precondition failed
+fr.all.HTTP412:Échec de précondition
+it.all.HTTP412:Precondizione fallita
+nl.all.HTTP412:Niet voldaan aan vooraf gestelde voorwaarde
+zh_CN.all.HTTP412:å‰ææ¡ä»¶å¤±è´¥
+
+en.all.HTTP413:Request entity too large
+de.all.HTTP413:Request entity too large
+fr.all.HTTP413:Requète trop grande pour cette entité
+it.all.HTTP413:Entità richiesta troppo larga
+nl.all.HTTP413:Aanvraag te groot
+zh_CN.all.HTTP413:请求的实体过大
+
+en.all.HTTP414:Request-URI too long
+de.all.HTTP414:Request-URI too long
+fr.all.HTTP414:L’URI de la requète est trop longue
+it.all.HTTP414:Richiesta URI troppo lunga
+nl.all.HTTP414:Aanvraagadres te lang
+zh_CN.all.HTTP414:请求的 URI 过长
+
+en.all.HTTP415:Unsupported media type
+de.all.HTTP415:Unsupported media type
+fr.all.HTTP415:Type de média non supporté
+it.all.HTTP415:Tipo di media non supportato
+nl.all.HTTP415:Media-type niet ondersteund
+zh_CN.all.HTTP415:ä¸æ”¯æŒçš„媒体类型
+
+en.all.HTTP416:Requested range not satisfiable
+de.all.HTTP416:Requested range not satisfiable
+fr.all.HTTP416:Plage demandée non satisfaite
+it.all.HTTP416:Estensione richiesta non soddisfabile
+nl.all.HTTP416:Aangevraagd gedeelte niet opvraagbaar
+zh_CN.all.HTTP416:无法满足è¦æ±‚的范围
+
+en.all.HTTP417:Expectation failed
+de.all.HTTP417:Expectation failed
+fr.all.HTTP417:Attente non satisfaite
+it.all.HTTP417:Previsione fallita
+nl.all.HTTP417:Niet voldaan aan verwachting
+zh_CN.all.HTTP417:期望失败
+
+en.all.HTTP500:Internal server error
+de.all.HTTP500:Internal server error
+fr.all.HTTP500:Erreur interne du serveur
+it.all.HTTP500:Errore interno del server
+nl.all.HTTP500:Interne serverfout
+zh_CN.all.HTTP500:内部æœåŠ¡å™¨é”™è¯¯
+
+en.all.HTTP501:Not implemented
+de.all.HTTP501:Not implemented
+fr.all.HTTP501:Non implémenté
+it.all.HTTP501:Non implementata
+nl.all.HTTP501:Niet geïmplementeerd
+zh_CN.all.HTTP501:未执行
+
+en.all.HTTP502:Bad gateway
+de.all.HTTP502:Bad gateway
+fr.all.HTTP502:Mauvaise passerelle
+it.all.HTTP502:Gateway errato
+nl.all.HTTP502:Ongeldige Gateway
+zh_CN.all.HTTP502:错误网关
+
+en.all.HTTP503:Service unavailable
+de.all.HTTP503:Service unavailable
+fr.all.HTTP503:Service non disponible
+it.all.HTTP503:Servizio non disponibile
+nl.all.HTTP503:Dienst niet beschikbaar
+zh_CN.all.HTTP503:ä¸å¯ç”¨æœåŠ¡
+
+en.all.HTTP504:Gateway timeout
+de.all.HTTP504:Gateway timeout
+fr.all.HTTP504:Délai expiré de la passerelle
+it.all.HTTP504:Timeout Gateway
+nl.all.HTTP504:Aanvraagtijd bij Gateway verstreken
+zh_CN.all.HTTP504:网关超时
+
+en.all.HTTP505:HTTP version not supported
+de.all.HTTP505:HTTP version not supported
+fr.all.HTTP505:Version HTTP non supportée
+it.all.HTTP505:Versione HTTP non supportata
+nl.all.HTTP505:HTTP-versie wordt niet ondersteund
+zh_CN.all.HTTP505:ä¸æ”¯æŒçš„ HTTP 版本
+
+
+# Directory browser interface
+# ===========================
+#
+en.all.FileIndex:Index of %s
+de.all.FileIndex:Inhalt von %s
+fr.all.FileIndex:Index de %s
+it.all.FileIndex:Indice di %s
+nl.all.FileIndex:Index van %s
+zh_CN.all.FileIndex:%s 的索引
+
+en.all.FileParent:^ Up to parent directory
+de.all.FileParent:^ Eine Ebene höher
+fr.all.FileParent:^ Répertoire parent
+it.all.FileParent:^ Livello superiore
+nl.all.FileParent:^ Een mapniveau hoger
+zh_CN.all.FileParent:^ 跳转到父目录
+
+en.all.FileDirectory:Directory
+de.all.FileDirectory:Verzeichnis
+fr.all.FileDirectory:Répertoire
+it.all.FileDirectory:Directory
+nl.all.FileDirectory:Map
+zh_CN.all.FileDirectory:文件目录
+
+en.all.FileName:Name
+de.all.FileName:Name
+fr.all.FileName:Nom
+it.all.FileName:Nome
+nl.all.FileName:Naam
+zh_CN.all.FileName:文件å
+
+en.all.FileSize:Size
+de.all.FileSize:Größe
+fr.all.FileSize:Taille
+it.all.FileSize:Dimensione
+nl.all.FileSize:Grootte
+zh_CN.all.FileSize:文件大å°
+
+en.all.FileDate:Date
+de.all.FileDate:Datum
+fr.all.FileDate:Date
+it.all.FileDate:Data
+nl.all.FileDate:Datum
+zh_CN.all.FileDate:文件日期
+
+en.all.FileTime:Time
+de.all.FileTime:Zeit
+fr.all.FileTime:Heure
+it.all.FileTime:Ora
+nl.all.FileTime:Tijd
+zh_CN.all.FileTime:文件时间
+
+en.all.FileType:Type
+de.all.FileType:Typ
+fr.all.FileType:Type
+it.all.FileType:Tipo
+nl.all.FileType:Type
+zh_CN.all.FileType:文件类型
+
+
+# Find text user interface
+# ========================
+#
+# This section contains tokens which are used in the find text
+# dialog box.
+#
+en.all.NotFound:Not found
+de.all.NotFound:nichts
+fr.all.NotFound:Non trouvé
+it.all.NotFound:Non trovato
+nl.all.NotFound:Niet gevonden
+zh_CN.all.NotFound:未找到
+
+en.all.Next:Next
+de.all.Next:Nächster
+fr.all.Next:Suivant
+it.all.Next:Successivo
+nl.all.Next:Volgende
+zh_CN.all.Next:下一页
+
+en.all.Prev:Previous
+de.all.Prev:Vorheriger
+fr.all.Prev:Précédent
+it.all.Prev:Precedente
+nl.all.Prev:Vorige
+zh_CN.all.Prev:上一页
+
+en.all.ShowAll:Show All
+de.all.ShowAll:Alle zeigen
+fr.all.ShowAll:Afficher tout
+it.all.ShowAll:Mostra Tutto
+nl.all.ShowAll:Toon alles
+zh_CN.all.ShowAll:显示全部
-en.all.NetSurfCopyright:© 2003-2017 The NetSurf Developers
-de.all.NetSurfCopyright:© 2003-2017 die NetSurf Entwickler
-nl.all.NetSurfCopyright:© 2003-2017 De NetSurf-ontwikkelaars
-it.all.NetSurfCopyright:© 2003-2017 A cura degli sviluppatori di NetSurf
+en.all.CaseSens:Case Sensitive
+de.all.CaseSens:Groß-/Kleinschreibung
+fr.all.CaseSens:Sensible à la casse
+it.all.CaseSens:Maiuscole/Minuscole
+nl.all.CaseSens:Hoofdlettergevoelig
+zh_CN.all.CaseSens:区分大å°å†™
+
+
+# 401 login user interface
+# ========================
+#
+# This section contains tokens which are used in the 401 login
+# (authentication) dialog box.
+#
+en.all.LoginTitle:Authentication Requested
+it.all.LoginTitle:Richiesta di Autentificazione
+fr.all.LoginTitle:Authentification requise
+zh_CN.all.LoginTitle:è¦æ±‚认è¯
+
+en.all.LoginDescription:The site %s with realm "%s" is requesting credentials for access.
+it.all.LoginDescription:Il sito %s con elementi di tipo realm "%s" richiede delle credenziali per l'accesso.
+fr.all.LoginDescription:Le site %s demande des informations d’identification pour accéder au domaine « %s ».
+zh_CN.all.LoginDescription:域“%2$sâ€çš„站点 %1$s 正在请求访问凭è¯ã€‚
+
+en.all.LoginAgain:The credentials for the site %s and realm "%s" were rejected.
+it.all.LoginAgain:Le credenziali per il sito %s ed il realm "%s" sono state rifiutate.
+fr.all.LoginAgain:Les identifiants pour le site %s et son domaine « %s » ont été rejetés.
+zh_CN.all.LoginAgain:网站 %s 和领域“%sâ€çš„凭è¯è¢«æ‹’ç»ã€‚
+
+en.all.Host:Host
+de.all.Host:Host
+fr.all.Host:Hôte
+it.all.Host:Host
+nl.all.Host:Server
+zh_CN.all.Host:主机
+
+en.all.Realm:Realm
+de.all.Realm:Realm
+fr.all.Realm:Domaine
+it.all.Realm:Realm
+nl.all.Realm:Gebied
+zh_CN.all.Realm:域
+
+en.all.Username:Username
+de.all.Username:Benutzername
+fr.all.Username:Nom d’utilisateur
+it.all.Username:Nome Utente
+nl.all.Username:Gebruikersnaam
+zh_CN.all.Username:用户å
+
+en.all.Password:Password
+de.all.Password:Passwort
+fr.all.Password:Mot de passe
+it.all.Password:Password
+nl.all.Password:Wachtwoord
+zh_CN.all.Password:密ç 
+
+en.all.Login:Login
+de.all.Login:Login
+fr.all.Login:Connexion
+it.all.Login:Login
+nl.all.Login:Login
+zh_CN.all.Login:登录
+
+en.all.Cancel:Cancel
+de.all.Cancel:Abbruch
+fr.all.Cancel:Annuler
+it.all.Cancel:Annulla
+nl.all.Cancel:Annuleer
+zh_CN.all.Cancel:å–消
+
+
+# Privacy error interface
+# =======================
+#
+en.all.PrivacyTitle:Privacy error
+de.all.PrivacyTitle:Datenschutzfehler
+fr.all.PrivacyTitle:Problème de confidentialité
+it.all.PrivacyTitle:Errore della privacy
+nl.all.PrivacyTitle:Privacyfout
+zh_CN.all.PrivacyTitle:用户éšç§é”™è¯¯
+
+en.all.PrivacyDescription:A privacy error occurred while communicating with %s this may be a site configuration error or an attempt to steal private information (passwords, messages or credit cards)
+fr.all.PrivacyDescription:Un problème de confidentialité est apparu lors de la communication avec %s. Cela peut être dû à une erreur de configuration du site ou une tentative de vol d’informations privées (mots de passe, messages, numéros de carte de crédit, …)
+it.all.PrivacyDescription:Si è verificato un errore della privacy durante la comunicazione con %s fai attenzione, questo potrebbe essere un errore di configurazione del sito oppure un tentativo di rubare informazioni private (password, messaggi o numeri di carte di credito)
+zh_CN.all.PrivacyDescription:与 %s 通讯时å‘生éšç§é”™è¯¯ï¼Œè¿™å¯èƒ½æ˜¯ç½‘ç«™é…置错误或试图窃å–ç§äººä¿¡æ¯ï¼ˆå¯†ç ï¼Œæ¶ˆæ¯æˆ–信用å¡ï¼‰å¯¼è‡´çš„
+
+en.all.ViewCertificates:View certificate details
+de.all.ViewCertificates:Zertifikatdetails anzeigen
+fr.all.ViewCertificates:Afficher les détails du certificat
+it.all.ViewCertificates:Visualizza i dettagli del certificato
+nl.all.ViewCertificates:Bekijk certificaatdetails
+zh_CN.all.ViewCertificates:查看è¯ä¹¦è¯¦ç»†ä¿¡æ¯
+
+en.all.ViewCertificatesNotPossible:Certificate information is not available for viewing
+de.all.ViewCertificatesNotPossible:Zertifikatinformationen können nicht angezeigt werden
+fr.all.ViewCertificatesNotPossible:Les informations du certificat ne sont pas disponibles pour la visualisation
+it.all.ViewCertificatesNotPossible:Le informazioni sul certificato non sono disponibili per la visualizzazione
+nl.all.ViewCertificatesNotPossible:Certificaatinformatie is niet beschikbaar voor weergave
+zh_CN.all.ViewCertificatesNotPossible:è¯ä¹¦ä¿¡æ¯ä¸å¯æŸ¥çœ‹
+
+en.all.Proceed:Proceed
+de.all.Proceed:Vorgehen
+fr.all.Proceed:Continuer
+it.all.Proceed:Procedi
+nl.all.Proceed:Doorgaan
+zh_CN.all.Proceed:继续进行
+
+en.all.Backtosafety:Back to safety
+de.all.Backtosafety:Zurück zur Sicherheit
+fr.all.Backtosafety:Retourner en sécurité
+it.all.Backtosafety:Torna al modo sicuro
+nl.all.Backtosafety:Terug naar veiligheid
+zh_CN.all.Backtosafety:返回到安全区域
+
+en.all.SSLCertErrOk:The certificate has no errors.
+fr.all.SSLCertErrOk:Le certificat n’a pas d’erreur.
+it.all.SSLCertErrOk:Il certificato non contiene errori.
+zh_CN.all.SSLCertErrOk:è¯ä¹¦æ²¡æœ‰é”™è¯¯ã€‚
+
+en.all.SSLCertErrUnknown:An unknown error occurred while processing the certificate.
+fr.all.SSLCertErrUnknown:Une erreur inconnue est survenue durant le traitement du certificat.
+it.all.SSLCertErrUnknown:Si è verificato un problema sconosciuto durante l'elaborazione del certificato.
+zh_CN.all.SSLCertErrUnknown:处ç†è¯ä¹¦æ—¶å‘生未知错误。
+
+en.all.SSLCertErrBadIssuer:The issuer of this certificate is not known. This may occur if the browser cannot access the certificate authority (CA) bundle.
+fr.all.SSLCertErrBadIssuer:L’émetteur de ce certificat est inconnu. Cela peut arriver si le navigateur ne peut pas accéder au paquet des certificats d’autorité.
+it.all.SSLCertErrBadIssuer:L'emittente di questo certificato è sconosciuto. Questo può verificarsi se il browser non è in grado di accedere al pacchetto dell'autorità di certificazione (CA).
+zh_CN.all.SSLCertErrBadIssuer:该è¯ä¹¦çš„å‘行者未知。如果æµè§ˆå™¨æ— æ³•è®¿é—®è¯ä¹¦é¢å‘机构(CA)的æ†ç»‘包,则å¯èƒ½ä¼šå‘生这ç§æƒ…况。
+
+en.all.SSLCertErrBadSig:The certificate is improperly signed.
+fr.all.SSLCertErrBadSig:Le certificat est mal signé.
+it.all.SSLCertErrBadSig:Il certificato non è stato firmato correttamente.
+zh_CN.all.SSLCertErrBadSig:è¯ä¹¦ç­¾åä¸æ­£ç¡®ã€‚
+
+en.all.SSLCertErrTooYoung:The certificate is not yet valid.
+fr.all.SSLCertErrTooYoung:Le certificat n’est pas encore valide.
+it.all.SSLCertErrTooYoung:Il certificato non è ancora valido.
+zh_CN.all.SSLCertErrTooYoung:è¯ä¹¦å°šæœªç”Ÿæ•ˆã€‚
+
+en.all.SSLCertErrTooOld:The certificate has expired.
+fr.all.SSLCertErrTooOld:Le certificat a expiré.
+it.all.SSLCertErrTooOld:Il certificato è scaduto.
+zh_CN.all.SSLCertErrTooOld:è¯ä¹¦å·²è¿‡æœŸã€‚
+
+en.all.SSLCertErrSelfSigned:The certificate is self signed.
+fr.all.SSLCertErrSelfSigned:Le certificat est auto-signé.
+it.all.SSLCertErrSelfSigned:Il certificato è autofirmato.
+zh_CN.all.SSLCertErrSelfSigned:è¯ä¹¦æ˜¯è‡ªç­¾å的。
+
+en.all.SSLCertErrChainSelfSigned:The certificate chain is self signed.
+fr.all.SSLCertErrChainSelfSigned:La chaîne de certification est auto-signée.
+it.all.SSLCertErrChainSelfSigned:La catena dei certificati è autofirmata.
+zh_CN.all.SSLCertErrChainSelfSigned:è¯ä¹¦é“¾æ˜¯è‡ªç­¾å的。
+
+en.all.SSLCertErrRevoked:The certificate has been revoked by the issuer.
+fr.all.SSLCertErrRevoked:Le certificat a été révoqué par son émetteur.
+it.all.SSLCertErrRevoked:Il certificato è stato revocato dall'emittente.
+zh_CN.all.SSLCertErrRevoked:该è¯ä¹¦å·²è¢«å‘行者åŠé”€ã€‚
+
+en.all.SSLCertErrHostnameMismatch:The certificate is for a different host than the server.
+fr.all.SSLCertErrHostnameMismatch:Le certificat est pour un nom d’hôte différent de celui du serveur.
+it.all.SSLCertErrHostnameMismatch:Il certificato è per un host diverso rispetto al server.
+zh_CN.all.SSLCertErrHostnameMismatch:è¯ä¹¦ç”¨äºŽä¸ŽæœåŠ¡å™¨ä¸åŒçš„主机。
+
+en.all.SSLCertErrCertMissing:The certificate was missing from the chain.
+fr.all.SSLCertErrCertMissing:Le certificat n’est pas dans la chaîne.
+it.all.SSLCertErrCertMissing:Il certificato mancava dalla catena.
+zh_CN.all.SSLCertErrCertMissing:è¯ä¹¦ä»Žé“¾ä¸­ä¸¢å¤±ã€‚
+
+
+# Timeout error interface
+# =======================
+#
+en.all.TimeoutTitle:Connection timed out
+fr.all.TimeoutTitle:La connexion a expiré
+it.all.TimeoutTitle:Connessione scaduta
+zh_CN.all.TimeoutTitle:连接超时
+
+en.all.TimeoutDescription: A connection to %s could not be established. The site may be temporarily unavailable or too busy to respond.
+fr.all.TimeoutDescription: La connexion à %s n’a pas pu être établie. Le site peut être temporairement injoignable ou trop occupé pour répondre.
+it.all.TimeoutDescription: La connessione a %s non può essere stabilita. Il sito potrebbe essere temporaneamente indisponibile o troppo occupato per rispondere.
+zh_CN.all.TimeoutDescription: 无法连接到 %s。该站点å¯èƒ½æš‚æ—¶ä¸å¯ç”¨æˆ–太ç¹å¿™è€Œæ— æ³•å“应。
+
+en.all.Backtoprevious:Back
+fr.all.Backtoprevious:Retour
+it.all.Backtoprevious:Indietro
+zh_CN.all.Backtoprevious:返回
+
+en.all.TryAgain:Try Again
+fr.all.TryAgain:Essayer à nouveau
+it.all.TryAgain:Ricarica
+zh_CN.all.TryAgain:é‡è¯•
+
+
+# Fetch error interface
+# =======================
+#
+en.all.FetchErrorTitle:Error occurred fetching page
+it.all.FetchErrorTitle:Errore durante il recupero della pagina
+zh_CN.all.FetchErrorTitle:获å–页é¢æ—¶å‘生错误
+
+en.all.FetchErrorDescription:An error occurred when connecting to %s
+it.all.FetchErrorDescription:Si è verificato un errore durante la connessione a %s
+zh_CN.all.FetchErrorDescription:连接到 %s æ—¶å‘生错误
+
+# Generic fetcher failure (really a programming error)
+en.all.FetchFailedToFinish:The fetcher for this request failed to complete
+zh_CN.all.FetchFailedToFinish:无法完æˆæ­¤è¯·æ±‚çš„æå–程åº
+
+
+# SSL certificate viewer
+# ======================
+#
+# This section contains tokens which are used in the
+# SSL certificate viewing dialog box.
+#
+en.all.SSLCerts:SSL certificates
+de.all.SSLCerts:SSL Zertifikat
+fr.all.SSLCerts:Certificats SSL
+it.all.SSLCerts:Certificati SSL
+nl.all.SSLCerts:SSL-certificaten
+zh_CN.all.SSLCerts:SSL è¯ä¹¦
+
+en.all.SSLError:NetSurf failed to verify the authenticity of an SSL certificate. Please verify the details presented below.
+de.all.SSLError:NetSurf konnte ein SSL Zertifikat nicht prüfen. Bitte die Details unten beachten.
+fr.all.SSLError:NetSurf n’a pas réussi à vérifier l’authenticité d’un certificat SSL. Vérifier les détails présentés ci-dessous.
+it.all.SSLError:NetSurf non è stato in grado di verificare l'autenticità di questo certificato SSL, per favore verifica i dettagli presenti di seguito
+nl.all.SSLError:NetSurf kan de authenticiteit van een SSL-certificaat niet controleren. Controleer onderstaande details.
+zh_CN.all.SSLError:NetSurf æ— æ³•éªŒè¯ SSL è¯ä¹¦çš„真实性。请验è¯ä¸‹é¢æ˜¾ç¤ºçš„详细信æ¯ã€‚
+
+en.all.SSL_Certificate_Subject:Subject: %s
+de.all.SSL_Certificate_Subject:Subject: %s
+fr.all.SSL_Certificate_Subject:Objet : %s
+it.all.SSL_Certificate_Subject:Soggetto: %s
+nl.all.SSL_Certificate_Subject:Subjekt: %s
+zh_CN.all.SSL_Certificate_Subject:主题:%s
+
+en.all.SSL_Certificate_Issuer:Issuer: %s
+de.all.SSL_Certificate_Issuer:Issuer: %s
+fr.all.SSL_Certificate_Issuer:Émetteur : %s
+it.all.SSL_Certificate_Issuer:Emittente: %s
+nl.all.SSL_Certificate_Issuer:Uitgever: %s
+zh_CN.all.SSL_Certificate_Issuer:å‘行者:%s
+
+en.all.SSL_Certificate_Version:Version: %ld
+de.all.SSL_Certificate_Version:Version: %ld
+fr.all.SSL_Certificate_Version:Version : %ld
+it.all.SSL_Certificate_Version:Versione: %ld
+nl.all.SSL_Certificate_Version:Versie: %ld
+zh_CN.all.SSL_Certificate_Version:版本:%ld
+
+en.all.SSL_Certificate_ValidFrom:Valid from: %s
+de.all.SSL_Certificate_ValidFrom:Valid from: %s
+fr.all.SSL_Certificate_ValidFrom:Valide à compter du : %s
+it.all.SSL_Certificate_ValidFrom:Valido da: %s
+nl.all.SSL_Certificate_ValidFrom:Geldig vanaf: %s
+zh_CN.all.SSL_Certificate_ValidFrom:有效期从:%s
+
+en.all.SSL_Certificate_ValidTo:Valid until: %s
+de.all.SSL_Certificate_ValidTo:Valid until: %s
+fr.all.SSL_Certificate_ValidTo:Valable jusqu’au : %s
+it.all.SSL_Certificate_ValidTo:Valido fino a: %s
+nl.all.SSL_Certificate_ValidTo:Geldig tot: %s
+zh_CN.all.SSL_Certificate_ValidTo:有效期至:%s
+
+en.all.SSL_Certificate_Type:Type: %i
+de.all.SSL_Certificate_Type:Type: %i
+fr.all.SSL_Certificate_Type:Type : %i
+it.all.SSL_Certificate_Type:Tipo: %i
+nl.all.SSL_Certificate_Type:Type: %i
+zh_CN.all.SSL_Certificate_Type:类型:%i
+
+en.all.SSL_Certificate_Serial:Serial: %ld
+de.all.SSL_Certificate_Serial:Serial: %ld
+fr.all.SSL_Certificate_Serial:Série : %ld
+it.all.SSL_Certificate_Serial:Seriale: %ld
+nl.all.SSL_Certificate_Serial:Serienr.: %ld
+zh_CN.all.SSL_Certificate_Serial:åºåˆ—å·ï¼š%ld
+
+en.all.SSL_Certificate_Accept:Accept
+de.all.SSL_Certificate_Accept:Accept
+fr.all.SSL_Certificate_Accept:Accepter
+it.all.SSL_Certificate_Accept:_Accetta
+nl.all.SSL_Certificate_Accept:Accepteer
+zh_CN.all.SSL_Certificate_Accept:接å—
+
+en.all.SSL_Certificate_Reject:Reject
+de.all.SSL_Certificate_Reject:Reject
+fr.all.SSL_Certificate_Reject:Rejeter
+it.all.SSL_Certificate_Reject:_Rifiuta
+nl.all.SSL_Certificate_Reject:Weiger
+zh_CN.all.SSL_Certificate_Reject:æ‹’ç»
+
+
+# Printing user interface
+# =======================
+#
+# This section contains tokens which are used in the printing
+# dialog box.
+#
+en.all.PrintSheetFilled:sheet is filled
+de.all.PrintSheetFilled:Druckseite
+fr.all.PrintSheetFilled:feuille remplie
+it.all.PrintSheetFilled:Il foglio stampato è pieno
+nl.all.PrintSheetFilled:pagina
+zh_CN.all.PrintSheetFilled:已填写打å°è¡¨å•
+
+en.all.PrintSheetsFilled:sheets are filled
+de.all.PrintSheetsFilled:Druckseiten
+fr.all.PrintSheetsFilled:feuilles remplies
+it.all.PrintSheetsFilled:I fogli stampati sono pieni
+nl.all.PrintSheetsFilled:pagina's
+zh_CN.all.PrintSheetsFilled:已填写打å°è¡¨å•
+
+en.all.Printer:Printer
+de.all.Printer:Drucker
+fr.all.Printer:Imprimante
+it.all.Printer:Stampante
+nl.all.Printer:Printer
+zh_CN.all.Printer:打å°æœº
+
+en.all.Copies:Copies
+de.all.Copies:Kopien
+fr.all.Copies:Copies
+it.all.Copies:Copie
+nl.all.Copies:Kopieën
+zh_CN.all.Copies:副本
+
+en.all.Printing:Printing page
+de.all.Printing:Drucke Seite
+fr.all.Printing:Impression de la page
+it.all.Printing:Stampa della pagina
+nl.all.Printing:Pagina aan het afdrukken
+zh_CN.all.Printing:正在打å°é¡µé¢
+
+
+# Treeview interface
+# ==================
+#
+# This section contains tokens which are used in the treeview
+# component. (For example, in the main hotlist/global history windows)
+#
+
+# Tree URL text
+#
+en.all.TreeAdded:Added: %s
+de.all.TreeAdded:eingetragen am: %s
+fr.all.TreeAdded:Ajoutée : %s
+it.all.TreeAdded:Aggiunto: %s
+nl.all.TreeAdded:Toegevoegd: %s
+zh_CN.all.TreeAdded:新增:%s
+
+en.all.TreeLast:Last visited: %s
+de.all.TreeLast:letzter Besuch: %s
+fr.all.TreeLast:Dernière visite : %s
+it.all.TreeLast:Ultima visita: %s
+nl.all.TreeLast:Laatst bezocht: %s
+zh_CN.all.TreeLast:上次访问:%s
+
+en.all.TreeVisited:Visited: %s
+de.all.TreeVisited:gesehen am: %s
+fr.all.TreeVisited:Visites : %s
+it.all.TreeVisited:Visitato: %s
+nl.all.TreeVisited:Bezocht: %s keer
+zh_CN.all.TreeVisited:访问日期:%s
+
+en.all.TreeVisits:Visits: %i
+de.all.TreeVisits:Besuche gesamt: %i
+fr.all.TreeVisits:Visites : %i
+it.all.TreeVisits:Visite totali: %i
+nl.all.TreeVisits:Bezocht: %i keer
+zh_CN.all.TreeVisits:访问次数:%i
+
+en.all.TreeUnknown:Unknown
+de.all.TreeUnknown:Unbekannt
+fr.all.TreeUnknown:Inconnue
+it.all.TreeUnknown:Sconosciuta/o
+nl.all.TreeUnknown:Onbekend
+zh_CN.all.TreeUnknown:未知
+
+en.all.TreeValue:Value: %s
+de.all.TreeValue:Eintrag: %s
+fr.all.TreeValue:Valeur : %s
+it.all.TreeValue:Valore: %s
+nl.all.TreeValue:Waarde: %s
+zh_CN.all.TreeValue:值:%s
+
+en.all.TreeComment:Comment: %s
+de.all.TreeComment:Kommentar: %s
+fr.all.TreeComment:Commentaire : %s
+it.all.TreeComment:Commento: %s
+nl.all.TreeComment:Commentaar: %s
+zh_CN.all.TreeComment:注释:%s
+
+en.all.TreeDomain:Domain: %s%s
+de.all.TreeDomain:Domain: %s%s
+fr.all.TreeDomain:Domaine : %s%s
+it.all.TreeDomain:Dominio: %s%s
+nl.all.TreeDomain:Domein: %s%s
+zh_CN.all.TreeDomain:域:%s%s
+
+en.all.TreePath:Path: %s%s
+de.all.TreePath:Pfad: %s%s
+fr.all.TreePath:Chemin : %s%s
+it.all.TreePath:Percorso: %s%s
+nl.all.TreePath:Pad: %s%s
+zh_CN.all.TreePath:路径:%s%s
+
+en.all.TreeExpires:Expires: %s
+de.all.TreeExpires:Verfällt: %s
+fr.all.TreeExpires:Expire : %s
+it.all.TreeExpires:Scadenza: %s
+nl.all.TreeExpires:Verloopt op: %s
+zh_CN.all.TreeExpires:过期:%s
+
+en.all.TreeLastUsed:Last used: %s
+de.all.TreeLastUsed:Zuletzt genutzt: %s
+fr.all.TreeLastUsed:Dernière utilisation : %s
+it.all.TreeLastUsed:Ultimo utilizzo: %s
+nl.all.TreeLastUsed:Laatst gebruikt: %s
+zh_CN.all.TreeLastUsed:上次使用:%s
+
+en.all.TreeSecure:Secure hosts only: %s
+de.all.TreeSecure:Nur sichere Hosts: %s
+fr.all.TreeSecure:Uniquement des sites sécurisés : %s
+it.all.TreeSecure:Solo host sicuri: %s
+nl.all.TreeSecure:Alleen veilige sites: %s
+zh_CN.all.TreeSecure:ä»…é™å®‰å…¨ä¸»æœºï¼š%s
+
+en.all.TreeVersion:Version: %s
+de.all.TreeVersion:Version: %s
+fr.all.TreeVersion:Version : %s
+it.all.TreeVersion:Versione: %s
+nl.all.TreeVersion:Versie: %s
+zh_CN.all.TreeVersion:版本:%s
+
+en.all.TreePersistent:Persistent: %s
+de.all.TreePersistent:Persistent: %s
+fr.all.TreePersistent:Persistant : %s
+it.all.TreePersistent:Persistenza: %s
+nl.all.TreePersistent:Permanent: %s
+zh_CN.all.TreePersistent:æŒç»­æ€§ï¼š%s
+
+en.all.TreeHeaders: (from headers)
+de.all.TreeHeaders: (aus Header)
+fr.all.TreeHeaders: (à partir des entêtes)
+it.all.TreeHeaders: (da intestazioni)
+nl.all.TreeHeaders: (van koppen)
+zh_CN.all.TreeHeaders: (æ¥è‡ªæŠ¥å¤´ï¼‰
+
+en.all.TreeVersion0:Netscape
+de.all.TreeVersion0:Netscape
+fr.all.TreeVersion0:Netscape
+it.all.TreeVersion0:Netscape
+nl.all.TreeVersion0:Netscape
+zh_CN.all.TreeVersion0:Netscape
+
+en.all.TreeVersion1:RFC 2109
+de.all.TreeVersion1:RFC 2109
+fr.all.TreeVersion1:RFC 2109
+it.all.TreeVersion1:RFC 2109
+nl.all.TreeVersion1:RFC 2109
+zh_CN.all.TreeVersion1:RFC 2109
+
+en.all.TreeVersion2:RFC 2965
+de.all.TreeVersion2:RFC 2965
+fr.all.TreeVersion2:RFC 2965
+it.all.TreeVersion2:RFC 2965
+nl.all.TreeVersion2:RFC 2965
+zh_CN.all.TreeVersion2:RFC 2965
+
+en.all.TreeSession:Session end
+de.all.TreeSession:Sitzungsende
+fr.all.TreeSession:Fin de session
+it.all.TreeSession:Fine sessione
+nl.all.TreeSession:Sessie-einde
+zh_CN.all.TreeSession:会è¯ç»“æŸ
+
+en.all.TreeUnused:Unused
+de.all.TreeUnused:Nicht benutzt
+fr.all.TreeUnused:Inutilisé
+it.all.TreeUnused:Inutilizzato
+nl.all.TreeUnused:Ongebruikt
+zh_CN.all.TreeUnused:未使用
+
+en.all.TreeImport:Imported URL
+de.all.TreeImport:Importierte URL
+fr.all.TreeImport:URL importée
+it.all.TreeImport:URL importati
+nl.all.TreeImport:Geïmporteerd adres
+zh_CN.all.TreeImport:导入 URL
+
+en.all.TreeNewLink:New address
+de.all.TreeNewLink:New address
+fr.all.TreeNewLink:Nouvelle adresse
+it.all.TreeNewLink:Nuovo indirizzo
+nl.all.TreeNewLink:Nieuw webadres
+zh_CN.all.TreeNewLink:新建地å€
+
+en.all.TreeNewFolder:New directory
+de.all.TreeNewFolder:Neues Verzeichnis
+fr.all.TreeNewFolder:Nouv. répertoire
+it.all.TreeNewFolder:Nuova cartella
+nl.all.TreeNewFolder:Nieuwe map
+zh_CN.all.TreeNewFolder:新建目录
+
+en.all.TreeLaunch:Visit URL
+de.all.TreeLaunch:URL ansehen
+fr.all.TreeLaunch:Visiter l’URL
+it.all.TreeLaunch:Visita URL
+nl.all.TreeLaunch:Bezoek webadres
+zh_CN.all.TreeLaunch:访问 URL
+
+en.all.TreeDelete:Delete
+de.all.TreeDelete:Löschen
+fr.all.TreeDelete:Effacer
+it.all.TreeDelete:Elimina
+nl.all.TreeDelete:Verwijder
+zh_CN.all.TreeDelete:删除
+
+en.all.TreeDefault:Set as default
+de.all.TreeDefault:Set as default
+fr.all.TreeDefault:Définir par défaut
+it.all.TreeDefault:Imposta come predefinito
+nl.all.TreeDefault:Stel in als standaard
+zh_CN.all.TreeDefault:设置为默认值
+
+en.all.TreeClear:Clear default
+de.all.TreeClear:Clear default
+fr.all.TreeClear:Effacer défaut
+it.all.TreeClear:Annulla predefinito
+nl.all.TreeClear:Annuleer standaard
+zh_CN.all.TreeClear:清除默认值
+
+en.ami.TreeEdit:Edit title
+de.ami.TreeEdit:Edit title
+fr.ami.TreeEdit:Modifier le titre
+it.ami.TreeEdit:Modifica titolo
+nl.ami.TreeEdit:Wijzig titel
+zh_CN.ami.TreeEdit:修改标题
+
+# Treeview field labels
+#
+en.all.TreeviewLabelTitle:Title
+de.all.TreeviewLabelTitle:Title
+fr.all.TreeviewLabelTitle:Titre
+it.all.TreeviewLabelTitle:Titolo:
+nl.all.TreeviewLabelTitle:Titel:
+zh_CN.all.TreeviewLabelTitle:标题
+
+en.all.TreeviewLabelURL:URL
+de.all.TreeviewLabelURL:URL
+fr.all.TreeviewLabelURL:URL
+it.all.TreeviewLabelURL:URL:
+nl.all.TreeviewLabelURL:Adres:
+zh_CN.all.TreeviewLabelURL:URL
+
+en.all.TreeviewLabelLastVisit:Last visit
+de.all.TreeviewLabelLastVisit:Last visit
+fr.all.TreeviewLabelLastVisit:Dernière visite
+it.all.TreeviewLabelLastVisit:Ultima visita:
+nl.all.TreeviewLabelLastVisit:Laatste bezoek:
+zh_CN.all.TreeviewLabelLastVisit:上次访问
+
+en.all.TreeviewLabelVisits:Visits
+de.all.TreeviewLabelVisits:Visits
+fr.all.TreeviewLabelVisits:Visites
+it.all.TreeviewLabelVisits:Visite:
+nl.all.TreeviewLabelVisits:Bezocht:
+zh_CN.all.TreeviewLabelVisits:访问次数
+
+en.all.TreeviewLabelPeriod:Period
+de.all.TreeviewLabelPeriod:Period
+fr.all.TreeviewLabelPeriod:Période
+it.all.TreeviewLabelPeriod:Periodo:
+nl.all.TreeviewLabelPeriod:Periode:
+zh_CN.all.TreeviewLabelPeriod:时间段
+
+en.all.TreeviewLabelName:Name
+de.all.TreeviewLabelName:Name
+fr.all.TreeviewLabelName:Nom
+it.all.TreeviewLabelName:Nome:
+nl.all.TreeviewLabelName:Naam:
+zh_CN.all.TreeviewLabelName:å称
+
+en.all.TreeviewLabelContent:Content
+de.all.TreeviewLabelContent:Content
+fr.all.TreeviewLabelContent:Contenu
+it.all.TreeviewLabelContent:Contenuto:
+nl.all.TreeviewLabelContent:Inhoud:
+zh_CN.all.TreeviewLabelContent:内容
+
+en.all.TreeviewLabelDomain:Domain
+de.all.TreeviewLabelDomain:Domain
+fr.all.TreeviewLabelDomain:Domaine
+it.all.TreeviewLabelDomain:Dominio:
+nl.all.TreeviewLabelDomain:Domein:
+zh_CN.all.TreeviewLabelDomain:域
+
+en.all.TreeviewLabelPath:Path
+de.all.TreeviewLabelPath:Path
+fr.all.TreeviewLabelPath:Chemin
+it.all.TreeviewLabelPath:Percorso:
+nl.all.TreeviewLabelPath:Pad:
+zh_CN.all.TreeviewLabelPath:路径
+
+en.all.TreeviewLabelExpires:Expires
+de.all.TreeviewLabelExpires:Expires
+fr.all.TreeviewLabelExpires:Expire
+it.all.TreeviewLabelExpires:Scadenza:
+nl.all.TreeviewLabelExpires:Verloopt:
+zh_CN.all.TreeviewLabelExpires:过期
+
+en.all.TreeviewLabelLastUsed:Last used
+de.all.TreeviewLabelLastUsed:Last used
+fr.all.TreeviewLabelLastUsed:Les dernières utilisées
+it.all.TreeviewLabelLastUsed:Ultimo utilizzo:
+nl.all.TreeviewLabelLastUsed:Laatst gebruikt:
+zh_CN.all.TreeviewLabelLastUsed:上次使用
+
+en.all.TreeviewLabelRestrictions:Restrictions
+de.all.TreeviewLabelRestrictions:Restrictions
+fr.all.TreeviewLabelRestrictions:Restrictions
+it.all.TreeviewLabelRestrictions:Restrizioni:
+nl.all.TreeviewLabelRestrictions:Beperkingen:
+zh_CN.all.TreeviewLabelRestrictions:é™åˆ¶æ¡ä»¶
+
+en.all.TreeviewLabelVersion:Version
+de.all.TreeviewLabelVersion:Version
+fr.all.TreeviewLabelVersion:Version
+it.all.TreeviewLabelVersion:Versione:
+nl.all.TreeviewLabelVersion:Versie:
+zh_CN.all.TreeviewLabelVersion:版本
+
+en.all.TreeviewLabelPersistent:Persistent
+de.all.TreeviewLabelPersistent:Persistent
+fr.all.TreeviewLabelPersistent:Persistant
+it.all.TreeviewLabelPersistent:Persistenza:
+nl.all.TreeviewLabelPersistent:Permanent:
+zh_CN.all.TreeviewLabelPersistent:æŒä¹…性
+
+en.all.TreeviewLabelDomainFolder:Domain folder
+de.all.TreeviewLabelDomainFolder:Domain folder
+fr.all.TreeviewLabelDomainFolder:Dossier de domaine
+it.all.TreeviewLabelDomainFolder:Cartella dominio:
+nl.all.TreeviewLabelDomainFolder:Domeinmap:
+zh_CN.all.TreeviewLabelDomainFolder:域文件夹
+
+en.all.TreeviewLabelSerial:Serial
+de.all.TreeviewLabelSerial:Serial
+fr.all.TreeviewLabelSerial:Série
+it.all.TreeviewLabelSerial:Seriale
+nl.all.TreeviewLabelSerial:Serienr:
+zh_CN.all.TreeviewLabelSerial:åºåˆ—å·
+
+en.all.TreeviewLabelType:Type
+de.all.TreeviewLabelType:Type
+fr.all.TreeviewLabelType:Type
+it.all.TreeviewLabelType:Tipo
+nl.all.TreeviewLabelType:Type:
+zh_CN.all.TreeviewLabelType:类型
+
+en.all.TreeviewLabelValidUntil:Valid until
+de.all.TreeviewLabelValidUntil:Valid until
+fr.all.TreeviewLabelValidUntil:Valable jusqu’au
+it.all.TreeviewLabelValidUntil:Valido fino a
+nl.all.TreeviewLabelValidUntil:Geldig tot:
+zh_CN.all.TreeviewLabelValidUntil:有效期从
+
+en.all.TreeviewLabelValidFrom:Valid from
+de.all.TreeviewLabelValidFrom:Valid from
+fr.all.TreeviewLabelValidFrom:Valable à partir du
+it.all.TreeviewLabelValidFrom:Valido da
+nl.all.TreeviewLabelValidFrom:Geldig vanaf:
+zh_CN.all.TreeviewLabelValidFrom:有效期至
+
+en.all.TreeviewLabelIssuer:Issuer
+de.all.TreeviewLabelIssuer:Issuer
+fr.all.TreeviewLabelIssuer:Émetteur
+it.all.TreeviewLabelIssuer:Emittente
+nl.all.TreeviewLabelIssuer:Uitgever:
+zh_CN.all.TreeviewLabelIssuer:å‘行者
+
+en.all.TreeviewLabelFolder:Folder
+de.all.TreeviewLabelFolder:Folder
+fr.all.TreeviewLabelFolder:Dossier
+it.all.TreeviewLabelFolder:Cartella
+nl.all.TreeviewLabelFolder:Map:
+zh_CN.all.TreeviewLabelFolder:文件夹
+
+# Cookie Manager field values
+#
+en.all.CookieManagerSession:Session
+it.all.CookieManagerSession:Sessione
+zh_CN.all.CookieManagerSession:会è¯
+
+en.all.CookieManagerHTTPS:Secure hosts via https only
+de.all.CookieManagerHTTPS:Secure hosts via https only
+fr.all.CookieManagerHTTPS:Hôtes sécurisés via https uniquement
+it.all.CookieManagerHTTPS:Solo host sicuri via https
+nl.all.CookieManagerHTTPS:Veilige websites alleen via https
+zh_CN.all.CookieManagerHTTPS:仅通过 HTTPS 连接安全主机
+
+en.all.CookieManagerSecure:Secure hosts only
+de.all.CookieManagerSecure:Secure hosts only
+fr.all.CookieManagerSecure:Hôtes sécurisés uniquement
+it.all.CookieManagerSecure:Solo host sicuri
+nl.all.CookieManagerSecure:Alleen veilige verbindingen
+zh_CN.all.CookieManagerSecure:ä»…é™å®‰å…¨ä¸»æœº
+
+en.all.CookieManagerHTTP:HTTP connections only
+de.all.CookieManagerHTTP:HTTP connections only
+fr.all.CookieManagerHTTP:Connexions HTTP uniquement
+it.all.CookieManagerHTTP:Solo connessioni HTTP
+nl.all.CookieManagerHTTP:Alleen HTTP-verbindingen
+zh_CN.all.CookieManagerHTTP:ä»…é™ HTTP 连接
+
+# Hotlist default folder's default name
+#
+en.all.HotlistDefaultFolderName:Unsorted entries
+fr.all.HotlistDefaultFolderName:Entrées non triées
+it.all.HotlistDefaultFolderName:Voci non ordinate
+nl.all.HotlistDefaultFolderName:Ongesorteerde items
+zh_CN.all.HotlistDefaultFolderName:未分类æ¡ç›®
+
+# Default name for new folders
+#
+en.all.NewFolderName:New folder
+de.all.NewFolderName:New folder
+fr.all.NewFolderName:Nouveau dossier
+it.all.NewFolderName:Nuova cartella
+nl.all.NewFolderName:Nieuwe map
+zh_CN.all.NewFolderName:新建文件夹
+
+# Default title
+#
+en.all.NoTitle:<No title>
+de.all.NoTitle:<No title>
+fr.all.NoTitle:<sans titre>
+it.all.NoTitle:<Senza titolo>
+nl.all.NoTitle:<Naamloos>
+zh_CN.all.NoTitle:<无标题>
+
+# Tree export
+#
+en.all.TreeHotlist:NetSurf hotlist
+de.all.TreeHotlist:NetSurf Hotlist
+fr.all.TreeHotlist:Marque-pages de NetSurf
+it.all.TreeHotlist:Segnalibri di NetSurf
+nl.all.TreeHotlist:NetSurf-favorieten
+zh_CN.all.TreeHotlist:NetSurf 常用列表
+
+
+# About user interface tokens
+# ===========================
+#
+# This secion is for tokens that have user information about the browser
+
+en.ami.NetSurfDesc:Small as a mouse, fast as a cheetah and available for free. NetSurf is a multi-platform web browser.
+fr.ami.NetSurfDesc:Petit comme une souris, rapide comme un guépard. NetSurf est un navigateur Web multi-plateforme libre.
+it.ami.NetSurfDesc:Piccolo come un mouse e veloce come un ghepardo! NetSurf, il browser web opensource e multi-piattaforma
+nl.ami.NetSurfDesc:Klein als een muis, snel als een cheetah en gratis beschikbaar. NetSurf is een multi-platform webbrowser.
+zh_CN.ami.NetSurfDesc:NetSurf 体积å°ï¼Œé€Ÿåº¦å¿«ï¼Œå¹¶æä¾›å…è´¹æœåŠ¡ã€‚NetSurf 是一个多平å°çš„网络æµè§ˆå™¨ã€‚
+
+en.gtk.AboutDesc:NetSurf is a small and fast web browser.
+fr.gtk.AboutDesc:NetSurf est un petit, mais rapide, navigateur Web libre.
+it.gtk.AboutDesc:NetSurf, il browser web opensource e multi-piattaforma
+nl.gtk.AboutDesc:NetSurf is een kleine, snelle webbrowser met open broncode.
+zh_CN.gtk.AboutDesc:NetSurf 是一款体积å°ï¼Œé€Ÿåº¦å¿«çš„网络æµè§ˆå™¨ã€‚
+
+
+# Hotlist user interface tokens
+# =============================
+#
+# This section contains tokens which are used in various parts of
+# the hotlist user interface.
+#
+
+# Hotlist sub-window titles
+#
+en.all.NewLink:Create new address
+de.all.NewLink:Neuen Eintrag erstellen
+fr.all.NewLink:Ajouter une nouvelle adresse
+it.all.NewLink:Crea nuovo indirizzo
+nl.all.NewLink:Nieuw adres aanmaken
+zh_CN.all.NewLink:新建地å€
+
+en.all.NewFolder:Create new directory
+de.all.NewFolder:Verzeichnis anlegen
+fr.all.NewFolder:Créer un nouveau dossier
+it.all.NewFolder:Crea nuova cartella
+nl.all.NewFolder:Nieuwe map aanmaken
+zh_CN.all.NewFolder:新建目录
+
+en.all.EditTitle:Edit title
+de.all.EditTitle:Edit title
+fr.all.EditTitle:Modifier le titre
+it.all.EditTitle:Modifica titolo
+nl.all.EditTitle:Wijzig titel
+zh_CN.all.EditTitle:修改标题
+
+en.all.EditLink:Edit address
+de.all.EditLink:Eintrag bearbeiten
+fr.all.EditLink:Modifier l’adresse
+it.all.EditLink:Modifica indirizzo
+nl.all.EditLink:Bewerk adres
+zh_CN.all.EditLink:修改地å€
+
+en.all.EditFolder:Rename directory
+de.all.EditFolder:Verzeichnis umbenennen
+fr.all.EditFolder:Renommer le dossier
+it.all.EditFolder:Rinomina cartella
+nl.all.EditFolder:Hernoem map
+zh_CN.all.EditFolder:é‡å‘½å目录
+
+# Default hotlist page names
+#
+en.all.HotlistHomepage:NetSurf homepage
+de.all.HotlistHomepage:NetSurf Homepage
+fr.all.HotlistHomepage:Page d’accueil de NetSurf
+it.all.HotlistHomepage:Pagina iniziale di NetSurf
+nl.all.HotlistHomepage:NetSurf-startpagina
+zh_CN.all.HotlistHomepage:NetSurf 主页
+
+en.all.HotlistDocumentation:Documentation
+de.all.HotlistDocumentation:Dokumentation
+fr.all.HotlistDocumentation:Documentation
+it.all.HotlistDocumentation:Documentazione
+nl.all.HotlistDocumentation:Documentatie
+zh_CN.all.HotlistDocumentation:文档
+
+en.all.HotlistContact:Contact the NetSurf developers
+de.all.HotlistContact:Contact the NetSurf developers
+fr.all.HotlistContact:Contacter les développeurs de NetSurf
+it.all.HotlistContact:Contatta gli sviluppatori di NetSurf
+nl.all.HotlistContact:Contacteer (Eng.) de NetSurf-ontwikkelaars
+zh_CN.all.HotlistContact:è”ç³» NetSurf å¼€å‘人员
+
+en.all.HotlistDownloads:Download the latest version
+de.all.HotlistDownloads:Download the latest version
+fr.all.HotlistDownloads:Télécharger la dernière version
+it.all.HotlistDownloads:Scarica l'ultima versione
+nl.all.HotlistDownloads:Haal de laatste versie op
+zh_CN.all.HotlistDownloads:下载最新版本
+
+# Default (Amiga) hotlist folder names
+#
+en.ami.HotlistMenu:Hotlist menu
+de.ami.HotlistMenu:Hotlist menu
+fr.ami.HotlistMenu:Menu des marque-pages
+it.ami.HotlistMenu:Menu segnalibri
+nl.ami.HotlistMenu:Favorietenmenu
+zh_CN.ami.HotlistMenu:常用列表èœå•
+
+en.ami.HotlistToolbar:Hotlist toolbar
+de.ami.HotlistToolbar:Hotlist toolbar
+fr.ami.HotlistToolbar:Barre d’outils des marque-pages
+it.ami.HotlistToolbar:Barra segnalibri
+nl.ami.HotlistToolbar:Favorietenwerkbalk
+zh_CN.ami.HotlistToolbar:常用列表工具æ 
+
+
+# Global history user interface tokens
+# ====================================
+#
+# This section contains tokens which are used in various parts of
+# the global history user interface.
+#
+en.all.GlobalHistory:Global history
+de.all.GlobalHistory:History (global)
+fr.all.GlobalHistory:Historique global
+it.all.GlobalHistory:Cronologia globale
+nl.all.GlobalHistory:Browsergeschiedenis
+zh_CN.all.GlobalHistory:全局历å²è®°å½•
+
+en.all.DomainAll:(All domains)
+de.all.DomainAll:(All domains)
+fr.all.DomainAll:(Tous les domaines)
+it.all.DomainAll:(Tutti i domini)
+nl.all.DomainAll:(Alle domeinen)
+zh_CN.all.DomainAll:(所有域)
+
+en.all.DateToday:Today
+de.all.DateToday:Heute
+fr.all.DateToday:Aujourd’hui
+it.all.DateToday:Oggi
+nl.all.DateToday:Vandaag
+zh_CN.all.DateToday:今天
+
+en.all.DateYesterday:Yesterday
+de.all.DateYesterday:Gestern
+fr.all.DateYesterday:Hier
+it.all.DateYesterday:Ieri
+nl.all.DateYesterday:Gisteren
+zh_CN.all.DateYesterday:昨天
+
+en.all.Date2Days:Two days ago
+de.all.Date2Days:vor 2 Tagen
+fr.all.Date2Days:Il y a deux jours
+it.all.Date2Days:2 giorni fa
+nl.all.Date2Days:2 dagen geleden
+zh_CN.all.Date2Days:两天å‰
+
+en.all.Date3Days:Three days ago
+de.all.Date3Days:vor 3 Tagen
+fr.all.Date3Days:Il y a trois jours
+it.all.Date3Days:3 giorni fa
+nl.all.Date3Days:3 dagen geleden
+zh_CN.all.Date3Days:三天å‰
+
+en.all.Date4Days:Four days ago
+de.all.Date4Days:vor 4 Tagen
+fr.all.Date4Days:Il y a quatre jours
+it.all.Date4Days:4 giorni fa
+nl.all.Date4Days:4 dagen geleden
+zh_CN.all.Date4Days:四天å‰
+
+en.all.Date5Days:Five days ago
+de.all.Date5Days:vor 5 Tagen
+fr.all.Date5Days:Il y a cinq jours
+it.all.Date5Days:5 giorni fa
+nl.all.Date5Days:5 dagen geleden
+zh_CN.all.Date5Days:五天å‰
+
+en.all.Date6Days:Six days ago
+de.all.Date6Days:vor 6 Tagen
+fr.all.Date6Days:Il y a six jours
+it.all.Date6Days:6 giorni fa
+nl.all.Date6Days:6 dagen geleden
+zh_CN.all.Date6Days:六天å‰
+
+en.all.Date1Week:A week ago
+de.all.Date1Week:vor einer Woche
+fr.all.Date1Week:Il y a une semaine
+it.all.Date1Week:1 settimana fa
+nl.all.Date1Week:Een week geleden
+zh_CN.all.Date1Week:一周å‰
+
+en.all.Date2Week:Two weeks ago
+de.all.Date2Week:vor 2 Wochen
+fr.all.Date2Week:Il y a 2 semaines
+it.all.Date2Week:2 settimane fa
+nl.all.Date2Week:2 weken geleden
+zh_CN.all.Date2Week:两周å‰
+
+en.all.Date3Week:Three weeks ago
+de.all.Date3Week:vor 3 Wochen
+fr.all.Date3Week:Il y a 3 semaines
+it.all.Date3Week:3 settimane fa
+nl.all.Date3Week:3 weken geleden
+zh_CN.all.Date3Week:三周å‰
+
+en.all.Sunday:Sunday
+de.all.Sunday:Sonntag
+fr.all.Sunday:Dimanche
+it.all.Sunday:Domenica
+nl.all.Sunday:Zondag
+zh_CN.all.Sunday:周天
+
+en.all.Monday:Monday
+de.all.Monday:Montag
+fr.all.Monday:Lundi
+it.all.Monday:Lunedi
+nl.all.Monday:Maandag
+zh_CN.all.Monday:周一
+
+en.all.Tuesday:Tuesday
+de.all.Tuesday:Dienstag
+fr.all.Tuesday:Mardi
+it.all.Tuesday:Martedi
+nl.all.Tuesday:Dinsdag
+zh_CN.all.Tuesday:周二
+
+en.all.Wednesday:Wednesday
+de.all.Wednesday:Mittwoch
+fr.all.Wednesday:Mercredi
+it.all.Wednesday:Mercoledi
+nl.all.Wednesday:Woensdag
+zh_CN.all.Wednesday:周三
+
+en.all.Thursday:Thursday
+de.all.Thursday:Donnerstag
+fr.all.Thursday:Jeudi
+it.all.Thursday:Giovedi
+nl.all.Thursday:Donderdag
+zh_CN.all.Thursday:周四
+
+en.all.Friday:Friday
+de.all.Friday:Freitag
+fr.all.Friday:Vendredi
+it.all.Friday:Venerdi
+nl.all.Friday:Vrijdag
+zh_CN.all.Friday:周五
+
+en.all.Saturday:Saturday
+de.all.Saturday:Samstag
+fr.all.Saturday:Samedi
+it.all.Saturday:Sabato
+nl.all.Saturday:Zaterdag
+zh_CN.all.Saturday:周六
# Menus
@@ -53,50 +2375,69 @@ it.all.NetSurfCopyright:© 2003-2017 A cura degli sviluppatori di NetSurf
en.all.Info:Info
de.all.Info:Information
fr.all.Info:Information
+it.all.Info:Informazioni
nl.all.Info:Informatie
+zh_CN.all.Info:ä¿¡æ¯
+
en.ro.AppHelpNoShortcut:Help...
de.ro.AppHelpNoShortcut:Hilfe...
-fr.ro.AppHelpNoShortcut:Aide...
+fr.ro.AppHelpNoShortcut:Aide…
it.ro.AppHelpNoShortcut:Aiuto...
nl.ro.AppHelpNoShortcut:Hulp...
+zh_CN.ro.AppHelpNoShortcut:帮助…
+
en.beos.AppHelp:Help...
de.beos.AppHelp:Hilfe...
-fr.beos.AppHelp:Aide...
+fr.beos.AppHelp:Aide…
it.beos.AppHelp:Aiuto...
nl.beos.AppHelp:Hulp...
+zh_CN.beos.AppHelp:帮助…
+
en.ro.HotlistShowNoShortcut:Show hotlist...
de.ro.HotlistShowNoShortcut:Hotlist zeigen...
-fr.ro.HotlistShowNoShortcut:Montrer les favoris...
+fr.ro.HotlistShowNoShortcut:Afficher les marque-pages…
it.ro.HotlistShowNoShortcut:Mostra...
nl.ro.HotlistShowNoShortcut:Favorieten...
+zh_CN.ro.HotlistShowNoShortcut:显示常用列表…
+
en.ro.HistGlobalNoShortcut:Show global history...
de.ro.HistGlobalNoShortcut:History (global) zeigen...
-fr.ro.HistGlobalNoShortcut:Montrer l'historique global...
+fr.ro.HistGlobalNoShortcut:Afficher l’historique global…
it.ro.HistGlobalNoShortcut:Mostra cronologia globale...
nl.ro.HistGlobalNoShortcut:Browsergeschiedenis...
+zh_CN.ro.HistGlobalNoShortcut:显示全局历å²è®°å½•â€¦
+
en.all.Open:Open
de.all.Open:Öffnen
fr.all.Open:Ouvrir
it.all.Open:Apri
+zh_CN.all.Open:打开
+
en.all.Choices:Choices...
de.all.Choices:Einstellungen...
-fr.all.Choices:Préférences...
+fr.all.Choices:Préférences…
it.all.Choices:Scegli...
nl.all.Choices:Keuzes...
+zh_CN.all.Choices:选择…
+
en.all.Quit:Quit
de.all.Quit:Beenden
fr.all.Quit:Quitter
it.all.Quit:Esci
nl.all.Quit:Stop
+zh_CN.all.Quit:退出
+
en.beos.QuitAccel:Q
+zh_CN.beos.QuitAccel:Q
# Iconbar -> Open menu
#
en.all.OpenURL:Open URL
de.all.OpenURL:Öffne URL
-fr.all.OpenURL:Ouvrir l'URL
+fr.all.OpenURL:Ouvrir l’URL
it.all.OpenURL:Apri URL
nl.all.OpenURL:Weblocatie
+zh_CN.all.OpenURL:打开 URL
# Main menu
#
@@ -105,138 +2446,193 @@ de.all.Page:Seite
fr.all.Page:Page
it.all.Page:Pagina
nl.all.Page:Pagina
+zh_CN.all.Page:页é¢
+
en.all.Object:Object
de.all.Object:Objekt
fr.all.Object:Objet
it.all.Object:Oggetto
nl.all.Object:Object
+zh_CN.all.Object:对象
+
en.all.Navigate:Navigate
de.all.Navigate:Navigieren
fr.all.Navigate:Navigation
it.all.Navigate:Visualizza
nl.all.Navigate:Navigeer
+zh_CN.all.Navigate:导航
+
en.all.View:Display
de.all.View:Anzeige
fr.all.View:Affichage
-it.all.View:Display
+it.all.View:Mostra
nl.all.View:Weergave
+zh_CN.all.View:显示
+
en.all.Utilities:Utilities
de.all.Utilities:Werkzeuge
fr.all.Utilities:Utilitaires
it.all.Utilities:Utilità
nl.all.Utilities:Diversen
-en.ro.Help:Help
-de.ro.Help:Hilfe
-fr.ro.Help:Aide
-it.ro.Help:Aiuto
-nl.ro.Help:Hulp
+zh_CN.all.Utilities:实用工具
+
+en.all.Help:Help
+de.all.Help:Hilfe
+fr.all.Help:Aide
+it.all.Help:Aiuto
+nl.all.Help:Hulp
+zh_CN.all.Help:帮助
# Main -> Page menu
#
en.ro.PageInfo:Info ^F1
fr.ro.PageInfo:Information ^F1
+it.ro.PageInfo:Informazioni ^F1
nl.ro.PageInfo:Informatie ^F1
+zh_CN.ro.PageInfo:ä¿¡æ¯ ^F1
+
en.ro.Save:Save F3
de.ro.Save:Speichern F3
-fr.ro.Save:Sauver F3
+fr.ro.Save:Enregistrer F3
it.ro.Save:Salva F3
nl.ro.Save:Bewaar F3
+zh_CN.ro.Save:ä¿å­˜ F3
+
en.ro.SaveComp:Full save ⇑F3
de.ro.SaveComp:Alles speichern ⇑F3
-fr.ro.SaveComp:Sauvegarde Complète ⇑F3
+fr.ro.SaveComp:Sauvegarde complète ⇑F3
it.ro.SaveComp:Salva Tutto ⇑F3
nl.ro.SaveComp:Bewaar alles ⇑F3
+zh_CN.ro.SaveComp:全部ä¿å­˜ ↑F3
+
en.all.Export:Export
de.all.Export:Exportieren
fr.all.Export:Exporter
it.all.Export:Esporta
nl.all.Export:Exporteer
+zh_CN.all.Export:导出
+
en.all.SaveURL:Save location
de.all.SaveURL:URL speichern
-fr.all.SaveURL:Sauver le lieu
+fr.all.SaveURL:Enregistrer l’adresse
it.all.SaveURL:Salva indirizzo
nl.all.SaveURL:Bewaar adres
+zh_CN.all.SaveURL:ä¿å­˜ä½ç½®
+
en.ro.Print:Print PRINT
de.ro.Print:Drucken DRUCK
fr.ro.Print:Imprimer PRINT
it.ro.Print:Stampa STAMPA
nl.ro.Print:Druk af PRINT
+zh_CN.ro.Print:æ‰“å° PRINT
+
en.ro.NewWindow:New window ^N
de.ro.NewWindow:Neues Fenster ^N
fr.ro.NewWindow:Nouvelle fenêtre ^N
it.ro.NewWindow:Nuova finestra ^N
nl.ro.NewWindow:Nieuw venster ^N
+zh_CN.ro.NewWindow:æ–°å»ºçª—å£ ^N
+
en.beos.NewWindowNSAccel:N
+it.beos.NewWindowNSAccel:N
+zh_CN.beos.NewWindowNSAccel:N
+
en.ro.ViewSrc:View source... F8
de.ro.ViewSrc:Quellcode... F8
-fr.ro.ViewSrc:Voir le source... F8
+fr.ro.ViewSrc:Voir la source… F8
it.ro.ViewSrc:Mostra sorgente... F8
nl.ro.ViewSrc:Toon HTML... F8
en.beos.ViewSrc:View source...
de.beos.ViewSrc:Quellcode...
-fr.beos.ViewSrc:Voir le source...
+fr.beos.ViewSrc:Voir le source…
it.beos.ViewSrc:Mostra sorgente...
nl.beos.ViewSrc:Toon HTML...
+zh_CN.beos.ViewSrc:查看æºä»£ç â€¦
+
en.beos.ViewSrcAccel:U
+it.beos.ViewSrcAccel:U
+zh_CN.beos.ViewSrcAccel:U
# Main -> Page -> Export menu
#
en.ro.Draw:Draw ⇑^F3
fr.ro.Draw:Dessiner ⇑^F3
+it.ro.Draw:Draw �^F3
nl.ro.Draw:Draw-bestand ⇑^F3
+zh_CN.ro.Draw:绘图 ↑^F3
en.all.PDF:PDF
fr.all.PDF:PDF
+it.all.PDF:PDF
nl.all.PDF:PDF
+zh_CN.all.PDF:PDF
en.ro.Text:Text ^F3
fr.ro.Text:Texte ^F3
it.ro.Text:Testo ^F3
nl.ro.Text:Tekstbestand ^F3
+zh_CN.ro.Text:文本 ^ F3
# Main -> Page -> Save location menu
#
en.ro.URI:Acorn URI
fr.ro.URI:Acorn URI
+it.ro.URI:Acorn URI
nl.ro.URI:Acorn-URI
+zh_CN.ro.URI:Acorn URI
en.ro.URL:ANT URL
fr.ro.URL:ANT URL
+it.ro.URL:ANT URL
nl.ro.URL:ANT-URL
+zh_CN.ro.URL:ANT URL
en.all.LinkText:Text
fr.all.LinkText:Texte
it.all.LinkText:Testo
nl.all.LinkText:Tekstbestand
+zh_CN.all.LinkText:文本
# Main -> Object -> Object menu
#
en.all.ObjInfo:Info
fr.all.ObjInfo:Information
+it.all.ObjInfo:Informazioni
nl.all.ObjInfo:Informatie
+zh_CN.all.ObjInfo:ä¿¡æ¯
+
en.all.ObjSave:Save
de.all.ObjSave:Speichern
-fr.all.ObjSave:Sauver
+fr.all.ObjSave:Enregistrer
it.all.ObjSave:Salva
nl.all.ObjSave:Bewaar
+zh_CN.all.ObjSave:ä¿å­˜
+
en.all.ObjPrint:Print
de.all.ObjPrint:Drucken
fr.all.ObjPrint:Imprimer
it.all.ObjPrint:Stampa
nl.all.ObjPrint:Druk af
+zh_CN.all.ObjPrint:打å°
+
en.all.ObjReload:Reload
de.all.ObjReload:erneut laden
fr.all.ObjReload:Recharger
it.all.ObjReload:Ricarica
nl.all.ObjReload:Herlaad
+zh_CN.all.ObjReload:é‡è£…
# Main -> Object -> Object -> Export menu
#
en.all.Sprite:Sprite
+it.all.Sprite:Sprite
nl.all.Sprite:Sprite-bestand
+zh_CN.all.Sprite:贴图
en.all.ObjDraw:Draw
+it.all.ObjDraw:Draw
nl.all.ObjDraw:Draw-bestand
+zh_CN.all.ObjDraw:绘制
# Main -> Object -> Link menu
en.all.LinkSave:Save
@@ -244,18 +2640,21 @@ de.all.LinkSave:Speichern
fr.all.LinkSave:Enregistrer
it.all.LinkSave:Salva
nl.all.LinkSave:Bewaar
+zh_CN.all.LinkSave:ä¿å­˜
en.all.LinkDload:Download target
de.all.LinkDload:Ziel speichern
-fr.all.LinkDload:Téléchargement cible
+fr.all.LinkDload:Télécharger la cible
it.all.LinkDload:Scarica file
nl.all.LinkDload:Haal op
+zh_CN.all.LinkDload:下载目标
en.all.LinkNew:New window
de.all.LinkNew:Neues Fenster
fr.all.LinkNew:Nouvelle fenêtre
it.all.LinkNew:Nuova finestra
nl.all.LinkNew:Nieuw venster
+zh_CN.all.LinkNew:新建窗å£
# Main -> Selection menu
en.all.SelSave:Save
@@ -263,33 +2662,54 @@ fr.all.SelSave:Enregistrer
de.all.SelSave:Speichern
it.all.SelSave:Salva
nl.all.SelSave:Bewaar
+zh_CN.all.SelSave:ä¿å­˜
# Main -> Navigate menu
#
en.all.Home:Home page
de.all.Home:Homepage
-fr.all.Home:Page d'accueil
+fr.all.Home:Page d’accueil
it.all.Home:Pagina iniziale
nl.all.Home:Startpagina
+zh_CN.all.Home:主页
+
en.beos.HomeAccel:H
+it.beos.HomeAccel:H
+zh_CN.beos.HomeAccel:H
+
en.all.Back:Back one page
de.all.Back:Eine Seite zurück
fr.all.Back:Retour
it.all.Back:Indietro
nl.all.Back:Vorige pagina
+zh_CN.all.Back:åŽé€€
+
en.beos.BackAccel:â†
+it.beos.BackAccel:�
+zh_CN.beos.BackAccel:â†
+
en.all.Forward:Forward one page
de.all.Forward:Eine Seite vor
fr.all.Forward:Avancer
it.all.Forward:Avanti
nl.all.Forward:Volgende pagina
+zh_CN.all.Forward:å‰è¿›
+
en.beos.ForwardAccel:→
+it.beos.ForwardAccel:�
+zh_CN.beos.ForwardAccel:→
+
en.all.UpLevel:Up one level
de.all.UpLevel:Eine Ebene hoch
-fr.all.UpLevel:Remonter d'un niveau
+fr.all.UpLevel:Remonter d’un niveau
it.all.UpLevel:Livello superiore
nl.all.UpLevel:Niveau omhoog
+zh_CN.all.UpLevel:回到上级
+
en.beos.UpLevelAccel:↑
+it.beos.UpLevelAccel:�
+zh_CN.beos.UpLevelAccel:↑
+
en.ro.Reload:Reload this page ^F5
de.ro.Reload:Seite erneut laden ^F5
fr.ro.Reload:Recharger cette page ^F5
@@ -300,13 +2720,22 @@ de.beos.Reload:Seite erneut laden
fr.beos.Reload:Recharger cette page
it.beos.Reload:Ricarica
nl.beos.Reload:Herlaad pagina
+zh_CN.beos.Reload:é‡æ–°è½½å…¥æ­¤é¡µé¢
+
en.beos.ReloadAccel:R
+it.beos.ReloadAccel:R
+zh_CN.beos.ReloadAccel:R
+
en.all.Stop:Stop loading this page
de.all.Stop:Ladevorgang abbrechen
fr.all.Stop:Arrêter le chargement de la page
it.all.Stop:Interrompi
nl.all.Stop:Breek ophaalproces af
+zh_CN.all.Stop:åœæ­¢åŠ è½½æ­¤é¡µé¢
+
en.beos.StopAccel:S
+it.beos.StopAccel:S
+zh_CN.beos.StopAccel:S
# Main -> Display menu
#
@@ -315,26 +2744,35 @@ de.ro.ScaleView:Vergrößerung F11
fr.ro.ScaleView:Ajuster la vue F11
it.ro.ScaleView:Visualizzazione graduale F11
nl.ro.ScaleView:Schaal pagina F11
+zh_CN.ro.ScaleView:缩放视图 F11
+
en.all.Images:Images
de.all.Images:Bilder
fr.all.Images:Images
it.all.Images:Immagini
nl.all.Images:Toon afbeeldingen
+zh_CN.all.Images:图åƒ
+
en.all.Toolbars:Toolbars
de.all.Toolbars:Anzeigen und Leisten
-fr.all.Toolbars:Barre d'outils
+fr.all.Toolbars:Barres d’outils
it.all.Toolbars:Barre strumenti
nl.all.Toolbars:Toon gereedschapbalken
+zh_CN.all.Toolbars:工具æ 
+
en.all.Render:Render
de.all.Render:Rendern
fr.all.Render:Rendu
it.all.Render:Interprete
nl.all.Render:Pagina-opbouw
+zh_CN.all.Render:渲染
+
en.all.OptDefault:Save as default
de.all.OptDefault:als Standard speichern
fr.all.OptDefault:Définir par défaut
it.all.OptDefault:Salva come predefinito
nl.all.OptDefault:Stel in als standaard
+zh_CN.all.OptDefault:ä¿å­˜ä¸ºé»˜è®¤å€¼
# Main -> Display -> Images menu
#
@@ -343,11 +2781,14 @@ de.all.ForeImg:Vordergrundbilder
fr.all.ForeImg:Images de premier plan
it.all.ForeImg:In primo piano
nl.all.ForeImg:Voorgrondafbeeldingen
+zh_CN.all.ForeImg:å‰æ™¯å›¾ç‰‡
+
en.all.BackImg:Background images
de.all.BackImg:Hintergrundbilder
fr.all.BackImg:Images de fond
it.all.BackImg:In sottofondo
nl.all.BackImg:Achtergrondafbeeldingen
+zh_CN.all.BackImg:背景图片
# Main -> Display -> Toolbars menu
#
@@ -356,97 +2797,124 @@ de.all.ToolButtons:Knopfgrafiken
fr.all.ToolButtons:Boutons
it.all.ToolButtons:Pulsanti
nl.all.ToolButtons:Knoppen
+zh_CN.all.ToolButtons:按钮
+
en.all.ToolAddress:Address bar
de.all.ToolAddress:Adressleiste
-fr.all.ToolAddress:Barre d'adresse
+fr.all.ToolAddress:Barre d’adresse
it.all.ToolAddress:Barra indirizzi
nl.all.ToolAddress:Adresveld
+zh_CN.all.ToolAddress:地å€æ 
+
en.all.ToolThrob:Throbber
de.all.ToolThrob:Ladeaktivität
-fr.all.ToolThrob:Pulseur
+fr.all.ToolThrob:Indicateur d’activité
it.all.ToolThrob:Indicatore di attività
nl.all.ToolThrob:Laadactiviteit
+zh_CN.all.ToolThrob:动æ€æµè§ˆå›¾ç¤º
+
en.all.ToolStatus:Status bar
de.all.ToolStatus:Statusanzeige
-fr.all.ToolStatus:Barre d'état
+fr.all.ToolStatus:Barre d’état
it.all.ToolStatus:Barra di stato
nl.all.ToolStatus:Statusbalk
+zh_CN.all.ToolStatus:状æ€æ 
# Main -> Display -> Render menu
#
en.all.RenderAnims:Buffer animations
de.all.RenderAnims:Animationen zwischenspeichern
-fr.all.RenderAnims:Tamponner les animations
-it.all.RenderAnims:Blocca le animazioni
+fr.all.RenderAnims:Utiliser un tampon pour les animations
+it.all.RenderAnims:Buffer animazioni
nl.all.RenderAnims:Buffer animaties
+zh_CN.all.RenderAnims:缓冲动画
+
en.all.RenderAll:Buffer all rendering
de.all.RenderAll:Alles zwischenspeichern
-fr.all.RenderAll:Tamponner tous les rendus
+fr.all.RenderAll:Utiliser un tampon pour tous les rendus
it.all.RenderAll:Blocca tutto l'interprete
nl.all.RenderAll:Buffer gehele weergave
+zh_CN.all.RenderAll:缓冲所有渲染
# Main -> Utilities menu
#
en.all.Hotlist:Hotlist
-fr.all.Hotlist:Favoris
+fr.all.Hotlist:Marque-pages
it.all.Hotlist:Segnalibri
nl.all.Hotlist:Favorieten
+zh_CN.all.Hotlist:常用列表
+
en.all.History:History
fr.all.History:Historique
it.all.History:Cronologia locale
nl.all.History:Geschiedenis
+zh_CN.all.History:历å²è®°å½•
+
en.all.Cookies:Cookies
it.all.Cookies:Cookie
nl.all.Cookies:Cookies
+zh_CN.all.Cookies:Cookies
en.ro.FindText:Find text F4
de.ro.FindText:Text suchen F4
-fr.ro.FindText:Recherche de texte F4
+fr.ro.FindText:Recherche texte F4
it.ro.FindText:Trova testo F4
nl.ro.FindText:Zoek tekst F4
+zh_CN.ro.FindText:查找文本 F4
+
en.all.Window:Window
de.all.Window:Fenster
fr.all.Window:Fenêtre
it.all.Window:Finestra
nl.all.Window:Vensteromvang en positie
+zh_CN.all.Window:窗å£
# Main -> Utilities -> Hotlist menu
#
en.all.HotlistAdd:Add to hotlist
de.all.HotlistAdd:Eintrag hinzufügen
-fr.all.HotlistAdd:Ajouter aux favoris
+fr.all.HotlistAdd:Ajouter aux marque-pages
it.all.HotlistAdd:Aggiungi
nl.all.HotlistAdd:Voeg pagina toe
+zh_CN.all.HotlistAdd:添加至常用列表
+
en.ro.HotlistShow:Show hotlist... F6
de.ro.HotlistShow:Hotlist zeigen... F6
-fr.ro.HotlistShow:Montrer les favoris... F6
+fr.ro.HotlistShow:Afficher les marque-pages… F6
it.ro.HotlistShow:Mostra... F6
nl.ro.HotlistShow:Favorieten... F6
+zh_CN.ro.HotlistShow:显示常用列表… F6
# Main -> Utilities -> History menu
#
en.ro.HistLocal:Show local history... F7
de.ro.HistLocal:History (lokal) zeigen... F7
-fr.ro.HistLocal:Montrer l'historique local... F7
+fr.ro.HistLocal:Afficher l’historique local… F7
it.ro.HistLocal:Mostra cronologia locale... F7
nl.ro.HistLocal:Venstergeschiedenis... F7
+zh_CN.ro.HistLocal:显示本地历å²è®°å½•â€¦ F7
+
en.ro.HistGlobal:Show global history... ^F7
de.ro.HistGlobal:History (global) zeigen... ^F7
-fr.ro.HistGlobal:Montrer l'historique global... ^F7
+fr.ro.HistGlobal:Afficher l’historique global… ^F7
it.ro.HistGlobal:Mostra cronologia globale... ^F7
nl.ro.HistGlobal:Browsergeschiedenis... ^F7
+zh_CN.ro.HistGlobal:显示全局历å²è®°å½•â€¦ ^F7
# Main -> Utilities -> Cookies menu
en.all.ShowCookies:Show cookies...
de.all.ShowCookies:Cookies verwalten...
-fr.all.ShowCookies:Montrer les cookies...
+fr.all.ShowCookies:Afficher les cookies…
it.all.ShowCookies:Mostra cookie...
nl.all.ShowCookies:Cookiesbeheer...
+zh_CN.all.ShowCookies:显示 Cookies …
+
en.all.DeleteCookies:Delete all cookies
de.all.DeleteCookies:Alle Cookies löschen
fr.all.DeleteCookies:Supprimer tous les cookies
it.all.DeleteCookies:Cancella tutti i cookie
nl.all.DeleteCookies:Verwijder cookies
+zh_CN.all.DeleteCookies:删除所有 Cookies
# Main -> Utilities -> Window menu
#
@@ -455,67 +2923,87 @@ de.all.WindowSave:aktuelle Fensterposition speichern
fr.all.WindowSave:Définir comme position par défaut
it.all.WindowSave:Imposta come posizione predefinita
nl.all.WindowSave:Bewaar als standaard
+zh_CN.all.WindowSave:设置为默认ä½ç½®
+
en.all.WindowStagr:Stagger window position
de.all.WindowStagr:neue Fenster versetzen
-fr.all.WindowStagr:Décaler la position des nouv. fenêtres
+fr.all.WindowStagr:Étaler la position des fenêtres
it.all.WindowStagr:Sfalsa posizione della finestra
nl.all.WindowStagr:Open vensters stapelgewijs
+zh_CN.all.WindowStagr:错开窗å£ä½ç½®
+
en.all.WindowSize:Copy window position
de.all.WindowSize:Fenstergröße beibehalten
fr.all.WindowSize:Garder cette taille de fenêtre
it.all.WindowSize:Copia posizione della finestra
nl.all.WindowSize:Kopieer voorgaand venster
+zh_CN.all.WindowSize:æ‹·è´çª—å£ä½ç½®
+
en.all.WindowReset:Reset default position
de.all.WindowReset:Fensterposition zurücksetzen
-fr.all.WindowReset:RAZ de la position par défaut
+fr.all.WindowReset:Revenir à la position par défaut
it.all.WindowReset:Resetta posizione della finestra
nl.all.WindowReset:Herstel standaardwaarden
+zh_CN.all.WindowReset:é‡ç½®é»˜è®¤ä½ç½®
# Main -> Help menu
#
en.ro.HelpContent:Contents F1
-de.ro.HelpContent:Inhalt F1
+de.ro.HelpContent:Inhalt F1
fr.ro.HelpContent:Contenus F1
it.ro.HelpContent:Contenuti F1
nl.ro.HelpContent:Inhoudsopgave F1
+zh_CN.ro.HelpContent:内容 F1
+
en.ro.HelpGuide:User guide
de.ro.HelpGuide:Handbuch
-fr.ro.HelpGuide:Guide de l'utilisateur
+fr.ro.HelpGuide:Guide de l’utilisateur
it.ro.HelpGuide:Guida in linea
nl.ro.HelpGuide:Gebruikershandleiding
+zh_CN.ro.HelpGuide:用户指å—
+
en.ro.HelpInfo:User information
de.ro.HelpInfo:Nutzerinformation
fr.ro.HelpInfo:Information utilisateur
it.ro.HelpInfo:Informazioni utente
nl.ro.HelpInfo:Gebruikersinformatie
+zh_CN.ro.HelpInfo:用户信æ¯
+
en.all.HelpCredits:Credits
fr.all.HelpCredits:Crédits
it.all.HelpCredits:Ringraziamenti
nl.all.HelpCredits:Bijdragen
+zh_CN.all.HelpCredits:制作人员åå•
en.all.HelpLicence:Licence
de.all.HelpLicence:Lizenz
+fr.all.HelpLicence:Licence
it.all.HelpLicence:Licenza
nl.all.HelpLicence:Licentie
+zh_CN.all.HelpLicence:许å¯è¯
en.ro.HelpInter:Interactive help
de.ro.HelpInter:interaktive Hilfe
fr.ro.HelpInter:Aide interactive
it.ro.HelpInter:Aiuto interattivo
nl.ro.HelpInter:Interactieve hulp
+zh_CN.ro.HelpInter:交互å¼å¸®åŠ©ç”¨æˆ·
# Toolbar menu
#
en.all.Toolbar:Toolbar
de.all.Toolbar:Symbolleiste
-fr.all.Toolbar:Barre d'outils
+fr.all.Toolbar:Barre d’outils
it.all.Toolbar:Barra strumenti
nl.all.Toolbar:Gereedschapbalk
+zh_CN.all.Toolbar:工具æ 
+
en.all.EditToolbar:Edit toolbar
de.all.EditToolbar:Symbolleiste bearbeiten
-fr.all.EditToolbar:Éditer la barre d'outils
+fr.all.EditToolbar:Éditer la barre d’outils
it.all.EditToolbar:Modifica barra strumenti
nl.all.EditToolbar:Aanpasmodus
+zh_CN.all.EditToolbar:编辑工具æ 
# Generic tree menus (currently Hotlist and Global history)
#
@@ -524,54 +3012,72 @@ de.all.Selection:Auswahl
fr.all.Selection:Sélection
it.all.Selection:Seleziona
nl.all.Selection:Selectie
+zh_CN.all.Selection:选项
+
en.ro.SelectAll:Select all ^A
de.ro.SelectAll:Alles auswählen ^A
fr.ro.SelectAll:Tout sélectionner ^A
it.ro.SelectAll:Seleziona tutto ^A
nl.ro.SelectAll:Selecteer alles ^A
+zh_CN.ro.SelectAll:全部选择 ^A
+
en.ro.Clear:Clear selection ^Z
de.ro.Clear:Auswahl aufheben ^Z
fr.ro.Clear:Effacer la sélection ^Z
it.ro.Clear:Annulla selezione ^Z
nl.ro.Clear:Deselecteer ^Z
+zh_CN.ro.Clear:清除选择 ^Z
+
en.ro.Copy:Copy to clipboard ^C
de.ro.Copy:Auswahl kopieren ^C
fr.ro.Copy:Copier vers le presse-papier ^C
it.ro.Copy:Copia nella clipboard ^C
nl.ro.Copy:Kopieer naar klembord ^C
+zh_CN.ro.Copy:å¤åˆ¶åˆ°å‰ªè´´æ¿ ^C
+
en.ro.Cut:Cut to clipboard ^X
de.ro.Cut:Ausschneiden ^X
fr.ro.Cut:Couper vers le presse-papier ^X
it.ro.Cut:Taglia dalla clipboard ^X
nl.ro.Cut:Verplaats naar klembord ^X
+zh_CN.ro.Cut:å‰ªåˆ‡åˆ°å‰ªè´´æ¿ ^X
+
en.ro.Paste:Paste from clipboard ^V
de.ro.Paste:Einfügen ^V
fr.ro.Paste:Coller depuis le presse-papier ^V
it.ro.Paste:Incolla sulla clipboard ^V
nl.ro.Paste:Plak in vanuit klembord ^V
+zh_CN.ro.Paste:从剪贴æ¿ç²˜è´´ ^V
# Selection Menu
#
en.all.Edit:Edit
de.all.Edit:Bearbeiten
-fr.all.Edit:Éditer
+fr.all.Edit:Édition
it.all.Edit:Modifica
nl.all.Edit:Wijzig naam
+zh_CN.all.Edit:编辑
+
en.ro.Launch:Launch RETURN
de.ro.Launch:Öffnen RETURN
fr.ro.Launch:Lancer RETURN
it.ro.Launch:Avvia INVIO
nl.ro.Launch:Open RETURN
+zh_CN.ro.Launch:å¯åŠ¨ RETURN
+
en.ro.Delete:Delete Del
de.ro.Delete:Löschen Entf
fr.ro.Delete:Supprimer Suppr
it.ro.Delete:Cancella Canc
nl.ro.Delete:Verwijder Del
+zh_CN.ro.Delete:删除 Del
+
en.all.ResetUsage:Reset statistics
de.all.ResetUsage:Statistik zurücksetzen
fr.all.ResetUsage:RAZ des statistiques
it.all.ResetUsage:Resetta statistiche
nl.all.ResetUsage:Statistiekgebruik op nul
+zh_CN.all.ResetUsage:é‡ç½®ç»Ÿè®¡æ•°æ®
# Hotlist/Global history menu
#
@@ -580,25 +3086,33 @@ de.all.New:Neu
fr.all.New:Nouveau
it.all.New:Nuovo
nl.all.New:Nieuw
+zh_CN.all.New:新建
+
en.all.Expand:Expand
de.all.Expand:Expandieren
-fr.all.Expand:Déployer
+fr.all.Expand:Développer
it.all.Expand:Espandi
nl.all.Expand:Klap uit
+zh_CN.all.Expand:扩展
+
en.all.Collapse:Collapse
de.all.Collapse:Zusammenfalten
-fr.all.Collapse:Regrouper
+fr.all.Collapse:Réduire
it.all.Collapse:Raggruppa
nl.all.Collapse:Klap in
+zh_CN.all.Collapse:崩溃
+
en.all.Tree:Tree
fr.all.Tree:Arbre
it.all.Tree:Albero
nl.all.Tree:Tree
+zh_CN.all.Tree:æ ‘
en.all.TreeExport:Export...
-fr.all.TreeExport:Exporter...
+fr.all.TreeExport:Exporter…
it.all.TreeExport:Esporta...
nl.all.TreeExport:Exporteer...
+zh_CN.all.TreeExport:导出…
# New hotlist entry menu
#
@@ -607,34 +3121,44 @@ de.all.Folder:Verzeichnis
fr.all.Folder:Dossier
it.all.Folder:Cartella
nl.all.Folder:Map
+zh_CN.all.Folder:目录
+
en.all.Link:Address
de.all.Link:Verweis
fr.all.Link:Lien
it.all.Link:Link
nl.all.Link:Koppeling
+zh_CN.all.Link:地å€
# Tree expand/collapse menu
#
en.all.All:All
de.all.All:Alles
fr.all.All:Tout
-it.all.All:Tutti
+it.all.All:Tutto
nl.all.All:Alles
+zh_CN.all.All:全部
+
en.all.Folders:Directories
de.all.Folders:Verzeichnisse
fr.all.Folders:Dossiers
it.all.Folders:Cartelle
nl.all.Folders:Mappen
+zh_CN.all.Folders:目录
+
en.all.Links:Addresses
de.all.Links:Einträge
fr.all.Links:Adresses
it.all.Links:Indirizzi
nl.all.Links:Adressen
+zh_CN.all.Links:地å€
+
en.all.Domains:Domains
de.all.Domains:Domains
fr.all.Domains:Domaines
it.all.Domains:Domini
nl.all.Domains:Domeinen
+zh_CN.all.Domains:域
# Other menus
#
@@ -644,6 +3168,7 @@ de.all.URLSuggest:Aktuelle URLs
fr.all.URLSuggest:URLs récentes
it.all.URLSuggest:URL recenti
nl.all.URLSuggest:Recente adressen
+zh_CN.all.URLSuggest:最近æµè§ˆçš„ URL
# Menus within the choices system
#
@@ -653,6 +3178,8 @@ de.all.Languages:Sprachen
fr.all.Languages:Langue
it.all.Languages:Lingua
nl.all.Languages:Taal
+zh_CN.all.Languages:语言
+
#
# Network pane
en.all.ProxyType:Proxy type
@@ -660,26 +3187,36 @@ de.all.ProxyType:Proxytyp
fr.all.ProxyType:Type de proxy
it.all.ProxyType:Tipo di Proxy
nl.all.ProxyType:Proxy-type
+zh_CN.all.ProxyType:代ç†æœåŠ¡å™¨ç±»åž‹
+
en.all.ProxyNone:No proxy
de.all.ProxyNone:kein Proxy
fr.all.ProxyNone:Pas de proxy
it.all.ProxyNone:Nessuno
nl.all.ProxyNone:Geen proxy
+zh_CN.all.ProxyNone:无代ç†æœåŠ¡å™¨
+
en.all.ProxyNoAuth:Simple proxy
de.all.ProxyNoAuth:normaler Proxy
fr.all.ProxyNoAuth:Proxy simple
it.all.ProxyNoAuth:Semplice
nl.all.ProxyNoAuth:Eenvoudige proxy
+zh_CN.all.ProxyNoAuth:简å•ä»£ç†æœåŠ¡å™¨
+
en.all.ProxyBasic:Basic authentication
de.all.ProxyBasic:mit Authentifizierung
fr.all.ProxyBasic:Authentification de base
it.all.ProxyBasic:Autentificazione base
nl.all.ProxyBasic:Basisauthenticatie
+zh_CN.all.ProxyBasic:基本认è¯
+
en.all.ProxyNTLM:NTLM authentication
de.all.ProxyNTLM:NTLM Authentifizierung
fr.all.ProxyNTLM:Authentification NTLM
it.all.ProxyNTLM:Autentificazione NTLM
nl.all.ProxyNTLM:NTLM-authenticatie
+zh_CN.all.ProxyNTLM:NTLM 认è¯
+
#
# Fonts pane
en.all.Fonts:Fonts
@@ -687,11 +3224,15 @@ de.all.Fonts:Schriften
fr.all.Fonts:Fontes
it.all.Fonts:Font
nl.all.Fonts:Lettertypen
+zh_CN.all.Fonts:字体
+
en.all.DefaultFonts:Font Families
de.all.DefaultFonts:Schriftfamilien
fr.all.DefaultFonts:Familles de fontes
it.all.DefaultFonts:Famiglia Font
nl.all.DefaultFonts:Lettertypesoorten
+zh_CN.all.DefaultFonts:字体家æ—
+
#
# Images pane
en.all.Display:Display
@@ -699,26 +3240,35 @@ de.all.Display:Ausgabe
fr.all.Display:Affichage
it.all.Display:Display
nl.all.Display:Weergave
+zh_CN.all.Display:显示
+
en.all.ImgStyle0:Use OS
de.all.ImgStyle0:RISC OS nutzen
-fr.all.ImgStyle0:Utiliser l'OS
+fr.all.ImgStyle0:Utiliser l’OS
it.all.ImgStyle0:Usa OS
nl.all.ImgStyle0:RISC OS-routines
+zh_CN.all.ImgStyle0:使用æ“作系统
+
en.all.ImgStyle1:Direct to screen
de.all.ImgStyle1:Direktausgabe
-fr.all.ImgStyle1:Directement sur l'écran
+fr.all.ImgStyle1:Directement sur l’écran
it.all.ImgStyle1:Diretto su schermo
nl.all.ImgStyle1:Directe weergave
+zh_CN.all.ImgStyle1:直接在å±å¹•ä¸Šæ˜¾ç¤º
+
en.all.ImgStyle2:Dithered
de.all.ImgStyle2:Dithern
fr.all.ImgStyle2:Tramé
it.all.ImgStyle2:Dithered
nl.all.ImgStyle2:Kleurbenadering
+zh_CN.all.ImgStyle2:数字抖动
+
en.all.ImgStyle3:Error diffused
de.all.ImgStyle3:Error-Diffusion
-fr.all.ImgStyle3:Avec diffusion d'erreur
-it.all.ImgStyle3:Diffusione errore
+fr.all.ImgStyle3:Avec diffusion d’erreur
+it.all.ImgStyle3:Errore diffuso
nl.all.ImgStyle3:Foutdiffusie
+zh_CN.all.ImgStyle3:误差扩散方法
# Menu items used in the Amiga version.
# Some of these are copies of other strings but without the
@@ -731,71 +3281,98 @@ de.ami.Project:Projekt
fr.ami.Project:Projet
it.ami.Project:Progetto
nl.ami.Project:Project
+zh_CN.ami.Project:投影
+
en.all.NewWindowNS:New window
de.all.NewWindowNS:Neues Fenster
fr.all.NewWindowNS:Nouvelle fenêtre
it.all.NewWindowNS:Nuova finestra
nl.all.NewWindowNS:Nieuw venster
+zh_CN.all.NewWindowNS:新建窗å£
+
en.all.NewTab:New tab
de.all.NewTab:Neuer Tab
fr.all.NewTab:Nouvel onglet
it.all.NewTab:Nuova scheda
nl.all.NewTab:Nieuw tabblad
+zh_CN.all.NewTab:新建标签页
+
en.all.CloseTab:Close tab
de.all.CloseTab:Schließe Tab
-fr.all.CloseTab:Fermer l'onglet
+fr.all.CloseTab:Fermer l’onglet
it.all.CloseTab:Chiudi scheda
nl.all.CloseTab:Sluit tabblad
+zh_CN.all.CloseTab:关闭标签页
+
en.all.CloseWindow:Close window
de.all.CloseWindow:Schließe Fenster
fr.all.CloseWindow:Fermer la fenêtre
it.all.CloseWindow:Chiudi finestra
nl.all.CloseWindow:Sluit venster
+zh_CN.all.CloseWindow:关闭窗å£
+
en.all.SaveAsNS:Save as
de.all.SaveAsNS:Speichern als
fr.all.SaveAsNS:Enregistrer sous
it.all.SaveAsNS:Salva come
nl.all.SaveAsNS:Bewaar als
+zh_CN.all.SaveAsNS:å¦å­˜ä¸º
+
en.all.Source:Source...
de.all.Source:Quelle...
-fr.all.Source:Source...
+fr.all.Source:Source…
it.all.Source:Sorgente...
nl.all.Source:Bron...
+zh_CN.all.Source:æºä»£ç â€¦
+
en.all.TextNS:Text...
de.all.TextNS:Text...
-fr.all.TextNS:Texte...
+fr.all.TextNS:Texte…
it.all.TextNS:Testo...
nl.all.TextNS:Tekst...
+zh_CN.all.TextNS:文本…
+
en.all.SaveCompNS:Complete...
de.all.SaveCompNS:Komplett...
-fr.all.SaveCompNS:Complète ...
+fr.all.SaveCompNS:Complète…
it.all.SaveCompNS:Cartella...
nl.all.SaveCompNS:Compleet...
+zh_CN.all.SaveCompNS:补全…
+
en.all.PDFNS:PDF...
de.all.PDFNS:PDF...
-fr.all.PDFNS:PDF...
+fr.all.PDFNS:PDF…
it.all.PDFNS:PDF...
nl.all.PDFNS:PDF...
+zh_CN.all.PDFNS:PDF…
+
en.ami.IFF:IFF...
de.ami.IFF:IFF...
-fr.ami.IFF:IFF...
+fr.ami.IFF:IFF…
it.ami.IFF:IFF...
nl.ami.IFF:IFF...
+zh_CN.ami.IFF:IFF…
+
en.all.OpenFile:Open local file...
de.all.OpenFile:Öffne lokale Datei...
-fr.all.OpenFile:Ouvrir un fichier local ...
+fr.all.OpenFile:Ouvrir un fichier local…
it.all.OpenFile:Apri file locale...
nl.all.OpenFile:Open lokaal bestand...
+zh_CN.all.OpenFile:打开本地文件…
+
en.all.About:About
de.all.About:Ãœber
fr.all.About:À propos
it.all.About:Informazioni
nl.all.About:Programma-informatie
+zh_CN.all.About:关于
+
en.all.PrintNS:Print...
de.all.PrintNS:Drucken...
-fr.all.PrintNS:Imprimer...
+fr.all.PrintNS:Imprimer…
it.all.PrintNS:Stampa...
nl.all.PrintNS:Druk af...
+zh_CN.all.PrintNS:打å°â€¦
# Edit menu
#
@@ -804,36 +3381,49 @@ de.all.CutNS:Ausschneiden
fr.all.CutNS:Couper
it.all.CutNS:Taglia
nl.all.CutNS:Knip uit
+zh_CN.all.CutNS:剪切
+
en.all.CopyNS:Copy
de.all.CopyNS:Kopieren
fr.all.CopyNS:Copier
it.all.CopyNS:Copia
nl.all.CopyNS:Kopieer
+zh_CN.all.CopyNS:æ‹·è´
+
en.all.PasteNS:Paste
de.all.PasteNS:Einfügen
fr.all.PasteNS:Coller
it.all.PasteNS:Incolla
nl.all.PasteNS:Plak in
+zh_CN.all.PasteNS:粘贴
+
en.all.SelectAllNS:Select all
de.all.SelectAllNS:Alles auswählen
fr.all.SelectAllNS:Sélectionner tout
it.all.SelectAllNS:Seleziona tutto
nl.all.SelectAllNS:Selecteer alles
+zh_CN.all.SelectAllNS:全部选择
+
en.all.ClearNS:Clear selection
de.all.ClearNS:Auswahl rückgängig
fr.all.ClearNS:Effacer la sélection
it.all.ClearNS:Annulla selezione
nl.all.ClearNS:Deselecteer
+zh_CN.all.ClearNS:清除选项
+
en.ami.Undo:Undo
de.ami.Undo:Undo
fr.ami.Undo:Annuler
it.ami.Undo:Annulla
nl.ami.Undo:Maak ongedaan
+zh_CN.ami.Undo:撤销
+
en.ami.Redo:Redo
de.ami.Redo:Redo
fr.ami.Redo:Rétablir
it.ami.Redo:Ripristina
nl.ami.Redo:Opnieuw
+zh_CN.ami.Redo:é‡åš
# Browser menu
#
@@ -842,59 +3432,79 @@ de.all.Browser:Browser
fr.all.Browser:Navigateur
it.all.Browser:Strumenti
nl.all.Browser:Browser
+zh_CN.all.Browser:æµè§ˆå™¨
+
en.all.HistGlobalNS:Show global history
de.all.HistGlobalNS:Zeige globale History
-fr.all.HistGlobalNS:Afficher l'historique global
+fr.all.HistGlobalNS:Afficher l’historique global
it.all.HistGlobalNS:Mostra cronologia globale
nl.all.HistGlobalNS:Toon browsergeschiedenis
+zh_CN.all.HistGlobalNS:显示全局历å²è®°å½•
+
en.all.HistLocalNS:Show local history
de.all.HistLocalNS:Zeige lokale History
-fr.all.HistLocalNS:Afficher l'historique local
+fr.all.HistLocalNS:Afficher l’historique local
it.all.HistLocalNS:Mostra cronologia locale
nl.all.HistLocalNS:Toon venstergeschiedenis
+zh_CN.all.HistLocalNS:显示本地历å²è®°å½•
+
en.ami.ShowCookiesNS:Show cookies
de.ami.ShowCookiesNS:Cookies verwalten
-fr.ami.ShowCookiesNS:Montrer les cookies
+fr.ami.ShowCookiesNS:Afficher les cookies
it.ami.ShowCookiesNS:Mostra cookie
nl.ami.ShowCookiesNS:Toon cookies
+zh_CN.ami.ShowCookiesNS:显示 Cookies
+
en.all.FindTextNS:Find text...
de.all.FindTextNS:Suchen...
-fr.all.FindTextNS:Recherche de texte...
+fr.all.FindTextNS:Recherche de texte…
it.all.FindTextNS:Trova testo...
nl.all.FindTextNS:Zoek tekst...
+zh_CN.all.FindTextNS:查找文本…
+
en.all.Redraw:Redraw page
de.all.Redraw:Seite neu aufbauen
fr.all.Redraw:Redessiner la page
it.all.Redraw:Ridisegna pagina
nl.all.Redraw:Bouw pagina opnieuw op
+zh_CN.all.Redraw:é‡æ–°ç»˜åˆ¶é¡µé¢
+
en.all.ScaleNS:Scale
de.all.ScaleNS:Skalieren
fr.all.ScaleNS:Zoom
it.all.ScaleNS:Scala di zoom
nl.all.ScaleNS:Schaal
+zh_CN.all.ScaleNS:缩放
+
en.all.ScaleInc:Increase
de.all.ScaleInc:Vergrößern
fr.all.ScaleInc:Augmenter (Zoom +)
it.all.ScaleInc:Aumenta
nl.all.ScaleInc:Vergroot
+zh_CN.all.ScaleInc:放大
+
en.all.ScaleDec:Decrease
de.all.ScaleDec:Verkleinern
fr.all.ScaleDec:Diminuer (Zoom -)
it.all.ScaleDec:Diminuisci
nl.all.ScaleDec:Verklein
+zh_CN.all.ScaleDec:缩å°
+
en.all.ScaleNorm:Normal
de.all.ScaleNorm:Normal
fr.all.ScaleNorm:Normal
it.all.ScaleNorm:Normale
nl.all.ScaleNorm:Normaal
+zh_CN.all.ScaleNorm:正常
# Hotlist menu
#
en.all.HotlistShowNS:Show hotlist
de.all.HotlistShowNS:Zeige Hotlist
-fr.all.HotlistShowNS:Afficher les favoris
+fr.all.HotlistShowNS:Afficher les marque-pages
it.all.HotlistShowNS:Mostra
nl.all.HotlistShowNS:Toon favorieten
+zh_CN.all.HotlistShowNS:显示常用列表
# Settings menu
#
@@ -903,21 +3513,28 @@ de.all.SettingsEdit:Voreinstellungen
fr.all.SettingsEdit:Modifier les préférences
it.all.SettingsEdit:Modifica
nl.all.SettingsEdit:Wijzig voorkeuren
+zh_CN.all.SettingsEdit:编辑首选项
+
en.all.Settings:Settings
de.all.Settings:Einstellungen
fr.all.Settings:Paramètres
it.all.Settings:Preferenze
nl.all.Settings:Instellingen
+zh_CN.all.Settings:设置
+
en.all.SnapshotWindow:Snapshot window
de.all.SnapshotWindow:Schnappschuß
fr.all.SnapshotWindow:Capture instantanée de la fenêtre
it.all.SnapshotWindow:Fissa finestra
nl.all.SnapshotWindow:Schermopnamevenster
+zh_CN.all.SnapshotWindow:窗å£æˆªå›¾
+
en.all.SettingsSave:Save settings
de.all.SettingsSave:Einstellungen speichern
fr.all.SettingsSave:Enregistrer les paramètres
it.all.SettingsSave:Salva
nl.all.SettingsSave:Bewaar instellingen
+zh_CN.all.SettingsSave:ä¿å­˜è®¾ç½®
# ARexx menu
#
@@ -926,11 +3543,14 @@ de.ami.ARexx:ARexx
fr.ami.ARexx:ARexx
it.ami.ARexx:ARexx
nl.ami.ARexx:ARexx
+zh_CN.ami.ARexx:ARexx
+
en.ami.ARexxExecute:Execute script...
de.ami.ARexxExecute:Script ausführen...
-fr.ami.ARexxExecute:Executer script...
+fr.ami.ARexxExecute:Executer script…
it.ami.ARexxExecute:Esegui script...
nl.ami.ARexxExecute:Voer script uit...
+zh_CN.ami.ARexxExecute:执行脚本…
# Context menu
#
@@ -944,591 +3564,112 @@ de.all.LinkNewTab:Öffnen in Tab
fr.all.LinkNewTab:Ouvrir dans un nouvel onglet
it.all.LinkNewTab:Apri in nuova scheda
nl.all.LinkNewTab:Open in nieuw tabblad
+zh_CN.all.LinkNewTab:打开新标签页
+
en.all.LinkNewWin:Open in new window
de.all.LinkNewWin:Öffnen in Fenster
fr.all.LinkNewWin:Ouvrir dans une nouvelle fenêtre
it.all.LinkNewWin:Apri in nuova finestra
nl.all.LinkNewWin:Open in nieuw venster
+zh_CN.all.LinkNewWin:打开新窗å£
+
en.all.CopyURL:Copy URL to clipboard
de.all.CopyURL:URL ins Clipboard
fr.all.CopyURL:Copy URL dans le presse papier
it.all.CopyURL:Copia indirizzo link
nl.all.CopyURL:Kopieer adres naar klembord
+zh_CN.all.CopyURL:å°† URL å¤åˆ¶åˆ°å‰ªè´´æ¿
+
en.all.CopyClip:Copy to clipboard
de.all.CopyClip:Inhalt ins Clipboard
fr.all.CopyClip:Copier vers le presse-papiers
it.all.CopyClip:Copia nella clipboard
nl.all.CopyClip:Kopieer naar klembord
+zh_CN.all.CopyClip:å¤åˆ¶åˆ°å‰ªè´´æ¿
+
en.all.SaveAs:Save as...
de.all.SaveAs:Speichern als...
-fr.all.SaveAs:Enregistrer sous...
+fr.all.SaveAs:Enregistrer sous…
it.all.SaveAs:Salva come...
nl.all.SaveAs:Bewaar als...
+zh_CN.all.SaveAs:å¦å­˜ä¸ºâ€¦
+
en.ami.SaveIFF:Save as IFF...
de.ami.SaveIFF:Speichern als IFF...
-fr.ami.SaveIFF:Enregistrer sous IFF...
+fr.ami.SaveIFF:Enregistrer sous IFF…
it.ami.SaveIFF:Salva come IFF...
nl.ami.SaveIFF:Bewaar als IFF...
+zh_CN.ami.SaveIFF:å¦å­˜ä¸º IFF …
+
en.all.SaveComplete:Save complete...
de.all.SaveComplete:Speichern abgeschlossen...
-fr.all.SaveComplete:Enregistrement terminé...
+fr.all.SaveComplete:Enregistrement terminé…
it.all.SaveComplete:Salva tutto...
nl.all.SaveComplete:Bewaar alles...
+zh_CN.all.SaveComplete:完æˆä¿å­˜â€¦
+
en.all.Close:Close
de.all.Close:Schließen
fr.all.Close:Fermer
it.all.Close:Chiudi
nl.all.Close:Sluit
+zh_CN.all.Close:关闭
+
en.ami.CloseInactive:Close inactive tabs
de.ami.CloseInactive:Close inactive tabs
-fr.ami.CloseInactive:Close inactive tabs
+fr.ami.CloseInactive:Fermer les onglets inactifs
it.ami.CloseInactive:Chiudi schede inattive
nl.ami.CloseInactive:Close inactive tabs
+zh_CN.ami.CloseInactive:关闭闲置的标签页
+
en.all.ObjShow:Show object
de.all.ObjShow:Zeige Objekt
-fr.all.ObjShow:Afficher l'objet
+fr.all.ObjShow:Afficher l’objet
it.all.ObjShow:Mostra file
nl.all.ObjShow:Toon object
+zh_CN.all.ObjShow:显示对象
+
en.all.Frame:Frame
de.all.Frame:Frame
-fr.all.Frame:Frame
+fr.all.Frame:Cadre
it.all.Frame:Frame
nl.all.Frame:Vensterkader
+zh_CN.all.Frame:帧
+
en.all.FrameNewWin:Show in new window
de.all.FrameNewWin:In neuem Fenster anzeigen
fr.all.FrameNewWin:Afficher dans une nouvelle fenêtre
it.all.FrameNewWin:Apri frame in nuova finestra
nl.all.FrameNewWin:Toon in nieuw venster
+zh_CN.all.FrameNewWin:在新窗å£ä¸­æ˜¾ç¤º
+
en.all.FrameNewTab:Show in new tab
de.all.FrameNewTab:In neuem Tab anzeigen
fr.all.FrameNewTab:Afficher dans un nouvel onglet
it.all.FrameNewTab:Apri frame in nuova scheda
nl.all.FrameNewTab:Toon in nieuw tabblad
+zh_CN.all.FrameNewTab:在新标签页中显示
+
en.all.FrameOnly:Show only this frame
de.all.FrameOnly:Nur diesen Frame anzeigen
-fr.all.FrameOnly:N'afficher que ce cadre
+fr.all.FrameOnly:N’afficher que ce cadre
it.all.FrameOnly:Apri frame in questa finestra
nl.all.FrameOnly:Toon alleen dit vensterkader
+zh_CN.all.FrameOnly:仅显示此帧
en.all.SelectFile:Select file...
de.all.SelectFile:Datei auswählen...
-fr.all.SelectFile:Sélectionnez le fichier...
+fr.all.SelectFile:Sélectionnez le fichier…
it.all.SelectFile:Seleziona file...
nl.all.SelectFile:Selecteer bestand...
+zh_CN.all.SelectFile:选择文件…
+
en.all.ExternalApp:Open in external application
de.all.ExternalApp:In externer Anwendung öffnen
fr.all.ExternalApp:Ouvrir dans une application externe
it.all.ExternalApp:Apri con applicazione esterna
nl.all.ExternalApp:Open in ander programma
-
-# Treeview interface tokens
-# =========================
-#
-# This section contains tokens which are used in the treeview
-# component. (For example, in the main hotlist/global history windows)
-#
-
-# Tree URL text
-#
-en.all.TreeAdded:Added: %s
-de.all.TreeAdded:eingetragen am: %s
-fr.all.TreeAdded:Ajoutée : %s
-it.all.TreeAdded:Aggiunto: %s
-nl.all.TreeAdded:Toegevoegd: %s
-en.all.TreeLast:Last visited: %s
-de.all.TreeLast:letzter Besuch: %s
-fr.all.TreeLast:Dernière visitée : %s
-it.all.TreeLast:Ultima visita: %s
-nl.all.TreeLast:Laatst bezocht: %s
-en.all.TreeVisited:Visited: %s
-de.all.TreeVisited:gesehen am: %s
-fr.all.TreeVisited:Visitées : %s
-it.all.TreeVisited:Visitato: %s
-nl.all.TreeVisited:Bezocht: %s keer
-en.all.TreeVisits:Visits: %i
-de.all.TreeVisits:Besuche gesamt: %i
-fr.all.TreeVisits:Visites : %i
-it.all.TreeVisits:Visite totali: %i
-nl.all.TreeVisits:Bezocht: %i keer
-en.all.TreeUnknown:Unknown
-de.all.TreeUnknown:Unbekannt
-fr.all.TreeUnknown:Inconnue
-it.all.TreeUnknown:Sconosciuta/o
-nl.all.TreeUnknown:Onbekend
-en.all.TreeValue:Value: %s
-de.all.TreeValue:Eintrag: %s
-fr.all.TreeValue:Valeur : %s
-it.all.TreeValue:Valore: %s
-nl.all.TreeValue:Waarde: %s
-en.all.TreeComment:Comment: %s
-de.all.TreeComment:Kommentar: %s
-fr.all.TreeComment:Commentaire : %s
-it.all.TreeComment:Commento: %s
-nl.all.TreeComment:Commentaar: %s
-en.all.TreeDomain:Domain: %s%s
-de.all.TreeDomain:Domain: %s%s
-fr.all.TreeDomain:Domaine : %s%s
-it.all.TreeDomain:Dominio: %s%s
-nl.all.TreeDomain:Domein: %s%s
-en.all.TreePath:Path: %s%s
-de.all.TreePath:Pfad: %s%s
-fr.all.TreePath:Chemin : %s%s
-it.all.TreePath:Percorso: %s%s
-nl.all.TreePath:Pad: %s%s
-en.all.TreeExpires:Expires: %s
-de.all.TreeExpires:Verfällt: %s
-fr.all.TreeExpires:Expire : %s
-it.all.TreeExpires:Scadenza: %s
-nl.all.TreeExpires:Verloopt op: %s
-en.all.TreeLastUsed:Last used: %s
-de.all.TreeLastUsed:Zuletzt genutzt: %s
-fr.all.TreeLastUsed:Dernière utilisation : %s
-it.all.TreeLastUsed:Ultimo utilizzo: %s
-nl.all.TreeLastUsed:Laatst gebruikt: %s
-en.all.TreeSecure:Secure hosts only: %s
-de.all.TreeSecure:Nur sichere Hosts: %s
-fr.all.TreeSecure:Uniquement des sites sécurisés : %s
-it.all.TreeSecure:Solo host sicuri: %s
-nl.all.TreeSecure:Alleen veilige sites: %s
-en.all.TreeVersion:Version: %s
-de.all.TreeVersion:Version: %s
-fr.all.TreeVersion:Version : %s
-it.all.TreeVersion:Versione: %s
-nl.all.TreeVersion:Versie: %s
-en.all.TreePersistent:Persistent: %s
-de.all.TreePersistent:Persistent: %s
-fr.all.TreePersistent:Persistant : %s
-it.all.TreePersistent:Persistenza: %s
-nl.all.TreePersistent:Permanent: %s
-en.all.TreeHeaders: (from headers)
-de.all.TreeHeaders: (aus Header)
-fr.all.TreeHeaders: (à partir des entêtes)
-it.all.TreeHeaders: (da intestazioni)
-nl.all.TreeHeaders: (van koppen)
-en.all.TreeVersion0:Netscape
-de.all.TreeVersion0:Netscape
-fr.all.TreeVersion0:Netscape
-it.all.TreeVersion0:Netscape
-nl.all.TreeVersion0:Netscape
-en.all.TreeVersion1:RFC 2109
-de.all.TreeVersion1:RFC 2109
-fr.all.TreeVersion1:RFC 2109
-it.all.TreeVersion1:RFC 2109
-nl.all.TreeVersion1:RFC 2109
-en.all.TreeVersion2:RFC 2965
-de.all.TreeVersion2:RFC 2965
-fr.all.TreeVersion2:RFC 2965
-it.all.TreeVersion2:RFC 2965
-nl.all.TreeVersion2:RFC 2965
-en.all.TreeSession:Session end
-de.all.TreeSession:Sitzungsende
-fr.all.TreeSession:Fin de session
-it.all.TreeSession:Fine sessione
-nl.all.TreeSession:Sessie-einde
-en.all.TreeUnused:Unused
-de.all.TreeUnused:Nicht benutzt
-fr.all.TreeUnused:Inutilisé
-it.all.TreeUnused:Inutilizzato
-nl.all.TreeUnused:Ongebruikt
-en.all.TreeImport:Imported URL
-de.all.TreeImport:Importierte URL
-fr.all.TreeImport:URL importée
-it.all.TreeImport:URL importati
-nl.all.TreeImport:Geïmporteerd adres
-en.all.TreeNewLink:New address
-de.all.TreeNewLink:New address
-fr.all.TreeNewLink:Nouvelle adresse
-it.all.TreeNewLink:Nuovo indirizzo
-nl.all.TreeNewLink:Nieuw webadres
-en.all.TreeNewFolder:New directory
-de.all.TreeNewFolder:Neues Verzeichnis
-fr.all.TreeNewFolder:Nouv. répertoire
-it.all.TreeNewFolder:Nuova cartella
-nl.all.TreeNewFolder:Nieuwe map
-en.all.TreeLaunch:Visit URL
-de.all.TreeLaunch:URL ansehen
-fr.all.TreeLaunch:Visiter l'URL
-it.all.TreeLaunch:Visita URL
-nl.all.TreeLaunch:Bezoek webadres
-en.all.TreeDelete:Delete
-de.all.TreeDelete:Löschen
-fr.all.TreeDelete:Effacer
-it.all.TreeDelete:Elimina
-nl.all.TreeDelete:Verwijder
-en.all.TreeDefault:Set as default
-de.all.TreeDefault:Set as default
-fr.all.TreeDefault:Définir par défaut
-it.all.TreeDefault:Imposta come predefinito
-nl.all.TreeDefault:Stel in als standaard
-en.all.TreeClear:Clear default
-de.all.TreeClear:Clear default
-fr.all.TreeClear:Effacer défaut
-it.all.TreeClear:Annulla predefinito
-nl.all.TreeClear:Annuleer standaard
-en.ami.TreeEdit:Edit title
-de.ami.TreeEdit:Edit title
-fr.ami.TreeEdit:Modifier le titre
-it.ami.TreeEdit:Modifica titolo
-nl.ami.TreeEdit:Wijzig titel
-
-# Treeview field labels
-#
-en.all.TreeviewLabelTitle:Title
-de.all.TreeviewLabelTitle:Title
-fr.all.TreeviewLabelTitle:Titre
-it.all.TreeviewLabelTitle:Titolo
-nl.all.TreeviewLabelTitle:Titel:
-en.all.TreeviewLabelURL:URL
-de.all.TreeviewLabelURL:URL
-fr.all.TreeviewLabelURL:URL
-it.all.TreeviewLabelURL:URL
-nl.all.TreeviewLabelURL:Adres:
-en.all.TreeviewLabelLastVisit:Last visit
-de.all.TreeviewLabelLastVisit:Last visit
-fr.all.TreeviewLabelLastVisit:Dernière visite
-it.all.TreeviewLabelLastVisit:Ultima visita
-nl.all.TreeviewLabelLastVisit:Laatste bezoek:
-en.all.TreeviewLabelVisits:Visits
-de.all.TreeviewLabelVisits:Visits
-fr.all.TreeviewLabelVisits:Visites
-it.all.TreeviewLabelVisits:Visite
-nl.all.TreeviewLabelVisits:Bezocht:
-en.all.TreeviewLabelPeriod:Period
-de.all.TreeviewLabelPeriod:Period
-fr.all.TreeviewLabelPeriod:Période
-it.all.TreeviewLabelPeriod:Periodo
-nl.all.TreeviewLabelPeriod:Periode:
-
-en.all.TreeviewLabelName:Name
-de.all.TreeviewLabelName:Name
-fr.all.TreeviewLabelName:Nom
-it.all.TreeviewLabelName:Nome
-nl.all.TreeviewLabelName:Naam:
-en.all.TreeviewLabelContent:Content
-de.all.TreeviewLabelContent:Content
-fr.all.TreeviewLabelContent:Contenu
-it.all.TreeviewLabelContent:Contenuto
-nl.all.TreeviewLabelContent:Inhoud:
-en.all.TreeviewLabelDomain:Domain
-de.all.TreeviewLabelDomain:Domain
-fr.all.TreeviewLabelDomain:Domaine
-it.all.TreeviewLabelDomain:Dominio
-nl.all.TreeviewLabelDomain:Domein:
-en.all.TreeviewLabelPath:Path
-de.all.TreeviewLabelPath:Path
-fr.all.TreeviewLabelPath:Chemin
-it.all.TreeviewLabelPath:Percorso
-nl.all.TreeviewLabelPath:Pad:
-en.all.TreeviewLabelExpires:Expires
-de.all.TreeviewLabelExpires:Expires
-fr.all.TreeviewLabelExpires:Expire
-it.all.TreeviewLabelExpires:Scadenza
-nl.all.TreeviewLabelExpires:Verloopt:
-en.all.TreeviewLabelLastUsed:Last used
-de.all.TreeviewLabelLastUsed:Last used
-fr.all.TreeviewLabelLastUsed:Les dernières utilisées
-it.all.TreeviewLabelLastUsed:Ultimo utilizzo
-nl.all.TreeviewLabelLastUsed:Laatst gebruikt:
-en.all.TreeviewLabelRestrictions:Restrictions
-de.all.TreeviewLabelRestrictions:Restrictions
-fr.all.TreeviewLabelRestrictions:Restrictions
-it.all.TreeviewLabelRestrictions:Restrizioni
-nl.all.TreeviewLabelRestrictions:Beperkingen:
-en.all.TreeviewLabelVersion:Version
-de.all.TreeviewLabelVersion:Version
-fr.all.TreeviewLabelVersion:Version
-it.all.TreeviewLabelVersion:Versione
-nl.all.TreeviewLabelVersion:Versie:
-en.all.TreeviewLabelPersistent:Persistent
-de.all.TreeviewLabelPersistent:Persistent
-fr.all.TreeviewLabelPersistent:Persistant
-it.all.TreeviewLabelPersistent:Persistenza
-nl.all.TreeviewLabelPersistent:Permanent:
-en.all.TreeviewLabelDomainFolder:Domain folder
-de.all.TreeviewLabelDomainFolder:Domain folder
-fr.all.TreeviewLabelDomainFolder:Dossier de domaine
-it.all.TreeviewLabelDomainFolder:Cartella dominio
-nl.all.TreeviewLabelDomainFolder:Domeinmap:
-
-en.all.TreeviewLabelSerial:Serial
-de.all.TreeviewLabelSerial:Serial
-fr.all.TreeviewLabelSerial:Série
-it.all.TreeviewLabelSerial:Seriale
-nl.all.TreeviewLabelSerial:Serienr:
-en.all.TreeviewLabelType:Type
-de.all.TreeviewLabelType:Type
-fr.all.TreeviewLabelType:Type
-it.all.TreeviewLabelType:Tipo
-nl.all.TreeviewLabelType:Type:
-en.all.TreeviewLabelValidUntil:Valid until
-de.all.TreeviewLabelValidUntil:Valid until
-fr.all.TreeviewLabelValidUntil:Valable jusqu'au
-it.all.TreeviewLabelValidUntil:Valido fino a
-nl.all.TreeviewLabelValidUntil:Geldig tot:
-en.all.TreeviewLabelValidFrom:Valid from
-de.all.TreeviewLabelValidFrom:Valid from
-fr.all.TreeviewLabelValidFrom:Valable à partir du
-it.all.TreeviewLabelValidFrom:Valido da
-nl.all.TreeviewLabelValidFrom:Geldig vanaf:
-en.all.TreeviewLabelIssuer:Issuer
-de.all.TreeviewLabelIssuer:Issuer
-fr.all.TreeviewLabelIssuer:Émetteur
-it.all.TreeviewLabelIssuer:Emittente
-nl.all.TreeviewLabelIssuer:Uitgever:
-
-en.all.TreeviewLabelFolder:Folder
-de.all.TreeviewLabelFolder:Folder
-fr.all.TreeviewLabelFolder:Dossier
-it.all.TreeviewLabelFolder:Cartella
-nl.all.TreeviewLabelFolder:Map:
-
-
-# Cookie Manager field values
-#
-en.all.CookieManagerSession:Session
-it.all.CookieManagerSession:Sessione
-en.all.CookieManagerHTTPS:Secure hosts via https only
-de.all.CookieManagerHTTPS:Secure hosts via https only
-fr.all.CookieManagerHTTPS:Hôtes sécurisés via https uniquement
-it.all.CookieManagerHTTPS:Solo host sicuri via https
-nl.all.CookieManagerHTTPS:Veilige websites alleen via https
-en.all.CookieManagerSecure:Secure hosts only
-de.all.CookieManagerSecure:Secure hosts only
-fr.all.CookieManagerSecure:Hôtes sécurisés uniquement
-it.all.CookieManagerSecure:Solo host sicuri
-nl.all.CookieManagerSecure:Alleen veilige verbindingen
-en.all.CookieManagerHTTP:HTTP connections only
-de.all.CookieManagerHTTP:HTTP connections only
-fr.all.CookieManagerHTTP:Connexions HTTP uniquement
-it.all.CookieManagerHTTP:Solo connessioni HTTP
-nl.all.CookieManagerHTTP:Alleen HTTP-verbindingen
-
-
-# Hotlist default folder's default name
-#
-en.all.HotlistDefaultFolderName:Unsorted entries
-fr.all.HotlistDefaultFolderName:Entrées non triées
-it.all.HotlistDefaultFolderName:Voci non ordinate
-nl.all.HotlistDefaultFolderName:Ongesorteerde items
-
-
-# Default name for new folders
-#
-en.all.NewFolderName:New folder
-de.all.NewFolderName:New folder
-fr.all.NewFolderName:Nouveau dossier
-it.all.NewFolderName:Nuova cartella
-nl.all.NewFolderName:Nieuwe map
-
-
-# Default title
-#
-en.all.NoTitle:<No title>
-de.all.NoTitle:<No title>
-fr.all.NoTitle:<Sans titre>
-it.all.NoTitle:<Senza titolo>
-nl.all.NoTitle:<Naamloos>
-
-
-
-# Tree export
-#
-en.all.TreeHotlist:NetSurf hotlist
-de.all.TreeHotlist:NetSurf Hotlist
-fr.all.TreeHotlist:Favoris de NetSurf
-it.all.TreeHotlist:Segnalibri di NetSurf
-nl.all.TreeHotlist:NetSurf-favorieten
-
-
-# About user interface tokens
-# ===========================
-#
-# This secion is for tokens that have user information about the browser
-
-en.ami.NetSurfDesc:Small as a mouse, fast as a cheetah and available for free. NetSurf is a multi-platform web browser.
-fr.ami.NetSurfDesc:Petit comme une souris, rapide comme un guépard. NetSurf est un navigateur Web multi-plate-forme libre.
-it.ami.NetSurfDesc:Piccolo come un mouse e veloce come un ghepardo! NetSurf, il browser web opensource e multi-piattaforma
-nl.ami.NetSurfDesc:Klein als een muis, snel als een cheetah en gratis beschikbaar. NetSurf is een multi-platform webbrowser.
-
-en.gtk.AboutDesc:NetSurf is a small and fast web browser.
-fr.gtk.AboutDesc:NetSurf est un navigateur Web multi-plate-forme libre.
-it.gtk.AboutDesc:NetSurf, il browser web opensource e multi-piattaforma
-nl.gtk.AboutDesc:NetSurf is een kleine, snelle webbrowser met open broncode.
-
-# Hotlist user interface tokens
-# =============================
-#
-# This section contains tokens which are used in various parts of
-# the hotlist user interface.
-#
-
-# Hotlist sub-window titles
-#
-en.all.NewLink:Create new address
-de.all.NewLink:Neuen Eintrag erstellen
-fr.all.NewLink:Créer une nouvelle adresse
-it.all.NewLink:Crea nuovo indirizzo
-nl.all.NewLink:Nieuw adres aanmaken
-en.all.NewFolder:Create new directory
-de.all.NewFolder:Verzeichnis anlegen
-fr.all.NewFolder:Créer un nouveau dossier
-it.all.NewFolder:Crea nuova cartella
-nl.all.NewFolder:Nieuwe map aanmaken
-en.all.EditTitle:Edit title
-de.all.EditTitle:Edit title
-fr.all.EditTitle:Éditer le titre
-it.all.EditTitle:Modifica titolo
-nl.all.EditTitle:Wijzig titel
-en.all.EditLink:Edit address
-de.all.EditLink:Eintrag bearbeiten
-fr.all.EditLink:Éditer l'adresse
-it.all.EditLink:Modifica indirizzo
-nl.all.EditLink:Bewerk adres
-en.all.EditFolder:Rename directory
-de.all.EditFolder:Verzeichnis umbenennen
-fr.all.EditFolder:Renommer le dossier
-it.all.EditFolder:Rinomina cartella
-nl.all.EditFolder:Hernoem map
-
-# Default hotlist page names
-#
-en.all.HotlistHomepage:NetSurf homepage
-de.all.HotlistHomepage:NetSurf Homepage
-fr.all.HotlistHomepage:Page d'accueil de NetSurf
-it.all.HotlistHomepage:Pagina iniziale di NetSurf
-nl.all.HotlistHomepage:NetSurf-startpagina
-en.all.HotlistDocumentation:Documentation
-de.all.HotlistDocumentation:Dokumentation
-fr.all.HotlistDocumentation:Documentation
-it.all.HotlistDocumentation:Documentazione
-nl.all.HotlistDocumentation:Documentatie
-en.all.HotlistContact:Contact the NetSurf developers
-de.all.HotlistContact:Contact the NetSurf developers
-fr.all.HotlistContact:Contacter les développeurs de NetSurf
-it.all.HotlistContact:Contatta gli sviluppatori di NetSurf
-nl.all.HotlistContact:Contacteer (Eng.) de NetSurf-ontwikkelaars
-en.all.HotlistDownloads:Download the latest version
-de.all.HotlistDownloads:Download the latest version
-fr.all.HotlistDownloads:Télécharger la dernière version
-it.all.HotlistDownloads:Scarica l'ultima versione
-nl.all.HotlistDownloads:Haal de laatste versie op
-
-# Default (Amiga) hotlist folder names
-#
-en.ami.HotlistMenu:Hotlist menu
-de.ami.HotlistMenu:Hotlist menu
-fr.ami.HotlistMenu:Hotlist menu
-it.ami.HotlistMenu:Menu segnalibri
-nl.ami.HotlistMenu:Favorietenmenu
-en.ami.HotlistToolbar:Hotlist toolbar
-de.ami.HotlistToolbar:Hotlist toolbar
-fr.ami.HotlistToolbar:Hotlist toolbar
-it.ami.HotlistToolbar:Barra segnalibri
-nl.ami.HotlistToolbar:Favorietenwerkbalk
-
-
-# Global history user interface tokens
-# ====================================
-#
-# This section contains tokens which are used in various parts of
-# the global history user interface.
-#
-
-en.all.GlobalHistory:Global history
-de.all.GlobalHistory:History (global)
-fr.all.GlobalHistory:Historique global
-it.all.GlobalHistory:Cronologia globale
-nl.all.GlobalHistory:Browsergeschiedenis
-en.all.DomainAll:(All domains)
-de.all.DomainAll:(All domains)
-fr.all.DomainAll:(Tous les domaines)
-it.all.DomainAll:(Tutti i domini)
-nl.all.DomainAll:(Alle domeinen)
-en.all.DateToday:Today
-de.all.DateToday:Heute
-fr.all.DateToday:Aujourd'hui
-it.all.DateToday:Oggi
-nl.all.DateToday:Vandaag
-en.all.DateYesterday:Yesterday
-de.all.DateYesterday:Gestern
-fr.all.DateYesterday:Hier
-it.all.DateYesterday:Ieri
-nl.all.DateYesterday:Gisteren
-en.all.Date2Days:Two days ago
-de.all.Date2Days:vor 2 Tagen
-fr.all.Date2Days:Il y a deux jours
-it.all.Date2Days:2 giorni fa
-nl.all.Date2Days:2 dagen geleden
-en.all.Date3Days:Three days ago
-de.all.Date3Days:vor 3 Tagen
-fr.all.Date3Days:Il y a trois jours
-it.all.Date3Days:3 giorni fa
-nl.all.Date3Days:3 dagen geleden
-en.all.Date4Days:Four days ago
-de.all.Date4Days:vor 4 Tagen
-fr.all.Date4Days:Il y a quatre jours
-it.all.Date4Days:4 giorni fa
-nl.all.Date4Days:4 dagen geleden
-en.all.Date5Days:Five days ago
-de.all.Date5Days:vor 5 Tagen
-fr.all.Date5Days:Il y a cinq jours
-it.all.Date5Days:5 giorni fa
-nl.all.Date5Days:5 dagen geleden
-en.all.Date6Days:Six days ago
-de.all.Date6Days:vor 6 Tagen
-fr.all.Date6Days:Il y a six jours
-it.all.Date6Days:6 giorni fa
-nl.all.Date6Days:6 dagen geleden
-en.all.Date1Week:A week ago
-de.all.Date1Week:vor einer Woche
-fr.all.Date1Week:Il y a une semaine
-it.all.Date1Week:1 settimana fa
-nl.all.Date1Week:Een week geleden
-en.all.Date2Week:Two weeks ago
-de.all.Date2Week:vor 2 Wochen
-fr.all.Date2Week:Il y a 2 semaines
-it.all.Date2Week:2 settimane fa
-nl.all.Date2Week:2 weken geleden
-en.all.Date3Week:Three weeks ago
-de.all.Date3Week:vor 3 Wochen
-fr.all.Date3Week:Il y a 3 semaines
-it.all.Date3Week:3 settimane fa
-nl.all.Date3Week:3 weken geleden
-en.all.Sunday:Sunday
-de.all.Sunday:Sonntag
-fr.all.Sunday:Dimanche
-it.all.Sunday:Domenica
-nl.all.Sunday:Zondag
-en.all.Monday:Monday
-de.all.Monday:Montag
-fr.all.Monday:Lundi
-it.all.Monday:Lunedi
-nl.all.Monday:Maandag
-en.all.Tuesday:Tuesday
-de.all.Tuesday:Dienstag
-fr.all.Tuesday:Mardi
-it.all.Tuesday:Martedi
-nl.all.Tuesday:Dinsdag
-en.all.Wednesday:Wednesday
-de.all.Wednesday:Mittwoch
-fr.all.Wednesday:Mercredi
-it.all.Wednesday:Mercoledi
-nl.all.Wednesday:Woensdag
-en.all.Thursday:Thursday
-de.all.Thursday:Donnerstag
-fr.all.Thursday:Jeudi
-it.all.Thursday:Giovedi
-nl.all.Thursday:Donderdag
-en.all.Friday:Friday
-de.all.Friday:Freitag
-fr.all.Friday:Vendredi
-it.all.Friday:Venerdi
-nl.all.Friday:Vrijdag
-en.all.Saturday:Saturday
-de.all.Saturday:Samstag
-fr.all.Saturday:Samedi
-it.all.Saturday:Sabato
-nl.all.Saturday:Zaterdag
+zh_CN.all.ExternalApp:在外部应用中打开
# Download user interface tokens
@@ -1540,28 +3681,37 @@ nl.all.Saturday:Zaterdag
en.all.Download:%s of %s • %s/s • %s remaining
de.all.Download:%s von %s • %s/s • noch %s
fr.all.Download:%s de %s • %s/s • %s restants
-it.all.Download:%s di %s ? %s/s ? %s al termine
+it.all.Download:%s di %s �� %s/s �� %s al termine
nl.all.Download:%s van %s • %s/s • nog %s
+zh_CN.all.Download:第 %s 个,共 %s 个 • %s/s • 剩余 %s
+
en.all.DownloadU:%s of unknown • %s/s • %s total
de.all.DownloadU:%s von unbekannt • %s/s • bisher %s
fr.all.DownloadU:%s sur inconnu • %s/s • %s total
-it.all.DownloadU:%s sconosciuto ? %s/s ? %s totale
+it.all.DownloadU:%s sconosciuto �� %s/s �� %s totale
nl.all.DownloadU:%s van onbekend • %s/s • %s totaal
+zh_CN.all.DownloadU:未知 %s • %s/s • 总共 %s
+
en.all.Downloaded:%s complete • average %s/s • %s total
de.all.Downloaded:%s komplett • etwa %s/s • gesamt %s
fr.all.Downloaded:%s effectués • moyenne %s/s • %s total
-it.all.Downloaded:%s completato ? media di %s/s ? %s totale
+it.all.Downloaded:%s completato �� average %s/s �� %s totale
nl.all.Downloaded:%s compleet • gemiddeld %s/s • %s totaal
+zh_CN.all.Downloaded:å®Œæˆ %s • å¹³å‡ %s/s • 总共 %s
+
en.all.Unwritten:Writing data to file failed.
de.all.Unwritten:Schreiben der Datei ist fehlgeschlagen.
-fr.all.Unwritten:L'écriture de données dans le fichier a échoué.
+fr.all.Unwritten:L’écriture de données dans le fichier a échoué.
it.all.Unwritten:Scrittura dei dati sul file fallita.
nl.all.Unwritten:Informatie naar bestand wegschrijven is mislukt.
+zh_CN.all.Unwritten:将数æ®å†™å…¥æ–‡ä»¶å¤±è´¥ã€‚
+
en.all.Abort:Abort
de.all.Abort:Abgebrochen
fr.all.Abort:Interrompre
it.all.Abort:Annulla
nl.all.Abort:Breek af
+zh_CN.all.Abort:中止
# Amiga download window tokens
#
@@ -1570,37 +3720,47 @@ nl.all.Abort:Breek af
#
en.ami.amiDownloading:NetSurf: Downloading...
de.ami.amiDownloading:NetSurf: Downloading...
-fr.ami.amiDownloading:NetSurf: Downloading...
+fr.ami.amiDownloading:NetSurf: Téléchargement…
it.ami.amiDownloading:NetSurf: Scaricamento...
nl.ami.amiDownloading:NetSurf: Downloading...
+zh_CN.ami.amiDownloading:NetSurf:正在下载…
+
en.ami.amiDownload:%ld of %ld bytes downloaded
de.ami.amiDownload:%ld von %ld Bytes heruntergeladen
-fr.ami.amiDownload:%ld of %ld bytes downloaded
+fr.ami.amiDownload:%ld de %ld bytes téléchargés
it.ami.amiDownload:%ld di %ld byte scaricati
nl.ami.amiDownload:%ld van %ld bytes opgehaald
+zh_CN.ami.amiDownload:已下载 %2$ld 个字节中的 %1$ld 个
+
en.ami.amiDownloadU:%ld bytes downloaded
de.ami.amiDownloadU:%ld Bytes heruntergeladen
-fr.ami.amiDownloadU:%ld bytes downloaded
+fr.ami.amiDownloadU:%ld bytes téléchargés
it.ami.amiDownloadU:%ld byte scaricati
nl.ami.amiDownloadU:%ld bytes opgehaald
+zh_CN.ami.amiDownloadU:已下载 %ld 个字节
+
en.ami.amiDownloadComplete:NetSurf: Download completed
de.ami.amiDownloadComplete:NetSurf: Download vollständig
fr.ami.amiDownloadComplete:NetSurf: Download completed
it.ami.amiDownloadComplete:NetSurf: Download completato
nl.ami.amiDownloadComplete:NetSurf: Download voltooid
+zh_CN.ami.amiDownloadComplete:NetSurf:已完æˆä¸‹è½½
# Requesters
#
en.ami.amiSizeExisting:Existing file size:
de.ami.amiSizeExisting:Größe der vorhandenen Datei:
fr.ami.amiSizeExisting:Existing file size:
-it.ami.amiSizeExisting:Dimensione del file esistente:
+it.ami.amiSizeExisting:Dimensione del file originale:
nl.ami.amiSizeExisting:Bestaande bestandsgrootte:
+zh_CN.ami.amiSizeExisting:已有文件大å°ï¼š
+
en.ami.amiSizeNew:New file size:
de.ami.amiSizeNew:Größe der neuen Datei:
fr.ami.amiSizeNew:New file size:
it.ami.amiSizeNew:Nuova dimensione del file:
nl.ami.amiSizeNew:Nieuwe bestandsgrootte:
+zh_CN.ami.amiSizeNew:新文件大å°ï¼š
# GTK download window tokens
#
@@ -1613,21 +3773,28 @@ de.gtk.gtkSizeInfo:%s von %s
fr.gtk.gtkSizeInfo:%s de %s
it.gtk.gtkSizeInfo:%s di %s
nl.gtk.gtkSizeInfo:%s van %s
+zh_CN.gtk.gtkSizeInfo:%s,共 %s
+
en.gtk.gtkProgressBar:%.0f%% of %u files
de.gtk.gtkProgressBar:%.0f%% von %u Dateien
fr.gtk.gtkProgressBar:%.0f%% de %u fichiers
-it.gtk.gtkProgressBar:%. di %% su %u file
+it.gtk.gtkProgressBar:%.0f%% di %u file
nl.gtk.gtkProgressBar:%.0f%% van %u bestanden
+zh_CN.gtk.gtkProgressBar:%.0f%%,共 %u 个文件
+
en.gtk.gtkProgressBarPulse:Downloading %u files
de.gtk.gtkProgressBarPulse:Lade %u Dateien herunter
-fr.gtk.gtkProgressBarPulse:Tèlèchargement des fichiers %u
+fr.gtk.gtkProgressBarPulse:Téléchargement des fichiers %u
it.gtk.gtkProgressBarPulse:Scaricamento dei file %u
nl.gtk.gtkProgressBarPulse:%u bestanden aan het downloaden
+zh_CN.gtk.gtkProgressBarPulse:正在下载 %u 个文件
+
en.gtk.gtkProgressBarPulseSingle:Downloading %u file
de.gtk.gtkProgressBarPulseSingle:Lade %u Datei
fr.gtk.gtkProgressBarPulseSingle:Téléchargement du fichier %u
it.gtk.gtkProgressBarPulseSingle:Scaricamento del file %u
nl.gtk.gtkProgressBarPulseSingle:%u bestand aan het downloaden
+zh_CN.gtk.gtkProgressBarPulseSingle:正在下载 %u 个文件
# Column Headers
#
@@ -1636,21 +3803,28 @@ de.gtk.gtkProgress:Fortschritt
fr.gtk.gtkProgress:Progression
it.gtk.gtkProgress:Progressi
nl.gtk.gtkProgress:Voortgang
+zh_CN.gtk.gtkProgress:进展
+
en.gtk.gtkDetails:Details
de.gtk.gtkDetails:Details
fr.gtk.gtkDetails:Détails
it.gtk.gtkDetails:Dettagli
nl.gtk.gtkDetails:Details
+zh_CN.gtk.gtkDetails:详细信æ¯
+
en.gtk.gtkSpeed:Speed
de.gtk.gtkSpeed:Geschwindigkeit
fr.gtk.gtkSpeed:Vitesse
it.gtk.gtkSpeed:Velocità
nl.gtk.gtkSpeed:Snelheid
+zh_CN.gtk.gtkSpeed:速度
+
en.gtk.gtkRemaining:Remaining
de.gtk.gtkRemaining:Ãœbrig
fr.gtk.gtkRemaining:Temps restant
it.gtk.gtkRemaining:Al termine
nl.gtk.gtkRemaining:Overig
+zh_CN.gtk.gtkRemaining:剩余
# Status Messages
# spaces necessary
@@ -1661,2025 +3835,1596 @@ de.gtk.gtkError: Fehler
fr.gtk.gtkError: Erreur
it.gtk.gtkError: Errore
nl.gtk.gtkError: Fout
+zh_CN.gtk.gtkError: 错误
+
en.gtk.gtkComplete: Complete
de.gtk.gtkComplete: Vollständig
-fr.gtk.gtkComplete: Terniné
-it.gtk.gtkComplete: Completo
+fr.gtk.gtkComplete: Terminé
+it.gtk.gtkComplete: Completato
nl.gtk.gtkComplete: Voltooid
+zh_CN.gtk.gtkComplete: 完æˆ
+
en.gtk.gtkCanceled: Canceled
de.gtk.gtkCanceled: Abgebrochen
fr.gtk.gtkCanceled: Annulé
it.gtk.gtkCanceled: Annullato
nl.gtk.gtkCanceled: Afgebroken
+zh_CN.gtk.gtkCanceled: å·²å–消
+
en.gtk.gtkWorking: Working
de.gtk.gtkWorking: Arbeite
-fr.gtk.gtkWorking: en cours
+fr.gtk.gtkWorking: En cours
it.gtk.gtkWorking: In corso
nl.gtk.gtkWorking: In bedrijf
+zh_CN.gtk.gtkWorking: 正在处ç†
# Dialogs
#
en.gtk.gtkQuit:Quit NetSurf?
de.gtk.gtkQuit:NetSurf beenden?
-fr.gtk.gtkQuit:Quitter NetSurf ?
+fr.gtk.gtkQuit:Quitter NetSurf ?
it.gtk.gtkQuit:Sei sicuro di voler uscire da NetSurf?
nl.gtk.gtkQuit:NetSurf afsluiten?
+zh_CN.gtk.gtkQuit:是å¦é€€å‡º NetSurf?
+
en.gtk.gtkDownloadsRunning:There are still downloads running, if you quit now these will be canceled and the files deleted.
de.gtk.gtkDownloadsRunning:Es sind noch Downloads aktiv, beim Beenden werden sie abgebrochen und die Dateien gelöscht.
fr.gtk.gtkDownloadsRunning:Il y a encore des téléchargements en cours, si vous quittez maintenant ceux-ci seront annulés et les fichiers supprimés.
it.gtk.gtkDownloadsRunning:Sono presenti alcuni file in download in attesa di essere completati, chiudendo questa sessione tutti i file incompleti verranno cancellati.
nl.gtk.gtkDownloadsRunning:Er zijn nog downloads bezig, bij het afsluiten worden deze afgebroken en worden de bijbehorende bestanden gewist.
+zh_CN.gtk.gtkDownloadsRunning:ç›®å‰ä»ç„¶æœ‰ä¸‹è½½ä»»åŠ¡æ­£åœ¨è¿è¡Œï¼Œå¦‚果您现在退出,将å–消这些下载任务并删除文件。
+
en.gtk.gtkStartDownload:Download file?
de.gtk.gtkStartDownload:Datei herunterladen?
-fr.gtk.gtkStartDownload:Téléchargement du fichier?
+fr.gtk.gtkStartDownload:Téléchargement du fichier ?
it.gtk.gtkStartDownload:Scaricare il file?
nl.gtk.gtkStartDownload:Bestand downloaden?
+zh_CN.gtk.gtkStartDownload:下载文件?
+
en.gtk.gtkOverwrite:A file named "%s" already exists. Do you want to replace it?
de.gtk.gtkOverwrite:Eine Datei mit dem Namen "%s" existiert bereits. Soll sie ersetzt werden?
-fr.gtk.gtkOverwrite:Un fichier nommé "%s" existe déja. Voulez-vous le remplacer ?
+fr.gtk.gtkOverwrite:Un fichier nommé « %s » existe déja. Voulez-vous le remplacer ?
it.gtk.gtkOverwrite:Il file "%s" è già esistente. Si desidera sovrascriverlo?
nl.gtk.gtkOverwrite:Een bestand met de naam "%s" bestaat reeds. Bestand overschrijven en vervangen?
+zh_CN.gtk.gtkOverwrite:已存在å为 “%s†的文件。您è¦æ›¿æ¢å®ƒå—?
+
en.gtk.gtkOverwriteTitle:File exists
de.gtk.gtkOverwriteTitle:File exists
-fr.gtk.gtkOverwriteTitle:Le fichier existe
+fr.gtk.gtkOverwriteTitle:Fichier existant
it.gtk.gtkOverwriteTitle:File già esistente
nl.gtk.gtkOverwriteTitle:Bestand bestaat reeds.
+zh_CN.gtk.gtkOverwriteTitle:文件已存在
+
en.gtk.gtkOverwriteInfo:The file already exists in "%s". Replacing it will overwrite its contents.
de.gtk.gtkOverwriteInfo:Die Datei existiert bereits im Verzeichnis "%s". Beim ersetzen wird ihr momentaner Inhalt überschrieben.
-fr.gtk.gtkOverwriteInfo:Le fichier existe déja dans "%s". Son remplacement réécrira son contenu.
+fr.gtk.gtkOverwriteInfo:Le fichier existe déja dans « %s ». Son remplacement réécrira son contenu.
it.gtk.gtkOverwriteInfo:Il file è già esistente in "%s". Sostituirlo comporterà la sovrascrittura del file.
nl.gtk.gtkOverwriteInfo:Het bestand bestaat reeds in map "%s". Bij het vervangen zal de huidige inhoud worden overschreven.
+zh_CN.gtk.gtkOverwriteInfo:“%s†中已有该文件。替æ¢æ­¤æ–‡ä»¶ä¼šè¦†ç›–其内容。
+
en.gtk.gtkFailed:Download failed
de.gtk.gtkFailed:Download fehlgeschlagen
fr.gtk.gtkFailed:Échec du téléchargement
it.gtk.gtkFailed:Scaricamento fallito
nl.gtk.gtkFailed:Download mislukt
+zh_CN.gtk.gtkFailed:下载失败
+
en.gtk.gtkFileError:File error: %s
de.gtk.gtkFileError:Dateifehler: %s
-fr.gtk.gtkFileError:Erreur de fichier : %s
+fr.gtk.gtkFileError:Erreur de fichier : %s
it.gtk.gtkFileError:Errore file: %s
nl.gtk.gtkFileError:Bestandsfout: %s
+zh_CN.gtk.gtkFileError:文件错误: %s
+
en.gtk.gtkInfo:%s from %s is %s in size
de.gtk.gtkInfo:%s von %s ist %s in size
fr.gtk.gtkInfo:%s de %s est de taille %s
it.gtk.gtkInfo:%s da %s è %s come dimensione
nl.gtk.gtkInfo:%s van %s is %s in grootte
+zh_CN.gtk.gtkInfo:%2$s 中的 %1$s 大å°æ˜¯ %3$s
+
en.gtk.gtkSave:Save file as…
de.gtk.gtkSave:Datei speichern unter...
-fr.gtk.gtkSave:Enregistrer le fichier sous...
+fr.gtk.gtkSave:Enregistrer le fichier sous…
it.gtk.gtkSave:Salva file come...
nl.gtk.gtkSave:Bestand bewaren als...
+zh_CN.gtk.gtkSave:文件å¦å­˜ä¸ºâ€¦
+
en.gtk.gtkSourceSave:Save source
de.gtk.gtkSourceSave:Quelltext speichern
-fr.gtk.gtkSourceSave:Enregistrer la Source
+fr.gtk.gtkSourceSave:Enregistrer la source
it.gtk.gtkSourceSave:Salva sorgente
nl.gtk.gtkSourceSave:Brontekst bewaren
+zh_CN.gtk.gtkSourceSave:ä¿å­˜æº
+
en.gtk.gtkSourceTabError:Error handling source data
de.gtk.gtkSourceTabError:Fehler beim behandeln der Quelldaten
fr.gtk.gtkSourceTabError:Erreur de manipulation des données source
it.gtk.gtkSourceTabError:Errore di modifica sul sorgente
nl.gtk.gtkSourceTabError:Fout plaatsgevonden bij afhandelen brondata
+zh_CN.gtk.gtkSourceTabError:处ç†æºæ•°æ®æ—¶å‡ºé”™
+
en.gtk.gtkplainSave:Save plain text
de.gtk.gtkplainSave:Als Text speichern
fr.gtk.gtkplainSave:Enregistrer sans mise en forme
it.gtk.gtkplainSave:Salva come testo
nl.gtk.gtkplainSave:Als tekst bewaren
-en.gtk.gtkcompleteSave:Save webpage complete - select an empty directory
-de.gtk.gtkcompleteSave:Seite komplett speichern - ein leeres Verzeichnis wählen
-fr.gtk.gtkcompleteSave:Enregistrer page web complète - sélectioner un dossier vide
-it.gtk.gtkcompleteSave:Salva l'intera pagina web - seleziona una directory vuota
-nl.gtk.gtkcompleteSave:Complete webpagina bewaren - selecteer een lege map
+zh_CN.gtk.gtkplainSave:ä¿å­˜çº¯æ–‡æœ¬
+
+en.gtk.gtkcompleteSave:Export complete page as a folder
+de.gtk.gtkcompleteSave:Seite komplett speichern
+fr.gtk.gtkcompleteSave:Enregistrer la page Web complète
+it.gtk.gtkcompleteSave:Salva pagina web completa
+nl.gtk.gtkcompleteSave:Complete webpagina bewaren
+zh_CN.gtk.gtkcompleteSave:将完整页é¢å¯¼å‡ºä¸ºæ–‡ä»¶å¤¹
+
en.gtk.gtkSaveConfirm:File saved
de.gtk.gtkSaveConfirm:Datei gespeichert
fr.gtk.gtkSaveConfirm:Fichier enregistré
it.gtk.gtkSaveConfirm:File salvato
nl.gtk.gtkSaveConfirm:Bestand bewaard
+zh_CN.gtk.gtkSaveConfirm:文件已ä¿å­˜
+
en.gtk.gtkSaveCancelled:File not saved
de.gtk.gtkSaveCancelled:Datei nicht gespeichert
-fr.gtk.gtkSaveCancelled:Fichier pas enregistré
+fr.gtk.gtkSaveCancelled:Fichier non enregistré
it.gtk.gtkSaveCancelled:File non salvato
nl.gtk.gtkSaveCancelled:Bestand is niet bewaard
+zh_CN.gtk.gtkSaveCancelled:文件未ä¿å­˜
+
en.gtk.gtkUnknownHost:an unknown host
de.gtk.gtkUnknownHost:ein unbekannter Host
fr.gtk.gtkUnknownHost:un hôte inconnu
it.gtk.gtkUnknownHost:un host sconosciuto
nl.gtk.gtkUnknownHost:een onbekende host
+zh_CN.gtk.gtkUnknownHost:未知主机
+
en.gtk.gtkUnknownFile:
de.gtk.gtkUnknownFile:
fr.gtk.gtkUnknownFile:
it.gtk.gtkUnknownFile:
nl.gtk.gtkUnknownFile:
+zh_CN.gtk.gtkUnknownFile:未知文件
+
en.gtk.gtkUnknownSize:unknown
de.gtk.gtkUnknownSize:unbekannt
fr.gtk.gtkUnknownSize:inconnue
it.gtk.gtkUnknownSize:sconosciuto
nl.gtk.gtkUnknownSize:onbekend
+zh_CN.gtk.gtkUnknownSize:未知大å°
# gtk Menu / Button labels
#
+en.gtk.gtkOpenMenu:Open Menu
+fr.gtk.gtkOpenMenu:Ouvrir le menu
+it.gtk.gtkOpenMenu:Apri menu
+zh_CN.gtk.gtkOpenMenu:打开èœå•
+
en.gtk.gtkFile:_File
de.gtk.gtkFile:_Datei
fr.gtk.gtkFile:_Fichier
it.gtk.gtkFile:_File
nl.gtk.gtkFile:_Bestand
+zh_CN.gtk.gtkFile:文件(_F)
+
en.gtk.gtkEdit:_Edit
de.gtk.gtkEdit:_Bearbeiten
-fr.gtk.gtkEdit:Édit_er
+fr.gtk.gtkEdit:Édi_tion
it.gtk.gtkEdit:Mo_difica
nl.gtk.gtkEdit:Be_werken
+zh_CN.gtk.gtkEdit:退出(_E)
+
en.gtk.gtkView:_View
de.gtk.gtkView:_Ansicht
fr.gtk.gtkView:_Affichage
it.gtk.gtkView:_Mostra
nl.gtk.gtkView:Bee_ld
+zh_CN.gtk.gtkView:视图(_V)
+
en.gtk.gtkNavigate:_Navigate
de.gtk.gtkNavigate:_Navigieren
fr.gtk.gtkNavigate:_Navigation
it.gtk.gtkNavigate:_Visualizza
nl.gtk.gtkNavigate:_Ga
+zh_CN.gtk.gtkNavigate:导航(_N)
+
en.gtk.gtkTools:_Tools
de.gtk.gtkTools:_Tools
-fr.gtk.gtkTools:Ou_tils
+fr.gtk.gtkTools:_Outils
it.gtk.gtkTools:_Strumenti
nl.gtk.gtkTools:E_xtra
+zh_CN.gtk.gtkTools:工具(_T)
+
en.gtk.gtkHelp:_Help
de.gtk.gtkHelp:_Hilfe
fr.gtk.gtkHelp:_Aide
it.gtk.gtkHelp:_Aiuto
nl.gtk.gtkHelp:_Hulp
+zh_CN.gtk.gtkHelp:帮助(_H)
en.gtk.gtkNewTab:New _Tab
de.gtk.gtkNewTab:Neuer _Tab
-fr.gtk.gtkNewTab:Nouvel _Onglet
+fr.gtk.gtkNewTab:Nouvel _onglet
it.gtk.gtkNewTab:Nuova _scheda
nl.gtk.gtkNewTab:Nieuw _Tabblad
+zh_CN.gtk.gtkNewTab:新建标签页(_T)
+
en.gtk.gtkNewWindow:_New Window
de.gtk.gtkNewWindow:_Neues Fenster
-fr.gtk.gtkNewWindow:_Nouvelle Fenêtre
-it.gtk.gtkNewWindow:_Nuova finestra
+fr.gtk.gtkNewWindow:_Nouvelle fenêtre
+it.gtk.gtkNewWindow:Nuova _finestra
nl.gtk.gtkNewWindow:_Nieuw venster
+zh_CN.gtk.gtkNewWindow:新建窗å£(_N)
+
en.gtk.gtkOpenFile:_Open File
de.gtk.gtkOpenFile:Datei öffnen
fr.gtk.gtkOpenFile:_Ouvrir un fichier
it.gtk.gtkOpenFile:_Apri file
nl.gtk.gtkOpenFile:Bestand _openen
+zh_CN.gtk.gtkOpenFile:打开文件(_O)
+
en.gtk.gtkCloseWindow:_Close Window
de.gtk.gtkCloseWindow:Fenster schließen
fr.gtk.gtkCloseWindow:_Fermer la fenêtre
it.gtk.gtkCloseWindow:_Chiudi finestra
nl.gtk.gtkCloseWindow:_Venster sluiten
-en.gtk.gtkSavePage:Save Page…
-de.gtk.gtkSavePage:Seite speichern..
-fr.gtk.gtkSavePage:Enregistrer la Page...
-it.gtk.gtkSavePage:Salva pagina...
-nl.gtk.gtkSavePage:Pagina bewaren...
+zh_CN.gtk.gtkCloseWindow:关闭窗å£(_C)
+
en.gtk.gtkExport:Export
de.gtk.gtkExport:Exportieren
fr.gtk.gtkExport:Exporter
it.gtk.gtkExport:Esporta
nl.gtk.gtkExport:Exporteren
+zh_CN.gtk.gtkExport:导出
+
+en.gtk.gtkSavePage:Complete Page…
+de.gtk.gtkSavePage:Seite speichern..
+fr.gtk.gtkSavePage:Enregistrer la Page…
+it.gtk.gtkSavePage:Salva pagina...
+nl.gtk.gtkSavePage:Pagina bewaren...
+zh_CN.gtk.gtkSavePage:完整页é¢â€¦
+
en.gtk.gtkPlainText:Plain Text…
de.gtk.gtkPlainText:Reiner Text..
-fr.gtk.gtkPlainText:Texte...
+fr.gtk.gtkPlainText:Texte…
it.gtk.gtkPlainText:Testo normale...
nl.gtk.gtkPlainText:Platte tekst...
+zh_CN.gtk.gtkPlainText:纯文本…
+
en.gtk.gtkDrawFile:Drawfile…
de.gtk.gtkDrawFile:Drawfile..
-fr.gtk.gtkDrawFile:Fichier dessin...
+fr.gtk.gtkDrawFile:Fichier dessin…
it.gtk.gtkDrawFile:File Draw...
nl.gtk.gtkDrawFile:Draw-bestand...
+zh_CN.gtk.gtkDrawFile:绘图文件…
+
en.gtk.gtkPostScript:PostScript…
de.gtk.gtkPostScript:PostScript..
-fr.gtk.gtkPostScript:PostScript...
-it.gtk.gtkPostScript:PostScript...
+fr.gtk.gtkPostScript:PostScript…
+it.gtk.gtkPostScript:File PostScript...
nl.gtk.gtkPostScript:PostScript...
+zh_CN.gtk.gtkPostScript:PostScript…
+
en.gtk.gtkPDF:PDF…
de.gtk.gtkPDF:PDF..
-fr.gtk.gtkPDF:PDF...
-it.gtk.gtkPDF:PDF...
+fr.gtk.gtkPDF:PDF…
+it.gtk.gtkPDF:File PDF...
nl.gtk.gtkPDF:PDF...
+zh_CN.gtk.gtkPDF:PDF…
+
en.gtk.gtkPrintPreview:Print Preview…
de.gtk.gtkPrintPreview:Druckvorschau...
-fr.gtk.gtkPrintPreview:Aperçu avant impression...
+fr.gtk.gtkPrintPreview:Aperçu avant impression…
it.gtk.gtkPrintPreview:Anteprima di stampa...
nl.gtk.gtkPrintPreview:Afdruk_voorbeeld...
+zh_CN.gtk.gtkPrintPreview:打å°é¢„览…
+
en.gtk.gtkPrint:Print…
de.gtk.gtkPrint:Drucken...
-fr.gtk.gtkPrint:Imprimer...
+fr.gtk.gtkPrint:Imprimer…
it.gtk.gtkPrint:Stampa...
nl.gtk.gtkPrint:Af_drukken...
+zh_CN.gtk.gtkPrint:打å°â€¦
+
en.gtk.gtkQuitMenu:_Quit
de.gtk.gtkQuitMenu:Beenden
fr.gtk.gtkQuitMenu:_Quitter
it.gtk.gtkQuitMenu:_Esci
nl.gtk.gtkQuitMenu:A_fsluiten
+zh_CN.gtk.gtkQuitMenu:退出(_Q)
en.gtk.gtkCut:Cu_t
de.gtk.gtkCut:Ausschneiden
fr.gtk.gtkCut:Cou_per
-it.gtk.gtkCut:Ta_glia
+it.gtk.gtkCut:_Taglia
nl.gtk.gtkCut:K_nippen
+zh_CN.gtk.gtkCut:剪切(_T)
+
en.gtk.gtkCopy:_Copy
de.gtk.gtkCopy:Kopieren
fr.gtk.gtkCopy:_Copier
it.gtk.gtkCopy:_Copia
nl.gtk.gtkCopy:_Kopiëren
+zh_CN.gtk.gtkCopy:å¤åˆ¶(_C)
+
en.gtk.gtkPaste:_Paste
de.gtk.gtkPaste:Einfügen
fr.gtk.gtkPaste:C_oller
it.gtk.gtkPaste:_Incolla
nl.gtk.gtkPaste:_Plakken
+zh_CN.gtk.gtkPaste:粘贴(_P)
+
en.gtk.gtkDelete:_Delete
de.gtk.gtkDelete:Löschen
fr.gtk.gtkDelete:_Supprimer
-it.gtk.gtkDelete:_Cancella
+it.gtk.gtkDelete:Ca_ncella
nl.gtk.gtkDelete:_Verwijderen
+zh_CN.gtk.gtkDelete:删除(_D)
+
en.gtk.gtkSelectAll:Select _All
de.gtk.gtkSelectAll:_Alles auswählen
fr.gtk.gtkSelectAll:_Tout sélectionner
-it.gtk.gtkSelectAll:Seleziona _Tutto
+it.gtk.gtkSelectAll:_Seleziona Tutto
nl.gtk.gtkSelectAll:_Alles selecteren
+zh_CN.gtk.gtkSelectAll:全选(_A)
+
en.gtk.gtkFind:_Find…
de.gtk.gtkFind:_Finden..
-fr.gtk.gtkFind:_Rechercher...
-it.gtk.gtkFind:_Trova...
+fr.gtk.gtkFind:_Rechercher…
+it.gtk.gtkFind:T_rova...
nl.gtk.gtkFind:_Zoeken...
+zh_CN.gtk.gtkFind:查找(_F) …
+
en.gtk.gtkPreferences:P_references
de.gtk.gtkPreferences:Einstellungen
fr.gtk.gtkPreferences:P_références
-it.gtk.gtkPreferences:P_referenze
+it.gtk.gtkPreferences:_Preferenze
nl.gtk.gtkPreferences:V_oorkeuren
+zh_CN.gtk.gtkPreferences:首选项(_R)
en.gtk.gtkStop:_Stop
de.gtk.gtkStop:_Stop
fr.gtk.gtkStop:_Arrêter
-it.gtk.gtkStop:_Stoppa
+it.gtk.gtkStop:_Stop
nl.gtk.gtkStop:_Stoppen
+zh_CN.gtk.gtkStop:åœæ­¢(_S)
+
en.gtk.gtkReload:_Reload
de.gtk.gtkReload:Neu laden
fr.gtk.gtkReload:_Actualiser
it.gtk.gtkReload:_Ricarica
nl.gtk.gtkReload:Ver_nieuwen
+zh_CN.gtk.gtkReload:é‡è½½(_R)
+
en.gtk.gtkScaleView:_Scale View
de.gtk.gtkScaleView:Ansicht skalieren
fr.gtk.gtkScaleView:_Zoom
-it.gtk.gtkScaleView:_Scala
+it.gtk.gtkScaleView:S_cala
nl.gtk.gtkScaleView:_Zoomen
+zh_CN.gtk.gtkScaleView:缩放视图(_S)
+
en.gtk.gtkZoomPlus:Zoom _in
de.gtk.gtkZoomPlus:Here_inzoomen
fr.gtk.gtkZoomPlus:Zoom _avant
-it.gtk.gtkZoomPlus:_Incrementa zoom
+it.gtk.gtkZoomPlus:_Aumenta zoom
nl.gtk.gtkZoomPlus:_Inzoomen
+zh_CN.gtk.gtkZoomPlus:放大(_I)
+
en.gtk.gtkZoomMinus:Zoom _out
de.gtk.gtkZoomMinus:Herausz_oomen
fr.gtk.gtkZoomMinus:Z_oom arrière
it.gtk.gtkZoomMinus:_Diminuisci zoom
nl.gtk.gtkZoomMinus:_Uitzoomen
+zh_CN.gtk.gtkZoomMinus:缩å°(_O)
+
en.gtk.gtkZoomNormal:_Normal size
de.gtk.gtkZoomNormal:_Normalgröße
fr.gtk.gtkZoomNormal:_Taille Normale
it.gtk.gtkZoomNormal:Dimensione _normale
nl.gtk.gtkZoomNormal:_Originele grootte
+zh_CN.gtk.gtkZoomNormal:正常大å°(_N)
+
en.gtk.gtkFullScreen:_Fullscreen
de.gtk.gtkFullScreen:_Vollbild
fr.gtk.gtkFullScreen:_Plein écran
-it.gtk.gtkFullScreen:_Tutto schermo
+it.gtk.gtkFullScreen:Tutto scher_mo
nl.gtk.gtkFullScreen:_Volledig scherm
+zh_CN.gtk.gtkFullScreen:å…¨å±(_F)
+
en.gtk.gtkPageSource:Page S_ource
de.gtk.gtkPageSource: Q_uelltext anzeigen
fr.gtk.gtkPageSource:Code s_ource de la page
it.gtk.gtkPageSource:Mostra s_orgente
nl.gtk.gtkPageSource:Pagina_bron
+zh_CN.gtk.gtkPageSource:页é¢æºä»£ç (_O)
+
en.gtk.gtkImages:_Images
de.gtk.gtkImages:B_ilder
fr.gtk.gtkImages:_Images
it.gtk.gtkImages:_Immagini
nl.gtk.gtkImages:_Afbeeldingen
+zh_CN.gtk.gtkImages:图åƒ(_I)
+
en.gtk.gtkForegroundImages:_Foreground Images
de.gtk.gtkForegroundImages:_Vordergrundbilder
fr.gtk.gtkForegroundImages:_Images de premier plan
it.gtk.gtkForegroundImages:In _primo piano
nl.gtk.gtkForegroundImages:_Voorgrondafbeeldingen
+zh_CN.gtk.gtkForegroundImages:å‰æ™¯å›¾åƒ(_F)
+
en.gtk.gtkBackgroundImages:_Background Images
de.gtk.gtkBackgroundImages:_Hintergrundbilder
-fr.gtk.gtkBackgroundImages:_Images d'arrière plan
+fr.gtk.gtkBackgroundImages:_Images d’arrière plan
it.gtk.gtkBackgroundImages:In _sottofondo
nl.gtk.gtkBackgroundImages:_Achtergrondafbeeldingen
+zh_CN.gtk.gtkBackgroundImages:背景图åƒ(_B)
+
en.gtk.gtkToolbars:_Toolbars
de.gtk.gtkToolbars:_Werkzeugleisten
-fr.gtk.gtkToolbars:Barre d'ou_tils
+fr.gtk.gtkToolbars:Barres d’ou_tils
it.gtk.gtkToolbars:_Barre strumenti
nl.gtk.gtkToolbars:_Werkbalken
+zh_CN.gtk.gtkToolbars:工具æ (_T)
+
en.gtk.gtkTabs:_Tabs
de.gtk.gtkTabs:_Tabs
fr.gtk.gtkTabs:Ongle_ts
it.gtk.gtkTabs:_Schede
nl.gtk.gtkTabs:_Tabbladen
+zh_CN.gtk.gtkTabs:标签页(_T)
+
en.gtk.gtkMenuBar:_Menu Bar
de.gtk.gtkMenuBar:_Menüleiste
fr.gtk.gtkMenuBar:Barre de _menu
it.gtk.gtkMenuBar:Barra _menu
nl.gtk.gtkMenuBar:_Menubalk
+zh_CN.gtk.gtkMenuBar:èœå•æ (_M)
+
en.gtk.gtkToolBar:_Button Bar
de.gtk.gtkToolBar:_Buttonleiste
-fr.gtk.gtkToolBar:_Barre de boutons
+fr.gtk.gtkToolBar:_Barre de navigation
it.gtk.gtkToolBar:Barra p_ulsanti
nl.gtk.gtkToolBar:_Knoppenbalk
+zh_CN.gtk.gtkToolBar:按钮æ (_B)
+
en.gtk.gtkStatusBar:_Status Bar
de.gtk.gtkStatusBar:_Statusleiste
-fr.gtk.gtkStatusBar:Ba_rre d'état
+fr.gtk.gtkStatusBar:Ba_rre d’état
it.gtk.gtkStatusBar:Barra di s_tato
nl.gtk.gtkStatusBar:_Statusbalk
+zh_CN.gtk.gtkStatusBar:状æ€æ (_S)
+
en.gtk.gtkDownloads:_Downloads...
de.gtk.gtkDownloads:_Downloads...
-fr.gtk.gtkDownloads:_Téléchargements...
+fr.gtk.gtkDownloads:_Téléchargements…
it.gtk.gtkDownloads:_Trasferimenti...
nl.gtk.gtkDownloads:_Downloads...
+zh_CN.gtk.gtkDownloads:下载(_D) …
+
en.gtk.gtkSaveWindowSize:S_ave Window Size
de.gtk.gtkSaveWindowSize:Fenstergröße _speichern
fr.gtk.gtkSaveWindowSize:E_nregistrer la taille de la fenêtre
it.gtk.gtkSaveWindowSize:S_alva dimensione finestra
nl.gtk.gtkSaveWindowSize:Vensteromvang ops_laan
+zh_CN.gtk.gtkSaveWindowSize:ä¿å­˜çª—å£å¤§å°(_A)
+
en.gtk.gtkDeveloper:De_veloper
de.gtk.gtkDeveloper:De_veloper
fr.gtk.gtkDeveloper:Dé_veloppeur
it.gtk.gtkDeveloper:S_viluppatore
nl.gtk.gtkDeveloper:_Internet ontwikkeling
+zh_CN.gtk.gtkDeveloper:å¼€å‘者(_V)
+
en.gtk.gtkToggleDebugging:T_oggle debug rendering
de.gtk.gtkToggleDebugging:T_oggle debug rendering
fr.gtk.gtkToggleDebugging:Basculer déb_ogage de rendu
it.gtk.gtkToggleDebugging:In_verti debug del rendering
nl.gtk.gtkToggleDebugging:Debug-weergave aan/uit
+zh_CN.gtk.gtkToggleDebugging:切æ¢è°ƒè¯•æ¸²æŸ“(_O)
+
en.gtk.gtkDebugBoxTree:Debug _box tree
de.gtk.gtkDebugBoxTree:Debug _box tree
-fr.gtk.gtkDebugBoxTree:Déboguer arbre _box
+fr.gtk.gtkDebugBoxTree:Déboguer l’arbre d’em_boîtement
it.gtk.gtkDebugBoxTree:Debug _box tree
nl.gtk.gtkDebugBoxTree:_Box-boom debuggen
+zh_CN.gtk.gtkDebugBoxTree:调试边框树(_B)
+
en.gtk.gtkDebugDomTree:Debug _DOM tree
de.gtk.gtkDebugDomTree:Debug _DOM tree
-fr.gtk.gtkDebugDomTree:Déboguer arbre _DOM
+fr.gtk.gtkDebugDomTree:Déboguer l’arbre _DOM
it.gtk.gtkDebugDomTree:Debug albero _DOM
nl.gtk.gtkDebugDomTree:_DOM-boom debuggen
+zh_CN.gtk.gtkDebugDomTree:调试 _DOM 树
+en.gtk.gtkStop:Stop
en.gtk.gtkBack:_Back
de.gtk.gtkBack:_Zurück
fr.gtk.gtkBack:_Précédent
it.gtk.gtkBack:_Indietro
nl.gtk.gtkBack:_Terug
+zh_CN.gtk.gtkBack:åŽé€€(_B)
+
en.gtk.gtkForward:_Forward
de.gtk.gtkForward:_Vorwärts
fr.gtk.gtkForward:_Suivant
it.gtk.gtkForward:_Avanti
nl.gtk.gtkForward:_Vooruit
+zh_CN.gtk.gtkForward:å‰è¿›(_F)
+
en.gtk.gtkHome:_Home
de.gtk.gtkHome:_Startseite
fr.gtk.gtkHome:_Accueil
-it.gtk.gtkHome:_Home
+it.gtk.gtkHome:_Pagina iniziale
nl.gtk.gtkHome:_Beginpagina
+zh_CN.gtk.gtkHome:主页(_H)
+
en.gtk.gtkLocalHistory:_Local History…
de.gtk.gtkLocalHistory:_Lokaler Verlauf
fr.gtk.gtkLocalHistory:Historique _local
it.gtk.gtkLocalHistory:Cronologia _locale
nl.gtk.gtkLocalHistory:Vensterge_schiedenis
+zh_CN.gtk.gtkLocalHistory:本地历å²è®°å½•(_L) …
+
en.gtk.gtkGlobalHistory:_Global History…
de.gtk.gtkGlobalHistory:_Globaler Verlauf
fr.gtk.gtkGlobalHistory:Historique _global
it.gtk.gtkGlobalHistory:Cronologia _globale
nl.gtk.gtkGlobalHistory:Browser_geschiedenis
+zh_CN.gtk.gtkGlobalHistory:全局历å²è®°å½•(_G) …
+
en.gtk.gtkAddBookMarks:_Add to Bookmarks…
de.gtk.gtkAddBookMarks:_Lesezeichen hinzufügen..
-fr.gtk.gtkAddBookMarks:_Ajouter un marque-page..
-it.gtk.gtkAddBookMarks:_Aggiungi ai segnalibri...
+fr.gtk.gtkAddBookMarks:_Ajouter un marque-page…
+it.gtk.gtkAddBookMarks:Aggiungi ai _segnalibri...
nl.gtk.gtkAddBookMarks:_Aan bladwijzers toevoegen...
+zh_CN.gtk.gtkAddBookMarks:添加到书签(_A) …
+
en.gtk.gtkShowBookMarks:_Show Bookmarks…
de.gtk.gtkShowBookMarks:Le_sezeichen anzeigen..
-fr.gtk.gtkShowBookMarks:_Montrer les marques-pages...
+fr.gtk.gtkShowBookMarks:_Afficher les marque-pages…
it.gtk.gtkShowBookMarks:_Mostra segnalibri...
nl.gtk.gtkShowBookMarks:Bladwijzers _beheren...
+zh_CN.gtk.gtkShowBookMarks:显示书签(_S) …
+
en.gtk.gtkShowCookies:Show _Cookies…
de.gtk.gtkShowCookies:Zeige _Cookies…
-fr.gtk.gtkShowCookies:Afficher _cookies...
+fr.gtk.gtkShowCookies:Afficher les _cookies…
it.gtk.gtkShowCookies:Mostra _cookie...
nl.gtk.gtkShowCookies:_Cookies beheren...
+zh_CN.gtk.gtkShowCookies:显示 Cookies(_C) …
+
en.gtk.gtkOpenLocation:_Open Location…
de.gtk.gtkOpenLocation:_Ort öffnen..
-fr.gtk.gtkOpenLocation:_Ouvrir un site..
-it.gtk.gtkOpenLocation:_Apri indirizzo...
+fr.gtk.gtkOpenLocation:_Ouvrir un site…
+it.gtk.gtkOpenLocation:Apri in_dirizzo...
nl.gtk.gtkOpenLocation:Locatie _openen..
+zh_CN.gtk.gtkOpenLocation:打开ä½ç½®ä¿¡æ¯(_O) …
en.gtk.gtkNextTab:_Next tab
de.gtk.gtkNextTab:_Nächster Tab
fr.gtk.gtkNextTab:O_nglet suivant
it.gtk.gtkNextTab:Scheda _successiva
nl.gtk.gtkNextTab:Vol_gende tabblad
+zh_CN.gtk.gtkNextTab:下一个标签页(_N)
+
en.gtk.gtkPrevTab:_Previous tab
de.gtk.gtkPrevTab:_Vorheriger Tab
fr.gtk.gtkPrevTab:Onglet _précédent
it.gtk.gtkPrevTab:Scheda _precedente
nl.gtk.gtkPrevTab:Vo_rige tabblad
+zh_CN.gtk.gtkPrevTab:上一个标签页(_P)
+
en.gtk.gtkCloseTab:_Close tab
de.gtk.gtkCloseTab:Tab s_chliessen
-fr.gtk.gtkCloseTab:_Fermer l'onglet
+fr.gtk.gtkCloseTab:_Fermer l’onglet
it.gtk.gtkCloseTab:_Chiudi scheda
nl.gtk.gtkCloseTab:Tabblad _sluiten
+zh_CN.gtk.gtkCloseTab:关闭标签页(_C)
en.gtk.gtkContents:_Contents…
de.gtk.gtkContents:_Inhalt
fr.gtk.gtkContents:_Contenus
it.gtk.gtkContents:_Contenuti
nl.gtk.gtkContents:_Inhoud
+zh_CN.gtk.gtkContents:内容(_C) …
+
en.gtk.gtkGuide:User _guide…
de.gtk.gtkGuide:H_andbuch
fr.gtk.gtkGuide:_Guide utilisateur
-it.gtk.gtkGuide:_Guida in linea...
+it.gtk.gtkGuide:_Guida in linea
nl.gtk.gtkGuide:Gebruiks_aanwijzing...
+zh_CN.gtk.gtkGuide:用户指å—(_G) …
+
en.gtk.gtkUserInformation:User _information…
de.gtk.gtkUserInformation:Benutzer_information
fr.gtk.gtkUserInformation:_Information utilisateur
-it.gtk.gtkUserInformation:Informazioni _utente...
+it.gtk.gtkUserInformation:Informazioni _utente
nl.gtk.gtkUserInformation:Gebruikers_informatie...
+zh_CN.gtk.gtkUserInformation:用户信æ¯(_I) …
+
en.gtk.gtkAbout:_About…
de.gtk.gtkAbout:Ü_ber
-fr.gtk.gtkAbout:_A propos...
+fr.gtk.gtkAbout:_À propos…
it.gtk.gtkAbout:_Informazioni...
nl.gtk.gtkAbout:_Programma-informatie...
-
+zh_CN.gtk.gtkAbout:关于(_A) …
en.gtk.gtkCustomize:Customise…
de.gtk.gtkCustomize:Anpassen…
-fr.gtk.gtkCustomize:Personnaliser...
+fr.gtk.gtkCustomize:Personnaliser…
it.gtk.gtkCustomize:Personalizza...
nl.gtk.gtkCustomize:Aanpassen...
+zh_CN.gtk.gtkCustomize:自定义(_C) …
+
en.gtk.gtkOpentab:Open Link in New _Tab
de.gtk.gtkOpentab:Link in neuem _Tab öffnen
-fr.gtk.gtkOpentab:Ouvrir dans un nouvel _Onglet
+fr.gtk.gtkOpentab:Ouvrir dans un nouvel _onglet
it.gtk.gtkOpentab:Apri in nuova _scheda
nl.gtk.gtkOpentab:Koppeling openen in nieuw _tabblad
+zh_CN.gtk.gtkOpentab:在新标签页中打开链接(_T)
+
en.gtk.gtkOpenwin:Open Link in New _Window
de.gtk.gtkOpenwin:Link in neuem _Fenster öffnen
-fr.gtk.gtkOpenwin:Ouvrir dans une nouvelle _Fenêtre
+fr.gtk.gtkOpenwin:Ouvrir dans une nouvelle _fenêtre
it.gtk.gtkOpenwin:Apri in nuova _finestra
nl.gtk.gtkOpenwin:Koppeling openen in nieuw _venster
+zh_CN.gtk.gtkOpenwin:在新窗å£ä¸­æ‰“开链接(_W)
+
en.gtk.gtkSavelink:Save Lin_k
de.gtk.gtkSavelink:Lin_k speichern..
-fr.gtk.gtkSavelink:Enregistrer li_en
-it.gtk.gtkSavelink:Salva Lin_k
+fr.gtk.gtkSavelink:Enregistrer le li_en
+it.gtk.gtkSavelink:Salva lin_k
nl.gtk.gtkSavelink:_Koppeling opslaan als...
+zh_CN.gtk.gtkSavelink:ä¿å­˜é“¾æŽ¥(_K)
+
en.gtk.gtkBookmarklink:Bookmark _Link
de.gtk.gtkBookmarklink:_Link als Bookmark
-fr.gtk.gtkBookmarklink:Marquer _Lien
+fr.gtk.gtkBookmarklink:Marquer le _lien
it.gtk.gtkBookmarklink:A_ggiungi ai segnalibri
nl.gtk.gtkBookmarklink:B_ladwijzer voor de koppeling maken
+zh_CN.gtk.gtkBookmarklink:书签链接(_L)
+
en.gtk.gtkCopylink:Copy link loc_ation
de.gtk.gtkCopylink:Link_adresse kopieren
fr.gtk.gtkCopylink:_Copier le lien
it.gtk.gtkCopylink:Copia in_dirizzo link
nl.gtk.gtkCopylink:Koppelingsloc_atie kopiëren
+zh_CN.gtk.gtkCopylink:å¤åˆ¶é“¾æŽ¥ä½ç½®(_A)
+# GTK theme handling
-en.gtk.gtkToolBarTitle:Toolbar custom button store
-de.gtk.gtkToolBarTitle:Benutzerdefinierter Ort für Toolbar-Icons
-fr.gtk.gtkToolBarTitle:Personaliser la barre d'outils
-it.gtk.gtkToolBarTitle:Pulsanti della barra strumenti
-nl.gtk.gtkToolBarTitle:Werkbalk aanpassen
en.gtk.gtkAddThemeTitle:Select folder containing theme images
de.gtk.gtkAddThemeTitle:Ordner mit Themenbildern auswählen
-fr.gtk.gtkAddThemeTitle:Sélectionner le dossier contenant des images de thèmes
+fr.gtk.gtkAddThemeTitle:Sélectionner le dossier contenant des images de thème
it.gtk.gtkAddThemeTitle:Seleziona una cartella contenente le immagini del tema in questione
nl.gtk.gtkAddThemeTitle:Map met thema-afbeeldingen selecteren
+zh_CN.gtk.gtkAddThemeTitle:选择包å«ä¸»é¢˜å›¾åƒçš„文件夹
en.gtk.gtkThemeFolderInstructions:To Install a theme, create a directory full of appropriately-named images as a subdirectory of gtk/res/themes/
de.gtk.gtkThemeFolderInstructions:Erstellen sie ein Verzeichnis mit korrekt benannten Bildern als Unterverzeichnis von gtk/res/themes um ein Thema zu installieren
-fr.gtk.gtkThemeFolderInstructions:Pour installer un thème, créer un dossier d'images avec un nom approprié comme sous-dossier de gtk/res/themes/
+fr.gtk.gtkThemeFolderInstructions:Pour installer un thème, créer un dossier d’images avec un nom approprié comme sous-dossier de gtk/res/themes/
it.gtk.gtkThemeFolderInstructions:Per installare un nuovo tema crea una directory con delle immagini appropriate ed inseriscile come sotto-directory di gtk/res/themes/
nl.gtk.gtkThemeFolderInstructions:Maak in de map gtk/res/themes/ een submap aan die afbeeldingen met de juiste namen bevatten om deze als thema te installeren.
+zh_CN.gtk.gtkThemeFolderInstructions:如果è¦å®‰è£…主题,请创建一个目录,作为 gtk/res/themes/ çš„å­ç›®å½•ï¼Œå…¶ä¸­åŒ…å«æ­£ç¡®å‘½å的图åƒã€‚
+
en.gtk.gtkThemeFolderSub:Select a subdirectory of the themes folder
de.gtk.gtkThemeFolderSub:Unterverzeichnis mit Themenbildern wählen
fr.gtk.gtkThemeFolderSub:Sélectionner un sous-dossier de thème
it.gtk.gtkThemeFolderSub:Seleziona una sotto-directory della cartella temi
nl.gtk.gtkThemeFolderSub:Submap met thema-afbeeldingen selecteren
+zh_CN.gtk.gtkThemeFolderSub:选择主题文件夹的å­ç›®å½•
+
en.gtk.gtkThemeDup:Theme is already included
de.gtk.gtkThemeDup:Das Thema ist bereits hinzugefügt worden
fr.gtk.gtkThemeDup:Le thème est déjà inclus
it.gtk.gtkThemeDup:Il tema è già incluso
nl.gtk.gtkThemeDup:Het thema is al toegevoegd
+zh_CN.gtk.gtkThemeDup:已应用主题
+
en.gtk.gtkThemeAdd:Theme added successfully
de.gtk.gtkThemeAdd:Thema erfolgreich hinzugefügt
-fr.gtk.gtkThemeAdd:Le thème a été ajouté avec succes
+fr.gtk.gtkThemeAdd:Le thème a été ajouté avec succès
it.gtk.gtkThemeAdd:Il tema è stato aggiunto con successo
nl.gtk.gtkThemeAdd:Thema is succesvol toegevoegd
+zh_CN.gtk.gtkThemeAdd:å·²æˆåŠŸæ·»åŠ ä¸»é¢˜
+
+# GTK toolbar customisation
+
+en.gtk.gtkCustomizeToolbarTitle:Customise Toolbar
+fr.gtk.gtkCustomizeToolbarTitle:Personnaliser la barre d’outils
+it.gtk.gtkCustomizeToolbarTitle:Personalizza barra strumenti
+zh_CN.gtk.gtkCustomizeToolbarTitle:自定义工具æ 
+
+en.gtk.gtkCustomizeToolbarInstructions:Drag toolbar items into and out of the toolbar.
+fr.gtk.gtkCustomizeToolbarInstructions:Glisser-déposer de nouveaux éléments sur la barre.
+it.gtk.gtkCustomizeToolbarInstructions:Trascina elementi della barra strumenti dentro e fuori la barra.
+zh_CN.gtk.gtkCustomizeToolbarInstructions:拖动工具æ é¡¹ã€‚
+
+# GTK find in page
+
+en.gtk.gtkFindPlaceholder:Find in page
+fr.gtk.gtkFindPlaceholder:Rechercher dans la page
+it.gtk.gtkFindPlaceholder:Trova nella pagina
+zh_CN.gtk.gtkFindPlaceholder:在页é¢ä¸­æŸ¥æ‰¾
+
+en.gtk.gtkFindBack:Find Previous Occurrence
+fr.gtk.gtkFindBack:Trouver l’occurence précédente
+it.gtk.gtkFindBack:Trova occorrenza _precedente
+zh_CN.gtk.gtkFindBack:查找上一个匹é…项
+
+en.gtk.gtkFindForward:Find _Next Occurrence
+fr.gtk.gtkFindForward:Trouver l’occurence _suivante
+it.gtk.gtkFindForward:Trova occorrenza _successiva
+zh_CN.gtk.gtkFindForward:查找下一个匹é…项(_N)
+
+en.gtk.gtkFindHighlightAll:Highlight All
+fr.gtk.gtkFindHighlightAll:Tout surligner
+it.gtk.gtkFindHighlightAll:Evidenzia tutto
+zh_CN.gtk.gtkFindHighlightAll:çªå‡ºæ˜¾ç¤ºæ‰€æœ‰æŸ¥æ‰¾å†…容
+
+en.gtk.gtkFindMatchCase:Match Case
+fr.gtk.gtkFindMatchCase:Respecter la casse
+it.gtk.gtkFindMatchCase:Marca corrispondenze
+zh_CN.gtk.gtkFindMatchCase:匹é…查找内容
+
+en.gtk.gtkFindClose:Close Find Bar
+fr.gtk.gtkFindClose:Fermer la barre de recherche
+it.gtk.gtkFindClose:Chiudi finestra di ricerca
+zh_CN.gtk.gtkFindClose:关闭æœç´¢æ 
# GTK preferences dialog
en.gtk.preferencesTitle:Netsurf Preferences
de.gtk.preferencesTitle:Netsurf Einstellungen
fr.gtk.preferencesTitle:Préférences de Netsurf
+it.gtk.preferencesTitle:Preferenze di Netsurf
nl.gtk.preferencesTitle:Netsurf-voorkeuren
+zh_CN.gtk.preferencesTitle:NetSurf 首选项
# Main tab
en.gtk.preferencesMainTabtitle:Main
de.gtk.preferencesMainTabtitle:Allgemein
-fr.gtk.preferencesMainTabtitle:Accueil/Principal
+fr.gtk.preferencesMainTabtitle:Général
+it.gtk.preferencesMainTabtitle:Principale
nl.gtk.preferencesMainTabtitle:Algemeen
+zh_CN.gtk.preferencesMainTabtitle:主èœå•
+
en.gtk.preferencesStartup:<b>Startup</b>
de.gtk.preferencesStartup:<b>Starten</b>
fr.gtk.preferencesStartup:<b>Démarrage</b>
+it.gtk.preferencesStartup:<b>Avvio</b>
nl.gtk.preferencesStartup:<b>Opstarten</b>
+zh_CN.gtk.preferencesStartup:<b>å¯åŠ¨</b>
+
en.gtk.preferencesStartupPage:Page:
de.gtk.preferencesStartupPage:Seite:
-fr.gtk.preferencesStartupPage:Page:
+fr.gtk.preferencesStartupPage:Page :
+it.gtk.preferencesStartupPage:Pagina:
nl.gtk.preferencesStartupPage:Pagina:
+zh_CN.gtk.preferencesStartupPage:页é¢ï¼š
+
en.gtk.preferencesStartupPageTooltip:The default startup page
de.gtk.preferencesStartupPageTooltip:Die Standard Startseite
fr.gtk.preferencesStartupPageTooltip:La page de démarrage par défaut
+it.gtk.preferencesStartupPageTooltip:Pagina di avvio predefinita
nl.gtk.preferencesStartupPageTooltip:De standaard startpagina
+zh_CN.gtk.preferencesStartupPageTooltip:默认å¯åŠ¨é¡µé¢
+
en.gtk.preferencesStartupPageDefault:Use Default Page
de.gtk.preferencesStartupPageDefault:Standard Seite nutzen
fr.gtk.preferencesStartupPageDefault:Utiliser la page par défaut
+it.gtk.preferencesStartupPageDefault:Usa pagina predefinita
nl.gtk.preferencesStartupPageDefault:Standaard herstellen
+zh_CN.gtk.preferencesStartupPageDefault:使用默认页é¢
+
en.gtk.preferencesStartupPageCurrent:Use Current Page
de.gtk.preferencesStartupPageCurrent:aktuelle Seite nehmen
fr.gtk.preferencesStartupPageCurrent:Utiliser la page en cours
+it.gtk.preferencesStartupPageCurrent:Usa pagina corrente
nl.gtk.preferencesStartupPageCurrent:Huidige pagina gebruiken
+zh_CN.gtk.preferencesStartupPageCurrent:使用当å‰é¡µé¢
+
en.gtk.preferencesSearch:<b>Search</b>
de.gtk.preferencesSearch:<b>Suchen</b>
fr.gtk.preferencesSearch:<b>Recherche</b>
+it.gtk.preferencesSearch:<b>Cerca</b>
nl.gtk.preferencesSearch:<b>Zoeken</b>
+zh_CN.gtk.preferencesSearch:<b>查找</b>
+
en.gtk.preferencesSearchURLBar:Search from URL bar
de.gtk.preferencesSearchURLBar:Adressleiste zum Suchen
-fr.gtk.preferencesSearchURLBar:Recherche depuis la barre d'URL
+fr.gtk.preferencesSearchURLBar:Recherche depuis la barre d’URL
+it.gtk.preferencesSearchURLBar:Cerca da barra URL
nl.gtk.preferencesSearchURLBar:Standaardzoekmachine
+zh_CN.gtk.preferencesSearchURLBar:从地å€æ æœç´¢
+
en.gtk.preferencesSearchProvider:Provider:
de.gtk.preferencesSearchProvider:Anbieter:
-fr.gtk.preferencesSearchProvider:Fournisseur :
+fr.gtk.preferencesSearchProvider:Fournisseur :
+it.gtk.preferencesSearchProvider:Provider:
nl.gtk.preferencesSearchProvider:Zoeken met:
+zh_CN.gtk.preferencesSearchProvider:æ供者:
+
en.gtk.preferencesSearchProviderTooltip:The default web search provider
de.gtk.preferencesSearchProviderTooltip:Voreingestellter Suchanbieter
-fr.gtk.preferencesSearchProviderTooltip:Le fournisseur de recherche sur le web par défaut
+fr.gtk.preferencesSearchProviderTooltip:Le fournisseur de recherche Web par défaut
+it.gtk.preferencesSearchProviderTooltip:Provider di ricerca web predefinito
nl.gtk.preferencesSearchProviderTooltip:Kies de standaardzoekmachine. NetSurf gebruikt deze in de zoekbalk.
+zh_CN.gtk.preferencesSearchProviderTooltip:默认网络æœç´¢æ供者
+
en.gtk.preferencesDownloads:<b>Downloads</b>
de.gtk.preferencesDownloads:<b>Downloads</b>
fr.gtk.preferencesDownloads:<b>Téléchargements</b>
+it.gtk.preferencesDownloads:<b>Download</b>
nl.gtk.preferencesDownloads:<b>Downloads</b>
+zh_CN.gtk.preferencesDownloads:<b>下载项</b>
+
en.gtk.preferencesDownloadsRemove:Remove download from list when complete
de.gtk.preferencesDownloadsRemove:abgeschlossene Downloads auslisten
fr.gtk.preferencesDownloadsRemove:Retirer le téléchargement de la liste une fois terminé
+it.gtk.preferencesDownloadsRemove:Rimuovi download dalla lista al completamento
nl.gtk.preferencesDownloadsRemove:Downloadvermeldingen verwijderen
+zh_CN.gtk.preferencesDownloadsRemove:完æˆåŽä»Žåˆ—表中删除下载任务
+
en.gtk.preferencesDownloadsConfirm:Confirm before overwriting files
de.gtk.preferencesDownloadsConfirm:Überschreiben bestätigen
-fr.gtk.preferencesDownloadsConfirm:Confirmer avant d'écraser des fichiers
+fr.gtk.preferencesDownloadsConfirm:Confirmer avant d’écraser des fichiers
+it.gtk.preferencesDownloadsConfirm:Conferma prima di sovrascrivere
nl.gtk.preferencesDownloadsConfirm:Overschrijven van bestand bevestigen
+zh_CN.gtk.preferencesDownloadsConfirm:覆盖文件之å‰è¿›è¡Œç¡®è®¤
+
en.gtk.preferencesDownloadsLocation:Location:
de.gtk.preferencesDownloadsLocation:Zielort:
-fr.gtk.preferencesDownloadsLocation:Emplacement :
+fr.gtk.preferencesDownloadsLocation:Emplacement :
+it.gtk.preferencesDownloadsLocation:Percorso:
nl.gtk.preferencesDownloadsLocation:Bestanden opslaan in:
+zh_CN.gtk.preferencesDownloadsLocation:ä½ç½®ï¼š
+
en.gtk.preferencesDownloadsLocationTooltip:The default location downloaded files are put
de.gtk.preferencesDownloadsLocationTooltip:Speicherort für Downloads
-fr.gtk.preferencesDownloadsLocationTooltip:L'emplacement par défaut des fichiers téléchargés sont mis
+fr.gtk.preferencesDownloadsLocationTooltip:L’emplacement par défaut où déplacer les fichiers téléchargés
+it.gtk.preferencesDownloadsLocationTooltip:Percorso predefinito dove scaricare i file
nl.gtk.preferencesDownloadsLocationTooltip:De standaardplaats waar gedownloade bestanden worden opgeslagen
+zh_CN.gtk.preferencesDownloadsLocationTooltip:默认ä½ç½®æ”¾ç½®ä¸‹è½½çš„文件
# Appearance tab
en.gtk.preferencesAppearanceTabtitle:Appearance
de.gtk.preferencesAppearanceTabtitle:Aussehen
fr.gtk.preferencesAppearanceTabtitle:Apparence
+it.gtk.preferencesAppearanceTabtitle:Aspetto
nl.gtk.preferencesAppearanceTabtitle:Vormgeving
+zh_CN.gtk.preferencesAppearanceTabtitle:外观
+
en.gtk.preferencesThemes:<b>Themes</b>
de.gtk.preferencesThemes:<b>Themen</b>
fr.gtk.preferencesThemes:<b>Thèmes</b>
+it.gtk.preferencesThemes:<b>Temi</b>
nl.gtk.preferencesThemes:<b>Thema's</b>
+zh_CN.gtk.preferencesThemes:<b>主题</b>
+
en.gtk.preferencesThemesAdd:Add Theme...
de.gtk.preferencesThemesAdd:Thema hinzu...
-fr.gtk.preferencesThemesAdd:Ajouter thème...
+fr.gtk.preferencesThemesAdd:Ajouter un thème…
+it.gtk.preferencesThemesAdd:Aggiungi tema...
nl.gtk.preferencesThemesAdd:Thema toevoegen...
+zh_CN.gtk.preferencesThemesAdd:添加主题…
+
en.gtk.preferencesTabs:<b>Tabs</b>
de.gtk.preferencesTabs:<b>Tabs</b>
fr.gtk.preferencesTabs:<b>Onglets</b>
+it.gtk.preferencesTabs:<b>Schede</b>
nl.gtk.preferencesTabs:<b>Tabbladen</b>
+zh_CN.gtk.preferencesTabs:<b>标签页</b>
+
en.gtk.preferencesTabsAlways:Always show tab bar
de.gtk.preferencesTabsAlways:Tableiste immer anzeigen
-fr.gtk.preferencesTabsAlways:Toujours afficher la barre d'onglet
+fr.gtk.preferencesTabsAlways:Toujours afficher la barre d’onglet
+it.gtk.preferencesTabsAlways:Mostra sempre la barra delle schede
nl.gtk.preferencesTabsAlways:De tabbladenwerkbalk verbergen wanneer slechts één tabblad is geopend
+zh_CN.gtk.preferencesTabsAlways:总是显示标签页æ 
+
en.gtk.preferencesTabsSwitch:Switch to newly opened tabs immediately
de.gtk.preferencesTabsSwitch:neue Tabs sofort in Vordergrund
-fr.gtk.preferencesTabsSwitch:Passer à l'onglet nouvellement ouvert immédiatement
+fr.gtk.preferencesTabsSwitch:À l’ouverture d’un nouvel onglet, basculer immédiatement vers celui-ci
+it.gtk.preferencesTabsSwitch:Passa immediatamente alle nuove schede aperte
nl.gtk.preferencesTabsSwitch:Naar vanuit koppeling geopende nieuwe tabbladen schakelen
+zh_CN.gtk.preferencesTabsSwitch:ç«‹å³åˆ‡æ¢åˆ°æ–°æ‰“开的标签页
+
en.gtk.preferencesTabsNewly:Newly opened tabs are blank
de.gtk.preferencesTabsNewly:neue Tabs als leere Seite
-fr.gtk.preferencesTabsNewly:Onglet récemment ouvert est vièrge
+fr.gtk.preferencesTabsNewly:Utiliser une page vide pour les nouveaux onglets
+it.gtk.preferencesTabsNewly:Le nuove schede aperte sono vuote
nl.gtk.preferencesTabsNewly:Geopende nieuwe tabbladen zijn leeg inplaats van de startpagina
+zh_CN.gtk.preferencesTabsNewly:新打开的标签页为空白
+
en.gtk.preferencesTabsPosition:Position:
de.gtk.preferencesTabsPosition:Position:
-fr.gtk.preferencesTabsPosition:Position :
+fr.gtk.preferencesTabsPosition:Position :
+it.gtk.preferencesTabsPosition:Posizione:
nl.gtk.preferencesTabsPosition:Positie in venster:
+zh_CN.gtk.preferencesTabsPosition:ä½ç½®ï¼š
+
en.gtk.preferencesTools:<b>Tools</b>
de.gtk.preferencesTools:<b>Tools</b>
fr.gtk.preferencesTools:<b>Outils</b>
+it.gtk.preferencesTools:<b>Strumenti</b>
nl.gtk.preferencesTools:<b>Ontwikkelaarshulpmiddelen</b>
+zh_CN.gtk.preferencesTools:<b>工具</b>
+
en.gtk.preferencesDeveloperView:Open developer views in a
de.gtk.preferencesDeveloperView:Entwickleransicht öffnen in
-fr.gtk.preferencesDeveloperView:Vues de développement s'ouvrent dans
+fr.gtk.preferencesDeveloperView:La vue de développement s’ouvre dans
+it.gtk.preferencesDeveloperView:Apri visualizzazione sviluppatori in
nl.gtk.preferencesDeveloperView:Informatie voor ontwikkelaars openen in
+zh_CN.gtk.preferencesDeveloperView:打开开å‘人员视图
+
en.gtk.preferencesDeveloperViewWindow:Window
de.gtk.preferencesDeveloperViewWindow:Fenster
-fr.gtk.preferencesDeveloperViewWindow:un fenêtre
+fr.gtk.preferencesDeveloperViewWindow:une nouvelle fenêtre
+it.gtk.preferencesDeveloperViewWindow:Finestra
nl.gtk.preferencesDeveloperViewWindow:Venster
+zh_CN.gtk.preferencesDeveloperViewWindow:窗å£
+
en.gtk.preferencesDeveloperViewTab:Tab
de.gtk.preferencesDeveloperViewTab:Tab
-fr.gtk.preferencesDeveloperViewTab:un onglet
+fr.gtk.preferencesDeveloperViewTab:un nouvel onglet
+it.gtk.preferencesDeveloperViewTab:Scheda
nl.gtk.preferencesDeveloperViewTab:Tabblad
+zh_CN.gtk.preferencesDeveloperViewTab:标签页
+
en.gtk.preferencesDeveloperViewEditor:Editor
de.gtk.preferencesDeveloperViewEditor:Editor
-fr.gtk.preferencesDeveloperViewEditor:Éditeur
+fr.gtk.preferencesDeveloperViewEditor:votre éditeur préféré
+it.gtk.preferencesDeveloperViewEditor:Editor di testo
nl.gtk.preferencesDeveloperViewEditor:Tekst-editor
+zh_CN.gtk.preferencesDeveloperViewEditor:编辑器
+
en.gtk.preferencesURLbar:<b>URLbar</b>
de.gtk.preferencesURLbar:<b>Adressleiste</b>
-fr.gtk.preferencesURLbar:<b>Barre URL</b>
+fr.gtk.preferencesURLbar:<b>Barre d’URL</b>
+it.gtk.preferencesURLbar:<b>Barra indirizzi</b>
nl.gtk.preferencesURLbar:<b>Locatiebalk</b>
+zh_CN.gtk.preferencesURLbar:<b>地å€æ </b>
+
en.gtk.preferencesURLbarDisplay:Display recently visited URLs as you type
de.gtk.preferencesURLbarDisplay:benutzte URLs während Eingabe zeigen
-fr.gtk.preferencesURLbarDisplay:Afficher les URL visités récemment lorsque vous tapez
+fr.gtk.preferencesURLbarDisplay:Afficher les URL récemment visitées lors de la frappe
+it.gtk.preferencesURLbarDisplay:Mostra gli URL visitati di recente durante la digitazione
nl.gtk.preferencesURLbarDisplay:Automatisch aanvullen vanuit de browsergeschiedenis tijdens het typen
+zh_CN.gtk.preferencesURLbarDisplay:键入时显示最近访问的地å€
+
en.gtk.preferencesToolbar:<b>Toolbar</b>
de.gtk.preferencesToolbar:<b>Knopfleiste</b>
-fr.gtk.preferencesToolbar:<b>Barre d'outils</b>
+fr.gtk.preferencesToolbar:<b>Barre d’outils</b>
+it.gtk.preferencesToolbar:<b>Barra strumenti</b>
nl.gtk.preferencesToolbar:<b>Werkbalk</b>
+zh_CN.gtk.preferencesToolbar:<b>工具æ </b>
+
en.gtk.preferencesToolbarButtons:Buttons:
de.gtk.preferencesToolbarButtons:Gestalt:
-fr.gtk.preferencesToolbarButtons:Boutons :
+fr.gtk.preferencesToolbarButtons:Boutons :
+it.gtk.preferencesToolbarButtons:Pulsanti:
nl.gtk.preferencesToolbarButtons:Knoppen:
+zh_CN.gtk.preferencesToolbarButtons:按钮:
+
# Theme list
en.gtk.preferencesThemeTypeDefault:Default
de.gtk.preferencesThemeTypeDefault:Standard
fr.gtk.preferencesThemeTypeDefault:Défaut
+it.gtk.preferencesThemeTypeDefault:Predefinito
nl.gtk.preferencesThemeTypeDefault:Standaard
+zh_CN.gtk.preferencesThemeTypeDefault:默认
+
# Tab position list
en.gtk.preferencesTabLocTop:Top
de.gtk.preferencesTabLocTop:Oben
-fr.gtk.preferencesTabLocTop:Haut
+fr.gtk.preferencesTabLocTop:en haut
+it.gtk.preferencesTabLocTop:In alto
nl.gtk.preferencesTabLocTop:Bovenaan
+zh_CN.gtk.preferencesTabLocTop:顶部
+
en.gtk.preferencesTabLocLeft:Left
de.gtk.preferencesTabLocLeft:Links
-fr.gtk.preferencesTabLocLeft:Gauche
+fr.gtk.preferencesTabLocLeft:à gauche
+it.gtk.preferencesTabLocLeft:A sinistra
nl.gtk.preferencesTabLocLeft:Links
+zh_CN.gtk.preferencesTabLocLeft:左侧
+
en.gtk.preferencesTabLocBottom:Bottom
de.gtk.preferencesTabLocBottom:Unten
-fr.gtk.preferencesTabLocBottom:Bas
+fr.gtk.preferencesTabLocBottom:en bas
+it.gtk.preferencesTabLocBottom:In basso
nl.gtk.preferencesTabLocBottom:Onderaan
+zh_CN.gtk.preferencesTabLocBottom:底部
+
en.gtk.preferencesTabLocRight:Right
de.gtk.preferencesTabLocRight:Rechts
-fr.gtk.preferencesTabLocRight:Droite
+fr.gtk.preferencesTabLocRight:à droite
+it.gtk.preferencesTabLocRight:A destra
nl.gtk.preferencesTabLocRight:Rechts
+zh_CN.gtk.preferencesTabLocRight:å³ä¾§
+
# button list
en.gtk.preferencesButtonTypeSmall:Small Icons
de.gtk.preferencesButtonTypeSmall:Kleine Icons
-fr.gtk.preferencesButtonTypeSmall:Petites icônes
+fr.gtk.preferencesButtonTypeSmall:petites icônes
+it.gtk.preferencesButtonTypeSmall:Pulsanti piccoli
nl.gtk.preferencesButtonTypeSmall:Kleine pictogrammen
+zh_CN.gtk.preferencesButtonTypeSmall:å°å›¾æ ‡
+
en.gtk.preferencesButtonTypeLarge:Large Icons
de.gtk.preferencesButtonTypeLarge:Große Icons
-fr.gtk.preferencesButtonTypeLarge:Grandes icônes
+fr.gtk.preferencesButtonTypeLarge:grandes icônes
+it.gtk.preferencesButtonTypeLarge:Pulsanti grandi
nl.gtk.preferencesButtonTypeLarge:Grote pictogrammen
+zh_CN.gtk.preferencesButtonTypeLarge:大图标
+
en.gtk.preferencesButtonTypeLargeText:Large Icons and Text
de.gtk.preferencesButtonTypeLargeText:Große Icons mit Text
-fr.gtk.preferencesButtonTypeLargeText:Grandes icônes et texte
+fr.gtk.preferencesButtonTypeLargeText:grandes icônes et texte
+it.gtk.preferencesButtonTypeLargeText:Pulsanti grandi e testo
nl.gtk.preferencesButtonTypeLargeText:Grote pictogrammen en tekst
+zh_CN.gtk.preferencesButtonTypeLargeText:大图标和文本
+
en.gtk.preferencesButtonTypeText:Text only
de.gtk.preferencesButtonTypeText:Text ohne Icons
-fr.gtk.preferencesButtonTypeText:Texte uniquement
+fr.gtk.preferencesButtonTypeText:texte uniquement
+it.gtk.preferencesButtonTypeText:Solo testo
nl.gtk.preferencesButtonTypeText:Alleen tekst
+zh_CN.gtk.preferencesButtonTypeText:仅文本
# content tab
en.gtk.preferencesContentTabtitle:Content
de.gtk.preferencesContentTabtitle:Inhalte
fr.gtk.preferencesContentTabtitle:Contenu
+it.gtk.preferencesContentTabtitle:Contenuto
nl.gtk.preferencesContentTabtitle:Inhoud
+zh_CN.gtk.preferencesContentTabtitle:内容
+
en.gtk.preferencesControl:<b>Control</b>
de.gtk.preferencesControl:<b>Steuerung</b>
fr.gtk.preferencesControl:<b>Contrôle</b>
+it.gtk.preferencesControl:<b>Controlli</b>
nl.gtk.preferencesControl:<b>Opties</b>
+zh_CN.gtk.preferencesControl:<b>控件</b>
+
en.gtk.preferencesControlPrevent:Prevent pop-up windows
de.gtk.preferencesControlPrevent:Pop-Up Fenster blocken
-fr.gtk.preferencesControlPrevent:Empêcher fenêtres pop-up
+fr.gtk.preferencesControlPrevent:Bloquer les fenêtres popup
+it.gtk.preferencesControlPrevent:Blocca finestre pop-up (AdBlock)
nl.gtk.preferencesControlPrevent:Pop-upvensters blokkeren
+zh_CN.gtk.preferencesControlPrevent:阻止弹窗
+
en.gtk.preferencesControlHide:Hide Adverts
de.gtk.preferencesControlHide:Werbung unterdrücken
fr.gtk.preferencesControlHide:Cacher les publicités
+it.gtk.preferencesControlHide:Nascondi pubblicità
nl.gtk.preferencesControlHide:Advertenties verbergen
+zh_CN.gtk.preferencesControlHide:éšè—广告
+
en.gtk.preferencesControlEnable:Enable JavaScript
de.gtk.preferencesControlEnable:JavaScript einschalten
-fr.gtk.preferencesControlEnable:Activer JavaScript
+fr.gtk.preferencesControlEnable:Activer le JavaScript
+it.gtk.preferencesControlEnable:Attiva JavaScript
nl.gtk.preferencesControlEnable:JavaScript inschakelen
+zh_CN.gtk.preferencesControlEnable:å¯ç”¨ JavaScript
+
en.gtk.preferencesControlDisable:Disable plug-ins
de.gtk.preferencesControlDisable:Plug-Ins abschalten
-fr.gtk.preferencesControlDisable:Désactiver modules externes
+fr.gtk.preferencesControlDisable:Désactiver les modules externes
+it.gtk.preferencesControlDisable:Disattiva Plugins
nl.gtk.preferencesControlDisable:Plug-ins uitschakelen
+zh_CN.gtk.preferencesControlDisable:ç¦ç”¨æ’件
+
en.gtk.preferencesControlHigh:High quality image scaling
de.gtk.preferencesControlHigh:Bildskalierung hoher Qualität
-fr.gtk.preferencesControlHigh:Haute qualité d'image redimensionnée
+fr.gtk.preferencesControlHigh:Haute qualité d’image
+it.gtk.preferencesControlHigh:Scala immagini in alta qualità
nl.gtk.preferencesControlHigh:Schalen op hoge beeldkwaliteit
+zh_CN.gtk.preferencesControlHigh:高质é‡å›¾åƒç¼©æ”¾
+
en.gtk.preferencesControlLoad:Load and display
de.gtk.preferencesControlLoad:laden und anzeigen
fr.gtk.preferencesControlLoad:Charger et visualiser
+it.gtk.preferencesControlLoad:Carica e visualizza
nl.gtk.preferencesControlLoad:Laad en toon
+zh_CN.gtk.preferencesControlLoad:加载并显示
+
en.gtk.preferencesAnimation:<b>Animation</b>
de.gtk.preferencesAnimation:<b>Animation</b>
fr.gtk.preferencesAnimation:<b>Animation</b>
+it.gtk.preferencesAnimation:<b>Animazione</b>
nl.gtk.preferencesAnimation:<b>Animaties</b>
+zh_CN.gtk.preferencesAnimation:<b>动画</b>
+
en.gtk.preferencesAnimationEnable:Enable
de.gtk.preferencesAnimationEnable:zulassen
fr.gtk.preferencesAnimationEnable:Activer
+it.gtk.preferencesAnimationEnable:Attiva
nl.gtk.preferencesAnimationEnable:Ingeschakeld
+zh_CN.gtk.preferencesAnimationEnable:å¯ç”¨
+
en.gtk.preferencesAnimationMinimum:Minimum time between frames:
de.gtk.preferencesAnimationMinimum:minimale Zeit zwischen Frames:
-fr.gtk.preferencesAnimationMinimum:Temps minimal entre cadres/frames/images/photo :
+fr.gtk.preferencesAnimationMinimum:Temps minimal entre chaque image :
+it.gtk.preferencesAnimationMinimum:Limita velocità fotogrammi al secondo:
nl.gtk.preferencesAnimationMinimum:Minimum tijd tussen opeenvolgende animatiebeelden:
+zh_CN.gtk.preferencesAnimationMinimum:最å°å¸§é—´éš”时间:
+
en.gtk.preferencesAnimationMinimumTooltip:Do not update animations any more often than this.
de.gtk.preferencesAnimationMinimumTooltip:Animation nicht öfter als so aktualisieren
fr.gtk.preferencesAnimationMinimumTooltip:Ne pas mettre à jour les animations plus souvent que cela.
+it.gtk.preferencesAnimationMinimumTooltip:Non aggiornare le animazioni più di cosi.
nl.gtk.preferencesAnimationMinimumTooltip:Animaties niet vaker actualiseren dan dit.
+zh_CN.gtk.preferencesAnimationMinimumTooltip:更新动画的频率ä¸è¦è¶…过此次数。
+
en.gtk.preferencesFonts:<b>Fonts</b>
de.gtk.preferencesFonts:<b>Fonts</b>
-fr.gtk.preferencesFonts:<b>Fontes/Polices</b>
+fr.gtk.preferencesFonts:<b>Polices de caractères</b>
+it.gtk.preferencesFonts:<b>Font</b>
nl.gtk.preferencesFonts:<b>Lettertypen</b>
+zh_CN.gtk.preferencesFonts:<b>字体</b>
+
en.gtk.preferencesFontsDefault:Default
de.gtk.preferencesFontsDefault:Standard
fr.gtk.preferencesFontsDefault:Défaut
+it.gtk.preferencesFontsDefault:Predefinito
nl.gtk.preferencesFontsDefault:Standaard
+zh_CN.gtk.preferencesFontsDefault:默认
+
en.gtk.preferencesFontsSize:Size
de.gtk.preferencesFontsSize:Größe
fr.gtk.preferencesFontsSize:Taille
+it.gtk.preferencesFontsSize:Dimensione
nl.gtk.preferencesFontsSize:Grootte
+zh_CN.gtk.preferencesFontsSize:字体大å°
+
en.gtk.preferencesFontsSizeTooltip:The base-line font size to use.
de.gtk.preferencesFontsSizeTooltip:Die Standardgröße für Basisschriften.
-fr.gtk.preferencesFontsSizeTooltip:La taille de la fonte/police de base à utiliser.
+fr.gtk.preferencesFontsSizeTooltip:La taille de référence à utiliser pour les polices.
+it.gtk.preferencesFontsSizeTooltip:Dimensione base del carattere di linea da utilizzare.
nl.gtk.preferencesFontsSizeTooltip:Het standaardlettertype te gebruiken voor webpagina's.
+zh_CN.gtk.preferencesFontsSizeTooltip:è¦ä½¿ç”¨çš„基准字体大å°ã€‚
+
en.gtk.preferencesFontsPreview:_Preview
de.gtk.preferencesFontsPreview:Vorschau
fr.gtk.preferencesFontsPreview:A_perçu
+it.gtk.preferencesFontsPreview:_Anteprima
nl.gtk.preferencesFontsPreview:_Voorbeeld
+zh_CN.gtk.preferencesFontsPreview:预览(_P)
+
en.gtk.preferencesLanguage:<b>Language</b>
de.gtk.preferencesLanguage:<b>Sprache</b>
fr.gtk.preferencesLanguage:<b>Langue</b>
+it.gtk.preferencesLanguage:<b>Lingua</b>
nl.gtk.preferencesLanguage:<b>Talen</b>
+zh_CN.gtk.preferencesLanguage:<b>语言</b>
+
en.gtk.preferencesLanguagePreferred:Preferred language:
de.gtk.preferencesLanguagePreferred:bevorzugte Sprache:
-fr.gtk.preferencesLanguagePreferred:Langue préférée :
+fr.gtk.preferencesLanguagePreferred:Langue préférée :
+it.gtk.preferencesLanguagePreferred:Lingua preferita:
nl.gtk.preferencesLanguagePreferred:Voorkeurtaal:
+zh_CN.gtk.preferencesLanguagePreferred:首选语言:
+
en.gtk.preferencesLanguagePreferredTooltip:The preferred language for web pages
de.gtk.preferencesLanguagePreferredTooltip:Die gewünschte Sprache für Webseiten
fr.gtk.preferencesLanguagePreferredTooltip:La langue préférée pour les pages Web
+it.gtk.preferencesLanguagePreferredTooltip:Lingua preferita delle pagine web
nl.gtk.preferencesLanguagePreferredTooltip:De voorkeurtaal voor webpagina's
+zh_CN.gtk.preferencesLanguagePreferredTooltip:网页的首选语言
+
# Image loading list
en.gtk.preferencesImageLoadBoth:foreground and background images
de.gtk.preferencesImageLoadBoth:Vorder- und Hintergrundbilder
-fr.gtk.preferencesImageLoadBoth:Images d'avant-plan et d'arrière-plan
+fr.gtk.preferencesImageLoadBoth:images de premier plan et d’arrière plan
+it.gtk.preferencesImageLoadBoth:Immagini in primo piano e di sfondo
nl.gtk.preferencesImageLoadBoth:voorgrond- en achtergrondafbeeldingen
+zh_CN.gtk.preferencesImageLoadBoth:å‰æ™¯å’ŒèƒŒæ™¯å›¾åƒ
+
en.gtk.preferencesImageLoadFore:foreground images
de.gtk.preferencesImageLoadFore:Vordergrundbilder
-fr.gtk.preferencesImageLoadFore:Images d'avant-plan
+fr.gtk.preferencesImageLoadFore:images de premier plan
+it.gtk.preferencesImageLoadFore:Immagini in primo piano
nl.gtk.preferencesImageLoadFore:voorgrondafbeeldingen
+zh_CN.gtk.preferencesImageLoadFore:å‰æ™¯å›¾åƒ
+
en.gtk.preferencesImageLoadBack:background images
de.gtk.preferencesImageLoadBack:Hintergrundbilder
-fr.gtk.preferencesImageLoadBack:Images d'arrière-plan
+fr.gtk.preferencesImageLoadBack:images d’arrière plan
+it.gtk.preferencesImageLoadBack:Immagini di sfondo
nl.gtk.preferencesImageLoadBack:achtergrondafbeeldingen
+zh_CN.gtk.preferencesImageLoadBack:背景图åƒ
+
en.gtk.preferencesImageLoadNone:no images
de.gtk.preferencesImageLoadNone:Keine Bidlder
-fr.gtk.preferencesImageLoadNone:pas d'images
+fr.gtk.preferencesImageLoadNone:aucune image
+it.gtk.preferencesImageLoadNone:Nessuna immagine
nl.gtk.preferencesImageLoadNone:geen afbeeldingen
+zh_CN.gtk.preferencesImageLoadNone:无图åƒ
+
# font type list
en.gtk.preferencesFonttypeSans:Sans-serif
de.gtk.preferencesFonttypeSans:Sans-serif
fr.gtk.preferencesFonttypeSans:Sans-serif
+it.gtk.preferencesFonttypeSans:Sans-serif
nl.gtk.preferencesFonttypeSans:Schreefloos
+zh_CN.gtk.preferencesFonttypeSans:无衬线字体
+
en.gtk.preferencesFonttypeSerif:Serif
de.gtk.preferencesFonttypeSerif:Serif
fr.gtk.preferencesFonttypeSerif:Serif
+it.gtk.preferencesFonttypeSerif:Serif
nl.gtk.preferencesFonttypeSerif:Met schreef
+zh_CN.gtk.preferencesFonttypeSerif:衬线字体
+
en.gtk.preferencesFonttypeMonospace:Monospace
de.gtk.preferencesFonttypeMonospace:Monospace
-fr.gtk.preferencesFonttypeMonospace:Monospace
+fr.gtk.preferencesFonttypeMonospace:Chasse fixe
+it.gtk.preferencesFonttypeMonospace:Monospaziato
nl.gtk.preferencesFonttypeMonospace:Monospace
+zh_CN.gtk.preferencesFonttypeMonospace:等宽字体
+
en.gtk.preferencesFonttypeCursive:Cursive
de.gtk.preferencesFonttypeCursive:Kursiv
fr.gtk.preferencesFonttypeCursive:Cursive
+it.gtk.preferencesFonttypeCursive:Corsivo
nl.gtk.preferencesFonttypeCursive:Cursief
+zh_CN.gtk.preferencesFonttypeCursive:手写字体
+
en.gtk.preferencesFonttypeFantasy:Fantasy
de.gtk.preferencesFonttypeFantasy:Fantasy
-fr.gtk.preferencesFonttypeFantasy:Fantasy
+fr.gtk.preferencesFonttypeFantasy:Fantaisie
+it.gtk.preferencesFonttypeFantasy:Fantasia
nl.gtk.preferencesFonttypeFantasy:Fantasie
+zh_CN.gtk.preferencesFonttypeFantasy:Fantasy 字体
+
en.gtk.preferencesPrivacyTabtitle:Privacy
de.gtk.preferencesPrivacyTabtitle:Privates
fr.gtk.preferencesPrivacyTabtitle:Confidentialité
+it.gtk.preferencesPrivacyTabtitle:Privacy
nl.gtk.preferencesPrivacyTabtitle:Privacy
+zh_CN.gtk.preferencesPrivacyTabtitle:éšç§
+
en.gtk.preferencesGeneral:<b>General</b>
de.gtk.preferencesGeneral:<b>Generelles</b>
fr.gtk.preferencesGeneral:<b>Général</b>
+it.gtk.preferencesGeneral:<b>Generale</b>
nl.gtk.preferencesGeneral:<b>Algemeen</b>
+zh_CN.gtk.preferencesGeneral:<b>常规</b>
+
en.gtk.preferencesGeneralReferral:Enable referral submission
de.gtk.preferencesGeneralReferral:Referenzen erlauben
-fr.gtk.preferencesGeneralReferral:Permettre l'envoi du referer en entête
+fr.gtk.preferencesGeneralReferral:Autoriser le partage du referer
+it.gtk.preferencesGeneralReferral:Permetti invio informazioni sul referral
nl.gtk.preferencesGeneralReferral:Referentie versturen inschakelen
+zh_CN.gtk.preferencesGeneralReferral:å¯ç”¨æŽ¨èæ交
+
en.gtk.preferencesGeneralDNT:Enable sending "Do Not Track" request
de.gtk.preferencesGeneralDNT:Webseiten sollen nicht nachverfolgen dürfen
-fr.gtk.preferencesGeneralDNT:Activer l'envoi d'une requête "Ne pas suivre à la trace"
+fr.gtk.preferencesGeneralDNT:Demander aux sites Web de « ne pas me pister »
+it.gtk.preferencesGeneralDNT:Attiva invio per la richiesta di non tracciamento
nl.gtk.preferencesGeneralDNT:Websites laten weten dat gebruiker niet gevolgd wil worden
+zh_CN.gtk.preferencesGeneralDNT:å‘é€â€œä¸è·Ÿè¸ªâ€è¯·æ±‚
+
en.gtk.preferencesHistory:<b>History</b>
de.gtk.preferencesHistory:<b>History</b>
fr.gtk.preferencesHistory:<b>Historque</b>
+it.gtk.preferencesHistory:<b>Cronologia</b>
nl.gtk.preferencesHistory:<b>Geschiedenis</b>
+zh_CN.gtk.preferencesHistory:<b>历å²è®°å½•</b>
+
en.gtk.preferencesHistoryShow:Local history shows URL in tooltip
de.gtk.preferencesHistoryShow:History (lokal) zeigt die URL in der Hilfe an
-fr.gtk.preferencesHistoryShow:Historique local dans une infobulle
+fr.gtk.preferencesHistoryShow:L’historique local montre les URLs dans une infobulle
+it.gtk.preferencesHistoryShow:Mostra cronologia locale dell'URL nella descrizione comandi
nl.gtk.preferencesHistoryShow:Venstergeschiedenis toont webadres in een tipkader
+zh_CN.gtk.preferencesHistoryShow:本地历å²è®°å½•åœ¨å·¥å…·æ示中显示 URL
+
en.gtk.preferencesHistoryRemember:Remember browsing history for up to
de.gtk.preferencesHistoryRemember:History merken für bis zu
-fr.gtk.preferencesHistoryRemember:Conserver l'historique de navigation pendant
+fr.gtk.preferencesHistoryRemember:Conserver l’historique de navigation pendant
+it.gtk.preferencesHistoryRemember:Ricorda cronologia di navigazione in
nl.gtk.preferencesHistoryRemember:Browsergeschiedenis onthouden voor
+zh_CN.gtk.preferencesHistoryRemember:è®°ä½æµè§ˆåŽ†å²è®°å½•
+
en.gtk.preferencesHistoryDays:days
de.gtk.preferencesHistoryDays:Tage(n)
fr.gtk.preferencesHistoryDays:jours
+it.gtk.preferencesHistoryDays:giorni
nl.gtk.preferencesHistoryDays:dag(en)
+zh_CN.gtk.preferencesHistoryDays:天
+
en.gtk.preferencesCache:<b>Cache</b>
de.gtk.preferencesCache:<b>Cache</b>
fr.gtk.preferencesCache:<b>Cache</b>
+it.gtk.preferencesCache:<b>Cache</b>
nl.gtk.preferencesCache:<b>Buffer</b>
+zh_CN.gtk.preferencesCache:<b>缓存</b>
+
en.gtk.preferencesCacheMemory:Memory cache size
de.gtk.preferencesCacheMemory:RAM Cache
-fr.gtk.preferencesCacheMemory:Taille du cache mémoire
+fr.gtk.preferencesCacheMemory:Taille du cache en mémoire vive
+it.gtk.preferencesCacheMemory:Dimensione memoria cache
nl.gtk.preferencesCacheMemory:Grootte geheugenbuffer
+zh_CN.gtk.preferencesCacheMemory:内存缓存大å°
+
en.gtk.preferencesCacheDisc:Disc cache size
de.gtk.preferencesCacheDisc:Festplatten Cache
-fr.gtk.preferencesCacheDisc:Taille du cache disque
+fr.gtk.preferencesCacheDisc:Taille du cache sur le disque
+it.gtk.preferencesCacheDisc:Dimensione memoria disco
nl.gtk.preferencesCacheDisc:Grootte schijfbuffer
+zh_CN.gtk.preferencesCacheDisc:ç£ç›˜ç¼“存大å°
+
en.gtk.preferencesCacheExpire:Expire cache entries after
de.gtk.preferencesCacheExpire:Einträge verfallen nach
fr.gtk.preferencesCacheExpire:Les entrées du cache expirent après un délai de
+it.gtk.preferencesCacheExpire:Le voci della cache scadono dopo
nl.gtk.preferencesCacheExpire:Buffergegevens vervallen na
+zh_CN.gtk.preferencesCacheExpire:缓存项过期时间为
+
en.gtk.preferencesCacheMaintenance:Maintenance
de.gtk.preferencesCacheMaintenance:Aufräumen
fr.gtk.preferencesCacheMaintenance:Maintenance
+it.gtk.preferencesCacheMaintenance:Manutenzione
nl.gtk.preferencesCacheMaintenance:Onderhoud
+zh_CN.gtk.preferencesCacheMaintenance:维护
+
en.gtk.preferencesCacheDays:days
de.gtk.preferencesCacheDays:Tage(n)
fr.gtk.preferencesCacheDays:jours
+it.gtk.preferencesCacheDays:giorni
nl.gtk.preferencesCacheDays:dag(en)
+zh_CN.gtk.preferencesCacheDays:天
+
en.gtk.preferencesNetworkTabtitle:Network
de.gtk.preferencesNetworkTabtitle:Netzwerk
fr.gtk.preferencesNetworkTabtitle:Réseau
+it.gtk.preferencesNetworkTabtitle:Rete
nl.gtk.preferencesNetworkTabtitle:Netwerk
+zh_CN.gtk.preferencesNetworkTabtitle:网络
+
en.gtk.preferencesProxy:<b>HTTP Proxy</b>
de.gtk.preferencesProxy:<b>HTTP Proxy</b>
fr.gtk.preferencesProxy:<b>Proxy HTTP</b>
+it.gtk.preferencesProxy:<b>Proxy HTTP</b>
nl.gtk.preferencesProxy:<b>HTTP-proxy</b>
+zh_CN.gtk.preferencesProxy:<b>HTTP 代ç†æœåŠ¡å™¨</b>
+
en.gtk.preferencesProxyType:Proxy type
de.gtk.preferencesProxyType:Proxytyp
-fr.gtk.preferencesProxyType:Type de Proxy
+fr.gtk.preferencesProxyType:Type de proxy
+it.gtk.preferencesProxyType:Tipo di Proxy
nl.gtk.preferencesProxyType:Proxy-type
+zh_CN.gtk.preferencesProxyType:代ç†æœåŠ¡å™¨ç±»åž‹
+
en.gtk.preferencesProxyHost:Host
de.gtk.preferencesProxyHost:Host
fr.gtk.preferencesProxyHost:Hôte
+it.gtk.preferencesProxyHost:Host
nl.gtk.preferencesProxyHost:Proxy-server
+zh_CN.gtk.preferencesProxyHost:主机
+
en.gtk.preferencesProxyUsername:Username
de.gtk.preferencesProxyUsername:Benutzer
-fr.gtk.preferencesProxyUsername:Nom d'utilisateur
+fr.gtk.preferencesProxyUsername:Nom d’utilisateur
+it.gtk.preferencesProxyUsername:Nome utente
nl.gtk.preferencesProxyUsername:Gebruikersnaam
+zh_CN.gtk.preferencesProxyUsername:用户å
+
en.gtk.preferencesProxyPassword:Password
de.gtk.preferencesProxyPassword:Passwort
fr.gtk.preferencesProxyPassword:Mot de passe
+it.gtk.preferencesProxyPassword:Password
nl.gtk.preferencesProxyPassword:Wachtwoord
+zh_CN.gtk.preferencesProxyPassword:密ç 
+
en.gtk.preferencesProxyNoproxy:No Proxy For
de.gtk.preferencesProxyNoproxy:Kein Proxy für
fr.gtk.preferencesProxyNoproxy:Pas de proxy pour
+it.gtk.preferencesProxyNoproxy:No Proxy Per
nl.gtk.preferencesProxyNoproxy:Geen proxy voor
+zh_CN.gtk.preferencesProxyNoproxy:没有代ç†æœåŠ¡å™¨ç”¨äºŽæ“作
+
en.gtk.preferencesProxyTypeTooltip:The type of HTTP proxy server.
de.gtk.preferencesProxyTypeTooltip:Der Type des HTTP Proxy-Servers.
-fr.gtk.preferencesProxyTypeTooltip:Le type de serveur proxy HTTP.
+fr.gtk.preferencesProxyTypeTooltip:Type de serveur proxy HTTP.
+it.gtk.preferencesProxyTypeTooltip:Il tipo di server Proxy HTTP.
nl.gtk.preferencesProxyTypeTooltip:Het type van de HTTP-proxy-server.
+zh_CN.gtk.preferencesProxyTypeTooltip:HTTP 代ç†æœåŠ¡å™¨çš„类型。
+
en.gtk.preferencesProxyHostTooltip:Host name of your proxy server.
de.gtk.preferencesProxyHostTooltip:Hostname des Proxy-Servers.
-fr.gtk.preferencesProxyHostTooltip:Nom d'hôte du serveur proxy.
+fr.gtk.preferencesProxyHostTooltip:Nom d’hôte du serveur proxy.
+it.gtk.preferencesProxyHostTooltip:Nome host del tuo server Proxy.
nl.gtk.preferencesProxyHostTooltip:Adres van de proxy-server.
+zh_CN.gtk.preferencesProxyHostTooltip:代ç†æœåŠ¡å™¨çš„主机å。
+
en.gtk.preferencesProxyPortTooltip:Port number to connect to on proxy server.
de.gtk.preferencesProxyPortTooltip:Portnummer für die Verbindung zum Proxy.
fr.gtk.preferencesProxyPortTooltip:Le numéro de port pour se connecter au serveur proxy.
+it.gtk.preferencesProxyPortTooltip:Numero della porta per l'accesso al server Proxy.
nl.gtk.preferencesProxyPortTooltip:Poortnummer om te verbinden met de proxy-server.
+zh_CN.gtk.preferencesProxyPortTooltip:连接代ç†æœåŠ¡å™¨çš„端å£å·ã€‚
+
en.gtk.preferencesProxyUsernameTooltip:Username to access the proxy.
de.gtk.preferencesProxyUsernameTooltip:Username für die Verbindung zum Proxy.
-fr.gtk.preferencesProxyUsernameTooltip:Nom d'utilisateur pour accéder au proxy.
+fr.gtk.preferencesProxyUsernameTooltip:Nom d’utilisateur pour accéder au proxy.
+it.gtk.preferencesProxyUsernameTooltip:Nome utente per l'accesso al Proxy.
nl.gtk.preferencesProxyUsernameTooltip:Gebruikersnaam voor toegang tot de proxy.
+zh_CN.gtk.preferencesProxyUsernameTooltip:访问代ç†æœåŠ¡å™¨çš„用户å。
+
en.gtk.preferencesProxyNoproxyTooltip:Comma separated list of host names that should not be proxied.
de.gtk.preferencesProxyNoproxyTooltip:Liste von Hosts, die kein Proxy sein sollen. Komma trennt Einträge.
-fr.gtk.preferencesProxyNoproxyTooltip:Liste des noms d'hôtes séparés par des virgules qui ne devraient pas être traitées par le proxy.
+fr.gtk.preferencesProxyNoproxyTooltip:Liste des noms d’hôtes séparés par des virgules qui ne devraient pas être traitées par le proxy.
+it.gtk.preferencesProxyNoproxyTooltip:Elenco separato da virgole dei nomi host che non devono essere sottoposti a Proxy.
nl.gtk.preferencesProxyNoproxyTooltip:Lijst van ip-adressen of servernamen die niet via de proxy mogen lopen, gescheiden door komma's.
+zh_CN.gtk.preferencesProxyNoproxyTooltip:用逗å·åˆ†éš”ä¸åº”代ç†çš„主机å列表。
en.gtk.preferencesFetching:<b>Fetching</b>
de.gtk.preferencesFetching:<b>Daten holen (Fetch)</b>
fr.gtk.preferencesFetching:<b>Connexions</b>
+it.gtk.preferencesFetching:<b>Connessioni</b>
nl.gtk.preferencesFetching:<b>Verbindingen</b>
+zh_CN.gtk.preferencesFetching:<b>正在获å–</b>
+
en.gtk.preferencesFetchingMax:Maximum fetchers
de.gtk.preferencesFetchingMax:Verbindungen maximal
fr.gtk.preferencesFetchingMax:Nombre maximum de connexions
+it.gtk.preferencesFetchingMax:Numero massimo di connessioni
nl.gtk.preferencesFetchingMax:Maximum aantal
+zh_CN.gtk.preferencesFetchingMax:获å–器åŒæ—¶èŽ·å–的最大数é‡
+
en.gtk.preferencesFetchingPerhost:Fetches per host
de.gtk.preferencesFetchingPerhost:Verbindungen pro Host
fr.gtk.preferencesFetchingPerhost:Nombre de connexions par hôte
+it.gtk.preferencesFetchingPerhost:Connessioni per host
nl.gtk.preferencesFetchingPerhost:Aantal verbindingen per server
+zh_CN.gtk.preferencesFetchingPerhost:æ¯ä¸ªä¸»æœºçš„获å–次数
+
en.gtk.preferencesFetchingCached:Cached connections
de.gtk.preferencesFetchingCached:gepufferte Verbindungen
fr.gtk.preferencesFetchingCached:Connexions en cache
+it.gtk.preferencesFetchingCached:Connessioni su cache
nl.gtk.preferencesFetchingCached:Gebufferde verbindingen
+zh_CN.gtk.preferencesFetchingCached:已缓存的连接
+
en.gtk.preferencesFetchingMaxTooltip:Maximum number of concurrent items to fetch at once.
de.gtk.preferencesFetchingMaxTooltip:Maximale Anzahl paralleler Verbindungen.
-fr.gtk.preferencesFetchingMaxTooltip:Nombre maximum d'éléments simultanés à récupérer
+fr.gtk.preferencesFetchingMaxTooltip:Nombre maximum d’éléments simultanés à récupérer
+it.gtk.preferencesFetchingMaxTooltip:Numero massimo di elementi simultanei da recuperare in contemporanea.
nl.gtk.preferencesFetchingMaxTooltip:Maximum aantal verbindingen die simultaan items ophalen.
+zh_CN.gtk.preferencesFetchingMaxTooltip:一次获å–的最大并å‘项数。
+
en.gtk.preferencesFetchingPerhostTooltip:Maximum number of item fetches per web server.
de.gtk.preferencesFetchingPerhostTooltip:Maximale Zahl je Webserver.
-fr.gtk.preferencesFetchingPerhostTooltip:Nombre maximum d'élément à extrair pour chaque serveur Web.
+fr.gtk.preferencesFetchingPerhostTooltip:Nombre maximum d’élément à extraire pour chaque serveur Web.
+it.gtk.preferencesFetchingPerhostTooltip:Numero massimo di elementi da recuperare per server Web.
nl.gtk.preferencesFetchingPerhostTooltip:Maximum aantal verbinden per webserver.
+zh_CN.gtk.preferencesFetchingPerhostTooltip:æ¯ä¸ªç½‘络æœåŠ¡å™¨çš„最大项目获å–数。
+
en.gtk.preferencesFetchingCachedTooltip:Number of connections to keep in case they are needed again.
de.gtk.preferencesFetchingCachedTooltip:Zahl offengehaltener Verbindungen für den Fall, daß sie nochmal benötigt werden.
-fr.gtk.preferencesFetchingCachedTooltip:Nombre de connexions à maintenir dans le cas où elles seront nécessaires à nouveau.
+fr.gtk.preferencesFetchingCachedTooltip:Nombre de connexions à maintenir dans le cas où elles seraient nécessaires à nouveau.
+it.gtk.preferencesFetchingCachedTooltip:Numero di connessioni da conservare nel caso in cui siano di nuovo necessarie.
nl.gtk.preferencesFetchingCachedTooltip:Aantal verbindingen te bufferen voor het geval ze zijn weer nodig.
+zh_CN.gtk.preferencesFetchingCachedTooltip:è¦ä¿ç•™çš„连接数,以备å†æ¬¡éœ€è¦æ—¶ä½¿ç”¨ã€‚
+
# Proxy type list
en.gtk.preferencesProxyTypeDirect:Direct connection
de.gtk.preferencesProxyTypeDirect:Direktverbindung
fr.gtk.preferencesProxyTypeDirect:Connexion directe
+it.gtk.preferencesProxyTypeDirect:Connessione diretta
nl.gtk.preferencesProxyTypeDirect:Directe verbinding
+zh_CN.gtk.preferencesProxyTypeDirect:直接连接
+
en.gtk.preferencesProxyTypeManual:Manual with no authentication
de.gtk.preferencesProxyTypeManual:Manuell ohne Authentifizierung
fr.gtk.preferencesProxyTypeManual:Manuel sans authentification
+it.gtk.preferencesProxyTypeManual:Manuale senza autentificazione
nl.gtk.preferencesProxyTypeManual:Handmatig zonder authenticatie
+zh_CN.gtk.preferencesProxyTypeManual:ä¸å¸¦èº«ä»½éªŒè¯çš„手动æ“作
+
en.gtk.preferencesProxyTypeBasic:Manual with basic authentication
de.gtk.preferencesProxyTypeBasic:Manuell mit einfacher Prüfung
fr.gtk.preferencesProxyTypeBasic:Manuel avec authentification basique
+it.gtk.preferencesProxyTypeBasic:Manuale con autentificazione base
nl.gtk.preferencesProxyTypeBasic:Handmatig met basisauthenticatie
+zh_CN.gtk.preferencesProxyTypeBasic:使用基本身份验è¯çš„手动æ“作
+
en.gtk.preferencesProxyTypeNLTM:Manual with - authentication
de.gtk.preferencesProxyTypeNLTM:Manuell mit - Authentifizierung
-fr.gtk.preferencesProxyTypeNLTM:Manuel avec l'authentification NTLM
+fr.gtk.preferencesProxyTypeNLTM:Manuel avec authentification NTLM
+it.gtk.preferencesProxyTypeNLTM:Manuale con autentificazione NTLM
nl.gtk.preferencesProxyTypeNLTM:Handmatig via NTLM-authenticatie
+zh_CN.gtk.preferencesProxyTypeNLTM:使用身份验è¯çš„手动æ“作
+
en.gtk.preferencesProxyTypeSystem:System settings
de.gtk.preferencesProxyTypeSystem:System
fr.gtk.preferencesProxyTypeSystem:Paramètres du système
+it.gtk.preferencesProxyTypeSystem:Impostazioni di sistema
nl.gtk.preferencesProxyTypeSystem:Systeeminstellingen
+zh_CN.gtk.preferencesProxyTypeSystem:系统设置
+
en.gtk.preferencesPDFTabtitle:PDF
de.gtk.preferencesPDFTabtitle:PDF (Dokumente)
fr.gtk.preferencesPDFTabtitle:PDF
+it.gtk.preferencesPDFTabtitle:Documento PDF
nl.gtk.preferencesPDFTabtitle:PDF-uitvoer
+zh_CN.gtk.preferencesPDFTabtitle:PDF
+
en.gtk.preferencesAppearance:<b>Appearance</b>
de.gtk.preferencesAppearance:<b>Aussehen</b>
fr.gtk.preferencesAppearance:<b>Apparence</b>
+it.gtk.preferencesAppearance:<b>Aspetto</b>
nl.gtk.preferencesAppearance:<b>Opmaak</b>
+zh_CN.gtk.preferencesAppearance:<b>外观</b>
+
en.gtk.preferencesAppearanceImages:No images in output
de.gtk.preferencesAppearanceImages:Bilder unterdrücken
-fr.gtk.preferencesAppearanceImages:Aucune image de rendu/restituée
+fr.gtk.preferencesAppearanceImages:Supprimer toutes les images
+it.gtk.preferencesAppearanceImages:Nessuna immagine in output
nl.gtk.preferencesAppearanceImages:Geen afbeeldingen in uitvoer
+zh_CN.gtk.preferencesAppearanceImages:输出结果中无图åƒ
+
en.gtk.preferencesAppearanceBackground:No background images in output
de.gtk.preferencesAppearanceBackground:keine Hintergrundbilder
-fr.gtk.preferencesAppearanceBackground:Aucune image d'arrière-plan de rendu/restituée
+fr.gtk.preferencesAppearanceBackground:Supprimer les images d’arrière plan
+it.gtk.preferencesAppearanceBackground:Nessuna immagine di sfondo in output
nl.gtk.preferencesAppearanceBackground:Geen achtergrondafbeeldingen in uitvoer
+zh_CN.gtk.preferencesAppearanceBackground:输出结果中无背景图åƒ
+
en.gtk.preferencesAppearanceScalefit:Scale output to fit page
de.gtk.preferencesAppearanceScalefit:Ausgabe auf Seitengröße skalieren
fr.gtk.preferencesAppearanceScalefit:Adapter à la page
+it.gtk.preferencesAppearanceScalefit:Scala output per adattarlo alla pagina
nl.gtk.preferencesAppearanceScalefit:Uitvoer passend maken aan pagina
+zh_CN.gtk.preferencesAppearanceScalefit:缩放输出结果以适应页é¢
+
en.gtk.preferencesAppearanceScale:Scale output
de.gtk.preferencesAppearanceScale:Skalierung
fr.gtk.preferencesAppearanceScale:Adapter
+it.gtk.preferencesAppearanceScale:Scala output
nl.gtk.preferencesAppearanceScale:Schaal
+zh_CN.gtk.preferencesAppearanceScale:缩放输出结果
+
en.gtk.preferencesMargins:<b>Margins</b>
de.gtk.preferencesMargins:<b>Ränder</b>
fr.gtk.preferencesMargins:<b>Marges</b>
+it.gtk.preferencesMargins:<b>Margini</b>
nl.gtk.preferencesMargins:<b>Marges</b>
+zh_CN.gtk.preferencesMargins:<b>è¾¹è·</b>
+
en.gtk.preferencesMarginsMeasurements:measurements in mm
de.gtk.preferencesMarginsMeasurements:Messen in mm
fr.gtk.preferencesMarginsMeasurements:Mesures en mm
+it.gtk.preferencesMarginsMeasurements:Misura in mm
nl.gtk.preferencesMarginsMeasurements:eenheden in millimeters
+zh_CN.gtk.preferencesMarginsMeasurements:å•ä½ä¸ºæ¯«ç±³
+
en.gtk.preferencesGeneration:<b>Generation</b>
de.gtk.preferencesGeneration:<b>Erstellung</b>
-fr.gtk.preferencesGeneration:<b>Generation</b>
+fr.gtk.preferencesGeneration:<b>Génération</b>
+it.gtk.preferencesGeneration:<b>Generazione</b>
nl.gtk.preferencesGeneration:<b>Genereren</b>
+zh_CN.gtk.preferencesGeneration:<b>生æˆ</b>
+
en.gtk.preferencesGenerationCompressed:Output is compressed
de.gtk.preferencesGenerationCompressed:Ausgabe komprimieren
-fr.gtk.preferencesGenerationCompressed:La restitution est compressée
+fr.gtk.preferencesGenerationCompressed:Compresser le document
+it.gtk.preferencesGenerationCompressed:L'output è compresso
nl.gtk.preferencesGenerationCompressed:Uitvoer wordt gecomprimeerd
+zh_CN.gtk.preferencesGenerationCompressed:输出结果已压缩
+
en.gtk.preferencesGenerationPassword:Output has a password
de.gtk.preferencesGenerationPassword:Dokument hat Passwort
-fr.gtk.preferencesGenerationPassword:La restitution possède un mot de passe
+fr.gtk.preferencesGenerationPassword:Protéger le document par un mot de passe
+it.gtk.preferencesGenerationPassword:L'output ha una password
nl.gtk.preferencesGenerationPassword:Uitvoer wordt met wachtwoord beveiligd
+zh_CN.gtk.preferencesGenerationPassword:输出结果有密ç 
-# Printing user interface tokens
-# ==============================
-#
-# This section contains tokens which are used in the printing
-# dialog box.
-#
-
-en.all.PrintSheetFilled:sheet is filled
-de.all.PrintSheetFilled:Druckseite
-fr.all.PrintSheetFilled:feuille remplie
-it.all.PrintSheetFilled:Il foglio stampato è pieno
-nl.all.PrintSheetFilled:pagina
-en.all.PrintSheetsFilled:sheets are filled
-de.all.PrintSheetsFilled:Druckseiten
-fr.all.PrintSheetsFilled:feuilles remplies
-it.all.PrintSheetsFilled:I fogli stampati sono pieni
-nl.all.PrintSheetsFilled:pagina's
-en.all.Printer:Printer
-de.all.Printer:Drucker
-fr.all.Printer:Imprimante
-it.all.Printer:Stampante
-nl.all.Printer:Printer
-en.all.Copies:Copies
-de.all.Copies:Kopien
-fr.all.Copies:Copies
-it.all.Copies:Copie
-nl.all.Copies:Kopieën
-en.all.Printing:Printing page
-de.all.Printing:Drucke Seite
-fr.all.Printing:Page impression
-it.all.Printing:Stampa della pagina
-nl.all.Printing:Pagina aan het afdrukken
-
-
-# Find text user interface tokens
-# ===============================
-#
-# This section contains tokens which are used in the find text
-# dialog box.
-#
-en.all.NotFound:Not found
-de.all.NotFound:nichts
-fr.all.NotFound:Non trouvé
-it.all.NotFound:Non trovato
-nl.all.NotFound:Niet gevonden
-en.all.Next:Next
-de.all.Next:Nächster
-fr.all.Next:Suivant
-it.all.Next:Successivo
-nl.all.Next:Volgende
-en.all.Prev:Previous
-de.all.Prev:Vorheriger
-fr.all.Prev:Précédent
-it.all.Prev:Precedente
-nl.all.Prev:Vorige
-en.all.ShowAll:Show All
-de.all.ShowAll:Alle zeigen
-fr.all.ShowAll:Tout afficher
-it.all.ShowAll:Mostra Tutto
-nl.all.ShowAll:Toon alles
-en.all.CaseSens:Case Sensitive
-de.all.CaseSens:Groß-/Kleinschreibung
-fr.all.CaseSens:Sensible à la casse
-it.all.CaseSens:Maiuscole/Minuscole
-nl.all.CaseSens:Hoofdlettergevoelig
-
-
-# 401 login user interface tokens
-# ===============================
-#
-# This section contains tokens which are used in the 401 login
-# (authentication) dialog box.
-#
-en.all.Host:Host
-de.all.Host:Host
-fr.all.Host:Hôte
-it.all.Host:Host
-nl.all.Host:Server
-en.all.Realm:Realm
-de.all.Realm:Realm
-fr.all.Realm:Domaine
-it.all.Realm:Tipo
-nl.all.Realm:Gebied
-en.all.Username:Username
-de.all.Username:Benutzername
-fr.all.Username:Nom d'utilisateur
-it.all.Username:Nome Utente
-nl.all.Username:Gebruikersnaam
-en.all.Password:Password
-de.all.Password:Passwort
-fr.all.Password:Mot de passe
-it.all.Password:Password
-nl.all.Password:Wachtwoord
-en.all.Login:Login
-de.all.Login:Login
-fr.all.Login:Connexion
-it.all.Login:Login
-nl.all.Login:Login
-en.all.Cancel:Cancel
-de.all.Cancel:Abbruch
-fr.all.Cancel:Annuler
-it.all.Cancel:Annulla
-nl.all.Cancel:Annuleer
-
-
-# SSL certificate verification
-# ============================
-#
-# This section contains tokens which are used in the
-# SSL certificate verification dialog box.
-#
-en.all.SSLCerts:SSL certificates
-de.all.SSLCerts:SSL Zertifikat
-fr.all.SSLCerts:Certificats SSL
-it.all.SSLCerts:Certificati SSL
-nl.all.SSLCerts:SSL-certificaten
-en.all.SSLError:NetSurf failed to verify the authenticity of an SSL certificate. Please verify the details presented below.
-de.all.SSLError:NetSurf konnte ein SSL Zertifikat nicht prüfen. Bitte die Details unten beachten.
-fr.all.SSLError:NetSurf a échoué dans la vérification de l'authenticité d'un certificat SSL. Vérifier les détails présentés ci-dessous.
-it.all.SSLError:NetSurf non è stato in grado di verificare l'autenticità di questo certificato SSL, per favore verifica i dettagli presenti di seguito
-nl.all.SSLError:NetSurf kan de authenticiteit van een SSL-certificaat niet controleren. Controleer onderstaande details.
-en.all.SSL_Certificate_Subject:Subject: %s
-de.all.SSL_Certificate_Subject:Subject: %s
-fr.all.SSL_Certificate_Subject:Objet : %s
-it.all.SSL_Certificate_Subject:Soggetto: %s
-nl.all.SSL_Certificate_Subject:Subjekt: %s
-en.all.SSL_Certificate_Issuer:Issuer: %s
-de.all.SSL_Certificate_Issuer:Issuer: %s
-fr.all.SSL_Certificate_Issuer:Émetteur : %s
-it.all.SSL_Certificate_Issuer:Emittente: %s
-nl.all.SSL_Certificate_Issuer:Uitgever: %s
-en.all.SSL_Certificate_Version:Version: %ld
-de.all.SSL_Certificate_Version:Version: %ld
-fr.all.SSL_Certificate_Version:Version : %ld
-it.all.SSL_Certificate_Version:Versione: %ld
-nl.all.SSL_Certificate_Version:Versie: %ld
-en.all.SSL_Certificate_ValidFrom:Valid from: %s
-de.all.SSL_Certificate_ValidFrom:Valid from: %s
-fr.all.SSL_Certificate_ValidFrom:Valide à compter du : %s
-it.all.SSL_Certificate_ValidFrom:Valido da: %s
-nl.all.SSL_Certificate_ValidFrom:Geldig vanaf: %s
-en.all.SSL_Certificate_ValidTo:Valid until: %s
-de.all.SSL_Certificate_ValidTo:Valid until: %s
-fr.all.SSL_Certificate_ValidTo:Valable jusqu'au : %s
-it.all.SSL_Certificate_ValidTo:Valido fino a: %s
-nl.all.SSL_Certificate_ValidTo:Geldig tot: %s
-en.all.SSL_Certificate_Type:Type: %i
-de.all.SSL_Certificate_Type:Type: %i
-fr.all.SSL_Certificate_Type:Type : %i
-it.all.SSL_Certificate_Type:Tipo: %i
-nl.all.SSL_Certificate_Type:Type: %i
-en.all.SSL_Certificate_Serial:Serial: %ld
-de.all.SSL_Certificate_Serial:Serial: %ld
-fr.all.SSL_Certificate_Serial:Série : %ld
-it.all.SSL_Certificate_Serial:Seriale: %ld
-nl.all.SSL_Certificate_Serial:Serienr.: %ld
-en.all.SSL_Certificate_Accept:Accept
-de.all.SSL_Certificate_Accept:Accept
-fr.all.SSL_Certificate_Accept:Accepter
-it.all.SSL_Certificate_Accept:Accetta
-nl.all.SSL_Certificate_Accept:Accepteer
-en.all.SSL_Certificate_Reject:Reject
-de.all.SSL_Certificate_Reject:Reject
-fr.all.SSL_Certificate_Reject:Rejeter
-it.all.SSL_Certificate_Reject:Rifiuta
-nl.all.SSL_Certificate_Reject:Weiger
-
-
-# Content
-# =======
-#
-# This section contains tokens used by contents
-#
-
-# Forms
-#
-en.all.Form_Submit:Submit
-de.all.Form_Submit:Ãœbertragen
-fr.all.Form_Submit:Soumettre
-it.all.Form_Submit:Invia
-nl.all.Form_Submit:Versturen
-en.all.Form_Reset:Reset
-de.all.Form_Reset:Zurücksetzen
-fr.all.Form_Reset:Effacer
-it.all.Form_Reset:Resetta
-nl.all.Form_Reset:Opnieuw
-en.all.Form_None:
-de.all.Form_None:
-fr.all.Form_None:
-it.all.Form_None:
-nl.all.Form_None:
-en.all.Form_Many:(Many)
-de.all.Form_Many:(Viele)
-fr.all.Form_Many:(Plusieurs)
-it.all.Form_Many:(Molti)
-nl.all.Form_Many:(Veel)
-en.gtk.Form_Drop:Click to select file
-fr.gtk.Form_Drop:Cliquer pour sélectionner fichier
-nl.gtk.Form_Drop:Klik om bestand te selecteren
-en.ro.Form_Drop:Drop file here
-fr.ro.Form_Drop:Déposer fichier ici
-en.ami.Form_Drop:Click or drop file here
-fr.ami.Form_Drop:Cliquer ou déposer fichier ici]
-nl.ami.Form_Drop:Sleep bestand hierheen
-en.beos.Form_Drop:Drop file here
-fr.beos.Form_Drop:Drop file here
-nl.beos.Form_Drop:Sleep bestand hierheen
-en.fb.Form_Drop:Click to select file
-fr.fb.Form_Drop:Cliquer pour sélectionner fichier
-nl.fb.Form_Drop:Klik om bestand te selecteren
-en.osx.Form_Drop:Click to select file
-fr.osx.Form_Drop:Cliquer pour sélectionner fichier
-de.all.Form_Drop:Datei hier hinziehen
-fr.all.Form_Drop:Déposer les fichiers ici
-it.all.Form_Drop:Inserisci un file qui
-nl.all.Form_Drop:Bestand hier plaatsen
-en.all.FormSelect:Click to choose a form item
-de.all.FormSelect:Anklicken öffnet Auswahlmenü
-fr.all.FormSelect:Cliquer pour choisir un item de formulaire
-it.all.FormSelect:Clicca per scegliere un oggetto del modulo
-nl.all.FormSelect:Klikken selecteert een formulieritem
-en.all.FormCheckbox:Click to check this option
-de.all.FormCheckbox:Anklicken um die Option an/abzuschalten
-fr.all.FormCheckbox:Cliquer pour cocher cette option
-it.all.FormCheckbox:Clicca per scegliere questa opzione
-nl.all.FormCheckbox:Klikken selecteert deze optie
-en.all.FormRadio:Click to choose this option
-de.all.FormRadio:Anklicken wählt diese Option
-fr.all.FormRadio:Cliquer pour choisir cette option
-it.all.FormRadio:Clicca per selezionare questa opzione
-nl.all.FormRadio:Klikken kiest deze optie
-en.all.FormSubmit:Send form to %s
-de.all.FormSubmit:Daten übertragen an %s
-fr.all.FormSubmit:Envoyer le formulaire à %s
-it.all.FormSubmit:Invia il risultato del modulo a: %s
-nl.all.FormSubmit:Informatie versturen naar %s
-en.all.FormBadSubmit:Warning: form can not be submitted
-de.all.FormBadSubmit:Achtung: Daten können nicht gesendet werden
-fr.all.FormBadSubmit:Alerte : le formulaire n'a pas pu être envoyé
-it.all.FormBadSubmit:Attenzione: Il modulo non può essere inviato
-nl.all.FormBadSubmit:Waarschuwing: informatie kan niet verzonden worden
-en.all.FormButton:Warning: button can not be activated
-de.all.FormButton:Achtung: Schaltknopf kann nicht aktiviert werden
-fr.all.FormButton:Warning: Bouton ne peut être activé
-it.all.FormButton:Attenzione: il pulsante non può essere attivato
-nl.all.FormButton:Waarschuwing: knop kan niet geactiveerd worden
-en.all.FormTextarea:Click to edit the text
-de.all.FormTextarea:Anklicken zum Editieren
-fr.all.FormTextarea:Cliquer pour éditer ce texte
-it.all.FormTextarea:Clicca per editare il testo
-nl.all.FormTextarea:Klikken om tekst te bewerken
-en.all.FormTextbox:Click to edit this field
-de.all.FormTextbox:Anklicken zum Bearbeiten des Feldes
-fr.all.FormTextbox:Cliquer pour éditer ce champ
-it.all.FormTextbox:Clicca per editare il campo di testo
-nl.all.FormTextbox:Klikken om dit veld te bewerken
-en.all.FormReset:Reset form (not implemented)
-de.all.FormReset:Zurücksetzen (nicht implementiert)
-fr.all.FormReset:Effacer le formulaire (non implémenté)
-it.all.FormReset:Resetta il modulo
-nl.all.FormReset:Formulier opnieuw instellen (niet geïmplemented)
-en.all.FormFile:Drop a file here to upload it
-de.all.FormFile:Zum Upload Datei hierhin ziehen und fallenlassen
-fr.all.FormFile:Déposer un fichier ici pour le téléverser #Need review
-it.all.FormFile:Inserisci un file da inviare qui
-nl.all.FormFile:Het bestand hier plaatsen voor verzenden
-en.all.SelectMenu:Select
-de.all.SelectMenu:Auswahl
-fr.all.SelectMenu:Sélectionner
-it.all.SelectMenu:Seleziona
-nl.all.SelectMenu:Selecteer
-
-# Content titles
-#
-en.all.DrawTitle:%s (Draw image %lux%lu pixels)
-de.all.DrawTitle:%s (Draw Bild %lux%lu pixels)
-fr.all.DrawTitle:%s (Image Draw %lux%lu pixels)
-it.all.DrawTitle:%s (Immagine Draw %lux%lu pixel)
-nl.all.DrawTitle:%s (Draw-afbeelding %lux%lu punten)
-en.all.GIFTitle:%s (GIF image %lux%lu pixels)
-de.all.GIFTitle:%s (GIF Bild %lux%lu pixels)
-fr.all.GIFTitle:%s (Image GIF %lux%lu pixels)
-it.all.GIFTitle:%s (Immagine GIF %lux%lu pixel)
-nl.all.GIFTitle:%s (GIF-afbeelding %lux%lu punten)
-en.all.BMPTitle:%s (BMP image %lux%lu pixels)
-de.all.BMPTitle:%s (BMP Bild %lux%lu pixels)
-fr.all.BMPTitle:%s (Image BMP %lux%lu pixels)
-it.all.BMPTitle:%s (Immagine BMP %lux%lu pixel)
-nl.all.BMPTitle:%s (BMP-afbeelding %lux%lu punten)
-en.all.ICOTitle:%s (ICO image %lux%lu pixels)
-de.all.ICOTitle:%s (ICO Bild %lux%lu pixels)
-fr.all.ICOTitle:%s (Image BMP %lux%lu pixels)
-it.all.ICOTitle:%s (Immagine ICO %lux%lu pixel)
-nl.all.ICOTitle:%s (ICO-afbeelding %lux%lu punten)
-en.all.JPEGTitle:%s (JPEG image %lux%lu pixels)
-de.all.JPEGTitle:%s (JPEG Bild %lux%lu pixels)
-fr.all.JPEGTitle:%s (Image JPEG %lux%lu pixels)
-it.all.JPEGTitle:%s (Immagine JPEG %lux%lu pixel)
-nl.all.JPEGTitle:%s (JPEG-afbeelding %lux%lu punten)
-en.all.PNGTitle:%s (PNG image %lux%lu pixels)
-de.all.PNGTitle:%s (PNG Bild %lux%lu pixels)
-fr.all.PNGTitle:%s (Image PNG %lux%lu pixels)
-it.all.PNGTitle:%s (Immagine PNG %lux%lu pixel)
-nl.all.PNGTitle:%s (PNG-afbeelding %lux%lu punten)
-en.all.JNGTitle:%s (JNG image %lux%lu pixels)
-de.all.JNGTitle:%s (JNG Bild %lux%lu pixels)
-fr.all.JNGTitle:%s (Image JNG %lux%lu pixels)
-it.all.JNGTitle:%s (Immagine JNG %lux%lu pixel)
-nl.all.JNGTitle:%s (JNG-afbeelding %lux%lu punten)
-en.all.MNGTitle:%s (MNG image %lux%lu pixels)
-de.all.MNGTitle:%s (MNG Bild %lux%lu pixels)
-fr.all.MNGTitle:%s (Image MNG %lux%lu pixels)
-it.all.MNGTitle:%s (Immagine MNG %lux%lu pixel)
-nl.all.MNGTitle:%s (MNG-afbeelding %lux%lu punten)
-en.all.WebPTitle:%s (WebP image %lux%lu pixels)
-de.all.WebPTitle:%s (WebP Bild %lux%lu pixels)
-fr.all.WebPTitle:%s (Image WebP %lux%lu pixels)
-it.all.WebPTitle:%s (Immagine WebP %lux%lu pixel)
-nl.all.WebPTitle:%s (WebP-afbeelding %lux%lu punten)
-en.all.SpriteTitle:%s (Sprite image %lux%lu pixels)
-de.all.SpriteTitle:%s (Sprite Bild %lux%lu pixels)
-fr.all.SpriteTitle:%s (Image Sprite %lux%lu pixels)
-it.all.SpriteTitle:%s (Immagine Sprite %lux%lu pixel)
-nl.all.SpriteTitle:%s (Sprite-afbeelding %lux%lu punten)
-en.all.ArtWorksTitle:%s (ArtWorks image %lux%lu pixels)
-de.all.ArtWorksTitle:%s (ArtWorks Bild %lux%lu pixels)
-fr.all.ArtWorksTitle:%s (Image ArtWorks %lux%lu pixels)
-it.all.ArtWorksTitle:%s (Immagine ArtWorks %lux%lu pixel)
-nl.all.ArtWorksTitle:%s (ArtWorks-afbeelding %lux%lu punten)
-en.ami.DataTypesTitle:%s (%s image %lux%lu pixels)
-de.ami.DataTypesTitle:%s (%s Bild %lux%lu pixels)
-fr.ami.DataTypesTitle:%s (Image %s %lux%lu pixels)
-it.ami.DataTypesTitle:%s (Immagine %s %lux%lu pixel)
-nl.ami.DataTypesTitle:%s (%s afbeelding %lux%lu punten)
-
-# HTML page character set
-#
-en.all.Encoding0:from HTTP headers
-de.all.Encoding0:aus HTTP Kopfzeilen
-fr.all.Encoding0:dans les en-têtes HTTP
-it.all.Encoding0:da intestazioni HTTP
-nl.all.Encoding0:van HTTP-koppen
-en.all.Encoding1:detected
-de.all.Encoding1:ermittelt
-fr.all.Encoding1:détecté
-it.all.Encoding1:rilevato
-nl.all.Encoding1:gedetecteerd
-en.all.Encoding2:from <meta>
-de.all.Encoding2:aus <meta>
-fr.all.Encoding2:de <meta>
-it.all.Encoding2:da <meta>
-nl.all.Encoding2:van <meta>
-en.all.EncodingUnk:Unknown
-de.all.EncodingUnk:Unbekannt
-fr.all.EncodingUnk:Inconnu
-it.all.EncodingUnk:Sconosciuto
-nl.all.EncodingUnk:Onbekend
-
-# Directory browser
-#
-en.all.FileIndex:Index of %s
-de.all.FileIndex:Inhalt von %s
-fr.all.FileIndex:Index de %s
-it.all.FileIndex:Indice di %s
-nl.all.FileIndex:Index van %s
-en.all.FileParent:^ Up to parent directory
-de.all.FileParent:^ Eine Ebene höher
-fr.all.FileParent:^ Répertoire parent
-it.all.FileParent:^ Livello superiore
-nl.all.FileParent:^ Een mapniveau hoger
-en.all.FileDirectory:Directory
-de.all.FileDirectory:Verzeichnis
-fr.all.FileDirectory:Répertoire
-it.all.FileDirectory:Directory
-nl.all.FileDirectory:Map
-en.all.FileName:Name
-de.all.FileName:Name
-fr.all.FileName:Nom
-it.all.FileName:Nome
-nl.all.FileName:Naam
-en.all.FileSize:Size
-de.all.FileSize:Größe
-fr.all.FileSize:Taille
-it.all.FileSize:Dimensione
-nl.all.FileSize:Grootte
-en.all.FileDate:Date
-de.all.FileDate:Datum
-fr.all.FileDate:Date
-it.all.FileDate:Data
-nl.all.FileDate:Datum
-en.all.FileTime:Time
-de.all.FileTime:Zeit
-fr.all.FileTime:Time
-it.all.FileTime:Ora
-nl.all.FileTime:Tijd
-en.all.FileType:Type
-de.all.FileType:Typ
-fr.all.FileType:Type
-it.all.FileType:Tipo
-nl.all.FileType:Type
-
-# Misc
-#
-en.all.Selecting:Selecting
-de.all.Selecting:Auswählen
-fr.all.Selecting:Sélection en cours
-it.all.Selecting:Selezione
-nl.all.Selecting:selecteren
-en.all.FrameDrag:Resizing frames
-de.all.FrameDrag:Frames ändern
-fr.all.FrameDrag:Redimensionnement des cadres en cours
-it.all.FrameDrag:Ridimensione dei frame
-nl.all.FrameDrag:frames aan het aanpassen
-
-
-# Errors
-# ======
-#
-# This section contains error and warning messages which
-# are displayed to the user.
-#
-
-# Fetching errors - displayed as an HTML page
-#
-en.all.Not2xx:Server returned an error
-de.all.Not2xx:Server meldet Fehler zurück
-fr.all.Not2xx:Le serveur a renvoyé une erreur
-it.all.Not2xx:Il server ha riportato un errore
-nl.all.Not2xx:Server meldt een fout
-en.all.InvalidURL:The address <em>%s</em> could not be understood.
-de.all.InvalidURL:Die Adresse <em>%s</em> konnte nicht ausgewertet werden.
-fr.all.InvalidURL:L'adresse <em>%s</em> est incomprise.
-it.all.InvalidURL:L'indirizzo <em>%s</em> non è stato riconosciuto.
-nl.all.InvalidURL:Het adres <em>%s</em> klopt niet.
-
-# HTML error page
-#
-en.all.ErrorPage:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Page error</title></head><body><h1>Sorry, NetSurf was unable to display this page</h1><p><strong>%s</strong></p></body></html>
-de.all.ErrorPage:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Seitenfehler</title></head><body><h1>NetSurf konnte diese Seite leider nicht darstellen.</h1><p><strong>%s</strong></p></body></html>
-fr.all.ErrorPage:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Erreur</title></head><body><h1>Désolé, NetSurf n'a pas pu afficher cette page</h1><p><strong>%s</strong></p></body></html>
-it.all.ErrorPage:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Errore nella pagina</title></head><body><h1>Spiacente, NetSurf non è in grado di visualizzare questa pagina.</h1><p><strong>%s</strong></p></body></html>
-nl.all.ErrorPage:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Pagina fout</title></head><body><h1>Sorry, NetSurf kan deze pagina</h1><p><strong>%s</strong></p>niet tonen.</body></html>
-
-# General errors - displayed in a dialog box
-#
-# These may be augmented with further relevant information, which
-# is displayed after the contents of the relevant token.
-#
-en.all.PathToURL:An error occurred converting the file path to an URL:
-de.all.PathToURL:Fehler beim Konvertieren des Dateipfades in eine URL Adresse:
-fr.all.PathToURL:Une erreur s'est produite en convertissant le chemin du fichier en une URL:
-it.all.PathToURL:Si è verificato un errore durante la conversione del percorso file nell'URL:
-nl.all.PathToURL:Fout tijdens het omzetten van het bestandspad naar een adres:
-en.all.SaveError:The file could not be saved due to an error:
-de.all.SaveError:Die Datei konnte wegen eines Fehlers nicht gespeichert werden:
-fr.all.SaveError:Le fichier n'a pas pu être sauvé suite à une erreur:
-it.all.SaveError:Il file non può essere salvato a causa di un errore:
-nl.all.SaveError:Wegens een fout kan dit bestand niet opgeslagen worden:
-en.all.LoadError:The file could not be loaded due to an error:
-de.all.LoadError:Die Datei konnte wegen eines Fehlers nicht geladen werden:
-fr.all.LoadError:Le fichier n'a pas pu être chargé à cause d'une erreur:
-it.all.LoadError:Il file non può essere caricato a causa di un errore:
-nl.all.LoadError:Wegens een fout kan dit bestand niet geladen worden:
-en.all.MenuError:An error occurred when opening the menu:
-de.all.MenuError:Fehler beim Öffnen des Menüs:
-fr.all.MenuError:Une erreur s'est produite lors de l'ouverture du menu:
-it.all.MenuError:Si è verificato un errore durante l'apertura del menu:
-nl.all.MenuError:Fout bij het openen van het menu:
-en.all.DragError:An error occurred when dragging the icon:
-de.all.DragError:Fehler beim Ziehen des Symboles:
-fr.all.DragError:Une erreur s'est produite lors du déplacement d'icône:
-it.all.DragError:Si è verificato un errore durante il trascinamento dell'icona:
-nl.all.DragError:Fout bij het slepen van het symbool:
-en.all.TbarError:An error occurred when constructing the toolbar:
-de.all.TbarError:Fehler beim Aufbau der Toolbar:
-fr.all.TbarError:Une erreur s'est produite lors de la construction de la barre d'outils:
-it.all.TbarError:Si è verificato un errore durante la costruzione della barra strumenti:
-nl.all.TbarError:Fout bij het maken van de gereedschapbalk:
-en.all.WimpError:An unexpected Window Manager error occurred:
-de.all.WimpError:Unerwarteter Fehler im Window Manager:
-fr.all.WimpError:Une erreur inattendue du Gestionnaire de Fenêtres s'est produite:
-it.all.WimpError:Si è verificato un errore inatteso nella finestra principale:
-nl.all.WimpError:Er trad een onverwachte fout op in de Vensterbeheerder:
-en.all.DownloadWarn:This download may not complete:
-de.all.DownloadWarn:Der Download ist wahrscheinlich unvollständig:
-fr.all.DownloadWarn:Ce téléchargement ne peut pas se terminer:
-it.all.DownloadWarn:Questo trasferimento potrebbe essere incompleto:
-nl.all.DownloadWarn:Dit bestand is misschien niet compleet opgehaald:
-en.all.MiscError:An unexpected error occurred:
-de.all.MiscError:Unerwarteter Fehler:
-fr.all.MiscError:Une erreur inattendue s'est produite:
-it.all.MiscError:Si è verificato un errore inatteso:
-nl.all.MiscError:Er trad een onverwachte fout op:
-en.all.FileError:File does not exist:
-de.all.FileError:Datei existiert nicht:
-fr.all.FileError:Le fichier n'existe pas:
-it.all.FileError:Il file è inesistente:
-nl.all.FileError:Bestand lijkt niet te bestaan:
-en.all.PrintError:An error occurred when printing:
-de.all.PrintError:Ein Fehler trat während des Druckens auf:
-fr.all.PrintError:Une erreur s'est produite lors de l'impression:
-it.all.PrintError:Si è verificato un errore durante la stampa:
-nl.all.PrintError:Fout tijdens afdrukken:
-
-# Specific errors - displayed in a dialog box
-#
-en.all.NoMemory:NetSurf is running out of memory. Please free some memory and try again.
-de.all.NoMemory:Zu wenig Speicher. Bitte mehr Speicher zur Verfügung stellen und erneut versuchen.
-fr.all.NoMemory:NetSurf a besoin de plus de mémoire. Veuillez libérer de la mémoire et réessayer.
-it.all.NoMemory:Memoria insufficiente per l'esecuzione di NetSurf. Per favore liberane un pò e riprova nuovamente.
-nl.all.NoMemory:NetSurf heeft gebrek aan voldoende geheugen. Maak wat geheugen vrij en probeer het dan nog eens.
-en.ro.LongURL:The URL for this page is too long for NetSurf to display.
-de.ro.LongURL:The URL for this page is too long for NetSurf to display.
-fr.ro.LongURL:The URL for this page is too long for NetSurf to display.
-it.ro.LongURL:L'URL di questa pagina è troppo lungo per essere visualizzato su NetSurf.
-nl.ro.LongURL:Het adres van deze pagina is te lang voor NetSurf om te kunnen tonen.
-en.ro.FontBadInst:An error occurred when initialising fonts due to the presence of obsolete copies of the ROM fonts on disc. NetSurf will exit and launch a program which will attempt to fix this.
-de.ro.FontBadInst:Font-Initialisierung fehlerhaft. Obsolete Kopien von ROM Fonts auf dem lokalem Speichermedium. Fehlerbehebung startet.
-fr.ro.FontBadInst:Une erreur s'est produite lors de l'initialisation des fontes à cause de la présence de copies obsolètes de fontes ROM sur disque. NetSurf va sortir et lancer un programme qui va tenter de réparer cela.
-it.ro.FontBadInst:Si è verificato un errore durante l'inizializzazione dei font a causa della presenza di una copia obsoleta dei font "ROM" nel disco. NetSurf verrà chiuso e si cercherà di lanciare un programma in grado di risolvere questo problema.
-nl.ro.FontBadInst:Probleem ontstaan bij het initialiseren van de lettertypen. Een schijf bevat een map met geactiveerde ROM-lettertypes die overbodig zijn. NetSurf wordt gestopt en activeert een programma die dit probleem probeert te verhelpen.
-en.ro.FontError:Failed to open font "Homerton.Medium" (%s).
-de.ro.FontError:Fehler beim öffnen des Fonts "Homerton.Medium" (%s).
-fr.ro.FontError:Échec d'ouverture de la fonte "Homerton.Medium" (%s).
-it.ro.FontError:Impossibile aprire il font "Homerton.Medium" (%s).
-nl.ro.FontError:Het lettertypebestand "Homerton.Medium" kan niet worden geopend (%s).
-en.ro.Resolvers:No domain name servers are configured, so only browsing local files will be possible. Use Configure to set your name server(s).
-de.ro.Resolvers:Keine Domain Name Servers (DNS) konfiguriert. Nur lokale Dateien sind ladbar. Bitte DNS unter !Boot eintragen.
-fr.ro.Resolvers:Aucun nom de domaine n'étant configuré, seul la consultation de fichiers locaux est possible. Utilisez Configure pour définir les serveurs de noms.
-it.ro.Resolvers:Non è stato configurato nessun nome per i domini dei server, perciò sarà possibile effettuare la navigazione dei file solo in modalità locale. Usa "Configura" per impostare il nome (o i nomi) del/dei server.
-nl.ro.Resolvers:Er zijn geen DNS-servers ingesteld, dus kunnen alleen lokale bestanden worden bekeken. Ga naar de netwerkinstellingen via !Boot om de DNS-server(s) in te stellen.
-en.all.NoDiscSpace:Not enough space available on disc.
-de.all.NoDiscSpace:Nicht genug Speicherplatz auf dem Medium vorhanden.
-fr.all.NoDiscSpace:Pas assez d'espace disque disponible.
-it.all.NoDiscSpace:Spazio insufficiente nel disco.
-nl.all.NoDiscSpace:Onvoldoende ruimte beschikbaar op schijf.
-en.ro.Template:A window template is missing from the Templates file. Please reinstall NetSurf.
-de.ro.Template:Ein Template für ein Fenster fehlt in der Datei Templates. Bitte NetSurf neu installieren.
-fr.ro.Template:Un modèle de fenêtre est absent du fichier Templates. Réinstallez NetSurf SVP.
-it.ro.Template:Una finestra di template risulta mancante. Per favore reinstalla NetSurf.
-nl.ro.Template:Er ontbreekt een vensterdefinitie in het Templates-bestand. Installeer NetSurf opnieuw.
-en.all.HotlistSaveError:The hotlist was unable to be correctly saved.
-de.all.HotlistSaveError:Hotlist konnte nicht korrekt gespeichert werden.
-fr.all.HotlistSaveError:Les favoris n'ont pas pu être sauvés correctement.
-it.all.HotlistSaveError:Non è stato possibile salvare correttamente i segnalibri.
-nl.all.HotlistSaveError:De favorietenlijst kon niet correct worden bewaard.
-en.all.TreeLoadError:The tree was unable to be correctly loaded.
-de.all.TreeLoadError:The tree was unable to be correctly loaded.
-fr.all.TreeLoadError:The tree was unable to be correctly loaded.
-it.all.TreeLoadError:L'albero della directory non è stato caricato correttamente.
-nl.all.TreeLoadError:De gegevensstructuur kon niet correct worden geladen.
-en.all.NoDirError:%s is not a directory
-de.all.NoDirError:%s ist kein Verzeichnis.
-fr.all.NoDirError:%s n'est pas un répertoire
-it.all.NoDirError:%s non è una directory
-nl.all.NoDirError:%s is geen map
-en.ro.NoPathError:To save, drag the icon to a directory display
-de.ro.NoPathError:Symbol in ein Verzeichnisfenster ziehen um zu Speichern.
-fr.ro.NoPathError:Pour sauver, lâcher cette icône dans une fenêtre de Filer
-it.ro.NoPathError:Per salvare, trascina l'icona in una directory di visualizzazione.
-nl.ro.NoPathError:Het symbool naar een geopende mapvenster slepen om te bewaren.
-en.all.NoNameError:Please enter a name
-de.all.NoNameError:Bitte einen Namen eingeben.
-fr.all.NoNameError:Entrez un nom SVP
-it.all.NoNameError:Inserisci un nome
-nl.all.NoNameError:Geef een naam op
-en.all.NoURLError:Please enter a URL
-de.all.NoURLError:Bitte eine URL Adresse eingeben.
-fr.all.NoURLError:Entrez une URL SVP
-it.all.NoURLError:Inserisci un URL
-nl.all.NoURLError:Geef een adres op
-en.all.URIError:NetSurf was unable to parse this URI file due to a syntax error.
-de.all.URIError:NetSurf konnte die URI Datei nicht lesen. Syntax Fehler.
-fr.all.URIError:NetSurf est incapable de traiter ce fichier URI à cause d'une erreur de syntaxe.
-it.all.URIError:NetSurf non è stato in grado di processare questo file URI a causa di un errore di sintassi.
-nl.all.URIError:NetSurf kon dit URI-bestand niet verwerken vanwege een syntaxisfout.
-en.all.EmptyError:file is empty.
-de.all.EmptyError:Die Datei ist leer.
-fr.all.EmptyError:Le fichier est vide.
-it.all.EmptyError:Il file è vuoto.
-nl.all.EmptyError:bestand is leeg.
-en.all.SearchError:Invalid Search.
-de.all.SearchError:Suche fehlerhaft.
-fr.all.SearchError:Recherche Non-Valide.
-it.all.SearchError:Ricerca non valida.
-nl.all.SearchError:Ongeldige zoekopdracht.
-en.all.PrintErrorRO2:It appears that the printer is busy.
-de.all.PrintErrorRO2:Der Drucker scheint beschäftigt zu sein.
-fr.all.PrintErrorRO2:Il semble que l'imprimante soit occupée.
-it.all.PrintErrorRO2:La stampante sembra essere occupata.
-nl.all.PrintErrorRO2:De printer lijkt al bezig te zijn.
-en.ro.AWNotSeen:Please locate the AWViewer application and try again.
-de.ro.AWNotSeen:Das Programm AWViewer wurde nicht gefunden.
-fr.ro.AWNotSeen:Localisez l'application AMViewer SVP puis réessayez.
-it.ro.AWNotSeen:Per favore fornisci l'applicativo AWViewer e riprova nuovamente.
-nl.ro.AWNotSeen:Initialiseer het AWViewer-programma door het op te zoeken en probeer het dan nog eens.
-en.all.EncNotRec:Encoding type not recognised.
-de.all.EncNotRec:Encodierung nicht erkannt.
-fr.all.EncNotRec:Type de codage non reconnu.
-it.all.EncNotRec:Tipo di codifica sconosciuta.
-nl.all.EncNotRec:Codeertype is niet herkend.
-en.all.FileOpenError:could not open file '%s'
-de.all.FileOpenError:Datei ist nicht zu öffnen: '%s'
-fr.all.FileOpenError:ne parvient pas à ouvrir le fichier '%s'
-it.all.FileOpenError:Impossibile aprire il file '%s'
-nl.all.FileOpenError:kan bestand '%s' niet openen
-en.all.DirectoryError:directory '%s' already exists
-de.all.DirectoryError:Verzeichnis '%s' existiert bereits.
-fr.all.DirectoryError:répertoire '%s' existe déjà
-it.all.DirectoryError:La directory '%s' è già esistente
-nl.all.DirectoryError:map '%s' bestaat reeds
-
-en.ro.SprIsNull:Unable to convert image to sprite
-de.ro.SprIsNull:Bild nicht in Sprite konvertierbar
-nl.ro.SprIsNull:Afbeelding kan niet worden omgezet in een sprite.
-
-# Error messages for Amiga version only
-en.ami.CompError:Unable to open
-de.ami.CompError:Nicht zu öffnen
-fr.ami.CompError:Unable to open
-it.ami.CompError:Impossibile aprire
-nl.ami.CompError:Niet te openen
-en.ami.BMConvErr:NetSurf requires guigfx.library to display images in this mode
-de.ami.BMConvErr:NetSurf benötigt die guigfx.library für Bilder in diesem Mode
-fr.ami.BMConvErr:NetSurf requires guigfx.library to display images in this mode
-it.ami.BMConvErr:NetSurf richiede guigfx.library per la visualizzazione delle immagini in questa modalità
-nl.ami.BMConvErr:NetSurf requires guigfx.library to display images in this mode
-en.ami.MultiTabClose:Are you sure you want to close multiple tabs?
-de.ami.MultiTabClose:Wirklich mehrere Tabs schließen?
-fr.ami.MultiTabClose:Are you sure you want to close multiple tabs?
-it.ami.MultiTabClose:Sono rimaste aperte più schede, sei sicuro di voler uscire da NetSurf?
-nl.ami.MultiTabClose:Er zijn meerdere tabbladen geopend. Tabbladen allemaal sluiten?
-en.ami.TCPIPShutdown:The TCP/IP stack has signalled that it is about to shutdown and NetSurf must exit. NetSurf will quit in 5 seconds unless this shutdown is aborted.
-de.ami.TCPIPShutdown:Der TCP/IP Stack geht grad' zur Hölle und reißt Netsurf mit sich. In genau 5 Sekunden - es sei denn, der Shutdown wird abgebrochen.
-fr.ami.TCPIPShutdown:The TCP/IP stack has signalled that it is about to shutdown and NetSurf must exit. NetSurf will quit in 5 seconds unless this shutdown is aborted.
-it.ami.TCPIPShutdown:Lo stack TCP/IP ha dato segnale di essere in procinto di arresto, NetSurf verrà chiuso. NetSurf si chiuderà entro 5 secondi a meno che lo shutdown non venga interrotto.
-nl.ami.TCPIPShutdown:De TCP/IP-stack meldt dat deze wordt afgesloten waardoor NetSurf gestopt moet worden. NetSurf zal stoppen in 5 seconden, tenzij het afsluiten wordt afgebroken.
-en.ami.AbortShutdown:Abort shutdown
-de.ami.AbortShutdown:Shutdown abbrechen
-fr.ami.AbortShutdown:Abort shutdown
-it.ami.AbortShutdown:Interrompi lo shutdown
-nl.ami.AbortShutdown:Afsluiten afbreken
-
-
-# Queries
-# =======
-#
-# This section contains queries which are displayed to the user
-#
-
-en.all.AbortDownload:Are you sure you wish to abort this download?
-de.all.AbortDownload:Soll das Herunterladen der Datei wirklich abgebrochen werden ?
-fr.all.AbortDownload:Étes-vous sûr de vouloir interrompre ce téléchargement ?
-it.all.AbortDownload:Sei sicuro di voler annullare questo trasferimento?
-nl.all.AbortDownload:Zeker weten dat deze ophaalopdracht afgebroken moet worden?
-en.all.QuitDownload:One or more downloads are still in progress. Are you sure you wish to quit?
-de.all.QuitDownload:Das Herunterladen ein oder mehrerer Dateien wurde noch nicht abgeschlossen. Soll NetSurf trotzdem beendet werden ?
-fr.all.QuitDownload:Un ou plusieurs téléchargements sont en cours. Êtes-vous sûr de vouloir quitter ?
-it.all.QuitDownload:Uno o più file si trovano in fase di scaricamento, sei sicuro di voler chiudere NetSurf?
-nl.all.QuitDownload:Eén of meer ophaalopdrachten zijn nog in uitvoering. Toch afbreken?
-en.all.OverwriteFile:A file with that name already exists and would be lost.
-de.all.OverwriteFile:Eine Datei mit diesem Namen existiert bereits und würde überschrieben werden.
-fr.all.OverwriteFile:Un fichier portant ce nom existe déjà et serait perdu.
-it.all.OverwriteFile:Un file con questo nome è già esistente, continuare comporterà la sovrascrittura del file originale.
-nl.all.OverwriteFile:Een bestand met deze naam bestaat al en zal door deze actie overschreven worden.
-en.all.RemoveHotlist:Are you sure you wish to remove this address from the hotlist?
-de.all.RemoveHotlist:Adresse wirklich aus der Hotlist entfernen?
-fr.all.RemoveHotlist:Êtes-vous sûr de vouloir supprimer l'adresse de la liste critique?
-it.all.RemoveHotlist:Sei sicuro di voler rimuovere questo indirizzo dai segnalibri?
-nl.all.RemoveHotlist:Zeker weten dat dit adres uit de favorietenlijst verwijderd moet worden?
-
-# Page fetching
-# =============
-#
-# This section contains messages which may be displayed whilst
-# fetching a page or other content
-#
-
-# Fetch status messages - displayed in status bar
-#
-en.all.Progress:%s of %s
-de.all.Progress:%s von %s
-fr.all.Progress:%s reçus de %s
-it.all.Progress:%s di %s
-nl.all.Progress:%s van %s
-en.all.ProgressU:%s
-de.all.ProgressU:%s
-fr.all.ProgressU:%s
-it.all.ProgressU:%s
-nl.all.ProgressU:%s
-en.all.RecPercent:Received %s (%u%%)
-de.all.RecPercent:Empfangen %s (%u%%)
-fr.all.RecPercent:%s (%u%%)
-it.all.RecPercent:ricevuti %s (%u%%)
-nl.all.RecPercent:ontvangen %s (%u%%)
-en.all.Received:Received %s
-de.all.Received:Empfangen %s
-fr.all.Received:%s reçus
-it.all.Received:ricevuti %s
-nl.all.Received:ontvangen %s
-en.all.Redirecting:Redirecting...
-de.all.Redirecting:Umleiten...
-fr.all.Redirecting:Redirection en cours...
-it.all.Redirecting:redirezione in corso...
-nl.all.Redirecting:doorverwijzen...
-en.all.Loading:Loading
-de.all.Loading:Laden
-fr.all.Loading:Chargement
-it.all.Loading:Caricamento della pagina...
-nl.all.Loading:laden
-en.all.Fetching:Fetching data
-de.all.Fetching:Daten holen
-fr.all.Fetching:Récupération des données
-it.all.Fetching:Ricezione
-nl.all.Fetching:ophalen
-en.all.Processing:Processing
-de.all.Processing:Auswerten
-fr.all.Processing:Traitement
-it.all.Processing:elaborazione del documento in corso...
-nl.all.Processing:verwerking
-en.all.Formatting:Formatting
-de.all.Formatting:Formatieren
-fr.all.Formatting:Formatage
-it.all.Formatting:formattazione del documento in corso...
-nl.all.Formatting:opmaken
-en.all.Done:Done
-de.all.Done:Fertiggestellt
-fr.all.Done:Terminé
-it.all.Done:Completato
-nl.all.Done:klaar
-en.all.Stopped:Stopped
-de.all.Stopped:Angehalten
-fr.all.Stopped:Arrêté
-it.all.Stopped:Interrotto
-nl.all.Stopped:gestopt
-
-# Fetch warning/error messages - displayed in status bar
-#
-en.all.BadRedirect:Bad redirect URL
-de.all.BadRedirect:Falsche URL für Redirect
-fr.all.BadRedirect:Mauvais URL de redirection
-it.all.BadRedirect:Errata redirezione dell'URL
-nl.all.BadRedirect:foutief doorverwijzen naar adres
-en.all.FetchFailed:Unable to fetch document
-de.all.FetchFailed:Kann Dokument nicht fetchen
-fr.all.FetchFailed:Récupération du fichier impossible
-it.all.FetchFailed:Impossibile ottenere il documento
-nl.all.FetchFailed:Dit document kan niet worden opgehaald.
-en.all.NotCSS:Warning: stylesheet is not CSS
-de.all.NotCSS:Warnung:Stylesheet ist kein CSS
-fr.all.NotCSS:Attention: feuille de style non CSS
-it.all.NotCSS:Attenzione: La dicitura "Foglio di stile" non ha nulla a che vedere con i CSS
-nl.all.NotCSS:melding: stijlblad is geen CSS
-en.all.NotFavIco:Favicon not supported
-de.all.NotFavIco:Favicon wird nicht unterstützt
-fr.all.NotFavIco:Favicon non-soutenu
-it.all.NotFavIco:Favicon non supportata
-nl.all.NotFavIco:websitesymbool wordt niet ondersteund
-en.all.BadObject:Warning: bad object type
-de.all.BadObject:Warnung: falscher Objekttyp
-fr.all.BadObject:Attention: mauvais type d'objet
-it.all.BadObject:Errore nell'analisi del tipo di oggetto
-nl.all.BadObject:melding: fout objecttype
-en.all.ObjError:Error loading object: %s
-de.all.ObjError:Fehler beim Laden des Objektes: %s
-fr.all.ObjError:Erreur lors du chargement de: %s
-it.all.ObjError:Errore nel caricamento dell'oggetto: %s
-nl.all.ObjError:fout bij het laden object: %s
-en.all.ParsingFail:Parsing the document failed.
-de.all.ParsingFail:Dokumentparsing ist fehlgeschlagen.
-fr.all.ParsingFail:L'analyse syntaxique du document a échoué.
-it.all.ParsingFail:Analisi del documento fallita.
-nl.all.ParsingFail:fout bij ontleden van dit document.
-en.all.CSSGeneric:Error processing CSS
-de.all.CSSGeneric:CSS Auswertung klappt nicht
-fr.all.CSSGeneric:Erreur lors du traitement CSS
-nl.all.CSSGeneric:fout bij het verwerken van de CSS
-it.all.CSSGeneric:Errore nell'elaborazione del CSS
-
-en.all.CSSBase:Base stylesheet failed to load
-fr.all.CSSBase:Échec de chargement de la feuille de style de base
-nl.all.CSSBase:basisstijlblad kan niet worden geladen
-it.all.CSSBase:Impossibile caricare il foglio di stile base
-
-en.all.BadGIF:Reading GIF failed.
-de.all.BadGIF:Lesen einer GIF Datei fehlgeschlagen.
-fr.all.BadGIF:Erreur de lecture de GIF.
-it.all.BadGIF:Lettura del file GIF fallita.
-nl.all.BadGIF:fout bij lezen GIF.
-en.all.BadBMP:Reading BMP failed.
-de.all.BadBMP:Lesen einer BMP Datei fehlgeschlagen.
-fr.all.BadBMP:Erreur de lecture de BMP.
-it.all.BadBMP:Lettura del file BMP fallita.
-nl.all.BadBMP:fout bij lezen BMP.
-en.all.BadICO:Reading ICO failed.
-de.all.BadICO:Lesen einer ICO Datei fehlgeschlagen.
-fr.all.BadICO:Erreur de lecture de ICO.
-it.all.BadICO:Lettura del file ICO fallita.
-nl.all.BadICO:fout bij lezen ICO.
-en.all.PNGError:Error converting PNG.
-de.all.PNGError:Fehler beim PNG konvertieren.
-fr.all.PNGError:Error converting PNG.
-it.all.PNGError:Errore durante la conversione PNG.
-nl.all.PNGError:fout bij omzetting PNG.
-en.all.MNGError:Error converting MNG/PNG/JNG: %i
-de.all.MNGError:MNG Library Fehler: %i
-fr.all.MNGError:Erreur dans la bibliothèque MNG: %i
-it.all.MNGError:Errore durante la conversione MNG/PNG/JNG: %i
-nl.all.MNGError:MNG-bibliotheekfout: %i
-en.all.BadSprite:Invalid or corrupt Sprite data.
-de.all.BadSprite:Ungültiges oder beschädigtes Sprite.
-fr.all.BadSprite:Les données du sprite sont invalides ou corrompues.
-it.all.BadSprite:Dati del file Sprite invalidi o corrotti.
-nl.all.BadSprite:foutief sprite-bestand.
-
-# HTTP status codes
-#
-en.all.HTTP0:OK
-de.all.HTTP0:OK
-fr.all.HTTP0:OK
-it.all.HTTP0:OK
-nl.all.HTTP0:OK
-en.all.HTTP200:OK
-de.all.HTTP200:OK
-fr.all.HTTP200:OK
-it.all.HTTP200:OK
-nl.all.HTTP200:OK
-en.all.HTTP201:Created
-de.all.HTTP201:Created
-fr.all.HTTP201:Créé
-it.all.HTTP201:Creato
-nl.all.HTTP201:Aangemaakt
-en.all.HTTP202:Accepted
-de.all.HTTP202:Accepted
-fr.all.HTTP202:Accepté
-it.all.HTTP202:Accettato
-nl.all.HTTP202:Aanvaard
-en.all.HTTP203:Non-authoritative information
-de.all.HTTP203:Non-authoritative information
-fr.all.HTTP203:Information ne faisant pas autorité
-it.all.HTTP203:Informazione non autorevole
-nl.all.HTTP203:Niet-gemachtigde informatie
-en.all.HTTP204:No content
-de.all.HTTP204:No content
-fr.all.HTTP204:Pas de contenu
-it.all.HTTP204:Nessun contenuto
-nl.all.HTTP204:Geen inhoud
-en.all.HTTP205:Reset content
-de.all.HTTP205:Reset content
-fr.all.HTTP205:Remise-à-Zéro du contenu
-it.all.HTTP205:Resetta contenuto
-nl.all.HTTP205:Inhoud opnieuw instellen
-en.all.HTTP206:Partial content
-de.all.HTTP206:Partial content
-fr.all.HTTP206:Contenu partiel
-it.all.HTTP206:Contenuto parziale
-nl.all.HTTP206:Gedeeltelijke inhoud
-en.all.HTTP300:Multiple choices
-de.all.HTTP300:Multiple choices
-fr.all.HTTP300:Choix multiples
-it.all.HTTP300:Scelte multiple
-nl.all.HTTP300:Meerkeuze
-en.all.HTTP301:Moved permanently
-de.all.HTTP301:Moved permanently
-fr.all.HTTP301:A déménagé définitivement
-it.all.HTTP301:Rimosso permanentemente
-nl.all.HTTP301:Definitief verplaatst
-en.all.HTTP302:Found
-de.all.HTTP302:Found
-fr.all.HTTP302:Trouvé
-it.all.HTTP302:Trovato
-nl.all.HTTP302:Gevonden
-en.all.HTTP303:See other
-de.all.HTTP303:See other
-fr.all.HTTP303:Voir autre
-it.all.HTTP303:Mostra altro
-nl.all.HTTP303:Zie andere
-en.all.HTTP304:Not modified
-de.all.HTTP304:Not modified
-fr.all.HTTP304:Pas modifié
-it.all.HTTP304:Non modificato
-nl.all.HTTP304:Niet gewijzigd
-en.all.HTTP305:Use proxy
-de.all.HTTP305:Use proxy
-fr.all.HTTP305:Utilisez un proxy
-it.all.HTTP305:Usa Proxy
-nl.all.HTTP305:Gebruik Proxy
-en.all.HTTP307:Temporary redirect
-de.all.HTTP307:Temporary redirect
-fr.all.HTTP307:Redirection temporaire
-it.all.HTTP307:Redirezione temporanea
-nl.all.HTTP307:Tijdelijke omleiding
-en.all.HTTP400:Bad request
-de.all.HTTP400:Bad request
-fr.all.HTTP400:Mauvaise requête
-it.all.HTTP400:Richiesta errata
-nl.all.HTTP400:Foute aanvraag
-en.all.HTTP401:Unauthorized
-de.all.HTTP401:Unauthorized
-fr.all.HTTP401:Sans autorisation
-it.all.HTTP401:Autorizzazione negata
-nl.all.HTTP401:Niet geautoriseerd
-en.all.HTTP402:Payment required
-de.all.HTTP402:Payment required
-fr.all.HTTP402:Paiment nécessaire
-it.all.HTTP402:Richiesto di pagamento
-nl.all.HTTP402:Betalende toegang
-en.all.HTTP403:Forbidden
-de.all.HTTP403:Forbidden
-fr.all.HTTP403:Interdit
-it.all.HTTP403:Vietato
-nl.all.HTTP403:Verboden toegang
-en.all.HTTP404:Not found
-de.all.HTTP404:Not found
-fr.all.HTTP404:Pas trouvé
-it.all.HTTP404:Non trovato
-nl.all.HTTP404:Niet gevonden
-en.all.HTTP405:Method not allowed
-de.all.HTTP405:Method not allowed
-fr.all.HTTP405:Méthode non autorisée
-it.all.HTTP405:Metodo non permesso
-nl.all.HTTP405:Methode niet toegestaan
-en.all.HTTP406:Not acceptable
-de.all.HTTP406:Not acceptable
-fr.all.HTTP406:Pas acceptable
-it.all.HTTP406:Non accettabile
-nl.all.HTTP406:Niet aanvaardbaar
-en.all.HTTP407:Proxy authentication required
-de.all.HTTP407:Proxy authentication required
-fr.all.HTTP407:Authentification du proxy nécessaire
-it.all.HTTP407:Autentificazione Proxy necessaria
-nl.all.HTTP407:Authenticatie op de proxy-server verplicht
-en.all.HTTP408:Request timeout
-de.all.HTTP408:Request timeout
-fr.all.HTTP408:Délai de requête trop long
-it.all.HTTP408:Timeout della richiesta
-nl.all.HTTP408:Aanvraagtijd verstreken
-en.all.HTTP409:Conflict
-de.all.HTTP409:Conflict
-fr.all.HTTP409:Conflit
-it.all.HTTP409:Conflitto
-nl.all.HTTP409:Conflict
-en.all.HTTP410:Gone
-de.all.HTTP410:Gone
-fr.all.HTTP410:Parti
-it.all.HTTP410:Irraggiungibile
-nl.all.HTTP410:Verdwenen
-en.all.HTTP411:Length required
-de.all.HTTP411:Length required
-fr.all.HTTP411:Longueur nécessaire
-it.all.HTTP411:Lunghezza richiesta
-nl.all.HTTP411:Lengte benodigd
-en.all.HTTP412:Precondition failed
-de.all.HTTP412:Precondition failed
-fr.all.HTTP412:Échec de précondition
-it.all.HTTP412:Precondizione fallita
-nl.all.HTTP412:Niet voldaan aan vooraf gestelde voorwaarde
-en.all.HTTP413:Request entity too large
-de.all.HTTP413:Request entity too large
-fr.all.HTTP413:Demande d'entité trop grande
-it.all.HTTP413:Entità richiesta troppo larga
-nl.all.HTTP413:Aanvraag te groot
-en.all.HTTP414:Request-URI too long
-de.all.HTTP414:Request-URI too long
-fr.all.HTTP414:Request-URI trop long
-it.all.HTTP414:Richiesta URI troppo lunga
-nl.all.HTTP414:Aanvraagadres te lang
-en.all.HTTP415:Unsupported media type
-de.all.HTTP415:Unsupported media type
-fr.all.HTTP415:Type de média non supporté
-it.all.HTTP415:Tipo di media non supportato
-nl.all.HTTP415:Media-type niet ondersteund
-en.all.HTTP416:Requested range not satisfiable
-de.all.HTTP416:Requested range not satisfiable
-fr.all.HTTP416:Étendue demandée non satisfaisable
-it.all.HTTP416:Estensione richiesta non soddisfabile
-nl.all.HTTP416:Aangevraagd gedeelte niet opvraagbaar
-en.all.HTTP417:Expectation failed
-de.all.HTTP417:Expectation failed
-fr.all.HTTP417:Attente non satisfaite
-it.all.HTTP417:Previsione fallita
-nl.all.HTTP417:Niet voldaan aan verwachting
-en.all.HTTP500:Internal server error
-de.all.HTTP500:Internal server error
-fr.all.HTTP500:Erreur interne du serveur
-it.all.HTTP500:Errore interno del server
-nl.all.HTTP500:Interne serverfout
-en.all.HTTP501:Not implemented
-de.all.HTTP501:Not implemented
-fr.all.HTTP501:Non implémenté
-it.all.HTTP501:Non implementata
-nl.all.HTTP501:Niet geïmplementeerd
-en.all.HTTP502:Bad gateway
-de.all.HTTP502:Bad gateway
-fr.all.HTTP502:Mauvaise passerelle
-it.all.HTTP502:Gateway errato
-nl.all.HTTP502:Ongeldige Gateway
-en.all.HTTP503:Service unavailable
-de.all.HTTP503:Service unavailable
-fr.all.HTTP503:Service non disponible
-it.all.HTTP503:Servizio non disponibile
-nl.all.HTTP503:Dienst niet beschikbaar
-en.all.HTTP504:Gateway timeout
-de.all.HTTP504:Gateway timeout
-fr.all.HTTP504:Délai passerelle expiré
-it.all.HTTP504:Timeout Gateway
-nl.all.HTTP504:Aanvraagtijd bij Gateway verstreken
-en.all.HTTP505:HTTP version not supported
-de.all.HTTP505:HTTP version not supported
-fr.all.HTTP505:version HTTP non supportée
-it.all.HTTP505:Versione HTTP non supportata
-nl.all.HTTP505:HTTP-versie wordt niet ondersteund
-
# User interface
# ==============
#
@@ -3694,74 +5439,100 @@ de.all.ScrollUp:Pfeil anklicken zum Hochscrollen
fr.all.ScrollUp:Cliquer sur la flèche pour faire défiler vers le haut
it.all.ScrollUp:Clicca sulla freccia per scrollare in alto
nl.all.ScrollUp:Klik op de pijl om omhoog te gaan
+zh_CN.all.ScrollUp:点击箭头å‘上滚动页é¢
+
en.all.ScrollPUp:Click to scroll up one page
de.all.ScrollPUp:Anklicken scrollt eine Seite hoch
-fr.all.ScrollPUp:Cliquer pour faire défiler d'une page vers le haut
+fr.all.ScrollPUp:Cliquer pour faire défiler d’une page vers le haut
it.all.ScrollPUp:Clicca per scrollare in alto di una pagina
nl.all.ScrollPUp:Klik om 1 pagina omhoog te gaan
+zh_CN.all.ScrollPUp:点击å‘上滚动一页
+
en.all.ScrollV:Drag the bar to scroll vertically
de.all.ScrollV:Ziehen der Leiste scrollt vertikal
-fr.all.ScrollV:Tirez la barre pour la faire défiler verticalement
+fr.all.ScrollV:Tirez sur la barre pour faire défiler verticalement
it.all.ScrollV:Trascina la barra per scrollare verticalmente
nl.all.ScrollV:Verschuif de balk om verticaal over de pagina te gaan
+zh_CN.all.ScrollV:拖动æ åž‚直滚动
+
en.all.ScrollPDown:Click to scroll down one page
de.all.ScrollPDown:Anklicken scrollt eine Seite nach unten
-fr.all.ScrollPDown:Cliquer pour faire défiler d'une page vers le bas
+fr.all.ScrollPDown:Cliquer pour faire défiler d’une page vers le bas
it.all.ScrollPDown:Clicca per scrollare in basso di una pagina
nl.all.ScrollPDown:Klik om 1 pagina omlaag te gaan
+zh_CN.all.ScrollPDown:点击å‘下滚动一页
+
en.all.ScrollDown:Click the arrow to scroll down
de.all.ScrollDown:Pfeil anklicken zum Herunterscrollen
fr.all.ScrollDown:Cliquer sur la flèche pour faire défiler vers le bas
it.all.ScrollDown:Clicca sulla freccia per scrollare in basso
nl.all.ScrollDown:Klik op de pijl om omlaag te gaan
+zh_CN.all.ScrollDown:点击箭头å‘下滚动页é¢
+
en.all.ScrollLeft:Click the arrow to scroll left
de.all.ScrollLeft:Pfeil anklicken scrollt links
fr.all.ScrollLeft:Cliquer sur la flèche pour faire défiler vers la gauche
it.all.ScrollLeft:Clicca sulla freccia per scrollare a sinistra
nl.all.ScrollLeft:Klik op de pijl om naar links te gaan
+zh_CN.all.ScrollLeft:点击箭头å‘左滚动页é¢
+
en.all.ScrollPLeft:Click to scroll left one page
de.all.ScrollPLeft:Anklicken scrollt eine Seite nach links
-fr.all.ScrollPLeft:Cliquer pour faire défiler d'une page vers la gauche
+fr.all.ScrollPLeft:Cliquer pour faire défiler d’une page vers la gauche
it.all.ScrollPLeft:Clicca per scrollare a sinistra di una pagina
nl.all.ScrollPLeft:Klik om 1 pagina naar links te gaan
+zh_CN.all.ScrollPLeft:点击å‘左滚动一页
+
en.all.ScrollH:Drag the bar to scroll horizontally
de.all.ScrollH:Ziehen der Leiste scrollt horizontal
-fr.all.ScrollH:Tirez la barre pour la faire défiler horizontalement
+fr.all.ScrollH:Tirez sur la barre pour faire défiler horizontalement
it.all.ScrollH:Trascina la barra per scrollare orizzontalmente
nl.all.ScrollH:Verschuif de balk om horizontaal over de pagina te gaan
+zh_CN.all.ScrollH:拖动æ æ°´å¹³æ»šåŠ¨
+
en.all.ScrollPRight:Click to scroll right one page
de.all.ScrollPRight:Anklicken scrollt eine Seite nach rechts
-fr.all.ScrollPRight:Cliquer pour faire défiler d'une page vers la droite
+fr.all.ScrollPRight:Cliquer pour faire défiler d’une page vers la droite
it.all.ScrollPRight:Clicca per scrollare a destra di una pagina
nl.all.ScrollPRight:Klik om 1 pagina naar rechts te gaan
+zh_CN.all.ScrollPRight:点击å‘å³æ»šåŠ¨ä¸€é¡µ
+
en.all.ScrollRight:Click the arrow to scroll right
de.all.ScrollRight:Pfeil anklicken scrollt rechts
fr.all.ScrollRight:Cliquer sur la flèche pour faire défiler vers la droite
it.all.ScrollRight:Clicca sulla freccia per scrollare a destra
nl.all.ScrollRight:Klik op de pijl om naar rechts te gaan
+zh_CN.all.ScrollRight:点击箭头å‘å³æ»šåŠ¨é¡µé¢
+
en.all.ScrollBoth:Move your mouse while keeping the button pressed to scroll the content
de.all.ScrollBoth:Bewege die Maus bei gedrückten Mausknopf zum Scrollen des Inhalts
fr.all.ScrollBoth:Déplacer la souris tout en maintenant le bouton enfoncé pour faire défiler le contenu
it.all.ScrollBoth:Sposta il mouse tenendo premuto il tasto sinistro per scrollare il contenuto della pagina
nl.all.ScrollBoth:Verplaats de muis met ingedrukte muisknop om de vensterinhoud te verplaatsen
+zh_CN.all.ScrollBoth:在按ä½æŒ‰é’®çš„åŒæ—¶ç§»åŠ¨é¼ æ ‡æ¥æ»šåŠ¨æµè§ˆå†…容
# Select menu - displayed in status bar
#
en.all.SelectClick:Click on entry to select it
de.all.SelectClick:Anklicken um auszuwählen
-fr.all.SelectClick:Cliquer sur l'entrée pour la sélectionner
+fr.all.SelectClick:Cliquer sur une entrée pour la sélectionner
it.all.SelectClick:Clicca sull'elemento per selezionarlo
nl.all.SelectClick:Klik op een item om het te selecteren.
+zh_CN.all.SelectClick:点击æ¡ç›®å°†å…¶é€‰ä¸­
+
en.all.SelectMClick:Click on entry to select it, multiple options can be selected
de.all.SelectMClick:Anklicken um auszuwählen, auch mehrere Optionen sind auswählbar
-fr.all.SelectMClick:Cliquer sur l'entrée pour la sélectionner, plusieurs options peuvent être sélectionnées
+fr.all.SelectMClick:Cliquer sur une entrée pour la sélectionner, plusieurs options peuvent être sélectionnées
it.all.SelectMClick:Clicca sull'elemento per selezionarlo, sono supportate le scelte multiple
nl.all.SelectMClick:Klik op een item om het te selecteren, er kunnen meerdere opties tegelijkertijd geselecteerd worden
+zh_CN.all.SelectMClick:点击æ¡ç›®å°†å…¶é€‰ä¸­ï¼Œå¯ä»¥é€‰æ‹©å¤šä¸ªé€‰é¡¹
+
en.all.SelectClose:Click to close the select menu
de.all.SelectClose:Anklicken zum Schließen des Menus
fr.all.SelectClose:Cliquer pour fermer le menu de sélection
it.all.SelectClose:Clicca per chiudere l'elemento selezionato
nl.all.SelectClose:Klik om het geselecteerde menu te sluiten
+zh_CN.all.SelectClose:点击关闭选择èœå•
# Saving
# ======
@@ -3771,34 +5542,45 @@ nl.all.SelectClose:Klik om het geselecteerde menu te sluiten
en.all.SaveSource:Source
de.all.SaveSource:Quellcode
-fr.all.SaveSource:Source
+fr.all.SaveSource:Code source
it.all.SaveSource:Sorgente
nl.all.SaveSource:Bron
+zh_CN.all.SaveSource:ä¿å­˜æºä»£ç 
+
en.all.SaveDraw:Webpage
de.all.SaveDraw:Webseite
-fr.all.SaveDraw:PageWeb
+fr.all.SaveDraw:Page Web
it.all.SaveDraw:Pagina Web
nl.all.SaveDraw:Webpagina
+zh_CN.all.SaveDraw:ä¿å­˜ç½‘页绘图
+
en.all.SaveText:Webpage
de.all.SaveText:Webseite
-fr.all.SaveText:PageWeb
+fr.all.SaveText:Page Web
it.all.SaveText:Pagina Web
nl.all.SaveText:Webpagina
+zh_CN.all.SaveText:ä¿å­˜ç½‘页文本
+
en.all.SaveObject:Object
de.all.SaveObject:Objekt
fr.all.SaveObject:Objet
it.all.SaveObject:Oggetto
nl.all.SaveObject:Object
+zh_CN.all.SaveObject:ä¿å­˜å¯¹è±¡
+
en.all.SaveLink:Link
de.all.SaveLink:Link
fr.all.SaveLink:Lien
it.all.SaveLink:Link
nl.all.SaveLink:Koppeling
+zh_CN.all.SaveLink:ä¿å­˜é“¾æŽ¥
+
en.all.SaveSelection:Selection
de.all.SaveSelection:Auswahl
-fr.all.SaveSelection:Texte
+fr.all.SaveSelection:Sélection
it.all.SaveSelection:Selezione
nl.all.SaveSelection:Selectie
+zh_CN.all.SaveSelection:ä¿å­˜é€‰é¡¹
# Themes
# ======
@@ -3808,123 +5590,52 @@ nl.all.SaveSelection:Selectie
en.all.ThemeInstActive:A theme is currently being downloaded or installed. Please wait for it to finish or cancel it before installing more themes.
de.all.ThemeInstActive:Ein Thema wird gerade geladen oder installiert. Bitte vor Installation weiterer Themen diesen Vorgang abwarten oder beenden.
-fr.all.ThemeInstActive:Un thème est en cours de téléchargement ou d'installation. Veuillez attendre que ce soit fini ou annulez l'opération avant d'installer de nouveaux thèmes.
+fr.all.ThemeInstActive:Un thème est en cours de téléchargement ou d’installation. Veuillez attendre que ce soit fini ou annulez l’opération avant d’installer de nouveaux thèmes.
it.all.ThemeInstActive:Il tema è attualmente in fase di scaricamento o di installazione. Attendere il completamente del processo oppure annullare l'intera operazione prima di installare altri temi.
nl.all.ThemeInstActive:Een thema wordt momenteel opgehaald of geïnstalleerd. Wacht tot het is geïnstalleerd of annuleer de opdracht voordat meer thema's geïnstalleerd worden.
+zh_CN.all.ThemeInstActive:主题正在下载或安装中。在安装更多主题之å‰ï¼Œè¯·ç­‰å¾…其完æˆæˆ–å–消任务。
+
en.all.ThemeInstDown:Please wait for the theme to download.
de.all.ThemeInstDown:Bitte warten bis das Thema vollständig heruntergeladen wurde.
-fr.all.ThemeInstDown:Veuillez attendre le téléchargement du thème.
+fr.all.ThemeInstDown:Veuillez attendre la fin du téléchargement du thème.
it.all.ThemeInstDown:Per favore attendere lo scaricamento del tema grafico.
nl.all.ThemeInstDown:Wacht tot het thema is opgehaald.
+zh_CN.all.ThemeInstDown:请等待下载主题。
+
en.all.ThemeInvalid:The downloaded theme is invalid or requires a newer version of NetSurf.
de.all.ThemeInvalid:Das geladene Thema ist fehlerhaft oder benötigt eine neuere Version von NetSurf.
fr.all.ThemeInvalid:Le thème téléchargé est invalide ou nécessite une version plus récente de NetSurf.
it.all.ThemeInvalid:Il tema scaricato non è compatibile oppure richiede una versione più recente di NetSurf.
nl.all.ThemeInvalid:Het opgehaalde thema is niet (meer) in orde of vereist een nieuwere NetSurf-versie.
+zh_CN.all.ThemeInvalid:下载的主题无效或需è¦ä½¿ç”¨æ›´é«˜ç‰ˆæœ¬çš„ NetSurf。
+
en.all.ThemeInstall:Would you like to install the theme '%s' by %s?
de.all.ThemeInstall:Soll das Thema '%s' von %s installiert werden ?
-fr.all.ThemeInstall:Voulez-vous installer le thème '%s' par %s?
+fr.all.ThemeInstall:Voulez-vous installer le thème « %s » créé par %s ?
it.all.ThemeInstall:Si desidera installare il tema '%s' di %s?
nl.all.ThemeInstall:Moet het thema '%s' geïnstalleerd worden door %s?
+zh_CN.all.ThemeInstall:是å¦è¦ç”± %2$s 安装主题“%1$sâ€ï¼Ÿ
+
en.all.ThemeInstallErr:An error occurred whilst trying to install the downloaded theme.
de.all.ThemeInstallErr:Beim Installieren des geladenen Themas trat ein Fehler auf.
-fr.all.ThemeInstallErr:Une erreur s'est produite pendant l'installation du thème téléchargé.
+fr.all.ThemeInstallErr:Une erreur s’est produite pendant l’installation du thème téléchargé.
it.all.ThemeInstallErr:Si è verificato un errore durante il tentativo di installazione del tema scaricato
nl.all.ThemeInstallErr:Een fout ontstond tijdens het installeren van het opgehaalde thema.
+zh_CN.all.ThemeInstallErr:å°è¯•å®‰è£…下载的主题时å‘生错误。
+
en.all.ThemeApplyErr:An error occurred whilst trying to apply the downloaded theme.
de.all.ThemeApplyErr:Beim Versuch der Anwendung eines geladenen Themas trat ein Fehler auf.
-fr.all.ThemeApplyErr:Une erreur s'est produite en essayant d'appliquer le thème téléchargé.
+fr.all.ThemeApplyErr:Une erreur s’est produite en essayant d’appliquer le thème téléchargé.
it.all.ThemeApplyErr:Si è verificato un errore durante il tentativo di applicazione del tema
nl.all.ThemeApplyErr:Een fout ontstond tijdens het toevoegen van het opgehaalde thema.
+zh_CN.all.ThemeApplyErr:å°è¯•åº”用下载的主题时å‘生错误。
-
-# General
-# =======
-#
-# Some general purpose words and phrases
-#
-
-en.all.Bytes: B
-de.all.Bytes: B
-fr.all.Bytes: octets
-it.all.Bytes: Byte
-nl.all.Bytes: B
-en.all.kBytes: kB
-de.all.kBytes: kB
-fr.all.kBytes: Ko
-it.all.kBytes: KB
-nl.all.kBytes: KB
-en.all.MBytes: MB
-de.all.MBytes: MB
-fr.all.MBytes: Mo
-it.all.MBytes: MB
-nl.all.MBytes: MB
-en.all.GBytes: GB
-de.all.GBytes: GB
-fr.all.GBytes: Go
-it.all.GBytes: GB
-nl.all.GBytes: GB
-
-en.all.Yes:Yes
-de.all.Yes:Ja
-fr.all.Yes:Oui
-it.all.Yes:Si
-nl.all.Yes:Ja
-en.all.No:No
-de.all.No:Nein
-fr.all.No:Non
-it.all.No:No
-nl.all.No:Nee
-en.all.Replace:Replace file
-de.all.Replace:Ãœberschreiben
-fr.all.Replace:Remplacer le fichier
-it.all.Replace:Sostituire il file
-nl.all.Replace:Vervang bestand
-en.all.DontReplace:Don't replace
-de.all.DontReplace:Abbrechen
-fr.all.DontReplace:Ne pas remplacer le fichier
-it.all.DontReplace:Non sostituire
-nl.all.DontReplace:Annuleer bewaaractie
-en.all.Remove:Remove address
-de.all.Remove:Adresse entfernen
-fr.all.Remove:Enlever/retirer une adresse
-it.all.Remove:Rimuovi indirizzo
-nl.all.Remove:Verwijder adres
-en.all.DontRemove:Don't remove
-de.all.DontRemove:Behalten
-fr.all.DontRemove:Ne pas enlever/retirer
-it.all.DontRemove:Non rimuovere
-nl.all.DontRemove:Niet verwijderen
-en.all.obj:object
-de.all.obj:Objekt
-fr.all.obj:objet
-it.all.obj:oggetto
-nl.all.obj:object
-en.all.objs:objects
-de.all.objs:Objekte
-fr.all.objs:objets
-it.all.objs:oggetti
-nl.all.objs:objecten
-en.all.styl:stylesheet
-de.all.styl:Formatvorlage
-fr.all.styl:feuille de styles
-it.all.styl:foglio di stile
-nl.all.styl:stijlblad
-en.all.styls:stylesheets
-de.all.styls:Formatvorlagen
-fr.all.styls:feuilles de styles
-it.all.styls:fogli di stile
-nl.all.styls:stijlbladen
-en.all.OK:OK
-de.all.OK:OK
-fr.all.OK:OK
-it.all.OK:OK
-nl.all.OK:OK
en.ami.More:More
de.ami.More:Mehr
-fr.ami.More:More
-it.ami.More:Di più
+fr.ami.More:Plus
+it.ami.More:Altro
nl.ami.More:Meer
+zh_CN.ami.More:更多
# Interactive help
@@ -3934,1105 +5645,1522 @@ nl.ami.More:Meer
#
en.ro.HelpToolbar0:\Tback button.|M\Straverse back one page in the history tree.|MDoes not resubmit form information.
de.ro.HelpToolbar0:Schaltet zurück auf die zuvor dargestellte Seite.|MDer Inhalt wird dabei nicht aktualisiert.
-fr.ro.HelpToolbar0:\Tle bouton de retour.|M\Srevenir d'une page en arrière dans l'historique.|MNe renvoie pas l'information de formulaire.
+fr.ro.HelpToolbar0:\Tle bouton de retour.|M\Srevenir d’une page en arrière dans l’historique.|MNe renvoie pas l’information de formulaire.
it.ro.HelpToolbar0:\Ttorna indietro di una pagina
nl.ro.HelpToolbar0:Dit is de Terug-knop.|MKlik met KIES om 1 pagina terug te gaan.|MKlik met PASAAN om 1 pagina terug te gaan en deze in een nieuw browservenster te openen.|MLet op! Formulieren worden niet nogmaals ingediend.
+zh_CN.ro.HelpToolbar0:\TåŽé€€é”®ã€‚|M\S在历å²è®°å½•æ ‘中å‘åŽé历一页。|Mä¸é‡æ–°æ交表å•ä¿¡æ¯ã€‚
+
en.ro.HelpToolbar1:\Tforward button.|M\Straverse forward one page in the history tree.|MDoes not resubmit form information.
de.ro.HelpToolbar1:Schaltet vorwärts auf die nächste Seite.|MDer Inhalt wird dabei nicht aktualisiert.
-fr.ro.HelpToolbar1:\Tle bouton d'avance.|M\Savancer d'une page dans l'historique.|MNe renvoie pas l'information de formulaire.
+fr.ro.HelpToolbar1:\Tle bouton d’avance.|M\Savancer d’une page dans l’historique.|MNe renvoie pas l’information de formulaire.
it.ro.HelpToolbar1:\Tvai avanti di una pagina
nl.ro.HelpToolbar1:Dit is de Vooruit-knop.|MKlik met KIES om 1 pagina vooruit te gaan.|MKlik met PASAAN om 1 pagina terug te gaan en deze in een nieuw browservenster te openen.|MLet op! Formulieren worden niet nogmaals ingediend.
+zh_CN.ro.HelpToolbar1:\Tå‰è¿›é”®ã€‚|M\S在历å²è®°å½•æ ‘中å‘å‰é历一页。|Mä¸é‡æ–°æ交表å•ä¿¡æ¯ã€‚
+
en.ro.HelpToolbar2:\Tstop button.|M\Sstop loading this page.
de.ro.HelpToolbar2:Das ist der Stop Schaltknopf.|MUnterbricht den Ladvorgang.
fr.ro.HelpToolbar2:\Tle bouton Stop.|M\Sarrêter le chargement de la page.
it.ro.HelpToolbar2:\Tinterrompi il caricamento della pagina
nl.ro.HelpToolbar2:Dit is de Stop-knop.|MKlik met KIES om het ophalen van deze pagina af te stoppen.
+zh_CN.ro.HelpToolbar2:\Tåœæ­¢é”®ã€‚|M\Såœæ­¢åŠ è½½é¡µé¢ã€‚
+
en.ro.HelpToolbar3:\Treload button.|M\Sreload this page.|M\Areload this page and any objects it contains.
de.ro.HelpToolbar3:Aktualisiert den Seiteninhalt.|MKlicken mit AUSWAHL lädt die Seite neu.|MKlicken mit SPEZIAL lädt die Seite und alle zugehörigen Objekte neu.
-fr.ro.HelpToolbar3:\Tle bouton de recharge.|M\Srecharger cette page.|M\Arecharger cette page et tous les objets qu'elle contient.
+fr.ro.HelpToolbar3:\Tle bouton de recharge.|M\Srecharger cette page.|M\Arecharger cette page et tous les objets qu’elle contient.
it.ro.HelpToolbar3:\Tricarica la pagina corrente
nl.ro.HelpToolbar3:Dit is de Herlaad-knop.|MKlik met KIES om deze pagina opnieuw op te halen.|MKlik met PASAAN om deze pagina opnieuw op te halen, inclusief alle objecten die deze pagina bevat.
+zh_CN.ro.HelpToolbar3:\Té‡è½½é”®ã€‚|M\Sé‡è½½æ­¤é¡µé¢ã€‚|M\Aé‡è½½æ­¤é¡µé¢å’Œå…¶ä¸­æ‰€æœ‰åŒ…å«çš„对象。
+
en.ro.HelpToolbar4:\Thome button.|M\Sgo to your home page.
de.ro.HelpToolbar4:Lädt die Homepage.
-fr.ro.HelpToolbar4:\Tle bouton Accueil.|M\Saller à votre page d'accueil.
+fr.ro.HelpToolbar4:\Tle bouton Accueil.|M\Saller à votre page d’accueil.
it.ro.HelpToolbar4:\Tvai alla pagina iniziale
nl.ro.HelpToolbar4:Dit is de Startpagina-knop.|MKlik met KIES om naar de begin-/startpagina te gaan.
+zh_CN.ro.HelpToolbar4:\T主页键。|M\Så‰å¾€ä¸»é¡µé¢ã€‚
+
en.ro.HelpToolbar5:\Thistory button.|M\Sopen the local history \w.|M\Aopen the global history \w.
de.ro.HelpToolbar5:Das ist der Schaltknopf zur History-Funktion.|MKlicken mit AUSWAHL öffnet die lokale History.|MKlicken mit SPEZIAL öffnet das Fenster mit der globalen History.
-fr.ro.HelpToolbar5:\Tle bouton d'historique.|M\Souvrir la \w d'historique locale.|M\Aopen the global history \w.
+fr.ro.HelpToolbar5:\Tle bouton d’historique.|M\Souvrir la \w d’historique locale.|M\Aopen the global history \w.
it.ro.HelpToolbar5:\Tmostra la cronologia locale o globale
nl.ro.HelpToolbar5:Dit is de Geschiedenis-knop.|MKlik met KIES om de venstergeschiedenis te openen.|MKlik met PASAAN om de browsergeschiedenis te openen.
+zh_CN.ro.HelpToolbar5:\T历å²é”®ã€‚|M\S打开本地历å²è®°å½•\w。|M\A打开全局历å²è®°å½• \w。
+
en.ro.HelpToolbar6:\Tsave button.|M\Ssave the current document.
de.ro.HelpToolbar6:Speichert das aktuelle Dokument als HTML Datei.
fr.ro.HelpToolbar6:\Tle bouton de sauvegarde.|M\Ssauver le document en cours.
it.ro.HelpToolbar6:\Tsalva il documento corrente
nl.ro.HelpToolbar6:Dit is de Bewaar-knop.|MKlik met KIES om deze pagina als HTML-bestand te bewaren.|MKlik met PASAAN om deze pagina volledig te bewaren, inclusief afbeeldingen en stijlbladen.
+zh_CN.ro.HelpToolbar6:\Tä¿å­˜é”®ã€‚|M\Sä¿æŒå½“å‰æ–‡ä»¶è®°å½•ã€‚
+
en.ro.HelpToolbar7:\Tprint button.|M\Sopen the print dialogue box.
de.ro.HelpToolbar7:Drucken der aktuellen Seite.|MAnklicken öffnet den 'Drucken' Dialog.
-fr.ro.HelpToolbar7:\Tle bouton d'impression.|M\Simprimer cette page.|MOuvre une bo�te de dialogue pour l'impression.
+fr.ro.HelpToolbar7:\Tle bouton d’impression.|M\Simprimer cette page.|MOuvre une boîte de dialogue pour l’impression.
it.ro.HelpToolbar7:\Tapri la finestra di stampa
nl.ro.HelpToolbar7:Dit is de Afdruk-knop.|MKlik met KIES om het afdrukvenster te openen.
+zh_CN.ro.HelpToolbar7:\T打å°é”®ã€‚|M\S打开打å°å¯¹è¯æ¡†ã€‚
+
en.ro.HelpToolbar8:\Thotlist button.|M\Sopen the hotlist management \w.|M\Aadd this address to the hotlist.
de.ro.HelpToolbar8:Das ist der Hotlist Schaltknopf.|MKlicken mit AUSWAHL öffnet die Hotlist.|MKlicken mit SPEZIAL trägt die aktuelle Seite in die Hotlist ein.
-fr.ro.HelpToolbar8:\Tle bouton de favoris.|M\Souvrir la \w de gestion des favoris.|M\Aajouter cette adresse aux favoris.
+fr.ro.HelpToolbar8:\Tle bouton des marque-pages.|M\Souvrir la \w de gestion des marque-pages.|M\Aajouter cette adresse aux marque-pages.
it.ro.HelpToolbar8:\Tapri o aggiungi un link ai segnalibri
nl.ro.HelpToolbar8:Dit is de Favorieten-knop.|MKlik met KIES om de favorietenlijst te openen.|MKlik met PASAAN om dit webadres aan de favorietenlijst toe te voegen.
+zh_CN.ro.HelpToolbar8:\T常用列表键。|M\S打开常用列表管ç†\w。|M\A添加此地å€åˆ°å¸¸ç”¨åˆ—表。
+
en.ro.HelpToolbar9:\Tscale view button.|M\Sscale the page, affecting both text and images.
de.ro.HelpToolbar9:Anklicken öffnet den Vergrößerungs-Dialog.|MDie Vergrößerung betrifft Text und Bilder.
-fr.ro.HelpToolbar9:\Tle bouton de changement d'échelle.|M\Sredimensionner la page, texte et images comprises.
+fr.ro.HelpToolbar9:\Tle bouton de changement d’échelle.|M\Sredimensionner la page, texte et images comprises.
it.ro.HelpToolbar9:\Tscala la dimensione del testo e delle immagini
nl.ro.HelpToolbar9:Dit is de Schaal-knop.|MKlik met KIES om deze pagina te schalen, zowel tekst als afbeeldingen.
+zh_CN.ro.HelpToolbar9:\T缩放键。|M\S 缩放页é¢ï¼Œæ”¹å˜æ–‡å­—和图åƒã€‚
+
en.ro.HelpToolbar10:\Tsearch button.|M\Sfind instances of a string of text on the page.
de.ro.HelpToolbar10:Anklicken öffnet das Fenster zur Textsuche.
fr.ro.HelpToolbar10:\Tle bouton de recherche.|M\Strouver des occurences de fragment de texte dans une page.
it.ro.HelpToolbar10:\Tcerca un occorrenza di testo all'interno della pagina web
nl.ro.HelpToolbar10:Dit is de Zoek-knop.|MKlik met KIES om naar een stuk tekst op deze pagina te zoeken.
+zh_CN.ro.HelpToolbar10:\T查找键。|M\S在页é¢ä¸ŠæŸ¥æ‰¾æ–‡æœ¬å­—符串的实例。
+
en.ro.HelpToolbar11:\Tup button.|M\Straverse up one level on the current website
de.ro.HelpToolbar11:Das ist der Aufwärtsknopf.|MKlicken mit AUSWAHL führt auf die nächsthöhere Ebene der innerhalb Webseite.
-fr.ro.HelpToolbar11:\Tle bouton haut.|M\Sremonte d'un niveau sur le site web en cours.
-it.ro.HelpToolbar11:\Tsale di un livello rispetto al corrente indirizzo
+fr.ro.HelpToolbar11:\Tle bouton haut.|M\Sremonte d’un niveau sur le site web en cours.
+it.ro.HelpToolbar11:\Tsali di un livello rispetto all'indirizzo corrente
nl.ro.HelpToolbar11:Dit is de Omhoog-knop.|MKlik met KIES om 1 niveau omhoog te gaan in de websitehiërarchie.|MKlik met PASAAN om 1 niveau omhoog te gaan in de websitehiërarchie en deze in een nieuw browservenster te openen.
+zh_CN.ro.HelpToolbar11:\Tå‘上方å‘键。|M\S在当å‰ç½‘站上å‘上移动一级
+
en.ro.HelpToolbar14:\TURL bar.|MType in the address of a site to visit and press Return to go there.
de.ro.HelpToolbar14:Das ist die Adressleiste.|MHier die Adresse (URL) eingeben und Entertaste drücken, um eine neue Seite zu laden.
-fr.ro.HelpToolbar14:\Tla barre d'URL.|MTapez l'adresse d'un site à visiter et appuyez sur Return pour y aller.
+fr.ro.HelpToolbar14:\Tla barre d’URL.|MTapez l’adresse d’un site à visiter et appuyez sur Return pour y aller.
it.ro.HelpToolbar14:\Tdigita un indirizzo e premi invio
nl.ro.HelpToolbar14:Dit is het Adresveld.|MVoer een adres in van een website en druk op RETURN om er naartoe te gaan.
+zh_CN.ro.HelpToolbar14:\T地å€æ ã€‚|M输入您è¦è®¿é—®çš„站点地å€ï¼Œç„¶åŽæŒ‰å›žè½¦é”®ã€‚
+
en.ro.HelpToolbar15:\TURL suggestion icon.|M\Sopen a list of recently typed URLs.
de.ro.HelpToolbar15:Das ist das URL-Schnellwahl Symbol.|MKlicken mit AUSWAHL öffnet eine Liste der zuletzt eingegebenen Web-Adressen.
-fr.ro.HelpToolbar15:\Tl'icône de suggestion d'URL.|M\Souvrir une liste d'URLs tapées récemment.
+fr.ro.HelpToolbar15:\Tl’icône de suggestion d’URL.|M\Souvrir une liste d’URLs tapées récemment.
it.ro.HelpToolbar15:\Tapri la lista dei siti visitati più recenti
nl.ro.HelpToolbar15:Dit is het Adressuggestie-symbool.|MKlik met KIES om een lijst met adressen van recent bezochte websites te openen.
+zh_CN.ro.HelpToolbar15:\T地å€å»ºè®®å›¾æ ‡ã€‚|M\S打开最近键入的 URL 列表。
+
en.ro.HelpToolbar16:\Tthrobber.|MIt animates while this \w is active.
de.ro.HelpToolbar16:Das ist die Ladeaktivitätsanzeige.|MSie wird animiert, wenn NetSurf aktiv ist.
-fr.ro.HelpToolbar16:\Tle pulseur.|MIl s'anime lorsque cette \w est active.
+fr.ro.HelpToolbar16:\Tle pulseur.|MIl s’anime lorsque cette \w est active.
it.ro.HelpToolbar16:\Tthrobber animato durante le attività di rete
nl.ro.HelpToolbar16:Dit is de Activiteitsindicator.|MDeze indicator beweegt zolang er actieve processen in het venster plaatsvinden.
+zh_CN.ro.HelpToolbar16:\T页é¢åŠ è½½æŒ‡ç¤ºå™¨ã€‚|M它会在此 \w 处于活跃状æ€æ—¶åˆ¶ä½œåŠ¨ç”»ã€‚
+
en.ro.HelpToolbarFav:\TFavicon: a small logo supplied by the current site, if available.
de.ro.HelpToolbarFav:\TFavicon: a small logo supplied by the current site, if available.
fr.ro.HelpToolbarFav:\TFavicon: a small logo supplied by the current site, if available.
it.ro.HelpToolbarFav:\TFavicon: un piccolo logo fornito dal sito, se disponibile.
nl.ro.HelpToolbarFav:Dit is het websitesymbool: een kleine logo dat meegeleverd wordt met de website, voorzover beschikbaar.
+zh_CN.ro.HelpToolbarFav:\T收è—夹图标:当å‰ç«™ç‚¹æ供的å°å¾½æ ‡(如果有)。
+
en.ro.HelpToolbarHot:\Thotlist indicator: if lit, the current address is in the hotlist.|M\Sto add the current address to the hotlist.|M\Ato remove the current address from the hotlist.
de.ro.HelpToolbarHot:\Thotlist indicator: if lit, the current address is in the hotlist.|M\Sto add the current address to the hotlist.|M\Ato remove the current address from the hotlist.
-fr.ro.HelpToolbarHot:\Thotlist indicator: if lit, the current address is in the hotlist.|M\Sto add the current address to the hotlist.|M\Ato remove the current address from the hotlist.
-it.ro.HelpToolbarHot:\Tindicatore segnalibri: se acceso significa che il corrente indirizzo è presente nei segnalibri.|M\Sper aggiungere il corrente indirizzo ai segnalibri.|M\Aper rimuovere il corrente indirizzo dai segnalibri.
+fr.ro.HelpToolbarHot:\Tindicateur des marque-pages : si allumé, l’adresse courante est déjà dans les marque-pages.|M\Spour ajouter l’adresse courante aux marque-pages.|M\Apour supprimer l’adresse courante des marque-pages.
+it.ro.HelpToolbarHot:\Tindicatore segnalibri: se acceso significa che il corrente indirizzo è presente nei segnalibri.|M\Sper aggiungere il corrente indirizzo ai segnalibri.|M\Aper rimuovere il corrente indirizzo dai segnalibri.
nl.ro.HelpToolbarHot:Dit is de favorietenindicator: wanneer deze oplicht, staat het webadres al in de favorietenlijst.|MKlik met KIES om het adres aan de favorietenlijst toe te voegen.|MKlik met PASAAN om het adres uit de favorietenlijst te verwijderen.
+zh_CN.ro.HelpToolbarHot:\T常用列表指示器:若指示图标亮起,则当å‰åœ°å€åœ¨è¯¥å¸¸ç”¨é¡¹åˆ—表中。|M\S将当å‰åœ°å€æ·»åŠ åˆ°è¯¥å¸¸ç”¨é¡¹åˆ—表中。|M\A从该常用项列表中删除当å‰åœ°å€ã€‚
en.ro.HelpStatus0:\Tstatus bar resizer.|MDrag to alter the size of the status bar.
de.ro.HelpStatus0:Das ist die Begrenzung der Statusanzeige.|MKlicken und Ziehen verändert die Länge der Statusanzeige.
-fr.ro.HelpStatus0:\Tla glissière de la barre d'état.|MDéplacez-la pour changer la taille de la barre d'état.
-it.ro.HelpStatus0:\Ttrascina per modificare la dimensione della barra di stato
+fr.ro.HelpStatus0:\Tla glissière de la barre d’état.|MDéplacez-la pour changer la taille de la barre d’état.
+it.ro.HelpStatus0:\Ttrascina per modificare le dimensioni della barra di stato
nl.ro.HelpStatus0:Dit is statusbalkaanpasser.|MVersleep het om de grootte van de statusbalk te wijzigen.
+zh_CN.ro.HelpStatus0:\T状æ€æ å¤§å°è°ƒæ•´å™¨ã€‚|M拖动以更改状æ€æ çš„大å°ã€‚
+
en.ro.HelpStatus1:\Tstatus bar.|MIt displays information on what the browser \w is doing.
de.ro.HelpStatus1:Das ist die Statusanzeige|MSie zeigt an, was gerade im Browserfenster geschieht.
-fr.ro.HelpStatus1:\Tla barre d'état.|MElle affiche des informations sur ce que fait la \w de navigateur.
+fr.ro.HelpStatus1:\Tla barre d’état.|MElle affiche des informations sur ce que fait la \w de navigateur.
it.ro.HelpStatus1:\Tmostra informazioni relative alle attività del browser
nl.ro.HelpStatus1:Dit is statusbalk.|MHet toont informatie over wat het browservenster aan het doen is.
+zh_CN.ro.HelpStatus1:\T状æ€æ ã€‚|M它会显示相关æµè§ˆå™¨ \w 正在执行的æ“作信æ¯ã€‚
en.ro.HelpIconMenu0:\Rview information about this software.
de.ro.HelpIconMenu0:Zeigt Informationen zu dieser Software.
fr.ro.HelpIconMenu0:\Rvoir des informations sur ce logiciel.
it.ro.HelpIconMenu0:\Rmostra informazioni su NetSurf
nl.ro.HelpIconMenu0:Verplaats de muispijl naar rechts om het informatievenster over dit programma te openen.
+zh_CN.ro.HelpIconMenu0:\R查看有关此软件的信æ¯ã€‚
+
en.ro.HelpIconMenu1:\Sview NetSurf's documentation.
de.ro.HelpIconMenu1:Lädt die NetSurf Dokumentation in einem neuen Browserfenster.
fr.ro.HelpIconMenu1:\Svoir la documentation de NetSurf.
it.ro.HelpIconMenu1:\Smostra documentazione di NetSurf
nl.ro.HelpIconMenu1:Klik met KIES om de documentatie van NetSurf te openen.
+zh_CN.ro.HelpIconMenu1:\S查看 NetSurf 的文档。
+
en.ro.HelpIconMenu2:\Ropen a window.
de.ro.HelpIconMenu2:Mauszeiger nach rechts bewegen, um ein Fenster zu öffnen.
fr.ro.HelpIconMenu2:\Rouvrir une fenêtre.
it.ro.HelpIconMenu2:\Rapri una finestra
nl.ro.HelpIconMenu2:Verplaats de muispijl naar rechts om een venster te openen.
+zh_CN.ro.HelpIconMenu2:\R打开窗å£ã€‚
+
en.ro.HelpIconMenu2-0:\Renter an address to visit.
de.ro.HelpIconMenu2-0:Erlaubt die Eingabe einer Web-Adresse.
fr.ro.HelpIconMenu2-0:\Rentrer une adresse à visiter.
-it.ro.HelpIconMenu2-0:\Rdigita un indirizzo da visitare
+it.ro.HelpIconMenu2-0:\Rdigita un indirizzo da aprire
nl.ro.HelpIconMenu2-0:Verplaats de muispijl naar rechts om een webadres in te voeren en vervolgens de locatie te bezoeken.
+zh_CN.ro.HelpIconMenu2-0:\R输入访问地å€ã€‚
+
en.ro.HelpIconMenu2-1:\Sopen the hotlist management \w.
de.ro.HelpIconMenu2-1:Klicken mit AUSWAHL öffnet die Hotlist.
-fr.ro.HelpIconMenu2-1:\Souvrir la fenêtre de gestion des favoris.
+fr.ro.HelpIconMenu2-1:\Souvrir la fenêtre de gestion des marque-pages.
it.ro.HelpIconMenu2-1:\Sapri la finestra dei segnalibri
nl.ro.HelpIconMenu2-1:Klik met KIES om de favorietenlijst te openen.
+zh_CN.ro.HelpIconMenu2-1:\S打开常用列表管ç†å™¨ \w。
+
en.ro.HelpIconMenu2-2:\Sopen the global history \w.
de.ro.HelpIconMenu2-2:Klicken mit AUSWAHL öffnet das Fenster mit der globalen History.
-fr.ro.HelpIconMenu2-2:\Souvrir la fenêtre d'historique global.
+fr.ro.HelpIconMenu2-2:\Souvrir la fenêtre d’historique global.
it.ro.HelpIconMenu2-2:\Smostra cronologia globale
nl.ro.HelpIconMenu2-2:Klik met KIES om de browsergeschiedenis te openen.
+zh_CN.ro.HelpIconMenu2-2:\S打开全局历å²è®°å½• \w。
+
en.ro.HelpIconMenu2-3:\Sopen the cookie management \w.
de.ro.HelpIconMenu2-3:Klicken mit AUSWAHL öffnet die Cookie Verwaltung.
fr.ro.HelpIconMenu2-3:\Souvrir la fenêtre de gestion des cookies.
it.ro.HelpIconMenu2-3:\Sapri la finestra di gestione dei cookie
nl.ro.HelpIconMenu2-3:Klik met KIES om het cookiesbeheervenster te openen.
+zh_CN.ro.HelpIconMenu2-3:\S打开 Cookie ç®¡ç† \w。
+
en.ro.HelpIconMenu3:\Sopen the Choices dialogue box.
de.ro.HelpIconMenu3:Öffnet einen Dialog mit Einstellungen für NetSurf.
fr.ro.HelpIconMenu3:\Souvrir la boîte de dialogue des Préférences.
it.ro.HelpIconMenu3:\Sapri una finestra di dialogo/scelta
nl.ro.HelpIconMenu3:Klik met KIES om een dialoogvenster te openen waarin de NetSurf-instellingen kunnen worden ingesteld.
+zh_CN.ro.HelpIconMenu3:\S打开选择对è¯æ¡†ã€‚
+
en.ro.HelpIconMenu4:\Squit NetSurf.
de.ro.HelpIconMenu4:Beendet das Programm.|MAlle Browserfenster werden geschlossen. Downloads werden abgebrochen.
fr.ro.HelpIconMenu4:\Squitter NetSurf.
it.ro.HelpIconMenu4:\Schiudi NetSurf
nl.ro.HelpIconMenu4:Klik met KIES om het programma NetSurf te stoppen.
+zh_CN.ro.HelpIconMenu4:\S退出 NetSurf æµè§ˆå™¨ã€‚
en.ro.HelpBrowserMenu0:\Rsee the options relating to the current page.
de.ro.HelpBrowserMenu0:Untermenü Seite.|MMenüpunkte beziehen sich auf die angezeigte Seite.
fr.ro.HelpBrowserMenu0:\Rvoir les options en rapport avec la page en cours.
it.ro.HelpBrowserMenu0:\Rmostra opzioni relative a questa pagina
nl.ro.HelpBrowserMenu0:Verplaats de muispijl naar rechts om de mogelijkheden bij deze pagina te tonen.
+zh_CN.ro.HelpBrowserMenu0:\R查看与当å‰é¡µé¢çš„相关选项。
+
en.ro.HelpBrowserMenu0-0:\Rsee information about the current page.
de.ro.HelpBrowserMenu0-0:Zeigt Informationen zur aktuellen Seite.
fr.ro.HelpBrowserMenu0-0:\Rvoir les informations concernant la page en cours.
it.ro.HelpBrowserMenu0-0:\Rmostra informazioni di questa pagina
nl.ro.HelpBrowserMenu0-0:Verplaats de muispijl naar rechts om informatie over deze pagina te tonen.
+zh_CN.ro.HelpBrowserMenu0-0:\R查看当å‰é¡µé¢çš„相关信æ¯ã€‚
+
en.ro.HelpBrowserMenu0-1:\Rsave the current page as an HTML file.
de.ro.HelpBrowserMenu0-1:Abspeichern der Seite als HTML Datei.|MGespeichert wird nur der HTML Quellcode (keine Bilder etc.).
fr.ro.HelpBrowserMenu0-1:\Rsauver la page courante en fichier HTML.
it.ro.HelpBrowserMenu0-1:\Rsalva la pagina corrente come file HTML
nl.ro.HelpBrowserMenu0-1:Verplaats de muispijl naar rechts om deze pagina als HTML-bestand te bewaren.
+zh_CN.ro.HelpBrowserMenu0-1:\R将当å‰é¡µé¢å¦å­˜ä¸º HTML 文件。
+
en.ro.HelpBrowserMenu0-2:\Rsave the current page including all the images and style sheets used.
de.ro.HelpBrowserMenu0-2:Abspeichern der kompletten Seite.|MDer HTML Quellcode sowie alle Bilder und StyleSheets werden gespeichert.
fr.ro.HelpBrowserMenu0-2:\Rsauver la page courante y compris toutes les images et les feuilles de style utilisées.
it.ro.HelpBrowserMenu0-2:\Rsalva la pagina corrente includendo tutte le immagini ed i fogli di stile usati
nl.ro.HelpBrowserMenu0-2:Verplaats de muispijl naar rechts om deze pagina te bewaren, inclusief bijbehorende afbeeldingen en stijlbladen.
+zh_CN.ro.HelpBrowserMenu0-2:\Rä¿å­˜å½“å‰é¡µé¢ï¼ŒåŒ…括所有图åƒå’Œæ ·å¼è¡¨ã€‚
+
en.ro.HelpBrowserMenu0-3:\Rsee the export options.
de.ro.HelpBrowserMenu0-3:Abspeichern der Seite in verschiedenen Formaten.
-fr.ro.HelpBrowserMenu0-3:\Rvoir les options d'exportation.
+fr.ro.HelpBrowserMenu0-3:\Rvoir les options d’exportation.
it.ro.HelpBrowserMenu0-3:\Rmostra opzioni di esportazione
nl.ro.HelpBrowserMenu0-3:Verplaats de muispijl naar rechts om de exporteermogelijkheden te tonen.
+zh_CN.ro.HelpBrowserMenu0-3:\R查看导出选项。
+
en.ro.HelpBrowserMenu0-3-0:\Rexport the current page as a Drawfile.
de.ro.HelpBrowserMenu0-3-0:Exportieren der Seite als Draw Datei.
fr.ro.HelpBrowserMenu0-3-0:\Rexporter la page courante en Drawfile.
it.ro.HelpBrowserMenu0-3-0:\Resporta la pagina corrente come file Draw
nl.ro.HelpBrowserMenu0-3-0:Verplaats de muispijl naar rechts om deze pagina als een Draw-bestand te exporteren.
+zh_CN.ro.HelpBrowserMenu0-3-0:\R将当å‰é¡µé¢å¯¼å‡ºä¸ºç»˜å›¾æ–‡ä»¶ã€‚
+
en.ro.HelpBrowserMenu0-3-1:\Rexport the current page as a plain text file.
de.ro.HelpBrowserMenu0-3-1:Exportieren der Seite als Text Datei.
fr.ro.HelpBrowserMenu0-3-1:\Rexporter la page courante en simple fichier texte.
it.ro.HelpBrowserMenu0-3-1:\Resporta la pagina corrente come file di testo
nl.ro.HelpBrowserMenu0-3-1:Verplaats de muispijl naar rechts om deze pagina als een tekst-bestand te exporteren
+zh_CN.ro.HelpBrowserMenu0-3-1:\R将当å‰é¡µé¢å¯¼å‡ºä¸ºçº¯æ–‡æœ¬æ–‡ä»¶ã€‚
+
en.ro.HelpBrowserMenu0-4:\Rsave the address of the current page.
de.ro.HelpBrowserMenu0-4:Adresse der Seite speichern.
-fr.ro.HelpBrowserMenu0-4:\Rsauver l'adresse de la page courante.
+fr.ro.HelpBrowserMenu0-4:\Rsauver l’adresse de la page courante.
it.ro.HelpBrowserMenu0-4:\Rsalva l'indirizzo della pagina corrente
nl.ro.HelpBrowserMenu0-4:Verplaats de muispijl naar rechts om het webadres van deze pagina te bewaren.
+zh_CN.ro.HelpBrowserMenu0-4:\Rä¿å­˜å½“å‰é¡µé¢çš„网å€ã€‚
+
en.ro.HelpBrowserMenu0-4-0:\Rsave the current address in Acorn URI format.
de.ro.HelpBrowserMenu0-4-0:Speichert die Adresse der Seite im Acorn URI Format.
-fr.ro.HelpBrowserMenu0-4-0:\Rsauver l'adresse en cours au format Acorn URI.
+fr.ro.HelpBrowserMenu0-4-0:\Rsauver l’adresse en cours au format Acorn URI.
it.ro.HelpBrowserMenu0-4-0:\Rsalva l'indirizzo corrente nel formato Acorn URI
nl.ro.HelpBrowserMenu0-4-0:Verplaats de muispijl naar rechts om dit adres in AcornURI-vorm te bewaren.
+zh_CN.ro.HelpBrowserMenu0-4-0:\R以 Acorn URI æ ¼å¼ä¿å­˜å½“å‰ç½‘å€ã€‚
+
en.ro.HelpBrowserMenu0-4-1:\Rsave the current address in Ant URL format.
de.ro.HelpBrowserMenu0-4-1:Speichert die Adresse der Seite im Ant URL Format.
-fr.ro.HelpBrowserMenu0-4-1:\Rsauver l'adresse en cours au format Ant URL.
+fr.ro.HelpBrowserMenu0-4-1:\Rsauver l’adresse en cours au format Ant URL.
it.ro.HelpBrowserMenu0-4-1:\Rsalva l'indirizzo corrente nel formato Ant URL
nl.ro.HelpBrowserMenu0-4-1:Verplaats de muispijl naar rechts om dit adres in AntURL-vorm te bewaren,
+zh_CN.ro.HelpBrowserMenu0-4-1:\R以 Ant URL æ ¼å¼ä¿å­˜å½“å‰ç½‘å€ã€‚
+
en.ro.HelpBrowserMenu0-4-2:\Rsave the current address as plain text.
de.ro.HelpBrowserMenu0-4-2:Speichert die Adresse der Seite als Text.
-fr.ro.HelpBrowserMenu0-4-2:\Rsauver l'adresse courante en simple texte.
+fr.ro.HelpBrowserMenu0-4-2:\Rsauver l’adresse courante en simple texte.
it.ro.HelpBrowserMenu0-4-2:\Rsalva l'indirizzo corrente come file di testo
nl.ro.HelpBrowserMenu0-4-2:Verplaats de muispijl naar rechts om dit adres als platte tekst te bewaren.
+zh_CN.ro.HelpBrowserMenu0-4-2:\R将当å‰ç½‘å€å¦å­˜ä¸ºçº¯æ–‡æœ¬ã€‚
+
en.ro.HelpBrowserMenu0-5:\Sopen the print dialogue box.
de.ro.HelpBrowserMenu0-5:Dialogfenster zum Drucken der Seite.
-fr.ro.HelpBrowserMenu0-5:\Souvrir la boîte de dialogue d'impression.
+fr.ro.HelpBrowserMenu0-5:\Souvrir la boîte de dialogue d’impression.
it.ro.HelpBrowserMenu0-5:\Sapri la finestra di stampa
nl.ro.HelpBrowserMenu0-5:Verplaats de muispijl naar rechts om het afdrukvenster te openen.
+zh_CN.ro.HelpBrowserMenu0-5:\S打开打å°å¯¹è¯æ¡†ã€‚
+
en.ro.HelpBrowserMenu0-6:\Sopen the current page in a new window.
de.ro.HelpBrowserMenu0-6:Öffnet die aktuelle Seite in einem neuen Fenster.
fr.ro.HelpBrowserMenu0-6:\Souvrir la page courante dans une nouvelle fenêtre.
it.ro.HelpBrowserMenu0-6:\Sapri la pagina corrente in una nuova finestra
nl.ro.HelpBrowserMenu0-6:Klik met KIES om deze pagina in een nieuw browservenster te openen.
+zh_CN.ro.HelpBrowserMenu0-6:\S在新窗å£ä¸­æ‰“开当å‰é¡µé¢ã€‚
+
en.ro.HelpBrowserMenu0-7:\Rsearch for instances of a string of text on the page.
de.ro.HelpBrowserMenu0-7:Erlaubt das Suchen einer Zeichenkette im Text des aktuellen Browserfensters.
fr.ro.HelpBrowserMenu0-7:\Rchercher un fragment de texte sur la page.
it.ro.HelpBrowserMenu0-7:\Rcerca una stringa di testo all'interno della pagina
nl.ro.HelpBrowserMenu0-7:Verplaats de muispijl naar rechts om een stuk tekst binnen de pagina op te zoeken.
+zh_CN.ro.HelpBrowserMenu0-7:\R在页é¢ä¸Šæœç´¢æ–‡æœ¬å­—符串的实例。
+
en.ro.HelpBrowserMenu0-8:\Sview the source code of the current page in a text editor.
de.ro.HelpBrowserMenu0-8:Lädt den Quellcode der Seite in einen Editor.
fr.ro.HelpBrowserMenu0-8:\Svoir le code source de la page courante dans un éditeur de texte.
it.ro.HelpBrowserMenu0-8:\Smostra sorgente della pagina
nl.ro.HelpBrowserMenu0-8:Klik met KIES om de broncode van deze pagina in een tekstbewerker te openen.
+zh_CN.ro.HelpBrowserMenu0-8:\S在文本编辑器中查看当å‰é¡µé¢çš„æºä»£ç ã€‚
+
en.ro.HelpBrowserMenu1:\Rsee the options relating to the current item.
de.ro.HelpBrowserMenu1:Untermenü Objekt.|MMenöpunkte beziehen sich auf das aktuelle Objekt.
-fr.ro.HelpBrowserMenu1:\Rvoir les options correspondant à l'objet courant.
+fr.ro.HelpBrowserMenu1:\Rvoir les options correspondant à l’objet courant.
it.ro.HelpBrowserMenu1:\Rmostra opzioni relative all'oggetto corrente.
nl.ro.HelpBrowserMenu1:Verplaats de muispijl naar rechts om de mogelijkheden bij dit item te tonen.
+zh_CN.ro.HelpBrowserMenu1:\R查看与当å‰é¡¹çš„相关选项。
+
en.ro.HelpBrowserMenu1-0-0:\Rsee information about the current item.
de.ro.HelpBrowserMenu1-0-0:Informationen zum aktuellen Objekt zeigen.
-fr.ro.HelpBrowserMenu1-0-0:\Rvoir les informations sur l'objet en cours.
+fr.ro.HelpBrowserMenu1-0-0:\Rvoir les informations sur l’objet en cours.
it.ro.HelpBrowserMenu1-0-0:\Rmostra informazioni relative all'oggetto corrente.
nl.ro.HelpBrowserMenu1-0-0:Verplaats de muispijl naar rechts om informatie over dit item te tonen.
+zh_CN.ro.HelpBrowserMenu1-0-0:\R查看当å‰é¡¹çš„ä¿¡æ¯ã€‚
+
en.ro.HelpBrowserMenu1-0-1:\Rsave the current item.
de.ro.HelpBrowserMenu1-0-1:Abspeichern des Objektes (Original).
-fr.ro.HelpBrowserMenu1-0-1:\Rsauver l'objet courant.
+fr.ro.HelpBrowserMenu1-0-1:\Rsauver l’objet courant.
it.ro.HelpBrowserMenu1-0-1:\Rsalva l'oggetto corrente
nl.ro.HelpBrowserMenu1-0-1:Verplaats de muispijl naar rechts om dit item te bewaren.
+zh_CN.ro.HelpBrowserMenu1-0-1:\Rä¿å­˜å½“å‰é¡¹ã€‚
+
en.ro.HelpBrowserMenu1-0-2:\Rsee the export options.
de.ro.HelpBrowserMenu1-0-2:Optionen zum Export des aktuellen Objektes zeigen.
-fr.ro.HelpBrowserMenu1-0-2:\Rvoir les options d'exportation.
+fr.ro.HelpBrowserMenu1-0-2:\Rvoir les options d’exportation.
it.ro.HelpBrowserMenu1-0-2:\Rmostra opzioni di esportazione
nl.ro.HelpBrowserMenu1-0-2:Verplaats de muispijl naar rechts om de exporteermogelijkheden te tonen.
+zh_CN.ro.HelpBrowserMenu1-0-2:\R查看导出选项。
+
en.ro.HelpBrowserMenu1-0-2-0:\Rsave the image as a Sprite.
de.ro.HelpBrowserMenu1-0-2-0:Abspeichern des Bildes als Sprite Datei.
-fr.ro.HelpBrowserMenu1-0-2-0:\Rsauver l'image au format Sprite.
+fr.ro.HelpBrowserMenu1-0-2-0:\Rsauver l’image au format « sprite ».
it.ro.HelpBrowserMenu1-0-2-0:\Rsalva l'immagine come file Sprite
nl.ro.HelpBrowserMenu1-0-2-0:Verplaats de muispijl naar rechts om de afbeelding als een Sprite-bestand te bewaren.
+zh_CN.ro.HelpBrowserMenu1-0-2-0:\R将图åƒå¦å­˜ä¸ºè´´å›¾æ–‡ä»¶ã€‚
+
en.ro.HelpBrowserMenu1-0-2-1:\Rsave the image as a DrawFile
de.ro.HelpBrowserMenu1-0-2-1:\Rsave the image as a DrawFile
fr.ro.HelpBrowserMenu1-0-2-1:\Rsave the image as a DrawFile
it.ro.HelpBrowserMenu1-0-2-1:\Rsalva l'immagine come file Draw
nl.ro.HelpBrowserMenu1-0-2-1:Verplaats de muispijl naar rechts om de afbeelding als een Draw-bestand te bewaren.
+zh_CN.ro.HelpBrowserMenu1-0-2-1:\R将图åƒå¦å­˜ä¸ºç»˜å›¾æ–‡ä»¶
+
en.ro.HelpBrowserMenu1-0-3:\Rsave the address of the current item.
de.ro.HelpBrowserMenu1-0-3:Die Adresse des Objektes speichern.
-fr.ro.HelpBrowserMenu1-0-3:\Rsauver l'adresse de l'objet courant.
+fr.ro.HelpBrowserMenu1-0-3:\Rsauver l’adresse de l’objet courant.
it.ro.HelpBrowserMenu1-0-3:\Rsalva l'indirizzo dell'oggetto corrente.
nl.ro.HelpBrowserMenu1-0-3:Verplaats de muispijl naar rechts om het adres van dit item te bewaren.
+zh_CN.ro.HelpBrowserMenu1-0-3:\Rä¿å­˜å½“å‰é¡¹çš„网å€ã€‚
+
en.ro.HelpBrowserMenu1-0-3-0:\Rsave the current item's address in Acorn URI format.
de.ro.HelpBrowserMenu1-0-3-0:Speichert die Adresse des Objektes im Acorn URI Format.
-fr.ro.HelpBrowserMenu1-0-3-0:\Rsauver l'adresse de l'objet courant au format Acorn URI.
+fr.ro.HelpBrowserMenu1-0-3-0:\Rsauver l’adresse de l’objet courant au format Acorn URI.
it.ro.HelpBrowserMenu1-0-3-0:\Rsalva l'indirizzo dell'oggetto corrente nel formato Acorn URI
nl.ro.HelpBrowserMenu1-0-3-0:Verplaats de muispijl naar rechts om het adres van dit item in AcornURI-vorm te bewaren.
+zh_CN.ro.HelpBrowserMenu1-0-3-0:\R以 Acorn URI æ ¼å¼ä¿å­˜å½“å‰é¡¹çš„网å€ã€‚
+
en.ro.HelpBrowserMenu1-0-3-1:\Rsave the current item's address in Ant URL format.
de.ro.HelpBrowserMenu1-0-3-1:Speichert die Adresse des Objektes im Ant URL Format.
-fr.ro.HelpBrowserMenu1-0-3-1:\Rsauver l'adresse de l'objet courant au format Ant URL.
+fr.ro.HelpBrowserMenu1-0-3-1:\Rsauver l’adresse de l’objet courant au format Ant URL.
it.ro.HelpBrowserMenu1-0-3-1:\Rsalva l'indirizzo dell'oggetto corrente nel formato Ant URL
nl.ro.HelpBrowserMenu1-0-3-1:Verplaats de muispijl naar rechts om het adres van dit item in AntURL-vorm te bewaren.
+zh_CN.ro.HelpBrowserMenu1-0-3-1:\R以 Ant URL æ ¼å¼ä¿å­˜å½“å‰é¡¹çš„网å€ã€‚
+
en.ro.HelpBrowserMenu1-0-3-2:\Rsave the current item's address as plain text.
de.ro.HelpBrowserMenu1-0-3-2:Speichert die Adresse des Objektes als Text.
-fr.ro.HelpBrowserMenu1-0-3-2:\Rsauver l'adresse de l'objet courant en texte simple.
+fr.ro.HelpBrowserMenu1-0-3-2:\Rsauver l’adresse de l’objet courant en texte simple.
it.ro.HelpBrowserMenu1-0-3-2:\Rsalva l'indirizzo dell'oggetto corrente come file di testo
nl.ro.HelpBrowserMenu1-0-3-2:Verplaats de muispijl naar rechts om het adres van dit item als platte tekst te bewaren.
+zh_CN.ro.HelpBrowserMenu1-0-3-2:\R将当å‰é¡¹çš„网å€å¦å­˜ä¸ºçº¯æ–‡æœ¬ã€‚
+
en.ro.HelpBrowserMenu1-0-4:\Sreload all the items on this page.
de.ro.HelpBrowserMenu1-0-4:Anklicken mit AUSWAHL um alle Objekte der Seite erneut zu laden.
fr.ro.HelpBrowserMenu1-0-4:\Srecharger tous les objets de cete page.
it.ro.HelpBrowserMenu1-0-4:\Sricarica tutti gli elementi di questa pagina
nl.ro.HelpBrowserMenu1-0-4:Klik met KIES om alle items van deze pagina opnieuw op te halen.
+zh_CN.ro.HelpBrowserMenu1-0-4:\Sé‡æ–°åŠ è½½æ­¤é¡µé¢ä¸Šçš„所有项。
+
en.ro.HelpBrowserMenu1-1:\Rsee the options relating to the current link.
de.ro.HelpBrowserMenu1-1:Optionen für den aktuellen Verweis
fr.ro.HelpBrowserMenu1-1:\Rsee the options relating to the current link.
it.ro.HelpBrowserMenu1-1:\Rmostra opzioni relative al link corrente.
nl.ro.HelpBrowserMenu1-1:Verplaats de muispijl naar rechts om de mogelijkheden bij deze koppeling te tonen.
+zh_CN.ro.HelpBrowserMenu1-1:\R查看当å‰é“¾æŽ¥çš„相关选项。
+
en.ro.HelpBrowserMenu1-1-0:\Rsave the current link.
de.ro.HelpBrowserMenu1-1-0:Die Adresse des aktuellen Verweises abspeichern.
fr.ro.HelpBrowserMenu1-1-0:\Rsave the current link.
it.ro.HelpBrowserMenu1-1-0:\Rsalva il link corrente
nl.ro.HelpBrowserMenu1-1-0:Verplaats de muispijl naar rechts om deze koppeling te bewaren,
+zh_CN.ro.HelpBrowserMenu1-1-0:\Rä¿å­˜å½“å‰é“¾æŽ¥ã€‚
+
en.ro.HelpBrowserMenu1-1-0-0:\Rsave the link in Acorn URI format.
de.ro.HelpBrowserMenu1-1-0-0:Speichert die Adresse des Verweises im Acorn URI Format.
fr.ro.HelpBrowserMenu1-1-0-0:\Rsave the link in Acorn URI format.
it.ro.HelpBrowserMenu1-1-0-0:\Rsalva il link nel formato Acorn URI
nl.ro.HelpBrowserMenu1-1-0-0:Verplaats de muispijl naar rechts om deze koppeling in AcornURI-vorm te bewaren.
+zh_CN.ro.HelpBrowserMenu1-1-0-0:\R以 Acorn URI æ ¼å¼ä¿å­˜é“¾æŽ¥ã€‚
+
en.ro.HelpBrowserMenu1-1-0-1:\Rsave the link in Ant URL format.
de.ro.HelpBrowserMenu1-1-0-1:Speichert die Adresse des Verweises im Ant URL Format.
fr.ro.HelpBrowserMenu1-1-0-1:\Rsave the link in Ant URL format.
it.ro.HelpBrowserMenu1-1-0-1:\Rsalva il link nel formato Ant URL
nl.ro.HelpBrowserMenu1-1-0-1:Verplaats de muispijl naar rechts om deze koppeling in AntURL-vorm te bewaren.
+zh_CN.ro.HelpBrowserMenu1-1-0-1:\R以 Ant URL æ ¼å¼ä¿å­˜é“¾æŽ¥ã€‚
+
en.ro.HelpBrowserMenu1-1-0-2:\Rsave the link as plain text.
de.ro.HelpBrowserMenu1-1-0-2:Speichert die Adresse des Verweises als Text.
fr.ro.HelpBrowserMenu1-1-0-2:\Rsave the link as plain text.
it.ro.HelpBrowserMenu1-1-0-2:\Rsalva il link come file di testo
nl.ro.HelpBrowserMenu1-1-0-2:Verplaats de muispijl naar rechts om deze koppeling als platte tekst te bewaren.
+zh_CN.ro.HelpBrowserMenu1-1-0-2:\R将链接å¦å­˜ä¸ºçº¯æ–‡æœ¬ã€‚
+
en.ro.HelpBrowserMenu1-1-1:\Sdownload from this link.
de.ro.HelpBrowserMenu1-1-1:Anklicken mit AUSWAHL startet einen Download von diesem Link.
fr.ro.HelpBrowserMenu1-1-1:\Sdownload from this link.
it.ro.HelpBrowserMenu1-1-1:\Sscarica da questo link
nl.ro.HelpBrowserMenu1-1-1:Klik met KIES om de pagina van deze koppeling op te halen.
+zh_CN.ro.HelpBrowserMenu1-1-1:\S从此链接下载。
+
en.ro.HelpBrowserMenu1-1-2:\Sopen this link in a new window.
de.ro.HelpBrowserMenu1-1-2:Anklicken mit AUSWAHL öffnet den Link in einem neuen Fenster.
fr.ro.HelpBrowserMenu1-1-2:\Sopen this link in a new window.
it.ro.HelpBrowserMenu1-1-2:\Sapri questo link in una nuova finestra
nl.ro.HelpBrowserMenu1-1-2:Klik met KIES om deze koppeling in een nieuw browservenster te openen.
+zh_CN.ro.HelpBrowserMenu1-1-2:\S在新窗å£ä¸­æ‰“开此链接。
+
en.ro.HelpBrowserMenu2:\Rsee the selection options.
de.ro.HelpBrowserMenu2:Optionen für die manuell markierten Webseitenbereiche
fr.ro.HelpBrowserMenu2:\Rsee the selection options.
it.ro.HelpBrowserMenu2:\Rmostra le opzioni di selezione
nl.ro.HelpBrowserMenu2:Verplaats de muispijl naar rechts om de selectiemogelijkheden te tonen.
+zh_CN.ro.HelpBrowserMenu2:\R查看选项。
+
en.ro.HelpBrowserMenu2-0:\Rsave the current selection.
de.ro.HelpBrowserMenu2-0:Die aktuell markierten Bereiche abspeichern.
fr.ro.HelpBrowserMenu2-0:\Rsave the current selection.
it.ro.HelpBrowserMenu2-0:\Rsalva la selezione corrente
nl.ro.HelpBrowserMenu2-0:Verplaats de muispijl naar rechts om deze selectie te bewaren.
+zh_CN.ro.HelpBrowserMenu2-0:\Rä¿å­˜å½“å‰é€‰é¡¹ã€‚
+
en.ro.HelpBrowserMenu2-1:\Scopy the selected text to the clipboard.
de.ro.HelpBrowserMenu2-1:Den markierten Text ins Clipboard kopieren.
fr.ro.HelpBrowserMenu2-1:\Scopy the selected text to the clipboard.
it.ro.HelpBrowserMenu2-1:\Scopia il testo selezionato nella clipboard
nl.ro.HelpBrowserMenu2-1:Klik met KIES om de geselecteerde tekst naar het klembord te kopiëren.
+zh_CN.ro.HelpBrowserMenu2-1:\S将所选文本å¤åˆ¶åˆ°å‰ªè´´æ¿ã€‚
+
en.ro.HelpBrowserMenu2-2:\Scut the selected text to the clipboard.
de.ro.HelpBrowserMenu2-2:Den markierten Text ausschneiden und ins Clipboard transferieren.
fr.ro.HelpBrowserMenu2-2:\Scut the selected text to the clipboard.
it.ro.HelpBrowserMenu2-2:\Staglia il testo selezionato nella clipboard
nl.ro.HelpBrowserMenu2-2:Klik met KIES om de geselecteerde tekst naar het klembord te verplaatsen.
+zh_CN.ro.HelpBrowserMenu2-2:\S剪切选定的文本到剪贴æ¿ã€‚
+
en.ro.HelpBrowserMenu2-3:\Spaste text from the clipboard.
de.ro.HelpBrowserMenu2-3:Text aus dem Clipboard einfügen.
fr.ro.HelpBrowserMenu2-3:\Spaste text from the clipboard.
it.ro.HelpBrowserMenu2-3:\Sincolla il testo dalla clipboard
nl.ro.HelpBrowserMenu2-3:Klik met KIES om de tekst van het klembord hier in te voegen.
+zh_CN.ro.HelpBrowserMenu2-3:\S粘贴剪贴æ¿çš„文本。
+
en.ro.HelpBrowserMenu2-4:\Sdeselect the current selection.
de.ro.HelpBrowserMenu2-4:\Sdeselect the current selection.
fr.ro.HelpBrowserMenu2-4:\Sdeselect the current selection.
it.ro.HelpBrowserMenu2-4:\Sdeseleziona la selezione corrente.
nl.ro.HelpBrowserMenu2-4:Klik met KIES om de gekozen selectie te deselecteren.
+zh_CN.ro.HelpBrowserMenu2-4:\Så–消选择当å‰é€‰é¡¹ã€‚
+
en.ro.HelpBrowserMenu2-5:\Sselect all text on the current page, without the contents of text input fields.|MWhen the carret is at a text input field, all text in that field is selected.
de.ro.HelpBrowserMenu2-5:\Sselect all text on the current page, without the contents of text input fields.|MWhen the carret is at a text input field, all text in that field is selected.
fr.ro.HelpBrowserMenu2-5:\Sselect all text on the current page, without the contents of text input fields.|MWhen the carret is at a text input field, all text in that field is selected.
it.ro.HelpBrowserMenu2-5:\Sseleziona tutto il testo della pagina corrente escludendo i contenuti di testo nei campi di input.|MQualora il caret sia in un campo di inserimento testo allora verrà selezionato tutto il testo in quel campo.
nl.ro.HelpBrowserMenu2-5:Klik met KIES om alle tekst op de pagina, uitgezonderd de invoervelden te selecteren.|MWanneer het inlasteken in een invoerveld staat, wordt alle tekst in het veld geselecteerd.
+zh_CN.ro.HelpBrowserMenu2-5:\S选择当å‰é¡µé¢ä¸Šçš„所有文本,但ä¸åŒ…å«æ–‡æœ¬è¾“入框的内容。|M当æ’入符åˆä½äºŽæ–‡æœ¬è¾“入框时,将选择该框中的所有文本。
+
en.ro.HelpBrowserMenu3:\Rsee the navigation options.
de.ro.HelpBrowserMenu3:Untermenü Navigieren.
fr.ro.HelpBrowserMenu3:\Rvoir les options de navigation.
it.ro.HelpBrowserMenu3:\Rmostra opzioni di navigazione
nl.ro.HelpBrowserMenu3:Verplaats de muispijl naar rechts om de navigatiemogelijkheden te tonen.
+zh_CN.ro.HelpBrowserMenu3:\R查看导航选项。
+
en.ro.HelpBrowserMenu3-0:\Sreturn to the configured home page.
de.ro.HelpBrowserMenu3-0:Öffnet die Homepage im aktuellen Fenster.
-fr.ro.HelpBrowserMenu3-0:\Srevenir à la page d'accueil configurée.
+fr.ro.HelpBrowserMenu3-0:\Srevenir à la page d’accueil configurée.
it.ro.HelpBrowserMenu3-0:\Storna alla pagina iniziale preconfigurata
nl.ro.HelpBrowserMenu3-0:Klik met KIES om terug naar de begin-/startpagina te gaan.
+zh_CN.ro.HelpBrowserMenu3-0:\S返回é…置好的主页。
+
en.ro.HelpBrowserMenu3-1:\Sgo back a page in the local history.|MForm information is not resubmitted.
de.ro.HelpBrowserMenu3-1:Schaltet zurück zur vorher dargestellten Seite.|MDie Seite wird dabei nicht aktualisiert.
-fr.ro.HelpBrowserMenu3-1:\Sreculer d'une page dans l'historique local.|ML'information du formlaire n'est pas réenvoyée.
+fr.ro.HelpBrowserMenu3-1:\Sreculer d’une page dans l’historique local.|ML’information du formlaire n’est pas réenvoyée.
it.ro.HelpBrowserMenu3-1:\Storna indietro di una pagina nella cronologia locale.|MIl form non verrà reinviato.
nl.ro.HelpBrowserMenu3-1:Klik met KIES om 1 pagina terug in de venstergeschiedenis te gaan.|MLet op! Formulierinformatie wordt niet opnieuw ingediend.
+zh_CN.ro.HelpBrowserMenu3-1:\S在本地历å²è®°å½•ä¸­åŽé€€ä¸€é¡µã€‚|Mä¸é‡æ–°æ交表格信æ¯ã€‚
+
en.ro.HelpBrowserMenu3-2:\Sstep forward a page in the local history.|MForm information is not resubmitted.
de.ro.HelpBrowserMenu3-2:Schaltet zur nächsten Seite in der lokalen History Liste.|MDie Seite wird dabei nicht aktualisiert.
-fr.ro.HelpBrowserMenu3-2:\Savancer d'une page dans l'historique local.|ML'information du formlaire n'est pas réenvoyée.
+fr.ro.HelpBrowserMenu3-2:\Savancer d’une page dans l’historique local.|ML’information du formlaire n’est pas réenvoyée.
it.ro.HelpBrowserMenu3-2:\Svai avanti di una pagina nella cronologia locale.|MLe informazioni contenute nel form non verranno inviate.
nl.ro.HelpBrowserMenu3-2:Klik met KIES om 1 pagina vooruit in de venstergeschiedenis te gaan.|MLet op! Formulierinformatie wordt niet opnieuw ingediend.
+zh_CN.ro.HelpBrowserMenu3-2:\S在本地历å²è®°å½•ä¸­å‰è¿›ä¸€é¡µã€‚|Mä¸é‡æ–°æ交表格信æ¯ã€‚
+
en.ro.HelpBrowserMenu3-3:\Straverse up one level in the directory tree.
de.ro.HelpBrowserMenu3-3:Wechselt in das übergeordnete Verzeichnis in der Hierarchie des Verzeichnisbaumes.
fr.ro.HelpBrowserMenu3-3:\Straverse up one level in the directory tree.
it.ro.HelpBrowserMenu3-3:\Sscorri in alto di un livello rispetto all'albero della directory.
nl.ro.HelpBrowserMenu3-3:Klik met KIES om 1 niveau omhoog te gaan in de websitehiërarchie.
+zh_CN.ro.HelpBrowserMenu3-3:\S移动到上一级目录。
+
en.ro.HelpBrowserMenu3-4:\Sfetch the current page again.
de.ro.HelpBrowserMenu3-4:Lädt die aktuelle Seite erneut.|MDie Seite wird aktualisiert. Ältere Informationen zu dieser Seite, die noch im lokalen Zwischenpuffer gespeichert sind, werden dabei überschrieben.
fr.ro.HelpBrowserMenu3-4:\Srecommencer le chargement de la page courante.
it.ro.HelpBrowserMenu3-4:\Sottieni nuovamente la pagina corrente.
nl.ro.HelpBrowserMenu3-4:Klik met KIES om deze pagina opnieuw op te halen.
+zh_CN.ro.HelpBrowserMenu3-4:\Så†æ¬¡èŽ·å–当å‰é¡µé¢ã€‚
+
en.ro.HelpBrowserMenu3-5:\Sstop NetSurf from continuing to load this page.
de.ro.HelpBrowserMenu3-5:Unterbricht den Ladevorgang und alle anderen Prozesse im aktuellen Browserfenster.
fr.ro.HelpBrowserMenu3-5:\Sarrêter le chargement de la page par NetSurf.
it.ro.HelpBrowserMenu3-5:\Simpedisci a NetSurf di continuare a caricare questa pagina.
nl.ro.HelpBrowserMenu3-5:Klik met KIES om het ophaalproces van deze pagina te stoppen.
+zh_CN.ro.HelpBrowserMenu3-5:\S阻止 NetSurf 继续加载此页é¢ã€‚
+
en.ro.HelpBrowserMenu4:\Rset the local display options.
de.ro.HelpBrowserMenu4:Untermenü Anzeige.|MFestlegen der Darstellungsparameter für das Browserfenster.
-fr.ro.HelpBrowserMenu4:\Rdéfinir les options d'affichage locales.
+fr.ro.HelpBrowserMenu4:\Rdéfinir les options d’affichage locales.
it.ro.HelpBrowserMenu4:\Rimposta le opzioni di visualizzazione locale.
nl.ro.HelpBrowserMenu4:Verplaats de muispijl naar rechts om de weergavemogelijkheden van dit browservenster aan te passen.
+zh_CN.ro.HelpBrowserMenu4:\R设置本地显示的选项。
+
en.ro.HelpBrowserMenu4-0:\Rscale the page, affecting both text and images.
de.ro.HelpBrowserMenu4-0:Ändern der Größe der Darstellung. Beeinflußt werden Text und Bilder.
fr.ro.HelpBrowserMenu4-0:\Rredimensionner la page, y compris texte et images.
it.ro.HelpBrowserMenu4-0:\Rscala la pagina, questo agirà sia sul testo che sulle immagini.
nl.ro.HelpBrowserMenu4-0:Verplaats de muispijl naar rechts om de pagina te schalen, inclusief tekst en afbeeldingen.
+zh_CN.ro.HelpBrowserMenu4-0:\R缩放页é¢ï¼ŒåŒæ—¶æ”¹å˜æ–‡æœ¬å’Œå›¾åƒã€‚
+
en.ro.HelpBrowserMenu4-1:\Rset the local image options.
de.ro.HelpBrowserMenu4-1:Optionen zur Anzeige von Bildern.
-fr.ro.HelpBrowserMenu4-1:\Rdéfinir les options d'images locales.
+fr.ro.HelpBrowserMenu4-1:\Rdéfinir les options d’images locales.
it.ro.HelpBrowserMenu4-1:\Rimposta le opzioni relative alle immagini locali.
nl.ro.HelpBrowserMenu4-1:Verplaats de muispijl naar rechts om de afbeeldingsmogelijkheden van dit browservenster aan te passen.
+zh_CN.ro.HelpBrowserMenu4-1:\R设置本地图åƒçš„选项。
+
en.ro.HelpBrowserMenu4-1-0:\Stoggle the display of foreground images.
de.ro.HelpBrowserMenu4-1-0:\Stoggle the display of foreground images.
fr.ro.HelpBrowserMenu4-1-0:\Stoggle the display of foreground images.
-it.ro.HelpBrowserMenu4-1-0:\SAlterna la visualizzazione delle immagini in primo piano.
+it.ro.HelpBrowserMenu4-1-0:\Salterna la visualizzazione delle immagini in primo piano.
nl.ro.HelpBrowserMenu4-1-0:Klik met KIES om het tonen van voorgrondafbeeldingen aan of uit te zetten.
+zh_CN.ro.HelpBrowserMenu4-1-0:\S切æ¢æ˜¾ç¤ºå‰æ™¯å›¾åƒã€‚
+
en.ro.HelpBrowserMenu4-1-1:\Stoggle the display of background images.
de.ro.HelpBrowserMenu4-1-1:Schaltet Hintergrundbilder ein/aus.
fr.ro.HelpBrowserMenu4-1-1:\Safficher ou pas des images de fond.
it.ro.HelpBrowserMenu4-1-1:\Salterna la visualizzazione delle immagini di sfondo.
nl.ro.HelpBrowserMenu4-1-1:Klik met KIES om het tonen van achtergrondafbeeldingen aan of uit te zetten.
+zh_CN.ro.HelpBrowserMenu4-1-1:\S切æ¢æ˜¾ç¤ºèƒŒæ™¯å›¾åƒã€‚
+
en.ro.HelpBrowserMenu4-1-2:\Stoggle the display of animations.|MIf turned off, the first frame is displayed.
de.ro.HelpBrowserMenu4-1-2:Schaltet Animationen ein/aus.|MBei ausgeschalteter Animation, wird nur das erste Teilbild (Frame) angezeigt.
fr.ro.HelpBrowserMenu4-1-2:\Safficher ou pas des animations.|MSi les animations ne sont pas montrées, seule la première image est affichée.
it.ro.HelpBrowserMenu4-1-2:\Salterna la visualizzazione delle animazioni.|MSe disattivato verrà visualizzato solo il primo frame.
nl.ro.HelpBrowserMenu4-1-2:Klik met KIES om het tonen van animaties aan of uit te zetten.|MWanneer uitgezet, wordt de eerste afbeelding van de animatie getoond.
+zh_CN.ro.HelpBrowserMenu4-1-2:\S切æ¢æ˜¾ç¤ºåŠ¨ç”»ã€‚|M如果关闭,则会显示第一帧动画。
+
en.ro.HelpBrowserMenu4-2:\Rcontrol the display of NetSurf's toolbars.
de.ro.HelpBrowserMenu4-2:Optionen zur Anzeige von Kontroll- und Steuerelementen.
-fr.ro.HelpBrowserMenu4-2:\Rcontroler l'affichage des barres d'outils de NetSurf.
+fr.ro.HelpBrowserMenu4-2:\Rcontroler l’affichage des barres d’outils de NetSurf.
it.ro.HelpBrowserMenu4-2:\Rcontrolla la visualizzazione delle barre strumenti di NetSurf.
nl.ro.HelpBrowserMenu4-2:Verplaats de muispijl naar rechts om de gereedschapbalken aan te passen.
+zh_CN.ro.HelpBrowserMenu4-2:\R控制显示 NetSurf 工具æ ã€‚
+
en.ro.HelpBrowserMenu4-2-0:\Stoggle the display of the toolbar buttons.|MURL bar uses the remaining space.
de.ro.HelpBrowserMenu4-2-0:Schaltet die Schaltknöpfe am oberen Fensterrand ein/aus.|MDie Länge der Adressleiste wird angepaßt.
-fr.ro.HelpBrowserMenu4-2-0:\Safficher ou pas les boutons de la barre d'outil.|MLa barre d'URL utilise l'espace restant.
+fr.ro.HelpBrowserMenu4-2-0:\Safficher ou pas les boutons de la barre d’outil.|MLa barre d’URL utilise l’espace restant.
it.ro.HelpBrowserMenu4-2-0:\Salterna la visualizzazione dei pulsanti della barra strumenti.|MLa barra URL coprirà lo spazio eccedente.
nl.ro.HelpBrowserMenu4-2-0:Klik met KIES om het tonen van de knoppen op de gereedschapbalk aan of uit te zetten.|MHet adresveld gebruikt de overblijvende vrijkomende ruimte.
+zh_CN.ro.HelpBrowserMenu4-2-0:\S切æ¢æ˜¾ç¤ºå·¥å…·æ æŒ‰é’®ã€‚|M 地å€æ ä½¿ç”¨å‰©ä½™çš„空间。
+
en.ro.HelpBrowserMenu4-2-1:\Stoggle the display of the address (URL) bar.
de.ro.HelpBrowserMenu4-2-1:Schaltet die Adressleiste am oberen Fensterrand ein/aus.
-fr.ro.HelpBrowserMenu4-2-1:\Safficher ou pas la barre d'adresse (URL).
+fr.ro.HelpBrowserMenu4-2-1:\Safficher ou pas la barre d’adresse (URL).
it.ro.HelpBrowserMenu4-2-1:\Salterna la visualizzazione della barra indirizzi (URL).
nl.ro.HelpBrowserMenu4-2-1:Klik met KIES om het tonen van het (web)adresveld aan of uit te zetten.
+zh_CN.ro.HelpBrowserMenu4-2-1:\S切æ¢æ˜¾ç¤ºåœ°å€(URL)æ ã€‚
+
en.ro.HelpBrowserMenu4-2-2:\Stoggle the display of the throbber.|MURL bar uses the remaining space.
de.ro.HelpBrowserMenu4-2-2:Schaltet die Ladeaktivitätsanzeige am oberen Fensterrand ein/aus.|MDie Länge der Adressleiste wird angepaßt.
-fr.ro.HelpBrowserMenu4-2-2:\Safficher le pulseur ou pas.|MLa barre d'URL utilise l'espace restant.
+fr.ro.HelpBrowserMenu4-2-2:\Safficher le pulseur ou pas.|MLa barre d’URL utilise l’espace restant.
it.ro.HelpBrowserMenu4-2-2:\Salterna la visualizzazione del throbber.|MLa barra URL coprirà lo spazio eccedente.
nl.ro.HelpBrowserMenu4-2-2:Klik met KIES om het tonen van de (laad)Activiteitsindicator aan of uit te zetten.|MHet adresveld gebruikt de overblijvende vrijkomende ruimte.
+zh_CN.ro.HelpBrowserMenu4-2-2:\S切æ¢æ˜¾ç¤ºåŠ¨æ€æµè§ˆå›¾ç¤ºã€‚|M 地å€æ ä½¿ç”¨å‰©ä½™çš„空间。
+
en.ro.HelpBrowserMenu4-2-3:\Stoggle toolbar edit mode.
de.ro.HelpBrowserMenu4-2-3:Schaltet in den Modus zur Bearbeitung der Iconleiste am oberen Fensterrand.
-fr.ro.HelpBrowserMenu4-2-3:\Schanger le mode d'édition de barre d'outils.
+fr.ro.HelpBrowserMenu4-2-3:\Schanger le mode d’édition de barre d’outils.
it.ro.HelpBrowserMenu4-2-3:\Salterna la modalità di modifica della barra strumenti.
nl.ro.HelpBrowserMenu4-2-3:Klik met KIES om de aanpasmodus van de gereedschapbalk in of uit te schakelen. Wanneer ingeschakelt, verschijnt er een balk onder de gereedschapbalk met extra knoppen die van en naar deze balk gesleept kunnen worden om deze aan te passen.
+zh_CN.ro.HelpBrowserMenu4-2-3:\S切æ¢å·¥å…·æ ç¼–辑模å¼ã€‚
+
en.ro.HelpBrowserMenu4-3:\Scontrol the manner in which the display is rendered.
de.ro.HelpBrowserMenu4-3:Einstellungen zur Berechnung der Seitendarstellung.
-fr.ro.HelpBrowserMenu4-3:\Scontroler la façon d'afficher.
+fr.ro.HelpBrowserMenu4-3:\Scontroler la façon d’afficher.
it.ro.HelpBrowserMenu4-3:\Scontrolla il modo in cui è resa l'esposizione.
nl.ro.HelpBrowserMenu4-3:Verplaats de muispijl naar rechts om de pagina-opbouwmethodes aan te passen.
+zh_CN.ro.HelpBrowserMenu4-3:\S控制显示的渲染方å¼ã€‚
+
en.ro.HelpBrowserMenu4-3-0:\Stoggle whether animations are not displayed until all calculations are complete.
de.ro.HelpBrowserMenu4-3-0:Schaltet das Puffern von Objekten ein/aus.|MNachzuzeichnende Objekte, z.B. Bildanimationen oder Textbereiche, werden zwischengespeichert um Flackern zu vermeiden.
fr.ro.HelpBrowserMenu4-3-0:\Sdécider si les animations sont affichées quand tous les calculs sont terminés (ou avant).
it.ro.HelpBrowserMenu4-3-0:\Simposta la non visualizzazione delle animazioni fino al completamento della procedura di calcolo.
nl.ro.HelpBrowserMenu4-3-0:Klik met KIES om animaties pas te tonen, nadat alle opgehaalde paginagegevens zijn verwerkt, aan of uit te zetten.
+zh_CN.ro.HelpBrowserMenu4-3-0:\S切æ¢æ˜¯å¦åœ¨æ‰€æœ‰è®¡ç®—完æˆä¹‹å‰ä¸æ˜¾ç¤ºåŠ¨ç”»ã€‚
+
en.ro.HelpBrowserMenu4-3-1:\Stoggle whether everything is not displayed until all calculations are complete.
de.ro.HelpBrowserMenu4-3-1:Schaltet das Puffern der gesamten Seitenberechnung ein/aus.|MDie komplette Seite wird nach Berechnung und Aufbau zwischengespeichert. Das ist vorteilhaft bei großen Hintergrundbildern und vielen sich überschneidenden Seitenelementen.
fr.ro.HelpBrowserMenu4-3-1:\Sdécider si tout doit être affiché quand tous les calculs sont terminés (ou avant).
it.ro.HelpBrowserMenu4-3-1:\Simposta la non visualizzazione di tutto il processo fino al completamento della procedura di calcolo.
nl.ro.HelpBrowserMenu4-3-1:Klik met KIES om het niet eerder tonen van de gehele pagina, nadat alle opgehaalde paginagegevens zijn verwerkt aan of uit te zetten.
+zh_CN.ro.HelpBrowserMenu4-3-1:\S切æ¢æ˜¯å¦åœ¨æ‰€æœ‰è®¡ç®—完æˆä¹‹å‰ä¸æ˜¾ç¤ºæ‰€æœ‰å†…容。
+
en.ro.HelpBrowserMenu4-4:\Smake your local display options the default options for NetSurf.
de.ro.HelpBrowserMenu4-4:Übernimmt die vorgenommenen Anzeigeeinstellungen als globale Standardwerte für die Darstellung aller weiteren Seiten.
-fr.ro.HelpBrowserMenu4-4:\Spromouvoir vos options d'affichage locales en options par défaut pour NetSurf.
+fr.ro.HelpBrowserMenu4-4:\Spromouvoir vos options d’affichage locales en options par défaut pour NetSurf.
it.ro.HelpBrowserMenu4-4:\Simposta come predefinite tutte le impostazioni di visualizzazione.
nl.ro.HelpBrowserMenu4-4:Klik met KIES om de gekozen weergave van dit browservenster als de standaardinstelling voor NetSurf te maken.
+zh_CN.ro.HelpBrowserMenu4-4:\S将本地显示选项设置为 NetSurf 的默认选项。
+
en.ro.HelpBrowserMenu4-5:\Rcontrol the default \w positioning.
de.ro.HelpBrowserMenu4-5:Kontrolle über Anordnung und Positionierung neuer Fenster.
fr.ro.HelpBrowserMenu4-5:\Rcontroler le positionnement de fenêtre par défaut.
it.ro.HelpBrowserMenu4-5:\Rimposta il posizionamento predefinito della finestra.
nl.ro.HelpBrowserMenu4-5:Verplaats de muispijl naar rechts om de standaardvensterpositionering en omvang aan te passen
+zh_CN.ro.HelpBrowserMenu4-5:\R控制默认的 \w ä½ç½®ã€‚
+
en.ro.HelpBrowserMenu4-5-0:\S make the current \w position the default.
de.ro.HelpBrowserMenu4-5-0:Die Position des aktuellen Fensters wird als globaler Standardwert übernommen. Alle nachfolgend neu geöffneten Fenster werden an dieser Position plaziert.
fr.ro.HelpBrowserMenu4-5-0:\Spromouvoir la position de fenêtre courante en celle par défault.
it.ro.HelpBrowserMenu4-5-0:\Simposta come predefinita la posizione corrente della finestra.
nl.ro.HelpBrowserMenu4-5-0:Klik met KIES om deze vensterpositie en omvang als standaard te maken.
+zh_CN.ro.HelpBrowserMenu4-5-0:\S å°†å½“å‰ \w ä½ç½®è®¾ç½®ä¸ºé»˜è®¤ä½ç½®ã€‚
+
en.ro.HelpBrowserMenu4-5-1:\S toggle whether subsequent windows are staggered down the screen.
de.ro.HelpBrowserMenu4-5-1:Neu geöffnete Fenster werden nicht alle an der Standardposition sondern zueinander leicht versetzt plaziert.
-fr.ro.HelpBrowserMenu4-5-1:\Sdécider si les fenêtres suivantes doivent être ouvertes en décalage à l'écran.
+fr.ro.HelpBrowserMenu4-5-1:\Sdécider si les fenêtres suivantes doivent être ouvertes en décalage à l’écran.
it.ro.HelpBrowserMenu4-5-1:\Simposta nel caso le finestre successive siano sfalsate rispetto alla parte bassa dello schermo.
nl.ro.HelpBrowserMenu4-5-1:Klik met KIES om het verticaal stapelen van nieuwe browservensters aan of uit te zetten.
+zh_CN.ro.HelpBrowserMenu4-5-1:\S 切æ¢åŽç»­çª—å£æ˜¯å¦åœ¨å±å¹•ä¸Šäº¤é”™æ˜¾ç¤ºã€‚
+
en.ro.HelpBrowserMenu4-5-2:\S toggle whether child windows copy the size and position of their parent.|MWhen off, all new windows open in the default position.
de.ro.HelpBrowserMenu4-5-2:Neue Fenster behalten die Größe des Fensters, aus dem heraus sie geöffnet werden, bei.
fr.ro.HelpBrowserMenu4-5-2:\Sdécider si les fenêtres-filles doivent être ouvertes à la même taille que celle de leurs parents.
it.ro.HelpBrowserMenu4-5-2:\Salterna nel caso le finestre figlie seguano la dimensione ed il posizionamento di quelle genitrici.|MSe disattivato tutte le finestre verranno aperte nel posizionamento predefinito.
nl.ro.HelpBrowserMenu4-5-2:Klik met KIES om aan of uit te zetten, dat de positie en omvang van het opvolgende venster gelijk is aan het voorgaande venster.
+zh_CN.ro.HelpBrowserMenu4-5-2:\S切æ¢å­çª—å£æ˜¯å¦å¤åˆ¶å…¶çˆ¶çª—å£çš„大å°å’Œä½ç½®ã€‚|M关闭åŽï¼Œæ‰€æœ‰æ–°çª—å£éƒ½å°†åœ¨é»˜è®¤ä½ç½®æ‰“开。
+
en.ro.HelpBrowserMenu4-5-3:\S return to the default \w positioning.
de.ro.HelpBrowserMenu4-5-3:Setzt die festgelegte Standardposition für Fenster auf einen in NetSurf voreingestellten Wert zurück.
fr.ro.HelpBrowserMenu4-5-3:\Srevenir au positionnement de fenêtre par défaut.
it.ro.HelpBrowserMenu4-5-3:\Sritorna al posizionamento della finestra predefinito.
nl.ro.HelpBrowserMenu4-5-3:Klik met KIES om de vensterpositie en omvang terug te zetten naar de oorspronkelijke standaardwaarden.
+zh_CN.ro.HelpBrowserMenu4-5-3:\S 返回默认的\w ä½ç½®ã€‚
+
en.ro.HelpBrowserMenu5:\Raccess NetSurf's built in utilities.|MUtilities are tools such as the hotlist, history tree and various setup options.
de.ro.HelpBrowserMenu5:Untermenü Werkzeuge.|MEnthält verschiedene nützliche Zusatz- und Sonderfunktionen.
-fr.ro.HelpBrowserMenu5:\Raccéder aux utilitaires intégrés à NetSurf.|MLes utilitaires sont des outils comme les favoris, l'historique arborescent et diverses options de configuration.
+fr.ro.HelpBrowserMenu5:\Raccéder aux utilitaires intégrés à NetSurf.|MLes utilitaires sont des outils comme les marque-pages, l’historique arborescent et diverses options de configuration.
it.ro.HelpBrowserMenu5:\Raccedi a NetSurf attraverso le utilità.|MLe utilità sono strumenti simili ai segnalibri, gli alberi della cronologia e le altre opzioni di configurazione.
nl.ro.HelpBrowserMenu5:Verplaats de muispijl naar rechts om toegang te krijgen tot NetSurf's ingebouwde mogelijkheden.|MMogelijkheden zijn bijvoorbeeld gereedschappen zoals de favorietenlijst, de browsergeschiedenis en verschillende instelmogelijkheden.
+zh_CN.ro.HelpBrowserMenu5:\R访问 NetSurf 的内置实用程åºã€‚|M实用程åºæ˜¯è¯¸å¦‚常用列表,历å²è®°å½•æ ‘å’Œå„ç§è®¾ç½®é€‰é¡¹ä¹‹ç±»çš„工具。
+
en.ro.HelpBrowserMenu5-0:\Rmanage the hotlist.
de.ro.HelpBrowserMenu5-0:Verwaltung der Hotlist.
-fr.ro.HelpBrowserMenu5-0:\Rgérer les favoris.
+fr.ro.HelpBrowserMenu5-0:\Rgérer les marque-pages.
it.ro.HelpBrowserMenu5-0:\Rgestisci i segnalibri.
nl.ro.HelpBrowserMenu5-0:Verplaats de muispijl naar rechts om de favorietenlijst te beheren.
+zh_CN.ro.HelpBrowserMenu5-0:\R管ç†å¸¸ç”¨åˆ—表。
+
en.ro.HelpBrowserMenu5-0-0:\Sadd the current page to the hotlist.
de.ro.HelpBrowserMenu5-0-0:Anklicken trägt die Adresse der aktuellen Seite in die Hotlist ein.
-fr.ro.HelpBrowserMenu5-0-0:\Sajouter la page en cours aux favoris.
+fr.ro.HelpBrowserMenu5-0-0:\Sajouter la page courante aux marque-pages.
it.ro.HelpBrowserMenu5-0-0:\Saggiungi la pagina corrente ai segnalibri
nl.ro.HelpBrowserMenu5-0-0:Klik met KIES om deze pagina aan de favorietenlijst toe te voegen.
+zh_CN.ro.HelpBrowserMenu5-0-0:\S将当å‰é¡µé¢æ·»åŠ åˆ°å¸¸ç”¨åˆ—表。
+
en.ro.HelpBrowserMenu5-0-1:\Sopen the hotlist management \w.
de.ro.HelpBrowserMenu5-0-1:Öffnet die Hotlist.
-fr.ro.HelpBrowserMenu5-0-1:\Souvrir la \w de gestion des favoris.
+fr.ro.HelpBrowserMenu5-0-1:\Souvrir la \w de gestion des marque-pages.
it.ro.HelpBrowserMenu5-0-1:\Sapri la finestra del gestore dei segnalibri
nl.ro.HelpBrowserMenu5-0-1:Klik met KIES om de favorietenlijst te openen.
+zh_CN.ro.HelpBrowserMenu5-0-1:\S打开常用列表管ç†å™¨ \w。
+
en.ro.HelpBrowserMenu5-1:\Rview the history options.
de.ro.HelpBrowserMenu5-1:Zugriff auf die History Funktionen.|MIn die History werden bereits besuchte Webseiten eingetragen. Dies erlaubt das einfache Wiederfinden einmal gesehener Web-Inhalte.
fr.ro.HelpBrowserMenu5-1:\Rview the history options.
it.ro.HelpBrowserMenu5-1:\Rmostra le opzioni della cronologia
nl.ro.HelpBrowserMenu5-1:Verplaats de muispijl naar rechts om de geschiedenismogelijkheden te tonen.
+zh_CN.ro.HelpBrowserMenu5-1:\R查看历å²è®°å½•é€‰é¡¹ã€‚
+
en.ro.HelpBrowserMenu5-1-0:\Sopen the local history \w.
de.ro.HelpBrowserMenu5-1-0:Anklicken mit AUSWAHL öffnet das Fenster mit der lokalen History.|MIn der lokalen History werden alle Webseiten notiert, die mit dem aktuellen Browserfenster bereits besucht worden waren.
-fr.ro.HelpBrowserMenu5-1-0:\Souvrir la \w d'historique local.
+fr.ro.HelpBrowserMenu5-1-0:\Souvrir la \w d’historique local.
it.ro.HelpBrowserMenu5-1-0:\Sapri la cronologia locale
nl.ro.HelpBrowserMenu5-1-0:Klik met KIES om de venstergeschiedenis te openen.
+zh_CN.ro.HelpBrowserMenu5-1-0:\S打开本地历å²è®°å½• \w。
+
en.ro.HelpBrowserMenu5-1-1:\Sopen the global history \w.
de.ro.HelpBrowserMenu5-1-1:Anklicken mit AUSWAHL öffnet das Fenster mit der globalen History.|MIn der globalen History werden alle mit NetSurf besuchten Webseiten notiert.
-fr.ro.HelpBrowserMenu5-1-1:\Souvrir la fenêtre d'historique global.
+fr.ro.HelpBrowserMenu5-1-1:\Souvrir la fenêtre d’historique global.
it.ro.HelpBrowserMenu5-1-1:\Sapri la cronologia globale
nl.ro.HelpBrowserMenu5-1-1:Klik met KIES om de browsergeschiedenis te openen.
+zh_CN.ro.HelpBrowserMenu5-1-1:\S打开全局历å²è®°å½• \w。
+
en.ro.HelpBrowserMenu5-2:\Rmanage your cookies.
de.ro.HelpBrowserMenu5-2:Cookies bearbeiten.
-fr.ro.HelpBrowserMenu5-2:\Rgérer vos favoris.
-it.ro.HelpBrowserMenu5-2:\Rgestisci i tuoi cookie
+fr.ro.HelpBrowserMenu5-2:\Rgérer vos cookies.
+it.ro.HelpBrowserMenu5-2:\Rgestisci i tuoi cookie.
nl.ro.HelpBrowserMenu5-2:Verplaats de muispijl naar rechts om de cookies te beheren.
+zh_CN.ro.HelpBrowserMenu5-2:\R管ç†æ‚¨çš„ Cookies。
+
en.ro.HelpBrowserMenu5-2-0:\Sopen the cookie management \w.
de.ro.HelpBrowserMenu5-2-0:Anklicken um die gespeicherten Cookies anzusehen und zu bearbeiten.
fr.ro.HelpBrowserMenu5-2-0:\Souvrir la fenêtre de gestion des cookies.
it.ro.HelpBrowserMenu5-2-0:\Sapri la finestra del gestore dei cookie
nl.ro.HelpBrowserMenu5-2-0:Klik met KIES om het cookiesbeheervenster te openen.
+zh_CN.ro.HelpBrowserMenu5-2-0:\S打开 Cookie ç®¡ç† \w。
+
en.ro.HelpBrowserMenu5-2-1:\Sdelete all stored cookies.
de.ro.HelpBrowserMenu5-2-1:\Sdelete all stored cookies.
fr.ro.HelpBrowserMenu5-2-1:\Sdelete all stored cookies.
it.ro.HelpBrowserMenu5-2-1:\Scancella tutti i cookie salvati.
nl.ro.HelpBrowserMenu5-2-1:Klik met KIES om alle opgeslagen cookies te verwijderen.
+zh_CN.ro.HelpBrowserMenu5-2-1:\S删除所有ä¿å­˜çš„ Cookies。
+
en.ro.HelpBrowserMenu6:\Rsee the help resources available.
de.ro.HelpBrowserMenu6:Untermenü Hilfe.|MZeigt Informationen zu und über NetSurf.
-fr.ro.HelpBrowserMenu6:\Rvoir l'aide disponible.
+fr.ro.HelpBrowserMenu6:\Rvoir l’aide disponible.
it.ro.HelpBrowserMenu6:\Rmostra la documentazione disponibile
nl.ro.HelpBrowserMenu6:Verplaats de muispijl naar rechts om extra hulp en informatie te raadplegen, indien deze beschikbaar is.
+zh_CN.ro.HelpBrowserMenu6:\R查看å¯ç”¨çš„帮助资æºã€‚
+
en.ro.HelpBrowserMenu6-0:\Sopen the documentation contents page in a new \w.
de.ro.HelpBrowserMenu6-0:Öffnet die NetSurf Dokumentation in einem neuen Browserfenster.
fr.ro.HelpBrowserMenu6-0:\Souvrir la page de documentation dans une nouvelle fenêtre.
it.ro.HelpBrowserMenu6-0:\Sapri i contenuti della documentazione in una nuova finestra
nl.ro.HelpBrowserMenu6-0:Klik met KIES om de inhoudsopgave van de documentatie in een nieuw browservenster te openen.
+zh_CN.ro.HelpBrowserMenu6-0:\S在新的 \w 中打开文档内容页é¢ã€‚
+
en.ro.HelpBrowserMenu6-1:\Sopen the user guide in a new \w.
de.ro.HelpBrowserMenu6-1:Öffnet das NetSurf Handbuch in einem neuen Browserfenster.
-fr.ro.HelpBrowserMenu6-1:\Souvrir le guide de l'utilisateur dans une nouvelle fenêtre.
+fr.ro.HelpBrowserMenu6-1:\Souvrir le guide de l’utilisateur dans une nouvelle fenêtre.
it.ro.HelpBrowserMenu6-1:\Sapri la guida in linea in una nuova finestra
nl.ro.HelpBrowserMenu6-1:Klik met KIES om de gebruikershandleiding in een nieuw browservenster te openen.
+zh_CN.ro.HelpBrowserMenu6-1:\S在新的 \w 中打开用户指å—。
+
en.ro.HelpBrowserMenu6-2:\Sopen the user information page in a new \w.
de.ro.HelpBrowserMenu6-2:Öffnet eine Seite mit allgemeinen Informationen zu NetSurf in einem neuen Browserfenster.
-fr.ro.HelpBrowserMenu6-2:\Souvrir la page d'information de l'utilisateur dans une nouvelle fenêtre.
+fr.ro.HelpBrowserMenu6-2:\Souvrir la page d’information de l’utilisateur dans une nouvelle fenêtre.
it.ro.HelpBrowserMenu6-2:\Sapri la pagina delle informazioni utente in una nuova finestra
nl.ro.HelpBrowserMenu6-2:Klik met KIES om de gebruikersinformatie in een nieuw browservenster te openen.
+zh_CN.ro.HelpBrowserMenu6-2:\S在新的 \w 中打开用户信æ¯é¡µé¢ã€‚
+
en.ro.HelpBrowserMenu6-3:\Sopen the about:credits page in a new \w.
de.ro.HelpBrowserMenu6-3:\Sopen the about:credits page in a new \w.
fr.ro.HelpBrowserMenu6-3:\Sopen the about:credits page in a new \w.
-it.ro.HelpBrowserMenu6-3:\Sapri la pagina about:credits in una nuova finestra
+it.ro.HelpBrowserMenu6-3:\Sapri la pagina informazioni:ringraziamenti in una nuova finestra
nl.ro.HelpBrowserMenu6-3:Klik met KIES om de bijdragenpagina "about:credits" in een nieuw browservenster te openen.
+zh_CN.ro.HelpBrowserMenu6-3:\S在新的 \w 中打开 about:credits 页é¢ã€‚
+
en.ro.HelpBrowserMenu6-4:\Sopen the about:licence page in a new \w.
de.ro.HelpBrowserMenu6-4:\Sopen the about:licence page in a new \w.
fr.ro.HelpBrowserMenu6-4:\Sopen the about:licence page in a new \w.
-it.ro.HelpBrowserMenu6-4:\Sapri la pagina about:licence in una nuova finestra
+it.ro.HelpBrowserMenu6-4:\Sapri la pagina informazioni:licenza in una nuova finestra
nl.ro.HelpBrowserMenu6-4:Klik met KIES om de licentiepagina "about:licence" in een nieuw browservenster te openen.
+zh_CN.ro.HelpBrowserMenu6-4:\S在新的 \w 中打开 about:licence 页é¢ã€‚
+
en.ro.HelpBrowserMenu6-5:\Srun Help.
de.ro.HelpBrowserMenu6-5:Lädt die interaktive Hilfe.
fr.ro.HelpBrowserMenu6-5:\Slancer Help.
-it.ro.HelpBrowserMenu6-5:\Savvia la guida in linea
+it.ro.HelpBrowserMenu6-5:\Sapri la guida in linea.
nl.ro.HelpBrowserMenu6-5:Klik met KIES om het interactieve hulpprogramma !Help op te starten.
+zh_CN.ro.HelpBrowserMenu6-5:\Sè¿è¡Œå¸®åŠ©ã€‚
en.ro.HelpBrowser-1:Click \s on a link to follow it.|MClick \a on a link to open it in a new \w.|MShift+\s click on a link to download the link target contents.|MShift+\a click to save the link target address.
de.ro.HelpBrowser-1:Das ist ein Browserfenster.|MEinen Link mit AUSWAHL anklicken, um ihm zu folgen.|MEinen Link mit SPEZIAL anklicken, um ihn in einem neuen Fenster zu öffnen.|MShift+AUSWAHL über einem Verweis lädt den verlinkten Inhalt herunter.|MShift+SPEZIAL über einem Link klicken zum Speichern der Adresse des Verweises.
-fr.ro.HelpBrowser-1:Cliquer \s sur un lien pour le suivre.|MCliquer \a sur un lien pour l'ouvrir dans une nouvelle \w.|MShift+\s click on a link to download the link target contents.|MShift+\a click to save the link target address.
+fr.ro.HelpBrowser-1:Cliquer \s sur un lien pour le suivre.|MCliquer \a sur un lien pour l’ouvrir dans une nouvelle \w.|MShift+\s click on a link to download the link target contents.|MShift+\a click to save the link target address.
it.ro.HelpBrowser-1:Clicca \s sul link per procedere.|MClicca \a in un link per aprirlo in una nuova finestra|MShift+\s clicca sul link per scaricarne i contenuti.|MShift+\a clicca per salvare l'indirizzo del link.
nl.ro.HelpBrowser-1:Klik met KIES op een koppeling om deze te volgen.|MKlik met PASAAN om de koppeling in een nieuw venster te openen.|MKlik met SHIFT+KIES om de inhoud op te halen voor opslag.|MKlik met SHIFT+PASAAN om het koppelingsadres te bewaren.
+zh_CN.ro.HelpBrowser-1:å•å‡»é“¾æŽ¥ä¸Šçš„ \s 以跟éšå®ƒã€‚|Må•å‡»é“¾æŽ¥ä¸Šçš„ \a 以在新的 \w 中打开。|MShift+\s å•å‡»é“¾æŽ¥ä»¥ä¸‹è½½é“¾æŽ¥ç›®æ ‡å†…容。|MShift+\a å•å‡»ä»¥ä¿å­˜é“¾æŽ¥ç›®æ ‡ç½‘å€ã€‚
en.ro.HelpIconbar:\TNetSurf icon.|M\Sopen a new browser \w.|M\Aopen the hotlist management \w.
de.ro.HelpIconbar:Das ist das NetSurf Icon.|MKlicken mit AUSWAHL öffnet ein neues Browserfenster.|MKlicken mit SPEZIAL öffnet die Hotlist.
-fr.ro.HelpIconbar:\Tl'icône de NetSurf.|M\Souvrir une nouvelle \w de navigateur.|M\Aouvrir la fenêtre de gestion des favoris.
+fr.ro.HelpIconbar:\Tl’icône de NetSurf.|M\Souvrir une nouvelle \w de navigateur.|M\Aouvrir la fenêtre de gestion des marque-pages.
it.ro.HelpIconbar:\TIcona di NetSurf.|M\Sapri una nuova finestra|M\Aapri la finestra del gestore dei segnalibri
nl.ro.HelpIconbar:Dit is het symbool van het programma NetSurf.|MKlik met KIES om een nieuw browservenster te openen.|MKlik met PASAAN om de favorietenlijst te openen.
+zh_CN.ro.HelpIconbar:\T NetSurf 图标。|M\S打开新的æµè§ˆå™¨ \w。|M\A打开常用项列表管ç†\w。
+
en.ro.HelpHistory:Use this \w to navigate around the local history tree.|M\Son a thumbnail to return to that page.
de.ro.HelpHistory:Die History zeigt alle in dieser Sitzung besuchten Seiten.|MKlicken mit AUSWAHL auf eine Symbolgrafik kehrt zurück zur jeweiligen Seite.
-fr.ro.HelpHistory:Utiliser cette \w pour naviguer dans l'historique arborescent local.|M\Ssur une vignette pour revenir à cette page.
+fr.ro.HelpHistory:Utiliser cette \w pour naviguer dans l’historique arborescent local.|M\Ssur une vignette pour revenir à cette page.
it.ro.HelpHistory:Usa questa finestra per navigare all'interno dell'albero della cronologia locale.|M\Ssulla miniatura per tornare a quella pagina.
nl.ro.HelpHistory:Gebruik dit venster om door de structuur van de venstergeschiedenis te kunnen gaan.|MKlik met KIES op een miniatuur om terug te keren naar de pagina.
+zh_CN.ro.HelpHistory:使用此 \w 在本地历å²è®°å½•æ ‘中导航。|M\S在缩略图上返回到该页é¢ã€‚
en.ro.HelpPrint:Use this \w to print the page.
de.ro.HelpPrint:Ãœber dieses Fenster kann die Seite gedruckt werden.
fr.ro.HelpPrint:Utiliser cette fenêtre pour imprimer cette page.
it.ro.HelpPrint:Usa questa finestra per le funzionalità di stampa della pagina.
nl.ro.HelpPrint:Met dit venster kan de pagina worden afgedrukt.
+zh_CN.ro.HelpPrint:使用此 \w æ¥æ‰“å°é¡µé¢ã€‚
en.ro.HelpSaveAs0:Drag SELECT this icon to the directory in which you want to save the file.
de.ro.HelpSaveAs0:Symbol mit AUSWAHL festhalten und in ein Verzeichnisfenster ziehen, um die Datei zu speichern.
fr.ro.HelpSaveAs0:Déposer cette icône dans le repertoire où vous voulez sauver le fichier.
it.ro.HelpSaveAs0:Seleziona e sposta questa icona nella directory nella quale si desidera salvare il file.
nl.ro.HelpSaveAs0:Sleep het symbool met KIES naar een geopende map om het bestand daarin te bewaren.
+zh_CN.ro.HelpSaveAs0:将选择图标拖到您è¦ä¿å­˜çš„文件目录中。
+
en.ro.HelpSaveAs1:This is the filename under which this document will be saved.
de.ro.HelpSaveAs1:Das ist der Name unter dem die Datei gespeichert wird.
fr.ro.HelpSaveAs1:Ceci est le nom de fichier sous lequel le document sera sauvé.
it.ro.HelpSaveAs1:Questo è il nome del file con il quale il documento verrà salvato.
nl.ro.HelpSaveAs1:Dit veld toont de bestandsnaam waaronder de inhoud bewaard zal gaan worden.
+zh_CN.ro.HelpSaveAs1:用æ¥ä¿å­˜æ­¤æ–‡æ¡£çš„文件å。
+
en.ro.HelpSaveAs2:\Ssave the file with the current filename.|MIf a full path is not set, you must drag the icon to a directory.
de.ro.HelpSaveAs2:Klicken mit AUSWAHL speichert die Datei unter angezeigtem Pfad und Namen.|MWird kein voller Dateipfad angezeigt, muß die Datei per Drag & Drop gespeichert werden.
-fr.ro.HelpSaveAs2:\Ssauver le fichier avec le nom de fichier en cours.|MSi le nom de chemin n'est pas complet, il vous faudra déposer l'icône dans un répertoire.
+fr.ro.HelpSaveAs2:\Ssauver le fichier avec le nom de fichier en cours.|MSi le nom de chemin n’est pas complet, il vous faudra déposer l’icône dans un répertoire.
it.ro.HelpSaveAs2:\Ssalva il file usando il suo nome corrente.|MNel caso il percorso completo non sia impostato sposta l'icona nella directory.
nl.ro.HelpSaveAs2:Klik met KIES om het bestand met deze bestandsnaam te bewaren.|MWanneer het veld geen volledig pad toont, dan moet het symbool naar de gewenste map worden gesleept.
+zh_CN.ro.HelpSaveAs2:\S用当å‰æ–‡ä»¶åä¿å­˜æ–‡ä»¶ã€‚|M如果您未设置完整路径,则必须将图标拖到目录中。
+
en.ro.HelpSaveAs3:\Sclose this \w without saving.
de.ro.HelpSaveAs3:Klicken mit AUSWAHL um nicht zu speichern.
fr.ro.HelpSaveAs3:\Sfermer cette \w sans sauvegarder.
it.ro.HelpSaveAs3:\Schiudi questa finestra senza salvare.
nl.ro.HelpSaveAs3:Klik met KIES om dit venster te sluiten zonder het bestand te bewaren.
+zh_CN.ro.HelpSaveAs3:\S关闭此 \w 而ä¸ä¿å­˜ã€‚
en.ro.HelpScaleView:Use this \w to change the scale the page is displayed at.
de.ro.HelpScaleView:Mit diesem Dialog kann die Darstellung der Seite vergrößert oder verkleinert werden.
-fr.ro.HelpScaleView:Utiliser cette \w pour changer l'échelle d'affichage.
+fr.ro.HelpScaleView:Utiliser cette \w pour changer l’échelle d’affichage.
it.ro.HelpScaleView:Usa questa finestra per modificare la scala di visualizzazione della pagina.
nl.ro.HelpScaleView:Gebruik dit venster om de schaal van deze pagina te wijzigen.
+zh_CN.ro.HelpScaleView:使用此 \w 以更改页é¢æ˜¾ç¤ºçš„比例。
+
en.ro.HelpScaleView1:Enter the scale you wish the page to be displayed at.
de.ro.HelpScaleView1:Gewünschte Skalierung hier eingeben.
-fr.ro.HelpScaleView1:Saisissez l'échelle à laquelle vous voulez afficher cette page.
+fr.ro.HelpScaleView1:Saisissez l’échelle à laquelle vous voulez afficher cette page.
it.ro.HelpScaleView1:Inserisci la scala di visualizzazione preferita.
nl.ro.HelpScaleView1:Voer hier de gewenste schaal in waarop deze pagina getoond moet worden.
+zh_CN.ro.HelpScaleView1:输入您希望显示的页é¢æ¯”例。
+
en.ro.HelpScaleView2:\Sreduce the scale, 10% at a time.
de.ro.HelpScaleView2:Klicken mit AUSWAHL um die Skalierung um 10% zu verringern.
-fr.ro.HelpScaleView2:\Sréduire l'échelle, par pas de 10%.
+fr.ro.HelpScaleView2:\Sréduire l’échelle, par pas de 10%.
it.ro.HelpScaleView2:\Sdecrementa la scala di un 10% alla volta.
nl.ro.HelpScaleView2:Klik met KIES om de schaal met 10% per keer te verkleinen.
+zh_CN.ro.HelpScaleView2:\S缩å°æ¯”例, æ¯æ¬¡å‡å°‘ 10%。
+
en.ro.HelpScaleView3:\Sincrease the scale, 10% at a time.
de.ro.HelpScaleView3:Klicken mit AUSWAHL um die Skalierung um 10% zu erhöhen.
-fr.ro.HelpScaleView3:\Saugmenter l'échelle, par pas de 10%.
+fr.ro.HelpScaleView3:\Saugmenter l’échelle, par pas de 10%.
it.ro.HelpScaleView3:\Sincrementa la scala di un 10% alla volta.
nl.ro.HelpScaleView3:Klik met KIES om de schaal met 10% per keer te vergroten.
+zh_CN.ro.HelpScaleView3:\S放大比例, æ¯æ¬¡å¢žåŠ  10%。
+
en.ro.HelpScaleView5:Choose whether all frames will also be scaled.
de.ro.HelpScaleView5:Choose whether all frames will also be scaled.
fr.ro.HelpScaleView5:Choose whether all frames will also be scaled.
it.ro.HelpScaleView5:Scegli se scalare anche tutti i frame.
nl.ro.HelpScaleView5:Selecteer de optie optie om ook de bijbehorende frames mee te schalen.
+zh_CN.ro.HelpScaleView5:选择是å¦ä¹Ÿç¼©æ”¾æ‰€æœ‰å¸§ã€‚
+
en.ro.HelpScaleView7:\Scancel changes.|MThe current scale will not be changed.
de.ro.HelpScaleView7:Klicken mit AUSWAHL um die Skalierung nicht durchzuführen.|MDas Dialogfenster wird geschlossen.|MDie Darstellung der Seite wird unverändert beibehalten.
-fr.ro.HelpScaleView7:\Sannuler les changements.|ML'échelle en cours ne sera pas modifiée.
+fr.ro.HelpScaleView7:\Sannuler les changements.|ML’échelle en cours ne sera pas modifiée.
it.ro.HelpScaleView7:\Sannulla tutte le modifiche.|MLa scala corrente non verrà modificata.
nl.ro.HelpScaleView7:Klik met KIES om dit venster te sluiten zonder dat de gemaakte wijzigingen worden ingesteld.|MDeze schaal wordt niet gewijzigd.
+zh_CN.ro.HelpScaleView7:\S撤销更改。|Mä¸ä¼šæ›´æ”¹å½“å‰æ¯”例。
+
en.ro.HelpScaleView8:\Schange the view to the scale you have chosen.
de.ro.HelpScaleView8:Klicken mit AUSWAHL um die Seite skaliert darzustellen.|MDie Seite wird in der gewählten Vergrößerung angezeigt.
-fr.ro.HelpScaleView8:\Svalider le changement d'échelle.
+fr.ro.HelpScaleView8:\Svalider le changement d’échelle.
it.ro.HelpScaleView8:\Smodifica la visualizzazione della scala prescelta.
nl.ro.HelpScaleView8:Klik met KIES om de gekozen schaal in te stellen op deze weergave en het venster sluiten.
+zh_CN.ro.HelpScaleView8:\S将视图更改到您选定的比例。
+
en.ro.HelpSearch:Use this \w to search for text within the page.
de.ro.HelpSearch:Dialogfenster zum Suchen von Text innerhalb der dargestellten Seite.
fr.ro.HelpSearch:Utiliser cette fenêtre pour faire une recherche textuelle sur cette page.
it.ro.HelpSearch:Usa questa finestra per cercare un testo nella pagina.
nl.ro.HelpSearch:Gebruik dit venster om te zoeken naar tekst in de pagina.
+zh_CN.ro.HelpSearch:使用 \w æœç´¢é¡µé¢å†…的文本。
+
en.ro.HelpSearch0:Enter the search text. # matches any single character, * matches 0 or more characters.
de.ro.HelpSearch0:Suchtext hier eingeben. # steht für exakt ein beliebiges Zeichen. * steht für 0 oder mehrere Zeichen.
-fr.ro.HelpSearch0:Entrer la chaîne de recherche. # remplace n'importe quel caractère, * correspond à 0 ou plus caractères.
-it.ro.HelpSearch0:Enter the search text. # matches any single character, * matches 0 or more characters.
+fr.ro.HelpSearch0:Entrer la chaîne de recherche. # remplace n’importe quel caractère, * correspond à 0 ou plus caractères.
+it.ro.HelpSearch0:Inserisci un testo da cercare. # corrispondenza di ogni singolo carattere, * corrispondenza di 0 o più caratteri.
nl.ro.HelpSearch0:Voer in dit veld de zoekreeks in. # staat voor 1 willekeurig letterteken, * staat voor 0 of meerdere lettertekens.
+zh_CN.ro.HelpSearch0:输入æœç´¢æ–‡å­—。# 匹é…任何å•ä¸ªå­—符,* åŒ¹é… 0 个或多个字符。
+
en.ro.HelpSearch1:Choose whether the search should regard upper and lower case characters as different.
de.ro.HelpSearch1:Wählt ob nach Groß- und Kleinschreibung unterschieden werden soll.
-fr.ro.HelpSearch1:Choisir si la recherche accorde de l'importance à la casse (minuscules/MAJUSCULES).
-it.ro.HelpSearch1:Choose whether the search should regard upper and lower case characters as different.
+fr.ro.HelpSearch1:Choisir si la recherche accorde de l’importance à la casse (minuscules/MAJUSCULES).
+it.ro.HelpSearch1:Scegli se la ricerca deve considerare i caratteri maiuscoli e minuscoli come diversi.
nl.ro.HelpSearch1:Kies of een zoekopdracht rekening moet houden met hoofd- en kleine letters.
+zh_CN.ro.HelpSearch1:选择æœç´¢æ˜¯å¦åº”区分大写和å°å†™å­—æ¯ã€‚
+
en.ro.HelpSearch2:\Smove to the next match.
de.ro.HelpSearch2:Klicken mit AUSWAHL findet den nächsten Treffer.
-fr.ro.HelpSearch2:\Schercher l'occurence suivante.
+fr.ro.HelpSearch2:\Schercher l’occurence suivante.
it.ro.HelpSearch2:\Spassa alla prossima occorrenza
nl.ro.HelpSearch2:Klik met KIES om naar de volgende gevonden zoekreeks te gaan.
+zh_CN.ro.HelpSearch2:\S移动到下一个匹é…ä½ç½®ã€‚
+
en.ro.HelpSearch3:\Smove to the previous match.
de.ro.HelpSearch3:Klicken mit AUSWAHL sucht rückwärts im Text.
-fr.ro.HelpSearch3:\Schercher l'occurence précédente.
+fr.ro.HelpSearch3:\Schercher l’occurence précédente.
it.ro.HelpSearch3:\Spassa alla precedente occorrenza
nl.ro.HelpSearch3:Klik met KIES om naar de vorige gevonden zoekreeks te gaan.
+zh_CN.ro.HelpSearch3:\S移动到上一个匹é…ä½ç½®ã€‚
+
en.ro.HelpSearch4:\Sstop searching and close this \w.
de.ro.HelpSearch4:Klicken mit AUSWAHL bricht die Suche ab und schließt das Fenster.
fr.ro.HelpSearch4:\Sarrêter la recherche et fermer cette fenêtre.
it.ro.HelpSearch4:\Sinterrompi la ricerca e chiudi \w.
nl.ro.HelpSearch4:Klik met KIES om het zoeken te stoppen en dit venster te sluiten.
+zh_CN.ro.HelpSearch4:\Såœæ­¢æœç´¢å¹¶å…³é—­å½“å‰çš„ \w。
en.ro.HelpHotFolder:Use this \w to set the directory name.
de.ro.HelpHotFolder:Dieses Fenster verwenden, um den Verzeichnis-Namen festzulegen.
fr.ro.HelpHotFolder:Utiliser cette \w pour définir le nom de répertoire.
-it.ro.HelpHotFolder:Usa questa \w per impostare il nome della directory.
+it.ro.HelpHotFolder:Usa questa finestra per impostare il nome della directory.
nl.ro.HelpHotFolder:Gebruik dit venster om de mapnaam in te voeren.
+zh_CN.ro.HelpHotFolder:使用此 \w æ¥è®¾ç½®ç›®å½•å。
+
en.ro.HelpHotEntry:Use this \w to set the entry details.
de.ro.HelpHotEntry:Dieses Fenster verwenden, um die Details des Eintrages festzulegen.
fr.ro.HelpHotEntry:Utiliser cette \w pour définir les détails de cette entrée.
-it.ro.HelpHotEntry:Usa questa \w per impostare i dettagli dell'immissione.
+it.ro.HelpHotEntry:Usa questa finestra per impostare i dettagli dell'immissione.
nl.ro.HelpHotEntry:Gebruik dit om details van dit item in te voeren.
+zh_CN.ro.HelpHotEntry:使用此 \w æ¥è®¾ç½®æ¡ç›®è¯¦ç»†ä¿¡æ¯ã€‚
+
en.ro.HelpHotlist:\Thotlist management window.
de.ro.HelpHotlist:Das ist das Hotlist Fenster.
-fr.ro.HelpHotlist:\Tla fenêtre de gestion des favoris.
+fr.ro.HelpHotlist:\Tla fenêtre de gestion des marque-pages.
it.ro.HelpHotlist:\Tfinestra di gestione dei segnalibri.
nl.ro.HelpHotlist:Dit venster toont de favorietenlijst.
+zh_CN.ro.HelpHotlist:\T常用列表管ç†çª—å£ã€‚
+
en.ro.HelpHotlist0:\Sopen this directory.
de.ro.HelpHotlist0:Klicken mit AUSWAHL öffnet das Verzeichnis.
fr.ro.HelpHotlist0:\Souvrir ce répertoire.
it.ro.HelpHotlist0:\Sapri questa directory.
nl.ro.HelpHotlist0:Klik met KIES om deze map te openen en alle bijbehorende items uit te klappen.
+zh_CN.ro.HelpHotlist0:\S打开此目录。
+
en.ro.HelpHotlist1:\Sclose this directory.
de.ro.HelpHotlist1:Klicken mit AUSWAHL schließt das Verzeichnis.
fr.ro.HelpHotlist1:\Sfermer ce répertoire.
it.ro.HelpHotlist1:\Schiudi questa directory.
nl.ro.HelpHotlist1:Klik met KIES om deze map te sluiten en de bijbehorende items in te klappen.
+zh_CN.ro.HelpHotlist1:\S关闭此目录。
+
en.ro.HelpHotlist2:\Sshow the entry details.
de.ro.HelpHotlist2:Klicken mit AUSWAHL zeigt die Zusatzinformationen zu diesem Eintrag.
fr.ro.HelpHotlist2:\Smontrer les détails de cette entrée.
it.ro.HelpHotlist2:\Smostra dettagli di questo elemento
nl.ro.HelpHotlist2:Klik met KIES om de details van dit item te tonen.
+zh_CN.ro.HelpHotlist2:\S显示æ¡ç›®è¯¦ç»†ä¿¡æ¯ã€‚
+
en.ro.HelpHotlist3:\Shide the entry details.
de.ro.HelpHotlist3:Klicken mit AUSWAHL schließt die Zusatzanzeige.
fr.ro.HelpHotlist3:\Scacher les détails de cette entrée.
it.ro.HelpHotlist3:\Snascondi dettagli di questo elemento.
nl.ro.HelpHotlist3:Klik met KIES om de details van dit item te verbergen.
+zh_CN.ro.HelpHotlist3:\Séšè—æ¡ç›®è¯¦ç»†ä¿¡æ¯ã€‚
+
en.ro.HelpHotlist4:\Sselect this directory.|MDouble-click \s to open this directory.
de.ro.HelpHotlist4:Klicken mit AUSWAHL markiert dieses Verzeichnis.|MDoppelklicken um das Verzeichnis zu öffnen.
fr.ro.HelpHotlist4:\Ssélectionner ce répertoire.|MDouble-cliquer \s pour ouvrir ce répertoire.
-it.ro.HelpHotlist4:\Sseleziona questa directory.|MDoppio-click \s per aprire questa directory.
+it.ro.HelpHotlist4:\Sseleziona questa directory.|MFai doppio-click \s per aprire questa directory.
nl.ro.HelpHotlist4:Klik met KIES om deze map te selecteren.|MDubbelklik met KIES om deze map te openen en alle bijbehorende items uit te klappen.
+zh_CN.ro.HelpHotlist4:\S选择此目录。|MåŒå‡» \s æ¥æ‰“开此目录。
+
en.ro.HelpHotlist5:\Sselect this entry.|MDouble-click \s to launch this URL.
de.ro.HelpHotlist5:Klicken mit AUSWAHL markiert diesen Eintrag.|MDoppelklicken öffnet diesen Eintrag in einem neuen Browserfenster.
fr.ro.HelpHotlist5:\Ssélectionner cette entrée.|MDouble-cliquer \s pour lancer cette URL.
-it.ro.HelpHotlist5:\Sseleziona questo elemento.|MDoppio-click \s per avviare questo URL.
+it.ro.HelpHotlist5:\Sseleziona questo elemento.|MFai doppio-click \s per avviare questo URL.
nl.ro.HelpHotlist5:Klik met KIES om dit item te selecteren.|MDubbelklik met om de inhoud van dit adres in een nieuw browservenster te openen.
+zh_CN.ro.HelpHotlist5:\S选择此æ¡ç›®ã€‚|MåŒå‡» \s æ¥å¯åŠ¨æ­¤åœ°å€ã€‚
+
en.ro.HelpHotlist6:Release the mouse buttons to complete your selection.
de.ro.HelpHotlist6:Maustasten loslassen, um die Auswahl abzuschließen.
fr.ro.HelpHotlist6:Lâcher les boutons de souris pour terminer votre sélection.
it.ro.HelpHotlist6:Rilascia il pulsante dei mouse per completare la selezione.
nl.ro.HelpHotlist6:Laat de muisknop(pen) los om de selectie af te ronden.
+zh_CN.ro.HelpHotlist6:æ¾å¼€é¼ æ ‡é”®ä»¥å®Œæˆé€‰æ‹©ã€‚
+
en.ro.HelpHotlist7:Release the mouse buttons to move the selection.
de.ro.HelpHotlist7:Maustasten loslassen, um das Verschieben auszuführen.
fr.ro.HelpHotlist7:Lâcher les boutons de souris pour déplacer votre sélection.
it.ro.HelpHotlist7:Rilascia il pulsante del mouse per spostare la selezione.
nl.ro.HelpHotlist7:Laat de muisknop(pen) los om de selectie te kunnen verplaatsen.
+zh_CN.ro.HelpHotlist7:æ¾å¼€é¼ æ ‡é”®ä»¥æ”¹å˜é€‰æ‹©ã€‚
en.ro.HelpHotToolbar0:\Tdelete button.|M\Sdelete the current selection.
de.ro.HelpHotToolbar0:Löscht die markierten Einträge und Verzeichnisse.
fr.ro.HelpHotToolbar0:\Tle bouton Supprimer.|M\Ssupprimer la sélection courante.
-it.ro.HelpHotToolbar0:\Tcancella pulsante.|M\Scancella la selezione corrente.
+it.ro.HelpHotToolbar0:\Tpulsante cancella.|M\Scancella la selezione corrente.
nl.ro.HelpHotToolbar0:Dit is de Verwijder-knop.|MKlik met KIES om deze selectie te verwijderen.
+zh_CN.ro.HelpHotToolbar0:\T删除键。|M\S删除当å‰é€‰é¡¹ã€‚
+
en.ro.HelpHotToolbar1:\Texpand entries button.|M\Sexpand all addresses in the hotlist.|M\Acollapse all addresses in the hotlist.|MExpanded addresses show additional details, such as a visit counter.
de.ro.HelpHotToolbar1:Expandiert Einträge.|MKlicken mit AUSWAHL expandiert alle / alle markierten Einträge.|MKlicken mit SPEZIAL faltet alle / alle markierten Einträge zusammen.|MBei expandierten Einträgen werden zusätzliche Informationen angezeigt.
-fr.ro.HelpHotToolbar1:\Tle bouton de déploiement des entrées.|M\Sdéployer toutes les entrées ou seulement celle de la sélection courante.|M\ARegrouper toutes les entrées ou seulement celles de la sélection courante.|MLes entrées déployées affichent des infos supplémentaires, comme un compteur de visite.
-it.ro.HelpHotToolbar1:\Texpand entries button.|M\Sexpand all addresses in the hotlist.|M\Acollapse all addresses in the hotlist.|MExpanded addresses show additional details, such as a visit counter.
+fr.ro.HelpHotToolbar1:\Tle bouton de développement des marque-pages.|M\Sdévelopper toutes les entrées.|M\Aréduire toutes les entrées.|MLes entrées développées affichent des détails supplémentaires, comme un compteur de visite.
+it.ro.HelpHotToolbar1:\Tpulsante espandi voci.|M\Sespande tutti gli indirizzi dei segnalibri.|M\Araggruppa tutti gli indirizzi nei segnalibri.|MEspandi gli indirizzi mostrando dettagli addizionali quali ad esempio il numero delle visite.
nl.ro.HelpHotToolbar1:Dit is de Detail-knop.|MKlik met KIES om alle favorieten uit te klappen.|MKlik met PASAAN om alle favorieten in te klappen.|MUitgeklapte favorieten tonen aanvullende details, zoals een bezoekteller.
+zh_CN.ro.HelpHotToolbar1:\T展开æ¡ç›®é”®ã€‚|M\S展开常用列表中的所有网å€ã€‚|M\A折å å¸¸ç”¨åˆ—表中的所有网å€ã€‚|M展开的网å€æ˜¾ç¤ºå…¶ä»–详细信æ¯ï¼Œå¦‚访问计数器。
+
en.ro.HelpHotToolbar2:\Topen directories button.|M\Sopen all directories in the hotlist.|M\Aclose all directories in the hotlist.
de.ro.HelpHotToolbar2:Öffnet Verzeichnisse.|MKlicken mit AUSWAHL öffnet alle / alle markierten Verzeichnisse.|MKlicken mit SPEZIAL schließt alle / alle markierten Verzeichnisse.
-fr.ro.HelpHotToolbar2:\Tle bouton d'ouverture de répertoires.|M\Souvrir tous les répertoires ou seulement ceux de la sélection courante.|M\Afermer tous les répertoires ou seulement ceux de la sélection courante.
-it.ro.HelpHotToolbar2:\Topen directories button.|M\Sopen all directories in the hotlist.|M\Aclose all directories in the hotlist.
+fr.ro.HelpHotToolbar2:\Tle bouton d’ouverture de répertoires.|M\Souvrir tous les répertoires ou seulement ceux de la sélection courante.|M\Afermer tous les répertoires ou seulement ceux de la sélection courante.
+it.ro.HelpHotToolbar2:\Tpulsante apri directory.|M\Sapri tutte le directory dei segnalibri.|M\Achiudi tutte le directory dei segnalibri.
nl.ro.HelpHotToolbar2:Dit is de Open map-knop.|MKlik met KIES om alle mappen in de favorietenlijst te openen.|MKlik met PASAAN om alle mappen in de favorietenlijst te sluiten.
+zh_CN.ro.HelpHotToolbar2:\T打开目录键。|M\S打开常用列表中的所有目录。|M\A关闭常用列表中的所有目录。
+
en.ro.HelpHotToolbar3:\Tlaunch button.|M\Slaunch the current selection.
de.ro.HelpHotToolbar3:Lädt alle markierten Einträge in jeweils ein neues Browserfenster.
fr.ro.HelpHotToolbar3:\Tle bouton de lancement.|M\Slancer (ouvrir) la sélection en cours.
it.ro.HelpHotToolbar3:\Tpulsante di avvio.|M\Savvia la selezione corrente.
nl.ro.HelpHotToolbar3:Dit is de Ga naar-knop.|MKlik met KIES om alle pagina's in deze selectie in nieuwe browservensters te openen.
+zh_CN.ro.HelpHotToolbar3:\Tå¯åŠ¨é”®ã€‚|M\Så¯åŠ¨å½“å‰é€‰é¡¹ã€‚
+
en.ro.HelpHotToolbar4:\Tcreate button.|M\Screate a new directory.
de.ro.HelpHotToolbar4:Erzeugt neue Einträge oder Verzeichnisse.|MKlicken mit AUSWAHL erstellt ein neues Verzeichnis.
fr.ro.HelpHotToolbar4:\Tle bouton Créer.|M\Scréer un nouveau répertoire.
-it.ro.HelpHotToolbar4:\Tcrea pulsante.|M\Screa una nuova directory.
+it.ro.HelpHotToolbar4:\Tpulsante crea.|M\Screa una nuova directory.
nl.ro.HelpHotToolbar4:Dit is de Nieuwe map-knop.|MKlik met KIES om een nieuwe map aan te maken.
+zh_CN.ro.HelpHotToolbar4:\T创建键。|M\S创建新目录。
en.ro.HelpHotlistMenu0:\Rperform an operation on the hotlist.
de.ro.HelpHotlistMenu0:Untermenü Hotlist. Bearbeiten der Hotlist.
-fr.ro.HelpHotlistMenu0:\Raccomplir une opération sur les favoris.
-it.ro.HelpHotlistMenu0:\Rperform an operation on the hotlist.
+fr.ro.HelpHotlistMenu0:\Raccomplir une opération sur les marque-pages.
+it.ro.HelpHotlistMenu0:\Resegui un'operazione nei segnalibri.
nl.ro.HelpHotlistMenu0:Verplaats de muispijl naar rechts om een operatie uit te voeren op de favorietenlijst.
+zh_CN.ro.HelpHotlistMenu0:\R在常用列表上执行æ“作。
+
en.ro.HelpHotlistMenu0-0:\Rcreate a new item.
de.ro.HelpHotlistMenu0-0:Neues Element in die Hotlist einfügen.
fr.ro.HelpHotlistMenu0-0:\Rcréer un nouvel item.
it.ro.HelpHotlistMenu0-0:\Rcrea un nuovo oggetto.
nl.ro.HelpHotlistMenu0-0:Verplaats de muispijl naar rechts om een nieuwe item aan te maken.
+zh_CN.ro.HelpHotlistMenu0-0:\R创建新项。
+
en.ro.HelpHotlistMenu0-0-0:\Rcreate a new directory.
de.ro.HelpHotlistMenu0-0-0:Neues Verzeichnis anlegen.
fr.ro.HelpHotlistMenu0-0-0:\Rcréer un nouveau répertoire.
it.ro.HelpHotlistMenu0-0-0:\Rcrea una nuova directory.
nl.ro.HelpHotlistMenu0-0-0:Klik met KIES om een nieuwe map aan te maken.
+zh_CN.ro.HelpHotlistMenu0-0-0:\R创建新目录。
+
en.ro.HelpHotlistMenu0-0-1:\Rcreate a new address.
de.ro.HelpHotlistMenu0-0-1:Neuen Eintrag erstellen.
fr.ro.HelpHotlistMenu0-0-1:\Rcréer une nouvelle adresse.
it.ro.HelpHotlistMenu0-0-1:\Rcrea un nuovo indirizzo.
nl.ro.HelpHotlistMenu0-0-1:Klik met KIES om een nieuwe favoriete locatie aan te maken.
+zh_CN.ro.HelpHotlistMenu0-0-1:\R创建新网å€ã€‚
+
en.ro.HelpHotlistMenu0-1:\Rexport the hotlist as an HTML file.
de.ro.HelpHotlistMenu0-1:Die gesamte Hotlist als HTML Datei speichern.
-fr.ro.HelpHotlistMenu0-1:\Rexporter les favoris en fichier HTML.
+fr.ro.HelpHotlistMenu0-1:\Rexporter les marque-pages en fichier HTML.
it.ro.HelpHotlistMenu0-1:\Resporta i segnalibri come file HTML.
nl.ro.HelpHotlistMenu0-1:Verplaats de muispijl naar rechts om de favorietenlijst te exporteren als een HTML-bestand.
+zh_CN.ro.HelpHotlistMenu0-1:\R将常用列表导出为 HTML 文件。
+
en.ro.HelpHotlistMenu0-2:\Rexpand items within the hotlist.
de.ro.HelpHotlistMenu0-2:Öffnen von Verzeichnissen und Anzeigen von Zusatzinformationen.
-fr.ro.HelpHotlistMenu0-2:\Rdéployer les items dans la liste des favoris.
-it.ro.HelpHotlistMenu0-2:\Respandi gli elementi all'interno del segnalibro.
+fr.ro.HelpHotlistMenu0-2:\Rdévelopper la liste des marque-pages.
+it.ro.HelpHotlistMenu0-2:\Respandi gli elementi all'interno dei segnalibri.
nl.ro.HelpHotlistMenu0-2:Verplaats de muispijl naar rechts om bepaalde items in de favorietenlijst uit te klappen.
+zh_CN.ro.HelpHotlistMenu0-2:\R展开常用列表中的项。
+
en.ro.HelpHotlistMenu0-2-0:\Sopen all directories and show all entry details.
de.ro.HelpHotlistMenu0-2-0:Öffnet alle Verzeichnisse und zeigt zu Einträgen die Zusatzinformationen an.
fr.ro.HelpHotlistMenu0-2-0:\Souvrir tous les répertoires et afficher tous les détails connus sur les entrées.
-it.ro.HelpHotlistMenu0-2-0:\Sapri tutte le directory e mostra in dettaglio tutte le immissioni
+it.ro.HelpHotlistMenu0-2-0:\Sapri tutte le directory e mostra in dettaglio tutte le immissioni.
nl.ro.HelpHotlistMenu0-2-0:Klik met KIES om alle mappen te openen en alle details van de favorieten te tonen.
+zh_CN.ro.HelpHotlistMenu0-2-0:\S打开所有目录并显示所有æ¡ç›®è¯¦ç»†ä¿¡æ¯ã€‚
+
en.ro.HelpHotlistMenu0-2-1:\Sopen all directories.
de.ro.HelpHotlistMenu0-2-1:Öffnet alle Verzeichnisse.
fr.ro.HelpHotlistMenu0-2-1:\Souvrir tous les répertoires.
it.ro.HelpHotlistMenu0-2-1:\Sapri tutte le directory.
nl.ro.HelpHotlistMenu0-2-1:Klik met KIES om alle mappen te openen en de bijbehorende items uit te klappen.
+zh_CN.ro.HelpHotlistMenu0-2-1:\S打开所有目录。
+
en.ro.HelpHotlistMenu0-2-2:\Sshow all entry details.
de.ro.HelpHotlistMenu0-2-2:Zeigt die Zusatzinformationen zu den Einträgen an.
fr.ro.HelpHotlistMenu0-2-2:\Smontrer tous les détails sur les entrées.
-it.ro.HelpHotlistMenu0-2-2:\Smostra tutti i dettagli dell'elemento
+it.ro.HelpHotlistMenu0-2-2:\Smostra tutti i dettagli dell'elemento.
nl.ro.HelpHotlistMenu0-2-2:Klik met KIES om alle details van de favorieten te tonen.
+zh_CN.ro.HelpHotlistMenu0-2-2:\S显示全部æ¡ç›®è¯¦ç»†ä¿¡æ¯ã€‚
+
en.ro.HelpHotlistMenu0-3:\Rcollapse items within the hotlist.
de.ro.HelpHotlistMenu0-3:Schließen von Verzeichnissen und Ausblenden der Zusatzinformationen.
-fr.ro.HelpHotlistMenu0-3:\Rregrouper les items dans la liste des favoris.
-it.ro.HelpHotlistMenu0-3:\Rraggruppa gli elementi all'interno del segnalibro.
+fr.ro.HelpHotlistMenu0-3:\Rréduire la liste des marque-pages.
+it.ro.HelpHotlistMenu0-3:\Rraggruppa gli elementi all'interno dei segnalibri.
nl.ro.HelpHotlistMenu0-3:Verplaats de muispijl naar rechts om bepaalde items in de favorietenlijst in te klappen.
+zh_CN.ro.HelpHotlistMenu0-3:\R折å å¸¸ç”¨åˆ—表中的项目。
+
en.ro.HelpHotlistMenu0-3-0:\Sclose all directories and hide all entry details.
de.ro.HelpHotlistMenu0-3-0:Schließt alle Verzeichnisse und versteckt die Zusatzinformationen bei Einträgen.
fr.ro.HelpHotlistMenu0-3-0:\Sfermer tous les répertoires et cacher les détails sur les entrées.
it.ro.HelpHotlistMenu0-3-0:\Schiudi tutte le directory e nascondi tutti i dettagli delle immissioni.
nl.ro.HelpHotlistMenu0-3-0:Klik met KIES om alle mappen te sluiten en alle details in de favorietenlijst te verbergen.
+zh_CN.ro.HelpHotlistMenu0-3-0:\S关闭所有目录并éšè—所有æ¡ç›®è¯¦ç»†ä¿¡æ¯ã€‚
+
en.ro.HelpHotlistMenu0-3-1:\Sclose all directories.
de.ro.HelpHotlistMenu0-3-1:Schließt alle Verzeichnisse.
fr.ro.HelpHotlistMenu0-3-1:\Sfermer tous les répertoires.
it.ro.HelpHotlistMenu0-3-1:\Schiudi tutte le directory.
nl.ro.HelpHotlistMenu0-3-1:Klik met KIES om alle mappen te sluiten en de bijbehorende items in te klappen.
+zh_CN.ro.HelpHotlistMenu0-3-1:\S关闭所有目录。
+
en.ro.HelpHotlistMenu0-3-2:\Shide all entry details.
de.ro.HelpHotlistMenu0-3-2:Versteckt die Zusatzinformationen der Einträge.
fr.ro.HelpHotlistMenu0-3-2:\Scacher tous les détails sur les entrées.
it.ro.HelpHotlistMenu0-3-2:\Snascondi tutti i dettagli dell'elemento.
nl.ro.HelpHotlistMenu0-3-2:Klik met KIES om alle details in de favorietenlijst te verbergen.
+zh_CN.ro.HelpHotlistMenu0-3-2:\Séšè—所有æ¡ç›®è¯¦ç»†ä¿¡æ¯ã€‚
+
en.ro.HelpHotlistMenu0-4:\Rcontrol the display of NetSurf's toolbars.
de.ro.HelpHotlistMenu0-4:Knopfleisteneinstellungen vornehmen.
-fr.ro.HelpHotlistMenu0-4:\Rcontroler l'affichage des barres d'outils de Netsurf.
-it.ro.HelpHotlistMenu0-4:\Rcontrol the display of NetSurf's toolbars.
+fr.ro.HelpHotlistMenu0-4:\Rcontroler l’affichage des barres d’outils de Netsurf.
+it.ro.HelpHotlistMenu0-4:\Rcontrolla la visualizzazione delle barre strumenti di NetSurf.
nl.ro.HelpHotlistMenu0-4:Verplaats de muispijl naar rechts om de gereedschapbalken aan te passen.
+zh_CN.ro.HelpHotlistMenu0-4:\R控制显示 NetSurf 工具æ ã€‚
+
en.ro.HelpHotlistMenu0-4-0:\Stoggle the display of the toolbar buttons.
de.ro.HelpHotlistMenu0-4-0:Anklicken um die Knopfleiste ein- bzw. auszuschalten.
-fr.ro.HelpHotlistMenu0-4-0:\Sbasculer l'affichage des boutons de la barre d'outils.
-it.ro.HelpHotlistMenu0-4-0:\Stoggle the display of the toolbar buttons.
+fr.ro.HelpHotlistMenu0-4-0:\Sbasculer l’affichage des boutons de la barre d’outils.
+it.ro.HelpHotlistMenu0-4-0:\Salterna la visualizzazione dei pulsanti della barra strumenti.
nl.ro.HelpHotlistMenu0-4-0:Klik met KIES om het tonen van de knoppen van de gereedschapbalk aan of uit te zetten.
+zh_CN.ro.HelpHotlistMenu0-4-0:\S切æ¢æ˜¾ç¤ºå·¥å…·æ æŒ‰é’®ã€‚
+
en.ro.HelpHotlistMenu0-4-1:\Stoggle toolbar edit mode.
de.ro.HelpHotlistMenu0-4-1:Anklicken zum Bearbeiten der Knopfleiste.
-fr.ro.HelpHotlistMenu0-4-1:\Sbasculer le mode d'édition de barre d'outils.
-it.ro.HelpHotlistMenu0-4-1:\Stoggle toolbar edit mode.
+fr.ro.HelpHotlistMenu0-4-1:\Sbasculer le mode d’édition de barre d’outils.
+it.ro.HelpHotlistMenu0-4-1:\Salterna la modalità di modifica della barra strumenti.
nl.ro.HelpHotlistMenu0-4-1:Klik met KIES om de aanpasmodus van de gereedschapbalk in of uit te schakelen. Wanneer ingeschakelt, verschijnt er een balk onder de gereedschapbalk met extra knoppen die van en naar deze balk gesleept kunnen worden om deze aan te passen.
+zh_CN.ro.HelpHotlistMenu0-4-1:\S切æ¢å·¥å…·æ ç¼–辑模å¼ã€‚
+
en.ro.HelpHotlistMenu1:\Roperate on the current selection.
de.ro.HelpHotlistMenu1:Untermenü Auswahl. Bearbeiten der markierten Hotlist Elemente.
fr.ro.HelpHotlistMenu1:\Ragir sur la sélection en cours.
it.ro.HelpHotlistMenu1:\Ropera nella selezione corrente.
nl.ro.HelpHotlistMenu1:Verplaats de muispijl naar rechts om een operatie op deze selectie uit te voeren.
+zh_CN.ro.HelpHotlistMenu1:\R对当å‰é€‰æ‹©æ‰§è¡Œæ“作。
+
en.ro.HelpHotlistMenu1-0:\Redit the current item.
de.ro.HelpHotlistMenu1-0:Ändern des markierten Elementes in der Hotlist.
-fr.ro.HelpHotlistMenu1-0:\Rééditer l'item en cours.
+fr.ro.HelpHotlistMenu1-0:\Rééditer l’item en cours.
it.ro.HelpHotlistMenu1-0:\Rmodifica l'oggetto corrente.
nl.ro.HelpHotlistMenu1-0:Klik met KIES om de naam van dit item te wijzigen
+zh_CN.ro.HelpHotlistMenu1-0:\R编辑当å‰é¡¹ã€‚
+
en.ro.HelpHotlistMenu1-1:\Slaunch the current selection.
de.ro.HelpHotlistMenu1-1:Öffnet markierte Einträge in je einem neuen Browserfenster.
fr.ro.HelpHotlistMenu1-1:\Slancer la sélection courante.
it.ro.HelpHotlistMenu1-1:\Savvia la selezione corrente.
nl.ro.HelpHotlistMenu1-1:Klik met KIES om deze selectie in nieuwe browservenster(s) te openen.
+zh_CN.ro.HelpHotlistMenu1-1:\Så¯åŠ¨å½“å‰é€‰é¡¹ã€‚
+
en.ro.HelpHotlistMenu1-2:\Sdelete the current selection from the hotlist.
de.ro.HelpHotlistMenu1-2:Löscht markierte Elemente aus der Hotlist.|MAchtung: Verzeichnisse werden mit allen in ihnen enthaltenen Einträgen gelöscht.
-fr.ro.HelpHotlistMenu1-2:\Ssupprimer la sélection courante de la liste des favoris.
+fr.ro.HelpHotlistMenu1-2:\Ssupprimer la sélection courante des marque-pages.
it.ro.HelpHotlistMenu1-2:\Scancella dai segnalibri la selezione corrente.
nl.ro.HelpHotlistMenu1-2:Klik met KIES om deze selectie uit de favorietenlijst te verwijderen.
+zh_CN.ro.HelpHotlistMenu1-2:\S从常用列表中删除当å‰é€‰é¡¹ã€‚
+
en.ro.HelpHotlistMenu1-3:\Sreset statistics, such as visit count, for selected items.
de.ro.HelpHotlistMenu1-3:Setzt für die markierten Einträge die Statistik, z.B. Anzahl der Seitenbesuche, zurück.
fr.ro.HelpHotlistMenu1-3:\Sremettre à zéro les statistiques, comme le compteur de visite, pour les items sélectionnés.
-it.ro.HelpHotlistMenu1-3:\Sreset statistics, such as visit count, for selected items.
+it.ro.HelpHotlistMenu1-3:\Sresetta le statistiche del contatore delle visite per gli oggetti selezionati.
nl.ro.HelpHotlistMenu1-3:Klik met KIES om de statistische gegevens van de geselecteerde items opnieuw in te stellen. Voorbeeld: de bezoekteller wordt weer op 0 gezet.
+zh_CN.ro.HelpHotlistMenu1-3:\Sé‡ç½®æ‰€é€‰é¡¹çš„统计信æ¯ï¼Œå¦‚访问计数等。
+
en.ro.HelpHotlistMenu2:\Sselect all the items in the hotlist.
de.ro.HelpHotlistMenu2:Markiert alle Elemente der Hotlist.
-fr.ro.HelpHotlistMenu2:\Ssélectionner tous les items de la liste des favoris.
+fr.ro.HelpHotlistMenu2:\Ssélectionner tous les marque-pages.
it.ro.HelpHotlistMenu2:\Sseleziona tutti gli elementi dei segnalibri.
nl.ro.HelpHotlistMenu2:Klik met KIES om alle items in de favorietenlijst te selecteren.
+zh_CN.ro.HelpHotlistMenu2:\S选择常用列表中的所有项。
+
en.ro.HelpHotlistMenu3:\Sdeselect all selected items.
de.ro.HelpHotlistMenu3:Deselektiert alle markierten Elemente.
fr.ro.HelpHotlistMenu3:\Sdésélectionner la sélection courante.
it.ro.HelpHotlistMenu3:\Sdeseleziona tutti gli oggetti selezionati.
nl.ro.HelpHotlistMenu3:Klik met KIES om alle geselecteerde items te deselecteren.
+zh_CN.ro.HelpHotlistMenu3:\Så–消选择所有选定项。
en.ro.HelpGHistory:\Tglobal history window.
de.ro.HelpGHistory:Das ist das Fenster der globalen History.
-fr.ro.HelpGHistory:\Tla fenêtre d'historique global.
+fr.ro.HelpGHistory:\Tla fenêtre d’historique global.
it.ro.HelpGHistory:\Tfinestra della cronologia globale.
nl.ro.HelpGHistory:Dit venster toont de browsergeschiedenis.
+zh_CN.ro.HelpGHistory:\T全局历å²è®°å½•çª—å£ã€‚
+
en.ro.HelpGHistoryToolbar0:\Tdelete button.|M\Sdelete the current selection.
de.ro.HelpGHistoryToolbar0:Entfernt markierte Bereiche.|MAnklicken mit AUSWAHL löscht die vorher markierten Bereiche aus der History.
fr.ro.HelpGHistoryToolbar0:\Tle bouton de suppression.|M\Ssupprimer la sélection en cours.
-it.ro.HelpGHistoryToolbar0:\Tdelete button.|M\Sdelete the current selection.
+it.ro.HelpGHistoryToolbar0:\Tpulsante cancella.|M\Scancella la selezione corrente.
nl.ro.HelpGHistoryToolbar0:Dit is de Verwijder-knop.|MKlik met KIES om deze selectie te verwijderen.
+zh_CN.ro.HelpGHistoryToolbar0:\T删除键。|M\S删除当å‰é€‰é¡¹ã€‚
+
en.ro.HelpGHistoryToolbar1:\Texpand entries button.|M\Sexpand all entries in the history.|M\Acollapse all entries in the history.|MExpanded entries show additional details, such as a visit counter.
de.ro.HelpGHistoryToolbar1:Expandiert Einträge.|MAnklicken mit AUSWAHL expandiert alle Adressen.|MAnklicken mit SPEZIAL macht die Expansion aller Adressen rückgängig.|MIn expandierten Adressen werden Zusatzinformationen angezeigt.
-fr.ro.HelpGHistoryToolbar1:\Tle bouton de déploiement des entrées.|M\Sdéployer toutes les adresses des favoris.|M\Aregrouper toutes les adresses des favoris.|MLes adresses déployées apportent des détails supplémentaires, comme un compteur de visites.
-it.ro.HelpGHistoryToolbar1:\Texpand entries button.|M\Sexpand all entries in the history.|M\Acollapse all entries in the history.|MExpanded entries show additional details, such as a visit counter.
+fr.ro.HelpGHistoryToolbar1:\Tle bouton de développement des entrées.|M\Sdévelopper toutes les entrées de l’historique.|M\Aréduire toutes les entrées de l’historique.|MLes adresses développées affichent des détails supplémentaires, comme un compteur de visites.
+it.ro.HelpGHistoryToolbar1:\Tpulsante espandi voci.|M\Sespandi tutte le voci nella cronologia.|M\Araggruppa tutte le voci nella cronologia.|ML'espansione delle voci mostra dettagli addizionali quali ad esempio il numero delle visite.
nl.ro.HelpGHistoryToolbar1:Dit is de Detail-knop.|MKlik met KIES om alle items in de broswergeschiedenis uit te klappen.|MKlik met PASAAN om alle items in te klappen.|MUitgeklapte items tonen aanvullende details, zoals een bezoekteller.
+zh_CN.ro.HelpGHistoryToolbar1:\T展开æ¡ç›®é”®ã€‚|M\S展开历å²è®°å½•ä¸­çš„所有æ¡ç›®ã€‚|M\A折å åŽ†å²è®°å½•ä¸­çš„所有æ¡ç›®ã€‚|M展开的æ¡ç›®æ˜¾ç¤ºå…¶ä»–详细信æ¯ï¼Œå¦‚访问计数器。
+
en.ro.HelpGHistoryToolbar2:\Topen sections button.|M\Sopen all sections in the global history.|M\Aclose all sections in the global history.
de.ro.HelpGHistoryToolbar2:Öffnet Verzeichnisse.|MAnklicken mit AUSWAHL öffnet alle Verzeichnisse.|MAnklicken mit SPEZIAL schließt alle geöffneten Verzeichnisse.
-fr.ro.HelpGHistoryToolbar2:\Tle bouton d'ouverture de répertoires.|M\Souvrir tous les répertoires des favoris.|M\Afermer tous les répertoires des favoris.
-it.ro.HelpGHistoryToolbar2:\Topen sections button.|M\Sopen all sections in the global history.|M\Aclose all sections in the global history.
+fr.ro.HelpGHistoryToolbar2:\Tle bouton d’ouverture des sections.|M\Souvrir toutes les sections de l’historique.|M\Afermer toutes les sections de l’historique.
+it.ro.HelpGHistoryToolbar2:\Tpulsante apri sezioni.|M\Sapri tutte le sezioni nella cronologia globale.|M\Achiudi tutte le sezioni nella cronologia globale.
nl.ro.HelpGHistoryToolbar2:Dit is de Open tijdsmappen-knop.|MKlik met KIES om alle tijdsmappen in de browsergeschiedenis te openen.|MKlik met PASAAN om alle tijdsmappen te sluiten.
+zh_CN.ro.HelpGHistoryToolbar2:\T打开分区键。|M\S打开全局历å²è®°å½•ä¸­çš„所有分区。|M\A关闭全局历å²è®°å½•ä¸­çš„所有分区。
+
en.ro.HelpGHistoryToolbar3:\Tlaunch button.|M\Slaunch the current selection.
de.ro.HelpGHistoryToolbar3:Lädt Webseiten.|MAnklicken mit AUSWAHL öffnet die markierten Webseiten in je einem neuen Browserfenster.
fr.ro.HelpGHistoryToolbar3:\Tle bouton de lancement.|M\Slancer la sélection en cours.
-it.ro.HelpGHistoryToolbar3:\Tlaunch button.|M\Slaunch the current selection.
+it.ro.HelpGHistoryToolbar3:\Tpulsante di avvio.|M\Savvia la selezione corrente.
nl.ro.HelpGHistoryToolbar3:Dit is de Ga naar-knop.|MKlik met KIES om alle pagina's in deze selectie in nieuwe browservensters te openen.
+zh_CN.ro.HelpGHistoryToolbar3:\Tå¯åŠ¨é”®ã€‚|M\Så¯åŠ¨å½“å‰é€‰é¡¹ã€‚
en.ro.HelpGHistoryMenu0:\Rperform an operation on global history.
de.ro.HelpGHistoryMenu0:Die globale History bearbeiten.
-fr.ro.HelpGHistoryMenu0:\Reffectuer une opération sur l'historique global.
-it.ro.HelpGHistoryMenu0:\Rperform an operation on global history.
+fr.ro.HelpGHistoryMenu0:\Reffectuer une opération sur l’historique global.
+it.ro.HelpGHistoryMenu0:\Resegui un'operazione nella cronologia globale.
nl.ro.HelpGHistoryMenu0:Verplaats de muispijl naar rechts om een operatie uit te voeren op de browsergeschiedenis.
+zh_CN.ro.HelpGHistoryMenu0:\R对全局历å²è®°å½•æ‰§è¡Œæ“作。
+
en.ro.HelpGHistoryMenu0-0:\Rexport global history as an HTML file.
de.ro.HelpGHistoryMenu0-0:Speichert die History (global) als HTML Datei.
-fr.ro.HelpGHistoryMenu0-0:\Rexporter l'historique global en fichier HTML.
+fr.ro.HelpGHistoryMenu0-0:\Rexporter l’historique global en fichier HTML.
it.ro.HelpGHistoryMenu0-0:\Resporta la cronologia globale come file HTML.
nl.ro.HelpGHistoryMenu0-0:Verplaats de muispijl naar rechts om de browsergeschiedenis te exporteren als een HTML-bestand.
+zh_CN.ro.HelpGHistoryMenu0-0:\R将全局历å²è®°å½•å¯¼å‡ºä¸º HTML 文件。
+
en.ro.HelpGHistoryMenu0-1:\Rexpand items within global history.
de.ro.HelpGHistoryMenu0-1:Mehr Information anzeigen
-fr.ro.HelpGHistoryMenu0-1:\Rdéployer les items de l'historique global.
+fr.ro.HelpGHistoryMenu0-1:\Rdévelopper les items de l’historique global.
it.ro.HelpGHistoryMenu0-1:\Respandi gli elementi all'interno della cronologia globale.
nl.ro.HelpGHistoryMenu0-1:Verplaats de muispijl naar rechts om bepaalde items in de browsergeschiedenis uit te klappen.
+zh_CN.ro.HelpGHistoryMenu0-1:\R展开全局历å²è®°å½•ä¸­çš„项。
+
en.ro.HelpGHistoryMenu0-1-0:\Sopen all directories and show all entry details.
de.ro.HelpGHistoryMenu0-1-0:Öffnet alle Verzeichnisse und zeigt die Details der Einträge an.
fr.ro.HelpGHistoryMenu0-1-0:\Souvrir tous les répertoires et donner le détail de toutes les entrées.
it.ro.HelpGHistoryMenu0-1-0:\Sapri tutte le directory e mostra in dettaglio tutte le immissioni.
nl.ro.HelpGHistoryMenu0-1-0:Klik met KIES om alle mappen te openen en alle itemdetails te tonen.
+zh_CN.ro.HelpGHistoryMenu0-1-0:\S打开所有目录并显示所有æ¡ç›®è¯¦ç»†ä¿¡æ¯ã€‚
+
en.ro.HelpGHistoryMenu0-1-1:\Sopen all directories.
de.ro.HelpGHistoryMenu0-1-1:Öffnet alle Verzeichnisse.
fr.ro.HelpGHistoryMenu0-1-1:\Souvrir tous les répertoires.
it.ro.HelpGHistoryMenu0-1-1:\Sapri tutte le directory.
nl.ro.HelpGHistoryMenu0-1-1:Klik met KIES om alle mappen te openen en de bijbehorende items uit te klappen.
+zh_CN.ro.HelpGHistoryMenu0-1-1:\S打开所有目录。
+
en.ro.HelpGHistoryMenu0-1-2:\Sshow all entry details.
de.ro.HelpGHistoryMenu0-1-2:Zeigt die Details der sichtbaren Einträge an.
fr.ro.HelpGHistoryMenu0-1-2:\Smontrer le détail de toutes les entrées.
-it.ro.HelpGHistoryMenu0-1-2:\Smostra tutte le immissioni in dettaglio
+it.ro.HelpGHistoryMenu0-1-2:\Smostra tutte le immissioni in dettaglio.
nl.ro.HelpGHistoryMenu0-1-2:Klik met KIES om alle itemdetails te tonen.
+zh_CN.ro.HelpGHistoryMenu0-1-2:\S显示全部æ¡ç›®è¯¦ç»†ä¿¡æ¯ã€‚
+
en.ro.HelpGHistoryMenu0-2:\Rcollapse items within global history.
de.ro.HelpGHistoryMenu0-2:Weniger Information anzeigen
-fr.ro.HelpGHistoryMenu0-2:\Rregrouper les items de l'historique global.
+fr.ro.HelpGHistoryMenu0-2:\Rréduire les entrées de l’historique global.
it.ro.HelpGHistoryMenu0-2:\Rraggruppa gli elementi all'interno della cronologia globale.
nl.ro.HelpGHistoryMenu0-2:Verplaats de muispijl naar rechts om bepaalde items in de browsergeschiedenis in te klappen.
+zh_CN.ro.HelpGHistoryMenu0-2:\R折å å…¨å±€åŽ†å²è®°å½•ä¸­çš„项。
+
en.ro.HelpGHistoryMenu0-2-0:\Sclose all directories and hide all entry details.
de.ro.HelpGHistoryMenu0-2-0:Schließt alle Verzeichnisse und versteckt die Details der Einträge.
fr.ro.HelpGHistoryMenu0-2-0:\Sfermer tous les répertoires et cacher le détail de toutes les entrées.
it.ro.HelpGHistoryMenu0-2-0:\Schiudi tutte le directory e nascondi i dettagli delle immissioni.
nl.ro.HelpGHistoryMenu0-2-0:Klik met KIES om alle mappen te sluiten en alle itemdetails te verbergen.
+zh_CN.ro.HelpGHistoryMenu0-2-0:\S关闭所有目录并éšè—所有æ¡ç›®è¯¦ç»†ä¿¡æ¯ã€‚
+
en.ro.HelpGHistoryMenu0-2-1:\Sclose all directories.
de.ro.HelpGHistoryMenu0-2-1:Schließt alle Verzeichnisse.
fr.ro.HelpGHistoryMenu0-2-1:\Sfermer tous les répertoires.
it.ro.HelpGHistoryMenu0-2-1:\Schiudi tutte le directory.
nl.ro.HelpGHistoryMenu0-2-1:Klik met KIES om alle mappen te sluiten en de bijbehorende items in te klappen.
+zh_CN.ro.HelpGHistoryMenu0-2-1:\S关闭所有目录。
+
en.ro.HelpGHistoryMenu0-2-2:\Shide all entry details.
de.ro.HelpGHistoryMenu0-2-2:Versteckt die Detailanzeige der Einträge.
fr.ro.HelpGHistoryMenu0-2-2:\Scacher le détail de toutes les entrées.
it.ro.HelpGHistoryMenu0-2-2:\Snascondi tutti i dettagli dell'immissione.
nl.ro.HelpGHistoryMenu0-2-2:Klik met KIES om alle itemdetails te verbergen.
+zh_CN.ro.HelpGHistoryMenu0-2-2:\Séšè—所有æ¡ç›®è¯¦ç»†ä¿¡æ¯ã€‚
+
en.ro.HelpGHistoryMenu0-3:\Rcontrol the display of NetSurf's toolbars.
de.ro.HelpGHistoryMenu0-3:Die Iconleiste der globalen History verändern.
-fr.ro.HelpGHistoryMenu0-3:\Rcontroler l'affichage des barre d'outils de NetSurf.
-it.ro.HelpGHistoryMenu0-3:\Rcontrol the display of NetSurf's toolbars.
+fr.ro.HelpGHistoryMenu0-3:\Rcontroler l’affichage des barre d’outils de NetSurf.
+it.ro.HelpGHistoryMenu0-3:\Rcontrolla la visualizzazione delle barre strumenti di NetSurf.
nl.ro.HelpGHistoryMenu0-3:Verplaats de muispijl naar rechts om de gereedschapbalken aan te passen.
+zh_CN.ro.HelpGHistoryMenu0-3:\R控制显示 NetSurf 工具æ ã€‚
+
en.ro.HelpGHistoryMenu0-3-0:\Stoggle the display of the toolbar buttons.
de.ro.HelpGHistoryMenu0-3-0:Iconleiste an- oder abschalten.
-fr.ro.HelpGHistoryMenu0-3-0:\Sbasculer l'affichage des boutons de la barre d'outils.
-it.ro.HelpGHistoryMenu0-3-0:\Stoggle the display of the toolbar buttons.
+fr.ro.HelpGHistoryMenu0-3-0:\Sbasculer l’affichage des boutons de la barre d’outils.
+it.ro.HelpGHistoryMenu0-3-0:\Salterna la visualizzazione dei pulsanti della barra strumenti.
nl.ro.HelpGHistoryMenu0-3-0:Klik met KIES om het tonen van de knoppen op de gereedschapbalk aan of uit te zetten.
+zh_CN.ro.HelpGHistoryMenu0-3-0:\S切æ¢æ˜¾ç¤ºå·¥å…·æ æŒ‰é’®ã€‚
+
en.ro.HelpGHistoryMenu0-3-1:\Stoggle toolbar edit mode.
de.ro.HelpGHistoryMenu0-3-1:Iconleiste bearbeiten.
-fr.ro.HelpGHistoryMenu0-3-1:\Sbasculer le mode d'édition de la barre d'outils.
-it.ro.HelpGHistoryMenu0-3-1:\Stoggle toolbar edit mode.
+fr.ro.HelpGHistoryMenu0-3-1:\Sbasculer le mode d’édition de la barre d’outils.
+it.ro.HelpGHistoryMenu0-3-1:\Salterna la modalità di modifica della barra strumenti.
nl.ro.HelpGHistoryMenu0-3-1:Klik met KIES om de aanpasmodus van de gereedschapbalk in of uit te schakelen. Wanneer ingeschakelt, verschijnt er een balk onder de gereedschapbalk met extra knoppen die van en naar deze balk gesleept kunnen worden om deze aan te passen.
+zh_CN.ro.HelpGHistoryMenu0-3-1:\S切æ¢å·¥å…·æ ç¼–辑模å¼ã€‚
+
en.ro.HelpGHistoryMenu1:\Roperate on the current selection.
de.ro.HelpGHistoryMenu1:Die aktuelle Auswahl bearbeiten.
fr.ro.HelpGHistoryMenu1:\Reffectuer une opération sur la sélection courante.
it.ro.HelpGHistoryMenu1:\Ropera nella selezione corrente.
nl.ro.HelpGHistoryMenu1:Verplaats de muispijl naar rechts om een operatie op deze selectie uit te voeren.
+zh_CN.ro.HelpGHistoryMenu1:\R对当å‰é€‰æ‹©æ‰§è¡Œæ“作。
+
en.ro.HelpGHistoryMenu1-0:\Slaunch the current selection.
de.ro.HelpGHistoryMenu1-0:Lädt Webseiten.|MAnklicken mit AUSWAHL öffnet die markierten Webseiten in je einem neuen Browserfenster.
fr.ro.HelpGHistoryMenu1-0:\Slancer la sélection courante.
it.ro.HelpGHistoryMenu1-0:\Savvia la selezione corrente.
nl.ro.HelpGHistoryMenu1-0:Klik met KIES om deze selectie in nieuwe browservenster(s) te openen.
+zh_CN.ro.HelpGHistoryMenu1-0:\Så¯åŠ¨å½“å‰é€‰é¡¹ã€‚
+
en.ro.HelpGHistoryMenu1-1:\Sdelete the current selection from global history.
de.ro.HelpGHistoryMenu1-1:Entfernt markierte Bereiche.|MAnklicken mit AUSWAHL löscht die vorher markierten Bereiche aus der History.
-fr.ro.HelpGHistoryMenu1-1:\Ssupprimer la sélection courante de l'historique global.
+fr.ro.HelpGHistoryMenu1-1:\Ssupprimer la sélection courante de l’historique global.
it.ro.HelpGHistoryMenu1-1:\Scancella la selezione corrente dalla cronologia globale.
nl.ro.HelpGHistoryMenu1-1:Klik met KIES om deze selectie uit de browsergeschiedenis te verwijderen.
+zh_CN.ro.HelpGHistoryMenu1-1:\S从全局历å²è®°å½•ä¸­åˆ é™¤å½“å‰é€‰é¡¹ã€‚
+
en.ro.HelpGHistoryMenu1-2:\Sreset statistics, such as visit count, for selected items.
de.ro.HelpGHistoryMenu1-2:Setzt die Besuchsstatistik der markierten Einträge zurück.
fr.ro.HelpGHistoryMenu1-2:\Sremettre à zéro les statistiques, comme le compteur de visites, pour les items sélectionnés.
-it.ro.HelpGHistoryMenu1-2:\Sreset statistics, such as visit count, for selected items.
+it.ro.HelpGHistoryMenu1-2:\Sresetta le statistiche del contatore delle visite per gli oggetti selezionati.
nl.ro.HelpGHistoryMenu1-2:Klik met KIES om de statistische gegevens van de geselecteerde items opnieuw in te stellen. Voorbeeld: de bezoekteller wordt weer op 0 gezet.
+zh_CN.ro.HelpGHistoryMenu1-2:\Sé‡ç½®æ‰€é€‰é¡¹çš„统计信æ¯ï¼Œå¦‚访问计数等。
+
en.ro.HelpGHistoryMenu2:\Sselect all the items in the history.
de.ro.HelpGHistoryMenu2:Markiert alle Elemente der globalen History.
-fr.ro.HelpGHistoryMenu2:\Ssélectionner tous les items des favoris.
+fr.ro.HelpGHistoryMenu2:\Ssélectionner toutes les entrées de l’historique.
it.ro.HelpGHistoryMenu2:\Sseleziona tutti gli oggetti della cronologia.
nl.ro.HelpGHistoryMenu2:Klik met KIES om alle items in de browsergeschiedenis te selecteren.
+zh_CN.ro.HelpGHistoryMenu2:\S选择历å²è®°å½•ä¸­çš„所有项。
+
en.ro.HelpGHistoryMenu3:\Sdeselect all selected items.
de.ro.HelpGHistoryMenu3:Deselektiert alle markierten Elemente.
fr.ro.HelpGHistoryMenu3:\Sdéselectionner tous les items sélectionnés.
it.ro.HelpGHistoryMenu3:\Sdeseleziona tutti gli oggetti selezionati.
nl.ro.HelpGHistoryMenu3:Klik met KIES om alle geselecteerde items te deselecteren.
+zh_CN.ro.HelpGHistoryMenu3:\Så–消选择所有选定项。
en.ro.HelpCookies:\TCookie management window.
de.ro.HelpCookies:Das ist das Fenster zur Cookie-Verwaltung.
fr.ro.HelpCookies:\TFenêtre de gestion des cookies.
it.ro.HelpCookies:\TFinestra di gestione Cookie.
nl.ro.HelpCookies:Dit is het cookiebeheervenster.
+zh_CN.ro.HelpCookies:\TCookie 管ç†çª—å£ã€‚
+
en.ro.HelpCookiesToolbar0:\Tdelete button.|M\Sdelete the current selection.
de.ro.HelpCookiesToolbar0:Dies ist der Löschschalter.|MAnklicken löscht alle markierten Einträge.
fr.ro.HelpCookiesToolbar0:\Tbouton de suppression.|M\Ssupprimer la sélection en cours.
-it.ro.HelpCookiesToolbar0:\Tdelete button.|M\Sdelete the current selection.
+it.ro.HelpCookiesToolbar0:\Tpulsante cancella.|M\Scancella la selezione corrente.
nl.ro.HelpCookiesToolbar0:Dit is de Verwijder-knop.|MKlik met KIES om deze selectie te verwijderen.
+zh_CN.ro.HelpCookiesToolbar0:\T删除键。|M\S删除当å‰é€‰é¡¹ã€‚
+
en.ro.HelpCookiesToolbar1:\Texpand cookies button.|M\Sexpand all cookies in the list.|M\Acollapse all cookies in the list.|MExpanded cookies show additional details.
de.ro.HelpCookiesToolbar1:Dies ist der Schalter zum Expandieren der Einträge.|MKlicken mit AUSWAHL expandiert alle Cookies.|MKlicken mit SPEZIAL versteckt die Zusatzinformationen wieder.|MIn expandierten Cookies werden zusätzliche Informationen angezeigt.
-fr.ro.HelpCookiesToolbar1:\Tdéployer le bouton de cookies.|M\Sdéployer tous les cookies de la liste.|M\Aregrouper tous les cookies de la liste.|MDéployer les cookies permet l'affichage d'informations supplémentaires.
-it.ro.HelpCookiesToolbar1:\Texpand cookies button.|M\Sexpand all cookies in the list.|M\Acollapse all cookies in the list.|MExpanded cookies show additional details.
+fr.ro.HelpCookiesToolbar1:\Tbouton de développement des cookies.|M\Sdévelopper tous les cookies de la liste.|M\Aréduire tous les cookies de la liste.|MDévelopper les cookies permet l’affichage de détails supplémentaires.
+it.ro.HelpCookiesToolbar1:\Tpulsante espandi cookie.|M\Sespandi tutti i cookie nella lista.|M\Araggruppa tutti i cookie nella lista.|ML'espansione dei cookie serve a mostrare dettagli addizionali.
nl.ro.HelpCookiesToolbar1:Dit is de Detail-knop.|MKlik met KIES om alle cookies uit te klappen.|MKlik met PASAAN om alle cookies in te klappen.|MUitgeklapte cookies tonen aanvullende details,
+zh_CN.ro.HelpCookiesToolbar1:\T展开 Cookies 键。|M\S展开列表中的所有 Cookies。|M\A折å åˆ—表中的所有 Cookies。|M展开的 Cookies 显示其他详细信æ¯ã€‚
+
en.ro.HelpCookiesToolbar2:\Topen directories button.|M\Sopen all directories in the list.|M\Aclose all directories in the list.
de.ro.HelpCookiesToolbar2:Öffnet und schließt Verzeichnisse|MKlicken mit AUSWAHL öffnet alle Verzeichnisse der Liste.|MKlicken mit SPEZIAL schließt alle Verzeichnisse.
fr.ro.HelpCookiesToolbar2:\Touvrir le bouton de répertoires.|M\Souvrir tous les répertoires de la liste.|M\Afermer tous les répertoires de la liste.
-it.ro.HelpCookiesToolbar2:\Topen directories button.|M\Sopen all directories in the list.|M\Aclose all directories in the list.
+it.ro.HelpCookiesToolbar2:\Tpulsante apri directory.|M\Sapri tutte le directory nella lista.|M\Achiudi tutte le directory nella lista.
nl.ro.HelpCookiesToolbar2:Dit is de Open map-knop.|MKlik met KIES om alle mappen in het cookiesbeheervenster te openen.|MKlik met PASAAN om alle mappen in het cookiesbeheervenster te sluiten.
+zh_CN.ro.HelpCookiesToolbar2:\T打开目录键。|M\S打开列表中的所有目录。|M\A关闭列表中的所有目录。
en.ro.HelpCookiesMenu0:\Rperform an operation on the cookie list.
de.ro.HelpCookiesMenu0:Die gesamte Liste bearbeiten.
-fr.ro.HelpCookiesMenu0:\Raccomplir une opération sur la liste de cookies.
-it.ro.HelpCookiesMenu0:\Rperform an operation on the cookie list.
+fr.ro.HelpCookiesMenu0:\Raccomplir une opération sur la liste des cookies.
+it.ro.HelpCookiesMenu0:\Resegui un'operazione nella lista dei cookie.
nl.ro.HelpCookiesMenu0:Verplaats de muispijl naar rechts om een operatie uit te voeren op de opgeslagen cookies.
+zh_CN.ro.HelpCookiesMenu0:\R对 Cookie 列表执行æ“作。
+
en.ro.HelpCookiesMenu0-0:\Rexpand items within the cookie list.
de.ro.HelpCookiesMenu0-0:Menü zum Expandieren der Einträge der Liste.
-fr.ro.HelpCookiesMenu0-0:\Rdéployer les items dans la liste de cookies.
+fr.ro.HelpCookiesMenu0-0:\Rdévelopper les items dans la liste des cookies.
it.ro.HelpCookiesMenu0-0:\Respandi gli elementi all'interno della lista dei cookie.
nl.ro.HelpCookiesMenu0-0:Verplaats de muispijl naar rechts om bepaalde items in het cookiesbeheervenster uit te klappen.
+zh_CN.ro.HelpCookiesMenu0-0:\R展开 Cookie 列表中的项。
+
en.ro.HelpCookiesMenu0-0-0:\Sopen all directories and show all cookie details.
de.ro.HelpCookiesMenu0-0-0:Klicken mit AUSWAHL öffnet alle Verzeichnisse und zeigt Details zu allen angezeigten Cookies.
fr.ro.HelpCookiesMenu0-0-0:\Souvrir tous les répertoires et montrer le détail de tous les cookies.
-it.ro.HelpCookiesMenu0-0-0:\Sapri tutte le directory e mostra in dettaglio tutti i cookie
+it.ro.HelpCookiesMenu0-0-0:\Sapri tutte le directory e mostra in dettaglio tutti i cookie.
nl.ro.HelpCookiesMenu0-0-0:Klik met KIES om alle mappen te openen en alle cookiedetails te tonen.
+zh_CN.ro.HelpCookiesMenu0-0-0:\S打开所有目录并显示所有 Cookie 详细信æ¯ã€‚
+
en.ro.HelpCookiesMenu0-0-1:\Sopen all directories.
de.ro.HelpCookiesMenu0-0-1:Klicken mit AUSWAHL öffnet alle Verzeichnisse.
fr.ro.HelpCookiesMenu0-0-1:\Souvrir tous les répertoires.
it.ro.HelpCookiesMenu0-0-1:\Sapri tutte le directory.
nl.ro.HelpCookiesMenu0-0-1:Klik met KIES om alle mappen te openen en de bijbehorende cookies uit te klappen.
+zh_CN.ro.HelpCookiesMenu0-0-1:\S打开所有目录。
+
en.ro.HelpCookiesMenu0-0-2:\Sshow all cookie details.
de.ro.HelpCookiesMenu0-0-2:Klicken mit AUSWAHL zeigt Details zu allen angezeigten Cookies.
fr.ro.HelpCookiesMenu0-0-2:\Smontrer le détail de tous les cookies.
-it.ro.HelpCookiesMenu0-0-2:\Smostra in dettaglio tutti i cookie
+it.ro.HelpCookiesMenu0-0-2:\Smostra in dettaglio tutti i cookie.
nl.ro.HelpCookiesMenu0-0-2:Klik met KIES om alle cookiedetails te tonen.
+zh_CN.ro.HelpCookiesMenu0-0-2:\S显示全部 Cookie 详细信æ¯ã€‚
+
en.ro.HelpCookiesMenu0-1:\Rcollapse items within the cookie list.
de.ro.HelpCookiesMenu0-1:Menü zum Schließen der Einträge der Liste.
-fr.ro.HelpCookiesMenu0-1:\Rregrouper les items dans la liste de cookies.
+fr.ro.HelpCookiesMenu0-1:\Rregrouper les items dans la liste des cookies.
it.ro.HelpCookiesMenu0-1:\Rragguppa gli elementi all'interno della lista dei cookie.
nl.ro.HelpCookiesMenu0-1:Verplaats de muispijl naar rechts om bepaalde items in het cookiesbeheervenster in te klappen.
+zh_CN.ro.HelpCookiesMenu0-1:\RæŠ˜å  Cookie 列表中的项。
+
en.ro.HelpCookiesMenu0-1-0:\Sclose all directories and hide all cookie details.
de.ro.HelpCookiesMenu0-1-0:Klicken mit AUSWAHL schließt alle Verzeichnisse und versteckt die Cookiedetails.
fr.ro.HelpCookiesMenu0-1-0:\Sfermer tous les répertoires et cacher le détail de tous les cookies.
it.ro.HelpCookiesMenu0-1-0:\Schiudi tutte le directory e nascondi i dettagli di tutti i cookie.
nl.ro.HelpCookiesMenu0-1-0:Klik met KIES om alle mappen te sluiten en alle cookiedetails te verbergen.
+zh_CN.ro.HelpCookiesMenu0-1-0:\S关闭所有目录并éšè—所有 Cookie 详细信æ¯ã€‚
+
en.ro.HelpCookiesMenu0-1-1:\Sclose all directories.
de.ro.HelpCookiesMenu0-1-1:Klicken mit AUSWAHL schließt alle Verzeichnisse.
fr.ro.HelpCookiesMenu0-1-1:\Sfermer tous les répertoires.
it.ro.HelpCookiesMenu0-1-1:\Schiudi le directory.
nl.ro.HelpCookiesMenu0-1-1:Klik met KIES om alle mappen te sluiten en de bijbehorende items in te klappen.
+zh_CN.ro.HelpCookiesMenu0-1-1:\S关闭所有目录。
+
en.ro.HelpCookiesMenu0-1-2:\Shide all cookie details.
de.ro.HelpCookiesMenu0-1-2:Klicken mit AUSWAHL versteckt alle Cookiedetails.
fr.ro.HelpCookiesMenu0-1-2:\Scacher le détail de tous les cookies.
it.ro.HelpCookiesMenu0-1-2:\Snascondi i dettagli dei cookie.
nl.ro.HelpCookiesMenu0-1-2:Klik met KIES om alle cookiedetails te verbergen.
+zh_CN.ro.HelpCookiesMenu0-1-2:\Séšè—所有 Cookie 详细信æ¯ã€‚
+
en.ro.HelpCookiesMenu0-2:\Rcontrol the display of NetSurf's toolbars.
de.ro.HelpCookiesMenu0-2:Die Iconleiste verändern.
-fr.ro.HelpCookiesMenu0-2:\Rcontroler l'affichage des barres d'outils de Netsurf.
-it.ro.HelpCookiesMenu0-2:\Rcontrol the display of NetSurf's toolbars.
+fr.ro.HelpCookiesMenu0-2:\Rcontroler l’affichage des barres d’outils de Netsurf.
+it.ro.HelpCookiesMenu0-2:\Rcontrolla la visualizzazione delle barre strumenti di NetSurf.
nl.ro.HelpCookiesMenu0-2:Verplaats de muispijl naar rechts om de gereedschapbalken aan te passen.
+zh_CN.ro.HelpCookiesMenu0-2:\R控制显示 NetSurf 工具æ ã€‚
+
en.ro.HelpCookiesMenu0-2-0:\Stoggle the display of the toolbar buttons.
de.ro.HelpCookiesMenu0-2-0:Klicken mit AUSWAHL um die Iconleiste an- oder abzuschalten.
-fr.ro.HelpCookiesMenu0-2-0:\Sbasculer l'affichage des boutons de la barre d'outils.
-it.ro.HelpCookiesMenu0-2-0:\Stoggle the display of the toolbar buttons.
+fr.ro.HelpCookiesMenu0-2-0:\Sbasculer l’affichage des boutons de la barre d’outils.
+it.ro.HelpCookiesMenu0-2-0:\Salterna la visualizzazione dei pulsanti della barra strumenti.
nl.ro.HelpCookiesMenu0-2-0:Klik met KIES om het tonen van de knoppen op de gereedschapbalk aan of uit te zetten.
+zh_CN.ro.HelpCookiesMenu0-2-0:\S切æ¢æ˜¾ç¤ºå·¥å…·æ æŒ‰é’®ã€‚
+
en.ro.HelpCookiesMenu0-2-1:\Stoggle toolbar edit mode.
de.ro.HelpCookiesMenu0-2-1:Klicken mit AUSWAHL um die Iconleiste zu bearbeiten.
-fr.ro.HelpCookiesMenu0-2-1:\Sbasculer le mode d'édition de la barre d'outils.
-it.ro.HelpCookiesMenu0-2-1:\Stoggle toolbar edit mode.
+fr.ro.HelpCookiesMenu0-2-1:\Sbasculer le mode d’édition de la barre d’outils.
+it.ro.HelpCookiesMenu0-2-1:\Salterna la modalità di modifica della barra strumenti.
nl.ro.HelpCookiesMenu0-2-1:Klik met KIES om de aanpasmodus van de gereedschapbalk in of uit te schakelen. Wanneer ingeschakelt, verschijnt er een balk onder de gereedschapbalk met extra knoppen die van en naar deze balk gesleept kunnen worden om deze aan te passen.
+zh_CN.ro.HelpCookiesMenu0-2-1:\S切æ¢å·¥å…·æ ç¼–辑模å¼ã€‚
+
en.ro.HelpCookiesMenu1:\Roperate on the current selection.
de.ro.HelpCookiesMenu1:Die ausgewählten Einträge bearbeiten.
fr.ro.HelpCookiesMenu1:\Rfaire une opération sur la sélection courante.
it.ro.HelpCookiesMenu1:\Ropera nella selezione corrente.
nl.ro.HelpCookiesMenu1:Verplaats de muispijl naar rechts om een operatie op deze selectie uit te voeren.
+zh_CN.ro.HelpCookiesMenu1:\R对当å‰é€‰æ‹©æ‰§è¡Œæ“作。
+
en.ro.HelpCookiesMenu1-0:\Sdelete any selected cookies.
de.ro.HelpCookiesMenu1-0:Klicken mit AUSWAHL löscht alle markierten Cookies.
fr.ro.HelpCookiesMenu1-0:\Ssupprimer tous les cookies sélectionnés.
it.ro.HelpCookiesMenu1-0:\Scancella tutti i cookie selezionati.
nl.ro.HelpCookiesMenu1-0:Klik met KIES om deze geselecteerde cookies te verwijderen.
+zh_CN.ro.HelpCookiesMenu1-0:\S删除所有选定的 Cookies。
+
en.ro.HelpCookiesMenu2:\Sselect all the items in the cookie list.
de.ro.HelpCookiesMenu2:Klicken mit AUSWAHL markiert alle Cookies als gewählt.
-fr.ro.HelpCookiesMenu2:\Ssélectionner tous les items dans la liste de cookies.
+fr.ro.HelpCookiesMenu2:\Ssélectionner tous les items dans la liste des cookies.
it.ro.HelpCookiesMenu2:\Sseleziona tutti gli oggetti dalla lista dei cookie.
nl.ro.HelpCookiesMenu2:Klik met KIES om alle cookies in het cookiesbeheervenster te selecteren.
+zh_CN.ro.HelpCookiesMenu2:\S选择 Cookie 列表中的所有项。
+
en.ro.HelpCookiesMenu3:\Sdeselect all selected items.
de.ro.HelpCookiesMenu3:Klicken mit AUSWAHL macht alle Markierungen rückgängig.
fr.ro.HelpCookiesMenu3:\Sdéselectionner tous les items.
it.ro.HelpCookiesMenu3:\Sdeseleziona tutti gli oggetti selezionati.
nl.ro.HelpCookiesMenu3:Klik met KIES om alle geselecteerde items te deselecteren.
+zh_CN.ro.HelpCookiesMenu3:\Så–消选择所有选定项。
en.ro.HelpAppInfo:\TNetSurf information \w.|MSee the about page for the contributor list and credits.
de.ro.HelpAppInfo:Das ist das Info-Fenster zu NetSurf.|MGenauere Angaben zu den Autoren, Grafikern, Übersetzern, genutzten Libraries etc. gibt es bei "Über NetSurf" im Untermenü Hilfe eines Browserfensters.
-fr.ro.HelpAppInfo:\Tla \w d'information de NetSurf.|MVoir la page "À propos de" pour une liste des contributeurs et les remerciements.
+fr.ro.HelpAppInfo:\Tla \w d’information de NetSurf.|MVoir la page "À propos de" pour une liste des contributeurs et les remerciements.
it.ro.HelpAppInfo:\TInformazioni su NetSurf \w.|MMostra la pagina delle informazioni e la lista dei ringraziamenti.
nl.ro.HelpAppInfo:Dit is het NetSurf-informatievenster.|MOpen de Bijdragen-pagina voor de lijst met degenen die bijdroegen aan het NetSurf-project.
+zh_CN.ro.HelpAppInfo:\TNetSurf ä¿¡æ¯ \w。|M相关贡献者列表和制作人员åå•ï¼Œè¯·å‚阅关于页é¢ã€‚
en.ro.HelpConfigure:\Tconfiguration \w for NetSurf
@@ -5040,641 +7168,882 @@ de.ro.HelpConfigure:Dies ist das Konfigurationsfenster von NetSurf.
fr.ro.HelpConfigure:\Tla fenêtre de configuration pour Netsurf
it.ro.HelpConfigure:\Tconfigurazione \w per NetSurf
nl.ro.HelpConfigure:Dit is het NetSurf-instellingenvenster.
+zh_CN.ro.HelpConfigure:\T NetSurf çš„é…ç½® \w
+
en.ro.HelpConfigure0:Cache configuration tool
de.ro.HelpConfigure0:Cachespeicher konfigurieren
fr.ro.HelpConfigure0:Outil de configuration de cache
it.ro.HelpConfigure0:Strumento di configurazione della cache
nl.ro.HelpConfigure0:Buffer-instellingen.|MKlik op dit symbool om de instellingen van de buffers aan te passen.
+zh_CN.ro.HelpConfigure0:缓存é…置工具
+
en.ro.HelpConfigure1:Connection configuration tool
de.ro.HelpConfigure1:Verbindungen konfigurieren
fr.ro.HelpConfigure1:Outil de configuration de connexion
it.ro.HelpConfigure1:Strumento di configurazione della connessione
nl.ro.HelpConfigure1:Verbinding-instellingen.|MKlik op dit symbool om de instellingen van de verbinding aan te passen.
+zh_CN.ro.HelpConfigure1:连接é…置工具
+
en.ro.HelpConfigure2:Content configuration tool
de.ro.HelpConfigure2:Bestimmte Seiteninhalte zulassen oder abschalten
fr.ro.HelpConfigure2:Outil de configuration de contenu
it.ro.HelpConfigure2:Strumento di configurazione dei contenuti
nl.ro.HelpConfigure2:Browsen-instellingen.|MKlik op dit symbool om het gedrag van de browser aan te passen.
+zh_CN.ro.HelpConfigure2:内容é…置工具
+
en.ro.HelpConfigure3:Font configuration tool
de.ro.HelpConfigure3:Zeichensätze konfigurieren
fr.ro.HelpConfigure3:Outil de configuration de fontes
it.ro.HelpConfigure3:Strumento di configurazione dei font
nl.ro.HelpConfigure3:Lettertypen-instellingen.|MKlik op dit symbool om de instellingen van de lettertypen aan te passen.
+zh_CN.ro.HelpConfigure3:字体é…置工具
+
en.ro.HelpConfigure4:Home page configuration tool
de.ro.HelpConfigure4:Homepage einstellen
-fr.ro.HelpConfigure4:Outil de configuration de la page d'accueil
+fr.ro.HelpConfigure4:Outil de configuration de la page d’accueil
it.ro.HelpConfigure4:Strumento di configurazione della pagina iniziale
nl.ro.HelpConfigure4:Begin-/Startpagina-instellingen.|MKlik op dit symbool om de begin-/startpagin in te stellen.
+zh_CN.ro.HelpConfigure4:主页é…置工具
+
en.ro.HelpConfigure5:Image configuration tool
de.ro.HelpConfigure5:Bilderdarstellung konfigurieren
-fr.ro.HelpConfigure5:Outil de configuration d'image
+fr.ro.HelpConfigure5:Outil de configuration d’image
it.ro.HelpConfigure5:Strumento di configurazione delle immagini
nl.ro.HelpConfigure5:Afbeeldingen-instellingen.|MKlik op dit symbool om de afhandelinginstellingen van de afbeeldingen aan te passen.
+zh_CN.ro.HelpConfigure5:图åƒé…置工具
+
en.ro.HelpConfigure6:Interface configuration tool
de.ro.HelpConfigure6:Programmverhalten für besondere Situationen einstellen
-fr.ro.HelpConfigure6:Outil de configuration d'interface
+fr.ro.HelpConfigure6:Outil de configuration d’interface
it.ro.HelpConfigure6:Strumento di configurazione dell'interfaccia
nl.ro.HelpConfigure6:Interface-instellingen.|MKlik op dit symbool om de instellingen van de gebruikersinterface aan te passen.
+zh_CN.ro.HelpConfigure6:ç•Œé¢é…置工具
+
en.ro.HelpConfigure7:Language configuration tool
de.ro.HelpConfigure7:Sprachen einstellen
fr.ro.HelpConfigure7:Outil de configuration de langue
it.ro.HelpConfigure7:Strumento di configurazione della lingua
nl.ro.HelpConfigure7:Taal-instellingen.|MKlik op dit symbool om de taalinstellingen aan te passen.
+zh_CN.ro.HelpConfigure7:语言é…置工具
+
en.ro.HelpConfigure8:Theme configuration tool
de.ro.HelpConfigure8:Themenauswahl
fr.ro.HelpConfigure8:Outil de configuration de thème
it.ro.HelpConfigure8:Strumento di configurazione dei temi
nl.ro.HelpConfigure8:Thema-instellingen.|MKlik op dit symbool om een weergavethema te kiezen.
+zh_CN.ro.HelpConfigure8:主题é…置工具
+
en.ro.HelpConfigure9:Security and Privacy configuration tool
de.ro.HelpConfigure9:Sicherheitseinstellungen und Privatsphäre
fr.ro.HelpConfigure9:Outil de configuration de la sécurité et de la confidentialité
-it.ro.HelpConfigure9:Strumento di configurazione per Sicurezza e la Privacy
+it.ro.HelpConfigure9:Strumento di configurazione della Sicurezza e della Privacy
nl.ro.HelpConfigure9:Veiligheid en Privacy-instellingen|MKlik op dit symbool om de veiligheids- en privacyinstellingen aan te passen.
+zh_CN.ro.HelpConfigure9:安全和éšç§é…置工具
en.ro.HelpCacheConfig:\Tcache configuration \w.
de.ro.HelpCacheConfig:Das ist das Fenster der Cache-Konfiguration.
fr.ro.HelpCacheConfig:\Tla fenêtre de configuration du cache.
it.ro.HelpCacheConfig:\Tconfigurazione della cache \w.
nl.ro.HelpCacheConfig:Diverse bufferinstelligen kunnen in dit venster gewijzigd worden.
+zh_CN.ro.HelpCacheConfig:\T缓存é…ç½® \w。
+
en.ro.HelpCacheConfig3:\Tamount of memory to be used for caching content.
de.ro.HelpCacheConfig3:Speichergröße, die verwendet wird um Inhalte zwischenzuspeichern.
fr.ro.HelpCacheConfig3:\Tla quantité de mémoire à utiliser pour le contenu du cache.
-it.ro.HelpCacheConfig3:\Tquantità di memoria da usare per il contenuto della cache.
+it.ro.HelpCacheConfig3:\Tquantità di memoria da usare per il contenuto della cache.
nl.ro.HelpCacheConfig3:Dit invoerveld toont de hoeveelheid geheugen die wordt gebruikt om de pagina-inhoud te bufferen.
+zh_CN.ro.HelpCacheConfig3:\T用于缓存内容的内存é‡ã€‚
+
en.ro.HelpCacheConfig4:\Sreduce the amount of memory.
de.ro.HelpCacheConfig4:Klicken mit AUSWAHL verringert die Größe des Cachespeichers.
fr.ro.HelpCacheConfig4:\Sréduire la quantité de mémoire.
-it.ro.HelpCacheConfig4:\Sriduce la quantità di memoria.
+it.ro.HelpCacheConfig4:\Sriduci la quantità di memoria.
nl.ro.HelpCacheConfig4:Klik met KIES om de geheugenruimte kleiner te maken.
+zh_CN.ro.HelpCacheConfig4:\Så‡å°‘内存é‡ã€‚
+
en.ro.HelpCacheConfig5:\Sincrease the amount of memory.
de.ro.HelpCacheConfig5:Klicken mit AUSWAHL vergrößert die Größe des Cachespeichers.
fr.ro.HelpCacheConfig5:\Saugmenter la quantité de mémoire.
it.ro.HelpCacheConfig5:\Saumenta la quantità di memoria.
nl.ro.HelpCacheConfig5:Klik met KIES om de geheugenruimte groter te maken.
+zh_CN.ro.HelpCacheConfig5:\S增加内存é‡ã€‚
+
en.ro.HelpCacheConfig10:\Tamount of disc space to be used for caching content between sessions.
de.ro.HelpCacheConfig10:\Tamount of disc space to be used for caching content between sessions.
fr.ro.HelpCacheConfig10:\Tamount of disc space to be used for caching content between sessions.
-it.ro.HelpCacheConfig10:\Tquantità di spazio su disco da usare per il contenuto della cache tra le sessioni.
+it.ro.HelpCacheConfig10:\Tquantità di spazio su disco da usare per il contenuto della cache tra le sessioni.
nl.ro.HelpCacheConfig10:Dit invoerveld toont de hoeveelheid schijfruimte die wordt gebruikt om de pagina-inhoud tussen sessies te bufferen.
+zh_CN.ro.HelpCacheConfig10:\T用于缓存会è¯å†…容的ç£ç›˜ç©ºé—´å¤§å°ã€‚
+
en.ro.HelpCacheConfig11:\Sreduce the amount of memory.
de.ro.HelpCacheConfig11:Klicken mit AUSWAHL verringert die Größe des Cachespeichers.
fr.ro.HelpCacheConfig11:\Sréduire la quantité de mémoire.
-it.ro.HelpCacheConfig11:\Sriduce la quantità di memoria.
+it.ro.HelpCacheConfig11:\Sriduci la quantità di memoria.
nl.ro.HelpCacheConfig11:Klik met KIES om de schijfruimte kleiner te maken.
+zh_CN.ro.HelpCacheConfig11:\Så‡å°‘内存é‡ã€‚
+
en.ro.HelpCacheConfig12:\Sincrease the amount of memory.
de.ro.HelpCacheConfig12:Klicken mit AUSWAHL vergrößert die Größe des Cachespeichers.
fr.ro.HelpCacheConfig12:\Saugmenter la quantité de mémoire.
it.ro.HelpCacheConfig12:\Saumenta la quantità di memoria.
nl.ro.HelpCacheConfig12:Klik met KIES om de schijfruimte groter te maken.
+zh_CN.ro.HelpCacheConfig12:\S增加内存é‡ã€‚
+
en.ro.HelpCacheConfig15:\Tmaximum number of days that content will be retained in the disc cache.
de.ro.HelpCacheConfig15:\Tmaximum number of days that content will be retained in the disc cache.
fr.ro.HelpCacheConfig15:\Tmaximum number of days that content will be retained in the disc cache.
-it.ro.HelpCacheConfig15:\Tmaximum number of days that content will be retained in the disc cache.
+it.ro.HelpCacheConfig15:\Tnumero massimo di giorni in cui il contenuto verrà conservato nella cache del disco.
nl.ro.HelpCacheConfig15:Dit is het maximum aantal dagen dat de gebufferde pagina-inhoud op de schijf opgeslagen blijft.
+zh_CN.ro.HelpCacheConfig15:\T在ç£ç›˜ç¼“存中ä¿å­˜å†…容的最大天数。
+
en.ro.HelpCacheConfig16:\Sreduce the number of days.
de.ro.HelpCacheConfig16:\Sreduce the number of days.
fr.ro.HelpCacheConfig16:\Sreduce the number of days.
-it.ro.HelpCacheConfig16:\Sriduce il numero di giorni.
+it.ro.HelpCacheConfig16:\Sriduci il numero di giorni.
nl.ro.HelpCacheConfig16:Klik met KIES om het aantal dagen te verlagen.
+zh_CN.ro.HelpCacheConfig16:\Så‡å°‘天数。
+
en.ro.HelpCacheConfig17:\Sincrease the number of days.
de.ro.HelpCacheConfig17:\Sincrease the number of days.
fr.ro.HelpCacheConfig17:\Sincrease the number of days.
it.ro.HelpCacheConfig17:\Saumenta il numero di giorni.
nl.ro.HelpCacheConfig17:Klik met KIES om het aantal dagen te verhogen.
+zh_CN.ro.HelpCacheConfig17:\S增加天数。
+
en.ro.HelpCacheConfig19:\Sreset the Cache options back to their default values.
de.ro.HelpCacheConfig19:Stellt die Standardeinstellungen wieder her.
fr.ro.HelpCacheConfig19:\Srevenir aux valeurs par défaut des options du Cache.
-it.ro.HelpCacheConfig19:\Sreset the Cache options back to their default values.
+it.ro.HelpCacheConfig19:\Sresetta le opzioni della cache ai valori predefiniti.
nl.ro.HelpCacheConfig19:Klik met KIES om de bufferinstellingen in dit venster terug te zetten op de standaardwaarden.
+zh_CN.ro.HelpCacheConfig19:\S将缓存选项é‡ç½®ä¸ºé»˜è®¤å€¼ã€‚
+
en.ro.HelpCacheConfig20:\Sclose this \w without saving changes.|M\Areturn the cache options to the last saved configuration.
de.ro.HelpCacheConfig20:Klicken mit AUSWAHL schließt das Fenster ohne die Änderungen zu speichern.|MKlicken mit SPEZIAL stellt die zuletzt abgespeicherten Einstellungen wieder her.
fr.ro.HelpCacheConfig20:\Sfermer cette fenêtre sans sauver les changements.|M\Arevenir aux options de Cache précédemment sauvegardées.
-it.ro.HelpCacheConfig20:\Sclose this \w without saving changes.|M\Areturn the cache options to the last saved configuration.
+it.ro.HelpCacheConfig20:\Schiudi questa finestra senza salvare le modifiche.|M\Aripristina le opzioni della cache all'ultima configurazione salvata.
nl.ro.HelpCacheConfig20:Klik met KIES om dit venster te sluiten zonder dat de gemaakte wijzigingen worden bewaard.|MKlik met PASAAN om de gemaakte wijzigingen ongedaan te maken; het venster wordt hierbij niet gesloten.
+zh_CN.ro.HelpCacheConfig20:\S关闭此 \w 而ä¸ä¿å­˜æ›´æ”¹ã€‚|M\A将缓存选项æ¢å¤åˆ°ä¸Šæ¬¡ä¿å­˜çš„é…置。
+
en.ro.HelpCacheConfig21:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
de.ro.HelpCacheConfig21:Klicken mit AUSWAHL speichert die Einstellungen und schließt das Fenster.|MKlicken mit SPEZIAL speichert die Einstellungen ohne das Fenster zu schließen.
fr.ro.HelpCacheConfig21:\Ssauver ces réglages et fermer la fenêtre.|M\Asauver ces réglages sans fermer la fenêtre.
-it.ro.HelpCacheConfig21:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
+it.ro.HelpCacheConfig21:\Ssalva queste impostazioni e chiudi la finestra.|M\Asalva queste impostazioni senza chiudere la finestra.
nl.ro.HelpCacheConfig21:Klik met KIES om de gemaakte wijzigingen te bewaren en dit venster te sluiten.|MKlikken met PASAAN heeft hetzelfde effect, alleen wordt het huidige venster dan niet gesloten.
+zh_CN.ro.HelpCacheConfig21:\Sä¿å­˜è¿™äº›è®¾ç½®å¹¶å…³é—­ \w。|M\A在ä¸å…³é—­ \w 的情况下ä¿å­˜è¿™äº›è®¾ç½®ã€‚
en.ro.HelpConnectConfig:\Tconnection configuration \w
de.ro.HelpConnectConfig:Das ist das Fenster zur Einstellung der Parameter für die Netzanbindung.
fr.ro.HelpConnectConfig:\Tla fenêtre de configuration de connexion.
it.ro.HelpConnectConfig:\Tconfigurazione della connessione \w
nl.ro.HelpConnectConfig:Diverse verbindingsinstellingen kunnen in dit venster gewijzigd worden.
+zh_CN.ro.HelpConnectConfig:\T连接é…ç½® \w
+
en.ro.HelpConnectConfig3:\Tcurrently selected proxy type.|MUse the menu to select a proxy type.
de.ro.HelpConnectConfig3:Aktuell gewählter Proxytyp.|MMit dem Menü kann ein anderer Typ eingestellt werden.
fr.ro.HelpConnectConfig3:\Tle type de proxy sélectionné en ce moment.|MUtiliser le menu pour choisir un type de proxy.
-it.ro.HelpConnectConfig3:\Tcurrently selected proxy type.|MUse the menu to select a proxy type.
+it.ro.HelpConnectConfig3:\Ttipo di proxy correntemente selezionato.|MUsa il menu per selezionare il tipo di proxy.
nl.ro.HelpConnectConfig3:Dit is het huidige geselecteerde proxy-type.|MKlik op het symbool hiernaast om een proxy-type te selecteren.
+zh_CN.ro.HelpConnectConfig3:\T当å‰é€‰æ‹©çš„代ç†æœåŠ¡å™¨ç±»åž‹ã€‚|M使用èœå•ä»¥é€‰æ‹©ä»£ç†æœåŠ¡å™¨ç±»åž‹ã€‚
+
en.ro.HelpConnectConfig4:\Sselect a proxy type.
de.ro.HelpConnectConfig4:Klicken mit AUSWAHL um einen anderen Proxytyp auszuwählen.
fr.ro.HelpConnectConfig4:\Schoisir un type de proxy.
it.ro.HelpConnectConfig4:\Sseleziona un tipo di proxy.
nl.ro.HelpConnectConfig4:Klik met KIES om een proxy-type te selecteren.
+zh_CN.ro.HelpConnectConfig4:\S选择代ç†æœåŠ¡å™¨ç±»åž‹ã€‚
+
en.ro.HelpConnectConfig6:You can enter the proxy's host name here.
de.ro.HelpConnectConfig6:Hier kann der Hostname des Proxys eingegeben werden.
-fr.ro.HelpConnectConfig6:Vous pouvez entrer ici le nom d'hôte du proxy.
+fr.ro.HelpConnectConfig6:Vous pouvez entrer ici le nom d’hôte du proxy.
it.ro.HelpConnectConfig6:Inserisci qui il nome host del proxy.
nl.ro.HelpConnectConfig6:Voer hier de hostnaam in voor de proxy-server.
+zh_CN.ro.HelpConnectConfig6:您å¯ä»¥åœ¨æ­¤å¤„输入代ç†æœåŠ¡å™¨çš„主机å。
+
en.ro.HelpConnectConfig8:You can enter the proxy's port number here.
de.ro.HelpConnectConfig8:Hier kann die zugehörige Portnummer eingestellt werden.
fr.ro.HelpConnectConfig8:Vous pouvez entrer ici le numéro de port du proxy.
it.ro.HelpConnectConfig8:Inserisci qui il numero di porta del proxy.
nl.ro.HelpConnectConfig8:Voer hier het poortnummer in voor de proxy.
+zh_CN.ro.HelpConnectConfig8:您å¯ä»¥åœ¨æ­¤å¤„输入代ç†æœåŠ¡å™¨çš„端å£å·ã€‚
+
en.ro.HelpConnectConfig10:You can enter a username for proxies that require authentication here.
de.ro.HelpConnectConfig10:Hier kann ein Username eingegeben werden, wenn der Proxy das erfordert.
-fr.ro.HelpConnectConfig10:Vous pouvez entrer ici un nom d'utilisateur pour les proxies nécessitant une authentification.
-it.ro.HelpConnectConfig10:Inserisci un nome utente per i proxy che richiedano un'autentificazione.
+fr.ro.HelpConnectConfig10:Vous pouvez entrer ici un nom d’utilisateur pour les proxies nécessitant une authentification.
+it.ro.HelpConnectConfig10:Inserisci un nome utente per i proxy che richiedono autentificazione.
nl.ro.HelpConnectConfig10:Voer hier een gebruikersnaam in voor proxies die authenticifering vereisen.
+zh_CN.ro.HelpConnectConfig10:您å¯ä»¥åœ¨æ­¤å¤„输入需è¦èº«ä»½éªŒè¯çš„代ç†æœåŠ¡å™¨ç”¨æˆ·å。
+
en.ro.HelpConnectConfig12:You can enter a password for proxies that require authentication here.
de.ro.HelpConnectConfig12:Hier kann das zum Usernamen gehörige Passwort eingegeben werden.
fr.ro.HelpConnectConfig12:Vous pouvez entrer ici un mot de passe pour les proxies nécessitant une authentification.
-it.ro.HelpConnectConfig12:Inserisci una password per i proxy che richiedano un'autentificazione.
+it.ro.HelpConnectConfig12:Inserisci una password per i proxy che richiedono autentificazione.
nl.ro.HelpConnectConfig12:Voer hier een wachtwoord in voor proxies die authenticifering vereisen.
+zh_CN.ro.HelpConnectConfig12:您å¯ä»¥åœ¨æ­¤å¤„输入需è¦èº«ä»½éªŒè¯çš„代ç†æœåŠ¡å™¨å¯†ç ã€‚
+
en.ro.HelpConnectConfig16:\Tmaximum number of simultaneous fetches that NetSurf will perform.
de.ro.HelpConnectConfig16:Das ist die Maximalzahl simultaner Fetches, die NetSurf verwenden soll.
fr.ro.HelpConnectConfig16:\Tle nombre maximum de télechargements simultanés que NetSurf peut effectuer.
-it.ro.HelpConnectConfig16:\Tmaximum number of simultaneous fetches that NetSurf will perform.
+it.ro.HelpConnectConfig16:\Tnumero massimo di tentativi simultanei che NetSurf dovrà eseguire.
nl.ro.HelpConnectConfig16:Dit is het maximaal aantal simultaan uit te voeren ophaalopdrachten.
+zh_CN.ro.HelpConnectConfig16:\T NetSurf 将执行的åŒæ—¶èŽ·å–最大数é‡ã€‚
+
en.ro.HelpConnectConfig17:\Sreduce the maximum number of simultaneous fetches.
de.ro.HelpConnectConfig17:Klicken mit AUSWAHL verringert die Maximalzahl simultaner Fetches.
fr.ro.HelpConnectConfig17:\Sréduire le nombre de téléchargements simultanés.
-it.ro.HelpConnectConfig17:\Sreduce the maximum number of simultaneous fetches.
+it.ro.HelpConnectConfig17:\Sriduci il numero massimo di tentativi simultanei.
nl.ro.HelpConnectConfig17:Klik met KIES om het maximaal aantal simultaan uit te voeren ophaalopdrachten te verlagen.
+zh_CN.ro.HelpConnectConfig17:\Så‡å°‘åŒæ—¶èŽ·å–的最大数é‡ã€‚
+
en.ro.HelpConnectConfig18:\Sincrease the maximum number of simultaneous fetches.
de.ro.HelpConnectConfig18:Klicken mit AUSWAHL vergrößert die Maximalzahl simultaner Fetches.
fr.ro.HelpConnectConfig18:\Saugmenter le nombre de téléchargements simultanés.
-it.ro.HelpConnectConfig18:\Sincrease the maximum number of simultaneous fetches.
+it.ro.HelpConnectConfig18:\Saumenta il numero massimo di tentativi simultanei.
nl.ro.HelpConnectConfig18:Klik met KIES om het maximaal aantal simultaan uit te voeren ophaaldopdrachten te verhogen.
+zh_CN.ro.HelpConnectConfig18:\S增加åŒæ—¶èŽ·å–的最大数é‡ã€‚
+
en.ro.HelpConnectConfig20:\Tmaximum number of simultaneous fetches that NetSurf will perform per host.
de.ro.HelpConnectConfig20:Das ist die Maximalzahl simultaner Fetches, die je Host von NetSurf verwendet werden.
fr.ro.HelpConnectConfig20:\Tle nombre maximum de téléchargements simultanés que Netsurf peut effectuer par hôte.
-it.ro.HelpConnectConfig20:\Tmaximum number of simultaneous fetches that NetSurf will perform per host.
+it.ro.HelpConnectConfig20:\Tnumero massimo di tentativi simultanei che NetSurf dovrà eseguire per host.
nl.ro.HelpConnectConfig20:Dit is het maximaal aantal simultaan uit te voeren ophaalopdrachten per host.
+zh_CN.ro.HelpConnectConfig20:\T NetSurf 将在æ¯å°ä¸»æœºä¸Šçš„最大åŒæ—¶èŽ·å–数。
+
en.ro.HelpConnectConfig21:\Sreduce the maximum number of simultaneous fetches per host.
de.ro.HelpConnectConfig21:Klicken mit AUSWAHL verringert die Maximalzahl simultaner Fetches je Host.
fr.ro.HelpConnectConfig21:\Sréduire le nombre maximum de téléchargements simultanés par hôte.
-it.ro.HelpConnectConfig21:\Sreduce the maximum number of simultaneous fetches per host.
+it.ro.HelpConnectConfig21:\Sriduci il numero massimo di tentativi simultanei per host.
nl.ro.HelpConnectConfig21:Klik met KIES om het maximaal aantal simultaan uit te voeren ophaalopdrachten per host te verlagen.
+zh_CN.ro.HelpConnectConfig21:\Så‡å°‘æ¯å°ä¸»æœºæœ€å¤§çš„åŒæ—¶èŽ·å–数。
+
en.ro.HelpConnectConfig22:\Sincrease the maximum number of simultaneous fetches per host.
de.ro.HelpConnectConfig22:Klicken mit AUSWAHL vergrößert die Maximalzahl simultaner Fetches je Host.
fr.ro.HelpConnectConfig22:\Saugmenter le nombre maximum de téléchargements simultanés par hôte.
-it.ro.HelpConnectConfig22:\Sincrease the maximum number of simultaneous fetches per host.
+it.ro.HelpConnectConfig22:\Saumenta il numero massimo di tentativi simultanei per host.
nl.ro.HelpConnectConfig22:Klik met KIES om het maximaal aantal simultaan uit te voeren ophaalopdrachten per host te verhogen.
+zh_CN.ro.HelpConnectConfig22:\S增加æ¯å°ä¸»æœºæœ€å¤§çš„åŒæ—¶èŽ·å–数。
+
en.ro.HelpConnectConfig24:\Tmaximum number of persistent connections.
de.ro.HelpConnectConfig24:Das ist die Maximalzahl aufrechtzuerhaltender Verbindungen.
fr.ro.HelpConnectConfig24:\Tle nombre maximum de connexions persistantes.
it.ro.HelpConnectConfig24:\Tnumero massimo di connessioni persistenti.
nl.ro.HelpConnectConfig24:Dit is het maximum aantal langdurige verbindingen.
+zh_CN.ro.HelpConnectConfig24:\TæŒç»­æ€§è¿žæŽ¥çš„最大数é‡ã€‚
+
en.ro.HelpConnectConfig25:\Sreduce the maximum number of persistent connections.
de.ro.HelpConnectConfig25:Klicken mit AUSWAHL verringert die Maximalzahl offengehaltener Verbindungen.
fr.ro.HelpConnectConfig25:\Sréduire le nombre maximum de connexions persistantes.
it.ro.HelpConnectConfig25:\Sriduci il numero massimo di connessioni persistenti.
nl.ro.HelpConnectConfig25:Klik met KIES om het maximum aantal langdurige verbindingen te verlagen.
+zh_CN.ro.HelpConnectConfig25:\Så‡å°‘æŒç»­æ€§è¿žæŽ¥çš„最大数é‡ã€‚
+
en.ro.HelpConnectConfig26:\Sincrease the maximum number of persistent connections.
de.ro.HelpConnectConfig26:Klicken mit AUSWAHL vergrößert die Maximalzahl offengehaltener Verbindungen.
fr.ro.HelpConnectConfig26:\Saugmenter le nombre maximum de connexions persistantes.
it.ro.HelpConnectConfig26:\Saumenta il numero massimo di connessioni persistenti.
nl.ro.HelpConnectConfig26:Klik met KIES om het maximum aantal langdurige verbindingen te verhogen.
+zh_CN.ro.HelpConnectConfig26:\S增加æŒç»­æ€§è¿žæŽ¥çš„最大数é‡ã€‚
+
en.ro.HelpConnectConfig27:\Sreset the Connection options back to their default values.
de.ro.HelpConnectConfig27:Stellt die Standardeinstellungen wieder her.
fr.ro.HelpConnectConfig27:\Srevenir aux valeurs par défaut des options de Connexion.
-it.ro.HelpConnectConfig27:\Sreset the Connection options back to their default values.
+it.ro.HelpConnectConfig27:\Sresetta le opzioni di connessioni ai valori predefiniti.
nl.ro.HelpConnectConfig27:Klik met KIES om de verbindingsinstellingen in dit venster terug te zetten op de standaardwaarden.
+zh_CN.ro.HelpConnectConfig27:\S将连接选项é‡ç½®ä¸ºé»˜è®¤å€¼ã€‚
+
en.ro.HelpConnectConfig28:\Sclose this \w without saving changes.|M\Areturn the connection options to the last saved configuration.
de.ro.HelpConnectConfig28:Klicken mit AUSWAHL schließt das Fenster ohne die Änderungen zu speichern.|MKlicken mit SPEZIAL stellt die zuletzt abgespeicherten Einstellungen wieder her.
fr.ro.HelpConnectConfig28:\Sfermer cette fenêtre sans sauvegarder les changements.|M\Arevenir aux options de Connexion précédemment sauvegardées.
-it.ro.HelpConnectConfig28:\Sclose this \w without saving changes.|M\Areturn the connection options to the last saved configuration.
+it.ro.HelpConnectConfig28:\Schiudi questa finestra senza salvare le modifiche.|M\Aripristina le opzioni della connessione all'ultima configurazione salvata.
nl.ro.HelpConnectConfig28:Klik met KIES om dit venster te sluiten zonder dat de gemaakte wijzigingen worden bewaard.|MKlik met PASAAN om de gemaakte wijzigingen ongedaan te maken; het venster wordt hierbij niet gesloten.
+zh_CN.ro.HelpConnectConfig28:\S关闭此 \w 而ä¸ä¿å­˜æ›´æ”¹ã€‚|M\A将连接选项æ¢å¤åˆ°ä¸Šæ¬¡ä¿å­˜çš„é…置。
+
en.ro.HelpConnectConfig29:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
de.ro.HelpConnectConfig29:Klicken mit AUSWAHL speichert die Einstellungen und schließt das Fenster.|MKlicken mit SPEZIAL speichert die Einstellungen ohne das Fenster zu schließen.
fr.ro.HelpConnectConfig29:\Ssauver ces réglages et fermer la fenêtre.|M\Asauver ces réglages sans fermer la fenêtre.
-it.ro.HelpConnectConfig29:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
+it.ro.HelpConnectConfig29:\Ssalva queste impostazioni e chiudi la finestra.|M\Asalva queste impostazioni senza chiudere la finestra.
nl.ro.HelpConnectConfig29:Klik met KIES om de gemaakte wijzigingen te bewaren en dit venster te sluiten.|MKlikken met PASAAN heeft hetzelfde effect, alleen wordt het huidige venster dan niet gesloten.
+zh_CN.ro.HelpConnectConfig29:\Sä¿å­˜è¿™äº›è®¾ç½®å¹¶å…³é—­ \w。|M\A在ä¸å…³é—­ \w 的情况下ä¿å­˜è¿™äº›è®¾ç½®ã€‚
en.ro.HelpContentConfig:\Tcontent configuration \w
de.ro.HelpContentConfig:Fenster zur Einstellung des Browserverhaltens bei bestimmten Seiteninhalten
fr.ro.HelpContentConfig:\Tla fenêtre de configuration du Contenu
-it.ro.HelpContentConfig:\Tconfigurazione dei contenuti \w
+it.ro.HelpContentConfig:\Tconfigurazione del contenuto \w
nl.ro.HelpContentConfig:Het gedrag van de browser kan in dit venster gewijzigd worden.
+zh_CN.ro.HelpContentConfig:\T文本é…ç½® \w
+
en.ro.HelpContentConfig2:This indicates whether NetSurf will attempt to block advertisements on web pages|MIn rare circumstances, this option may cause valid content to be blocked too.
de.ro.HelpContentConfig2:Stellt ein, ob NetSurf versuchen soll, die auf Webseiten eingeblendete Werbung automatisch zu unterdrücken.|MIn seltenen Fällen wird dadurch jedoch auch 'echter' Seiteninhalt geblockt.
fr.ro.HelpContentConfig2:Ceci indique si Netsurf doit essayer de bloquer les pubs sur les pages web.|MEn de rares circonstances, cette option peut également bloquer du contenu valide.
-it.ro.HelpContentConfig2:This indicates whether NetSurf will attempt to block advertisements on web pages|MIn rare circumstances, this option may cause valid content to be blocked too.
+it.ro.HelpContentConfig2:Indica se NetSurf tenterà di bloccare gli annunci pubblicitari sulle pagine Web|MNota che in rare circostanze questa opzione potrebbe causare il blocco anche di contenuti validi.
nl.ro.HelpContentConfig2:Deze optie geeft aan of NetSurf advertenties op webpagina's probeert te blokkeren.|MIn zeldzame situaties, kan deze optie ook zinvolle informatie blokkeren.
+zh_CN.ro.HelpContentConfig2:这表示 NetSurf 是å¦ä¼šå°è¯•å±è”½ç½‘页上的广告|M在æžå°‘数情况下,此选项å¯èƒ½ä¼šå¯¼è‡´å±è”½æœ‰æ•ˆå†…容。
+
en.ro.HelpContentConfig3:This indicates whether NetSurf will stop web sites from automatically opening new windows on your desktop.
de.ro.HelpContentConfig3:Stellt ein, ob NetSurf das automatische Öffnen neuer Fenster auf dem Desktop unterbinden soll.
-fr.ro.HelpContentConfig3:Ceci indique si Netsurf doit empêcher les sites web d'ouvrir automatiquement de nouvelles fenêtres sur votre Bureau.
-it.ro.HelpContentConfig3:This indicates whether NetSurf will stop web sites from automatically opening new windows on your desktop.
+fr.ro.HelpContentConfig3:Ceci indique si Netsurf doit empêcher les sites web d’ouvrir automatiquement de nouvelles fenêtres sur votre Bureau.
+it.ro.HelpContentConfig3:Indica se NetSurf impedirà ai siti Web di aprire automaticamente nuove finestre sul desktop.
nl.ro.HelpContentConfig3:Deze optie geeft aan of NetSurf websites, die automatisch nieuwe pagina's proberen te openen blokkeerd.
-en.ro.HelpContentConfig4:This indicates whether NetSurf will allow external plug-ins to handle additional types of content, such as Flash.
-de.ro.HelpContentConfig4:Stellt ein, ob externe Pluginroutinen genutzt werden dürfen, um Zusatzinhalte darzustellen (z.B. Flash).
-fr.ro.HelpContentConfig4:Ceci indique si Netsurf doit autoriser les plug-ins externes à manipuler des types de contenu supplémentaires, comme le Flash.
-it.ro.HelpContentConfig4:This indicates whether NetSurf will allow external plug-ins to handle additional types of content, such as Flash.
-nl.ro.HelpContentConfig4:Deze optie geeft aan of NetSurf externe plug-ins, voor aanvullende soorten inhoud zoals Flash toestaat.
+zh_CN.ro.HelpContentConfig3:这表示NetSurf是å¦ä¼šé˜»æ­¢ç½‘站在您的桌é¢ä¸Šè‡ªåŠ¨æ‰“开新窗å£ã€‚
+
+en.ro.HelpContentConfig4:This indicates whether NetSurf will allow web pages to style their content with CSS.
+de.ro.HelpContentConfig4:This indicates whether NetSurf will allow web pages to style their content with CSS.
+fr.ro.HelpContentConfig4:This indicates whether NetSurf will allow web pages to style their content with CSS.
+it.ro.HelpContentConfig4:This indicates whether NetSurf will allow web pages to style their content with CSS.
+nl.ro.HelpContentConfig4:This indicates whether NetSurf will allow web pages to style their content with CSS.
+zh_CN.ro.HelpContentConfig4:This indicates whether NetSurf will allow web pages to style their content with CSS.
+
en.ro.HelpContentConfig7:This indicates whether NetSurf will allow links to open in new windows.
de.ro.HelpContentConfig7:Stellt ein, ob NetSurf erlaubt, daß Links beim Aufruf neue Browserfenster öffnen dürfen.
fr.ro.HelpContentConfig7:This indicates whether NetSurf will allow links to open in new windows.
-it.ro.HelpContentConfig7:This indicates whether NetSurf will allow links to open in new windows.
+it.ro.HelpContentConfig7:Indica se NetSurf consentirà l'apertura dei link in nuove finestre.
nl.ro.HelpContentConfig7:Deze optie geeft aan of NetSurf toestaat, dat koppelingen in een nieuwe venster geopend mogen worden.
+zh_CN.ro.HelpContentConfig7:这表示 NetSurf 是å¦å…许在新窗å£ä¸­æ‰“开链接。
+
en.ro.HelpContentConfig8:\Sreset the Content options back to their default values.
de.ro.HelpContentConfig8:Stellt die Standardeinstellungen wieder her.
fr.ro.HelpContentConfig8:\Srevenir aux valeurs par défaut des options du Contenu.
-it.ro.HelpContentConfig8:\Sreset the Content options back to their default values.
+it.ro.HelpContentConfig8:\Sresetta le opzioni del contenuto ai valori predefiniti.
nl.ro.HelpContentConfig8:Klik met KIES om de instellingen in dit venster terug te zetten op de standaardwaarden.
+zh_CN.ro.HelpContentConfig8:\S将内容选项é‡ç½®ä¸ºé»˜è®¤å€¼ã€‚
+
en.ro.HelpContentConfig9:\Sclose this \w without saving changes.|M\Areturn the content options to the last saved configuration.
de.ro.HelpContentConfig9:Klicken mit AUSWAHL schließt das Fenster ohne die Änderungen zu speichern.|MKlicken mit SPEZIAL stellt die zuletzt abgespeicherten Einstellungen wieder her.
fr.ro.HelpContentConfig9:\Sfermer cette fenêtre sans sauver les changements|M\Arevenir aux options de Contenu précédemment sauvegardées.
-it.ro.HelpContentConfig9:\Sclose this \w without saving changes.|M\Areturn the content options to the last saved configuration.
+it.ro.HelpContentConfig9:\Schiudi questa finestra senza salvare le modifiche.|M\Aripristina le opzioni del contenuto all'ultima configurazione salvata.
nl.ro.HelpContentConfig9:Klik met KIES om dit venster te sluiten zonder dat de gemaakte wijzigingen worden bewaard.|MKlik met PASAAN om de gemaakte wijzigingen ongedaan te maken; het venster wordt hierbij niet gesloten.
+zh_CN.ro.HelpContentConfig9:\S关闭此 \w 而ä¸ä¿å­˜æ›´æ”¹ã€‚|M\A将文本选项æ¢å¤åˆ°ä¸Šæ¬¡ä¿å­˜çš„é…置。
+
en.ro.HelpContentConfig10:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
de.ro.HelpContentConfig10:Klicken mit AUSWAHL speichert die Einstellungen und schließt das Fenster.|MKlicken mit SPEZIAL speichert die Einstellungen ohne das Fenster zu schließen.
fr.ro.HelpContentConfig10:\Ssauver ces réglages et fermer la fenêtre.|M\Asauver ces réglages sans fermer la fenêtre.
-it.ro.HelpContentConfig10:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
+it.ro.HelpContentConfig10:\Ssalva queste impostazioni e chiudi la finestra.|M\Asalva queste impostazioni senza chiudere la finestra.
nl.ro.HelpContentConfig10:Klik met KIES om de gemaakte wijzigingen te bewaren en dit venster te sluiten.|MKlikken met PASAAN heeft hetzelfde effect, alleen wordt het huidige venster dan niet gesloten.
+zh_CN.ro.HelpContentConfig10:\Sä¿å­˜è¿™äº›è®¾ç½®å¹¶å…³é—­ \w。|M\A在ä¸å…³é—­ \w 的情况下ä¿å­˜è¿™äº›è®¾ç½®ã€‚
+
en.ro.HelpContentConfig11:This indicates whether NetSurf will disable executing JavaScript.
de.ro.HelpContentConfig11:This indicates whether NetSurf will disable executing JavaScript.
fr.ro.HelpContentConfig11:This indicates whether NetSurf will disable executing JavaScript.
-it.ro.HelpContentConfig11:This indicates whether NetSurf will disable executing JavaScript.
+it.ro.HelpContentConfig11:Indica se NetSurf disabiliterà l'esecuzione di JavaScript.
nl.ro.HelpContentConfig11:Deze optie geeft aan of het uitvoeren van JavaScript-scripts is uitgeschakeld.
+zh_CN.ro.HelpContentConfig11:这表示 NetSurf 是å¦ç¦ç”¨ JavaScript。
+
en.ro.HelpFontConfig:\Tfont configuration \w
de.ro.HelpFontConfig:Konfigurationsfenster zur Einstellung der verwendeten Schriftarten
fr.ro.HelpFontConfig:\Tla fenêtre de configuration de Fontes
it.ro.HelpFontConfig:\Tconfigurazione dei font \w
nl.ro.HelpFontConfig:De instellingen voor de verschillende tekststijlen kunnen in dit venster gewijzigd worden.
+zh_CN.ro.HelpFontConfig:\T字体é…ç½® \w
+
en.ro.HelpFontConfig3:\Tcurrently selected sans-serif font.|MNetSurf will use this font wherever a web page specifies a sans-serif typeface.
de.ro.HelpFontConfig3:Das ist die aktuell gewählte Schriftart für Sans-serif.|MNetSurf wird diese Schriftart überall dort verwenden, wo von der Webseite ein Schriftbild in Sans-serif vorgegeben wird.
-fr.ro.HelpFontConfig3:\Tla fonte sans-sérif actuellement sélectionnée.|MNetsurf utilisera cette fonte à chaque fois qu'une page web spécifiera une police sans-sérif.
-it.ro.HelpFontConfig3:\Tcurrently selected sans-serif font.|MNetSurf will use this font wherever a web page specifies a sans-serif typeface.
+fr.ro.HelpFontConfig3:\Tla fonte sans-sérif actuellement sélectionnée.|MNetsurf utilisera cette fonte à chaque fois qu’une page web spécifiera une police sans-sérif.
+it.ro.HelpFontConfig3:\Tfont sans-serif correntemente selezionato.|MNetSurf utilizzerà questo font ovunque una pagina Web specifichi un carattere tipografico di tipo sans-serif.
nl.ro.HelpFontConfig3:Dit is momenteel het geselecteerde schreefloos lettertype.|MNetSurf gebruikt dit lettertype wanneer een webpagina om deze tekststijl vraagt.
+zh_CN.ro.HelpFontConfig3:\T当å‰é€‰å®šçš„无衬线字体。|M NetSurf 将在网页指定 无衬线字体的任何地方使用此字体。
+
en.ro.HelpFontConfig4:\Sselect a sans-serif font.
de.ro.HelpFontConfig4:Klicken mit AUSWAHL, um eine Schriftart auszuwählen.
fr.ro.HelpFontConfig4:\Ssélectionner une fonte sans-sérif.
it.ro.HelpFontConfig4:\Sseleziona un font sans-serif
nl.ro.HelpFontConfig4:Klik met KIES om een schreefloos lettertype te selecteren.
+zh_CN.ro.HelpFontConfig4:\S选择一个无衬线字体。
+
en.ro.HelpFontConfig6:\Tcurrently selected serif font.|MNetSurf will use this font wherever a web page specifies a serif typeface.
de.ro.HelpFontConfig6:Das ist die aktuell gewählte Schriftart für Serif.|MNetSurf wird diese Schriftart überall dort verwenden, wo von der Webseite ein Schriftbild in Serif vorgegeben wird.
-fr.ro.HelpFontConfig6:\Tla fonte sérif actuellement sélectionnée.|MNetsurf utilisera cette fonte à chaque fois qu'une page web spécifiera une police sérif.
-it.ro.HelpFontConfig6:\Tcurrently selected serif font.|MNetSurf will use this font wherever a web page specifies a serif typeface.
+fr.ro.HelpFontConfig6:\Tla fonte sérif actuellement sélectionnée.|MNetsurf utilisera cette fonte à chaque fois qu’une page web spécifiera une police sérif.
+it.ro.HelpFontConfig6:\Tfont serif correntemente selezionato.|MNetSurf utilizzerà questo font ovunque una pagina Web specifichi un carattere tipografico di tipo serif.
nl.ro.HelpFontConfig6:Dit is momenteel het geselecteerde lettertype met schreef.|MNetSurf gebruikt dit lettertype wanneer een webpagina om deze tekststijl vraagt.
+zh_CN.ro.HelpFontConfig6:\T当å‰é€‰å®šçš„衬线字体。|M NetSurf 将在网页指定衬线字体的任何地方使用此字体。
+
en.ro.HelpFontConfig7:\Sselect a sans-serif font.
de.ro.HelpFontConfig7:Klicken mit AUSWAHL, um eine Schriftart auszuwählen.
fr.ro.HelpFontConfig7:\Ssélectionner une fonte sérif.
it.ro.HelpFontConfig7:\Sseleziona un font sans-serif
nl.ro.HelpFontConfig7:Klik met KIES om een lettertype met schreef te selecteren.
+zh_CN.ro.HelpFontConfig7:\S选择一个无衬线字体。
+
en.ro.HelpFontConfig9:\Tcurrently selected monospace font.|MNetSurf will use this font wherever a web page specifies a monospace typeface.
de.ro.HelpFontConfig9:Das ist die aktuell gewählte Schriftart für Monospace.|MNetSurf wird diese Schriftart überall dort verwenden, wo von der Webseite ein Schriftbild in Monospace vorgegeben wird.
-fr.ro.HelpFontConfig9:\Tla fonte sérif actuellement sélectionnée.|MNetsurf utilisera cette fonte à chaque fois qu'une page web spécifiera une police monospace.
-it.ro.HelpFontConfig9:\Tcurrently selected monospace font.|MNetSurf will use this font wherever a web page specifies a monospace typeface.
+fr.ro.HelpFontConfig9:\Tla fonte sérif actuellement sélectionnée.|MNetsurf utilisera cette fonte à chaque fois qu’une page web spécifiera une police monospace.
+it.ro.HelpFontConfig9:\Tfont monospaziato correntemente selezionato.|MNetSurf utilizzerà questo font ovunque una pagina Web specifichi un carattere tipografico di tipo monospaziato.
nl.ro.HelpFontConfig9:Dit is momenteel het geselecteerde monospace-lettertype.|MNetSurf gebruikt dit lettertype wanneer een webpagina om deze tekststijl vraagt.
+zh_CN.ro.HelpFontConfig9:\T当å‰é€‰å®šçš„等宽字体。|M NetSurf 将在网页指定等宽字体的任何地方使用此字体。
+
en.ro.HelpFontConfig10:\Sselect a monospace font.
de.ro.HelpFontConfig10:Klicken mit AUSWAHL, um eine Schriftart auszuwählen.
fr.ro.HelpFontConfig10:\Ssélectionner une fonte monospace.
it.ro.HelpFontConfig10:\Sseleziona un font monospaziato
nl.ro.HelpFontConfig10:Klik met KIES om een monospace-lettertype te selecteren.
+zh_CN.ro.HelpFontConfig10:\S选择一个等宽字体。
+
en.ro.HelpFontConfig12:\Tcurrently selected cursive font.|MNetSurf will use this font wherever a web page specifies a cursive typeface.
de.ro.HelpFontConfig12:Das ist die aktuell gewählte Schriftart für Kursiv.|MNetSurf wird diese Schriftart überall dort verwenden, wo von der Webseite ein Schriftbild in Kursiv vorgegeben wird.
-fr.ro.HelpFontConfig12:\Tla fonte cursive actuellement sélectionnée.|MNetsurf utilisera cette fonte à chaque fois qu'une page web spécifiera une police cursive.
-it.ro.HelpFontConfig12:\Tcurrently selected cursive font.|MNetSurf will use this font wherever a web page specifies a cursive typeface.
+fr.ro.HelpFontConfig12:\Tla fonte cursive actuellement sélectionnée.|MNetsurf utilisera cette fonte à chaque fois qu’une page web spécifiera une police cursive.
+it.ro.HelpFontConfig12:\Tfont corsivo correntemente selezionato.|MNetSurf utilizzerà questo font ovunque una pagina Web specifichi un carattere tipografico di tipo corsivo.
nl.ro.HelpFontConfig12:Dit is momenteel het geselecteerde cursieve lettertype.|MNetSurf gebruikt dit lettertype wanneer een webpagina om deze tekststijl vraagt.
+zh_CN.ro.HelpFontConfig12:\T当å‰é€‰å®šçš„手写字体。|M NetSurf 将在网页指定手写字体的任何地方使用此字体。
+
en.ro.HelpFontConfig13:\Sselect a cursive font.
de.ro.HelpFontConfig13:Klicken mit AUSWAHL, um eine Schriftart auszuwählen.
fr.ro.HelpFontConfig13:\Ssélectionner une fonte cursive.
it.ro.HelpFontConfig13:\Sseleziona un font corsivo
nl.ro.HelpFontConfig13:Klik met KIES om een cursieve lettertype te selecteren.
+zh_CN.ro.HelpFontConfig13:\S选择一个手写字体。
+
en.ro.HelpFontConfig15:\Tcurrently selected fantasy font.|MNetSurf will use this font wherever a web page specifies a fantasy typeface.
de.ro.HelpFontConfig15:Das ist die aktuell gewählte Schriftart für Fantasy.|MNetSurf wird diese Schriftart überall dort verwenden, wo von der Webseite ein Schriftbild in Fantasy vorgegeben wird.
-fr.ro.HelpFontConfig15:\Tla fonte fantaisie actuellement sélectionnée.|MNetsurf utilisera cette fonte à chaque fois qu'une page web spécifiera une police fantaisie.
-it.ro.HelpFontConfig15:\Tcurrently selected fantasy font.|MNetSurf will use this font wherever a web page specifies a fantasy typeface.
+fr.ro.HelpFontConfig15:\Tla fonte fantaisie actuellement sélectionnée.|MNetsurf utilisera cette fonte à chaque fois qu’une page web spécifiera une police fantaisie.
+it.ro.HelpFontConfig15:\Tfont fantasia correntemente selezionato.|MNetSurf utilizzerà questo font ovunque una pagina Web specifichi un carattere tipografico di tipo fantasia.
nl.ro.HelpFontConfig15:Dit is momenteel het geselecteerde fantasie-lettertype.|MNetSurf gebruikt dit lettertype wanneer een webpagina om deze tekststijl vraagt.
+zh_CN.ro.HelpFontConfig15:\T当å‰é€‰å®šçš„ Fantasy 字体。|M NetSurf 将在网页指定 Fantasy 字体的任何地方使用此字体。
+
en.ro.HelpFontConfig16:\Sselect a fantasy font.
de.ro.HelpFontConfig16:Klicken mit AUSWAHL, um eine Schriftart auszuwählen.
fr.ro.HelpFontConfig16:\Ssélectionner une fonte fantaisie.
it.ro.HelpFontConfig16:\Sseleziona un font fantasia
nl.ro.HelpFontConfig16:Klik met KIES om een fantasie-lettertype te selecteren.
+zh_CN.ro.HelpFontConfig16:\S选择一个 Fantasy 字体。
+
en.ro.HelpFontConfig18:\Tcurrently selected font family.|MNetSurf will use this wherever a web page does not specify a typeface.
de.ro.HelpFontConfig18:Das ist die aktuell gewählte Schriftart für die Standardtextanzeige.|MNetSurf wird diese Schriftart überall dort verwenden, wo von der Webseite KEIN bestimmtes Schriftbild vorgegeben wird.
-fr.ro.HelpFontConfig18:\Tla famille de fontes actuellement sélectionnée.|MNetsurf utilisera cette fonte à chaque fois qu'une page web ne spécifiera aucune police.
-it.ro.HelpFontConfig18:\Tcurrently selected font family.|MNetSurf will use this wherever a web page does not specify a typeface.
+fr.ro.HelpFontConfig18:\Tla famille de fontes actuellement sélectionnée.|MNetsurf utilisera cette fonte à chaque fois qu’une page web ne spécifiera aucune police.
+it.ro.HelpFontConfig18:\Tfamiglia font correntemente selezionata.|MNetSurf lo utilizzerà laddove una pagina Web non specifichi un carattere tipografico.
nl.ro.HelpFontConfig18:Dit is momenteel het geselecteerde lettertypesoort.|MNetSurf gebruikt dit lettertype als een webpagina geen lettertypesoort specificeerd.
+zh_CN.ro.HelpFontConfig18:\T当å‰é€‰å®šçš„字体家æ—。|M NetSurf 将在网页未指定字体的地方使用此字体。
+
en.ro.HelpFontConfig19:\Sselect a default font family.
de.ro.HelpFontConfig19:Klicken mit AUSWAHL, um eine Schriftart auszuwählen.
fr.ro.HelpFontConfig19:\Ssélectionner une famille de fontes par défaut.
it.ro.HelpFontConfig19:\Sseleziona una famiglia font predefinita
nl.ro.HelpFontConfig19:Klik met KIES om een standaardlettertypesoort te selecteren.
+zh_CN.ro.HelpFontConfig19:\S选择默认字体家æ—。
+
en.ro.HelpFontConfig23:You can enter a default font size here.|MNetSurf will use this wherever a web page does not specify a font size of its own.
de.ro.HelpFontConfig23:Hier kann eine Standarfontgröße gewählt werden.|MNetSurf wird diese Größe immer dann verwenden, wenn von der Webseite keine eigene Schriftgröße eingestellt wird.
-fr.ro.HelpFontConfig23:Vous pouvez entrer ici une taille par défaut.|MNetsurf l'utilisera chaque fois qu'une page web ne spécifiera pas de taille de fonte.
-it.ro.HelpFontConfig23:You can enter a default font size here.|MNetSurf will use this wherever a web page does not specify a font size of its own.
+fr.ro.HelpFontConfig23:Vous pouvez entrer ici une taille par défaut.|MNetsurf l’utilisera chaque fois qu’une page web ne spécifiera pas de taille de fonte.
+it.ro.HelpFontConfig23:Puoi inserire qui la dimensione predefinita del carattere.|MNetSurf lo utilizzerà laddove una pagina Web non specifichi una propria dimensione del carattere.
nl.ro.HelpFontConfig23:In dit veld kan een standaardlettergrootte ingevoerd worden.|MNetSurf gebruikt deze lettergrootte waar een webpagina niet van zichzelf de grootte specificeerd.
+zh_CN.ro.HelpFontConfig23:您å¯ä»¥åœ¨æ­¤è¾“入默认字体大å°ã€‚|MNetSurf 将在网页未指定自己的字体大å°æ—¶ä½¿ç”¨æ­¤å¤§å°ã€‚
+
en.ro.HelpFontConfig24:\Sreduce the default font size.
de.ro.HelpFontConfig24:Klicken mit AUSWAHL verkleinert die Standardfontgröße.
fr.ro.HelpFontConfig24:\Sréduire la taille de fonte.
-it.ro.HelpFontConfig24:\Sriduce la dimensione del font predefinito
+it.ro.HelpFontConfig24:\Sriduci la dimensione del font predefinito.
nl.ro.HelpFontConfig24:Klik met KIES om de standaardlettergrootte te verkleinen
+zh_CN.ro.HelpFontConfig24:\Så‡å°‘默认字体大å°ã€‚
+
en.ro.HelpFontConfig25:\Sincrease the default font size.
de.ro.HelpFontConfig25:Klicken mit AUSWAHL vergrößert die Standardfontgröße.
fr.ro.HelpFontConfig25:\Saugmenter la taille de fonte.
-it.ro.HelpFontConfig25:\Saumenta la dimensione del font predefinita
+it.ro.HelpFontConfig25:\Saumenta la dimensione del font predefinito.
nl.ro.HelpFontConfig25:Klik met KIES om de standaardlettergrootte te vergroten.
+zh_CN.ro.HelpFontConfig25:\Sæ高默认字体大å°ã€‚
+
en.ro.HelpFontConfig28:You can enter a minimum font size here.|MNetSurf will not allow web pages to display smaller text than this.
de.ro.HelpFontConfig28:Hier kann eine minimale Schriftgröße eingestellt werden.|MNetSurf wird keine Darstellung von noch kleineren Schriften zulassen.
-fr.ro.HelpFontConfig28:Vous pouvez entrer ici une taille de fonte minimum.|MNetsurf ne permettra pas aux pages web d'afficher un texte ayant une taille plus petite.
-it.ro.HelpFontConfig28:You can enter a minimum font size here.|MNetSurf will not allow web pages to display smaller text than this.
+fr.ro.HelpFontConfig28:Vous pouvez entrer ici une taille de fonte minimum.|MNetsurf ne permettra pas aux pages web d’afficher un texte ayant une taille plus petite.
+it.ro.HelpFontConfig28:Puoi inserire qui la dimensione minima del carattere.|MNetSurf non consentirà alle pagine Web di visualizzare un testo più piccolo di questo.
nl.ro.HelpFontConfig28:In dit veld kan een minimum lettertypegrootte ingevoerd worden.|MNetSurf staat webpagina's dan niet toe om kleinere lettertypes te tonen.
+zh_CN.ro.HelpFontConfig28:您å¯ä»¥åœ¨æ­¤å¤„输入最å°å­—体大å°ã€‚|MNetSurf ä¸å…许网页显示å°äºŽæ­¤å¤§å°çš„文本。
+
en.ro.HelpFontConfig29:\Sreduce the minimum font size.
de.ro.HelpFontConfig29:Klicken mit AUSWAHL verkleinert die minimal zugelassene Schriftgröße.
fr.ro.HelpFontConfig29:\Sréduire la taille de fonte minimum.
-it.ro.HelpFontConfig29:\Sriduce la dimensione minima del font
+it.ro.HelpFontConfig29:\Sriduci la dimensione minima del font.
nl.ro.HelpFontConfig29:Klik met KIES om de minimum lettergrootte te verkleinen.
+zh_CN.ro.HelpFontConfig29:\Sé™ä½Žå­—体下é™ã€‚
+
en.ro.HelpFontConfig30:\Sincrease the minimum font size.
de.ro.HelpFontConfig30:Klicken mit AUSWAHL vergrößert die minimal zugelassene Schriftgröße.
fr.ro.HelpFontConfig30:\Saugmenter la taille de fonte minimum.
-it.ro.HelpFontConfig30:\Saumenta la dimensione minima del font
+it.ro.HelpFontConfig30:\Saumenta la dimensione minima del font.
nl.ro.HelpFontConfig30:Klik met KIES om de minimum lettergrootte te vergroten.
+zh_CN.ro.HelpFontConfig30:\Sæ高字体下é™ã€‚
+
en.ro.HelpFontConfig32:\Sreset the Font options back to their default values.
de.ro.HelpFontConfig32:Stellt die Standardeinstellungen wieder her.
fr.ro.HelpFontConfig32:\Srevenir aux valeurs par défaut des options de Fontes.
-it.ro.HelpFontConfig32:\Sripristina le impostazioni dei font ai loro valori originali
+it.ro.HelpFontConfig32:\Sresetta le impostazioni dei font ai valori predefiniti.
nl.ro.HelpFontConfig32:Klik met KIES om de lettertype-instellingen in dit venster terug te zetten op de standaardwaarden.
+zh_CN.ro.HelpFontConfig32:\S将字体选项é‡ç½®ä¸ºå…¶é»˜è®¤å€¼ã€‚
+
en.ro.HelpFontConfig33:\Sclose this \w without saving changes.|M\Areturn the font options to the last saved configuration.
de.ro.HelpFontConfig33:Klicken mit AUSWAHL schließt das Fenster ohne die Änderungen zu speichern.|MKlicken mit SPEZIAL stellt die zuletzt abgespeicherten Einstellungen wieder her.
fr.ro.HelpFontConfig33:\Sfermer cette fenêtre sans sauver les changements|M\Arevenir aux options de Fontes précédemment sauvegardées.
-it.ro.HelpFontConfig33:\Sclose this \w without saving changes.|M\Areturn the font options to the last saved configuration.
+it.ro.HelpFontConfig33:\Schiudi questa finestra senza salvare le modifiche.|M\Aripristina le opzioni dei font all'ultima configurazione salvata.
nl.ro.HelpFontConfig33:Klik met KIES om dit venster te sluiten zonder dat de gemaakte wijzigingen worden bewaard.|MKlik met PASAAN om de gemaakte wijzigingen ongedaan te maken; het venster wordt hierbij niet gesloten.
+zh_CN.ro.HelpFontConfig33:\S关闭此 \w 而ä¸ä¿å­˜æ›´æ”¹ã€‚|M\A将字体选项æ¢å¤åˆ°ä¸Šæ¬¡ä¿å­˜çš„é…置。
+
en.ro.HelpFontConfig34:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
de.ro.HelpFontConfig34:Klicken mit AUSWAHL speichert die Einstellungen und schließt das Fenster.|MKlicken mit SPEZIAL speichert die Einstellungen ohne das Fenster zu schließen.
fr.ro.HelpFontConfig34:\Ssauver ces réglages et fermer la fenêtre.|M\Asauver ces réglages sans fermer la fenêtre.
-it.ro.HelpFontConfig34:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
+it.ro.HelpFontConfig34:\Ssalva queste impostazioni e chiudi la finestra.|M\Asalva queste impostazioni senza chiudere la finestra.
nl.ro.HelpFontConfig34:Klik met KIES om de gemaakte wijzigingen te bewaren en dit venster te sluiten.|MKlikken met PASAAN heeft hetzelfde effect, alleen wordt het huidige venster dan niet gesloten.
+zh_CN.ro.HelpFontConfig34:\Sä¿å­˜è¿™äº›è®¾ç½®å¹¶å…³é—­ \w。|M\A在ä¸å…³é—­ \w 的情况下ä¿å­˜è¿™äº›è®¾ç½®ã€‚
en.ro.HelpHomeConfig:\Thome page configuration \w
de.ro.HelpHomeConfig:Homepage Konfiguration
-fr.ro.HelpHomeConfig:\Tla fenêtre de configuration de Page d'accueil
+fr.ro.HelpHomeConfig:\Tla fenêtre de configuration de Page d’accueil
it.ro.HelpHomeConfig:\Tconfigurazione della pagina iniziale \w
nl.ro.HelpHomeConfig:De begin/startpagina kan in dit venster gewijzigd worden.
+zh_CN.ro.HelpHomeConfig:\T主页é…ç½® \w
+
en.ro.HelpHomeConfig3:You can enter a default home page address here.
de.ro.HelpHomeConfig3:Hier kann die Webadresse der Homepage eingegeben werden.
-fr.ro.HelpHomeConfig3:Vous pouvez entrer ici une page d'accueil par défaut.
-it.ro.HelpHomeConfig3:Puoi inserire l'indirizzo della pagina iniziale qui.
+fr.ro.HelpHomeConfig3:Vous pouvez entrer ici une page d’accueil par défaut.
+it.ro.HelpHomeConfig3:Puoi inserire qui l'indirizzo della pagina iniziale.
nl.ro.HelpHomeConfig3:Voer hier een standaard begin-/startpagina-adres in.
+zh_CN.ro.HelpHomeConfig3:您å¯ä»¥åœ¨æ­¤å¤„输入默认主页网å€ã€‚
+
en.ro.HelpHomeConfig4:\Sselect a recently typed URL.|MThese addresses have recently been typed into a NetSurf browser \w's URL bar.
de.ro.HelpHomeConfig4:Klicken mit AUSWAHL zur schnellen Auswahl einer Adresse.|MDie angezeigten Adressen wurden in letzter Zeit in die Adressleiste eines Browserfensters eingegeben.
-fr.ro.HelpHomeConfig4:\Ssélectionner une URL récemment tapée.|MCes adresses ont été récemment tapées dans la barre d'URL du navigateur Netsurf.
-it.ro.HelpHomeConfig4:\Sselect a recently typed URL.|MThese addresses have recently been typed into a NetSurf browser \w's URL bar.
+fr.ro.HelpHomeConfig4:\Ssélectionner une URL récemment tapée.|MCes adresses ont été récemment tapées dans la barre d’URL du navigateur Netsurf.
+it.ro.HelpHomeConfig4:\Sseleziona un URL digitato di recente.|MQuesti indirizzi sono stati digitati recentemente nella barra indirizzi del browser NetSurf.
nl.ro.HelpHomeConfig4:Klik met KIES om een recent bezochte pagina te selecteren als startpagina.
+zh_CN.ro.HelpHomeConfig4:\S选择最近键入的地å€ã€‚|M这些地å€æœ€è¿‘已键入 NetSurf æµè§ˆå™¨ \w 的地å€æ ã€‚
+
en.ro.HelpHomeConfig5:This indicates whether NetSurf will open a browser \w on start-up.
de.ro.HelpHomeConfig5:Stellt ein, ob NetSurf beim Starten automatisch ein Browserfenster öffnet.
fr.ro.HelpHomeConfig5:Ceci indique si Netsurf doit ouvrir une fenêtre de navigation au démarrage.
-it.ro.HelpHomeConfig5:This indicates whether NetSurf will open a browser \w on start-up.
+it.ro.HelpHomeConfig5:Indica se NetSurf aprirà una finestra del browser all'avvio.
nl.ro.HelpHomeConfig5:Deze optie geeft aan of NetSurf automatisch een browservenster opent nadat het programma is opgestart.
+zh_CN.ro.HelpHomeConfig5:这表示 NetSurf 是å¦åœ¨å¯åŠ¨æ—¶æ‰“å¼€æµè§ˆå™¨ \w。
+
en.ro.HelpHomeConfig6:\Sreset the Home page options back to their default values.
de.ro.HelpHomeConfig6:Stellt die Standardeinstellungen wieder her.
-fr.ro.HelpHomeConfig6:\Srevenir aux valeurs par défaut des options de Page d'accueil.
-it.ro.HelpHomeConfig6:\Sreset the Home page options back to their default values.
+fr.ro.HelpHomeConfig6:\Srevenir aux valeurs par défaut des options de Page d’accueil.
+it.ro.HelpHomeConfig6:\Sresetta le opzioni della pagina iniziale ai valori predefiniti.
nl.ro.HelpHomeConfig6:Klik met KIES om de startpagina-instellingen in dit venster terug te zetten op de standaardwaarden.
+zh_CN.ro.HelpHomeConfig6:\S将主页选项é‡ç½®ä¸ºé»˜è®¤å€¼ã€‚
+
en.ro.HelpHomeConfig7:\Sclose this \w without saving changes.|M\Areturn the home options to the last saved configuration.
de.ro.HelpHomeConfig7:Klicken mit AUSWAHL schließt das Fenster ohne die Änderungen zu speichern.|MKlicken mit SPEZIAL stellt die zuletzt abgespeicherten Einstellungen wieder her.
-fr.ro.HelpHomeConfig7:\Sfermer cette fenêtre sans sauver les changements|M\Arevenir aux options de Page d'accueil précédemment sauvegardées.
-it.ro.HelpHomeConfig7:\Sclose this \w without saving changes.|M\Areturn the home options to the last saved configuration.
+fr.ro.HelpHomeConfig7:\Sfermer cette fenêtre sans sauver les changements|M\Arevenir aux options de Page d’accueil précédemment sauvegardées.
+it.ro.HelpHomeConfig7:\Schiudi questa finestra senza salvare le modifiche.|M\Aripristina le opzioni della home all'ultima configurazione salvata.
nl.ro.HelpHomeConfig7:Klik met KIES om dit venster te sluiten zonder dat de gemaakte wijzigingen worden bewaard.|MKlik met PASAAN om de gemaakte wijzigingen ongedaan te maken; het venster wordt hierbij niet gesloten.
+zh_CN.ro.HelpHomeConfig7:\S关闭此 \w 而ä¸ä¿å­˜æ›´æ”¹ã€‚|M\A将主页选项æ¢å¤åˆ°ä¸Šæ¬¡ä¿å­˜çš„é…置。
+
en.ro.HelpHomeConfig8:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
de.ro.HelpHomeConfig8:Klicken mit AUSWAHL speichert die Einstellungen und schließt das Fenster.|MKlicken mit SPEZIAL speichert die Einstellungen ohne das Fenster zu schließen.
fr.ro.HelpHomeConfig8:\Ssauver ces réglages et fermer la fenêtre.|M\Asauver ces réglages sans fermer la fenêtre.
-it.ro.HelpHomeConfig8:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
+it.ro.HelpHomeConfig8:\Ssalva queste impostazioni e chiudi la finestra.|M\Asalva queste impostazioni senza chiudere la finestra.
nl.ro.HelpHomeConfig8:Klik met KIES om de gemaakte wijzigingen te bewaren en dit venster te sluiten.|MKlikken met PASAAN heeft hetzelfde effect, alleen wordt het huidige venster dan niet gesloten.
+zh_CN.ro.HelpHomeConfig8:\Sä¿å­˜è¿™äº›è®¾ç½®å¹¶å…³é—­ \w。|M\A在ä¸å…³é—­ \w 的情况下ä¿å­˜è¿™äº›è®¾ç½®ã€‚
en.ro.HelpImageConfig:\Timage configuration \w
de.ro.HelpImageConfig:Das ist das Fenster zur Konfiguration der Bilddarstellungsoptionen.
-fr.ro.HelpImageConfig:\Tla fenêtre de configuration d'Image
+fr.ro.HelpImageConfig:\Tla fenêtre de configuration d’Image
it.ro.HelpImageConfig:\Tconfigurazione della immagini \w
nl.ro.HelpImageConfig:De verwerking van afbeeldingen kan in dit venster gewijzigd worden.
+zh_CN.ro.HelpImageConfig:\T图åƒé…ç½® \w
+
en.ro.HelpImageConfig3:\Tcurrently selected foreground image quality.
de.ro.HelpImageConfig3:Das ist die aktuell gewählte Qualität für die Darstellung der Vordergrundbilder.
-fr.ro.HelpImageConfig3:\Tla qualité d'image de premier plan sélectionnée actuellement.
-it.ro.HelpImageConfig3:\Tcurrently selected foreground image quality.
+fr.ro.HelpImageConfig3:\Tla qualité d’image de premier plan sélectionnée actuellement.
+it.ro.HelpImageConfig3:\Tqualità dell'immagine in primo piano correntemente selezionata.
nl.ro.HelpImageConfig3:Dit is momenteel de geselecteerde voorgrondafbeeldingskwaliteit.
+zh_CN.ro.HelpImageConfig3:\T当å‰é€‰æ‹©çš„å‰æ™¯å›¾åƒè´¨é‡ã€‚
+
en.ro.HelpImageConfig4:\Sselect a foreground image quality setting.|MError diffused provides the highest quality.
de.ro.HelpImageConfig4:Klicken mit AUSWAHL zur Wahl der Anzeigequalität für Vordergrundbilder.|MError-Diffusion bietet die beste Qualität.
-fr.ro.HelpImageConfig4:\Schoisir un réglage de qualité pour les images de premier plan.|MAvec diffusion d'erreur correspond à la meilleure qualité.
-it.ro.HelpImageConfig4:\Sselect a foreground image quality setting.|MError diffused provides the highest quality.
+fr.ro.HelpImageConfig4:\Schoisir un réglage de qualité pour les images de premier plan.|MAvec diffusion d’erreur correspond à la meilleure qualité.
+it.ro.HelpImageConfig4:\Sseleziona una impostazione per la qualità dell'immagine in primo piano.|ML'errore diffuso fornisce la qualità migliore.
nl.ro.HelpImageConfig4:Klik met KIES om een bepaalde voorgrondafbeeldingskwaliteit te selecteren.|MFoutdiffusie biedt de hoogstmogelijke kwaliteit.
+zh_CN.ro.HelpImageConfig4:\S选择å‰æ™¯å›¾åƒè´¨é‡è®¾ç½®ã€‚|M误差扩散方法å¯æ供最高质é‡ã€‚
+
en.ro.HelpImageConfig6:\Tcurrently selected background image quality.
de.ro.HelpImageConfig6:Das ist die aktuell gewählte Qualität für die Darstellung der Hintergrundbilder.
-fr.ro.HelpImageConfig6:\Tla qualité d'image de fond sélectionnée actuellement.
-it.ro.HelpImageConfig6:\Tcurrently selected background image quality.
+fr.ro.HelpImageConfig6:\Tla qualité d’image de fond sélectionnée actuellement.
+it.ro.HelpImageConfig6:\Tqualità dell'immagine di sfondo correntemente selezionata.
nl.ro.HelpImageConfig6:Dit is momenteel de geselecteerde achtergrondafbeeldingskwaliteit.
+zh_CN.ro.HelpImageConfig6:\T当å‰é€‰æ‹©çš„背景图åƒè´¨é‡ã€‚
+
en.ro.HelpImageConfig7:\Sselect a background image quality setting.|MError diffused provides the highest quality.
de.ro.HelpImageConfig7:Klicken mit AUSWAHL zur Wahl der Anzeigequalität für Hintergrundbilder.|MError-Diffusion bietet die beste Qualität.
-fr.ro.HelpImageConfig7:\Schoisir un réglage de qualité pour les images de fond.|MAvec diffusion d'erreur correspond à la meilleure qualité.
-it.ro.HelpImageConfig7:\Sselect a background image quality setting.|MError diffused provides the highest quality.
+fr.ro.HelpImageConfig7:\Schoisir un réglage de qualité pour les images de fond.|MAvec diffusion d’erreur correspond à la meilleure qualité.
+it.ro.HelpImageConfig7:\Sseleziona una impostazione per la qualità dell'immagine di sfondo.|ML'errore diffuso fornisce la qualità migliore.
nl.ro.HelpImageConfig7:Klik met KIES om een bepaalde achtergrondafbeeldingskwaliteit te selecteren.|MFoutdiffusie biedt de hoogstmogelijke kwaliteit.
+zh_CN.ro.HelpImageConfig7:\S选择背景图åƒè´¨é‡è®¾ç½®ã€‚|M误差扩散方法å¯æ供最高质é‡ã€‚
+
en.ro.HelpImageConfig8:\Timage quality preview image.|MThe optimum results are achived with both foreground and background image quality set to error diffused.|MThe user guide provides more information on the implications of these options.
de.ro.HelpImageConfig8:Das ist das Vorschaubild.|MDie qualitativ besten Anzeigeresultate werden erzielt, wenn Vorder- und Hintergrundbilder per Error-Diffusion dargestellt werden.|MGenauere Informationen gibt es in der Dokumentation.
-fr.ro.HelpImageConfig8:\Timage de prévisualisation de qualité d'image.|MLes résultats optimaux sont obtenus avec des images de premier plan et de fond avec diffusion d'erreur.|MLe guide utilisateur fournit plus d'informations quant aux implications de cette option.
-it.ro.HelpImageConfig8:\Timage quality preview image.|MThe optimum results are achived with both foreground and background image quality set to error diffused.|MThe user guide provides more information on the implications of these options.
+fr.ro.HelpImageConfig8:\Timage de prévisualisation de qualité d’image.|MLes résultats optimaux sont obtenus avec des images de premier plan et de fond avec diffusion d’erreur.|MLe guide utilisateur fournit plus d’informations quant aux implications de cette option.
+it.ro.HelpImageConfig8:\TQualità immagine di anteprima.|MI risultati ottimali vengono raggiunti impostando la qualità dell'immagine in primo piano e di sfondo su errore diffuso.|MLa guida in linea fornisce ulteriori informazioni sulle implicazioni di queste opzioni.
nl.ro.HelpImageConfig8:Dit is een kwaliteitsvoorbeeldafbeelding.|MSelecteer foutdiffusie voor zowel voorgrond- als achtergrond voor de beste kwaliteit.|MDe gebruikershandleiding geeft meer informatie over de implicaties van deze mogelijkheden.
+zh_CN.ro.HelpImageConfig8:\T图åƒè´¨é‡é¢„览图åƒã€‚|M在å‰æ™¯å’ŒèƒŒæ™¯å›¾åƒè´¨é‡å‡è®¾ç½®ä¸ºè¯¯å·®æ‰©æ•£çš„情况下å¯èŽ·å¾—最佳效果。|M用户指å—æ供了有关这些选项å«ä¹‰çš„详细信æ¯ã€‚
+
en.ro.HelpImageConfig12:You can enter the minimum time between animation frames here.|MA very low setting can cause your computer to slow down when rapid animations are displayed and is not suitable for slow computers.
de.ro.HelpImageConfig12:Hier kann die minimale Zeitverzögerung zwischen den Frames einer Animation vorgegeben werden.|MSehr niedrige Werte können bei raschen Animationen hohe Rechenleistungen erfordern und sind darum nicht geeignet für langsamere Computer.
-fr.ro.HelpImageConfig12:Vous pouvez entrer ici le temps minimum entre deux images d'animation.|MUn réglage trop bas peut ralentir les animations affichées et ne convient pas à des ordinateurs lents.
-it.ro.HelpImageConfig12:You can enter the minimum time between animation frames here.|MA very low setting can cause your computer to slow down when rapid animations are displayed and is not suitable for slow computers.
+fr.ro.HelpImageConfig12:Vous pouvez entrer ici le temps minimum entre deux images d’animation.|MUn réglage trop bas peut ralentir les animations affichées et ne convient pas à des ordinateurs lents.
+it.ro.HelpImageConfig12:Puoi inserire qui il tempo minimo tra i frame di animazione.|MUn'impostazione molto bassa potrebbe rallentare il computer qualora vengano visualizzate animazioni rapide, potrebbe quindi non essere adatta su computer lenti.
nl.ro.HelpImageConfig12:In dit veld kan de minimumtijd ingevoerd worden tussen de opeenvolgende animatiebeelden.|MEen lage waarde kan er toe leiden dat het systeem traag wordt bij het tonen van snelle animaties en is niet geschikt voor langzame systemen.
+zh_CN.ro.HelpImageConfig12:您å¯ä»¥åœ¨æ­¤å¤„输入画帧之间的最短时间。|M一个éžå¸¸ä½Žçš„设置会导致您的计算机在显示快速动画时速度å˜æ…¢ï¼Œä¸é€‚åˆé€Ÿåº¦è¾ƒæ…¢çš„计算机。
+
en.ro.HelpImageConfig13:\Sreduce the minimum time between animation frames.
de.ro.HelpImageConfig13:Klicken mit AUSWAHL verkleinert die minimale Wartezeit zwischen aufeinanderfolgenden Einzelbildern einer Animation.
-fr.ro.HelpImageConfig13:\Sréduire le temps minimum entre deux images d'animation.
-it.ro.HelpImageConfig13:\Sriduce il tempo di intervallo minimo tra i frame di animazione.
+fr.ro.HelpImageConfig13:\Sréduire le temps minimum entre deux images d’animation.
+it.ro.HelpImageConfig13:\Sriduci il tempo di intervallo minimo tra i frame di animazione.
nl.ro.HelpImageConfig13:Klik met KIES om de minimumtijd tussen animatie-afbeeldingen te verkleinen.
+zh_CN.ro.HelpImageConfig13:\Så‡å°‘画帧之间的最短时间。
+
en.ro.HelpImageConfig14:\Sincrease the minimum time between animation frames.
de.ro.HelpImageConfig14:Klicken mit AUSWAHL vergrößert die minimale Wartezeit zwischen aufeinanderfolgenden Einzelbildern einer Animation.
-fr.ro.HelpImageConfig14:\Saugmenter le temps minimum entre deux images d'animation.
+fr.ro.HelpImageConfig14:\Saugmenter le temps minimum entre deux images d’animation.
it.ro.HelpImageConfig14:\Saumenta il tempo di intervallo minimo tra i frame di animazione.
nl.ro.HelpImageConfig14:Klik met KIES om de minimumtijd tussen animatie-afbeeldingen te vergroten.
+zh_CN.ro.HelpImageConfig14:\S增加画帧之间的最短时间。
+
en.ro.HelpImageConfig16:This indicates whether NetSurf will disable animations on web pages.|MWhen animations are disabled, NetSurf will show the first frame as a static image.
de.ro.HelpImageConfig16:Erlaubt das Abschalten der Animationsdarstellung auf Webseiten.|MSind die Animationen abgeschaltet, wird von NetSurf lediglich das erste Einzelbild der Animationsfolge als einfaches Bild angezeigt.
fr.ro.HelpImageConfig16:Ceci indique si Netsurf doit annuler les animations des pages web.|MLorsque les animations sont désactivées, Netsurf utilisera la première image comme image statique.
-it.ro.HelpImageConfig16:This indicates whether NetSurf will disable animations on web pages.|MWhen animations are disabled, NetSurf will show the first frame as a static image.
+it.ro.HelpImageConfig16:Indica se NetSurf disabiliterà le animazioni sulle pagine Web.|MQuando le animazioni sono disabilitate NetSurf mostrerà il primo fotogramma come immagine statica.
nl.ro.HelpImageConfig16:Deze optie geeft aan of animaties getoond worden.|MWanneer animaties niet worden getoond, dan wordt de eerste beeld van de animatie als een statische afbeelding getoond.
+zh_CN.ro.HelpImageConfig16:这表示 NetSurf 是å¦ç¦ç”¨ç½‘页上的动画。|Mç¦ç”¨åŠ¨ç”»æ—¶ï¼ŒNetSurf 会将第一帧动画显示为é™æ€å›¾åƒã€‚
+
en.ro.HelpImageConfig17:\Sreset the Image options back to their default values.
de.ro.HelpImageConfig17:Stellt die Bildoptionen zurück auf die Standardwerte.
-fr.ro.HelpImageConfig17:\Srevenir aux valeurs par défaut des options d'Image.
-it.ro.HelpImageConfig17:\Sreset the Image options back to their default values.
+fr.ro.HelpImageConfig17:\Srevenir aux valeurs par défaut des options d’Image.
+it.ro.HelpImageConfig17:\Sresetta le opzioni della immagini ai valori predefiniti.
nl.ro.HelpImageConfig17:Klik met KIES om de instellingen in dit venster terug te zetten op de standaardwaarden.
+zh_CN.ro.HelpImageConfig17:\S将图åƒé€‰é¡¹é‡ç½®ä¸ºé»˜è®¤å€¼ã€‚
+
en.ro.HelpImageConfig18:\Sclose this \w without saving changes.|M\Areturn the image options to the last saved configuration.
de.ro.HelpImageConfig18:Klicken mit AUSWAHL schließt das Fenster ohne die Änderungen zu speichern.|MKlicken mit SPEZIAL stellt die zuletzt abgespeicherten Einstellungen wieder her.
-fr.ro.HelpImageConfig18:\Sfermer cette fenêtre sans sauver les changements|M\Arevenir aux options d'Image précédemment sauvegardées.
-it.ro.HelpImageConfig18:\Sclose this \w without saving changes.|M\Areturn the image options to the last saved configuration.
+fr.ro.HelpImageConfig18:\Sfermer cette fenêtre sans sauver les changements|M\Arevenir aux options d’Image précédemment sauvegardées.
+it.ro.HelpImageConfig18:\Schiudi questa finestra senza salvare le modifiche.|M\Aripristina le opzioni delle immagini all'ultima configurazione salvata.
nl.ro.HelpImageConfig18:Klik met KIES om dit venster te sluiten zonder dat de gemaakte wijzigingen worden bewaard.|MKlik met PASAAN om de gemaakte wijzigingen ongedaan te maken; het venster wordt hierbij niet gesloten.
+zh_CN.ro.HelpImageConfig18:\S关闭此 \w 而ä¸ä¿å­˜æ›´æ”¹ã€‚|M\A将图åƒé€‰é¡¹æ¢å¤åˆ°ä¸Šæ¬¡ä¿å­˜çš„é…置。
+
en.ro.HelpImageConfig19:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
de.ro.HelpImageConfig19:Klicken mit AUSWAHL speichert die Einstellungen und schließt das Fenster.|MKlicken mit SPEZIAL speichert die Einstellungen ohne das Fenster zu schließen.
fr.ro.HelpImageConfig19:\Ssauver ces réglages et fermer la fenêtre.|M\Asauver ces réglages sans fermer la fenêtre.
-it.ro.HelpImageConfig19:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
+it.ro.HelpImageConfig19:\Ssalva queste impostazioni e chiudi la finestra.|M\Asalva queste impostazioni senza chiudere la finestra.
nl.ro.HelpImageConfig19:Klik met KIES om de gemaakte wijzigingen te bewaren en dit venster te sluiten.|MKlikken met PASAAN heeft hetzelfde effect, alleen wordt het huidige venster dan niet gesloten.
+zh_CN.ro.HelpImageConfig19:\Sä¿å­˜è¿™äº›è®¾ç½®å¹¶å…³é—­ \w。|M\A在ä¸å…³é—­ \w 的情况下ä¿å­˜è¿™äº›è®¾ç½®ã€‚
en.ro.HelpInterfaceConfig:\Tinterface configuration \w
de.ro.HelpInterfaceConfig:Fenster zur Einstellung des Programmverhaltens in ausgewählten Situationen
-fr.ro.HelpInterfaceConfig:\Tla fenêtre de configuration d'interface
+fr.ro.HelpInterfaceConfig:\Tla fenêtre de configuration d’interface
it.ro.HelpInterfaceConfig:\Tconfigurazione dell'interfaccia \w
nl.ro.HelpInterfaceConfig:De interface-instellingen kunnen in dit venster gewijzigd worden.
+zh_CN.ro.HelpInterfaceConfig:\Tç•Œé¢é…ç½® \w
+
en.ro.HelpInterfaceConfig2:This indicates whether NetSurf will strip file extensions when saving files to disc.
de.ro.HelpInterfaceConfig2:Beim Abspeichern von Dateien auf einen Datenträger werden die Dateinamenserweiterungen (Extensions) aus dem Dateinamen entfernt.
-fr.ro.HelpInterfaceConfig2:Ceci indique si Netsurf supprime les extensions de fichiers lors d'une sauvegarde sur disque.
-it.ro.HelpInterfaceConfig2:This indicates whether NetSurf will strip file extensions when saving files to disc.
+fr.ro.HelpInterfaceConfig2:Ceci indique si Netsurf supprime les extensions de fichiers lors d’une sauvegarde sur disque.
+it.ro.HelpInterfaceConfig2:Indica se NetSurf rimuoverà le estensioni dei file durante il salvataggio dei file su disco.
nl.ro.HelpInterfaceConfig2:Deze optie geeft aan of bestandsextensies verwijderd zullen worden bij het bewaren.
+zh_CN.ro.HelpInterfaceConfig2:这表示 NetSurf 是å¦åœ¨å°†æ–‡ä»¶ä¿å­˜åˆ°ç£ç›˜æ—¶çœåŽ»æ–‡ä»¶æ‰©å±•å。
+
en.ro.HelpInterfaceConfig3:This indicates whether NetSurf will ask for confirmation before overwriting files of the same name.
de.ro.HelpInterfaceConfig3:Beim Abspeichern wird vor dem Ãœberschreiben namensgleicher Dateien von NetSurf nachgefragt, ob dies so erfolgen soll.
-fr.ro.HelpInterfaceConfig3:Ceci indique si Netsurf doit demander confirmation avant d'écraser des fichiers portant le même nom.
-it.ro.HelpInterfaceConfig3:This indicates whether NetSurf will ask for confirmation before overwriting files of the same name.
+fr.ro.HelpInterfaceConfig3:Ceci indique si Netsurf doit demander confirmation avant d’écraser des fichiers portant le même nom.
+it.ro.HelpInterfaceConfig3:Indica se NetSurf chiederà conferma prima di sovrascrivere i file con lo stesso nome.
nl.ro.HelpInterfaceConfig3:Deze optie geeft aan of er toestemming wordt gevraagd voor het overschrijven van bestanden met dezelfde naam.
+zh_CN.ro.HelpInterfaceConfig3:这表示 NetSurf 是å¦åœ¨è¦†ç›–åŒå文件之å‰éœ€è¦ç¡®è®¤ã€‚
+
en.ro.HelpInterfaceConfig6:This indicates whether NetSurf's URL suggestion feature is enabled.|MURL suggestion shows options for completing URLs as you type into NetSurf's URL bar.
de.ro.HelpInterfaceConfig6:Fantastisches Feature zum automatischen Vorschlagen von URL Adressen bei deren Eingabe.|MDiese Funktion zeigt bei der Eingabe von Webadressen in die Adressleiste mögliche sinnvolle Adressvorschläge während des Eintippens an.
-fr.ro.HelpInterfaceConfig6:Ceci indique si la fontion de suggestion d'URL de Netsurf est activée.|MLa suggestion d'URL montre les possibilités de complétion d'URL au fur et à mesure où elles sont tapées dans la barre.
-it.ro.HelpInterfaceConfig6:This indicates whether NetSurf's URL suggestion feature is enabled.|MURL suggestion shows options for completing URLs as you type into NetSurf's URL bar.
+fr.ro.HelpInterfaceConfig6:Ceci indique si la fontion de suggestion d’URL de Netsurf est activée.|MLa suggestion d’URL montre les possibilités de complétion d’URL au fur et à mesure où elles sont tapées dans la barre.
+it.ro.HelpInterfaceConfig6:Indica se la funzione di suggerimento URL di NetSurf sarà abilitata.|MIl suggerimento URL mostra le opzioni per il completamento degli URL durante la digitazione nella barra indirizzi di NetSurf.
nl.ro.HelpInterfaceConfig6:Deze optie geeft aan of het geven van adressuggesties is ingesteld.|MAdressuggestie geeft tijdens het typen van een adres een suggestie van het complete webadres.
+zh_CN.ro.HelpInterfaceConfig6:这表示是å¦å¯ç”¨ NetSurf 的地å€å»ºè®®åŠŸèƒ½ã€‚|M当您在 NetSurf 的地å€æ ä¸­é”®å…¥æ—¶ï¼Œåœ°å€å»ºè®®ä¼šæ˜¾ç¤ºç”¨äºŽå¡«å†™åœ°å€çš„选项。
+
en.ro.HelpInterfaceConfig7:This indicates whether the URL for the item under the pointer in NetSurf's local history \w will be displayed.
de.ro.HelpInterfaceConfig7:In der lokalen History werden die Adressen der besuchten Webseiten schwebend über den zugehörigen Bildern eingeblendet.
-fr.ro.HelpInterfaceConfig7:Ceci indique si l'URL de l'item sous le pointeur dans la fenêtre d'historique local doit être affiché.
-it.ro.HelpInterfaceConfig7:This indicates whether the URL for the item under the pointer in NetSurf's local history \w will be displayed.
+fr.ro.HelpInterfaceConfig7:Ceci indique si l’URL de l’item sous le pointeur dans la fenêtre d’historique local doit être affiché.
+it.ro.HelpInterfaceConfig7:Indica se verrà visualizzato l'URL dell'elemento sotto il puntatore del mouse nella finestra della cronologia locale di NetSurf.
nl.ro.HelpInterfaceConfig7:Deze optie geeft aan of het adres van een item onder de muisaanwijzer in de venstergeschiedenis zal worden getoond.
+zh_CN.ro.HelpInterfaceConfig7:这表示是å¦åœ¨ NetSurf æœ¬åœ°åŽ†å² \w 中显示鼠标指针下的项地å€ã€‚
+
en.ro.HelpInterfaceConfig10:This indicates whether NetSurf will use a thumbnail when iconising windows to the Pinboard.
de.ro.HelpInterfaceConfig10:Beim verkleinernden Ablegen eines Browserfensters auf dem Desktophintergrund (Iconisieren) wird von NetSurf ein fensterspezifisches Icon erzeugt, welches den aktuellen Seiteninhalt wiedergibt.
-fr.ro.HelpInterfaceConfig10:Ceci indique si Netsurf doit utiliser une miniature lors de l'iconisation vers le Punaiseur (Pinboard).
-it.ro.HelpInterfaceConfig10:This indicates whether NetSurf will use a thumbnail when iconising windows to the Pinboard.
+fr.ro.HelpInterfaceConfig10:Ceci indique si Netsurf doit utiliser une miniature lors de l’iconisation vers le Punaiseur (Pinboard).
+it.ro.HelpInterfaceConfig10:Indica se NetSurf utilizzerà una miniatura quando si iconificano le finestre nella Pinboard.
nl.ro.HelpInterfaceConfig10:Deze optie geeft aan of er een miniatuur van de pagina wordt getoond bij het symboliseren van vensters naar het prikbord.
+zh_CN.ro.HelpInterfaceConfig10:这表示 NetSurf 是å¦åœ¨å°†çª—å£å›¾æ ‡åŒ–到æ’接æ¿æ—¶ä½¿ç”¨ç¼©ç•¥å›¾ã€‚
+
en.ro.HelpInterfaceConfig11:\Sreset the Interface options back to their default values.
de.ro.HelpInterfaceConfig11:Stellt die Standardeinstellungen wieder her.
-fr.ro.HelpInterfaceConfig11:\Srevenir aux valeurs par défaut des options d'Interface.
-it.ro.HelpInterfaceConfig11:\Sreset the Interface options back to their default values.
+fr.ro.HelpInterfaceConfig11:\Srevenir aux valeurs par défaut des options d’Interface.
+it.ro.HelpInterfaceConfig11:\Sresetta le opzioni dell'interfaccia ai valori predefiniti.
nl.ro.HelpInterfaceConfig11:Klik met KIES om de instellingen in dit venster terug te zetten op de standaardwaarden.
+zh_CN.ro.HelpInterfaceConfig11:\S将界é¢é€‰é¡¹é‡ç½®ä¸ºé»˜è®¤å€¼ã€‚
+
en.ro.HelpInterfaceConfig12:\Sclose this \w without saving changes.|M\Areturn the interface options to the last saved configuration.
de.ro.HelpInterfaceConfig12:Klicken mit AUSWAHL schließt das Fenster ohne die Änderungen zu speichern.|MKlicken mit SPEZIAL stellt die zuletzt abgespeicherten Einstellungen wieder her.
-fr.ro.HelpInterfaceConfig12:\Sfermer cette fenêtre sans sauver les changements|M\Arevenir aux options d'Interface précédemment sauvegardées.
-it.ro.HelpInterfaceConfig12:\Sclose this \w without saving changes.|M\Areturn the interface options to the last saved configuration.
+fr.ro.HelpInterfaceConfig12:\Sfermer cette fenêtre sans sauver les changements|M\Arevenir aux options d’Interface précédemment sauvegardées.
+it.ro.HelpInterfaceConfig12:\Schiudi questa finestra senza salvare le modifiche.|M\Aripristina le opzioni dell'interfaccia all'ultima configurazione salvata.
nl.ro.HelpInterfaceConfig12:Klik met KIES om dit venster te sluiten zonder dat de gemaakte wijzigingen worden bewaard.|MKlik met PASAAN om de gemaakte wijzigingen ongedaan te maken; het venster wordt hierbij niet gesloten.
+zh_CN.ro.HelpInterfaceConfig12:\S关闭此 \w 而ä¸ä¿å­˜æ›´æ”¹ã€‚|M\A将界é¢é€‰é¡¹æ¢å¤åˆ°ä¸Šæ¬¡ä¿å­˜çš„é…置。
+
en.ro.HelpInterfaceConfig13:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
de.ro.HelpInterfaceConfig13:Klicken mit AUSWAHL speichert die Einstellungen und schließt das Fenster.|MKlicken mit SPEZIAL speichert die Einstellungen ohne das Fenster zu schließen.
fr.ro.HelpInterfaceConfig13:\Ssauver ces réglages et fermer la fenêtre.|M\Asauver ces réglages sans fermer la fenêtre.
-it.ro.HelpInterfaceConfig13:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
+it.ro.HelpInterfaceConfig13:\Ssalva queste impostazioni e chiudi la finestra.|M\Asalva queste impostazioni senza chiudere la finestra.
nl.ro.HelpInterfaceConfig13:Klik met KIES om de gemaakte wijzigingen te bewaren en dit venster te sluiten.|MKlikken met PASAAN heeft hetzelfde effect, alleen wordt het huidige venster dan niet gesloten.
+zh_CN.ro.HelpInterfaceConfig13:\Sä¿å­˜è¿™äº›è®¾ç½®å¹¶å…³é—­ \w。|M\A在ä¸å…³é—­ \w 的情况下ä¿å­˜è¿™äº›è®¾ç½®ã€‚
+
en.ro.HelpInterfaceConfig16:This indicates whether NetSurf will use an external hotlist client if available, in preference to the internal hotlist.
de.ro.HelpInterfaceConfig16:Erlaubt das Benutzen eines externen Programmes zur Verwaltung der Hotlist.
-fr.ro.HelpInterfaceConfig16:This indicates whether NetSurf will use an external hotlist client if available, in preference to the internal hotlist.
-it.ro.HelpInterfaceConfig16:This indicates whether NetSurf will use an external hotlist client if available, in preference to the internal hotlist.
+fr.ro.HelpInterfaceConfig16:Indique si NetSurf doit utiliser un client externe pour gérer les marque-pages en remplacement de sa propre liste interne.
+it.ro.HelpInterfaceConfig16:Indica se NetSurf tenterà di utilizzare un client segnalibri esterno se disponibile, al posto di quello interno.
nl.ro.HelpInterfaceConfig16:Deze optie geeft aan of de favorietenlijst via een extern programma (indien beschikbaar) beheerd mogen worden.
+zh_CN.ro.HelpInterfaceConfig16:这表示 NetSurf 是å¦ä¼˜å…ˆä½¿ç”¨å¤–部常用列表客户端(如果å¯ç”¨),而ä¸æ˜¯å†…部常用列表。
+
en.ro.HelpInterfaceConfig18:\Tthe path to a hotlist application which will be used to display the hotlist.
de.ro.HelpInterfaceConfig18:\Tder Pfad zu einer Anwendung, die die Hotlist verwalten kann.
-fr.ro.HelpInterfaceConfig18:\Tthe path to a hotlist application which will be used to display the hotlist.
-it.ro.HelpInterfaceConfig18:\Tthe path to a hotlist application which will be used to display the hotlist.
+fr.ro.HelpInterfaceConfig18:\Tle chemin vers l’application externe à utiliser pour afficher les marque-pages.
+it.ro.HelpInterfaceConfig18:\Til percorso di un'applicazione esterna da utilizzare per la visualizzazione dei segnalibri.
nl.ro.HelpInterfaceConfig18:Voer in dit invoerveld het pad in van een extern programma dat de favorietenlijst mag beheren.
+zh_CN.ro.HelpInterfaceConfig18:\T常用列表应用程åºçš„路径,将用æ¥æ˜¾ç¤ºå¸¸ç”¨åˆ—表。
en.ro.HelpLanguageConfig:\Tlanguage configuration \w
de.ro.HelpLanguageConfig:Konfigurationsfenster für die Spracheinstellungen
fr.ro.HelpLanguageConfig:\Tfenêtre de configuration de langue.
it.ro.HelpLanguageConfig:\Tconfigurazione della lingua \w
nl.ro.HelpLanguageConfig:Diverse taalinstellingen kunnen in dit venster gewijzigd worden.
+zh_CN.ro.HelpLanguageConfig:\T语言é…ç½® \w
+
en.ro.HelpLanguageConfig3:\Tcurrently selected interface language.|MThe interface language is the language used for NetSurf's messages and dialogue boxes.
de.ro.HelpLanguageConfig3:Das ist die aktuell eingestellte Sprache für die Bedienoberfläche.|MDiese Sprache wird genutzt, um NetSurf's Meldungen, Texte der Dialogboxen, Menüs darzustellen.
-fr.ro.HelpLanguageConfig3:\Tla langue d'interface sélectionnée actuellement.|MLa langue d'interface est la langue utilisée pour les messages et les boîtes de dialogue de Netsurf.
-it.ro.HelpLanguageConfig3:\Tcurrently selected interface language.|MThe interface language is the language used for NetSurf's messages and dialogue boxes.
+fr.ro.HelpLanguageConfig3:\Tla langue d’interface sélectionnée actuellement.|MLa langue d’interface est la langue utilisée pour les messages et les boîtes de dialogue de Netsurf.
+it.ro.HelpLanguageConfig3:\Tla lingua dell'interfaccia correntemente selezionata.|MLa lingua dell'interfaccia � la lingua utilizzata per i messaggi e le finestre di dialogo di NetSurf.
nl.ro.HelpLanguageConfig3:Dit is momenteel de geselecteerde gebruikersinterfacetaal.|MDe interfacetaal is de taal voor de melding- en dialoogvensters.
+zh_CN.ro.HelpLanguageConfig3:\T当å‰é€‰æ‹©çš„ç•Œé¢è¯­è¨€ã€‚|Mç•Œé¢è¯­è¨€æ˜¯ NetSurf æµè§ˆå™¨æ¶ˆæ¯å’Œå¯¹è¯æ¡†ä½¿ç”¨çš„语言。
+
en.ro.HelpLanguageConfig4:\Sselect an interface language.
de.ro.HelpLanguageConfig4:Klicken mit AUSWAHL zum Auswählen einer Oberflächensprache.
-fr.ro.HelpLanguageConfig4:\Schoisir une langue d'interface.
-it.ro.HelpLanguageConfig4:\Sseleziona un'interfaccia di lingua.
+fr.ro.HelpLanguageConfig4:\Schoisir une langue d’interface.
+it.ro.HelpLanguageConfig4:\Sseleziona una lingua per l'interfaccia.
nl.ro.HelpLanguageConfig4:Klik met KIES om de gebruikersinterfacetaal te kiezen.
+zh_CN.ro.HelpLanguageConfig4:\S选择界é¢è¯­è¨€ã€‚
+
en.ro.HelpLanguageConfig6:\Tcurrently selected web page language.|MIf a web site provides a choice of languages, NetSurf will request the page in your preferred language.
de.ro.HelpLanguageConfig6:Das ist die aktuelle Sprache zur Anzeige auf Webseiten.|MWenn eine Webseite die Darstellung in verschiedenen Sprachen anbietet, wird NetSurf die Webseite in der hier eingestellten bevorzugten Sprache abrufen.
fr.ro.HelpLanguageConfig6:\Tla langue de page web sélectionnée actuellement.|MSi un site web fournit un choix de langues, Netsurf demandera la page dans votre langue favorite.
-it.ro.HelpLanguageConfig6:\Tcurrently selected web page language.|MIf a web site provides a choice of languages, NetSurf will request the page in your preferred language.
+it.ro.HelpLanguageConfig6:\Tla lingua della pagina web correntemente selezionata.|MSe un sito Web offre una scelta di lingue, NetSurf richiederà la pagina nella tua lingua preferita.
nl.ro.HelpLanguageConfig6:Dit is momenteel de geselecteerde webpaginataal.|MWanneer een pagina meerdere taalmogelijkheden biedt, zal de NetSurf de pagina in de gewenste taal proberen op te vragen.
+zh_CN.ro.HelpLanguageConfig6:\T当å‰é€‰æ‹©çš„网页语言。|M如果网站æ供语言选择,NetSurf 将以您的首选语言请求网页。
+
en.ro.HelpLanguageConfig7:\Sselect a preferred web page language.
de.ro.HelpLanguageConfig7:Klicken mit AUSWAHL zum Auswählen einer Webseitensprache.
fr.ro.HelpLanguageConfig7:\Schoisir une langue de page web préférée.
it.ro.HelpLanguageConfig7:\Sseleziona una lingua preferita per le pagine web.
nl.ro.HelpLanguageConfig7:Klik met KIES om de gewenste webpaginataal te kiezen.
+zh_CN.ro.HelpLanguageConfig7:\S选择网页首选语言。
+
en.ro.HelpLanguageConfig8:\Sreset the Language options back to their default values.
de.ro.HelpLanguageConfig8:Stellt die Standardeinstellungen wieder her.
fr.ro.HelpLanguageConfig8:\Srevenir aux valeurs par défaut des options de Langue.
-it.ro.HelpLanguageConfig8:\Sreset the Language options back to their default values.
+it.ro.HelpLanguageConfig8:\Sresetta le opzioni della lingua ai valori predefiniti.
nl.ro.HelpLanguageConfig8:Klik met KIES om de instellingen in dit venster terug te zetten op de standaardwaarden.
+zh_CN.ro.HelpLanguageConfig8:\S将语言选项é‡ç½®ä¸ºé»˜è®¤å€¼ã€‚
+
en.ro.HelpLanguageConfig9:\Sclose this \w without saving changes.|M\Areturn the language options to the last saved configuration.
de.ro.HelpLanguageConfig9:Klicken mit AUSWAHL schließt das Fenster ohne die Änderungen zu speichern.|MKlicken mit SPEZIAL stellt die zuletzt abgespeicherten Einstellungen wieder her.
fr.ro.HelpLanguageConfig9:\Sfermer cette fenêtre sans sauver les changements|M\Arevenir aux options de Langue précédemment sauvegardées.
-it.ro.HelpLanguageConfig9:\Sclose this \w without saving changes.|M\Areturn the language options to the last saved configuration.
+it.ro.HelpLanguageConfig9:\Schiudi questa finestra senza salvare le modifiche.|M\Aripristina le opzioni della lingua all'ultima configurazione salvata.
nl.ro.HelpLanguageConfig9:Klik met KIES om dit venster te sluiten zonder dat de gemaakte wijzigingen worden bewaard.|MKlik met PASAAN om de gemaakte wijzigingen ongedaan te maken; het venster wordt hierbij niet gesloten.
+zh_CN.ro.HelpLanguageConfig9:\S关闭此 \w 而ä¸ä¿å­˜æ›´æ”¹ã€‚|M\A将语言选项æ¢å¤åˆ°ä¸Šæ¬¡ä¿å­˜çš„é…置。
+
en.ro.HelpLanguageConfig10:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
de.ro.HelpLanguageConfig10:Klicken mit AUSWAHL speichert die Einstellungen und schließt das Fenster.|MKlicken mit SPEZIAL speichert die Einstellungen ohne das Fenster zu schließen.
fr.ro.HelpLanguageConfig10:\Ssauver ces réglages et fermer la fenêtre.|M\Asauver ces réglages sans fermer la fenêtre.
-it.ro.HelpLanguageConfig10:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
+it.ro.HelpLanguageConfig10:\Ssalva queste impostazioni e chiudi la finestra.|M\Asalva queste impostazioni senza chiudere la finestra.
nl.ro.HelpLanguageConfig10:Klik met KIES om de gemaakte wijzigingen te bewaren en dit venster te sluiten.|MKlikken met PASAAN heeft hetzelfde effect, alleen wordt het huidige venster dan niet gesloten.
+zh_CN.ro.HelpLanguageConfig10:\Sä¿å­˜è¿™äº›è®¾ç½®å¹¶å…³é—­ \w。|M\A在ä¸å…³é—­ \w 的情况下ä¿å­˜è¿™äº›è®¾ç½®ã€‚
en.ro.HelpSecurityConfig:\Tsecurity configuration \w
de.ro.HelpSecurityConfig:Fenster zur Konfiguration der Sicherheitseinstellungen
fr.ro.HelpSecurityConfig:\Tla fenêtre de configuration de sécurité
it.ro.HelpSecurityConfig:\Tconfigurazione di sicurezza \w
nl.ro.HelpSecurityConfig:De privacy- en veiligheidsinstellingen kunnen in dit venster gewijzigd worden.
+zh_CN.ro.HelpSecurityConfig:\T安全é…ç½® \w
+
en.ro.HelpSecurityConfig2:This indicates whether NetSurf will send site referral information to web servers.|MWhen this is enabled NetSurf will tell the web server of a new page the address of the site you came from, after following a link.
de.ro.HelpSecurityConfig2:NetSurf sendet Seitenreferenzinformationen an Webserver.|MIst diese Option gewählt, schickt NetSurf an den Server einer neuen Webseite die Adresse der Seite von der aus die aktuelle über einen Link aufgerufen wurde.
-fr.ro.HelpSecurityConfig2:Ceci indique si Netsurf doit envoyer l'information de renvoi de site aux serveurs web.|MLorsque ceci est activé Netsurf signalera au serveur web d'une nouvelle page l'adresse du site d'où vous venez, après avoir suivi un lien.
-it.ro.HelpSecurityConfig2:This indicates whether NetSurf will send site referral information to web servers.|MWhen this is enabled NetSurf will tell the web server of a new page the address of the site you came from, after following a link.
+fr.ro.HelpSecurityConfig2:Ceci indique si Netsurf doit envoyer l’information de renvoi de site aux serveurs web.|MLorsque ceci est activé Netsurf signalera au serveur web d’une nouvelle page l’adresse du site d’où vous venez, après avoir suivi un lien.
+it.ro.HelpSecurityConfig2:Indica se NetSurf invierà le informazioni di riferimento del sito ai server Web.|MQuando questo � abilitato, NetSurf comunicherà al server Web di una nuova pagina l'indirizzo del sito dal quale proveniva, dopo aver seguito un link.
nl.ro.HelpSecurityConfig2:Deze optie geeft aan of site-gerelateerde informatie naar webservers wordt meegezonden.|MIndien toegestaan, ontvangt de webserver informatie over de vorige pagina waar, via een koppeling, vandaan is gekomen.
+zh_CN.ro.HelpSecurityConfig2:这表示 NetSurf 是å¦å°†ç«™ç‚¹æŽ¨èä¿¡æ¯å‘é€åˆ°ç½‘络æœåŠ¡å™¨ã€‚|Må¯ç”¨æ­¤é€‰é¡¹åŽï¼ŒNetSurf 将在跟踪链接åŽå°†æ‚¨çš„站点网å€å‘ŠçŸ¥æ–°ç½‘页的网络æœåŠ¡å™¨ã€‚
+
en.ro.HelpSecurityConfig6:You can enter the length of time that items are stored in global history here.
de.ro.HelpSecurityConfig6:Hier kann die Zeitdauer in Tagen angegeben werden, bis zu deren Ablauf Objekte in der globalen History gespeichert bleiben.
-fr.ro.HelpSecurityConfig6:Vous pouvez entrer ici la durée de stockage des items dans l'historique global.
-it.ro.HelpSecurityConfig6:You can enter the length of time that items are stored in global history here.
+fr.ro.HelpSecurityConfig6:Vous pouvez entrer ici la durée de stockage des items dans l’historique global.
+it.ro.HelpSecurityConfig6:Puoi inserire qui il periodo di tempo nel quale gli oggetti verranno memorizzati nella cronologia globale.
nl.ro.HelpSecurityConfig6:In dit veld kan de tijdsduur ingevoerd worden, dat items bewaard worden in de browsergeschiedenis.
+zh_CN.ro.HelpSecurityConfig6:您å¯ä»¥åœ¨æ­¤å¤„输入项在全局历å²è®°å½•ä¸­å­˜å‚¨çš„时长。
+
en.ro.HelpSecurityConfig7:\Sreduce the global history duration.
de.ro.HelpSecurityConfig7:Klicken mit AUSWAHL verkürzt die Aufbewahrungszeit von Seiten in der globalen History.
-fr.ro.HelpSecurityConfig7:\Sréduire la durée de l'historique global.
-it.ro.HelpSecurityConfig7:\Sriduce la durata della cronologia globale.
+fr.ro.HelpSecurityConfig7:\Sréduire la durée de l’historique global.
+it.ro.HelpSecurityConfig7:\Sriduci la durata della cronologia globale.
nl.ro.HelpSecurityConfig7:Klik met KIES om de tijdsduur van de browsergeschiedenis per dag te verminderen.
+zh_CN.ro.HelpSecurityConfig7:\S缩短全局历å²è®°å½•ä¿å­˜æ—¶é—´ã€‚
+
en.ro.HelpSecurityConfig8:\Sincrease the global history duration.
de.ro.HelpSecurityConfig8:Klicken mit AUSWAHL verlängert die Aufbewahrungszeit von Seiten in der globalen History.
-fr.ro.HelpSecurityConfig8:\Saugmenter la durée de l'historique global.
+fr.ro.HelpSecurityConfig8:\Saugmenter la durée de l’historique global.
it.ro.HelpSecurityConfig8:\Saumenta la durata della cronologia globale.
nl.ro.HelpSecurityConfig8:Klik met KIES om de tijdsduur van de browsergeschiedenis per dag te vermeerderen,
+zh_CN.ro.HelpSecurityConfig8:\S增加全局历å²è®°å½•ä¿å­˜æ—¶é—´ã€‚
+
en.ro.HelpSecurityConfig10:\Sreset the Security options back to their default values.
de.ro.HelpSecurityConfig10:Stellt die Standardeinstellungen wieder her.
fr.ro.HelpSecurityConfig10:\Srevenir aux valeurs par défaut des options de Sécurité.
-it.ro.HelpSecurityConfig10:\Sreset the Security options back to their default values.
+it.ro.HelpSecurityConfig10:\Sresetta le opzioni di sicurezza ai valori predefiniti.
nl.ro.HelpSecurityConfig10:Klik met KIES om de instellingen in dit venster terug te zetten op de standaardwaarden.
+zh_CN.ro.HelpSecurityConfig10:\S将安全选项é‡ç½®ä¸ºå…¶é»˜è®¤å€¼ã€‚
+
en.ro.HelpSecurityConfig11:\Sclose this \w without saving changes.|M\Areturn the security options to the last saved configuration.
de.ro.HelpSecurityConfig11:Klicken mit AUSWAHL schließt das Fenster ohne die Änderungen zu speichern.|MKlicken mit SPEZIAL stellt die zuletzt abgespeicherten Einstellungen wieder her.
fr.ro.HelpSecurityConfig11:\Sfermer cette fenêtre sans sauver les changements|M\Arevenir aux options de Sécurité précédemment sauvegardées.
-it.ro.HelpSecurityConfig11:\Sclose this \w without saving changes.|M\Areturn the security options to the last saved configuration.
+it.ro.HelpSecurityConfig11:\Schiudi questa finestra senza salvare le modifiche.|M\Aripristina le opzioni di sicurezza all'ultima configurazione salvata.
nl.ro.HelpSecurityConfig11:Klik met KIES om dit venster te sluiten zonder dat de gemaakte wijzigingen worden bewaard.|MKlik met PASAAN om de gemaakte wijzigingen ongedaan te maken; het venster wordt hierbij niet gesloten.
+zh_CN.ro.HelpSecurityConfig11:\S关闭此 \w 而ä¸ä¿å­˜æ›´æ”¹ã€‚|M\A将安全选项æ¢å¤åˆ°ä¸Šæ¬¡ä¿å­˜çš„é…置。
+
en.ro.HelpSecurityConfig12:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
de.ro.HelpSecurityConfig12:Klicken mit AUSWAHL speichert die Einstellungen und schließt das Fenster.|MKlicken mit SPEZIAL speichert die Einstellungen ohne das Fenster zu schließen.
fr.ro.HelpSecurityConfig12:\Ssauver ces réglages et fermer la fenêtre.|M\Asauver ces réglages sans fermer la fenêtre.
-it.ro.HelpSecurityConfig12:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
+it.ro.HelpSecurityConfig12:\Ssalva queste impostazioni e chiudi la finestra.|M\Asalva queste impostazioni senza chiudere la finestra.
nl.ro.HelpSecurityConfig12:Klik met KIES om de gemaakte wijzigingen te bewaren en dit venster te sluiten.|MKlikken met PASAAN heeft hetzelfde effect, alleen wordt het huidige venster dan niet gesloten.
+zh_CN.ro.HelpSecurityConfig12:\Sä¿å­˜è¿™äº›è®¾ç½®å¹¶å…³é—­\w。|M\A在ä¸å…³é—­\w的情况下ä¿å­˜è¿™äº›è®¾ç½®ã€‚
en.ro.HelpThemeConfig:\Ttheme configuration \w
de.ro.HelpThemeConfig:Fenster zur Auswahl des Anzeigethemas
fr.ro.HelpThemeConfig:\Tla fenêtre de configuration de thème
-it.ro.HelpThemeConfig:\Tconfigurazione del tema \w
+it.ro.HelpThemeConfig:\Tconfigurazione dei temi \w
nl.ro.HelpThemeConfig:Het thema kan in dit venster gewijzigd worden.
+zh_CN.ro.HelpThemeConfig:\T主题é…ç½® \w
+
en.ro.HelpThemeConfig2:\Sreset the Theme options back to their default values.
de.ro.HelpThemeConfig2:Stellt die Standardeinstellungen wieder her.
fr.ro.HelpThemeConfig2:\Srevenir aux valeurs par défaut des options de Thème.
-it.ro.HelpThemeConfig2:\Sreset the Theme options back to their default values.
+it.ro.HelpThemeConfig2:\Sresetta le opzioni del tema ai valori predefiniti.
nl.ro.HelpThemeConfig2:Klik met KIES om de instellingen in dit venster terug te zetten op de standaardwaarden.
+zh_CN.ro.HelpThemeConfig2:\S将主题选项é‡ç½®ä¸ºé»˜è®¤å€¼ã€‚
+
en.ro.HelpThemeConfig3:\Sclose this \w without saving changes.|M\Areturn the theme options to the last saved configuration.
de.ro.HelpThemeConfig3:Klicken mit AUSWAHL schließt das Fenster ohne die Änderungen zu speichern.|MKlicken mit SPEZIAL stellt die zuletzt abgespeicherten Einstellungen wieder her.
fr.ro.HelpThemeConfig3:\Sfermer cette fenêtre sans sauver les changements|M\Arevenir aux options de Thème précédemment sauvegardées.
-it.ro.HelpThemeConfig3:\Sclose this \w without saving changes.|M\Areturn the theme options to the last saved configuration.
+it.ro.HelpThemeConfig3:\Schiudi questa finestra senza salvare le modifiche.|M\Aripristina le opzioni dei temi all'ultima configurazione salvata.
nl.ro.HelpThemeConfig3:Klik met KIES om dit venster te sluiten zonder dat de gemaakte wijzigingen worden bewaard.|MKlik met PASAAN om de gemaakte wijzigingen ongedaan te maken; het venster wordt hierbij niet gesloten.
+zh_CN.ro.HelpThemeConfig3:\S关闭此 \w 而ä¸ä¿å­˜æ›´æ”¹ã€‚|M\A将主题选项æ¢å¤åˆ°ä¸Šæ¬¡ä¿å­˜çš„é…置。
+
en.ro.HelpThemeConfig4:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
de.ro.HelpThemeConfig4:Klicken mit AUSWAHL speichert die Einstellungen und schließt das Fenster.|MKlicken mit SPEZIAL speichert die Einstellungen ohne das Fenster zu schließen.
fr.ro.HelpThemeConfig4:\Ssauver ces réglages et fermer la fenêtre.|M\Asauver ces réglages sans fermer la fenêtre.
-it.ro.HelpThemeConfig4:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
+it.ro.HelpThemeConfig4:\Ssalva queste impostazioni e chiudi la finestra.|M\Asalva queste impostazioni senza chiudere la finestra.
nl.ro.HelpThemeConfig4:Klik met KIES om de gemaakte wijzigingen te bewaren en dit venster te sluiten.|MKlikken met PASAAN heeft hetzelfde effect, alleen wordt het huidige venster dan niet gesloten.
+zh_CN.ro.HelpThemeConfig4:\Sä¿å­˜è¿™äº›è®¾ç½®å¹¶å…³é—­ \w。|M\A在ä¸å…³é—­ \w 的情况下ä¿å­˜è¿™äº›è®¾ç½®ã€‚
en.ro.HelpThemePConfig:This pane shows the available themes.|MThe selected icon theme is used for NetSurf browser \ws, the hotlist, global history and cookie management.
de.ro.HelpThemePConfig:Dieser Dialog zeigt die verfügbaren Themen.|MDas ausgewählte Thema wird bei der Anzeige von Browserfenster, Cookieverwaltung, Hotlist und History eingesetzt.
-fr.ro.HelpThemePConfig:Cette fenêtre indique les thèmes disponibles.|MLe thème de l'icône sélectionnée est utilisée pour les fenêtres de navigation de Netsurf, la liste des favoris et l'historique global.
-it.ro.HelpThemePConfig:This pane shows the available themes.|MThe selected icon theme is used for NetSurf browser \ws, the hotlist, global history and cookie management.
+fr.ro.HelpThemePConfig:Cette fenêtre indique les thèmes disponibles.|MLe thème de l’icône sélectionnée est utilisée pour les fenêtres de navigation de Netsurf, la fenêtre des marque-pages et l’historique global.
+it.ro.HelpThemePConfig:Questo pannello mostra i temi disponibili.|MIl tema delle icone selezionato verrà usato dal browser NetSurf \ws, dai segnalibri, dalla cronologia globale e dal gestore dei cookie.
nl.ro.HelpThemePConfig:Dit deelvenster toont de beschikbare thema's.|MHet geselecteerde thema wordt gebruikt in de NetSurf-browservensters, de favorietenlijst en de browsergeschiedenis.
+zh_CN.ro.HelpThemePConfig:此窗格显示å¯ç”¨çš„主题。|M选定的图标主题用于 NetSurf æµè§ˆå™¨ \wsã€å¸¸ç”¨åˆ—表ã€å…¨å±€åŽ†å²è®°å½•å’Œ Cookie 管ç†ã€‚
# Amiga HelpHint (tooltip) text
#
@@ -5684,41 +8053,84 @@ de.ami.HelpToolbarBack:Back\nLMB: Steps back one page\nRMB: Display a menu of re
fr.ami.HelpToolbarBack:Back\nLMB: Steps back one page\nRMB: Display a menu of recent pages
it.ami.HelpToolbarBack:Indietro
nl.ami.HelpToolbarBack:Vorige\nLMB: Springt naar de vorige pagina in de venstergeschiedenis\nRMB: Toon menu met de venstergeschiedenis
+zh_CN.ami.HelpToolbarBack:åŽé€€ \n鼠标左键:åŽé€€ä¸€é¡µ\né¼ æ ‡å³é”®ï¼šæ˜¾ç¤ºæœ€è¿‘页é¢çš„èœå•
+
en.ami.HelpToolbarForward:Forward\nLMB: Steps forward one page
de.ami.HelpToolbarForward:Forward\nLMB: Steps forward one page
fr.ami.HelpToolbarForward:Forward\nLMB: Steps forward one page
it.ami.HelpToolbarForward:Avanti
nl.ami.HelpToolbarForward:Volgende\nLMB: Springt naar de volgende pagina in de venstergeschiedenis
+zh_CN.ami.HelpToolbarForward:å‰è¿›\n鼠标左键:å‰è¿›ä¸€é¡µ
+
en.ami.HelpToolbarStop:Stop\nLMB: Stops loading the page
de.ami.HelpToolbarStop:Stop\nLMB: Stops loading the page
fr.ami.HelpToolbarStop:Stop\nLMB: Stops loading the page
-it.ami.HelpToolbarStop:Stoppa
+it.ami.HelpToolbarStop:Stop
nl.ami.HelpToolbarStop:Stop\nLMB: Stopt het laden van de pagina
+zh_CN.ami.HelpToolbarStop:åœæ­¢\n鼠标左键:åœæ­¢åŠ è½½é¡µé¢
+
en.ami.HelpToolbarReload:Reload\nLMB: Reloads the page\nShift+LMB: Reloads the page and all objects
de.ami.HelpToolbarReload:Reload\nLMB: Reloads the page\nShift+LMB: Reloads the page and all objects
fr.ami.HelpToolbarReload:Reload\nLMB: Reloads the page\nShift+LMB: Reloads the page and all objects
it.ami.HelpToolbarReload:Ricarica
nl.ami.HelpToolbarReload:Herlaad\nLMB: Herlaad de pagina\nShift+LMB: Herlaad de pagina inclusief alle objecten
+zh_CN.ami.HelpToolbarReload:é‡æ–°åŠ è½½\n鼠标左键:é‡æ–°åŠ è½½é¡µé¢\nShifté”®+鼠标左键:é‡æ–°åŠ è½½é¡µé¢å’Œæ‰€æœ‰å¯¹è±¡
+
en.ami.HelpToolbarHome:Home\nLMB: Goes to the homepage
de.ami.HelpToolbarHome:Home\nLMB: Homepage ansteuern
fr.ami.HelpToolbarHome:Home\nLMB: Goes to the homepage
it.ami.HelpToolbarHome:Pagina iniziale
nl.ami.HelpToolbarHome:Startpagina\nLMB: Opent de ingestelde startpagina
+zh_CN.ami.HelpToolbarHome:主页\n鼠标左键:转到主页
+
en.ami.HelpToolbarURL:URL bar\nType a URL and press Return\nSuggestions can be selected with up/down
de.ami.HelpToolbarURL:URL bar\nType a URL and press Return\nSuggestions can be selected with up/down
fr.ami.HelpToolbarURL:URL bar\nType a URL and press Return\nSuggestions can be selected with up/down
it.ami.HelpToolbarURL:Barra indirizzi
nl.ami.HelpToolbarURL:Webadresbalk\nVoor een webadres in en druk op Enter\nSuggesties kunnen worden geselecteerd via cursor-omhoog/omlaag
+zh_CN.ami.HelpToolbarURL:地å€æ \n键入地å€å¹¶æŒ‰å›žè½¦é”®\nå¯ä½¿ç”¨å‘上/å‘下方å‘é”®æ¥é€‰æ‹©å»ºè®®
+
en.ami.HelpToolbarWebSearch:Web search bar\nType text and press Return to search using your default search provider
de.ami.HelpToolbarWebSearch:Websuchleiste\nText eingeben und Enter drücken um mit der Standardsuchmaschine zu suchen
fr.ami.HelpToolbarWebSearch:Web search bar\nType text and press Return to search using your default search provider
-it.ami.HelpToolbarWebSearch:Digita una voce in base al provider scelto e premi invio
+it.ami.HelpToolbarWebSearch:Digita un testo in base al provider di ricerca predefinito e premi invio
nl.ami.HelpToolbarWebSearch:Web-zoekbalk\nVoer de tekst in en druk op Enter om te zoeken met behulp van de standaard ingestelde zoekmachine
+zh_CN.ami.HelpToolbarWebSearch:Webæœç´¢æ \n键入文本并按下回车键使用默认æœç´¢æ供程åºè¿›è¡Œæœç´¢
+
en.ami.HelpToolbarAddTab:Add tab\nLMB: Adds a new blank tab
de.ami.HelpToolbarAddTab:Tab hinzufügen.
-fr.ami.HelpToolbarAddTab:Add tab\nLMB: Adds a new blank tab
+fr.ami.HelpToolbarAddTab:Ajouter un onglet\nLMB: Ajouter un nouvel onglet vide
it.ami.HelpToolbarAddTab:Apri una nuova scheda
nl.ami.HelpToolbarAddTab:Tabblad toevoegen\nLMB: Een nieuwe leeg tabblad wordt geopend
+zh_CN.ami.HelpToolbarAddTab:添加标签页\n鼠标左键:添加新的空白标签页
+
+en.ami.PageInfo:Page info
+fr.ami.PageInfo:Information sur la page
+
+en.ami.PageInfoInsecure:Insecure
+fr.ami.PageInfoInsecure:Non sécurisé
+it.ami.PageInfoInsecure:Non sicuro
+zh_CN.ami.PageInfoInsecure:ä¸å®‰å…¨
+
+en.ami.PageInfoLocal:Local
+fr.ami.PageInfoLocal:Local
+it.ami.PageInfoLocal:Locale
+zh_CN.ami.PageInfoLocal:本地
+
+en.ami.PageInfoSecure:Secure
+fr.ami.PageInfoSecure:Securisé
+it.ami.PageInfoSecure:Sicuro
+zh_CN.ami.PageInfoSecure:安全
+
+en.ami.PageInfoWarning:Warning
+fr.ami.PageInfoWarning:Attention
+it.ami.PageInfoWarning:Avviso
+zh_CN.ami.PageInfoWarning:警告
+
+en.ami.PageInfoInternal:Internal
+fr.ami.PageInfoInternal:Interne
+it.ami.PageInfoInternal:Interno
+zh_CN.ami.PageInfoInternal:内部
# Configuration tokens
@@ -5732,71 +8144,98 @@ de.all.con_cache:Cache
fr.all.con_cache:Cache
it.all.con_cache:Cache
nl.all.con_cache:Buffer
+zh_CN.all.con_cache:缓存
+
en.all.con_connect:Connection
de.all.con_connect:Verbindung
fr.all.con_connect:Connexion
it.all.con_connect:Connessione
nl.all.con_connect:Verbinding
+zh_CN.all.con_connect:连接
+
en.all.con_content:Content
de.all.con_content:Inhalte
fr.all.con_content:Contenu
it.all.con_content:Contenuto
nl.all.con_content:Browsen
+zh_CN.all.con_content:内容
+
en.all.con_fonts:Fonts
de.all.con_fonts:Schriftarten
fr.all.con_fonts:Polices de caractères
it.all.con_fonts:Font
nl.all.con_fonts:Lettertypen
+zh_CN.all.con_fonts:字体
+
en.all.con_home:Home page
de.all.con_home:Homepage
-fr.all.con_home:Page d'accueil
+fr.all.con_home:Page d’accueil
it.all.con_home:Pagina iniziale
nl.all.con_home:Startpagina
+zh_CN.all.con_home:主页
+
en.all.con_image:Images
de.all.con_image:Bilder
fr.all.con_image:Images
it.all.con_image:Immagini
nl.all.con_image:Afbeeldingen
+zh_CN.all.con_image:图åƒ
+
en.all.con_inter:Interface
de.all.con_inter:Nützliches
fr.all.con_inter:Interface
it.all.con_inter:Interfaccia
nl.all.con_inter:Interface
+zh_CN.all.con_inter:ç•Œé¢
+
en.all.con_lang:Language
de.all.con_lang:Sprachen
fr.all.con_lang:Langue
it.all.con_lang:Lingua
nl.all.con_lang:Taal
+zh_CN.all.con_lang:语言
+
en.all.con_memory:Memory
de.all.con_memory:Speicher
fr.all.con_memory:Mémoire
it.all.con_memory:Memoria
nl.all.con_memory:Geheugen
+zh_CN.all.con_memory:内存
+
en.all.con_secure:Security
de.all.con_secure:Sicherheit
fr.all.con_secure:Sécurité
it.all.con_secure:Sicurezza
nl.all.con_secure:Veiligheid
+zh_CN.all.con_secure:安全
+
en.all.con_theme:Themes
de.all.con_theme:Themen
fr.all.con_theme:Thèmes
it.all.con_theme:Temi
nl.all.con_theme:Thema's
+zh_CN.all.con_theme:主题
+
en.all.con_general:General
de.all.con_general:Allgemeines
fr.all.con_general:Général
it.all.con_general:Generale
nl.all.con_general:Algemeen
+zh_CN.all.con_general:常规
+
en.all.con_rendering:Rendering
de.all.con_rendering:Rendern
fr.all.con_rendering:Rendu
it.all.con_rendering:Rendering
nl.all.con_rendering:Weergave
+zh_CN.all.con_rendering:正在渲染
+
en.all.con_advanced:Advanced
de.all.con_advanced:Erweitertes
fr.all.con_advanced:Avancé
it.all.con_advanced:Avanzate
nl.all.con_advanced:Geavanceerd
+zh_CN.all.con_advanced:高级
# General tab
#
@@ -5806,97 +8245,133 @@ de.all.Preferences:Einstellungen
fr.all.Preferences:Préférences
it.all.Preferences:Preferenze di NetSurf
nl.all.Preferences:Voorkeuren
+zh_CN.all.Preferences:首选项
+
en.all.Use:Use
de.all.Use:Benutzen
fr.all.Use:Utiliser
it.all.Use:Usa
nl.all.Use:Gebruik
+zh_CN.all.Use:使用
en.all.HomePageURL:URL
de.all.HomePageURL:URL
-fr.all.HomePageURL:URL
+fr.all.HomePageURL:Adresse
it.all.HomePageURL:URL
nl.all.HomePageURL:Adres
+zh_CN.all.HomePageURL:URL
+
en.all.HomePageDefault:Use default page
de.all.HomePageDefault:Standardseite
fr.all.HomePageDefault:Utiliser la page par défaut
it.all.HomePageDefault:Usa pagina predefinita
nl.all.HomePageDefault:Gebruik standaardpagina
+zh_CN.all.HomePageDefault:使用默认页é¢
+
en.all.HomePageCurrent:Use current page
de.all.HomePageCurrent:Aktuelle Seite
fr.all.HomePageCurrent:Utiliser la page courante
it.all.HomePageCurrent:Usa pagina corrente
nl.all.HomePageCurrent:Gebruik deze pagina
+zh_CN.all.HomePageCurrent:使用当å‰é¡µé¢
+
en.all.HomePageBlank:Use blank page
de.all.HomePageBlank:Use blank page
-fr.all.HomePageBlank:Utiliser une page vierge
+fr.all.HomePageBlank:Utiliser une page vide
it.all.HomePageBlank:Usa pagina vuota
nl.all.HomePageBlank:Gebruik een lege pagina
+zh_CN.all.HomePageBlank:使用空白页é¢
+
en.all.ContentBlocking:Content blocking
de.all.ContentBlocking:Inhalte blockieren
-fr.all.ContentBlocking:blocage de contenu
+fr.all.ContentBlocking:Blocage de contenu
it.all.ContentBlocking:Blocca contenuti (AdBlock)
nl.all.ContentBlocking:Inhoud blokkeren
+zh_CN.all.ContentBlocking:å±è”½å†…容
+
en.all.BlockAds:Hide advertisements
de.all.BlockAds:Werbung unterdrücken
-fr.all.BlockAds:Cacher la publicité
+fr.all.BlockAds:Cacher les publicités
it.all.BlockAds:Nascondi messaggi/banner
nl.all.BlockAds:Verberg advertenties
+zh_CN.all.BlockAds:éšè—广告
+
en.all.ContentLanguage:Content language
de.all.ContentLanguage:Sprache
fr.all.ContentLanguage:Langue du contenu
it.all.ContentLanguage:Lingua contenuti
nl.all.ContentLanguage:Taal webpagina's
+zh_CN.all.ContentLanguage:内容语言
+
en.ami.LocaleLang:Get from Locale prefs
de.ami.LocaleLang:Rechnervorgabe nutzen
fr.ami.LocaleLang:Get from Locale prefs
it.ami.LocaleLang:Ottieni da preferenze localizzazione
nl.ami.LocaleLang:Gebruik computerspecificatie
+zh_CN.ami.LocaleLang:从区域设置首选项获å–
+
en.all.HistoryAge:Keep history for
de.all.HistoryAge:History behalten für
-fr.all.HistoryAge:Conserver l'historique de navigation pendant
+fr.all.HistoryAge:Conserver l’historique de navigation pendant
it.all.HistoryAge:Conserva cronologia per
nl.all.HistoryAge:Bewaar geschiedenis voor
+zh_CN.all.HistoryAge:ä¿å­˜åŽ†å²è®°å½•
+
en.all.Days:days
de.all.Days:Tage
fr.all.Days:jours
it.all.Days:giorni
nl.all.Days:dagen
+zh_CN.all.Days:天
+
en.all.Scripting:Scripting
de.all.Scripting:Scripting
fr.all.Scripting:Scripts
it.all.Scripting:Scripting
nl.all.Scripting:Scripts
+zh_CN.all.Scripting:脚本
+
en.all.EnableJS:Enable JavaScript
de.all.EnableJS:JavaScript benutzen
fr.all.EnableJS:Activer le JavaScript
it.all.EnableJS:Attiva JavaScript
nl.all.EnableJS:JavaScript ingeschakeld
+zh_CN.all.EnableJS:å¯ç”¨ JavaScript
+
en.all.Miscellaneous:Miscellaneous
de.all.Miscellaneous:Verschiedenes
fr.all.Miscellaneous:Autres
it.all.Miscellaneous:Impostazioni varie
nl.all.Miscellaneous:Overig
+zh_CN.all.Miscellaneous:æ‚项
+
en.ami.Privacy:Privacy
de.ami.Privacy:Privacy
fr.ami.Privacy:Confidentialité
it.ami.Privacy:Privacy
nl.ami.Privacy:Privacy
+zh_CN.ami.Privacy:éšç§
+
en.all.SendReferer:Send site referral information
de.all.SendReferer:Seitenreferenzen senden
-fr.all.SendReferer:Permettre l'envoi du referer en entête
+fr.all.SendReferer:Autoriser le partage du referer
it.all.SendReferer:Invia informazioni sul referral del sito
nl.all.SendReferer:Zend websitereferentie
+zh_CN.all.SendReferer:å‘é€ç½‘站推èä¿¡æ¯
+
en.ami.DoNotTrack:Send header to tell websites not to track
de.ami.DoNotTrack:Webseiten das Tracking verbieten - Wunsch
-fr.ami.DoNotTrack:Activer l'envoi d'une requête "Ne pas suivre à la trace"
+fr.ami.DoNotTrack:Demander aux sites Web de « ne pas me pister »
it.ami.DoNotTrack:Invia header al sito per la richiesta di non tracciamento
nl.ami.DoNotTrack:Websites laten weten dat gebruiker niet gevolgd wil worden
+zh_CN.ami.DoNotTrack:å‘é€æŠ¥å¤´ä»¥å‘ŠçŸ¥ç½‘ç«™ä¸è¦è·Ÿè¸ªèŽ·å–用户éšç§ä¿¡æ¯
+
en.all.FastScrolling:Fast scrolling
de.all.FastScrolling:Schnelles Scrollen
fr.all.FastScrolling:Défilement rapide
it.all.FastScrolling:Scrolling veloce
nl.all.FastScrolling:Snelschuiven
+zh_CN.all.FastScrolling:快速滚动
# Display tab
#
@@ -5906,51 +8381,98 @@ de.all.Screen:Ausgabe
fr.all.Screen:Écran
it.all.Screen:Gestione schermi
nl.all.Screen:Scherm
+zh_CN.all.Screen:å±å¹•
+
en.all.ScreenOwn:Own screen
de.all.ScreenOwn:Eigener Screen
-fr.all.ScreenOwn:Own screen
+fr.all.ScreenOwn:Écran privé
it.all.ScreenOwn:Schermo proprietario
nl.all.ScreenOwn:Eigen scherm
+zh_CN.all.ScreenOwn:本机å±å¹•
+
en.ami.ScreenWB:Workbench
de.ami.ScreenWB:Workbench
-fr.ami.ScreenWB:Plan de travail
+fr.ami.ScreenWB:Espace de travail
it.ami.ScreenWB:Schermo Workbench
nl.ami.ScreenWB:Workbench-scherm
+zh_CN.ami.ScreenWB:工作å°
+
en.ami.ScreenPublic:Public screen
de.ami.ScreenPublic:Public Screen
fr.ami.ScreenPublic:Écran public
it.ami.ScreenPublic:Schermo pubblico
nl.ami.ScreenPublic:Openbaar scherm
+zh_CN.ami.ScreenPublic:共享å±å¹•
+
en.ami.SimpleRefresh:Simple refresh
de.ami.SimpleRefresh:Simple refresh
fr.ami.SimpleRefresh:Rafraîchissement simple
it.ami.SimpleRefresh:Refresh semplice
nl.ami.SimpleRefresh:Eenvoudig verversen
+zh_CN.ami.SimpleRefresh:刷新
+
en.all.Theme:Theme
de.all.Theme:Thema
fr.all.Theme:Thème
it.all.Theme:Tema grafico
nl.all.Theme:Thema
+zh_CN.all.Theme:主题
+
+en.ami.ThemeGUI:GUI theme
+de.ami.ThemeGUI:GUI theme
+fr.ami.ThemeGUI:Thème de l’interface
+it.ami.ThemeGUI:GUI theme
+nl.ami.ThemeGUI:GUI theme
+zh_CN.ami.ThemeGUI:GUI theme
+
+en.ami.ThemePage:Preferred page theme
+de.ami.ThemePage:Preferred page theme
+fr.ami.ThemePage:Thème de page préféré
+it.ami.ThemePage:Preferred page theme
+nl.ami.ThemePage:Preferred page theme
+zh_CN.ami.ThemePage:Preferred page theme
+
+en.ami.Light:Light
+de.ami.Light:Light
+fr.ami.Light:Clair
+it.ami.Light:Light
+nl.ami.Light:Light
+zh_CN.ami.Light:Light
+
+en.ami.Dark:Dark
+de.ami.Dark:Dark
+fr.ami.Dark:Sombre
+it.ami.Dark:Dark
+nl.ami.Dark:Dark
+zh_CN.ami.Dark:Dark
+
en.all.MousePointers:Mouse pointers
de.all.MousePointers:Mauszeiger
fr.all.MousePointers:Pointeurs de souris
it.all.MousePointers:Puntatori del mouse
nl.all.MousePointers:Muisaanwijzers
+zh_CN.all.MousePointers:鼠标指针
+
en.all.TrueColour:True colour
de.all.TrueColour:TrueColour
-fr.all.TrueColour:Couleur vraie
+fr.all.TrueColour:Vraies couleurs
it.all.TrueColour:True color
nl.all.TrueColour:Ware kleuren
+zh_CN.all.TrueColour:真彩
+
en.all.OSPointers:Use OS mouse pointers when possible
de.all.OSPointers:Mauszeiger vom OS nutzen, wenn möglich
-fr.all.OSPointers:Utiliser les pointeurs de souris du système d'exploitation lorsque cela est possible
+fr.all.OSPointers:Utiliser les pointeurs de souris du système d’exploitation lorsque cela est possible
it.all.OSPointers:Se possibile usa i puntatori del mouse di sistema
nl.all.OSPointers:Gebruik bij voorkeur besturingssysteem-muisaanwijzers
+zh_CN.all.OSPointers:å°½å¯èƒ½ä½¿ç”¨æ“作系统的鼠标指针
+
en.all.NeedRestart:These options will not take effect until the next time NetSurf is started
de.all.NeedRestart:Diese Optionen werden erst nach einem Neustart von NetSurf aktiviert.
-fr.all.NeedRestart:Ces options ne prendront effet qu'au prochain démarrage de NetSurf
+fr.all.NeedRestart:Ces options ne prendront effet qu’au prochain démarrage de NetSurf
it.all.NeedRestart:Queste modifiche avranno effetto al prossimo riavvio di NetSurf
nl.all.NeedRestart:Deze opties worden pas actief nadat NetSurf opieuw is gestart
+zh_CN.all.NeedRestart:这些选项在下次å¯åŠ¨ NetSurf 之å‰ä¸ä¼šç”Ÿæ•ˆ
# Connection tab
#
@@ -5960,31 +8482,40 @@ de.all.Proxy:HTTP Proxy
fr.all.Proxy:Proxy HTTP
it.all.Proxy:Proxy HTTP
nl.all.Proxy:HTTP-proxy
+zh_CN.all.Proxy:HTTP 代ç†æœåŠ¡å™¨
+
en.ami.ProxyBypass:Bypass proxy for
de.ami.ProxyBypass:Bypass proxy for
fr.ami.ProxyBypass:Contournement du proxy pour
it.ami.ProxyBypass:Bypassa proxy per
nl.ami.ProxyBypass:Proxy omleiden voor
+zh_CN.ami.ProxyBypass:绕过代ç†æœåŠ¡å™¨
+
en.all.Fetching:Fetching
de.all.Fetching:Fetching
-fr.all.Fetching:Connexion
+fr.all.Fetching:Récupération
it.all.Fetching:Ricezione
nl.all.Fetching:ophalen
en.all.FetchesMax:Maximum fetches
de.all.FetchesMax:Maximale Anzahl an Ladevorgängen
-fr.all.FetchesMax:Maximum de connexions
+fr.all.FetchesMax:Maximum de récupération
it.all.FetchesMax:Massima
nl.all.FetchesMax:Maximaal aantal keer ophalen
+zh_CN.all.FetchesMax:最大获å–æ•°
+
en.all.FetchesHost:Fetches per host
de.all.FetchesHost:Ladevorgänge pro Host
-fr.all.FetchesHost:Connexions par hôte
+fr.all.FetchesHost:Récupérations par hôte
it.all.FetchesHost:Per host
nl.all.FetchesHost:Fetches per host
+zh_CN.all.FetchesHost:æ¯ä¸ªä¸»æœºçš„获å–次数
+
en.all.FetchesCached:Cached connections
de.all.FetchesCached:Gehaltene Verbindungen
fr.all.FetchesCached:Connexions en cache
it.all.FetchesCached:Su cache
nl.all.FetchesCached:Gebufferde verbindingen
+zh_CN.all.FetchesCached:已缓存连接
# Rendering tab
#
@@ -5994,83 +8525,119 @@ de.all.CacheNative:Originale zwischenspeichern
fr.all.CacheNative:Versions natives du cache
it.all.CacheNative:Versioni cache native
nl.all.CacheNative:Buffer oorspronkelijke versies
+zh_CN.all.CacheNative:缓存本机版本
+
en.all.ScaleQuality:Higher quality scaling
de.all.ScaleQuality:Skalieren hoher Qualität
-fr.all.ScaleQuality:Graduation de qualité supérieur
+fr.all.ScaleQuality:Mise à l’échelle de haute qualité
it.all.ScaleQuality:Massima qualità di visualizzazione
nl.all.ScaleQuality:Hogere schaalkwaliteit
+zh_CN.all.ScaleQuality:高质é‡ç¼©æ”¾
+
en.ami.DitherQuality:Dither quality
de.ami.DitherQuality:Dithern
fr.ami.DitherQuality:Qualité de tramage
it.ami.DitherQuality:Qualità dither
nl.ami.DitherQuality:Kwaliteit kleurbenadering
+zh_CN.ami.DitherQuality:数字抖动质é‡
+
en.ami.Low:Low
de.ami.Low:Low
fr.ami.Low:Faible
it.ami.Low:Bassa
nl.ami.Low:Laag
+zh_CN.ami.Low:低
+
en.ami.Medium:Medium
de.ami.Medium:Medium
fr.ami.Medium:Moyenne
it.ami.Medium:Media
nl.ami.Medium:Gemiddeld
+zh_CN.ami.Medium:中
+
en.ami.High:High
de.ami.High:High
fr.ami.High:Élevée
it.ami.High:Alta
nl.ami.High:Hoog
+zh_CN.ami.High:高
+
en.all.Animations:Animations
de.all.Animations:Animationen
fr.all.Animations:Animations et effets
it.all.Animations:Animazioni
nl.all.Animations:Animaties
+zh_CN.all.Animations:动画
+
en.all.AnimSpeedLimit:Limit speed to
de.all.AnimSpeedLimit:Geschwindigkeit begrenzen
fr.all.AnimSpeedLimit:Limiter la vitesse à
it.all.AnimSpeedLimit:Limita velocità a
nl.all.AnimSpeedLimit:Beperk snelheid tot
+zh_CN.all.AnimSpeedLimit:é™åˆ¶é€Ÿåº¦ä¸º
+
en.all.AnimSpeedFrames:seconds between frames
de.all.AnimSpeedFrames:Bildintervall (Sekunden)
-fr.all.AnimSpeedFrames:secondes entre les images
+fr.all.AnimSpeedFrames:secondes entre chaque image
it.all.AnimSpeedFrames:fotogrammi al secondo
nl.all.AnimSpeedFrames:seconden per beeld
+zh_CN.all.AnimSpeedFrames:æ¯å¸§ä¹‹é—´çš„秒数
+
en.all.AnimDisable:Disable animations
de.all.AnimDisable:Animationen abschalten
fr.all.AnimDisable:Désactiver les animations
it.all.AnimDisable:Disattiva animazioni
nl.all.AnimDisable:Schakel animaties uit
+zh_CN.all.AnimDisable:ç¦ç”¨åŠ¨ç”»
en.all.None:None
de.all.None:Keine
fr.all.None:Aucun
it.all.None:Nessuna
nl.all.None:Geen
+zh_CN.all.None:æ— 
+
en.all.Scaled:Scaled
de.all.Scaled:Skaliert
-fr.all.Scaled:Scaled
+fr.all.Scaled:Ajusté
it.all.Scaled:Scalate
nl.all.Scaled:Geschaald
+zh_CN.all.Scaled:已缩放
en.all.Resolution:Resolution
de.all.Resolution:Auflösung
fr.all.Resolution:Résolution
it.all.Resolution:Risoluzione
nl.all.Resolution:Resolutie
+zh_CN.all.Resolution:分辨率
+
en.all.ResolutionY:Vertical resolution
de.all.ResolutionY:Vertikale Auflösung
fr.all.ResolutionY:Résolution verticale
it.all.ResolutionY:Verticale
nl.all.ResolutionY:Verticale resolutie
+zh_CN.all.ResolutionY:纵å‘分辨率
+
en.all.ResolutionX:Horizontal resolution
de.all.ResolutionX:Horizontale Auflösung
fr.all.ResolutionX:Résolution horizontale
it.all.ResolutionX:Orizzontale
nl.all.ResolutionX:Horizontale resolutie
+zh_CN.all.ResolutionX:横å‘分辨率
+
en.all.DPI:DPI
de.all.DPI:DPI
fr.all.DPI:PPP
it.all.DPI:DPI
nl.all.DPI:DPI
+zh_CN.all.DPI:DPI(Dot Per Inch æ¯è‹±å¯¸ç‚¹æ•°ï¼‰
+
+en.ami.EnableCSS:Enable CSS
+de.ami.EnableCSS:CSS benutzen
+fr.ami.EnableCSS:Activer le CSS
+it.ami.EnableCSS:Attiva CSS
+nl.ami.EnableCSS:CSS ingeschakeld
+zh_CN.ami.EnableCSS:å¯ç”¨ CSS
# Fonts tab
#
@@ -6080,103 +8647,137 @@ de.all.FontFamilies:Schriftfamilien
fr.all.FontFamilies:Familles de police de caractères
it.all.FontFamilies:Famiglia Font
nl.all.FontFamilies:Lettertypesoort
+zh_CN.all.FontFamilies:字体家æ—
+
en.all.FontSans:Sans-serif
de.all.FontSans:Sans-serif
fr.all.FontSans:Sans-serif
it.all.FontSans:Sans-serif
nl.all.FontSans:Sans-serif
+zh_CN.all.FontSans:无衬线字体
+
en.all.FontSerif:Serif
de.all.FontSerif:Serif
fr.all.FontSerif:Serif
it.all.FontSerif:Serif
nl.all.FontSerif:Serif
+zh_CN.all.FontSerif:衬线字体
+
en.all.FontMono:Monospaced
de.all.FontMono:Monospace
-fr.all.FontMono:Monospace
+fr.all.FontMono:Chasse fixe
it.all.FontMono:Monospaziato
nl.all.FontMono:Monospaced
+zh_CN.all.FontMono:等宽字体
+
en.all.FontCursive:Cursive
de.all.FontCursive:Kursiv
fr.all.FontCursive:Cursive
it.all.FontCursive:Corsivo
nl.all.FontCursive:Cursief
+zh_CN.all.FontCursive:手写字体
+
en.all.FontFantasy:Fantasy
de.all.FontFantasy:Fantasy
fr.all.FontFantasy:Fantaisie
it.all.FontFantasy:Fantasia
nl.all.FontFantasy:Fantasie
+zh_CN.all.FontFantasy:Fantasy 字体
+
en.ami.FontFallback:Preferred fallback
de.ami.FontFallback:wenns nicht klappt
-fr.ami.FontFallback:Police de caractères de secour préférée
+fr.ami.FontFallback:Police de caractères de remplacement préférée
it.ami.FontFallback:Fallback preferito
nl.ami.FontFallback:Favoriete reserve lettertype
+zh_CN.ami.FontFallback:字体的首选åŽå¤‡
+
en.all.Default:Default
de.all.Default:Standard
fr.all.Default:Défaut
it.all.Default:Predefinito
nl.all.Default:Standaard
+zh_CN.all.Default:默认
+
en.all.FontSize:Font size
de.all.FontSize:Schriftgröße
-fr.all.FontSize:Taille de police de caractères
+fr.all.FontSize:Taille de la police de caractères
it.all.FontSize:Dimensione Font
nl.all.FontSize:Lettertypegrootte
+zh_CN.all.FontSize:字体大å°
+
en.all.Minimum:Minimum
de.all.Minimum:Minimum
fr.all.Minimum:Minimum
it.all.Minimum:Minimo
nl.all.Minimum:Minimum
+zh_CN.all.Minimum:最å°çš„字体大å°
+
en.all.Pt:pt
de.all.Pt:pt
fr.all.Pt:pt
it.all.Pt:pt
nl.all.Pt:pt
+zh_CN.all.Pt:pt
+
en.ami.FontAntialiasing:Use anti-aliasing (when possible)
de.ami.FontAntialiasing:Anti-aliasing nutzen (wenn möglich)
-fr.ami.FontAntialiasing:Utiliser l'anticrénelage (si possible)
+fr.ami.FontAntialiasing:Utiliser l’anticrénelage (si possible)
it.ami.FontAntialiasing:Usa anti-aliasing (quando possibile)
nl.ami.FontAntialiasing:Anti-aliasing (indien mogelijk) gebruiken
+zh_CN.ami.FontAntialiasing:使用抗锯齿处ç†æ–¹å¼ï¼ˆå¦‚æžœå¯èƒ½ï¼‰
+
en.ami.FontBitmap:Allow bitmap fonts
de.ami.FontBitmap:Bitmap Fonts zulassen
-fr.ami.FontBitmap:Allow bitmap fonts
+fr.ami.FontBitmap:Autoriser les polices de caractères bitmap
it.ami.FontBitmap:Permetti font bitmap
nl.ami.FontBitmap:Allow bitmap fonts
+zh_CN.ami.FontBitmap:å…许使用点阵字体
# Font scanning
en.ami.FontScanning:Scanning fonts...
de.ami.FontScanning:Lese Fonts ein...
-fr.ami.FontScanning:Balayage de polices de caractères...
+fr.ami.FontScanning:Lecture des polices de caractères…
it.ami.FontScanning:Scansione dei font in corso...
nl.ami.FontScanning:Scannen lettertypen...
+zh_CN.ami.FontScanning:正在扫æ字体…
+
en.ami.FontGlyphs:%ld unique glyphs found
de.ami.FontGlyphs:%ld eigenständige Glyphen gefunden
-fr.ami.FontGlyphs:%ld glyphe(s) unique(s) trouvé
+fr.ami.FontGlyphs:%ld glyphes uniques trouvés
it.ami.FontGlyphs:%ld glifi unici trovati
nl.ami.FontGlyphs:%ld unieke tekens gevonden
+zh_CN.ami.FontGlyphs:找到 %ld 个字形
# Cache tab
#
en.all.CacheMemory:Memory cache
de.all.CacheMemory:Arbeitsspeicher Cache
-fr.all.CacheMemory:Mémoire cache
+fr.all.CacheMemory:Cache en mémoire vive
it.all.CacheMemory:Memoria cache
nl.all.CacheMemory:Buffergeheugen
+zh_CN.all.CacheMemory:内存缓存
+
en.all.CacheDisc:Disc cache
de.all.CacheDisc:Festplatten Cache
-fr.all.CacheDisc:Cache du disque
+fr.all.CacheDisc:Cache sur le disque
it.all.CacheDisc:Cache su disco
nl.all.CacheDisc:Schijfbuffer
+zh_CN.all.CacheDisc:ç£ç›˜ç¼“å­˜
en.all.Size:Size
de.all.Size:Größe
fr.all.Size:Taille
it.all.Size:Dimensione
nl.all.Size:Grootte
+zh_CN.all.Size:大å°
+
en.all.Duration:Duration
de.all.Duration:Dauer
fr.all.Duration:Durée
it.all.Duration:Durata
nl.all.Duration:Tijdsduur
+zh_CN.all.Duration:缓存ç£ç›˜çš„时长
# Tabs
#
@@ -6186,128 +8787,171 @@ de.ami.Tabs:Tabs
fr.ami.Tabs:Onglets
it.ami.Tabs:Schede
nl.ami.Tabs:Tabbladen
+zh_CN.ami.Tabs:标签页
+
en.all.TabbedBrowsing:Tabbed browsing
de.all.TabbedBrowsing:Registernavigation (Tabs)
fr.all.TabbedBrowsing:Navigation par onglets
it.all.TabbedBrowsing:Navigazione a schede
nl.all.TabbedBrowsing:Browsen met tabbladen
+zh_CN.all.TabbedBrowsing:标签页å¼æµè§ˆ
+
en.all.TabActive:Open new tabs in background
de.all.TabActive:Neuen Tab im Hintergrund öffnen
-fr.all.TabActive:Ouvrir de nouveaux onglets en arrière-plan
+fr.all.TabActive:Ouvrir les nouveaux onglets en arrière plan
it.all.TabActive:Apri le nuove schede in sottofondo
nl.all.TabActive:Open nieuwe tabbladen in de achtergrond
+zh_CN.all.TabActive:在åŽå°ä¸­æ‰“开新标签页
+
en.all.TabMiddle:Middle mouse button opens tabs
de.all.TabMiddle:Mittlere Maustaste öffnet Tab
-fr.all.TabMiddle:Bouton du milieu de la souris ouvre un onglet
+fr.all.TabMiddle:Le bouton du milieu de la souris ouvre un onglet
it.all.TabMiddle:Usa tasto centrale del mouse per aprire le schede
nl.all.TabMiddle:Middelste muisknop opent een nieuw tabblad
+zh_CN.all.TabMiddle:鼠标中键点击 URL,并在新标签页中打开
+
en.all.TabLast:Open new tabs after all existing tabs
de.all.TabLast:Neue Tabs hinter letztem öffnen
-fr.all.TabLast:Ouvrir de nouveaux onglets après tous les onglets existants
+fr.all.TabLast:Placer les nouveaux onglets après tous les autres
it.all.TabLast:Apri le nuove schede dopo quella corrente
nl.all.TabLast:Open nieuw tabblad na alle bestaande tabbladen
+zh_CN.all.TabLast:在已有标签页å³ä¾§æ‰“开新标签页
+
en.ami.TabClose:Warn when closing multiple tabs
de.ami.TabClose:Warnen beim Schließen vieler Tabs
fr.ami.TabClose:Avertir lors de la fermeture de plusieurs onglets
it.ami.TabClose:Avvisa quando si chiudono più schede
nl.ami.TabClose:Waarschuwen wanneer meerdere tabbladen tegelijkertijd worden gesloten
+zh_CN.ami.TabClose:关闭多个标签页时å‘出警告
+
en.ami.TabAlways:Always show tabs
de.ami.TabAlways:Tabs immer zeigen
fr.ami.TabAlways:Toujours afficher les onglets
it.ami.TabAlways:Mostra sempre la barra delle schede
nl.ami.TabAlways:Tabbladen altijd tonen
+zh_CN.ami.TabAlways:总是显示标签页æ 
# Advanced
#
en.all.Downloads:Downloads
de.all.Downloads:Downloads
+fr.all.Downloads:Téléchargements
it.all.Downloads:Trasferimenti
nl.all.Downloads:Opgehaalde items
+zh_CN.all.Downloads:下载项
en.all.ConfirmOverwrite:Request confirmation when overwriting
de.all.ConfirmOverwrite:vor Ãœberschreiben nachfragen
-fr.all.ConfirmOverwrite:Demande de confirmation lors de l'écrasement
+fr.all.ConfirmOverwrite:Demander une confirmation avant d’écraser
it.all.ConfirmOverwrite:Richiedi conferma prima di sovrascrivere
nl.all.ConfirmOverwrite:Vraag bevestiging bij overschrijven
+zh_CN.all.ConfirmOverwrite:覆盖时请求确认
+
en.all.DownloadDir:Initial download location
de.all.DownloadDir:Downloadverzeichnis
fr.all.DownloadDir:Emplacement initial de téléchargement
it.all.DownloadDir:Percorso predefinito
nl.all.DownloadDir:Initiële ophaallocatie
+zh_CN.all.DownloadDir:默认下载ä½ç½®
+
en.all.DownloadNotify:Notify on completion
de.all.DownloadNotify:Downloadende melden
-fr.all.DownloadNotify:Notifier sur complétion
+fr.all.DownloadNotify:Notifier lorsque le téléchargement se termine
it.all.DownloadNotify:Notifica al completamento (Ringhio)
nl.all.DownloadNotify:Melding wanneer ophalenproces gereed is
+zh_CN.all.DownloadNotify:完æˆæ—¶é€šçŸ¥
+
en.all.SearchWeb:Web search
de.all.SearchWeb:Websuche
fr.all.SearchWeb:Recherche Web
it.all.SearchWeb:Ricerca nel Web
nl.all.SearchWeb:Zoek op web
+zh_CN.all.SearchWeb:互è”网æœç´¢
+
en.all.SearchURL:Search from URL bar
de.all.SearchURL:Suche über URL Leiste
-fr.all.SearchURL:Recherche depuis la barre URL
+fr.all.SearchURL:Lancer des recherches depuis la barre d’adresse
it.all.SearchURL:Ricerca da barra URL
nl.all.SearchURL:Zoek via (web)adresveld
+zh_CN.all.SearchURL:从地å€æ æœç´¢
+
en.all.SearchProvider:Search provider
de.all.SearchProvider:Suchmaschine
fr.all.SearchProvider:Fournisseur de recherche
it.all.SearchProvider:Ricerca su provider
nl.all.SearchProvider:Zoekmachine
+zh_CN.all.SearchProvider:æœç´¢æ供者
+
en.ami.OptionDocky:Show in AmiDock
de.ami.OptionDocky:In AmiDock zeigen
fr.ami.OptionDocky:Afficher dans AmiDock
it.ami.OptionDocky:Mostra icona di NetSurf su AmiDock
nl.ami.OptionDocky:Toon in AmiDock
+zh_CN.ami.OptionDocky:在 AmiDock 中显示
+
en.ami.PopupMenu:Use popupmenu for forms
de.ami.PopupMenu:Use popupmenu for forms
-fr.ami.PopupMenu:Use popupmenu for forms
+fr.ami.PopupMenu:Utiliser un menu popup pour les formulaires
it.ami.PopupMenu:Usa menu popup nei form
nl.ami.PopupMenu:Gebruik popup-menu for formulieren
+zh_CN.ami.PopupMenu:对表格使用弹出å¼èœå•
+
en.all.Clipboard:Clipboard
de.all.Clipboard:Clipboard
fr.all.Clipboard:Presse-papiers
it.all.Clipboard:Clipboard
nl.all.Clipboard:Klembord
+zh_CN.all.Clipboard:剪贴æ¿
+
en.all.ClipboardUTF8:Write text as UTF-8
de.all.ClipboardUTF8:Text als UTF-8
-fr.all.ClipboardUTF8:Écrire du texte en UTF-8
+fr.all.ClipboardUTF8:Écrire le texte en UTF-8
it.all.ClipboardUTF8:Scrivi testo come UTF-8
nl.all.ClipboardUTF8:Schrijf tekst in UTF8-formaat
+zh_CN.all.ClipboardUTF8:以 UTF-8 ç¼–ç å†™å…¥æ–‡ä»¶
+
en.all.ContextMenu:Context menu
de.all.ContextMenu:Kontextmenu
fr.all.ContextMenu:Menu contextuel
it.all.ContextMenu:Menu contestuali
nl.all.ContextMenu:Contextmenu
+zh_CN.all.ContextMenu:å³é”®èœå•
+
en.all.Enable:Enable
de.all.Enable:Erlauben
fr.all.Enable:Activer
it.all.Enable:Attivi
nl.all.Enable:Ingschakeld
+zh_CN.all.Enable:å¯ç”¨
+
en.all.Sticky:Sticky
de.all.Sticky:Klebrig
fr.all.Sticky:Collant
it.all.Sticky:Fissi
nl.all.Sticky:Vensterkleven
+zh_CN.all.Sticky:置顶
en.all.Behaviour:Behaviour
de.all.Behaviour:Verhalten
fr.all.Behaviour:Comportement général
it.all.Behaviour:Comportamento generale
nl.all.Behaviour:Gedrag
+zh_CN.all.Behaviour:行为
en.all.OptionNoWindow:Do not open window on startup
de.all.OptionNoWindow:Kein Fenster beim Start öffnen
fr.all.OptionNoWindow:Ne pas ouvrir de fenêtre au démarrage
it.all.OptionNoWindow:Non aprire la finestra all'avvio (avvio da AmiDock)
nl.all.OptionNoWindow:Geen venster openen na starten programma
+zh_CN.all.OptionNoWindow:å¯åŠ¨æ—¶ä¸æ‰“开窗å£
en.all.OptionNoQuit:Do not quit when last window closed
de.all.OptionNoQuit:Nicht Beenden beim Schließen des letzten Fensters
-fr.all.OptionNoQuit:Ne pas quitter lorsque la dernière fenêtre se trouve fermée
+fr.all.OptionNoQuit:Ne pas quitter lorsque la dernière fenêtre est fermée
it.all.OptionNoQuit:Iconifica su AmiDock alla chiusura di NetSurf
nl.all.OptionNoQuit:Stop programma niet als laatste venster worden gesloten
+zh_CN.all.OptionNoQuit:在最åŽä¸€ä¸ªçª—å£å…³é—­æ—¶ä¸é€€å‡º
# Export
#
@@ -6317,75 +8961,91 @@ de.all.Margins:Ränder
fr.all.Margins:Marges
it.all.Margins:Margini
nl.all.Margins:Marges
+zh_CN.all.Margins:è¾¹è·
+
en.all.Top:Top
de.all.Top:Oben
-fr.all.Top:Haut/Supérieur
+fr.all.Top:supérieure
it.all.Top:Superiore
nl.all.Top:Top
+zh_CN.all.Top:顶端
en.all.Left:Left
de.all.Left:Links
-fr.all.Left:Gauche
+fr.all.Left:gauche
it.all.Left:Sinistro
nl.all.Left:Links
+zh_CN.all.Left:左端
en.all.Right:Right
de.all.Right:Rechts
-fr.all.Right:Droite
+fr.all.Right:droite
it.all.Right:Destro
nl.all.Right:Rechts
+zh_CN.all.Right:å³ç«¯
en.all.Bottom:Bottom
de.all.Bottom:Unten
-fr.all.Bottom:Bas/inférieur
+fr.all.Bottom:inférieure
it.all.Bottom:Inferiore
nl.all.Bottom:Onder
+zh_CN.all.Bottom:底端
en.all.MM:mm
+de.all.MM:mm
fr.all.MM:mm
nl.all.MM:mm
it.all.MM:mm
+zh_CN.all.MM:毫米
en.all.Scaling:Scaling
de.all.Scaling:Skalierung
-fr.all.Scaling:Mise à l'échelle
+fr.all.Scaling:Mise à l’échelle
it.all.Scaling:Scala
nl.all.Scaling:Schaling
+zh_CN.all.Scaling:缩放比例
en.all.Scale:Scale
de.all.Scale:Skalieren
-fr.all.Scale:Échelle (proportion)
+fr.all.Scale:Échelle
it.all.Scale:Scalati
nl.all.Scale:Schaal
+zh_CN.all.Scale:缩放
en.all.Appearance:Appearance
de.all.Appearance:Aussehen
fr.all.Appearance:Apparence
it.all.Appearance:Aspetto
nl.all.Appearance:Verschijning
+zh_CN.all.Appearance:外观
en.all.SuppressImages:Suppress images
de.all.SuppressImages:Bilder unterbinden
fr.all.SuppressImages:Supprimer les images
it.all.SuppressImages:Sopprimi immagini
nl.all.SuppressImages:Onderdruk afbeeldingen
+zh_CN.all.SuppressImages:éšè—图åƒ
en.all.RemoveBackground:Remove background
de.all.RemoveBackground:Hintergrund entfernen
-fr.all.RemoveBackground:Retirer l'arrière-plan
+fr.all.RemoveBackground:Supprimer l’arrière plan
it.all.RemoveBackground:Rimuovi sfondo
nl.all.RemoveBackground:Verwijder achtergrond
+zh_CN.all.RemoveBackground:删除背景
en.all.FitPage:Fit page
de.all.FitPage:Seite einpassen
fr.all.FitPage:Adapter la page
it.all.FitPage:Adatta pagina
nl.all.FitPage:Maak pagina passend
+zh_CN.all.FitPage:适应页é¢
+
en.all.CompressPDF:Compress PDF
de.all.CompressPDF:PDF komprimieren
fr.all.CompressPDF:Compresser le PDF
it.all.CompressPDF:Comprimi PDF
nl.all.CompressPDF:Comprimeer PDF
+zh_CN.all.CompressPDF:压缩 PDF
en.all.SetPassword:Set password
de.all.SetPassword:Passwort festlegen
@@ -6400,38 +9060,60 @@ nl.all.SetPassword:Stel wachtwoord in
# These tokens appear to be unused at the current time.
#
-en.all.TreeHistory:NetSurf history
-de.all.TreeHistory:NetSurf Verlauf
-fr.all.TreeHistory:Historique de NetSurf
-it.all.TreeHistory:Cronologia NetSurf
-nl.all.TreeHistory:NetSurf-geschiedenis
-en.all.SaveSelect:Save
-de.all.SaveSelect:Sichern
-fr.all.SaveSelect:Sauver
-it.all.SaveSelect:Salva
-nl.all.SaveSelect:Bewaar
-en.all.ExportAs:Export as
-de.all.ExportAs:Exportieren als
-fr.all.ExportAs:Exporter sous
-it.all.ExportAs:Esporta come...
-nl.all.ExportAs:Exporteer als
-en.all.AnimImg:Animations
-de.all.AnimImg:Animationen
-fr.all.AnimImg:Animations et effets
-it.all.AnimImg:Animazioni
-nl.all.AnimImg:Animatie
-en.all.DitherImg:Dither images
-de.all.DitherImg:Bilder dithern
-fr.all.DitherImg:Tramage
-it.all.DitherImg:Immagini Dither
-nl.all.DitherImg:Benader kleur op afbeelding
-en.all.FilterImg:Smooth images
-de.all.FilterImg:Bilder weichzeichnen
-fr.all.FilterImg:Adoucir les images
-it.all.FilterImg:Immagini Smooth
-nl.all.FilterImg:Maak afbeelding vloeiend
-en.all.RenderText:Blend text to background
-de.all.RenderText:Text/Hintergrund Ãœbergang weich
-fr.all.RenderText:Fondre le texte sur l'arrière-plan
-it.all.RenderText:Sfuma testo di sfondo
-nl.all.RenderText:Harmoniseer tekst met achtergrond
+#en.all.TreeHistory:NetSurf history
+#de.all.TreeHistory:NetSurf Verlauf
+#fr.all.TreeHistory:Historique de NetSurf
+#it.all.TreeHistory:Cronologia NetSurf
+#nl.all.TreeHistory:NetSurf-geschiedenis
+#en.all.SaveSelect:Save
+#de.all.SaveSelect:Sichern
+#fr.all.SaveSelect:Sauver
+#it.all.SaveSelect:Salva
+#nl.all.SaveSelect:Bewaar
+#en.all.ExportAs:Export as
+#de.all.ExportAs:Exportieren als
+#fr.all.ExportAs:Exporter sous
+#it.all.ExportAs:Esporta come...
+#nl.all.ExportAs:Exporteer als
+#en.all.AnimImg:Animations
+#de.all.AnimImg:Animationen
+#fr.all.AnimImg:Animations et effets
+#it.all.AnimImg:Animazioni
+#nl.all.AnimImg:Animatie
+#en.all.DitherImg:Dither images
+#de.all.DitherImg:Bilder dithern
+#fr.all.DitherImg:Tramage
+#it.all.DitherImg:Immagini Dither
+#nl.all.DitherImg:Benader kleur op afbeelding
+#en.all.FilterImg:Smooth images
+#de.all.FilterImg:Bilder weichzeichnen
+#fr.all.FilterImg:Adoucir les images
+#it.all.FilterImg:Immagini Smooth
+#nl.all.FilterImg:Maak afbeelding vloeiend
+#en.all.RenderText:Blend text to background
+#de.all.RenderText:Text/Hintergrund Ãœbergang weich
+#fr.all.RenderText:Fondre le texte sur l’arrière plan
+#it.all.RenderText:Sfuma testo di sfondo
+#nl.all.RenderText:Harmoniseer tekst met achtergrond
+#en.all.TbarError:An error occurred when constructing the toolbar:
+#de.all.TbarError:Fehler beim Aufbau der Toolbar:
+#fr.all.TbarError:Une erreur s’est produite lors de la construction de la barre d’outils:
+#it.all.TbarError:Si è verificato un errore durante la costruzione della barra strumenti:
+#nl.all.TbarError:Fout bij het maken van de gereedschapbalk:
+#en.all.JNGTitle:%s (JNG image %lux%lu pixels)
+#de.all.JNGTitle:%s (JNG Bild %lux%lu pixels)
+#fr.all.JNGTitle:%s (Image JNG %lux%lu pixels)
+#it.all.JNGTitle:%s (Immagine JNG %lux%lu pixel)
+#nl.all.JNGTitle:%s (JNG-afbeelding %lux%lu punten)
+#en.all.MNGTitle:%s (MNG image %lux%lu pixels)
+#de.all.MNGTitle:%s (MNG Bild %lux%lu pixels)
+#fr.all.MNGTitle:%s (Image MNG %lux%lu pixels)
+#it.all.MNGTitle:%s (Immagine MNG %lux%lu pixel)
+#nl.all.MNGTitle:%s (MNG-afbeelding %lux%lu punten)
+#en.all.LoginLabel:A website is requesting credentials for access.
+#it.all.LoginLabel:Il sito web richiede delle credenziali per l'accesso.
+#en.gtk.gtkToolBarTitle:Toolbar custom button store
+#de.gtk.gtkToolBarTitle:Benutzerdefinierter Ort für Toolbar-Icons
+#fr.gtk.gtkToolBarTitle:Personaliser la barre d’outils
+#it.gtk.gtkToolBarTitle:Pulsanti della barra strumenti
+#nl.gtk.gtkToolBarTitle:Werkbalk aanpassen
diff --git a/resources/SearchEngines b/resources/SearchEngines
index 38e77957b..71a22697e 100644
--- a/resources/SearchEngines
+++ b/resources/SearchEngines
@@ -1,20 +1,17 @@
-Google|www.google.com|http://www.google.com/search?q=%s|http://www.google.com/favicon.ico|
-Yahoo|search.yahoo.com|http://search.yahoo.com/search?p=%s|http://www.yahoo.com/favicon.ico|
-Bing|www.bing.com|http://www.bing.com/search?q=%s|http://www.bing.com/favicon.ico|
-Business.com|www.business.com|http://www.business.com/search/rslt_default.asp?query=%s|http://www.business.com/favicon.ico|
-Omgili|www.omgili.com|http://www.omgili.com/AAAAA/%s.html|http://omgili.com/public/images/favicon.ico|
-BBC News|search.bbc.co.uk|http://search.bbc.co.uk/search?q=%s&tab=ns|http://www.bbc.co.uk/favicon.ico|
-Ubuntu Packages|packages.ubuntu.com|http://packages.ubuntu.com/search?keywords=%s|http://packages.ubuntu.com/favicon.ico|
-Creative Commons|creativecommons.org|http://creativecommons.org/?s=%s|http://creativecommons.org/favicon.ico|fixme:favicon does not work as it is served as x-icon and is a png
-Ask.com|www.ask.com|http://www.ask.com/web?q=%s|http://sp.uk.ask.com/sh/i/a14/favicon/favicon.ico|fixme:favicon is served as text/plain
-Dictionary.com|dictionary.reference.com|http://dictionary.reference.com/browse/%s?jss=0|http://dictionary.reference.com/favicon.ico|
-Youtube|www.youtube.com|http://www.youtube.com/results?search_query=%s|http://www.youtube.com/favicon.ico|
-AOL|search.aol.com|http://search.aol.com/aol/search?query=%s|http://www.aol.com/favicon.ico|
-Baidu|www.baidu.com|http://www.baidu.com/s?wd=%s|http://www.baidu.com/favicon.ico|
-Amazon|www.amazon.com|http://www.amazon.com/s/ref=nb_ss_gw?field-keywords=%s|http://www.amazon.com/favicon.ico|
-Ebay|shop.ebay.com|http://shop.ebay.com/items/%s|http://www.ebay.com/favicon.ico|
-IMDB|www.imdb.com|http://www.imdb.com/find?q=%s|http://www.imdb.com/favicon.ico|
-ESPN|search.espn.go.com|http://search.espn.go.com/%s/|http://www.espn.go.com/favicon.ico|
-Wikipedia|en.wikipedia.org|http://en.wikipedia.org/w/index.php?title=Special%%3ASearch&search=%s|http://en.wikipedia.org/favicon.ico|
-DuckDuckGo|www.duckduckgo.com|http://www.duckduckgo.com/html/?q=%s|http://www.duckduckgo.com/favicon.ico|fixme:Their ico upsets the current implementation
-Seeks|www.seeks-project.info|https://www.seeks-project.info/search.php/search?q=%s|http://www.seeks-project.info/search.php/public/images/seek_icon_32x32_transparent.png|fixme:they have no icon
+Google|www.google.com|https://www.google.com/search?q=%s|https://www.google.com/favicon.ico|
+Yahoo|search.yahoo.com|https://search.yahoo.com/search?p=%s|https://www.yahoo.com/favicon.ico|
+Bing|www.bing.com|https://www.bing.com/search?q=%s|https://www.bing.com/favicon.ico|
+DuckDuckGo|www.duckduckgo.com|https://www.duckduckgo.com/html/?q=%s|https://www.duckduckgo.com/favicon.ico|fixme:Their ico upsets the current implementation
+Wikipedia|en.wikipedia.org|https://en.wikipedia.org/w/index.php?title=Special%3ASearch&search=%s|https://en.wikipedia.org/favicon.ico|
+BBC News|search.bbc.co.uk|https://search.bbc.co.uk/search?q=%s&tab=ns|https://www.bbc.co.uk/favicon.ico|
+Ubuntu Packages|packages.ubuntu.com|https://packages.ubuntu.com/search?keywords=%s|https://packages.ubuntu.com/favicon.ico|
+Creative Commons|creativecommons.org|https://creativecommons.org/?s=%s|https://creativecommons.org/favicon.ico|fixme:favicon does not work as it is served as x-icon and is a png
+Ask.com|www.ask.com|https://www.ask.com/web?q=%s|https://sp.uk.ask.com/sh/i/a14/favicon/favicon.ico|fixme:favicon is served as text/plain
+Dictionary.com|dictionary.reference.com|https://dictionary.reference.com/browse/%s?jss=0|https://dictionary.reference.com/favicon.ico|
+Youtube|www.youtube.com|https://www.youtube.com/results?search_query=%s|https://www.youtube.com/favicon.ico|
+AOL|search.aol.com|https://search.aol.com/aol/search?query=%s|https://www.aol.com/favicon.ico|
+Baidu|www.baidu.com|https://www.baidu.com/s?wd=%s|https://www.baidu.com/favicon.ico|
+Amazon|www.amazon.com|https://www.amazon.com/s/ref=nb_ss_gw?field-keywords=%s|https://www.amazon.com/favicon.ico|
+Ebay|www.ebay.com|https://www.ebay.com/sch/i.html?_nkw=%s|https://www.ebay.com/favicon.ico|
+IMDB|www.imdb.com|https://www.imdb.com/find?q=%s|https://www.imdb.com/favicon.ico|
+Stract|stract.com|https://stract.com/search?q=%s|https://stract.com/favicon.ico|
diff --git a/resources/ca-bundle b/resources/ca-bundle
index 39ba33683..fd61b8b49 100644
--- a/resources/ca-bundle
+++ b/resources/ca-bundle
@@ -1,7 +1,7 @@
##
## Bundle of CA Root Certificates
##
-## Certificate data from Mozilla as of: Wed Sep 20 03:12:05 2017 GMT
+## Certificate data from Mozilla as of: Tue Dec 19 23:28:07 2023 GMT
##
## This is a bundle of X.509 certificates of public Certificate Authorities
## (CA). These were automatically extracted from Mozilla's root certificates
@@ -13,8 +13,8 @@
## an Apache+mod_ssl webserver for SSL client authentication.
## Just configure this file as the SSLCACertificateFile.
##
-## Conversion done with mk-ca-bundle.pl version 1.27.
-## SHA256: 2b2dbe5244e0047e088c597998883a913f6c5fffd1cb5c0fe5a368c8466cb2ec
+## Conversion done with mk-ca-bundle.pl version 1.29.
+## SHA256: 1970dd65858925d68498d2356aea6d03f764422523c5887deca8ce3ba9e1f845
##
@@ -39,52 +39,6 @@ hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
-----END CERTIFICATE-----
-GlobalSign Root CA - R2
-=======================
------BEGIN CERTIFICATE-----
-MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
-YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
-bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
-aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
-bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6
-ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp
-s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN
-S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL
-TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C
-ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
-FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i
-YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN
-BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
-9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu
-01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7
-9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
-TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
------END CERTIFICATE-----
-
-Verisign Class 3 Public Primary Certification Authority - G3
-============================================================
------BEGIN CERTIFICATE-----
-MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
-UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
-cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
-IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
-dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
-CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
-dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
-cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg
-Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1
-EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc
-cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw
-EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj
-055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
-ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f
-j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
-/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0
-xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa
-t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
------END CERTIFICATE-----
-
Entrust.net Premium 2048 Secure Server CA
=========================================
-----BEGIN CERTIFICATE-----
@@ -130,30 +84,6 @@ Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
-----END CERTIFICATE-----
-AddTrust External Root
-======================
------BEGIN CERTIFICATE-----
-MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
-QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD
-VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw
-NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU
-cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg
-Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821
-+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw
-Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo
-aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy
-2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7
-7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P
-BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL
-VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk
-VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB
-IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl
-j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
-6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355
-e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u
-G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
------END CERTIFICATE-----
-
Entrust Root Certification Authority
====================================
-----BEGIN CERTIFICATE-----
@@ -180,128 +110,6 @@ W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
-----END CERTIFICATE-----
-GeoTrust Global CA
-==================
------BEGIN CERTIFICATE-----
-MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
-Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw
-MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
-LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo
-BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet
-8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc
-T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU
-vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD
-AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk
-DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q
-zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4
-d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2
-mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p
-XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm
-Mw==
------END CERTIFICATE-----
-
-GeoTrust Universal CA
-=====================
------BEGIN CERTIFICATE-----
-MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
-R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1
-MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu
-Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
-ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t
-JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e
-RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs
-7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d
-8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V
-qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga
-Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB
-Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu
-KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08
-ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0
-XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB
-hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
-aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2
-qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL
-oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK
-xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF
-KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2
-DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK
-xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU
-p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI
-P/rmMuGNG2+k5o7Y+SlIis5z/iw=
------END CERTIFICATE-----
-
-GeoTrust Universal CA 2
-=======================
------BEGIN CERTIFICATE-----
-MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
-R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0
-MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg
-SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA
-A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0
-DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17
-j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q
-JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a
-QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2
-WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP
-20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn
-ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC
-SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG
-8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2
-+/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E
-BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
-dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ
-4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+
-mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq
-A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg
-Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP
-pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d
-FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp
-gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm
-X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
------END CERTIFICATE-----
-
-Visa eCommerce Root
-===================
------BEGIN CERTIFICATE-----
-MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG
-EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug
-QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2
-WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm
-VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv
-bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL
-F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b
-RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0
-TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI
-/k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs
-GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG
-MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc
-CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW
-YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz
-zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu
-YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt
-398znM/jra6O1I7mT1GvFpLgXPYHDw==
------END CERTIFICATE-----
-
-Certum Root CA
-==============
------BEGIN CERTIFICATE-----
-MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK
-ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla
-Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u
-by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x
-wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL
-kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ
-89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K
-Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P
-NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq
-hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+
-GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg
-GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/
-0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS
-qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw==
------END CERTIFICATE-----
-
Comodo AAA Services root
========================
-----BEGIN CERTIFICATE-----
@@ -326,38 +134,6 @@ Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
-----END CERTIFICATE-----
-QuoVadis Root CA
-================
------BEGIN CERTIFICATE-----
-MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE
-ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
-eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz
-MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp
-cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD
-EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
-AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk
-J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL
-F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL
-YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen
-AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w
-PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y
-ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7
-MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj
-YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs
-ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
-Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW
-Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu
-BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw
-FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0
-aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6
-tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo
-fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul
-LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x
-gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi
-5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi
-5nrQNiOKSnQ2+Q==
------END CERTIFICATE-----
-
QuoVadis Root CA 2
==================
-----BEGIN CERTIFICATE-----
@@ -424,101 +200,6 @@ vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
-----END CERTIFICATE-----
-Security Communication Root CA
-==============================
------BEGIN CERTIFICATE-----
-MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
-U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
-HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
-U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
-ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw
-8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM
-DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX
-5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd
-DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2
-JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw
-DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g
-0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a
-mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ
-s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ
-6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi
-FL39vmwLAw==
------END CERTIFICATE-----
-
-Sonera Class 2 Root CA
-======================
------BEGIN CERTIFICATE-----
-MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG
-U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw
-NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh
-IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3
-/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT
-dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG
-f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P
-tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH
-nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT
-XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt
-0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI
-cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph
-Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx
-EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH
-llpwrN9M
------END CERTIFICATE-----
-
-Camerfirma Chambers of Commerce Root
-====================================
------BEGIN CERTIFICATE-----
-MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
-QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
-ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx
-NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp
-cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn
-MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC
-AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU
-xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH
-NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW
-DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV
-d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud
-EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v
-cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P
-AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh
-bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD
-VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz
-aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi
-fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD
-L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN
-UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n
-ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1
-erfutGWaIZDgqtCYvDi1czyL+Nw=
------END CERTIFICATE-----
-
-Camerfirma Global Chambersign Root
-==================================
------BEGIN CERTIFICATE-----
-MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
-QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
-ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx
-NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt
-YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg
-MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw
-ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J
-1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O
-by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl
-6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c
-8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/
-BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j
-aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B
-Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj
-aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y
-ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh
-bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA
-PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y
-gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ
-PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4
-IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes
-t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A==
------END CERTIFICATE-----
-
XRamp Global CA Root
====================
-----BEGIN CERTIFICATE-----
@@ -591,77 +272,6 @@ KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
QBFGmh95DmK/D5fs4C8fF5Q=
-----END CERTIFICATE-----
-StartCom Certification Authority
-================================
------BEGIN CERTIFICATE-----
-MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
-U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
-ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
-NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
-LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
-U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
-ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
-o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
-Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
-eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
-2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
-6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
-osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
-untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
-UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
-37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
-FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0
-Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj
-YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH
-AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw
-Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg
-U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5
-LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl
-cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh
-cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT
-dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC
-AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh
-3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm
-vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk
-fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3
-fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ
-EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
-yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl
-1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/
-lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro
-g14=
------END CERTIFICATE-----
-
-Taiwan GRCA
-===========
------BEGIN CERTIFICATE-----
-MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG
-EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X
-DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv
-dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD
-ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN
-w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5
-BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O
-1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO
-htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov
-J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7
-Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t
-B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB
-O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8
-lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV
-HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2
-09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
-TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj
-Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2
-Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU
-D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz
-DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk
-Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk
-7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ
-CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy
-+fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS
------END CERTIFICATE-----
-
DigiCert Assured ID Root CA
===========================
-----BEGIN CERTIFICATE-----
@@ -728,72 +338,6 @@ mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
-----END CERTIFICATE-----
-Certplus Class 2 Primary CA
-===========================
------BEGIN CERTIFICATE-----
-MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE
-BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN
-OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy
-dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
-ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR
-5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ
-Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO
-YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e
-e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME
-CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ
-YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t
-L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD
-P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R
-TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+
-7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW
-//1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
-l7+ijrRU
------END CERTIFICATE-----
-
-DST Root CA X3
-==============
------BEGIN CERTIFICATE-----
-MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK
-ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X
-DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1
-cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD
-ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT
-rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9
-UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy
-xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d
-utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T
-AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ
-MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug
-dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE
-GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw
-RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS
-fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
------END CERTIFICATE-----
-
-DST ACES CA X6
-==============
------BEGIN CERTIFICATE-----
-MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG
-EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT
-MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha
-MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE
-CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC
-AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI
-DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa
-pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow
-GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy
-MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud
-EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu
-Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy
-dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU
-CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2
-5FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t
-Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq
-nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs
-vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3
-oKfN5XozNmr6mis=
------END CERTIFICATE-----
-
SwissSign Gold CA - G2
======================
-----BEGIN CERTIFICATE-----
@@ -856,78 +400,6 @@ DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub
DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
-----END CERTIFICATE-----
-GeoTrust Primary Certification Authority
-========================================
------BEGIN CERTIFICATE-----
-MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG
-EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD
-ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx
-CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ
-cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN
-b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9
-nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge
-RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt
-tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
-AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI
-hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K
-Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN
-NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa
-Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG
-1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
------END CERTIFICATE-----
-
-thawte Primary Root CA
-======================
------BEGIN CERTIFICATE-----
-MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE
-BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
-aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
-cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3
-MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg
-SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv
-KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT
-FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs
-oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ
-1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc
-q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K
-aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p
-afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
-VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF
-AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE
-uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
-xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89
-jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH
-z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA==
------END CERTIFICATE-----
-
-VeriSign Class 3 Public Primary Certification Authority - G5
-============================================================
------BEGIN CERTIFICATE-----
-MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
-BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
-ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
-IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
-ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
-yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
-biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
-dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
-YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
-j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
-Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
-Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
-fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
-BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
-Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
-aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
-SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
-X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
-KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
-Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
-ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
------END CERTIFICATE-----
-
SecureTrust CA
==============
-----BEGIN CERTIFICATE-----
@@ -996,29 +468,6 @@ IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
-----END CERTIFICATE-----
-Network Solutions Certificate Authority
-=======================================
------BEGIN CERTIFICATE-----
-MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG
-EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr
-IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx
-MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
-MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
-CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx
-jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT
-aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT
-crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc
-/Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB
-AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP
-BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv
-bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA
-A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q
-4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/
-GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
-wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD
-ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
------END CERTIFICATE-----
-
COMODO ECC Certification Authority
==================================
-----BEGIN CERTIFICATE-----
@@ -1036,50 +485,6 @@ FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
-----END CERTIFICATE-----
-Security Communication EV RootCA1
-=================================
------BEGIN CERTIFICATE-----
-MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
-U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh
-dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE
-BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl
-Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
-AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO
-/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX
-WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z
-ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4
-bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK
-9U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
-SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm
-iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG
-Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW
-mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW
-T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490
------END CERTIFICATE-----
-
-OISTE WISeKey Global Root GA CA
-===============================
------BEGIN CERTIFICATE-----
-MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE
-BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG
-A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH
-bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD
-VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw
-IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5
-IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9
-Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg
-Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD
-d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ
-/yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R
-LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
-AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
-KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm
-MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4
-+vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
-hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY
-okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0=
------END CERTIFICATE-----
-
Certigna
========
-----BEGIN CERTIFICATE-----
@@ -1102,50 +507,6 @@ PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
-----END CERTIFICATE-----
-Deutsche Telekom Root CA 2
-==========================
------BEGIN CERTIFICATE-----
-MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT
-RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG
-A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5
-MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G
-A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS
-b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5
-bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI
-KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY
-AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK
-Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV
-jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV
-HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr
-E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy
-zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8
-rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G
-dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
-Cm26OWMohpLzGITY+9HPBVZkVw==
------END CERTIFICATE-----
-
-Cybertrust Global Root
-======================
------BEGIN CERTIFICATE-----
-MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li
-ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4
-MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD
-ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
-+Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW
-0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL
-AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin
-89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT
-8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP
-BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2
-MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G
-A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO
-lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi
-5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2
-hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T
-X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
-WL1WMRJOEcgh4LMRkWXbtKaIOM5V
------END CERTIFICATE-----
-
ePKI Root Certification Authority
=================================
-----BEGIN CERTIFICATE-----
@@ -1177,34 +538,6 @@ sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD
BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw=
-----END CERTIFICATE-----
-T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3
-=============================================================================================================================
------BEGIN CERTIFICATE-----
-MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH
-DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q
-aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry
-b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV
-BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg
-S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4
-MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl
-IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF
-n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl
-IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft
-dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl
-cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B
-AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO
-Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1
-xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR
-6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL
-hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd
-BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
-MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4
-N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT
-y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh
-LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M
-dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI=
------END CERTIFICATE-----
-
certSIGN ROOT CA
================
-----BEGIN CERTIFICATE-----
@@ -1225,136 +558,6 @@ vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
-----END CERTIFICATE-----
-GeoTrust Primary Certification Authority - G3
-=============================================
------BEGIN CERTIFICATE-----
-MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE
-BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0
-IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy
-eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz
-NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo
-YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT
-LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI
-hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j
-K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE
-c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C
-IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu
-dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC
-MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr
-2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9
-cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE
-Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
-AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s
-t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt
------END CERTIFICATE-----
-
-thawte Primary Root CA - G2
-===========================
------BEGIN CERTIFICATE-----
-MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC
-VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu
-IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg
-Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV
-MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG
-b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt
-IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS
-LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5
-8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
-mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN
-G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K
-rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
------END CERTIFICATE-----
-
-thawte Primary Root CA - G3
-===========================
------BEGIN CERTIFICATE-----
-MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE
-BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
-aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
-cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w
-ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
-d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD
-VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG
-A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
-MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At
-P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC
-+BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY
-7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW
-vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E
-BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ
-KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK
-A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
-t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC
-8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm
-er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A=
------END CERTIFICATE-----
-
-GeoTrust Primary Certification Authority - G2
-=============================================
------BEGIN CERTIFICATE-----
-MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC
-VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu
-Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD
-ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1
-OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
-MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl
-b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG
-BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc
-KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD
-VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+
-EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m
-ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2
-npaqBA+K
------END CERTIFICATE-----
-
-VeriSign Universal Root Certification Authority
-===============================================
------BEGIN CERTIFICATE-----
-MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE
-BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
-ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
-IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u
-IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV
-UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
-cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
-IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0
-aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj
-1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP
-MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72
-9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I
-AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR
-tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G
-CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O
-a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
-DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3
-Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx
-Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx
-P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P
-wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4
-mJO37M2CYfE45k+XmCpajQ==
------END CERTIFICATE-----
-
-VeriSign Class 3 Public Primary Certification Authority - G4
-============================================================
------BEGIN CERTIFICATE-----
-MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC
-VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3
-b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz
-ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj
-YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL
-MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU
-cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo
-b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5
-IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8
-Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz
-rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB
-/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw
-HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u
-Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD
-A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx
-AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
------END CERTIFICATE-----
-
NetLock Arany (Class Gold) Főtanúsítvány
========================================
-----BEGIN CERTIFICATE-----
@@ -1379,58 +582,6 @@ NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
-----END CERTIFICATE-----
-Staat der Nederlanden Root CA - G2
-==================================
------BEGIN CERTIFICATE-----
-MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
-CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
-Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC
-TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
-ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ
-5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn
-vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj
-CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil
-e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR
-OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI
-CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65
-48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi
-trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737
-qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB
-AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC
-ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
-HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA
-A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz
-+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj
-f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN
-kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk
-CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF
-URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb
-CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h
-oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV
-IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm
-66+KAQ==
------END CERTIFICATE-----
-
-Hongkong Post Root CA 1
-=======================
------BEGIN CERTIFICATE-----
-MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT
-DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx
-NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n
-IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF
-AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1
-ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr
-auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh
-qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY
-V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV
-HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i
-h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio
-l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei
-IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps
-T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT
-c4afU9hDDl3WY4JxHYB0yvbiAmvZWg==
------END CERTIFICATE-----
-
SecureSign RootCA11
===================
-----BEGIN CERTIFICATE-----
@@ -1452,37 +603,6 @@ y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061
lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I=
-----END CERTIFICATE-----
-ACEDICOM Root
-=============
------BEGIN CERTIFICATE-----
-MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UEAwwNQUNFRElD
-T00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMB4XDTA4
-MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEWMBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoG
-A1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEF
-AAOCAg8AMIICCgKCAgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHk
-WLn709gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7XBZXehuD
-YAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5PGrjm6gSSrj0RuVFCPYew
-MYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAKt0SdE3QrwqXrIhWYENiLxQSfHY9g5QYb
-m8+5eaA9oiM/Qj9r+hwDezCNzmzAv+YbX79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbk
-HQl/Sog4P75n/TSW9R28MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTT
-xKJxqvQUfecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI2Sf2
-3EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyHK9caUPgn6C9D4zq9
-2Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEaeZAwUswdbxcJzbPEHXEUkFDWug/Fq
-TYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz
-4SsrSbbXc6GqlPUB53NlTKxQMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU
-9QHnc2VMrFAwRAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv
-bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWImfQwng4/F9tqg
-aHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3gvoFNTPhNahXwOf9jU8/kzJP
-eGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKeI6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1Pwk
-zQSulgUV1qzOMPPKC8W64iLgpq0i5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1
-ThCojz2GuHURwCRiipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oI
-KiMnMCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZo5NjEFIq
-nxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6zqylfDJKZ0DcMDQj3dcE
-I2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacNGHk0vFQYXlPKNFHtRQrmjseCNj6nOGOp
-MCwXEGCSn1WHElkQwg9naRHMTh5+Spqtr0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3o
-tkYNbn5XOmeUwssfnHdKZ05phkOTOPu220+DkdRgfks+KzgHVZhepA==
------END CERTIFICATE-----
-
Microsec e-Szigno Root CA 2009
==============================
-----BEGIN CERTIFICATE-----
@@ -1528,39 +648,6 @@ YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
kpeDMdmztcpHWD9f
-----END CERTIFICATE-----
-Autoridad de Certificacion Firmaprofesional CIF A62634068
-=========================================================
------BEGIN CERTIFICATE-----
-MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA
-BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
-MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw
-QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
-NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
-Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
-B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
-7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
-ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
-plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
-MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
-LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
-bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
-vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud
-EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH
-DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
-cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA
-bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx
-ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx
-51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk
-R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP
-T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f
-Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl
-osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR
-crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR
-saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD
-KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi
-6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
------END CERTIFICATE-----
-
Izenpe.com
==========
-----BEGIN CERTIFICATE-----
@@ -1593,82 +680,6 @@ Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
-----END CERTIFICATE-----
-Chambers of Commerce Root - 2008
-================================
------BEGIN CERTIFICATE-----
-MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD
-MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
-bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
-QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy
-Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl
-ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF
-EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl
-cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
-AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA
-XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj
-h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/
-ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk
-NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g
-D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331
-lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ
-0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
-ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2
-EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI
-G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ
-BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh
-bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh
-bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC
-CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH
-AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1
-wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH
-3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU
-RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6
-M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1
-YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF
-9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK
-zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG
-nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
-OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ
------END CERTIFICATE-----
-
-Global Chambersign Root - 2008
-==============================
------BEGIN CERTIFICATE-----
-MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD
-MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
-bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
-QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx
-NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg
-Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ
-QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
-aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf
-VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf
-XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0
-ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB
-/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA
-TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M
-H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe
-Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF
-HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
-wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB
-AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT
-BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE
-BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm
-aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm
-aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp
-1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0
-dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG
-/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6
-ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s
-dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg
-9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH
-foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du
-qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr
-P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq
-c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
-09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
------END CERTIFICATE-----
-
Go Daddy Root Certificate Authority - G2
========================================
-----BEGIN CERTIFICATE-----
@@ -1843,37 +854,6 @@ Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
-----END CERTIFICATE-----
-Certinomis - Autorité Racine
-============================
------BEGIN CERTIFICATE-----
-MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK
-Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg
-LSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkG
-A1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYw
-JAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQAD
-ggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jYF1AMnmHa
-wE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N8y4oH3DfVS9O7cdxbwly
-Lu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWerP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw
-2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92N
-jMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9q
-c1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTC
-lrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNb
-xxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g
-530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna
-4NH4+ej9Uji29YnfAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
-A1UdDgQWBBQNjLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ
-KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/x
-WqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva
-R6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40
-nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1B
-CxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjv
-JL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG5ERQL1TE
-qkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWqpdEdnV1j6CTmNhTih60b
-WfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XSAPCjDuGtbkD326C00EauFddE
-wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/
-vgt2Fl43N+bYdJeimUV5
------END CERTIFICATE-----
-
TWCA Root Certification Authority
=================================
-----BEGIN CERTIFICATE-----
@@ -1916,60 +896,6 @@ tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
-----END CERTIFICATE-----
-EC-ACC
-======
------BEGIN CERTIFICATE-----
-MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE
-BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w
-ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD
-VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE
-CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT
-BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7
-MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt
-SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl
-Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh
-cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK
-w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT
-ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4
-HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a
-E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw
-0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
-BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD
-VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0
-Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l
-dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ
-lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa
-Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe
-l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2
-E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D
-5EI=
------END CERTIFICATE-----
-
-Hellenic Academic and Research Institutions RootCA 2011
-=======================================================
------BEGIN CERTIFICATE-----
-MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
-O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
-aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
-IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
-AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
-IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
-IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
-AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
-1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
-71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
-8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
-3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
-MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
-MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
-b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
-XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
-TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
-/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
-7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
------END CERTIFICATE-----
-
Actalis Authentication Root CA
==============================
-----BEGIN CERTIFICATE-----
@@ -2001,96 +927,6 @@ OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9
vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
-----END CERTIFICATE-----
-Trustis FPS Root CA
-===================
------BEGIN CERTIFICATE-----
-MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG
-EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290
-IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV
-BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ
-KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ
-RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk
-H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa
-cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt
-o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA
-AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd
-BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c
-GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC
-yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P
-8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV
-l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl
-iB6XzCGcKQENZetX2fNXlrtIzYE=
------END CERTIFICATE-----
-
-StartCom Certification Authority
-================================
------BEGIN CERTIFICATE-----
-MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
-U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
-ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
-NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
-LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
-U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
-ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
-o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
-Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
-eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
-2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
-6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
-osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
-untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
-UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
-37uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
-VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ
-Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0
-dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu
-c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv
-bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0
-aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0
-aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t
-L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG
-cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5
-fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm
-N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN
-Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T
-tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX
-e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA
-2MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs
-HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE
-JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib
-D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8=
------END CERTIFICATE-----
-
-StartCom Certification Authority G2
-===================================
------BEGIN CERTIFICATE-----
-MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
-U3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
-RzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UE
-ChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3Jp
-dHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8O
-o1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsDvfOpL9HG
-4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnooD/Uefyf3lLE3PbfHkffi
-Aez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/Q0kGi4xDuFby2X8hQxfqp0iVAXV16iul
-Q5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbs
-O+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8H
-vKTlXcxNnw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4L
-nMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iS
-FGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMa
-z6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8E
-BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJ
-KoZIhvcNAQELBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K
-2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbk
-J4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+
-JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG
-/+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTc
-nIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/Xld
-blhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5lIxKVCCIc
-l85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoohdVddLHRDiBYmxOlsGOm
-7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjRkcfGEvRM/TAXw8HaOFvjqerm
-obp573PYtlNXLfbQ4ddI
------END CERTIFICATE-----
-
Buypass Class 2 Root CA
=======================
-----BEGIN CERTIFICATE-----
@@ -2173,55 +1009,6 @@ P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==
-----END CERTIFICATE-----
-EE Certification Centre Root CA
-===============================
------BEGIN CERTIFICATE-----
-MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
-EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy
-dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw
-MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB
-UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy
-ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB
-DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM
-TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2
-rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw
-93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN
-P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T
-AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ
-MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF
-BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj
-xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM
-lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
-uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU
-3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM
-dcGWxZ0=
------END CERTIFICATE-----
-
-TURKTRUST Certificate Services Provider Root 2007
-=================================================
------BEGIN CERTIFICATE-----
-MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOcUktUUlVTVCBF
-bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP
-MA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg
-QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4X
-DTA3MTIyNTE4MzcxOVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxl
-a3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMCVFIxDzAN
-BgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp
-bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4gKGMpIEFyYWzEsWsgMjAwNzCCASIw
-DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9N
-YvDdE3ePYakqtdTyuTFYKTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQv
-KUmi8wUG+7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveGHtya
-KhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6PIzdezKKqdfcYbwnT
-rqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M733WB2+Y8a+xwXrXgTW4qhe04MsC
-AwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHkYb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAP
-BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/s
-Px+EnWVUXKgWAkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I
-aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5mxRZNTZPz/OO
-Xl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsaXRik7r4EW5nVcV9VZWRi1aKb
-BFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZqxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAK
-poRq0Tl9
------END CERTIFICATE-----
-
D-TRUST Root Class 3 CA 2 2009
==============================
-----BEGIN CERTIFICATE-----
@@ -2271,84 +1058,6 @@ NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv
w9y4AyHqnxbxLFS1
-----END CERTIFICATE-----
-PSCProcert
-==========
------BEGIN CERTIFICATE-----
-MIIJhjCCB26gAwIBAgIBCzANBgkqhkiG9w0BAQsFADCCAR4xPjA8BgNVBAMTNUF1dG9yaWRhZCBk
-ZSBDZXJ0aWZpY2FjaW9uIFJhaXogZGVsIEVzdGFkbyBWZW5lem9sYW5vMQswCQYDVQQGEwJWRTEQ
-MA4GA1UEBxMHQ2FyYWNhczEZMBcGA1UECBMQRGlzdHJpdG8gQ2FwaXRhbDE2MDQGA1UEChMtU2lz
-dGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMUMwQQYDVQQLEzpTdXBl
-cmludGVuZGVuY2lhIGRlIFNlcnZpY2lvcyBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMSUw
-IwYJKoZIhvcNAQkBFhZhY3JhaXpAc3VzY2VydGUuZ29iLnZlMB4XDTEwMTIyODE2NTEwMFoXDTIw
-MTIyNTIzNTk1OVowgdExJjAkBgkqhkiG9w0BCQEWF2NvbnRhY3RvQHByb2NlcnQubmV0LnZlMQ8w
-DQYDVQQHEwZDaGFjYW8xEDAOBgNVBAgTB01pcmFuZGExKjAoBgNVBAsTIVByb3ZlZWRvciBkZSBD
-ZXJ0aWZpY2Fkb3MgUFJPQ0VSVDE2MDQGA1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZp
-Y2FjaW9uIEVsZWN0cm9uaWNhMQswCQYDVQQGEwJWRTETMBEGA1UEAxMKUFNDUHJvY2VydDCCAiIw
-DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANW39KOUM6FGqVVhSQ2oh3NekS1wwQYalNo97BVC
-wfWMrmoX8Yqt/ICV6oNEolt6Vc5Pp6XVurgfoCfAUFM+jbnADrgV3NZs+J74BCXfgI8Qhd19L3uA
-3VcAZCP4bsm+lU/hdezgfl6VzbHvvnpC2Mks0+saGiKLt38GieU89RLAu9MLmV+QfI4tL3czkkoh
-RqipCKzx9hEC2ZUWno0vluYC3XXCFCpa1sl9JcLB/KpnheLsvtF8PPqv1W7/U0HU9TI4seJfxPmO
-EO8GqQKJ/+MMbpfg353bIdD0PghpbNjU5Db4g7ayNo+c7zo3Fn2/omnXO1ty0K+qP1xmk6wKImG2
-0qCZyFSTXai20b1dCl53lKItwIKOvMoDKjSuc/HUtQy9vmebVOvh+qBa7Dh+PsHMosdEMXXqP+UH
-0quhJZb25uSgXTcYOWEAM11G1ADEtMo88aKjPvM6/2kwLkDd9p+cJsmWN63nOaK/6mnbVSKVUyqU
-td+tFjiBdWbjxywbk5yqjKPK2Ww8F22c3HxT4CAnQzb5EuE8XL1mv6JpIzi4mWCZDlZTOpx+FIyw
-Bm/xhnaQr/2v/pDGj59/i5IjnOcVdo/Vi5QTcmn7K2FjiO/mpF7moxdqWEfLcU8UC17IAggmosvp
-r2uKGcfLFFb14dq12fy/czja+eevbqQ34gcnAgMBAAGjggMXMIIDEzASBgNVHRMBAf8ECDAGAQH/
-AgEBMDcGA1UdEgQwMC6CD3N1c2NlcnRlLmdvYi52ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAz
-Ni0wMB0GA1UdDgQWBBRBDxk4qpl/Qguk1yeYVKIXTC1RVDCCAVAGA1UdIwSCAUcwggFDgBStuyId
-xuDSAaj9dlBSk+2YwU2u06GCASakggEiMIIBHjE+MDwGA1UEAxM1QXV0b3JpZGFkIGRlIENlcnRp
-ZmljYWNpb24gUmFpeiBkZWwgRXN0YWRvIFZlbmV6b2xhbm8xCzAJBgNVBAYTAlZFMRAwDgYDVQQH
-EwdDYXJhY2FzMRkwFwYDVQQIExBEaXN0cml0byBDYXBpdGFsMTYwNAYDVQQKEy1TaXN0ZW1hIE5h
-Y2lvbmFsIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExQzBBBgNVBAsTOlN1cGVyaW50ZW5k
-ZW5jaWEgZGUgU2VydmljaW9zIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExJTAjBgkqhkiG
-9w0BCQEWFmFjcmFpekBzdXNjZXJ0ZS5nb2IudmWCAQowDgYDVR0PAQH/BAQDAgEGME0GA1UdEQRG
-MESCDnByb2NlcnQubmV0LnZloBUGBWCGXgIBoAwMClBTQy0wMDAwMDKgGwYFYIZeAgKgEgwQUklG
-LUotMzE2MzUzNzMtNzB2BgNVHR8EbzBtMEagRKBChkBodHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52
-ZS9sY3IvQ0VSVElGSUNBRE8tUkFJWi1TSEEzODRDUkxERVIuY3JsMCOgIaAfhh1sZGFwOi8vYWNy
-YWl6LnN1c2NlcnRlLmdvYi52ZTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9v
-Y3NwLnN1c2NlcnRlLmdvYi52ZTBBBgNVHSAEOjA4MDYGBmCGXgMBAjAsMCoGCCsGAQUFBwIBFh5o
-dHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9kcGMwDQYJKoZIhvcNAQELBQADggIBACtZ6yKZu4Sq
-T96QxtGGcSOeSwORR3C7wJJg7ODU523G0+1ng3dS1fLld6c2suNUvtm7CpsR72H0xpkzmfWvADmN
-g7+mvTV+LFwxNG9s2/NkAZiqlCxB3RWGymspThbASfzXg0gTB1GEMVKIu4YXx2sviiCtxQuPcD4q
-uxtxj7mkoP3YldmvWb8lK5jpY5MvYB7Eqvh39YtsL+1+LrVPQA3uvFd359m21D+VJzog1eWuq2w1
-n8GhHVnchIHuTQfiSLaeS5UtQbHh6N5+LwUeaO6/u5BlOsju6rEYNxxik6SgMexxbJHmpHmJWhSn
-FFAFTKQAVzAswbVhltw+HoSvOULP5dAssSS830DD7X9jSr3hTxJkhpXzsOfIt+FTvZLm8wyWuevo
-5pLtp4EJFAv8lXrPj9Y0TzYS3F7RNHXGRoAvlQSMx4bEqCaJqD8Zm4G7UaRKhqsLEQ+xrmNTbSjq
-3TNWOByyrYDT13K9mmyZY+gAu0F2BbdbmRiKw7gSXFbPVgx96OLP7bx0R/vu0xdOIk9W/1DzLuY5
-poLWccret9W6aAjtmcz9opLLabid+Qqkpj5PkygqYWwHJgD/ll9ohri4zspV4KuxPX+Y1zMOWj3Y
-eMLEYC/HYvBhkdI4sPaeVdtAgAUSM84dkpvRabP/v/GSCmE1P93+hvS84Bpxs2Km
------END CERTIFICATE-----
-
-CA Disig Root R1
-================
------BEGIN CERTIFICATE-----
-MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNVBAYTAlNLMRMw
-EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
-ZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQyMDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sx
-EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
-c2lnIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy
-3QRkD2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/oOI7bm+V8
-u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3AfQ+lekLZWnDZv6fXARz2
-m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJeIgpFy4QxTaz+29FHuvlglzmxZcfe+5nk
-CiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8noc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTa
-YVKvJrT1cU/J19IG32PK/yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6
-vpmumwKjrckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD3AjL
-LhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE7cderVC6xkGbrPAX
-ZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkCyC2fg69naQanMVXVz0tv/wQFx1is
-XxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLdqvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNV
-HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ
-04IwDQYJKoZIhvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR
-xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaASfX8MPWbTx9B
-LxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXoHqJPYNcHKfyyo6SdbhWSVhlM
-CrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpBemOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5Gfb
-VSUZP/3oNn6z4eGBrxEWi1CXYBmCAMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85
-YmLLW1AL14FABZyb7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKS
-ds+xDzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvkF7mGnjix
-lAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqFa3qdnom2piiZk4hA9z7N
-UaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsTQ6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJ
-a7+h89n07eLw4+1knj0vllJPgFOL
------END CERTIFICATE-----
-
CA Disig Root R2
================
-----BEGIN CERTIFICATE-----
@@ -2478,40 +1187,6 @@ Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems
WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
-----END CERTIFICATE-----
-E-Tugra Certification Authority
-===============================
------BEGIN CERTIFICATE-----
-MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w
-DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls
-ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN
-ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw
-NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx
-QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl
-cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD
-DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
-MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd
-hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K
-CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g
-ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ
-BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0
-E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz
-rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq
-jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn
-rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5
-dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB
-/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG
-MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK
-kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO
-XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807
-VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo
-a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc
-dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV
-KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT
-Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0
-8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G
-C7TbO6Orb1wdtn7os4I07QZcJA==
------END CERTIFICATE-----
-
T-TeleSec GlobalRoot Class 2
============================
-----BEGIN CERTIFICATE-----
@@ -2752,66 +1427,6 @@ G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP
82Z+
-----END CERTIFICATE-----
-WoSign
-======
------BEGIN CERTIFICATE-----
-MIIFdjCCA16gAwIBAgIQXmjWEXGUY1BWAGjzPsnFkTANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQG
-EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxKjAoBgNVBAMTIUNlcnRpZmljYXRpb24g
-QXV0aG9yaXR5IG9mIFdvU2lnbjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgwMTAwMDFaMFUxCzAJ
-BgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEqMCgGA1UEAxMhQ2VydGlmaWNh
-dGlvbiBBdXRob3JpdHkgb2YgV29TaWduMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
-vcqNrLiRFVaXe2tcesLea9mhsMMQI/qnobLMMfo+2aYpbxY94Gv4uEBf2zmoAHqLoE1UfcIiePyO
-CbiohdfMlZdLdNiefvAA5A6JrkkoRBoQmTIPJYhTpA2zDxIIFgsDcSccf+Hb0v1naMQFXQoOXXDX
-2JegvFNBmpGN9J42Znp+VsGQX+axaCA2pIwkLCxHC1l2ZjC1vt7tj/id07sBMOby8w7gLJKA84X5
-KIq0VC6a7fd2/BVoFutKbOsuEo/Uz/4Mx1wdC34FMr5esAkqQtXJTpCzWQ27en7N1QhatH/YHGkR
-+ScPewavVIMYe+HdVHpRaG53/Ma/UkpmRqGyZxq7o093oL5d//xWC0Nyd5DKnvnyOfUNqfTq1+ez
-EC8wQjchzDBwyYaYD8xYTYO7feUapTeNtqwylwA6Y3EkHp43xP901DfA4v6IRmAR3Qg/UDaruHqk
-lWJqbrDKaiFaafPz+x1wOZXzp26mgYmhiMU7ccqjUu6Du/2gd/Tkb+dC221KmYo0SLwX3OSACCK2
-8jHAPwQ+658geda4BmRkAjHXqc1S+4RFaQkAKtxVi8QGRkvASh0JWzko/amrzgD5LkhLJuYwTKVY
-yrREgk/nkR4zw7CT/xH8gdLKH3Ep3XZPkiWvHYG3Dy+MwwbMLyejSuQOmbp8HkUff6oZRZb9/D0C
-AwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOFmzw7R
-8bNLtwYgFP6HEtX2/vs+MA0GCSqGSIb3DQEBBQUAA4ICAQCoy3JAsnbBfnv8rWTjMnvMPLZdRtP1
-LOJwXcgu2AZ9mNELIaCJWSQBnfmvCX0KI4I01fx8cpm5o9dU9OpScA7F9dY74ToJMuYhOZO9sxXq
-T2r09Ys/L3yNWC7F4TmgPsc9SnOeQHrAK2GpZ8nzJLmzbVUsWh2eJXLOC62qx1ViC777Y7NhRCOj
-y+EaDveaBk3e1CNOIZZbOVtXHS9dCF4Jef98l7VNg64N1uajeeAz0JmWAjCnPv/So0M/BVoG6kQC
-2nz4SNAzqfkHx5Xh9T71XXG68pWpdIhhWeO/yloTunK0jF02h+mmxTwTv97QRCbut+wucPrXnbes
-5cVAWubXbHssw1abR80LzvobtCHXt2a49CUwi1wNuepnsvRtrtWhnk/Yn+knArAdBtaP4/tIEp9/
-EaEQPkxROpaw0RPxx9gmrjrKkcRpnd8BKWRRb2jaFOwIQZeQjdCygPLPwj2/kWjFgGcexGATVdVh
-mVd8upUPYUk6ynW8yQqTP2cOEvIo4jEbwFcW3wh8GcF+Dx+FHgo2fFt+J7x6v+Db9NpSvd4MVHAx
-kUOVyLzwPt0JfjBkUO1/AaQzZ01oT74V77D2AhGiGxMlOtzCWfHjXEa7ZywCRuoeSKbmW9m1vFGi
-kpbbqsY3Iqb+zCB0oy2pLmvLwIIRIbWTee5Ehr7XHuQe+w==
------END CERTIFICATE-----
-
-WoSign China
-============
------BEGIN CERTIFICATE-----
-MIIFWDCCA0CgAwIBAgIQUHBrzdgT/BtOOzNy0hFIjTANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQG
-EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMMEkNBIOayg+mAmuagueiv
-geS5pjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgwMTAwMDFaMEYxCzAJBgNVBAYTAkNOMRowGAYD
-VQQKExFXb1NpZ24gQ0EgTGltaXRlZDEbMBkGA1UEAwwSQ0Eg5rKD6YCa5qC56K+B5LmmMIICIjAN
-BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0EkhHiX8h8EqwqzbdoYGTufQdDTc7WU1/FDWiD+k
-8H/rD195L4mx/bxjWDeTmzj4t1up+thxx7S8gJeNbEvxUNUqKaqoGXqW5pWOdO2XCld19AXbbQs5
-uQF/qvbW2mzmBeCkTVL829B0txGMe41P/4eDrv8FAxNXUDf+jJZSEExfv5RxadmWPgxDT74wwJ85
-dE8GRV2j1lY5aAfMh09Qd5Nx2UQIsYo06Yms25tO4dnkUkWMLhQfkWsZHWgpLFbE4h4TV2TwYeO5
-Ed+w4VegG63XX9Gv2ystP9Bojg/qnw+LNVgbExz03jWhCl3W6t8Sb8D7aQdGctyB9gQjF+BNdeFy
-b7Ao65vh4YOhn0pdr8yb+gIgthhid5E7o9Vlrdx8kHccREGkSovrlXLp9glk3Kgtn3R46MGiCWOc
-76DbT52VqyBPt7D3h1ymoOQ3OMdc4zUPLK2jgKLsLl3Az+2LBcLmc272idX10kaO6m1jGx6KyX2m
-+Jzr5dVjhU1zZmkR/sgO9MHHZklTfuQZa/HpelmjbX7FF+Ynxu8b22/8DU0GAbQOXDBGVWCvOGU6
-yke6rCzMRh+yRpY/8+0mBe53oWprfi1tWFxK1I5nuPHa1UaKJ/kR8slC/k7e3x9cxKSGhxYzoacX
-GKUN5AXlK8IrC6KVkLn9YDxOiT7nnO4fuwECAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud
-EwEB/wQFMAMBAf8wHQYDVR0OBBYEFOBNv9ybQV0T6GTwp+kVpOGBwboxMA0GCSqGSIb3DQEBCwUA
-A4ICAQBqinA4WbbaixjIvirTthnVZil6Xc1bL3McJk6jfW+rtylNpumlEYOnOXOvEESS5iVdT2H6
-yAa+Tkvv/vMx/sZ8cApBWNromUuWyXi8mHwCKe0JgOYKOoICKuLJL8hWGSbueBwj/feTZU7n85iY
-r83d2Z5AiDEoOqsuC7CsDCT6eiaY8xJhEPRdF/d+4niXVOKM6Cm6jBAyvd0zaziGfjk9DgNyp115
-j0WKWa5bIW4xRtVZjc8VX90xJc/bYNaBRHIpAlf2ltTW/+op2znFuCyKGo3Oy+dCMYYFaA6eFN0A
-kLppRQjbbpCBhqcqBT/mhDn4t/lXX0ykeVoQDF7Va/81XwVRHmyjdanPUIPTfPRm94KNPQx96N97
-qA4bLJyuQHCH2u2nFoJavjVsIE4iYdm8UXrNemHcSxH5/mc0zy4EZmFcV5cjjPOGG0jfKq+nwf/Y
-jj4Du9gqsPoUJbJRa4ZDhS4HIxaAjUz7tGM7zMN07RujHv41D198HRaG9Q7DlfEvr10lO1Hm13ZB
-ONFLAzkopR6RctR9q5czxNM+4Gm2KHmgCY0c0f9BckgG/Jou5yD5m6Leie2uPAmvylezkolwQOQv
-T8Jwg0DXJCxr5wkf09XHwQj02w47HAcLQxGEIYbpgNR12KvxAmLBsX5VYc8T1yaw15zLKYs4SgsO
-kI26oQ==
------END CERTIFICATE-----
-
COMODO RSA Certification Authority
==================================
-----BEGIN CERTIFICATE-----
@@ -2893,20 +1508,6 @@ HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu
9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
-----END CERTIFICATE-----
-GlobalSign ECC Root CA - R4
-===========================
------BEGIN CERTIFICATE-----
-MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb
-R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
-EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
-R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
-EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl
-OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P
-AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV
-MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF
-JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q=
------END CERTIFICATE-----
-
GlobalSign ECC Root CA - R5
===========================
-----BEGIN CERTIFICATE-----
@@ -2922,66 +1523,6 @@ uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7
yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3
-----END CERTIFICATE-----
-Staat der Nederlanden Root CA - G3
-==================================
------BEGIN CERTIFICATE-----
-MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
-CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
-Um9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloXDTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMC
-TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
-ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4y
-olQPcPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WWIkYFsO2t
-x1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqXxz8ecAgwoNzFs21v0IJy
-EavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFyKJLZWyNtZrVtB0LrpjPOktvA9mxjeM3K
-Tj215VKb8b475lRgsGYeCasH/lSJEULR9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUur
-mkVLoR9BvUhTFXFkC4az5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU5
-1nus6+N86U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7Ngzp
-07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHPbMk7ccHViLVlvMDo
-FxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXtBznaqB16nzaeErAMZRKQFWDZJkBE
-41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTtXUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMB
-AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleu
-yjWcLhL75LpdINyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD
-U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwpLiniyMMB8jPq
-KqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8Ipf3YF3qKS9Ysr1YvY2WTxB1
-v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixpgZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA
-8KCWAg8zxXHzniN9lLf9OtMJgwYh/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b
-8KKaa8MFSu1BYBQw0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0r
-mj1AfsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq4BZ+Extq
-1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR1VmiiXTTn74eS9fGbbeI
-JG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/QFH1T/U67cjF68IeHRaVesd+QnGTbksV
-tzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM94B7IWcnMFk=
------END CERTIFICATE-----
-
-Staat der Nederlanden EV Root CA
-================================
------BEGIN CERTIFICATE-----
-MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE
-CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
-RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M
-MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl
-cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk
-SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW
-O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r
-0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8
-Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV
-XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr
-08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV
-0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd
-74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx
-fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC
-MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa
-ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI
-eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu
-c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq
-5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN
-b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN
-f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi
-5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4
-WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK
-DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy
-eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg==
------END CERTIFICATE-----
-
IdenTrust Commercial Root CA 1
==============================
-----BEGIN CERTIFICATE-----
@@ -3116,61 +1657,6 @@ kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C
ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
-----END CERTIFICATE-----
-TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H5
-====================================================
------BEGIN CERTIFICATE-----
-MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UEBhMCVFIxDzAN
-BgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp
-bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4xQjBABgNVBAMMOVTDnFJLVFJVU1Qg
-RWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSBINTAeFw0xMzA0MzAw
-ODA3MDFaFw0yMzA0MjgwODA3MDFaMIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0w
-SwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnE
-n2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBFbGVrdHJvbmlrIFNlcnRp
-ZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEApCUZ4WWe60ghUEoI5RHwWrom/4NZzkQqL/7hzmAD/I0Dpe3/a6i6zDQGn1k19uwsu537
-jVJp45wnEFPzpALFp/kRGml1bsMdi9GYjZOHp3GXDSHHmflS0yxjXVW86B8BSLlg/kJK9siArs1m
-ep5Fimh34khon6La8eHBEJ/rPCmBp+EyCNSgBbGM+42WAA4+Jd9ThiI7/PS98wl+d+yG6w8z5UNP
-9FR1bSmZLmZaQ9/LXMrI5Tjxfjs1nQ/0xVqhzPMggCTTV+wVunUlm+hkS7M0hO8EuPbJbKoCPrZV
-4jI3X/xml1/N1p7HIL9Nxqw/dV8c7TKcfGkAaZHjIxhT6QIDAQABo0IwQDAdBgNVHQ4EFgQUVpkH
-HtOsDGlktAxQR95DLL4gwPswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
-hvcNAQELBQADggEBAJ5FdnsXSDLyOIspve6WSk6BGLFRRyDN0GSxDsnZAdkJzsiZ3GglE9Rc8qPo
-BP5yCccLqh0lVX6Wmle3usURehnmp349hQ71+S4pL+f5bFgWV1Al9j4uPqrtd3GqqpmWRgqujuwq
-URawXs3qZwQcWDD1YIq9pr1N5Za0/EKJAWv2cMhQOQwt1WbZyNKzMrcbGW3LM/nfpeYVhDfwwvJl
-lpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CFYv4HAqGEVka+lgqaE9chTLd8
-B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW+qtB4Uu2NQvAmxU=
------END CERTIFICATE-----
-
-Certinomis - Root CA
-====================
------BEGIN CERTIFICATE-----
-MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjETMBEGA1UEChMK
-Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAbBgNVBAMTFENlcnRpbm9taXMg
-LSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMzMTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIx
-EzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRD
-ZXJ0aW5vbWlzIC0gUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQos
-P5L2fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJflLieY6pOo
-d5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQVWZUKxkd8aRi5pwP5ynap
-z8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDFTKWrteoB4owuZH9kb/2jJZOLyKIOSY00
-8B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09x
-RLWtwHkziOC/7aOgFLScCbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE
-6OXWk6RiwsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJwx3t
-FvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SGm/lg0h9tkQPTYKbV
-PZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4F2iw4lNVYC2vPsKD2NkJK/DAZNuH
-i5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZngWVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGj
-YzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I
-6tNxIqSSaHh02TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF
-AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/0KGRHCwPT5iV
-WVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWwF6YSjNRieOpWauwK0kDDPAUw
-Pk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZSg081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAX
-lCOotQqSD7J6wWAsOMwaplv/8gzjqh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJ
-y29SWwNyhlCVCNSNh4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9
-Iff/ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8Vbtaw5Bng
-DwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwjY/M50n92Uaf0yKHxDHYi
-I0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nM
-cyrDflOR1m749fPH0FFNjkulW+YZFzvWgQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVr
-hkIGuUE=
------END CERTIFICATE-----
-
OISTE WISeKey Global Root GB CA
===============================
-----BEGIN CERTIFICATE-----
@@ -3193,42 +1679,6 @@ HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
-----END CERTIFICATE-----
-Certification Authority of WoSign G2
-====================================
------BEGIN CERTIFICATE-----
-MIIDfDCCAmSgAwIBAgIQayXaioidfLwPBbOxemFFRDANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQG
-EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxLTArBgNVBAMTJENlcnRpZmljYXRpb24g
-QXV0aG9yaXR5IG9mIFdvU2lnbiBHMjAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4NThaMFgx
-CzAJBgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEtMCsGA1UEAxMkQ2VydGlm
-aWNhdGlvbiBBdXRob3JpdHkgb2YgV29TaWduIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEAvsXEoCKASU+/2YcRxlPhuw+9YH+v9oIOH9ywjj2X4FA8jzrvZjtFB5sg+OPXJYY1kBai
-XW8wGQiHC38Gsp1ij96vkqVg1CuAmlI/9ZqD6TRay9nVYlzmDuDfBpgOgHzKtB0TiGsOqCR3A9Du
-W/PKaZE1OVbFbeP3PU9ekzgkyhjpJMuSA93MHD0JcOQg5PGurLtzaaNjOg9FD6FKmsLRY6zLEPg9
-5k4ot+vElbGs/V6r+kHLXZ1L3PR8du9nfwB6jdKgGlxNIuG12t12s9R23164i5jIFFTMaxeSt+BK
-v0mUYQs4kI9dJGwlezt52eJ+na2fmKEG/HgUYFf47oB3sQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
-AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU+mCp62XF3RYUCE4MD42b4Pdkr2cwDQYJKoZI
-hvcNAQELBQADggEBAFfDejaCnI2Y4qtAqkePx6db7XznPWZaOzG73/MWM5H8fHulwqZm46qwtyeY
-P0nXYGdnPzZPSsvxFPpahygc7Y9BMsaV+X3avXtbwrAh449G3CE4Q3RM+zD4F3LBMvzIkRfEzFg3
-TgvMWvchNSiDbGAtROtSjFA9tWwS1/oJu2yySrHFieT801LYYRf+epSEj3m2M1m6D8QL4nCgS3gu
-+sif/a+RZQp4OBXllxcU3fngLDT4ONCEIgDAFFEYKwLcMFrw6AF8NTojrwjkr6qOKEJJLvD1mTS+
-7Q9LGOHSJDy7XUe3IfKN0QqZjuNuPq1w4I+5ysxugTH2e5x6eeRncRg=
------END CERTIFICATE-----
-
-CA WoSign ECC Root
-==================
------BEGIN CERTIFICATE-----
-MIICCTCCAY+gAwIBAgIQaEpYcIBr8I8C+vbe6LCQkDAKBggqhkjOPQQDAzBGMQswCQYDVQQGEwJD
-TjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMTEkNBIFdvU2lnbiBFQ0MgUm9v
-dDAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4NThaMEYxCzAJBgNVBAYTAkNOMRowGAYDVQQK
-ExFXb1NpZ24gQ0EgTGltaXRlZDEbMBkGA1UEAxMSQ0EgV29TaWduIEVDQyBSb290MHYwEAYHKoZI
-zj0CAQYFK4EEACIDYgAE4f2OuEMkq5Z7hcK6C62N4DrjJLnSsb6IOsq/Srj57ywvr1FQPEd1bPiU
-t5v8KB7FVMxjnRZLU8HnIKvNrCXSf4/CwVqCXjCLelTOA7WRf6qU0NGKSMyCBSah1VES1ns2o0Iw
-QDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUqv3VWqP2h4syhf3R
-MluARZPzA7gwCgYIKoZIzj0EAwMDaAAwZQIxAOSkhLCB1T2wdKyUpOgOPQB0TKGXa/kNUTyh2Tv0
-Daupn75OcsqF1NnstTJFGG+rrQIwfcf3aWMvoeGY7xMQ0Xk/0f7qO3/eVvSQsRUR2LIiFdAvwyYu
-a/GRspBl9JrmkO5K
------END CERTIFICATE-----
-
SZAFIR ROOT CA2
===============
-----BEGIN CERTIFICATE-----
@@ -3333,126 +1783,6 @@ GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn
dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
-----END CERTIFICATE-----
-Certplus Root CA G1
-===================
------BEGIN CERTIFICATE-----
-MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUAMD4xCzAJBgNV
-BAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTAe
-Fw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhD
-ZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQAD
-ggIPADCCAgoCggIBANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHN
-r49aiZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt6kuJPKNx
-Qv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP0FG7Yn2ksYyy/yARujVj
-BYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTv
-LRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDEEW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2
-z4QTd28n6v+WZxcIbekN1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc
-4nBvCGrch2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCTmehd
-4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV4EJQeIQEQWGw9CEj
-jy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPOWftwenMGE9nTdDckQQoRb5fc5+R+
-ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0G
-A1UdDgQWBBSowcCbkahDFXxdBie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHY
-lwuBsTANBgkqhkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh
-66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7/SMNkPX0XtPG
-YX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BSS7CTKtQ+FjPlnsZlFT5kOwQ/
-2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F
-6ALEUz65noe8zDUa3qHpimOHZR4RKttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilX
-CNQ314cnrUlZp5GrRHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWe
-tUNy6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEVV/xuZDDC
-VRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5g4VCXA9DO2pJNdWY9BW/
-+mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl++O/QmueD6i9a5jc2NvLi6Td11n0bt3+
-qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo=
------END CERTIFICATE-----
-
-Certplus Root CA G2
-===================
------BEGIN CERTIFICATE-----
-MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4xCzAJBgNVBAYT
-AkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjAeFw0x
-NDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0
-cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IA
-BM0PW1aC3/BFGtat93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uN
-Am8xIk0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0PAQH/BAQD
-AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMB8GA1Ud
-IwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqGSM49BAMDA2gAMGUCMHD+sAvZ94OX7PNV
-HdTcswYO/jOYnYs5kGuUIe22113WTNchp+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjl
-vPl5adytRSv3tjFzzAalU5ORGpOucGpnutee5WEaXw==
------END CERTIFICATE-----
-
-OpenTrust Root CA G1
-====================
------BEGIN CERTIFICATE-----
-MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUAMEAxCzAJBgNV
-BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcx
-MB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM
-CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEB
-AQUAA4ICDwAwggIKAoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7fa
-Yp6bwiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX/uMftk87
-ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR077F9jAHiOH3BX2pfJLKO
-YheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGPuY4zbGneWK2gDqdkVBFpRGZPTBKnjix9
-xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLxp2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO
-9z0M+Yo0FMT7MzUj8czxKselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq
-3ywgsNw2TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+WG+Oi
-n6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPwvFEVVJSmdz7QdFG9
-URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYYEQRVzXR7z2FwefR7LFxckvzluFqr
-TJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
-/zAdBgNVHQ4EFgQUl0YhVyE12jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/Px
-N3DlCPaTKbYwDQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E
-PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kfgLMtMrpkZ2Cv
-uVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbSFXJfLkur1J1juONI5f6ELlgK
-n0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLh
-X4SPgPL0DTatdrOjteFkdjpY3H1PXlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80
-nR14SohWZ25g/4/Ii+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcm
-GS3tTAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L9109S5zvE/
-bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/KyPu1svf0OnWZzsD2097+o
-4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJAwSQiumPv+i2tCqjI40cHLI5kqiPAlxA
-OXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj1oxx
------END CERTIFICATE-----
-
-OpenTrust Root CA G2
-====================
------BEGIN CERTIFICATE-----
-MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUAMEAxCzAJBgNV
-BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcy
-MB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM
-CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEB
-AQUAA4ICDwAwggIKAoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+
-Ntmh/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78eCbY2albz
-4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/61UWY0jUJ9gNDlP7ZvyCV
-eYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fEFY8ElggGQgT4hNYdvJGmQr5J1WqIP7wt
-UdGejeBSzFfdNTVY27SPJIjki9/ca1TSgSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz
-3GIZ38i1MH/1PCZ1Eb3XG7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj
-3CzMpSZyYhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaHvGOz
-9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4t/bQWVyJ98LVtZR0
-0dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/gh7PU3+06yzbXfZqfUAkBXKJOAGT
-y3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
-/zAdBgNVHQ4EFgQUajn6QiL35okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59
-M4PLuG53hq8wDQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz
-Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0nXGEL8pZ0keI
-mUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qTRmTFAHneIWv2V6CG1wZy7HBG
-S4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpTwm+bREx50B1ws9efAvSyB7DH5fitIw6mVskp
-EndI2S9G/Tvw/HRwkqWOOAgfZDC2t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ
-6e18CL13zSdkzJTaTkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97kr
-gCf2o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU3jg9CcCo
-SmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eAiN1nE28daCSLT7d0geX0
-YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14fWKGVyasvc0rQLW6aWQ9VGHgtPFGml4vm
-u7JwqkwR3v98KzfUetF3NI/n+UL3PIEMS1IK
------END CERTIFICATE-----
-
-OpenTrust Root CA G3
-====================
------BEGIN CERTIFICATE-----
-MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAxCzAJBgNVBAYT
-AkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEczMB4X
-DTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9w
-ZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQA
-IgNiAARK7liuTcpm3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5B
-ta1doYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4GA1UdDwEB
-/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAf
-BgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAKBggqhkjOPQQDAwNpADBmAjEAj6jcnboM
-BBf6Fek9LykBl7+BFjNAk2z8+e2AcG+qj9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta
-3U1fJAuwACEl74+nBCZx4nxp5V2a+EEfOzmTk51V6s2N8fvB
------END CERTIFICATE-----
-
ISRG Root X1
============
-----BEGIN CERTIFICATE-----
@@ -3589,37 +1919,6 @@ MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1
AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA==
-----END CERTIFICATE-----
-LuxTrust Global Root 2
-======================
------BEGIN CERTIFICATE-----
-MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQELBQAwRjELMAkG
-A1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNVBAMMFkx1eFRydXN0IEdsb2Jh
-bCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUwMzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEW
-MBQGA1UECgwNTHV4VHJ1c3QgUy5BLjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCC
-AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wm
-Kb3FibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTemhfY7RBi2
-xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1EMShduxq3sVs35a0VkBC
-wGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsnXpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm
-1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkm
-FRseTJIpgp7VkoGSQXAZ96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niF
-wpN6cj5mj5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4gDEa/
-a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+8kPREd8vZS9kzl8U
-ubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2jX5t/Lax5Gw5CMZdjpPuKadUiDTSQ
-MC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmHhFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB
-/zBCBgNVHSAEOzA5MDcGByuBKwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5
-Lmx1eHRydXN0Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT
-+Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQELBQADggIBAGoZ
-FO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9BzZAcg4atmpZ1gDlaCDdLnIN
-H2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTOjFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW
-7MM3LGVYvlcAGvI1+ut7MV3CwRI9loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIu
-ZY+kt9J/Z93I055cqqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWA
-VWe+2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/JEAdemrR
-TxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKrezrnK+T+Tb/mjuuqlPpmt
-/f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQfLSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc
-7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31I
-iyBMz2TWuJdGsE7RKlY6oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr
------END CERTIFICATE-----
-
TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
=============================================
-----BEGIN CERTIFICATE-----
@@ -3644,3 +1943,1592 @@ lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R
e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j
q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
-----END CERTIFICATE-----
+
+GDCA TrustAUTH R5 ROOT
+======================
+-----BEGIN CERTIFICATE-----
+MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw
+BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD
+DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow
+YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ
+IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs
+AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p
+OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr
+pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ
+9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ
+xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM
+R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ
+D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4
+oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx
+9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR
+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg
+p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9
+H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35
+6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd
++PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ
+HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD
+F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ
+8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv
+/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT
+aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g==
+-----END CERTIFICATE-----
+
+SSL.com Root Certification Authority RSA
+========================================
+-----BEGIN CERTIFICATE-----
+MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxDjAM
+BgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24x
+MTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYw
+MjEyMTczOTM5WhcNNDEwMjEyMTczOTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
+EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NM
+LmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2RxFdHaxh3a3by/ZPkPQ/C
+Fp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aXqhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8
+P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcCC52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/ge
+oeOy3ZExqysdBP+lSgQ36YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkp
+k8zruFvh/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrFYD3Z
+fBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93EJNyAKoFBbZQ+yODJ
+gUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVcUS4cK38acijnALXRdMbX5J+tB5O2
+UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi8
+1xtZPCvM8hnIk2snYxnP/Okm+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4s
+bE6x/c+cCbqiM+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4GA1UdDwEB/wQE
+AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGVcpNxJK1ok1iOMq8bs3AD/CUr
+dIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBcHadm47GUBwwyOabqG7B52B2ccETjit3E+ZUf
+ijhDPwGFpUenPUayvOUiaPd7nNgsPgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAsl
+u1OJD7OAUN5F7kR/q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjq
+erQ0cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jra6x+3uxj
+MxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90IH37hVZkLId6Tngr75qNJ
+vTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/YK9f1JmzJBjSWFupwWRoyeXkLtoh/D1JI
+Pb9s2KJELtFOt3JY04kTlf5Eq/jXixtunLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406y
+wKBjYZC6VWg3dGq2ktufoYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NI
+WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k=
+-----END CERTIFICATE-----
+
+SSL.com Root Certification Authority ECC
+========================================
+-----BEGIN CERTIFICATE-----
+MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV
+BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv
+BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy
+MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO
+BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv
+bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA
+BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+
+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR
+hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT
+jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW
+e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z
+5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl
+-----END CERTIFICATE-----
+
+SSL.com EV Root Certification Authority RSA R2
+==============================================
+-----BEGIN CERTIFICATE-----
+MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w
+DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u
+MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy
+MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI
+DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD
+VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN
+BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh
+hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w
+cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO
+Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+
+B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh
+CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim
+9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto
+RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm
+JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48
++qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV
+HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp
+qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1
+++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx
+Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G
+guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz
+OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7
+CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq
+lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR
+rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1
+hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX
+9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w==
+-----END CERTIFICATE-----
+
+SSL.com EV Root Certification Authority ECC
+===========================================
+-----BEGIN CERTIFICATE-----
+MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV
+BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy
+BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw
+MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
+EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM
+LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy
+3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O
+BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe
+5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ
+N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm
+m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg==
+-----END CERTIFICATE-----
+
+GlobalSign Root CA - R6
+=======================
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEgMB4GA1UECxMX
+R2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds
+b2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQxMjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9i
+YWxTaWduIFJvb3QgQ0EgLSBSNjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFs
+U2lnbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQss
+grRIxutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1kZguSgMpE
+3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxDaNc9PIrFsmbVkJq3MQbF
+vuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJwLnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqM
+PKq0pPbzlUoSB239jLKJz9CgYXfIWHSw1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+
+azayOeSsJDa38O+2HBNXk7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05O
+WgtH8wY2SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/hbguy
+CLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4nWUx2OVvq+aWh2IMP
+0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpYrZxCRXluDocZXFSxZba/jJvcE+kN
+b7gu3GduyYsRtYQUigAZcIN5kZeR1BonvzceMgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQE
+AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNV
+HSMEGDAWgBSubAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
+nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGtIxg93eFyRJa0
+lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr6155wsTLxDKZmOMNOsIeDjHfrY
+BzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLjvUYAGm0CuiVdjaExUd1URhxN25mW7xocBFym
+Fe944Hn+Xds+qkxV/ZoVqW/hpvvfcDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr
+3TsTjxKM4kEaSHpzoHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB1
+0jZpnOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfspA9MRf/T
+uTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+vJJUEeKgDu+6B5dpffItK
+oZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+t
+JDfLRVpOoERIyNiwmcUVhAn21klJwGW45hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
+-----END CERTIFICATE-----
+
+OISTE WISeKey Global Root GC CA
+===============================
+-----BEGIN CERTIFICATE-----
+MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQswCQYDVQQGEwJD
+SDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEo
+MCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRa
+Fw00MjA1MDkwOTU4MzNaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQL
+ExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh
+bCBSb290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4nieUqjFqdr
+VCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4Wp2OQ0jnUsYd4XxiWD1Ab
+NTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
+BgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7TrYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0E
+AwMDaAAwZQIwJsdpW9zV57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtk
+AjEA2zQgMgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9
+-----END CERTIFICATE-----
+
+UCA Global G2 Root
+==================
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQG
+EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBHbG9iYWwgRzIgUm9vdDAeFw0x
+NjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0xCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlU
+cnVzdDEbMBkGA1UEAwwSVUNBIEdsb2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEAxeYrb3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmT
+oni9kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzmVHqUwCoV
+8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/RVogvGjqNO7uCEeBHANBS
+h6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDcC/Vkw85DvG1xudLeJ1uK6NjGruFZfc8o
+LTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIjtm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/
+R+zvWr9LesGtOxdQXGLYD0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBe
+KW4bHAyvj5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6DlNaBa
+4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6iIis7nCs+dwp4wwc
+OxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznPO6Q0ibd5Ei9Hxeepl2n8pndntd97
+8XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
+BBYEFIHEjMz15DD/pQwIX4wVZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo
+5sOASD0Ee/ojL3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5
+1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl1qnN3e92mI0A
+Ds0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oUb3n09tDh05S60FdRvScFDcH9
+yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LVPtateJLbXDzz2K36uGt/xDYotgIVilQsnLAX
+c47QN6MUPJiVAAwpBVueSUmxX8fjy88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHo
+jhJi6IjMtX9Gl8CbEGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZk
+bxqgDMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI+Vg7RE+x
+ygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGyYiGqhkCyLmTTX8jjfhFn
+RR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bXUB+K+wb1whnw0A==
+-----END CERTIFICATE-----
+
+UCA Extended Validation Root
+============================
+-----BEGIN CERTIFICATE-----
+MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQG
+EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9u
+IFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMxMDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8G
+A1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrs
+iWogD4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvSsPGP2KxF
+Rv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aopO2z6+I9tTcg1367r3CTu
+eUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dksHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR
+59mzLC52LqGj3n5qiAno8geK+LLNEOfic0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH
+0mK1lTnj8/FtDw5lhIpjVMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KR
+el7sFsLzKuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/TuDv
+B0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41Gsx2VYVdWf6/wFlth
+WG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs1+lvK9JKBZP8nm9rZ/+I8U6laUpS
+NwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQDfwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS
+3H5aBZ8eNJr34RQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL
+BQADggIBADaNl8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR
+ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQVBcZEhrxH9cM
+aVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5c6sq1WnIeJEmMX3ixzDx/BR4
+dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb
++7lsq+KePRXBOy5nAliRn+/4Qh8st2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOW
+F3sGPjLtx7dCvHaj2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwi
+GpWOvpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2CxR9GUeOc
+GMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmxcmtpzyKEC2IPrNkZAJSi
+djzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbMfjKaiJUINlK73nZfdklJrX+9ZSCyycEr
+dhh2n1ax
+-----END CERTIFICATE-----
+
+Certigna Root CA
+================
+-----BEGIN CERTIFICATE-----
+MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UE
+BhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAwMiA0ODE0NjMwODEwMDAzNjEZ
+MBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0xMzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjda
+MFoxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYz
+MDgxMDAwMzYxGTAXBgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sOty3tRQgX
+stmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9MCiBtnyN6tMbaLOQdLNyz
+KNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPuI9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8
+JXrJhFwLrN1CTivngqIkicuQstDuI7pmTLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16
+XdG+RCYyKfHx9WzMfgIhC59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq
+4NYKpkDfePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3YzIoej
+wpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWTCo/1VTp2lc5ZmIoJ
+lXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1kJWumIWmbat10TWuXekG9qxf5kBdI
+jzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp/
+/TBt2dzhauH8XwIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
+HQYDVR0OBBYEFBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of
+1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczovL3d3d3cuY2Vy
+dGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilodHRwOi8vY3JsLmNlcnRpZ25h
+LmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYraHR0cDovL2NybC5kaGlteW90aXMuY29tL2Nl
+cnRpZ25hcm9vdGNhLmNybDANBgkqhkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOIt
+OoldaDgvUSILSo3L6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxP
+TGRGHVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH60BGM+RFq
+7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncBlA2c5uk5jR+mUYyZDDl3
+4bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdio2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd
+8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS
+6Cvu5zHbugRqh5jnxV/vfaci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaY
+tlu3zM63Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayhjWZS
+aX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw3kAP+HwV96LOPNde
+E4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0=
+-----END CERTIFICATE-----
+
+emSign Root CA - G1
+===================
+-----BEGIN CERTIFICATE-----
+MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJJTjET
+MBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl
+ZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBHMTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgx
+ODMwMDBaMGcxCzAJBgNVBAYTAklOMRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVk
+aHJhIFRlY2hub2xvZ2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQzf2N4aLTN
+LnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO8oG0x5ZOrRkVUkr+PHB1
+cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aqd7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHW
+DV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhMtTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ
+6DqS0hdW5TUaQBw+jSztOd9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrH
+hQIDAQABo0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQDAgEG
+MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31xPaOfG1vR2vjTnGs2
+vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjMwiI/aTvFthUvozXGaCocV685743Q
+NcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6dGNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q
++Mri/Tm3R7nrft8EI6/6nAYH6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeih
+U80Bv2noWgbyRQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx
+iN66zB+Afko=
+-----END CERTIFICATE-----
+
+emSign ECC Root CA - G3
+=======================
+-----BEGIN CERTIFICATE-----
+MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQGEwJJTjETMBEG
+A1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEg
+MB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4
+MTgzMDAwWjBrMQswCQYDVQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11
+ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g
+RzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0WXTsuwYc
+58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xySfvalY8L1X44uT6EYGQIr
+MgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuBzhccLikenEhjQjAOBgNVHQ8BAf8EBAMC
+AQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+D
+CBeQyh+KTOgNG3qxrdWBCUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7
+jHvrZQnD+JbNR6iC8hZVdyR+EhCVBCyj
+-----END CERTIFICATE-----
+
+emSign Root CA - C1
+===================
+-----BEGIN CERTIFICATE-----
+MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx
+EzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNp
+Z24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UE
+BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQD
+ExNlbVNpZ24gUm9vdCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+up
+ufGZBczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZHdPIWoU/
+Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH3DspVpNqs8FqOp099cGX
+OFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvHGPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4V
+I5b2P/AgNBbeCsbEBEV5f6f9vtKppa+cxSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleooms
+lMuoaJuvimUnzYnu3Yy1aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+
+XJGFehiqTbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD
+ggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87/kOXSTKZEhVb3xEp
+/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4kqNPEjE2NuLe/gDEo2APJ62gsIq1
+NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrGYQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9
+wC68AivTxEDkigcxHpvOJpkT+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQ
+BmIMMMAVSKeoWXzhriKi4gp6D/piq1JM4fHfyr6DDUI=
+-----END CERTIFICATE-----
+
+emSign ECC Root CA - C3
+=======================
+-----BEGIN CERTIFICATE-----
+MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQGEwJVUzETMBEG
+A1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMxIDAeBgNVBAMTF2VtU2lnbiBF
+Q0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UE
+BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQD
+ExdlbVNpZ24gRUNDIFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd
+6bciMK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4OjavtisIGJAnB9
+SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0OBBYEFPtaSNCAIEDyqOkA
+B2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gA
+MGUCMQC02C8Cif22TGK6Q04ThHK1rt0c3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwU
+ZOR8loMRnLDRWmFLpg9J0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ==
+-----END CERTIFICATE-----
+
+Hongkong Post Root CA 3
+=======================
+-----BEGIN CERTIFICATE-----
+MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQELBQAwbzELMAkG
+A1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJSG9uZyBLb25nMRYwFAYDVQQK
+Ew1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2
+MDMwMjI5NDZaFw00MjA2MDMwMjI5NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtv
+bmcxEjAQBgNVBAcTCUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMX
+SG9uZ2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz
+iNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFOdem1p+/l6TWZ5Mwc50tf
+jTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mIVoBc+L0sPOFMV4i707mV78vH9toxdCim
+5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOe
+sL4jpNrcyCse2m5FHomY2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj
+0mRiikKYvLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+TtbNe/
+JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZbx39ri1UbSsUgYT2u
+y1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+l2oBlKN8W4UdKjk60FSh0Tlxnf0h
++bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YKTE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsG
+xVd7GYYKecsAyVKvQv83j+GjHno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwID
+AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e
+i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEwDQYJKoZIhvcN
+AQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG7BJ8dNVI0lkUmcDrudHr9Egw
+W62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCkMpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWld
+y8joRTnU+kLBEUx3XZL7av9YROXrgZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov
++BS5gLNdTaqX4fnkGMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDc
+eqFS3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJmOzj/2ZQw
+9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+l6mc1X5VTMbeRRAc6uk7
+nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6cJfTzPV4e0hz5sy229zdcxsshTrD3mUcY
+hcErulWuBurQB7Lcq9CClnXO0lD+mefPL5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB
+60PZ2Pierc+xYw5F9KBaLJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fq
+dBb9HxEGmpv0
+-----END CERTIFICATE-----
+
+Entrust Root Certification Authority - G4
+=========================================
+-----BEGIN CERTIFICATE-----
+MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAwgb4xCzAJBgNV
+BAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3Qu
+bmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1
+dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1
+dGhvcml0eSAtIEc0MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYT
+AlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0
+L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhv
+cml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhv
+cml0eSAtIEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3D
+umSXbcr3DbVZwbPLqGgZ2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV
+3imz/f3ET+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j5pds
+8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAMC1rlLAHGVK/XqsEQ
+e9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73TDtTUXm6Hnmo9RR3RXRv06QqsYJn7
+ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNXwbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5X
+xNMhIWNlUpEbsZmOeX7m640A2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV
+7rtNOzK+mndmnqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8
+dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwlN4y6mACXi0mW
+Hv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNjc0kCAwEAAaNCMEAwDwYDVR0T
+AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9n
+MA0GCSqGSIb3DQEBCwUAA4ICAQAS5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4Q
+jbRaZIxowLByQzTSGwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht
+7LGrhFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/B7NTeLUK
+YvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uIAeV8KEsD+UmDfLJ/fOPt
+jqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbwH5Lk6rWS02FREAutp9lfx1/cH6NcjKF+
+m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKW
+RGhXxNUzzxkvFMSUHHuk2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjA
+JOgc47OlIQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk5F6G
++TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuYn/PIjhs4ViFqUZPT
+kcpG2om3PVODLAgfi49T3f+sHw==
+-----END CERTIFICATE-----
+
+Microsoft ECC Root Certificate Authority 2017
+=============================================
+-----BEGIN CERTIFICATE-----
+MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV
+UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQgRUND
+IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4
+MjMxNjA0WjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw
+NAYDVQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQ
+BgcqhkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZRogPZnZH6
+thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYbhGBKia/teQ87zvH2RPUB
+eMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIy5lycFIM
++Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlf
+Xu5gKcs68tvWMoQZP3zVL8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaR
+eNtUjGUBiudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M=
+-----END CERTIFICATE-----
+
+Microsoft RSA Root Certificate Authority 2017
+=============================================
+-----BEGIN CERTIFICATE-----
+MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBlMQswCQYDVQQG
+EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQg
+UlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIw
+NzE4MjMwMDIzWjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u
+MTYwNAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcw
+ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZNt9GkMml
+7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0ZdDMbRnMlfl7rEqUrQ7e
+S0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw7
+1VdyvD/IybLeS2v4I2wDwAW9lcfNcztmgGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+
+dkC0zVJhUXAoP8XFWvLJjEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49F
+yGcohJUcaDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaGYaRS
+MLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6W6IYZVcSn2i51BVr
+lMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4KUGsTuqwPN1q3ErWQgR5WrlcihtnJ
+0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH+FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJ
+ClTUFLkqqNfs+avNJVgyeY+QW5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYw
+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC
+NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZCLgLNFgVZJ8og
+6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OCgMNPOsduET/m4xaRhPtthH80
+dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk
++ONVFT24bcMKpBLBaYVu32TxU5nhSnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex
+/2kskZGT4d9Mozd2TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDy
+AmH3pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGRxpl/j8nW
+ZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiAppGWSZI1b7rCoucL5mxAyE
+7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKT
+c0QWbej09+CVgI+WXTik9KveCjCHk9hNAHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D
+5KbvtwEwXlGjefVwaaZBRA+GsCyRxj3qrg+E
+-----END CERTIFICATE-----
+
+e-Szigno Root CA 2017
+=====================
+-----BEGIN CERTIFICATE-----
+MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNVBAYTAkhVMREw
+DwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUt
+MjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJvb3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZa
+Fw00MjA4MjIxMjA3MDZaMHExCzAJBgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UE
+CgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3pp
+Z25vIFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtvxie+RJCx
+s1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+HWyx7xf58etqjYzBhMA8G
+A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSHERUI0arBeAyxr87GyZDv
+vzAEwDAfBgNVHSMEGDAWgBSHERUI0arBeAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEA
+tVfd14pVCzbhhkT61NlojbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxO
+svxyqltZ+efcMQ==
+-----END CERTIFICATE-----
+
+certSIGN Root CA G2
+===================
+-----BEGIN CERTIFICATE-----
+MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNVBAYTAlJPMRQw
+EgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjAeFw0xNzAy
+MDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJBgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lH
+TiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBAMDFdRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05
+N0IwvlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZuIt4Imfk
+abBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhpn+Sc8CnTXPnGFiWeI8Mg
+wT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKscpc/I1mbySKEwQdPzH/iV8oScLumZfNp
+dWO9lfsbl83kqK/20U6o2YpxJM02PbyWxPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91Qqh
+ngLjYl/rNUssuHLoPj1PrCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732
+jcZZroiFDsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fxDTvf
+95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgyLcsUDFDYg2WD7rlc
+z8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6CeWRgKRM+o/1Pcmqr4tTluCRVLERL
+iohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1Ud
+DgQWBBSCIS1mxteg4BXrzkwJd8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOB
+ywaK8SJJ6ejqkX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC
+b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQlqiCA2ClV9+BB
+/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0OJD7uNGzcgbJceaBxXntC6Z5
+8hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+cNywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5
+BiKDUyUM/FHE5r7iOZULJK2v0ZXkltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklW
+atKcsWMy5WHgUyIOpwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tU
+Sxfj03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZkPuXaTH4M
+NMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE1LlSVHJ7liXMvGnjSG4N
+0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MXQRBdJ3NghVdJIgc=
+-----END CERTIFICATE-----
+
+Trustwave Global Certification Authority
+========================================
+-----BEGIN CERTIFICATE-----
+MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJV
+UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2
+ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u
+IEF1dGhvcml0eTAeFw0xNzA4MjMxOTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJV
+UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2
+ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u
+IEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALldUShLPDeS0YLOvR29
+zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0XznswuvCAAJWX/NKSqIk4cXGIDtiLK0thAf
+LdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4Bq
+stTnoApTAbqOl5F2brz81Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9o
+WN0EACyW80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotPJqX+
+OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1lRtzuzWniTY+HKE40
+Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfwhI0Vcnyh78zyiGG69Gm7DIwLdVcE
+uE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm
++9jaJXLE9gCxInm943xZYkqcBW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqj
+ifLJS3tBEW1ntwiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud
+EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1UdDwEB/wQEAwIB
+BjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W0OhUKDtkLSGm+J1WE2pIPU/H
+PinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfeuyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0H
+ZJDmHvUqoai7PF35owgLEQzxPy0QlG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla
+4gt5kNdXElE1GYhBaCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5R
+vbbEsLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPTMaCm/zjd
+zyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qequ5AvzSxnI9O4fKSTx+O
+856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxhVicGaeVyQYHTtgGJoC86cnn+OjC/QezH
+Yj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu
+3R3y4G5OBVixwJAWKqQ9EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP
+29FpHOTKyeC2nOnOcXHebD8WpHk=
+-----END CERTIFICATE-----
+
+Trustwave Global ECC P256 Certification Authority
+=================================================
+-----BEGIN CERTIFICATE-----
+MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYDVQQGEwJVUzER
+MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI
+b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYD
+VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy
+dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1
+NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH77bOYj
+43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoNFWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqm
+P62jQzBBMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt
+0UrrdaVKEJmzsaGLSvcwCgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjz
+RM4q3wghDDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7
+-----END CERTIFICATE-----
+
+Trustwave Global ECC P384 Certification Authority
+=================================================
+-----BEGIN CERTIFICATE-----
+MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYDVQQGEwJVUzER
+MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI
+b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYD
+VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy
+dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4
+NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuBBAAiA2IABGvaDXU1CDFH
+Ba5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJj9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr
+/TklZvFe/oyujUF5nQlgziip04pt89ZF1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNV
+HQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNn
+ADBkAjA3AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsCMGcl
+CrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVuSw==
+-----END CERTIFICATE-----
+
+NAVER Global Root Certification Authority
+=========================================
+-----BEGIN CERTIFICATE-----
+MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEMBQAwaTELMAkG
+A1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRGT1JNIENvcnAuMTIwMAYDVQQD
+DClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4
+NDJaFw0zNzA4MTgyMzU5NTlaMGkxCzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVT
+UyBQTEFURk9STSBDb3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVAiQqrDZBb
+UGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH38dq6SZeWYp34+hInDEW
++j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lEHoSTGEq0n+USZGnQJoViAbbJAh2+g1G7
+XNr4rRVqmfeSVPc0W+m/6imBEtRTkZazkVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2
+aacp+yPOiNgSnABIqKYPszuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4
+Yb8ObtoqvC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHfnZ3z
+VHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaGYQ5fG8Ir4ozVu53B
+A0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo0es+nPxdGoMuK8u180SdOqcXYZai
+cdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3aCJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejy
+YhbLgGvtPe31HzClrkvJE+2KAQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNV
+HQ4EFgQU0p+I36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB
+Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoNqo0hV4/GPnrK
+21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatjcu3cvuzHV+YwIHHW1xDBE1UB
+jCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm+LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bx
+hYTeodoS76TiEJd6eN4MUZeoIUCLhr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTg
+E34h5prCy8VCZLQelHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTH
+D8z7p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8piKCk5XQ
+A76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLRLBT/DShycpWbXgnbiUSY
+qqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oG
+I/hGoiLtk/bdmuYqh7GYVPEi92tF4+KOdh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmg
+kpzNNIaRkPpkUZ3+/uul9XXeifdy
+-----END CERTIFICATE-----
+
+AC RAIZ FNMT-RCM SERVIDORES SEGUROS
+===================================
+-----BEGIN CERTIFICATE-----
+MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQswCQYDVQQGEwJF
+UzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgwFgYDVQRhDA9WQVRFUy1RMjgy
+NjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1SQ00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4
+MTIyMDA5MzczM1oXDTQzMTIyMDA5MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQt
+UkNNMQ4wDAYDVQQLDAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNB
+QyBSQUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuBBAAiA2IA
+BPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LHsbI6GA60XYyzZl2hNPk2
+LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oKUm8BA06Oi6NCMEAwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqG
+SM49BAMDA2kAMGYCMQCuSuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoD
+zBOQn5ICMQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJyv+c=
+-----END CERTIFICATE-----
+
+GlobalSign Root R46
+===================
+-----BEGIN CERTIFICATE-----
+MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUAMEYxCzAJBgNV
+BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJv
+b3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAX
+BgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08Es
+CVeJOaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQGvGIFAha/
+r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud316HCkD7rRlr+/fKYIje
+2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo0q3v84RLHIf8E6M6cqJaESvWJ3En7YEt
+bWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSEy132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvj
+K8Cd+RTyG/FWaha/LIWFzXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD4
+12lPFzYE+cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCNI/on
+ccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzsx2sZy/N78CsHpdls
+eVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqaByFrgY/bxFn63iLABJzjqls2k+g9
+vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEM
+BQADggIBAHx47PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg
+JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti2kM3S+LGteWy
+gxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIkpnnpHs6i58FZFZ8d4kuaPp92
+CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRFFRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZm
+OUdkLG5NrmJ7v2B0GbhWrJKsFjLtrWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qq
+JZ4d16GLuc1CLgSkZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwye
+qiv5u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP4vkYxboz
+nxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6N3ec592kD3ZDZopD8p/7
+DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3vouXsXgxT7PntgMTzlSdriVZzH81Xwj3
+QEUxeCp6
+-----END CERTIFICATE-----
+
+GlobalSign Root E46
+===================
+-----BEGIN CERTIFICATE-----
+MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYxCzAJBgNVBAYT
+AkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJvb3Qg
+RTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNV
+BAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcq
+hkjOPQIBBgUrgQQAIgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkB
+jtjqR+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGddyXqBPCCj
+QjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQxCpCPtsad0kRL
+gLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZk
+vLtoURMMA/cVi4RguYv/Uo7njLwcAjA8+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+
+CAezNIm8BZ/3Hobui3A=
+-----END CERTIFICATE-----
+
+GLOBALTRUST 2020
+================
+-----BEGIN CERTIFICATE-----
+MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkGA1UEBhMCQVQx
+IzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVT
+VCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYxMDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAh
+BgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAy
+MDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWi
+D59bRatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9ZYybNpyrO
+VPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3QWPKzv9pj2gOlTblzLmM
+CcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPwyJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCm
+fecqQjuCgGOlYx8ZzHyyZqjC0203b+J+BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKA
+A1GqtH6qRNdDYfOiaxaJSaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9OR
+JitHHmkHr96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj04KlG
+DfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9MedKZssCz3AwyIDMvU
+clOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIwq7ejMZdnrY8XD2zHc+0klGvIg5rQ
+mjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1Ud
+IwQYMBaAFNwuH9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA
+VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJCXtzoRlgHNQIw
+4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd6IwPS3BD0IL/qMy/pJTAvoe9
+iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf+I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS
+8cE54+X1+NZK3TTN+2/BT+MAi1bikvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2
+HcqtbepBEX4tdJP7wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxS
+vTOBTI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6CMUO+1918
+oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn4rnvyOL2NSl6dPrFf4IF
+YqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+IaFvowdlxfv1k7/9nR4hYJS8+hge9+6jl
+gqispdNpQ80xiEmEU5LAsTkbOYMBMMTyqfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg==
+-----END CERTIFICATE-----
+
+ANF Secure Server Root CA
+=========================
+-----BEGIN CERTIFICATE-----
+MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNVBAUTCUc2MzI4
+NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lv
+bjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNVBAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3Qg
+Q0EwHhcNMTkwOTA0MTAwMDM4WhcNMzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEw
+MQswCQYDVQQGEwJFUzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQw
+EgYDVQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9vdCBDQTCC
+AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCjcqQZAZ2cC4Ffc0m6p6zz
+BE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9qyGFOtibBTI3/TO80sh9l2Ll49a2pcbnv
+T1gdpd50IJeh7WhM3pIXS7yr/2WanvtH2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcv
+B2VSAKduyK9o7PQUlrZXH1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXse
+zx76W0OLzc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyRp1RM
+VwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQzW7i1o0TJrH93PB0j
+7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/SiOL9V8BY9KHcyi1Swr1+KuCLH5z
+JTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJnLNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe
+8TZBAQIvfXOn3kLMTOmJDVb3n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVO
+Hj1tyRRM4y5Bu8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj
+o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAOBgNVHQ8BAf8E
+BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEATh65isagmD9uw2nAalxJ
+UqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzx
+j6ptBZNscsdW699QIyjlRRA96Gejrw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDt
+dD+4E5UGUcjohybKpFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM
+5gf0vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjqOknkJjCb
+5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ/zo1PqVUSlJZS2Db7v54
+EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ92zg/LFis6ELhDtjTO0wugumDLmsx2d1H
+hk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI+PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGy
+g77FGr8H6lnco4g175x2MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3
+r5+qPeoott7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw=
+-----END CERTIFICATE-----
+
+Certum EC-384 CA
+================
+-----BEGIN CERTIFICATE-----
+MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQswCQYDVQQGEwJQ
+TDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2
+MDcyNDU0WhcNNDMwMzI2MDcyNDU0WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERh
+dGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx
+GTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATEKI6rGFtq
+vm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7TmFy8as10CW4kjPMIRBSqn
+iBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68KjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
+VR0OBBYEFI0GZnQkdjrzife81r1HfS+8EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNo
+ADBlAjADVS2m5hjEfO/JUG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0
+QoSZ/6vnnvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k=
+-----END CERTIFICATE-----
+
+Certum Trusted Root CA
+======================
+-----BEGIN CERTIFICATE-----
+MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6MQswCQYDVQQG
+EwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0g
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0Ew
+HhcNMTgwMzE2MTIxMDEzWhcNNDMwMzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMY
+QXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZn0EGze2jusDbCSzBfN8p
+fktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/qp1x4EaTByIVcJdPTsuclzxFUl6s1wB52
+HO8AU5853BSlLCIls3Jy/I2z5T4IHhQqNwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2
+fJmItdUDmj0VDT06qKhF8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGt
+g/BKEiJ3HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGamqi4
+NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi7VdNIuJGmj8PkTQk
+fVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSFytKAQd8FqKPVhJBPC/PgP5sZ0jeJ
+P/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0PqafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSY
+njYJdmZm/Bo/6khUHL4wvYBQv3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHK
+HRzQ+8S1h9E6Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1
+vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQADggIBAEii1QAL
+LtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4WxmB82M+w85bj/UvXgF2Ez8s
+ALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvozMrnadyHncI013nR03e4qllY/p0m+jiGPp2K
+h2RX5Rc64vmNueMzeMGQ2Ljdt4NR5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8
+CYyqOhNf6DR5UMEQGfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA
+4kZf5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq0Uc9Nneo
+WWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7DP78v3DSk+yshzWePS/Tj
+6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTMqJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmT
+OPQD8rv7gmsHINFSH5pkAnuYZttcTVoP0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZck
+bxJF0WddCajJFdr60qZfE2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb
+-----END CERTIFICATE-----
+
+TunTrust Root CA
+================
+-----BEGIN CERTIFICATE-----
+MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQELBQAwYTELMAkG
+A1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUgQ2VydGlmaWNhdGlvbiBFbGVj
+dHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJvb3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQw
+NDI2MDg1NzU2WjBhMQswCQYDVQQGEwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBD
+ZXJ0aWZpY2F0aW9uIEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIw
+DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZn56eY+hz
+2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd2JQDoOw05TDENX37Jk0b
+bjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgFVwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7
+NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZGoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAd
+gjH8KcwAWJeRTIAAHDOFli/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViW
+VSHbhlnUr8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2eY8f
+Tpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIbMlEsPvLfe/ZdeikZ
+juXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISgjwBUFfyRbVinljvrS5YnzWuioYas
+DXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwS
+VXAkPcvCFDVDXSdOvsC9qnyW5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI
+04Y+oXNZtPdEITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0
+90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+zxiD2BkewhpMl
+0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYuQEkHDVneixCwSQXi/5E/S7fd
+Ao74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRY
+YdZ2vyJ/0Adqp2RT8JeNnYA/u8EH22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJp
+adbGNjHh/PqAulxPxOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65x
+xBzndFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5Xc0yGYuP
+jCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7bnV2UqL1g52KAdoGDDIzM
+MEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQCvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9z
+ZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZHu/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3r
+AZ3r2OvEhJn7wAzMMujjd9qDRIueVSjAi1jTkD5OGwDxFa2DK5o=
+-----END CERTIFICATE-----
+
+HARICA TLS RSA Root CA 2021
+===========================
+-----BEGIN CERTIFICATE-----
+MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQG
+EwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u
+cyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0EgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUz
+OFoXDTQ1MDIxMzEwNTUzN1owbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRl
+bWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNB
+IFJvb3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569lmwVnlskN
+JLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE4VGC/6zStGndLuwRo0Xu
+a2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uva9of08WRiFukiZLRgeaMOVig1mlDqa2Y
+Ulhu2wr7a89o+uOkXjpFc5gH6l8Cct4MpbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K
+5FrZx40d/JiZ+yykgmvwKh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEv
+dmn8kN3bLW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcYAuUR
+0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqBAGMUuTNe3QvboEUH
+GjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYqE613TBoYm5EPWNgGVMWX+Ko/IIqm
+haZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHrW2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQ
+CPxrvrNQKlr9qEgYRtaQQJKQCoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8G
+A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE
+AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAUX15QvWiWkKQU
+EapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3f5Z2EMVGpdAgS1D0NTsY9FVq
+QRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxajaH6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxD
+QpSbIPDRzbLrLFPCU3hKTwSUQZqPJzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcR
+j88YxeMn/ibvBZ3PzzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5
+vZStjBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0/L5H9MG0
+qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pTBGIBnfHAT+7hOtSLIBD6
+Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79aPib8qXPMThcFarmlwDB31qlpzmq6YR/
+PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YWxw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnn
+kf3/W9b3raYvAwtt41dU63ZTGI0RmLo=
+-----END CERTIFICATE-----
+
+HARICA TLS ECC Root CA 2021
+===========================
+-----BEGIN CERTIFICATE-----
+MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQswCQYDVQQGEwJH
+UjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBD
+QTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoX
+DTQ1MDIxMzExMDEwOVowbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWlj
+IGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJv
+b3QgQ0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7KKrxcm1l
+AEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9YSTHMmE5gEYd103KUkE+b
+ECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW
+0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAi
+rcJRQO9gcS3ujwLEXQNwSaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/Qw
+CZ61IygNnxS2PFOiTAZpffpskcYqSUXm7LcT4Tps
+-----END CERTIFICATE-----
+
+Autoridad de Certificacion Firmaprofesional CIF A62634068
+=========================================================
+-----BEGIN CERTIFICATE-----
+MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCRVMxQjBA
+BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
+MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIw
+QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
+NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
+Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
+B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
+7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
+ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
+plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
+MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
+LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
+bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
+vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1Ud
+DgQWBBRlzeurNR4APn7VdMActHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4w
+gZswgZgGBFUdIAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j
+b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABCAG8AbgBhAG4A
+bwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAwADEANzAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9miWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL
+4QjbEwj4KKE1soCzC1HA01aajTNFSa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDb
+LIpgD7dvlAceHabJhfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1il
+I45PVf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZEEAEeiGaP
+cjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV1aUsIC+nmCjuRfzxuIgA
+LI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2tCsvMo2ebKHTEm9caPARYpoKdrcd7b/+A
+lun4jWq9GJAd/0kakFI3ky88Al2CdgtR5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH
+9IBk9W6VULgRfhVwOEqwf9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpf
+NIbnYrX9ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNKGbqE
+ZycPvEJdvSRUDewdcAZfpLz6IHxV
+-----END CERTIFICATE-----
+
+vTrus ECC Root CA
+=================
+-----BEGIN CERTIFICATE-----
+MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMwRzELMAkGA1UE
+BhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBS
+b290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDczMTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAa
+BgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYw
+EAYHKoZIzj0CAQYFK4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+c
+ToL0v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUde4BdS49n
+TPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIwV53dVvHH4+m4SVBrm2nDb+zDfSXkV5UT
+QJtS0zvzQBm8JsctBp61ezaf9SXUY2sAAjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQL
+YgmRWAD5Tfs0aNoJrSEGGJTO
+-----END CERTIFICATE-----
+
+vTrus Root CA
+=============
+-----BEGIN CERTIFICATE-----
+MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQELBQAwQzELMAkG
+A1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xFjAUBgNVBAMTDXZUcnVzIFJv
+b3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMxMDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoG
+A1UEChMTaVRydXNDaGluYSBDby4sTHRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZots
+SKYcIrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykUAyyNJJrI
+ZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+GrPSbcKvdmaVayqwlHeF
+XgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z98Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KA
+YPxMvDVTAWqXcoKv8R1w6Jz1717CbMdHflqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70
+kLJrxLT5ZOrpGgrIDajtJ8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2
+AXPKBlim0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZNpGvu
+/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQUqqzApVg+QxMaPnu
+1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHWOXSuTEGC2/KmSNGzm/MzqvOmwMVO
+9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMBAAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYg
+scasGrz2iTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOC
+AgEAKbqSSaet8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd
+nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1jbhd47F18iMjr
+jld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvMKar5CKXiNxTKsbhm7xqC5PD4
+8acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIivTDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJn
+xDHO2zTlJQNgJXtxmOTAGytfdELSS8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554Wg
+icEFOwE30z9J4nfrI8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4
+sEb9b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNBUvupLnKW
+nyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1PTi07NEPhmg4NpGaXutIc
+SkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929vensBxXVsFy6K2ir40zSbofitzmdHxghm+H
+l3s=
+-----END CERTIFICATE-----
+
+ISRG Root X2
+============
+-----BEGIN CERTIFICATE-----
+MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQswCQYDVQQGEwJV
+UzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElT
+UkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVT
+MSkwJwYDVQQKEyBJbnRlcm5ldCBTZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNS
+RyBSb290IFgyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0H
+ttwW+1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9ItgKbppb
+d9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZIzj0EAwMDaAAwZQIwe3lORlCEwkSHRhtF
+cP9Ymd70/aTSVaYgLXTWNLxBo1BfASdWtL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5
+U6VR5CmD1/iQMVtCnwr1/q4AaOeMSQ+2b1tbFfLn
+-----END CERTIFICATE-----
+
+HiPKI Root CA - G1
+==================
+-----BEGIN CERTIFICATE-----
+MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQG
+EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xGzAZBgNVBAMMEkhpUEtJ
+IFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRaFw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYT
+AlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kg
+Um9vdCBDQSAtIEcxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0
+o9QwqNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twvVcg3Px+k
+wJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6lZgRZq2XNdZ1AYDgr/SE
+YYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnzQs7ZngyzsHeXZJzA9KMuH5UHsBffMNsA
+GJZMoYFL3QRtU6M9/Aes1MU3guvklQgZKILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfd
+hSi8MEyr48KxRURHH+CKFgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj
+1jOXTyFjHluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDry+K4
+9a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ/W3c1pzAtH2lsN0/
+Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgMa/aOEmem8rJY5AIJEzypuxC00jBF
+8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQD
+AgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi
+7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqcSE5XCV0vrPSl
+tJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6FzaZsT0pPBWGTMpWmWSBUdGSquE
+wx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9TcXzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07Q
+JNBAsNB1CI69aO4I1258EHBGG3zgiLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv
+5wiZqAxeJoBF1PhoL5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+Gpz
+jLrFNe85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wrkkVbbiVg
+hUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+vhV4nYWBSipX3tUZQ9rb
+yltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQUYDksswBVLuT1sw5XxJFBAJw/6KXf6vb/
+yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ==
+-----END CERTIFICATE-----
+
+GlobalSign ECC Root CA - R4
+===========================
+-----BEGIN CERTIFICATE-----
+MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYDVQQLExtHbG9i
+YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds
+b2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgwMTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9i
+YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds
+b2JhbFNpZ24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkW
+ymOxuYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNVHQ8BAf8E
+BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/+wpu+74zyTyjhNUwCgYI
+KoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147bmF0774BxL4YSFlhgjICICadVGNA3jdg
+UM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm
+-----END CERTIFICATE-----
+
+GTS Root R1
+===========
+-----BEGIN CERTIFICATE-----
+MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV
+UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
+UjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
+ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM
+f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7raKb0
+xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnWr4+w
+B7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXW
+nOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk
+9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zq
+kUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92wO1A
+K/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om3xPX
+V2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDW
+cfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T
+AQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQAD
+ggIBAJ+qQibbC5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe
+QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuyh6f88/qBVRRi
+ClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM47HLwEXWdyzRSjeZ2axfG34ar
+J45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8JZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYci
+NuaCp+0KueIHoI17eko8cdLiA6EfMgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5me
+LMFrUKTX5hgUvYU/Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJF
+fbdT6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ0E6yove+
+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm2tIMPNuzjsmhDYAPexZ3
+FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bbbP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3
+gm3c
+-----END CERTIFICATE-----
+
+GTS Root R2
+===========
+-----BEGIN CERTIFICATE-----
+MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV
+UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
+UjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
+ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv
+CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo7JUl
+e3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWIm8Wb
+a96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS
++LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7M
+kogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJG
+r61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RWIr9q
+S34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73VululycslaVNV
+J1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy5okL
+dWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T
+AQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQAD
+ggIBAB/Kzt3HvqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8
+0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyCB19m3H0Q/gxh
+swWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2uNmSRXbBoGOqKYcl3qJfEycel
+/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMgyALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVn
+jWQye+mew4K6Ki3pHrTgSAai/GevHyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y5
+9PYjJbigapordwj6xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M
+7YNRTOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924SgJPFI/2R8
+0L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV7LXTWtiBmelDGDfrs7vR
+WGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjW
+HYbL
+-----END CERTIFICATE-----
+
+GTS Root R3
+===========
+-----BEGIN CERTIFICATE-----
+MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi
+MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMw
+HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ
+R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjO
+PQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout
+736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24CejQjBA
+MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP0/Eq
+Er24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azT
+L818+FsuVbu/3ZL3pAzcMeGiAjEA/JdmZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV
+11RZt+cRLInUue4X
+-----END CERTIFICATE-----
+
+GTS Root R4
+===========
+-----BEGIN CERTIFICATE-----
+MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi
+MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQw
+HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ
+R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjO
+PQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu
+hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqjQjBA
+MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV2Py1
+PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/C
+r8deVl5c1RxYIigL9zC2L7F8AjEA8GE8p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh
+4rsUecrNIdSUtUlD
+-----END CERTIFICATE-----
+
+Telia Root CA v2
+================
+-----BEGIN CERTIFICATE-----
+MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQxCzAJBgNVBAYT
+AkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2
+MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQK
+DBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZI
+hvcNAQEBBQADggIPADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ7
+6zBqAMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9vVYiQJ3q
+9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9lRdU2HhE8Qx3FZLgmEKn
+pNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTODn3WhUidhOPFZPY5Q4L15POdslv5e2QJl
+tI5c0BE0312/UqeBAMN/mUWZFdUXyApT7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW
+5olWK8jjfN7j/4nlNW4o6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNr
+RBH0pUPCTEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6WT0E
+BXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63RDolUK5X6wK0dmBR4
+M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZIpEYslOqodmJHixBTB0hXbOKSTbau
+BcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGjYzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7W
+xy+G2CQ5MB0GA1UdDgQWBBRyrOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ
+8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi0f6X+J8wfBj5
+tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMMA8iZGok1GTzTyVR8qPAs5m4H
+eW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBSSRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+C
+y748fdHif64W1lZYudogsYMVoe+KTTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygC
+QMez2P2ccGrGKMOF6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15
+h2Er3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMtTy3EHD70
+sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pTVmBds9hCG1xLEooc6+t9
+xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAWysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQ
+raVplI/owd8k+BsHMYeB2F326CjYSlKArBPuUBQemMc=
+-----END CERTIFICATE-----
+
+D-TRUST BR Root CA 1 2020
+=========================
+-----BEGIN CERTIFICATE-----
+MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE
+RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEJSIFJvb3QgQ0EgMSAy
+MDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNV
+BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7
+dPYSzuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0QVK5buXu
+QqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/VbNafAkl1bK6CKBrqx9t
+MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu
+bmV0L2NybC9kLXRydXN0X2JyX3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj
+dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP
+PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD
+AwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFWwKrY7RjEsK70Pvom
+AjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHVdWNbFJWcHwHP2NVypw87
+-----END CERTIFICATE-----
+
+D-TRUST EV Root CA 1 2020
+=========================
+-----BEGIN CERTIFICATE-----
+MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE
+RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEVWIFJvb3QgQ0EgMSAy
+MDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNV
+BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8
+ZRCC/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rDwpdhQntJ
+raOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3OqQo5FD4pPfsazK2/umL
+MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu
+bmV0L2NybC9kLXRydXN0X2V2X3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj
+dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP
+PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD
+AwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CAy/m0sRtW9XLS/BnR
+AjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJbgfM0agPnIjhQW+0ZT0MW
+-----END CERTIFICATE-----
+
+DigiCert TLS ECC P384 Root G5
+=============================
+-----BEGIN CERTIFICATE-----
+MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURpZ2lDZXJ0IFRMUyBFQ0MgUDM4
+NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMx
+FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQg
+Um9vdCBHNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1Tzvd
+lHJS7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp0zVozptj
+n4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICISB4CIfBFqMA4GA1UdDwEB
+/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQCJao1H5+z8blUD2Wds
+Jk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQLgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIx
+AJSdYsiJvRmEFOml+wG4DXZDjC5Ty3zfDBeWUA==
+-----END CERTIFICATE-----
+
+DigiCert TLS RSA4096 Root G5
+============================
+-----BEGIN CERTIFICATE-----
+MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBNMQswCQYDVQQG
+EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0
+MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcNNDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2
+IFJvb3QgRzUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS8
+7IE+ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG02C+JFvuU
+AT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgpwgscONyfMXdcvyej/Ces
+tyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZMpG2T6T867jp8nVid9E6P/DsjyG244gXa
+zOvswzH016cpVIDPRFtMbzCe88zdH5RDnU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnV
+DdXifBBiqmvwPXbzP6PosMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9q
+TXeXAaDxZre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cdLvvy
+z6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvXKyY//SovcfXWJL5/
+MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNeXoVPzthwiHvOAbWWl9fNff2C+MIk
+wcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPLtgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4E
+FgQUUTMc7TZArxfTJc1paPKvTiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8w
+DQYJKoZIhvcNAQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw
+GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7HPNtQOa27PShN
+lnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLFO4uJ+DQtpBflF+aZfTCIITfN
+MBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQREtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/
+u4cnYiWB39yhL/btp/96j1EuMPikAdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9G
+OUrYU9DzLjtxpdRv/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh
+47a+p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilwMUc/dNAU
+FvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WFqUITVuwhd4GTWgzqltlJ
+yqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCKovfepEWFJqgejF0pW8hL2JpqA15w8oVP
+bEtoL8pU9ozaMv7Da4M/OMZ+
+-----END CERTIFICATE-----
+
+Certainly Root R1
+=================
+-----BEGIN CERTIFICATE-----
+MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAwPTELMAkGA1UE
+BhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2VydGFpbmx5IFJvb3QgUjEwHhcN
+MjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2Vy
+dGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBANA21B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O
+5MQTvqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbedaFySpvXl
+8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b01C7jcvk2xusVtyWMOvwl
+DbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGI
+XsXwClTNSaa/ApzSRKft43jvRl5tcdF5cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkN
+KPl6I7ENPT2a/Z2B7yyQwHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQ
+AjeZjOVJ6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA2Cnb
+rlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyHWyf5QBGenDPBt+U1
+VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMReiFPCyEQtkA6qyI6BJyLm4SGcprS
+p6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
+DgQWBBTgqj8ljZ9EXME66C6ud0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAsz
+HQNTVfSVcOQrPbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d
+8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi1wrykXprOQ4v
+MMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrdrRT90+7iIgXr0PK3aBLXWopB
+GsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9ditaY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+
+gjwN/KUD+nsa2UUeYNrEjvn8K8l7lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgH
+JBu6haEaBQmAupVjyTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7
+fpYnKx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLyyCwzk5Iw
+x06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5nwXARPbv0+Em34yaXOp/S
+X3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6OV+KmalBWQewLK8=
+-----END CERTIFICATE-----
+
+Certainly Root E1
+=================
+-----BEGIN CERTIFICATE-----
+MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQswCQYDVQQGEwJV
+UzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBFMTAeFw0yMTA0
+MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlu
+bHkxGjAYBgNVBAMTEUNlcnRhaW5seSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4
+fxzf7flHh4axpMCK+IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9
+YBk2QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8EBAMCAQYw
+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4hevIIgcwCgYIKoZIzj0E
+AwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozmut6Dacpps6kFtZaSF4fC0urQe87YQVt8
+rgIwRt7qy12a7DLCZRawTDBcMPPaTnOGBtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR
+-----END CERTIFICATE-----
+
+Security Communication RootCA3
+==============================
+-----BEGIN CERTIFICATE-----
+MIIFfzCCA2egAwIBAgIJAOF8N0D9G/5nMA0GCSqGSIb3DQEBDAUAMF0xCzAJBgNVBAYTAkpQMSUw
+IwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQDEx5TZWN1cml0eSBD
+b21tdW5pY2F0aW9uIFJvb3RDQTMwHhcNMTYwNjE2MDYxNzE2WhcNMzgwMTE4MDYxNzE2WjBdMQsw
+CQYDVQQGEwJKUDElMCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UE
+AxMeU2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEA48lySfcw3gl8qUCBWNO0Ot26YQ+TUG5pPDXC7ltzkBtnTCHsXzW7OT4rCmDvu20r
+hvtxosis5FaU+cmvsXLUIKx00rgVrVH+hXShuRD+BYD5UpOzQD11EKzAlrenfna84xtSGc4RHwsE
+NPXY9Wk8d/Nk9A2qhd7gCVAEF5aEt8iKvE1y/By7z/MGTfmfZPd+pmaGNXHIEYBMwXFAWB6+oHP2
+/D5Q4eAvJj1+XCO1eXDe+uDRpdYMQXF79+qMHIjH7Iv10S9VlkZ8WjtYO/u62C21Jdp6Ts9EriGm
+npjKIG58u4iFW/vAEGK78vknR+/RiTlDxN/e4UG/VHMgly1s2vPUB6PmudhvrvyMGS7TZ2crldtY
+XLVqAvO4g160a75BflcJdURQVc1aEWEhCmHCqYj9E7wtiS/NYeCVvsq1e+F7NGcLH7YMx3weGVPK
+p7FKFSBWFHA9K4IsD50VHUeAR/94mQ4xr28+j+2GaR57GIgUssL8gjMunEst+3A7caoreyYn8xrC
+3PsXuKHqy6C0rtOUfnrQq8PsOC0RLoi/1D+tEjtCrI8Cbn3M0V9hvqG8OmpI6iZVIhZdXw3/JzOf
+GAN0iltSIEdrRU0id4xVJ/CvHozJgyJUt5rQT9nO/NkuHJYosQLTA70lUhw0Zk8jq/R3gpYd0Vcw
+CBEF/VfR2ccCAwEAAaNCMEAwHQYDVR0OBBYEFGQUfPxYchamCik0FW8qy7z8r6irMA4GA1UdDwEB
+/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDAUAA4ICAQDcAiMI4u8hOscNtybS
+YpOnpSNyByCCYN8Y11StaSWSntkUz5m5UoHPrmyKO1o5yGwBQ8IibQLwYs1OY0PAFNr0Y/Dq9HHu
+Tofjcan0yVflLl8cebsjqodEV+m9NU1Bu0soo5iyG9kLFwfl9+qd9XbXv8S2gVj/yP9kaWJ5rW4O
+H3/uHWnlt3Jxs/6lATWUVCvAUm2PVcTJ0rjLyjQIUYWg9by0F1jqClx6vWPGOi//lkkZhOpn2ASx
+YfQAW0q3nHE3GYV5v4GwxxMOdnE+OoAGrgYWp421wsTL/0ClXI2lyTrtcoHKXJg80jQDdwj98ClZ
+XSEIx2C/pHF7uNkegr4Jr2VvKKu/S7XuPghHJ6APbw+LP6yVGPO5DtxnVW5inkYO0QR4ynKudtml
++LLfiAlhi+8kTtFZP1rUPcmTPCtk9YENFpb3ksP+MW/oKjJ0DvRMmEoYDjBU1cXrvMUVnuiZIesn
+KwkK2/HmcBhWuwzkvvnoEKQTkrgc4NtnHVMDpCKn3F2SEDzq//wbEBrD2NCcnWXL0CsnMQMeNuE9
+dnUM/0Umud1RvCPHX9jYhxBAEg09ODfnRDwYwFMJZI//1ZqmfHAuc1Uh6N//g7kdPjIe1qZ9LPFm
+6Vwdp6POXiUyK+OVrCoHzrQoeIY8LaadTdJ0MN1kURXbg4NR16/9M51NZg==
+-----END CERTIFICATE-----
+
+Security Communication ECC RootCA1
+==================================
+-----BEGIN CERTIFICATE-----
+MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYTAkpQMSUwIwYD
+VQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYDVQQDEyJTZWN1cml0eSBDb21t
+dW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYxNjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTEL
+MAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNV
+BAMTIlNlY3VyaXR5IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+CnnfdldB9sELLo
+5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpKULGjQjBAMB0GA1UdDgQW
+BBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAK
+BggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3L
+snNdo4gIxwwCMQDAqy0Obe0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70e
+N9k=
+-----END CERTIFICATE-----
+
+BJCA Global Root CA1
+====================
+-----BEGIN CERTIFICATE-----
+MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQG
+EwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJVFkxHTAbBgNVBAMMFEJK
+Q0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAzMTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkG
+A1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQD
+DBRCSkNBIEdsb2JhbCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFm
+CL3ZxRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZspDyRhyS
+sTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O558dnJCNPYwpj9mZ9S1Wn
+P3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgRat7GGPZHOiJBhyL8xIkoVNiMpTAK+BcW
+yqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRj
+eulumijWML3mG90Vr4TqnMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNn
+MoH1V6XKV0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/pj+b
+OT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZOz2nxbkRs1CTqjSSh
+GL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXnjSXWgXSHRtQpdaJCbPdzied9v3pK
+H9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMB
+AAGjQjBAMB0GA1UdDgQWBBTF7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4
+YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3KliawLwQ8hOnThJ
+dMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u+2D2/VnGKhs/I0qUJDAnyIm8
+60Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuh
+TaRjAv04l5U/BXCga99igUOLtFkNSoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW
+4AB+dAb/OMRyHdOoP2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmp
+GQrI+pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRzznfSxqxx
+4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9eVzYH6Eze9mCUAyTF6ps
+3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4S
+SPfSKcOYKMryMguTjClPPGAyzQWWYezyr/6zcCwupvI=
+-----END CERTIFICATE-----
+
+BJCA Global Root CA2
+====================
+-----BEGIN CERTIFICATE-----
+MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQswCQYDVQQGEwJD
+TjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJVFkxHTAbBgNVBAMMFEJKQ0Eg
+R2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgyMVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UE
+BhMCQ04xJjAkBgNVBAoMHUJFSUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRC
+SkNBIEdsb2JhbCBSb290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jl
+SR9BIgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK++kpRuDCK
+/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJKsVF/BvDRgh9Obl+rg/xI
+1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8
+W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8g
+UXOQwKhbYdDFUDn9hf7B43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w==
+-----END CERTIFICATE-----
+
+Sectigo Public Server Authentication Root E46
+=============================================
+-----BEGIN CERTIFICATE-----
+MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQswCQYDVQQGEwJH
+QjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBTZXJ2
+ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5
+WjBfMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0
+aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUr
+gQQAIgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccCWvkEN/U0
+NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+6xnOQ6OjQjBAMB0GA1Ud
+DgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
+/zAKBggqhkjOPQQDAwNnADBkAjAn7qRaqCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RH
+lAFWovgzJQxC36oCMB3q4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21U
+SAGKcw==
+-----END CERTIFICATE-----
+
+Sectigo Public Server Authentication Root R46
+=============================================
+-----BEGIN CERTIFICATE-----
+MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBfMQswCQYDVQQG
+EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT
+ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwHhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1
+OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T
+ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3
+DQEBAQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDaef0rty2k
+1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnzSDBh+oF8HqcIStw+Kxwf
+GExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xfiOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMP
+FF1bFOdLvt30yNoDN9HWOaEhUTCDsG3XME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vu
+ZDCQOc2TZYEhMbUjUDM3IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5Qaz
+Yw6A3OASVYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgESJ/A
+wSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu+Zd4KKTIRJLpfSYF
+plhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt8uaZFURww3y8nDnAtOFr94MlI1fZ
+EoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+LHaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW
+6aWWrL3DkJiy4Pmi1KZHQ3xtzwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWI
+IUkwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c
+mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQYKlJfp/imTYp
+E0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52gDY9hAaLMyZlbcp+nv4fjFg4
+exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZAFv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M
+0ejf5lG5Nkc/kLnHvALcWxxPDkjBJYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI
+84HxZmduTILA7rpXDhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9m
+pFuiTdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5dHn5Hrwd
+Vw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65LvKRRFHQV80MNNVIIb/b
+E/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmm
+J1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAYQqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL
+-----END CERTIFICATE-----
+
+SSL.com TLS RSA Root CA 2022
+============================
+-----BEGIN CERTIFICATE-----
+MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQG
+EwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxTU0wuY29tIFRMUyBSU0Eg
+Um9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloXDTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMC
+VVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJv
+b3QgQ0EgMjAyMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u
+9nTPL3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OYt6/wNr/y
+7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0insS657Lb85/bRi3pZ7Qcac
+oOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3PnxEX4MN8/HdIGkWCVDi1FW24IBydm5M
+R7d1VVm0U3TZlMZBrViKMWYPHqIbKUBOL9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDG
+D6C1vBdOSHtRwvzpXGk3R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEW
+TO6Af77wdr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS+YCk
+8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYSd66UNHsef8JmAOSq
+g+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoGAtUjHBPW6dvbxrB6y3snm/vg1UYk
+7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2fgTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1Ud
+EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsu
+N+7jhHonLs0ZNbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt
+hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsMQtfhWsSWTVTN
+j8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvfR4iyrT7gJ4eLSYwfqUdYe5by
+iB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJDPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjU
+o3KUQyxi4U5cMj29TH0ZR6LDSeeWP4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqo
+ENjwuSfr98t67wVylrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7Egkaib
+MOlqbLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2wAgDHbICi
+vRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3qr5nsLFR+jM4uElZI7xc7
+P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sjiMho6/4UIyYOf8kpIEFR3N+2ivEC+5BB0
+9+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA=
+-----END CERTIFICATE-----
+
+SSL.com TLS ECC Root CA 2022
+============================
+-----BEGIN CERTIFICATE-----
+MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV
+UzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxTU0wuY29tIFRMUyBFQ0MgUm9v
+dCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMx
+GDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3Qg
+Q0EgMjAyMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWy
+JGYmacCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFNSeR7T5v1
+5wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSJjy+j6CugFFR7
+81a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NWuCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGG
+MAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w
+7deedWo1dlJF4AIxAMeNb0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5
+Zn6g6g==
+-----END CERTIFICATE-----
+
+Atos TrustedRoot Root CA ECC TLS 2021
+=====================================
+-----BEGIN CERTIFICATE-----
+MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4wLAYDVQQDDCVB
+dG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0wCwYDVQQKDARBdG9zMQswCQYD
+VQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3Mg
+VHJ1c3RlZFJvb3QgUm9vdCBDQSBFQ0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYT
+AkRFMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6K
+DP/XtXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4AjJn8ZQS
+b+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2KCXWfeBmmnoJsmo7jjPX
+NtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMDaAAwZQIwW5kp85wxtolrbNa9d+F851F+
+uDrNozZffPc8dz7kUK2o59JZDCaOMDtuCCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGY
+a3cpetskz2VAv9LcjBHo9H1/IISpQuQo
+-----END CERTIFICATE-----
+
+Atos TrustedRoot Root CA RSA TLS 2021
+=====================================
+-----BEGIN CERTIFICATE-----
+MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBMMS4wLAYDVQQD
+DCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIxMQ0wCwYDVQQKDARBdG9zMQsw
+CQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0
+b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNV
+BAYTAkRFMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BB
+l01Z4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYvYe+W/CBG
+vevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZkmGbzSoXfduP9LVq6hdK
+ZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDsGY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt
+0xU6kGpn8bRrZtkh68rZYnxGEFzedUlnnkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVK
+PNe0OwANwI8f4UDErmwh3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMY
+sluMWuPD0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzygeBY
+Br3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8ANSbhqRAvNncTFd+
+rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezBc6eUWsuSZIKmAMFwoW4sKeFYV+xa
+fJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lIpw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUdEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0G
+CSqGSIb3DQEBDAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS
+4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPso0UvFJ/1TCpl
+Q3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJqM7F78PRreBrAwA0JrRUITWX
+AdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuywxfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9G
+slA9hGCZcbUztVdF5kJHdWoOsAgMrr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2Vkt
+afcxBPTy+av5EzH4AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9q
+TFsR0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuYo7Ey7Nmj
+1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5dDTedk+SKlOxJTnbPP/l
+PqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcEoji2jbDwN/zIIX8/syQbPYtuzE2wFg2W
+HYMfRsCbvUOZ58SWLs5fyQ==
+-----END CERTIFICATE-----
+
+TrustAsia Global Root CA G3
+===========================
+-----BEGIN CERTIFICATE-----
+MIIFpTCCA42gAwIBAgIUZPYOZXdhaqs7tOqFhLuxibhxkw8wDQYJKoZIhvcNAQEMBQAwWjELMAkG
+A1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xJDAiBgNVBAMM
+G1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHMzAeFw0yMTA1MjAwMjEwMTlaFw00NjA1MTkwMjEw
+MTlaMFoxCzAJBgNVBAYTAkNOMSUwIwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMu
+MSQwIgYDVQQDDBtUcnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzMwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDAMYJhkuSUGwoqZdC+BqmHO1ES6nBBruL7dOoKjbmzTNyPtxNST1QY4Sxz
+lZHFZjtqz6xjbYdT8PfxObegQ2OwxANdV6nnRM7EoYNl9lA+sX4WuDqKAtCWHwDNBSHvBm3dIZwZ
+Q0WhxeiAysKtQGIXBsaqvPPW5vxQfmZCHzyLpnl5hkA1nyDvP+uLRx+PjsXUjrYsyUQE49RDdT/V
+P68czH5GX6zfZBCK70bwkPAPLfSIC7Epqq+FqklYqL9joDiR5rPmd2jE+SoZhLsO4fWvieylL1Ag
+dB4SQXMeJNnKziyhWTXAyB1GJ2Faj/lN03J5Zh6fFZAhLf3ti1ZwA0pJPn9pMRJpxx5cynoTi+jm
+9WAPzJMshH/x/Gr8m0ed262IPfN2dTPXS6TIi/n1Q1hPy8gDVI+lhXgEGvNz8teHHUGf59gXzhqc
+D0r83ERoVGjiQTz+LISGNzzNPy+i2+f3VANfWdP3kXjHi3dqFuVJhZBFcnAvkV34PmVACxmZySYg
+WmjBNb9Pp1Hx2BErW+Canig7CjoKH8GB5S7wprlppYiU5msTf9FkPz2ccEblooV7WIQn3MSAPmea
+mseaMQ4w7OYXQJXZRe0Blqq/DPNL0WP3E1jAuPP6Z92bfW1K/zJMtSU7/xxnD4UiWQWRkUF3gdCF
+TIcQcf+eQxuulXUtgQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEDk5PIj
+7zjKsK5Xf/IhMBY027ySMB0GA1UdDgQWBBRA5OTyI+84yrCuV3/yITAWNNu8kjAOBgNVHQ8BAf8E
+BAMCAQYwDQYJKoZIhvcNAQEMBQADggIBACY7UeFNOPMyGLS0XuFlXsSUT9SnYaP4wM8zAQLpw6o1
+D/GUE3d3NZ4tVlFEbuHGLige/9rsR82XRBf34EzC4Xx8MnpmyFq2XFNFV1pF1AWZLy4jVe5jaN/T
+G3inEpQGAHUNcoTpLrxaatXeL1nHo+zSh2bbt1S1JKv0Q3jbSwTEb93mPmY+KfJLaHEih6D4sTNj
+duMNhXJEIlU/HHzp/LgV6FL6qj6jITk1dImmasI5+njPtqzn59ZW/yOSLlALqbUHM/Q4X6RJpstl
+cHboCoWASzY9M/eVVHUl2qzEc4Jl6VL1XP04lQJqaTDFHApXB64ipCz5xUG3uOyfT0gA+QEEVcys
++TIxxHWVBqB/0Y0n3bOppHKH/lmLmnp0Ft0WpWIp6zqW3IunaFnT63eROfjXy9mPX1onAX1daBli
+2MjN9LdyR75bl87yraKZk62Uy5P2EgmVtqvXO9A/EcswFi55gORngS1d7XB4tmBZrOFdRWOPyN9y
+aFvqHbgB8X7754qz41SgOAngPN5C8sLtLpvzHzW2NtjjgKGLzZlkD8Kqq7HK9W+eQ42EVJmzbsAS
+ZthwEPEGNTNDqJwuuhQxzhB/HIbjj9LV+Hfsm6vxL2PZQl/gZ4FkkfGXL/xuJvYz+NO1+MRiqzFR
+JQJ6+N1rZdVtTTDIZbpoFGWsJwt0ivKH
+-----END CERTIFICATE-----
+
+TrustAsia Global Root CA G4
+===========================
+-----BEGIN CERTIFICATE-----
+MIICVTCCAdygAwIBAgIUTyNkuI6XY57GU4HBdk7LKnQV1tcwCgYIKoZIzj0EAwMwWjELMAkGA1UE
+BhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xJDAiBgNVBAMMG1Ry
+dXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHNDAeFw0yMTA1MjAwMjEwMjJaFw00NjA1MTkwMjEwMjJa
+MFoxCzAJBgNVBAYTAkNOMSUwIwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQw
+IgYDVQQDDBtUcnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
+AATxs8045CVD5d4ZCbuBeaIVXxVjAd7Cq92zphtnS4CDr5nLrBfbK5bKfFJV4hrhPVbwLxYI+hW8
+m7tH5j/uqOFMjPXTNvk4XatwmkcN4oFBButJ+bAp3TPsUKV/eSm4IJijYzBhMA8GA1UdEwEB/wQF
+MAMBAf8wHwYDVR0jBBgwFoAUpbtKl86zK3+kMd6Xg1mDpm9xy94wHQYDVR0OBBYEFKW7SpfOsyt/
+pDHel4NZg6ZvccveMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjBe8usGzEkxn0AA
+bbd+NvBNEU/zy4k6LHiRUKNbwMp1JvK/kF0LgoxgKJ/GcJpo5PECMFxYDlZ2z1jD1xCMuo6u47xk
+dUfFVZDj/bpV6wfEU6s3qe4hsiFbYI89MvHVI5TWWA==
+-----END CERTIFICATE-----
+
+CommScope Public Trust ECC Root-01
+==================================
+-----BEGIN CERTIFICATE-----
+MIICHTCCAaOgAwIBAgIUQ3CCd89NXTTxyq4yLzf39H91oJ4wCgYIKoZIzj0EAwMwTjELMAkGA1UE
+BhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBUcnVz
+dCBFQ0MgUm9vdC0wMTAeFw0yMTA0MjgxNzM1NDNaFw00NjA0MjgxNzM1NDJaME4xCzAJBgNVBAYT
+AlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3Qg
+RUNDIFJvb3QtMDEwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARLNumuV16ocNfQj3Rid8NeeqrltqLx
+eP0CflfdkXmcbLlSiFS8LwS+uM32ENEp7LXQoMPwiXAZu1FlxUOcw5tjnSCDPgYLpkJEhRGnSjot
+6dZoL0hOUysHP029uax3OVejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
+A1UdDgQWBBSOB2LAUN3GGQYARnQE9/OufXVNMDAKBggqhkjOPQQDAwNoADBlAjEAnDPfQeMjqEI2
+Jpc1XHvr20v4qotzVRVcrHgpD7oh2MSg2NED3W3ROT3Ek2DS43KyAjB8xX6I01D1HiXo+k515liW
+pDVfG2XqYZpwI7UNo5uSUm9poIyNStDuiw7LR47QjRE=
+-----END CERTIFICATE-----
+
+CommScope Public Trust ECC Root-02
+==================================
+-----BEGIN CERTIFICATE-----
+MIICHDCCAaOgAwIBAgIUKP2ZYEFHpgE6yhR7H+/5aAiDXX0wCgYIKoZIzj0EAwMwTjELMAkGA1UE
+BhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBUcnVz
+dCBFQ0MgUm9vdC0wMjAeFw0yMTA0MjgxNzQ0NTRaFw00NjA0MjgxNzQ0NTNaME4xCzAJBgNVBAYT
+AlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3Qg
+RUNDIFJvb3QtMDIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAR4MIHoYx7l63FRD/cHB8o5mXxO1Q/M
+MDALj2aTPs+9xYa9+bG3tD60B8jzljHz7aRP+KNOjSkVWLjVb3/ubCK1sK9IRQq9qEmUv4RDsNuE
+SgMjGWdqb8FuvAY5N9GIIvejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
+A1UdDgQWBBTmGHX/72DehKT1RsfeSlXjMjZ59TAKBggqhkjOPQQDAwNnADBkAjAmc0l6tqvmSfR9
+Uj/UQQSugEODZXW5hYA4O9Zv5JOGq4/nich/m35rChJVYaoR4HkCMHfoMXGsPHED1oQmHhS48zs7
+3u1Z/GtMMH9ZzkXpc2AVmkzw5l4lIhVtwodZ0LKOag==
+-----END CERTIFICATE-----
+
+CommScope Public Trust RSA Root-01
+==================================
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIUPgNJgXUWdDGOTKvVxZAplsU5EN0wDQYJKoZIhvcNAQELBQAwTjELMAkG
+A1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBU
+cnVzdCBSU0EgUm9vdC0wMTAeFw0yMTA0MjgxNjQ1NTRaFw00NjA0MjgxNjQ1NTNaME4xCzAJBgNV
+BAYTAlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1
+c3QgUlNBIFJvb3QtMDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwSGWjDR1C45Ft
+nYSkYZYSwu3D2iM0GXb26v1VWvZVAVMP8syMl0+5UMuzAURWlv2bKOx7dAvnQmtVzslhsuitQDy6
+uUEKBU8bJoWPQ7VAtYXR1HHcg0Hz9kXHgKKEUJdGzqAMxGBWBB0HW0alDrJLpA6lfO741GIDuZNq
+ihS4cPgugkY4Iw50x2tBt9Apo52AsH53k2NC+zSDO3OjWiE260f6GBfZumbCk6SP/F2krfxQapWs
+vCQz0b2If4b19bJzKo98rwjyGpg/qYFlP8GMicWWMJoKz/TUyDTtnS+8jTiGU+6Xn6myY5QXjQ/c
+Zip8UlF1y5mO6D1cv547KI2DAg+pn3LiLCuz3GaXAEDQpFSOm117RTYm1nJD68/A6g3czhLmfTif
+BSeolz7pUcZsBSjBAg/pGG3svZwG1KdJ9FQFa2ww8esD1eo9anbCyxooSU1/ZOD6K9pzg4H/kQO9
+lLvkuI6cMmPNn7togbGEW682v3fuHX/3SZtS7NJ3Wn2RnU3COS3kuoL4b/JOHg9O5j9ZpSPcPYeo
+KFgo0fEbNttPxP/hjFtyjMcmAyejOQoBqsCyMWCDIqFPEgkBEa801M/XrmLTBQe0MXXgDW1XT2mH
++VepuhX2yFJtocucH+X8eKg1mp9BFM6ltM6UCBwJrVbl2rZJmkrqYxhTnCwuwwIDAQABo0IwQDAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUN12mmnQywsL5x6YVEFm4
+5P3luG0wDQYJKoZIhvcNAQELBQADggIBAK+nz97/4L1CjU3lIpbfaOp9TSp90K09FlxD533Ahuh6
+NWPxzIHIxgvoLlI1pKZJkGNRrDSsBTtXAOnTYtPZKdVUvhwQkZyybf5Z/Xn36lbQnmhUQo8mUuJM
+3y+Xpi/SB5io82BdS5pYV4jvguX6r2yBS5KPQJqTRlnLX3gWsWc+QgvfKNmwrZggvkN80V4aCRck
+jXtdlemrwWCrWxhkgPut4AZ9HcpZuPN4KWfGVh2vtrV0KnahP/t1MJ+UXjulYPPLXAziDslg+Mkf
+Foom3ecnf+slpoq9uC02EJqxWE2aaE9gVOX2RhOOiKy8IUISrcZKiX2bwdgt6ZYD9KJ0DLwAHb/W
+NyVntHKLr4W96ioDj8z7PEQkguIBpQtZtjSNMgsSDesnwv1B10A8ckYpwIzqug/xBpMu95yo9GA+
+o/E4Xo4TwbM6l4c/ksp4qRyv0LAbJh6+cOx69TOY6lz/KwsETkPdY34Op054A5U+1C0wlREQKC6/
+oAI+/15Z0wUOlV9TRe9rh9VIzRamloPh37MG88EU26fsHItdkJANclHnYfkUyq+Dj7+vsQpZXdxc
+1+SWrVtgHdqul7I52Qb1dgAT+GhMIbA1xNxVssnBQVocicCMb3SgazNNtQEo/a2tiRc7ppqEvOuM
+6sRxJKi6KfkIsidWNTJf6jn7MZrVGczw
+-----END CERTIFICATE-----
+
+CommScope Public Trust RSA Root-02
+==================================
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIUVBa/O345lXGN0aoApYYNK496BU4wDQYJKoZIhvcNAQELBQAwTjELMAkG
+A1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBU
+cnVzdCBSU0EgUm9vdC0wMjAeFw0yMTA0MjgxNzE2NDNaFw00NjA0MjgxNzE2NDJaME4xCzAJBgNV
+BAYTAlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1
+c3QgUlNBIFJvb3QtMDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDh+g77aAASyE3V
+rCLENQE7xVTlWXZjpX/rwcRqmL0yjReA61260WI9JSMZNRTpf4mnG2I81lDnNJUDMrG0kyI9p+Kx
+7eZ7Ti6Hmw0zdQreqjXnfuU2mKKuJZ6VszKWpCtYHu8//mI0SFHRtI1CrWDaSWqVcN3SAOLMV2MC
+e5bdSZdbkk6V0/nLKR8YSvgBKtJjCW4k6YnS5cciTNxzhkcAqg2Ijq6FfUrpuzNPDlJwnZXjfG2W
+Wy09X6GDRl224yW4fKcZgBzqZUPckXk2LHR88mcGyYnJ27/aaL8j7dxrrSiDeS/sOKUNNwFnJ5rp
+M9kzXzehxfCrPfp4sOcsn/Y+n2Dg70jpkEUeBVF4GiwSLFworA2iI540jwXmojPOEXcT1A6kHkIf
+hs1w/tkuFT0du7jyU1fbzMZ0KZwYszZ1OC4PVKH4kh+Jlk+71O6d6Ts2QrUKOyrUZHk2EOH5kQMr
+eyBUzQ0ZGshBMjTRsJnhkB4BQDa1t/qp5Xd1pCKBXbCL5CcSD1SIxtuFdOa3wNemKfrb3vOTlycE
+VS8KbzfFPROvCgCpLIscgSjX74Yxqa7ybrjKaixUR9gqiC6vwQcQeKwRoi9C8DfF8rhW3Q5iLc4t
+Vn5V8qdE9isy9COoR+jUKgF4z2rDN6ieZdIs5fq6M8EGRPbmz6UNp2YINIos8wIDAQABo0IwQDAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUR9DnsSL/nSz12Vdgs7Gx
+cJXvYXowDQYJKoZIhvcNAQELBQADggIBAIZpsU0v6Z9PIpNojuQhmaPORVMbc0RTAIFhzTHjCLqB
+KCh6krm2qMhDnscTJk3C2OVVnJJdUNjCK9v+5qiXz1I6JMNlZFxHMaNlNRPDk7n3+VGXu6TwYofF
+1gbTl4MgqX67tiHCpQ2EAOHyJxCDut0DgdXdaMNmEMjRdrSzbymeAPnCKfWxkxlSaRosTKCL4BWa
+MS/TiJVZbuXEs1DIFAhKm4sTg7GkcrI7djNB3NyqpgdvHSQSn8h2vS/ZjvQs7rfSOBAkNlEv41xd
+gSGn2rtO/+YHqP65DSdsu3BaVXoT6fEqSWnHX4dXTEN5bTpl6TBcQe7rd6VzEojov32u5cSoHw2O
+HG1QAk8mGEPej1WFsQs3BWDJVTkSBKEqz3EWnzZRSb9wO55nnPt7eck5HHisd5FUmrh1CoFSl+Nm
+YWvtPjgelmFV4ZFUjO2MJB+ByRCac5krFk5yAD9UG/iNuovnFNa2RU9g7Jauwy8CTl2dlklyALKr
+dVwPaFsdZcJfMw8eD/A7hvWwTruc9+olBdytoptLFwG+Qt81IR2tq670v64fG9PiO/yzcnMcmyiQ
+iRM9HcEARwmWmjgb3bHPDcK0RPOWlc4yOo80nOAXx17Org3bhzjlP1v9mxnhMUF6cKojawHhRUzN
+lM47ni3niAIi9G7oyOzWPPO5std3eqx7
+-----END CERTIFICATE-----
diff --git a/resources/de/welcome.html b/resources/de/welcome.html
index 8cbcbd8c5..899f685f9 100644
--- a/resources/de/welcome.html
+++ b/resources/de/welcome.html
@@ -6,13 +6,13 @@
</head>
<body>
-<h1 class="banner"><a href="http://www.netsurf-browser.org/"><img src="about:logo" alt="NetSurf"></a></h1>
+<h1 class="banner"><a href="https://www.netsurf-browser.org/"><img src="about:logo" alt="NetSurf"></a></h1>
<ul class="nslinks">
-<li><a href="http://www.netsurf-browser.org/">NetSurf Website</a></li>
-<li><a href="http://www.netsurf-browser.org/documentation/">Dokumentation</a></li>
-<li><a href="http://www.netsurf-browser.org/downloads/">Download neustes NetSurf</a></li>
-<li><a href="http://www.netsurf-browser.org/contact/">Kontakt zu den Entwicklern</a></li>
+<li><a href="https://www.netsurf-browser.org/">NetSurf Website</a></li>
+<li><a href="https://www.netsurf-browser.org/documentation/">Dokumentation</a></li>
+<li><a href="https://www.netsurf-browser.org/downloads/">Download neustes NetSurf</a></li>
+<li><a href="https://www.netsurf-browser.org/contact/">Kontakt zu den Entwicklern</a></li>
</ul>
<div class="onlycontent">
@@ -21,7 +21,7 @@
<p class="intro">NetSurf ist ein kleiner, schneller Opensource Webbrowser. Wir sind st&auml;ndig daran interessiert, unseren Browser zu verbessern. Bitte kontaktieren Sie uns, wenn Sie irgend welche Probleme bemerken.<br>
Danke, dass Sie sich f&uuml;r NetSurf entschieden haben!</p>
-<form method="get" action="http://www.google.de/search">
+<form method="get" action="https://www.google.de/search">
<div class="websearch">
<input type="text" name="q" size="42" maxlength="255">
<input type="submit" value="Google-Suche" name="btnG">
@@ -30,29 +30,29 @@ Danke, dass Sie sich f&uuml;r NetSurf entschieden haben!</p>
<div class="links">
<ul>
-<li><a href="http://news.bbc.co.uk/">BBC News</a></li>
-<li><a href="http://www.reuters.com/news">Reuters</a></li>
-<li><a href="http://www.cnn.com/">CNN</a></li>
+<li><a href="https://news.bbc.co.uk/">BBC News</a></li>
+<li><a href="https://www.reuters.com/news">Reuters</a></li>
+<li><a href="https://www.cnn.com/">CNN</a></li>
</ul>
<ul>
-<li><a href="http://slashdot.org/">Slashdot</a></li>
-<li><a href="http://arstechnica.com/">Ars Technica</a></li>
-<li><a href="http://www.theregister.co.uk/">The Register</a></li>
-<li><a href="http://www.w3.org/">W3C</a></li>
+<li><a href="https://slashdot.org/">Slashdot</a></li>
+<li><a href="https://arstechnica.com/">Ars Technica</a></li>
+<li><a href="https://www.theregister.co.uk/">The Register</a></li>
+<li><a href="https://www.w3.org/">W3C</a></li>
</ul>
<ul>
-<li><a href="http://de.wikipedia.org/">Wikipedia</a></li>
-<li><a href="http://www.google.de/">Google</a></li>
-<li><a href="http://de.yahoo.com/">Yahoo!</a></li>
-<li><a href="http://www.imdb.com/">IMDB</a></li>
+<li><a href="https://de.wikipedia.org/">Wikipedia</a></li>
+<li><a href="https://www.google.de/">Google</a></li>
+<li><a href="https://de.yahoo.com/">Yahoo!</a></li>
+<li><a href="https://www.imdb.com/">IMDB</a></li>
</ul>
<ul>
-<li><a href="http://www.iconbar.com/">The Icon Bar</a></li>
-<li><a href="http://www.riscosopen.org/">ROOL</a></li>
-<li><a href="http://www.riscos.info/">riscos.info</a></li>
+<li><a href="https://www.iconbar.com/">The Icon Bar</a></li>
+<li><a href="https://www.riscosopen.org/">ROOL</a></li>
+<li><a href="https://www.riscos.info/">riscos.info</a></li>
</ul>
</div>
diff --git a/resources/default.css b/resources/default.css
index 276bc1554..fa47c76ff 100644
--- a/resources/default.css
+++ b/resources/default.css
@@ -50,9 +50,9 @@ pre { display: block; font-family: monospace; white-space: pre; margin-bottom: 1
ins { color: green; text-decoration: underline; }
del { color: red; text-decoration: line-through; }
-ul { display: block; padding-left: 1.5em; margin: 1.12em 0;
+ul { display: block; padding-left: 40px; margin: 1.12em 0;
list-style-type: disc; }
-ol { display: block; padding-left: 1.5em; margin: 1.12em 0;
+ol { display: block; padding-left: 40px; margin: 1.12em 0;
list-style-type: decimal; }
li { display: list-item; }
diff --git a/resources/en/credits.html b/resources/en/credits.html
index 7789bcdea..1a728d376 100644
--- a/resources/en/credits.html
+++ b/resources/en/credits.html
@@ -13,54 +13,53 @@ div#DevList ul {
</style>
</head>
-<body>
-<p class="banner"><a href="http://www.netsurf-browser.org/"><img src="resource:netsurf.png" alt="NetSurf"></a></p>
+<body class="ns-even-bg ns-even-fg ns-border">
-<h1>NetSurf Credits</h1>
+<h1 class="ns-border">NetSurf Credits</h1>
<p>NetSurf was brought to you by the following people:</p>
<div id="DevList">
-<h2>Code</h2>
+<h2 class="ns-border">Code</h2>
<ul>
-<li>Kevin Bagust</li>
<li>John-Mark Bell</li>
+<li>Michael Drake</li>
+<li>Rob Kendrick</li>
+<li>François Revol</li>
+<li>Vincent Sanders</li>
+<li>Daniel Silverstone</li>
+<li>Chris Young</li>
+<li>Kevin Bagust</li>
<li>Mark Benjamin</li>
<li>Adam Blokus</li>
<li>Pawe&#x0142 Blokus</li>
<li>James Bursa</li>
<li>Stefaan Claes</li>
<li>Calin Dobos</li>
-<li>Michael Drake</li>
<li>Sean Fox</li>
<li>Stephen Fryatt</li>
<li>Rik Griffin</li>
<li>Matthew Hambley</li>
<li>Rob Jackson</li>
-<li>Rob Kendrick</li>
<li>Jeffrey Lee</li>
<li>Adrian Lees</li>
<li>Michael Lester</li>
<li>Ole Loots</li>
<li>Phil Mellor</li>
<li>Philip Pemberton</li>
-<li>François Revol</li>
<li>Darren Salt</li>
-<li>Vincent Sanders</li>
<li>James Shaw</li>
<li>Andrew Sidwell</li>
-<li>Daniel Silverstone</li>
<li>Andrew Timmins</li>
<li>John Tytgat</li>
<li>Sven Weidauer</li>
<li>Chris Williams</li>
<li>Richard Wilson</li>
<li>Bo Yang</li>
-<li>Chris Young</li>
</ul>
-<h2>Documentation</h2>
+<h2 class="ns-border">Documentation</h2>
<ul>
<li>John-Mark Bell</li>
<li>James Bursa</li>
@@ -70,7 +69,7 @@ div#DevList ul {
<li>Richard Wilson</li>
</ul>
-<h2>Graphics</h2>
+<h2 class="ns-border">Graphics</h2>
<ul>
<li>Michael Drake</li>
<li>Andrew Duffell</li>
@@ -79,7 +78,7 @@ div#DevList ul {
<li>Phil Mellor</li>
</ul>
-<h2>Translations</h2>
+<h2 class="ns-border">Translations</h2>
<ul>
<li>Sebastian Barthel</li>
<li>Bruno D'Arcangeli</li>
@@ -91,8 +90,8 @@ div#DevList ul {
</div>
-<div class="footer">
-<p>Copyright 2003&ndash;2017 The NetSurf Developers</p>
+<div class="footer ns-even-fg-subtle">
+<p class="ns-even-fg-faded ns-border">Copyright 2003&ndash;2023 The NetSurf Developers</p>
</div>
</body>
diff --git a/resources/en/licence.html b/resources/en/licence.html
index 515757cd7..0ab4c2b40 100644
--- a/resources/en/licence.html
+++ b/resources/en/licence.html
@@ -6,23 +6,22 @@
<link rel="stylesheet" type="text/css" href="resource:internal.css">
<style>
div.licence {
- background: #ddd;
white-space: pre;
font-family: monospace;
- border: solid 1px black;
+ border-width: 1px;
+ border-style: solid;
margin: 10mm;
padding: 1em 0.5em;
}
dl.components > dt {
- border-bottom: dotted 2px #94adff;
+ border-bottom-width: 1px;
+ border-bottom-style: solid;
}
dl.components > dt > a {
text-decoration: none;
}
dl.components > dd > span {
display: table-cell;
-}
-dl.components > dd > span {
width: 100%;
}
dl.components > dd > span + span {
@@ -31,10 +30,9 @@ dl.components > dd > span + span {
</style>
</head>
-<body>
-<p class="banner"><a href="http://www.netsurf-browser.org/"><img src="resource:netsurf.png" alt="NetSurf"></a></p>
+<body class="ns-even-bg ns-even-fg ns-border">
-<h1>NetSurf Licence</h1>
+<h1 class="ns-border">NetSurf Licence</h1>
<p>NetSurf, the source code, documentation, translatable messages files and UI
definitions are licensed under the GNU General Public Licence, version 2.0. In
@@ -49,7 +47,7 @@ extend this exception to your version of the code, but you are not obligated to
do so. If you do not wish to do so, delete this exception statement from your
version.</p>
-<h2>Component Licencing</h2>
+<h2 class="ns-border">Component Licencing</h2>
<p>NetSurf's artwork resources are licensed under the MIT licence.</p>
@@ -58,75 +56,75 @@ version.</p>
<h3>NetSurf Project Components</h3>
<dl class="components">
-<dt><a href="http://www.netsurf-browser.org/">NetSurf</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/">NetSurf</a></dt>
<dd>
-<span>&copy; 2002&ndash;2017 The NetSurf Developers</span>
+<span>&copy; 2002&ndash;2020 The NetSurf Developers</span>
<span><a href="#gplv2">GPLv2</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libcss/">LibCSS</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libcss/">LibCSS</a></dt>
<dd>
-<span>&copy; 2007&ndash;2017 John-Mark Bell</span>
+<span>&copy; 2007&ndash;2023 John-Mark Bell</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/hubbub/">Hubbub</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/hubbub/">Hubbub</a></dt>
<dd>
-<span>&copy; 2007&ndash;2017 John-Mark Bell<br>&copy; 2008&ndash;2009 Andrew Sidwell</span>
+<span>&copy; 2007&ndash;2023 John-Mark Bell<br>&copy; 2008&ndash;2009 Andrew Sidwell</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libparserutils/">LibParserUtils</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libparserutils/">LibParserUtils</a></dt>
<dd>
-<span>&copy; 2007&ndash;2017 John-Mark Bell</span>
+<span>&copy; 2007&ndash;2023 John-Mark Bell</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/librosprite/">LibROSprite</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/librosprite/">LibROSprite</a></dt>
<dd>
<span>&copy; 2008 James Shaw</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libpencil">Libpencil</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libpencil">Libpencil</a></dt>
<dd>
<span>&copy; 2005&ndash;2006 James Bursa</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/rufl">RUfl</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/rufl">RUfl</a></dt>
<dd>
<span>&copy; 2005&ndash;2009 James Bursa</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libsvgtiny">Libsvgtiny</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libsvgtiny">Libsvgtiny</a></dt>
<dd>
<span>&copy; 2008&ndash;2009 James Bursa<br>&copy; 2017 Michael Drake</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libnsbmp/">Libnsbmp</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libnsbmp/">Libnsbmp</a></dt>
<dd>
-<span>&copy; 2006 Richard Wilson<br>&copy; 2008 Sean Fox<br>&copy; 2017 Vincent Sanders</span>
+<span>&copy; 2006 Richard Wilson<br>&copy; 2008 Sean Fox<br>&copy; 2017&ndash;2023 Vincent Sanders</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libnsfb/">Libnsfb</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libnsfb/">Libnsfb</a></dt>
<dd>
-<span>&copy; 2009&ndash;2017 Vincent Sanders<br>&copy; 2009&ndash;2017 Michael Drake</span>
+<span>&copy; 2009&ndash;2017 Vincent Sanders<br>&copy; 2009&ndash;2023 Michael Drake</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libnsgif/">Libnsgif</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libnsgif/">Libnsgif</a></dt>
<dd>
-<span>&copy; 2004 Richard Wilson</br>&copy; 2008 Sean Fox</span>
+<span>&copy; 2004 Richard Wilson</br>&copy; 2008 Sean Fox<br>&copy; 2020&ndash;2023 Michael Drake</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libwapcaplet">LibWapcaplet</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libwapcaplet">LibWapcaplet</a></dt>
<dd>
-<span>&copy; 2009&ndash;2017 NetSurf Browser Project, Daniel Silverstone</span>
+<span>&copy; 2009&ndash;2023 NetSurf Browser Project, Daniel Silverstone</span>
<span><a href="#mit">MIT</a></span>
</dd>
</dl>
@@ -134,49 +132,49 @@ version.</p>
<h3>Third Party Components</h3>
<dl class="components">
-<dt><a href="http://curl.haxx.se/">cURL</a></dt>
+<dt class="ns-border"><a href="https://curl.haxx.se/">cURL</a></dt>
<dd>
-<span>&copy; 1996&ndash;2010 Daniel Stenberg</span>
+<span>&copy; 1996&ndash;2020 Daniel Stenberg</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://libharu.org/">Haru PDF</a></dt>
+<dt class="ns-border"><a href="https://libharu.org/">Haru PDF</a></dt>
<dd>
<span>&copy; 2000&ndash;2008 Takeshi Kanno</span>
<span><a href="#zlib">ZLib</a></span>
</dd>
-<dt><a href="http://www.ijg.org">libjpeg</a></dt>
+<dt class="ns-border"><a href="https://www.ijg.org">libjpeg</a></dt>
<dd>
<span>&copy; 1991&ndash;2010 Thomas G. Lane, Guido Vollbeding</span>
<span><a href="#ijg">IJG</a></span>
</dd>
-<dt><a href="http://www.littlecms.com/">liblcms</a></dt>
+<dt class="ns-border"><a href="https://www.littlecms.com/">liblcms</a></dt>
<dd>
<span>&copy; 1998&ndash;2007 Marti Maria Saguer</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://ro-oslib.sourceforge.net/">OSLib</a></dt>
+<dt class="ns-border"><a href="https://ro-oslib.sourceforge.net/">OSLib</a></dt>
<dd>
<span>&copy; 1994&ndash;1998 Jonathan Coxhead and contributors</span>
<span><a href="#oslib">OSLib</a></span>
</dd>
-<dt><a href="http://www.openssl.org/">OpenSSL</a></dt>
+<dt class="ns-border"><a href="https://www.openssl.org/">OpenSSL</a></dt>
<dd>
<span>&copy; 1995&ndash;1998 Eric A. Young, Tim J. Hudson<br>&copy; 1998&ndash;2010 The OpenSSL Project</span>
<span><a href="#openssl">OpenSSL</a></span>
</dd>
-<dt><a href="http://www.libpng.org">libpng</a></dt>
+<dt class="ns-border"><a href="https://www.libpng.org">libpng</a></dt>
<dd>
<span>&copy; 2004&ndash;2010 Glenn Randers-Pehrson</span>
<span><a href="#png">PNG</a></span>
</dd>
-<dt><a href="http://www.riscos.info/websvn/listing.php?repname=gccsdk&path=%2Ftrunk%2Fgcc4%2Frecipe%2Ffiles%2Fgcc%2Flibunixlib%2F&#a9586e56e500c7fdfb58279167b82472d">UnixLib</a></dt>
+<dt class="ns-border"><a href="https://www.riscos.info/websvn/listing.php?repname=gccsdk&path=%2Ftrunk%2Fgcc4%2Frecipe%2Ffiles%2Fgcc%2Flibunixlib%2F&#a9586e56e500c7fdfb58279167b82472d">UnixLib</a></dt>
<dd>
<span>&copy; 1995&ndash;1999 Simon Callan, Nick Burrett, Nicholas Clark and
Peter Burwood<br>&copy; 1999&ndash;2009 Nick Burrett, John Tytgat, Peter Naulls,
@@ -185,14 +183,14 @@ Graham Shaw, James Bursa and John-Mark Bell.</span>
<span><a href="#unixlib">UnixLib</a></span>
</dd>
-<dt><a href="http://zlib.net/">ZLib</a></dt>
+<dt class="ns-border"><a href="https://zlib.net/">ZLib</a></dt>
<dd>
<span>&copy; 1995&ndash;2010 Jean-loup Gailly and Mark Adler</span>
<span><a href="#zlib">ZLib</a></span>
</dd>
</dl>
-<h2>Licence texts</h2>
+<h2 class="ns-border">Licence texts</h2>
<p>Generic forms of the licence texts appear here where possible. Some
components may vary the licence slightly, and our best effort has been made to
@@ -201,7 +199,7 @@ white space, etc, were not considered.</p>
<a name="gplv2" />
<h3>GNU General Public Licence, Version 2</h3>
-<div class="licence"> GNU GENERAL PUBLIC LICENSE
+<div class="licence ns-border ns-odd-bg"> GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
@@ -544,7 +542,7 @@ Public License instead of this License.
<a name="mit" />
<h3>MIT/X Licence</h3>
-<div class="licence">Permission is hereby granted, free of charge, to any person obtaining a copy
+<div class="licence ns-border ns-odd-bg">Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
@@ -565,7 +563,7 @@ THE SOFTWARE.
<a name="zlib" />
<h3>ZLib Licence</h3>
-<div class="licence"> This software is provided 'as-is', without any express or implied
+<div class="licence ns-border ns-odd-bg"> This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
@@ -584,7 +582,7 @@ THE SOFTWARE.
<a name="ijg" />
<h3>IJG Licence</h3>
-<div class="licence">The authors make NO WARRANTY or representation, either express or implied,
+<div class="licence ns-border ns-odd-bg">The authors make NO WARRANTY or representation, either express or implied,
with respect to this software, its quality, accuracy, merchantability, or
fitness for a particular purpose. This software is provided "AS IS", and you,
its user, assume the entire risk as to its quality and accuracy.
@@ -639,7 +637,7 @@ but is also freely distributable.
<a name="oslib" />
<h3>OSLib Licence</h3>
-<div class="licence">The copyright holder has granted a small relaxation of the
+<div class="licence ns-border ns-odd-bg">The copyright holder has granted a small relaxation of the
conditions of the GNU Public Licence, in that OSLib is itself
free software, but applications linked to it need not be.
This means that any changes to OSLib itself (the contents of
@@ -899,7 +897,7 @@ That's all there is to it!
<a name="openssl" />
<h3>OpenSSL Licence</h3>
-<div class="licence"> The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
+<div class="licence ns-border ns-odd-bg"> The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
the OpenSSL License and the original SSLeay license apply to the toolkit.
See below for the actual license texts. Actually both licenses are BSD-style
Open Source licenses. In case of any license issues related to OpenSSL
@@ -1025,7 +1023,7 @@ That's all there is to it!
<a name="png" />
<h3>PNG Licence</h3>
-<div class="licence"> * This code is released under the libpng license.
+<div class="licence ns-border ns-odd-bg"> * This code is released under the libpng license.
*
* libpng versions 1.2.6, August 15, 2004, through 1.4.1, February 25, 2010, are
* Copyright (c) 2004, 2006-2010 Glenn Randers-Pehrson, and are
@@ -1115,7 +1113,7 @@ That's all there is to it!
<a name="unixlib" />
<h3>UnixLib Licence</h3>
-<div class="licence">In January 2005, permission was obtained from all relevant contributors
+<div class="licence ns-border ns-odd-bg">In January 2005, permission was obtained from all relevant contributors
by Peter Naulls to license all past and present contributions to UnixLib
(where possible) under the revised BSD license. The license is included
in the next section and is applicable to all code in UnixLib that does not
@@ -1864,8 +1862,8 @@ ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
</div>
-<div class="footer">
-<p>Copyright 2003&ndash;2017 The NetSurf Developers</p>
+<div class="footer ns-even-fg-subtle">
+<p class="ns-even-fg-faded ns-border">Copyright 2003&ndash;2019 The NetSurf Developers</p>
</div>
</body>
diff --git a/resources/en/maps.html b/resources/en/maps.html
deleted file mode 100644
index 2427d8a9c..000000000
--- a/resources/en/maps.html
+++ /dev/null
@@ -1,85 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<title>NetSurf: Static Maps</title>
-<style type="text/css">html,body{margin:0;padding:0;}body{color:#000;background:#fff;font-family:sans-serif;margin:0 auto;}a:link{text-decoration:underline;color:#00f;}a:visited{text-decoration:underline;color:#60a;}a:hover{text-decoration:none;}a:active{text-decoration:underline;color:#f00;}.banner{margin:0;padding:0;background:#94adff;text-align:left;}.banner img{border:none;color:#000;height:86px;width:308px;display:block;}.onlycontent{margin:0 1em;}.nslinks{display:table;width:100%;margin:0;border-spacing:0;padding:0;background:#ccd8ff;font-size:94%;}.nslinks li{display:table-cell;text-align:center;padding:0.2em 0.3em 0.3em;vertical-align:middle;}.nslinks li+li{border-left:2px solid #b1c3ff;}.version{padding:0;margin:1.2em auto 0;width:90%;color:#444;font-size:160%;}.intro{width:90%;margin:1em auto;color:#666;}.websearch{margin:1.5em auto;padding:0 0.3em 1.2em;background:#d8e2ff;border:2px solid #c5d3ff;width:80%;text-align:center;}.websearch p {text-align:left;color:#8c93a6;margin-left:1em; }.websearch input[type=text]{border:2px solid #b6c7ff;background:#f9faff;color:#000;margin:2px;}.websearch input[type=submit]{border:2px outset #cedaff;color:#000;background:#cedaff;margin:2px;}.footer{font-style:italic;color:#666;text-align:right; clear: both;}.footer p{margin-top:1.5em;padding-top:0.4em;border-top:2px solid #94adff;}.options {display:table;width:80%;margin:1.2em auto 3em; }.options-col {display:table-cell;}.options-col table {margin:0 auto;}</style>
-</head>
-
-<body>
-<h1 class="banner"><a href="http://www.netsurf-browser.org/"><img src="about:logo" alt="NetSurf"></a></h1>
-
-<ul class="nslinks">
-<li><a href="http://www.netsurf-browser.org/">NetSurf web&nbsp;site</a></li>
-<li><a href="http://www.netsurf-browser.org/documentation/">Documentation</a></li>
-<li><a href="http://www.netsurf-browser.org/downloads/">Download latest NetSurf</a></li>
-<li><a href="http://www.netsurf-browser.org/contact/">Contact the developers</a></li>
-</ul>
-
-<div class="onlycontent">
-<h2 class="version">Static Maps</h2>
-
-<p class="intro">Since NetSurf does not yet have enough JavaScript support
-to handle most mapping sites on the web, we provide here a simple interface
-to Google's Static Maps API.</p>
-
-<form method="get" action="https://maps.googleapis.com/maps/api/staticmap">
-<div class="websearch">
-<dl>
-<p>Example: <em>Oxford Street, London, UK</em></p>
-<input name="center" size="42" maxlength="255" type="text">
-<input type="submit" value="View Map!">
-</div>
-<div class="options">
-<div class="options-col">
-<table>
-<tr><td>Size</td><td><input name="size" size="10" maxlength="255" type="text" value="400x400"></td></tr>
-<tr><td>Scale</td><td><input type="radio" name="scale" value="1" checked>Standard<br>
-<input type="radio" name="scale" value="2">Double</td></tr>
-</table>
-</div>
-<div class="options-col">
-<table>
-<tr><td>Zoom</td><td><select name="zoom">
-<option value="0">Whole planet</option>
-<option value="1">1</option>
-<option value="2">2</option>
-<option value="3">3</option>
-<option value="4">4</option>
-<option value="5">5</option>
-<option value="6">6</option>
-<option value="7">7</option>
-<option value="8">8</option>
-<option value="9">9</option>
-<option value="10">10</option>
-<option value="11">11</option>
-<option value="12">12</option>
-<option value="13">13</option>
-<option value="14">14</option>
-<option value="15">15</option>
-<option value="16" selected>16</option>
-<option value="17">17</option>
-<option value="18">18</option>
-<option value="19">19</option>
-<option value="20">20</option>
-<option value="21">Really close</option>
-</select></td></tr>
-<tr><td>Type</td><td><select name="maptype">
-<option value="roadmap" selected>Road map</option>
-<option value="satellite">Satellite</option>
-<option value="terrain">Terrain</option>
-<option value="hybrid">Hybrid</option>
-</select></td></tr>
-</table>
-</div>
-</div>
-</form>
-
-
-
-<div class="footer">
-<p>NetSurf is licensed under the GNU Public Licence version 2</p>
-</div>
-</div>
-
-
-</body></html>
diff --git a/resources/en/welcome.html b/resources/en/welcome.html
index 14884f074..a4dbcad36 100644
--- a/resources/en/welcome.html
+++ b/resources/en/welcome.html
@@ -6,13 +6,13 @@
</head>
<body>
-<h1 class="banner"><a href="http://www.netsurf-browser.org/"><img src="about:logo" alt="NetSurf"></a></h1>
+<h1 class="banner"><a href="https://www.netsurf-browser.org/"><img src="about:logo" alt="NetSurf"></a></h1>
<ul class="nslinks">
-<li><a href="http://www.netsurf-browser.org/">NetSurf web&nbsp;site</a></li>
-<li><a href="http://www.netsurf-browser.org/documentation/">Documentation</a></li>
-<li><a href="http://www.netsurf-browser.org/downloads/">Download latest NetSurf</a></li>
-<li><a href="http://www.netsurf-browser.org/contact/">Contact the developers</a></li>
+<li><a href="https://www.netsurf-browser.org/">NetSurf web&nbsp;site</a></li>
+<li><a href="https://www.netsurf-browser.org/documentation/">Documentation</a></li>
+<li><a href="https://www.netsurf-browser.org/downloads/">Download latest NetSurf</a></li>
+<li><a href="https://www.netsurf-browser.org/contact/">Contact the developers</a></li>
</ul>
<div class="onlycontent">
@@ -20,7 +20,7 @@
<p class="intro">NetSurf is a small, fast open source web browser. We are always keen to improve our browser, so get in touch if you run into any problems. Thanks for choosing NetSurf!</p>
-<form method="get" action="http://www.google.co.uk/search">
+<form method="get" action="https://www.google.co.uk/search">
<div class="websearch">
<input type="text" name="q" size="42" maxlength="255">
<input type="submit" value="Google Search" name="btnG">
@@ -29,29 +29,29 @@
<div class="links">
<ul>
-<li><a href="http://news.bbc.co.uk/">BBC News</a></li>
-<li><a href="http://www.reuters.com/news">Reuters</a></li>
-<li><a href="http://www.cnn.com/">CNN</a></li>
+<li><a href="https://news.bbc.co.uk/">BBC News</a></li>
+<li><a href="https://www.reuters.com/news">Reuters</a></li>
+<li><a href="https://www.cnn.com/">CNN</a></li>
</ul>
<ul>
-<li><a href="http://slashdot.org/">Slashdot</a></li>
-<li><a href="http://arstechnica.com/">Ars Technica</a></li>
-<li><a href="http://www.theregister.co.uk/">The Register</a></li>
-<li><a href="http://www.w3.org/">W3C</a></li>
+<li><a href="https://slashdot.org/">Slashdot</a></li>
+<li><a href="https://arstechnica.com/">Ars Technica</a></li>
+<li><a href="https://www.theregister.co.uk/">The Register</a></li>
+<li><a href="https://www.w3.org/">W3C</a></li>
</ul>
<ul>
-<li><a href="http://en.wikipedia.org/wiki/Main_Page">Wikipedia</a></li>
-<li><a href="http://google.co.uk/">Google</a></li>
-<li><a href="http://yahoo.co.uk/">Yahoo!</a></li>
-<li><a href="http://www.imdb.com/">IMDB</a></li>
+<li><a href="https://en.wikipedia.org/wiki/Main_Page">Wikipedia</a></li>
+<li><a href="https://google.co.uk/">Google</a></li>
+<li><a href="https://yahoo.co.uk/">Yahoo!</a></li>
+<li><a href="https://www.imdb.com/">IMDB</a></li>
</ul>
<ul>
-<li><a href="http://www.iconbar.com/">The Icon Bar</a></li>
-<li><a href="http://www.riscosopen.org/">ROOL</a></li>
-<li><a href="http://www.riscos.info/">riscos.info</a></li>
+<li><a href="https://www.iconbar.com/">The Icon Bar</a></li>
+<li><a href="https://www.riscosopen.org/">ROOL</a></li>
+<li><a href="https://www.riscos.info/">riscos.info</a></li>
</ul>
</div>
@@ -61,4 +61,4 @@
</div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/resources/fr/credits.html b/resources/fr/credits.html
new file mode 100644
index 000000000..dc4b19f15
--- /dev/null
+++ b/resources/fr/credits.html
@@ -0,0 +1,98 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>NetSurf | &Agrave; propos des cr&eacute;dits</title>
+<link rel="stylesheet" type="text/css" href="resource:internal.css">
+<style>
+div#DevList li {
+ float: left;
+ width: 18em; }
+div#DevList ul {
+ overflow: hidden; }
+</style>
+</head>
+
+<body class="ns-even-bg ns-even-fg ns-border">
+
+<h1 class="ns-border">Cr&eacute;dits NetSurf</h1>
+
+<p>NetSurf est rendu possible gr&acirc;ce &agrave; toutes ces personnes&nbsp;:</p>
+
+<div id="DevList">
+
+<h2 class="ns-border">Code</h2>
+<ul>
+<li>John-Mark Bell</li>
+<li>Michael Drake</li>
+<li>Rob Kendrick</li>
+<li>Fran&ccedil;ois Revol</li>
+<li>Vincent Sanders</li>
+<li>Daniel Silverstone</li>
+<li>Chris Young</li>
+<li>Kevin Bagust</li>
+<li>Mark Benjamin</li>
+<li>Adam Blokus</li>
+<li>Pawe&#x0142 Blokus</li>
+<li>James Bursa</li>
+<li>Stefaan Claes</li>
+<li>Calin Dobos</li>
+<li>Sean Fox</li>
+<li>Stephen Fryatt</li>
+<li>Rik Griffin</li>
+<li>Matthew Hambley</li>
+<li>Rob Jackson</li>
+<li>Jeffrey Lee</li>
+<li>Adrian Lees</li>
+<li>Michael Lester</li>
+<li>Ole Loots</li>
+<li>Phil Mellor</li>
+<li>Philip Pemberton</li>
+<li>Darren Salt</li>
+<li>James Shaw</li>
+<li>Andrew Sidwell</li>
+<li>Andrew Timmins</li>
+<li>John Tytgat</li>
+<li>Sven Weidauer</li>
+<li>Chris Williams</li>
+<li>Richard Wilson</li>
+<li>Bo Yang</li>
+</ul>
+
+<h2 class="ns-border">Documentation</h2>
+<ul>
+<li>John-Mark Bell</li>
+<li>James Bursa</li>
+<li>Michael Drake</li>
+<li>Rob Kendrick</li>
+<li>James Shaw</li>
+<li>Richard Wilson</li>
+</ul>
+
+<h2 class="ns-border">Graphismes</h2>
+<ul>
+<li>Michael Drake</li>
+<li>Andrew Duffell</li>
+<li>John Duffell</li>
+<li>Richard Hallas</li>
+<li>Phil Mellor</li>
+</ul>
+
+<h2 class="ns-border">Traductions</h2>
+<ul>
+<li>Sebastian Barthel</li>
+<li>Bruno D'Arcangeli</li>
+<li>Samir Hawamdeh</li>
+<li>Gerard van Katwijk</li>
+<li>J&eacute;r&ocirc;me Mathevet</li>
+<li>Simon Voortman</li>
+</ul>
+
+</div>
+
+<div class="footer ns-even-fg-subtle">
+<p class="ns-even-fg-faded ns-border">Copyright 2003&ndash;2023 Les d&eacute;veloppeurs de NetSurf</p>
+</div>
+
+</body>
+</html>
diff --git a/resources/fr/licence.html b/resources/fr/licence.html
new file mode 100644
index 000000000..50b68730a
--- /dev/null
+++ b/resources/fr/licence.html
@@ -0,0 +1,1876 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>NetSurf | &Agrave; propos de la licence</title>
+<link rel="stylesheet" type="text/css" href="resource:internal.css">
+<style>
+div.licence {
+ white-space: pre;
+ font-family: monospace;
+ border-width: 1px;
+ border-style: solid;
+ margin: 10mm;
+ padding: 1em 0.5em;
+}
+dl.components > dt {
+ border-bottom-width: 1px;
+ border-bottom-style: solid;
+}
+dl.components > dt > a {
+ text-decoration: none;
+}
+dl.components > dd > span {
+ display: table-cell;
+ width: 100%;
+}
+dl.components > dd > span + span {
+ width: auto;
+}
+</style>
+</head>
+
+<body class="ns-even-bg ns-even-fg ns-border">
+
+<h1 class="ns-border">Licence NetSurf</h1>
+
+<p>NetSurf, son code source, sa documentation, ses traductions et ses fichiers
+de d&eacute;finition d'interface sont disponibles selon les termes de la
+licence publique g&eacute;n&eacute;rale GNU en version 2.0. De plus, une
+exception sp&eacute;cifique est garantie de pouvoir lier le code de cette
+version de NetSurf avec la librairie &laquo;&nbsp;OpenSSL&nbsp;&raquo; mise
+&agrave; disposition par le projet OpenSSL (ou avec une version modifi&eacute;e
+de cette librairie, tant qu'elle utilise la m&ecirc;me licence que la librairie
+&laquo;&nbsp;OpenSSL&nbsp;&raquo; originale) et de distribuer les fichiers
+ex&eacute;cutables r&eacute;sultant.</p>
+
+<p>Vous devez ob&eacute;ir &agrave; la licence publique g&eacute;n&eacute;rale
+GNU en version 2 pour l'ensemble du code, autre que
+&laquo;&nbsp;OpenSSL&nbsp;&raquo;. Si vous modifiez le code, vous pouvez
+&eacute;tendre cette exception &agrave; votre propre version du code, mais vous
+n'y &ecirc;tes pas oblig&eacute;. Si vous ne souhaitez pas utiliser cette
+exception, pensez &agrave; supprimer la mention de cette exception de votre
+version du code.</p>
+
+<h2 class="ns-border">Licence des composants</h2>
+
+<p>Les cr&eacute;ations graphiques de NetSurf sont distribu&eacute;es selon la licence MIT.</p>
+
+<p>NetSurf peut &eacute;galement contenir les diff&eacute;rents composants suivant.</p>
+
+<h3>Composants issus du projet NetSurf</h3>
+
+<dl class="components">
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/">NetSurf</a></dt>
+<dd>
+<span>&copy; 2002&ndash;2020 Les d&eacute;veloppeurs de NetSurf</span>
+<span><a href="#gplv2">GPLv2</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libcss/">LibCSS</a></dt>
+<dd>
+<span>&copy; 2007&ndash;2023 John-Mark Bell</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/hubbub/">Hubbub</a></dt>
+<dd>
+<span>&copy; 2007&ndash;2023 John-Mark Bell<br>&copy; 2008&ndash;2009 Andrew Sidwell</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libparserutils/">LibParserUtils</a></dt>
+<dd>
+<span>&copy; 2007&ndash;2023 John-Mark Bell</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/librosprite/">LibROSprite</a></dt>
+<dd>
+<span>&copy; 2008 James Shaw</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libpencil">Libpencil</a></dt>
+<dd>
+<span>&copy; 2005&ndash;2006 James Bursa</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/rufl">RUfl</a></dt>
+<dd>
+<span>&copy; 2005&ndash;2009 James Bursa</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libsvgtiny">Libsvgtiny</a></dt>
+<dd>
+<span>&copy; 2008&ndash;2009 James Bursa<br>&copy; 2017 Michael Drake</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libnsbmp/">Libnsbmp</a></dt>
+<dd>
+<span>&copy; 2006 Richard Wilson<br>&copy; 2008 Sean Fox<br>&copy; 2017&ndash;2023 Vincent Sanders</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libnsfb/">Libnsfb</a></dt>
+<dd>
+<span>&copy; 2009&ndash;2017 Vincent Sanders<br>&copy; 2009&ndash;2023 Michael Drake</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libnsgif/">Libnsgif</a></dt>
+<dd>
+<span>&copy; 2004 Richard Wilson</br>&copy; 2008 Sean Fox<br>&copy; 2020&ndash;2023 Michael Drake</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libwapcaplet">LibWapcaplet</a></dt>
+<dd>
+<span>&copy; 2009&ndash;2023 NetSurf Browser Project, Daniel Silverstone</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+</dl>
+
+<h3>Composants tiers</h3>
+
+<dl class="components">
+<dt class="ns-border"><a href="https://curl.haxx.se/">cURL</a></dt>
+<dd>
+<span>&copy; 1996&ndash;2020 Daniel Stenberg</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://libharu.org/">Haru PDF</a></dt>
+<dd>
+<span>&copy; 2000&ndash;2008 Takeshi Kanno</span>
+<span><a href="#zlib">ZLib</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.ijg.org">libjpeg</a></dt>
+<dd>
+<span>&copy; 1991&ndash;2010 Thomas G. Lane, Guido Vollbeding</span>
+<span><a href="#ijg">IJG</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.littlecms.com/">liblcms</a></dt>
+<dd>
+<span>&copy; 1998&ndash;2007 Marti Maria Saguer</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://ro-oslib.sourceforge.net/">OSLib</a></dt>
+<dd>
+<span>&copy; 1994&ndash;1998 Jonathan Coxhead et contributeurs</span>
+<span><a href="#oslib">OSLib</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.openssl.org/">OpenSSL</a></dt>
+<dd>
+<span>&copy; 1995&ndash;1998 Eric A. Young, Tim J. Hudson<br>&copy; 1998&ndash;2010 The OpenSSL Project</span>
+<span><a href="#openssl">OpenSSL</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.libpng.org">libpng</a></dt>
+<dd>
+<span>&copy; 2004&ndash;2010 Glenn Randers-Pehrson</span>
+<span><a href="#png">PNG</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.riscos.info/websvn/listing.php?repname=gccsdk&path=%2Ftrunk%2Fgcc4%2Frecipe%2Ffiles%2Fgcc%2Flibunixlib%2F&#a9586e56e500c7fdfb58279167b82472d">UnixLib</a></dt>
+<dd>
+<span>&copy; 1995&ndash;1999 Simon Callan, Nick Burrett, Nicholas Clark et
+Peter Burwood<br>&copy; 1999&ndash;2009 Nick Burrett, John Tytgat, Peter Naulls,
+Lee Noar, Peter Teichmann, Alex Waugh, Christian Ludlam, Theo Markettos,
+Graham Shaw, James Bursa et John-Mark Bell.</span>
+<span><a href="#unixlib">UnixLib</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://zlib.net/">ZLib</a></dt>
+<dd>
+<span>&copy; 1995&ndash;2010 Jean-loup Gailly et Mark Adler</span>
+<span><a href="#zlib">ZLib</a></span>
+</dd>
+</dl>
+
+<h2 class="ns-border">Textes des licences</h2>
+
+<p>La version g&eacute;n&eacute;rique des textes des licences sont reproduits ici lorsque
+c'est possible. Certains composants utilisent des versions l&eacute;g&egrave;rement
+diff&eacute;rentes de ces textes de r&eacute;f&eacute;rence. Nous avons fait de notre mieux pour
+d&eacute;tecter ces changements et les lister ci-apr&egrave;s. Les changements dans les
+espacements, etc. n'ont pas &eacute;t&eacute; consid&eacute;r&eacute;s.</p>
+
+<a name="gplv2" />
+<h3>GNU General Public Licence, Version 2</h3>
+<div class="licence ns-border ns-odd-bg"> GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
+</div>
+
+<a name="mit" />
+<h3>MIT/X Licence</h3>
+<div class="licence ns-border ns-odd-bg">Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+</div>
+
+<a name="zlib" />
+<h3>ZLib Licence</h3>
+<div class="licence ns-border ns-odd-bg"> This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+</div>
+
+<a name="ijg" />
+<h3>IJG Licence</h3>
+<div class="licence ns-border ns-odd-bg">The authors make NO WARRANTY or representation, either express or implied,
+with respect to this software, its quality, accuracy, merchantability, or
+fitness for a particular purpose. This software is provided "AS IS", and you,
+its user, assume the entire risk as to its quality and accuracy.
+
+This software is copyright (C) 1991-2010, Thomas G. Lane, Guido Vollbeding.
+All Rights Reserved except as specified below.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+software (or portions thereof) for any purpose, without fee, subject to these
+conditions:
+(1) If any part of the source code for this software is distributed, then this
+README file must be included, with this copyright and no-warranty notice
+unaltered; and any additions, deletions, or changes to the original files
+must be clearly indicated in accompanying documentation.
+(2) If only executable code is distributed, then the accompanying
+documentation must state that "this software is based in part on the work of
+the Independent JPEG Group".
+(3) Permission for use of this software is granted only if the user accepts
+full responsibility for any undesirable consequences; the authors accept
+NO LIABILITY for damages of any kind.
+
+These conditions apply to any software derived from or based on the IJG code,
+not just to the unmodified library. If you use our work, you ought to
+acknowledge us.
+
+Permission is NOT granted for the use of any IJG author's name or company name
+in advertising or publicity relating to this software or products derived from
+it. This software may be referred to only as "the Independent JPEG Group's
+software".
+
+We specifically permit and encourage the use of this software as the basis of
+commercial products, provided that all warranty or liability claims are
+assumed by the product vendor.
+
+
+ansi2knr.c is included in this distribution by permission of L. Peter Deutsch,
+sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA.
+ansi2knr.c is NOT covered by the above copyright and conditions, but instead
+by the usual distribution terms of the Free Software Foundation; principally,
+that you must include source code if you redistribute it. (See the file
+ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part
+of any program generated from the IJG code, this does not limit you more than
+the foregoing paragraphs do.
+
+The Unix configuration script "configure" was produced with GNU Autoconf.
+It is copyright by the Free Software Foundation but is freely distributable.
+The same holds for its supporting scripts (config.guess, config.sub,
+ltmain.sh). Another support script, install-sh, is copyright by X Consortium
+but is also freely distributable.
+</div>
+
+
+<a name="oslib" />
+<h3>OSLib Licence</h3>
+<div class="licence ns-border ns-odd-bg">The copyright holder has granted a small relaxation of the
+conditions of the GNU Public Licence, in that OSLib is itself
+free software, but applications linked to it need not be.
+This means that any changes to OSLib itself (the contents of
+the OSLib, OSLibHelp, OSLibSrc, and OSLibSupport archives)
+fall under the terms of the GNU Public Licence; but programs
+written using OSLib need not be so restricted.
+
+ GNU GENERAL PUBLIC LICENCE
+ Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, U S A
+ Everyone is permitted to copy and distribute verbatim copies
+ of this licence document, but changing it is not allowed.
+
+ Preamble
+
+ The licence agreements of most software companies try to keep users
+at the mercy of those companies. By contrast, our General Public
+Licence is intended to guarantee your freedom to share and change free
+software---to make sure the software is free for all its users. The
+General Public Licence applies to the Free Software Foundation's
+software and to any other programme whose authors commit to using it.
+You can use it for your programmes, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public Licence is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programmes; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of a such a programme, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this licence which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENCE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This Licence Agreement applies to any programme or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public Licence. The
+"Programme", below, refers to any such programme or work, and a "work based
+on the Programme" means either the Programme or any work containing the
+Programme or a portion of it, either verbatim or with modifications. Each
+licensee is addressed as "you".
+
+ 1. You may copy and distribute verbatim copies of the Programme's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public Licence and to the absence of any warranty; and give any
+other recipients of the Programme a copy of this General Public Licence
+along with the Programme. You may charge a fee for the physical act of
+transferring a copy.
+
+ 2. You may modify your copy or copies of the Programme or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating that
+ you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish, that
+ in whole or in part contains the Programme or any part thereof, either
+ with or without modifications, to be licensed at no charge to all
+ third parties under the terms of this General Public Licence (except
+ that you may choose to grant warranty protection to some or all
+ third parties, at your option).
+
+ c) If the modified programme normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the simplest and most usual way, to print or display an
+ announcement including an appropriate copyright notice and a notice
+ that there is no warranty (or else, saying that you provide a
+ warranty) and that users may redistribute the programme under these
+ conditions, and telling the user how to view a copy of this General
+ Public Licence.
+
+ d) You may charge a fee for the physical act of transferring a
+ copy, and you may at your option offer warranty protection in
+ exchange for a fee.
+
+Mere aggregation of another independent work with the Programme (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+ 3. You may copy and distribute the Programme (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal charge
+ for the cost of distribution) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the programme in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it. For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+ 4. You may not copy, modify, sublicense, distribute or transfer the
+Programme except as expressly provided under this General Public Licence.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Programme is void, and will automatically terminate your rights to use
+the Programme under this Licence. However, parties who have received
+copies, or rights to use copies, from you under this General Public
+Licence will not have their licences terminated so long as such parties
+remain in full compliance.
+
+ 5. By copying, distributing or modifying the Programme (or any work based
+on the Programme) you indicate your acceptance of this licence to do so,
+and all its terms and conditions.
+
+ 6. Each time you redistribute the Programme (or any work based on the
+Programme), the recipient automatically receives a licence from the original
+licensor to copy, distribute or modify the Programme subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+ 7. The Free Software Foundation may publish revised and/or new versions
+of the General Public Licence from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Programme
+specifies a version number of the licence which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Programme does not specify a version number of
+the licence, you may choose any version ever published by the Free Software
+Foundation.
+
+ 8. If you wish to incorporate parts of the Programme into other free
+programmes whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 9. BECAUSE THE PROGRAMME IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAMME, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAMME "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAMME IS WITH YOU. SHOULD THE
+PROGRAMME PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAMME AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAMME (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAMME TO OPERATE WITH ANY OTHER
+PROGRAMMES), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programmes
+
+ If you develop a new programme, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+ To do so, attach the following notices to the programme. It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the programme's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This programme is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public Licence as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This programme is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public Licence for more details.
+
+ You should have received a copy of the GNU General Public Licence
+ along with this programme; if not, write to the Free Software
+ Foundation, Inc, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the programme is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19xx name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public Licence. Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+programme.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the programme, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ programme `Gnomovision' (a programme to direct compilers to make passes
+ at assemblers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+That's all there is to it!
+</div>
+
+<a name="openssl" />
+<h3>OpenSSL Licence</h3>
+<div class="licence ns-border ns-odd-bg"> The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
+ the OpenSSL License and the original SSLeay license apply to the toolkit.
+ See below for the actual license texts. Actually both licenses are BSD-style
+ Open Source licenses. In case of any license issues related to OpenSSL
+ please contact openssl-core@openssl.org.
+
+ OpenSSL License
+ ---------------
+
+/* ====================================================================
+ * Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+ Original SSLeay License
+ -----------------------
+
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+</div>
+
+<a name="png" />
+<h3>PNG Licence</h3>
+<div class="licence ns-border ns-odd-bg"> * This code is released under the libpng license.
+ *
+ * libpng versions 1.2.6, August 15, 2004, through 1.4.1, February 25, 2010, are
+ * Copyright (c) 2004, 2006-2010 Glenn Randers-Pehrson, and are
+ * distributed according to the same disclaimer and license as libpng-1.2.5
+ * with the following individual added to the list of Contributing Authors:
+ *
+ * Cosmin Truta
+ *
+ * libpng versions 1.0.7, July 1, 2000, through 1.2.5, October 3, 2002, are
+ * Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are
+ * distributed according to the same disclaimer and license as libpng-1.0.6
+ * with the following individuals added to the list of Contributing Authors:
+ *
+ * Simon-Pierre Cadieux
+ * Eric S. Raymond
+ * Gilles Vollant
+ *
+ * and with the following additions to the disclaimer:
+ *
+ * There is no warranty against interference with your enjoyment of the
+ * library or against infringement. There is no warranty that our
+ * efforts or the library will fulfill any of your particular purposes
+ * or needs. This library is provided with all faults, and the entire
+ * risk of satisfactory quality, performance, accuracy, and effort is with
+ * the user.
+ *
+ * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson, and are
+ * distributed according to the same disclaimer and license as libpng-0.96,
+ * with the following individuals added to the list of Contributing Authors:
+ *
+ * Tom Lane
+ * Glenn Randers-Pehrson
+ * Willem van Schaik
+ *
+ * libpng versions 0.89, June 1996, through 0.96, May 1997, are
+ * Copyright (c) 1996, 1997 Andreas Dilger
+ * Distributed according to the same disclaimer and license as libpng-0.88,
+ * with the following individuals added to the list of Contributing Authors:
+ *
+ * John Bowler
+ * Kevin Bracey
+ * Sam Bushell
+ * Magnus Holmgren
+ * Greg Roelofs
+ * Tom Tanner
+ *
+ * libpng versions 0.5, May 1995, through 0.88, January 1996, are
+ * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
+ *
+ * For the purposes of this copyright and license, "Contributing Authors"
+ * is defined as the following set of individuals:
+ *
+ * Andreas Dilger
+ * Dave Martindale
+ * Guy Eric Schalnat
+ * Paul Schmidt
+ * Tim Wegner
+ *
+ * The PNG Reference Library is supplied "AS IS". The Contributing Authors
+ * and Group 42, Inc. disclaim all warranties, expressed or implied,
+ * including, without limitation, the warranties of merchantability and of
+ * fitness for any purpose. The Contributing Authors and Group 42, Inc.
+ * assume no liability for direct, indirect, incidental, special, exemplary,
+ * or consequential damages, which may result from the use of the PNG
+ * Reference Library, even if advised of the possibility of such damage.
+ *
+ * Permission is hereby granted to use, copy, modify, and distribute this
+ * source code, or portions hereof, for any purpose, without fee, subject
+ * to the following restrictions:
+ *
+ * 1. The origin of this source code must not be misrepresented.
+ *
+ * 2. Altered versions must be plainly marked as such and
+ * must not be misrepresented as being the original source.
+ *
+ * 3. This Copyright notice may not be removed or altered from
+ * any source or altered source distribution.
+ *
+ * The Contributing Authors and Group 42, Inc. specifically permit, without
+ * fee, and encourage the use of this source code as a component to
+ * supporting the PNG file format in commercial products. If you use this
+ * source code in a product, acknowledgment is not required but would be
+ * appreciated.
+ */
+</div>
+
+<a name="unixlib" />
+<h3>UnixLib Licence</h3>
+<div class="licence ns-border ns-odd-bg">In January 2005, permission was obtained from all relevant contributors
+by Peter Naulls to license all past and present contributions to UnixLib
+(where possible) under the revised BSD license. The license is included
+in the next section and is applicable to all code in UnixLib that does not
+have an explicit license in its source.
+
+Prior to 4th January 2005 and after May 2001, UnixLib contained code licensed
+under the GNU General Public License, and versions of UnixLib produced
+between these dates are subject to the provisions of the GPL. We realised
+that this might cause potential problems with the wider use of UnixLib in
+RISC OS, and along with the desire to clarify the overall licensing status of
+UnixLib, GPL code was removed from UnixLib and the above permission from all
+copyright holders allowed UnixLib contributions to be relicensed as per the
+revised BSD license. The GPL is therefore not included in this notice
+as it is no longer relevant to UnixLib.
+
+
+Practical notes on using UnixLib in your own programs:
+
+This is a plain English version of guidelines for use of UnixLib in
+your programs. It does not override any of the licenses included
+below, but is intended to state instances when it may be used in
+free and non-free software. Where there is contradiction or
+ambiguity in this wording, please refer to the specifics of the licence
+in question. These recommendations are based upon our understading
+of the GPL/LGPL and BSD licenses and are subject to change should
+our understanding of the topics improve.
+
+ - Because UnixLib contains code that is subject to the Lesser GNU
+ Public License, the LGPL is the overriding consideration when
+ linking UnixLib to programs (unless the program itself is GPL).
+
+ - You are free to use sections of UnixLib in your own programs
+ subject to the conditions of that code. If the entirety of
+ that code is under a BSD license, then you can generally use
+ that code as you see fit, and there is no further obligation
+ from you as long as the copyright notice remains. If you
+ use LGPL code in your program, then your program must also be
+ distributed under the LGPL (or GPL).
+
+ - If you use UnixLib in its intended original form - that is as a
+ supporting library for ported programs to RISC OS - then your program
+ is subject to the LGPL; or the GPL if the program is covered by that.
+ Note that you must make the source and any modifications available to for
+ both if requested. This is of course equally true if you write an original
+ GPL program using UnixLib. In most cases, no additional action is
+ required of you, especially since source is usually readibly available.
+
+ - If you use UnixLib for a non-free program - whether that's commercial or
+ otherwise, then you should carefully read section 6 of the LGPL. This
+ applies, because at the present time, there is no practical method of
+ dynamic linking on RISC OS. At such time that UnixLib is available as a
+ shared library, then programs dynamically linking to it will no longer be
+ subject to the LPGL as applied to UnixLib.
+
+ - Section 6 means that in practice, you must supply, or offer to
+ supply either source or object code for your program.
+ This is mainly to allow rebuilding of the executable program
+ with later or modified versions of UnixLib. You must of course
+ supply (or better, contribute to the GCCSDK project) any
+ modifications you make to UnixLib upon request.
+
+
+Recommended reading:
+
+Frequently Asked Questions about the GNU GPL
+http://www.fsf.org/licenses/gpl-faq.html (has some sections on LGPL)
+
+About the justifications for using LGPL
+http://www.fsf.org/licenses/why-not-lgpl.html
+
+
+
+===========================================================================
+
+ Copyright (c) 1995-2009 UnixLib Developers
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+===========================================================================
+
+Portions of UnixLib are copyright The Regents of the University of
+California.
+
+Portions of this library are copyright Sun Microsystems, Inc. The
+
+Portions of this library are derived from the GNU C Library and fall under
+the GNU Library General Public License.
+
+Portions of this library are copyright Henry Spencer.
+
+Portions of this library are copyright The Regents of the University of
+California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState
+Corporation and other parties.
+
+Portions of this library are copyright PostgreSQL Global Development Group.
+
+The licenses for the above are duplicated below.
+
+
+===========================================================================
+
+ Copyright (c) The Regents of the University of California.
+ All rights reserved.
+
+ This code is derived from software contributed to Berkeley by
+ Chris Torek.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+ This product includes software developed by the University of
+ California, Berkeley and its contributors.
+ 4. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+===========================================================================
+
+ Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+
+ Developed at SunPro, a Sun Microsystems, Inc. business.
+ Permission to use, copy, modify, and distribute this
+ software is freely granted, provided that this notice
+ is preserved.
+
+===========================================================================
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+===========================================================================
+
+Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
+
+Development of this software was funded, in part, by Cray Research Inc.,
+UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
+Corporation, none of whom are responsible for the results. The author
+thanks all of them.
+
+Redistribution and use in source and binary forms -- with or without
+modification -- are permitted for any purpose, provided that
+redistributions in source form retain this entire copyright notice and
+indicate the origin and nature of any modifications.
+
+I'd appreciate being given credit for this package in the documentation
+of software which uses it, but that is not a requirement.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+===========================================================================
+
+This software is copyrighted by the Regents of the University of
+California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState
+Corporation and other parties. The following terms apply to all files
+associated with the software unless explicitly disclaimed in
+individual files.
+
+The authors hereby grant permission to use, copy, modify, distribute,
+and license this software and its documentation for any purpose, provided
+that existing copyright notices are retained in all copies and that this
+notice is included verbatim in any distributions. No written agreement,
+license, or royalty fee is required for any of the authorized uses.
+Modifications to this software may be copyrighted by their authors
+and need not follow the licensing terms described here, provided that
+the new terms are clearly indicated on the first page of each file where
+they apply.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
+IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+GOVERNMENT USE: If you are acquiring this software on behalf of the
+U.S. government, the Government shall have only "Restricted Rights"
+in the software and related documentation as defined in the Federal
+Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
+are acquiring the software on behalf of the Department of Defense, the
+software shall be classified as "Commercial Computer Software" and the
+Government shall have only "Restricted Rights" as defined in Clause
+252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
+authors grant the U.S. Government and others acting in its behalf
+permission to use and distribute the software in accordance with the
+terms specified in this license.
+
+===========================================================================
+
+PostgreSQL Database Management System
+(formerly known as Postgres, then as Postgres95)
+
+Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
+
+Portions Copyright (c) 1994, The Regents of the University of California
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose, without fee, and without a written agreement
+is hereby granted, provided that the above copyright notice and this
+paragraph and the following two paragraphs appear in all copies.
+
+IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
+LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
+DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
+PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+</div>
+
+<div class="footer ns-even-fg-subtle">
+<p class="ns-even-fg-faded ns-border">Copyright 2003&ndash;2019 Les d&eacute;veloppeurs de NetSurf</p>
+</div>
+
+</body>
+</html>
diff --git a/resources/fr/welcome.html b/resources/fr/welcome.html
new file mode 100644
index 000000000..241ea180e
--- /dev/null
+++ b/resources/fr/welcome.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>Bienvenue sur NetSurf</title>
+<style type="text/css">html,body{margin:0;padding:0;}body{color:#000;background:#fff;font-family:sans-serif;margin:0 auto;}a:link{text-decoration:underline;color:#00f;}a:visited{text-decoration:underline;color:#60a;}a:hover{text-decoration:none;}a:active{text-decoration:underline;color:#f00;}.banner{margin:0;padding:0;background:#94adff;text-align:left;}.banner img{border:none;color:#000;height:86px;width:308px;display:block;}.onlycontent{margin:0 1em;}.nslinks{display:table;width:100%;margin:0;border-spacing:0;padding:0;background:#ccd8ff;font-size:94%;}.nslinks li{display:table-cell;text-align:center;padding:0.2em 0.3em 0.3em;vertical-align:middle;}.nslinks li+li{border-left:2px solid #b1c3ff;}.version{padding:0;margin:1.2em auto 0;width:90%;color:#444;font-size:160%;}.intro{width: 90%;margin:1em auto;color:#666;}.websearch{margin:1.5em auto;padding:1.2em 0.3em;background:#d8e2ff;border:2px solid #c5d3ff;width:80%;text-align:center;}input[type=text]{border:2px solid #b6c7ff;background:#f9faff;color:#000;margin:2px;}input[type=submit]{border:2px outset #cedaff;color:#000;background:#cedaff;margin:2px;}.links{display:table;width:80%;margin:0 auto 3em;font-size:94%;}.links ul{display:table-cell;padding-left:2.5em;}.links ul+ul{padding-left:1em;}.footer{font-style:italic;color:#666;text-align:right;}.footer p{margin-top:1.5em;padding-top:0.4em;border-top:2px solid #94adff;}</style>
+</head>
+
+<body>
+<h1 class="banner"><a href="https://www.netsurf-browser.org/"><img src="about:logo" alt="NetSurf"></a></h1>
+
+<ul class="nslinks">
+<li><a href="https://www.netsurf-browser.org/">Site&nbsp;Web de NetSurf</a></li>
+<li><a href="https://www.netsurf-browser.org/documentation/">Documentation</a></li>
+<li><a href="https://www.netsurf-browser.org/downloads/">T&eacute;l&eacute;charger la derni&egrave;re version de NetSurf</a></li>
+<li><a href="https://www.netsurf-browser.org/contact/">Contacter les d&eacute;veloppeurs</a></li>
+</ul>
+
+<div class="onlycontent">
+<h2 class="version">Bienvenue sur NetSurf</h2>
+
+<p class="intro">NetSurf est un petit et rapide navigateur Web &agrave; code source ouvert. Nous sommes toujours pr&ecirc;t &agrave; am&eacute;liorer notre navigateur, donc n'h&eacute;sitez pas &agrave; nous contacter si vous rencontrez le moindre p&eacute;pin. Merci d'avoir choisi Netsurf&nbsp;!</p>
+
+<form method="get" action="https://www.google.fr/search">
+<div class="websearch">
+<input type="text" name="q" size="42" maxlength="255">
+<input type="submit" value="Recherche Google" name="btnG">
+</div>
+</form>
+
+<div class="links">
+<ul>
+<li><a href="https://news.bbc.co.uk/">BBC News</a></li>
+<li><a href="https://www.reuters.com/news">Reuters</a></li>
+<li><a href="https://www.cnn.com/">CNN</a></li>
+</ul>
+
+<ul>
+<li><a href="https://slashdot.org/">Slashdot</a></li>
+<li><a href="https://arstechnica.com/">Ars Technica</a></li>
+<li><a href="https://www.theregister.co.uk/">The Register</a></li>
+<li><a href="https://www.w3.org/">W3C</a></li>
+</ul>
+
+<ul>
+<li><a href="https://fr.wikipedia.org/">Wikipedia</a></li>
+<li><a href="https://google.fr/">Google</a></li>
+<li><a href="https://yahoo.fr/">Yahoo!</a></li>
+<li><a href="https://www.imdb.com/">IMDB</a></li>
+</ul>
+
+<ul>
+<li><a href="https://www.iconbar.com/">The Icon Bar</a></li>
+<li><a href="https://www.riscosopen.org/">ROOL</a></li>
+<li><a href="https://www.riscos.info/">riscos.info</a></li>
+</ul>
+</div>
+
+<div class="footer">
+<p>NetSurf est distribu&eacute; selon la licence publique GNU version 2</p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/resources/icons/16x16/actions/page-info-insecure.png b/resources/icons/16x16/actions/page-info-insecure.png
new file mode 100644
index 000000000..1a4bc156c
--- /dev/null
+++ b/resources/icons/16x16/actions/page-info-insecure.png
Binary files differ
diff --git a/resources/icons/16x16/actions/page-info-internal.png b/resources/icons/16x16/actions/page-info-internal.png
new file mode 100644
index 000000000..e8422c709
--- /dev/null
+++ b/resources/icons/16x16/actions/page-info-internal.png
Binary files differ
diff --git a/resources/icons/16x16/actions/page-info-local.png b/resources/icons/16x16/actions/page-info-local.png
new file mode 100644
index 000000000..85dc8536e
--- /dev/null
+++ b/resources/icons/16x16/actions/page-info-local.png
Binary files differ
diff --git a/resources/icons/16x16/actions/page-info-secure.png b/resources/icons/16x16/actions/page-info-secure.png
new file mode 100644
index 000000000..7ef0bedd9
--- /dev/null
+++ b/resources/icons/16x16/actions/page-info-secure.png
Binary files differ
diff --git a/resources/icons/16x16/actions/page-info-warning.png b/resources/icons/16x16/actions/page-info-warning.png
new file mode 100644
index 000000000..dc2c87a57
--- /dev/null
+++ b/resources/icons/16x16/actions/page-info-warning.png
Binary files differ
diff --git a/resources/icons/24x24/actions/page-info-insecure.png b/resources/icons/24x24/actions/page-info-insecure.png
new file mode 100644
index 000000000..bd9b4a3a3
--- /dev/null
+++ b/resources/icons/24x24/actions/page-info-insecure.png
Binary files differ
diff --git a/resources/icons/24x24/actions/page-info-internal.png b/resources/icons/24x24/actions/page-info-internal.png
new file mode 100644
index 000000000..c97cead5a
--- /dev/null
+++ b/resources/icons/24x24/actions/page-info-internal.png
Binary files differ
diff --git a/resources/icons/24x24/actions/page-info-local.png b/resources/icons/24x24/actions/page-info-local.png
new file mode 100644
index 000000000..4d638ad0a
--- /dev/null
+++ b/resources/icons/24x24/actions/page-info-local.png
Binary files differ
diff --git a/resources/icons/24x24/actions/page-info-secure.png b/resources/icons/24x24/actions/page-info-secure.png
new file mode 100644
index 000000000..c949ff907
--- /dev/null
+++ b/resources/icons/24x24/actions/page-info-secure.png
Binary files differ
diff --git a/resources/icons/24x24/actions/page-info-warning.png b/resources/icons/24x24/actions/page-info-warning.png
new file mode 100644
index 000000000..b9eaabb22
--- /dev/null
+++ b/resources/icons/24x24/actions/page-info-warning.png
Binary files differ
diff --git a/resources/icons/48x48/actions/page-info-insecure.png b/resources/icons/48x48/actions/page-info-insecure.png
new file mode 100644
index 000000000..fc7e25cd1
--- /dev/null
+++ b/resources/icons/48x48/actions/page-info-insecure.png
Binary files differ
diff --git a/resources/icons/48x48/actions/page-info-internal.png b/resources/icons/48x48/actions/page-info-internal.png
new file mode 100644
index 000000000..086340be5
--- /dev/null
+++ b/resources/icons/48x48/actions/page-info-internal.png
Binary files differ
diff --git a/resources/icons/48x48/actions/page-info-local.png b/resources/icons/48x48/actions/page-info-local.png
new file mode 100644
index 000000000..17a313989
--- /dev/null
+++ b/resources/icons/48x48/actions/page-info-local.png
Binary files differ
diff --git a/resources/icons/48x48/actions/page-info-secure.png b/resources/icons/48x48/actions/page-info-secure.png
new file mode 100644
index 000000000..3e738b577
--- /dev/null
+++ b/resources/icons/48x48/actions/page-info-secure.png
Binary files differ
diff --git a/resources/icons/48x48/actions/page-info-warning.png b/resources/icons/48x48/actions/page-info-warning.png
new file mode 100644
index 000000000..408fc0056
--- /dev/null
+++ b/resources/icons/48x48/actions/page-info-warning.png
Binary files differ
diff --git a/frontends/gtk/res/arrow_down_8x32.png b/resources/icons/local-history.png
index 475b4ff61..475b4ff61 100644
--- a/frontends/gtk/res/arrow_down_8x32.png
+++ b/resources/icons/local-history.png
Binary files differ
diff --git a/resources/icons/page-info-insecure.svg b/resources/icons/page-info-insecure.svg
new file mode 100644
index 000000000..82f3b243c
--- /dev/null
+++ b/resources/icons/page-info-insecure.svg
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.0"
+ width="1190.000000pt"
+ height="1280.000000pt"
+ viewBox="0 0 1190.000000 1280.000000"
+ preserveAspectRatio="xMidYMid meet"
+ id="svg8"
+ sodipodi:docname="padlock-insecure.svg"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
+ <defs
+ id="defs12" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="2560"
+ inkscape:window-height="1416"
+ id="namedview10"
+ showgrid="false"
+ inkscape:zoom="0.39111844"
+ inkscape:cx="-663.2803"
+ inkscape:cy="1243.2619"
+ inkscape:window-x="0"
+ inkscape:window-y="24"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg8" />
+ <metadata
+ id="metadata2">
+Created by potrace 1.15, written by Peter Selinger 2001-2017
+<rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+</rdf:RDF>
+</metadata>
+ <g
+ transform="translate(0.000000,1280.000000) scale(0.100000,-0.100000)"
+ fill="#000000"
+ stroke="none"
+ id="g6">
+ <path
+ d="M5610 11999 c-1096 -88 -1924 -626 -2375 -1544 -80 -162 -155 -347 -155 -380 0 -8 -4 -15 -8 -15 -4 0 -8 -8 -9 -17 -1 -19 -6 -38 -16 -63 -17 -47 -78 -287 -91 -360 -3 -19 -8 -46 -11 -59 -2 -14 -7 -47 -10 -74 -3 -28 -8 -53 -10 -56 -8 -13 -24 -189 -28 -313 -1 -27 -5 -48 -10 -48 -4 0 -3 -9 3 -20 8 -14 8 -20 0 -20 -7 0 -8 -6 -1 -19 6 -10 8 -21 5 -24 -3 -3 -5 -392 -4 -865 l1 -860 -26 -20 c-14 -11 -69 -30 -123 -43 -159 -36 -266 -74 -364 -128 -109 -60 -149 -91 -240 -183 -206 -208 -334 -560 -353 -968 -5 -99 -4 -3022 1 -3125 8 -175 28 -319 46 -343 7 -8 7 -12 -1 -12 -7 0 -9 -5 -4 -13 4 -6 8 -16 9 -22 1 -5 11 -34 23 -62 11 -29 17 -53 13 -53 -4 0 -2 -4 3 -8 10 -7 37 -61 37 -72 0 -3 6 -12 14 -21 8 -9 12 -18 9 -21 -3 -3 6 -17 20 -32 13 -14 25 -29 25 -31 0 -14 84 -117 122 -150 24 -21 34 -32 23 -24 -18 13 -19 13 -6 -3 7 -10 17 -18 22 -18 5 0 17 -8 27 -17 39 -37 67 -57 121 -86 175 -94 267 -121 521 -153 111 -13 461 -15 3121 -14 3106 0 3123 0 3314 39 221 45 397 134 531 270 161 162 238 342 269 626 12 107 15 407 15 1696 0 862 -2 1573 -4 1580 -3 8 -7 63 -10 122 -4 60 -8 112 -10 116 -3 4 -7 27 -10 51 -17 143 -76 342 -137 463 -30 57 -107 176 -138 211 -62 69 -159 160 -174 164 -13 3 -37 30 -38 44 0 7 -4 4 -8 -7 -8 -19 -8 -19 -15 3 -5 14 -13 21 -21 18 -8 -3 -19 2 -25 10 -7 8 -19 14 -26 14 -8 0 -14 5 -14 10 0 6 -7 10 -15 10 -8 0 -15 5 -15 10 0 6 -9 10 -20 10 -11 0 -20 5 -20 11 0 5 -4 7 -10 4 -5 -3 -10 -1 -10 5 0 6 -4 8 -10 5 -5 -3 -10 -2 -10 4 0 5 -8 8 -17 6 -10 -1 -30 4 -45 11 -15 8 -31 13 -35 13 -4 -1 -16 1 -25 4 -46 18 -54 20 -69 23 -9 2 -27 8 -40 13 -13 5 -27 8 -30 7 -4 0 -17 8 -30 19 -14 13 -20 14 -15 5 4 -8 -4 -2 -18 13 l-26 28 0 847 c-1 466 -3 883 -5 927 -7 117 -14 206 -19 240 -3 24 -26 169 -40 255 -21 125 -30 170 -36 170 -4 0 -6 10 -5 23 1 12 -1 27 -5 32 -5 6 -11 24 -13 40 -9 46 -14 68 -25 96 -6 15 -8 29 -6 32 3 3 -2 22 -10 42 -9 21 -16 47 -16 59 0 16 -2 18 -9 7 -7 -10 -11 -1 -16 32 -4 26 -12 47 -17 47 -6 0 -8 9 -5 20 3 11 1 20 -4 20 -5 0 -9 7 -9 15 0 8 -4 15 -10 15 -5 0 -6 7 -3 17 5 11 3 14 -6 8 -10 -6 -11 -2 -6 15 5 17 4 21 -5 15 -8 -5 -11 -4 -6 3 7 11 -28 93 -96 227 -22 44 -55 107 -71 140 -17 33 -34 62 -38 65 -3 3 -16 25 -29 49 -12 24 -26 49 -31 55 -30 36 -84 113 -105 149 -13 23 -24 38 -24 34 0 -4 -6 -2 -14 5 -8 7 -12 16 -9 20 2 4 -7 19 -21 33 -15 14 -26 31 -26 37 0 6 -3 8 -7 5 -3 -4 -13 2 -20 13 -8 11 -19 18 -24 15 -5 -4 -9 2 -9 12 0 11 -20 39 -45 63 -24 24 -42 47 -39 52 3 4 -4 8 -15 8 -11 0 -22 9 -26 20 -3 11 -13 20 -21 20 -8 0 -14 7 -14 15 0 8 -7 15 -16 15 -8 0 -12 5 -9 10 3 6 -1 10 -9 10 -9 0 -16 5 -16 11 0 5 -3 8 -7 6 -5 -3 -14 1 -21 9 -7 8 -9 14 -5 14 4 1 -4 8 -19 16 -16 8 -28 19 -28 24 0 6 -7 10 -15 10 -8 0 -15 5 -15 10 0 6 -5 10 -10 10 -6 0 -21 11 -34 25 -13 14 -26 25 -30 25 -7 0 -67 41 -76 51 -3 3 -19 13 -37 22 -17 9 -37 22 -45 29 -18 17 -59 42 -143 85 -38 19 -73 40 -76 45 -3 5 -9 9 -12 9 -4 0 -26 8 -49 18 -374 158 -665 229 -1072 261 -150 12 -504 11 -656 -1z m475 -1214 c103 -10 140 -15 240 -31 90 -15 283 -67 314 -85 17 -9 74 -31 79 -30 10 4 273 -148 292 -170 3 -3 23 -18 44 -35 22 -16 49 -38 60 -49 12 -11 35 -31 51 -43 17 -13 23 -21 15 -17 -8 4 -1 -6 16 -22 27 -24 98 -107 157 -184 10 -13 27 -40 38 -59 11 -19 28 -48 39 -65 19 -30 73 -126 75 -135 1 -3 10 -23 20 -45 10 -22 18 -43 17 -47 -1 -5 2 -8 6 -8 5 0 9 -6 10 -12 2 -29 29 -88 37 -81 4 5 5 3 1 -4 -4 -7 7 -50 23 -97 16 -46 27 -87 24 -90 -3 -3 0 -12 7 -21 7 -9 10 -18 7 -22 -4 -3 -2 -12 4 -20 9 -10 8 -13 -2 -13 -9 -1 -8 -5 5 -15 11 -8 15 -15 8 -15 -8 0 -9 -7 -1 -27 6 -16 12 -37 14 -48 8 -49 27 -203 29 -230 0 -16 5 -33 11 -37 7 -5 6 -8 0 -8 -6 0 -11 -9 -11 -20 0 -11 4 -20 9 -20 5 0 4 -6 -2 -14 -9 -11 -9 -15 1 -20 10 -5 10 -7 1 -12 -19 -8 -16 -24 5 -24 10 0 13 -3 6 -8 -16 -10 -18 -222 -3 -222 8 0 9 -4 0 -13 -8 -10 -12 -215 -13 -707 l-3 -694 -34 -20 c-34 -20 -56 -20 -1717 -24 -1216 -3 -1683 -1 -1688 7 -4 6 -22 11 -40 11 -69 0 -65 -59 -66 905 -1 479 -1 872 0 875 1 3 3 32 5 65 4 65 10 117 26 210 6 33 12 71 13 85 2 14 6 32 10 41 4 9 8 27 10 41 1 13 5 28 8 33 3 6 9 28 13 50 8 42 47 159 71 212 8 17 14 34 14 39 0 33 188 356 247 424 36 42 197 200 239 235 110 93 398 240 507 259 7 1 28 7 47 14 58 19 273 52 382 58 57 4 104 7 105 8 4 3 156 -3 218 -9z"
+ id="path4" />
+ </g>
+ <rect
+ id="rect14"
+ width="1321.9366"
+ height="329.28085"
+ x="-502.36847"
+ y="728.58783"
+ style="stroke-width:1.05677092;fill:#ffffff"
+ ry="46.090546"
+ transform="matrix(0.7710634,-0.63675838,0.53742864,0.84330923,0,0)" />
+ <rect
+ transform="matrix(0.7710634,-0.63675838,0.53742864,0.84330923,0,0)"
+ ry="35.784081"
+ style="fill:#ff0000;stroke-width:0.82046276"
+ y="771.86188"
+ x="-367.09418"
+ height="255.64925"
+ width="1026.3339"
+ id="rect16" />
+</svg>
diff --git a/resources/icons/page-info-internal.svg b/resources/icons/page-info-internal.svg
new file mode 100644
index 000000000..d5fc24d1d
--- /dev/null
+++ b/resources/icons/page-info-internal.svg
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="19.683775cm"
+ height="19.707985cm"
+ viewBox="842.6016 303.4219 2789.8313 2793.2508"
+ version="1.0"
+ id="svg43"
+ sodipodi:docname="page-info-internal.svg"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
+ <metadata
+ id="metadata49">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs47">
+ <filter
+ style="color-interpolation-filters:sRGB"
+ inkscape:label="Greyscale"
+ id="filter3860">
+ <feColorMatrix
+ values="0.26 0.72 -0.04 0 0 0.26 0.72 -0.04 0 0 0.26 0.72 -0.04 0 0 0 0 0 1 0 "
+ id="feColorMatrix3858"
+ result="fbSourceGraphic" />
+ <feColorMatrix
+ result="fbSourceGraphicAlpha"
+ in="fbSourceGraphic"
+ values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+ id="feColorMatrix3862" />
+ <feColorMatrix
+ id="feColorMatrix3864"
+ values="0.26 0.72 -0.04 0 0 0.26 0.72 -0.04 0 0 0.26 0.72 -0.04 0 0 0 0 0 1 0 "
+ in="fbSourceGraphic" />
+ </filter>
+ </defs>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1354"
+ inkscape:window-height="678"
+ id="namedview45"
+ showgrid="false"
+ inkscape:zoom="0.73408106"
+ inkscape:cx="218.20267"
+ inkscape:cy="428.1062"
+ inkscape:window-x="0"
+ inkscape:window-y="28"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg43" />
+ <desc
+ id="desc2">
+ Exported by the ArtWorks SVGExport module.
+ Source document: ADFS::Pan.$.Public.Michael.NetSurf.SVN.trunk.art.logo.emblem.NetSurf
+</desc>
+ <g
+ transform="matrix(1,0,0,-1,188.36093,3206.6654)"
+ stroke-miterlimit="16"
+ id="g41"
+ style="clip-rule:evenodd;fill-rule:evenodd;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:16;filter:url(#filter3860)">
+ <g
+ id="g39">
+ <defs
+ id="defs9">
+ <radialGradient
+ id="_Fill0"
+ gradientUnits="userSpaceOnUse"
+ cx="1431.0469"
+ cy="2198.4453"
+ r="2142.9219"
+ spreadMethod="pad">
+ <stop
+ offset="0"
+ stop-color="#b8f5ff"
+ id="stop4" />
+ <stop
+ offset="1"
+ stop-color="#0097ff"
+ id="stop6" />
+ </radialGradient>
+ </defs>
+ <path
+ d="m 886.7266,1509.0156 c 0,641.4688 519.8593,1161.461 1161.4453,1161.461 641.6953,0 1161.5859,-519.9922 1161.5859,-1161.461 0,-641.4218 -519.8906,-1161.4687 -1161.4375,-1161.4687 -641.7344,0 -1161.5937,520.0469 -1161.5937,1161.4687 z"
+ id="path11"
+ inkscape:connector-curvature="0"
+ style="fill:url(#_Fill0);stroke:#000000;stroke-width:88.35160065" />
+ <path
+ d="m 2819.9219,1695.4375 -72.9375,202.0234 166.6172,100.2891 -194.5235,91.3906 46.8438,188.6016 -202.0235,-72.9453 -100.3203,166.6797 -91.3593,-194.5782 -188.625,46.8125 72.9687,-202 -166.6719,-100.3437 194.625,-91.3281 -46.8906,-188.6016 202.0234,72.9141 100.2969,-166.6485 91.3828,194.5703 z"
+ id="path13"
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff" />
+ <path
+ d="m 1527.625,2475.9219 -52.9297,-201.7656 -88.4531,17.6875 60.1328,219.4531 z"
+ id="path15"
+ inkscape:connector-curvature="0"
+ style="fill:#000000" />
+ <path
+ d="m 1432.1094,2069.1016 -17.6797,-205.211 -81.2266,3.4219 17.711,215.8203 z"
+ id="path17"
+ inkscape:connector-curvature="0"
+ style="fill:#000000" />
+ <path
+ d="m 1414.4297,1651.625 31.9453,-201.5781 -88.4062,-17.711 -24.7657,215.5547 z"
+ id="path19"
+ inkscape:connector-curvature="0"
+ style="fill:#000000" />
+ <path
+ d="m 1495.8047,1244.8594 81.4062,-184.0235 -77.7812,-35.3203 -84.8438,197.7735 z"
+ id="path21"
+ inkscape:connector-curvature="0"
+ style="fill:#000000" />
+ <path
+ d="m 1676.3594,873.3906 120.164,-162.8437 -70.7656,-56.5313 -123.6484,176.5547 z"
+ id="path23"
+ inkscape:connector-curvature="0"
+ style="fill:#000000" />
+ <path
+ d="m 1927.3594,540.7344 152.2031,-155.5703 -84.8437,-42.4063 -130.836,144.5078 z"
+ id="path25"
+ inkscape:connector-curvature="0"
+ style="fill:#000000" />
+ <path
+ d="m 1018.2656,1046.625 176.8907,-74.1953 -21.1329,-74.3203 -152.1484,46 z"
+ id="path27"
+ inkscape:connector-curvature="0"
+ style="fill:#000000" />
+ <path
+ d="m 1396.7891,929.9219 212.2343,-14.1328 -3.4375,-88.4063 -219.3437,21.2656 z"
+ id="path29"
+ inkscape:connector-curvature="0"
+ style="fill:#000000" />
+ <path
+ d="m 1817.8203,912.2109 208.6563,21.2657 10.6093,-84.8282 -215.7968,-21.2656 z"
+ id="path31"
+ inkscape:connector-curvature="0"
+ style="fill:#000000" />
+ <path
+ d="m 2231.6641,965.0859 201.6328,49.7657 24.75,-84.9297 -208.6719,-49.4844 z"
+ id="path33"
+ inkscape:connector-curvature="0"
+ style="fill:#000000" />
+ <path
+ d="m 2635.0625,1081.7656 187.3438,85.25 35.4062,-74.3593 -190.9531,-92.0391 z"
+ id="path35"
+ inkscape:connector-curvature="0"
+ style="fill:#000000" />
+ <path
+ d="m 2992.4063,1279.6094 141.3593,142.0625 77.8203,-49.586 -162.7812,-159.2031 z"
+ id="path37"
+ inkscape:connector-curvature="0"
+ style="fill:#000000" />
+ </g>
+ </g>
+</svg>
diff --git a/resources/icons/page-info-local.svg b/resources/icons/page-info-local.svg
new file mode 100644
index 000000000..0ceeabe6d
--- /dev/null
+++ b/resources/icons/page-info-local.svg
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="108mm"
+ height="108mm"
+ viewBox="0 0 108 108"
+ version="1.1"
+ id="svg8"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="page-info-local.svg">
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.35"
+ inkscape:cx="-29.077615"
+ inkscape:cy="563.77953"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1366"
+ inkscape:window-height="683"
+ inkscape:window-x="0"
+ inkscape:window-y="28"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(1,-190)">
+ <circle
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path10"
+ cx="53"
+ cy="244"
+ r="50" />
+ <g
+ aria-label="i"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:102.01290894px;line-height:125%;font-family:'Noto Serif';-inkscape-font-specification:'Noto Serif Bold';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.53131729px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="text4522">
+ <path
+ d="m 53.612077,218.90481 q -3.672465,0 -6.222787,-1.73422 -2.44831,-1.83623 -2.44831,-5.61071 0,-3.87649 2.44831,-5.61071 2.550322,-1.73422 6.222787,-1.73422 3.570452,0 6.120775,1.73422 2.652335,1.73422 2.652335,5.61071 0,3.77448 -2.652335,5.61071 -2.550323,1.73422 -6.120775,1.73422 z m -15.709988,63.86008 v -5.40668 h 1.224155 q 1.530194,0 3.1624,-0.40805 1.73422,-0.51007 2.856362,-1.93825 1.224154,-1.42818 1.224154,-4.28454 v -31.01192 q 0,-2.75435 -1.224154,-4.08052 -1.224155,-1.32617 -2.958375,-1.73422 -1.632206,-0.40805 -3.060387,-0.40805 h -1.224155 v -5.40669 h 23.973034 v 42.6414 q 0,2.85636 1.122142,4.28454 1.224155,1.42818 2.958374,1.93825 1.734219,0.40805 3.1624,0.40805 h 1.224155 v 5.40668 z"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:102.01290894px;font-family:'Noto Serif';-inkscape-font-specification:'Noto Serif Bold';stroke-width:0.53131729px"
+ id="path4524"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+</svg>
diff --git a/resources/icons/page-info-secure.svg b/resources/icons/page-info-secure.svg
new file mode 100644
index 000000000..b7277c478
--- /dev/null
+++ b/resources/icons/page-info-secure.svg
@@ -0,0 +1,69 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
+ width="1190.000000pt" height="1280.000000pt" viewBox="0 0 1190.000000 1280.000000"
+ preserveAspectRatio="xMidYMid meet">
+<metadata>
+Created by potrace 1.15, written by Peter Selinger 2001-2017
+</metadata>
+<g transform="translate(0.000000,1280.000000) scale(0.100000,-0.100000)"
+fill="#000000" stroke="none">
+<path d="M5610 11999 c-1096 -88 -1924 -626 -2375 -1544 -80 -162 -155 -347
+-155 -380 0 -8 -4 -15 -8 -15 -4 0 -8 -8 -9 -17 -1 -19 -6 -38 -16 -63 -17
+-47 -78 -287 -91 -360 -3 -19 -8 -46 -11 -59 -2 -14 -7 -47 -10 -74 -3 -28 -8
+-53 -10 -56 -8 -13 -24 -189 -28 -313 -1 -27 -5 -48 -10 -48 -4 0 -3 -9 3 -20
+8 -14 8 -20 0 -20 -7 0 -8 -6 -1 -19 6 -10 8 -21 5 -24 -3 -3 -5 -392 -4 -865
+l1 -860 -26 -20 c-14 -11 -69 -30 -123 -43 -159 -36 -266 -74 -364 -128 -109
+-60 -149 -91 -240 -183 -206 -208 -334 -560 -353 -968 -5 -99 -4 -3022 1
+-3125 8 -175 28 -319 46 -343 7 -8 7 -12 -1 -12 -7 0 -9 -5 -4 -13 4 -6 8 -16
+9 -22 1 -5 11 -34 23 -62 11 -29 17 -53 13 -53 -4 0 -2 -4 3 -8 10 -7 37 -61
+37 -72 0 -3 6 -12 14 -21 8 -9 12 -18 9 -21 -3 -3 6 -17 20 -32 13 -14 25 -29
+25 -31 0 -14 84 -117 122 -150 24 -21 34 -32 23 -24 -18 13 -19 13 -6 -3 7
+-10 17 -18 22 -18 5 0 17 -8 27 -17 39 -37 67 -57 121 -86 175 -94 267 -121
+521 -153 111 -13 461 -15 3121 -14 3106 0 3123 0 3314 39 221 45 397 134 531
+270 161 162 238 342 269 626 12 107 15 407 15 1696 0 862 -2 1573 -4 1580 -3
+8 -7 63 -10 122 -4 60 -8 112 -10 116 -3 4 -7 27 -10 51 -17 143 -76 342 -137
+463 -30 57 -107 176 -138 211 -62 69 -159 160 -174 164 -13 3 -37 30 -38 44 0
+7 -4 4 -8 -7 -8 -19 -8 -19 -15 3 -5 14 -13 21 -21 18 -8 -3 -19 2 -25 10 -7
+8 -19 14 -26 14 -8 0 -14 5 -14 10 0 6 -7 10 -15 10 -8 0 -15 5 -15 10 0 6 -9
+10 -20 10 -11 0 -20 5 -20 11 0 5 -4 7 -10 4 -5 -3 -10 -1 -10 5 0 6 -4 8 -10
+5 -5 -3 -10 -2 -10 4 0 5 -8 8 -17 6 -10 -1 -30 4 -45 11 -15 8 -31 13 -35 13
+-4 -1 -16 1 -25 4 -46 18 -54 20 -69 23 -9 2 -27 8 -40 13 -13 5 -27 8 -30 7
+-4 0 -17 8 -30 19 -14 13 -20 14 -15 5 4 -8 -4 -2 -18 13 l-26 28 0 847 c-1
+466 -3 883 -5 927 -7 117 -14 206 -19 240 -3 24 -26 169 -40 255 -21 125 -30
+170 -36 170 -4 0 -6 10 -5 23 1 12 -1 27 -5 32 -5 6 -11 24 -13 40 -9 46 -14
+68 -25 96 -6 15 -8 29 -6 32 3 3 -2 22 -10 42 -9 21 -16 47 -16 59 0 16 -2 18
+-9 7 -7 -10 -11 -1 -16 32 -4 26 -12 47 -17 47 -6 0 -8 9 -5 20 3 11 1 20 -4
+20 -5 0 -9 7 -9 15 0 8 -4 15 -10 15 -5 0 -6 7 -3 17 5 11 3 14 -6 8 -10 -6
+-11 -2 -6 15 5 17 4 21 -5 15 -8 -5 -11 -4 -6 3 7 11 -28 93 -96 227 -22 44
+-55 107 -71 140 -17 33 -34 62 -38 65 -3 3 -16 25 -29 49 -12 24 -26 49 -31
+55 -30 36 -84 113 -105 149 -13 23 -24 38 -24 34 0 -4 -6 -2 -14 5 -8 7 -12
+16 -9 20 2 4 -7 19 -21 33 -15 14 -26 31 -26 37 0 6 -3 8 -7 5 -3 -4 -13 2
+-20 13 -8 11 -19 18 -24 15 -5 -4 -9 2 -9 12 0 11 -20 39 -45 63 -24 24 -42
+47 -39 52 3 4 -4 8 -15 8 -11 0 -22 9 -26 20 -3 11 -13 20 -21 20 -8 0 -14 7
+-14 15 0 8 -7 15 -16 15 -8 0 -12 5 -9 10 3 6 -1 10 -9 10 -9 0 -16 5 -16 11
+0 5 -3 8 -7 6 -5 -3 -14 1 -21 9 -7 8 -9 14 -5 14 4 1 -4 8 -19 16 -16 8 -28
+19 -28 24 0 6 -7 10 -15 10 -8 0 -15 5 -15 10 0 6 -5 10 -10 10 -6 0 -21 11
+-34 25 -13 14 -26 25 -30 25 -7 0 -67 41 -76 51 -3 3 -19 13 -37 22 -17 9 -37
+22 -45 29 -18 17 -59 42 -143 85 -38 19 -73 40 -76 45 -3 5 -9 9 -12 9 -4 0
+-26 8 -49 18 -374 158 -665 229 -1072 261 -150 12 -504 11 -656 -1z m475
+-1214 c103 -10 140 -15 240 -31 90 -15 283 -67 314 -85 17 -9 74 -31 79 -30
+10 4 273 -148 292 -170 3 -3 23 -18 44 -35 22 -16 49 -38 60 -49 12 -11 35
+-31 51 -43 17 -13 23 -21 15 -17 -8 4 -1 -6 16 -22 27 -24 98 -107 157 -184
+10 -13 27 -40 38 -59 11 -19 28 -48 39 -65 19 -30 73 -126 75 -135 1 -3 10
+-23 20 -45 10 -22 18 -43 17 -47 -1 -5 2 -8 6 -8 5 0 9 -6 10 -12 2 -29 29
+-88 37 -81 4 5 5 3 1 -4 -4 -7 7 -50 23 -97 16 -46 27 -87 24 -90 -3 -3 0 -12
+7 -21 7 -9 10 -18 7 -22 -4 -3 -2 -12 4 -20 9 -10 8 -13 -2 -13 -9 -1 -8 -5 5
+-15 11 -8 15 -15 8 -15 -8 0 -9 -7 -1 -27 6 -16 12 -37 14 -48 8 -49 27 -203
+29 -230 0 -16 5 -33 11 -37 7 -5 6 -8 0 -8 -6 0 -11 -9 -11 -20 0 -11 4 -20 9
+-20 5 0 4 -6 -2 -14 -9 -11 -9 -15 1 -20 10 -5 10 -7 1 -12 -19 -8 -16 -24 5
+-24 10 0 13 -3 6 -8 -16 -10 -18 -222 -3 -222 8 0 9 -4 0 -13 -8 -10 -12 -215
+-13 -707 l-3 -694 -34 -20 c-34 -20 -56 -20 -1717 -24 -1216 -3 -1683 -1
+-1688 7 -4 6 -22 11 -40 11 -69 0 -65 -59 -66 905 -1 479 -1 872 0 875 1 3 3
+32 5 65 4 65 10 117 26 210 6 33 12 71 13 85 2 14 6 32 10 41 4 9 8 27 10 41
+1 13 5 28 8 33 3 6 9 28 13 50 8 42 47 159 71 212 8 17 14 34 14 39 0 33 188
+356 247 424 36 42 197 200 239 235 110 93 398 240 507 259 7 1 28 7 47 14 58
+19 273 52 382 58 57 4 104 7 105 8 4 3 156 -3 218 -9z"/>
+</g>
+</svg>
diff --git a/resources/icons/page-info-warning.svg b/resources/icons/page-info-warning.svg
new file mode 100644
index 000000000..b22b7a147
--- /dev/null
+++ b/resources/icons/page-info-warning.svg
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.0"
+ width="1190.000000pt"
+ height="1280.000000pt"
+ viewBox="0 0 1190.000000 1280.000000"
+ preserveAspectRatio="xMidYMid meet"
+ id="svg8"
+ sodipodi:docname="padlock-warning.svg"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
+ <defs
+ id="defs12">
+ <linearGradient
+ y1="45.47"
+ x2="0"
+ y2="-.599"
+ id="0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.31117,0,0,1.30239,737.39,159.91)">
+ <stop
+ id="stop33"
+ stop-color="#ffc515" />
+ <stop
+ id="stop35"
+ stop-color="#ffd55b"
+ offset="1" />
+ </linearGradient>
+ </defs>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="2560"
+ inkscape:window-height="1416"
+ id="namedview10"
+ showgrid="false"
+ inkscape:zoom="0.13828125"
+ inkscape:cx="807.79661"
+ inkscape:cy="853.33333"
+ inkscape:window-x="0"
+ inkscape:window-y="24"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg8" />
+ <metadata
+ id="metadata2">
+Created by potrace 1.15, written by Peter Selinger 2001-2017
+<rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+</rdf:RDF>
+</metadata>
+ <g
+ transform="translate(0.000000,1280.000000) scale(0.100000,-0.100000)"
+ fill="#000000"
+ stroke="none"
+ id="g6">
+ <path
+ d="M5610 11999 c-1096 -88 -1924 -626 -2375 -1544 -80 -162 -155 -347 -155 -380 0 -8 -4 -15 -8 -15 -4 0 -8 -8 -9 -17 -1 -19 -6 -38 -16 -63 -17 -47 -78 -287 -91 -360 -3 -19 -8 -46 -11 -59 -2 -14 -7 -47 -10 -74 -3 -28 -8 -53 -10 -56 -8 -13 -24 -189 -28 -313 -1 -27 -5 -48 -10 -48 -4 0 -3 -9 3 -20 8 -14 8 -20 0 -20 -7 0 -8 -6 -1 -19 6 -10 8 -21 5 -24 -3 -3 -5 -392 -4 -865 l1 -860 -26 -20 c-14 -11 -69 -30 -123 -43 -159 -36 -266 -74 -364 -128 -109 -60 -149 -91 -240 -183 -206 -208 -334 -560 -353 -968 -5 -99 -4 -3022 1 -3125 8 -175 28 -319 46 -343 7 -8 7 -12 -1 -12 -7 0 -9 -5 -4 -13 4 -6 8 -16 9 -22 1 -5 11 -34 23 -62 11 -29 17 -53 13 -53 -4 0 -2 -4 3 -8 10 -7 37 -61 37 -72 0 -3 6 -12 14 -21 8 -9 12 -18 9 -21 -3 -3 6 -17 20 -32 13 -14 25 -29 25 -31 0 -14 84 -117 122 -150 24 -21 34 -32 23 -24 -18 13 -19 13 -6 -3 7 -10 17 -18 22 -18 5 0 17 -8 27 -17 39 -37 67 -57 121 -86 175 -94 267 -121 521 -153 111 -13 461 -15 3121 -14 3106 0 3123 0 3314 39 221 45 397 134 531 270 161 162 238 342 269 626 12 107 15 407 15 1696 0 862 -2 1573 -4 1580 -3 8 -7 63 -10 122 -4 60 -8 112 -10 116 -3 4 -7 27 -10 51 -17 143 -76 342 -137 463 -30 57 -107 176 -138 211 -62 69 -159 160 -174 164 -13 3 -37 30 -38 44 0 7 -4 4 -8 -7 -8 -19 -8 -19 -15 3 -5 14 -13 21 -21 18 -8 -3 -19 2 -25 10 -7 8 -19 14 -26 14 -8 0 -14 5 -14 10 0 6 -7 10 -15 10 -8 0 -15 5 -15 10 0 6 -9 10 -20 10 -11 0 -20 5 -20 11 0 5 -4 7 -10 4 -5 -3 -10 -1 -10 5 0 6 -4 8 -10 5 -5 -3 -10 -2 -10 4 0 5 -8 8 -17 6 -10 -1 -30 4 -45 11 -15 8 -31 13 -35 13 -4 -1 -16 1 -25 4 -46 18 -54 20 -69 23 -9 2 -27 8 -40 13 -13 5 -27 8 -30 7 -4 0 -17 8 -30 19 -14 13 -20 14 -15 5 4 -8 -4 -2 -18 13 l-26 28 0 847 c-1 466 -3 883 -5 927 -7 117 -14 206 -19 240 -3 24 -26 169 -40 255 -21 125 -30 170 -36 170 -4 0 -6 10 -5 23 1 12 -1 27 -5 32 -5 6 -11 24 -13 40 -9 46 -14 68 -25 96 -6 15 -8 29 -6 32 3 3 -2 22 -10 42 -9 21 -16 47 -16 59 0 16 -2 18 -9 7 -7 -10 -11 -1 -16 32 -4 26 -12 47 -17 47 -6 0 -8 9 -5 20 3 11 1 20 -4 20 -5 0 -9 7 -9 15 0 8 -4 15 -10 15 -5 0 -6 7 -3 17 5 11 3 14 -6 8 -10 -6 -11 -2 -6 15 5 17 4 21 -5 15 -8 -5 -11 -4 -6 3 7 11 -28 93 -96 227 -22 44 -55 107 -71 140 -17 33 -34 62 -38 65 -3 3 -16 25 -29 49 -12 24 -26 49 -31 55 -30 36 -84 113 -105 149 -13 23 -24 38 -24 34 0 -4 -6 -2 -14 5 -8 7 -12 16 -9 20 2 4 -7 19 -21 33 -15 14 -26 31 -26 37 0 6 -3 8 -7 5 -3 -4 -13 2 -20 13 -8 11 -19 18 -24 15 -5 -4 -9 2 -9 12 0 11 -20 39 -45 63 -24 24 -42 47 -39 52 3 4 -4 8 -15 8 -11 0 -22 9 -26 20 -3 11 -13 20 -21 20 -8 0 -14 7 -14 15 0 8 -7 15 -16 15 -8 0 -12 5 -9 10 3 6 -1 10 -9 10 -9 0 -16 5 -16 11 0 5 -3 8 -7 6 -5 -3 -14 1 -21 9 -7 8 -9 14 -5 14 4 1 -4 8 -19 16 -16 8 -28 19 -28 24 0 6 -7 10 -15 10 -8 0 -15 5 -15 10 0 6 -5 10 -10 10 -6 0 -21 11 -34 25 -13 14 -26 25 -30 25 -7 0 -67 41 -76 51 -3 3 -19 13 -37 22 -17 9 -37 22 -45 29 -18 17 -59 42 -143 85 -38 19 -73 40 -76 45 -3 5 -9 9 -12 9 -4 0 -26 8 -49 18 -374 158 -665 229 -1072 261 -150 12 -504 11 -656 -1z m475 -1214 c103 -10 140 -15 240 -31 90 -15 283 -67 314 -85 17 -9 74 -31 79 -30 10 4 273 -148 292 -170 3 -3 23 -18 44 -35 22 -16 49 -38 60 -49 12 -11 35 -31 51 -43 17 -13 23 -21 15 -17 -8 4 -1 -6 16 -22 27 -24 98 -107 157 -184 10 -13 27 -40 38 -59 11 -19 28 -48 39 -65 19 -30 73 -126 75 -135 1 -3 10 -23 20 -45 10 -22 18 -43 17 -47 -1 -5 2 -8 6 -8 5 0 9 -6 10 -12 2 -29 29 -88 37 -81 4 5 5 3 1 -4 -4 -7 7 -50 23 -97 16 -46 27 -87 24 -90 -3 -3 0 -12 7 -21 7 -9 10 -18 7 -22 -4 -3 -2 -12 4 -20 9 -10 8 -13 -2 -13 -9 -1 -8 -5 5 -15 11 -8 15 -15 8 -15 -8 0 -9 -7 -1 -27 6 -16 12 -37 14 -48 8 -49 27 -203 29 -230 0 -16 5 -33 11 -37 7 -5 6 -8 0 -8 -6 0 -11 -9 -11 -20 0 -11 4 -20 9 -20 5 0 4 -6 -2 -14 -9 -11 -9 -15 1 -20 10 -5 10 -7 1 -12 -19 -8 -16 -24 5 -24 10 0 13 -3 6 -8 -16 -10 -18 -222 -3 -222 8 0 9 -4 0 -13 -8 -10 -12 -215 -13 -707 l-3 -694 -34 -20 c-34 -20 -56 -20 -1717 -24 -1216 -3 -1683 -1 -1688 7 -4 6 -22 11 -40 11 -69 0 -65 -59 -66 905 -1 479 -1 872 0 875 1 3 3 32 5 65 4 65 10 117 26 210 6 33 12 71 13 85 2 14 6 32 10 41 4 9 8 27 10 41 1 13 5 28 8 33 3 6 9 28 13 50 8 42 47 159 71 212 8 17 14 34 14 39 0 33 188 356 247 424 36 42 197 200 239 235 110 93 398 240 507 259 7 1 28 7 47 14 58 19 273 52 382 58 57 4 104 7 105 8 4 3 156 -3 218 -9z"
+ id="path4" />
+ </g>
+ <g
+ id="g44"
+ transform="matrix(14.340787,0,0,14.340787,-10339.937,-1906.3913)">
+ <path
+ id="path40"
+ d="m 797.94,212.01 -25.607,-48 c -0.736,-1.333 -2.068,-2.074 -3.551,-2.074 -1.483,0 -2.822,0.889 -3.569,2.222 l -25.417,48 c -0.598,1.185 -0.605,2.815 0.132,4 0.737,1.185 1.921,1.778 3.404,1.778 h 51.02 c 1.483,0 2.821,-0.741 3.42,-1.926 0.747,-1.185 0.753,-2.667 0.165,-4"
+ inkscape:connector-curvature="0"
+ style="fill:url(#0)" />
+ <path
+ id="path42"
+ transform="matrix(1.05196,0,0,1.05196,796.53,161.87)"
+ d="m -26.309,18.07 c -1.18,0 -2.135,0.968 -2.135,2.129 v 12.82 c 0,1.176 0.948,2.129 2.135,2.129 1.183,0 2.135,-0.968 2.135,-2.129 v -12.82 c 0,-1.176 -0.946,-2.129 -2.135,-2.129 z m 0,21.348 c -1.18,0 -2.135,0.954 -2.135,2.135 0,1.18 0.954,2.135 2.135,2.135 1.181,0 2.135,-0.954 2.135,-2.135 0,-1.18 -0.952,-2.135 -2.135,-2.135 z"
+ inkscape:connector-curvature="0"
+ style="fill:#000000;fill-opacity:0.75;stroke:#40330d" />
+ </g>
+</svg>
diff --git a/resources/icons/show-cookie.png b/resources/icons/show-cookie.png
new file mode 100644
index 000000000..8e449721c
--- /dev/null
+++ b/resources/icons/show-cookie.png
Binary files differ
diff --git a/resources/internal.css b/resources/internal.css
index c72dfac06..7f8c40699 100644
--- a/resources/internal.css
+++ b/resources/internal.css
@@ -1,42 +1,42 @@
+@import url("about:nscolours.css");
+
html, body {
margin: 0;
padding: 0; }
+html {
+ padding: 2em;
+}
+
body {
- color: #000;
- background-color: #fff;
font-family: sans-serif;
font-size: 94%;
margin: 0 auto;
- position: relative; }
+ position: relative;
+ border-width: 2px;
+ border-style: solid; }
h1, h2, h3, h4, h5, h6, h7, p, ul, dl, ol, table {
margin-left: 5mm;
margin-right: 5mm; }
-a:link {
- text-decoration: underline;
- color: #00f; }
-
-a:visited {
- text-decoration: underline;
- color: #60a; }
-
-a:hover {
- text-decoration: none; }
-
-a:active {
- text-decoration: underline;
- color: #f00; }
-
h1 {
font-size: 200%;
- font-weight: bold; }
+ font-weight: bold;
+ padding: 5mm;
+ margin: 0;
+ border-bottom-width: 2px;
+ border-bottom-style: solid; }
h2 {
font-size: 160%;
padding-top: 5mm;
- border-top: 1px solid black; }
+ border-top-width: 1px;
+ border-top-style: solid; }
+
+h1+h2 {
+ border-top: none;
+}
h3 {
font-size: 140%;
@@ -72,45 +72,30 @@ dd > ul {
padding-left: 0;
margin-bottom: 1em; }
-.banner {
- margin: 0;
- padding: 0;
- background-color: #94adff;
- color: black;
- text-align: left; }
-
-.banner img {
- border: none;
- color: #000;
- height: 86px;
- width: 308px;
- display: block; }
-
.footer {
clear: both;
font-style: italic;
- color:#666;
text-align: right; }
.footer p {
margin-top: 1.5em;
padding-top: 0.4em;
- border-top: 2px solid #94adff; }
+ border-top-width: 2px;
+ border-top-style: solid; }
+input.default-action {
+ color: white;
+ background: rgb(0, 96, 223);
+ border-color: rgb(0, 96, 223);
+}
/*
* Directory Listing Style
*/
body#dirlist {
- background-color: #abf;
padding-bottom: 2em; }
-body#dirlist h1 {
- padding: 5mm;
- margin: 0;
- border-bottom: 2px solid #bcf; }
-
body#dirlist p {
padding: 2px 5mm;
margin: 0; }
@@ -121,26 +106,31 @@ body#dirlist div {
margin: 5mm auto 2em auto;
padding: 0; }
-body#dirlist a, strong {
+body#dirlist strong {
display: table-row;
margin: 0;
- padding: 0; }
-
-body#dirlist a.odd {
- background-color: #bcf; }
+ padding: 0;
+ font-size: 120%;
+}
-body#dirlist a.even {
- background-color: #b2c3ff; }
+body#dirlist a {
+ display: table-row;
+ margin: 0;
+ padding: 0; }
body#dirlist span {
display: table-cell;
vertical-align: middle; }
+body#dirlist a > span {
+ padding-top: 0.1em; }
+
body#dirlist em > span {
padding-bottom: 1px; }
body#dirlist a + a>span {
- border-top: 1px solid #9af; }
+ border-top-width: 1px;
+ border-top-style: solid; }
body#dirlist a {
background-position: 4px 50%;
@@ -172,27 +162,56 @@ body#dirlist span.size + span.size {
padding-right: 0; }
+/*
+ * certificate display style
+ */
+body#certificate table.info {
+ width: 90%;
+ margin: 1.2em auto 0;
+}
+
+body#certificate table.info th {
+ width: 14em;
+ vertical-align: top;
+ text-align: right;
+ font-weight: bold;
+ font-family: sans-serif;
+ padding-right: 1em;
+}
+
+body#certificate table.info td.data {
+ font-family: monospace;
+ font-size: 90%;
+}
+
+
/*
* configuration listing style
*/
body#configlist table.config {
- border-spacing: 0; }
-
-body#configlist table.config tr:nth-child(2n-1) {
- background: #eee; }
+ border-spacing: 0;
+ font-size: 85%;
+ margin: 1.3em 0;
+ width: 100%;
+ box-sizing: border-box }
body#configlist table.config tr:first-child th {
text-align: left;
font-weight: bold;
- font-family: sans-serif;
- background: #ddd; }
+ font-family: sans-serif; }
body#configlist table.config tr th {
text-align: left;
font-weight: normal;
font-family: monospace; }
+body#configlist table.config tr+tr th,
+body#configlist table.config tr+tr td {
+ border-top-width: 1px;
+ border-top-style: solid;
+}
+
body#configlist table.config td, body#configlist table.config th {
padding-left: 1em; }
@@ -205,7 +224,7 @@ body#configlist table.config tr *:nth-child(4) {
padding-right: 1em; }
body#configlist .null-content {
- font-style: italic; }
+ font-style: italic; }
/*
@@ -219,21 +238,154 @@ p.imagecachelist {
display: table;
}
-p.imagecachelist a:nth-child(2n+3) {
- background: #e8edff;
-}
-
p.imagecachelist strong, p.imagecachelist a {
display: table-row;
}
-p.imagecachelist strong span {
- background: #c8d5ff;
-}
-
p.imagecachelist span {
- border-top: 1px solid #bcf;
padding: 2px 0.5em;
display: table-cell;
}
+p.imagecachelist a+a span {
+ border-top-width: 1px;
+ border-top-style: solid;
+}
+
+/*
+ * authentication query styling
+ */
+
+body#authentication {
+ max-width: 45em;
+}
+
+body#authentication form {
+ /* Just to center the form on the page */
+ margin: 0 auto;
+ /* To see the outline of the form */
+ padding: 1em;
+}
+
+body#authentication table {
+ box-sizing: border-box;
+ width: 100%;
+ margin: 1.5em auto;
+}
+
+body#authentication label {
+ /* To make sure that all labels have the same size and are properly aligned */
+ display: inline-block;
+ text-align: right;
+}
+
+body#authentication table th {
+ text-align: right;
+}
+
+body#authentication table td {
+ text-align: left;
+}
+
+body#authentication table input {
+ /* To give the same size to all text fields */
+ width: 20em;
+ box-sizing: border-box;
+ margin-right: 10%;
+
+ /* To harmonize the look & feel of text field border */
+ border: 1px solid #999;
+}
+
+body#authentication div#buttons {
+ text-align: right;
+ margin-right: 1em;
+}
+
+body#authentication div#buttons input#login {
+ margin-right: 1em;
+}
+
+/*
+ * privacy query styling
+ */
+
+body#privacy {
+ max-width: 45em;
+}
+
+body#privacy form {
+ /* Just to center the form on the page */
+ margin: 0 auto;
+ /* To see the outline of the form */
+ padding: 1em;
+}
+
+body#privacy form div + div {
+ margin-top: 1em;
+}
+
+body#privacy div#buttons {
+ text-align: right;
+ margin-right: 1em;
+}
+
+body#privacy div#buttons input#back {
+ margin-right: 1em;
+}
+
+/*
+ * timeout query styling
+ */
+
+body#timeout {
+ max-width: 45em;
+}
+
+body#timeout form {
+ /* Just to center the form on the page */
+ margin: 0 auto;
+ /* To see the outline of the form */
+ padding: 1em;
+}
+
+body#timeout form div + div {
+ margin-top: 1em;
+}
+
+body#timeout div#buttons {
+ text-align: right;
+ margin-right: 1em;
+}
+
+body#timeout div#buttons input#back {
+ margin-right: 1em;
+}
+
+/*
+ * fetch error query styling
+ */
+
+body#fetcherror {
+ max-width: 45em;
+}
+
+body#fetcherror form {
+ /* Just to center the form on the page */
+ margin: 0 auto;
+ /* To see the outline of the form */
+ padding: 1em;
+}
+
+body#fetcherror form div + div {
+ margin-top: 1em;
+}
+
+body#fetcherror div#buttons {
+ text-align: right;
+ margin-right: 1em;
+}
+
+body#fetcherror div#buttons input#back {
+ margin-right: 1em;
+}
diff --git a/resources/it/credits.html b/resources/it/credits.html
index cec1912a6..c700f3184 100644
--- a/resources/it/credits.html
+++ b/resources/it/credits.html
@@ -12,16 +12,15 @@ div#DevList ul {
</style>
</head>
-<body>
-<p class="banner"><a href="http://www.netsurf-browser.org/"><img src="resource:netsurf.png" alt="NetSurf"></a></p>
+<body class="ns-even-bg ns-even-fg ns-border">
-<h1>Ringraziamenti</h1>
+<h1 class="ns-border">Ringraziamenti</h1>
<p>NetSurf è stato sviluppato dalle seguenti persone:</p>
<div id="DevList">
-<h2>Programmazione e codice sorgente</h2>
+<h2 class="ns-border">Programmazione e codice sorgente</h2>
<ul>
<li>Kevin Bagust</li>
<li>John-Mark Bell</li>
@@ -59,7 +58,7 @@ div#DevList ul {
<li>Chris Young</li>
</ul>
-<h2>Documentazione</h2>
+<h2 class="ns-border">Documentazione</h2>
<ul>
<li>John-Mark Bell</li>
<li>James Bursa</li>
@@ -69,7 +68,7 @@ div#DevList ul {
<li>Richard Wilson</li>
</ul>
-<h2>Grafica e loghi</h2>
+<h2 class="ns-border">Grafica e loghi</h2>
<ul>
<li>Michael Drake</li>
<li>Andrew Duffell</li>
@@ -78,7 +77,7 @@ div#DevList ul {
<li>Phil Mellor</li>
</ul>
-<h2>Traduttori</h2>
+<h2 class="ns-border">Traduttori</h2>
<ul>
<li>Sebastian Barthel</li>
<li>Bruno D'Arcangeli</li>
@@ -90,8 +89,8 @@ div#DevList ul {
</div>
-<div class="footer">
-<p><br>Copyright 2003&ndash;2017 The NetSurf Developers</p>
+<div class="footer ns-even-fg-subtle">
+<p class="ns-even-fg-faded ns-border">Copyright 2003&ndash;2023 The NetSurf Developers</p>
</div>
</body>
diff --git a/resources/it/licence.html b/resources/it/licence.html
index 8b9c4891f..0de3ffa55 100644
--- a/resources/it/licence.html
+++ b/resources/it/licence.html
@@ -5,23 +5,22 @@
<link rel="stylesheet" type="text/css" href="resource:internal.css">
<style type="text/css">
div.licence {
- background: #ddd;
white-space: pre;
font-family: monospace;
- border: solid 1px black;
+ border-width: 1px;
+ border-style: solid;
margin: 10mm;
padding: 1em 0.5em;
}
dl.components > dt {
- border-bottom: dotted 2px #94adff;
+ border-bottom-width: 1px;
+ border-bottom-style: solid;
}
dl.components > dt > a {
text-decoration: none;
}
dl.components > dd > span {
display: table-cell;
-}
-dl.components > dd > span {
width: 100%;
}
dl.components > dd > span + span {
@@ -30,10 +29,9 @@ dl.components > dd > span + span {
</style>
</head>
-<body>
-<p class="banner"><a href="http://www.netsurf-browser.org/"><img src="resource:netsurf.png" alt="NetSurf"></a></p>
+<body class="ns-even-bg ns-even-fg ns-border">
-<h1>Licenza d'uso</h1>
+<h1 class="ns-border">Licenza d'uso</h1>
<p style="text-align: justify">Il codice sorgente di NetSurf, la sua documentazione, nonchè i file delle traduzioni e le definizioni UI sono rilasciati liberamente secondo i termini della Licenza Pubblica Generica GNU cosi com'è pubblicata dalla Free Software Foundation nella versione 2.0 o successiva, inoltre, come eccezione particolare è possibile collegare il codice sorgente di NetSurf a quello della libreria OpenSSL oppure distribuirli insieme usando una versione modificata della libreria stessa avente però la medesima licenza d'uso.</p>
@@ -41,7 +39,7 @@ dl.components > dd > span + span {
<p style="text-align: justify">Nel caso si desideri modificare il programma è possibile estendere questa eccezione anche alla versione del codice sorgente modificato, tuttavia non è obbligatorio farlo e se non lo si desidera è possibile cancellare questa eccezione dalla propria versione.</p>
-<h2>Licenza d'uso dei vari componenti</h2>
+<h2 class="ns-border">Licenza d'uso dei vari componenti</h2>
<p>Tutte le risorse ArtWork di NetSurf sono rilasciate secondo i termini della licenza MIT.</p>
@@ -50,73 +48,73 @@ dl.components > dd > span + span {
<h3>Componenti del progetto NetSurf</h3>
<dl class="components">
-<dt><a href="http://www.netsurf-browser.org/">NetSurf</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/">NetSurf</a></dt>
<dd>
-<span>&copy; 2002&ndash;2017 The NetSurf Developers</span>
+<span>&copy; 2002&ndash;2020 The NetSurf Developers</span>
<span><a href="#gplv2">GPLv2</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libcss/">LibCSS</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libcss/">LibCSS</a></dt>
<dd>
-<span>&copy; 2007&ndash;2017 John-Mark Bell</span>
+<span>&copy; 2007&ndash;2018 John-Mark Bell</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/hubbub/">Hubbub</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/hubbub/">Hubbub</a></dt>
<dd>
<span>&copy; 2007&ndash;2017 John-Mark Bell<br>&copy; 2008&ndash;2009 Andrew Sidwell</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libparserutils/">LibParserUtils</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libparserutils/">LibParserUtils</a></dt>
<dd>
<span>&copy; 2007&ndash;2017 John-Mark Bell</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/librosprite/">LibROSprite</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/librosprite/">LibROSprite</a></dt>
<dd>
<span>&copy; 2008 James Shaw</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libpencil">Libpencil</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libpencil">Libpencil</a></dt>
<dd>
<span>&copy; 2005&ndash;2006 James Bursa</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/rufl">RUfl</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/rufl">RUfl</a></dt>
<dd>
<span>&copy; 2005&ndash;2009 James Bursa</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libsvgtiny">Libsvgtiny</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libsvgtiny">Libsvgtiny</a></dt>
<dd>
<span>&copy; 2008&ndash;2009 James Bursa</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libnsbmp/">Libnsbmp</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libnsbmp/">Libnsbmp</a></dt>
<dd>
<span>&copy; 2006 Richard Wilson<br>&copy; 2008 Sean Fox</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libnsfb/">Libnsfb</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libnsfb/">Libnsfb</a></dt>
<dd>
<span>&copy; 2009&ndash;2017 Vincent Sanders<br>&copy; 2009&ndash;2017 Michael Drake</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libnsgif/">Libnsgif</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libnsgif/">Libnsgif</a></dt>
<dd>
<span>&copy; 2004 Richard Wilson<br>&copy; 2008 Sean Fox</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libwapcaplet">LibWapcaplet</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libwapcaplet">LibWapcaplet</a></dt>
<dd>
<span>&copy; 2009&ndash;2017 NetSurf Browser Project, Daniel Silverstone</span>
<span><a href="#mit">MIT</a></span>
@@ -126,49 +124,49 @@ dl.components > dd > span + span {
<h3>Componenti di terze parti</h3>
<dl class="components">
-<dt><a href="http://curl.haxx.se/">cURL</a></dt>
+<dt class="ns-border"><a href="https://curl.haxx.se/">cURL</a></dt>
<dd>
-<span>&copy; 1996&ndash;2010 Daniel Stenberg</span>
+<span>&copy; 1996&ndash;2020 Daniel Stenberg</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://libharu.org/">Haru PDF</a></dt>
+<dt class="ns-border"><a href="https://libharu.org/">Haru PDF</a></dt>
<dd>
<span>&copy; 2000&ndash;2008 Takeshi Kanno</span>
<span><a href="#zlib">ZLib</a></span>
</dd>
-<dt><a href="http://www.ijg.org">libjpeg</a></dt>
+<dt class="ns-border"><a href="https://www.ijg.org">libjpeg</a></dt>
<dd>
<span>&copy; 1991&ndash;2010 Thomas G. Lane, Guido Vollbeding</span>
<span><a href="#ijg">IJG</a></span>
</dd>
-<dt><a href="http://www.littlecms.com/">liblcms</a></dt>
+<dt class="ns-border"><a href="https://www.littlecms.com/">liblcms</a></dt>
<dd>
<span>&copy; 1998&ndash;2007 Marti Maria Saguer</span>
<span><a href="#mit">MIT</a></span>
</dd>
-q<dt><a href="http://ro-oslib.sourceforge.net/">OSLib</a></dt>
+q<dt class="ns-border"><a href="https://ro-oslib.sourceforge.net/">OSLib</a></dt>
<dd>
<span>&copy; 1994&ndash;1998 Jonathan Coxhead and contributors</span>
<span><a href="#oslib">OSLib</a></span>
</dd>
-<dt><a href="http://www.openssl.org/">OpenSSL</a></dt>
+<dt class="ns-border"><a href="https://www.openssl.org/">OpenSSL</a></dt>
<dd>
<span>&copy; 1995&ndash;1998 Eric A. Young, Tim J. Hudson<br>&copy; 1998&ndash;2010 The OpenSSL Project</span>
<span><a href="#openssl">OpenSSL</a></span>
</dd>
-<dt><a href="http://www.libpng.org">libpng</a></dt>
+<dt class="ns-border"><a href="https://www.libpng.org">libpng</a></dt>
<dd>
<span>&copy; 2004&ndash;2010 Glenn Randers-Pehrson</span>
<span><a href="#png">PNG</a></span>
</dd>
-<dt><a href="http://www.riscos.info/websvn/listing.php?repname=gccsdk&path=%2Ftrunk%2Fgcc4%2Frecipe%2Ffiles%2Fgcc%2Flibunixlib%2F&#a9586e56e500c7fdfb58279167b82472d">UnixLib</a></dt>
+<dt class="ns-border"><a href="https://www.riscos.info/websvn/listing.php?repname=gccsdk&path=%2Ftrunk%2Fgcc4%2Frecipe%2Ffiles%2Fgcc%2Flibunixlib%2F&#a9586e56e500c7fdfb58279167b82472d">UnixLib</a></dt>
<dd>
<span>&copy; 1995&ndash;1999 Simon Callan, Nick Burrett, Nicholas Clark and
Peter Burwood<br>&copy; 1999&ndash;2009 Nick Burrett, John Tytgat, Peter Naulls,
@@ -177,20 +175,20 @@ Graham Shaw, James Bursa and John-Mark Bell.</span>
<span><a href="#unixlib">UnixLib</a></span>
</dd>
-<dt><a href="http://zlib.net/">ZLib</a></dt>
+<dt class="ns-border"><a href="https://zlib.net/">ZLib</a></dt>
<dd>
<span>&copy; 1995&ndash;2010 Jean-loup Gailly and Mark Adler</span>
<span><a href="#zlib">ZLib</a></span>
</dd>
</dl>
-<h2>Testi delle licenze</h2>
+<h2 class="ns-border">Testi delle licenze</h2>
<p style="text-align: justify">Ove possibile le forme generiche dei vari testi delle licenze sono visualizzate qui. Alcuni componenti possono variare leggermente la licenza d'uso, tuttavia nei casi in cui abbiamo apportato delle modifiche il nostro sforzo è stato quello di rispettare il più fedelmente possibile (ed in accordo ad essa) la licenza originale, in questo caso le piccole variazioni alla licenza sono elencate qui, eventuali altre variazioni minori come ad esempio gli spazi bianchi non sono considerati.</p>
<a name="gplv2" />
<h3>GNU General Public Licence, Versione 2</h3>
-<div class="licence"> GNU GENERAL PUBLIC LICENSE
+<div class="licence ns-border ns-odd-bg"> GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
@@ -533,7 +531,7 @@ Public License instead of this License.
<a name="mit" />
<h3>Licenza MIT/X</h3>
-<div class="licence">Permission is hereby granted, free of charge, to any person obtaining a copy
+<div class="licence ns-border ns-odd-bg">Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
@@ -554,7 +552,7 @@ THE SOFTWARE.
<a name="zlib" />
<h3>Licenza ZLib</h3>
-<div class="licence"> This software is provided 'as-is', without any express or implied
+<div class="licence ns-border ns-odd-bg"> This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
@@ -573,7 +571,7 @@ THE SOFTWARE.
<a name="ijg" />
<h3>Licenza IJG</h3>
-<div class="licence">The authors make NO WARRANTY or representation, either express or implied,
+<div class="licence ns-border ns-odd-bg">The authors make NO WARRANTY or representation, either express or implied,
with respect to this software, its quality, accuracy, merchantability, or
fitness for a particular purpose. This software is provided "AS IS", and you,
its user, assume the entire risk as to its quality and accuracy.
@@ -627,7 +625,7 @@ but is also freely distributable.
<a name="oslib" />
<h3>Licenza OSLib</h3>
-<div class="licence">The copyright holder has granted a small relaxation of the
+<div class="licence ns-border ns-odd-bg">The copyright holder has granted a small relaxation of the
conditions of the GNU Public Licence, in that OSLib is itself
free software, but applications linked to it need not be.
This means that any changes to OSLib itself (the contents of
@@ -887,7 +885,7 @@ That's all there is to it!
<a name="openssl" />
<h3>Licenza OpenSSL</h3>
-<div class="licence"> The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
+<div class="licence ns-border ns-odd-bg"> The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
the OpenSSL License and the original SSLeay license apply to the toolkit.
See below for the actual license texts. Actually both licenses are BSD-style
Open Source licenses. In case of any license issues related to OpenSSL
@@ -1013,7 +1011,7 @@ That's all there is to it!
<a name="png" />
<h3>Licenza PNG</h3>
-<div class="licence"> * This code is released under the libpng license.
+<div class="licence ns-border ns-odd-bg"> * This code is released under the libpng license.
*
* libpng versions 1.2.6, August 15, 2004, through 1.4.1, February 25, 2010, are
* Copyright (c) 2004, 2006-2010 Glenn Randers-Pehrson, and are
@@ -1103,7 +1101,7 @@ That's all there is to it!
<a name="unixlib" />
<h3>Licenza UnixLib</h3>
-<div class="licence">In January 2005, permission was obtained from all relevant contributors
+<div class="licence ns-border ns-odd-bg">In January 2005, permission was obtained from all relevant contributors
by Peter Naulls to license all past and present contributions to UnixLib
(where possible) under the revised BSD license. The license is included
in the next section and is applicable to all code in UnixLib that does not
@@ -1852,8 +1850,8 @@ ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
</div>
-<div class="footer">
-<p>Copyright 2003&ndash;2017 The NetSurf Developers</p>
+<div class="footer ns-even-fg-subtle">
+<p class="ns-even-fg-faded ns-border">Copyright 2003&ndash;2019 The NetSurf Developers</p>
</div>
</body>
diff --git a/resources/it/welcome.html b/resources/it/welcome.html
index f936fe3a6..98bb3a0ae 100644
--- a/resources/it/welcome.html
+++ b/resources/it/welcome.html
@@ -6,13 +6,13 @@
</head>
<body>
-<h1 class="banner"><a href="http://www.netsurf-browser.org/"><img src="about:logo" alt="NetSurf"></a></h1>
+<h1 class="banner"><a href="https://www.netsurf-browser.org/"><img src="about:logo" alt="NetSurf"></a></h1>
<ul class="nslinks">
-<li><a href="http://www.netsurf-browser.org/">Pagina principale</a></li>
-<li><a href="http://www.netsurf-browser.org/documentation/">Documentazione</a></li>
-<li><a href="http://www.netsurf-browser.org/downloads/">Scarica NetSurf</a></li>
-<li><a href="http://www.netsurf-browser.org/contact/">Contatta gli sviluppatori</a></li>
+<li><a href="https://www.netsurf-browser.org/">Pagina principale</a></li>
+<li><a href="https://www.netsurf-browser.org/documentation/">Documentazione</a></li>
+<li><a href="https://www.netsurf-browser.org/downloads/">Scarica NetSurf</a></li>
+<li><a href="https://www.netsurf-browser.org/contact/">Contatta gli sviluppatori</a></li>
</ul>
<div class="onlycontent">
@@ -20,7 +20,7 @@
<p class="intro">NetSurf è la nostra idea di browser, per questo abbiamo scelto di renderlo veloce e sicuro ed ogni giorno lavoriamo per renderlo migliore, se hai qualche suggerimento o semplicemente hai bisogno di aiuto contattaci!<br><br> Grazie per aver scelto NetSurf!</p>
-<form method="get" action="http://www.google.it/search">
+<form method="get" action="https://www.google.it/search">
<div class="websearch">
<input type="text" name="q" size="42" maxlength="255">
<input type="submit" value="Ricerca Google" name="btnG">
@@ -29,29 +29,29 @@
<div class="links">
<ul>
-<li><a href="http://news.bbc.co.uk/">BBC News</a></li>
-<li><a href="http://www.reuters.com/news">Reuters</a></li>
-<li><a href="http://www.cnn.com/">CNN</a></li>
+<li><a href="https://news.bbc.co.uk/">BBC News</a></li>
+<li><a href="https://www.reuters.com/news">Reuters</a></li>
+<li><a href="https://www.cnn.com/">CNN</a></li>
</ul>
<ul>
-<li><a href="http://slashdot.org/">Slashdot</a></li>
-<li><a href="http://arstechnica.com/">Ars Technica</a></li>
-<li><a href="http://www.theregister.co.uk/">The Register</a></li>
-<li><a href="http://www.w3.org/">W3C</a></li>
+<li><a href="https://slashdot.org/">Slashdot</a></li>
+<li><a href="https://arstechnica.com/">Ars Technica</a></li>
+<li><a href="https://www.theregister.co.uk/">The Register</a></li>
+<li><a href="https://www.w3.org/">W3C</a></li>
</ul>
<ul>
-<li><a href="http://en.wikipedia.org/wiki/Main_Page">Wikipedia</a></li>
-<li><a href="http://google.it/">Google</a></li>
-<li><a href="http://yahoo.co.uk/">Yahoo!</a></li>
-<li><a href="http://www.imdb.com/">IMDB</a></li>
+<li><a href="https://en.wikipedia.org/wiki/Main_Page">Wikipedia</a></li>
+<li><a href="https://google.it/">Google</a></li>
+<li><a href="https://yahoo.co.uk/">Yahoo!</a></li>
+<li><a href="https://www.imdb.com/">IMDB</a></li>
</ul>
<ul>
-<li><a href="http://www.iconbar.com/">The Icon Bar</a></li>
-<li><a href="http://www.riscosopen.org/">ROOL</a></li>
-<li><a href="http://www.riscos.info/">riscos.info</a></li>
+<li><a href="https://www.iconbar.com/">The Icon Bar</a></li>
+<li><a href="https://www.riscosopen.org/">ROOL</a></li>
+<li><a href="https://www.riscos.info/">riscos.info</a></li>
</ul>
</div>
diff --git a/resources/ja/welcome.html b/resources/ja/welcome.html
index ce7b36343..6f6cf97f3 100644
--- a/resources/ja/welcome.html
+++ b/resources/ja/welcome.html
@@ -7,13 +7,13 @@
</head>
<body>
-<h1 class="banner"><a href="http://www.netsurf-browser.org/"><img src="about:logo" alt="NetSurf"></a></h1>
+<h1 class="banner"><a href="https://www.netsurf-browser.org/"><img src="about:logo" alt="NetSurf"></a></h1>
<ul class="nslinks">
-<li><a href="http://www.netsurf-browser.org/">NetSurfウェブサイト</a></li>
-<li><a href="http://www.netsurf-browser.org/documentation/">ドキュメンテーション</a></li>
-<li><a href="http://www.netsurf-browser.org/downloads/">最新ã®NetSurfをダウンロード</a></li>
-<li><a href="http://www.netsurf-browser.org/contact/">開発者ã¨ã‚³ãƒ³ã‚¿ã‚¯ãƒˆ</a></li>
+<li><a href="https://www.netsurf-browser.org/">NetSurfウェブサイト</a></li>
+<li><a href="https://www.netsurf-browser.org/documentation/">ドキュメンテーション</a></li>
+<li><a href="https://www.netsurf-browser.org/downloads/">最新ã®NetSurfをダウンロード</a></li>
+<li><a href="https://www.netsurf-browser.org/contact/">開発者ã¨ã‚³ãƒ³ã‚¿ã‚¯ãƒˆ</a></li>
</ul>
<div class="onlycontent">
@@ -21,7 +21,7 @@
<p class="intro">NetSurfã¯å°ã•ãã¦é€Ÿã„オープンソースã®ã‚¦ã‚§ãƒ–ブラウザã§ã™ã€‚ç§ãŸã¡ã¯ã„ã¤ã‚‚ã“ã®ãƒ–ラウザを改良ã™ã‚‹æ°—満々ã§ã™ã‹ã‚‰ã€ã©ã‚“ãªå•é¡Œã§ã‚‚声をã‹ã‘ã¦ãã ã•ã„。NetSurfã‚’é¸ã‚“ã§ãã‚Œã¦ã‚ã‚ŠãŒã¨ã†ï¼</p>
-<form method="get" action="http://www.google.co.jp/search">
+<form method="get" action="https://www.google.co.jp/search">
<div class="websearch">
<input type="text" name="q" size="42" maxlength="255">
<input type="submit" value="Google検索" name="btnG">
@@ -30,29 +30,29 @@
<div class="links">
<ul>
-<li><a href="http://news.bbc.co.uk/">BBC News</a></li>
-<li><a href="http://www.reuters.com/news">Reuters</a></li>
-<li><a href="http://www.cnn.com/">CNN</a></li>
+<li><a href="https://news.bbc.co.uk/">BBC News</a></li>
+<li><a href="https://www.reuters.com/news">Reuters</a></li>
+<li><a href="https://www.cnn.com/">CNN</a></li>
</ul>
<ul>
-<li><a href="http://slashdot.jp/">Slashdot</a></li>
-<li><a href="http://arstechnica.com/">Ars Technica</a></li>
-<li><a href="http://www.theregister.co.uk/">The Register</a></li>
-<li><a href="http://www.w3.org/">W3C</a></li>
+<li><a href="https://slashdot.jp/">Slashdot</a></li>
+<li><a href="https://arstechnica.com/">Ars Technica</a></li>
+<li><a href="https://www.theregister.co.uk/">The Register</a></li>
+<li><a href="https://www.w3.org/">W3C</a></li>
</ul>
<ul>
-<li><a href="http://ja.wikipedia.org/wiki/Main_Page">Wikipedia</a></li>
-<li><a href="http://google.co.jp/">Google</a></li>
-<li><a href="http://yahoo.co.jp/">Yahoo!</a></li>
-<li><a href="http://www.imdb.com/">IMDB</a></li>
+<li><a href="https://ja.wikipedia.org/wiki/Main_Page">Wikipedia</a></li>
+<li><a href="https://google.co.jp/">Google</a></li>
+<li><a href="https://yahoo.co.jp/">Yahoo!</a></li>
+<li><a href="https://www.imdb.com/">IMDB</a></li>
</ul>
<ul>
-<li><a href="http://www.iconbar.com/">The Icon Bar</a></li>
-<li><a href="http://www.riscosopen.org/">ROOL</a></li>
-<li><a href="http://www.riscos.info/">riscos.info</a></li>
+<li><a href="https://www.iconbar.com/">The Icon Bar</a></li>
+<li><a href="https://www.riscosopen.org/">ROOL</a></li>
+<li><a href="https://www.riscos.info/">riscos.info</a></li>
</ul>
</div>
diff --git a/resources/nl/credits.html b/resources/nl/credits.html
index f9e0932c5..0bd3f02ea 100644
--- a/resources/nl/credits.html
+++ b/resources/nl/credits.html
@@ -13,16 +13,15 @@ div#DevList ul {
</style>
</head>
-<body>
-<p class="banner"><a href="http://www.netsurf-browser.org/"><img src="resource:netsurf.png" alt="NetSurf"></a></p>
+<body class="ns-even-bg ns-even-fg ns-border">
-<h1>NetSurf-bijdragen</h1>
+<h1 class="ns-border">NetSurf-bijdragen</h1>
<p>NetSurf kwam tot stand door bijdragen van de volgende personen:</p>
<div id="DevList">
-<h2>Code</h2>
+<h2 class="ns-border">Code</h2>
<ul>
<li>Kevin Bagust</li>
<li>John-Mark Bell</li>
@@ -60,7 +59,7 @@ div#DevList ul {
<li>Chris Young</li>
</ul>
-<h2>Documentatie</h2>
+<h2 class="ns-border">Documentatie</h2>
<ul>
<li>John-Mark Bell</li>
<li>James Bursa</li>
@@ -70,7 +69,7 @@ div#DevList ul {
<li>Richard Wilson</li>
</ul>
-<h2>Afbeeldingen</h2>
+<h2 class="ns-border">Afbeeldingen</h2>
<ul>
<li>Michael Drake</li>
<li>Andrew Duffell</li>
@@ -79,7 +78,7 @@ div#DevList ul {
<li>Phil Mellor</li>
</ul>
-<h2>Vertalingen</h2>
+<h2 class="ns-border">Vertalingen</h2>
<ul>
<li>Sebastian Barthel</li>
<li>Bruno D'Arcangeli</li>
@@ -95,8 +94,8 @@ div#DevList ul {
</ul>
</div>
-<div class="footer">
-<p>Auteursrecht 2003&ndash;2017 De NetSurf-ontwikkelaars</p>
+<div class="footer ns-even-fg-subtle">
+<p class="ns-border">Auteursrecht 2003&ndash;2023 De NetSurf-ontwikkelaars</p>
</div>
</body>
diff --git a/resources/nl/licence.html b/resources/nl/licence.html
index 89ce8564e..f30ce1440 100644
--- a/resources/nl/licence.html
+++ b/resources/nl/licence.html
@@ -6,23 +6,22 @@
<link rel="stylesheet" type="text/css" href="resource:internal.css">
<style>
div.licence {
- background: #ddd;
white-space: pre;
font-family: monospace;
- border: solid 1px black;
+ border-width: 1px;
+ border-style: solid;
margin: 10mm;
padding: 1em 0.5em;
}
dl.components > dt {
- border-bottom: dotted 2px #94adff;
+ border-bottom-width: 1px;
+ border-bottom-style: solid;
}
dl.components > dt > a {
text-decoration: none;
}
dl.components > dd > span {
display: table-cell;
-}
-dl.components > dd > span {
width: 100%;
}
dl.components > dd > span + span {
@@ -31,10 +30,9 @@ dl.components > dd > span + span {
</style>
</head>
-<body>
-<p class="banner"><a href="http://www.netsurf-browser.org/"><img src="resource:netsurf.png" alt="NetSurf"></a></p>
+<body class="ns-even-bg ns-even-fg ns-border">
-<h1>NetSurf-gebruikerslicentie</h1>
+<h1 class="ns-border">NetSurf-gebruikerslicentie</h1>
<p>De broncode van NetSurf, de documentatie, evenals de verschillende
vertalingen, bijbehorende bestanden en de gebruikersinterface-definities zijn
@@ -52,7 +50,7 @@ wijzigen, mag u deze uitzondering ook opnemen in uw versie van de gewijzigde
broncode. Dit is echter niet verplicht om te doen en als u dat ook niet wenst
dan verwijder deze uitzonderingverklaring uit uw eigen versie.</p>
-<h2>Gebruikerslicenties van de verschillende componenten</h2>
+<h2 class="ns-border">Gebruikerslicenties van de verschillende componenten</h2>
<p>De grafische vormgeving van NetSurf, inclusief de bijbehorende bronbestanden, vallen onder de MIT-licentie.</p>
@@ -61,75 +59,75 @@ dan verwijder deze uitzonderingverklaring uit uw eigen versie.</p>
<h3>Onderdelen van het NetSurf-project</h3>
<dl class="components">
-<dt><a href="http://www.netsurf-browser.org/">NetSurf</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/">NetSurf</a></dt>
<dd>
-<span>&copy; 2002&ndash;2017 De NetSurf-ontwikkerlaars</span>
+<span>&copy; 2002&ndash;2020 De NetSurf-ontwikkerlaars</span>
<span><a href="#gplv2">GPLv2</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libcss/">LibCSS</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libcss/">LibCSS</a></dt>
<dd>
-<span>&copy; 2007&ndash;2017 John-Mark Bell</span>
+<span>&copy; 2007&ndash;2023 John-Mark Bell</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/hubbub/">Hubbub</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/hubbub/">Hubbub</a></dt>
<dd>
-<span>&copy; 2007&ndash;2017 John-Mark Bell<br>&copy; 2008&ndash;2009 Andrew Sidwell</span>
+<span>&copy; 2007&ndash;2023 John-Mark Bell<br>&copy; 2008&ndash;2009 Andrew Sidwell</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libparserutils/">LibParserUtils</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libparserutils/">LibParserUtils</a></dt>
<dd>
-<span>&copy; 2007&ndash;2017 John-Mark Bell</span>
+<span>&copy; 2007&ndash;2023 John-Mark Bell</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/librosprite/">LibROSprite</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/librosprite/">LibROSprite</a></dt>
<dd>
<span>&copy; 2008 James Shaw</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libpencil">Libpencil</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libpencil">Libpencil</a></dt>
<dd>
<span>&copy; 2005&ndash;2006 James Bursa</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/rufl">RUfl</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/rufl">RUfl</a></dt>
<dd>
<span>&copy; 2005&ndash;2009 James Bursa</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libsvgtiny">Libsvgtiny</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libsvgtiny">Libsvgtiny</a></dt>
<dd>
-<span>&copy; 2008&ndash;2009 James Bursa<br>&copy; 2016 Michael Drake</span>
+<span>&copy; 2008&ndash;2009 James Bursa<br>&copy; 2016&ndash;2023 Michael Drake</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libnsbmp/">Libnsbmp</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libnsbmp/">Libnsbmp</a></dt>
<dd>
-<span>&copy; 2006 Richard Wilson<br>&copy; 2008 Sean Fox<br>&copy; 2016 Vincent Sanders</span>
+<span>&copy; 2006 Richard Wilson<br>&copy; 2008 Sean Fox<br>&copy; 2016&ndash;2023 Vincent Sanders</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libnsfb/">Libnsfb</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libnsfb/">Libnsfb</a></dt>
<dd>
-<span>&copy; 2009&ndash;2017 Vincent Sanders<br>&copy; 2009&ndash;2017 Michael Drake</span>
+<span>&copy; 2009&ndash;2017 Vincent Sanders<br>&copy; 2009&ndash;2023 Michael Drake</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libnsgif/">Libnsgif</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libnsgif/">Libnsgif</a></dt>
<dd>
<span>&copy; 2004 Richard Wilson</br>&copy; 2008 Sean Fox</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://www.netsurf-browser.org/projects/libwapcaplet">LibWapcaplet</a></dt>
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libwapcaplet">LibWapcaplet</a></dt>
<dd>
-<span>&copy; 2009&ndash;2017 NetSurf Browser Project, Daniel Silverstone</span>
+<span>&copy; 2009&ndash;2023 NetSurf Browser Project, Daniel Silverstone</span>
<span><a href="#mit">MIT</a></span>
</dd>
</dl>
@@ -138,49 +136,49 @@ dan verwijder deze uitzonderingverklaring uit uw eigen versie.</p>
<h3>Onderdelen van derden</h3>
<dl class="components">
-<dt><a href="http://curl.haxx.se/">cURL</a></dt>
+<dt class="ns-border"><a href="https://curl.haxx.se/">cURL</a></dt>
<dd>
-<span>&copy; 1996&ndash;2010 Daniel Stenberg</span>
+<span>&copy; 1996&ndash;2020 Daniel Stenberg</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://libharu.org/">Haru PDF</a></dt>
+<dt class="ns-border"><a href="https://libharu.org/">Haru PDF</a></dt>
<dd>
<span>&copy; 2000&ndash;2008 Takeshi Kanno</span>
<span><a href="#zlib">ZLib</a></span>
</dd>
-<dt><a href="http://www.ijg.org">libjpeg</a></dt>
+<dt class="ns-border"><a href="https://www.ijg.org">libjpeg</a></dt>
<dd>
<span>&copy; 1991&ndash;2010 Thomas G. Lane, Guido Vollbeding</span>
<span><a href="#ijg">IJG</a></span>
</dd>
-<dt><a href="http://www.littlecms.com/">liblcms</a></dt>
+<dt class="ns-border"><a href="https://www.littlecms.com/">liblcms</a></dt>
<dd>
<span>&copy; 1998&ndash;2007 Marti Maria Saguer</span>
<span><a href="#mit">MIT</a></span>
</dd>
-<dt><a href="http://ro-oslib.sourceforge.net/">OSLib</a></dt>
+<dt class="ns-border"><a href="https://ro-oslib.sourceforge.net/">OSLib</a></dt>
<dd>
<span>&copy; 1994&ndash;1998 Jonathan Coxhead and contributors</span>
<span><a href="#oslib">OSLib</a></span>
</dd>
-<dt><a href="http://www.openssl.org/">OpenSSL</a></dt>
+<dt class="ns-border"><a href="https://www.openssl.org/">OpenSSL</a></dt>
<dd>
<span>&copy; 1995&ndash;1998 Eric A. Young, Tim J. Hudson<br>&copy; 1998&ndash;2010 The OpenSSL Project</span>
<span><a href="#openssl">OpenSSL</a></span>
</dd>
-<dt><a href="http://www.libpng.org">libpng</a></dt>
+<dt class="ns-border"><a href="https://www.libpng.org">libpng</a></dt>
<dd>
<span>&copy; 2004&ndash;2010 Glenn Randers-Pehrson</span>
<span><a href="#png">PNG</a></span>
</dd>
-<dt><a href="http://www.riscos.info/websvn/listing.php?repname=gccsdk&path=%2Ftrunk%2Fgcc4%2Frecipe%2Ffiles%2Fgcc%2Flibunixlib%2F&#a9586e56e500c7fdfb58279167b82472d">UnixLib</a></dt>
+<dt class="ns-border"><a href="https://www.riscos.info/websvn/listing.php?repname=gccsdk&path=%2Ftrunk%2Fgcc4%2Frecipe%2Ffiles%2Fgcc%2Flibunixlib%2F&#a9586e56e500c7fdfb58279167b82472d">UnixLib</a></dt>
<dd>
<span>&copy; 1995&ndash;1999 Simon Callan, Nick Burrett, Nicholas Clark and
Peter Burwood<br>&copy; 1999&ndash;2009 Nick Burrett, John Tytgat, Peter Naulls,
@@ -189,14 +187,14 @@ Graham Shaw, James Bursa and John-Mark Bell.</span>
<span><a href="#unixlib">UnixLib</a></span>
</dd>
-<dt><a href="http://zlib.net/">ZLib</a></dt>
+<dt class="ns-border"><a href="https://zlib.net/">ZLib</a></dt>
<dd>
<span>&copy; 1995&ndash;2010 Jean-loup Gailly and Mark Adler</span>
<span><a href="#zlib">ZLib</a></span>
</dd>
</dl>
-<h2>Licentieteksten</h2>
+<h2 class="ns-border">Licentieteksten</h2>
<p>Waar mogelijk zijn hieronder de algemeen geldende licentieteksten van de
verschillende NetSurf-onderdelen opgenomen. Bij sommige onderdelen kan de
@@ -208,7 +206,7 @@ genomen.</p>
<a name="gplv2" />
<h3>GNU General Public Licence, Versie 2 (Engels)</h3>
-<div class="licence"> GNU GENERAL PUBLIC LICENSE
+<div class="licence ns-border ns-odd-bg"> GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
@@ -551,7 +549,7 @@ Public License instead of this License.
<a name="mit" />
<h3>MIT/X-licentie (Engels)</h3>
-<div class="licence">Permission is hereby granted, free of charge, to any person obtaining a copy
+<div class="licence ns-border ns-odd-bg">Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
@@ -572,7 +570,7 @@ THE SOFTWARE.
<a name="zlib" />
<h3>ZLib-licentie (Engels)</h3>
-<div class="licence"> This software is provided 'as-is', without any express or implied
+<div class="licence ns-border ns-odd-bg"> This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
@@ -591,7 +589,7 @@ THE SOFTWARE.
<a name="ijg" />
<h3>IJG-licentie (Engels)</h3>
-<div class="licence">The authors make NO WARRANTY or representation, either express or implied,
+<div class="licence ns-border ns-odd-bg">The authors make NO WARRANTY or representation, either express or implied,
with respect to this software, its quality, accuracy, merchantability, or
fitness for a particular purpose. This software is provided "AS IS", and you,
its user, assume the entire risk as to its quality and accuracy.
@@ -646,7 +644,7 @@ but is also freely distributable.
<a name="oslib" />
<h3>OSLib-licentie (Engels)</h3>
-<div class="licence">The copyright holder has granted a small relaxation of the
+<div class="licence ns-border ns-odd-bg">The copyright holder has granted a small relaxation of the
conditions of the GNU Public Licence, in that OSLib is itself
free software, but applications linked to it need not be.
This means that any changes to OSLib itself (the contents of
@@ -906,7 +904,7 @@ That's all there is to it!
<a name="openssl" />
<h3>OpenSSL-licentie (Engels)</h3>
-<div class="licence"> The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
+<div class="licence ns-border ns-odd-bg"> The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
the OpenSSL License and the original SSLeay license apply to the toolkit.
See below for the actual license texts. Actually both licenses are BSD-style
Open Source licenses. In case of any license issues related to OpenSSL
@@ -1032,7 +1030,7 @@ That's all there is to it!
<a name="png" />
<h3>PNG-licentie (Engels)</h3>
-<div class="licence"> * This code is released under the libpng license.
+<div class="licence ns-border ns-odd-bg"> * This code is released under the libpng license.
*
* libpng versions 1.2.6, August 15, 2004, through 1.4.1, February 25, 2010, are
* Copyright (c) 2004, 2006-2010 Glenn Randers-Pehrson, and are
@@ -1122,7 +1120,7 @@ That's all there is to it!
<a name="unixlib" />
<h3>UnixLib-licenctie (Engels)</h3>
-<div class="licence">In January 2005, permission was obtained from all relevant contributors
+<div class="licence ns-border ns-odd-bg">In January 2005, permission was obtained from all relevant contributors
by Peter Naulls to license all past and present contributions to UnixLib
(where possible) under the revised BSD license. The license is included
in the next section and is applicable to all code in UnixLib that does not
@@ -1871,8 +1869,8 @@ ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
</div>
-<div class="footer">
-<p>Auteursrecht 2003&ndash;2017 De NetSurf-ontwikkelaars</p>
+<div class="footer ns-even-fg-subtle">
+<p class="ns-even-fg-faded ns-border">Auteursrecht 2003&ndash;2019 De NetSurf-ontwikkelaars</p>
</div>
</body>
diff --git a/resources/nl/welcome.html b/resources/nl/welcome.html
index aec47e74e..e138fb7bb 100644
--- a/resources/nl/welcome.html
+++ b/resources/nl/welcome.html
@@ -6,13 +6,13 @@
</head>
<body>
-<h1 class="banner"><a href="http://www.netsurf-browser.org/"><img src="about:logo" alt="NetSurf"></a></h1>
+<h1 class="banner"><a href="https://www.netsurf-browser.org/"><img src="about:logo" alt="NetSurf"></a></h1>
<ul class="nslinks">
-<li><a href="http://www.netsurf-browser.org/"><strong>NetSurf-website</strong> </a> (Engels)</li>
-<li><a href="http://www.netsurf-browser.org/documentation/">Engelstalige documentatie</a></li>
-<li>Nieuwste <a href="http://www.netsurf-browser.org/downloads/"><strong>NetSurf-versie</strong></a> ophalen</li>
-<li>Schrijf de <a href="http://www.netsurf-browser.org/contact/"><strong>ontwikkelaars</strong> </a> (Engels)</li>
+<li><a href="https://www.netsurf-browser.org/"><strong>NetSurf-website</strong> </a> (Engels)</li>
+<li><a href="https://www.netsurf-browser.org/documentation/">Engelstalige documentatie</a></li>
+<li>Nieuwste <a href="https://www.netsurf-browser.org/downloads/"><strong>NetSurf-versie</strong></a> ophalen</li>
+<li>Schrijf de <a href="https://www.netsurf-browser.org/contact/"><strong>ontwikkelaars</strong> </a> (Engels)</li>
<li>Schrijf de <a href="mailto:g.vankatwijk@freeler.nl">vertalers</a>
</ul>
@@ -21,7 +21,7 @@
<p class="intro">NetSurf is een kleine, snelle webbrowser met open broncode. Wij willen altijd onze browser nog beter maken. Neem dus contact op met de ontwikkelaars (in het Engels!) of met de vertalers (gewoon in het Nederlands) mocht je verbeteringsvoorstellen hebben en/of problemen ervaren. Bedankt dat je voor NetSurf hebt gekozen.</p>
-<form method="get" action="http://www.ixquick.nl/do/search/">
+<form method="get" action="https://www.ixquick.nl/do/search/">
<div class="websearch">
<input type="text" name="q" size="42" maxlength="255">
<input type="submit" value="Zoeken" name="btnG">
@@ -32,36 +32,36 @@
<p><h3>Nieuws</h3>
<ul>
-<li><a href="http://nos.nl/nieuws/">NOS nieuws</a></li>
-<li><a href="http://teletekst-data.nos.nl/webplus?p=100">NOS teletekst</a></li>
-<li><a href="http://www.nu.nl">NU.nl</a></li>
-<li><a href="http://news.bbc.co.uk/">BBC news</a></li>
-<li><a href="http://www.cnn.com/">CNN</a></li>
+<li><a href="https://nos.nl/nieuws/">NOS nieuws</a></li>
+<li><a href="https://teletekst-data.nos.nl/webplus?p=100">NOS teletekst</a></li>
+<li><a href="https://www.nu.nl">NU.nl</a></li>
+<li><a href="https://news.bbc.co.uk/">BBC news</a></li>
+<li><a href="https://www.cnn.com/">CNN</a></li>
</ul></p>
<p><h3>RISC OS</h3>
<ul>
-<li><a href="http://www.bigbenclub.nl/">Big Ben Club</a></li>
-<li><a href="http://www.iconbar.com/">Icon Bar</a></li>
+<li><a href="https://www.bigbenclub.nl/">Big Ben Club</a></li>
+<li><a href="https://www.iconbar.com/">Icon Bar</a></li>
<li><a href="http://riscos.be">RISCOS.be</a>
-<li><a href="http://www.riscos.info/">riscos.info</a></li>
-<li><a href="http://www.riscosopen.org/">ROOL</a></li>
+<li><a href="https://www.riscos.info/">riscos.info</a></li>
+<li><a href="https://www.riscosopen.org/">ROOL</a></li>
</ul></p>
<p><h3>Techniek</h3>
<ul>
-<li><a href="http://arstechnica.com/">Ars Technica</a></li>
-<li><a href="http://slashdot.org/">Slashdot</a></li>
-<li><a href="http://www.theregister.co.uk/">The Register</a></li>
-<li><a href="http://tweakers.net">Tweakers</a></li>
-<li><a href="http://www.w3.org/">W3C</a></li>
+<li><a href="https://arstechnica.com/">Ars Technica</a></li>
+<li><a href="https://slashdot.org/">Slashdot</a></li>
+<li><a href="https://www.theregister.co.uk/">The Register</a></li>
+<li><a href="https://tweakers.net">Tweakers</a></li>
+<li><a href="https://www.w3.org/">W3C</a></li>
</ul></p>
<p><h3>Zoeken</h3>
<ul>
-<li><a href="http://google.nl/">Google</a></li>
-<li><a href="http://www.imdb.com/">IMDB</a></li>
-<li><a href="http://nl.wikipedia.org/wiki/Main_Page">Wikipedia</a></li>
+<li><a href="https://google.nl/">Google</a></li>
+<li><a href="https://www.imdb.com/">IMDB</a></li>
+<li><a href="https://nl.wikipedia.org/wiki/Main_Page">Wikipedia</a></li>
</ul></p>
</div>
diff --git a/resources/zh_CN/credits.html b/resources/zh_CN/credits.html
new file mode 100644
index 000000000..aa669f417
--- /dev/null
+++ b/resources/zh_CN/credits.html
@@ -0,0 +1,98 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>NetSurf | 关于制作人员åå•</title>
+<link rel="stylesheet" type="text/css" href="resource:internal.css">
+<style>
+div#DevList li {
+ float: left;
+ width: 18em; }
+div#DevList ul {
+ overflow: hidden; }
+</style>
+</head>
+
+<body class="ns-even-bg ns-even-fg ns-border">
+
+<h1 class="ns-border">NetSurf 制作人员åå•</h1>
+
+<p>NetSurf 是由以下人员制作的:</p>
+
+<div id="DevList">
+
+<h2 class="ns-border">代ç </h2>
+<ul>
+<li>John-Mark Bell</li>
+<li>Michael Drake</li>
+<li>Rob Kendrick</li>
+<li>François Revol</li>
+<li>Vincent Sanders</li>
+<li>Daniel Silverstone</li>
+<li>Chris Young</li>
+<li>Kevin Bagust</li>
+<li>Mark Benjamin</li>
+<li>Adam Blokus</li>
+<li>Pawe&#x0142 Blokus</li>
+<li>James Bursa</li>
+<li>Stefaan Claes</li>
+<li>Calin Dobos</li>
+<li>Sean Fox</li>
+<li>Stephen Fryatt</li>
+<li>Rik Griffin</li>
+<li>Matthew Hambley</li>
+<li>Rob Jackson</li>
+<li>Jeffrey Lee</li>
+<li>Adrian Lees</li>
+<li>Michael Lester</li>
+<li>Ole Loots</li>
+<li>Phil Mellor</li>
+<li>Philip Pemberton</li>
+<li>Darren Salt</li>
+<li>James Shaw</li>
+<li>Andrew Sidwell</li>
+<li>Andrew Timmins</li>
+<li>John Tytgat</li>
+<li>Sven Weidauer</li>
+<li>Chris Williams</li>
+<li>Richard Wilson</li>
+<li>Bo Yang</li>
+</ul>
+
+<h2 class="ns-border">文档</h2>
+<ul>
+<li>John-Mark Bell</li>
+<li>James Bursa</li>
+<li>Michael Drake</li>
+<li>Rob Kendrick</li>
+<li>James Shaw</li>
+<li>Richard Wilson</li>
+</ul>
+
+<h2 class="ns-border">图åƒ</h2>
+<ul>
+<li>Michael Drake</li>
+<li>Andrew Duffell</li>
+<li>John Duffell</li>
+<li>Richard Hallas</li>
+<li>Phil Mellor</li>
+</ul>
+
+<h2 class="ns-border">翻译</h2>
+<ul>
+<li>Sebastian Barthel</li>
+<li>Bruno D'Arcangeli</li>
+<li>Samir Hawamdeh</li>
+<li>Gerard van Katwijk</li>
+<li>Jérôme Mathevet</li>
+<li>Simon Voortman</li>
+</ul>
+
+</div>
+
+<div class="footer">
+<p class="ns-even-fg-faded ns-border">Copyright 2003&ndash;2023 NetSurf å¼€å‘人员</p>
+</div>
+
+</body>
+</html>
diff --git a/resources/zh_CN/licence.html b/resources/zh_CN/licence.html
new file mode 100644
index 000000000..2d7a29f4a
--- /dev/null
+++ b/resources/zh_CN/licence.html
@@ -0,0 +1,1869 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>NetSurf | 关于许å¯è¯</title>
+<link rel="stylesheet" type="text/css" href="resource:internal.css">
+<style>
+div.licence {
+ white-space: pre;
+ font-family: monospace;
+ border-width: 1px;
+ border-style: solid;
+ margin: 10mm;
+ padding: 1em 0.5em;
+}
+dl.components > dt {
+ border-bottom-width: 1px;
+ border-bottom-style: solid;
+}
+dl.components > dt > a {
+ text-decoration: none;
+}
+dl.components > dd > span {
+ display: table-cell;
+ width: 100%;
+}
+dl.components > dd > span + span {
+ width: auto;
+}
+</style>
+</head>
+
+<body class="ns-even-bg ns-even-fg ns-border">
+
+<h1 class="ns-border">NetSurf 许å¯è¯</h1>
+
+<p>NetSurf, the source code, documentation, translatable messages files and UI
+definitions are licensed under the GNU General Public Licence, version 2.0. In
+addition, as a special exception, permission is granted to link the code of this
+release of NetSurf with the OpenSSL project's "OpenSSL" library (or with
+modified versions of it that use the same licence as the "OpenSSL" library),
+and distribute the linked executables.</p>
+
+<p>You must obey the GNU General Public License version 2 in all respects for
+all of the code used other than "OpenSSL". If you modify the code, you may
+extend this exception to your version of the code, but you are not obligated to
+do so. If you do not wish to do so, delete this exception statement from your
+version.</p>
+
+<h2 class="ns-border">组件许å¯è¯</h2>
+
+<p>NetSurf 的艺术作å“资æºæ˜¯æ ¹æ® MIT 的许å¯è¯æŽˆæƒçš„。</p>
+
+<p>NetSurf 还å¯ä»¥åŒ…å«ä»¥ä¸‹å…¶ä»–组件。</p>
+
+<h3>NetSurf 项目组件</h3>
+
+<dl class="components">
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/">NetSurf</a></dt>
+<dd>
+<span>&copy; 2002&ndash;2023 NetSurf å¼€å‘人员</span>
+<span><a href="#gplv2">GPLv2</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libcss/">LibCSS</a></dt>
+<dd>
+<span>&copy; 2007&ndash;2023 John-Mark Bell</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/hubbub/">Hubbub</a></dt>
+<dd>
+<span>&copy; 2007&ndash;2023 John-Mark Bell<br>&copy; 2008&ndash;2009 Andrew Sidwell</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libparserutils/">LibParserUtils</a></dt>
+<dd>
+<span>&copy; 2007&ndash;2023 John-Mark Bell</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/librosprite/">LibROSprite</a></dt>
+<dd>
+<span>&copy; 2008 James Shaw</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libpencil">Libpencil</a></dt>
+<dd>
+<span>&copy; 2005&ndash;2023 James Bursa</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/rufl">RUfl</a></dt>
+<dd>
+<span>&copy; 2005&ndash;2023 James Bursa</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libsvgtiny">Libsvgtiny</a></dt>
+<dd>
+<span>&copy; 2008&ndash;2009 James Bursa<br>&copy; 2017 Michael Drake</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libnsbmp/">Libnsbmp</a></dt>
+<dd>
+<span>&copy; 2006 Richard Wilson<br>&copy; 2008 Sean Fox<br>&copy; 2017 Vincent Sanders</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libnsfb/">Libnsfb</a></dt>
+<dd>
+<span>&copy; 2009&ndash;2017 Vincent Sanders<br>&copy; 2009&ndash;2023 Michael Drake</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libnsgif/">Libnsgif</a></dt>
+<dd>
+<span>&copy; 2004 Richard Wilson</br>&copy; 2008 Sean Fox</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.netsurf-browser.org/projects/libwapcaplet">LibWapcaplet</a></dt>
+<dd>
+<span>&copy; 2009&ndash;2023 NetSurf æµè§ˆå™¨é¡¹ç›®ï¼ŒDaniel Silverstone</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+</dl>
+
+<h3>第三方组件</h3>
+
+<dl class="components">
+<dt class="ns-border"><a href="https://curl.haxx.se/">cURL</a></dt>
+<dd>
+<span>&copy; 1996&ndash;2023 Daniel Stenberg</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://libharu.org/">Haru PDF</a></dt>
+<dd>
+<span>&copy; 2000&ndash;2008 Takeshi Kanno</span>
+<span><a href="#zlib">ZLib</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.ijg.org">libjpeg</a></dt>
+<dd>
+<span>&copy; 1991&ndash;2010 Thomas G. Lane,Guido Vollbeding</span>
+<span><a href="#ijg">IJG</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.littlecms.com/">liblcms</a></dt>
+<dd>
+<span>&copy; 1998&ndash;2007 Marti Maria Saguer</span>
+<span><a href="#mit">MIT</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://ro-oslib.sourceforge.net/">OSLib</a></dt>
+<dd>
+<span>&copy; 1994&ndash;1998 Jonathan Coxhead and contributors</span>
+<span><a href="#oslib">OSLib</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.openssl.org/">OpenSSL</a></dt>
+<dd>
+<span>&copy; 1995&ndash;1998 Eric A. Young, Tim J. Hudson<br>&copy; 1998&ndash;2010 OpenSSL 项目</span>
+<span><a href="#openssl">OpenSSL</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.libpng.org">libpng</a></dt>
+<dd>
+<span>&copy; 2004&ndash;2010 Glenn Randers-Pehrson</span>
+<span><a href="#png">PNG</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://www.riscos.info/websvn/listing.php?repname=gccsdk&path=%2Ftrunk%2Fgcc4%2Frecipe%2Ffiles%2Fgcc%2Flibunixlib%2F&#a9586e56e500c7fdfb58279167b82472d">UnixLib</a></dt>
+<dd>
+<span>&copy; 1995&ndash;1999 Simon Callan,Nick Burrett,Nicholas Clark and
+Peter Burwood<br>&copy; 1999&ndash;2009 Nick Burrett,John Tytgat,Peter Naulls,
+Lee Noar,Peter Teichmann,Alex Waugh,Christian Ludlam,Theo Markettos,
+Graham Shaw,James Bursa and John-Mark Bell。</span>
+<span><a href="#unixlib">UnixLib</a></span>
+</dd>
+
+<dt class="ns-border"><a href="https://zlib.net/">ZLib</a></dt>
+<dd>
+<span>&copy; 1995&ndash;2010 Jean-loup Gailly and Mark Adler</span>
+<span><a href="#zlib">ZLib</a></span>
+</dd>
+</dl>
+
+<h2 class="ns-border">许å¯è¯æ–‡æœ¬</h2>
+
+<p>此处尽å¯èƒ½æ˜¾ç¤ºè®¸å¯è¯æ–‡æœ¬çš„通用形å¼ã€‚æŸäº›éƒ¨ä»¶å¯èƒ½ä¼šç¨å¾®æ”¹å˜è®¸å¯è¯ï¼Œ
+我们已尽最大努力检测这些å˜åŒ–,并在此处列出ä¸åŒçš„许å¯è¯ã€‚
+ä¸è€ƒè™‘空白等的å˜åŒ–。</p>
+
+<a name="gplv2" />
+<h3>GNU 通用公共许å¯è¯ï¼Œç¬¬ 2 版</h3>
+<div class="licence ns-border ns-odd-bg"> GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
+</div>
+
+<a name="mit" />
+<h3>MIT/X 许å¯è¯</h3>
+<div class="licence ns-border ns-odd-bg">Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+</div>
+
+<a name="zlib" />
+<h3>ZLib 许å¯è¯</h3>
+<div class="licence ns-border ns-odd-bg"> This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+</div>
+
+<a name="ijg" />
+<h3>IJG 许å¯è¯</h3>
+<div class="licence ns-border ns-odd-bg">The authors make NO WARRANTY or representation, either express or implied,
+with respect to this software, its quality, accuracy, merchantability, or
+fitness for a particular purpose. This software is provided "AS IS", and you,
+its user, assume the entire risk as to its quality and accuracy.
+
+This software is copyright (C) 1991-2010, Thomas G. Lane, Guido Vollbeding.
+All Rights Reserved except as specified below.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+software (or portions thereof) for any purpose, without fee, subject to these
+conditions:
+(1) If any part of the source code for this software is distributed, then this
+README file must be included, with this copyright and no-warranty notice
+unaltered; and any additions, deletions, or changes to the original files
+must be clearly indicated in accompanying documentation.
+(2) If only executable code is distributed, then the accompanying
+documentation must state that "this software is based in part on the work of
+the Independent JPEG Group".
+(3) Permission for use of this software is granted only if the user accepts
+full responsibility for any undesirable consequences; the authors accept
+NO LIABILITY for damages of any kind.
+
+These conditions apply to any software derived from or based on the IJG code,
+not just to the unmodified library. If you use our work, you ought to
+acknowledge us.
+
+Permission is NOT granted for the use of any IJG author's name or company name
+in advertising or publicity relating to this software or products derived from
+it. This software may be referred to only as "the Independent JPEG Group's
+software".
+
+We specifically permit and encourage the use of this software as the basis of
+commercial products, provided that all warranty or liability claims are
+assumed by the product vendor.
+
+
+ansi2knr.c is included in this distribution by permission of L. Peter Deutsch,
+sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA.
+ansi2knr.c is NOT covered by the above copyright and conditions, but instead
+by the usual distribution terms of the Free Software Foundation; principally,
+that you must include source code if you redistribute it. (See the file
+ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part
+of any program generated from the IJG code, this does not limit you more than
+the foregoing paragraphs do.
+
+The Unix configuration script "configure" was produced with GNU Autoconf.
+It is copyright by the Free Software Foundation but is freely distributable.
+The same holds for its supporting scripts (config.guess, config.sub,
+ltmain.sh). Another support script, install-sh, is copyright by X Consortium
+but is also freely distributable.
+</div>
+
+
+<a name="oslib" />
+<h3>OSLib 许å¯è¯</h3>
+<div class="licence ns-border ns-odd-bg">The copyright holder has granted a small relaxation of the
+conditions of the GNU Public Licence, in that OSLib is itself
+free software, but applications linked to it need not be.
+This means that any changes to OSLib itself (the contents of
+the OSLib, OSLibHelp, OSLibSrc, and OSLibSupport archives)
+fall under the terms of the GNU Public Licence; but programs
+written using OSLib need not be so restricted.
+
+ GNU GENERAL PUBLIC LICENCE
+ Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, U S A
+ Everyone is permitted to copy and distribute verbatim copies
+ of this licence document, but changing it is not allowed.
+
+ Preamble
+
+ The licence agreements of most software companies try to keep users
+at the mercy of those companies. By contrast, our General Public
+Licence is intended to guarantee your freedom to share and change free
+software---to make sure the software is free for all its users. The
+General Public Licence applies to the Free Software Foundation's
+software and to any other programme whose authors commit to using it.
+You can use it for your programmes, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public Licence is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programmes; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of a such a programme, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this licence which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENCE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This Licence Agreement applies to any programme or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public Licence. The
+"Programme", below, refers to any such programme or work, and a "work based
+on the Programme" means either the Programme or any work containing the
+Programme or a portion of it, either verbatim or with modifications. Each
+licensee is addressed as "you".
+
+ 1. You may copy and distribute verbatim copies of the Programme's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public Licence and to the absence of any warranty; and give any
+other recipients of the Programme a copy of this General Public Licence
+along with the Programme. You may charge a fee for the physical act of
+transferring a copy.
+
+ 2. You may modify your copy or copies of the Programme or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating that
+ you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish, that
+ in whole or in part contains the Programme or any part thereof, either
+ with or without modifications, to be licensed at no charge to all
+ third parties under the terms of this General Public Licence (except
+ that you may choose to grant warranty protection to some or all
+ third parties, at your option).
+
+ c) If the modified programme normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the simplest and most usual way, to print or display an
+ announcement including an appropriate copyright notice and a notice
+ that there is no warranty (or else, saying that you provide a
+ warranty) and that users may redistribute the programme under these
+ conditions, and telling the user how to view a copy of this General
+ Public Licence.
+
+ d) You may charge a fee for the physical act of transferring a
+ copy, and you may at your option offer warranty protection in
+ exchange for a fee.
+
+Mere aggregation of another independent work with the Programme (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+ 3. You may copy and distribute the Programme (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal charge
+ for the cost of distribution) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the programme in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it. For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+ 4. You may not copy, modify, sublicense, distribute or transfer the
+Programme except as expressly provided under this General Public Licence.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Programme is void, and will automatically terminate your rights to use
+the Programme under this Licence. However, parties who have received
+copies, or rights to use copies, from you under this General Public
+Licence will not have their licences terminated so long as such parties
+remain in full compliance.
+
+ 5. By copying, distributing or modifying the Programme (or any work based
+on the Programme) you indicate your acceptance of this licence to do so,
+and all its terms and conditions.
+
+ 6. Each time you redistribute the Programme (or any work based on the
+Programme), the recipient automatically receives a licence from the original
+licensor to copy, distribute or modify the Programme subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+ 7. The Free Software Foundation may publish revised and/or new versions
+of the General Public Licence from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Programme
+specifies a version number of the licence which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Programme does not specify a version number of
+the licence, you may choose any version ever published by the Free Software
+Foundation.
+
+ 8. If you wish to incorporate parts of the Programme into other free
+programmes whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 9. BECAUSE THE PROGRAMME IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAMME, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAMME "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAMME IS WITH YOU. SHOULD THE
+PROGRAMME PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAMME AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAMME (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAMME TO OPERATE WITH ANY OTHER
+PROGRAMMES), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programmes
+
+ If you develop a new programme, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+ To do so, attach the following notices to the programme. It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the programme's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This programme is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public Licence as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This programme is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public Licence for more details.
+
+ You should have received a copy of the GNU General Public Licence
+ along with this programme; if not, write to the Free Software
+ Foundation, Inc, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the programme is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19xx name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public Licence. Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+programme.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the programme, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ programme `Gnomovision' (a programme to direct compilers to make passes
+ at assemblers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+That's all there is to it!
+</div>
+
+<a name="openssl" />
+<h3>OpenSSL 许å¯è¯</h3>
+<div class="licence ns-border ns-odd-bg"> The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
+ the OpenSSL License and the original SSLeay license apply to the toolkit.
+ See below for the actual license texts. Actually both licenses are BSD-style
+ Open Source licenses. In case of any license issues related to OpenSSL
+ please contact openssl-core@openssl.org.
+
+ OpenSSL License
+ ---------------
+
+/* ====================================================================
+ * Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+ Original SSLeay License
+ -----------------------
+
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+</div>
+
+<a name="png" />
+<h3>PNG 许å¯è¯</h3>
+<div class="licence ns-border ns-odd-bg"> * This code is released under the libpng license.
+ *
+ * libpng versions 1.2.6, August 15, 2004, through 1.4.1, February 25, 2010, are
+ * Copyright (c) 2004, 2006-2010 Glenn Randers-Pehrson, and are
+ * distributed according to the same disclaimer and license as libpng-1.2.5
+ * with the following individual added to the list of Contributing Authors:
+ *
+ * Cosmin Truta
+ *
+ * libpng versions 1.0.7, July 1, 2000, through 1.2.5, October 3, 2002, are
+ * Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are
+ * distributed according to the same disclaimer and license as libpng-1.0.6
+ * with the following individuals added to the list of Contributing Authors:
+ *
+ * Simon-Pierre Cadieux
+ * Eric S. Raymond
+ * Gilles Vollant
+ *
+ * and with the following additions to the disclaimer:
+ *
+ * There is no warranty against interference with your enjoyment of the
+ * library or against infringement. There is no warranty that our
+ * efforts or the library will fulfill any of your particular purposes
+ * or needs. This library is provided with all faults, and the entire
+ * risk of satisfactory quality, performance, accuracy, and effort is with
+ * the user.
+ *
+ * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson, and are
+ * distributed according to the same disclaimer and license as libpng-0.96,
+ * with the following individuals added to the list of Contributing Authors:
+ *
+ * Tom Lane
+ * Glenn Randers-Pehrson
+ * Willem van Schaik
+ *
+ * libpng versions 0.89, June 1996, through 0.96, May 1997, are
+ * Copyright (c) 1996, 1997 Andreas Dilger
+ * Distributed according to the same disclaimer and license as libpng-0.88,
+ * with the following individuals added to the list of Contributing Authors:
+ *
+ * John Bowler
+ * Kevin Bracey
+ * Sam Bushell
+ * Magnus Holmgren
+ * Greg Roelofs
+ * Tom Tanner
+ *
+ * libpng versions 0.5, May 1995, through 0.88, January 1996, are
+ * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
+ *
+ * For the purposes of this copyright and license, "Contributing Authors"
+ * is defined as the following set of individuals:
+ *
+ * Andreas Dilger
+ * Dave Martindale
+ * Guy Eric Schalnat
+ * Paul Schmidt
+ * Tim Wegner
+ *
+ * The PNG Reference Library is supplied "AS IS". The Contributing Authors
+ * and Group 42, Inc. disclaim all warranties, expressed or implied,
+ * including, without limitation, the warranties of merchantability and of
+ * fitness for any purpose. The Contributing Authors and Group 42, Inc.
+ * assume no liability for direct, indirect, incidental, special, exemplary,
+ * or consequential damages, which may result from the use of the PNG
+ * Reference Library, even if advised of the possibility of such damage.
+ *
+ * Permission is hereby granted to use, copy, modify, and distribute this
+ * source code, or portions hereof, for any purpose, without fee, subject
+ * to the following restrictions:
+ *
+ * 1. The origin of this source code must not be misrepresented.
+ *
+ * 2. Altered versions must be plainly marked as such and
+ * must not be misrepresented as being the original source.
+ *
+ * 3. This Copyright notice may not be removed or altered from
+ * any source or altered source distribution.
+ *
+ * The Contributing Authors and Group 42, Inc. specifically permit, without
+ * fee, and encourage the use of this source code as a component to
+ * supporting the PNG file format in commercial products. If you use this
+ * source code in a product, acknowledgment is not required but would be
+ * appreciated.
+ */
+</div>
+
+<a name="unixlib" />
+<h3>UnixLib 许å¯è¯</h3>
+<div class="licence ns-border ns-odd-bg">In January 2005, permission was obtained from all relevant contributors
+by Peter Naulls to license all past and present contributions to UnixLib
+(where possible) under the revised BSD license. The license is included
+in the next section and is applicable to all code in UnixLib that does not
+have an explicit license in its source.
+
+Prior to 4th January 2005 and after May 2001, UnixLib contained code licensed
+under the GNU General Public License, and versions of UnixLib produced
+between these dates are subject to the provisions of the GPL. We realised
+that this might cause potential problems with the wider use of UnixLib in
+RISC OS, and along with the desire to clarify the overall licensing status of
+UnixLib, GPL code was removed from UnixLib and the above permission from all
+copyright holders allowed UnixLib contributions to be relicensed as per the
+revised BSD license. The GPL is therefore not included in this notice
+as it is no longer relevant to UnixLib.
+
+
+Practical notes on using UnixLib in your own programs:
+
+This is a plain English version of guidelines for use of UnixLib in
+your programs. It does not override any of the licenses included
+below, but is intended to state instances when it may be used in
+free and non-free software. Where there is contradiction or
+ambiguity in this wording, please refer to the specifics of the licence
+in question. These recommendations are based upon our understading
+of the GPL/LGPL and BSD licenses and are subject to change should
+our understanding of the topics improve.
+
+ - Because UnixLib contains code that is subject to the Lesser GNU
+ Public License, the LGPL is the overriding consideration when
+ linking UnixLib to programs (unless the program itself is GPL).
+
+ - You are free to use sections of UnixLib in your own programs
+ subject to the conditions of that code. If the entirety of
+ that code is under a BSD license, then you can generally use
+ that code as you see fit, and there is no further obligation
+ from you as long as the copyright notice remains. If you
+ use LGPL code in your program, then your program must also be
+ distributed under the LGPL (or GPL).
+
+ - If you use UnixLib in its intended original form - that is as a
+ supporting library for ported programs to RISC OS - then your program
+ is subject to the LGPL; or the GPL if the program is covered by that.
+ Note that you must make the source and any modifications available to for
+ both if requested. This is of course equally true if you write an original
+ GPL program using UnixLib. In most cases, no additional action is
+ required of you, especially since source is usually readibly available.
+
+ - If you use UnixLib for a non-free program - whether that's commercial or
+ otherwise, then you should carefully read section 6 of the LGPL. This
+ applies, because at the present time, there is no practical method of
+ dynamic linking on RISC OS. At such time that UnixLib is available as a
+ shared library, then programs dynamically linking to it will no longer be
+ subject to the LPGL as applied to UnixLib.
+
+ - Section 6 means that in practice, you must supply, or offer to
+ supply either source or object code for your program.
+ This is mainly to allow rebuilding of the executable program
+ with later or modified versions of UnixLib. You must of course
+ supply (or better, contribute to the GCCSDK project) any
+ modifications you make to UnixLib upon request.
+
+
+Recommended reading:
+
+Frequently Asked Questions about the GNU GPL
+http://www.fsf.org/licenses/gpl-faq.html (has some sections on LGPL)
+
+About the justifications for using LGPL
+http://www.fsf.org/licenses/why-not-lgpl.html
+
+
+
+===========================================================================
+
+ Copyright (c) 1995-2009 UnixLib Developers
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+===========================================================================
+
+Portions of UnixLib are copyright The Regents of the University of
+California.
+
+Portions of this library are copyright Sun Microsystems, Inc. The
+
+Portions of this library are derived from the GNU C Library and fall under
+the GNU Library General Public License.
+
+Portions of this library are copyright Henry Spencer.
+
+Portions of this library are copyright The Regents of the University of
+California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState
+Corporation and other parties.
+
+Portions of this library are copyright PostgreSQL Global Development Group.
+
+The licenses for the above are duplicated below.
+
+
+===========================================================================
+
+ Copyright (c) The Regents of the University of California.
+ All rights reserved.
+
+ This code is derived from software contributed to Berkeley by
+ Chris Torek.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+ This product includes software developed by the University of
+ California, Berkeley and its contributors.
+ 4. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+===========================================================================
+
+ Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+
+ Developed at SunPro, a Sun Microsystems, Inc. business.
+ Permission to use, copy, modify, and distribute this
+ software is freely granted, provided that this notice
+ is preserved.
+
+===========================================================================
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+===========================================================================
+
+Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
+
+Development of this software was funded, in part, by Cray Research Inc.,
+UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
+Corporation, none of whom are responsible for the results. The author
+thanks all of them.
+
+Redistribution and use in source and binary forms -- with or without
+modification -- are permitted for any purpose, provided that
+redistributions in source form retain this entire copyright notice and
+indicate the origin and nature of any modifications.
+
+I'd appreciate being given credit for this package in the documentation
+of software which uses it, but that is not a requirement.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+===========================================================================
+
+This software is copyrighted by the Regents of the University of
+California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState
+Corporation and other parties. The following terms apply to all files
+associated with the software unless explicitly disclaimed in
+individual files.
+
+The authors hereby grant permission to use, copy, modify, distribute,
+and license this software and its documentation for any purpose, provided
+that existing copyright notices are retained in all copies and that this
+notice is included verbatim in any distributions. No written agreement,
+license, or royalty fee is required for any of the authorized uses.
+Modifications to this software may be copyrighted by their authors
+and need not follow the licensing terms described here, provided that
+the new terms are clearly indicated on the first page of each file where
+they apply.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
+IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+GOVERNMENT USE: If you are acquiring this software on behalf of the
+U.S. government, the Government shall have only "Restricted Rights"
+in the software and related documentation as defined in the Federal
+Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
+are acquiring the software on behalf of the Department of Defense, the
+software shall be classified as "Commercial Computer Software" and the
+Government shall have only "Restricted Rights" as defined in Clause
+252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
+authors grant the U.S. Government and others acting in its behalf
+permission to use and distribute the software in accordance with the
+terms specified in this license.
+
+===========================================================================
+
+PostgreSQL Database Management System
+(formerly known as Postgres, then as Postgres95)
+
+Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
+
+Portions Copyright (c) 1994, The Regents of the University of California
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose, without fee, and without a written agreement
+is hereby granted, provided that the above copyright notice and this
+paragraph and the following two paragraphs appear in all copies.
+
+IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
+LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
+DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
+PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+</div>
+
+<div class="footer">
+<p class="ns-even-fg-faded ns-border">Copyright 2003&ndash;2019 NetSurf å¼€å‘人员</p>
+</div>
+
+</body>
+</html>
diff --git a/resources/zh_CN/welcome.html b/resources/zh_CN/welcome.html
new file mode 100644
index 000000000..340a8e206
--- /dev/null
+++ b/resources/zh_CN/welcome.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<title>欢迎使用 NetSurf</title>
+<style type="text/css">html,body{margin:0;padding:0;}body{color:#000;background:#fff;font-family:sans-serif;margin:0 auto;}a:link{text-decoration:underline;color:#00f;}a:visited{text-decoration:underline;color:#60a;}a:hover{text-decoration:none;}a:active{text-decoration:underline;color:#f00;}.banner{margin:0;padding:0;background:#94adff;text-align:left;}.banner img{border:none;color:#000;height:86px;width:308px;display:block;}.onlycontent{margin:0 1em;}.nslinks{display:table;width:100%;margin:0;border-spacing:0;padding:0;background:#ccd8ff;font-size:94%;}.nslinks li{display:table-cell;text-align:center;padding:0.2em 0.3em 0.3em;vertical-align:middle;}.nslinks li+li{border-left:2px solid #b1c3ff;}.version{padding:0;margin:1.2em auto 0;width:90%;color:#444;font-size:160%;}.intro{width: 90%;margin:1em auto;color:#666;}.websearch{margin:1.5em auto;padding:1.2em 0.3em;background:#d8e2ff;border:2px solid #c5d3ff;width:80%;text-align:center;}input[type=text]{border:2px solid #b6c7ff;background:#f9faff;color:#000;margin:2px;}input[type=submit]{border:2px outset #cedaff;color:#000;background:#cedaff;margin:2px;}.links{display:table;width:80%;margin:0 auto 3em;font-size:94%;}.links ul{display:table-cell;padding-left:2.5em;}.links ul+ul{padding-left:1em;}.footer{font-style:italic;color:#666;text-align:right;}.footer p{margin-top:1.5em;padding-top:0.4em;border-top:2px solid #94adff;}</style>
+</head>
+
+<body>
+<h1 class="banner"><a href="https://www.netsurf-browser.org/"><img src="about:logo" alt="NetSurf"></a></h1>
+
+<ul class="nslinks">
+<li><a href="https://www.netsurf-browser.org/">NetSurf 网站</a></li>
+<li><a href="https://www.netsurf-browser.org/documentation/">文档</a></li>
+<li><a href="https://www.netsurf-browser.org/downloads/">下载最新版 NetSurf</a></li>
+<li><a href="https://www.netsurf-browser.org/contact/">è”系开å‘者</a></li>
+</ul>
+
+<div class="onlycontent">
+<h2 class="version">欢迎使用 NetSurf</h2>
+
+<p class="intro">NetSurf 是一款体积å°ã€é€Ÿè¯»å¿«çš„å¼€æºç½‘络æµè§ˆå™¨ã€‚我们一直致力于改进æµè§ˆå™¨ï¼Œå¦‚æžœé‡åˆ°ä»»ä½•é—®é¢˜ï¼Œè¯·ä¸Žæˆ‘们è”系。感谢您选择 NetSurfï¼</p>
+
+<form method="get" action="https://www.google.co.uk/search">
+<div class="websearch">
+<input type="text" name="q" size="42" maxlength="255">
+<input type="submit" value="Google Search" name="btnG">
+</div>
+</form>
+
+<div class="links">
+<ul>
+<li><a href="https://news.bbc.co.uk/">BBC æ–°é—»</a></li>
+<li><a href="https://www.reuters.com/news">è·¯é€ç¤¾</a></li>
+<li><a href="https://www.cnn.com/">CNN</a></li>
+</ul>
+
+<ul>
+<li><a href="https://slashdot.org/">Slashdot</a></li>
+<li><a href="https://arstechnica.com/">Ars Technica</a></li>
+<li><a href="https://www.theregister.co.uk/">The Register</a></li>
+<li><a href="https://www.w3.org/">W3C</a></li>
+</ul>
+
+<ul>
+<li><a href="https://en.wikipedia.org/wiki/Main_Page">维基百科</a></li>
+<li><a href="https://google.co.uk/">谷歌</a></li>
+<li><a href="https://yahoo.co.uk/">雅虎</a></li>
+<li><a href="https://www.imdb.com/">IMDB</a></li>
+</ul>
+
+<ul>
+<li><a href="https://www.iconbar.com/">图标æ </a></li>
+<li><a href="https://www.riscosopen.org/">ROOL</a></li>
+<li><a href="https://www.riscos.info/">riscos.info</a></li>
+</ul>
+</div>
+
+<div class="footer">
+<p>NetSurf æ˜¯æ ¹æ® GNU 公共许å¯è¯ç‰ˆæœ¬ 2 许å¯çš„</p>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/test/.gitignore b/test/.gitignore
new file mode 100644
index 000000000..bee8a64b7
--- /dev/null
+++ b/test/.gitignore
@@ -0,0 +1 @@
+__pycache__
diff --git a/test/Makefile b/test/Makefile
index a5f023bdc..82ffee6fa 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -7,6 +7,7 @@ TESTS := \
nsoption \
bloom \
hashtable \
+ hashmap \
urlescape \
utils \
messages \
@@ -18,7 +19,7 @@ TESTS := \
NSURL_SOURCES := utils/nsurl/nsurl.c utils/nsurl/parse.c utils/idna.c \
utils/punycode.c
-# nsurl sources
+# nsurl test sources
nsurl_SRCS := $(NSURL_SOURCES) utils/corestrings.c test/log.c test/nsurl.c
# url database test sources
@@ -30,7 +31,7 @@ urldbtest_SRCS := $(NSURL_SOURCES) \
content/urldb.c \
test/log.c test/urldbtest.c
-# low level cache sources
+# low level cache test sources
llcache_SRCS := content/fetch.c content/fetchers/curl.c \
content/fetchers/about.c content/fetchers/data.c \
content/fetchers/resource.c content/llcache.c \
@@ -52,6 +53,10 @@ bloom_SRCS := utils/bloom.c test/bloom.c
# hash table test sources
hashtable_SRCS := utils/hashtable.c test/log.c test/hashtable.c
+# hashmap test sources
+hashmap_SRCS := $(NSURL_SOURCES) utils/hashmap.c utils/corestrings.c test/log.c test/hashmap.c
+hashmap_LD := -lmalloc_fig
+
# url escape test sources
urlescape_SRCS := utils/url.c test/log.c test/urlescape.c
@@ -127,20 +132,25 @@ endef
$(eval $(call pkg_cfg_detect_lib,check,Check))
-COMMON_WARNFLAGS = -W -Wall -Wundef -Wpointer-arith -Wcast-align \
+TEST_WARNFLAGS = -W -Wall -Wundef -Wpointer-arith -Wcast-align \
-Wwrite-strings -Wmissing-declarations -Wuninitialized
ifneq ($(CC_MAJOR),2)
- COMMON_WARNFLAGS += -Wno-unused-parameter
+ TEST_WARNFLAGS += -Wno-unused-parameter
endif
BASE_TESTCFLAGS := -std=c99 -g \
- $(COMMON_WARNFLAGS) \
+ $(TEST_WARNFLAGS) \
-D_DEFAULT_SOURCE \
-D_POSIX_C_SOURCE=200809L \
-D_XOPEN_SOURCE=600 \
-Itest -Iinclude -Icontent/handlers -Ifrontends -I. -I.. \
-Dnsgtk \
+ -DNETSURF_BUILTIN_LOG_FILTER=\"level:WARNING\" \
+ -DNETSURF_BUILTIN_VERBOSE_FILTER=\"level:DEBUG\" \
+ -DTESTROOT=\"$(TESTROOT)\" \
+ -DWITH_UTF8PROC \
+ $(SAN_FLAGS) \
$(shell pkg-config --cflags libcurl libparserutils libwapcaplet libdom libnsutils libutf8proc) \
$(LIB_CFLAGS)
TESTCFLAGS := $(BASE_TESTCFLAGS) \
@@ -149,12 +159,13 @@ TESTCFLAGS := $(BASE_TESTCFLAGS) \
TESTLDFLAGS := -L$(TESTROOT) \
$(shell pkg-config --libs libcurl libparserutils libwapcaplet libdom libnsutils libutf8proc) -lz \
+ $(SAN_FLAGS) \
$(LIB_LDFLAGS)\
$(COV_LDFLAGS)
# malloc faliure injection generator
$(TESTROOT)/libmalloc_fig.so:test/malloc_fig.c
- $(CC) -shared -fPIC -I. -std=c99 $(COMMON_WARNFLAGS) $^ -o $@
+ $(CC) -shared -fPIC -I. -std=c99 $(TEST_WARNFLAGS) $^ -ldl -o $@
# Source files for all tests being compiled
TESTSOURCES :=
@@ -202,11 +213,12 @@ $(eval $(foreach SOURCE,$(sort $(filter %.c,$(NOCOV_TESTSOURCES))), \
$(call compile_test_nocov_target_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.o)),$(subst /,_,$(SOURCE:.c=.d)))))
-.PHONY:test coverage
+.PHONY:test coverage sanitize
test: $(TESTROOT)/created $(TESTROOT)/libmalloc_fig.so $(addsuffix _test,$(TESTS))
coverage: test
+sanitize: test
$(TESTROOT)/created:
$(VQ)echo " MKDIR: $(TESTROOT)"
diff --git a/test/assert.c b/test/assert.c
index d21926e5e..fb4db8cc9 100644
--- a/test/assert.c
+++ b/test/assert.c
@@ -30,7 +30,23 @@ __ns_assert_fail(const char *__assertion, const char *__file,
unsigned int __line, const char *__function)
__THROW __attribute__ ((__noreturn__));
-/* We use this to flush coverage data */
+#if __GNUC__ > 10
+
+/* We use this to dump coverage data in gcc 11 and later */
+extern void __gcov_dump(void);
+
+/* And here's our entry point */
+void
+__ns_assert_fail(const char *__assertion, const char *__file,
+ unsigned int __line, const char *__function)
+{
+ __gcov_dump();
+ __assert_fail(__assertion, __file, __line, __function);
+}
+
+#else
+
+/* We use this to flush coverage data before gcc 11 */
extern void __gcov_flush(void);
/* And here's our entry point */
@@ -41,3 +57,4 @@ __ns_assert_fail(const char *__assertion, const char *__file,
__gcov_flush();
__assert_fail(__assertion, __file, __line, __function);
}
+#endif
diff --git a/test/corestrings.c b/test/corestrings.c
index 02640c953..c3c4e93eb 100644
--- a/test/corestrings.c
+++ b/test/corestrings.c
@@ -40,7 +40,7 @@
*
* This is used to test all the out of memory paths in initialisation.
*/
-#define CORESTRING_TEST_COUNT 435
+#define CORESTRING_TEST_COUNT 488
START_TEST(corestrings_test)
{
@@ -53,8 +53,12 @@ START_TEST(corestrings_test)
res = corestrings_fini();
malloc_limit(UINT_MAX);
-
- ck_assert_int_eq(ires, NSERROR_NOMEM);
+
+ if (_i < CORESTRING_TEST_COUNT) {
+ ck_assert_int_eq(ires, NSERROR_NOMEM);
+ } else {
+ ck_assert_int_eq(ires, NSERROR_OK);
+ }
ck_assert_int_eq(res, NSERROR_OK);
}
END_TEST
@@ -65,7 +69,7 @@ static TCase *corestrings_case_create(void)
TCase *tc;
tc = tcase_create("corestrings");
- tcase_add_loop_test(tc, corestrings_test, 0, CORESTRING_TEST_COUNT);
+ tcase_add_loop_test(tc, corestrings_test, 0, CORESTRING_TEST_COUNT + 1);
return tc;
}
diff --git a/test/data/Choices b/test/data/Choices
index bd946f77b..511ecf87e 100644
--- a/test/data/Choices
+++ b/test/data/Choices
@@ -30,7 +30,6 @@ disc_cache_size:1073741824
disc_cache_age:28
block_advertisements:0
do_not_track:0
-minimum_gif_delay:10
send_referer:1
foreground_images:1
background_images:1
@@ -50,8 +49,6 @@ window_x:0
window_y:0
window_width:0
window_height:0
-window_screen_width:0
-window_screen_height:0
toolbar_status_size:6667
scale:100
incremental_reflow:1
@@ -101,7 +98,6 @@ sys_colour_ThreeDShadow:000000
sys_colour_Window:000000
sys_colour_WindowFrame:000000
sys_colour_WindowText:000000
-render_resample:1
downloads_clear:0
request_overwrite:1
downloads_directory:/home/vince
@@ -109,7 +105,6 @@ url_file:/home/vince/.netsurf/URLs
show_single_tab:1
button_type:1
disable_popups:0
-disable_plugins:0
history_age:0
hover_urls:0
focus_new:0
diff --git a/test/data/Choices-all b/test/data/Choices-all
index 9f2e18377..5c26f2887 100644
--- a/test/data/Choices-all
+++ b/test/data/Choices-all
@@ -16,16 +16,17 @@ font_fantasy:Serif
accept_language:en
accept_charset:
memory_cache_size:12582912
+disc_cache_path:
disc_cache_size:1073741824
disc_cache_age:28
block_advertisements:0
do_not_track:0
-minimum_gif_delay:10
send_referer:1
foreground_images:1
background_images:1
animate_images:1
enable_javascript:1
+author_level_css:1
script_timeout:10
expire_url:28
font_default:0
@@ -41,8 +42,6 @@ window_x:0
window_y:0
window_width:0
window_height:0
-window_screen_width:0
-window_screen_height:0
toolbar_status_size:6667
scale:100
incremental_reflow:1
@@ -67,6 +66,7 @@ remove_backgrounds:0
enable_loosening:1
enable_PDF_compression:1
enable_PDF_password:0
+prefer_dark_mode:0
sys_colour_ActiveBorder:d3d3d3
sys_colour_ActiveCaption:f1f1f1
sys_colour_AppWorkspace:f1f1f1
@@ -96,8 +96,7 @@ sys_colour_Window:f1f1f1
sys_colour_WindowFrame:4e4e4e
sys_colour_WindowText:000000
log_filter:level:WARNING
-verbose_filter:level:VERBOSE
-render_resample:1
+verbose_filter:level:DEBUG
downloads_clear:0
request_overwrite:1
downloads_directory:/home/vince
@@ -105,7 +104,6 @@ url_file:/home/vince/.netsurf/URLs
show_single_tab:1
button_type:1
disable_popups:0
-disable_plugins:0
history_age:0
hover_urls:0
focus_new:0
@@ -113,4 +111,5 @@ new_blank:0
hotlist_path:/home/vince/.netsurf/Hotlist
developer_view:0
position_tab:0
-toolbar_order:
+toolbar_items:
+bar_show:
diff --git a/test/data/urldb-out b/test/data/urldb-out
index 6db02bc91..11f400e02 100644
--- a/test/data/urldb-out
+++ b/test/data/urldb-out
@@ -1,5 +1,5 @@
-106
-en.wikipedia.org
+107
+en.wikipedia.org 0 0
1
https
@@ -9,7 +9,7 @@ https
1
Wikipedia, the free encyclopedia
-slashdot.org
+slashdot.org 0 0
2
http
@@ -27,7 +27,7 @@ https
1
Slashdot: News for nerds, stuff that matters
-www.bbc.co.uk
+www.bbc.co.uk 0 0
1
http
diff --git a/test/hashmap.c b/test/hashmap.c
new file mode 100644
index 000000000..ed951e9a7
--- /dev/null
+++ b/test/hashmap.c
@@ -0,0 +1,571 @@
+/*
+ * Copyright 2020 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ * Copyright 2016 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Tests for hashmap.
+ *
+ * In part, borrows from the corestrings tests
+ */
+
+#include "utils/config.h"
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <check.h>
+#include <limits.h>
+
+#include <libwapcaplet/libwapcaplet.h>
+
+#include "utils/nsurl.h"
+#include "utils/corestrings.h"
+#include "utils/hashmap.h"
+
+#include "test/malloc_fig.h"
+
+/* Low level fixtures */
+
+static void
+corestring_create(void)
+{
+ ck_assert(corestrings_init() == NSERROR_OK);
+}
+
+/**
+ * iterator for any remaining strings in teardown fixture
+ */
+static void
+netsurf_lwc_iterator(lwc_string *str, void *pw)
+{
+ fprintf(stderr,
+ "[%3u] %.*s",
+ str->refcnt,
+ (int)lwc_string_length(str),
+ lwc_string_data(str));
+}
+
+static void
+corestring_teardown(void)
+{
+ corestrings_fini();
+
+ lwc_iterate_strings(netsurf_lwc_iterator, NULL);
+}
+
+/* Infra */
+
+static ssize_t keys;
+static ssize_t values;
+
+typedef struct {
+ nsurl *key;
+} hashmap_test_value_t;
+
+static void *
+key_clone(void *key)
+{
+ /* Pretend cloning costs memory so that it can fail for
+ * testing error return pathways
+ */
+ void *temp = malloc(1);
+ if (temp == NULL) return NULL;
+ free(temp);
+ /* In reality we just ref the nsurl */
+ keys++;
+ return nsurl_ref((nsurl *)key);
+}
+
+static void
+key_destroy(void *key)
+{
+ keys--;
+ nsurl_unref((nsurl *)key);
+}
+
+static uint32_t
+key_hash(void *key)
+{
+ /* Deliberately bad hash.
+ * returns 0, 1, 2, or 3 to force bucket chaining
+ */
+ return nsurl_hash((nsurl *)key) & 3;
+}
+
+static bool
+key_eq(void *key1, void *key2)
+{
+ return nsurl_compare((nsurl *)key1, (nsurl*)key2, NSURL_COMPLETE);
+}
+
+static void *
+value_alloc(void *key)
+{
+ hashmap_test_value_t *ret = malloc(sizeof(hashmap_test_value_t));
+
+ if (ret == NULL)
+ return NULL;
+
+ ret->key = (nsurl *)key;
+
+ values++;
+
+ return ret;
+}
+
+static void
+value_destroy(void *value)
+{
+ hashmap_test_value_t *val = value;
+
+ /* Do nothing for now */
+
+ free(val);
+ values--;
+}
+
+static hashmap_parameters_t test_params = {
+ .key_clone = key_clone,
+ .key_hash = key_hash,
+ .key_eq = key_eq,
+ .key_destroy = key_destroy,
+ .value_alloc = value_alloc,
+ .value_destroy = value_destroy,
+};
+
+/* Iteration helpers */
+
+static size_t iteration_counter = 0;
+static size_t iteration_stop = 0;
+static char iteration_ctx = 0;
+
+static bool
+hashmap_test_iterator_cb(void *key, void *value, void *ctx)
+{
+ ck_assert(ctx == &iteration_ctx);
+ iteration_counter++;
+ return iteration_counter == iteration_stop;
+}
+
+/* Fixtures for basic tests */
+
+static hashmap_t *test_hashmap = NULL;
+
+static void
+basic_fixture_create(void)
+{
+ corestring_create();
+
+ test_hashmap = hashmap_create(&test_params);
+
+ ck_assert(test_hashmap != NULL);
+ ck_assert_int_eq(keys, 0);
+ ck_assert_int_eq(values, 0);
+}
+
+static void
+basic_fixture_teardown(void)
+{
+ hashmap_destroy(test_hashmap);
+ test_hashmap = NULL;
+
+ ck_assert_int_eq(keys, 0);
+ ck_assert_int_eq(values, 0);
+
+ corestring_teardown();
+}
+
+/* basic api tests */
+
+START_TEST(empty_hashmap_create_destroy)
+{
+ ck_assert_int_eq(hashmap_count(test_hashmap), 0);
+}
+END_TEST
+
+START_TEST(check_not_present)
+{
+ /* We're checking for a key which should not be present */
+ ck_assert(hashmap_lookup(test_hashmap, corestring_nsurl_about_blank) == NULL);
+}
+END_TEST
+
+START_TEST(insert_works)
+{
+ hashmap_test_value_t *value = hashmap_insert(test_hashmap, corestring_nsurl_about_blank);
+ ck_assert(value != NULL);
+ ck_assert(value->key == corestring_nsurl_about_blank);
+ ck_assert_int_eq(hashmap_count(test_hashmap), 1);
+}
+END_TEST
+
+START_TEST(remove_not_present)
+{
+ ck_assert(hashmap_remove(test_hashmap, corestring_nsurl_about_blank) == false);
+}
+END_TEST
+
+START_TEST(insert_then_remove)
+{
+ hashmap_test_value_t *value = hashmap_insert(test_hashmap, corestring_nsurl_about_blank);
+ ck_assert(value != NULL);
+ ck_assert(value->key == corestring_nsurl_about_blank);
+ ck_assert_int_eq(keys, 1);
+ ck_assert_int_eq(values, 1);
+ ck_assert_int_eq(hashmap_count(test_hashmap), 1);
+ ck_assert(hashmap_remove(test_hashmap, corestring_nsurl_about_blank) == true);
+ ck_assert_int_eq(keys, 0);
+ ck_assert_int_eq(values, 0);
+ ck_assert_int_eq(hashmap_count(test_hashmap), 0);
+}
+END_TEST
+
+START_TEST(insert_then_lookup)
+{
+ hashmap_test_value_t *value = hashmap_insert(test_hashmap, corestring_nsurl_about_blank);
+ ck_assert(value != NULL);
+ ck_assert(value->key == corestring_nsurl_about_blank);
+ ck_assert(hashmap_lookup(test_hashmap, corestring_nsurl_about_blank) == value);
+}
+END_TEST
+
+START_TEST(iterate_empty)
+{
+ iteration_stop = iteration_counter = 0;
+ ck_assert(hashmap_iterate(test_hashmap, hashmap_test_iterator_cb, &iteration_ctx) == false);
+ ck_assert_int_eq(iteration_counter, 0);
+}
+END_TEST
+
+START_TEST(iterate_one)
+{
+ iteration_stop = iteration_counter = 0;
+ hashmap_test_value_t *value = hashmap_insert(test_hashmap, corestring_nsurl_about_blank);
+ ck_assert(value != NULL);
+ ck_assert(hashmap_iterate(test_hashmap, hashmap_test_iterator_cb, &iteration_ctx) == false);
+ ck_assert_int_eq(iteration_counter, 1);
+}
+END_TEST
+
+START_TEST(iterate_one_and_stop)
+{
+ iteration_stop = 1;
+ iteration_counter = 0;
+ hashmap_test_value_t *value = hashmap_insert(test_hashmap, corestring_nsurl_about_blank);
+ ck_assert(value != NULL);
+ ck_assert(hashmap_iterate(test_hashmap, hashmap_test_iterator_cb, &iteration_ctx) == true);
+ ck_assert_int_eq(iteration_counter, 1);
+}
+END_TEST
+
+static TCase *basic_api_case_create(void)
+{
+ TCase *tc;
+ tc = tcase_create("Basic API");
+
+ tcase_add_unchecked_fixture(tc,
+ basic_fixture_create,
+ basic_fixture_teardown);
+
+ tcase_add_test(tc, empty_hashmap_create_destroy);
+ tcase_add_test(tc, check_not_present);
+ tcase_add_test(tc, insert_works);
+ tcase_add_test(tc, remove_not_present);
+ tcase_add_test(tc, insert_then_remove);
+ tcase_add_test(tc, insert_then_lookup);
+
+ tcase_add_test(tc, iterate_empty);
+ tcase_add_test(tc, iterate_one);
+ tcase_add_test(tc, iterate_one_and_stop);
+
+ return tc;
+}
+
+/* Chain verification test suite */
+
+typedef struct {
+ const char *url;
+ nsurl *nsurl;
+} case_pair;
+
+/* The hobbled hash has only 4 values
+ * By having at least 12 test cases, we can be confident that
+ * at worst they'll all be on one chain, but at best there'll
+ * be four chains of 3 entries which means we should be able
+ * to validate prevptr and next in all cases.
+ */
+static case_pair chain_pairs[] = {
+ { "https://www.google.com/", NULL },
+ { "https://www.google.co.uk/", NULL },
+ { "https://www.netsurf-browser.org/", NULL },
+ { "http://www.google.com/", NULL },
+ { "http://www.google.co.uk/", NULL },
+ { "http://www.netsurf-browser.org/", NULL },
+ { "file:///tmp/test.html", NULL },
+ { "file:///tmp/inner.html", NULL },
+ { "about:blank", NULL },
+ { "about:welcome", NULL },
+ { "about:testament", NULL },
+ { "resources:default.css", NULL },
+ { NULL, NULL }
+};
+
+static void
+chain_fixture_create(void)
+{
+ case_pair *chain_case = chain_pairs;
+ basic_fixture_create();
+
+ while (chain_case->url != NULL) {
+ ck_assert(nsurl_create(chain_case->url, &chain_case->nsurl) == NSERROR_OK);
+ chain_case++;
+ }
+
+}
+
+static void
+chain_fixture_teardown(void)
+{
+ case_pair *chain_case = chain_pairs;
+
+ while (chain_case->url != NULL) {
+ nsurl_unref(chain_case->nsurl);
+ chain_case->nsurl = NULL;
+ chain_case++;
+ }
+
+ basic_fixture_teardown();
+}
+
+START_TEST(chain_add_remove_all)
+{
+ case_pair *chain_case;
+
+ for (chain_case = chain_pairs;
+ chain_case->url != NULL;
+ chain_case++) {
+ ck_assert(hashmap_lookup(test_hashmap, chain_case->nsurl) == NULL);
+ ck_assert(hashmap_insert(test_hashmap, chain_case->nsurl) != NULL);
+ ck_assert(hashmap_lookup(test_hashmap, chain_case->nsurl) != NULL);
+ ck_assert(hashmap_remove(test_hashmap, chain_case->nsurl) == true);
+ }
+
+ ck_assert_int_eq(keys, 0);
+ ck_assert_int_eq(values, 0);
+}
+END_TEST
+
+START_TEST(chain_add_all_remove_all)
+{
+ case_pair *chain_case;
+
+ for (chain_case = chain_pairs;
+ chain_case->url != NULL;
+ chain_case++) {
+ ck_assert(hashmap_lookup(test_hashmap, chain_case->nsurl) == NULL);
+ ck_assert(hashmap_insert(test_hashmap, chain_case->nsurl) != NULL);
+ }
+
+ for (chain_case = chain_pairs;
+ chain_case->url != NULL;
+ chain_case++) {
+ ck_assert(hashmap_remove(test_hashmap, chain_case->nsurl) == true);
+ }
+
+ ck_assert_int_eq(keys, 0);
+ ck_assert_int_eq(values, 0);
+}
+END_TEST
+
+START_TEST(chain_add_all_twice_remove_all)
+{
+ case_pair *chain_case;
+
+ for (chain_case = chain_pairs;
+ chain_case->url != NULL;
+ chain_case++) {
+ ck_assert(hashmap_lookup(test_hashmap, chain_case->nsurl) == NULL);
+ ck_assert(hashmap_insert(test_hashmap, chain_case->nsurl) != NULL);
+ }
+
+ for (chain_case = chain_pairs;
+ chain_case->url != NULL;
+ chain_case++) {
+ ck_assert(hashmap_lookup(test_hashmap, chain_case->nsurl) != NULL);
+ ck_assert(hashmap_insert(test_hashmap, chain_case->nsurl) != NULL);
+ }
+
+ for (chain_case = chain_pairs;
+ chain_case->url != NULL;
+ chain_case++) {
+ ck_assert(hashmap_remove(test_hashmap, chain_case->nsurl) == true);
+ }
+
+ ck_assert_int_eq(keys, 0);
+ ck_assert_int_eq(values, 0);
+}
+END_TEST
+
+START_TEST(chain_add_all_twice_remove_all_iterate)
+{
+ case_pair *chain_case;
+ size_t chain_count = 0;
+
+ for (chain_case = chain_pairs;
+ chain_case->url != NULL;
+ chain_case++) {
+ ck_assert(hashmap_lookup(test_hashmap, chain_case->nsurl) == NULL);
+ ck_assert(hashmap_insert(test_hashmap, chain_case->nsurl) != NULL);
+ chain_count++;
+ }
+
+ iteration_counter = 0;
+ iteration_stop = 0;
+ ck_assert(hashmap_iterate(test_hashmap, hashmap_test_iterator_cb, &iteration_ctx) == false);
+ ck_assert_int_eq(iteration_counter, chain_count);
+
+ for (chain_case = chain_pairs;
+ chain_case->url != NULL;
+ chain_case++) {
+ ck_assert(hashmap_lookup(test_hashmap, chain_case->nsurl) != NULL);
+ ck_assert(hashmap_insert(test_hashmap, chain_case->nsurl) != NULL);
+ }
+
+ iteration_counter = 0;
+ iteration_stop = 0;
+ ck_assert(hashmap_iterate(test_hashmap, hashmap_test_iterator_cb, &iteration_ctx) == false);
+ ck_assert_int_eq(iteration_counter, chain_count);
+ ck_assert_int_eq(hashmap_count(test_hashmap), chain_count);
+
+ iteration_counter = 0;
+ iteration_stop = chain_count;
+ ck_assert(hashmap_iterate(test_hashmap, hashmap_test_iterator_cb, &iteration_ctx) == true);
+ ck_assert_int_eq(iteration_counter, chain_count);
+
+ for (chain_case = chain_pairs;
+ chain_case->url != NULL;
+ chain_case++) {
+ ck_assert(hashmap_remove(test_hashmap, chain_case->nsurl) == true);
+ }
+
+ iteration_counter = 0;
+ iteration_stop = chain_count;
+ ck_assert(hashmap_iterate(test_hashmap, hashmap_test_iterator_cb, &iteration_ctx) == false);
+ ck_assert_int_eq(iteration_counter, 0);
+
+ ck_assert_int_eq(keys, 0);
+ ck_assert_int_eq(values, 0);
+ ck_assert_int_eq(hashmap_count(test_hashmap), 0);
+}
+END_TEST
+
+#define CHAIN_TEST_MALLOC_COUNT_MAX 60
+
+START_TEST(chain_add_all_remove_all_alloc)
+{
+ bool failed = false;
+ case_pair *chain_case;
+
+ malloc_limit(_i);
+
+ for (chain_case = chain_pairs;
+ chain_case->url != NULL;
+ chain_case++) {
+ if (hashmap_insert(test_hashmap, chain_case->nsurl) == NULL) {
+ failed = true;
+ }
+ }
+
+ for (chain_case = chain_pairs;
+ chain_case->url != NULL;
+ chain_case++) {
+ if (hashmap_insert(test_hashmap, chain_case->nsurl) == NULL) {
+ failed = true;
+ }
+ }
+
+ for (chain_case = chain_pairs;
+ chain_case->url != NULL;
+ chain_case++) {
+ hashmap_remove(test_hashmap, chain_case->nsurl);
+ }
+
+ malloc_limit(UINT_MAX);
+
+ ck_assert_int_eq(keys, 0);
+ ck_assert_int_eq(values, 0);
+
+ if (_i < CHAIN_TEST_MALLOC_COUNT_MAX) {
+ ck_assert(failed);
+ } else {
+ ck_assert(!failed);
+ }
+
+}
+END_TEST
+
+static TCase *chain_case_create(void)
+{
+ TCase *tc;
+ tc = tcase_create("Bucket Chain tests");
+
+ tcase_add_unchecked_fixture(tc,
+ chain_fixture_create,
+ chain_fixture_teardown);
+
+ tcase_add_test(tc, chain_add_remove_all);
+ tcase_add_test(tc, chain_add_all_remove_all);
+ tcase_add_test(tc, chain_add_all_twice_remove_all);
+ tcase_add_test(tc, chain_add_all_twice_remove_all_iterate);
+
+ tcase_add_loop_test(tc, chain_add_all_remove_all_alloc, 0, CHAIN_TEST_MALLOC_COUNT_MAX + 1);
+
+ return tc;
+}
+
+/*
+ * hashmap test suite creation
+ */
+static Suite *hashmap_suite_create(void)
+{
+ Suite *s;
+ s = suite_create("Hashmap");
+
+ suite_add_tcase(s, basic_api_case_create());
+ suite_add_tcase(s, chain_case_create());
+
+ return s;
+}
+
+int main(int argc, char **argv)
+{
+ int number_failed;
+ SRunner *sr;
+
+ sr = srunner_create(hashmap_suite_create());
+
+ srunner_run_all(sr, CK_ENV);
+
+ number_failed = srunner_ntests_failed(sr);
+ srunner_free(sr);
+
+ return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/test/js/class-list.html b/test/js/class-list.html
new file mode 100644
index 000000000..4c73283e5
--- /dev/null
+++ b/test/js/class-list.html
@@ -0,0 +1,29 @@
+<html>
+ <head>
+ <title>Class List (and other token lists?)</title>
+ <style>
+ .bad { background-color: red; }
+ .ok { background-color: green; }
+ </style>
+ </head>
+ <body>
+ <h1>This is a set of demonstrators for the token list Element.classList</h1>
+ <h2>This first is taken from the MDN for DOMTokenList</h2>
+ <span id="demo1" class=" d d e f bad"></span>
+ <script>
+ var span = document.getElementById("demo1");
+ var classes = span.classList;
+ classes.add("x", "d", "g");
+ classes.remove("e", "g");
+ classes.toggle("d"); // Toggles d off
+ classes.toggle("q", false); // Forces q off (won't be present)
+ classes.toggle("d"); // Toggles d on
+ classes.toggle("d", true); // Forces d on (won't toggle it off again)
+ if (classes.contains("d")) {
+ classes.add("ok")
+ classes.remove("bad")
+ span.textContent = "span classList is \"" + classes + '"';
+ }
+ </script>
+ </body>
+</html>
diff --git a/test/js/event-onclick-insert.html b/test/js/event-onclick-insert.html
new file mode 100644
index 000000000..62b9d7ee8
--- /dev/null
+++ b/test/js/event-onclick-insert.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<body>
+
+<button onclick="add_paragraph()">Click me!</button>
+
+<script>
+function add_paragraph() {
+ var paragraph = document.createElement("P");
+ var textnode = document.createTextNode("New paragraph!");
+ paragraph.appendChild(textnode);
+ document.body.appendChild(paragraph);
+}
+</script>
+
+</body>
+</html>
+
diff --git a/test/js/index.html b/test/js/index.html
index 2abe954e5..6d2c6541e 100644
--- a/test/js/index.html
+++ b/test/js/index.html
@@ -104,6 +104,9 @@
<li><a href="assorted-log-doc-write.html">console.log and document.write</a></li>
<li><a href="wikipedia-lcm.html">Example from wikipedia</a></li>
<li><a href="verify-instanceofness.html">Check instanceof behaviour</a></li>
+<li><a href="class-list.html">Class list (and other token lists?)</a></li>
+<li><a href="mandelbrot.html">Canvas/ImageData Mandelbrot ploter</a></li>
+<li><a href="life.html">Game of Life</a></li>
</ul>
</body>
diff --git a/test/js/inserted-script-async.js b/test/js/inserted-script-async.js
new file mode 100644
index 000000000..aa6c0a351
--- /dev/null
+++ b/test/js/inserted-script-async.js
@@ -0,0 +1 @@
+console.log("External %s dynamism!", "asynchronous");
diff --git a/test/js/inserted-script-defer.js b/test/js/inserted-script-defer.js
new file mode 100644
index 000000000..2d89edd34
--- /dev/null
+++ b/test/js/inserted-script-defer.js
@@ -0,0 +1 @@
+console.log("External deferred dynamism!");
diff --git a/test/js/inserted-script.html b/test/js/inserted-script.html
new file mode 100644
index 000000000..b1c381aaa
--- /dev/null
+++ b/test/js/inserted-script.html
@@ -0,0 +1,39 @@
+<html>
+ <head>
+ <title>Inserted script test</title>
+ <script>
+ /* After one second, insert an inline script element */
+ setTimeout(function() {
+ var div = document.createElement("DIV");
+ var script = document.createElement("SCRIPT");
+ var textnode = document.createTextNode("console.log(\"Dynamism\");");
+ script.appendChild(textnode);
+ div.appendChild(script);
+ document.body.appendChild(div);
+ }, 1000);
+ /* After two seconds, insert a script element for immediate fetch */
+ setTimeout(function() {
+ var script = document.createElement("SCRIPT");
+ script.setAttribute("src", "inserted-script.js");
+ document.body.appendChild(script);
+ }, 2000);
+ /* After three seconds, insert a script element for async fetch */
+ setTimeout(function() {
+ var script = document.createElement("SCRIPT");
+ script.setAttribute("src", "inserted-script-async.js");
+ script.setAttribute("async", "");
+ document.body.appendChild(script);
+ }, 3000);
+ /* After four seconds, insert a script element for deferred fetch */
+ setTimeout(function() {
+ var script = document.createElement("SCRIPT");
+ script.setAttribute("src", "inserted-script-defer.js");
+ script.setAttribute("defer", "");
+ document.body.appendChild(script);
+ }, 4000);
+ </script>
+ </head>
+ <body>
+ Check the log
+ </body>
+</html>
diff --git a/test/js/inserted-script.js b/test/js/inserted-script.js
new file mode 100644
index 000000000..f3a954827
--- /dev/null
+++ b/test/js/inserted-script.js
@@ -0,0 +1 @@
+console.log("External dynamism!");
diff --git a/test/js/life.html b/test/js/life.html
new file mode 100644
index 000000000..de54d0aae
--- /dev/null
+++ b/test/js/life.html
@@ -0,0 +1,175 @@
+<html>
+ <head>
+ <meta charset="UTF-8" />
+ <title>Conway's Game of Life</title>
+ <link rel="stylesheet" type="text/css" href="resource:internal.css" />
+ <style>
+ canvas#surface {
+ width: 50vmin;
+ height: 50vmin;
+ border: 2px solid black;
+ }
+ </style>
+ </head>
+ <body class="ns-even-bg ns-even-fg ns-border">
+ <h1 class="ns-border">Conway's Game of Life</h1>
+ <div style="margin: 1em;">
+ <div>
+ Run: <input id="running" type="checkbox" checked/><br />
+ Set Size: <input id="width" type="text" size="4" value="50" /> x
+ <input id="height" type="text" size="4" value="50" />
+ <button id="commitsize">Commit</button><br />
+ </div>
+ <div>
+ <canvas id="surface" width="50" height="50">
+ Sorry, you can't play Game of Life if JavaScript is turned off
+ </canvas>
+ </div>
+ <div>
+ <button id="random">Randomise</button>
+ </div>
+ </div>
+ </body>
+ <script>
+ (function () {
+ const running = document.getElementById("running");
+ const iwidth = document.getElementById("width");
+ const iheight = document.getElementById("height");
+ const surface = document.getElementById("surface");
+ const context = surface.getContext("2d");
+ var width = surface.width - 10;
+ var height = surface.height - 10;
+ var frame = context.createImageData(width, height);
+ var drawto = context.createImageData(width, height);
+ var greyto = context.createImageData(width, height);
+ const greylevel = 31;
+
+ function getOffset(x, y) {
+ if (x < 0) {
+ x = width + x;
+ }
+ if (y < 0) {
+ y = height + y;
+ }
+ if (x >= width) {
+ x = x - width;
+ }
+ if (y >= height) {
+ y = y - height;
+ }
+ return (y * width + x) * 4;
+ }
+ function getCell(x, y) {
+ const offset = getOffset(x, y);
+ return frame.data[offset + 3] != 0;
+ }
+ function setCell(x, y) {
+ const offset = getOffset(x, y);
+ drawto.data[offset + 3] = 255;
+ greyto.data[offset + 3] = greylevel;
+ }
+ function clearCell(x, y) {
+ const offset = getOffset(x, y);
+ drawto.data[offset + 3] = 0;
+ greyto.data[offset + 3] = 0;
+ }
+ function countNeighbours(x, y) {
+ return (
+ getCell(x - 1, y - 1) +
+ getCell(x, y - 1) +
+ getCell(x + 1, y - 1) +
+ getCell(x - 1, y) +
+ getCell(x + 1, y) +
+ getCell(x - 1, y + 1) +
+ getCell(x, y + 1) +
+ getCell(x + 1, y + 1)
+ );
+ }
+ function flip() {
+ var temp = frame;
+ context.putImageData(drawto, 5, 5);
+ context.putImageData(greyto, 5 - width, 5 - height); /* top left */
+ context.putImageData(greyto, 5 - width, 5); /* left */
+ context.putImageData(greyto, 5, 5 - height); /* top */
+ context.putImageData(greyto, 5 + width, 5 + height); /* bottom right */
+ context.putImageData(greyto, 5 + width, 5); /* right */
+ context.putImageData(greyto, 5, 5 + height); /* bottom */
+ context.putImageData(greyto, 5 + width, 5 - height); /* top right */
+ context.putImageData(greyto, 5 - width, 5 + height); /* bottom left */
+ frame = drawto;
+ drawto = temp;
+ }
+ /* Game of life is run on a timer */
+ setInterval(function () {
+ if (!running.checked) {
+ return;
+ }
+ console.log("Frame");
+ /* To do a frame of GoL we compute by consuming frame and writing to drawto */
+ for (var y = 0; y < height; y++) {
+ for (var x = 0; x < width; x++) {
+ const neighbours = countNeighbours(x, y);
+ if (getCell(x, y)) {
+ if (neighbours == 2 || neighbours == 3) {
+ setCell(x, y); // live, 2/3 neigh => stay alive
+ } else {
+ clearCell(x, y); // live, <2/>3 neigh => dies
+ }
+ } else {
+ if (neighbours == 3) {
+ setCell(x, y); // dead, 3 neigh => born
+ } else {
+ clearCell(x, y); // dead, !3 neigh => stay dead
+ }
+ }
+ }
+ }
+ flip();
+ }, 100);
+ const randomise = function () {
+ var ofs = 3;
+ for (var y = 0; y < height; y++) {
+ for (var x = 0; x < width; x++) {
+ if (Math.random() < 0.5) {
+ drawto.data[ofs] = 0;
+ } else {
+ drawto.data[ofs] = 255;
+ greyto.data[ofs] = greylevel;
+ }
+ ofs += 4;
+ }
+ }
+ flip();
+ };
+ document.getElementById("random").addEventListener("click", randomise);
+ document
+ .getElementById("commitsize")
+ .addEventListener("click", function () {
+ const iwval = parseInt(iwidth.value, 10);
+ const ihval = parseInt(iheight.value, 10);
+ console.log(width, height, "->", iwval, ihval);
+ if (
+ (iwval != width || ihval != height) &&
+ iwval >= 10 &&
+ iwval <= 200 &&
+ ihval >= 10 &&
+ ihval <= 200
+ ) {
+ console.log("yes");
+ surface.height = ihval + 10;
+ context.height = ihval + 10;
+ height = ihval;
+ surface.width = iwval + 10;
+ context.width = iwval + 10;
+ width = iwval;
+ frame = context.createImageData(width, height);
+ drawto = context.createImageData(width, height);
+ greyto = context.createImageData(width, height);
+ resetGrey();
+ randomise();
+ }
+ });
+ randomise();
+ })();
+ </script>
+</html>
diff --git a/test/js/mandelbrot.html b/test/js/mandelbrot.html
new file mode 100644
index 000000000..38f77eff5
--- /dev/null
+++ b/test/js/mandelbrot.html
@@ -0,0 +1,31 @@
+<html>
+ <head>
+ <title>JS Mandelbrot</title>
+ <script src="https://nerget.com/mandelbrot.js"></script>
+ <script>
+ var drawn = false;
+ var dimension = 2;
+ var cx = -dimension / 2 + 0.5;
+ var cy = -dimension / 2;
+
+ function log(msg) {
+ document.getElementById("log").innerHTML += msg + "<br/>";
+ }
+
+ function draw() {
+ var forceSlowPath = document.getElementById('forceSlowPath').checked;
+ drawMandelbrot(document.getElementById('canvas').getContext('2d'), 200, 200,
+ cx + dimension / 2, cy + dimension / 2, dimension, 500, forceSlowPath);
+ drawn = true;
+ }
+
+ </script>
+ </head>
+ <body>
+ <canvas id="canvas" width="200" height="200" style="border: 1px solid black;"></canvas>
+ <br />
+ <input id="forceSlowPath" type="checkbox">Use slow path.</input> <br />
+ <a href="javascript:draw()">Start</a>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/test/js/settimeout.html b/test/js/settimeout.html
new file mode 100644
index 000000000..1755973c6
--- /dev/null
+++ b/test/js/settimeout.html
@@ -0,0 +1,17 @@
+<html>
+ <head>
+ <title>setTimeout and setInterval</title>
+ <script>
+ var counter = 0;
+ var interval_handle = setInterval(function() {
+ console.log("Called back ", counter, " times");
+ counter = counter + 1;
+ }, 100);
+ setTimeout(function() {clearInterval(interval_handle);}, 10000);
+ </script>
+ </head>
+ <body>
+ Check the log, it should be printing a callback indicator for ten
+ seconds and then stop.
+ </body>
+</html>
diff --git a/test/js/sleepy-async.html b/test/js/sleepy-async.html
new file mode 100644
index 000000000..b94997f05
--- /dev/null
+++ b/test/js/sleepy-async.html
@@ -0,0 +1,13 @@
+<html>
+ <head>
+ <title>
+ Async sleepy script
+ </title>
+ </head>
+ <body>
+ This page is loading a sleepy async script.
+
+ Do not expect it to do anything useful.
+ <script src="https://test.netsurf-browser.org/cgi-bin/sleep.cgi" type="text/javascript" async></script>
+ </body>
+</html>
diff --git a/test/messages.c b/test/messages.c
index ae82d1ede..3ec770a56 100644
--- a/test/messages.c
+++ b/test/messages.c
@@ -118,8 +118,7 @@ START_TEST(message_get_buff_test)
ck_assert_int_eq(res, NSERROR_OK);
buf = messages_get_buff("DefinitelyNotAKey");
- ck_assert_str_eq(buf, "DefinitelyNotAKey");
- free(buf);
+ ck_assert(buf == NULL);
buf = messages_get_buff("NoMemory");
ck_assert_str_eq(buf, "NetSurf is running out of memory. Please free some memory and try again.");
diff --git a/test/monkey-see-monkey-do b/test/monkey-see-monkey-do
new file mode 100755
index 000000000..72b8685ec
--- /dev/null
+++ b/test/monkey-see-monkey-do
@@ -0,0 +1,143 @@
+#!/usr/bin/python3
+
+'''
+NetSurf automated test runner
+
+This script retrives a test plan from the NetSurf infrastructure and
+ executes it using the monkey frontend
+'''
+
+# If you have any poo, fling it now!
+
+import sys
+import getopt
+import multiprocessing as mp
+from urllib import request, parse
+from io import StringIO
+import yaml
+import monkey_driver as driver
+
+# Otherwise let's begin...
+
+BASE_PATH = "https://test.netsurf-browser.org/cgi-bin/monkey-index.cgi"
+MONKEY_PATH = "./nsmonkey"
+
+mp.set_start_method('fork')
+
+def decode_trace_line(l):
+ from re import findall, match
+ from subprocess import getstatusoutput
+
+ caps = findall(r'./nsmonkey\(\+(0x[0-9a-f]+)\)', l);
+ if not caps:
+ return l
+
+ exitcode, output = getstatusoutput(
+ "addr2line -e {} -a -p -f -C {} 2>/dev/null".format(
+ MONKEY_PATH, caps[0]))
+ if exitcode != 0:
+ return './nsmonkey(+{})'.format(caps[0])
+
+ m = match(r'0x(.+): (.+) at (.+):(.+)', output)
+
+ return '{}:{}({})[0x{}]'.format(
+ m.group(3), m.group(4), m.group(2), m.group(1))
+
+def decode_trace(s):
+ return "\n".join(decode_trace_line(l) for l in s.split("\n"))
+
+def child_run_test(verbose, parts):
+ outcapture = StringIO()
+ errcapture = StringIO()
+ oldout = sys.stdout
+ olderr = sys.stderr
+ sys.stdout = outcapture
+ sys.stderr = errcapture
+ try:
+ driver.run_preloaded_test(MONKEY_PATH, parts)
+ except:
+ sys.stdout = oldout
+ sys.stderr = olderr
+ print("FAIL:")
+ print("STDOUT:\n{}\n".format(outcapture.getvalue()))
+ print("STDERR:\n{}\n".format(decode_trace(errcapture.getvalue())))
+ print("RERAISE:")
+ raise
+ else:
+ sys.stdout = oldout
+ sys.stderr = olderr
+ if verbose:
+ print("STDOUT:\n{}\n".format(outcapture.getvalue()))
+
+def run_test(verbose, parts):
+ p = mp.Process(target=child_run_test, args=(verbose, parts, ))
+ p.start()
+ p.join()
+ return p.exitcode
+
+def print_usage():
+ print('Usage:')
+ print(' ' + sys.argv[0] + ' [-v] [-h] [-d <division>] [-g group]')
+
+def parse_argv(argv):
+ verbose = False
+ division = None
+ group = None
+ try:
+ opts, args = getopt.getopt(argv, "hvd:g:", [])
+ except getopt.GetoptError:
+ print_usage()
+ sys.exit(2)
+ for opt, arg in opts:
+ if opt == '-h':
+ print_usage()
+ sys.exit()
+ elif opt in ("-v", "--verbose"):
+ verbose = True
+ elif opt == '-d':
+ division = arg
+ elif opt == '-g':
+ group = arg
+
+ return verbose, division, group
+
+def main():
+ verbose, division, group = parse_argv(sys.argv[1:])
+
+ print("Fetching tests...")
+ data_dict = {}
+ if division is not None:
+ data_dict['division'] = division
+ if group is not None:
+ data_dict['group'] = group
+
+ data = parse.urlencode(data_dict).encode()
+ req = request.Request(BASE_PATH, data=data)
+ index = request.urlopen(req)
+ index = index.read()
+
+ print("Parsing tests...")
+ test_set = yaml.load_all(index, Loader=yaml.SafeLoader)
+
+ print("Running tests...")
+ ret = 0
+ for test in test_set:
+ if test["kind"] == 'group':
+ print("Start group: {}".format(test["group"]))
+ print(" [ {} ]".format(test["description"]))
+ elif test["kind"] == 'test':
+ print(" => Run test: {}".format(test["filename"]))
+ ret = run_test(verbose, test["content"])
+ if ret != 0:
+ break
+
+ if ret != 0:
+ print("FAIL")
+ sys.exit(1)
+ else:
+ print("PASS")
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/test/monkey-tests/401login.yaml b/test/monkey-tests/401login.yaml
new file mode 100644
index 000000000..a9a74cd10
--- /dev/null
+++ b/test/monkey-tests/401login.yaml
@@ -0,0 +1,38 @@
+title: Test the 401 LOGIN functionality
+group: real-world
+steps:
+- action: launch
+ language: en
+- action: window-new
+ tag: win1
+- action: navigate
+ window: win1
+ url: https://httpbin.org/basic-auth/foo/bar
+- action: block
+ conditions:
+ - window: win1
+ status: complete
+- action: plot-check
+ window: win1
+ checks:
+ - text-not-contains: "\"authenticated\": true"
+- action: add-auth
+ url: https://httpbin.org/basic-auth/foo/bar
+ realm: Fake Realm
+ username: foo
+ password: bar
+- action: navigate
+ window: win1
+ url: https://httpbin.org/basic-auth/foo/bar
+- action: block
+ conditions:
+ - window: win1
+ status: complete
+- action: plot-check
+ window: win1
+ checks:
+ - text-contains: "\"authenticated\": true"
+- action: window-close
+ window: win1
+- action: quit
+
diff --git a/test/monkey-tests/cache-test.yaml b/test/monkey-tests/cache-test.yaml
new file mode 100644
index 000000000..372c5a1ba
--- /dev/null
+++ b/test/monkey-tests/cache-test.yaml
@@ -0,0 +1,35 @@
+title: cache test
+group: performance
+steps:
+- action: launch
+ language: en
+- action: timer-start
+ timer: timer1
+- action: window-new
+ tag: win1
+- action: navigate
+ window: win1
+ url: http://www.bbc.co.uk/news
+- action: block
+ conditions:
+ - window: win1
+ status: complete
+- action: timer-stop
+ timer: timer1
+- action: timer-start
+ timer: timer2
+- action: window-new
+ tag: win2
+- action: navigate
+ window: win2
+ url: http://www.bbc.co.uk/news
+- action: block
+ conditions:
+ - window: win2
+ status: complete
+- action: timer-stop
+ timer: timer2
+- action: timer-check
+ condition: timer2 < timer1
+- action: quit
+
diff --git a/test/monkey-tests/inserted-script.yaml b/test/monkey-tests/inserted-script.yaml
new file mode 100644
index 000000000..ac7bb0f7f
--- /dev/null
+++ b/test/monkey-tests/inserted-script.yaml
@@ -0,0 +1,28 @@
+title: run inserted-script test in JS enabled browser
+group: basic
+steps:
+- action: launch
+ args:
+ - "--enable_javascript=1"
+- action: window-new
+ tag: win1
+- action: clear-log
+ window: win1
+- action: navigate
+ window: win1
+ url: about:blank
+- action: block
+ conditions:
+ - window: win1
+ status: complete
+- action: js-exec
+ window: win1
+ cmd: location.assign("file:///home/dsilvers/dev-netsurf/workspace/netsurf/test/js/inserted-script.html")
+- action: block
+ conditions:
+ - window: win1
+ status: complete
+- action: wait-log
+ window: win1
+ substring: deferred
+- action: quit
diff --git a/test/monkey-tests/quit-mid-fetch.yaml b/test/monkey-tests/quit-mid-fetch.yaml
new file mode 100644
index 000000000..cffdae3f2
--- /dev/null
+++ b/test/monkey-tests/quit-mid-fetch.yaml
@@ -0,0 +1,22 @@
+title: quitting mid-fetch
+group: cleanup
+steps:
+- action: repeat
+ min: 0
+ step: 50
+ tag: sleepytimer
+ steps:
+ - action: launch
+ - action: window-new
+ tag: win1
+ - action: navigate
+ window: win1
+ url: http://www.bbc.co.uk/news
+ - action: sleep-ms
+ time: sleepytimer
+ conditions:
+ - window: win1
+ status: complete
+ breaks: sleepytimer
+ - action: quit
+
diff --git a/test/monkey-tests/resource-scheme.yaml b/test/monkey-tests/resource-scheme.yaml
new file mode 100644
index 000000000..791a79cd6
--- /dev/null
+++ b/test/monkey-tests/resource-scheme.yaml
@@ -0,0 +1,34 @@
+title: resource scheme
+group: basic
+steps:
+- action: launch
+ language: en
+- action: window-new
+ tag: win1
+- action: navigate
+ window: win1
+ url: resource:does-not-exist
+- action: block
+ conditions:
+ - window: win1
+ status: complete
+- action: plot-check
+ window: win1
+ checks:
+ - text-contains: Not found
+ - text-contains: Error 404
+- action: navigate
+ window: win1
+ url: resource:netsurf.png
+- action: block
+ conditions:
+ - window: win1
+ status: complete
+- action: plot-check
+ window: win1
+ checks:
+ - bitmap-count: 1
+- action: window-close
+ window: win1
+- action: quit
+
diff --git a/test/monkey-tests/simultanious-fetches.yaml b/test/monkey-tests/simultanious-fetches.yaml
new file mode 100644
index 000000000..57ec6e17f
--- /dev/null
+++ b/test/monkey-tests/simultanious-fetches.yaml
@@ -0,0 +1,35 @@
+title: simultanious page fetches
+group: real-world
+steps:
+- action: launch
+ language: en
+- action: window-new
+ tag: win1
+- action: window-new
+ tag: win2
+- action: window-new
+ tag: win3
+- action: window-new
+ tag: win4
+- action: navigate
+ window: win1
+ url: http://www.bbc.co.uk/news
+- action: navigate
+ window: win2
+ url: http://www.amazon.co.uk/
+- action: navigate
+ window: win3
+ url: http://www.theregister.co.uk/
+- action: navigate
+ window: win4
+ url: http://www.arstechnica.co.uk/
+- action: block
+ conditions:
+ - window: "*all*"
+ status: complete
+- action: window-close
+ window: win1
+- action: window-close
+ window: win2
+- action: quit
+
diff --git a/test/monkey-tests/sslcert.yaml b/test/monkey-tests/sslcert.yaml
new file mode 100644
index 000000000..96df2d651
--- /dev/null
+++ b/test/monkey-tests/sslcert.yaml
@@ -0,0 +1,33 @@
+title: Test the SSL certificate error functionality
+group: real-world
+steps:
+- action: launch
+ language: en
+- action: window-new
+ tag: win1
+- action: navigate
+ window: win1
+ url: https://badssl.com/
+- action: block
+ conditions:
+ - window: win1
+ status: complete
+- action: plot-check
+ window: win1
+ checks:
+ - text-contains: "badssl.com"
+- action: navigate
+ window: win1
+ url: https://expired.badssl.com/
+- action: block
+ conditions:
+ - window: win1
+ status: complete
+- action: plot-check
+ window: win1
+ checks:
+ - text-not-contains: "expired. badssl.com"
+- action: window-close
+ window: win1
+- action: quit
+
diff --git a/test/monkey-tests/start-stop-no-js.yaml b/test/monkey-tests/start-stop-no-js.yaml
new file mode 100644
index 000000000..028e08f8e
--- /dev/null
+++ b/test/monkey-tests/start-stop-no-js.yaml
@@ -0,0 +1,7 @@
+title: start and stop browser without JS
+group: initial
+steps:
+- action: launch
+ options:
+ - enable_javascript=0
+- action: quit
diff --git a/test/monkey-tests/start-stop.yaml b/test/monkey-tests/start-stop.yaml
new file mode 100644
index 000000000..68df47316
--- /dev/null
+++ b/test/monkey-tests/start-stop.yaml
@@ -0,0 +1,6 @@
+title: start and stop browser
+group: basic
+steps:
+- action: launch
+- action: quit
+
diff --git a/test/monkey-tests/state-test.yaml b/test/monkey-tests/state-test.yaml
new file mode 100644
index 000000000..6f25a78d4
--- /dev/null
+++ b/test/monkey-tests/state-test.yaml
@@ -0,0 +1,69 @@
+title: Page state info test
+group: basic
+steps:
+- action: launch
+ language: en
+- action: window-new
+ tag: win1
+- action: navigate
+ window: win1
+ url: about:config
+- action: block
+ conditions:
+ - window: win1
+ status: complete
+- action: page-info-state
+ window: win1
+ match: INTERNAL
+- action: navigate
+ window: win1
+ url: file:///
+- action: block
+ conditions:
+ - window: win1
+ status: complete
+- action: page-info-state
+ window: win1
+ match: LOCAL
+- action: navigate
+ window: win1
+ url: http://test.netsurf-browser.org/html/trivial-document.html
+- action: block
+ conditions:
+ - window: win1
+ status: complete
+- action: page-info-state
+ window: win1
+ match: INSECURE
+- action: navigate
+ window: win1
+ url: https://test.netsurf-browser.org/html/trivial-document.html
+- action: block
+ conditions:
+ - window: win1
+ status: complete
+- action: page-info-state
+ window: win1
+ match: SECURE
+- action: navigate
+ window: win1
+ url: https://test.netsurf-browser.org/html/trivial-document-with-png.html
+- action: block
+ conditions:
+ - window: win1
+ status: complete
+- action: page-info-state
+ window: win1
+ match: SECURE
+- action: navigate
+ window: win1
+ url: https://test.netsurf-browser.org/html/trivial-document-with-http-png.html
+- action: block
+ conditions:
+ - window: win1
+ status: complete
+- action: page-info-state
+ window: win1
+ match: SECURE_ISSUES
+- action: quit
+
diff --git a/test/monkey_driver.py b/test/monkey_driver.py
new file mode 100755
index 000000000..9b810d2a6
--- /dev/null
+++ b/test/monkey_driver.py
@@ -0,0 +1,670 @@
+#!/usr/bin/python3
+#
+# Copyright 2019 Daniel Silverstone <dsilvers@digital-scurf.org>
+#
+# This file is part of NetSurf, http://www.netsurf-browser.org/
+#
+# NetSurf is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# NetSurf is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+runs tests in monkey as defined in a yaml file
+"""
+
+# pylint: disable=locally-disabled, missing-docstring
+
+import os
+import sys
+import getopt
+import time
+import yaml
+
+from monkeyfarmer import Browser
+
+
+class DriverBrowser(Browser):
+ def __init__(self, *args, **kwargs):
+ super(DriverBrowser, self).__init__(*args, **kwargs)
+ self.auth = []
+
+ def add_auth(self, url, realm, username, password):
+ self.auth.append((url, realm, username, password))
+
+ def remove_auth(self, url, realm, username, password):
+ keep = []
+
+ def matches(first, second):
+ if first is None or second is None:
+ return True
+ return first == second
+
+ for (iurl, irealm, iusername, ipassword) in self.auth:
+ if not (matches(url, iurl) or
+ matches(realm, irealm) or
+ matches(username, iusername) or
+ matches(password, ipassword)):
+ keep.append((iurl, irealm, iusername, ipassword))
+ self.auth = keep
+
+ def handle_ready_login(self, logwin):
+ # We have logwin.{url,username,password,realm}
+ # We must logwin.send_{username,password}(xxx)
+ # We may logwin.go()
+ # We may logwin.destroy()
+ def matches(first, second):
+ if first is None or second is None:
+ return True
+ return first == second
+ candidates = []
+ for (url, realm, username, password) in self.auth:
+ score = 0
+ if matches(url, logwin.url):
+ score += 1
+ if matches(realm, logwin.realm):
+ score += 1
+ if matches(username, logwin.username):
+ score += 1
+ if score > 0:
+ candidates.append((score, username, password))
+ if candidates:
+ candidates.sort()
+ (score, username, password) = candidates[-1]
+ print("401: Found candidate {}/{} with score {}".format(username, password, score))
+ logwin.send_username(username)
+ logwin.send_password(password)
+ logwin.go()
+ else:
+ print("401: No candidate found, cancelling login box")
+ logwin.destroy()
+
+
+def print_usage():
+ print('Usage:')
+ print(' ' + sys.argv[0] + ' -m <path to monkey> -t <path to test> [-w <wrapper arguments>]')
+
+
+def parse_argv(argv):
+
+ # pylint: disable=locally-disabled, unused-variable
+
+ path_monkey = ''
+ path_test = ''
+ wrapper = None
+ try:
+ opts, args = getopt.getopt(argv, "hm:t:w:", ["monkey=", "test=", "wrapper="])
+ except getopt.GetoptError:
+ print_usage()
+ sys.exit(2)
+ for opt, arg in opts:
+ if opt == '-h':
+ print_usage()
+ sys.exit()
+ elif opt in ("-m", "--monkey"):
+ path_monkey = arg
+ elif opt in ("-t", "--test"):
+ path_test = arg
+ elif opt in ("-w", "--wrapper"):
+ if wrapper is None:
+ wrapper = []
+ wrapper.extend(arg.split())
+
+ if path_monkey == '':
+ print_usage()
+ sys.exit()
+ if path_test == '':
+ print_usage()
+ sys.exit()
+
+ return path_monkey, path_test, wrapper
+
+
+def load_test_plan(path):
+
+ # pylint: disable=locally-disabled, broad-except
+
+ plan = []
+ with open(path, 'r') as stream:
+ try:
+ plan = (yaml.load(stream, Loader=yaml.CSafeLoader))
+ except Exception as exc:
+ print(exc)
+ return plan
+
+
+def get_indent(ctx):
+ return ' ' * ctx["depth"]
+
+
+def print_test_plan_info(ctx, plan):
+
+ # pylint: disable=locally-disabled, unused-argument
+
+ print('Running test: [' + plan["group"] + '] ' + plan["title"])
+
+
+def assert_browser(ctx):
+ assert ctx['browser'].started
+ assert not ctx['browser'].stopped
+
+
+def conds_met(ctx, conds):
+ # for each condition listed determine if they have been met
+ # efectively this is condition1 | condition2
+ for cond in conds:
+ if 'timer' in cond.keys():
+ timer = cond['timer']
+ elapsed = cond['elapsed']
+ assert_browser(ctx)
+ assert ctx['timers'].get(timer) is not None
+ taken = time.time() - ctx['timers'][timer]["start"]
+ if taken >= elapsed:
+ return True
+ elif 'window' in cond.keys():
+ status = cond['status']
+ window = cond['window']
+ assert status == "complete" or status == "loading" # TODO: Add more status support?
+ if window == "*all*":
+ # all windows must be complete, or any still loading
+ throbbing = False
+ for win in ctx['windows'].items():
+ if win[1].throbbing:
+ throbbing = True
+ # throbbing and want loading => true
+ # not throbbing and want complete => true
+ if (status == "loading") == throbbing:
+ return True
+ else:
+ win = ctx['windows'][window]
+ if win.throbbing == (status == "loading"):
+ return True
+ else:
+ raise AssertionError("Unknown condition: {}".format(repr(cond)))
+
+ return False
+
+
+def run_test_step_action_launch(ctx, step):
+ print(get_indent(ctx) + "Action: " + step["action"])
+
+ # ensure browser is not already launched
+ assert ctx.get('browser') is None
+ assert ctx.get('windows') is None
+
+ # build command line switches list
+ monkey_cmd = [ctx["monkey"]]
+ for option in step.get('launch-options', []):
+ monkey_cmd.append("--{}".format(option))
+ print(get_indent(ctx) + " " + "Command line: " + repr(monkey_cmd))
+
+ # build command environment
+ monkey_env = os.environ.copy()
+ for envkey, envvalue in step.get('environment', {}).items():
+ monkey_env[envkey] = envvalue
+ print(get_indent(ctx) + " " + envkey + "=" + envvalue)
+ if 'language' in step.keys():
+ monkey_env['LANGUAGE'] = step['language']
+
+ # create browser object
+ ctx['browser'] = DriverBrowser(
+ monkey_cmd=monkey_cmd,
+ monkey_env=monkey_env,
+ quiet=True,
+ wrapper=ctx.get("wrapper"))
+ assert_browser(ctx)
+ ctx['windows'] = dict()
+
+ # set user options
+ for option in step.get('options', []):
+ print(get_indent(ctx) + " " + option)
+ ctx['browser'].pass_options(option)
+
+
+def run_test_step_action_window_new(ctx, step):
+
+ # pylint: disable=locally-disabled, invalid-name
+
+ print(get_indent(ctx) + "Action: " + step["action"])
+ tag = step['tag']
+ assert_browser(ctx)
+ assert ctx['windows'].get(tag) is None
+ ctx['windows'][tag] = ctx['browser'].new_window(url=step.get('url'))
+
+
+def run_test_step_action_window_close(ctx, step):
+
+ # pylint: disable=locally-disabled, invalid-name
+
+ print(get_indent(ctx) + "Action: " + step["action"])
+ assert_browser(ctx)
+ tag = step['window']
+ assert ctx['windows'].get(tag) is not None
+ win = ctx['windows'].pop(tag)
+ timeout = int(step.get('timeout', 30))
+ win.kill()
+ win.wait_until_dead(timeout=timeout)
+ assert not win.alive
+
+
+def run_test_step_action_navigate(ctx, step):
+ print(get_indent(ctx) + "Action: " + step["action"])
+ assert_browser(ctx)
+ if 'url' in step.keys():
+ url = step['url']
+ elif 'repeaturl' in step.keys():
+ repeat = ctx['repeats'].get(step['repeaturl'])
+ assert repeat is not None
+ assert repeat.get('values') is not None
+ url = repeat['values'][repeat['i']]
+ else:
+ url = None
+ assert url is not None
+ tag = step['window']
+ print(get_indent(ctx) + " " + tag + " --> " + url)
+ win = ctx['windows'].get(tag)
+ assert win is not None
+ win.go(url)
+
+
+def run_test_step_action_stop(ctx, step):
+ print(get_indent(ctx) + "Action: " + step["action"])
+ assert_browser(ctx)
+ tag = step['window']
+ win = ctx['windows'].get(tag)
+ assert win is not None
+ win.stop()
+
+
+def run_test_step_action_reload(ctx, step):
+ print(get_indent(ctx) + "Action: " + step["action"])
+ assert_browser(ctx)
+ tag = step['window']
+ win = ctx['windows'].get(tag)
+ assert win is not None
+ win.reload()
+
+
+def run_test_step_action_sleep_ms(ctx, step):
+ print(get_indent(ctx) + "Action: " + step["action"])
+ conds = step.get('conditions', {})
+ sleep_time = step['time']
+ sleep = 0
+ have_repeat = False
+ if isinstance(sleep_time, str):
+ assert ctx['repeats'].get(sleep_time) is not None
+ repeat = ctx['repeats'].get(sleep_time)
+ sleep = repeat["i"] / 1000
+ start = repeat["start"]
+ have_repeat = True
+ else:
+ sleep = sleep_time / 1000
+ start = time.time()
+
+ while True:
+ slept = time.time() - start
+ if conds_met(ctx, conds):
+ if have_repeat:
+ ctx['repeats'][sleep_time]["loop"] = False
+ print(get_indent(ctx) + " Condition met after {}s".format(slept))
+ break
+ elif slept > sleep:
+ print(get_indent(ctx) + " Condition not met after {}s".format(sleep))
+ break
+ else:
+ ctx['browser'].farmer.loop(once=True)
+
+
+def run_test_step_action_block(ctx, step):
+ print(get_indent(ctx) + "Action: " + step["action"])
+ conds = step['conditions']
+ assert_browser(ctx)
+
+ while not conds_met(ctx, conds):
+ ctx['browser'].farmer.loop(once=True)
+
+
+def run_test_step_action_repeat(ctx, step):
+ print(get_indent(ctx) + "Action: " + step["action"])
+ tag = step['tag']
+ assert ctx['repeats'].get(tag) is None
+ # initialise the loop continue conditional
+ ctx['repeats'][tag] = {"loop": True, }
+
+ if 'values' in step.keys():
+ # value iterator
+ ctx['repeats'][tag]['values'] = step["values"]
+ ctx['repeats'][tag]["max"] = len(step["values"])
+ ctx['repeats'][tag]["i"] = 0
+ ctx['repeats'][tag]["step"] = 1
+ else:
+ # numeric iterator
+ ctx['repeats'][tag]['values'] = None
+
+ if 'min' in step.keys():
+ ctx['repeats'][tag]["i"] = step["min"]
+ else:
+ ctx['repeats'][tag]["i"] = 0
+
+ if 'step' in step.keys():
+ ctx['repeats'][tag]["step"] = step["step"]
+ else:
+ ctx['repeats'][tag]["step"] = 1
+
+ if 'max' in step.keys():
+ ctx['repeats'][tag]["max"] = step["max"]
+ else:
+ ctx['repeats'][tag]["max"] = None
+
+ while ctx['repeats'][tag]["loop"]:
+ ctx['repeats'][tag]["start"] = time.time()
+ ctx["depth"] += 1
+
+ # run through steps for this iteration
+ for stp in step["steps"]:
+ run_test_step(ctx, stp)
+
+ # increment iterator
+ ctx['repeats'][tag]["i"] += ctx['repeats'][tag]["step"]
+
+ # check for end condition
+ if ctx['repeats'][tag]["max"] is not None:
+ if ctx['repeats'][tag]["i"] >= ctx['repeats'][tag]["max"]:
+ ctx['repeats'][tag]["loop"] = False
+
+ ctx["depth"] -= 1
+
+
+def run_test_step_action_click(ctx, step):
+ print(get_indent(ctx) + "Action: " + step["action"])
+ assert_browser(ctx)
+ win = ctx['windows'][step['window']]
+ targets = step['target']
+ if type(targets) == dict:
+ targets = [targets]
+ button = step.get('button', 'left').upper()
+ kind = step.get('kind', 'single').upper()
+ all_text_list = []
+ bitmaps = []
+ for plot in win.redraw():
+ if plot[0] == 'TEXT':
+ all_text_list.append((int(plot[2]), int(plot[4]), " ".join(plot[6:])))
+ if plot[0] == 'BITMAP':
+ bitmaps.append((int(plot[2]), int(plot[4]), int(plot[6]), int(plot[8])))
+
+ x = None
+ y = None
+
+ for target in targets:
+ if 'bitmap' in target:
+ if x is not None:
+ assert False, "Found more than one thing to click on, oh well"
+ bmap = int(target['bitmap'])
+ assert bmap < 0 or bmap >= len(bitmaps)
+ x = bitmaps[bmap][0] + bitmaps[bmap][2] / 2
+ y = bitmaps[bmap][1] + bitmaps[bmap][3] / 2
+ elif 'text' in target:
+ if x is not None:
+ assert False, "Found more than one thing to click on, oh well"
+ text = target['text']
+ for textentry in all_text_list:
+ if text in textentry[2]:
+ if x is not None:
+ assert False, "Text {} found more than once".format(text)
+ x = textentry[0] + 2
+ y = textentry[1] + 2
+
+ # Now we want to click on the x/y coordinate given
+ print(get_indent(ctx) + " Clicking at {}, {} (button={} kind={})".format(x, y, button, kind))
+ win.click(x, y, button, kind)
+
+
+def run_test_step_action_wait_loading(ctx, step):
+ print(get_indent(ctx) + "Action: " + step["action"])
+ assert_browser(ctx)
+ win = ctx['windows'][step['window']]
+ win.wait_start_loading()
+
+def run_test_step_action_plot_check(ctx, step):
+ print(get_indent(ctx) + "Action: " + step["action"])
+ assert_browser(ctx)
+ win = ctx['windows'][step['window']]
+
+ if 'area' in step.keys():
+ if step["area"] == "extent":
+ # ought to capture the extent updates and use that, instead use a
+ # big area and have the browser clip it
+ area=["0","0","1000","1000000"]
+ else:
+ area = [step["area"]]
+ else:
+ area = None
+
+ # get the list of checks
+ if 'checks' in step.keys():
+ checks = step['checks']
+ else:
+ checks = {}
+
+ all_text_list = []
+ bitmaps = []
+ for plot in win.redraw(coords=area):
+ if plot[0] == 'TEXT':
+ all_text_list.extend(plot[6:])
+ if plot[0] == 'BITMAP':
+ bitmaps.append(plot[1:])
+ all_text = " ".join(all_text_list)
+ for check in checks:
+ if 'text-contains' in check.keys():
+ print(" Check {} in {}".format(repr(check['text-contains']), repr(all_text)))
+ assert check['text-contains'] in all_text
+ elif 'text-not-contains' in check.keys():
+ print(" Check {} NOT in {}".format(repr(check['text-not-contains']), repr(all_text)))
+ assert check['text-not-contains'] not in all_text
+ elif 'bitmap-count' in check.keys():
+ print(" Check bitmap count is {}".format(int(check['bitmap-count'])))
+ assert len(bitmaps) == int(check['bitmap-count'])
+ else:
+ raise AssertionError("Unknown check: {}".format(repr(check)))
+
+
+def run_test_step_action_timer_start(ctx, step):
+
+ # pylint: disable=locally-disabled, invalid-name
+
+ print(get_indent(ctx) + "Action: " + step["action"])
+ tag = step['timer']
+ assert_browser(ctx)
+ assert ctx['timers'].get(tag) is None
+ ctx['timers'][tag] = {}
+ ctx['timers'][tag]["start"] = time.time()
+
+
+def run_test_step_action_timer_restart(ctx, step):
+
+ # pylint: disable=locally-disabled, invalid-name
+
+ print(get_indent(ctx) + "Action: " + step["action"])
+ timer = step['timer']
+ assert_browser(ctx)
+ assert ctx['timers'].get(timer) is not None
+ taken = time.time() - ctx['timers'][timer]["start"]
+ print("{} {} restarted at: {:.2f}s".format(get_indent(ctx), timer, taken))
+ ctx['timers'][timer]["taken"] = taken
+ ctx['timers'][timer]["start"] = time.time()
+
+
+def run_test_step_action_timer_stop(ctx, step):
+ print(get_indent(ctx) + "Action: " + step["action"])
+ timer = step['timer']
+ assert_browser(ctx)
+ assert ctx['timers'].get(timer) is not None
+ taken = time.time() - ctx['timers'][timer]["start"]
+ print("{} {} took: {:.2f}s".format(get_indent(ctx), timer, taken))
+ ctx['timers'][timer]["taken"] = taken
+
+
+def run_test_step_action_timer_check(ctx, step):
+
+ # pylint: disable=locally-disabled, invalid-name
+
+ print(get_indent(ctx) + "Action: " + step["action"])
+ condition = step["condition"].split()
+ assert len(condition) == 3
+ timer1 = ctx['timers'].get(condition[0])
+ timer2 = ctx['timers'].get(condition[2])
+ assert timer1 is not None
+ assert timer2 is not None
+ assert timer1["taken"] is not None
+ assert timer2["taken"] is not None
+ assert condition[1] in ('<', '>')
+ if condition[1] == '<':
+ assert timer1["taken"] < timer2["taken"]
+ elif condition[1] == '>':
+ assert timer1["taken"] > timer2["taken"]
+
+
+def run_test_step_action_add_auth(ctx, step):
+ print(get_indent(ctx) + "Action:" + step["action"])
+ assert_browser(ctx)
+ browser = ctx['browser']
+ browser.add_auth(step.get("url"), step.get("realm"),
+ step.get("username"), step.get("password"))
+
+
+def run_test_step_action_remove_auth(ctx, step):
+
+ # pylint: disable=locally-disabled, invalid-name
+
+ print(get_indent(ctx) + "Action:" + step["action"])
+ assert_browser(ctx)
+ browser = ctx['browser']
+ browser.remove_auth(step.get("url"), step.get("realm"),
+ step.get("username"), step.get("password"))
+
+
+def run_test_step_action_clear_log(ctx, step):
+ print(get_indent(ctx) + "Action: " + step["action"])
+ assert_browser(ctx)
+ tag = step['window']
+ print(get_indent(ctx) + " " + tag + " Log cleared")
+ win = ctx['windows'].get(tag)
+ assert win is not None
+ win.clear_log()
+
+
+def run_test_step_action_wait_log(ctx, step):
+ print(get_indent(ctx) + "Action: " + step["action"])
+ assert_browser(ctx)
+ tag = step['window']
+ source = step.get('source')
+ foldable = step.get('foldable')
+ level = step.get('level')
+ substr = step.get('substring')
+ print(get_indent(ctx) + " " + tag + " Wait for logging")
+ win = ctx['windows'].get(tag)
+ assert win is not None
+ win.wait_for_log(source=source, foldable=foldable, level=level, substr=substr)
+
+
+def run_test_step_action_js_exec(ctx, step):
+ print(get_indent(ctx) + "Action: " + step["action"])
+ assert_browser(ctx)
+ tag = step['window']
+ cmd = step['cmd']
+ print(get_indent(ctx) + " " + tag + " Run " + cmd)
+ win = ctx['windows'].get(tag)
+ assert win is not None
+ win.js_exec(cmd)
+
+
+def run_test_step_action_page_info_state(ctx, step):
+ print(get_indent(ctx) + "Action: " + step["action"])
+ assert_browser(ctx)
+ tag = step['window']
+ win = ctx['windows'].get(tag)
+ assert win is not None
+ match = step['match']
+ assert win.page_info_state == match
+
+
+def run_test_step_action_quit(ctx, step):
+ print(get_indent(ctx) + "Action: " + step["action"])
+ assert_browser(ctx)
+ browser = ctx.pop('browser')
+ assert browser.quit_and_wait()
+ # clean up context as all windows have gone away after browser quit
+ ctx.pop('windows')
+
+
+STEP_HANDLERS = {
+ "launch": run_test_step_action_launch,
+ "window-new": run_test_step_action_window_new,
+ "window-close": run_test_step_action_window_close,
+ "navigate": run_test_step_action_navigate,
+ "reload": run_test_step_action_reload,
+ "stop": run_test_step_action_stop,
+ "sleep-ms": run_test_step_action_sleep_ms,
+ "block": run_test_step_action_block,
+ "repeat": run_test_step_action_repeat,
+ "timer-start": run_test_step_action_timer_start,
+ "timer-restart": run_test_step_action_timer_restart,
+ "timer-stop": run_test_step_action_timer_stop,
+ "timer-check": run_test_step_action_timer_check,
+ "plot-check": run_test_step_action_plot_check,
+ "click": run_test_step_action_click,
+ "wait-loading": run_test_step_action_wait_loading,
+ "add-auth": run_test_step_action_add_auth,
+ "remove-auth": run_test_step_action_remove_auth,
+ "clear-log": run_test_step_action_clear_log,
+ "wait-log": run_test_step_action_wait_log,
+ "js-exec": run_test_step_action_js_exec,
+ "page-info-state":
+ run_test_step_action_page_info_state,
+ "quit": run_test_step_action_quit,
+}
+
+
+def run_test_step(ctx, step):
+ STEP_HANDLERS[step["action"]](ctx, step)
+
+
+def walk_test_plan(ctx, plan):
+ ctx["depth"] = 0
+ ctx["timers"] = dict()
+ ctx['repeats'] = dict()
+ for step in plan["steps"]:
+ run_test_step(ctx, step)
+
+
+def run_test_plan(ctx, plan):
+ print_test_plan_info(ctx, plan)
+ walk_test_plan(ctx, plan)
+
+
+def run_preloaded_test(path_monkey, plan):
+ ctx = {
+ "monkey": path_monkey,
+ }
+ run_test_plan(ctx, plan)
+
+
+def main(argv):
+ ctx = {}
+ path_monkey, path_test, wrapper = parse_argv(argv)
+ plan = load_test_plan(path_test)
+ ctx["monkey"] = path_monkey
+ ctx["wrapper"] = wrapper
+ run_test_plan(ctx, plan)
+
+
+# Some python weirdness to get to main().
+if __name__ == "__main__":
+ main(sys.argv[1:])
diff --git a/test/monkeyfarmer.py b/test/monkeyfarmer.py
new file mode 100644
index 000000000..905fd9a81
--- /dev/null
+++ b/test/monkeyfarmer.py
@@ -0,0 +1,661 @@
+# Copyright 2017-2019 Daniel Silverstone <dsilvers@digital-scurf.org>
+#
+# This file is part of NetSurf, http://www.netsurf-browser.org/
+#
+# NetSurf is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# NetSurf is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Monkey Farmer
+
+The monkey farmer is a wrapper around `nsmonkey` which can be used to simplify
+access to the monkey behaviours and ultimately to write useful tests in an
+expressive but not overcomplicated DSLish way. Tests are, ultimately, still
+Python code.
+
+"""
+
+# pylint: disable=locally-disabled, missing-docstring
+
+import asyncore
+import os
+import socket
+import subprocess
+import time
+import errno
+import sys
+
+class StderrEcho(asyncore.dispatcher):
+ def __init__(self, sockend):
+ asyncore.dispatcher.__init__(self, sock=sockend)
+ self.incoming = b""
+
+ def handle_connect(self):
+ pass
+
+ def handle_close(self):
+ # the pipe to the monkey process has closed
+ self.close()
+
+ def handle_read(self):
+ try:
+ got = self.recv(8192)
+ if not got:
+ return
+ except socket.error as error:
+ if error.errno == errno.EAGAIN or error.errno == errno.EWOULDBLOCK:
+ return
+ else:
+ raise
+
+ self.incoming += got
+ if b"\n" in self.incoming:
+ lines = self.incoming.split(b"\n")
+ self.incoming = lines.pop()
+ for line in lines:
+ try:
+ line = line.decode('utf-8')
+ except UnicodeDecodeError:
+ print("WARNING: Unicode decode error")
+ line = line.decode('utf-8', 'replace')
+
+ sys.stderr.write("{}\n".format(line))
+
+
+class MonkeyFarmer(asyncore.dispatcher):
+
+ # pylint: disable=locally-disabled, too-many-instance-attributes
+
+ def __init__(self, monkey_cmd, monkey_env, online, quiet=False, *, wrapper=None):
+ (mine, monkeys) = socket.socketpair()
+
+ asyncore.dispatcher.__init__(self, sock=mine)
+
+ (mine2, monkeyserr) = socket.socketpair()
+
+ self._errwrapper = StderrEcho(mine2)
+
+ if wrapper is not None:
+ new_cmd = list(wrapper)
+ new_cmd.extend(monkey_cmd)
+ monkey_cmd = new_cmd
+
+ self.monkey = subprocess.Popen(
+ monkey_cmd,
+ env=monkey_env,
+ stdin=monkeys,
+ stdout=monkeys,
+ stderr=monkeyserr,
+ close_fds=[mine, mine2])
+
+ monkeys.close()
+ monkeyserr.close()
+
+ self.buffer = b""
+ self.incoming = b""
+ self.lines = []
+ self.scheduled = []
+ self.deadmonkey = False
+ self.online = online
+ self.quiet = quiet
+ self.discussion = []
+ self.maybe_slower = wrapper is not None
+
+ def handle_connect(self):
+ pass
+
+ def handle_close(self):
+ # the pipe to the monkey process has closed
+ self.close()
+
+ def handle_read(self):
+ try:
+ got = self.recv(8192)
+ if not got:
+ self.deadmonkey = True
+ # ensure the child process is finished and report the exit
+ if self.monkey.poll() is None:
+ self.monkey.terminate()
+ self.monkey.wait()
+ print("Handling an exit {}".format(self.monkey.returncode))
+ print("The following are present in the queue: {}".format(self.lines))
+ self.lines.append("GENERIC EXIT {}".format(
+ self.monkey.returncode).encode('utf-8'))
+ print("The queue is now: {}".format(self.lines))
+ return
+ except socket.error as error:
+ if error.errno == errno.EAGAIN or error.errno == errno.EWOULDBLOCK:
+ return
+ else:
+ raise
+
+ self.incoming += got
+ if b"\n" in self.incoming:
+ lines = self.incoming.split(b"\n")
+ self.incoming = lines.pop()
+ self.lines.extend(lines)
+
+ def writable(self):
+ return len(self.buffer) > 0
+
+ def handle_write(self):
+ sent = self.send(self.buffer)
+ self.buffer = self.buffer[sent:]
+
+ def tell_monkey(self, *args):
+ cmd = (" ".join(args))
+ if not self.quiet:
+ print(">>> {}".format(cmd))
+ self.discussion.append((">", cmd))
+ cmd = cmd + "\n"
+ self.buffer += cmd.encode('utf-8')
+
+ def monkey_says(self, line):
+ try:
+ line = line.decode('utf-8')
+ except UnicodeDecodeError:
+ print("WARNING: Unicode decode error")
+ line = line.decode('utf-8', 'replace')
+ if not self.quiet:
+ print("<<< {}".format(line))
+ self.discussion.append(("<", line))
+ self.online(line)
+
+ def schedule_event(self, event, secs=None, when=None):
+ assert secs is not None or when is not None
+ if when is None:
+ when = time.time() + secs
+ self.scheduled.append((when, event))
+ self.scheduled.sort()
+
+ def unschedule_event(self, event):
+ self.scheduled = [x for x in self.scheduled if x[1] != event]
+
+ def loop(self, once=False):
+ if len(self.lines) > 0:
+ self.monkey_says(self.lines.pop(0))
+ if once:
+ return
+ while not self.deadmonkey:
+ now = time.time()
+ while len(self.scheduled) > 0 and now >= self.scheduled[0][0]:
+ func = self.scheduled[0][1]
+ self.scheduled.pop(0)
+ func(self)
+ now = time.time()
+ if len(self.scheduled) > 0:
+ next_event = self.scheduled[0][0]
+ asyncore.loop(timeout=next_event - now, count=1)
+ else:
+ asyncore.loop(count=1)
+ while len(self.lines) > 0:
+ self.monkey_says(self.lines.pop(0))
+ if once or self.deadmonkey:
+ return
+
+
+class Browser:
+
+ # pylint: disable=locally-disabled, too-many-instance-attributes, dangerous-default-value, invalid-name
+
+ def __init__(self, monkey_cmd=["./nsmonkey"], monkey_env=None, quiet=False, *, wrapper=None):
+ self.farmer = MonkeyFarmer(
+ monkey_cmd=monkey_cmd,
+ monkey_env=monkey_env,
+ online=self.on_monkey_line,
+ quiet=quiet,
+ wrapper=wrapper)
+ self.windows = {}
+ self.logins = {}
+ self.current_draw_target = None
+ self.started = False
+ self.stopped = False
+ self.launchurl = None
+ now = time.time()
+ timeout = now + 1
+
+ if wrapper is not None:
+ timeout = now + 10
+
+ while not self.started:
+ self.farmer.loop(once=True)
+ if time.time() > timeout:
+ break
+
+ def pass_options(self, *opts):
+ if len(opts) > 0:
+ self.farmer.tell_monkey("OPTIONS " + (" ".join(['--' + opt for opt in opts])))
+
+ def on_monkey_line(self, line):
+ parts = line.split(" ")
+ handler = getattr(self, "handle_" + parts[0], None)
+ if handler is not None:
+ handler(*parts[1:])
+
+ def quit(self):
+ self.farmer.tell_monkey("QUIT")
+
+ def quit_and_wait(self):
+ self.quit()
+ self.farmer.loop()
+ return self.stopped
+
+ def handle_GENERIC(self, what, *args):
+ if what == 'STARTED':
+ self.started = True
+ elif what == 'FINISHED':
+ self.stopped = True
+ elif what == 'LAUNCH':
+ self.launchurl = args[1]
+ elif what == 'EXIT':
+ if not self.stopped:
+ print("Unexpected exit of monkey process with code {}".format(args[0]))
+ assert self.stopped
+ else:
+ pass
+
+ def handle_WINDOW(self, action, _win, winid, *args):
+ if action == "NEW":
+ new_win = BrowserWindow(self, winid, *args)
+ self.windows[winid] = new_win
+ else:
+ win = self.windows.get(winid, None)
+ if win is None:
+ print(" Unknown window id {}".format(winid))
+ else:
+ win.handle(action, *args)
+
+ def handle_LOGIN(self, action, _lwin, winid, *args):
+ if action == "OPEN":
+ new_win = LoginWindow(self, winid, *args)
+ self.logins[winid] = new_win
+ else:
+ win = self.logins.get(winid, None)
+ if win is None:
+ print(" Unknown login window id {}".format(winid))
+ else:
+ win.handle(action, *args)
+ if win.alive and win.ready:
+ self.handle_ready_login(win)
+
+ def handle_PLOT(self, *args):
+ if self.current_draw_target is not None:
+ self.current_draw_target.handle_plot(*args)
+
+ def new_window(self, url=None):
+ if url is None:
+ self.farmer.tell_monkey("WINDOW NEW")
+ else:
+ self.farmer.tell_monkey("WINDOW NEW %s" % url)
+ wins_known = set(self.windows.keys())
+ while len(set(self.windows.keys()).difference(wins_known)) == 0:
+ self.farmer.loop(once=True)
+ poss_wins = set(self.windows.keys()).difference(wins_known)
+ return self.windows[poss_wins.pop()]
+
+ def handle_ready_login(self, lwin):
+
+ # pylint: disable=locally-disabled, no-self-use
+
+ # Override this method to do useful stuff
+ lwin.destroy()
+
+
+class LoginWindow:
+
+ # pylint: disable=locally-disabled, too-many-instance-attributes, invalid-name
+
+ def __init__(self, browser, winid, _url, *url):
+ self.alive = True
+ self.ready = False
+ self.browser = browser
+ self.winid = winid
+ self.url = " ".join(url)
+ self.username = None
+ self.password = None
+ self.realm = None
+
+ def handle(self, action, _str="STR", *rest):
+ content = " ".join(rest)
+ if action == "USER":
+ self.username = content
+ elif action == "PASS":
+ self.password = content
+ elif action == "REALM":
+ self.realm = content
+ elif action == "DESTROY":
+ self.alive = False
+ else:
+ raise AssertionError("Unknown action {} for login window".format(action))
+ if not (self.username is None or self.password is None or self.realm is None):
+ self.ready = True
+
+ def send_username(self, username=None):
+ assert self.alive
+ if username is None:
+ username = self.username
+ self.browser.farmer.tell_monkey("LOGIN USERNAME {} {}".format(self.winid, username))
+
+ def send_password(self, password=None):
+ assert self.alive
+ if password is None:
+ password = self.password
+ self.browser.farmer.tell_monkey("LOGIN PASSWORD {} {}".format(self.winid, password))
+
+ def _wait_dead(self):
+ while self.alive:
+ self.browser.farmer.loop(once=True)
+
+ def go(self):
+ assert self.alive
+ self.browser.farmer.tell_monkey("LOGIN GO {}".format(self.winid))
+ self._wait_dead()
+
+ def destroy(self):
+ assert self.alive
+ self.browser.farmer.tell_monkey("LOGIN DESTROY {}".format(self.winid))
+ self._wait_dead()
+
+
+class BrowserWindow:
+
+ # pylint: disable=locally-disabled, too-many-instance-attributes, too-many-public-methods, invalid-name
+
+ def __init__(
+ self,
+ browser,
+ winid,
+ _for,
+ coreid,
+ _existing,
+ otherid,
+ _newtab,
+ newtab,
+ _clone,
+ clone):
+ # pylint: disable=locally-disabled, too-many-arguments
+ self.alive = True
+ self.browser = browser
+ self.winid = winid
+ self.coreid = coreid
+ self.existing = browser.windows.get(otherid, None)
+ self.newtab = newtab == "TRUE"
+ self.clone = clone == "TRUE"
+ self.width = 0
+ self.height = 0
+ self.title = ""
+ self.throbbing = False
+ self.scrollx = 0
+ self.scrolly = 0
+ self.content_width = 0
+ self.content_height = 0
+ self.status = ""
+ self.pointer = ""
+ self.scale = 1.0
+ self.url = ""
+ self.plotted = []
+ self.plotting = False
+ self.log_entries = []
+ self.page_info_state = "UNKNOWN"
+
+ def kill(self):
+ self.browser.farmer.tell_monkey("WINDOW DESTROY %s" % self.winid)
+
+ def wait_until_dead(self, timeout=1):
+ now = time.time()
+ while self.alive:
+ self.browser.farmer.loop(once=True)
+ if (time.time() - now) > timeout:
+ print("*** Timed out waiting for window to be destroyed")
+ print("*** URL was: {}".format(self.url))
+ print("*** Title was: {}".format(self.title))
+ print("*** Status was: {}".format(self.status))
+ break
+
+ def go(self, url, referer=None):
+ if referer is None:
+ self.browser.farmer.tell_monkey("WINDOW GO %s %s" % (
+ self.winid, url))
+ else:
+ self.browser.farmer.tell_monkey("WINDOW GO %s %s %s" % (
+ self.winid, url, referer))
+ self.wait_start_loading()
+
+ def stop(self):
+ self.browser.farmer.tell_monkey("WINDOW STOP %s" % (self.winid))
+
+ def reload(self, all=False):
+ all = " ALL" if all else ""
+ self.browser.farmer.tell_monkey("WINDOW RELOAD %s%s" % (self.winid, all))
+ self.wait_start_loading()
+
+ def click(self, x, y, button="LEFT", kind="SINGLE"):
+ self.browser.farmer.tell_monkey("WINDOW CLICK WIN %s X %s Y %s BUTTON %s KIND %s" % (self.winid, x, y, button, kind))
+
+ def js_exec(self, src):
+ self.browser.farmer.tell_monkey("WINDOW EXEC WIN %s %s" % (self.winid, src))
+
+ def handle(self, action, *args):
+ handler = getattr(self, "handle_window_" + action, None)
+ if handler is not None:
+ handler(*args)
+
+ def handle_window_SIZE(self, _width, width, _height, height):
+ self.width = int(width)
+ self.height = int(height)
+
+ def handle_window_DESTROY(self):
+ self.alive = False
+
+ def handle_window_TITLE(self, _str, *title):
+ self.title = " ".join(title)
+
+ def handle_window_GET_DIMENSIONS(self, _width, width, _height, height):
+ self.width = width
+ self.height = height
+
+ def handle_window_NEW_CONTENT(self):
+ pass
+
+ def handle_window_NEW_ICON(self):
+ pass
+
+ def handle_window_START_THROBBER(self):
+ self.throbbing = True
+
+ def handle_window_STOP_THROBBER(self):
+ self.throbbing = False
+
+ def handle_window_SET_SCROLL(self, _x, x, _y, y):
+ self.scrollx = int(x)
+ self.scrolly = int(y)
+
+ def handle_window_UPDATE_BOX(self, _x, x, _y, y, _width, width, _height, height):
+ # pylint: disable=locally-disabled, no-self-use
+
+ x = int(x)
+ y = int(y)
+ width = int(width)
+ height = int(height)
+
+ def handle_window_UPDATE_EXTENT(self, _width, width, _height, height):
+ self.content_width = int(width)
+ self.content_height = int(height)
+
+ def handle_window_SET_STATUS(self, _str, *status):
+ self.status = (" ".join(status))
+
+ def handle_window_SET_POINTER(self, _ptr, ptr):
+ self.pointer = ptr
+
+ def handle_window_SET_SCALE(self, _scale, scale):
+ self.scale = float(scale)
+
+ def handle_window_SET_URL(self, _url, url):
+ self.url = url
+
+ def handle_window_GET_SCROLL(self, _x, x, _y, y):
+ self.scrollx = int(x)
+ self.scrolly = int(y)
+
+ def handle_window_SCROLL_START(self):
+ self.scrollx = 0
+ self.scrolly = 0
+
+ def handle_window_REDRAW(self, act):
+ if act == "START":
+ self.browser.current_draw_target = self
+ self.plotted = []
+ self.plotting = True
+ else:
+ self.browser.current_draw_target = None
+ self.plotting = False
+
+ def handle_window_CONSOLE_LOG(self, _src, src, folding, level, *msg):
+ self.log_entries.append((src, folding == "FOLDABLE", level, " ".join(msg)))
+
+ def handle_window_PAGE_STATUS(self, _status, status):
+ self.page_info_state = status
+
+ def load_page(self, url=None, referer=None):
+ if url is not None:
+ self.go(url, referer)
+ self.wait_loaded()
+
+ def wait_start_loading(self):
+ while not self.throbbing:
+ self.browser.farmer.loop(once=True)
+
+ def wait_loaded(self):
+ self.wait_start_loading()
+ while self.throbbing:
+ self.browser.farmer.loop(once=True)
+
+ def handle_plot(self, *args):
+ self.plotted.append(args)
+
+ def redraw(self, coords=None):
+ if coords is None:
+ self.browser.farmer.tell_monkey("WINDOW REDRAW %s" % self.winid)
+ else:
+ self.browser.farmer.tell_monkey("WINDOW REDRAW %s %s" % (
+ self.winid, (" ".join(coords))))
+ while not self.plotting:
+ self.browser.farmer.loop(once=True)
+ while self.plotting:
+ self.browser.farmer.loop(once=True)
+ return self.plotted
+
+ def clear_log(self):
+ self.log_entries = []
+
+ def log_contains(self, source=None, foldable=None, level=None, substr=None):
+ if (source is None) and (foldable is None) and (level is None) and (substr is None):
+ assert False, "Unable to run log_contains, no predicate given"
+
+ for (source_, foldable_, level_, msg_) in self.log_entries:
+ ok = True
+ if (source is not None) and (source != source_):
+ ok = False
+ if (foldable is not None) and (foldable != foldable_):
+ ok = False
+ if (level is not None) and (level != level_):
+ ok = False
+ if (substr is not None) and (substr not in msg_):
+ ok = False
+ if ok:
+ return True
+
+ return False
+
+ def wait_for_log(self, source=None, foldable=None, level=None, substr=None):
+ while not self.log_contains(source=source, foldable=foldable, level=level, substr=substr):
+ self.browser.farmer.loop(once=True)
+
+
+def farmer_test():
+ '''
+ Simple farmer test
+ '''
+
+ browser = Browser(quiet=True)
+ win = browser.new_window()
+
+ fname = "test/js/inline-doc-write-simple.html"
+ full_fname = os.path.join(os.getcwd(), fname)
+
+ browser.pass_options("--enable_javascript=0")
+ win.load_page("file://" + full_fname)
+
+ print("Loaded, URL is {}".format(win.url))
+
+ cmds = win.redraw()
+ print("Received {} plot commands".format(len(cmds)))
+ for cmd in cmds:
+ if cmd[0] == "TEXT":
+ text_x = cmd[2]
+ text_y = cmd[4]
+ rest = " ".join(cmd[6:])
+ print("{} {} -> {}".format(text_x, text_y, rest))
+
+ browser.pass_options("--enable_javascript=1")
+ win.load_page("file://" + full_fname)
+
+ print("Loaded, URL is {}".format(win.url))
+
+ cmds = win.redraw()
+ print("Received {} plot commands".format(len(cmds)))
+ for cmd in cmds:
+ if cmd[0] == "TEXT":
+ text_x = cmd[2]
+ text_y = cmd[4]
+ rest = " ".join(cmd[6:])
+ print("{} {} -> {}".format(text_x, text_y, rest))
+
+ browser.quit_and_wait()
+
+ class FooBarLogin(Browser):
+ def handle_ready_login(self, lwin):
+ lwin.send_username("foo")
+ lwin.send_password("bar")
+ lwin.go()
+
+ fbbrowser = FooBarLogin(quiet=True)
+ win = fbbrowser.new_window()
+ win.load_page("https://httpbin.org/basic-auth/foo/bar")
+ cmds = win.redraw()
+ print("Received {} plot commands for auth test".format(len(cmds)))
+ for cmd in cmds:
+ if cmd[0] == "TEXT":
+ text_x = cmd[2]
+ text_y = cmd[4]
+ rest = " ".join(cmd[6:])
+ print("{} {} -> {}".format(text_x, text_y, rest))
+
+ fname = "test/js/inserted-script.html"
+ full_fname = os.path.join(os.getcwd(), fname)
+
+ browser = Browser(quiet=True)
+ browser.pass_options("--enable_javascript=1")
+ win = browser.new_window()
+ win.load_page("file://" + full_fname)
+ print("Loaded, URL is {}".format(win.url))
+
+ win.wait_for_log(substr="deferred")
+
+ # print("Discussion was:")
+ # for line in browser.farmer.discussion:
+ # print("{} {}".format(line[0], line[1]))
+
+
+if __name__ == '__main__':
+ farmer_test()
diff --git a/test/nsoption.c b/test/nsoption.c
index 8f2388a5b..33da1f7e0 100644
--- a/test/nsoption.c
+++ b/test/nsoption.c
@@ -33,6 +33,10 @@
#include "utils/log.h"
#include "utils/nsoption.h"
+#ifndef TESTROOT
+#define TESTROOT "/tmp"
+#endif
+
const char *test_choices_path = "test/data/Choices";
const char *test_choices_short_path = "test/data/Choices-short";
const char *test_choices_all_path = "test/data/Choices-all";
@@ -49,7 +53,9 @@ static char *testnam(char *out)
{
static int count = 0;
static char name[64];
- snprintf(name, 64, "/tmp/nsoptiontest%d", count);
+ int pid;
+ pid=getpid();
+ snprintf(name, 64, TESTROOT"/nsoptiontest%d%d", pid, count);
count++;
return name;
}
@@ -241,7 +247,7 @@ struct format_test_vec_s format_test_vec[] = {
},
{
NSOPTION_sys_colour_ActiveBorder,
- "<tr><th>sys_colour_ActiveBorder</th><td>colour</td><td>default</td><td><span style=\"background-color: #d3d3d3; color: #000000; font-family:Monospace; \">#D3D3D3</span></td></tr>",
+ "<tr><th>sys_colour_ActiveBorder</th><td>colour</td><td>default</td><td><span style=\"font-family:Monospace;\">#D3D3D3</span> <span style=\"background-color: #d3d3d3; border: 1px solid #000000; display: inline-block; width: 1em; height: 1em;\"></span></td></tr>",
"sys_colour_ActiveBorder:d3d3d3"
},
};
diff --git a/test/nsurl.c b/test/nsurl.c
index ba024291b..631e7ae2c 100644
--- a/test/nsurl.c
+++ b/test/nsurl.c
@@ -428,9 +428,9 @@ static const struct test_pairs join_tests[] = {
{ " ", "http://a/b/c/d;p?q" },
{ "/", "http://a/" },
{ " / ", "http://a/" },
- { " ? ", "http://a/b/c/d;p?" },
+ { " ? ", "http://a/b/c/d;p" },
{ " h ", "http://a/b/c/h" },
- { "//foo?", "http://foo/?" },
+ { "//foo?", "http://foo/" },
{ "//foo#bar", "http://foo/#bar" },
{ "//foo/", "http://foo/" },
{ "http://<!--#echo var=", "http://<!--/#echo%20var="},
@@ -531,21 +531,25 @@ END_TEST
*/
static const struct test_triplets replace_query_tests[] = {
{ "http://netsurf-browser.org/?magical=true",
- "?magical=true&result=win",
+ "magical=true&result=win",
"http://netsurf-browser.org/?magical=true&result=win"},
{ "http://netsurf-browser.org/?magical=true#fragment",
- "?magical=true&result=win",
+ "magical=true&result=win",
"http://netsurf-browser.org/?magical=true&result=win#fragment"},
{ "http://netsurf-browser.org/#fragment",
- "?magical=true&result=win",
+ "magical=true&result=win",
"http://netsurf-browser.org/?magical=true&result=win#fragment"},
{ "http://netsurf-browser.org/path",
- "?magical=true",
+ "magical=true",
"http://netsurf-browser.org/path?magical=true"},
+ { "http://netsurf-browser.org/path?magical=true",
+ "",
+ "http://netsurf-browser.org/path"},
+
};
/**
@@ -655,7 +659,7 @@ static const struct test_compare component_tests[] = {
{ "http://u:p@a:66/b/c/d;p?q#f", "a", NSURL_HOST, true },
{ "http://u:p@a:66/b/c/d;p?q#f", "66", NSURL_PORT, true },
{ "http://u:p@a:66/b/c/d;p?q#f", "/b/c/d;p", NSURL_PATH, true },
- { "http://u:p@a:66/b/c/d;p?q#f", "?q", NSURL_QUERY, true },
+ { "http://u:p@a:66/b/c/d;p?q#f", "q", NSURL_QUERY, true },
{ "http://u:p@a:66/b/c/d;p?q#f", "f", NSURL_FRAGMENT, true },
{ "file:", "file", NSURL_SCHEME, true },
@@ -667,6 +671,11 @@ static const struct test_compare component_tests[] = {
{ "file:", NULL, NSURL_QUERY, false },
{ "file:", NULL, NSURL_FRAGMENT, false },
+ { "http://u:p@a:66/b/c/d;p?q=v#f", "q=v", NSURL_QUERY, true },
+ { "http://u:p@a:66/b/c/d;p?q=v", "q=v", NSURL_QUERY, true },
+ { "http://u:p@a:66/b/c/d;p?q=v&q1=v1#f", "q=v&q1=v1", NSURL_QUERY, true },
+ { "http://u:p@a:66/b/c/d;p?q=v&q1=v1", "q=v&q1=v1", NSURL_QUERY, true },
+
};
@@ -1167,12 +1176,11 @@ START_TEST(nsurl_api_assert_replace_query3_test)
nsurl *url;
nsurl *res;
nserror err;
- const char *rel = "moo";
err = nsurl_create(base_str, &url);
ck_assert(err == NSERROR_OK);
- err = nsurl_replace_query(url, rel, &res);
+ err = nsurl_replace_query(url, NULL, &res);
ck_assert(err != NSERROR_OK);
nsurl_unref(url);
diff --git a/test/utils.c b/test/utils.c
index 3d5319a28..9fe6747c3 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -37,22 +37,31 @@
#define SLEN(x) (sizeof((x)) - 1)
struct test_pairs {
- const unsigned long test;
+ const unsigned long long int test;
const char* res;
};
static const struct test_pairs human_friendly_bytesize_test_vec[] = {
- { 0, "0.00Bytes" },
- { 1024, "1024.00Bytes" },
- { 1025, "1.00kBytes" },
- { 1048576, "1024.00kBytes" },
- { 1048577, "1.00MBytes" },
- { 1073741824, "1024.00MBytes" },
- { 1073741888, "1024.00MBytes" }, /* spot the rounding error */
- { 1073741889, "1.00GBytes" },
- { 2147483648, "2.00GBytes" },
- { 3221225472, "3.00GBytes" },
- { 4294967295, "4.00GBytes" },
+ { 0ULL, "0Bytes" },
+ { 0x2AULL, "42Bytes" },
+ { 0x400ULL, "1024Bytes" },
+ { 0x401ULL, "1.00KiBytes" },
+ { 0xA9AEULL, "42.42KiBytes" },
+ { 0x100000ULL, "1024.00KiBytes" },
+ { 0x100001ULL, "1.00MiBytes" },
+ { 0x2A6B852ULL, "42.42MiBytes" },
+ { 0x40000000ULL, "1024.00MiBytes" },
+ { 0x40000001ULL, "1.00GiBytes" },
+ { 0x80000000ULL, "2.00GiBytes" },
+ { 0xC0000000ULL, "3.00GiBytes" },
+ { 0x100000000ULL, "4.00GiBytes" },
+ { 0x10000000000ULL, "1024.00GiBytes" },
+ { 0x10000000001ULL, "1.00TiBytes" },
+ { 0x4000000000000ULL, "1024.00TiBytes" },
+ { 0x4000000000001ULL, "1.00PiBytes" },
+ { 0x1000000000000000ULL, "1024.00PiBytes" },
+ { 0x1000000000000100ULL, "1.00EiBytes" }, /* precision loss */
+ { 0xFFFFFFFFFFFFFFFFULL, "16.00EiBytes" },
};
/**
diff --git a/utils/DerivedJoiningType.txt b/tools/DerivedJoiningType.txt
index d4dcc85f6..d4d382bb7 100644
--- a/utils/DerivedJoiningType.txt
+++ b/tools/DerivedJoiningType.txt
@@ -1,10 +1,11 @@
-# DerivedJoiningType-5.2.0.txt
-# Date: 2009-05-28, 20:37:39 GMT [MD]
+# DerivedJoiningType-11.0.0.txt
+# Date: 2018-02-21, 05:34:05 GMT
+# © 2018 Unicode®, Inc.
+# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
#
# Unicode Character Database
-# Copyright (c) 1991-2009 Unicode, Inc.
-# For terms of use, see http://www.unicode.org/terms_of_use.html
-# For documentation, see http://www.unicode.org/reports/tr44/
+# For documentation, see http://www.unicode.org/reports/tr44/
# ================================================
@@ -21,14 +22,16 @@
0640 ; C # Lm ARABIC TATWEEL
07FA ; C # Lm NKO LAJANYALAN
+180A ; C # Po MONGOLIAN NIRUGU
200D ; C # Cf ZERO WIDTH JOINER
-# Total code points: 3
+# Total code points: 4
# ================================================
# Joining_Type=Dual_Joining
+0620 ; D # Lo ARABIC LETTER KASHMIRI YEH
0626 ; D # Lo ARABIC LETTER YEH WITH HAMZA ABOVE
0628 ; D # Lo ARABIC LETTER BEH
062A..062E ; D # Lo [5] ARABIC LETTER TEH..ARABIC LETTER KHAH
@@ -57,8 +60,45 @@
0775..0777 ; D # Lo [3] ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE..ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW
077A..077F ; D # Lo [6] ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE..ARABIC LETTER KAF WITH TWO DOTS ABOVE
07CA..07EA ; D # Lo [33] NKO LETTER A..NKO LETTER JONA RA
+0841..0845 ; D # Lo [5] MANDAIC LETTER AB..MANDAIC LETTER USHENNA
+0848 ; D # Lo MANDAIC LETTER ATT
+084A..0853 ; D # Lo [10] MANDAIC LETTER AK..MANDAIC LETTER AR
+0855 ; D # Lo MANDAIC LETTER AT
+0860 ; D # Lo SYRIAC LETTER MALAYALAM NGA
+0862..0865 ; D # Lo [4] SYRIAC LETTER MALAYALAM NYA..SYRIAC LETTER MALAYALAM NNNA
+0868 ; D # Lo SYRIAC LETTER MALAYALAM LLA
+08A0..08A9 ; D # Lo [10] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER YEH WITH TWO DOTS BELOW AND DOT ABOVE
+08AF..08B0 ; D # Lo [2] ARABIC LETTER SAD WITH THREE DOTS BELOW..ARABIC LETTER GAF WITH INVERTED STROKE
+08B3..08B4 ; D # Lo [2] ARABIC LETTER AIN WITH THREE DOTS BELOW..ARABIC LETTER KAF WITH DOT BELOW
+08B6..08B8 ; D # Lo [3] ARABIC LETTER BEH WITH SMALL MEEM ABOVE..ARABIC LETTER TEH WITH SMALL TEH ABOVE
+08BA..08BD ; D # Lo [4] ARABIC LETTER YEH WITH TWO DOTS BELOW AND SMALL NOON ABOVE..ARABIC LETTER AFRICAN NOON
+1807 ; D # Po MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER
+1820..1842 ; D # Lo [35] MONGOLIAN LETTER A..MONGOLIAN LETTER CHI
+1843 ; D # Lm MONGOLIAN LETTER TODO LONG VOWEL SIGN
+1844..1878 ; D # Lo [53] MONGOLIAN LETTER TODO E..MONGOLIAN LETTER CHA WITH TWO DOTS
+1887..18A8 ; D # Lo [34] MONGOLIAN LETTER ALI GALI A..MONGOLIAN LETTER MANCHU ALI GALI BHA
+18AA ; D # Lo MONGOLIAN LETTER MANCHU ALI GALI LHA
+A840..A871 ; D # Lo [50] PHAGS-PA LETTER KA..PHAGS-PA SUBJOINED LETTER RA
+10AC0..10AC4 ; D # Lo [5] MANICHAEAN LETTER ALEPH..MANICHAEAN LETTER GHIMEL
+10AD3..10AD6 ; D # Lo [4] MANICHAEAN LETTER LAMEDH..MANICHAEAN LETTER MEM
+10AD8..10ADC ; D # Lo [5] MANICHAEAN LETTER SAMEKH..MANICHAEAN LETTER FE
+10ADE..10AE0 ; D # Lo [3] MANICHAEAN LETTER QOPH..MANICHAEAN LETTER QHOPH
+10AEB..10AEE ; D # No [4] MANICHAEAN NUMBER ONE..MANICHAEAN NUMBER TWENTY
+10B80 ; D # Lo PSALTER PAHLAVI LETTER ALEPH
+10B82 ; D # Lo PSALTER PAHLAVI LETTER GIMEL
+10B86..10B88 ; D # Lo [3] PSALTER PAHLAVI LETTER ZAYIN..PSALTER PAHLAVI LETTER YODH
+10B8A..10B8B ; D # Lo [2] PSALTER PAHLAVI LETTER LAMEDH..PSALTER PAHLAVI LETTER MEM-QOPH
+10B8D ; D # Lo PSALTER PAHLAVI LETTER SAMEKH
+10B90 ; D # Lo PSALTER PAHLAVI LETTER SHIN
+10BAD..10BAE ; D # No [2] PSALTER PAHLAVI NUMBER TEN..PSALTER PAHLAVI NUMBER TWENTY
+10D01..10D21 ; D # Lo [33] HANIFI ROHINGYA LETTER BA..HANIFI ROHINGYA VOWEL O
+10D23 ; D # Lo HANIFI ROHINGYA MARK NA KHONNA
+10F30..10F32 ; D # Lo [3] SOGDIAN LETTER ALEPH..SOGDIAN LETTER GIMEL
+10F34..10F44 ; D # Lo [17] SOGDIAN LETTER WAW..SOGDIAN LETTER LESH
+10F51..10F53 ; D # No [3] SOGDIAN NUMBER ONE..SOGDIAN NUMBER TWENTY
+1E900..1E943 ; D # L& [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA
-# Total code points: 188
+# Total code points: 565
# ================================================
@@ -92,8 +132,47 @@
0771 ; R # Lo ARABIC LETTER REH WITH SMALL ARABIC LETTER TAH AND TWO DOTS
0773..0774 ; R # Lo [2] ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE..ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE
0778..0779 ; R # Lo [2] ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE..ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE
+0840 ; R # Lo MANDAIC LETTER HALQA
+0846..0847 ; R # Lo [2] MANDAIC LETTER AZ..MANDAIC LETTER IT
+0849 ; R # Lo MANDAIC LETTER AKSA
+0854 ; R # Lo MANDAIC LETTER ASH
+0867 ; R # Lo SYRIAC LETTER MALAYALAM RA
+0869..086A ; R # Lo [2] SYRIAC LETTER MALAYALAM LLLA..SYRIAC LETTER MALAYALAM SSA
+08AA..08AC ; R # Lo [3] ARABIC LETTER REH WITH LOOP..ARABIC LETTER ROHINGYA YEH
+08AE ; R # Lo ARABIC LETTER DAL WITH THREE DOTS BELOW
+08B1..08B2 ; R # Lo [2] ARABIC LETTER STRAIGHT WAW..ARABIC LETTER ZAIN WITH INVERTED V ABOVE
+08B9 ; R # Lo ARABIC LETTER REH WITH SMALL NOON ABOVE
+10AC5 ; R # Lo MANICHAEAN LETTER DALETH
+10AC7 ; R # Lo MANICHAEAN LETTER WAW
+10AC9..10ACA ; R # Lo [2] MANICHAEAN LETTER ZAYIN..MANICHAEAN LETTER ZHAYIN
+10ACE..10AD2 ; R # Lo [5] MANICHAEAN LETTER TETH..MANICHAEAN LETTER KHAPH
+10ADD ; R # Lo MANICHAEAN LETTER SADHE
+10AE1 ; R # Lo MANICHAEAN LETTER RESH
+10AE4 ; R # Lo MANICHAEAN LETTER TAW
+10AEF ; R # No MANICHAEAN NUMBER ONE HUNDRED
+10B81 ; R # Lo PSALTER PAHLAVI LETTER BETH
+10B83..10B85 ; R # Lo [3] PSALTER PAHLAVI LETTER DALETH..PSALTER PAHLAVI LETTER WAW-AYIN-RESH
+10B89 ; R # Lo PSALTER PAHLAVI LETTER KAPH
+10B8C ; R # Lo PSALTER PAHLAVI LETTER NUN
+10B8E..10B8F ; R # Lo [2] PSALTER PAHLAVI LETTER PE..PSALTER PAHLAVI LETTER SADHE
+10B91 ; R # Lo PSALTER PAHLAVI LETTER TAW
+10BA9..10BAC ; R # No [4] PSALTER PAHLAVI NUMBER ONE..PSALTER PAHLAVI NUMBER FOUR
+10D22 ; R # Lo HANIFI ROHINGYA MARK SAKIN
+10F33 ; R # Lo SOGDIAN LETTER HE
+10F54 ; R # No SOGDIAN NUMBER ONE HUNDRED
+
+# Total code points: 118
+
+# ================================================
+
+# Joining_Type=Left_Joining
+
+A872 ; L # Lo PHAGS-PA SUPERFIXED LETTER RA
+10ACD ; L # Lo MANICHAEAN LETTER HETH
+10AD7 ; L # Lo MANICHAEAN LETTER NUN
+10D00 ; L # Lo HANIFI ROHINGYA LETTER A
-# Total code points: 74
+# Total code points: 4
# ================================================
@@ -109,10 +188,10 @@
05C4..05C5 ; T # Mn [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT
05C7 ; T # Mn HEBREW POINT QAMATS QATAN
0610..061A ; T # Mn [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA
-064B..065E ; T # Mn [20] ARABIC FATHATAN..ARABIC FATHA WITH TWO DOTS
+061C ; T # Cf ARABIC LETTER MARK
+064B..065F ; T # Mn [21] ARABIC FATHATAN..ARABIC WAVY HAMZA BELOW
0670 ; T # Mn ARABIC LETTER SUPERSCRIPT ALEF
06D6..06DC ; T # Mn [7] ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA..ARABIC SMALL HIGH SEEN
-06DE ; T # Me ARABIC START OF RUB EL HIZB
06DF..06E4 ; T # Mn [6] ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH MADDA
06E7..06E8 ; T # Mn [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON
06EA..06ED ; T # Mn [4] ARABIC EMPTY CENTRE LOW STOP..ARABIC SMALL LOW MEEM
@@ -121,21 +200,26 @@
0730..074A ; T # Mn [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH
07A6..07B0 ; T # Mn [11] THAANA ABAFILI..THAANA SUKUN
07EB..07F3 ; T # Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE
+07FD ; T # Mn NKO DANTAYALAN
0816..0819 ; T # Mn [4] SAMARITAN MARK IN..SAMARITAN MARK DAGESH
081B..0823 ; T # Mn [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A
0825..0827 ; T # Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U
0829..082D ; T # Mn [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA
-0900..0902 ; T # Mn [3] DEVANAGARI SIGN INVERTED CANDRABINDU..DEVANAGARI SIGN ANUSVARA
+0859..085B ; T # Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK
+08D3..08E1 ; T # Mn [15] ARABIC SMALL LOW WAW..ARABIC SMALL HIGH SIGN SAFHA
+08E3..0902 ; T # Mn [32] ARABIC TURNED DAMMA BELOW..DEVANAGARI SIGN ANUSVARA
+093A ; T # Mn DEVANAGARI VOWEL SIGN OE
093C ; T # Mn DEVANAGARI SIGN NUKTA
0941..0948 ; T # Mn [8] DEVANAGARI VOWEL SIGN U..DEVANAGARI VOWEL SIGN AI
094D ; T # Mn DEVANAGARI SIGN VIRAMA
-0951..0955 ; T # Mn [5] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI VOWEL SIGN CANDRA LONG E
+0951..0957 ; T # Mn [7] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI VOWEL SIGN UUE
0962..0963 ; T # Mn [2] DEVANAGARI VOWEL SIGN VOCALIC L..DEVANAGARI VOWEL SIGN VOCALIC LL
0981 ; T # Mn BENGALI SIGN CANDRABINDU
09BC ; T # Mn BENGALI SIGN NUKTA
09C1..09C4 ; T # Mn [4] BENGALI VOWEL SIGN U..BENGALI VOWEL SIGN VOCALIC RR
09CD ; T # Mn BENGALI SIGN VIRAMA
09E2..09E3 ; T # Mn [2] BENGALI VOWEL SIGN VOCALIC L..BENGALI VOWEL SIGN VOCALIC LL
+09FE ; T # Mn BENGALI SANDHI MARK
0A01..0A02 ; T # Mn [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN BINDI
0A3C ; T # Mn GURMUKHI SIGN NUKTA
0A41..0A42 ; T # Mn [2] GURMUKHI VOWEL SIGN U..GURMUKHI VOWEL SIGN UU
@@ -150,6 +234,7 @@
0AC7..0AC8 ; T # Mn [2] GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN AI
0ACD ; T # Mn GUJARATI SIGN VIRAMA
0AE2..0AE3 ; T # Mn [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL
+0AFA..0AFF ; T # Mn [6] GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE
0B01 ; T # Mn ORIYA SIGN CANDRABINDU
0B3C ; T # Mn ORIYA SIGN NUKTA
0B3F ; T # Mn ORIYA VOWEL SIGN I
@@ -160,16 +245,21 @@
0B82 ; T # Mn TAMIL SIGN ANUSVARA
0BC0 ; T # Mn TAMIL VOWEL SIGN II
0BCD ; T # Mn TAMIL SIGN VIRAMA
+0C00 ; T # Mn TELUGU SIGN COMBINING CANDRABINDU ABOVE
+0C04 ; T # Mn TELUGU SIGN COMBINING ANUSVARA ABOVE
0C3E..0C40 ; T # Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II
0C46..0C48 ; T # Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI
0C4A..0C4D ; T # Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA
0C55..0C56 ; T # Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK
0C62..0C63 ; T # Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL
+0C81 ; T # Mn KANNADA SIGN CANDRABINDU
0CBC ; T # Mn KANNADA SIGN NUKTA
0CBF ; T # Mn KANNADA VOWEL SIGN I
0CC6 ; T # Mn KANNADA VOWEL SIGN E
0CCC..0CCD ; T # Mn [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA
0CE2..0CE3 ; T # Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL
+0D00..0D01 ; T # Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU
+0D3B..0D3C ; T # Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA
0D41..0D44 ; T # Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR
0D4D ; T # Mn MALAYALAM SIGN VIRAMA
0D62..0D63 ; T # Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL
@@ -190,7 +280,7 @@
0F71..0F7E ; T # Mn [14] TIBETAN VOWEL SIGN AA..TIBETAN SIGN RJES SU NGA RO
0F80..0F84 ; T # Mn [5] TIBETAN VOWEL SIGN REVERSED I..TIBETAN MARK HALANTA
0F86..0F87 ; T # Mn [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS
-0F90..0F97 ; T # Mn [8] TIBETAN SUBJOINED LETTER KA..TIBETAN SUBJOINED LETTER JA
+0F8D..0F97 ; T # Mn [11] TIBETAN SUBJOINED SIGN LCE TSA CAN..TIBETAN SUBJOINED LETTER JA
0F99..0FBC ; T # Mn [36] TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER FIXED-FORM RA
0FC6 ; T # Mn TIBETAN SYMBOL PADMA GDAN
102D..1030 ; T # Mn [4] MYANMAR VOWEL SIGN I..MYANMAR VOWEL SIGN UU
@@ -204,23 +294,25 @@
1085..1086 ; T # Mn [2] MYANMAR VOWEL SIGN SHAN E ABOVE..MYANMAR VOWEL SIGN SHAN FINAL Y
108D ; T # Mn MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE
109D ; T # Mn MYANMAR VOWEL SIGN AITON AI
-135F ; T # Mn ETHIOPIC COMBINING GEMINATION MARK
+135D..135F ; T # Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK
1712..1714 ; T # Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA
1732..1734 ; T # Mn [3] HANUNOO VOWEL SIGN I..HANUNOO SIGN PAMUDPOD
1752..1753 ; T # Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U
1772..1773 ; T # Mn [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U
-17B4..17B5 ; T # Cf [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
+17B4..17B5 ; T # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
17B7..17BD ; T # Mn [7] KHMER VOWEL SIGN I..KHMER VOWEL SIGN UA
17C6 ; T # Mn KHMER SIGN NIKAHIT
17C9..17D3 ; T # Mn [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT
17DD ; T # Mn KHMER SIGN ATTHACAN
180B..180D ; T # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
+1885..1886 ; T # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA
18A9 ; T # Mn MONGOLIAN LETTER ALI GALI DAGALGA
1920..1922 ; T # Mn [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U
1927..1928 ; T # Mn [2] LIMBU VOWEL SIGN E..LIMBU VOWEL SIGN O
1932 ; T # Mn LIMBU SMALL LETTER ANUSVARA
1939..193B ; T # Mn [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I
1A17..1A18 ; T # Mn [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U
+1A1B ; T # Mn BUGINESE VOWEL SIGN AE
1A56 ; T # Mn TAI THAM CONSONANT SIGN MEDIAL LA
1A58..1A5E ; T # Mn [7] TAI THAM SIGN MAI KANG LAI..TAI THAM CONSONANT SIGN SA
1A60 ; T # Mn TAI THAM SIGN SAKOT
@@ -228,6 +320,8 @@
1A65..1A6C ; T # Mn [8] TAI THAM VOWEL SIGN I..TAI THAM VOWEL SIGN OA BELOW
1A73..1A7C ; T # Mn [10] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN KHUEN-LUE KARAN
1A7F ; T # Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT
+1AB0..1ABD ; T # Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW
+1ABE ; T # Me COMBINING PARENTHESES OVERLAY
1B00..1B03 ; T # Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG
1B34 ; T # Mn BALINESE SIGN REREKAN
1B36..1B3A ; T # Mn [5] BALINESE VOWEL SIGN ULU..BALINESE VOWEL SIGN RA REPA
@@ -237,14 +331,21 @@
1B80..1B81 ; T # Mn [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR
1BA2..1BA5 ; T # Mn [4] SUNDANESE CONSONANT SIGN PANYAKRA..SUNDANESE VOWEL SIGN PANYUKU
1BA8..1BA9 ; T # Mn [2] SUNDANESE VOWEL SIGN PAMEPET..SUNDANESE VOWEL SIGN PANEULEUNG
+1BAB..1BAD ; T # Mn [3] SUNDANESE SIGN VIRAMA..SUNDANESE CONSONANT SIGN PASANGAN WA
+1BE6 ; T # Mn BATAK SIGN TOMPI
+1BE8..1BE9 ; T # Mn [2] BATAK VOWEL SIGN PAKPAK E..BATAK VOWEL SIGN EE
+1BED ; T # Mn BATAK VOWEL SIGN KARO O
+1BEF..1BF1 ; T # Mn [3] BATAK VOWEL SIGN U FOR SIMALUNGUN SA..BATAK CONSONANT SIGN H
1C2C..1C33 ; T # Mn [8] LEPCHA VOWEL SIGN E..LEPCHA CONSONANT SIGN T
1C36..1C37 ; T # Mn [2] LEPCHA SIGN RAN..LEPCHA SIGN NUKTA
1CD0..1CD2 ; T # Mn [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA
1CD4..1CE0 ; T # Mn [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA
1CE2..1CE8 ; T # Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL
1CED ; T # Mn VEDIC SIGN TIRYAK
-1DC0..1DE6 ; T # Mn [39] COMBINING DOTTED GRAVE ACCENT..COMBINING LATIN SMALL LETTER Z
-1DFD..1DFF ; T # Mn [3] COMBINING ALMOST EQUAL TO BELOW..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW
+1CF4 ; T # Mn VEDIC TONE CANDRA ABOVE
+1CF8..1CF9 ; T # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE
+1DC0..1DF9 ; T # Mn [58] COMBINING DOTTED GRAVE ACCENT..COMBINING WIDE INVERTED BRIDGE BELOW
+1DFB..1DFF ; T # Mn [5] COMBINING DELETION MARK..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW
200B ; T # Cf ZERO WIDTH SPACE
200E..200F ; T # Cf [2] LEFT-TO-RIGHT MARK..RIGHT-TO-LEFT MARK
202A..202E ; T # Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
@@ -256,63 +357,160 @@
20E2..20E4 ; T # Me [3] COMBINING ENCLOSING SCREEN..COMBINING ENCLOSING UPWARD POINTING TRIANGLE
20E5..20F0 ; T # Mn [12] COMBINING REVERSE SOLIDUS OVERLAY..COMBINING ASTERISK ABOVE
2CEF..2CF1 ; T # Mn [3] COPTIC COMBINING NI ABOVE..COPTIC COMBINING SPIRITUS LENIS
+2D7F ; T # Mn TIFINAGH CONSONANT JOINER
2DE0..2DFF ; T # Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS
-302A..302F ; T # Mn [6] IDEOGRAPHIC LEVEL TONE MARK..HANGUL DOUBLE DOT TONE MARK
+302A..302D ; T # Mn [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK
3099..309A ; T # Mn [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
A66F ; T # Mn COMBINING CYRILLIC VZMET
A670..A672 ; T # Me [3] COMBINING CYRILLIC TEN MILLIONS SIGN..COMBINING CYRILLIC THOUSAND MILLIONS SIGN
-A67C..A67D ; T # Mn [2] COMBINING CYRILLIC KAVYKA..COMBINING CYRILLIC PAYEROK
+A674..A67D ; T # Mn [10] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC PAYEROK
+A69E..A69F ; T # Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E
A6F0..A6F1 ; T # Mn [2] BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS
A802 ; T # Mn SYLOTI NAGRI SIGN DVISVARA
A806 ; T # Mn SYLOTI NAGRI SIGN HASANTA
A80B ; T # Mn SYLOTI NAGRI SIGN ANUSVARA
A825..A826 ; T # Mn [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E
-A8C4 ; T # Mn SAURASHTRA SIGN VIRAMA
+A8C4..A8C5 ; T # Mn [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA SIGN CANDRABINDU
A8E0..A8F1 ; T # Mn [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA
+A8FF ; T # Mn DEVANAGARI VOWEL SIGN AY
A926..A92D ; T # Mn [8] KAYAH LI VOWEL UE..KAYAH LI TONE CALYA PLOPHU
A947..A951 ; T # Mn [11] REJANG VOWEL SIGN I..REJANG CONSONANT SIGN R
A980..A982 ; T # Mn [3] JAVANESE SIGN PANYANGGA..JAVANESE SIGN LAYAR
A9B3 ; T # Mn JAVANESE SIGN CECAK TELU
A9B6..A9B9 ; T # Mn [4] JAVANESE VOWEL SIGN WULU..JAVANESE VOWEL SIGN SUKU MENDUT
A9BC ; T # Mn JAVANESE VOWEL SIGN PEPET
+A9E5 ; T # Mn MYANMAR SIGN SHAN SAW
AA29..AA2E ; T # Mn [6] CHAM VOWEL SIGN AA..CHAM VOWEL SIGN OE
AA31..AA32 ; T # Mn [2] CHAM VOWEL SIGN AU..CHAM VOWEL SIGN UE
AA35..AA36 ; T # Mn [2] CHAM CONSONANT SIGN LA..CHAM CONSONANT SIGN WA
AA43 ; T # Mn CHAM CONSONANT SIGN FINAL NG
AA4C ; T # Mn CHAM CONSONANT SIGN FINAL M
+AA7C ; T # Mn MYANMAR SIGN TAI LAING TONE-2
AAB0 ; T # Mn TAI VIET MAI KANG
AAB2..AAB4 ; T # Mn [3] TAI VIET VOWEL I..TAI VIET VOWEL U
AAB7..AAB8 ; T # Mn [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA
AABE..AABF ; T # Mn [2] TAI VIET VOWEL AM..TAI VIET TONE MAI EK
AAC1 ; T # Mn TAI VIET TONE MAI THO
+AAEC..AAED ; T # Mn [2] MEETEI MAYEK VOWEL SIGN UU..MEETEI MAYEK VOWEL SIGN AAI
+AAF6 ; T # Mn MEETEI MAYEK VIRAMA
ABE5 ; T # Mn MEETEI MAYEK VOWEL SIGN ANAP
ABE8 ; T # Mn MEETEI MAYEK VOWEL SIGN UNAP
ABED ; T # Mn MEETEI MAYEK APUN IYEK
FB1E ; T # Mn HEBREW POINT JUDEO-SPANISH VARIKA
FE00..FE0F ; T # Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
-FE20..FE26 ; T # Mn [7] COMBINING LIGATURE LEFT HALF..COMBINING CONJOINING MACRON
+FE20..FE2F ; T # Mn [16] COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF
FEFF ; T # Cf ZERO WIDTH NO-BREAK SPACE
FFF9..FFFB ; T # Cf [3] INTERLINEAR ANNOTATION ANCHOR..INTERLINEAR ANNOTATION TERMINATOR
101FD ; T # Mn PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE
+102E0 ; T # Mn COPTIC EPACT THOUSANDS MARK
+10376..1037A ; T # Mn [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII
10A01..10A03 ; T # Mn [3] KHAROSHTHI VOWEL SIGN I..KHAROSHTHI VOWEL SIGN VOCALIC R
10A05..10A06 ; T # Mn [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O
10A0C..10A0F ; T # Mn [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA
10A38..10A3A ; T # Mn [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW
10A3F ; T # Mn KHAROSHTHI VIRAMA
-11080..11081 ; T # Mn [2] KAITHI SIGN CANDRABINDU..KAITHI SIGN ANUSVARA
+10AE5..10AE6 ; T # Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW
+10D24..10D27 ; T # Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI
+10F46..10F50 ; T # Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW
+11001 ; T # Mn BRAHMI SIGN ANUSVARA
+11038..11046 ; T # Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA
+1107F..11081 ; T # Mn [3] BRAHMI NUMBER JOINER..KAITHI SIGN ANUSVARA
110B3..110B6 ; T # Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI
110B9..110BA ; T # Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA
-110BD ; T # Cf KAITHI NUMBER SIGN
+11100..11102 ; T # Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA
+11127..1112B ; T # Mn [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU
+1112D..11134 ; T # Mn [8] CHAKMA VOWEL SIGN AI..CHAKMA MAAYYAA
+11173 ; T # Mn MAHAJANI SIGN NUKTA
+11180..11181 ; T # Mn [2] SHARADA SIGN CANDRABINDU..SHARADA SIGN ANUSVARA
+111B6..111BE ; T # Mn [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O
+111C9..111CC ; T # Mn [4] SHARADA SANDHI MARK..SHARADA EXTRA SHORT VOWEL MARK
+1122F..11231 ; T # Mn [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI
+11234 ; T # Mn KHOJKI SIGN ANUSVARA
+11236..11237 ; T # Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA
+1123E ; T # Mn KHOJKI SIGN SUKUN
+112DF ; T # Mn KHUDAWADI SIGN ANUSVARA
+112E3..112EA ; T # Mn [8] KHUDAWADI VOWEL SIGN U..KHUDAWADI SIGN VIRAMA
+11300..11301 ; T # Mn [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU
+1133B..1133C ; T # Mn [2] COMBINING BINDU BELOW..GRANTHA SIGN NUKTA
+11340 ; T # Mn GRANTHA VOWEL SIGN II
+11366..1136C ; T # Mn [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX
+11370..11374 ; T # Mn [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA
+11438..1143F ; T # Mn [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI
+11442..11444 ; T # Mn [3] NEWA SIGN VIRAMA..NEWA SIGN ANUSVARA
+11446 ; T # Mn NEWA SIGN NUKTA
+1145E ; T # Mn NEWA SANDHI MARK
+114B3..114B8 ; T # Mn [6] TIRHUTA VOWEL SIGN U..TIRHUTA VOWEL SIGN VOCALIC LL
+114BA ; T # Mn TIRHUTA VOWEL SIGN SHORT E
+114BF..114C0 ; T # Mn [2] TIRHUTA SIGN CANDRABINDU..TIRHUTA SIGN ANUSVARA
+114C2..114C3 ; T # Mn [2] TIRHUTA SIGN VIRAMA..TIRHUTA SIGN NUKTA
+115B2..115B5 ; T # Mn [4] SIDDHAM VOWEL SIGN U..SIDDHAM VOWEL SIGN VOCALIC RR
+115BC..115BD ; T # Mn [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA
+115BF..115C0 ; T # Mn [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA
+115DC..115DD ; T # Mn [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU
+11633..1163A ; T # Mn [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI
+1163D ; T # Mn MODI SIGN ANUSVARA
+1163F..11640 ; T # Mn [2] MODI SIGN VIRAMA..MODI SIGN ARDHACANDRA
+116AB ; T # Mn TAKRI SIGN ANUSVARA
+116AD ; T # Mn TAKRI VOWEL SIGN AA
+116B0..116B5 ; T # Mn [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU
+116B7 ; T # Mn TAKRI SIGN NUKTA
+1171D..1171F ; T # Mn [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA
+11722..11725 ; T # Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU
+11727..1172B ; T # Mn [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER
+1182F..11837 ; T # Mn [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA
+11839..1183A ; T # Mn [2] DOGRA SIGN VIRAMA..DOGRA SIGN NUKTA
+11A01..11A0A ; T # Mn [10] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL LENGTH MARK
+11A33..11A38 ; T # Mn [6] ZANABAZAR SQUARE FINAL CONSONANT MARK..ZANABAZAR SQUARE SIGN ANUSVARA
+11A3B..11A3E ; T # Mn [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA
+11A47 ; T # Mn ZANABAZAR SQUARE SUBJOINER
+11A51..11A56 ; T # Mn [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE
+11A59..11A5B ; T # Mn [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK
+11A8A..11A96 ; T # Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA
+11A98..11A99 ; T # Mn [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER
+11C30..11C36 ; T # Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L
+11C38..11C3D ; T # Mn [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA
+11C3F ; T # Mn BHAIKSUKI SIGN VIRAMA
+11C92..11CA7 ; T # Mn [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA
+11CAA..11CB0 ; T # Mn [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA
+11CB2..11CB3 ; T # Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E
+11CB5..11CB6 ; T # Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU
+11D31..11D36 ; T # Mn [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R
+11D3A ; T # Mn MASARAM GONDI VOWEL SIGN E
+11D3C..11D3D ; T # Mn [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O
+11D3F..11D45 ; T # Mn [7] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI VIRAMA
+11D47 ; T # Mn MASARAM GONDI RA-KARA
+11D90..11D91 ; T # Mn [2] GUNJALA GONDI VOWEL SIGN EE..GUNJALA GONDI VOWEL SIGN AI
+11D95 ; T # Mn GUNJALA GONDI SIGN ANUSVARA
+11D97 ; T # Mn GUNJALA GONDI VIRAMA
+11EF3..11EF4 ; T # Mn [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U
+16AF0..16AF4 ; T # Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE
+16B30..16B36 ; T # Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM
+16F8F..16F92 ; T # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW
+1BC9D..1BC9E ; T # Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK
+1BCA0..1BCA3 ; T # Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
1D167..1D169 ; T # Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3
1D173..1D17A ; T # Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
1D17B..1D182 ; T # Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE
1D185..1D18B ; T # Mn [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE
1D1AA..1D1AD ; T # Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO
1D242..1D244 ; T # Mn [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME
+1DA00..1DA36 ; T # Mn [55] SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN
+1DA3B..1DA6C ; T # Mn [50] SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT
+1DA75 ; T # Mn SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS
+1DA84 ; T # Mn SIGNWRITING LOCATION HEAD NECK
+1DA9B..1DA9F ; T # Mn [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6
+1DAA1..1DAAF ; T # Mn [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16
+1E000..1E006 ; T # Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE
+1E008..1E018 ; T # Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU
+1E01B..1E021 ; T # Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI
+1E023..1E024 ; T # Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS
+1E026..1E02A ; T # Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA
+1E8D0..1E8D6 ; T # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS
+1E944..1E94A ; T # Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA
E0001 ; T # Cf LANGUAGE TAG
E0020..E007F ; T # Cf [96] TAG SPACE..CANCEL TAG
E0100..E01EF ; T # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
-# Total code points: 1308
+# Total code points: 1953
# EOF
diff --git a/tools/Makefile b/tools/Makefile
new file mode 100644
index 000000000..5dc4a1000
--- /dev/null
+++ b/tools/Makefile
@@ -0,0 +1,75 @@
+# Tools
+
+# testament rules
+
+clean-testament:
+ $(VQ)echo " CLEAN: testament.h"
+ $(Q)$(RM) $(OBJROOT)/testament.h
+CLEANS += clean-testament
+
+.PHONY: testament
+
+testament $(OBJROOT)/testament.h:
+ $(Q)$(PERL) tools/git-testament.pl $(CURDIR) $(OBJROOT)/testament.h
+
+
+# lib png build compiler flags
+ifeq ($(HOST),OpenBSD)
+ BUILD_LIBPNG_CFLAGS += $(shell $(PKG_CONFIG) --cflags libpng)
+ BUILD_LIBPNG_LDFLAGS += $(shell $(PKG_CONFIG) --libs libpng)
+else
+ ifeq ($(HOST),FreeBSD)
+ BUILD_LIBPNG_CFLAGS += $(shell $(PKG_CONFIG) --cflags libpng)
+ BUILD_LIBPNG_LDFLAGS += $(shell $(PKG_CONFIG) --libs libpng)
+ else
+ BUILD_LIBPNG_CFLAGS +=
+ BUILD_LIBPNG_LDFLAGS += -lpng
+ endif
+endif
+
+
+# Build tool to convert file to comiled data
+#
+$(TOOLROOT)/xxd: tools/xxd.c $(TOOLROOT)/created
+ $(VQ)echo "BUILD CC: $@"
+ $(Q)$(BUILD_CC) $(BUILD_CFLAGS) -o $@ $< $(BUILD_LDFLAGS)
+
+
+# Build tool to filter messages
+#
+$(TOOLROOT)/split-messages: tools/split-messages.c $(TOOLROOT)/created
+ $(VQ)echo "BUILD CC: $@"
+ $(Q)$(BUILD_CC) $(BUILD_CFLAGS) -I. -o $@ $< $(BUILD_LDFLAGS) -lz
+
+
+# Build tool to convert image bitmaps to source code.
+#
+$(TOOLROOT)/convert_image: tools/convert_image.c $(TOOLROOT)/created
+ $(VQ)echo "BUILD CC: $@"
+ $(Q)$(BUILD_CC) $(BUILD_CFLAGS) $(BUILD_LIBPNG_CFLAGS) -o $@ $< $(BUILD_LDFLAGS) $(BUILD_LIBPNG_LDFLAGS)
+
+
+# Build too to perform font conversion
+$(TOOLROOT)/convert_font: tools/convert_font.c $(TOOLROOT)/created
+ $(VQ)echo "BUILD CC: $@"
+ $(Q)$(BUILD_CC) $(BUILD_CFLAGS) -o $@ $<
+
+# idna
+#
+IDNA_UNICODE_MAJOR=11
+
+tools/DerivedJoiningType.txt:
+ curl -o $@ "https://www.unicode.org/Public/$(IDNA_UNICODE_MAJOR).0.0/ucd/extracted/DerivedJoiningType.txt"
+
+tools/IdnaMappingTable.txt:
+ curl -o $@ "https://www.unicode.org/Public/idna/$(IDNA_UNICODE_MAJOR).0.0/IdnaMappingTable.txt"
+
+tools/idna-tables-properties.csv:
+ curl -o $@ "https://www.iana.org/assignments/idna-tables-$(IDNA_UNICODE_MAJOR).0.0/idna-tables-properties.csv"
+
+# the idna props header must be explicitly rebuilt
+ifneq ($(filter $(MAKECMDGOALS),utils/idna_props.h),)
+utils/idna_props.h: tools/DerivedJoiningType.txt tools/idna-tables-properties.csv
+ $(VQ)echo " IDNA: $@"
+ $(Q)$(PERL) tools/idna-derived-props-gen.pl -o $@ -p tools/idna-tables-properties.csv -j tools/DerivedJoiningType.txt
+endif
diff --git a/frontends/framebuffer/convert_font.c b/tools/convert_font.c
index 010af857a..d22c85920 100644
--- a/frontends/framebuffer/convert_font.c
+++ b/tools/convert_font.c
@@ -271,7 +271,7 @@ struct font_data {
int glyphs;
};
-bool generate_font_header(const char *path, struct font_data *data)
+static bool generate_font_header(const char *path, struct font_data *data)
{
FILE *fp;
int s;
@@ -290,14 +290,14 @@ bool generate_font_header(const char *path, struct font_data *data)
for (s = 0; s < 4; s++) {
- fprintf(fp, "const uint8_t *%s_section_table;\n",
+ fprintf(fp, "extern const uint8_t *%s_section_table;\n",
var_lables[s]);
- fprintf(fp, "const uint16_t *%s_sections;\n",
+ fprintf(fp, "extern const uint16_t *%s_sections;\n",
var_lables[s]);
}
- fprintf(fp, "const uint8_t *font_glyph_data;\n");
+ fprintf(fp, "extern const uint8_t *font_glyph_data;\n");
fprintf(fp, "\n\n");
@@ -307,7 +307,7 @@ bool generate_font_header(const char *path, struct font_data *data)
}
-bool generate_font_source(const char *path, struct font_data *data)
+static bool generate_font_source(const char *path, struct font_data *data)
{
int s, i, y;
int limit;
@@ -624,7 +624,7 @@ uint8_t frag[16][5] = {
THREE_S__ }
};
-void build_codepoint(int id, bool italic, uint8_t *code_point)
+static void build_codepoint(int id, bool italic, uint8_t *code_point)
{
int shift = 0;
int l;
@@ -1002,7 +1002,7 @@ static bool parse_chunk(struct parse_context *ctx, const char *buf, size_t len,
}
-bool load_font(const char *path, struct font_data **data)
+static bool load_font(const char *path, struct font_data **data)
{
struct parse_context ctx;
struct font_data *d;
@@ -1033,7 +1033,7 @@ bool load_font(const char *path, struct font_data **data)
/* Find filesize */
fseek(fp, 0L, SEEK_END);
file_len = ftell(fp);
- if (file_len == -1) {
+ if ((long)file_len == -1) {
LOG(LOG_ERROR, "Could not size input file\n");
free(d);
fclose(fp);
diff --git a/frontends/framebuffer/convert_image.c b/tools/convert_image.c
index de772fc29..de772fc29 100644
--- a/frontends/framebuffer/convert_image.c
+++ b/tools/convert_image.c
diff --git a/utils/coverity-build.sh b/tools/coverity-build.sh
index b51562f8f..24dafd16a 100755
--- a/utils/coverity-build.sh
+++ b/tools/coverity-build.sh
@@ -36,8 +36,8 @@
COVERITY_PROJECT="NetSurf+Browser"
-# build gtk, framebuffer and monkey frontend by default
-TARGETS="gtk framebuffer monkey"
+# build gtk2, framebuffer and monkey frontend by default
+TARGETS="gtk2 framebuffer monkey"
# setup build environment
export PREFIX=${PREFIX:-${JENKINS_HOME}/artifacts-${HOST}}
diff --git a/utils/fetch-transifex.pl b/tools/fetch-transifex.pl
index 4d40062c9..4d40062c9 100644
--- a/utils/fetch-transifex.pl
+++ b/tools/fetch-transifex.pl
diff --git a/utils/git-date.sh b/tools/git-date.sh
index d9a9059a0..d9a9059a0 100755
--- a/utils/git-date.sh
+++ b/tools/git-date.sh
diff --git a/utils/git-testament.pl b/tools/git-testament.pl
index 5a71a16df..5a71a16df 100644
--- a/utils/git-testament.pl
+++ b/tools/git-testament.pl
diff --git a/tools/idna-derived-props-gen.pl b/tools/idna-derived-props-gen.pl
new file mode 100644
index 000000000..a9e9b4b53
--- /dev/null
+++ b/tools/idna-derived-props-gen.pl
@@ -0,0 +1,182 @@
+#!/usr/bin/perl
+#
+# Copyright 2014 Chris Young <chris@unsatisfactorysoftware.co.uk>
+#
+# This file is part of NetSurf, http://www.netsurf-browser.org/
+#
+# NetSurf is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# NetSurf is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+use strict;
+
+use Getopt::Long ();
+use Fcntl qw( O_CREAT O_EXCL O_WRONLY O_APPEND O_RDONLY O_WRONLY );
+
+use constant GETOPT_OPTS => qw( auto_abbrev no_getopt_compat bundling );
+use constant GETOPT_SPEC =>
+ qw( output|o=s
+ properties|p=s
+ joining|j=s
+ help|h|? );
+
+# default option values:
+my %opt = qw(properties "idna-tables-properties.csv" joining "DerivedJoiningType.txt");
+
+sub usage
+{
+ my @fmt = map { s/::$//; $_ } keys(%{$::{'msgfmt::'}});
+ print(STDERR <<TXT );
+usage:
+ $0 [-o output-file] -p properties-file -j joining-file
+
+ output-file : defaults to standard output
+TXT
+ exit(1);
+}
+
+sub output_stream
+{
+ if( $opt{output} )
+ {
+ my $ofh;
+
+ sysopen( $ofh, $opt{output}, O_CREAT|O_EXCL|O_APPEND|O_WRONLY ) ||
+ die( "$0: Failed to open output file $opt{output}: $!\n" );
+
+ return $ofh;
+ }
+
+ return \*STDOUT;
+}
+
+sub input_stream
+{
+ my $stream = $_[0];
+
+ if( $opt{$stream} )
+ {
+ my $ifh;
+
+ sysopen( $ifh, $opt{$stream}, O_RDONLY ) ||
+ die( "$0: Failed to open input file $stream: $!\n" );
+
+ return $ifh;
+ }
+ die( "$0: No input file for $stream");
+}
+
+sub main
+{
+ my $output;
+ my $properties;
+ my $joining;
+ my $opt_ok;
+
+ # option parsing:
+ Getopt::Long::Configure( GETOPT_OPTS );
+ $opt_ok = Getopt::Long::GetOptions( \%opt, GETOPT_SPEC );
+
+ # double check the options are sane (and we weren't asked for the help)
+ if( !$opt_ok || $opt{help} )
+ {
+ usage();
+ }
+
+ # open the appropriate files
+ $properties = input_stream("properties");
+ $joining = input_stream("joining");
+ $output = output_stream();
+
+
+ print { $output } <<HEADER;
+/* This file is generated by idna-derived-props-gen.pl
+ * DO NOT EDIT BY HAND
+ */
+#ifndef _NETSURF_UTILS_IDNA_PROPS_H_
+#define _NETSURF_UTILS_IDNA_PROPS_H_
+
+typedef enum idna_property {
+ IDNA_P_PVALID = 1,
+ IDNA_P_CONTEXTJ = 2,
+ IDNA_P_CONTEXTO = 3,
+ IDNA_P_DISALLOWED = 4,
+ IDNA_P_UNASSIGNED = 5
+} idna_property;
+
+typedef enum idna_unicode_jt {
+ IDNA_UNICODE_JT_U = 0,
+ IDNA_UNICODE_JT_C = 1,
+ IDNA_UNICODE_JT_D = 2,
+ IDNA_UNICODE_JT_R = 3,
+ IDNA_UNICODE_JT_T = 4,
+ IDNA_UNICODE_JT_L = 5
+} idna_unicode_jt;
+
+
+typedef struct idna_table {
+ int32_t start;
+ int32_t end;
+ union p {
+ idna_property property;
+ idna_unicode_jt jt;
+ } p;
+} idna_table;
+
+idna_table idna_derived[] = {
+HEADER
+
+
+ my $line = <$properties>; # discard header line
+
+ while($line = <$properties>) {
+ my @items = split(/\,/, $line);
+ my @codepoints = split(/-/, $items[0]);
+ if($#codepoints == 0) {
+ $codepoints[1] = $codepoints[0];
+ }
+ print { $output } "\t{ 0x" . $codepoints[0] . ", 0x" . $codepoints[1] . ", .p.property = IDNA_P_" . $items[1] . " },\n";
+ }
+
+ close($properties);
+
+ print { $output } <<HEADER;
+ { 0, 0, .p.property = 0}
+};
+
+idna_table idna_joiningtype[] = {
+HEADER
+
+
+ while($line = <$joining>) {
+ chop($line);
+ if(substr($line, 0, 1) eq '#') {next;}
+ if(length($line) == 0) {next;}
+ my @items = split(/;/, $line);
+ my @codepoints = split(/\./, $items[0]);
+ if($#codepoints == 0) {
+ $codepoints[2] = $codepoints[0];
+ }
+ print { $output } "\t{ 0x" . $codepoints[0] . ", 0x" . $codepoints[2] . ", .p.jt = IDNA_UNICODE_JT_" . substr($items[1], 1, 1) . " },\n";
+ }
+
+ close($joining);
+
+ print { $output } <<HEADER;
+ { 0, 0, .p.jt = 0}
+};
+#endif
+HEADER
+
+
+}
+
+main();
diff --git a/tools/idna-tables-properties.csv b/tools/idna-tables-properties.csv
new file mode 100644
index 000000000..5f245ee1a
--- /dev/null
+++ b/tools/idna-tables-properties.csv
@@ -0,0 +1,2838 @@
+Codepoint,Property,Status,Description
+0000-002C,DISALLOWED,,NULL..COMMA
+002D,PVALID,,HYPHEN-MINUS
+002E-002F,DISALLOWED,,FULL STOP..SOLIDUS
+0030-0039,PVALID,,DIGIT ZERO..DIGIT NINE
+003A-0060,DISALLOWED,,COLON..GRAVE ACCENT
+0061-007A,PVALID,,LATIN SMALL LETTER A..LATIN SMALL LETTER Z
+007B-00B6,DISALLOWED,,LEFT CURLY BRACKET..PILCROW SIGN
+00B7,CONTEXTO,,MIDDLE DOT
+00B8-00DE,DISALLOWED,,CEDILLA..LATIN CAPITAL LETTER THORN
+00DF-00F6,PVALID,,LATIN SMALL LETTER SHARP S..LATIN SMALL LETTER O WITH DIAERESIS
+00F7,DISALLOWED,,DIVISION SIGN
+00F8-00FF,PVALID,,LATIN SMALL LETTER O WITH STROKE..LATIN SMALL LETTER Y WITH DIAERESIS
+0100,DISALLOWED,,LATIN CAPITAL LETTER A WITH MACRON
+0101,PVALID,,LATIN SMALL LETTER A WITH MACRON
+0102,DISALLOWED,,LATIN CAPITAL LETTER A WITH BREVE
+0103,PVALID,,LATIN SMALL LETTER A WITH BREVE
+0104,DISALLOWED,,LATIN CAPITAL LETTER A WITH OGONEK
+0105,PVALID,,LATIN SMALL LETTER A WITH OGONEK
+0106,DISALLOWED,,LATIN CAPITAL LETTER C WITH ACUTE
+0107,PVALID,,LATIN SMALL LETTER C WITH ACUTE
+0108,DISALLOWED,,LATIN CAPITAL LETTER C WITH CIRCUMFLEX
+0109,PVALID,,LATIN SMALL LETTER C WITH CIRCUMFLEX
+010A,DISALLOWED,,LATIN CAPITAL LETTER C WITH DOT ABOVE
+010B,PVALID,,LATIN SMALL LETTER C WITH DOT ABOVE
+010C,DISALLOWED,,LATIN CAPITAL LETTER C WITH CARON
+010D,PVALID,,LATIN SMALL LETTER C WITH CARON
+010E,DISALLOWED,,LATIN CAPITAL LETTER D WITH CARON
+010F,PVALID,,LATIN SMALL LETTER D WITH CARON
+0110,DISALLOWED,,LATIN CAPITAL LETTER D WITH STROKE
+0111,PVALID,,LATIN SMALL LETTER D WITH STROKE
+0112,DISALLOWED,,LATIN CAPITAL LETTER E WITH MACRON
+0113,PVALID,,LATIN SMALL LETTER E WITH MACRON
+0114,DISALLOWED,,LATIN CAPITAL LETTER E WITH BREVE
+0115,PVALID,,LATIN SMALL LETTER E WITH BREVE
+0116,DISALLOWED,,LATIN CAPITAL LETTER E WITH DOT ABOVE
+0117,PVALID,,LATIN SMALL LETTER E WITH DOT ABOVE
+0118,DISALLOWED,,LATIN CAPITAL LETTER E WITH OGONEK
+0119,PVALID,,LATIN SMALL LETTER E WITH OGONEK
+011A,DISALLOWED,,LATIN CAPITAL LETTER E WITH CARON
+011B,PVALID,,LATIN SMALL LETTER E WITH CARON
+011C,DISALLOWED,,LATIN CAPITAL LETTER G WITH CIRCUMFLEX
+011D,PVALID,,LATIN SMALL LETTER G WITH CIRCUMFLEX
+011E,DISALLOWED,,LATIN CAPITAL LETTER G WITH BREVE
+011F,PVALID,,LATIN SMALL LETTER G WITH BREVE
+0120,DISALLOWED,,LATIN CAPITAL LETTER G WITH DOT ABOVE
+0121,PVALID,,LATIN SMALL LETTER G WITH DOT ABOVE
+0122,DISALLOWED,,LATIN CAPITAL LETTER G WITH CEDILLA
+0123,PVALID,,LATIN SMALL LETTER G WITH CEDILLA
+0124,DISALLOWED,,LATIN CAPITAL LETTER H WITH CIRCUMFLEX
+0125,PVALID,,LATIN SMALL LETTER H WITH CIRCUMFLEX
+0126,DISALLOWED,,LATIN CAPITAL LETTER H WITH STROKE
+0127,PVALID,,LATIN SMALL LETTER H WITH STROKE
+0128,DISALLOWED,,LATIN CAPITAL LETTER I WITH TILDE
+0129,PVALID,,LATIN SMALL LETTER I WITH TILDE
+012A,DISALLOWED,,LATIN CAPITAL LETTER I WITH MACRON
+012B,PVALID,,LATIN SMALL LETTER I WITH MACRON
+012C,DISALLOWED,,LATIN CAPITAL LETTER I WITH BREVE
+012D,PVALID,,LATIN SMALL LETTER I WITH BREVE
+012E,DISALLOWED,,LATIN CAPITAL LETTER I WITH OGONEK
+012F,PVALID,,LATIN SMALL LETTER I WITH OGONEK
+0130,DISALLOWED,,LATIN CAPITAL LETTER I WITH DOT ABOVE
+0131,PVALID,,LATIN SMALL LETTER DOTLESS I
+0132-0134,DISALLOWED,,LATIN CAPITAL LIGATURE IJ..LATIN CAPITAL LETTER J WITH CIRCUMFLEX
+0135,PVALID,,LATIN SMALL LETTER J WITH CIRCUMFLEX
+0136,DISALLOWED,,LATIN CAPITAL LETTER K WITH CEDILLA
+0137-0138,PVALID,,LATIN SMALL LETTER K WITH CEDILLA..LATIN SMALL LETTER KRA
+0139,DISALLOWED,,LATIN CAPITAL LETTER L WITH ACUTE
+013A,PVALID,,LATIN SMALL LETTER L WITH ACUTE
+013B,DISALLOWED,,LATIN CAPITAL LETTER L WITH CEDILLA
+013C,PVALID,,LATIN SMALL LETTER L WITH CEDILLA
+013D,DISALLOWED,,LATIN CAPITAL LETTER L WITH CARON
+013E,PVALID,,LATIN SMALL LETTER L WITH CARON
+013F-0141,DISALLOWED,,LATIN CAPITAL LETTER L WITH MIDDLE DOT..LATIN CAPITAL LETTER L WITH STROKE
+0142,PVALID,,LATIN SMALL LETTER L WITH STROKE
+0143,DISALLOWED,,LATIN CAPITAL LETTER N WITH ACUTE
+0144,PVALID,,LATIN SMALL LETTER N WITH ACUTE
+0145,DISALLOWED,,LATIN CAPITAL LETTER N WITH CEDILLA
+0146,PVALID,,LATIN SMALL LETTER N WITH CEDILLA
+0147,DISALLOWED,,LATIN CAPITAL LETTER N WITH CARON
+0148,PVALID,,LATIN SMALL LETTER N WITH CARON
+0149-014A,DISALLOWED,,LATIN SMALL LETTER N PRECEDED BY APOSTROPHE..LATIN CAPITAL LETTER ENG
+014B,PVALID,,LATIN SMALL LETTER ENG
+014C,DISALLOWED,,LATIN CAPITAL LETTER O WITH MACRON
+014D,PVALID,,LATIN SMALL LETTER O WITH MACRON
+014E,DISALLOWED,,LATIN CAPITAL LETTER O WITH BREVE
+014F,PVALID,,LATIN SMALL LETTER O WITH BREVE
+0150,DISALLOWED,,LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+0151,PVALID,,LATIN SMALL LETTER O WITH DOUBLE ACUTE
+0152,DISALLOWED,,LATIN CAPITAL LIGATURE OE
+0153,PVALID,,LATIN SMALL LIGATURE OE
+0154,DISALLOWED,,LATIN CAPITAL LETTER R WITH ACUTE
+0155,PVALID,,LATIN SMALL LETTER R WITH ACUTE
+0156,DISALLOWED,,LATIN CAPITAL LETTER R WITH CEDILLA
+0157,PVALID,,LATIN SMALL LETTER R WITH CEDILLA
+0158,DISALLOWED,,LATIN CAPITAL LETTER R WITH CARON
+0159,PVALID,,LATIN SMALL LETTER R WITH CARON
+015A,DISALLOWED,,LATIN CAPITAL LETTER S WITH ACUTE
+015B,PVALID,,LATIN SMALL LETTER S WITH ACUTE
+015C,DISALLOWED,,LATIN CAPITAL LETTER S WITH CIRCUMFLEX
+015D,PVALID,,LATIN SMALL LETTER S WITH CIRCUMFLEX
+015E,DISALLOWED,,LATIN CAPITAL LETTER S WITH CEDILLA
+015F,PVALID,,LATIN SMALL LETTER S WITH CEDILLA
+0160,DISALLOWED,,LATIN CAPITAL LETTER S WITH CARON
+0161,PVALID,,LATIN SMALL LETTER S WITH CARON
+0162,DISALLOWED,,LATIN CAPITAL LETTER T WITH CEDILLA
+0163,PVALID,,LATIN SMALL LETTER T WITH CEDILLA
+0164,DISALLOWED,,LATIN CAPITAL LETTER T WITH CARON
+0165,PVALID,,LATIN SMALL LETTER T WITH CARON
+0166,DISALLOWED,,LATIN CAPITAL LETTER T WITH STROKE
+0167,PVALID,,LATIN SMALL LETTER T WITH STROKE
+0168,DISALLOWED,,LATIN CAPITAL LETTER U WITH TILDE
+0169,PVALID,,LATIN SMALL LETTER U WITH TILDE
+016A,DISALLOWED,,LATIN CAPITAL LETTER U WITH MACRON
+016B,PVALID,,LATIN SMALL LETTER U WITH MACRON
+016C,DISALLOWED,,LATIN CAPITAL LETTER U WITH BREVE
+016D,PVALID,,LATIN SMALL LETTER U WITH BREVE
+016E,DISALLOWED,,LATIN CAPITAL LETTER U WITH RING ABOVE
+016F,PVALID,,LATIN SMALL LETTER U WITH RING ABOVE
+0170,DISALLOWED,,LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+0171,PVALID,,LATIN SMALL LETTER U WITH DOUBLE ACUTE
+0172,DISALLOWED,,LATIN CAPITAL LETTER U WITH OGONEK
+0173,PVALID,,LATIN SMALL LETTER U WITH OGONEK
+0174,DISALLOWED,,LATIN CAPITAL LETTER W WITH CIRCUMFLEX
+0175,PVALID,,LATIN SMALL LETTER W WITH CIRCUMFLEX
+0176,DISALLOWED,,LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
+0177,PVALID,,LATIN SMALL LETTER Y WITH CIRCUMFLEX
+0178-0179,DISALLOWED,,LATIN CAPITAL LETTER Y WITH DIAERESIS..LATIN CAPITAL LETTER Z WITH ACUTE
+017A,PVALID,,LATIN SMALL LETTER Z WITH ACUTE
+017B,DISALLOWED,,LATIN CAPITAL LETTER Z WITH DOT ABOVE
+017C,PVALID,,LATIN SMALL LETTER Z WITH DOT ABOVE
+017D,DISALLOWED,,LATIN CAPITAL LETTER Z WITH CARON
+017E,PVALID,,LATIN SMALL LETTER Z WITH CARON
+017F,DISALLOWED,,LATIN SMALL LETTER LONG S
+0180,PVALID,,LATIN SMALL LETTER B WITH STROKE
+0181-0182,DISALLOWED,,LATIN CAPITAL LETTER B WITH HOOK..LATIN CAPITAL LETTER B WITH TOPBAR
+0183,PVALID,,LATIN SMALL LETTER B WITH TOPBAR
+0184,DISALLOWED,,LATIN CAPITAL LETTER TONE SIX
+0185,PVALID,,LATIN SMALL LETTER TONE SIX
+0186-0187,DISALLOWED,,LATIN CAPITAL LETTER OPEN O..LATIN CAPITAL LETTER C WITH HOOK
+0188,PVALID,,LATIN SMALL LETTER C WITH HOOK
+0189-018B,DISALLOWED,,LATIN CAPITAL LETTER AFRICAN D..LATIN CAPITAL LETTER D WITH TOPBAR
+018C-018D,PVALID,,LATIN SMALL LETTER D WITH TOPBAR..LATIN SMALL LETTER TURNED DELTA
+018E-0191,DISALLOWED,,LATIN CAPITAL LETTER REVERSED E..LATIN CAPITAL LETTER F WITH HOOK
+0192,PVALID,,LATIN SMALL LETTER F WITH HOOK
+0193-0194,DISALLOWED,,LATIN CAPITAL LETTER G WITH HOOK..LATIN CAPITAL LETTER GAMMA
+0195,PVALID,,LATIN SMALL LETTER HV
+0196-0198,DISALLOWED,,LATIN CAPITAL LETTER IOTA..LATIN CAPITAL LETTER K WITH HOOK
+0199-019B,PVALID,,LATIN SMALL LETTER K WITH HOOK..LATIN SMALL LETTER LAMBDA WITH STROKE
+019C-019D,DISALLOWED,,LATIN CAPITAL LETTER TURNED M..LATIN CAPITAL LETTER N WITH LEFT HOOK
+019E,PVALID,,LATIN SMALL LETTER N WITH LONG RIGHT LEG
+019F-01A0,DISALLOWED,,LATIN CAPITAL LETTER O WITH MIDDLE TILDE..LATIN CAPITAL LETTER O WITH HORN
+01A1,PVALID,,LATIN SMALL LETTER O WITH HORN
+01A2,DISALLOWED,,LATIN CAPITAL LETTER OI
+01A3,PVALID,,LATIN SMALL LETTER OI
+01A4,DISALLOWED,,LATIN CAPITAL LETTER P WITH HOOK
+01A5,PVALID,,LATIN SMALL LETTER P WITH HOOK
+01A6-01A7,DISALLOWED,,LATIN LETTER YR..LATIN CAPITAL LETTER TONE TWO
+01A8,PVALID,,LATIN SMALL LETTER TONE TWO
+01A9,DISALLOWED,,LATIN CAPITAL LETTER ESH
+01AA-01AB,PVALID,,LATIN LETTER REVERSED ESH LOOP..LATIN SMALL LETTER T WITH PALATAL HOOK
+01AC,DISALLOWED,,LATIN CAPITAL LETTER T WITH HOOK
+01AD,PVALID,,LATIN SMALL LETTER T WITH HOOK
+01AE-01AF,DISALLOWED,,LATIN CAPITAL LETTER T WITH RETROFLEX HOOK..LATIN CAPITAL LETTER U WITH HORN
+01B0,PVALID,,LATIN SMALL LETTER U WITH HORN
+01B1-01B3,DISALLOWED,,LATIN CAPITAL LETTER UPSILON..LATIN CAPITAL LETTER Y WITH HOOK
+01B4,PVALID,,LATIN SMALL LETTER Y WITH HOOK
+01B5,DISALLOWED,,LATIN CAPITAL LETTER Z WITH STROKE
+01B6,PVALID,,LATIN SMALL LETTER Z WITH STROKE
+01B7-01B8,DISALLOWED,,LATIN CAPITAL LETTER EZH..LATIN CAPITAL LETTER EZH REVERSED
+01B9-01BB,PVALID,,LATIN SMALL LETTER EZH REVERSED..LATIN LETTER TWO WITH STROKE
+01BC,DISALLOWED,,LATIN CAPITAL LETTER TONE FIVE
+01BD-01C3,PVALID,,LATIN SMALL LETTER TONE FIVE..LATIN LETTER RETROFLEX CLICK
+01C4-01CD,DISALLOWED,,LATIN CAPITAL LETTER DZ WITH CARON..LATIN CAPITAL LETTER A WITH CARON
+01CE,PVALID,,LATIN SMALL LETTER A WITH CARON
+01CF,DISALLOWED,,LATIN CAPITAL LETTER I WITH CARON
+01D0,PVALID,,LATIN SMALL LETTER I WITH CARON
+01D1,DISALLOWED,,LATIN CAPITAL LETTER O WITH CARON
+01D2,PVALID,,LATIN SMALL LETTER O WITH CARON
+01D3,DISALLOWED,,LATIN CAPITAL LETTER U WITH CARON
+01D4,PVALID,,LATIN SMALL LETTER U WITH CARON
+01D5,DISALLOWED,,LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON
+01D6,PVALID,,LATIN SMALL LETTER U WITH DIAERESIS AND MACRON
+01D7,DISALLOWED,,LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE
+01D8,PVALID,,LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE
+01D9,DISALLOWED,,LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON
+01DA,PVALID,,LATIN SMALL LETTER U WITH DIAERESIS AND CARON
+01DB,DISALLOWED,,LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE
+01DC-01DD,PVALID,,LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE..LATIN SMALL LETTER TURNED E
+01DE,DISALLOWED,,LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON
+01DF,PVALID,,LATIN SMALL LETTER A WITH DIAERESIS AND MACRON
+01E0,DISALLOWED,,LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON
+01E1,PVALID,,LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON
+01E2,DISALLOWED,,LATIN CAPITAL LETTER AE WITH MACRON
+01E3,PVALID,,LATIN SMALL LETTER AE WITH MACRON
+01E4,DISALLOWED,,LATIN CAPITAL LETTER G WITH STROKE
+01E5,PVALID,,LATIN SMALL LETTER G WITH STROKE
+01E6,DISALLOWED,,LATIN CAPITAL LETTER G WITH CARON
+01E7,PVALID,,LATIN SMALL LETTER G WITH CARON
+01E8,DISALLOWED,,LATIN CAPITAL LETTER K WITH CARON
+01E9,PVALID,,LATIN SMALL LETTER K WITH CARON
+01EA,DISALLOWED,,LATIN CAPITAL LETTER O WITH OGONEK
+01EB,PVALID,,LATIN SMALL LETTER O WITH OGONEK
+01EC,DISALLOWED,,LATIN CAPITAL LETTER O WITH OGONEK AND MACRON
+01ED,PVALID,,LATIN SMALL LETTER O WITH OGONEK AND MACRON
+01EE,DISALLOWED,,LATIN CAPITAL LETTER EZH WITH CARON
+01EF-01F0,PVALID,,LATIN SMALL LETTER EZH WITH CARON..LATIN SMALL LETTER J WITH CARON
+01F1-01F4,DISALLOWED,,LATIN CAPITAL LETTER DZ..LATIN CAPITAL LETTER G WITH ACUTE
+01F5,PVALID,,LATIN SMALL LETTER G WITH ACUTE
+01F6-01F8,DISALLOWED,,LATIN CAPITAL LETTER HWAIR..LATIN CAPITAL LETTER N WITH GRAVE
+01F9,PVALID,,LATIN SMALL LETTER N WITH GRAVE
+01FA,DISALLOWED,,LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE
+01FB,PVALID,,LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE
+01FC,DISALLOWED,,LATIN CAPITAL LETTER AE WITH ACUTE
+01FD,PVALID,,LATIN SMALL LETTER AE WITH ACUTE
+01FE,DISALLOWED,,LATIN CAPITAL LETTER O WITH STROKE AND ACUTE
+01FF,PVALID,,LATIN SMALL LETTER O WITH STROKE AND ACUTE
+0200,DISALLOWED,,LATIN CAPITAL LETTER A WITH DOUBLE GRAVE
+0201,PVALID,,LATIN SMALL LETTER A WITH DOUBLE GRAVE
+0202,DISALLOWED,,LATIN CAPITAL LETTER A WITH INVERTED BREVE
+0203,PVALID,,LATIN SMALL LETTER A WITH INVERTED BREVE
+0204,DISALLOWED,,LATIN CAPITAL LETTER E WITH DOUBLE GRAVE
+0205,PVALID,,LATIN SMALL LETTER E WITH DOUBLE GRAVE
+0206,DISALLOWED,,LATIN CAPITAL LETTER E WITH INVERTED BREVE
+0207,PVALID,,LATIN SMALL LETTER E WITH INVERTED BREVE
+0208,DISALLOWED,,LATIN CAPITAL LETTER I WITH DOUBLE GRAVE
+0209,PVALID,,LATIN SMALL LETTER I WITH DOUBLE GRAVE
+020A,DISALLOWED,,LATIN CAPITAL LETTER I WITH INVERTED BREVE
+020B,PVALID,,LATIN SMALL LETTER I WITH INVERTED BREVE
+020C,DISALLOWED,,LATIN CAPITAL LETTER O WITH DOUBLE GRAVE
+020D,PVALID,,LATIN SMALL LETTER O WITH DOUBLE GRAVE
+020E,DISALLOWED,,LATIN CAPITAL LETTER O WITH INVERTED BREVE
+020F,PVALID,,LATIN SMALL LETTER O WITH INVERTED BREVE
+0210,DISALLOWED,,LATIN CAPITAL LETTER R WITH DOUBLE GRAVE
+0211,PVALID,,LATIN SMALL LETTER R WITH DOUBLE GRAVE
+0212,DISALLOWED,,LATIN CAPITAL LETTER R WITH INVERTED BREVE
+0213,PVALID,,LATIN SMALL LETTER R WITH INVERTED BREVE
+0214,DISALLOWED,,LATIN CAPITAL LETTER U WITH DOUBLE GRAVE
+0215,PVALID,,LATIN SMALL LETTER U WITH DOUBLE GRAVE
+0216,DISALLOWED,,LATIN CAPITAL LETTER U WITH INVERTED BREVE
+0217,PVALID,,LATIN SMALL LETTER U WITH INVERTED BREVE
+0218,DISALLOWED,,LATIN CAPITAL LETTER S WITH COMMA BELOW
+0219,PVALID,,LATIN SMALL LETTER S WITH COMMA BELOW
+021A,DISALLOWED,,LATIN CAPITAL LETTER T WITH COMMA BELOW
+021B,PVALID,,LATIN SMALL LETTER T WITH COMMA BELOW
+021C,DISALLOWED,,LATIN CAPITAL LETTER YOGH
+021D,PVALID,,LATIN SMALL LETTER YOGH
+021E,DISALLOWED,,LATIN CAPITAL LETTER H WITH CARON
+021F,PVALID,,LATIN SMALL LETTER H WITH CARON
+0220,DISALLOWED,,LATIN CAPITAL LETTER N WITH LONG RIGHT LEG
+0221,PVALID,,LATIN SMALL LETTER D WITH CURL
+0222,DISALLOWED,,LATIN CAPITAL LETTER OU
+0223,PVALID,,LATIN SMALL LETTER OU
+0224,DISALLOWED,,LATIN CAPITAL LETTER Z WITH HOOK
+0225,PVALID,,LATIN SMALL LETTER Z WITH HOOK
+0226,DISALLOWED,,LATIN CAPITAL LETTER A WITH DOT ABOVE
+0227,PVALID,,LATIN SMALL LETTER A WITH DOT ABOVE
+0228,DISALLOWED,,LATIN CAPITAL LETTER E WITH CEDILLA
+0229,PVALID,,LATIN SMALL LETTER E WITH CEDILLA
+022A,DISALLOWED,,LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON
+022B,PVALID,,LATIN SMALL LETTER O WITH DIAERESIS AND MACRON
+022C,DISALLOWED,,LATIN CAPITAL LETTER O WITH TILDE AND MACRON
+022D,PVALID,,LATIN SMALL LETTER O WITH TILDE AND MACRON
+022E,DISALLOWED,,LATIN CAPITAL LETTER O WITH DOT ABOVE
+022F,PVALID,,LATIN SMALL LETTER O WITH DOT ABOVE
+0230,DISALLOWED,,LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON
+0231,PVALID,,LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON
+0232,DISALLOWED,,LATIN CAPITAL LETTER Y WITH MACRON
+0233-0239,PVALID,,LATIN SMALL LETTER Y WITH MACRON..LATIN SMALL LETTER QP DIGRAPH
+023A-023B,DISALLOWED,,LATIN CAPITAL LETTER A WITH STROKE..LATIN CAPITAL LETTER C WITH STROKE
+023C,PVALID,,LATIN SMALL LETTER C WITH STROKE
+023D-023E,DISALLOWED,,LATIN CAPITAL LETTER L WITH BAR..LATIN CAPITAL LETTER T WITH DIAGONAL STROKE
+023F-0240,PVALID,,LATIN SMALL LETTER S WITH SWASH TAIL..LATIN SMALL LETTER Z WITH SWASH TAIL
+0241,DISALLOWED,,LATIN CAPITAL LETTER GLOTTAL STOP
+0242,PVALID,,LATIN SMALL LETTER GLOTTAL STOP
+0243-0246,DISALLOWED,,LATIN CAPITAL LETTER B WITH STROKE..LATIN CAPITAL LETTER E WITH STROKE
+0247,PVALID,,LATIN SMALL LETTER E WITH STROKE
+0248,DISALLOWED,,LATIN CAPITAL LETTER J WITH STROKE
+0249,PVALID,,LATIN SMALL LETTER J WITH STROKE
+024A,DISALLOWED,,LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL
+024B,PVALID,,LATIN SMALL LETTER Q WITH HOOK TAIL
+024C,DISALLOWED,,LATIN CAPITAL LETTER R WITH STROKE
+024D,PVALID,,LATIN SMALL LETTER R WITH STROKE
+024E,DISALLOWED,,LATIN CAPITAL LETTER Y WITH STROKE
+024F-02AF,PVALID,,LATIN SMALL LETTER Y WITH STROKE..LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL
+02B0-02B8,DISALLOWED,,MODIFIER LETTER SMALL H..MODIFIER LETTER SMALL Y
+02B9-02C1,PVALID,,MODIFIER LETTER PRIME..MODIFIER LETTER REVERSED GLOTTAL STOP
+02C2-02C5,DISALLOWED,,MODIFIER LETTER LEFT ARROWHEAD..MODIFIER LETTER DOWN ARROWHEAD
+02C6-02D1,PVALID,,MODIFIER LETTER CIRCUMFLEX ACCENT..MODIFIER LETTER HALF TRIANGULAR COLON
+02D2-02EB,DISALLOWED,,MODIFIER LETTER CENTRED RIGHT HALF RING..MODIFIER LETTER YANG DEPARTING TONE MARK
+02EC,PVALID,,MODIFIER LETTER VOICING
+02ED,DISALLOWED,,MODIFIER LETTER UNASPIRATED
+02EE,PVALID,,MODIFIER LETTER DOUBLE APOSTROPHE
+02EF-02FF,DISALLOWED,,MODIFIER LETTER LOW DOWN ARROWHEAD..MODIFIER LETTER LOW LEFT ARROW
+0300-033F,PVALID,,COMBINING GRAVE ACCENT..COMBINING DOUBLE OVERLINE
+0340-0341,DISALLOWED,,COMBINING GRAVE TONE MARK..COMBINING ACUTE TONE MARK
+0342,PVALID,,COMBINING GREEK PERISPOMENI
+0343-0345,DISALLOWED,,COMBINING GREEK KORONIS..COMBINING GREEK YPOGEGRAMMENI
+0346-034E,PVALID,,COMBINING BRIDGE ABOVE..COMBINING UPWARDS ARROW BELOW
+034F,DISALLOWED,,COMBINING GRAPHEME JOINER
+0350-036F,PVALID,,COMBINING RIGHT ARROWHEAD ABOVE..COMBINING LATIN SMALL LETTER X
+0370,DISALLOWED,,GREEK CAPITAL LETTER HETA
+0371,PVALID,,GREEK SMALL LETTER HETA
+0372,DISALLOWED,,GREEK CAPITAL LETTER ARCHAIC SAMPI
+0373,PVALID,,GREEK SMALL LETTER ARCHAIC SAMPI
+0374,DISALLOWED,,GREEK NUMERAL SIGN
+0375,CONTEXTO,,GREEK LOWER NUMERAL SIGN
+0376,DISALLOWED,,GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA
+0377,PVALID,,GREEK SMALL LETTER PAMPHYLIAN DIGAMMA
+0378-0379,UNASSIGNED,,<RESERVED>..<RESERVED>
+037A,DISALLOWED,,GREEK YPOGEGRAMMENI
+037B-037D,PVALID,,GREEK SMALL REVERSED LUNATE SIGMA SYMBOL..GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL
+037E-037F,DISALLOWED,,GREEK QUESTION MARK..GREEK CAPITAL LETTER YOT
+0380-0383,UNASSIGNED,,<RESERVED>..<RESERVED>
+0384-038A,DISALLOWED,,GREEK TONOS..GREEK CAPITAL LETTER IOTA WITH TONOS
+038B,UNASSIGNED,,<RESERVED>
+038C,DISALLOWED,,GREEK CAPITAL LETTER OMICRON WITH TONOS
+038D,UNASSIGNED,,<RESERVED>
+038E-038F,DISALLOWED,,GREEK CAPITAL LETTER UPSILON WITH TONOS..GREEK CAPITAL LETTER OMEGA WITH TONOS
+0390,PVALID,,GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+0391-03A1,DISALLOWED,,GREEK CAPITAL LETTER ALPHA..GREEK CAPITAL LETTER RHO
+03A2,UNASSIGNED,,<RESERVED>
+03A3-03AB,DISALLOWED,,GREEK CAPITAL LETTER SIGMA..GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+03AC-03CE,PVALID,,GREEK SMALL LETTER ALPHA WITH TONOS..GREEK SMALL LETTER OMEGA WITH TONOS
+03CF-03D6,DISALLOWED,,GREEK CAPITAL KAI SYMBOL..GREEK PI SYMBOL
+03D7,PVALID,,GREEK KAI SYMBOL
+03D8,DISALLOWED,,GREEK LETTER ARCHAIC KOPPA
+03D9,PVALID,,GREEK SMALL LETTER ARCHAIC KOPPA
+03DA,DISALLOWED,,GREEK LETTER STIGMA
+03DB,PVALID,,GREEK SMALL LETTER STIGMA
+03DC,DISALLOWED,,GREEK LETTER DIGAMMA
+03DD,PVALID,,GREEK SMALL LETTER DIGAMMA
+03DE,DISALLOWED,,GREEK LETTER KOPPA
+03DF,PVALID,,GREEK SMALL LETTER KOPPA
+03E0,DISALLOWED,,GREEK LETTER SAMPI
+03E1,PVALID,,GREEK SMALL LETTER SAMPI
+03E2,DISALLOWED,,COPTIC CAPITAL LETTER SHEI
+03E3,PVALID,,COPTIC SMALL LETTER SHEI
+03E4,DISALLOWED,,COPTIC CAPITAL LETTER FEI
+03E5,PVALID,,COPTIC SMALL LETTER FEI
+03E6,DISALLOWED,,COPTIC CAPITAL LETTER KHEI
+03E7,PVALID,,COPTIC SMALL LETTER KHEI
+03E8,DISALLOWED,,COPTIC CAPITAL LETTER HORI
+03E9,PVALID,,COPTIC SMALL LETTER HORI
+03EA,DISALLOWED,,COPTIC CAPITAL LETTER GANGIA
+03EB,PVALID,,COPTIC SMALL LETTER GANGIA
+03EC,DISALLOWED,,COPTIC CAPITAL LETTER SHIMA
+03ED,PVALID,,COPTIC SMALL LETTER SHIMA
+03EE,DISALLOWED,,COPTIC CAPITAL LETTER DEI
+03EF,PVALID,,COPTIC SMALL LETTER DEI
+03F0-03F2,DISALLOWED,,GREEK KAPPA SYMBOL..GREEK LUNATE SIGMA SYMBOL
+03F3,PVALID,,GREEK LETTER YOT
+03F4-03F7,DISALLOWED,,GREEK CAPITAL THETA SYMBOL..GREEK CAPITAL LETTER SHO
+03F8,PVALID,,GREEK SMALL LETTER SHO
+03F9-03FA,DISALLOWED,,GREEK CAPITAL LUNATE SIGMA SYMBOL..GREEK CAPITAL LETTER SAN
+03FB-03FC,PVALID,,GREEK SMALL LETTER SAN..GREEK RHO WITH STROKE SYMBOL
+03FD-042F,DISALLOWED,,GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL..CYRILLIC CAPITAL LETTER YA
+0430-045F,PVALID,,CYRILLIC SMALL LETTER A..CYRILLIC SMALL LETTER DZHE
+0460,DISALLOWED,,CYRILLIC CAPITAL LETTER OMEGA
+0461,PVALID,,CYRILLIC SMALL LETTER OMEGA
+0462,DISALLOWED,,CYRILLIC CAPITAL LETTER YAT
+0463,PVALID,,CYRILLIC SMALL LETTER YAT
+0464,DISALLOWED,,CYRILLIC CAPITAL LETTER IOTIFIED E
+0465,PVALID,,CYRILLIC SMALL LETTER IOTIFIED E
+0466,DISALLOWED,,CYRILLIC CAPITAL LETTER LITTLE YUS
+0467,PVALID,,CYRILLIC SMALL LETTER LITTLE YUS
+0468,DISALLOWED,,CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS
+0469,PVALID,,CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS
+046A,DISALLOWED,,CYRILLIC CAPITAL LETTER BIG YUS
+046B,PVALID,,CYRILLIC SMALL LETTER BIG YUS
+046C,DISALLOWED,,CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS
+046D,PVALID,,CYRILLIC SMALL LETTER IOTIFIED BIG YUS
+046E,DISALLOWED,,CYRILLIC CAPITAL LETTER KSI
+046F,PVALID,,CYRILLIC SMALL LETTER KSI
+0470,DISALLOWED,,CYRILLIC CAPITAL LETTER PSI
+0471,PVALID,,CYRILLIC SMALL LETTER PSI
+0472,DISALLOWED,,CYRILLIC CAPITAL LETTER FITA
+0473,PVALID,,CYRILLIC SMALL LETTER FITA
+0474,DISALLOWED,,CYRILLIC CAPITAL LETTER IZHITSA
+0475,PVALID,,CYRILLIC SMALL LETTER IZHITSA
+0476,DISALLOWED,,CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT
+0477,PVALID,,CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT
+0478,DISALLOWED,,CYRILLIC CAPITAL LETTER UK
+0479,PVALID,,CYRILLIC SMALL LETTER UK
+047A,DISALLOWED,,CYRILLIC CAPITAL LETTER ROUND OMEGA
+047B,PVALID,,CYRILLIC SMALL LETTER ROUND OMEGA
+047C,DISALLOWED,,CYRILLIC CAPITAL LETTER OMEGA WITH TITLO
+047D,PVALID,,CYRILLIC SMALL LETTER OMEGA WITH TITLO
+047E,DISALLOWED,,CYRILLIC CAPITAL LETTER OT
+047F,PVALID,,CYRILLIC SMALL LETTER OT
+0480,DISALLOWED,,CYRILLIC CAPITAL LETTER KOPPA
+0481,PVALID,,CYRILLIC SMALL LETTER KOPPA
+0482,DISALLOWED,,CYRILLIC THOUSANDS SIGN
+0483-0487,PVALID,,COMBINING CYRILLIC TITLO..COMBINING CYRILLIC POKRYTIE
+0488-048A,DISALLOWED,,COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..CYRILLIC CAPITAL LETTER SHORT I WITH TAIL
+048B,PVALID,,CYRILLIC SMALL LETTER SHORT I WITH TAIL
+048C,DISALLOWED,,CYRILLIC CAPITAL LETTER SEMISOFT SIGN
+048D,PVALID,,CYRILLIC SMALL LETTER SEMISOFT SIGN
+048E,DISALLOWED,,CYRILLIC CAPITAL LETTER ER WITH TICK
+048F,PVALID,,CYRILLIC SMALL LETTER ER WITH TICK
+0490,DISALLOWED,,CYRILLIC CAPITAL LETTER GHE WITH UPTURN
+0491,PVALID,,CYRILLIC SMALL LETTER GHE WITH UPTURN
+0492,DISALLOWED,,CYRILLIC CAPITAL LETTER GHE WITH STROKE
+0493,PVALID,,CYRILLIC SMALL LETTER GHE WITH STROKE
+0494,DISALLOWED,,CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK
+0495,PVALID,,CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK
+0496,DISALLOWED,,CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER
+0497,PVALID,,CYRILLIC SMALL LETTER ZHE WITH DESCENDER
+0498,DISALLOWED,,CYRILLIC CAPITAL LETTER ZE WITH DESCENDER
+0499,PVALID,,CYRILLIC SMALL LETTER ZE WITH DESCENDER
+049A,DISALLOWED,,CYRILLIC CAPITAL LETTER KA WITH DESCENDER
+049B,PVALID,,CYRILLIC SMALL LETTER KA WITH DESCENDER
+049C,DISALLOWED,,CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE
+049D,PVALID,,CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE
+049E,DISALLOWED,,CYRILLIC CAPITAL LETTER KA WITH STROKE
+049F,PVALID,,CYRILLIC SMALL LETTER KA WITH STROKE
+04A0,DISALLOWED,,CYRILLIC CAPITAL LETTER BASHKIR KA
+04A1,PVALID,,CYRILLIC SMALL LETTER BASHKIR KA
+04A2,DISALLOWED,,CYRILLIC CAPITAL LETTER EN WITH DESCENDER
+04A3,PVALID,,CYRILLIC SMALL LETTER EN WITH DESCENDER
+04A4,DISALLOWED,,CYRILLIC CAPITAL LIGATURE EN GHE
+04A5,PVALID,,CYRILLIC SMALL LIGATURE EN GHE
+04A6,DISALLOWED,,CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK
+04A7,PVALID,,CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK
+04A8,DISALLOWED,,CYRILLIC CAPITAL LETTER ABKHASIAN HA
+04A9,PVALID,,CYRILLIC SMALL LETTER ABKHASIAN HA
+04AA,DISALLOWED,,CYRILLIC CAPITAL LETTER ES WITH DESCENDER
+04AB,PVALID,,CYRILLIC SMALL LETTER ES WITH DESCENDER
+04AC,DISALLOWED,,CYRILLIC CAPITAL LETTER TE WITH DESCENDER
+04AD,PVALID,,CYRILLIC SMALL LETTER TE WITH DESCENDER
+04AE,DISALLOWED,,CYRILLIC CAPITAL LETTER STRAIGHT U
+04AF,PVALID,,CYRILLIC SMALL LETTER STRAIGHT U
+04B0,DISALLOWED,,CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE
+04B1,PVALID,,CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE
+04B2,DISALLOWED,,CYRILLIC CAPITAL LETTER HA WITH DESCENDER
+04B3,PVALID,,CYRILLIC SMALL LETTER HA WITH DESCENDER
+04B4,DISALLOWED,,CYRILLIC CAPITAL LIGATURE TE TSE
+04B5,PVALID,,CYRILLIC SMALL LIGATURE TE TSE
+04B6,DISALLOWED,,CYRILLIC CAPITAL LETTER CHE WITH DESCENDER
+04B7,PVALID,,CYRILLIC SMALL LETTER CHE WITH DESCENDER
+04B8,DISALLOWED,,CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE
+04B9,PVALID,,CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE
+04BA,DISALLOWED,,CYRILLIC CAPITAL LETTER SHHA
+04BB,PVALID,,CYRILLIC SMALL LETTER SHHA
+04BC,DISALLOWED,,CYRILLIC CAPITAL LETTER ABKHASIAN CHE
+04BD,PVALID,,CYRILLIC SMALL LETTER ABKHASIAN CHE
+04BE,DISALLOWED,,CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER
+04BF,PVALID,,CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER
+04C0-04C1,DISALLOWED,,CYRILLIC LETTER PALOCHKA..CYRILLIC CAPITAL LETTER ZHE WITH BREVE
+04C2,PVALID,,CYRILLIC SMALL LETTER ZHE WITH BREVE
+04C3,DISALLOWED,,CYRILLIC CAPITAL LETTER KA WITH HOOK
+04C4,PVALID,,CYRILLIC SMALL LETTER KA WITH HOOK
+04C5,DISALLOWED,,CYRILLIC CAPITAL LETTER EL WITH TAIL
+04C6,PVALID,,CYRILLIC SMALL LETTER EL WITH TAIL
+04C7,DISALLOWED,,CYRILLIC CAPITAL LETTER EN WITH HOOK
+04C8,PVALID,,CYRILLIC SMALL LETTER EN WITH HOOK
+04C9,DISALLOWED,,CYRILLIC CAPITAL LETTER EN WITH TAIL
+04CA,PVALID,,CYRILLIC SMALL LETTER EN WITH TAIL
+04CB,DISALLOWED,,CYRILLIC CAPITAL LETTER KHAKASSIAN CHE
+04CC,PVALID,,CYRILLIC SMALL LETTER KHAKASSIAN CHE
+04CD,DISALLOWED,,CYRILLIC CAPITAL LETTER EM WITH TAIL
+04CE-04CF,PVALID,,CYRILLIC SMALL LETTER EM WITH TAIL..CYRILLIC SMALL LETTER PALOCHKA
+04D0,DISALLOWED,,CYRILLIC CAPITAL LETTER A WITH BREVE
+04D1,PVALID,,CYRILLIC SMALL LETTER A WITH BREVE
+04D2,DISALLOWED,,CYRILLIC CAPITAL LETTER A WITH DIAERESIS
+04D3,PVALID,,CYRILLIC SMALL LETTER A WITH DIAERESIS
+04D4,DISALLOWED,,CYRILLIC CAPITAL LIGATURE A IE
+04D5,PVALID,,CYRILLIC SMALL LIGATURE A IE
+04D6,DISALLOWED,,CYRILLIC CAPITAL LETTER IE WITH BREVE
+04D7,PVALID,,CYRILLIC SMALL LETTER IE WITH BREVE
+04D8,DISALLOWED,,CYRILLIC CAPITAL LETTER SCHWA
+04D9,PVALID,,CYRILLIC SMALL LETTER SCHWA
+04DA,DISALLOWED,,CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS
+04DB,PVALID,,CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS
+04DC,DISALLOWED,,CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS
+04DD,PVALID,,CYRILLIC SMALL LETTER ZHE WITH DIAERESIS
+04DE,DISALLOWED,,CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS
+04DF,PVALID,,CYRILLIC SMALL LETTER ZE WITH DIAERESIS
+04E0,DISALLOWED,,CYRILLIC CAPITAL LETTER ABKHASIAN DZE
+04E1,PVALID,,CYRILLIC SMALL LETTER ABKHASIAN DZE
+04E2,DISALLOWED,,CYRILLIC CAPITAL LETTER I WITH MACRON
+04E3,PVALID,,CYRILLIC SMALL LETTER I WITH MACRON
+04E4,DISALLOWED,,CYRILLIC CAPITAL LETTER I WITH DIAERESIS
+04E5,PVALID,,CYRILLIC SMALL LETTER I WITH DIAERESIS
+04E6,DISALLOWED,,CYRILLIC CAPITAL LETTER O WITH DIAERESIS
+04E7,PVALID,,CYRILLIC SMALL LETTER O WITH DIAERESIS
+04E8,DISALLOWED,,CYRILLIC CAPITAL LETTER BARRED O
+04E9,PVALID,,CYRILLIC SMALL LETTER BARRED O
+04EA,DISALLOWED,,CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS
+04EB,PVALID,,CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS
+04EC,DISALLOWED,,CYRILLIC CAPITAL LETTER E WITH DIAERESIS
+04ED,PVALID,,CYRILLIC SMALL LETTER E WITH DIAERESIS
+04EE,DISALLOWED,,CYRILLIC CAPITAL LETTER U WITH MACRON
+04EF,PVALID,,CYRILLIC SMALL LETTER U WITH MACRON
+04F0,DISALLOWED,,CYRILLIC CAPITAL LETTER U WITH DIAERESIS
+04F1,PVALID,,CYRILLIC SMALL LETTER U WITH DIAERESIS
+04F2,DISALLOWED,,CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE
+04F3,PVALID,,CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE
+04F4,DISALLOWED,,CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS
+04F5,PVALID,,CYRILLIC SMALL LETTER CHE WITH DIAERESIS
+04F6,DISALLOWED,,CYRILLIC CAPITAL LETTER GHE WITH DESCENDER
+04F7,PVALID,,CYRILLIC SMALL LETTER GHE WITH DESCENDER
+04F8,DISALLOWED,,CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS
+04F9,PVALID,,CYRILLIC SMALL LETTER YERU WITH DIAERESIS
+04FA,DISALLOWED,,CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK
+04FB,PVALID,,CYRILLIC SMALL LETTER GHE WITH STROKE AND HOOK
+04FC,DISALLOWED,,CYRILLIC CAPITAL LETTER HA WITH HOOK
+04FD,PVALID,,CYRILLIC SMALL LETTER HA WITH HOOK
+04FE,DISALLOWED,,CYRILLIC CAPITAL LETTER HA WITH STROKE
+04FF,PVALID,,CYRILLIC SMALL LETTER HA WITH STROKE
+0500,DISALLOWED,,CYRILLIC CAPITAL LETTER KOMI DE
+0501,PVALID,,CYRILLIC SMALL LETTER KOMI DE
+0502,DISALLOWED,,CYRILLIC CAPITAL LETTER KOMI DJE
+0503,PVALID,,CYRILLIC SMALL LETTER KOMI DJE
+0504,DISALLOWED,,CYRILLIC CAPITAL LETTER KOMI ZJE
+0505,PVALID,,CYRILLIC SMALL LETTER KOMI ZJE
+0506,DISALLOWED,,CYRILLIC CAPITAL LETTER KOMI DZJE
+0507,PVALID,,CYRILLIC SMALL LETTER KOMI DZJE
+0508,DISALLOWED,,CYRILLIC CAPITAL LETTER KOMI LJE
+0509,PVALID,,CYRILLIC SMALL LETTER KOMI LJE
+050A,DISALLOWED,,CYRILLIC CAPITAL LETTER KOMI NJE
+050B,PVALID,,CYRILLIC SMALL LETTER KOMI NJE
+050C,DISALLOWED,,CYRILLIC CAPITAL LETTER KOMI SJE
+050D,PVALID,,CYRILLIC SMALL LETTER KOMI SJE
+050E,DISALLOWED,,CYRILLIC CAPITAL LETTER KOMI TJE
+050F,PVALID,,CYRILLIC SMALL LETTER KOMI TJE
+0510,DISALLOWED,,CYRILLIC CAPITAL LETTER REVERSED ZE
+0511,PVALID,,CYRILLIC SMALL LETTER REVERSED ZE
+0512,DISALLOWED,,CYRILLIC CAPITAL LETTER EL WITH HOOK
+0513,PVALID,,CYRILLIC SMALL LETTER EL WITH HOOK
+0514,DISALLOWED,,CYRILLIC CAPITAL LETTER LHA
+0515,PVALID,,CYRILLIC SMALL LETTER LHA
+0516,DISALLOWED,,CYRILLIC CAPITAL LETTER RHA
+0517,PVALID,,CYRILLIC SMALL LETTER RHA
+0518,DISALLOWED,,CYRILLIC CAPITAL LETTER YAE
+0519,PVALID,,CYRILLIC SMALL LETTER YAE
+051A,DISALLOWED,,CYRILLIC CAPITAL LETTER QA
+051B,PVALID,,CYRILLIC SMALL LETTER QA
+051C,DISALLOWED,,CYRILLIC CAPITAL LETTER WE
+051D,PVALID,,CYRILLIC SMALL LETTER WE
+051E,DISALLOWED,,CYRILLIC CAPITAL LETTER ALEUT KA
+051F,PVALID,,CYRILLIC SMALL LETTER ALEUT KA
+0520,DISALLOWED,,CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK
+0521,PVALID,,CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK
+0522,DISALLOWED,,CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK
+0523,PVALID,,CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK
+0524,DISALLOWED,,CYRILLIC CAPITAL LETTER PE WITH DESCENDER
+0525,PVALID,,CYRILLIC SMALL LETTER PE WITH DESCENDER
+0526,DISALLOWED,,CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER
+0527,PVALID,,CYRILLIC SMALL LETTER SHHA WITH DESCENDER
+0528,DISALLOWED,,CYRILLIC CAPITAL LETTER EN WITH LEFT HOOK
+0529,PVALID,,CYRILLIC SMALL LETTER EN WITH LEFT HOOK
+052A,DISALLOWED,,CYRILLIC CAPITAL LETTER DZZHE
+052B,PVALID,,CYRILLIC SMALL LETTER DZZHE
+052C,DISALLOWED,,CYRILLIC CAPITAL LETTER DCHE
+052D,PVALID,,CYRILLIC SMALL LETTER DCHE
+052E,DISALLOWED,,CYRILLIC CAPITAL LETTER EL WITH DESCENDER
+052F,PVALID,,CYRILLIC SMALL LETTER EL WITH DESCENDER
+0530,UNASSIGNED,,<RESERVED>
+0531-0556,DISALLOWED,,ARMENIAN CAPITAL LETTER AYB..ARMENIAN CAPITAL LETTER FEH
+0557-0558,UNASSIGNED,,<RESERVED>..<RESERVED>
+0559,PVALID,,ARMENIAN MODIFIER LETTER LEFT HALF RING
+055A-055F,DISALLOWED,,ARMENIAN APOSTROPHE..ARMENIAN ABBREVIATION MARK
+0560-0586,PVALID,,ARMENIAN SMALL LETTER TURNED AYB..ARMENIAN SMALL LETTER FEH
+0587,DISALLOWED,,ARMENIAN SMALL LIGATURE ECH YIWN
+0588,PVALID,,ARMENIAN SMALL LETTER YI WITH STROKE
+0589-058A,DISALLOWED,,ARMENIAN FULL STOP..ARMENIAN HYPHEN
+058B-058C,UNASSIGNED,,<RESERVED>..<RESERVED>
+058D-058F,DISALLOWED,,RIGHT-FACING ARMENIAN ETERNITY SIGN..ARMENIAN DRAM SIGN
+0590,UNASSIGNED,,<RESERVED>
+0591-05BD,PVALID,,HEBREW ACCENT ETNAHTA..HEBREW POINT METEG
+05BE,DISALLOWED,,HEBREW PUNCTUATION MAQAF
+05BF,PVALID,,HEBREW POINT RAFE
+05C0,DISALLOWED,,HEBREW PUNCTUATION PASEQ
+05C1-05C2,PVALID,,HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT
+05C3,DISALLOWED,,HEBREW PUNCTUATION SOF PASUQ
+05C4-05C5,PVALID,,HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT
+05C6,DISALLOWED,,HEBREW PUNCTUATION NUN HAFUKHA
+05C7,PVALID,,HEBREW POINT QAMATS QATAN
+05C8-05CF,UNASSIGNED,,<RESERVED>..<RESERVED>
+05D0-05EA,PVALID,,HEBREW LETTER ALEF..HEBREW LETTER TAV
+05EB-05EE,UNASSIGNED,,<RESERVED>..<RESERVED>
+05EF-05F2,PVALID,,HEBREW YOD TRIANGLE..HEBREW LIGATURE YIDDISH DOUBLE YOD
+05F3-05F4,CONTEXTO,,HEBREW PUNCTUATION GERESH..HEBREW PUNCTUATION GERSHAYIM
+05F5-05FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+0600-060F,DISALLOWED,,ARABIC NUMBER SIGN..ARABIC SIGN MISRA
+0610-061A,PVALID,,ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA
+061B-061C,DISALLOWED,,ARABIC SEMICOLON..ARABIC LETTER MARK
+061D,UNASSIGNED,,<RESERVED>
+061E-061F,DISALLOWED,,ARABIC TRIPLE DOT PUNCTUATION MARK..ARABIC QUESTION MARK
+0620-063F,PVALID,,ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE
+0640,DISALLOWED,,ARABIC TATWEEL
+0641-065F,PVALID,,ARABIC LETTER FEH..ARABIC WAVY HAMZA BELOW
+0660-0669,CONTEXTO,,ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE
+066A-066D,DISALLOWED,,ARABIC PERCENT SIGN..ARABIC FIVE POINTED STAR
+066E-0674,PVALID,,ARABIC LETTER DOTLESS BEH..ARABIC LETTER HIGH HAMZA
+0675-0678,DISALLOWED,,ARABIC LETTER HIGH HAMZA ALEF..ARABIC LETTER HIGH HAMZA YEH
+0679-06D3,PVALID,,ARABIC LETTER TTEH..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE
+06D4,DISALLOWED,,ARABIC FULL STOP
+06D5-06DC,PVALID,,ARABIC LETTER AE..ARABIC SMALL HIGH SEEN
+06DD-06DE,DISALLOWED,,ARABIC END OF AYAH..ARABIC START OF RUB EL HIZB
+06DF-06E8,PVALID,,ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH NOON
+06E9,DISALLOWED,,ARABIC PLACE OF SAJDAH
+06EA-06EF,PVALID,,ARABIC EMPTY CENTRE LOW STOP..ARABIC LETTER REH WITH INVERTED V
+06F0-06F9,CONTEXTO,,EXTENDED ARABIC-INDIC DIGIT ZERO..EXTENDED ARABIC-INDIC DIGIT NINE
+06FA-06FF,PVALID,,ARABIC LETTER SHEEN WITH DOT BELOW..ARABIC LETTER HEH WITH INVERTED V
+0700-070D,DISALLOWED,,SYRIAC END OF PARAGRAPH..SYRIAC HARKLEAN ASTERISCUS
+070E,UNASSIGNED,,<RESERVED>
+070F,DISALLOWED,,SYRIAC ABBREVIATION MARK
+0710-074A,PVALID,,SYRIAC LETTER ALAPH..SYRIAC BARREKH
+074B-074C,UNASSIGNED,,<RESERVED>..<RESERVED>
+074D-07B1,PVALID,,SYRIAC LETTER SOGDIAN ZHAIN..THAANA LETTER NAA
+07B2-07BF,UNASSIGNED,,<RESERVED>..<RESERVED>
+07C0-07F5,PVALID,,NKO DIGIT ZERO..NKO LOW TONE APOSTROPHE
+07F6-07FA,DISALLOWED,,NKO SYMBOL OO DENNEN..NKO LAJANYALAN
+07FB-07FC,UNASSIGNED,,<RESERVED>..<RESERVED>
+07FD,PVALID,,NKO DANTAYALAN
+07FE-07FF,DISALLOWED,,NKO DOROME SIGN..NKO TAMAN SIGN
+0800-082D,PVALID,,SAMARITAN LETTER ALAF..SAMARITAN MARK NEQUDAA
+082E-082F,UNASSIGNED,,<RESERVED>..<RESERVED>
+0830-083E,DISALLOWED,,SAMARITAN PUNCTUATION NEQUDAA..SAMARITAN PUNCTUATION ANNAAU
+083F,UNASSIGNED,,<RESERVED>
+0840-085B,PVALID,,MANDAIC LETTER HALQA..MANDAIC GEMINATION MARK
+085C-085D,UNASSIGNED,,<RESERVED>..<RESERVED>
+085E,DISALLOWED,,MANDAIC PUNCTUATION
+085F,UNASSIGNED,,<RESERVED>
+0860-086A,PVALID,,SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA
+086B-089F,UNASSIGNED,,<RESERVED>..<RESERVED>
+08A0-08B4,PVALID,,ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER KAF WITH DOT BELOW
+08B5,UNASSIGNED,,<RESERVED>
+08B6-08BD,PVALID,,ARABIC LETTER BEH WITH SMALL MEEM ABOVE..ARABIC LETTER AFRICAN NOON
+08BE-08D2,UNASSIGNED,,<RESERVED>..<RESERVED>
+08D3-08E1,PVALID,,ARABIC SMALL LOW WAW..ARABIC SMALL HIGH SIGN SAFHA
+08E2,DISALLOWED,,ARABIC DISPUTED END OF AYAH
+08E3-0957,PVALID,,ARABIC TURNED DAMMA BELOW..DEVANAGARI VOWEL SIGN UUE
+0958-095F,DISALLOWED,,DEVANAGARI LETTER QA..DEVANAGARI LETTER YYA
+0960-0963,PVALID,,DEVANAGARI LETTER VOCALIC RR..DEVANAGARI VOWEL SIGN VOCALIC LL
+0964-0965,DISALLOWED,,DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA
+0966-096F,PVALID,,DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE
+0970,DISALLOWED,,DEVANAGARI ABBREVIATION SIGN
+0971-0983,PVALID,,DEVANAGARI SIGN HIGH SPACING DOT..BENGALI SIGN VISARGA
+0984,UNASSIGNED,,<RESERVED>
+0985-098C,PVALID,,BENGALI LETTER A..BENGALI LETTER VOCALIC L
+098D-098E,UNASSIGNED,,<RESERVED>..<RESERVED>
+098F-0990,PVALID,,BENGALI LETTER E..BENGALI LETTER AI
+0991-0992,UNASSIGNED,,<RESERVED>..<RESERVED>
+0993-09A8,PVALID,,BENGALI LETTER O..BENGALI LETTER NA
+09A9,UNASSIGNED,,<RESERVED>
+09AA-09B0,PVALID,,BENGALI LETTER PA..BENGALI LETTER RA
+09B1,UNASSIGNED,,<RESERVED>
+09B2,PVALID,,BENGALI LETTER LA
+09B3-09B5,UNASSIGNED,,<RESERVED>..<RESERVED>
+09B6-09B9,PVALID,,BENGALI LETTER SHA..BENGALI LETTER HA
+09BA-09BB,UNASSIGNED,,<RESERVED>..<RESERVED>
+09BC-09C4,PVALID,,BENGALI SIGN NUKTA..BENGALI VOWEL SIGN VOCALIC RR
+09C5-09C6,UNASSIGNED,,<RESERVED>..<RESERVED>
+09C7-09C8,PVALID,,BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI
+09C9-09CA,UNASSIGNED,,<RESERVED>..<RESERVED>
+09CB-09CE,PVALID,,BENGALI VOWEL SIGN O..BENGALI LETTER KHANDA TA
+09CF-09D6,UNASSIGNED,,<RESERVED>..<RESERVED>
+09D7,PVALID,,BENGALI AU LENGTH MARK
+09D8-09DB,UNASSIGNED,,<RESERVED>..<RESERVED>
+09DC-09DD,DISALLOWED,,BENGALI LETTER RRA..BENGALI LETTER RHA
+09DE,UNASSIGNED,,<RESERVED>
+09DF,DISALLOWED,,BENGALI LETTER YYA
+09E0-09E3,PVALID,,BENGALI LETTER VOCALIC RR..BENGALI VOWEL SIGN VOCALIC LL
+09E4-09E5,UNASSIGNED,,<RESERVED>..<RESERVED>
+09E6-09F1,PVALID,,BENGALI DIGIT ZERO..BENGALI LETTER RA WITH LOWER DIAGONAL
+09F2-09FB,DISALLOWED,,BENGALI RUPEE MARK..BENGALI GANDA MARK
+09FC,PVALID,,BENGALI LETTER VEDIC ANUSVARA
+09FD,DISALLOWED,,BENGALI ABBREVIATION SIGN
+09FE,PVALID,,BENGALI SANDHI MARK
+09FF-0A00,UNASSIGNED,,<RESERVED>..<RESERVED>
+0A01-0A03,PVALID,,GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN VISARGA
+0A04,UNASSIGNED,,<RESERVED>
+0A05-0A0A,PVALID,,GURMUKHI LETTER A..GURMUKHI LETTER UU
+0A0B-0A0E,UNASSIGNED,,<RESERVED>..<RESERVED>
+0A0F-0A10,PVALID,,GURMUKHI LETTER EE..GURMUKHI LETTER AI
+0A11-0A12,UNASSIGNED,,<RESERVED>..<RESERVED>
+0A13-0A28,PVALID,,GURMUKHI LETTER OO..GURMUKHI LETTER NA
+0A29,UNASSIGNED,,<RESERVED>
+0A2A-0A30,PVALID,,GURMUKHI LETTER PA..GURMUKHI LETTER RA
+0A31,UNASSIGNED,,<RESERVED>
+0A32,PVALID,,GURMUKHI LETTER LA
+0A33,DISALLOWED,,GURMUKHI LETTER LLA
+0A34,UNASSIGNED,,<RESERVED>
+0A35,PVALID,,GURMUKHI LETTER VA
+0A36,DISALLOWED,,GURMUKHI LETTER SHA
+0A37,UNASSIGNED,,<RESERVED>
+0A38-0A39,PVALID,,GURMUKHI LETTER SA..GURMUKHI LETTER HA
+0A3A-0A3B,UNASSIGNED,,<RESERVED>..<RESERVED>
+0A3C,PVALID,,GURMUKHI SIGN NUKTA
+0A3D,UNASSIGNED,,<RESERVED>
+0A3E-0A42,PVALID,,GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN UU
+0A43-0A46,UNASSIGNED,,<RESERVED>..<RESERVED>
+0A47-0A48,PVALID,,GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI
+0A49-0A4A,UNASSIGNED,,<RESERVED>..<RESERVED>
+0A4B-0A4D,PVALID,,GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA
+0A4E-0A50,UNASSIGNED,,<RESERVED>..<RESERVED>
+0A51,PVALID,,GURMUKHI SIGN UDAAT
+0A52-0A58,UNASSIGNED,,<RESERVED>..<RESERVED>
+0A59-0A5B,DISALLOWED,,GURMUKHI LETTER KHHA..GURMUKHI LETTER ZA
+0A5C,PVALID,,GURMUKHI LETTER RRA
+0A5D,UNASSIGNED,,<RESERVED>
+0A5E,DISALLOWED,,GURMUKHI LETTER FA
+0A5F-0A65,UNASSIGNED,,<RESERVED>..<RESERVED>
+0A66-0A75,PVALID,,GURMUKHI DIGIT ZERO..GURMUKHI SIGN YAKASH
+0A76,DISALLOWED,,GURMUKHI ABBREVIATION SIGN
+0A77-0A80,UNASSIGNED,,<RESERVED>..<RESERVED>
+0A81-0A83,PVALID,,GUJARATI SIGN CANDRABINDU..GUJARATI SIGN VISARGA
+0A84,UNASSIGNED,,<RESERVED>
+0A85-0A8D,PVALID,,GUJARATI LETTER A..GUJARATI VOWEL CANDRA E
+0A8E,UNASSIGNED,,<RESERVED>
+0A8F-0A91,PVALID,,GUJARATI LETTER E..GUJARATI VOWEL CANDRA O
+0A92,UNASSIGNED,,<RESERVED>
+0A93-0AA8,PVALID,,GUJARATI LETTER O..GUJARATI LETTER NA
+0AA9,UNASSIGNED,,<RESERVED>
+0AAA-0AB0,PVALID,,GUJARATI LETTER PA..GUJARATI LETTER RA
+0AB1,UNASSIGNED,,<RESERVED>
+0AB2-0AB3,PVALID,,GUJARATI LETTER LA..GUJARATI LETTER LLA
+0AB4,UNASSIGNED,,<RESERVED>
+0AB5-0AB9,PVALID,,GUJARATI LETTER VA..GUJARATI LETTER HA
+0ABA-0ABB,UNASSIGNED,,<RESERVED>..<RESERVED>
+0ABC-0AC5,PVALID,,GUJARATI SIGN NUKTA..GUJARATI VOWEL SIGN CANDRA E
+0AC6,UNASSIGNED,,<RESERVED>
+0AC7-0AC9,PVALID,,GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN CANDRA O
+0ACA,UNASSIGNED,,<RESERVED>
+0ACB-0ACD,PVALID,,GUJARATI VOWEL SIGN O..GUJARATI SIGN VIRAMA
+0ACE-0ACF,UNASSIGNED,,<RESERVED>..<RESERVED>
+0AD0,PVALID,,GUJARATI OM
+0AD1-0ADF,UNASSIGNED,,<RESERVED>..<RESERVED>
+0AE0-0AE3,PVALID,,GUJARATI LETTER VOCALIC RR..GUJARATI VOWEL SIGN VOCALIC LL
+0AE4-0AE5,UNASSIGNED,,<RESERVED>..<RESERVED>
+0AE6-0AEF,PVALID,,GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE
+0AF0-0AF1,DISALLOWED,,GUJARATI ABBREVIATION SIGN..GUJARATI RUPEE SIGN
+0AF2-0AF8,UNASSIGNED,,<RESERVED>..<RESERVED>
+0AF9-0AFF,PVALID,,GUJARATI LETTER ZHA..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE
+0B00,UNASSIGNED,,<RESERVED>
+0B01-0B03,PVALID,,ORIYA SIGN CANDRABINDU..ORIYA SIGN VISARGA
+0B04,UNASSIGNED,,<RESERVED>
+0B05-0B0C,PVALID,,ORIYA LETTER A..ORIYA LETTER VOCALIC L
+0B0D-0B0E,UNASSIGNED,,<RESERVED>..<RESERVED>
+0B0F-0B10,PVALID,,ORIYA LETTER E..ORIYA LETTER AI
+0B11-0B12,UNASSIGNED,,<RESERVED>..<RESERVED>
+0B13-0B28,PVALID,,ORIYA LETTER O..ORIYA LETTER NA
+0B29,UNASSIGNED,,<RESERVED>
+0B2A-0B30,PVALID,,ORIYA LETTER PA..ORIYA LETTER RA
+0B31,UNASSIGNED,,<RESERVED>
+0B32-0B33,PVALID,,ORIYA LETTER LA..ORIYA LETTER LLA
+0B34,UNASSIGNED,,<RESERVED>
+0B35-0B39,PVALID,,ORIYA LETTER VA..ORIYA LETTER HA
+0B3A-0B3B,UNASSIGNED,,<RESERVED>..<RESERVED>
+0B3C-0B44,PVALID,,ORIYA SIGN NUKTA..ORIYA VOWEL SIGN VOCALIC RR
+0B45-0B46,UNASSIGNED,,<RESERVED>..<RESERVED>
+0B47-0B48,PVALID,,ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI
+0B49-0B4A,UNASSIGNED,,<RESERVED>..<RESERVED>
+0B4B-0B4D,PVALID,,ORIYA VOWEL SIGN O..ORIYA SIGN VIRAMA
+0B4E-0B55,UNASSIGNED,,<RESERVED>..<RESERVED>
+0B56-0B57,PVALID,,ORIYA AI LENGTH MARK..ORIYA AU LENGTH MARK
+0B58-0B5B,UNASSIGNED,,<RESERVED>..<RESERVED>
+0B5C-0B5D,DISALLOWED,,ORIYA LETTER RRA..ORIYA LETTER RHA
+0B5E,UNASSIGNED,,<RESERVED>
+0B5F-0B63,PVALID,,ORIYA LETTER YYA..ORIYA VOWEL SIGN VOCALIC LL
+0B64-0B65,UNASSIGNED,,<RESERVED>..<RESERVED>
+0B66-0B6F,PVALID,,ORIYA DIGIT ZERO..ORIYA DIGIT NINE
+0B70,DISALLOWED,,ORIYA ISSHAR
+0B71,PVALID,,ORIYA LETTER WA
+0B72-0B77,DISALLOWED,,ORIYA FRACTION ONE QUARTER..ORIYA FRACTION THREE SIXTEENTHS
+0B78-0B81,UNASSIGNED,,<RESERVED>..<RESERVED>
+0B82-0B83,PVALID,,TAMIL SIGN ANUSVARA..TAMIL SIGN VISARGA
+0B84,UNASSIGNED,,<RESERVED>
+0B85-0B8A,PVALID,,TAMIL LETTER A..TAMIL LETTER UU
+0B8B-0B8D,UNASSIGNED,,<RESERVED>..<RESERVED>
+0B8E-0B90,PVALID,,TAMIL LETTER E..TAMIL LETTER AI
+0B91,UNASSIGNED,,<RESERVED>
+0B92-0B95,PVALID,,TAMIL LETTER O..TAMIL LETTER KA
+0B96-0B98,UNASSIGNED,,<RESERVED>..<RESERVED>
+0B99-0B9A,PVALID,,TAMIL LETTER NGA..TAMIL LETTER CA
+0B9B,UNASSIGNED,,<RESERVED>
+0B9C,PVALID,,TAMIL LETTER JA
+0B9D,UNASSIGNED,,<RESERVED>
+0B9E-0B9F,PVALID,,TAMIL LETTER NYA..TAMIL LETTER TTA
+0BA0-0BA2,UNASSIGNED,,<RESERVED>..<RESERVED>
+0BA3-0BA4,PVALID,,TAMIL LETTER NNA..TAMIL LETTER TA
+0BA5-0BA7,UNASSIGNED,,<RESERVED>..<RESERVED>
+0BA8-0BAA,PVALID,,TAMIL LETTER NA..TAMIL LETTER PA
+0BAB-0BAD,UNASSIGNED,,<RESERVED>..<RESERVED>
+0BAE-0BB9,PVALID,,TAMIL LETTER MA..TAMIL LETTER HA
+0BBA-0BBD,UNASSIGNED,,<RESERVED>..<RESERVED>
+0BBE-0BC2,PVALID,,TAMIL VOWEL SIGN AA..TAMIL VOWEL SIGN UU
+0BC3-0BC5,UNASSIGNED,,<RESERVED>..<RESERVED>
+0BC6-0BC8,PVALID,,TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI
+0BC9,UNASSIGNED,,<RESERVED>
+0BCA-0BCD,PVALID,,TAMIL VOWEL SIGN O..TAMIL SIGN VIRAMA
+0BCE-0BCF,UNASSIGNED,,<RESERVED>..<RESERVED>
+0BD0,PVALID,,TAMIL OM
+0BD1-0BD6,UNASSIGNED,,<RESERVED>..<RESERVED>
+0BD7,PVALID,,TAMIL AU LENGTH MARK
+0BD8-0BE5,UNASSIGNED,,<RESERVED>..<RESERVED>
+0BE6-0BEF,PVALID,,TAMIL DIGIT ZERO..TAMIL DIGIT NINE
+0BF0-0BFA,DISALLOWED,,TAMIL NUMBER TEN..TAMIL NUMBER SIGN
+0BFB-0BFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+0C00-0C0C,PVALID,,TELUGU SIGN COMBINING CANDRABINDU ABOVE..TELUGU LETTER VOCALIC L
+0C0D,UNASSIGNED,,<RESERVED>
+0C0E-0C10,PVALID,,TELUGU LETTER E..TELUGU LETTER AI
+0C11,UNASSIGNED,,<RESERVED>
+0C12-0C28,PVALID,,TELUGU LETTER O..TELUGU LETTER NA
+0C29,UNASSIGNED,,<RESERVED>
+0C2A-0C39,PVALID,,TELUGU LETTER PA..TELUGU LETTER HA
+0C3A-0C3C,UNASSIGNED,,<RESERVED>..<RESERVED>
+0C3D-0C44,PVALID,,TELUGU SIGN AVAGRAHA..TELUGU VOWEL SIGN VOCALIC RR
+0C45,UNASSIGNED,,<RESERVED>
+0C46-0C48,PVALID,,TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI
+0C49,UNASSIGNED,,<RESERVED>
+0C4A-0C4D,PVALID,,TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA
+0C4E-0C54,UNASSIGNED,,<RESERVED>..<RESERVED>
+0C55-0C56,PVALID,,TELUGU LENGTH MARK..TELUGU AI LENGTH MARK
+0C57,UNASSIGNED,,<RESERVED>
+0C58-0C5A,PVALID,,TELUGU LETTER TSA..TELUGU LETTER RRRA
+0C5B-0C5F,UNASSIGNED,,<RESERVED>..<RESERVED>
+0C60-0C63,PVALID,,TELUGU LETTER VOCALIC RR..TELUGU VOWEL SIGN VOCALIC LL
+0C64-0C65,UNASSIGNED,,<RESERVED>..<RESERVED>
+0C66-0C6F,PVALID,,TELUGU DIGIT ZERO..TELUGU DIGIT NINE
+0C70-0C77,UNASSIGNED,,<RESERVED>..<RESERVED>
+0C78-0C7F,DISALLOWED,,TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR..TELUGU SIGN TUUMU
+0C80-0C83,PVALID,,KANNADA SIGN SPACING CANDRABINDU..KANNADA SIGN VISARGA
+0C84,DISALLOWED,,KANNADA SIGN SIDDHAM
+0C85-0C8C,PVALID,,KANNADA LETTER A..KANNADA LETTER VOCALIC L
+0C8D,UNASSIGNED,,<RESERVED>
+0C8E-0C90,PVALID,,KANNADA LETTER E..KANNADA LETTER AI
+0C91,UNASSIGNED,,<RESERVED>
+0C92-0CA8,PVALID,,KANNADA LETTER O..KANNADA LETTER NA
+0CA9,UNASSIGNED,,<RESERVED>
+0CAA-0CB3,PVALID,,KANNADA LETTER PA..KANNADA LETTER LLA
+0CB4,UNASSIGNED,,<RESERVED>
+0CB5-0CB9,PVALID,,KANNADA LETTER VA..KANNADA LETTER HA
+0CBA-0CBB,UNASSIGNED,,<RESERVED>..<RESERVED>
+0CBC-0CC4,PVALID,,KANNADA SIGN NUKTA..KANNADA VOWEL SIGN VOCALIC RR
+0CC5,UNASSIGNED,,<RESERVED>
+0CC6-0CC8,PVALID,,KANNADA VOWEL SIGN E..KANNADA VOWEL SIGN AI
+0CC9,UNASSIGNED,,<RESERVED>
+0CCA-0CCD,PVALID,,KANNADA VOWEL SIGN O..KANNADA SIGN VIRAMA
+0CCE-0CD4,UNASSIGNED,,<RESERVED>..<RESERVED>
+0CD5-0CD6,PVALID,,KANNADA LENGTH MARK..KANNADA AI LENGTH MARK
+0CD7-0CDD,UNASSIGNED,,<RESERVED>..<RESERVED>
+0CDE,PVALID,,KANNADA LETTER FA
+0CDF,UNASSIGNED,,<RESERVED>
+0CE0-0CE3,PVALID,,KANNADA LETTER VOCALIC RR..KANNADA VOWEL SIGN VOCALIC LL
+0CE4-0CE5,UNASSIGNED,,<RESERVED>..<RESERVED>
+0CE6-0CEF,PVALID,,KANNADA DIGIT ZERO..KANNADA DIGIT NINE
+0CF0,UNASSIGNED,,<RESERVED>
+0CF1-0CF2,PVALID,,KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA
+0CF3-0CFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+0D00-0D03,PVALID,,MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN VISARGA
+0D04,UNASSIGNED,,<RESERVED>
+0D05-0D0C,PVALID,,MALAYALAM LETTER A..MALAYALAM LETTER VOCALIC L
+0D0D,UNASSIGNED,,<RESERVED>
+0D0E-0D10,PVALID,,MALAYALAM LETTER E..MALAYALAM LETTER AI
+0D11,UNASSIGNED,,<RESERVED>
+0D12-0D44,PVALID,,MALAYALAM LETTER O..MALAYALAM VOWEL SIGN VOCALIC RR
+0D45,UNASSIGNED,,<RESERVED>
+0D46-0D48,PVALID,,MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI
+0D49,UNASSIGNED,,<RESERVED>
+0D4A-0D4E,PVALID,,MALAYALAM VOWEL SIGN O..MALAYALAM LETTER DOT REPH
+0D4F,DISALLOWED,,MALAYALAM SIGN PARA
+0D50-0D53,UNASSIGNED,,<RESERVED>..<RESERVED>
+0D54-0D57,PVALID,,MALAYALAM LETTER CHILLU M..MALAYALAM AU LENGTH MARK
+0D58-0D5E,DISALLOWED,,MALAYALAM FRACTION ONE ONE-HUNDRED-AND-SIXTIETH..MALAYALAM FRACTION ONE FIFTH
+0D5F-0D63,PVALID,,MALAYALAM LETTER ARCHAIC II..MALAYALAM VOWEL SIGN VOCALIC LL
+0D64-0D65,UNASSIGNED,,<RESERVED>..<RESERVED>
+0D66-0D6F,PVALID,,MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE
+0D70-0D79,DISALLOWED,,MALAYALAM NUMBER TEN..MALAYALAM DATE MARK
+0D7A-0D7F,PVALID,,MALAYALAM LETTER CHILLU NN..MALAYALAM LETTER CHILLU K
+0D80-0D81,UNASSIGNED,,<RESERVED>..<RESERVED>
+0D82-0D83,PVALID,,SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA
+0D84,UNASSIGNED,,<RESERVED>
+0D85-0D96,PVALID,,SINHALA LETTER AYANNA..SINHALA LETTER AUYANNA
+0D97-0D99,UNASSIGNED,,<RESERVED>..<RESERVED>
+0D9A-0DB1,PVALID,,SINHALA LETTER ALPAPRAANA KAYANNA..SINHALA LETTER DANTAJA NAYANNA
+0DB2,UNASSIGNED,,<RESERVED>
+0DB3-0DBB,PVALID,,SINHALA LETTER SANYAKA DAYANNA..SINHALA LETTER RAYANNA
+0DBC,UNASSIGNED,,<RESERVED>
+0DBD,PVALID,,SINHALA LETTER DANTAJA LAYANNA
+0DBE-0DBF,UNASSIGNED,,<RESERVED>..<RESERVED>
+0DC0-0DC6,PVALID,,SINHALA LETTER VAYANNA..SINHALA LETTER FAYANNA
+0DC7-0DC9,UNASSIGNED,,<RESERVED>..<RESERVED>
+0DCA,PVALID,,SINHALA SIGN AL-LAKUNA
+0DCB-0DCE,UNASSIGNED,,<RESERVED>..<RESERVED>
+0DCF-0DD4,PVALID,,SINHALA VOWEL SIGN AELA-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA
+0DD5,UNASSIGNED,,<RESERVED>
+0DD6,PVALID,,SINHALA VOWEL SIGN DIGA PAA-PILLA
+0DD7,UNASSIGNED,,<RESERVED>
+0DD8-0DDF,PVALID,,SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN GAYANUKITTA
+0DE0-0DE5,UNASSIGNED,,<RESERVED>..<RESERVED>
+0DE6-0DEF,PVALID,,SINHALA LITH DIGIT ZERO..SINHALA LITH DIGIT NINE
+0DF0-0DF1,UNASSIGNED,,<RESERVED>..<RESERVED>
+0DF2-0DF3,PVALID,,SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA
+0DF4,DISALLOWED,,SINHALA PUNCTUATION KUNDDALIYA
+0DF5-0E00,UNASSIGNED,,<RESERVED>..<RESERVED>
+0E01-0E32,PVALID,,THAI CHARACTER KO KAI..THAI CHARACTER SARA AA
+0E33,DISALLOWED,,THAI CHARACTER SARA AM
+0E34-0E3A,PVALID,,THAI CHARACTER SARA I..THAI CHARACTER PHINTHU
+0E3B-0E3E,UNASSIGNED,,<RESERVED>..<RESERVED>
+0E3F,DISALLOWED,,THAI CURRENCY SYMBOL BAHT
+0E40-0E4E,PVALID,,THAI CHARACTER SARA E..THAI CHARACTER YAMAKKAN
+0E4F,DISALLOWED,,THAI CHARACTER FONGMAN
+0E50-0E59,PVALID,,THAI DIGIT ZERO..THAI DIGIT NINE
+0E5A-0E5B,DISALLOWED,,THAI CHARACTER ANGKHANKHU..THAI CHARACTER KHOMUT
+0E5C-0E80,UNASSIGNED,,<RESERVED>..<RESERVED>
+0E81-0E82,PVALID,,LAO LETTER KO..LAO LETTER KHO SUNG
+0E83,UNASSIGNED,,<RESERVED>
+0E84,PVALID,,LAO LETTER KHO TAM
+0E85-0E86,UNASSIGNED,,<RESERVED>..<RESERVED>
+0E87-0E88,PVALID,,LAO LETTER NGO..LAO LETTER CO
+0E89,UNASSIGNED,,<RESERVED>
+0E8A,PVALID,,LAO LETTER SO TAM
+0E8B-0E8C,UNASSIGNED,,<RESERVED>..<RESERVED>
+0E8D,PVALID,,LAO LETTER NYO
+0E8E-0E93,UNASSIGNED,,<RESERVED>..<RESERVED>
+0E94-0E97,PVALID,,LAO LETTER DO..LAO LETTER THO TAM
+0E98,UNASSIGNED,,<RESERVED>
+0E99-0E9F,PVALID,,LAO LETTER NO..LAO LETTER FO SUNG
+0EA0,UNASSIGNED,,<RESERVED>
+0EA1-0EA3,PVALID,,LAO LETTER MO..LAO LETTER LO LING
+0EA4,UNASSIGNED,,<RESERVED>
+0EA5,PVALID,,LAO LETTER LO LOOT
+0EA6,UNASSIGNED,,<RESERVED>
+0EA7,PVALID,,LAO LETTER WO
+0EA8-0EA9,UNASSIGNED,,<RESERVED>..<RESERVED>
+0EAA-0EAB,PVALID,,LAO LETTER SO SUNG..LAO LETTER HO SUNG
+0EAC,UNASSIGNED,,<RESERVED>
+0EAD-0EB2,PVALID,,LAO LETTER O..LAO VOWEL SIGN AA
+0EB3,DISALLOWED,,LAO VOWEL SIGN AM
+0EB4-0EB9,PVALID,,LAO VOWEL SIGN I..LAO VOWEL SIGN UU
+0EBA,UNASSIGNED,,<RESERVED>
+0EBB-0EBD,PVALID,,LAO VOWEL SIGN MAI KON..LAO SEMIVOWEL SIGN NYO
+0EBE-0EBF,UNASSIGNED,,<RESERVED>..<RESERVED>
+0EC0-0EC4,PVALID,,LAO VOWEL SIGN E..LAO VOWEL SIGN AI
+0EC5,UNASSIGNED,,<RESERVED>
+0EC6,PVALID,,LAO KO LA
+0EC7,UNASSIGNED,,<RESERVED>
+0EC8-0ECD,PVALID,,LAO TONE MAI EK..LAO NIGGAHITA
+0ECE-0ECF,UNASSIGNED,,<RESERVED>..<RESERVED>
+0ED0-0ED9,PVALID,,LAO DIGIT ZERO..LAO DIGIT NINE
+0EDA-0EDB,UNASSIGNED,,<RESERVED>..<RESERVED>
+0EDC-0EDD,DISALLOWED,,LAO HO NO..LAO HO MO
+0EDE-0EDF,PVALID,,LAO LETTER KHMU GO..LAO LETTER KHMU NYO
+0EE0-0EFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+0F00,PVALID,,TIBETAN SYLLABLE OM
+0F01-0F0A,DISALLOWED,,TIBETAN MARK GTER YIG MGO TRUNCATED A..TIBETAN MARK BKA- SHOG YIG MGO
+0F0B,PVALID,,TIBETAN MARK INTERSYLLABIC TSHEG
+0F0C-0F17,DISALLOWED,,TIBETAN MARK DELIMITER TSHEG BSTAR..TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS
+0F18-0F19,PVALID,,TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS
+0F1A-0F1F,DISALLOWED,,TIBETAN SIGN RDEL DKAR GCIG..TIBETAN SIGN RDEL DKAR RDEL NAG
+0F20-0F29,PVALID,,TIBETAN DIGIT ZERO..TIBETAN DIGIT NINE
+0F2A-0F34,DISALLOWED,,TIBETAN DIGIT HALF ONE..TIBETAN MARK BSDUS RTAGS
+0F35,PVALID,,TIBETAN MARK NGAS BZUNG NYI ZLA
+0F36,DISALLOWED,,TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN
+0F37,PVALID,,TIBETAN MARK NGAS BZUNG SGOR RTAGS
+0F38,DISALLOWED,,TIBETAN MARK CHE MGO
+0F39,PVALID,,TIBETAN MARK TSA -PHRU
+0F3A-0F3D,DISALLOWED,,TIBETAN MARK GUG RTAGS GYON..TIBETAN MARK ANG KHANG GYAS
+0F3E-0F42,PVALID,,TIBETAN SIGN YAR TSHES..TIBETAN LETTER GA
+0F43,DISALLOWED,,TIBETAN LETTER GHA
+0F44-0F47,PVALID,,TIBETAN LETTER NGA..TIBETAN LETTER JA
+0F48,UNASSIGNED,,<RESERVED>
+0F49-0F4C,PVALID,,TIBETAN LETTER NYA..TIBETAN LETTER DDA
+0F4D,DISALLOWED,,TIBETAN LETTER DDHA
+0F4E-0F51,PVALID,,TIBETAN LETTER NNA..TIBETAN LETTER DA
+0F52,DISALLOWED,,TIBETAN LETTER DHA
+0F53-0F56,PVALID,,TIBETAN LETTER NA..TIBETAN LETTER BA
+0F57,DISALLOWED,,TIBETAN LETTER BHA
+0F58-0F5B,PVALID,,TIBETAN LETTER MA..TIBETAN LETTER DZA
+0F5C,DISALLOWED,,TIBETAN LETTER DZHA
+0F5D-0F68,PVALID,,TIBETAN LETTER WA..TIBETAN LETTER A
+0F69,DISALLOWED,,TIBETAN LETTER KSSA
+0F6A-0F6C,PVALID,,TIBETAN LETTER FIXED-FORM RA..TIBETAN LETTER RRA
+0F6D-0F70,UNASSIGNED,,<RESERVED>..<RESERVED>
+0F71-0F72,PVALID,,TIBETAN VOWEL SIGN AA..TIBETAN VOWEL SIGN I
+0F73,DISALLOWED,,TIBETAN VOWEL SIGN II
+0F74,PVALID,,TIBETAN VOWEL SIGN U
+0F75-0F79,DISALLOWED,,TIBETAN VOWEL SIGN UU..TIBETAN VOWEL SIGN VOCALIC LL
+0F7A-0F80,PVALID,,TIBETAN VOWEL SIGN E..TIBETAN VOWEL SIGN REVERSED I
+0F81,DISALLOWED,,TIBETAN VOWEL SIGN REVERSED II
+0F82-0F84,PVALID,,TIBETAN SIGN NYI ZLA NAA DA..TIBETAN MARK HALANTA
+0F85,DISALLOWED,,TIBETAN MARK PALUTA
+0F86-0F92,PVALID,,TIBETAN SIGN LCI RTAGS..TIBETAN SUBJOINED LETTER GA
+0F93,DISALLOWED,,TIBETAN SUBJOINED LETTER GHA
+0F94-0F97,PVALID,,TIBETAN SUBJOINED LETTER NGA..TIBETAN SUBJOINED LETTER JA
+0F98,UNASSIGNED,,<RESERVED>
+0F99-0F9C,PVALID,,TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER DDA
+0F9D,DISALLOWED,,TIBETAN SUBJOINED LETTER DDHA
+0F9E-0FA1,PVALID,,TIBETAN SUBJOINED LETTER NNA..TIBETAN SUBJOINED LETTER DA
+0FA2,DISALLOWED,,TIBETAN SUBJOINED LETTER DHA
+0FA3-0FA6,PVALID,,TIBETAN SUBJOINED LETTER NA..TIBETAN SUBJOINED LETTER BA
+0FA7,DISALLOWED,,TIBETAN SUBJOINED LETTER BHA
+0FA8-0FAB,PVALID,,TIBETAN SUBJOINED LETTER MA..TIBETAN SUBJOINED LETTER DZA
+0FAC,DISALLOWED,,TIBETAN SUBJOINED LETTER DZHA
+0FAD-0FB8,PVALID,,TIBETAN SUBJOINED LETTER WA..TIBETAN SUBJOINED LETTER A
+0FB9,DISALLOWED,,TIBETAN SUBJOINED LETTER KSSA
+0FBA-0FBC,PVALID,,TIBETAN SUBJOINED LETTER FIXED-FORM WA..TIBETAN SUBJOINED LETTER FIXED-FORM RA
+0FBD,UNASSIGNED,,<RESERVED>
+0FBE-0FC5,DISALLOWED,,TIBETAN KU RU KHA..TIBETAN SYMBOL RDO RJE
+0FC6,PVALID,,TIBETAN SYMBOL PADMA GDAN
+0FC7-0FCC,DISALLOWED,,TIBETAN SYMBOL RDO RJE RGYA GRAM..TIBETAN SYMBOL NOR BU BZHI -KHYIL
+0FCD,UNASSIGNED,,<RESERVED>
+0FCE-0FDA,DISALLOWED,,TIBETAN SIGN RDEL NAG RDEL DKAR..TIBETAN MARK TRAILING MCHAN RTAGS
+0FDB-0FFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1000-1049,PVALID,,MYANMAR LETTER KA..MYANMAR DIGIT NINE
+104A-104F,DISALLOWED,,MYANMAR SIGN LITTLE SECTION..MYANMAR SYMBOL GENITIVE
+1050-109D,PVALID,,MYANMAR LETTER SHA..MYANMAR VOWEL SIGN AITON AI
+109E-10C5,DISALLOWED,,MYANMAR SYMBOL SHAN ONE..GEORGIAN CAPITAL LETTER HOE
+10C6,UNASSIGNED,,<RESERVED>
+10C7,DISALLOWED,,GEORGIAN CAPITAL LETTER YN
+10C8-10CC,UNASSIGNED,,<RESERVED>..<RESERVED>
+10CD,DISALLOWED,,GEORGIAN CAPITAL LETTER AEN
+10CE-10CF,UNASSIGNED,,<RESERVED>..<RESERVED>
+10D0-10FA,PVALID,,GEORGIAN LETTER AN..GEORGIAN LETTER AIN
+10FB-10FC,DISALLOWED,,GEORGIAN PARAGRAPH SEPARATOR..MODIFIER LETTER GEORGIAN NAR
+10FD-10FF,PVALID,,GEORGIAN LETTER AEN..GEORGIAN LETTER LABIAL SIGN
+1100-11FF,DISALLOWED,,HANGUL CHOSEONG KIYEOK..HANGUL JONGSEONG SSANGNIEUN
+1200-1248,PVALID,,ETHIOPIC SYLLABLE HA..ETHIOPIC SYLLABLE QWA
+1249,UNASSIGNED,,<RESERVED>
+124A-124D,PVALID,,ETHIOPIC SYLLABLE QWI..ETHIOPIC SYLLABLE QWE
+124E-124F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1250-1256,PVALID,,ETHIOPIC SYLLABLE QHA..ETHIOPIC SYLLABLE QHO
+1257,UNASSIGNED,,<RESERVED>
+1258,PVALID,,ETHIOPIC SYLLABLE QHWA
+1259,UNASSIGNED,,<RESERVED>
+125A-125D,PVALID,,ETHIOPIC SYLLABLE QHWI..ETHIOPIC SYLLABLE QHWE
+125E-125F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1260-1288,PVALID,,ETHIOPIC SYLLABLE BA..ETHIOPIC SYLLABLE XWA
+1289,UNASSIGNED,,<RESERVED>
+128A-128D,PVALID,,ETHIOPIC SYLLABLE XWI..ETHIOPIC SYLLABLE XWE
+128E-128F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1290-12B0,PVALID,,ETHIOPIC SYLLABLE NA..ETHIOPIC SYLLABLE KWA
+12B1,UNASSIGNED,,<RESERVED>
+12B2-12B5,PVALID,,ETHIOPIC SYLLABLE KWI..ETHIOPIC SYLLABLE KWE
+12B6-12B7,UNASSIGNED,,<RESERVED>..<RESERVED>
+12B8-12BE,PVALID,,ETHIOPIC SYLLABLE KXA..ETHIOPIC SYLLABLE KXO
+12BF,UNASSIGNED,,<RESERVED>
+12C0,PVALID,,ETHIOPIC SYLLABLE KXWA
+12C1,UNASSIGNED,,<RESERVED>
+12C2-12C5,PVALID,,ETHIOPIC SYLLABLE KXWI..ETHIOPIC SYLLABLE KXWE
+12C6-12C7,UNASSIGNED,,<RESERVED>..<RESERVED>
+12C8-12D6,PVALID,,ETHIOPIC SYLLABLE WA..ETHIOPIC SYLLABLE PHARYNGEAL O
+12D7,UNASSIGNED,,<RESERVED>
+12D8-1310,PVALID,,ETHIOPIC SYLLABLE ZA..ETHIOPIC SYLLABLE GWA
+1311,UNASSIGNED,,<RESERVED>
+1312-1315,PVALID,,ETHIOPIC SYLLABLE GWI..ETHIOPIC SYLLABLE GWE
+1316-1317,UNASSIGNED,,<RESERVED>..<RESERVED>
+1318-135A,PVALID,,ETHIOPIC SYLLABLE GGA..ETHIOPIC SYLLABLE FYA
+135B-135C,UNASSIGNED,,<RESERVED>..<RESERVED>
+135D-135F,PVALID,,ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK
+1360-137C,DISALLOWED,,ETHIOPIC SECTION MARK..ETHIOPIC NUMBER TEN THOUSAND
+137D-137F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1380-138F,PVALID,,ETHIOPIC SYLLABLE SEBATBEIT MWA..ETHIOPIC SYLLABLE PWE
+1390-1399,DISALLOWED,,ETHIOPIC TONAL MARK YIZET..ETHIOPIC TONAL MARK KURT
+139A-139F,UNASSIGNED,,<RESERVED>..<RESERVED>
+13A0-13F5,PVALID,,CHEROKEE LETTER A..CHEROKEE LETTER MV
+13F6-13F7,UNASSIGNED,,<RESERVED>..<RESERVED>
+13F8-13FD,DISALLOWED,,CHEROKEE SMALL LETTER YE..CHEROKEE SMALL LETTER MV
+13FE-13FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1400,DISALLOWED,,CANADIAN SYLLABICS HYPHEN
+1401-166C,PVALID,,CANADIAN SYLLABICS E..CANADIAN SYLLABICS CARRIER TTSA
+166D-166E,DISALLOWED,,CANADIAN SYLLABICS CHI SIGN..CANADIAN SYLLABICS FULL STOP
+166F-167F,PVALID,,CANADIAN SYLLABICS QAI..CANADIAN SYLLABICS BLACKFOOT W
+1680,DISALLOWED,,OGHAM SPACE MARK
+1681-169A,PVALID,,OGHAM LETTER BEITH..OGHAM LETTER PEITH
+169B-169C,DISALLOWED,,OGHAM FEATHER MARK..OGHAM REVERSED FEATHER MARK
+169D-169F,UNASSIGNED,,<RESERVED>..<RESERVED>
+16A0-16EA,PVALID,,RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X
+16EB-16F0,DISALLOWED,,RUNIC SINGLE PUNCTUATION..RUNIC BELGTHOR SYMBOL
+16F1-16F8,PVALID,,RUNIC LETTER K..RUNIC LETTER FRANKS CASKET AESC
+16F9-16FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1700-170C,PVALID,,TAGALOG LETTER A..TAGALOG LETTER YA
+170D,UNASSIGNED,,<RESERVED>
+170E-1714,PVALID,,TAGALOG LETTER LA..TAGALOG SIGN VIRAMA
+1715-171F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1720-1734,PVALID,,HANUNOO LETTER A..HANUNOO SIGN PAMUDPOD
+1735-1736,DISALLOWED,,PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION
+1737-173F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1740-1753,PVALID,,BUHID LETTER A..BUHID VOWEL SIGN U
+1754-175F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1760-176C,PVALID,,TAGBANWA LETTER A..TAGBANWA LETTER YA
+176D,UNASSIGNED,,<RESERVED>
+176E-1770,PVALID,,TAGBANWA LETTER LA..TAGBANWA LETTER SA
+1771,UNASSIGNED,,<RESERVED>
+1772-1773,PVALID,,TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U
+1774-177F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1780-17B3,PVALID,,KHMER LETTER KA..KHMER INDEPENDENT VOWEL QAU
+17B4-17B5,DISALLOWED,,KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
+17B6-17D3,PVALID,,KHMER VOWEL SIGN AA..KHMER SIGN BATHAMASAT
+17D4-17D6,DISALLOWED,,KHMER SIGN KHAN..KHMER SIGN CAMNUC PII KUUH
+17D7,PVALID,,KHMER SIGN LEK TOO
+17D8-17DB,DISALLOWED,,KHMER SIGN BEYYAL..KHMER CURRENCY SYMBOL RIEL
+17DC-17DD,PVALID,,KHMER SIGN AVAKRAHASANYA..KHMER SIGN ATTHACAN
+17DE-17DF,UNASSIGNED,,<RESERVED>..<RESERVED>
+17E0-17E9,PVALID,,KHMER DIGIT ZERO..KHMER DIGIT NINE
+17EA-17EF,UNASSIGNED,,<RESERVED>..<RESERVED>
+17F0-17F9,DISALLOWED,,KHMER SYMBOL LEK ATTAK SON..KHMER SYMBOL LEK ATTAK PRAM-BUON
+17FA-17FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1800-180E,DISALLOWED,,MONGOLIAN BIRGA..MONGOLIAN VOWEL SEPARATOR
+180F,UNASSIGNED,,<RESERVED>
+1810-1819,PVALID,,MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE
+181A-181F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1820-1878,PVALID,,MONGOLIAN LETTER A..MONGOLIAN LETTER CHA WITH TWO DOTS
+1879-187F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1880-18AA,PVALID,,MONGOLIAN LETTER ALI GALI ANUSVARA ONE..MONGOLIAN LETTER MANCHU ALI GALI LHA
+18AB-18AF,UNASSIGNED,,<RESERVED>..<RESERVED>
+18B0-18F5,PVALID,,CANADIAN SYLLABICS OY..CANADIAN SYLLABICS CARRIER DENTAL S
+18F6-18FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1900-191E,PVALID,,LIMBU VOWEL-CARRIER LETTER..LIMBU LETTER TRA
+191F,UNASSIGNED,,<RESERVED>
+1920-192B,PVALID,,LIMBU VOWEL SIGN A..LIMBU SUBJOINED LETTER WA
+192C-192F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1930-193B,PVALID,,LIMBU SMALL LETTER KA..LIMBU SIGN SA-I
+193C-193F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1940,DISALLOWED,,LIMBU SIGN LOO
+1941-1943,UNASSIGNED,,<RESERVED>..<RESERVED>
+1944-1945,DISALLOWED,,LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK
+1946-196D,PVALID,,LIMBU DIGIT ZERO..TAI LE LETTER AI
+196E-196F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1970-1974,PVALID,,TAI LE LETTER TONE-2..TAI LE LETTER TONE-6
+1975-197F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1980-19AB,PVALID,,NEW TAI LUE LETTER HIGH QA..NEW TAI LUE LETTER LOW SUA
+19AC-19AF,UNASSIGNED,,<RESERVED>..<RESERVED>
+19B0-19C9,PVALID,,NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW TAI LUE TONE MARK-2
+19CA-19CF,UNASSIGNED,,<RESERVED>..<RESERVED>
+19D0-19D9,PVALID,,NEW TAI LUE DIGIT ZERO..NEW TAI LUE DIGIT NINE
+19DA,DISALLOWED,,NEW TAI LUE THAM DIGIT ONE
+19DB-19DD,UNASSIGNED,,<RESERVED>..<RESERVED>
+19DE-19FF,DISALLOWED,,NEW TAI LUE SIGN LAE..KHMER SYMBOL DAP-PRAM ROC
+1A00-1A1B,PVALID,,BUGINESE LETTER KA..BUGINESE VOWEL SIGN AE
+1A1C-1A1D,UNASSIGNED,,<RESERVED>..<RESERVED>
+1A1E-1A1F,DISALLOWED,,BUGINESE PALLAWA..BUGINESE END OF SECTION
+1A20-1A5E,PVALID,,TAI THAM LETTER HIGH KA..TAI THAM CONSONANT SIGN SA
+1A5F,UNASSIGNED,,<RESERVED>
+1A60-1A7C,PVALID,,TAI THAM SIGN SAKOT..TAI THAM SIGN KHUEN-LUE KARAN
+1A7D-1A7E,UNASSIGNED,,<RESERVED>..<RESERVED>
+1A7F-1A89,PVALID,,TAI THAM COMBINING CRYPTOGRAMMIC DOT..TAI THAM HORA DIGIT NINE
+1A8A-1A8F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1A90-1A99,PVALID,,TAI THAM THAM DIGIT ZERO..TAI THAM THAM DIGIT NINE
+1A9A-1A9F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1AA0-1AA6,DISALLOWED,,TAI THAM SIGN WIANG..TAI THAM SIGN REVERSED ROTATED RANA
+1AA7,PVALID,,TAI THAM SIGN MAI YAMOK
+1AA8-1AAD,DISALLOWED,,TAI THAM SIGN KAAN..TAI THAM SIGN CAANG
+1AAE-1AAF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1AB0-1ABD,PVALID,,COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW
+1ABE,DISALLOWED,,COMBINING PARENTHESES OVERLAY
+1ABF-1AFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1B00-1B4B,PVALID,,BALINESE SIGN ULU RICEM..BALINESE LETTER ASYURA SASAK
+1B4C-1B4F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1B50-1B59,PVALID,,BALINESE DIGIT ZERO..BALINESE DIGIT NINE
+1B5A-1B6A,DISALLOWED,,BALINESE PANTI..BALINESE MUSICAL SYMBOL DANG GEDE
+1B6B-1B73,PVALID,,BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG
+1B74-1B7C,DISALLOWED,,BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG..BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING
+1B7D-1B7F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1B80-1BF3,PVALID,,SUNDANESE SIGN PANYECEK..BATAK PANONGONAN
+1BF4-1BFB,UNASSIGNED,,<RESERVED>..<RESERVED>
+1BFC-1BFF,DISALLOWED,,BATAK SYMBOL BINDU NA METEK..BATAK SYMBOL BINDU PANGOLAT
+1C00-1C37,PVALID,,LEPCHA LETTER KA..LEPCHA SIGN NUKTA
+1C38-1C3A,UNASSIGNED,,<RESERVED>..<RESERVED>
+1C3B-1C3F,DISALLOWED,,LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION TSHOOK
+1C40-1C49,PVALID,,LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE
+1C4A-1C4C,UNASSIGNED,,<RESERVED>..<RESERVED>
+1C4D-1C7D,PVALID,,LEPCHA LETTER TTA..OL CHIKI AHAD
+1C7E-1C88,DISALLOWED,,OL CHIKI PUNCTUATION MUCAAD..CYRILLIC SMALL LETTER UNBLENDED UK
+1C89-1C8F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1C90-1CBA,DISALLOWED,,GEORGIAN MTAVRULI CAPITAL LETTER AN..GEORGIAN MTAVRULI CAPITAL LETTER AIN
+1CBB-1CBC,UNASSIGNED,,<RESERVED>..<RESERVED>
+1CBD-1CC7,DISALLOWED,,GEORGIAN MTAVRULI CAPITAL LETTER AEN..SUNDANESE PUNCTUATION BINDU BA SATANGA
+1CC8-1CCF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1CD0-1CD2,PVALID,,VEDIC TONE KARSHANA..VEDIC TONE PRENKHA
+1CD3,DISALLOWED,,VEDIC SIGN NIHSHVASA
+1CD4-1CF9,PVALID,,VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE DOUBLE RING ABOVE
+1CFA-1CFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1D00-1D2B,PVALID,,LATIN LETTER SMALL CAPITAL A..CYRILLIC LETTER SMALL CAPITAL EL
+1D2C-1D2E,DISALLOWED,,MODIFIER LETTER CAPITAL A..MODIFIER LETTER CAPITAL B
+1D2F,PVALID,,MODIFIER LETTER CAPITAL BARRED B
+1D30-1D3A,DISALLOWED,,MODIFIER LETTER CAPITAL D..MODIFIER LETTER CAPITAL N
+1D3B,PVALID,,MODIFIER LETTER CAPITAL REVERSED N
+1D3C-1D4D,DISALLOWED,,MODIFIER LETTER CAPITAL O..MODIFIER LETTER SMALL G
+1D4E,PVALID,,MODIFIER LETTER SMALL TURNED I
+1D4F-1D6A,DISALLOWED,,MODIFIER LETTER SMALL K..GREEK SUBSCRIPT SMALL LETTER CHI
+1D6B-1D77,PVALID,,LATIN SMALL LETTER UE..LATIN SMALL LETTER TURNED G
+1D78,DISALLOWED,,MODIFIER LETTER CYRILLIC EN
+1D79-1D9A,PVALID,,LATIN SMALL LETTER INSULAR G..LATIN SMALL LETTER EZH WITH RETROFLEX HOOK
+1D9B-1DBF,DISALLOWED,,MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL THETA
+1DC0-1DF9,PVALID,,COMBINING DOTTED GRAVE ACCENT..COMBINING WIDE INVERTED BRIDGE BELOW
+1DFA,UNASSIGNED,,<RESERVED>
+1DFB-1DFF,PVALID,,COMBINING DELETION MARK..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW
+1E00,DISALLOWED,,LATIN CAPITAL LETTER A WITH RING BELOW
+1E01,PVALID,,LATIN SMALL LETTER A WITH RING BELOW
+1E02,DISALLOWED,,LATIN CAPITAL LETTER B WITH DOT ABOVE
+1E03,PVALID,,LATIN SMALL LETTER B WITH DOT ABOVE
+1E04,DISALLOWED,,LATIN CAPITAL LETTER B WITH DOT BELOW
+1E05,PVALID,,LATIN SMALL LETTER B WITH DOT BELOW
+1E06,DISALLOWED,,LATIN CAPITAL LETTER B WITH LINE BELOW
+1E07,PVALID,,LATIN SMALL LETTER B WITH LINE BELOW
+1E08,DISALLOWED,,LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE
+1E09,PVALID,,LATIN SMALL LETTER C WITH CEDILLA AND ACUTE
+1E0A,DISALLOWED,,LATIN CAPITAL LETTER D WITH DOT ABOVE
+1E0B,PVALID,,LATIN SMALL LETTER D WITH DOT ABOVE
+1E0C,DISALLOWED,,LATIN CAPITAL LETTER D WITH DOT BELOW
+1E0D,PVALID,,LATIN SMALL LETTER D WITH DOT BELOW
+1E0E,DISALLOWED,,LATIN CAPITAL LETTER D WITH LINE BELOW
+1E0F,PVALID,,LATIN SMALL LETTER D WITH LINE BELOW
+1E10,DISALLOWED,,LATIN CAPITAL LETTER D WITH CEDILLA
+1E11,PVALID,,LATIN SMALL LETTER D WITH CEDILLA
+1E12,DISALLOWED,,LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW
+1E13,PVALID,,LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW
+1E14,DISALLOWED,,LATIN CAPITAL LETTER E WITH MACRON AND GRAVE
+1E15,PVALID,,LATIN SMALL LETTER E WITH MACRON AND GRAVE
+1E16,DISALLOWED,,LATIN CAPITAL LETTER E WITH MACRON AND ACUTE
+1E17,PVALID,,LATIN SMALL LETTER E WITH MACRON AND ACUTE
+1E18,DISALLOWED,,LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW
+1E19,PVALID,,LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW
+1E1A,DISALLOWED,,LATIN CAPITAL LETTER E WITH TILDE BELOW
+1E1B,PVALID,,LATIN SMALL LETTER E WITH TILDE BELOW
+1E1C,DISALLOWED,,LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE
+1E1D,PVALID,,LATIN SMALL LETTER E WITH CEDILLA AND BREVE
+1E1E,DISALLOWED,,LATIN CAPITAL LETTER F WITH DOT ABOVE
+1E1F,PVALID,,LATIN SMALL LETTER F WITH DOT ABOVE
+1E20,DISALLOWED,,LATIN CAPITAL LETTER G WITH MACRON
+1E21,PVALID,,LATIN SMALL LETTER G WITH MACRON
+1E22,DISALLOWED,,LATIN CAPITAL LETTER H WITH DOT ABOVE
+1E23,PVALID,,LATIN SMALL LETTER H WITH DOT ABOVE
+1E24,DISALLOWED,,LATIN CAPITAL LETTER H WITH DOT BELOW
+1E25,PVALID,,LATIN SMALL LETTER H WITH DOT BELOW
+1E26,DISALLOWED,,LATIN CAPITAL LETTER H WITH DIAERESIS
+1E27,PVALID,,LATIN SMALL LETTER H WITH DIAERESIS
+1E28,DISALLOWED,,LATIN CAPITAL LETTER H WITH CEDILLA
+1E29,PVALID,,LATIN SMALL LETTER H WITH CEDILLA
+1E2A,DISALLOWED,,LATIN CAPITAL LETTER H WITH BREVE BELOW
+1E2B,PVALID,,LATIN SMALL LETTER H WITH BREVE BELOW
+1E2C,DISALLOWED,,LATIN CAPITAL LETTER I WITH TILDE BELOW
+1E2D,PVALID,,LATIN SMALL LETTER I WITH TILDE BELOW
+1E2E,DISALLOWED,,LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE
+1E2F,PVALID,,LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE
+1E30,DISALLOWED,,LATIN CAPITAL LETTER K WITH ACUTE
+1E31,PVALID,,LATIN SMALL LETTER K WITH ACUTE
+1E32,DISALLOWED,,LATIN CAPITAL LETTER K WITH DOT BELOW
+1E33,PVALID,,LATIN SMALL LETTER K WITH DOT BELOW
+1E34,DISALLOWED,,LATIN CAPITAL LETTER K WITH LINE BELOW
+1E35,PVALID,,LATIN SMALL LETTER K WITH LINE BELOW
+1E36,DISALLOWED,,LATIN CAPITAL LETTER L WITH DOT BELOW
+1E37,PVALID,,LATIN SMALL LETTER L WITH DOT BELOW
+1E38,DISALLOWED,,LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON
+1E39,PVALID,,LATIN SMALL LETTER L WITH DOT BELOW AND MACRON
+1E3A,DISALLOWED,,LATIN CAPITAL LETTER L WITH LINE BELOW
+1E3B,PVALID,,LATIN SMALL LETTER L WITH LINE BELOW
+1E3C,DISALLOWED,,LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW
+1E3D,PVALID,,LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW
+1E3E,DISALLOWED,,LATIN CAPITAL LETTER M WITH ACUTE
+1E3F,PVALID,,LATIN SMALL LETTER M WITH ACUTE
+1E40,DISALLOWED,,LATIN CAPITAL LETTER M WITH DOT ABOVE
+1E41,PVALID,,LATIN SMALL LETTER M WITH DOT ABOVE
+1E42,DISALLOWED,,LATIN CAPITAL LETTER M WITH DOT BELOW
+1E43,PVALID,,LATIN SMALL LETTER M WITH DOT BELOW
+1E44,DISALLOWED,,LATIN CAPITAL LETTER N WITH DOT ABOVE
+1E45,PVALID,,LATIN SMALL LETTER N WITH DOT ABOVE
+1E46,DISALLOWED,,LATIN CAPITAL LETTER N WITH DOT BELOW
+1E47,PVALID,,LATIN SMALL LETTER N WITH DOT BELOW
+1E48,DISALLOWED,,LATIN CAPITAL LETTER N WITH LINE BELOW
+1E49,PVALID,,LATIN SMALL LETTER N WITH LINE BELOW
+1E4A,DISALLOWED,,LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW
+1E4B,PVALID,,LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW
+1E4C,DISALLOWED,,LATIN CAPITAL LETTER O WITH TILDE AND ACUTE
+1E4D,PVALID,,LATIN SMALL LETTER O WITH TILDE AND ACUTE
+1E4E,DISALLOWED,,LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS
+1E4F,PVALID,,LATIN SMALL LETTER O WITH TILDE AND DIAERESIS
+1E50,DISALLOWED,,LATIN CAPITAL LETTER O WITH MACRON AND GRAVE
+1E51,PVALID,,LATIN SMALL LETTER O WITH MACRON AND GRAVE
+1E52,DISALLOWED,,LATIN CAPITAL LETTER O WITH MACRON AND ACUTE
+1E53,PVALID,,LATIN SMALL LETTER O WITH MACRON AND ACUTE
+1E54,DISALLOWED,,LATIN CAPITAL LETTER P WITH ACUTE
+1E55,PVALID,,LATIN SMALL LETTER P WITH ACUTE
+1E56,DISALLOWED,,LATIN CAPITAL LETTER P WITH DOT ABOVE
+1E57,PVALID,,LATIN SMALL LETTER P WITH DOT ABOVE
+1E58,DISALLOWED,,LATIN CAPITAL LETTER R WITH DOT ABOVE
+1E59,PVALID,,LATIN SMALL LETTER R WITH DOT ABOVE
+1E5A,DISALLOWED,,LATIN CAPITAL LETTER R WITH DOT BELOW
+1E5B,PVALID,,LATIN SMALL LETTER R WITH DOT BELOW
+1E5C,DISALLOWED,,LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON
+1E5D,PVALID,,LATIN SMALL LETTER R WITH DOT BELOW AND MACRON
+1E5E,DISALLOWED,,LATIN CAPITAL LETTER R WITH LINE BELOW
+1E5F,PVALID,,LATIN SMALL LETTER R WITH LINE BELOW
+1E60,DISALLOWED,,LATIN CAPITAL LETTER S WITH DOT ABOVE
+1E61,PVALID,,LATIN SMALL LETTER S WITH DOT ABOVE
+1E62,DISALLOWED,,LATIN CAPITAL LETTER S WITH DOT BELOW
+1E63,PVALID,,LATIN SMALL LETTER S WITH DOT BELOW
+1E64,DISALLOWED,,LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE
+1E65,PVALID,,LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE
+1E66,DISALLOWED,,LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE
+1E67,PVALID,,LATIN SMALL LETTER S WITH CARON AND DOT ABOVE
+1E68,DISALLOWED,,LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE
+1E69,PVALID,,LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE
+1E6A,DISALLOWED,,LATIN CAPITAL LETTER T WITH DOT ABOVE
+1E6B,PVALID,,LATIN SMALL LETTER T WITH DOT ABOVE
+1E6C,DISALLOWED,,LATIN CAPITAL LETTER T WITH DOT BELOW
+1E6D,PVALID,,LATIN SMALL LETTER T WITH DOT BELOW
+1E6E,DISALLOWED,,LATIN CAPITAL LETTER T WITH LINE BELOW
+1E6F,PVALID,,LATIN SMALL LETTER T WITH LINE BELOW
+1E70,DISALLOWED,,LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW
+1E71,PVALID,,LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW
+1E72,DISALLOWED,,LATIN CAPITAL LETTER U WITH DIAERESIS BELOW
+1E73,PVALID,,LATIN SMALL LETTER U WITH DIAERESIS BELOW
+1E74,DISALLOWED,,LATIN CAPITAL LETTER U WITH TILDE BELOW
+1E75,PVALID,,LATIN SMALL LETTER U WITH TILDE BELOW
+1E76,DISALLOWED,,LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW
+1E77,PVALID,,LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW
+1E78,DISALLOWED,,LATIN CAPITAL LETTER U WITH TILDE AND ACUTE
+1E79,PVALID,,LATIN SMALL LETTER U WITH TILDE AND ACUTE
+1E7A,DISALLOWED,,LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS
+1E7B,PVALID,,LATIN SMALL LETTER U WITH MACRON AND DIAERESIS
+1E7C,DISALLOWED,,LATIN CAPITAL LETTER V WITH TILDE
+1E7D,PVALID,,LATIN SMALL LETTER V WITH TILDE
+1E7E,DISALLOWED,,LATIN CAPITAL LETTER V WITH DOT BELOW
+1E7F,PVALID,,LATIN SMALL LETTER V WITH DOT BELOW
+1E80,DISALLOWED,,LATIN CAPITAL LETTER W WITH GRAVE
+1E81,PVALID,,LATIN SMALL LETTER W WITH GRAVE
+1E82,DISALLOWED,,LATIN CAPITAL LETTER W WITH ACUTE
+1E83,PVALID,,LATIN SMALL LETTER W WITH ACUTE
+1E84,DISALLOWED,,LATIN CAPITAL LETTER W WITH DIAERESIS
+1E85,PVALID,,LATIN SMALL LETTER W WITH DIAERESIS
+1E86,DISALLOWED,,LATIN CAPITAL LETTER W WITH DOT ABOVE
+1E87,PVALID,,LATIN SMALL LETTER W WITH DOT ABOVE
+1E88,DISALLOWED,,LATIN CAPITAL LETTER W WITH DOT BELOW
+1E89,PVALID,,LATIN SMALL LETTER W WITH DOT BELOW
+1E8A,DISALLOWED,,LATIN CAPITAL LETTER X WITH DOT ABOVE
+1E8B,PVALID,,LATIN SMALL LETTER X WITH DOT ABOVE
+1E8C,DISALLOWED,,LATIN CAPITAL LETTER X WITH DIAERESIS
+1E8D,PVALID,,LATIN SMALL LETTER X WITH DIAERESIS
+1E8E,DISALLOWED,,LATIN CAPITAL LETTER Y WITH DOT ABOVE
+1E8F,PVALID,,LATIN SMALL LETTER Y WITH DOT ABOVE
+1E90,DISALLOWED,,LATIN CAPITAL LETTER Z WITH CIRCUMFLEX
+1E91,PVALID,,LATIN SMALL LETTER Z WITH CIRCUMFLEX
+1E92,DISALLOWED,,LATIN CAPITAL LETTER Z WITH DOT BELOW
+1E93,PVALID,,LATIN SMALL LETTER Z WITH DOT BELOW
+1E94,DISALLOWED,,LATIN CAPITAL LETTER Z WITH LINE BELOW
+1E95-1E99,PVALID,,LATIN SMALL LETTER Z WITH LINE BELOW..LATIN SMALL LETTER Y WITH RING ABOVE
+1E9A-1E9B,DISALLOWED,,LATIN SMALL LETTER A WITH RIGHT HALF RING..LATIN SMALL LETTER LONG S WITH DOT ABOVE
+1E9C-1E9D,PVALID,,LATIN SMALL LETTER LONG S WITH DIAGONAL STROKE..LATIN SMALL LETTER LONG S WITH HIGH STROKE
+1E9E,DISALLOWED,,LATIN CAPITAL LETTER SHARP S
+1E9F,PVALID,,LATIN SMALL LETTER DELTA
+1EA0,DISALLOWED,,LATIN CAPITAL LETTER A WITH DOT BELOW
+1EA1,PVALID,,LATIN SMALL LETTER A WITH DOT BELOW
+1EA2,DISALLOWED,,LATIN CAPITAL LETTER A WITH HOOK ABOVE
+1EA3,PVALID,,LATIN SMALL LETTER A WITH HOOK ABOVE
+1EA4,DISALLOWED,,LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE
+1EA5,PVALID,,LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE
+1EA6,DISALLOWED,,LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE
+1EA7,PVALID,,LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE
+1EA8,DISALLOWED,,LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE
+1EA9,PVALID,,LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE
+1EAA,DISALLOWED,,LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE
+1EAB,PVALID,,LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE
+1EAC,DISALLOWED,,LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW
+1EAD,PVALID,,LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW
+1EAE,DISALLOWED,,LATIN CAPITAL LETTER A WITH BREVE AND ACUTE
+1EAF,PVALID,,LATIN SMALL LETTER A WITH BREVE AND ACUTE
+1EB0,DISALLOWED,,LATIN CAPITAL LETTER A WITH BREVE AND GRAVE
+1EB1,PVALID,,LATIN SMALL LETTER A WITH BREVE AND GRAVE
+1EB2,DISALLOWED,,LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE
+1EB3,PVALID,,LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE
+1EB4,DISALLOWED,,LATIN CAPITAL LETTER A WITH BREVE AND TILDE
+1EB5,PVALID,,LATIN SMALL LETTER A WITH BREVE AND TILDE
+1EB6,DISALLOWED,,LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW
+1EB7,PVALID,,LATIN SMALL LETTER A WITH BREVE AND DOT BELOW
+1EB8,DISALLOWED,,LATIN CAPITAL LETTER E WITH DOT BELOW
+1EB9,PVALID,,LATIN SMALL LETTER E WITH DOT BELOW
+1EBA,DISALLOWED,,LATIN CAPITAL LETTER E WITH HOOK ABOVE
+1EBB,PVALID,,LATIN SMALL LETTER E WITH HOOK ABOVE
+1EBC,DISALLOWED,,LATIN CAPITAL LETTER E WITH TILDE
+1EBD,PVALID,,LATIN SMALL LETTER E WITH TILDE
+1EBE,DISALLOWED,,LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE
+1EBF,PVALID,,LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE
+1EC0,DISALLOWED,,LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE
+1EC1,PVALID,,LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE
+1EC2,DISALLOWED,,LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE
+1EC3,PVALID,,LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE
+1EC4,DISALLOWED,,LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE
+1EC5,PVALID,,LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE
+1EC6,DISALLOWED,,LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW
+1EC7,PVALID,,LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW
+1EC8,DISALLOWED,,LATIN CAPITAL LETTER I WITH HOOK ABOVE
+1EC9,PVALID,,LATIN SMALL LETTER I WITH HOOK ABOVE
+1ECA,DISALLOWED,,LATIN CAPITAL LETTER I WITH DOT BELOW
+1ECB,PVALID,,LATIN SMALL LETTER I WITH DOT BELOW
+1ECC,DISALLOWED,,LATIN CAPITAL LETTER O WITH DOT BELOW
+1ECD,PVALID,,LATIN SMALL LETTER O WITH DOT BELOW
+1ECE,DISALLOWED,,LATIN CAPITAL LETTER O WITH HOOK ABOVE
+1ECF,PVALID,,LATIN SMALL LETTER O WITH HOOK ABOVE
+1ED0,DISALLOWED,,LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE
+1ED1,PVALID,,LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE
+1ED2,DISALLOWED,,LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE
+1ED3,PVALID,,LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE
+1ED4,DISALLOWED,,LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE
+1ED5,PVALID,,LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE
+1ED6,DISALLOWED,,LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE
+1ED7,PVALID,,LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE
+1ED8,DISALLOWED,,LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW
+1ED9,PVALID,,LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW
+1EDA,DISALLOWED,,LATIN CAPITAL LETTER O WITH HORN AND ACUTE
+1EDB,PVALID,,LATIN SMALL LETTER O WITH HORN AND ACUTE
+1EDC,DISALLOWED,,LATIN CAPITAL LETTER O WITH HORN AND GRAVE
+1EDD,PVALID,,LATIN SMALL LETTER O WITH HORN AND GRAVE
+1EDE,DISALLOWED,,LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE
+1EDF,PVALID,,LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE
+1EE0,DISALLOWED,,LATIN CAPITAL LETTER O WITH HORN AND TILDE
+1EE1,PVALID,,LATIN SMALL LETTER O WITH HORN AND TILDE
+1EE2,DISALLOWED,,LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW
+1EE3,PVALID,,LATIN SMALL LETTER O WITH HORN AND DOT BELOW
+1EE4,DISALLOWED,,LATIN CAPITAL LETTER U WITH DOT BELOW
+1EE5,PVALID,,LATIN SMALL LETTER U WITH DOT BELOW
+1EE6,DISALLOWED,,LATIN CAPITAL LETTER U WITH HOOK ABOVE
+1EE7,PVALID,,LATIN SMALL LETTER U WITH HOOK ABOVE
+1EE8,DISALLOWED,,LATIN CAPITAL LETTER U WITH HORN AND ACUTE
+1EE9,PVALID,,LATIN SMALL LETTER U WITH HORN AND ACUTE
+1EEA,DISALLOWED,,LATIN CAPITAL LETTER U WITH HORN AND GRAVE
+1EEB,PVALID,,LATIN SMALL LETTER U WITH HORN AND GRAVE
+1EEC,DISALLOWED,,LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE
+1EED,PVALID,,LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE
+1EEE,DISALLOWED,,LATIN CAPITAL LETTER U WITH HORN AND TILDE
+1EEF,PVALID,,LATIN SMALL LETTER U WITH HORN AND TILDE
+1EF0,DISALLOWED,,LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW
+1EF1,PVALID,,LATIN SMALL LETTER U WITH HORN AND DOT BELOW
+1EF2,DISALLOWED,,LATIN CAPITAL LETTER Y WITH GRAVE
+1EF3,PVALID,,LATIN SMALL LETTER Y WITH GRAVE
+1EF4,DISALLOWED,,LATIN CAPITAL LETTER Y WITH DOT BELOW
+1EF5,PVALID,,LATIN SMALL LETTER Y WITH DOT BELOW
+1EF6,DISALLOWED,,LATIN CAPITAL LETTER Y WITH HOOK ABOVE
+1EF7,PVALID,,LATIN SMALL LETTER Y WITH HOOK ABOVE
+1EF8,DISALLOWED,,LATIN CAPITAL LETTER Y WITH TILDE
+1EF9,PVALID,,LATIN SMALL LETTER Y WITH TILDE
+1EFA,DISALLOWED,,LATIN CAPITAL LETTER MIDDLE-WELSH LL
+1EFB,PVALID,,LATIN SMALL LETTER MIDDLE-WELSH LL
+1EFC,DISALLOWED,,LATIN CAPITAL LETTER MIDDLE-WELSH V
+1EFD,PVALID,,LATIN SMALL LETTER MIDDLE-WELSH V
+1EFE,DISALLOWED,,LATIN CAPITAL LETTER Y WITH LOOP
+1EFF-1F07,PVALID,,LATIN SMALL LETTER Y WITH LOOP..GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI
+1F08-1F0F,DISALLOWED,,GREEK CAPITAL LETTER ALPHA WITH PSILI..GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI
+1F10-1F15,PVALID,,GREEK SMALL LETTER EPSILON WITH PSILI..GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA
+1F16-1F17,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F18-1F1D,DISALLOWED,,GREEK CAPITAL LETTER EPSILON WITH PSILI..GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA
+1F1E-1F1F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F20-1F27,PVALID,,GREEK SMALL LETTER ETA WITH PSILI..GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI
+1F28-1F2F,DISALLOWED,,GREEK CAPITAL LETTER ETA WITH PSILI..GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI
+1F30-1F37,PVALID,,GREEK SMALL LETTER IOTA WITH PSILI..GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI
+1F38-1F3F,DISALLOWED,,GREEK CAPITAL LETTER IOTA WITH PSILI..GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI
+1F40-1F45,PVALID,,GREEK SMALL LETTER OMICRON WITH PSILI..GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA
+1F46-1F47,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F48-1F4D,DISALLOWED,,GREEK CAPITAL LETTER OMICRON WITH PSILI..GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA
+1F4E-1F4F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F50-1F57,PVALID,,GREEK SMALL LETTER UPSILON WITH PSILI..GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI
+1F58,UNASSIGNED,,<RESERVED>
+1F59,DISALLOWED,,GREEK CAPITAL LETTER UPSILON WITH DASIA
+1F5A,UNASSIGNED,,<RESERVED>
+1F5B,DISALLOWED,,GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA
+1F5C,UNASSIGNED,,<RESERVED>
+1F5D,DISALLOWED,,GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA
+1F5E,UNASSIGNED,,<RESERVED>
+1F5F,DISALLOWED,,GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI
+1F60-1F67,PVALID,,GREEK SMALL LETTER OMEGA WITH PSILI..GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI
+1F68-1F6F,DISALLOWED,,GREEK CAPITAL LETTER OMEGA WITH PSILI..GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI
+1F70,PVALID,,GREEK SMALL LETTER ALPHA WITH VARIA
+1F71,DISALLOWED,,GREEK SMALL LETTER ALPHA WITH OXIA
+1F72,PVALID,,GREEK SMALL LETTER EPSILON WITH VARIA
+1F73,DISALLOWED,,GREEK SMALL LETTER EPSILON WITH OXIA
+1F74,PVALID,,GREEK SMALL LETTER ETA WITH VARIA
+1F75,DISALLOWED,,GREEK SMALL LETTER ETA WITH OXIA
+1F76,PVALID,,GREEK SMALL LETTER IOTA WITH VARIA
+1F77,DISALLOWED,,GREEK SMALL LETTER IOTA WITH OXIA
+1F78,PVALID,,GREEK SMALL LETTER OMICRON WITH VARIA
+1F79,DISALLOWED,,GREEK SMALL LETTER OMICRON WITH OXIA
+1F7A,PVALID,,GREEK SMALL LETTER UPSILON WITH VARIA
+1F7B,DISALLOWED,,GREEK SMALL LETTER UPSILON WITH OXIA
+1F7C,PVALID,,GREEK SMALL LETTER OMEGA WITH VARIA
+1F7D,DISALLOWED,,GREEK SMALL LETTER OMEGA WITH OXIA
+1F7E-1F7F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F80-1FAF,DISALLOWED,,GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI..GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
+1FB0-1FB1,PVALID,,GREEK SMALL LETTER ALPHA WITH VRACHY..GREEK SMALL LETTER ALPHA WITH MACRON
+1FB2-1FB4,DISALLOWED,,GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI
+1FB5,UNASSIGNED,,<RESERVED>
+1FB6,PVALID,,GREEK SMALL LETTER ALPHA WITH PERISPOMENI
+1FB7-1FC4,DISALLOWED,,GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI..GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI
+1FC5,UNASSIGNED,,<RESERVED>
+1FC6,PVALID,,GREEK SMALL LETTER ETA WITH PERISPOMENI
+1FC7-1FCF,DISALLOWED,,GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI..GREEK PSILI AND PERISPOMENI
+1FD0-1FD2,PVALID,,GREEK SMALL LETTER IOTA WITH VRACHY..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA
+1FD3,DISALLOWED,,GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA
+1FD4-1FD5,UNASSIGNED,,<RESERVED>..<RESERVED>
+1FD6-1FD7,PVALID,,GREEK SMALL LETTER IOTA WITH PERISPOMENI..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI
+1FD8-1FDB,DISALLOWED,,GREEK CAPITAL LETTER IOTA WITH VRACHY..GREEK CAPITAL LETTER IOTA WITH OXIA
+1FDC,UNASSIGNED,,<RESERVED>
+1FDD-1FDF,DISALLOWED,,GREEK DASIA AND VARIA..GREEK DASIA AND PERISPOMENI
+1FE0-1FE2,PVALID,,GREEK SMALL LETTER UPSILON WITH VRACHY..GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA
+1FE3,DISALLOWED,,GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA
+1FE4-1FE7,PVALID,,GREEK SMALL LETTER RHO WITH PSILI..GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI
+1FE8-1FEF,DISALLOWED,,GREEK CAPITAL LETTER UPSILON WITH VRACHY..GREEK VARIA
+1FF0-1FF1,UNASSIGNED,,<RESERVED>..<RESERVED>
+1FF2-1FF4,DISALLOWED,,GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI
+1FF5,UNASSIGNED,,<RESERVED>
+1FF6,PVALID,,GREEK SMALL LETTER OMEGA WITH PERISPOMENI
+1FF7-1FFE,DISALLOWED,,GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI..GREEK DASIA
+1FFF,UNASSIGNED,,<RESERVED>
+2000-200B,DISALLOWED,,EN QUAD..ZERO WIDTH SPACE
+200C-200D,CONTEXTJ,,ZERO WIDTH NON-JOINER..ZERO WIDTH JOINER
+200E-2064,DISALLOWED,,LEFT-TO-RIGHT MARK..INVISIBLE PLUS
+2065,UNASSIGNED,,<RESERVED>
+2066-2071,DISALLOWED,,LEFT-TO-RIGHT ISOLATE..SUPERSCRIPT LATIN SMALL LETTER I
+2072-2073,UNASSIGNED,,<RESERVED>..<RESERVED>
+2074-208E,DISALLOWED,,SUPERSCRIPT FOUR..SUBSCRIPT RIGHT PARENTHESIS
+208F,UNASSIGNED,,<RESERVED>
+2090-209C,DISALLOWED,,LATIN SUBSCRIPT SMALL LETTER A..LATIN SUBSCRIPT SMALL LETTER T
+209D-209F,UNASSIGNED,,<RESERVED>..<RESERVED>
+20A0-20BF,DISALLOWED,,EURO-CURRENCY SIGN..BITCOIN SIGN
+20C0-20CF,UNASSIGNED,,<RESERVED>..<RESERVED>
+20D0-20F0,DISALLOWED,,COMBINING LEFT HARPOON ABOVE..COMBINING ASTERISK ABOVE
+20F1-20FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+2100-214D,DISALLOWED,,ACCOUNT OF..AKTIESELSKAB
+214E,PVALID,,TURNED SMALL F
+214F-2183,DISALLOWED,,SYMBOL FOR SAMARITAN SOURCE..ROMAN NUMERAL REVERSED ONE HUNDRED
+2184,PVALID,,LATIN SMALL LETTER REVERSED C
+2185-218B,DISALLOWED,,ROMAN NUMERAL SIX LATE FORM..TURNED DIGIT THREE
+218C-218F,UNASSIGNED,,<RESERVED>..<RESERVED>
+2190-2426,DISALLOWED,,LEFTWARDS ARROW..SYMBOL FOR SUBSTITUTE FORM TWO
+2427-243F,UNASSIGNED,,<RESERVED>..<RESERVED>
+2440-244A,DISALLOWED,,OCR HOOK..OCR DOUBLE BACKSLASH
+244B-245F,UNASSIGNED,,<RESERVED>..<RESERVED>
+2460-2B73,DISALLOWED,,CIRCLED DIGIT ONE..DOWNWARDS TRIANGLE-HEADED ARROW TO BAR
+2B74-2B75,UNASSIGNED,,<RESERVED>..<RESERVED>
+2B76-2B95,DISALLOWED,,NORTH WEST TRIANGLE-HEADED ARROW TO BAR..RIGHTWARDS BLACK ARROW
+2B96-2B97,UNASSIGNED,,<RESERVED>..<RESERVED>
+2B98-2BC8,DISALLOWED,,THREE-D TOP-LIGHTED LEFTWARDS EQUILATERAL ARROWHEAD..BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED
+2BC9,UNASSIGNED,,<RESERVED>
+2BCA-2BFE,DISALLOWED,,TOP HALF BLACK CIRCLE..REVERSED RIGHT ANGLE
+2BFF,UNASSIGNED,,<RESERVED>
+2C00-2C2E,DISALLOWED,,GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE
+2C2F,UNASSIGNED,,<RESERVED>
+2C30-2C5E,PVALID,,GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE
+2C5F,UNASSIGNED,,<RESERVED>
+2C60,DISALLOWED,,LATIN CAPITAL LETTER L WITH DOUBLE BAR
+2C61,PVALID,,LATIN SMALL LETTER L WITH DOUBLE BAR
+2C62-2C64,DISALLOWED,,LATIN CAPITAL LETTER L WITH MIDDLE TILDE..LATIN CAPITAL LETTER R WITH TAIL
+2C65-2C66,PVALID,,LATIN SMALL LETTER A WITH STROKE..LATIN SMALL LETTER T WITH DIAGONAL STROKE
+2C67,DISALLOWED,,LATIN CAPITAL LETTER H WITH DESCENDER
+2C68,PVALID,,LATIN SMALL LETTER H WITH DESCENDER
+2C69,DISALLOWED,,LATIN CAPITAL LETTER K WITH DESCENDER
+2C6A,PVALID,,LATIN SMALL LETTER K WITH DESCENDER
+2C6B,DISALLOWED,,LATIN CAPITAL LETTER Z WITH DESCENDER
+2C6C,PVALID,,LATIN SMALL LETTER Z WITH DESCENDER
+2C6D-2C70,DISALLOWED,,LATIN CAPITAL LETTER ALPHA..LATIN CAPITAL LETTER TURNED ALPHA
+2C71,PVALID,,LATIN SMALL LETTER V WITH RIGHT HOOK
+2C72,DISALLOWED,,LATIN CAPITAL LETTER W WITH HOOK
+2C73-2C74,PVALID,,LATIN SMALL LETTER W WITH HOOK..LATIN SMALL LETTER V WITH CURL
+2C75,DISALLOWED,,LATIN CAPITAL LETTER HALF H
+2C76-2C7B,PVALID,,LATIN SMALL LETTER HALF H..LATIN LETTER SMALL CAPITAL TURNED E
+2C7C-2C80,DISALLOWED,,LATIN SUBSCRIPT SMALL LETTER J..COPTIC CAPITAL LETTER ALFA
+2C81,PVALID,,COPTIC SMALL LETTER ALFA
+2C82,DISALLOWED,,COPTIC CAPITAL LETTER VIDA
+2C83,PVALID,,COPTIC SMALL LETTER VIDA
+2C84,DISALLOWED,,COPTIC CAPITAL LETTER GAMMA
+2C85,PVALID,,COPTIC SMALL LETTER GAMMA
+2C86,DISALLOWED,,COPTIC CAPITAL LETTER DALDA
+2C87,PVALID,,COPTIC SMALL LETTER DALDA
+2C88,DISALLOWED,,COPTIC CAPITAL LETTER EIE
+2C89,PVALID,,COPTIC SMALL LETTER EIE
+2C8A,DISALLOWED,,COPTIC CAPITAL LETTER SOU
+2C8B,PVALID,,COPTIC SMALL LETTER SOU
+2C8C,DISALLOWED,,COPTIC CAPITAL LETTER ZATA
+2C8D,PVALID,,COPTIC SMALL LETTER ZATA
+2C8E,DISALLOWED,,COPTIC CAPITAL LETTER HATE
+2C8F,PVALID,,COPTIC SMALL LETTER HATE
+2C90,DISALLOWED,,COPTIC CAPITAL LETTER THETHE
+2C91,PVALID,,COPTIC SMALL LETTER THETHE
+2C92,DISALLOWED,,COPTIC CAPITAL LETTER IAUDA
+2C93,PVALID,,COPTIC SMALL LETTER IAUDA
+2C94,DISALLOWED,,COPTIC CAPITAL LETTER KAPA
+2C95,PVALID,,COPTIC SMALL LETTER KAPA
+2C96,DISALLOWED,,COPTIC CAPITAL LETTER LAULA
+2C97,PVALID,,COPTIC SMALL LETTER LAULA
+2C98,DISALLOWED,,COPTIC CAPITAL LETTER MI
+2C99,PVALID,,COPTIC SMALL LETTER MI
+2C9A,DISALLOWED,,COPTIC CAPITAL LETTER NI
+2C9B,PVALID,,COPTIC SMALL LETTER NI
+2C9C,DISALLOWED,,COPTIC CAPITAL LETTER KSI
+2C9D,PVALID,,COPTIC SMALL LETTER KSI
+2C9E,DISALLOWED,,COPTIC CAPITAL LETTER O
+2C9F,PVALID,,COPTIC SMALL LETTER O
+2CA0,DISALLOWED,,COPTIC CAPITAL LETTER PI
+2CA1,PVALID,,COPTIC SMALL LETTER PI
+2CA2,DISALLOWED,,COPTIC CAPITAL LETTER RO
+2CA3,PVALID,,COPTIC SMALL LETTER RO
+2CA4,DISALLOWED,,COPTIC CAPITAL LETTER SIMA
+2CA5,PVALID,,COPTIC SMALL LETTER SIMA
+2CA6,DISALLOWED,,COPTIC CAPITAL LETTER TAU
+2CA7,PVALID,,COPTIC SMALL LETTER TAU
+2CA8,DISALLOWED,,COPTIC CAPITAL LETTER UA
+2CA9,PVALID,,COPTIC SMALL LETTER UA
+2CAA,DISALLOWED,,COPTIC CAPITAL LETTER FI
+2CAB,PVALID,,COPTIC SMALL LETTER FI
+2CAC,DISALLOWED,,COPTIC CAPITAL LETTER KHI
+2CAD,PVALID,,COPTIC SMALL LETTER KHI
+2CAE,DISALLOWED,,COPTIC CAPITAL LETTER PSI
+2CAF,PVALID,,COPTIC SMALL LETTER PSI
+2CB0,DISALLOWED,,COPTIC CAPITAL LETTER OOU
+2CB1,PVALID,,COPTIC SMALL LETTER OOU
+2CB2,DISALLOWED,,COPTIC CAPITAL LETTER DIALECT-P ALEF
+2CB3,PVALID,,COPTIC SMALL LETTER DIALECT-P ALEF
+2CB4,DISALLOWED,,COPTIC CAPITAL LETTER OLD COPTIC AIN
+2CB5,PVALID,,COPTIC SMALL LETTER OLD COPTIC AIN
+2CB6,DISALLOWED,,COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE
+2CB7,PVALID,,COPTIC SMALL LETTER CRYPTOGRAMMIC EIE
+2CB8,DISALLOWED,,COPTIC CAPITAL LETTER DIALECT-P KAPA
+2CB9,PVALID,,COPTIC SMALL LETTER DIALECT-P KAPA
+2CBA,DISALLOWED,,COPTIC CAPITAL LETTER DIALECT-P NI
+2CBB,PVALID,,COPTIC SMALL LETTER DIALECT-P NI
+2CBC,DISALLOWED,,COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI
+2CBD,PVALID,,COPTIC SMALL LETTER CRYPTOGRAMMIC NI
+2CBE,DISALLOWED,,COPTIC CAPITAL LETTER OLD COPTIC OOU
+2CBF,PVALID,,COPTIC SMALL LETTER OLD COPTIC OOU
+2CC0,DISALLOWED,,COPTIC CAPITAL LETTER SAMPI
+2CC1,PVALID,,COPTIC SMALL LETTER SAMPI
+2CC2,DISALLOWED,,COPTIC CAPITAL LETTER CROSSED SHEI
+2CC3,PVALID,,COPTIC SMALL LETTER CROSSED SHEI
+2CC4,DISALLOWED,,COPTIC CAPITAL LETTER OLD COPTIC SHEI
+2CC5,PVALID,,COPTIC SMALL LETTER OLD COPTIC SHEI
+2CC6,DISALLOWED,,COPTIC CAPITAL LETTER OLD COPTIC ESH
+2CC7,PVALID,,COPTIC SMALL LETTER OLD COPTIC ESH
+2CC8,DISALLOWED,,COPTIC CAPITAL LETTER AKHMIMIC KHEI
+2CC9,PVALID,,COPTIC SMALL LETTER AKHMIMIC KHEI
+2CCA,DISALLOWED,,COPTIC CAPITAL LETTER DIALECT-P HORI
+2CCB,PVALID,,COPTIC SMALL LETTER DIALECT-P HORI
+2CCC,DISALLOWED,,COPTIC CAPITAL LETTER OLD COPTIC HORI
+2CCD,PVALID,,COPTIC SMALL LETTER OLD COPTIC HORI
+2CCE,DISALLOWED,,COPTIC CAPITAL LETTER OLD COPTIC HA
+2CCF,PVALID,,COPTIC SMALL LETTER OLD COPTIC HA
+2CD0,DISALLOWED,,COPTIC CAPITAL LETTER L-SHAPED HA
+2CD1,PVALID,,COPTIC SMALL LETTER L-SHAPED HA
+2CD2,DISALLOWED,,COPTIC CAPITAL LETTER OLD COPTIC HEI
+2CD3,PVALID,,COPTIC SMALL LETTER OLD COPTIC HEI
+2CD4,DISALLOWED,,COPTIC CAPITAL LETTER OLD COPTIC HAT
+2CD5,PVALID,,COPTIC SMALL LETTER OLD COPTIC HAT
+2CD6,DISALLOWED,,COPTIC CAPITAL LETTER OLD COPTIC GANGIA
+2CD7,PVALID,,COPTIC SMALL LETTER OLD COPTIC GANGIA
+2CD8,DISALLOWED,,COPTIC CAPITAL LETTER OLD COPTIC DJA
+2CD9,PVALID,,COPTIC SMALL LETTER OLD COPTIC DJA
+2CDA,DISALLOWED,,COPTIC CAPITAL LETTER OLD COPTIC SHIMA
+2CDB,PVALID,,COPTIC SMALL LETTER OLD COPTIC SHIMA
+2CDC,DISALLOWED,,COPTIC CAPITAL LETTER OLD NUBIAN SHIMA
+2CDD,PVALID,,COPTIC SMALL LETTER OLD NUBIAN SHIMA
+2CDE,DISALLOWED,,COPTIC CAPITAL LETTER OLD NUBIAN NGI
+2CDF,PVALID,,COPTIC SMALL LETTER OLD NUBIAN NGI
+2CE0,DISALLOWED,,COPTIC CAPITAL LETTER OLD NUBIAN NYI
+2CE1,PVALID,,COPTIC SMALL LETTER OLD NUBIAN NYI
+2CE2,DISALLOWED,,COPTIC CAPITAL LETTER OLD NUBIAN WAU
+2CE3-2CE4,PVALID,,COPTIC SMALL LETTER OLD NUBIAN WAU..COPTIC SYMBOL KAI
+2CE5-2CEB,DISALLOWED,,COPTIC SYMBOL MI RO..COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI
+2CEC,PVALID,,COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI
+2CED,DISALLOWED,,COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA
+2CEE-2CF1,PVALID,,COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA..COPTIC COMBINING SPIRITUS LENIS
+2CF2,DISALLOWED,,COPTIC CAPITAL LETTER BOHAIRIC KHEI
+2CF3,PVALID,,COPTIC SMALL LETTER BOHAIRIC KHEI
+2CF4-2CF8,UNASSIGNED,,<RESERVED>..<RESERVED>
+2CF9-2CFF,DISALLOWED,,COPTIC OLD NUBIAN FULL STOP..COPTIC MORPHOLOGICAL DIVIDER
+2D00-2D25,PVALID,,GEORGIAN SMALL LETTER AN..GEORGIAN SMALL LETTER HOE
+2D26,UNASSIGNED,,<RESERVED>
+2D27,PVALID,,GEORGIAN SMALL LETTER YN
+2D28-2D2C,UNASSIGNED,,<RESERVED>..<RESERVED>
+2D2D,PVALID,,GEORGIAN SMALL LETTER AEN
+2D2E-2D2F,UNASSIGNED,,<RESERVED>..<RESERVED>
+2D30-2D67,PVALID,,TIFINAGH LETTER YA..TIFINAGH LETTER YO
+2D68-2D6E,UNASSIGNED,,<RESERVED>..<RESERVED>
+2D6F-2D70,DISALLOWED,,TIFINAGH MODIFIER LETTER LABIALIZATION MARK..TIFINAGH SEPARATOR MARK
+2D71-2D7E,UNASSIGNED,,<RESERVED>..<RESERVED>
+2D7F-2D96,PVALID,,TIFINAGH CONSONANT JOINER..ETHIOPIC SYLLABLE GGWE
+2D97-2D9F,UNASSIGNED,,<RESERVED>..<RESERVED>
+2DA0-2DA6,PVALID,,ETHIOPIC SYLLABLE SSA..ETHIOPIC SYLLABLE SSO
+2DA7,UNASSIGNED,,<RESERVED>
+2DA8-2DAE,PVALID,,ETHIOPIC SYLLABLE CCA..ETHIOPIC SYLLABLE CCO
+2DAF,UNASSIGNED,,<RESERVED>
+2DB0-2DB6,PVALID,,ETHIOPIC SYLLABLE ZZA..ETHIOPIC SYLLABLE ZZO
+2DB7,UNASSIGNED,,<RESERVED>
+2DB8-2DBE,PVALID,,ETHIOPIC SYLLABLE CCHA..ETHIOPIC SYLLABLE CCHO
+2DBF,UNASSIGNED,,<RESERVED>
+2DC0-2DC6,PVALID,,ETHIOPIC SYLLABLE QYA..ETHIOPIC SYLLABLE QYO
+2DC7,UNASSIGNED,,<RESERVED>
+2DC8-2DCE,PVALID,,ETHIOPIC SYLLABLE KYA..ETHIOPIC SYLLABLE KYO
+2DCF,UNASSIGNED,,<RESERVED>
+2DD0-2DD6,PVALID,,ETHIOPIC SYLLABLE XYA..ETHIOPIC SYLLABLE XYO
+2DD7,UNASSIGNED,,<RESERVED>
+2DD8-2DDE,PVALID,,ETHIOPIC SYLLABLE GYA..ETHIOPIC SYLLABLE GYO
+2DDF,UNASSIGNED,,<RESERVED>
+2DE0-2DFF,PVALID,,COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS
+2E00-2E2E,DISALLOWED,,RIGHT ANGLE SUBSTITUTION MARKER..REVERSED QUESTION MARK
+2E2F,PVALID,,VERTICAL TILDE
+2E30-2E4E,DISALLOWED,,RING POINT..PUNCTUS ELEVATUS MARK
+2E4F-2E7F,UNASSIGNED,,<RESERVED>..<RESERVED>
+2E80-2E99,DISALLOWED,,CJK RADICAL REPEAT..CJK RADICAL RAP
+2E9A,UNASSIGNED,,<RESERVED>
+2E9B-2EF3,DISALLOWED,,CJK RADICAL CHOKE..CJK RADICAL C-SIMPLIFIED TURTLE
+2EF4-2EFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+2F00-2FD5,DISALLOWED,,KANGXI RADICAL ONE..KANGXI RADICAL FLUTE
+2FD6-2FEF,UNASSIGNED,,<RESERVED>..<RESERVED>
+2FF0-2FFB,DISALLOWED,,IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID
+2FFC-2FFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+3000-3004,DISALLOWED,,IDEOGRAPHIC SPACE..JAPANESE INDUSTRIAL STANDARD SYMBOL
+3005-3007,PVALID,,IDEOGRAPHIC ITERATION MARK..IDEOGRAPHIC NUMBER ZERO
+3008-3029,DISALLOWED,,LEFT ANGLE BRACKET..HANGZHOU NUMERAL NINE
+302A-302D,PVALID,,IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK
+302E-303B,DISALLOWED,,HANGUL SINGLE DOT TONE MARK..VERTICAL IDEOGRAPHIC ITERATION MARK
+303C,PVALID,,MASU MARK
+303D-303F,DISALLOWED,,PART ALTERNATION MARK..IDEOGRAPHIC HALF FILL SPACE
+3040,UNASSIGNED,,<RESERVED>
+3041-3096,PVALID,,HIRAGANA LETTER SMALL A..HIRAGANA LETTER SMALL KE
+3097-3098,UNASSIGNED,,<RESERVED>..<RESERVED>
+3099-309A,PVALID,,COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+309B-309C,DISALLOWED,,KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+309D-309E,PVALID,,HIRAGANA ITERATION MARK..HIRAGANA VOICED ITERATION MARK
+309F-30A0,DISALLOWED,,HIRAGANA DIGRAPH YORI..KATAKANA-HIRAGANA DOUBLE HYPHEN
+30A1-30FA,PVALID,,KATAKANA LETTER SMALL A..KATAKANA LETTER VO
+30FB,CONTEXTO,,KATAKANA MIDDLE DOT
+30FC-30FE,PVALID,,KATAKANA-HIRAGANA PROLONGED SOUND MARK..KATAKANA VOICED ITERATION MARK
+30FF,DISALLOWED,,KATAKANA DIGRAPH KOTO
+3100-3104,UNASSIGNED,,<RESERVED>..<RESERVED>
+3105-312F,PVALID,,BOPOMOFO LETTER B..BOPOMOFO LETTER NN
+3130,UNASSIGNED,,<RESERVED>
+3131-318E,DISALLOWED,,HANGUL LETTER KIYEOK..HANGUL LETTER ARAEAE
+318F,UNASSIGNED,,<RESERVED>
+3190-319F,DISALLOWED,,IDEOGRAPHIC ANNOTATION LINKING MARK..IDEOGRAPHIC ANNOTATION MAN MARK
+31A0-31BA,PVALID,,BOPOMOFO LETTER BU..BOPOMOFO LETTER ZY
+31BB-31BF,UNASSIGNED,,<RESERVED>..<RESERVED>
+31C0-31E3,DISALLOWED,,CJK STROKE T..CJK STROKE Q
+31E4-31EF,UNASSIGNED,,<RESERVED>..<RESERVED>
+31F0-31FF,PVALID,,KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO
+3200-321E,DISALLOWED,,PARENTHESIZED HANGUL KIYEOK..PARENTHESIZED KOREAN CHARACTER O HU
+321F,UNASSIGNED,,<RESERVED>
+3220-32FE,DISALLOWED,,PARENTHESIZED IDEOGRAPH ONE..CIRCLED KATAKANA WO
+32FF,UNASSIGNED,,<RESERVED>
+3300-33FF,DISALLOWED,,SQUARE APAATO..SQUARE GAL
+3400-4DB5,PVALID,,"<CJK IDEOGRAPH EXTENSION A, FIRST>..<CJK IDEOGRAPH EXTENSION A, LAST>"
+4DB6-4DBF,UNASSIGNED,,<RESERVED>..<RESERVED>
+4DC0-4DFF,DISALLOWED,,HEXAGRAM FOR THE CREATIVE HEAVEN..HEXAGRAM FOR BEFORE COMPLETION
+4E00-9FEF,PVALID,,"<CJK IDEOGRAPH, FIRST>..<CJK IDEOGRAPH, LAST>"
+9FF0-9FFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+A000-A48C,PVALID,,YI SYLLABLE IT..YI SYLLABLE YYR
+A48D-A48F,UNASSIGNED,,<RESERVED>..<RESERVED>
+A490-A4C6,DISALLOWED,,YI RADICAL QOT..YI RADICAL KE
+A4C7-A4CF,UNASSIGNED,,<RESERVED>..<RESERVED>
+A4D0-A4FD,PVALID,,LISU LETTER BA..LISU LETTER TONE MYA JEU
+A4FE-A4FF,DISALLOWED,,LISU PUNCTUATION COMMA..LISU PUNCTUATION FULL STOP
+A500-A60C,PVALID,,VAI SYLLABLE EE..VAI SYLLABLE LENGTHENER
+A60D-A60F,DISALLOWED,,VAI COMMA..VAI QUESTION MARK
+A610-A62B,PVALID,,VAI SYLLABLE NDOLE FA..VAI SYLLABLE NDOLE DO
+A62C-A63F,UNASSIGNED,,<RESERVED>..<RESERVED>
+A640,DISALLOWED,,CYRILLIC CAPITAL LETTER ZEMLYA
+A641,PVALID,,CYRILLIC SMALL LETTER ZEMLYA
+A642,DISALLOWED,,CYRILLIC CAPITAL LETTER DZELO
+A643,PVALID,,CYRILLIC SMALL LETTER DZELO
+A644,DISALLOWED,,CYRILLIC CAPITAL LETTER REVERSED DZE
+A645,PVALID,,CYRILLIC SMALL LETTER REVERSED DZE
+A646,DISALLOWED,,CYRILLIC CAPITAL LETTER IOTA
+A647,PVALID,,CYRILLIC SMALL LETTER IOTA
+A648,DISALLOWED,,CYRILLIC CAPITAL LETTER DJERV
+A649,PVALID,,CYRILLIC SMALL LETTER DJERV
+A64A,DISALLOWED,,CYRILLIC CAPITAL LETTER MONOGRAPH UK
+A64B,PVALID,,CYRILLIC SMALL LETTER MONOGRAPH UK
+A64C,DISALLOWED,,CYRILLIC CAPITAL LETTER BROAD OMEGA
+A64D,PVALID,,CYRILLIC SMALL LETTER BROAD OMEGA
+A64E,DISALLOWED,,CYRILLIC CAPITAL LETTER NEUTRAL YER
+A64F,PVALID,,CYRILLIC SMALL LETTER NEUTRAL YER
+A650,DISALLOWED,,CYRILLIC CAPITAL LETTER YERU WITH BACK YER
+A651,PVALID,,CYRILLIC SMALL LETTER YERU WITH BACK YER
+A652,DISALLOWED,,CYRILLIC CAPITAL LETTER IOTIFIED YAT
+A653,PVALID,,CYRILLIC SMALL LETTER IOTIFIED YAT
+A654,DISALLOWED,,CYRILLIC CAPITAL LETTER REVERSED YU
+A655,PVALID,,CYRILLIC SMALL LETTER REVERSED YU
+A656,DISALLOWED,,CYRILLIC CAPITAL LETTER IOTIFIED A
+A657,PVALID,,CYRILLIC SMALL LETTER IOTIFIED A
+A658,DISALLOWED,,CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS
+A659,PVALID,,CYRILLIC SMALL LETTER CLOSED LITTLE YUS
+A65A,DISALLOWED,,CYRILLIC CAPITAL LETTER BLENDED YUS
+A65B,PVALID,,CYRILLIC SMALL LETTER BLENDED YUS
+A65C,DISALLOWED,,CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS
+A65D,PVALID,,CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS
+A65E,DISALLOWED,,CYRILLIC CAPITAL LETTER YN
+A65F,PVALID,,CYRILLIC SMALL LETTER YN
+A660,DISALLOWED,,CYRILLIC CAPITAL LETTER REVERSED TSE
+A661,PVALID,,CYRILLIC SMALL LETTER REVERSED TSE
+A662,DISALLOWED,,CYRILLIC CAPITAL LETTER SOFT DE
+A663,PVALID,,CYRILLIC SMALL LETTER SOFT DE
+A664,DISALLOWED,,CYRILLIC CAPITAL LETTER SOFT EL
+A665,PVALID,,CYRILLIC SMALL LETTER SOFT EL
+A666,DISALLOWED,,CYRILLIC CAPITAL LETTER SOFT EM
+A667,PVALID,,CYRILLIC SMALL LETTER SOFT EM
+A668,DISALLOWED,,CYRILLIC CAPITAL LETTER MONOCULAR O
+A669,PVALID,,CYRILLIC SMALL LETTER MONOCULAR O
+A66A,DISALLOWED,,CYRILLIC CAPITAL LETTER BINOCULAR O
+A66B,PVALID,,CYRILLIC SMALL LETTER BINOCULAR O
+A66C,DISALLOWED,,CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O
+A66D-A66F,PVALID,,CYRILLIC SMALL LETTER DOUBLE MONOCULAR O..COMBINING CYRILLIC VZMET
+A670-A673,DISALLOWED,,COMBINING CYRILLIC TEN MILLIONS SIGN..SLAVONIC ASTERISK
+A674-A67D,PVALID,,COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC PAYEROK
+A67E,DISALLOWED,,CYRILLIC KAVYKA
+A67F,PVALID,,CYRILLIC PAYEROK
+A680,DISALLOWED,,CYRILLIC CAPITAL LETTER DWE
+A681,PVALID,,CYRILLIC SMALL LETTER DWE
+A682,DISALLOWED,,CYRILLIC CAPITAL LETTER DZWE
+A683,PVALID,,CYRILLIC SMALL LETTER DZWE
+A684,DISALLOWED,,CYRILLIC CAPITAL LETTER ZHWE
+A685,PVALID,,CYRILLIC SMALL LETTER ZHWE
+A686,DISALLOWED,,CYRILLIC CAPITAL LETTER CCHE
+A687,PVALID,,CYRILLIC SMALL LETTER CCHE
+A688,DISALLOWED,,CYRILLIC CAPITAL LETTER DZZE
+A689,PVALID,,CYRILLIC SMALL LETTER DZZE
+A68A,DISALLOWED,,CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK
+A68B,PVALID,,CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK
+A68C,DISALLOWED,,CYRILLIC CAPITAL LETTER TWE
+A68D,PVALID,,CYRILLIC SMALL LETTER TWE
+A68E,DISALLOWED,,CYRILLIC CAPITAL LETTER TSWE
+A68F,PVALID,,CYRILLIC SMALL LETTER TSWE
+A690,DISALLOWED,,CYRILLIC CAPITAL LETTER TSSE
+A691,PVALID,,CYRILLIC SMALL LETTER TSSE
+A692,DISALLOWED,,CYRILLIC CAPITAL LETTER TCHE
+A693,PVALID,,CYRILLIC SMALL LETTER TCHE
+A694,DISALLOWED,,CYRILLIC CAPITAL LETTER HWE
+A695,PVALID,,CYRILLIC SMALL LETTER HWE
+A696,DISALLOWED,,CYRILLIC CAPITAL LETTER SHWE
+A697,PVALID,,CYRILLIC SMALL LETTER SHWE
+A698,DISALLOWED,,CYRILLIC CAPITAL LETTER DOUBLE O
+A699,PVALID,,CYRILLIC SMALL LETTER DOUBLE O
+A69A,DISALLOWED,,CYRILLIC CAPITAL LETTER CROSSED O
+A69B,PVALID,,CYRILLIC SMALL LETTER CROSSED O
+A69C-A69D,DISALLOWED,,MODIFIER LETTER CYRILLIC HARD SIGN..MODIFIER LETTER CYRILLIC SOFT SIGN
+A69E-A6E5,PVALID,,COMBINING CYRILLIC LETTER EF..BAMUM LETTER KI
+A6E6-A6EF,DISALLOWED,,BAMUM LETTER MO..BAMUM LETTER KOGHOM
+A6F0-A6F1,PVALID,,BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS
+A6F2-A6F7,DISALLOWED,,BAMUM NJAEMLI..BAMUM QUESTION MARK
+A6F8-A6FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+A700-A716,DISALLOWED,,MODIFIER LETTER CHINESE TONE YIN PING..MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR
+A717-A71F,PVALID,,MODIFIER LETTER DOT VERTICAL BAR..MODIFIER LETTER LOW INVERTED EXCLAMATION MARK
+A720-A722,DISALLOWED,,MODIFIER LETTER STRESS AND HIGH TONE..LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF
+A723,PVALID,,LATIN SMALL LETTER EGYPTOLOGICAL ALEF
+A724,DISALLOWED,,LATIN CAPITAL LETTER EGYPTOLOGICAL AIN
+A725,PVALID,,LATIN SMALL LETTER EGYPTOLOGICAL AIN
+A726,DISALLOWED,,LATIN CAPITAL LETTER HENG
+A727,PVALID,,LATIN SMALL LETTER HENG
+A728,DISALLOWED,,LATIN CAPITAL LETTER TZ
+A729,PVALID,,LATIN SMALL LETTER TZ
+A72A,DISALLOWED,,LATIN CAPITAL LETTER TRESILLO
+A72B,PVALID,,LATIN SMALL LETTER TRESILLO
+A72C,DISALLOWED,,LATIN CAPITAL LETTER CUATRILLO
+A72D,PVALID,,LATIN SMALL LETTER CUATRILLO
+A72E,DISALLOWED,,LATIN CAPITAL LETTER CUATRILLO WITH COMMA
+A72F-A731,PVALID,,LATIN SMALL LETTER CUATRILLO WITH COMMA..LATIN LETTER SMALL CAPITAL S
+A732,DISALLOWED,,LATIN CAPITAL LETTER AA
+A733,PVALID,,LATIN SMALL LETTER AA
+A734,DISALLOWED,,LATIN CAPITAL LETTER AO
+A735,PVALID,,LATIN SMALL LETTER AO
+A736,DISALLOWED,,LATIN CAPITAL LETTER AU
+A737,PVALID,,LATIN SMALL LETTER AU
+A738,DISALLOWED,,LATIN CAPITAL LETTER AV
+A739,PVALID,,LATIN SMALL LETTER AV
+A73A,DISALLOWED,,LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR
+A73B,PVALID,,LATIN SMALL LETTER AV WITH HORIZONTAL BAR
+A73C,DISALLOWED,,LATIN CAPITAL LETTER AY
+A73D,PVALID,,LATIN SMALL LETTER AY
+A73E,DISALLOWED,,LATIN CAPITAL LETTER REVERSED C WITH DOT
+A73F,PVALID,,LATIN SMALL LETTER REVERSED C WITH DOT
+A740,DISALLOWED,,LATIN CAPITAL LETTER K WITH STROKE
+A741,PVALID,,LATIN SMALL LETTER K WITH STROKE
+A742,DISALLOWED,,LATIN CAPITAL LETTER K WITH DIAGONAL STROKE
+A743,PVALID,,LATIN SMALL LETTER K WITH DIAGONAL STROKE
+A744,DISALLOWED,,LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE
+A745,PVALID,,LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE
+A746,DISALLOWED,,LATIN CAPITAL LETTER BROKEN L
+A747,PVALID,,LATIN SMALL LETTER BROKEN L
+A748,DISALLOWED,,LATIN CAPITAL LETTER L WITH HIGH STROKE
+A749,PVALID,,LATIN SMALL LETTER L WITH HIGH STROKE
+A74A,DISALLOWED,,LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY
+A74B,PVALID,,LATIN SMALL LETTER O WITH LONG STROKE OVERLAY
+A74C,DISALLOWED,,LATIN CAPITAL LETTER O WITH LOOP
+A74D,PVALID,,LATIN SMALL LETTER O WITH LOOP
+A74E,DISALLOWED,,LATIN CAPITAL LETTER OO
+A74F,PVALID,,LATIN SMALL LETTER OO
+A750,DISALLOWED,,LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER
+A751,PVALID,,LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER
+A752,DISALLOWED,,LATIN CAPITAL LETTER P WITH FLOURISH
+A753,PVALID,,LATIN SMALL LETTER P WITH FLOURISH
+A754,DISALLOWED,,LATIN CAPITAL LETTER P WITH SQUIRREL TAIL
+A755,PVALID,,LATIN SMALL LETTER P WITH SQUIRREL TAIL
+A756,DISALLOWED,,LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER
+A757,PVALID,,LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER
+A758,DISALLOWED,,LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE
+A759,PVALID,,LATIN SMALL LETTER Q WITH DIAGONAL STROKE
+A75A,DISALLOWED,,LATIN CAPITAL LETTER R ROTUNDA
+A75B,PVALID,,LATIN SMALL LETTER R ROTUNDA
+A75C,DISALLOWED,,LATIN CAPITAL LETTER RUM ROTUNDA
+A75D,PVALID,,LATIN SMALL LETTER RUM ROTUNDA
+A75E,DISALLOWED,,LATIN CAPITAL LETTER V WITH DIAGONAL STROKE
+A75F,PVALID,,LATIN SMALL LETTER V WITH DIAGONAL STROKE
+A760,DISALLOWED,,LATIN CAPITAL LETTER VY
+A761,PVALID,,LATIN SMALL LETTER VY
+A762,DISALLOWED,,LATIN CAPITAL LETTER VISIGOTHIC Z
+A763,PVALID,,LATIN SMALL LETTER VISIGOTHIC Z
+A764,DISALLOWED,,LATIN CAPITAL LETTER THORN WITH STROKE
+A765,PVALID,,LATIN SMALL LETTER THORN WITH STROKE
+A766,DISALLOWED,,LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER
+A767,PVALID,,LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER
+A768,DISALLOWED,,LATIN CAPITAL LETTER VEND
+A769,PVALID,,LATIN SMALL LETTER VEND
+A76A,DISALLOWED,,LATIN CAPITAL LETTER ET
+A76B,PVALID,,LATIN SMALL LETTER ET
+A76C,DISALLOWED,,LATIN CAPITAL LETTER IS
+A76D,PVALID,,LATIN SMALL LETTER IS
+A76E,DISALLOWED,,LATIN CAPITAL LETTER CON
+A76F,PVALID,,LATIN SMALL LETTER CON
+A770,DISALLOWED,,MODIFIER LETTER US
+A771-A778,PVALID,,LATIN SMALL LETTER DUM..LATIN SMALL LETTER UM
+A779,DISALLOWED,,LATIN CAPITAL LETTER INSULAR D
+A77A,PVALID,,LATIN SMALL LETTER INSULAR D
+A77B,DISALLOWED,,LATIN CAPITAL LETTER INSULAR F
+A77C,PVALID,,LATIN SMALL LETTER INSULAR F
+A77D-A77E,DISALLOWED,,LATIN CAPITAL LETTER INSULAR G..LATIN CAPITAL LETTER TURNED INSULAR G
+A77F,PVALID,,LATIN SMALL LETTER TURNED INSULAR G
+A780,DISALLOWED,,LATIN CAPITAL LETTER TURNED L
+A781,PVALID,,LATIN SMALL LETTER TURNED L
+A782,DISALLOWED,,LATIN CAPITAL LETTER INSULAR R
+A783,PVALID,,LATIN SMALL LETTER INSULAR R
+A784,DISALLOWED,,LATIN CAPITAL LETTER INSULAR S
+A785,PVALID,,LATIN SMALL LETTER INSULAR S
+A786,DISALLOWED,,LATIN CAPITAL LETTER INSULAR T
+A787-A788,PVALID,,LATIN SMALL LETTER INSULAR T..MODIFIER LETTER LOW CIRCUMFLEX ACCENT
+A789-A78B,DISALLOWED,,MODIFIER LETTER COLON..LATIN CAPITAL LETTER SALTILLO
+A78C,PVALID,,LATIN SMALL LETTER SALTILLO
+A78D,DISALLOWED,,LATIN CAPITAL LETTER TURNED H
+A78E-A78F,PVALID,,LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT..LATIN LETTER SINOLOGICAL DOT
+A790,DISALLOWED,,LATIN CAPITAL LETTER N WITH DESCENDER
+A791,PVALID,,LATIN SMALL LETTER N WITH DESCENDER
+A792,DISALLOWED,,LATIN CAPITAL LETTER C WITH BAR
+A793-A795,PVALID,,LATIN SMALL LETTER C WITH BAR..LATIN SMALL LETTER H WITH PALATAL HOOK
+A796,DISALLOWED,,LATIN CAPITAL LETTER B WITH FLOURISH
+A797,PVALID,,LATIN SMALL LETTER B WITH FLOURISH
+A798,DISALLOWED,,LATIN CAPITAL LETTER F WITH STROKE
+A799,PVALID,,LATIN SMALL LETTER F WITH STROKE
+A79A,DISALLOWED,,LATIN CAPITAL LETTER VOLAPUK AE
+A79B,PVALID,,LATIN SMALL LETTER VOLAPUK AE
+A79C,DISALLOWED,,LATIN CAPITAL LETTER VOLAPUK OE
+A79D,PVALID,,LATIN SMALL LETTER VOLAPUK OE
+A79E,DISALLOWED,,LATIN CAPITAL LETTER VOLAPUK UE
+A79F,PVALID,,LATIN SMALL LETTER VOLAPUK UE
+A7A0,DISALLOWED,,LATIN CAPITAL LETTER G WITH OBLIQUE STROKE
+A7A1,PVALID,,LATIN SMALL LETTER G WITH OBLIQUE STROKE
+A7A2,DISALLOWED,,LATIN CAPITAL LETTER K WITH OBLIQUE STROKE
+A7A3,PVALID,,LATIN SMALL LETTER K WITH OBLIQUE STROKE
+A7A4,DISALLOWED,,LATIN CAPITAL LETTER N WITH OBLIQUE STROKE
+A7A5,PVALID,,LATIN SMALL LETTER N WITH OBLIQUE STROKE
+A7A6,DISALLOWED,,LATIN CAPITAL LETTER R WITH OBLIQUE STROKE
+A7A7,PVALID,,LATIN SMALL LETTER R WITH OBLIQUE STROKE
+A7A8,DISALLOWED,,LATIN CAPITAL LETTER S WITH OBLIQUE STROKE
+A7A9,PVALID,,LATIN SMALL LETTER S WITH OBLIQUE STROKE
+A7AA-A7AE,DISALLOWED,,LATIN CAPITAL LETTER H WITH HOOK..LATIN CAPITAL LETTER SMALL CAPITAL I
+A7AF,PVALID,,LATIN LETTER SMALL CAPITAL Q
+A7B0-A7B4,DISALLOWED,,LATIN CAPITAL LETTER TURNED K..LATIN CAPITAL LETTER BETA
+A7B5,PVALID,,LATIN SMALL LETTER BETA
+A7B6,DISALLOWED,,LATIN CAPITAL LETTER OMEGA
+A7B7,PVALID,,LATIN SMALL LETTER OMEGA
+A7B8,DISALLOWED,,LATIN CAPITAL LETTER U WITH STROKE
+A7B9,PVALID,,LATIN SMALL LETTER U WITH STROKE
+A7BA-A7F6,UNASSIGNED,,<RESERVED>..<RESERVED>
+A7F7,PVALID,,LATIN EPIGRAPHIC LETTER SIDEWAYS I
+A7F8-A7F9,DISALLOWED,,MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE
+A7FA-A827,PVALID,,LATIN LETTER SMALL CAPITAL TURNED M..SYLOTI NAGRI VOWEL SIGN OO
+A828-A82B,DISALLOWED,,SYLOTI NAGRI POETRY MARK-1..SYLOTI NAGRI POETRY MARK-4
+A82C-A82F,UNASSIGNED,,<RESERVED>..<RESERVED>
+A830-A839,DISALLOWED,,NORTH INDIC FRACTION ONE QUARTER..NORTH INDIC QUANTITY MARK
+A83A-A83F,UNASSIGNED,,<RESERVED>..<RESERVED>
+A840-A873,PVALID,,PHAGS-PA LETTER KA..PHAGS-PA LETTER CANDRABINDU
+A874-A877,DISALLOWED,,PHAGS-PA SINGLE HEAD MARK..PHAGS-PA MARK DOUBLE SHAD
+A878-A87F,UNASSIGNED,,<RESERVED>..<RESERVED>
+A880-A8C5,PVALID,,SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN CANDRABINDU
+A8C6-A8CD,UNASSIGNED,,<RESERVED>..<RESERVED>
+A8CE-A8CF,DISALLOWED,,SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA
+A8D0-A8D9,PVALID,,SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE
+A8DA-A8DF,UNASSIGNED,,<RESERVED>..<RESERVED>
+A8E0-A8F7,PVALID,,COMBINING DEVANAGARI DIGIT ZERO..DEVANAGARI SIGN CANDRABINDU AVAGRAHA
+A8F8-A8FA,DISALLOWED,,DEVANAGARI SIGN PUSHPIKA..DEVANAGARI CARET
+A8FB,PVALID,,DEVANAGARI HEADSTROKE
+A8FC,DISALLOWED,,DEVANAGARI SIGN SIDDHAM
+A8FD-A92D,PVALID,,DEVANAGARI JAIN OM..KAYAH LI TONE CALYA PLOPHU
+A92E-A92F,DISALLOWED,,KAYAH LI SIGN CWI..KAYAH LI SIGN SHYA
+A930-A953,PVALID,,REJANG LETTER KA..REJANG VIRAMA
+A954-A95E,UNASSIGNED,,<RESERVED>..<RESERVED>
+A95F-A97C,DISALLOWED,,REJANG SECTION MARK..HANGUL CHOSEONG SSANGYEORINHIEUH
+A97D-A97F,UNASSIGNED,,<RESERVED>..<RESERVED>
+A980-A9C0,PVALID,,JAVANESE SIGN PANYANGGA..JAVANESE PANGKON
+A9C1-A9CD,DISALLOWED,,JAVANESE LEFT RERENGGAN..JAVANESE TURNED PADA PISELEH
+A9CE,UNASSIGNED,,<RESERVED>
+A9CF-A9D9,PVALID,,JAVANESE PANGRANGKEP..JAVANESE DIGIT NINE
+A9DA-A9DD,UNASSIGNED,,<RESERVED>..<RESERVED>
+A9DE-A9DF,DISALLOWED,,JAVANESE PADA TIRTA TUMETES..JAVANESE PADA ISEN-ISEN
+A9E0-A9FE,PVALID,,MYANMAR LETTER SHAN GHA..MYANMAR LETTER TAI LAING BHA
+A9FF,UNASSIGNED,,<RESERVED>
+AA00-AA36,PVALID,,CHAM LETTER A..CHAM CONSONANT SIGN WA
+AA37-AA3F,UNASSIGNED,,<RESERVED>..<RESERVED>
+AA40-AA4D,PVALID,,CHAM LETTER FINAL K..CHAM CONSONANT SIGN FINAL H
+AA4E-AA4F,UNASSIGNED,,<RESERVED>..<RESERVED>
+AA50-AA59,PVALID,,CHAM DIGIT ZERO..CHAM DIGIT NINE
+AA5A-AA5B,UNASSIGNED,,<RESERVED>..<RESERVED>
+AA5C-AA5F,DISALLOWED,,CHAM PUNCTUATION SPIRAL..CHAM PUNCTUATION TRIPLE DANDA
+AA60-AA76,PVALID,,MYANMAR LETTER KHAMTI GA..MYANMAR LOGOGRAM KHAMTI HM
+AA77-AA79,DISALLOWED,,MYANMAR SYMBOL AITON EXCLAMATION..MYANMAR SYMBOL AITON TWO
+AA7A-AAC2,PVALID,,MYANMAR LETTER AITON RA..TAI VIET TONE MAI SONG
+AAC3-AADA,UNASSIGNED,,<RESERVED>..<RESERVED>
+AADB-AADD,PVALID,,TAI VIET SYMBOL KON..TAI VIET SYMBOL SAM
+AADE-AADF,DISALLOWED,,TAI VIET SYMBOL HO HOI..TAI VIET SYMBOL KOI KOI
+AAE0-AAEF,PVALID,,MEETEI MAYEK LETTER E..MEETEI MAYEK VOWEL SIGN AAU
+AAF0-AAF1,DISALLOWED,,MEETEI MAYEK CHEIKHAN..MEETEI MAYEK AHANG KHUDAM
+AAF2-AAF6,PVALID,,MEETEI MAYEK ANJI..MEETEI MAYEK VIRAMA
+AAF7-AB00,UNASSIGNED,,<RESERVED>..<RESERVED>
+AB01-AB06,PVALID,,ETHIOPIC SYLLABLE TTHU..ETHIOPIC SYLLABLE TTHO
+AB07-AB08,UNASSIGNED,,<RESERVED>..<RESERVED>
+AB09-AB0E,PVALID,,ETHIOPIC SYLLABLE DDHU..ETHIOPIC SYLLABLE DDHO
+AB0F-AB10,UNASSIGNED,,<RESERVED>..<RESERVED>
+AB11-AB16,PVALID,,ETHIOPIC SYLLABLE DZU..ETHIOPIC SYLLABLE DZO
+AB17-AB1F,UNASSIGNED,,<RESERVED>..<RESERVED>
+AB20-AB26,PVALID,,ETHIOPIC SYLLABLE CCHHA..ETHIOPIC SYLLABLE CCHHO
+AB27,UNASSIGNED,,<RESERVED>
+AB28-AB2E,PVALID,,ETHIOPIC SYLLABLE BBA..ETHIOPIC SYLLABLE BBO
+AB2F,UNASSIGNED,,<RESERVED>
+AB30-AB5A,PVALID,,LATIN SMALL LETTER BARRED ALPHA..LATIN SMALL LETTER Y WITH SHORT RIGHT LEG
+AB5B-AB5F,DISALLOWED,,MODIFIER BREVE WITH INVERTED BREVE..MODIFIER LETTER SMALL U WITH LEFT HOOK
+AB60-AB65,PVALID,,LATIN SMALL LETTER SAKHA YAT..GREEK LETTER SMALL CAPITAL OMEGA
+AB66-AB6F,UNASSIGNED,,<RESERVED>..<RESERVED>
+AB70-ABBF,DISALLOWED,,CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETTER YA
+ABC0-ABEA,PVALID,,MEETEI MAYEK LETTER KOK..MEETEI MAYEK VOWEL SIGN NUNG
+ABEB,DISALLOWED,,MEETEI MAYEK CHEIKHEI
+ABEC-ABED,PVALID,,MEETEI MAYEK LUM IYEK..MEETEI MAYEK APUN IYEK
+ABEE-ABEF,UNASSIGNED,,<RESERVED>..<RESERVED>
+ABF0-ABF9,PVALID,,MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DIGIT NINE
+ABFA-ABFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+AC00-D7A3,PVALID,,"<HANGUL SYLLABLE, FIRST>..<HANGUL SYLLABLE, LAST>"
+D7A4-D7AF,UNASSIGNED,,<RESERVED>..<RESERVED>
+D7B0-D7C6,DISALLOWED,,HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARAEA-E
+D7C7-D7CA,UNASSIGNED,,<RESERVED>..<RESERVED>
+D7CB-D7FB,DISALLOWED,,HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEONG PHIEUPH-THIEUTH
+D7FC-D7FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+D800-FA0D,DISALLOWED,,"<NON PRIVATE USE HIGH SURROGATE, FIRST>..CJK COMPATIBILITY IDEOGRAPH-FA0D"
+FA0E-FA0F,PVALID,,CJK COMPATIBILITY IDEOGRAPH-FA0E..CJK COMPATIBILITY IDEOGRAPH-FA0F
+FA10,DISALLOWED,,CJK COMPATIBILITY IDEOGRAPH-FA10
+FA11,PVALID,,CJK COMPATIBILITY IDEOGRAPH-FA11
+FA12,DISALLOWED,,CJK COMPATIBILITY IDEOGRAPH-FA12
+FA13-FA14,PVALID,,CJK COMPATIBILITY IDEOGRAPH-FA13..CJK COMPATIBILITY IDEOGRAPH-FA14
+FA15-FA1E,DISALLOWED,,CJK COMPATIBILITY IDEOGRAPH-FA15..CJK COMPATIBILITY IDEOGRAPH-FA1E
+FA1F,PVALID,,CJK COMPATIBILITY IDEOGRAPH-FA1F
+FA20,DISALLOWED,,CJK COMPATIBILITY IDEOGRAPH-FA20
+FA21,PVALID,,CJK COMPATIBILITY IDEOGRAPH-FA21
+FA22,DISALLOWED,,CJK COMPATIBILITY IDEOGRAPH-FA22
+FA23-FA24,PVALID,,CJK COMPATIBILITY IDEOGRAPH-FA23..CJK COMPATIBILITY IDEOGRAPH-FA24
+FA25-FA26,DISALLOWED,,CJK COMPATIBILITY IDEOGRAPH-FA25..CJK COMPATIBILITY IDEOGRAPH-FA26
+FA27-FA29,PVALID,,CJK COMPATIBILITY IDEOGRAPH-FA27..CJK COMPATIBILITY IDEOGRAPH-FA29
+FA2A-FA6D,DISALLOWED,,CJK COMPATIBILITY IDEOGRAPH-FA2A..CJK COMPATIBILITY IDEOGRAPH-FA6D
+FA6E-FA6F,UNASSIGNED,,<RESERVED>..<RESERVED>
+FA70-FAD9,DISALLOWED,,CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9
+FADA-FAFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+FB00-FB06,DISALLOWED,,LATIN SMALL LIGATURE FF..LATIN SMALL LIGATURE ST
+FB07-FB12,UNASSIGNED,,<RESERVED>..<RESERVED>
+FB13-FB17,DISALLOWED,,ARMENIAN SMALL LIGATURE MEN NOW..ARMENIAN SMALL LIGATURE MEN XEH
+FB18-FB1C,UNASSIGNED,,<RESERVED>..<RESERVED>
+FB1D,DISALLOWED,,HEBREW LETTER YOD WITH HIRIQ
+FB1E,PVALID,,HEBREW POINT JUDEO-SPANISH VARIKA
+FB1F-FB36,DISALLOWED,,HEBREW LIGATURE YIDDISH YOD YOD PATAH..HEBREW LETTER ZAYIN WITH DAGESH
+FB37,UNASSIGNED,,<RESERVED>
+FB38-FB3C,DISALLOWED,,HEBREW LETTER TET WITH DAGESH..HEBREW LETTER LAMED WITH DAGESH
+FB3D,UNASSIGNED,,<RESERVED>
+FB3E,DISALLOWED,,HEBREW LETTER MEM WITH DAGESH
+FB3F,UNASSIGNED,,<RESERVED>
+FB40-FB41,DISALLOWED,,HEBREW LETTER NUN WITH DAGESH..HEBREW LETTER SAMEKH WITH DAGESH
+FB42,UNASSIGNED,,<RESERVED>
+FB43-FB44,DISALLOWED,,HEBREW LETTER FINAL PE WITH DAGESH..HEBREW LETTER PE WITH DAGESH
+FB45,UNASSIGNED,,<RESERVED>
+FB46-FBC1,DISALLOWED,,HEBREW LETTER TSADI WITH DAGESH..ARABIC SYMBOL SMALL TAH BELOW
+FBC2-FBD2,UNASSIGNED,,<RESERVED>..<RESERVED>
+FBD3-FD3F,DISALLOWED,,ARABIC LETTER NG ISOLATED FORM..ORNATE RIGHT PARENTHESIS
+FD40-FD4F,UNASSIGNED,,<RESERVED>..<RESERVED>
+FD50-FD8F,DISALLOWED,,ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM..ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM
+FD90-FD91,UNASSIGNED,,<RESERVED>..<RESERVED>
+FD92-FDC7,DISALLOWED,,ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM..ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM
+FDC8-FDCF,UNASSIGNED,,<RESERVED>..<RESERVED>
+FDD0-FDFD,DISALLOWED,,<NOT A CHARACTER>..ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM
+FDFE-FDFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+FE00-FE19,DISALLOWED,,VARIATION SELECTOR-1..PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS
+FE1A-FE1F,UNASSIGNED,,<RESERVED>..<RESERVED>
+FE20-FE2F,PVALID,,COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF
+FE30-FE52,DISALLOWED,,PRESENTATION FORM FOR VERTICAL TWO DOT LEADER..SMALL FULL STOP
+FE53,UNASSIGNED,,<RESERVED>
+FE54-FE66,DISALLOWED,,SMALL SEMICOLON..SMALL EQUALS SIGN
+FE67,UNASSIGNED,,<RESERVED>
+FE68-FE6B,DISALLOWED,,SMALL REVERSE SOLIDUS..SMALL COMMERCIAL AT
+FE6C-FE6F,UNASSIGNED,,<RESERVED>..<RESERVED>
+FE70-FE72,DISALLOWED,,ARABIC FATHATAN ISOLATED FORM..ARABIC DAMMATAN ISOLATED FORM
+FE73,PVALID,,ARABIC TAIL FRAGMENT
+FE74,DISALLOWED,,ARABIC KASRATAN ISOLATED FORM
+FE75,UNASSIGNED,,<RESERVED>
+FE76-FEFC,DISALLOWED,,ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE LAM WITH ALEF FINAL FORM
+FEFD-FEFE,UNASSIGNED,,<RESERVED>..<RESERVED>
+FEFF,DISALLOWED,,ZERO WIDTH NO-BREAK SPACE
+FF00,UNASSIGNED,,<RESERVED>
+FF01-FFBE,DISALLOWED,,FULLWIDTH EXCLAMATION MARK..HALFWIDTH HANGUL LETTER HIEUH
+FFBF-FFC1,UNASSIGNED,,<RESERVED>..<RESERVED>
+FFC2-FFC7,DISALLOWED,,HALFWIDTH HANGUL LETTER A..HALFWIDTH HANGUL LETTER E
+FFC8-FFC9,UNASSIGNED,,<RESERVED>..<RESERVED>
+FFCA-FFCF,DISALLOWED,,HALFWIDTH HANGUL LETTER YEO..HALFWIDTH HANGUL LETTER OE
+FFD0-FFD1,UNASSIGNED,,<RESERVED>..<RESERVED>
+FFD2-FFD7,DISALLOWED,,HALFWIDTH HANGUL LETTER YO..HALFWIDTH HANGUL LETTER YU
+FFD8-FFD9,UNASSIGNED,,<RESERVED>..<RESERVED>
+FFDA-FFDC,DISALLOWED,,HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL LETTER I
+FFDD-FFDF,UNASSIGNED,,<RESERVED>..<RESERVED>
+FFE0-FFE6,DISALLOWED,,FULLWIDTH CENT SIGN..FULLWIDTH WON SIGN
+FFE7,UNASSIGNED,,<RESERVED>
+FFE8-FFEE,DISALLOWED,,HALFWIDTH FORMS LIGHT VERTICAL..HALFWIDTH WHITE CIRCLE
+FFEF-FFF8,UNASSIGNED,,<RESERVED>..<RESERVED>
+FFF9-FFFF,DISALLOWED,,INTERLINEAR ANNOTATION ANCHOR..<NOT A CHARACTER>
+10000-1000B,PVALID,,LINEAR B SYLLABLE B008 A..LINEAR B SYLLABLE B046 JE
+1000C,UNASSIGNED,,<RESERVED>
+1000D-10026,PVALID,,LINEAR B SYLLABLE B036 JO..LINEAR B SYLLABLE B032 QO
+10027,UNASSIGNED,,<RESERVED>
+10028-1003A,PVALID,,LINEAR B SYLLABLE B060 RA..LINEAR B SYLLABLE B042 WO
+1003B,UNASSIGNED,,<RESERVED>
+1003C-1003D,PVALID,,LINEAR B SYLLABLE B017 ZA..LINEAR B SYLLABLE B074 ZE
+1003E,UNASSIGNED,,<RESERVED>
+1003F-1004D,PVALID,,LINEAR B SYLLABLE B020 ZO..LINEAR B SYLLABLE B091 TWO
+1004E-1004F,UNASSIGNED,,<RESERVED>..<RESERVED>
+10050-1005D,PVALID,,LINEAR B SYMBOL B018..LINEAR B SYMBOL B089
+1005E-1007F,UNASSIGNED,,<RESERVED>..<RESERVED>
+10080-100FA,PVALID,,LINEAR B IDEOGRAM B100 MAN..LINEAR B IDEOGRAM VESSEL B305
+100FB-100FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+10100-10102,DISALLOWED,,AEGEAN WORD SEPARATOR LINE..AEGEAN CHECK MARK
+10103-10106,UNASSIGNED,,<RESERVED>..<RESERVED>
+10107-10133,DISALLOWED,,AEGEAN NUMBER ONE..AEGEAN NUMBER NINETY THOUSAND
+10134-10136,UNASSIGNED,,<RESERVED>..<RESERVED>
+10137-1018E,DISALLOWED,,AEGEAN WEIGHT BASE UNIT..NOMISMA SIGN
+1018F,UNASSIGNED,,<RESERVED>
+10190-1019B,DISALLOWED,,ROMAN SEXTANS SIGN..ROMAN CENTURIAL SIGN
+1019C-1019F,UNASSIGNED,,<RESERVED>..<RESERVED>
+101A0,DISALLOWED,,GREEK SYMBOL TAU RHO
+101A1-101CF,UNASSIGNED,,<RESERVED>..<RESERVED>
+101D0-101FC,DISALLOWED,,PHAISTOS DISC SIGN PEDESTRIAN..PHAISTOS DISC SIGN WAVY BAND
+101FD,PVALID,,PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE
+101FE-1027F,UNASSIGNED,,<RESERVED>..<RESERVED>
+10280-1029C,PVALID,,LYCIAN LETTER A..LYCIAN LETTER X
+1029D-1029F,UNASSIGNED,,<RESERVED>..<RESERVED>
+102A0-102D0,PVALID,,CARIAN LETTER A..CARIAN LETTER UUU3
+102D1-102DF,UNASSIGNED,,<RESERVED>..<RESERVED>
+102E0,PVALID,,COPTIC EPACT THOUSANDS MARK
+102E1-102FB,DISALLOWED,,COPTIC EPACT DIGIT ONE..COPTIC EPACT NUMBER NINE HUNDRED
+102FC-102FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+10300-1031F,PVALID,,OLD ITALIC LETTER A..OLD ITALIC LETTER ESS
+10320-10323,DISALLOWED,,OLD ITALIC NUMERAL ONE..OLD ITALIC NUMERAL FIFTY
+10324-1032C,UNASSIGNED,,<RESERVED>..<RESERVED>
+1032D-10340,PVALID,,OLD ITALIC LETTER YE..GOTHIC LETTER PAIRTHRA
+10341,DISALLOWED,,GOTHIC LETTER NINETY
+10342-10349,PVALID,,GOTHIC LETTER RAIDA..GOTHIC LETTER OTHAL
+1034A,DISALLOWED,,GOTHIC LETTER NINE HUNDRED
+1034B-1034F,UNASSIGNED,,<RESERVED>..<RESERVED>
+10350-1037A,PVALID,,OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII
+1037B-1037F,UNASSIGNED,,<RESERVED>..<RESERVED>
+10380-1039D,PVALID,,UGARITIC LETTER ALPA..UGARITIC LETTER SSU
+1039E,UNASSIGNED,,<RESERVED>
+1039F,DISALLOWED,,UGARITIC WORD DIVIDER
+103A0-103C3,PVALID,,OLD PERSIAN SIGN A..OLD PERSIAN SIGN HA
+103C4-103C7,UNASSIGNED,,<RESERVED>..<RESERVED>
+103C8-103CF,PVALID,,OLD PERSIAN SIGN AURAMAZDAA..OLD PERSIAN SIGN BUUMISH
+103D0-103D5,DISALLOWED,,OLD PERSIAN WORD DIVIDER..OLD PERSIAN NUMBER HUNDRED
+103D6-103FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+10400-10427,DISALLOWED,,DESERET CAPITAL LETTER LONG I..DESERET CAPITAL LETTER EW
+10428-1049D,PVALID,,DESERET SMALL LETTER LONG I..OSMANYA LETTER OO
+1049E-1049F,UNASSIGNED,,<RESERVED>..<RESERVED>
+104A0-104A9,PVALID,,OSMANYA DIGIT ZERO..OSMANYA DIGIT NINE
+104AA-104AF,UNASSIGNED,,<RESERVED>..<RESERVED>
+104B0-104D3,DISALLOWED,,OSAGE CAPITAL LETTER A..OSAGE CAPITAL LETTER ZHA
+104D4-104D7,UNASSIGNED,,<RESERVED>..<RESERVED>
+104D8-104FB,PVALID,,OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA
+104FC-104FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+10500-10527,PVALID,,ELBASAN LETTER A..ELBASAN LETTER KHE
+10528-1052F,UNASSIGNED,,<RESERVED>..<RESERVED>
+10530-10563,PVALID,,CAUCASIAN ALBANIAN LETTER ALT..CAUCASIAN ALBANIAN LETTER KIW
+10564-1056E,UNASSIGNED,,<RESERVED>..<RESERVED>
+1056F,DISALLOWED,,CAUCASIAN ALBANIAN CITATION MARK
+10570-105FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+10600-10736,PVALID,,LINEAR A SIGN AB001..LINEAR A SIGN A664
+10737-1073F,UNASSIGNED,,<RESERVED>..<RESERVED>
+10740-10755,PVALID,,LINEAR A SIGN A701 A..LINEAR A SIGN A732 JE
+10756-1075F,UNASSIGNED,,<RESERVED>..<RESERVED>
+10760-10767,PVALID,,LINEAR A SIGN A800..LINEAR A SIGN A807
+10768-107FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+10800-10805,PVALID,,CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA
+10806-10807,UNASSIGNED,,<RESERVED>..<RESERVED>
+10808,PVALID,,CYPRIOT SYLLABLE JO
+10809,UNASSIGNED,,<RESERVED>
+1080A-10835,PVALID,,CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO
+10836,UNASSIGNED,,<RESERVED>
+10837-10838,PVALID,,CYPRIOT SYLLABLE XA..CYPRIOT SYLLABLE XE
+10839-1083B,UNASSIGNED,,<RESERVED>..<RESERVED>
+1083C,PVALID,,CYPRIOT SYLLABLE ZA
+1083D-1083E,UNASSIGNED,,<RESERVED>..<RESERVED>
+1083F-10855,PVALID,,CYPRIOT SYLLABLE ZO..IMPERIAL ARAMAIC LETTER TAW
+10856,UNASSIGNED,,<RESERVED>
+10857-1085F,DISALLOWED,,IMPERIAL ARAMAIC SECTION SIGN..IMPERIAL ARAMAIC NUMBER TEN THOUSAND
+10860-10876,PVALID,,PALMYRENE LETTER ALEPH..PALMYRENE LETTER TAW
+10877-1087F,DISALLOWED,,PALMYRENE LEFT-POINTING FLEURON..PALMYRENE NUMBER TWENTY
+10880-1089E,PVALID,,NABATAEAN LETTER FINAL ALEPH..NABATAEAN LETTER TAW
+1089F-108A6,UNASSIGNED,,<RESERVED>..<RESERVED>
+108A7-108AF,DISALLOWED,,NABATAEAN NUMBER ONE..NABATAEAN NUMBER ONE HUNDRED
+108B0-108DF,UNASSIGNED,,<RESERVED>..<RESERVED>
+108E0-108F2,PVALID,,HATRAN LETTER ALEPH..HATRAN LETTER QOPH
+108F3,UNASSIGNED,,<RESERVED>
+108F4-108F5,PVALID,,HATRAN LETTER SHIN..HATRAN LETTER TAW
+108F6-108FA,UNASSIGNED,,<RESERVED>..<RESERVED>
+108FB-108FF,DISALLOWED,,HATRAN NUMBER ONE..HATRAN NUMBER ONE HUNDRED
+10900-10915,PVALID,,PHOENICIAN LETTER ALF..PHOENICIAN LETTER TAU
+10916-1091B,DISALLOWED,,PHOENICIAN NUMBER ONE..PHOENICIAN NUMBER THREE
+1091C-1091E,UNASSIGNED,,<RESERVED>..<RESERVED>
+1091F,DISALLOWED,,PHOENICIAN WORD SEPARATOR
+10920-10939,PVALID,,LYDIAN LETTER A..LYDIAN LETTER C
+1093A-1093E,UNASSIGNED,,<RESERVED>..<RESERVED>
+1093F,DISALLOWED,,LYDIAN TRIANGULAR MARK
+10940-1097F,UNASSIGNED,,<RESERVED>..<RESERVED>
+10980-109B7,PVALID,,MEROITIC HIEROGLYPHIC LETTER A..MEROITIC CURSIVE LETTER DA
+109B8-109BB,UNASSIGNED,,<RESERVED>..<RESERVED>
+109BC-109BD,DISALLOWED,,MEROITIC CURSIVE FRACTION ELEVEN TWELFTHS..MEROITIC CURSIVE FRACTION ONE HALF
+109BE-109BF,PVALID,,MEROITIC CURSIVE LOGOGRAM RMT..MEROITIC CURSIVE LOGOGRAM IMN
+109C0-109CF,DISALLOWED,,MEROITIC CURSIVE NUMBER ONE..MEROITIC CURSIVE NUMBER SEVENTY
+109D0-109D1,UNASSIGNED,,<RESERVED>..<RESERVED>
+109D2-109FF,DISALLOWED,,MEROITIC CURSIVE NUMBER ONE HUNDRED..MEROITIC CURSIVE FRACTION TEN TWELFTHS
+10A00-10A03,PVALID,,KHAROSHTHI LETTER A..KHAROSHTHI VOWEL SIGN VOCALIC R
+10A04,UNASSIGNED,,<RESERVED>
+10A05-10A06,PVALID,,KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O
+10A07-10A0B,UNASSIGNED,,<RESERVED>..<RESERVED>
+10A0C-10A13,PVALID,,KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI LETTER GHA
+10A14,UNASSIGNED,,<RESERVED>
+10A15-10A17,PVALID,,KHAROSHTHI LETTER CA..KHAROSHTHI LETTER JA
+10A18,UNASSIGNED,,<RESERVED>
+10A19-10A35,PVALID,,KHAROSHTHI LETTER NYA..KHAROSHTHI LETTER VHA
+10A36-10A37,UNASSIGNED,,<RESERVED>..<RESERVED>
+10A38-10A3A,PVALID,,KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW
+10A3B-10A3E,UNASSIGNED,,<RESERVED>..<RESERVED>
+10A3F,PVALID,,KHAROSHTHI VIRAMA
+10A40-10A48,DISALLOWED,,KHAROSHTHI DIGIT ONE..KHAROSHTHI FRACTION ONE HALF
+10A49-10A4F,UNASSIGNED,,<RESERVED>..<RESERVED>
+10A50-10A58,DISALLOWED,,KHAROSHTHI PUNCTUATION DOT..KHAROSHTHI PUNCTUATION LINES
+10A59-10A5F,UNASSIGNED,,<RESERVED>..<RESERVED>
+10A60-10A7C,PVALID,,OLD SOUTH ARABIAN LETTER HE..OLD SOUTH ARABIAN LETTER THETH
+10A7D-10A7F,DISALLOWED,,OLD SOUTH ARABIAN NUMBER ONE..OLD SOUTH ARABIAN NUMERIC INDICATOR
+10A80-10A9C,PVALID,,OLD NORTH ARABIAN LETTER HEH..OLD NORTH ARABIAN LETTER ZAH
+10A9D-10A9F,DISALLOWED,,OLD NORTH ARABIAN NUMBER ONE..OLD NORTH ARABIAN NUMBER TWENTY
+10AA0-10ABF,UNASSIGNED,,<RESERVED>..<RESERVED>
+10AC0-10AC7,PVALID,,MANICHAEAN LETTER ALEPH..MANICHAEAN LETTER WAW
+10AC8,DISALLOWED,,MANICHAEAN SIGN UD
+10AC9-10AE6,PVALID,,MANICHAEAN LETTER ZAYIN..MANICHAEAN ABBREVIATION MARK BELOW
+10AE7-10AEA,UNASSIGNED,,<RESERVED>..<RESERVED>
+10AEB-10AF6,DISALLOWED,,MANICHAEAN NUMBER ONE..MANICHAEAN PUNCTUATION LINE FILLER
+10AF7-10AFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+10B00-10B35,PVALID,,AVESTAN LETTER A..AVESTAN LETTER HE
+10B36-10B38,UNASSIGNED,,<RESERVED>..<RESERVED>
+10B39-10B3F,DISALLOWED,,AVESTAN ABBREVIATION MARK..LARGE ONE RING OVER TWO RINGS PUNCTUATION
+10B40-10B55,PVALID,,INSCRIPTIONAL PARTHIAN LETTER ALEPH..INSCRIPTIONAL PARTHIAN LETTER TAW
+10B56-10B57,UNASSIGNED,,<RESERVED>..<RESERVED>
+10B58-10B5F,DISALLOWED,,INSCRIPTIONAL PARTHIAN NUMBER ONE..INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND
+10B60-10B72,PVALID,,INSCRIPTIONAL PAHLAVI LETTER ALEPH..INSCRIPTIONAL PAHLAVI LETTER TAW
+10B73-10B77,UNASSIGNED,,<RESERVED>..<RESERVED>
+10B78-10B7F,DISALLOWED,,INSCRIPTIONAL PAHLAVI NUMBER ONE..INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND
+10B80-10B91,PVALID,,PSALTER PAHLAVI LETTER ALEPH..PSALTER PAHLAVI LETTER TAW
+10B92-10B98,UNASSIGNED,,<RESERVED>..<RESERVED>
+10B99-10B9C,DISALLOWED,,PSALTER PAHLAVI SECTION MARK..PSALTER PAHLAVI FOUR DOTS WITH DOT
+10B9D-10BA8,UNASSIGNED,,<RESERVED>..<RESERVED>
+10BA9-10BAF,DISALLOWED,,PSALTER PAHLAVI NUMBER ONE..PSALTER PAHLAVI NUMBER ONE HUNDRED
+10BB0-10BFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+10C00-10C48,PVALID,,OLD TURKIC LETTER ORKHON A..OLD TURKIC LETTER ORKHON BASH
+10C49-10C7F,UNASSIGNED,,<RESERVED>..<RESERVED>
+10C80-10CB2,DISALLOWED,,OLD HUNGARIAN CAPITAL LETTER A..OLD HUNGARIAN CAPITAL LETTER US
+10CB3-10CBF,UNASSIGNED,,<RESERVED>..<RESERVED>
+10CC0-10CF2,PVALID,,OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US
+10CF3-10CF9,UNASSIGNED,,<RESERVED>..<RESERVED>
+10CFA-10CFF,DISALLOWED,,OLD HUNGARIAN NUMBER ONE..OLD HUNGARIAN NUMBER ONE THOUSAND
+10D00-10D27,PVALID,,HANIFI ROHINGYA LETTER A..HANIFI ROHINGYA SIGN TASSI
+10D28-10D2F,UNASSIGNED,,<RESERVED>..<RESERVED>
+10D30-10D39,PVALID,,HANIFI ROHINGYA DIGIT ZERO..HANIFI ROHINGYA DIGIT NINE
+10D3A-10E5F,UNASSIGNED,,<RESERVED>..<RESERVED>
+10E60-10E7E,DISALLOWED,,RUMI DIGIT ONE..RUMI FRACTION TWO THIRDS
+10E7F-10EFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+10F00-10F1C,PVALID,,OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL
+10F1D-10F26,DISALLOWED,,OLD SOGDIAN NUMBER ONE..OLD SOGDIAN FRACTION ONE HALF
+10F27,PVALID,,OLD SOGDIAN LIGATURE AYIN-DALETH
+10F28-10F2F,UNASSIGNED,,<RESERVED>..<RESERVED>
+10F30-10F50,PVALID,,SOGDIAN LETTER ALEPH..SOGDIAN COMBINING STROKE BELOW
+10F51-10F59,DISALLOWED,,SOGDIAN NUMBER ONE..SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT
+10F5A-10FFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+11000-11046,PVALID,,BRAHMI SIGN CANDRABINDU..BRAHMI VIRAMA
+11047-1104D,DISALLOWED,,BRAHMI DANDA..BRAHMI PUNCTUATION LOTUS
+1104E-11051,UNASSIGNED,,<RESERVED>..<RESERVED>
+11052-11065,DISALLOWED,,BRAHMI NUMBER ONE..BRAHMI NUMBER ONE THOUSAND
+11066-1106F,PVALID,,BRAHMI DIGIT ZERO..BRAHMI DIGIT NINE
+11070-1107E,UNASSIGNED,,<RESERVED>..<RESERVED>
+1107F-110BA,PVALID,,BRAHMI NUMBER JOINER..KAITHI SIGN NUKTA
+110BB-110C1,DISALLOWED,,KAITHI ABBREVIATION SIGN..KAITHI DOUBLE DANDA
+110C2-110CC,UNASSIGNED,,<RESERVED>..<RESERVED>
+110CD,DISALLOWED,,KAITHI NUMBER SIGN ABOVE
+110CE-110CF,UNASSIGNED,,<RESERVED>..<RESERVED>
+110D0-110E8,PVALID,,SORA SOMPENG LETTER SAH..SORA SOMPENG LETTER MAE
+110E9-110EF,UNASSIGNED,,<RESERVED>..<RESERVED>
+110F0-110F9,PVALID,,SORA SOMPENG DIGIT ZERO..SORA SOMPENG DIGIT NINE
+110FA-110FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+11100-11134,PVALID,,CHAKMA SIGN CANDRABINDU..CHAKMA MAAYYAA
+11135,UNASSIGNED,,<RESERVED>
+11136-1113F,PVALID,,CHAKMA DIGIT ZERO..CHAKMA DIGIT NINE
+11140-11143,DISALLOWED,,CHAKMA SECTION MARK..CHAKMA QUESTION MARK
+11144-11146,PVALID,,CHAKMA LETTER LHAA..CHAKMA VOWEL SIGN EI
+11147-1114F,UNASSIGNED,,<RESERVED>..<RESERVED>
+11150-11173,PVALID,,MAHAJANI LETTER A..MAHAJANI SIGN NUKTA
+11174-11175,DISALLOWED,,MAHAJANI ABBREVIATION SIGN..MAHAJANI SECTION MARK
+11176,PVALID,,MAHAJANI LIGATURE SHRI
+11177-1117F,UNASSIGNED,,<RESERVED>..<RESERVED>
+11180-111C4,PVALID,,SHARADA SIGN CANDRABINDU..SHARADA OM
+111C5-111C8,DISALLOWED,,SHARADA DANDA..SHARADA SEPARATOR
+111C9-111CC,PVALID,,SHARADA SANDHI MARK..SHARADA EXTRA SHORT VOWEL MARK
+111CD,DISALLOWED,,SHARADA SUTRA MARK
+111CE-111CF,UNASSIGNED,,<RESERVED>..<RESERVED>
+111D0-111DA,PVALID,,SHARADA DIGIT ZERO..SHARADA EKAM
+111DB,DISALLOWED,,SHARADA SIGN SIDDHAM
+111DC,PVALID,,SHARADA HEADSTROKE
+111DD-111DF,DISALLOWED,,SHARADA CONTINUATION SIGN..SHARADA SECTION MARK-2
+111E0,UNASSIGNED,,<RESERVED>
+111E1-111F4,DISALLOWED,,SINHALA ARCHAIC DIGIT ONE..SINHALA ARCHAIC NUMBER ONE THOUSAND
+111F5-111FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+11200-11211,PVALID,,KHOJKI LETTER A..KHOJKI LETTER JJA
+11212,UNASSIGNED,,<RESERVED>
+11213-11237,PVALID,,KHOJKI LETTER NYA..KHOJKI SIGN SHADDA
+11238-1123D,DISALLOWED,,KHOJKI DANDA..KHOJKI ABBREVIATION SIGN
+1123E,PVALID,,KHOJKI SIGN SUKUN
+1123F-1127F,UNASSIGNED,,<RESERVED>..<RESERVED>
+11280-11286,PVALID,,MULTANI LETTER A..MULTANI LETTER GA
+11287,UNASSIGNED,,<RESERVED>
+11288,PVALID,,MULTANI LETTER GHA
+11289,UNASSIGNED,,<RESERVED>
+1128A-1128D,PVALID,,MULTANI LETTER CA..MULTANI LETTER JJA
+1128E,UNASSIGNED,,<RESERVED>
+1128F-1129D,PVALID,,MULTANI LETTER NYA..MULTANI LETTER BA
+1129E,UNASSIGNED,,<RESERVED>
+1129F-112A8,PVALID,,MULTANI LETTER BHA..MULTANI LETTER RHA
+112A9,DISALLOWED,,MULTANI SECTION MARK
+112AA-112AF,UNASSIGNED,,<RESERVED>..<RESERVED>
+112B0-112EA,PVALID,,KHUDAWADI LETTER A..KHUDAWADI SIGN VIRAMA
+112EB-112EF,UNASSIGNED,,<RESERVED>..<RESERVED>
+112F0-112F9,PVALID,,KHUDAWADI DIGIT ZERO..KHUDAWADI DIGIT NINE
+112FA-112FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+11300-11303,PVALID,,GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN VISARGA
+11304,UNASSIGNED,,<RESERVED>
+11305-1130C,PVALID,,GRANTHA LETTER A..GRANTHA LETTER VOCALIC L
+1130D-1130E,UNASSIGNED,,<RESERVED>..<RESERVED>
+1130F-11310,PVALID,,GRANTHA LETTER EE..GRANTHA LETTER AI
+11311-11312,UNASSIGNED,,<RESERVED>..<RESERVED>
+11313-11328,PVALID,,GRANTHA LETTER OO..GRANTHA LETTER NA
+11329,UNASSIGNED,,<RESERVED>
+1132A-11330,PVALID,,GRANTHA LETTER PA..GRANTHA LETTER RA
+11331,UNASSIGNED,,<RESERVED>
+11332-11333,PVALID,,GRANTHA LETTER LA..GRANTHA LETTER LLA
+11334,UNASSIGNED,,<RESERVED>
+11335-11339,PVALID,,GRANTHA LETTER VA..GRANTHA LETTER HA
+1133A,UNASSIGNED,,<RESERVED>
+1133B-11344,PVALID,,COMBINING BINDU BELOW..GRANTHA VOWEL SIGN VOCALIC RR
+11345-11346,UNASSIGNED,,<RESERVED>..<RESERVED>
+11347-11348,PVALID,,GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI
+11349-1134A,UNASSIGNED,,<RESERVED>..<RESERVED>
+1134B-1134D,PVALID,,GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA
+1134E-1134F,UNASSIGNED,,<RESERVED>..<RESERVED>
+11350,PVALID,,GRANTHA OM
+11351-11356,UNASSIGNED,,<RESERVED>..<RESERVED>
+11357,PVALID,,GRANTHA AU LENGTH MARK
+11358-1135C,UNASSIGNED,,<RESERVED>..<RESERVED>
+1135D-11363,PVALID,,GRANTHA SIGN PLUTA..GRANTHA VOWEL SIGN VOCALIC LL
+11364-11365,UNASSIGNED,,<RESERVED>..<RESERVED>
+11366-1136C,PVALID,,COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX
+1136D-1136F,UNASSIGNED,,<RESERVED>..<RESERVED>
+11370-11374,PVALID,,COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA
+11375-113FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+11400-1144A,PVALID,,NEWA LETTER A..NEWA SIDDHI
+1144B-1144F,DISALLOWED,,NEWA DANDA..NEWA ABBREVIATION SIGN
+11450-11459,PVALID,,NEWA DIGIT ZERO..NEWA DIGIT NINE
+1145A,UNASSIGNED,,<RESERVED>
+1145B,DISALLOWED,,NEWA PLACEHOLDER MARK
+1145C,UNASSIGNED,,<RESERVED>
+1145D,DISALLOWED,,NEWA INSERTION SIGN
+1145E,PVALID,,NEWA SANDHI MARK
+1145F-1147F,UNASSIGNED,,<RESERVED>..<RESERVED>
+11480-114C5,PVALID,,TIRHUTA ANJI..TIRHUTA GVANG
+114C6,DISALLOWED,,TIRHUTA ABBREVIATION SIGN
+114C7,PVALID,,TIRHUTA OM
+114C8-114CF,UNASSIGNED,,<RESERVED>..<RESERVED>
+114D0-114D9,PVALID,,TIRHUTA DIGIT ZERO..TIRHUTA DIGIT NINE
+114DA-1157F,UNASSIGNED,,<RESERVED>..<RESERVED>
+11580-115B5,PVALID,,SIDDHAM LETTER A..SIDDHAM VOWEL SIGN VOCALIC RR
+115B6-115B7,UNASSIGNED,,<RESERVED>..<RESERVED>
+115B8-115C0,PVALID,,SIDDHAM VOWEL SIGN E..SIDDHAM SIGN NUKTA
+115C1-115D7,DISALLOWED,,SIDDHAM SIGN SIDDHAM..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES
+115D8-115DD,PVALID,,SIDDHAM LETTER THREE-CIRCLE ALTERNATE I..SIDDHAM VOWEL SIGN ALTERNATE UU
+115DE-115FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+11600-11640,PVALID,,MODI LETTER A..MODI SIGN ARDHACANDRA
+11641-11643,DISALLOWED,,MODI DANDA..MODI ABBREVIATION SIGN
+11644,PVALID,,MODI SIGN HUVA
+11645-1164F,UNASSIGNED,,<RESERVED>..<RESERVED>
+11650-11659,PVALID,,MODI DIGIT ZERO..MODI DIGIT NINE
+1165A-1165F,UNASSIGNED,,<RESERVED>..<RESERVED>
+11660-1166C,DISALLOWED,,MONGOLIAN BIRGA WITH ORNAMENT..MONGOLIAN TURNED SWIRL BIRGA WITH DOUBLE ORNAMENT
+1166D-1167F,UNASSIGNED,,<RESERVED>..<RESERVED>
+11680-116B7,PVALID,,TAKRI LETTER A..TAKRI SIGN NUKTA
+116B8-116BF,UNASSIGNED,,<RESERVED>..<RESERVED>
+116C0-116C9,PVALID,,TAKRI DIGIT ZERO..TAKRI DIGIT NINE
+116CA-116FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+11700-1171A,PVALID,,AHOM LETTER KA..AHOM LETTER ALTERNATE BA
+1171B-1171C,UNASSIGNED,,<RESERVED>..<RESERVED>
+1171D-1172B,PVALID,,AHOM CONSONANT SIGN MEDIAL LA..AHOM SIGN KILLER
+1172C-1172F,UNASSIGNED,,<RESERVED>..<RESERVED>
+11730-11739,PVALID,,AHOM DIGIT ZERO..AHOM DIGIT NINE
+1173A-1173F,DISALLOWED,,AHOM NUMBER TEN..AHOM SYMBOL VI
+11740-117FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+11800-1183A,PVALID,,DOGRA LETTER A..DOGRA SIGN NUKTA
+1183B,DISALLOWED,,DOGRA ABBREVIATION SIGN
+1183C-1189F,UNASSIGNED,,<RESERVED>..<RESERVED>
+118A0-118BF,DISALLOWED,,WARANG CITI CAPITAL LETTER NGAA..WARANG CITI CAPITAL LETTER VIYO
+118C0-118E9,PVALID,,WARANG CITI SMALL LETTER NGAA..WARANG CITI DIGIT NINE
+118EA-118F2,DISALLOWED,,WARANG CITI NUMBER TEN..WARANG CITI NUMBER NINETY
+118F3-118FE,UNASSIGNED,,<RESERVED>..<RESERVED>
+118FF,PVALID,,WARANG CITI OM
+11900-119FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+11A00-11A3E,PVALID,,ZANABAZAR SQUARE LETTER A..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA
+11A3F-11A46,DISALLOWED,,ZANABAZAR SQUARE INITIAL HEAD MARK..ZANABAZAR SQUARE CLOSING DOUBLE-LINED HEAD MARK
+11A47,PVALID,,ZANABAZAR SQUARE SUBJOINER
+11A48-11A4F,UNASSIGNED,,<RESERVED>..<RESERVED>
+11A50-11A83,PVALID,,SOYOMBO LETTER A..SOYOMBO LETTER KSSA
+11A84-11A85,UNASSIGNED,,<RESERVED>..<RESERVED>
+11A86-11A99,PVALID,,SOYOMBO CLUSTER-INITIAL LETTER RA..SOYOMBO SUBJOINER
+11A9A-11A9C,DISALLOWED,,SOYOMBO MARK TSHEG..SOYOMBO MARK DOUBLE SHAD
+11A9D,PVALID,,SOYOMBO MARK PLUTA
+11A9E-11AA2,DISALLOWED,,SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME..SOYOMBO TERMINAL MARK-2
+11AA3-11ABF,UNASSIGNED,,<RESERVED>..<RESERVED>
+11AC0-11AF8,PVALID,,PAU CIN HAU LETTER PA..PAU CIN HAU GLOTTAL STOP FINAL
+11AF9-11BFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+11C00-11C08,PVALID,,BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L
+11C09,UNASSIGNED,,<RESERVED>
+11C0A-11C36,PVALID,,BHAIKSUKI LETTER E..BHAIKSUKI VOWEL SIGN VOCALIC L
+11C37,UNASSIGNED,,<RESERVED>
+11C38-11C40,PVALID,,BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN AVAGRAHA
+11C41-11C45,DISALLOWED,,BHAIKSUKI DANDA..BHAIKSUKI GAP FILLER-2
+11C46-11C4F,UNASSIGNED,,<RESERVED>..<RESERVED>
+11C50-11C59,PVALID,,BHAIKSUKI DIGIT ZERO..BHAIKSUKI DIGIT NINE
+11C5A-11C6C,DISALLOWED,,BHAIKSUKI NUMBER ONE..BHAIKSUKI HUNDREDS UNIT MARK
+11C6D-11C6F,UNASSIGNED,,<RESERVED>..<RESERVED>
+11C70-11C71,DISALLOWED,,MARCHEN HEAD MARK..MARCHEN MARK SHAD
+11C72-11C8F,PVALID,,MARCHEN LETTER KA..MARCHEN LETTER A
+11C90-11C91,UNASSIGNED,,<RESERVED>..<RESERVED>
+11C92-11CA7,PVALID,,MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA
+11CA8,UNASSIGNED,,<RESERVED>
+11CA9-11CB6,PVALID,,MARCHEN SUBJOINED LETTER YA..MARCHEN SIGN CANDRABINDU
+11CB7-11CFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+11D00-11D06,PVALID,,MASARAM GONDI LETTER A..MASARAM GONDI LETTER E
+11D07,UNASSIGNED,,<RESERVED>
+11D08-11D09,PVALID,,MASARAM GONDI LETTER AI..MASARAM GONDI LETTER O
+11D0A,UNASSIGNED,,<RESERVED>
+11D0B-11D36,PVALID,,MASARAM GONDI LETTER AU..MASARAM GONDI VOWEL SIGN VOCALIC R
+11D37-11D39,UNASSIGNED,,<RESERVED>..<RESERVED>
+11D3A,PVALID,,MASARAM GONDI VOWEL SIGN E
+11D3B,UNASSIGNED,,<RESERVED>
+11D3C-11D3D,PVALID,,MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O
+11D3E,UNASSIGNED,,<RESERVED>
+11D3F-11D47,PVALID,,MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI RA-KARA
+11D48-11D4F,UNASSIGNED,,<RESERVED>..<RESERVED>
+11D50-11D59,PVALID,,MASARAM GONDI DIGIT ZERO..MASARAM GONDI DIGIT NINE
+11D5A-11D5F,UNASSIGNED,,<RESERVED>..<RESERVED>
+11D60-11D65,PVALID,,GUNJALA GONDI LETTER A..GUNJALA GONDI LETTER UU
+11D66,UNASSIGNED,,<RESERVED>
+11D67-11D68,PVALID,,GUNJALA GONDI LETTER EE..GUNJALA GONDI LETTER AI
+11D69,UNASSIGNED,,<RESERVED>
+11D6A-11D8E,PVALID,,GUNJALA GONDI LETTER OO..GUNJALA GONDI VOWEL SIGN UU
+11D8F,UNASSIGNED,,<RESERVED>
+11D90-11D91,PVALID,,GUNJALA GONDI VOWEL SIGN EE..GUNJALA GONDI VOWEL SIGN AI
+11D92,UNASSIGNED,,<RESERVED>
+11D93-11D98,PVALID,,GUNJALA GONDI VOWEL SIGN OO..GUNJALA GONDI OM
+11D99-11D9F,UNASSIGNED,,<RESERVED>..<RESERVED>
+11DA0-11DA9,PVALID,,GUNJALA GONDI DIGIT ZERO..GUNJALA GONDI DIGIT NINE
+11DAA-11EDF,UNASSIGNED,,<RESERVED>..<RESERVED>
+11EE0-11EF6,PVALID,,MAKASAR LETTER KA..MAKASAR VOWEL SIGN O
+11EF7-11EF8,DISALLOWED,,MAKASAR PASSIMBANG..MAKASAR END OF SECTION
+11EF9-11FFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+12000-12399,PVALID,,CUNEIFORM SIGN A..CUNEIFORM SIGN U U
+1239A-123FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+12400-1246E,DISALLOWED,,CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM
+1246F,UNASSIGNED,,<RESERVED>
+12470-12474,DISALLOWED,,CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER..CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON
+12475-1247F,UNASSIGNED,,<RESERVED>..<RESERVED>
+12480-12543,PVALID,,CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU
+12544-12FFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+13000-1342E,PVALID,,EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH AA032
+1342F-143FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+14400-14646,PVALID,,ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530
+14647-167FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+16800-16A38,PVALID,,BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ
+16A39-16A3F,UNASSIGNED,,<RESERVED>..<RESERVED>
+16A40-16A5E,PVALID,,MRO LETTER TA..MRO LETTER TEK
+16A5F,UNASSIGNED,,<RESERVED>
+16A60-16A69,PVALID,,MRO DIGIT ZERO..MRO DIGIT NINE
+16A6A-16A6D,UNASSIGNED,,<RESERVED>..<RESERVED>
+16A6E-16A6F,DISALLOWED,,MRO DANDA..MRO DOUBLE DANDA
+16A70-16ACF,UNASSIGNED,,<RESERVED>..<RESERVED>
+16AD0-16AED,PVALID,,BASSA VAH LETTER ENNI..BASSA VAH LETTER I
+16AEE-16AEF,UNASSIGNED,,<RESERVED>..<RESERVED>
+16AF0-16AF4,PVALID,,BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE
+16AF5,DISALLOWED,,BASSA VAH FULL STOP
+16AF6-16AFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+16B00-16B36,PVALID,,PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG MARK CIM TAUM
+16B37-16B3F,DISALLOWED,,PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN XYEEM FAIB
+16B40-16B43,PVALID,,PAHAWH HMONG SIGN VOS SEEV..PAHAWH HMONG SIGN IB YAM
+16B44-16B45,DISALLOWED,,PAHAWH HMONG SIGN XAUS..PAHAWH HMONG SIGN CIM TSOV ROG
+16B46-16B4F,UNASSIGNED,,<RESERVED>..<RESERVED>
+16B50-16B59,PVALID,,PAHAWH HMONG DIGIT ZERO..PAHAWH HMONG DIGIT NINE
+16B5A,UNASSIGNED,,<RESERVED>
+16B5B-16B61,DISALLOWED,,PAHAWH HMONG NUMBER TENS..PAHAWH HMONG NUMBER TRILLIONS
+16B62,UNASSIGNED,,<RESERVED>
+16B63-16B77,PVALID,,PAHAWH HMONG SIGN VOS LUB..PAHAWH HMONG SIGN CIM NRES TOS
+16B78-16B7C,UNASSIGNED,,<RESERVED>..<RESERVED>
+16B7D-16B8F,PVALID,,PAHAWH HMONG CLAN SIGN TSHEEJ..PAHAWH HMONG CLAN SIGN VWJ
+16B90-16E3F,UNASSIGNED,,<RESERVED>..<RESERVED>
+16E40-16E5F,DISALLOWED,,MEDEFAIDRIN CAPITAL LETTER M..MEDEFAIDRIN CAPITAL LETTER Y
+16E60-16E7F,PVALID,,MEDEFAIDRIN SMALL LETTER M..MEDEFAIDRIN SMALL LETTER Y
+16E80-16E9A,DISALLOWED,,MEDEFAIDRIN DIGIT ZERO..MEDEFAIDRIN EXCLAMATION OH
+16E9B-16EFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+16F00-16F44,PVALID,,MIAO LETTER PA..MIAO LETTER HHA
+16F45-16F4F,UNASSIGNED,,<RESERVED>..<RESERVED>
+16F50-16F7E,PVALID,,MIAO LETTER NASALIZATION..MIAO VOWEL SIGN NG
+16F7F-16F8E,UNASSIGNED,,<RESERVED>..<RESERVED>
+16F8F-16F9F,PVALID,,MIAO TONE RIGHT..MIAO LETTER REFORMED TONE-8
+16FA0-16FDF,UNASSIGNED,,<RESERVED>..<RESERVED>
+16FE0-16FE1,PVALID,,TANGUT ITERATION MARK..NUSHU ITERATION MARK
+16FE2-16FFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+17000-187F1,PVALID,,"<TANGUT IDEOGRAPH, FIRST>..<TANGUT IDEOGRAPH, LAST>"
+187F2-187FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+18800-18AF2,PVALID,,TANGUT COMPONENT-001..TANGUT COMPONENT-755
+18AF3-1AFFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1B000-1B11E,PVALID,,KATAKANA LETTER ARCHAIC E..HENTAIGANA LETTER N-MU-MO-2
+1B11F-1B16F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1B170-1B2FB,PVALID,,NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB
+1B2FC-1BBFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1BC00-1BC6A,PVALID,,DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M
+1BC6B-1BC6F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1BC70-1BC7C,PVALID,,DUPLOYAN AFFIX LEFT HORIZONTAL SECANT..DUPLOYAN AFFIX ATTACHED TANGENT HOOK
+1BC7D-1BC7F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1BC80-1BC88,PVALID,,DUPLOYAN AFFIX HIGH ACUTE..DUPLOYAN AFFIX HIGH VERTICAL
+1BC89-1BC8F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1BC90-1BC99,PVALID,,DUPLOYAN AFFIX LOW ACUTE..DUPLOYAN AFFIX LOW ARROW
+1BC9A-1BC9B,UNASSIGNED,,<RESERVED>..<RESERVED>
+1BC9C,DISALLOWED,,DUPLOYAN SIGN O WITH CROSS
+1BC9D-1BC9E,PVALID,,DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK
+1BC9F-1BCA3,DISALLOWED,,DUPLOYAN PUNCTUATION CHINOOK FULL STOP..SHORTHAND FORMAT UP STEP
+1BCA4-1CFFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1D000-1D0F5,DISALLOWED,,BYZANTINE MUSICAL SYMBOL PSILI..BYZANTINE MUSICAL SYMBOL GORGON NEO KATO
+1D0F6-1D0FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1D100-1D126,DISALLOWED,,MUSICAL SYMBOL SINGLE BARLINE..MUSICAL SYMBOL DRUM CLEF-2
+1D127-1D128,UNASSIGNED,,<RESERVED>..<RESERVED>
+1D129-1D1E8,DISALLOWED,,MUSICAL SYMBOL MULTIPLE MEASURE REST..MUSICAL SYMBOL KIEVAN FLAT SIGN
+1D1E9-1D1FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1D200-1D245,DISALLOWED,,GREEK VOCAL NOTATION SYMBOL-1..GREEK MUSICAL LEIMMA
+1D246-1D2DF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1D2E0-1D2F3,DISALLOWED,,MAYAN NUMERAL ZERO..MAYAN NUMERAL NINETEEN
+1D2F4-1D2FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1D300-1D356,DISALLOWED,,MONOGRAM FOR EARTH..TETRAGRAM FOR FOSTERING
+1D357-1D35F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1D360-1D378,DISALLOWED,,COUNTING ROD UNIT DIGIT ONE..TALLY MARK FIVE
+1D379-1D3FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1D400-1D454,DISALLOWED,,MATHEMATICAL BOLD CAPITAL A..MATHEMATICAL ITALIC SMALL G
+1D455,UNASSIGNED,,<RESERVED>
+1D456-1D49C,DISALLOWED,,MATHEMATICAL ITALIC SMALL I..MATHEMATICAL SCRIPT CAPITAL A
+1D49D,UNASSIGNED,,<RESERVED>
+1D49E-1D49F,DISALLOWED,,MATHEMATICAL SCRIPT CAPITAL C..MATHEMATICAL SCRIPT CAPITAL D
+1D4A0-1D4A1,UNASSIGNED,,<RESERVED>..<RESERVED>
+1D4A2,DISALLOWED,,MATHEMATICAL SCRIPT CAPITAL G
+1D4A3-1D4A4,UNASSIGNED,,<RESERVED>..<RESERVED>
+1D4A5-1D4A6,DISALLOWED,,MATHEMATICAL SCRIPT CAPITAL J..MATHEMATICAL SCRIPT CAPITAL K
+1D4A7-1D4A8,UNASSIGNED,,<RESERVED>..<RESERVED>
+1D4A9-1D4AC,DISALLOWED,,MATHEMATICAL SCRIPT CAPITAL N..MATHEMATICAL SCRIPT CAPITAL Q
+1D4AD,UNASSIGNED,,<RESERVED>
+1D4AE-1D4B9,DISALLOWED,,MATHEMATICAL SCRIPT CAPITAL S..MATHEMATICAL SCRIPT SMALL D
+1D4BA,UNASSIGNED,,<RESERVED>
+1D4BB,DISALLOWED,,MATHEMATICAL SCRIPT SMALL F
+1D4BC,UNASSIGNED,,<RESERVED>
+1D4BD-1D4C3,DISALLOWED,,MATHEMATICAL SCRIPT SMALL H..MATHEMATICAL SCRIPT SMALL N
+1D4C4,UNASSIGNED,,<RESERVED>
+1D4C5-1D505,DISALLOWED,,MATHEMATICAL SCRIPT SMALL P..MATHEMATICAL FRAKTUR CAPITAL B
+1D506,UNASSIGNED,,<RESERVED>
+1D507-1D50A,DISALLOWED,,MATHEMATICAL FRAKTUR CAPITAL D..MATHEMATICAL FRAKTUR CAPITAL G
+1D50B-1D50C,UNASSIGNED,,<RESERVED>..<RESERVED>
+1D50D-1D514,DISALLOWED,,MATHEMATICAL FRAKTUR CAPITAL J..MATHEMATICAL FRAKTUR CAPITAL Q
+1D515,UNASSIGNED,,<RESERVED>
+1D516-1D51C,DISALLOWED,,MATHEMATICAL FRAKTUR CAPITAL S..MATHEMATICAL FRAKTUR CAPITAL Y
+1D51D,UNASSIGNED,,<RESERVED>
+1D51E-1D539,DISALLOWED,,MATHEMATICAL FRAKTUR SMALL A..MATHEMATICAL DOUBLE-STRUCK CAPITAL B
+1D53A,UNASSIGNED,,<RESERVED>
+1D53B-1D53E,DISALLOWED,,MATHEMATICAL DOUBLE-STRUCK CAPITAL D..MATHEMATICAL DOUBLE-STRUCK CAPITAL G
+1D53F,UNASSIGNED,,<RESERVED>
+1D540-1D544,DISALLOWED,,MATHEMATICAL DOUBLE-STRUCK CAPITAL I..MATHEMATICAL DOUBLE-STRUCK CAPITAL M
+1D545,UNASSIGNED,,<RESERVED>
+1D546,DISALLOWED,,MATHEMATICAL DOUBLE-STRUCK CAPITAL O
+1D547-1D549,UNASSIGNED,,<RESERVED>..<RESERVED>
+1D54A-1D550,DISALLOWED,,MATHEMATICAL DOUBLE-STRUCK CAPITAL S..MATHEMATICAL DOUBLE-STRUCK CAPITAL Y
+1D551,UNASSIGNED,,<RESERVED>
+1D552-1D6A5,DISALLOWED,,MATHEMATICAL DOUBLE-STRUCK SMALL A..MATHEMATICAL ITALIC SMALL DOTLESS J
+1D6A6-1D6A7,UNASSIGNED,,<RESERVED>..<RESERVED>
+1D6A8-1D7CB,DISALLOWED,,MATHEMATICAL BOLD CAPITAL ALPHA..MATHEMATICAL BOLD SMALL DIGAMMA
+1D7CC-1D7CD,UNASSIGNED,,<RESERVED>..<RESERVED>
+1D7CE-1D9FF,DISALLOWED,,MATHEMATICAL BOLD DIGIT ZERO..SIGNWRITING HEAD
+1DA00-1DA36,PVALID,,SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN
+1DA37-1DA3A,DISALLOWED,,SIGNWRITING AIR BLOW SMALL ROTATIONS..SIGNWRITING BREATH EXHALE
+1DA3B-1DA6C,PVALID,,SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT
+1DA6D-1DA74,DISALLOWED,,SIGNWRITING SHOULDER HIP SPINE..SIGNWRITING TORSO-FLOORPLANE TWISTING
+1DA75,PVALID,,SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS
+1DA76-1DA83,DISALLOWED,,SIGNWRITING LIMB COMBINATION..SIGNWRITING LOCATION DEPTH
+1DA84,PVALID,,SIGNWRITING LOCATION HEAD NECK
+1DA85-1DA8B,DISALLOWED,,SIGNWRITING LOCATION TORSO..SIGNWRITING PARENTHESIS
+1DA8C-1DA9A,UNASSIGNED,,<RESERVED>..<RESERVED>
+1DA9B-1DA9F,PVALID,,SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6
+1DAA0,UNASSIGNED,,<RESERVED>
+1DAA1-1DAAF,PVALID,,SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16
+1DAB0-1DFFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1E000-1E006,PVALID,,COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE
+1E007,UNASSIGNED,,<RESERVED>
+1E008-1E018,PVALID,,COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU
+1E019-1E01A,UNASSIGNED,,<RESERVED>..<RESERVED>
+1E01B-1E021,PVALID,,COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI
+1E022,UNASSIGNED,,<RESERVED>
+1E023-1E024,PVALID,,COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS
+1E025,UNASSIGNED,,<RESERVED>
+1E026-1E02A,PVALID,,COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA
+1E02B-1E7FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1E800-1E8C4,PVALID,,MENDE KIKAKUI SYLLABLE M001 KI..MENDE KIKAKUI SYLLABLE M060 NYON
+1E8C5-1E8C6,UNASSIGNED,,<RESERVED>..<RESERVED>
+1E8C7-1E8CF,DISALLOWED,,MENDE KIKAKUI DIGIT ONE..MENDE KIKAKUI DIGIT NINE
+1E8D0-1E8D6,PVALID,,MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS
+1E8D7-1E8FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1E900-1E921,DISALLOWED,,ADLAM CAPITAL LETTER ALIF..ADLAM CAPITAL LETTER SHA
+1E922-1E94A,PVALID,,ADLAM SMALL LETTER ALIF..ADLAM NUKTA
+1E94B-1E94F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1E950-1E959,PVALID,,ADLAM DIGIT ZERO..ADLAM DIGIT NINE
+1E95A-1E95D,UNASSIGNED,,<RESERVED>..<RESERVED>
+1E95E-1E95F,DISALLOWED,,ADLAM INITIAL EXCLAMATION MARK..ADLAM INITIAL QUESTION MARK
+1E960-1EC70,UNASSIGNED,,<RESERVED>..<RESERVED>
+1EC71-1ECB4,DISALLOWED,,INDIC SIYAQ NUMBER ONE..INDIC SIYAQ ALTERNATE LAKH MARK
+1ECB5-1EDFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1EE00-1EE03,DISALLOWED,,ARABIC MATHEMATICAL ALEF..ARABIC MATHEMATICAL DAL
+1EE04,UNASSIGNED,,<RESERVED>
+1EE05-1EE1F,DISALLOWED,,ARABIC MATHEMATICAL WAW..ARABIC MATHEMATICAL DOTLESS QAF
+1EE20,UNASSIGNED,,<RESERVED>
+1EE21-1EE22,DISALLOWED,,ARABIC MATHEMATICAL INITIAL BEH..ARABIC MATHEMATICAL INITIAL JEEM
+1EE23,UNASSIGNED,,<RESERVED>
+1EE24,DISALLOWED,,ARABIC MATHEMATICAL INITIAL HEH
+1EE25-1EE26,UNASSIGNED,,<RESERVED>..<RESERVED>
+1EE27,DISALLOWED,,ARABIC MATHEMATICAL INITIAL HAH
+1EE28,UNASSIGNED,,<RESERVED>
+1EE29-1EE32,DISALLOWED,,ARABIC MATHEMATICAL INITIAL YEH..ARABIC MATHEMATICAL INITIAL QAF
+1EE33,UNASSIGNED,,<RESERVED>
+1EE34-1EE37,DISALLOWED,,ARABIC MATHEMATICAL INITIAL SHEEN..ARABIC MATHEMATICAL INITIAL KHAH
+1EE38,UNASSIGNED,,<RESERVED>
+1EE39,DISALLOWED,,ARABIC MATHEMATICAL INITIAL DAD
+1EE3A,UNASSIGNED,,<RESERVED>
+1EE3B,DISALLOWED,,ARABIC MATHEMATICAL INITIAL GHAIN
+1EE3C-1EE41,UNASSIGNED,,<RESERVED>..<RESERVED>
+1EE42,DISALLOWED,,ARABIC MATHEMATICAL TAILED JEEM
+1EE43-1EE46,UNASSIGNED,,<RESERVED>..<RESERVED>
+1EE47,DISALLOWED,,ARABIC MATHEMATICAL TAILED HAH
+1EE48,UNASSIGNED,,<RESERVED>
+1EE49,DISALLOWED,,ARABIC MATHEMATICAL TAILED YEH
+1EE4A,UNASSIGNED,,<RESERVED>
+1EE4B,DISALLOWED,,ARABIC MATHEMATICAL TAILED LAM
+1EE4C,UNASSIGNED,,<RESERVED>
+1EE4D-1EE4F,DISALLOWED,,ARABIC MATHEMATICAL TAILED NOON..ARABIC MATHEMATICAL TAILED AIN
+1EE50,UNASSIGNED,,<RESERVED>
+1EE51-1EE52,DISALLOWED,,ARABIC MATHEMATICAL TAILED SAD..ARABIC MATHEMATICAL TAILED QAF
+1EE53,UNASSIGNED,,<RESERVED>
+1EE54,DISALLOWED,,ARABIC MATHEMATICAL TAILED SHEEN
+1EE55-1EE56,UNASSIGNED,,<RESERVED>..<RESERVED>
+1EE57,DISALLOWED,,ARABIC MATHEMATICAL TAILED KHAH
+1EE58,UNASSIGNED,,<RESERVED>
+1EE59,DISALLOWED,,ARABIC MATHEMATICAL TAILED DAD
+1EE5A,UNASSIGNED,,<RESERVED>
+1EE5B,DISALLOWED,,ARABIC MATHEMATICAL TAILED GHAIN
+1EE5C,UNASSIGNED,,<RESERVED>
+1EE5D,DISALLOWED,,ARABIC MATHEMATICAL TAILED DOTLESS NOON
+1EE5E,UNASSIGNED,,<RESERVED>
+1EE5F,DISALLOWED,,ARABIC MATHEMATICAL TAILED DOTLESS QAF
+1EE60,UNASSIGNED,,<RESERVED>
+1EE61-1EE62,DISALLOWED,,ARABIC MATHEMATICAL STRETCHED BEH..ARABIC MATHEMATICAL STRETCHED JEEM
+1EE63,UNASSIGNED,,<RESERVED>
+1EE64,DISALLOWED,,ARABIC MATHEMATICAL STRETCHED HEH
+1EE65-1EE66,UNASSIGNED,,<RESERVED>..<RESERVED>
+1EE67-1EE6A,DISALLOWED,,ARABIC MATHEMATICAL STRETCHED HAH..ARABIC MATHEMATICAL STRETCHED KAF
+1EE6B,UNASSIGNED,,<RESERVED>
+1EE6C-1EE72,DISALLOWED,,ARABIC MATHEMATICAL STRETCHED MEEM..ARABIC MATHEMATICAL STRETCHED QAF
+1EE73,UNASSIGNED,,<RESERVED>
+1EE74-1EE77,DISALLOWED,,ARABIC MATHEMATICAL STRETCHED SHEEN..ARABIC MATHEMATICAL STRETCHED KHAH
+1EE78,UNASSIGNED,,<RESERVED>
+1EE79-1EE7C,DISALLOWED,,ARABIC MATHEMATICAL STRETCHED DAD..ARABIC MATHEMATICAL STRETCHED DOTLESS BEH
+1EE7D,UNASSIGNED,,<RESERVED>
+1EE7E,DISALLOWED,,ARABIC MATHEMATICAL STRETCHED DOTLESS FEH
+1EE7F,UNASSIGNED,,<RESERVED>
+1EE80-1EE89,DISALLOWED,,ARABIC MATHEMATICAL LOOPED ALEF..ARABIC MATHEMATICAL LOOPED YEH
+1EE8A,UNASSIGNED,,<RESERVED>
+1EE8B-1EE9B,DISALLOWED,,ARABIC MATHEMATICAL LOOPED LAM..ARABIC MATHEMATICAL LOOPED GHAIN
+1EE9C-1EEA0,UNASSIGNED,,<RESERVED>..<RESERVED>
+1EEA1-1EEA3,DISALLOWED,,ARABIC MATHEMATICAL DOUBLE-STRUCK BEH..ARABIC MATHEMATICAL DOUBLE-STRUCK DAL
+1EEA4,UNASSIGNED,,<RESERVED>
+1EEA5-1EEA9,DISALLOWED,,ARABIC MATHEMATICAL DOUBLE-STRUCK WAW..ARABIC MATHEMATICAL DOUBLE-STRUCK YEH
+1EEAA,UNASSIGNED,,<RESERVED>
+1EEAB-1EEBB,DISALLOWED,,ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN
+1EEBC-1EEEF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1EEF0-1EEF1,DISALLOWED,,ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL..ARABIC MATHEMATICAL OPERATOR HAH WITH DAL
+1EEF2-1EFFF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F000-1F02B,DISALLOWED,,MAHJONG TILE EAST WIND..MAHJONG TILE BACK
+1F02C-1F02F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F030-1F093,DISALLOWED,,DOMINO TILE HORIZONTAL BACK..DOMINO TILE VERTICAL-06-06
+1F094-1F09F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F0A0-1F0AE,DISALLOWED,,PLAYING CARD BACK..PLAYING CARD KING OF SPADES
+1F0AF-1F0B0,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F0B1-1F0BF,DISALLOWED,,PLAYING CARD ACE OF HEARTS..PLAYING CARD RED JOKER
+1F0C0,UNASSIGNED,,<RESERVED>
+1F0C1-1F0CF,DISALLOWED,,PLAYING CARD ACE OF DIAMONDS..PLAYING CARD BLACK JOKER
+1F0D0,UNASSIGNED,,<RESERVED>
+1F0D1-1F0F5,DISALLOWED,,PLAYING CARD ACE OF CLUBS..PLAYING CARD TRUMP-21
+1F0F6-1F0FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F100-1F10C,DISALLOWED,,DIGIT ZERO FULL STOP..DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ZERO
+1F10D-1F10F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F110-1F16B,DISALLOWED,,PARENTHESIZED LATIN CAPITAL LETTER A..RAISED MD SIGN
+1F16C-1F16F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F170-1F1AC,DISALLOWED,,NEGATIVE SQUARED LATIN CAPITAL LETTER A..SQUARED VOD
+1F1AD-1F1E5,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F1E6-1F202,DISALLOWED,,REGIONAL INDICATOR SYMBOL LETTER A..SQUARED KATAKANA SA
+1F203-1F20F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F210-1F23B,DISALLOWED,,SQUARED CJK UNIFIED IDEOGRAPH-624B..SQUARED CJK UNIFIED IDEOGRAPH-914D
+1F23C-1F23F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F240-1F248,DISALLOWED,,TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C..TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557
+1F249-1F24F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F250-1F251,DISALLOWED,,CIRCLED IDEOGRAPH ADVANTAGE..CIRCLED IDEOGRAPH ACCEPT
+1F252-1F25F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F260-1F265,DISALLOWED,,ROUNDED SYMBOL FOR FU..ROUNDED SYMBOL FOR CAI
+1F266-1F2FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F300-1F6D4,DISALLOWED,,CYCLONE..PAGODA
+1F6D5-1F6DF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F6E0-1F6EC,DISALLOWED,,HAMMER AND WRENCH..AIRPLANE ARRIVING
+1F6ED-1F6EF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F6F0-1F6F9,DISALLOWED,,SATELLITE..SKATEBOARD
+1F6FA-1F6FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F700-1F773,DISALLOWED,,ALCHEMICAL SYMBOL FOR QUINTESSENCE..ALCHEMICAL SYMBOL FOR HALF OUNCE
+1F774-1F77F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F780-1F7D8,DISALLOWED,,BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE..NEGATIVE CIRCLED SQUARE
+1F7D9-1F7FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F800-1F80B,DISALLOWED,,LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD..DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD
+1F80C-1F80F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F810-1F847,DISALLOWED,,LEFTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD..DOWNWARDS HEAVY ARROW
+1F848-1F84F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F850-1F859,DISALLOWED,,LEFTWARDS SANS-SERIF ARROW..UP DOWN SANS-SERIF ARROW
+1F85A-1F85F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F860-1F887,DISALLOWED,,WIDE-HEADED LEFTWARDS LIGHT BARB ARROW..WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW
+1F888-1F88F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F890-1F8AD,DISALLOWED,,LEFTWARDS TRIANGLE ARROWHEAD..WHITE ARROW SHAFT WIDTH TWO THIRDS
+1F8AE-1F8FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F900-1F90B,DISALLOWED,,CIRCLED CROSS FORMEE WITH FOUR DOTS..DOWNWARD FACING NOTCHED HOOK WITH DOT
+1F90C-1F90F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F910-1F93E,DISALLOWED,,ZIPPER-MOUTH FACE..HANDBALL
+1F93F,UNASSIGNED,,<RESERVED>
+1F940-1F970,DISALLOWED,,WILTED FLOWER..SMILING FACE WITH SMILING EYES AND THREE HEARTS
+1F971-1F972,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F973-1F976,DISALLOWED,,FACE WITH PARTY HORN AND PARTY HAT..FREEZING FACE
+1F977-1F979,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F97A,DISALLOWED,,FACE WITH PLEADING EYES
+1F97B,UNASSIGNED,,<RESERVED>
+1F97C-1F9A2,DISALLOWED,,LAB COAT..SWAN
+1F9A3-1F9AF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F9B0-1F9B9,DISALLOWED,,EMOJI COMPONENT RED HAIR..SUPERVILLAIN
+1F9BA-1F9BF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F9C0-1F9C2,DISALLOWED,,CHEESE WEDGE..SALT SHAKER
+1F9C3-1F9CF,UNASSIGNED,,<RESERVED>..<RESERVED>
+1F9D0-1F9FF,DISALLOWED,,FACE WITH MONOCLE..NAZAR AMULET
+1FA00-1FA5F,UNASSIGNED,,<RESERVED>..<RESERVED>
+1FA60-1FA6D,DISALLOWED,,XIANGQI RED GENERAL..XIANGQI BLACK SOLDIER
+1FA6E-1FFFD,UNASSIGNED,,<RESERVED>..<RESERVED>
+1FFFE-1FFFF,DISALLOWED,,<NOT A CHARACTER>..<NOT A CHARACTER>
+20000-2A6D6,PVALID,,"<CJK IDEOGRAPH EXTENSION B, FIRST>..<CJK IDEOGRAPH EXTENSION B, LAST>"
+2A6D7-2A6FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+2A700-2B734,PVALID,,"<CJK IDEOGRAPH EXTENSION C, FIRST>..<CJK IDEOGRAPH EXTENSION C, LAST>"
+2B735-2B73F,UNASSIGNED,,<RESERVED>..<RESERVED>
+2B740-2B81D,PVALID,,"<CJK IDEOGRAPH EXTENSION D, FIRST>..<CJK IDEOGRAPH EXTENSION D, LAST>"
+2B81E-2B81F,UNASSIGNED,,<RESERVED>..<RESERVED>
+2B820-2CEA1,PVALID,,"<CJK IDEOGRAPH EXTENSION E, FIRST>..<CJK IDEOGRAPH EXTENSION E, LAST>"
+2CEA2-2CEAF,UNASSIGNED,,<RESERVED>..<RESERVED>
+2CEB0-2EBE0,PVALID,,"<CJK IDEOGRAPH EXTENSION F, FIRST>..<CJK IDEOGRAPH EXTENSION F, LAST>"
+2EBE1-2F7FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+2F800-2FA1D,DISALLOWED,,CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
+2FA1E-2FFFD,UNASSIGNED,,<RESERVED>..<RESERVED>
+2FFFE-2FFFF,DISALLOWED,,<NOT A CHARACTER>..<NOT A CHARACTER>
+30000-3FFFD,UNASSIGNED,,<RESERVED>..<RESERVED>
+3FFFE-3FFFF,DISALLOWED,,<NOT A CHARACTER>..<NOT A CHARACTER>
+40000-4FFFD,UNASSIGNED,,<RESERVED>..<RESERVED>
+4FFFE-4FFFF,DISALLOWED,,<NOT A CHARACTER>..<NOT A CHARACTER>
+50000-5FFFD,UNASSIGNED,,<RESERVED>..<RESERVED>
+5FFFE-5FFFF,DISALLOWED,,<NOT A CHARACTER>..<NOT A CHARACTER>
+60000-6FFFD,UNASSIGNED,,<RESERVED>..<RESERVED>
+6FFFE-6FFFF,DISALLOWED,,<NOT A CHARACTER>..<NOT A CHARACTER>
+70000-7FFFD,UNASSIGNED,,<RESERVED>..<RESERVED>
+7FFFE-7FFFF,DISALLOWED,,<NOT A CHARACTER>..<NOT A CHARACTER>
+80000-8FFFD,UNASSIGNED,,<RESERVED>..<RESERVED>
+8FFFE-8FFFF,DISALLOWED,,<NOT A CHARACTER>..<NOT A CHARACTER>
+90000-9FFFD,UNASSIGNED,,<RESERVED>..<RESERVED>
+9FFFE-9FFFF,DISALLOWED,,<NOT A CHARACTER>..<NOT A CHARACTER>
+A0000-AFFFD,UNASSIGNED,,<RESERVED>..<RESERVED>
+AFFFE-AFFFF,DISALLOWED,,<NOT A CHARACTER>..<NOT A CHARACTER>
+B0000-BFFFD,UNASSIGNED,,<RESERVED>..<RESERVED>
+BFFFE-BFFFF,DISALLOWED,,<NOT A CHARACTER>..<NOT A CHARACTER>
+C0000-CFFFD,UNASSIGNED,,<RESERVED>..<RESERVED>
+CFFFE-CFFFF,DISALLOWED,,<NOT A CHARACTER>..<NOT A CHARACTER>
+D0000-DFFFD,UNASSIGNED,,<RESERVED>..<RESERVED>
+DFFFE-DFFFF,DISALLOWED,,<NOT A CHARACTER>..<NOT A CHARACTER>
+E0000,UNASSIGNED,,<RESERVED>
+E0001,DISALLOWED,,LANGUAGE TAG
+E0002-E001F,UNASSIGNED,,<RESERVED>..<RESERVED>
+E0020-E007F,DISALLOWED,,TAG SPACE..CANCEL TAG
+E0080-E00FF,UNASSIGNED,,<RESERVED>..<RESERVED>
+E0100-E01EF,DISALLOWED,,VARIATION SELECTOR-17..VARIATION SELECTOR-256
+E01F0-EFFFD,UNASSIGNED,,<RESERVED>..<RESERVED>
+EFFFE-10FFFF,DISALLOWED,,<NOT A CHARACTER>..<NOT A CHARACTER>
diff --git a/utils/import-messages.pl b/tools/import-messages.pl
index 4c13a859e..fe23842aa 100644
--- a/utils/import-messages.pl
+++ b/tools/import-messages.pl
@@ -81,7 +81,7 @@ sub main ()
}
# double check the options are sane (and we weren't asked for the help)
- if( !$opt_ok || $opt{help} || $opt{lang} !~ /^[a-z]{2}$/ )
+ if( !$opt_ok || $opt{help} || $opt{lang} !~ /^[a-z]{2}(?:_[A-Z]{2})?$/ )
{
usage();
}
@@ -97,7 +97,7 @@ sub main ()
my( $lang, $plat, $key );
- if( /^([a-z]{2})\.([^.]+)\.([^:]+):/ )
+ if( /(^[a-z]{2}(?:_[A-Z]{2})?)\.([^.]+)\.([^:]+):/ )
{
( $lang, $plat, $key ) = ( $1, $2, $3 );
}
@@ -246,7 +246,7 @@ sub parser ()
while ( <$stream> )
{
- if( /^([a-z]{2})\.([^.]+)\.([^:]+):(.*)/ )
+ if( /(^[a-z]{2}(?:_[A-Z]{2})?)\.([^.]+)\.([^:]+):(.*)/ )
{
my( $lang, $plat, $key, $val ) = ( $1, $2, $3, $4 );
diff --git a/utils/jenkins-build.sh b/tools/jenkins-build.sh
index 6fd6a777a..7dcd788a0 100755
--- a/utils/jenkins-build.sh
+++ b/tools/jenkins-build.sh
@@ -51,11 +51,19 @@ ATARIARCH=68020-60
# make tool
MAKE=make
+# NetSurf version number haiku needs it for package name
+NETSURF_VERSION="3.11"
+
+UPDATE_LATEST=yes
+
# Ensure the combination of target and toolchain works and set build
# specific parameters too
case ${TARGET} in
"riscos")
case ${HOST} in
+ "arm-riscos-gnueabi")
+ UPDATE_LATEST=no
+ ;;
"arm-unknown-riscos")
;;
@@ -66,6 +74,10 @@ case ${TARGET} in
esac
+ export GCCSDK_INSTALL_ENV=/opt/netsurf/${HOST}/env
+ export GCCSDK_INSTALL_CROSSBIN=/opt/netsurf/${HOST}/cross/bin
+ IDENTIFIER="${HOST}-${IDENTIFIER}"
+ OLD_IDENTIFIER="${HOST}-${OLD_IDENTIFIER}"
PKG_SRC=netsurf
PKG_SFX=.zip
;;
@@ -82,8 +94,8 @@ case ${TARGET} in
esac
- PKG_SRC=NetSurf
- PKG_SFX=
+ PKG_SRC="netsurf_x86-${NETSURF_VERSION}-1-x86_gcc2"
+ PKG_SFX=.hpkg
;;
@@ -191,7 +203,7 @@ case ${TARGET} in
;;
- "gtk")
+ "gtk2")
case ${HOST} in
"x86_64-linux-gnu")
;;
@@ -219,7 +231,7 @@ case ${TARGET} in
IDENTIFIER="${HOST}-${IDENTIFIER}"
OLD_IDENTIFIER="${HOST}-${OLD_IDENTIFIER}"
- PKG_SRC=nsgtk
+ PKG_SRC=nsgtk2
PKG_SFX=
;;
@@ -282,6 +294,11 @@ case ${TARGET} in
MAKE=gmake
;;
+ "arm-riscos-gnueabi")
+ export GCCSDK_INSTALL_ENV=/opt/netsurf/${HOST}/env
+ export GCCSDK_INSTALL_CROSSBIN=/opt/netsurf/${HOST}/cross/bin
+ ;;
+
"arm-unknown-riscos")
export GCCSDK_INSTALL_ENV=/opt/netsurf/${HOST}/env
export GCCSDK_INSTALL_CROSSBIN=/opt/netsurf/${HOST}/cross/bin
@@ -338,6 +355,11 @@ case ${TARGET} in
MAKE=gmake
;;
+ "arm-riscos-gnueabi")
+ export GCCSDK_INSTALL_ENV=/opt/netsurf/${HOST}/env
+ export GCCSDK_INSTALL_CROSSBIN=/opt/netsurf/${HOST}/cross/bin
+ ;;
+
"arm-unknown-riscos")
export GCCSDK_INSTALL_ENV=/opt/netsurf/${HOST}/env
export GCCSDK_INSTALL_CROSSBIN=/opt/netsurf/${HOST}/cross/bin
@@ -411,6 +433,17 @@ if [ ${HAVE_DISTCC} = "true" ];then
fi
+########### Prepare a Makefile.config ##################
+
+rm -f Makefile.config
+cat > Makefile.config <<EOF
+override NETSURF_LOG_LEVEL := DEBUG
+EOF
+
+########### Additional environment info ########
+
+uname -a
+
########### Build from source ##################
@@ -421,17 +454,30 @@ ${MAKE} clean
${MAKE} -j ${PARALLEL} -k CI_BUILD=${BUILD_NUMBER} ATARIARCH=${ATARIARCH} Q=
-
############ Package artifact construction ################
# build the package file
-${MAKE} -k CI_BUILD=${BUILD_NUMBER} ATARIARCH=${ATARIARCH} package Q=
+${MAKE} -k CI_BUILD=${BUILD_NUMBER} ATARIARCH=${ATARIARCH} PACKAGER="NetSurf Developers <support@netsurf-browser.org>" Q= package
if [ ! -f "${PKG_SRC}${PKG_SFX}" ]; then
# unable to find package file
exit 1
fi
+# create package checksum files
+
+# find md5sum binary
+MD5SUM=md5sum;
+command -v ${MD5SUM} >/dev/null 2>&1 || MD5SUM=md5
+command -v ${MD5SUM} >/dev/null 2>&1 || MD5SUM=echo
+
+# find sha256 binary name
+SHAR256SUM=sha256sum
+command -v ${SHAR256SUM} >/dev/null 2>&1 || SHAR256SUM=sha256
+command -v ${SHAR256SUM} >/dev/null 2>&1 || SHAR256SUM=echo
+
+${MD5SUM} "${PKG_SRC}${PKG_SFX}" > ${PKG_SRC}.md5
+${SHAR256SUM} "${PKG_SRC}${PKG_SFX}" > ${PKG_SRC}.sha256
############ Package artifact deployment ################
@@ -439,21 +485,24 @@ fi
#destination for package artifacts
DESTDIR=/srv/ci.netsurf-browser.org/html/builds/${TARGET}/
-NEW_ARTIFACT_TARGET="NetSurf-${IDENTIFIER}${PKG_SFX}"
-
-# copy the file into the output - always use scp as it works local or remote
-scp "${PKG_SRC}${PKG_SFX}" netsurf@ci.netsurf-browser.org:${DESTDIR}/${NEW_ARTIFACT_TARGET}
+NEW_ARTIFACT_TARGET="NetSurf-${IDENTIFIER}"
+OLD_ARTIFACT_TARGETS=""
-# remove the local package file artifact
-rm -f "${PKG_SRC}${PKG_SFX}"
+for SUFFIX in "${PKG_SFX}" .md5 .sha256;do
+ # copy the file to the output - always use scp as it works local or remote
+ scp "${PKG_SRC}${SUFFIX}" netsurf@ci.netsurf-browser.org:${DESTDIR}/${NEW_ARTIFACT_TARGET}${SUFFIX}
-# setup latest link
-ssh netsurf@ci.netsurf-browser.org "rm -f ${DESTDIR}/LATEST && echo "${NEW_ARTIFACT_TARGET}" > ${DESTDIR}/LATEST"
+ # remove the local file artifact
+ rm -f "${PKG_SRC}${SUFFIX}"
+ OLD_ARTIFACT_TARGETS="${OLD_ARTIFACT_TARGETS} ${DESTDIR}/NetSurf-${OLD_IDENTIFIER}${SUFFIX}"
+done
-############ Package artifact cleanup ################
+############ Expired package artifact removal and latest linking ##############
-OLD_ARTIFACT_TARGET="NetSurf-${OLD_IDENTIFIER}${PKG_SFX}"
-ssh netsurf@ci.netsurf-browser.org "rm -f ${DESTDIR}/${OLD_ARTIFACT_TARGET}"
+ssh netsurf@ci.netsurf-browser.org "rm -f ${OLD_ARTIFACT_TARGETS}"
+if [ ${UPDATE_LATEST} = "yes" ]; then
+ ssh netsurf@ci.netsurf-browser.org "rm -f ${DESTDIR}/LATEST && echo "${NEW_ARTIFACT_TARGET}${PKG_SFX}" > ${DESTDIR}/LATEST"
+fi
diff --git a/tools/linktrace-to-depfile.pl b/tools/linktrace-to-depfile.pl
new file mode 100644
index 000000000..9c90af322
--- /dev/null
+++ b/tools/linktrace-to-depfile.pl
@@ -0,0 +1,19 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Cwd qw(abs_path);
+
+my %deps;
+
+while (my $line = <>) {
+ chomp $line;
+ $line =~ s/[()]/ /g;
+ for my $word (split(/\s+/, $line)) {
+ $deps{abs_path($word)} = 1 if ($word =~ /\.a$/);
+ }
+}
+
+my @deps = keys %deps;
+
+print join("\t\\\n\t", @deps), "\n";
+
diff --git a/utils/memanalyze.pl b/tools/memanalyze.pl
index 57e107d11..57e107d11 100755
--- a/utils/memanalyze.pl
+++ b/tools/memanalyze.pl
diff --git a/tools/split-messages.c b/tools/split-messages.c
new file mode 100644
index 000000000..73a95e153
--- /dev/null
+++ b/tools/split-messages.c
@@ -0,0 +1,557 @@
+/**
+ * \file
+ * simple tool to split fat messages file without the capabilities of
+ * the full tool but without the dependancy on perl.
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <zlib.h>
+
+#include "utils/errors.h"
+
+enum out_fmt {
+ OUTPUTFMT_NONE = 0,
+ OUTPUTFMT_MESSAGES,
+};
+
+/**
+ * parameters that control behaviour of tool
+ */
+struct param {
+ /**
+ * compress output
+ */
+ int compress;
+ /**
+ * select language
+ */
+ char *selected;
+ /**
+ * fallback language for items unavailable in selecte dlanguage
+ */
+ char *fallback;
+ int warnings;
+ char *platform;
+ enum out_fmt format;
+ char *infilename;
+ char *outfilename;
+};
+
+struct trnsltn_entry {
+ struct trnsltn_entry *next;
+ char *lang;
+ char *key;
+ char *value;
+};
+
+static nserror usage(int argc, char **argv)
+{
+ fprintf(stderr,
+ "Usage: %s -l lang [-z] [-d lang] [-W warning] [-o <file>] [-i <file>] [-p platform] [-f format] [<file> [<file>]]\n"
+ "Options:\n"
+ " -z Gzip output\n"
+ " -l lang Language to select for\n"
+ " -d lang Fallback language [default: en]\n"
+ " -W warning Warnings generated none, all [default: none]\n"
+ " -p platform Platform to select for any, gtk, ami [default: any]\n"
+ " -f format Output format [default: messages]\n"
+ " -i filename Input file\n"
+ " -o filename Output file\n",
+ argv[0]);
+ return NSERROR_OK;
+}
+
+/**
+ * process command line arguments
+ *
+ *
+ */
+static nserror process_cmdline(int argc, char **argv, struct param *param)
+{
+ int opt;
+
+ memset(param, 0, sizeof(*param));
+
+ while ((opt = getopt(argc, argv, "zl:d:W:o:i:p:f:")) != -1) {
+ switch (opt) {
+ case 'z':
+ param->compress = 1;
+ break;
+
+ case 'l':
+ param->selected = strdup(optarg);
+ break;
+
+ case 'd':
+ param->fallback = strdup(optarg);
+ break;
+
+ case 'W':
+ param->warnings = 1;
+ break;
+
+ case 'o':
+ param->outfilename = strdup(optarg);
+ break;
+
+ case 'i':
+ param->infilename = strdup(optarg);
+ break;
+
+ case 'p':
+ param->platform = strdup(optarg);
+ break;
+
+ case 'f':
+ if (strcmp(optarg, "messages") == 0) {
+ param->format = OUTPUTFMT_MESSAGES;
+ } else {
+ fprintf(stderr,
+ "output format %s not supported",
+ optarg);
+ usage(argc, argv);
+ return NSERROR_NOT_IMPLEMENTED;
+ }
+ break;
+
+ default:
+ usage(argc, argv);
+ return NSERROR_BAD_PARAMETER;
+ }
+ }
+
+ /* trailing filename arguments */
+ if (optind < argc) {
+ param->infilename = strdup(argv[optind]);
+ optind++;
+ }
+
+ if (optind < argc) {
+ param->outfilename = strdup(argv[optind]);
+ optind++;
+ }
+
+ /* parameter checks */
+ if (param->selected == NULL) {
+ fprintf(stderr, "A language to select must be specified\n");
+ usage(argc, argv);
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if (param->infilename == NULL) {
+ fprintf(stderr, "Input file required\n");
+ usage(argc, argv);
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if (param->outfilename == NULL) {
+ fprintf(stderr, "Output file required\n");
+ usage(argc, argv);
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if ((param->platform != NULL) &&
+ (strcmp(param->platform, "any") ==0)) {
+ free(param->platform);
+ param->platform = NULL;
+ }
+
+ /* defaults */
+ if (param->fallback == NULL) {
+ param->fallback = strdup("en");
+ }
+
+ if (param->format == OUTPUTFMT_NONE) {
+ param->format = OUTPUTFMT_MESSAGES;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * extract key/value from a line of input
+ *
+ * \retun NSERROR_OK and key_out and value_out updated
+ * NSERROR_NOT_FOUND if not a key/value input line
+ * NSERROR_INVALID if the line is and invalid format (missing colon)
+ */
+static nserror
+get_key_value(char *line, ssize_t linelen, char **key_out, char **value_out)
+{
+ char *key;
+ char *value;
+
+ /* skip leading whitespace for start of key */
+ for (key = line; *key != 0; key++) {
+ if ((*key != ' ') && (*key != '\t') && (*key != '\n')) {
+ break;
+ }
+ }
+
+ /* empty line or only whitespace */
+ if (*key == 0) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ /* comment */
+ if (*key == '#') {
+ return NSERROR_NOT_FOUND;
+ }
+
+ /* get start of value */
+ for (value = key; *value != 0; value++) {
+ if (*value == ':') {
+ *value = 0;
+ value++;
+ break;
+ }
+ }
+
+ /* missing colon separator */
+ if (*value == 0) {
+ return NSERROR_INVALID;
+ }
+
+ /* remove delimiter from value */
+ if (line[linelen - 1] == '\n') {
+ linelen--;
+ line[linelen] = 0;
+ }
+
+ *key_out = key;
+ *value_out = value;
+ return NSERROR_OK;
+}
+
+
+/**
+ * extract language, platform and token elements from a string
+ */
+static nserror
+get_lang_plat_tok(char *str, char **lang_out, char **plat_out, char **tok_out)
+{
+ char *plat;
+ char *tok;
+
+ for (plat = str; *plat != 0; plat++) {
+ if (*plat == '.') {
+ *plat = 0;
+ plat++;
+ break;
+ }
+ }
+ if (*plat == 0) {
+ return NSERROR_INVALID;
+ }
+
+ for (tok = plat; *tok != 0; tok++) {
+ if (*tok == '.') {
+ *tok = 0;
+ tok++;
+ break;
+ }
+ }
+ if (*tok == 0) {
+ return NSERROR_INVALID;
+ }
+
+ *lang_out = str;
+ *plat_out = plat;
+ *tok_out = tok;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * reverse order of entries in a translation list
+ */
+static nserror
+translation_list_reverse(struct trnsltn_entry **tlist)
+{
+ struct trnsltn_entry *prev;
+ struct trnsltn_entry *next;
+ struct trnsltn_entry *curr;
+
+ prev = NULL;
+ next = NULL;
+ curr = *tlist;
+
+ while (curr != NULL) {
+ next = curr->next;
+ curr->next = prev;
+ prev = curr;
+ curr = next;
+ }
+
+ *tlist = prev;
+ return NSERROR_OK;
+}
+
+
+/**
+ * find a translation entry from a key
+ *
+ * \todo This implementation is imcomplete! it only considers the very
+ * first entry on the list. this introduces the odd ordering
+ * requirement for keys in the fatmessages file. This is done to avoid
+ * an O(n^2) list search for every line of input.
+ *
+ * \param tlist translation list head
+ * \param key The key of the translation to search for
+ * \param trans_out The sucessful result
+ * \return NSERROR_OK and trans_out updated on success else NSERROR_NOT_FOUND;
+ */
+static nserror
+translation_from_key(struct trnsltn_entry *tlist,
+ char *key,
+ struct trnsltn_entry **trans_out)
+{
+ if (tlist == NULL) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ if (strcmp(tlist->key, key) != 0) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ *trans_out = tlist;
+ return NSERROR_OK;
+}
+
+
+/**
+ * create and link an entry into translation list
+ */
+static nserror
+translation_add(struct trnsltn_entry **tlist,
+ const char *lang,
+ const char *key,
+ const char *value)
+{
+ struct trnsltn_entry *tnew;
+
+ tnew = malloc(sizeof(*tnew));
+ if (tnew == NULL) {
+ return NSERROR_NOMEM;
+ }
+ tnew->next = *tlist;
+ tnew->lang = strdup(lang);
+ tnew->key = strdup(key);
+ tnew->value = strdup(value);
+
+ *tlist = tnew;
+ return NSERROR_OK;
+}
+
+
+/**
+ * replace key and value on a translation entry
+ */
+static nserror
+translation_replace(struct trnsltn_entry *tran,
+ const char *lang,
+ const char *key,
+ const char *value)
+{
+ free(tran->lang);
+ tran->lang = strdup(lang);
+ free(tran->key);
+ tran->key = strdup(key);
+ free(tran->value);
+ tran->value = strdup(value);
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * process a line of the input file
+ *
+ */
+static nserror
+messageline(struct param *param,
+ struct trnsltn_entry **tlist,
+ char *line, ssize_t linelen)
+{
+ nserror res;
+ char *key;
+ char *value;
+ char *lang;
+ char *plat;
+ char *tok;
+ struct trnsltn_entry *tran;
+
+ res = get_key_value(line, linelen, &key, &value);
+ if (res != NSERROR_OK) {
+ /* skip line as no valid key value pair found */
+ return res;
+ }
+
+ res = get_lang_plat_tok(key, &lang, &plat, &tok);
+ if (res != NSERROR_OK) {
+ /* malformed key */
+ return res;
+ }
+
+ if ((param->platform != NULL) &&
+ (strcmp(plat, "all") != 0) &&
+ (strcmp(plat, param->platform) != 0)) {
+ /* this translation is not for the selected platform */
+ return NSERROR_OK;
+ }
+
+ res = translation_from_key(*tlist, tok, &tran);
+ if (res == NSERROR_OK) {
+ if (strcmp(tran->lang, param->selected) != 0) {
+ /* current entry is not the selected language */
+ if (strcmp(lang, param->selected) == 0) {
+ /*
+ * new entry is in selected language and
+ * current entry is not
+ */
+ res = translation_replace(tran, lang, tok, value);
+ } else if ((strcmp(lang, param->fallback) != 0) &&
+ (strcmp(tran->lang, param->fallback) != 0)) {
+ /*
+ * new entry is in fallback language and
+ * current entry is not.
+ */
+ res = translation_replace(tran, lang, tok, value);
+ }
+ } else {
+ if (strcmp(tran->lang, lang) == 0) {
+ /* second entry with matching language */
+ res = translation_replace(tran, lang, tok, value);
+ }
+ }
+ } else if (res == NSERROR_NOT_FOUND) {
+ res = translation_add(tlist, lang, tok, value);
+ }
+
+ return res;
+}
+
+
+/**
+ * read fatmessages file and create a translation entry list
+ */
+static nserror
+fatmessages_read(struct param *param, struct trnsltn_entry **tlist)
+{
+ nserror res;
+ FILE *infile;
+ char *line = NULL;
+ size_t linealloc = 0;
+ ssize_t linelen;
+ int linenum = 0;
+
+ infile = fopen(param->infilename, "r");
+ if (infile == NULL) {
+ perror("Unable to open input file");
+ return NSERROR_NOT_FOUND;
+ }
+
+ while (1) {
+ linelen = getline(&line, &linealloc, infile);
+ if (linelen == -1) {
+ break;
+ }
+ linenum++;
+
+ res = messageline(param, tlist, line, linelen);
+ if ((res == NSERROR_INVALID) && (param->warnings > 0)) {
+ fprintf(stderr, "line %d Malformed: \"%s\"\n",
+ linenum, line);
+ }
+ }
+
+ fclose(infile);
+
+ res = translation_list_reverse(tlist);
+
+ return res;
+}
+
+
+/**
+ * write output in NetSurf messages format
+ */
+static nserror
+message_write(struct param *param, struct trnsltn_entry *tlist)
+{
+ gzFile outf;
+ const char *mode;
+
+ if (param->compress == 0) {
+ mode = "wbT";
+ } else {
+ mode = "wb9";
+ }
+
+ outf = gzopen(param->outfilename, mode);
+ if (outf == NULL) {
+ perror("Unable to open output file");
+ return NSERROR_PERMISSION;
+ }
+
+ if (gzprintf(outf,
+ "# This messages file is automatically generated from %s\n"
+ "# at build-time. Please go and edit that instead of this.\n\n",
+ param->infilename) < 1) {
+ gzclose(outf);
+ unlink(param->outfilename);
+ return NSERROR_NOSPACE;
+ };
+
+ while (tlist != NULL) {
+ if (gzprintf(outf, "%s:%s\n", tlist->key, tlist->value) < 1) {
+ gzclose(outf);
+ unlink(param->outfilename);
+ return NSERROR_NOSPACE;
+ }
+ tlist = tlist->next;
+ }
+
+ gzclose(outf);
+
+ return NSERROR_OK;
+}
+
+int main(int argc, char **argv)
+{
+ nserror res;
+ struct param param; /* control paramters */
+ struct trnsltn_entry *translations = NULL;
+
+ res = process_cmdline(argc, argv, &param);
+ if (res != NSERROR_OK) {
+ return EXIT_FAILURE;
+ }
+
+ res = fatmessages_read(&param, &translations);
+ if (res != NSERROR_OK) {
+ return EXIT_FAILURE;
+ }
+
+ switch (param.format) {
+ case OUTPUTFMT_NONE:
+ res = NSERROR_OK;
+ break;
+
+ case OUTPUTFMT_MESSAGES:
+ res = message_write(&param, translations);
+ break;
+ }
+
+ if (res != NSERROR_OK) {
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/utils/split-messages.pl b/tools/split-messages.pl
index 4b50dded8..1c78fd271 100644
--- a/utils/split-messages.pl
+++ b/tools/split-messages.pl
@@ -85,7 +85,7 @@ sub main ()
}
# double check the options are sane (and we weren't asked for the help)
- if( !$opt_ok || $opt{help} || $opt{lang} !~ /^[a-z]{2}$/ || $opt{dlang} !~ /^[a-z]{2}$/ )
+ if( !$opt_ok || $opt{help} || $opt{lang} !~ /^[a-z]{2}(?:_[A-Z]{2})?$/ || $opt{dlang} !~ /^[a-z]{2}(?:_[A-Z]{2})?$/ )
{
usage();
}
@@ -109,7 +109,7 @@ sub main ()
/^\s*$/ && next;
# only parsing things that look like message lines:
- if( /^([a-z]{2}).([^.]+).([^:]+):(.*)/ )
+ if( /^([a-z]{2}(?:_[A-Z]{2})?).([^.]+).([^:]+):(.*)/ )
{
my( $lang, $plat, $key, $val ) = ( $1, $2, $3, $4 );
@@ -187,7 +187,7 @@ sub usage ()
print(STDERR <<TXT );
usage:
$0 -l lang-code [-d def-lang-code] [-W warning] \
- [-o output-file] [-i input-file] [-p platform] [-f format]
+ [-o output-file] [-i input-file] [-p platform] [-f format] [-z]
$0 -l lang-code ... [input-file [output-file]]
diff --git a/utils/test-netsurf b/tools/test-netsurf
index 90c7e121b..90c7e121b 100755
--- a/utils/test-netsurf
+++ b/tools/test-netsurf
diff --git a/utils/valgrind.supp b/tools/valgrind.supp
index f1a27f4b4..f1a27f4b4 100644
--- a/utils/valgrind.supp
+++ b/tools/valgrind.supp
diff --git a/tools/xxd.c b/tools/xxd.c
new file mode 100644
index 000000000..a4e5dac5b
--- /dev/null
+++ b/tools/xxd.c
@@ -0,0 +1,135 @@
+/*
+ * xxd utility
+ *
+ * Copyright 2020 Lars Wirzenius
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+static char *get_array_name(const char *fname)
+{
+ int fnamelen;
+ char *aryname;
+ int idx;
+
+ fnamelen = strlen(fname);
+ aryname = malloc(fnamelen + 1);
+
+ if (aryname != NULL) {
+ for (idx = 0; idx < fnamelen; idx++) {
+ int c = fname[idx];
+ if ((c >= '0' && c <= '9') ||
+ (c >= 'A' && c <= 'Z') ||
+ (c >= 'a' && c <= 'z')) {
+ aryname[idx] = fname[idx];
+ } else {
+ aryname[idx] = '_';
+ }
+ }
+ aryname[idx] = 0;
+ }
+ return aryname;
+}
+
+int main(int argc, char **argv)
+{
+ int inc = 0;
+ int opt;
+ int c, n;
+ FILE *inf;
+ FILE *outf;
+ char *aryname = NULL;
+ int outlen;
+
+ while ((opt = getopt(argc, argv, "i")) != -1) {
+ switch (opt) {
+ case 'i':
+ inc = 1;
+ break;
+
+ default: /* '?' */
+ fprintf(stderr, "Usage: %s [-i] [infile [outfile]]]\n",
+ argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (optind < argc) {
+ inf = fopen(argv[optind], "r");
+ if (inf == NULL) {
+ perror("Opening for read");
+ exit(EXIT_FAILURE);
+ }
+ aryname = get_array_name(argv[optind]);
+ optind++;
+ } else {
+ inf = stdin;
+
+ }
+
+ if (optind < argc) {
+ outf = fopen(argv[optind], "w");
+ if (outf == NULL) {
+ perror("Opening for write");
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ outf = stdout;
+ }
+
+ if ((inc != 0) && (aryname != NULL)) {
+ fprintf(outf, "unsigned char %s[] = {\n", aryname);
+ }
+
+ outlen = 0;
+ n = 0;
+ while ((c = getc(inf)) != EOF) {
+ if (n == 0) {
+ fprintf(outf, " ");
+ }
+ fprintf(outf, " 0x%02x,", c);
+ n += 1;
+ outlen++;
+ if (n >= 12) {
+ fprintf(outf, "\n");
+ n = 0;
+ }
+ }
+ if (n > 0) {
+ fprintf(outf, "\n");
+ }
+
+ if ((inc != 0) && (aryname != NULL)) {
+ fprintf(outf, "};\nunsigned int %s_len = %d;\n",
+ aryname, outlen);
+ }
+
+
+
+ fclose(outf);
+ fclose(inf);
+
+ return 0;
+}
diff --git a/utils/Makefile b/utils/Makefile
index 2f59501c2..b186cd116 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -6,13 +6,16 @@ S_UTILS := \
file.c \
filename.c \
filepath.c \
+ hashmap.c \
hashtable.c \
idna.c \
libdom.c \
log.c \
messages.c \
+ nscolour.c \
nsoption.c \
punycode.c \
+ ssl_certs.c \
talloc.c \
time.c \
url.c \
diff --git a/utils/config.h b/utils/config.h
index ddd1c6e8e..f54326dba 100644
--- a/utils/config.h
+++ b/utils/config.h
@@ -16,21 +16,38 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_UTILS_CONFIG_H_
-#define _NETSURF_UTILS_CONFIG_H_
+#ifndef NETSURF_UTILS_CONFIG_H_
+#define NETSURF_UTILS_CONFIG_H_
#include <stddef.h>
+#if defined(__NetBSD__)
+#include <sys/param.h>
+#if (defined(__NetBSD_Version__) && __NetBSD_Prereq__(8,0,0))
+#define NetBSD_v8
+#endif
+#endif
+
/* Try to detect which features the target OS supports */
-#if (defined(_GNU_SOURCE) && !defined(__APPLE__) || defined(__amigaos4__) || defined(__HAIKU__) || (defined(_POSIX_C_SOURCE) && ((_POSIX_C_SOURCE - 0) >= 200809L)) && !defined(__riscos__))
+#if (defined(_GNU_SOURCE) && \
+ !defined(__APPLE__) || \
+ defined(__amigaos4__) || \
+ defined(__HAIKU__) || \
+ (defined(_POSIX_C_SOURCE) && ((_POSIX_C_SOURCE - 0) >= 200809L)) && \
+ !defined(__riscos__))
#define HAVE_STRNDUP
#else
#undef HAVE_STRNDUP
char *strndup(const char *s, size_t n);
#endif
-#if (defined(_GNU_SOURCE) || defined(__APPLE__) || defined(__HAIKU__) || defined(__OpenBSD__))
+#if ((defined(_GNU_SOURCE) || \
+ defined(__APPLE__) || \
+ defined(__HAIKU__) || \
+ defined(__NetBSD__) || \
+ defined(__OpenBSD__)) && \
+ !defined(__serenity__))
#define HAVE_STRCASESTR
#else
#undef HAVE_STRCASESTR
@@ -40,7 +57,13 @@ char *strcasestr(const char *haystack, const char *needle);
/* Although these platforms might have strftime or strptime they
* appear not to support the time_t seconds format specifier.
*/
-#if (defined(_WIN32) || defined(__riscos__) || defined(__HAIKU__) || defined(__BEOS__) || defined(__amigaos4__) || defined(__AMIGA__) || defined(__MINT__))
+#if (defined(_WIN32) || \
+ defined(__riscos__) || \
+ defined(__HAIKU__) || \
+ defined(__BEOS__) || \
+ defined(__amigaos4__) || \
+ defined(__AMIGA__) || \
+ defined(__MINT__))
#undef HAVE_STRPTIME
#undef HAVE_STRFTIME
#else
@@ -51,22 +74,36 @@ char *strcasestr(const char *haystack, const char *needle);
/* For some reason, UnixLib defines this unconditionally. Assume we're using
* UnixLib if building for RISC OS.
*/
-#if ((defined(_GNU_SOURCE) && !defined(__APPLE__)) || defined(__riscos__))
+#if ((defined(_GNU_SOURCE) && !defined(__APPLE__)) || \
+ defined(__riscos__) || \
+ defined(NetBSD_v8))
#define HAVE_STRCHRNUL
#else
#undef HAVE_STRCHRNUL
char *strchrnul(const char *s, int c);
#endif
+/*
+ * amigaos3 declares this but does not have it in its actual library
+ */
+#define HAVE_STRTOULL
+#if !defined(__amigaos4__) && defined(__AMIGA__)
+#undef HAVE_STRTOULL
+#endif
+
#define HAVE_SYS_SELECT
-#define HAVE_INETATON
#define HAVE_POSIX_INET_HEADERS
#if (defined(_WIN32))
-#undef HAVE_INETATON
#undef HAVE_SYS_SELECT
#undef HAVE_POSIX_INET_HEADERS
#endif
+#define HAVE_INETATON
+#if (defined(_WIN32) || \
+ defined(__serenity__))
+#undef HAVE_INETATON
+#endif
+
#define HAVE_INETPTON
#if (defined(_WIN32))
#undef HAVE_INETPTON
@@ -104,10 +141,31 @@ char *realpath(const char *path, char *resolved_path);
#endif
#define HAVE_SCANDIR
-#if (defined(_WIN32))
+#if (defined(_WIN32) || \
+ defined(__serenity__))
#undef HAVE_SCANDIR
#endif
+#define HAVE_DIRFD
+#define HAVE_UNLINKAT
+#define HAVE_FSTATAT
+#if (defined(_WIN32) || defined(__riscos__) || defined(__HAIKU__) || defined(__BEOS__) || defined(__amigaos4__) || defined(__AMIGA__) || defined(__MINT__))
+#undef HAVE_DIRFD
+#undef HAVE_UNLINKAT
+#undef HAVE_FSTATAT
+#endif
+
+#define HAVE_REGEX
+#if (defined(__serenity__))
+#undef HAVE_REGEX
+#endif
+
+/* execinfo available for backtrace */
+#if ((defined(__linux__) && defined(__GLIBC__) && !defined(__UCLIBC__)) || \
+ defined(__APPLE__))
+#define HAVE_EXECINFO
+#endif
+
/* This section toggles build options on and off.
* Simply undefine a symbol to turn the relevant feature off.
*
@@ -133,9 +191,11 @@ char *realpath(const char *path, char *resolved_path);
#define WITH_MMAP
#endif
-/* amiga */
-#if defined(__amigaos4__) || defined(__AMIGA__) || \
- defined(nsatari)
+/* IPv6 */
+#if (defined(__amigaos4__) || \
+ defined(__AMIGA__) || \
+ defined(nsatari) || \
+ defined(__serenity__))
#define NO_IPV6
#endif
diff --git a/utils/corestringlist.h b/utils/corestringlist.h
index 90dd796a7..5cdbb3af7 100644
--- a/utils/corestringlist.h
+++ b/utils/corestringlist.h
@@ -139,11 +139,19 @@ CORESTRING_LWC_STRING(_blank);
CORESTRING_LWC_STRING(_parent);
CORESTRING_LWC_STRING(_self);
CORESTRING_LWC_STRING(_top);
+CORESTRING_LWC_STRING(443);
/* unusual lwc strings */
CORESTRING_LWC_VALUE(shortcut_icon, "shortcut icon");
CORESTRING_LWC_VALUE(slash_, "/");
CORESTRING_LWC_VALUE(max_age, "max-age");
+CORESTRING_LWC_VALUE(no_cache, "no-cache");
+CORESTRING_LWC_VALUE(no_store, "no-store");
+CORESTRING_LWC_VALUE(query_auth, "query/auth");
+CORESTRING_LWC_VALUE(query_ssl, "query/ssl");
+CORESTRING_LWC_VALUE(query_timeout, "query/timeout");
+CORESTRING_LWC_VALUE(query_fetcherror, "query/fetcherror");
+CORESTRING_LWC_VALUE(x_ns_css, "x-ns-css");
/* mime types */
CORESTRING_LWC_VALUE(multipart_form_data, "multipart/form-data");
@@ -159,6 +167,7 @@ CORESTRING_LWC_VALUE(application_octet_stream, "application/octet-stream");
CORESTRING_LWC_VALUE(image_gif, "image/gif");
CORESTRING_LWC_VALUE(image_png, "image/png");
CORESTRING_LWC_VALUE(image_jpeg, "image/jpeg");
+CORESTRING_LWC_VALUE(image_jxl, "image/jxl");
CORESTRING_LWC_VALUE(image_bmp, "image/bmp");
CORESTRING_LWC_VALUE(image_vnd_microsoft_icon, "image/vnd.microsoft.icon");
CORESTRING_LWC_VALUE(image_webp, "image/webp");
@@ -183,6 +192,10 @@ CORESTRING_DOM_STRING(afterprint);
CORESTRING_DOM_STRING(align);
CORESTRING_DOM_STRING(alt);
CORESTRING_DOM_STRING(area);
+CORESTRING_DOM_STRING(ArrowDown);
+CORESTRING_DOM_STRING(ArrowLeft);
+CORESTRING_DOM_STRING(ArrowRight);
+CORESTRING_DOM_STRING(ArrowUp);
CORESTRING_DOM_STRING(async);
CORESTRING_DOM_STRING(background);
CORESTRING_DOM_STRING(beforeprint);
@@ -226,12 +239,15 @@ CORESTRING_DOM_STRING(dragstart);
CORESTRING_DOM_STRING(drop);
CORESTRING_DOM_STRING(durationchange);
CORESTRING_DOM_STRING(emptied);
+CORESTRING_DOM_STRING(End);
CORESTRING_DOM_STRING(ended);
CORESTRING_DOM_STRING(error);
+CORESTRING_DOM_STRING(Escape);
CORESTRING_DOM_STRING(focus);
CORESTRING_DOM_STRING(frameborder);
CORESTRING_DOM_STRING(hashchange);
CORESTRING_DOM_STRING(height);
+CORESTRING_DOM_STRING(Home);
CORESTRING_DOM_STRING(href);
CORESTRING_DOM_STRING(hreflang);
CORESTRING_DOM_STRING(hspace);
@@ -243,6 +259,7 @@ CORESTRING_DOM_STRING(keydown);
CORESTRING_DOM_STRING(keypress);
CORESTRING_DOM_STRING(keyup);
CORESTRING_DOM_STRING(link);
+CORESTRING_DOM_STRING(languagechange);
CORESTRING_DOM_STRING(load);
CORESTRING_DOM_STRING(loadeddata);
CORESTRING_DOM_STRING(loadedmetadata);
@@ -264,8 +281,10 @@ CORESTRING_DOM_STRING(noresize);
CORESTRING_DOM_STRING(nowrap);
CORESTRING_DOM_STRING(offline);
CORESTRING_DOM_STRING(online);
+CORESTRING_DOM_STRING(PageDown);
CORESTRING_DOM_STRING(pagehide);
CORESTRING_DOM_STRING(pageshow);
+CORESTRING_DOM_STRING(PageUp);
CORESTRING_DOM_STRING(pause);
CORESTRING_DOM_STRING(play);
CORESTRING_DOM_STRING(playing);
@@ -277,6 +296,7 @@ CORESTRING_DOM_STRING(rect);
CORESTRING_DOM_STRING(rel);
CORESTRING_DOM_STRING(reset);
CORESTRING_DOM_STRING(resize);
+CORESTRING_DOM_STRING(reversed);
CORESTRING_DOM_STRING(rows);
CORESTRING_DOM_STRING(rowspan);
CORESTRING_DOM_STRING(scroll);
@@ -291,6 +311,7 @@ CORESTRING_DOM_STRING(size);
CORESTRING_DOM_STRING(sizes);
CORESTRING_DOM_STRING(src);
CORESTRING_DOM_STRING(stalled);
+CORESTRING_DOM_STRING(start);
CORESTRING_DOM_STRING(storage);
CORESTRING_DOM_STRING(style);
CORESTRING_DOM_STRING(submit);
@@ -310,11 +331,14 @@ CORESTRING_DOM_STRING(waiting);
CORESTRING_DOM_STRING(width);
/* DOM node names, not really CSS */
CORESTRING_DOM_STRING(BUTTON);
+CORESTRING_DOM_STRING(HTML);
CORESTRING_DOM_STRING(INPUT);
CORESTRING_DOM_STRING(SELECT);
CORESTRING_DOM_STRING(TEXTAREA);
+CORESTRING_DOM_STRING(TITLE);
CORESTRING_DOM_STRING(BODY);
CORESTRING_DOM_STRING(HEAD);
+CORESTRING_DOM_STRING(SCRIPT);
/* DOM input types, not really CSS */
CORESTRING_DOM_STRING(button);
CORESTRING_DOM_STRING(image);
@@ -345,6 +369,7 @@ CORESTRING_DOM_STRING(__ns_key_libcss_node_data);
CORESTRING_DOM_STRING(__ns_key_file_name_node_data);
CORESTRING_DOM_STRING(__ns_key_image_coords_node_data);
CORESTRING_DOM_STRING(__ns_key_html_content_data);
+CORESTRING_DOM_STRING(__ns_key_canvas_node_data);
/* unusual DOM strings */
CORESTRING_DOM_VALUE(text_javascript, "text/javascript");
@@ -352,6 +377,10 @@ CORESTRING_DOM_VALUE(http_equiv, "http-equiv");
CORESTRING_DOM_VALUE(html_namespace, "http://www.w3.org/1999/xhtml");
CORESTRING_NSURL(about_blank, "about:blank");
+CORESTRING_NSURL(about_query_ssl, "about:query/ssl");
+CORESTRING_NSURL(about_query_auth, "about:query/auth");
+CORESTRING_NSURL(about_query_timeout, "about:query/timeout");
+CORESTRING_NSURL(about_query_fetcherror, "about:query/fetcherror");
#undef CORESTRING_LWC_STRING
#undef CORESTRING_DOM_STRING
diff --git a/utils/dirent.h b/utils/dirent.h
index fa78e1491..318734c30 100644
--- a/utils/dirent.h
+++ b/utils/dirent.h
@@ -28,8 +28,8 @@
* utils config header include.
*/
-#ifndef _NETSURF_UTILS_DIRENT_H_
-#define _NETSURF_UTILS_DIRENT_H_
+#ifndef NETSURF_UTILS_DIRENT_H
+#define NETSURF_UTILS_DIRENT_H
#include "utils/config.h"
diff --git a/utils/errors.h b/utils/errors.h
index 9a0a9bc04..ac4d38e2b 100644
--- a/utils/errors.h
+++ b/utils/errors.h
@@ -59,6 +59,10 @@ typedef enum {
NSERROR_NOSPACE, /**< Insufficient space */
NSERROR_BAD_SIZE, /**< Bad size */
NSERROR_NOT_IMPLEMENTED, /**< Functionality is not implemented */
+ NSERROR_BAD_REDIRECT, /**< Fetch encountered a bad redirect */
+ NSERROR_BAD_AUTH, /**< Fetch needs authentication data */
+ NSERROR_BAD_CERTS, /**< Fetch needs certificate chain check */
+ NSERROR_TIMEOUT, /**< Operation timed out */
} nserror;
#endif
diff --git a/utils/file.c b/utils/file.c
index cc82657c9..75a8a1c03 100644
--- a/utils/file.c
+++ b/utils/file.c
@@ -26,6 +26,8 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
#include "desktop/gui_internal.h"
@@ -35,6 +37,11 @@
#include "utils/nsurl.h"
#include "utils/string.h"
#include "utils/file.h"
+#include "utils/dirent.h"
+
+#ifdef nsamiga
+#include "frontends/amiga/os3support.h"
+#endif
/**
* Generate a posix path from one or more component elemnts.
@@ -307,3 +314,82 @@ nserror netsurf_mkdir_all(const char *fname)
{
return guit->file->mkdir_all(fname);
}
+
+/* exported interface documented in utils/file.h */
+nserror
+netsurf_recursive_rm(const char *path)
+{
+ DIR *parent;
+ struct dirent *entry;
+ nserror ret = NSERROR_OK;
+ struct stat ent_stat; /* stat result of leaf entry */
+
+ parent = opendir(path);
+ if (parent == NULL) {
+ switch (errno) {
+ case ENOENT:
+ return NSERROR_NOT_FOUND;
+ default:
+ return NSERROR_UNKNOWN;
+ }
+ }
+
+ while ((entry = readdir(parent))) {
+ char *leafpath = NULL;
+
+ if (strcmp(entry->d_name, ".") == 0 ||
+ strcmp(entry->d_name, "..") == 0)
+ continue;
+
+ ret = netsurf_mkpath(&leafpath, NULL, 2, path, entry->d_name);
+ if (ret != NSERROR_OK)
+ goto out;
+
+#if (defined(HAVE_DIRFD) && defined(HAVE_FSTATAT))
+ if (fstatat(dirfd(parent), entry->d_name, &ent_stat,
+ AT_SYMLINK_NOFOLLOW) != 0) {
+#else
+ if (stat(leafpath, &ent_stat) != 0) {
+#endif
+ free(leafpath);
+ goto out_via_errno;
+ }
+ if (S_ISDIR(ent_stat.st_mode)) {
+ ret = netsurf_recursive_rm(leafpath);
+ if (ret != NSERROR_OK) {
+ free(leafpath);
+ goto out;
+ }
+ } else {
+#if (defined(HAVE_DIRFD) && defined(HAVE_UNLINKAT))
+ if (unlinkat(dirfd(parent), entry->d_name, 0) != 0) {
+#else
+ if (unlink(leafpath) != 0) {
+#endif
+ free(leafpath);
+ goto out_via_errno;
+ }
+ }
+
+ free(leafpath);
+ }
+
+ if (rmdir(path) != 0) {
+ goto out_via_errno;
+ }
+
+ goto out;
+
+out_via_errno:
+ switch (errno) {
+ case ENOENT:
+ ret = NSERROR_NOT_FOUND;
+ break;
+ default:
+ ret = NSERROR_UNKNOWN;
+ }
+out:
+ closedir(parent);
+
+ return ret;
+}
diff --git a/utils/file.h b/utils/file.h
index 5ee13b5aa..809ffe419 100644
--- a/utils/file.h
+++ b/utils/file.h
@@ -117,7 +117,7 @@ struct gui_file_table {
};
/** Default (posix) file operation table. */
-struct gui_file_table *default_file_table;
+extern struct gui_file_table *default_file_table;
/**
* Generate a path from one or more component elemnts.
@@ -172,4 +172,15 @@ nserror netsurf_path_to_nsurl(const char *path, struct nsurl **url);
*/
nserror netsurf_mkdir_all(const char *fname);
+/**
+ * Recursively remove a directory
+ *
+ * If this returns a failure code, there's an unpredictable amount left
+ * unremoved.
+ *
+ * @param path The path to recursively remove
+ * @return NSERROR_OK on success, or an error code on failure.
+ */
+nserror netsurf_recursive_rm(const char *path);
+
#endif
diff --git a/utils/filename.c b/utils/filename.c
index f0e1bb0f5..346fa85cc 100644
--- a/utils/filename.c
+++ b/utils/filename.c
@@ -29,10 +29,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
+#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include "utils/dirent.h"
+#include "utils/errors.h"
+#include "utils/file.h"
#include "utils/filename.h"
#include "utils/log.h"
#include "utils/utils.h"
@@ -55,7 +58,6 @@ static char filename_directory[256];
static struct directory *filename_create_directory(const char *prefix);
static bool filename_flush_directory(const char *folder, int depth);
-static bool filename_delete_recursive(char *folder);
/**
* Request a new, unique, filename.
@@ -96,7 +98,9 @@ const char *filename_request(void)
else
dir->high_used |= (1 << (i - 32));
- sprintf(filename_buffer, "%s%.2i", dir->prefix, i);
+ i = i % 99;
+
+ snprintf(filename_buffer, sizeof(filename_buffer), "%s%.2i", dir->prefix, i);
return filename_buffer;
}
@@ -270,6 +274,8 @@ bool filename_flush_directory(const char *folder, int depth)
}
parent = opendir(folder);
+ if (parent == NULL)
+ return false;
while ((entry = readdir(parent))) {
int written;
@@ -286,7 +292,12 @@ bool filename_flush_directory(const char *folder, int depth)
child[sizeof(child) - 1] = '\0';
}
+#if (defined(HAVE_DIRFD) && defined(HAVE_FSTATAT))
+ if (fstatat(dirfd(parent), entry->d_name, &statbuf,
+ AT_SYMLINK_NOFOLLOW) == -1) {
+#else
if (stat(child, &statbuf) == -1) {
+#endif
NSLOG(netsurf, INFO, "Unable to stat %s: %s", child,
strerror(errno));
continue;
@@ -352,14 +363,20 @@ bool filename_flush_directory(const char *folder, int depth)
/* delete or recurse */
if (del) {
- if (S_ISDIR(statbuf.st_mode))
- filename_delete_recursive(child);
-
- if (remove(child))
- NSLOG(netsurf, INFO, "Failed to remove '%s'",
- child);
- else
- changed = true;
+ if (S_ISDIR(statbuf.st_mode)) {
+ changed = (netsurf_recursive_rm(child) ==
+ NSERROR_OK);
+ } else {
+#if (defined(HAVE_DIRFD) && defined(HAVE_UNLINKAT))
+ if (unlinkat(dirfd(parent), entry->d_name, 0)) {
+#else
+ if (unlink(child)) {
+#endif
+ NSLOG(netsurf, INFO,
+ "Failed to remove '%s'", child);
+ } else
+ changed = true;
+ }
} else {
while (filename_flush_directory(child, depth + 1));
}
@@ -372,61 +389,6 @@ bool filename_flush_directory(const char *folder, int depth)
/**
- * Recursively deletes the contents of a directory
- *
- * \param folder the directory to delete
- * \return true on success, false otherwise
- */
-bool filename_delete_recursive(char *folder)
-{
- DIR *parent;
- struct dirent *entry;
- char child[256];
- struct stat statbuf;
-
- parent = opendir(folder);
-
- while ((entry = readdir(parent))) {
- int written;
-
- /* Ignore '.' and '..' */
- if (strcmp(entry->d_name, ".") == 0 ||
- strcmp(entry->d_name, "..") == 0)
- continue;
-
- written = snprintf(child, sizeof(child), "%s/%s",
- folder, entry->d_name);
- if (written == sizeof(child)) {
- child[sizeof(child) - 1] = '\0';
- }
-
- if (stat(child, &statbuf) == -1) {
- NSLOG(netsurf, INFO, "Unable to stat %s: %s", child,
- strerror(errno));
- continue;
- }
-
- if (S_ISDIR(statbuf.st_mode)) {
- if (!filename_delete_recursive(child)) {
- closedir(parent);
- return false;
- }
- }
-
- if (remove(child)) {
- NSLOG(netsurf, INFO, "Failed to remove '%s'", child);
- closedir(parent);
- return false;
- }
- }
-
- closedir(parent);
-
- return true;
-}
-
-
-/**
* Creates a new directory.
*
* \param prefix the prefix to use, or NULL to allocate a new one
diff --git a/utils/filepath.c b/utils/filepath.c
index 156ba2d75..b87e2bf0d 100644
--- a/utils/filepath.c
+++ b/utils/filepath.c
@@ -16,10 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Provides utility functions for finding readable files.
*
- * These functions are intended to make finding resource files more straightforward.
+ * These functions are intended to make finding resource files more
+ * straightforward.
*/
#include <sys/types.h>
@@ -37,7 +39,7 @@
#include "utils/filepath.h"
/** maximum number of elements in the resource vector */
-#define MAX_RESPATH 128
+#define MAX_RESPATH 128
/* exported interface documented in filepath.h */
char *filepath_vsfindfile(char *str, const char *format, va_list ap)
@@ -61,20 +63,21 @@ char *filepath_vsfindfile(char *str, const char *format, va_list ap)
}
realpathname = realpath(pathname, str);
-
+
free(pathname);
-
+
if (realpathname != NULL) {
/* sucessfully expanded pathname */
if (access(realpathname, R_OK) != 0) {
/* unable to read the file */
return NULL;
- }
+ }
}
return realpathname;
}
+
/* exported interface documented in filepath.h */
char *filepath_sfindfile(char *str, const char *format, ...)
{
@@ -88,6 +91,7 @@ char *filepath_sfindfile(char *str, const char *format, ...)
return ret;
}
+
/* exported interface documented in filepath.h */
char *filepath_findfile(const char *format, ...)
{
@@ -120,6 +124,7 @@ char *filepath_sfind(char **respathv, char *filepath, const char *filename)
return NULL;
}
+
/* exported interface documented in filepath.h */
char *filepath_find(char **respathv, const char *filename)
{
@@ -141,8 +146,13 @@ char *filepath_find(char **respathv, const char *filename)
return ret;
}
+
/* exported interface documented in filepath.h */
-char *filepath_sfinddef(char **respathv, char *filepath, const char *filename, const char *def)
+char *
+filepath_sfinddef(char **respathv,
+ char *filepath,
+ const char *filename,
+ const char *def)
{
char t[PATH_MAX];
char *ret;
@@ -159,9 +169,9 @@ char *filepath_sfinddef(char **respathv, char *filepath, const char *filename, c
snprintf(t, PATH_MAX, "%s/%s/%s", getenv("HOME"), def + 1, filename);
} else {
snprintf(t, PATH_MAX, "%s/%s", def, filename);
- }
+ }
if (realpath(t, ret) == NULL) {
- strcpy(ret, t);
+ strncpy(ret, t, PATH_MAX);
}
}
@@ -178,23 +188,41 @@ filepath_generate(char * const *pathv, const char * const *langv)
int langc = 0;
int respathc = 0;
struct stat dstat;
- char tmppath[PATH_MAX];
+ char *tmppath;
+ int tmppathlen;
respath = calloc(MAX_RESPATH, sizeof(char *));
while ((respath != NULL) &&
(pathv[pathc] != NULL)) {
- if ((stat(pathv[pathc], &dstat) == 0) &&
+ if ((stat(pathv[pathc], &dstat) == 0) &&
S_ISDIR(dstat.st_mode)) {
/* path element exists and is a directory */
langc = 0;
while (langv[langc] != NULL) {
- snprintf(tmppath, sizeof tmppath, "%s/%s", pathv[pathc],langv[langc]);
- if ((stat(tmppath, &dstat) == 0) &&
+ tmppathlen = snprintf(NULL,
+ 0,
+ "%s/%s",
+ pathv[pathc],
+ langv[langc]);
+ tmppath = malloc(tmppathlen + 1);
+ if (tmppath == NULL) {
+ break;
+ }
+ snprintf(tmppath,
+ tmppathlen + 1,
+ "%s/%s",
+ pathv[pathc],
+ langv[langc]);
+
+ if ((stat(tmppath, &dstat) == 0) &&
S_ISDIR(dstat.st_mode)) {
/* path element exists and is a directory */
- respath[respathc++] = strdup(tmppath);
+ respath[respathc++] = tmppath;
+ } else {
+ free(tmppath);
}
+
langc++;
}
respath[respathc++] = strdup(pathv[pathc]);
@@ -204,6 +232,7 @@ filepath_generate(char * const *pathv, const char * const *langv)
return respath;
}
+
/**
* expand ${} in a string into environment variables.
*
@@ -232,20 +261,20 @@ expand_path(const char *path, int pathlen)
explen = pathlen;
while (exp[cloop] != 0) {
- if ((exp[cloop] == '$') &&
+ if ((exp[cloop] == '$') &&
(exp[cloop + 1] == '{')) {
cstart = cloop;
cloop++;
- }
-
+ }
+
if ((cstart != -1) &&
(exp[cloop] == '}')) {
replen = cloop - cstart;
exp[cloop] = 0;
envv = getenv(exp + cstart + 2);
if (envv == NULL) {
- memmove(exp + cstart,
- exp + cloop + 1,
+ memmove(exp + cstart,
+ exp + cloop + 1,
explen - cloop);
explen -= replen;
} else {
@@ -257,8 +286,8 @@ expand_path(const char *path, int pathlen)
return NULL;
}
exp = tmp;
- memmove(exp + cstart + envlen,
- exp + cloop + 1,
+ memmove(exp + cstart + envlen,
+ exp + cloop + 1,
explen - cloop );
memmove(exp + cstart, envv, envlen);
explen += envlen - replen;
@@ -278,6 +307,7 @@ expand_path(const char *path, int pathlen)
return exp;
}
+
/* exported interface documented in filepath.h */
char **
filepath_path_to_strvec(const char *path)
@@ -315,12 +345,13 @@ filepath_path_to_strvec(const char *path)
/* check for termination */
if (*eend == 0)
break;
-
+
estart = eend;
}
return strvec;
}
+
/* exported interface documented in filepath.h */
void filepath_free_strvec(char **pathv)
{
@@ -331,4 +362,3 @@ void filepath_free_strvec(char **pathv)
}
free(pathv);
}
-
diff --git a/utils/filepath.h b/utils/filepath.h
index ad077e2ce..784264b33 100644
--- a/utils/filepath.h
+++ b/utils/filepath.h
@@ -69,10 +69,10 @@ char *filepath_findfile(const char *format, ...);
* normalised file name of the first acessible file or NULL if no file
* can be found in any of the resource paths.
*
- * @param respathv The resource path vector to iterate.
- * @param filepath The buffer to place the result in.
- * @param filename The filename of the resource to search for.
- * @return A pointer to filepath if a target is found or NULL if not.
+ * \param respathv The resource path vector to iterate.
+ * \param filepath The buffer to place the result in.
+ * \param filename The filename of the resource to search for.
+ * \return A pointer to filepath if a target is found or NULL if not.
*/
char *filepath_sfind(char **respathv, char *filepath, const char *filename);
@@ -93,6 +93,12 @@ char *filepath_find(char **respathv, const char *filename);
* is used as an additional path element to search, if that still
* fails the returned path is set to the concatination of the default
* path and the filename.
+ *
+ * \param respathv The resource path vector to iterate.
+ * \param filepath The buffer to place the result in. Must have space for PATH_MAX bytes.
+ * \param filename The filename of the resource to search for.
+ * \param def The default path to use
+ * \return A pointer to filepath if a target is found or the default if not
*/
char *filepath_sfinddef(char **respathv, char *filepath, const char *filename,
const char *def);
diff --git a/utils/hashmap.c b/utils/hashmap.c
new file mode 100644
index 000000000..4d9c78869
--- /dev/null
+++ b/utils/hashmap.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2020 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils/hashmap.h"
+
+/**
+ * The default number of buckets in the hashmaps we create.
+ */
+#define DEFAULT_HASHMAP_BUCKETS (4091)
+
+/**
+ * Hashmaps have chains of entries in buckets.
+ */
+typedef struct hashmap_entry_s {
+ struct hashmap_entry_s **prevptr;
+ struct hashmap_entry_s *next;
+ void *key;
+ void *value;
+ uint32_t key_hash;
+} hashmap_entry_t;
+
+/**
+ * The content of a hashmap
+ */
+struct hashmap_s {
+ /**
+ * The parameters to be used for this hashmap
+ */
+ hashmap_parameters_t *params;
+
+ /**
+ * The buckets for the hash chains
+ */
+ hashmap_entry_t **buckets;
+
+ /**
+ * The number of buckets in this map
+ */
+ uint32_t bucket_count;
+
+ /**
+ * The number of entries in this map
+ */
+ size_t entry_count;
+};
+
+/* Exported function, documented in hashmap.h */
+hashmap_t *
+hashmap_create(hashmap_parameters_t *params)
+{
+ hashmap_t *ret = malloc(sizeof(hashmap_t));
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ ret->params = params;
+ ret->bucket_count = DEFAULT_HASHMAP_BUCKETS;
+ ret->entry_count = 0;
+ ret->buckets = malloc(ret->bucket_count * sizeof(hashmap_entry_t *));
+
+ if (ret->buckets == NULL) {
+ free(ret);
+ return NULL;
+ }
+
+ memset(ret->buckets, 0, ret->bucket_count * sizeof(hashmap_entry_t *));
+
+ return ret;
+}
+
+/* Exported function, documented in hashmap.h */
+void
+hashmap_destroy(hashmap_t *hashmap)
+{
+ uint32_t bucket;
+ hashmap_entry_t *entry;
+
+ for (bucket = 0; bucket < hashmap->bucket_count; bucket++) {
+ for (entry = hashmap->buckets[bucket];
+ entry != NULL;) {
+ hashmap_entry_t *next = entry->next;
+ hashmap->params->value_destroy(entry->value);
+ hashmap->params->key_destroy(entry->key);
+ free(entry);
+ entry = next;
+ }
+ }
+
+ free(hashmap->buckets);
+ free(hashmap);
+}
+
+/* Exported function, documented in hashmap.h */
+void *
+hashmap_lookup(hashmap_t *hashmap, void *key)
+{
+ uint32_t hash = hashmap->params->key_hash(key);
+ hashmap_entry_t *entry = hashmap->buckets[hash % hashmap->bucket_count];
+
+ for(;entry != NULL; entry = entry->next) {
+ if (entry->key_hash == hash) {
+ if (hashmap->params->key_eq(key, entry->key)) {
+ return entry->value;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/* Exported function, documented in hashmap.h */
+void *
+hashmap_insert(hashmap_t *hashmap, void *key)
+{
+ uint32_t hash = hashmap->params->key_hash(key);
+ uint32_t bucket = hash % hashmap->bucket_count;
+ hashmap_entry_t *entry = hashmap->buckets[bucket];
+ void *new_key, *new_value;
+
+ for(;entry != NULL; entry = entry->next) {
+ if (entry->key_hash == hash) {
+ if (hashmap->params->key_eq(key, entry->key)) {
+ /* This key is already here */
+ new_key = hashmap->params->key_clone(key);
+ if (new_key == NULL) {
+ /* Allocation failed */
+ return NULL;
+ }
+ new_value = hashmap->params->value_alloc(entry->key);
+ if (new_value == NULL) {
+ /* Allocation failed */
+ hashmap->params->key_destroy(new_key);
+ return NULL;
+ }
+ hashmap->params->value_destroy(entry->value);
+ hashmap->params->key_destroy(entry->key);
+ entry->value = new_value;
+ entry->key = new_key;
+ return entry->value;
+ }
+ }
+ }
+
+ /* The key was not found in the map, so allocate a new entry */
+ entry = malloc(sizeof(*entry));
+
+ if (entry == NULL) {
+ return NULL;
+ }
+
+ memset(entry, 0, sizeof(*entry));
+
+ entry->key = hashmap->params->key_clone(key);
+ if (entry->key == NULL) {
+ goto err;
+ }
+ entry->key_hash = hash;
+
+ entry->value = hashmap->params->value_alloc(entry->key);
+ if (entry->value == NULL) {
+ goto err;
+ }
+
+ entry->prevptr = &(hashmap->buckets[bucket]);
+ entry->next = hashmap->buckets[bucket];
+ if (entry->next != NULL) {
+ entry->next->prevptr = &entry->next;
+ }
+
+ hashmap->buckets[bucket] = entry;
+
+ hashmap->entry_count++;
+
+ return entry->value;
+
+err:
+ if (entry->value != NULL)
+ hashmap->params->value_destroy(entry->value);
+ if (entry->key != NULL)
+ hashmap->params->key_destroy(entry->key);
+ free(entry);
+
+ return NULL;
+}
+
+/* Exported function, documented in hashmap.h */
+bool
+hashmap_remove(hashmap_t *hashmap, void *key)
+{
+ uint32_t hash = hashmap->params->key_hash(key);
+
+ hashmap_entry_t *entry = hashmap->buckets[hash % hashmap->bucket_count];
+
+ for(;entry != NULL; entry = entry->next) {
+ if (entry->key_hash == hash) {
+ if (hashmap->params->key_eq(key, entry->key)) {
+ hashmap->params->value_destroy(entry->value);
+ hashmap->params->key_destroy(entry->key);
+ if (entry->next != NULL) {
+ entry->next->prevptr = entry->prevptr;
+ }
+ *entry->prevptr = entry->next;
+ free(entry);
+ hashmap->entry_count--;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+/* Exported function, documented in hashmap.h */
+bool
+hashmap_iterate(hashmap_t *hashmap, hashmap_iteration_cb_t cb, void *ctx)
+{
+ for (uint32_t bucket = 0;
+ bucket < hashmap->bucket_count;
+ bucket++) {
+ for (hashmap_entry_t *entry = hashmap->buckets[bucket];
+ entry != NULL;
+ entry = entry->next) {
+ /* If the callback returns true, we early-exit */
+ if (cb(entry->key, entry->value, ctx))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Exported function, documented in hashmap.h */
+size_t
+hashmap_count(hashmap_t *hashmap)
+{
+ return hashmap->entry_count;
+}
diff --git a/utils/hashmap.h b/utils/hashmap.h
new file mode 100644
index 000000000..3968fd3fe
--- /dev/null
+++ b/utils/hashmap.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2020 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETSURF_HASHMAP_H
+#define NETSURF_HASHMAP_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/**
+ * Generic hashmap.
+ *
+ * Hashmaps take ownership of the keys inserted into them by means of a
+ * clone function in their parameters. They also manage the value memory
+ * directly.
+ */
+typedef struct hashmap_s hashmap_t;
+
+/**
+ * Key cloning function type
+ */
+typedef void* (*hashmap_key_clone_t)(void *);
+
+/**
+ * Key destructor function type
+ */
+typedef void (*hashmap_key_destroy_t)(void *);
+
+/**
+ * Key hashing function type
+ */
+typedef uint32_t (*hashmap_key_hash_t)(void *);
+
+/**
+ * Key comparison function type
+ */
+typedef bool (*hashmap_key_eq_t)(void *, void*);
+
+/**
+ * Value allocation function type
+ */
+typedef void* (*hashmap_value_alloc_t)(void *);
+
+/**
+ * Value destructor function type
+ */
+typedef void (*hashmap_value_destroy_t)(void *);
+
+/**
+ * Hashmap iteration callback function type.
+ *
+ * First parameter is the key, second is the value.
+ * The final parameter is the context pointer for the iteration.
+ *
+ * Return true to stop iterating early
+ */
+typedef bool (*hashmap_iteration_cb_t)(void *, void *, void *);
+
+/**
+ * Parameters for hashmaps
+ */
+typedef struct {
+ /**
+ * A function which when called will clone a key and give
+ * ownership of the returned object to the hashmap
+ */
+ hashmap_key_clone_t key_clone;
+
+ /**
+ * A function which when given a key will return its hash.
+ */
+ hashmap_key_hash_t key_hash;
+
+ /**
+ * A function to compare two keys and return if they are equal.
+ * Note: identity is not necessary, nor strict equality, so long
+ * as the function is a full equality model.
+ * (i.e. key1 == key2 => key2 == key1)
+ */
+ hashmap_key_eq_t key_eq;
+
+ /**
+ * A function which when called will destroy a key object
+ */
+ hashmap_key_destroy_t key_destroy;
+
+ /**
+ * A function which when called will allocate a value object
+ */
+ hashmap_value_alloc_t value_alloc;
+
+ /**
+ * A function which when called will destroy a value object
+ */
+ hashmap_value_destroy_t value_destroy;
+} hashmap_parameters_t;
+
+
+/**
+ * Create a hashmap
+ *
+ * The provided hashmap parameter table will be used for map operations
+ * which need to allocate/free etc.
+ *
+ * \param params The hashmap parameters for this map
+ */
+hashmap_t* hashmap_create(hashmap_parameters_t *params);
+
+/**
+ * Destroy a hashmap
+ *
+ * After this, all keys and values will have been destroyed and all memory
+ * associated with this hashmap will be invalidated.
+ *
+ * \param hashmap The hashmap to destroy
+ */
+void hashmap_destroy(hashmap_t *hashmap);
+
+/**
+ * Look up a key in a hashmap
+ *
+ * If the key has an associated value in the hashmap then the pointer to it
+ * is returned, otherwise NULL.
+ *
+ * \param hashmap The hashmap to look up the key inside
+ * \param key The key to look up in the hashmap
+ * \return A pointer to the value if found, NULL otherwise
+ */
+void* hashmap_lookup(hashmap_t *hashmap, void *key);
+
+/**
+ * Create an entry in a hashmap
+ *
+ * This creates a blank value using the parameters and then associates it with
+ * a clone of the given key, inserting it into the hashmap. If a value was
+ * present for the given key already, then it is destroyed first.
+ *
+ * NOTE: If allocation of the new value object fails, then any existing entry
+ * will be left alone, but NULL will be returned.
+ *
+ * \param hashmap The hashmap to insert into
+ * \param key The key to insert an entry for
+ * \return The value pointer for that key, or NULL if allocation failed.
+ */
+void *hashmap_insert(hashmap_t *hashmap, void *key);
+
+/**
+ * Remove an entry from the hashmap
+ *
+ * This will remove the entry for the given key from the hashmap
+ * If there is no such entry, this will safely do nothing.
+ * The value associated with the entry will be destroyed and so should not
+ * be used beyond calling this function.
+ *
+ * \param hashmap The hashmap to remove the entry from
+ * \param key The key to remove the entry for
+ * \return true if an entry was removed, false otherwise
+ */
+bool hashmap_remove(hashmap_t *hashmap, void *key);
+
+/**
+ * Iterate the hashmap
+ *
+ * For each key/value pair in the hashmap, call the callback passing in
+ * the key and value. During iteration you MUST NOT mutate the hashmap.
+ *
+ * \param hashmap The hashmap to iterate
+ * \param cb The callback for each key,value pair
+ * \param ctx The callback context
+ * \return Whether or not we stopped iteration early
+ */
+bool hashmap_iterate(hashmap_t *hashmap, hashmap_iteration_cb_t cb, void *ctx);
+
+/**
+ * Get the number of entries in this map
+ *
+ * \param hashmap The hashmap to retrieve the entry count from
+ * \return The number of entries in the hashmap
+ */
+size_t hashmap_count(hashmap_t *hashmap);
+
+#endif
diff --git a/utils/hashtable.c b/utils/hashtable.c
index 4935d6b3f..aa162cbc4 100644
--- a/utils/hashtable.c
+++ b/utils/hashtable.c
@@ -347,10 +347,12 @@ const char *hash_get(struct hash_table *ht, const char *key)
h = hash_string_fnv(key, &key_length);
c = h % ht->nchains;
- for (e = ht->chain[c]; e; e = e->next)
+ for (e = ht->chain[c]; e; e = e->next) {
if ((key_length == e->key_length) &&
- (memcmp(key, e->pairing, key_length) == 0))
+ (memcmp(key, e->pairing, key_length) == 0)) {
return e->pairing + key_length + 1;
+ }
+ }
return NULL;
}
diff --git a/utils/http.h b/utils/http.h
index 00caf8954..8da4f3fe3 100644
--- a/utils/http.h
+++ b/utils/http.h
@@ -27,6 +27,7 @@
#include "utils/errors.h"
+#include "utils/http/cache-control.h"
#include "utils/http/content-disposition.h"
#include "utils/http/content-type.h"
#include "utils/http/strict-transport-security.h"
diff --git a/utils/http/Makefile b/utils/http/Makefile
index f3bb765f0..b60f8f60a 100644
--- a/utils/http/Makefile
+++ b/utils/http/Makefile
@@ -1,7 +1,7 @@
# http utils sources
S_HTTP := challenge.c generics.c primitives.c parameter.c \
- content-disposition.c content-type.c \
+ cache-control.c content-disposition.c content-type.c \
strict-transport-security.c www-authenticate.c
S_HTTP := $(addprefix utils/http/,$(S_HTTP))
diff --git a/utils/http/cache-control.c b/utils/http/cache-control.c
new file mode 100644
index 000000000..44700821d
--- /dev/null
+++ b/utils/http/cache-control.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright 2019 John-Mark Bell <jmb@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <limits.h>
+#include <stdlib.h>
+
+#include "utils/corestrings.h"
+#include "utils/http.h"
+
+#include "utils/http/generics.h"
+#include "utils/http/primitives.h"
+
+/**
+ * Representation of a Cache-Control
+ */
+struct http_cache_control {
+ uint32_t max_age; /**< Max age (delta seconds) */
+ bool max_age_valid; /**< Whether max-age is valid */
+ bool no_cache; /**< Whether caching is forbidden */
+ bool no_store; /**< Whether persistent caching is forbidden */
+};
+
+/**
+ * Representation of a directive
+ */
+typedef struct http_directive {
+ http__item base;
+
+ lwc_string *name; /**< Parameter name */
+ lwc_string *value; /**< Parameter value (optional) */
+} http_directive;
+
+
+static void http_destroy_directive(http_directive *self)
+{
+ lwc_string_unref(self->name);
+ if (self->value != NULL) {
+ lwc_string_unref(self->value);
+ }
+ free(self);
+}
+
+static nserror http__parse_directive(const char **input,
+ http_directive **result)
+{
+ const char *pos = *input;
+ lwc_string *name;
+ lwc_string *value = NULL;
+ http_directive *directive;
+ nserror error;
+
+ /* token [ "=" ( token | quoted-string ) ] */
+
+ error = http__parse_token(&pos, &name);
+ if (error != NSERROR_OK)
+ return error;
+
+ http__skip_LWS(&pos);
+
+ if (*pos == '=') {
+ pos++;
+
+ http__skip_LWS(&pos);
+
+ if (*pos == '"')
+ error = http__parse_quoted_string(&pos, &value);
+ else
+ error = http__parse_token(&pos, &value);
+
+ if (error != NSERROR_OK) {
+ lwc_string_unref(name);
+ return error;
+ }
+ }
+
+ directive = malloc(sizeof(*directive));
+ if (directive == NULL) {
+ if (value != NULL) {
+ lwc_string_unref(value);
+ }
+ lwc_string_unref(name);
+ return NSERROR_NOMEM;
+ }
+
+ HTTP__ITEM_INIT(directive, NULL, http_destroy_directive);
+ directive->name = name;
+ directive->value = value;
+
+ *result = directive;
+ *input = pos;
+
+ return NSERROR_OK;
+}
+
+static void http_directive_list_destroy(http_directive *list)
+{
+ http__item_list_destroy(list);
+}
+
+static nserror http_directive_list_find_item(const http_directive *list,
+ lwc_string *name, lwc_string **value)
+{
+ bool match;
+
+ while (list != NULL) {
+ if (lwc_string_caseless_isequal(name, list->name,
+ &match) == lwc_error_ok && match)
+ break;
+
+ list = (http_directive *) list->base.next;
+ }
+
+ if (list == NULL)
+ return NSERROR_NOT_FOUND;
+
+ if (list->value != NULL) {
+ *value = lwc_string_ref(list->value);
+ } else {
+ *value = NULL;
+ }
+
+ return NSERROR_OK;
+}
+
+static const http_directive *http_directive_list_iterate(
+ const http_directive *cur,
+ lwc_string **name, lwc_string **value)
+{
+ if (cur == NULL)
+ return NULL;
+
+ *name = lwc_string_ref(cur->name);
+ if (cur->value != NULL) {
+ *value = lwc_string_ref(cur->value);
+ } else {
+ *value = NULL;
+ }
+
+ return (http_directive *) cur->base.next;
+}
+
+static uint32_t count(const http_directive *list, lwc_string *key)
+{
+ uint32_t count = 0;
+ bool match;
+
+ while (list != NULL) {
+ if (lwc_string_caseless_isequal(key, list->name,
+ &match) == lwc_error_ok && match) {
+ count++;
+ }
+
+ list = (http_directive *) list->base.next;
+ }
+
+ return count;
+}
+
+static bool check_duplicates(const http_directive *directives)
+{
+ bool result = true;
+ const http_directive *key = directives;
+
+ if (key == NULL) {
+ /* No directives, so there can't be any duplicates */
+ return true;
+ }
+
+ do {
+ lwc_string *name = NULL, *value = NULL;
+
+ key = http_directive_list_iterate(key, &name, &value);
+
+ result &= (count(directives, name) == 1);
+
+ lwc_string_unref(name);
+ if (value != NULL) {
+ lwc_string_unref(value);
+ }
+ } while (key != NULL);
+
+ return result;
+}
+
+static nserror parse_max_age(lwc_string *value, uint32_t *result)
+{
+ const char *pos = lwc_string_data(value);
+ const char *end = pos + lwc_string_length(value);
+ uint32_t val = 0;
+
+ /* 1*DIGIT */
+
+ if (pos == end) {
+ /* Blank value */
+ return NSERROR_NOT_FOUND;
+ }
+
+ while (pos < end) {
+ if ('0' <= *pos && *pos <= '9') {
+ uint32_t nv = val * 10 + (*pos - '0');
+ if (nv < val) {
+ val = UINT_MAX;
+ } else {
+ val = nv;
+ }
+ } else {
+ /* Non-digit */
+ return NSERROR_NOT_FOUND;
+ }
+
+ pos++;
+ }
+
+ *result = val;
+
+ return NSERROR_OK;
+}
+
+/* See cache-control.h for documentation */
+nserror http_parse_cache_control(const char *header_value,
+ http_cache_control **result)
+{
+ const char *pos = header_value;
+ http_cache_control *cc;
+ http_directive *first = NULL;
+ http_directive *directives = NULL;
+ lwc_string *value_str = NULL;
+ uint32_t max_age = 0;
+ bool max_age_valid = false;
+ bool no_cache = false;
+ bool no_store = false;
+ nserror error;
+
+ /* 1#cache-directive */
+
+ http__skip_LWS(&pos);
+
+ error = http__parse_directive(&pos, &first);
+ if (error != NSERROR_OK) {
+ return error;
+ }
+
+ http__skip_LWS(&pos);
+
+ if (*pos == ',') {
+ error = http__item_list_parse(&pos,
+ http__parse_directive, first, &directives);
+ if (error != NSERROR_OK) {
+ if (directives != NULL) {
+ http_directive_list_destroy(directives);
+ }
+ return error;
+ }
+ } else {
+ directives = first;
+ }
+
+ /* Each directive must only appear once */
+ if (check_duplicates(directives) == false) {
+ http_directive_list_destroy(directives);
+ return NSERROR_NOT_FOUND;
+ }
+
+ /* Find max-age */
+ error = http_directive_list_find_item(directives,
+ corestring_lwc_max_age, &value_str);
+ if (error == NSERROR_OK && value_str != NULL) {
+ error = parse_max_age(value_str, &max_age);
+ max_age_valid = (error == NSERROR_OK);
+ lwc_string_unref(value_str);
+ }
+
+ /* Find no-cache */
+ error = http_directive_list_find_item(directives,
+ corestring_lwc_no_cache, &value_str);
+ if (error == NSERROR_OK) {
+ no_cache = true;
+ if (value_str != NULL) {
+ lwc_string_unref(value_str);
+ }
+ }
+
+ /* Find no-store */
+ error = http_directive_list_find_item(directives,
+ corestring_lwc_no_store, &value_str);
+ if (error == NSERROR_OK) {
+ no_store = true;
+ if (value_str != NULL) {
+ lwc_string_unref(value_str);
+ }
+ }
+
+ http_directive_list_destroy(directives);
+
+ cc = malloc(sizeof(*cc));
+ if (cc == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ cc->max_age = max_age;
+ cc->max_age_valid = max_age_valid;
+ cc->no_cache = no_cache;
+ cc->no_store = no_store;
+
+ *result = cc;
+
+ return NSERROR_OK;
+}
+
+/* See cache-control.h for documentation */
+void http_cache_control_destroy(http_cache_control *victim)
+{
+ free(victim);
+}
+
+/* See cache-control.h for documentation */
+bool http_cache_control_has_max_age(http_cache_control *cc)
+{
+ return cc->max_age_valid;
+}
+
+/* See cache-control.h for documentation */
+uint32_t http_cache_control_max_age(http_cache_control *cc)
+{
+ return cc->max_age;
+}
+
+/* See cache-control.h for documentation */
+bool http_cache_control_no_cache(http_cache_control *cc)
+{
+ return cc->no_cache;
+}
+
+/* See cache-control.h for documentation */
+bool http_cache_control_no_store(http_cache_control *cc)
+{
+ return cc->no_store;
+}
diff --git a/utils/http/cache-control.h b/utils/http/cache-control.h
new file mode 100644
index 000000000..945cfcec0
--- /dev/null
+++ b/utils/http/cache-control.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2019 John-Mark Bell <jmb@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETSURF_UTILS_HTTP_CACHE_CONTROL_H_
+#define NETSURF_UTILS_HTTP_CACHE_CONTROL_H_
+
+#include <libwapcaplet/libwapcaplet.h>
+
+typedef struct http_cache_control http_cache_control;
+
+/**
+ * Parse an HTTP Cache-Control header value
+ *
+ * \param header_value Header value to parse
+ * \param result Pointer to location to receive result
+ * \return NSERROR_OK on success,
+ * NSERROR_NOMEM on memory exhaustion,
+ * appropriate error otherwise
+ */
+nserror http_parse_cache_control(const char *header_value,
+ http_cache_control **result);
+
+/**
+ * Destroy a cache_control object
+ *
+ * \param victim Object to destroy
+ */
+void http_cache_control_destroy(http_cache_control *victim);
+
+/**
+ * Determine if a valid max-age directive is present
+ *
+ * \param cc Object to inspect
+ * \return Whether max-age is valid
+ */
+bool http_cache_control_has_max_age(http_cache_control *cc);
+
+/**
+ * Get the value of a cache control's max-age
+ *
+ * \param cc Object to inspect
+ * \return Max age, in delta-seconds
+ */
+uint32_t http_cache_control_max_age(http_cache_control *cc);
+
+/**
+ * Get the value of a cache control's no-cache flag
+ *
+ * \param cc Object to inspect
+ * \return Whether caching is forbidden
+ */
+bool http_cache_control_no_cache(http_cache_control *cc);
+
+/**
+ * Get the value of a cache control's no-store flag
+ *
+ * \param cc Object to inspect
+ * \return Whether persistent caching is forbidden
+ */
+bool http_cache_control_no_store(http_cache_control *cc);
+
+#endif
diff --git a/utils/idna-derived-props-gen.pl b/utils/idna-derived-props-gen.pl
deleted file mode 100644
index 515f62a40..000000000
--- a/utils/idna-derived-props-gen.pl
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/usr/bin/perl
-#
-# Copyright 2014 Chris Young <chris@unsatisfactorysoftware.co.uk>
-#
-# This file is part of NetSurf, http://www.netsurf-browser.org/
-#
-# NetSurf is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# NetSurf is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-print <<HEADER;
-/* This file is generated by idna-derived-props-gen.pl
- * DO NOT EDIT BY HAND
- */
-#ifndef _NETSURF_UTILS_IDNA_PROPS_H_
-#define _NETSURF_UTILS_IDNA_PROPS_H_
-
-typedef enum idna_property {
- IDNA_P_PVALID = 1,
- IDNA_P_CONTEXTJ = 2,
- IDNA_P_CONTEXTO = 3,
- IDNA_P_DISALLOWED = 4,
- IDNA_P_UNASSIGNED = 5
-} idna_property;
-
-typedef enum idna_unicode_jt {
- IDNA_UNICODE_JT_U = 0,
- IDNA_UNICODE_JT_C = 1,
- IDNA_UNICODE_JT_D = 2,
- IDNA_UNICODE_JT_R = 3,
- IDNA_UNICODE_JT_T = 4,
- IDNA_UNICODE_JT_L = 5
-} idna_unicode_jt;
-
-
-typedef struct idna_table {
- int32_t start;
- int32_t end;
- union p {
- idna_property property;
- idna_unicode_jt jt;
- } p;
-} idna_table;
-
-idna_table idna_derived[] = {
-HEADER
-
-open(CSVFILE, "idna-tables-5.2.0-properties.csv");
-$line = <CSVFILE>; # discard header line
-
-while($line = <CSVFILE>) {
- @items = split(/\,/, $line);
- @codepoints = split(/-/, $items[0]);
- if($#codepoints == 0) { $codepoints[1] = $codepoints[0]; }
- print "\t{ 0x" . $codepoints[0] . ", 0x" . $codepoints[1] . ", .p.property = IDNA_P_" . $items[1] . " },\n";
-}
-
-close(CSVFILE);
-
-print <<HEADER;
- { 0, 0, .p.property = 0}
-};
-
-idna_table idna_joiningtype[] = {
-HEADER
-
-
-open(TXTFILE, "DerivedJoiningType.txt");
-
-while($line = <TXTFILE>) {
- chop($line);
- if(substr($line, 0, 1) eq '#') {next;}
- if(length($line) == 0) {next;}
- @items = split(/;/, $line);
- @codepoints = split(/\./, $items[0]);
- if($#codepoints == 0) { $codepoints[2] = $codepoints[0]; }
- print "\t{ 0x" . $codepoints[0] . ", 0x" . $codepoints[2] . ", .p.jt = IDNA_UNICODE_JT_" . substr($items[1], 1, 1) . " },\n";
-}
-
-close(TXTFILE);
-
-print <<HEADER;
- { 0, 0, .p.jt = 0}
-};
-#endif
-HEADER
-
-
diff --git a/utils/idna-tables-5.2.0-properties.csv b/utils/idna-tables-5.2.0-properties.csv
deleted file mode 100644
index a74547bc9..000000000
--- a/utils/idna-tables-5.2.0-properties.csv
+++ /dev/null
@@ -1,2322 +0,0 @@
-Codepoint,Property,Description
-0000-002C,DISALLOWED,NULL..COMMA
-002D,PVALID,HYPHEN-MINUS
-002E-002F,DISALLOWED,FULL STOP..SOLIDUS
-0030-0039,PVALID,DIGIT ZERO..DIGIT NINE
-003A-0060,DISALLOWED,COLON..GRAVE ACCENT
-0061-007A,PVALID,LATIN SMALL LETTER A..LATIN SMALL LETTER Z
-007B-00B6,DISALLOWED,LEFT CURLY BRACKET..PILCROW SIGN
-00B7,CONTEXTO,MIDDLE DOT
-00B8-00DE,DISALLOWED,CEDILLA..LATIN CAPITAL LETTER THORN
-00DF-00F6,PVALID,LATIN SMALL LETTER SHARP S..LATIN SMALL LETTER O WITH DIAERESIS
-00F7,DISALLOWED,DIVISION SIGN
-00F8-00FF,PVALID,LATIN SMALL LETTER O WITH STROKE..LATIN SMALL LETTER Y WITH DIAERESIS
-0100,DISALLOWED,LATIN CAPITAL LETTER A WITH MACRON
-0101,PVALID,LATIN SMALL LETTER A WITH MACRON
-0102,DISALLOWED,LATIN CAPITAL LETTER A WITH BREVE
-0103,PVALID,LATIN SMALL LETTER A WITH BREVE
-0104,DISALLOWED,LATIN CAPITAL LETTER A WITH OGONEK
-0105,PVALID,LATIN SMALL LETTER A WITH OGONEK
-0106,DISALLOWED,LATIN CAPITAL LETTER C WITH ACUTE
-0107,PVALID,LATIN SMALL LETTER C WITH ACUTE
-0108,DISALLOWED,LATIN CAPITAL LETTER C WITH CIRCUMFLEX
-0109,PVALID,LATIN SMALL LETTER C WITH CIRCUMFLEX
-010A,DISALLOWED,LATIN CAPITAL LETTER C WITH DOT ABOVE
-010B,PVALID,LATIN SMALL LETTER C WITH DOT ABOVE
-010C,DISALLOWED,LATIN CAPITAL LETTER C WITH CARON
-010D,PVALID,LATIN SMALL LETTER C WITH CARON
-010E,DISALLOWED,LATIN CAPITAL LETTER D WITH CARON
-010F,PVALID,LATIN SMALL LETTER D WITH CARON
-0110,DISALLOWED,LATIN CAPITAL LETTER D WITH STROKE
-0111,PVALID,LATIN SMALL LETTER D WITH STROKE
-0112,DISALLOWED,LATIN CAPITAL LETTER E WITH MACRON
-0113,PVALID,LATIN SMALL LETTER E WITH MACRON
-0114,DISALLOWED,LATIN CAPITAL LETTER E WITH BREVE
-0115,PVALID,LATIN SMALL LETTER E WITH BREVE
-0116,DISALLOWED,LATIN CAPITAL LETTER E WITH DOT ABOVE
-0117,PVALID,LATIN SMALL LETTER E WITH DOT ABOVE
-0118,DISALLOWED,LATIN CAPITAL LETTER E WITH OGONEK
-0119,PVALID,LATIN SMALL LETTER E WITH OGONEK
-011A,DISALLOWED,LATIN CAPITAL LETTER E WITH CARON
-011B,PVALID,LATIN SMALL LETTER E WITH CARON
-011C,DISALLOWED,LATIN CAPITAL LETTER G WITH CIRCUMFLEX
-011D,PVALID,LATIN SMALL LETTER G WITH CIRCUMFLEX
-011E,DISALLOWED,LATIN CAPITAL LETTER G WITH BREVE
-011F,PVALID,LATIN SMALL LETTER G WITH BREVE
-0120,DISALLOWED,LATIN CAPITAL LETTER G WITH DOT ABOVE
-0121,PVALID,LATIN SMALL LETTER G WITH DOT ABOVE
-0122,DISALLOWED,LATIN CAPITAL LETTER G WITH CEDILLA
-0123,PVALID,LATIN SMALL LETTER G WITH CEDILLA
-0124,DISALLOWED,LATIN CAPITAL LETTER H WITH CIRCUMFLEX
-0125,PVALID,LATIN SMALL LETTER H WITH CIRCUMFLEX
-0126,DISALLOWED,LATIN CAPITAL LETTER H WITH STROKE
-0127,PVALID,LATIN SMALL LETTER H WITH STROKE
-0128,DISALLOWED,LATIN CAPITAL LETTER I WITH TILDE
-0129,PVALID,LATIN SMALL LETTER I WITH TILDE
-012A,DISALLOWED,LATIN CAPITAL LETTER I WITH MACRON
-012B,PVALID,LATIN SMALL LETTER I WITH MACRON
-012C,DISALLOWED,LATIN CAPITAL LETTER I WITH BREVE
-012D,PVALID,LATIN SMALL LETTER I WITH BREVE
-012E,DISALLOWED,LATIN CAPITAL LETTER I WITH OGONEK
-012F,PVALID,LATIN SMALL LETTER I WITH OGONEK
-0130,DISALLOWED,LATIN CAPITAL LETTER I WITH DOT ABOVE
-0131,PVALID,LATIN SMALL LETTER DOTLESS I
-0132-0134,DISALLOWED,LATIN CAPITAL LIGATURE IJ..LATIN CAPITAL LETTER J WITH CIRCUMFLEX
-0135,PVALID,LATIN SMALL LETTER J WITH CIRCUMFLEX
-0136,DISALLOWED,LATIN CAPITAL LETTER K WITH CEDILLA
-0137-0138,PVALID,LATIN SMALL LETTER K WITH CEDILLA..LATIN SMALL LETTER KRA
-0139,DISALLOWED,LATIN CAPITAL LETTER L WITH ACUTE
-013A,PVALID,LATIN SMALL LETTER L WITH ACUTE
-013B,DISALLOWED,LATIN CAPITAL LETTER L WITH CEDILLA
-013C,PVALID,LATIN SMALL LETTER L WITH CEDILLA
-013D,DISALLOWED,LATIN CAPITAL LETTER L WITH CARON
-013E,PVALID,LATIN SMALL LETTER L WITH CARON
-013F-0141,DISALLOWED,LATIN CAPITAL LETTER L WITH MIDDLE DOT..LATIN CAPITAL LETTER L WITH STROKE
-0142,PVALID,LATIN SMALL LETTER L WITH STROKE
-0143,DISALLOWED,LATIN CAPITAL LETTER N WITH ACUTE
-0144,PVALID,LATIN SMALL LETTER N WITH ACUTE
-0145,DISALLOWED,LATIN CAPITAL LETTER N WITH CEDILLA
-0146,PVALID,LATIN SMALL LETTER N WITH CEDILLA
-0147,DISALLOWED,LATIN CAPITAL LETTER N WITH CARON
-0148,PVALID,LATIN SMALL LETTER N WITH CARON
-0149-014A,DISALLOWED,LATIN SMALL LETTER N PRECEDED BY APOSTROPHE..LATIN CAPITAL LETTER ENG
-014B,PVALID,LATIN SMALL LETTER ENG
-014C,DISALLOWED,LATIN CAPITAL LETTER O WITH MACRON
-014D,PVALID,LATIN SMALL LETTER O WITH MACRON
-014E,DISALLOWED,LATIN CAPITAL LETTER O WITH BREVE
-014F,PVALID,LATIN SMALL LETTER O WITH BREVE
-0150,DISALLOWED,LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
-0151,PVALID,LATIN SMALL LETTER O WITH DOUBLE ACUTE
-0152,DISALLOWED,LATIN CAPITAL LIGATURE OE
-0153,PVALID,LATIN SMALL LIGATURE OE
-0154,DISALLOWED,LATIN CAPITAL LETTER R WITH ACUTE
-0155,PVALID,LATIN SMALL LETTER R WITH ACUTE
-0156,DISALLOWED,LATIN CAPITAL LETTER R WITH CEDILLA
-0157,PVALID,LATIN SMALL LETTER R WITH CEDILLA
-0158,DISALLOWED,LATIN CAPITAL LETTER R WITH CARON
-0159,PVALID,LATIN SMALL LETTER R WITH CARON
-015A,DISALLOWED,LATIN CAPITAL LETTER S WITH ACUTE
-015B,PVALID,LATIN SMALL LETTER S WITH ACUTE
-015C,DISALLOWED,LATIN CAPITAL LETTER S WITH CIRCUMFLEX
-015D,PVALID,LATIN SMALL LETTER S WITH CIRCUMFLEX
-015E,DISALLOWED,LATIN CAPITAL LETTER S WITH CEDILLA
-015F,PVALID,LATIN SMALL LETTER S WITH CEDILLA
-0160,DISALLOWED,LATIN CAPITAL LETTER S WITH CARON
-0161,PVALID,LATIN SMALL LETTER S WITH CARON
-0162,DISALLOWED,LATIN CAPITAL LETTER T WITH CEDILLA
-0163,PVALID,LATIN SMALL LETTER T WITH CEDILLA
-0164,DISALLOWED,LATIN CAPITAL LETTER T WITH CARON
-0165,PVALID,LATIN SMALL LETTER T WITH CARON
-0166,DISALLOWED,LATIN CAPITAL LETTER T WITH STROKE
-0167,PVALID,LATIN SMALL LETTER T WITH STROKE
-0168,DISALLOWED,LATIN CAPITAL LETTER U WITH TILDE
-0169,PVALID,LATIN SMALL LETTER U WITH TILDE
-016A,DISALLOWED,LATIN CAPITAL LETTER U WITH MACRON
-016B,PVALID,LATIN SMALL LETTER U WITH MACRON
-016C,DISALLOWED,LATIN CAPITAL LETTER U WITH BREVE
-016D,PVALID,LATIN SMALL LETTER U WITH BREVE
-016E,DISALLOWED,LATIN CAPITAL LETTER U WITH RING ABOVE
-016F,PVALID,LATIN SMALL LETTER U WITH RING ABOVE
-0170,DISALLOWED,LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
-0171,PVALID,LATIN SMALL LETTER U WITH DOUBLE ACUTE
-0172,DISALLOWED,LATIN CAPITAL LETTER U WITH OGONEK
-0173,PVALID,LATIN SMALL LETTER U WITH OGONEK
-0174,DISALLOWED,LATIN CAPITAL LETTER W WITH CIRCUMFLEX
-0175,PVALID,LATIN SMALL LETTER W WITH CIRCUMFLEX
-0176,DISALLOWED,LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
-0177,PVALID,LATIN SMALL LETTER Y WITH CIRCUMFLEX
-0178-0179,DISALLOWED,LATIN CAPITAL LETTER Y WITH DIAERESIS..LATIN CAPITAL LETTER Z WITH ACUTE
-017A,PVALID,LATIN SMALL LETTER Z WITH ACUTE
-017B,DISALLOWED,LATIN CAPITAL LETTER Z WITH DOT ABOVE
-017C,PVALID,LATIN SMALL LETTER Z WITH DOT ABOVE
-017D,DISALLOWED,LATIN CAPITAL LETTER Z WITH CARON
-017E,PVALID,LATIN SMALL LETTER Z WITH CARON
-017F,DISALLOWED,LATIN SMALL LETTER LONG S
-0180,PVALID,LATIN SMALL LETTER B WITH STROKE
-0181-0182,DISALLOWED,LATIN CAPITAL LETTER B WITH HOOK..LATIN CAPITAL LETTER B WITH TOPBAR
-0183,PVALID,LATIN SMALL LETTER B WITH TOPBAR
-0184,DISALLOWED,LATIN CAPITAL LETTER TONE SIX
-0185,PVALID,LATIN SMALL LETTER TONE SIX
-0186-0187,DISALLOWED,LATIN CAPITAL LETTER OPEN O..LATIN CAPITAL LETTER C WITH HOOK
-0188,PVALID,LATIN SMALL LETTER C WITH HOOK
-0189-018B,DISALLOWED,LATIN CAPITAL LETTER AFRICAN D..LATIN CAPITAL LETTER D WITH TOPBAR
-018C-018D,PVALID,LATIN SMALL LETTER D WITH TOPBAR..LATIN SMALL LETTER TURNED DELTA
-018E-0191,DISALLOWED,LATIN CAPITAL LETTER REVERSED E..LATIN CAPITAL LETTER F WITH HOOK
-0192,PVALID,LATIN SMALL LETTER F WITH HOOK
-0193-0194,DISALLOWED,LATIN CAPITAL LETTER G WITH HOOK..LATIN CAPITAL LETTER GAMMA
-0195,PVALID,LATIN SMALL LETTER HV
-0196-0198,DISALLOWED,LATIN CAPITAL LETTER IOTA..LATIN CAPITAL LETTER K WITH HOOK
-0199-019B,PVALID,LATIN SMALL LETTER K WITH HOOK..LATIN SMALL LETTER LAMBDA WITH STROKE
-019C-019D,DISALLOWED,LATIN CAPITAL LETTER TURNED M..LATIN CAPITAL LETTER N WITH LEFT HOOK
-019E,PVALID,LATIN SMALL LETTER N WITH LONG RIGHT LEG
-019F-01A0,DISALLOWED,LATIN CAPITAL LETTER O WITH MIDDLE TILDE..LATIN CAPITAL LETTER O WITH HORN
-01A1,PVALID,LATIN SMALL LETTER O WITH HORN
-01A2,DISALLOWED,LATIN CAPITAL LETTER OI
-01A3,PVALID,LATIN SMALL LETTER OI
-01A4,DISALLOWED,LATIN CAPITAL LETTER P WITH HOOK
-01A5,PVALID,LATIN SMALL LETTER P WITH HOOK
-01A6-01A7,DISALLOWED,LATIN LETTER YR..LATIN CAPITAL LETTER TONE TWO
-01A8,PVALID,LATIN SMALL LETTER TONE TWO
-01A9,DISALLOWED,LATIN CAPITAL LETTER ESH
-01AA-01AB,PVALID,LATIN LETTER REVERSED ESH LOOP..LATIN SMALL LETTER T WITH PALATAL HOOK
-01AC,DISALLOWED,LATIN CAPITAL LETTER T WITH HOOK
-01AD,PVALID,LATIN SMALL LETTER T WITH HOOK
-01AE-01AF,DISALLOWED,LATIN CAPITAL LETTER T WITH RETROFLEX HOOK..LATIN CAPITAL LETTER U WITH HORN
-01B0,PVALID,LATIN SMALL LETTER U WITH HORN
-01B1-01B3,DISALLOWED,LATIN CAPITAL LETTER UPSILON..LATIN CAPITAL LETTER Y WITH HOOK
-01B4,PVALID,LATIN SMALL LETTER Y WITH HOOK
-01B5,DISALLOWED,LATIN CAPITAL LETTER Z WITH STROKE
-01B6,PVALID,LATIN SMALL LETTER Z WITH STROKE
-01B7-01B8,DISALLOWED,LATIN CAPITAL LETTER EZH..LATIN CAPITAL LETTER EZH REVERSED
-01B9-01BB,PVALID,LATIN SMALL LETTER EZH REVERSED..LATIN LETTER TWO WITH STROKE
-01BC,DISALLOWED,LATIN CAPITAL LETTER TONE FIVE
-01BD-01C3,PVALID,LATIN SMALL LETTER TONE FIVE..LATIN LETTER RETROFLEX CLICK
-01C4-01CD,DISALLOWED,LATIN CAPITAL LETTER DZ WITH CARON..LATIN CAPITAL LETTER A WITH CARON
-01CE,PVALID,LATIN SMALL LETTER A WITH CARON
-01CF,DISALLOWED,LATIN CAPITAL LETTER I WITH CARON
-01D0,PVALID,LATIN SMALL LETTER I WITH CARON
-01D1,DISALLOWED,LATIN CAPITAL LETTER O WITH CARON
-01D2,PVALID,LATIN SMALL LETTER O WITH CARON
-01D3,DISALLOWED,LATIN CAPITAL LETTER U WITH CARON
-01D4,PVALID,LATIN SMALL LETTER U WITH CARON
-01D5,DISALLOWED,LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON
-01D6,PVALID,LATIN SMALL LETTER U WITH DIAERESIS AND MACRON
-01D7,DISALLOWED,LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE
-01D8,PVALID,LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE
-01D9,DISALLOWED,LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON
-01DA,PVALID,LATIN SMALL LETTER U WITH DIAERESIS AND CARON
-01DB,DISALLOWED,LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE
-01DC-01DD,PVALID,LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE..LATIN SMALL LETTER TURNED E
-01DE,DISALLOWED,LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON
-01DF,PVALID,LATIN SMALL LETTER A WITH DIAERESIS AND MACRON
-01E0,DISALLOWED,LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON
-01E1,PVALID,LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON
-01E2,DISALLOWED,LATIN CAPITAL LETTER AE WITH MACRON
-01E3,PVALID,LATIN SMALL LETTER AE WITH MACRON
-01E4,DISALLOWED,LATIN CAPITAL LETTER G WITH STROKE
-01E5,PVALID,LATIN SMALL LETTER G WITH STROKE
-01E6,DISALLOWED,LATIN CAPITAL LETTER G WITH CARON
-01E7,PVALID,LATIN SMALL LETTER G WITH CARON
-01E8,DISALLOWED,LATIN CAPITAL LETTER K WITH CARON
-01E9,PVALID,LATIN SMALL LETTER K WITH CARON
-01EA,DISALLOWED,LATIN CAPITAL LETTER O WITH OGONEK
-01EB,PVALID,LATIN SMALL LETTER O WITH OGONEK
-01EC,DISALLOWED,LATIN CAPITAL LETTER O WITH OGONEK AND MACRON
-01ED,PVALID,LATIN SMALL LETTER O WITH OGONEK AND MACRON
-01EE,DISALLOWED,LATIN CAPITAL LETTER EZH WITH CARON
-01EF-01F0,PVALID,LATIN SMALL LETTER EZH WITH CARON..LATIN SMALL LETTER J WITH CARON
-01F1-01F4,DISALLOWED,LATIN CAPITAL LETTER DZ..LATIN CAPITAL LETTER G WITH ACUTE
-01F5,PVALID,LATIN SMALL LETTER G WITH ACUTE
-01F6-01F8,DISALLOWED,LATIN CAPITAL LETTER HWAIR..LATIN CAPITAL LETTER N WITH GRAVE
-01F9,PVALID,LATIN SMALL LETTER N WITH GRAVE
-01FA,DISALLOWED,LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE
-01FB,PVALID,LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE
-01FC,DISALLOWED,LATIN CAPITAL LETTER AE WITH ACUTE
-01FD,PVALID,LATIN SMALL LETTER AE WITH ACUTE
-01FE,DISALLOWED,LATIN CAPITAL LETTER O WITH STROKE AND ACUTE
-01FF,PVALID,LATIN SMALL LETTER O WITH STROKE AND ACUTE
-0200,DISALLOWED,LATIN CAPITAL LETTER A WITH DOUBLE GRAVE
-0201,PVALID,LATIN SMALL LETTER A WITH DOUBLE GRAVE
-0202,DISALLOWED,LATIN CAPITAL LETTER A WITH INVERTED BREVE
-0203,PVALID,LATIN SMALL LETTER A WITH INVERTED BREVE
-0204,DISALLOWED,LATIN CAPITAL LETTER E WITH DOUBLE GRAVE
-0205,PVALID,LATIN SMALL LETTER E WITH DOUBLE GRAVE
-0206,DISALLOWED,LATIN CAPITAL LETTER E WITH INVERTED BREVE
-0207,PVALID,LATIN SMALL LETTER E WITH INVERTED BREVE
-0208,DISALLOWED,LATIN CAPITAL LETTER I WITH DOUBLE GRAVE
-0209,PVALID,LATIN SMALL LETTER I WITH DOUBLE GRAVE
-020A,DISALLOWED,LATIN CAPITAL LETTER I WITH INVERTED BREVE
-020B,PVALID,LATIN SMALL LETTER I WITH INVERTED BREVE
-020C,DISALLOWED,LATIN CAPITAL LETTER O WITH DOUBLE GRAVE
-020D,PVALID,LATIN SMALL LETTER O WITH DOUBLE GRAVE
-020E,DISALLOWED,LATIN CAPITAL LETTER O WITH INVERTED BREVE
-020F,PVALID,LATIN SMALL LETTER O WITH INVERTED BREVE
-0210,DISALLOWED,LATIN CAPITAL LETTER R WITH DOUBLE GRAVE
-0211,PVALID,LATIN SMALL LETTER R WITH DOUBLE GRAVE
-0212,DISALLOWED,LATIN CAPITAL LETTER R WITH INVERTED BREVE
-0213,PVALID,LATIN SMALL LETTER R WITH INVERTED BREVE
-0214,DISALLOWED,LATIN CAPITAL LETTER U WITH DOUBLE GRAVE
-0215,PVALID,LATIN SMALL LETTER U WITH DOUBLE GRAVE
-0216,DISALLOWED,LATIN CAPITAL LETTER U WITH INVERTED BREVE
-0217,PVALID,LATIN SMALL LETTER U WITH INVERTED BREVE
-0218,DISALLOWED,LATIN CAPITAL LETTER S WITH COMMA BELOW
-0219,PVALID,LATIN SMALL LETTER S WITH COMMA BELOW
-021A,DISALLOWED,LATIN CAPITAL LETTER T WITH COMMA BELOW
-021B,PVALID,LATIN SMALL LETTER T WITH COMMA BELOW
-021C,DISALLOWED,LATIN CAPITAL LETTER YOGH
-021D,PVALID,LATIN SMALL LETTER YOGH
-021E,DISALLOWED,LATIN CAPITAL LETTER H WITH CARON
-021F,PVALID,LATIN SMALL LETTER H WITH CARON
-0220,DISALLOWED,LATIN CAPITAL LETTER N WITH LONG RIGHT LEG
-0221,PVALID,LATIN SMALL LETTER D WITH CURL
-0222,DISALLOWED,LATIN CAPITAL LETTER OU
-0223,PVALID,LATIN SMALL LETTER OU
-0224,DISALLOWED,LATIN CAPITAL LETTER Z WITH HOOK
-0225,PVALID,LATIN SMALL LETTER Z WITH HOOK
-0226,DISALLOWED,LATIN CAPITAL LETTER A WITH DOT ABOVE
-0227,PVALID,LATIN SMALL LETTER A WITH DOT ABOVE
-0228,DISALLOWED,LATIN CAPITAL LETTER E WITH CEDILLA
-0229,PVALID,LATIN SMALL LETTER E WITH CEDILLA
-022A,DISALLOWED,LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON
-022B,PVALID,LATIN SMALL LETTER O WITH DIAERESIS AND MACRON
-022C,DISALLOWED,LATIN CAPITAL LETTER O WITH TILDE AND MACRON
-022D,PVALID,LATIN SMALL LETTER O WITH TILDE AND MACRON
-022E,DISALLOWED,LATIN CAPITAL LETTER O WITH DOT ABOVE
-022F,PVALID,LATIN SMALL LETTER O WITH DOT ABOVE
-0230,DISALLOWED,LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON
-0231,PVALID,LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON
-0232,DISALLOWED,LATIN CAPITAL LETTER Y WITH MACRON
-0233-0239,PVALID,LATIN SMALL LETTER Y WITH MACRON..LATIN SMALL LETTER QP DIGRAPH
-023A-023B,DISALLOWED,LATIN CAPITAL LETTER A WITH STROKE..LATIN CAPITAL LETTER C WITH STROKE
-023C,PVALID,LATIN SMALL LETTER C WITH STROKE
-023D-023E,DISALLOWED,LATIN CAPITAL LETTER L WITH BAR..LATIN CAPITAL LETTER T WITH DIAGONAL STROKE
-023F-0240,PVALID,LATIN SMALL LETTER S WITH SWASH TAIL..LATIN SMALL LETTER Z WITH SWASH TAIL
-0241,DISALLOWED,LATIN CAPITAL LETTER GLOTTAL STOP
-0242,PVALID,LATIN SMALL LETTER GLOTTAL STOP
-0243-0246,DISALLOWED,LATIN CAPITAL LETTER B WITH STROKE..LATIN CAPITAL LETTER E WITH STROKE
-0247,PVALID,LATIN SMALL LETTER E WITH STROKE
-0248,DISALLOWED,LATIN CAPITAL LETTER J WITH STROKE
-0249,PVALID,LATIN SMALL LETTER J WITH STROKE
-024A,DISALLOWED,LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL
-024B,PVALID,LATIN SMALL LETTER Q WITH HOOK TAIL
-024C,DISALLOWED,LATIN CAPITAL LETTER R WITH STROKE
-024D,PVALID,LATIN SMALL LETTER R WITH STROKE
-024E,DISALLOWED,LATIN CAPITAL LETTER Y WITH STROKE
-024F-02AF,PVALID,LATIN SMALL LETTER Y WITH STROKE..LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL
-02B0-02B8,DISALLOWED,MODIFIER LETTER SMALL H..MODIFIER LETTER SMALL Y
-02B9-02C1,PVALID,MODIFIER LETTER PRIME..MODIFIER LETTER REVERSED GLOTTAL STOP
-02C2-02C5,DISALLOWED,MODIFIER LETTER LEFT ARROWHEAD..MODIFIER LETTER DOWN ARROWHEAD
-02C6-02D1,PVALID,MODIFIER LETTER CIRCUMFLEX ACCENT..MODIFIER LETTER HALF TRIANGULAR COLON
-02D2-02EB,DISALLOWED,MODIFIER LETTER CENTRED RIGHT HALF RING..MODIFIER LETTER YANG DEPARTING TONE MARK
-02EC,PVALID,MODIFIER LETTER VOICING
-02ED,DISALLOWED,MODIFIER LETTER UNASPIRATED
-02EE,PVALID,MODIFIER LETTER DOUBLE APOSTROPHE
-02EF-02FF,DISALLOWED,MODIFIER LETTER LOW DOWN ARROWHEAD..MODIFIER LETTER LOW LEFT ARROW
-0300-033F,PVALID,COMBINING GRAVE ACCENT..COMBINING DOUBLE OVERLINE
-0340-0341,DISALLOWED,COMBINING GRAVE TONE MARK..COMBINING ACUTE TONE MARK
-0342,PVALID,COMBINING GREEK PERISPOMENI
-0343-0345,DISALLOWED,COMBINING GREEK KORONIS..COMBINING GREEK YPOGEGRAMMENI
-0346-034E,PVALID,COMBINING BRIDGE ABOVE..COMBINING UPWARDS ARROW BELOW
-034F,DISALLOWED,COMBINING GRAPHEME JOINER
-0350-036F,PVALID,COMBINING RIGHT ARROWHEAD ABOVE..COMBINING LATIN SMALL LETTER X
-0370,DISALLOWED,GREEK CAPITAL LETTER HETA
-0371,PVALID,GREEK SMALL LETTER HETA
-0372,DISALLOWED,GREEK CAPITAL LETTER ARCHAIC SAMPI
-0373,PVALID,GREEK SMALL LETTER ARCHAIC SAMPI
-0374,DISALLOWED,GREEK NUMERAL SIGN
-0375,CONTEXTO,GREEK LOWER NUMERAL SIGN
-0376,DISALLOWED,GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA
-0377,PVALID,GREEK SMALL LETTER PAMPHYLIAN DIGAMMA
-0378-0379,UNASSIGNED,<RESERVED>..<RESERVED>
-037A,DISALLOWED,GREEK YPOGEGRAMMENI
-037B-037D,PVALID,GREEK SMALL REVERSED LUNATE SIGMA SYMBOL..GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL
-037E,DISALLOWED,GREEK QUESTION MARK
-037F-0383,UNASSIGNED,<RESERVED>..<RESERVED>
-0384-038A,DISALLOWED,GREEK TONOS..GREEK CAPITAL LETTER IOTA WITH TONOS
-038B,UNASSIGNED,<RESERVED>
-038C,DISALLOWED,GREEK CAPITAL LETTER OMICRON WITH TONOS
-038D,UNASSIGNED,<RESERVED>
-038E-038F,DISALLOWED,GREEK CAPITAL LETTER UPSILON WITH TONOS..GREEK CAPITAL LETTER OMEGA WITH TONOS
-0390,PVALID,GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
-0391-03A1,DISALLOWED,GREEK CAPITAL LETTER ALPHA..GREEK CAPITAL LETTER RHO
-03A2,UNASSIGNED,<RESERVED>
-03A3-03AB,DISALLOWED,GREEK CAPITAL LETTER SIGMA..GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
-03AC-03CE,PVALID,GREEK SMALL LETTER ALPHA WITH TONOS..GREEK SMALL LETTER OMEGA WITH TONOS
-03CF-03D6,DISALLOWED,GREEK CAPITAL KAI SYMBOL..GREEK PI SYMBOL
-03D7,PVALID,GREEK KAI SYMBOL
-03D8,DISALLOWED,GREEK LETTER ARCHAIC KOPPA
-03D9,PVALID,GREEK SMALL LETTER ARCHAIC KOPPA
-03DA,DISALLOWED,GREEK LETTER STIGMA
-03DB,PVALID,GREEK SMALL LETTER STIGMA
-03DC,DISALLOWED,GREEK LETTER DIGAMMA
-03DD,PVALID,GREEK SMALL LETTER DIGAMMA
-03DE,DISALLOWED,GREEK LETTER KOPPA
-03DF,PVALID,GREEK SMALL LETTER KOPPA
-03E0,DISALLOWED,GREEK LETTER SAMPI
-03E1,PVALID,GREEK SMALL LETTER SAMPI
-03E2,DISALLOWED,COPTIC CAPITAL LETTER SHEI
-03E3,PVALID,COPTIC SMALL LETTER SHEI
-03E4,DISALLOWED,COPTIC CAPITAL LETTER FEI
-03E5,PVALID,COPTIC SMALL LETTER FEI
-03E6,DISALLOWED,COPTIC CAPITAL LETTER KHEI
-03E7,PVALID,COPTIC SMALL LETTER KHEI
-03E8,DISALLOWED,COPTIC CAPITAL LETTER HORI
-03E9,PVALID,COPTIC SMALL LETTER HORI
-03EA,DISALLOWED,COPTIC CAPITAL LETTER GANGIA
-03EB,PVALID,COPTIC SMALL LETTER GANGIA
-03EC,DISALLOWED,COPTIC CAPITAL LETTER SHIMA
-03ED,PVALID,COPTIC SMALL LETTER SHIMA
-03EE,DISALLOWED,COPTIC CAPITAL LETTER DEI
-03EF,PVALID,COPTIC SMALL LETTER DEI
-03F0-03F2,DISALLOWED,GREEK KAPPA SYMBOL..GREEK LUNATE SIGMA SYMBOL
-03F3,PVALID,GREEK LETTER YOT
-03F4-03F7,DISALLOWED,GREEK CAPITAL THETA SYMBOL..GREEK CAPITAL LETTER SHO
-03F8,PVALID,GREEK SMALL LETTER SHO
-03F9-03FA,DISALLOWED,GREEK CAPITAL LUNATE SIGMA SYMBOL..GREEK CAPITAL LETTER SAN
-03FB-03FC,PVALID,GREEK SMALL LETTER SAN..GREEK RHO WITH STROKE SYMBOL
-03FD-042F,DISALLOWED,GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL..CYRILLIC CAPITAL LETTER YA
-0430-045F,PVALID,CYRILLIC SMALL LETTER A..CYRILLIC SMALL LETTER DZHE
-0460,DISALLOWED,CYRILLIC CAPITAL LETTER OMEGA
-0461,PVALID,CYRILLIC SMALL LETTER OMEGA
-0462,DISALLOWED,CYRILLIC CAPITAL LETTER YAT
-0463,PVALID,CYRILLIC SMALL LETTER YAT
-0464,DISALLOWED,CYRILLIC CAPITAL LETTER IOTIFIED E
-0465,PVALID,CYRILLIC SMALL LETTER IOTIFIED E
-0466,DISALLOWED,CYRILLIC CAPITAL LETTER LITTLE YUS
-0467,PVALID,CYRILLIC SMALL LETTER LITTLE YUS
-0468,DISALLOWED,CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS
-0469,PVALID,CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS
-046A,DISALLOWED,CYRILLIC CAPITAL LETTER BIG YUS
-046B,PVALID,CYRILLIC SMALL LETTER BIG YUS
-046C,DISALLOWED,CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS
-046D,PVALID,CYRILLIC SMALL LETTER IOTIFIED BIG YUS
-046E,DISALLOWED,CYRILLIC CAPITAL LETTER KSI
-046F,PVALID,CYRILLIC SMALL LETTER KSI
-0470,DISALLOWED,CYRILLIC CAPITAL LETTER PSI
-0471,PVALID,CYRILLIC SMALL LETTER PSI
-0472,DISALLOWED,CYRILLIC CAPITAL LETTER FITA
-0473,PVALID,CYRILLIC SMALL LETTER FITA
-0474,DISALLOWED,CYRILLIC CAPITAL LETTER IZHITSA
-0475,PVALID,CYRILLIC SMALL LETTER IZHITSA
-0476,DISALLOWED,CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT
-0477,PVALID,CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT
-0478,DISALLOWED,CYRILLIC CAPITAL LETTER UK
-0479,PVALID,CYRILLIC SMALL LETTER UK
-047A,DISALLOWED,CYRILLIC CAPITAL LETTER ROUND OMEGA
-047B,PVALID,CYRILLIC SMALL LETTER ROUND OMEGA
-047C,DISALLOWED,CYRILLIC CAPITAL LETTER OMEGA WITH TITLO
-047D,PVALID,CYRILLIC SMALL LETTER OMEGA WITH TITLO
-047E,DISALLOWED,CYRILLIC CAPITAL LETTER OT
-047F,PVALID,CYRILLIC SMALL LETTER OT
-0480,DISALLOWED,CYRILLIC CAPITAL LETTER KOPPA
-0481,PVALID,CYRILLIC SMALL LETTER KOPPA
-0482,DISALLOWED,CYRILLIC THOUSANDS SIGN
-0483-0487,PVALID,COMBINING CYRILLIC TITLO..COMBINING CYRILLIC POKRYTIE
-0488-048A,DISALLOWED,COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..CYRILLIC CAPITAL LETTER SHORT I WITH TAIL
-048B,PVALID,CYRILLIC SMALL LETTER SHORT I WITH TAIL
-048C,DISALLOWED,CYRILLIC CAPITAL LETTER SEMISOFT SIGN
-048D,PVALID,CYRILLIC SMALL LETTER SEMISOFT SIGN
-048E,DISALLOWED,CYRILLIC CAPITAL LETTER ER WITH TICK
-048F,PVALID,CYRILLIC SMALL LETTER ER WITH TICK
-0490,DISALLOWED,CYRILLIC CAPITAL LETTER GHE WITH UPTURN
-0491,PVALID,CYRILLIC SMALL LETTER GHE WITH UPTURN
-0492,DISALLOWED,CYRILLIC CAPITAL LETTER GHE WITH STROKE
-0493,PVALID,CYRILLIC SMALL LETTER GHE WITH STROKE
-0494,DISALLOWED,CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK
-0495,PVALID,CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK
-0496,DISALLOWED,CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER
-0497,PVALID,CYRILLIC SMALL LETTER ZHE WITH DESCENDER
-0498,DISALLOWED,CYRILLIC CAPITAL LETTER ZE WITH DESCENDER
-0499,PVALID,CYRILLIC SMALL LETTER ZE WITH DESCENDER
-049A,DISALLOWED,CYRILLIC CAPITAL LETTER KA WITH DESCENDER
-049B,PVALID,CYRILLIC SMALL LETTER KA WITH DESCENDER
-049C,DISALLOWED,CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE
-049D,PVALID,CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE
-049E,DISALLOWED,CYRILLIC CAPITAL LETTER KA WITH STROKE
-049F,PVALID,CYRILLIC SMALL LETTER KA WITH STROKE
-04A0,DISALLOWED,CYRILLIC CAPITAL LETTER BASHKIR KA
-04A1,PVALID,CYRILLIC SMALL LETTER BASHKIR KA
-04A2,DISALLOWED,CYRILLIC CAPITAL LETTER EN WITH DESCENDER
-04A3,PVALID,CYRILLIC SMALL LETTER EN WITH DESCENDER
-04A4,DISALLOWED,CYRILLIC CAPITAL LIGATURE EN GHE
-04A5,PVALID,CYRILLIC SMALL LIGATURE EN GHE
-04A6,DISALLOWED,CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK
-04A7,PVALID,CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK
-04A8,DISALLOWED,CYRILLIC CAPITAL LETTER ABKHASIAN HA
-04A9,PVALID,CYRILLIC SMALL LETTER ABKHASIAN HA
-04AA,DISALLOWED,CYRILLIC CAPITAL LETTER ES WITH DESCENDER
-04AB,PVALID,CYRILLIC SMALL LETTER ES WITH DESCENDER
-04AC,DISALLOWED,CYRILLIC CAPITAL LETTER TE WITH DESCENDER
-04AD,PVALID,CYRILLIC SMALL LETTER TE WITH DESCENDER
-04AE,DISALLOWED,CYRILLIC CAPITAL LETTER STRAIGHT U
-04AF,PVALID,CYRILLIC SMALL LETTER STRAIGHT U
-04B0,DISALLOWED,CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE
-04B1,PVALID,CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE
-04B2,DISALLOWED,CYRILLIC CAPITAL LETTER HA WITH DESCENDER
-04B3,PVALID,CYRILLIC SMALL LETTER HA WITH DESCENDER
-04B4,DISALLOWED,CYRILLIC CAPITAL LIGATURE TE TSE
-04B5,PVALID,CYRILLIC SMALL LIGATURE TE TSE
-04B6,DISALLOWED,CYRILLIC CAPITAL LETTER CHE WITH DESCENDER
-04B7,PVALID,CYRILLIC SMALL LETTER CHE WITH DESCENDER
-04B8,DISALLOWED,CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE
-04B9,PVALID,CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE
-04BA,DISALLOWED,CYRILLIC CAPITAL LETTER SHHA
-04BB,PVALID,CYRILLIC SMALL LETTER SHHA
-04BC,DISALLOWED,CYRILLIC CAPITAL LETTER ABKHASIAN CHE
-04BD,PVALID,CYRILLIC SMALL LETTER ABKHASIAN CHE
-04BE,DISALLOWED,CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER
-04BF,PVALID,CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER
-04C0-04C1,DISALLOWED,CYRILLIC LETTER PALOCHKA..CYRILLIC CAPITAL LETTER ZHE WITH BREVE
-04C2,PVALID,CYRILLIC SMALL LETTER ZHE WITH BREVE
-04C3,DISALLOWED,CYRILLIC CAPITAL LETTER KA WITH HOOK
-04C4,PVALID,CYRILLIC SMALL LETTER KA WITH HOOK
-04C5,DISALLOWED,CYRILLIC CAPITAL LETTER EL WITH TAIL
-04C6,PVALID,CYRILLIC SMALL LETTER EL WITH TAIL
-04C7,DISALLOWED,CYRILLIC CAPITAL LETTER EN WITH HOOK
-04C8,PVALID,CYRILLIC SMALL LETTER EN WITH HOOK
-04C9,DISALLOWED,CYRILLIC CAPITAL LETTER EN WITH TAIL
-04CA,PVALID,CYRILLIC SMALL LETTER EN WITH TAIL
-04CB,DISALLOWED,CYRILLIC CAPITAL LETTER KHAKASSIAN CHE
-04CC,PVALID,CYRILLIC SMALL LETTER KHAKASSIAN CHE
-04CD,DISALLOWED,CYRILLIC CAPITAL LETTER EM WITH TAIL
-04CE-04CF,PVALID,CYRILLIC SMALL LETTER EM WITH TAIL..CYRILLIC SMALL LETTER PALOCHKA
-04D0,DISALLOWED,CYRILLIC CAPITAL LETTER A WITH BREVE
-04D1,PVALID,CYRILLIC SMALL LETTER A WITH BREVE
-04D2,DISALLOWED,CYRILLIC CAPITAL LETTER A WITH DIAERESIS
-04D3,PVALID,CYRILLIC SMALL LETTER A WITH DIAERESIS
-04D4,DISALLOWED,CYRILLIC CAPITAL LIGATURE A IE
-04D5,PVALID,CYRILLIC SMALL LIGATURE A IE
-04D6,DISALLOWED,CYRILLIC CAPITAL LETTER IE WITH BREVE
-04D7,PVALID,CYRILLIC SMALL LETTER IE WITH BREVE
-04D8,DISALLOWED,CYRILLIC CAPITAL LETTER SCHWA
-04D9,PVALID,CYRILLIC SMALL LETTER SCHWA
-04DA,DISALLOWED,CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS
-04DB,PVALID,CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS
-04DC,DISALLOWED,CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS
-04DD,PVALID,CYRILLIC SMALL LETTER ZHE WITH DIAERESIS
-04DE,DISALLOWED,CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS
-04DF,PVALID,CYRILLIC SMALL LETTER ZE WITH DIAERESIS
-04E0,DISALLOWED,CYRILLIC CAPITAL LETTER ABKHASIAN DZE
-04E1,PVALID,CYRILLIC SMALL LETTER ABKHASIAN DZE
-04E2,DISALLOWED,CYRILLIC CAPITAL LETTER I WITH MACRON
-04E3,PVALID,CYRILLIC SMALL LETTER I WITH MACRON
-04E4,DISALLOWED,CYRILLIC CAPITAL LETTER I WITH DIAERESIS
-04E5,PVALID,CYRILLIC SMALL LETTER I WITH DIAERESIS
-04E6,DISALLOWED,CYRILLIC CAPITAL LETTER O WITH DIAERESIS
-04E7,PVALID,CYRILLIC SMALL LETTER O WITH DIAERESIS
-04E8,DISALLOWED,CYRILLIC CAPITAL LETTER BARRED O
-04E9,PVALID,CYRILLIC SMALL LETTER BARRED O
-04EA,DISALLOWED,CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS
-04EB,PVALID,CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS
-04EC,DISALLOWED,CYRILLIC CAPITAL LETTER E WITH DIAERESIS
-04ED,PVALID,CYRILLIC SMALL LETTER E WITH DIAERESIS
-04EE,DISALLOWED,CYRILLIC CAPITAL LETTER U WITH MACRON
-04EF,PVALID,CYRILLIC SMALL LETTER U WITH MACRON
-04F0,DISALLOWED,CYRILLIC CAPITAL LETTER U WITH DIAERESIS
-04F1,PVALID,CYRILLIC SMALL LETTER U WITH DIAERESIS
-04F2,DISALLOWED,CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE
-04F3,PVALID,CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE
-04F4,DISALLOWED,CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS
-04F5,PVALID,CYRILLIC SMALL LETTER CHE WITH DIAERESIS
-04F6,DISALLOWED,CYRILLIC CAPITAL LETTER GHE WITH DESCENDER
-04F7,PVALID,CYRILLIC SMALL LETTER GHE WITH DESCENDER
-04F8,DISALLOWED,CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS
-04F9,PVALID,CYRILLIC SMALL LETTER YERU WITH DIAERESIS
-04FA,DISALLOWED,CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK
-04FB,PVALID,CYRILLIC SMALL LETTER GHE WITH STROKE AND HOOK
-04FC,DISALLOWED,CYRILLIC CAPITAL LETTER HA WITH HOOK
-04FD,PVALID,CYRILLIC SMALL LETTER HA WITH HOOK
-04FE,DISALLOWED,CYRILLIC CAPITAL LETTER HA WITH STROKE
-04FF,PVALID,CYRILLIC SMALL LETTER HA WITH STROKE
-0500,DISALLOWED,CYRILLIC CAPITAL LETTER KOMI DE
-0501,PVALID,CYRILLIC SMALL LETTER KOMI DE
-0502,DISALLOWED,CYRILLIC CAPITAL LETTER KOMI DJE
-0503,PVALID,CYRILLIC SMALL LETTER KOMI DJE
-0504,DISALLOWED,CYRILLIC CAPITAL LETTER KOMI ZJE
-0505,PVALID,CYRILLIC SMALL LETTER KOMI ZJE
-0506,DISALLOWED,CYRILLIC CAPITAL LETTER KOMI DZJE
-0507,PVALID,CYRILLIC SMALL LETTER KOMI DZJE
-0508,DISALLOWED,CYRILLIC CAPITAL LETTER KOMI LJE
-0509,PVALID,CYRILLIC SMALL LETTER KOMI LJE
-050A,DISALLOWED,CYRILLIC CAPITAL LETTER KOMI NJE
-050B,PVALID,CYRILLIC SMALL LETTER KOMI NJE
-050C,DISALLOWED,CYRILLIC CAPITAL LETTER KOMI SJE
-050D,PVALID,CYRILLIC SMALL LETTER KOMI SJE
-050E,DISALLOWED,CYRILLIC CAPITAL LETTER KOMI TJE
-050F,PVALID,CYRILLIC SMALL LETTER KOMI TJE
-0510,DISALLOWED,CYRILLIC CAPITAL LETTER REVERSED ZE
-0511,PVALID,CYRILLIC SMALL LETTER REVERSED ZE
-0512,DISALLOWED,CYRILLIC CAPITAL LETTER EL WITH HOOK
-0513,PVALID,CYRILLIC SMALL LETTER EL WITH HOOK
-0514,DISALLOWED,CYRILLIC CAPITAL LETTER LHA
-0515,PVALID,CYRILLIC SMALL LETTER LHA
-0516,DISALLOWED,CYRILLIC CAPITAL LETTER RHA
-0517,PVALID,CYRILLIC SMALL LETTER RHA
-0518,DISALLOWED,CYRILLIC CAPITAL LETTER YAE
-0519,PVALID,CYRILLIC SMALL LETTER YAE
-051A,DISALLOWED,CYRILLIC CAPITAL LETTER QA
-051B,PVALID,CYRILLIC SMALL LETTER QA
-051C,DISALLOWED,CYRILLIC CAPITAL LETTER WE
-051D,PVALID,CYRILLIC SMALL LETTER WE
-051E,DISALLOWED,CYRILLIC CAPITAL LETTER ALEUT KA
-051F,PVALID,CYRILLIC SMALL LETTER ALEUT KA
-0520,DISALLOWED,CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK
-0521,PVALID,CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK
-0522,DISALLOWED,CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK
-0523,PVALID,CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK
-0524,DISALLOWED,CYRILLIC CAPITAL LETTER PE WITH DESCENDER
-0525,PVALID,CYRILLIC SMALL LETTER PE WITH DESCENDER
-0526-0530,UNASSIGNED,<RESERVED>..<RESERVED>
-0531-0556,DISALLOWED,ARMENIAN CAPITAL LETTER AYB..ARMENIAN CAPITAL LETTER FEH
-0557-0558,UNASSIGNED,<RESERVED>..<RESERVED>
-0559,PVALID,ARMENIAN MODIFIER LETTER LEFT HALF RING
-055A-055F,DISALLOWED,ARMENIAN APOSTROPHE..ARMENIAN ABBREVIATION MARK
-0560,UNASSIGNED,<RESERVED>
-0561-0586,PVALID,ARMENIAN SMALL LETTER AYB..ARMENIAN SMALL LETTER FEH
-0587,DISALLOWED,ARMENIAN SMALL LIGATURE ECH YIWN
-0588,UNASSIGNED,<RESERVED>
-0589-058A,DISALLOWED,ARMENIAN FULL STOP..ARMENIAN HYPHEN
-058B-0590,UNASSIGNED,<RESERVED>..<RESERVED>
-0591-05BD,PVALID,HEBREW ACCENT ETNAHTA..HEBREW POINT METEG
-05BE,DISALLOWED,HEBREW PUNCTUATION MAQAF
-05BF,PVALID,HEBREW POINT RAFE
-05C0,DISALLOWED,HEBREW PUNCTUATION PASEQ
-05C1-05C2,PVALID,HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT
-05C3,DISALLOWED,HEBREW PUNCTUATION SOF PASUQ
-05C4-05C5,PVALID,HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT
-05C6,DISALLOWED,HEBREW PUNCTUATION NUN HAFUKHA
-05C7,PVALID,HEBREW POINT QAMATS QATAN
-05C8-05CF,UNASSIGNED,<RESERVED>..<RESERVED>
-05D0-05EA,PVALID,HEBREW LETTER ALEF..HEBREW LETTER TAV
-05EB-05EF,UNASSIGNED,<RESERVED>..<RESERVED>
-05F0-05F2,PVALID,HEBREW LIGATURE YIDDISH DOUBLE VAV..HEBREW LIGATURE YIDDISH DOUBLE YOD
-05F3-05F4,CONTEXTO,HEBREW PUNCTUATION GERESH..HEBREW PUNCTUATION GERSHAYIM
-05F5-05FF,UNASSIGNED,<RESERVED>..<RESERVED>
-0600-0603,DISALLOWED,ARABIC NUMBER SIGN..ARABIC SIGN SAFHA
-0604-0605,UNASSIGNED,<RESERVED>..<RESERVED>
-0606-060F,DISALLOWED,ARABIC-INDIC CUBE ROOT..ARABIC SIGN MISRA
-0610-061A,PVALID,ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA
-061B,DISALLOWED,ARABIC SEMICOLON
-061C-061D,UNASSIGNED,<RESERVED>..<RESERVED>
-061E-061F,DISALLOWED,ARABIC TRIPLE DOT PUNCTUATION MARK..ARABIC QUESTION MARK
-0620,UNASSIGNED,<RESERVED>
-0621-063F,PVALID,ARABIC LETTER HAMZA..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE
-0640,DISALLOWED,ARABIC TATWEEL
-0641-065E,PVALID,ARABIC LETTER FEH..ARABIC FATHA WITH TWO DOTS
-065F,UNASSIGNED,<RESERVED>
-0660-0669,CONTEXTO,ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE
-066A-066D,DISALLOWED,ARABIC PERCENT SIGN..ARABIC FIVE POINTED STAR
-066E-0674,PVALID,ARABIC LETTER DOTLESS BEH..ARABIC LETTER HIGH HAMZA
-0675-0678,DISALLOWED,ARABIC LETTER HIGH HAMZA ALEF..ARABIC LETTER HIGH HAMZA YEH
-0679-06D3,PVALID,ARABIC LETTER TTEH..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE
-06D4,DISALLOWED,ARABIC FULL STOP
-06D5-06DC,PVALID,ARABIC LETTER AE..ARABIC SMALL HIGH SEEN
-06DD-06DE,DISALLOWED,ARABIC END OF AYAH..ARABIC START OF RUB EL HIZB
-06DF-06E8,PVALID,ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH NOON
-06E9,DISALLOWED,ARABIC PLACE OF SAJDAH
-06EA-06EF,PVALID,ARABIC EMPTY CENTRE LOW STOP..ARABIC LETTER REH WITH INVERTED V
-06F0-06F9,CONTEXTO,EXTENDED ARABIC-INDIC DIGIT ZERO..EXTENDED ARABIC-INDIC DIGIT NINE
-06FA-06FF,PVALID,ARABIC LETTER SHEEN WITH DOT BELOW..ARABIC LETTER HEH WITH INVERTED V
-0700-070D,DISALLOWED,SYRIAC END OF PARAGRAPH..SYRIAC HARKLEAN ASTERISCUS
-070E,UNASSIGNED,<RESERVED>
-070F,DISALLOWED,SYRIAC ABBREVIATION MARK
-0710-074A,PVALID,SYRIAC LETTER ALAPH..SYRIAC BARREKH
-074B-074C,UNASSIGNED,<RESERVED>..<RESERVED>
-074D-07B1,PVALID,SYRIAC LETTER SOGDIAN ZHAIN..THAANA LETTER NAA
-07B2-07BF,UNASSIGNED,<RESERVED>..<RESERVED>
-07C0-07F5,PVALID,NKO DIGIT ZERO..NKO LOW TONE APOSTROPHE
-07F6-07FA,DISALLOWED,NKO SYMBOL OO DENNEN..NKO LAJANYALAN
-07FB-07FF,UNASSIGNED,<RESERVED>..<RESERVED>
-0800-082D,PVALID,SAMARITAN LETTER ALAF..SAMARITAN MARK NEQUDAA
-082E-082F,UNASSIGNED,<RESERVED>..<RESERVED>
-0830-083E,DISALLOWED,SAMARITAN PUNCTUATION NEQUDAA..SAMARITAN PUNCTUATION ANNAAU
-083F-08FF,UNASSIGNED,<RESERVED>..<RESERVED>
-0900-0939,PVALID,DEVANAGARI SIGN INVERTED CANDRABINDU..DEVANAGARI LETTER HA
-093A-093B,UNASSIGNED,<RESERVED>..<RESERVED>
-093C-094E,PVALID,DEVANAGARI SIGN NUKTA..DEVANAGARI VOWEL SIGN PRISHTHAMATRA E
-094F,UNASSIGNED,<RESERVED>
-0950-0955,PVALID,DEVANAGARI OM..DEVANAGARI VOWEL SIGN CANDRA LONG E
-0956-0957,UNASSIGNED,<RESERVED>..<RESERVED>
-0958-095F,DISALLOWED,DEVANAGARI LETTER QA..DEVANAGARI LETTER YYA
-0960-0963,PVALID,DEVANAGARI LETTER VOCALIC RR..DEVANAGARI VOWEL SIGN VOCALIC LL
-0964-0965,DISALLOWED,DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA
-0966-096F,PVALID,DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE
-0970,DISALLOWED,DEVANAGARI ABBREVIATION SIGN
-0971-0972,PVALID,DEVANAGARI SIGN HIGH SPACING DOT..DEVANAGARI LETTER CANDRA A
-0973-0978,UNASSIGNED,<RESERVED>..<RESERVED>
-0979-097F,PVALID,DEVANAGARI LETTER ZHA..DEVANAGARI LETTER BBA
-0980,UNASSIGNED,<RESERVED>
-0981-0983,PVALID,BENGALI SIGN CANDRABINDU..BENGALI SIGN VISARGA
-0984,UNASSIGNED,<RESERVED>
-0985-098C,PVALID,BENGALI LETTER A..BENGALI LETTER VOCALIC L
-098D-098E,UNASSIGNED,<RESERVED>..<RESERVED>
-098F-0990,PVALID,BENGALI LETTER E..BENGALI LETTER AI
-0991-0992,UNASSIGNED,<RESERVED>..<RESERVED>
-0993-09A8,PVALID,BENGALI LETTER O..BENGALI LETTER NA
-09A9,UNASSIGNED,<RESERVED>
-09AA-09B0,PVALID,BENGALI LETTER PA..BENGALI LETTER RA
-09B1,UNASSIGNED,<RESERVED>
-09B2,PVALID,BENGALI LETTER LA
-09B3-09B5,UNASSIGNED,<RESERVED>..<RESERVED>
-09B6-09B9,PVALID,BENGALI LETTER SHA..BENGALI LETTER HA
-09BA-09BB,UNASSIGNED,<RESERVED>..<RESERVED>
-09BC-09C4,PVALID,BENGALI SIGN NUKTA..BENGALI VOWEL SIGN VOCALIC RR
-09C5-09C6,UNASSIGNED,<RESERVED>..<RESERVED>
-09C7-09C8,PVALID,BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI
-09C9-09CA,UNASSIGNED,<RESERVED>..<RESERVED>
-09CB-09CE,PVALID,BENGALI VOWEL SIGN O..BENGALI LETTER KHANDA TA
-09CF-09D6,UNASSIGNED,<RESERVED>..<RESERVED>
-09D7,PVALID,BENGALI AU LENGTH MARK
-09D8-09DB,UNASSIGNED,<RESERVED>..<RESERVED>
-09DC-09DD,DISALLOWED,BENGALI LETTER RRA..BENGALI LETTER RHA
-09DE,UNASSIGNED,<RESERVED>
-09DF,DISALLOWED,BENGALI LETTER YYA
-09E0-09E3,PVALID,BENGALI LETTER VOCALIC RR..BENGALI VOWEL SIGN VOCALIC LL
-09E4-09E5,UNASSIGNED,<RESERVED>..<RESERVED>
-09E6-09F1,PVALID,BENGALI DIGIT ZERO..BENGALI LETTER RA WITH LOWER DIAGONAL
-09F2-09FB,DISALLOWED,BENGALI RUPEE MARK..BENGALI GANDA MARK
-09FC-0A00,UNASSIGNED,<RESERVED>..<RESERVED>
-0A01-0A03,PVALID,GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN VISARGA
-0A04,UNASSIGNED,<RESERVED>
-0A05-0A0A,PVALID,GURMUKHI LETTER A..GURMUKHI LETTER UU
-0A0B-0A0E,UNASSIGNED,<RESERVED>..<RESERVED>
-0A0F-0A10,PVALID,GURMUKHI LETTER EE..GURMUKHI LETTER AI
-0A11-0A12,UNASSIGNED,<RESERVED>..<RESERVED>
-0A13-0A28,PVALID,GURMUKHI LETTER OO..GURMUKHI LETTER NA
-0A29,UNASSIGNED,<RESERVED>
-0A2A-0A30,PVALID,GURMUKHI LETTER PA..GURMUKHI LETTER RA
-0A31,UNASSIGNED,<RESERVED>
-0A32,PVALID,GURMUKHI LETTER LA
-0A33,DISALLOWED,GURMUKHI LETTER LLA
-0A34,UNASSIGNED,<RESERVED>
-0A35,PVALID,GURMUKHI LETTER VA
-0A36,DISALLOWED,GURMUKHI LETTER SHA
-0A37,UNASSIGNED,<RESERVED>
-0A38-0A39,PVALID,GURMUKHI LETTER SA..GURMUKHI LETTER HA
-0A3A-0A3B,UNASSIGNED,<RESERVED>..<RESERVED>
-0A3C,PVALID,GURMUKHI SIGN NUKTA
-0A3D,UNASSIGNED,<RESERVED>
-0A3E-0A42,PVALID,GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN UU
-0A43-0A46,UNASSIGNED,<RESERVED>..<RESERVED>
-0A47-0A48,PVALID,GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI
-0A49-0A4A,UNASSIGNED,<RESERVED>..<RESERVED>
-0A4B-0A4D,PVALID,GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA
-0A4E-0A50,UNASSIGNED,<RESERVED>..<RESERVED>
-0A51,PVALID,GURMUKHI SIGN UDAAT
-0A52-0A58,UNASSIGNED,<RESERVED>..<RESERVED>
-0A59-0A5B,DISALLOWED,GURMUKHI LETTER KHHA..GURMUKHI LETTER ZA
-0A5C,PVALID,GURMUKHI LETTER RRA
-0A5D,UNASSIGNED,<RESERVED>
-0A5E,DISALLOWED,GURMUKHI LETTER FA
-0A5F-0A65,UNASSIGNED,<RESERVED>..<RESERVED>
-0A66-0A75,PVALID,GURMUKHI DIGIT ZERO..GURMUKHI SIGN YAKASH
-0A76-0A80,UNASSIGNED,<RESERVED>..<RESERVED>
-0A81-0A83,PVALID,GUJARATI SIGN CANDRABINDU..GUJARATI SIGN VISARGA
-0A84,UNASSIGNED,<RESERVED>
-0A85-0A8D,PVALID,GUJARATI LETTER A..GUJARATI VOWEL CANDRA E
-0A8E,UNASSIGNED,<RESERVED>
-0A8F-0A91,PVALID,GUJARATI LETTER E..GUJARATI VOWEL CANDRA O
-0A92,UNASSIGNED,<RESERVED>
-0A93-0AA8,PVALID,GUJARATI LETTER O..GUJARATI LETTER NA
-0AA9,UNASSIGNED,<RESERVED>
-0AAA-0AB0,PVALID,GUJARATI LETTER PA..GUJARATI LETTER RA
-0AB1,UNASSIGNED,<RESERVED>
-0AB2-0AB3,PVALID,GUJARATI LETTER LA..GUJARATI LETTER LLA
-0AB4,UNASSIGNED,<RESERVED>
-0AB5-0AB9,PVALID,GUJARATI LETTER VA..GUJARATI LETTER HA
-0ABA-0ABB,UNASSIGNED,<RESERVED>..<RESERVED>
-0ABC-0AC5,PVALID,GUJARATI SIGN NUKTA..GUJARATI VOWEL SIGN CANDRA E
-0AC6,UNASSIGNED,<RESERVED>
-0AC7-0AC9,PVALID,GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN CANDRA O
-0ACA,UNASSIGNED,<RESERVED>
-0ACB-0ACD,PVALID,GUJARATI VOWEL SIGN O..GUJARATI SIGN VIRAMA
-0ACE-0ACF,UNASSIGNED,<RESERVED>..<RESERVED>
-0AD0,PVALID,GUJARATI OM
-0AD1-0ADF,UNASSIGNED,<RESERVED>..<RESERVED>
-0AE0-0AE3,PVALID,GUJARATI LETTER VOCALIC RR..GUJARATI VOWEL SIGN VOCALIC LL
-0AE4-0AE5,UNASSIGNED,<RESERVED>..<RESERVED>
-0AE6-0AEF,PVALID,GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE
-0AF0,UNASSIGNED,<RESERVED>
-0AF1,DISALLOWED,GUJARATI RUPEE SIGN
-0AF2-0B00,UNASSIGNED,<RESERVED>..<RESERVED>
-0B01-0B03,PVALID,ORIYA SIGN CANDRABINDU..ORIYA SIGN VISARGA
-0B04,UNASSIGNED,<RESERVED>
-0B05-0B0C,PVALID,ORIYA LETTER A..ORIYA LETTER VOCALIC L
-0B0D-0B0E,UNASSIGNED,<RESERVED>..<RESERVED>
-0B0F-0B10,PVALID,ORIYA LETTER E..ORIYA LETTER AI
-0B11-0B12,UNASSIGNED,<RESERVED>..<RESERVED>
-0B13-0B28,PVALID,ORIYA LETTER O..ORIYA LETTER NA
-0B29,UNASSIGNED,<RESERVED>
-0B2A-0B30,PVALID,ORIYA LETTER PA..ORIYA LETTER RA
-0B31,UNASSIGNED,<RESERVED>
-0B32-0B33,PVALID,ORIYA LETTER LA..ORIYA LETTER LLA
-0B34,UNASSIGNED,<RESERVED>
-0B35-0B39,PVALID,ORIYA LETTER VA..ORIYA LETTER HA
-0B3A-0B3B,UNASSIGNED,<RESERVED>..<RESERVED>
-0B3C-0B44,PVALID,ORIYA SIGN NUKTA..ORIYA VOWEL SIGN VOCALIC RR
-0B45-0B46,UNASSIGNED,<RESERVED>..<RESERVED>
-0B47-0B48,PVALID,ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI
-0B49-0B4A,UNASSIGNED,<RESERVED>..<RESERVED>
-0B4B-0B4D,PVALID,ORIYA VOWEL SIGN O..ORIYA SIGN VIRAMA
-0B4E-0B55,UNASSIGNED,<RESERVED>..<RESERVED>
-0B56-0B57,PVALID,ORIYA AI LENGTH MARK..ORIYA AU LENGTH MARK
-0B58-0B5B,UNASSIGNED,<RESERVED>..<RESERVED>
-0B5C-0B5D,DISALLOWED,ORIYA LETTER RRA..ORIYA LETTER RHA
-0B5E,UNASSIGNED,<RESERVED>
-0B5F-0B63,PVALID,ORIYA LETTER YYA..ORIYA VOWEL SIGN VOCALIC LL
-0B64-0B65,UNASSIGNED,<RESERVED>..<RESERVED>
-0B66-0B6F,PVALID,ORIYA DIGIT ZERO..ORIYA DIGIT NINE
-0B70,DISALLOWED,ORIYA ISSHAR
-0B71,PVALID,ORIYA LETTER WA
-0B72-0B81,UNASSIGNED,<RESERVED>..<RESERVED>
-0B82-0B83,PVALID,TAMIL SIGN ANUSVARA..TAMIL SIGN VISARGA
-0B84,UNASSIGNED,<RESERVED>
-0B85-0B8A,PVALID,TAMIL LETTER A..TAMIL LETTER UU
-0B8B-0B8D,UNASSIGNED,<RESERVED>..<RESERVED>
-0B8E-0B90,PVALID,TAMIL LETTER E..TAMIL LETTER AI
-0B91,UNASSIGNED,<RESERVED>
-0B92-0B95,PVALID,TAMIL LETTER O..TAMIL LETTER KA
-0B96-0B98,UNASSIGNED,<RESERVED>..<RESERVED>
-0B99-0B9A,PVALID,TAMIL LETTER NGA..TAMIL LETTER CA
-0B9B,UNASSIGNED,<RESERVED>
-0B9C,PVALID,TAMIL LETTER JA
-0B9D,UNASSIGNED,<RESERVED>
-0B9E-0B9F,PVALID,TAMIL LETTER NYA..TAMIL LETTER TTA
-0BA0-0BA2,UNASSIGNED,<RESERVED>..<RESERVED>
-0BA3-0BA4,PVALID,TAMIL LETTER NNA..TAMIL LETTER TA
-0BA5-0BA7,UNASSIGNED,<RESERVED>..<RESERVED>
-0BA8-0BAA,PVALID,TAMIL LETTER NA..TAMIL LETTER PA
-0BAB-0BAD,UNASSIGNED,<RESERVED>..<RESERVED>
-0BAE-0BB9,PVALID,TAMIL LETTER MA..TAMIL LETTER HA
-0BBA-0BBD,UNASSIGNED,<RESERVED>..<RESERVED>
-0BBE-0BC2,PVALID,TAMIL VOWEL SIGN AA..TAMIL VOWEL SIGN UU
-0BC3-0BC5,UNASSIGNED,<RESERVED>..<RESERVED>
-0BC6-0BC8,PVALID,TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI
-0BC9,UNASSIGNED,<RESERVED>
-0BCA-0BCD,PVALID,TAMIL VOWEL SIGN O..TAMIL SIGN VIRAMA
-0BCE-0BCF,UNASSIGNED,<RESERVED>..<RESERVED>
-0BD0,PVALID,TAMIL OM
-0BD1-0BD6,UNASSIGNED,<RESERVED>..<RESERVED>
-0BD7,PVALID,TAMIL AU LENGTH MARK
-0BD8-0BE5,UNASSIGNED,<RESERVED>..<RESERVED>
-0BE6-0BEF,PVALID,TAMIL DIGIT ZERO..TAMIL DIGIT NINE
-0BF0-0BFA,DISALLOWED,TAMIL NUMBER TEN..TAMIL NUMBER SIGN
-0BFB-0C00,UNASSIGNED,<RESERVED>..<RESERVED>
-0C01-0C03,PVALID,TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA
-0C04,UNASSIGNED,<RESERVED>
-0C05-0C0C,PVALID,TELUGU LETTER A..TELUGU LETTER VOCALIC L
-0C0D,UNASSIGNED,<RESERVED>
-0C0E-0C10,PVALID,TELUGU LETTER E..TELUGU LETTER AI
-0C11,UNASSIGNED,<RESERVED>
-0C12-0C28,PVALID,TELUGU LETTER O..TELUGU LETTER NA
-0C29,UNASSIGNED,<RESERVED>
-0C2A-0C33,PVALID,TELUGU LETTER PA..TELUGU LETTER LLA
-0C34,UNASSIGNED,<RESERVED>
-0C35-0C39,PVALID,TELUGU LETTER VA..TELUGU LETTER HA
-0C3A-0C3C,UNASSIGNED,<RESERVED>..<RESERVED>
-0C3D-0C44,PVALID,TELUGU SIGN AVAGRAHA..TELUGU VOWEL SIGN VOCALIC RR
-0C45,UNASSIGNED,<RESERVED>
-0C46-0C48,PVALID,TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI
-0C49,UNASSIGNED,<RESERVED>
-0C4A-0C4D,PVALID,TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA
-0C4E-0C54,UNASSIGNED,<RESERVED>..<RESERVED>
-0C55-0C56,PVALID,TELUGU LENGTH MARK..TELUGU AI LENGTH MARK
-0C57,UNASSIGNED,<RESERVED>
-0C58-0C59,PVALID,TELUGU LETTER TSA..TELUGU LETTER DZA
-0C5A-0C5F,UNASSIGNED,<RESERVED>..<RESERVED>
-0C60-0C63,PVALID,TELUGU LETTER VOCALIC RR..TELUGU VOWEL SIGN VOCALIC LL
-0C64-0C65,UNASSIGNED,<RESERVED>..<RESERVED>
-0C66-0C6F,PVALID,TELUGU DIGIT ZERO..TELUGU DIGIT NINE
-0C70-0C77,UNASSIGNED,<RESERVED>..<RESERVED>
-0C78-0C7F,DISALLOWED,TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR..TELUGU SIGN TUUMU
-0C80-0C81,UNASSIGNED,<RESERVED>..<RESERVED>
-0C82-0C83,PVALID,KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA
-0C84,UNASSIGNED,<RESERVED>
-0C85-0C8C,PVALID,KANNADA LETTER A..KANNADA LETTER VOCALIC L
-0C8D,UNASSIGNED,<RESERVED>
-0C8E-0C90,PVALID,KANNADA LETTER E..KANNADA LETTER AI
-0C91,UNASSIGNED,<RESERVED>
-0C92-0CA8,PVALID,KANNADA LETTER O..KANNADA LETTER NA
-0CA9,UNASSIGNED,<RESERVED>
-0CAA-0CB3,PVALID,KANNADA LETTER PA..KANNADA LETTER LLA
-0CB4,UNASSIGNED,<RESERVED>
-0CB5-0CB9,PVALID,KANNADA LETTER VA..KANNADA LETTER HA
-0CBA-0CBB,UNASSIGNED,<RESERVED>..<RESERVED>
-0CBC-0CC4,PVALID,KANNADA SIGN NUKTA..KANNADA VOWEL SIGN VOCALIC RR
-0CC5,UNASSIGNED,<RESERVED>
-0CC6-0CC8,PVALID,KANNADA VOWEL SIGN E..KANNADA VOWEL SIGN AI
-0CC9,UNASSIGNED,<RESERVED>
-0CCA-0CCD,PVALID,KANNADA VOWEL SIGN O..KANNADA SIGN VIRAMA
-0CCE-0CD4,UNASSIGNED,<RESERVED>..<RESERVED>
-0CD5-0CD6,PVALID,KANNADA LENGTH MARK..KANNADA AI LENGTH MARK
-0CD7-0CDD,UNASSIGNED,<RESERVED>..<RESERVED>
-0CDE,PVALID,KANNADA LETTER FA
-0CDF,UNASSIGNED,<RESERVED>
-0CE0-0CE3,PVALID,KANNADA LETTER VOCALIC RR..KANNADA VOWEL SIGN VOCALIC LL
-0CE4-0CE5,UNASSIGNED,<RESERVED>..<RESERVED>
-0CE6-0CEF,PVALID,KANNADA DIGIT ZERO..KANNADA DIGIT NINE
-0CF0,UNASSIGNED,<RESERVED>
-0CF1-0CF2,DISALLOWED,KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA
-0CF3-0D01,UNASSIGNED,<RESERVED>..<RESERVED>
-0D02-0D03,PVALID,MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA
-0D04,UNASSIGNED,<RESERVED>
-0D05-0D0C,PVALID,MALAYALAM LETTER A..MALAYALAM LETTER VOCALIC L
-0D0D,UNASSIGNED,<RESERVED>
-0D0E-0D10,PVALID,MALAYALAM LETTER E..MALAYALAM LETTER AI
-0D11,UNASSIGNED,<RESERVED>
-0D12-0D28,PVALID,MALAYALAM LETTER O..MALAYALAM LETTER NA
-0D29,UNASSIGNED,<RESERVED>
-0D2A-0D39,PVALID,MALAYALAM LETTER PA..MALAYALAM LETTER HA
-0D3A-0D3C,UNASSIGNED,<RESERVED>..<RESERVED>
-0D3D-0D44,PVALID,MALAYALAM SIGN AVAGRAHA..MALAYALAM VOWEL SIGN VOCALIC RR
-0D45,UNASSIGNED,<RESERVED>
-0D46-0D48,PVALID,MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI
-0D49,UNASSIGNED,<RESERVED>
-0D4A-0D4D,PVALID,MALAYALAM VOWEL SIGN O..MALAYALAM SIGN VIRAMA
-0D4E-0D56,UNASSIGNED,<RESERVED>..<RESERVED>
-0D57,PVALID,MALAYALAM AU LENGTH MARK
-0D58-0D5F,UNASSIGNED,<RESERVED>..<RESERVED>
-0D60-0D63,PVALID,MALAYALAM LETTER VOCALIC RR..MALAYALAM VOWEL SIGN VOCALIC LL
-0D64-0D65,UNASSIGNED,<RESERVED>..<RESERVED>
-0D66-0D6F,PVALID,MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE
-0D70-0D75,DISALLOWED,MALAYALAM NUMBER TEN..MALAYALAM FRACTION THREE QUARTERS
-0D76-0D78,UNASSIGNED,<RESERVED>..<RESERVED>
-0D79,DISALLOWED,MALAYALAM DATE MARK
-0D7A-0D7F,PVALID,MALAYALAM LETTER CHILLU NN..MALAYALAM LETTER CHILLU K
-0D80-0D81,UNASSIGNED,<RESERVED>..<RESERVED>
-0D82-0D83,PVALID,SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA
-0D84,UNASSIGNED,<RESERVED>
-0D85-0D96,PVALID,SINHALA LETTER AYANNA..SINHALA LETTER AUYANNA
-0D97-0D99,UNASSIGNED,<RESERVED>..<RESERVED>
-0D9A-0DB1,PVALID,SINHALA LETTER ALPAPRAANA KAYANNA..SINHALA LETTER DANTAJA NAYANNA
-0DB2,UNASSIGNED,<RESERVED>
-0DB3-0DBB,PVALID,SINHALA LETTER SANYAKA DAYANNA..SINHALA LETTER RAYANNA
-0DBC,UNASSIGNED,<RESERVED>
-0DBD,PVALID,SINHALA LETTER DANTAJA LAYANNA
-0DBE-0DBF,UNASSIGNED,<RESERVED>..<RESERVED>
-0DC0-0DC6,PVALID,SINHALA LETTER VAYANNA..SINHALA LETTER FAYANNA
-0DC7-0DC9,UNASSIGNED,<RESERVED>..<RESERVED>
-0DCA,PVALID,SINHALA SIGN AL-LAKUNA
-0DCB-0DCE,UNASSIGNED,<RESERVED>..<RESERVED>
-0DCF-0DD4,PVALID,SINHALA VOWEL SIGN AELA-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA
-0DD5,UNASSIGNED,<RESERVED>
-0DD6,PVALID,SINHALA VOWEL SIGN DIGA PAA-PILLA
-0DD7,UNASSIGNED,<RESERVED>
-0DD8-0DDF,PVALID,SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN GAYANUKITTA
-0DE0-0DF1,UNASSIGNED,<RESERVED>..<RESERVED>
-0DF2-0DF3,PVALID,SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA
-0DF4,DISALLOWED,SINHALA PUNCTUATION KUNDDALIYA
-0DF5-0E00,UNASSIGNED,<RESERVED>..<RESERVED>
-0E01-0E32,PVALID,THAI CHARACTER KO KAI..THAI CHARACTER SARA AA
-0E33,DISALLOWED,THAI CHARACTER SARA AM
-0E34-0E3A,PVALID,THAI CHARACTER SARA I..THAI CHARACTER PHINTHU
-0E3B-0E3E,UNASSIGNED,<RESERVED>..<RESERVED>
-0E3F,DISALLOWED,THAI CURRENCY SYMBOL BAHT
-0E40-0E4E,PVALID,THAI CHARACTER SARA E..THAI CHARACTER YAMAKKAN
-0E4F,DISALLOWED,THAI CHARACTER FONGMAN
-0E50-0E59,PVALID,THAI DIGIT ZERO..THAI DIGIT NINE
-0E5A-0E5B,DISALLOWED,THAI CHARACTER ANGKHANKHU..THAI CHARACTER KHOMUT
-0E5C-0E80,UNASSIGNED,<RESERVED>..<RESERVED>
-0E81-0E82,PVALID,LAO LETTER KO..LAO LETTER KHO SUNG
-0E83,UNASSIGNED,<RESERVED>
-0E84,PVALID,LAO LETTER KHO TAM
-0E85-0E86,UNASSIGNED,<RESERVED>..<RESERVED>
-0E87-0E88,PVALID,LAO LETTER NGO..LAO LETTER CO
-0E89,UNASSIGNED,<RESERVED>
-0E8A,PVALID,LAO LETTER SO TAM
-0E8B-0E8C,UNASSIGNED,<RESERVED>..<RESERVED>
-0E8D,PVALID,LAO LETTER NYO
-0E8E-0E93,UNASSIGNED,<RESERVED>..<RESERVED>
-0E94-0E97,PVALID,LAO LETTER DO..LAO LETTER THO TAM
-0E98,UNASSIGNED,<RESERVED>
-0E99-0E9F,PVALID,LAO LETTER NO..LAO LETTER FO SUNG
-0EA0,UNASSIGNED,<RESERVED>
-0EA1-0EA3,PVALID,LAO LETTER MO..LAO LETTER LO LING
-0EA4,UNASSIGNED,<RESERVED>
-0EA5,PVALID,LAO LETTER LO LOOT
-0EA6,UNASSIGNED,<RESERVED>
-0EA7,PVALID,LAO LETTER WO
-0EA8-0EA9,UNASSIGNED,<RESERVED>..<RESERVED>
-0EAA-0EAB,PVALID,LAO LETTER SO SUNG..LAO LETTER HO SUNG
-0EAC,UNASSIGNED,<RESERVED>
-0EAD-0EB2,PVALID,LAO LETTER O..LAO VOWEL SIGN AA
-0EB3,DISALLOWED,LAO VOWEL SIGN AM
-0EB4-0EB9,PVALID,LAO VOWEL SIGN I..LAO VOWEL SIGN UU
-0EBA,UNASSIGNED,<RESERVED>
-0EBB-0EBD,PVALID,LAO VOWEL SIGN MAI KON..LAO SEMIVOWEL SIGN NYO
-0EBE-0EBF,UNASSIGNED,<RESERVED>..<RESERVED>
-0EC0-0EC4,PVALID,LAO VOWEL SIGN E..LAO VOWEL SIGN AI
-0EC5,UNASSIGNED,<RESERVED>
-0EC6,PVALID,LAO KO LA
-0EC7,UNASSIGNED,<RESERVED>
-0EC8-0ECD,PVALID,LAO TONE MAI EK..LAO NIGGAHITA
-0ECE-0ECF,UNASSIGNED,<RESERVED>..<RESERVED>
-0ED0-0ED9,PVALID,LAO DIGIT ZERO..LAO DIGIT NINE
-0EDA-0EDB,UNASSIGNED,<RESERVED>..<RESERVED>
-0EDC-0EDD,DISALLOWED,LAO HO NO..LAO HO MO
-0EDE-0EFF,UNASSIGNED,<RESERVED>..<RESERVED>
-0F00,PVALID,TIBETAN SYLLABLE OM
-0F01-0F0A,DISALLOWED,TIBETAN MARK GTER YIG MGO TRUNCATED A..TIBETAN MARK BKA- SHOG YIG MGO
-0F0B,PVALID,TIBETAN MARK INTERSYLLABIC TSHEG
-0F0C-0F17,DISALLOWED,TIBETAN MARK DELIMITER TSHEG BSTAR..TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS
-0F18-0F19,PVALID,TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS
-0F1A-0F1F,DISALLOWED,TIBETAN SIGN RDEL DKAR GCIG..TIBETAN SIGN RDEL DKAR RDEL NAG
-0F20-0F29,PVALID,TIBETAN DIGIT ZERO..TIBETAN DIGIT NINE
-0F2A-0F34,DISALLOWED,TIBETAN DIGIT HALF ONE..TIBETAN MARK BSDUS RTAGS
-0F35,PVALID,TIBETAN MARK NGAS BZUNG NYI ZLA
-0F36,DISALLOWED,TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN
-0F37,PVALID,TIBETAN MARK NGAS BZUNG SGOR RTAGS
-0F38,DISALLOWED,TIBETAN MARK CHE MGO
-0F39,PVALID,TIBETAN MARK TSA -PHRU
-0F3A-0F3D,DISALLOWED,TIBETAN MARK GUG RTAGS GYON..TIBETAN MARK ANG KHANG GYAS
-0F3E-0F42,PVALID,TIBETAN SIGN YAR TSHES..TIBETAN LETTER GA
-0F43,DISALLOWED,TIBETAN LETTER GHA
-0F44-0F47,PVALID,TIBETAN LETTER NGA..TIBETAN LETTER JA
-0F48,UNASSIGNED,<RESERVED>
-0F49-0F4C,PVALID,TIBETAN LETTER NYA..TIBETAN LETTER DDA
-0F4D,DISALLOWED,TIBETAN LETTER DDHA
-0F4E-0F51,PVALID,TIBETAN LETTER NNA..TIBETAN LETTER DA
-0F52,DISALLOWED,TIBETAN LETTER DHA
-0F53-0F56,PVALID,TIBETAN LETTER NA..TIBETAN LETTER BA
-0F57,DISALLOWED,TIBETAN LETTER BHA
-0F58-0F5B,PVALID,TIBETAN LETTER MA..TIBETAN LETTER DZA
-0F5C,DISALLOWED,TIBETAN LETTER DZHA
-0F5D-0F68,PVALID,TIBETAN LETTER WA..TIBETAN LETTER A
-0F69,DISALLOWED,TIBETAN LETTER KSSA
-0F6A-0F6C,PVALID,TIBETAN LETTER FIXED-FORM RA..TIBETAN LETTER RRA
-0F6D-0F70,UNASSIGNED,<RESERVED>..<RESERVED>
-0F71-0F72,PVALID,TIBETAN VOWEL SIGN AA..TIBETAN VOWEL SIGN I
-0F73,DISALLOWED,TIBETAN VOWEL SIGN II
-0F74,PVALID,TIBETAN VOWEL SIGN U
-0F75-0F79,DISALLOWED,TIBETAN VOWEL SIGN UU..TIBETAN VOWEL SIGN VOCALIC LL
-0F7A-0F80,PVALID,TIBETAN VOWEL SIGN E..TIBETAN VOWEL SIGN REVERSED I
-0F81,DISALLOWED,TIBETAN VOWEL SIGN REVERSED II
-0F82-0F84,PVALID,TIBETAN SIGN NYI ZLA NAA DA..TIBETAN MARK HALANTA
-0F85,DISALLOWED,TIBETAN MARK PALUTA
-0F86-0F8B,PVALID,TIBETAN SIGN LCI RTAGS..TIBETAN SIGN GRU MED RGYINGS
-0F8C-0F8F,UNASSIGNED,<RESERVED>..<RESERVED>
-0F90-0F92,PVALID,TIBETAN SUBJOINED LETTER KA..TIBETAN SUBJOINED LETTER GA
-0F93,DISALLOWED,TIBETAN SUBJOINED LETTER GHA
-0F94-0F97,PVALID,TIBETAN SUBJOINED LETTER NGA..TIBETAN SUBJOINED LETTER JA
-0F98,UNASSIGNED,<RESERVED>
-0F99-0F9C,PVALID,TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER DDA
-0F9D,DISALLOWED,TIBETAN SUBJOINED LETTER DDHA
-0F9E-0FA1,PVALID,TIBETAN SUBJOINED LETTER NNA..TIBETAN SUBJOINED LETTER DA
-0FA2,DISALLOWED,TIBETAN SUBJOINED LETTER DHA
-0FA3-0FA6,PVALID,TIBETAN SUBJOINED LETTER NA..TIBETAN SUBJOINED LETTER BA
-0FA7,DISALLOWED,TIBETAN SUBJOINED LETTER BHA
-0FA8-0FAB,PVALID,TIBETAN SUBJOINED LETTER MA..TIBETAN SUBJOINED LETTER DZA
-0FAC,DISALLOWED,TIBETAN SUBJOINED LETTER DZHA
-0FAD-0FB8,PVALID,TIBETAN SUBJOINED LETTER WA..TIBETAN SUBJOINED LETTER A
-0FB9,DISALLOWED,TIBETAN SUBJOINED LETTER KSSA
-0FBA-0FBC,PVALID,TIBETAN SUBJOINED LETTER FIXED-FORM WA..TIBETAN SUBJOINED LETTER FIXED-FORM RA
-0FBD,UNASSIGNED,<RESERVED>
-0FBE-0FC5,DISALLOWED,TIBETAN KU RU KHA..TIBETAN SYMBOL RDO RJE
-0FC6,PVALID,TIBETAN SYMBOL PADMA GDAN
-0FC7-0FCC,DISALLOWED,TIBETAN SYMBOL RDO RJE RGYA GRAM..TIBETAN SYMBOL NOR BU BZHI -KHYIL
-0FCD,UNASSIGNED,<RESERVED>
-0FCE-0FD8,DISALLOWED,TIBETAN SIGN RDEL NAG RDEL DKAR..LEFT-FACING SVASTI SIGN WITH DOTS
-0FD9-0FFF,UNASSIGNED,<RESERVED>..<RESERVED>
-1000-1049,PVALID,MYANMAR LETTER KA..MYANMAR DIGIT NINE
-104A-104F,DISALLOWED,MYANMAR SIGN LITTLE SECTION..MYANMAR SYMBOL GENITIVE
-1050-109D,PVALID,MYANMAR LETTER SHA..MYANMAR VOWEL SIGN AITON AI
-109E-10C5,DISALLOWED,MYANMAR SYMBOL SHAN ONE..GEORGIAN CAPITAL LETTER HOE
-10C6-10CF,UNASSIGNED,<RESERVED>..<RESERVED>
-10D0-10FA,PVALID,GEORGIAN LETTER AN..GEORGIAN LETTER AIN
-10FB-10FC,DISALLOWED,GEORGIAN PARAGRAPH SEPARATOR..MODIFIER LETTER GEORGIAN NAR
-10FD-10FF,UNASSIGNED,<RESERVED>..<RESERVED>
-1100-11FF,DISALLOWED,HANGUL CHOSEONG KIYEOK..HANGUL JONGSEONG SSANGNIEUN
-1200-1248,PVALID,ETHIOPIC SYLLABLE HA..ETHIOPIC SYLLABLE QWA
-1249,UNASSIGNED,<RESERVED>
-124A-124D,PVALID,ETHIOPIC SYLLABLE QWI..ETHIOPIC SYLLABLE QWE
-124E-124F,UNASSIGNED,<RESERVED>..<RESERVED>
-1250-1256,PVALID,ETHIOPIC SYLLABLE QHA..ETHIOPIC SYLLABLE QHO
-1257,UNASSIGNED,<RESERVED>
-1258,PVALID,ETHIOPIC SYLLABLE QHWA
-1259,UNASSIGNED,<RESERVED>
-125A-125D,PVALID,ETHIOPIC SYLLABLE QHWI..ETHIOPIC SYLLABLE QHWE
-125E-125F,UNASSIGNED,<RESERVED>..<RESERVED>
-1260-1288,PVALID,ETHIOPIC SYLLABLE BA..ETHIOPIC SYLLABLE XWA
-1289,UNASSIGNED,<RESERVED>
-128A-128D,PVALID,ETHIOPIC SYLLABLE XWI..ETHIOPIC SYLLABLE XWE
-128E-128F,UNASSIGNED,<RESERVED>..<RESERVED>
-1290-12B0,PVALID,ETHIOPIC SYLLABLE NA..ETHIOPIC SYLLABLE KWA
-12B1,UNASSIGNED,<RESERVED>
-12B2-12B5,PVALID,ETHIOPIC SYLLABLE KWI..ETHIOPIC SYLLABLE KWE
-12B6-12B7,UNASSIGNED,<RESERVED>..<RESERVED>
-12B8-12BE,PVALID,ETHIOPIC SYLLABLE KXA..ETHIOPIC SYLLABLE KXO
-12BF,UNASSIGNED,<RESERVED>
-12C0,PVALID,ETHIOPIC SYLLABLE KXWA
-12C1,UNASSIGNED,<RESERVED>
-12C2-12C5,PVALID,ETHIOPIC SYLLABLE KXWI..ETHIOPIC SYLLABLE KXWE
-12C6-12C7,UNASSIGNED,<RESERVED>..<RESERVED>
-12C8-12D6,PVALID,ETHIOPIC SYLLABLE WA..ETHIOPIC SYLLABLE PHARYNGEAL O
-12D7,UNASSIGNED,<RESERVED>
-12D8-1310,PVALID,ETHIOPIC SYLLABLE ZA..ETHIOPIC SYLLABLE GWA
-1311,UNASSIGNED,<RESERVED>
-1312-1315,PVALID,ETHIOPIC SYLLABLE GWI..ETHIOPIC SYLLABLE GWE
-1316-1317,UNASSIGNED,<RESERVED>..<RESERVED>
-1318-135A,PVALID,ETHIOPIC SYLLABLE GGA..ETHIOPIC SYLLABLE FYA
-135B-135E,UNASSIGNED,<RESERVED>..<RESERVED>
-135F,PVALID,ETHIOPIC COMBINING GEMINATION MARK
-1360-137C,DISALLOWED,ETHIOPIC SECTION MARK..ETHIOPIC NUMBER TEN THOUSAND
-137D-137F,UNASSIGNED,<RESERVED>..<RESERVED>
-1380-138F,PVALID,ETHIOPIC SYLLABLE SEBATBEIT MWA..ETHIOPIC SYLLABLE PWE
-1390-1399,DISALLOWED,ETHIOPIC TONAL MARK YIZET..ETHIOPIC TONAL MARK KURT
-139A-139F,UNASSIGNED,<RESERVED>..<RESERVED>
-13A0-13F4,PVALID,CHEROKEE LETTER A..CHEROKEE LETTER YV
-13F5-13FF,UNASSIGNED,<RESERVED>..<RESERVED>
-1400,DISALLOWED,CANADIAN SYLLABICS HYPHEN
-1401-166C,PVALID,CANADIAN SYLLABICS E..CANADIAN SYLLABICS CARRIER TTSA
-166D-166E,DISALLOWED,CANADIAN SYLLABICS CHI SIGN..CANADIAN SYLLABICS FULL STOP
-166F-167F,PVALID,CANADIAN SYLLABICS QAI..CANADIAN SYLLABICS BLACKFOOT W
-1680,DISALLOWED,OGHAM SPACE MARK
-1681-169A,PVALID,OGHAM LETTER BEITH..OGHAM LETTER PEITH
-169B-169C,DISALLOWED,OGHAM FEATHER MARK..OGHAM REVERSED FEATHER MARK
-169D-169F,UNASSIGNED,<RESERVED>..<RESERVED>
-16A0-16EA,PVALID,RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X
-16EB-16F0,DISALLOWED,RUNIC SINGLE PUNCTUATION..RUNIC BELGTHOR SYMBOL
-16F1-16FF,UNASSIGNED,<RESERVED>..<RESERVED>
-1700-170C,PVALID,TAGALOG LETTER A..TAGALOG LETTER YA
-170D,UNASSIGNED,<RESERVED>
-170E-1714,PVALID,TAGALOG LETTER LA..TAGALOG SIGN VIRAMA
-1715-171F,UNASSIGNED,<RESERVED>..<RESERVED>
-1720-1734,PVALID,HANUNOO LETTER A..HANUNOO SIGN PAMUDPOD
-1735-1736,DISALLOWED,PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION
-1737-173F,UNASSIGNED,<RESERVED>..<RESERVED>
-1740-1753,PVALID,BUHID LETTER A..BUHID VOWEL SIGN U
-1754-175F,UNASSIGNED,<RESERVED>..<RESERVED>
-1760-176C,PVALID,TAGBANWA LETTER A..TAGBANWA LETTER YA
-176D,UNASSIGNED,<RESERVED>
-176E-1770,PVALID,TAGBANWA LETTER LA..TAGBANWA LETTER SA
-1771,UNASSIGNED,<RESERVED>
-1772-1773,PVALID,TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U
-1774-177F,UNASSIGNED,<RESERVED>..<RESERVED>
-1780-17B3,PVALID,KHMER LETTER KA..KHMER INDEPENDENT VOWEL QAU
-17B4-17B5,DISALLOWED,KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
-17B6-17D3,PVALID,KHMER VOWEL SIGN AA..KHMER SIGN BATHAMASAT
-17D4-17D6,DISALLOWED,KHMER SIGN KHAN..KHMER SIGN CAMNUC PII KUUH
-17D7,PVALID,KHMER SIGN LEK TOO
-17D8-17DB,DISALLOWED,KHMER SIGN BEYYAL..KHMER CURRENCY SYMBOL RIEL
-17DC-17DD,PVALID,KHMER SIGN AVAKRAHASANYA..KHMER SIGN ATTHACAN
-17DE-17DF,UNASSIGNED,<RESERVED>..<RESERVED>
-17E0-17E9,PVALID,KHMER DIGIT ZERO..KHMER DIGIT NINE
-17EA-17EF,UNASSIGNED,<RESERVED>..<RESERVED>
-17F0-17F9,DISALLOWED,KHMER SYMBOL LEK ATTAK SON..KHMER SYMBOL LEK ATTAK PRAM-BUON
-17FA-17FF,UNASSIGNED,<RESERVED>..<RESERVED>
-1800-180E,DISALLOWED,MONGOLIAN BIRGA..MONGOLIAN VOWEL SEPARATOR
-180F,UNASSIGNED,<RESERVED>
-1810-1819,PVALID,MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE
-181A-181F,UNASSIGNED,<RESERVED>..<RESERVED>
-1820-1877,PVALID,MONGOLIAN LETTER A..MONGOLIAN LETTER MANCHU ZHA
-1878-187F,UNASSIGNED,<RESERVED>..<RESERVED>
-1880-18AA,PVALID,MONGOLIAN LETTER ALI GALI ANUSVARA ONE..MONGOLIAN LETTER MANCHU ALI GALI LHA
-18AB-18AF,UNASSIGNED,<RESERVED>..<RESERVED>
-18B0-18F5,PVALID,CANADIAN SYLLABICS OY..CANADIAN SYLLABICS CARRIER DENTAL S
-18F6-18FF,UNASSIGNED,<RESERVED>..<RESERVED>
-1900-191C,PVALID,LIMBU VOWEL-CARRIER LETTER..LIMBU LETTER HA
-191D-191F,UNASSIGNED,<RESERVED>..<RESERVED>
-1920-192B,PVALID,LIMBU VOWEL SIGN A..LIMBU SUBJOINED LETTER WA
-192C-192F,UNASSIGNED,<RESERVED>..<RESERVED>
-1930-193B,PVALID,LIMBU SMALL LETTER KA..LIMBU SIGN SA-I
-193C-193F,UNASSIGNED,<RESERVED>..<RESERVED>
-1940,DISALLOWED,LIMBU SIGN LOO
-1941-1943,UNASSIGNED,<RESERVED>..<RESERVED>
-1944-1945,DISALLOWED,LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK
-1946-196D,PVALID,LIMBU DIGIT ZERO..TAI LE LETTER AI
-196E-196F,UNASSIGNED,<RESERVED>..<RESERVED>
-1970-1974,PVALID,TAI LE LETTER TONE-2..TAI LE LETTER TONE-6
-1975-197F,UNASSIGNED,<RESERVED>..<RESERVED>
-1980-19AB,PVALID,NEW TAI LUE LETTER HIGH QA..NEW TAI LUE LETTER LOW SUA
-19AC-19AF,UNASSIGNED,<RESERVED>..<RESERVED>
-19B0-19C9,PVALID,NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW TAI LUE TONE MARK-2
-19CA-19CF,UNASSIGNED,<RESERVED>..<RESERVED>
-19D0-19DA,PVALID,NEW TAI LUE DIGIT ZERO..NEW TAI LUE THAM DIGIT ONE
-19DB-19DD,UNASSIGNED,<RESERVED>..<RESERVED>
-19DE-19FF,DISALLOWED,NEW TAI LUE SIGN LAE..KHMER SYMBOL DAP-PRAM ROC
-1A00-1A1B,PVALID,BUGINESE LETTER KA..BUGINESE VOWEL SIGN AE
-1A1C-1A1D,UNASSIGNED,<RESERVED>..<RESERVED>
-1A1E-1A1F,DISALLOWED,BUGINESE PALLAWA..BUGINESE END OF SECTION
-1A20-1A5E,PVALID,TAI THAM LETTER HIGH KA..TAI THAM CONSONANT SIGN SA
-1A5F,UNASSIGNED,<RESERVED>
-1A60-1A7C,PVALID,TAI THAM SIGN SAKOT..TAI THAM SIGN KHUEN-LUE KARAN
-1A7D-1A7E,UNASSIGNED,<RESERVED>..<RESERVED>
-1A7F-1A89,PVALID,TAI THAM COMBINING CRYPTOGRAMMIC DOT..TAI THAM HORA DIGIT NINE
-1A8A-1A8F,UNASSIGNED,<RESERVED>..<RESERVED>
-1A90-1A99,PVALID,TAI THAM THAM DIGIT ZERO..TAI THAM THAM DIGIT NINE
-1A9A-1A9F,UNASSIGNED,<RESERVED>..<RESERVED>
-1AA0-1AA6,DISALLOWED,TAI THAM SIGN WIANG..TAI THAM SIGN REVERSED ROTATED RANA
-1AA7,PVALID,TAI THAM SIGN MAI YAMOK
-1AA8-1AAD,DISALLOWED,TAI THAM SIGN KAAN..TAI THAM SIGN CAANG
-1AAE-1AFF,UNASSIGNED,<RESERVED>..<RESERVED>
-1B00-1B4B,PVALID,BALINESE SIGN ULU RICEM..BALINESE LETTER ASYURA SASAK
-1B4C-1B4F,UNASSIGNED,<RESERVED>..<RESERVED>
-1B50-1B59,PVALID,BALINESE DIGIT ZERO..BALINESE DIGIT NINE
-1B5A-1B6A,DISALLOWED,BALINESE PANTI..BALINESE MUSICAL SYMBOL DANG GEDE
-1B6B-1B73,PVALID,BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG
-1B74-1B7C,DISALLOWED,BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG..BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING
-1B7D-1B7F,UNASSIGNED,<RESERVED>..<RESERVED>
-1B80-1BAA,PVALID,SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PAMAAEH
-1BAB-1BAD,UNASSIGNED,<RESERVED>..<RESERVED>
-1BAE-1BB9,PVALID,SUNDANESE LETTER KHA..SUNDANESE DIGIT NINE
-1BBA-1BFF,UNASSIGNED,<RESERVED>..<RESERVED>
-1C00-1C37,PVALID,LEPCHA LETTER KA..LEPCHA SIGN NUKTA
-1C38-1C3A,UNASSIGNED,<RESERVED>..<RESERVED>
-1C3B-1C3F,DISALLOWED,LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION TSHOOK
-1C40-1C49,PVALID,LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE
-1C4A-1C4C,UNASSIGNED,<RESERVED>..<RESERVED>
-1C4D-1C7D,PVALID,LEPCHA LETTER TTA..OL CHIKI AHAD
-1C7E-1C7F,DISALLOWED,OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTUATION DOUBLE MUCAAD
-1C80-1CCF,UNASSIGNED,<RESERVED>..<RESERVED>
-1CD0-1CD2,PVALID,VEDIC TONE KARSHANA..VEDIC TONE PRENKHA
-1CD3,DISALLOWED,VEDIC SIGN NIHSHVASA
-1CD4-1CF2,PVALID,VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC SIGN ARDHAVISARGA
-1CF3-1CFF,UNASSIGNED,<RESERVED>..<RESERVED>
-1D00-1D2B,PVALID,LATIN LETTER SMALL CAPITAL A..CYRILLIC LETTER SMALL CAPITAL EL
-1D2C-1D2E,DISALLOWED,MODIFIER LETTER CAPITAL A..MODIFIER LETTER CAPITAL B
-1D2F,PVALID,MODIFIER LETTER CAPITAL BARRED B
-1D30-1D3A,DISALLOWED,MODIFIER LETTER CAPITAL D..MODIFIER LETTER CAPITAL N
-1D3B,PVALID,MODIFIER LETTER CAPITAL REVERSED N
-1D3C-1D4D,DISALLOWED,MODIFIER LETTER CAPITAL O..MODIFIER LETTER SMALL G
-1D4E,PVALID,MODIFIER LETTER SMALL TURNED I
-1D4F-1D6A,DISALLOWED,MODIFIER LETTER SMALL K..GREEK SUBSCRIPT SMALL LETTER CHI
-1D6B-1D77,PVALID,LATIN SMALL LETTER UE..LATIN SMALL LETTER TURNED G
-1D78,DISALLOWED,MODIFIER LETTER CYRILLIC EN
-1D79-1D9A,PVALID,LATIN SMALL LETTER INSULAR G..LATIN SMALL LETTER EZH WITH RETROFLEX HOOK
-1D9B-1DBF,DISALLOWED,MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL THETA
-1DC0-1DE6,PVALID,COMBINING DOTTED GRAVE ACCENT..COMBINING LATIN SMALL LETTER Z
-1DE7-1DFC,UNASSIGNED,<RESERVED>..<RESERVED>
-1DFD-1DFF,PVALID,COMBINING ALMOST EQUAL TO BELOW..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW
-1E00,DISALLOWED,LATIN CAPITAL LETTER A WITH RING BELOW
-1E01,PVALID,LATIN SMALL LETTER A WITH RING BELOW
-1E02,DISALLOWED,LATIN CAPITAL LETTER B WITH DOT ABOVE
-1E03,PVALID,LATIN SMALL LETTER B WITH DOT ABOVE
-1E04,DISALLOWED,LATIN CAPITAL LETTER B WITH DOT BELOW
-1E05,PVALID,LATIN SMALL LETTER B WITH DOT BELOW
-1E06,DISALLOWED,LATIN CAPITAL LETTER B WITH LINE BELOW
-1E07,PVALID,LATIN SMALL LETTER B WITH LINE BELOW
-1E08,DISALLOWED,LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE
-1E09,PVALID,LATIN SMALL LETTER C WITH CEDILLA AND ACUTE
-1E0A,DISALLOWED,LATIN CAPITAL LETTER D WITH DOT ABOVE
-1E0B,PVALID,LATIN SMALL LETTER D WITH DOT ABOVE
-1E0C,DISALLOWED,LATIN CAPITAL LETTER D WITH DOT BELOW
-1E0D,PVALID,LATIN SMALL LETTER D WITH DOT BELOW
-1E0E,DISALLOWED,LATIN CAPITAL LETTER D WITH LINE BELOW
-1E0F,PVALID,LATIN SMALL LETTER D WITH LINE BELOW
-1E10,DISALLOWED,LATIN CAPITAL LETTER D WITH CEDILLA
-1E11,PVALID,LATIN SMALL LETTER D WITH CEDILLA
-1E12,DISALLOWED,LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW
-1E13,PVALID,LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW
-1E14,DISALLOWED,LATIN CAPITAL LETTER E WITH MACRON AND GRAVE
-1E15,PVALID,LATIN SMALL LETTER E WITH MACRON AND GRAVE
-1E16,DISALLOWED,LATIN CAPITAL LETTER E WITH MACRON AND ACUTE
-1E17,PVALID,LATIN SMALL LETTER E WITH MACRON AND ACUTE
-1E18,DISALLOWED,LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW
-1E19,PVALID,LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW
-1E1A,DISALLOWED,LATIN CAPITAL LETTER E WITH TILDE BELOW
-1E1B,PVALID,LATIN SMALL LETTER E WITH TILDE BELOW
-1E1C,DISALLOWED,LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE
-1E1D,PVALID,LATIN SMALL LETTER E WITH CEDILLA AND BREVE
-1E1E,DISALLOWED,LATIN CAPITAL LETTER F WITH DOT ABOVE
-1E1F,PVALID,LATIN SMALL LETTER F WITH DOT ABOVE
-1E20,DISALLOWED,LATIN CAPITAL LETTER G WITH MACRON
-1E21,PVALID,LATIN SMALL LETTER G WITH MACRON
-1E22,DISALLOWED,LATIN CAPITAL LETTER H WITH DOT ABOVE
-1E23,PVALID,LATIN SMALL LETTER H WITH DOT ABOVE
-1E24,DISALLOWED,LATIN CAPITAL LETTER H WITH DOT BELOW
-1E25,PVALID,LATIN SMALL LETTER H WITH DOT BELOW
-1E26,DISALLOWED,LATIN CAPITAL LETTER H WITH DIAERESIS
-1E27,PVALID,LATIN SMALL LETTER H WITH DIAERESIS
-1E28,DISALLOWED,LATIN CAPITAL LETTER H WITH CEDILLA
-1E29,PVALID,LATIN SMALL LETTER H WITH CEDILLA
-1E2A,DISALLOWED,LATIN CAPITAL LETTER H WITH BREVE BELOW
-1E2B,PVALID,LATIN SMALL LETTER H WITH BREVE BELOW
-1E2C,DISALLOWED,LATIN CAPITAL LETTER I WITH TILDE BELOW
-1E2D,PVALID,LATIN SMALL LETTER I WITH TILDE BELOW
-1E2E,DISALLOWED,LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE
-1E2F,PVALID,LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE
-1E30,DISALLOWED,LATIN CAPITAL LETTER K WITH ACUTE
-1E31,PVALID,LATIN SMALL LETTER K WITH ACUTE
-1E32,DISALLOWED,LATIN CAPITAL LETTER K WITH DOT BELOW
-1E33,PVALID,LATIN SMALL LETTER K WITH DOT BELOW
-1E34,DISALLOWED,LATIN CAPITAL LETTER K WITH LINE BELOW
-1E35,PVALID,LATIN SMALL LETTER K WITH LINE BELOW
-1E36,DISALLOWED,LATIN CAPITAL LETTER L WITH DOT BELOW
-1E37,PVALID,LATIN SMALL LETTER L WITH DOT BELOW
-1E38,DISALLOWED,LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON
-1E39,PVALID,LATIN SMALL LETTER L WITH DOT BELOW AND MACRON
-1E3A,DISALLOWED,LATIN CAPITAL LETTER L WITH LINE BELOW
-1E3B,PVALID,LATIN SMALL LETTER L WITH LINE BELOW
-1E3C,DISALLOWED,LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW
-1E3D,PVALID,LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW
-1E3E,DISALLOWED,LATIN CAPITAL LETTER M WITH ACUTE
-1E3F,PVALID,LATIN SMALL LETTER M WITH ACUTE
-1E40,DISALLOWED,LATIN CAPITAL LETTER M WITH DOT ABOVE
-1E41,PVALID,LATIN SMALL LETTER M WITH DOT ABOVE
-1E42,DISALLOWED,LATIN CAPITAL LETTER M WITH DOT BELOW
-1E43,PVALID,LATIN SMALL LETTER M WITH DOT BELOW
-1E44,DISALLOWED,LATIN CAPITAL LETTER N WITH DOT ABOVE
-1E45,PVALID,LATIN SMALL LETTER N WITH DOT ABOVE
-1E46,DISALLOWED,LATIN CAPITAL LETTER N WITH DOT BELOW
-1E47,PVALID,LATIN SMALL LETTER N WITH DOT BELOW
-1E48,DISALLOWED,LATIN CAPITAL LETTER N WITH LINE BELOW
-1E49,PVALID,LATIN SMALL LETTER N WITH LINE BELOW
-1E4A,DISALLOWED,LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW
-1E4B,PVALID,LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW
-1E4C,DISALLOWED,LATIN CAPITAL LETTER O WITH TILDE AND ACUTE
-1E4D,PVALID,LATIN SMALL LETTER O WITH TILDE AND ACUTE
-1E4E,DISALLOWED,LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS
-1E4F,PVALID,LATIN SMALL LETTER O WITH TILDE AND DIAERESIS
-1E50,DISALLOWED,LATIN CAPITAL LETTER O WITH MACRON AND GRAVE
-1E51,PVALID,LATIN SMALL LETTER O WITH MACRON AND GRAVE
-1E52,DISALLOWED,LATIN CAPITAL LETTER O WITH MACRON AND ACUTE
-1E53,PVALID,LATIN SMALL LETTER O WITH MACRON AND ACUTE
-1E54,DISALLOWED,LATIN CAPITAL LETTER P WITH ACUTE
-1E55,PVALID,LATIN SMALL LETTER P WITH ACUTE
-1E56,DISALLOWED,LATIN CAPITAL LETTER P WITH DOT ABOVE
-1E57,PVALID,LATIN SMALL LETTER P WITH DOT ABOVE
-1E58,DISALLOWED,LATIN CAPITAL LETTER R WITH DOT ABOVE
-1E59,PVALID,LATIN SMALL LETTER R WITH DOT ABOVE
-1E5A,DISALLOWED,LATIN CAPITAL LETTER R WITH DOT BELOW
-1E5B,PVALID,LATIN SMALL LETTER R WITH DOT BELOW
-1E5C,DISALLOWED,LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON
-1E5D,PVALID,LATIN SMALL LETTER R WITH DOT BELOW AND MACRON
-1E5E,DISALLOWED,LATIN CAPITAL LETTER R WITH LINE BELOW
-1E5F,PVALID,LATIN SMALL LETTER R WITH LINE BELOW
-1E60,DISALLOWED,LATIN CAPITAL LETTER S WITH DOT ABOVE
-1E61,PVALID,LATIN SMALL LETTER S WITH DOT ABOVE
-1E62,DISALLOWED,LATIN CAPITAL LETTER S WITH DOT BELOW
-1E63,PVALID,LATIN SMALL LETTER S WITH DOT BELOW
-1E64,DISALLOWED,LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE
-1E65,PVALID,LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE
-1E66,DISALLOWED,LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE
-1E67,PVALID,LATIN SMALL LETTER S WITH CARON AND DOT ABOVE
-1E68,DISALLOWED,LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE
-1E69,PVALID,LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE
-1E6A,DISALLOWED,LATIN CAPITAL LETTER T WITH DOT ABOVE
-1E6B,PVALID,LATIN SMALL LETTER T WITH DOT ABOVE
-1E6C,DISALLOWED,LATIN CAPITAL LETTER T WITH DOT BELOW
-1E6D,PVALID,LATIN SMALL LETTER T WITH DOT BELOW
-1E6E,DISALLOWED,LATIN CAPITAL LETTER T WITH LINE BELOW
-1E6F,PVALID,LATIN SMALL LETTER T WITH LINE BELOW
-1E70,DISALLOWED,LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW
-1E71,PVALID,LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW
-1E72,DISALLOWED,LATIN CAPITAL LETTER U WITH DIAERESIS BELOW
-1E73,PVALID,LATIN SMALL LETTER U WITH DIAERESIS BELOW
-1E74,DISALLOWED,LATIN CAPITAL LETTER U WITH TILDE BELOW
-1E75,PVALID,LATIN SMALL LETTER U WITH TILDE BELOW
-1E76,DISALLOWED,LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW
-1E77,PVALID,LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW
-1E78,DISALLOWED,LATIN CAPITAL LETTER U WITH TILDE AND ACUTE
-1E79,PVALID,LATIN SMALL LETTER U WITH TILDE AND ACUTE
-1E7A,DISALLOWED,LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS
-1E7B,PVALID,LATIN SMALL LETTER U WITH MACRON AND DIAERESIS
-1E7C,DISALLOWED,LATIN CAPITAL LETTER V WITH TILDE
-1E7D,PVALID,LATIN SMALL LETTER V WITH TILDE
-1E7E,DISALLOWED,LATIN CAPITAL LETTER V WITH DOT BELOW
-1E7F,PVALID,LATIN SMALL LETTER V WITH DOT BELOW
-1E80,DISALLOWED,LATIN CAPITAL LETTER W WITH GRAVE
-1E81,PVALID,LATIN SMALL LETTER W WITH GRAVE
-1E82,DISALLOWED,LATIN CAPITAL LETTER W WITH ACUTE
-1E83,PVALID,LATIN SMALL LETTER W WITH ACUTE
-1E84,DISALLOWED,LATIN CAPITAL LETTER W WITH DIAERESIS
-1E85,PVALID,LATIN SMALL LETTER W WITH DIAERESIS
-1E86,DISALLOWED,LATIN CAPITAL LETTER W WITH DOT ABOVE
-1E87,PVALID,LATIN SMALL LETTER W WITH DOT ABOVE
-1E88,DISALLOWED,LATIN CAPITAL LETTER W WITH DOT BELOW
-1E89,PVALID,LATIN SMALL LETTER W WITH DOT BELOW
-1E8A,DISALLOWED,LATIN CAPITAL LETTER X WITH DOT ABOVE
-1E8B,PVALID,LATIN SMALL LETTER X WITH DOT ABOVE
-1E8C,DISALLOWED,LATIN CAPITAL LETTER X WITH DIAERESIS
-1E8D,PVALID,LATIN SMALL LETTER X WITH DIAERESIS
-1E8E,DISALLOWED,LATIN CAPITAL LETTER Y WITH DOT ABOVE
-1E8F,PVALID,LATIN SMALL LETTER Y WITH DOT ABOVE
-1E90,DISALLOWED,LATIN CAPITAL LETTER Z WITH CIRCUMFLEX
-1E91,PVALID,LATIN SMALL LETTER Z WITH CIRCUMFLEX
-1E92,DISALLOWED,LATIN CAPITAL LETTER Z WITH DOT BELOW
-1E93,PVALID,LATIN SMALL LETTER Z WITH DOT BELOW
-1E94,DISALLOWED,LATIN CAPITAL LETTER Z WITH LINE BELOW
-1E95-1E99,PVALID,LATIN SMALL LETTER Z WITH LINE BELOW..LATIN SMALL LETTER Y WITH RING ABOVE
-1E9A-1E9B,DISALLOWED,LATIN SMALL LETTER A WITH RIGHT HALF RING..LATIN SMALL LETTER LONG S WITH DOT ABOVE
-1E9C-1E9D,PVALID,LATIN SMALL LETTER LONG S WITH DIAGONAL STROKE..LATIN SMALL LETTER LONG S WITH HIGH STROKE
-1E9E,DISALLOWED,LATIN CAPITAL LETTER SHARP S
-1E9F,PVALID,LATIN SMALL LETTER DELTA
-1EA0,DISALLOWED,LATIN CAPITAL LETTER A WITH DOT BELOW
-1EA1,PVALID,LATIN SMALL LETTER A WITH DOT BELOW
-1EA2,DISALLOWED,LATIN CAPITAL LETTER A WITH HOOK ABOVE
-1EA3,PVALID,LATIN SMALL LETTER A WITH HOOK ABOVE
-1EA4,DISALLOWED,LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE
-1EA5,PVALID,LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE
-1EA6,DISALLOWED,LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE
-1EA7,PVALID,LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE
-1EA8,DISALLOWED,LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE
-1EA9,PVALID,LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE
-1EAA,DISALLOWED,LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE
-1EAB,PVALID,LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE
-1EAC,DISALLOWED,LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW
-1EAD,PVALID,LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW
-1EAE,DISALLOWED,LATIN CAPITAL LETTER A WITH BREVE AND ACUTE
-1EAF,PVALID,LATIN SMALL LETTER A WITH BREVE AND ACUTE
-1EB0,DISALLOWED,LATIN CAPITAL LETTER A WITH BREVE AND GRAVE
-1EB1,PVALID,LATIN SMALL LETTER A WITH BREVE AND GRAVE
-1EB2,DISALLOWED,LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE
-1EB3,PVALID,LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE
-1EB4,DISALLOWED,LATIN CAPITAL LETTER A WITH BREVE AND TILDE
-1EB5,PVALID,LATIN SMALL LETTER A WITH BREVE AND TILDE
-1EB6,DISALLOWED,LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW
-1EB7,PVALID,LATIN SMALL LETTER A WITH BREVE AND DOT BELOW
-1EB8,DISALLOWED,LATIN CAPITAL LETTER E WITH DOT BELOW
-1EB9,PVALID,LATIN SMALL LETTER E WITH DOT BELOW
-1EBA,DISALLOWED,LATIN CAPITAL LETTER E WITH HOOK ABOVE
-1EBB,PVALID,LATIN SMALL LETTER E WITH HOOK ABOVE
-1EBC,DISALLOWED,LATIN CAPITAL LETTER E WITH TILDE
-1EBD,PVALID,LATIN SMALL LETTER E WITH TILDE
-1EBE,DISALLOWED,LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE
-1EBF,PVALID,LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE
-1EC0,DISALLOWED,LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE
-1EC1,PVALID,LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE
-1EC2,DISALLOWED,LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE
-1EC3,PVALID,LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE
-1EC4,DISALLOWED,LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE
-1EC5,PVALID,LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE
-1EC6,DISALLOWED,LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW
-1EC7,PVALID,LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW
-1EC8,DISALLOWED,LATIN CAPITAL LETTER I WITH HOOK ABOVE
-1EC9,PVALID,LATIN SMALL LETTER I WITH HOOK ABOVE
-1ECA,DISALLOWED,LATIN CAPITAL LETTER I WITH DOT BELOW
-1ECB,PVALID,LATIN SMALL LETTER I WITH DOT BELOW
-1ECC,DISALLOWED,LATIN CAPITAL LETTER O WITH DOT BELOW
-1ECD,PVALID,LATIN SMALL LETTER O WITH DOT BELOW
-1ECE,DISALLOWED,LATIN CAPITAL LETTER O WITH HOOK ABOVE
-1ECF,PVALID,LATIN SMALL LETTER O WITH HOOK ABOVE
-1ED0,DISALLOWED,LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE
-1ED1,PVALID,LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE
-1ED2,DISALLOWED,LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE
-1ED3,PVALID,LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE
-1ED4,DISALLOWED,LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE
-1ED5,PVALID,LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE
-1ED6,DISALLOWED,LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE
-1ED7,PVALID,LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE
-1ED8,DISALLOWED,LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW
-1ED9,PVALID,LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW
-1EDA,DISALLOWED,LATIN CAPITAL LETTER O WITH HORN AND ACUTE
-1EDB,PVALID,LATIN SMALL LETTER O WITH HORN AND ACUTE
-1EDC,DISALLOWED,LATIN CAPITAL LETTER O WITH HORN AND GRAVE
-1EDD,PVALID,LATIN SMALL LETTER O WITH HORN AND GRAVE
-1EDE,DISALLOWED,LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE
-1EDF,PVALID,LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE
-1EE0,DISALLOWED,LATIN CAPITAL LETTER O WITH HORN AND TILDE
-1EE1,PVALID,LATIN SMALL LETTER O WITH HORN AND TILDE
-1EE2,DISALLOWED,LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW
-1EE3,PVALID,LATIN SMALL LETTER O WITH HORN AND DOT BELOW
-1EE4,DISALLOWED,LATIN CAPITAL LETTER U WITH DOT BELOW
-1EE5,PVALID,LATIN SMALL LETTER U WITH DOT BELOW
-1EE6,DISALLOWED,LATIN CAPITAL LETTER U WITH HOOK ABOVE
-1EE7,PVALID,LATIN SMALL LETTER U WITH HOOK ABOVE
-1EE8,DISALLOWED,LATIN CAPITAL LETTER U WITH HORN AND ACUTE
-1EE9,PVALID,LATIN SMALL LETTER U WITH HORN AND ACUTE
-1EEA,DISALLOWED,LATIN CAPITAL LETTER U WITH HORN AND GRAVE
-1EEB,PVALID,LATIN SMALL LETTER U WITH HORN AND GRAVE
-1EEC,DISALLOWED,LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE
-1EED,PVALID,LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE
-1EEE,DISALLOWED,LATIN CAPITAL LETTER U WITH HORN AND TILDE
-1EEF,PVALID,LATIN SMALL LETTER U WITH HORN AND TILDE
-1EF0,DISALLOWED,LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW
-1EF1,PVALID,LATIN SMALL LETTER U WITH HORN AND DOT BELOW
-1EF2,DISALLOWED,LATIN CAPITAL LETTER Y WITH GRAVE
-1EF3,PVALID,LATIN SMALL LETTER Y WITH GRAVE
-1EF4,DISALLOWED,LATIN CAPITAL LETTER Y WITH DOT BELOW
-1EF5,PVALID,LATIN SMALL LETTER Y WITH DOT BELOW
-1EF6,DISALLOWED,LATIN CAPITAL LETTER Y WITH HOOK ABOVE
-1EF7,PVALID,LATIN SMALL LETTER Y WITH HOOK ABOVE
-1EF8,DISALLOWED,LATIN CAPITAL LETTER Y WITH TILDE
-1EF9,PVALID,LATIN SMALL LETTER Y WITH TILDE
-1EFA,DISALLOWED,LATIN CAPITAL LETTER MIDDLE-WELSH LL
-1EFB,PVALID,LATIN SMALL LETTER MIDDLE-WELSH LL
-1EFC,DISALLOWED,LATIN CAPITAL LETTER MIDDLE-WELSH V
-1EFD,PVALID,LATIN SMALL LETTER MIDDLE-WELSH V
-1EFE,DISALLOWED,LATIN CAPITAL LETTER Y WITH LOOP
-1EFF-1F07,PVALID,LATIN SMALL LETTER Y WITH LOOP..GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI
-1F08-1F0F,DISALLOWED,GREEK CAPITAL LETTER ALPHA WITH PSILI..GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI
-1F10-1F15,PVALID,GREEK SMALL LETTER EPSILON WITH PSILI..GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA
-1F16-1F17,UNASSIGNED,<RESERVED>..<RESERVED>
-1F18-1F1D,DISALLOWED,GREEK CAPITAL LETTER EPSILON WITH PSILI..GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA
-1F1E-1F1F,UNASSIGNED,<RESERVED>..<RESERVED>
-1F20-1F27,PVALID,GREEK SMALL LETTER ETA WITH PSILI..GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI
-1F28-1F2F,DISALLOWED,GREEK CAPITAL LETTER ETA WITH PSILI..GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI
-1F30-1F37,PVALID,GREEK SMALL LETTER IOTA WITH PSILI..GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI
-1F38-1F3F,DISALLOWED,GREEK CAPITAL LETTER IOTA WITH PSILI..GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI
-1F40-1F45,PVALID,GREEK SMALL LETTER OMICRON WITH PSILI..GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA
-1F46-1F47,UNASSIGNED,<RESERVED>..<RESERVED>
-1F48-1F4D,DISALLOWED,GREEK CAPITAL LETTER OMICRON WITH PSILI..GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA
-1F4E-1F4F,UNASSIGNED,<RESERVED>..<RESERVED>
-1F50-1F57,PVALID,GREEK SMALL LETTER UPSILON WITH PSILI..GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI
-1F58,UNASSIGNED,<RESERVED>
-1F59,DISALLOWED,GREEK CAPITAL LETTER UPSILON WITH DASIA
-1F5A,UNASSIGNED,<RESERVED>
-1F5B,DISALLOWED,GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA
-1F5C,UNASSIGNED,<RESERVED>
-1F5D,DISALLOWED,GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA
-1F5E,UNASSIGNED,<RESERVED>
-1F5F,DISALLOWED,GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI
-1F60-1F67,PVALID,GREEK SMALL LETTER OMEGA WITH PSILI..GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI
-1F68-1F6F,DISALLOWED,GREEK CAPITAL LETTER OMEGA WITH PSILI..GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI
-1F70,PVALID,GREEK SMALL LETTER ALPHA WITH VARIA
-1F71,DISALLOWED,GREEK SMALL LETTER ALPHA WITH OXIA
-1F72,PVALID,GREEK SMALL LETTER EPSILON WITH VARIA
-1F73,DISALLOWED,GREEK SMALL LETTER EPSILON WITH OXIA
-1F74,PVALID,GREEK SMALL LETTER ETA WITH VARIA
-1F75,DISALLOWED,GREEK SMALL LETTER ETA WITH OXIA
-1F76,PVALID,GREEK SMALL LETTER IOTA WITH VARIA
-1F77,DISALLOWED,GREEK SMALL LETTER IOTA WITH OXIA
-1F78,PVALID,GREEK SMALL LETTER OMICRON WITH VARIA
-1F79,DISALLOWED,GREEK SMALL LETTER OMICRON WITH OXIA
-1F7A,PVALID,GREEK SMALL LETTER UPSILON WITH VARIA
-1F7B,DISALLOWED,GREEK SMALL LETTER UPSILON WITH OXIA
-1F7C,PVALID,GREEK SMALL LETTER OMEGA WITH VARIA
-1F7D,DISALLOWED,GREEK SMALL LETTER OMEGA WITH OXIA
-1F7E-1F7F,UNASSIGNED,<RESERVED>..<RESERVED>
-1F80-1FAF,DISALLOWED,GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI..GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI
-1FB0-1FB1,PVALID,GREEK SMALL LETTER ALPHA WITH VRACHY..GREEK SMALL LETTER ALPHA WITH MACRON
-1FB2-1FB4,DISALLOWED,GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI
-1FB5,UNASSIGNED,<RESERVED>
-1FB6,PVALID,GREEK SMALL LETTER ALPHA WITH PERISPOMENI
-1FB7-1FC4,DISALLOWED,GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI..GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI
-1FC5,UNASSIGNED,<RESERVED>
-1FC6,PVALID,GREEK SMALL LETTER ETA WITH PERISPOMENI
-1FC7-1FCF,DISALLOWED,GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI..GREEK PSILI AND PERISPOMENI
-1FD0-1FD2,PVALID,GREEK SMALL LETTER IOTA WITH VRACHY..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA
-1FD3,DISALLOWED,GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA
-1FD4-1FD5,UNASSIGNED,<RESERVED>..<RESERVED>
-1FD6-1FD7,PVALID,GREEK SMALL LETTER IOTA WITH PERISPOMENI..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI
-1FD8-1FDB,DISALLOWED,GREEK CAPITAL LETTER IOTA WITH VRACHY..GREEK CAPITAL LETTER IOTA WITH OXIA
-1FDC,UNASSIGNED,<RESERVED>
-1FDD-1FDF,DISALLOWED,GREEK DASIA AND VARIA..GREEK DASIA AND PERISPOMENI
-1FE0-1FE2,PVALID,GREEK SMALL LETTER UPSILON WITH VRACHY..GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA
-1FE3,DISALLOWED,GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA
-1FE4-1FE7,PVALID,GREEK SMALL LETTER RHO WITH PSILI..GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI
-1FE8-1FEF,DISALLOWED,GREEK CAPITAL LETTER UPSILON WITH VRACHY..GREEK VARIA
-1FF0-1FF1,UNASSIGNED,<RESERVED>..<RESERVED>
-1FF2-1FF4,DISALLOWED,GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI
-1FF5,UNASSIGNED,<RESERVED>
-1FF6,PVALID,GREEK SMALL LETTER OMEGA WITH PERISPOMENI
-1FF7-1FFE,DISALLOWED,GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI..GREEK DASIA
-1FFF,UNASSIGNED,<RESERVED>
-2000-200B,DISALLOWED,EN QUAD..ZERO WIDTH SPACE
-200C-200D,CONTEXTJ,ZERO WIDTH NON-JOINER..ZERO WIDTH JOINER
-200E-2064,DISALLOWED,LEFT-TO-RIGHT MARK..INVISIBLE PLUS
-2065-2069,UNASSIGNED,<RESERVED>..<RESERVED>
-206A-2071,DISALLOWED,INHIBIT SYMMETRIC SWAPPING..SUPERSCRIPT LATIN SMALL LETTER I
-2072-2073,UNASSIGNED,<RESERVED>..<RESERVED>
-2074-208E,DISALLOWED,SUPERSCRIPT FOUR..SUBSCRIPT RIGHT PARENTHESIS
-208F,UNASSIGNED,<RESERVED>
-2090-2094,DISALLOWED,LATIN SUBSCRIPT SMALL LETTER A..LATIN SUBSCRIPT SMALL LETTER SCHWA
-2095-209F,UNASSIGNED,<RESERVED>..<RESERVED>
-20A0-20B8,DISALLOWED,EURO-CURRENCY SIGN..TENGE SIGN
-20B9-20CF,UNASSIGNED,<RESERVED>..<RESERVED>
-20D0-20F0,DISALLOWED,COMBINING LEFT HARPOON ABOVE..COMBINING ASTERISK ABOVE
-20F1-20FF,UNASSIGNED,<RESERVED>..<RESERVED>
-2100-214D,DISALLOWED,ACCOUNT OF..AKTIESELSKAB
-214E,PVALID,TURNED SMALL F
-214F-2183,DISALLOWED,SYMBOL FOR SAMARITAN SOURCE..ROMAN NUMERAL REVERSED ONE HUNDRED
-2184,PVALID,LATIN SMALL LETTER REVERSED C
-2185-2189,DISALLOWED,ROMAN NUMERAL SIX LATE FORM..VULGAR FRACTION ZERO THIRDS
-218A-218F,UNASSIGNED,<RESERVED>..<RESERVED>
-2190-23E8,DISALLOWED,LEFTWARDS ARROW..DECIMAL EXPONENT SYMBOL
-23E9-23FF,UNASSIGNED,<RESERVED>..<RESERVED>
-2400-2426,DISALLOWED,SYMBOL FOR NULL..SYMBOL FOR SUBSTITUTE FORM TWO
-2427-243F,UNASSIGNED,<RESERVED>..<RESERVED>
-2440-244A,DISALLOWED,OCR HOOK..OCR DOUBLE BACKSLASH
-244B-245F,UNASSIGNED,<RESERVED>..<RESERVED>
-2460-26CD,DISALLOWED,CIRCLED DIGIT ONE..DISABLED CAR
-26CE,UNASSIGNED,<RESERVED>
-26CF-26E1,DISALLOWED,PICK..RESTRICTED LEFT ENTRY-2
-26E2,UNASSIGNED,<RESERVED>
-26E3,DISALLOWED,HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE
-26E4-26E7,UNASSIGNED,<RESERVED>..<RESERVED>
-26E8-26FF,DISALLOWED,BLACK CROSS ON SHIELD..WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE
-2700,UNASSIGNED,<RESERVED>
-2701-2704,DISALLOWED,UPPER BLADE SCISSORS..WHITE SCISSORS
-2705,UNASSIGNED,<RESERVED>
-2706-2709,DISALLOWED,TELEPHONE LOCATION SIGN..ENVELOPE
-270A-270B,UNASSIGNED,<RESERVED>..<RESERVED>
-270C-2727,DISALLOWED,VICTORY HAND..WHITE FOUR POINTED STAR
-2728,UNASSIGNED,<RESERVED>
-2729-274B,DISALLOWED,STRESS OUTLINED WHITE STAR..HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK
-274C,UNASSIGNED,<RESERVED>
-274D,DISALLOWED,SHADOWED WHITE CIRCLE
-274E,UNASSIGNED,<RESERVED>
-274F-2752,DISALLOWED,LOWER RIGHT DROP-SHADOWED WHITE SQUARE..UPPER RIGHT SHADOWED WHITE SQUARE
-2753-2755,UNASSIGNED,<RESERVED>..<RESERVED>
-2756-275E,DISALLOWED,BLACK DIAMOND MINUS WHITE X..HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT
-275F-2760,UNASSIGNED,<RESERVED>..<RESERVED>
-2761-2794,DISALLOWED,CURVED STEM PARAGRAPH SIGN ORNAMENT..HEAVY WIDE-HEADED RIGHTWARDS ARROW
-2795-2797,UNASSIGNED,<RESERVED>..<RESERVED>
-2798-27AF,DISALLOWED,HEAVY SOUTH EAST ARROW..NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW
-27B0,UNASSIGNED,<RESERVED>
-27B1-27BE,DISALLOWED,NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW..OPEN-OUTLINED RIGHTWARDS ARROW
-27BF,UNASSIGNED,<RESERVED>
-27C0-27CA,DISALLOWED,THREE DIMENSIONAL ANGLE..VERTICAL BAR WITH HORIZONTAL STROKE
-27CB,UNASSIGNED,<RESERVED>
-27CC,DISALLOWED,LONG DIVISION
-27CD-27CF,UNASSIGNED,<RESERVED>..<RESERVED>
-27D0-2B4C,DISALLOWED,WHITE DIAMOND WITH CENTRED DOT..RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR
-2B4D-2B4F,UNASSIGNED,<RESERVED>..<RESERVED>
-2B50-2B59,DISALLOWED,WHITE MEDIUM STAR..HEAVY CIRCLED SALTIRE
-2B5A-2BFF,UNASSIGNED,<RESERVED>..<RESERVED>
-2C00-2C2E,DISALLOWED,GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE
-2C2F,UNASSIGNED,<RESERVED>
-2C30-2C5E,PVALID,GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE
-2C5F,UNASSIGNED,<RESERVED>
-2C60,DISALLOWED,LATIN CAPITAL LETTER L WITH DOUBLE BAR
-2C61,PVALID,LATIN SMALL LETTER L WITH DOUBLE BAR
-2C62-2C64,DISALLOWED,LATIN CAPITAL LETTER L WITH MIDDLE TILDE..LATIN CAPITAL LETTER R WITH TAIL
-2C65-2C66,PVALID,LATIN SMALL LETTER A WITH STROKE..LATIN SMALL LETTER T WITH DIAGONAL STROKE
-2C67,DISALLOWED,LATIN CAPITAL LETTER H WITH DESCENDER
-2C68,PVALID,LATIN SMALL LETTER H WITH DESCENDER
-2C69,DISALLOWED,LATIN CAPITAL LETTER K WITH DESCENDER
-2C6A,PVALID,LATIN SMALL LETTER K WITH DESCENDER
-2C6B,DISALLOWED,LATIN CAPITAL LETTER Z WITH DESCENDER
-2C6C,PVALID,LATIN SMALL LETTER Z WITH DESCENDER
-2C6D-2C70,DISALLOWED,LATIN CAPITAL LETTER ALPHA..LATIN CAPITAL LETTER TURNED ALPHA
-2C71,PVALID,LATIN SMALL LETTER V WITH RIGHT HOOK
-2C72,DISALLOWED,LATIN CAPITAL LETTER W WITH HOOK
-2C73-2C74,PVALID,LATIN SMALL LETTER W WITH HOOK..LATIN SMALL LETTER V WITH CURL
-2C75,DISALLOWED,LATIN CAPITAL LETTER HALF H
-2C76-2C7B,PVALID,LATIN SMALL LETTER HALF H..LATIN LETTER SMALL CAPITAL TURNED E
-2C7C-2C80,DISALLOWED,LATIN SUBSCRIPT SMALL LETTER J..COPTIC CAPITAL LETTER ALFA
-2C81,PVALID,COPTIC SMALL LETTER ALFA
-2C82,DISALLOWED,COPTIC CAPITAL LETTER VIDA
-2C83,PVALID,COPTIC SMALL LETTER VIDA
-2C84,DISALLOWED,COPTIC CAPITAL LETTER GAMMA
-2C85,PVALID,COPTIC SMALL LETTER GAMMA
-2C86,DISALLOWED,COPTIC CAPITAL LETTER DALDA
-2C87,PVALID,COPTIC SMALL LETTER DALDA
-2C88,DISALLOWED,COPTIC CAPITAL LETTER EIE
-2C89,PVALID,COPTIC SMALL LETTER EIE
-2C8A,DISALLOWED,COPTIC CAPITAL LETTER SOU
-2C8B,PVALID,COPTIC SMALL LETTER SOU
-2C8C,DISALLOWED,COPTIC CAPITAL LETTER ZATA
-2C8D,PVALID,COPTIC SMALL LETTER ZATA
-2C8E,DISALLOWED,COPTIC CAPITAL LETTER HATE
-2C8F,PVALID,COPTIC SMALL LETTER HATE
-2C90,DISALLOWED,COPTIC CAPITAL LETTER THETHE
-2C91,PVALID,COPTIC SMALL LETTER THETHE
-2C92,DISALLOWED,COPTIC CAPITAL LETTER IAUDA
-2C93,PVALID,COPTIC SMALL LETTER IAUDA
-2C94,DISALLOWED,COPTIC CAPITAL LETTER KAPA
-2C95,PVALID,COPTIC SMALL LETTER KAPA
-2C96,DISALLOWED,COPTIC CAPITAL LETTER LAULA
-2C97,PVALID,COPTIC SMALL LETTER LAULA
-2C98,DISALLOWED,COPTIC CAPITAL LETTER MI
-2C99,PVALID,COPTIC SMALL LETTER MI
-2C9A,DISALLOWED,COPTIC CAPITAL LETTER NI
-2C9B,PVALID,COPTIC SMALL LETTER NI
-2C9C,DISALLOWED,COPTIC CAPITAL LETTER KSI
-2C9D,PVALID,COPTIC SMALL LETTER KSI
-2C9E,DISALLOWED,COPTIC CAPITAL LETTER O
-2C9F,PVALID,COPTIC SMALL LETTER O
-2CA0,DISALLOWED,COPTIC CAPITAL LETTER PI
-2CA1,PVALID,COPTIC SMALL LETTER PI
-2CA2,DISALLOWED,COPTIC CAPITAL LETTER RO
-2CA3,PVALID,COPTIC SMALL LETTER RO
-2CA4,DISALLOWED,COPTIC CAPITAL LETTER SIMA
-2CA5,PVALID,COPTIC SMALL LETTER SIMA
-2CA6,DISALLOWED,COPTIC CAPITAL LETTER TAU
-2CA7,PVALID,COPTIC SMALL LETTER TAU
-2CA8,DISALLOWED,COPTIC CAPITAL LETTER UA
-2CA9,PVALID,COPTIC SMALL LETTER UA
-2CAA,DISALLOWED,COPTIC CAPITAL LETTER FI
-2CAB,PVALID,COPTIC SMALL LETTER FI
-2CAC,DISALLOWED,COPTIC CAPITAL LETTER KHI
-2CAD,PVALID,COPTIC SMALL LETTER KHI
-2CAE,DISALLOWED,COPTIC CAPITAL LETTER PSI
-2CAF,PVALID,COPTIC SMALL LETTER PSI
-2CB0,DISALLOWED,COPTIC CAPITAL LETTER OOU
-2CB1,PVALID,COPTIC SMALL LETTER OOU
-2CB2,DISALLOWED,COPTIC CAPITAL LETTER DIALECT-P ALEF
-2CB3,PVALID,COPTIC SMALL LETTER DIALECT-P ALEF
-2CB4,DISALLOWED,COPTIC CAPITAL LETTER OLD COPTIC AIN
-2CB5,PVALID,COPTIC SMALL LETTER OLD COPTIC AIN
-2CB6,DISALLOWED,COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE
-2CB7,PVALID,COPTIC SMALL LETTER CRYPTOGRAMMIC EIE
-2CB8,DISALLOWED,COPTIC CAPITAL LETTER DIALECT-P KAPA
-2CB9,PVALID,COPTIC SMALL LETTER DIALECT-P KAPA
-2CBA,DISALLOWED,COPTIC CAPITAL LETTER DIALECT-P NI
-2CBB,PVALID,COPTIC SMALL LETTER DIALECT-P NI
-2CBC,DISALLOWED,COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI
-2CBD,PVALID,COPTIC SMALL LETTER CRYPTOGRAMMIC NI
-2CBE,DISALLOWED,COPTIC CAPITAL LETTER OLD COPTIC OOU
-2CBF,PVALID,COPTIC SMALL LETTER OLD COPTIC OOU
-2CC0,DISALLOWED,COPTIC CAPITAL LETTER SAMPI
-2CC1,PVALID,COPTIC SMALL LETTER SAMPI
-2CC2,DISALLOWED,COPTIC CAPITAL LETTER CROSSED SHEI
-2CC3,PVALID,COPTIC SMALL LETTER CROSSED SHEI
-2CC4,DISALLOWED,COPTIC CAPITAL LETTER OLD COPTIC SHEI
-2CC5,PVALID,COPTIC SMALL LETTER OLD COPTIC SHEI
-2CC6,DISALLOWED,COPTIC CAPITAL LETTER OLD COPTIC ESH
-2CC7,PVALID,COPTIC SMALL LETTER OLD COPTIC ESH
-2CC8,DISALLOWED,COPTIC CAPITAL LETTER AKHMIMIC KHEI
-2CC9,PVALID,COPTIC SMALL LETTER AKHMIMIC KHEI
-2CCA,DISALLOWED,COPTIC CAPITAL LETTER DIALECT-P HORI
-2CCB,PVALID,COPTIC SMALL LETTER DIALECT-P HORI
-2CCC,DISALLOWED,COPTIC CAPITAL LETTER OLD COPTIC HORI
-2CCD,PVALID,COPTIC SMALL LETTER OLD COPTIC HORI
-2CCE,DISALLOWED,COPTIC CAPITAL LETTER OLD COPTIC HA
-2CCF,PVALID,COPTIC SMALL LETTER OLD COPTIC HA
-2CD0,DISALLOWED,COPTIC CAPITAL LETTER L-SHAPED HA
-2CD1,PVALID,COPTIC SMALL LETTER L-SHAPED HA
-2CD2,DISALLOWED,COPTIC CAPITAL LETTER OLD COPTIC HEI
-2CD3,PVALID,COPTIC SMALL LETTER OLD COPTIC HEI
-2CD4,DISALLOWED,COPTIC CAPITAL LETTER OLD COPTIC HAT
-2CD5,PVALID,COPTIC SMALL LETTER OLD COPTIC HAT
-2CD6,DISALLOWED,COPTIC CAPITAL LETTER OLD COPTIC GANGIA
-2CD7,PVALID,COPTIC SMALL LETTER OLD COPTIC GANGIA
-2CD8,DISALLOWED,COPTIC CAPITAL LETTER OLD COPTIC DJA
-2CD9,PVALID,COPTIC SMALL LETTER OLD COPTIC DJA
-2CDA,DISALLOWED,COPTIC CAPITAL LETTER OLD COPTIC SHIMA
-2CDB,PVALID,COPTIC SMALL LETTER OLD COPTIC SHIMA
-2CDC,DISALLOWED,COPTIC CAPITAL LETTER OLD NUBIAN SHIMA
-2CDD,PVALID,COPTIC SMALL LETTER OLD NUBIAN SHIMA
-2CDE,DISALLOWED,COPTIC CAPITAL LETTER OLD NUBIAN NGI
-2CDF,PVALID,COPTIC SMALL LETTER OLD NUBIAN NGI
-2CE0,DISALLOWED,COPTIC CAPITAL LETTER OLD NUBIAN NYI
-2CE1,PVALID,COPTIC SMALL LETTER OLD NUBIAN NYI
-2CE2,DISALLOWED,COPTIC CAPITAL LETTER OLD NUBIAN WAU
-2CE3-2CE4,PVALID,COPTIC SMALL LETTER OLD NUBIAN WAU..COPTIC SYMBOL KAI
-2CE5-2CEB,DISALLOWED,COPTIC SYMBOL MI RO..COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI
-2CEC,PVALID,COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI
-2CED,DISALLOWED,COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA
-2CEE-2CF1,PVALID,COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA..COPTIC COMBINING SPIRITUS LENIS
-2CF2-2CF8,UNASSIGNED,<RESERVED>..<RESERVED>
-2CF9-2CFF,DISALLOWED,COPTIC OLD NUBIAN FULL STOP..COPTIC MORPHOLOGICAL DIVIDER
-2D00-2D25,PVALID,GEORGIAN SMALL LETTER AN..GEORGIAN SMALL LETTER HOE
-2D26-2D2F,UNASSIGNED,<RESERVED>..<RESERVED>
-2D30-2D65,PVALID,TIFINAGH LETTER YA..TIFINAGH LETTER YAZZ
-2D66-2D6E,UNASSIGNED,<RESERVED>..<RESERVED>
-2D6F,DISALLOWED,TIFINAGH MODIFIER LETTER LABIALIZATION MARK
-2D70-2D7F,UNASSIGNED,<RESERVED>..<RESERVED>
-2D80-2D96,PVALID,ETHIOPIC SYLLABLE LOA..ETHIOPIC SYLLABLE GGWE
-2D97-2D9F,UNASSIGNED,<RESERVED>..<RESERVED>
-2DA0-2DA6,PVALID,ETHIOPIC SYLLABLE SSA..ETHIOPIC SYLLABLE SSO
-2DA7,UNASSIGNED,<RESERVED>
-2DA8-2DAE,PVALID,ETHIOPIC SYLLABLE CCA..ETHIOPIC SYLLABLE CCO
-2DAF,UNASSIGNED,<RESERVED>
-2DB0-2DB6,PVALID,ETHIOPIC SYLLABLE ZZA..ETHIOPIC SYLLABLE ZZO
-2DB7,UNASSIGNED,<RESERVED>
-2DB8-2DBE,PVALID,ETHIOPIC SYLLABLE CCHA..ETHIOPIC SYLLABLE CCHO
-2DBF,UNASSIGNED,<RESERVED>
-2DC0-2DC6,PVALID,ETHIOPIC SYLLABLE QYA..ETHIOPIC SYLLABLE QYO
-2DC7,UNASSIGNED,<RESERVED>
-2DC8-2DCE,PVALID,ETHIOPIC SYLLABLE KYA..ETHIOPIC SYLLABLE KYO
-2DCF,UNASSIGNED,<RESERVED>
-2DD0-2DD6,PVALID,ETHIOPIC SYLLABLE XYA..ETHIOPIC SYLLABLE XYO
-2DD7,UNASSIGNED,<RESERVED>
-2DD8-2DDE,PVALID,ETHIOPIC SYLLABLE GYA..ETHIOPIC SYLLABLE GYO
-2DDF,UNASSIGNED,<RESERVED>
-2DE0-2DFF,PVALID,COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS
-2E00-2E2E,DISALLOWED,RIGHT ANGLE SUBSTITUTION MARKER..REVERSED QUESTION MARK
-2E2F,PVALID,VERTICAL TILDE
-2E30-2E31,DISALLOWED,RING POINT..WORD SEPARATOR MIDDLE DOT
-2E32-2E7F,UNASSIGNED,<RESERVED>..<RESERVED>
-2E80-2E99,DISALLOWED,CJK RADICAL REPEAT..CJK RADICAL RAP
-2E9A,UNASSIGNED,<RESERVED>
-2E9B-2EF3,DISALLOWED,CJK RADICAL CHOKE..CJK RADICAL C-SIMPLIFIED TURTLE
-2EF4-2EFF,UNASSIGNED,<RESERVED>..<RESERVED>
-2F00-2FD5,DISALLOWED,KANGXI RADICAL ONE..KANGXI RADICAL FLUTE
-2FD6-2FEF,UNASSIGNED,<RESERVED>..<RESERVED>
-2FF0-2FFB,DISALLOWED,IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID
-2FFC-2FFF,UNASSIGNED,<RESERVED>..<RESERVED>
-3000-3004,DISALLOWED,IDEOGRAPHIC SPACE..JAPANESE INDUSTRIAL STANDARD SYMBOL
-3005-3007,PVALID,IDEOGRAPHIC ITERATION MARK..IDEOGRAPHIC NUMBER ZERO
-3008-3029,DISALLOWED,LEFT ANGLE BRACKET..HANGZHOU NUMERAL NINE
-302A-302D,PVALID,IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK
-302E-303B,DISALLOWED,HANGUL SINGLE DOT TONE MARK..VERTICAL IDEOGRAPHIC ITERATION MARK
-303C,PVALID,MASU MARK
-303D-303F,DISALLOWED,PART ALTERNATION MARK..IDEOGRAPHIC HALF FILL SPACE
-3040,UNASSIGNED,<RESERVED>
-3041-3096,PVALID,HIRAGANA LETTER SMALL A..HIRAGANA LETTER SMALL KE
-3097-3098,UNASSIGNED,<RESERVED>..<RESERVED>
-3099-309A,PVALID,COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
-309B-309C,DISALLOWED,KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
-309D-309E,PVALID,HIRAGANA ITERATION MARK..HIRAGANA VOICED ITERATION MARK
-309F-30A0,DISALLOWED,HIRAGANA DIGRAPH YORI..KATAKANA-HIRAGANA DOUBLE HYPHEN
-30A1-30FA,PVALID,KATAKANA LETTER SMALL A..KATAKANA LETTER VO
-30FB,CONTEXTO,KATAKANA MIDDLE DOT
-30FC-30FE,PVALID,KATAKANA-HIRAGANA PROLONGED SOUND MARK..KATAKANA VOICED ITERATION MARK
-30FF,DISALLOWED,KATAKANA DIGRAPH KOTO
-3100-3104,UNASSIGNED,<RESERVED>..<RESERVED>
-3105-312D,PVALID,BOPOMOFO LETTER B..BOPOMOFO LETTER IH
-312E-3130,UNASSIGNED,<RESERVED>..<RESERVED>
-3131-318E,DISALLOWED,HANGUL LETTER KIYEOK..HANGUL LETTER ARAEAE
-318F,UNASSIGNED,<RESERVED>
-3190-319F,DISALLOWED,IDEOGRAPHIC ANNOTATION LINKING MARK..IDEOGRAPHIC ANNOTATION MAN MARK
-31A0-31B7,PVALID,BOPOMOFO LETTER BU..BOPOMOFO FINAL LETTER H
-31B8-31BF,UNASSIGNED,<RESERVED>..<RESERVED>
-31C0-31E3,DISALLOWED,CJK STROKE T..CJK STROKE Q
-31E4-31EF,UNASSIGNED,<RESERVED>..<RESERVED>
-31F0-31FF,PVALID,KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO
-3200-321E,DISALLOWED,PARENTHESIZED HANGUL KIYEOK..PARENTHESIZED KOREAN CHARACTER O HU
-321F,UNASSIGNED,<RESERVED>
-3220-32FE,DISALLOWED,PARENTHESIZED IDEOGRAPH ONE..CIRCLED KATAKANA WO
-32FF,UNASSIGNED,<RESERVED>
-3300-33FF,DISALLOWED,SQUARE APAATO..SQUARE GAL
-3400-4DB5,PVALID,"<CJK IDEOGRAPH EXTENSION A, FIRST>..<CJK IDEOGRAPH EXTENSION A, LAST>"
-4DB6-4DBF,UNASSIGNED,<RESERVED>..<RESERVED>
-4DC0-4DFF,DISALLOWED,HEXAGRAM FOR THE CREATIVE HEAVEN..HEXAGRAM FOR BEFORE COMPLETION
-4E00-9FCB,PVALID,"<CJK IDEOGRAPH, FIRST>..<CJK IDEOGRAPH, LAST>"
-9FCC-9FFF,UNASSIGNED,<RESERVED>..<RESERVED>
-A000-A48C,PVALID,YI SYLLABLE IT..YI SYLLABLE YYR
-A48D-A48F,UNASSIGNED,<RESERVED>..<RESERVED>
-A490-A4C6,DISALLOWED,YI RADICAL QOT..YI RADICAL KE
-A4C7-A4CF,UNASSIGNED,<RESERVED>..<RESERVED>
-A4D0-A4FD,PVALID,LISU LETTER BA..LISU LETTER TONE MYA JEU
-A4FE-A4FF,DISALLOWED,LISU PUNCTUATION COMMA..LISU PUNCTUATION FULL STOP
-A500-A60C,PVALID,VAI SYLLABLE EE..VAI SYLLABLE LENGTHENER
-A60D-A60F,DISALLOWED,VAI COMMA..VAI QUESTION MARK
-A610-A62B,PVALID,VAI SYLLABLE NDOLE FA..VAI SYLLABLE NDOLE DO
-A62C-A63F,UNASSIGNED,<RESERVED>..<RESERVED>
-A640,DISALLOWED,CYRILLIC CAPITAL LETTER ZEMLYA
-A641,PVALID,CYRILLIC SMALL LETTER ZEMLYA
-A642,DISALLOWED,CYRILLIC CAPITAL LETTER DZELO
-A643,PVALID,CYRILLIC SMALL LETTER DZELO
-A644,DISALLOWED,CYRILLIC CAPITAL LETTER REVERSED DZE
-A645,PVALID,CYRILLIC SMALL LETTER REVERSED DZE
-A646,DISALLOWED,CYRILLIC CAPITAL LETTER IOTA
-A647,PVALID,CYRILLIC SMALL LETTER IOTA
-A648,DISALLOWED,CYRILLIC CAPITAL LETTER DJERV
-A649,PVALID,CYRILLIC SMALL LETTER DJERV
-A64A,DISALLOWED,CYRILLIC CAPITAL LETTER MONOGRAPH UK
-A64B,PVALID,CYRILLIC SMALL LETTER MONOGRAPH UK
-A64C,DISALLOWED,CYRILLIC CAPITAL LETTER BROAD OMEGA
-A64D,PVALID,CYRILLIC SMALL LETTER BROAD OMEGA
-A64E,DISALLOWED,CYRILLIC CAPITAL LETTER NEUTRAL YER
-A64F,PVALID,CYRILLIC SMALL LETTER NEUTRAL YER
-A650,DISALLOWED,CYRILLIC CAPITAL LETTER YERU WITH BACK YER
-A651,PVALID,CYRILLIC SMALL LETTER YERU WITH BACK YER
-A652,DISALLOWED,CYRILLIC CAPITAL LETTER IOTIFIED YAT
-A653,PVALID,CYRILLIC SMALL LETTER IOTIFIED YAT
-A654,DISALLOWED,CYRILLIC CAPITAL LETTER REVERSED YU
-A655,PVALID,CYRILLIC SMALL LETTER REVERSED YU
-A656,DISALLOWED,CYRILLIC CAPITAL LETTER IOTIFIED A
-A657,PVALID,CYRILLIC SMALL LETTER IOTIFIED A
-A658,DISALLOWED,CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS
-A659,PVALID,CYRILLIC SMALL LETTER CLOSED LITTLE YUS
-A65A,DISALLOWED,CYRILLIC CAPITAL LETTER BLENDED YUS
-A65B,PVALID,CYRILLIC SMALL LETTER BLENDED YUS
-A65C,DISALLOWED,CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS
-A65D,PVALID,CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS
-A65E,DISALLOWED,CYRILLIC CAPITAL LETTER YN
-A65F,PVALID,CYRILLIC SMALL LETTER YN
-A660-A661,UNASSIGNED,<RESERVED>..<RESERVED>
-A662,DISALLOWED,CYRILLIC CAPITAL LETTER SOFT DE
-A663,PVALID,CYRILLIC SMALL LETTER SOFT DE
-A664,DISALLOWED,CYRILLIC CAPITAL LETTER SOFT EL
-A665,PVALID,CYRILLIC SMALL LETTER SOFT EL
-A666,DISALLOWED,CYRILLIC CAPITAL LETTER SOFT EM
-A667,PVALID,CYRILLIC SMALL LETTER SOFT EM
-A668,DISALLOWED,CYRILLIC CAPITAL LETTER MONOCULAR O
-A669,PVALID,CYRILLIC SMALL LETTER MONOCULAR O
-A66A,DISALLOWED,CYRILLIC CAPITAL LETTER BINOCULAR O
-A66B,PVALID,CYRILLIC SMALL LETTER BINOCULAR O
-A66C,DISALLOWED,CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O
-A66D-A66F,PVALID,CYRILLIC SMALL LETTER DOUBLE MONOCULAR O..COMBINING CYRILLIC VZMET
-A670-A673,DISALLOWED,COMBINING CYRILLIC TEN MILLIONS SIGN..SLAVONIC ASTERISK
-A674-A67B,UNASSIGNED,<RESERVED>..<RESERVED>
-A67C-A67D,PVALID,COMBINING CYRILLIC KAVYKA..COMBINING CYRILLIC PAYEROK
-A67E,DISALLOWED,CYRILLIC KAVYKA
-A67F,PVALID,CYRILLIC PAYEROK
-A680,DISALLOWED,CYRILLIC CAPITAL LETTER DWE
-A681,PVALID,CYRILLIC SMALL LETTER DWE
-A682,DISALLOWED,CYRILLIC CAPITAL LETTER DZWE
-A683,PVALID,CYRILLIC SMALL LETTER DZWE
-A684,DISALLOWED,CYRILLIC CAPITAL LETTER ZHWE
-A685,PVALID,CYRILLIC SMALL LETTER ZHWE
-A686,DISALLOWED,CYRILLIC CAPITAL LETTER CCHE
-A687,PVALID,CYRILLIC SMALL LETTER CCHE
-A688,DISALLOWED,CYRILLIC CAPITAL LETTER DZZE
-A689,PVALID,CYRILLIC SMALL LETTER DZZE
-A68A,DISALLOWED,CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK
-A68B,PVALID,CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK
-A68C,DISALLOWED,CYRILLIC CAPITAL LETTER TWE
-A68D,PVALID,CYRILLIC SMALL LETTER TWE
-A68E,DISALLOWED,CYRILLIC CAPITAL LETTER TSWE
-A68F,PVALID,CYRILLIC SMALL LETTER TSWE
-A690,DISALLOWED,CYRILLIC CAPITAL LETTER TSSE
-A691,PVALID,CYRILLIC SMALL LETTER TSSE
-A692,DISALLOWED,CYRILLIC CAPITAL LETTER TCHE
-A693,PVALID,CYRILLIC SMALL LETTER TCHE
-A694,DISALLOWED,CYRILLIC CAPITAL LETTER HWE
-A695,PVALID,CYRILLIC SMALL LETTER HWE
-A696,DISALLOWED,CYRILLIC CAPITAL LETTER SHWE
-A697,PVALID,CYRILLIC SMALL LETTER SHWE
-A698-A69F,UNASSIGNED,<RESERVED>..<RESERVED>
-A6A0-A6E5,PVALID,BAMUM LETTER A..BAMUM LETTER KI
-A6E6-A6EF,DISALLOWED,BAMUM LETTER MO..BAMUM LETTER KOGHOM
-A6F0-A6F1,PVALID,BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS
-A6F2-A6F7,DISALLOWED,BAMUM NJAEMLI..BAMUM QUESTION MARK
-A6F8-A6FF,UNASSIGNED,<RESERVED>..<RESERVED>
-A700-A716,DISALLOWED,MODIFIER LETTER CHINESE TONE YIN PING..MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR
-A717-A71F,PVALID,MODIFIER LETTER DOT VERTICAL BAR..MODIFIER LETTER LOW INVERTED EXCLAMATION MARK
-A720-A722,DISALLOWED,MODIFIER LETTER STRESS AND HIGH TONE..LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF
-A723,PVALID,LATIN SMALL LETTER EGYPTOLOGICAL ALEF
-A724,DISALLOWED,LATIN CAPITAL LETTER EGYPTOLOGICAL AIN
-A725,PVALID,LATIN SMALL LETTER EGYPTOLOGICAL AIN
-A726,DISALLOWED,LATIN CAPITAL LETTER HENG
-A727,PVALID,LATIN SMALL LETTER HENG
-A728,DISALLOWED,LATIN CAPITAL LETTER TZ
-A729,PVALID,LATIN SMALL LETTER TZ
-A72A,DISALLOWED,LATIN CAPITAL LETTER TRESILLO
-A72B,PVALID,LATIN SMALL LETTER TRESILLO
-A72C,DISALLOWED,LATIN CAPITAL LETTER CUATRILLO
-A72D,PVALID,LATIN SMALL LETTER CUATRILLO
-A72E,DISALLOWED,LATIN CAPITAL LETTER CUATRILLO WITH COMMA
-A72F-A731,PVALID,LATIN SMALL LETTER CUATRILLO WITH COMMA..LATIN LETTER SMALL CAPITAL S
-A732,DISALLOWED,LATIN CAPITAL LETTER AA
-A733,PVALID,LATIN SMALL LETTER AA
-A734,DISALLOWED,LATIN CAPITAL LETTER AO
-A735,PVALID,LATIN SMALL LETTER AO
-A736,DISALLOWED,LATIN CAPITAL LETTER AU
-A737,PVALID,LATIN SMALL LETTER AU
-A738,DISALLOWED,LATIN CAPITAL LETTER AV
-A739,PVALID,LATIN SMALL LETTER AV
-A73A,DISALLOWED,LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR
-A73B,PVALID,LATIN SMALL LETTER AV WITH HORIZONTAL BAR
-A73C,DISALLOWED,LATIN CAPITAL LETTER AY
-A73D,PVALID,LATIN SMALL LETTER AY
-A73E,DISALLOWED,LATIN CAPITAL LETTER REVERSED C WITH DOT
-A73F,PVALID,LATIN SMALL LETTER REVERSED C WITH DOT
-A740,DISALLOWED,LATIN CAPITAL LETTER K WITH STROKE
-A741,PVALID,LATIN SMALL LETTER K WITH STROKE
-A742,DISALLOWED,LATIN CAPITAL LETTER K WITH DIAGONAL STROKE
-A743,PVALID,LATIN SMALL LETTER K WITH DIAGONAL STROKE
-A744,DISALLOWED,LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE
-A745,PVALID,LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE
-A746,DISALLOWED,LATIN CAPITAL LETTER BROKEN L
-A747,PVALID,LATIN SMALL LETTER BROKEN L
-A748,DISALLOWED,LATIN CAPITAL LETTER L WITH HIGH STROKE
-A749,PVALID,LATIN SMALL LETTER L WITH HIGH STROKE
-A74A,DISALLOWED,LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY
-A74B,PVALID,LATIN SMALL LETTER O WITH LONG STROKE OVERLAY
-A74C,DISALLOWED,LATIN CAPITAL LETTER O WITH LOOP
-A74D,PVALID,LATIN SMALL LETTER O WITH LOOP
-A74E,DISALLOWED,LATIN CAPITAL LETTER OO
-A74F,PVALID,LATIN SMALL LETTER OO
-A750,DISALLOWED,LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER
-A751,PVALID,LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER
-A752,DISALLOWED,LATIN CAPITAL LETTER P WITH FLOURISH
-A753,PVALID,LATIN SMALL LETTER P WITH FLOURISH
-A754,DISALLOWED,LATIN CAPITAL LETTER P WITH SQUIRREL TAIL
-A755,PVALID,LATIN SMALL LETTER P WITH SQUIRREL TAIL
-A756,DISALLOWED,LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER
-A757,PVALID,LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER
-A758,DISALLOWED,LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE
-A759,PVALID,LATIN SMALL LETTER Q WITH DIAGONAL STROKE
-A75A,DISALLOWED,LATIN CAPITAL LETTER R ROTUNDA
-A75B,PVALID,LATIN SMALL LETTER R ROTUNDA
-A75C,DISALLOWED,LATIN CAPITAL LETTER RUM ROTUNDA
-A75D,PVALID,LATIN SMALL LETTER RUM ROTUNDA
-A75E,DISALLOWED,LATIN CAPITAL LETTER V WITH DIAGONAL STROKE
-A75F,PVALID,LATIN SMALL LETTER V WITH DIAGONAL STROKE
-A760,DISALLOWED,LATIN CAPITAL LETTER VY
-A761,PVALID,LATIN SMALL LETTER VY
-A762,DISALLOWED,LATIN CAPITAL LETTER VISIGOTHIC Z
-A763,PVALID,LATIN SMALL LETTER VISIGOTHIC Z
-A764,DISALLOWED,LATIN CAPITAL LETTER THORN WITH STROKE
-A765,PVALID,LATIN SMALL LETTER THORN WITH STROKE
-A766,DISALLOWED,LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER
-A767,PVALID,LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER
-A768,DISALLOWED,LATIN CAPITAL LETTER VEND
-A769,PVALID,LATIN SMALL LETTER VEND
-A76A,DISALLOWED,LATIN CAPITAL LETTER ET
-A76B,PVALID,LATIN SMALL LETTER ET
-A76C,DISALLOWED,LATIN CAPITAL LETTER IS
-A76D,PVALID,LATIN SMALL LETTER IS
-A76E,DISALLOWED,LATIN CAPITAL LETTER CON
-A76F,PVALID,LATIN SMALL LETTER CON
-A770,DISALLOWED,MODIFIER LETTER US
-A771-A778,PVALID,LATIN SMALL LETTER DUM..LATIN SMALL LETTER UM
-A779,DISALLOWED,LATIN CAPITAL LETTER INSULAR D
-A77A,PVALID,LATIN SMALL LETTER INSULAR D
-A77B,DISALLOWED,LATIN CAPITAL LETTER INSULAR F
-A77C,PVALID,LATIN SMALL LETTER INSULAR F
-A77D-A77E,DISALLOWED,LATIN CAPITAL LETTER INSULAR G..LATIN CAPITAL LETTER TURNED INSULAR G
-A77F,PVALID,LATIN SMALL LETTER TURNED INSULAR G
-A780,DISALLOWED,LATIN CAPITAL LETTER TURNED L
-A781,PVALID,LATIN SMALL LETTER TURNED L
-A782,DISALLOWED,LATIN CAPITAL LETTER INSULAR R
-A783,PVALID,LATIN SMALL LETTER INSULAR R
-A784,DISALLOWED,LATIN CAPITAL LETTER INSULAR S
-A785,PVALID,LATIN SMALL LETTER INSULAR S
-A786,DISALLOWED,LATIN CAPITAL LETTER INSULAR T
-A787-A788,PVALID,LATIN SMALL LETTER INSULAR T..MODIFIER LETTER LOW CIRCUMFLEX ACCENT
-A789-A78B,DISALLOWED,MODIFIER LETTER COLON..LATIN CAPITAL LETTER SALTILLO
-A78C,PVALID,LATIN SMALL LETTER SALTILLO
-A78D-A7FA,UNASSIGNED,<RESERVED>..<RESERVED>
-A7FB-A827,PVALID,LATIN EPIGRAPHIC LETTER REVERSED F..SYLOTI NAGRI VOWEL SIGN OO
-A828-A82B,DISALLOWED,SYLOTI NAGRI POETRY MARK-1..SYLOTI NAGRI POETRY MARK-4
-A82C-A82F,UNASSIGNED,<RESERVED>..<RESERVED>
-A830-A839,DISALLOWED,NORTH INDIC FRACTION ONE QUARTER..NORTH INDIC QUANTITY MARK
-A83A-A83F,UNASSIGNED,<RESERVED>..<RESERVED>
-A840-A873,PVALID,PHAGS-PA LETTER KA..PHAGS-PA LETTER CANDRABINDU
-A874-A877,DISALLOWED,PHAGS-PA SINGLE HEAD MARK..PHAGS-PA MARK DOUBLE SHAD
-A878-A87F,UNASSIGNED,<RESERVED>..<RESERVED>
-A880-A8C4,PVALID,SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VIRAMA
-A8C5-A8CD,UNASSIGNED,<RESERVED>..<RESERVED>
-A8CE-A8CF,DISALLOWED,SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA
-A8D0-A8D9,PVALID,SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE
-A8DA-A8DF,UNASSIGNED,<RESERVED>..<RESERVED>
-A8E0-A8F7,PVALID,COMBINING DEVANAGARI DIGIT ZERO..DEVANAGARI SIGN CANDRABINDU AVAGRAHA
-A8F8-A8FA,DISALLOWED,DEVANAGARI SIGN PUSHPIKA..DEVANAGARI CARET
-A8FB,PVALID,DEVANAGARI HEADSTROKE
-A8FC-A8FF,UNASSIGNED,<RESERVED>..<RESERVED>
-A900-A92D,PVALID,KAYAH LI DIGIT ZERO..KAYAH LI TONE CALYA PLOPHU
-A92E-A92F,DISALLOWED,KAYAH LI SIGN CWI..KAYAH LI SIGN SHYA
-A930-A953,PVALID,REJANG LETTER KA..REJANG VIRAMA
-A954-A95E,UNASSIGNED,<RESERVED>..<RESERVED>
-A95F-A97C,DISALLOWED,REJANG SECTION MARK..HANGUL CHOSEONG SSANGYEORINHIEUH
-A97D-A97F,UNASSIGNED,<RESERVED>..<RESERVED>
-A980-A9C0,PVALID,JAVANESE SIGN PANYANGGA..JAVANESE PANGKON
-A9C1-A9CD,DISALLOWED,JAVANESE LEFT RERENGGAN..JAVANESE TURNED PADA PISELEH
-A9CE,UNASSIGNED,<RESERVED>
-A9CF-A9D9,PVALID,JAVANESE PANGRANGKEP..JAVANESE DIGIT NINE
-A9DA-A9DD,UNASSIGNED,<RESERVED>..<RESERVED>
-A9DE-A9DF,DISALLOWED,JAVANESE PADA TIRTA TUMETES..JAVANESE PADA ISEN-ISEN
-A9E0-A9FF,UNASSIGNED,<RESERVED>..<RESERVED>
-AA00-AA36,PVALID,CHAM LETTER A..CHAM CONSONANT SIGN WA
-AA37-AA3F,UNASSIGNED,<RESERVED>..<RESERVED>
-AA40-AA4D,PVALID,CHAM LETTER FINAL K..CHAM CONSONANT SIGN FINAL H
-AA4E-AA4F,UNASSIGNED,<RESERVED>..<RESERVED>
-AA50-AA59,PVALID,CHAM DIGIT ZERO..CHAM DIGIT NINE
-AA5A-AA5B,UNASSIGNED,<RESERVED>..<RESERVED>
-AA5C-AA5F,DISALLOWED,CHAM PUNCTUATION SPIRAL..CHAM PUNCTUATION TRIPLE DANDA
-AA60-AA76,PVALID,MYANMAR LETTER KHAMTI GA..MYANMAR LOGOGRAM KHAMTI HM
-AA77-AA79,DISALLOWED,MYANMAR SYMBOL AITON EXCLAMATION..MYANMAR SYMBOL AITON TWO
-AA7A-AA7B,PVALID,MYANMAR LETTER AITON RA..MYANMAR SIGN PAO KAREN TONE
-AA7C-AA7F,UNASSIGNED,<RESERVED>..<RESERVED>
-AA80-AAC2,PVALID,TAI VIET LETTER LOW KO..TAI VIET TONE MAI SONG
-AAC3-AADA,UNASSIGNED,<RESERVED>..<RESERVED>
-AADB-AADD,PVALID,TAI VIET SYMBOL KON..TAI VIET SYMBOL SAM
-AADE-AADF,DISALLOWED,TAI VIET SYMBOL HO HOI..TAI VIET SYMBOL KOI KOI
-AAE0-ABBF,UNASSIGNED,<RESERVED>..<RESERVED>
-ABC0-ABEA,PVALID,MEETEI MAYEK LETTER KOK..MEETEI MAYEK VOWEL SIGN NUNG
-ABEB,DISALLOWED,MEETEI MAYEK CHEIKHEI
-ABEC-ABED,PVALID,MEETEI MAYEK LUM IYEK..MEETEI MAYEK APUN IYEK
-ABEE-ABEF,UNASSIGNED,<RESERVED>..<RESERVED>
-ABF0-ABF9,PVALID,MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DIGIT NINE
-ABFA-ABFF,UNASSIGNED,<RESERVED>..<RESERVED>
-AC00-D7A3,PVALID,"<HANGUL SYLLABLE, FIRST>..<HANGUL SYLLABLE, LAST>"
-D7A4-D7AF,UNASSIGNED,<RESERVED>..<RESERVED>
-D7B0-D7C6,DISALLOWED,HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARAEA-E
-D7C7-D7CA,UNASSIGNED,<RESERVED>..<RESERVED>
-D7CB-D7FB,DISALLOWED,HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEONG PHIEUPH-THIEUTH
-D7FC-D7FF,UNASSIGNED,<RESERVED>..<RESERVED>
-D800-FA0D,DISALLOWED,"<NON PRIVATE USE HIGH SURROGATE, FIRST>..CJK COMPATIBILITY IDEOGRAPH-FA0D"
-FA0E-FA0F,PVALID,CJK COMPATIBILITY IDEOGRAPH-FA0E..CJK COMPATIBILITY IDEOGRAPH-FA0F
-FA10,DISALLOWED,CJK COMPATIBILITY IDEOGRAPH-FA10
-FA11,PVALID,CJK COMPATIBILITY IDEOGRAPH-FA11
-FA12,DISALLOWED,CJK COMPATIBILITY IDEOGRAPH-FA12
-FA13-FA14,PVALID,CJK COMPATIBILITY IDEOGRAPH-FA13..CJK COMPATIBILITY IDEOGRAPH-FA14
-FA15-FA1E,DISALLOWED,CJK COMPATIBILITY IDEOGRAPH-FA15..CJK COMPATIBILITY IDEOGRAPH-FA1E
-FA1F,PVALID,CJK COMPATIBILITY IDEOGRAPH-FA1F
-FA20,DISALLOWED,CJK COMPATIBILITY IDEOGRAPH-FA20
-FA21,PVALID,CJK COMPATIBILITY IDEOGRAPH-FA21
-FA22,DISALLOWED,CJK COMPATIBILITY IDEOGRAPH-FA22
-FA23-FA24,PVALID,CJK COMPATIBILITY IDEOGRAPH-FA23..CJK COMPATIBILITY IDEOGRAPH-FA24
-FA25-FA26,DISALLOWED,CJK COMPATIBILITY IDEOGRAPH-FA25..CJK COMPATIBILITY IDEOGRAPH-FA26
-FA27-FA29,PVALID,CJK COMPATIBILITY IDEOGRAPH-FA27..CJK COMPATIBILITY IDEOGRAPH-FA29
-FA2A-FA2D,DISALLOWED,CJK COMPATIBILITY IDEOGRAPH-FA2A..CJK COMPATIBILITY IDEOGRAPH-FA2D
-FA2E-FA2F,UNASSIGNED,<RESERVED>..<RESERVED>
-FA30-FA6D,DISALLOWED,CJK COMPATIBILITY IDEOGRAPH-FA30..CJK COMPATIBILITY IDEOGRAPH-FA6D
-FA6E-FA6F,UNASSIGNED,<RESERVED>..<RESERVED>
-FA70-FAD9,DISALLOWED,CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9
-FADA-FAFF,UNASSIGNED,<RESERVED>..<RESERVED>
-FB00-FB06,DISALLOWED,LATIN SMALL LIGATURE FF..LATIN SMALL LIGATURE ST
-FB07-FB12,UNASSIGNED,<RESERVED>..<RESERVED>
-FB13-FB17,DISALLOWED,ARMENIAN SMALL LIGATURE MEN NOW..ARMENIAN SMALL LIGATURE MEN XEH
-FB18-FB1C,UNASSIGNED,<RESERVED>..<RESERVED>
-FB1D,DISALLOWED,HEBREW LETTER YOD WITH HIRIQ
-FB1E,PVALID,HEBREW POINT JUDEO-SPANISH VARIKA
-FB1F-FB36,DISALLOWED,HEBREW LIGATURE YIDDISH YOD YOD PATAH..HEBREW LETTER ZAYIN WITH DAGESH
-FB37,UNASSIGNED,<RESERVED>
-FB38-FB3C,DISALLOWED,HEBREW LETTER TET WITH DAGESH..HEBREW LETTER LAMED WITH DAGESH
-FB3D,UNASSIGNED,<RESERVED>
-FB3E,DISALLOWED,HEBREW LETTER MEM WITH DAGESH
-FB3F,UNASSIGNED,<RESERVED>
-FB40-FB41,DISALLOWED,HEBREW LETTER NUN WITH DAGESH..HEBREW LETTER SAMEKH WITH DAGESH
-FB42,UNASSIGNED,<RESERVED>
-FB43-FB44,DISALLOWED,HEBREW LETTER FINAL PE WITH DAGESH..HEBREW LETTER PE WITH DAGESH
-FB45,UNASSIGNED,<RESERVED>
-FB46-FBB1,DISALLOWED,HEBREW LETTER TSADI WITH DAGESH..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM
-FBB2-FBD2,UNASSIGNED,<RESERVED>..<RESERVED>
-FBD3-FD3F,DISALLOWED,ARABIC LETTER NG ISOLATED FORM..ORNATE RIGHT PARENTHESIS
-FD40-FD4F,UNASSIGNED,<RESERVED>..<RESERVED>
-FD50-FD8F,DISALLOWED,ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM..ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM
-FD90-FD91,UNASSIGNED,<RESERVED>..<RESERVED>
-FD92-FDC7,DISALLOWED,ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM..ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM
-FDC8-FDCF,UNASSIGNED,<RESERVED>..<RESERVED>
-FDD0-FDFD,DISALLOWED,<NOT A CHARACTER>..ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM
-FDFE-FDFF,UNASSIGNED,<RESERVED>..<RESERVED>
-FE00-FE19,DISALLOWED,VARIATION SELECTOR-1..PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS
-FE1A-FE1F,UNASSIGNED,<RESERVED>..<RESERVED>
-FE20-FE26,PVALID,COMBINING LIGATURE LEFT HALF..COMBINING CONJOINING MACRON
-FE27-FE2F,UNASSIGNED,<RESERVED>..<RESERVED>
-FE30-FE52,DISALLOWED,PRESENTATION FORM FOR VERTICAL TWO DOT LEADER..SMALL FULL STOP
-FE53,UNASSIGNED,<RESERVED>
-FE54-FE66,DISALLOWED,SMALL SEMICOLON..SMALL EQUALS SIGN
-FE67,UNASSIGNED,<RESERVED>
-FE68-FE6B,DISALLOWED,SMALL REVERSE SOLIDUS..SMALL COMMERCIAL AT
-FE6C-FE6F,UNASSIGNED,<RESERVED>..<RESERVED>
-FE70-FE72,DISALLOWED,ARABIC FATHATAN ISOLATED FORM..ARABIC DAMMATAN ISOLATED FORM
-FE73,PVALID,ARABIC TAIL FRAGMENT
-FE74,DISALLOWED,ARABIC KASRATAN ISOLATED FORM
-FE75,UNASSIGNED,<RESERVED>
-FE76-FEFC,DISALLOWED,ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE LAM WITH ALEF FINAL FORM
-FEFD-FEFE,UNASSIGNED,<RESERVED>..<RESERVED>
-FEFF,DISALLOWED,ZERO WIDTH NO-BREAK SPACE
-FF00,UNASSIGNED,<RESERVED>
-FF01-FFBE,DISALLOWED,FULLWIDTH EXCLAMATION MARK..HALFWIDTH HANGUL LETTER HIEUH
-FFBF-FFC1,UNASSIGNED,<RESERVED>..<RESERVED>
-FFC2-FFC7,DISALLOWED,HALFWIDTH HANGUL LETTER A..HALFWIDTH HANGUL LETTER E
-FFC8-FFC9,UNASSIGNED,<RESERVED>..<RESERVED>
-FFCA-FFCF,DISALLOWED,HALFWIDTH HANGUL LETTER YEO..HALFWIDTH HANGUL LETTER OE
-FFD0-FFD1,UNASSIGNED,<RESERVED>..<RESERVED>
-FFD2-FFD7,DISALLOWED,HALFWIDTH HANGUL LETTER YO..HALFWIDTH HANGUL LETTER YU
-FFD8-FFD9,UNASSIGNED,<RESERVED>..<RESERVED>
-FFDA-FFDC,DISALLOWED,HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL LETTER I
-FFDD-FFDF,UNASSIGNED,<RESERVED>..<RESERVED>
-FFE0-FFE6,DISALLOWED,FULLWIDTH CENT SIGN..FULLWIDTH WON SIGN
-FFE7,UNASSIGNED,<RESERVED>
-FFE8-FFEE,DISALLOWED,HALFWIDTH FORMS LIGHT VERTICAL..HALFWIDTH WHITE CIRCLE
-FFEF-FFF8,UNASSIGNED,<RESERVED>..<RESERVED>
-FFF9-FFFF,DISALLOWED,INTERLINEAR ANNOTATION ANCHOR..<NOT A CHARACTER>
-10000-1000B,PVALID,LINEAR B SYLLABLE B008 A..LINEAR B SYLLABLE B046 JE
-1000C,UNASSIGNED,<RESERVED>
-1000D-10026,PVALID,LINEAR B SYLLABLE B036 JO..LINEAR B SYLLABLE B032 QO
-10027,UNASSIGNED,<RESERVED>
-10028-1003A,PVALID,LINEAR B SYLLABLE B060 RA..LINEAR B SYLLABLE B042 WO
-1003B,UNASSIGNED,<RESERVED>
-1003C-1003D,PVALID,LINEAR B SYLLABLE B017 ZA..LINEAR B SYLLABLE B074 ZE
-1003E,UNASSIGNED,<RESERVED>
-1003F-1004D,PVALID,LINEAR B SYLLABLE B020 ZO..LINEAR B SYLLABLE B091 TWO
-1004E-1004F,UNASSIGNED,<RESERVED>..<RESERVED>
-10050-1005D,PVALID,LINEAR B SYMBOL B018..LINEAR B SYMBOL B089
-1005E-1007F,UNASSIGNED,<RESERVED>..<RESERVED>
-10080-100FA,PVALID,LINEAR B IDEOGRAM B100 MAN..LINEAR B IDEOGRAM VESSEL B305
-100FB-100FF,UNASSIGNED,<RESERVED>..<RESERVED>
-10100-10102,DISALLOWED,AEGEAN WORD SEPARATOR LINE..AEGEAN CHECK MARK
-10103-10106,UNASSIGNED,<RESERVED>..<RESERVED>
-10107-10133,DISALLOWED,AEGEAN NUMBER ONE..AEGEAN NUMBER NINETY THOUSAND
-10134-10136,UNASSIGNED,<RESERVED>..<RESERVED>
-10137-1018A,DISALLOWED,AEGEAN WEIGHT BASE UNIT..GREEK ZERO SIGN
-1018B-1018F,UNASSIGNED,<RESERVED>..<RESERVED>
-10190-1019B,DISALLOWED,ROMAN SEXTANS SIGN..ROMAN CENTURIAL SIGN
-1019C-101CF,UNASSIGNED,<RESERVED>..<RESERVED>
-101D0-101FC,DISALLOWED,PHAISTOS DISC SIGN PEDESTRIAN..PHAISTOS DISC SIGN WAVY BAND
-101FD,PVALID,PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE
-101FE-1027F,UNASSIGNED,<RESERVED>..<RESERVED>
-10280-1029C,PVALID,LYCIAN LETTER A..LYCIAN LETTER X
-1029D-1029F,UNASSIGNED,<RESERVED>..<RESERVED>
-102A0-102D0,PVALID,CARIAN LETTER A..CARIAN LETTER UUU3
-102D1-102FF,UNASSIGNED,<RESERVED>..<RESERVED>
-10300-1031E,PVALID,OLD ITALIC LETTER A..OLD ITALIC LETTER UU
-1031F,UNASSIGNED,<RESERVED>
-10320-10323,DISALLOWED,OLD ITALIC NUMERAL ONE..OLD ITALIC NUMERAL FIFTY
-10324-1032F,UNASSIGNED,<RESERVED>..<RESERVED>
-10330-10340,PVALID,GOTHIC LETTER AHSA..GOTHIC LETTER PAIRTHRA
-10341,DISALLOWED,GOTHIC LETTER NINETY
-10342-10349,PVALID,GOTHIC LETTER RAIDA..GOTHIC LETTER OTHAL
-1034A,DISALLOWED,GOTHIC LETTER NINE HUNDRED
-1034B-1037F,UNASSIGNED,<RESERVED>..<RESERVED>
-10380-1039D,PVALID,UGARITIC LETTER ALPA..UGARITIC LETTER SSU
-1039E,UNASSIGNED,<RESERVED>
-1039F,DISALLOWED,UGARITIC WORD DIVIDER
-103A0-103C3,PVALID,OLD PERSIAN SIGN A..OLD PERSIAN SIGN HA
-103C4-103C7,UNASSIGNED,<RESERVED>..<RESERVED>
-103C8-103CF,PVALID,OLD PERSIAN SIGN AURAMAZDAA..OLD PERSIAN SIGN BUUMISH
-103D0-103D5,DISALLOWED,OLD PERSIAN WORD DIVIDER..OLD PERSIAN NUMBER HUNDRED
-103D6-103FF,UNASSIGNED,<RESERVED>..<RESERVED>
-10400-10427,DISALLOWED,DESERET CAPITAL LETTER LONG I..DESERET CAPITAL LETTER EW
-10428-1049D,PVALID,DESERET SMALL LETTER LONG I..OSMANYA LETTER OO
-1049E-1049F,UNASSIGNED,<RESERVED>..<RESERVED>
-104A0-104A9,PVALID,OSMANYA DIGIT ZERO..OSMANYA DIGIT NINE
-104AA-107FF,UNASSIGNED,<RESERVED>..<RESERVED>
-10800-10805,PVALID,CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA
-10806-10807,UNASSIGNED,<RESERVED>..<RESERVED>
-10808,PVALID,CYPRIOT SYLLABLE JO
-10809,UNASSIGNED,<RESERVED>
-1080A-10835,PVALID,CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO
-10836,UNASSIGNED,<RESERVED>
-10837-10838,PVALID,CYPRIOT SYLLABLE XA..CYPRIOT SYLLABLE XE
-10839-1083B,UNASSIGNED,<RESERVED>..<RESERVED>
-1083C,PVALID,CYPRIOT SYLLABLE ZA
-1083D-1083E,UNASSIGNED,<RESERVED>..<RESERVED>
-1083F-10855,PVALID,CYPRIOT SYLLABLE ZO..IMPERIAL ARAMAIC LETTER TAW
-10856,UNASSIGNED,<RESERVED>
-10857-1085F,DISALLOWED,IMPERIAL ARAMAIC SECTION SIGN..IMPERIAL ARAMAIC NUMBER TEN THOUSAND
-10860-108FF,UNASSIGNED,<RESERVED>..<RESERVED>
-10900-10915,PVALID,PHOENICIAN LETTER ALF..PHOENICIAN LETTER TAU
-10916-1091B,DISALLOWED,PHOENICIAN NUMBER ONE..PHOENICIAN NUMBER THREE
-1091C-1091E,UNASSIGNED,<RESERVED>..<RESERVED>
-1091F,DISALLOWED,PHOENICIAN WORD SEPARATOR
-10920-10939,PVALID,LYDIAN LETTER A..LYDIAN LETTER C
-1093A-1093E,UNASSIGNED,<RESERVED>..<RESERVED>
-1093F,DISALLOWED,LYDIAN TRIANGULAR MARK
-10940-109FF,UNASSIGNED,<RESERVED>..<RESERVED>
-10A00-10A03,PVALID,KHAROSHTHI LETTER A..KHAROSHTHI VOWEL SIGN VOCALIC R
-10A04,UNASSIGNED,<RESERVED>
-10A05-10A06,PVALID,KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O
-10A07-10A0B,UNASSIGNED,<RESERVED>..<RESERVED>
-10A0C-10A13,PVALID,KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI LETTER GHA
-10A14,UNASSIGNED,<RESERVED>
-10A15-10A17,PVALID,KHAROSHTHI LETTER CA..KHAROSHTHI LETTER JA
-10A18,UNASSIGNED,<RESERVED>
-10A19-10A33,PVALID,KHAROSHTHI LETTER NYA..KHAROSHTHI LETTER TTTHA
-10A34-10A37,UNASSIGNED,<RESERVED>..<RESERVED>
-10A38-10A3A,PVALID,KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW
-10A3B-10A3E,UNASSIGNED,<RESERVED>..<RESERVED>
-10A3F,PVALID,KHAROSHTHI VIRAMA
-10A40-10A47,DISALLOWED,KHAROSHTHI DIGIT ONE..KHAROSHTHI NUMBER ONE THOUSAND
-10A48-10A4F,UNASSIGNED,<RESERVED>..<RESERVED>
-10A50-10A58,DISALLOWED,KHAROSHTHI PUNCTUATION DOT..KHAROSHTHI PUNCTUATION LINES
-10A59-10A5F,UNASSIGNED,<RESERVED>..<RESERVED>
-10A60-10A7C,PVALID,OLD SOUTH ARABIAN LETTER HE..OLD SOUTH ARABIAN LETTER THETH
-10A7D-10A7F,DISALLOWED,OLD SOUTH ARABIAN NUMBER ONE..OLD SOUTH ARABIAN NUMERIC INDICATOR
-10A80-10AFF,UNASSIGNED,<RESERVED>..<RESERVED>
-10B00-10B35,PVALID,AVESTAN LETTER A..AVESTAN LETTER HE
-10B36-10B38,UNASSIGNED,<RESERVED>..<RESERVED>
-10B39-10B3F,DISALLOWED,AVESTAN ABBREVIATION MARK..LARGE ONE RING OVER TWO RINGS PUNCTUATION
-10B40-10B55,PVALID,INSCRIPTIONAL PARTHIAN LETTER ALEPH..INSCRIPTIONAL PARTHIAN LETTER TAW
-10B56-10B57,UNASSIGNED,<RESERVED>..<RESERVED>
-10B58-10B5F,DISALLOWED,INSCRIPTIONAL PARTHIAN NUMBER ONE..INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND
-10B60-10B72,PVALID,INSCRIPTIONAL PAHLAVI LETTER ALEPH..INSCRIPTIONAL PAHLAVI LETTER TAW
-10B73-10B77,UNASSIGNED,<RESERVED>..<RESERVED>
-10B78-10B7F,DISALLOWED,INSCRIPTIONAL PAHLAVI NUMBER ONE..INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND
-10B80-10BFF,UNASSIGNED,<RESERVED>..<RESERVED>
-10C00-10C48,PVALID,OLD TURKIC LETTER ORKHON A..OLD TURKIC LETTER ORKHON BASH
-10C49-10E5F,UNASSIGNED,<RESERVED>..<RESERVED>
-10E60-10E7E,DISALLOWED,RUMI DIGIT ONE..RUMI FRACTION TWO THIRDS
-10E7F-1107F,UNASSIGNED,<RESERVED>..<RESERVED>
-11080-110BA,PVALID,KAITHI SIGN CANDRABINDU..KAITHI SIGN NUKTA
-110BB-110C1,DISALLOWED,KAITHI ABBREVIATION SIGN..KAITHI DOUBLE DANDA
-110C2-11FFF,UNASSIGNED,<RESERVED>..<RESERVED>
-12000-1236E,PVALID,CUNEIFORM SIGN A..CUNEIFORM SIGN ZUM
-1236F-123FF,UNASSIGNED,<RESERVED>..<RESERVED>
-12400-12462,DISALLOWED,CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE QUARTER
-12463-1246F,UNASSIGNED,<RESERVED>..<RESERVED>
-12470-12473,DISALLOWED,CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER..CUNEIFORM PUNCTUATION SIGN DIAGONAL TRICOLON
-12474-12FFF,UNASSIGNED,<RESERVED>..<RESERVED>
-13000-1342E,PVALID,EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH AA032
-1342F-1CFFF,UNASSIGNED,<RESERVED>..<RESERVED>
-1D000-1D0F5,DISALLOWED,BYZANTINE MUSICAL SYMBOL PSILI..BYZANTINE MUSICAL SYMBOL GORGON NEO KATO
-1D0F6-1D0FF,UNASSIGNED,<RESERVED>..<RESERVED>
-1D100-1D126,DISALLOWED,MUSICAL SYMBOL SINGLE BARLINE..MUSICAL SYMBOL DRUM CLEF-2
-1D127-1D128,UNASSIGNED,<RESERVED>..<RESERVED>
-1D129-1D1DD,DISALLOWED,MUSICAL SYMBOL MULTIPLE MEASURE REST..MUSICAL SYMBOL PES SUBPUNCTIS
-1D1DE-1D1FF,UNASSIGNED,<RESERVED>..<RESERVED>
-1D200-1D245,DISALLOWED,GREEK VOCAL NOTATION SYMBOL-1..GREEK MUSICAL LEIMMA
-1D246-1D2FF,UNASSIGNED,<RESERVED>..<RESERVED>
-1D300-1D356,DISALLOWED,MONOGRAM FOR EARTH..TETRAGRAM FOR FOSTERING
-1D357-1D35F,UNASSIGNED,<RESERVED>..<RESERVED>
-1D360-1D371,DISALLOWED,COUNTING ROD UNIT DIGIT ONE..COUNTING ROD TENS DIGIT NINE
-1D372-1D3FF,UNASSIGNED,<RESERVED>..<RESERVED>
-1D400-1D454,DISALLOWED,MATHEMATICAL BOLD CAPITAL A..MATHEMATICAL ITALIC SMALL G
-1D455,UNASSIGNED,<RESERVED>
-1D456-1D49C,DISALLOWED,MATHEMATICAL ITALIC SMALL I..MATHEMATICAL SCRIPT CAPITAL A
-1D49D,UNASSIGNED,<RESERVED>
-1D49E-1D49F,DISALLOWED,MATHEMATICAL SCRIPT CAPITAL C..MATHEMATICAL SCRIPT CAPITAL D
-1D4A0-1D4A1,UNASSIGNED,<RESERVED>..<RESERVED>
-1D4A2,DISALLOWED,MATHEMATICAL SCRIPT CAPITAL G
-1D4A3-1D4A4,UNASSIGNED,<RESERVED>..<RESERVED>
-1D4A5-1D4A6,DISALLOWED,MATHEMATICAL SCRIPT CAPITAL J..MATHEMATICAL SCRIPT CAPITAL K
-1D4A7-1D4A8,UNASSIGNED,<RESERVED>..<RESERVED>
-1D4A9-1D4AC,DISALLOWED,MATHEMATICAL SCRIPT CAPITAL N..MATHEMATICAL SCRIPT CAPITAL Q
-1D4AD,UNASSIGNED,<RESERVED>
-1D4AE-1D4B9,DISALLOWED,MATHEMATICAL SCRIPT CAPITAL S..MATHEMATICAL SCRIPT SMALL D
-1D4BA,UNASSIGNED,<RESERVED>
-1D4BB,DISALLOWED,MATHEMATICAL SCRIPT SMALL F
-1D4BC,UNASSIGNED,<RESERVED>
-1D4BD-1D4C3,DISALLOWED,MATHEMATICAL SCRIPT SMALL H..MATHEMATICAL SCRIPT SMALL N
-1D4C4,UNASSIGNED,<RESERVED>
-1D4C5-1D505,DISALLOWED,MATHEMATICAL SCRIPT SMALL P..MATHEMATICAL FRAKTUR CAPITAL B
-1D506,UNASSIGNED,<RESERVED>
-1D507-1D50A,DISALLOWED,MATHEMATICAL FRAKTUR CAPITAL D..MATHEMATICAL FRAKTUR CAPITAL G
-1D50B-1D50C,UNASSIGNED,<RESERVED>..<RESERVED>
-1D50D-1D514,DISALLOWED,MATHEMATICAL FRAKTUR CAPITAL J..MATHEMATICAL FRAKTUR CAPITAL Q
-1D515,UNASSIGNED,<RESERVED>
-1D516-1D51C,DISALLOWED,MATHEMATICAL FRAKTUR CAPITAL S..MATHEMATICAL FRAKTUR CAPITAL Y
-1D51D,UNASSIGNED,<RESERVED>
-1D51E-1D539,DISALLOWED,MATHEMATICAL FRAKTUR SMALL A..MATHEMATICAL DOUBLE-STRUCK CAPITAL B
-1D53A,UNASSIGNED,<RESERVED>
-1D53B-1D53E,DISALLOWED,MATHEMATICAL DOUBLE-STRUCK CAPITAL D..MATHEMATICAL DOUBLE-STRUCK CAPITAL G
-1D53F,UNASSIGNED,<RESERVED>
-1D540-1D544,DISALLOWED,MATHEMATICAL DOUBLE-STRUCK CAPITAL I..MATHEMATICAL DOUBLE-STRUCK CAPITAL M
-1D545,UNASSIGNED,<RESERVED>
-1D546,DISALLOWED,MATHEMATICAL DOUBLE-STRUCK CAPITAL O
-1D547-1D549,UNASSIGNED,<RESERVED>..<RESERVED>
-1D54A-1D550,DISALLOWED,MATHEMATICAL DOUBLE-STRUCK CAPITAL S..MATHEMATICAL DOUBLE-STRUCK CAPITAL Y
-1D551,UNASSIGNED,<RESERVED>
-1D552-1D6A5,DISALLOWED,MATHEMATICAL DOUBLE-STRUCK SMALL A..MATHEMATICAL ITALIC SMALL DOTLESS J
-1D6A6-1D6A7,UNASSIGNED,<RESERVED>..<RESERVED>
-1D6A8-1D7CB,DISALLOWED,MATHEMATICAL BOLD CAPITAL ALPHA..MATHEMATICAL BOLD SMALL DIGAMMA
-1D7CC-1D7CD,UNASSIGNED,<RESERVED>..<RESERVED>
-1D7CE-1D7FF,DISALLOWED,MATHEMATICAL BOLD DIGIT ZERO..MATHEMATICAL MONOSPACE DIGIT NINE
-1D800-1EFFF,UNASSIGNED,<RESERVED>..<RESERVED>
-1F000-1F02B,DISALLOWED,MAHJONG TILE EAST WIND..MAHJONG TILE BACK
-1F02C-1F02F,UNASSIGNED,<RESERVED>..<RESERVED>
-1F030-1F093,DISALLOWED,DOMINO TILE HORIZONTAL BACK..DOMINO TILE VERTICAL-06-06
-1F094-1F0FF,UNASSIGNED,<RESERVED>..<RESERVED>
-1F100-1F10A,DISALLOWED,DIGIT ZERO FULL STOP..DIGIT NINE COMMA
-1F10B-1F10F,UNASSIGNED,<RESERVED>..<RESERVED>
-1F110-1F12E,DISALLOWED,PARENTHESIZED LATIN CAPITAL LETTER A..CIRCLED WZ
-1F12F-1F130,UNASSIGNED,<RESERVED>..<RESERVED>
-1F131,DISALLOWED,SQUARED LATIN CAPITAL LETTER B
-1F132-1F13C,UNASSIGNED,<RESERVED>..<RESERVED>
-1F13D,DISALLOWED,SQUARED LATIN CAPITAL LETTER N
-1F13E,UNASSIGNED,<RESERVED>
-1F13F,DISALLOWED,SQUARED LATIN CAPITAL LETTER P
-1F140-1F141,UNASSIGNED,<RESERVED>..<RESERVED>
-1F142,DISALLOWED,SQUARED LATIN CAPITAL LETTER S
-1F143-1F145,UNASSIGNED,<RESERVED>..<RESERVED>
-1F146,DISALLOWED,SQUARED LATIN CAPITAL LETTER W
-1F147-1F149,UNASSIGNED,<RESERVED>..<RESERVED>
-1F14A-1F14E,DISALLOWED,SQUARED HV..SQUARED PPV
-1F14F-1F156,UNASSIGNED,<RESERVED>..<RESERVED>
-1F157,DISALLOWED,NEGATIVE CIRCLED LATIN CAPITAL LETTER H
-1F158-1F15E,UNASSIGNED,<RESERVED>..<RESERVED>
-1F15F,DISALLOWED,NEGATIVE CIRCLED LATIN CAPITAL LETTER P
-1F160-1F178,UNASSIGNED,<RESERVED>..<RESERVED>
-1F179,DISALLOWED,NEGATIVE SQUARED LATIN CAPITAL LETTER J
-1F17A,UNASSIGNED,<RESERVED>
-1F17B-1F17C,DISALLOWED,NEGATIVE SQUARED LATIN CAPITAL LETTER L..NEGATIVE SQUARED LATIN CAPITAL LETTER M
-1F17D-1F17E,UNASSIGNED,<RESERVED>..<RESERVED>
-1F17F,DISALLOWED,NEGATIVE SQUARED LATIN CAPITAL LETTER P
-1F180-1F189,UNASSIGNED,<RESERVED>..<RESERVED>
-1F18A-1F18D,DISALLOWED,CROSSED NEGATIVE SQUARED LATIN CAPITAL LETTER P..NEGATIVE SQUARED SA
-1F18E-1F18F,UNASSIGNED,<RESERVED>..<RESERVED>
-1F190,DISALLOWED,SQUARE DJ
-1F191-1F1FF,UNASSIGNED,<RESERVED>..<RESERVED>
-1F200,DISALLOWED,SQUARE HIRAGANA HOKA
-1F201-1F20F,UNASSIGNED,<RESERVED>..<RESERVED>
-1F210-1F231,DISALLOWED,SQUARED CJK UNIFIED IDEOGRAPH-624B..SQUARED CJK UNIFIED IDEOGRAPH-6253
-1F232-1F23F,UNASSIGNED,<RESERVED>..<RESERVED>
-1F240-1F248,DISALLOWED,TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C..TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557
-1F249-1FFFD,UNASSIGNED,<RESERVED>..<RESERVED>
-1FFFE-1FFFF,DISALLOWED,<NOT A CHARACTER>..<NOT A CHARACTER>
-20000-2A6D6,PVALID,"<CJK IDEOGRAPH EXTENSION B, FIRST>..<CJK IDEOGRAPH EXTENSION B, LAST>"
-2A6D7-2A6FF,UNASSIGNED,<RESERVED>..<RESERVED>
-2A700-2B734,PVALID,"<CJK IDEOGRAPH EXTENSION C, FIRST>..<CJK IDEOGRAPH EXTENSION C, LAST>"
-2B735-2F7FF,UNASSIGNED,<RESERVED>..<RESERVED>
-2F800-2FA1D,DISALLOWED,CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
-2FA1E-2FFFD,UNASSIGNED,<RESERVED>..<RESERVED>
-2FFFE-2FFFF,DISALLOWED,<NOT A CHARACTER>..<NOT A CHARACTER>
-30000-3FFFD,UNASSIGNED,<RESERVED>..<RESERVED>
-3FFFE-3FFFF,DISALLOWED,<NOT A CHARACTER>..<NOT A CHARACTER>
-40000-4FFFD,UNASSIGNED,<RESERVED>..<RESERVED>
-4FFFE-4FFFF,DISALLOWED,<NOT A CHARACTER>..<NOT A CHARACTER>
-50000-5FFFD,UNASSIGNED,<RESERVED>..<RESERVED>
-5FFFE-5FFFF,DISALLOWED,<NOT A CHARACTER>..<NOT A CHARACTER>
-60000-6FFFD,UNASSIGNED,<RESERVED>..<RESERVED>
-6FFFE-6FFFF,DISALLOWED,<NOT A CHARACTER>..<NOT A CHARACTER>
-70000-7FFFD,UNASSIGNED,<RESERVED>..<RESERVED>
-7FFFE-7FFFF,DISALLOWED,<NOT A CHARACTER>..<NOT A CHARACTER>
-80000-8FFFD,UNASSIGNED,<RESERVED>..<RESERVED>
-8FFFE-8FFFF,DISALLOWED,<NOT A CHARACTER>..<NOT A CHARACTER>
-90000-9FFFD,UNASSIGNED,<RESERVED>..<RESERVED>
-9FFFE-9FFFF,DISALLOWED,<NOT A CHARACTER>..<NOT A CHARACTER>
-A0000-AFFFD,UNASSIGNED,<RESERVED>..<RESERVED>
-AFFFE-AFFFF,DISALLOWED,<NOT A CHARACTER>..<NOT A CHARACTER>
-B0000-BFFFD,UNASSIGNED,<RESERVED>..<RESERVED>
-BFFFE-BFFFF,DISALLOWED,<NOT A CHARACTER>..<NOT A CHARACTER>
-C0000-CFFFD,UNASSIGNED,<RESERVED>..<RESERVED>
-CFFFE-CFFFF,DISALLOWED,<NOT A CHARACTER>..<NOT A CHARACTER>
-D0000-DFFFD,UNASSIGNED,<RESERVED>..<RESERVED>
-DFFFE-DFFFF,DISALLOWED,<NOT A CHARACTER>..<NOT A CHARACTER>
-E0000,UNASSIGNED,<RESERVED>
-E0001,DISALLOWED,LANGUAGE TAG
-E0002-E001F,UNASSIGNED,<RESERVED>..<RESERVED>
-E0020-E007F,DISALLOWED,TAG SPACE..CANCEL TAG
-E0080-E00FF,UNASSIGNED,<RESERVED>..<RESERVED>
-E0100-E01EF,DISALLOWED,VARIATION SELECTOR-17..VARIATION SELECTOR-256
-E01F0-EFFFD,UNASSIGNED,<RESERVED>..<RESERVED>
-EFFFE-10FFFF,DISALLOWED,<NOT A CHARACTER>..<NOT A CHARACTER>
diff --git a/utils/idna.c b/utils/idna.c
index 572882ecb..3ce3e1be1 100644
--- a/utils/idna.c
+++ b/utils/idna.c
@@ -26,7 +26,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
-#include <libutf8proc/utf8proc.h>
+#include <sys/types.h>
#include "netsurf/inttypes.h"
@@ -39,14 +39,6 @@
#include "utils/utils.h"
-int32_t idna_contexto[] = {
- /* CONTEXTO codepoints which have a rule defined */
- 0x00b7, 0x0375, 0x05f3, 0x05f4, 0x30fb, 0x0660, 0x0661,
- 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668,
- 0x0669, 0x06f0, 0x06f1, 0x06f2, 0x06f3, 0x06f4, 0x06f5,
- 0x06f6, 0x06f7, 0x06f8, 0x06f9, 0
-};
-
/**
* Convert punycode status into nserror.
*
@@ -83,6 +75,108 @@ static nserror punycode_status_to_nserror(enum punycode_status status)
return ret;
}
+
+/**
+ * Convert a host label in UCS-4 to an ACE version
+ *
+ * \param ucs4_label UCS-4 NFC string containing host label
+ * \param len Length of host label (in characters/codepoints)
+ * \param ace_label ASCII-compatible encoded version
+ * \param out_len Length of ace_label
+ * \return NSERROR_OK on success, appropriate error otherwise
+ *
+ * If return value != NSERROR_OK, output will be left untouched.
+ */
+static nserror
+idna__ucs4_to_ace(int32_t *ucs4_label,
+ size_t len,
+ char **ace_label,
+ size_t *out_len)
+{
+ char punycode[65]; /* max length of host label + NULL */
+ size_t output_length = 60; /* punycode length - 4 - 1 */
+ nserror ret;
+
+ punycode[0] = 'x';
+ punycode[1] = 'n';
+ punycode[2] = '-';
+ punycode[3] = '-';
+
+ ret = punycode_status_to_nserror(punycode_encode(len,
+ (const punycode_uint *)ucs4_label, NULL,
+ &output_length, punycode + 4));
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ output_length += SLEN("xn--");
+ punycode[output_length] = '\0';
+
+ *ace_label = strdup(punycode);
+ *out_len = output_length;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Convert a host label in ACE format to UCS-4
+ *
+ * \param ace_label ASCII string containing host label
+ * \param ace_len Length of host label
+ * \param ucs4_label Pointer to hold UCS4 decoded version
+ * \param ucs4_len Pointer to hold length of ucs4_label
+ * \return NSERROR_OK on success, appropriate error otherwise
+ *
+ * If return value != NSERROR_OK, output will be left untouched.
+ */
+static nserror
+idna__ace_to_ucs4(const char *ace_label,
+ size_t ace_len,
+ int32_t **ucs4_label,
+ size_t *ucs4_len)
+{
+ int32_t *ucs4;
+ nserror ret;
+ size_t output_length = ace_len; /* never exceeds input length */
+
+ /* The header should always have been checked before calling */
+ assert((ace_label[0] == 'x') && (ace_label[1] == 'n') &&
+ (ace_label[2] == '-') && (ace_label[3] == '-'));
+
+ ucs4 = malloc(output_length * 4);
+ if (ucs4 == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ ret = punycode_status_to_nserror(punycode_decode(ace_len - 4,
+ ace_label + 4, &output_length, (punycode_uint *)ucs4, NULL));
+ if (ret != NSERROR_OK) {
+ free(ucs4);
+ return ret;
+ }
+
+ ucs4[output_length] = '\0';
+
+ *ucs4_label = ucs4;
+ *ucs4_len = output_length;
+
+ return NSERROR_OK;
+}
+
+
+#ifdef WITH_UTF8PROC
+
+#include <libutf8proc/utf8proc.h>
+
+int32_t idna_contexto[] = {
+ /* CONTEXTO codepoints which have a rule defined */
+ 0x00b7, 0x0375, 0x05f3, 0x05f4, 0x30fb, 0x0660, 0x0661,
+ 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668,
+ 0x0669, 0x06f0, 0x06f1, 0x06f2, 0x06f3, 0x06f4, 0x06f5,
+ 0x06f6, 0x06f7, 0x06f8, 0x06f9, 0
+};
+
/**
* Find the IDNA property of a UCS-4 codepoint
*
@@ -305,119 +399,6 @@ idna__ucs4_to_utf8(const int32_t *ucs4_label,
/**
- * Convert a host label in UCS-4 to an ACE version
- *
- * \param ucs4_label UCS-4 NFC string containing host label
- * \param len Length of host label (in characters/codepoints)
- * \param ace_label ASCII-compatible encoded version
- * \param out_len Length of ace_label
- * \return NSERROR_OK on success, appropriate error otherwise
- *
- * If return value != NSERROR_OK, output will be left untouched.
- */
-static nserror
-idna__ucs4_to_ace(int32_t *ucs4_label,
- size_t len,
- char **ace_label,
- size_t *out_len)
-{
- char punycode[65]; /* max length of host label + NULL */
- size_t output_length = 60; /* punycode length - 4 - 1 */
- nserror ret;
-
- punycode[0] = 'x';
- punycode[1] = 'n';
- punycode[2] = '-';
- punycode[3] = '-';
-
- ret = punycode_status_to_nserror(punycode_encode(len,
- (const punycode_uint *)ucs4_label, NULL,
- &output_length, punycode + 4));
- if (ret != NSERROR_OK) {
- return ret;
- }
-
- output_length += SLEN("xn--");
- punycode[output_length] = '\0';
-
- *ace_label = strdup(punycode);
- *out_len = output_length;
-
- return NSERROR_OK;
-}
-
-
-/**
- * Convert a host label in ACE format to UCS-4
- *
- * \param ace_label ASCII string containing host label
- * \param ace_len Length of host label
- * \param ucs4_label Pointer to hold UCS4 decoded version
- * \param ucs4_len Pointer to hold length of ucs4_label
- * \return NSERROR_OK on success, appropriate error otherwise
- *
- * If return value != NSERROR_OK, output will be left untouched.
- */
-static nserror
-idna__ace_to_ucs4(const char *ace_label,
- size_t ace_len,
- int32_t **ucs4_label,
- size_t *ucs4_len)
-{
- int32_t *ucs4;
- nserror ret;
- size_t output_length = ace_len; /* never exceeds input length */
-
- /* The header should always have been checked before calling */
- assert((ace_label[0] == 'x') && (ace_label[1] == 'n') &&
- (ace_label[2] == '-') && (ace_label[3] == '-'));
-
- ucs4 = malloc(output_length * 4);
- if (ucs4 == NULL) {
- return NSERROR_NOMEM;
- }
-
- ret = punycode_status_to_nserror(punycode_decode(ace_len - 4,
- ace_label + 4, &output_length, (punycode_uint *)ucs4, NULL));
- if (ret != NSERROR_OK) {
- free(ucs4);
- return ret;
- }
-
- ucs4[output_length] = '\0';
-
- *ucs4_label = ucs4;
- *ucs4_len = output_length;
-
- return NSERROR_OK;
-}
-
-
-/**
- * Find the length of a host label
- *
- * \param host String containing a host or FQDN
- * \param max_length Length of host string to search (in bytes)
- * \return Distance to next separator character or end of string
- */
-static size_t idna__host_label_length(const char *host, size_t max_length)
-{
- const char *p = host;
- size_t length = 0;
-
- while (length < max_length) {
- if ((*p == '.') || (*p == ':') || (*p == '\0')) {
- break;
- }
- length++;
- p++;
- }
-
- return length;
-}
-
-
-/**
* Check if a host label is valid for IDNA2008
*
* \param label Host label to check (UCS-4)
@@ -436,7 +417,7 @@ static bool idna__is_valid(int32_t *label, size_t len)
*/
/* 2. Check characters 3 and 4 are not '--'. */
- if ((label[2] == 0x002d) && (label[3] == 0x002d)) {
+ if ((len >= 4) && (label[2] == 0x002d) && (label[3] == 0x002d)) {
NSLOG(netsurf, INFO,
"Check failed: characters 2 and 3 are '--'");
return false;
@@ -459,7 +440,7 @@ static bool idna__is_valid(int32_t *label, size_t len)
/* 4. Check characters not DISALLOWED by RFC5892 */
if (idna_prop == IDNA_P_DISALLOWED) {
NSLOG(netsurf, INFO,
- "Check failed: character %"PRIsizet" (%x) is DISALLOWED",
+ "Check failed: character %"PRIsizet" (%"PRIx32") is DISALLOWED",
i,
label[i]);
return false;
@@ -469,7 +450,7 @@ static bool idna__is_valid(int32_t *label, size_t len)
if (idna_prop == IDNA_P_CONTEXTJ) {
if (idna__contextj_rule(label, i, len) == false) {
NSLOG(netsurf, INFO,
- "Check failed: character %"PRIsizet" (%x) does not conform to CONTEXTJ rule",
+ "Check failed: character %"PRIsizet" (%"PRIx32") does not conform to CONTEXTJ rule",
i,
label[i]);
return false;
@@ -481,7 +462,7 @@ static bool idna__is_valid(int32_t *label, size_t len)
if (idna_prop == IDNA_P_CONTEXTO) {
if (idna__contexto_rule(label[i]) == false) {
NSLOG(netsurf, INFO,
- "Check failed: character %"PRIsizet" (%x) has no CONTEXTO rule defined",
+ "Check failed: character %"PRIsizet" (%"PRIx32") has no CONTEXTO rule defined",
i,
label[i]);
return false;
@@ -491,7 +472,7 @@ static bool idna__is_valid(int32_t *label, size_t len)
/* 7. Check characters are not UNASSIGNED */
if (idna_prop == IDNA_P_UNASSIGNED) {
NSLOG(netsurf, INFO,
- "Check failed: character %"PRIsizet" (%x) is UNASSIGNED",
+ "Check failed: character %"PRIsizet" (%"PRIx32") is UNASSIGNED",
i,
label[i]);
return false;
@@ -505,6 +486,155 @@ static bool idna__is_valid(int32_t *label, size_t len)
/**
+ * Verify an ACE label is valid
+ *
+ * \param label Host label to check
+ * \param len Length of label
+ * \return true if valid, false otherwise
+ */
+static bool idna__verify(const char *label, size_t len)
+{
+ nserror error;
+ int32_t *ucs4;
+ char *ace;
+ ssize_t ucs4_len;
+ size_t u_ucs4_len, ace_len;
+
+ /* Convert our ACE label back to UCS-4 */
+ error = idna__ace_to_ucs4(label, len, &ucs4, &u_ucs4_len);
+ if (error != NSERROR_OK) {
+ return false;
+ }
+
+ /* Perform NFC normalisation */
+ ucs4_len = utf8proc_normalize_utf32(ucs4, u_ucs4_len,
+ UTF8PROC_STABLE | UTF8PROC_COMPOSE);
+ if (ucs4_len < 0) {
+ free(ucs4);
+ return false;
+ }
+
+ /* Convert the UCS-4 label back to ACE */
+ error = idna__ucs4_to_ace(ucs4, (size_t)ucs4_len,
+ &ace, &ace_len);
+ free(ucs4);
+ if (error != NSERROR_OK) {
+ return false;
+ }
+
+ /* Check if it matches the input */
+ if ((len == ace_len) && (strncmp(label, ace, len) == 0)) {
+ free(ace);
+ return true;
+ }
+
+ NSLOG(netsurf, INFO, "Re-encoded ACE label %s does not match input",
+ ace);
+ free(ace);
+
+ return false;
+}
+
+
+#else /* WITH_UTF8PROC */
+
+
+/**
+ * Convert a UTF-8 string to UCS-4
+ *
+ * \param utf8_label UTF-8 string containing host label
+ * \param len Length of host label (in bytes)
+ * \param ucs4_label Pointer to update with the output
+ * \param ucs4_len Pointer to update with the length
+ * \return NSERROR_OK on success, appropriate error otherwise
+ *
+ * If return value != NSERROR_OK, output will be left untouched.
+ */
+static nserror
+idna__utf8_to_ucs4(const char *utf8_label,
+ size_t len,
+ int32_t **ucs4_label,
+ size_t *ucs4_len)
+{
+ return NSERROR_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * Convert a UCS-4 string to UTF-8
+ *
+ * \param ucs4_label UCS-4 string containing host label
+ * \param ucs4_len Length of host label (in bytes)
+ * \param utf8_label Pointer to update with the output
+ * \param utf8_len Pointer to update with the length
+ * \return NSERROR_OK on success, appropriate error otherwise
+ *
+ * If return value != NSERROR_OK, output will be left untouched.
+ */
+static nserror
+idna__ucs4_to_utf8(const int32_t *ucs4_label,
+ size_t ucs4_len,
+ char **utf8_label,
+ size_t *utf8_len)
+{
+ return NSERROR_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * Check if a host label is valid for IDNA2008
+ *
+ * \param label Host label to check (UCS-4)
+ * \param len Length of host label (in characters/codepoints)
+ * \return true if compliant, false otherwise
+ */
+static bool idna__is_valid(int32_t *label, size_t len)
+{
+ return true;
+}
+
+
+/**
+ * Verify an ACE label is valid
+ *
+ * \param label Host label to check
+ * \param len Length of label
+ * \return true if valid, false otherwise
+ */
+static bool idna__verify(const char *label, size_t len)
+{
+ return true;
+}
+
+
+#endif /* WITH_UTF8PROC */
+
+
+/**
+ * Find the length of a host label
+ *
+ * \param host String containing a host or FQDN
+ * \param max_length Length of host string to search (in bytes)
+ * \return Distance to next separator character or end of string
+ */
+static size_t idna__host_label_length(const char *host, size_t max_length)
+{
+ const char *p = host;
+ size_t length = 0;
+
+ while (length < max_length) {
+ if ((*p == '.') || (*p == ':') || (*p == '\0')) {
+ break;
+ }
+ length++;
+ p++;
+ }
+
+ return length;
+}
+
+
+/**
* Check if a host label is LDH
*
* \param label Host label to check
@@ -559,57 +689,6 @@ static bool idna__is_ace(const char *label, size_t len)
}
-/**
- * Verify an ACE label is valid
- *
- * \param label Host label to check
- * \param len Length of label
- * \return true if valid, false otherwise
- */
-static bool idna__verify(const char *label, size_t len)
-{
- nserror error;
- int32_t *ucs4;
- char *ace;
- ssize_t ucs4_len;
- size_t u_ucs4_len, ace_len;
-
- /* Convert our ACE label back to UCS-4 */
- error = idna__ace_to_ucs4(label, len, &ucs4, &u_ucs4_len);
- if (error != NSERROR_OK) {
- return false;
- }
-
- /* Perform NFC normalisation */
- ucs4_len = utf8proc_normalize_utf32(ucs4, u_ucs4_len,
- UTF8PROC_STABLE | UTF8PROC_COMPOSE);
- if (ucs4_len < 0) {
- free(ucs4);
- return false;
- }
-
- /* Convert the UCS-4 label back to ACE */
- error = idna__ucs4_to_ace(ucs4, (size_t)ucs4_len,
- &ace, &ace_len);
- free(ucs4);
- if (error != NSERROR_OK) {
- return false;
- }
-
- /* Check if it matches the input */
- if ((len == ace_len) && (strncmp(label, ace, len) == 0)) {
- free(ace);
- return true;
- }
-
- NSLOG(netsurf, INFO, "Re-encoded ACE label %s does not match input",
- ace);
- free(ace);
-
- return false;
-}
-
-
/* exported interface documented in idna.h */
nserror
idna_encode(const char *host, size_t len, char **ace_host, size_t *ace_len)
@@ -630,8 +709,9 @@ idna_encode(const char *host, size_t len, char **ace_host, size_t *ace_len)
/* This string is IDN or invalid */
/* Convert to Unicode */
- if ((error = idna__utf8_to_ucs4(host, label_len,
- &ucs4_host, &ucs4_len)) != NSERROR_OK) {
+ error = idna__utf8_to_ucs4(host, label_len,
+ &ucs4_host, &ucs4_len);
+ if (error != NSERROR_OK) {
return error;
}
@@ -709,7 +789,7 @@ idna_decode(const char *ace_host, size_t ace_len, char **host, size_t *host_len)
/* Decode to Unicode */
error = idna__ace_to_ucs4(ace_host, label_len,
- &ucs4_host, &ucs4_len);
+ &ucs4_host, &ucs4_len);
if (error != NSERROR_OK) {
return error;
}
@@ -722,7 +802,7 @@ idna_decode(const char *ace_host, size_t ace_len, char **host, size_t *host_len)
return error;
}
- memcpy(fqdn_p, output, output_len * 4);
+ memcpy(fqdn_p, output, output_len);
free(output);
fqdn_p += output_len;
fqdn_len += output_len;
diff --git a/utils/idna.h b/utils/idna.h
index 1fb344730..efc73eb72 100644
--- a/utils/idna.h
+++ b/utils/idna.h
@@ -16,12 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * NetSurf international domain name handling (interface).
+/**
+ * \file
+ * interface to international domain name handling.
*/
-#ifndef _NETSURF_UTILS_IDNA_H_
-#define _NETSURF_UTILS_IDNA_H_
+#ifndef NETSURF_UTILS_IDNA_H_
+#define NETSURF_UTILS_IDNA_H_
/**
* Unicode canonical combining class for virama
diff --git a/utils/idna_props.h b/utils/idna_props.h
index b5ca966c0..05546c51a 100644
--- a/utils/idna_props.h
+++ b/utils/idna_props.h
@@ -343,8 +343,8 @@ idna_table idna_derived[] = {
{ 0x0378, 0x0379, .p.property = IDNA_P_UNASSIGNED },
{ 0x037A, 0x037A, .p.property = IDNA_P_DISALLOWED },
{ 0x037B, 0x037D, .p.property = IDNA_P_PVALID },
- { 0x037E, 0x037E, .p.property = IDNA_P_DISALLOWED },
- { 0x037F, 0x0383, .p.property = IDNA_P_UNASSIGNED },
+ { 0x037E, 0x037F, .p.property = IDNA_P_DISALLOWED },
+ { 0x0380, 0x0383, .p.property = IDNA_P_UNASSIGNED },
{ 0x0384, 0x038A, .p.property = IDNA_P_DISALLOWED },
{ 0x038B, 0x038B, .p.property = IDNA_P_UNASSIGNED },
{ 0x038C, 0x038C, .p.property = IDNA_P_DISALLOWED },
@@ -579,17 +579,28 @@ idna_table idna_derived[] = {
{ 0x0523, 0x0523, .p.property = IDNA_P_PVALID },
{ 0x0524, 0x0524, .p.property = IDNA_P_DISALLOWED },
{ 0x0525, 0x0525, .p.property = IDNA_P_PVALID },
- { 0x0526, 0x0530, .p.property = IDNA_P_UNASSIGNED },
+ { 0x0526, 0x0526, .p.property = IDNA_P_DISALLOWED },
+ { 0x0527, 0x0527, .p.property = IDNA_P_PVALID },
+ { 0x0528, 0x0528, .p.property = IDNA_P_DISALLOWED },
+ { 0x0529, 0x0529, .p.property = IDNA_P_PVALID },
+ { 0x052A, 0x052A, .p.property = IDNA_P_DISALLOWED },
+ { 0x052B, 0x052B, .p.property = IDNA_P_PVALID },
+ { 0x052C, 0x052C, .p.property = IDNA_P_DISALLOWED },
+ { 0x052D, 0x052D, .p.property = IDNA_P_PVALID },
+ { 0x052E, 0x052E, .p.property = IDNA_P_DISALLOWED },
+ { 0x052F, 0x052F, .p.property = IDNA_P_PVALID },
+ { 0x0530, 0x0530, .p.property = IDNA_P_UNASSIGNED },
{ 0x0531, 0x0556, .p.property = IDNA_P_DISALLOWED },
{ 0x0557, 0x0558, .p.property = IDNA_P_UNASSIGNED },
{ 0x0559, 0x0559, .p.property = IDNA_P_PVALID },
{ 0x055A, 0x055F, .p.property = IDNA_P_DISALLOWED },
- { 0x0560, 0x0560, .p.property = IDNA_P_UNASSIGNED },
- { 0x0561, 0x0586, .p.property = IDNA_P_PVALID },
+ { 0x0560, 0x0586, .p.property = IDNA_P_PVALID },
{ 0x0587, 0x0587, .p.property = IDNA_P_DISALLOWED },
- { 0x0588, 0x0588, .p.property = IDNA_P_UNASSIGNED },
+ { 0x0588, 0x0588, .p.property = IDNA_P_PVALID },
{ 0x0589, 0x058A, .p.property = IDNA_P_DISALLOWED },
- { 0x058B, 0x0590, .p.property = IDNA_P_UNASSIGNED },
+ { 0x058B, 0x058C, .p.property = IDNA_P_UNASSIGNED },
+ { 0x058D, 0x058F, .p.property = IDNA_P_DISALLOWED },
+ { 0x0590, 0x0590, .p.property = IDNA_P_UNASSIGNED },
{ 0x0591, 0x05BD, .p.property = IDNA_P_PVALID },
{ 0x05BE, 0x05BE, .p.property = IDNA_P_DISALLOWED },
{ 0x05BF, 0x05BF, .p.property = IDNA_P_PVALID },
@@ -601,22 +612,18 @@ idna_table idna_derived[] = {
{ 0x05C7, 0x05C7, .p.property = IDNA_P_PVALID },
{ 0x05C8, 0x05CF, .p.property = IDNA_P_UNASSIGNED },
{ 0x05D0, 0x05EA, .p.property = IDNA_P_PVALID },
- { 0x05EB, 0x05EF, .p.property = IDNA_P_UNASSIGNED },
- { 0x05F0, 0x05F2, .p.property = IDNA_P_PVALID },
+ { 0x05EB, 0x05EE, .p.property = IDNA_P_UNASSIGNED },
+ { 0x05EF, 0x05F2, .p.property = IDNA_P_PVALID },
{ 0x05F3, 0x05F4, .p.property = IDNA_P_CONTEXTO },
{ 0x05F5, 0x05FF, .p.property = IDNA_P_UNASSIGNED },
- { 0x0600, 0x0603, .p.property = IDNA_P_DISALLOWED },
- { 0x0604, 0x0605, .p.property = IDNA_P_UNASSIGNED },
- { 0x0606, 0x060F, .p.property = IDNA_P_DISALLOWED },
+ { 0x0600, 0x060F, .p.property = IDNA_P_DISALLOWED },
{ 0x0610, 0x061A, .p.property = IDNA_P_PVALID },
- { 0x061B, 0x061B, .p.property = IDNA_P_DISALLOWED },
- { 0x061C, 0x061D, .p.property = IDNA_P_UNASSIGNED },
+ { 0x061B, 0x061C, .p.property = IDNA_P_DISALLOWED },
+ { 0x061D, 0x061D, .p.property = IDNA_P_UNASSIGNED },
{ 0x061E, 0x061F, .p.property = IDNA_P_DISALLOWED },
- { 0x0620, 0x0620, .p.property = IDNA_P_UNASSIGNED },
- { 0x0621, 0x063F, .p.property = IDNA_P_PVALID },
+ { 0x0620, 0x063F, .p.property = IDNA_P_PVALID },
{ 0x0640, 0x0640, .p.property = IDNA_P_DISALLOWED },
- { 0x0641, 0x065E, .p.property = IDNA_P_PVALID },
- { 0x065F, 0x065F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x0641, 0x065F, .p.property = IDNA_P_PVALID },
{ 0x0660, 0x0669, .p.property = IDNA_P_CONTEXTO },
{ 0x066A, 0x066D, .p.property = IDNA_P_DISALLOWED },
{ 0x066E, 0x0674, .p.property = IDNA_P_PVALID },
@@ -639,27 +646,32 @@ idna_table idna_derived[] = {
{ 0x07B2, 0x07BF, .p.property = IDNA_P_UNASSIGNED },
{ 0x07C0, 0x07F5, .p.property = IDNA_P_PVALID },
{ 0x07F6, 0x07FA, .p.property = IDNA_P_DISALLOWED },
- { 0x07FB, 0x07FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x07FB, 0x07FC, .p.property = IDNA_P_UNASSIGNED },
+ { 0x07FD, 0x07FD, .p.property = IDNA_P_PVALID },
+ { 0x07FE, 0x07FF, .p.property = IDNA_P_DISALLOWED },
{ 0x0800, 0x082D, .p.property = IDNA_P_PVALID },
{ 0x082E, 0x082F, .p.property = IDNA_P_UNASSIGNED },
{ 0x0830, 0x083E, .p.property = IDNA_P_DISALLOWED },
- { 0x083F, 0x08FF, .p.property = IDNA_P_UNASSIGNED },
- { 0x0900, 0x0939, .p.property = IDNA_P_PVALID },
- { 0x093A, 0x093B, .p.property = IDNA_P_UNASSIGNED },
- { 0x093C, 0x094E, .p.property = IDNA_P_PVALID },
- { 0x094F, 0x094F, .p.property = IDNA_P_UNASSIGNED },
- { 0x0950, 0x0955, .p.property = IDNA_P_PVALID },
- { 0x0956, 0x0957, .p.property = IDNA_P_UNASSIGNED },
+ { 0x083F, 0x083F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x0840, 0x085B, .p.property = IDNA_P_PVALID },
+ { 0x085C, 0x085D, .p.property = IDNA_P_UNASSIGNED },
+ { 0x085E, 0x085E, .p.property = IDNA_P_DISALLOWED },
+ { 0x085F, 0x085F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x0860, 0x086A, .p.property = IDNA_P_PVALID },
+ { 0x086B, 0x089F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x08A0, 0x08B4, .p.property = IDNA_P_PVALID },
+ { 0x08B5, 0x08B5, .p.property = IDNA_P_UNASSIGNED },
+ { 0x08B6, 0x08BD, .p.property = IDNA_P_PVALID },
+ { 0x08BE, 0x08D2, .p.property = IDNA_P_UNASSIGNED },
+ { 0x08D3, 0x08E1, .p.property = IDNA_P_PVALID },
+ { 0x08E2, 0x08E2, .p.property = IDNA_P_DISALLOWED },
+ { 0x08E3, 0x0957, .p.property = IDNA_P_PVALID },
{ 0x0958, 0x095F, .p.property = IDNA_P_DISALLOWED },
{ 0x0960, 0x0963, .p.property = IDNA_P_PVALID },
{ 0x0964, 0x0965, .p.property = IDNA_P_DISALLOWED },
{ 0x0966, 0x096F, .p.property = IDNA_P_PVALID },
{ 0x0970, 0x0970, .p.property = IDNA_P_DISALLOWED },
- { 0x0971, 0x0972, .p.property = IDNA_P_PVALID },
- { 0x0973, 0x0978, .p.property = IDNA_P_UNASSIGNED },
- { 0x0979, 0x097F, .p.property = IDNA_P_PVALID },
- { 0x0980, 0x0980, .p.property = IDNA_P_UNASSIGNED },
- { 0x0981, 0x0983, .p.property = IDNA_P_PVALID },
+ { 0x0971, 0x0983, .p.property = IDNA_P_PVALID },
{ 0x0984, 0x0984, .p.property = IDNA_P_UNASSIGNED },
{ 0x0985, 0x098C, .p.property = IDNA_P_PVALID },
{ 0x098D, 0x098E, .p.property = IDNA_P_UNASSIGNED },
@@ -688,7 +700,10 @@ idna_table idna_derived[] = {
{ 0x09E4, 0x09E5, .p.property = IDNA_P_UNASSIGNED },
{ 0x09E6, 0x09F1, .p.property = IDNA_P_PVALID },
{ 0x09F2, 0x09FB, .p.property = IDNA_P_DISALLOWED },
- { 0x09FC, 0x0A00, .p.property = IDNA_P_UNASSIGNED },
+ { 0x09FC, 0x09FC, .p.property = IDNA_P_PVALID },
+ { 0x09FD, 0x09FD, .p.property = IDNA_P_DISALLOWED },
+ { 0x09FE, 0x09FE, .p.property = IDNA_P_PVALID },
+ { 0x09FF, 0x0A00, .p.property = IDNA_P_UNASSIGNED },
{ 0x0A01, 0x0A03, .p.property = IDNA_P_PVALID },
{ 0x0A04, 0x0A04, .p.property = IDNA_P_UNASSIGNED },
{ 0x0A05, 0x0A0A, .p.property = IDNA_P_PVALID },
@@ -723,7 +738,8 @@ idna_table idna_derived[] = {
{ 0x0A5E, 0x0A5E, .p.property = IDNA_P_DISALLOWED },
{ 0x0A5F, 0x0A65, .p.property = IDNA_P_UNASSIGNED },
{ 0x0A66, 0x0A75, .p.property = IDNA_P_PVALID },
- { 0x0A76, 0x0A80, .p.property = IDNA_P_UNASSIGNED },
+ { 0x0A76, 0x0A76, .p.property = IDNA_P_DISALLOWED },
+ { 0x0A77, 0x0A80, .p.property = IDNA_P_UNASSIGNED },
{ 0x0A81, 0x0A83, .p.property = IDNA_P_PVALID },
{ 0x0A84, 0x0A84, .p.property = IDNA_P_UNASSIGNED },
{ 0x0A85, 0x0A8D, .p.property = IDNA_P_PVALID },
@@ -749,9 +765,10 @@ idna_table idna_derived[] = {
{ 0x0AE0, 0x0AE3, .p.property = IDNA_P_PVALID },
{ 0x0AE4, 0x0AE5, .p.property = IDNA_P_UNASSIGNED },
{ 0x0AE6, 0x0AEF, .p.property = IDNA_P_PVALID },
- { 0x0AF0, 0x0AF0, .p.property = IDNA_P_UNASSIGNED },
- { 0x0AF1, 0x0AF1, .p.property = IDNA_P_DISALLOWED },
- { 0x0AF2, 0x0B00, .p.property = IDNA_P_UNASSIGNED },
+ { 0x0AF0, 0x0AF1, .p.property = IDNA_P_DISALLOWED },
+ { 0x0AF2, 0x0AF8, .p.property = IDNA_P_UNASSIGNED },
+ { 0x0AF9, 0x0AFF, .p.property = IDNA_P_PVALID },
+ { 0x0B00, 0x0B00, .p.property = IDNA_P_UNASSIGNED },
{ 0x0B01, 0x0B03, .p.property = IDNA_P_PVALID },
{ 0x0B04, 0x0B04, .p.property = IDNA_P_UNASSIGNED },
{ 0x0B05, 0x0B0C, .p.property = IDNA_P_PVALID },
@@ -781,7 +798,8 @@ idna_table idna_derived[] = {
{ 0x0B66, 0x0B6F, .p.property = IDNA_P_PVALID },
{ 0x0B70, 0x0B70, .p.property = IDNA_P_DISALLOWED },
{ 0x0B71, 0x0B71, .p.property = IDNA_P_PVALID },
- { 0x0B72, 0x0B81, .p.property = IDNA_P_UNASSIGNED },
+ { 0x0B72, 0x0B77, .p.property = IDNA_P_DISALLOWED },
+ { 0x0B78, 0x0B81, .p.property = IDNA_P_UNASSIGNED },
{ 0x0B82, 0x0B83, .p.property = IDNA_P_PVALID },
{ 0x0B84, 0x0B84, .p.property = IDNA_P_UNASSIGNED },
{ 0x0B85, 0x0B8A, .p.property = IDNA_P_PVALID },
@@ -814,18 +832,14 @@ idna_table idna_derived[] = {
{ 0x0BD8, 0x0BE5, .p.property = IDNA_P_UNASSIGNED },
{ 0x0BE6, 0x0BEF, .p.property = IDNA_P_PVALID },
{ 0x0BF0, 0x0BFA, .p.property = IDNA_P_DISALLOWED },
- { 0x0BFB, 0x0C00, .p.property = IDNA_P_UNASSIGNED },
- { 0x0C01, 0x0C03, .p.property = IDNA_P_PVALID },
- { 0x0C04, 0x0C04, .p.property = IDNA_P_UNASSIGNED },
- { 0x0C05, 0x0C0C, .p.property = IDNA_P_PVALID },
+ { 0x0BFB, 0x0BFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x0C00, 0x0C0C, .p.property = IDNA_P_PVALID },
{ 0x0C0D, 0x0C0D, .p.property = IDNA_P_UNASSIGNED },
{ 0x0C0E, 0x0C10, .p.property = IDNA_P_PVALID },
{ 0x0C11, 0x0C11, .p.property = IDNA_P_UNASSIGNED },
{ 0x0C12, 0x0C28, .p.property = IDNA_P_PVALID },
{ 0x0C29, 0x0C29, .p.property = IDNA_P_UNASSIGNED },
- { 0x0C2A, 0x0C33, .p.property = IDNA_P_PVALID },
- { 0x0C34, 0x0C34, .p.property = IDNA_P_UNASSIGNED },
- { 0x0C35, 0x0C39, .p.property = IDNA_P_PVALID },
+ { 0x0C2A, 0x0C39, .p.property = IDNA_P_PVALID },
{ 0x0C3A, 0x0C3C, .p.property = IDNA_P_UNASSIGNED },
{ 0x0C3D, 0x0C44, .p.property = IDNA_P_PVALID },
{ 0x0C45, 0x0C45, .p.property = IDNA_P_UNASSIGNED },
@@ -835,16 +849,15 @@ idna_table idna_derived[] = {
{ 0x0C4E, 0x0C54, .p.property = IDNA_P_UNASSIGNED },
{ 0x0C55, 0x0C56, .p.property = IDNA_P_PVALID },
{ 0x0C57, 0x0C57, .p.property = IDNA_P_UNASSIGNED },
- { 0x0C58, 0x0C59, .p.property = IDNA_P_PVALID },
- { 0x0C5A, 0x0C5F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x0C58, 0x0C5A, .p.property = IDNA_P_PVALID },
+ { 0x0C5B, 0x0C5F, .p.property = IDNA_P_UNASSIGNED },
{ 0x0C60, 0x0C63, .p.property = IDNA_P_PVALID },
{ 0x0C64, 0x0C65, .p.property = IDNA_P_UNASSIGNED },
{ 0x0C66, 0x0C6F, .p.property = IDNA_P_PVALID },
{ 0x0C70, 0x0C77, .p.property = IDNA_P_UNASSIGNED },
{ 0x0C78, 0x0C7F, .p.property = IDNA_P_DISALLOWED },
- { 0x0C80, 0x0C81, .p.property = IDNA_P_UNASSIGNED },
- { 0x0C82, 0x0C83, .p.property = IDNA_P_PVALID },
- { 0x0C84, 0x0C84, .p.property = IDNA_P_UNASSIGNED },
+ { 0x0C80, 0x0C83, .p.property = IDNA_P_PVALID },
+ { 0x0C84, 0x0C84, .p.property = IDNA_P_DISALLOWED },
{ 0x0C85, 0x0C8C, .p.property = IDNA_P_PVALID },
{ 0x0C8D, 0x0C8D, .p.property = IDNA_P_UNASSIGNED },
{ 0x0C8E, 0x0C90, .p.property = IDNA_P_PVALID },
@@ -869,32 +882,27 @@ idna_table idna_derived[] = {
{ 0x0CE4, 0x0CE5, .p.property = IDNA_P_UNASSIGNED },
{ 0x0CE6, 0x0CEF, .p.property = IDNA_P_PVALID },
{ 0x0CF0, 0x0CF0, .p.property = IDNA_P_UNASSIGNED },
- { 0x0CF1, 0x0CF2, .p.property = IDNA_P_DISALLOWED },
- { 0x0CF3, 0x0D01, .p.property = IDNA_P_UNASSIGNED },
- { 0x0D02, 0x0D03, .p.property = IDNA_P_PVALID },
+ { 0x0CF1, 0x0CF2, .p.property = IDNA_P_PVALID },
+ { 0x0CF3, 0x0CFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x0D00, 0x0D03, .p.property = IDNA_P_PVALID },
{ 0x0D04, 0x0D04, .p.property = IDNA_P_UNASSIGNED },
{ 0x0D05, 0x0D0C, .p.property = IDNA_P_PVALID },
{ 0x0D0D, 0x0D0D, .p.property = IDNA_P_UNASSIGNED },
{ 0x0D0E, 0x0D10, .p.property = IDNA_P_PVALID },
{ 0x0D11, 0x0D11, .p.property = IDNA_P_UNASSIGNED },
- { 0x0D12, 0x0D28, .p.property = IDNA_P_PVALID },
- { 0x0D29, 0x0D29, .p.property = IDNA_P_UNASSIGNED },
- { 0x0D2A, 0x0D39, .p.property = IDNA_P_PVALID },
- { 0x0D3A, 0x0D3C, .p.property = IDNA_P_UNASSIGNED },
- { 0x0D3D, 0x0D44, .p.property = IDNA_P_PVALID },
+ { 0x0D12, 0x0D44, .p.property = IDNA_P_PVALID },
{ 0x0D45, 0x0D45, .p.property = IDNA_P_UNASSIGNED },
{ 0x0D46, 0x0D48, .p.property = IDNA_P_PVALID },
{ 0x0D49, 0x0D49, .p.property = IDNA_P_UNASSIGNED },
- { 0x0D4A, 0x0D4D, .p.property = IDNA_P_PVALID },
- { 0x0D4E, 0x0D56, .p.property = IDNA_P_UNASSIGNED },
- { 0x0D57, 0x0D57, .p.property = IDNA_P_PVALID },
- { 0x0D58, 0x0D5F, .p.property = IDNA_P_UNASSIGNED },
- { 0x0D60, 0x0D63, .p.property = IDNA_P_PVALID },
+ { 0x0D4A, 0x0D4E, .p.property = IDNA_P_PVALID },
+ { 0x0D4F, 0x0D4F, .p.property = IDNA_P_DISALLOWED },
+ { 0x0D50, 0x0D53, .p.property = IDNA_P_UNASSIGNED },
+ { 0x0D54, 0x0D57, .p.property = IDNA_P_PVALID },
+ { 0x0D58, 0x0D5E, .p.property = IDNA_P_DISALLOWED },
+ { 0x0D5F, 0x0D63, .p.property = IDNA_P_PVALID },
{ 0x0D64, 0x0D65, .p.property = IDNA_P_UNASSIGNED },
{ 0x0D66, 0x0D6F, .p.property = IDNA_P_PVALID },
- { 0x0D70, 0x0D75, .p.property = IDNA_P_DISALLOWED },
- { 0x0D76, 0x0D78, .p.property = IDNA_P_UNASSIGNED },
- { 0x0D79, 0x0D79, .p.property = IDNA_P_DISALLOWED },
+ { 0x0D70, 0x0D79, .p.property = IDNA_P_DISALLOWED },
{ 0x0D7A, 0x0D7F, .p.property = IDNA_P_PVALID },
{ 0x0D80, 0x0D81, .p.property = IDNA_P_UNASSIGNED },
{ 0x0D82, 0x0D83, .p.property = IDNA_P_PVALID },
@@ -916,7 +924,9 @@ idna_table idna_derived[] = {
{ 0x0DD6, 0x0DD6, .p.property = IDNA_P_PVALID },
{ 0x0DD7, 0x0DD7, .p.property = IDNA_P_UNASSIGNED },
{ 0x0DD8, 0x0DDF, .p.property = IDNA_P_PVALID },
- { 0x0DE0, 0x0DF1, .p.property = IDNA_P_UNASSIGNED },
+ { 0x0DE0, 0x0DE5, .p.property = IDNA_P_UNASSIGNED },
+ { 0x0DE6, 0x0DEF, .p.property = IDNA_P_PVALID },
+ { 0x0DF0, 0x0DF1, .p.property = IDNA_P_UNASSIGNED },
{ 0x0DF2, 0x0DF3, .p.property = IDNA_P_PVALID },
{ 0x0DF4, 0x0DF4, .p.property = IDNA_P_DISALLOWED },
{ 0x0DF5, 0x0E00, .p.property = IDNA_P_UNASSIGNED },
@@ -967,7 +977,8 @@ idna_table idna_derived[] = {
{ 0x0ED0, 0x0ED9, .p.property = IDNA_P_PVALID },
{ 0x0EDA, 0x0EDB, .p.property = IDNA_P_UNASSIGNED },
{ 0x0EDC, 0x0EDD, .p.property = IDNA_P_DISALLOWED },
- { 0x0EDE, 0x0EFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x0EDE, 0x0EDF, .p.property = IDNA_P_PVALID },
+ { 0x0EE0, 0x0EFF, .p.property = IDNA_P_UNASSIGNED },
{ 0x0F00, 0x0F00, .p.property = IDNA_P_PVALID },
{ 0x0F01, 0x0F0A, .p.property = IDNA_P_DISALLOWED },
{ 0x0F0B, 0x0F0B, .p.property = IDNA_P_PVALID },
@@ -1006,9 +1017,7 @@ idna_table idna_derived[] = {
{ 0x0F81, 0x0F81, .p.property = IDNA_P_DISALLOWED },
{ 0x0F82, 0x0F84, .p.property = IDNA_P_PVALID },
{ 0x0F85, 0x0F85, .p.property = IDNA_P_DISALLOWED },
- { 0x0F86, 0x0F8B, .p.property = IDNA_P_PVALID },
- { 0x0F8C, 0x0F8F, .p.property = IDNA_P_UNASSIGNED },
- { 0x0F90, 0x0F92, .p.property = IDNA_P_PVALID },
+ { 0x0F86, 0x0F92, .p.property = IDNA_P_PVALID },
{ 0x0F93, 0x0F93, .p.property = IDNA_P_DISALLOWED },
{ 0x0F94, 0x0F97, .p.property = IDNA_P_PVALID },
{ 0x0F98, 0x0F98, .p.property = IDNA_P_UNASSIGNED },
@@ -1028,16 +1037,20 @@ idna_table idna_derived[] = {
{ 0x0FC6, 0x0FC6, .p.property = IDNA_P_PVALID },
{ 0x0FC7, 0x0FCC, .p.property = IDNA_P_DISALLOWED },
{ 0x0FCD, 0x0FCD, .p.property = IDNA_P_UNASSIGNED },
- { 0x0FCE, 0x0FD8, .p.property = IDNA_P_DISALLOWED },
- { 0x0FD9, 0x0FFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x0FCE, 0x0FDA, .p.property = IDNA_P_DISALLOWED },
+ { 0x0FDB, 0x0FFF, .p.property = IDNA_P_UNASSIGNED },
{ 0x1000, 0x1049, .p.property = IDNA_P_PVALID },
{ 0x104A, 0x104F, .p.property = IDNA_P_DISALLOWED },
{ 0x1050, 0x109D, .p.property = IDNA_P_PVALID },
{ 0x109E, 0x10C5, .p.property = IDNA_P_DISALLOWED },
- { 0x10C6, 0x10CF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10C6, 0x10C6, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10C7, 0x10C7, .p.property = IDNA_P_DISALLOWED },
+ { 0x10C8, 0x10CC, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10CD, 0x10CD, .p.property = IDNA_P_DISALLOWED },
+ { 0x10CE, 0x10CF, .p.property = IDNA_P_UNASSIGNED },
{ 0x10D0, 0x10FA, .p.property = IDNA_P_PVALID },
{ 0x10FB, 0x10FC, .p.property = IDNA_P_DISALLOWED },
- { 0x10FD, 0x10FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10FD, 0x10FF, .p.property = IDNA_P_PVALID },
{ 0x1100, 0x11FF, .p.property = IDNA_P_DISALLOWED },
{ 0x1200, 0x1248, .p.property = IDNA_P_PVALID },
{ 0x1249, 0x1249, .p.property = IDNA_P_UNASSIGNED },
@@ -1070,15 +1083,17 @@ idna_table idna_derived[] = {
{ 0x1312, 0x1315, .p.property = IDNA_P_PVALID },
{ 0x1316, 0x1317, .p.property = IDNA_P_UNASSIGNED },
{ 0x1318, 0x135A, .p.property = IDNA_P_PVALID },
- { 0x135B, 0x135E, .p.property = IDNA_P_UNASSIGNED },
- { 0x135F, 0x135F, .p.property = IDNA_P_PVALID },
+ { 0x135B, 0x135C, .p.property = IDNA_P_UNASSIGNED },
+ { 0x135D, 0x135F, .p.property = IDNA_P_PVALID },
{ 0x1360, 0x137C, .p.property = IDNA_P_DISALLOWED },
{ 0x137D, 0x137F, .p.property = IDNA_P_UNASSIGNED },
{ 0x1380, 0x138F, .p.property = IDNA_P_PVALID },
{ 0x1390, 0x1399, .p.property = IDNA_P_DISALLOWED },
{ 0x139A, 0x139F, .p.property = IDNA_P_UNASSIGNED },
- { 0x13A0, 0x13F4, .p.property = IDNA_P_PVALID },
- { 0x13F5, 0x13FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x13A0, 0x13F5, .p.property = IDNA_P_PVALID },
+ { 0x13F6, 0x13F7, .p.property = IDNA_P_UNASSIGNED },
+ { 0x13F8, 0x13FD, .p.property = IDNA_P_DISALLOWED },
+ { 0x13FE, 0x13FF, .p.property = IDNA_P_UNASSIGNED },
{ 0x1400, 0x1400, .p.property = IDNA_P_DISALLOWED },
{ 0x1401, 0x166C, .p.property = IDNA_P_PVALID },
{ 0x166D, 0x166E, .p.property = IDNA_P_DISALLOWED },
@@ -1089,7 +1104,8 @@ idna_table idna_derived[] = {
{ 0x169D, 0x169F, .p.property = IDNA_P_UNASSIGNED },
{ 0x16A0, 0x16EA, .p.property = IDNA_P_PVALID },
{ 0x16EB, 0x16F0, .p.property = IDNA_P_DISALLOWED },
- { 0x16F1, 0x16FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x16F1, 0x16F8, .p.property = IDNA_P_PVALID },
+ { 0x16F9, 0x16FF, .p.property = IDNA_P_UNASSIGNED },
{ 0x1700, 0x170C, .p.property = IDNA_P_PVALID },
{ 0x170D, 0x170D, .p.property = IDNA_P_UNASSIGNED },
{ 0x170E, 0x1714, .p.property = IDNA_P_PVALID },
@@ -1121,14 +1137,14 @@ idna_table idna_derived[] = {
{ 0x180F, 0x180F, .p.property = IDNA_P_UNASSIGNED },
{ 0x1810, 0x1819, .p.property = IDNA_P_PVALID },
{ 0x181A, 0x181F, .p.property = IDNA_P_UNASSIGNED },
- { 0x1820, 0x1877, .p.property = IDNA_P_PVALID },
- { 0x1878, 0x187F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1820, 0x1878, .p.property = IDNA_P_PVALID },
+ { 0x1879, 0x187F, .p.property = IDNA_P_UNASSIGNED },
{ 0x1880, 0x18AA, .p.property = IDNA_P_PVALID },
{ 0x18AB, 0x18AF, .p.property = IDNA_P_UNASSIGNED },
{ 0x18B0, 0x18F5, .p.property = IDNA_P_PVALID },
{ 0x18F6, 0x18FF, .p.property = IDNA_P_UNASSIGNED },
- { 0x1900, 0x191C, .p.property = IDNA_P_PVALID },
- { 0x191D, 0x191F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1900, 0x191E, .p.property = IDNA_P_PVALID },
+ { 0x191F, 0x191F, .p.property = IDNA_P_UNASSIGNED },
{ 0x1920, 0x192B, .p.property = IDNA_P_PVALID },
{ 0x192C, 0x192F, .p.property = IDNA_P_UNASSIGNED },
{ 0x1930, 0x193B, .p.property = IDNA_P_PVALID },
@@ -1144,7 +1160,8 @@ idna_table idna_derived[] = {
{ 0x19AC, 0x19AF, .p.property = IDNA_P_UNASSIGNED },
{ 0x19B0, 0x19C9, .p.property = IDNA_P_PVALID },
{ 0x19CA, 0x19CF, .p.property = IDNA_P_UNASSIGNED },
- { 0x19D0, 0x19DA, .p.property = IDNA_P_PVALID },
+ { 0x19D0, 0x19D9, .p.property = IDNA_P_PVALID },
+ { 0x19DA, 0x19DA, .p.property = IDNA_P_DISALLOWED },
{ 0x19DB, 0x19DD, .p.property = IDNA_P_UNASSIGNED },
{ 0x19DE, 0x19FF, .p.property = IDNA_P_DISALLOWED },
{ 0x1A00, 0x1A1B, .p.property = IDNA_P_PVALID },
@@ -1161,7 +1178,10 @@ idna_table idna_derived[] = {
{ 0x1AA0, 0x1AA6, .p.property = IDNA_P_DISALLOWED },
{ 0x1AA7, 0x1AA7, .p.property = IDNA_P_PVALID },
{ 0x1AA8, 0x1AAD, .p.property = IDNA_P_DISALLOWED },
- { 0x1AAE, 0x1AFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1AAE, 0x1AAF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1AB0, 0x1ABD, .p.property = IDNA_P_PVALID },
+ { 0x1ABE, 0x1ABE, .p.property = IDNA_P_DISALLOWED },
+ { 0x1ABF, 0x1AFF, .p.property = IDNA_P_UNASSIGNED },
{ 0x1B00, 0x1B4B, .p.property = IDNA_P_PVALID },
{ 0x1B4C, 0x1B4F, .p.property = IDNA_P_UNASSIGNED },
{ 0x1B50, 0x1B59, .p.property = IDNA_P_PVALID },
@@ -1169,22 +1189,25 @@ idna_table idna_derived[] = {
{ 0x1B6B, 0x1B73, .p.property = IDNA_P_PVALID },
{ 0x1B74, 0x1B7C, .p.property = IDNA_P_DISALLOWED },
{ 0x1B7D, 0x1B7F, .p.property = IDNA_P_UNASSIGNED },
- { 0x1B80, 0x1BAA, .p.property = IDNA_P_PVALID },
- { 0x1BAB, 0x1BAD, .p.property = IDNA_P_UNASSIGNED },
- { 0x1BAE, 0x1BB9, .p.property = IDNA_P_PVALID },
- { 0x1BBA, 0x1BFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1B80, 0x1BF3, .p.property = IDNA_P_PVALID },
+ { 0x1BF4, 0x1BFB, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1BFC, 0x1BFF, .p.property = IDNA_P_DISALLOWED },
{ 0x1C00, 0x1C37, .p.property = IDNA_P_PVALID },
{ 0x1C38, 0x1C3A, .p.property = IDNA_P_UNASSIGNED },
{ 0x1C3B, 0x1C3F, .p.property = IDNA_P_DISALLOWED },
{ 0x1C40, 0x1C49, .p.property = IDNA_P_PVALID },
{ 0x1C4A, 0x1C4C, .p.property = IDNA_P_UNASSIGNED },
{ 0x1C4D, 0x1C7D, .p.property = IDNA_P_PVALID },
- { 0x1C7E, 0x1C7F, .p.property = IDNA_P_DISALLOWED },
- { 0x1C80, 0x1CCF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1C7E, 0x1C88, .p.property = IDNA_P_DISALLOWED },
+ { 0x1C89, 0x1C8F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1C90, 0x1CBA, .p.property = IDNA_P_DISALLOWED },
+ { 0x1CBB, 0x1CBC, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1CBD, 0x1CC7, .p.property = IDNA_P_DISALLOWED },
+ { 0x1CC8, 0x1CCF, .p.property = IDNA_P_UNASSIGNED },
{ 0x1CD0, 0x1CD2, .p.property = IDNA_P_PVALID },
{ 0x1CD3, 0x1CD3, .p.property = IDNA_P_DISALLOWED },
- { 0x1CD4, 0x1CF2, .p.property = IDNA_P_PVALID },
- { 0x1CF3, 0x1CFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1CD4, 0x1CF9, .p.property = IDNA_P_PVALID },
+ { 0x1CFA, 0x1CFF, .p.property = IDNA_P_UNASSIGNED },
{ 0x1D00, 0x1D2B, .p.property = IDNA_P_PVALID },
{ 0x1D2C, 0x1D2E, .p.property = IDNA_P_DISALLOWED },
{ 0x1D2F, 0x1D2F, .p.property = IDNA_P_PVALID },
@@ -1197,9 +1220,9 @@ idna_table idna_derived[] = {
{ 0x1D78, 0x1D78, .p.property = IDNA_P_DISALLOWED },
{ 0x1D79, 0x1D9A, .p.property = IDNA_P_PVALID },
{ 0x1D9B, 0x1DBF, .p.property = IDNA_P_DISALLOWED },
- { 0x1DC0, 0x1DE6, .p.property = IDNA_P_PVALID },
- { 0x1DE7, 0x1DFC, .p.property = IDNA_P_UNASSIGNED },
- { 0x1DFD, 0x1DFF, .p.property = IDNA_P_PVALID },
+ { 0x1DC0, 0x1DF9, .p.property = IDNA_P_PVALID },
+ { 0x1DFA, 0x1DFA, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1DFB, 0x1DFF, .p.property = IDNA_P_PVALID },
{ 0x1E00, 0x1E00, .p.property = IDNA_P_DISALLOWED },
{ 0x1E01, 0x1E01, .p.property = IDNA_P_PVALID },
{ 0x1E02, 0x1E02, .p.property = IDNA_P_DISALLOWED },
@@ -1518,65 +1541,35 @@ idna_table idna_derived[] = {
{ 0x2000, 0x200B, .p.property = IDNA_P_DISALLOWED },
{ 0x200C, 0x200D, .p.property = IDNA_P_CONTEXTJ },
{ 0x200E, 0x2064, .p.property = IDNA_P_DISALLOWED },
- { 0x2065, 0x2069, .p.property = IDNA_P_UNASSIGNED },
- { 0x206A, 0x2071, .p.property = IDNA_P_DISALLOWED },
+ { 0x2065, 0x2065, .p.property = IDNA_P_UNASSIGNED },
+ { 0x2066, 0x2071, .p.property = IDNA_P_DISALLOWED },
{ 0x2072, 0x2073, .p.property = IDNA_P_UNASSIGNED },
{ 0x2074, 0x208E, .p.property = IDNA_P_DISALLOWED },
{ 0x208F, 0x208F, .p.property = IDNA_P_UNASSIGNED },
- { 0x2090, 0x2094, .p.property = IDNA_P_DISALLOWED },
- { 0x2095, 0x209F, .p.property = IDNA_P_UNASSIGNED },
- { 0x20A0, 0x20B8, .p.property = IDNA_P_DISALLOWED },
- { 0x20B9, 0x20CF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x2090, 0x209C, .p.property = IDNA_P_DISALLOWED },
+ { 0x209D, 0x209F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x20A0, 0x20BF, .p.property = IDNA_P_DISALLOWED },
+ { 0x20C0, 0x20CF, .p.property = IDNA_P_UNASSIGNED },
{ 0x20D0, 0x20F0, .p.property = IDNA_P_DISALLOWED },
{ 0x20F1, 0x20FF, .p.property = IDNA_P_UNASSIGNED },
{ 0x2100, 0x214D, .p.property = IDNA_P_DISALLOWED },
{ 0x214E, 0x214E, .p.property = IDNA_P_PVALID },
{ 0x214F, 0x2183, .p.property = IDNA_P_DISALLOWED },
{ 0x2184, 0x2184, .p.property = IDNA_P_PVALID },
- { 0x2185, 0x2189, .p.property = IDNA_P_DISALLOWED },
- { 0x218A, 0x218F, .p.property = IDNA_P_UNASSIGNED },
- { 0x2190, 0x23E8, .p.property = IDNA_P_DISALLOWED },
- { 0x23E9, 0x23FF, .p.property = IDNA_P_UNASSIGNED },
- { 0x2400, 0x2426, .p.property = IDNA_P_DISALLOWED },
+ { 0x2185, 0x218B, .p.property = IDNA_P_DISALLOWED },
+ { 0x218C, 0x218F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x2190, 0x2426, .p.property = IDNA_P_DISALLOWED },
{ 0x2427, 0x243F, .p.property = IDNA_P_UNASSIGNED },
{ 0x2440, 0x244A, .p.property = IDNA_P_DISALLOWED },
{ 0x244B, 0x245F, .p.property = IDNA_P_UNASSIGNED },
- { 0x2460, 0x26CD, .p.property = IDNA_P_DISALLOWED },
- { 0x26CE, 0x26CE, .p.property = IDNA_P_UNASSIGNED },
- { 0x26CF, 0x26E1, .p.property = IDNA_P_DISALLOWED },
- { 0x26E2, 0x26E2, .p.property = IDNA_P_UNASSIGNED },
- { 0x26E3, 0x26E3, .p.property = IDNA_P_DISALLOWED },
- { 0x26E4, 0x26E7, .p.property = IDNA_P_UNASSIGNED },
- { 0x26E8, 0x26FF, .p.property = IDNA_P_DISALLOWED },
- { 0x2700, 0x2700, .p.property = IDNA_P_UNASSIGNED },
- { 0x2701, 0x2704, .p.property = IDNA_P_DISALLOWED },
- { 0x2705, 0x2705, .p.property = IDNA_P_UNASSIGNED },
- { 0x2706, 0x2709, .p.property = IDNA_P_DISALLOWED },
- { 0x270A, 0x270B, .p.property = IDNA_P_UNASSIGNED },
- { 0x270C, 0x2727, .p.property = IDNA_P_DISALLOWED },
- { 0x2728, 0x2728, .p.property = IDNA_P_UNASSIGNED },
- { 0x2729, 0x274B, .p.property = IDNA_P_DISALLOWED },
- { 0x274C, 0x274C, .p.property = IDNA_P_UNASSIGNED },
- { 0x274D, 0x274D, .p.property = IDNA_P_DISALLOWED },
- { 0x274E, 0x274E, .p.property = IDNA_P_UNASSIGNED },
- { 0x274F, 0x2752, .p.property = IDNA_P_DISALLOWED },
- { 0x2753, 0x2755, .p.property = IDNA_P_UNASSIGNED },
- { 0x2756, 0x275E, .p.property = IDNA_P_DISALLOWED },
- { 0x275F, 0x2760, .p.property = IDNA_P_UNASSIGNED },
- { 0x2761, 0x2794, .p.property = IDNA_P_DISALLOWED },
- { 0x2795, 0x2797, .p.property = IDNA_P_UNASSIGNED },
- { 0x2798, 0x27AF, .p.property = IDNA_P_DISALLOWED },
- { 0x27B0, 0x27B0, .p.property = IDNA_P_UNASSIGNED },
- { 0x27B1, 0x27BE, .p.property = IDNA_P_DISALLOWED },
- { 0x27BF, 0x27BF, .p.property = IDNA_P_UNASSIGNED },
- { 0x27C0, 0x27CA, .p.property = IDNA_P_DISALLOWED },
- { 0x27CB, 0x27CB, .p.property = IDNA_P_UNASSIGNED },
- { 0x27CC, 0x27CC, .p.property = IDNA_P_DISALLOWED },
- { 0x27CD, 0x27CF, .p.property = IDNA_P_UNASSIGNED },
- { 0x27D0, 0x2B4C, .p.property = IDNA_P_DISALLOWED },
- { 0x2B4D, 0x2B4F, .p.property = IDNA_P_UNASSIGNED },
- { 0x2B50, 0x2B59, .p.property = IDNA_P_DISALLOWED },
- { 0x2B5A, 0x2BFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x2460, 0x2B73, .p.property = IDNA_P_DISALLOWED },
+ { 0x2B74, 0x2B75, .p.property = IDNA_P_UNASSIGNED },
+ { 0x2B76, 0x2B95, .p.property = IDNA_P_DISALLOWED },
+ { 0x2B96, 0x2B97, .p.property = IDNA_P_UNASSIGNED },
+ { 0x2B98, 0x2BC8, .p.property = IDNA_P_DISALLOWED },
+ { 0x2BC9, 0x2BC9, .p.property = IDNA_P_UNASSIGNED },
+ { 0x2BCA, 0x2BFE, .p.property = IDNA_P_DISALLOWED },
+ { 0x2BFF, 0x2BFF, .p.property = IDNA_P_UNASSIGNED },
{ 0x2C00, 0x2C2E, .p.property = IDNA_P_DISALLOWED },
{ 0x2C2F, 0x2C2F, .p.property = IDNA_P_UNASSIGNED },
{ 0x2C30, 0x2C5E, .p.property = IDNA_P_PVALID },
@@ -1701,15 +1694,21 @@ idna_table idna_derived[] = {
{ 0x2CEC, 0x2CEC, .p.property = IDNA_P_PVALID },
{ 0x2CED, 0x2CED, .p.property = IDNA_P_DISALLOWED },
{ 0x2CEE, 0x2CF1, .p.property = IDNA_P_PVALID },
- { 0x2CF2, 0x2CF8, .p.property = IDNA_P_UNASSIGNED },
+ { 0x2CF2, 0x2CF2, .p.property = IDNA_P_DISALLOWED },
+ { 0x2CF3, 0x2CF3, .p.property = IDNA_P_PVALID },
+ { 0x2CF4, 0x2CF8, .p.property = IDNA_P_UNASSIGNED },
{ 0x2CF9, 0x2CFF, .p.property = IDNA_P_DISALLOWED },
{ 0x2D00, 0x2D25, .p.property = IDNA_P_PVALID },
- { 0x2D26, 0x2D2F, .p.property = IDNA_P_UNASSIGNED },
- { 0x2D30, 0x2D65, .p.property = IDNA_P_PVALID },
- { 0x2D66, 0x2D6E, .p.property = IDNA_P_UNASSIGNED },
- { 0x2D6F, 0x2D6F, .p.property = IDNA_P_DISALLOWED },
- { 0x2D70, 0x2D7F, .p.property = IDNA_P_UNASSIGNED },
- { 0x2D80, 0x2D96, .p.property = IDNA_P_PVALID },
+ { 0x2D26, 0x2D26, .p.property = IDNA_P_UNASSIGNED },
+ { 0x2D27, 0x2D27, .p.property = IDNA_P_PVALID },
+ { 0x2D28, 0x2D2C, .p.property = IDNA_P_UNASSIGNED },
+ { 0x2D2D, 0x2D2D, .p.property = IDNA_P_PVALID },
+ { 0x2D2E, 0x2D2F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x2D30, 0x2D67, .p.property = IDNA_P_PVALID },
+ { 0x2D68, 0x2D6E, .p.property = IDNA_P_UNASSIGNED },
+ { 0x2D6F, 0x2D70, .p.property = IDNA_P_DISALLOWED },
+ { 0x2D71, 0x2D7E, .p.property = IDNA_P_UNASSIGNED },
+ { 0x2D7F, 0x2D96, .p.property = IDNA_P_PVALID },
{ 0x2D97, 0x2D9F, .p.property = IDNA_P_UNASSIGNED },
{ 0x2DA0, 0x2DA6, .p.property = IDNA_P_PVALID },
{ 0x2DA7, 0x2DA7, .p.property = IDNA_P_UNASSIGNED },
@@ -1730,8 +1729,8 @@ idna_table idna_derived[] = {
{ 0x2DE0, 0x2DFF, .p.property = IDNA_P_PVALID },
{ 0x2E00, 0x2E2E, .p.property = IDNA_P_DISALLOWED },
{ 0x2E2F, 0x2E2F, .p.property = IDNA_P_PVALID },
- { 0x2E30, 0x2E31, .p.property = IDNA_P_DISALLOWED },
- { 0x2E32, 0x2E7F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x2E30, 0x2E4E, .p.property = IDNA_P_DISALLOWED },
+ { 0x2E4F, 0x2E7F, .p.property = IDNA_P_UNASSIGNED },
{ 0x2E80, 0x2E99, .p.property = IDNA_P_DISALLOWED },
{ 0x2E9A, 0x2E9A, .p.property = IDNA_P_UNASSIGNED },
{ 0x2E9B, 0x2EF3, .p.property = IDNA_P_DISALLOWED },
@@ -1759,13 +1758,13 @@ idna_table idna_derived[] = {
{ 0x30FC, 0x30FE, .p.property = IDNA_P_PVALID },
{ 0x30FF, 0x30FF, .p.property = IDNA_P_DISALLOWED },
{ 0x3100, 0x3104, .p.property = IDNA_P_UNASSIGNED },
- { 0x3105, 0x312D, .p.property = IDNA_P_PVALID },
- { 0x312E, 0x3130, .p.property = IDNA_P_UNASSIGNED },
+ { 0x3105, 0x312F, .p.property = IDNA_P_PVALID },
+ { 0x3130, 0x3130, .p.property = IDNA_P_UNASSIGNED },
{ 0x3131, 0x318E, .p.property = IDNA_P_DISALLOWED },
{ 0x318F, 0x318F, .p.property = IDNA_P_UNASSIGNED },
{ 0x3190, 0x319F, .p.property = IDNA_P_DISALLOWED },
- { 0x31A0, 0x31B7, .p.property = IDNA_P_PVALID },
- { 0x31B8, 0x31BF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x31A0, 0x31BA, .p.property = IDNA_P_PVALID },
+ { 0x31BB, 0x31BF, .p.property = IDNA_P_UNASSIGNED },
{ 0x31C0, 0x31E3, .p.property = IDNA_P_DISALLOWED },
{ 0x31E4, 0x31EF, .p.property = IDNA_P_UNASSIGNED },
{ 0x31F0, 0x31FF, .p.property = IDNA_P_PVALID },
@@ -1777,8 +1776,8 @@ idna_table idna_derived[] = {
{ 0x3400, 0x4DB5, .p.property = IDNA_P_PVALID },
{ 0x4DB6, 0x4DBF, .p.property = IDNA_P_UNASSIGNED },
{ 0x4DC0, 0x4DFF, .p.property = IDNA_P_DISALLOWED },
- { 0x4E00, 0x9FCB, .p.property = IDNA_P_PVALID },
- { 0x9FCC, 0x9FFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x4E00, 0x9FEF, .p.property = IDNA_P_PVALID },
+ { 0x9FF0, 0x9FFF, .p.property = IDNA_P_UNASSIGNED },
{ 0xA000, 0xA48C, .p.property = IDNA_P_PVALID },
{ 0xA48D, 0xA48F, .p.property = IDNA_P_UNASSIGNED },
{ 0xA490, 0xA4C6, .p.property = IDNA_P_DISALLOWED },
@@ -1821,7 +1820,8 @@ idna_table idna_derived[] = {
{ 0xA65D, 0xA65D, .p.property = IDNA_P_PVALID },
{ 0xA65E, 0xA65E, .p.property = IDNA_P_DISALLOWED },
{ 0xA65F, 0xA65F, .p.property = IDNA_P_PVALID },
- { 0xA660, 0xA661, .p.property = IDNA_P_UNASSIGNED },
+ { 0xA660, 0xA660, .p.property = IDNA_P_DISALLOWED },
+ { 0xA661, 0xA661, .p.property = IDNA_P_PVALID },
{ 0xA662, 0xA662, .p.property = IDNA_P_DISALLOWED },
{ 0xA663, 0xA663, .p.property = IDNA_P_PVALID },
{ 0xA664, 0xA664, .p.property = IDNA_P_DISALLOWED },
@@ -1835,8 +1835,7 @@ idna_table idna_derived[] = {
{ 0xA66C, 0xA66C, .p.property = IDNA_P_DISALLOWED },
{ 0xA66D, 0xA66F, .p.property = IDNA_P_PVALID },
{ 0xA670, 0xA673, .p.property = IDNA_P_DISALLOWED },
- { 0xA674, 0xA67B, .p.property = IDNA_P_UNASSIGNED },
- { 0xA67C, 0xA67D, .p.property = IDNA_P_PVALID },
+ { 0xA674, 0xA67D, .p.property = IDNA_P_PVALID },
{ 0xA67E, 0xA67E, .p.property = IDNA_P_DISALLOWED },
{ 0xA67F, 0xA67F, .p.property = IDNA_P_PVALID },
{ 0xA680, 0xA680, .p.property = IDNA_P_DISALLOWED },
@@ -1863,8 +1862,12 @@ idna_table idna_derived[] = {
{ 0xA695, 0xA695, .p.property = IDNA_P_PVALID },
{ 0xA696, 0xA696, .p.property = IDNA_P_DISALLOWED },
{ 0xA697, 0xA697, .p.property = IDNA_P_PVALID },
- { 0xA698, 0xA69F, .p.property = IDNA_P_UNASSIGNED },
- { 0xA6A0, 0xA6E5, .p.property = IDNA_P_PVALID },
+ { 0xA698, 0xA698, .p.property = IDNA_P_DISALLOWED },
+ { 0xA699, 0xA699, .p.property = IDNA_P_PVALID },
+ { 0xA69A, 0xA69A, .p.property = IDNA_P_DISALLOWED },
+ { 0xA69B, 0xA69B, .p.property = IDNA_P_PVALID },
+ { 0xA69C, 0xA69D, .p.property = IDNA_P_DISALLOWED },
+ { 0xA69E, 0xA6E5, .p.property = IDNA_P_PVALID },
{ 0xA6E6, 0xA6EF, .p.property = IDNA_P_DISALLOWED },
{ 0xA6F0, 0xA6F1, .p.property = IDNA_P_PVALID },
{ 0xA6F2, 0xA6F7, .p.property = IDNA_P_DISALLOWED },
@@ -1965,8 +1968,44 @@ idna_table idna_derived[] = {
{ 0xA787, 0xA788, .p.property = IDNA_P_PVALID },
{ 0xA789, 0xA78B, .p.property = IDNA_P_DISALLOWED },
{ 0xA78C, 0xA78C, .p.property = IDNA_P_PVALID },
- { 0xA78D, 0xA7FA, .p.property = IDNA_P_UNASSIGNED },
- { 0xA7FB, 0xA827, .p.property = IDNA_P_PVALID },
+ { 0xA78D, 0xA78D, .p.property = IDNA_P_DISALLOWED },
+ { 0xA78E, 0xA78F, .p.property = IDNA_P_PVALID },
+ { 0xA790, 0xA790, .p.property = IDNA_P_DISALLOWED },
+ { 0xA791, 0xA791, .p.property = IDNA_P_PVALID },
+ { 0xA792, 0xA792, .p.property = IDNA_P_DISALLOWED },
+ { 0xA793, 0xA795, .p.property = IDNA_P_PVALID },
+ { 0xA796, 0xA796, .p.property = IDNA_P_DISALLOWED },
+ { 0xA797, 0xA797, .p.property = IDNA_P_PVALID },
+ { 0xA798, 0xA798, .p.property = IDNA_P_DISALLOWED },
+ { 0xA799, 0xA799, .p.property = IDNA_P_PVALID },
+ { 0xA79A, 0xA79A, .p.property = IDNA_P_DISALLOWED },
+ { 0xA79B, 0xA79B, .p.property = IDNA_P_PVALID },
+ { 0xA79C, 0xA79C, .p.property = IDNA_P_DISALLOWED },
+ { 0xA79D, 0xA79D, .p.property = IDNA_P_PVALID },
+ { 0xA79E, 0xA79E, .p.property = IDNA_P_DISALLOWED },
+ { 0xA79F, 0xA79F, .p.property = IDNA_P_PVALID },
+ { 0xA7A0, 0xA7A0, .p.property = IDNA_P_DISALLOWED },
+ { 0xA7A1, 0xA7A1, .p.property = IDNA_P_PVALID },
+ { 0xA7A2, 0xA7A2, .p.property = IDNA_P_DISALLOWED },
+ { 0xA7A3, 0xA7A3, .p.property = IDNA_P_PVALID },
+ { 0xA7A4, 0xA7A4, .p.property = IDNA_P_DISALLOWED },
+ { 0xA7A5, 0xA7A5, .p.property = IDNA_P_PVALID },
+ { 0xA7A6, 0xA7A6, .p.property = IDNA_P_DISALLOWED },
+ { 0xA7A7, 0xA7A7, .p.property = IDNA_P_PVALID },
+ { 0xA7A8, 0xA7A8, .p.property = IDNA_P_DISALLOWED },
+ { 0xA7A9, 0xA7A9, .p.property = IDNA_P_PVALID },
+ { 0xA7AA, 0xA7AE, .p.property = IDNA_P_DISALLOWED },
+ { 0xA7AF, 0xA7AF, .p.property = IDNA_P_PVALID },
+ { 0xA7B0, 0xA7B4, .p.property = IDNA_P_DISALLOWED },
+ { 0xA7B5, 0xA7B5, .p.property = IDNA_P_PVALID },
+ { 0xA7B6, 0xA7B6, .p.property = IDNA_P_DISALLOWED },
+ { 0xA7B7, 0xA7B7, .p.property = IDNA_P_PVALID },
+ { 0xA7B8, 0xA7B8, .p.property = IDNA_P_DISALLOWED },
+ { 0xA7B9, 0xA7B9, .p.property = IDNA_P_PVALID },
+ { 0xA7BA, 0xA7F6, .p.property = IDNA_P_UNASSIGNED },
+ { 0xA7F7, 0xA7F7, .p.property = IDNA_P_PVALID },
+ { 0xA7F8, 0xA7F9, .p.property = IDNA_P_DISALLOWED },
+ { 0xA7FA, 0xA827, .p.property = IDNA_P_PVALID },
{ 0xA828, 0xA82B, .p.property = IDNA_P_DISALLOWED },
{ 0xA82C, 0xA82F, .p.property = IDNA_P_UNASSIGNED },
{ 0xA830, 0xA839, .p.property = IDNA_P_DISALLOWED },
@@ -1974,16 +2013,16 @@ idna_table idna_derived[] = {
{ 0xA840, 0xA873, .p.property = IDNA_P_PVALID },
{ 0xA874, 0xA877, .p.property = IDNA_P_DISALLOWED },
{ 0xA878, 0xA87F, .p.property = IDNA_P_UNASSIGNED },
- { 0xA880, 0xA8C4, .p.property = IDNA_P_PVALID },
- { 0xA8C5, 0xA8CD, .p.property = IDNA_P_UNASSIGNED },
+ { 0xA880, 0xA8C5, .p.property = IDNA_P_PVALID },
+ { 0xA8C6, 0xA8CD, .p.property = IDNA_P_UNASSIGNED },
{ 0xA8CE, 0xA8CF, .p.property = IDNA_P_DISALLOWED },
{ 0xA8D0, 0xA8D9, .p.property = IDNA_P_PVALID },
{ 0xA8DA, 0xA8DF, .p.property = IDNA_P_UNASSIGNED },
{ 0xA8E0, 0xA8F7, .p.property = IDNA_P_PVALID },
{ 0xA8F8, 0xA8FA, .p.property = IDNA_P_DISALLOWED },
{ 0xA8FB, 0xA8FB, .p.property = IDNA_P_PVALID },
- { 0xA8FC, 0xA8FF, .p.property = IDNA_P_UNASSIGNED },
- { 0xA900, 0xA92D, .p.property = IDNA_P_PVALID },
+ { 0xA8FC, 0xA8FC, .p.property = IDNA_P_DISALLOWED },
+ { 0xA8FD, 0xA92D, .p.property = IDNA_P_PVALID },
{ 0xA92E, 0xA92F, .p.property = IDNA_P_DISALLOWED },
{ 0xA930, 0xA953, .p.property = IDNA_P_PVALID },
{ 0xA954, 0xA95E, .p.property = IDNA_P_UNASSIGNED },
@@ -1995,7 +2034,8 @@ idna_table idna_derived[] = {
{ 0xA9CF, 0xA9D9, .p.property = IDNA_P_PVALID },
{ 0xA9DA, 0xA9DD, .p.property = IDNA_P_UNASSIGNED },
{ 0xA9DE, 0xA9DF, .p.property = IDNA_P_DISALLOWED },
- { 0xA9E0, 0xA9FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0xA9E0, 0xA9FE, .p.property = IDNA_P_PVALID },
+ { 0xA9FF, 0xA9FF, .p.property = IDNA_P_UNASSIGNED },
{ 0xAA00, 0xAA36, .p.property = IDNA_P_PVALID },
{ 0xAA37, 0xAA3F, .p.property = IDNA_P_UNASSIGNED },
{ 0xAA40, 0xAA4D, .p.property = IDNA_P_PVALID },
@@ -2005,13 +2045,29 @@ idna_table idna_derived[] = {
{ 0xAA5C, 0xAA5F, .p.property = IDNA_P_DISALLOWED },
{ 0xAA60, 0xAA76, .p.property = IDNA_P_PVALID },
{ 0xAA77, 0xAA79, .p.property = IDNA_P_DISALLOWED },
- { 0xAA7A, 0xAA7B, .p.property = IDNA_P_PVALID },
- { 0xAA7C, 0xAA7F, .p.property = IDNA_P_UNASSIGNED },
- { 0xAA80, 0xAAC2, .p.property = IDNA_P_PVALID },
+ { 0xAA7A, 0xAAC2, .p.property = IDNA_P_PVALID },
{ 0xAAC3, 0xAADA, .p.property = IDNA_P_UNASSIGNED },
{ 0xAADB, 0xAADD, .p.property = IDNA_P_PVALID },
{ 0xAADE, 0xAADF, .p.property = IDNA_P_DISALLOWED },
- { 0xAAE0, 0xABBF, .p.property = IDNA_P_UNASSIGNED },
+ { 0xAAE0, 0xAAEF, .p.property = IDNA_P_PVALID },
+ { 0xAAF0, 0xAAF1, .p.property = IDNA_P_DISALLOWED },
+ { 0xAAF2, 0xAAF6, .p.property = IDNA_P_PVALID },
+ { 0xAAF7, 0xAB00, .p.property = IDNA_P_UNASSIGNED },
+ { 0xAB01, 0xAB06, .p.property = IDNA_P_PVALID },
+ { 0xAB07, 0xAB08, .p.property = IDNA_P_UNASSIGNED },
+ { 0xAB09, 0xAB0E, .p.property = IDNA_P_PVALID },
+ { 0xAB0F, 0xAB10, .p.property = IDNA_P_UNASSIGNED },
+ { 0xAB11, 0xAB16, .p.property = IDNA_P_PVALID },
+ { 0xAB17, 0xAB1F, .p.property = IDNA_P_UNASSIGNED },
+ { 0xAB20, 0xAB26, .p.property = IDNA_P_PVALID },
+ { 0xAB27, 0xAB27, .p.property = IDNA_P_UNASSIGNED },
+ { 0xAB28, 0xAB2E, .p.property = IDNA_P_PVALID },
+ { 0xAB2F, 0xAB2F, .p.property = IDNA_P_UNASSIGNED },
+ { 0xAB30, 0xAB5A, .p.property = IDNA_P_PVALID },
+ { 0xAB5B, 0xAB5F, .p.property = IDNA_P_DISALLOWED },
+ { 0xAB60, 0xAB65, .p.property = IDNA_P_PVALID },
+ { 0xAB66, 0xAB6F, .p.property = IDNA_P_UNASSIGNED },
+ { 0xAB70, 0xABBF, .p.property = IDNA_P_DISALLOWED },
{ 0xABC0, 0xABEA, .p.property = IDNA_P_PVALID },
{ 0xABEB, 0xABEB, .p.property = IDNA_P_DISALLOWED },
{ 0xABEC, 0xABED, .p.property = IDNA_P_PVALID },
@@ -2038,9 +2094,7 @@ idna_table idna_derived[] = {
{ 0xFA23, 0xFA24, .p.property = IDNA_P_PVALID },
{ 0xFA25, 0xFA26, .p.property = IDNA_P_DISALLOWED },
{ 0xFA27, 0xFA29, .p.property = IDNA_P_PVALID },
- { 0xFA2A, 0xFA2D, .p.property = IDNA_P_DISALLOWED },
- { 0xFA2E, 0xFA2F, .p.property = IDNA_P_UNASSIGNED },
- { 0xFA30, 0xFA6D, .p.property = IDNA_P_DISALLOWED },
+ { 0xFA2A, 0xFA6D, .p.property = IDNA_P_DISALLOWED },
{ 0xFA6E, 0xFA6F, .p.property = IDNA_P_UNASSIGNED },
{ 0xFA70, 0xFAD9, .p.property = IDNA_P_DISALLOWED },
{ 0xFADA, 0xFAFF, .p.property = IDNA_P_UNASSIGNED },
@@ -2060,8 +2114,8 @@ idna_table idna_derived[] = {
{ 0xFB42, 0xFB42, .p.property = IDNA_P_UNASSIGNED },
{ 0xFB43, 0xFB44, .p.property = IDNA_P_DISALLOWED },
{ 0xFB45, 0xFB45, .p.property = IDNA_P_UNASSIGNED },
- { 0xFB46, 0xFBB1, .p.property = IDNA_P_DISALLOWED },
- { 0xFBB2, 0xFBD2, .p.property = IDNA_P_UNASSIGNED },
+ { 0xFB46, 0xFBC1, .p.property = IDNA_P_DISALLOWED },
+ { 0xFBC2, 0xFBD2, .p.property = IDNA_P_UNASSIGNED },
{ 0xFBD3, 0xFD3F, .p.property = IDNA_P_DISALLOWED },
{ 0xFD40, 0xFD4F, .p.property = IDNA_P_UNASSIGNED },
{ 0xFD50, 0xFD8F, .p.property = IDNA_P_DISALLOWED },
@@ -2072,8 +2126,7 @@ idna_table idna_derived[] = {
{ 0xFDFE, 0xFDFF, .p.property = IDNA_P_UNASSIGNED },
{ 0xFE00, 0xFE19, .p.property = IDNA_P_DISALLOWED },
{ 0xFE1A, 0xFE1F, .p.property = IDNA_P_UNASSIGNED },
- { 0xFE20, 0xFE26, .p.property = IDNA_P_PVALID },
- { 0xFE27, 0xFE2F, .p.property = IDNA_P_UNASSIGNED },
+ { 0xFE20, 0xFE2F, .p.property = IDNA_P_PVALID },
{ 0xFE30, 0xFE52, .p.property = IDNA_P_DISALLOWED },
{ 0xFE53, 0xFE53, .p.property = IDNA_P_UNASSIGNED },
{ 0xFE54, 0xFE66, .p.property = IDNA_P_DISALLOWED },
@@ -2121,26 +2174,32 @@ idna_table idna_derived[] = {
{ 0x10103, 0x10106, .p.property = IDNA_P_UNASSIGNED },
{ 0x10107, 0x10133, .p.property = IDNA_P_DISALLOWED },
{ 0x10134, 0x10136, .p.property = IDNA_P_UNASSIGNED },
- { 0x10137, 0x1018A, .p.property = IDNA_P_DISALLOWED },
- { 0x1018B, 0x1018F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10137, 0x1018E, .p.property = IDNA_P_DISALLOWED },
+ { 0x1018F, 0x1018F, .p.property = IDNA_P_UNASSIGNED },
{ 0x10190, 0x1019B, .p.property = IDNA_P_DISALLOWED },
- { 0x1019C, 0x101CF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1019C, 0x1019F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x101A0, 0x101A0, .p.property = IDNA_P_DISALLOWED },
+ { 0x101A1, 0x101CF, .p.property = IDNA_P_UNASSIGNED },
{ 0x101D0, 0x101FC, .p.property = IDNA_P_DISALLOWED },
{ 0x101FD, 0x101FD, .p.property = IDNA_P_PVALID },
{ 0x101FE, 0x1027F, .p.property = IDNA_P_UNASSIGNED },
{ 0x10280, 0x1029C, .p.property = IDNA_P_PVALID },
{ 0x1029D, 0x1029F, .p.property = IDNA_P_UNASSIGNED },
{ 0x102A0, 0x102D0, .p.property = IDNA_P_PVALID },
- { 0x102D1, 0x102FF, .p.property = IDNA_P_UNASSIGNED },
- { 0x10300, 0x1031E, .p.property = IDNA_P_PVALID },
- { 0x1031F, 0x1031F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x102D1, 0x102DF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x102E0, 0x102E0, .p.property = IDNA_P_PVALID },
+ { 0x102E1, 0x102FB, .p.property = IDNA_P_DISALLOWED },
+ { 0x102FC, 0x102FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10300, 0x1031F, .p.property = IDNA_P_PVALID },
{ 0x10320, 0x10323, .p.property = IDNA_P_DISALLOWED },
- { 0x10324, 0x1032F, .p.property = IDNA_P_UNASSIGNED },
- { 0x10330, 0x10340, .p.property = IDNA_P_PVALID },
+ { 0x10324, 0x1032C, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1032D, 0x10340, .p.property = IDNA_P_PVALID },
{ 0x10341, 0x10341, .p.property = IDNA_P_DISALLOWED },
{ 0x10342, 0x10349, .p.property = IDNA_P_PVALID },
{ 0x1034A, 0x1034A, .p.property = IDNA_P_DISALLOWED },
- { 0x1034B, 0x1037F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1034B, 0x1034F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10350, 0x1037A, .p.property = IDNA_P_PVALID },
+ { 0x1037B, 0x1037F, .p.property = IDNA_P_UNASSIGNED },
{ 0x10380, 0x1039D, .p.property = IDNA_P_PVALID },
{ 0x1039E, 0x1039E, .p.property = IDNA_P_UNASSIGNED },
{ 0x1039F, 0x1039F, .p.property = IDNA_P_DISALLOWED },
@@ -2153,7 +2212,23 @@ idna_table idna_derived[] = {
{ 0x10428, 0x1049D, .p.property = IDNA_P_PVALID },
{ 0x1049E, 0x1049F, .p.property = IDNA_P_UNASSIGNED },
{ 0x104A0, 0x104A9, .p.property = IDNA_P_PVALID },
- { 0x104AA, 0x107FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x104AA, 0x104AF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x104B0, 0x104D3, .p.property = IDNA_P_DISALLOWED },
+ { 0x104D4, 0x104D7, .p.property = IDNA_P_UNASSIGNED },
+ { 0x104D8, 0x104FB, .p.property = IDNA_P_PVALID },
+ { 0x104FC, 0x104FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10500, 0x10527, .p.property = IDNA_P_PVALID },
+ { 0x10528, 0x1052F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10530, 0x10563, .p.property = IDNA_P_PVALID },
+ { 0x10564, 0x1056E, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1056F, 0x1056F, .p.property = IDNA_P_DISALLOWED },
+ { 0x10570, 0x105FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10600, 0x10736, .p.property = IDNA_P_PVALID },
+ { 0x10737, 0x1073F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10740, 0x10755, .p.property = IDNA_P_PVALID },
+ { 0x10756, 0x1075F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10760, 0x10767, .p.property = IDNA_P_PVALID },
+ { 0x10768, 0x107FF, .p.property = IDNA_P_UNASSIGNED },
{ 0x10800, 0x10805, .p.property = IDNA_P_PVALID },
{ 0x10806, 0x10807, .p.property = IDNA_P_UNASSIGNED },
{ 0x10808, 0x10808, .p.property = IDNA_P_PVALID },
@@ -2167,7 +2242,17 @@ idna_table idna_derived[] = {
{ 0x1083F, 0x10855, .p.property = IDNA_P_PVALID },
{ 0x10856, 0x10856, .p.property = IDNA_P_UNASSIGNED },
{ 0x10857, 0x1085F, .p.property = IDNA_P_DISALLOWED },
- { 0x10860, 0x108FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10860, 0x10876, .p.property = IDNA_P_PVALID },
+ { 0x10877, 0x1087F, .p.property = IDNA_P_DISALLOWED },
+ { 0x10880, 0x1089E, .p.property = IDNA_P_PVALID },
+ { 0x1089F, 0x108A6, .p.property = IDNA_P_UNASSIGNED },
+ { 0x108A7, 0x108AF, .p.property = IDNA_P_DISALLOWED },
+ { 0x108B0, 0x108DF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x108E0, 0x108F2, .p.property = IDNA_P_PVALID },
+ { 0x108F3, 0x108F3, .p.property = IDNA_P_UNASSIGNED },
+ { 0x108F4, 0x108F5, .p.property = IDNA_P_PVALID },
+ { 0x108F6, 0x108FA, .p.property = IDNA_P_UNASSIGNED },
+ { 0x108FB, 0x108FF, .p.property = IDNA_P_DISALLOWED },
{ 0x10900, 0x10915, .p.property = IDNA_P_PVALID },
{ 0x10916, 0x1091B, .p.property = IDNA_P_DISALLOWED },
{ 0x1091C, 0x1091E, .p.property = IDNA_P_UNASSIGNED },
@@ -2175,7 +2260,14 @@ idna_table idna_derived[] = {
{ 0x10920, 0x10939, .p.property = IDNA_P_PVALID },
{ 0x1093A, 0x1093E, .p.property = IDNA_P_UNASSIGNED },
{ 0x1093F, 0x1093F, .p.property = IDNA_P_DISALLOWED },
- { 0x10940, 0x109FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10940, 0x1097F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10980, 0x109B7, .p.property = IDNA_P_PVALID },
+ { 0x109B8, 0x109BB, .p.property = IDNA_P_UNASSIGNED },
+ { 0x109BC, 0x109BD, .p.property = IDNA_P_DISALLOWED },
+ { 0x109BE, 0x109BF, .p.property = IDNA_P_PVALID },
+ { 0x109C0, 0x109CF, .p.property = IDNA_P_DISALLOWED },
+ { 0x109D0, 0x109D1, .p.property = IDNA_P_UNASSIGNED },
+ { 0x109D2, 0x109FF, .p.property = IDNA_P_DISALLOWED },
{ 0x10A00, 0x10A03, .p.property = IDNA_P_PVALID },
{ 0x10A04, 0x10A04, .p.property = IDNA_P_UNASSIGNED },
{ 0x10A05, 0x10A06, .p.property = IDNA_P_PVALID },
@@ -2184,18 +2276,26 @@ idna_table idna_derived[] = {
{ 0x10A14, 0x10A14, .p.property = IDNA_P_UNASSIGNED },
{ 0x10A15, 0x10A17, .p.property = IDNA_P_PVALID },
{ 0x10A18, 0x10A18, .p.property = IDNA_P_UNASSIGNED },
- { 0x10A19, 0x10A33, .p.property = IDNA_P_PVALID },
- { 0x10A34, 0x10A37, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10A19, 0x10A35, .p.property = IDNA_P_PVALID },
+ { 0x10A36, 0x10A37, .p.property = IDNA_P_UNASSIGNED },
{ 0x10A38, 0x10A3A, .p.property = IDNA_P_PVALID },
{ 0x10A3B, 0x10A3E, .p.property = IDNA_P_UNASSIGNED },
{ 0x10A3F, 0x10A3F, .p.property = IDNA_P_PVALID },
- { 0x10A40, 0x10A47, .p.property = IDNA_P_DISALLOWED },
- { 0x10A48, 0x10A4F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10A40, 0x10A48, .p.property = IDNA_P_DISALLOWED },
+ { 0x10A49, 0x10A4F, .p.property = IDNA_P_UNASSIGNED },
{ 0x10A50, 0x10A58, .p.property = IDNA_P_DISALLOWED },
{ 0x10A59, 0x10A5F, .p.property = IDNA_P_UNASSIGNED },
{ 0x10A60, 0x10A7C, .p.property = IDNA_P_PVALID },
{ 0x10A7D, 0x10A7F, .p.property = IDNA_P_DISALLOWED },
- { 0x10A80, 0x10AFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10A80, 0x10A9C, .p.property = IDNA_P_PVALID },
+ { 0x10A9D, 0x10A9F, .p.property = IDNA_P_DISALLOWED },
+ { 0x10AA0, 0x10ABF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10AC0, 0x10AC7, .p.property = IDNA_P_PVALID },
+ { 0x10AC8, 0x10AC8, .p.property = IDNA_P_DISALLOWED },
+ { 0x10AC9, 0x10AE6, .p.property = IDNA_P_PVALID },
+ { 0x10AE7, 0x10AEA, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10AEB, 0x10AF6, .p.property = IDNA_P_DISALLOWED },
+ { 0x10AF7, 0x10AFF, .p.property = IDNA_P_UNASSIGNED },
{ 0x10B00, 0x10B35, .p.property = IDNA_P_PVALID },
{ 0x10B36, 0x10B38, .p.property = IDNA_P_UNASSIGNED },
{ 0x10B39, 0x10B3F, .p.property = IDNA_P_DISALLOWED },
@@ -2205,34 +2305,312 @@ idna_table idna_derived[] = {
{ 0x10B60, 0x10B72, .p.property = IDNA_P_PVALID },
{ 0x10B73, 0x10B77, .p.property = IDNA_P_UNASSIGNED },
{ 0x10B78, 0x10B7F, .p.property = IDNA_P_DISALLOWED },
- { 0x10B80, 0x10BFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10B80, 0x10B91, .p.property = IDNA_P_PVALID },
+ { 0x10B92, 0x10B98, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10B99, 0x10B9C, .p.property = IDNA_P_DISALLOWED },
+ { 0x10B9D, 0x10BA8, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10BA9, 0x10BAF, .p.property = IDNA_P_DISALLOWED },
+ { 0x10BB0, 0x10BFF, .p.property = IDNA_P_UNASSIGNED },
{ 0x10C00, 0x10C48, .p.property = IDNA_P_PVALID },
- { 0x10C49, 0x10E5F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10C49, 0x10C7F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10C80, 0x10CB2, .p.property = IDNA_P_DISALLOWED },
+ { 0x10CB3, 0x10CBF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10CC0, 0x10CF2, .p.property = IDNA_P_PVALID },
+ { 0x10CF3, 0x10CF9, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10CFA, 0x10CFF, .p.property = IDNA_P_DISALLOWED },
+ { 0x10D00, 0x10D27, .p.property = IDNA_P_PVALID },
+ { 0x10D28, 0x10D2F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10D30, 0x10D39, .p.property = IDNA_P_PVALID },
+ { 0x10D3A, 0x10E5F, .p.property = IDNA_P_UNASSIGNED },
{ 0x10E60, 0x10E7E, .p.property = IDNA_P_DISALLOWED },
- { 0x10E7F, 0x1107F, .p.property = IDNA_P_UNASSIGNED },
- { 0x11080, 0x110BA, .p.property = IDNA_P_PVALID },
+ { 0x10E7F, 0x10EFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10F00, 0x10F1C, .p.property = IDNA_P_PVALID },
+ { 0x10F1D, 0x10F26, .p.property = IDNA_P_DISALLOWED },
+ { 0x10F27, 0x10F27, .p.property = IDNA_P_PVALID },
+ { 0x10F28, 0x10F2F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x10F30, 0x10F50, .p.property = IDNA_P_PVALID },
+ { 0x10F51, 0x10F59, .p.property = IDNA_P_DISALLOWED },
+ { 0x10F5A, 0x10FFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11000, 0x11046, .p.property = IDNA_P_PVALID },
+ { 0x11047, 0x1104D, .p.property = IDNA_P_DISALLOWED },
+ { 0x1104E, 0x11051, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11052, 0x11065, .p.property = IDNA_P_DISALLOWED },
+ { 0x11066, 0x1106F, .p.property = IDNA_P_PVALID },
+ { 0x11070, 0x1107E, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1107F, 0x110BA, .p.property = IDNA_P_PVALID },
{ 0x110BB, 0x110C1, .p.property = IDNA_P_DISALLOWED },
- { 0x110C2, 0x11FFF, .p.property = IDNA_P_UNASSIGNED },
- { 0x12000, 0x1236E, .p.property = IDNA_P_PVALID },
- { 0x1236F, 0x123FF, .p.property = IDNA_P_UNASSIGNED },
- { 0x12400, 0x12462, .p.property = IDNA_P_DISALLOWED },
- { 0x12463, 0x1246F, .p.property = IDNA_P_UNASSIGNED },
- { 0x12470, 0x12473, .p.property = IDNA_P_DISALLOWED },
- { 0x12474, 0x12FFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x110C2, 0x110CC, .p.property = IDNA_P_UNASSIGNED },
+ { 0x110CD, 0x110CD, .p.property = IDNA_P_DISALLOWED },
+ { 0x110CE, 0x110CF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x110D0, 0x110E8, .p.property = IDNA_P_PVALID },
+ { 0x110E9, 0x110EF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x110F0, 0x110F9, .p.property = IDNA_P_PVALID },
+ { 0x110FA, 0x110FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11100, 0x11134, .p.property = IDNA_P_PVALID },
+ { 0x11135, 0x11135, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11136, 0x1113F, .p.property = IDNA_P_PVALID },
+ { 0x11140, 0x11143, .p.property = IDNA_P_DISALLOWED },
+ { 0x11144, 0x11146, .p.property = IDNA_P_PVALID },
+ { 0x11147, 0x1114F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11150, 0x11173, .p.property = IDNA_P_PVALID },
+ { 0x11174, 0x11175, .p.property = IDNA_P_DISALLOWED },
+ { 0x11176, 0x11176, .p.property = IDNA_P_PVALID },
+ { 0x11177, 0x1117F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11180, 0x111C4, .p.property = IDNA_P_PVALID },
+ { 0x111C5, 0x111C8, .p.property = IDNA_P_DISALLOWED },
+ { 0x111C9, 0x111CC, .p.property = IDNA_P_PVALID },
+ { 0x111CD, 0x111CD, .p.property = IDNA_P_DISALLOWED },
+ { 0x111CE, 0x111CF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x111D0, 0x111DA, .p.property = IDNA_P_PVALID },
+ { 0x111DB, 0x111DB, .p.property = IDNA_P_DISALLOWED },
+ { 0x111DC, 0x111DC, .p.property = IDNA_P_PVALID },
+ { 0x111DD, 0x111DF, .p.property = IDNA_P_DISALLOWED },
+ { 0x111E0, 0x111E0, .p.property = IDNA_P_UNASSIGNED },
+ { 0x111E1, 0x111F4, .p.property = IDNA_P_DISALLOWED },
+ { 0x111F5, 0x111FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11200, 0x11211, .p.property = IDNA_P_PVALID },
+ { 0x11212, 0x11212, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11213, 0x11237, .p.property = IDNA_P_PVALID },
+ { 0x11238, 0x1123D, .p.property = IDNA_P_DISALLOWED },
+ { 0x1123E, 0x1123E, .p.property = IDNA_P_PVALID },
+ { 0x1123F, 0x1127F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11280, 0x11286, .p.property = IDNA_P_PVALID },
+ { 0x11287, 0x11287, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11288, 0x11288, .p.property = IDNA_P_PVALID },
+ { 0x11289, 0x11289, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1128A, 0x1128D, .p.property = IDNA_P_PVALID },
+ { 0x1128E, 0x1128E, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1128F, 0x1129D, .p.property = IDNA_P_PVALID },
+ { 0x1129E, 0x1129E, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1129F, 0x112A8, .p.property = IDNA_P_PVALID },
+ { 0x112A9, 0x112A9, .p.property = IDNA_P_DISALLOWED },
+ { 0x112AA, 0x112AF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x112B0, 0x112EA, .p.property = IDNA_P_PVALID },
+ { 0x112EB, 0x112EF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x112F0, 0x112F9, .p.property = IDNA_P_PVALID },
+ { 0x112FA, 0x112FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11300, 0x11303, .p.property = IDNA_P_PVALID },
+ { 0x11304, 0x11304, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11305, 0x1130C, .p.property = IDNA_P_PVALID },
+ { 0x1130D, 0x1130E, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1130F, 0x11310, .p.property = IDNA_P_PVALID },
+ { 0x11311, 0x11312, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11313, 0x11328, .p.property = IDNA_P_PVALID },
+ { 0x11329, 0x11329, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1132A, 0x11330, .p.property = IDNA_P_PVALID },
+ { 0x11331, 0x11331, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11332, 0x11333, .p.property = IDNA_P_PVALID },
+ { 0x11334, 0x11334, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11335, 0x11339, .p.property = IDNA_P_PVALID },
+ { 0x1133A, 0x1133A, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1133B, 0x11344, .p.property = IDNA_P_PVALID },
+ { 0x11345, 0x11346, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11347, 0x11348, .p.property = IDNA_P_PVALID },
+ { 0x11349, 0x1134A, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1134B, 0x1134D, .p.property = IDNA_P_PVALID },
+ { 0x1134E, 0x1134F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11350, 0x11350, .p.property = IDNA_P_PVALID },
+ { 0x11351, 0x11356, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11357, 0x11357, .p.property = IDNA_P_PVALID },
+ { 0x11358, 0x1135C, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1135D, 0x11363, .p.property = IDNA_P_PVALID },
+ { 0x11364, 0x11365, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11366, 0x1136C, .p.property = IDNA_P_PVALID },
+ { 0x1136D, 0x1136F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11370, 0x11374, .p.property = IDNA_P_PVALID },
+ { 0x11375, 0x113FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11400, 0x1144A, .p.property = IDNA_P_PVALID },
+ { 0x1144B, 0x1144F, .p.property = IDNA_P_DISALLOWED },
+ { 0x11450, 0x11459, .p.property = IDNA_P_PVALID },
+ { 0x1145A, 0x1145A, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1145B, 0x1145B, .p.property = IDNA_P_DISALLOWED },
+ { 0x1145C, 0x1145C, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1145D, 0x1145D, .p.property = IDNA_P_DISALLOWED },
+ { 0x1145E, 0x1145E, .p.property = IDNA_P_PVALID },
+ { 0x1145F, 0x1147F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11480, 0x114C5, .p.property = IDNA_P_PVALID },
+ { 0x114C6, 0x114C6, .p.property = IDNA_P_DISALLOWED },
+ { 0x114C7, 0x114C7, .p.property = IDNA_P_PVALID },
+ { 0x114C8, 0x114CF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x114D0, 0x114D9, .p.property = IDNA_P_PVALID },
+ { 0x114DA, 0x1157F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11580, 0x115B5, .p.property = IDNA_P_PVALID },
+ { 0x115B6, 0x115B7, .p.property = IDNA_P_UNASSIGNED },
+ { 0x115B8, 0x115C0, .p.property = IDNA_P_PVALID },
+ { 0x115C1, 0x115D7, .p.property = IDNA_P_DISALLOWED },
+ { 0x115D8, 0x115DD, .p.property = IDNA_P_PVALID },
+ { 0x115DE, 0x115FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11600, 0x11640, .p.property = IDNA_P_PVALID },
+ { 0x11641, 0x11643, .p.property = IDNA_P_DISALLOWED },
+ { 0x11644, 0x11644, .p.property = IDNA_P_PVALID },
+ { 0x11645, 0x1164F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11650, 0x11659, .p.property = IDNA_P_PVALID },
+ { 0x1165A, 0x1165F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11660, 0x1166C, .p.property = IDNA_P_DISALLOWED },
+ { 0x1166D, 0x1167F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11680, 0x116B7, .p.property = IDNA_P_PVALID },
+ { 0x116B8, 0x116BF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x116C0, 0x116C9, .p.property = IDNA_P_PVALID },
+ { 0x116CA, 0x116FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11700, 0x1171A, .p.property = IDNA_P_PVALID },
+ { 0x1171B, 0x1171C, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1171D, 0x1172B, .p.property = IDNA_P_PVALID },
+ { 0x1172C, 0x1172F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11730, 0x11739, .p.property = IDNA_P_PVALID },
+ { 0x1173A, 0x1173F, .p.property = IDNA_P_DISALLOWED },
+ { 0x11740, 0x117FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11800, 0x1183A, .p.property = IDNA_P_PVALID },
+ { 0x1183B, 0x1183B, .p.property = IDNA_P_DISALLOWED },
+ { 0x1183C, 0x1189F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x118A0, 0x118BF, .p.property = IDNA_P_DISALLOWED },
+ { 0x118C0, 0x118E9, .p.property = IDNA_P_PVALID },
+ { 0x118EA, 0x118F2, .p.property = IDNA_P_DISALLOWED },
+ { 0x118F3, 0x118FE, .p.property = IDNA_P_UNASSIGNED },
+ { 0x118FF, 0x118FF, .p.property = IDNA_P_PVALID },
+ { 0x11900, 0x119FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11A00, 0x11A3E, .p.property = IDNA_P_PVALID },
+ { 0x11A3F, 0x11A46, .p.property = IDNA_P_DISALLOWED },
+ { 0x11A47, 0x11A47, .p.property = IDNA_P_PVALID },
+ { 0x11A48, 0x11A4F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11A50, 0x11A83, .p.property = IDNA_P_PVALID },
+ { 0x11A84, 0x11A85, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11A86, 0x11A99, .p.property = IDNA_P_PVALID },
+ { 0x11A9A, 0x11A9C, .p.property = IDNA_P_DISALLOWED },
+ { 0x11A9D, 0x11A9D, .p.property = IDNA_P_PVALID },
+ { 0x11A9E, 0x11AA2, .p.property = IDNA_P_DISALLOWED },
+ { 0x11AA3, 0x11ABF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11AC0, 0x11AF8, .p.property = IDNA_P_PVALID },
+ { 0x11AF9, 0x11BFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11C00, 0x11C08, .p.property = IDNA_P_PVALID },
+ { 0x11C09, 0x11C09, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11C0A, 0x11C36, .p.property = IDNA_P_PVALID },
+ { 0x11C37, 0x11C37, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11C38, 0x11C40, .p.property = IDNA_P_PVALID },
+ { 0x11C41, 0x11C45, .p.property = IDNA_P_DISALLOWED },
+ { 0x11C46, 0x11C4F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11C50, 0x11C59, .p.property = IDNA_P_PVALID },
+ { 0x11C5A, 0x11C6C, .p.property = IDNA_P_DISALLOWED },
+ { 0x11C6D, 0x11C6F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11C70, 0x11C71, .p.property = IDNA_P_DISALLOWED },
+ { 0x11C72, 0x11C8F, .p.property = IDNA_P_PVALID },
+ { 0x11C90, 0x11C91, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11C92, 0x11CA7, .p.property = IDNA_P_PVALID },
+ { 0x11CA8, 0x11CA8, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11CA9, 0x11CB6, .p.property = IDNA_P_PVALID },
+ { 0x11CB7, 0x11CFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11D00, 0x11D06, .p.property = IDNA_P_PVALID },
+ { 0x11D07, 0x11D07, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11D08, 0x11D09, .p.property = IDNA_P_PVALID },
+ { 0x11D0A, 0x11D0A, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11D0B, 0x11D36, .p.property = IDNA_P_PVALID },
+ { 0x11D37, 0x11D39, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11D3A, 0x11D3A, .p.property = IDNA_P_PVALID },
+ { 0x11D3B, 0x11D3B, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11D3C, 0x11D3D, .p.property = IDNA_P_PVALID },
+ { 0x11D3E, 0x11D3E, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11D3F, 0x11D47, .p.property = IDNA_P_PVALID },
+ { 0x11D48, 0x11D4F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11D50, 0x11D59, .p.property = IDNA_P_PVALID },
+ { 0x11D5A, 0x11D5F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11D60, 0x11D65, .p.property = IDNA_P_PVALID },
+ { 0x11D66, 0x11D66, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11D67, 0x11D68, .p.property = IDNA_P_PVALID },
+ { 0x11D69, 0x11D69, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11D6A, 0x11D8E, .p.property = IDNA_P_PVALID },
+ { 0x11D8F, 0x11D8F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11D90, 0x11D91, .p.property = IDNA_P_PVALID },
+ { 0x11D92, 0x11D92, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11D93, 0x11D98, .p.property = IDNA_P_PVALID },
+ { 0x11D99, 0x11D9F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11DA0, 0x11DA9, .p.property = IDNA_P_PVALID },
+ { 0x11DAA, 0x11EDF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x11EE0, 0x11EF6, .p.property = IDNA_P_PVALID },
+ { 0x11EF7, 0x11EF8, .p.property = IDNA_P_DISALLOWED },
+ { 0x11EF9, 0x11FFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x12000, 0x12399, .p.property = IDNA_P_PVALID },
+ { 0x1239A, 0x123FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x12400, 0x1246E, .p.property = IDNA_P_DISALLOWED },
+ { 0x1246F, 0x1246F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x12470, 0x12474, .p.property = IDNA_P_DISALLOWED },
+ { 0x12475, 0x1247F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x12480, 0x12543, .p.property = IDNA_P_PVALID },
+ { 0x12544, 0x12FFF, .p.property = IDNA_P_UNASSIGNED },
{ 0x13000, 0x1342E, .p.property = IDNA_P_PVALID },
- { 0x1342F, 0x1CFFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1342F, 0x143FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x14400, 0x14646, .p.property = IDNA_P_PVALID },
+ { 0x14647, 0x167FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x16800, 0x16A38, .p.property = IDNA_P_PVALID },
+ { 0x16A39, 0x16A3F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x16A40, 0x16A5E, .p.property = IDNA_P_PVALID },
+ { 0x16A5F, 0x16A5F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x16A60, 0x16A69, .p.property = IDNA_P_PVALID },
+ { 0x16A6A, 0x16A6D, .p.property = IDNA_P_UNASSIGNED },
+ { 0x16A6E, 0x16A6F, .p.property = IDNA_P_DISALLOWED },
+ { 0x16A70, 0x16ACF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x16AD0, 0x16AED, .p.property = IDNA_P_PVALID },
+ { 0x16AEE, 0x16AEF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x16AF0, 0x16AF4, .p.property = IDNA_P_PVALID },
+ { 0x16AF5, 0x16AF5, .p.property = IDNA_P_DISALLOWED },
+ { 0x16AF6, 0x16AFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x16B00, 0x16B36, .p.property = IDNA_P_PVALID },
+ { 0x16B37, 0x16B3F, .p.property = IDNA_P_DISALLOWED },
+ { 0x16B40, 0x16B43, .p.property = IDNA_P_PVALID },
+ { 0x16B44, 0x16B45, .p.property = IDNA_P_DISALLOWED },
+ { 0x16B46, 0x16B4F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x16B50, 0x16B59, .p.property = IDNA_P_PVALID },
+ { 0x16B5A, 0x16B5A, .p.property = IDNA_P_UNASSIGNED },
+ { 0x16B5B, 0x16B61, .p.property = IDNA_P_DISALLOWED },
+ { 0x16B62, 0x16B62, .p.property = IDNA_P_UNASSIGNED },
+ { 0x16B63, 0x16B77, .p.property = IDNA_P_PVALID },
+ { 0x16B78, 0x16B7C, .p.property = IDNA_P_UNASSIGNED },
+ { 0x16B7D, 0x16B8F, .p.property = IDNA_P_PVALID },
+ { 0x16B90, 0x16E3F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x16E40, 0x16E5F, .p.property = IDNA_P_DISALLOWED },
+ { 0x16E60, 0x16E7F, .p.property = IDNA_P_PVALID },
+ { 0x16E80, 0x16E9A, .p.property = IDNA_P_DISALLOWED },
+ { 0x16E9B, 0x16EFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x16F00, 0x16F44, .p.property = IDNA_P_PVALID },
+ { 0x16F45, 0x16F4F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x16F50, 0x16F7E, .p.property = IDNA_P_PVALID },
+ { 0x16F7F, 0x16F8E, .p.property = IDNA_P_UNASSIGNED },
+ { 0x16F8F, 0x16F9F, .p.property = IDNA_P_PVALID },
+ { 0x16FA0, 0x16FDF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x16FE0, 0x16FE1, .p.property = IDNA_P_PVALID },
+ { 0x16FE2, 0x16FFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x17000, 0x187F1, .p.property = IDNA_P_PVALID },
+ { 0x187F2, 0x187FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x18800, 0x18AF2, .p.property = IDNA_P_PVALID },
+ { 0x18AF3, 0x1AFFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1B000, 0x1B11E, .p.property = IDNA_P_PVALID },
+ { 0x1B11F, 0x1B16F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1B170, 0x1B2FB, .p.property = IDNA_P_PVALID },
+ { 0x1B2FC, 0x1BBFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1BC00, 0x1BC6A, .p.property = IDNA_P_PVALID },
+ { 0x1BC6B, 0x1BC6F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1BC70, 0x1BC7C, .p.property = IDNA_P_PVALID },
+ { 0x1BC7D, 0x1BC7F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1BC80, 0x1BC88, .p.property = IDNA_P_PVALID },
+ { 0x1BC89, 0x1BC8F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1BC90, 0x1BC99, .p.property = IDNA_P_PVALID },
+ { 0x1BC9A, 0x1BC9B, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1BC9C, 0x1BC9C, .p.property = IDNA_P_DISALLOWED },
+ { 0x1BC9D, 0x1BC9E, .p.property = IDNA_P_PVALID },
+ { 0x1BC9F, 0x1BCA3, .p.property = IDNA_P_DISALLOWED },
+ { 0x1BCA4, 0x1CFFF, .p.property = IDNA_P_UNASSIGNED },
{ 0x1D000, 0x1D0F5, .p.property = IDNA_P_DISALLOWED },
{ 0x1D0F6, 0x1D0FF, .p.property = IDNA_P_UNASSIGNED },
{ 0x1D100, 0x1D126, .p.property = IDNA_P_DISALLOWED },
{ 0x1D127, 0x1D128, .p.property = IDNA_P_UNASSIGNED },
- { 0x1D129, 0x1D1DD, .p.property = IDNA_P_DISALLOWED },
- { 0x1D1DE, 0x1D1FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1D129, 0x1D1E8, .p.property = IDNA_P_DISALLOWED },
+ { 0x1D1E9, 0x1D1FF, .p.property = IDNA_P_UNASSIGNED },
{ 0x1D200, 0x1D245, .p.property = IDNA_P_DISALLOWED },
- { 0x1D246, 0x1D2FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1D246, 0x1D2DF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1D2E0, 0x1D2F3, .p.property = IDNA_P_DISALLOWED },
+ { 0x1D2F4, 0x1D2FF, .p.property = IDNA_P_UNASSIGNED },
{ 0x1D300, 0x1D356, .p.property = IDNA_P_DISALLOWED },
{ 0x1D357, 0x1D35F, .p.property = IDNA_P_UNASSIGNED },
- { 0x1D360, 0x1D371, .p.property = IDNA_P_DISALLOWED },
- { 0x1D372, 0x1D3FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1D360, 0x1D378, .p.property = IDNA_P_DISALLOWED },
+ { 0x1D379, 0x1D3FF, .p.property = IDNA_P_UNASSIGNED },
{ 0x1D400, 0x1D454, .p.property = IDNA_P_DISALLOWED },
{ 0x1D455, 0x1D455, .p.property = IDNA_P_UNASSIGNED },
{ 0x1D456, 0x1D49C, .p.property = IDNA_P_DISALLOWED },
@@ -2273,53 +2651,191 @@ idna_table idna_derived[] = {
{ 0x1D6A6, 0x1D6A7, .p.property = IDNA_P_UNASSIGNED },
{ 0x1D6A8, 0x1D7CB, .p.property = IDNA_P_DISALLOWED },
{ 0x1D7CC, 0x1D7CD, .p.property = IDNA_P_UNASSIGNED },
- { 0x1D7CE, 0x1D7FF, .p.property = IDNA_P_DISALLOWED },
- { 0x1D800, 0x1EFFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1D7CE, 0x1D9FF, .p.property = IDNA_P_DISALLOWED },
+ { 0x1DA00, 0x1DA36, .p.property = IDNA_P_PVALID },
+ { 0x1DA37, 0x1DA3A, .p.property = IDNA_P_DISALLOWED },
+ { 0x1DA3B, 0x1DA6C, .p.property = IDNA_P_PVALID },
+ { 0x1DA6D, 0x1DA74, .p.property = IDNA_P_DISALLOWED },
+ { 0x1DA75, 0x1DA75, .p.property = IDNA_P_PVALID },
+ { 0x1DA76, 0x1DA83, .p.property = IDNA_P_DISALLOWED },
+ { 0x1DA84, 0x1DA84, .p.property = IDNA_P_PVALID },
+ { 0x1DA85, 0x1DA8B, .p.property = IDNA_P_DISALLOWED },
+ { 0x1DA8C, 0x1DA9A, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1DA9B, 0x1DA9F, .p.property = IDNA_P_PVALID },
+ { 0x1DAA0, 0x1DAA0, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1DAA1, 0x1DAAF, .p.property = IDNA_P_PVALID },
+ { 0x1DAB0, 0x1DFFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1E000, 0x1E006, .p.property = IDNA_P_PVALID },
+ { 0x1E007, 0x1E007, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1E008, 0x1E018, .p.property = IDNA_P_PVALID },
+ { 0x1E019, 0x1E01A, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1E01B, 0x1E021, .p.property = IDNA_P_PVALID },
+ { 0x1E022, 0x1E022, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1E023, 0x1E024, .p.property = IDNA_P_PVALID },
+ { 0x1E025, 0x1E025, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1E026, 0x1E02A, .p.property = IDNA_P_PVALID },
+ { 0x1E02B, 0x1E7FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1E800, 0x1E8C4, .p.property = IDNA_P_PVALID },
+ { 0x1E8C5, 0x1E8C6, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1E8C7, 0x1E8CF, .p.property = IDNA_P_DISALLOWED },
+ { 0x1E8D0, 0x1E8D6, .p.property = IDNA_P_PVALID },
+ { 0x1E8D7, 0x1E8FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1E900, 0x1E921, .p.property = IDNA_P_DISALLOWED },
+ { 0x1E922, 0x1E94A, .p.property = IDNA_P_PVALID },
+ { 0x1E94B, 0x1E94F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1E950, 0x1E959, .p.property = IDNA_P_PVALID },
+ { 0x1E95A, 0x1E95D, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1E95E, 0x1E95F, .p.property = IDNA_P_DISALLOWED },
+ { 0x1E960, 0x1EC70, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EC71, 0x1ECB4, .p.property = IDNA_P_DISALLOWED },
+ { 0x1ECB5, 0x1EDFF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE00, 0x1EE03, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE04, 0x1EE04, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE05, 0x1EE1F, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE20, 0x1EE20, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE21, 0x1EE22, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE23, 0x1EE23, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE24, 0x1EE24, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE25, 0x1EE26, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE27, 0x1EE27, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE28, 0x1EE28, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE29, 0x1EE32, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE33, 0x1EE33, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE34, 0x1EE37, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE38, 0x1EE38, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE39, 0x1EE39, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE3A, 0x1EE3A, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE3B, 0x1EE3B, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE3C, 0x1EE41, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE42, 0x1EE42, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE43, 0x1EE46, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE47, 0x1EE47, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE48, 0x1EE48, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE49, 0x1EE49, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE4A, 0x1EE4A, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE4B, 0x1EE4B, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE4C, 0x1EE4C, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE4D, 0x1EE4F, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE50, 0x1EE50, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE51, 0x1EE52, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE53, 0x1EE53, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE54, 0x1EE54, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE55, 0x1EE56, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE57, 0x1EE57, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE58, 0x1EE58, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE59, 0x1EE59, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE5A, 0x1EE5A, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE5B, 0x1EE5B, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE5C, 0x1EE5C, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE5D, 0x1EE5D, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE5E, 0x1EE5E, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE5F, 0x1EE5F, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE60, 0x1EE60, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE61, 0x1EE62, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE63, 0x1EE63, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE64, 0x1EE64, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE65, 0x1EE66, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE67, 0x1EE6A, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE6B, 0x1EE6B, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE6C, 0x1EE72, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE73, 0x1EE73, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE74, 0x1EE77, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE78, 0x1EE78, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE79, 0x1EE7C, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE7D, 0x1EE7D, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE7E, 0x1EE7E, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE7F, 0x1EE7F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE80, 0x1EE89, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE8A, 0x1EE8A, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EE8B, 0x1EE9B, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EE9C, 0x1EEA0, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EEA1, 0x1EEA3, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EEA4, 0x1EEA4, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EEA5, 0x1EEA9, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EEAA, 0x1EEAA, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EEAB, 0x1EEBB, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EEBC, 0x1EEEF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1EEF0, 0x1EEF1, .p.property = IDNA_P_DISALLOWED },
+ { 0x1EEF2, 0x1EFFF, .p.property = IDNA_P_UNASSIGNED },
{ 0x1F000, 0x1F02B, .p.property = IDNA_P_DISALLOWED },
{ 0x1F02C, 0x1F02F, .p.property = IDNA_P_UNASSIGNED },
{ 0x1F030, 0x1F093, .p.property = IDNA_P_DISALLOWED },
- { 0x1F094, 0x1F0FF, .p.property = IDNA_P_UNASSIGNED },
- { 0x1F100, 0x1F10A, .p.property = IDNA_P_DISALLOWED },
- { 0x1F10B, 0x1F10F, .p.property = IDNA_P_UNASSIGNED },
- { 0x1F110, 0x1F12E, .p.property = IDNA_P_DISALLOWED },
- { 0x1F12F, 0x1F130, .p.property = IDNA_P_UNASSIGNED },
- { 0x1F131, 0x1F131, .p.property = IDNA_P_DISALLOWED },
- { 0x1F132, 0x1F13C, .p.property = IDNA_P_UNASSIGNED },
- { 0x1F13D, 0x1F13D, .p.property = IDNA_P_DISALLOWED },
- { 0x1F13E, 0x1F13E, .p.property = IDNA_P_UNASSIGNED },
- { 0x1F13F, 0x1F13F, .p.property = IDNA_P_DISALLOWED },
- { 0x1F140, 0x1F141, .p.property = IDNA_P_UNASSIGNED },
- { 0x1F142, 0x1F142, .p.property = IDNA_P_DISALLOWED },
- { 0x1F143, 0x1F145, .p.property = IDNA_P_UNASSIGNED },
- { 0x1F146, 0x1F146, .p.property = IDNA_P_DISALLOWED },
- { 0x1F147, 0x1F149, .p.property = IDNA_P_UNASSIGNED },
- { 0x1F14A, 0x1F14E, .p.property = IDNA_P_DISALLOWED },
- { 0x1F14F, 0x1F156, .p.property = IDNA_P_UNASSIGNED },
- { 0x1F157, 0x1F157, .p.property = IDNA_P_DISALLOWED },
- { 0x1F158, 0x1F15E, .p.property = IDNA_P_UNASSIGNED },
- { 0x1F15F, 0x1F15F, .p.property = IDNA_P_DISALLOWED },
- { 0x1F160, 0x1F178, .p.property = IDNA_P_UNASSIGNED },
- { 0x1F179, 0x1F179, .p.property = IDNA_P_DISALLOWED },
- { 0x1F17A, 0x1F17A, .p.property = IDNA_P_UNASSIGNED },
- { 0x1F17B, 0x1F17C, .p.property = IDNA_P_DISALLOWED },
- { 0x1F17D, 0x1F17E, .p.property = IDNA_P_UNASSIGNED },
- { 0x1F17F, 0x1F17F, .p.property = IDNA_P_DISALLOWED },
- { 0x1F180, 0x1F189, .p.property = IDNA_P_UNASSIGNED },
- { 0x1F18A, 0x1F18D, .p.property = IDNA_P_DISALLOWED },
- { 0x1F18E, 0x1F18F, .p.property = IDNA_P_UNASSIGNED },
- { 0x1F190, 0x1F190, .p.property = IDNA_P_DISALLOWED },
- { 0x1F191, 0x1F1FF, .p.property = IDNA_P_UNASSIGNED },
- { 0x1F200, 0x1F200, .p.property = IDNA_P_DISALLOWED },
- { 0x1F201, 0x1F20F, .p.property = IDNA_P_UNASSIGNED },
- { 0x1F210, 0x1F231, .p.property = IDNA_P_DISALLOWED },
- { 0x1F232, 0x1F23F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F094, 0x1F09F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F0A0, 0x1F0AE, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F0AF, 0x1F0B0, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F0B1, 0x1F0BF, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F0C0, 0x1F0C0, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F0C1, 0x1F0CF, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F0D0, 0x1F0D0, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F0D1, 0x1F0F5, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F0F6, 0x1F0FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F100, 0x1F10C, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F10D, 0x1F10F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F110, 0x1F16B, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F16C, 0x1F16F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F170, 0x1F1AC, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F1AD, 0x1F1E5, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F1E6, 0x1F202, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F203, 0x1F20F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F210, 0x1F23B, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F23C, 0x1F23F, .p.property = IDNA_P_UNASSIGNED },
{ 0x1F240, 0x1F248, .p.property = IDNA_P_DISALLOWED },
- { 0x1F249, 0x1FFFD, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F249, 0x1F24F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F250, 0x1F251, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F252, 0x1F25F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F260, 0x1F265, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F266, 0x1F2FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F300, 0x1F6D4, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F6D5, 0x1F6DF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F6E0, 0x1F6EC, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F6ED, 0x1F6EF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F6F0, 0x1F6F9, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F6FA, 0x1F6FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F700, 0x1F773, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F774, 0x1F77F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F780, 0x1F7D8, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F7D9, 0x1F7FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F800, 0x1F80B, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F80C, 0x1F80F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F810, 0x1F847, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F848, 0x1F84F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F850, 0x1F859, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F85A, 0x1F85F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F860, 0x1F887, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F888, 0x1F88F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F890, 0x1F8AD, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F8AE, 0x1F8FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F900, 0x1F90B, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F90C, 0x1F90F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F910, 0x1F93E, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F93F, 0x1F93F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F940, 0x1F970, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F971, 0x1F972, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F973, 0x1F976, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F977, 0x1F979, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F97A, 0x1F97A, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F97B, 0x1F97B, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F97C, 0x1F9A2, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F9A3, 0x1F9AF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F9B0, 0x1F9B9, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F9BA, 0x1F9BF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F9C0, 0x1F9C2, .p.property = IDNA_P_DISALLOWED },
+ { 0x1F9C3, 0x1F9CF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1F9D0, 0x1F9FF, .p.property = IDNA_P_DISALLOWED },
+ { 0x1FA00, 0x1FA5F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x1FA60, 0x1FA6D, .p.property = IDNA_P_DISALLOWED },
+ { 0x1FA6E, 0x1FFFD, .p.property = IDNA_P_UNASSIGNED },
{ 0x1FFFE, 0x1FFFF, .p.property = IDNA_P_DISALLOWED },
{ 0x20000, 0x2A6D6, .p.property = IDNA_P_PVALID },
{ 0x2A6D7, 0x2A6FF, .p.property = IDNA_P_UNASSIGNED },
{ 0x2A700, 0x2B734, .p.property = IDNA_P_PVALID },
- { 0x2B735, 0x2F7FF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x2B735, 0x2B73F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x2B740, 0x2B81D, .p.property = IDNA_P_PVALID },
+ { 0x2B81E, 0x2B81F, .p.property = IDNA_P_UNASSIGNED },
+ { 0x2B820, 0x2CEA1, .p.property = IDNA_P_PVALID },
+ { 0x2CEA2, 0x2CEAF, .p.property = IDNA_P_UNASSIGNED },
+ { 0x2CEB0, 0x2EBE0, .p.property = IDNA_P_PVALID },
+ { 0x2EBE1, 0x2F7FF, .p.property = IDNA_P_UNASSIGNED },
{ 0x2F800, 0x2FA1D, .p.property = IDNA_P_DISALLOWED },
{ 0x2FA1E, 0x2FFFD, .p.property = IDNA_P_UNASSIGNED },
{ 0x2FFFE, 0x2FFFF, .p.property = IDNA_P_DISALLOWED },
@@ -2359,7 +2875,9 @@ idna_table idna_derived[] = {
idna_table idna_joiningtype[] = {
{ 0x0640 , 0x0640 , .p.jt = IDNA_UNICODE_JT_C },
{ 0x07FA , 0x07FA , .p.jt = IDNA_UNICODE_JT_C },
+ { 0x180A , 0x180A , .p.jt = IDNA_UNICODE_JT_C },
{ 0x200D , 0x200D , .p.jt = IDNA_UNICODE_JT_C },
+ { 0x0620 , 0x0620 , .p.jt = IDNA_UNICODE_JT_D },
{ 0x0626 , 0x0626 , .p.jt = IDNA_UNICODE_JT_D },
{ 0x0628 , 0x0628 , .p.jt = IDNA_UNICODE_JT_D },
{ 0x062A, 0x062E , .p.jt = IDNA_UNICODE_JT_D },
@@ -2388,6 +2906,43 @@ idna_table idna_joiningtype[] = {
{ 0x0775, 0x0777 , .p.jt = IDNA_UNICODE_JT_D },
{ 0x077A, 0x077F , .p.jt = IDNA_UNICODE_JT_D },
{ 0x07CA, 0x07EA , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x0841, 0x0845 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x0848 , 0x0848 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x084A, 0x0853 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x0855 , 0x0855 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x0860 , 0x0860 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x0862, 0x0865 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x0868 , 0x0868 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x08A0, 0x08A9 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x08AF, 0x08B0 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x08B3, 0x08B4 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x08B6, 0x08B8 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x08BA, 0x08BD , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x1807 , 0x1807 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x1820, 0x1842 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x1843 , 0x1843 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x1844, 0x1878 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x1887, 0x18A8 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x18AA , 0x18AA , .p.jt = IDNA_UNICODE_JT_D },
+ { 0xA840, 0xA871 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x10AC0, 0x10AC4 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x10AD3, 0x10AD6 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x10AD8, 0x10ADC , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x10ADE, 0x10AE0 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x10AEB, 0x10AEE , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x10B80 , 0x10B80 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x10B82 , 0x10B82 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x10B86, 0x10B88 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x10B8A, 0x10B8B , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x10B8D , 0x10B8D , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x10B90 , 0x10B90 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x10BAD, 0x10BAE , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x10D01, 0x10D21 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x10D23 , 0x10D23 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x10F30, 0x10F32 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x10F34, 0x10F44 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x10F51, 0x10F53 , .p.jt = IDNA_UNICODE_JT_D },
+ { 0x1E900, 0x1E943 , .p.jt = IDNA_UNICODE_JT_D },
{ 0x0622, 0x0625 , .p.jt = IDNA_UNICODE_JT_R },
{ 0x0627 , 0x0627 , .p.jt = IDNA_UNICODE_JT_R },
{ 0x0629 , 0x0629 , .p.jt = IDNA_UNICODE_JT_R },
@@ -2416,6 +2971,38 @@ idna_table idna_joiningtype[] = {
{ 0x0771 , 0x0771 , .p.jt = IDNA_UNICODE_JT_R },
{ 0x0773, 0x0774 , .p.jt = IDNA_UNICODE_JT_R },
{ 0x0778, 0x0779 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x0840 , 0x0840 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x0846, 0x0847 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x0849 , 0x0849 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x0854 , 0x0854 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x0867 , 0x0867 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x0869, 0x086A , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x08AA, 0x08AC , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x08AE , 0x08AE , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x08B1, 0x08B2 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x08B9 , 0x08B9 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x10AC5 , 0x10AC5 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x10AC7 , 0x10AC7 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x10AC9, 0x10ACA , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x10ACE, 0x10AD2 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x10ADD , 0x10ADD , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x10AE1 , 0x10AE1 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x10AE4 , 0x10AE4 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x10AEF , 0x10AEF , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x10B81 , 0x10B81 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x10B83, 0x10B85 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x10B89 , 0x10B89 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x10B8C , 0x10B8C , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x10B8E, 0x10B8F , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x10B91 , 0x10B91 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x10BA9, 0x10BAC , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x10D22 , 0x10D22 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x10F33 , 0x10F33 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0x10F54 , 0x10F54 , .p.jt = IDNA_UNICODE_JT_R },
+ { 0xA872 , 0xA872 , .p.jt = IDNA_UNICODE_JT_L },
+ { 0x10ACD , 0x10ACD , .p.jt = IDNA_UNICODE_JT_L },
+ { 0x10AD7 , 0x10AD7 , .p.jt = IDNA_UNICODE_JT_L },
+ { 0x10D00 , 0x10D00 , .p.jt = IDNA_UNICODE_JT_L },
{ 0x00AD , 0x00AD , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0300, 0x036F , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0483, 0x0487 , .p.jt = IDNA_UNICODE_JT_T },
@@ -2426,10 +3013,10 @@ idna_table idna_joiningtype[] = {
{ 0x05C4, 0x05C5 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x05C7 , 0x05C7 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0610, 0x061A , .p.jt = IDNA_UNICODE_JT_T },
- { 0x064B, 0x065E , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x061C , 0x061C , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x064B, 0x065F , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0670 , 0x0670 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x06D6, 0x06DC , .p.jt = IDNA_UNICODE_JT_T },
- { 0x06DE , 0x06DE , .p.jt = IDNA_UNICODE_JT_T },
{ 0x06DF, 0x06E4 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x06E7, 0x06E8 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x06EA, 0x06ED , .p.jt = IDNA_UNICODE_JT_T },
@@ -2438,21 +3025,26 @@ idna_table idna_joiningtype[] = {
{ 0x0730, 0x074A , .p.jt = IDNA_UNICODE_JT_T },
{ 0x07A6, 0x07B0 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x07EB, 0x07F3 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x07FD , 0x07FD , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0816, 0x0819 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x081B, 0x0823 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0825, 0x0827 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0829, 0x082D , .p.jt = IDNA_UNICODE_JT_T },
- { 0x0900, 0x0902 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x0859, 0x085B , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x08D3, 0x08E1 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x08E3, 0x0902 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x093A , 0x093A , .p.jt = IDNA_UNICODE_JT_T },
{ 0x093C , 0x093C , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0941, 0x0948 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x094D , 0x094D , .p.jt = IDNA_UNICODE_JT_T },
- { 0x0951, 0x0955 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x0951, 0x0957 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0962, 0x0963 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0981 , 0x0981 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x09BC , 0x09BC , .p.jt = IDNA_UNICODE_JT_T },
{ 0x09C1, 0x09C4 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x09CD , 0x09CD , .p.jt = IDNA_UNICODE_JT_T },
{ 0x09E2, 0x09E3 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x09FE , 0x09FE , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0A01, 0x0A02 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0A3C , 0x0A3C , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0A41, 0x0A42 , .p.jt = IDNA_UNICODE_JT_T },
@@ -2467,6 +3059,7 @@ idna_table idna_joiningtype[] = {
{ 0x0AC7, 0x0AC8 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0ACD , 0x0ACD , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0AE2, 0x0AE3 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x0AFA, 0x0AFF , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0B01 , 0x0B01 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0B3C , 0x0B3C , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0B3F , 0x0B3F , .p.jt = IDNA_UNICODE_JT_T },
@@ -2477,16 +3070,21 @@ idna_table idna_joiningtype[] = {
{ 0x0B82 , 0x0B82 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0BC0 , 0x0BC0 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0BCD , 0x0BCD , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x0C00 , 0x0C00 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x0C04 , 0x0C04 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0C3E, 0x0C40 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0C46, 0x0C48 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0C4A, 0x0C4D , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0C55, 0x0C56 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0C62, 0x0C63 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x0C81 , 0x0C81 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0CBC , 0x0CBC , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0CBF , 0x0CBF , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0CC6 , 0x0CC6 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0CCC, 0x0CCD , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0CE2, 0x0CE3 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x0D00, 0x0D01 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x0D3B, 0x0D3C , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0D41, 0x0D44 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0D4D , 0x0D4D , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0D62, 0x0D63 , .p.jt = IDNA_UNICODE_JT_T },
@@ -2507,7 +3105,7 @@ idna_table idna_joiningtype[] = {
{ 0x0F71, 0x0F7E , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0F80, 0x0F84 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0F86, 0x0F87 , .p.jt = IDNA_UNICODE_JT_T },
- { 0x0F90, 0x0F97 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x0F8D, 0x0F97 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0F99, 0x0FBC , .p.jt = IDNA_UNICODE_JT_T },
{ 0x0FC6 , 0x0FC6 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x102D, 0x1030 , .p.jt = IDNA_UNICODE_JT_T },
@@ -2521,7 +3119,7 @@ idna_table idna_joiningtype[] = {
{ 0x1085, 0x1086 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x108D , 0x108D , .p.jt = IDNA_UNICODE_JT_T },
{ 0x109D , 0x109D , .p.jt = IDNA_UNICODE_JT_T },
- { 0x135F , 0x135F , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x135D, 0x135F , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1712, 0x1714 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1732, 0x1734 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1752, 0x1753 , .p.jt = IDNA_UNICODE_JT_T },
@@ -2532,12 +3130,14 @@ idna_table idna_joiningtype[] = {
{ 0x17C9, 0x17D3 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x17DD , 0x17DD , .p.jt = IDNA_UNICODE_JT_T },
{ 0x180B, 0x180D , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1885, 0x1886 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x18A9 , 0x18A9 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1920, 0x1922 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1927, 0x1928 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1932 , 0x1932 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1939, 0x193B , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1A17, 0x1A18 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1A1B , 0x1A1B , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1A56 , 0x1A56 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1A58, 0x1A5E , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1A60 , 0x1A60 , .p.jt = IDNA_UNICODE_JT_T },
@@ -2545,6 +3145,8 @@ idna_table idna_joiningtype[] = {
{ 0x1A65, 0x1A6C , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1A73, 0x1A7C , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1A7F , 0x1A7F , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1AB0, 0x1ABD , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1ABE , 0x1ABE , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1B00, 0x1B03 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1B34 , 0x1B34 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1B36, 0x1B3A , .p.jt = IDNA_UNICODE_JT_T },
@@ -2554,14 +3156,21 @@ idna_table idna_joiningtype[] = {
{ 0x1B80, 0x1B81 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1BA2, 0x1BA5 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1BA8, 0x1BA9 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1BAB, 0x1BAD , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1BE6 , 0x1BE6 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1BE8, 0x1BE9 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1BED , 0x1BED , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1BEF, 0x1BF1 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1C2C, 0x1C33 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1C36, 0x1C37 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1CD0, 0x1CD2 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1CD4, 0x1CE0 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1CE2, 0x1CE8 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1CED , 0x1CED , .p.jt = IDNA_UNICODE_JT_T },
- { 0x1DC0, 0x1DE6 , .p.jt = IDNA_UNICODE_JT_T },
- { 0x1DFD, 0x1DFF , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1CF4 , 0x1CF4 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1CF8, 0x1CF9 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1DC0, 0x1DF9 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1DFB, 0x1DFF , .p.jt = IDNA_UNICODE_JT_T },
{ 0x200B , 0x200B , .p.jt = IDNA_UNICODE_JT_T },
{ 0x200E, 0x200F , .p.jt = IDNA_UNICODE_JT_T },
{ 0x202A, 0x202E , .p.jt = IDNA_UNICODE_JT_T },
@@ -2573,59 +3182,156 @@ idna_table idna_joiningtype[] = {
{ 0x20E2, 0x20E4 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x20E5, 0x20F0 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x2CEF, 0x2CF1 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x2D7F , 0x2D7F , .p.jt = IDNA_UNICODE_JT_T },
{ 0x2DE0, 0x2DFF , .p.jt = IDNA_UNICODE_JT_T },
- { 0x302A, 0x302F , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x302A, 0x302D , .p.jt = IDNA_UNICODE_JT_T },
{ 0x3099, 0x309A , .p.jt = IDNA_UNICODE_JT_T },
{ 0xA66F , 0xA66F , .p.jt = IDNA_UNICODE_JT_T },
{ 0xA670, 0xA672 , .p.jt = IDNA_UNICODE_JT_T },
- { 0xA67C, 0xA67D , .p.jt = IDNA_UNICODE_JT_T },
+ { 0xA674, 0xA67D , .p.jt = IDNA_UNICODE_JT_T },
+ { 0xA69E, 0xA69F , .p.jt = IDNA_UNICODE_JT_T },
{ 0xA6F0, 0xA6F1 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xA802 , 0xA802 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xA806 , 0xA806 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xA80B , 0xA80B , .p.jt = IDNA_UNICODE_JT_T },
{ 0xA825, 0xA826 , .p.jt = IDNA_UNICODE_JT_T },
- { 0xA8C4 , 0xA8C4 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0xA8C4, 0xA8C5 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xA8E0, 0xA8F1 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0xA8FF , 0xA8FF , .p.jt = IDNA_UNICODE_JT_T },
{ 0xA926, 0xA92D , .p.jt = IDNA_UNICODE_JT_T },
{ 0xA947, 0xA951 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xA980, 0xA982 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xA9B3 , 0xA9B3 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xA9B6, 0xA9B9 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xA9BC , 0xA9BC , .p.jt = IDNA_UNICODE_JT_T },
+ { 0xA9E5 , 0xA9E5 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xAA29, 0xAA2E , .p.jt = IDNA_UNICODE_JT_T },
{ 0xAA31, 0xAA32 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xAA35, 0xAA36 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xAA43 , 0xAA43 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xAA4C , 0xAA4C , .p.jt = IDNA_UNICODE_JT_T },
+ { 0xAA7C , 0xAA7C , .p.jt = IDNA_UNICODE_JT_T },
{ 0xAAB0 , 0xAAB0 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xAAB2, 0xAAB4 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xAAB7, 0xAAB8 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xAABE, 0xAABF , .p.jt = IDNA_UNICODE_JT_T },
{ 0xAAC1 , 0xAAC1 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0xAAEC, 0xAAED , .p.jt = IDNA_UNICODE_JT_T },
+ { 0xAAF6 , 0xAAF6 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xABE5 , 0xABE5 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xABE8 , 0xABE8 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xABED , 0xABED , .p.jt = IDNA_UNICODE_JT_T },
{ 0xFB1E , 0xFB1E , .p.jt = IDNA_UNICODE_JT_T },
{ 0xFE00, 0xFE0F , .p.jt = IDNA_UNICODE_JT_T },
- { 0xFE20, 0xFE26 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0xFE20, 0xFE2F , .p.jt = IDNA_UNICODE_JT_T },
{ 0xFEFF , 0xFEFF , .p.jt = IDNA_UNICODE_JT_T },
{ 0xFFF9, 0xFFFB , .p.jt = IDNA_UNICODE_JT_T },
{ 0x101FD , 0x101FD , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x102E0 , 0x102E0 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x10376, 0x1037A , .p.jt = IDNA_UNICODE_JT_T },
{ 0x10A01, 0x10A03 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x10A05, 0x10A06 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x10A0C, 0x10A0F , .p.jt = IDNA_UNICODE_JT_T },
{ 0x10A38, 0x10A3A , .p.jt = IDNA_UNICODE_JT_T },
{ 0x10A3F , 0x10A3F , .p.jt = IDNA_UNICODE_JT_T },
- { 0x11080, 0x11081 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x10AE5, 0x10AE6 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x10D24, 0x10D27 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x10F46, 0x10F50 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11001 , 0x11001 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11038, 0x11046 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1107F, 0x11081 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x110B3, 0x110B6 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x110B9, 0x110BA , .p.jt = IDNA_UNICODE_JT_T },
- { 0x110BD , 0x110BD , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11100, 0x11102 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11127, 0x1112B , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1112D, 0x11134 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11173 , 0x11173 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11180, 0x11181 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x111B6, 0x111BE , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x111C9, 0x111CC , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1122F, 0x11231 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11234 , 0x11234 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11236, 0x11237 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1123E , 0x1123E , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x112DF , 0x112DF , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x112E3, 0x112EA , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11300, 0x11301 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1133B, 0x1133C , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11340 , 0x11340 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11366, 0x1136C , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11370, 0x11374 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11438, 0x1143F , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11442, 0x11444 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11446 , 0x11446 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1145E , 0x1145E , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x114B3, 0x114B8 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x114BA , 0x114BA , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x114BF, 0x114C0 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x114C2, 0x114C3 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x115B2, 0x115B5 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x115BC, 0x115BD , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x115BF, 0x115C0 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x115DC, 0x115DD , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11633, 0x1163A , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1163D , 0x1163D , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1163F, 0x11640 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x116AB , 0x116AB , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x116AD , 0x116AD , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x116B0, 0x116B5 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x116B7 , 0x116B7 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1171D, 0x1171F , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11722, 0x11725 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11727, 0x1172B , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1182F, 0x11837 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11839, 0x1183A , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11A01, 0x11A0A , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11A33, 0x11A38 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11A3B, 0x11A3E , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11A47 , 0x11A47 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11A51, 0x11A56 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11A59, 0x11A5B , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11A8A, 0x11A96 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11A98, 0x11A99 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11C30, 0x11C36 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11C38, 0x11C3D , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11C3F , 0x11C3F , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11C92, 0x11CA7 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11CAA, 0x11CB0 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11CB2, 0x11CB3 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11CB5, 0x11CB6 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11D31, 0x11D36 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11D3A , 0x11D3A , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11D3C, 0x11D3D , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11D3F, 0x11D45 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11D47 , 0x11D47 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11D90, 0x11D91 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11D95 , 0x11D95 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11D97 , 0x11D97 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x11EF3, 0x11EF4 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x16AF0, 0x16AF4 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x16B30, 0x16B36 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x16F8F, 0x16F92 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1BC9D, 0x1BC9E , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1BCA0, 0x1BCA3 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1D167, 0x1D169 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1D173, 0x1D17A , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1D17B, 0x1D182 , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1D185, 0x1D18B , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1D1AA, 0x1D1AD , .p.jt = IDNA_UNICODE_JT_T },
{ 0x1D242, 0x1D244 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1DA00, 0x1DA36 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1DA3B, 0x1DA6C , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1DA75 , 0x1DA75 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1DA84 , 0x1DA84 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1DA9B, 0x1DA9F , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1DAA1, 0x1DAAF , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1E000, 0x1E006 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1E008, 0x1E018 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1E01B, 0x1E021 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1E023, 0x1E024 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1E026, 0x1E02A , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1E8D0, 0x1E8D6 , .p.jt = IDNA_UNICODE_JT_T },
+ { 0x1E944, 0x1E94A , .p.jt = IDNA_UNICODE_JT_T },
{ 0xE0001 , 0xE0001 , .p.jt = IDNA_UNICODE_JT_T },
{ 0xE0020, 0xE007F , .p.jt = IDNA_UNICODE_JT_T },
{ 0xE0100, 0xE01EF , .p.jt = IDNA_UNICODE_JT_T },
diff --git a/utils/inet.h b/utils/inet.h
index da1798432..29010efc1 100644
--- a/utils/inet.h
+++ b/utils/inet.h
@@ -40,6 +40,15 @@
#include <arpa/inet.h>
#include <sys/select.h>
+#define ns_close_socket close
+
+#ifdef WITH_AMISSL
+/* AmiSSL needs everything to be using bsdsocket directly to avoid conflicts */
+#include <proto/bsdsocket.h>
+#undef ns_close_socket
+#define ns_close_socket CloseSocket
+#endif
+
#else
#include <winsock2.h>
@@ -49,6 +58,8 @@
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#endif
+#define ns_close_socket closesocket
+
#endif
diff --git a/utils/libdom.c b/utils/libdom.c
index a996e98bf..c39aad343 100644
--- a/utils/libdom.c
+++ b/utils/libdom.c
@@ -28,129 +28,6 @@
#include "utils/log.h"
#include "utils/libdom.h"
-/* exported interface documented in libdom.h */
-bool libdom_treewalk(dom_node *root,
- bool (*callback)(dom_node *node, dom_string *name, void *ctx),
- void *ctx)
-{
- dom_node *node;
- bool result = true;
-
- node = dom_node_ref(root); /* tree root */
-
- while (node != NULL) {
- dom_node *next = NULL;
- dom_node_type type;
- dom_string *name;
- dom_exception exc;
-
- exc = dom_node_get_first_child(node, &next);
- if (exc != DOM_NO_ERR) {
- dom_node_unref(node);
- break;
- }
-
- if (next != NULL) {
- /* 1. Got children */
- dom_node_unref(node);
- node = next;
- } else {
- /* No children; siblings & ancestor's siblings */
- while (node != NULL) {
- exc = dom_node_get_next_sibling(node, &next);
- if (exc != DOM_NO_ERR) {
- dom_node_unref(node);
- node = NULL;
- break;
- }
-
- if (next != NULL) {
- /* 2. Got sibling */
- break;
- }
-
- exc = dom_node_get_parent_node(node, &next);
- if (exc != DOM_NO_ERR) {
- dom_node_unref(node);
- node = NULL;
- break;
- }
-
- /* 3. Try parent */
- dom_node_unref(node);
- node = next;
- }
-
- if (node == NULL)
- break;
-
- dom_node_unref(node);
- node = next;
- }
-
- assert(node != NULL);
-
- exc = dom_node_get_node_type(node, &type);
- if ((exc != DOM_NO_ERR) || (type != DOM_ELEMENT_NODE))
- continue;
-
- exc = dom_node_get_node_name(node, &name);
- if (exc != DOM_NO_ERR)
- continue;
-
- result = callback(node, name, ctx);
-
- dom_string_unref(name);
-
- if (result == false) {
- break; /* callback caused early termination */
- }
-
- }
- return result;
-}
-
-
-/* libdom_treewalk context for libdom_find_element */
-struct find_element_ctx {
- lwc_string *search;
- dom_node *found;
-};
-
-/* libdom_treewalk callback for libdom_find_element */
-static bool libdom_find_element_callback(dom_node *node, dom_string *name,
- void *ctx)
-{
- struct find_element_ctx *data = ctx;
-
- if (dom_string_caseless_lwc_isequal(name, data->search)) {
- /* Found element */
- data->found = node;
- return false; /* Discontinue search */
- }
-
- return true; /* Continue search */
-}
-
-
-/* exported interface documented in libdom.h */
-dom_node *libdom_find_element(dom_node *node, lwc_string *element_name)
-{
- struct find_element_ctx data;
-
- assert(element_name != NULL);
-
- if (node == NULL)
- return NULL;
-
- data.search = element_name;
- data.found = NULL;
-
- libdom_treewalk(node, libdom_find_element_callback, &data);
-
- return data.found;
-}
-
/* exported interface documented in libdom.h */
dom_node *libdom_find_first_element(dom_node *parent, lwc_string *element_name)
diff --git a/utils/libdom.h b/utils/libdom.h
index 306aa0f8b..63841934f 100644
--- a/utils/libdom.h
+++ b/utils/libdom.h
@@ -33,29 +33,6 @@
#include <dom/bindings/hubbub/errors.h>
/**
- * depth-first walk the dom calling callback for each element
- *
- * \param root the dom node to use as the root of the tree walk
- * \param callback The function called for each element
- * \param ctx The context passed to the callback.
- * \return true if all nodes were examined, false if the callback terminated
- * the walk early.
- */
-bool libdom_treewalk(dom_node *root,
- bool (*callback)(dom_node *node, dom_string *name, void *ctx),
- void *ctx);
-
-/**
- * Search the descendants of a node for an element.
- *
- * \param node dom_node to search children of, or NULL
- * \param element_name name of element to find
- * \return first child of node which is an element and matches name, or
- * NULL if not found or parameter node is NULL
- */
-dom_node *libdom_find_element(dom_node *node, lwc_string *element_name);
-
-/**
* Search children of a node for first named element
* \param parent dom_node to search children of, or NULL
* \param element_name name of element to find
diff --git a/utils/log.c b/utils/log.c
index e267b3179..a083b5720 100644
--- a/utils/log.c
+++ b/utils/log.c
@@ -94,11 +94,14 @@ static const char *nslog_gettime(void)
NSLOG_DEFINE_CATEGORY(netsurf, "NetSurf default logging");
NSLOG_DEFINE_CATEGORY(llcache, "Low level cache");
-NSLOG_DEFINE_CATEGORY(fetch, "objet fetching");
-NSLOG_DEFINE_CATEGORY(plot, "rendering system");
-NSLOG_DEFINE_CATEGORY(schedule, "scheduler");
+NSLOG_DEFINE_CATEGORY(fetch, "Object fetching");
+NSLOG_DEFINE_CATEGORY(plot, "Rendering system");
+NSLOG_DEFINE_CATEGORY(schedule, "Scheduler");
NSLOG_DEFINE_CATEGORY(fbtk, "Framebuffer toolkit");
NSLOG_DEFINE_CATEGORY(layout, "Layout");
+NSLOG_DEFINE_CATEGORY(flex, "Flex");
+NSLOG_DEFINE_CATEGORY(dukky, "Duktape JavaScript Binding");
+NSLOG_DEFINE_CATEGORY(jserrors, "JavaScript error messages");
static void
netsurf_render_log(void *_ctx,
@@ -107,8 +110,11 @@ netsurf_render_log(void *_ctx,
va_list args)
{
fprintf(logfile,
- "%s %.*s:%i %.*s: ",
+ "%s [%s %.*s] %.*s:%i %.*s: ",
nslog_gettime(),
+ nslog_short_level_name(ctx->level),
+ ctx->category->namelen,
+ ctx->category->name,
ctx->filenamelen,
ctx->filename,
ctx->lineno,
@@ -280,7 +286,7 @@ nserror nslog_init(nslog_ensure_t *ensure, int *pargc, char **argv)
/* exported interface documented in utils/log.h */
nserror
-nslog_set_filter_by_options()
+nslog_set_filter_by_options(void)
{
if (verbose_log)
return nslog_set_filter(nsoption_charp(verbose_filter));
@@ -290,7 +296,7 @@ nslog_set_filter_by_options()
/* exported interface documented in utils/log.h */
void
-nslog_finalise()
+nslog_finalise(void)
{
NSLOG(netsurf, INFO,
"Finalising logging, please report any further messages");
diff --git a/utils/log.h b/utils/log.h
index b773ec4a2..b7aa83358 100644
--- a/utils/log.h
+++ b/utils/log.h
@@ -84,6 +84,9 @@ NSLOG_DECLARE_CATEGORY(plot);
NSLOG_DECLARE_CATEGORY(schedule);
NSLOG_DECLARE_CATEGORY(fbtk);
NSLOG_DECLARE_CATEGORY(layout);
+NSLOG_DECLARE_CATEGORY(flex);
+NSLOG_DECLARE_CATEGORY(dukky);
+NSLOG_DECLARE_CATEGORY(jserrors);
#else /* WITH_NSLOG */
diff --git a/utils/messages.c b/utils/messages.c
index e1e61201f..418276ec3 100644
--- a/utils/messages.c
+++ b/utils/messages.c
@@ -42,11 +42,69 @@
/** Messages are stored in a fixed-size hash table. */
#define HASH_SIZE 101
-/** The hash table used to store the standard Messages file for the old API */
+/**
+ * The hash table used to store the standard Messages file for the old API
+ */
static struct hash_table *messages_hash = NULL;
/**
+ * Create a message context
+ *
+ * generate a message context populated with english fallbacks for
+ * some formatted messages.
+ */
+static struct hash_table *messages_create_ctx(int hash_size)
+{
+ struct hash_table *nctx;
+ const struct {
+ const char *key;
+ const char *value;
+ } fallback[] = {
+ { "LoginDescription",
+ "The site %s is requesting your username and password. "
+ "The realm is \"%s\""},
+ { "PrivacyDescription",
+ "A privacy error occurred while communicating with %s this "
+ "may be a site configuration error or an attempt to steal "
+ "private information (passwords, messages or credit cards)"},
+ { "TimeoutDescription",
+ "A connection to %s could not be established. The site may "
+ "be temporarily unavailable or too busy to respond."},
+ { "FetchErrorDescription",
+ "An error occurred when connecting to %s"},
+ { NULL, NULL}
+ };
+ nctx = hash_create(hash_size);
+
+ if (nctx != NULL) {
+ int floop;
+ for (floop = 0; fallback[floop].key != NULL; floop++) {
+ hash_add(nctx,
+ fallback[floop].key,
+ fallback[floop].value);
+ }
+ }
+
+ return nctx;
+}
+
+/**
+ * Free memory used by a messages hash.
+ * The context will not be valid after this function returns.
+ *
+ * \param ctx context of messages file to free
+ */
+static void messages_destroy_ctx(struct hash_table *ctx)
+{
+ if (ctx == NULL)
+ return;
+
+ hash_destroy(ctx);
+}
+
+
+/**
* Read keys and values from messages file.
*
* \param path pathname of messages file
@@ -57,16 +115,16 @@ static nserror messages_load_ctx(const char *path, struct hash_table **ctx)
{
struct hash_table *nctx; /* new context */
nserror res;
-
- if (*ctx == NULL) {
- nctx = hash_create(HASH_SIZE);
- } else {
+
+ if (*ctx != NULL) {
/**
* \note The passed hash is not copied here so this
* updates in place.
*/
- nctx = *ctx;
+ return hash_add_file(*ctx, path);
}
+
+ nctx = messages_create_ctx(HASH_SIZE);
if (nctx == NULL) {
NSLOG(netsurf, INFO,
"Unable to create hash table for messages file %s",
@@ -74,10 +132,11 @@ static nserror messages_load_ctx(const char *path, struct hash_table **ctx)
return NSERROR_NOMEM;
}
-
res = hash_add_file(nctx, path);
if (res == NSERROR_OK) {
*ctx = nctx;
+ } else {
+ hash_destroy(nctx);
}
return res;
@@ -114,21 +173,6 @@ messages_get_ctx(const char *key, struct hash_table *ctx)
}
-/**
- * Free memory used by a messages hash.
- * The context will not be valid after this function returns.
- *
- * \param ctx context of messages file to free
- */
-static void messages_destroy_ctx(struct hash_table *ctx)
-{
- if (ctx == NULL)
- return;
-
- hash_destroy(ctx);
-}
-
-
/* exported interface documented in messages.h */
nserror messages_add_from_file(const char *path)
{
@@ -147,7 +191,7 @@ nserror messages_add_from_inline(const uint8_t *data, size_t size)
{
/* ensure the hash table is initialised */
if (messages_hash == NULL) {
- messages_hash = hash_create(HASH_SIZE);
+ messages_hash = messages_create_ctx(HASH_SIZE);
}
if (messages_hash == NULL) {
NSLOG(netsurf, INFO, "Unable to create hash table");
@@ -156,6 +200,7 @@ nserror messages_add_from_inline(const uint8_t *data, size_t size)
return hash_add_inline(messages_hash, data, size);
}
+
/* exported interface documented in messages.h */
char *messages_get_buff(const char *key, ...)
{
@@ -164,7 +209,17 @@ char *messages_get_buff(const char *key, ...)
int buff_len = 0;
va_list ap;
- msg_fmt = messages_get_ctx(key, messages_hash);
+ assert(key != NULL);
+
+ if (messages_hash == NULL) {
+ return NULL;
+ }
+
+ msg_fmt = hash_get(messages_hash, key);
+
+ if (msg_fmt == NULL) {
+ return NULL;
+ }
va_start(ap, key);
buff_len = vsnprintf(buff, buff_len, msg_fmt, ap);
@@ -320,6 +375,22 @@ const char *messages_get_errorcode(nserror code)
case NSERROR_UNKNOWN:
/* Unknown error */
return messages_get_ctx("Unknown", messages_hash);
+
+ case NSERROR_BAD_AUTH:
+ /* Authentication required */
+ return messages_get_ctx("BadAuth", messages_hash);
+
+ case NSERROR_BAD_REDIRECT:
+ /* To many redirects */
+ return messages_get_ctx("TooManyRedirects", messages_hash);
+
+ case NSERROR_BAD_CERTS:
+ /* Certificate chain verification failure */
+ return messages_get_ctx("CertificateVerificationNeeded", messages_hash);
+
+ case NSERROR_TIMEOUT:
+ /* Operation timed out */
+ return messages_get_ctx("Timeout", messages_hash);
}
/* The switch has no default, so the compiler should tell us when we
@@ -330,6 +401,63 @@ const char *messages_get_errorcode(nserror code)
return messages_get_ctx("Unknown", messages_hash);
}
+/* exported function documented in utils/messages.h */
+const char *messages_get_sslcode(ssl_cert_err code)
+{
+ switch (code) {
+ case SSL_CERT_ERR_OK:
+ /* Nothing wrong with this certificate */
+ return messages_get_ctx("SSLCertErrOk", messages_hash);
+
+ case SSL_CERT_ERR_UNKNOWN:
+ /* Unknown error */
+ return messages_get_ctx("SSLCertErrUnknown", messages_hash);
+
+ case SSL_CERT_ERR_BAD_ISSUER:
+ /* Bad issuer */
+ return messages_get_ctx("SSLCertErrBadIssuer", messages_hash);
+
+ case SSL_CERT_ERR_BAD_SIG:
+ /* Bad signature on this certificate */
+ return messages_get_ctx("SSLCertErrBadSig", messages_hash);
+
+ case SSL_CERT_ERR_TOO_YOUNG:
+ /* This certificate is not yet valid */
+ return messages_get_ctx("SSLCertErrTooYoung", messages_hash);
+
+ case SSL_CERT_ERR_TOO_OLD:
+ /* This certificate is no longer valid */
+ return messages_get_ctx("SSLCertErrTooOld", messages_hash);
+
+ case SSL_CERT_ERR_SELF_SIGNED:
+ /* This certificate is self signed */
+ return messages_get_ctx("SSLCertErrSelfSigned", messages_hash);
+
+ case SSL_CERT_ERR_CHAIN_SELF_SIGNED:
+ /* This certificate chain is self signed */
+ return messages_get_ctx("SSLCertErrChainSelfSigned", messages_hash);
+
+ case SSL_CERT_ERR_REVOKED:
+ /* This certificate has been revoked */
+ return messages_get_ctx("SSLCertErrRevoked", messages_hash);
+
+ case SSL_CERT_ERR_HOSTNAME_MISMATCH:
+ /* Common name is invalid */
+ return messages_get_ctx("SSLCertErrHostnameMismatch", messages_hash);
+
+ case SSL_CERT_ERR_CERT_MISSING:
+ /* Common name is invalid */
+ return messages_get_ctx("SSLCertErrCertMissing", messages_hash);
+
+ }
+
+ /* The switch has no default, so the compiler should tell us when we
+ * forget to add messages for new error codes. As such, we should
+ * never get here.
+ */
+ assert(0);
+ return messages_get_ctx("Unknown", messages_hash);
+}
/* exported function documented in utils/messages.h */
void messages_destroy(void)
@@ -337,4 +465,3 @@ void messages_destroy(void)
messages_destroy_ctx(messages_hash);
messages_hash = NULL;
}
-
diff --git a/utils/messages.h b/utils/messages.h
index 4024f7e77..5da35e4ad 100644
--- a/utils/messages.h
+++ b/utils/messages.h
@@ -16,7 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Localised message support (interface).
*
* The messages module loads a file of keys and associated strings, and
@@ -30,12 +31,13 @@
* file table. Use the _ctx versions of the functions to do this.
*/
-#ifndef _NETSURF_UTILS_MESSAGES_H_
-#define _NETSURF_UTILS_MESSAGES_H_
+#ifndef NETSURF_UTILS_MESSAGES_H_
+#define NETSURF_UTILS_MESSAGES_H_
#include <stdint.h>
#include "utils/errors.h"
+#include "netsurf/ssl_certs.h"
/**
* Read keys and values from messages file into the standard Messages hash.
@@ -79,15 +81,22 @@ const char *messages_get(const char *key);
const char *messages_get_errorcode(nserror code);
/**
+ * lookup of a message by SSL error code from the standard Messages hash.
+ *
+ * \param code ssl error code
+ * \return message text
+ */
+const char *messages_get_sslcode(ssl_cert_err code);
+
+/**
* Formatted message from a key in the global message hash.
*
- * \param key key of message
+ * \param key key of message
* \param ... message parameters
- * \return buffer containing formatted message text or NULL if memory
- * is unavailable. The caller owns the returned buffer and is
- * responsible for freeing it.
+ * \return buffer containing formatted message text or NULL if key is
+ * unavailable or memory allocation failed. The caller owns the
+ * returned buffer and is responsible for freeing it.
*/
-
char *messages_get_buff(const char *key, ...);
/**
diff --git a/utils/nscolour.c b/utils/nscolour.c
new file mode 100644
index 000000000..5a772b8a6
--- /dev/null
+++ b/utils/nscolour.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright 2020 Michael Drake <tlsa@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * NetSurf UI colours (implementation).
+ *
+ * Builds common colours used throughout NetSurf's interface.
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include <stddef.h>
+#include <stdbool.h>
+
+#include "netsurf/inttypes.h"
+#include "netsurf/plot_style.h"
+
+#include "utils/errors.h"
+#include "utils/nscolour.h"
+#include "desktop/system_colour.h"
+
+colour nscolours[NSCOLOUR__COUNT];
+
+/**
+ * Set some colours up from a couple of system colour entries.
+ *
+ * \param[in] name_bg Name of choices string for background colour lookup.
+ * \param[in] name_fg Name of choices string for foreground colour lookup.
+ * \param[in] bg_num Numerator for background adjustment ratio.
+ * \param[in] bg_den Denominator for backfground adjustment ratio.
+ * \param[out] bg Returns the background colour.
+ * \param[out] bg_hover Returns the hovered background colour.
+ * \param[out] fg Returns the foreground colour.
+ * \param[out] fg_subtle Returns the subtle foreground colour.
+ * \param[out] fg_faded Returns the faded foreground colour.
+ * \param[out] fg_good Returns the good foreground colour.
+ * \param[out] fg_bad Returns the bad foreground colour.
+ * \param[out] border Returns the border colour.
+ */
+static nserror nscolour__get(
+ const char *name_bg,
+ const char *name_fg,
+ unsigned bg_num,
+ unsigned bg_den,
+ colour *bg,
+ colour *bg_hover,
+ colour *fg,
+ colour *fg_subtle,
+ colour *fg_faded,
+ colour *fg_good,
+ colour *fg_bad,
+ colour *border)
+{
+ nserror res;
+ bool dark_mode;
+ colour bg_sys;
+
+ assert(name_bg != NULL);
+ assert(name_fg != NULL);
+ assert(bg != NULL);
+ assert(fg != NULL);
+
+ /* user configured background colour */
+ res = ns_system_colour_char(name_bg, &bg_sys);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* user configured foreground colour */
+ res = ns_system_colour_char(name_fg, fg);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* if there is a valid background fraction apply it */
+ if (bg_num < bg_den) {
+ *bg = mix_colour(bg_sys, *fg, 255 * bg_num / bg_den);
+ } else {
+ *bg = bg_sys;
+ }
+
+ dark_mode = colour_lightness(*fg) > colour_lightness(*bg);
+
+ if (bg_hover != NULL) {
+ *bg_hover = dark_mode ?
+ half_lighten_colour(*bg) :
+ half_darken_colour(*bg);
+ }
+
+ if (fg_subtle != NULL) {
+ *fg_subtle = mix_colour(*fg, *bg, 255 * 25 / 32);
+ }
+
+ if (fg_faded != NULL) {
+ *fg_faded = mix_colour(*fg, *bg, 255 * 20 / 32);
+ }
+
+ if (fg_good != NULL) {
+ *fg_good = colour_engorge_component(*fg, !dark_mode,
+ PLOT_COLOUR_COMPONENT_GREEN);
+ }
+
+ if (fg_bad != NULL) {
+ *fg_bad = colour_engorge_component(*fg, !dark_mode,
+ PLOT_COLOUR_COMPONENT_RED);
+ }
+
+ if (border != NULL) {
+ *border = mix_colour(*fg, bg_sys, 255 * 8 / 32);
+ }
+
+ return NSERROR_OK;
+}
+
+/* Exported interface, documented in utils/nscolour.h */
+nserror nscolour_update(void)
+{
+ nserror res;
+
+ res = nscolour__get("Window", "WindowText", 16, 16,
+ &nscolours[NSCOLOUR_WIN_EVEN_BG],
+ &nscolours[NSCOLOUR_WIN_EVEN_BG_HOVER],
+ &nscolours[NSCOLOUR_WIN_EVEN_FG],
+ &nscolours[NSCOLOUR_WIN_EVEN_FG_SUBTLE],
+ &nscolours[NSCOLOUR_WIN_EVEN_FG_FADED],
+ &nscolours[NSCOLOUR_WIN_EVEN_FG_GOOD],
+ &nscolours[NSCOLOUR_WIN_EVEN_FG_BAD],
+ &nscolours[NSCOLOUR_WIN_EVEN_BORDER]);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = nscolour__get("Window", "WindowText", 15, 16,
+ &nscolours[NSCOLOUR_WIN_ODD_BG],
+ &nscolours[NSCOLOUR_WIN_ODD_BG_HOVER],
+ &nscolours[NSCOLOUR_WIN_ODD_FG],
+ &nscolours[NSCOLOUR_WIN_ODD_FG_SUBTLE],
+ &nscolours[NSCOLOUR_WIN_ODD_FG_FADED],
+ &nscolours[NSCOLOUR_WIN_ODD_FG_GOOD],
+ &nscolours[NSCOLOUR_WIN_ODD_FG_BAD],
+ &nscolours[NSCOLOUR_WIN_ODD_BORDER]);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = nscolour__get("Highlight", "HighlightText", 16, 16,
+ &nscolours[NSCOLOUR_SEL_BG],
+ NULL,
+ &nscolours[NSCOLOUR_SEL_FG],
+ &nscolours[NSCOLOUR_SEL_FG_SUBTLE],
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = ns_system_colour_char("Scrollbar",
+ &nscolours[NSCOLOUR_SCROLL_WELL]);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = nscolour__get("ButtonFace", "ButtonText", 16, 16,
+ &nscolours[NSCOLOUR_BUTTON_BG],
+ NULL,
+ &nscolours[NSCOLOUR_BUTTON_FG],
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ nscolours[NSCOLOUR_TEXT_INPUT_BG] =
+ colour_to_bw_nearest(nscolours[NSCOLOUR_WIN_EVEN_BG]);
+ nscolours[NSCOLOUR_TEXT_INPUT_FG] =
+ colour_to_bw_nearest(nscolours[NSCOLOUR_WIN_EVEN_FG]);
+ nscolours[NSCOLOUR_TEXT_INPUT_FG_SUBTLE] =
+ blend_colour(nscolours[NSCOLOUR_TEXT_INPUT_BG],
+ nscolours[NSCOLOUR_TEXT_INPUT_FG]);
+
+ return NSERROR_OK;
+}
+
+/* Exported interface, documented in utils/nscolour.h */
+nserror nscolour_get_stylesheet(const char **stylesheet_out)
+{
+ static char buffer[640];
+ int ret;
+
+ assert(stylesheet_out != NULL);
+
+ ret = snprintf(buffer, sizeof(buffer),
+ ".ns-odd-bg {\n"
+ "\tbackground-color: #%06"PRIx32";\n"
+ "}\n"
+ ".ns-odd-bg-hover {\n"
+ "\tbackground-color: #%06"PRIx32";\n"
+ "}\n"
+ ".ns-odd-fg {\n"
+ "\tcolor: #%06"PRIx32";\n"
+ "}\n"
+ ".ns-odd-fg-subtle {\n"
+ "\tcolor: #%06"PRIx32";\n"
+ "}\n"
+ ".ns-odd-fg-faded {\n"
+ "\tcolor: #%06"PRIx32";\n"
+ "}\n"
+ ".ns-odd-fg-good {\n"
+ "\tcolor: #%06"PRIx32";\n"
+ "}\n"
+ ".ns-odd-fg-bad {\n"
+ "\tcolor: #%06"PRIx32";\n"
+ "}\n"
+ ".ns-even-bg {\n"
+ "\tbackground-color: #%06"PRIx32";\n"
+ "}\n"
+ ".ns-even-bg-hover {\n"
+ "\tbackground-color: #%06"PRIx32";\n"
+ "}\n"
+ ".ns-even-fg {\n"
+ "\tcolor: #%06"PRIx32";\n"
+ "}\n"
+ ".ns-even-fg-subtle {\n"
+ "\tcolor: #%06"PRIx32";\n"
+ "}\n"
+ ".ns-even-fg-faded {\n"
+ "\tcolor: #%06"PRIx32";\n"
+ "}\n"
+ ".ns-even-fg-good {\n"
+ "\tcolor: #%06"PRIx32";\n"
+ "}\n"
+ ".ns-even-fg-bad {\n"
+ "\tcolor: #%06"PRIx32";\n"
+ "}\n"
+ ".ns-border {\n"
+ "\tborder-color: #%06"PRIx32";\n"
+ "}\n",
+ colour_rb_swap(nscolours[NSCOLOUR_WIN_ODD_BG]),
+ colour_rb_swap(nscolours[NSCOLOUR_WIN_ODD_BG_HOVER]),
+ colour_rb_swap(nscolours[NSCOLOUR_WIN_ODD_FG]),
+ colour_rb_swap(nscolours[NSCOLOUR_WIN_ODD_FG_SUBTLE]),
+ colour_rb_swap(nscolours[NSCOLOUR_WIN_ODD_FG_FADED]),
+ colour_rb_swap(nscolours[NSCOLOUR_WIN_ODD_FG_GOOD]),
+ colour_rb_swap(nscolours[NSCOLOUR_WIN_ODD_FG_BAD]),
+ colour_rb_swap(nscolours[NSCOLOUR_WIN_EVEN_BG]),
+ colour_rb_swap(nscolours[NSCOLOUR_WIN_EVEN_BG_HOVER]),
+ colour_rb_swap(nscolours[NSCOLOUR_WIN_EVEN_FG]),
+ colour_rb_swap(nscolours[NSCOLOUR_WIN_EVEN_FG_SUBTLE]),
+ colour_rb_swap(nscolours[NSCOLOUR_WIN_EVEN_FG_FADED]),
+ colour_rb_swap(nscolours[NSCOLOUR_WIN_EVEN_FG_GOOD]),
+ colour_rb_swap(nscolours[NSCOLOUR_WIN_EVEN_FG_BAD]),
+ colour_rb_swap(nscolours[NSCOLOUR_WIN_EVEN_BORDER]));
+ assert(ret > 0 && (size_t)ret < sizeof(buffer));
+ if (ret < 0 || (size_t)ret >= sizeof(buffer)) {
+ /* Error or buffer too small */
+ return NSERROR_NOSPACE;
+ }
+
+ *stylesheet_out = buffer;
+ return NSERROR_OK;
+}
diff --git a/utils/nscolour.h b/utils/nscolour.h
new file mode 100644
index 000000000..855a39806
--- /dev/null
+++ b/utils/nscolour.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2020 Michael Drake <tlsa@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * NetSurf UI colours (interface).
+ *
+ * Interface to acquire common colours used throughout NetSurf's interface.
+ */
+
+#ifndef _NETSURF_UTILS_NSCOLOUR_H_
+#define _NETSURF_UTILS_NSCOLOUR_H_
+
+#include "netsurf/types.h"
+
+/**
+ * NetSurf UI colour key.
+ */
+enum nscolour {
+ NSCOLOUR_WIN_ODD_BG,
+ NSCOLOUR_WIN_ODD_BG_HOVER,
+ NSCOLOUR_WIN_ODD_FG,
+ NSCOLOUR_WIN_ODD_FG_SUBTLE,
+ NSCOLOUR_WIN_ODD_FG_FADED,
+ NSCOLOUR_WIN_ODD_FG_GOOD,
+ NSCOLOUR_WIN_ODD_FG_BAD,
+ NSCOLOUR_WIN_ODD_BORDER,
+ NSCOLOUR_WIN_EVEN_BG,
+ NSCOLOUR_WIN_EVEN_BG_HOVER,
+ NSCOLOUR_WIN_EVEN_FG,
+ NSCOLOUR_WIN_EVEN_FG_SUBTLE,
+ NSCOLOUR_WIN_EVEN_FG_FADED,
+ NSCOLOUR_WIN_EVEN_FG_GOOD,
+ NSCOLOUR_WIN_EVEN_FG_BAD,
+ NSCOLOUR_WIN_EVEN_BORDER,
+ NSCOLOUR_TEXT_INPUT_BG,
+ NSCOLOUR_TEXT_INPUT_FG,
+ NSCOLOUR_TEXT_INPUT_FG_SUBTLE,
+ NSCOLOUR_SEL_BG,
+ NSCOLOUR_SEL_FG,
+ NSCOLOUR_SEL_FG_SUBTLE,
+ NSCOLOUR_SCROLL_WELL,
+ NSCOLOUR_BUTTON_BG,
+ NSCOLOUR_BUTTON_FG,
+ NSCOLOUR__COUNT,
+};
+
+/**
+ * NetSurf UI colour table.
+ */
+extern colour nscolours[];
+
+/**
+ * Update the nscolour table from the current nsoptions.
+ *
+ * \return NSERROR_OK on success, or appropriate error otherwise.
+ */
+nserror nscolour_update(void);
+
+/**
+ * Get a pointer to a stylesheet for nscolours.
+ *
+ * \return NSERROR_OK on success, or appropriate error otherwise.
+ */
+nserror nscolour_get_stylesheet(const char **stylesheet_out);
+
+#endif
diff --git a/utils/nsoption.c b/utils/nsoption.c
index 09529a0d0..7306dee1b 100644
--- a/utils/nsoption.c
+++ b/utils/nsoption.c
@@ -32,6 +32,7 @@
#include <string.h>
#include <strings.h>
+#include "netsurf/inttypes.h"
#include "netsurf/plot_style.h"
#include "utils/errors.h"
#include "utils/log.h"
@@ -112,7 +113,7 @@ strtooption(const char *value, struct nsoption_s *option)
break;
case OPTION_COLOUR:
- if (sscanf(value, "%x", &rgbcolour) == 1) {
+ if (sscanf(value, "%"SCNx32"", &rgbcolour) == 1) {
option->value.c = (((0x000000FF & rgbcolour) << 16) |
((0x0000FF00 & rgbcolour) << 0) |
((0x00FF0000 & rgbcolour) >> 16));
@@ -323,7 +324,7 @@ nsoption_output(FILE *fp,
rgbcolour = (((0x000000FF & opts[entry].value.c) << 16) |
((0x0000FF00 & opts[entry].value.c) << 0) |
((0x00FF0000 & opts[entry].value.c) >> 16));
- fprintf(fp, "%s:%06x\n",
+ fprintf(fp, "%s:%06"PRIx32"\n",
opts[entry].key,
rgbcolour);
@@ -383,17 +384,20 @@ nsoption_output_value_html(struct nsoption_s *option,
break;
case OPTION_COLOUR:
- rgbcolour = (((0x000000FF & option->value.c) << 16) |
- ((0x0000FF00 & option->value.c) << 0) |
- ((0x00FF0000 & option->value.c) >> 16));
+ rgbcolour = colour_rb_swap(option->value.c);
slen = snprintf(string + pos,
size - pos,
- "<span style=\"background-color: #%06x; "
- "color: #%06x; "
- "font-family:Monospace; \">#%06X</span>",
+ "<span style=\"font-family:Monospace;\">"
+ "#%06"PRIX32
+ "</span> "
+ "<span style=\"background-color: #%06"PRIx32"; "
+ "border: 1px solid #%06"PRIx32"; "
+ "display: inline-block; "
+ "width: 1em; height: 1em;\">"
+ "</span>",
rgbcolour,
- colour_to_bw_furthest(rgbcolour),
- rgbcolour);
+ rgbcolour,
+ colour_to_bw_furthest(rgbcolour));
break;
case OPTION_STRING:
@@ -456,7 +460,7 @@ nsoption_output_value_text(struct nsoption_s *option,
rgbcolour = (((0x000000FF & option->value.c) << 16) |
((0x0000FF00 & option->value.c) << 0) |
((0x00FF0000 & option->value.c) >> 16));
- slen = snprintf(string + pos, size - pos, "%06x", rgbcolour);
+ slen = snprintf(string + pos, size - pos, "%06"PRIx32, rgbcolour);
break;
case OPTION_STRING:
@@ -537,6 +541,89 @@ nsoption_free(struct nsoption_s *opts)
}
+/**
+ * extract key/value from a line of input
+ *
+ * \retun NSERROR_OK and key_out and value_out updated
+ * NSERROR_NOT_FOUND if not a key/value input line
+ * NSERROR_INVALID if the line is and invalid format (missing colon)
+ */
+static nserror
+get_key_value(char *line, int linelen, char **key_out, char **value_out)
+{
+ char *key;
+ char *value;
+
+ /* skip leading whitespace for start of key */
+ for (key = line; *key != 0; key++) {
+ if ((*key != ' ') && (*key != '\t') && (*key != '\n')) {
+ break;
+ }
+ }
+
+ /* empty line or only whitespace */
+ if (*key == 0) {
+ return NSERROR_NOT_FOUND;
+ }
+
+ /* comment */
+ if (*key == '#') {
+ return NSERROR_NOT_FOUND;
+ }
+
+ /* get start of value */
+ for (value = key; *value != 0; value++) {
+ if (*value == ':') {
+ *value = 0;
+ value++;
+ break;
+ }
+ }
+
+ /* missing colon separator */
+ if (*value == 0) {
+ return NSERROR_INVALID;
+ }
+
+ /* remove delimiter from value */
+ if (line[linelen - 1] == '\n') {
+ linelen--;
+ line[linelen] = 0;
+ }
+
+ *key_out = key;
+ *value_out = value;
+ return NSERROR_OK;
+}
+
+
+/**
+ * Process a line from a user option file
+ */
+static nserror optionline(struct nsoption_s *opts, char *line, int linelen)
+{
+ nserror res;
+ char *key;
+ char *value;
+ int idx;
+
+ res = get_key_value(line, linelen, &key, &value);
+ if (res != NSERROR_OK) {
+ /* skip line as no valid key value pair found */
+ return res;
+ }
+
+ for (idx = 0; opts[idx].key != NULL; idx++) {
+ if (strcasecmp(key, opts[idx].key) == 0) {
+ strtooption(value, &opts[idx]);
+ break;
+ }
+ }
+
+ return res;
+}
+
+
/* exported interface documented in utils/nsoption.h */
nserror
nsoption_init(nsoption_set_default_t *set_defaults,
@@ -642,7 +729,9 @@ nsoption_read(const char *path, struct nsoption_s *opts)
opts = nsoptions;
}
- /** @todo is this and API bug not being a parameter */
+ /**
+ * @todo is this an API bug not being a parameter
+ */
defs = nsoptions_default;
if ((opts == NULL) || (defs == NULL)) {
@@ -655,34 +744,10 @@ nsoption_read(const char *path, struct nsoption_s *opts)
return NSERROR_NOT_FOUND;
}
- NSLOG(netsurf, INFO, "Successfully opened '%s' for Options file",
- path);
+ NSLOG(netsurf, INFO, "Successfully opened '%s' for Options file", path);
while (fgets(s, NSOPTION_MAX_LINE_LEN, fp)) {
- char *colon, *value;
- unsigned int idx;
-
- if ((s[0] == 0) || (s[0] == '#')) {
- continue;
- }
-
- colon = strchr(s, ':');
- if (colon == 0) {
- continue;
- }
-
- s[strlen(s) - 1] = 0; /* remove \n at end */
- *colon = 0; /* terminate key */
- value = colon + 1;
-
- for (idx = 0; opts[idx].key != NULL; idx++) {
- if (strcasecmp(s, opts[idx].key) != 0) {
- continue;
- }
-
- strtooption(value, &opts[idx]);
- break;
- }
+ optionline(opts, s, strlen(s));
}
fclose(fp);
diff --git a/utils/nsurl.h b/utils/nsurl.h
index 054baf26b..fcae12e0c 100644
--- a/utils/nsurl.h
+++ b/utils/nsurl.h
@@ -30,6 +30,16 @@
/** NetSurf URL object */
typedef struct nsurl nsurl;
+/** A type for URL schemes */
+enum nsurl_scheme_type {
+ NSURL_SCHEME_OTHER,
+ NSURL_SCHEME_HTTP,
+ NSURL_SCHEME_HTTPS,
+ NSURL_SCHEME_FILE,
+ NSURL_SCHEME_FTP,
+ NSURL_SCHEME_MAILTO,
+ NSURL_SCHEME_DATA
+};
typedef enum nsurl_component {
NSURL_SCHEME = (1 << 0),
@@ -146,6 +156,15 @@ lwc_string *nsurl_get_component(const nsurl *url, nsurl_component part);
/**
+ * Get the scheme type from a NetSurf URL object
+ *
+ * \param url NetSurf URL object
+ * \return The URL scheme type.
+ */
+enum nsurl_scheme_type nsurl_get_scheme_type(const nsurl *url);
+
+
+/**
* Enquire about the existence of componenets in a given URL
*
* \param url NetSurf URL object
@@ -181,6 +200,24 @@ const char *nsurl_access(const nsurl *url);
/**
+ * Variant of \ref nsurl_access for logging.
+ *
+ * \param url NetSurf URL to retrieve a string pointer for.
+ * \return the required string
+ *
+ * This will not necessarily return the actual nsurl's URL, but something
+ * that is suitable for recording to logs. E.g. URLs with the `data` scheme
+ * will return a simple place holder, to avoid repeatedly dumping loads of data.
+ *
+ * The returned string is owned by the NetSurf URL object. It will die
+ * with the NetSurf URL object. Keep a reference to the URL if you need it.
+ *
+ * The returned string has a trailing '\0'.
+ */
+const char *nsurl_access_log(const nsurl *url);
+
+
+/**
* Get a UTF-8 string (for human readable IDNs) from a NetSurf URL object
*
* \param url NetSurf URL object
@@ -295,6 +332,9 @@ nserror nsurl_refragment(const nsurl *url, lwc_string *frag, nsurl **new_url);
* the created object.
*
* Any query component in url is replaced with query in new_url.
+ *
+ * Passing the empty string as a replacement will result in the query
+ * component being removed.
*/
nserror nsurl_replace_query(const nsurl *url, const char *query,
nsurl **new_url);
@@ -348,4 +388,14 @@ nserror nsurl_nice(const nsurl *url, char **result, bool remove_extensions);
*/
nserror nsurl_parent(const nsurl *url, nsurl **new_url);
+/**
+ * Dump a NetSurf URL's internal components to stderr
+ *
+ * This is helper functionality for developers, and shouldn't be called
+ * generally.
+ *
+ * \param url The NetSurf URL to dump components of
+ */
+void nsurl_dump(const nsurl *url);
+
#endif
diff --git a/utils/nsurl/nsurl.c b/utils/nsurl/nsurl.c
index 8c769cfff..63619af15 100644
--- a/utils/nsurl/nsurl.c
+++ b/utils/nsurl/nsurl.c
@@ -36,6 +36,7 @@
#include <stdlib.h>
#include <string.h>
#include <strings.h>
+#include <inttypes.h>
#include "utils/ascii.h"
#include "utils/corestrings.h"
@@ -54,7 +55,7 @@
* Does nothing if the components are the same, so ensure match is
* preset to true.
*/
-#define nsurl__component_compare(c1, c2, match) \
+#define nsurl__component_compare(c1, c2, match) \
if (c1 && c2 && lwc_error_ok == \
lwc_string_isequal(c1, c2, match)) { \
/* do nothing */ \
@@ -88,10 +89,6 @@ void nsurl_unref(nsurl *url)
if (--url->count > 0)
return;
-#ifdef NSURL_DEBUG
- nsurl__dump(url);
-#endif
-
/* Release lwc strings */
nsurl__components_destroy(&url->components);
@@ -240,6 +237,15 @@ lwc_string *nsurl_get_component(const nsurl *url, nsurl_component part)
/* exported interface, documented in nsurl.h */
+enum nsurl_scheme_type nsurl_get_scheme_type(const nsurl *url)
+{
+ assert(url != NULL);
+
+ return url->components.scheme_type;
+}
+
+
+/* exported interface, documented in nsurl.h */
bool nsurl_has_component(const nsurl *url, nsurl_component part)
{
assert(url != NULL);
@@ -316,6 +322,19 @@ const char *nsurl_access(const nsurl *url)
/* exported interface, documented in nsurl.h */
+const char *nsurl_access_log(const nsurl *url)
+{
+ assert(url != NULL);
+
+ if (url->components.scheme_type == NSURL_SCHEME_DATA) {
+ return "[data url]";
+ }
+
+ return url->string;
+}
+
+
+/* exported interface, documented in nsurl.h */
nserror nsurl_get_utf8(const nsurl *url, char **url_s, size_t *url_l)
{
nserror err;
@@ -355,7 +374,7 @@ nserror nsurl_get_utf8(const nsurl *url, char **url_s, size_t *url_l)
}
*url_l = scheme_len + idna_host_len + path_len + 1; /* +1 for \0 */
- *url_s = malloc(*url_l);
+ *url_s = malloc(*url_l);
if (*url_s == NULL) {
err = NSERROR_NOMEM;
@@ -565,57 +584,67 @@ nserror nsurl_refragment(const nsurl *url, lwc_string *frag, nsurl **new_url)
nserror nsurl_replace_query(const nsurl *url, const char *query,
nsurl **new_url)
{
- int query_len; /* Length of new query string, including '?' */
- int frag_len = 0; /* Length of fragment, including '#' */
- int base_len; /* Length of URL up to start of query */
- char *pos;
- size_t len;
- lwc_string *lwc_query;
+ int query_len; /* Length of new query string excluding '?' */
+ int frag_len = 0; /* Length of fragment, excluding '#' */
+ int base_len; /* Length of URL up to start of query */
+ char *pos; /* current position in output string */
+ size_t length; /* new url string length */
+ lwc_string *lwc_query = NULL;
assert(url != NULL);
assert(query != NULL);
- assert(query[0] == '?');
- /* Get the length of the new query */
- query_len = strlen(query);
+ length = query_len = strlen(query);
+ if (query_len > 0) {
+ length++; /* allow for '?' */
+
+ /* intern string */
+ if (lwc_intern_string(query,
+ query_len,
+ &lwc_query) != lwc_error_ok) {
+ return NSERROR_NOMEM;
+ }
+ }
/* Find the change in length from url to new_url */
base_len = url->length;
if (url->components.query != NULL) {
- base_len -= lwc_string_length(url->components.query);
+ base_len -= (1 + lwc_string_length(url->components.query));
}
if (url->components.fragment != NULL) {
- frag_len = 1 + lwc_string_length(url->components.fragment);
- base_len -= frag_len;
+ frag_len = lwc_string_length(url->components.fragment);
+ base_len -= (1 + frag_len);
+ length += frag_len + 1; /* allow for '#' */
}
- /* Set new_url's length */
- len = base_len + query_len + frag_len;
+ /* compute new url string length */
+ length += base_len;
/* Create NetSurf URL object */
- *new_url = malloc(sizeof(nsurl) + len + 1); /* Add 1 for \0 */
+ *new_url = malloc(sizeof(nsurl) + length + 1); /* Add 1 for \0 */
if (*new_url == NULL) {
+ if (query_len > 0) {
+ lwc_string_unref(lwc_query);
+ }
return NSERROR_NOMEM;
}
- if (lwc_intern_string(query, query_len, &lwc_query) != lwc_error_ok) {
- free(*new_url);
- return NSERROR_NOMEM;
- }
-
- (*new_url)->length = len;
+ (*new_url)->length = length;
/* Set string */
pos = (*new_url)->string;
memcpy(pos, url->string, base_len);
pos += base_len;
- memcpy(pos, query, query_len);
- pos += query_len;
+ if (query_len > 0) {
+ *pos = '?';
+ memcpy(++pos, query, query_len);
+ pos += query_len;
+ }
if (url->components.fragment != NULL) {
const char *frag = lwc_string_data(url->components.fragment);
*pos = '#';
- memcpy(++pos, frag, frag_len - 1);
- pos += frag_len - 1;
+ memcpy(++pos, frag, frag_len);
+ pos += frag_len;
}
*pos = '\0';
@@ -896,7 +925,7 @@ nserror nsurl_parent(const nsurl *url, nsurl **new_url)
} else if (old_path_len == new_path_len) {
lwc_path = lwc_string_ref(url->components.path);
} else {
- if (lwc_intern_string(path, old_path_len - new_path_len,
+ if (lwc_intern_string(path, new_path_len,
&lwc_path) != lwc_error_ok) {
free(*new_url);
return NSERROR_NOMEM;
@@ -937,3 +966,35 @@ nserror nsurl_parent(const nsurl *url, nsurl **new_url)
return NSERROR_OK;
}
+/* exported interface, documented in nsurl.h */
+void nsurl_dump(const nsurl *url)
+{
+ fprintf(stderr, "nsurl components for %p "
+ "(refs: %i hash: %"PRIx32"):\n",
+ url, url->count, url->hash);
+
+ if (url->components.scheme)
+ fprintf(stderr, " Scheme: %s\n",
+ lwc_string_data(url->components.scheme));
+ if (url->components.username)
+ fprintf(stderr, "Username: %s\n",
+ lwc_string_data(url->components.username));
+ if (url->components.password)
+ fprintf(stderr, "Password: %s\n",
+ lwc_string_data(url->components.password));
+ if (url->components.host)
+ fprintf(stderr, " Host: %s\n",
+ lwc_string_data(url->components.host));
+ if (url->components.port)
+ fprintf(stderr, " Port: %s\n",
+ lwc_string_data(url->components.port));
+ if (url->components.path)
+ fprintf(stderr, " Path: %s\n",
+ lwc_string_data(url->components.path));
+ if (url->components.query)
+ fprintf(stderr, " Query: %s\n",
+ lwc_string_data(url->components.query));
+ if (url->components.fragment)
+ fprintf(stderr, "Fragment: %s\n",
+ lwc_string_data(url->components.fragment));
+}
diff --git a/utils/nsurl/parse.c b/utils/nsurl/parse.c
index ce6f4435d..dbf0c6e2c 100644
--- a/utils/nsurl/parse.c
+++ b/utils/nsurl/parse.c
@@ -37,6 +37,8 @@
#include <string.h>
#include <strings.h>
+#include "netsurf/inttypes.h"
+
#include "utils/ascii.h"
#include "utils/corestrings.h"
#include "utils/errors.h"
@@ -302,6 +304,16 @@ static void nsurl__get_string_markers(const char * const url_s,
((*(pos - off + 5) == 'o') ||
(*(pos - off + 5) == 'O')))) {
marker.scheme_type = NSURL_SCHEME_MAILTO;
+ } else if (off == SLEN("data") &&
+ (((*(pos - off + 0) == 'd') ||
+ (*(pos - off + 0) == 'D')) &&
+ ((*(pos - off + 1) == 'a') ||
+ (*(pos - off + 1) == 'A')) &&
+ ((*(pos - off + 2) == 't') ||
+ (*(pos - off + 2) == 'T')) &&
+ ((*(pos - off + 3) == 'a') ||
+ (*(pos - off + 3) == 'A')))) {
+ marker.scheme_type = NSURL_SCHEME_DATA;
}
/* Skip over colon */
@@ -332,7 +344,7 @@ static void nsurl__get_string_markers(const char * const url_s,
* and in the case of mailto: when we assume there is an authority.
*/
if ((*pos == '/' && *(pos + 1) == '/') ||
- (is_http && ((joining && *pos == '/') ||
+ (is_http && ((joining && *pos == '/') ||
(joining == false &&
marker.scheme_end != marker.start))) ||
marker.scheme_type == NSURL_SCHEME_MAILTO) {
@@ -450,21 +462,29 @@ static void nsurl__get_string_markers(const char * const url_s,
marker.fragment = marker.end;
}
-#ifdef NSURL_DEBUG
- NSLOG(netsurf, INFO, "marker.start: %i", marker.start);
- NSLOG(netsurf, INFO, "marker.scheme_end: %i", marker.scheme_end);
- NSLOG(netsurf, INFO, "marker.authority: %i", marker.authority);
-
- NSLOG(netsurf, INFO, "marker.colon_first: %i", marker.colon_first);
- NSLOG(netsurf, INFO, "marker.at: %i", marker.at);
- NSLOG(netsurf, INFO, "marker.colon_last: %i", marker.colon_last);
-
- NSLOG(netsurf, INFO, "marker.path: %i", marker.path);
- NSLOG(netsurf, INFO, "marker.query: %i", marker.query);
- NSLOG(netsurf, INFO, "marker.fragment: %i", marker.fragment);
-
- NSLOG(netsurf, INFO, "marker.end: %i", marker.end);
-#endif
+ NSLOG(netsurf, DEEPDEBUG,
+ "marker.start: %"PRIsizet, marker.start);
+ NSLOG(netsurf, DEEPDEBUG,
+ "marker.scheme_end: %"PRIsizet, marker.scheme_end);
+ NSLOG(netsurf, DEEPDEBUG,
+ "marker.authority: %"PRIsizet, marker.authority);
+
+ NSLOG(netsurf, DEEPDEBUG,
+ "marker.colon_first: %"PRIsizet, marker.colon_first);
+ NSLOG(netsurf, DEEPDEBUG,
+ "marker.at: %"PRIsizet, marker.at);
+ NSLOG(netsurf, DEEPDEBUG,
+ "marker.colon_last: %"PRIsizet, marker.colon_last);
+
+ NSLOG(netsurf, DEEPDEBUG,
+ "marker.path: %"PRIsizet, marker.path);
+ NSLOG(netsurf, DEEPDEBUG,
+ "marker.query: %"PRIsizet, marker.query);
+ NSLOG(netsurf, DEEPDEBUG,
+ "marker.fragment: %"PRIsizet, marker.fragment);
+
+ NSLOG(netsurf, DEEPDEBUG,
+ "marker.end: %"PRIsizet, marker.end);
/* Got all the URL components pegged out now */
*markers = marker;
@@ -484,10 +504,10 @@ static size_t nsurl__remove_dot_segments(char *path, char *output)
char *output_pos = output;
while (*path_pos != '\0') {
-#ifdef NSURL_DEBUG
- NSLOG(netsurf, INFO, " in:%s", path_pos);
- NSLOG(netsurf, INFO, "out:%.*s", output_pos - output, output);
-#endif
+ NSLOG(netsurf, DEEPDEBUG, " in:%s", path_pos);
+ NSLOG(netsurf, DEEPDEBUG, "out:%.*s",
+ (int)(output_pos - output), output);
+
if (*path_pos == '.') {
if (*(path_pos + 1) == '.' &&
*(path_pos + 2) == '/') {
@@ -557,7 +577,7 @@ static size_t nsurl__remove_dot_segments(char *path, char *output)
/* Copy up to but not including next '/' */
while ((*path_pos != '/') && (*path_pos != '\0'))
- *output_pos++ = *path_pos++;
+ *output_pos++ = *path_pos++;
}
return output_pos - output;
@@ -651,7 +671,9 @@ static nserror nsurl__create_from_section(const char * const url_s,
break;
case URL_QUERY:
- start = pegs->query;
+ start = (*(url_s + pegs->query) != '?') ?
+ pegs->query :
+ pegs->query + 1;
end = pegs->fragment;
break;
@@ -1065,6 +1087,15 @@ static void nsurl__get_string_data(const struct nsurl_components *url,
*url_l += SLEN("@");
}
+ /* spanned query question mark */
+ if ((flags & ~(NSURL_F_QUERY | NSURL_F_FRAGMENT)) &&
+ (flags & NSURL_F_QUERY)) {
+ flags |= NSURL_F_QUERY_PUNCTUATION;
+
+ *url_l += SLEN("?");
+ }
+
+ /* spanned fragment hash mark */
if ((flags & ~NSURL_F_FRAGMENT) && (flags & NSURL_F_FRAGMENT)) {
flags |= NSURL_F_FRAGMENT_PUNCTUATION;
@@ -1138,6 +1169,8 @@ static void nsurl__get_string(const struct nsurl_components *url, char *url_s,
}
if (flags & NSURL_F_QUERY) {
+ if (flags & NSURL_F_QUERY_PUNCTUATION)
+ *(pos++) = '?';
memcpy(pos, lwc_string_data(url->query), l->query);
pos += l->query;
}
@@ -1283,7 +1316,7 @@ nserror nsurl_create(const char * const url_s, nsurl **url)
}
e = nsurl__components_to_string(&c, NSURL_WITH_FRAGMENT,
- sizeof(nsurl), (char **)url, &length);
+ offsetof(nsurl, string), (char **)url, &length);
if (e != NSERROR_OK) {
return e;
}
@@ -1323,10 +1356,8 @@ nserror nsurl_join(const nsurl *base, const char *rel, nsurl **joined)
assert(base != NULL);
assert(rel != NULL);
-#ifdef NSURL_DEBUG
- NSLOG(netsurf, INFO, "base: \"%s\", rel: \"%s\"", nsurl_access(base),
- rel);
-#endif
+ NSLOG(netsurf, DEEPDEBUG, "base: \"%s\", rel: \"%s\"",
+ nsurl_access(base), rel);
/* Peg out the URL sections */
nsurl__get_string_markers(rel, &m, true);
@@ -1523,7 +1554,7 @@ nserror nsurl_join(const nsurl *base, const char *rel, nsurl **joined)
}
error = nsurl__components_to_string(&c, NSURL_WITH_FRAGMENT,
- sizeof(nsurl), (char **)joined, &length);
+ offsetof(nsurl, string), (char **)joined, &length);
if (error != NSERROR_OK) {
return error;
}
@@ -1539,4 +1570,3 @@ nserror nsurl_join(const nsurl *base, const char *rel, nsurl **joined)
return NSERROR_OK;
}
-
diff --git a/utils/nsurl/private.h b/utils/nsurl/private.h
index bc6737cd6..b099a451c 100644
--- a/utils/nsurl/private.h
+++ b/utils/nsurl/private.h
@@ -25,21 +25,6 @@
#include "utils/utils.h"
-/* Define to enable NSURL debugging */
-#undef NSURL_DEBUG
-
-
-/** A type for URL schemes */
-enum nsurl_scheme_type {
- NSURL_SCHEME_OTHER,
- NSURL_SCHEME_HTTP,
- NSURL_SCHEME_HTTPS,
- NSURL_SCHEME_FILE,
- NSURL_SCHEME_FTP,
- NSURL_SCHEME_MAILTO
-};
-
-
/**
* nsurl components
*
@@ -108,9 +93,10 @@ enum nsurl_string_flags {
NSURL_F_HOST |
NSURL_F_PORT),
NSURL_F_PATH = (1 << 8),
- NSURL_F_QUERY = (1 << 9),
- NSURL_F_FRAGMENT_PUNCTUATION = (1 << 10),
- NSURL_F_FRAGMENT = (1 << 11)
+ NSURL_F_QUERY_PUNCTUATION = (1 << 9),
+ NSURL_F_QUERY = (1 << 10),
+ NSURL_F_FRAGMENT_PUNCTUATION = (1 << 11),
+ NSURL_F_FRAGMENT = (1 << 12)
};
/**
@@ -176,57 +162,4 @@ static inline void nsurl__components_destroy(struct nsurl_components *c)
lwc_string_unref(c->fragment);
}
-
-
-#ifdef NSURL_DEBUG
-/**
- * Dump a NetSurf URL's internal components
- *
- * \param url The NetSurf URL to dump components of
- */
-static inline void nsurl__dump(const nsurl *url)
-{
- if (url->components.scheme)
- NSLOG(netsurf, INFO,netsurf, INFO,
- " Scheme: %s",
- lwc_string_data(url->components.scheme));
-
- if (url->components.username)
- NSLOG(netsurf, INFO,
- "Username: %s",
- lwc_string_data(url->components.username));
-
- if (url->components.password)
- NSLOG(netsurf, INFO,
- "Password: %s",
- lwc_string_data(url->components.password));
-
- if (url->components.host)
- NSLOG(netsurf, INFO,
- " Host: %s",
- lwc_string_data(url->components.host));
-
- if (url->components.port)
- NSLOG(netsurf, INFO,
- " Port: %s",
- lwc_string_data(url->components.port));
-
- if (url->components.path)
- NSLOG(netsurf, INFO,
- " Path: %s",
- lwc_string_data(url->components.path));
-
- if (url->components.query)
- NSLOG(netsurf, INFO,
- " Query: %s",
- lwc_string_data(url->components.query));
-
- if (url->components.fragment)
- NSLOG(netsurf, INFO,
- "Fragment: %s",
- lwc_string_data(url->components.fragment));
-}
-#endif
-
-
#endif
diff --git a/utils/regex.h b/utils/regex.h
new file mode 100644
index 000000000..a415239d6
--- /dev/null
+++ b/utils/regex.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019 Vincent Sanders <vince@netxurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETSURF_UTILS_REGEX_H_
+#define NETSURF_UTILS_REGEX_H_
+
+#include "utils/config.h"
+
+#ifdef HAVE_REGEX
+#include <sys/types.h>
+#include <regex.h>
+#else
+
+#define REG_NOMATCH 1
+
+#define REG_EXTENDED 1
+#define REG_ICASE (1 << 1)
+#define REG_NEWLINE (1 << 2)
+#define REG_NOSUB (1 << 3)
+
+typedef ssize_t regoff_t;
+
+typedef struct {
+ size_t re_nsub; /* Number of parenthesized subexpressions.*/
+} regex_t;
+
+
+typedef struct {
+ regoff_t rm_so; /* Byte offset from start of string to start
+ * of substring.
+ */
+ regoff_t rm_eo; /* Byte offset from start of string of the
+ * first character after the end of substring.
+ */
+} regmatch_t;
+
+
+int regcomp(regex_t *restrict preg, const char *restrictregex, int cflags);
+
+size_t regerror(int errorcode, const regex_t *restrict preg, char *restrict errbuf, size_t errbuf_size);
+
+int regexec(const regex_t *restrict preg, const char *restrict string, size_t nmatch, regmatch_t pmatch[restrict], int eflags);
+
+void regfree(regex_t *preg);
+
+#endif
+
+#endif
diff --git a/utils/ring.h b/utils/ring.h
index 1802b4484..55880a695 100644
--- a/utils/ring.h
+++ b/utils/ring.h
@@ -66,24 +66,6 @@
/** Find the element (by hostname) in the given ring, leave it in the
* provided element variable
*/
-#define RING_FINDBYHOST(ring, element, hostname) \
- /*LOG("RING_FINDBYHOST(%s, %s)", #ring, hostname);*/ \
- if (ring) { \
- bool found = false; \
- element = ring; \
- do { \
- if (strcasecmp(element->host, hostname) == 0) { \
- found = true; \
- break; \
- } \
- element = element->r_next; \
- } while (element != ring); \
- if (!found) element = 0; \
- } else element = 0
-
-/** Find the element (by hostname) in the given ring, leave it in the
- * provided element variable
- */
#define RING_FINDBYLWCHOST(ring, element, lwc_hostname) \
/*LOG("RING_FINDBYHOST(%s, %s)", #ring, hostname);*/ \
if (ring) { \
@@ -112,19 +94,6 @@
} while (p != ring); \
} else sizevar = 0
-/** Count the number of elements in the ring which match the provided hostname */
-#define RING_COUNTBYHOST(ringtype, ring, sizevar, hostname) \
- /*LOG("RING_COUNTBYHOST(%s, %s)", #ring, hostname);*/ \
- if (ring) { \
- ringtype *p = ring; \
- sizevar = 0; \
- do { \
- if (strcasecmp(p->host, hostname) == 0) \
- sizevar++; \
- p = p->r_next; \
- } while (p != ring); \
- } else sizevar = 0
-
/** Count the number of elements in the ring which match the provided lwc_hostname */
#define RING_COUNTBYLWCHOST(ringtype, ring, sizevar, lwc_hostname) \
/*LOG("RING_COUNTBYHOST(%s, %s)", #ring, hostname);*/ \
@@ -136,7 +105,7 @@
/* nsurl guarantees lowercase host */ \
if (lwc_string_isequal(p->host, lwc_hostname, \
&matches) == lwc_error_ok) \
- if (matches) \
+ if (matches) \
sizevar++; \
p = p->r_next; \
} while (p != ring); \
diff --git a/utils/ssl_certs.c b/utils/ssl_certs.c
new file mode 100644
index 000000000..8546165ac
--- /dev/null
+++ b/utils/ssl_certs.c
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2020 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * helpers for X509 certificate chains
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <nsutils/base64.h>
+
+#include "utils/errors.h"
+#include "utils/log.h"
+#include "utils/nsurl.h"
+
+#include "netsurf/ssl_certs.h"
+
+/*
+ * create new certificate chain
+ *
+ * exported interface documented in netsurf/ssl_certs.h
+ */
+nserror
+cert_chain_alloc(size_t depth, struct cert_chain **chain_out)
+{
+ struct cert_chain* chain;
+
+ chain = calloc(1, sizeof(struct cert_chain));
+ if (chain == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ chain->depth = depth;
+
+ *chain_out = chain;
+
+ return NSERROR_OK;
+}
+
+
+/*
+ * duplicate certificate chain into existing chain
+ *
+ * exported interface documented in netsurf/ssl_certs.h
+ */
+nserror
+cert_chain_dup_into(const struct cert_chain *src, struct cert_chain *dst)
+{
+ size_t depth;
+ for (depth = 0; depth < dst->depth; depth++) {
+ if (dst->certs[depth].der != NULL) {
+ free(dst->certs[depth].der);
+ dst->certs[depth].der = NULL;
+ }
+ }
+
+ dst->depth = src->depth;
+
+ for (depth = 0; depth < src->depth; depth++) {
+ dst->certs[depth].err = src->certs[depth].err;
+ dst->certs[depth].der_length = src->certs[depth].der_length;
+ if (src->certs[depth].der != NULL) {
+ dst->certs[depth].der = malloc(src->certs[depth].der_length);
+ if (dst->certs[depth].der == NULL) {
+ return NSERROR_NOMEM;
+ }
+ memcpy(dst->certs[depth].der,
+ src->certs[depth].der,
+ src->certs[depth].der_length);
+ }
+
+ }
+
+ return NSERROR_OK;
+}
+
+
+/*
+ * duplicate certificate chain
+ *
+ * exported interface documented in netsurf/ssl_certs.h
+ */
+nserror
+cert_chain_dup(const struct cert_chain *src, struct cert_chain **dst_out)
+{
+ struct cert_chain* dst;
+ size_t depth;
+ nserror res;
+
+ res = cert_chain_alloc(src->depth, &dst);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ for (depth = 0; depth < src->depth; depth++) {
+ dst->certs[depth].err = src->certs[depth].err;
+ dst->certs[depth].der_length = src->certs[depth].der_length;
+ if (src->certs[depth].der != NULL) {
+ dst->certs[depth].der = malloc(src->certs[depth].der_length);
+ if (dst->certs[depth].der == NULL) {
+ cert_chain_free(dst);
+ return NSERROR_NOMEM;
+ }
+ memcpy(dst->certs[depth].der,
+ src->certs[depth].der,
+ src->certs[depth].der_length);
+ }
+
+ }
+
+ *dst_out = dst;
+ return NSERROR_OK;
+}
+
+
+#define MIN_CERT_LEN 64
+
+/**
+ * process a part of a query extracting the certificate of an error code
+ */
+static nserror
+process_query_section(const char *str, size_t len, struct cert_chain* chain)
+{
+ nsuerror nsures;
+
+ if ((len > (5 + MIN_CERT_LEN)) &&
+ (strncmp(str, "cert=", 5) == 0)) {
+ /* possible certificate entry */
+ nsures = nsu_base64_decode_alloc_url(
+ (const uint8_t *)str + 5,
+ len - 5,
+ &chain->certs[chain->depth].der,
+ &chain->certs[chain->depth].der_length);
+ if (nsures == NSUERROR_OK) {
+ chain->depth++;
+ }
+ } else if ((len > 8) &&
+ (strncmp(str, "certerr=", 8) == 0)) {
+ /* certificate entry error code */
+ if (chain->depth > 0) {
+ chain->certs[chain->depth - 1].err = strtoul(str + 8, NULL, 10);
+ }
+ }
+ return NSERROR_OK;
+}
+
+/*
+ * create a certificate chain from a fetch query string
+ *
+ * exported interface documented in netsurf/ssl_certs.h
+ */
+nserror cert_chain_from_query(struct nsurl *url, struct cert_chain **chain_out)
+{
+ struct cert_chain* chain;
+ nserror res;
+ char *querystr;
+ size_t querylen;
+ size_t kvstart;
+ size_t kvlen;
+
+ res = nsurl_get(url, NSURL_QUERY, &querystr, &querylen);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ if (querylen < MIN_CERT_LEN) {
+ free(querystr);
+ return NSERROR_NEED_DATA;
+ }
+
+ res = cert_chain_alloc(0, &chain);
+ if (res != NSERROR_OK) {
+ free(querystr);
+ return res;
+ }
+
+ for (kvlen = 0, kvstart = 0; kvstart < querylen; kvstart += kvlen) {
+ /* get query section length */
+ kvlen = 0;
+ while (((kvstart + kvlen) < querylen) &&
+ (querystr[kvstart + kvlen] != '&')) {
+ kvlen++;
+ }
+
+ res = process_query_section(querystr + kvstart, kvlen, chain);
+ if (res != NSERROR_OK) {
+ break;
+ }
+ kvlen++; /* account for & separator */
+ }
+ free(querystr);
+
+ if (chain->depth > 0) {
+ *chain_out = chain;
+ } else {
+ free(chain);
+ return NSERROR_INVALID;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/*
+ * create a fetch query string from a certificate chain
+ *
+ * exported interface documented in netsurf/ssl_certs.h
+ */
+nserror cert_chain_to_query(struct cert_chain *chain, struct nsurl **url_out )
+{
+ nserror res;
+ nsurl *url;
+ size_t allocsize;
+ size_t urlstrlen;
+ uint8_t *urlstr;
+ size_t depth;
+
+ allocsize = 20;
+ for (depth = 0; depth < chain->depth; depth++) {
+ allocsize += 7; /* allow for &cert= */
+ allocsize += 4 * ((chain->certs[depth].der_length + 2) / 3);
+ if (chain->certs[depth].err != SSL_CERT_ERR_OK) {
+ allocsize += 20; /* allow for &certerr=4000000000 */
+ }
+ }
+
+ urlstr = malloc(allocsize);
+ if (urlstr == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ urlstrlen = snprintf((char *)urlstr, allocsize, "about:certificate");
+ for (depth = 0; depth < chain->depth; depth++) {
+ int written;
+ nsuerror nsures;
+ size_t output_length;
+
+ written = snprintf((char *)urlstr + urlstrlen,
+ allocsize - urlstrlen,
+ "&cert=");
+ if (written < 0) {
+ free(urlstr);
+ return NSERROR_UNKNOWN;
+ }
+ if ((size_t)written >= allocsize - urlstrlen) {
+ free(urlstr);
+ return NSERROR_UNKNOWN;
+ }
+
+ urlstrlen += (size_t)written;
+
+ output_length = allocsize - urlstrlen;
+ nsures = nsu_base64_encode_url(
+ chain->certs[depth].der,
+ chain->certs[depth].der_length,
+ (uint8_t *)urlstr + urlstrlen,
+ &output_length);
+ if (nsures != NSUERROR_OK) {
+ free(urlstr);
+ return (nserror)nsures;
+ }
+ urlstrlen += output_length;
+
+ if (chain->certs[depth].err != SSL_CERT_ERR_OK) {
+ written = snprintf((char *)urlstr + urlstrlen,
+ allocsize - urlstrlen,
+ "&certerr=%d",
+ chain->certs[depth].err);
+ if (written < 0) {
+ free(urlstr);
+ return NSERROR_UNKNOWN;
+ }
+ if ((size_t)written >= allocsize - urlstrlen) {
+ free(urlstr);
+ return NSERROR_UNKNOWN;
+ }
+
+ urlstrlen += (size_t)written;
+ }
+
+ }
+ urlstr[17] = '?';
+ urlstr[urlstrlen] = 0;
+
+ res = nsurl_create((const char *)urlstr, &url);
+ free(urlstr);
+
+ if (res == NSERROR_OK) {
+ *url_out = url;
+ }
+
+ return res;
+}
+
+/*
+ * free certificate chain
+ *
+ * exported interface documented in netsurf/ssl_certs.h
+ */
+nserror cert_chain_free(struct cert_chain* chain)
+{
+ size_t depth;
+
+ if (chain != NULL) {
+ for (depth = 0; depth < chain->depth; depth++) {
+ if (chain->certs[depth].der != NULL) {
+ free(chain->certs[depth].der);
+ }
+ }
+
+ free(chain);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/*
+ * calculate storage used of certificate chain
+ *
+ * exported interface documented in netsurf/ssl_certs.h
+ */
+size_t cert_chain_size(const struct cert_chain *chain)
+{
+ size_t size = 0;
+ size_t depth;
+
+ if (chain != NULL) {
+ size += sizeof(struct cert_chain);
+
+ for (depth = 0; depth < chain->depth; depth++) {
+ if (chain->certs[depth].der != NULL) {
+ size += chain->certs[depth].der_length;
+ }
+ }
+ }
+
+ return size;
+}
diff --git a/utils/string.h b/utils/string.h
index 03d891700..abb343154 100644
--- a/utils/string.h
+++ b/utils/string.h
@@ -64,7 +64,7 @@ char *cnv_space2nbsp(const char *s);
* @param bytesize The size in bytes.
* @return A human readable string representing the size.
*/
-char *human_friendly_bytesize(unsigned long bytesize);
+char *human_friendly_bytesize(unsigned long long int bytesize);
/**
diff --git a/utils/sys_time.h b/utils/sys_time.h
index 82d88fd25..c9ce8202f 100644
--- a/utils/sys_time.h
+++ b/utils/sys_time.h
@@ -18,14 +18,26 @@
/**
* \file
- * \brief BSD style time functions
+ * BSD style timeval macros
+ *
+ * BSD added macros for manipulating timeval which have become standard on
+ * modern c libraries but for compatability where they are missing it is
+ * necessary to provide fallbacks.
*/
-#ifndef _NETSURF_UTILS_SYS_TIME_H_
-#define _NETSURF_UTILS_SYS_TIME_H_
+#ifndef NETSURF_UTILS_SYS_TIME_H_
+#define NETSURF_UTILS_SYS_TIME_H_
#include <sys/time.h>
+#ifndef timerclear
+#define timerclear(a) ((a)->tv_sec = (a)->tv_usec = 0)
+#endif
+
+#ifndef timerisset
+#define timerisset(a) ((a)->tv_sec || (a)->tv_usec)
+#endif
+
#ifndef timeradd
#define timeradd(a, aa, result) \
do { \
@@ -50,4 +62,10 @@
} while (0)
#endif
+#ifndef timercmp
+#define timercmp(a, aa, cmp) \
+ (((a)->tv_sec cmp (aa)->tv_sec) || \
+ ((a)->tv_sec == (aa)->tv_sec && (a)->tv_usec cmp (aa)->tv_usec))
+#endif
+
#endif
diff --git a/utils/time.c b/utils/time.c
index 71fa30fe3..e1f76ca54 100644
--- a/utils/time.c
+++ b/utils/time.c
@@ -109,7 +109,7 @@ static const char * const months[NSC_TIME_MONTH__COUNT] = {
/* exported interface documented in utils/time.h */
const char *rfc1123_date(time_t t)
{
- static char ret[30];
+ static char ret[31];
struct tm *tm = gmtime(&t);
diff --git a/utils/useragent.c b/utils/useragent.c
index b528dce4f..547999c7c 100644
--- a/utils/useragent.c
+++ b/utils/useragent.c
@@ -19,6 +19,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "utils/config.h"
#include "utils/utsname.h"
@@ -29,7 +30,7 @@
static const char *core_user_agent_string = NULL;
#ifndef NETSURF_UA_FORMAT_STRING
-#define NETSURF_UA_FORMAT_STRING "NetSurf/%d.%d (%s)"
+#define NETSURF_UA_FORMAT_STRING "Mozilla/5.0 (%s) NetSurf/%d.%d"
#endif
/**
@@ -46,12 +47,16 @@ user_agent_build_string(void)
if (uname(&un) >= 0) {
sysname = un.sysname;
+ if (strcmp(sysname, "Linux") == 0) {
+ /* Force desktop, not mobile */
+ sysname = "X11; Linux";
+ }
}
len = snprintf(NULL, 0, NETSURF_UA_FORMAT_STRING,
+ sysname,
netsurf_version_major,
- netsurf_version_minor,
- sysname);
+ netsurf_version_minor);
ua_string = malloc(len + 1);
if (!ua_string) {
/** \todo this needs handling better */
@@ -59,9 +64,9 @@ user_agent_build_string(void)
}
snprintf(ua_string, len + 1,
NETSURF_UA_FORMAT_STRING,
+ sysname,
netsurf_version_major,
- netsurf_version_minor,
- sysname);
+ netsurf_version_minor);
core_user_agent_string = ua_string;
@@ -78,3 +83,13 @@ user_agent_string(void)
return core_user_agent_string;
}
+/* Public API documented in useragent.h */
+void
+free_user_agent_string(void)
+{
+ if (core_user_agent_string != NULL) {
+ /* Nasty cast because we need to de-const it to free it */
+ free((void *)core_user_agent_string);
+ core_user_agent_string = NULL;
+ }
+}
diff --git a/utils/useragent.h b/utils/useragent.h
index 87677e7bc..6eb309a62 100644
--- a/utils/useragent.h
+++ b/utils/useragent.h
@@ -27,4 +27,11 @@
*/
const char * user_agent_string(void);
+/** Free any memory allocated for the user_agent_string
+ *
+ * After calling this, the value returned by \ref user_agent_string()
+ * is to be considered invalid.
+ */
+void free_user_agent_string(void);
+
#endif
diff --git a/utils/utf8.c b/utils/utf8.c
index f0ac0c9b2..3eedd0810 100644
--- a/utils/utf8.c
+++ b/utils/utf8.c
@@ -32,6 +32,7 @@
#include "utils/log.h"
#include "utils/utf8.h"
+#include "netsurf/inttypes.h"
#include "netsurf/utf8.h"
#include "desktop/gui_internal.h"
@@ -44,7 +45,7 @@ uint32_t utf8_to_ucs4(const char *s_in, size_t l)
parserutils_error perror;
perror = parserutils_charset_utf8_to_ucs4((const uint8_t *) s_in, l,
- &ucs4, &len);
+ &ucs4, &len);
if (perror != PARSERUTILS_OK)
ucs4 = 0xfffd;
@@ -106,7 +107,7 @@ size_t utf8_char_byte_length(const char *s)
parserutils_error perror;
perror = parserutils_charset_utf8_char_byte_length((const uint8_t *) s,
- &len);
+ &len);
assert(perror == PARSERUTILS_OK);
return len;
@@ -131,7 +132,7 @@ size_t utf8_next(const char *s, size_t l, size_t o)
parserutils_error perror;
perror = parserutils_charset_utf8_next((const uint8_t *) s, l, o,
- &next);
+ &next);
assert(perror == PARSERUTILS_OK);
return next;
@@ -151,6 +152,47 @@ static inline void utf8_clear_cd_cache(void)
last_cd.cd = 0;
}
+/**
+ * obtain a cached conversion descriptor
+ *
+ * either return the cached conversion descriptor or create one if required
+ */
+static nserror
+get_cached_cd(const char *enc_from, const char *enc_to, iconv_t *cd_out)
+{
+ iconv_t cd;
+ /* we cache the last used conversion descriptor,
+ * so check if we're trying to use it here */
+ if (strncasecmp(last_cd.from, enc_from, sizeof(last_cd.from)) == 0 &&
+ strncasecmp(last_cd.to, enc_to, sizeof(last_cd.to)) == 0 &&
+ last_cd.cd != 0) {
+ *cd_out = last_cd.cd;
+ return NSERROR_OK;
+ }
+
+ /* no match, so create a new cd */
+ cd = iconv_open(enc_to, enc_from);
+ if (cd == (iconv_t) -1) {
+ if (errno == EINVAL) {
+ return NSERROR_BAD_ENCODING;
+ }
+ /* default to no memory */
+ return NSERROR_NOMEM;
+ }
+
+ /* close the last cd - we don't care if this fails */
+ if (last_cd.cd) {
+ iconv_close(last_cd.cd);
+ }
+
+ /* and safely copy the to/from/cd data into last_cd */
+ snprintf(last_cd.from, sizeof(last_cd.from), "%s", enc_from);
+ snprintf(last_cd.to, sizeof(last_cd.to), "%s", enc_to);
+ *cd_out = last_cd.cd = cd;
+
+ return NSERROR_OK;
+}
+
/* exported interface documented in utils/utf8.h */
nserror utf8_finalise(void)
{
@@ -168,95 +210,72 @@ nserror utf8_finalise(void)
* Convert a string from one encoding to another
*
* \param string The NULL-terminated string to convert
- * \param len Length of input string to consider (in bytes), or 0
+ * \param slen Length of input string to consider (in bytes), or 0
* \param from The encoding name to convert from
* \param to The encoding name to convert to
- * \param result Pointer to location in which to store result.
- * \param result_len Pointer to location in which to store result length.
+ * \param result_out Pointer to location in which to store result.
+ * \param result_len_out Pointer to location in which to store result length.
* \return NSERROR_OK for no error, NSERROR_NOMEM on allocation error,
* NSERROR_BAD_ENCODING for a bad character encoding
*/
static nserror
utf8_convert(const char *string,
- size_t len,
+ size_t slen,
const char *from,
const char *to,
- char **result,
- size_t *result_len)
+ char **result_out,
+ size_t *result_len_out)
{
iconv_t cd;
- char *temp, *out, *in;
- size_t slen, rlen;
-
- assert(string && from && to && result);
-
- if (string[0] == '\0') {
- /* On AmigaOS, iconv() returns an error if we pass an
- * empty string. This prevents iconv() being called as
- * there is no conversion necessary anyway. */
- *result = strdup("");
- if (!(*result)) {
- *result = NULL;
- return NSERROR_NOMEM;
- }
+ char *temp, *out, *in, *result;
+ size_t result_len;
+ nserror res;
- return NSERROR_OK;
+ assert(string && from && to && result_out);
+
+ /* calculate the source length if not given */
+ if (slen==0) {
+ slen = strlen(string);
}
- if (strcasecmp(from, to) == 0) {
- /* conversion from an encoding to itself == strdup */
- slen = len ? len : strlen(string);
- *(result) = strndup(string, slen);
- if (!(*result)) {
- *(result) = NULL;
+ /* process the empty string separately avoiding any conversion
+ * check for the source and destination encoding being the same
+ *
+ * This optimisation is necessary on AmigaOS as iconv()
+ * returns an error if an empty string is passed.
+ */
+ if ((slen == 0) || (strcasecmp(from, to) == 0)) {
+ *result_out = strndup(string, slen);
+ if (*result_out == NULL) {
return NSERROR_NOMEM;
}
+ if (result_len_out != NULL) {
+ *result_len_out = slen;
+ }
return NSERROR_OK;
}
in = (char *)string;
- /* we cache the last used conversion descriptor,
- * so check if we're trying to use it here */
- if (strncasecmp(last_cd.from, from, sizeof(last_cd.from)) == 0 &&
- strncasecmp(last_cd.to, to, sizeof(last_cd.to)) == 0) {
- cd = last_cd.cd;
- }
- else {
- /* no match, so create a new cd */
- cd = iconv_open(to, from);
- if (cd == (iconv_t)-1) {
- if (errno == EINVAL)
- return NSERROR_BAD_ENCODING;
- /* default to no memory */
- return NSERROR_NOMEM;
- }
-
- /* close the last cd - we don't care if this fails */
- if (last_cd.cd)
- iconv_close(last_cd.cd);
-
- /* and copy the to/from/cd data into last_cd */
- snprintf(last_cd.from, sizeof(last_cd.from), "%s", from);
- snprintf(last_cd.to, sizeof(last_cd.to), "%s", to);
- last_cd.cd = cd;
+ res = get_cached_cd(from, to, &cd);
+ if (res != NSERROR_OK) {
+ return res;
}
- slen = len ? len : strlen(string);
/* Worst case = ASCII -> UCS4, so allocate an output buffer
* 4 times larger than the input buffer, and add 4 bytes at
* the end for the NULL terminator
*/
- rlen = slen * 4 + 4;
+ result_len = slen * 4 + 4;
- temp = out = malloc(rlen);
+ temp = out = malloc(result_len);
if (!out) {
return NSERROR_NOMEM;
}
/* perform conversion */
- if (iconv(cd, (void *) &in, &slen, &out, &rlen) == (size_t)-1) {
+ if (iconv(cd, (void *) &in, &slen, &out, &result_len) == (size_t)-1) {
free(temp);
/* clear the cached conversion descriptor as it's invalid */
if (last_cd.cd)
@@ -270,19 +289,22 @@ utf8_convert(const char *string,
return NSERROR_NOMEM;
}
- *(result) = realloc(temp, out - temp + 4);
- if (!(*result)) {
+ result_len = out - temp;
+
+ /* resize buffer allowing for null termination */
+ result = realloc(temp, result_len + 4);
+ if (result == NULL) {
free(temp);
- *(result) = NULL; /* for sanity's sake */
return NSERROR_NOMEM;
}
/* NULL terminate - needs 4 characters as we may have
* converted to UTF-32 */
- memset((*result) + (out - temp), 0, 4);
+ memset(result + result_len, 0, 4);
- if (result_len != NULL) {
- *result_len = (out - temp);
+ *result_out = result;
+ if (result_len_out != NULL) {
+ *result_len_out = result_len;
}
return NSERROR_OK;
@@ -290,14 +312,14 @@ utf8_convert(const char *string,
/* exported interface documented in utils/utf8.h */
nserror utf8_to_enc(const char *string, const char *encname,
- size_t len, char **result)
+ size_t len, char **result)
{
return utf8_convert(string, len, "UTF-8", encname, result, NULL);
}
/* exported interface documented in utils/utf8.h */
nserror utf8_from_enc(const char *string, const char *encname,
- size_t len, char **result, size_t *result_len)
+ size_t len, char **result, size_t *result_len)
{
return utf8_convert(string, len, encname, "UTF-8", result, result_len);
}
@@ -325,10 +347,10 @@ utf8_convert_html_chunk(iconv_t cd,
return NSERROR_NOMEM;
ucs4 = utf8_to_ucs4(chunk, inlen);
- esclen = snprintf(escape, sizeof(escape), "&#x%06x;", ucs4);
+ esclen = snprintf(escape, sizeof(escape), "&#x%06"PRIx32";", ucs4);
pescape = escape;
ret = iconv(cd, (void *) &pescape, &esclen,
- (void *) out, outlen);
+ (void *) out, outlen);
if (ret == (size_t) -1)
return NSERROR_NOMEM;
@@ -340,45 +362,26 @@ utf8_convert_html_chunk(iconv_t cd,
return NSERROR_OK;
}
+
+
/* exported interface documented in utils/utf8.h */
nserror
-utf8_to_html(const char *string, const char *encname, size_t len, char **result)
+utf8_to_html(const char *string, const char *encname, size_t len, char **result_out)
{
iconv_t cd;
const char *in;
- char *out, *origout;
+ char *out, *origout, *result;
size_t off, prev_off, inlen, outlen, origoutlen, esclen;
nserror ret;
char *pescape, escape[11];
+ nserror res;
if (len == 0)
len = strlen(string);
- /* we cache the last used conversion descriptor,
- * so check if we're trying to use it here */
- if (strncasecmp(last_cd.from, "UTF-8", sizeof(last_cd.from)) == 0 &&
- strncasecmp(last_cd.to, encname,
- sizeof(last_cd.to)) == 0 &&
- last_cd.cd != 0) {
- cd = last_cd.cd;
- } else {
- /* no match, so create a new cd */
- cd = iconv_open(encname, "UTF-8");
- if (cd == (iconv_t) -1) {
- if (errno == EINVAL)
- return NSERROR_BAD_ENCODING;
- /* default to no memory */
- return NSERROR_NOMEM;
- }
-
- /* close the last cd - we don't care if this fails */
- if (last_cd.cd)
- iconv_close(last_cd.cd);
-
- /* and safely copy the to/from/cd data into last_cd */
- snprintf(last_cd.from, sizeof(last_cd.from), "UTF-8");
- snprintf(last_cd.to, sizeof(last_cd.to), "%s", encname);
- last_cd.cd = cd;
+ res = get_cached_cd("UTF-8", encname, &cd);
+ if (res != NSERROR_OK) {
+ return res;
}
/* Worst case is ASCII -> UCS4, with all characters escaped:
@@ -398,13 +401,13 @@ utf8_to_html(const char *string, const char *encname, size_t len, char **result)
while (off < len) {
/* Must escape '&', '<', and '>' */
if (string[off] == '&' || string[off] == '<' ||
- string[off] == '>') {
+ string[off] == '>') {
if (off - prev_off > 0) {
/* Emit chunk */
in = string + prev_off;
inlen = off - prev_off;
ret = utf8_convert_html_chunk(cd, in, inlen,
- &out, &outlen);
+ &out, &outlen);
if (ret != NSERROR_OK) {
free(origout);
iconv_close(cd);
@@ -415,10 +418,10 @@ utf8_to_html(const char *string, const char *encname, size_t len, char **result)
/* Emit mandatory escape */
esclen = snprintf(escape, sizeof(escape),
- "&#x%06x;", string[off]);
+ "&#x%06x;", string[off]);
pescape = escape;
ret = utf8_convert_html_chunk(cd, pescape, esclen,
- &out, &outlen);
+ &out, &outlen);
if (ret != NSERROR_OK) {
free(origout);
iconv_close(cd);
@@ -450,11 +453,12 @@ utf8_to_html(const char *string, const char *encname, size_t len, char **result)
outlen -= 4;
/* Shrink-wrap */
- *result = realloc(origout, origoutlen - outlen);
- if (*result == NULL) {
+ result = realloc(origout, origoutlen - outlen);
+ if (result == NULL) {
free(origout);
return NSERROR_NOMEM;
}
+ *result_out = result;
return NSERROR_OK;
}
diff --git a/utils/utils.c b/utils/utils.c
index 15c91c621..c64718531 100644
--- a/utils/utils.c
+++ b/utils/utils.c
@@ -24,7 +24,9 @@
#include <stdio.h>
#include <string.h>
#include <strings.h>
+#include <sys/types.h>
#include <sys/stat.h>
+#include <unistd.h>
#include "utils/messages.h"
#include "utils/dirent.h"
@@ -172,6 +174,7 @@ nserror vsnstrjoin(char **str, size_t *size, char sep, size_t nelm, va_list ap)
return NSERROR_OK;
}
+
/* exported interface documented in utils/utils.h */
nserror snstrjoin(char **str, size_t *size, char sep, size_t nelm, ...)
{
@@ -189,26 +192,43 @@ nserror snstrjoin(char **str, size_t *size, char sep, size_t nelm, ...)
/**
* The size of buffers within human_friendly_bytesize.
*
- * We can have a fairly good estimate of how long the buffer needs to
- * be. The unsigned long can store a value representing a maximum
- * size of around 4 GB. Therefore the greatest space required is to
- * represent 1023MB. Currently that would be represented as "1023MB"
- * so 12 including a null terminator. Ideally we would be able to
- * know this value for sure, in the mean time the following should
- * suffice.
+ * We can have a fairly good estimate of the output buffers maximum length.
+ *
+ * The unsigned long long int can store a value representing a maximum
+ * size of 16 EiB (exibytes). Therefore the greatest space required is to
+ * represent 1023 PiB.
+ * Currently that would be represented as "1023.00PiBytes" in english
+ * giving a 15 byte length including a null terminator.
+ * Ideally we would be able to accurately know this length for other
+ * languages, in the mean time a largeish buffer size is selected
+ * and should suffice.
*/
-#define BYTESIZE_BUFFER_SIZE 20
+#define BYTESIZE_BUFFER_SIZE 32
/* exported interface documented in utils/string.h */
-char *human_friendly_bytesize(unsigned long bsize) {
+char *human_friendly_bytesize(unsigned long long int bsize) {
static char buffer1[BYTESIZE_BUFFER_SIZE];
static char buffer2[BYTESIZE_BUFFER_SIZE];
static char buffer3[BYTESIZE_BUFFER_SIZE];
static char *curbuffer = buffer3;
- enum {bytes, kilobytes, megabytes, gigabytes} unit = bytes;
- static char units[][7] = {"Bytes", "kBytes", "MBytes", "GBytes"};
-
- float bytesize = (float)bsize;
+ enum {
+ bytes,
+ kilobytes,
+ megabytes,
+ gibibytes,
+ tebibytes,
+ pebibytes,
+ exbibytes } unit = bytes;
+ static const char *const units[] = {
+ "Bytes",
+ "KiBytes",
+ "MiBytes",
+ "GiBytes",
+ "TiBytes",
+ "PiBytes",
+ "EiBytes" };
+ double bytesize = (double)bsize;
+ const char *fmt;
if (curbuffer == buffer1)
curbuffer = buffer2;
@@ -229,15 +249,55 @@ char *human_friendly_bytesize(unsigned long bsize) {
if (bytesize > 1024) {
bytesize /= 1024;
- unit = gigabytes;
+ unit = gibibytes;
+ }
+
+ if (bytesize > 1024) {
+ bytesize /= 1024;
+ unit = tebibytes;
}
- snprintf(curbuffer, BYTESIZE_BUFFER_SIZE, "%3.2f%s", bytesize, messages_get(units[unit]));
+ if (bytesize > 1024) {
+ bytesize /= 1024;
+ unit = pebibytes;
+ }
+
+ if (bytesize > 1024) {
+ bytesize /= 1024;
+ unit = exbibytes;
+ }
+
+ if (unit == bytes) {
+ fmt = "%.0f%s";
+ } else {
+ fmt = "%3.2f%s";
+ }
+
+ snprintf(curbuffer,
+ BYTESIZE_BUFFER_SIZE,
+ fmt,
+ bytesize,
+ messages_get(units[unit]));
return curbuffer;
}
+#ifndef HAVE_STRTOULL
+#include <stdlib.h>
+
+/**
+ * string to unsigned long long
+ *
+ */
+unsigned long long int strtoull(const char *nptr, char **endptr, int base)
+{
+ return (unsigned long long int)strtoul(nptr, endptr, base);
+}
+
+#endif
+
+
#ifndef HAVE_STRCASESTR
/**
@@ -263,12 +323,12 @@ char *strcasestr(const char *haystack, const char *needle)
#endif
+
#ifndef HAVE_STRNDUP
/**
* Duplicate up to n characters of a string.
*/
-
char *strndup(const char *s, size_t n)
{
size_t len;
@@ -393,6 +453,7 @@ char *strchrnul (const char *s, int c_in)
#endif
#ifndef HAVE_UTSNAME
+
#include "utils/utsname.h"
int uname(struct utsname *buf) {
@@ -404,9 +465,11 @@ int uname(struct utsname *buf) {
return 0;
}
+
#endif
#ifndef HAVE_REALPATH
+
char *realpath(const char *path, char *resolved_path)
{
char *ret;
@@ -419,8 +482,9 @@ char *realpath(const char *path, char *resolved_path)
return ret;
}
-#ifndef HAVE_INETATON
+#endif
+#ifndef HAVE_INETATON
int inet_aton(const char *cp, struct in_addr *inp)
{
@@ -470,4 +534,40 @@ int inet_pton(int af, const char *src, void *dst)
#endif
+#ifndef HAVE_REGEX
+
+#include "utils/regex.h"
+
+int
+regcomp(regex_t *restrict preg, const char *restrictregex, int cflags)
+{
+ return 0;
+}
+
+size_t
+regerror(int errorcode,
+ const regex_t *restrict preg,
+ char *restrict errbuf,
+ size_t errbuf_size)
+{
+ if ((errbuf != NULL) && (errbuf_size != 0)) {
+ *errbuf = 0;
+ }
+ return 0;
+}
+
+int
+regexec(const regex_t *restrict preg,
+ const char *restrict string,
+ size_t nmatch,
+ regmatch_t pmatch[restrict],
+ int eflags)
+{
+ return REG_NOMATCH;
+}
+
+void regfree(regex_t *preg)
+{
+}
+
#endif
diff --git a/utils/utils.h b/utils/utils.h
index 3995071cd..cb9e04b45 100644
--- a/utils/utils.h
+++ b/utils/utils.h
@@ -89,4 +89,31 @@
*/
bool is_dir(const char *path);
+/**
+ * switch fall through
+ */
+#if defined __cplusplus && defined __has_cpp_attribute
+ #if __has_cpp_attribute(fallthrough) && __cplusplus >= __has_cpp_attribute(fallthrough)
+ #define fallthrough [[fallthrough]]
+ #elif __has_cpp_attribute(gnu::fallthrough) && __STDC_VERSION__ >= __has_cpp_attribute(gnu::fallthrough)
+ #define fallthrough [[gnu::fallthrough]]
+ #elif __has_cpp_attribute(clang::fallthrough) && __STDC_VERSION__ >= __has_cpp_attribute(clang::fallthrough)
+ #define fallthrough [[clang::fallthrough]]
+ #endif
+#elif defined __STDC_VERSION__ && defined __has_c_attribute
+ #if __has_c_attribute(fallthrough) && __STDC_VERSION__ >= __has_c_attribute(fallthrough)
+ #define fallthrough [[fallthrough]]
+ #endif
+#endif
+#if !defined fallthrough && defined __has_attribute
+ #if __has_attribute(__fallthrough__)
+ #define fallthrough __attribute__((__fallthrough__))
+ #endif
+#endif
+#if !defined fallthrough
+/* early gcc and clang have no implicit fallthrough warning */
+ #define fallthrough do {} while(0)
+#endif
+
+
#endif